rabbitmq-server-3.2.4/0000755000000000000000000000000012305126066013324 5ustar rootrootrabbitmq-server-3.2.4/scripts/0000755000000000000000000000000012305126066015013 5ustar rootrootrabbitmq-server-3.2.4/scripts/rabbitmqctl0000755000000000000000000000247612305126066017256 0ustar rootroot#!/bin/sh ## The contents of this file are subject to the Mozilla Public License ## Version 1.1 (the "License"); you may not use this file except in ## compliance with the License. You may obtain a copy of the License ## at http://www.mozilla.org/MPL/ ## ## Software distributed under the License is distributed on an "AS IS" ## basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See ## the License for the specific language governing rights and ## limitations under the License. ## ## The Original Code is RabbitMQ. ## ## The Initial Developer of the Original Code is GoPivotal, Inc. ## Copyright (c) 2007-2013 GoPivotal, Inc. All rights reserved. ## # Get default settings with user overrides for (RABBITMQ_) # Non-empty defaults should be set in rabbitmq-env . `dirname $0`/rabbitmq-env ##--- Set environment vars RABBITMQ_ to defaults if not set [ "x" = "x$RABBITMQ_NODENAME" ] && RABBITMQ_NODENAME=${NODENAME} [ "x" = "x$RABBITMQ_CTL_ERL_ARGS" ] && RABBITMQ_CTL_ERL_ARGS=${CTL_ERL_ARGS} ##--- End of overridden variables exec ${ERL_DIR}erl \ -pa "${RABBITMQ_HOME}/ebin" \ -noinput \ -hidden \ ${RABBITMQ_CTL_ERL_ARGS} \ -sname rabbitmqctl$$ \ -boot "${CLEAN_BOOT_FILE}" \ -s rabbit_control_main \ -nodename $RABBITMQ_NODENAME \ -extra "$@" rabbitmq-server-3.2.4/scripts/rabbitmqctl.bat0000755000000000000000000000312512305126066020013 0ustar rootroot@echo off REM The contents of this file are subject to the Mozilla Public License REM Version 1.1 (the "License"); you may not use this file except in REM compliance with the License. You may obtain a copy of the License REM at http://www.mozilla.org/MPL/ REM REM Software distributed under the License is distributed on an "AS IS" REM basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See REM the License for the specific language governing rights and REM limitations under the License. REM REM The Original Code is RabbitMQ. REM REM The Initial Developer of the Original Code is GoPivotal, Inc. REM Copyright (c) 2007-2013 GoPivotal, Inc. All rights reserved. REM setlocal rem Preserve values that might contain exclamation marks before rem enabling delayed expansion set TDP0=%~dp0 set STAR=%* setlocal enabledelayedexpansion if "!COMPUTERNAME!"=="" ( set COMPUTERNAME=localhost ) if "!RABBITMQ_NODENAME!"=="" ( set RABBITMQ_NODENAME=rabbit@!COMPUTERNAME! ) if not exist "!ERLANG_HOME!\bin\erl.exe" ( echo. echo ****************************** echo ERLANG_HOME not set correctly. echo ****************************** echo. echo Please either set ERLANG_HOME to point to your Erlang installation or place the echo RabbitMQ server distribution in the Erlang lib folder. echo. exit /B ) "!ERLANG_HOME!\bin\erl.exe" -pa "!TDP0!..\ebin" -noinput -hidden !RABBITMQ_CTL_ERL_ARGS! -sname rabbitmqctl!RANDOM!!TIME:~9! -s rabbit_control_main -nodename !RABBITMQ_NODENAME! -extra !STAR! endlocal endlocal rabbitmq-server-3.2.4/scripts/rabbitmq-server.bat0000755000000000000000000001040412305126066020612 0ustar rootroot@echo off REM The contents of this file are subject to the Mozilla Public License REM Version 1.1 (the "License"); you may not use this file except in REM compliance with the License. You may obtain a copy of the License REM at http://www.mozilla.org/MPL/ REM REM Software distributed under the License is distributed on an "AS IS" REM basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See REM the License for the specific language governing rights and REM limitations under the License. REM REM The Original Code is RabbitMQ. REM REM The Initial Developer of the Original Code is GoPivotal, Inc. REM Copyright (c) 2007-2013 GoPivotal, Inc. All rights reserved. REM setlocal rem Preserve values that might contain exclamation marks before rem enabling delayed expansion set TDP0=%~dp0 set STAR=%* setlocal enabledelayedexpansion if "!RABBITMQ_BASE!"=="" ( set RABBITMQ_BASE=!APPDATA!\RabbitMQ ) if "!COMPUTERNAME!"=="" ( set COMPUTERNAME=localhost ) if "!RABBITMQ_NODENAME!"=="" ( set RABBITMQ_NODENAME=rabbit@!COMPUTERNAME! ) if "!RABBITMQ_NODE_IP_ADDRESS!"=="" ( if not "!RABBITMQ_NODE_PORT!"=="" ( set RABBITMQ_NODE_IP_ADDRESS=auto ) ) else ( if "!RABBITMQ_NODE_PORT!"=="" ( set RABBITMQ_NODE_PORT=5672 ) ) if not exist "!ERLANG_HOME!\bin\erl.exe" ( echo. echo ****************************** echo ERLANG_HOME not set correctly. echo ****************************** echo. echo Please either set ERLANG_HOME to point to your Erlang installation or place the echo RabbitMQ server distribution in the Erlang lib folder. echo. exit /B ) if "!RABBITMQ_MNESIA_BASE!"=="" ( set RABBITMQ_MNESIA_BASE=!RABBITMQ_BASE!/db ) if "!RABBITMQ_LOG_BASE!"=="" ( set RABBITMQ_LOG_BASE=!RABBITMQ_BASE!/log ) rem We save the previous logs in their respective backup rem Log management (rotation, filtering based of size...) is left as an exercice for the user. set LOGS=!RABBITMQ_LOG_BASE!\!RABBITMQ_NODENAME!.log set SASL_LOGS=!RABBITMQ_LOG_BASE!\!RABBITMQ_NODENAME!-sasl.log rem End of log management if "!RABBITMQ_MNESIA_DIR!"=="" ( set RABBITMQ_MNESIA_DIR=!RABBITMQ_MNESIA_BASE!/!RABBITMQ_NODENAME!-mnesia ) if "!RABBITMQ_PLUGINS_EXPAND_DIR!"=="" ( set RABBITMQ_PLUGINS_EXPAND_DIR=!RABBITMQ_MNESIA_BASE!/!RABBITMQ_NODENAME!-plugins-expand ) if "!RABBITMQ_ENABLED_PLUGINS_FILE!"=="" ( set RABBITMQ_ENABLED_PLUGINS_FILE=!RABBITMQ_BASE!\enabled_plugins ) if "!RABBITMQ_PLUGINS_DIR!"=="" ( set RABBITMQ_PLUGINS_DIR=!TDP0!..\plugins ) set RABBITMQ_EBIN_ROOT=!TDP0!..\ebin "!ERLANG_HOME!\bin\erl.exe" ^ -pa "!RABBITMQ_EBIN_ROOT!" ^ -noinput -hidden ^ -s rabbit_prelaunch ^ -sname rabbitmqprelaunch!RANDOM!!TIME:~9! ^ -extra "!RABBITMQ_NODENAME!" if ERRORLEVEL 1 ( exit /B 1 ) set RABBITMQ_EBIN_PATH="-pa !RABBITMQ_EBIN_ROOT!" if "!RABBITMQ_CONFIG_FILE!"=="" ( set RABBITMQ_CONFIG_FILE=!RABBITMQ_BASE!\rabbitmq ) if exist "!RABBITMQ_CONFIG_FILE!.config" ( set RABBITMQ_CONFIG_ARG=-config "!RABBITMQ_CONFIG_FILE!" ) else ( set RABBITMQ_CONFIG_ARG= ) set RABBITMQ_LISTEN_ARG= if not "!RABBITMQ_NODE_IP_ADDRESS!"=="" ( if not "!RABBITMQ_NODE_PORT!"=="" ( set RABBITMQ_LISTEN_ARG=-rabbit tcp_listeners [{\""!RABBITMQ_NODE_IP_ADDRESS!"\","!RABBITMQ_NODE_PORT!"}] ) ) "!ERLANG_HOME!\bin\erl.exe" ^ -pa "!RABBITMQ_EBIN_ROOT!" ^ -noinput ^ -boot start_sasl ^ -s rabbit boot ^ !RABBITMQ_CONFIG_ARG! ^ -sname !RABBITMQ_NODENAME! ^ +W w ^ +A30 ^ +P 1048576 ^ -kernel inet_default_connect_options "[{nodelay, true}]" ^ !RABBITMQ_LISTEN_ARG! ^ !RABBITMQ_SERVER_ERL_ARGS! ^ -sasl errlog_type error ^ -sasl sasl_error_logger false ^ -rabbit error_logger {file,\""!LOGS:\=/!"\"} ^ -rabbit sasl_error_logger {file,\""!SASL_LOGS:\=/!"\"} ^ -rabbit enabled_plugins_file \""!RABBITMQ_ENABLED_PLUGINS_FILE:\=/!"\" ^ -rabbit plugins_dir \""!RABBITMQ_PLUGINS_DIR:\=/!"\" ^ -rabbit plugins_expand_dir \""!RABBITMQ_PLUGINS_EXPAND_DIR:\=/!"\" ^ -os_mon start_cpu_sup false ^ -os_mon start_disksup false ^ -os_mon start_memsup false ^ -mnesia dir \""!RABBITMQ_MNESIA_DIR:\=/!"\" ^ !RABBITMQ_SERVER_START_ARGS! ^ !STAR! endlocal endlocal rabbitmq-server-3.2.4/scripts/rabbitmq-service.bat0000755000000000000000000001572312305126066020755 0ustar rootroot@echo off REM The contents of this file are subject to the Mozilla Public License REM Version 1.1 (the "License"); you may not use this file except in REM compliance with the License. You may obtain a copy of the License REM at http://www.mozilla.org/MPL/ REM REM Software distributed under the License is distributed on an "AS IS" REM basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See REM the License for the specific language governing rights and REM limitations under the License. REM REM The Original Code is RabbitMQ. REM REM The Initial Developer of the Original Code is GoPivotal, Inc. REM Copyright (c) 2007-2013 GoPivotal, Inc. All rights reserved. REM setlocal rem Preserve values that might contain exclamation marks before rem enabling delayed expansion set TN0=%~n0 set TDP0=%~dp0 set P1=%1 setlocal enabledelayedexpansion set STARVAR= shift :loop1 if "%1"=="" goto after_loop set STARVAR=%STARVAR% %1 shift goto loop1 :after_loop if "!RABBITMQ_SERVICENAME!"=="" ( set RABBITMQ_SERVICENAME=RabbitMQ ) if "!RABBITMQ_BASE!"=="" ( set RABBITMQ_BASE=!APPDATA!\!RABBITMQ_SERVICENAME! ) if "!COMPUTERNAME!"=="" ( set COMPUTERNAME=localhost ) if "!RABBITMQ_NODENAME!"=="" ( set RABBITMQ_NODENAME=rabbit@!COMPUTERNAME! ) if "!RABBITMQ_NODE_IP_ADDRESS!"=="" ( if not "!RABBITMQ_NODE_PORT!"=="" ( set RABBITMQ_NODE_IP_ADDRESS=auto ) ) else ( if "!RABBITMQ_NODE_PORT!"=="" ( set RABBITMQ_NODE_PORT=5672 ) ) if "!ERLANG_SERVICE_MANAGER_PATH!"=="" ( if not exist "!ERLANG_HOME!\bin\erl.exe" ( echo. echo ****************************** echo ERLANG_HOME not set correctly. echo ****************************** echo. echo Please either set ERLANG_HOME to point to your Erlang installation or place the echo RabbitMQ server distribution in the Erlang lib folder. echo. exit /B ) for /f "delims=" %%i in ('dir /ad/b "!ERLANG_HOME!"') do if exist "!ERLANG_HOME!\%%i\bin\erlsrv.exe" ( set ERLANG_SERVICE_MANAGER_PATH=!ERLANG_HOME!\%%i\bin ) ) set CONSOLE_FLAG= set CONSOLE_LOG_VALID= for %%i in (new reuse) do if "%%i" == "!RABBITMQ_CONSOLE_LOG!" set CONSOLE_LOG_VALID=TRUE if "!CONSOLE_LOG_VALID!" == "TRUE" ( set CONSOLE_FLAG=-debugtype !RABBITMQ_CONSOLE_LOG! ) rem *** End of configuration *** if not exist "!ERLANG_SERVICE_MANAGER_PATH!\erlsrv.exe" ( echo. echo ********************************************** echo ERLANG_SERVICE_MANAGER_PATH not set correctly. echo ********************************************** echo. echo "!ERLANG_SERVICE_MANAGER_PATH!\erlsrv.exe" not found echo Please set ERLANG_SERVICE_MANAGER_PATH to the folder containing "erlsrv.exe". echo. exit /B 1 ) if "!RABBITMQ_MNESIA_BASE!"=="" ( set RABBITMQ_MNESIA_BASE=!RABBITMQ_BASE!/db ) if "!RABBITMQ_LOG_BASE!"=="" ( set RABBITMQ_LOG_BASE=!RABBITMQ_BASE!/log ) rem We save the previous logs in their respective backup rem Log management (rotation, filtering based on size...) is left as an exercise for the user. set LOGS=!RABBITMQ_LOG_BASE!\!RABBITMQ_NODENAME!.log set SASL_LOGS=!RABBITMQ_LOG_BASE!\!RABBITMQ_NODENAME!-sasl.log rem End of log management if "!RABBITMQ_MNESIA_DIR!"=="" ( set RABBITMQ_MNESIA_DIR=!RABBITMQ_MNESIA_BASE!/!RABBITMQ_NODENAME!-mnesia ) if "!RABBITMQ_PLUGINS_EXPAND_DIR!"=="" ( set RABBITMQ_PLUGINS_EXPAND_DIR=!RABBITMQ_MNESIA_BASE!/!RABBITMQ_NODENAME!-plugins-expand ) if "!P1!" == "install" goto INSTALL_SERVICE for %%i in (start stop disable enable list remove) do if "%%i" == "!P1!" goto MODIFY_SERVICE echo. echo ********************* echo Service control usage echo ********************* echo. echo !TN0! help - Display this help echo !TN0! install - Install the !RABBITMQ_SERVICENAME! service echo !TN0! remove - Remove the !RABBITMQ_SERVICENAME! service echo. echo The following actions can also be accomplished by using echo Windows Services Management Console (services.msc): echo. echo !TN0! start - Start the !RABBITMQ_SERVICENAME! service echo !TN0! stop - Stop the !RABBITMQ_SERVICENAME! service echo !TN0! disable - Disable the !RABBITMQ_SERVICENAME! service echo !TN0! enable - Enable the !RABBITMQ_SERVICENAME! service echo. exit /B :INSTALL_SERVICE if not exist "!RABBITMQ_BASE!" ( echo Creating base directory !RABBITMQ_BASE! & md "!RABBITMQ_BASE!" ) "!ERLANG_SERVICE_MANAGER_PATH!\erlsrv" list !RABBITMQ_SERVICENAME! 2>NUL 1>NUL if errorlevel 1 ( "!ERLANG_SERVICE_MANAGER_PATH!\erlsrv" add !RABBITMQ_SERVICENAME! -internalservicename !RABBITMQ_SERVICENAME! ) else ( echo !RABBITMQ_SERVICENAME! service is already present - only updating service parameters ) if "!RABBITMQ_ENABLED_PLUGINS_FILE!"=="" ( set RABBITMQ_ENABLED_PLUGINS_FILE=!RABBITMQ_BASE!\enabled_plugins ) if "!RABBITMQ_PLUGINS_DIR!"=="" ( set RABBITMQ_PLUGINS_DIR=!TDP0!..\plugins ) set RABBITMQ_EBIN_ROOT=!TDP0!..\ebin if "!RABBITMQ_CONFIG_FILE!"=="" ( set RABBITMQ_CONFIG_FILE=!RABBITMQ_BASE!\rabbitmq ) if exist "!RABBITMQ_CONFIG_FILE!.config" ( set RABBITMQ_CONFIG_ARG=-config "!RABBITMQ_CONFIG_FILE!" ) else ( set RABBITMQ_CONFIG_ARG= ) set RABBITMQ_LISTEN_ARG= if not "!RABBITMQ_NODE_IP_ADDRESS!"=="" ( if not "!RABBITMQ_NODE_PORT!"=="" ( set RABBITMQ_LISTEN_ARG=-rabbit tcp_listeners "[{\"!RABBITMQ_NODE_IP_ADDRESS!\", !RABBITMQ_NODE_PORT!}]" ) ) set ERLANG_SERVICE_ARGUMENTS= ^ -pa "!RABBITMQ_EBIN_ROOT!" ^ -boot start_sasl ^ -s rabbit boot ^ !RABBITMQ_CONFIG_ARG! ^ +W w ^ +A30 ^ +P 1048576 ^ -kernel inet_default_connect_options "[{nodelay,true}]" ^ !RABBITMQ_LISTEN_ARG! ^ !RABBITMQ_SERVER_ERL_ARGS! ^ -sasl errlog_type error ^ -sasl sasl_error_logger false ^ -rabbit error_logger {file,\""!LOGS:\=/!"\"} ^ -rabbit sasl_error_logger {file,\""!SASL_LOGS:\=/!"\"} ^ -rabbit enabled_plugins_file \""!RABBITMQ_ENABLED_PLUGINS_FILE:\=/!"\" ^ -rabbit plugins_dir \""!RABBITMQ_PLUGINS_DIR:\=/!"\" ^ -rabbit plugins_expand_dir \""!RABBITMQ_PLUGINS_EXPAND_DIR:\=/!"\" ^ -os_mon start_cpu_sup false ^ -os_mon start_disksup false ^ -os_mon start_memsup false ^ -mnesia dir \""!RABBITMQ_MNESIA_DIR:\=/!"\" ^ !RABBITMQ_SERVER_START_ARGS! ^ !STARVAR! set ERLANG_SERVICE_ARGUMENTS=!ERLANG_SERVICE_ARGUMENTS:\=\\! set ERLANG_SERVICE_ARGUMENTS=!ERLANG_SERVICE_ARGUMENTS:"=\"! "!ERLANG_SERVICE_MANAGER_PATH!\erlsrv" set !RABBITMQ_SERVICENAME! ^ -machine "!ERLANG_SERVICE_MANAGER_PATH!\erl.exe" ^ -env ERL_CRASH_DUMP="!RABBITMQ_BASE:\=/!/erl_crash.dump" ^ -workdir "!RABBITMQ_BASE!" ^ -stopaction "rabbit:stop_and_halt()." ^ -sname !RABBITMQ_NODENAME! ^ !CONSOLE_FLAG! ^ -comment "A robust and scalable messaging broker" ^ -args "!ERLANG_SERVICE_ARGUMENTS!" > NUL goto END :MODIFY_SERVICE "!ERLANG_SERVICE_MANAGER_PATH!\erlsrv" !P1! !RABBITMQ_SERVICENAME! goto END :END endlocal endlocal rabbitmq-server-3.2.4/scripts/rabbitmq-server0000755000000000000000000001252612305126066020054 0ustar rootroot#!/bin/sh ## The contents of this file are subject to the Mozilla Public License ## Version 1.1 (the "License"); you may not use this file except in ## compliance with the License. You may obtain a copy of the License ## at http://www.mozilla.org/MPL/ ## ## Software distributed under the License is distributed on an "AS IS" ## basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See ## the License for the specific language governing rights and ## limitations under the License. ## ## The Original Code is RabbitMQ. ## ## The Initial Developer of the Original Code is GoPivotal, Inc. ## Copyright (c) 2007-2013 GoPivotal, Inc. All rights reserved. ## # Get default settings with user overrides for (RABBITMQ_) # Non-empty defaults should be set in rabbitmq-env . `dirname $0`/rabbitmq-env ##--- Set environment vars RABBITMQ_ to defaults if not set DEFAULT_NODE_IP_ADDRESS=auto DEFAULT_NODE_PORT=5672 [ "x" = "x$RABBITMQ_NODE_IP_ADDRESS" ] && RABBITMQ_NODE_IP_ADDRESS=${NODE_IP_ADDRESS} [ "x" = "x$RABBITMQ_NODE_PORT" ] && RABBITMQ_NODE_PORT=${NODE_PORT} [ "x" = "x$RABBITMQ_NODE_IP_ADDRESS" ] && [ "x" != "x$RABBITMQ_NODE_PORT" ] && RABBITMQ_NODE_IP_ADDRESS=${DEFAULT_NODE_IP_ADDRESS} [ "x" != "x$RABBITMQ_NODE_IP_ADDRESS" ] && [ "x" = "x$RABBITMQ_NODE_PORT" ] && RABBITMQ_NODE_PORT=${DEFAULT_NODE_PORT} [ "x" = "x$RABBITMQ_NODENAME" ] && RABBITMQ_NODENAME=${NODENAME} [ "x" = "x$RABBITMQ_SERVER_ERL_ARGS" ] && RABBITMQ_SERVER_ERL_ARGS=${SERVER_ERL_ARGS} [ "x" = "x$RABBITMQ_CONFIG_FILE" ] && RABBITMQ_CONFIG_FILE=${CONFIG_FILE} [ "x" = "x$RABBITMQ_LOG_BASE" ] && RABBITMQ_LOG_BASE=${LOG_BASE} [ "x" = "x$RABBITMQ_MNESIA_BASE" ] && RABBITMQ_MNESIA_BASE=${MNESIA_BASE} [ "x" = "x$RABBITMQ_SERVER_START_ARGS" ] && RABBITMQ_SERVER_START_ARGS=${SERVER_START_ARGS} [ "x" = "x$RABBITMQ_MNESIA_DIR" ] && RABBITMQ_MNESIA_DIR=${MNESIA_DIR} [ "x" = "x$RABBITMQ_MNESIA_DIR" ] && RABBITMQ_MNESIA_DIR=${RABBITMQ_MNESIA_BASE}/${RABBITMQ_NODENAME} [ "x" = "x$RABBITMQ_PID_FILE" ] && RABBITMQ_PID_FILE=${PID_FILE} [ "x" = "x$RABBITMQ_PID_FILE" ] && RABBITMQ_PID_FILE=${RABBITMQ_MNESIA_DIR}.pid [ "x" = "x$RABBITMQ_PLUGINS_EXPAND_DIR" ] && RABBITMQ_PLUGINS_EXPAND_DIR=${PLUGINS_EXPAND_DIR} [ "x" = "x$RABBITMQ_PLUGINS_EXPAND_DIR" ] && RABBITMQ_PLUGINS_EXPAND_DIR=${RABBITMQ_MNESIA_BASE}/${RABBITMQ_NODENAME}-plugins-expand [ "x" = "x$RABBITMQ_ENABLED_PLUGINS_FILE" ] && RABBITMQ_ENABLED_PLUGINS_FILE=${ENABLED_PLUGINS_FILE} [ "x" = "x$RABBITMQ_PLUGINS_DIR" ] && RABBITMQ_PLUGINS_DIR=${PLUGINS_DIR} ## Log rotation [ "x" = "x$RABBITMQ_LOGS" ] && RABBITMQ_LOGS=${LOGS} [ "x" = "x$RABBITMQ_LOGS" ] && RABBITMQ_LOGS="${RABBITMQ_LOG_BASE}/${RABBITMQ_NODENAME}.log" [ "x" = "x$RABBITMQ_SASL_LOGS" ] && RABBITMQ_SASL_LOGS=${SASL_LOGS} [ "x" = "x$RABBITMQ_SASL_LOGS" ] && RABBITMQ_SASL_LOGS="${RABBITMQ_LOG_BASE}/${RABBITMQ_NODENAME}-sasl.log" ##--- End of overridden variables RABBITMQ_START_RABBIT= [ "x" = "x$RABBITMQ_ALLOW_INPUT" ] && RABBITMQ_START_RABBIT=" -noinput" [ "x" = "x$RABBITMQ_NODE_ONLY" ] && RABBITMQ_START_RABBIT="$RABBITMQ_START_RABBIT -s rabbit boot " case "$(uname -s)" in CYGWIN*) # we make no attempt to record the cygwin pid; rabbitmqctl wait # will not be able to make sense of it anyway ;; *) # When -detached is passed, we don't write the pid, since it'd be the # wrong one detached="" for opt in "$@"; do if [ "$opt" = "-detached" ]; then detached="true" fi done if [ $detached ]; then echo "Warning: PID file not written; -detached was passed." 1>&2 else mkdir -p $(dirname ${RABBITMQ_PID_FILE}); echo $$ > ${RABBITMQ_PID_FILE} fi esac RABBITMQ_EBIN_ROOT="${RABBITMQ_HOME}/ebin" if ! ${ERL_DIR}erl -pa "$RABBITMQ_EBIN_ROOT" \ -boot "${CLEAN_BOOT_FILE}" \ -noinput \ -hidden \ -s rabbit_prelaunch \ -sname rabbitmqprelaunch$$ \ -extra "${RABBITMQ_NODENAME}"; then exit 1; fi RABBITMQ_CONFIG_ARG= [ -f "${RABBITMQ_CONFIG_FILE}.config" ] && RABBITMQ_CONFIG_ARG="-config ${RABBITMQ_CONFIG_FILE}" RABBITMQ_LISTEN_ARG= [ "x" != "x$RABBITMQ_NODE_PORT" ] && [ "x" != "x$RABBITMQ_NODE_IP_ADDRESS" ] && RABBITMQ_LISTEN_ARG="-rabbit tcp_listeners [{\""${RABBITMQ_NODE_IP_ADDRESS}"\","${RABBITMQ_NODE_PORT}"}]" # we need to turn off path expansion because some of the vars, notably # RABBITMQ_SERVER_ERL_ARGS, contain terms that look like globs and # there is no other way of preventing their expansion. set -f exec ${ERL_DIR}erl \ -pa ${RABBITMQ_EBIN_ROOT} \ ${RABBITMQ_START_RABBIT} \ -sname ${RABBITMQ_NODENAME} \ -boot "${SASL_BOOT_FILE}" \ ${RABBITMQ_CONFIG_ARG} \ +W w \ ${RABBITMQ_SERVER_ERL_ARGS} \ ${RABBITMQ_LISTEN_ARG} \ -sasl errlog_type error \ -sasl sasl_error_logger false \ -rabbit error_logger '{file,"'${RABBITMQ_LOGS}'"}' \ -rabbit sasl_error_logger '{file,"'${RABBITMQ_SASL_LOGS}'"}' \ -rabbit enabled_plugins_file "\"$RABBITMQ_ENABLED_PLUGINS_FILE\"" \ -rabbit plugins_dir "\"$RABBITMQ_PLUGINS_DIR\"" \ -rabbit plugins_expand_dir "\"$RABBITMQ_PLUGINS_EXPAND_DIR\"" \ -os_mon start_cpu_sup false \ -os_mon start_disksup false \ -os_mon start_memsup false \ -mnesia dir "\"${RABBITMQ_MNESIA_DIR}\"" \ ${RABBITMQ_SERVER_START_ARGS} \ "$@" rabbitmq-server-3.2.4/scripts/rabbitmq-plugins0000755000000000000000000000261712305126066020227 0ustar rootroot#!/bin/sh ## The contents of this file are subject to the Mozilla Public License ## Version 1.1 (the "License"); you may not use this file except in ## compliance with the License. You may obtain a copy of the License ## at http://www.mozilla.org/MPL/ ## ## Software distributed under the License is distributed on an "AS IS" ## basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See ## the License for the specific language governing rights and ## limitations under the License. ## ## The Original Code is RabbitMQ. ## ## The Initial Developer of the Original Code is GoPivotal, Inc. ## Copyright (c) 2007-2013 GoPivotal, Inc. All rights reserved. ## # Get default settings with user overrides for (RABBITMQ_) # Non-empty defaults should be set in rabbitmq-env . `dirname $0`/rabbitmq-env ##--- Set environment vars RABBITMQ_ to defaults if not set [ "x" = "x$RABBITMQ_ENABLED_PLUGINS_FILE" ] && RABBITMQ_ENABLED_PLUGINS_FILE=${ENABLED_PLUGINS_FILE} [ "x" = "x$RABBITMQ_PLUGINS_DIR" ] && RABBITMQ_PLUGINS_DIR=${PLUGINS_DIR} ##--- End of overridden variables exec ${ERL_DIR}erl \ -pa "${RABBITMQ_HOME}/ebin" \ -noinput \ -hidden \ -sname rabbitmq-plugins$$ \ -boot "${CLEAN_BOOT_FILE}" \ -s rabbit_plugins_main \ -enabled_plugins_file "$RABBITMQ_ENABLED_PLUGINS_FILE" \ -plugins_dist_dir "$RABBITMQ_PLUGINS_DIR" \ -extra "$@" rabbitmq-server-3.2.4/scripts/rabbitmq-env0000755000000000000000000000352512305126066017335 0ustar rootroot#!/bin/sh ## The contents of this file are subject to the Mozilla Public License ## Version 1.1 (the "License"); you may not use this file except in ## compliance with the License. You may obtain a copy of the License ## at http://www.mozilla.org/MPL/ ## ## Software distributed under the License is distributed on an "AS IS" ## basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See ## the License for the specific language governing rights and ## limitations under the License. ## ## The Original Code is RabbitMQ. ## ## The Initial Developer of the Original Code is GoPivotal, Inc. ## Copyright (c) 2007-2013 GoPivotal, Inc. All rights reserved. ## # Determine where this script is really located (if this script is # invoked from another script, this is the location of the caller) SCRIPT_PATH="$0" while [ -h "$SCRIPT_PATH" ] ; do FULL_PATH=`readlink -f $SCRIPT_PATH 2>/dev/null` if [ "$?" != "0" ]; then REL_PATH=`readlink $SCRIPT_PATH` if expr "$REL_PATH" : '/.*' > /dev/null; then SCRIPT_PATH="$REL_PATH" else SCRIPT_PATH="`dirname "$SCRIPT_PATH"`/$REL_PATH" fi else SCRIPT_PATH=$FULL_PATH fi done SCRIPT_DIR=`dirname $SCRIPT_PATH` RABBITMQ_HOME="${SCRIPT_DIR}/.." [ "x" = "x$HOSTNAME" ] && HOSTNAME=`env hostname` NODENAME=rabbit@${HOSTNAME%%.*} ## Set defaults . ${SCRIPT_DIR}/rabbitmq-defaults ## Common defaults SERVER_ERL_ARGS="+K true +A30 +P 1048576 \ -kernel inet_default_connect_options [{nodelay,true}]" # warn about old rabbitmq.conf file, if no new one if [ -f /etc/rabbitmq/rabbitmq.conf ] && \ [ ! -f ${CONF_ENV_FILE} ] ; then echo -n "WARNING: ignoring /etc/rabbitmq/rabbitmq.conf -- " echo "location has moved to ${CONF_ENV_FILE}" fi ## Get configuration variables from the configure environment file [ -f ${CONF_ENV_FILE} ] && . ${CONF_ENV_FILE} rabbitmq-server-3.2.4/scripts/rabbitmq-plugins.bat0000755000000000000000000000355412305126066020775 0ustar rootroot@echo off REM The contents of this file are subject to the Mozilla Public License REM Version 1.1 (the "License"); you may not use this file except in REM compliance with the License. You may obtain a copy of the License REM at http://www.mozilla.org/MPL/ REM REM Software distributed under the License is distributed on an "AS IS" REM basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See REM the License for the specific language governing rights and REM limitations under the License. REM REM The Original Code is RabbitMQ. REM REM The Initial Developer of the Original Code is GoPivotal, Inc. REM Copyright (c) 2007-2013 GoPivotal, Inc. All rights reserved. REM setlocal rem Preserve values that might contain exclamation marks before rem enabling delayed expansion set TDP0=%~dp0 set STAR=%* setlocal enabledelayedexpansion if "!RABBITMQ_SERVICENAME!"=="" ( set RABBITMQ_SERVICENAME=RabbitMQ ) if "!RABBITMQ_BASE!"=="" ( set RABBITMQ_BASE=!APPDATA!\!RABBITMQ_SERVICENAME! ) if not exist "!ERLANG_HOME!\bin\erl.exe" ( echo. echo ****************************** echo ERLANG_HOME not set correctly. echo ****************************** echo. echo Please either set ERLANG_HOME to point to your Erlang installation or place the echo RabbitMQ server distribution in the Erlang lib folder. echo. exit /B ) if "!RABBITMQ_ENABLED_PLUGINS_FILE!"=="" ( set RABBITMQ_ENABLED_PLUGINS_FILE=!RABBITMQ_BASE!\enabled_plugins ) if "!RABBITMQ_PLUGINS_DIR!"=="" ( set RABBITMQ_PLUGINS_DIR=!TDP0!..\plugins ) "!ERLANG_HOME!\bin\erl.exe" -pa "!TDP0!..\ebin" -noinput -hidden -sname rabbitmq-plugins!RANDOM!!TIME:~9! -s rabbit_plugins_main -enabled_plugins_file "!RABBITMQ_ENABLED_PLUGINS_FILE!" -plugins_dist_dir "!RABBITMQ_PLUGINS_DIR:\=/!" -extra !STAR! endlocal endlocal rabbitmq-server-3.2.4/scripts/rabbitmq-echopid.bat0000755000000000000000000000146112305126066020722 0ustar rootroot@echo off REM Usage: rabbitmq-echopid.bat REM REM sname of the erlang node to connect to (required) setlocal if "%1"=="" goto fail :: set timeout vars :: set TIMEOUT=10 set TIMER=1 :: check that wmic exists :: set WMIC_PATH=%SYSTEMROOT%\System32\Wbem\wmic.exe if not exist "%WMIC_PATH%" ( goto fail ) :getpid for /f "usebackq tokens=* skip=1" %%P IN (`%%WMIC_PATH%% process where "name='erl.exe' and commandline like '%%-sname %1%%'" get processid 2^>nul`) do ( set PID=%%P goto echopid ) :echopid :: check for pid not found :: if "%PID%" == "" ( PING 127.0.0.1 -n 2 > nul set /a TIMER+=1 if %TIMEOUT%==%TIMER% goto fail goto getpid ) :: show pid :: echo %PID% :: all done :: :ok endlocal EXIT /B 0 :: something went wrong :: :fail endlocal EXIT /B 1 rabbitmq-server-3.2.4/scripts/rabbitmq-defaults0000755000000000000000000000226712305126066020356 0ustar rootroot#!/bin/sh ## The contents of this file are subject to the Mozilla Public License ## Version 1.1 (the "License"); you may not use this file except in ## compliance with the License. You may obtain a copy of the License ## at http://www.mozilla.org/MPL/ ## ## Software distributed under the License is distributed on an "AS IS" ## basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See ## the License for the specific language governing rights and ## limitations under the License. ## ## The Original Code is RabbitMQ. ## ## The Initial Developer of the Original Code is GoPivotal, Inc. ## Copyright (c) 2012-2013 GoPivotal, Inc. All rights reserved. ## ### next line potentially updated in package install steps SYS_PREFIX= ### next line will be updated when generating a standalone release ERL_DIR= CLEAN_BOOT_FILE=start_clean SASL_BOOT_FILE=start_sasl ## Set default values CONFIG_FILE=${SYS_PREFIX}/etc/rabbitmq/rabbitmq LOG_BASE=${SYS_PREFIX}/var/log/rabbitmq MNESIA_BASE=${SYS_PREFIX}/var/lib/rabbitmq/mnesia ENABLED_PLUGINS_FILE=${SYS_PREFIX}/etc/rabbitmq/enabled_plugins PLUGINS_DIR="${RABBITMQ_HOME}/plugins" CONF_ENV_FILE=${SYS_PREFIX}/etc/rabbitmq/rabbitmq-env.conf rabbitmq-server-3.2.4/plugins-src/0000755000000000000000000000000012305126066015572 5ustar rootrootrabbitmq-server-3.2.4/plugins-src/rabbitmq-management/0000755000000000000000000000000012305126066021505 5ustar rootrootrabbitmq-server-3.2.4/plugins-src/rabbitmq-management/priv/0000755000000000000000000000000012305126066022465 5ustar rootrootrabbitmq-server-3.2.4/plugins-src/rabbitmq-management/priv/www/0000755000000000000000000000000012305126066023311 5ustar rootrootrabbitmq-server-3.2.4/plugins-src/rabbitmq-management/priv/www/index.html0000644000000000000000000000250512305126066025310 0ustar rootroot RabbitMQ Management
rabbitmq-server-3.2.4/plugins-src/rabbitmq-management/priv/www/cli/0000755000000000000000000000000012305126066024060 5ustar rootrootrabbitmq-server-3.2.4/plugins-src/rabbitmq-management/priv/www/cli/index.html0000644000000000000000000000170212305126066026055 0ustar rootroot rabbitmqadmin

rabbitmqadmin

Download it from here (Right click, Save as), make executable, and drop it in your path. Note that many browsers will rename the file rabbitmqadmin.txt. You will need Python 2.x, 2.6 or later (i.e. not Python 3).

See the rabbitmqadmin page on the website for more information on its use, or invoke rabbitmqadmin --help for usage instructions. Windows users will need to ensure Python is on their path, and invoke rabbitmqadmin as python.exe rabbitmqadmin.

rabbitmq-server-3.2.4/plugins-src/rabbitmq-management/priv/www/favicon.ico0000644000000000000000000000047612305126066025441 0ustar rootroot(( fÿ—Áÿýþÿÿÿÿ•¿ÿt¬ÿ5000C@0300C@000033030#3303033303033303033353533333333333rabbitmq-server-3.2.4/plugins-src/rabbitmq-management/priv/www/api/0000755000000000000000000000000012305126066024062 5ustar rootrootrabbitmq-server-3.2.4/plugins-src/rabbitmq-management/priv/www/api/index.html0000644000000000000000000005603112305126066026064 0ustar rootroot RabbitMQ Management HTTP API

RabbitMQ Management HTTP API

Introduction

Apart from this help page, all URIs will serve only resources of type application/json, and will require HTTP basic authentication (using the standard RabbitMQ user database). The default user is guest/guest.

Many URIs require the name of a virtual host as part of the path, since names only uniquely identify objects within a virtual host. As the default virtual host is called "/", this will need to be encoded as "%2f".

PUTing a resource creates it. The JSON object you upload must have certain mandatory keys (documented below) and may have optional keys. Other keys are ignored. Missing mandatory keys constitute an error.

Since bindings do not have names or IDs in AMQP we synthesise one based on all its properties. Since predicting this name is hard in the general case, you can also create bindings by POSTing to a factory URI. See the example below.

Many URIs return lists. Such URIs can have the query string parameters sort and sort_reverse added. sort allows you to select a primary field to sort by, and sort_reverse will reverse the sort order if set to true. The sort parameter can contain subfields separated by dots. This allows you to sort by a nested component of the listed items; it does not allow you to sort by more than one field. See the example below.

You can also restrict what information is returned per item with the columns parameter. This is a comma-separated list of subfields separated by dots. See the example below.

URIs which return some forms of numerical data (such as message rates and queue lengths) can return historical samples. To return samples you need to set an age and an increment for the samples you want. The end of the range returned will always correspond to the present. Use msg_rates_age and msg_rates_incr to return samples for messages sent and received, data_rates_age and data_rates_incr to return samples for bytes sent and received, and lengths_age and lengths_incr to return samples for queue lengths. For example, appending ?lengths_age=3600&lengths_incr=60 will return the last hour's data on queue lengths, with a sample for every minute.

Examples

A few quick examples for Windows and Unix, using the command line tool curl:

  • Get a list of vhosts:
    :: Windows
    C:\> curl -i -u guest:guest http://localhost:15672/api/vhosts
    
    # Unix
    $ curl -i -u guest:guest http://localhost:15672/api/vhosts
    
    HTTP/1.1 200 OK
    Server: MochiWeb/1.1 WebMachine/1.10.0 (never breaks eye contact)
    Date: Mon, 16 Sep 2013 12:00:02 GMT
    Content-Type: application/json
    Content-Length: 30
    
    [{"name":"/","tracing":false}]
    
  • Get a list of channels, fast publishers first, restricting the info items we get back:
    :: Windows
    C:\> curl -i -u guest:guest "http://localhost:15672/api/channels?sort=message_stats.publish_details.rate&sort_reverse=true&columns=name,message_stats.publish_details.rate,message_stats.deliver_get_details.rate"
    
    # Unix
    $ curl -i -u guest:guest 'http://localhost:15672/api/channels?sort=message_stats.publish_details.rate&sort_reverse=true&columns=name,message_stats.publish_details.rate,message_stats.deliver_get_details.rate'
    
    HTTP/1.1 200 OK
    Server: MochiWeb/1.1 WebMachine/1.10.0 (never breaks eye contact)
    Date: Mon, 16 Sep 2013 12:01:17 GMT
    Content-Type: application/json
    Content-Length: 219
    Cache-Control: no-cache
    
    [{"message_stats":{"publish_details":{"rate" ... (remainder elided)
  • Create a new vhost:
    :: Windows
    C:\> curl -i -u guest:guest -H "content-type:application/json" ^
          -XPUT http://localhost:15672/api/vhosts/foo
    
    # Unix
    $ curl -i -u guest:guest -H "content-type:application/json" \
       -XPUT http://localhost:15672/api/vhosts/foo
    
    HTTP/1.1 204 No Content
    Server: MochiWeb/1.1 WebMachine/1.10.0 (never breaks eye contact)
    Date: Mon, 16 Sep 2013 12:03:00 GMT
    Content-Type: application/json
    Content-Length: 0

    Note: you must specify application/json as the mime type.

    Note: the name of the object is not needed in the JSON object uploaded, since it is in the URI. As a virtual host has no properties apart from its name, this means you do not need to specify a body at all!

  • Create a new exchange in the default virtual host:
    :: Windows
    C:\> curl -i -u guest:guest -H "content-type:application/json" ^
           -XPUT -d"{""type"":""direct"",""durable"":true}" ^
           http://localhost:15672/api/exchanges/%2f/my-new-exchange
    
    # Unix
    $ curl -i -u guest:guest -H "content-type:application/json" \
        -XPUT -d'{"type":"direct","durable":true}' \
        http://localhost:15672/api/exchanges/%2f/my-new-exchange
    
    HTTP/1.1 204 No Content
    Server: MochiWeb/1.1 WebMachine/1.10.0 (never breaks eye contact)
    Date: Mon, 16 Sep 2013 12:04:00 GMT
    Content-Type: application/json
    Content-Length: 0

    Note: we never return a body in response to a PUT or DELETE, unless it fails.

  • And delete it again:
    :: Windows
    C:\> curl -i -u guest:guest -H "content-type:application/json" ^
           -XDELETE http://localhost:15672/api/exchanges/%2f/my-new-exchange
    
    # Unix
    $ curl -i -u guest:guest -H "content-type:application/json" \
        -XDELETE http://localhost:15672/api/exchanges/%2f/my-new-exchange
    
    HTTP/1.1 204 No Content
    Server: MochiWeb/1.1 WebMachine/1.10.0 (never breaks eye contact)
    Date: Mon, 16 Sep 2013 12:05:30 GMT
    Content-Type: application/json
    Content-Length: 0

Reference

GET PUT DELETE POST Path Description
X /api/overview Various random bits of information that describe the whole system.
X /api/nodes A list of nodes in the RabbitMQ cluster.
X /api/nodes/name An individual node in the RabbitMQ cluster. Add "?memory=true" to get memory statistics.
X /api/extensions A list of extensions to the management plugin.
X X /api/definitions
/api/all-configuration (deprecated)
The server definitions - exchanges, queues, bindings, users, virtual hosts, permissions and parameters. Everything apart from messages. POST to upload an existing set of definitions. Note that:
  • The definitions are merged. Anything already existing is untouched.
  • Conflicts will cause an error.
  • In the event of an error you will be left with a part-applied set of definitions.
For convenience you may upload a file from a browser to this URI (i.e. you can use multipart/form-data as well as application/json) in which case the definitions should be uploaded as a form field named "file".
X /api/connections A list of all open connections.
X X /api/connections/name An individual connection. DELETEing it will close the connection. Optionally set the "X-Reason" header when DELETEing to provide a reason.
X /api/channels A list of all open channels.
X /api/channels/channel Details about an individual channel.
X /api/exchanges A list of all exchanges.
X /api/exchanges/vhost A list of all exchanges in a given virtual host.
X X X /api/exchanges/vhost/name An individual exchange. To PUT an exchange, you will need a body looking something like this:
{"type":"direct","auto_delete":false,"durable":true,"internal":false,"arguments":[]}
The type key is mandatory; other keys are optional.
X /api/exchanges/vhost/name/bindings/source A list of all bindings in which a given exchange is the source.
X /api/exchanges/vhost/name/bindings/destination A list of all bindings in which a given exchange is the destination.
X /api/exchanges/vhost/name/publish Publish a message to a given exchange. You will need a body looking something like:
{"properties":{},"routing_key":"my key","payload":"my body","payload_encoding":"string"}
All keys are mandatory. The payload_encoding key should be either "string" (in which case the payload will be taken to be the UTF-8 encoding of the payload field) or "base64" (in which case the payload field is taken to be base64 encoded).
If the message is published successfully, the response will look like:
{"routed": true}
routed will be true if the message was sent to at least one queue.

Please note that the publish / get paths in the HTTP API are intended for injecting test messages, diagnostics etc - they do not implement reliable delivery and so should be treated as a sysadmin's tool rather than a general API for messaging.

X /api/queues A list of all queues.
X /api/queues/vhost A list of all queues in a given virtual host.
X X X /api/queues/vhost/name An individual queue. To PUT a queue, you will need a body looking something like this:
{"auto_delete":false,"durable":true,"arguments":[],"node":"rabbit@smacmullen"}
All keys are optional.
X /api/queues/vhost/name/bindings A list of all bindings on a given queue.
X /api/queues/vhost/name/contents Contents of a queue. DELETE to purge. Note you can't GET this.
X /api/queues/vhost/name/actions Actions that can be taken on a queue. POST a body like:
{"action":"sync"}
Currently the actions which are supported are sync and cancel_sync.
X /api/queues/vhost/name/get Get messages from a queue. (This is not an HTTP GET as it will alter the state of the queue.) You should post a body looking like:
{"count":5,"requeue":true,"encoding":"auto","truncate":50000}
  • count controls the maximum number of messages to get. You may get fewer messages than this if the queue cannot immediately provide them.
  • requeue determines whether the messages will be removed from the queue. If requeue is true they will be requeued - but their redelivered flag will be set.
  • encoding must be either "auto" (in which case the payload will be returned as a string if it is valid UTF-8, and base64 encoded otherwise), or "base64" (in which case the payload will always be base64 encoded).
  • If truncate is present it will truncate the message payload if it is larger than the size given (in bytes).

truncate is optional; all other keys are mandatory.

Please note that the publish / get paths in the HTTP API are intended for injecting test messages, diagnostics etc - they do not implement reliable delivery and so should be treated as a sysadmin's tool rather than a general API for messaging.

X /api/bindings A list of all bindings.
X /api/bindings/vhost A list of all bindings in a given virtual host.
X X /api/bindings/vhost/e/exchange/q/queue A list of all bindings between an exchange and a queue. Remember, an exchange and a queue can be bound together many times! To create a new binding, POST to this URI. You will need a body looking something like this:
{"routing_key":"my_routing_key","arguments":[]}
All keys are optional. The response will contain a Location header telling you the URI of your new binding.
X X /api/bindings/vhost/e/exchange/q/queue/props An individual binding between an exchange and a queue. The props part of the URI is a "name" for the binding composed of its routing key and a hash of its arguments.
X X /api/bindings/vhost/e/source/e/destination A list of all bindings between two exchanges. Similar to the list of all bindings between an exchange and a queue, above.
X X /api/bindings/vhost/e/source/e/destination/props An individual binding between two exchanges. Similar to the individual binding between an exchange and a queue, above.
X /api/vhosts A list of all vhosts.
X X X /api/vhosts/name An individual virtual host. As a virtual host usually only has a name, you do not need an HTTP body when PUTing one of these. To enable / disable tracing, provide a body looking like:
{"tracing":true}
X /api/vhosts/name/permissions A list of all permissions for a given virtual host.
X /api/users A list of all users.
X X X /api/users/name An individual user. To PUT a user, you will need a body looking something like this:
{"password":"secret","tags":"administrator"}
or:
{"password_hash":"2lmoth8l4H0DViLaK9Fxi6l9ds8=", "tags":"administrator"}
The tags key is mandatory. Either password or password_hash must be set. Setting password_hash to "" will ensure the user cannot use a password to log in. tags is a comma-separated list of tags for the user. Currently recognised tags are "administrator", "monitoring" and "management".
X /api/users/user/permissions A list of all permissions for a given user.
X /api/whoami Details of the currently authenticated user.
X /api/permissions A list of all permissions for all users.
X X X /api/permissions/vhost/user An individual permission of a user and virtual host. To PUT a permission, you will need a body looking something like this:
{"configure":".*","write":".*","read":".*"}
All keys are mandatory.
X /api/parameters A list of all parameters.
X /api/parameters/component A list of all parameters for a given component.
X /api/parameters/component/vhost A list of all parameters for a given component and virtual host.
X X X /api/parameters/component/vhost/name An individual parameter. To PUT a parameter, you will need a body looking something like this:
{"vhost": "/","component":"federation","name":"local_username","value":"guest"}
X /api/policies A list of all policies.
X /api/policies/vhost A list of all policies in a given virtual host.
X X X /api/policies/vhost/name An individual policy. To PUT a policy, you will need a body looking something like this:
{"pattern":"^amq.", "definition": {"federation-upstream-set":"all"}, "priority":0, "apply-to": "all"}
pattern and definition are mandatory, priority and apply-to are optional.
X /api/aliveness-test/vhost Declares a test queue, then publishes and consumes a message. Intended for use by monitoring tools. If everything is working correctly, will return HTTP status 200 with body:
{"status":"ok"}
Note: the test queue will not be deleted (to to prevent queue churn if this is repeatedly pinged).
rabbitmq-server-3.2.4/plugins-src/rabbitmq-management/priv/www/js/0000755000000000000000000000000012305126066023725 5ustar rootrootrabbitmq-server-3.2.4/plugins-src/rabbitmq-management/priv/www/js/charts.js0000644000000000000000000000446212305126066025555 0ustar rootrootfunction render_charts() { $('.chart').map(function() { render_chart($(this)); }); } var chart_colors = ['#edc240', '#afd8f8', '#cb4b4b', '#4da74d', '#9440ed', '#666666', '#aaaaaa']; var chart_chrome = { series: { lines: { show: true } }, grid: { borderWidth: 2, borderColor: "#aaa" }, xaxis: { tickColor: "#fff", mode: "time", timezone: "browser" }, yaxis: { tickColor: "#eee", min: 0 }, legend: { show: false } }; function render_chart(div) { var id = div.attr('id').substring('chart-'.length); var rate_mode = div.hasClass('chart-rates'); var out_data = []; var i = 0; var data = chart_data[id]['data']; var fmt = chart_data[id]['fmt']; for (var name in data) { var series = data[name]; var samples = series.samples; var d = []; for (var j = 1; j < samples.length; j++) { var x = samples[j].timestamp; var y; if (rate_mode) { // TODO This doesn't work well if you are looking at // stuff in the browser that is finer granularity than // the data we have in the DB (and thus we get // duplicated entries). Do we care? We should just // never allow that... y = (samples[j - 1].sample - samples[j].sample) * 1000 / (samples[j - 1].timestamp - samples[j].timestamp); } else { y = samples[j].sample; } d.push([x, y]); } out_data.push({data: d, color: chart_colors[i], shadowSize: 0}); i++; } chart_data[id] = {}; chart_chrome.yaxis.tickFormatter = fmt_y_axis(fmt); $.plot(div, out_data, chart_chrome); } function fmt_y_axis(fmt) { return function (val, axis) { // axis.ticks seems to include the bottom value but not the top if (axis.max == 1 && axis.ticks.length > 1) { var newTicks = [axis.ticks[0]]; axis.ticks = newTicks; } return fmt(val, axis.max); } } function update_rate_options(sammy) { var id = sammy.params['id']; store_pref('rate-mode-' + id, sammy.params['mode']); store_pref('chart-size-' + id, sammy.params['size']); store_pref('chart-range-' + id, sammy.params['range']); partial_update(); } rabbitmq-server-3.2.4/plugins-src/rabbitmq-management/priv/www/js/jquery.flot.time.min.js0000644000000000000000000001143112305126066030264 0ustar rootroot/* Pretty handling of time axes. Copyright (c) 2007-2013 IOLA and Ole Laursen. Licensed under the MIT license. Set axis.mode to "time" to enable. See the section "Time series data" in API.txt for details. */(function(e){function n(e,t){return t*Math.floor(e/t)}function r(e,t,n,r){if(typeof e.strftime=="function")return e.strftime(t);var i=function(e,t){return e=""+e,t=""+(t==null?"0":t),e.length==1?t+e:e},s=[],o=!1,u=e.getHours(),a=u<12;n==null&&(n=["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"]),r==null&&(r=["Sun","Mon","Tue","Wed","Thu","Fri","Sat"]);var f;u>12?f=u-12:u==0?f=12:f=u;for(var l=0;l=u)break;var h=l[c][0],p=l[c][1];if(p=="year"){if(i.minTickSize!=null&&i.minTickSize[1]=="year")h=Math.floor(i.minTickSize[0]);else{var d=Math.pow(10,Math.floor(Math.log(e.delta/o.year)/Math.LN10)),v=e.delta/o.year/d;v<1.5?h=1:v<3?h=2:v<7.5?h=5:h=10,h*=d}h<1&&(h=1)}e.tickSize=i.tickSize||[h,p];var m=e.tickSize[0];p=e.tickSize[1];var g=m*o[p];p=="second"?r.setSeconds(n(r.getSeconds(),m)):p=="minute"?r.setMinutes(n(r.getMinutes(),m)):p=="hour"?r.setHours(n(r.getHours(),m)):p=="month"?r.setMonth(n(r.getMonth(),m)):p=="quarter"?r.setMonth(3*n(r.getMonth()/3,m)):p=="year"&&r.setFullYear(n(r.getFullYear(),m)),r.setMilliseconds(0),g>=o.minute&&r.setSeconds(0),g>=o.hour&&r.setMinutes(0),g>=o.day&&r.setHours(0),g>=o.day*4&&r.setDate(1),g>=o.month*2&&r.setMonth(n(r.getMonth(),3)),g>=o.quarter*2&&r.setMonth(n(r.getMonth(),6)),g>=o.year&&r.setMonth(0);var y=0,b=Number.NaN,w;do{w=b,b=r.getTime(),t.push(b);if(p=="month"||p=="quarter")if(m<1){r.setDate(1);var E=r.getTime();r.setMonth(r.getMonth()+(p=="quarter"?3:1));var S=r.getTime();r.setTime(b+y*o.hour+(S-E)*m),y=r.getHours(),r.setHours(0)}else r.setMonth(r.getMonth()+m*(p=="quarter"?3:1));else p=="year"?r.setFullYear(r.getFullYear()+m):r.setTime(b+g)}while(b 0) { %> <% var col_return_unroutable = !is_col_empty(channels, 'return_unroutable'); var col_redeliver = !is_col_empty(channels, 'redeliver'); var ratesWidth = col_return_unroutable ? 5 : 4; %> <% if (mode == 'standalone') { %> <% } else { %> <% } %> <% if (statistics_level == 'fine') { %> <% } %> <% if (mode == 'standalone') { %> <% if (nodes_interesting) { %> <% } %> <% if (vhosts_interesting) { %> <% } %> <% if (statistics_level == 'fine') { %> <% if (col_return_unroutable) { %> <% } %> <% } %> <% } else { %> <% if (statistics_level == 'fine') { %> <% if (col_return_unroutable) { %> <% } %> <% } %> <% } %> <% for (var i = 0; i < channels.length; i++) { var channel = channels[i]; %> > <% if (mode == 'standalone' && nodes_interesting) { %> <% } %> <% if (mode == 'standalone') { %> <% if (vhosts_interesting) { %> <% } %> <% } %> <% if (statistics_level == 'fine') { %> <% if (col_return_unroutable) { %> <% } %> <% } %> <% } %>
Details DetailsMessage rates
<%= fmt_sort('Channel', 'name') %><%= fmt_sort('Node', 'node') %><%= fmt_sort('Virtual host', 'vhost') %><%= fmt_sort('User name', 'user') %> Mode <%= fmt_sort('Prefetch', 'prefetch_count') %> <%= fmt_sort('Unacked', 'messages_unacknowledged') %> <%= fmt_sort('Unconfirmed', 'messages_unconfirmed') %> <%= fmt_sort('Status', 'idle_since') %><%= fmt_sort('publish', 'message_stats.publish_details.rate') %> <%= fmt_sort('confirm', 'message_stats.confirm_details.rate') %> <%= fmt_sort('deliver / get', 'message_stats.deliver_get_details.rate') %> <% if (col_redeliver) { %> <%= fmt_sort('of which redelivered', 'message_stats.redeliver_details.rate') %> <% } %> <%= fmt_sort('ack', 'message_stats.ack_details.rate') %><%= fmt_sort('return (mandatory)', 'message_stats.return_unroutable_details.rate') %> Channel Mode Prefetch Unacked Unconfirmed Statuspublish confirm deliver / get <% if (col_redeliver) { %> of which redelivered <% } %> ackreturn (mandatory)
<%= link_channel(channel.name) %> <%= fmt_node(channel.node) %><%= fmt_string(channel.vhost) %><%= fmt_string(channel.user) %> <%= fmt_channel_mode(channel) %> <% if (channel.transactional) { %> <%= channel.messages_uncommitted %>m/<%= channel.acks_uncommitted %>a <% } %> <%= channel.prefetch_count %> <%= channel.messages_unacknowledged %> <%= channel.messages_unconfirmed %> <%= fmt_idle(channel) %><%= fmt_rate(channel.message_stats, 'publish') %> <%= fmt_rate(channel.message_stats, 'confirm') %> <%= fmt_deliver_rate(channel.message_stats, col_redeliver) %> <%= fmt_rate(channel.message_stats, 'ack') %><%= fmt_rate(channel.message_stats, 'return_unroutable') %>
<% } else { %>

... no channels ...

<% } %> rabbitmq-server-3.2.4/plugins-src/rabbitmq-management/priv/www/js/tmpl/policy.ejs0000644000000000000000000000216712305126066026711 0ustar rootroot

Policy: <%= fmt_string(policy.name) %>

Overview

Virtual Host <%= fmt_string(policy.vhost) %>
Pattern <%= fmt_string(policy.pattern) %>
Apply to <%= fmt_string(policy['apply-to']) %>
Definition <%= fmt_table_short(policy.definition) %>
Priority <%= fmt_string(policy.priority) %>

Delete this policy

rabbitmq-server-3.2.4/plugins-src/rabbitmq-management/priv/www/js/tmpl/exchanges.ejs0000644000000000000000000001011312305126066027345 0ustar rootroot

Exchanges

All exchanges

<%= filter_ui(exchanges) %>
<% if (exchanges.length > 0) { %> <% if (vhosts_interesting) { %> <% } %> <% if (statistics_level == 'fine') { %> <% } %> <% for (var i = 0; i < exchanges.length; i++) { var exchange = exchanges[i]; %> > <% if (vhosts_interesting) { %> <% } %> <% if (statistics_level == 'fine') { %> <% } %> <% } %>
<%= fmt_sort('Virtual host', 'vhost') %><%= fmt_sort('Name', 'name') %> <%= fmt_sort('Type', 'type') %> <%= fmt_sort('Policy', 'policy') %> Parameters<%= fmt_sort('Message rate in', 'message_stats.publish_in_details.rate') %> <%= fmt_sort('Message rate out', 'message_stats.publish_out_details.rate') %>
<%= fmt_string(exchange.vhost) %><%= link_exchange(exchange.vhost, exchange.name, exchange.arguments) %> <%= fmt_exchange_type(exchange.type) %> <%= fmt_string(exchange.policy, '') %> <%= fmt_parameters_short(exchange) %><%= fmt_rate(exchange.message_stats, 'publish_in') %> <%= fmt_rate(exchange.message_stats, 'publish_out') %>
<% } else { %>

... no exchanges ...

<% } %>

Add a new exchange

<% if (vhosts_interesting) { %> <% } else { %> <% } %>
*
rabbitmq-server-3.2.4/plugins-src/rabbitmq-management/priv/www/js/tmpl/consumers.ejs0000644000000000000000000000210512305126066027420 0ustar rootroot<% if (consumers.length > 0) { %> <% if (mode == 'queue') { %> <% } else { %> <% } %> <% for (var i = 0; i < consumers.length; i++) { var consumer = consumers[i]; %> > <% if (mode == 'queue') { %> <% } else { %> <% } %> <% } %>
Channel Consumer tagConsumer tag QueueAck required Exclusive Arguments
<%= link_channel(consumer.channel_details.name) %> <%= fmt_string(consumer.consumer_tag) %><%= fmt_string(consumer.consumer_tag) %> <%= link_queue(consumer.queue.vhost, consumer.queue.name) %><%= fmt_boolean(consumer.ack_required) %> <%= fmt_boolean(consumer.exclusive) %> <%= fmt_table_short(consumer.arguments) %>
<% } else { %>

... no consumers ...

<% } %> rabbitmq-server-3.2.4/plugins-src/rabbitmq-management/priv/www/js/tmpl/error-popup.ejs0000644000000000000000000000013712305126066027677 0ustar rootroot
<%= text %>

Close
rabbitmq-server-3.2.4/plugins-src/rabbitmq-management/priv/www/js/tmpl/queue.ejs0000644000000000000000000001657312305126066026544 0ustar rootroot

Queue <%= fmt_string(queue.name) %>

Overview

<%= queue_lengths('lengths-q', queue) %> <% if (statistics_level == 'fine') { %> <%= message_rates('msg-rates-q', queue.message_stats) %> <% } %>

Details

Parameters <%= fmt_parameters(queue) %>
Policy <%= fmt_string(queue.policy, '') %>
Exclusive owner <% if (queue.owner_pid_details == undefined) { %> None <% } else { %> <%= link_conn(queue.owner_pid_details.name) %> <% } %>
Status <%= fmt_idle_long(queue) %>
Consumers <%= fmt_string(queue.consumers) %>
Memory <%= fmt_bytes(queue.memory) %>
Paging <% var messages_ram = queue.backing_queue_status.ram_msg_count + queue.backing_queue_status.ram_ack_count; %> <% if (messages_ram == queue.messages) { %> No paging <% } else { %> <%= fmt_num_thousands(messages_ram) %> / <%= fmt_num_thousands(queue.messages) %> msg (in RAM / total) <% } %> <% if (queue.backing_queue_status.target_ram_count == 'infinity') { %> No limit <% } else { %> RAM target: <%= fmt_num_thousands(queue.backing_queue_status.target_ram_count) %> msg <% } %>
Persistent <%= fmt_num_thousands(queue.backing_queue_status.persistent_count) %> msg
<% if (vhosts_interesting) { %> <% } %> <% if (nodes_interesting) { %> <% } %>
Virtual host <%= fmt_string(queue.vhost) %>
Node <%= fmt_node(queue.node) %>
Slaves <% var has_unsynced_node = false; for (var i in queue.slave_nodes) { var node = queue.slave_nodes[i]; %> <% if (jQuery.inArray(node, queue.synchronised_slave_nodes) == -1) { has_unsynced_node = true; %> <%= fmt_node(node) %> (unsynchronised) <% } else { %> <%= fmt_node(node) %> <% } %>
<% } %> <% if (queue.status == 'syncing') { %>
<%= fmt_sync_status(queue) %>
<% } else if (has_unsynced_node) { %>
<% } %>
<% if (statistics_level == 'fine') { %>

Message rates breakdown

<%= format('msg-detail-publishes', {'mode': 'queue', 'object': queue.incoming, 'label': 'Incoming'}) %> <%= format('msg-detail-deliveries', {'mode': 'queue', 'object': queue.deliveries}) %>
<% } %>

Consumers

<%= format('consumers', {'mode': 'queue', 'consumers': queue.consumer_details}) %>

Bindings

<%= format('bindings', {'mode': 'queue', 'bindings': bindings}) %>

This queue

<%= format('add-binding', {'mode': 'queue', 'parent': queue}) %>
<%= format('publish', {'mode': 'queue', 'queue': queue}) %>

Get messages

Warning: getting messages from a queue is a destructive action.

Delete / purge

rabbitmq-server-3.2.4/plugins-src/rabbitmq-management/priv/www/js/tmpl/channels.ejs0000644000000000000000000000023312305126066027175 0ustar rootroot

Channels

<%= filter_ui(channels) %>
<%= format('channels-list', {'channels': channels, 'mode': 'standalone'}) %>
rabbitmq-server-3.2.4/plugins-src/rabbitmq-management/priv/www/js/tmpl/registry.ejs0000644000000000000000000000107112305126066027253 0ustar rootroot<% if (node.running) { %> <% if (show_enabled) { %> <% } %> <% for (var i = 0; i < list.length; i++) { var item = list[i]; %> > <% if (show_enabled) { %> <% } %> <% } %>
Name DescriptionEnabled
<%= fmt_string(item.name) %> <%= fmt_string(item.description) %><%= fmt_boolean(item.enabled) %>
<% } else {%>

...node not running...

<% } %> rabbitmq-server-3.2.4/plugins-src/rabbitmq-management/priv/www/js/tmpl/permissions.ejs0000644000000000000000000000562112305126066027763 0ustar rootroot

Permissions

Current permissions

<% if (permissions.length > 0) { %> <% if (mode == 'vhost') { %> <% } else { %> <% } %> <% for (var i = 0; i < permissions.length; i++) { var permission = permissions[i]; %> > <% if (mode == 'vhost') { %> <% } else { %> <% } %> <% } %>
UserVirtual hostConfigure regexp Write regexp Read regexp
<%= link_user(permission.user) %><%= link_vhost(permission.vhost) %><%= fmt_string(permission.configure) %> <%= fmt_string(permission.write) %> <%= fmt_string(permission.read) %>
<% } else { %>

... no permissions ...

<% } %>

Set permission

<% if (mode == 'vhost') { %> <% } else { %> <% } %>
User
rabbitmq-server-3.2.4/plugins-src/rabbitmq-management/priv/www/js/tmpl/partition.ejs0000644000000000000000000000266512305126066027426 0ustar rootroot
<% var partitions = []; for (var i = 0; i < nodes.length; i++) { var node = nodes[i]; if (node.partitions != undefined && node.partitions.length != 0) { partitions.push({'node': node.name, 'others': node.partitions}); } } if (partitions.length > 0) { %>

Network partition detected

Mnesia reports that this RabbitMQ cluster has experienced a network partition. This is a dangerous situation. RabbitMQ clusters should not be installed on networks which can experience partitions.

The nature of the partition is as follows:

<% for (var i = 0; i < partitions.length; i++) { var partition = partitions[i]; %> > <% } %>
NodeWas partitioned from
<%= partition.node %> <% for (var j = 0; j < partition.others.length; j++) { var other = partition.others[j]; %> <%= other %>
<% } %>

While running in this partitioned state, changes (such as queue or exchange declaration and binding) which take place in one partition will not be visible to other partition(s). Other behaviour is not guaranteed.

More information on network partitions.

<% } %>
rabbitmq-server-3.2.4/plugins-src/rabbitmq-management/priv/www/js/tmpl/layout.ejs0000644000000000000000000000211112305126066026714 0ustar rootroot
rabbitmq-server-3.2.4/plugins-src/rabbitmq-management/priv/www/js/tmpl/connections.ejs0000644000000000000000000000373412305126066027735 0ustar rootroot

Connections

<%= filter_ui(connections) %>
<% if (connections.length > 0) { %> <% if (nodes_interesting) { %> <% } %> <% if (vhosts_interesting) { %> <% } %> <% for (var i = 0; i < connections.length; i++) { var connection = connections[i]; %> > <% if (nodes_interesting) { %> <% } %> <% if (vhosts_interesting) { %> <% } %> <% } %>
Network Overview
<%= fmt_sort('Name', 'name') %> <%= fmt_sort('Protocol', 'protocol') %> <%= fmt_sort('Client', 'properties') %><%= fmt_sort('Node', 'node') %><%= fmt_sort('From client', 'recv_oct_details.rate') %> <%= fmt_sort('To client', 'send_oct_details.rate') %> <%= fmt_sort('Timeout', 'timeout') %> <%= fmt_sort('Channels', 'channels') %><%= fmt_sort('Virtual host', 'vhost') %><%= fmt_sort('User name', 'user') %> <%= fmt_sort('State', 'state') %>
<%= link_conn(connection.name) %> <%= connection.protocol %> <% if (connection.ssl) { %> SSL <% } %> <%= fmt_client_name(connection.client_properties) %><%= fmt_node(connection.node) %><%= fmt_rate_bytes(connection, 'recv_oct') %> <%= fmt_rate_bytes(connection, 'send_oct') %> <%= fmt_time(connection.timeout, 's') %> <%= connection.channels %><%= fmt_string(connection.vhost) %><%= fmt_string(connection.user) %> <%= fmt_connection_state(connection) %>
<% } else { %>

... no connections ...

<% } %>
rabbitmq-server-3.2.4/plugins-src/rabbitmq-management/priv/www/js/tmpl/add-binding.ejs0000644000000000000000000000351212305126066027545 0ustar rootroot<% if (mode == 'queue') { %>

Add binding to this queue

<% } else { %>

Add binding from this exchange

<% } %>
<% if (mode == 'queue') { %> <% } else { %> <% } %> <% if (mode == 'queue') { %> <% } else { %> <% } %>
*
: *
rabbitmq-server-3.2.4/plugins-src/rabbitmq-management/priv/www/js/tmpl/queues.ejs0000644000000000000000000001366312305126066026724 0ustar rootroot

Queues

All queues

<%= filter_ui(queues) %>
<% if (queues.length > 0) { %> <% var col_redeliver = !is_col_empty(queues, 'redeliver'); %> <% if (statistics_level == 'fine') { %> <% } %> <% if (vhosts_interesting) { %> <% } %> <% if (nodes_interesting) { %> <% } %> <% if (statistics_level == 'fine') { %> <% } %> <% for (var i = 0; i < queues.length; i++) { var queue = queues[i]; %> > <% if (vhosts_interesting) { %> <% } %> <% if (nodes_interesting) { %> <% } %> <% if (statistics_level == 'fine') { %> <% } %> <% } %>
Overview MessagesMessage rates
<%= fmt_sort('Virtual host', 'vhost') %><%= fmt_sort('Name', 'name') %><%= fmt_sort('Node', 'node') %><%= fmt_sort('Exclusive', 'owner_pid_details.name') %> Parameters <%= fmt_sort('Policy', 'policy') %> <%= fmt_sort('Status', 'idle_since') %> <%= fmt_sort('Ready', 'messages_ready') %> <%= fmt_sort('Unacked', 'messages_unacknowledged') %> <%= fmt_sort('Total', 'messages') %><%= fmt_sort('incoming', 'message_stats.publish_details.rate') %> <%= fmt_sort('deliver / get', 'message_stats.deliver_get_details.rate') %> <% if (col_redeliver) { %> <%= fmt_sort('of which redelivered', 'message_stats.redeliver_details.rate') %> <% } %> <%= fmt_sort('ack', 'message_stats.ack_details.rate') %>
<%= fmt_string(queue.vhost) %><%= link_queue(queue.vhost, queue.name, queue.arguments) %> <%= fmt_node(queue.node) %> <%= fmt_mirrors(queue) %> <% if (queue.status == 'syncing') { %> <%= fmt_sync_status(queue) %> <% } %> <% if (queue.owner_pid_details != undefined) { %> <%= link_conn(queue.owner_pid_details.name, "Owner") %> <% } %> <%= fmt_parameters_short(queue) %> <%= fmt_string(queue.policy, '') %> <%= fmt_idle(queue) %> <%= fmt_num_thousands(queue.messages_ready) %> <%= fmt_num_thousands(queue.messages_unacknowledged) %> <%= fmt_num_thousands(queue.messages) %><%= fmt_rate(queue.message_stats, 'publish') %> <%= fmt_deliver_rate(queue.message_stats, col_redeliver) %> <%= fmt_rate(queue.message_stats, 'ack') %>
<% } else { %>

... no queues ...

<% } %>

Add a new queue

<% if (vhosts_interesting) { %> <% } else { %> <% } %> <% if (nodes_interesting) { var nodes = JSON.parse(sync_get('/nodes')); %> <% } %>
*
ms
ms
rabbitmq-server-3.2.4/plugins-src/rabbitmq-management/priv/www/js/tmpl/exchange.ejs0000644000000000000000000000560712305126066027176 0ustar rootroot

Exchange: <%= fmt_exchange(exchange.name) %>

Overview

<% if (statistics_level == 'fine') { %> <%= message_rates('msg-rates-x', exchange.message_stats) %> <% } %>

Details

<% if (vhosts_interesting) { %> <% } %>
Type <%= fmt_exchange_type(exchange.type) %>
Parameters <%= fmt_parameters(exchange) %>
Policy <%= fmt_string(exchange.policy, '') %>
Virtual host <%= fmt_string(exchange.vhost) %>
<% if (statistics_level == 'fine') { %>

Message rates breakdown

<%= format('msg-detail-publishes', {'mode': 'exchange-incoming', 'object': exchange.incoming, 'label': 'Incoming '}) %> <%= format('msg-detail-publishes', {'mode': 'exchange-outgoing', 'object': exchange.outgoing, 'label': 'Outgoing '}) %>
<% } %>

Bindings

<% if (exchange.name == "") { %>

Default exchange

The default exchange is implicitly bound to every queue, with a routing key equal to the queue name. It it not possible to explicitly bind to, or unbind from the default exchange. It also cannot be deleted.

<% } else { %>
<% if (bindings_destination.length > 0) { %> <%= format('bindings', {'mode': 'exchange_destination', 'bindings': bindings_destination}) %>

<% } %>

This exchange

<%= format('bindings', {'mode': 'exchange_source', 'bindings': bindings_source}) %>
<%= format('add-binding', {'mode': 'exchange_source', 'parent': exchange}) %> <% } %>
<% if (!exchange.internal) { %> <%= format('publish', {'mode': 'exchange', 'exchange': exchange}) %> <% } %> <% if (exchange.name != "") { %>

Delete this exchange

<% } %> rabbitmq-server-3.2.4/plugins-src/rabbitmq-management/priv/www/js/tmpl/node.ejs0000644000000000000000000001136012305126066026332 0ustar rootroot

Node <%= node.name %>

Overview

<% if (!node.running) { %>

Node not running

<% } else if (node.os_pid == undefined) { %>

Node statistics not available

<% } else { %>
File descriptors <%= fmt_resource_bar_count(fmt_fd_used(node.fd_used, node.fd_total), node.fd_total, FD_THRESHOLDS) %>
Socket descriptors <%= fmt_resource_bar_count(node.sockets_used, node.sockets_total, FD_THRESHOLDS) %>
Erlang processes <%= fmt_resource_bar_count(node.proc_used, node.proc_total, PROCESS_THRESHOLDS) %>
Memory <% if (node.mem_limit != 'memory_monitoring_disabled') { %> <%= fmt_resource_bar(fmt_bytes(node.mem_used), fmt_bytes(node.mem_limit) + ' high watermark', node.mem_used / node.mem_limit, node.mem_alarm ? 'red' : 'green', node.mem_alarm ? 'memory-alarm' : null) %> <% } else { %> <%= fmt_bytes(node.mem_used) %> <% } %>
Disk space <% if (node.disk_free_limit != 'disk_free_monitoring_disabled') { %> <%= fmt_resource_bar(fmt_bytes(node.disk_free), fmt_bytes(node.disk_free_limit) + ' low watermark', node.disk_free_limit / node.disk_free, node.disk_free_alarm ? 'red' : 'green', node.disk_free_alarm ? 'disk_free-alarm' : null) %> <% } else { %> (not available) <% } %>
<% if (rabbit_versions_interesting) { %> <% } %>
Uptime <%= fmt_uptime(node.uptime) %>
RabbitMQ Version <%= fmt_rabbit_version(node.applications) %>
Type <% if (node.type == 'disc') { %> Disc <% } else { %> RAM <% } %>
<% } %>

Memory details

Applications

<% if (!node.running) { %>

Node not running

<% } else if (node.os_pid == undefined) { %>

Node statistics not available

<% } else { %> <% for (var j = 0; j < node.applications.length; j++) { var application = node.applications[j]; %> > <% } %>
Name Version
<%= application.name %> <%= application.description %> <%= application.version %>
<% } %>

Registry

<% if (!node.running) { %>

Node not running

<% } else if (node.os_pid == undefined) { %>

Node statistics not available

<% } else { %>

Exchange types

<%= format('registry', {'list': node.exchange_types, 'node': node, 'show_enabled': false} ) %>

Authentication mechanisms

<%= format('registry', {'list': node.auth_mechanisms, 'node': node, 'show_enabled': true} ) %> <% } %>

Advanced

<% if (!node.running) { %>

Node not running

<% } else if (node.os_pid == undefined) { %>

Node statistics not available

<% } else { %>

VM

OS pid <%= node.os_pid %>
Statistics <%= node.statistics_level %>
Run queue <%= node.run_queue %>
Processors <%= node.processors %>
<% } %>
rabbitmq-server-3.2.4/plugins-src/rabbitmq-management/priv/www/js/tmpl/memory.ejs0000644000000000000000000000504012305126066026713 0ustar rootroot<% var width = 800; if (memory == "not_available") { %>

Memory statistics not available.

<% } else { %>
<% var sections = {'connection_procs' : 'Connections', 'queue_procs' : 'Queues', 'plugins' : 'Plugins', 'other_proc' : 'Other process memory', 'mnesia' : 'Mnesia', 'msg_index' : 'Message store index', 'mgmt_db' : 'Management database', 'other_ets' : 'Other ETS tables', 'binary' : 'Binaries', 'code' : 'Code', 'atom' : 'Atoms', 'other_system' : 'Other system'}; for (var section in sections) { var section_width = Math.round(width * memory[section] / memory.total); %>
<% } %>
 
Connections <%= fmt_memory(memory, 'connection_procs') %>
Queues <%= fmt_memory(memory, 'queue_procs') %>
Plugins <%= fmt_memory(memory, 'plugins') %>
Other process memory <%= fmt_memory(memory, 'other_proc') %>
Mnesia <%= fmt_memory(memory, 'mnesia') %>
Message store index <%= fmt_memory(memory, 'msg_index') %>
Management database <%= fmt_memory(memory, 'mgmt_db') %>
Other ETS tables <%= fmt_memory(memory, 'other_ets') %>
Binaries <%= fmt_memory(memory, 'binary') %>
Code <%= fmt_memory(memory, 'code') %>
Atoms <%= fmt_memory(memory, 'atom') %>
Other system <%= fmt_memory(memory, 'other_system') %>
Last updated: <%= fmt_date(new Date()) %>.
Total memory used at last update: <%= fmt_bytes(memory.total) %>
<% } %> rabbitmq-server-3.2.4/plugins-src/rabbitmq-management/priv/www/js/tmpl/user.ejs0000644000000000000000000000526612305126066026373 0ustar rootroot

User: <%= fmt_string(user.name) %>

<% if (permissions.length == 0) { %>

This user does not have permission to access any virtual hosts.
Use "Set Permission" below to grant permission to access virtual hosts.

<% } %>

Overview

Tags <%= fmt_string(user.tags) %>
Can log in with password <%= fmt_boolean(user.password_hash.length > 0) %>
<%= format('permissions', {'mode': 'user', 'permissions': permissions, 'vhosts': vhosts, 'parent': user}) %>

Update this user

*
* (confirm)
[Admin] [Monitoring] [Policymaker] [Management] [None]

Delete this user

rabbitmq-server-3.2.4/plugins-src/rabbitmq-management/priv/www/js/tmpl/msg-detail-publishes.ejs0000644000000000000000000000300212305126066031421 0ustar rootroot

<%= label %>

<% if (object && object.length > 0) { %> <% var col_return_unroutable = !is_col_empty(object, 'return_unroutable', function(o) {return o.stats;}); var col_confirm = mode != 'exchange-outgoing'; %> <% if (mode == 'channel') { %> <% } else if (mode == 'exchange-incoming') { %> <% } else if (mode == 'exchange-outgoing') { %> <% } else { %> <% } %> <% if (col_confirm) { %> <% } %> <% if (col_return_unroutable) { %> <% } %> <% for (var i = 0; i < object.length; i++) { var pub = object[i]; %> > <% if (mode == 'channel') { %> <% } else if (mode == 'exchange-incoming') { %> <% } else if (mode == 'exchange-outgoing') { %> <% } else { %> <% } %> <% if (col_confirm) { %> <% } %> <% if (col_return_unroutable) { %> <% } %> <% } %>
ExchangeChannelQueueExchangepublishconfirmreturn (mandatory)
<%= link_exchange(pub.exchange.vhost, pub.exchange.name) %><%= link_channel(pub.channel_details.name) %><%= link_queue(pub.queue.vhost, pub.queue.name) %><%= link_exchange(pub.exchange.vhost, pub.exchange.name) %><%= fmt_rate(pub.stats, 'publish') %><%= fmt_rate(pub.stats, 'confirm') %><%= fmt_rate(pub.stats, 'return_unroutable') %>
<% } else { %>

... no publishes ...

<% } %> rabbitmq-server-3.2.4/plugins-src/rabbitmq-management/priv/www/js/tmpl/msg-detail-deliveries.ejs0000644000000000000000000000164412305126066031570 0ustar rootroot

Deliveries

<% if (object && object.length > 0) { %> <% var col_redeliver = !is_col_empty(object, 'redeliver', function(o) {return o.stats;}); %> <% if (mode == 'queue') { %> <% } else { %> <% } %> <% for (var i = 0; i < object.length; i++) { var del = object[i]; %> > <% if (mode == 'queue') { %> <% } else { %> <% } %> <% } %>
ChannelQueue deliver / get <% if (col_redeliver) { %> of which redelivered <% } %> ack
<%= link_channel(del.channel_details.name) %><%= link_queue(del.queue.vhost, del.queue.name) %><%= fmt_deliver_rate(del.stats, col_redeliver) %> <%= fmt_rate(del.stats, 'ack') %>
<% } else { %>

... no deliveries ...

<% } %> rabbitmq-server-3.2.4/plugins-src/rabbitmq-management/priv/www/js/tmpl/login.ejs0000644000000000000000000000105512305126066026515 0ustar rootroot

*
*

rabbitmq-server-3.2.4/plugins-src/rabbitmq-management/priv/www/js/tmpl/messages.ejs0000644000000000000000000000153412305126066027216 0ustar rootroot<% for (var i = 0; i < msgs.length; i++) { var msg = msgs[i]; %>

Message <%= i+1 %>

The server reported <%= msg.message_count %> messages remaining.

Exchange <%= fmt_exchange(msg.exchange) %>
Routing Key <%= fmt_string(msg.routing_key) %>
Redelivered <%= fmt_boolean(msg.redelivered) %>
Properties <%= fmt_table_short(msg.properties) %>
Payload <%= msg.payload_bytes %> bytes Encoding: <%= msg.payload_encoding %>
<%= fmt_maybe_wrap(msg.payload, msg.payload_encoding) %>
<% } %> rabbitmq-server-3.2.4/plugins-src/rabbitmq-management/priv/www/js/tmpl/channel.ejs0000644000000000000000000000443212305126066027017 0ustar rootroot

Channel: <%= fmt_escape_html(channel.name) %>

Overview

<% if (statistics_level == 'fine') { %> <%= message_rates('msg-rates-ch', channel.message_stats) %> <% } %>

Details

<% if (nodes_interesting) { %> <% } %> <% if (vhosts_interesting) { %> <% } %>
Connection <%= link_conn(channel.connection_details.name) %>
Node <%= fmt_node(channel.node) %>
Virtual host <%= fmt_string(channel.vhost) %>
Username <%= fmt_string(channel.user) %>
Mode <%= fmt_channel_mode(channel) %>
Prefetch count <%= channel.prefetch_count %>
Messages unacknowledged <%= channel.messages_unacknowledged %>
Messages unconfirmed <%= channel.messages_unconfirmed %>
Messages uncommitted <%= channel.messages_uncommitted %>
Acks uncommitted <%= channel.acks_uncommitted %>
Blocked by client <%= fmt_boolean(channel.client_flow_blocked) %>
Status <%= fmt_idle_long(channel) %>

Consumers

<%= format('consumers', {'mode': 'channel', 'consumers': channel.consumer_details}) %>
<% if (statistics_level == 'fine') { %>

Message rates breakdown

<%= format('msg-detail-publishes', {'mode': 'channel', 'object': channel.publishes, 'label': 'Publishes'}) %> <%= format('msg-detail-deliveries', {'mode': 'channel', 'object': channel.deliveries}) %>
<% } %> rabbitmq-server-3.2.4/plugins-src/rabbitmq-management/priv/www/js/tmpl/publish.ejs0000644000000000000000000000413212305126066027052 0ustar rootroot

Publish message

<% if (mode == 'queue') { %> <% } else { %> <% } %> <% if (mode == 'queue') { %> <% } else { %> <% } %>
Message will be published to the default exchange with routing key <%= fmt_string(queue.name) %>, routing it to this queue.
rabbitmq-server-3.2.4/plugins-src/rabbitmq-management/priv/www/js/tmpl/rate-options.ejs0000644000000000000000000000220512305126066030027 0ustar rootroot<% var id = span.attr('for'); var mode = get_pref('rate-mode-' + id); var size = get_pref('chart-size-' + id); var range = get_pref('chart-range-' + id); %>

This time series

<%= fmt_radio('mode', 'Chart', 'chart', mode) %> <%= fmt_radio('mode', 'Current value', 'curr', mode) %> <%= fmt_radio('mode', 'Moving average', 'avg', mode) %>
<%= fmt_radio('size', 'Small', 'small', size) %> <%= fmt_radio('size', 'Medium', 'medium', size) %> <%= fmt_radio('size', 'Large', 'large', size) %>
<% for (p in CHART_PERIODS) { %> <%= fmt_radio('range', CHART_PERIODS[p], p, range) %> <% } %>
rabbitmq-server-3.2.4/plugins-src/rabbitmq-management/priv/www/js/tmpl/vhosts.ejs0000644000000000000000000000473512305126066026743 0ustar rootroot

Virtual Hosts

All virtual hosts

<%= filter_ui(vhosts) %>
<% if (vhosts.length > 0) { %> <% if (statistics_level == 'fine') { %> <% } %> <% if (statistics_level == 'fine') { %> <% for (var i = 0; i < vhosts.length; i++) { var vhost = vhosts[i]; %> > <% if (statistics_level == 'fine') { %> <% } %> <% } %>
Overview Messages Data ratesMessage rates
<%= fmt_sort('Name', 'name') %> Users <%= fmt_sort('Ready', 'messages_ready') %> <%= fmt_sort('Unacked', 'messages_unacknowledged') %> <%= fmt_sort('Total', 'messages') %> <%= fmt_sort('From clients', 'recv_oct_details.rate') %> <%= fmt_sort('To clients', 'send_oct_details.rate') %><%= fmt_sort('publish', 'message_stats.publish_details.rate') %> <%= fmt_sort('deliver / get', 'message_stats.deliver_get_details.rate') %> <% } %>
<%= link_vhost(vhost.name) %> <%= fmt_permissions(vhost, permissions, 'vhost', 'user', '

No users

') %>
<%= fmt_string(vhost.messages_ready) %> <%= fmt_string(vhost.messages_unacknowledged) %> <%= fmt_string(vhost.messages) %> <%= fmt_rate_bytes(vhost, 'recv_oct') %> <%= fmt_rate_bytes(vhost, 'send_oct') %><%= fmt_rate(vhost.message_stats, 'publish') %> <%= fmt_deliver_rate(vhost.message_stats, false) %>
<% } else { %>

... no vhosts ...

<% } %>

Add a new virtual host

*
rabbitmq-server-3.2.4/plugins-src/rabbitmq-management/priv/www/js/tmpl/status.ejs0000644000000000000000000000007412305126066026730 0ustar rootroot

<%= text %>

rabbitmq-server-3.2.4/plugins-src/rabbitmq-management/priv/www/js/tmpl/connection.ejs0000644000000000000000000000571112305126066027547 0ustar rootroot

Connection <%= fmt_string(connection.name) %>

Overview

<%= data_rates('data-rates-conn', connection, 'Data rates') %>

Details

<% if (nodes_interesting) { %> <% } %> <% if (vhosts_interesting) { %> <% } %> <% if (connection.ssl) { %> <% } %> <% if (connection.auth_mechanism) { %> <% } %>
Node <%= fmt_node(connection.node) %>
Virtual host <%= fmt_string(connection.vhost) %>
Username <%= fmt_string(connection.user) %>
Protocol <%= connection.protocol %>
SSL <%= fmt_boolean(connection.ssl) %>
Authentication <%= connection.auth_mechanism %>
<% if (connection.state) { %>
State <%= fmt_connection_state(connection) %>
Timeout <%= fmt_time(connection.timeout, 's') %>
Frame max <%= connection.frame_max %> bytes
<% } %>

Channels

<%= format('channels-list', {'channels': channels, 'mode': 'connection'}) %>
<% if (connection.ssl) { %>

SSL

Protocol Version <%= connection.ssl_protocol %>
Key Exchange Algorithm <%= connection.ssl_key_exchange %>
Cipher Algorithm <%= connection.ssl_cipher %>
Hash Algorithm <%= connection.ssl_hash %>
<% if (connection.peer_cert_issuer != '') { %>
Peer Certificate Issuer <%= connection.peer_cert_issuer %>
Peer Certificate Subject <%= connection.peer_cert_subject %>
Peer Certificate Validity <%= connection.peer_cert_validity %>
<% } %>
<% } %> <% if (properties_size(connection.client_properties) > 0) { %>

Client properties

<%= fmt_table_long(connection.client_properties) %>
<% } %>

Close this connection

rabbitmq-server-3.2.4/plugins-src/rabbitmq-management/priv/www/js/tmpl/policies.ejs0000644000000000000000000000527312305126066027222 0ustar rootroot

Policies

All policies

<%= filter_ui(policies) %>
<% if (policies.length > 0) { %> <% if (vhosts_interesting) { %> <% } %> <% for (var i = 0; i < policies.length; i++) { var policy = policies[i]; %> > <% if (vhosts_interesting) { %> <% } %> <% } %>
Virtual HostName Pattern Apply to Definition Priority
<%= fmt_string(policy.vhost) %><%= link_policy(policy.vhost, policy.name) %> <%= fmt_string(policy.pattern) %> <%= fmt_string(policy['apply-to']) %> <%= fmt_table_short(policy.definition) %> <%= fmt_string(policy.priority) %>
<% } else { %>

... no policies ...

<% } %>

Add / update a policy

<% if (vhosts_interesting) { %> <% } else { %> <% } %>
*
*
*
rabbitmq-server-3.2.4/plugins-src/rabbitmq-management/priv/www/js/tmpl/import-succeeded.ejs0000644000000000000000000000012212305126066030633 0ustar rootroot

Import succeeded

Your definitions were imported successfully.

rabbitmq-server-3.2.4/plugins-src/rabbitmq-management/priv/www/js/tmpl/vhost.ejs0000644000000000000000000000223212305126066026546 0ustar rootroot

Virtual Host: <%= fmt_string(vhost.name) %>

<% if (permissions.length == 0) { %>

No users have permission to access this virtual host.
Use "Set Permission" below to grant users permission to access this virtual host.

<% } %>

Overview

<%= queue_lengths('lengths-vhost', vhost) %> <% if (statistics_level == 'fine') { %> <%= message_rates('msg-rates-vhost', vhost.message_stats) %> <% } %> <%= data_rates('data-rates-vhost', vhost, 'Data rates') %>

Details

Tracing enabled: <%= fmt_boolean(vhost.tracing) %>
<%= format('permissions', {'mode': 'vhost', 'permissions': permissions, 'users': users, 'parent': vhost}) %>

Delete this vhost

rabbitmq-server-3.2.4/plugins-src/rabbitmq-management/priv/www/js/tmpl/404.ejs0000644000000000000000000000015412305126066025713 0ustar rootroot

Not found

The object you clicked on was not found; it may have been deleted on the server.

rabbitmq-server-3.2.4/plugins-src/rabbitmq-management/priv/www/js/tmpl/overview.ejs0000644000000000000000000001762012305126066027260 0ustar rootroot

Overview

<% if (user_monitor) { %> <%= format('partition', {'nodes': nodes}) %> <% } %>

Totals

<% if (overview.statistics_db_node != 'not_running') { %> <%= queue_lengths('lengths-over', overview.queue_totals) %> <% if (statistics_level == 'fine') { %> <%= message_rates('msg-rates-over', overview.message_stats) %> <% } %> <% } else { %> Totals not available <% } %>
<% if (user_monitor) { %>

Nodes

<% for (var i = 0; i < nodes.length; i++) { var node = nodes[i]; %> > <% if (!node.running) { %> <% } else if (node.os_pid == undefined) { %> <% } else { %> <% } %> <% } %>
Name File descriptors Socket descriptors Erlang processes Memory Disk space Uptime Type
<%= link_node(node.name) %> <% if (rabbit_versions_interesting) { %> RabbitMQ <%= fmt_rabbit_version(node.applications) %> <% } %>
Node not running
Node statistics not available
<%= fmt_resource_bar_count(fmt_fd_used(node.fd_used, node.fd_total), node.fd_total, FD_THRESHOLDS) %> <%= fmt_resource_bar_count(node.sockets_used, node.sockets_total, FD_THRESHOLDS) %> <%= fmt_resource_bar_count(node.proc_used, node.proc_total, PROCESS_THRESHOLDS) %> <% if (node.mem_limit != 'memory_monitoring_disabled') { %> <%= fmt_resource_bar(fmt_bytes(node.mem_used), fmt_bytes(node.mem_limit) + ' high watermark', node.mem_used / node.mem_limit, node.mem_alarm ? 'red' : 'green', node.mem_alarm ? 'memory-alarm' : null) %> <% } else { %> <%= fmt_bytes(node.mem_used) %> <% } %> <% if (node.disk_free_limit != 'disk_free_monitoring_disabled') { %> <%= fmt_resource_bar(fmt_bytes(node.disk_free), fmt_bytes(node.disk_free_limit) + ' low watermark', node.disk_free_limit / node.disk_free, node.disk_free_alarm ? 'red' : 'green', node.disk_free_alarm ? 'disk-free-alarm' : null) %> <% } else { %> (not available) <% } %> <%= fmt_uptime(node.uptime) %> <% if (node.type == 'disc') { %> Disc <% } else { %> RAM <% } %> <% if (overview.statistics_db_node == node.name) { %> Stats <% } %> <% if (overview.node == node.name) { %> * <% } %>
<% if (overview.statistics_db_node == 'not_running') { %>

Statistics database could not be contacted. Message rates and queue lengths will not be shown.

<% } %>

Ports and contexts

Listening ports

<% if (nodes_interesting) { %> <% } %> <% for (var i = 0; i < overview.listeners.length; i++) { var listener = overview.listeners[i]; %> > <% if (nodes_interesting) { %> <% } %> <% } %>
ProtocolNodeBound to Port
<%= listener.protocol %><%= fmt_node(listener.node) %><%= listener.ip_address %> <%= listener.port %>

Web contexts

<% if (nodes_interesting) { %> <% } %> <% for (var i = 0; i < overview.contexts.length; i++) { var context = overview.contexts[i]; %> > <% if (nodes_interesting) { %> <% } %> <% } %>
ContextNodeBound to Port SSL Path
<%= context.description %><%= fmt_node(context.node) %><%= (context.ip != undefined) ? context.ip : "0.0.0.0" %> <%= context.port %> <%= fmt_boolean(context.ssl || false) %> <%= context.path %>

Import / export definitions

Export


Import


<% if (overview.statistics_level != 'fine') { %>

Message Rates Disabled

The statistics level in this RabbitMQ server is currently set to <%= overview.statistics_level %>. Message rates are therefore disabled.

To re-enable message rates, edit your configuration file and either set collect_statistics to fine in the rabbit application, or set force_fine_statistics to true in the rabbitmq_management_agent application

<% } %> <% } %> rabbitmq-server-3.2.4/plugins-src/rabbitmq-management/priv/www/js/tmpl/users.ejs0000644000000000000000000000545112305126066026552 0ustar rootroot

Users

All users

<%= filter_ui(users) %>
<% if (users.length > 0) { %> <% for (var i = 0; i < users.length; i++) { var user = users[i]; %> > <% } %>
<%= fmt_sort('Name', 'name') %> <%= fmt_sort('Tags', 'tags') %> Can access virtual hosts Has password
<%= link_user(user.name) %> <%= fmt_string(user.tags) %> <%= fmt_permissions(user, permissions, 'user', 'vhost', '

No access

') %>
<%= fmt_boolean(user.password_hash.length > 0) %>
<% } else { %>

... no vhosts ...

<% } %>

Add a user

*
*
* (confirm)
[Admin] [Monitoring] [Policymaker] [Management] [None]
rabbitmq-server-3.2.4/plugins-src/rabbitmq-management/priv/www/js/tmpl/bindings.ejs0000644000000000000000000000443012305126066027202 0ustar rootroot<%= maybe_truncate(bindings) %> <% if (bindings.length > 0) { %> <% if (mode == 'exchange_source') { %> <% } else { %> <% } %> <% for (var i = 0; i < bindings.length; i++) { var binding = bindings[i]; %> > <% if (binding.source == '') { %> <% } else { %> <% if (mode == 'queue' || mode == 'exchange_destination') { %> <% } else if (binding.destination_type == 'exchange') { %> <% } else { %> <% } %> <% } %> <% } %>
ToFromRouting key Arguments
(Default exchange binding) <%= link_exchange(binding.vhost, binding.source) %> <%= link_exchange(binding.vhost, binding.destination) %> <%= link_queue(binding.vhost, binding.destination) %> <%= fmt_string(binding.routing_key) %> <%= fmt_table_short(binding.arguments) %>
<% } else { %>

... no bindings ...

<% } %> rabbitmq-server-3.2.4/plugins-src/rabbitmq-management/priv/www/js/formatters.js0000644000000000000000000006154512305126066026464 0ustar rootrootUNKNOWN_REPR = '?'; FD_THRESHOLDS=[[0.95, 'red'], [0.8, 'yellow']]; SOCKETS_THRESHOLDS=[[1.0, 'red'], [0.8, 'yellow']]; PROCESS_THRESHOLDS=[[0.75, 'red'], [0.5, 'yellow']]; function fmt_string(str, unknown) { if (unknown == undefined) unknown = UNKNOWN_REPR; if (str == undefined) return unknown; return fmt_escape_html("" + str); } function fmt_bytes(bytes) { if (bytes == undefined) return UNKNOWN_REPR; return fmt_si_prefix(bytes, bytes, 1024, false) + 'B'; } function fmt_si_prefix(num0, max0, thousand, allow_fractions) { if (num == 0) return 0; function f(n, m, p) { if (m > thousand) return f(n / thousand, m / thousand, p + 1); else return [n, m, p]; } var num_power = f(num0, max0, 0); var num = num_power[0]; var max = num_power[1]; var power = num_power[2]; var powers = ['', 'k', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y']; return (((power != 0 || allow_fractions) && max <= 10) ? num.toFixed(1) : num.toFixed(0)) + powers[power]; } function fmt_memory(memory, key) { return '
' + fmt_bytes(memory[key]); } function fmt_boolean(b) { if (b == undefined) return UNKNOWN_REPR; return b ? "●" : "○"; } function fmt_date(d) { function f(i) { return i < 10 ? "0" + i : i; } return d.getFullYear() + "-" + f(d.getMonth() + 1) + "-" + f(d.getDate()) + " " + f(d.getHours()) + ":" + f(d.getMinutes()) + ":" + f(d.getSeconds()); } function fmt_time(t, suffix) { if (t == undefined || t == 0) return ''; return t + suffix; } function fmt_millis(millis) { return Math.round(millis / 1000) + "s"; } function fmt_parameters(obj) { return fmt_table_short(args_to_params(obj)); } function fmt_parameters_short(obj) { var res = ''; var params = args_to_params(obj); for (var k in ALL_ARGS) { if (params[k] != undefined) { res += '' + ALL_ARGS[k].short + ' '; } } if (params.arguments) { res += 'Args'; } return res; } function short_conn(name) { var pat = /^(.*)->/; var match = pat.exec(name); return (match != null && match.length == 2) ? match[1] : name; } function short_chan(name) { var pat = /^(.*)->.*( \(.*\))/; var match = pat.exec(name); return (match != null && match.length == 3) ? match[1] + match[2] : name; } function args_to_params(obj) { var res = {}; for (var k in obj.arguments) { if (k in KNOWN_ARGS) { res[k] = obj.arguments[k]; } else { if (res.arguments == undefined) res.arguments = {}; res.arguments[k] = obj.arguments[k]; } } if (obj.durable) { res['durable'] = true; } if (obj.auto_delete) { res['auto-delete'] = true; } if (obj.internal != undefined && obj.internal) { res['internal'] = true; } return res; } function fmt_mirrors(queue) { var synced = queue.synchronised_slave_nodes || []; var unsynced = queue.slave_nodes || []; unsynced = jQuery.grep(unsynced, function (node, i) { return jQuery.inArray(node, synced) == -1 }); var res = ''; if (synced.length > 0) { res += ' +' + synced.length + ''; } if (synced.length == 0 && unsynced.length > 0) { res += ' +0'; } if (unsynced.length > 0) { res += ' +' + unsynced.length + ''; } return res; } function fmt_sync_status(queue) { var res = '

Syncing: '; res += (queue.messages == 0) ? 100 : Math.round(100 * queue.sync_messages / queue.messages); res += '%

'; return res; } function fmt_channel_mode(ch) { if (ch.transactional) { return 'T'; } else if (ch.confirm) { return 'C'; } else { return ''; } } function fmt_color(r, thresholds) { if (r == undefined) return ''; for (var i in thresholds) { var threshold = thresholds[i][0]; var color = thresholds[i][1]; if (r >= threshold) { return color; } } return 'green'; } function fmt_deliver_rate(obj, show_redeliver) { var res = fmt_rate(obj, 'deliver_get'); if (show_redeliver) { res += '' + fmt_rate(obj, 'redeliver') + ''; } return res; } function fmt_rate_num(num) { if (num == undefined) return UNKNOWN_REPR; else if (num < 1) return num.toFixed(2); else if (num < 10) return num.toFixed(1); else return fmt_num_thousands(num.toFixed(0)); } function fmt_num_thousands(num) { if (num == undefined) return UNKNOWN_REPR; num = '' + num; if (num.length < 4) return num; return fmt_num_thousands(num.slice(0, -3)) + ',' + num.slice(-3); } function fmt_rate(obj, name, mode) { var raw = fmt_rate0(obj, name, mode, fmt_rate_num); return raw == '' ? '' : (raw + '/s'); } function fmt_rate_bytes(obj, name, mode) { var raw = fmt_rate0(obj, name, mode, fmt_bytes); return raw == '' ? '' : (raw + '/s' + '(' + fmt_bytes(obj[name]) + ' total)'); } function fmt_rate_large(obj, name, mode) { return '' + fmt_rate0(obj, name, mode, fmt_rate_num) + 'msg/s'; } function fmt_rate_bytes_large(obj, name, mode) { return '' + fmt_rate0(obj, name, mode, fmt_bytes) + '/s' + '(' + fmt_bytes(obj[name]) + ' total)'; } function fmt_rate0(obj, name, mode, fmt) { if (obj == undefined || obj[name] == undefined || obj[name + '_details'] == undefined) return ''; var details = obj[name + '_details']; return fmt(mode == 'avg' ? details.avg_rate : details.rate); } function fmt_msgs(obj, name, mode) { return fmt_msgs0(obj, name, mode) + ' msg'; } function fmt_msgs_large(obj, name, mode) { return '' + fmt_msgs0(obj, name, mode) + '' + fmt_rate0(obj, name, mode, fmt_msgs_rate); } function fmt_msgs0(obj, name, mode) { if (obj == undefined || obj[name] == undefined || obj[name + '_details'] == undefined) return ''; var details = obj[name + '_details']; return mode == 'avg' ? fmt_rate_num(details.avg) : fmt_num_thousands(obj[name]); } function fmt_msgs_rate(num) { if (num > 0) return '+' + fmt_rate_num(num) + ' msg/s'; else if (num < 0) return '-' + fmt_rate_num(-num) + ' msg/s'; else return ' '; } function fmt_rate_axis(num, max) { return fmt_si_prefix(num, max, 1000, true) + '/s'; } function fmt_msgs_axis(num, max) { return fmt_si_prefix(num, max, 1000, true); } function fmt_rate_bytes_axis(num, max) { num = parseInt(num); return fmt_bytes(isNaN(num) ? 0 : num) + '/s'; } function is_stat_empty(obj, name) { if (obj == undefined || obj[name] == undefined || obj[name + '_details'] == undefined || obj[name + '_details'].rate < 0.00001) return true; return false; } function is_col_empty(objects, name, accessor) { if (accessor == undefined) accessor = function(o) {return o.message_stats;}; for (var i = 0; i < objects.length; i++) { var object = objects[i]; if (!is_stat_empty(accessor(object), name)) { return false; } } return true; } function fmt_exchange(name) { return fmt_escape_html(fmt_exchange0(name)); } function fmt_exchange0(name) { return name == '' ? '(AMQP default)' : name; } function fmt_exchange_type(type) { for (var i in exchange_types) { if (exchange_types[i].name == type) { return fmt_escape_html(type); } } return '
' + fmt_escape_html(type) + '
'; } function fmt_exchange_url(name) { return name == '' ? 'amq.default' : fmt_escape_html(name); } function fmt_download_filename(host) { var now = new Date(); return host.replace('@', '_') + "_" + now.getFullYear() + "-" + (now.getMonth() + 1) + "-" + now.getDate() + ".json"; } function fmt_fd_used(used, total) { if (used == 'install_handle_from_sysinternals') { return '

handle.exe missing ' + total + ' available

'; } else { return used; } } function fmt_table_short(table) { return '' + fmt_table_body(table, ':') + '
'; } function fmt_table_long(table) { return '' + fmt_table_body(table, '') + '
'; } function fmt_table_body(table, x) { var res = ''; for (k in table) { res += '' + k + x + '' + fmt_amqp_value(table[k]) + ''; } return res; } function fmt_amqp_value(val) { if (val instanceof Array) { var val2 = new Array(); for (var i = 0; i < val.length; i++) { val2[i] = fmt_amqp_value(val[i]); } return val2.join("
"); } else if (val instanceof Object) { return fmt_table_short(val); } else { var t = typeof(val); if (t == 'string') { return '' + fmt_escape_html(val) + ''; } else { return '' + val + ''; } } } function fmt_table_flat(table) { var res = []; for (k in table) { res.push(k + ': ' + fmt_amqp_value_flat(table[k])); } return res.join(', '); } function fmt_amqp_value_flat(val) { if (val instanceof Array) { var val2 = new Array(); for (var i = 0; i < val.length; i++) { val2[i] = fmt_amqp_value_flat(val[i]); } return '[' + val2.join(",") + ']'; } else if (val instanceof Object) { return '(' + fmt_table_flat(val) + ')'; } else if (typeof(val) == 'string') { return fmt_escape_html(val); } else { return val; } } function fmt_uptime(u) { var uptime = Math.floor(u / 1000); var sec = uptime % 60; var min = Math.floor(uptime / 60) % 60; var hour = Math.floor(uptime / 3600) % 24; var day = Math.floor(uptime / 86400); if (day > 0) return day + 'd ' + hour + 'h'; else if (hour > 0) return hour + 'h ' + min + 'm'; else return min + 'm ' + sec + 's'; } function fmt_rabbit_version(applications) { for (var i in applications) { if (applications[i].name == 'rabbit') { return applications[i].version; } } return 'unknown'; } function fmt_idle(obj) { if (obj.idle_since == undefined) { return 'Active'; } else { return 'Idle'; } } function fmt_idle_long(obj) { if (obj.idle_since == undefined) { return 'Active'; } else { return 'Idle since
' + obj.idle_since; } } function fmt_escape_html(txt) { return fmt_escape_html0(txt).replace(/\n/g, '
'); } function fmt_escape_html_one_line(txt) { return fmt_escape_html0(txt).replace(/\n/g, ''); } function fmt_escape_html0(txt) { return txt.replace(/&/g, '&') .replace(//g, '>') .replace(/\"/g, '"'); } function fmt_maybe_wrap(txt, encoding) { if (encoding == 'string') return fmt_escape_html(txt); var WRAP = 120; var res = ''; while (txt != '') { var i = txt.indexOf('\n'); if (i == -1 || i > WRAP) { i = Math.min(WRAP, txt.length); res += txt.substring(0, i) + '\n'; txt = txt.substring(i); } else { res += txt.substring(0, i + 1); txt = txt.substring(i + 1); } } return fmt_escape_html(res); } function fmt_node(node_host) { var both = node_host.split('@'); var node = both.slice(0, 1); var host = both.slice(1); return '' + node + '@' + host; } function fmt_connection_state(conn) { if (conn.state == undefined) return ''; var colour = 'green'; var text = conn.state; var explanation; if (conn.last_blocked_by == 'resource' && conn.state == 'blocked') { colour = 'red'; explanation = 'Resource alarm: Connection blocked.'; } else if (conn.state == 'blocking') { colour = 'yellow'; explanation = 'Resource alarm: Connection will block on publish.'; } else if (conn.last_blocked_by == 'flow') { var age = conn.last_blocked_age.toFixed(); if (age < 5) { colour = 'yellow'; text = 'flow'; explanation = 'Publishing rate recently restricted by server.'; } } if (explanation) { return '
' + text + '
'; } else { return '
' + text + '
'; } } function fmt_resource_bar(used_label, limit_label, ratio, colour, help) { var width = 120; var res = ''; var other_colour = colour; if (ratio > 1) { ratio = 1 / ratio; inverted = true; colour += '-dark'; } else { other_colour += '-dark'; } var offset = Math.round(width * (1 - ratio)); res += '
'; res += '
'; res += used_label; if (help != null) { res += ' '; } res += '
'; // status-bar-main if (limit_label != null) { res += '' + limit_label + ''; } res += '
'; // status-bar return res; } function fmt_resource_bar_count(used, total, thresholds) { if (typeof used == 'number') { return fmt_resource_bar(used, total + ' available', used / total, fmt_color(used / total, thresholds)); } else { return used; } } function fmt_shortened_uri(uri) { if (typeof uri == 'object') { var res = ''; for (i in uri) { res += fmt_shortened_uri(uri[i]) + '
'; } return res; } var uri = fmt_escape_html(uri); if (uri.indexOf('?') == -1) { return uri; } else { return '' + uri.substr(0, uri.indexOf('?')) + '?...'; } } function fmt_client_name(properties) { var res = []; if (properties.product != undefined) { res.push(fmt_trunc(properties.product, 10)); } if (properties.platform != undefined) { res.push(fmt_trunc(properties.platform, 10)); } res = res.join(" / "); if (properties.version != undefined) { res += '' + fmt_trunc(properties.version) + ''; } return res; } function fmt_trunc(str, max_length) { return str.length > max_length ? ('' + str.substring(0, max_length) + '...') : str; } function alt_rows(i, args) { var css = [(i % 2 == 0) ? 'alt1' : 'alt2']; if (args != undefined && args['x-internal-purpose'] != undefined) { css.push('internal-purpose'); } return ' class="' + css.join(' ') + '"'; } function esc(str) { return encodeURIComponent(str); } function link_conn(name, desc) { if (desc == undefined) { return _link_to(short_conn(name), '#/connections/' + esc(name)); } else { return _link_to(desc, '#/connections/' + esc(name), false); } } function link_channel(name) { return _link_to(short_chan(name), '#/channels/' + esc(name)) } function link_exchange(vhost, name, args) { var url = esc(vhost) + '/' + (name == '' ? 'amq.default' : esc(name)); return _link_to(fmt_exchange0(name), '#/exchanges/' + url, true, args); } function link_queue(vhost, name, args) { return _link_to(name, '#/queues/' + esc(vhost) + '/' + esc(name), true, args); } function link_vhost(name) { return _link_to(name, '#/vhosts/' + esc(name)) } function link_user(name) { return _link_to(name, '#/users/' + esc(name)) } function link_node(name) { return _link_to(name, '#/nodes/' + esc(name)) } function link_policy(vhost, name) { return _link_to(name, '#/policies/' + esc(vhost) + '/' + esc(name)) } function _link_to(name, url, highlight, args) { if (highlight == undefined) highlight = true; var title = null; if (args != undefined && args['x-internal-purpose'] != undefined) { var purpose = args['x-internal-purpose']; title = 'This is used internally by the ' + purpose + ' mechanism.'; } return '' + (highlight ? fmt_highlight_filter(name) : fmt_escape_html(name)) + ''; } function fmt_highlight_filter(text) { if (current_filter == '') return fmt_escape_html(text); var ix = text.toLowerCase().indexOf(current_filter.toLowerCase()); var l = current_filter.length; if (ix == -1) { return fmt_escape_html(text); } else { return fmt_escape_html(text.substring(0, ix)) + '' + fmt_escape_html(text.substring(ix, ix + l)) + '' + fmt_escape_html(text.substring(ix + l)); } } function message_rates(id, stats) { var items = [['Publish', 'publish'], ['Confirm', 'confirm'], ['Publish (In)', 'publish_in'], ['Publish (Out)', 'publish_out'], ['Deliver', 'deliver'], ['Redelivered', 'redeliver'], ['Acknowledge', 'ack'], ['Get', 'get'], ['Deliver (noack)', 'deliver_no_ack'], ['Get (noack)', 'get_no_ack'], ['Return', 'return_unroutable']]; return rates_chart_or_text(id, stats, items, fmt_rate, fmt_rate_large, fmt_rate_axis, true, 'Message rates', 'message-rates'); } function queue_lengths(id, stats) { var items = [['Ready', 'messages_ready'], ['Unacknowledged', 'messages_unacknowledged'], ['Total', 'messages']]; return rates_chart_or_text(id, stats, items, fmt_msgs, fmt_msgs_large, fmt_msgs_axis, false, 'Queued messages', 'queued-messages'); } function data_rates(id, stats) { var items = [['From client', 'recv_oct'], ['To client', 'send_oct']]; return rates_chart_or_text(id, stats, items, fmt_rate_bytes, fmt_rate_bytes_large, fmt_rate_bytes_axis, true, 'Data rates'); } function rates_chart_or_text(id, stats, items, chart_fmt, text_fmt, axis_fmt, chart_rates, heading, heading_help) { var mode = get_pref('rate-mode-' + id); var range = get_pref('chart-range-' + id); var prefix = '

' + heading + ' (' + prefix_title(mode, range) + ')' + (heading_help == undefined ? '' : ' ') + '

'; var res; if (keys(stats).length > 0) { if (mode == 'chart') { res = rates_chart(id, items, stats, chart_fmt, axis_fmt, chart_rates); } else { res = rates_text(items, stats, mode, text_fmt); } if (res == "") res = '

Waiting for data...

'; } else { res = '

Currently idle

'; } return prefix + '
' + res + '
'; } function prefix_title(mode, range) { var desc = CHART_PERIODS[range]; if (mode == 'chart') { return 'chart: ' + desc.toLowerCase(); } else if (mode == 'curr') { return 'current value'; } else { return 'moving average: ' + desc.toLowerCase(); } } function rates_chart(id, items, stats, rate_fmt, axis_fmt, chart_rates) { var size = get_pref('chart-size-' + id); var show = []; chart_data[id] = {}; chart_data[id]['data'] = {}; chart_data[id]['fmt'] = axis_fmt; for (var i in items) { var name = items[i][0]; var key = items[i][1]; var key_details = key + '_details'; if (key_details in stats) { chart_data[id]['data'][name] = stats[key_details]; show.push([name, rate_fmt(stats, key)]); } } var html = '
'; html += ''; for (var i = 0; i < show.length; i++) { html += '' } html += '
' + show[i][0] + ''; html += '
' + show[i][1] + '
'; return show.length > 0 ? html : ''; } function rates_text(items, stats, mode, rate_fmt) { var res = ''; for (var i in items) { var name = items[i][0]; var key = items[i][1]; var key_details = key + '_details'; if (key_details in stats) { var details = stats[key_details]; res += '
' + name; res += rate_fmt(stats, key, mode); res += '
'; } } return res == '' ? '' : '
' + res + '
'; } function filter_ui(items) { current_truncate = (current_truncate == null) ? parseInt(get_pref('truncate')) : current_truncate; var total = items.length; if (current_filter != '') { var items2 = []; for (var i in items) { var item = items[i]; if (item.name.toLowerCase().indexOf(current_filter.toLowerCase()) != -1) { items2.push(item); } } items.length = items2.length; for (var i in items2) items[i] = items2[i]; } var res = '
Filter:' + ''; function items_desc(l) { return l == 1 ? (l + ' item') : (l + ' items'); } var selected = current_filter == '' ? (items_desc(items.length)) : (items.length + ' of ' + items_desc(total) + ' selected'); var truncate_input = ''; if (items.length > current_truncate) { selected += ' ' + '(only showing first '; items.length = current_truncate; } else { selected += ' (show at most '; } res += '

' + selected + '' + truncate_input + ')

'; res += '
'; return res; } function maybe_truncate(items) { var maximum = 500; var str = ''; if (items.length > maximum) { str = '

Only ' + maximum + ' of ' + items.length + ' items are shown.

'; items.length = maximum; } return str; } function fmt_sort(display, sort) { var prefix = ''; if (current_sort == sort) { prefix = '' + (current_sort_reverse ? '▲ ' : '▼ ') + ''; } return '' + prefix + display + ''; } function fmt_permissions(obj, permissions, lookup, show, warning) { var res = []; for (var i in permissions) { var permission = permissions[i]; if (permission[lookup] == obj.name) { res.push(permission[show]); } } return res.length == 0 ? warning : res.join(', '); } var radio_id = 0; function fmt_radio(name, text, value, current) { radio_id++; return ''; } function properties_size(obj) { var count = 0; for (k in obj) { if (obj.hasOwnProperty(k)) count++; } return count; } rabbitmq-server-3.2.4/plugins-src/rabbitmq-management/priv/www/js/jquery.flot.min.js0000644000000000000000000010745112305126066027337 0ustar rootroot/* Javascript plotting library for jQuery, version 0.8.1. Copyright (c) 2007-2013 IOLA and Ole Laursen. Licensed under the MIT license. */// first an inline dependency, jquery.colorhelpers.js, we inline it here // for convenience /* Plugin for jQuery for working with colors. * * Version 1.1. * * Inspiration from jQuery color animation plugin by John Resig. * * Released under the MIT license by Ole Laursen, October 2009. * * Examples: * * $.color.parse("#fff").scale('rgb', 0.25).add('a', -0.5).toString() * var c = $.color.extract($("#mydiv"), 'background-color'); * console.log(c.r, c.g, c.b, c.a); * $.color.make(100, 50, 25, 0.4).toString() // returns "rgba(100,50,25,0.4)" * * Note that .scale() and .add() return the same modified object * instead of making a new one. * * V. 1.1: Fix error handling so e.g. parsing an empty string does * produce a color rather than just crashing. */(function(e){e.color={},e.color.make=function(t,n,r,i){var s={};return s.r=t||0,s.g=n||0,s.b=r||0,s.a=i!=null?i:1,s.add=function(e,t){for(var n=0;n=1?"rgb("+[s.r,s.g,s.b].join(",")+")":"rgba("+[s.r,s.g,s.b,s.a].join(",")+")"},s.normalize=function(){function e(e,t,n){return tn?n:t}return s.r=e(0,parseInt(s.r),255),s.g=e(0,parseInt(s.g),255),s.b=e(0,parseInt(s.b),255),s.a=e(0,s.a,1),s},s.clone=function(){return e.color.make(s.r,s.b,s.g,s.a)},s.normalize()},e.color.extract=function(t,n){var r;do{r=t.css(n).toLowerCase();if(r!=""&&r!="transparent")break;t=t.parent()}while(!e.nodeName(t.get(0),"body"));return r=="rgba(0, 0, 0, 0)"&&(r="transparent"),e.color.parse(r)},e.color.parse=function(n){var r,i=e.color.make;if(r=/rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/.exec(n))return i(parseInt(r[1],10),parseInt(r[2],10),parseInt(r[3],10));if(r=/rgba\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]+(?:\.[0-9]+)?)\s*\)/.exec(n))return i(parseInt(r[1],10),parseInt(r[2],10),parseInt(r[3],10),parseFloat(r[4]));if(r=/rgb\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*\)/.exec(n))return i(parseFloat(r[1])*2.55,parseFloat(r[2])*2.55,parseFloat(r[3])*2.55);if(r=/rgba\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\s*\)/.exec(n))return i(parseFloat(r[1])*2.55,parseFloat(r[2])*2.55,parseFloat(r[3])*2.55,parseFloat(r[4]));if(r=/#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(n))return i(parseInt(r[1],16),parseInt(r[2],16),parseInt(r[3],16));if(r=/#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/.exec(n))return i(parseInt(r[1]+r[1],16),parseInt(r[2]+r[2],16),parseInt(r[3]+r[3],16));var s=e.trim(n).toLowerCase();return s=="transparent"?i(255,255,255,0):(r=t[s]||[0,0,0],i(r[0],r[1],r[2]))};var t={aqua:[0,255,255],azure:[240,255,255],beige:[245,245,220],black:[0,0,0],blue:[0,0,255],brown:[165,42,42],cyan:[0,255,255],darkblue:[0,0,139],darkcyan:[0,139,139],darkgrey:[169,169,169],darkgreen:[0,100,0],darkkhaki:[189,183,107],darkmagenta:[139,0,139],darkolivegreen:[85,107,47],darkorange:[255,140,0],darkorchid:[153,50,204],darkred:[139,0,0],darksalmon:[233,150,122],darkviolet:[148,0,211],fuchsia:[255,0,255],gold:[255,215,0],green:[0,128,0],indigo:[75,0,130],khaki:[240,230,140],lightblue:[173,216,230],lightcyan:[224,255,255],lightgreen:[144,238,144],lightgrey:[211,211,211],lightpink:[255,182,193],lightyellow:[255,255,224],lime:[0,255,0],magenta:[255,0,255],maroon:[128,0,0],navy:[0,0,128],olive:[128,128,0],orange:[255,165,0],pink:[255,192,203],purple:[128,0,128],violet:[128,0,128],red:[255,0,0],silver:[192,192,192],white:[255,255,255],yellow:[255,255,0]}})(jQuery),function(e){function n(t,n){var r=n.children("."+t)[0];if(r==null){r=document.createElement("canvas"),r.className=t,e(r).css({direction:"ltr",position:"absolute",left:0,top:0}).appendTo(n);if(!r.getContext){if(!window.G_vmlCanvasManager)throw new Error("Canvas is not available. If you're using IE with a fall-back such as Excanvas, then there's either a mistake in your conditional include, or the page has no DOCTYPE and is rendering in Quirks Mode.");r=window.G_vmlCanvasManager.initElement(r)}}this.element=r;var i=this.context=r.getContext("2d"),s=window.devicePixelRatio||1,o=i.webkitBackingStorePixelRatio||i.mozBackingStorePixelRatio||i.msBackingStorePixelRatio||i.oBackingStorePixelRatio||i.backingStorePixelRatio||1;this.pixelRatio=s/o,this.resize(n.width(),n.height()),this.textContainer=null,this.text={},this._textCache={}}function r(t,r,s,o){function E(e,t){t=[w].concat(t);for(var n=0;nn&&(n=i))}t<=n&&(t=n+1);var s,o=[],f=a.colors,l=f.length,c=0;for(r=0;r=0?c<.5?c=-c-.2:c=0:c=-c),o[r]=s.scale("rgb",1+c);var h=0,p;for(r=0;re.datamax&&n!=r&&(e.datamax=n)}var t=Number.POSITIVE_INFINITY,n=Number.NEGATIVE_INFINITY,r=Number.MAX_VALUE,i,s,o,a,f,l,c,h,p,d,v,m,g,y,w,S;e.each(k(),function(e,r){r.datamin=t,r.datamax=n,r.used=!1});for(i=0;i0&&c[o-h]!=null&&c[o-h]!=c[o]&&c[o-h+1]!=c[o+1]){for(a=0;aO&&(O=m)),g.y&&(mM&&(M=m))}}if(l.bars.show){var _;switch(l.bars.align){case"left":_=0;break;case"right":_=-l.bars.barWidth;break;case"center":_=-l.bars.barWidth/2;break;default:throw new Error("Invalid bar alignment: "+l.bars.align)}l.bars.horizontal?(A+=_,M+=_+l.bars.barWidth):(L+=_,O+=_+l.bars.barWidth)}x(l.xaxis,L,O),x(l.yaxis,A,M)}e.each(k(),function(e,r){r.datamin==t&&(r.datamin=null),r.datamax==n&&(r.datamax=null)})}function D(){t.css("padding",0).children(":not(.flot-base,.flot-overlay)").remove(),t.css("position")=="static"&&t.css("position","relative"),f=new n("flot-base",t),l=new n("flot-overlay",t),h=f.context,p=l.context,c=e(l.element).unbind();var r=t.data("plot");r&&(r.shutdown(),l.clear()),t.data("plot",w)}function P(){a.grid.hoverable&&(c.mousemove(at),c.bind("mouseleave",ft)),a.grid.clickable&&c.click(lt),E(b.bindEvents,[c])}function H(){ot&&clearTimeout(ot),c.unbind("mousemove",at),c.unbind("mouseleave",ft),c.unbind("click",lt),E(b.shutdown,[c])}function B(e){function t(e){return e}var n,r,i=e.options.transform||t,s=e.options.inverseTransform;e.direction=="x"?(n=e.scale=g/Math.abs(i(e.max)-i(e.min)),r=Math.min(i(e.max),i(e.min))):(n=e.scale=y/Math.abs(i(e.max)-i(e.min)),n=-n,r=Math.max(i(e.max),i(e.min))),i==t?e.p2c=function(e){return(e-r)*n}:e.p2c=function(e){return(i(e)-r)*n},s?e.c2p=function(e){return s(r+e/n)}:e.c2p=function(e){return r+e/n}}function j(e){var t=e.options,n=e.ticks||[],r=t.labelWidth||0,i=t.labelHeight||0,s=r||e.direction=="x"?Math.floor(f.width/(n.length||1)):null;legacyStyles=e.direction+"Axis "+e.direction+e.n+"Axis",layer="flot-"+e.direction+"-axis flot-"+e.direction+e.n+"-axis "+legacyStyles,font=t.font||"flot-tick-label tickLabel";for(var o=0;o=0;--t)F(o[t]);q(),e.each(o,function(e,t){I(t)})}g=f.width-m.left-m.right,y=f.height-m.bottom-m.top,e.each(n,function(e,t){B(t)}),r&&G(),it()}function U(e){var t=e.options,n=+(t.min!=null?t.min:e.datamin),r=+(t.max!=null?t.max:e.datamax),i=r-n;if(i==0){var s=r==0?1:.01;t.min==null&&(n-=s);if(t.max==null||t.min!=null)r+=s}else{var o=t.autoscaleMargin;o!=null&&(t.min==null&&(n-=i*o,n<0&&e.datamin!=null&&e.datamin>=0&&(n=0)),t.max==null&&(r+=i*o,r>0&&e.datamax!=null&&e.datamax<=0&&(r=0)))}e.min=n,e.max=r}function z(t){var n=t.options,r;typeof n.ticks=="number"&&n.ticks>0?r=n.ticks:r=.3*Math.sqrt(t.direction=="x"?f.width:f.height);var s=(t.max-t.min)/r,o=-Math.floor(Math.log(s)/Math.LN10),u=n.tickDecimals;u!=null&&o>u&&(o=u);var a=Math.pow(10,-o),l=s/a,c;l<1.5?c=1:l<3?(c=2,l>2.25&&(u==null||o+1<=u)&&(c=2.5,++o)):l<7.5?c=5:c=10,c*=a,n.minTickSize!=null&&c0&&(n.min==null&&(t.min=Math.min(t.min,p[0])),n.max==null&&p.length>1&&(t.max=Math.max(t.max,p[p.length-1]))),t.tickGenerator=function(e){var t=[],n,r;for(r=0;r1&&/\..*0$/.test((g[1]-g[0]).toFixed(m))||(t.tickDecimals=m)}}}}function W(t){var n=t.options.ticks,r=[];n==null||typeof n=="number"&&n>0?r=t.tickGenerator(t):n&&(e.isFunction(n)?r=n(t):r=n);var i,s;t.ticks=[];for(i=0;i1&&(o=u[1])):s=+u,o==null&&(o=t.tickFormatter(s,t)),isNaN(s)||t.ticks.push({v:s,label:o})}}function X(e,t){e.options.autoscaleMargin&&t.length>0&&(e.options.min==null&&(e.min=Math.min(e.min,t[0].v)),e.options.max==null&&t.length>1&&(e.max=Math.max(e.max,t[t.length-1].v)))}function V(){f.clear(),E(b.drawBackground,[h]);var e=a.grid;e.show&&e.backgroundColor&&K(),e.show&&!e.aboveData&&Q();for(var t=0;ti){var a=r;r=i,i=a}return{from:r,to:i,axis:n}}function K(){h.save(),h.translate(m.left,m.top),h.fillStyle=bt(a.grid.backgroundColor,y,0,"rgba(255, 255, 255, 0)"),h.fillRect(0,0,g,y),h.restore()}function Q(){var t,n,r,i;h.save(),h.translate(m.left,m.top);var s=a.grid.markings;if(s){e.isFunction(s)&&(n=w.getAxes(),n.xmin=n.xaxis.min,n.xmax=n.xaxis.max,n.ymin=n.yaxis.min,n.ymax=n.yaxis.max,s=s(n));for(t=0;tu.axis.max||f.tof.axis.max)continue;u.from=Math.max(u.from,u.axis.min),u.to=Math.min(u.to,u.axis.max),f.from=Math.max(f.from,f.axis.min),f.to=Math.min(f.to,f.axis.max);if(u.from==u.to&&f.from==f.to)continue;u.from=u.axis.p2c(u.from),u.to=u.axis.p2c(u.to),f.from=f.axis.p2c(f.from),f.to=f.axis.p2c(f.to),u.from==u.to||f.from==f.to?(h.beginPath(),h.strokeStyle=o.color||a.grid.markingsColor,h.lineWidth=o.lineWidth||a.grid.markingsLineWidth,h.moveTo(u.from,f.from),h.lineTo(u.to,f.to),h.stroke()):(h.fillStyle=o.color||a.grid.markingsColor,h.fillRect(u.from,f.to,u.to-u.from,f.from-f.to))}}n=k(),r=a.grid.borderWidth;for(var l=0;lc.max||d=="full"&&(typeof r=="object"&&r[c.position]>0||r>0)&&(x==c.min||x==c.max))continue;c.direction=="x"?(v=c.p2c(x),S=d=="full"?-y:d,c.position=="top"&&(S=-S)):(b=c.p2c(x),E=d=="full"?-g:d,c.position=="left"&&(E=-E)),h.lineWidth==1&&(c.direction=="x"?v=Math.floor(v)+.5:b=Math.floor(b)+.5),h.moveTo(v,b),h.lineTo(v+E,b+S)}h.stroke()}r&&(i=a.grid.borderColor,typeof r=="object"||typeof i=="object"?(typeof r!="object"&&(r={top:r,right:r,bottom:r,left:r}),typeof i!="object"&&(i={top:i,right:i,bottom:i,left:i}),r.top>0&&(h.strokeStyle=i.top,h.lineWidth=r.top,h.beginPath(),h.moveTo(0-r.left,0-r.top/2),h.lineTo(g,0-r.top/2),h.stroke()),r.right>0&&(h.strokeStyle=i.right,h.lineWidth=r.right,h.beginPath(),h.moveTo(g+r.right/2,0-r.top),h.lineTo(g+r.right/2,y),h.stroke()),r.bottom>0&&(h.strokeStyle=i.bottom,h.lineWidth=r.bottom,h.beginPath(),h.moveTo(g+r.right,y+r.bottom/2),h.lineTo(0,y+r.bottom/2),h.stroke()),r.left>0&&(h.strokeStyle=i.left,h.lineWidth=r.left,h.beginPath(),h.moveTo(0-r.left/2,y+r.bottom),h.lineTo(0-r.left/2,0),h.stroke())):(h.lineWidth=r,h.strokeStyle=a.grid.borderColor,h.strokeRect(-r/2,-r/2,g+r,y+r))),h.restore()}function G(){e.each(k(),function(e,t){if(!t.show||t.ticks.length==0)return;var n=t.box,r=t.direction+"Axis "+t.direction+t.n+"Axis",i="flot-"+t.direction+"-axis flot-"+t.direction+t.n+"-axis "+r,s=t.options.font||"flot-tick-label tickLabel",o,u,a,l,c;f.removeText(i);for(var h=0;ht.max)continue;t.direction=="x"?(l="center",u=m.left+t.p2c(o.v),t.position=="bottom"?a=n.top+n.padding:(a=n.top+n.height-n.padding,c="bottom")):(c="middle",a=m.top+t.p2c(o.v),t.position=="left"?(u=n.left+n.width-n.padding,l="right"):u=n.left+n.padding),f.addText(i,u,a,o.label,s,null,null,l,c)}})}function Y(e){e.lines.show&&Z(e),e.bars.show&&nt(e),e.points.show&&et(e)}function Z(e){function t(e,t,n,r,i){var s=e.points,o=e.pointsize,u=null,a=null;h.beginPath();for(var f=o;f=d&&c>i.max){if(d>i.max)continue;l=(i.max-c)/(d-c)*(p-l)+l,c=i.max}else if(d>=c&&d>i.max){if(c>i.max)continue;p=(i.max-c)/(d-c)*(p-l)+l,d=i.max}if(l<=p&&l=p&&l>r.max){if(p>r.max)continue;c=(r.max-l)/(p-l)*(d-c)+c,l=r.max}else if(p>=l&&p>r.max){if(l>r.max)continue;d=(r.max-l)/(p-l)*(d-c)+c,p=r.max}(l!=u||c!=a)&&h.moveTo(r.p2c(l)+t,i.p2c(c)+n),u=p,a=d,h.lineTo(r.p2c(p)+t,i.p2c(d)+n)}h.stroke()}function n(e,t,n){var r=e.points,i=e.pointsize,s=Math.min(Math.max(0,n.min),n.max),o=0,u,a=!1,f=1,l=0,c=0;for(;;){if(i>0&&o>r.length+i)break;o+=i;var p=r[o-i],d=r[o-i+f],v=r[o],m=r[o+f];if(a){if(i>0&&p!=null&&v==null){c=o,i=-i,f=2;continue}if(i<0&&o==l+i){h.fill(),a=!1,i=-i,f=1,o=l=c+i;continue}}if(p==null||v==null)continue;if(p<=v&&p=v&&p>t.max){if(v>t.max)continue;d=(t.max-p)/(v-p)*(m-d)+d,p=t.max}else if(v>=p&&v>t.max){if(p>t.max)continue;m=(t.max-p)/(v-p)*(m-d)+d,v=t.max}a||(h.beginPath(),h.moveTo(t.p2c(p),n.p2c(s)),a=!0);if(d>=n.max&&m>=n.max){h.lineTo(t.p2c(p),n.p2c(n.max)),h.lineTo(t.p2c(v),n.p2c(n.max));continue}if(d<=n.min&&m<=n.min){h.lineTo(t.p2c(p),n.p2c(n.min)),h.lineTo(t.p2c(v),n.p2c(n.min));continue}var g=p,y=v;d<=m&&d=n.min?(p=(n.min-d)/(m-d)*(v-p)+p,d=n.min):m<=d&&m=n.min&&(v=(n.min-d)/(m-d)*(v-p)+p,m=n.min),d>=m&&d>n.max&&m<=n.max?(p=(n.max-d)/(m-d)*(v-p)+p,d=n.max):m>=d&&m>n.max&&d<=n.max&&(v=(n.max-d)/(m-d)*(v-p)+p,m=n.max),p!=g&&h.lineTo(t.p2c(g),n.p2c(d)),h.lineTo(t.p2c(p),n.p2c(d)),h.lineTo(t.p2c(v),n.p2c(m)),v!=y&&(h.lineTo(t.p2c(v),n.p2c(m)),h.lineTo(t.p2c(y),n.p2c(m)))}}h.save(),h.translate(m.left,m.top),h.lineJoin="round";var r=e.lines.lineWidth,i=e.shadowSize;if(r>0&&i>0){h.lineWidth=i,h.strokeStyle="rgba(0,0,0,0.1)";var s=Math.PI/18;t(e.datapoints,Math.sin(s)*(r/2+i/2),Math.cos(s)*(r/2+i/2),e.xaxis,e.yaxis),h.lineWidth=i/2,t(e.datapoints,Math.sin(s)*(r/2+i/4),Math.cos(s)*(r/2+i/4),e.xaxis,e.yaxis)}h.lineWidth=r,h.strokeStyle=e.color;var o=rt(e.lines,e.color,0,y);o&&(h.fillStyle=o,n(e.datapoints,e.xaxis,e.yaxis)),r>0&&t(e.datapoints,0,0,e.xaxis,e.yaxis),h.restore()}function et(e){function t(e,t,n,r,i,s,o,u){var a=e.points,f=e.pointsize;for(var l=0;ls.max||po.max)continue;h.beginPath(),c=s.p2c(c),p=o.p2c(p)+r,u=="circle"?h.arc(c,p,t,0,i?Math.PI:Math.PI*2,!1):u(h,c,p,t,i),h.closePath(),n&&(h.fillStyle=n,h.fill()),h.stroke()}}h.save(),h.translate(m.left,m.top);var n=e.points.lineWidth,r=e.shadowSize,i=e.points.radius,s=e.points.symbol;n==0&&(n=1e-4);if(n>0&&r>0){var o=r/2;h.lineWidth=o,h.strokeStyle="rgba(0,0,0,0.1)",t(e.datapoints,i,null,o+o/2,!0,e.xaxis,e.yaxis,s),h.strokeStyle="rgba(0,0,0,0.2)",t(e.datapoints,i,null,o/2,!0,e.xaxis,e.yaxis,s)}h.lineWidth=n,h.strokeStyle=e.color,t(e.datapoints,i,rt(e.points,e.color),0,!1,e.xaxis,e.yaxis,s),h.restore()}function tt(e,t,n,r,i,s,o,u,a,f,l,c){var h,p,d,v,m,g,y,b,w;l?(b=g=y=!0,m=!1,h=n,p=e,v=t+r,d=t+i,pu.max||va.max)return;hu.max&&(p=u.max,g=!1),da.max&&(v=a.max,y=!1),h=u.p2c(h),d=a.p2c(d),p=u.p2c(p),v=a.p2c(v),o&&(f.beginPath(),f.moveTo(h,d),f.lineTo(h,v),f.lineTo(p,v),f.lineTo(p,d),f.fillStyle=o(d,v),f.fill()),c>0&&(m||g||y||b)&&(f.beginPath(),f.moveTo(h,d+s),m?f.lineTo(h,v+s):f.moveTo(h,v+s),y?f.lineTo(p,v+s):f.moveTo(p,v+s),g?f.lineTo(p,d+s):f.moveTo(p,d+s),b?f.lineTo(h,d+s):f.moveTo(h,d+s),f.stroke())}function nt(e){function t(t,n,r,i,s,o,u){var a=t.points,f=t.pointsize;for(var l=0;l"),n.push(""),i=!0),n.push('
'+''+h.label+"")}i&&n.push("");if(n.length==0)return;var p=''+n.join("")+"
";if(a.legend.container!=null)e(a.legend.container).html(p);else{var d="",v=a.legend.position,g=a.legend.margin;g[0]==null&&(g=[g,g]),v.charAt(0)=="n"?d+="top:"+(g[1]+m.top)+"px;":v.charAt(0)=="s"&&(d+="bottom:"+(g[1]+m.bottom)+"px;"),v.charAt(1)=="e"?d+="right:"+(g[0]+m.right)+"px;":v.charAt(1)=="w"&&(d+="left:"+(g[0]+m.left)+"px;");var y=e('
'+p.replace('style="','style="position:absolute;'+d+";")+"
").appendTo(t);if(a.legend.backgroundOpacity!=0){var b=a.legend.backgroundColor;b==null&&(b=a.grid.backgroundColor,b&&typeof b=="string"?b=e.color.parse(b):b=e.color.extract(y,"background-color"),b.a=1,b=b.toString());var w=y.children();e('
').prependTo(y).css("opacity",a.legend.backgroundOpacity)}}}function ut(e,t,n){var r=a.grid.mouseActiveRadius,i=r*r+1,s=null,o=!1,f,l,c;for(f=u.length-1;f>=0;--f){if(!n(u[f]))continue;var h=u[f],p=h.xaxis,d=h.yaxis,v=h.datapoints.points,m=p.c2p(e),g=d.c2p(t),y=r/p.scale,b=r/d.scale;c=h.datapoints.pointsize,p.options.inverseTransform&&(y=Number.MAX_VALUE),d.options.inverseTransform&&(b=Number.MAX_VALUE);if(h.lines.show||h.points.show)for(l=0;ly||w-m<-y||E-g>b||E-g<-b)continue;var S=Math.abs(p.p2c(w)-e),x=Math.abs(d.p2c(E)-t),T=S*S+x*x;T=Math.min(k,w)&&g>=E+N&&g<=E+C:m>=w+N&&m<=w+C&&g>=Math.min(k,E)&&g<=Math.max(k,E))s=[f,l/c]}}}return s?(f=s[0],l=s[1],c=u[f].datapoints.pointsize,{datapoint:u[f].datapoints.points.slice(l*c,(l+1)*c),dataIndex:l,series:u[f],seriesIndex:f}):null}function at(e){a.grid.hoverable&&ct("plothover",e,function(e){return e["hoverable"]!=0})}function ft(e){a.grid.hoverable&&ct("plothover",e,function(e){return!1})}function lt(e){ct("plotclick",e,function(e){return e["clickable"]!=0})}function ct(e,n,r){var i=c.offset(),s=n.pageX-i.left-m.left,o=n.pageY-i.top-m.top,u=L({left:s,top:o});u.pageX=n.pageX,u.pageY=n.pageY;var f=ut(s,o,r);f&&(f.pageX=parseInt(f.series.xaxis.p2c(f.datapoint[0])+i.left+m.left,10),f.pageY=parseInt(f.series.yaxis.p2c(f.datapoint[1])+i.top+m.top,10));if(a.grid.autoHighlight){for(var l=0;ls.max||io.max)return;var a=t.points.radius+t.points.lineWidth/2;p.lineWidth=a,p.strokeStyle=u;var f=1.5*a;r=s.p2c(r),i=o.p2c(i),p.beginPath(),t.points.symbol=="circle"?p.arc(r,i,f,0,2*Math.PI,!1):t.points.symbol(p,r,i,f,!1),p.closePath(),p.stroke()}function yt(t,n){var r=typeof t.highlightColor=="string"?t.highlightColor:e.color.parse(t.color).scale("a",.5).toString(),i=r,s=t.bars.align=="left"?0:-t.bars.barWidth/2;p.lineWidth=t.bars.lineWidth,p.strokeStyle=r,tt(n[0],n[1],n[2]||0,s,s+t.bars.barWidth,0,function(){return i},t.xaxis,t.yaxis,p,t.bars.horizontal,t.bars.lineWidth)}function bt(t,n,r,i){if(typeof t=="string")return t;var s=h.createLinearGradient(0,r,0,n);for(var o=0,u=t.colors.length;o
").css({position:"absolute",top:0,left:0,bottom:0,right:0,"font-size":"smaller",color:"#545454"}).insertAfter(this.element)),n=this.text[t]=e("
").addClass(t).css({position:"absolute",top:0,left:0,bottom:0,right:0}).appendTo(this.textContainer)),n},n.prototype.getTextInfo=function(t,n,r,i,s){var o,u,a,f;n=""+n,typeof r=="object"?o=r.style+" "+r.variant+" "+r.weight+" "+r.size+"px/"+r.lineHeight+"px "+r.family:o=r,u=this._textCache[t],u==null&&(u=this._textCache[t]={}),a=u[o],a==null&&(a=u[o]={}),f=a[n];if(f==null){var l=e("
").html(n).css({position:"absolute","max-width":s,top:-9999}).appendTo(this.getTextLayer(t));typeof r=="object"?l.css({font:o,color:r.color}):typeof r=="string"&&l.addClass(r),f=a[n]={width:l.outerWidth(!0),height:l.outerHeight(!0),element:l,positions:[]},l.detach()}return f},n.prototype.addText=function(e,t,n,r,i,s,o,u,a){var f=this.getTextInfo(e,r,i,s,o),l=f.positions;u=="center"?t-=f.width/2:u=="right"&&(t-=f.width),a=="middle"?n-=f.height/2:a=="bottom"&&(n-=f.height);for(var c=0,h;h=l[c];c++)if(h.x==t&&h.y==n){h.active=!0;return}h={active:!0,rendered:!1,element:l.length?f.element.clone():f.element,x:t,y:n},l.push(h),h.element.css({top:Math.round(n),left:Math.round(t),"text-align":u})},n.prototype.removeText=function(e,n,r,i,s,o){if(i==null){var u=this._textCache[e];if(u!=null)for(var a in u)if(t.call(u,a)){var f=u[a];for(var l in f)if(t.call(f,l)){var c=f[l].positions;for(var h=0,p;p=c[h];h++)p.active=!1}}}else{var c=this.getTextInfo(e,i,s,o).positions;for(var h=0,p;p=c[h];h++)p.x==n&&p.y==r&&(p.active=!1)}},e.plot=function(t,n,i){var s=new r(e(t),n,i,e.plot.plugins);return s},e.plot.version="0.8.1",e.plot.plugins=[],e.fn.plot=function(t,n){return this.each(function(){e.plot(this,t,n)})}}(jQuery);rabbitmq-server-3.2.4/plugins-src/rabbitmq-management/priv/www/js/prefs.js0000644000000000000000000000420512305126066025403 0ustar rootroot// TODO It would be nice to use DOM storage. When that's available. function store_pref(k, v) { var d = parse_cookie(); d[short_key(k)] = v; store_cookie(d); } function clear_pref(k) { var d = parse_cookie(); delete d[short_key(k)]; store_cookie(d); } function get_pref(k) { var r = parse_cookie()[short_key(k)]; return r == undefined ? default_pref(k) : r; } function section_pref(template, name) { return 'visible|' + template + '|' + name; } // --------------------------------------------------------------------------- function default_pref(k) { if (k.substring(0, 12) == 'chart-range-') return '60|5'; if (k.substring(0, 11) == 'chart-size-') return 'small'; if (k.substring(0, 10) == 'rate-mode-') return 'chart'; if (k == 'truncate') return '100'; return null; } // --------------------------------------------------------------------------- function parse_cookie() { var c = get_cookie('m'); var items = c.length == 0 ? [] : c.split('|'); var start = 0; var dict = {}; for (var i in items) { var kv = items[i].split(':'); dict[kv[0]] = unescape(kv[1]); } return dict; } function store_cookie(dict) { var enc = []; for (var k in dict) { enc.push(k + ':' + escape(dict[k])); } var date = new Date(); date.setFullYear(date.getFullYear() + 1); document.cookie = 'm=' + enc.join('|') + '; expires=' + date.toUTCString(); } function get_cookie(key) { var cookies = document.cookie.split(';'); for (var i in cookies) { var kv = jQuery.trim(cookies[i]).split('='); if (kv[0] == key) return kv[1]; } return ''; } // Try to economise on space since cookies have limited length. function short_key(k) { var res = Math.abs(k.hashCode() << 16 >> 16); res = res.toString(16); return res; } String.prototype.hashCode = function() { var hash = 0; if (this.length == 0) return code; for (i = 0; i < this.length; i++) { char = this.charCodeAt(i); hash = 31*hash+char; hash = hash & hash; // Convert to 32bit integer } return hash; } rabbitmq-server-3.2.4/plugins-src/rabbitmq-management/priv/www/js/main.js0000644000000000000000000010444112305126066025213 0ustar rootroot$(document).ready(function() { replace_content('outer', format('login', {})); start_app_login(); }); function dispatcher_add(fun) { dispatcher_modules.push(fun); if (dispatcher_modules.length == extension_count) { start_app(); } } function dispatcher() { for (var i in dispatcher_modules) { dispatcher_modules[i](this); } } function set_auth_cookie(userinfo) { var b64 = b64_encode_utf8(userinfo); document.cookie = 'auth=' + encodeURIComponent(b64); } function login_route () { var userpass = '' + this.params['username'] + ':' + this.params['password'], location = window.location.href, hash = window.location.hash; set_auth_cookie(decodeURIComponent(userpass)); location = location.substr(0, location.length - hash.length); window.location.replace(location); // because we change url, we don't need to hit check_login as // we'll end up doing that at the bottom of start_app_login after // we've changed url. } function start_app_login() { app = new Sammy.Application(function () { this.put('#/login', function() { username = this.params['username']; password = this.params['password']; set_auth_cookie(username + ':' + password); check_login(); }); this.get('#/login/:username/:password', login_route) }); app.run(); if (get_cookie('auth') != '') { check_login(); } } function check_login() { var user = JSON.parse(sync_get('/whoami')); if (user == false) { document.cookie = 'auth=; expires=Thu, 01 Jan 1970 00:00:00 GMT'; replace_content('login-status', '

Login failed

'); } else { replace_content('outer', format('layout', {})); setup_global_vars(user); setup_constant_events(); update_vhosts(); update_interval(); setup_extensions(); } } function start_app() { if (app !== undefined) { app.unload(); } // Oh boy. Sammy uses various different methods to determine if // the URL hash has changed. Unsurprisingly this is a native event // in modern browsers, and falls back to an icky polling function // in MSIE. But it looks like there's a bug. The polling function // should get installed when the app is started. But it's guarded // behind if (Sammy.HashLocationProxy._interval != null). And of // course that's not specific to the application; it's pretty // global. So we need to manually clear that in order for links to // work in MSIE. // Filed as https://github.com/quirkey/sammy/issues/171 // // Note for when we upgrade: HashLocationProxy has become // DefaultLocationProxy in later versions, but otherwise the issue // remains. Sammy.HashLocationProxy._interval = null; app = new Sammy.Application(dispatcher); app.run(); var url = this.location.toString(); if (url.indexOf('#') == -1) { this.location = url + '#/'; } } function setup_constant_events() { $('#update-every').change(function() { var interval = $(this).val(); store_pref('interval', interval); if (interval == '') interval = null; else interval = parseInt(interval); set_timer_interval(interval); }); $('#show-vhost').change(function() { current_vhost = $(this).val(); store_pref('vhost', current_vhost); update(); }); if (!vhosts_interesting) { $('#vhost-form').hide(); } } function update_vhosts() { var vhosts = JSON.parse(sync_get('/vhosts')); vhosts_interesting = vhosts.length > 1; if (vhosts_interesting) $('#vhost-form').show(); else $('#vhost-form').hide(); var select = $('#show-vhost').get(0); select.options.length = vhosts.length + 1; var index = 0; for (var i = 0; i < vhosts.length; i++) { var vhost = vhosts[i].name; select.options[i + 1] = new Option(vhost, vhost); if (vhost == current_vhost) index = i + 1; } select.selectedIndex = index; current_vhost = select.options[index].value; store_pref('vhost', current_vhost); } function setup_extensions() { var extensions = JSON.parse(sync_get('/extensions')); extension_count = extensions.length; for (var i in extensions) { var extension = extensions[i]; dynamic_load(extension.javascript); } } function dynamic_load(filename) { var element = document.createElement('script'); element.setAttribute('type', 'text/javascript'); element.setAttribute('src', 'js/' + filename); document.getElementsByTagName("head")[0].appendChild(element); } function update_interval() { var intervalStr = get_pref('interval'); var interval; if (intervalStr == null) interval = 5000; else if (intervalStr == '') interval = null; else interval = parseInt(intervalStr); if (isNaN(interval)) interval = null; // Prevent DoS if cookie malformed set_timer_interval(interval); var select = $('#update-every').get(0); var opts = select.options; for (var i = 0; i < opts.length; i++) { if (opts[i].value == intervalStr) { select.selectedIndex = i; break; } } } function go_to(url) { this.location = url; } function set_timer_interval(interval) { timer_interval = interval; reset_timer(); } function reset_timer() { clearInterval(timer); if (timer_interval != null) { timer = setInterval('partial_update()', timer_interval); } } function update_manual(div, query) { var path; var template; if (query == 'memory') { path = current_reqs['node'] + '?memory=true'; template = 'memory'; } var data = JSON.parse(sync_get(path)); replace_content(div, format(template, data)); postprocess_partial(); } function render(reqs, template, highlight) { current_template = template; current_reqs = reqs; current_highlight = highlight; update(); } function update() { replace_content('debug', ''); clearInterval(timer); with_update(function(html) { update_navigation(); replace_content('main', html); postprocess(); postprocess_partial(); render_charts(); maybe_scroll(); reset_timer(); }); } function partial_update() { if ($('.updatable').length > 0) { if (update_counter >= 200) { update_counter = 0; full_refresh(); return; } with_update(function(html) { update_counter++; replace_content('scratch', html); var befores = $('#main .updatable'); var afters = $('#scratch .updatable'); if (befores.length != afters.length) { throw("before/after mismatch"); } for (var i = 0; i < befores.length; i++) { $(befores[i]).empty().append($(afters[i]).contents()); } replace_content('scratch', ''); postprocess_partial(); render_charts(); }); } } function update_navigation() { var l1 = ''; var l2 = ''; var descend = null; for (var k in NAVIGATION) { var val = NAVIGATION[k]; var path = val; while (!leaf(path)) { path = first_showable_child(path); } var selected = false; if (contains_current_highlight(val)) { selected = true; if (!leaf(val)) { descend = nav(val); } } if (show(path)) { l1 += '
  • ' + k + '
  • '; } } if (descend) { l2 = obj_to_ul(descend); $('#main').addClass('with-rhs'); } else { $('#main').removeClass('with-rhs'); } replace_content('tabs', l1); replace_content('rhs', l2); } function nav(pair) { return pair[0]; } function show(pair) { return jQuery.inArray(pair[1], user_tags) != -1; } function leaf(pair) { return typeof(nav(pair)) == 'string'; } function first_showable_child(pair) { var items = pair[0]; var ks = keys(items); for (var i = 0; i < ks.length; i++) { var child = items[ks[i]]; if (show(child)) return child; } return items[ks[0]]; // We'll end up not showing it anyway } function contains_current_highlight(val) { if (leaf(val)) { return current_highlight == nav(val); } else { var b = false; for (var k in val) { b |= contains_current_highlight(val[k]); } return b; } } function obj_to_ul(val) { var res = '
      '; for (var k in val) { var obj = val[k]; if (show(obj)) { res += '
    • '; if (leaf(obj)) { res += '' + k + ''; } else { res += obj_to_ul(nav(obj)); } res += '
    • '; } } return res + '
    '; } function full_refresh() { store_pref('position', x_position() + ',' + y_position()); location.reload(); } function maybe_scroll() { var pos = get_pref('position'); if (pos) { clear_pref('position'); var xy = pos.split(","); window.scrollTo(parseInt(xy[0]), parseInt(xy[1])); } } function x_position() { return window.pageXOffset ? window.pageXOffset : document.documentElement.scrollLeft ? document.documentElement.scrollLeft : document.body.scrollLeft; } function y_position() { return window.pageYOffset ? window.pageYOffset : document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop; } function with_update(fun) { with_reqs(apply_state(current_reqs), [], function(json) { json.statistics_level = statistics_level; var html = format(current_template, json); fun(html); update_status('ok'); }); } function apply_state(reqs) { var reqs2 = {}; for (k in reqs) { var req = reqs[k]; var options = {}; if (typeof(req) == "object") { options = req.options; req = req.path; } var req2; if (options['vhost'] != undefined && current_vhost != '') { req2 = req + '/' + esc(current_vhost); } else { req2 = req; } var qs = []; if (options['sort'] != undefined && current_sort != null) { qs.push('sort=' + current_sort); qs.push('sort_reverse=' + current_sort_reverse); } if (options['ranges'] != undefined) { for (i in options['ranges']) { var type = options['ranges'][i]; var range = get_pref('chart-range-' + type).split('|'); var prefix; if (type.substring(0, 8) == 'lengths-') { prefix = 'lengths'; } else if (type.substring(0, 10) == 'msg-rates-') { prefix = 'msg_rates'; } else if (type.substring(0, 11) == 'data-rates-') { prefix = 'data_rates'; } qs.push(prefix + '_age=' + parseInt(range[0])); qs.push(prefix + '_incr=' + parseInt(range[1])); } } qs = qs.join('&'); if (qs != '') qs = '?' + qs; reqs2[k] = req2 + qs; } return reqs2; } function show_popup(type, text, mode) { var cssClass = '.form-popup-' + type; function hide() { if (mode == 'fade') { $(cssClass).fadeOut(200, function() { $(this).remove(); }); } else { $(cssClass).slideUp(200, function() { $(this).remove(); }); } } hide(); $('h1').after(format('error-popup', {'type': type, 'text': text})); if (mode == 'fade') { $(cssClass).fadeIn(200); } else { $(cssClass).center().slideDown(200); } $(cssClass + ' span').click(function () { $('.popup-owner').removeClass('popup-owner'); hide(); }); } function postprocess() { $('form.confirm').submit(function() { return confirm("Are you sure? This object cannot be recovered " + "after deletion."); }); $('div.section h2, div.section-hidden h2').click(function() { toggle_visibility($(this)); }); $('label').map(function() { if ($(this).attr('for') == '') { var id = 'auto-label-' + Math.floor(Math.random()*1000000000); var input = $(this).parents('tr').first().find('input, select'); if (input.attr('id') == '') { $(this).attr('for', id); input.attr('id', id); } } }); $('#download-definitions').click(function() { var path = 'api/definitions?download=' + esc($('#download-filename').val()) + '&auth=' + get_cookie('auth'); window.location = path; setTimeout('app.run()'); return false; }); $('.update-manual').click(function() { update_manual($(this).attr('for'), $(this).attr('query')); }); $('input, select').die(); $('.multifield input').live('keyup', function() { update_multifields(); }); $('.multifield select').live('change', function() { update_multifields(); }); $('.controls-appearance').change(function() { var controls = $(this).attr('controls-divs'); if ($(this).val() == 'true') { $('#' + controls + '-yes').slideDown(100); $('#' + controls + '-no').slideUp(100); } else { $('#' + controls + '-yes').slideUp(100); $('#' + controls + '-no').slideDown(100); } }); setup_visibility(); $('.help').die().live('click', function() { help($(this).attr('id')) }); $('.rate-options').die().live('click', function() { var remove = $('.popup-owner').length == 1 && $('.popup-owner').get(0) == $(this).get(0); $('.popup-owner').removeClass('popup-owner'); if (remove) { $('.form-popup-rate-options').fadeOut(200, function() { $(this).remove(); }); } else { $(this).addClass('popup-owner'); show_popup('rate-options', format('rate-options', {span: $(this)}), 'fade'); } }); $('input, select').live('focus', function() { update_counter = 0; // If there's interaction, reset the counter. }); $('.tag-link').click(function() { $('#tags').val($(this).attr('tag')); }); $('form.auto-submit select, form.auto-submit input').live('click', function(){ $(this).parents('form').submit(); }); $('#filter').die().live('keyup', debounce(update_filter, 500)); $('#truncate').die().live('keyup', debounce(update_truncate, 500)); if (! user_administrator) { $('.administrator-only').remove(); } update_multifields(); } function postprocess_partial() { $('.sort').click(function() { var sort = $(this).attr('sort'); if (current_sort == sort) { current_sort_reverse = ! current_sort_reverse; } else { current_sort = sort; current_sort_reverse = false; } update(); }); $('.help').html('(?)'); // TODO remove this hack when we get rid of "updatable" if ($('#filter-warning-show').length > 0) { $('#filter-truncate').addClass('filter-warning'); } else { $('#filter-truncate').removeClass('filter-warning'); } } function update_multifields() { $('div.multifield').each(function(index) { update_multifield($(this), true); }); } function update_multifield(multifield, dict) { var largest_id = 0; var empty_found = false; var name = multifield.attr('id'); $('#' + name + ' *[name$="_mftype"]').each(function(index) { var re = new RegExp(name + '_([0-9]*)_mftype'); var match = $(this).attr('name').match(re); if (!match) return; var id = parseInt(match[1]); largest_id = Math.max(id, largest_id); var prefix = name + '_' + id; var type = $(this).val(); var input = $('#' + prefix + '_mfvalue'); if (type == 'list') { if (input.size() == 1) { input.replaceWith('
    '); } update_multifield($('#' + prefix), false); } else { if (input.size() == 1) { var key = dict ? $('#' + prefix + '_mfkey').val() : ''; var value = input.val(); if (key == '' && value == '') { if (empty_found) { $(this).parent().remove(); } empty_found = true; } } else { $('#' + prefix).replaceWith(multifield_input(prefix, 'value', 'text')); } } }); if (!empty_found) { var prefix = name + '_' + (largest_id + 1); var t = multifield.hasClass('string-only') ? 'hidden' : 'select'; var val_type = multifield_input(prefix, 'value', 'text') + ' ' + multifield_input(prefix, 'type', t); if (dict) { multifield.append('
    ' + multifield_input(prefix, 'key', 'text') + ' = ' + val_type + '
    '); } else { multifield.append('
    ' + val_type + '
    '); } } } function multifield_input(prefix, suffix, type) { if (type == 'hidden' ) { return ''; } else if (type == 'text' ) { return ''; } else if (type == 'select' ) { return ''; } } function update_filter() { current_filter = $(this).val(); var table = $(this).parents('table').first(); table.removeClass('filter-active'); if ($(this).val() != '') { table.addClass('filter-active'); } partial_update(); } function update_truncate() { var current_truncate_str = $(this).val().replace(new RegExp('\\D', 'g'), ''); if (current_truncate_str == '') current_truncate_str = '0'; if ($(this).val() != current_truncate_str) $(this).val(current_truncate_str); current_truncate = parseInt(current_truncate_str, 10); store_pref('truncate', current_truncate); partial_update(); } function setup_visibility() { $('div.section,div.section-hidden').each(function(_index) { var pref = section_pref(current_template, $(this).children('h2').text()); var show = get_pref(pref); if (show == null) { show = $(this).hasClass('section'); } else { show = show == 't'; } if (show) { $(this).addClass('section-visible'); } else { $(this).addClass('section-invisible'); } }); } function toggle_visibility(item) { var hider = item.next(); var all = item.parent(); var pref = section_pref(current_template, item.text()); item.next().slideToggle(100); if (all.hasClass('section-visible')) { if (all.hasClass('section')) store_pref(pref, 'f'); else clear_pref(pref); all.removeClass('section-visible'); all.addClass('section-invisible'); } else { if (all.hasClass('section-hidden')) store_pref(pref, 't'); else clear_pref(pref); all.removeClass('section-invisible'); all.addClass('section-visible'); } } function publish_msg(params0) { var params = params_magic(params0); var path = fill_path_template('/exchanges/:vhost/:name/publish', params); params['payload_encoding'] = 'string'; params['properties'] = {}; params['properties']['delivery_mode'] = parseInt(params['delivery_mode']); if (params['headers'] != '') params['properties']['headers'] = params['headers']; var props = ['content_type', 'content_encoding', 'priority', 'correlation_id', 'reply_to', 'expiration', 'message_id', 'timestamp', 'type', 'user_id', 'app_id', 'cluster_id']; for (var i in props) { var p = props[i]; if (params['props'][p] != '') params['properties'][p] = params['props'][p]; } with_req('POST', path, JSON.stringify(params), function(resp) { var result = jQuery.parseJSON(resp.responseText); if (result.routed) { show_popup('info', 'Message published.'); } else { show_popup('warn', 'Message published, but not routed.'); } }); } function get_msgs(params) { var path = fill_path_template('/queues/:vhost/:name/get', params); with_req('POST', path, JSON.stringify(params), function(resp) { var msgs = jQuery.parseJSON(resp.responseText); if (msgs.length == 0) { show_popup('info', 'Queue is empty'); } else { $('#msg-wrapper').slideUp(200); replace_content('msg-wrapper', format('messages', {'msgs': msgs})); $('#msg-wrapper').slideDown(200); } }); } function with_reqs(reqs, acc, fun) { if (keys(reqs).length > 0) { var key = keys(reqs)[0]; with_req('GET', reqs[key], null, function(resp) { acc[key] = jQuery.parseJSON(resp.responseText); var remainder = {}; for (var k in reqs) { if (k != key) remainder[k] = reqs[k]; } with_reqs(remainder, acc, fun); }); } else { fun(acc); } } function replace_content(id, html) { $("#" + id).html(html); } var ejs_cached = {}; function format(template, json) { try { var cache = true; if (!(template in ejs_cached)) { ejs_cached[template] = true; cache = false; } var tmpl = new EJS({url: 'js/tmpl/' + template + '.ejs', cache: cache}); return tmpl.render(json); } catch (err) { clearInterval(timer); debug(err['name'] + ": " + err['message']); } } function update_status(status) { var text; if (status == 'ok') text = "Last update: " + fmt_date(new Date()); else if (status == 'error') { var next_try = new Date(new Date().getTime() + timer_interval); text = "Error: could not connect to server since " + fmt_date(last_successful_connect) + ".
    Will retry at " + fmt_date(next_try) + "."; } else throw("Unknown status " + status); var html = format('status', {status: status, text: text}); replace_content('status', html); } function auth_header() { return "Basic " + decodeURIComponent(get_cookie('auth')); } function with_req(method, path, body, fun) { var json; var req = xmlHttpRequest(); req.open(method, 'api' + path, true ); req.setRequestHeader('authorization', auth_header()); req.onreadystatechange = function () { if (req.readyState == 4) { if (check_bad_response(req, true)) { last_successful_connect = new Date(); fun(req); } } }; req.send(body); } function sync_get(path) { return sync_req('GET', [], path); } function sync_put(sammy, path_template) { return sync_req('PUT', sammy.params, path_template); } function sync_delete(sammy, path_template, options) { return sync_req('DELETE', sammy.params, path_template, options); } function sync_post(sammy, path_template) { return sync_req('POST', sammy.params, path_template); } function sync_req(type, params0, path_template, options) { var params; var path; try { params = params_magic(params0); path = fill_path_template(path_template, params); } catch (e) { show_popup('warn', e); return false; } var req = xmlHttpRequest(); req.open(type, 'api' + path, false); req.setRequestHeader('content-type', 'application/json'); req.setRequestHeader('authorization', auth_header()); if (options != undefined || options != null) { if (options.headers != undefined || options.headers != null) { jQuery.each(options.headers, function (k, v) { req.setRequestHeader(k, v); }); } } try { if (type == 'GET') req.send(null); else req.send(JSON.stringify(params)); } catch (e) { if (e.number == 0x80004004) { // 0x80004004 means "Operation aborted." // http://support.microsoft.com/kb/186063 // MSIE6 appears to do this in response to HTTP 204. } } if (check_bad_response(req, false)) { if (type == 'GET') return req.responseText; else return true; } else { return false; } } function check_bad_response(req, full_page_404) { // 1223 == 204 - see http://www.enhanceie.com/ie/bugs.asp // MSIE7 and 8 appear to do this in response to HTTP 204. if ((req.status >= 200 && req.status < 300) || req.status == 1223) { return true; } else if (req.status == 404 && full_page_404) { var html = format('404', {}); replace_content('main', html); } else if (req.status >= 400 && req.status <= 404) { var reason = JSON.parse(req.responseText).reason; if (typeof(reason) != 'string') reason = JSON.stringify(reason); show_popup('warn', reason); } else if (req.status == 408) { update_status('timeout'); } else if (req.status == 0) { // Non-MSIE: could not connect update_status('error'); } else if (req.status > 12000) { // MSIE: could not connect update_status('error'); } else if (req.status == 503) { // Proxy: could not connect update_status('error'); } else { debug("Got response code " + req.status + " with body " + req.responseText); clearInterval(timer); } return false; } function fill_path_template(template, params) { var re = /:[a-zA-Z_]*/g; return template.replace(re, function(m) { var str = esc(params[m.substring(1)]); if (str == '') { throw(m.substring(1) + " is required"); } return str; }); } function params_magic(params) { return check_password( add_known_arguments( maybe_remove_fields( collapse_multifields(params)))); } function collapse_multifields(params0) { function set(x) { return x != '' && x != undefined } var params = {}; var ks = keys(params0); var ids = []; for (i in ks) { var key = ks[i]; var match = key.match(/([a-z]*)_([0-9_]*)_mftype/); var match2 = key.match(/[a-z]*_[0-9_]*_mfkey/); var match3 = key.match(/[a-z]*_[0-9_]*_mfvalue/); if (match == null && match2 == null && match3 == null) { params[key] = params0[key]; } else if (match == null) { // Do nothing, value is handled below } else { var name = match[1]; var id = match[2]; ids.push([name, id]); } } ids.sort(); var id_map = {}; for (i in ids) { var name = ids[i][0]; var id = ids[i][1]; if (params[name] == undefined) { params[name] = {}; id_map[name] = {}; } var id_parts = id.split('_'); var k = params0[name + '_' + id_parts[0] + '_mfkey']; var v = params0[name + '_' + id + '_mfvalue']; var t = params0[name + '_' + id + '_mftype']; var val = null; if (t == 'list') { val = []; id_map[name][id] = val; } else if (set(k) || set(v)) { if (t == 'boolean') { if (v != 'true' && v != 'false') throw(k + ' must be "true" or "false"; got ' + v); val = (v == 'true'); } else if (t == 'number') { var n = parseFloat(v); if (isNaN(n)) throw(k + ' must be a number; got ' + v); val = n; } else { val = v; } } if (val != null) { if (id_parts.length == 1) { params[name][k] = val; } else { var prefix = id_parts.slice(0, id_parts.length - 1).join('_'); id_map[name][prefix].push(val); } } } return params; } function add_known_arguments(params) { for (var k in KNOWN_ARGS) { var v = params[k]; if (v != undefined && v != '') { var type = KNOWN_ARGS[k].type; if (type == 'int') { v = parseInt(v); if (isNaN(v)) { throw(k + " must be an integer."); } } params.arguments[k] = v; } delete params[k]; } return params; } function check_password(params) { if (params['password'] != undefined) { if (params['password'] == '') { throw("Please specify a password."); } if (params['password'] != params['password_confirm']) { throw("Passwords do not match."); } delete params['password_confirm']; } return params; } function maybe_remove_fields(params) { $('.controls-appearance').each(function(index) { if ($(this).val() == 'false') { delete params[$(this).attr('param-name')]; delete params[$(this).attr('name')]; } }); return params; } function put_parameter(sammy, mandatory_keys, num_keys, bool_keys, arrayable_keys) { for (var i in sammy.params) { if (i === 'length' || !sammy.params.hasOwnProperty(i)) continue; if (sammy.params[i] == '' && jQuery.inArray(i, mandatory_keys) == -1) { delete sammy.params[i]; } else if (jQuery.inArray(i, num_keys) != -1) { sammy.params[i] = parseInt(sammy.params[i]); } else if (jQuery.inArray(i, bool_keys) != -1) { sammy.params[i] = sammy.params[i] == 'true'; } else if (jQuery.inArray(i, arrayable_keys) != -1) { sammy.params[i] = sammy.params[i].split(' '); if (sammy.params[i].length == 1) { sammy.params[i] = sammy.params[i][0]; } } } var params = {"component": sammy.params.component, "vhost": sammy.params.vhost, "name": sammy.params.name, "value": params_magic(sammy.params)}; delete params.value.vhost; delete params.value.component; delete params.value.name; sammy.params = params; if (sync_put(sammy, '/parameters/:component/:vhost/:name')) update(); } function put_policy(sammy, mandatory_keys, num_keys, bool_keys) { for (var i in sammy.params) { if (i === 'length' || !sammy.params.hasOwnProperty(i)) continue; if (sammy.params[i] == '' && jQuery.inArray(i, mandatory_keys) == -1) { delete sammy.params[i]; } else if (jQuery.inArray(i, num_keys) != -1) { sammy.params[i] = parseInt(sammy.params[i]); } else if (jQuery.inArray(i, bool_keys) != -1) { sammy.params[i] = sammy.params[i] == 'true'; } } if (sync_put(sammy, '/policies/:vhost/:name')) update(); } function debug(str) { $('

    ' + str + '

    ').appendTo('#debug'); } function keys(obj) { var ks = []; for (var k in obj) { ks.push(k); } return ks; } // Don't use the jQuery AJAX support, it seemss to have trouble reporting // server-down type errors. function xmlHttpRequest() { var res; try { res = new XMLHttpRequest(); } catch(e) { res = new ActiveXObject("Microsoft.XMLHttp"); } return res; } // Our base64 library takes a string that is really a byte sequence, // and will throw if given a string with chars > 255 (and hence not // DTRT for chars > 127). So encode a unicode string as a UTF-8 // sequence of "bytes". function b64_encode_utf8(str) { return base64.encode(encode_utf8(str)); } // encodeURIComponent handles utf-8, unescape does not. Neat! function encode_utf8(str) { return unescape(encodeURIComponent(str)); } (function($){ $.fn.extend({ center: function () { return this.each(function() { var top = ($(window).height() - $(this).outerHeight()) / 2; var left = ($(window).width() - $(this).outerWidth()) / 2; $(this).css({margin:0, top: (top > 0 ? top : 0)+'px', left: (left > 0 ? left : 0)+'px'}); }); } }); })(jQuery); function debounce(f, delay) { var timeout = null; return function() { var obj = this; var args = arguments; function delayed () { f.apply(obj, args); timeout = null; } if (timeout) clearTimeout(timeout); timeout = setTimeout(delayed, delay); } } rabbitmq-server-3.2.4/plugins-src/rabbitmq-management/priv/www/js/excanvas.min.js0000644000000000000000000004573012305126066026666 0ustar rootrootif(!document.createElement("canvas").getContext){(function(){var z=Math;var K=z.round;var J=z.sin;var U=z.cos;var b=z.abs;var k=z.sqrt;var D=10;var F=D/2;function T(){return this.context_||(this.context_=new W(this))}var O=Array.prototype.slice;function G(i,j,m){var Z=O.call(arguments,2);return function(){return i.apply(j,Z.concat(O.call(arguments)))}}function AD(Z){return String(Z).replace(/&/g,"&").replace(/"/g,""")}function r(i){if(!i.namespaces.g_vml_){i.namespaces.add("g_vml_","urn:schemas-microsoft-com:vml","#default#VML")}if(!i.namespaces.g_o_){i.namespaces.add("g_o_","urn:schemas-microsoft-com:office:office","#default#VML")}if(!i.styleSheets.ex_canvas_){var Z=i.createStyleSheet();Z.owningElement.id="ex_canvas_";Z.cssText="canvas{display:inline-block;overflow:hidden;text-align:left;width:300px;height:150px}"}}r(document);var E={init:function(Z){if(/MSIE/.test(navigator.userAgent)&&!window.opera){var i=Z||document;i.createElement("canvas");i.attachEvent("onreadystatechange",G(this.init_,this,i))}},init_:function(m){var j=m.getElementsByTagName("canvas");for(var Z=0;Z1){j--}if(6*j<1){return i+(Z-i)*6*j}else{if(2*j<1){return Z}else{if(3*j<2){return i+(Z-i)*(2/3-j)*6}else{return i}}}}function Y(Z){var AE,p=1;Z=String(Z);if(Z.charAt(0)=="#"){AE=Z}else{if(/^rgb/.test(Z)){var m=g(Z);var AE="#",AF;for(var j=0;j<3;j++){if(m[j].indexOf("%")!=-1){AF=Math.floor(C(m[j])*255)}else{AF=Number(m[j])}AE+=I[N(AF,0,255)]}p=m[3]}else{if(/^hsl/.test(Z)){var m=g(Z);AE=c(m);p=m[3]}else{AE=B[Z]||Z}}}return{color:AE,alpha:p}}var L={style:"normal",variant:"normal",weight:"normal",size:10,family:"sans-serif"};var f={};function X(Z){if(f[Z]){return f[Z]}var m=document.createElement("div");var j=m.style;try{j.font=Z}catch(i){}return f[Z]={style:j.fontStyle||L.style,variant:j.fontVariant||L.variant,weight:j.fontWeight||L.weight,size:j.fontSize||L.size,family:j.fontFamily||L.family}}function P(j,i){var Z={};for(var AF in j){Z[AF]=j[AF]}var AE=parseFloat(i.currentStyle.fontSize),m=parseFloat(j.size);if(typeof j.size=="number"){Z.size=j.size}else{if(j.size.indexOf("px")!=-1){Z.size=m}else{if(j.size.indexOf("em")!=-1){Z.size=AE*m}else{if(j.size.indexOf("%")!=-1){Z.size=(AE/100)*m}else{if(j.size.indexOf("pt")!=-1){Z.size=m/0.75}else{Z.size=AE}}}}}Z.size*=0.981;return Z}function AA(Z){return Z.style+" "+Z.variant+" "+Z.weight+" "+Z.size+"px "+Z.family}function t(Z){switch(Z){case"butt":return"flat";case"round":return"round";case"square":default:return"square"}}function W(i){this.m_=V();this.mStack_=[];this.aStack_=[];this.currentPath_=[];this.strokeStyle="#000";this.fillStyle="#000";this.lineWidth=1;this.lineJoin="miter";this.lineCap="butt";this.miterLimit=D*1;this.globalAlpha=1;this.font="10px sans-serif";this.textAlign="left";this.textBaseline="alphabetic";this.canvas=i;var Z=i.ownerDocument.createElement("div");Z.style.width=i.clientWidth+"px";Z.style.height=i.clientHeight+"px";Z.style.overflow="hidden";Z.style.position="absolute";i.appendChild(Z);this.element_=Z;this.arcScaleX_=1;this.arcScaleY_=1;this.lineScale_=1}var M=W.prototype;M.clearRect=function(){if(this.textMeasureEl_){this.textMeasureEl_.removeNode(true);this.textMeasureEl_=null}this.element_.innerHTML=""};M.beginPath=function(){this.currentPath_=[]};M.moveTo=function(i,Z){var j=this.getCoords_(i,Z);this.currentPath_.push({type:"moveTo",x:j.x,y:j.y});this.currentX_=j.x;this.currentY_=j.y};M.lineTo=function(i,Z){var j=this.getCoords_(i,Z);this.currentPath_.push({type:"lineTo",x:j.x,y:j.y});this.currentX_=j.x;this.currentY_=j.y};M.bezierCurveTo=function(j,i,AI,AH,AG,AE){var Z=this.getCoords_(AG,AE);var AF=this.getCoords_(j,i);var m=this.getCoords_(AI,AH);e(this,AF,m,Z)};function e(Z,m,j,i){Z.currentPath_.push({type:"bezierCurveTo",cp1x:m.x,cp1y:m.y,cp2x:j.x,cp2y:j.y,x:i.x,y:i.y});Z.currentX_=i.x;Z.currentY_=i.y}M.quadraticCurveTo=function(AG,j,i,Z){var AF=this.getCoords_(AG,j);var AE=this.getCoords_(i,Z);var AH={x:this.currentX_+2/3*(AF.x-this.currentX_),y:this.currentY_+2/3*(AF.y-this.currentY_)};var m={x:AH.x+(AE.x-this.currentX_)/3,y:AH.y+(AE.y-this.currentY_)/3};e(this,AH,m,AE)};M.arc=function(AJ,AH,AI,AE,i,j){AI*=D;var AN=j?"at":"wa";var AK=AJ+U(AE)*AI-F;var AM=AH+J(AE)*AI-F;var Z=AJ+U(i)*AI-F;var AL=AH+J(i)*AI-F;if(AK==Z&&!j){AK+=0.125}var m=this.getCoords_(AJ,AH);var AG=this.getCoords_(AK,AM);var AF=this.getCoords_(Z,AL);this.currentPath_.push({type:AN,x:m.x,y:m.y,radius:AI,xStart:AG.x,yStart:AG.y,xEnd:AF.x,yEnd:AF.y})};M.rect=function(j,i,Z,m){this.moveTo(j,i);this.lineTo(j+Z,i);this.lineTo(j+Z,i+m);this.lineTo(j,i+m);this.closePath()};M.strokeRect=function(j,i,Z,m){var p=this.currentPath_;this.beginPath();this.moveTo(j,i);this.lineTo(j+Z,i);this.lineTo(j+Z,i+m);this.lineTo(j,i+m);this.closePath();this.stroke();this.currentPath_=p};M.fillRect=function(j,i,Z,m){var p=this.currentPath_;this.beginPath();this.moveTo(j,i);this.lineTo(j+Z,i);this.lineTo(j+Z,i+m);this.lineTo(j,i+m);this.closePath();this.fill();this.currentPath_=p};M.createLinearGradient=function(i,m,Z,j){var p=new v("gradient");p.x0_=i;p.y0_=m;p.x1_=Z;p.y1_=j;return p};M.createRadialGradient=function(m,AE,j,i,p,Z){var AF=new v("gradientradial");AF.x0_=m;AF.y0_=AE;AF.r0_=j;AF.x1_=i;AF.y1_=p;AF.r1_=Z;return AF};M.drawImage=function(AO,j){var AH,AF,AJ,AV,AM,AK,AQ,AX;var AI=AO.runtimeStyle.width;var AN=AO.runtimeStyle.height;AO.runtimeStyle.width="auto";AO.runtimeStyle.height="auto";var AG=AO.width;var AT=AO.height;AO.runtimeStyle.width=AI;AO.runtimeStyle.height=AN;if(arguments.length==3){AH=arguments[1];AF=arguments[2];AM=AK=0;AQ=AJ=AG;AX=AV=AT}else{if(arguments.length==5){AH=arguments[1];AF=arguments[2];AJ=arguments[3];AV=arguments[4];AM=AK=0;AQ=AG;AX=AT}else{if(arguments.length==9){AM=arguments[1];AK=arguments[2];AQ=arguments[3];AX=arguments[4];AH=arguments[5];AF=arguments[6];AJ=arguments[7];AV=arguments[8]}else{throw Error("Invalid number of arguments")}}}var AW=this.getCoords_(AH,AF);var m=AQ/2;var i=AX/2;var AU=[];var Z=10;var AE=10;AU.push(" ','","");this.element_.insertAdjacentHTML("BeforeEnd",AU.join(""))};M.stroke=function(AM){var m=10;var AN=10;var AE=5000;var AG={x:null,y:null};var AL={x:null,y:null};for(var AH=0;AHAL.x){AL.x=Z.x}if(AG.y==null||Z.yAL.y){AL.y=Z.y}}}AK.push(' ">');if(!AM){R(this,AK)}else{a(this,AK,AG,AL)}AK.push("");this.element_.insertAdjacentHTML("beforeEnd",AK.join(""))}};function R(j,AE){var i=Y(j.strokeStyle);var m=i.color;var p=i.alpha*j.globalAlpha;var Z=j.lineScale_*j.lineWidth;if(Z<1){p*=Z}AE.push("')}function a(AO,AG,Ah,AP){var AH=AO.fillStyle;var AY=AO.arcScaleX_;var AX=AO.arcScaleY_;var Z=AP.x-Ah.x;var m=AP.y-Ah.y;if(AH instanceof v){var AL=0;var Ac={x:0,y:0};var AU=0;var AK=1;if(AH.type_=="gradient"){var AJ=AH.x0_/AY;var j=AH.y0_/AX;var AI=AH.x1_/AY;var Aj=AH.y1_/AX;var Ag=AO.getCoords_(AJ,j);var Af=AO.getCoords_(AI,Aj);var AE=Af.x-Ag.x;var p=Af.y-Ag.y;AL=Math.atan2(AE,p)*180/Math.PI;if(AL<0){AL+=360}if(AL<0.000001){AL=0}}else{var Ag=AO.getCoords_(AH.x0_,AH.y0_);Ac={x:(Ag.x-Ah.x)/Z,y:(Ag.y-Ah.y)/m};Z/=AY*D;m/=AX*D;var Aa=z.max(Z,m);AU=2*AH.r0_/Aa;AK=2*AH.r1_/Aa-AU}var AS=AH.colors_;AS.sort(function(Ak,i){return Ak.offset-i.offset});var AN=AS.length;var AR=AS[0].color;var AQ=AS[AN-1].color;var AW=AS[0].alpha*AO.globalAlpha;var AV=AS[AN-1].alpha*AO.globalAlpha;var Ab=[];for(var Ae=0;Ae')}else{if(AH instanceof u){if(Z&&m){var AF=-Ah.x;var AZ=-Ah.y;AG.push("')}}else{var Ai=Y(AO.fillStyle);var AT=Ai.color;var Ad=Ai.alpha*AO.globalAlpha;AG.push('')}}}M.fill=function(){this.stroke(true)};M.closePath=function(){this.currentPath_.push({type:"close"})};M.getCoords_=function(j,i){var Z=this.m_;return{x:D*(j*Z[0][0]+i*Z[1][0]+Z[2][0])-F,y:D*(j*Z[0][1]+i*Z[1][1]+Z[2][1])-F}};M.save=function(){var Z={};Q(this,Z);this.aStack_.push(Z);this.mStack_.push(this.m_);this.m_=d(V(),this.m_)};M.restore=function(){if(this.aStack_.length){Q(this.aStack_.pop(),this);this.m_=this.mStack_.pop()}};function H(Z){return isFinite(Z[0][0])&&isFinite(Z[0][1])&&isFinite(Z[1][0])&&isFinite(Z[1][1])&&isFinite(Z[2][0])&&isFinite(Z[2][1])}function y(i,Z,j){if(!H(Z)){return }i.m_=Z;if(j){var p=Z[0][0]*Z[1][1]-Z[0][1]*Z[1][0];i.lineScale_=k(b(p))}}M.translate=function(j,i){var Z=[[1,0,0],[0,1,0],[j,i,1]];y(this,d(Z,this.m_),false)};M.rotate=function(i){var m=U(i);var j=J(i);var Z=[[m,j,0],[-j,m,0],[0,0,1]];y(this,d(Z,this.m_),false)};M.scale=function(j,i){this.arcScaleX_*=j;this.arcScaleY_*=i;var Z=[[j,0,0],[0,i,0],[0,0,1]];y(this,d(Z,this.m_),true)};M.transform=function(p,m,AF,AE,i,Z){var j=[[p,m,0],[AF,AE,0],[i,Z,1]];y(this,d(j,this.m_),true)};M.setTransform=function(AE,p,AG,AF,j,i){var Z=[[AE,p,0],[AG,AF,0],[j,i,1]];y(this,Z,true)};M.drawText_=function(AK,AI,AH,AN,AG){var AM=this.m_,AQ=1000,i=0,AP=AQ,AF={x:0,y:0},AE=[];var Z=P(X(this.font),this.element_);var j=AA(Z);var AR=this.element_.currentStyle;var p=this.textAlign.toLowerCase();switch(p){case"left":case"center":case"right":break;case"end":p=AR.direction=="ltr"?"right":"left";break;case"start":p=AR.direction=="rtl"?"right":"left";break;default:p="left"}switch(this.textBaseline){case"hanging":case"top":AF.y=Z.size/1.75;break;case"middle":break;default:case null:case"alphabetic":case"ideographic":case"bottom":AF.y=-Z.size/2.25;break}switch(p){case"right":i=AQ;AP=0.05;break;case"center":i=AP=AQ/2;break}var AO=this.getCoords_(AI+AF.x,AH+AF.y);AE.push('');if(AG){R(this,AE)}else{a(this,AE,{x:-i,y:0},{x:AP,y:Z.size})}var AL=AM[0][0].toFixed(3)+","+AM[1][0].toFixed(3)+","+AM[0][1].toFixed(3)+","+AM[1][1].toFixed(3)+",0,0";var AJ=K(AO.x/D)+","+K(AO.y/D);AE.push('','','');this.element_.insertAdjacentHTML("beforeEnd",AE.join(""))};M.fillText=function(j,Z,m,i){this.drawText_(j,Z,m,i,false)};M.strokeText=function(j,Z,m,i){this.drawText_(j,Z,m,i,true)};M.measureText=function(j){if(!this.textMeasureEl_){var Z='';this.element_.insertAdjacentHTML("beforeEnd",Z);this.textMeasureEl_=this.element_.lastChild}var i=this.element_.ownerDocument;this.textMeasureEl_.innerHTML="";this.textMeasureEl_.style.font=this.font;this.textMeasureEl_.appendChild(i.createTextNode(j));return{width:this.textMeasureEl_.offsetWidth}};M.clip=function(){};M.arcTo=function(){};M.createPattern=function(i,Z){return new u(i,Z)};function v(Z){this.type_=Z;this.x0_=0;this.y0_=0;this.r0_=0;this.x1_=0;this.y1_=0;this.r1_=0;this.colors_=[]}v.prototype.addColorStop=function(i,Z){Z=Y(Z);this.colors_.push({offset:i,color:Z.color,alpha:Z.alpha})};function u(i,Z){q(i);switch(Z){case"repeat":case null:case"":this.repetition_="repeat";break;case"repeat-x":case"repeat-y":case"no-repeat":this.repetition_=Z;break;default:n("SYNTAX_ERR")}this.src_=i.src;this.width_=i.width;this.height_=i.height}function n(Z){throw new o(Z)}function q(Z){if(!Z||Z.nodeType!=1||Z.tagName!="IMG"){n("TYPE_MISMATCH_ERR")}if(Z.readyState!="complete"){n("INVALID_STATE_ERR")}}function o(Z){this.code=this[Z];this.message=Z+": DOM Exception "+this.code}var x=o.prototype=new Error;x.INDEX_SIZE_ERR=1;x.DOMSTRING_SIZE_ERR=2;x.HIERARCHY_REQUEST_ERR=3;x.WRONG_DOCUMENT_ERR=4;x.INVALID_CHARACTER_ERR=5;x.NO_DATA_ALLOWED_ERR=6;x.NO_MODIFICATION_ALLOWED_ERR=7;x.NOT_FOUND_ERR=8;x.NOT_SUPPORTED_ERR=9;x.INUSE_ATTRIBUTE_ERR=10;x.INVALID_STATE_ERR=11;x.SYNTAX_ERR=12;x.INVALID_MODIFICATION_ERR=13;x.NAMESPACE_ERR=14;x.INVALID_ACCESS_ERR=15;x.VALIDATION_ERR=16;x.TYPE_MISMATCH_ERR=17;G_vmlCanvasManager=E;CanvasRenderingContext2D=W;CanvasGradient=v;CanvasPattern=u;DOMException=o})()}; rabbitmq-server-3.2.4/plugins-src/rabbitmq-management/priv/www/js/base64.js0000644000000000000000000001150312305126066025347 0ustar rootroot/* * Copyright (c) 2010 Nick Galbreath * http://code.google.com/p/stringencoders/source/browse/#svn/trunk/javascript * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. */ /* base64 encode/decode compatible with window.btoa/atob * * window.atob/btoa is a Firefox extension to convert binary data (the "b") * to base64 (ascii, the "a"). * * It is also found in Safari and Chrome. It is not available in IE. * * if (!window.btoa) window.btoa = base64.encode * if (!window.atob) window.atob = base64.decode * * The original spec's for atob/btoa are a bit lacking * https://developer.mozilla.org/en/DOM/window.atob * https://developer.mozilla.org/en/DOM/window.btoa * * window.btoa and base64.encode takes a string where charCodeAt is [0,255] * If any character is not [0,255], then an exception is thrown. * * window.atob and base64.decode take a base64-encoded string * If the input length is not a multiple of 4, or contains invalid characters * then an exception is thrown. */ base64 = {}; base64.PADCHAR = '='; base64.ALPHA = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'; base64.getbyte64 = function(s,i) { // This is oddly fast, except on Chrome/V8. // Minimal or no improvement in performance by using a // object with properties mapping chars to value (eg. 'A': 0) var idx = base64.ALPHA.indexOf(s.charAt(i)); if (idx == -1) { throw "Cannot decode base64"; } return idx; } base64.decode = function(s) { // convert to string s = "" + s; var getbyte64 = base64.getbyte64; var pads, i, b10; var imax = s.length if (imax == 0) { return s; } if (imax % 4 != 0) { throw "Cannot decode base64"; } pads = 0 if (s.charAt(imax -1) == base64.PADCHAR) { pads = 1; if (s.charAt(imax -2) == base64.PADCHAR) { pads = 2; } // either way, we want to ignore this last block imax -= 4; } var x = []; for (i = 0; i < imax; i += 4) { b10 = (getbyte64(s,i) << 18) | (getbyte64(s,i+1) << 12) | (getbyte64(s,i+2) << 6) | getbyte64(s,i+3); x.push(String.fromCharCode(b10 >> 16, (b10 >> 8) & 0xff, b10 & 0xff)); } switch (pads) { case 1: b10 = (getbyte64(s,i) << 18) | (getbyte64(s,i+1) << 12) | (getbyte64(s,i+2) << 6) x.push(String.fromCharCode(b10 >> 16, (b10 >> 8) & 0xff)); break; case 2: b10 = (getbyte64(s,i) << 18) | (getbyte64(s,i+1) << 12); x.push(String.fromCharCode(b10 >> 16)); break; } return x.join(''); } base64.getbyte = function(s,i) { var x = s.charCodeAt(i); if (x > 255) { throw "INVALID_CHARACTER_ERR: DOM Exception 5"; } return x; } base64.encode = function(s) { if (arguments.length != 1) { throw "SyntaxError: Not enough arguments"; } var padchar = base64.PADCHAR; var alpha = base64.ALPHA; var getbyte = base64.getbyte; var i, b10; var x = []; // convert to string s = "" + s; var imax = s.length - s.length % 3; if (s.length == 0) { return s; } for (i = 0; i < imax; i += 3) { b10 = (getbyte(s,i) << 16) | (getbyte(s,i+1) << 8) | getbyte(s,i+2); x.push(alpha.charAt(b10 >> 18)); x.push(alpha.charAt((b10 >> 12) & 0x3F)); x.push(alpha.charAt((b10 >> 6) & 0x3f)); x.push(alpha.charAt(b10 & 0x3f)); } switch (s.length - imax) { case 1: b10 = getbyte(s,i) << 16; x.push(alpha.charAt(b10 >> 18) + alpha.charAt((b10 >> 12) & 0x3F) + padchar + padchar); break; case 2: b10 = (getbyte(s,i) << 16) | (getbyte(s,i+1) << 8); x.push(alpha.charAt(b10 >> 18) + alpha.charAt((b10 >> 12) & 0x3F) + alpha.charAt((b10 >> 6) & 0x3f) + padchar); break; } return x.join(''); } rabbitmq-server-3.2.4/plugins-src/rabbitmq-management/priv/www/js/jquery-1.6.4.min.js0000644000000000000000000026302612305126066027041 0ustar rootroot/*! jQuery v1.6.4 http://jquery.com/ | http://jquery.org/license */ (function(a,b){function cu(a){return f.isWindow(a)?a:a.nodeType===9?a.defaultView||a.parentWindow:!1}function cr(a){if(!cg[a]){var b=c.body,d=f("<"+a+">").appendTo(b),e=d.css("display");d.remove();if(e==="none"||e===""){ch||(ch=c.createElement("iframe"),ch.frameBorder=ch.width=ch.height=0),b.appendChild(ch);if(!ci||!ch.createElement)ci=(ch.contentWindow||ch.contentDocument).document,ci.write((c.compatMode==="CSS1Compat"?"":"")+""),ci.close();d=ci.createElement(a),ci.body.appendChild(d),e=f.css(d,"display"),b.removeChild(ch)}cg[a]=e}return cg[a]}function cq(a,b){var c={};f.each(cm.concat.apply([],cm.slice(0,b)),function(){c[this]=a});return c}function cp(){cn=b}function co(){setTimeout(cp,0);return cn=f.now()}function cf(){try{return new a.ActiveXObject("Microsoft.XMLHTTP")}catch(b){}}function ce(){try{return new a.XMLHttpRequest}catch(b){}}function b$(a,c){a.dataFilter&&(c=a.dataFilter(c,a.dataType));var d=a.dataTypes,e={},g,h,i=d.length,j,k=d[0],l,m,n,o,p;for(g=1;g0){c!=="border"&&f.each(e,function(){c||(d-=parseFloat(f.css(a,"padding"+this))||0),c==="margin"?d+=parseFloat(f.css(a,c+this))||0:d-=parseFloat(f.css(a,"border"+this+"Width"))||0});return d+"px"}d=bv(a,b,b);if(d<0||d==null)d=a.style[b]||0;d=parseFloat(d)||0,c&&f.each(e,function(){d+=parseFloat(f.css(a,"padding"+this))||0,c!=="padding"&&(d+=parseFloat(f.css(a,"border"+this+"Width"))||0),c==="margin"&&(d+=parseFloat(f.css(a,c+this))||0)});return d+"px"}function bl(a,b){b.src?f.ajax({url:b.src,async:!1,dataType:"script"}):f.globalEval((b.text||b.textContent||b.innerHTML||"").replace(bd,"/*$0*/")),b.parentNode&&b.parentNode.removeChild(b)}function bk(a){f.nodeName(a,"input")?bj(a):"getElementsByTagName"in a&&f.grep(a.getElementsByTagName("input"),bj)}function bj(a){if(a.type==="checkbox"||a.type==="radio")a.defaultChecked=a.checked}function bi(a){return"getElementsByTagName"in a?a.getElementsByTagName("*"):"querySelectorAll"in a?a.querySelectorAll("*"):[]}function bh(a,b){var c;if(b.nodeType===1){b.clearAttributes&&b.clearAttributes(),b.mergeAttributes&&b.mergeAttributes(a),c=b.nodeName.toLowerCase();if(c==="object")b.outerHTML=a.outerHTML;else if(c!=="input"||a.type!=="checkbox"&&a.type!=="radio"){if(c==="option")b.selected=a.defaultSelected;else if(c==="input"||c==="textarea")b.defaultValue=a.defaultValue}else a.checked&&(b.defaultChecked=b.checked=a.checked),b.value!==a.value&&(b.value=a.value);b.removeAttribute(f.expando)}}function bg(a,b){if(b.nodeType===1&&!!f.hasData(a)){var c=f.expando,d=f.data(a),e=f.data(b,d);if(d=d[c]){var g=d.events;e=e[c]=f.extend({},d);if(g){delete e.handle,e.events={};for(var h in g)for(var i=0,j=g[h].length;i=0===c})}function U(a){return!a||!a.parentNode||a.parentNode.nodeType===11}function M(a,b){return(a&&a!=="*"?a+".":"")+b.replace(y,"`").replace(z,"&")}function L(a){var b,c,d,e,g,h,i,j,k,l,m,n,o,p=[],q=[],r=f._data(this,"events");if(!(a.liveFired===this||!r||!r.live||a.target.disabled||a.button&&a.type==="click")){a.namespace&&(n=new RegExp("(^|\\.)"+a.namespace.split(".").join("\\.(?:.*\\.)?")+"(\\.|$)")),a.liveFired=this;var s=r.live.slice(0);for(i=0;ic)break;a.currentTarget=e.elem,a.data=e.handleObj.data,a.handleObj=e.handleObj,o=e.handleObj.origHandler.apply(e.elem,arguments);if(o===!1||a.isPropagationStopped()){c=e.level,o===!1&&(b=!1);if(a.isImmediatePropagationStopped())break}}return b}}function J(a,c,d){var e=f.extend({},d[0]);e.type=a,e.originalEvent={},e.liveFired=b,f.event.handle.call(c,e),e.isDefaultPrevented()&&d[0].preventDefault()}function D(){return!0}function C(){return!1}function m(a,c,d){var e=c+"defer",g=c+"queue",h=c+"mark",i=f.data(a,e,b,!0);i&&(d==="queue"||!f.data(a,g,b,!0))&&(d==="mark"||!f.data(a,h,b,!0))&&setTimeout(function(){!f.data(a,g,b,!0)&&!f.data(a,h,b,!0)&&(f.removeData(a,e,!0),i.resolve())},0)}function l(a){for(var b in a)if(b!=="toJSON")return!1;return!0}function k(a,c,d){if(d===b&&a.nodeType===1){var e="data-"+c.replace(j,"-$1").toLowerCase();d=a.getAttribute(e);if(typeof d=="string"){try{d=d==="true"?!0:d==="false"?!1:d==="null"?null:f.isNaN(d)?i.test(d)?f.parseJSON(d):d:parseFloat(d)}catch(g){}f.data(a,c,d)}else d=b}return d}var c=a.document,d=a.navigator,e=a.location,f=function(){function K(){if(!e.isReady){try{c.documentElement.doScroll("left")}catch(a){setTimeout(K,1);return}e.ready()}}var e=function(a,b){return new e.fn.init(a,b,h)},f=a.jQuery,g=a.$,h,i=/^(?:[^#<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/,j=/\S/,k=/^\s+/,l=/\s+$/,m=/\d/,n=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,o=/^[\],:{}\s]*$/,p=/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,q=/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,r=/(?:^|:|,)(?:\s*\[)+/g,s=/(webkit)[ \/]([\w.]+)/,t=/(opera)(?:.*version)?[ \/]([\w.]+)/,u=/(msie) ([\w.]+)/,v=/(mozilla)(?:.*? rv:([\w.]+))?/,w=/-([a-z]|[0-9])/ig,x=/^-ms-/,y=function(a,b){return(b+"").toUpperCase()},z=d.userAgent,A,B,C,D=Object.prototype.toString,E=Object.prototype.hasOwnProperty,F=Array.prototype.push,G=Array.prototype.slice,H=String.prototype.trim,I=Array.prototype.indexOf,J={};e.fn=e.prototype={constructor:e,init:function(a,d,f){var g,h,j,k;if(!a)return this;if(a.nodeType){this.context=this[0]=a,this.length=1;return this}if(a==="body"&&!d&&c.body){this.context=c,this[0]=c.body,this.selector=a,this.length=1;return this}if(typeof a=="string"){a.charAt(0)!=="<"||a.charAt(a.length-1)!==">"||a.length<3?g=i.exec(a):g=[null,a,null];if(g&&(g[1]||!d)){if(g[1]){d=d instanceof e?d[0]:d,k=d?d.ownerDocument||d:c,j=n.exec(a),j?e.isPlainObject(d)?(a=[c.createElement(j[1])],e.fn.attr.call(a,d,!0)):a=[k.createElement(j[1])]:(j=e.buildFragment([g[1]],[k]),a=(j.cacheable?e.clone(j.fragment):j.fragment).childNodes);return e.merge(this,a)}h=c.getElementById(g[2]);if(h&&h.parentNode){if(h.id!==g[2])return f.find(a);this.length=1,this[0]=h}this.context=c,this.selector=a;return this}return!d||d.jquery?(d||f).find(a):this.constructor(d).find(a)}if(e.isFunction(a))return f.ready(a);a.selector!==b&&(this.selector=a.selector,this.context=a.context);return e.makeArray(a,this)},selector:"",jquery:"1.6.4",length:0,size:function(){return this.length},toArray:function(){return G.call(this,0)},get:function(a){return a==null?this.toArray():a<0?this[this.length+a]:this[a]},pushStack:function(a,b,c){var d=this.constructor();e.isArray(a)?F.apply(d,a):e.merge(d,a),d.prevObject=this,d.context=this.context,b==="find"?d.selector=this.selector+(this.selector?" ":"")+c:b&&(d.selector=this.selector+"."+b+"("+c+")");return d},each:function(a,b){return e.each(this,a,b)},ready:function(a){e.bindReady(),B.done(a);return this},eq:function(a){return a===-1?this.slice(a):this.slice(a,+a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(G.apply(this,arguments),"slice",G.call(arguments).join(","))},map:function(a){return this.pushStack(e.map(this,function(b,c){return a.call(b,c,b)}))},end:function(){return this.prevObject||this.constructor(null)},push:F,sort:[].sort,splice:[].splice},e.fn.init.prototype=e.fn,e.extend=e.fn.extend=function(){var a,c,d,f,g,h,i=arguments[0]||{},j=1,k=arguments.length,l=!1;typeof i=="boolean"&&(l=i,i=arguments[1]||{},j=2),typeof i!="object"&&!e.isFunction(i)&&(i={}),k===j&&(i=this,--j);for(;j0)return;B.resolveWith(c,[e]),e.fn.trigger&&e(c).trigger("ready").unbind("ready")}},bindReady:function(){if(!B){B=e._Deferred();if(c.readyState==="complete")return setTimeout(e.ready,1);if(c.addEventListener)c.addEventListener("DOMContentLoaded",C,!1),a.addEventListener("load",e.ready,!1);else if(c.attachEvent){c.attachEvent("onreadystatechange",C),a.attachEvent("onload",e.ready);var b=!1;try{b=a.frameElement==null}catch(d){}c.documentElement.doScroll&&b&&K()}}},isFunction:function(a){return e.type(a)==="function"},isArray:Array.isArray||function(a){return e.type(a)==="array"},isWindow:function(a){return a&&typeof a=="object"&&"setInterval"in a},isNaN:function(a){return a==null||!m.test(a)||isNaN(a)},type:function(a){return a==null?String(a):J[D.call(a)]||"object"},isPlainObject:function(a){if(!a||e.type(a)!=="object"||a.nodeType||e.isWindow(a))return!1;try{if(a.constructor&&!E.call(a,"constructor")&&!E.call(a.constructor.prototype,"isPrototypeOf"))return!1}catch(c){return!1}var d;for(d in a);return d===b||E.call(a,d)},isEmptyObject:function(a){for(var b in a)return!1;return!0},error:function(a){throw a},parseJSON:function(b){if(typeof b!="string"||!b)return null;b=e.trim(b);if(a.JSON&&a.JSON.parse)return a.JSON.parse(b);if(o.test(b.replace(p,"@").replace(q,"]").replace(r,"")))return(new Function("return "+b))();e.error("Invalid JSON: "+b)},parseXML:function(c){var d,f;try{a.DOMParser?(f=new DOMParser,d=f.parseFromString(c,"text/xml")):(d=new ActiveXObject("Microsoft.XMLDOM"),d.async="false",d.loadXML(c))}catch(g){d=b}(!d||!d.documentElement||d.getElementsByTagName("parsererror").length)&&e.error("Invalid XML: "+c);return d},noop:function(){},globalEval:function(b){b&&j.test(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},camelCase:function(a){return a.replace(x,"ms-").replace(w,y)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toUpperCase()===b.toUpperCase()},each:function(a,c,d){var f,g=0,h=a.length,i=h===b||e.isFunction(a);if(d){if(i){for(f in a)if(c.apply(a[f],d)===!1)break}else for(;g0&&a[0]&&a[j-1]||j===0||e.isArray(a));if(k)for(;i1?h.call(arguments,0):c,--e||g.resolveWith(g,h.call(b,0))}}var b=arguments,c=0,d=b.length,e=d,g=d<=1&&a&&f.isFunction(a.promise)?a:f.Deferred();if(d>1){for(;c
    a",d=a.getElementsByTagName("*"),e=a.getElementsByTagName("a")[0];if(!d||!d.length||!e)return{};g=c.createElement("select"),h=g.appendChild(c.createElement("option")),i=a.getElementsByTagName("input")[0],k={leadingWhitespace:a.firstChild.nodeType===3,tbody:!a.getElementsByTagName("tbody").length,htmlSerialize:!!a.getElementsByTagName("link").length,style:/top/.test(e.getAttribute("style")),hrefNormalized:e.getAttribute("href")==="/a",opacity:/^0.55$/.test(e.style.opacity),cssFloat:!!e.style.cssFloat,checkOn:i.value==="on",optSelected:h.selected,getSetAttribute:a.className!=="t",submitBubbles:!0,changeBubbles:!0,focusinBubbles:!1,deleteExpando:!0,noCloneEvent:!0,inlineBlockNeedsLayout:!1,shrinkWrapBlocks:!1,reliableMarginRight:!0},i.checked=!0,k.noCloneChecked=i.cloneNode(!0).checked,g.disabled=!0,k.optDisabled=!h.disabled;try{delete a.test}catch(v){k.deleteExpando=!1}!a.addEventListener&&a.attachEvent&&a.fireEvent&&(a.attachEvent("onclick",function(){k.noCloneEvent=!1}),a.cloneNode(!0).fireEvent("onclick")),i=c.createElement("input"),i.value="t",i.setAttribute("type","radio"),k.radioValue=i.value==="t",i.setAttribute("checked","checked"),a.appendChild(i),l=c.createDocumentFragment(),l.appendChild(a.firstChild),k.checkClone=l.cloneNode(!0).cloneNode(!0).lastChild.checked,a.innerHTML="",a.style.width=a.style.paddingLeft="1px",m=c.getElementsByTagName("body")[0],o=c.createElement(m?"div":"body"),p={visibility:"hidden",width:0,height:0,border:0,margin:0,background:"none"},m&&f.extend(p,{position:"absolute",left:"-1000px",top:"-1000px"});for(t in p)o.style[t]=p[t];o.appendChild(a),n=m||b,n.insertBefore(o,n.firstChild),k.appendChecked=i.checked,k.boxModel=a.offsetWidth===2,"zoom"in a.style&&(a.style.display="inline",a.style.zoom=1,k.inlineBlockNeedsLayout=a.offsetWidth===2,a.style.display="",a.innerHTML="
    ",k.shrinkWrapBlocks=a.offsetWidth!==2),a.innerHTML="
    t
    ",q=a.getElementsByTagName("td"),u=q[0].offsetHeight===0,q[0].style.display="",q[1].style.display="none",k.reliableHiddenOffsets=u&&q[0].offsetHeight===0,a.innerHTML="",c.defaultView&&c.defaultView.getComputedStyle&&(j=c.createElement("div"),j.style.width="0",j.style.marginRight="0",a.appendChild(j),k.reliableMarginRight=(parseInt((c.defaultView.getComputedStyle(j,null)||{marginRight:0}).marginRight,10)||0)===0),o.innerHTML="",n.removeChild(o);if(a.attachEvent)for(t in{submit:1,change:1,focusin:1})s="on"+t,u=s in a,u||(a.setAttribute(s,"return;"),u=typeof a[s]=="function"),k[t+"Bubbles"]=u;o=l=g=h=m=j=a=i=null;return k}(),f.boxModel=f.support.boxModel;var i=/^(?:\{.*\}|\[.*\])$/,j=/([A-Z])/g;f.extend({cache:{},uuid:0,expando:"jQuery"+(f.fn.jquery+Math.random()).replace(/\D/g,""),noData:{embed:!0,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:!0},hasData:function(a){a=a.nodeType?f.cache[a[f.expando]]:a[f.expando];return!!a&&!l(a)},data:function(a,c,d,e){if(!!f.acceptData(a)){var g,h,i=f.expando,j=typeof c=="string",k=a.nodeType,l=k?f.cache:a,m=k?a[f.expando]:a[f.expando]&&f.expando;if((!m||e&&m&&l[m]&&!l[m][i])&&j&&d===b)return;m||(k?a[f.expando]=m=++f.uuid:m=f.expando),l[m]||(l[m]={},k||(l[m].toJSON=f.noop));if(typeof c=="object"||typeof c=="function")e?l[m][i]=f.extend(l[m][i],c):l[m]=f.extend(l[m],c);g=l[m],e&&(g[i]||(g[i]={}),g=g[i]),d!==b&&(g[f.camelCase(c)]=d);if(c==="events"&&!g[c])return g[i]&&g[i].events;j?(h=g[c],h==null&&(h=g[f.camelCase(c)])):h=g;return h}},removeData:function(a,b,c){if(!!f.acceptData(a)){var d,e=f.expando,g=a.nodeType,h=g?f.cache:a,i=g?a[f.expando]:f.expando;if(!h[i])return;if(b){d=c?h[i][e]:h[i];if(d){d[b]||(b=f.camelCase(b)),delete d[b];if(!l(d))return}}if(c){delete h[i][e];if(!l(h[i]))return}var j=h[i][e];f.support.deleteExpando||!h.setInterval?delete h[i]:h[i]=null,j?(h[i]={},g||(h[i].toJSON=f.noop),h[i][e]=j):g&&(f.support.deleteExpando?delete a[f.expando]:a.removeAttribute?a.removeAttribute(f.expando):a[f.expando]=null)}},_data:function(a,b,c){return f.data(a,b,c,!0)},acceptData:function(a){if(a.nodeName){var b=f.noData[a.nodeName.toLowerCase()];if(b)return b!==!0&&a.getAttribute("classid")===b}return!0}}),f.fn.extend({data:function(a,c){var d=null;if(typeof a=="undefined"){if(this.length){d=f.data(this[0]);if(this[0].nodeType===1){var e=this[0].attributes,g;for(var h=0,i=e.length;h-1)return!0;return!1},val:function(a){var c,d,e=this[0];if(!arguments.length){if(e){c=f.valHooks[e.nodeName.toLowerCase()]||f.valHooks[e.type];if(c&&"get"in c&&(d=c.get(e,"value"))!==b)return d;d=e.value;return typeof d=="string"?d.replace(p,""):d==null?"":d}return b}var g=f.isFunction(a);return this.each(function(d){var e=f(this),h;if(this.nodeType===1){g?h=a.call(this,d,e.val()):h=a,h==null?h="":typeof h=="number"?h+="":f.isArray(h)&&(h=f.map(h,function(a){return a==null?"":a+""})),c=f.valHooks[this.nodeName.toLowerCase()]||f.valHooks[this.type];if(!c||!("set"in c)||c.set(this,h,"value")===b)this.value=h}})}}),f.extend({valHooks:{option:{get:function(a){var b=a.attributes.value;return!b||b.specified?a.value:a.text}},select:{get:function(a){var b,c=a.selectedIndex,d=[],e=a.options,g=a.type==="select-one";if(c<0)return null;for(var h=g?c:0,i=g?c+1:e.length;h=0}),c.length||(a.selectedIndex=-1);return c}}},attrFn:{val:!0,css:!0,html:!0,text:!0,data:!0,width:!0,height:!0,offset:!0},attrFix:{tabindex:"tabIndex"},attr:function(a,c,d,e){var g=a.nodeType;if(!a||g===3||g===8||g===2)return b;if(e&&c in f.attrFn)return f(a)[c](d);if(!("getAttribute"in a))return f.prop(a,c,d);var h,i,j=g!==1||!f.isXMLDoc(a);j&&(c=f.attrFix[c]||c,i=f.attrHooks[c],i||(t.test(c)?i=v:u&&(i=u)));if(d!==b){if(d===null){f.removeAttr(a,c);return b}if(i&&"set"in i&&j&&(h=i.set(a,d,c))!==b)return h;a.setAttribute(c,""+d);return d}if(i&&"get"in i&&j&&(h=i.get(a,c))!==null)return h;h=a.getAttribute(c);return h===null?b:h},removeAttr:function(a,b){var c;a.nodeType===1&&(b=f.attrFix[b]||b,f.attr(a,b,""),a.removeAttribute(b),t.test(b)&&(c=f.propFix[b]||b)in a&&(a[c]=!1))},attrHooks:{type:{set:function(a,b){if(q.test(a.nodeName)&&a.parentNode)f.error("type property can't be changed");else if(!f.support.radioValue&&b==="radio"&&f.nodeName(a,"input")){var c=a.value;a.setAttribute("type",b),c&&(a.value=c);return b}}},value:{get:function(a,b){if(u&&f.nodeName(a,"button"))return u.get(a,b);return b in a?a.value:null},set:function(a,b,c){if(u&&f.nodeName(a,"button"))return u.set(a,b,c);a.value=b}}},propFix:{tabindex:"tabIndex",readonly:"readOnly","for":"htmlFor","class":"className",maxlength:"maxLength",cellspacing:"cellSpacing",cellpadding:"cellPadding",rowspan:"rowSpan",colspan:"colSpan",usemap:"useMap",frameborder:"frameBorder",contenteditable:"contentEditable"},prop:function(a,c,d){var e=a.nodeType;if(!a||e===3||e===8||e===2)return b;var g,h,i=e!==1||!f.isXMLDoc(a);i&&(c=f.propFix[c]||c,h=f.propHooks[c]);return d!==b?h&&"set"in h&&(g=h.set(a,d,c))!==b?g:a[c]=d:h&&"get"in h&&(g=h.get(a,c))!==null?g:a[c]},propHooks:{tabIndex:{get:function(a){var c=a.getAttributeNode("tabindex");return c&&c.specified?parseInt(c.value,10):r.test(a.nodeName)||s.test(a.nodeName)&&a.href?0:b}}}}),f.attrHooks.tabIndex=f.propHooks.tabIndex,v={get:function(a,c){var d;return f.prop(a,c)===!0||(d=a.getAttributeNode(c))&&d.nodeValue!==!1?c.toLowerCase():b},set:function(a,b,c){var d;b===!1?f.removeAttr(a,c):(d=f.propFix[c]||c,d in a&&(a[d]=!0),a.setAttribute(c,c.toLowerCase()));return c}},f.support.getSetAttribute||(u=f.valHooks.button={get:function(a,c){var d;d=a.getAttributeNode(c);return d&&d.nodeValue!==""?d.nodeValue:b},set:function(a,b,d){var e=a.getAttributeNode(d);e||(e=c.createAttribute(d),a.setAttributeNode(e));return e.nodeValue=b+""}},f.each(["width","height"],function(a,b){f.attrHooks[b]=f.extend(f.attrHooks[b],{set:function(a,c){if(c===""){a.setAttribute(b,"auto");return c}}})})),f.support.hrefNormalized||f.each(["href","src","width","height"],function(a,c){f.attrHooks[c]=f.extend(f.attrHooks[c],{get:function(a){var d=a.getAttribute(c,2);return d===null?b:d}})}),f.support.style||(f.attrHooks.style={get:function(a){return a.style.cssText.toLowerCase()||b},set:function(a,b){return a.style.cssText=""+b}}),f.support.optSelected||(f.propHooks.selected=f.extend(f.propHooks.selected,{get:function(a){var b=a.parentNode;b&&(b.selectedIndex,b.parentNode&&b.parentNode.selectedIndex);return null}})),f.support.checkOn||f.each(["radio","checkbox"],function(){f.valHooks[this]={get:function(a){return a.getAttribute("value")===null?"on":a.value}}}),f.each(["radio","checkbox"],function(){f.valHooks[this]=f.extend(f.valHooks[this],{set:function(a,b){if(f.isArray(b))return a.checked=f.inArray(f(a).val(),b)>=0}})});var w=/\.(.*)$/,x=/^(?:textarea|input|select)$/i,y=/\./g,z=/ /g,A=/[^\w\s.|`]/g,B=function(a){return a.replace(A,"\\$&")};f.event={add:function(a,c,d,e){if(a.nodeType!==3&&a.nodeType!==8){if(d===!1)d=C;else if(!d)return;var g,h;d.handler&&(g=d,d=g.handler),d.guid||(d.guid=f.guid++);var i=f._data(a);if(!i)return;var j=i.events,k=i.handle;j||(i.events=j={}),k||(i.handle=k=function(a){return typeof f!="undefined"&&(!a||f.event.triggered!==a.type)?f.event.handle.apply(k.elem,arguments):b}),k.elem=a,c=c.split(" ");var l,m=0,n;while(l=c[m++]){h=g?f.extend({},g):{handler:d,data:e},l.indexOf(".")>-1?(n=l.split("."),l=n.shift(),h.namespace=n.slice(0).sort().join(".")):(n=[],h.namespace=""),h.type=l,h.guid||(h.guid=d.guid);var o=j[l],p=f.event.special[l]||{};if(!o){o=j[l]=[];if(!p.setup||p.setup.call(a,e,n,k)===!1)a.addEventListener?a.addEventListener(l,k,!1):a.attachEvent&&a.attachEvent("on"+l,k)}p.add&&(p.add.call(a,h),h.handler.guid||(h.handler.guid=d.guid)),o.push(h),f.event.global[l]=!0}a=null}},global:{},remove:function(a,c,d,e){if(a.nodeType!==3&&a.nodeType!==8){d===!1&&(d=C);var g,h,i,j,k=0,l,m,n,o,p,q,r,s=f.hasData(a)&&f._data(a),t=s&&s.events;if(!s||!t)return;c&&c.type&&(d=c.handler,c=c.type);if(!c||typeof c=="string"&&c.charAt(0)==="."){c=c||"";for(h in t)f.event.remove(a,h+c);return}c=c.split(" ");while(h=c[k++]){r=h,q=null,l=h.indexOf(".")<0,m=[],l||(m=h.split("."),h=m.shift(),n=new RegExp("(^|\\.)"+f.map(m.slice(0).sort(),B).join("\\.(?:.*\\.)?")+"(\\.|$)")),p=t[h];if(!p)continue;if(!d){for(j=0;j=0&&(h=h.slice(0,-1),j=!0),h.indexOf(".")>=0&&(i=h.split("."),h=i.shift(),i.sort());if(!!e&&!f.event.customEvent[h]||!!f.event.global[h]){c=typeof c=="object"?c[f.expando]?c:new f.Event(h,c):new f.Event(h),c.type=h,c.exclusive=j,c.namespace=i.join("."),c.namespace_re=new RegExp("(^|\\.)"+i.join("\\.(?:.*\\.)?")+"(\\.|$)");if(g||!e)c.preventDefault(),c.stopPropagation();if(!e){f.each(f.cache,function(){var a=f.expando,b=this[a];b&&b.events&&b.events[h]&&f.event.trigger(c,d,b.handle.elem)});return}if(e.nodeType===3||e.nodeType===8)return;c.result=b,c.target=e,d=d!=null?f.makeArray(d):[],d.unshift(c);var k=e,l=h.indexOf(":")<0?"on"+h:"";do{var m=f._data(k,"handle");c.currentTarget=k,m&&m.apply(k,d),l&&f.acceptData(k)&&k[l]&&k[l].apply(k,d)===!1&&(c.result=!1,c.preventDefault()),k=k.parentNode||k.ownerDocument||k===c.target.ownerDocument&&a}while(k&&!c.isPropagationStopped());if(!c.isDefaultPrevented()){var n,o=f.event.special[h]||{};if((!o._default||o._default.call(e.ownerDocument,c)===!1)&&(h!=="click"||!f.nodeName(e,"a"))&&f.acceptData(e)){try{l&&e[h]&&(n=e[l],n&&(e[l]=null),f.event.triggered=h,e[h]())}catch(p){}n&&(e[l]=n),f.event.triggered=b}}return c.result}},handle:function(c){c=f.event.fix(c||a.event);var d=((f._data(this,"events")||{})[c.type]||[]).slice(0),e=!c.exclusive&&!c.namespace,g=Array.prototype.slice.call(arguments,0);g[0]=c,c.currentTarget=this;for(var h=0,i=d.length;h-1?f.map(a.options,function(a){return a.selected}).join("-"):"":f.nodeName(a,"select")&&(c=a.selectedIndex);return c},I=function(c){var d=c.target,e,g;if(!!x.test(d.nodeName)&&!d.readOnly){e=f._data(d,"_change_data"),g=H(d),(c.type!=="focusout"||d.type!=="radio")&&f._data(d,"_change_data",g);if(e===b||g===e)return;if(e!=null||g)c.type="change",c.liveFired=b,f.event.trigger(c,arguments[1],d)}};f.event.special.change={filters:{focusout:I,beforedeactivate:I,click:function(a){var b=a.target,c=f.nodeName(b,"input")?b.type:"";(c==="radio"||c==="checkbox"||f.nodeName(b,"select"))&&I.call(this,a)},keydown:function(a){var b=a.target,c=f.nodeName(b,"input")?b.type:"";(a.keyCode===13&&!f.nodeName(b,"textarea")||a.keyCode===32&&(c==="checkbox"||c==="radio")||c==="select-multiple")&&I.call(this,a)},beforeactivate:function(a){var b=a.target;f._data(b,"_change_data",H(b))}},setup:function(a,b){if(this.type==="file")return!1;for(var c in G)f.event.add(this,c+".specialChange",G[c]);return x.test(this.nodeName)},teardown:function(a){f.event.remove(this,".specialChange");return x.test(this.nodeName)}},G=f.event.special.change.filters,G.focus=G.beforeactivate}f.support.focusinBubbles||f.each({focus:"focusin",blur:"focusout"},function(a,b){function e(a){var c=f.event.fix(a);c.type=b,c.originalEvent={},f.event.trigger(c,null,c.target),c.isDefaultPrevented()&&a.preventDefault()}var d=0;f.event.special[b]={setup:function(){d++===0&&c.addEventListener(a,e,!0)},teardown:function(){--d===0&&c.removeEventListener(a,e,!0)}}}),f.each(["bind","one"],function(a,c){f.fn[c]=function(a,d,e){var g;if(typeof a=="object"){for(var h in a)this[c](h,d,a[h],e);return this}if(arguments.length===2||d===!1)e=d,d=b;c==="one"?(g=function(a){f(this).unbind(a,g);return e.apply(this,arguments)},g.guid=e.guid||f.guid++):g=e;if(a==="unload"&&c!=="one")this.one(a,d,e);else for(var i=0,j=this.length;i0?this.bind(b,a,c):this.trigger(b)},f.attrFn&&(f.attrFn[b]=!0)}),function(){function u(a,b,c,d,e,f){for(var g=0,h=d.length;g0){j=i;break}}i=i[a]}d[g]=j}}}function t(a,b,c,d,e,f){for(var g=0,h=d.length;g+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,d=0,e=Object.prototype.toString,g=!1,h=!0,i=/\\/g,j=/\W/;[0,0].sort(function(){h=!1;return 0});var k=function(b,d,f,g){f=f||[],d=d||c;var h=d;if(d.nodeType!==1&&d.nodeType!==9)return[];if(!b||typeof b!="string")return f;var i,j,n,o,q,r,s,t,u=!0,w=k.isXML(d),x=[],y=b;do{a.exec(""),i=a.exec(y);if(i){y=i[3],x.push(i[1]);if(i[2]){o=i[3];break}}}while(i);if(x.length>1&&m.exec(b))if(x.length===2&&l.relative[x[0]])j=v(x[0]+x[1],d);else{j=l.relative[x[0]]?[d]:k(x.shift(),d);while(x.length)b=x.shift(),l.relative[b]&&(b+=x.shift()),j=v(b,j)}else{!g&&x.length>1&&d.nodeType===9&&!w&&l.match.ID.test(x[0])&&!l.match.ID.test(x[x.length-1])&&(q=k.find(x.shift(),d,w),d=q.expr?k.filter(q.expr,q.set)[0]:q.set[0]);if(d){q=g?{expr:x.pop(),set:p(g)}:k.find(x.pop(),x.length===1&&(x[0]==="~"||x[0]==="+")&&d.parentNode?d.parentNode:d,w),j=q.expr?k.filter(q.expr,q.set):q.set,x.length>0?n=p(j):u=!1;while(x.length)r=x.pop(),s=r,l.relative[r]?s=x.pop():r="",s==null&&(s=d),l.relative[r](n,s,w)}else n=x=[]}n||(n=j),n||k.error(r||b);if(e.call(n)==="[object Array]")if(!u)f.push.apply(f,n);else if(d&&d.nodeType===1)for(t=0;n[t]!=null;t++)n[t]&&(n[t]===!0||n[t].nodeType===1&&k.contains(d,n[t]))&&f.push(j[t]);else for(t=0;n[t]!=null;t++)n[t]&&n[t].nodeType===1&&f.push(j[t]);else p(n,f);o&&(k(o,h,f,g),k.uniqueSort(f));return f};k.uniqueSort=function(a){if(r){g=h,a.sort(r);if(g)for(var b=1;b0},k.find=function(a,b,c){var d;if(!a)return[];for(var e=0,f=l.order.length;e":function(a,b){var c,d=typeof b=="string",e=0,f=a.length;if(d&&!j.test(b)){b=b.toLowerCase();for(;e=0)?c||d.push(h):c&&(b[g]=!1));return!1},ID:function(a){return a[1].replace(i,"")},TAG:function(a,b){return a[1].replace(i,"").toLowerCase()},CHILD:function(a){if(a[1]==="nth"){a[2]||k.error(a[0]),a[2]=a[2].replace(/^\+|\s*/g,"");var b=/(-?)(\d*)(?:n([+\-]?\d*))?/.exec(a[2]==="even"&&"2n"||a[2]==="odd"&&"2n+1"||!/\D/.test(a[2])&&"0n+"+a[2]||a[2]);a[2]=b[1]+(b[2]||1)-0,a[3]=b[3]-0}else a[2]&&k.error(a[0]);a[0]=d++;return a},ATTR:function(a,b,c,d,e,f){var g=a[1]=a[1].replace(i,"");!f&&l.attrMap[g]&&(a[1]=l.attrMap[g]),a[4]=(a[4]||a[5]||"").replace(i,""),a[2]==="~="&&(a[4]=" "+a[4]+" ");return a},PSEUDO:function(b,c,d,e,f){if(b[1]==="not")if((a.exec(b[3])||"").length>1||/^\w/.test(b[3]))b[3]=k(b[3],null,null,c);else{var g=k.filter(b[3],c,d,!0^f);d||e.push.apply(e,g);return!1}else if(l.match.POS.test(b[0])||l.match.CHILD.test(b[0]))return!0;return b},POS:function(a){a.unshift(!0);return a}},filters:{enabled:function(a){return a.disabled===!1&&a.type!=="hidden"},disabled:function(a){return a.disabled===!0},checked:function(a){return a.checked===!0},selected:function(a){a.parentNode&&a.parentNode.selectedIndex;return a.selected===!0},parent:function(a){return!!a.firstChild},empty:function(a){return!a.firstChild},has:function(a,b,c){return!!k(c[3],a).length},header:function(a){return/h\d/i.test(a.nodeName)},text:function(a){var b=a.getAttribute("type"),c=a.type;return a.nodeName.toLowerCase()==="input"&&"text"===c&&(b===c||b===null)},radio:function(a){return a.nodeName.toLowerCase()==="input"&&"radio"===a.type},checkbox:function(a){return a.nodeName.toLowerCase()==="input"&&"checkbox"===a.type},file:function(a){return a.nodeName.toLowerCase()==="input"&&"file"===a.type},password:function(a){return a.nodeName.toLowerCase()==="input"&&"password"===a.type},submit:function(a){var b=a.nodeName.toLowerCase();return(b==="input"||b==="button")&&"submit"===a.type},image:function(a){return a.nodeName.toLowerCase()==="input"&&"image"===a.type},reset:function(a){var b=a.nodeName.toLowerCase();return(b==="input"||b==="button")&&"reset"===a.type},button:function(a){var b=a.nodeName.toLowerCase();return b==="input"&&"button"===a.type||b==="button"},input:function(a){return/input|select|textarea|button/i.test(a.nodeName)},focus:function(a){return a===a.ownerDocument.activeElement}},setFilters:{first:function(a,b){return b===0},last:function(a,b,c,d){return b===d.length-1},even:function(a,b){return b%2===0},odd:function(a,b){return b%2===1},lt:function(a,b,c){return bc[3]-0},nth:function(a,b,c){return c[3]-0===b},eq:function(a,b,c){return c[3]-0===b}},filter:{PSEUDO:function(a,b,c,d){var e=b[1],f=l.filters[e];if(f)return f(a,c,b,d);if(e==="contains")return(a.textContent||a.innerText||k.getText([a])||"").indexOf(b[3])>=0;if(e==="not"){var g=b[3];for(var h=0,i=g.length;h=0}},ID:function(a,b){return a.nodeType===1&&a.getAttribute("id")===b},TAG:function(a,b){return b==="*"&&a.nodeType===1||a.nodeName.toLowerCase()===b},CLASS:function(a,b){return(" "+(a.className||a.getAttribute("class"))+" ").indexOf(b)>-1},ATTR:function(a,b){var c=b[1],d=l.attrHandle[c]?l.attrHandle[c](a):a[c]!=null?a[c]:a.getAttribute(c),e=d+"",f=b[2],g=b[4];return d==null?f==="!=":f==="="?e===g:f==="*="?e.indexOf(g)>=0:f==="~="?(" "+e+" ").indexOf(g)>=0:g?f==="!="?e!==g:f==="^="?e.indexOf(g)===0:f==="$="?e.substr(e.length-g.length)===g:f==="|="?e===g||e.substr(0,g.length+1)===g+"-":!1:e&&d!==!1},POS:function(a,b,c,d){var e=b[2],f=l.setFilters[e];if(f)return f(a,c,b,d)}}},m=l.match.POS,n=function(a,b){return"\\"+(b-0+1)};for(var o in l.match)l.match[o]=new RegExp(l.match[o].source+/(?![^\[]*\])(?![^\(]*\))/.source),l.leftMatch[o]=new RegExp(/(^(?:.|\r|\n)*?)/.source+l.match[o].source.replace(/\\(\d+)/g,n));var p=function(a,b){a=Array.prototype.slice.call(a,0);if(b){b.push.apply(b,a);return b}return a};try{Array.prototype.slice.call(c.documentElement.childNodes,0)[0].nodeType}catch(q){p=function(a,b){var c=0,d=b||[];if(e.call(a)==="[object Array]")Array.prototype.push.apply(d,a);else if(typeof a.length=="number")for(var f=a.length;c",e.insertBefore(a,e.firstChild),c.getElementById(d)&&(l.find.ID=function(a,c,d){if(typeof c.getElementById!="undefined"&&!d){var e=c.getElementById(a[1]);return e?e.id===a[1]||typeof e.getAttributeNode!="undefined"&&e.getAttributeNode("id").nodeValue===a[1]?[e]:b:[]}},l.filter.ID=function(a,b){var c=typeof a.getAttributeNode!="undefined"&&a.getAttributeNode("id");return a.nodeType===1&&c&&c.nodeValue===b}),e.removeChild(a),e=a=null}(),function(){var a=c.createElement("div");a.appendChild(c.createComment("")),a.getElementsByTagName("*").length>0&&(l.find.TAG=function(a,b){var c=b.getElementsByTagName(a[1]);if(a[1]==="*"){var d=[];for(var e=0;c[e];e++)c[e].nodeType===1&&d.push(c[e]);c=d}return c}),a.innerHTML="",a.firstChild&&typeof a.firstChild.getAttribute!="undefined"&&a.firstChild.getAttribute("href")!=="#"&&(l.attrHandle.href=function(a){return a.getAttribute("href",2)}),a=null}(),c.querySelectorAll&&function(){var a=k,b=c.createElement("div"),d="__sizzle__";b.innerHTML="

    ";if(!b.querySelectorAll||b.querySelectorAll(".TEST").length!==0){k=function(b,e,f,g){e=e||c;if(!g&&!k.isXML(e)){var h=/^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec(b);if(h&&(e.nodeType===1||e.nodeType===9)){if(h[1])return p(e.getElementsByTagName(b),f);if(h[2]&&l.find.CLASS&&e.getElementsByClassName)return p(e.getElementsByClassName(h[2]),f)}if(e.nodeType===9){if(b==="body"&&e.body)return p([e.body],f);if(h&&h[3]){var i=e.getElementById(h[3]);if(!i||!i.parentNode)return p([],f);if(i.id===h[3])return p([i],f)}try{return p(e.querySelectorAll(b),f)}catch(j){}}else if(e.nodeType===1&&e.nodeName.toLowerCase()!=="object"){var m=e,n=e.getAttribute("id"),o=n||d,q=e.parentNode,r=/^\s*[+~]/.test(b);n?o=o.replace(/'/g,"\\$&"):e.setAttribute("id",o),r&&q&&(e=e.parentNode);try{if(!r||q)return p(e.querySelectorAll("[id='"+o+"'] "+b),f)}catch(s){}finally{n||m.removeAttribute("id")}}}return a(b,e,f,g)};for(var e in a)k[e]=a[e];b=null}}(),function(){var a=c.documentElement,b=a.matchesSelector||a.mozMatchesSelector||a.webkitMatchesSelector||a.msMatchesSelector;if(b){var d=!b.call(c.createElement("div"),"div"),e=!1;try{b.call(c.documentElement,"[test!='']:sizzle")}catch(f){e=!0}k.matchesSelector=function(a,c){c=c.replace(/\=\s*([^'"\]]*)\s*\]/g,"='$1']");if(!k.isXML(a))try{if(e||!l.match.PSEUDO.test(c)&&!/!=/.test(c)){var f=b.call(a,c);if(f||!d||a.document&&a.document.nodeType!==11)return f}}catch(g){}return k(c,null,null,[a]).length>0}}}(),function(){var a=c.createElement("div");a.innerHTML="
    ";if(!!a.getElementsByClassName&&a.getElementsByClassName("e").length!==0){a.lastChild.className="e";if(a.getElementsByClassName("e").length===1)return;l.order.splice(1,0,"CLASS"),l.find.CLASS=function(a,b,c){if(typeof b.getElementsByClassName!="undefined"&&!c)return b.getElementsByClassName(a[1])},a=null}}(),c.documentElement.contains?k.contains=function(a,b){return a!==b&&(a.contains?a.contains(b):!0)}:c.documentElement.compareDocumentPosition?k.contains=function(a,b){return!!(a.compareDocumentPosition(b)&16)}:k.contains=function(){return!1},k.isXML=function(a){var b=(a?a.ownerDocument||a:0).documentElement;return b?b.nodeName!=="HTML":!1};var v=function(a,b){var c,d=[],e="",f=b.nodeType?[b]:b;while(c=l.match.PSEUDO.exec(a))e+=c[0],a=a.replace(l.match.PSEUDO,"");a=l.relative[a]?a+"*":a;for(var g=0,h=f.length;g0)for(h=g;h0:this.filter(a).length>0)},closest:function(a,b){var c=[],d,e,g=this[0];if(f.isArray(a)){var h,i,j={},k=1;if(g&&a.length){for(d=0,e=a.length;d-1:f(g).is(h))&&c.push({selector:i,elem:g,level:k});g=g.parentNode,k++}}return c}var l=S.test(a)||typeof a!="string"?f(a,b||this.context):0;for(d=0,e=this.length;d-1:f.find.matchesSelector(g,a)){c.push(g);break}g=g.parentNode;if(!g||!g.ownerDocument||g===b||g.nodeType===11)break}}c=c.length>1?f.unique(c):c;return this.pushStack(c,"closest",a)},index:function(a){if(!a)return this[0]&&this[0].parentNode?this.prevAll().length:-1;if(typeof a=="string")return f.inArray(this[0],f(a));return f.inArray(a.jquery?a[0]:a,this)},add:function(a,b){var c=typeof a=="string"?f(a,b):f.makeArray(a&&a.nodeType?[a]:a),d=f.merge(this.get(),c);return this.pushStack(U(c[0])||U(d[0])?d:f.unique(d))},andSelf:function(){return this.add(this.prevObject)}}),f.each({parent:function(a){var b=a.parentNode;return b&&b.nodeType!==11?b:null},parents:function(a){return f.dir(a,"parentNode")},parentsUntil:function(a,b,c){return f.dir(a,"parentNode",c)},next:function(a){return f.nth(a,2,"nextSibling")},prev:function(a){return f.nth(a,2,"previousSibling")},nextAll:function(a){return f.dir(a,"nextSibling")},prevAll:function(a){return f.dir(a,"previousSibling")},nextUntil:function(a,b,c){return f.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return f.dir(a,"previousSibling",c)},siblings:function(a){return f.sibling(a.parentNode.firstChild,a)},children:function(a){return f.sibling(a.firstChild)},contents:function(a){return f.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:f.makeArray(a.childNodes)}},function(a,b){f.fn[a]=function(c,d){var e=f.map(this,b,c),g=R.call(arguments);N.test(a)||(d=c),d&&typeof d=="string"&&(e=f.filter(d,e)),e=this.length>1&&!T[a]?f.unique(e):e,(this.length>1||P.test(d))&&O.test(a)&&(e=e.reverse());return this.pushStack(e,a,g.join(","))}}),f.extend({filter:function(a,b,c){c&&(a=":not("+a+")");return b.length===1?f.find.matchesSelector(b[0],a)?[b[0]]:[]:f.find.matches(a,b)},dir:function(a,c,d){var e=[],g=a[c];while(g&&g.nodeType!==9&&(d===b||g.nodeType!==1||!f(g).is(d)))g.nodeType===1&&e.push(g),g=g[c];return e},nth:function(a,b,c,d){b=b||1;var e=0;for(;a;a=a[c])if(a.nodeType===1&&++e===b)break;return a},sibling:function(a,b){var c=[];for(;a;a=a.nextSibling)a.nodeType===1&&a!==b&&c.push(a);return c}});var W=/ jQuery\d+="(?:\d+|null)"/g,X=/^\s+/,Y=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig,Z=/<([\w:]+)/,$=/",""],legend:[1,"
    ","
    "],thead:[1,"","
    "],tr:[2,"","
    "],td:[3,"","
    "],col:[2,"","
    "],area:[1,"",""],_default:[0,"",""]};be.optgroup=be.option,be.tbody=be.tfoot=be.colgroup=be.caption=be.thead,be.th=be.td,f.support.htmlSerialize||(be._default=[1,"div
    ","
    "]),f.fn.extend({text:function(a){if(f.isFunction(a))return this.each(function(b){var c=f(this);c.text(a.call(this,b,c.text()))});if(typeof a!="object"&&a!==b)return this.empty().append((this[0]&&this[0].ownerDocument||c).createTextNode(a));return f.text(this)},wrapAll:function(a){if(f.isFunction(a))return this.each(function(b){f(this).wrapAll(a.call(this,b))});if(this[0]){var b=f(a,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstChild&&a.firstChild.nodeType===1)a=a.firstChild;return a}).append(this)}return this},wrapInner:function(a){if(f.isFunction(a))return this.each(function(b){f(this).wrapInner(a.call(this,b))});return this.each(function(){var b=f(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){return this.each(function(){f(this).wrapAll(a)})},unwrap:function(){return this.parent().each(function(){f.nodeName(this,"body")||f(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.appendChild(a)})},prepend:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.insertBefore(a,this.firstChild)})},before:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this)});if(arguments.length){var a=f(arguments[0]);a.push.apply(a,this.toArray());return this.pushStack(a,"before",arguments)}},after:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this.nextSibling)});if(arguments.length){var a=this.pushStack(this,"after",arguments);a.push.apply(a,f(arguments[0]).toArray());return a}},remove:function(a,b){for(var c=0,d;(d=this[c])!=null;c++)if(!a||f.filter(a,[d]).length)!b&&d.nodeType===1&&(f.cleanData(d.getElementsByTagName("*")),f.cleanData([d])),d.parentNode&&d.parentNode.removeChild(d);return this},empty:function(){for(var a=0,b;(b=this[a])!=null;a++){b.nodeType===1&&f.cleanData(b.getElementsByTagName("*"));while(b.firstChild)b.removeChild(b.firstChild)}return this},clone:function(a,b){a=a==null?!1:a,b=b==null?a:b;return this.map(function(){return f.clone(this,a,b)})},html:function(a){if(a===b)return this[0]&&this[0].nodeType===1?this[0].innerHTML.replace(W,""):null;if(typeof a=="string"&&!ba.test(a)&&(f.support.leadingWhitespace||!X.test(a))&&!be[(Z.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(Y,"<$1>");try{for(var c=0,d=this.length;c1&&l0?this.clone(!0):this).get();f(e[h])[b](j),d=d.concat(j)}return this.pushStack(d,a,e.selector)}}),f.extend({clone:function(a,b,c){var d=a.cloneNode(!0),e,g,h;if((!f.support.noCloneEvent||!f.support.noCloneChecked)&&(a.nodeType===1||a.nodeType===11)&&!f.isXMLDoc(a)){bh(a,d),e=bi(a),g=bi(d);for(h=0;e[h];++h)g[h]&&bh(e[h],g[h])}if(b){bg(a,d);if(c){e=bi(a),g=bi(d);for(h=0;e[h];++h)bg(e[h],g[h])}}e=g=null;return d},clean:function(a,b,d,e){var g;b=b||c,typeof b.createElement=="undefined"&&(b=b.ownerDocument||b[0]&&b[0].ownerDocument||c);var h=[],i;for(var j=0,k;(k=a[j])!=null;j++){typeof k=="number"&&(k+="");if(!k)continue;if(typeof k=="string")if(!_.test(k))k=b.createTextNode(k);else{k=k.replace(Y,"<$1>");var l=(Z.exec(k)||["",""])[1].toLowerCase(),m=be[l]||be._default,n=m[0],o=b.createElement("div");o.innerHTML=m[1]+k+m[2];while(n--)o=o.lastChild;if(!f.support.tbody){var p=$.test(k),q=l==="table"&&!p?o.firstChild&&o.firstChild.childNodes:m[1]===""&&!p?o.childNodes:[];for(i=q.length-1;i>=0;--i)f.nodeName(q[i],"tbody")&&!q[i].childNodes.length&&q[i].parentNode.removeChild(q[i])}!f.support.leadingWhitespace&&X.test(k)&&o.insertBefore(b.createTextNode(X.exec(k)[0]),o.firstChild),k=o.childNodes}var r;if(!f.support.appendChecked)if(k[0]&&typeof (r=k.length)=="number")for(i=0;i=0)return b+"px"}}}),f.support.opacity||(f.cssHooks.opacity={get:function(a,b){return bn.test((b&&a.currentStyle?a.currentStyle.filter:a.style.filter)||"")?parseFloat(RegExp.$1)/100+"":b?"1":""},set:function(a,b){var c=a.style,d=a.currentStyle,e=f.isNaN(b)?"":"alpha(opacity="+b*100+")",g=d&&d.filter||c.filter||"";c.zoom=1;if(b>=1&&f.trim(g.replace(bm,""))===""){c.removeAttribute("filter");if(d&&!d.filter)return}c.filter=bm.test(g)?g.replace(bm,e):g+" "+e}}),f(function(){f.support.reliableMarginRight||(f.cssHooks.marginRight={get:function(a,b){var c;f.swap(a,{display:"inline-block"},function(){b?c=bv(a,"margin-right","marginRight"):c=a.style.marginRight});return c}})}),c.defaultView&&c.defaultView.getComputedStyle&&(bw=function(a,c){var d,e,g;c=c.replace(bo,"-$1").toLowerCase();if(!(e=a.ownerDocument.defaultView))return b;if(g=e.getComputedStyle(a,null))d=g.getPropertyValue(c),d===""&&!f.contains(a.ownerDocument.documentElement,a)&&(d=f.style(a,c));return d}),c.documentElement.currentStyle&&(bx=function(a,b){var c,d=a.currentStyle&&a.currentStyle[b],e=a.runtimeStyle&&a.runtimeStyle[b],f=a.style;!bp.test(d)&&bq.test(d)&&(c=f.left,e&&(a.runtimeStyle.left=a.currentStyle.left),f.left=b==="fontSize"?"1em":d||0,d=f.pixelLeft+"px",f.left=c,e&&(a.runtimeStyle.left=e));return d===""?"auto":d}),bv=bw||bx,f.expr&&f.expr.filters&&(f.expr.filters.hidden=function(a){var b=a.offsetWidth,c=a.offsetHeight;return b===0&&c===0||!f.support.reliableHiddenOffsets&&(a.style.display||f.css(a,"display"))==="none"},f.expr.filters.visible=function(a){return!f.expr.filters.hidden(a)});var bz=/%20/g,bA=/\[\]$/,bB=/\r?\n/g,bC=/#.*$/,bD=/^(.*?):[ \t]*([^\r\n]*)\r?$/mg,bE=/^(?:color|date|datetime|datetime-local|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,bF=/^(?:about|app|app\-storage|.+\-extension|file|res|widget):$/,bG=/^(?:GET|HEAD)$/,bH=/^\/\//,bI=/\?/,bJ=/)<[^<]*)*<\/script>/gi,bK=/^(?:select|textarea)/i,bL=/\s+/,bM=/([?&])_=[^&]*/,bN=/^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+))?)?/,bO=f.fn.load,bP={},bQ={},bR,bS,bT=["*/"]+["*"];try{bR=e.href}catch(bU){bR=c.createElement("a"),bR.href="",bR=bR.href}bS=bN.exec(bR.toLowerCase())||[],f.fn.extend({load:function(a,c,d){if(typeof a!="string"&&bO)return bO.apply(this,arguments);if(!this.length)return this;var e=a.indexOf(" ");if(e>=0){var g=a.slice(e,a.length);a=a.slice(0,e)}var h="GET";c&&(f.isFunction(c)?(d=c,c=b):typeof c=="object"&&(c=f.param(c,f.ajaxSettings.traditional),h="POST"));var i=this;f.ajax({url:a,type:h,dataType:"html",data:c,complete:function(a,b,c){c=a.responseText,a.isResolved()&&(a.done(function(a){c=a}),i.html(g?f("
    ").append(c.replace(bJ,"")).find(g):c)),d&&i.each(d,[c,b,a])}});return this},serialize:function(){return f.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?f.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||bK.test(this.nodeName)||bE.test(this.type))}).map(function(a,b){var c=f(this).val();return c==null?null:f.isArray(c)?f.map(c,function(a,c){return{name:b.name,value:a.replace(bB,"\r\n")}}):{name:b.name,value:c.replace(bB,"\r\n")}}).get()}}),f.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),function(a,b){f.fn[b]=function(a){return this.bind(b,a)}}),f.each(["get","post"],function(a,c){f[c]=function(a,d,e,g){f.isFunction(d)&&(g=g||e,e=d,d=b);return f.ajax({type:c,url:a,data:d,success:e,dataType:g})}}),f.extend({getScript:function(a,c){return f.get(a,b,c,"script")},getJSON:function(a,b,c){return f.get(a,b,c,"json")},ajaxSetup:function(a,b){b?bX(a,f.ajaxSettings):(b=a,a=f.ajaxSettings),bX(a,b);return a},ajaxSettings:{url:bR,isLocal:bF.test(bS[1]),global:!0,type:"GET",contentType:"application/x-www-form-urlencoded",processData:!0,async:!0,accepts:{xml:"application/xml, text/xml",html:"text/html",text:"text/plain",json:"application/json, text/javascript","*":bT},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText"},converters:{"* text":a.String,"text html":!0,"text json":f.parseJSON,"text xml":f.parseXML},flatOptions:{context:!0,url:!0}},ajaxPrefilter:bV(bP),ajaxTransport:bV(bQ),ajax:function(a,c){function w(a,c,l,m){if(s!==2){s=2,q&&clearTimeout(q),p=b,n=m||"",v.readyState=a>0?4:0;var o,r,u,w=c,x=l?bZ(d,v,l):b,y,z;if(a>=200&&a<300||a===304){if(d.ifModified){if(y=v.getResponseHeader("Last-Modified"))f.lastModified[k]=y;if(z=v.getResponseHeader("Etag"))f.etag[k]=z}if(a===304)w="notmodified",o=!0;else try{r=b$(d,x),w="success",o=!0}catch(A){w="parsererror",u=A}}else{u=w;if(!w||a)w="error",a<0&&(a=0)}v.status=a,v.statusText=""+(c||w),o?h.resolveWith(e,[r,w,v]):h.rejectWith(e,[v,w,u]),v.statusCode(j),j=b,t&&g.trigger("ajax"+(o?"Success":"Error"),[v,d,o?r:u]),i.resolveWith(e,[v,w]),t&&(g.trigger("ajaxComplete",[v,d]),--f.active||f.event.trigger("ajaxStop"))}}typeof a=="object"&&(c=a,a=b),c=c||{};var d=f.ajaxSetup({},c),e=d.context||d,g=e!==d&&(e.nodeType||e instanceof f)?f(e):f.event,h=f.Deferred(),i=f._Deferred(),j=d.statusCode||{},k,l={},m={},n,o,p,q,r,s=0,t,u,v={readyState:0,setRequestHeader:function(a,b){if(!s){var c=a.toLowerCase();a=m[c]=m[c]||a,l[a]=b}return this},getAllResponseHeaders:function(){return s===2?n:null},getResponseHeader:function(a){var c;if(s===2){if(!o){o={};while(c=bD.exec(n))o[c[1].toLowerCase()]=c[2]}c=o[a.toLowerCase()]}return c===b?null:c},overrideMimeType:function(a){s||(d.mimeType=a);return this},abort:function(a){a=a||"abort",p&&p.abort(a),w(0,a);return this}};h.promise(v),v.success=v.done,v.error=v.fail,v.complete=i.done,v.statusCode=function(a){if(a){var b;if(s<2)for(b in a)j[b]=[j[b],a[b]];else b=a[v.status],v.then(b,b)}return this},d.url=((a||d.url)+"").replace(bC,"").replace(bH,bS[1]+"//"),d.dataTypes=f.trim(d.dataType||"*").toLowerCase().split(bL),d.crossDomain==null&&(r=bN.exec(d.url.toLowerCase()),d.crossDomain=!(!r||r[1]==bS[1]&&r[2]==bS[2]&&(r[3]||(r[1]==="http:"?80:443))==(bS[3]||(bS[1]==="http:"?80:443)))),d.data&&d.processData&&typeof d.data!="string"&&(d.data=f.param(d.data,d.traditional)),bW(bP,d,c,v);if(s===2)return!1;t=d.global,d.type=d.type.toUpperCase(),d.hasContent=!bG.test(d.type),t&&f.active++===0&&f.event.trigger("ajaxStart");if(!d.hasContent){d.data&&(d.url+=(bI.test(d.url)?"&":"?")+d.data,delete d.data),k=d.url;if(d.cache===!1){var x=f.now(),y=d.url.replace(bM,"$1_="+x);d.url=y+(y===d.url?(bI.test(d.url)?"&":"?")+"_="+x:"")}}(d.data&&d.hasContent&&d.contentType!==!1||c.contentType)&&v.setRequestHeader("Content-Type",d.contentType),d.ifModified&&(k=k||d.url,f.lastModified[k]&&v.setRequestHeader("If-Modified-Since",f.lastModified[k]),f.etag[k]&&v.setRequestHeader("If-None-Match",f.etag[k])),v.setRequestHeader("Accept",d.dataTypes[0]&&d.accepts[d.dataTypes[0]]?d.accepts[d.dataTypes[0]]+(d.dataTypes[0]!=="*"?", "+bT+"; q=0.01":""):d.accepts["*"]);for(u in d.headers)v.setRequestHeader(u,d.headers[u]);if(d.beforeSend&&(d.beforeSend.call(e,v,d)===!1||s===2)){v.abort();return!1}for(u in{success:1,error:1,complete:1})v[u](d[u]);p=bW(bQ,d,c,v);if(!p)w(-1,"No Transport");else{v.readyState=1,t&&g.trigger("ajaxSend",[v,d]),d.async&&d.timeout>0&&(q=setTimeout(function(){v.abort("timeout")},d.timeout));try{s=1,p.send(l,w)}catch(z){s<2?w(-1,z):f.error(z)}}return v},param:function(a,c){var d=[],e=function(a,b){b=f.isFunction(b)?b():b,d[d.length]=encodeURIComponent(a)+"="+encodeURIComponent(b)};c===b&&(c=f.ajaxSettings.traditional);if(f.isArray(a)||a.jquery&&!f.isPlainObject(a))f.each(a,function(){e(this.name,this.value)});else for(var g in a)bY(g,a[g],c,e);return d.join("&").replace(bz,"+")}}),f.extend({active:0,lastModified:{},etag:{}});var b_=f.now(),ca=/(\=)\?(&|$)|\?\?/i;f.ajaxSetup({jsonp:"callback",jsonpCallback:function(){return f.expando+"_"+b_++}}),f.ajaxPrefilter("json jsonp",function(b,c,d){var e=b.contentType==="application/x-www-form-urlencoded"&&typeof b.data=="string";if(b.dataTypes[0]==="jsonp"||b.jsonp!==!1&&(ca.test(b.url)||e&&ca.test(b.data))){var g,h=b.jsonpCallback=f.isFunction(b.jsonpCallback)?b.jsonpCallback():b.jsonpCallback,i=a[h],j=b.url,k=b.data,l="$1"+h+"$2";b.jsonp!==!1&&(j=j.replace(ca,l),b.url===j&&(e&&(k=k.replace(ca,l)),b.data===k&&(j+=(/\?/.test(j)?"&":"?")+b.jsonp+"="+h))),b.url=j,b.data=k,a[h]=function(a){g=[a]},d.always(function(){a[h]=i,g&&f.isFunction(i)&&a[h](g[0])}),b.converters["script json"]=function(){g||f.error(h+" was not called");return g[0]},b.dataTypes[0]="json";return"script"}}),f.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/javascript|ecmascript/},converters:{"text script":function(a){f.globalEval(a);return a}}}),f.ajaxPrefilter("script",function(a){a.cache===b&&(a.cache=!1),a.crossDomain&&(a.type="GET",a.global=!1)}),f.ajaxTransport("script",function(a){if(a.crossDomain){var d,e=c.head||c.getElementsByTagName("head")[0]||c.documentElement;return{send:function(f,g){d=c.createElement("script"),d.async="async",a.scriptCharset&&(d.charset=a.scriptCharset),d.src=a.url,d.onload=d.onreadystatechange=function(a,c){if(c||!d.readyState||/loaded|complete/.test(d.readyState))d.onload=d.onreadystatechange=null,e&&d.parentNode&&e.removeChild(d),d=b,c||g(200,"success")},e.insertBefore(d,e.firstChild)},abort:function(){d&&d.onload(0,1)}}}});var cb=a.ActiveXObject?function(){for(var a in cd)cd[a](0,1)}:!1,cc=0,cd;f.ajaxSettings.xhr=a.ActiveXObject?function(){return!this.isLocal&&ce()||cf()}:ce,function(a){f.extend(f.support,{ajax:!!a,cors:!!a&&"withCredentials"in a})}(f.ajaxSettings.xhr()),f.support.ajax&&f.ajaxTransport(function(c){if(!c.crossDomain||f.support.cors){var d;return{send:function(e,g){var h=c.xhr(),i,j;c.username?h.open(c.type,c.url,c.async,c.username,c.password):h.open(c.type,c.url,c.async);if(c.xhrFields)for(j in c.xhrFields)h[j]=c.xhrFields[j];c.mimeType&&h.overrideMimeType&&h.overrideMimeType(c.mimeType),!c.crossDomain&&!e["X-Requested-With"]&&(e["X-Requested-With"]="XMLHttpRequest");try{for(j in e)h.setRequestHeader(j,e[j])}catch(k){}h.send(c.hasContent&&c.data||null),d=function(a,e){var j,k,l,m,n;try{if(d&&(e||h.readyState===4)){d=b,i&&(h.onreadystatechange=f.noop,cb&&delete cd[i]);if(e)h.readyState!==4&&h.abort();else{j=h.status,l=h.getAllResponseHeaders(),m={},n=h.responseXML,n&&n.documentElement&&(m.xml=n),m.text=h.responseText;try{k=h.statusText}catch(o){k=""}!j&&c.isLocal&&!c.crossDomain?j=m.text?200:404:j===1223&&(j=204)}}}catch(p){e||g(-1,p)}m&&g(j,k,m,l)},!c.async||h.readyState===4?d():(i=++cc,cb&&(cd||(cd={},f(a).unload(cb)),cd[i]=d),h.onreadystatechange=d)},abort:function(){d&&d(0,1)}}}});var cg={},ch,ci,cj=/^(?:toggle|show|hide)$/,ck=/^([+\-]=)?([\d+.\-]+)([a-z%]*)$/i,cl,cm=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]],cn;f.fn.extend({show:function(a,b,c){var d,e;if(a||a===0)return this.animate(cq("show",3),a,b,c);for(var g=0,h=this.length;g=e.duration+this.startTime){this.now=this.end,this.pos=this.state=1,this.update(),e.animatedProperties[this.prop]=!0;for(g in e.animatedProperties)e.animatedProperties[g]!==!0&&(c=!1);if(c){e.overflow!=null&&!f.support.shrinkWrapBlocks&&f.each(["","X","Y"],function(a,b){d.style["overflow"+b]=e.overflow[a]}),e.hide&&f(d).hide();if(e.hide||e.show)for(var i in e.animatedProperties)f.style(d,i,e.orig[i]);e.complete.call(d)}return!1}e.duration==Infinity?this.now=b:(h=b-this.startTime,this.state=h/e.duration,this.pos=f.easing[e.animatedProperties[this.prop]](this.state,h,0,1,e.duration),this.now=this.start+(this.end-this.start)*this.pos),this.update();return!0}},f.extend(f.fx,{tick:function(){for(var a=f.timers,b=0;b
    ";f.extend(b.style,{position:"absolute",top:0,left:0,margin:0,border:0,width:"1px",height:"1px",visibility:"hidden"}),b.innerHTML=j,a.insertBefore(b,a.firstChild),d=b.firstChild,e=d.firstChild,h=d.nextSibling.firstChild.firstChild,this.doesNotAddBorder=e.offsetTop!==5,this.doesAddBorderForTableAndCells=h.offsetTop===5,e.style.position="fixed",e.style.top="20px",this.supportsFixedPosition=e.offsetTop===20||e.offsetTop===15,e.style.position=e.style.top="",d.style.overflow="hidden",d.style.position="relative",this.subtractsBorderForOverflowNotVisible=e.offsetTop===-5,this.doesNotIncludeMarginInBodyOffset=a.offsetTop!==i,a.removeChild(b),f.offset.initialize=f.noop},bodyOffset:function(a){var b=a.offsetTop,c=a.offsetLeft;f.offset.initialize(),f.offset.doesNotIncludeMarginInBodyOffset&&(b+=parseFloat(f.css(a,"marginTop"))||0,c+=parseFloat(f.css(a,"marginLeft"))||0);return{top:b,left:c}},setOffset:function(a,b,c){var d=f.css(a,"position");d==="static"&&(a.style.position="relative");var e=f(a),g=e.offset(),h=f.css(a,"top"),i=f.css(a,"left"),j=(d==="absolute"||d==="fixed")&&f.inArray("auto",[h,i])>-1,k={},l={},m,n;j?(l=e.position(),m=l.top,n=l.left):(m=parseFloat(h)||0,n=parseFloat(i)||0),f.isFunction(b)&&(b=b.call(a,c,g)),b.top!=null&&(k.top=b.top-g.top+m),b.left!=null&&(k.left=b.left-g.left+n),"using"in b?b.using.call(a,k):e.css(k)}},f.fn.extend({position:function(){if(!this[0])return null;var a=this[0],b=this.offsetParent(),c=this.offset(),d=ct.test(b[0].nodeName)?{top:0,left:0}:b.offset();c.top-=parseFloat(f.css(a,"marginTop"))||0,c.left-=parseFloat(f.css(a,"marginLeft"))||0,d.top+=parseFloat(f.css(b[0],"borderTopWidth"))||0,d.left+=parseFloat(f.css(b[0],"borderLeftWidth"))||0;return{top:c.top-d.top,left:c.left-d.left}},offsetParent:function(){return this.map(function(){var a=this.offsetParent||c.body;while(a&&!ct.test(a.nodeName)&&f.css(a,"position")==="static")a=a.offsetParent;return a})}}),f.each(["Left","Top"],function(a,c){var d="scroll"+c;f.fn[d]=function(c){var e,g;if(c===b){e=this[0];if(!e)return null;g=cu(e);return g?"pageXOffset"in g?g[a?"pageYOffset":"pageXOffset"]:f.support.boxModel&&g.document.documentElement[d]||g.document.body[d]:e[d]}return this.each(function(){g=cu(this),g?g.scrollTo(a?f(g).scrollLeft():c,a?c:f(g).scrollTop()):this[d]=c})}}),f.each(["Height","Width"],function(a,c){var d=c.toLowerCase();f.fn["inner"+c]=function(){var a=this[0];return a&&a.style?parseFloat(f.css(a,d,"padding")):null},f.fn["outer"+c]=function(a){var b=this[0];return b&&b.style?parseFloat(f.css(b,d,a?"margin":"border")):null},f.fn[d]=function(a){var e=this[0];if(!e)return a==null?null:this;if(f.isFunction(a))return this.each(function(b){var c=f(this);c[d](a.call(this,b,c[d]()))});if(f.isWindow(e)){var g=e.document.documentElement["client"+c],h=e.document.body;return e.document.compatMode==="CSS1Compat"&&g||h&&h["client"+c]||g}if(e.nodeType===9)return Math.max(e.documentElement["client"+c],e.body["scroll"+c],e.documentElement["scroll"+c],e.body["offset"+c],e.documentElement["offset"+c]);if(a===b){var i=f.css(e,d),j=parseFloat(i);return f.isNaN(j)?i:j}return this.css(d,typeof a=="string"?a:a+"px")}}),a.jQuery=a.$=f})(window); rabbitmq-server-3.2.4/plugins-src/rabbitmq-management/priv/www/js/sammy-0.6.0.min.js0000644000000000000000000003566712305126066026653 0ustar rootroot// -- Sammy -- /sammy.js // http://code.quirkey.com/sammy // Version: 0.6.0 // Built: Wed Sep 01 23:12:46 -0700 2010 (function(g){var m,f="([^/]+)",i=/:([\w\d]+)/g,j=/\?([^#]*)$/,b=function(n){return Array.prototype.slice.call(n)},c=function(n){return Object.prototype.toString.call(n)==="[object Function]"},k=function(n){return Object.prototype.toString.call(n)==="[object Array]"},h=decodeURIComponent,e=function(n){return n.replace(/&/g,"&").replace(//g,">")},l=function(n){return function(o,p){return this.route.apply(this,[n,o,p])}},a={},d=[];m=function(){var o=b(arguments),p,n;m.apps=m.apps||{};if(o.length===0||o[0]&&c(o[0])){return m.apply(m,["body"].concat(o))}else{if(typeof(n=o.shift())=="string"){p=m.apps[n]||new m.Application();p.element_selector=n;if(o.length>0){g.each(o,function(q,r){p.use(r)})}if(p.element_selector!=n){delete m.apps[n]}m.apps[p.element_selector]=p;return p}}};m.VERSION="0.6.0";m.addLogger=function(n){d.push(n)};m.log=function(){var n=b(arguments);n.unshift("["+Date()+"]");g.each(d,function(p,o){o.apply(m,n)})};if(typeof window.console!="undefined"){if(c(console.log.apply)){m.addLogger(function(){window.console.log.apply(console,arguments)})}else{m.addLogger(function(){window.console.log(arguments)})}}else{if(typeof console!="undefined"){m.addLogger(function(){console.log.apply(console,arguments)})}}g.extend(m,{makeArray:b,isFunction:c,isArray:k});m.Object=function(n){return g.extend(this,n||{})};g.extend(m.Object.prototype,{escapeHTML:e,h:e,toHash:function(){var n={};g.each(this,function(p,o){if(!c(o)){n[p]=o}});return n},toHTML:function(){var n="";g.each(this,function(p,o){if(!c(o)){n+=""+p+" "+o+"
    "}});return n},keys:function(n){var o=[];for(var p in this){if(!c(this[p])||!n){o.push(p)}}return o},has:function(n){return this[n]&&g.trim(this[n].toString())!=""},join:function(){var o=b(arguments);var n=o.shift();return o.join(n)},log:function(){m.log.apply(m,arguments)},toString:function(n){var o=[];g.each(this,function(q,p){if(!c(p)||n){o.push('"'+q+'": '+p.toString())}});return"Sammy.Object: {"+o.join(",")+"}"}});m.HashLocationProxy=function(o,n){this.app=o;this.is_native=false;this._startPolling(n)};m.HashLocationProxy.prototype={bind:function(){var n=this,o=this.app;g(window).bind("hashchange."+this.app.eventNamespace(),function(q,p){if(n.is_native===false&&!p){m.log("native hash change exists, using");n.is_native=true;clearInterval(m.HashLocationProxy._interval)}o.trigger("location-changed")});if(!m.HashLocationProxy._bindings){m.HashLocationProxy._bindings=0}m.HashLocationProxy._bindings++},unbind:function(){g(window).unbind("hashchange."+this.app.eventNamespace());m.HashLocationProxy._bindings--;if(m.HashLocationProxy._bindings<=0){clearInterval(m.HashLocationProxy._interval)}},getLocation:function(){var n=window.location.toString().match(/^[^#]*(#.+)$/);return n?n[1]:""},setLocation:function(n){return(window.location=n)},_startPolling:function(p){var o=this;if(!m.HashLocationProxy._interval){if(!p){p=10}var n=function(){current_location=o.getLocation();if(!m.HashLocationProxy._last_location||current_location!=m.HashLocationProxy._last_location){setTimeout(function(){g(window).trigger("hashchange",[true])},13)}m.HashLocationProxy._last_location=current_location};n();m.HashLocationProxy._interval=setInterval(n,p)}}};m.Application=function(n){var o=this;this.routes={};this.listeners=new m.Object({});this.arounds=[];this.befores=[];this.namespace=(new Date()).getTime()+"-"+parseInt(Math.random()*1000,10);this.context_prototype=function(){m.EventContext.apply(this,arguments)};this.context_prototype.prototype=new m.EventContext();if(c(n)){n.apply(this,[this])}if(!this._location_proxy){this.setLocationProxy(new m.HashLocationProxy(this,this.run_interval_every))}if(this.debug){this.bindToAllEvents(function(q,p){o.log(o.toString(),q.cleaned_type,p||{})})}};m.Application.prototype=g.extend({},m.Object.prototype,{ROUTE_VERBS:["get","post","put","delete"],APP_EVENTS:["run","unload","lookup-route","run-route","route-found","event-context-before","event-context-after","changed","error","check-form-submission","redirect"],_last_route:null,_location_proxy:null,_running:false,element_selector:"body",debug:false,raise_errors:false,run_interval_every:50,template_engine:null,toString:function(){return"Sammy.Application:"+this.element_selector},$element:function(){return g(this.element_selector)},use:function(){var n=b(arguments),p=n.shift(),o=p||"";try{n.unshift(this);if(typeof p=="string"){o="Sammy."+p;p=m[p]}p.apply(this,n)}catch(q){if(typeof p==="undefined"){this.error("Plugin Error: called use() but plugin ("+o.toString()+") is not defined",q)}else{if(!c(p)){this.error("Plugin Error: called use() but '"+o.toString()+"' is not a function",q)}else{this.error("Plugin Error",q)}}}return this},setLocationProxy:function(n){var o=this._location_proxy;this._location_proxy=n;if(this.isRunning()){if(o){o.unbind()}this._location_proxy.bind()}},route:function(q,o,s){var p=this,r=[],n;if(!s&&c(o)){o=q;s=o;q="any"}q=q.toLowerCase();if(o.constructor==String){i.lastIndex=0;while((path_match=i.exec(o))!==null){r.push(path_match[1])}o=new RegExp("^"+o.replace(i,f)+"$")}if(typeof s=="string"){s=p[s]}n=function(t){var u={verb:t,path:o,callback:s,param_names:r};p.routes[t]=p.routes[t]||[];p.routes[t].push(u)};if(q==="any"){g.each(this.ROUTE_VERBS,function(u,t){n(t)})}else{n(q)}return this},get:l("get"),post:l("post"),put:l("put"),del:l("delete"),any:l("any"),mapRoutes:function(o){var n=this;g.each(o,function(p,q){n.route.apply(n,q)});return this},eventNamespace:function(){return["sammy-app",this.namespace].join("-")},bind:function(n,p,r){var q=this;if(typeof r=="undefined"){r=p}var o=function(){var u,s,t;u=arguments[0];t=arguments[1];if(t&&t.context){s=t.context;delete t.context}else{s=new q.context_prototype(q,"bind",u.type,t,u.target)}u.cleaned_type=u.type.replace(q.eventNamespace(),"");r.apply(s,[u,t])};if(!this.listeners[n]){this.listeners[n]=[]}this.listeners[n].push(o);if(this.isRunning()){this._listen(n,o)}return this},trigger:function(n,o){this.$element().trigger([n,this.eventNamespace()].join("."),[o]);return this},refresh:function(){this.last_location=null;this.trigger("location-changed");return this},before:function(n,o){if(c(n)){o=n;n={}}this.befores.push([n,o]);return this},after:function(n){return this.bind("event-context-after",n)},around:function(n){this.arounds.push(n);return this},isRunning:function(){return this._running},helpers:function(n){g.extend(this.context_prototype.prototype,n);return this},helper:function(n,o){this.context_prototype.prototype[n]=o;return this},run:function(n){if(this.isRunning()){return false}var o=this;g.each(this.listeners.toHash(),function(p,q){g.each(q,function(s,r){o._listen(p,r)})});this.trigger("run",{start_url:n});this._running=true;this.last_location=null;if(this.getLocation()==""&&typeof n!="undefined"){this.setLocation(n)}this._checkLocation();this._location_proxy.bind();this.bind("location-changed",function(){o._checkLocation()});this.bind("submit",function(q){var p=o._checkFormSubmission(g(q.target).closest("form"));return(p===false)?q.preventDefault():false});g(window).bind("beforeunload",function(){o.unload()});return this.trigger("changed")},unload:function(){if(!this.isRunning()){return false}var n=this;this.trigger("unload");this._location_proxy.unbind();this.$element().unbind("submit").removeClass(n.eventNamespace());g.each(this.listeners.toHash(),function(o,p){g.each(p,function(r,q){n._unlisten(o,q)})});this._running=false;return this},bindToAllEvents:function(o){var n=this;g.each(this.APP_EVENTS,function(p,q){n.bind(q,o)});g.each(this.listeners.keys(true),function(q,p){if(n.APP_EVENTS.indexOf(p)==-1){n.bind(p,o)}});return this},routablePath:function(n){return n.replace(j,"")},lookupRoute:function(q,o){var p=this,n=false;this.trigger("lookup-route",{verb:q,path:o});if(typeof this.routes[q]!="undefined"){g.each(this.routes[q],function(s,r){if(p.routablePath(o).match(r.path)){n=r;return false}})}return n},runRoute:function(p,B,r,u){var q=this,z=this.lookupRoute(p,B),o,x,s,w,A,y,v,n;this.log("runRoute",[p,B].join(" "));this.trigger("run-route",{verb:p,path:B,params:r});if(typeof r=="undefined"){r={}}g.extend(r,this._parseQueryString(B));if(z){this.trigger("route-found",{route:z});if((path_params=z.path.exec(this.routablePath(B)))!==null){path_params.shift();g.each(path_params,function(C,D){if(z.param_names[C]){r[z.param_names[C]]=h(D)}else{if(!r.splat){r.splat=[]}r.splat.push(h(D))}})}o=new this.context_prototype(this,p,B,r,u);s=this.arounds.slice(0);A=this.befores.slice(0);v=[o].concat(r.splat);x=function(){var C;while(A.length>0){y=A.shift();if(q.contextMatchesOptions(o,y[0])){C=y[1].apply(o,[o]);if(C===false){return false}}}q.last_route=z;o.trigger("event-context-before",{context:o});C=z.callback.apply(o,v);o.trigger("event-context-after",{context:o});return C};g.each(s.reverse(),function(C,D){var E=x;x=function(){return D.apply(o,[E])}});try{n=x()}catch(t){this.error(["500 Error",p,B].join(" "),t)}return n}else{return this.notFound(p,B)}},contextMatchesOptions:function(q,s,o){var p=s;if(typeof p==="undefined"||p=={}){return true}if(typeof o==="undefined"){o=true}if(typeof p==="string"||c(p.test)){p={path:p}}if(p.only){return this.contextMatchesOptions(q,p.only,true)}else{if(p.except){return this.contextMatchesOptions(q,p.except,false)}}var n=true,r=true;if(p.path){if(c(p.path.test)){n=p.path.test(q.path)}else{n=(p.path.toString()===q.path)}}if(p.verb){r=p.verb===q.verb}return o?(r&&n):!(r&&n)},getLocation:function(){return this._location_proxy.getLocation()},setLocation:function(n){return this._location_proxy.setLocation(n)},swap:function(n){return this.$element().html(n)},templateCache:function(n,o){if(typeof o!="undefined"){return a[n]=o}else{return a[n]}},notFound:function(p,o){var n=this.error(["404 Not Found",p,o].join(" "));return(p==="get")?n:true},error:function(o,n){if(!n){n=new Error()}n.message=[o,n.message].join(" ");this.trigger("error",{message:n.message,error:n});if(this.raise_errors){throw (n)}else{this.log(n.message,n)}},_checkLocation:function(){var n,o;n=this.getLocation();if(n!=this.last_location){this.last_location=n;o=this.runRoute("get",n)}return o},_getFormVerb:function(o){var n=g(o),p;$_method=n.find('input[name="_method"]');if($_method.length>0){p=$_method.val()}if(!p){p=n[0].getAttribute("method")}return g.trim(p.toString().toLowerCase())},_checkFormSubmission:function(p){var n,q,s,r,o;this.trigger("check-form-submission",{form:p});n=g(p);q=n.attr("action");s=this._getFormVerb(n);if(!s||s==""){s="get"}this.log("_checkFormSubmission",n,q,s);if(s==="get"){this.setLocation(q+"?"+n.serialize());o=false}else{r=g.extend({},this._parseFormParams(n));o=this.runRoute(s,q,r,p.get(0))}return(typeof o=="undefined")?false:o},_parseFormParams:function(n){var q={},p=n.serializeArray(),o;for(o=0;o0){this.then(this.callbacks.shift())}},load:function(n,o,q){var p=this;return this.then(function(){var r,s;if(c(o)){q=o;o={}}else{o=g.extend({},o)}if(q){this.then(q)}if(typeof n==="string"){r=!(o.cache===false);delete o.cache;if(o.engine){p.next_engine=o.engine;delete o.engine}if(r&&(s=this.event_context.app.templateCache(n))){return s}this.wait();g.ajax(g.extend({url:n,data:{},type:"get",success:function(t){if(r){p.event_context.app.templateCache(n,t)}p.next(t)}},o));return false}else{if(n.nodeType){return n.innerHTML}if(n.selector){p.next_engine=n.attr("data-engine");if(o.clone===false){return n.remove()[0].innerHTML.toString()}else{return n[0].innerHTML.toString()}}}})},render:function(n,o,p){if(c(n)&&!o){return this.then(n)}else{return this.load(n).interpolate(o,n).then(p)}},collect:function(p,o){var n=this;return this.then(function(){var q="";g.each(p,function(r,t){var s=o.apply(n,[r,t]);q+=s;return s});return q})},renderEach:function(n,o,p,q){if(k(o)){q=p;p=o;o=null}if(!p&&k(this.content)){p=this.content}return this.load(n).collect(p,function(r,s){var t={};o?(t[o]=s):(t=s);return this.event_context.interpolate(this.content,t,n)})},interpolate:function(q,p,n){var o=this;return this.then(function(s,r){if(this.next_engine){p=this.next_engine;this.next_engine=false}var t=o.event_context.interpolate(s,q,p);return n?r+t:t})},swap:function(){return this.then(function(n){this.event_context.swap(n)}).trigger("changed",{})},appendTo:function(n){return this.then(function(o){g(n).append(o)}).trigger("changed",{})},prependTo:function(n){return this.then(function(o){g(n).prepend(o)}).trigger("changed",{})},replace:function(n){return this.then(function(o){g(n).html(o)}).trigger("changed",{})},trigger:function(n,o){return this.then(function(p){if(typeof o=="undefined"){o={content:p}}this.event_context.trigger(n,o)})}});m.EventContext=function(r,q,o,p,n){this.app=r;this.verb=q;this.path=o;this.params=new m.Object(p);this.target=n};m.EventContext.prototype=g.extend({},m.Object.prototype,{$element:function(){return this.app.$element()},engineFor:function(p){var o=this,n;if(c(p)){return p}p=p.toString();if((n=p.match(/\.([^\.]+)$/))){p=n[1]}if(p&&c(o[p])){return o[p]}if(o.app.template_engine){return this.engineFor(o.app.template_engine)}return function(q,r){return q}},interpolate:function(o,p,n){return this.engineFor(n).apply(this,[o,p])},render:function(n,o,p){return new m.RenderContext(this).render(n,o,p)},load:function(n,o,p){return new m.RenderContext(this).load(n,o,p)},partial:function(n,o){return this.render(n,o).swap()},redirect:function(){var p,o=b(arguments),n=this.app.getLocation();if(o.length>1){o.unshift("/");p=this.join.apply(this,o)}else{p=o[0]}this.trigger("redirect",{to:p});this.app.last_location=this.path;this.app.setLocation(p);if(n==p){this.app.trigger("location-changed")}},trigger:function(n,o){if(typeof o=="undefined"){o={}}if(!o.context){o.context=this}return this.app.trigger(n,o)},eventNamespace:function(){return this.app.eventNamespace()},swap:function(n){return this.app.swap(n)},notFound:function(){return this.app.notFound(this.verb,this.path)},toString:function(){return"Sammy.EventContext: "+[this.verb,this.path,this.params].join(" ")}});g.sammy=window.Sammy=m})(jQuery); rabbitmq-server-3.2.4/plugins-src/rabbitmq-management/priv/www/js/help.js0000644000000000000000000003071012305126066025214 0ustar rootrootHELP = { 'exchange-auto-delete': 'If yes, the exchange will delete itself after at least one queue or exchange has been bound to this one, and then all queues or exchanges have been unbound.', 'exchange-internal': 'If yes, clients cannot publish to this exchange directly. It can only be used with exchange to exchange bindings.', 'exchange-alternate': 'If messages to this exchange cannot otherwise be routed, send them to the alternate exchange named here.
    (Sets the "alternate-exchange" argument.)', 'queue-message-ttl': 'How long a message published to a queue can live before it is discarded (milliseconds).
    (Sets the "x-message-ttl" argument.)', 'queue-expires': 'How long a queue can be unused for before it is automatically deleted (milliseconds).
    (Sets the "x-expires" argument.)', 'queue-max-length': 'How many (ready) messages a queue can contain before it starts to drop them from its head.
    (Sets the "x-max-length" argument.)', 'queue-auto-delete': 'If yes, the queue will delete itself after at least one consumer has connected, and then all consumers have disconnected.', 'queue-dead-letter-exchange': 'Optional name of an exchange to which messages will be republished if they are rejected or expire.
    (Sets the "x-dead-letter-exchange" argument.)', 'queue-dead-letter-routing-key': 'Optional replacement routing key to use when a message is dead-lettered. If this is not set, the message\'s original routing key will be used.
    (Sets the "x-dead-letter-routing-key" argument.)', 'queue-memory-resident': '

    Number of messages in the queue which are held in memory. These messages may also be on disc (if they are persistent).

    There may be a limit imposed in order to manage total memory use. If the number of memory-resident messages in the queue exceeds the limit some messages will be paged out.

    ', 'queue-persistent': 'Number of messages in the queue which are persistent. These messages will be on disc but may also be available in memory. Note that if a message is published as persistent but routed to a transient queue it is not considered persistent by that queue, so transient queues will always report 0 persistent messages.', 'internal-users-only': 'Only users within the internal RabbitMQ database are shown here. Other users (e.g. those authenticated over LDAP) will not appear.', 'export-definitions': 'The definitions consist of users, virtual hosts, permissions, parameters, exchanges, queues and bindings. They do not include the contents of queues. Exclusive queues will not be exported.', 'import-definitions': 'The definitions that are imported will be merged with the current definitions. If an error occurs during import, any changes made will not be rolled back.', 'exchange-rates-incoming': 'The incoming rate is the rate at which messages are published directly to this exchange.', 'exchange-rates-outgoing': 'The outgoing rate is the rate at which messages enter queues, having been published directly to this exchange.', 'channel-mode': 'Channel guarantee mode. Can be one of the following, or neither:
    \
    \
    Cconfirm
    \
    Channel will send streaming publish confirmations.
    \
    Ttransactional
    \
    Channel is transactional.
    \
    ', 'file-descriptors': '

    File descriptor count and limit, as reported by the operating \ system. The count includes network sockets and file handles.

    \

    To optimize disk access RabbitMQ uses as many free descriptors as are \ available, so the count may safely approach the limit. \ However, if most of the file descriptors are used by sockets then \ persister performance will be negatively impacted.

    \

    To change the limit on Unix / Linux, use "ulimit -n". To change \ the limit on Windows, set the ERL_MAX_PORTS environment variable

    \

    To report used file handles on Windows, handle.exe from \ sysinternals must be installed in your path. You can download it \ here.

    ', 'socket-descriptors': 'The network sockets count and limit managed by RabbitMQ.
    \ When the limit is exhausted RabbitMQ will stop accepting new \ network connections.', 'memory-alarm': '

    The memory \ alarm for this node has gone off. It will block \ incoming network traffic until the memory usage drops below \ the watermark.

    \

    Note that the pale line in this case indicates the high watermark \ in relation to how much memory is used in total.

    ', 'disk-free-alarm': 'The disk \ free space alarm for this node has gone off. It will block \ incoming network traffic until the amount of free space exceeds \ the limit.', 'message-get-requeue': '

    Clicking "Get Message(s)" will consume messages from the queue. \ If requeue is set the message will be put back into the queue in place, \ but "redelivered" will be set on the message.

    \

    If requeue is not set messages will be removed from the queue.

    \

    Furthermore, message payloads will be truncated to 50000 bytes.

    ', 'message-publish-headers': 'Headers can have any name. Only long string headers can be set here.', 'message-publish-properties': '

    You can set other message properties here (delivery mode and headers \ are pulled out as the most common cases).

    \

    Invalid properties will be ignored. Valid properties are:

    \
      \
    • content_type
    • \
    • content_encoding
    • \
    • priority
    • \
    • correlation_id
    • \
    • reply_to
    • \
    • expiration
    • \
    • message_id
    • \
    • timestamp
    • \
    • type
    • \
    • user_id
    • \
    • app_id
    • \
    • cluster_id
    • \
    ', 'string-base64': '

    AMQP message payloads can contain any binary content. They can \ therefore be difficult to display in a browser. The options here \ have the following meanings:

    \
    \
    Auto string / base64
    \
    If the message payload can be interpreted as a string in UTF-8 \ encoding, do so. Otherwise return the payload encoded as \ base64.
    \
    base64
    \
    Return the payload encoded as base64 unconditionally.
    \
    ', 'user-tags': 'Comma-separated list of tags to apply to the user. Currently \ supported \ by the management plugin: \
    \
    management
    \
    \ User can access the management plugin \
    \
    policymaker
    \
    \ User can access the management plugin and manage policies and \ parameters for the vhosts they have access to. \
    \
    monitoring
    \
    \ User can access the management plugin and see all connections and \ channels as well as node-related information. \
    \
    administrator
    \
    \ User can do everything monitoring can do, manage users, \ vhosts and permissions, close other user\'s connections, and manage \ policies and parameters for all vhosts. \
    \
    \

    \ Note that you can set any tag here; the links for the above four \ tags are just for convenience. \

    ', 'queued-messages': '
    \
    Ready
    \
    Number of messages that are available to be delivered now.
    \
    Unacknowledged
    \
    Number of messages for which the server is waiting for acknowledgement.
    \
    Total
    \
    The total of these two numbers.
    \
    \ Note that the rate of change of total queued messages does \ not include messages removed due to queue deletion.', 'message-rates': 'Only rates for which some activity is taking place will be shown.\
    \
    Publish
    \
    Rate at which messages are entering the server.
    \
    Confirm
    \
    Rate at which the server is confirming publishes.
    \
    Deliver
    \
    Rate at which messages requiring acknowledgement are being delivered in response to basic.consume.
    \
    Deliver (noack)
    \
    Rate at which messages not requiring acknowledgement are being delivered in response to basic.consume.
    \
    Get
    \
    Rate at which messages requiring acknowledgement are being delivered in response to basic.get.
    \
    Get (noack)
    \
    Rate at which messages not requiring acknowledgement are being delivered in response to basic.get.
    \
    Acknowledge
    \
    Rate at which messages are being acknowledged.
    \
    Redelivered
    \
    Rate at which messages with the \'redelivered\' flag set are being delivered. Note that these messages will also be counted in one of the delivery rates above.
    \
    Return
    \
    Rate at which basic.return is sent to publishers for unroutable messages published with the \'mandatory\' flag set.
    \
    ', 'disk-monitoring-no-watermark' : 'There is no disk space low watermark set. RabbitMQ will not take any action to avoid running out of disk space.', 'resource-counts' : 'Shows total number of objects for all virtual hosts the current user has access to.', 'memory-use' : '

    Note that the memory details shown here are only updated on request - they could be too expensive to calculate every few seconds on a busy server.

    Read more on memory use.

    ', 'policy-definitions' : '
    \
    ha-mode
    \
    \ One of all, exactly\ or nodes.\
    \
    ha-params
    \
    \ Absent if ha-mode is all, a number\ if ha-mode is exactly, or a list\ of strings if ha-mode is nodes.\
    \
    ha-sync-mode
    \
    \ One of manual or automatic.\
    \
    alternate-exchange
    \
    \ The name of an alternate exchange.\
    \
    dead-letter-exchange
    \
    \ The name of a dead letter exchange.\
    \
    dead-letter-routing-key
    \
    \ Key to use when dead-lettering.\
    \
    message-ttl
    \
    \ Per-queue message TTL, in milliseconds.\
    \
    expires
    \
    \ Queue TTL, in milliseconds.\
    \
    max-length
    \
    \ Maximum queue length, in messages.\
    \
    federation-upstream-set
    \
    \ A string; only if the federation plugin is enabled.\
    \
    ', 'handle-exe' : 'In order to monitor the number of file descriptors in use on Windows, RabbitMQ needs the handle.exe command line tool from Microsoft. Download it and place it in the path (e.g. in C:\Windows).', 'foo': 'foo' // No comma. }; function help(id) { show_popup('help', HELP[id]); } rabbitmq-server-3.2.4/plugins-src/rabbitmq-management/priv/www/js/json2.js0000644000000000000000000004174612305126066025332 0ustar rootroot/* http://www.JSON.org/json2.js 2010-08-25 Public Domain. NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK. See http://www.JSON.org/js.html This code should be minified before deployment. See http://javascript.crockford.com/jsmin.html USE YOUR OWN COPY. IT IS EXTREMELY UNWISE TO LOAD CODE FROM SERVERS YOU DO NOT CONTROL. This file creates a global JSON object containing two methods: stringify and parse. JSON.stringify(value, replacer, space) value any JavaScript value, usually an object or array. replacer an optional parameter that determines how object values are stringified for objects. It can be a function or an array of strings. space an optional parameter that specifies the indentation of nested structures. If it is omitted, the text will be packed without extra whitespace. If it is a number, it will specify the number of spaces to indent at each level. If it is a string (such as '\t' or ' '), it contains the characters used to indent at each level. This method produces a JSON text from a JavaScript value. When an object value is found, if the object contains a toJSON method, its toJSON method will be called and the result will be stringified. A toJSON method does not serialize: it returns the value represented by the name/value pair that should be serialized, or undefined if nothing should be serialized. The toJSON method will be passed the key associated with the value, and this will be bound to the value For example, this would serialize Dates as ISO strings. Date.prototype.toJSON = function (key) { function f(n) { // Format integers to have at least two digits. return n < 10 ? '0' + n : n; } return this.getUTCFullYear() + '-' + f(this.getUTCMonth() + 1) + '-' + f(this.getUTCDate()) + 'T' + f(this.getUTCHours()) + ':' + f(this.getUTCMinutes()) + ':' + f(this.getUTCSeconds()) + 'Z'; }; You can provide an optional replacer method. It will be passed the key and value of each member, with this bound to the containing object. The value that is returned from your method will be serialized. If your method returns undefined, then the member will be excluded from the serialization. If the replacer parameter is an array of strings, then it will be used to select the members to be serialized. It filters the results such that only members with keys listed in the replacer array are stringified. Values that do not have JSON representations, such as undefined or functions, will not be serialized. Such values in objects will be dropped; in arrays they will be replaced with null. You can use a replacer function to replace those with JSON values. JSON.stringify(undefined) returns undefined. The optional space parameter produces a stringification of the value that is filled with line breaks and indentation to make it easier to read. If the space parameter is a non-empty string, then that string will be used for indentation. If the space parameter is a number, then the indentation will be that many spaces. Example: text = JSON.stringify(['e', {pluribus: 'unum'}]); // text is '["e",{"pluribus":"unum"}]' text = JSON.stringify(['e', {pluribus: 'unum'}], null, '\t'); // text is '[\n\t"e",\n\t{\n\t\t"pluribus": "unum"\n\t}\n]' text = JSON.stringify([new Date()], function (key, value) { return this[key] instanceof Date ? 'Date(' + this[key] + ')' : value; }); // text is '["Date(---current time---)"]' JSON.parse(text, reviver) This method parses a JSON text to produce an object or array. It can throw a SyntaxError exception. The optional reviver parameter is a function that can filter and transform the results. It receives each of the keys and values, and its return value is used instead of the original value. If it returns what it received, then the structure is not modified. If it returns undefined then the member is deleted. Example: // Parse the text. Values that look like ISO date strings will // be converted to Date objects. myData = JSON.parse(text, function (key, value) { var a; if (typeof value === 'string') { a = /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)Z$/.exec(value); if (a) { return new Date(Date.UTC(+a[1], +a[2] - 1, +a[3], +a[4], +a[5], +a[6])); } } return value; }); myData = JSON.parse('["Date(09/09/2001)"]', function (key, value) { var d; if (typeof value === 'string' && value.slice(0, 5) === 'Date(' && value.slice(-1) === ')') { d = new Date(value.slice(5, -1)); if (d) { return d; } } return value; }); This is a reference implementation. You are free to copy, modify, or redistribute. */ /*jslint evil: true, strict: false */ /*members "", "\b", "\t", "\n", "\f", "\r", "\"", JSON, "\\", apply, call, charCodeAt, getUTCDate, getUTCFullYear, getUTCHours, getUTCMinutes, getUTCMonth, getUTCSeconds, hasOwnProperty, join, lastIndex, length, parse, prototype, push, replace, slice, stringify, test, toJSON, toString, valueOf */ // Create a JSON object only if one does not already exist. We create the // methods in a closure to avoid creating global variables. if (!this.JSON) { this.JSON = {}; } (function () { function f(n) { // Format integers to have at least two digits. return n < 10 ? '0' + n : n; } if (typeof Date.prototype.toJSON !== 'function') { Date.prototype.toJSON = function (key) { return isFinite(this.valueOf()) ? this.getUTCFullYear() + '-' + f(this.getUTCMonth() + 1) + '-' + f(this.getUTCDate()) + 'T' + f(this.getUTCHours()) + ':' + f(this.getUTCMinutes()) + ':' + f(this.getUTCSeconds()) + 'Z' : null; }; String.prototype.toJSON = Number.prototype.toJSON = Boolean.prototype.toJSON = function (key) { return this.valueOf(); }; } var cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g, escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g, gap, indent, meta = { // table of character substitutions '\b': '\\b', '\t': '\\t', '\n': '\\n', '\f': '\\f', '\r': '\\r', '"' : '\\"', '\\': '\\\\' }, rep; function quote(string) { // If the string contains no control characters, no quote characters, and no // backslash characters, then we can safely slap some quotes around it. // Otherwise we must also replace the offending characters with safe escape // sequences. escapable.lastIndex = 0; return escapable.test(string) ? '"' + string.replace(escapable, function (a) { var c = meta[a]; return typeof c === 'string' ? c : '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4); }) + '"' : '"' + string + '"'; } function str(key, holder) { // Produce a string from holder[key]. var i, // The loop counter. k, // The member key. v, // The member value. length, mind = gap, partial, value = holder[key]; // If the value has a toJSON method, call it to obtain a replacement value. if (value && typeof value === 'object' && typeof value.toJSON === 'function') { value = value.toJSON(key); } // If we were called with a replacer function, then call the replacer to // obtain a replacement value. if (typeof rep === 'function') { value = rep.call(holder, key, value); } // What happens next depends on the value's type. switch (typeof value) { case 'string': return quote(value); case 'number': // JSON numbers must be finite. Encode non-finite numbers as null. return isFinite(value) ? String(value) : 'null'; case 'boolean': case 'null': // If the value is a boolean or null, convert it to a string. Note: // typeof null does not produce 'null'. The case is included here in // the remote chance that this gets fixed someday. return String(value); // If the type is 'object', we might be dealing with an object or an array or // null. case 'object': // Due to a specification blunder in ECMAScript, typeof null is 'object', // so watch out for that case. if (!value) { return 'null'; } // Make an array to hold the partial results of stringifying this object value. gap += indent; partial = []; // Is the value an array? if (Object.prototype.toString.apply(value) === '[object Array]') { // The value is an array. Stringify every element. Use null as a placeholder // for non-JSON values. length = value.length; for (i = 0; i < length; i += 1) { partial[i] = str(i, value) || 'null'; } // Join all of the elements together, separated with commas, and wrap them in // brackets. v = partial.length === 0 ? '[]' : gap ? '[\n' + gap + partial.join(',\n' + gap) + '\n' + mind + ']' : '[' + partial.join(',') + ']'; gap = mind; return v; } // If the replacer is an array, use it to select the members to be stringified. if (rep && typeof rep === 'object') { length = rep.length; for (i = 0; i < length; i += 1) { k = rep[i]; if (typeof k === 'string') { v = str(k, value); if (v) { partial.push(quote(k) + (gap ? ': ' : ':') + v); } } } } else { // Otherwise, iterate through all of the keys in the object. for (k in value) { if (Object.hasOwnProperty.call(value, k)) { v = str(k, value); if (v) { partial.push(quote(k) + (gap ? ': ' : ':') + v); } } } } // Join all of the member texts together, separated with commas, // and wrap them in braces. v = partial.length === 0 ? '{}' : gap ? '{\n' + gap + partial.join(',\n' + gap) + '\n' + mind + '}' : '{' + partial.join(',') + '}'; gap = mind; return v; } } // If the JSON object does not yet have a stringify method, give it one. if (typeof JSON.stringify !== 'function') { JSON.stringify = function (value, replacer, space) { // The stringify method takes a value and an optional replacer, and an optional // space parameter, and returns a JSON text. The replacer can be a function // that can replace values, or an array of strings that will select the keys. // A default replacer method can be provided. Use of the space parameter can // produce text that is more easily readable. var i; gap = ''; indent = ''; // If the space parameter is a number, make an indent string containing that // many spaces. if (typeof space === 'number') { for (i = 0; i < space; i += 1) { indent += ' '; } // If the space parameter is a string, it will be used as the indent string. } else if (typeof space === 'string') { indent = space; } // If there is a replacer, it must be a function or an array. // Otherwise, throw an error. rep = replacer; if (replacer && typeof replacer !== 'function' && (typeof replacer !== 'object' || typeof replacer.length !== 'number')) { throw new Error('JSON.stringify'); } // Make a fake root object containing our value under the key of ''. // Return the result of stringifying the value. return str('', {'': value}); }; } // If the JSON object does not yet have a parse method, give it one. if (typeof JSON.parse !== 'function') { JSON.parse = function (text, reviver) { // The parse method takes a text and an optional reviver function, and returns // a JavaScript value if the text is a valid JSON text. var j; function walk(holder, key) { // The walk method is used to recursively walk the resulting structure so // that modifications can be made. var k, v, value = holder[key]; if (value && typeof value === 'object') { for (k in value) { if (Object.hasOwnProperty.call(value, k)) { v = walk(value, k); if (v !== undefined) { value[k] = v; } else { delete value[k]; } } } } return reviver.call(holder, key, value); } // Parsing happens in four stages. In the first stage, we replace certain // Unicode characters with escape sequences. JavaScript handles many characters // incorrectly, either silently deleting them, or treating them as line endings. text = String(text); cx.lastIndex = 0; if (cx.test(text)) { text = text.replace(cx, function (a) { return '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4); }); } // In the second stage, we run the text against regular expressions that look // for non-JSON patterns. We are especially concerned with '()' and 'new' // because they can cause invocation, and '=' because it can cause mutation. // But just to be safe, we want to reject all unexpected forms. // We split the second stage into 4 regexp operations in order to work around // crippling inefficiencies in IE's and Safari's regexp engines. First we // replace the JSON backslash pairs with '@' (a non-JSON character). Second, we // replace all simple value tokens with ']' characters. Third, we delete all // open brackets that follow a colon or comma or that begin the text. Finally, // we look to see that the remaining characters are only whitespace or ']' or // ',' or ':' or '{' or '}'. If that is so, then the text is safe for eval. if (/^[\],:{}\s]*$/ .test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@') .replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']') .replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) { // In the third stage we use the eval function to compile the text into a // JavaScript structure. The '{' operator is subject to a syntactic ambiguity // in JavaScript: it can begin a block or an object literal. We wrap the text // in parens to eliminate the ambiguity. j = eval('(' + text + ')'); // In the optional fourth stage, we recursively walk the new structure, passing // each name/value pair to a reviver function for possible transformation. return typeof reviver === 'function' ? walk({'': j}, '') : j; } // If the text is not JSON parseable, then a SyntaxError is thrown. throw new SyntaxError('JSON.parse'); }; } }()); rabbitmq-server-3.2.4/plugins-src/rabbitmq-management/priv/www/js/global.js0000644000000000000000000001460712305126066025533 0ustar rootroot/////////////////////// // // // Genuine constants // // // /////////////////////// // Just used below function map(list) { var res = {}; for (i in list) { res[list[i]] = ''; } return res; } // Extension arguments that we know about and present specially in the UI. var KNOWN_ARGS = {'alternate-exchange': {'short': 'AE', 'type': 'string'}, 'x-message-ttl': {'short': 'TTL', 'type': 'int'}, 'x-expires': {'short': 'Exp', 'type': 'int'}, 'x-max-length': {'short': 'Lim', 'type': 'int'}, 'x-dead-letter-exchange': {'short': 'DLX', 'type': 'string'}, 'x-dead-letter-routing-key': {'short': 'DLK', 'type': 'string'}}; // Things that are like arguments that we format the same way in listings. var IMPLICIT_ARGS = {'durable': {'short': 'D', 'type': 'boolean'}, 'auto-delete': {'short': 'AD', 'type': 'boolean'}, 'internal': {'short': 'I', 'type': 'boolean'}}; // Both the above var ALL_ARGS = {}; for (var k in KNOWN_ARGS) ALL_ARGS[k] = KNOWN_ARGS[k]; for (var k in IMPLICIT_ARGS) ALL_ARGS[k] = IMPLICIT_ARGS[k]; var NAVIGATION = {'Overview': ['#/', "management"], 'Connections': ['#/connections', "management"], 'Channels': ['#/channels', "management"], 'Exchanges': ['#/exchanges', "management"], 'Queues': ['#/queues', "management"], 'Admin': [{'Users': ['#/users', "administrator"], 'Virtual Hosts': ['#/vhosts', "administrator"], 'Policies': ['#/policies', "policymaker"]}, "policymaker"] }; var CHART_PERIODS = {'60|5': 'Last minute', '600|5': 'Last ten minutes', '3600|60': 'Last hour', '28800|600': 'Last eight hours', '86400|1800': 'Last day'}; /////////////////////////////////////////////////////////////////////////// // // // Mostly constant, typically get set once at startup (or rarely anyway) // // // /////////////////////////////////////////////////////////////////////////// // All these are to do with hiding UI elements if var statistics_level; // ...there are no fine stats var user_administrator; // ...user is not an admin var user_monitor; // ...user cannot monitor var nodes_interesting; // ...we are not in a cluster var vhosts_interesting; // ...there is only one vhost var rabbit_versions_interesting; // ...all cluster nodes run the same version // Extensions write to this, the dispatcher maker reads it var dispatcher_modules = []; // We need to know when all extension script files have loaded var extension_count; // The dispatcher needs access to the Sammy app var app; // Used for the new exchange form, and to display broken exchange types var exchange_types; // Used for access control to the menu var user_tags; // Set up the above vars function setup_global_vars(user) { var overview = JSON.parse(sync_get('/overview')); statistics_level = overview.statistics_level; replace_content('login-details', '

    User: ' + user.name + '

    ' + '

    RabbitMQ ' + overview.rabbitmq_version + ', Erlang ' + overview.erlang_version + '

    '); user_tags = expand_user_tags(user.tags.split(",")); user_administrator = jQuery.inArray("administrator", user_tags) != -1; user_monitor = jQuery.inArray("monitoring", user_tags) != -1; nodes_interesting = false; rabbit_versions_interesting = false; if (user_monitor) { var nodes = JSON.parse(sync_get('/nodes')); if (nodes.length > 1) { nodes_interesting = true; var v = ''; for (var i = 0; i < nodes.length; i++) { var v1 = fmt_rabbit_version(nodes[i].applications); if (v1 != 'unknown') { if (v != '' && v != v1) rabbit_versions_interesting = true; v = v1; } } } } vhosts_interesting = JSON.parse(sync_get('/vhosts')).length > 1; current_vhost = get_pref('vhost'); exchange_types = overview.exchange_types; } function expand_user_tags(tags) { var new_tags = []; for (var i = 0; i < tags.length; i++) { var tag = tags[i]; new_tags.push(tag); switch (tag) { // Note deliberate fall-through case "administrator": new_tags.push("monitoring"); new_tags.push("policymaker"); case "monitoring": new_tags.push("management"); break; case "policymaker": new_tags.push("management"); default: break; } } return new_tags; } //////////////////////////////////////////////////// // // // Change frequently (typically every "new page") // // // //////////////////////////////////////////////////// // Which top level template we're showing var current_template; // Which JSON requests do we need to populate it var current_reqs; // Which tab is highlighted var current_highlight; // Which vhost are we looking at var current_vhost = ''; // What is our current sort order var current_sort; var current_sort_reverse = false; var current_filter = ''; var current_truncate; // The timer object for auto-updates, and how often it goes off var timer; var timer_interval; // When did we last connect successfully (for the "could not connect" error) var last_successful_connect; // Every 200 updates without user interaction we do a full refresh, to // work around memory leaks in browser DOM implementations. // TODO: maybe we don't need this any more? var update_counter = 0; // Holds chart data in between writing the div in an ejs and rendering // the chart. var chart_data = {}; rabbitmq-server-3.2.4/plugins-src/rabbitmq-management/priv/www/js/ejs.js0000644000000000000000000003112212305126066025043 0ustar rootroot(function(){var rsplit=function(string,regex){var result=regex.exec(string),retArr=new Array(),first_idx,last_idx,first_bit;while(result!=null){first_idx=result.index;last_idx=regex.lastIndex;if((first_idx)!=0){first_bit=string.substring(0,first_idx);retArr.push(string.substring(0,first_idx));string=string.slice(first_idx)}retArr.push(result[0]);string=string.slice(result[0].length);result=regex.exec(string)}if(!string==""){retArr.push(string)}return retArr},chop=function(string){return string.substr(0,string.length-1)},extend=function(d,s){for(var n in s){if(s.hasOwnProperty(n)){d[n]=s[n]}}};EJS=function(options){options=typeof options=="string"?{view:options}:options;this.set_options(options);if(options.precompiled){this.template={};this.template.process=options.precompiled;EJS.update(this.name,this);return }if(options.element){if(typeof options.element=="string"){var name=options.element;options.element=document.getElementById(options.element);if(options.element==null){throw name+"does not exist!"}}if(options.element.value){this.text=options.element.value}else{this.text=options.element.innerHTML}this.name=options.element.id;this.type="["}else{if(options.url){options.url=EJS.endExt(options.url,this.extMatch);this.name=this.name?this.name:options.url;var url=options.url;var template=EJS.get(this.name,this.cache);if(template){return template}if(template==EJS.INVALID_PATH){return null}try{this.text=EJS.request(url+(this.cache?"":"?"+Math.random()))}catch(e){}if(this.text==null){throw ({type:"EJS",message:"There is no template at "+url})}}}var template=new EJS.Compiler(this.text,this.type);template.compile(options,this.name);EJS.update(this.name,this);this.template=template};EJS.prototype={render:function(object,extra_helpers){object=object||{};this._extra_helpers=extra_helpers;var v=new EJS.Helpers(object,extra_helpers||{});return this.template.process.call(object,object,v)},update:function(element,options){if(typeof element=="string"){element=document.getElementById(element)}if(options==null){_template=this;return function(object){EJS.prototype.update.call(_template,element,object)}}if(typeof options=="string"){params={};params.url=options;_template=this;params.onComplete=function(request){var object=eval(request.responseText);EJS.prototype.update.call(_template,element,object)};EJS.ajax_request(params)}else{element.innerHTML=this.render(options)}},out:function(){return this.template.out},set_options:function(options){this.type=options.type||EJS.type;this.cache=options.cache!=null?options.cache:EJS.cache;this.text=options.text||null;this.name=options.name||null;this.ext=options.ext||EJS.ext;this.extMatch=new RegExp(this.ext.replace(/\./,"."))}};EJS.endExt=function(path,match){if(!path){return null}match.lastIndex=0;return path+(match.test(path)?"":this.ext)};EJS.Scanner=function(source,left,right){extend(this,{left_delimiter:left+"%",right_delimiter:"%"+right,double_left:left+"%%",double_right:"%%"+right,left_equal:left+"%=",left_comment:left+"%#"});this.SplitRegexp=left=="["?/(\[%%)|(%%\])|(\[%=)|(\[%#)|(\[%)|(%\]\n)|(%\])|(\n)/:new RegExp("("+this.double_left+")|(%%"+this.double_right+")|("+this.left_equal+")|("+this.left_comment+")|("+this.left_delimiter+")|("+this.right_delimiter+"\n)|("+this.right_delimiter+")|(\n)");this.source=source;this.stag=null;this.lines=0};EJS.Scanner.to_text=function(input){if(input==null||input===undefined){return""}if(input instanceof Date){return input.toDateString()}if(input.toString){return input.toString()}return""};EJS.Scanner.prototype={scan:function(block){scanline=this.scanline;regex=this.SplitRegexp;if(!this.source==""){var source_split=rsplit(this.source,/\n/);for(var i=0;i0){for(var i=0;i0){buff.push(put_cmd+'"'+clean(content)+'")')}content="";break;case scanner.double_left:content=content+scanner.left_delimiter;break;default:content=content+token;break}}else{switch(token){case scanner.right_delimiter:switch(scanner.stag){case scanner.left_delimiter:if(content[content.length-1]=="\n"){content=chop(content);buff.push(content);buff.cr()}else{buff.push(content)}break;case scanner.left_equal:buff.push(insert_cmd+"(EJS.Scanner.to_text("+content+")))");break}scanner.stag=null;content="";break;case scanner.double_right:content=content+scanner.right_delimiter;break;default:content=content+token;break}}});if(content.length>0){buff.push(put_cmd+'"'+clean(content)+'")')}buff.close();this.out=buff.script+";";var to_be_evaled="/*"+name+"*/this.process = function(_CONTEXT,_VIEW) { try { with(_VIEW) { with (_CONTEXT) {"+this.out+" return ___ViewO.join('');}}}catch(e){e.lineNumber=null;throw e;}};";try{eval(to_be_evaled)}catch(e){if(typeof JSLINT!="undefined"){JSLINT(this.out);for(var i=0;i").replace(/''/g,"'")}return""}};EJS.newRequest=function(){var factories=[function(){return new ActiveXObject("Msxml2.XMLHTTP")},function(){return new XMLHttpRequest()},function(){return new ActiveXObject("Microsoft.XMLHTTP")}];for(var i=0;i")};EJS.Helpers.prototype.start_tag_for=function(A,B){return this.tag(A,B)};EJS.Helpers.prototype.submit_tag=function(A,B){B=B||{};B.type=B.type||"submit";B.value=A||"Submit";return this.single_tag_for("input",B)};EJS.Helpers.prototype.tag=function(C,E,D){if(!D){var D=">"}var B=" ";for(var A in E){if(E[A]!=null){var F=E[A].toString()}else{var F=""}if(A=="Class"){A="class"}if(F.indexOf("'")!=-1){B+=A+'="'+F+'" '}else{B+=A+"='"+F+"' "}}return"<"+C+B+D};EJS.Helpers.prototype.tag_end=function(A){return""};EJS.Helpers.prototype.text_area_tag=function(A,C,B){B=B||{};B.id=B.id||A;B.name=B.name||A;C=C||"";if(B.size){B.cols=B.size.split("x")[0];B.rows=B.size.split("x")[1];delete B.size}B.cols=B.cols||50;B.rows=B.rows||4;return this.start_tag_for("textarea",B)+C+this.tag_end("textarea")};EJS.Helpers.prototype.text_tag=EJS.Helpers.prototype.text_area_tag;EJS.Helpers.prototype.text_field_tag=function(A,C,B){return this.input_field_tag(A,C,"text",B)};EJS.Helpers.prototype.url_for=function(A){return'window.location="'+A+'";'};EJS.Helpers.prototype.img_tag=function(B,C,A){A=A||{};A.src=B;A.alt=C;return this.single_tag_for("img",A)} rabbitmq-server-3.2.4/plugins-src/rabbitmq-management/priv/www/js/dispatcher.js0000644000000000000000000002065212305126066026416 0ustar rootrootdispatcher_add(function(sammy) { function path(p, r, t) { sammy.get(p, function() { render(r, t, p); }); } sammy.get('#/', function() { var reqs = {'overview': {path: '/overview', options: {ranges: ['lengths-over', 'msg-rates-over']}}}; if (user_monitor) { reqs['nodes'] = '/nodes'; } render(reqs, 'overview', '#/'); }); sammy.get('#/login/:username/:password', login_route); sammy.get('#/nodes/:name', function() { var name = esc(this.params['name']); render({'node': '/nodes/' + name}, 'node', ''); }); path('#/connections', {'connections': {path: '/connections', options: {sort:true}}}, 'connections'); sammy.get('#/connections/:name', function() { var name = esc(this.params['name']); render({'connection': {path: '/connections/' + name, options: {ranges: ['data-rates-conn']}}, 'channels': '/connections/' + name + '/channels'}, 'connection', '#/connections'); }); sammy.del('#/connections', function() { var options = {headers: { 'X-Reason': this.params['reason'] }}; if (sync_delete(this, '/connections/:name', options)) { go_to('#/connections'); } return false; }); path('#/channels', {'channels': {path: '/channels', options: {sort:true}}}, 'channels'); sammy.get('#/channels/:name', function() { render({'channel': {path: '/channels/' + esc(this.params['name']), options:{ranges:['msg-rates-ch']}}}, 'channel', '#/channels'); }); path('#/exchanges', {'exchanges': {path: '/exchanges', options: {sort:true,vhost:true}}, 'vhosts': '/vhosts'}, 'exchanges'); sammy.get('#/exchanges/:vhost/:name', function() { var path = '/exchanges/' + esc(this.params['vhost']) + '/' + esc(this.params['name']); render({'exchange': {path: path, options: {ranges:['msg-rates-x']}}, 'bindings_source': path + '/bindings/source', 'bindings_destination': path + '/bindings/destination'}, 'exchange', '#/exchanges'); }); sammy.put('#/exchanges', function() { if (sync_put(this, '/exchanges/:vhost/:name')) update(); return false; }); sammy.del('#/exchanges', function() { if (sync_delete(this, '/exchanges/:vhost/:name')) go_to('#/exchanges'); return false; }); sammy.post('#/exchanges/publish', function() { publish_msg(this.params); return false; }); path('#/queues', {'queues': {path: '/queues', options: {sort:true,vhost:true}}, 'vhosts': '/vhosts'}, 'queues'); sammy.get('#/queues/:vhost/:name', function() { var path = '/queues/' + esc(this.params['vhost']) + '/' + esc(this.params['name']); render({'queue': {path: path, options: {ranges:['lengths-q', 'msg-rates-q']}}, 'bindings': path + '/bindings'}, 'queue', '#/queues'); }); sammy.put('#/queues', function() { if (sync_put(this, '/queues/:vhost/:name')) update(); return false; }); sammy.del('#/queues', function() { if (this.params['mode'] == 'delete') { if (sync_delete(this, '/queues/:vhost/:name')) go_to('#/queues'); } else if (this.params['mode'] == 'purge') { if (sync_delete(this, '/queues/:vhost/:name/contents')) { show_popup('info', "Queue purged"); update_partial(); } } return false; }); sammy.post('#/queues/get', function() { get_msgs(this.params); return false; }); sammy.post('#/queues/actions', function() { if (sync_post(this, '/queues/:vhost/:name/actions')) // We can't refresh fast enough, it's racy. So grey // the button and wait for a normal refresh. $('#action-button').addClass('wait').prop('disabled', true); return false; }); sammy.post('#/bindings', function() { if (sync_post(this, '/bindings/:vhost/e/:source/:destination_type/:destination')) update(); return false; }); sammy.del('#/bindings', function() { if (sync_delete(this, '/bindings/:vhost/e/:source/:destination_type/:destination/:properties_key')) update(); return false; }); path('#/vhosts', {'vhosts': {path: '/vhosts', options: {sort:true}}, 'permissions': '/permissions'}, 'vhosts'); sammy.get('#/vhosts/:id', function() { render({'vhost': {path: '/vhosts/' + esc(this.params['id']), options: {ranges: ['lengths-vhost', 'msg-rates-vhost', 'data-rates-vhost']}}, 'permissions': '/vhosts/' + esc(this.params['id']) + '/permissions', 'users': '/users/'}, 'vhost', '#/vhosts'); }); sammy.put('#/vhosts', function() { if (sync_put(this, '/vhosts/:name')) { update_vhosts(); update(); } return false; }); sammy.del('#/vhosts', function() { if (sync_delete(this, '/vhosts/:name')) { update_vhosts(); go_to('#/vhosts'); } return false; }); path('#/users', {'users': {path: '/users', options: {sort:true}}, 'permissions': '/permissions'}, 'users'); sammy.get('#/users/:id', function() { render({'user': '/users/' + esc(this.params['id']), 'permissions': '/users/' + esc(this.params['id']) + '/permissions', 'vhosts': '/vhosts/'}, 'user', '#/users'); }); sammy.put('#/users-add', function() { if (sync_put(this, '/users/:username')) update(); return false; }); sammy.put('#/users-modify', function() { if (sync_put(this, '/users/:username')) go_to('#/users'); return false; }); sammy.del('#/users', function() { if (sync_delete(this, '/users/:username')) go_to('#/users'); return false; }); sammy.put('#/permissions', function() { if (sync_put(this, '/permissions/:vhost/:username')) update(); return false; }); sammy.del('#/permissions', function() { if (sync_delete(this, '/permissions/:vhost/:username')) update(); return false; }); path('#/policies', {'policies': '/policies', 'vhosts': '/vhosts'}, 'policies'); sammy.get('#/policies/:vhost/:id', function() { render({'policy': '/policies/' + esc(this.params['vhost']) + '/' + esc(this.params['id'])}, 'policy', '#/policies'); }); sammy.put('#/policies', function() { put_policy(this, ['name', 'pattern', 'policy'], ['priority'], []); return false; }); sammy.del('#/policies', function() { if (sync_delete(this, '/policies/:vhost/:name')) go_to('#/policies'); return false; }); sammy.put('#/logout', function() { document.cookie = 'auth=; expires=Thu, 01 Jan 1970 00:00:00 GMT'; location.reload(); }); sammy.get('#/import-succeeded', function() { render({}, 'import-succeeded', '#/overview'); }); sammy.put('#/rate-options', function() { update_rate_options(this); }); }); rabbitmq-server-3.2.4/plugins-src/rabbitmq-management/priv/www/css/0000755000000000000000000000000012305126066024101 5ustar rootrootrabbitmq-server-3.2.4/plugins-src/rabbitmq-management/priv/www/css/evil.css0000644000000000000000000000003712305126066025552 0ustar rootroot#login { text-align: center; } rabbitmq-server-3.2.4/plugins-src/rabbitmq-management/priv/www/css/main.css0000644000000000000000000003245312305126066025546 0ustar rootrootbody { font: 12px Verdana,sans-serif; color: #484848; padding: 8px 35px; } #login table { margin: auto; } #login p { text-align: center; } #logo { margin-bottom: 20px; } #logo img { border: none; } #login-version { float: right; color: #444; } #login-version form { float: left; display: block; margin-left: 10px; } #login-version form input { padding: 5px; border: 1px solid #ddd !important; color: #666 !important; background: none; } #login-details { float: left; } #login-details p { padding: 0 0 0.2em 0; margin: 0; text-align: right; } #login-details b { color: black; font-weight: normal; } #menu ul { float: left; padding: 0; margin: 0; } #menu li { float: left; list-style-type: none; padding: 0 2em 0 0; } #menu li a { display: block; padding: 0.5em; } #menu { border-bottom: 1px solid #FF8C00; overflow: auto; width: 100%; } #menu a { color: #444; font-weight: bold; text-decoration: none; } #main a { color: black; font-weight: bold; text-decoration: none; } #main a:hover { color: #222; } #menu a.selected { background-color: #F60; color:white; -moz-border-radius: 8px 8px 0 0; border-radius: 8px 8px 0 0; } #menu a:hover { color: black; } #menu a.selected:hover { color: white; } #vhost-form { float: right; padding: 0; margin: 0; } #main.with-rhs { margin-right: 210px; } #rhs { float: right; width: 200px; padding-top: 10px; } #rhs ul { padding: 0; margin: 0; } #rhs li { list-style-type: none; padding: 0; } #rhs a { display: block; padding: 0.5em; color: #444; font-weight: bold; text-decoration: none; } #rhs a.selected { background-color: #F60; color:white; -moz-border-radius: 8px 0 0 8px; border-radius: 8px 0 0 8px; } h1 { font-size: 2em; font-weight: normal; padding: 0; } b, dt { color: black; font-weight: normal; } dd { margin-bottom: 5px; } div.box, div.section, div.section-hidden { overflow: auto; width: 100%; } .left { float: left; } .right { float: right; } .clear { clear: both; } .help, .rate-options { color: #888; cursor: pointer; } .help:hover, .rate-options:hover { color: #444; } .tag-link { color: #444; cursor: pointer; } .tag-link:hover { color: #888; } .filter { overflow: auto; width: 100%; margin-bottom: 10px; } .filter table { float: left; } .filter p { float: right; padding: 4px; margin: 0; } .filter p.filter-warning { border-radius: 5px; background: #ff8; } .filter-active { background: #99ebff; border-radius: 5px; } .filter-highlight { background: #99ebff; } input#truncate { width: 50px; text-align: right; } table { border-collapse: collapse; } table th { font-weight: normal; color: black; } table th, table td { font: 12px/17px Verdana,sans-serif; padding: 4px; } table.list th, table.list td { vertical-align: top; min-width: 5em; width: auto; } table.list { border-width: 1px; border-bottom: 1px solid #ccc; margin-bottom: 1em; } table.list th, table.list td { border-left: 1px solid #ccc; border-right: 1px solid #ccc; } table.list th { text-align: center; border-top: 1px solid #ccc; border-bottom: 1px solid #ccc; } table.list td a { display: block; width: 100%; } table.list th a.sort { display: block; width: 100%; cursor: pointer; } table.list th a.sort .arrow { color: #888; } table.list td p { margin: 0; padding: 1px 0 0 0; } table.list td p.warning { margin: 0; padding: 5px; } #main .internal-purpose, #main .internal-purpose * { color: #aaa; } div.section table.list, div.section-hidden table.list { margin-bottom: 0; } div.memory-bar { margin: 10px 0 5px 0; border-radius: 5px; border: 1px solid #ddd; float: left; } div.memory-section { float: left; height: 30px; } div.colour-key { float: left; width: 10px; height: 10px; margin: 3px 5px 0 0;} div.memory-info { float: left; padding: 10px 10px 0 0; } button.memory-button { margin-top: 10px; } div.memory_connection_procs { background: #955300; } div.memory_queue_procs { background: #da7900; } div.memory_plugins { background: #ffc884; } div.memory_other_proc { background: #fff4e7; } div.memory_mnesia { background: #005395; } div.memory_msg_index { background: #0079da; } div.memory_mgmt_db { background: #84c8ff; } div.memory_other_ets { background: #e7f4ff; } div.memory_binary { background: #666; } div.memory_code { background: #999; } div.memory_atom { background: #bbb; } div.memory_other_system { background: #ddd; } sub { display: block; font-size: 0.8em; color: #888; } small { font-size: 0.8em; color: #888; } #main sub a { color: #888; } #main sub a:hover { color: #444; } .unknown { color: #888; } table.facts { float: left; margin-right: 50px; } table.facts th { color: black; text-align: right; border-right: 1px solid #ccc; } table.facts th, table.facts td { vertical-align: top; padding: 0 10px 10px 10px; } table.facts-long th { text-align: right; font-weight: bold; } table.facts-long th, table.facts-long td { vertical-align: top; } table.facts-fixed-width th, table.facts-fixed-width td { width: 130px; } table.mini th { border: none; padding: 0 2px 2px 2px; text-align: right; } table.mini td { border: none; padding: 0 2px 2px 2px; } tr.alt1>td { background: #eee; } tr.alt2>td { background: #fff; } div.status-bar, div.status-red, div.status-yellow, div.status-green { text-align: center; } div.status-bar-main, div.status-red, div.status-yellow, div.status-green { border-radius: 5px; -moz-border-radius: 5px; padding: 5px; } div.status-bar sub { white-space: nowrap; } div.status-bar .red, div.status-red { background: #ff7a7a; color: white; } div.status-bar .yellow, div.status-yellow { background: #ffff7b; } div.status-bar .green, div.status-green { background: #98f898; } div.status-bar .red-dark { background: #e24545; color: white; } /* yellow-dark and green-dark can never happen */ div.status-bar .red *, div.status-bar .red-dark *, div.status-red * { color: white; } .l { text-align: left !important; } .c { text-align: center !important; } .r { text-align: right !important; } .t { vertical-align: top !important; } p.status-ok { color: #888; text-align: right; } p.status-error { background: #ff7a7a; color: white; margin-top: 50px !important; } p.status-error th { background: white; } p.warning, div.form-popup-warn { background: #ff8; } div.form-popup-info { background: #8f8; } div.form-popup-help { text-align: left !important; background: #f8f8f8; border: 1px solid #ccc; } div.form-popup-warn, div.form-popup-info, div.form-popup-help { margin: 20px; padding: 15px; border-radius: 10px; -moz-border-radius: 10px; text-align: center; max-width: 600px; z-index: 1; display: none; position: fixed; min-width: 500px; } div.form-popup-warn span, div.form-popup-info span, div.form-popup-help span, div.form-popup-rate-options span { color: black; font-weight: bold; cursor: pointer; } div.form-popup-rate-options { z-index: 1; position: absolute; right: 35px; padding: 15px; background: white; border-left: 1px solid #ccc; border-top: 1px solid #ccc; border-bottom: 1px solid #ccc; border-radius: 10px 0 0 10px; -moz-border-radius: 10px 0 0 10px; } .popup-owner { background: #eee; padding: 5px; border-radius: 3px; -moz-border-radius: 3px; } p.status-error, p.warning { margin: 20px; padding: 15px; border-radius: 10px; -moz-border-radius: 10px; text-align: center; } .highlight { min-width: 120px; font-size: 120%; text-align:center; padding:10px; background-color: #ddd; margin: 0 20px 0 0; color: #888; border-radius: 10px; -moz-border-radius: 10px; } .highlight strong { font-size: 2em; display: block; color: #444; font-weight: normal; } .highlight, .micro-highlight { float: left; } .chart { margin: 0 20px 20px 0; float: left; } .chart-small { width: 400px; height: 100px; } .chart-medium { width: 600px; height: 200px; } .chart-large { width: 800px; height: 300px; } .chart-legend { float: left; } .micro-highlight { min-width: 120px; font-size: 100%; text-align:center; padding:10px; background-color: #ddd; margin: 0 20px 0 0; color: #888; border-radius: 10px; -moz-border-radius: 10px; } .micro-highlight a { font-weight: normal !important; color: #888 !important; } .micro-highlight strong { font-size: 120%; color: #444; font-weight: normal; } div.section, div.section-hidden { margin: 0 0 1em 0; } div.section-invisible div.hider { display: none; } div.section div.hider, div.section-hidden div.hider { padding: 0.5em 0; } div.section h2, div.section-hidden h2 { font-size: 1em; padding: 5px 5px 5px 25px; cursor: pointer; margin: 0; } div.section h2:hover, div.section-hidden h2:hover { color: black; } div.section-invisible h2 { background: white; border-bottom: 1px solid #ddd; background-image: url(../img/collapse.png); background-repeat:no-repeat; background-position:4px 4px; } div.section-visible h2 { background: #f8f8f8; border-bottom: 1px solid #ddd; background-image: url(../img/expand.png); background-repeat:no-repeat; background-position:4px 4px; } form { margin: 0; } form.inline-form { float: left; } form.inline-form-right { float: right; } input, select { padding: 0.2em; } input[type=text], input[type=password] { font: 1.1em Andale Mono, Lucidatypewriter, Courier New, Courier, monospace; border: 1px solid #ccc; } textarea { width: 600px; height: 200px; border: 1px solid #ccc; } .mand { color: #f88; padding: 0 5px;} input[type=submit].wait { cursor: wait; } table.form { margin-bottom: 0.5em; } table.form th { text-align: right; vertical-align: top; } table.form input[type=text], table.form input[type=password] { width: 200px; } table.form input[type=text].wide, table.form input[type=password].wide { width: 300px; } table.form select { width: 200px; } table.form select.narrow { width: 110px; } table.form .multifield { margin: 0; padding: 0; } table.form .multifield td { margin: 0; padding: 0; vertical-align: top; } table.form .multifield td.equals { padding: 3px; } table.form .multifield td input { float: left; } table.form .multifield td select { width: 70px; display: block; float: left; margin-left: 5px; } table.form label { margin-top: 5px; display: block; } .multifield-sub { border: 1px solid #ddd; background: #f8f8f8; padding: 10px; border-radius: 10px; -moz-border-radius: 10px; float: left; margin-bottom: 10px; } label.radio { padding: 5px; border: 1px solid #eee; cursor: pointer; border-radius: 5px; -moz-border-radius: 5px; } table.two-col-layout { width: 100%; } table.two-col-layout > tbody > tr > td { width: 50%; vertical-align: top; } input[type=submit], button { padding: 8px; border-radius: 5px; -moz-border-radius: 5px; color: black !important; text-decoration: none; cursor: pointer; font-weight: normal; } table.list input[type=submit], table.list button { padding: 4px; } input[type=submit], button { background: #ddf; background: -webkit-gradient(linear, left top, left bottom, color-stop(0, #ddf),color-stop(1, #bbf)); border: 1px solid #88d; } input[type=submit]:hover, button:hover { background: #bbf; background: -webkit-gradient(linear, left top, left bottom, color-stop(0, #bbf),color-stop(1, #99d)); border: 1px solid #66b; } input[type=submit][disabled], button[disabled] { background: #aac; } input[type=submit][disabled]:hover, button[disabled]:hover { background: #aac; } h3 { padding: 0 0 2px 0; margin: 1em 0 1em 0; font-size: 1em; border-bottom: 1px solid #E4E4E4; font-weight: normal; } acronym { background: #add; color: #222; padding: 2px 4px; border-radius: 2px; -moz-border-radius: 2px; border: none; cursor: default; } acronym.warning { background: #daa; } .status-red acronym, .status-yellow acronym, .status-green acronym, small acronym, acronym.normal { background: none; color: inherit; padding: 0; border-bottom: 1px dotted; cursor: default; } acronym.type { background: none; color: inherit; padding: 0; border-bottom: 1px dotted #ddd; cursor: default; } div.bindings-wrapper { display: inline-block; } div.bindings-wrapper table { margin: auto; } div.bindings-wrapper p { margin: 10px; text-align: center; } div.bindings-wrapper span.exchange { border: 1px solid #bbb; padding: 10px; border-radius: 10px; -moz-border-radius: 10px; } div.bindings-wrapper span.queue { border: 1px solid #666; padding: 10px; } div.bindings-wrapper td span.exchange, div.bindings-wrapper td span.queue { background: white; display: block; } div.bindings-wrapper span.exchange a, div.bindings-wrapper span.queue a { font-weight: normal !important; } div.bindings-wrapper p.arrow { font-size: 200%; } #footer { overflow: auto; width: 100%; } #footer-nav { padding-top: 5px; } #footer-nav ul { float: left; list-style-type: none; padding: 0; margin: 0;} #footer-nav ul li { float: left; border-right: 1px solid #ccc; padding: 2px 5px 2px 0;} #footer-nav ul li + li { border-right: none; padding: 2px 5px;} #footer-nav ul li a { color: #888; text-decoration: none; } #footer-nav ul li a:hover { color: #444; } #update-form { float: right; margin: 0; padding: 0; } #status { clear: both; } #scratch { display: none; } tr.alt1>td { background: -moz-linear-gradient(center top, #f0f0f0 0%,#e0e0e0 100%); background: -webkit-gradient(linear, left top, left bottom, color-stop(0, #f0f0f0),color-stop(1, #e0e0e0)); } tr.alt2>td { background: -moz-linear-gradient(center top, #f8f8f8 0%,#ffffff 100%); background: -webkit-gradient(linear, left top, left bottom, color-stop(0, #f8f8f8),color-stop(1, #ffffff)); } .highlight, .mini-highlight, .micro-highlight { background: -moz-linear-gradient(center top, #f0f0f0 0%,#e0e0e0 100%); background: -webkit-gradient(linear, left top, left bottom, color-stop(0, #f0f0f0),color-stop(1, #e0e0e0)); border: 1px solid #e0e0e0; } rabbitmq-server-3.2.4/plugins-src/rabbitmq-management/priv/www/img/0000755000000000000000000000000012305126066024065 5ustar rootrootrabbitmq-server-3.2.4/plugins-src/rabbitmq-management/priv/www/img/bg-red.png0000644000000000000000000000033412305126066025733 0ustar rootroot‰PNG  IHDRxô̯{†sRGB®ÎéPLTEâEEârrËVsÚbKGDˆH pHYs  šœtIMEÜ 8€Ç‚tEXtCommentCreated with GIMPW*IDATXÃíDZ À &þÿ³³7uLîîîîîîîîîîîîîîî¿‰ÝøÕWIEND®B`‚rabbitmq-server-3.2.4/plugins-src/rabbitmq-management/priv/www/img/expand.png0000644000000000000000000000033512305126066026053 0ustar rootroot‰PNG  IHDR sRGB®ÎéPLTE¦¦¦¿z…¯tRNS@æØfbKGDˆH pHYs  šœtIMEÚ  0bÚátEXtCommentCreated with GIMPWIDAT×c`Àö?ä?0ð?``?ÀÀÜÀÀˆ[,p~0ñIEND®B`‚rabbitmq-server-3.2.4/plugins-src/rabbitmq-management/priv/www/img/bg-red-dark.png0000644000000000000000000000027612305126066026657 0ustar rootroot‰PNG  IHDRxô̯{†sRGB®ÎéPLTEâEE†¤7K pHYs  šœtIMEÜ  .‚üÃŽtEXtCommentCreated with GIMPWIDATXÃíÁ€þ¯î @âø·IEND®B`‚rabbitmq-server-3.2.4/plugins-src/rabbitmq-management/priv/www/img/rabbitmqlogo.png0000644000000000000000000000634012305126066027260 0ustar rootroot‰PNG  IHDRÌ% ‘ïtEXtSoftwareAdobe ImageReadyqÉe< ‚IDATxÚì\ l×ÝõîÚ»‹½þìú‹P°M, „&åÛB‘)m£ºT¨•PA¢X@©PQi‘ÚRÒ8Š„ IDZ@J*RA ®Ô Õ ŠŠ $1ŸÜØøþ{ýÁßõg?î}swŸÇ³3ogÆìb»{µ²fgÞ{3žwæÜsﻳÚññqMØÂLÓ‡oAØü­µ½µ³§·ã,–$[’ÉhšÈ잦;ô{DöfÿFãÕãݸ­5ÇjŸÊUq&gñ‘‘’÷ý÷kÍ&]Z†nn†~ùfѳOÝðÔúÅËLŠ•ö~+ßU[aÌÛaÈÿ½º¾°¡®;ï«·Ëé×-k¿c±ÄÊï~«â˺懸m‹Kظz=ë‚G†kêkë›.§àÐü”´åÙ9ê ¦üÃÆqÇðÄ÷Œe¦_Mž‰ÁÎÁÃ[ù;Œy?7üèw pv˜ øŒ^¹¨K_h*x]»07Ì%RÖÜÞš­d]½=r[vwÞºWÑ78 z´±½µ­«sÝ7smÖDÅ ã#Œ›s¿&ÑþƒNIÆÁcÍÿêyÔîéiÃ'ÞÝÜ0tb§ù•cA¢´Y`òAÖßß'ûìÎmø‹„·hþt‘°§¹­åë†:Øz+»U®gO@“‰;Ž»óòIpjzÇ©ýÑüT“4ÓÀ+Bls%‰¼£ÚÓT©{ö'GK±%¶wuÂæ[¦ÛÚã÷e´¼QáE¸ÅU+'< œ(cáâôÔ¹wª*ÌgÀvyë7)ºÓeBb’|æ‚Cè@G?:< X'rû› á£[·K´ûæ…¡¢mž¦*9£Áà†½Ë®ˆö zCl´…-û‚€E>ÂøPƒý±Ñ1° Ôx¿¡vf‚ ýu»@ž©~·ôÿÁ÷ýç¬P®H[œ% ¬ÍÞ!Ó"tRm¼Û×õ^ЬX²”Ñ,'óiܨoz8ƒAF»œõHfàG L`i6"!:{ÉiL /5)™­ÛðÀQ²ãÖ´”4dS 3ˆf0È"æy&š4 Û„ÇLH@Š’3Ç”ð’lIrt‹hóRÓp£¥£}ƒ,l [¾–Ì9F™Ŏh¸ ƒ3ÙWvËcÓ']²mÜÑ'§™§êOÓÝqÇÆn™kµÉY ÎÒPݵæÝŠ­Šú©ÝÕŸáyu+~â(ØÇŘöålÉßÝIóì»{{å4C³pºP©’LŠÈ´OdîûÞì¶TªÌUrl´ôœÇÏ_@Ä`|éÀp°¿÷¦å¼VüvÔ†m‘?8.MÇ©}üSk‹óvéóöKÁqèx! OÖMº„ÂEü¯#%ïó×BØ+©‰É2PE ¥ŠR]zJ[arßl4Êœ Øèh„/û$Ü¥öÉ# 0vã 3ÓŠ=³{¸ømœfhóÑ(_m…ãø=¾ãÏ?C„aw­™¸’Ñ+a@„ ؉§¦ç…®gìï¿ÙJOõ¦Ü:˜²¬SýÀ:l :†h’B6È,‚¾3Ì]Ž~tCú¨ Ûý:‹Œ•— >L¯¾3AZvè‡ÎË'«„pÔÝÜ0iñÊ×öÃøŒ¾#ÿ×fÈYc|ù-ä<ˆ‡ÿº:F-¼ÎÙwÒ;æÇEÐ=27ϰ*âa7±`hˆŽ&këìÈX¸X*y‰þ4[n¦k”f“âEIÿõM¹Âžr÷Í üGßù#ÂìÎKãÊY½ŠìÀ}ä—C@¢ÙËѲónAÝüË'¹Å˜¤¨ï"µŒÝ¼ÄqÙyowº<ÊõEâ$ãK¡»µî ñÈ{> ^®`¹ðÒ» ¢­ìÍøÑIz3">…î!;-ÝÎã< j)ñ€±­EfÀØÛßïŽÉ,ó⬂¾j˜Ìqú > åÛÓ9Xäc‰eLSþ^)¥"ðAžîFWŧλ¥Èa„f^{OTß`ƒÈç¶ŠŠ§Èoˆ; ˆ5@/IüŽ|ÄYª¿~Vô²•×H³—Þ*Øä¬¨u?EƒÃÿš¥ý$«MS[ Dò°ù¡hH$§áýiLA2 –»Ä¸Oœ³&ËÞ‰çÛšhÜòªÔ Lļåèe´Öù r¼plº#å¹à¢ã ±&o[Y*õl€S*ô«_Ôp²ÝõÕ¿ !™Íšè ñzzDA†$0Ñ2›.y2R•Bú5¯7‘ˆå¤! K׳MŠ:W¸l£ÔyÑÛºê¾ ÙíJŒ‹‡¿­b‹˜@o¨–¬ñ Óeryä¢S J}ˆÜ©»MJÊŽ¨¯ Zæ ä¹Ô!]F®æÊEôË¢DÈ(”Ð/Z úÐÇn ¶Û[Ìüó@o‚8tÖºKLŽà ¨ú?8ºæ 6ˆ¸oK€Zs¬ÏÑ÷‰-cX­1š†/¡ÉÍ‚—ü¢‚§ #ÒD S)˜žî2& €…N  Z®òë¨&ù÷²ÓÎâ#ð ð¯2Kí(þD o"R}uYߢr0d÷,…“\‚*1 6̔Γ'ùy¡bŸÌóÒÌí&#Y^ñ*Iýe»¥aªn” ñÈ¿ñù…H¦‚`9?/'ëQT ŸªþYŒOÑL3ÃÔWo¿†‘®v“TYÒË%³¥üÌÅ”@™ïwHÿ½BÇ©ƒS÷eâz"¥©käo¿á«à?Ì6±eûì3ºVmï²Ó‰ 0'³B:ž 4¤zG.t\>8ÊÏèËcMÍT⢕cÝ$ù.…°¡¢m˜-3ä¬1<ÿ‚@ŒK%Gf¥Þ÷¦þí2ºn0ÑO àˆÙ¾ÁA™]p-A‘à›f•±¾¢xpˆþGÃaæ‚CDÃɨ‹—ot•‚Q/Ù—¾/(‘à š,#`jóÉ2Z¥ˆeg2-6:Ú/O–!Ž}8A–¹Æ§ ï '²¡œ¾Ã(šN .°)(옧«…*‡PÞ®¹É)¨Ä±†« zƒœÊ0¾¶è9†=ô½Â©( §dþwÜêŒ.˸[î ¹k®y]êêEûҌ豨Š%bnia²†üƒÚÞ©Ê‘à¦þ5¾Â¤4k\œ¢Ah:­®9p)2­¶MVòVœ*ÕVŒžÙMʹ«äØHÉéÇuã0#åéN*]§’b‹ÑÒs’Øõ‘“§æªdxu¯Ô ”ɉ.ôžŽHtÀŽ ‚2ôÜn«½Ëd†ÉÊLòeÙ|NƒÇd¿†§häØÎ— è-v•ÉØ±ò¬˜†,ÃÊ%[ˆ%<ÅGé À%Æ­c_üË$æjI²‹6"Ÿû¾ð)Ì\ë}´®Ÿ-r^öÖíV©Ôˆã#ƒªo¦þAŒWÕÕ¨à´ìÅYˆž»÷«ã-±¢‘)@ðÖ=ï¤,ù†H‰H:p¸IV›½»kŽÙ .ûNUeb‚‚Ðé÷"‰/í)ÐXÔåÑIå#LôW6øùìV!“µ#q1²I¿ºÀ H®£eçýÉ . Hý£òÕq­)†ó¶·Uß.AòâMECÕ¥‹³PÞ•Ý*oõg°§´ü:Æ•@c¢É $Ž(üÅ\šA¯Ÿ“d¾·•<Í•:Þ´‘¥q³ ¢KÀ“»µÖðü Zs,hAZеaÛ(·ø(žÛûn!A‰cxøÃÃÆî&ZjA ¹b—è¢PÔÖÝ.®Èq|‡©àèÄÚ@Õ'ŽSû1à5nû­*mðŒ³òš°^RáÚÿíð›ÊE­ì̧ûðñ«·Ë¬&½^ïr¹ œ¤¿u;Æ…ÐÀd6™Dk'Ø Ãt™o ÝÍÕ:zÈßï8ûº†[z¯ ¢ÊÍ‹Üþ&d0ms~qfèÄN,˜Ž(=Ÿ:>2@sr0‚T‘\’¹àœÐÀÀü€ù˜<Ë‚uPÁqöFIEND®B`‚rabbitmq-server-3.2.4/plugins-src/rabbitmq-management/priv/www/img/bg-yellow-dark.png0000644000000000000000000000027612305126066027420 0ustar rootroot‰PNG  IHDRxô̯{†sRGB®ÎéPLTEââjÌ3 < pHYs  šœtIMEÜ  -;oÝIÿtEXtCommentCreated with GIMPWIDATXÃíÁ€þ¯î @âø·IEND®B`‚rabbitmq-server-3.2.4/plugins-src/rabbitmq-management/src/0000755000000000000000000000000012305126066022274 5ustar rootrootrabbitmq-server-3.2.4/plugins-src/rabbitmq-management/src/rabbit_mgmt_wm_channel.erl0000644000000000000000000000345112305126066027465 0ustar rootroot%% The contents of this file are subject to the Mozilla Public License %% Version 1.1 (the "License"); you may not use this file except in %% compliance with the License. You may obtain a copy of the License at %% http://www.mozilla.org/MPL/ %% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the %% License for the specific language governing rights and limitations %% under the License. %% %% The Original Code is RabbitMQ Management Plugin. %% %% The Initial Developer of the Original Code is GoPivotal, Inc. %% Copyright (c) 2010-2013 GoPivotal, Inc. All rights reserved. %% -module(rabbit_mgmt_wm_channel). -export([init/1, to_json/2, content_types_provided/2, is_authorized/2]). -export([resource_exists/2]). -include("rabbit_mgmt.hrl"). -include_lib("webmachine/include/webmachine.hrl"). -include_lib("rabbit_common/include/rabbit.hrl"). %%-------------------------------------------------------------------- init(_Config) -> {ok, #context{}}. content_types_provided(ReqData, Context) -> {[{"application/json", to_json}], ReqData, Context}. resource_exists(ReqData, Context) -> case channel(ReqData) of not_found -> {false, ReqData, Context}; _Conn -> {true, ReqData, Context} end. to_json(ReqData, Context) -> rabbit_mgmt_util:reply( {struct, rabbit_mgmt_format:strip_pids(channel(ReqData))}, ReqData, Context). is_authorized(ReqData, Context) -> rabbit_mgmt_util:is_authorized_user(ReqData, Context, channel(ReqData)). %%-------------------------------------------------------------------- channel(ReqData) -> rabbit_mgmt_db:get_channel(rabbit_mgmt_util:id(channel, ReqData), rabbit_mgmt_util:range(ReqData)). rabbitmq-server-3.2.4/plugins-src/rabbitmq-management/src/rabbit_mgmt_wm_whoami.erl0000644000000000000000000000252312305126066027340 0ustar rootroot%% The contents of this file are subject to the Mozilla Public License %% Version 1.1 (the "License"); you may not use this file except in %% compliance with the License. You may obtain a copy of the License at %% http://www.mozilla.org/MPL/ %% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the %% License for the specific language governing rights and limitations %% under the License. %% %% The Original Code is RabbitMQ Management Plugin. %% %% The Initial Developer of the Original Code is GoPivotal, Inc. %% Copyright (c) 2010-2013 GoPivotal, Inc. All rights reserved. %% -module(rabbit_mgmt_wm_whoami). -export([init/1, to_json/2, content_types_provided/2, is_authorized/2]). -include("rabbit_mgmt.hrl"). -include_lib("webmachine/include/webmachine.hrl"). -include_lib("rabbit_common/include/rabbit.hrl"). %%-------------------------------------------------------------------- init(_Config) -> {ok, #context{}}. content_types_provided(ReqData, Context) -> {[{"application/json", to_json}], ReqData, Context}. to_json(ReqData, Context = #context{user = User}) -> rabbit_mgmt_util:reply(rabbit_mgmt_format:user(User), ReqData, Context). is_authorized(ReqData, Context) -> rabbit_mgmt_util:is_authorized(ReqData, Context). rabbitmq-server-3.2.4/plugins-src/rabbitmq-management/src/rabbit_mgmt_db.erl0000644000000000000000000012753012305126066025744 0ustar rootroot%% The contents of this file are subject to the Mozilla Public License %% Version 1.1 (the "License"); you may not use this file except in %% compliance with the License. You may obtain a copy of the License at %% http://www.mozilla.org/MPL/ %% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the %% License for the specific language governing rights and limitations %% under the License. %% %% The Original Code is RabbitMQ Management Plugin. %% %% The Initial Developer of the Original Code is GoPivotal, Inc. %% Copyright (c) 2010-2013 GoPivotal, Inc. All rights reserved. %% -module(rabbit_mgmt_db). -include("rabbit_mgmt.hrl"). -include_lib("rabbit_common/include/rabbit.hrl"). -behaviour(gen_server2). -export([start_link/0]). -export([augment_exchanges/3, augment_queues/3, augment_nodes/1, augment_vhosts/2, get_channel/2, get_connection/2, get_all_channels/1, get_all_connections/1, get_overview/2, get_overview/1]). -export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3, handle_pre_hibernate/1, prioritise_cast/3, format_message_queue/2]). %% For testing -export([override_lookups/1, reset_lookups/0]). -import(rabbit_misc, [pget/3, pset/3]). %% The management database listens to events broadcast via the %% rabbit_event mechanism, and responds to queries from the various %% rabbit_mgmt_wm_* modules. It handles several kinds of events, and %% slices and dices them in various ways. %% %% There are three types of events coming in: created (when an object %% is created, containing immutable facts about it), stats (emitted on %% a timer, with mutable facts about the object), and deleted (just %% containing the object's ID). In this context "objects" means %% connections, channels, exchanges, queues, consumers, vhosts and %% nodes. Note that we do not care about users, permissions, bindings, %% parameters or policies. %% %% Connections and channels are identified by pids. Queues and %% exchanges are identified by names (which are #resource{}s). VHosts %% and nodes are identified by names which are binaries. And consumers %% are identified by {ChPid, QName, CTag}. %% %% The management database records the "created" events for %% connections, channels and consumers, and can thus be authoritative %% about those objects. For queues, exchanges and nodes we go to %% Mnesia to find out the immutable details of the objects. %% %% For everything other than consumers, the database can then augment %% these immutable details with stats, as the object changes. (We %% never emit anything very interesting about consumers). %% %% Stats on the inbound side are refered to as coarse- and %% fine-grained. Fine grained statistics are the message rates %% maintained by channels and associated with tuples: {publishing %% channel, exchange}, {publishing channel, exchange, queue} and %% {queue, consuming channel}. Coarse grained stats are everything %% else and are associated with only one object, not a tuple. %% %% Within the management database though we rearrange things a bit: we %% refer to basic stats, simple stats and detail stats. %% %% Basic stats are those coarse grained stats for which we do not %% retain a history and do not perform any calculations - %% e.g. connection.state or channel.prefetch_count. %% %% Simple stats are those for which we do history / calculations which %% are associated with one object *after aggregation* - so these might %% originate with coarse grained stats - e.g. connection.send_oct or %% queue.messages_ready. But they might also originate from fine %% grained stats which have been aggregated - e.g. the message rates %% for a vhost or queue. %% %% Finally, detailed stats are those for which we do history / %% calculations which are associated with two objects. These %% have to have originated as fine grained stats, but can still have %% been aggregated. %% %% Created events and basic stats are stored in ETS tables by object, %% looked up in an orddict in #state.tables. Simple and detailed stats %% (which only differ depending on how they're keyed) are stored in %% #state.aggregated_stats. %% %% For detailed stats we also store an index for each object referencing %% all the other objects that form a detailed stats key with it. This is %% so that we can always avoid table scanning while deleting stats and %% thus make sure that handling deleted events is O(n)-ish. %% %% For each key for simple and detailed stats we maintain a #stats{} %% record, essentially a base counter for everything that happened %% before the samples we have kept, and a gb_tree of {timestamp, %% sample} values. %% %% We also have #state.old_stats to let us calculate instantaneous %% rates, in order to apportion simple / detailed stats into time %% slices as they come in. These instantaneous rates are not returned %% in response to any query, the rates shown in the API are calculated %% at query time. old_stats contains both coarse and fine %% entries. Coarse entries are pruned when the corresponding object is %% deleted, and fine entries are pruned when the emitting channel is %% closed, and whenever we receive new fine stats from a channel. So %% it's quite close to being a cache of "the previous stats we %% received". %% %% We also keep a timer going, in order to prune old samples from %% #state.aggregated_stats. %% %% Overall the object is to do all the aggregation when events come %% in, and make queries be simple lookups as much as possible. One %% area where this does not happen is the global overview - which is %% aggregated from vhost stats at query time since we do not want to %% reveal anything about other vhosts to unprivileged users. -record(state, { %% "stats" for which no calculations are required tables, %% database of aggregated samples aggregated_stats, %% index for detailed aggregated_stats that have 2-tuple keys aggregated_stats_index, %% What the previous info item was for any given %% {queue/channel/connection} old_stats, gc_timer, gc_continuation, lookups, interval}). -define(FINE_STATS_TYPES, [channel_queue_stats, channel_exchange_stats, channel_queue_exchange_stats]). -define(TABLES, [queue_stats, connection_stats, channel_stats, consumers_by_queue, consumers_by_channel, node_stats]). -define(DELIVER_GET, [deliver, deliver_no_ack, get, get_no_ack]). -define(FINE_STATS, [publish, publish_in, publish_out, ack, deliver_get, confirm, return_unroutable, redeliver] ++ ?DELIVER_GET). -define(COARSE_QUEUE_STATS, [messages, messages_ready, messages_unacknowledged]). -define(COARSE_CONN_STATS, [recv_oct, send_oct]). -define(GC_INTERVAL, 5000). -define(GC_MIN_ROWS, 100). -define(GC_MIN_RATIO, 0.01). -define(DROP_LENGTH, 1000). prioritise_cast({event, #event{type = Type, props = Props}}, Len, _State) when (Type =:= channel_stats orelse Type =:= queue_stats) andalso Len > ?DROP_LENGTH -> case pget(idle_since, Props) of unknown -> drop; _ -> 0 end; prioritise_cast(_Msg, _Len, _State) -> 0. %%---------------------------------------------------------------------------- %% API %%---------------------------------------------------------------------------- start_link() -> case gen_server2:start_link({global, ?MODULE}, ?MODULE, [], []) of {ok, Pid} -> register(?MODULE, Pid), %% [1] rabbit:force_event_refresh(), {ok, Pid}; Else -> Else end. %% [1] For debugging it's helpful to locally register the name too %% since that shows up in places global names don't. %% R = Ranges, M = Mode augment_exchanges(Xs, R, M) -> safe_call({augment_exchanges, Xs, R, M}, Xs). augment_queues(Qs, R, M) -> safe_call({augment_queues, Qs, R, M}, Qs). augment_vhosts(VHosts, R) -> safe_call({augment_vhosts, VHosts, R}, VHosts). augment_nodes(Nodes) -> safe_call({augment_nodes, Nodes}, Nodes). get_channel(Name, R) -> safe_call({get_channel, Name, R}, not_found). get_connection(Name, R) -> safe_call({get_connection, Name, R}, not_found). get_all_channels(R) -> safe_call({get_all_channels, R}). get_all_connections(R) -> safe_call({get_all_connections, R}). get_overview(User, R) -> safe_call({get_overview, User, R}). get_overview(R) -> safe_call({get_overview, all, R}). override_lookups(Lookups) -> safe_call({override_lookups, Lookups}). reset_lookups() -> safe_call(reset_lookups). safe_call(Term) -> safe_call(Term, []). safe_call(Term, Default) -> safe_call(Term, Default, 1). %% See rabbit_mgmt_sup_sup for a discussion of the retry logic. safe_call(Term, Default, Retries) -> try gen_server2:call({global, ?MODULE}, Term, infinity) catch exit:{noproc, _} -> case Retries of 0 -> Default; _ -> rabbit_mgmt_sup_sup:start_child(), safe_call(Term, Default, Retries - 1) end end. %%---------------------------------------------------------------------------- %% Internal, gen_server2 callbacks %%---------------------------------------------------------------------------- init([]) -> %% When Rabbit is overloaded, it's usually especially important %% that the management plugin work. process_flag(priority, high), {ok, Interval} = application:get_env(rabbit, collect_statistics_interval), rabbit_node_monitor:subscribe(self()), rabbit_log:info("Statistics database started.~n"), Table = fun () -> ets:new(rabbit_mgmt_db, [ordered_set]) end, Tables = orddict:from_list([{Key, Table()} || Key <- ?TABLES]), {ok, set_gc_timer( reset_lookups( #state{interval = Interval, tables = Tables, old_stats = Table(), aggregated_stats = Table(), aggregated_stats_index = Table()})), hibernate, {backoff, ?HIBERNATE_AFTER_MIN, ?HIBERNATE_AFTER_MIN, ?DESIRED_HIBERNATE}}. handle_call({augment_exchanges, Xs, Ranges, basic}, _From, State) -> reply(list_exchange_stats(Ranges, Xs, State), State); handle_call({augment_exchanges, Xs, Ranges, full}, _From, State) -> reply(detail_exchange_stats(Ranges, Xs, State), State); handle_call({augment_queues, Qs, Ranges, basic}, _From, State) -> reply(list_queue_stats(Ranges, Qs, State), State); handle_call({augment_queues, Qs, Ranges, full}, _From, State) -> reply(detail_queue_stats(Ranges, Qs, State), State); handle_call({augment_vhosts, VHosts, Ranges}, _From, State) -> reply(vhost_stats(Ranges, VHosts, State), State); handle_call({augment_nodes, Nodes}, _From, State) -> {reply, node_stats(Nodes, State), State}; handle_call({get_channel, Name, Ranges}, _From, State = #state{tables = Tables}) -> case created_event(Name, channel_stats, Tables) of not_found -> reply(not_found, State); Ch -> [Result] = detail_channel_stats(Ranges, [Ch], State), reply(Result, State) end; handle_call({get_connection, Name, Ranges}, _From, State = #state{tables = Tables}) -> case created_event(Name, connection_stats, Tables) of not_found -> reply(not_found, State); Conn -> [Result] = connection_stats(Ranges, [Conn], State), reply(Result, State) end; handle_call({get_all_channels, Ranges}, _From, State = #state{tables = Tables}) -> Chans = created_events(channel_stats, Tables), reply(list_channel_stats(Ranges, Chans, State), State); handle_call({get_all_connections, Ranges}, _From, State = #state{tables = Tables}) -> Conns = created_events(connection_stats, Tables), reply(connection_stats(Ranges, Conns, State), State); handle_call({get_overview, User, Ranges}, _From, State = #state{tables = Tables}) -> VHosts = case User of all -> rabbit_vhost:list(); _ -> rabbit_mgmt_util:list_visible_vhosts(User) end, %% TODO: there's no reason we can't do an overview of send_oct and %% recv_oct now! VStats = [read_simple_stats(vhost_stats, VHost, State) || VHost <- VHosts], MessageStats = [overview_sum(Type, VStats) || Type <- ?FINE_STATS], QueueStats = [overview_sum(Type, VStats) || Type <- ?COARSE_QUEUE_STATS], F = case User of all -> fun (L) -> length(L) end; _ -> fun (L) -> length(rabbit_mgmt_util:filter_user(L, User)) end end, %% Filtering out the user's consumers would be rather expensive so let's %% just not show it Consumers = case User of all -> Table = orddict:fetch(consumers_by_queue, Tables), [{consumers, ets:info(Table, size)}]; _ -> [] end, ObjectTotals = Consumers ++ [{queues, length([Q || V <- VHosts, Q <- rabbit_amqqueue:list(V)])}, {exchanges, length([X || V <- VHosts, X <- rabbit_exchange:list(V)])}, {connections, F(created_events(connection_stats, Tables))}, {channels, F(created_events(channel_stats, Tables))}], reply([{message_stats, format_samples(Ranges, MessageStats, State)}, {queue_totals, format_samples(Ranges, QueueStats, State)}, {object_totals, ObjectTotals}], State); handle_call({override_lookups, Lookups}, _From, State) -> reply(ok, State#state{lookups = Lookups}); handle_call(reset_lookups, _From, State) -> reply(ok, reset_lookups(State)); handle_call(_Request, _From, State) -> reply(not_understood, State). handle_cast({event, Event}, State) -> handle_event(Event, State), noreply(State); handle_cast(_Request, State) -> noreply(State). handle_info(gc, State) -> noreply(set_gc_timer(gc_batch(State))); handle_info({node_down, Node}, State = #state{tables = Tables}) -> Conns = created_events(connection_stats, Tables), Chs = created_events(channel_stats, Tables), delete_all_from_node(connection_closed, Node, Conns, State), delete_all_from_node(channel_closed, Node, Chs, State), noreply(State); handle_info(_Info, State) -> noreply(State). terminate(_Arg, _State) -> ok. code_change(_OldVsn, State, _Extra) -> {ok, State}. reply(Reply, NewState) -> {reply, Reply, NewState, hibernate}. noreply(NewState) -> {noreply, NewState, hibernate}. set_gc_timer(State) -> TRef = erlang:send_after(?GC_INTERVAL, self(), gc), State#state{gc_timer = TRef}. reset_lookups(State) -> State#state{lookups = [{exchange, fun rabbit_exchange:lookup/1}, {queue, fun rabbit_amqqueue:lookup/1}]}. handle_pre_hibernate(State) -> %% rabbit_event can end up holding on to some memory after a busy %% workout, but it's not a gen_server so we can't make it %% hibernate. The best we can do is forcibly GC it here (if %% rabbit_mgmt_db is hibernating the odds are rabbit_event is %% quiescing in some way too). rpc:multicall( rabbit_mnesia:cluster_nodes(running), rabbit_mgmt_db_handler, gc, []), {hibernate, State}. format_message_queue(Opt, MQ) -> rabbit_misc:format_message_queue(Opt, MQ). delete_all_from_node(Type, Node, Items, State) -> [case node(Pid) of Node -> handle_event(#event{type = Type, props = [{pid, Pid}]}, State); _ -> ok end || Item <- Items, Pid <- [pget(pid, Item)]]. %%---------------------------------------------------------------------------- %% Internal, utilities %%---------------------------------------------------------------------------- pget(Key, List) -> pget(Key, List, unknown). %% id_name() and id() are for use when handling events, id_lookup() %% for when augmenting. The difference is that when handling events a %% queue name will be a resource, but when augmenting we will be %% passed a queue proplist that will already have been formatted - %% i.e. it will have name and vhost keys. id_name(node_stats) -> name; id_name(vhost_stats) -> name; id_name(queue_stats) -> name; id_name(exchange_stats) -> name; id_name(channel_stats) -> pid; id_name(connection_stats) -> pid. id(Type, List) -> pget(id_name(Type), List). id_lookup(queue_stats, List) -> rabbit_misc:r(pget(vhost, List), queue, pget(name, List)); id_lookup(exchange_stats, List) -> rabbit_misc:r(pget(vhost, List), exchange, pget(name, List)); id_lookup(Type, List) -> id(Type, List). lookup_element(Table, Key) -> lookup_element(Table, Key, 2). lookup_element(Table, Key, Pos) -> try ets:lookup_element(Table, Key, Pos) catch error:badarg -> [] end. fine_stats_id(ChPid, {Q, X}) -> {ChPid, Q, X}; fine_stats_id(ChPid, QorX) -> {ChPid, QorX}. floor(TS, #state{interval = Interval}) -> rabbit_mgmt_util:floor(rabbit_mgmt_format:timestamp_ms(TS), Interval). ceil(TS, #state{interval = Interval}) -> rabbit_mgmt_util:ceil (rabbit_mgmt_format:timestamp_ms(TS), Interval). details_key(Key) -> list_to_atom(atom_to_list(Key) ++ "_details"). %%---------------------------------------------------------------------------- %% Internal, event-receiving side %%---------------------------------------------------------------------------- handle_event(#event{type = queue_stats, props = Stats, timestamp = Timestamp}, State) -> handle_stats(queue_stats, Stats, Timestamp, [{fun rabbit_mgmt_format:properties/1,[backing_queue_status]}, {fun rabbit_mgmt_format:timestamp/1, [idle_since]}, {fun rabbit_mgmt_format:queue_status/1, [status]}], [messages, messages_ready, messages_unacknowledged], State); handle_event(Event = #event{type = queue_deleted, props = [{name, Name}], timestamp = Timestamp}, State = #state{old_stats = OldTable}) -> delete_consumers(Name, consumers_by_queue, consumers_by_channel, State), %% This is fiddly. Unlike for connections and channels, we need to %% decrease any amalgamated coarse stats for [messages, %% messages_ready, messages_unacknowledged] for this queue - since %% the queue's deletion means we have really got rid of messages! Id = {coarse, {queue_stats, Name}}, %% This ceil must correspond to the ceil in append_samples/5 TS = ceil(Timestamp, State), OldStats = lookup_element(OldTable, Id), [record_sample(Id, {Key, -pget(Key, OldStats, 0), TS, State}, State) || Key <- ?COARSE_QUEUE_STATS], delete_samples(channel_queue_stats, {'_', Name}, State), delete_samples(queue_exchange_stats, {Name, '_'}, State), delete_samples(queue_stats, Name, State), handle_deleted(queue_stats, Event, State); handle_event(Event = #event{type = exchange_deleted, props = [{name, Name}]}, State) -> delete_samples(channel_exchange_stats, {'_', Name}, State), delete_samples(queue_exchange_stats, {'_', Name}, State), delete_samples(exchange_stats, Name, State), handle_deleted(exchange_stats, Event, State); handle_event(#event{type = vhost_deleted, props = [{name, Name}]}, State) -> delete_samples(vhost_stats, Name, State), {ok, State}; handle_event(#event{type = connection_created, props = Stats}, State) -> handle_created( connection_stats, Stats, [{fun rabbit_mgmt_format:addr/1, [host, peer_host]}, {fun rabbit_mgmt_format:port/1, [port, peer_port]}, {fun rabbit_mgmt_format:protocol/1, [protocol]}, {fun rabbit_mgmt_format:amqp_table/1, [client_properties]}], State); handle_event(#event{type = connection_stats, props = Stats, timestamp = Timestamp}, State) -> handle_stats(connection_stats, Stats, Timestamp, [], ?COARSE_CONN_STATS, State); handle_event(Event = #event{type = connection_closed, props = [{pid, Pid}]}, State) -> delete_samples(connection_stats, Pid, State), handle_deleted(connection_stats, Event, State); handle_event(#event{type = channel_created, props = Stats}, State) -> handle_created(channel_stats, Stats, [], State); handle_event(#event{type = channel_stats, props = Stats, timestamp = Timestamp}, State = #state{old_stats = OldTable}) -> handle_stats(channel_stats, Stats, Timestamp, [{fun rabbit_mgmt_format:timestamp/1, [idle_since]}], [], State), ChPid = id(channel_stats, Stats), AllStats = [old_fine_stats(Type, Stats, State) || Type <- ?FINE_STATS_TYPES], ets:match_delete(OldTable, {{fine, {ChPid, '_'}}, '_'}), ets:match_delete(OldTable, {{fine, {ChPid, '_', '_'}}, '_'}), [handle_fine_stats(Timestamp, AllStatsElem, State) || AllStatsElem <- AllStats], {ok, State}; handle_event(Event = #event{type = channel_closed, props = [{pid, Pid}]}, State = #state{old_stats = Old}) -> delete_consumers(Pid, consumers_by_channel, consumers_by_queue, State), delete_samples(channel_queue_stats, {Pid, '_'}, State), delete_samples(channel_exchange_stats, {Pid, '_'}, State), delete_samples(channel_stats, Pid, State), handle_deleted(channel_stats, Event, State), ets:match_delete(Old, {{fine, {Pid, '_'}}, '_'}), ets:match_delete(Old, {{fine, {Pid, '_', '_'}}, '_'}); handle_event(#event{type = consumer_created, props = Props}, State) -> Fmt = [{fun rabbit_mgmt_format:amqp_table/1, [arguments]}], handle_consumer(fun(Table, Id, P0) -> P = rabbit_mgmt_format:format(P0, Fmt), ets:insert(Table, {Id, P}) end, Props, State); handle_event(#event{type = consumer_deleted, props = Props}, State) -> handle_consumer(fun(Table, Id, _P) -> ets:delete(Table, Id) end, Props, State); %% TODO: we don't clear up after dead nodes here - this is a very tiny %% leak every time a node is permanently removed from the cluster. Do %% we care? handle_event(#event{type = node_stats, props = Stats, timestamp = Timestamp}, State = #state{tables = Tables}) -> Table = orddict:fetch(node_stats, Tables), ets:insert(Table, {{pget(name, Stats), stats}, proplists:delete(name, Stats), Timestamp}), {ok, State}; handle_event(_Event, State) -> {ok, State}. handle_created(TName, Stats, Funs, State = #state{tables = Tables}) -> Formatted = rabbit_mgmt_format:format(Stats, Funs), ets:insert(orddict:fetch(TName, Tables), {{id(TName, Stats), create}, Formatted, pget(name, Stats)}), {ok, State}. handle_stats(TName, Stats, Timestamp, Funs, RatesKeys, State = #state{tables = Tables, old_stats = OldTable}) -> Id = id(TName, Stats), IdSamples = {coarse, {TName, Id}}, OldStats = lookup_element(OldTable, IdSamples), append_samples(Stats, Timestamp, OldStats, IdSamples, RatesKeys, State), StripKeys = [id_name(TName)] ++ RatesKeys ++ ?FINE_STATS_TYPES, Stats1 = [{K, V} || {K, V} <- Stats, not lists:member(K, StripKeys)], Stats2 = rabbit_mgmt_format:format(Stats1, Funs), ets:insert(orddict:fetch(TName, Tables), {{Id, stats}, Stats2, Timestamp}), {ok, State}. handle_deleted(TName, #event{props = Props}, State = #state{tables = Tables, old_stats = Old}) -> Id = id(TName, Props), case orddict:find(TName, Tables) of {ok, Table} -> ets:delete(Table, {Id, create}), ets:delete(Table, {Id, stats}); error -> ok end, ets:delete(Old, {coarse, {TName, Id}}), {ok, State}. handle_consumer(Fun, Props, State = #state{tables = Tables}) -> P = rabbit_mgmt_format:format(Props, []), CTag = pget(consumer_tag, P), Q = pget(queue, P), Ch = pget(channel, P), QTable = orddict:fetch(consumers_by_queue, Tables), ChTable = orddict:fetch(consumers_by_channel, Tables), Fun(QTable, {Q, Ch, CTag}, P), Fun(ChTable, {Ch, Q, CTag}, P), {ok, State}. %% The consumer_deleted event is emitted by queues themselves - %% therefore in the event that a queue dies suddenly we may not get %% it. The best way to handle this is to make sure we also clean up %% consumers when we hear about any queue going down. delete_consumers(PrimId, PrimTableName, SecTableName, #state{tables = Tables}) -> Table1 = orddict:fetch(PrimTableName, Tables), Table2 = orddict:fetch(SecTableName, Tables), SecIdCTags = ets:match(Table1, {{PrimId, '$1', '$2'}, '_'}), ets:match_delete(Table1, {{PrimId, '_', '_'}, '_'}), [ets:delete(Table2, {SecId, PrimId, CTag}) || [SecId, CTag] <- SecIdCTags]. old_fine_stats(Type, Props, #state{old_stats = Old}) -> case pget(Type, Props) of unknown -> ignore; AllFineStats0 -> ChPid = id(channel_stats, Props), [begin Id = fine_stats_id(ChPid, Ids), {Id, Stats, lookup_element(Old, {fine, Id})} end || {Ids, Stats} <- AllFineStats0] end. handle_fine_stats(_Timestamp, ignore, _State) -> ok; handle_fine_stats(Timestamp, AllStats, State) -> [handle_fine_stat(Id, Stats, Timestamp, OldStats, State) || {Id, Stats, OldStats} <- AllStats]. handle_fine_stat(Id, Stats, Timestamp, OldStats, State) -> Total = lists:sum([V || {K, V} <- Stats, lists:member(K, ?DELIVER_GET)]), Stats1 = case Total of 0 -> Stats; _ -> [{deliver_get, Total}|Stats] end, append_samples(Stats1, Timestamp, OldStats, {fine, Id}, all, State). delete_samples(Type, {Id, '_'}, State) -> delete_samples_with_index(Type, Id, fun forward/2, State); delete_samples(Type, {'_', Id}, State) -> delete_samples_with_index(Type, Id, fun reverse/2, State); delete_samples(Type, Id, #state{aggregated_stats = ETS}) -> ets:match_delete(ETS, delete_match(Type, Id)). delete_samples_with_index(Type, Id, Order, #state{aggregated_stats = ETS, aggregated_stats_index = ETSi}) -> Ids2 = lists:append(ets:match(ETSi, {{Type, Id, '$1'}})), ets:match_delete(ETSi, {{Type, Id, '_'}}), [begin ets:match_delete(ETS, delete_match(Type, Order(Id, Id2))), ets:match_delete(ETSi, {{Type, Id2, Id}}) end || Id2 <- Ids2]. forward(A, B) -> {A, B}. reverse(A, B) -> {B, A}. delete_match(Type, Id) -> {{{Type, Id}, '_'}, '_'}. append_samples(Stats, TS, OldStats, Id, Keys, State = #state{old_stats = OldTable}) -> case ignore_coarse_sample(Id, State) of false -> %% This ceil must correspond to the ceil in handle_event %% queue_deleted NewMS = ceil(TS, State), case Keys of all -> [append_sample(Key, Value, NewMS, OldStats, Id, State) || {Key, Value} <- Stats]; _ -> [append_sample( Key, pget(Key, Stats), NewMS, OldStats, Id, State) || Key <- Keys] end, ets:insert(OldTable, {Id, Stats}); true -> ok end. append_sample(Key, Value, NewMS, OldStats, Id, State) when is_number(Value) -> record_sample( Id, {Key, Value - pget(Key, OldStats, 0), NewMS, State}, State); append_sample(_Key, _Value, _NewMS, _OldStats, _Id, _State) -> ok. ignore_coarse_sample({coarse, {queue_stats, Q}}, State) -> not object_exists(Q, State); ignore_coarse_sample(_, _) -> false. record_sample({coarse, Id}, Args, State) -> record_sample0(Id, Args), record_sample0({vhost_stats, vhost(Id, State)}, Args); %% Deliveries / acks (Q -> Ch) record_sample({fine, {Ch, Q = #resource{kind = queue}}}, Args, State) -> case object_exists(Q, State) of true -> record_sample0({channel_queue_stats, {Ch, Q}}, Args), record_sample0({queue_stats, Q}, Args); false -> ok end, record_sample0({channel_stats, Ch}, Args), record_sample0({vhost_stats, vhost(Q)}, Args); %% Publishes / confirms (Ch -> X) record_sample({fine, {Ch, X = #resource{kind = exchange}}}, Args, State) -> case object_exists(X, State) of true -> record_sample0({channel_exchange_stats, {Ch, X}}, Args), record_sampleX(publish_in, X, Args); false -> ok end, record_sample0({channel_stats, Ch}, Args), record_sample0({vhost_stats, vhost(X)}, Args); %% Publishes (but not confirms) (Ch -> X -> Q) record_sample({fine, {_Ch, Q = #resource{kind = queue}, X = #resource{kind = exchange}}}, Args, State) -> %% TODO This one logically feels like it should be here. It would %% correspond to "publishing channel message rates to queue" - %% which would be nice to handle - except we don't. And just %% uncommenting this means it gets merged in with "consuming %% channel delivery from queue" - which is not very helpful. %% record_sample0({channel_queue_stats, {Ch, Q}}, Args), QExists = object_exists(Q, State), XExists = object_exists(X, State), case QExists of true -> record_sample0({queue_stats, Q}, Args); false -> ok end, case QExists andalso XExists of true -> record_sample0({queue_exchange_stats, {Q, X}}, Args); false -> ok end, case XExists of true -> record_sampleX(publish_out, X, Args); false -> ok end. %% We have to check the queue and exchange objects still exist since %% their deleted event could be overtaken by a channel stats event %% which contains fine stats referencing them. That's also why we %% don't need to check the channels exist - their deleted event can't %% be overtaken by their own last stats event. %% %% Also, sometimes the queue_deleted event is not emitted by the queue %% (in the nodedown case) - so it can overtake the final queue_stats %% event (which is not *guaranteed* to be lost). So we make a similar %% check for coarse queue stats. %% %% We can be sure that mnesia will be up to date by the time we receive %% the event (even though we dirty read) since the deletions are %% synchronous and we do not emit the deleted event until after the %% deletion has occurred. object_exists(Name = #resource{kind = Kind}, #state{lookups = Lookups}) -> case (pget(Kind, Lookups))(Name) of {ok, _} -> true; _ -> false end. vhost(#resource{virtual_host = VHost}) -> VHost. vhost({queue_stats, #resource{virtual_host = VHost}}, _State) -> VHost; vhost({TName, Pid}, #state{tables = Tables}) -> Table = orddict:fetch(TName, Tables), pget(vhost, lookup_element(Table, {Pid, create})). %% exchanges have two sets of "publish" stats, so rearrange things a touch record_sampleX(RenamePublishTo, X, {publish, Diff, TS, State}) -> record_sample0({exchange_stats, X}, {RenamePublishTo, Diff, TS, State}); record_sampleX(_RenamePublishTo, X, {Type, Diff, TS, State}) -> record_sample0({exchange_stats, X}, {Type, Diff, TS, State}). record_sample0(Id0, {Key, Diff, TS, #state{aggregated_stats = ETS, aggregated_stats_index = ETSi}}) -> Id = {Id0, Key}, Old = case lookup_element(ETS, Id) of [] -> case Id0 of {Type, {Id1, Id2}} -> ets:insert(ETSi, {{Type, Id2, Id1}}), ets:insert(ETSi, {{Type, Id1, Id2}}); _ -> ok end, rabbit_mgmt_stats:blank(); E -> E end, ets:insert(ETS, {Id, rabbit_mgmt_stats:record(TS, Diff, Old)}). %%---------------------------------------------------------------------------- %% Internal, querying side %%---------------------------------------------------------------------------- -define(QUEUE_DETAILS, {queue_stats, [{incoming, queue_exchange_stats, fun first/1}, {deliveries, channel_queue_stats, fun second/1}]}). -define(EXCHANGE_DETAILS, {exchange_stats, [{incoming, channel_exchange_stats, fun second/1}, {outgoing, queue_exchange_stats, fun second/1}]}). -define(CHANNEL_DETAILS, {channel_stats, [{publishes, channel_exchange_stats, fun first/1}, {deliveries, channel_queue_stats, fun first/1}]}). first(Id) -> {Id, '$1'}. second(Id) -> {'$1', Id}. list_queue_stats(Ranges, Objs, State) -> adjust_hibernated_memory_use( merge_stats(Objs, queue_funs(Ranges, State))). detail_queue_stats(Ranges, Objs, State) -> adjust_hibernated_memory_use( merge_stats(Objs, [consumer_details_fun( fun (Props) -> id_lookup(queue_stats, Props) end, consumers_by_queue, State), detail_stats_fun(Ranges, ?QUEUE_DETAILS, State) | queue_funs(Ranges, State)])). queue_funs(Ranges, State) -> [basic_stats_fun(queue_stats, State), simple_stats_fun(Ranges, queue_stats, State), augment_msg_stats_fun(State)]. list_exchange_stats(Ranges, Objs, State) -> merge_stats(Objs, [simple_stats_fun(Ranges, exchange_stats, State), augment_msg_stats_fun(State)]). detail_exchange_stats(Ranges, Objs, State) -> merge_stats(Objs, [simple_stats_fun(Ranges, exchange_stats, State), detail_stats_fun(Ranges, ?EXCHANGE_DETAILS, State), augment_msg_stats_fun(State)]). connection_stats(Ranges, Objs, State) -> merge_stats(Objs, [basic_stats_fun(connection_stats, State), simple_stats_fun(Ranges, connection_stats, State), augment_msg_stats_fun(State)]). list_channel_stats(Ranges, Objs, State) -> merge_stats(Objs, [basic_stats_fun(channel_stats, State), simple_stats_fun(Ranges, channel_stats, State), augment_msg_stats_fun(State)]). detail_channel_stats(Ranges, Objs, State) -> merge_stats(Objs, [basic_stats_fun(channel_stats, State), simple_stats_fun(Ranges, channel_stats, State), consumer_details_fun( fun (Props) -> pget(pid, Props) end, consumers_by_channel, State), detail_stats_fun(Ranges, ?CHANNEL_DETAILS, State), augment_msg_stats_fun(State)]). vhost_stats(Ranges, Objs, State) -> merge_stats(Objs, [simple_stats_fun(Ranges, vhost_stats, State)]). node_stats(Objs, State) -> merge_stats(Objs, [basic_stats_fun(node_stats, State)]). merge_stats(Objs, Funs) -> [lists:foldl(fun (Fun, Props) -> Fun(Props) ++ Props end, Obj, Funs) || Obj <- Objs]. %% i.e. the non-calculated stats basic_stats_fun(Type, #state{tables = Tables}) -> Table = orddict:fetch(Type, Tables), fun (Props) -> Id = id_lookup(Type, Props), lookup_element(Table, {Id, stats}) end. %% i.e. coarse stats, and fine stats aggregated up to a single number per thing simple_stats_fun(Ranges, Type, State) -> fun (Props) -> Id = id_lookup(Type, Props), extract_msg_stats( format_samples(Ranges, read_simple_stats(Type, Id, State), State)) end. %% i.e. fine stats that are broken out per sub-thing detail_stats_fun(Ranges, {IdType, FineSpecs}, State) -> fun (Props) -> Id = id_lookup(IdType, Props), [detail_stats(Ranges, Name, AggregatedStatsType, IdFun(Id), State) || {Name, AggregatedStatsType, IdFun} <- FineSpecs] end. read_simple_stats(Type, Id, #state{aggregated_stats = ETS}) -> FromETS = ets:match(ETS, {{{Type, Id}, '$1'}, '$2'}), [{K, V} || [K, V] <- FromETS]. read_detail_stats(Type, Id, #state{aggregated_stats = ETS}) -> %% Id must contain '$1' FromETS = ets:match(ETS, {{{Type, Id}, '$2'}, '$3'}), %% [[G, K, V]] -> [{G, [{K, V}]}] where G is Q/X/Ch, K is from %% ?FINE_STATS and V is a stats tree %% TODO does this need to be optimised? lists:foldl( fun ([G, K, V], L) -> case lists:keyfind(G, 1, L) of false -> [{G, [{K, V}]} | L]; {G, KVs} -> lists:keyreplace(G, 1, L, {G, [{K, V} | KVs]}) end end, [], FromETS). extract_msg_stats(Stats) -> FineStats = lists:append([[K, details_key(K)] || K <- ?FINE_STATS]), {MsgStats, Other} = lists:partition(fun({K, _}) -> lists:member(K, FineStats) end, Stats), case MsgStats of [] -> Other; _ -> [{message_stats, MsgStats} | Other] end. detail_stats(Ranges, Name, AggregatedStatsType, Id, State) -> {Name, [[{stats, format_samples(Ranges, KVs, State)} | format_detail_id(G, State)] || {G, KVs} <- read_detail_stats(AggregatedStatsType, Id, State)]}. format_detail_id(ChPid, State) when is_pid(ChPid) -> augment_msg_stats([{channel, ChPid}], State); format_detail_id(#resource{name = Name, virtual_host = Vhost, kind = Kind}, _State) -> [{Kind, [{name, Name}, {vhost, Vhost}]}]. format_samples(Ranges, ManyStats, #state{interval = Interval}) -> lists:append( [case rabbit_mgmt_stats:is_blank(Stats) andalso not lists:member(K, ?COARSE_QUEUE_STATS) of true -> []; false -> {Details, Counter} = rabbit_mgmt_stats:format( pick_range(K, Ranges), Stats, Interval), [{K, Counter}, {details_key(K), Details}] end || {K, Stats} <- ManyStats]). pick_range(K, {RangeL, RangeM, RangeD}) -> case {lists:member(K, ?COARSE_QUEUE_STATS), lists:member(K, ?FINE_STATS), lists:member(K, ?COARSE_CONN_STATS)} of {true, false, false} -> RangeL; {false, true, false} -> RangeM; {false, false, true} -> RangeD end. %% We do this when retrieving the queue record rather than when %% storing it since the memory use will drop *after* we find out about %% hibernation, so to do it when we receive a queue stats event would %% be fiddly and racy. This should be quite cheap though. adjust_hibernated_memory_use(Qs) -> Pids = [pget(pid, Q) || Q <- Qs, pget(idle_since, Q, not_idle) =/= not_idle], %% We use delegate here not for ordering reasons but because we %% want to get the right amount of parallelism and minimise %% cross-cluster communication. {Mem, _BadNodes} = delegate:invoke(Pids, {erlang, process_info, [memory]}), MemDict = dict:from_list([{P, M} || {P, M = {memory, _}} <- Mem]), [case dict:find(pget(pid, Q), MemDict) of error -> Q; {ok, Memory} -> [Memory|proplists:delete(memory, Q)] end || Q <- Qs]. created_event(Name, Type, Tables) -> Table = orddict:fetch(Type, Tables), case ets:match(Table, {{'$1', create}, '_', Name}) of [] -> not_found; [[Id]] -> lookup_element(Table, {Id, create}) end. created_events(Type, Tables) -> [Facts || {{_, create}, Facts, _Name} <- ets:tab2list(orddict:fetch(Type, Tables))]. consumer_details_fun(KeyFun, TableName, State = #state{tables = Tables}) -> Table = orddict:fetch(TableName, Tables), fun ([]) -> []; (Props) -> Pattern = {KeyFun(Props), '_', '_'}, [{consumer_details, [augment_msg_stats(augment_consumer(Obj), State) || Obj <- lists:append( ets:match(Table, {Pattern, '$1'}))]}] end. augment_consumer(Obj) -> [{queue, rabbit_mgmt_format:resource(pget(queue, Obj))} | proplists:delete(queue, Obj)]. %%---------------------------------------------------------------------------- %% Internal, query-time summing for overview %%---------------------------------------------------------------------------- overview_sum(Type, VHostStats) -> Stats = [pget(Type, VHost, rabbit_mgmt_stats:blank()) || VHost <- VHostStats], {Type, rabbit_mgmt_stats:sum(Stats)}. %%---------------------------------------------------------------------------- %% Internal, query-time augmentation %%---------------------------------------------------------------------------- augment_msg_stats(Props, State) -> rabbit_mgmt_format:strip_pids( (augment_msg_stats_fun(State))(Props) ++ Props). augment_msg_stats_fun(State) -> Funs = [{connection, fun augment_connection_pid/2}, {channel, fun augment_channel_pid/2}, {owner_pid, fun augment_connection_pid/2}], fun (Props) -> augment(Props, Funs, State) end. augment(Items, Funs, State) -> Augmented = [augment(K, Items, Fun, State) || {K, Fun} <- Funs], [{K, V} || {K, V} <- Augmented, V =/= unknown]. augment(K, Items, Fun, State) -> Key = details_key(K), case pget(K, Items) of none -> {Key, unknown}; unknown -> {Key, unknown}; Id -> {Key, Fun(Id, State)} end. augment_channel_pid(Pid, #state{tables = Tables}) -> Ch = lookup_element(orddict:fetch(channel_stats, Tables), {Pid, create}), Conn = lookup_element(orddict:fetch(connection_stats, Tables), {pget(connection, Ch), create}), [{name, pget(name, Ch)}, {number, pget(number, Ch)}, {connection_name, pget(name, Conn)}, {peer_port, pget(peer_port, Conn)}, {peer_host, pget(peer_host, Conn)}]. augment_connection_pid(Pid, #state{tables = Tables}) -> Conn = lookup_element(orddict:fetch(connection_stats, Tables), {Pid, create}), [{name, pget(name, Conn)}, {peer_port, pget(peer_port, Conn)}, {peer_host, pget(peer_host, Conn)}]. %%---------------------------------------------------------------------------- %% Internal, event-GCing %%---------------------------------------------------------------------------- gc_batch(State = #state{aggregated_stats = ETS, gc_continuation = Continuation}) -> Match = case Continuation of undefined -> Size = ets:info(ETS, size), Rows = lists:max([?GC_MIN_ROWS, round(?GC_MIN_RATIO * Size)]), ets:match(ETS, '$1', Rows); _ -> ets:match(Continuation) end, case Match of {Matches, Continuation1} -> {ok, Policies} = application:get_env( rabbitmq_management, sample_retention_policies), Now = floor(erlang:now(), State), [gc(Key, Stats, Policies, Now, ETS) || [{Key, Stats}] <- Matches], State#state{gc_continuation = Continuation1}; '$end_of_table' -> State#state{gc_continuation = undefined} end. gc({{Type, Id}, Key}, Stats, Policies, Now, ETS) -> Policy = pget(retention_policy(Type), Policies), case rabbit_mgmt_stats:gc({Policy, Now}, Stats) of Stats -> ok; Stats2 -> ets:insert(ETS, {{{Type, Id}, Key}, Stats2}) end. retention_policy(vhost_stats) -> global; retention_policy(queue_stats) -> basic; retention_policy(exchange_stats) -> basic; retention_policy(connection_stats) -> basic; retention_policy(channel_stats) -> basic; retention_policy(queue_exchange_stats) -> detailed; retention_policy(channel_exchange_stats) -> detailed; retention_policy(channel_queue_stats) -> detailed. rabbitmq-server-3.2.4/plugins-src/rabbitmq-management/src/rabbit_mgmt_extension.erl0000644000000000000000000000217312305126066027366 0ustar rootroot%% The contents of this file are subject to the Mozilla Public License %% Version 1.1 (the "License"); you may not use this file except in %% compliance with the License. You may obtain a copy of the License at %% http://www.mozilla.org/MPL/ %% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the %% License for the specific language governing rights and limitations %% under the License. %% %% The Original Code is RabbitMQ Management Plugin. %% %% The Initial Developer of the Original Code is GoPivotal, Inc. %% Copyright (c) 2011-2013 GoPivotal, Inc. All rights reserved. %% -module(rabbit_mgmt_extension). -export([behaviour_info/1]). behaviour_info(callbacks) -> [ %% Return a webmachine dispatcher table to integrate {dispatcher, 0}, %% Return a proplist of information for the web UI to integrate %% this extension. Currently the proplist should have one key, %% 'javascript', the name of a javascript file to load and run. {web_ui, 0} ]; behaviour_info(_Other) -> undefined. rabbitmq-server-3.2.4/plugins-src/rabbitmq-management/src/rabbit_mgmt_wm_vhost.erl0000644000000000000000000000530712305126066027222 0ustar rootroot%% The contents of this file are subject to the Mozilla Public License %% Version 1.1 (the "License"); you may not use this file except in %% compliance with the License. You may obtain a copy of the License at %% http://www.mozilla.org/MPL/ %% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the %% License for the specific language governing rights and limitations %% under the License. %% %% The Original Code is RabbitMQ Management Plugin. %% %% The Initial Developer of the Original Code is GoPivotal, Inc. %% Copyright (c) 2010-2013 GoPivotal, Inc. All rights reserved. %% -module(rabbit_mgmt_wm_vhost). -export([init/1, resource_exists/2, to_json/2, content_types_provided/2, content_types_accepted/2, is_authorized/2, allowed_methods/2, accept_content/2, delete_resource/2, put_vhost/2]). -import(rabbit_misc, [pget/2]). -include("rabbit_mgmt.hrl"). -include_lib("webmachine/include/webmachine.hrl"). -include_lib("rabbit_common/include/rabbit.hrl"). %%-------------------------------------------------------------------- init(_Config) -> {ok, #context{}}. content_types_provided(ReqData, Context) -> {[{"application/json", to_json}], ReqData, Context}. content_types_accepted(ReqData, Context) -> {[{"application/json", accept_content}], ReqData, Context}. allowed_methods(ReqData, Context) -> {['HEAD', 'GET', 'PUT', 'DELETE'], ReqData, Context}. resource_exists(ReqData, Context) -> {rabbit_vhost:exists(id(ReqData)), ReqData, Context}. to_json(ReqData, Context) -> rabbit_mgmt_util:reply( hd(rabbit_mgmt_db:augment_vhosts( [rabbit_vhost:info(id(ReqData))], rabbit_mgmt_util:range(ReqData))), ReqData, Context). accept_content(ReqData, Context) -> Name = id(ReqData), rabbit_mgmt_util:with_decode( [], ReqData, Context, fun(_, VHost) -> put_vhost(Name, rabbit_mgmt_util:parse_bool( pget(tracing, VHost))), {true, ReqData, Context} end). delete_resource(ReqData, Context) -> VHost = id(ReqData), rabbit_vhost:delete(VHost), {true, ReqData, Context}. is_authorized(ReqData, Context) -> rabbit_mgmt_util:is_authorized_admin(ReqData, Context). %%-------------------------------------------------------------------- id(ReqData) -> rabbit_mgmt_util:id(vhost, ReqData). put_vhost(Name, Trace) -> case rabbit_vhost:exists(Name) of true -> ok; false -> rabbit_vhost:add(Name) end, case Trace of true -> rabbit_trace:start(Name); false -> rabbit_trace:stop(Name); undefined -> ok end. rabbitmq-server-3.2.4/plugins-src/rabbitmq-management/src/rabbit_mgmt_wm_permission.erl0000644000000000000000000000673112305126066030251 0ustar rootroot%% The contents of this file are subject to the Mozilla Public License %% Version 1.1 (the "License"); you may not use this file except in %% compliance with the License. You may obtain a copy of the License at %% http://www.mozilla.org/MPL/ %% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the %% License for the specific language governing rights and limitations %% under the License. %% %% The Original Code is RabbitMQ Management Plugin. %% %% The Initial Developer of the Original Code is GoPivotal, Inc. %% Copyright (c) 2010-2013 GoPivotal, Inc. All rights reserved. %% -module(rabbit_mgmt_wm_permission). -export([init/1, resource_exists/2, to_json/2, content_types_provided/2, content_types_accepted/2, is_authorized/2, allowed_methods/2, accept_content/2, delete_resource/2]). -include("rabbit_mgmt.hrl"). -include_lib("webmachine/include/webmachine.hrl"). -include_lib("rabbit_common/include/rabbit.hrl"). %%-------------------------------------------------------------------- init(_Config) -> {ok, #context{}}. content_types_provided(ReqData, Context) -> {[{"application/json", to_json}], ReqData, Context}. content_types_accepted(ReqData, Context) -> {[{"application/json", accept_content}], ReqData, Context}. allowed_methods(ReqData, Context) -> {['HEAD', 'GET', 'PUT', 'DELETE'], ReqData, Context}. resource_exists(ReqData, Context) -> {case perms(ReqData) of none -> false; not_found -> false; _ -> true end, ReqData, Context}. to_json(ReqData, Context) -> rabbit_mgmt_util:reply(perms(ReqData), ReqData, Context). accept_content(ReqData, Context) -> case perms(ReqData) of not_found -> rabbit_mgmt_util:bad_request(vhost_or_user_not_found, ReqData, Context); _ -> User = rabbit_mgmt_util:id(user, ReqData), VHost = rabbit_mgmt_util:id(vhost, ReqData), rabbit_mgmt_util:with_decode( [configure, write, read], ReqData, Context, fun([Conf, Write, Read], _) -> rabbit_auth_backend_internal:set_permissions( User, VHost, Conf, Write, Read), {true, ReqData, Context} end) end. delete_resource(ReqData, Context) -> User = rabbit_mgmt_util:id(user, ReqData), VHost = rabbit_mgmt_util:id(vhost, ReqData), rabbit_auth_backend_internal:clear_permissions(User, VHost), {true, ReqData, Context}. is_authorized(ReqData, Context) -> rabbit_mgmt_util:is_authorized_admin(ReqData, Context). %%-------------------------------------------------------------------- perms(ReqData) -> User = rabbit_mgmt_util:id(user, ReqData), case rabbit_auth_backend_internal:lookup_user(User) of {ok, _} -> case rabbit_mgmt_util:vhost(ReqData) of not_found -> not_found; VHost -> Perms = rabbit_auth_backend_internal:list_user_vhost_permissions( User, VHost), case Perms of [Rest] -> [{user, User}, {vhost, VHost} | Rest]; [] -> none end end; {error, _} -> not_found end. rabbitmq-server-3.2.4/plugins-src/rabbitmq-management/src/rabbit_mgmt_wm_vhosts.erl0000644000000000000000000000324112305126066027400 0ustar rootroot%% The contents of this file are subject to the Mozilla Public License %% Version 1.1 (the "License"); you may not use this file except in %% compliance with the License. You may obtain a copy of the License at %% http://www.mozilla.org/MPL/ %% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the %% License for the specific language governing rights and limitations %% under the License. %% %% The Original Code is RabbitMQ Management Plugin. %% %% The Initial Developer of the Original Code is GoPivotal, Inc. %% Copyright (c) 2010-2013 GoPivotal, Inc. All rights reserved. %% -module(rabbit_mgmt_wm_vhosts). -export([init/1, to_json/2, content_types_provided/2, is_authorized/2]). -export([basic/0, augmented/2]). -include("rabbit_mgmt.hrl"). -include_lib("webmachine/include/webmachine.hrl"). -include_lib("rabbit_common/include/rabbit.hrl"). %%-------------------------------------------------------------------- init(_Config) -> {ok, #context{}}. content_types_provided(ReqData, Context) -> {[{"application/json", to_json}], ReqData, Context}. to_json(ReqData, Context) -> rabbit_mgmt_util:reply_list(augmented(ReqData, Context), ReqData, Context). is_authorized(ReqData, Context) -> rabbit_mgmt_util:is_authorized(ReqData, Context). %%-------------------------------------------------------------------- augmented(ReqData, #context{user = User}) -> rabbit_mgmt_db:augment_vhosts( [rabbit_vhost:info(V) || V <- rabbit_mgmt_util:list_visible_vhosts(User)], rabbit_mgmt_util:range(ReqData)). basic() -> rabbit_vhost:info_all([name]). rabbitmq-server-3.2.4/plugins-src/rabbitmq-management/src/rabbit_mgmt_wm_connections.erl0000644000000000000000000000306112305126066030374 0ustar rootroot%% The contents of this file are subject to the Mozilla Public License %% Version 1.1 (the "License"); you may not use this file except in %% compliance with the License. You may obtain a copy of the License at %% http://www.mozilla.org/MPL/ %% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the %% License for the specific language governing rights and limitations %% under the License. %% %% The Original Code is RabbitMQ Management Plugin. %% %% The Initial Developer of the Original Code is GoPivotal, Inc. %% Copyright (c) 2010-2013 GoPivotal, Inc. All rights reserved. %% -module(rabbit_mgmt_wm_connections). -export([init/1, to_json/2, content_types_provided/2, is_authorized/2, augmented/2]). -import(rabbit_misc, [pget/2]). -include("rabbit_mgmt.hrl"). -include_lib("webmachine/include/webmachine.hrl"). -include_lib("rabbit_common/include/rabbit.hrl"). %%-------------------------------------------------------------------- init(_Config) -> {ok, #context{}}. content_types_provided(ReqData, Context) -> {[{"application/json", to_json}], ReqData, Context}. to_json(ReqData, Context) -> rabbit_mgmt_util:reply_list(augmented(ReqData, Context), ReqData, Context). is_authorized(ReqData, Context) -> rabbit_mgmt_util:is_authorized(ReqData, Context). augmented(ReqData, Context) -> rabbit_mgmt_util:filter_conn_ch_list( rabbit_mgmt_db:get_all_connections( rabbit_mgmt_util:range_ceil(ReqData)), ReqData, Context). rabbitmq-server-3.2.4/plugins-src/rabbitmq-management/src/rabbit_mgmt_wm_aliveness_test.erl0000644000000000000000000000434512305126066031110 0ustar rootroot%% The contents of this file are subject to the Mozilla Public License %% Version 1.1 (the "License"); you may not use this file except in %% compliance with the License. You may obtain a copy of the License at %% http://www.mozilla.org/MPL/ %% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the %% License for the specific language governing rights and limitations %% under the License. %% %% The Original Code is RabbitMQ Management Plugin. %% %% The Initial Developer of the Original Code is GoPivotal, Inc. %% Copyright (c) 2010-2013 GoPivotal, Inc. All rights reserved. %% -module(rabbit_mgmt_wm_aliveness_test). -export([init/1, to_json/2, content_types_provided/2, is_authorized/2]). -export([resource_exists/2]). -include("rabbit_mgmt.hrl"). -include_lib("webmachine/include/webmachine.hrl"). -include_lib("amqp_client/include/amqp_client.hrl"). -define(QUEUE, <<"aliveness-test">>). %%-------------------------------------------------------------------- init(_Config) -> {ok, #context{}}. content_types_provided(ReqData, Context) -> {[{"application/json", to_json}], ReqData, Context}. resource_exists(ReqData, Context) -> {case rabbit_mgmt_util:vhost(ReqData) of not_found -> false; _ -> true end, ReqData, Context}. to_json(ReqData, Context) -> rabbit_mgmt_util:with_channel( rabbit_mgmt_util:vhost(ReqData), ReqData, Context, fun(Ch) -> amqp_channel:call(Ch, #'queue.declare'{queue = ?QUEUE}), amqp_channel:call(Ch, #'basic.publish'{routing_key = ?QUEUE}, #amqp_msg{payload = <<"test_message">>}), {#'basic.get_ok'{}, _} = amqp_channel:call(Ch, #'basic.get'{queue = ?QUEUE, no_ack = true}), %% Don't delete the queue. If this is pinged every few %% seconds we don't want to create a mnesia transaction %% each time. rabbit_mgmt_util:reply([{status, ok}], ReqData, Context) end). is_authorized(ReqData, Context) -> rabbit_mgmt_util:is_authorized_vhost(ReqData, Context). rabbitmq-server-3.2.4/plugins-src/rabbitmq-management/src/rabbit_mgmt_load_definitions.erl0000644000000000000000000000372212305126066030665 0ustar rootroot%% The contents of this file are subject to the Mozilla Public License %% Version 1.1 (the "License"); you may not use this file except in %% compliance with the License. You may obtain a copy of the License at %% http://www.mozilla.org/MPL/ %% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the %% License for the specific language governing rights and limitations %% under the License. %% %% The Original Code is RabbitMQ Management Plugin. %% %% The Initial Developer of the Original Code is GoPivotal, Inc. %% Copyright (c) 2010-2013 GoPivotal, Inc. All rights reserved. %% -module(rabbit_mgmt_load_definitions). -export([maybe_load_definitions/0]). %% We want to A) make sure we apply defintions before being open for %% business (hence why we don't do this in the mgmt app startup) and %% B) in fact do it before empty_db_check (so the defaults will not %% get created if we don't need 'em). -rabbit_boot_step({load_definitions, [{description, "configured definitions"}, {mfa, {rabbit_mgmt_load_definitions, maybe_load_definitions, []}}, {requires, recovery}, {enables, empty_db_check}]}). maybe_load_definitions() -> {ok, File} = application:get_env(rabbitmq_management, load_definitions), case File of none -> ok; _ -> case file:read_file(File) of {ok, Body} -> rabbit_log:info( "Applying definitions from: ~s~n", [File]), load_definitions(Body); {error, E} -> {error, {could_not_read_defs, {File, E}}} end end. load_definitions(Body) -> rabbit_mgmt_wm_definitions:apply_defs( Body, fun rabbit_misc:const_ok/0, fun (E) -> {error, E} end). rabbitmq-server-3.2.4/plugins-src/rabbitmq-management/src/rabbit_mgmt_wm_policies.erl0000644000000000000000000000351712305126066027667 0ustar rootroot%% The contents of this file are subject to the Mozilla Public License %% Version 1.1 (the "License"); you may not use this file except in %% compliance with the License. You may obtain a copy of the License at %% http://www.mozilla.org/MPL/ %% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the %% License for the specific language governing rights and limitations %% under the License. %% %% The Original Code is RabbitMQ Management Plugin. %% %% The Initial Developer of the Original Code is GoPivotal, Inc. %% Copyright (c) 2010-2013 GoPivotal, Inc. All rights reserved. %% -module(rabbit_mgmt_wm_policies). -export([init/1, to_json/2, content_types_provided/2, is_authorized/2, resource_exists/2, basic/1]). -include("rabbit_mgmt.hrl"). -include_lib("webmachine/include/webmachine.hrl"). -include_lib("rabbit_common/include/rabbit.hrl"). %%-------------------------------------------------------------------- init(_Config) -> {ok, #context{}}. content_types_provided(ReqData, Context) -> {[{"application/json", to_json}], ReqData, Context}. resource_exists(ReqData, Context) -> {case basic(ReqData) of not_found -> false; _ -> true end, ReqData, Context}. to_json(ReqData, Context) -> rabbit_mgmt_util:reply_list( rabbit_mgmt_util:filter_vhost(basic(ReqData), ReqData, Context), ["priority"], ReqData, Context). is_authorized(ReqData, Context) -> rabbit_mgmt_util:is_authorized_policies(ReqData, Context). %%-------------------------------------------------------------------- basic(ReqData) -> case rabbit_mgmt_util:vhost(ReqData) of not_found -> not_found; none -> rabbit_policy:list(); VHost -> rabbit_policy:list(VHost) end. rabbitmq-server-3.2.4/plugins-src/rabbitmq-management/src/rabbit_mgmt_wm_parameters.erl0000644000000000000000000000443112305126066030217 0ustar rootroot%% The contents of this file are subject to the Mozilla Public License %% Version 1.1 (the "License"); you may not use this file except in %% compliance with the License. You may obtain a copy of the License at %% http://www.mozilla.org/MPL/ %% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the %% License for the specific language governing rights and limitations %% under the License. %% %% The Original Code is RabbitMQ Management Plugin. %% %% The Initial Developer of the Original Code is GoPivotal, Inc. %% Copyright (c) 2010-2013 GoPivotal, Inc. All rights reserved. %% -module(rabbit_mgmt_wm_parameters). -export([init/1, to_json/2, content_types_provided/2, is_authorized/2, resource_exists/2, basic/1]). -include("rabbit_mgmt.hrl"). -include_lib("webmachine/include/webmachine.hrl"). -include_lib("rabbit_common/include/rabbit.hrl"). %%-------------------------------------------------------------------- init(_Config) -> {ok, #context{}}. content_types_provided(ReqData, Context) -> {[{"application/json", to_json}], ReqData, Context}. resource_exists(ReqData, Context) -> {case basic(ReqData) of not_found -> false; _ -> true end, ReqData, Context}. to_json(ReqData, Context) -> rabbit_mgmt_util:reply_list( rabbit_mgmt_util:filter_vhost(basic(ReqData), ReqData, Context), ReqData, Context). is_authorized(ReqData, Context) -> rabbit_mgmt_util:is_authorized_policies(ReqData, Context). %%-------------------------------------------------------------------- basic(ReqData) -> Raw = case rabbit_mgmt_util:id(component, ReqData) of none -> rabbit_runtime_parameters:list(); Name -> case rabbit_mgmt_util:vhost(ReqData) of none -> rabbit_runtime_parameters:list_component( Name); not_found -> not_found; VHost -> rabbit_runtime_parameters:list( VHost, Name) end end, case Raw of not_found -> not_found; _ -> [rabbit_mgmt_format:parameter(P) || P <- Raw] end. rabbitmq-server-3.2.4/plugins-src/rabbitmq-management/src/rabbit_mgmt_wm_exchanges.erl0000644000000000000000000000374312305126066030026 0ustar rootroot%% The contents of this file are subject to the Mozilla Public License %% Version 1.1 (the "License"); you may not use this file except in %% compliance with the License. You may obtain a copy of the License at %% http://www.mozilla.org/MPL/ %% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the %% License for the specific language governing rights and limitations %% under the License. %% %% The Original Code is RabbitMQ Management Plugin. %% %% The Initial Developer of the Original Code is GoPivotal, Inc. %% Copyright (c) 2010-2013 GoPivotal, Inc. All rights reserved. %% -module(rabbit_mgmt_wm_exchanges). -export([init/1, to_json/2, content_types_provided/2, is_authorized/2, resource_exists/2, basic/1, augmented/2]). -include("rabbit_mgmt.hrl"). -include_lib("webmachine/include/webmachine.hrl"). -include_lib("rabbit_common/include/rabbit.hrl"). %%-------------------------------------------------------------------- init(_Config) -> {ok, #context{}}. content_types_provided(ReqData, Context) -> {[{"application/json", to_json}], ReqData, Context}. resource_exists(ReqData, Context) -> {case exchanges0(ReqData) of vhost_not_found -> false; _ -> true end, ReqData, Context}. to_json(ReqData, Context) -> rabbit_mgmt_util:reply_list(augmented(ReqData, Context), ReqData, Context). is_authorized(ReqData, Context) -> rabbit_mgmt_util:is_authorized_vhost(ReqData, Context). %%-------------------------------------------------------------------- augmented(ReqData, Context) -> rabbit_mgmt_db:augment_exchanges( rabbit_mgmt_util:filter_vhost(basic(ReqData), ReqData, Context), rabbit_mgmt_util:range(ReqData), basic). basic(ReqData) -> [rabbit_mgmt_format:exchange(X) || X <- exchanges0(ReqData)]. exchanges0(ReqData) -> rabbit_mgmt_util:all_or_one_vhost(ReqData, fun rabbit_exchange:info_all/1). rabbitmq-server-3.2.4/plugins-src/rabbitmq-management/src/rabbit_mgmt_wm_bindings.erl0000644000000000000000000001231612305126066027652 0ustar rootroot%% The contents of this file are subject to the Mozilla Public License %% Version 1.1 (the "License"); you may not use this file except in %% compliance with the License. You may obtain a copy of the License at %% http://www.mozilla.org/MPL/ %% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the %% License for the specific language governing rights and limitations %% under the License. %% %% The Original Code is RabbitMQ Management Plugin. %% %% The Initial Developer of the Original Code is GoPivotal, Inc. %% Copyright (c) 2010-2013 GoPivotal, Inc. All rights reserved. %% -module(rabbit_mgmt_wm_bindings). -export([init/1, to_json/2, content_types_provided/2, is_authorized/2]). -export([allowed_methods/2, post_is_create/2, create_path/2]). -export([content_types_accepted/2, accept_content/2, resource_exists/2]). -export([basic/1, augmented/2]). -include("rabbit_mgmt.hrl"). -include_lib("webmachine/include/webmachine.hrl"). -include_lib("amqp_client/include/amqp_client.hrl"). %%-------------------------------------------------------------------- init([Mode]) -> {ok, {Mode, #context{}}}. content_types_provided(ReqData, Context) -> {[{"application/json", to_json}], ReqData, Context}. resource_exists(ReqData, {Mode, Context}) -> {case list_bindings(Mode, ReqData) of vhost_not_found -> false; _ -> true end, ReqData, {Mode, Context}}. content_types_accepted(ReqData, Context) -> {[{"application/json", accept_content}], ReqData, Context}. allowed_methods(ReqData, {Mode, Context}) -> {case Mode of source_destination -> ['HEAD', 'GET', 'POST']; _ -> ['HEAD', 'GET'] end, ReqData, {Mode, Context}}. post_is_create(ReqData, Context) -> {true, ReqData, Context}. to_json(ReqData, {Mode, Context}) -> Bs = [rabbit_mgmt_format:binding(B) || B <- list_bindings(Mode, ReqData)], rabbit_mgmt_util:reply_list( rabbit_mgmt_util:filter_vhost(Bs, ReqData, Context), ["vhost", "source", "type", "destination", "routing_key", "properties_key"], ReqData, {Mode, Context}). create_path(ReqData, Context) -> {"dummy", ReqData, Context}. accept_content(ReqData, {_Mode, Context}) -> Source = rabbit_mgmt_util:id(source, ReqData), Dest = rabbit_mgmt_util:id(destination, ReqData), DestType = rabbit_mgmt_util:id(dtype, ReqData), VHost = rabbit_mgmt_util:vhost(ReqData), {ok, Props} = rabbit_mgmt_util:decode(wrq:req_body(ReqData)), {Method, Key, Args} = method_key_args(DestType, Source, Dest, Props), Response = rabbit_mgmt_util:amqp_request(VHost, ReqData, Context, Method), case Response of {{halt, _}, _, _} = Res -> Res; {true, ReqData, Context2} -> Loc = rabbit_web_dispatch_util:relativise( wrq:path(ReqData), binary_to_list( rabbit_mgmt_format:url( "/api/bindings/~s/e/~s/~s/~s/~s", [VHost, Source, DestType, Dest, rabbit_mgmt_format:pack_binding_props(Key, Args)]))), ReqData2 = wrq:set_resp_header("Location", Loc, ReqData), {true, ReqData2, Context2} end. is_authorized(ReqData, {Mode, Context}) -> {Res, RD2, C2} = rabbit_mgmt_util:is_authorized_vhost(ReqData, Context), {Res, RD2, {Mode, C2}}. %%-------------------------------------------------------------------- basic(ReqData) -> [rabbit_mgmt_format:binding(B) || B <- list_bindings(all, ReqData)]. augmented(ReqData, Context) -> rabbit_mgmt_util:filter_vhost(basic(ReqData), ReqData, Context). method_key_args(<<"q">>, Source, Dest, Props) -> M = #'queue.bind'{routing_key = K, arguments = A} = rabbit_mgmt_util:props_to_method( 'queue.bind', Props, [], [{exchange, Source}, {queue, Dest}]), {M, K, A}; method_key_args(<<"e">>, Source, Dest, Props) -> M = #'exchange.bind'{routing_key = K, arguments = A} = rabbit_mgmt_util:props_to_method( 'exchange.bind', Props, [], [{source, Source}, {destination, Dest}]), {M, K, A}. %%-------------------------------------------------------------------- list_bindings(all, ReqData) -> rabbit_mgmt_util:all_or_one_vhost(ReqData, fun (VHost) -> rabbit_binding:list(VHost) end); list_bindings(exchange_source, ReqData) -> rabbit_binding:list_for_source(r(exchange, exchange, ReqData)); list_bindings(exchange_destination, ReqData) -> rabbit_binding:list_for_destination(r(exchange, exchange, ReqData)); list_bindings(queue, ReqData) -> rabbit_binding:list_for_destination(r(queue, destination, ReqData)); list_bindings(source_destination, ReqData) -> DestType = rabbit_mgmt_util:destination_type(ReqData), rabbit_binding:list_for_source_and_destination( r(exchange, source, ReqData), r(DestType, destination, ReqData)). r(Type, Name, ReqData) -> rabbit_misc:r(rabbit_mgmt_util:vhost(ReqData), Type, rabbit_mgmt_util:id(Name, ReqData)). rabbitmq-server-3.2.4/plugins-src/rabbitmq-management/src/rabbit_mgmt_wm_user.erl0000644000000000000000000000772012305126066027036 0ustar rootroot%% The contents of this file are subject to the Mozilla Public License %% Version 1.1 (the "License"); you may not use this file except in %% compliance with the License. You may obtain a copy of the License at %% http://www.mozilla.org/MPL/ %% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the %% License for the specific language governing rights and limitations %% under the License. %% %% The Original Code is RabbitMQ Management Plugin. %% %% The Initial Developer of the Original Code is GoPivotal, Inc. %% Copyright (c) 2010-2013 GoPivotal, Inc. All rights reserved. %% -module(rabbit_mgmt_wm_user). -export([init/1, resource_exists/2, to_json/2, content_types_provided/2, content_types_accepted/2, is_authorized/2, allowed_methods/2, accept_content/2, delete_resource/2, put_user/1]). -import(rabbit_misc, [pget/2]). -include("rabbit_mgmt.hrl"). -include_lib("webmachine/include/webmachine.hrl"). -include_lib("rabbit_common/include/rabbit.hrl"). %%-------------------------------------------------------------------- init(_Config) -> {ok, #context{}}. content_types_provided(ReqData, Context) -> {[{"application/json", to_json}], ReqData, Context}. content_types_accepted(ReqData, Context) -> {[{"application/json", accept_content}], ReqData, Context}. allowed_methods(ReqData, Context) -> {['HEAD', 'GET', 'PUT', 'DELETE'], ReqData, Context}. resource_exists(ReqData, Context) -> {case user(ReqData) of {ok, _} -> true; {error, _} -> false end, ReqData, Context}. to_json(ReqData, Context) -> {ok, User} = user(ReqData), rabbit_mgmt_util:reply(rabbit_mgmt_format:internal_user(User), ReqData, Context). accept_content(ReqData, Context) -> Username = rabbit_mgmt_util:id(user, ReqData), rabbit_mgmt_util:with_decode( [], ReqData, Context, fun(_, User) -> put_user([{name, Username} | User]), {true, ReqData, Context} end). delete_resource(ReqData, Context) -> User = rabbit_mgmt_util:id(user, ReqData), rabbit_auth_backend_internal:delete_user(User), {true, ReqData, Context}. is_authorized(ReqData, Context) -> rabbit_mgmt_util:is_authorized_admin(ReqData, Context). %%-------------------------------------------------------------------- user(ReqData) -> rabbit_auth_backend_internal:lookup_user(rabbit_mgmt_util:id(user, ReqData)). put_user(User) -> CP = fun rabbit_auth_backend_internal:change_password/2, CPH = fun rabbit_auth_backend_internal:change_password_hash/2, case {proplists:is_defined(password, User), proplists:is_defined(password_hash, User)} of {true, _} -> put_user(User, pget(password, User), CP); {_, true} -> Hash = rabbit_mgmt_util:b64decode_or_throw( pget(password_hash, User)), put_user(User, Hash, CPH); _ -> put_user(User, <<>>, CPH) end. put_user(User, PWArg, PWFun) -> Username = pget(name, User), Tags = case {pget(tags, User), pget(administrator, User)} of {undefined, undefined} -> throw({error, tags_not_present}); {undefined, AdminS} -> case rabbit_mgmt_util:parse_bool(AdminS) of true -> [administrator]; false -> [] end; {TagsS, _} -> [list_to_atom(string:strip(T)) || T <- string:tokens(binary_to_list(TagsS), ",")] end, case rabbit_auth_backend_internal:lookup_user(Username) of {error, not_found} -> rabbit_auth_backend_internal:add_user( Username, rabbit_guid:binary(rabbit_guid:gen_secure(), "tmp")); _ -> ok end, PWFun(Username, PWArg), ok = rabbit_auth_backend_internal:set_tags(Username, Tags). rabbitmq-server-3.2.4/plugins-src/rabbitmq-management/src/rabbit_mgmt_dispatcher.erl0000644000000000000000000001337312305126066027504 0ustar rootroot%% The contents of this file are subject to the Mozilla Public License %% Version 1.1 (the "License"); you may not use this file except in %% compliance with the License. You may obtain a copy of the License at %% http://www.mozilla.org/MPL/ %% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the %% License for the specific language governing rights and limitations %% under the License. %% %% The Original Code is RabbitMQ Management Plugin. %% %% The Initial Developer of the Original Code is GoPivotal, Inc. %% Copyright (c) 2010-2013 GoPivotal, Inc. All rights reserved. %% -module(rabbit_mgmt_dispatcher). -export([modules/0, build_dispatcher/0]). -behaviour(rabbit_mgmt_extension). -export([dispatcher/0, web_ui/0]). build_dispatcher() -> [{["api" | Path], Mod, Args} || {Path, Mod, Args} <- lists:append([Module:dispatcher() || Module <- modules()])]. modules() -> [Module || {Module, Behaviours} <- rabbit_misc:all_module_attributes(behaviour), lists:member(rabbit_mgmt_extension, Behaviours)]. %%---------------------------------------------------------------------------- web_ui() -> [{javascript, <<"dispatcher.js">>}]. dispatcher() -> [{["overview"], rabbit_mgmt_wm_overview, []}, {["nodes"], rabbit_mgmt_wm_nodes, []}, {["nodes", node], rabbit_mgmt_wm_node, []}, {["extensions"], rabbit_mgmt_wm_extensions, []}, {["all-configuration"], rabbit_mgmt_wm_definitions, []}, %% This was the old name, let's not break things gratuitously. {["definitions"], rabbit_mgmt_wm_definitions, []}, {["parameters"], rabbit_mgmt_wm_parameters, []}, {["parameters", component], rabbit_mgmt_wm_parameters, []}, {["parameters", component, vhost], rabbit_mgmt_wm_parameters, []}, {["parameters", component, vhost, name], rabbit_mgmt_wm_parameter, []}, {["policies"], rabbit_mgmt_wm_policies, []}, {["policies", vhost], rabbit_mgmt_wm_policies, []}, {["policies", vhost, name], rabbit_mgmt_wm_policy, []}, {["connections"], rabbit_mgmt_wm_connections, []}, {["connections", connection], rabbit_mgmt_wm_connection, []}, {["connections", connection, "channels"], rabbit_mgmt_wm_connection_channels, []}, {["channels"], rabbit_mgmt_wm_channels, []}, {["channels", channel], rabbit_mgmt_wm_channel, []}, {["exchanges"], rabbit_mgmt_wm_exchanges, []}, {["exchanges", vhost], rabbit_mgmt_wm_exchanges, []}, {["exchanges", vhost, exchange], rabbit_mgmt_wm_exchange, []}, {["exchanges", vhost, exchange, "publish"], rabbit_mgmt_wm_exchange_publish, []}, {["exchanges", vhost, exchange, "bindings", "source"], rabbit_mgmt_wm_bindings, [exchange_source]}, {["exchanges", vhost, exchange, "bindings", "destination"], rabbit_mgmt_wm_bindings, [exchange_destination]}, {["queues"], rabbit_mgmt_wm_queues, []}, {["queues", vhost], rabbit_mgmt_wm_queues, []}, {["queues", vhost, queue], rabbit_mgmt_wm_queue, []}, {["queues", vhost, destination, "bindings"], rabbit_mgmt_wm_bindings, [queue]}, {["queues", vhost, queue, "contents"], rabbit_mgmt_wm_queue_purge, []}, {["queues", vhost, queue, "get"], rabbit_mgmt_wm_queue_get, []}, {["queues", vhost, queue, "actions"], rabbit_mgmt_wm_queue_actions, []}, {["bindings"], rabbit_mgmt_wm_bindings, [all]}, {["bindings", vhost], rabbit_mgmt_wm_bindings, [all]}, {["bindings", vhost, "e", source, dtype, destination], rabbit_mgmt_wm_bindings, [source_destination]}, {["bindings", vhost, "e", source, dtype, destination, props], rabbit_mgmt_wm_binding, []}, {["vhosts"], rabbit_mgmt_wm_vhosts, []}, {["vhosts", vhost], rabbit_mgmt_wm_vhost, []}, {["vhosts", vhost, "permissions"], rabbit_mgmt_wm_permissions_vhost, []}, {["users"], rabbit_mgmt_wm_users, []}, {["users", user], rabbit_mgmt_wm_user, []}, {["users", user, "permissions"], rabbit_mgmt_wm_permissions_user, []}, {["whoami"], rabbit_mgmt_wm_whoami, []}, {["permissions"], rabbit_mgmt_wm_permissions, []}, {["permissions", vhost, user], rabbit_mgmt_wm_permission, []}, {["aliveness-test", vhost], rabbit_mgmt_wm_aliveness_test, []} ]. rabbitmq-server-3.2.4/plugins-src/rabbitmq-management/src/rabbit_mgmt_util.erl0000644000000000000000000005237612305126066026341 0ustar rootroot%% The contents of this file are subject to the Mozilla Public License %% Version 1.1 (the "License"); you may not use this file except in %% compliance with the License. You may obtain a copy of the License at %% http://www.mozilla.org/MPL/ %% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the %% License for the specific language governing rights and limitations %% under the License. %% %% The Original Code is RabbitMQ Management Plugin. %% %% The Initial Developer of the Original Code is GoPivotal, Inc. %% Copyright (c) 2010-2013 GoPivotal, Inc. All rights reserved. %% -module(rabbit_mgmt_util). %% TODO sort all this out; maybe there's scope for rabbit_mgmt_request? -export([is_authorized/2, is_authorized_admin/2, is_authorized_admin/4, vhost/1]). -export([is_authorized_vhost/2, is_authorized_user/3, is_authorized_monitor/2, is_authorized_policies/2]). -export([bad_request/3, bad_request_exception/4, id/2, parse_bool/1, parse_int/1]). -export([with_decode/4, not_found/3, amqp_request/4]). -export([with_channel/4, with_channel/5]). -export([props_to_method/2, props_to_method/4]). -export([all_or_one_vhost/2, http_to_amqp/5, reply/3, filter_vhost/3]). -export([filter_conn_ch_list/3, filter_user/2]). -export([with_decode/5, decode/1, decode/2, redirect/2, args/1]). -export([reply_list/3, reply_list/4, sort_list/2, destination_type/1]). -export([post_respond/1, columns/1, is_monitor/1]). -export([list_visible_vhosts/1, b64decode_or_throw/1, no_range/0, range/1, range_ceil/1, floor/2, ceil/2]). -import(rabbit_misc, [pget/2, pget/3]). -include("rabbit_mgmt.hrl"). -include_lib("amqp_client/include/amqp_client.hrl"). -define(FRAMING, rabbit_framing_amqp_0_9_1). %%-------------------------------------------------------------------- is_authorized(ReqData, Context) -> is_authorized(ReqData, Context, '', fun(_) -> true end). is_authorized_admin(ReqData, Context) -> is_authorized(ReqData, Context, <<"Not administrator user">>, fun(#user{tags = Tags}) -> is_admin(Tags) end). is_authorized_admin(ReqData, Context, Username, Password) -> is_authorized(ReqData, Context, Username, Password, <<"Not administrator user">>, fun(#user{tags = Tags}) -> is_admin(Tags) end). is_authorized_monitor(ReqData, Context) -> is_authorized(ReqData, Context, <<"Not monitor user">>, fun(#user{tags = Tags}) -> is_monitor(Tags) end). is_authorized_vhost(ReqData, Context) -> is_authorized(ReqData, Context, <<"User not authorised to access virtual host">>, fun(User) -> user_matches_vhost(ReqData, User) end). user_matches_vhost(ReqData, User) -> case vhost(ReqData) of not_found -> true; none -> true; V -> lists:member(V, list_login_vhosts(User)) end. %% Used for connections / channels. A normal user can only see / delete %% their own stuff. Monitors can see other users' and delete their %% own. Admins can do it all. is_authorized_user(ReqData, Context, Item) -> is_authorized(ReqData, Context, <<"User not authorised to access object">>, fun(#user{username = Username, tags = Tags}) -> case wrq:method(ReqData) of 'DELETE' -> is_admin(Tags); _ -> is_monitor(Tags) end orelse Username == pget(user, Item) end). %% For policies / parameters. Like is_authorized_vhost but you have to %% be a policymaker. is_authorized_policies(ReqData, Context) -> is_authorized(ReqData, Context, <<"User not authorised to access object">>, fun(User = #user{tags = Tags}) -> is_policymaker(Tags) andalso user_matches_vhost(ReqData, User) end). is_authorized(ReqData, Context, ErrorMsg, Fun) -> case rabbit_web_dispatch_util:parse_auth_header( wrq:get_req_header("authorization", ReqData)) of [Username, Password] -> is_authorized(ReqData, Context, Username, Password, ErrorMsg, Fun); _ -> {?AUTH_REALM, ReqData, Context} end. is_authorized(ReqData, Context, Username, Password, ErrorMsg, Fun) -> ErrFun = fun (Msg) -> not_authorised(Msg, ReqData, Context) end, case rabbit_access_control:check_user_pass_login(Username, Password) of {ok, User = #user{tags = Tags}} -> case is_mgmt_user(Tags) of true -> case Fun(User) of true -> {true, ReqData, Context#context{user = User, password = Password}}; false -> ErrFun(ErrorMsg) end; false -> ErrFun(<<"Not management user">>) end; _ -> ErrFun(<<"Login failed">>) end. vhost(ReqData) -> case id(vhost, ReqData) of none -> none; VHost -> case rabbit_vhost:exists(VHost) of true -> VHost; false -> not_found end end. destination_type(ReqData) -> case id(dtype, ReqData) of <<"e">> -> exchange; <<"q">> -> queue end. reply(Facts, ReqData, Context) -> reply0(extract_columns(Facts, ReqData), ReqData, Context). reply0(Facts, ReqData, Context) -> ReqData1 = wrq:set_resp_header("Cache-Control", "no-cache", ReqData), try {mochijson2:encode(Facts), ReqData1, Context} catch exit:{json_encode, E} -> Error = iolist_to_binary( io_lib:format("JSON encode error: ~p", [E])), Reason = iolist_to_binary( io_lib:format("While encoding:~n~p", [Facts])), internal_server_error(Error, Reason, ReqData1, Context) end. reply_list(Facts, ReqData, Context) -> reply_list(Facts, ["vhost", "name"], ReqData, Context). reply_list(Facts, DefaultSorts, ReqData, Context) -> reply(sort_list( extract_columns_list(Facts, ReqData), DefaultSorts, wrq:get_qs_value("sort", ReqData), wrq:get_qs_value("sort_reverse", ReqData)), ReqData, Context). sort_list(Facts, Sorts) -> sort_list(Facts, Sorts, undefined, false). sort_list(Facts, DefaultSorts, Sort, Reverse) -> SortList = case Sort of undefined -> DefaultSorts; Extra -> [Extra | DefaultSorts] end, %% lists:sort/2 is much more expensive than lists:sort/1 Sorted = [V || {_K, V} <- lists:sort( [{sort_key(F, SortList), F} || F <- Facts])], case Reverse of "true" -> lists:reverse(Sorted); _ -> Sorted end. sort_key(_Item, []) -> []; sort_key(Item, [Sort | Sorts]) -> [get_dotted_value(Sort, Item) | sort_key(Item, Sorts)]. get_dotted_value(Key, Item) -> Keys = string:tokens(Key, "."), get_dotted_value0(Keys, Item). get_dotted_value0([Key], Item) -> %% Put "nothing" before everything else, in number terms it usually %% means 0. pget_bin(list_to_binary(Key), Item, 0); get_dotted_value0([Key | Keys], Item) -> get_dotted_value0(Keys, pget_bin(list_to_binary(Key), Item, [])). pget_bin(Key, List, Default) -> case lists:partition(fun ({K, _V}) -> a2b(K) =:= Key end, List) of {[{_K, V}], _} -> V; {[], _} -> Default end. extract_columns(Item, ReqData) -> extract_column_items(Item, columns(ReqData)). extract_columns_list(Items, ReqData) -> Cols = columns(ReqData), [extract_column_items(Item, Cols) || Item <- Items]. columns(ReqData) -> case wrq:get_qs_value("columns", ReqData) of undefined -> all; Str -> [[list_to_binary(T) || T <- string:tokens(C, ".")] || C <- string:tokens(Str, ",")] end. extract_column_items(Item, all) -> Item; extract_column_items({struct, L}, Cols) -> extract_column_items(L, Cols); extract_column_items(Item = [T | _], Cols) when is_tuple(T) -> [{K, extract_column_items(V, descend_columns(a2b(K), Cols))} || {K, V} <- Item, want_column(a2b(K), Cols)]; extract_column_items(L, Cols) when is_list(L) -> [extract_column_items(I, Cols) || I <- L]; extract_column_items(O, _Cols) -> O. want_column(_Col, all) -> true; want_column(Col, Cols) -> lists:any(fun([C|_]) -> C == Col end, Cols). descend_columns(_K, []) -> []; descend_columns( K, [[K] | _Rest]) -> all; descend_columns( K, [[K | K2] | Rest]) -> [K2 | descend_columns(K, Rest)]; descend_columns( K, [[_K2 | _ ] | Rest]) -> descend_columns(K, Rest). a2b(A) when is_atom(A) -> list_to_binary(atom_to_list(A)); a2b(B) -> B. bad_request(Reason, ReqData, Context) -> halt_response(400, bad_request, Reason, ReqData, Context). not_authorised(Reason, ReqData, Context) -> halt_response(401, not_authorised, Reason, ReqData, Context). not_found(Reason, ReqData, Context) -> halt_response(404, not_found, Reason, ReqData, Context). internal_server_error(Error, Reason, ReqData, Context) -> rabbit_log:error("~s~n~s~n", [Error, Reason]), halt_response(500, Error, Reason, ReqData, Context). halt_response(Code, Type, Reason, ReqData, Context) -> Json = {struct, [{error, Type}, {reason, rabbit_mgmt_format:tuple(Reason)}]}, ReqData1 = wrq:append_to_response_body(mochijson2:encode(Json), ReqData), {{halt, Code}, ReqData1, Context}. id(Key, ReqData) when Key =:= exchange; Key =:= source; Key =:= destination -> case id0(Key, ReqData) of <<"amq.default">> -> <<"">>; Name -> Name end; id(Key, ReqData) -> id0(Key, ReqData). id0(Key, ReqData) -> case orddict:find(Key, wrq:path_info(ReqData)) of {ok, Id} -> list_to_binary(mochiweb_util:unquote(Id)); error -> none end. with_decode(Keys, ReqData, Context, Fun) -> with_decode(Keys, wrq:req_body(ReqData), ReqData, Context, Fun). with_decode(Keys, Body, ReqData, Context, Fun) -> case decode(Keys, Body) of {error, Reason} -> bad_request(Reason, ReqData, Context); {ok, Values, JSON} -> try Fun(Values, JSON) catch {error, Error} -> bad_request(Error, ReqData, Context) end end. decode(Keys, Body) -> case decode(Body) of {ok, J0} -> J = [{list_to_atom(binary_to_list(K)), V} || {K, V} <- J0], Results = [get_or_missing(K, J) || K <- Keys], case [E || E = {key_missing, _} <- Results] of [] -> {ok, Results, J}; Errors -> {error, Errors} end; Else -> Else end. decode(<<"">>) -> {ok, []}; decode(Body) -> try {struct, J} = mochijson2:decode(Body), {ok, J} catch error:_ -> {error, not_json} end. get_or_missing(K, L) -> case pget(K, L) of undefined -> {key_missing, K}; V -> V end. http_to_amqp(MethodName, ReqData, Context, Transformers, Extra) -> case vhost(ReqData) of not_found -> not_found(vhost_not_found, ReqData, Context); VHost -> case decode(wrq:req_body(ReqData)) of {ok, Props} -> try Node = case pget(<<"node">>, Props) of undefined -> node(); N -> rabbit_nodes:make( binary_to_list(N)) end, amqp_request(VHost, ReqData, Context, Node, props_to_method( MethodName, Props, Transformers, Extra)) catch {error, Error} -> bad_request(Error, ReqData, Context) end; {error, Reason} -> bad_request(Reason, ReqData, Context) end end. props_to_method(MethodName, Props, Transformers, Extra) -> Props1 = [{list_to_atom(binary_to_list(K)), V} || {K, V} <- Props], props_to_method( MethodName, rabbit_mgmt_format:format(Props1 ++ Extra, Transformers)). props_to_method(MethodName, Props) -> Props1 = rabbit_mgmt_format:format( Props, [{fun (Args) -> [{arguments, args(Args)}] end, [arguments]}]), FieldNames = ?FRAMING:method_fieldnames(MethodName), {Res, _Idx} = lists:foldl( fun (K, {R, Idx}) -> NewR = case pget(K, Props1) of undefined -> R; V -> setelement(Idx, R, V) end, {NewR, Idx + 1} end, {?FRAMING:method_record(MethodName), 2}, FieldNames), Res. parse_bool(<<"true">>) -> true; parse_bool(<<"false">>) -> false; parse_bool(true) -> true; parse_bool(false) -> false; parse_bool(undefined) -> undefined; parse_bool(V) -> throw({error, {not_boolean, V}}). parse_int(I) when is_integer(I) -> I; parse_int(F) when is_number(F) -> trunc(F); parse_int(S) -> try list_to_integer(binary_to_list(S)) catch error:badarg -> throw({error, {not_integer, S}}) end. amqp_request(VHost, ReqData, Context, Method) -> amqp_request(VHost, ReqData, Context, node(), Method). amqp_request(VHost, ReqData, Context, Node, Method) -> with_channel(VHost, ReqData, Context, Node, fun (Ch) -> amqp_channel:call(Ch, Method), {true, ReqData, Context} end). with_channel(VHost, ReqData, Context, Fun) -> with_channel(VHost, ReqData, Context, node(), Fun). with_channel(VHost, ReqData, Context = #context{user = #user {username = Username}, password = Password}, Node, Fun) -> Params = #amqp_params_direct{username = Username, password = Password, node = Node, virtual_host = VHost}, case amqp_connection:start(Params) of {ok, Conn} -> {ok, Ch} = amqp_connection:open_channel(Conn), try Fun(Ch) catch exit:{{shutdown, {server_initiated_close, ?NOT_FOUND, Reason}}, _} -> not_found(Reason, ReqData, Context); exit:{{shutdown, {server_initiated_close, ?ACCESS_REFUSED, Reason}}, _} -> not_authorised(Reason, ReqData, Context); exit:{{shutdown, {ServerClose, Code, Reason}}, _} when ServerClose =:= server_initiated_close; ServerClose =:= server_initiated_hard_close -> bad_request_exception(Code, Reason, ReqData, Context); exit:{{shutdown, {connection_closing, {ServerClose, Code, Reason}}}, _} when ServerClose =:= server_initiated_close; ServerClose =:= server_initiated_hard_close -> bad_request_exception(Code, Reason, ReqData, Context) after catch amqp_channel:close(Ch), catch amqp_connection:close(Conn) end; {error, {auth_failure, Msg}} -> not_authorised(Msg, ReqData, Context); {error, {nodedown, N}} -> bad_request( list_to_binary( io_lib:format("Node ~s could not be contacted", [N])), ReqData, Context) end. bad_request_exception(Code, Reason, ReqData, Context) -> bad_request(list_to_binary(io_lib:format("~p ~s", [Code, Reason])), ReqData, Context). all_or_one_vhost(ReqData, Fun) -> case rabbit_mgmt_util:vhost(ReqData) of none -> lists:append([Fun(V) || V <- rabbit_vhost:list()]); not_found -> vhost_not_found; VHost -> Fun(VHost) end. filter_vhost(List, _ReqData, Context) -> VHosts = list_login_vhosts(Context#context.user), [I || I <- List, lists:member(pget(vhost, I), VHosts)]. filter_user(List, _ReqData, #context{user = User}) -> filter_user(List, User). filter_user(List, #user{username = Username, tags = Tags}) -> case is_monitor(Tags) of true -> List; false -> [I || I <- List, pget(user, I) == Username] end. filter_conn_ch_list(List, ReqData, Context) -> rabbit_mgmt_format:strip_pids( filter_user( case vhost(ReqData) of none -> List; VHost -> [I || I <- List, pget(vhost, I) =:= VHost] end, ReqData, Context)). redirect(Location, ReqData) -> wrq:do_redirect(true, wrq:set_resp_header("Location", binary_to_list(Location), ReqData)). args({struct, L}) -> args(L); args(L) -> rabbit_mgmt_format:to_amqp_table(L). %% Make replying to a post look like anything else... post_respond({true, ReqData, Context}) -> {true, ReqData, Context}; post_respond({{halt, Code}, ReqData, Context}) -> {{halt, Code}, ReqData, Context}; post_respond({JSON, ReqData, Context}) -> {true, wrq:set_resp_header( "content-type", "application/json", wrq:append_to_response_body(JSON, ReqData)), Context}. is_admin(T) -> intersects(T, [administrator]). is_policymaker(T) -> intersects(T, [administrator, policymaker]). is_monitor(T) -> intersects(T, [administrator, monitoring]). is_mgmt_user(T) -> intersects(T, [administrator, monitoring, policymaker, management]). intersects(A, B) -> lists:any(fun(I) -> lists:member(I, B) end, A). %% The distinction between list_visible_vhosts and list_login_vhosts %% is there to ensure that admins / monitors can always learn of the %% existence of all vhosts, and can always see their contribution to %% global stats. However, if an admin / monitor does not have any %% permissions for a vhost, it's probably less confusing to make that %% prevent them from seeing "into" it, than letting them see stuff %% that they then can't touch. list_visible_vhosts(User = #user{tags = Tags}) -> case is_monitor(Tags) of true -> rabbit_vhost:list(); false -> list_login_vhosts(User) end. list_login_vhosts(User) -> [V || V <- rabbit_vhost:list(), case catch rabbit_access_control:check_vhost_access(User, V) of ok -> true; _ -> false end]. %% Wow, base64:decode throws lots of weird errors. Catch and convert to one %% that will cause a bad_request. b64decode_or_throw(B64) -> try base64:decode(B64) catch error:_ -> throw({error, {not_base64, B64}}) end. no_range() -> {no_range, no_range, no_range}. %% Take floor on queries so we make sure we only return samples %% for which we've finished receiving events. Fixes the "drop at %% the end" problem. range(ReqData) -> {range("lengths", fun floor/2, ReqData), range("msg_rates", fun floor/2, ReqData), range("data_rates", fun floor/2, ReqData)}. %% ...but if we know only one event could have contributed towards %% what we are interested in, then let's take the ceiling instead and %% get slightly fresher data. %% %% Why does msg_rates still use floor/2? Because in the cases where we %% call this function (for connections and queues) the msg_rates are still %% aggregated even though the lengths and data rates aren't. range_ceil(ReqData) -> {range("lengths", fun ceil/2, ReqData), range("msg_rates", fun floor/2, ReqData), range("data_rates", fun ceil/2, ReqData)}. range(Prefix, Round, ReqData) -> Age0 = int(Prefix ++ "_age", ReqData), Incr0 = int(Prefix ++ "_incr", ReqData), if is_integer(Age0) andalso is_integer(Incr0) -> Age = Age0 * 1000, Incr = Incr0 * 1000, Now = rabbit_mgmt_format:timestamp_ms(erlang:now()), Last = Round(Now, Incr), #range{first = (Last - Age), last = Last, incr = Incr}; true -> no_range end. floor(TS, Interval) -> (TS div Interval) * Interval. ceil(TS, Interval) -> case floor(TS, Interval) of TS -> TS; Floor -> Floor + Interval end. int(Name, ReqData) -> case wrq:get_qs_value(Name, ReqData) of undefined -> undefined; Str -> case catch list_to_integer(Str) of {'EXIT', _} -> undefined; Integer -> Integer end end. rabbitmq-server-3.2.4/plugins-src/rabbitmq-management/src/rabbit_mgmt_wm_permissions_user.erl0000644000000000000000000000300412305126066031460 0ustar rootroot%% The contents of this file are subject to the Mozilla Public License %% Version 1.1 (the "License"); you may not use this file except in %% compliance with the License. You may obtain a copy of the License at %% http://www.mozilla.org/MPL/ %% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the %% License for the specific language governing rights and limitations %% under the License. %% %% The Original Code is RabbitMQ Management Plugin. %% %% The Initial Developer of the Original Code is GoPivotal, Inc. %% Copyright (c) 2010-2013 GoPivotal, Inc. All rights reserved. %% -module(rabbit_mgmt_wm_permissions_user). -export([init/1, to_json/2, content_types_provided/2, is_authorized/2]). -include("rabbit_mgmt.hrl"). -include_lib("webmachine/include/webmachine.hrl"). -include_lib("rabbit_common/include/rabbit.hrl"). %%-------------------------------------------------------------------- init(_Config) -> {ok, #context{}}. content_types_provided(ReqData, Context) -> {[{"application/json", to_json}], ReqData, Context}. to_json(ReqData, Context) -> User = rabbit_mgmt_util:id(user, ReqData), Perms = rabbit_auth_backend_internal:list_user_permissions(User), rabbit_mgmt_util:reply_list([[{user, User} | Rest] || Rest <- Perms], ["vhost", "user"], ReqData, Context). is_authorized(ReqData, Context) -> rabbit_mgmt_util:is_authorized_admin(ReqData, Context). rabbitmq-server-3.2.4/plugins-src/rabbitmq-management/src/rabbit_mgmt_wm_queue.erl0000644000000000000000000000547612305126066027212 0ustar rootroot%% The contents of this file are subject to the Mozilla Public License %% Version 1.1 (the "License"); you may not use this file except in %% compliance with the License. You may obtain a copy of the License at %% http://www.mozilla.org/MPL/ %% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the %% License for the specific language governing rights and limitations %% under the License. %% %% The Original Code is RabbitMQ Management Plugin. %% %% The Initial Developer of the Original Code is GoPivotal, Inc. %% Copyright (c) 2010-2013 GoPivotal, Inc. All rights reserved. %% -module(rabbit_mgmt_wm_queue). -export([init/1, resource_exists/2, to_json/2, content_types_provided/2, content_types_accepted/2, is_authorized/2, allowed_methods/2, accept_content/2, delete_resource/2, queue/1, queue/2]). -include("rabbit_mgmt.hrl"). -include_lib("webmachine/include/webmachine.hrl"). -include_lib("amqp_client/include/amqp_client.hrl"). %%-------------------------------------------------------------------- init(_Config) -> {ok, #context{}}. content_types_provided(ReqData, Context) -> {[{"application/json", to_json}], ReqData, Context}. content_types_accepted(ReqData, Context) -> {[{"application/json", accept_content}], ReqData, Context}. allowed_methods(ReqData, Context) -> {['HEAD', 'GET', 'PUT', 'DELETE'], ReqData, Context}. resource_exists(ReqData, Context) -> {case queue(ReqData) of not_found -> false; _ -> true end, ReqData, Context}. to_json(ReqData, Context) -> [Q] = rabbit_mgmt_db:augment_queues( [queue(ReqData)], rabbit_mgmt_util:range_ceil(ReqData), full), rabbit_mgmt_util:reply(rabbit_mgmt_format:strip_pids(Q), ReqData, Context). accept_content(ReqData, Context) -> rabbit_mgmt_util:http_to_amqp( 'queue.declare', ReqData, Context, [{fun rabbit_mgmt_util:parse_bool/1, [durable, auto_delete]}], [{queue, rabbit_mgmt_util:id(queue, ReqData)}]). delete_resource(ReqData, Context) -> rabbit_mgmt_util:amqp_request( rabbit_mgmt_util:vhost(ReqData), ReqData, Context, #'queue.delete'{ queue = rabbit_mgmt_util:id(queue, ReqData) }). is_authorized(ReqData, Context) -> rabbit_mgmt_util:is_authorized_vhost(ReqData, Context). %%-------------------------------------------------------------------- queue(ReqData) -> case rabbit_mgmt_util:vhost(ReqData) of not_found -> not_found; VHost -> queue(VHost, rabbit_mgmt_util:id(queue, ReqData)) end. queue(VHost, QName) -> Name = rabbit_misc:r(VHost, queue, QName), case rabbit_amqqueue:lookup(Name) of {ok, Q} -> rabbit_mgmt_format:queue(Q); {error, not_found} -> not_found end. rabbitmq-server-3.2.4/plugins-src/rabbitmq-management/src/rabbit_mgmt_wm_overview.erl0000644000000000000000000000717312305126066027730 0ustar rootroot%% The contents of this file are subject to the Mozilla Public License %% Version 1.1 (the "License"); you may not use this file except in %% compliance with the License. You may obtain a copy of the License at %% http://www.mozilla.org/MPL/ %% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the %% License for the specific language governing rights and limitations %% under the License. %% %% The Original Code is RabbitMQ Management Plugin. %% %% The Initial Developer of the Original Code is GoPivotal, Inc. %% Copyright (c) 2010-2013 GoPivotal, Inc. All rights reserved. %% -module(rabbit_mgmt_wm_overview). -export([init/1, to_json/2, content_types_provided/2, is_authorized/2]). -import(rabbit_misc, [pget/2, pget/3]). -include("rabbit_mgmt.hrl"). -include_lib("webmachine/include/webmachine.hrl"). -include_lib("rabbit_common/include/rabbit.hrl"). %%-------------------------------------------------------------------- init(_Config) -> {ok, #context{}}. content_types_provided(ReqData, Context) -> {[{"application/json", to_json}], ReqData, Context}. to_json(ReqData, Context = #context{user = User = #user{tags = Tags}}) -> {ok, StatsLevel} = application:get_env(rabbit, collect_statistics), %% NB: this duplicates what's in /nodes but we want a global idea %% of this. And /nodes is not accessible to non-monitor users. ExchangeTypes = rabbit_mgmt_external_stats:list_registry_plugins(exchange), Overview0 = [{management_version, version(rabbitmq_management)}, {statistics_level, StatsLevel}, {exchange_types, ExchangeTypes}, {rabbitmq_version, version(rabbit)}, {erlang_version, erl_version(otp_release)}, {erlang_full_version, erl_version(system_version)}], Range = rabbit_mgmt_util:range(ReqData), Overview = case rabbit_mgmt_util:is_monitor(Tags) of true -> Overview0 ++ [{K, {struct, V}} || {K, V} <- rabbit_mgmt_db:get_overview(Range)] ++ [{node, node()}, {statistics_db_node, stats_db_node()}, {listeners, listeners()}, {contexts, rabbit_web_dispatch_contexts()}]; _ -> Overview0 ++ [{K, {struct, V}} || {K, V} <- rabbit_mgmt_db:get_overview(User, Range)] end, rabbit_mgmt_util:reply(Overview, ReqData, Context). is_authorized(ReqData, Context) -> rabbit_mgmt_util:is_authorized(ReqData, Context). %%-------------------------------------------------------------------- stats_db_node() -> case global:whereis_name(rabbit_mgmt_db) of undefined -> not_running; Pid -> node(Pid) end. version(App) -> {ok, V} = application:get_key(App, vsn), list_to_binary(V). listeners() -> rabbit_mgmt_util:sort_list( [rabbit_mgmt_format:listener(L) || L <- rabbit_networking:active_listeners()], ["protocol", "port", "node"] ). %%-------------------------------------------------------------------- rabbit_web_dispatch_contexts() -> rabbit_mgmt_util:sort_list( lists:append( [rabbit_web_dispatch_contexts(N) || N <- rabbit_mgmt_wm_nodes:all_nodes()]), ["description", "port", "node"]). rabbit_web_dispatch_contexts(N) -> [[{node, pget(name, N)} | C] || C <- pget(contexts, N, [])]. erl_version(K) -> list_to_binary(string:strip(erlang:system_info(K), both, $\n)). rabbitmq-server-3.2.4/plugins-src/rabbitmq-management/src/rabbit_mgmt_app.erl0000644000000000000000000000777612305126066026150 0ustar rootroot%% The contents of this file are subject to the Mozilla Public License %% Version 1.1 (the "License"); you may not use this file except in %% compliance with the License. You may obtain a copy of the License at %% http://www.mozilla.org/MPL/ %% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the %% License for the specific language governing rights and limitations %% under the License. %% %% The Original Code is RabbitMQ Management Plugin. %% %% The Initial Developer of the Original Code is GoPivotal, Inc. %% Copyright (c) 2010-2013 GoPivotal, Inc. All rights reserved. %% -module(rabbit_mgmt_app). -behaviour(application). -export([start/2, stop/1]). -include("rabbit_mgmt.hrl"). -include_lib("amqp_client/include/amqp_client.hrl"). -define(CONTEXT, rabbit_mgmt). -define(CONTEXT_REDIRECT, rabbit_mgmt_redirect). -define(STATIC_PATH, "priv/www"). start(_Type, _StartArgs) -> {ok, Listener} = application:get_env(rabbitmq_management, listener), setup_wm_logging(), register_context(Listener), log_startup(Listener), rabbit_mgmt_sup_sup:start_link(). stop(_State) -> unregister_context(), ok. register_context(Listener) -> if_redirect( fun () -> rabbit_web_dispatch:register_port_redirect( ?CONTEXT_REDIRECT, [{port, 55672}, {ignore_in_use, true}], "", port(Listener)) end), rabbit_web_dispatch:register_context_handler( ?CONTEXT, Listener, "", make_loop(), "RabbitMQ Management"). unregister_context() -> if_redirect( fun () -> rabbit_web_dispatch:unregister_context(?CONTEXT_REDIRECT) end), rabbit_web_dispatch:unregister_context(?CONTEXT). if_redirect(Thunk) -> {ok, Redir} = application:get_env(rabbitmq_management, redirect_old_port), case Redir of true -> Thunk(); false -> ok end. make_loop() -> Dispatch = rabbit_mgmt_dispatcher:build_dispatcher(), WMLoop = rabbit_webmachine:makeloop(Dispatch), LocalPaths = [filename:join(module_path(M), ?STATIC_PATH) || M <- rabbit_mgmt_dispatcher:modules()], fun(Req) -> respond(Req, LocalPaths, WMLoop) end. module_path(Module) -> {file, Here} = code:is_loaded(Module), filename:dirname(filename:dirname(Here)). respond(Req, LocalPaths, WMLoop) -> Path = Req:get(path), Redirect = fun(L) -> {301, [{"Location", L}], ""} end, case Path of "/api/" ++ Rest when length(Rest) > 0 -> WMLoop(Req); "" -> Req:respond(Redirect("/")); "/mgmt/" -> Req:respond(Redirect("/")); "/mgmt" -> Req:respond(Redirect("/")); "/" ++ Stripped -> serve_file(Req, Stripped, LocalPaths, Redirect) end. serve_file(Req, Path, [LocalPath], _Redirect) -> Req:serve_file(Path, LocalPath); serve_file(Req, Path, [LocalPath | Others], Redirect) -> Path1 = filename:join([LocalPath, Path]), case filelib:is_regular(Path1) of true -> Req:serve_file(Path, LocalPath); false -> case filelib:is_regular(Path1 ++ "/index.html") of true -> index(Req, Path, LocalPath, Redirect); false -> serve_file(Req, Path, Others, Redirect) end end. index(Req, Path, LocalPath, Redirect) -> case lists:reverse(Path) of "" -> Req:serve_file("index.html", LocalPath); "/" ++ _ -> Req:serve_file(Path ++ "index.html", LocalPath); _ -> Req:respond(Redirect(Path ++ "/")) end. setup_wm_logging() -> rabbit_webmachine:setup(), {ok, LogDir} = application:get_env(rabbitmq_management, http_log_dir), case LogDir of none -> ok; _ -> webmachine_log:add_handler(webmachine_log_handler, [LogDir]) end. log_startup(Listener) -> rabbit_log:info("Management plugin started. Port: ~w~n", [port(Listener)]). port(Listener) -> proplists:get_value(port, Listener). rabbitmq-server-3.2.4/plugins-src/rabbitmq-management/src/rabbit_mgmt_wm_policy.erl0000644000000000000000000000622112305126066027352 0ustar rootroot%% The contents of this file are subject to the Mozilla Public License %% Version 1.1 (the "License"); you may not use this file except in %% compliance with the License. You may obtain a copy of the License at %% http://www.mozilla.org/MPL/ %% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the %% License for the specific language governing rights and limitations %% under the License. %% %% The Original Code is RabbitMQ Management Plugin. %% %% The Initial Developer of the Original Code is GoPivotal, Inc. %% Copyright (c) 2010-2013 GoPivotal, Inc. All rights reserved. %% -module(rabbit_mgmt_wm_policy). -export([init/1, resource_exists/2, to_json/2, content_types_provided/2, content_types_accepted/2, is_authorized/2, allowed_methods/2, accept_content/2, delete_resource/2]). -import(rabbit_misc, [pget/2]). -include("rabbit_mgmt.hrl"). -include_lib("webmachine/include/webmachine.hrl"). -include_lib("rabbit_common/include/rabbit.hrl"). %%-------------------------------------------------------------------- init(_Config) -> {ok, #context{}}. content_types_provided(ReqData, Context) -> {[{"application/json", to_json}], ReqData, Context}. content_types_accepted(ReqData, Context) -> {[{"application/json", accept_content}], ReqData, Context}. allowed_methods(ReqData, Context) -> {['HEAD', 'GET', 'PUT', 'DELETE'], ReqData, Context}. resource_exists(ReqData, Context) -> {case policy(ReqData) of not_found -> false; _ -> true end, ReqData, Context}. to_json(ReqData, Context) -> rabbit_mgmt_util:reply(policy(ReqData), ReqData, Context). accept_content(ReqData, Context) -> case rabbit_mgmt_util:vhost(ReqData) of not_found -> rabbit_mgmt_util:not_found(vhost_not_found, ReqData, Context); VHost -> rabbit_mgmt_util:with_decode( [pattern, definition], ReqData, Context, fun([Pattern, Definition], Body) -> case rabbit_policy:set( VHost, name(ReqData), Pattern, rabbit_misc:json_to_term(Definition), proplists:get_value(priority, Body), proplists:get_value('apply-to', Body)) of ok -> {true, ReqData, Context}; {error_string, Reason} -> rabbit_mgmt_util:bad_request( list_to_binary(Reason), ReqData, Context) end end) end. delete_resource(ReqData, Context) -> ok = rabbit_policy:delete( rabbit_mgmt_util:vhost(ReqData), name(ReqData)), {true, ReqData, Context}. is_authorized(ReqData, Context) -> rabbit_mgmt_util:is_authorized_policies(ReqData, Context). %%-------------------------------------------------------------------- policy(ReqData) -> rabbit_policy:lookup( rabbit_mgmt_util:vhost(ReqData), name(ReqData)). name(ReqData) -> rabbit_mgmt_util:id(name, ReqData). rabbitmq-server-3.2.4/plugins-src/rabbitmq-management/src/rabbit_mgmt_wm_queue_actions.erl0000644000000000000000000000464412305126066030726 0ustar rootroot%% The contents of this file are subject to the Mozilla Public License %% Version 1.1 (the "License"); you may not use this file except in %% compliance with the License. You may obtain a copy of the License at %% http://www.mozilla.org/MPL/ %% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the %% License for the specific language governing rights and limitations %% under the License. %% %% The Original Code is RabbitMQ Management Plugin. %% %% The Initial Developer of the Original Code is GoPivotal, Inc. %% Copyright (c) 2011-2012 GoPivotal, Inc. All rights reserved. %% -module(rabbit_mgmt_wm_queue_actions). -export([init/1, resource_exists/2, post_is_create/2, is_authorized/2, allowed_methods/2, process_post/2]). -include("rabbit_mgmt.hrl"). -include_lib("webmachine/include/webmachine.hrl"). -include_lib("amqp_client/include/amqp_client.hrl"). %%-------------------------------------------------------------------- init(_Config) -> {ok, #context{}}. allowed_methods(ReqData, Context) -> {['POST'], ReqData, Context}. resource_exists(ReqData, Context) -> {case rabbit_mgmt_wm_queue:queue(ReqData) of not_found -> false; _ -> true end, ReqData, Context}. post_is_create(ReqData, Context) -> {false, ReqData, Context}. process_post(ReqData, Context) -> rabbit_mgmt_util:post_respond(do_it(ReqData, Context)). do_it(ReqData, Context) -> VHost = rabbit_mgmt_util:vhost(ReqData), QName = rabbit_mgmt_util:id(queue, ReqData), rabbit_mgmt_util:with_decode( [action], ReqData, Context, fun([Action], _Body) -> rabbit_amqqueue:with( rabbit_misc:r(VHost, queue, QName), fun(Q) -> action(Action, Q, ReqData, Context) end) end). is_authorized(ReqData, Context) -> rabbit_mgmt_util:is_authorized_admin(ReqData, Context). %%-------------------------------------------------------------------- action(<<"sync">>, #amqqueue{pid = QPid}, ReqData, Context) -> spawn(fun() -> rabbit_amqqueue:sync_mirrors(QPid) end), {true, ReqData, Context}; action(<<"cancel_sync">>, #amqqueue{pid = QPid}, ReqData, Context) -> rabbit_amqqueue:cancel_sync_mirrors(QPid), {true, ReqData, Context}; action(Else, _Q, ReqData, Context) -> rabbit_mgmt_util:bad_request({unknown, Else}, ReqData, Context). rabbitmq-server-3.2.4/plugins-src/rabbitmq-management/src/rabbit_mgmt_wm_queue_get.erl0000644000000000000000000001150112305126066030033 0ustar rootroot%% The contents of this file are subject to the Mozilla Public License %% Version 1.1 (the "License"); you may not use this file except in %% compliance with the License. You may obtain a copy of the License at %% http://www.mozilla.org/MPL/ %% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the %% License for the specific language governing rights and limitations %% under the License. %% %% The Original Code is RabbitMQ Management Plugin. %% %% The Initial Developer of the Original Code is GoPivotal, Inc. %% Copyright (c) 2011-2013 GoPivotal, Inc. All rights reserved. %% -module(rabbit_mgmt_wm_queue_get). -export([init/1, resource_exists/2, post_is_create/2, is_authorized/2, allowed_methods/2, process_post/2]). -include("rabbit_mgmt.hrl"). -include_lib("webmachine/include/webmachine.hrl"). -include_lib("amqp_client/include/amqp_client.hrl"). %%-------------------------------------------------------------------- init(_Config) -> {ok, #context{}}. allowed_methods(ReqData, Context) -> {['POST'], ReqData, Context}. resource_exists(ReqData, Context) -> {case rabbit_mgmt_wm_queue:queue(ReqData) of not_found -> false; _ -> true end, ReqData, Context}. post_is_create(ReqData, Context) -> {false, ReqData, Context}. process_post(ReqData, Context) -> rabbit_mgmt_util:post_respond(do_it(ReqData, Context)). do_it(ReqData, Context) -> VHost = rabbit_mgmt_util:vhost(ReqData), Q = rabbit_mgmt_util:id(queue, ReqData), rabbit_mgmt_util:with_decode( [requeue, count, encoding], ReqData, Context, fun([RequeueBin, CountBin, EncBin], Body) -> rabbit_mgmt_util:with_channel( VHost, ReqData, Context, fun (Ch) -> NoAck = not rabbit_mgmt_util:parse_bool(RequeueBin), Count = rabbit_mgmt_util:parse_int(CountBin), Enc = case EncBin of <<"auto">> -> auto; <<"base64">> -> base64; _ -> throw({error, {bad_encoding, EncBin}}) end, Trunc = case proplists:get_value(truncate, Body) of undefined -> none; TruncBin -> rabbit_mgmt_util:parse_int( TruncBin) end, rabbit_mgmt_util:reply( basic_gets(Count, Ch, Q, NoAck, Enc, Trunc), ReqData, Context) end) end). basic_gets(0, _, _, _, _, _) -> []; basic_gets(Count, Ch, Q, NoAck, Enc, Trunc) -> case basic_get(Ch, Q, NoAck, Enc, Trunc) of none -> []; M -> [M | basic_gets(Count - 1, Ch, Q, NoAck, Enc, Trunc)] end. basic_get(Ch, Q, NoAck, Enc, Trunc) -> case amqp_channel:call(Ch, #'basic.get'{queue = Q, no_ack = NoAck}) of {#'basic.get_ok'{redelivered = Redelivered, exchange = Exchange, routing_key = RoutingKey, message_count = MessageCount}, #amqp_msg{props = Props, payload = Payload}} -> [{payload_bytes, size(Payload)}, {redelivered, Redelivered}, {exchange, Exchange}, {routing_key, RoutingKey}, {message_count, MessageCount}, {properties, rabbit_mgmt_format:basic_properties(Props)}] ++ payload_part(maybe_truncate(Payload, Trunc), Enc); #'basic.get_empty'{} -> none end. is_authorized(ReqData, Context) -> rabbit_mgmt_util:is_authorized_vhost(ReqData, Context). %%-------------------------------------------------------------------- maybe_truncate(Payload, none) -> Payload; maybe_truncate(Payload, Len) when size(Payload) < Len -> Payload; maybe_truncate(Payload, Len) -> <> = Payload, Start. payload_part(Payload, Enc) -> {PL, E} = case Enc of auto -> try %% TODO mochijson does this but is it safe? xmerl_ucs:from_utf8(Payload), {Payload, string} catch exit:{ucs, _} -> {base64:encode(Payload), base64} end; _ -> {base64:encode(Payload), base64} end, [{payload, PL}, {payload_encoding, E}]. rabbitmq-server-3.2.4/plugins-src/rabbitmq-management/src/rabbit_mgmt_wm_extensions.erl0000644000000000000000000000257712305126066030264 0ustar rootroot%% The contents of this file are subject to the Mozilla Public License %% Version 1.1 (the "License"); you may not use this file except in %% compliance with the License. You may obtain a copy of the License at %% http://www.mozilla.org/MPL/ %% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the %% License for the specific language governing rights and limitations %% under the License. %% %% The Original Code is RabbitMQ Management Plugin. %% %% The Initial Developer of the Original Code is GoPivotal, Inc. %% Copyright (c) 2011-2013 GoPivotal, Inc. All rights reserved. %% -module(rabbit_mgmt_wm_extensions). -export([init/1, to_json/2, content_types_provided/2, is_authorized/2]). -include("rabbit_mgmt.hrl"). -include_lib("webmachine/include/webmachine.hrl"). -include_lib("rabbit_common/include/rabbit.hrl"). %%-------------------------------------------------------------------- init(_Config) -> {ok, #context{}}. content_types_provided(ReqData, Context) -> {[{"application/json", to_json}], ReqData, Context}. to_json(ReqData, Context) -> Modules = rabbit_mgmt_dispatcher:modules(), rabbit_mgmt_util:reply( [Module:web_ui() || Module <- Modules], ReqData, Context). is_authorized(ReqData, Context) -> rabbit_mgmt_util:is_authorized(ReqData, Context). rabbitmq-server-3.2.4/plugins-src/rabbitmq-management/src/rabbit_mgmt_wm_exchange.erl0000644000000000000000000000562112305126066027640 0ustar rootroot%% The contents of this file are subject to the Mozilla Public License %% Version 1.1 (the "License"); you may not use this file except in %% compliance with the License. You may obtain a copy of the License at %% http://www.mozilla.org/MPL/ %% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the %% License for the specific language governing rights and limitations %% under the License. %% %% The Original Code is RabbitMQ Management Plugin. %% %% The Initial Developer of the Original Code is GoPivotal, Inc. %% Copyright (c) 2010-2013 GoPivotal, Inc. All rights reserved. %% -module(rabbit_mgmt_wm_exchange). -export([init/1, resource_exists/2, to_json/2, content_types_provided/2, content_types_accepted/2, is_authorized/2, allowed_methods/2, accept_content/2, delete_resource/2, exchange/1, exchange/2]). -include("rabbit_mgmt.hrl"). -include_lib("webmachine/include/webmachine.hrl"). -include_lib("amqp_client/include/amqp_client.hrl"). %%-------------------------------------------------------------------- init(_Config) -> {ok, #context{}}. content_types_provided(ReqData, Context) -> {[{"application/json", to_json}], ReqData, Context}. content_types_accepted(ReqData, Context) -> {[{"application/json", accept_content}], ReqData, Context}. allowed_methods(ReqData, Context) -> {['HEAD', 'GET', 'PUT', 'DELETE'], ReqData, Context}. resource_exists(ReqData, Context) -> {case exchange(ReqData) of not_found -> false; _ -> true end, ReqData, Context}. to_json(ReqData, Context) -> [X] = rabbit_mgmt_db:augment_exchanges( [exchange(ReqData)], rabbit_mgmt_util:range(ReqData), full), rabbit_mgmt_util:reply(X, ReqData, Context). accept_content(ReqData, Context) -> rabbit_mgmt_util:http_to_amqp( 'exchange.declare', ReqData, Context, [{fun rabbit_mgmt_util:parse_bool/1, [durable, auto_delete, internal]}], [{exchange, rabbit_mgmt_util:id(exchange, ReqData)}]). delete_resource(ReqData, Context) -> rabbit_mgmt_util:amqp_request( rabbit_mgmt_util:vhost(ReqData), ReqData, Context, #'exchange.delete'{ exchange = id(ReqData) }). is_authorized(ReqData, Context) -> rabbit_mgmt_util:is_authorized_vhost(ReqData, Context). %%-------------------------------------------------------------------- exchange(ReqData) -> case rabbit_mgmt_util:vhost(ReqData) of not_found -> not_found; VHost -> exchange(VHost, id(ReqData)) end. exchange(VHost, XName) -> Name = rabbit_misc:r(VHost, exchange, XName), case rabbit_exchange:lookup(Name) of {ok, X} -> rabbit_mgmt_format:exchange( rabbit_exchange:info(X)); {error, not_found} -> not_found end. id(ReqData) -> rabbit_mgmt_util:id(exchange, ReqData). rabbitmq-server-3.2.4/plugins-src/rabbitmq-management/src/rabbit_mgmt_wm_users.erl0000644000000000000000000000320012305126066027206 0ustar rootroot%% The contents of this file are subject to the Mozilla Public License %% Version 1.1 (the "License"); you may not use this file except in %% compliance with the License. You may obtain a copy of the License at %% http://www.mozilla.org/MPL/ %% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the %% License for the specific language governing rights and limitations %% under the License. %% %% The Original Code is RabbitMQ Management Plugin. %% %% The Initial Developer of the Original Code is GoPivotal, Inc. %% Copyright (c) 2010-2013 GoPivotal, Inc. All rights reserved. %% -module(rabbit_mgmt_wm_users). -export([init/1, to_json/2, content_types_provided/2, is_authorized/2]). -export([users/0]). -import(rabbit_misc, [pget/2]). -include("rabbit_mgmt.hrl"). -include_lib("webmachine/include/webmachine.hrl"). -include_lib("rabbit_common/include/rabbit.hrl"). %%-------------------------------------------------------------------- init(_Config) -> {ok, #context{}}. content_types_provided(ReqData, Context) -> {[{"application/json", to_json}], ReqData, Context}. to_json(ReqData, Context) -> rabbit_mgmt_util:reply_list(users(), ReqData, Context). is_authorized(ReqData, Context) -> rabbit_mgmt_util:is_authorized_admin(ReqData, Context). %%-------------------------------------------------------------------- users() -> [begin {ok, User} = rabbit_auth_backend_internal:lookup_user(pget(user, U)), rabbit_mgmt_format:internal_user(User) end || U <- rabbit_auth_backend_internal:list_users()]. rabbitmq-server-3.2.4/plugins-src/rabbitmq-management/src/rabbit_mgmt_wm_queues.erl0000644000000000000000000000377412305126066027374 0ustar rootroot%% The contents of this file are subject to the Mozilla Public License %% Version 1.1 (the "License"); you may not use this file except in %% compliance with the License. You may obtain a copy of the License at %% http://www.mozilla.org/MPL/ %% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the %% License for the specific language governing rights and limitations %% under the License. %% %% The Original Code is RabbitMQ Management Plugin. %% %% The Initial Developer of the Original Code is GoPivotal, Inc. %% Copyright (c) 2010-2013 GoPivotal, Inc. All rights reserved. %% -module(rabbit_mgmt_wm_queues). -export([init/1, to_json/2, content_types_provided/2, is_authorized/2, resource_exists/2, basic/1, augmented/2]). -include("rabbit_mgmt.hrl"). -include_lib("webmachine/include/webmachine.hrl"). -include_lib("rabbit_common/include/rabbit.hrl"). %%-------------------------------------------------------------------- init(_Config) -> {ok, #context{}}. content_types_provided(ReqData, Context) -> {[{"application/json", to_json}], ReqData, Context}. resource_exists(ReqData, Context) -> {case queues0(ReqData) of vhost_not_found -> false; _ -> true end, ReqData, Context}. to_json(ReqData, Context) -> rabbit_mgmt_util:reply_list(augmented(ReqData, Context), ReqData, Context). is_authorized(ReqData, Context) -> rabbit_mgmt_util:is_authorized_vhost(ReqData, Context). %%-------------------------------------------------------------------- augmented(ReqData, Context) -> rabbit_mgmt_format:strip_pids( rabbit_mgmt_db:augment_queues( rabbit_mgmt_util:filter_vhost(basic(ReqData), ReqData, Context), rabbit_mgmt_util:range_ceil(ReqData), basic)). basic(ReqData) -> [rabbit_mgmt_format:queue(Q) || Q <- queues0(ReqData)]. queues0(ReqData) -> rabbit_mgmt_util:all_or_one_vhost(ReqData, fun rabbit_amqqueue:list/1). rabbitmq-server-3.2.4/plugins-src/rabbitmq-management/src/rabbit_mgmt_wm_permissions_vhost.erl0000644000000000000000000000301312305126066031645 0ustar rootroot%% The contents of this file are subject to the Mozilla Public License %% Version 1.1 (the "License"); you may not use this file except in %% compliance with the License. You may obtain a copy of the License at %% http://www.mozilla.org/MPL/ %% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the %% License for the specific language governing rights and limitations %% under the License. %% %% The Original Code is RabbitMQ Management Plugin. %% %% The Initial Developer of the Original Code is GoPivotal, Inc. %% Copyright (c) 2010-2013 GoPivotal, Inc. All rights reserved. %% -module(rabbit_mgmt_wm_permissions_vhost). -export([init/1, to_json/2, content_types_provided/2, is_authorized/2]). -include("rabbit_mgmt.hrl"). -include_lib("webmachine/include/webmachine.hrl"). -include_lib("rabbit_common/include/rabbit.hrl"). %%-------------------------------------------------------------------- init(_Config) -> {ok, #context{}}. content_types_provided(ReqData, Context) -> {[{"application/json", to_json}], ReqData, Context}. to_json(ReqData, Context) -> VHost = rabbit_mgmt_util:id(vhost, ReqData), Perms = rabbit_auth_backend_internal:list_vhost_permissions(VHost), rabbit_mgmt_util:reply_list([[{vhost, VHost} | Rest] || Rest <- Perms], ["vhost", "user"], ReqData, Context). is_authorized(ReqData, Context) -> rabbit_mgmt_util:is_authorized_admin(ReqData, Context). rabbitmq-server-3.2.4/plugins-src/rabbitmq-management/src/rabbit_mgmt_wm_queue_purge.erl0000644000000000000000000000313212305126066030377 0ustar rootroot%% The contents of this file are subject to the Mozilla Public License %% Version 1.1 (the "License"); you may not use this file except in %% compliance with the License. You may obtain a copy of the License at %% http://www.mozilla.org/MPL/ %% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the %% License for the specific language governing rights and limitations %% under the License. %% %% The Original Code is RabbitMQ Management Plugin. %% %% The Initial Developer of the Original Code is GoPivotal, Inc. %% Copyright (c) 2010-2013 GoPivotal, Inc. All rights reserved. %% -module(rabbit_mgmt_wm_queue_purge). -export([init/1, resource_exists/2, is_authorized/2, allowed_methods/2, delete_resource/2]). -include("rabbit_mgmt.hrl"). -include_lib("webmachine/include/webmachine.hrl"). -include_lib("amqp_client/include/amqp_client.hrl"). %%-------------------------------------------------------------------- init(_Config) -> {ok, #context{}}. allowed_methods(ReqData, Context) -> {['DELETE'], ReqData, Context}. resource_exists(ReqData, Context) -> {case rabbit_mgmt_wm_queue:queue(ReqData) of not_found -> false; _ -> true end, ReqData, Context}. delete_resource(ReqData, Context) -> rabbit_mgmt_util:amqp_request( rabbit_mgmt_util:vhost(ReqData), ReqData, Context, #'queue.purge'{ queue = rabbit_mgmt_util:id(queue, ReqData) }). is_authorized(ReqData, Context) -> rabbit_mgmt_util:is_authorized_vhost(ReqData, Context). rabbitmq-server-3.2.4/plugins-src/rabbitmq-management/src/rabbit_mgmt_sup_sup.erl0000644000000000000000000000515712305126066027055 0ustar rootroot%% The contents of this file are subject to the Mozilla Public License %% Version 1.1 (the "License"); you may not use this file except in %% compliance with the License. You may obtain a copy of the License at %% http://www.mozilla.org/MPL/ %% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the %% License for the specific language governing rights and limitations %% under the License. %% %% The Original Code is RabbitMQ Management Console. %% %% The Initial Developer of the Original Code is GoPivotal, Inc. %% Copyright (c) 2011-2013 GoPivotal, Inc. All rights reserved. %% -module(rabbit_mgmt_sup_sup). %% We want there to be one management database in the cluster, with a %% globally registered name. So we use mirrored_supervisor for %% failover (in rabbit_mgmt_sup) and register a global name for the %% database. %% %% Unfortunately it's more complicated than using these things %% naively. The first problem is that on failover the mirrored %% supervisor might move the DB to a new node before the global name %% database notices and removes the old record. In that case starting %% the new database will fail. %% %% The second problem is that after a network partition things get %% worse. Since mirrored_supervisor uses Mnesia for global shared %% state, we have effectively two (or more) mirrored_supervisors. But %% the global name database does not do this, so at least one of them %% cannot start the management database; so the mirrored supervisor %% has to die. But what if the admin restarts the partition which %% contains the management DB? In that case we need to start a new %% management DB in the winning partition. %% %% Rather than try to get mirrored_supervisor to handle this %% post-partition state we go for a simpler approach: allow the whole %% mirrored_supervisor to die in the two edge cases above, and %% whenever we want to call into the mgmt DB we will start it up if it %% appears not to be there. See rabbit_mgmt_db:safe_call/3 for the %% code which restarts the DB if necessary. -behaviour(supervisor2). -export([start_link/0, start_child/0]). -export([init/1]). -include_lib("rabbit_common/include/rabbit.hrl"). start_link() -> supervisor2:start_link({local, ?MODULE}, ?MODULE, []). start_child() -> supervisor2:start_child( ?MODULE, sup()). %%---------------------------------------------------------------------------- init([]) -> {ok, {{one_for_one, 0, 1}, [sup()]}}. sup() -> {rabbit_mgmt_sup, {rabbit_mgmt_sup, start_link, []}, temporary, ?MAX_WAIT, supervisor, [rabbit_mgmt_sup]}. rabbitmq-server-3.2.4/plugins-src/rabbitmq-management/src/rabbitmq_management.app.src0000644000000000000000000000133212305126066027560 0ustar rootroot{application, rabbitmq_management, [{description, "RabbitMQ Management Console"}, {vsn, "%%VSN%%"}, {modules, []}, {registered, []}, {mod, {rabbit_mgmt_app, []}}, {env, [{listener, [{port, 15672}]}, {redirect_old_port, true}, {http_log_dir, none}, {load_definitions, none}, {sample_retention_policies, %% List of {MaxAgeSecs, IfTimestampDivisibleBySecs} [{global, [{605, 5}, {3660, 60}, {29400, 600}, {86400, 1800}]}, {basic, [{605, 5}, {3600, 60}]}, {detailed, [{10, 5}]}]} ]}, {applications, [kernel, stdlib, rabbit, xmerl, rabbitmq_web_dispatch, amqp_client, rabbitmq_management_agent]}]}. rabbitmq-server-3.2.4/plugins-src/rabbitmq-management/src/rabbit_mgmt_wm_definitions.erl0000644000000000000000000002477012305126066030377 0ustar rootroot%% The contents of this file are subject to the Mozilla Public License %% Version 1.1 (the "License"); you may not use this file except in %% compliance with the License. You may obtain a copy of the License at %% http://www.mozilla.org/MPL/ %% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the %% License for the specific language governing rights and limitations %% under the License. %% %% The Original Code is RabbitMQ Management Plugin. %% %% The Initial Developer of the Original Code is GoPivotal, Inc. %% Copyright (c) 2010-2013 GoPivotal, Inc. All rights reserved. %% -module(rabbit_mgmt_wm_definitions). -export([init/1, to_json/2, content_types_provided/2, is_authorized/2]). -export([content_types_accepted/2, allowed_methods/2, accept_json/2]). -export([post_is_create/2, create_path/2, accept_multipart/2]). -export([apply_defs/3]). -import(rabbit_misc, [pget/2, pget/3]). -include("rabbit_mgmt.hrl"). -include_lib("webmachine/include/webmachine.hrl"). -include_lib("amqp_client/include/amqp_client.hrl"). %%-------------------------------------------------------------------- init(_Config) -> {ok, #context{}}. content_types_provided(ReqData, Context) -> {[{"application/json", to_json}], ReqData, Context}. content_types_accepted(ReqData, Context) -> {[{"application/json", accept_json}, {"multipart/form-data", accept_multipart}], ReqData, Context}. allowed_methods(ReqData, Context) -> {['HEAD', 'GET', 'POST'], ReqData, Context}. post_is_create(ReqData, Context) -> {true, ReqData, Context}. create_path(ReqData, Context) -> {"dummy", ReqData, Context}. to_json(ReqData, Context) -> Xs = [X || X <- rabbit_mgmt_wm_exchanges:basic(ReqData), export_exchange(X)], Qs = [Q || Q <- rabbit_mgmt_wm_queues:basic(ReqData), export_queue(Q)], QNames = [{pget(name, Q), pget(vhost, Q)} || Q <- Qs], Bs = [B || B <- rabbit_mgmt_wm_bindings:basic(ReqData), export_binding(B, QNames)], {ok, Vsn} = application:get_key(rabbit, vsn), rabbit_mgmt_util:reply( [{rabbit_version, list_to_binary(Vsn)}] ++ filter( [{users, rabbit_mgmt_wm_users:users()}, {vhosts, rabbit_mgmt_wm_vhosts:basic()}, {permissions, rabbit_mgmt_wm_permissions:permissions()}, {parameters, rabbit_mgmt_wm_parameters:basic(ReqData)}, {policies, rabbit_mgmt_wm_policies:basic(ReqData)}, {queues, Qs}, {exchanges, Xs}, {bindings, Bs}]), case wrq:get_qs_value("download", ReqData) of undefined -> ReqData; Filename -> wrq:set_resp_header( "Content-Disposition", "attachment; filename=" ++ mochiweb_util:unquote(Filename), ReqData) end, Context). accept_json(ReqData, Context) -> accept(wrq:req_body(ReqData), ReqData, Context). accept_multipart(ReqData, Context) -> Parts = webmachine_multipart:get_all_parts( wrq:req_body(ReqData), webmachine_multipart:find_boundary(ReqData)), Redirect = get_part("redirect", Parts), Json = get_part("file", Parts), Resp = {Res, _, _} = accept(Json, ReqData, Context), case Res of true -> ReqData1 = case Redirect of unknown -> ReqData; _ -> rabbit_mgmt_util:redirect(Redirect, ReqData) end, {true, ReqData1, Context}; _ -> Resp end. is_authorized(ReqData, Context) -> case wrq:get_qs_value("auth", ReqData) of undefined -> rabbit_mgmt_util:is_authorized_admin(ReqData, Context); Auth -> is_authorized_qs(ReqData, Context, Auth) end. %% Support for the web UI - it can't add a normal "authorization" %% header for a file download. is_authorized_qs(ReqData, Context, Auth) -> case rabbit_web_dispatch_util:parse_auth_header("Basic " ++ Auth) of [Username, Password] -> rabbit_mgmt_util:is_authorized_admin( ReqData, Context, Username, Password); _ -> {?AUTH_REALM, ReqData, Context} end. %%-------------------------------------------------------------------- accept(Body, ReqData, Context) -> apply_defs(Body, fun() -> {true, ReqData, Context} end, fun(E) -> rabbit_mgmt_util:bad_request(E, ReqData, Context) end). apply_defs(Body, SuccessFun, ErrorFun) -> case rabbit_mgmt_util:decode([], Body) of {error, E} -> ErrorFun(E); {ok, _, All} -> try for_all(users, All, fun add_user/1), for_all(vhosts, All, fun add_vhost/1), for_all(permissions, All, fun add_permission/1), for_all(parameters, All, fun add_parameter/1), for_all(policies, All, fun add_policy/1), for_all(queues, All, fun add_queue/1), for_all(exchanges, All, fun add_exchange/1), for_all(bindings, All, fun add_binding/1), SuccessFun() catch {error, E} -> ErrorFun(E); exit:E -> ErrorFun(E) end end. get_part(Name, Parts) -> %% TODO any reason not to use lists:keyfind instead? Filtered = [Value || {N, _Meta, Value} <- Parts, N == Name], case Filtered of [] -> unknown; [F] -> F end. export_queue(Queue) -> pget(owner_pid, Queue) == none. export_binding(Binding, Qs) -> Src = pget(source, Binding), Dest = pget(destination, Binding), DestType = pget(destination_type, Binding), VHost = pget(vhost, Binding), Src =/= <<"">> andalso ( (DestType =:= queue andalso lists:member({Dest, VHost}, Qs)) orelse (DestType =:= exchange andalso Dest =/= <<"">>) ). export_exchange(Exchange) -> export_name(pget(name, Exchange)). export_name(<<>>) -> false; export_name(<<"amq.", _/binary>>) -> false; export_name(_Name) -> true. %%-------------------------------------------------------------------- rw_state() -> [{users, [name, password_hash, tags]}, {vhosts, [name]}, {permissions, [user, vhost, configure, write, read]}, {parameters, [vhost, component, name, value]}, {policies, [vhost, name, pattern, definition, priority, 'apply-to']}, {queues, [name, vhost, durable, auto_delete, arguments]}, {exchanges, [name, vhost, type, durable, auto_delete, internal, arguments]}, {bindings, [source, vhost, destination, destination_type, routing_key, arguments]}]. filter(Items) -> [filter_items(N, V, proplists:get_value(N, rw_state())) || {N, V} <- Items]. filter_items(Name, List, Allowed) -> {Name, [filter_item(I, Allowed) || I <- List]}. filter_item(Item, Allowed) -> [{K, Fact} || {K, Fact} <- Item, lists:member(K, Allowed)]. %%-------------------------------------------------------------------- for_all(Name, All, Fun) -> case pget(Name, All) of undefined -> ok; List -> [Fun([{atomise_name(K), V} || {K, V} <- I]) || {struct, I} <- List] end. atomise_name(N) -> list_to_atom(binary_to_list(N)). %%-------------------------------------------------------------------- add_parameter(Param) -> VHost = pget(vhost, Param), Comp = pget(component, Param), Key = pget(name, Param), case rabbit_runtime_parameters:set( VHost, Comp, Key, rabbit_misc:json_to_term(pget(value, Param))) of ok -> ok; {error_string, E} -> S = rabbit_misc:format(" (~s/~s/~s)", [VHost, Comp, Key]), exit(list_to_binary(E ++ S)) end. add_policy(Param) -> VHost = pget(vhost, Param), Key = pget(name, Param), case rabbit_policy:set( VHost, Key, pget(pattern, Param), rabbit_misc:json_to_term(pget(definition, Param)), pget(priority, Param), pget('apply-to', Param, <<"all">>)) of ok -> ok; {error_string, E} -> S = rabbit_misc:format(" (~s/~s)", [VHost, Key]), exit(list_to_binary(E ++ S)) end. add_user(User) -> rabbit_mgmt_wm_user:put_user(User). add_vhost(VHost) -> VHostName = pget(name, VHost), VHostTrace = pget(tracing, VHost), rabbit_mgmt_wm_vhost:put_vhost(VHostName, VHostTrace). add_permission(Permission) -> rabbit_auth_backend_internal:set_permissions(pget(user, Permission), pget(vhost, Permission), pget(configure, Permission), pget(write, Permission), pget(read, Permission)). add_queue(Queue) -> rabbit_amqqueue:declare(r(queue, Queue), pget(durable, Queue), pget(auto_delete, Queue), rabbit_mgmt_util:args(pget(arguments, Queue)), none). add_exchange(Exchange) -> Internal = case pget(internal, Exchange) of undefined -> false; %% =< 2.2.0 I -> I end, rabbit_exchange:declare(r(exchange, Exchange), rabbit_exchange:check_type(pget(type, Exchange)), pget(durable, Exchange), pget(auto_delete, Exchange), Internal, rabbit_mgmt_util:args(pget(arguments, Exchange))). add_binding(Binding) -> DestType = list_to_atom(binary_to_list(pget(destination_type, Binding))), rabbit_binding:add( #binding{source = r(exchange, source, Binding), destination = r(DestType, destination, Binding), key = pget(routing_key, Binding), args = rabbit_mgmt_util:args(pget(arguments, Binding))}). r(Type, Props) -> r(Type, name, Props). r(Type, Name, Props) -> rabbit_misc:r(pget(vhost, Props), Type, pget(Name, Props)). rabbitmq-server-3.2.4/plugins-src/rabbitmq-management/src/rabbit_mgmt_sup.erl0000644000000000000000000000223612305126066026161 0ustar rootroot%% The contents of this file are subject to the Mozilla Public License %% Version 1.1 (the "License"); you may not use this file except in %% compliance with the License. You may obtain a copy of the License at %% http://www.mozilla.org/MPL/ %% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the %% License for the specific language governing rights and limitations %% under the License. %% %% The Original Code is RabbitMQ Management Console. %% %% The Initial Developer of the Original Code is GoPivotal, Inc. %% Copyright (c) 2011-2013 GoPivotal, Inc. All rights reserved. %% -module(rabbit_mgmt_sup). -behaviour(mirrored_supervisor). -export([init/1]). -export([start_link/0]). -include_lib("rabbit_common/include/rabbit.hrl"). init([]) -> DB = {rabbit_mgmt_db, {rabbit_mgmt_db, start_link, []}, permanent, ?MAX_WAIT, worker, [rabbit_mgmt_db]}, {ok, {{one_for_one, 10, 10}, [DB]}}. start_link() -> mirrored_supervisor:start_link( {local, ?MODULE}, ?MODULE, fun rabbit_misc:execute_mnesia_transaction/1, ?MODULE, []). rabbitmq-server-3.2.4/plugins-src/rabbitmq-management/src/rabbit_mgmt_wm_exchange_publish.erl0000644000000000000000000001027512305126066031367 0ustar rootroot%% The contents of this file are subject to the Mozilla Public License %% Version 1.1 (the "License"); you may not use this file except in %% compliance with the License. You may obtain a copy of the License at %% http://www.mozilla.org/MPL/ %% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the %% License for the specific language governing rights and limitations %% under the License. %% %% The Original Code is RabbitMQ Management Plugin. %% %% The Initial Developer of the Original Code is GoPivotal, Inc. %% Copyright (c) 2011-2013 GoPivotal, Inc. All rights reserved. %% -module(rabbit_mgmt_wm_exchange_publish). -export([init/1, resource_exists/2, post_is_create/2, is_authorized/2, allowed_methods/2, process_post/2]). -include("rabbit_mgmt.hrl"). -include_lib("webmachine/include/webmachine.hrl"). -include_lib("amqp_client/include/amqp_client.hrl"). %%-------------------------------------------------------------------- init(_Config) -> {ok, #context{}}. allowed_methods(ReqData, Context) -> {['POST'], ReqData, Context}. resource_exists(ReqData, Context) -> {case rabbit_mgmt_wm_exchange:exchange(ReqData) of not_found -> false; _ -> true end, ReqData, Context}. post_is_create(ReqData, Context) -> {false, ReqData, Context}. process_post(ReqData, Context) -> rabbit_mgmt_util:post_respond(do_it(ReqData, Context)). do_it(ReqData, Context) -> VHost = rabbit_mgmt_util:vhost(ReqData), X = rabbit_mgmt_util:id(exchange, ReqData), rabbit_mgmt_util:with_decode( [routing_key, properties, payload, payload_encoding], ReqData, Context, fun ([RoutingKey, Props0, Payload0, Enc], _) when is_binary(Payload0) -> rabbit_mgmt_util:with_channel( VHost, ReqData, Context, fun (Ch) -> MRef = erlang:monitor(process, Ch), amqp_channel:register_confirm_handler(Ch, self()), amqp_channel:register_return_handler(Ch, self()), amqp_channel:call(Ch, #'confirm.select'{}), Props = rabbit_mgmt_format:to_basic_properties(Props0), Payload = decode(Payload0, Enc), amqp_channel:cast(Ch, #'basic.publish'{ exchange = X, routing_key = RoutingKey, mandatory = true}, #amqp_msg{props = Props, payload = Payload}), receive {#'basic.return'{}, _} -> receive #'basic.ack'{} -> ok end, good(MRef, false, ReqData, Context); #'basic.ack'{} -> good(MRef, true, ReqData, Context); {'DOWN', _, _, _, Err} -> bad(Err, ReqData, Context) end end); ([_RoutingKey, _Props, _Payload, _Enc], _) -> throw({error, payload_not_string}) end). good(MRef, Routed, ReqData, Context) -> erlang:demonitor(MRef), rabbit_mgmt_util:reply([{routed, Routed}], ReqData, Context). bad({shutdown, {connection_closing, {server_initiated_close, Code, Reason}}}, ReqData, Context) -> rabbit_mgmt_util:bad_request_exception(Code, Reason, ReqData, Context); bad({shutdown, {server_initiated_close, Code, Reason}}, ReqData, Context) -> rabbit_mgmt_util:bad_request_exception(Code, Reason, ReqData, Context). is_authorized(ReqData, Context) -> rabbit_mgmt_util:is_authorized_vhost(ReqData, Context). %%-------------------------------------------------------------------- decode(Payload, <<"string">>) -> Payload; decode(Payload, <<"base64">>) -> rabbit_mgmt_util:b64decode_or_throw(Payload); decode(_Payload, Enc) -> throw({error, {unsupported_encoding, Enc}}). rabbitmq-server-3.2.4/plugins-src/rabbitmq-management/src/rabbit_mgmt_wm_binding.erl0000644000000000000000000001224212305126066027465 0ustar rootroot%% The contents of this file are subject to the Mozilla Public License %% Version 1.1 (the "License"); you may not use this file except in %% compliance with the License. You may obtain a copy of the License at %% http://www.mozilla.org/MPL/ %% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the %% License for the specific language governing rights and limitations %% under the License. %% %% The Original Code is RabbitMQ Management Plugin. %% %% The Initial Developer of the Original Code is GoPivotal, Inc. %% Copyright (c) 2010-2013 GoPivotal, Inc. All rights reserved. %% -module(rabbit_mgmt_wm_binding). -export([init/1, resource_exists/2, to_json/2, content_types_provided/2, content_types_accepted/2, is_authorized/2, allowed_methods/2, delete_resource/2, args_hash/1]). -include("rabbit_mgmt.hrl"). -include_lib("webmachine/include/webmachine.hrl"). -include_lib("amqp_client/include/amqp_client.hrl"). %%-------------------------------------------------------------------- init(_Config) -> {ok, #context{}}. content_types_provided(ReqData, Context) -> {[{"application/json", to_json}], ReqData, Context}. content_types_accepted(ReqData, Context) -> {[{"application/json", accept_content}], ReqData, Context}. allowed_methods(ReqData, Context) -> {['HEAD', 'GET', 'DELETE'], ReqData, Context}. resource_exists(ReqData, Context) -> Binding = binding(ReqData), {case Binding of not_found -> false; {bad_request, _} -> false; _ -> case rabbit_binding:exists(Binding) of true -> true; _ -> false end end, ReqData, Context}. to_json(ReqData, Context) -> with_binding(ReqData, Context, fun(Binding) -> rabbit_mgmt_util:reply( rabbit_mgmt_format:binding(Binding), ReqData, Context) end). delete_resource(ReqData, Context) -> MethodName = case rabbit_mgmt_util:destination_type(ReqData) of exchange -> 'exchange.unbind'; queue -> 'queue.unbind' end, sync_resource(MethodName, ReqData, Context). is_authorized(ReqData, Context) -> rabbit_mgmt_util:is_authorized_vhost(ReqData, Context). %%-------------------------------------------------------------------- binding(ReqData) -> case rabbit_mgmt_util:vhost(ReqData) of not_found -> not_found; VHost -> Source = rabbit_mgmt_util:id(source, ReqData), Dest = rabbit_mgmt_util:id(destination, ReqData), DestType = rabbit_mgmt_util:destination_type(ReqData), Props = rabbit_mgmt_util:id(props, ReqData), SName = rabbit_misc:r(VHost, exchange, Source), DName = rabbit_misc:r(VHost, DestType, Dest), case unpack(SName, DName, Props) of {bad_request, Str} -> {bad_request, Str}; {Key, Args} -> #binding{ source = SName, destination = DName, key = Key, args = Args } end end. unpack(Src, Dst, Props) -> case rabbit_mgmt_format:tokenise(binary_to_list(Props)) of ["~"] -> {<<>>, []}; [Key] -> {unquote(Key), []}; ["~", ArgsEnc] -> lookup(<<>>, ArgsEnc, Src, Dst); [Key, ArgsEnc] -> lookup(unquote(Key), ArgsEnc, Src, Dst); _ -> {bad_request, {too_many_tokens, Props}} end. lookup(RoutingKey, ArgsEnc, Src, Dst) -> lookup(RoutingKey, unquote(ArgsEnc), rabbit_binding:list_for_source_and_destination(Src, Dst)). lookup(_RoutingKey, _Hash, []) -> {bad_request, "binding not found"}; lookup(RoutingKey, Hash, [#binding{args = Args} | Rest]) -> case args_hash(Args) =:= Hash of true -> {RoutingKey, Args}; false -> lookup(RoutingKey, Hash, Rest) end. args_hash(Args) -> list_to_binary(rabbit_misc:base64url(erlang:md5(term_to_binary(Args)))). unquote(Name) -> list_to_binary(mochiweb_util:unquote(Name)). with_binding(ReqData, Context, Fun) -> case binding(ReqData) of {bad_request, Reason} -> rabbit_mgmt_util:bad_request(Reason, ReqData, Context); Binding -> Fun(Binding) end. sync_resource(MethodName, ReqData, Context) -> with_binding( ReqData, Context, fun(Binding) -> Props0 = rabbit_mgmt_format:binding(Binding), Props = Props0 ++ [{exchange, proplists:get_value(source, Props0)}, {queue, proplists:get_value(destination, Props0)}], rabbit_mgmt_util:amqp_request( rabbit_mgmt_util:vhost(ReqData), ReqData, Context, rabbit_mgmt_util:props_to_method(MethodName, Props)) end). rabbitmq-server-3.2.4/plugins-src/rabbitmq-management/src/rabbit_mgmt_stats.erl0000644000000000000000000002074512305126066026515 0ustar rootroot%% The contents of this file are subject to the Mozilla Public License %% Version 1.1 (the "License"); you may not use this file except in %% compliance with the License. You may obtain a copy of the License at %% http://www.mozilla.org/MPL/ %% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the %% License for the specific language governing rights and limitations %% under the License. %% %% The Original Code is RabbitMQ Management Plugin. %% %% The Initial Developer of the Original Code is GoPivotal, Inc. %% Copyright (c) 2010-2012 GoPivotal, Inc. All rights reserved. %% -module(rabbit_mgmt_stats). -include("rabbit_mgmt.hrl"). -export([blank/0, is_blank/1, record/3, format/3, sum/1, gc/2]). -import(rabbit_misc, [pget/2]). %%---------------------------------------------------------------------------- blank() -> #stats{diffs = gb_trees:empty(), base = 0}. is_blank(#stats{diffs = Diffs, base = 0}) -> gb_trees:is_empty(Diffs); is_blank(#stats{}) -> false. %%---------------------------------------------------------------------------- %% Event-time %%---------------------------------------------------------------------------- record(TS, Diff, Stats = #stats{diffs = Diffs}) -> Diffs2 = case gb_trees:lookup(TS, Diffs) of {value, Total} -> gb_trees:update(TS, Diff + Total, Diffs); none -> gb_trees:insert(TS, Diff, Diffs) end, Stats#stats{diffs = Diffs2}. %%---------------------------------------------------------------------------- %% Query-time %%---------------------------------------------------------------------------- format(no_range, #stats{diffs = Diffs, base = Base}, Interval) -> Now = rabbit_mgmt_format:timestamp_ms(erlang:now()), RangePoint = ((Now div Interval) * Interval) - Interval, Count = sum_entire_tree(gb_trees:iterator(Diffs), Base), {[{rate, format_rate( Diffs, RangePoint, Interval, Interval)}], Count}; format(Range, #stats{diffs = Diffs, base = Base}, Interval) -> RangePoint = Range#range.last - Interval, {Samples, Count} = extract_samples( Range, Base, gb_trees:iterator(Diffs), []), Part1 = [{rate, format_rate( Diffs, RangePoint, Range#range.incr, Interval)}, {samples, Samples}], Length = length(Samples), Part2 = case Length > 1 of true -> [{sample, S2}, {timestamp, T2}] = hd(Samples), [{sample, S1}, {timestamp, T1}] = lists:last(Samples), Total = lists:sum([pget(sample, I) || I <- Samples]), [{avg_rate, (S2 - S1) * 1000 / (T2 - T1)}, {avg, Total / Length}]; false -> [] end, {Part1 ++ Part2, Count}. format_rate(Diffs, RangePoint, Incr, Interval) -> case nth_largest(Diffs, 2) of false -> 0.0; {TS, S} -> case TS - RangePoint of %% [0] D when D =< Incr andalso D >= 0 -> S * 1000 / Interval; _ -> 0.0 end end. %% [0] Only display the rate if it's live - i.e. ((the end of the %% range) - interval) corresponds to the second to last data point we %% have. If the end of the range is earlier we have gone silent, if %% it's later we have been asked for a range back in time (in which %% case showing the correct instantaneous rate would be quite a faff, %% and probably unwanted). Why the second to last? Because data is %% still arriving for the last... nth_largest(Tree, N) -> case gb_trees:is_empty(Tree) of true -> false; false when N == 1 -> gb_trees:largest(Tree); false -> {_, _, Tree2} = gb_trees:take_largest(Tree), nth_largest(Tree2, N - 1) end. sum_entire_tree(Iter, Acc) -> case gb_trees:next(Iter) of none -> Acc; {_TS, S, Iter2} -> sum_entire_tree(Iter2, Acc + S) end. %% What we want to do here is: given the #range{}, provide a set of %% samples such that we definitely provide a set of samples which %% covers the exact range requested, despite the fact that we might %% not have it. We need to spin up over the entire range of the %% samples we *do* have since they are diff-based (and we convert to %% absolute values here). extract_samples(Range = #range{first = Next}, Base, It, Samples) -> case gb_trees:next(It) of {TS, S, It2} -> extract_samples1(Range, Base, TS, S, It2, Samples); none -> extract_samples1(Range, Base, Next, 0, It, Samples) end. extract_samples1(Range = #range{first = Next, last = Last, incr = Incr}, Base, TS, S, It, Samples) -> if %% We've gone over the range. Terminate. Next > Last -> {Samples, Base}; %% We've hit bang on a sample. Record it and move to the next. Next =:= TS -> extract_samples(Range#range{first = Next + Incr}, Base + S, It, append(Base + S, Next, Samples)); %% We haven't yet hit the beginning of our range. Next > TS -> extract_samples(Range, Base + S, It, Samples); %% We have a valid sample, but we haven't used it up %% yet. Append it and loop around. Next < TS -> extract_samples1(Range#range{first = Next + Incr}, Base, TS, S, It, append(Base, Next, Samples)) end. append(S, TS, Samples) -> [[{sample, S}, {timestamp, TS}] | Samples]. sum([]) -> blank(); sum([Stats | StatsN]) -> lists:foldl( fun (#stats{diffs = D1, base = B1}, #stats{diffs = D2, base = B2}) -> #stats{diffs = add_trees(D1, gb_trees:iterator(D2)), base = B1 + B2} end, Stats, StatsN). add_trees(Tree, It) -> case gb_trees:next(It) of none -> Tree; {K, V, It2} -> add_trees( case gb_trees:lookup(K, Tree) of {value, V2} -> gb_trees:update(K, V + V2, Tree); none -> gb_trees:insert(K, V, Tree) end, It2) end. %%---------------------------------------------------------------------------- %% Event-GCing %%---------------------------------------------------------------------------- gc(Cutoff, #stats{diffs = Diffs, base = Base}) -> List = lists:reverse(gb_trees:to_list(Diffs)), gc(Cutoff, List, [], Base). %% Go through the list, amalgamating all too-old samples with the next %% newest keepable one [0] (we move samples forward in time since the %% semantics of a sample is "we had this many x by this time"). If the %% sample is too old, but would not be too old if moved to a rounder %% timestamp which does not exist then invent one and move it there %% [1]. But if it's just outright too old, move it to the base [2]. gc(_Cutoff, [], Keep, Base) -> #stats{diffs = gb_trees:from_orddict(Keep), base = Base}; gc(Cutoff, [H = {TS, S} | T], Keep, Base) -> {NewKeep, NewBase} = case keep(Cutoff, TS) of keep -> {[H | Keep], Base}; drop -> {Keep, S + Base}; %% [2] {move, D} when Keep =:= [] -> {[{TS + D, S}], Base}; %% [1] {move, _} -> [{KTS, KS} | KT] = Keep, {[{KTS, KS + S} | KT], Base} %% [0] end, gc(Cutoff, T, NewKeep, NewBase). keep({Policy, Now}, TS) -> lists:foldl(fun ({AgeSec, DivisorSec}, Action) -> prefer_action( Action, case (Now - TS) =< (AgeSec * 1000) of true -> DivisorMillis = DivisorSec * 1000, case TS rem DivisorMillis of 0 -> keep; Rem -> {move, DivisorMillis - Rem} end; false -> drop end) end, drop, Policy). prefer_action(keep, _) -> keep; prefer_action(_, keep) -> keep; prefer_action({move, A}, {move, B}) -> {move, lists:min([A, B])}; prefer_action({move, A}, drop) -> {move, A}; prefer_action(drop, {move, A}) -> {move, A}; prefer_action(drop, drop) -> drop. rabbitmq-server-3.2.4/plugins-src/rabbitmq-management/src/rabbit_mgmt_wm_node.erl0000644000000000000000000000431012305126066026775 0ustar rootroot%% The contents of this file are subject to the Mozilla Public License %% Version 1.1 (the "License"); you may not use this file except in %% compliance with the License. You may obtain a copy of the License at %% http://www.mozilla.org/MPL/ %% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the %% License for the specific language governing rights and limitations %% under the License. %% %% The Original Code is RabbitMQ Management Console. %% %% The Initial Developer of the Original Code is GoPivotal, Inc. %% Copyright (c) 2010-2013 GoPivotal, Inc. All rights reserved. %% -module(rabbit_mgmt_wm_node). -export([init/1, to_json/2, content_types_provided/2, is_authorized/2]). -export([resource_exists/2]). -include("rabbit_mgmt.hrl"). -include_lib("webmachine/include/webmachine.hrl"). -include_lib("rabbit_common/include/rabbit.hrl"). %%-------------------------------------------------------------------- init(_Config) -> {ok, #context{}}. content_types_provided(ReqData, Context) -> {[{"application/json", to_json}], ReqData, Context}. resource_exists(ReqData, Context) -> {case node0(ReqData) of not_found -> false; _ -> true end, ReqData, Context}. to_json(ReqData, Context) -> rabbit_mgmt_util:reply(node0(ReqData), ReqData, Context). is_authorized(ReqData, Context) -> rabbit_mgmt_util:is_authorized_monitor(ReqData, Context). %%-------------------------------------------------------------------- node0(ReqData) -> Name = list_to_atom(binary_to_list(rabbit_mgmt_util:id(node, ReqData))), case [N || N <- rabbit_mgmt_wm_nodes:all_nodes(), proplists:get_value(name, N) == Name] of [] -> not_found; [Node] -> augment(ReqData, Name, Node) end. augment(ReqData, Name, Node) -> case wrq:get_qs_value("memory", ReqData) of "true" -> Mem = case rpc:call(Name, rabbit_vm, memory, [], infinity) of {badrpc, _} -> not_available; Memory -> Memory end, [{memory, Mem} | Node]; _ -> Node end. rabbitmq-server-3.2.4/plugins-src/rabbitmq-management/src/rabbit_mgmt_wm_permissions.erl0000644000000000000000000000303012305126066030421 0ustar rootroot%% The contents of this file are subject to the Mozilla Public License %% Version 1.1 (the "License"); you may not use this file except in %% compliance with the License. You may obtain a copy of the License at %% http://www.mozilla.org/MPL/ %% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the %% License for the specific language governing rights and limitations %% under the License. %% %% The Original Code is RabbitMQ Management Plugin. %% %% The Initial Developer of the Original Code is GoPivotal, Inc. %% Copyright (c) 2010-2013 GoPivotal, Inc. All rights reserved. %% -module(rabbit_mgmt_wm_permissions). -export([init/1, to_json/2, content_types_provided/2, is_authorized/2]). -export([permissions/0]). -include("rabbit_mgmt.hrl"). -include_lib("webmachine/include/webmachine.hrl"). -include_lib("rabbit_common/include/rabbit.hrl"). %%-------------------------------------------------------------------- init(_Config) -> {ok, #context{}}. content_types_provided(ReqData, Context) -> {[{"application/json", to_json}], ReqData, Context}. to_json(ReqData, Context) -> rabbit_mgmt_util:reply_list(permissions(), ["vhost", "user"], ReqData, Context). is_authorized(ReqData, Context) -> rabbit_mgmt_util:is_authorized_admin(ReqData, Context). %%-------------------------------------------------------------------- permissions() -> rabbit_auth_backend_internal:list_permissions(). rabbitmq-server-3.2.4/plugins-src/rabbitmq-management/src/rabbit_mgmt_wm_nodes.erl0000644000000000000000000000340412305126066027163 0ustar rootroot%% The contents of this file are subject to the Mozilla Public License %% Version 1.1 (the "License"); you may not use this file except in %% compliance with the License. You may obtain a copy of the License at %% http://www.mozilla.org/MPL/ %% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the %% License for the specific language governing rights and limitations %% under the License. %% %% The Original Code is RabbitMQ Management Console. %% %% The Initial Developer of the Original Code is GoPivotal, Inc. %% Copyright (c) 2010-2013 GoPivotal, Inc. All rights reserved. %% -module(rabbit_mgmt_wm_nodes). -export([init/1, to_json/2, content_types_provided/2, is_authorized/2]). -export([all_nodes/0]). -include("rabbit_mgmt.hrl"). -include_lib("webmachine/include/webmachine.hrl"). -include_lib("rabbit_common/include/rabbit.hrl"). %%-------------------------------------------------------------------- init(_Config) -> {ok, #context{}}. content_types_provided(ReqData, Context) -> {[{"application/json", to_json}], ReqData, Context}. to_json(ReqData, Context) -> rabbit_mgmt_util:reply_list(all_nodes(), ReqData, Context). is_authorized(ReqData, Context) -> rabbit_mgmt_util:is_authorized_monitor(ReqData, Context). %%-------------------------------------------------------------------- all_nodes() -> S = rabbit_mnesia:status(), Nodes = proplists:get_value(nodes, S), Types = proplists:get_keys(Nodes), Running = proplists:get_value(running_nodes, S), rabbit_mgmt_db:augment_nodes( [[{name, Node}, {type, Type}, {running, lists:member(Node, Running)}] || Type <- Types, Node <- proplists:get_value(Type, Nodes)]). rabbitmq-server-3.2.4/plugins-src/rabbitmq-management/src/rabbit_mgmt_wm_connection.erl0000644000000000000000000000465012305126066030216 0ustar rootroot%% The contents of this file are subject to the Mozilla Public License %% Version 1.1 (the "License"); you may not use this file except in %% compliance with the License. You may obtain a copy of the License at %% http://www.mozilla.org/MPL/ %% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the %% License for the specific language governing rights and limitations %% under the License. %% %% The Original Code is RabbitMQ Management Plugin. %% %% The Initial Developer of the Original Code is GoPivotal, Inc. %% Copyright (c) 2010-2013 GoPivotal, Inc. All rights reserved. %% -module(rabbit_mgmt_wm_connection). -export([init/1, resource_exists/2, to_json/2, content_types_provided/2, is_authorized/2, allowed_methods/2, delete_resource/2, conn/1]). -include("rabbit_mgmt.hrl"). -include_lib("webmachine/include/webmachine.hrl"). -include_lib("rabbit_common/include/rabbit.hrl"). %%-------------------------------------------------------------------- init(_Config) -> {ok, #context{}}. content_types_provided(ReqData, Context) -> {[{"application/json", to_json}], ReqData, Context}. allowed_methods(ReqData, Context) -> {['HEAD', 'GET', 'DELETE'], ReqData, Context}. resource_exists(ReqData, Context) -> case conn(ReqData) of not_found -> {false, ReqData, Context}; _Conn -> {true, ReqData, Context} end. to_json(ReqData, Context) -> rabbit_mgmt_util:reply( {struct, rabbit_mgmt_format:strip_pids(conn(ReqData))}, ReqData, Context). delete_resource(ReqData, Context) -> Conn = conn(ReqData), Pid = proplists:get_value(pid, Conn), Reason = case wrq:get_req_header(<<"X-Reason">>, ReqData) of undefined -> "Closed via management plugin"; V -> V end, case proplists:get_value(type, Conn) of direct -> amqp_direct_connection:server_close(Pid, 320, Reason); network -> rabbit_networking:close_connection(Pid, Reason) end, {true, ReqData, Context}. is_authorized(ReqData, Context) -> rabbit_mgmt_util:is_authorized_user(ReqData, Context, conn(ReqData)). %%-------------------------------------------------------------------- conn(ReqData) -> rabbit_mgmt_db:get_connection(rabbit_mgmt_util:id(connection, ReqData), rabbit_mgmt_util:range_ceil(ReqData)). rabbitmq-server-3.2.4/plugins-src/rabbitmq-management/src/rabbit_mgmt_wm_parameter.erl0000644000000000000000000000630612305126066030037 0ustar rootroot%% The contents of this file are subject to the Mozilla Public License %% Version 1.1 (the "License"); you may not use this file except in %% compliance with the License. You may obtain a copy of the License at %% http://www.mozilla.org/MPL/ %% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the %% License for the specific language governing rights and limitations %% under the License. %% %% The Original Code is RabbitMQ Management Plugin. %% %% The Initial Developer of the Original Code is GoPivotal, Inc. %% Copyright (c) 2010-2013 GoPivotal, Inc. All rights reserved. %% -module(rabbit_mgmt_wm_parameter). -export([init/1, resource_exists/2, to_json/2, content_types_provided/2, content_types_accepted/2, is_authorized/2, allowed_methods/2, accept_content/2, delete_resource/2]). -import(rabbit_misc, [pget/2]). -include("rabbit_mgmt.hrl"). -include_lib("webmachine/include/webmachine.hrl"). -include_lib("rabbit_common/include/rabbit.hrl"). %%-------------------------------------------------------------------- init(_Config) -> {ok, #context{}}. content_types_provided(ReqData, Context) -> {[{"application/json", to_json}], ReqData, Context}. content_types_accepted(ReqData, Context) -> {[{"application/json", accept_content}], ReqData, Context}. allowed_methods(ReqData, Context) -> {['HEAD', 'GET', 'PUT', 'DELETE'], ReqData, Context}. resource_exists(ReqData, Context) -> {case parameter(ReqData) of not_found -> false; _ -> true end, ReqData, Context}. to_json(ReqData, Context) -> rabbit_mgmt_util:reply(rabbit_mgmt_format:parameter(parameter(ReqData)), ReqData, Context). accept_content(ReqData, Context) -> case rabbit_mgmt_util:vhost(ReqData) of not_found -> rabbit_mgmt_util:not_found(vhost_not_found, ReqData, Context); VHost -> rabbit_mgmt_util:with_decode( [value], ReqData, Context, fun([Value], _) -> case rabbit_runtime_parameters:set( VHost, component(ReqData), name(ReqData), rabbit_misc:json_to_term(Value)) of ok -> {true, ReqData, Context}; {error_string, Reason} -> rabbit_mgmt_util:bad_request( list_to_binary(Reason), ReqData, Context) end end) end. delete_resource(ReqData, Context) -> ok = rabbit_runtime_parameters:clear( rabbit_mgmt_util:vhost(ReqData), component(ReqData), name(ReqData)), {true, ReqData, Context}. is_authorized(ReqData, Context) -> rabbit_mgmt_util:is_authorized_policies(ReqData, Context). %%-------------------------------------------------------------------- parameter(ReqData) -> rabbit_runtime_parameters:lookup( rabbit_mgmt_util:vhost(ReqData), component(ReqData), name(ReqData)). component(ReqData) -> rabbit_mgmt_util:id(component, ReqData). name(ReqData) -> rabbit_mgmt_util:id(name, ReqData). rabbitmq-server-3.2.4/plugins-src/rabbitmq-management/src/rabbit_mgmt_format.erl0000644000000000000000000002525512305126066026650 0ustar rootroot%% The contents of this file are subject to the Mozilla Public License %% Version 1.1 (the "License"); you may not use this file except in %% compliance with the License. You may obtain a copy of the License at %% http://www.mozilla.org/MPL/ %% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the %% License for the specific language governing rights and limitations %% under the License. %% %% The Original Code is RabbitMQ Management Plugin. %% %% The Initial Developer of the Original Code is GoPivotal, Inc. %% Copyright (c) 2010-2013 GoPivotal, Inc. All rights reserved. %% -module(rabbit_mgmt_format). -export([format/2, print/2, remove/1, ip/1, ipb/1, amqp_table/1, tuple/1]). -export([parameter/1, timestamp/1, timestamp_ms/1, strip_pids/1]). -export([node_from_pid/1, protocol/1, resource/1, queue/1, queue_status/1]). -export([exchange/1, user/1, internal_user/1, binding/1, url/2]). -export([pack_binding_props/2, tokenise/1]). -export([to_amqp_table/1, listener/1, properties/1, basic_properties/1]). -export([record/2, to_basic_properties/1]). -export([addr/1, port/1]). -import(rabbit_misc, [pget/2, pset/3]). -include_lib("rabbit_common/include/rabbit.hrl"). -include_lib("rabbit_common/include/rabbit_framing.hrl"). -define(PIDS_TO_STRIP, [connection, owner_pid, channel, exclusive_consumer_pid]). %%-------------------------------------------------------------------- format(Stats, Fs) -> lists:concat([format_item(Stat, Fs) || {_Name, Value} = Stat <- Stats, Value =/= unknown]). format_item(Stat, []) -> [Stat]; format_item({Name, Value}, [{Fun, Names} | Fs]) -> case lists:member(Name, Names) of true -> case Fun(Value) of List when is_list(List) -> List; Formatted -> [{Name, Formatted}] end; false -> format_item({Name, Value}, Fs) end. print(Fmt, Val) when is_list(Val) -> list_to_binary(lists:flatten(io_lib:format(Fmt, Val))); print(Fmt, Val) -> print(Fmt, [Val]). %% TODO - can we remove all these "unknown" cases? Coverage never hits them. remove(_) -> []. node_from_pid(Pid) when is_pid(Pid) -> [{node, node(Pid)}]; node_from_pid('') -> []; node_from_pid(unknown) -> []; node_from_pid(none) -> []. nodes_from_pids(Name) -> fun('') -> []; (Pids) -> [{Name, [node(Pid) || Pid <- Pids]}] end. ip(unknown) -> unknown; ip(IP) -> list_to_binary(rabbit_misc:ntoa(IP)). ipb(unknown) -> unknown; ipb(IP) -> list_to_binary(rabbit_misc:ntoab(IP)). addr(S) when is_list(S); is_atom(S); is_binary(S) -> print("~s", S); addr(Addr) when is_tuple(Addr) -> ip(Addr). port(Port) when is_number(Port) -> Port; port(Port) -> print("~w", Port). properties(unknown) -> unknown; properties(Table) -> {struct, [{Name, tuple(Value)} || {Name, Value} <- Table]}. amqp_table(unknown) -> unknown; amqp_table(undefined) -> amqp_table([]); amqp_table(Table) -> {struct, [{Name, amqp_value(Type, Value)} || {Name, Type, Value} <- Table]}. amqp_value(array, Vs) -> [amqp_value(T, V) || {T, V} <- Vs]; amqp_value(table, V) -> amqp_table(V); amqp_value(_Type, V) when is_binary(V) -> utf8_safe(V); amqp_value(_Type, V) -> V. utf8_safe(V) -> try xmerl_ucs:from_utf8(V), V catch exit:{ucs, _} -> Enc = base64:encode(V), <<"Invalid UTF-8, base64 is: ", Enc/binary>> end. parameter(P) -> pset(value, rabbit_misc:term_to_json(pget(value, P)), P). tuple(unknown) -> unknown; tuple(Tuple) when is_tuple(Tuple) -> [tuple(E) || E <- tuple_to_list(Tuple)]; tuple(Term) -> Term. protocol(unknown) -> unknown; protocol(Version = {_Major, _Minor, _Revision}) -> protocol({'AMQP', Version}); protocol({Family, Version}) -> print("~s ~s", [Family, protocol_version(Version)]). protocol_version(Arbitrary) when is_list(Arbitrary) -> Arbitrary; protocol_version({Major, Minor}) -> io_lib:format("~B-~B", [Major, Minor]); protocol_version({Major, Minor, 0}) -> protocol_version({Major, Minor}); protocol_version({Major, Minor, Revision}) -> io_lib:format("~B-~B-~B", [Major, Minor, Revision]). timestamp_ms(unknown) -> unknown; timestamp_ms(Timestamp) -> timer:now_diff(Timestamp, {0,0,0}) div 1000. timestamp(unknown) -> unknown; timestamp(Timestamp) -> {{Y, M, D}, {H, Min, S}} = calendar:now_to_local_time(Timestamp), print("~w-~2.2.0w-~2.2.0w ~w:~2.2.0w:~2.2.0w", [Y, M, D, H, Min, S]). resource(unknown) -> unknown; resource(Res) -> resource(name, Res). resource(_, unknown) -> unknown; resource(NameAs, #resource{name = Name, virtual_host = VHost}) -> [{NameAs, Name}, {vhost, VHost}]. policy('') -> []; policy(Policy) -> [{policy, Policy}]. internal_user(User) -> [{name, User#internal_user.username}, {password_hash, base64:encode(User#internal_user.password_hash)}, {tags, tags(User#internal_user.tags)}]. user(User) -> [{name, User#user.username}, {tags, tags(User#user.tags)}, {auth_backend, User#user.auth_backend}]. tags(Tags) -> list_to_binary(string:join([atom_to_list(T) || T <- Tags], ",")). listener(#listener{node = Node, protocol = Protocol, ip_address = IPAddress, port = Port}) -> [{node, Node}, {protocol, Protocol}, {ip_address, ip(IPAddress)}, {port, Port}]. pack_binding_props(<<"">>, []) -> <<"~">>; pack_binding_props(Key, []) -> list_to_binary(quote_binding(Key)); pack_binding_props(Key, Args) -> ArgsEnc = rabbit_mgmt_wm_binding:args_hash(Args), list_to_binary(quote_binding(Key) ++ "~" ++ quote_binding(ArgsEnc)). quote_binding(Name) -> re:replace(mochiweb_util:quote_plus(Name), "~", "%7E", [global]). %% Unfortunately string:tokens("foo~~bar", "~"). -> ["foo","bar"], we lose %% the fact that there's a double ~. tokenise("") -> []; tokenise(Str) -> Count = string:cspan(Str, "~"), case length(Str) of Count -> [Str]; _ -> [string:sub_string(Str, 1, Count) | tokenise(string:sub_string(Str, Count + 2))] end. to_amqp_table({struct, T}) -> to_amqp_table(T); to_amqp_table(T) -> [to_amqp_table_row(K, V) || {K, V} <- T]. to_amqp_table_row(K, V) -> {T, V2} = type_val(V), {K, T, V2}. to_amqp_array(L) -> [type_val(I) || I <- L]. type_val({struct, M}) -> {table, to_amqp_table(M)}; type_val(L) when is_list(L) -> {array, to_amqp_array(L)}; type_val(X) when is_binary(X) -> {longstr, X}; type_val(X) when is_integer(X) -> {long, X}; type_val(X) when is_number(X) -> {double, X}; type_val(true) -> {bool, true}; type_val(false) -> {bool, false}; type_val(null) -> throw({error, null_not_allowed}); type_val(X) -> throw({error, {unhandled_type, X}}). url(Fmt, Vals) -> print(Fmt, [mochiweb_util:quote_plus(V) || V <- Vals]). exchange(X) -> format(X, [{fun resource/1, [name]}, {fun amqp_table/1, [arguments]}, {fun policy/1, [policy]}]). %% We get queues using rabbit_amqqueue:list/1 rather than :info_all/1 since %% the latter wakes up each queue. Therefore we have a record rather than a %% proplist to deal with. queue(#amqqueue{name = Name, durable = Durable, auto_delete = AutoDelete, exclusive_owner = ExclusiveOwner, arguments = Arguments, pid = Pid}) -> format( [{name, Name}, {durable, Durable}, {auto_delete, AutoDelete}, {owner_pid, ExclusiveOwner}, {arguments, Arguments}, {pid, Pid}], [{fun resource/1, [name]}, {fun amqp_table/1, [arguments]}, {fun policy/1, [policy]}]). queue_status({syncing, Msgs}) -> [{status, syncing}, {sync_messages, Msgs}]; queue_status(Status) -> [{status, Status}]. %% We get bindings using rabbit_binding:list_*/1 rather than :info_all/1 since %% there are no per-exchange / queue / etc variants for the latter. Therefore %% we have a record rather than a proplist to deal with. binding(#binding{source = S, key = Key, destination = D, args = Args}) -> format( [{source, S}, {destination, D#resource.name}, {destination_type, D#resource.kind}, {routing_key, Key}, {arguments, Args}, {properties_key, pack_binding_props(Key, Args)}], [{fun (Res) -> resource(source, Res) end, [source]}, {fun amqp_table/1, [arguments]}]). basic_properties(Props = #'P_basic'{}) -> Res = record(Props, record_info(fields, 'P_basic')), format(Res, [{fun amqp_table/1, [headers]}]). record(Record, Fields) -> {Res, _Ix} = lists:foldl(fun (K, {L, Ix}) -> {case element(Ix, Record) of undefined -> L; V -> [{K, V}|L] end, Ix + 1} end, {[], 2}, Fields), Res. to_basic_properties({struct, P}) -> to_basic_properties(P); to_basic_properties(Props) -> Fmt = fun (headers, H) -> to_amqp_table(H); (_K , V) -> V end, {Res, _Ix} = lists:foldl( fun (K, {P, Ix}) -> {case proplists:get_value(a2b(K), Props) of undefined -> P; V -> setelement(Ix, P, Fmt(K, V)) end, Ix + 1} end, {#'P_basic'{}, 2}, record_info(fields, 'P_basic')), Res. a2b(A) -> list_to_binary(atom_to_list(A)). %% Items can be connections, channels, consumers or queues, hence remove takes %% various items. strip_pids(Item = [T | _]) when is_tuple(T) -> format(Item, [{fun node_from_pid/1, [pid]}, {fun remove/1, ?PIDS_TO_STRIP}, {nodes_from_pids(slave_nodes), [slave_pids]}, {nodes_from_pids(synchronised_slave_nodes), [synchronised_slave_pids]} ]); strip_pids(Items) -> [strip_pids(I) || I <- Items]. rabbitmq-server-3.2.4/plugins-src/rabbitmq-management/src/rabbit_mgmt_wm_connection_channels.erl0000644000000000000000000000377112305126066032074 0ustar rootroot%% The contents of this file are subject to the Mozilla Public License %% Version 1.1 (the "License"); you may not use this file except in %% compliance with the License. You may obtain a copy of the License at %% http://www.mozilla.org/MPL/ %% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the %% License for the specific language governing rights and limitations %% under the License. %% %% The Original Code is RabbitMQ Management Plugin. %% %% The Initial Developer of the Original Code is GoPivotal, Inc. %% Copyright (c) 2010-2013 GoPivotal, Inc. All rights reserved. %% -module(rabbit_mgmt_wm_connection_channels). -export([init/1, to_json/2, content_types_provided/2, is_authorized/2]). -export([resource_exists/2]). -include("rabbit_mgmt.hrl"). -include_lib("webmachine/include/webmachine.hrl"). -include_lib("rabbit_common/include/rabbit.hrl"). %%-------------------------------------------------------------------- init(_Config) -> {ok, #context{}}. content_types_provided(ReqData, Context) -> {[{"application/json", to_json}], ReqData, Context}. resource_exists(ReqData, Context) -> case rabbit_mgmt_wm_connection:conn(ReqData) of error -> {false, ReqData, Context}; _Conn -> {true, ReqData, Context} end. to_json(ReqData, Context) -> Name = proplists:get_value(name, rabbit_mgmt_wm_connection:conn(ReqData)), Chs = rabbit_mgmt_db:get_all_channels(rabbit_mgmt_util:range(ReqData)), rabbit_mgmt_util:reply_list( [Ch || Ch <- rabbit_mgmt_util:filter_conn_ch_list(Chs, ReqData, Context), conn_name(Ch) =:= Name], ReqData, Context). is_authorized(ReqData, Context) -> rabbit_mgmt_util:is_authorized_user( ReqData, Context, rabbit_mgmt_wm_connection:conn(ReqData)). %%-------------------------------------------------------------------- conn_name(Ch) -> proplists:get_value(name, proplists:get_value(connection_details, Ch)). rabbitmq-server-3.2.4/plugins-src/rabbitmq-management/src/rabbit_mgmt_wm_channels.erl0000644000000000000000000000304612305126066027650 0ustar rootroot%% The contents of this file are subject to the Mozilla Public License %% Version 1.1 (the "License"); you may not use this file except in %% compliance with the License. You may obtain a copy of the License at %% http://www.mozilla.org/MPL/ %% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the %% License for the specific language governing rights and limitations %% under the License. %% %% The Original Code is RabbitMQ Management Plugin. %% %% The Initial Developer of the Original Code is GoPivotal, Inc. %% Copyright (c) 2010-2013 GoPivotal, Inc. All rights reserved. %% -module(rabbit_mgmt_wm_channels). -export([init/1, to_json/2, content_types_provided/2, is_authorized/2, augmented/2]). -import(rabbit_misc, [pget/2]). -include("rabbit_mgmt.hrl"). -include_lib("webmachine/include/webmachine.hrl"). -include_lib("rabbit_common/include/rabbit.hrl"). %%-------------------------------------------------------------------- init(_Config) -> {ok, #context{}}. content_types_provided(ReqData, Context) -> {[{"application/json", to_json}], ReqData, Context}. to_json(ReqData, Context) -> rabbit_mgmt_util:reply_list(augmented(ReqData, Context), ReqData, Context). is_authorized(ReqData, Context) -> rabbit_mgmt_util:is_authorized(ReqData, Context). augmented(ReqData, Context) -> rabbit_mgmt_util:filter_conn_ch_list( rabbit_mgmt_db:get_all_channels( rabbit_mgmt_util:range(ReqData)), ReqData, Context). rabbitmq-server-3.2.4/plugins-src/rabbitmq-management/README0000644000000000000000000000044312305126066022366 0ustar rootrootGeneric build instructions are at: http://www.rabbitmq.com/plugin-development.html When installed, point your broswer at: http://:15672/ and log in with AMQP credentials (guest/guest by default). Documentation for the HTTP API can be found at http://:15672/api/ rabbitmq-server-3.2.4/plugins-src/rabbitmq-management/test/0000755000000000000000000000000012305126066022464 5ustar rootrootrabbitmq-server-3.2.4/plugins-src/rabbitmq-management/test/src/0000755000000000000000000000000012305126066023253 5ustar rootrootrabbitmq-server-3.2.4/plugins-src/rabbitmq-management/test/src/rabbit_mgmt_test_all.erl0000644000000000000000000000275612305126066030147 0ustar rootroot%% The contents of this file are subject to the Mozilla Public License %% Version 1.1 (the "License"); you may not use this file except in %% compliance with the License. You may obtain a copy of the License at %% http://www.mozilla.org/MPL/ %% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the %% License for the specific language governing rights and limitations %% under the License. %% %% The Original Code is RabbitMQ Management Console. %% %% The Initial Developer of the Original Code is GoPivotal, Inc. %% Copyright (c) 2010-2013 GoPivotal, Inc. All rights reserved. %% -module(rabbit_mgmt_test_all). -export([all_tests/0]). all_tests() -> ok = eunit:test(rabbit_mgmt_test_unit, [verbose]), ok = eunit:test(rabbit_mgmt_test_db_unit, [verbose]), ok = eunit:test(rabbit_mgmt_test_db, [verbose]), ok = eunit:test(tests(rabbit_mgmt_test_http, 60), [verbose]), io:format("Starting second node...~n"), ok = rabbit_mgmt_test_clustering:start_second_node(), io:format("...done.~n"), try ok = eunit:test(rabbit_mgmt_test_clustering,[verbose]) after ok = rabbit_mgmt_test_clustering:stop_second_node() end. tests(Module, Timeout) -> {foreach, fun() -> ok end, [{timeout, Timeout, fun Module:F/0} || {F, _Arity} <- proplists:get_value(exports, Module:module_info()), string:right(atom_to_list(F), 5) =:= "_test"]}. rabbitmq-server-3.2.4/plugins-src/rabbitmq-management/test/src/rabbit_mgmt_test_util.erl0000644000000000000000000000266712305126066030355 0ustar rootroot%% The contents of this file are subject to the Mozilla Public License %% Version 1.1 (the "License"); you may not use this file except in %% compliance with the License. You may obtain a copy of the License at %% http://www.mozilla.org/MPL/ %% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the %% License for the specific language governing rights and limitations %% under the License. %% %% The Original Code is RabbitMQ Management Console. %% %% The Initial Developer of the Original Code is GoPivotal, Inc. %% Copyright (c) 2010-2012 GoPivotal, Inc. All rights reserved. %% -module(rabbit_mgmt_test_util). -export([assert_list/2, assert_item/2, test_item/2]). assert_list(Exp, Act) -> case length(Exp) == length(Act) of true -> ok; false -> throw({expected, Exp, actual, Act}) end, [case length(lists:filter(fun(ActI) -> test_item(ExpI, ActI) end, Act)) of 1 -> ok; N -> throw({found, N, ExpI, in, Act}) end || ExpI <- Exp]. assert_item(Exp, Act) -> case test_item0(Exp, Act) of [] -> ok; Or -> throw(Or) end. test_item(Exp, Act) -> case test_item0(Exp, Act) of [] -> true; _ -> false end. test_item0(Exp, Act) -> [{did_not_find, ExpI, in, Act} || ExpI <- Exp, not lists:member(ExpI, Act)]. rabbitmq-server-3.2.4/plugins-src/rabbitmq-management/test/src/rabbit_mgmt_test_db.erl0000644000000000000000000002444712305126066027765 0ustar rootroot%% The contents of this file are subject to the Mozilla Public License %% Version 1.1 (the "License"); you may not use this file except in %% compliance with the License. You may obtain a copy of the License at %% http://www.mozilla.org/MPL/ %% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the %% License for the specific language governing rights and limitations %% under the License. %% %% The Original Code is RabbitMQ Management Console. %% %% The Initial Developer of the Original Code is GoPivotal, Inc. %% Copyright (c) 2010-2013 GoPivotal, Inc. All rights reserved. %% -module(rabbit_mgmt_test_db). -include("rabbit_mgmt.hrl"). -include_lib("eunit/include/eunit.hrl"). -include_lib("rabbit_common/include/rabbit.hrl"). -import(rabbit_misc, [pget/2]). -import(rabbit_mgmt_test_util, [assert_list/2, assert_item/2, test_item/2]). -define(debugVal2(E), ((fun (__V) -> ?debugFmt(<<"~s = ~p">>, [(??E), __V]), __V end)(E))). %%---------------------------------------------------------------------------- %% Tests %%---------------------------------------------------------------------------- queue_coarse_test() -> rabbit_mgmt_db:override_lookups([{exchange, fun dummy_lookup/1}, {queue, fun dummy_lookup/1}]), create_q(test, 0), create_q(test2, 0), stats_q(test, 0, 10), stats_q(test2, 0, 1), R = range(0, 1, 1), Exp = fun(N) -> simple_details(messages, N, R) end, assert_item(Exp(10), get_q(test, R)), assert_item(Exp(11), get_vhost(R)), assert_item(Exp(11), get_overview_q(R)), delete_q(test, 0), assert_item(Exp(1), get_vhost(R)), assert_item(Exp(1), get_overview_q(R)), delete_q(test2, 0), assert_item(Exp(0), get_vhost(R)), assert_item(Exp(0), get_overview_q(R)), rabbit_mgmt_db:reset_lookups(), ok. connection_coarse_test() -> create_conn(test, 0), create_conn(test2, 0), stats_conn(test, 0, 10), stats_conn(test2, 0, 1), R = range(0, 1, 1), Exp = fun(N) -> simple_details(recv_oct, N, R) end, assert_item(Exp(10), get_conn(test, R)), assert_item(Exp(1), get_conn(test2, R)), delete_conn(test, 1), delete_conn(test2, 1), assert_list([], rabbit_mgmt_db:get_all_connections(R)), ok. fine_stats_aggregation_test() -> rabbit_mgmt_db:override_lookups([{exchange, fun dummy_lookup/1}, {queue, fun dummy_lookup/1}]), create_ch(ch1, 0), create_ch(ch2, 0), stats_ch(ch1, 0, [{x, 100}], [{q1, x, 100}, {q2, x, 10}], [{q1, 2}, {q2, 1}]), stats_ch(ch2, 0, [{x, 10}], [{q1, x, 50}, {q2, x, 5}], []), fine_stats_aggregation_test0(true), delete_q(q2, 0), fine_stats_aggregation_test0(false), delete_ch(ch1, 1), delete_ch(ch2, 1), rabbit_mgmt_db:reset_lookups(), ok. fine_stats_aggregation_test0(Q2Exists) -> R = range(0, 1, 1), Ch1 = get_ch(ch1, R), Ch2 = get_ch(ch2, R), X = get_x(x, R), Q1 = get_q(q1, R), V = get_vhost(R), O = get_overview(R), assert_fine_stats(m, publish, 100, Ch1, R), assert_fine_stats(m, publish, 10, Ch2, R), assert_fine_stats(m, publish_in, 110, X, R), assert_fine_stats(m, publish_out, 165, X, R), assert_fine_stats(m, publish, 150, Q1, R), assert_fine_stats(m, deliver_get, 2, Q1, R), assert_fine_stats(m, deliver_get, 3, Ch1, R), assert_fine_stats(m, publish, 110, V, R), assert_fine_stats(m, deliver_get, 3, V, R), assert_fine_stats(m, publish, 110, O, R), assert_fine_stats(m, deliver_get, 3, O, R), assert_fine_stats({pub, x}, publish, 100, Ch1, R), assert_fine_stats({pub, x}, publish, 10, Ch2, R), assert_fine_stats({in, ch1}, publish, 100, X, R), assert_fine_stats({in, ch2}, publish, 10, X, R), assert_fine_stats({out, q1}, publish, 150, X, R), assert_fine_stats({in, x}, publish, 150, Q1, R), assert_fine_stats({del, ch1}, deliver_get, 2, Q1, R), assert_fine_stats({del, q1}, deliver_get, 2, Ch1, R), case Q2Exists of true -> Q2 = get_q(q2, R), assert_fine_stats(m, publish, 15, Q2, R), assert_fine_stats(m, deliver_get, 1, Q2, R), assert_fine_stats({out, q2}, publish, 15, X, R), assert_fine_stats({in, x}, publish, 15, Q2, R), assert_fine_stats({del, ch1}, deliver_get, 1, Q2, R), assert_fine_stats({del, q2}, deliver_get, 1, Ch1, R); false -> assert_fine_stats_neg({out, q2}, X), assert_fine_stats_neg({del, q2}, Ch1) end, ok. fine_stats_aggregation_time_test() -> rabbit_mgmt_db:override_lookups([{exchange, fun dummy_lookup/1}, {queue, fun dummy_lookup/1}]), create_ch(ch, 0), stats_ch(ch, 0, [{x, 100}], [{q, x, 50}], [{q, 20}]), stats_ch(ch, 5, [{x, 110}], [{q, x, 55}], [{q, 22}]), R1 = range(0, 1, 1), assert_fine_stats(m, publish, 100, get_ch(ch, R1), R1), assert_fine_stats(m, publish, 50, get_q(q, R1), R1), assert_fine_stats(m, deliver_get, 20, get_q(q, R1), R1), R2 = range(5, 6, 1), assert_fine_stats(m, publish, 110, get_ch(ch, R2), R2), assert_fine_stats(m, publish, 55, get_q(q, R2), R2), assert_fine_stats(m, deliver_get, 22, get_q(q, R2), R2), delete_q(q, 0), delete_ch(ch, 1), rabbit_mgmt_db:reset_lookups(), ok. assert_fine_stats(m, Type, N, Obj, R) -> Act = pget(message_stats, Obj), assert_item(simple_details(Type, N, R), Act); assert_fine_stats({T2, Name}, Type, N, Obj, R) -> Act = find_detailed_stats(Name, pget(expand(T2), Obj)), assert_item(simple_details(Type, N, R), Act). assert_fine_stats_neg({T2, Name}, Obj) -> detailed_stats_absent(Name, pget(expand(T2), Obj)). %%---------------------------------------------------------------------------- %% Events in %%---------------------------------------------------------------------------- create_q(Name, Timestamp) -> %% Technically we do not need this, the DB ignores it, but let's %% be symmetrical... event(queue_created, [{name, q(Name)}], Timestamp). create_conn(Name, Timestamp) -> event(connection_created, [{pid, pid(Name)}, {name, a2b(Name)}], Timestamp). create_ch(Name, Timestamp) -> event(channel_created, [{pid, pid(Name)}, {name, a2b(Name)}], Timestamp). stats_q(Name, Timestamp, Msgs) -> event(queue_stats, [{name, q(Name)}, {messages, Msgs}], Timestamp). stats_conn(Name, Timestamp, Oct) -> event(connection_stats, [{pid , pid(Name)}, {recv_oct, Oct}], Timestamp). stats_ch(Name, Timestamp, XStats, QXStats, QStats) -> XStats1 = [{x(XName), [{publish, N}]} || {XName, N} <- XStats], QXStats1 = [{{q(QName), x(XName)}, [{publish, N}]} || {QName, XName, N} <- QXStats], QStats1 = [{q(QName), [{deliver_no_ack, N}]} || {QName, N} <- QStats], event(channel_stats, [{pid, pid(Name)}, {channel_exchange_stats, XStats1}, {channel_queue_exchange_stats, QXStats1}, {channel_queue_stats, QStats1}], Timestamp). delete_q(Name, Timestamp) -> event(queue_deleted, [{name, q(Name)}], Timestamp). delete_conn(Name, Timestamp) -> event(connection_closed, [{pid, pid_del(Name)}], Timestamp). delete_ch(Name, Timestamp) -> event(channel_closed, [{pid, pid_del(Name)}], Timestamp). event(Type, Stats, Timestamp) -> gen_server:cast({global, rabbit_mgmt_db}, {event, #event{type = Type, props = Stats, timestamp = sec_to_triple(Timestamp)}}). sec_to_triple(Sec) -> {Sec div 1000000, Sec rem 1000000, 0}. %%---------------------------------------------------------------------------- %% Events out %%---------------------------------------------------------------------------- range(F, L, I) -> R = #range{first = F * 1000, last = L * 1000, incr = I * 1000}, {R, R, R}. get_x(Name, Range) -> [X] = rabbit_mgmt_db:augment_exchanges([x2(Name)], Range, full), X. get_q(Name, Range) -> [Q] = rabbit_mgmt_db:augment_queues([q2(Name)], Range, full), Q. get_vhost(Range) -> [VHost] = rabbit_mgmt_db:augment_vhosts([[{name, <<"/">>}]], Range), VHost. get_conn(Name, Range) -> rabbit_mgmt_db:get_connection(a2b(Name), Range). get_ch(Name, Range) -> rabbit_mgmt_db:get_channel(a2b(Name), Range). get_overview(Range) -> rabbit_mgmt_db:get_overview(Range). get_overview_q(Range) -> pget(queue_totals, get_overview(Range)). details0(R, AR, A, L) -> [{rate, R}, {samples, [[{sample, S}, {timestamp, T}] || {T, S} <- L]}, {avg_rate, AR}, {avg, A}]. simple_details(Thing, N, {#range{first = First, last = Last}, _, _}) -> [{Thing, N}, {atom_suffix(Thing, "_details"), details0(0.0, 0.0, N * 1.0, [{Last, N}, {First, N}])}]. atom_suffix(Atom, Suffix) -> list_to_atom(atom_to_list(Atom) ++ Suffix). find_detailed_stats(Name, List) -> [S] = filter_detailed_stats(Name, List), S. detailed_stats_absent(Name, List) -> [] = filter_detailed_stats(Name, List). filter_detailed_stats(Name, List) -> [Stats || [{stats, Stats}, {_, Details}] <- List, pget(name, Details) =:= a2b(Name)]. expand(in) -> incoming; expand(out) -> outgoing; expand(del) -> deliveries; expand(pub) -> publishes. %%---------------------------------------------------------------------------- %% Util %%---------------------------------------------------------------------------- x(Name) -> rabbit_misc:r(<<"/">>, exchange, a2b(Name)). x2(Name) -> q2(Name). q(Name) -> rabbit_misc:r(<<"/">>, queue, a2b(Name)). q2(Name) -> [{name, a2b(Name)}, {vhost, <<"/">>}]. pid(Name) -> case get({pid, Name}) of undefined -> P = spawn(fun() -> ok end), put({pid, Name}, P), P; Pid -> Pid end. pid_del(Name) -> Pid = pid(Name), erase({pid, Name}), Pid. a2b(A) -> list_to_binary(atom_to_list(A)). dummy_lookup(_Thing) -> {ok, ignore_this}. rabbitmq-server-3.2.4/plugins-src/rabbitmq-management/test/src/rabbit_mgmt_test_unit.erl0000644000000000000000000000441612305126066030351 0ustar rootroot%% The contents of this file are subject to the Mozilla Public License %% Version 1.1 (the "License"); you may not use this file except in %% compliance with the License. You may obtain a copy of the License at %% http://www.mozilla.org/MPL/ %% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the %% License for the specific language governing rights and limitations %% under the License. %% %% The Original Code is RabbitMQ Management Console. %% %% The Initial Developer of the Original Code is GoPivotal, Inc. %% Copyright (c) 2010-2013 GoPivotal, Inc. All rights reserved. %% -module(rabbit_mgmt_test_unit). -include_lib("eunit/include/eunit.hrl"). tokenise_test() -> [] = rabbit_mgmt_format:tokenise(""), ["foo"] = rabbit_mgmt_format:tokenise("foo"), ["foo", "bar"] = rabbit_mgmt_format:tokenise("foo~bar"), ["foo", "", "bar"] = rabbit_mgmt_format:tokenise("foo~~bar"), ok. pack_binding_test() -> assert_binding(<<"~">>, <<"">>, []), assert_binding(<<"foo">>, <<"foo">>, []), assert_binding(<<"foo%7Ebar%2Fbash">>, <<"foo~bar/bash">>, []), assert_binding(<<"foo%7Ebar%7Ebash">>, <<"foo~bar~bash">>, []), ok. amqp_table_test() -> assert_table({struct, []}, []), assert_table({struct, [{<<"x-expires">>, 1000}]}, [{<<"x-expires">>, long, 1000}]), assert_table({struct, [{<<"x-forwarding">>, [{struct, [{<<"uri">>, <<"amqp://localhost/%2f/upstream">>}]}]}]}, [{<<"x-forwarding">>, array, [{table, [{<<"uri">>, longstr, <<"amqp://localhost/%2f/upstream">>}]}]}]). assert_table(JSON, AMQP) -> ?assertEqual(JSON, rabbit_mgmt_format:amqp_table(AMQP)), ?assertEqual(AMQP, rabbit_mgmt_format:to_amqp_table(JSON)). %%-------------------------------------------------------------------- assert_binding(Packed, Routing, Args) -> case rabbit_mgmt_format:pack_binding_props(Routing, Args) of Packed -> ok; Act -> throw({pack, Routing, Args, expected, Packed, got, Act}) end. rabbitmq-server-3.2.4/plugins-src/rabbitmq-management/test/src/rabbitmqadmin-test.py0000755000000000000000000002662412305126066027431 0ustar rootroot#!/usr/bin/env python import unittest import os import os.path import socket import subprocess import sys import shutil # TODO test: SSL, depth, config file, encodings(?), completion(???) class TestRabbitMQAdmin(unittest.TestCase): def test_no_args(self): self.run_fail([]) def test_help(self): self.run_success(['--help']) self.run_success(['help', 'subcommands']) self.run_success(['help', 'config']) self.run_fail(['help', 'astronomy']) def test_host(self): self.run_success(['show', 'overview']) self.run_success(['--host', 'localhost', 'show', 'overview']) self.run_success(['--host', socket.gethostname(), 'show', 'overview']) self.run_fail(['--host', 'some-host-that-does-not-exist', 'show', 'overview']) def test_port(self): # Test port selection self.run_success(['--port', '15672', 'show', 'overview']) # Test redirect self.run_success(['--port', '55672', 'show', 'overview']) # Test port not open self.run_fail(['--port', '15673', 'show', 'overview']) # Test port open but not talking HTTP self.run_fail(['--port', '5672', 'show', 'overview']) def test_config(self): original_home = os.getenv('HOME') tmpdir = os.getenv("TMPDIR") or os.getenv("TEMP") or "/tmp" shutil.copyfile(os.path.dirname(__file__) + os.sep + "default-config", tmpdir + os.sep + ".rabbitmqadmin.conf") os.environ['HOME'] = tmpdir self.run_fail(['--config', '/tmp/no-such-config-file', 'show', 'overview']) cf = os.path.dirname(__file__) + os.sep + "test-config" self.run_success(['--config', cf, '--node', 'host_normal', 'show', 'overview']) # test 'default node in the config file' where "default" uses an invalid host self.run_fail(['--config', cf, 'show', 'overview']) self.run_success(["show", "overview"]) self.run_fail(['--node', 'non_default', "show", "overview"]) os.environ['HOME'] = original_home def test_user(self): self.run_success(['--user', 'guest', '--password', 'guest', 'show', 'overview']) self.run_fail(['--user', 'no', '--password', 'guest', 'show', 'overview']) self.run_fail(['--user', 'guest', '--password', 'no', 'show', 'overview']) def test_fmt_long(self): self.assert_output(""" -------------------------------------------------------------------------------- name: / tracing: False -------------------------------------------------------------------------------- """, ['--format', 'long', 'list', 'vhosts', 'name', 'tracing']) def test_fmt_kvp(self): self.assert_output("""name="/" tracing="False" """, ['--format', 'kvp', 'list', 'vhosts', 'name', 'tracing']) def test_fmt_tsv(self): self.assert_output("""name tracing / False """, ['--format', 'tsv', 'list', 'vhosts', 'name', 'tracing']) def test_fmt_table(self): out = """+------+---------+ | name | tracing | +------+---------+ | / | False | +------+---------+ """ self.assert_output(out, ['list', 'vhosts', 'name', 'tracing']) self.assert_output(out, ['--format', 'table', 'list', 'vhosts', 'name', 'tracing']) def test_fmt_bash(self): self.assert_output("""/ """, ['--format', 'bash', 'list', 'vhosts', 'name', 'tracing']) def test_vhosts(self): self.assert_list(['/'], l('vhosts')) self.run_success(['declare', 'vhost', 'name=foo']) self.assert_list(['/', 'foo'], l('vhosts')) self.run_success(['delete', 'vhost', 'name=foo']) self.assert_list(['/'], l('vhosts')) def test_users(self): self.assert_list(['guest'], l('users')) self.run_fail(['declare', 'user', 'name=foo']) self.run_success(['declare', 'user', 'name=foo', 'password=pass', 'tags=']) self.assert_list(['foo', 'guest'], l('users')) self.run_success(['delete', 'user', 'name=foo']) self.assert_list(['guest'], l('users')) def test_permissions(self): self.run_success(['declare', 'vhost', 'name=foo']) self.run_success(['declare', 'user', 'name=bar', 'password=pass', 'tags=']) self.assert_table([['guest', '/']], ['list', 'permissions', 'user', 'vhost']) self.run_success(['declare', 'permission', 'user=bar', 'vhost=foo', 'configure=.*', 'write=.*', 'read=.*']) self.assert_table([['guest', '/'], ['bar', 'foo']], ['list', 'permissions', 'user', 'vhost']) self.run_success(['delete', 'user', 'name=bar']) self.run_success(['delete', 'vhost', 'name=foo']) def test_alt_vhost(self): self.run_success(['declare', 'vhost', 'name=foo']) self.run_success(['declare', 'permission', 'user=guest', 'vhost=foo', 'configure=.*', 'write=.*', 'read=.*']) self.run_success(['declare', 'queue', 'name=in_/']) self.run_success(['--vhost', 'foo', 'declare', 'queue', 'name=in_foo']) self.assert_table([['/', 'in_/'], ['foo', 'in_foo']], ['list', 'queues', 'vhost', 'name']) self.run_success(['--vhost', 'foo', 'delete', 'queue', 'name=in_foo']) self.run_success(['delete', 'queue', 'name=in_/']) self.run_success(['delete', 'vhost', 'name=foo']) def test_exchanges(self): self.run_success(['declare', 'exchange', 'name=foo', 'type=direct']) self.assert_list(['', 'amq.direct', 'amq.fanout', 'amq.headers', 'amq.match', 'amq.rabbitmq.log', 'amq.rabbitmq.trace', 'amq.topic', 'foo'], l('exchanges')) self.run_success(['delete', 'exchange', 'name=foo']) def test_queues(self): self.run_success(['declare', 'queue', 'name=foo']) self.assert_list(['foo'], l('queues')) self.run_success(['delete', 'queue', 'name=foo']) def test_bindings(self): self.run_success(['declare', 'queue', 'name=foo']) self.run_success(['declare', 'binding', 'source=amq.direct', 'destination=foo', 'destination_type=queue', 'routing_key=test']) self.assert_table([['', 'foo', 'queue', 'foo'], ['amq.direct', 'foo', 'queue', 'test']], ['list', 'bindings', 'source', 'destination', 'destination_type', 'routing_key']) self.run_success(['delete', 'queue', 'name=foo']) def test_policies(self): self.run_success(['declare', 'policy', 'name=ha', 'pattern=.*', 'definition={"ha-mode":"all"}']) self.assert_table([['ha', '/', '.*', '{"ha-mode": "all"}']], ['list', 'policies', 'name', 'vhost', 'pattern', 'definition']) self.run_success(['delete', 'policy', 'name=ha']) def test_parameters(self): self.ctl(['eval', 'rabbit_runtime_parameters_test:register().']) self.run_success(['declare', 'parameter', 'component=test', 'name=good', 'value=123']) self.assert_table([['test', 'good', '/', '123']], ['list', 'parameters', 'component', 'name', 'vhost', 'value']) self.run_success(['delete', 'parameter', 'component=test', 'name=good']) self.ctl(['eval', 'rabbit_runtime_parameters_test:unregister().']) def test_publish(self): self.run_success(['declare', 'queue', 'name=test']) self.run_success(['publish', 'routing_key=test', 'payload=test_1']) self.run_success(['publish', 'routing_key=test', 'payload=test_2']) self.run_success(['publish', 'routing_key=test'], stdin='test_3') self.assert_table([exp_msg('test', 2, False, 'test_1')], ['get', 'queue=test', 'requeue=false']) self.assert_table([exp_msg('test', 1, False, 'test_2')], ['get', 'queue=test', 'requeue=true']) self.assert_table([exp_msg('test', 1, True, 'test_2')], ['get', 'queue=test', 'requeue=false']) self.assert_table([exp_msg('test', 0, False, 'test_3')], ['get', 'queue=test', 'requeue=false']) self.run_success(['publish', 'routing_key=test'], stdin='test_4') filename = '/tmp/rabbitmq-test/get.txt' self.run_success(['get', 'queue=test', 'requeue=false', 'payload_file=' + filename]) with open(filename) as f: self.assertEqual('test_4', f.read()) os.remove(filename) self.run_success(['delete', 'queue', 'name=test']) def test_ignore_vhost(self): self.run_success(['--vhost', '/', 'show', 'overview']) self.run_success(['--vhost', '/', 'list', 'users']) self.run_success(['--vhost', '/', 'list', 'vhosts']) self.run_success(['--vhost', '/', 'list', 'nodes']) self.run_success(['--vhost', '/', 'list', 'permissions']) self.run_success(['--vhost', '/', 'declare', 'user', 'name=foo', 'password=pass', 'tags=']) self.run_success(['delete', 'user', 'name=foo']) def test_sort(self): self.run_success(['declare', 'queue', 'name=foo']) self.run_success(['declare', 'binding', 'source=amq.direct', 'destination=foo', 'destination_type=queue', 'routing_key=bbb']) self.run_success(['declare', 'binding', 'source=amq.topic', 'destination=foo', 'destination_type=queue', 'routing_key=aaa']) self.assert_table([['', 'foo'], ['amq.direct', 'bbb'], ['amq.topic', 'aaa']], ['--sort', 'source', 'list', 'bindings', 'source', 'routing_key']) self.assert_table([['amq.topic', 'aaa'], ['amq.direct', 'bbb'], ['', 'foo']], ['--sort', 'routing_key', 'list', 'bindings', 'source', 'routing_key']) self.assert_table([['amq.topic', 'aaa'], ['amq.direct', 'bbb'], ['', 'foo']], ['--sort', 'source', '--sort-reverse', 'list', 'bindings', 'source', 'routing_key']) self.run_success(['delete', 'queue', 'name=foo']) # --------------------------------------------------------------------------- def run_success(self, args, **kwargs): (stdout, ret) = self.admin(args, **kwargs) if ret != 0: self.fail(stdout) def run_fail(self, args): (stdout, ret) = self.admin(args) if ret == 0: self.fail(stdout) def assert_output(self, expected, args): self.assertEqual(expected, self.admin(args)[0]) def assert_list(self, expected, args0): args = ['-f', 'tsv', '-q'] args.extend(args0) self.assertEqual(expected, self.admin(args)[0].splitlines()) def assert_table(self, expected, args0): args = ['-f', 'tsv', '-q'] args.extend(args0) self.assertEqual(expected, [l.split('\t') for l in self.admin(args)[0].splitlines()]) def admin(self, args, stdin=None): return run('../../../bin/rabbitmqadmin', args, stdin) def ctl(self, args0, stdin=None): args = ['-n', 'rabbit-test'] args.extend(args0) (stdout, ret) = run('../../../../rabbitmq-server/scripts/rabbitmqctl', args, stdin) if ret != 0: self.fail(stdout) def run(cmd, args, stdin): path = os.path.normpath(os.path.join(os.getcwd(), sys.argv[0], cmd)) cmdline = [path] cmdline.extend(args) proc = subprocess.Popen(cmdline, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE) (stdout, stderr) = proc.communicate(stdin) returncode = proc.returncode return (stdout + stderr, returncode) def l(thing): return ['list', thing, 'name'] def exp_msg(key, count, redelivered, payload): # routing_key, exchange, message_count, payload, payload_bytes, payload_encoding, properties, redelivered return [key, '', str(count), payload, str(len(payload)), 'string', '', str(redelivered)] if __name__ == '__main__': print "\nrabbitmqadmin tests\n===================\n" suite = unittest.TestLoader().loadTestsFromTestCase(TestRabbitMQAdmin) unittest.TextTestRunner(verbosity=2).run(suite) rabbitmq-server-3.2.4/plugins-src/rabbitmq-management/test/src/default-config0000644000000000000000000000051212305126066026063 0ustar rootroot# rabbitmqadmin.conf.example START [non_default] hostname = localhost port = 25672 username = guest password = guest declare_vhost = / # Used as default for declare / delete only vhost = / # Used as default for declare / delete / list [bad_host] hostname = rabbit.acme.com port = 15672 username = guest password = guest rabbitmq-server-3.2.4/plugins-src/rabbitmq-management/test/src/rabbit_mgmt_test_clustering.erl0000644000000000000000000001041012305126066031540 0ustar rootroot%% The contents of this file are subject to the Mozilla Public License %% Version 1.1 (the "License"); you may not use this file except in %% compliance with the License. You may obtain a copy of the License at %% http://www.mozilla.org/MPL/ %% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the %% License for the specific language governing rights and limitations %% under the License. %% %% The Original Code is RabbitMQ Management Console. %% %% The Initial Developers of the Original Code are Rabbit Technologies Ltd. %% %% Copyright (C) 2010 Rabbit Technologies Ltd. %% %% All Rights Reserved. %% %% Contributor(s): ______________________________________. %% -module(rabbit_mgmt_test_clustering). -include("rabbit_mgmt_test.hrl"). -export([start_second_node/0, stop_second_node/0]). -import(rabbit_mgmt_test_http, [http_get/1, http_put/3, http_delete/2]). -import(rabbit_misc, [pget/2]). %%---------------------------------------------------------------------------- start_second_node() -> start_other_node(hare, 5673), cluster_other_node(hare). stop_second_node() -> stop_other_node(hare). start_other_node(Name, Port) -> %% ?assertCmd seems to hang if you background anything. Bah! Res = os:cmd("make -C " ++ plugin_dir() ++ " OTHER_NODE=" ++ atom_to_list(Name) ++ " OTHER_PORT=" ++ integer_to_list(Port) ++ " start-other-node ; echo $?"), LastLine = hd(lists:reverse(string:tokens(Res, "\n"))), case LastLine of "0" -> ok; _ -> ?debugVal(Res), ?assertEqual("0", LastLine) end. cluster_other_node(Name) -> ?assertCmd("make -C " ++ plugin_dir() ++ " OTHER_NODE=" ++ atom_to_list(Name) ++ " cluster-other-node"). stop_other_node(Name) -> ?assertCmd("make -C " ++ plugin_dir() ++ " OTHER_NODE=" ++ atom_to_list(Name) ++ " stop-other-node"). plugin_dir() -> {ok, [[File]]} = init:get_argument(config), filename:dirname(filename:dirname(File)). %%---------------------------------------------------------------------------- cluster_nodes_test() -> ?assertEqual(2, length(http_get("/nodes"))), ok. ha_test_() -> {timeout, 120, fun ha/0}. ha() -> Policy = [{pattern, <<".*">>}, {definition, [{'ha-mode', <<"all">>}]}], http_put("/policies/%2f/HA", Policy, ?NO_CONTENT), QArgs = [{node, <<"hare">>}], http_put("/queues/%2f/ha-queue", QArgs, ?NO_CONTENT), Q = wait_for("/queues/%2f/ha-queue"), assert_node(hare, pget(node, Q)), assert_single_node('rabbit-test', pget(slave_nodes, Q)), assert_single_node('rabbit-test', pget(synchronised_slave_nodes, Q)), restart_node(), Q2 = wait_for("/queues/%2f/ha-queue"), assert_node('rabbit-test', pget(node, Q2)), assert_single_node(hare, pget(slave_nodes, Q2)), assert_single_node(hare, pget(synchronised_slave_nodes, Q2)), http_delete("/queues/%2f/ha-queue", ?NO_CONTENT), http_delete("/policies/%2f/HA", ?NO_CONTENT), ok. %%---------------------------------------------------------------------------- wait_for(Path) -> wait_for(Path, [slave_nodes, synchronised_slave_nodes]). wait_for(Path, Keys) -> wait_for(Path, Keys, 1000). wait_for(Path, Keys, 0) -> exit({timeout, {Path, Keys}}); wait_for(Path, Keys, Count) -> Res = http_get(Path), case present(Keys, Res) of false -> timer:sleep(10), wait_for(Path, Keys, Count - 1); true -> Res end. present(Keys, Res) -> lists:all(fun (Key) -> X = pget(Key, Res), X =/= [] andalso X =/= undefined end, Keys). assert_single_node(Exp, Act) -> ?assertEqual(1, length(Act)), assert_node(Exp, hd(Act)). assert_nodes(Exp, Act0) -> Act = [read_node(A) || A <- Act0], ?debugVal({Exp, Act}), ?assertEqual(length(Exp), length(Act)), [?assert(lists:member(E, Act)) || E <- Exp]. assert_node(Exp, Act) -> ?assertEqual(Exp, read_node(Act)). read_node(N) -> list_to_atom(hd(string:tokens(binary_to_list(N), "@"))). restart_node() -> stop_second_node(), timer:sleep(1000), start_second_node(). rabbitmq-server-3.2.4/plugins-src/rabbitmq-management/test/src/rabbit_mgmt_test_http.erl0000644000000000000000000014606712305126066030362 0ustar rootroot%% The contents of this file are subject to the Mozilla Public License %% Version 1.1 (the "License"); you may not use this file except in %% compliance with the License. You may obtain a copy of the License at %% http://www.mozilla.org/MPL/ %% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the %% License for the specific language governing rights and limitations %% under the License. %% %% The Original Code is RabbitMQ Management Console. %% %% The Initial Developer of the Original Code is GoPivotal, Inc. %% Copyright (c) 2010-2013 GoPivotal, Inc. All rights reserved. %% -module(rabbit_mgmt_test_http). -include("rabbit_mgmt_test.hrl"). -export([http_get/1, http_put/3, http_delete/2]). -import(rabbit_mgmt_test_util, [assert_list/2, assert_item/2, test_item/2]). -import(rabbit_misc, [pget/2]). overview_test() -> %% Rather crude, but this req doesn't say much and at least this means it %% didn't blow up. true = 0 < length(pget(listeners, http_get("/overview"))), http_put("/users/myuser", [{password, <<"myuser">>}, {tags, <<"management">>}], ?NO_CONTENT), http_get("/overview", "myuser", "myuser", ?OK), http_delete("/users/myuser", ?NO_CONTENT), %% TODO uncomment when priv works in test %%http_get(""), ok. nodes_test() -> http_put("/users/user", [{password, <<"user">>}, {tags, <<"management">>}], ?NO_CONTENT), http_put("/users/monitor", [{password, <<"monitor">>}, {tags, <<"monitoring">>}], ?NO_CONTENT), DiscNode = [{type, <<"disc">>}, {running, true}], assert_list([DiscNode], http_get("/nodes")), assert_list([DiscNode], http_get("/nodes", "monitor", "monitor", ?OK)), http_get("/nodes", "user", "user", ?NOT_AUTHORISED), [Node] = http_get("/nodes"), Path = "/nodes/" ++ binary_to_list(pget(name, Node)), assert_item(DiscNode, http_get(Path, ?OK)), assert_item(DiscNode, http_get(Path, "monitor", "monitor", ?OK)), http_get(Path, "user", "user", ?NOT_AUTHORISED), http_delete("/users/user", ?NO_CONTENT), http_delete("/users/monitor", ?NO_CONTENT), ok. auth_test() -> http_put("/users/user", [{password, <<"user">>}, {tags, <<"">>}], ?NO_CONTENT), test_auth(?NOT_AUTHORISED, []), test_auth(?NOT_AUTHORISED, [auth_header("user", "user")]), test_auth(?NOT_AUTHORISED, [auth_header("guest", "gust")]), test_auth(?OK, [auth_header("guest", "guest")]), http_delete("/users/user", ?NO_CONTENT), ok. %% This test is rather over-verbose as we're trying to test understanding of %% Webmachine vhosts_test() -> assert_list([[{name, <<"/">>}]], http_get("/vhosts")), %% Create a new one http_put("/vhosts/myvhost", none, ?NO_CONTENT), %% PUT should be idempotent http_put("/vhosts/myvhost", none, ?NO_CONTENT), %% Check it's there assert_list([[{name, <<"/">>}], [{name, <<"myvhost">>}]], http_get("/vhosts")), %% Check individually assert_item([{name, <<"/">>}], http_get("/vhosts/%2f", ?OK)), assert_item([{name, <<"myvhost">>}],http_get("/vhosts/myvhost")), %% Delete it http_delete("/vhosts/myvhost", ?NO_CONTENT), %% It's not there http_get("/vhosts/myvhost", ?NOT_FOUND), http_delete("/vhosts/myvhost", ?NOT_FOUND). vhosts_trace_test() -> http_put("/vhosts/myvhost", none, ?NO_CONTENT), Disabled = [{name, <<"myvhost">>}, {tracing, false}], Enabled = [{name, <<"myvhost">>}, {tracing, true}], Disabled = http_get("/vhosts/myvhost"), http_put("/vhosts/myvhost", [{tracing, true}], ?NO_CONTENT), Enabled = http_get("/vhosts/myvhost"), http_put("/vhosts/myvhost", [{tracing, true}], ?NO_CONTENT), Enabled = http_get("/vhosts/myvhost"), http_put("/vhosts/myvhost", [{tracing, false}], ?NO_CONTENT), Disabled = http_get("/vhosts/myvhost"), http_delete("/vhosts/myvhost", ?NO_CONTENT). users_test() -> assert_item([{name, <<"guest">>}, {tags, <<"administrator">>}], http_get("/whoami")), http_get("/users/myuser", ?NOT_FOUND), http_put_raw("/users/myuser", "Something not JSON", ?BAD_REQUEST), http_put("/users/myuser", [{flim, <<"flam">>}], ?BAD_REQUEST), http_put("/users/myuser", [{tags, <<"management">>}], ?NO_CONTENT), http_put("/users/myuser", [{password_hash, <<"not_hash">>}], ?BAD_REQUEST), http_put("/users/myuser", [{password_hash, <<"IECV6PZI/Invh0DL187KFpkO5Jc=">>}, {tags, <<"management">>}], ?NO_CONTENT), http_put("/users/myuser", [{password, <<"password">>}, {tags, <<"administrator, foo">>}], ?NO_CONTENT), assert_item([{name, <<"myuser">>}, {tags, <<"administrator,foo">>}], http_get("/users/myuser")), assert_list([[{name, <<"myuser">>}, {tags, <<"administrator,foo">>}], [{name, <<"guest">>}, {tags, <<"administrator">>}]], http_get("/users")), test_auth(?OK, [auth_header("myuser", "password")]), http_delete("/users/myuser", ?NO_CONTENT), test_auth(?NOT_AUTHORISED, [auth_header("myuser", "password")]), http_get("/users/myuser", ?NOT_FOUND), ok. users_legacy_administrator_test() -> http_put("/users/myuser1", [{administrator, <<"true">>}], ?NO_CONTENT), http_put("/users/myuser2", [{administrator, <<"false">>}], ?NO_CONTENT), assert_item([{name, <<"myuser1">>}, {tags, <<"administrator">>}], http_get("/users/myuser1")), assert_item([{name, <<"myuser2">>}, {tags, <<"">>}], http_get("/users/myuser2")), http_delete("/users/myuser1", ?NO_CONTENT), http_delete("/users/myuser2", ?NO_CONTENT), ok. permissions_validation_test() -> Good = [{configure, <<".*">>}, {write, <<".*">>}, {read, <<".*">>}], http_put("/permissions/wrong/guest", Good, ?BAD_REQUEST), http_put("/permissions/%2f/wrong", Good, ?BAD_REQUEST), http_put("/permissions/%2f/guest", [{configure, <<"[">>}, {write, <<".*">>}, {read, <<".*">>}], ?BAD_REQUEST), http_put("/permissions/%2f/guest", Good, ?NO_CONTENT), ok. permissions_list_test() -> [[{user,<<"guest">>}, {vhost,<<"/">>}, {configure,<<".*">>}, {write,<<".*">>}, {read,<<".*">>}]] = http_get("/permissions"), http_put("/users/myuser1", [{password, <<"">>}, {tags, <<"administrator">>}], ?NO_CONTENT), http_put("/users/myuser2", [{password, <<"">>}, {tags, <<"administrator">>}], ?NO_CONTENT), http_put("/vhosts/myvhost1", none, ?NO_CONTENT), http_put("/vhosts/myvhost2", none, ?NO_CONTENT), Perms = [{configure, <<"foo">>}, {write, <<"foo">>}, {read, <<"foo">>}], http_put("/permissions/myvhost1/myuser1", Perms, ?NO_CONTENT), http_put("/permissions/myvhost2/myuser1", Perms, ?NO_CONTENT), http_put("/permissions/myvhost1/myuser2", Perms, ?NO_CONTENT), 4 = length(http_get("/permissions")), 2 = length(http_get("/users/myuser1/permissions")), 1 = length(http_get("/users/myuser2/permissions")), http_delete("/users/myuser1", ?NO_CONTENT), http_delete("/users/myuser2", ?NO_CONTENT), http_delete("/vhosts/myvhost1", ?NO_CONTENT), http_delete("/vhosts/myvhost2", ?NO_CONTENT), ok. permissions_test() -> http_put("/users/myuser", [{password, <<"myuser">>}, {tags, <<"administrator">>}], ?NO_CONTENT), http_put("/vhosts/myvhost", none, ?NO_CONTENT), http_put("/permissions/myvhost/myuser", [{configure, <<"foo">>}, {write, <<"foo">>}, {read, <<"foo">>}], ?NO_CONTENT), Permission = [{user,<<"myuser">>}, {vhost,<<"myvhost">>}, {configure,<<"foo">>}, {write,<<"foo">>}, {read,<<"foo">>}], Default = [{user,<<"guest">>}, {vhost,<<"/">>}, {configure,<<".*">>}, {write,<<".*">>}, {read,<<".*">>}], Permission = http_get("/permissions/myvhost/myuser"), assert_list([Permission, Default], http_get("/permissions")), assert_list([Permission], http_get("/users/myuser/permissions")), http_delete("/permissions/myvhost/myuser", ?NO_CONTENT), http_get("/permissions/myvhost/myuser", ?NOT_FOUND), http_delete("/users/myuser", ?NO_CONTENT), http_delete("/vhosts/myvhost", ?NO_CONTENT), ok. connections_test() -> {ok, Conn} = amqp_connection:start(#amqp_params_network{}), LocalPort = local_port(Conn), Path = binary_to_list( rabbit_mgmt_format:print( "/connections/127.0.0.1%3A~w%20->%20127.0.0.1%3A5672", [LocalPort])), http_get(Path, ?OK), http_delete(Path, ?NO_CONTENT), %% TODO rabbit_reader:shutdown/2 returns before the connection is %% closed. It may not be worth fixing. timer:sleep(200), http_get(Path, ?NOT_FOUND). test_auth(Code, Headers) -> {ok, {{_, Code, _}, _, _}} = req(get, "/overview", Headers). exchanges_test() -> %% Can pass booleans or strings Good = [{type, <<"direct">>}, {durable, <<"true">>}], http_put("/vhosts/myvhost", none, ?NO_CONTENT), http_get("/exchanges/myvhost/foo", ?NOT_AUTHORISED), http_put("/exchanges/myvhost/foo", Good, ?NOT_AUTHORISED), http_put("/permissions/myvhost/guest", [{configure, <<".*">>}, {write, <<".*">>}, {read, <<".*">>}], ?NO_CONTENT), http_get("/exchanges/myvhost/foo", ?NOT_FOUND), http_put("/exchanges/myvhost/foo", Good, ?NO_CONTENT), http_put("/exchanges/myvhost/foo", Good, ?NO_CONTENT), http_get("/exchanges/%2f/foo", ?NOT_FOUND), assert_item([{name,<<"foo">>}, {vhost,<<"myvhost">>}, {type,<<"direct">>}, {durable,true}, {auto_delete,false}, {internal,false}, {arguments,[]}], http_get("/exchanges/myvhost/foo")), http_put("/exchanges/badvhost/bar", Good, ?NOT_FOUND), http_put("/exchanges/myvhost/bar", [{type, <<"bad_exchange_type">>}], ?BAD_REQUEST), http_put("/exchanges/myvhost/bar", [{type, <<"direct">>}, {durable, <<"troo">>}], ?BAD_REQUEST), http_put("/exchanges/myvhost/foo", [{type, <<"direct">>}], ?BAD_REQUEST), http_delete("/exchanges/myvhost/foo", ?NO_CONTENT), http_delete("/exchanges/myvhost/foo", ?NOT_FOUND), http_delete("/vhosts/myvhost", ?NO_CONTENT), http_get("/exchanges/badvhost", ?NOT_FOUND), ok. queues_test() -> Good = [{durable, true}], http_get("/queues/%2f/foo", ?NOT_FOUND), http_put("/queues/%2f/foo", Good, ?NO_CONTENT), http_put("/queues/%2f/foo", Good, ?NO_CONTENT), http_get("/queues/%2f/foo", ?OK), http_put("/queues/badvhost/bar", Good, ?NOT_FOUND), http_put("/queues/%2f/bar", [{durable, <<"troo">>}], ?BAD_REQUEST), http_put("/queues/%2f/foo", [{durable, false}], ?BAD_REQUEST), http_put("/queues/%2f/baz", Good, ?NO_CONTENT), Queues = http_get("/queues/%2f"), Queue = http_get("/queues/%2f/foo"), assert_list([[{name, <<"foo">>}, {vhost, <<"/">>}, {durable, true}, {auto_delete, false}, {arguments, []}], [{name, <<"baz">>}, {vhost, <<"/">>}, {durable, true}, {auto_delete, false}, {arguments, []}]], Queues), assert_item([{name, <<"foo">>}, {vhost, <<"/">>}, {durable, true}, {auto_delete, false}, {arguments, []}], Queue), http_delete("/queues/%2f/foo", ?NO_CONTENT), http_delete("/queues/%2f/baz", ?NO_CONTENT), http_delete("/queues/%2f/foo", ?NOT_FOUND), http_get("/queues/badvhost", ?NOT_FOUND), ok. bindings_test() -> XArgs = [{type, <<"direct">>}], QArgs = [], http_put("/exchanges/%2f/myexchange", XArgs, ?NO_CONTENT), http_put("/queues/%2f/myqueue", QArgs, ?NO_CONTENT), BArgs = [{routing_key, <<"routing">>}, {arguments, []}], http_post("/bindings/%2f/e/myexchange/q/myqueue", BArgs, ?CREATED), http_get("/bindings/%2f/e/myexchange/q/myqueue/routing", ?OK), http_get("/bindings/%2f/e/myexchange/q/myqueue/rooting", ?NOT_FOUND), Binding = [{source,<<"myexchange">>}, {vhost,<<"/">>}, {destination,<<"myqueue">>}, {destination_type,<<"queue">>}, {routing_key,<<"routing">>}, {arguments,[]}, {properties_key,<<"routing">>}], DBinding = [{source,<<"">>}, {vhost,<<"/">>}, {destination,<<"myqueue">>}, {destination_type,<<"queue">>}, {routing_key,<<"myqueue">>}, {arguments,[]}, {properties_key,<<"myqueue">>}], Binding = http_get("/bindings/%2f/e/myexchange/q/myqueue/routing"), assert_list([Binding], http_get("/bindings/%2f/e/myexchange/q/myqueue")), assert_list([Binding, DBinding], http_get("/queues/%2f/myqueue/bindings")), assert_list([Binding], http_get("/exchanges/%2f/myexchange/bindings/source")), http_delete("/bindings/%2f/e/myexchange/q/myqueue/routing", ?NO_CONTENT), http_delete("/bindings/%2f/e/myexchange/q/myqueue/routing", ?NOT_FOUND), http_delete("/exchanges/%2f/myexchange", ?NO_CONTENT), http_delete("/queues/%2f/myqueue", ?NO_CONTENT), http_get("/bindings/badvhost", ?NOT_FOUND), http_get("/bindings/badvhost/myqueue/myexchange/routing", ?NOT_FOUND), http_get("/bindings/%2f/e/myexchange/q/myqueue/routing", ?NOT_FOUND), ok. bindings_post_test() -> XArgs = [{type, <<"direct">>}], QArgs = [], BArgs = [{routing_key, <<"routing">>}, {arguments, [{foo, <<"bar">>}]}], http_put("/exchanges/%2f/myexchange", XArgs, ?NO_CONTENT), http_put("/queues/%2f/myqueue", QArgs, ?NO_CONTENT), http_post("/bindings/%2f/e/myexchange/q/badqueue", BArgs, ?NOT_FOUND), http_post("/bindings/%2f/e/badexchange/q/myqueue", BArgs, ?NOT_FOUND), Headers1 = http_post("/bindings/%2f/e/myexchange/q/myqueue", [], ?CREATED), "../../../../%2F/e/myexchange/q/myqueue/~" = pget("location", Headers1), Headers2 = http_post("/bindings/%2f/e/myexchange/q/myqueue", BArgs, ?CREATED), PropertiesKey = "routing~V4mGFgnPNrdtRmluZIxTDA", PropertiesKeyBin = list_to_binary(PropertiesKey), "../../../../%2F/e/myexchange/q/myqueue/" ++ PropertiesKey = pget("location", Headers2), URI = "/bindings/%2F/e/myexchange/q/myqueue/" ++ PropertiesKey, [{source,<<"myexchange">>}, {vhost,<<"/">>}, {destination,<<"myqueue">>}, {destination_type,<<"queue">>}, {routing_key,<<"routing">>}, {arguments,[{foo,<<"bar">>}]}, {properties_key,PropertiesKeyBin}] = http_get(URI, ?OK), http_get(URI ++ "x", ?NOT_FOUND), http_delete(URI, ?NO_CONTENT), http_delete("/exchanges/%2f/myexchange", ?NO_CONTENT), http_delete("/queues/%2f/myqueue", ?NO_CONTENT), ok. bindings_e2e_test() -> BArgs = [{routing_key, <<"routing">>}, {arguments, []}], http_post("/bindings/%2f/e/amq.direct/e/badexchange", BArgs, ?NOT_FOUND), http_post("/bindings/%2f/e/badexchange/e/amq.fanout", BArgs, ?NOT_FOUND), Headers = http_post("/bindings/%2f/e/amq.direct/e/amq.fanout", BArgs, ?CREATED), "../../../../%2F/e/amq.direct/e/amq.fanout/routing" = pget("location", Headers), [{source,<<"amq.direct">>}, {vhost,<<"/">>}, {destination,<<"amq.fanout">>}, {destination_type,<<"exchange">>}, {routing_key,<<"routing">>}, {arguments,[]}, {properties_key,<<"routing">>}] = http_get("/bindings/%2f/e/amq.direct/e/amq.fanout/routing", ?OK), http_delete("/bindings/%2f/e/amq.direct/e/amq.fanout/routing", ?NO_CONTENT), http_post("/bindings/%2f/e/amq.direct/e/amq.headers", BArgs, ?CREATED), Binding = [{source,<<"amq.direct">>}, {vhost,<<"/">>}, {destination,<<"amq.headers">>}, {destination_type,<<"exchange">>}, {routing_key,<<"routing">>}, {arguments,[]}, {properties_key,<<"routing">>}], Binding = http_get("/bindings/%2f/e/amq.direct/e/amq.headers/routing"), assert_list([Binding], http_get("/bindings/%2f/e/amq.direct/e/amq.headers")), assert_list([Binding], http_get("/exchanges/%2f/amq.direct/bindings/source")), assert_list([Binding], http_get("/exchanges/%2f/amq.headers/bindings/destination")), http_delete("/bindings/%2f/e/amq.direct/e/amq.headers/routing", ?NO_CONTENT), http_get("/bindings/%2f/e/amq.direct/e/amq.headers/rooting", ?NOT_FOUND), ok. permissions_administrator_test() -> http_put("/users/isadmin", [{password, <<"isadmin">>}, {tags, <<"administrator">>}], ?NO_CONTENT), http_put("/users/notadmin", [{password, <<"notadmin">>}, {tags, <<"administrator">>}], ?NO_CONTENT), http_put("/users/notadmin", [{password, <<"notadmin">>}, {tags, <<"management">>}], ?NO_CONTENT), Test = fun(Path) -> http_get(Path, "notadmin", "notadmin", ?NOT_AUTHORISED), http_get(Path, "isadmin", "isadmin", ?OK), http_get(Path, "guest", "guest", ?OK) end, %% All users can get a list of vhosts. It may be filtered. %%Test("/vhosts"), Test("/vhosts/%2f"), Test("/vhosts/%2f/permissions"), Test("/users"), Test("/users/guest"), Test("/users/guest/permissions"), Test("/permissions"), Test("/permissions/%2f/guest"), http_delete("/users/notadmin", ?NO_CONTENT), http_delete("/users/isadmin", ?NO_CONTENT), ok. permissions_vhost_test() -> QArgs = [], PermArgs = [{configure, <<".*">>}, {write, <<".*">>}, {read, <<".*">>}], http_put("/users/myuser", [{password, <<"myuser">>}, {tags, <<"management">>}], ?NO_CONTENT), http_put("/vhosts/myvhost1", none, ?NO_CONTENT), http_put("/vhosts/myvhost2", none, ?NO_CONTENT), http_put("/permissions/myvhost1/myuser", PermArgs, ?NO_CONTENT), http_put("/permissions/myvhost1/guest", PermArgs, ?NO_CONTENT), http_put("/permissions/myvhost2/guest", PermArgs, ?NO_CONTENT), assert_list([[{name, <<"/">>}], [{name, <<"myvhost1">>}], [{name, <<"myvhost2">>}]], http_get("/vhosts", ?OK)), assert_list([[{name, <<"myvhost1">>}]], http_get("/vhosts", "myuser", "myuser", ?OK)), http_put("/queues/myvhost1/myqueue", QArgs, ?NO_CONTENT), http_put("/queues/myvhost2/myqueue", QArgs, ?NO_CONTENT), Test1 = fun(Path) -> Results = http_get(Path, "myuser", "myuser", ?OK), [case pget(vhost, Result) of <<"myvhost2">> -> throw({got_result_from_vhost2_in, Path, Result}); _ -> ok end || Result <- Results] end, Test2 = fun(Path1, Path2) -> http_get(Path1 ++ "/myvhost1/" ++ Path2, "myuser", "myuser", ?OK), http_get(Path1 ++ "/myvhost2/" ++ Path2, "myuser", "myuser", ?NOT_AUTHORISED) end, Test1("/exchanges"), Test2("/exchanges", ""), Test2("/exchanges", "amq.direct"), Test1("/queues"), Test2("/queues", ""), Test2("/queues", "myqueue"), Test1("/bindings"), Test2("/bindings", ""), Test2("/queues", "myqueue/bindings"), Test2("/exchanges", "amq.default/bindings/source"), Test2("/exchanges", "amq.default/bindings/destination"), Test2("/bindings", "e/amq.default/q/myqueue"), Test2("/bindings", "e/amq.default/q/myqueue/myqueue"), http_delete("/vhosts/myvhost1", ?NO_CONTENT), http_delete("/vhosts/myvhost2", ?NO_CONTENT), http_delete("/users/myuser", ?NO_CONTENT), ok. permissions_amqp_test() -> %% Just test that it works at all, not that it works in all possible cases. QArgs = [], PermArgs = [{configure, <<"foo.*">>}, {write, <<"foo.*">>}, {read, <<"foo.*">>}], http_put("/users/myuser", [{password, <<"myuser">>}, {tags, <<"management">>}], ?NO_CONTENT), http_put("/permissions/%2f/myuser", PermArgs, ?NO_CONTENT), http_put("/queues/%2f/bar-queue", QArgs, "myuser", "myuser", ?NOT_AUTHORISED), http_put("/queues/%2f/bar-queue", QArgs, "nonexistent", "nonexistent", ?NOT_AUTHORISED), http_delete("/users/myuser", ?NO_CONTENT), ok. get_conn(Username, Password) -> {ok, Conn} = amqp_connection:start(#amqp_params_network{ username = list_to_binary(Username), password = list_to_binary(Password)}), LocalPort = local_port(Conn), ConnPath = rabbit_misc:format( "/connections/127.0.0.1%3A~w%20->%20127.0.0.1%3A5672", [LocalPort]), ChPath = rabbit_misc:format( "/channels/127.0.0.1%3A~w%20->%20127.0.0.1%3A5672%20(1)", [LocalPort]), ConnChPath = rabbit_misc:format( "/connections/127.0.0.1%3A~w%20->%20127.0.0.1%3A5672/channels", [LocalPort]), {Conn, ConnPath, ChPath, ConnChPath}. permissions_connection_channel_test() -> PermArgs = [{configure, <<".*">>}, {write, <<".*">>}, {read, <<".*">>}], http_put("/users/user", [{password, <<"user">>}, {tags, <<"management">>}], ?NO_CONTENT), http_put("/permissions/%2f/user", PermArgs, ?NO_CONTENT), http_put("/users/monitor", [{password, <<"monitor">>}, {tags, <<"monitoring">>}], ?NO_CONTENT), http_put("/permissions/%2f/monitor", PermArgs, ?NO_CONTENT), {Conn1, UserConn, UserCh, UserConnCh} = get_conn("user", "user"), {Conn2, MonConn, MonCh, MonConnCh} = get_conn("monitor", "monitor"), {Conn3, AdmConn, AdmCh, AdmConnCh} = get_conn("guest", "guest"), {ok, _Ch1} = amqp_connection:open_channel(Conn1), {ok, _Ch2} = amqp_connection:open_channel(Conn2), {ok, _Ch3} = amqp_connection:open_channel(Conn3), AssertLength = fun (Path, User, Len) -> ?assertEqual(Len, length(http_get(Path, User, User, ?OK))) end, [begin AssertLength(P, "user", 1), AssertLength(P, "monitor", 3), AssertLength(P, "guest", 3) end || P <- ["/connections", "/channels"]], AssertRead = fun(Path, UserStatus) -> http_get(Path, "user", "user", UserStatus), http_get(Path, "monitor", "monitor", ?OK), http_get(Path, ?OK) end, AssertRead(UserConn, ?OK), AssertRead(MonConn, ?NOT_AUTHORISED), AssertRead(AdmConn, ?NOT_AUTHORISED), AssertRead(UserCh, ?OK), AssertRead(MonCh, ?NOT_AUTHORISED), AssertRead(AdmCh, ?NOT_AUTHORISED), AssertRead(UserConnCh, ?OK), AssertRead(MonConnCh, ?NOT_AUTHORISED), AssertRead(AdmConnCh, ?NOT_AUTHORISED), AssertClose = fun(Path, User, Status) -> http_delete(Path, User, User, Status) end, AssertClose(UserConn, "monitor", ?NOT_AUTHORISED), AssertClose(MonConn, "user", ?NOT_AUTHORISED), AssertClose(AdmConn, "guest", ?NO_CONTENT), AssertClose(MonConn, "guest", ?NO_CONTENT), AssertClose(UserConn, "user", ?NO_CONTENT), http_delete("/users/user", ?NO_CONTENT), http_delete("/users/monitor", ?NO_CONTENT), http_get("/connections/foo", ?NOT_FOUND), http_get("/channels/foo", ?NOT_FOUND), ok. unicode_test() -> QArgs = [], http_put("/queues/%2f/♫♪♫♪", QArgs, ?NO_CONTENT), http_get("/queues/%2f/♫♪♫♪", ?OK), http_delete("/queues/%2f/♫♪♫♪", ?NO_CONTENT), ok. defs(Key, URI, CreateMethod, Args) -> defs(Key, URI, CreateMethod, Args, fun(URI2) -> http_delete(URI2, ?NO_CONTENT) end). defs_v(Key, URI, CreateMethod, Args) -> Rep1 = fun (S, S2) -> re:replace(S, "", S2, [{return, list}]) end, Rep2 = fun (L, V2) -> lists:keymap(fun (vhost) -> V2; (V) -> V end, 2, L) end, %% Test against default vhost defs(Key, Rep1(URI, "%2f"), CreateMethod, Rep2(Args, <<"/">>)), %% Test against new vhost http_put("/vhosts/test", none, ?NO_CONTENT), PermArgs = [{configure, <<".*">>}, {write, <<".*">>}, {read, <<".*">>}], http_put("/permissions/test/guest", PermArgs, ?NO_CONTENT), defs(Key, Rep1(URI, "test"), CreateMethod, Rep2(Args, <<"test">>), fun(URI2) -> http_delete(URI2, ?NO_CONTENT), http_delete("/vhosts/test", ?NO_CONTENT) end). defs(Key, URI, CreateMethod, Args, DeleteFun) -> %% Create the item URI2 = case CreateMethod of put -> http_put(URI, Args, ?NO_CONTENT), URI; post -> Headers = http_post(URI, Args, ?CREATED), rabbit_web_dispatch_util:unrelativise( URI, pget("location", Headers)) end, %% Make sure it ends up in definitions Definitions = http_get("/definitions", ?OK), true = lists:any(fun(I) -> test_item(Args, I) end, pget(Key, Definitions)), %% Delete it DeleteFun(URI2), %% Post the definitions back, it should get recreated in correct form http_post("/definitions", Definitions, ?CREATED), assert_item(Args, http_get(URI2, ?OK)), %% And delete it again DeleteFun(URI2), ok. definitions_test() -> rabbit_runtime_parameters_test:register(), rabbit_runtime_parameters_test:register_policy_validator(), defs_v(queues, "/queues//my-queue", put, [{name, <<"my-queue">>}, {durable, true}]), defs_v(exchanges, "/exchanges//my-exchange", put, [{name, <<"my-exchange">>}, {type, <<"direct">>}]), defs_v(bindings, "/bindings//e/amq.direct/e/amq.fanout", post, [{routing_key, <<"routing">>}, {arguments, []}]), defs_v(policies, "/policies//my-policy", put, [{vhost, vhost}, {name, <<"my-policy">>}, {pattern, <<".*">>}, {definition, [{testpos, [1, 2, 3]}]}, {priority, 1}]), defs_v(parameters, "/parameters/test//good", put, [{vhost, vhost}, {component, <<"test">>}, {name, <<"good">>}, {value, <<"ignore">>}]), defs(users, "/users/myuser", put, [{name, <<"myuser">>}, {password_hash, <<"WAbU0ZIcvjTpxM3Q3SbJhEAM2tQ=">>}, {tags, <<"management">>}]), defs(vhosts, "/vhosts/myvhost", put, [{name, <<"myvhost">>}]), defs(permissions, "/permissions/%2f/guest", put, [{user, <<"guest">>}, {vhost, <<"/">>}, {configure, <<"c">>}, {write, <<"w">>}, {read, <<"r">>}]), %% We just messed with guest's permissions http_put("/permissions/%2f/guest", [{configure, <<".*">>}, {write, <<".*">>}, {read, <<".*">>}], ?NO_CONTENT), BrokenConfig = [{users, []}, {vhosts, []}, {permissions, []}, {queues, []}, {exchanges, [[{name, <<"amq.direct">>}, {vhost, <<"/">>}, {type, <<"definitely not direct">>}, {durable, true}, {auto_delete, false}, {arguments, []} ]]}, {bindings, []}], http_post("/definitions", BrokenConfig, ?BAD_REQUEST), rabbit_runtime_parameters_test:unregister_policy_validator(), rabbit_runtime_parameters_test:unregister(), ok. definitions_remove_things_test() -> {ok, Conn} = amqp_connection:start(#amqp_params_network{}), {ok, Ch} = amqp_connection:open_channel(Conn), amqp_channel:call(Ch, #'queue.declare'{ queue = <<"my-exclusive">>, exclusive = true }), http_get("/queues/%2f/my-exclusive", ?OK), Definitions = http_get("/definitions", ?OK), [] = pget(queues, Definitions), [] = pget(exchanges, Definitions), [] = pget(bindings, Definitions), amqp_channel:close(Ch), amqp_connection:close(Conn), ok. definitions_server_named_queue_test() -> {ok, Conn} = amqp_connection:start(#amqp_params_network{}), {ok, Ch} = amqp_connection:open_channel(Conn), #'queue.declare_ok'{ queue = QName } = amqp_channel:call(Ch, #'queue.declare'{}), amqp_channel:close(Ch), amqp_connection:close(Conn), Path = "/queues/%2f/" ++ mochiweb_util:quote_plus(QName), http_get(Path, ?OK), Definitions = http_get("/definitions", ?OK), http_delete(Path, ?NO_CONTENT), http_get(Path, ?NOT_FOUND), http_post("/definitions", Definitions, ?CREATED), http_get(Path, ?OK), http_delete(Path, ?NO_CONTENT), ok. aliveness_test() -> [{status, <<"ok">>}] = http_get("/aliveness-test/%2f", ?OK), http_get("/aliveness-test/foo", ?NOT_FOUND), http_delete("/queues/%2f/aliveness-test", ?NO_CONTENT), ok. arguments_test() -> XArgs = [{type, <<"headers">>}, {arguments, [{'alternate-exchange', <<"amq.direct">>}]}], QArgs = [{arguments, [{'x-expires', 1800000}]}], BArgs = [{routing_key, <<"">>}, {arguments, [{'x-match', <<"all">>}, {foo, <<"bar">>}]}], http_put("/exchanges/%2f/myexchange", XArgs, ?NO_CONTENT), http_put("/queues/%2f/myqueue", QArgs, ?NO_CONTENT), http_post("/bindings/%2f/e/myexchange/q/myqueue", BArgs, ?CREATED), Definitions = http_get("/definitions", ?OK), http_delete("/exchanges/%2f/myexchange", ?NO_CONTENT), http_delete("/queues/%2f/myqueue", ?NO_CONTENT), http_post("/definitions", Definitions, ?CREATED), [{'alternate-exchange', <<"amq.direct">>}] = pget(arguments, http_get("/exchanges/%2f/myexchange", ?OK)), [{'x-expires', 1800000}] = pget(arguments, http_get("/queues/%2f/myqueue", ?OK)), true = lists:sort([{'x-match', <<"all">>}, {foo, <<"bar">>}]) =:= lists:sort(pget(arguments, http_get("/bindings/%2f/e/myexchange/q/myqueue/" ++ "~nXOkVwqZzUOdS9_HcBWheg", ?OK))), http_delete("/exchanges/%2f/myexchange", ?NO_CONTENT), http_delete("/queues/%2f/myqueue", ?NO_CONTENT), ok. arguments_table_test() -> Args = [{'upstreams', [<<"amqp://localhost/%2f/upstream1">>, <<"amqp://localhost/%2f/upstream2">>]}], XArgs = [{type, <<"headers">>}, {arguments, Args}], http_put("/exchanges/%2f/myexchange", XArgs, ?NO_CONTENT), Definitions = http_get("/definitions", ?OK), http_delete("/exchanges/%2f/myexchange", ?NO_CONTENT), http_post("/definitions", Definitions, ?CREATED), Args = pget(arguments, http_get("/exchanges/%2f/myexchange", ?OK)), http_delete("/exchanges/%2f/myexchange", ?NO_CONTENT), ok. queue_purge_test() -> QArgs = [], http_put("/queues/%2f/myqueue", QArgs, ?NO_CONTENT), {ok, Conn} = amqp_connection:start(#amqp_params_network{}), {ok, Ch} = amqp_connection:open_channel(Conn), Publish = fun() -> amqp_channel:call( Ch, #'basic.publish'{exchange = <<"">>, routing_key = <<"myqueue">>}, #amqp_msg{payload = <<"message">>}) end, Publish(), Publish(), amqp_channel:call( Ch, #'queue.declare'{queue = <<"exclusive">>, exclusive = true}), {#'basic.get_ok'{}, _} = amqp_channel:call(Ch, #'basic.get'{queue = <<"myqueue">>}), http_delete("/queues/%2f/myqueue/contents", ?NO_CONTENT), http_delete("/queues/%2f/badqueue/contents", ?NOT_FOUND), http_delete("/queues/%2f/exclusive/contents", ?BAD_REQUEST), http_delete("/queues/%2f/exclusive", ?BAD_REQUEST), #'basic.get_empty'{} = amqp_channel:call(Ch, #'basic.get'{queue = <<"myqueue">>}), amqp_channel:close(Ch), amqp_connection:close(Conn), http_delete("/queues/%2f/myqueue", ?NO_CONTENT), ok. queue_actions_test() -> http_put("/queues/%2f/q", [], ?NO_CONTENT), http_post("/queues/%2f/q/actions", [{action, sync}], ?NO_CONTENT), http_post("/queues/%2f/q/actions", [{action, cancel_sync}], ?NO_CONTENT), http_post("/queues/%2f/q/actions", [{action, change_colour}], ?BAD_REQUEST), http_delete("/queues/%2f/q", ?NO_CONTENT), ok. exclusive_consumer_test() -> {ok, Conn} = amqp_connection:start(#amqp_params_network{}), {ok, Ch} = amqp_connection:open_channel(Conn), #'queue.declare_ok'{ queue = QName } = amqp_channel:call(Ch, #'queue.declare'{exclusive = true}), amqp_channel:subscribe(Ch, #'basic.consume'{queue = QName, exclusive = true}, self()), timer:sleep(1000), %% Sadly we need to sleep to let the stats update http_get("/queues/%2f/"), %% Just check we don't blow up amqp_channel:close(Ch), amqp_connection:close(Conn), ok. sorting_test() -> QArgs = [], PermArgs = [{configure, <<".*">>}, {write, <<".*">>}, {read, <<".*">>}], http_put("/vhosts/vh1", none, ?NO_CONTENT), http_put("/permissions/vh1/guest", PermArgs, ?NO_CONTENT), http_put("/queues/%2f/test0", QArgs, ?NO_CONTENT), http_put("/queues/vh1/test1", QArgs, ?NO_CONTENT), http_put("/queues/%2f/test2", QArgs, ?NO_CONTENT), http_put("/queues/vh1/test3", QArgs, ?NO_CONTENT), assert_list([[{name, <<"test0">>}], [{name, <<"test2">>}], [{name, <<"test1">>}], [{name, <<"test3">>}]], http_get("/queues", ?OK)), assert_list([[{name, <<"test0">>}], [{name, <<"test1">>}], [{name, <<"test2">>}], [{name, <<"test3">>}]], http_get("/queues?sort=name", ?OK)), assert_list([[{name, <<"test0">>}], [{name, <<"test2">>}], [{name, <<"test1">>}], [{name, <<"test3">>}]], http_get("/queues?sort=vhost", ?OK)), assert_list([[{name, <<"test3">>}], [{name, <<"test1">>}], [{name, <<"test2">>}], [{name, <<"test0">>}]], http_get("/queues?sort_reverse=true", ?OK)), assert_list([[{name, <<"test3">>}], [{name, <<"test2">>}], [{name, <<"test1">>}], [{name, <<"test0">>}]], http_get("/queues?sort=name&sort_reverse=true", ?OK)), assert_list([[{name, <<"test3">>}], [{name, <<"test1">>}], [{name, <<"test2">>}], [{name, <<"test0">>}]], http_get("/queues?sort=vhost&sort_reverse=true", ?OK)), %% Rather poor but at least test it doesn't blow up with dots http_get("/queues?sort=owner_pid_details.name", ?OK), http_delete("/queues/%2f/test0", ?NO_CONTENT), http_delete("/queues/vh1/test1", ?NO_CONTENT), http_delete("/queues/%2f/test2", ?NO_CONTENT), http_delete("/queues/vh1/test3", ?NO_CONTENT), http_delete("/vhosts/vh1", ?NO_CONTENT), ok. columns_test() -> http_put("/queues/%2f/test", [{arguments, [{<<"foo">>, <<"bar">>}]}], ?NO_CONTENT), [[{name, <<"test">>}, {arguments, [{foo, <<"bar">>}]}]] = http_get("/queues?columns=arguments.foo,name", ?OK), [{name, <<"test">>}, {arguments, [{foo, <<"bar">>}]}] = http_get("/queues/%2f/test?columns=arguments.foo,name", ?OK), http_delete("/queues/%2f/test", ?NO_CONTENT), ok. get_test() -> %% Real world example... Headers = [{<<"x-forwarding">>, array, [{table, [{<<"uri">>, longstr, <<"amqp://localhost/%2f/upstream">>}]}]}], http_put("/queues/%2f/myqueue", [], ?NO_CONTENT), {ok, Conn} = amqp_connection:start(#amqp_params_network{}), {ok, Ch} = amqp_connection:open_channel(Conn), Publish = fun (Payload) -> amqp_channel:cast( Ch, #'basic.publish'{exchange = <<>>, routing_key = <<"myqueue">>}, #amqp_msg{props = #'P_basic'{headers = Headers}, payload = Payload}) end, Publish(<<"1aaa">>), Publish(<<"2aaa">>), Publish(<<"3aaa">>), amqp_connection:close(Conn), [Msg] = http_post("/queues/%2f/myqueue/get", [{requeue, false}, {count, 1}, {encoding, auto}, {truncate, 1}], ?OK), false = pget(redelivered, Msg), <<>> = pget(exchange, Msg), <<"myqueue">> = pget(routing_key, Msg), <<"1">> = pget(payload, Msg), [{'x-forwarding', [[{uri,<<"amqp://localhost/%2f/upstream">>}]]}] = pget(headers, pget(properties, Msg)), [M2, M3] = http_post("/queues/%2f/myqueue/get", [{requeue, true}, {count, 5}, {encoding, auto}], ?OK), <<"2aaa">> = pget(payload, M2), <<"3aaa">> = pget(payload, M3), 2 = length(http_post("/queues/%2f/myqueue/get", [{requeue, false}, {count, 5}, {encoding, auto}], ?OK)), [] = http_post("/queues/%2f/myqueue/get", [{requeue, false}, {count, 5}, {encoding, auto}], ?OK), http_delete("/queues/%2f/myqueue", ?NO_CONTENT), ok. get_fail_test() -> http_put("/users/myuser", [{password, <<"password">>}, {tags, <<"management">>}], ?NO_CONTENT), http_put("/queues/%2f/myqueue", [], ?NO_CONTENT), http_post("/queues/%2f/myqueue/get", [{requeue, false}, {count, 1}, {encoding, auto}], "myuser", "password", ?NOT_AUTHORISED), http_delete("/queues/%2f/myqueue", ?NO_CONTENT), http_delete("/users/myuser", ?NO_CONTENT), ok. publish_test() -> Headers = [{'x-forwarding', [[{uri,<<"amqp://localhost/%2f/upstream">>}]]}], Msg = msg(<<"myqueue">>, Headers, <<"Hello world">>), http_put("/queues/%2f/myqueue", [], ?NO_CONTENT), ?assertEqual([{routed, true}], http_post("/exchanges/%2f/amq.default/publish", Msg, ?OK)), [Msg2] = http_post("/queues/%2f/myqueue/get", [{requeue, false}, {count, 1}, {encoding, auto}], ?OK), assert_item(Msg, Msg2), http_post("/exchanges/%2f/amq.default/publish", Msg2, ?OK), [Msg3] = http_post("/queues/%2f/myqueue/get", [{requeue, false}, {count, 1}, {encoding, auto}], ?OK), assert_item(Msg, Msg3), http_delete("/queues/%2f/myqueue", ?NO_CONTENT), ok. publish_fail_test() -> Msg = msg(<<"myqueue">>, [], <<"Hello world">>), http_put("/queues/%2f/myqueue", [], ?NO_CONTENT), http_put("/users/myuser", [{password, <<"password">>}, {tags, <<"management">>}], ?NO_CONTENT), http_post("/exchanges/%2f/amq.default/publish", Msg, "myuser", "password", ?NOT_AUTHORISED), Msg2 = [{exchange, <<"">>}, {routing_key, <<"myqueue">>}, {properties, [{user_id, <<"foo">>}]}, {payload, <<"Hello world">>}, {payload_encoding, <<"string">>}], http_post("/exchanges/%2f/amq.default/publish", Msg2, ?BAD_REQUEST), Msg3 = [{exchange, <<"">>}, {routing_key, <<"myqueue">>}, {properties, []}, {payload, [<<"not a string">>]}, {payload_encoding, <<"string">>}], http_post("/exchanges/%2f/amq.default/publish", Msg3, ?BAD_REQUEST), http_delete("/users/myuser", ?NO_CONTENT), ok. publish_base64_test() -> Msg = msg(<<"myqueue">>, [], <<"YWJjZA==">>, <<"base64">>), BadMsg1 = msg(<<"myqueue">>, [], <<"flibble">>, <<"base64">>), BadMsg2 = msg(<<"myqueue">>, [], <<"YWJjZA==">>, <<"base99">>), http_put("/queues/%2f/myqueue", [], ?NO_CONTENT), http_post("/exchanges/%2f/amq.default/publish", Msg, ?OK), http_post("/exchanges/%2f/amq.default/publish", BadMsg1, ?BAD_REQUEST), http_post("/exchanges/%2f/amq.default/publish", BadMsg2, ?BAD_REQUEST), [Msg2] = http_post("/queues/%2f/myqueue/get", [{requeue, false}, {count, 1}, {encoding, auto}], ?OK), ?assertEqual(<<"abcd">>, pget(payload, Msg2)), http_delete("/queues/%2f/myqueue", ?NO_CONTENT), ok. publish_unrouted_test() -> Msg = msg(<<"hmmm">>, [], <<"Hello world">>), ?assertEqual([{routed, false}], http_post("/exchanges/%2f/amq.default/publish", Msg, ?OK)). parameters_test() -> rabbit_runtime_parameters_test:register(), http_put("/parameters/test/%2f/good", [{value, <<"ignore">>}], ?NO_CONTENT), http_put("/parameters/test/%2f/maybe", [{value, <<"good">>}], ?NO_CONTENT), http_put("/parameters/test/%2f/maybe", [{value, <<"bad">>}], ?BAD_REQUEST), http_put("/parameters/test/%2f/bad", [{value, <<"good">>}], ?BAD_REQUEST), http_put("/parameters/test/um/good", [{value, <<"ignore">>}], ?NOT_FOUND), Good = [{vhost, <<"/">>}, {component, <<"test">>}, {name, <<"good">>}, {value, <<"ignore">>}], Maybe = [{vhost, <<"/">>}, {component, <<"test">>}, {name, <<"maybe">>}, {value, <<"good">>}], List = [Good, Maybe], assert_list(List, http_get("/parameters")), assert_list(List, http_get("/parameters/test")), assert_list(List, http_get("/parameters/test/%2f")), assert_list([], http_get("/parameters/oops")), http_get("/parameters/test/oops", ?NOT_FOUND), assert_item(Good, http_get("/parameters/test/%2f/good", ?OK)), assert_item(Maybe, http_get("/parameters/test/%2f/maybe", ?OK)), http_delete("/parameters/test/%2f/good", ?NO_CONTENT), http_delete("/parameters/test/%2f/maybe", ?NO_CONTENT), http_delete("/parameters/test/%2f/bad", ?NOT_FOUND), 0 = length(http_get("/parameters")), 0 = length(http_get("/parameters/test")), 0 = length(http_get("/parameters/test/%2f")), rabbit_runtime_parameters_test:unregister(), ok. policy_test() -> rabbit_runtime_parameters_test:register_policy_validator(), PolicyPos = [{vhost, <<"/">>}, {name, <<"policy_pos">>}, {pattern, <<".*">>}, {definition, [{testpos,[1,2,3]}]}, {priority, 10}], PolicyEven = [{vhost, <<"/">>}, {name, <<"policy_even">>}, {pattern, <<".*">>}, {definition, [{testeven,[1,2,3,4]}]}, {priority, 10}], http_put( "/policies/%2f/policy_pos", lists:keydelete(key, 1, PolicyPos), ?NO_CONTENT), http_put( "/policies/%2f/policy_even", lists:keydelete(key, 1, PolicyEven), ?NO_CONTENT), assert_item(PolicyPos, http_get("/policies/%2f/policy_pos", ?OK)), assert_item(PolicyEven, http_get("/policies/%2f/policy_even", ?OK)), List = [PolicyPos, PolicyEven], assert_list(List, http_get("/policies", ?OK)), assert_list(List, http_get("/policies/%2f", ?OK)), http_delete("/policies/%2f/policy_pos", ?NO_CONTENT), http_delete("/policies/%2f/policy_even", ?NO_CONTENT), 0 = length(http_get("/policies")), 0 = length(http_get("/policies/%2f")), rabbit_runtime_parameters_test:unregister_policy_validator(), ok. policy_permissions_test() -> rabbit_runtime_parameters_test:register(), http_put("/users/admin", [{password, <<"admin">>}, {tags, <<"administrator">>}], ?NO_CONTENT), http_put("/users/mon", [{password, <<"monitor">>}, {tags, <<"monitoring">>}], ?NO_CONTENT), http_put("/users/policy", [{password, <<"policy">>}, {tags, <<"policymaker">>}], ?NO_CONTENT), http_put("/users/mgmt", [{password, <<"mgmt">>}, {tags, <<"management">>}], ?NO_CONTENT), Perms = [{configure, <<".*">>}, {write, <<".*">>}, {read, <<".*">>}], http_put("/vhosts/v", none, ?NO_CONTENT), http_put("/permissions/v/admin", Perms, ?NO_CONTENT), http_put("/permissions/v/mon", Perms, ?NO_CONTENT), http_put("/permissions/v/policy", Perms, ?NO_CONTENT), http_put("/permissions/v/mgmt", Perms, ?NO_CONTENT), Policy = [{pattern, <<".*">>}, {definition, [{<<"ha-mode">>, <<"all">>}]}], Param = [{value, <<"">>}], http_put("/policies/%2f/HA", Policy, ?NO_CONTENT), http_put("/parameters/test/%2f/good", Param, ?NO_CONTENT), Pos = fun (U) -> http_put("/policies/v/HA", Policy, U, U, ?NO_CONTENT), http_put( "/parameters/test/v/good", Param, U, U, ?NO_CONTENT), 1 = length(http_get("/policies", U, U, ?OK)), 1 = length(http_get("/parameters/test", U, U, ?OK)), 1 = length(http_get("/parameters", U, U, ?OK)), 1 = length(http_get("/policies/v", U, U, ?OK)), 1 = length(http_get("/parameters/test/v", U, U, ?OK)), http_get("/policies/v/HA", U, U, ?OK), http_get("/parameters/test/v/good", U, U, ?OK) end, Neg = fun (U) -> http_put("/policies/v/HA", Policy, U, U, ?NOT_AUTHORISED), http_put( "/parameters/test/v/good", Param, U, U, ?NOT_AUTHORISED), http_get("/policies", U, U, ?NOT_AUTHORISED), http_get("/policies/v", U, U, ?NOT_AUTHORISED), http_get("/parameters", U, U, ?NOT_AUTHORISED), http_get("/parameters/test", U, U, ?NOT_AUTHORISED), http_get("/parameters/test/v", U, U, ?NOT_AUTHORISED), http_get("/policies/v/HA", U, U, ?NOT_AUTHORISED), http_get("/parameters/test/v/good", U, U, ?NOT_AUTHORISED) end, AlwaysNeg = fun (U) -> http_put("/policies/%2f/HA", Policy, U, U, ?NOT_AUTHORISED), http_put( "/parameters/test/%2f/good", Param, U, U, ?NOT_AUTHORISED), http_get("/policies/%2f/HA", U, U, ?NOT_AUTHORISED), http_get("/parameters/test/%2f/good", U, U, ?NOT_AUTHORISED) end, [Neg(U) || U <- ["mon", "mgmt"]], [Pos(U) || U <- ["admin", "policy"]], [AlwaysNeg(U) || U <- ["mon", "mgmt", "admin", "policy"]], http_delete("/vhosts/v", ?NO_CONTENT), http_delete("/users/admin", ?NO_CONTENT), http_delete("/users/mon", ?NO_CONTENT), http_delete("/users/policy", ?NO_CONTENT), http_delete("/users/mgmt", ?NO_CONTENT), http_delete("/policies/%2f/HA", ?NO_CONTENT), rabbit_runtime_parameters_test:unregister(), ok. extensions_test() -> [[{javascript,<<"dispatcher.js">>}]] = http_get("/extensions", ?OK), ok. %%--------------------------------------------------------------------------- msg(Key, Headers, Body) -> msg(Key, Headers, Body, <<"string">>). msg(Key, Headers, Body, Enc) -> [{exchange, <<"">>}, {routing_key, Key}, {properties, [{delivery_mode, 2}, {headers, Headers}]}, {payload, Body}, {payload_encoding, Enc}]. local_port(Conn) -> [{sock, Sock}] = amqp_connection:info(Conn, [sock]), {ok, Port} = inet:port(Sock), Port. %%--------------------------------------------------------------------------- http_get(Path) -> http_get(Path, ?OK). http_get(Path, CodeExp) -> http_get(Path, "guest", "guest", CodeExp). http_get(Path, User, Pass, CodeExp) -> {ok, {{_HTTP, CodeAct, _}, Headers, ResBody}} = req(get, Path, [auth_header(User, Pass)]), assert_code(CodeExp, CodeAct, "GET", Path, ResBody), decode(CodeExp, Headers, ResBody). http_put(Path, List, CodeExp) -> http_put_raw(Path, format_for_upload(List), CodeExp). http_put(Path, List, User, Pass, CodeExp) -> http_put_raw(Path, format_for_upload(List), User, Pass, CodeExp). http_post(Path, List, CodeExp) -> http_post_raw(Path, format_for_upload(List), CodeExp). http_post(Path, List, User, Pass, CodeExp) -> http_post_raw(Path, format_for_upload(List), User, Pass, CodeExp). format_for_upload(none) -> <<"">>; format_for_upload(List) -> iolist_to_binary(mochijson2:encode({struct, List})). http_put_raw(Path, Body, CodeExp) -> http_upload_raw(put, Path, Body, "guest", "guest", CodeExp). http_put_raw(Path, Body, User, Pass, CodeExp) -> http_upload_raw(put, Path, Body, User, Pass, CodeExp). http_post_raw(Path, Body, CodeExp) -> http_upload_raw(post, Path, Body, "guest", "guest", CodeExp). http_post_raw(Path, Body, User, Pass, CodeExp) -> http_upload_raw(post, Path, Body, User, Pass, CodeExp). http_upload_raw(Type, Path, Body, User, Pass, CodeExp) -> {ok, {{_HTTP, CodeAct, _}, Headers, ResBody}} = req(Type, Path, [auth_header(User, Pass)], Body), assert_code(CodeExp, CodeAct, Type, Path, ResBody), decode(CodeExp, Headers, ResBody). http_delete(Path, CodeExp) -> http_delete(Path, "guest", "guest", CodeExp). http_delete(Path, User, Pass, CodeExp) -> {ok, {{_HTTP, CodeAct, _}, Headers, ResBody}} = req(delete, Path, [auth_header(User, Pass)]), assert_code(CodeExp, CodeAct, "DELETE", Path, ResBody), decode(CodeExp, Headers, ResBody). assert_code(CodeExp, CodeAct, Type, Path, Body) -> case CodeExp of CodeAct -> ok; _ -> throw({expected, CodeExp, got, CodeAct, type, Type, path, Path, body, Body}) end. req(Type, Path, Headers) -> httpc:request(Type, {?PREFIX ++ Path, Headers}, ?HTTPC_OPTS, []). req(Type, Path, Headers, Body) -> httpc:request(Type, {?PREFIX ++ Path, Headers, "application/json", Body}, ?HTTPC_OPTS, []). decode(?OK, _Headers, ResBody) -> cleanup(mochijson2:decode(ResBody)); decode(_, Headers, _ResBody) -> Headers. cleanup(L) when is_list(L) -> [cleanup(I) || I <- L]; cleanup({struct, I}) -> cleanup(I); cleanup({K, V}) when is_binary(K) -> {list_to_atom(binary_to_list(K)), cleanup(V)}; cleanup(I) -> I. auth_header(Username, Password) -> {"Authorization", "Basic " ++ binary_to_list(base64:encode(Username ++ ":" ++ Password))}. rabbitmq-server-3.2.4/plugins-src/rabbitmq-management/test/src/rabbit_mgmt_test_db_unit.erl0000644000000000000000000001110312305126066031005 0ustar rootroot%% The contents of this file are subject to the Mozilla Public License %% Version 1.1 (the "License"); you may not use this file except in %% compliance with the License. You may obtain a copy of the License at %% http://www.mozilla.org/MPL/ %% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the %% License for the specific language governing rights and limitations %% under the License. %% %% The Original Code is RabbitMQ Management Console. %% %% The Initial Developer of the Original Code is GoPivotal, Inc. %% Copyright (c) 2010-2012 GoPivotal, Inc. All rights reserved. %% -module(rabbit_mgmt_test_db_unit). -include("rabbit_mgmt.hrl"). -include_lib("eunit/include/eunit.hrl"). gc_test() -> T = fun (Before, After) -> ?assertEqual(After, unstats( rabbit_mgmt_stats:gc( cutoff(), stats(Before)))) end, %% Cut off old sample, move to base T({[{8999, 123}, {9000, 456}], 0}, {[{9000, 456}], 123}), %% Amalgamate old samples to rounder one T({[{9001, 100}, {9010, 020}, {10000, 003}], 0}, {[{10000, 123}], 0}), %% The same, but a bit less T({[{9000, 100}, {9901, 020}, {9910, 003}], 0}, {[{9000, 100}, {9910, 023}], 0}), %% Nothing needs to be done T({[{9000, 100}, {9990, 020}, {9991, 003}], 0}, {[{9000, 100}, {9990, 020}, {9991, 003}], 0}), %% Invent a newer sample that's acceptable T({[{9001, 10}, {9010, 02}], 0}, {[{9100, 12}], 0}), %% ...but don't if it's too old T({[{8001, 10}, {8010, 02}], 0}, {[], 12}), ok. format_test() -> Interval = 10, T = fun ({First, Last, Incr}, Stats, Results) -> ?assertEqual(format(Results), rabbit_mgmt_stats:format( #range{first = First * 1000, last = Last * 1000, incr = Incr * 1000}, stats(Stats), Interval * 1000)) end, %% Just three samples, all of which we format. Note the %% instantaneous rate is taken from the penultimate sample. T({10, 30, 10}, {[{10, 10}, {20, 20}, {30, 30}], 1}, {[{30, 61}, {20, 31}, {10, 11}], 2.0, 2.5, 103/3, 61}), %% Skip over the second (and ditto). T({10, 30, 20}, {[{10, 10}, {20, 20}, {30, 30}], 1}, {[{30, 61}, {10, 11}], 2.0, 2.5, 36.0, 61}), %% Skip over some and invent some. Note that the instantaneous %% rate drops to 0 since the last event is now in the past. T({0, 40, 20}, {[{10, 10}, {20, 20}, {30, 30}], 1}, {[{40, 61}, {20, 31}, {0, 1}], 0.0, 1.5, 31.0, 61}), %% And a case where the range starts after the samples T({20, 40, 10}, {[{10, 10}, {20, 20}, {30, 30}], 1}, {[{40, 61}, {30, 61}, {20, 31}], 0.0, 1.5, 51.0, 61}), %% A single sample - which should lead to some bits not getting generated T({10, 10, 10}, {[{10, 10}, {20, 20}, {30, 30}], 1}, {[{10, 11}], 0.0, 11}), %% No samples - which should also lead to some bits not getting generated T({10, 0, 10}, {[{10, 10}, {20, 20}, {30, 30}], 1}, {[], 0.0, 1}), %% TODO more? ok. format_no_range_test() -> Interval = 10, T = fun (Stats, Results) -> ?assertEqual(format(Results), rabbit_mgmt_stats:format( no_range, stats(Stats), Interval * 1000)) end, %% Just three samples T({[{10, 10}, {20, 20}, {30, 30}], 1}, {0.0, 61}), ok. %%-------------------------------------------------------------------- cutoff() -> {[{10, 1}, {100, 10}, {1000, 100}], %% Sec 10000000}. %% Millis stats({Diffs, Base}) -> #stats{diffs = gb_trees:from_orddict(secs_to_millis(Diffs)), base = Base}. unstats(#stats{diffs = Diffs, base = Base}) -> {millis_to_secs(gb_trees:to_list(Diffs)), Base}. secs_to_millis(L) -> [{TS * 1000, S} || {TS, S} <- L]. millis_to_secs(L) -> [{TS div 1000, S} || {TS, S} <- L]. format({Rate, Count}) -> {[{rate, Rate}], Count}; format({Samples, Rate, Count}) -> {[{rate, Rate}, {samples, format_samples(Samples)}], Count}; format({Samples, Rate, AvgRate, Avg, Count}) -> {[{rate, Rate}, {samples, format_samples(Samples)}, {avg_rate, AvgRate}, {avg, Avg}], Count}. format_samples(Samples) -> [[{sample, S}, {timestamp, TS * 1000}] || {TS, S} <- Samples]. rabbitmq-server-3.2.4/plugins-src/rabbitmq-management/test/src/test-config0000644000000000000000000000050312305126066025416 0ustar rootroot# rabbitmqadmin.conf.example START [host_normal] hostname = localhost port = 15672 username = guest password = guest declare_vhost = / # Used as default for declare / delete only vhost = / # Used as default for declare / delete / list [default] hostname = localhost port = 99999 username = guest password = guest rabbitmq-server-3.2.4/plugins-src/rabbitmq-management/.srcdist_done0000644000000000000000000000000012305126066024154 0ustar rootrootrabbitmq-server-3.2.4/plugins-src/rabbitmq-management/license_info0000644000000000000000000000127212305126066024067 0ustar rootrootjQuery is "Copyright (c) 2010 John Resig" and is covered by the MIT license. It was downloaded from http://jquery.com/ EJS is "Copyright (c) 2007 Edward Benson" and is covered by the MIT license. It was downloaded from http://embeddedjs.com/ Sammy is "Copyright (c) 2008 Aaron Quint, Quirkey NYC, LLC" and is covered by the MIT license. It was downloaded from http://code.quirkey.com/sammy/ ExplorerCanvas is "Copyright 2006 Google Inc" and is covered by the Apache License version 2.0. It was downloaded from http://code.google.com/p/explorercanvas/ Flot is "Copyright (c) 2007-2013 IOLA and Ole Laursen" and is covered by the MIT license. It was downloaded from http://www.flotcharts.org/ rabbitmq-server-3.2.4/plugins-src/rabbitmq-management/LICENSE-MPL-RabbitMQ0000644000000000000000000006052312305126066024605 0ustar rootroot MOZILLA PUBLIC LICENSE Version 1.1 --------------- 1. Definitions. 1.0.1. "Commercial Use" means distribution or otherwise making the Covered Code available to a third party. 1.1. "Contributor" means each entity that creates or contributes to the creation of Modifications. 1.2. "Contributor Version" means the combination of the Original Code, prior Modifications used by a Contributor, and the Modifications made by that particular Contributor. 1.3. "Covered Code" means the Original Code or Modifications or the combination of the Original Code and Modifications, in each case including portions thereof. 1.4. "Electronic Distribution Mechanism" means a mechanism generally accepted in the software development community for the electronic transfer of data. 1.5. "Executable" means Covered Code in any form other than Source Code. 1.6. "Initial Developer" means the individual or entity identified as the Initial Developer in the Source Code notice required by Exhibit A. 1.7. "Larger Work" means a work which combines Covered Code or portions thereof with code not governed by the terms of this License. 1.8. "License" means this document. 1.8.1. "Licensable" means having the right to grant, to the maximum extent possible, whether at the time of the initial grant or subsequently acquired, any and all of the rights conveyed herein. 1.9. "Modifications" means any addition to or deletion from the substance or structure of either the Original Code or any previous Modifications. When Covered Code is released as a series of files, a Modification is: A. Any addition to or deletion from the contents of a file containing Original Code or previous Modifications. B. Any new file that contains any part of the Original Code or previous Modifications. 1.10. "Original Code" means Source Code of computer software code which is described in the Source Code notice required by Exhibit A as Original Code, and which, at the time of its release under this License is not already Covered Code governed by this License. 1.10.1. "Patent Claims" means any patent claim(s), now owned or hereafter acquired, including without limitation, method, process, and apparatus claims, in any patent Licensable by grantor. 1.11. "Source Code" means the preferred form of the Covered Code for making modifications to it, including all modules it contains, plus any associated interface definition files, scripts used to control compilation and installation of an Executable, or source code differential comparisons against either the Original Code or another well known, available Covered Code of the Contributor's choice. The Source Code can be in a compressed or archival form, provided the appropriate decompression or de-archiving software is widely available for no charge. 1.12. "You" (or "Your") means an individual or a legal entity exercising rights under, and complying with all of the terms of, this License or a future version of this License issued under Section 6.1. For legal entities, "You" includes any entity which controls, is controlled by, or is under common control with You. For purposes of this definition, "control" means (a) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (b) ownership of more than fifty percent (50%) of the outstanding shares or beneficial ownership of such entity. 2. Source Code License. 2.1. The Initial Developer Grant. The Initial Developer hereby grants You a world-wide, royalty-free, non-exclusive license, subject to third party intellectual property claims: (a) under intellectual property rights (other than patent or trademark) Licensable by Initial Developer to use, reproduce, modify, display, perform, sublicense and distribute the Original Code (or portions thereof) with or without Modifications, and/or as part of a Larger Work; and (b) under Patents Claims infringed by the making, using or selling of Original Code, to make, have made, use, practice, sell, and offer for sale, and/or otherwise dispose of the Original Code (or portions thereof). (c) the licenses granted in this Section 2.1(a) and (b) are effective on the date Initial Developer first distributes Original Code under the terms of this License. (d) Notwithstanding Section 2.1(b) above, no patent license is granted: 1) for code that You delete from the Original Code; 2) separate from the Original Code; or 3) for infringements caused by: i) the modification of the Original Code or ii) the combination of the Original Code with other software or devices. 2.2. Contributor Grant. Subject to third party intellectual property claims, each Contributor hereby grants You a world-wide, royalty-free, non-exclusive license (a) under intellectual property rights (other than patent or trademark) Licensable by Contributor, to use, reproduce, modify, display, perform, sublicense and distribute the Modifications created by such Contributor (or portions thereof) either on an unmodified basis, with other Modifications, as Covered Code and/or as part of a Larger Work; and (b) under Patent Claims infringed by the making, using, or selling of Modifications made by that Contributor either alone and/or in combination with its Contributor Version (or portions of such combination), to make, use, sell, offer for sale, have made, and/or otherwise dispose of: 1) Modifications made by that Contributor (or portions thereof); and 2) the combination of Modifications made by that Contributor with its Contributor Version (or portions of such combination). (c) the licenses granted in Sections 2.2(a) and 2.2(b) are effective on the date Contributor first makes Commercial Use of the Covered Code. (d) Notwithstanding Section 2.2(b) above, no patent license is granted: 1) for any code that Contributor has deleted from the Contributor Version; 2) separate from the Contributor Version; 3) for infringements caused by: i) third party modifications of Contributor Version or ii) the combination of Modifications made by that Contributor with other software (except as part of the Contributor Version) or other devices; or 4) under Patent Claims infringed by Covered Code in the absence of Modifications made by that Contributor. 3. Distribution Obligations. 3.1. Application of License. The Modifications which You create or to which You contribute are governed by the terms of this License, including without limitation Section 2.2. The Source Code version of Covered Code may be distributed only under the terms of this License or a future version of this License released under Section 6.1, and You must include a copy of this License with every copy of the Source Code You distribute. You may not offer or impose any terms on any Source Code version that alters or restricts the applicable version of this License or the recipients' rights hereunder. However, You may include an additional document offering the additional rights described in Section 3.5. 3.2. Availability of Source Code. Any Modification which You create or to which You contribute must be made available in Source Code form under the terms of this License either on the same media as an Executable version or via an accepted Electronic Distribution Mechanism to anyone to whom you made an Executable version available; and if made available via Electronic Distribution Mechanism, must remain available for at least twelve (12) months after the date it initially became available, or at least six (6) months after a subsequent version of that particular Modification has been made available to such recipients. You are responsible for ensuring that the Source Code version remains available even if the Electronic Distribution Mechanism is maintained by a third party. 3.3. Description of Modifications. You must cause all Covered Code to which You contribute to contain a file documenting the changes You made to create that Covered Code and the date of any change. You must include a prominent statement that the Modification is derived, directly or indirectly, from Original Code provided by the Initial Developer and including the name of the Initial Developer in (a) the Source Code, and (b) in any notice in an Executable version or related documentation in which You describe the origin or ownership of the Covered Code. 3.4. Intellectual Property Matters (a) Third Party Claims. If Contributor has knowledge that a license under a third party's intellectual property rights is required to exercise the rights granted by such Contributor under Sections 2.1 or 2.2, Contributor must include a text file with the Source Code distribution titled "LEGAL" which describes the claim and the party making the claim in sufficient detail that a recipient will know whom to contact. If Contributor obtains such knowledge after the Modification is made available as described in Section 3.2, Contributor shall promptly modify the LEGAL file in all copies Contributor makes available thereafter and shall take other steps (such as notifying appropriate mailing lists or newsgroups) reasonably calculated to inform those who received the Covered Code that new knowledge has been obtained. (b) Contributor APIs. If Contributor's Modifications include an application programming interface and Contributor has knowledge of patent licenses which are reasonably necessary to implement that API, Contributor must also include this information in the LEGAL file. (c) Representations. Contributor represents that, except as disclosed pursuant to Section 3.4(a) above, Contributor believes that Contributor's Modifications are Contributor's original creation(s) and/or Contributor has sufficient rights to grant the rights conveyed by this License. 3.5. Required Notices. You must duplicate the notice in Exhibit A in each file of the Source Code. If it is not possible to put such notice in a particular Source Code file due to its structure, then You must include such notice in a location (such as a relevant directory) where a user would be likely to look for such a notice. If You created one or more Modification(s) You may add your name as a Contributor to the notice described in Exhibit A. You must also duplicate this License in any documentation for the Source Code where You describe recipients' rights or ownership rights relating to Covered Code. You may choose to offer, and to charge a fee for, warranty, support, indemnity or liability obligations to one or more recipients of Covered Code. However, You may do so only on Your own behalf, and not on behalf of the Initial Developer or any Contributor. You must make it absolutely clear than any such warranty, support, indemnity or liability obligation is offered by You alone, and You hereby agree to indemnify the Initial Developer and every Contributor for any liability incurred by the Initial Developer or such Contributor as a result of warranty, support, indemnity or liability terms You offer. 3.6. Distribution of Executable Versions. You may distribute Covered Code in Executable form only if the requirements of Section 3.1-3.5 have been met for that Covered Code, and if You include a notice stating that the Source Code version of the Covered Code is available under the terms of this License, including a description of how and where You have fulfilled the obligations of Section 3.2. The notice must be conspicuously included in any notice in an Executable version, related documentation or collateral in which You describe recipients' rights relating to the Covered Code. You may distribute the Executable version of Covered Code or ownership rights under a license of Your choice, which may contain terms different from this License, provided that You are in compliance with the terms of this License and that the license for the Executable version does not attempt to limit or alter the recipient's rights in the Source Code version from the rights set forth in this License. If You distribute the Executable version under a different license You must make it absolutely clear that any terms which differ from this License are offered by You alone, not by the Initial Developer or any Contributor. You hereby agree to indemnify the Initial Developer and every Contributor for any liability incurred by the Initial Developer or such Contributor as a result of any such terms You offer. 3.7. Larger Works. You may create a Larger Work by combining Covered Code with other code not governed by the terms of this License and distribute the Larger Work as a single product. In such a case, You must make sure the requirements of this License are fulfilled for the Covered Code. 4. Inability to Comply Due to Statute or Regulation. If it is impossible for You to comply with any of the terms of this License with respect to some or all of the Covered Code due to statute, judicial order, or regulation then You must: (a) comply with the terms of this License to the maximum extent possible; and (b) describe the limitations and the code they affect. Such description must be included in the LEGAL file described in Section 3.4 and must be included with all distributions of the Source Code. Except to the extent prohibited by statute or regulation, such description must be sufficiently detailed for a recipient of ordinary skill to be able to understand it. 5. Application of this License. This License applies to code to which the Initial Developer has attached the notice in Exhibit A and to related Covered Code. 6. Versions of the License. 6.1. New Versions. Netscape Communications Corporation ("Netscape") may publish revised and/or new versions of the License from time to time. Each version will be given a distinguishing version number. 6.2. Effect of New Versions. Once Covered Code has been published under a particular version of the License, You may always continue to use it under the terms of that version. You may also choose to use such Covered Code under the terms of any subsequent version of the License published by Netscape. No one other than Netscape has the right to modify the terms applicable to Covered Code created under this License. 6.3. Derivative Works. If You create or use a modified version of this License (which you may only do in order to apply it to code which is not already Covered Code governed by this License), You must (a) rename Your license so that the phrases "Mozilla", "MOZILLAPL", "MOZPL", "Netscape", "MPL", "NPL" or any confusingly similar phrase do not appear in your license (except to note that your license differs from this License) and (b) otherwise make it clear that Your version of the license contains terms which differ from the Mozilla Public License and Netscape Public License. (Filling in the name of the Initial Developer, Original Code or Contributor in the notice described in Exhibit A shall not of themselves be deemed to be modifications of this License.) 7. DISCLAIMER OF WARRANTY. COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER THIS DISCLAIMER. 8. TERMINATION. 8.1. This License and the rights granted hereunder will terminate automatically if You fail to comply with terms herein and fail to cure such breach within 30 days of becoming aware of the breach. All sublicenses to the Covered Code which are properly granted shall survive any termination of this License. Provisions which, by their nature, must remain in effect beyond the termination of this License shall survive. 8.2. If You initiate litigation by asserting a patent infringement claim (excluding declatory judgment actions) against Initial Developer or a Contributor (the Initial Developer or Contributor against whom You file such action is referred to as "Participant") alleging that: (a) such Participant's Contributor Version directly or indirectly infringes any patent, then any and all rights granted by such Participant to You under Sections 2.1 and/or 2.2 of this License shall, upon 60 days notice from Participant terminate prospectively, unless if within 60 days after receipt of notice You either: (i) agree in writing to pay Participant a mutually agreeable reasonable royalty for Your past and future use of Modifications made by such Participant, or (ii) withdraw Your litigation claim with respect to the Contributor Version against such Participant. If within 60 days of notice, a reasonable royalty and payment arrangement are not mutually agreed upon in writing by the parties or the litigation claim is not withdrawn, the rights granted by Participant to You under Sections 2.1 and/or 2.2 automatically terminate at the expiration of the 60 day notice period specified above. (b) any software, hardware, or device, other than such Participant's Contributor Version, directly or indirectly infringes any patent, then any rights granted to You by such Participant under Sections 2.1(b) and 2.2(b) are revoked effective as of the date You first made, used, sold, distributed, or had made, Modifications made by that Participant. 8.3. If You assert a patent infringement claim against Participant alleging that such Participant's Contributor Version directly or indirectly infringes any patent where such claim is resolved (such as by license or settlement) prior to the initiation of patent infringement litigation, then the reasonable value of the licenses granted by such Participant under Sections 2.1 or 2.2 shall be taken into account in determining the amount or value of any payment or license. 8.4. In the event of termination under Sections 8.1 or 8.2 above, all end user license agreements (excluding distributors and resellers) which have been validly granted by You or any distributor hereunder prior to termination shall survive termination. 9. LIMITATION OF LIABILITY. UNDER NO CIRCUMSTANCES AND UNDER NO LEGAL THEORY, WHETHER TORT (INCLUDING NEGLIGENCE), CONTRACT, OR OTHERWISE, SHALL YOU, THE INITIAL DEVELOPER, ANY OTHER CONTRIBUTOR, OR ANY DISTRIBUTOR OF COVERED CODE, OR ANY SUPPLIER OF ANY OF SUCH PARTIES, BE LIABLE TO ANY PERSON FOR ANY INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES OF ANY CHARACTER INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF GOODWILL, WORK STOPPAGE, COMPUTER FAILURE OR MALFUNCTION, OR ANY AND ALL OTHER COMMERCIAL DAMAGES OR LOSSES, EVEN IF SUCH PARTY SHALL HAVE BEEN INFORMED OF THE POSSIBILITY OF SUCH DAMAGES. THIS LIMITATION OF LIABILITY SHALL NOT APPLY TO LIABILITY FOR DEATH OR PERSONAL INJURY RESULTING FROM SUCH PARTY'S NEGLIGENCE TO THE EXTENT APPLICABLE LAW PROHIBITS SUCH LIMITATION. SOME JURISDICTIONS DO NOT ALLOW THE EXCLUSION OR LIMITATION OF INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO THIS EXCLUSION AND LIMITATION MAY NOT APPLY TO YOU. 10. U.S. GOVERNMENT END USERS. The Covered Code is a "commercial item," as that term is defined in 48 C.F.R. 2.101 (Oct. 1995), consisting of "commercial computer software" and "commercial computer software documentation," as such terms are used in 48 C.F.R. 12.212 (Sept. 1995). Consistent with 48 C.F.R. 12.212 and 48 C.F.R. 227.7202-1 through 227.7202-4 (June 1995), all U.S. Government End Users acquire Covered Code with only those rights set forth herein. 11. MISCELLANEOUS. This License represents the complete agreement concerning subject matter hereof. If any provision of this License is held to be unenforceable, such provision shall be reformed only to the extent necessary to make it enforceable. This License shall be governed by California law provisions (except to the extent applicable law, if any, provides otherwise), excluding its conflict-of-law provisions. With respect to disputes in which at least one party is a citizen of, or an entity chartered or registered to do business in the United States of America, any litigation relating to this License shall be subject to the jurisdiction of the Federal Courts of the Northern District of California, with venue lying in Santa Clara County, California, with the losing party responsible for costs, including without limitation, court costs and reasonable attorneys' fees and expenses. The application of the United Nations Convention on Contracts for the International Sale of Goods is expressly excluded. Any law or regulation which provides that the language of a contract shall be construed against the drafter shall not apply to this License. 12. RESPONSIBILITY FOR CLAIMS. As between Initial Developer and the Contributors, each party is responsible for claims and damages arising, directly or indirectly, out of its utilization of rights under this License and You agree to work with Initial Developer and Contributors to distribute such responsibility on an equitable basis. Nothing herein is intended or shall be deemed to constitute any admission of liability. 13. MULTIPLE-LICENSED CODE. Initial Developer may designate portions of the Covered Code as "Multiple-Licensed". "Multiple-Licensed" means that the Initial Developer permits you to utilize portions of the Covered Code under Your choice of the NPL or the alternative licenses, if any, specified by the Initial Developer in the file described in Exhibit A. EXHIBIT A -Mozilla Public License. ``The contents of this file are subject to the Mozilla Public License Version 1.1 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.mozilla.org/MPL/ Software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for the specific language governing rights and limitations under the License. The Original Code is RabbitMQ Management Plugin. The Initial Developer of the Original Code is GoPivotal, Inc. Copyright (c) 2010-2013 GoPivotal, Inc. All rights reserved.'' [NOTE: The text of this Exhibit A may differ slightly from the text of the notices in the Source Code files of the Original Code. You should use the text of this Exhibit A rather than the text found in the Original Code Source Code for Your Modifications.] rabbitmq-server-3.2.4/plugins-src/rabbitmq-management/bin/0000755000000000000000000000000012305126066022255 5ustar rootrootrabbitmq-server-3.2.4/plugins-src/rabbitmq-management/bin/rabbitmqadmin0000755000000000000000000007723012305126066025026 0ustar rootroot#!/usr/bin/env python # The contents of this file are subject to the Mozilla Public License # Version 1.1 (the "License"); you may not use this file except in # compliance with the License. You may obtain a copy of the License at # http://www.mozilla.org/MPL/ # # Software distributed under the License is distributed on an "AS IS" # basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the # License for the specific language governing rights and limitations # under the License. # # The Original Code is RabbitMQ Management Plugin. # # The Initial Developer of the Original Code is GoPivotal, Inc. # Copyright (c) 2010-2013 GoPivotal, Inc. All rights reserved. import sys if sys.version_info[0] < 2 or sys.version_info[1] < 6: print "Sorry, rabbitmqadmin requires at least Python 2.6." sys.exit(1) from ConfigParser import ConfigParser, NoSectionError from optparse import OptionParser, TitledHelpFormatter import httplib import urllib import urlparse import base64 import json import os import socket VERSION = '%%VSN%%' LISTABLE = {'connections': {'vhost': False}, 'channels': {'vhost': False}, 'exchanges': {'vhost': True}, 'queues': {'vhost': True}, 'bindings': {'vhost': True}, 'users': {'vhost': False}, 'vhosts': {'vhost': False}, 'permissions': {'vhost': False}, 'nodes': {'vhost': False}, 'parameters': {'vhost': False, 'json': ['value']}, 'policies': {'vhost': False, 'json': ['definition']}} SHOWABLE = {'overview': {'vhost': False}} PROMOTE_COLUMNS = ['vhost', 'name', 'type', 'source', 'destination', 'destination_type', 'routing_key'] URIS = { 'exchange': '/exchanges/{vhost}/{name}', 'queue': '/queues/{vhost}/{name}', 'binding': '/bindings/{vhost}/e/{source}/{destination_char}/{destination}', 'binding_del':'/bindings/{vhost}/e/{source}/{destination_char}/{destination}/{properties_key}', 'vhost': '/vhosts/{name}', 'user': '/users/{name}', 'permission': '/permissions/{vhost}/{user}', 'parameter': '/parameters/{component}/{vhost}/{name}', 'policy': '/policies/{vhost}/{name}' } DECLARABLE = { 'exchange': {'mandatory': ['name', 'type'], 'json': ['arguments'], 'optional': {'auto_delete': 'false', 'durable': 'true', 'internal': 'false', 'arguments': {}}}, 'queue': {'mandatory': ['name'], 'json': ['arguments'], 'optional': {'auto_delete': 'false', 'durable': 'true', 'arguments': {}, 'node': None}}, 'binding': {'mandatory': ['source', 'destination'], 'json': ['arguments'], 'optional': {'destination_type': 'queue', 'routing_key': '', 'arguments': {}}}, 'vhost': {'mandatory': ['name'], 'optional': {'tracing': None}}, 'user': {'mandatory': ['name', 'password', 'tags'], 'optional': {}}, 'permission': {'mandatory': ['vhost', 'user', 'configure', 'write', 'read'], 'optional': {}}, 'parameter': {'mandatory': ['component', 'name', 'value'], 'json': ['value'], 'optional': {}}, # Priority is 'json' to convert to int 'policy': {'mandatory': ['name', 'pattern', 'definition'], 'json': ['definition', 'priority'], 'optional': {'priority' : 0, 'apply-to': None}} } DELETABLE = { 'exchange': {'mandatory': ['name']}, 'queue': {'mandatory': ['name']}, 'binding': {'mandatory': ['source', 'destination_type', 'destination', 'properties_key']}, 'vhost': {'mandatory': ['name']}, 'user': {'mandatory': ['name']}, 'permission': {'mandatory': ['vhost', 'user']}, 'parameter': {'mandatory': ['component', 'name']}, 'policy': {'mandatory': ['name']} } CLOSABLE = { 'connection': {'mandatory': ['name'], 'optional': {}, 'uri': '/connections/{name}'} } PURGABLE = { 'queue': {'mandatory': ['name'], 'optional': {}, 'uri': '/queues/{vhost}/{name}/contents'} } EXTRA_VERBS = { 'publish': {'mandatory': ['routing_key'], 'optional': {'payload': None, 'exchange': 'amq.default', 'payload_encoding': 'string'}, 'uri': '/exchanges/{vhost}/{exchange}/publish'}, 'get': {'mandatory': ['queue'], 'optional': {'count': '1', 'requeue': 'true', 'payload_file': None, 'encoding': 'auto'}, 'uri': '/queues/{vhost}/{queue}/get'} } for k in DECLARABLE: DECLARABLE[k]['uri'] = URIS[k] for k in DELETABLE: DELETABLE[k]['uri'] = URIS[k] DELETABLE[k]['optional'] = {} DELETABLE['binding']['uri'] = URIS['binding_del'] def short_usage(): return "rabbitmqadmin [options] subcommand" def title(name): return "\n%s\n%s\n\n" % (name, '=' * len(name)) def subcommands_usage(): usage = """Usage ===== """ + short_usage() + """ where subcommand is one of: """ + title("Display") for l in LISTABLE: usage += " list {0} [...]\n".format(l) for s in SHOWABLE: usage += " show {0} [...]\n".format(s) usage += title("Object Manipulation") usage += fmt_usage_stanza(DECLARABLE, 'declare') usage += fmt_usage_stanza(DELETABLE, 'delete') usage += fmt_usage_stanza(CLOSABLE, 'close') usage += fmt_usage_stanza(PURGABLE, 'purge') usage += title("Broker Definitions") usage += """ export import """ usage += title("Publishing and Consuming") usage += fmt_usage_stanza(EXTRA_VERBS, '') usage += """ * If payload is not specified on publish, standard input is used * If payload_file is not specified on get, the payload will be shown on standard output along with the message metadata * If payload_file is specified on get, count must not be set """ return usage def config_usage(): usage = "Usage\n=====\n" + short_usage() usage += "\n" + title("Configuration File") usage += """ It is possible to specify a configuration file from the command line. Hosts can be configured easily in a configuration file and called from the command line. """ usage += title("Example") usage += """ # rabbitmqadmin.conf.example START [host_normal] hostname = localhost port = 15672 username = guest password = guest declare_vhost = / # Used as default for declare / delete only vhost = / # Used as default for declare / delete / list [host_ssl] hostname = otherhost port = 15672 username = guest password = guest ssl = True ssl_key_file = /path/to/key.pem ssl_cert_file = /path/to/cert.pem # rabbitmqadmin.conf.example END """ usage += title("Use") usage += """ rabbitmqadmin -c rabbitmqadmin.conf.example -N host_normal ...""" return usage def more_help(): return """ More Help ========= For more help use the help subcommand: rabbitmqadmin help subcommands # For a list of available subcommands rabbitmqadmin help config # For help with the configuration file """ def fmt_usage_stanza(root, verb): def fmt_args(args): res = " ".join(["{0}=...".format(a) for a in args['mandatory']]) opts = " ".join("{0}=...".format(o) for o in args['optional'].keys()) if opts != "": res += " [{0}]".format(opts) return res text = "" if verb != "": verb = " " + verb for k in root.keys(): text += " {0} {1} {2}\n".format(verb, k, fmt_args(root[k])) return text default_options = { "hostname" : "localhost", "port" : "15672", "declare_vhost" : "/", "username" : "guest", "password" : "guest", "ssl" : False, "verbose" : True, "format" : "table", "depth" : 1, "bash_completion" : False } class MyFormatter(TitledHelpFormatter): def format_epilog(self, epilog): return epilog parser = OptionParser(usage=short_usage(), formatter=MyFormatter(), epilog=more_help()) def make_parser(): def add(*args, **kwargs): key = kwargs['dest'] if key in default_options: default = " [default: %s]" % default_options[key] kwargs['help'] = kwargs['help'] + default parser.add_option(*args, **kwargs) add("-c", "--config", dest="config", help="configuration file [default: ~/.rabbitmqadmin.conf]", metavar="CONFIG") add("-N", "--node", dest="node", help="node described in the configuration file [default: 'default'" + \ " only if configuration file is specified]", metavar="NODE") add("-H", "--host", dest="hostname", help="connect to host HOST" , metavar="HOST") add("-P", "--port", dest="port", help="connect to port PORT", metavar="PORT") add("-V", "--vhost", dest="vhost", help="connect to vhost VHOST [default: all vhosts for list, '/' for declare]", metavar="VHOST") add("-u", "--username", dest="username", help="connect using username USERNAME", metavar="USERNAME") add("-p", "--password", dest="password", help="connect using password PASSWORD", metavar="PASSWORD") add("-q", "--quiet", action="store_false", dest="verbose", help="suppress status messages") add("-s", "--ssl", action="store_true", dest="ssl", help="connect with ssl") add("--ssl-key-file", dest="ssl_key_file", help="PEM format key file for SSL") add("--ssl-cert-file", dest="ssl_cert_file", help="PEM format certificate file for SSL") add("-f", "--format", dest="format", help="format for listing commands - one of [" + ", ".join(FORMATS.keys()) + "]") add("-S", "--sort", dest="sort", help="sort key for listing queries") add("-R", "--sort-reverse", action="store_true", dest="sort_reverse", help="reverse the sort order") add("-d", "--depth", dest="depth", help="maximum depth to recurse for listing tables") add("--bash-completion", action="store_true", dest="bash_completion", help="Print bash completion script") add("--version", action="store_true", dest="version", help="Display version and exit") def default_config(): home = os.getenv('USERPROFILE') or os.getenv('HOME') if home is not None: config_file = home + os.sep + ".rabbitmqadmin.conf" if os.path.isfile(config_file): return config_file return None def make_configuration(): make_parser() (options, args) = parser.parse_args() setattr(options, "declare_vhost", None) if options.version: print_version() if options.config is None: config_file = default_config() if config_file is not None: setattr(options, "config", config_file) else: if not os.path.isfile(options.config): assert_usage(False, "Could not read config file '%s'" % options.config) if options.node is None and options.config: options.node = "default" else: options.node = options.node for (key, val) in default_options.items(): if getattr(options, key) is None: setattr(options, key, val) if options.config is not None: config = ConfigParser() try: config.read(options.config) new_conf = dict(config.items(options.node)) except NoSectionError, error: if options.node == "default": pass else: assert_usage(False, ("Could not read section '%s' in config file" + " '%s':\n %s") % (options.node, options.config, error)) else: for key, val in new_conf.items(): setattr(options, key, val) return (options, args) def assert_usage(expr, error): if not expr: output("\nERROR: {0}\n".format(error)) output("{0} --help for help\n".format(os.path.basename(sys.argv[0]))) sys.exit(1) def print_version(): output("rabbitmqadmin {0}".format(VERSION)) sys.exit(0) def column_sort_key(col): if col in PROMOTE_COLUMNS: return (1, PROMOTE_COLUMNS.index(col)) else: return (2, col) def main(): (options, args) = make_configuration() if options.bash_completion: print_bash_completion() exit(0) assert_usage(len(args) > 0, 'Action not specified') mgmt = Management(options, args[1:]) mode = "invoke_" + args[0] assert_usage(hasattr(mgmt, mode), 'Action {0} not understood'.format(args[0])) method = getattr(mgmt, "invoke_%s" % args[0]) method() def output(s): print maybe_utf8(s, sys.stdout) def die(s): sys.stderr.write(maybe_utf8("*** {0}\n".format(s), sys.stderr)) exit(1) def maybe_utf8(s, stream): if stream.isatty(): # It will have an encoding, which Python will respect return s else: # It won't have an encoding, and Python will pick ASCII by default return s.encode('utf-8') class Management: def __init__(self, options, args): self.options = options self.args = args def get(self, path): return self.http("GET", "/api%s" % path, "") def put(self, path, body): return self.http("PUT", "/api%s" % path, body) def post(self, path, body): return self.http("POST", "/api%s" % path, body) def delete(self, path): return self.http("DELETE", "/api%s" % path, "") def http(self, method, path, body): if self.options.ssl: conn = httplib.HTTPSConnection(self.options.hostname, self.options.port, self.options.ssl_key_file, self.options.ssl_cert_file) else: conn = httplib.HTTPConnection(self.options.hostname, self.options.port) headers = {"Authorization": "Basic " + base64.b64encode(self.options.username + ":" + self.options.password)} if body != "": headers["Content-Type"] = "application/json" try: conn.request(method, path, body, headers) except socket.error, e: die("Could not connect: {0}".format(e)) resp = conn.getresponse() if resp.status == 400: die(json.loads(resp.read())['reason']) if resp.status == 401: die("Access refused: {0}".format(path)) if resp.status == 404: die("Not found: {0}".format(path)) if resp.status == 301: url = urlparse.urlparse(resp.getheader('location')) [host, port] = url.netloc.split(':') self.options.hostname = host self.options.port = int(port) return self.http(method, url.path + '?' + url.query, body) if resp.status < 200 or resp.status > 400: raise Exception("Received %d %s for path %s\n%s" % (resp.status, resp.reason, path, resp.read())) return resp.read() def verbose(self, string): if self.options.verbose: output(string) def get_arg(self): assert_usage(len(self.args) == 1, 'Exactly one argument required') return self.args[0] def invoke_help(self): if len(self.args) == 0: parser.print_help() else: help_cmd = self.get_arg() if help_cmd == 'subcommands': usage = subcommands_usage() elif help_cmd == 'config': usage = config_usage() else: assert_usage(False, """help topic must be one of: subcommands config""") print usage exit(0) def invoke_publish(self): (uri, upload) = self.parse_args(self.args, EXTRA_VERBS['publish']) upload['properties'] = {} # TODO do we care here? if not 'payload' in upload: data = sys.stdin.read() upload['payload'] = base64.b64encode(data) upload['payload_encoding'] = 'base64' resp = json.loads(self.post(uri, json.dumps(upload))) if resp['routed']: self.verbose("Message published") else: self.verbose("Message published but NOT routed") def invoke_get(self): (uri, upload) = self.parse_args(self.args, EXTRA_VERBS['get']) payload_file = 'payload_file' in upload and upload['payload_file'] or None assert_usage(not payload_file or upload['count'] == '1', 'Cannot get multiple messages using payload_file') result = self.post(uri, json.dumps(upload)) if payload_file: write_payload_file(payload_file, result) columns = ['routing_key', 'exchange', 'message_count', 'payload_bytes', 'redelivered'] format_list(result, columns, {}, self.options) else: format_list(result, [], {}, self.options) def invoke_export(self): path = self.get_arg() definitions = self.get("/definitions") f = open(path, 'w') f.write(definitions) f.close() self.verbose("Exported definitions for %s to \"%s\"" % (self.options.hostname, path)) def invoke_import(self): path = self.get_arg() f = open(path, 'r') definitions = f.read() f.close() self.post("/definitions", definitions) self.verbose("Imported definitions for %s from \"%s\"" % (self.options.hostname, path)) def invoke_list(self): cols = self.args[1:] (uri, obj_info) = self.list_show_uri(LISTABLE, 'list', cols) format_list(self.get(uri), cols, obj_info, self.options) def invoke_show(self): cols = self.args[1:] (uri, obj_info) = self.list_show_uri(SHOWABLE, 'show', cols) format_list('[{0}]'.format(self.get(uri)), cols, obj_info, self.options) def list_show_uri(self, obj_types, verb, cols): obj_type = self.args[0] assert_usage(obj_type in obj_types, "Don't know how to {0} {1}".format(verb, obj_type)) obj_info = obj_types[obj_type] uri = "/%s" % obj_type query = [] if obj_info['vhost'] and self.options.vhost: uri += "/%s" % urllib.quote_plus(self.options.vhost) if cols != []: query.append("columns=" + ",".join(cols)) sort = self.options.sort if sort: query.append("sort=" + sort) if self.options.sort_reverse: query.append("sort_reverse=true") query = "&".join(query) if query != "": uri += "?" + query return (uri, obj_info) def invoke_declare(self): (obj_type, uri, upload) = self.declare_delete_parse(DECLARABLE) if obj_type == 'binding': self.post(uri, json.dumps(upload)) else: self.put(uri, json.dumps(upload)) self.verbose("{0} declared".format(obj_type)) def invoke_delete(self): (obj_type, uri, upload) = self.declare_delete_parse(DELETABLE) self.delete(uri) self.verbose("{0} deleted".format(obj_type)) def invoke_close(self): (obj_type, uri, upload) = self.declare_delete_parse(CLOSABLE) self.delete(uri) self.verbose("{0} closed".format(obj_type)) def invoke_purge(self): (obj_type, uri, upload) = self.declare_delete_parse(PURGABLE) self.delete(uri) self.verbose("{0} purged".format(obj_type)) def declare_delete_parse(self, root): assert_usage(len(self.args) > 0, 'Type not specified') obj_type = self.args[0] assert_usage(obj_type in root, 'Type {0} not recognised'.format(obj_type)) obj = root[obj_type] (uri, upload) = self.parse_args(self.args[1:], obj) return (obj_type, uri, upload) def parse_args(self, args, obj): mandatory = obj['mandatory'] optional = obj['optional'] uri_template = obj['uri'] upload = {} for k in optional.keys(): if optional[k]: upload[k] = optional[k] for arg in args: assert_usage("=" in arg, 'Argument "{0}" not in format name=value'.format(arg)) (name, value) = arg.split("=", 1) assert_usage(name in mandatory or name in optional.keys(), 'Argument "{0}" not recognised'.format(name)) if 'json' in obj and name in obj['json']: upload[name] = self.parse_json(value) else: upload[name] = value for m in mandatory: assert_usage(m in upload.keys(), 'mandatory argument "{0}" required'.format(m)) if 'vhost' not in mandatory: upload['vhost'] = self.options.vhost or self.options.declare_vhost uri_args = {} for k in upload: v = upload[k] if v and isinstance(v, basestring): uri_args[k] = urllib.quote_plus(v) if k == 'destination_type': uri_args['destination_char'] = v[0] uri = uri_template.format(**uri_args) return (uri, upload) def parse_json(self, text): try: return json.loads(text) except ValueError: print "Could not parse JSON:\n {0}".format(text) sys.exit(1) def format_list(json_list, columns, args, options): format = options.format formatter = None if format == "raw_json": output(json_list) return elif format == "pretty_json": enc = json.JSONEncoder(False, False, True, True, True, 2) output(enc.encode(json.loads(json_list))) return else: formatter = FORMATS[format] assert_usage(formatter != None, "Format {0} not recognised".format(format)) formatter_instance = formatter(columns, args, options) formatter_instance.display(json_list) class Lister: def verbose(self, string): if self.options.verbose: output(string) def display(self, json_list): depth = sys.maxint if len(self.columns) == 0: depth = int(self.options.depth) (columns, table) = self.list_to_table(json.loads(json_list), depth) if len(table) > 0: self.display_list(columns, table) else: self.verbose("No items") def list_to_table(self, items, max_depth): columns = {} column_ix = {} row = None table = [] def add(prefix, depth, item, fun): for key in item: column = prefix == '' and key or (prefix + '.' + key) subitem = item[key] if type(subitem) == dict: if self.obj_info.has_key('json') and key in self.obj_info['json']: fun(column, json.dumps(subitem)) else: if depth < max_depth: add(column, depth + 1, subitem, fun) elif type(subitem) == list: # The first branch has slave nodes in queues in # mind (which come out looking decent); the second # one has applications in nodes (which look less # so, but what would look good?). if [x for x in subitem if type(x) != unicode] == []: serialised = " ".join(subitem) else: serialised = json.dumps(subitem) fun(column, serialised) else: fun(column, subitem) def add_to_columns(col, val): columns[col] = True def add_to_row(col, val): if col in column_ix: row[column_ix[col]] = unicode(val) if len(self.columns) == 0: for item in items: add('', 1, item, add_to_columns) columns = columns.keys() columns.sort(key=column_sort_key) else: columns = self.columns for i in xrange(0, len(columns)): column_ix[columns[i]] = i for item in items: row = len(columns) * [''] add('', 1, item, add_to_row) table.append(row) return (columns, table) class TSVList(Lister): def __init__(self, columns, obj_info, options): self.columns = columns self.obj_info = obj_info self.options = options def display_list(self, columns, table): head = "\t".join(columns) self.verbose(head) for row in table: line = "\t".join(row) output(line) class LongList(Lister): def __init__(self, columns, obj_info, options): self.columns = columns self.obj_info = obj_info self.options = options def display_list(self, columns, table): sep = "\n" + "-" * 80 + "\n" max_width = 0 for col in columns: max_width = max(max_width, len(col)) fmt = "{0:>" + unicode(max_width) + "}: {1}" output(sep) for i in xrange(0, len(table)): for j in xrange(0, len(columns)): output(fmt.format(columns[j], table[i][j])) output(sep) class TableList(Lister): def __init__(self, columns, obj_info, options): self.columns = columns self.obj_info = obj_info self.options = options def display_list(self, columns, table): total = [columns] total.extend(table) self.ascii_table(total) def ascii_table(self, rows): table = "" col_widths = [0] * len(rows[0]) for i in xrange(0, len(rows[0])): for j in xrange(0, len(rows)): col_widths[i] = max(col_widths[i], len(rows[j][i])) self.ascii_bar(col_widths) self.ascii_row(col_widths, rows[0], "^") self.ascii_bar(col_widths) for row in rows[1:]: self.ascii_row(col_widths, row, "<") self.ascii_bar(col_widths) def ascii_row(self, col_widths, row, align): txt = "|" for i in xrange(0, len(col_widths)): fmt = " {0:" + align + unicode(col_widths[i]) + "} " txt += fmt.format(row[i]) + "|" output(txt) def ascii_bar(self, col_widths): txt = "+" for w in col_widths: txt += ("-" * (w + 2)) + "+" output(txt) class KeyValueList(Lister): def __init__(self, columns, obj_info, options): self.columns = columns self.obj_info = obj_info self.options = options def display_list(self, columns, table): for i in xrange(0, len(table)): row = [] for j in xrange(0, len(columns)): row.append("{0}=\"{1}\"".format(columns[j], table[i][j])) output(" ".join(row)) # TODO handle spaces etc in completable names class BashList(Lister): def __init__(self, columns, obj_info, options): self.columns = columns self.obj_info = obj_info self.options = options def display_list(self, columns, table): ix = None for i in xrange(0, len(columns)): if columns[i] == 'name': ix = i if ix is not None: res = [] for row in table: res.append(row[ix]) output(" ".join(res)) FORMATS = { 'raw_json' : None, # Special cased 'pretty_json' : None, # Ditto 'tsv' : TSVList, 'long' : LongList, 'table' : TableList, 'kvp' : KeyValueList, 'bash' : BashList } def write_payload_file(payload_file, json_list): result = json.loads(json_list)[0] payload = result['payload'] payload_encoding = result['payload_encoding'] f = open(payload_file, 'w') if payload_encoding == 'base64': data = base64.b64decode(payload) else: data = payload f.write(data) f.close() def print_bash_completion(): script = """# This is a bash completion script for rabbitmqadmin. # Redirect it to a file, then source it or copy it to /etc/bash_completion.d # to get tab completion. rabbitmqadmin must be on your PATH for this to work. _rabbitmqadmin() { local cur prev opts base COMPREPLY=() cur="${COMP_WORDS[COMP_CWORD]}" prev="${COMP_WORDS[COMP_CWORD-1]}" opts="list show declare delete close purge import export get publish help" fargs="--help --host --port --vhost --username --password --format --depth --sort --sort-reverse" case "${prev}" in list) COMPREPLY=( $(compgen -W '""" + " ".join(LISTABLE) + """' -- ${cur}) ) return 0 ;; show) COMPREPLY=( $(compgen -W '""" + " ".join(SHOWABLE) + """' -- ${cur}) ) return 0 ;; declare) COMPREPLY=( $(compgen -W '""" + " ".join(DECLARABLE.keys()) + """' -- ${cur}) ) return 0 ;; delete) COMPREPLY=( $(compgen -W '""" + " ".join(DELETABLE.keys()) + """' -- ${cur}) ) return 0 ;; close) COMPREPLY=( $(compgen -W '""" + " ".join(CLOSABLE.keys()) + """' -- ${cur}) ) return 0 ;; purge) COMPREPLY=( $(compgen -W '""" + " ".join(PURGABLE.keys()) + """' -- ${cur}) ) return 0 ;; export) COMPREPLY=( $(compgen -f ${cur}) ) return 0 ;; import) COMPREPLY=( $(compgen -f ${cur}) ) return 0 ;; help) opts="subcommands config" COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) ) return 0 ;; -H) COMPREPLY=( $(compgen -A hostname ${cur}) ) return 0 ;; --host) COMPREPLY=( $(compgen -A hostname ${cur}) ) return 0 ;; -V) opts="$(rabbitmqadmin -q -f bash list vhosts)" COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) ) return 0 ;; --vhost) opts="$(rabbitmqadmin -q -f bash list vhosts)" COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) ) return 0 ;; -u) opts="$(rabbitmqadmin -q -f bash list users)" COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) ) return 0 ;; --username) opts="$(rabbitmqadmin -q -f bash list users)" COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) ) return 0 ;; -f) COMPREPLY=( $(compgen -W \"""" + " ".join(FORMATS.keys()) + """\" -- ${cur}) ) return 0 ;; --format) COMPREPLY=( $(compgen -W \"""" + " ".join(FORMATS.keys()) + """\" -- ${cur}) ) return 0 ;; """ for l in LISTABLE: key = l[0:len(l) - 1] script += " " + key + """) opts="$(rabbitmqadmin -q -f bash list """ + l + """)" COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) ) return 0 ;; """ script += """ *) ;; esac COMPREPLY=($(compgen -W "${opts} ${fargs}" -- ${cur})) return 0 } complete -F _rabbitmqadmin rabbitmqadmin """ output(script) if __name__ == "__main__": main() rabbitmq-server-3.2.4/plugins-src/rabbitmq-management/LICENSE-MIT-Sammy0600000644000000000000000000000206412305126066024455 0ustar rootrootCopyright (c) 2008 Aaron Quint, Quirkey NYC, LLC Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. rabbitmq-server-3.2.4/plugins-src/rabbitmq-management/Makefile0000644000000000000000000000206412305126066023147 0ustar rootrootinclude ../umbrella.mk RABBITMQCTL=../rabbitmq-server/scripts/rabbitmqctl TEST_TMPDIR=$(TMPDIR)/rabbitmq-test OTHER_NODE=undefined OTHER_PORT=undefined start-other-node: rm -f $(TEST_TMPDIR)/rabbitmq-$(OTHER_NODE)-pid RABBITMQ_MNESIA_BASE=$(TEST_TMPDIR)/rabbitmq-$(OTHER_NODE)-mnesia \ RABBITMQ_PID_FILE=$(TEST_TMPDIR)/rabbitmq-$(OTHER_NODE)-pid \ RABBITMQ_LOG_BASE=$(TEST_TMPDIR)/log \ RABBITMQ_NODENAME=$(OTHER_NODE) \ RABBITMQ_NODE_PORT=$(OTHER_PORT) \ RABBITMQ_CONFIG_FILE=etc/$(OTHER_NODE) \ RABBITMQ_PLUGINS_DIR=$(TEST_TMPDIR)/plugins \ RABBITMQ_PLUGINS_EXPAND_DIR=$(TEST_TMPDIR)/$(OTHER_NODE)-plugins-expand \ ../rabbitmq-server/scripts/rabbitmq-server >/tmp/$(OTHER_NODE).out 2>/tmp/$(OTHER_NODE).err & $(RABBITMQCTL) -n $(OTHER_NODE) wait $(TEST_TMPDIR)/rabbitmq-$(OTHER_NODE)-pid cluster-other-node: $(RABBITMQCTL) -n $(OTHER_NODE) stop_app $(RABBITMQCTL) -n $(OTHER_NODE) reset $(RABBITMQCTL) -n $(OTHER_NODE) join_cluster rabbit-test@`hostname -s` $(RABBITMQCTL) -n $(OTHER_NODE) start_app stop-other-node: $(RABBITMQCTL) -n $(OTHER_NODE) stop rabbitmq-server-3.2.4/plugins-src/rabbitmq-management/LICENSE-MIT-jQuery1640000644000000000000000000000206312305126066024652 0ustar rootrootCopyright (c) 2011 John Resig, http://jquery.com/ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. rabbitmq-server-3.2.4/plugins-src/rabbitmq-management/ebin/0000755000000000000000000000000012305126066022422 5ustar rootrootrabbitmq-server-3.2.4/plugins-src/rabbitmq-management/LICENSE-MIT-EJS100000644000000000000000000000207712305126066023727 0ustar rootrootEJS - Embedded JavaScript Copyright (c) 2007 Edward Benson Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. rabbitmq-server-3.2.4/plugins-src/rabbitmq-management/LICENSE-APACHE2-ExplorerCanvas0000644000000000000000000002613612305126066026455 0ustar rootroot 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. rabbitmq-server-3.2.4/plugins-src/rabbitmq-management/include/0000755000000000000000000000000012305126066023130 5ustar rootrootrabbitmq-server-3.2.4/plugins-src/rabbitmq-management/include/rabbit_mgmt.hrl0000644000000000000000000000154612305126066026134 0ustar rootroot%% The contents of this file are subject to the Mozilla Public License %% Version 1.1 (the "License"); you may not use this file except in %% compliance with the License. You may obtain a copy of the License at %% http://www.mozilla.org/MPL/ %% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the %% License for the specific language governing rights and limitations %% under the License. %% %% The Original Code is RabbitMQ Management Console. %% %% The Initial Developer of the Original Code is GoPivotal, Inc. %% Copyright (c) 2010-2013 GoPivotal, Inc. All rights reserved. %% -record(context, {user, password = none}). -record(range, {first, last, incr}). -record(stats, {diffs, base}). -define(AUTH_REALM, "Basic realm=\"RabbitMQ Management\""). rabbitmq-server-3.2.4/plugins-src/rabbitmq-management/include/rabbit_mgmt_test.hrl0000644000000000000000000000065712305126066027175 0ustar rootroot-include_lib("eunit/include/eunit.hrl"). -include_lib("amqp_client/include/amqp_client.hrl"). -define(OK, 200). -define(CREATED, 201). -define(NO_CONTENT, 204). -define(BAD_REQUEST, 400). -define(NOT_AUTHORISED, 401). %%-define(NOT_FOUND, 404). Defined for AMQP by amqp_client.hrl (as 404) -define(PREFIX, "http://localhost:15672/api"). %% httpc seems to get racy when using HTTP 1.1 -define(HTTPC_OPTS, [{version, "HTTP/1.0"}]). rabbitmq-server-3.2.4/plugins-src/rabbitmq-management/etc/0000755000000000000000000000000012305126066022260 5ustar rootrootrabbitmq-server-3.2.4/plugins-src/rabbitmq-management/etc/rabbit-test.config0000644000000000000000000000074712305126066025677 0ustar rootroot%% We test sample retention separately in rabbit_mgmt_test_db_unit, %% but for rabbit_mgmt_test_db we want to make sure samples never %% expire. [{rabbitmq_management, [{sample_retention_policies, %% List of {MaxAgeSecs, IfTimestampDivisibleBySecs} [{global, [{10000000000000, 1}]}, {basic, [{10000000000000, 1}]}, {detailed, [{10000000000000, 1}]}]} ]} ]. rabbitmq-server-3.2.4/plugins-src/rabbitmq-management/etc/bunny.config0000644000000000000000000000006712305126066024605 0ustar rootroot[{rabbitmq_management, [{listener,[{port, 15674}]}]}]. rabbitmq-server-3.2.4/plugins-src/rabbitmq-management/etc/hare.config0000644000000000000000000000006712305126066024371 0ustar rootroot[{rabbitmq_management, [{listener,[{port, 15673}]}]}]. rabbitmq-server-3.2.4/plugins-src/rabbitmq-management/LICENSE-BSD-base64js0000644000000000000000000000226612305126066024545 0ustar rootroot/* * Copyright (c) 2010 Nick Galbreath * http://code.google.com/p/stringencoders/source/browse/#svn/trunk/javascript * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. */ rabbitmq-server-3.2.4/plugins-src/rabbitmq-management/package.mk0000644000000000000000000000156712305126066023442 0ustar rootrootRELEASABLE:=true DEPS:=rabbitmq-web-dispatch webmachine-wrapper rabbitmq-server rabbitmq-erlang-client rabbitmq-management-agent WITH_BROKER_TEST_COMMANDS:=rabbit_mgmt_test_all:all_tests() WITH_BROKER_TEST_CONFIG:=$(PACKAGE_DIR)/etc/rabbit-test WITH_BROKER_TEST_SCRIPTS:=$(PACKAGE_DIR)/test/src/rabbitmqadmin-test.py CONSTRUCT_APP_PREREQS:=$(shell find $(PACKAGE_DIR)/priv -type f) $(PACKAGE_DIR)/bin/rabbitmqadmin define construct_app_commands cp -r $(PACKAGE_DIR)/priv $(APP_DIR) sed 's/%%VSN%%/$(VERSION)/' $(PACKAGE_DIR)/bin/rabbitmqadmin > $(APP_DIR)/priv/www/cli/rabbitmqadmin endef # The tests require erlang/OTP R14 (httpc issue) $(PACKAGE_DIR)+pre-test:: if [ "`erl -noshell -eval 'io:format([list_to_integer(X) || X <- string:tokens(erlang:system_info(version), ".")] >= [5,8]), halt().'`" != true ] ; then \ echo "Need Erlang/OTP R14A or higher" ; \ exit 1 ; \ fi rabbitmq-server-3.2.4/plugins-src/rabbitmq-management/LICENSE-MIT-Flot0000644000000000000000000000205512305126066024045 0ustar rootrootCopyright (c) 2007-2013 IOLA and Ole Laursen Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. rabbitmq-server-3.2.4/plugins-src/rabbitmq-management/LICENSE0000644000000000000000000000142312305126066022512 0ustar rootrootThis package, the RabbitMQ Management Plugin is licensed under the MPL. For the MPL, please see LICENSE-MPL-RabbitMQ. This package makes use of the following third party libraries: jQuery - http://jquery.com/ - MIT license, see LICENSE-MIT-jQuery164 EJS - http://embeddedjs.com/ - MIT license, see LICENSE-MIT-EJS10 Sammy - http://code.quirkey.com/sammy/ - MIT license, see LICENSE-MIT-Sammy060 webmachine - http://webmachine.basho.com/ - Apache license, 2.0 mochiweb - http://github.com/mochi/mochiweb/ - MIT license base64.js - http://code.google.com/p/stringencoders/ - BSD license, see LICENSE-BSD-base64js If you have any questions regarding licensing, please contact us at info@rabbitmq.com. rabbitmq-server-3.2.4/plugins-src/rabbitmq-auth-mechanism-ssl/0000755000000000000000000000000012305126066023073 5ustar rootrootrabbitmq-server-3.2.4/plugins-src/rabbitmq-auth-mechanism-ssl/src/0000755000000000000000000000000012305126066023662 5ustar rootrootrabbitmq-server-3.2.4/plugins-src/rabbitmq-auth-mechanism-ssl/src/rabbit_auth_mechanism_ssl_app.erl0000644000000000000000000000211512305126066032416 0ustar rootroot%% The contents of this file are subject to the Mozilla Public License %% Version 1.1 (the "License"); you may not use this file except in %% compliance with the License. You may obtain a copy of the License %% at http://www.mozilla.org/MPL/ %% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See %% the License for the specific language governing rights and %% limitations under the License. %% %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is GoPivotal, Inc. %% Copyright (c) 2007-2013 GoPivotal, Inc. All rights reserved. %% -module(rabbit_auth_mechanism_ssl_app). -behaviour(application). -export([start/2, stop/1]). %% Dummy supervisor - see Ulf Wiger's comment at %% http://erlang.2086793.n4.nabble.com/initializing-library-applications-without-processes-td2094473.html -behaviour(supervisor). -export([init/1]). start(normal, []) -> supervisor:start_link({local,?MODULE},?MODULE,[]). stop(_State) -> ok. init([]) -> {ok, {{one_for_one,3,10},[]}}. ././@LongLink0000000000000000000000000000014600000000000011566 Lustar rootrootrabbitmq-server-3.2.4/plugins-src/rabbitmq-auth-mechanism-ssl/src/rabbitmq_auth_mechanism_ssl.app.srcrabbitmq-server-3.2.4/plugins-src/rabbitmq-auth-mechanism-ssl/src/rabbitmq_auth_mechanism_ssl.app.sr0000644000000000000000000000046712305126066032545 0ustar rootroot%% -*- erlang -*- {application, rabbitmq_auth_mechanism_ssl, [{description, "RabbitMQ SSL authentication (SASL EXTERNAL)"}, {vsn, "%%VSN%%"}, {modules, []}, {registered, []}, {mod, {rabbit_auth_mechanism_ssl_app, []}}, {env, [{name_from, distinguished_name}] }, {applications, [kernel, stdlib]}]}. rabbitmq-server-3.2.4/plugins-src/rabbitmq-auth-mechanism-ssl/src/rabbit_auth_mechanism_ssl.erl0000644000000000000000000000502112305126066031555 0ustar rootroot%% The contents of this file are subject to the Mozilla Public License %% Version 1.1 (the "License"); you may not use this file except in %% compliance with the License. You may obtain a copy of the License %% at http://www.mozilla.org/MPL/ %% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See %% the License for the specific language governing rights and %% limitations under the License. %% %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is GoPivotal, Inc. %% Copyright (c) 2007-2013 GoPivotal, Inc. All rights reserved. %% -module(rabbit_auth_mechanism_ssl). -behaviour(rabbit_auth_mechanism). -export([description/0, should_offer/1, init/1, handle_response/2]). -include_lib("rabbit_common/include/rabbit.hrl"). -include_lib("public_key/include/public_key.hrl"). -rabbit_boot_step({?MODULE, [{description, "auth mechanism external"}, {mfa, {rabbit_registry, register, [auth_mechanism, <<"EXTERNAL">>, ?MODULE]}}, {requires, rabbit_registry}, {enables, kernel_ready}]}). -record(state, {username = undefined}). %% SASL EXTERNAL. SASL says EXTERNAL means "use credentials %% established by means external to the mechanism". We define that to %% mean the peer certificate's subject's CN. description() -> [{description, <<"SSL authentication mechanism using SASL EXTERNAL">>}]. should_offer(Sock) -> case rabbit_net:peercert(Sock) of nossl -> false; {error, no_peercert} -> false; {ok, _} -> true end. init(Sock) -> Username = case rabbit_net:peercert(Sock) of {ok, C} -> case rabbit_ssl:peer_cert_auth_name(C) of unsafe -> {refused, "configuration unsafe", []}; not_found -> {refused, "no name found", []}; Name -> Name end; {error, no_peercert} -> {refused, "no peer certificate", []}; nossl -> {refused, "not SSL connection", []} end, #state{username = Username}. handle_response(_Response, #state{username = Username}) -> case Username of {refused, _, _} = E -> E; _ -> rabbit_access_control:check_user_login(Username, []) end. rabbitmq-server-3.2.4/plugins-src/rabbitmq-auth-mechanism-ssl/README0000644000000000000000000000307612305126066023761 0ustar rootrootAuthenticates the user, obtaining the username from the client's SSL certificate. The user's password is not checked. In order to use this mechanism the client must connect over SSL, and present a client certificate. The mechanism must also be enabled in RabbitMQ's configuration file - see http://www.rabbitmq.com/authentication.html for more details, or in short, ensure that the 'rabbit' section of your configuration contains: {auth_mechanisms, ['PLAIN', 'AMQPLAIN', 'EXTERNAL']} to allow this mechanism in addition to the defaults, or: {auth_mechanisms, ['EXTERNAL']} to allow only this mechanism. For safety the server must be configured with the SSL options fail_if_no_peer_cert set to true and verify set to verify_peer, to force all SSL clients to have a verifiable client certificate. By default this will set the username to an RFC4514-ish string form of the certificate's subject's Distinguished Name, similar to that produced by OpenSSL's "-nameopt RFC2253" option. You can obtain this string form from a certificate with a command like: $ openssl x509 -in path/to/cert.pem -nameopt RFC2253 -subject -noout or from an existing amqps connection with commands like: $ rabbitmqctl list_connections peer_cert_subject To use the Common Name instead, ensure that the 'rabbit' section of your configuration contains: {ssl_cert_login_from, common_name} Note that the authenticated user will then be looked up in the configured authentication / authorisation backend(s) - this will be the mnesia-based user database by default, but could include other backends if so configured. rabbitmq-server-3.2.4/plugins-src/rabbitmq-auth-mechanism-ssl/.srcdist_done0000644000000000000000000000000012305126066025542 0ustar rootrootrabbitmq-server-3.2.4/plugins-src/rabbitmq-auth-mechanism-ssl/Makefile0000644000000000000000000000002712305126066024532 0ustar rootrootinclude ../umbrella.mk rabbitmq-server-3.2.4/plugins-src/rabbitmq-auth-mechanism-ssl/ebin/0000755000000000000000000000000012305126066024010 5ustar rootrootrabbitmq-server-3.2.4/plugins-src/rabbitmq-auth-mechanism-ssl/package.mk0000644000000000000000000000007612305126066025022 0ustar rootrootRELEASABLE:=true DEPS:=rabbitmq-server rabbitmq-erlang-client rabbitmq-server-3.2.4/plugins-src/rabbitmq-amqp1.0/0000755000000000000000000000000012305126066020546 5ustar rootrootrabbitmq-server-3.2.4/plugins-src/rabbitmq-amqp1.0/README.md0000644000000000000000000002017712305126066022034 0ustar rootroot# AMQP 1.0 support for RabbitMQ This plugin adds AMQP 1.0 support to RabbitMQ. # Status This is a prototype. You can send and receive messages between 0-9-1 or 0-8 clients and 1.0 clients with broadly the same semantics as you would get with 0-9-1. # Building and configuring The plugin uses the standard RabbitMQ plugin build environment; see . It will listen on the standard AMQP port, 5672. To reconfigure this, do so as you would for 0-9-1. Clients connecting with 0-9-1 and 0-8 will continue to work on the same port. The following two configuration options (which are specific to the AMQP 1.0 adapter) are accepted in the `rabbitmq_amqp1_0` section of the configuration file. AMQP 1.0 conceptually allows connections that are not authenticated with SASL (i.e. where no username and password is supplied). By default these will connect as the "guest" user. To change this, set `default_user` to a string with the name of the user to use, or the atom `none` to prevent unauthenticated connections. {default_user, "guest"} The default virtual host can be specified using the `default_vhost` setting. See the "Virtual Hosts" section below for a description. {default_vhost, <<"/">>} The `protocol_strict_mode` setting controls how strictly peers must conform to the specification. The default is not to enforce strictness, which allows non-fatal byte-counts in frames and inaccuracies in flow-control from peers. {protocol_strict_mode, false} # Clients we have tested The current field of AMQP 1.0 clients is somewhat limited. Therefore we have not achieved as much interoperability as we might like. We have tested against: * SwiftMQ Java client [1] We have done most of our testing against this client and things seem to work. * QPid / Proton C client [2] We have successfully tested against the "proton" command line tool this client ships with. * QPid / Proton Java client [2] We have not been able to get this client to get as far as opening a network connection (tested against 0.2 and 0.4). * Windows Azure Service Bus [3] It seems that the URI scheme used by this client assumes that it is connecting to Azure; it does not seem to be possible to get it to connect to another server. [1] http://www.swiftmq.com/products/router/swiftlets/sys_amqp/client/index.html [2] http://qpid.apache.org/proton/ [3] http://www.windowsazure.com/en-us/develop/net/how-to-guides/service-bus-amqp/ As new clients appear we will of course work on interoperability with them. # Interoperability with AMQP 0-9-1 ## Message payloads This implementation as a plugin aims for useful interoperability with AMQP 0-9-1 clients. AMQP 1.0 messages can be far more structured than AMQP 0-9-1 messages, which simply have a payload of bytes. The way we deal with this is that an AMQP 1.0 message with a single data section will be transcoded to an AMQP 0-9-1 message with just the bytes from that section, and vice versa. An AMQP 1.0 with any other payload will keep exactly that payload (i.e., encoded AMQP 1.0 sections, concatenated), and for AMQP 0-9-1 clients the `type` field of the `basic.properties` will contain the value `"amqp-1.0"`. Thus, AMQP 0-9-1 clients may receive messages that they cannot understand (if they don't have an AMQP 1.0 codec handy, anyway); however, these will at least be labelled. AMQP 1.0 clients shall receive exactly what they expect. ## Message properties, annotations, headers, etc. The headers and properties map as follows: AMQP 1.0 AMQP 0-9-1 Header Properties durable <---------------> delivery-mode [1] priority <---------------> priority ttl <---------------> expiration [2] first-acquirer [3] delivery-count [4] Properties message-id <---------------> message-id [5] user-id <---------------> user-id to [6] subject [6] reply-to <---------------> reply-to [6] correlation-id <---------------> correlation-id content-type <---------------> content-type content-encoding <---------------> content-encoding absolute-expiry-time [7] creation-time <---------------> timestamp Application headers <-------/-------> headers [8] [1] `durable` is `true` if and only if `delivery-mode` is `2`. [2] `expiration` is a shortstr; since RabbitMQ will expect this to be an encoded string, we translate a `ttl` to the string representation of its integer value. [3] `first-acquirer` is true if and only if the `basic.deliver` field `redelivered` is false. [4] `delivery-count` is left null. [5] AMQP 0-9-1 expects this to be a shortstr. [6] See Routing and Addressing below. [7] `absolute-expiry-time` has no corresponding field in AMQP 0-9-1, and is not supported in RabbitMQ in any case. [8] The application headers section and the `basic.properties` field `headers` are natural analogues. However, rather than try to transcode an AMQP 1.0 map to an AMQP 0-9-1 field-table, currently we discard application headers (of AMQP 1.0 messages) and headers (of AMQP 0-9-1 messages sent through to AMQP 1.0). In other words, the (AMQP 1.0) application headers section is only available to AMQP 1.0 clients, and the (AMQP 0-9-1) headers field is only available to AMQP 0-9-1 clients. Note that properties (in both AMQP 1.0 and AMQP 0-9-1) and application properties (in AMQP 1.0) are immutable; however, this can only apply when the sending and receiving clients are using the same protocol. ## Routing and Addressing In AMQP 1.0 source and destination addresses are opaque values, and each message may have a `subject` field value. For targets, addresses are: = "/exchange/" X "/" RK Publish to exchange X with routing key RK | "/exchange/" X Publish to exchange X with message subject as routing key | "/topic/" RK Publish to amq.topic with routing key RK | "/amq/queue/" Q Publish to default exchange with routing key Q | "/queue/" Q Publish to default exchange with routing key Q | "/queue" Publish to default exchange with message subj as routing key For sources, addresses are: = "/exchange/" X "/" RK Consume from temp queue bound to X with routing key RK | "/topic/" RK Consume from temp queue bound to amq.topic with routing key RK | "/amq/queue/" Q Consume from Q | "/queue/" Q Consume from Q ## Virtual Hosts AMQP 1.0 has no equivalent of AMQP 0-9-1 virtual hosts. A virtual host on the broker may be addressed when opening an AMQP 1.0 connection by setting the `hostname` field, prefixing with "vhost:". Setting the `hostname` field to "vhost:/" addresses the default virtual host. If the `hostname` field does not start with "vhost:" then the `default_vhost` configuration setting will be consulted. # Limitations and unsupported features At the minute, the RabbitMQ AMQP 1.0 adapter does not support: - "Exactly once" delivery [9] - Link recovery [9] - Full message fragmentation [10] - Resuming messages - "Modified" outcome - Filters [11] - Transactions - Source/target expiry-policy other than link-detach and timeout other than 0 - Max message size for links - Aborted transfers - TLS negotiation via the AMQP2100 handshake (although SSL is supported) [9] We do not deduplicate as a target, though we may resend as a source (messages that have no settled outcome when an outgoing link is detached will be requeued). [10] We do fragment messages over multiple frames; however, if this would overflow the session window we may discard or requeue messages. [11] In principle, filters for consuming from an exchange could translate to AMQP 0-9-1 bindings. This is not implemented, so effectively only consuming from fanout exchanges and queues is useful currently. rabbitmq-server-3.2.4/plugins-src/rabbitmq-amqp1.0/src/0000755000000000000000000000000012305126066021335 5ustar rootrootrabbitmq-server-3.2.4/plugins-src/rabbitmq-amqp1.0/src/rabbit_amqp1_0_session_sup_sup.erl0000644000000000000000000000321012305126066030137 0ustar rootroot%% The contents of this file are subject to the Mozilla Public License %% Version 1.1 (the "License"); you may not use this file except in %% compliance with the License. You may obtain a copy of the License %% at http://www.mozilla.org/MPL/ %% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See %% the License for the specific language governing rights and %% limitations under the License. %% %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is GoPivotal, Inc. %% Copyright (c) 2007-2013 GoPivotal, Inc. All rights reserved. %% -module(rabbit_amqp1_0_session_sup_sup). -behaviour(supervisor2). -export([start_link/0, start_session/2]). -export([init/1]). %% It would be much nicer if rabbit_channel_sup_sup was parameterised %% on the module. %%---------------------------------------------------------------------------- -ifdef(use_specs). -spec(start_link/0 :: () -> rabbit_types:ok_pid_or_error()). -spec(start_session/2 :: (pid(), rabbit_amqp1_0_session_sup:start_link_args()) -> {'ok', pid(), pid()}). -endif. %%---------------------------------------------------------------------------- start_link() -> supervisor2:start_link(?MODULE, []). start_session(Pid, Args) -> supervisor2:start_child(Pid, [Args]). %%---------------------------------------------------------------------------- init([]) -> {ok, {{simple_one_for_one, 0, 1}, [{session_sup, {rabbit_amqp1_0_session_sup, start_link, []}, temporary, infinity, supervisor, [rabbit_amqp1_0_session_sup]}]}}. rabbitmq-server-3.2.4/plugins-src/rabbitmq-amqp1.0/src/rabbit_amqp1_0_channel.erl0000644000000000000000000000613112305126066026313 0ustar rootroot%% The contents of this file are subject to the Mozilla Public License %% Version 1.1 (the "License"); you may not use this file except in %% compliance with the License. You may obtain a copy of the License %% at http://www.mozilla.org/MPL/ %% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See %% the License for the specific language governing rights and %% limitations under the License. %% %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is GoPivotal, Inc. %% Copyright (c) 2007-2013 GoPivotal, Inc. All rights reserved. %% -module(rabbit_amqp1_0_channel). -include_lib("amqp_client/include/amqp_client.hrl"). -include("rabbit_amqp1_0.hrl"). -export([call/2, call/3, cast/2, cast/3, cast_flow/3, subscribe/3]). -export([convert_error/1]). -import(rabbit_amqp1_0_util, [protocol_error/3]). call(Ch, Method) -> convert_error(fun () -> amqp_channel:call(Ch, Method) end). call(Ch, Method, Content) -> convert_error(fun () -> amqp_channel:call(Ch, Method, Content) end). cast(Ch, Method) -> convert_error(fun () -> amqp_channel:cast(Ch, Method) end). cast(Ch, Method, Content) -> convert_error(fun () -> amqp_channel:cast(Ch, Method, Content) end). cast_flow(Ch, Method, Content) -> convert_error(fun () -> amqp_channel:cast_flow(Ch, Method, Content) end). subscribe(Ch, Method, Subscriber) -> convert_error(fun () -> amqp_channel:subscribe(Ch, Method, Subscriber) end). convert_error(Fun) -> try Fun() catch exit:{{shutdown, {server_initiated_close, Code, Msg}}, _} -> protocol_error(convert_code(Code), Msg, []) end. %% TODO this was completely off the top of my head. Check these make sense. convert_code(?CONTENT_TOO_LARGE) -> ?V_1_0_AMQP_ERROR_FRAME_SIZE_TOO_SMALL; convert_code(?NO_ROUTE) -> ?V_1_0_AMQP_ERROR_PRECONDITION_FAILED; convert_code(?NO_CONSUMERS) -> ?V_1_0_AMQP_ERROR_PRECONDITION_FAILED; convert_code(?ACCESS_REFUSED) -> ?V_1_0_AMQP_ERROR_UNAUTHORIZED_ACCESS; convert_code(?NOT_FOUND) -> ?V_1_0_AMQP_ERROR_NOT_FOUND; convert_code(?RESOURCE_LOCKED) -> ?V_1_0_AMQP_ERROR_RESOURCE_LOCKED; convert_code(?PRECONDITION_FAILED) -> ?V_1_0_AMQP_ERROR_PRECONDITION_FAILED; convert_code(?CONNECTION_FORCED) -> ?V_1_0_CONNECTION_ERROR_CONNECTION_FORCED; convert_code(?INVALID_PATH) -> ?V_1_0_AMQP_ERROR_INVALID_FIELD; convert_code(?FRAME_ERROR) -> ?V_1_0_CONNECTION_ERROR_FRAMING_ERROR; convert_code(?SYNTAX_ERROR) -> ?V_1_0_CONNECTION_ERROR_FRAMING_ERROR; convert_code(?COMMAND_INVALID) -> ?V_1_0_CONNECTION_ERROR_FRAMING_ERROR; convert_code(?CHANNEL_ERROR) -> ?V_1_0_CONNECTION_ERROR_FRAMING_ERROR; convert_code(?UNEXPECTED_FRAME) -> ?V_1_0_CONNECTION_ERROR_FRAMING_ERROR; convert_code(?RESOURCE_ERROR) -> ?V_1_0_AMQP_ERROR_RESOURCE_LIMIT_EXCEEDED; convert_code(?NOT_ALLOWED) -> ?V_1_0_AMQP_ERROR_UNAUTHORIZED_ACCESS; convert_code(?NOT_IMPLEMENTED) -> ?V_1_0_AMQP_ERROR_NOT_IMPLEMENTED; convert_code(?INTERNAL_ERROR) -> ?V_1_0_AMQP_ERROR_INTERNAL_ERROR. rabbitmq-server-3.2.4/plugins-src/rabbitmq-amqp1.0/src/rabbit_amqp1_0_writer.erl0000644000000000000000000003032512305126066026221 0ustar rootroot%% The contents of this file are subject to the Mozilla Public License %% Version 1.1 (the "License"); you may not use this file except in %% compliance with the License. You may obtain a copy of the License %% at http://www.mozilla.org/MPL/ %% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See %% the License for the specific language governing rights and %% limitations under the License. %% %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is GoPivotal, Inc. %% Copyright (c) 2007-2013 GoPivotal, Inc. All rights reserved. %% -module(rabbit_amqp1_0_writer). -include_lib("rabbit_common/include/rabbit.hrl"). -include_lib("rabbit_common/include/rabbit_framing.hrl"). -include("rabbit_amqp1_0.hrl"). -export([start/5, start_link/5, start/6, start_link/6]). -export([send_command/2, send_command/3, send_command_sync/2, send_command_sync/3, send_command_and_notify/4, send_command_and_notify/5]). -export([internal_send_command/4, internal_send_command/6]). %% internal -export([mainloop/1, mainloop1/1]). -record(wstate, {sock, channel, frame_max, protocol, reader, stats_timer, pending}). -define(HIBERNATE_AFTER, 5000). -define(AMQP_SASL_FRAME_TYPE, 1). %%--------------------------------------------------------------------------- -ifdef(use_specs). -spec(start/5 :: (rabbit_net:socket(), rabbit_channel:channel_number(), non_neg_integer(), rabbit_types:protocol(), pid()) -> rabbit_types:ok(pid())). -spec(start_link/5 :: (rabbit_net:socket(), rabbit_channel:channel_number(), non_neg_integer(), rabbit_types:protocol(), pid()) -> rabbit_types:ok(pid())). -spec(start/6 :: (rabbit_net:socket(), rabbit_channel:channel_number(), non_neg_integer(), rabbit_types:protocol(), pid(), boolean()) -> rabbit_types:ok(pid())). -spec(start_link/6 :: (rabbit_net:socket(), rabbit_channel:channel_number(), non_neg_integer(), rabbit_types:protocol(), pid(), boolean()) -> rabbit_types:ok(pid())). -spec(send_command/2 :: (pid(), rabbit_framing:amqp_method_record()) -> 'ok'). -spec(send_command/3 :: (pid(), rabbit_framing:amqp_method_record(), rabbit_types:content()) -> 'ok'). -spec(send_command_sync/2 :: (pid(), rabbit_framing:amqp_method_record()) -> 'ok'). -spec(send_command_sync/3 :: (pid(), rabbit_framing:amqp_method_record(), rabbit_types:content()) -> 'ok'). -spec(send_command_and_notify/4 :: (pid(), pid(), pid(), rabbit_framing:amqp_method_record()) -> 'ok'). -spec(send_command_and_notify/5 :: (pid(), pid(), pid(), rabbit_framing:amqp_method_record(), rabbit_types:content()) -> 'ok'). -spec(internal_send_command/4 :: (rabbit_net:socket(), rabbit_channel:channel_number(), rabbit_framing:amqp_method_record(), rabbit_types:protocol()) -> 'ok'). -spec(internal_send_command/6 :: (rabbit_net:socket(), rabbit_channel:channel_number(), rabbit_framing:amqp_method_record(), rabbit_types:content(), non_neg_integer(), rabbit_types:protocol()) -> 'ok'). -endif. %%--------------------------------------------------------------------------- start(Sock, Channel, FrameMax, Protocol, ReaderPid) -> start(Sock, Channel, FrameMax, Protocol, ReaderPid, false). start_link(Sock, Channel, FrameMax, Protocol, ReaderPid) -> start_link(Sock, Channel, FrameMax, Protocol, ReaderPid, false). start(Sock, Channel, FrameMax, Protocol, ReaderPid, ReaderWantsStats) -> State = initial_state(Sock, Channel, FrameMax, Protocol, ReaderPid, ReaderWantsStats), {ok, proc_lib:spawn(?MODULE, mainloop, [State])}. start_link(Sock, Channel, FrameMax, Protocol, ReaderPid, ReaderWantsStats) -> State = initial_state(Sock, Channel, FrameMax, Protocol, ReaderPid, ReaderWantsStats), {ok, proc_lib:spawn_link(?MODULE, mainloop, [State])}. initial_state(Sock, Channel, FrameMax, Protocol, ReaderPid, ReaderWantsStats) -> (case ReaderWantsStats of true -> fun rabbit_event:init_stats_timer/2; false -> fun rabbit_event:init_disabled_stats_timer/2 end)(#wstate{sock = Sock, channel = Channel, frame_max = FrameMax, protocol = Protocol, reader = ReaderPid, pending = []}, #wstate.stats_timer). mainloop(State) -> try mainloop1(State) catch exit:Error -> #wstate{reader = ReaderPid, channel = Channel} = State, ReaderPid ! {channel_exit, Channel, Error} end, done. mainloop1(State = #wstate{pending = []}) -> receive Message -> ?MODULE:mainloop1(handle_message(Message, State)) after ?HIBERNATE_AFTER -> erlang:hibernate(?MODULE, mainloop, [State]) end; mainloop1(State) -> receive Message -> ?MODULE:mainloop1(handle_message(Message, State)) after 0 -> ?MODULE:mainloop1(flush(State)) end. handle_message({send_command, MethodRecord}, State) -> internal_send_command_async(MethodRecord, State); handle_message({send_command, MethodRecord, Content}, State) -> internal_send_command_async(MethodRecord, Content, State); handle_message({'$gen_call', From, {send_command_sync, MethodRecord}}, State) -> State1 = flush(internal_send_command_async(MethodRecord, State)), gen_server:reply(From, ok), State1; handle_message({'$gen_call', From, {send_command_sync, MethodRecord, Content}}, State) -> State1 = flush(internal_send_command_async(MethodRecord, Content, State)), gen_server:reply(From, ok), State1; handle_message({send_command_and_notify, QPid, ChPid, MethodRecord}, State) -> State1 = internal_send_command_async(MethodRecord, State), rabbit_amqqueue:notify_sent(QPid, ChPid), State1; handle_message({send_command_and_notify, QPid, ChPid, MethodRecord, Content}, State) -> State1 = internal_send_command_async(MethodRecord, Content, State), rabbit_amqqueue:notify_sent(QPid, ChPid), State1; handle_message({'DOWN', _MRef, process, QPid, _Reason}, State) -> rabbit_amqqueue:notify_sent_queue_down(QPid), State; handle_message({inet_reply, _, ok}, State) -> rabbit_event:ensure_stats_timer(State, #wstate.stats_timer, emit_stats); handle_message({inet_reply, _, Status}, _State) -> exit({writer, send_failed, Status}); handle_message(emit_stats, State = #wstate{reader = ReaderPid}) -> ReaderPid ! ensure_stats, rabbit_event:reset_stats_timer(State, #wstate.stats_timer); handle_message(Message, _State) -> exit({writer, message_not_understood, Message}). %%--------------------------------------------------------------------------- send_command(W, MethodRecord) -> W ! {send_command, MethodRecord}, ok. send_command(W, MethodRecord, Content) -> W ! {send_command, MethodRecord, Content}, ok. send_command_sync(W, MethodRecord) -> call(W, {send_command_sync, MethodRecord}). send_command_sync(W, MethodRecord, Content) -> call(W, {send_command_sync, MethodRecord, Content}). send_command_and_notify(W, Q, ChPid, MethodRecord) -> W ! {send_command_and_notify, Q, ChPid, MethodRecord}, ok. send_command_and_notify(W, Q, ChPid, MethodRecord, Content) -> W ! {send_command_and_notify, Q, ChPid, MethodRecord, Content}, ok. %%--------------------------------------------------------------------------- call(Pid, Msg) -> {ok, Res} = gen:call(Pid, '$gen_call', Msg, infinity), Res. %%--------------------------------------------------------------------------- %% Begin 1-0 assemble_frame(Channel, Performative, rabbit_amqp1_0_framing) -> ?DEBUG("Channel ~p <-~n~p~n~n", [Channel, rabbit_amqp1_0_framing:pprint(Performative)]), PerfBin = rabbit_amqp1_0_framing:encode_bin(Performative), rabbit_amqp1_0_binary_generator:build_frame(Channel, PerfBin); assemble_frame(Channel, Performative, rabbit_amqp1_0_sasl) -> ?DEBUG("Channel ~p <-~n~p~n~n", [Channel, rabbit_amqp1_0_framing:pprint(Performative)]), PerfBin = rabbit_amqp1_0_framing:encode_bin(Performative), rabbit_amqp1_0_binary_generator:build_frame(Channel, ?AMQP_SASL_FRAME_TYPE, PerfBin). %% Note: a transfer record can be followed by a number of other %% records to make a complete frame but unlike 0-9-1 we may have many %% content records. However, that's already been handled for us, we're %% just sending a chunk, so from this perspective it's just a binary. assemble_frames(Channel, Performative, Content, FrameMax, rabbit_amqp1_0_framing) -> ?DEBUG("Channel ~p <-~n~p~n followed by ~p bytes of content~n~n", [Channel, rabbit_amqp1_0_framing:pprint(Performative), iolist_size(Content)]), PerfBin = rabbit_amqp1_0_framing:encode_bin(Performative), rabbit_amqp1_0_binary_generator:build_frame(Channel, [PerfBin, Content]). %% End 1-0 tcp_send(Sock, Data) -> rabbit_misc:throw_on_error(inet_error, fun () -> rabbit_net:send(Sock, Data) end). internal_send_command(Sock, Channel, MethodRecord, Protocol) -> ok = tcp_send(Sock, assemble_frame(Channel, MethodRecord, Protocol)). internal_send_command(Sock, Channel, MethodRecord, Content, FrameMax, Protocol) -> ok = lists:foldl(fun (Frame, ok) -> tcp_send(Sock, Frame); (_Frame, Other) -> Other end, ok, assemble_frames(Channel, MethodRecord, Content, FrameMax, Protocol)). internal_send_command_async(MethodRecord, State = #wstate{channel = Channel, protocol = Protocol, pending = Pending}) -> Frame = assemble_frame(Channel, MethodRecord, Protocol), maybe_flush(State#wstate{pending = [Frame | Pending]}). internal_send_command_async(MethodRecord, Content, State = #wstate{channel = Channel, frame_max = FrameMax, protocol = Protocol, pending = Pending}) -> Frames = assemble_frames(Channel, MethodRecord, Content, FrameMax, Protocol), maybe_flush(State#wstate{pending = [Frames | Pending]}). %% This magic number is the tcp-over-ethernet MSS (1460) minus the %% minimum size of a AMQP basic.deliver method frame (24) plus basic %% content header (22). The idea is that we want to flush just before %% exceeding the MSS. -define(FLUSH_THRESHOLD, 1414). maybe_flush(State = #wstate{pending = Pending}) -> case iolist_size(Pending) >= ?FLUSH_THRESHOLD of true -> flush(State); false -> State end. flush(State = #wstate{pending = []}) -> State; flush(State = #wstate{sock = Sock, pending = Pending}) -> ok = port_cmd(Sock, lists:reverse(Pending)), State#wstate{pending = []}. %% gen_tcp:send/2 does a selective receive of {inet_reply, Sock, %% Status} to obtain the result. That is bad when it is called from %% the writer since it requires scanning of the writers possibly quite %% large message queue. %% %% So instead we lift the code from prim_inet:send/2, which is what %% gen_tcp:send/2 calls, do the first half here and then just process %% the result code in handle_message/2 as and when it arrives. %% %% This means we may end up happily sending data down a closed/broken %% socket, but that's ok since a) data in the buffers will be lost in %% any case (so qualitatively we are no worse off than if we used %% gen_tcp:send/2), and b) we do detect the changed socket status %% eventually, i.e. when we get round to handling the result code. %% %% Also note that the port has bounded buffers and port_command blocks %% when these are full. So the fact that we process the result %% asynchronously does not impact flow control. port_cmd(Sock, Data) -> true = try rabbit_net:port_command(Sock, Data) catch error:Error -> exit({writer, send_failed, Error}) end, ok. rabbitmq-server-3.2.4/plugins-src/rabbitmq-amqp1.0/src/rabbit_amqp1_0_incoming_link.erl0000644000000000000000000002374712305126066027537 0ustar rootroot%% The contents of this file are subject to the Mozilla Public License %% Version 1.1 (the "License"); you may not use this file except in %% compliance with the License. You may obtain a copy of the License %% at http://www.mozilla.org/MPL/ %% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See %% the License for the specific language governing rights and %% limitations under the License. %% %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is GoPivotal, Inc. %% Copyright (c) 2007-2013 GoPivotal, Inc. All rights reserved. %% -module(rabbit_amqp1_0_incoming_link). -export([attach/3, transfer/4]). -include_lib("amqp_client/include/amqp_client.hrl"). -include("rabbit_amqp1_0.hrl"). -import(rabbit_amqp1_0_util, [protocol_error/3]). %% Just make these constant for the time being. -define(INCOMING_CREDIT, 65536). -record(incoming_link, {name, exchange, routing_key, delivery_id = undefined, delivery_count = 0, send_settle_mode = undefined, recv_settle_mode = undefined, credit_used = ?INCOMING_CREDIT div 2, msg_acc = [], route_state}). attach(#'v1_0.attach'{name = Name, handle = Handle, source = Source, snd_settle_mode = SndSettleMode, rcv_settle_mode = RcvSettleMode, target = Target, initial_delivery_count = {uint, InitTransfer}}, BCh, DCh) -> %% TODO associate link name with target case ensure_target(Target, #incoming_link{ name = Name, route_state = rabbit_routing_util:init_state() }, DCh) of {ok, ServerTarget, IncomingLink = #incoming_link{ delivery_count = InitTransfer }} -> {_, _Outcomes} = rabbit_amqp1_0_link_util:outcomes(Source), %% Default is mixed Confirm = case SndSettleMode of ?V_1_0_SENDER_SETTLE_MODE_SETTLED -> false; _ when SndSettleMode == undefined; SndSettleMode == ?V_1_0_SENDER_SETTLE_MODE_UNSETTLED; SndSettleMode == ?V_1_0_SENDER_SETTLE_MODE_MIXED -> amqp_channel:register_confirm_handler(BCh, self()), rabbit_amqp1_0_channel:call(BCh, #'confirm.select'{}), true end, Flow = #'v1_0.flow'{ handle = Handle, link_credit = {uint, ?INCOMING_CREDIT}, drain = false, echo = false }, Attach = #'v1_0.attach'{ name = Name, handle = Handle, source = Source, snd_settle_mode = SndSettleMode, rcv_settle_mode = RcvSettleMode, target = ServerTarget, initial_delivery_count = undefined, % must be, I am the receiver role = ?RECV_ROLE}, %% server is receiver IncomingLink1 = IncomingLink#incoming_link{recv_settle_mode = RcvSettleMode}, {ok, [Attach, Flow], IncomingLink1, Confirm}; {error, Reason} -> rabbit_log:warning("AMQP 1.0 attach rejected ~p~n", [Reason]), %% TODO proper link establishment protocol here? protocol_error(?V_1_0_AMQP_ERROR_INVALID_FIELD, "Attach rejected: ~p", [Reason]) end. set_delivery_id({uint, D}, #incoming_link{delivery_id = undefined} = Link) -> Link#incoming_link{delivery_id = D}; set_delivery_id(DeliveryId, #incoming_link{delivery_id = D} = Link) when DeliveryId == {uint, D} orelse DeliveryId == undefined -> Link. effective_send_settle_mode(undefined, undefined) -> false; effective_send_settle_mode(undefined, SettleMode) when is_boolean(SettleMode) -> SettleMode; effective_send_settle_mode(SettleMode, undefined) when is_boolean(SettleMode) -> SettleMode; effective_send_settle_mode(SettleMode, SettleMode) when is_boolean(SettleMode) -> SettleMode. effective_recv_settle_mode(undefined, undefined) -> ?V_1_0_RECEIVER_SETTLE_MODE_FIRST; effective_recv_settle_mode(undefined, Mode) -> Mode; effective_recv_settle_mode(Mode, _) -> Mode. % TODO: validate effective settle modes against % those declared during attach % TODO: handle aborted transfers transfer(#'v1_0.transfer'{delivery_id = DeliveryId, more = true, settled = Settled}, MsgPart, #incoming_link{msg_acc = MsgAcc, send_settle_mode = SSM} = Link, _BCh) -> {ok, set_delivery_id( DeliveryId, Link#incoming_link{msg_acc = [MsgPart | MsgAcc], send_settle_mode = effective_send_settle_mode(Settled, SSM)})}; transfer(#'v1_0.transfer'{delivery_id = DeliveryId0, settled = Settled, rcv_settle_mode = RcvSettleMode, handle = Handle}, MsgPart, #incoming_link{exchange = X, routing_key = LinkRKey, delivery_count = Count, credit_used = CreditUsed, msg_acc = MsgAcc, send_settle_mode = SSM, recv_settle_mode = RSM} = Link, BCh) -> MsgBin = iolist_to_binary(lists:reverse([MsgPart | MsgAcc])), ?DEBUG("Inbound content:~n ~p~n", [[rabbit_amqp1_0_framing:pprint(Section) || Section <- rabbit_amqp1_0_framing:decode_bin(MsgBin)]]), {MsgRKey, Msg} = rabbit_amqp1_0_message:assemble(MsgBin), RKey = case LinkRKey of undefined -> MsgRKey; _ -> LinkRKey end, rabbit_amqp1_0_channel:cast_flow( BCh, #'basic.publish'{exchange = X, routing_key = RKey}, Msg), {SendFlow, CreditUsed1} = case CreditUsed - 1 of C when C =< 0 -> {true, ?INCOMING_CREDIT div 2}; D -> {false, D} end, #incoming_link{delivery_id = DeliveryId} = set_delivery_id(DeliveryId0, Link), NewLink = Link#incoming_link{ delivery_id = undefined, send_settle_mode = undefined, delivery_count = rabbit_amqp1_0_util:serial_add(Count, 1), credit_used = CreditUsed1, msg_acc = []}, Reply = case SendFlow of true -> ?DEBUG("sending flow for incoming ~p", [NewLink]), [incoming_flow(NewLink, Handle)]; false -> [] end, EffectiveSendSettleMode = effective_send_settle_mode(Settled, SSM), EffectiveRecvSettleMode = effective_recv_settle_mode(RcvSettleMode, RSM), case not EffectiveSendSettleMode andalso EffectiveRecvSettleMode =:= ?V_1_0_RECEIVER_SETTLE_MODE_SECOND of false -> ok; true -> protocol_error(?V_1_0_AMQP_ERROR_NOT_IMPLEMENTED, "rcv-settle-mode second not supported", []) end, {message, Reply, NewLink, DeliveryId, EffectiveSendSettleMode}. %% TODO default-outcome and outcomes, dynamic lifetimes ensure_target(Target = #'v1_0.target'{address = Address, dynamic = Dynamic, durable = Durable, %% TODO expiry_policy = _ExpiryPolicy, %% TODO timeout = _Timeout}, Link = #incoming_link{ route_state = RouteState }, DCh) -> DeclareParams = [{durable, rabbit_amqp1_0_link_util:durable(Durable)}, {check_exchange, true}], case Dynamic of true -> protocol_error(?V_1_0_AMQP_ERROR_NOT_IMPLEMENTED, "Dynamic targets not supported", []); _ -> ok end, case Address of {utf8, Destination} -> case rabbit_routing_util:parse_endpoint(Destination, true) of {ok, Dest} -> {ok, _Queue, RouteState1} = rabbit_amqp1_0_channel:convert_error( fun () -> rabbit_routing_util:ensure_endpoint( dest, DCh, Dest, DeclareParams, RouteState) end), {XName, RK} = rabbit_routing_util:parse_routing(Dest), {ok, Target, Link#incoming_link{ route_state = RouteState1, exchange = list_to_binary(XName), routing_key = case RK of undefined -> undefined; [] -> undefined; _ -> list_to_binary(RK) end}}; {error, _} = E -> E end; _Else -> {error, {unknown_address, Address}} end. incoming_flow(#incoming_link{ delivery_count = Count }, Handle) -> #'v1_0.flow'{handle = Handle, delivery_count = {uint, Count}, link_credit = {uint, ?INCOMING_CREDIT}}. rabbitmq-server-3.2.4/plugins-src/rabbitmq-amqp1.0/src/rabbitmq_amqp1_0.app.src0000644000000000000000000000046512305126066025751 0ustar rootroot{application, rabbitmq_amqp1_0, [{description, "AMQP 1.0 support for RabbitMQ"}, {vsn, "%%VSN%%"}, {modules, []}, {registered, []}, {env, [{default_user, "guest"}, {default_vhost, <<"/">>}, {protocol_strict_mode, false}]}, {applications, [kernel, stdlib, rabbit, amqp_client]}]}. rabbitmq-server-3.2.4/plugins-src/rabbitmq-amqp1.0/src/rabbit_amqp1_0_binary_parser.erl0000644000000000000000000001436112305126066027547 0ustar rootroot%% The contents of this file are subject to the Mozilla Public License %% Version 1.1 (the "License"); you may not use this file except in %% compliance with the License. You may obtain a copy of the License %% at http://www.mozilla.org/MPL/ %% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See %% the License for the specific language governing rights and %% limitations under the License. %% %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is GoPivotal, Inc. %% Copyright (c) 2007-2013 GoPivotal, Inc. All rights reserved. %% -module(rabbit_amqp1_0_binary_parser). -export([parse/1, parse_all/1]). -include("rabbit_amqp1_0.hrl"). -ifdef(use_specs). -spec(parse/1 :: (binary()) -> tuple()). -endif. parse_all(ValueBin) when is_binary(ValueBin) -> lists:reverse(parse_all([], parse(ValueBin))). parse_all(Acc, {Value, <<>>}) -> [Value | Acc]; parse_all(Acc, {Value, Rest}) -> parse_all([Value | Acc], parse(Rest)). parse(<>) -> parse_described(Rest); parse(Rest) -> parse_primitive0(Rest). parse_described(Bin) -> {Descriptor, Rest1} = parse(Bin), {Value, Rest2} = parse(Rest1), {{described, Descriptor, Value}, Rest2}. parse_primitive0(<>) -> parse_primitive(Type, Rest). -define(SYM(V), {symbol, binary_to_list(V)}). %% Constants parse_primitive(16#40, Rest) -> {null, Rest}; parse_primitive(16#41, Rest) -> {true, Rest}; parse_primitive(16#42, Rest) -> {false, Rest}; parse_primitive(16#43, Rest) -> {{uint, 0}, Rest}; parse_primitive(16#44, Rest) -> {{ulong, 0}, Rest}; %% Fixed-widths. Most integral types have a compact encoding as a byte. parse_primitive(16#50, <>) -> {{ubyte, V}, R}; parse_primitive(16#51, <>) -> {{byte, V}, R}; parse_primitive(16#52, <>) -> {{uint, V}, R}; parse_primitive(16#53, <>) -> {{ulong, V}, R}; parse_primitive(16#54, <>) -> {{int, V}, R}; parse_primitive(16#55, <>) -> {{long, V}, R}; parse_primitive(16#56, <<0:8/unsigned, R/binary>>) -> {false, R}; parse_primitive(16#56, <<1:8/unsigned, R/binary>>) -> {true, R}; parse_primitive(16#60, <>) -> {{ushort, V}, R}; parse_primitive(16#61, <>) -> {{short, V}, R}; parse_primitive(16#70, <>) -> {{uint, V}, R}; parse_primitive(16#71, <>) -> {{int, V}, R}; parse_primitive(16#72, <>) -> {{float, V}, R}; parse_primitive(16#73, <>) -> {{char, Utf32}, R}; parse_primitive(16#80, <>) -> {{ulong, V}, R}; parse_primitive(16#81, <>) -> {{long, V}, R}; parse_primitive(16#82, <>) -> {{double, V}, R}; parse_primitive(16#83, <>) -> {{timestamp, TS}, R}; parse_primitive(16#98, <>) -> {{uuid, Uuid}, R}; %% Variable-widths parse_primitive(16#a0,<>)-> {{binary, V}, R}; parse_primitive(16#a1,<>)-> {{utf8, V}, R}; parse_primitive(16#a3,<>)-> {?SYM(V), R}; parse_primitive(16#b3,<>)-> {?SYM(V), R}; parse_primitive(16#b0,<>)-> {{binary, V}, R}; parse_primitive(16#b1,<>)-> {{utf8, V}, R}; %% Compounds parse_primitive(16#45, R) -> {{list, []}, R}; parse_primitive(16#c0,<>) -> {{list, parse_compound(8, CountAndValue)}, R}; parse_primitive(16#c1,<>) -> List = parse_compound(8, CountAndValue), {{map, mapify(List)}, R}; parse_primitive(16#d0,<>) -> {{list, parse_compound(32, CountAndValue)}, R}; parse_primitive(16#d1,<>) -> List = parse_compound(32, CountAndValue), {{map, mapify(List)}, R}; %% Arrays parse_primitive(16#e0,<>) -> {{list, parse_array(8, CountAndV)}, R}; parse_primitive(16#f0,<>) -> {{list, parse_array(32, CountAndV)}, R}; %% NaN or +-inf parse_primitive(16#72, <>) -> {{as_is, 16#72, <>}, R}; parse_primitive(16#82, <>) -> {{as_is, 16#82, <>}, R}; %% decimals parse_primitive(16#74, <>) -> {{as_is, 16#74, <>}, R}; parse_primitive(16#84, <>) -> {{as_is, 16#84, <>}, R}; parse_primitive(16#94, <>) -> {{as_is, 16#94, <>}, R}; parse_primitive(Type, _) -> throw({primitive_type_unsupported, Type}). parse_compound(UnitSize, Bin) -> <> = Bin, parse_compound1(Count, Bin1, []). parse_compound1(0, <<>>, List) -> lists:reverse(List); parse_compound1(_Left, <<>>, List) -> case application:get_env(rabbitmq_amqp1_0, protocol_strict_mode) of {ok, false} -> lists:reverse(List); %% ignore miscount {ok, true} -> throw(compound_datatype_miscount) end; parse_compound1(Count, Bin, Acc) -> {Value, Rest} = parse(Bin), parse_compound1(Count - 1, Rest, [Value | Acc]). parse_array(UnitSize, Bin) -> <> = Bin, parse_array1(Count, Bin1). parse_array1(Count, <>) -> {Descriptor, Rest1} = parse(Rest), List = parse_array1(Count, Rest1), lists:map(fun (Value) -> {described, Descriptor, Value} end, List); parse_array1(Count, <>) -> parse_array2(Count, Type, ArrayBin, []). parse_array2(0, _Type, <<>>, Acc) -> lists:reverse(Acc); parse_array2(Count, Type, Bin, Acc) -> {Value, Rest} = parse_primitive(Type, Bin), parse_array2(Count - 1, Type, Rest, [Value | Acc]). mapify([]) -> []; mapify([Key, Value | Rest]) -> [{Key, Value} | mapify(Rest)]. rabbitmq-server-3.2.4/plugins-src/rabbitmq-amqp1.0/src/rabbit_amqp1_0_binary_generator.erl0000644000000000000000000001217712305126066030244 0ustar rootroot%% The contents of this file are subject to the Mozilla Public License %% Version 1.1 (the "License"); you may not use this file except in %% compliance with the License. You may obtain a copy of the License %% at http://www.mozilla.org/MPL/ %% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See %% the License for the specific language governing rights and %% limitations under the License. %% %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is GoPivotal, Inc. %% Copyright (c) 2007-2013 GoPivotal, Inc. All rights reserved. %% -module(rabbit_amqp1_0_binary_generator). -export([generate/1, build_frame/2, build_frame/3, build_heartbeat_frame/0]). -include("rabbit_amqp1_0.hrl"). -ifdef(use_specs). -spec(generate/1 :: (tuple()) -> iolist()). -spec(build_frame/2 :: (int(), iolist()) -> iolist()). -endif. -define(AMQP_FRAME_TYPE, 0). -define(DOFF, 2). -define(VAR_1_LIMIT, 16#FF). build_frame(Channel, Payload) -> build_frame(Channel, ?AMQP_FRAME_TYPE, Payload). build_frame(Channel, FrameType, Payload) -> Size = iolist_size(Payload) + 8, % frame header and no extension [ <>, Payload ]. build_heartbeat_frame() -> %% length is inclusive <<8:32, ?DOFF:8, ?AMQP_FRAME_TYPE:8, 0:16>>. generate({described, Descriptor, Value}) -> DescBin = generate(Descriptor), ValueBin = generate(Value), [ ?DESCRIBED_BIN, DescBin, ValueBin ]; generate(null) -> <<16#40>>; generate(true) -> <<16#41>>; generate(false) -> <<16#42>>; %% some integral types have a compact encoding as a byte; this is in %% particular for the descriptors of AMQP types, which have the domain %% bits set to zero and values < 256. generate({ubyte, V}) -> <<16#50,V:8/unsigned>>; generate({ushort, V}) -> <<16#60,V:16/unsigned>>; generate({uint, V}) when V =:= 0 -> <<16#43>>; generate({uint, V}) when V < 256 -> <<16#52,V:8/unsigned>>; generate({uint, V}) -> <<16#70,V:32/unsigned>>; generate({ulong, V}) when V =:= 0 -> <<16#44>>; generate({ulong, V}) when V < 256 -> <<16#53,V:8/unsigned>>; generate({ulong, V}) -> <<16#80,V:64/unsigned>>; generate({byte, V}) -> <<16#51,V:8/signed>>; generate({short, V}) -> <<16#61,V:16/signed>>; generate({int, V}) when V<128 andalso V>-129 -> <<16#54,V:8/signed>>; generate({int, V}) -> <<16#71,V:32/signed>>; generate({long, V}) when V<128 andalso V>-129 -> <<16#55,V:8/signed>>; generate({long, V}) -> <<16#81,V:64/signed>>; generate({float, V}) -> <<16#72,V:32/float>>; generate({double, V}) -> <<16#82,V:64/float>>; generate({char, V}) -> <<16#73,V:4/binary>>; generate({timestamp,V}) -> <<16#83,V:64/signed>>; generate({uuid, V}) -> <<16#98,V:16/binary>>; generate({utf8, V}) when size(V) < ?VAR_1_LIMIT -> [<<16#a1,(size(V)):8>>, V]; generate({utf8, V}) -> [<<16#b1,(size(V)):32>>, V]; generate({symbol, V}) -> [<<16#a3,(length(V)):8>>, list_to_binary(V)]; generate({binary, V}) -> Size = iolist_size(V), if Size < ?VAR_1_LIMIT -> [<<16#a0,Size:8>>, V]; true -> [<<16#b0,Size:32>>, V] end; generate({list, []}) -> <<16#45>>; generate({list, List}) -> Count = length(List), Compound = lists:map(fun generate/1, List), S = iolist_size(Compound), %% S < 256 -> Count < 256 if S > 255 -> [<<16#d0, (S + 4):32/unsigned, Count:32/unsigned>>, Compound]; true -> [<<16#c0, (S + 1):8/unsigned, Count:8/unsigned>>, Compound] end; generate({map, ListOfPairs}) -> Count = length(ListOfPairs) * 2, Compound = lists:map(fun ({Key, Val}) -> [(generate(Key)), (generate(Val))] end, ListOfPairs), S = iolist_size(Compound), if S > 255 -> [<<16#d1,(S + 4):32,Count:32>>, Compound]; true -> [<<16#c1,(S + 1):8,Count:8>>, Compound] end; generate({array, Type, List}) -> Count = length(List), Body = iolist_to_binary( [constructor(Type), [generate(Type, I) || I <- List]]), S = size(Body), %% S < 256 -> Count < 256 if S > 255 -> [<<16#f0, (S + 4):32/unsigned, Count:32/unsigned>>, Body]; true -> [<<16#e0, (S + 1):8/unsigned, Count:8/unsigned>>, Body] end; generate({as_is, TypeCode, Bin}) -> <>. %% TODO again these are a stub to get SASL working. New codec? Will %% that ever happen? If not we really just need to split generate/1 %% up into things like these... constructor(symbol) -> <<16#a3>>. generate(symbol, Value) -> [<<(length(Value)):8>>, list_to_binary(Value)]. rabbitmq-server-3.2.4/plugins-src/rabbitmq-amqp1.0/src/rabbit_amqp1_0_util.erl0000644000000000000000000000520512305126066025661 0ustar rootroot%% The contents of this file are subject to the Mozilla Public License %% Version 1.1 (the "License"); you may not use this file except in %% compliance with the License. You may obtain a copy of the License %% at http://www.mozilla.org/MPL/ %% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See %% the License for the specific language governing rights and %% limitations under the License. %% %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is GoPivotal, Inc. %% Copyright (c) 2007-2013 GoPivotal, Inc. All rights reserved. %% -module(rabbit_amqp1_0_util). -include("rabbit_amqp1_0.hrl"). -export([protocol_error/3]). -export([serial_add/2, serial_compare/2, serial_diff/2]). -ifdef(use_specs). -export_type([serial_number/0]). -type(serial_number() :: non_neg_integer()). -type(serial_compare_result() :: 'equal' | 'less' | 'greater'). -spec(serial_add/2 :: (serial_number(), non_neg_integer()) -> serial_number()). -spec(serial_compare/2 :: (serial_number(), serial_number()) -> serial_compare_result()). -spec(serial_diff/2 :: (serial_number(), serial_number()) -> integer()). -endif. protocol_error(Condition, Msg, Args) -> exit(#'v1_0.error'{ condition = Condition, description = {utf8, list_to_binary( lists:flatten(io_lib:format(Msg, Args)))} }). %% Serial arithmetic for unsigned ints. %% http://www.faqs.org/rfcs/rfc1982.html %% SERIAL_BITS = 32 %% 2 ^ SERIAL_BITS -define(SERIAL_MAX, 16#100000000). %% 2 ^ (SERIAL_BITS - 1) - 1 -define(SERIAL_MAX_ADDEND, 16#7fffffff). serial_add(S, N) when N =< ?SERIAL_MAX_ADDEND -> (S + N) rem ?SERIAL_MAX; serial_add(S, N) -> exit({out_of_bound_serial_addition, S, N}). serial_compare(A, B) -> if A =:= B -> equal; (A < B andalso B - A < ?SERIAL_MAX_ADDEND) orelse (A > B andalso A - B > ?SERIAL_MAX_ADDEND) -> less; (A < B andalso B - A > ?SERIAL_MAX_ADDEND) orelse (A > B andalso B - A < ?SERIAL_MAX_ADDEND) -> greater; true -> exit({indeterminate_serial_comparison, A, B}) end. -define(SERIAL_DIFF_BOUND, 16#80000000). serial_diff(A, B) -> Diff = A - B, if Diff > (?SERIAL_DIFF_BOUND) -> %% B is actually greater than A - (?SERIAL_MAX - Diff); Diff < - (?SERIAL_DIFF_BOUND) -> ?SERIAL_MAX + Diff; Diff < ?SERIAL_DIFF_BOUND andalso Diff > -?SERIAL_DIFF_BOUND -> Diff; true -> exit({indeterminate_serial_diff, A, B}) end. rabbitmq-server-3.2.4/plugins-src/rabbitmq-amqp1.0/src/rabbit_amqp1_0_outgoing_link.erl0000644000000000000000000002554612305126066027566 0ustar rootroot%% The contents of this file are subject to the Mozilla Public License %% Version 1.1 (the "License"); you may not use this file except in %% compliance with the License. You may obtain a copy of the License %% at http://www.mozilla.org/MPL/ %% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See %% the License for the specific language governing rights and %% limitations under the License. %% %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is GoPivotal, Inc. %% Copyright (c) 2007-2013 GoPivotal, Inc. All rights reserved. %% -module(rabbit_amqp1_0_outgoing_link). -export([attach/3, delivery/6, transferred/3, credit_drained/4, flow/3]). -include_lib("amqp_client/include/amqp_client.hrl"). -include("rabbit_amqp1_0.hrl"). -import(rabbit_amqp1_0_util, [protocol_error/3, serial_add/2]). -import(rabbit_amqp1_0_link_util, [handle_to_ctag/1]). -define(INIT_TXFR_COUNT, 0). -define(DEFAULT_SEND_SETTLED, false). -record(outgoing_link, {queue, delivery_count = 0, send_settled, default_outcome, route_state}). attach(#'v1_0.attach'{name = Name, handle = Handle, source = Source, snd_settle_mode = SndSettleMode, rcv_settle_mode = RcvSettleMode}, BCh, DCh) -> {DefaultOutcome, Outcomes} = rabbit_amqp1_0_link_util:outcomes(Source), SndSettled = case SndSettleMode of ?V_1_0_SENDER_SETTLE_MODE_SETTLED -> true; ?V_1_0_SENDER_SETTLE_MODE_UNSETTLED -> false; _ -> ?DEFAULT_SEND_SETTLED end, DOSym = rabbit_amqp1_0_framing:symbol_for(DefaultOutcome), case ensure_source(Source, #outgoing_link{delivery_count = ?INIT_TXFR_COUNT, send_settled = SndSettled, default_outcome = DOSym, route_state = rabbit_routing_util:init_state()}, DCh) of {ok, Source1, OutgoingLink = #outgoing_link{queue = QueueName}} -> CTag = handle_to_ctag(Handle), case rabbit_amqp1_0_channel:subscribe( BCh, #'basic.consume'{ queue = QueueName, consumer_tag = CTag, %% we will ack when we've transferred %% a message, or when we get an ack %% from the client. no_ack = false, %% TODO exclusive? exclusive = false, arguments = [{<<"x-credit">>, table, [{<<"credit">>, long, 0}, {<<"drain">>, boolean, false}]}]}, self()) of #'basic.consume_ok'{} -> %% TODO we should avoid the race by getting the queue to send %% attach back, but a.t.m. it would use the wrong codec. {ok, [#'v1_0.attach'{ name = Name, handle = Handle, initial_delivery_count = {uint, ?INIT_TXFR_COUNT}, snd_settle_mode = case SndSettled of true -> ?V_1_0_SENDER_SETTLE_MODE_SETTLED; false -> ?V_1_0_SENDER_SETTLE_MODE_UNSETTLED end, rcv_settle_mode = RcvSettleMode, source = Source1#'v1_0.source'{ default_outcome = DefaultOutcome, outcomes = Outcomes }, role = ?SEND_ROLE}], OutgoingLink}; Fail -> protocol_error(?V_1_0_AMQP_ERROR_INTERNAL_ERROR, "Consume failed: ~p", [Fail]) end; {error, _Reason} -> %% TODO Deal with this properly -- detach and what have you {ok, [#'v1_0.attach'{source = undefined}]} end. credit_drained(#'basic.credit_drained'{credit_drained = CreditDrained}, Handle, Link = #outgoing_link{delivery_count = Count0}, WriterPid) -> Count = Count0 + CreditDrained, %% The transfer count that is given by the queue should be at %% least that we have locally, since we will either have received %% all the deliveries and transferred them, or the queue will have %% advanced it due to drain. So we adopt the queue's idea of the %% count. %% TODO account for it not being there any more F = #'v1_0.flow'{ handle = Handle, delivery_count = {uint, Count}, link_credit = {uint, 0}, available = {uint, 0}, drain = true }, rabbit_amqp1_0_writer:send_command(WriterPid, F), Link#outgoing_link{delivery_count = Count}. flow(#outgoing_link{delivery_count = LocalCount}, #'v1_0.flow'{handle = Handle, delivery_count = Count0, link_credit = {uint, RemoteCredit}, drain = Drain0}, BCh) -> {uint, RemoteCount} = default(Count0, {uint, LocalCount}), Drain = default(Drain0, false), %% See section 2.6.7 LocalCredit = RemoteCount + RemoteCredit - LocalCount, CTag = handle_to_ctag(Handle), #'basic.credit_ok'{available = Available} = rabbit_amqp1_0_channel:call( BCh, #'basic.credit'{consumer_tag = CTag, credit = LocalCredit, drain = Drain}), case Available of -1 -> {ok, []}; %% We don't know - probably because this flow relates %% to a handle that does not yet exist %% TODO is this an error? _ -> {ok, [#'v1_0.flow'{ handle = Handle, delivery_count = {uint, LocalCount}, link_credit = {uint, LocalCredit}, available = {uint, Available}, drain = Drain}]} end. default(undefined, Default) -> Default; default(Thing, _Default) -> Thing. ensure_source(Source = #'v1_0.source'{address = Address, dynamic = Dynamic, durable = Durable, %% TODO expiry_policy = _ExpiryPolicy, %% TODO timeout = _Timeout}, Link = #outgoing_link{ route_state = RouteState }, DCh) -> DeclareParams = [{durable, rabbit_amqp1_0_link_util:durable(Durable)}, {check_exchange, true}], case Dynamic of true -> protocol_error(?V_1_0_AMQP_ERROR_NOT_IMPLEMENTED, "Dynamic sources not supported", []); _ -> ok end, case Address of {utf8, Destination} -> case rabbit_routing_util:parse_endpoint(Destination, false) of {ok, Dest} -> {ok, Queue, RouteState1} = rabbit_amqp1_0_channel:convert_error( fun() -> rabbit_routing_util:ensure_endpoint( source, DCh, Dest, DeclareParams, RouteState) end), ER = rabbit_routing_util:parse_routing(Dest), ok = rabbit_routing_util:ensure_binding(Queue, ER, DCh), {ok, Source, Link#outgoing_link{route_state = RouteState1, queue = Queue}} end; _ -> {error, {unknown_address, Address}} end. delivery(Deliver = #'basic.deliver'{delivery_tag = DeliveryTag, routing_key = RKey}, Msg, FrameMax, Handle, Session, #outgoing_link{send_settled = SendSettled, default_outcome = DefaultOutcome}) -> DeliveryId = rabbit_amqp1_0_session:next_delivery_id(Session), Session1 = rabbit_amqp1_0_session:record_outgoing( DeliveryTag, SendSettled, DefaultOutcome, Session), Txfr = #'v1_0.transfer'{handle = Handle, delivery_tag = {binary, <>}, delivery_id = {uint, DeliveryId}, %% The only one in AMQP 1-0 message_format = {uint, 0}, settled = SendSettled, resume = false, more = false, aborted = false, %% TODO: actually batchable would be fine, %% but in any case it's only a hint batchable = false}, Msg1_0 = rabbit_amqp1_0_message:annotated_message( RKey, Deliver, Msg), ?DEBUG("Outbound content:~n ~p~n", [[rabbit_amqp1_0_framing:pprint(Section) || Section <- rabbit_amqp1_0_framing:decode_bin( iolist_to_binary(Msg1_0))]]), %% TODO Ugh TLen = iolist_size(rabbit_amqp1_0_framing:encode_bin(Txfr)), Frames = case FrameMax of unlimited -> [[Txfr, Msg1_0]]; _ -> encode_frames(Txfr, Msg1_0, FrameMax - TLen, []) end, {ok, Frames, Session1}. encode_frames(_T, _Msg, MaxContentLen, _Transfers) when MaxContentLen =< 0 -> protocol_error(?V_1_0_AMQP_ERROR_FRAME_SIZE_TOO_SMALL, "Frame size is too small by ~p bytes", [-MaxContentLen]); encode_frames(T, Msg, MaxContentLen, Transfers) -> case iolist_size(Msg) > MaxContentLen of true -> <> = iolist_to_binary(Msg), T1 = T#'v1_0.transfer'{more = true}, encode_frames(T, Rest, MaxContentLen, [[T1, Chunk] | Transfers]); false -> lists:reverse([[T, Msg] | Transfers]) end. transferred(DeliveryTag, Channel, Link = #outgoing_link{ delivery_count = Count, send_settled = SendSettled }) -> if SendSettled -> rabbit_amqp1_0_channel:cast( Channel, #'basic.ack'{ delivery_tag = DeliveryTag }); true -> ok end, Link#outgoing_link{delivery_count = serial_add(Count, 1)}. rabbitmq-server-3.2.4/plugins-src/rabbitmq-amqp1.0/src/rabbit_amqp1_0_framing.erl0000644000000000000000000001272012305126066026327 0ustar rootroot%% The contents of this file are subject to the Mozilla Public License %% Version 1.1 (the "License"); you may not use this file except in %% compliance with the License. You may obtain a copy of the License %% at http://www.mozilla.org/MPL/ %% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See %% the License for the specific language governing rights and %% limitations under the License. %% %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is GoPivotal, Inc. %% Copyright (c) 2007-2013 GoPivotal, Inc. All rights reserved. %% -module(rabbit_amqp1_0_framing). -export([encode/1, encode_described/3, decode/1, version/0, symbol_for/1, number_for/1, encode_bin/1, decode_bin/1, pprint/1]). %% debug -export([fill_from_list/2, fill_from_map/2]). -include("rabbit_amqp1_0.hrl"). version() -> {1, 0, 0}. %% These are essentially in lieu of code generation .. fill_from_list(Record, Fields) -> {Res, _} = lists:foldl( fun (Field, {Record1, Num}) -> DecodedField = decode(Field), {setelement(Num, Record1, DecodedField), Num + 1} end, {Record, 2}, Fields), Res. fill_from_map(Record, Fields) -> {Res, _} = lists:foldl( fun (Key, {Record1, Num}) -> case proplists:get_value(Key, Fields) of undefined -> {Record1, Num+1}; Value -> {setelement(Num, Record1, decode(Value)), Num+1} end end, {Record, 2}, keys(Record)), Res. %% TODO should this be part of a more general handler for AMQP values etc? fill_from_binary(F = #'v1_0.data'{}, Field) -> F#'v1_0.data'{content = Field}. %% TODO so should this? fill_from_amqp(F = #'v1_0.amqp_value'{}, Field) -> F#'v1_0.amqp_value'{content = Field}. keys(Record) -> [{symbol, symbolify(K)} || K <- rabbit_amqp1_0_framing0:fields(Record)]. symbolify(FieldName) when is_atom(FieldName) -> re:replace(atom_to_list(FieldName), "_", "-", [{return,list}, global]). %% TODO: in fields of composite types with multiple=true, "a null %% value and a zero-length array (with a correct type for its %% elements) both describe an absence of a value and should be treated %% as semantically identical." (see section 1.3) %% A sequence comes as an arbitrary list of values; it's not a %% composite type. decode({described, Descriptor, {list, Fields}}) -> case rabbit_amqp1_0_framing0:record_for(Descriptor) of #'v1_0.amqp_sequence'{} -> #'v1_0.amqp_sequence'{content = [decode(F) || F <- Fields]}; Else -> fill_from_list(Else, Fields) end; decode({described, Descriptor, {map, Fields}}) -> case rabbit_amqp1_0_framing0:record_for(Descriptor) of #'v1_0.application_properties'{} -> #'v1_0.application_properties'{content = decode_map(Fields)}; #'v1_0.delivery_annotations'{} -> #'v1_0.delivery_annotations'{content = decode_map(Fields)}; #'v1_0.message_annotations'{} -> #'v1_0.message_annotations'{content = decode_map(Fields)}; #'v1_0.footer'{} -> #'v1_0.footer'{content = decode_map(Fields)}; Else -> fill_from_map(Else, Fields) end; decode({described, Descriptor, {binary, Field}}) -> fill_from_binary(rabbit_amqp1_0_framing0:record_for(Descriptor), Field); decode({described, Descriptor, Field}) -> fill_from_amqp(rabbit_amqp1_0_framing0:record_for(Descriptor), Field); decode(null) -> undefined; decode(Other) -> Other. decode_map(Fields) -> [{decode(K), decode(V)} || {K, V} <- Fields]. encode_described(list, ListOrNumber, Frame) -> Desc = descriptor(ListOrNumber), {described, Desc, {list, lists:map(fun encode/1, tl(tuple_to_list(Frame)))}}; encode_described(map, ListOrNumber, Frame) -> Desc = descriptor(ListOrNumber), {described, Desc, {map, lists:zip(keys(Frame), lists:map(fun encode/1, tl(tuple_to_list(Frame))))}}; encode_described(binary, ListOrNumber, #'v1_0.data'{content = Content}) -> Desc = descriptor(ListOrNumber), {described, Desc, {binary, Content}}; encode_described('*', ListOrNumber, #'v1_0.amqp_value'{content = Content}) -> Desc = descriptor(ListOrNumber), {described, Desc, Content}; encode_described(annotations, ListOrNumber, Frame) -> encode_described(map, ListOrNumber, Frame). encode(X) -> rabbit_amqp1_0_framing0:encode(X). encode_bin(X) -> rabbit_amqp1_0_binary_generator:generate(encode(X)). decode_bin(X) -> [decode(PerfDesc) || PerfDesc <- decode_bin0(X)]. decode_bin0(<<>>) -> []; decode_bin0(X) -> {PerfDesc, Rest} = rabbit_amqp1_0_binary_parser:parse(X), [PerfDesc | decode_bin0(Rest)]. symbol_for(X) -> rabbit_amqp1_0_framing0:symbol_for(X). number_for(X) -> rabbit_amqp1_0_framing0:number_for(X). descriptor(Symbol) when is_list(Symbol) -> {symbol, Symbol}; descriptor(Number) when is_number(Number) -> {ulong, Number}. pprint(Thing) when is_tuple(Thing) -> case rabbit_amqp1_0_framing0:fields(Thing) of unknown -> Thing; Names -> [T|L] = tuple_to_list(Thing), {T, lists:zip(Names, [pprint(I) || I <- L])} end; pprint(Other) -> Other. rabbitmq-server-3.2.4/plugins-src/rabbitmq-amqp1.0/src/rabbit_amqp1_0_link_util.erl0000644000000000000000000000472212305126066026701 0ustar rootroot%% The contents of this file are subject to the Mozilla Public License %% Version 1.1 (the "License"); you may not use this file except in %% compliance with the License. You may obtain a copy of the License %% at http://www.mozilla.org/MPL/ %% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See %% the License for the specific language governing rights and %% limitations under the License. %% %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is GoPivotal, Inc. %% Copyright (c) 2007-2013 GoPivotal, Inc. All rights reserved. %% -module(rabbit_amqp1_0_link_util). -include_lib("amqp_client/include/amqp_client.hrl"). -include("rabbit_amqp1_0.hrl"). -export([outcomes/1, ctag_to_handle/1, handle_to_ctag/1, durable/1]). -define(EXCHANGE_SUB_LIFETIME, "delete-on-close"). -define(DEFAULT_OUTCOME, #'v1_0.released'{}). -define(OUTCOMES, [?V_1_0_SYMBOL_ACCEPTED, ?V_1_0_SYMBOL_REJECTED, ?V_1_0_SYMBOL_RELEASED]). outcomes(Source) -> {DefaultOutcome, Outcomes} = case Source of #'v1_0.source' { default_outcome = DO, outcomes = Os } -> DO1 = case DO of undefined -> ?DEFAULT_OUTCOME; _ -> DO end, Os1 = case Os of undefined -> ?OUTCOMES; _ -> Os end, {DO1, Os1}; _ -> {?DEFAULT_OUTCOME, ?OUTCOMES} end, case [O || O <- Outcomes, not lists:member(O, ?OUTCOMES)] of [] -> {DefaultOutcome, {array, symbol, [X || {symbol, X} <- Outcomes]}}; Bad -> rabbit_amqp1_0_util:protocol_error( ?V_1_0_AMQP_ERROR_NOT_IMPLEMENTED, "Outcomes not supported: ~p", [Bad]) end. handle_to_ctag({uint, H}) -> <<"ctag-", H:32/integer>>. ctag_to_handle(<<"ctag-", H:32/integer>>) -> {uint, H}. durable(undefined) -> false; %% default: none durable(?V_1_0_TERMINUS_DURABILITY_NONE) -> false; %% This one means "existence of the thing is durable, but unacked msgs %% aren't". We choose to upgrade that. durable(?V_1_0_TERMINUS_DURABILITY_CONFIGURATION) -> true; durable(?V_1_0_TERMINUS_DURABILITY_UNSETTLED_STATE) -> true. rabbitmq-server-3.2.4/plugins-src/rabbitmq-amqp1.0/src/rabbit_amqp1_0_reader.erl0000644000000000000000000007170412305126066026155 0ustar rootroot%% The contents of this file are subject to the Mozilla Public License %% Version 1.1 (the "License"); you may not use this file except in %% compliance with the License. You may obtain a copy of the License %% at http://www.mozilla.org/MPL/ %% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See %% the License for the specific language governing rights and %% limitations under the License. %% %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is GoPivotal, Inc. %% Copyright (c) 2007-2013 GoPivotal, Inc. All rights reserved. %% -module(rabbit_amqp1_0_reader). -include_lib("rabbit_common/include/rabbit.hrl"). -include_lib("rabbit_common/include/rabbit_framing.hrl"). -include_lib("kernel/include/inet.hrl"). -include("rabbit_amqp1_0.hrl"). -export([init/2, mainloop/2]). %% TODO which of these are needed? -export([shutdown/2]). -export([system_continue/3, system_terminate/4, system_code_change/4]). -export([conserve_resources/3]). -import(rabbit_amqp1_0_util, [protocol_error/3]). -define(HANDSHAKE_TIMEOUT, 10). -define(NORMAL_TIMEOUT, 3). -define(CLOSING_TIMEOUT, 30). -define(SILENT_CLOSE_DELAY, 3). %%-------------------------------------------------------------------------- -record(v1, {parent, sock, connection, callback, recv_len, pending_recv, connection_state, queue_collector, heartbeater, helper_sup, channel_sup_sup_pid, buf, buf_len, throttle}). -record(connection, {user, timeout_sec, frame_max, auth_mechanism, auth_state, hostname}). -record(throttle, {alarmed_by, last_blocked_by, last_blocked_at}). -define(IS_RUNNING(State), (State#v1.connection_state =:= running orelse State#v1.connection_state =:= blocking orelse State#v1.connection_state =:= blocked)). %%-------------------------------------------------------------------------- unpack_from_0_9_1({Parent, Sock,RecvLen, PendingRecv, HelperSupPid, Buf, BufLen}) -> #v1{parent = Parent, sock = Sock, callback = handshake, recv_len = RecvLen, pending_recv = PendingRecv, connection_state = pre_init, queue_collector = undefined, heartbeater = none, helper_sup = HelperSupPid, buf = Buf, buf_len = BufLen, throttle = #throttle{alarmed_by = [], last_blocked_by = none, last_blocked_at = never}, connection = #connection{user = none, timeout_sec = ?HANDSHAKE_TIMEOUT, frame_max = ?FRAME_MIN_SIZE, auth_mechanism = none, auth_state = none}}. shutdown(Pid, Explanation) -> gen_server:call(Pid, {shutdown, Explanation}, infinity). system_continue(Parent, Deb, State) -> ?MODULE:mainloop(Deb, State#v1{parent = Parent}). system_terminate(Reason, _Parent, _Deb, _State) -> exit(Reason). system_code_change(Misc, _Module, _OldVsn, _Extra) -> {ok, Misc}. conserve_resources(Pid, Source, Conserve) -> Pid ! {conserve_resources, Source, Conserve}, ok. server_properties() -> %% The atom doesn't match anything, it's just "not 0-9-1". Raw = lists:keydelete( <<"capabilities">>, 1, rabbit_reader:server_properties(amqp_1_0)), {map, [{{symbol, binary_to_list(K)}, {utf8, V}} || {K, longstr, V} <- Raw]}. %% TODO copypasta from rabbit_federation_util:local_nodename_implicit/0. Unify. container_id() -> {ID, _} = rabbit_nodes:parts(node()), {ok, Host} = inet:gethostname(), {ok, #hostent{h_name = FQDN}} = inet:gethostbyname(Host), {utf8, list_to_binary(atom_to_list(rabbit_nodes:make({ID, FQDN})))}. %%-------------------------------------------------------------------------- log(Level, Fmt, Args) -> rabbit_log:log(connection, Level, Fmt, Args). inet_op(F) -> rabbit_misc:throw_on_error(inet_error, F). recvloop(Deb, State = #v1{pending_recv = true}) -> mainloop(Deb, State); recvloop(Deb, State = #v1{connection_state = blocked}) -> mainloop(Deb, State); recvloop(Deb, State = #v1{sock = Sock, recv_len = RecvLen, buf_len = BufLen}) when BufLen < RecvLen -> ok = rabbit_net:setopts(Sock, [{active, once}]), mainloop(Deb, State#v1{pending_recv = true}); recvloop(Deb, State = #v1{recv_len = RecvLen, buf = Buf, buf_len = BufLen}) -> {Data, Rest} = split_binary(case Buf of [B] -> B; _ -> list_to_binary(lists:reverse(Buf)) end, RecvLen), recvloop(Deb, handle_input(State#v1.callback, Data, State#v1{buf = [Rest], buf_len = BufLen - RecvLen})). mainloop(Deb, State = #v1{sock = Sock, buf = Buf, buf_len = BufLen}) -> case rabbit_net:recv(Sock) of {data, Data} -> recvloop(Deb, State#v1{buf = [Data | Buf], buf_len = BufLen + size(Data), pending_recv = false}); closed when State#v1.connection_state =:= closed -> ok; closed -> throw(connection_closed_abruptly); {error, Reason} -> throw({inet_error, Reason}); {other, {system, From, Request}} -> sys:handle_system_msg(Request, From, State#v1.parent, ?MODULE, Deb, State); {other, Other} -> case handle_other(Other, State) of stop -> ok; NewState -> recvloop(Deb, NewState) end end. handle_other({conserve_resources, Source, Conserve}, State = #v1{throttle = Throttle = #throttle{alarmed_by = CR}}) -> CR1 = case Conserve of true -> lists:usort([Source | CR]); false -> CR -- [Source] end, Throttle1 = Throttle#throttle{alarmed_by = CR1}, control_throttle(State#v1{throttle = Throttle1}); handle_other({'EXIT', Parent, Reason}, State = #v1{parent = Parent}) -> terminate(io_lib:format("broker forced connection closure " "with reason '~w'", [Reason]), State), %% this is what we are expected to do according to %% http://www.erlang.org/doc/man/sys.html %% %% If we wanted to be *really* nice we should wait for a while for %% clients to close the socket at their end, just as we do in the %% ordinary error case. However, since this termination is %% initiated by our parent it is probably more important to exit %% quickly. exit(Reason); handle_other({'DOWN', _MRef, process, ChPid, Reason}, State) -> handle_dependent_exit(ChPid, Reason, State); handle_other(handshake_timeout, State) when ?IS_RUNNING(State) orelse State#v1.connection_state =:= closing orelse State#v1.connection_state =:= closed -> State; handle_other(handshake_timeout, State) -> throw({handshake_timeout, State#v1.callback}); handle_other(heartbeat_timeout, State = #v1{connection_state = closed}) -> State; handle_other(heartbeat_timeout, #v1{connection_state = S}) -> throw({heartbeat_timeout, S}); handle_other({'$gen_call', From, {shutdown, Explanation}}, State) -> {ForceTermination, NewState} = terminate(Explanation, State), gen_server:reply(From, ok), case ForceTermination of force -> stop; normal -> NewState end; handle_other({'$gen_cast', force_event_refresh}, State) -> %% Ignore, the broker sent us this as it thinks we are a 0-9-1 connection State; handle_other({bump_credit, Msg}, State) -> credit_flow:handle_bump_msg(Msg), control_throttle(State); handle_other(terminate_connection, State) -> State; handle_other(Other, _State) -> %% internal error -> something worth dying for exit({unexpected_message, Other}). switch_callback(State, Callback, Length) -> State#v1{callback = Callback, recv_len = Length}. terminate(Reason, State) when ?IS_RUNNING(State) -> {normal, handle_exception(State, 0, {?V_1_0_AMQP_ERROR_INTERNAL_ERROR, "Connection forced: ~p~n", [Reason]})}; terminate(_Reason, State) -> {force, State}. control_throttle(State = #v1{connection_state = CS, throttle = Throttle}) -> IsThrottled = ((Throttle#throttle.alarmed_by =/= []) orelse credit_flow:blocked()), case {CS, IsThrottled} of {running, true} -> State#v1{connection_state = blocking}; {blocking, false} -> State#v1{connection_state = running}; {blocked, false} -> ok = rabbit_heartbeat:resume_monitor( State#v1.heartbeater), State#v1{connection_state = running}; {blocked, true} -> State#v1{throttle = update_last_blocked_by( Throttle)}; {_, _} -> State end. update_last_blocked_by(Throttle = #throttle{alarmed_by = []}) -> Throttle#throttle{last_blocked_by = flow}; update_last_blocked_by(Throttle) -> Throttle#throttle{last_blocked_by = resource}. %%-------------------------------------------------------------------------- %% error handling / termination close_connection(State = #v1{connection = #connection{ timeout_sec = TimeoutSec}}) -> erlang:send_after((if TimeoutSec > 0 andalso TimeoutSec < ?CLOSING_TIMEOUT -> TimeoutSec; true -> ?CLOSING_TIMEOUT end) * 1000, self(), terminate_connection), State#v1{connection_state = closed}. handle_dependent_exit(ChPid, Reason, State) -> case {ChPid, termination_kind(Reason)} of {undefined, uncontrolled} -> exit({abnormal_dependent_exit, ChPid, Reason}); {_Channel, controlled} -> maybe_close(control_throttle(State)); {Channel, uncontrolled} -> {RealReason, Trace} = Reason, R = {?V_1_0_AMQP_ERROR_INTERNAL_ERROR, "Session error: ~p~n~p~n", [RealReason, Trace]}, maybe_close(handle_exception(control_throttle(State), Channel, R)) end. termination_kind(normal) -> controlled; termination_kind(_) -> uncontrolled. maybe_close(State = #v1{connection_state = closing, sock = Sock}) -> NewState = close_connection(State), ok = send_on_channel0(Sock, #'v1_0.close'{}), NewState; maybe_close(State) -> State. error_frame(Condition, Fmt, Args) -> #'v1_0.error'{condition = Condition, description = {utf8, list_to_binary( rabbit_misc:format(Fmt, Args))}}. handle_exception(State = #v1{connection_state = closed}, Channel, #'v1_0.error'{description = {utf8, Desc}}) -> log(error, "AMQP 1.0 connection ~p (~p), channel ~p - error:~n~p~n", [self(), closed, Channel, Desc]), State; handle_exception(State = #v1{connection_state = CS}, Channel, ErrorFrame = #'v1_0.error'{description = {utf8, Desc}}) when ?IS_RUNNING(State) orelse CS =:= closing -> log(error, "AMQP 1.0 connection ~p (~p), channel ~p - error:~n~p~n", [self(), CS, Channel, Desc]), %% TODO: session errors shouldn't force the connection to close State1 = close_connection(State), ok = send_on_channel0(State#v1.sock, #'v1_0.close'{error = ErrorFrame}), State1; handle_exception(State, Channel, Error) -> %% We don't trust the client at this point - force them to wait %% for a bit so they can't DOS us with repeated failed logins etc. timer:sleep(?SILENT_CLOSE_DELAY * 1000), throw({handshake_error, State#v1.connection_state, Channel, Error}). %%-------------------------------------------------------------------------- %% Begin 1-0 %% ---------------------------------------- %% AMQP 1.0 frame handlers is_connection_frame(#'v1_0.open'{}) -> true; is_connection_frame(#'v1_0.close'{}) -> true; is_connection_frame(_) -> false. %% TODO Handle depending on connection state %% TODO It'd be nice to only decode up to the descriptor handle_1_0_frame(Mode, Channel, Payload, State) -> try handle_1_0_frame0(Mode, Channel, Payload, State) catch _:#'v1_0.error'{} = Reason -> handle_exception(State, 0, Reason); _:Reason -> Trace = erlang:get_stacktrace(), handle_exception(State, 0, error_frame( ?V_1_0_AMQP_ERROR_INTERNAL_ERROR, "Reader error: ~p~n~p~n", [Reason, Trace])) end. %% Nothing specifies that connection methods have to be on a %% particular channel. handle_1_0_frame0(_Mode, Channel, Payload, State = #v1{ connection_state = CS}) when CS =:= closing; CS =:= closed -> Sections = parse_1_0_frame(Payload, Channel), case is_connection_frame(Sections) of true -> handle_1_0_connection_frame(Sections, State); false -> State end; handle_1_0_frame0(Mode, Channel, Payload, State) -> Sections = parse_1_0_frame(Payload, Channel), case {Mode, is_connection_frame(Sections)} of {amqp, true} -> handle_1_0_connection_frame(Sections, State); {amqp, false} -> handle_1_0_session_frame(Channel, Sections, State); {sasl, false} -> handle_1_0_sasl_frame(Sections, State) end. parse_1_0_frame(Payload, _Channel) -> {PerfDesc, Rest} = rabbit_amqp1_0_binary_parser:parse(Payload), Perf = rabbit_amqp1_0_framing:decode(PerfDesc), ?DEBUG("Channel ~p ->~n~p~n~s~n", [_Channel, rabbit_amqp1_0_framing:pprint(Perf), case Rest of <<>> -> <<>>; _ -> rabbit_misc:format( " followed by ~p bytes of content~n", [size(Rest)]) end]), case Rest of <<>> -> Perf; _ -> {Perf, Rest} end. handle_1_0_connection_frame(#'v1_0.open'{ max_frame_size = ClientFrameMax, channel_max = ClientChannelMax, idle_time_out = IdleTimeout, hostname = Hostname, properties = Props }, State = #v1{ connection_state = starting, connection = Connection, throttle = Throttle, helper_sup = HelperSupPid, sock = Sock}) -> ClientProps = case Props of undefined -> []; {map, Ps} -> Ps end, ClientHeartbeatSec = case IdleTimeout of undefined -> 0; {uint, Interval} -> Interval div 1000 end, FrameMax = case ClientFrameMax of undefined -> unlimited; {_, FM} -> FM end, ChannelMax = case ClientChannelMax of undefined -> unlimited; {_, CM} -> CM end, {ok, HeartbeatSec} = application:get_env(rabbit, heartbeat), State1 = if (FrameMax =/= unlimited) and (FrameMax < ?FRAME_1_0_MIN_SIZE) -> protocol_error(?V_1_0_AMQP_ERROR_FRAME_SIZE_TOO_SMALL, "frame_max=~w < ~w min size", [FrameMax, ?FRAME_1_0_MIN_SIZE]); true -> {ok, Collector} = rabbit_connection_helper_sup:start_queue_collector(HelperSupPid), SendFun = fun() -> Frame = rabbit_amqp1_0_binary_generator:build_heartbeat_frame(), catch rabbit_net:send(Sock, Frame) end, Parent = self(), ReceiveFun = fun() -> Parent ! heartbeat_timeout end, %% [2.4.5] the value in idle-time-out SHOULD be half the peer's %% actual timeout threshold ReceiverHeartbeatSec = lists:min([HeartbeatSec * 2, 4294967]), %% TODO: only start heartbeat receive timer at next next frame Heartbeater = rabbit_heartbeat:start(HelperSupPid, Sock, ClientHeartbeatSec, SendFun, ReceiverHeartbeatSec, ReceiveFun), State#v1{connection_state = running, connection = Connection#connection{ frame_max = FrameMax, hostname = Hostname}, heartbeater = Heartbeater, queue_collector = Collector} end, %% TODO enforce channel_max ok = send_on_channel0( Sock, #'v1_0.open'{channel_max = ClientChannelMax, max_frame_size = ClientFrameMax, idle_time_out = {uint, HeartbeatSec * 1000}, container_id = container_id(), properties = server_properties()}), Conserve = rabbit_alarm:register(self(), {?MODULE, conserve_resources, []}), control_throttle( State1#v1{throttle = Throttle#throttle{alarmed_by = Conserve}}); handle_1_0_connection_frame(_Frame, State) -> maybe_close(State#v1{connection_state = closing}). handle_1_0_session_frame(Channel, Frame, State) -> case get({channel, Channel}) of {ch_fr_pid, SessionPid} -> ok = rabbit_amqp1_0_session:process_frame(SessionPid, Frame), case Frame of #'v1_0.end'{} -> erase({channel, Channel}), State; #'v1_0.transfer'{} -> case (State#v1.connection_state =:= blocking) of true -> ok = rabbit_heartbeat:pause_monitor( State#v1.heartbeater), State#v1{connection_state = blocked}; false -> State end; _ -> State end; closing -> case Frame of #'v1_0.end'{} -> erase({channel, Channel}); _Else -> ok end, State; undefined -> case ?IS_RUNNING(State) of true -> ok = send_to_new_1_0_session(Channel, Frame, State), State; false -> throw({channel_frame_while_starting, Channel, State#v1.connection_state, Frame}) end end. %% TODO: write a proper ANONYMOUS plugin and unify with STOMP handle_1_0_sasl_frame(#'v1_0.sasl_init'{mechanism = {symbol, "ANONYMOUS"}, hostname = _Hostname}, State = #v1{connection_state = starting, sock = Sock}) -> case application:get_env(rabbitmq_amqp1_0, default_user) of {ok, none} -> %% No need to do anything, we will blow up in start_connection ok; {ok, _} -> %% We only need to send the frame, again start_connection %% will set up the default user. Outcome = #'v1_0.sasl_outcome'{code = {ubyte, 0}}, ok = send_on_channel0(Sock, Outcome, rabbit_amqp1_0_sasl), switch_callback(State#v1{connection_state = waiting_amqp0100}, handshake, 8) end; handle_1_0_sasl_frame(#'v1_0.sasl_init'{mechanism = {symbol, Mechanism}, initial_response = {binary, Response}, hostname = _Hostname}, State0 = #v1{connection_state = starting, connection = Connection, sock = Sock}) -> AuthMechanism = auth_mechanism_to_module(list_to_binary(Mechanism), Sock), State = State0#v1{connection = Connection#connection{ auth_mechanism = {Mechanism, AuthMechanism}, auth_state = AuthMechanism:init(Sock)}, connection_state = securing}, auth_phase_1_0(Response, State); handle_1_0_sasl_frame(#'v1_0.sasl_response'{response = {binary, Response}}, State = #v1{connection_state = securing}) -> auth_phase_1_0(Response, State); handle_1_0_sasl_frame(Frame, State) -> throw({unexpected_1_0_sasl_frame, Frame, State}). %% We need to handle restarts... handle_input(handshake, <<"AMQP", 0, 1, 0, 0>>, State) -> start_1_0_connection(amqp, State); %% 3 stands for "SASL" (keeping this here for when we do TLS) handle_input(handshake, <<"AMQP", 3, 1, 0, 0>>, State) -> start_1_0_connection(sasl, State); handle_input({frame_header_1_0, Mode}, Header = <>, State) when DOff >= 2 -> case {Mode, Type} of {amqp, 0} -> ok; {sasl, 1} -> ok; _ -> throw({bad_1_0_header_type, Header, Mode}) end, case Size of 8 -> % length inclusive {State, {frame_header_1_0, Mode}, 8}; %% heartbeat _ -> switch_callback(State, {frame_payload_1_0, Mode, DOff, Channel}, Size - 8) end; handle_input({frame_header_1_0, _Mode}, Malformed, _State) -> throw({bad_1_0_header, Malformed}); handle_input({frame_payload_1_0, Mode, DOff, Channel}, FrameBin, State) -> SkipBits = (DOff * 32 - 64), % DOff = 4-byte words, we've read 8 already <> = FrameBin, Skip = Skip, %% hide warning when debug is off handle_1_0_frame(Mode, Channel, FramePayload, switch_callback(State, {frame_header_1_0, Mode}, 8)); handle_input(Callback, Data, _State) -> throw({bad_input, Callback, Data}). init(Mode, PackedState) -> %% By invoking recvloop here we become 1.0. recvloop(sys:debug_options([]), start_1_0_connection(Mode, unpack_from_0_9_1(PackedState))). start_1_0_connection(sasl, State = #v1{sock = Sock}) -> send_1_0_handshake(Sock, <<"AMQP",3,1,0,0>>), Ms = {array, symbol, case application:get_env(rabbitmq_amqp1_0, default_user) of {ok, none} -> []; {ok, _} -> ["ANONYMOUS"] end ++ [ atom_to_list(M) || M <- auth_mechanisms(Sock)]}, Mechanisms = #'v1_0.sasl_mechanisms'{sasl_server_mechanisms = Ms}, ok = send_on_channel0(Sock, Mechanisms, rabbit_amqp1_0_sasl), start_1_0_connection0(sasl, State); start_1_0_connection(amqp, State = #v1{sock = Sock, connection = C = #connection{user = User}}) -> {ok, NoAuthUsername} = application:get_env(rabbitmq_amqp1_0, default_user), case {User, NoAuthUsername} of {none, none} -> send_1_0_handshake(Sock, <<"AMQP",3,1,0,0>>), throw(banned_unauthenticated_connection); {none, Username} -> case rabbit_access_control:check_user_login( list_to_binary(Username), []) of {ok, NoAuthUser} -> State1 = State#v1{ connection = C#connection{user = NoAuthUser}}, send_1_0_handshake(Sock, <<"AMQP",0,1,0,0>>), start_1_0_connection0(amqp, State1); _ -> send_1_0_handshake(Sock, <<"AMQP",3,1,0,0>>), throw(default_user_missing) end; _ -> send_1_0_handshake(Sock, <<"AMQP",0,1,0,0>>), start_1_0_connection0(amqp, State) end. start_1_0_connection0(Mode, State = #v1{connection = Connection, helper_sup = HelperSup}) -> ChannelSupSupPid = case Mode of sasl -> undefined; amqp -> {ok, Pid} = supervisor2:start_child( HelperSup, {channel_sup_sup, {rabbit_amqp1_0_session_sup_sup, start_link, []}, intrinsic, infinity, supervisor, [rabbit_amqp1_0_session_sup_sup]}), Pid end, switch_callback(State#v1{connection = Connection#connection{ timeout_sec = ?NORMAL_TIMEOUT}, channel_sup_sup_pid = ChannelSupSupPid, connection_state = starting}, {frame_header_1_0, Mode}, 8). send_1_0_handshake(Sock, Handshake) -> ok = inet_op(fun () -> rabbit_net:send(Sock, Handshake) end). send_on_channel0(Sock, Method) -> send_on_channel0(Sock, Method, rabbit_amqp1_0_framing). send_on_channel0(Sock, Method, Framing) -> ok = rabbit_amqp1_0_writer:internal_send_command( Sock, 0, Method, Framing). %% End 1-0 auth_mechanism_to_module(TypeBin, Sock) -> case rabbit_registry:binary_to_type(TypeBin) of {error, not_found} -> protocol_error(?V_1_0_AMQP_ERROR_NOT_FOUND, "unknown authentication mechanism '~s'", [TypeBin]); T -> case {lists:member(T, auth_mechanisms(Sock)), rabbit_registry:lookup_module(auth_mechanism, T)} of {true, {ok, Module}} -> Module; _ -> protocol_error(?V_1_0_AMQP_ERROR_NOT_FOUND, "invalid authentication mechanism '~s'", [T]) end end. auth_mechanisms(Sock) -> {ok, Configured} = application:get_env(auth_mechanisms), [Name || {Name, Module} <- rabbit_registry:lookup_all(auth_mechanism), Module:should_offer(Sock), lists:member(Name, Configured)]. %% Begin 1-0 auth_phase_1_0(Response, State = #v1{connection = Connection = #connection{auth_mechanism = {Name, AuthMechanism}, auth_state = AuthState}, sock = Sock}) -> case AuthMechanism:handle_response(Response, AuthState) of {refused, Msg, Args} -> protocol_error( ?V_1_0_AMQP_ERROR_UNAUTHORIZED_ACCESS, "~s login refused: ~s", [Name, io_lib:format(Msg, Args)]); {protocol_error, Msg, Args} -> protocol_error(?V_1_0_AMQP_ERROR_DECODE_ERROR, Msg, Args); {challenge, Challenge, AuthState1} -> Secure = #'v1_0.sasl_challenge'{challenge = {binary, Challenge}}, ok = send_on_channel0(Sock, Secure, rabbit_amqp1_0_sasl), State#v1{connection = Connection = #connection{auth_state = AuthState1}}; {ok, User} -> Outcome = #'v1_0.sasl_outcome'{code = {ubyte, 0}}, ok = send_on_channel0(Sock, Outcome, rabbit_amqp1_0_sasl), switch_callback( State#v1{connection_state = waiting_amqp0100, connection = Connection#connection{user = User}}, handshake, 8) end. send_to_new_1_0_session(Channel, Frame, State) -> #v1{sock = Sock, queue_collector = Collector, channel_sup_sup_pid = ChanSupSup, connection = #connection{frame_max = FrameMax, hostname = Hostname, user = User}} = State, {ok, ChSupPid, ChFrPid} = %% Note: the equivalent, start_channel is in channel_sup_sup rabbit_amqp1_0_session_sup_sup:start_session( %% NB subtract fixed frame header size ChanSupSup, {rabbit_amqp1_0_framing, Sock, Channel, case FrameMax of unlimited -> unlimited; _ -> FrameMax - 8 end, self(), User, vhost(Hostname), Collector}), erlang:monitor(process, ChFrPid), put({channel, Channel}, {ch_fr_pid, ChFrPid}), put({ch_sup_pid, ChSupPid}, {{channel, Channel}, {ch_fr_pid, ChFrPid}}), put({ch_fr_pid, ChFrPid}, {channel, Channel}), ok = rabbit_amqp1_0_session:process_frame(ChFrPid, Frame). vhost({utf8, <<"vhost:", VHost/binary>>}) -> VHost; vhost(_) -> {ok, DefaultVHost} = application:get_env(default_vhost), DefaultVHost. %% End 1-0 rabbitmq-server-3.2.4/plugins-src/rabbitmq-amqp1.0/src/rabbit_amqp1_0_session_process.erl0000644000000000000000000003667512305126066030144 0ustar rootroot%% The contents of this file are subject to the Mozilla Public License %% Version 1.1 (the "License"); you may not use this file except in %% compliance with the License. You may obtain a copy of the License %% at http://www.mozilla.org/MPL/ %% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See %% the License for the specific language governing rights and %% limitations under the License. %% %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is GoPivotal, Inc. %% Copyright (c) 2007-2013 GoPivotal, Inc. All rights reserved. %% -module(rabbit_amqp1_0_session_process). -behaviour(gen_server2). -export([init/1, terminate/2, code_change/3, handle_call/3, handle_cast/2, handle_info/2]). -export([start_link/1]). -record(state, {backing_connection, backing_channel, frame_max, reader_pid, writer_pid, buffer, session}). -record(pending, {delivery_tag, frames, link_handle }). -include_lib("amqp_client/include/amqp_client.hrl"). -include("rabbit_amqp1_0.hrl"). -import(rabbit_amqp1_0_util, [protocol_error/3]). -import(rabbit_amqp1_0_link_util, [ctag_to_handle/1]). start_link(Args) -> gen_server2:start_link(?MODULE, Args, []). %% --------- init({Channel, ReaderPid, WriterPid, #user{username = Username}, VHost, FrameMax, AdapterInfo, _Collector}) -> process_flag(trap_exit, true), {ok, Conn} = amqp_connection:start( #amqp_params_direct{username = Username, virtual_host = VHost, adapter_info = AdapterInfo}), {ok, Ch} = amqp_connection:open_channel(Conn), {ok, #state{backing_connection = Conn, backing_channel = Ch, reader_pid = ReaderPid, writer_pid = WriterPid, frame_max = FrameMax, buffer = queue:new(), session = rabbit_amqp1_0_session:init(Channel) }}. terminate(_Reason, _State = #state{backing_connection = Conn}) -> rabbit_misc:with_exit_handler(fun () -> ok end, fun () -> amqp_connection:close(Conn) end). code_change(_OldVsn, State, _Extra) -> {ok, State}. handle_call(Msg, _From, State) -> {reply, {error, not_understood, Msg}, State}. handle_info(#'basic.consume_ok'{}, State) -> %% Handled above {noreply, State}; handle_info({#'basic.deliver'{ consumer_tag = ConsumerTag, delivery_tag = DeliveryTag } = Deliver, Msg}, State = #state{frame_max = FrameMax, buffer = Buffer, session = Session}) -> Handle = ctag_to_handle(ConsumerTag), case get({out, Handle}) of undefined -> %% TODO handle missing link -- why does the queue think it's there? rabbit_log:warning("Delivery to non-existent consumer ~p", [ConsumerTag]), {noreply, State}; Link -> {ok, Frames, Session1} = rabbit_amqp1_0_outgoing_link:delivery( Deliver, Msg, FrameMax, Handle, Session, Link), Pending = #pending{ delivery_tag = DeliveryTag, frames = Frames, link_handle = Handle }, Buffer1 = queue:in(Pending, Buffer), {noreply, run_buffer( state(Session1, State#state{ buffer = Buffer1 }))} end; %% A message from the queue saying that there are no more messages handle_info(#'basic.credit_drained'{consumer_tag = CTag} = CreditDrained, State = #state{writer_pid = WriterPid}) -> Handle = ctag_to_handle(CTag), Link = get({out, Handle}), Link1 = rabbit_amqp1_0_outgoing_link:credit_drained( CreditDrained, Handle, Link, WriterPid), put({out, Handle}, Link1), {noreply, State}; handle_info(#'basic.ack'{} = Ack, State = #state{writer_pid = WriterPid, session = Session}) -> {Reply, Session1} = rabbit_amqp1_0_session:ack(Ack, Session), [rabbit_amqp1_0_writer:send_command(WriterPid, F) || F <- rabbit_amqp1_0_session:flow_fields(Reply, Session)], {noreply, state(Session1, State)}; handle_info({bump_credit, Msg}, State) -> credit_flow:handle_bump_msg(Msg), {noreply, State}; %% TODO these pretty much copied wholesale from rabbit_channel handle_info({'EXIT', WriterPid, Reason = {writer, send_failed, _Error}}, State = #state{writer_pid = WriterPid}) -> State#state.reader_pid ! {channel_exit, rabbit_amqp1_0_session:channel(session(State)), Reason}, {stop, normal, State}; handle_info({'EXIT', _Pid, Reason}, State) -> {stop, Reason, State}; handle_info({'DOWN', _MRef, process, _QPid, _Reason}, State) -> %% TODO do we care any more since we're using direct client? {noreply, State}. % TODO rabbit_channel uses queue_blocked? handle_cast({frame, Frame, FlowPid}, State = #state{ reader_pid = ReaderPid, writer_pid = Sock }) -> credit_flow:ack(FlowPid), try handle_control(Frame, State) of {reply, Replies, NewState} when is_list(Replies) -> lists:foreach(fun (Reply) -> rabbit_amqp1_0_writer:send_command(Sock, Reply) end, Replies), noreply(NewState); {reply, Reply, NewState} -> rabbit_amqp1_0_writer:send_command(Sock, Reply), noreply(NewState); {noreply, NewState} -> noreply(NewState); stop -> {stop, normal, State} catch exit:Reason = #'v1_0.error'{} -> %% TODO shut down nicely like rabbit_channel End = #'v1_0.end'{ error = Reason }, rabbit_log:warning("Closing session for connection ~p: ~p~n", [ReaderPid, Reason]), ok = rabbit_amqp1_0_writer:send_command_sync(Sock, End), {stop, normal, State}; exit:normal -> {stop, normal, State}; _:Reason -> {stop, {Reason, erlang:get_stacktrace()}, State} end. %% TODO rabbit_channel returns {noreply, State, hibernate}, but that %% appears to break things here (it stops the session responding to %% frames). noreply(State) -> {noreply, State}. %% ------ handle_control(#'v1_0.begin'{} = Begin, State = #state{backing_channel = Ch, session = Session}) -> {ok, Reply, Session1, Prefetch} = rabbit_amqp1_0_session:begin_(Begin, Session), %% Attempt to limit the number of "at risk" messages we can have. rabbit_amqp1_0_channel:cast(Ch, #'basic.qos'{prefetch_count = Prefetch}), reply(Reply, state(Session1, State)); handle_control(#'v1_0.attach'{handle = Handle, role = ?SEND_ROLE} = Attach, State = #state{backing_channel = BCh, backing_connection = Conn}) -> ok = rabbit_amqp1_0_session:validate_attach(Attach), {ok, Reply, Link, Confirm} = with_disposable_channel( Conn, fun (DCh) -> rabbit_amqp1_0_incoming_link:attach(Attach, BCh, DCh) end), put({in, Handle}, Link), reply(Reply, state(rabbit_amqp1_0_session:maybe_init_publish_id( Confirm, session(State)), State)); handle_control(#'v1_0.attach'{handle = Handle, role = ?RECV_ROLE} = Attach, State = #state{backing_channel = BCh, backing_connection = Conn}) -> ok = rabbit_amqp1_0_session:validate_attach(Attach), {ok, Reply, Link} = with_disposable_channel( Conn, fun (DCh) -> rabbit_amqp1_0_outgoing_link:attach(Attach, BCh, DCh) end), put({out, Handle}, Link), reply(Reply, State); handle_control({Txfr = #'v1_0.transfer'{handle = Handle}, MsgPart}, State = #state{backing_channel = BCh, session = Session}) -> case get({in, Handle}) of undefined -> protocol_error(?V_1_0_AMQP_ERROR_ILLEGAL_STATE, "Unknown link handle ~p", [Handle]); Link -> {Flows, Session1} = rabbit_amqp1_0_session:incr_incoming_id(Session), case rabbit_amqp1_0_incoming_link:transfer( Txfr, MsgPart, Link, BCh) of {message, Reply, Link1, DeliveryId, Settled} -> put({in, Handle}, Link1), Session2 = rabbit_amqp1_0_session:record_delivery( DeliveryId, Settled, Session1), reply(Reply ++ Flows, state(Session2, State)); {ok, Link1} -> put({in, Handle}, Link1), reply(Flows, state(Session1, State)) end end; %% Disposition: multiple deliveries may be settled at a time. %% TODO: should we send a flow after this, to indicate the state %% of the session window? handle_control(#'v1_0.disposition'{state = Outcome, role = ?RECV_ROLE} = Disp, State = #state{backing_channel = Ch}) -> AckFun = fun (DeliveryTag) -> ok = rabbit_amqp1_0_channel:call( Ch, case Outcome of #'v1_0.accepted'{} -> #'basic.ack'{delivery_tag = DeliveryTag, multiple = false}; #'v1_0.rejected'{} -> #'basic.reject'{delivery_tag = DeliveryTag, requeue = false}; #'v1_0.released'{} -> #'basic.reject'{delivery_tag = DeliveryTag, requeue = true} end) end, case rabbit_amqp1_0_session:settle(Disp, session(State), AckFun) of {none, Session1} -> {noreply, state(Session1, State)}; {Reply, Session1} -> {reply, Reply, state(Session1, State)} end; handle_control(#'v1_0.detach'{ handle = Handle }, State) -> %% TODO keep the state around depending on the lifetime %% TODO outgoing links? erase({in, Handle}), {reply, #'v1_0.detach'{ handle = Handle }, State}; handle_control(#'v1_0.end'{}, _State = #state{ writer_pid = Sock }) -> ok = rabbit_amqp1_0_writer:send_command(Sock, #'v1_0.end'{}), stop; %% Flow control. These frames come with two pieces of information: %% the session window, and optionally, credit for a particular link. %% We'll deal with each of them separately. handle_control(Flow = #'v1_0.flow'{}, State = #state{backing_channel = BCh, session = Session}) -> State1 = state(rabbit_amqp1_0_session:flow(Flow, Session), State), State2 = run_buffer(State1), case Flow#'v1_0.flow'.handle of undefined -> {noreply, State2}; Handle -> case get({in, Handle}) of undefined -> case get({out, Handle}) of undefined -> rabbit_log:warning("Flow for unknown link handle ~p", [Flow]), protocol_error(?V_1_0_AMQP_ERROR_INVALID_FIELD, "Unattached handle: ~p", [Handle]); Out -> {ok, Reply} = rabbit_amqp1_0_outgoing_link:flow( Out, Flow, BCh), reply(Reply, State2) end; _In -> %% We're being told about available messages at %% the sender. Yawn. %% TODO at least check transfer-count? {noreply, State2} end end; handle_control(Frame, _State) -> protocol_error(?V_1_0_AMQP_ERROR_INTERNAL_ERROR, "Unexpected frame ~p", [rabbit_amqp1_0_framing:pprint(Frame)]). run_buffer(State = #state{ writer_pid = WriterPid, session = Session, backing_channel = BCh, buffer = Buffer }) -> {Session1, Buffer1} = run_buffer1(WriterPid, BCh, Session, Buffer), State#state{ buffer = Buffer1, session = Session1 }. run_buffer1(WriterPid, BCh, Session, Buffer) -> case rabbit_amqp1_0_session:transfers_left(Session) of {LocalSpace, RemoteSpace} when RemoteSpace > 0 andalso LocalSpace > 0 -> Space = erlang:min(LocalSpace, RemoteSpace), case queue:out(Buffer) of {empty, Buffer} -> {Session, Buffer}; {{value, #pending{ delivery_tag = DeliveryTag, frames = Frames, link_handle = Handle } = Pending}, BufferTail} -> Link = get({out, Handle}), case send_frames(WriterPid, Frames, Space) of {all, SpaceLeft} -> NewLink = rabbit_amqp1_0_outgoing_link:transferred( DeliveryTag, BCh, Link), put({out, Handle}, NewLink), Session1 = rabbit_amqp1_0_session:record_transfers( Space - SpaceLeft, Session), run_buffer1(WriterPid, BCh, Session1, BufferTail); {some, Rest} -> Session1 = rabbit_amqp1_0_session:record_transfers( Space, Session), Buffer1 = queue:in_r(Pending#pending{ frames = Rest }, BufferTail), run_buffer1(WriterPid, BCh, Session1, Buffer1) end end; {_, RemoteSpace} when RemoteSpace > 0 -> case rabbit_amqp1_0_session:bump_outgoing_window(Session) of {Flow = #'v1_0.flow'{}, Session1} -> rabbit_amqp1_0_writer:send_command( WriterPid, rabbit_amqp1_0_session:flow_fields(Flow, Session1)), run_buffer1(WriterPid, BCh, Session1, Buffer); {none, Session1} -> {Session1, Buffer} end; _ -> {Session, Buffer} end. send_frames(_WriterPid, [], Left) -> {all, Left}; send_frames(_WriterPid, Rest, 0) -> {some, Rest}; send_frames(WriterPid, [[T, C] | Rest], Left) -> rabbit_amqp1_0_writer:send_command(WriterPid, T, C), send_frames(WriterPid, Rest, Left - 1). %% ------ reply([], State) -> {noreply, State}; reply(Reply, State) -> {reply, rabbit_amqp1_0_session:flow_fields(Reply, session(State)), State}. session(#state{session = Session}) -> Session. state(Session, State) -> State#state{session = Session}. with_disposable_channel(Conn, Fun) -> {ok, Ch} = amqp_connection:open_channel(Conn), try Fun(Ch) after catch amqp_channel:close(Ch) end. rabbitmq-server-3.2.4/plugins-src/rabbitmq-amqp1.0/src/rabbit_amqp1_0_session_sup.erl0000644000000000000000000000455512305126066027265 0ustar rootroot%% The contents of this file are subject to the Mozilla Public License %% Version 1.1 (the "License"); you may not use this file except in %% compliance with the License. You may obtain a copy of the License %% at http://www.mozilla.org/MPL/ %% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See %% the License for the specific language governing rights and %% limitations under the License. %% %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is GoPivotal, Inc. %% Copyright (c) 2007-2013 GoPivotal, Inc. All rights reserved. %% -module(rabbit_amqp1_0_session_sup). -behaviour(supervisor2). -export([start_link/1]). -export([init/1]). -include_lib("amqp_client/include/amqp_client.hrl"). %%---------------------------------------------------------------------------- -ifdef(use_specs). -export_type([start_link_args/0]). -type(start_link_args() :: {rabbit_types:protocol(), rabbit_net:socket(), rabbit_channel:channel_number(), non_neg_integer(), pid(), rabbit_access_control:username(), rabbit_types:vhost(), pid()}). -spec(start_link/1 :: (start_link_args()) -> {'ok', pid(), pid()}). -endif. %%---------------------------------------------------------------------------- start_link({rabbit_amqp1_0_framing, Sock, Channel, FrameMax, ReaderPid, Username, VHost, Collector}) -> {ok, SupPid} = supervisor2:start_link(?MODULE, []), {ok, WriterPid} = supervisor2:start_child( SupPid, {writer, {rabbit_amqp1_0_writer, start_link, [Sock, Channel, FrameMax, rabbit_amqp1_0_framing, ReaderPid]}, intrinsic, ?MAX_WAIT, worker, [rabbit_amqp1_0_writer]}), {ok, ChannelPid} = supervisor2:start_child( SupPid, {channel, {rabbit_amqp1_0_session_process, start_link, [{Channel, ReaderPid, WriterPid, Username, VHost, FrameMax, adapter_info(Sock), Collector}]}, intrinsic, ?MAX_WAIT, worker, [rabbit_amqp1_0_session_process]}), {ok, SupPid, ChannelPid}. %%---------------------------------------------------------------------------- init([]) -> {ok, {{one_for_all, 0, 1}, []}}. adapter_info(Sock) -> amqp_connection:socket_adapter_info(Sock, {'AMQP', "1.0"}). rabbitmq-server-3.2.4/plugins-src/rabbitmq-amqp1.0/src/rabbit_amqp1_0_session.erl0000644000000000000000000004353212305126066026374 0ustar rootroot%% The contents of this file are subject to the Mozilla Public License %% Version 1.1 (the "License"); you may not use this file except in %% compliance with the License. You may obtain a copy of the License %% at http://www.mozilla.org/MPL/ %% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See %% the License for the specific language governing rights and %% limitations under the License. %% %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is GoPivotal, Inc. %% Copyright (c) 2007-2013 GoPivotal, Inc. All rights reserved. %% -module(rabbit_amqp1_0_session). -export([process_frame/2]). -export([init/1, begin_/2, maybe_init_publish_id/2, record_delivery/3, incr_incoming_id/1, next_delivery_id/1, transfers_left/1, record_transfers/2, bump_outgoing_window/1, record_outgoing/4, settle/3, flow_fields/2, channel/1, flow/2, ack/2, validate_attach/1]). -import(rabbit_amqp1_0_util, [protocol_error/3, serial_add/2, serial_diff/2, serial_compare/2]). -include_lib("amqp_client/include/amqp_client.hrl"). -include("rabbit_amqp1_0.hrl"). -define(MAX_SESSION_WINDOW_SIZE, 65535). -define(DEFAULT_MAX_HANDLE, 16#ffffffff). -record(session, {channel_num, %% we just use the incoming (AMQP 1.0) channel number remote_incoming_window, % keep track of the window until we're told remote_outgoing_window, next_incoming_id, % just to keep a check incoming_window_max, % ) incoming_window, % ) so we know when to open the session window next_outgoing_id = 0, % arbitrary count of outgoing transfers outgoing_window, outgoing_window_max, next_publish_id, %% the 0-9-1-side counter for confirms next_delivery_id = 0, incoming_unsettled_map, outgoing_unsettled_map }). %% We record delivery_id -> #outgoing_delivery{}, so that we can %% respond to dispositions about messages we've sent. NB the %% delivery-tag doubles as the id we use when acking the rabbit %% delivery. -record(outgoing_delivery, {delivery_tag, expected_outcome}). %% We record confirm_id -> #incoming_delivery{} so we can relay %% confirms from the broker back to the sending client. NB we have %% only one possible outcome, so there's no need to record it here. -record(incoming_delivery, {delivery_id}). process_frame(Pid, Frame) -> credit_flow:send(Pid), gen_server2:cast(Pid, {frame, Frame, self()}). init(Channel) -> #session{channel_num = Channel, next_publish_id = 0, incoming_unsettled_map = gb_trees:empty(), outgoing_unsettled_map = gb_trees:empty()}. %% Session window: %% %% Each session has two abstract[1] buffers, one to record the %% unsettled state of incoming messages, one to record the unsettled %% state of outgoing messages. In general we want to bound these %% buffers; but if we bound them, and don't tell the other side, we %% may end up deadlocking the other party. %% %% Hence the flow frame contains a session window, expressed as the %% next-id and the window size for each of the buffers. The frame %% refers to the window of the sender of the frame, of course. %% %% The numbers work this way: for the outgoing window, the next-id %% counts the next transfer the session will send, and it will stop %% sending at next-id + window. For the incoming window, the next-id %% counts the next transfer id expected, and it will not accept %% messages beyond next-id + window (in fact it will probably close %% the session, since sending outside the window is a transgression of %% the protocol). %% %% We may as well just pick a value for the incoming and outgoing %% windows; choosing based on what the client says may just stop %% things dead, if the value is zero for instance. %% %% [1] Abstract because there probably won't be a data structure with %% a size directly related to transfers; settlement is done with %% delivery-id, which may refer to one or more transfers. begin_(#'v1_0.begin'{next_outgoing_id = {uint, RemoteNextOut}, incoming_window = {uint, RemoteInWindow}, outgoing_window = {uint, RemoteOutWindow}, handle_max = HandleMax0}, Session = #session{next_outgoing_id = LocalNextOut, channel_num = Channel}) -> InWindow = ?MAX_SESSION_WINDOW_SIZE, OutWindow = ?MAX_SESSION_WINDOW_SIZE, HandleMax = case HandleMax0 of {uint, Max} -> Max; _ -> ?DEFAULT_MAX_HANDLE end, {ok, #'v1_0.begin'{remote_channel = {ushort, Channel}, handle_max = {uint, HandleMax}, next_outgoing_id = {uint, LocalNextOut}, incoming_window = {uint, InWindow}, outgoing_window = {uint, OutWindow}}, Session#session{ outgoing_window = OutWindow, outgoing_window_max = OutWindow, next_incoming_id = RemoteNextOut, remote_incoming_window = RemoteInWindow, remote_outgoing_window = RemoteOutWindow, incoming_window = InWindow, incoming_window_max = InWindow}, OutWindow}. validate_attach(#'v1_0.attach'{target = #'v1_0.coordinator'{}}) -> protocol_error(?V_1_0_AMQP_ERROR_NOT_IMPLEMENTED, "Transactions not supported", []); validate_attach(#'v1_0.attach'{unsettled = Unsettled, incomplete_unsettled = IncompleteSettled}) when Unsettled =/= undefined andalso Unsettled =/= {map, []} orelse IncompleteSettled =:= true -> protocol_error(?V_1_0_AMQP_ERROR_NOT_IMPLEMENTED, "Link recovery not supported", []); validate_attach( #'v1_0.attach'{snd_settle_mode = SndSettleMode, rcv_settle_mode = ?V_1_0_RECEIVER_SETTLE_MODE_SECOND}) when SndSettleMode =/= ?V_1_0_SENDER_SETTLE_MODE_SETTLED -> protocol_error(?V_1_0_AMQP_ERROR_NOT_IMPLEMENTED, "rcv-settle-mode second not supported", []); validate_attach(#'v1_0.attach'{}) -> ok. maybe_init_publish_id(false, Session) -> Session; maybe_init_publish_id(true, Session = #session{next_publish_id = Id}) -> Session#session{next_publish_id = erlang:max(1, Id)}. record_delivery(DeliveryId, Settled, Session = #session{next_publish_id = Id, incoming_unsettled_map = Unsettled}) -> Id1 = case Id of 0 -> 0; _ -> Id + 1 % this ought to be a serial number in the broker, but isn't end, Unsettled1 = case Settled of true -> Unsettled; false -> gb_trees:insert(Id, #incoming_delivery{ delivery_id = DeliveryId }, Unsettled) end, Session#session{ next_publish_id = Id1, incoming_unsettled_map = Unsettled1}. incr_incoming_id(Session = #session{ next_incoming_id = NextIn, incoming_window = InWindow, incoming_window_max = InWindowMax, remote_outgoing_window = RemoteOut }) -> NewOutWindow = RemoteOut - 1, InWindow1 = InWindow - 1, NewNextIn = serial_add(NextIn, 1), %% If we've reached halfway, open the window {Flows, NewInWindow} = if InWindow1 =< (InWindowMax div 2) -> {[#'v1_0.flow'{}], InWindowMax}; true -> {[], InWindow1} end, {Flows, Session#session{ next_incoming_id = NewNextIn, incoming_window = NewInWindow, remote_outgoing_window = NewOutWindow}}. next_delivery_id(#session{next_delivery_id = Num}) -> Num. transfers_left(#session{remote_incoming_window = RemoteWindow, outgoing_window = LocalWindow}) -> {LocalWindow, RemoteWindow}. record_outgoing(DeliveryTag, SendSettled, DefaultOutcome, Session = #session{next_delivery_id = DeliveryId, outgoing_unsettled_map = Unsettled}) -> Unsettled1 = case SendSettled of true -> Unsettled; false -> gb_trees:insert(DeliveryId, #outgoing_delivery{ delivery_tag = DeliveryTag, expected_outcome = DefaultOutcome }, Unsettled) end, Session#session{outgoing_unsettled_map = Unsettled1, next_delivery_id = serial_add(DeliveryId, 1)}. record_transfers(NumTransfers, Session = #session{ remote_incoming_window = RemoteInWindow, outgoing_window = OutWindow, next_outgoing_id = NextOutId }) -> Session#session{ remote_incoming_window = RemoteInWindow - NumTransfers, outgoing_window = OutWindow - NumTransfers, next_outgoing_id = serial_add(NextOutId, NumTransfers) }. %% Make sure we have "room" in our outgoing window by bumping the %% window if necessary. TODO this *could* be based on how much %% notional "room" there is in outgoing_unsettled. bump_outgoing_window(Session = #session{ outgoing_window_max = OutMax }) -> {#'v1_0.flow'{}, Session#session{ outgoing_window = OutMax }}. %% We've been told that the fate of a delivery has been determined. %% Generally if the other side has not settled it, we will do so. If %% the other side /has/ settled it, we don't need to reply -- it's %% already forgotten its state for the delivery anyway. settle(Disp = #'v1_0.disposition'{first = First0, last = Last0, state = _Outcome, settled = Settled}, Session = #session{outgoing_unsettled_map = Unsettled}, UpstreamAckFun) -> {uint, First} = First0, %% Last may be omitted, in which case it's the same as first Last = case Last0 of {uint, L} -> L; undefined -> First end, %% The other party may be talking about something we've already %% forgotten; this isn't a crime, we can just ignore it. case gb_trees:is_empty(Unsettled) of true -> {none, Session}; false -> {LWM, _} = gb_trees:smallest(Unsettled), {HWM, _} = gb_trees:largest(Unsettled), if Last < LWM -> {none, Session}; %% TODO this should probably be an error, rather than ignored. First > HWM -> {none, Session}; true -> Unsettled1 = lists:foldl( fun (Delivery, Map) -> case gb_trees:lookup(Delivery, Map) of none -> Map; {value, Entry} -> #outgoing_delivery{delivery_tag = DeliveryTag } = Entry, ?DEBUG("Settling ~p with ~p~n", [Delivery, _Outcome]), UpstreamAckFun(DeliveryTag), gb_trees:delete(Delivery, Map) end end, Unsettled, lists:seq(erlang:max(LWM, First), erlang:min(HWM, Last))), {case Settled of true -> none; false -> Disp#'v1_0.disposition'{ settled = true, role = ?SEND_ROLE } end, Session#session{outgoing_unsettled_map = Unsettled1}} end end. flow_fields(Frames, Session) when is_list(Frames) -> [flow_fields(F, Session) || F <- Frames]; flow_fields(Flow = #'v1_0.flow'{}, #session{next_outgoing_id = NextOut, next_incoming_id = NextIn, outgoing_window = OutWindow, incoming_window = InWindow}) -> Flow#'v1_0.flow'{ next_outgoing_id = {uint, NextOut}, outgoing_window = {uint, OutWindow}, next_incoming_id = {uint, NextIn}, incoming_window = {uint, InWindow}}; flow_fields(Frame, _Session) -> Frame. channel(#session{channel_num = Channel}) -> Channel. %% We should already know the next outgoing transfer sequence number, %% because it's one more than the last transfer we saw; and, we don't %% need to know the next incoming transfer sequence number (although %% we might use it to detect congestion -- e.g., if it's lagging far %% behind our outgoing sequence number). We probably care about the %% outgoing window, since we want to keep it open by sending back %% settlements, but there's not much we can do to hurry things along. %% %% We do care about the incoming window, because we must not send %% beyond it. This may cause us problems, even in normal operation, %% since we want our unsettled transfers to be exactly those that are %% held as unacked by the backing channel; however, the far side may %% close the window while we still have messages pending transfer, and %% indeed, an individual message may take more than one 'slot'. %% %% Note that this isn't a race so far as AMQP 1.0 is concerned; it's %% only because AMQP 0-9-1 defines QoS in terms of the total number of %% unacked messages, whereas 1.0 has an explicit window. flow(#'v1_0.flow'{next_incoming_id = FlowNextIn0, incoming_window = {uint, FlowInWindow}, next_outgoing_id = {uint, FlowNextOut}, outgoing_window = {uint, FlowOutWindow}}, Session = #session{next_incoming_id = LocalNextIn, next_outgoing_id = LocalNextOut}) -> %% The far side may not have our begin{} with our next-transfer-id FlowNextIn = case FlowNextIn0 of {uint, Id} -> Id; undefined -> LocalNextOut end, case serial_compare(FlowNextOut, LocalNextIn) of equal -> case serial_compare(FlowNextIn, LocalNextOut) of greater -> protocol_error(?V_1_0_SESSION_ERROR_WINDOW_VIOLATION, "Remote incoming id (~p) leads " "local outgoing id (~p)", [FlowNextIn, LocalNextOut]); equal -> Session#session{ remote_outgoing_window = FlowOutWindow, remote_incoming_window = FlowInWindow}; less -> Session#session{ remote_outgoing_window = FlowOutWindow, remote_incoming_window = serial_diff(serial_add(FlowNextIn, FlowInWindow), LocalNextOut)} end; _ -> case application:get_env(rabbitmq_amqp1_0, protocol_strict_mode) of {ok, false} -> Session#session{next_incoming_id = FlowNextOut}; {ok, true} -> protocol_error(?V_1_0_SESSION_ERROR_WINDOW_VIOLATION, "Remote outgoing id (~p) not equal to " "local incoming id (~p)", [FlowNextOut, LocalNextIn]) end end. %% An acknowledgement from the queue, which we'll get if we are %% using confirms. ack(#'basic.ack'{delivery_tag = DTag, multiple = Multiple}, Session = #session{incoming_unsettled_map = Unsettled}) -> {DeliveryIds, Unsettled1} = case Multiple of true -> acknowledgement_range(DTag, Unsettled); false -> case gb_trees:lookup(DTag, Unsettled) of {value, #incoming_delivery{ delivery_id = Id }} -> {[Id], gb_trees:delete(DTag, Unsettled)}; none -> {[], Unsettled} end end, Disposition = case DeliveryIds of [] -> []; _ -> [acknowledgement( DeliveryIds, #'v1_0.disposition'{role = ?RECV_ROLE})] end, {Disposition, Session#session{incoming_unsettled_map = Unsettled1}}. acknowledgement_range(DTag, Unsettled) -> acknowledgement_range(DTag, Unsettled, []). acknowledgement_range(DTag, Unsettled, Acc) -> case gb_trees:is_empty(Unsettled) of true -> {lists:reverse(Acc), Unsettled}; false -> {DTag1, #incoming_delivery{ delivery_id = Id}} = gb_trees:smallest(Unsettled), case DTag1 =< DTag of true -> {_K, _V, Unsettled1} = gb_trees:take_smallest(Unsettled), acknowledgement_range(DTag, Unsettled1, [Id|Acc]); false -> {lists:reverse(Acc), Unsettled} end end. acknowledgement(DeliveryIds, Disposition) -> Disposition#'v1_0.disposition'{ first = {uint, hd(DeliveryIds)}, last = {uint, lists:last(DeliveryIds)}, settled = true, state = #'v1_0.accepted'{} }. rabbitmq-server-3.2.4/plugins-src/rabbitmq-amqp1.0/src/rabbit_amqp1_0_message.erl0000644000000000000000000002526212305126066026335 0ustar rootroot%% The contents of this file are subject to the Mozilla Public License %% Version 1.1 (the "License"); you may not use this file except in %% compliance with the License. You may obtain a copy of the License %% at http://www.mozilla.org/MPL/ %% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See %% the License for the specific language governing rights and %% limitations under the License. %% %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is GoPivotal, Inc. %% Copyright (c) 2007-2013 GoPivotal, Inc. All rights reserved. %% -module(rabbit_amqp1_0_message). -export([assemble/1, annotated_message/3]). -define(PROPERTIES_HEADER, <<"x-amqp-1.0-properties">>). -define(APP_PROPERTIES_HEADER, <<"x-amqp-1.0-app-properties">>). -define(MESSAGE_ANNOTATIONS_HEADER, <<"x-amqp-1.0-message-annotations">>). -define(FOOTER, <<"x-amqp-1.0-footer">>). -include_lib("amqp_client/include/amqp_client.hrl"). -include("rabbit_amqp1_0.hrl"). assemble(MsgBin) -> {RKey, Props, Content} = assemble(header, {<<"">>, #'P_basic'{}, []}, decode_section(MsgBin), MsgBin), {RKey, #amqp_msg{props = Props, payload = Content}}. assemble(header, {R, P, C}, {H = #'v1_0.header'{}, Rest}, _Uneaten) -> assemble(message_annotations, {R, translate_header(H, P), C}, decode_section(Rest), Rest); assemble(header, {R, P, C}, Else, Uneaten) -> assemble(message_annotations, {R, P, C}, Else, Uneaten); assemble(delivery_annotations, RPC, {#'v1_0.delivery_annotations'{}, Rest}, Uneaten) -> %% ignore delivery annotations for now %% TODO: handle "rejected" error assemble(message_annotations, RPC, Rest, Uneaten); assemble(delivery_annotations, RPC, Else, Uneaten) -> assemble(message_annotations, RPC, Else, Uneaten); assemble(message_annotations, {R, P = #'P_basic'{headers = Headers}, C}, {#'v1_0.message_annotations'{}, Rest}, Uneaten) -> MsgAnnoBin = chunk(Rest, Uneaten), assemble(properties, {R, P#'P_basic'{ headers = set_header(?MESSAGE_ANNOTATIONS_HEADER, MsgAnnoBin, Headers)}, C}, decode_section(Rest), Rest); assemble(message_annotations, {R, P, C}, Else, Uneaten) -> assemble(properties, {R, P, C}, Else, Uneaten); assemble(properties, {_R, P, C}, {X = #'v1_0.properties'{}, Rest}, Uneaten) -> PropsBin = chunk(Rest, Uneaten), assemble(app_properties, {routing_key(X), translate_properties(X, PropsBin, P), C}, decode_section(Rest), Rest); assemble(properties, {R, P, C}, Else, Uneaten) -> assemble(app_properties, {R, P, C}, Else, Uneaten); assemble(app_properties, {R, P = #'P_basic'{headers = Headers}, C}, {#'v1_0.application_properties'{}, Rest}, Uneaten) -> AppPropsBin = chunk(Rest, Uneaten), assemble(body, {R, P#'P_basic'{ headers = set_header(?APP_PROPERTIES_HEADER, AppPropsBin, Headers)}, C}, decode_section(Rest), Rest); assemble(app_properties, {R, P, C}, Else, Uneaten) -> assemble(body, {R, P, C}, Else, Uneaten); %% The only 'interoperable' content is a single amqp-data section. %% Everything else we will leave as-is. We still have to parse the %% sections one-by-one, however, to see when we hit the footer or %% whatever comes next. %% NB we do not strictly enforce the (slightly random) rules %% pertaining to body sections, that is: %% - one amqp-value; OR %% - one or more amqp-sequence; OR %% - one or more amqp-data. %% We allow any number of each kind, in any permutation. assemble(body, {R, P, _}, {#'v1_0.data'{content = Content}, Rest}, Uneaten) -> Chunk = chunk(Rest, Uneaten), assemble(amqp10body, {R, set_1_0_type(<<"binary">>, P), {data, Content, Chunk}}, decode_section(Rest), Rest); assemble(body, {R, P, C}, Else, Uneaten) -> assemble(amqp10body, {R, P, C}, Else, Uneaten); assemble(amqp10body, {R, P, C}, {{Type, _}, Rest}, Uneaten) when Type =:= 'v1_0.data' orelse Type =:= 'v1_0.amqp_sequence' orelse Type =:= 'v1_0.amqp_value' -> Encoded = chunk(Rest, Uneaten), assemble(amqp10body, {R, set_1_0_type(<<"amqp-1.0">>, P), add_body_section(Encoded, C)}, decode_section(Rest), Rest); assemble(amqp10body, {R, P, C}, Else, Uneaten) -> assemble(footer, {R, P, compile_body(C)}, Else, Uneaten); assemble(footer, {R, P = #'P_basic'{headers = Headers}, C}, {#'v1_0.footer'{}, <<>>}, Uneaten) -> {R, P#'P_basic'{headers = set_header(?FOOTER, Uneaten, Headers)}, C}; assemble(footer, {R, P, C}, none, _) -> {R, P, C}; assemble(footer, _, Else, _) -> exit({unexpected_trailing_sections, Else}); assemble(Expected, _, Actual, _) -> exit({expected_section, Expected, Actual}). decode_section(<<>>) -> none; decode_section(MsgBin) -> {AmqpValue, Rest} = rabbit_amqp1_0_binary_parser:parse(MsgBin), {rabbit_amqp1_0_framing:decode(AmqpValue), Rest}. chunk(Rest, Uneaten) -> ChunkLen = size(Uneaten) - size(Rest), <> = Uneaten, Chunk. add_body_section(C, {data, _, Bin}) -> [C, Bin]; add_body_section(C, Cs) -> [C | Cs]. compile_body({data, Content, _}) -> Content; compile_body(Sections) -> lists:reverse(Sections). translate_header(Header10, Props) -> Props#'P_basic'{ delivery_mode = case Header10#'v1_0.header'.durable of true -> 2; _ -> 1 end, priority = unwrap(Header10#'v1_0.header'.priority), expiration = to_expiration(Header10#'v1_0.header'.ttl), type = undefined, app_id = undefined, cluster_id = undefined}. translate_properties(Props10, Props10Bin, Props = #'P_basic'{headers = Headers}) -> Props#'P_basic'{ headers = set_header(?PROPERTIES_HEADER, Props10Bin, Headers), content_type = unwrap(Props10#'v1_0.properties'.content_type), content_encoding = unwrap(Props10#'v1_0.properties'.content_encoding), correlation_id = unwrap(Props10#'v1_0.properties'.correlation_id), reply_to = case unwrap(Props10#'v1_0.properties'.reply_to) of <<"/queue/", Q/binary>> -> Q; Else -> Else end, message_id = unwrap(Props10#'v1_0.properties'.message_id), user_id = unwrap(Props10#'v1_0.properties'.user_id)}. routing_key(Props10) -> unwrap(Props10#'v1_0.properties'.subject). unwrap({utf8, Bin}) -> Bin; unwrap({binary, Bin})-> Bin; unwrap({ubyte, Num}) -> Num; unwrap({uint, Num}) -> Num; unwrap({ulong, Num}) -> Num; unwrap({long, Num}) -> Num; unwrap(undefined) -> undefined. to_expiration(undefined) -> undefined; to_expiration({timestamp, Num}) -> list_to_binary(integer_to_list(Num)). to_absolute_expiry_time(undefined) -> undefined; to_absolute_expiry_time(MaybeIntegerBin) -> case catch list_to_integer(binary_to_list(MaybeIntegerBin)) of {'EXIT', {badarg, _}} -> undefined; Integer -> {timestamp, Integer} end. set_header(Header, Value, undefined) -> set_header(Header, Value, []); set_header(Header, Value, Headers) -> rabbit_misc:set_table_value(Headers, Header, longstr, Value). set_1_0_type(Type, Props = #'P_basic'{}) -> Props#'P_basic'{type = Type}. %%-------------------------------------------------------------------- %% TODO create delivery-annotations annotated_message(RKey, #'basic.deliver'{redelivered = Redelivered}, #amqp_msg{props = Props, payload = Content}) -> #'P_basic'{ headers = Headers } = Props, Header10 = #'v1_0.header' {durable = case Props#'P_basic'.delivery_mode of 2 -> true; _ -> false end, priority = wrap(ubyte, Props#'P_basic'.priority), ttl = undefined, first_acquirer = not Redelivered, delivery_count = undefined}, HeadersBin = rabbit_amqp1_0_framing:encode_bin(Header10), MsgAnnoBin = case table_lookup(Headers, ?MESSAGE_ANNOTATIONS_HEADER) of undefined -> <<>>; {_, MABin} -> MABin end, PropsBin = case table_lookup(Headers, ?PROPERTIES_HEADER) of {_, Props10Bin} -> Props10Bin; undefined -> Props10 = #'v1_0.properties'{ message_id = wrap(Props#'P_basic'.message_id), user_id = wrap(Props#'P_basic'.user_id), to = undefined, subject = wrap(RKey), reply_to = case Props#'P_basic'.reply_to of undefined -> undefined; _ -> wrap(<<"/queue/", (Props#'P_basic'.reply_to)/binary>>) end, correlation_id = wrap(Props#'P_basic'.correlation_id), content_type = wrap(Props#'P_basic'.content_type), content_encoding = wrap(Props#'P_basic'.content_encoding), absolute_expiry_time = to_absolute_expiry_time( Props#'P_basic'.expiration), creation_time = wrap(timstamp, Props#'P_basic'.timestamp)}, rabbit_amqp1_0_framing:encode_bin(Props10) end, AppPropsBin = case table_lookup(Headers, ?APP_PROPERTIES_HEADER) of {_, AppProps10Bin} -> AppProps10Bin; undefined -> [] end, DataBin = case Props#'P_basic'.type of <<"amqp-1.0">> -> Content; _Else -> % e.g., <<"binary">> if originally from 1.0 rabbit_amqp1_0_framing:encode_bin( #'v1_0.data'{content = Content}) end, FooterBin = case table_lookup(Headers, ?FOOTER) of undefined -> <<>>; {_, FBin} -> FBin end, [HeadersBin, MsgAnnoBin, PropsBin, AppPropsBin, DataBin, FooterBin]. wrap(Bin) when is_binary(Bin) -> {utf8, Bin}; wrap(Num) when is_number(Num) -> {ulong, Num}; wrap(undefined) -> undefined. wrap(_Type, undefined) -> undefined; wrap(Type, Val) -> {Type, Val}. table_lookup(undefined, _) -> undefined; table_lookup(Headers, Header) -> rabbit_misc:table_lookup(Headers, Header). rabbitmq-server-3.2.4/plugins-src/rabbitmq-amqp1.0/test/0000755000000000000000000000000012305126066021525 5ustar rootrootrabbitmq-server-3.2.4/plugins-src/rabbitmq-amqp1.0/test/src/0000755000000000000000000000000012305126066022314 5ustar rootrootrabbitmq-server-3.2.4/plugins-src/rabbitmq-amqp1.0/test/src/rabbit_amqp1_0_test.erl0000644000000000000000000000275212305126066026646 0ustar rootroot%% The contents of this file are subject to the Mozilla Public License %% Version 1.1 (the "License"); you may not use this file except in %% compliance with the License. You may obtain a copy of the License %% at http://www.mozilla.org/MPL/ %% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See %% the License for the specific language governing rights and %% limitations under the License. %% %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is GoPivotal, Inc. %% Copyright (c) 2007-2013 GoPivotal, Inc. All rights reserved. %% -module(rabbit_amqp1_0_test). -include("rabbit_amqp1_0.hrl"). -include_lib("eunit/include/eunit.hrl"). -import(rabbit_amqp1_0_util, [serial_add/2, serial_diff/2, serial_compare/2]). serial_arithmetic_test() -> ?assertEqual(1, serial_add(0, 1)), ?assertEqual(16#7fffffff, serial_add(0, 16#7fffffff)), ?assertEqual(0, serial_add(16#ffffffff, 1)), %% Cannot add more than 2 ^ 31 - 1 ?assertExit({out_of_bound_serial_addition, _, _}, serial_add(200, 16#80000000)), ?assertEqual(1, serial_diff(1, 0)), ?assertEqual(2, serial_diff(1, 16#ffffffff)), ?assertEqual(-2, serial_diff(16#ffffffff, 1)), ?assertExit({indeterminate_serial_diff, _, _}, serial_diff(0, 16#80000000)), ?assertExit({indeterminate_serial_diff, _, _}, serial_diff(16#ffffffff, 16#7fffffff)), passed. rabbitmq-server-3.2.4/plugins-src/rabbitmq-amqp1.0/test/proton/0000755000000000000000000000000012305126066023046 5ustar rootrootrabbitmq-server-3.2.4/plugins-src/rabbitmq-amqp1.0/test/proton/Makefile0000644000000000000000000000123412305126066024506 0ustar rootroot# Check before changing this - do other versions build on platforms we care # about? Neither 0.2 nor 0.5 build on a Mac for example. PROTON_VER=0.4 PROTON_DIR=qpid-proton-$(PROTON_VER) PROTON_TARBALL=$(PROTON_DIR).tar.gz PROTON_URL=http://apache.mirror.anlx.net/qpid/proton/$(PROTON_VER)/$(PROTON_TARBALL) deps: proton proton: $(PROTON_TARBALL) rm -rf tmp mkdir tmp tar xvzf $(PROTON_TARBALL) -C tmp cd tmp/$(PROTON_DIR) && mkdir build && cd build && cmake -DCMAKE_INSTALL_PREFIX=/not-going-to-install .. && make all cp tmp/$(PROTON_DIR)/build/proton-c/proton . $(PROTON_TARBALL): wget $(PROTON_URL) clean: rm -rf $(PROTON_DIR) $(PROTON_TARBALL) proton tmp rabbitmq-server-3.2.4/plugins-src/rabbitmq-amqp1.0/test/proton/test.sh0000755000000000000000000000041312305126066024362 0ustar rootroot#!/bin/sh -e DIR=`dirname $0` echo Sending one message... # Not localhost in case it resolves to IPv6 (proton will not work) $DIR/proton -c amqp://guest:guest@127.0.0.1 echo Sending 10k messages... $DIR/proton -c amqp://guest:guest@127.0.0.1 -q -n 10000 echo Done rabbitmq-server-3.2.4/plugins-src/rabbitmq-amqp1.0/test/swiftmq/0000755000000000000000000000000012305126066023217 5ustar rootrootrabbitmq-server-3.2.4/plugins-src/rabbitmq-amqp1.0/test/swiftmq/test/0000755000000000000000000000000012305126066024176 5ustar rootrootrabbitmq-server-3.2.4/plugins-src/rabbitmq-amqp1.0/test/swiftmq/test/com/0000755000000000000000000000000012305126066024754 5ustar rootrootrabbitmq-server-3.2.4/plugins-src/rabbitmq-amqp1.0/test/swiftmq/test/com/rabbitmq/0000755000000000000000000000000012305126066026555 5ustar rootrootrabbitmq-server-3.2.4/plugins-src/rabbitmq-amqp1.0/test/swiftmq/test/com/rabbitmq/amqp1_0/0000755000000000000000000000000012305126066030013 5ustar rootrootrabbitmq-server-3.2.4/plugins-src/rabbitmq-amqp1.0/test/swiftmq/test/com/rabbitmq/amqp1_0/tests/0000755000000000000000000000000012305126066031155 5ustar rootroot././@LongLink0000000000000000000000000000015100000000000011562 Lustar rootrootrabbitmq-server-3.2.4/plugins-src/rabbitmq-amqp1.0/test/swiftmq/test/com/rabbitmq/amqp1_0/tests/swiftmq/rabbitmq-server-3.2.4/plugins-src/rabbitmq-amqp1.0/test/swiftmq/test/com/rabbitmq/amqp1_0/tests/swif0000755000000000000000000000000012305126066032046 5ustar rootroot././@LongLink0000000000000000000000000000017200000000000011565 Lustar rootrootrabbitmq-server-3.2.4/plugins-src/rabbitmq-amqp1.0/test/swiftmq/test/com/rabbitmq/amqp1_0/tests/swiftmq/SwiftMQTests.javarabbitmq-server-3.2.4/plugins-src/rabbitmq-amqp1.0/test/swiftmq/test/com/rabbitmq/amqp1_0/tests/swif0000644000000000000000000003361012305126066032053 0ustar rootrootpackage com.rabbitmq.amqp1_0.tests.swiftmq; import com.swiftmq.amqp.AMQPContext; import com.swiftmq.amqp.v100.client.*; import com.swiftmq.amqp.v100.generated.messaging.message_format.*; import com.swiftmq.amqp.v100.generated.messaging.message_format.Properties; import com.swiftmq.amqp.v100.messaging.AMQPMessage; import com.swiftmq.amqp.v100.types.*; import junit.framework.TestCase; import java.io.ByteArrayOutputStream; import java.io.DataOutputStream; import java.io.IOException; import java.math.BigDecimal; import java.util.*; public class SwiftMQTests extends TestCase { private static final String host = "localhost"; private static final int port = 5672; private static final int INBOUND_WINDOW = 100; private static final int OUTBOUND_WINDOW = 100; private static final int CONSUMER_LINK_CREDIT = 200; private static final String QUEUE = "/queue/test"; private AMQPMessage msg() { AMQPMessage m = new AMQPMessage(); m.addData(data()); return m; } private Data data() { return new Data("Hello World".getBytes()); } public void testRoundTrip() throws Exception { AMQPContext ctx = new AMQPContext(AMQPContext.CLIENT); Connection conn = new Connection(ctx, host, port, false); conn.connect(); Session s = conn.createSession(INBOUND_WINDOW, OUTBOUND_WINDOW); Producer p = s.createProducer(QUEUE, QoS.AT_LEAST_ONCE); p.send(msg()); p.close(); // Settlement happens here Consumer c = s.createConsumer(QUEUE, CONSUMER_LINK_CREDIT, QoS.AT_LEAST_ONCE, false, null); AMQPMessage m = c.receive(); m.accept(); assertEquals(1, m.getData().size()); assertEquals(data(), m.getData().get(0)); conn.close(); } public void testMessageFragmentation() throws UnsupportedProtocolVersionException, AMQPException, AuthenticationException, IOException { fragmentation(512L, 512); fragmentation(512L, 600); fragmentation(512L, 1024); fragmentation(1024L, 1024); } public void fragmentation(long FrameSize, int PayloadSize) throws UnsupportedProtocolVersionException, AMQPException, AuthenticationException, IOException { AMQPContext ctx = new AMQPContext(AMQPContext.CLIENT); Connection conn = new Connection(ctx, host, port, false); conn.setMaxFrameSize(FrameSize); conn.connect(); Session s = conn.createSession(INBOUND_WINDOW, OUTBOUND_WINDOW); Producer p = s.createProducer(QUEUE, QoS.AT_LEAST_ONCE); AMQPMessage msg = new AMQPMessage(); msg.addData(new Data(new byte [PayloadSize])); p.send(msg); p.close(); Consumer c = s.createConsumer(QUEUE, CONSUMER_LINK_CREDIT, QoS.AT_LEAST_ONCE, false, null); AMQPMessage m = c.receive(); m.accept(); c.close(); assertEquals(PayloadSize, m.getData().get(0).getValue().length); conn.close(); } public void testMessageAnnotations() throws Exception { decorationTest(new DecorationProtocol() { @Override public void decorateMessage(AMQPMessage msg, Map m) throws IOException { msg.setMessageAnnotations(new MessageAnnotations(m)); } @Override public Map getDecoration(AMQPMessage msg) throws IOException { return msg.getMessageAnnotations().getValue(); } }, annotationMap()); } public void testFooter() throws Exception { decorationTest(new DecorationProtocol() { @Override public void decorateMessage(AMQPMessage msg, Map m) throws IOException { msg.setFooter(new Footer(m)); } @Override public Map getDecoration(AMQPMessage msg) throws IOException { return msg.getFooter().getValue(); } }, annotationMap()); } public void testDataTypes() throws Exception { AMQPContext ctx = new AMQPContext(AMQPContext.CLIENT); Connection conn = new Connection(ctx, host, port, false); conn.connect(); Session s = conn.createSession(INBOUND_WINDOW, OUTBOUND_WINDOW); Producer p = s.createProducer(QUEUE, QoS.AT_LEAST_ONCE); AMQPMessage msg = new AMQPMessage(); List al = new ArrayList(); al.add(new AMQPBoolean(true)); al.add(new AMQPByte(Byte.MAX_VALUE)); al.add(new AMQPChar(Character.CURRENCY_SYMBOL)); al.add(new AMQPDecimal64(BigDecimal.TEN)); al.add(new AMQPDouble(Double.NaN)); al.add(new AMQPInt(Integer.MIN_VALUE)); al.add(new AMQPNull()); al.add(new AMQPString("\uFFF9")); al.add(new AMQPSymbol(new String(new char[256]))); al.add(new AMQPTimestamp(Long.MAX_VALUE)); al.add(new AMQPUuid(System.currentTimeMillis(), Long.MIN_VALUE)); al.add(new AMQPUnsignedShort(0)); al.add(new AMQPArray(AMQPBoolean.FALSE.getCode(), new AMQPBoolean[]{})); al.add(new AmqpSequence(new ArrayList())); AmqpSequence seq = new AmqpSequence(al); AmqpValue val = new AmqpValue(seq); msg.setAmqpValue(val); p.send(msg); p.close(); Consumer c = s.createConsumer(QUEUE, CONSUMER_LINK_CREDIT, QoS.AT_LEAST_ONCE, false, null); AMQPMessage recvMsg = c.receive(); recvMsg.accept(); assertEquals(val.getValue().getValueString(), recvMsg.getAmqpValue().getValue().getValueString()); conn.close(); } public void testAtMostOnce() throws Exception { AMQPContext ctx = new AMQPContext(AMQPContext.CLIENT); Connection conn = new Connection(ctx, host, port, false); conn.connect(); Session s = conn.createSession(INBOUND_WINDOW, OUTBOUND_WINDOW); Producer p = s.createProducer(QUEUE, QoS.AT_MOST_ONCE); p.send(msg()); p.close(); Consumer c = s.createConsumer(QUEUE, CONSUMER_LINK_CREDIT, QoS.AT_MOST_ONCE, false, null); AMQPMessage m = c.receive(); assertTrue(m.isSettled()); s.close(); s = conn.createSession(INBOUND_WINDOW, OUTBOUND_WINDOW); c = s.createConsumer(QUEUE, CONSUMER_LINK_CREDIT, QoS.AT_MOST_ONCE, false, null); assertNull(get(c)); conn.close(); } public void testReject() throws Exception { AMQPContext ctx = new AMQPContext(AMQPContext.CLIENT); Connection conn = new Connection(ctx, host, port, false); conn.connect(); Session s = conn.createSession(INBOUND_WINDOW, OUTBOUND_WINDOW); Producer p = s.createProducer(QUEUE, QoS.AT_LEAST_ONCE); p.send(msg()); p.close(); Consumer c = s.createConsumer(QUEUE, CONSUMER_LINK_CREDIT, QoS.AT_LEAST_ONCE, false, null); AMQPMessage m = c.receive(); m.reject(); assertNull(get(c)); conn.close(); } public void testRedelivery() throws Exception { AMQPContext ctx = new AMQPContext(AMQPContext.CLIENT); Connection conn = new Connection(ctx, host, port, false); conn.connect(); Session s = conn.createSession(INBOUND_WINDOW, OUTBOUND_WINDOW); Producer p = s.createProducer(QUEUE, QoS.AT_MOST_ONCE); p.send(msg()); p.close(); Consumer c = s.createConsumer(QUEUE, CONSUMER_LINK_CREDIT, QoS.AT_LEAST_ONCE, false, null); AMQPMessage m1 = c.receive(); assertTrue(m1.getHeader().getFirstAcquirer().getValue()); assertFalse(m1.isSettled()); s.close(); s = conn.createSession(INBOUND_WINDOW, OUTBOUND_WINDOW); c = s.createConsumer(QUEUE, CONSUMER_LINK_CREDIT, QoS.AT_LEAST_ONCE, false, null); AMQPMessage m2 = c.receive(); m2.accept(); assertTrue(compareMessageData(m1, m2)); assertFalse(m2.getHeader().getFirstAcquirer().getValue()); assertNull(get(c)); conn.close(); } public void testRouting() throws Exception { route("test", QUEUE, "", true); route(QUEUE, "test", "", true); route("test", "test", "", true); try { route(QUEUE, "/exchange/missing", "", false); fail("Missing exchange should fail"); } catch (Exception e) { } try { route("/exchange/missing/", QUEUE, "", false); fail("Missing exchange should fail"); } catch (Exception e) { } route("/topic/#.c.*", "/topic/a.b.c.d", "", true); route("/topic/#.c.*", "/exchange/amq.topic", "a.b.c.d", true); route("/exchange/amq.topic/#.y.*", "/topic/w.x.y.z", "", true); route("/exchange/amq.topic/#.y.*", "/exchange/amq.topic", "w.x.y.z", true); route("/exchange/amq.fanout/", "/exchange/amq.fanout", "", true); route("/exchange/amq.direct/", "/exchange/amq.direct", "", true); route("/exchange/amq.direct/a", "/exchange/amq.direct", "a", true); route("/amq/queue/test", QUEUE, "", true); route(QUEUE, "/amq/queue/test", "", true); route("/amq/queue/test", "/amq/queue/test", "", true); route("/exchange/amq.direct/b", "/exchange/amq.direct", "a", false); route(QUEUE, "/exchange/amq.fanout", "", false); route(QUEUE, "/exchange/amq.headers", "", false); emptyQueue(QUEUE); } private void emptyQueue(String q) throws Exception { AMQPContext ctx = new AMQPContext(AMQPContext.CLIENT); Connection conn = new Connection(ctx, host, port, false); conn.connect(); Session s = conn.createSession(INBOUND_WINDOW, OUTBOUND_WINDOW); Consumer c = s.createConsumer(q, CONSUMER_LINK_CREDIT, QoS.AT_MOST_ONCE, false, null); AMQPMessage m; while ((m = get(c)) != null); conn.close(); } // Whatever Consumer.receiveNoWait() does, it does not involve the drain // flag, so it's clearly more a case of "have any messages arrived?" rather // than "has the queue got any messages?" Therefore we have an icky timeout // to give the server time to deliver messages. Really we want a way to use // drain... private AMQPMessage get(Consumer c) { return c.receive(100); } private void route(String consumerSource, String producerTarget, String routingKey, boolean succeed) throws Exception { AMQPContext ctx = new AMQPContext(AMQPContext.CLIENT); Connection conn = new Connection(ctx, host, port, false); conn.connect(); Session s = conn.createSession(INBOUND_WINDOW, OUTBOUND_WINDOW); Consumer c = s.createConsumer(consumerSource, CONSUMER_LINK_CREDIT, QoS.AT_LEAST_ONCE, false, null); Producer p = s.createProducer(producerTarget, QoS.AT_LEAST_ONCE); AMQPMessage msg = msg(); AmqpValue sentinel = new AmqpValue(new AMQPDouble(Math.random())); msg.setAmqpValue(sentinel); Properties props = new Properties(); props.setSubject(new AMQPString(routingKey)); msg.setProperties(props); p.send(msg); if (succeed) { AMQPMessage m = c.receive(); assertNotNull(m); assertEquals(sentinel.getValue().getValueString(), m.getAmqpValue().getValue().getValueString()); m.accept(); } else { assertNull(get(c)); } c.close(); p.close(); conn.close(); } // TODO: generalise to a comparison of all immutable parts of messages private boolean compareMessageData(AMQPMessage m1, AMQPMessage m2) throws IOException { ByteArrayOutputStream b1 = new ByteArrayOutputStream(); ByteArrayOutputStream b2 = new ByteArrayOutputStream(); m1.getData().get(0).writeContent(new DataOutputStream(b1)); m2.getData().get(0).writeContent(new DataOutputStream(b2)); return Arrays.equals(b1.toByteArray(), b2.toByteArray()); } private void decorationTest(DecorationProtocol d, Map map) throws Exception { AMQPContext ctx = new AMQPContext(AMQPContext.CLIENT); Connection conn = new Connection(ctx, host, port, false); conn.connect(); Session s = conn.createSession(INBOUND_WINDOW, OUTBOUND_WINDOW); Producer p = s.createProducer(QUEUE, QoS.AT_LEAST_ONCE); AMQPMessage msg = msg(); d.decorateMessage(msg, map); p.send(msg); p.close(); Consumer c = s.createConsumer(QUEUE, CONSUMER_LINK_CREDIT, QoS.AT_LEAST_ONCE, false, null); AMQPMessage recvMsg = c.receive(); recvMsg.accept(); compareMaps(map, d.getDecoration(recvMsg)); conn.close(); } private void compareMaps(Map m1, Map m2){ Set e1 = m1.entrySet(); Set e2 = m2.entrySet(); assertTrue(e1.containsAll(e2)); assertTrue(e2.containsAll(e1)); } private Map annotationMap() throws IOException { Map annotations = new HashMap(); // the spec allows keys to be symbol or ulong only, but the library only allows string annotations.put(new AMQPString("key1"), new AMQPString("value1")); annotations.put(new AMQPString("key2"), new AMQPString("value2")); return annotations; } private interface DecorationProtocol { void decorateMessage(AMQPMessage msg, Map m) throws IOException; Map getDecoration(AMQPMessage _) throws IOException; } } rabbitmq-server-3.2.4/plugins-src/rabbitmq-amqp1.0/test/swiftmq/Makefile0000644000000000000000000000101512305126066024654 0ustar rootrootCLIENT_DIR=swiftmq_9_2_5_client CLIENT_PKG=$(CLIENT_DIR).zip .PHONY: test test: build/lib ant test build/lib: $(CLIENT_PKG) mkdir -p build/tmp unzip -d build/tmp $(CLIENT_PKG) mkdir -p build/lib mv build/tmp/$(CLIENT_DIR)/jars/*.jar build/lib rm -rf build/tmp cp lib/*.jar build/lib $(CLIENT_PKG): @echo @echo You need $(CLIENT_PKG) to run these tests. Unfortunately we can\'t @echo redistribute it. Obtain it from the SwiftMQ website and place it @echo in this directory. @echo @false clean: rm -rf build rabbitmq-server-3.2.4/plugins-src/rabbitmq-amqp1.0/test/swiftmq/build.xml0000644000000000000000000000205112305126066025036 0ustar rootroot rabbitmq-server-3.2.4/plugins-src/rabbitmq-amqp1.0/test/swiftmq/lib/0000755000000000000000000000000012305126066023765 5ustar rootrootrabbitmq-server-3.2.4/plugins-src/rabbitmq-amqp1.0/test/swiftmq/lib/junit.jar0000644000000000000000000035435612305126066025634 0ustar rootrootPK ®»$- META-INF/PK®»$-META-INF/MANIFEST.MFóMÌËLK-.Ñ K-*ÎÌϳR0Ô3àår.JM,IMÑuª´RpÌ+ šèòrñrPK/c„10PK rº$-junit/PK ʺ$- junit/awtui/PK ʺ$-junit/extensions/PK ʺ$-junit/framework/PK ­»$- junit/runner/PK ˺$-junit/swingui/PK sº$-junit/swingui/icons/PK ̺$- junit/textui/PK ®»$- junit3.8.1/PKʺ$-junit/awtui/AboutDialog$1.class}P]KA=7I»&®MLšÔÔ¤VɃFìÆ·‚R¢!´BJÞ'›©NXwew6ÒŸ%Ø|ðôG‰w&¡H1 ÷cÎ9÷Ìý{{‡,ö°E¨OÒPiO\éTyÝQ”ê#%‚謵‰˜ /á™÷m4‘¾v%4m—9žœÊP{]_«(ì«DËPÆ^^ês•´:< ¿`Â!?øês©•Ï„CŰO„ÆöBÆÎëEcIÈnï ]°R@¯\8XÊ#ƒ¡ØW¡üš^Œdü]ŒÆ–û‘/‚¡ˆ•©çÍœ1HX_4¬µÏ‹ÂþìTÆ?¢øBŽ ìî©Ï›Ü,þ{Ÿ 9X#8c•\F‰tñÖX®c@ì¢ñœ¡0ˆÒØ—_”q\zäÜ“Þ D’È^@¼J¾e³Žy˜“á[À2×.g¹¶öÛ»¿°zm1e‹2/«SáÌåhº¯QåH¨áÍ\å3Gƒ]jß`õ7ÿkTÙAÍjÔf¸¹†ÉšxgÙ–ó›–5ÓÊPK؉Þ䎡PKʺ$-junit/awtui/AboutDialog$2.class}]KA†ßIkÓÖ4+Ë´ì 5Jñ*H,±‚@º1ìzÔAG¶]Ù¤Ÿô]ôúQÑ™Q""[Î÷sÞ³Ÿoïáû éQ`K¿Ì'~ Ë®øç’[Î _5À²#~ÏUµ,î…í—o¥Ýw&>ûÂ5bXò‡ÒËWˆÔšƒ:aˆ´l(|Ù£š¤¶:± s'ІpÓé †P¡Ø1±Œ•(Â0M,b)‚¬2Ä[Ò×Á]W¸7¼kQo²åô¸Õá®Tñ,V2ó–å«$06ч5-Ç“ö€!GÚþºüBùZ^ü»>ÅH1}éO˜ØV‚·f`¤!û!Úv·'.¥Ò›ø¡íH1˜W¶-ܦÅ=Ox¨Ðùat¯úd ¨oÞ2"GÉ;¦Xe¢¥WÄJψ?êž„ÊéJ( kä™dU6‰uÍÝÀæŒrFVsKOˆ¿`ç7£N»O5#5Û?e(/ƒ¬žÞÕ3{Èé©)H~PK€¸àeu†PKʺ$-junit/awtui/AboutDialog.class}VKtUþn›d&cè#¼¡¡@ZByÖPZ ÂC Å “dšLIgj2¡ñýB|¿qãJ÷ºhâ1ç°å·ºõ¸séÖÇïδ%-…žöææ~÷»ÿÿþö߯wÑŒ|'°v¢b[nÒ˜v+VòpÆ©¸G,£èäÖ ãš!uÉya³@è€EC+ã©ýÑ’1it †œœA! ¨‘²éž5ËÖ #S4©_ì‹@ÃcRX³äXÉÊ ù”1C ZšãÒ6ˆ6 ­hˆ.Ø9¶kX¶YR°R ̾›ÀºX¾ì¤ay³4 c­Æ «°vq¬É)Ç6mæÔƵnj0>2"}Öa½†'ÐA‰ÇŠ*ÍÎY®<Ò까EÃÎ'GÝ’eç½\Ob“<ãæF"+®ëØ ¶0ØPÑ)›*¶ÉÒr+ºô‡ÜGg¯‚íë™jyƒŸ© ÝØ!Ðnär‡³®åØ)«ìš$J`S3æ5ž7¹ØÂ ±½Ê.–3fQÁb>~žÙUìÓ°WÂ]q¿ÉßS¬œ‡GÅ«kf|Nƒ8¨¡‡|¾¥3o¤± (ñð<ƒÃ’üÁùBi5X—p„I=\1G5 K`«|šJ›KŽ™¥²%ih²rTÇ»DÁ ¤4ÇI4¦¦L›–ÝË]î" #œÆ‰à9ŽXf&v‚,ÇÍìÕ˜açbÃ%+[ˆ3&' £¬!×ñÝ#8/3ƒ ÔÖxÁ)'ï(x^CZ–ÿº¥­Â.(»%ö[Vð‚†KÒ*˜§òº€‰à%\SzeN:AÆ—dÙ4R2måÜB¦/Ф´`Zù‚AÁ[’;[pJ\õEE6'KL «áÒi  Ó™ 3ëߥ G6ßTcCŒØ¼¢g}*ì·ùêp5”Qa^ËÓ³ SK\Hö4®K,3h›] ^ÑpS¶Äýœ,;çL+xÍïÿë£úd±…w–7ð¦†×ñã¦øªLfÌÒ9ÿ‹¦œ¬Q3J–ü>' ¸‹çÐÚÀ<ì”Q2e'´-}Y©Ëx/Ç""üÇD*‹²C{9zM» c?˜Ä‘à–Ú³÷+)5«#õˆr[·9¢ 2ÕhÈ|i£N¥”5Z’™¶vÈœ#²o‡ŠF¹l–CßQùê–£…«4ÝâªQXLl¯!œh®bE¢ŽÖt Ñ*O´‹ãí¸]ņD4VEg[ÓÑx ‰“Ýut§5$«Ø]ÇÞtt }§zêèOG4·uÖðtCRSÇp:z¬†gÁ©*ÎFÏq©âÍûz`Þ¡eÞ!ÍÔûƒu\âæÅþ ÍÂÐCͳÈé¡À,òÞ:¡‡Ú´YL&zôP/Ï›+º”æJ@šË}ÞÛOèŠo®t¥Á^ÕUÏ^®9oÍëªg¯zöºZG9ݦ6ó·†k³¸‘èÖÕ†a=ì{øÂ¾° <—0¨‡iORoJ¾^­âíŸy Mx‡ë÷ØÆUã}Èq¾‚£µ9§· ID9IV¢Ÿ|¾‡9DÏ£lÀ{¼ÏO± w°? ?ѣƑsqÜC~Ga;þæ$û;ð/’¢;E+zŦ8v‹$öŠ>ìG°_œAŸ¸ÀÉs™ç ˆ?¯bïݸ_Ìù¾W>Eܬž¤8ˆÛø'Ûð>æÿCfú„»ÑýÉ¿Ïx²;øŸã VÜ=üˆ/¹ShUÁWÜ©D°_sfœo<^¾¥xæ&b‡·»éþPK×uÔ˜Lt PKʺ$-junit/awtui/Logo.class…UkWWÝ#è@œF-)‚EM‚€ÅGmcm%ŠbZ@û°C2$ƒÃ ™€Ú÷ûý~¿Öê7¿Z«ÑU×jû©]«_úººÏäAx¸š¬äÎÜ{î9ûì³ï¹ÿûëo¨A~TÐ4›·M¿O_ôóf_ÊÉ:*³ú‚.“}IÝ^Ð=5 6Ì ÍéYƒ{R•å`&!k“fÆÏ)P†¨3' 3›óù”¶tÏëÚ«`Sq¥ÛÙ¾¤LrSýØeÛϾ™¦ƒÃ&qQPM(¨M:CÃ=h¡M ê,bëÍš3us§å虚®h•ë1ß5íl"¶¡†fl aZ4¬Ç†z>mU°¥b5ldL}ÜÕÓ WŽ Z£K.’Îܼc¶ŸˆM¦Hm¸˜ôLDsteÄ!±ÝޱíTZÔMÐqZ–†û%­6t)hX¾KÅ.ºÍ~‰ÍÎ*·¦ÍNO{†»`¸‰Ø†(b!ìF\ƒŠ:Ilù¡‹b 4ô×û4Ô×P^›Š}¬—gøcæ&´>:dpCØl^bùø¥´1­â!Š%eÚÆH~nÚpÇõi‹›Ã)'­[ºkÊ{i²ÖÏ™ž¬­T• úEêÉ{jÍš$D©å…qDZ.šD|”ºb¦ÇŒ=où¥i)FUýK³T@ÇBÀq !l"N(h ÀôºyÛ6ÜÞÝ3Æ Ï ^ë0T> K²Uñ¸ÜqGô9&µóîâ«’º†aŒ„ÂiíK‹#N°LøƒNÞÎw]‡â{bÕã9×YUŒQEÌvØð¼’æb«ƒk8‹‰Æ1Iy¯.PðT£8¯`#ýž“wÓt¸ãîÉØ†ßwv4E÷OáiÉäZõŠŠg‹ð’ŽíSN+ážž5ÒR…i¤CБQYKÚg\'“OË!œ!¼´kè¾Q:c{×> åkúL)ù¬‚Ž5qü"éKR¶¨Q;¨jx5¢Ñ²¾Â«Õž•wé a9]€ÀN‘kŒÿ|û‡÷n Çtü6ÅãáÍ´ÞĶ;h›âL{ª;~Ûj ØÑ]ÀΫ¨–÷?Ñ—1^@÷Mô”Ÿ÷ÞDÿU4Æ›šeRþûe©‡¿þýÌlü»ñ0¡%ô €Pj ¥MhÅ&Zl¦E3o‘Vôa+í¶áï¦3ˆ`í<®Ûq˜»Z胰ñŽplex1‚"k)¹Ÿ˜šPsè6‡¯ãäÔ_ˆL†OÝÆ™©_p’Pï`ôü…ÎÝ“¿3Á #{z 0þ@¶€‹×F”kŒ¡ÓVÌÑÏ~ËÈ[H5°ƒ³]ˆa'Wv1›h€,^ŒYB&O6"ª¥Fæñ=ÄèÕ…Gt |äKhu–MrêŒÊ¥"Ï­EþkÊ4’å—&j+0ÂA¨=Ó¹X;HÙ9x¯ä,TÂã.±Št_Ç[¼×Í(|tŸ‡¯ øn)RC ’~BÜÇb쯊©D‰T¢|ìûá?PK(äQØ PKʺ$-junit/awtui/ProgressBar.classuV[WgÝŒ Sn€ ॶ ƒ%´^¨¢UAÑX@ JÅÞ“Œ†'P[{¿_úXú |P– ]íZý}íÿéê>3Ã$MíC¾9ßíœ}öÙßYùóïßþ@/á…¾›Õ’ífÌ ·jg.9åǪT&M' ¥ÐqÓ\7e/3e–ÖÍJ…Ëg§ì(¨k2¹\vÍ"'Y…Øò¶…xh_å©ã6ƒ¼¦I/*hSå¼¥£ zÚu´bG -èÔÅN±ºuÄ|«GGÜ·’ Ýu<åÕµrÉ*¹Qô+D+–»`ß³ZÓÙìð¢Žg‘Šc˜ÃŒ]²æª«7,ç²y£È3Ý3åœY\4[æÁ¢ælÂÞ5ó?|L(´¯0ŠkºÕÊT¹(t§‡gqMNý{%ŠýLÛ±ò ͇u¼€cxig «¤ÃðWF¸²fÚ%W!™®ß;ç˜k;W™;¼“fîÖŠS®–ò:2“©1…6oÏG«ãý Ë´¢xŠ?…žpqánŵVôãd7W.¹N™ENÎ<íó8Šc1¼ ºéúï(N(ìd…Öéf¤`'q*Ž×pš*"Í“’OEro`xÞʹfi¥h1àÎH}Ï6j"ÜâéÛ°ónAGVÔs¨Â‚e¯\3þÒ,a-ÛÅ¢Üc–Tޝ‹¸$PÞàvÞtn1»:üº\–EÇÜQéXôO¾)Ñ ¶Ë•%ÿ_†bª=O¿ÏI9Þ•'@çqY³Öű¼™Žœìïų£âšŽË·¤Y¥É•p¶`ÎŽhZ_+ñÍ×ñu{jK³ôÃDh¼‘c!Ž±Ç +éãh…8®8FJHåƒØʪ‡Š{eÈLCˆD"eÂPžµBKR-„Ÿ÷æ@¿¡‰š·uÝe0X±†R=N’:IjÅAÆ<³¸‘’îPÃçÍÏ0ÆYFnÈ(FŒã‹ £/ñUàóGÞ“›ãÆóЮKe(ÀyI“x€öÔFfýº´Æ€ÚÂ7uû¼¾–e ,Ú Õ5Çÿ©ÈKìó,áBƒpÆCPãø–úã_ êø~ œï<¯ßÿPKäž;lx- PKʺ$-junit/awtui/TestRunner$1.class}P]/A=W˶k)õýY¤TXÞ$DˆHéût ¦ÝÝYâgIñàøQâÎh"‘2Éä~Ì9gνŸoïÈ` K„Éf*í‹{*ÿR&ú< C—7a¨)î„ßáZoÊ@;Èæl—)¾¼“¡ö÷­¢°ª-™ê —Ч*)o°~µûÛ„üÅC¨R«€ñ;ŠQ»„™å¿+5Bö º’„ÌòJ̓‹Y zpË£C„BU…ò$m×e|)ê-Æ«Q Z5+SwšYc0ýÇ_åM¶Wv¬3_Gq[^Jì­Ûä‡&·þÆ»ë9˜$äDÈ„—âaý.¦0Cèµ:„Ùÿ” îE”Æ"t®„ŽdÅFZÙyés¡ãH¯l4 "´¬ˆu‘µ…³œ/yR˜I$õAÉòûG GòÕÝÇ …M'(ÉÀ2MëÂîøk!´I訸=±*7\ïJäÊNõëÏÆ2!WwX ÔN¹&ƒ'2 :44i¨Å!u¨o@ Zt¤Ð NiBsÞräÅpuIzóbÉf¯tÞ5„½ «$Ø7åË /–¤­cM‘åâ-nN1&Fí•ý”±} ;$Ô,:6Ô®šÄÛ¼4£)V H5™‰‰¥$Ÿ´‚z†œ¶Ô†jÞkˆ DÐg”0e Ÿ/FyßÕjë©E‚úK«e¸+Õ𣡑eOgYNð»yð&?Ç·Ð:8´…¶k‘a{dÊô sYÖùÍæèÀa~ó¯šb(:ÉAUˆëƒ7…Ÿ2Žmáuº¿ÊÈÄÒ¿ÚnᡌÓJ•>³sÛxjR}¨xÜÂ35¨œËxîÎOY^ØÆ¥Ï1ÊÆ¹¾yªN)¿ÂÜbzþ&^RBG]¯•!Òÿ+c™‘•švs¹’^-ëèÖ·±¹Wm-\Éw8Dߣ›~@–~Äiú ô3_½_°H¿BÒo°èwž‡?ð1ý‰Oé/|Fã ú×è߈¥Á¨×+,M`ïà]æÉâíøŸpøf¿Ï§:ŽüAÿ*>Œø¦¨EܶÿPKM ¼31»PKʺ$-junit/awtui/TestRunner$2.class}Q/A…ÏhkYK)ªª­„‹D’&D›¾OÛÁ4ÛÝdw¶H„ßä‰xðü(qgÚ„^öÜ;{Ï7gîûÇëRØB™¡ÐO©\~£é¶D¬.’ ÑÆ®Æ0ßçCîú<¸rÏ:}ÑUR esJW E Ü£®’aàÉX ²ZÈ0LîKÂ2¤*Õ6Cºö„ S6Ò°²ž Äi2舨Å;¾`Èya—ûmIÝÓêZÆ Eﯔ5Bqsý¹ˆ.Ãh z ëïׄǺ®é<ßÞÕ¼£Ø 9ºMÜJERiTÛ–°lcy†Œ0”þÃ2ØÍ0‰ºâDêäÙ¯”ÛÚÅà4tS÷y‹;˜ MТª WCÝ4U{¤Œ4³ùŒ™'óÛ¡¯mÆîi–*g4„9dIéIXHõl&õ‚•Ÿ€<@~44誀Uc-ÏJÆ5‚¹OPK§ qG\7PKʺ$-junit/awtui/TestRunner$3.class}R]kA=·‰Ýf»ÍÖ´ÖZ£Õ6–4EWðEP  ÁSâó4Û)›Ù²3›´ÿDÔ?!ø…þ”xgÚ"èÂp¿Î=÷žËþúýã'J¸-Âêq¡•MÄØ*ٗƾ.´–yãQ"ÔÅH¸b"GRÛäÒƒlü| N¬Ì”Õ‘Ho•én.†’°Ø9ïñ™'„J÷LÛ#iUŸ0ûTñ¼g„¥æßÀí¡ÜÎLRjn÷"Ìa>DQ„+˜­`UBÜQZ¾*†2ß)ck¬/Ҟȕ‹§É²=R†°Öù—<^kaìÕ´ÓÌ(}HX¿´Ñe¹/œï·‹Ïë“J€B0Pæ$32ªÛ÷:nð<0ú0éž+‡nòRòTY6Í=§în‡¨c@¼pý³ a7+ò¾ÜUN\|!äë"D{.h§ÂiðOUÀ·q—cÀ}3üæPá8dï1Ç.¶¾a¡µóñ'Yt9_yÇ,„«ìEl]¶†%Ï»ŒkS–—l6j}Fük¥ï¸sÁSåß xÏó?`=×Ê?årÞ]lx–Mß×À=?k ÔþPK_£Zh²¯PKʺ$-junit/awtui/TestRunner$4.class}P]KA=×Än·Fßµ•›Ôb|ðø£Œg¦•Ö›LfΙï|ß¹ÌþþóóâXÁ+†¹N$<é¸eä9{<”ï"!x7W2ÀÒ÷Èu|W´œ·oJq†í¥‡q!)쓬z¡ähàÃEÙöÂܱWϦ/3$kŸ…lsé5 ¿áj“˜íóòu†D%Øç q;_·`â’‰¦,˜H"†4Cªê þ&:lðîžÛð ›­Mׯ»]OÙCgB¥Ç0ŽV®Dé¥%UwýˆWÚT>ßgX¤äN¾£N:½Ù³é Ì‘ä ™Ãv$e Êæ±ÄU\c˜<¨Ežä¯=î“Üô«t´—à×±¤à7”Þø}%8üÊÅÀ-£Å¥ò¯Ž¦X“]O´ˆ&‡;&nãî3ܰi$>-ÙÖÝÞµP@ÑDËÔÑÕ1ÅU3ärG¨Sî û½šÑî›pð@—&]…j@ j(1`OÆ9O*5ð”ªÿU1cŸ.B)”±aâž30®'zÞ€(ÁZu›Ô]õR£ù¬ªkWß CRæ1z\ÔZYõÂhOB}1Z&&ɶè´N¶öŽ‘*¿#óMc²¥nzšç2,Ú•w3´ÓüpeÈÒ²,zÈô°8Ønöq¯•/0_‘ˆ÷ñpàœ]ïcs¤3Eÿ2ÐÇŽQÄ­5;àj©Ó^Z /uÜ6*:¦q@ö/PK±þ*»NPKʺ$-junit/awtui/TestRunner$6.class}P]kA=7Ú¬Úm5¦5©&5 >DC»>I !¤H IK ¾ë¤1³°;kÉÏ*$-ôAš×þ¨’;£(&Ãý˜sΜ{ÿþû=Co±KاZ™@|7© Îdb¾¦Z˸Ññ@„ÒXLE0ú[ðy8–¡ñ!l».S9•ÚïC£"ÝS‰‘Lõð„°j.TÒh³~où‡„|ÿJ› iTÈø#ŨcBmï!Bs@Èv£‘$döš<+ ‹ç><äòXA‰Pì)-OÓË¡ŒÏÄpÂØr/ Åd beëE3kíªüÕè°½¢pc}‘ñy_Ê¡ÎÞ–MþÁæÎ_e¹ž‡MB.Nu?UFú¨Zç¯P#›ÙzL•PèGiÊÊ/Þ‹¾³,‚ÿÉ݉H™ ÍkÈ‚÷É·l÷Â1{Vøð”kŸ³®]§õ ÅÖþ Ö~8LÙ¡ìËÌé¬sæs´ÝxÉ‘‡ÄÆB儣ſZ×Xû‰­ÿ5þ°ƒ[§Q™ã6ÛÆkÇ®;ÎÞ8Ö\(ßPKqø·‹¤PKʺ$-junit/awtui/TestRunner$7.classuPÛJBA]“ÖQ;¥Ùý~Á‡4êôVPD dø>ê.GŽG8gNÑg] ‡> ¯ˆúhÏ$•þÌZkÖÞ¯ŸÏ/H`k3í8PÚ“7:VÞEú< ;„@®-¯¥çËàÊ;«·©¡$æm—)]S ½MŠŠ41ÑÁ Àn©¨°Íê•ÿå÷ÒÕÛ@·H«ã÷£Xy½¡XH–»MH¬k.2É ‰QRi '­¨€NãN Y÷›¯tÒ¯ÉP™º×L{s}þ*ì°½œâ¡ªZj*·x|j ,²¹¿ƒ™ÌÚ›ú_ÎÁ ;»”ÊCª’Ï[¤¦‹9ã󂬗~Ò™j7t¬Œùìò–á¸'¦(û2Š(Â6¯" Þ)ß¼Ù Ç4Ìà›Á0×.g»\ÛNé ÙÒÆÆî,&oQæåÍêŒsær4Ý LräI1ÝS9äh°©Ò=Ʊð[ã|X©o\OÃd‹X²ìeËYÁªe}ëù/PKD´܇¦PKʺ$-junit/awtui/TestRunner$8.class}PÙJ1=×VÇÖÑjÝ÷…>hEÇÇ‚"Š(EE¥ïé5¥f`&£øY‚ øàø'¢ß ÞÄ‚ Õ@¸KÎ99÷¾~>¿ ƒ,Æ©V&7&UÁ©LÌqªµŒKDèoˆk4…¾ë ´ë2%×R›`;4*ÒU•ÉT„.s©’ÒëWÛ°NÈÜjs) ¿¡µI˜\ü‹°T#dw¢3IÈ,.Õ|äÑ›G}>õ&c‹Õ(Íšˆ•­[ͬµG˜øã¯R…í„ëHÆçQ|%ϳì­Ýä»6wþFÚëy#tÆ2Nµ k{“b'SÿIò'Q‡rOY×…ÅUË"øû¶ØiŠ$‘ ÖxYð2ùíR8æ`OßFMig`&ãã³\).ü?J½I Ѝ›œs“{NNnÞÞ_^QÀ:ª„…N+ˆ;«àRfúf0ëasâ$•ÿ, ÞE’§‘¯žmû°¢qf~¿ (1òs050Øc4½ÅÂ3æð:4d æúMðh¥KV³ŒŠUõÍ€ò'PK³Ž±ÊZ3PKʺ$-junit/awtui/TestRunner.class•z |TÕõÿ9wf2“É# IXÂ-b˜¢ˆ Š!€F³ a1(꼄ÑÉLœ™@[[Ô*u©k´T­–VÑ šlE+.­ÚÍ¥ÖRíbkmµÖ­Z—ß÷Ü÷fK&öÿçÜ÷î=÷ܳ/÷Í3Ÿÿd?9h¦ú‚iì9}¡@¬Æßë Ô¬4£±}¡q3M´Ö"z¦f±?jf8˜òº–Eü=&SqÓ9þ~ÁR£gê˜ º–nê0{cp(ÊTbôÅÁšÕfG,ˆÑµÌš‚0î. u :èu׬Ü1ý¡>ÝŒöcL“š,âºä¸þpäÜšô*€½]+#þ³{™JÓÔ­47ÅdRãkë ÄÌe3ØÉT– £g䚘F§W÷Åbá–Jº–GÂÝ3m u:üà‰©¼)SžI€Åþ4»}³)Eiœ2WWS¸;¬ÙÏ@"sX,êjéëYoFZ»–F"áH4KèMþõf@£S@öQ•š+QáûTðm±!D­0¡àä+„óÇú¢M)èVEͦ°¿3êNê&C˜ ÌŽsׇ7‰¼—7Õ7¶œµ¬µeegËÂ!áÌqbýr&n5 °‡˜?[íö™"rBóA4:mvJÐZó 2‰Íùm›C± f,ÐÁäYØ @6ÇgåŒÕPPC¸”ŽÊ:ÑM50Î΀?îöÐ{ 2h”<ÁÉ'Œ¿ÜtðÃ+Â}¡˜¶ôFƒ¢óR„ú`ì¢+ñxíCÂÀÐH •×O›„ÖÍ•Ñ9õ|lí÷GÛú::”ºú‚õZƒ¾J_Ô1ËŒðå¦oÀ˜¢1³× ‹Dû[éb…ðhÅp¦šÊÆœ1¹.;˜‡ûÅi´O°Är™Ó4»}ËbôrDƒôÎÆPÌ쳸RL©q}ÛKWÑÕL…ÙòpÓµ2š„vƒ®%^G7ÀÎu,õÐŒeRvÜd:!‡eýò·vˆn6h’Åéw%ÞZؼ~ÏâõVgŸì¡ÛaßQ…% ˜’+Ææ>!‹crŒþÎÎ#¨ff†,÷‡` MÃÃâ`cã’Fñɉ©UÙ¿Øß­ƒvÄÅ¢nºÛK»%عº±¸É {iz>f~lÏÀÞöX3{á2ÓèŒm0èkv@Ü7Ô±!1(aMí±ýf {ClXZbÐOhPæ’ Úo>’Ä), Ç2£`cZ?`¥0d…˃^z‚žÄÁ½ž•Э-0Ÿ§éÁ÷³ì Šm1¼gá-(ÓŒÊ\ÒËPBëúsPâhxž~á¥çè—`«7+c[j`Rá¬â#[D›ñ¯pýò‚ 8¹éK”ƒMÅC­ÖM¿‡06J¨híbš^™ƒÒ\ÞôzÍK‡èuœ-ñ÷OC‚íˆ[3‚í_$€¾,–Ã@Ýô7ø}72"Œ¿Yåïpߤ·Àg­‡þ)!1)ÉBõˆq‡¾Cÿ’\ü®AciœøÜ{™ÅZnú@ô‚ð!}d›<öqRr%ª›þ ¡ó¥A³Ç”H<&— æÏès/}J_”¯Ñ1ªg¼5ÆÌËÓÙ!žþ!;Å¹Í 6Jróäù(ç¶™½þˆ”é ±b¡b]ºIäá™Á¹n®öòL]ÞõhY “´ê dUÆ)PYª’™hÚ€’@Ò{E\,z>:i…ënF%Z1dßP†5³Çzy× 5ëSEIæA@n“ÙHMù•’ì„kã*TðÓFvÅÌþ¯0{ÆÍ ^^"†4*ˆ†BÏ5vH­Y’i¹=u/ãE'AsˆÎ¨W² b XÄw2Ÿìܧµp¤ÓŒ4ù7Ã’ÝÜ"i`¹—[H¾. 6ëB|bVñ$sÍþðZzYÁmˆßŒJ·,Õ¶9ªÝ:ˆÁ«¥{A’ˆ„ƒ:Mç;§q{>¯áµVí¶Øßqnwa¡3› ZŽ=ƒ×¡Àæ3G¶Êyn>ÛËþì` BD¸ß-iBÍzý2GˆÐG›ÜååNî†-(ŸÇG‰"α:Û’ bïI Qº«A©µKuµ.3¦Zj7ƒòpÌËQZgP1–pÙŸì’ÀéæD`¾1ëQ ðùâº[øXFÄ<¯O ÐpG_Ôà¯I¨lá ­JOÚ@±­!­¨pø Þ*€Y,Aè}=!ì¿a˜£üÍ‘e~”›/óò6ž"p‡ w´›¯ðò•á'­„ŠaJÈ\×~›¯¯ÉT­Õ »ù:¤ãá¼|½H°„JE‚7YÜ, InEâØ¡[4¾yd*ç»ù»^Þ)Ü\/ÜL싚+Ì Õí œ¾‘îß„Âo“ÁÉ·g¦Œdÿïæ;pŒµ×²3ZÞ"›+"Bê ÝAc­•~èå;ùGF‡ #w#ØB«ëO¸Á÷XÇÞ+ ‡àÙøãá=¹ZÅßóãPE2°B—NÃfD×]C‚ŽU‹¼[ÿ œÝºc©ð‡:+’7)0쇽NÖûG–ë1n~ÔË’Ú—4ðeÚÏ\×Úœ*'+û²Ý£æ$sAúfÔ­æÉy8bÙËÿ£C²nS u´šïUG)Ô”SÒ‹-a½ ò—‰·h™¸Õ±^U«+¶h? ÂøguºhéKøp¯¡öšˆÚ+ ò1d«ü6ÔVz°úûã¡Ò8Õ> hB•[Ô1üÁÀ€ÈezH¶Þ)ף⺳¹èµG,Ç×Wèꟷ¨Ç’s"W_î,Û8~ªžz¦ røÅÒl·zŠiΈ7K#†š§žñª§Õϲ¼ÙŠœnõ,‚ „§žSÏÛ_ilÉŠ—ŠA!šý Bä;Õ¯!Ä@h#$Ô©§_Ð-¦zÑ Ëý¯ÆVfUÊö…1x|YýVÀ_ê4ŽWÇsê÷°“ U¹6ZŸq䦣-YJy,(¢mR, QçÀ2¥XI_CýðãVTýYýE¤ý®JÑ©þ¦ eõ¦äÊ é´ÙŠ{#añ¼úHwŸDoL™3±ä:æêŸrÌÛ×ób1¥êuË5ÿm¨û¬êê}ˆÃ¯½{ÚlƒY“¥'çXß+FÒy®oˆÉ­s¡¯6]“@VQQzç,Ù7ÊKƒÕ£¢åTä$¢1øßEyò1Zîƒõ˜oȳz4h”ÑØè±˜Fëý·Ë€EƱ4Nèô8&êq’=N¶Ç)ö¾©öXaãCŒq’|…Æ8Ž éè ŽÄ³¢JЄŠïU$¦á½šfâ}ÞŽò§xf·—Ìu š?-Ø£÷‹ÿ¥ `(µµz–°w^ Ã<ŒŒÑåKС۪AÜL½Í°€è8:^Ã,J!0É¡a¤úvßÔ eMUÎ85UæjüÓ y]•F>VS=Hç@s!yÅQú ±2û ^D«5kè4ûÈf%Pc|ƒ´¶½äŒY§õqêJP`(Ç€ñ¨Çبåé:W£¦Po7ò Ÿ¬„ð¯7N´Å×ÞüÞ.°f¾§KªßEyÕ?²;K¡°éCØ«ƒÈbå80³ X”Aƒ/Eƒ/EÃ7éR›†{Áž˜hËÄ»4L“V™¥:1´y b›EÈûèš8}ÇWrSõÌݲ‹&a~§µv[ríûz--—)0x¢Å0×% k)”° Â? Om“¦ÓgQ¢³…îÐF)OwÒ4--´‹~i9¥×µhçràçé¤Ýí º§Ö[î<@÷•{Ç8è~ ®ŠcÈ ˽ãÝô0ÞòèÑ1yÎïQþ˜¼¼[)¿Ü[4@—{é‰ö1Îävï"§cròÁíNÐSôóªêroœ~•fm–>¼ž¼¢>ž·ÓßY ;[fVƒé50ÚÓ ôvÍj §Xí¡_Óo4«=ô½¨Yí¡—À¾C?½Œ'§~ú-ž\úi?žòôÓ+4¨ÅÛ#:AG>uÒïèUmŒÛi‡­â7Kv†Å€«öÑaÂ%† Ã[þ ;nš§Ô:Ëij&ÈÛ)wî£[æÞM¿ÓÿÆOfÆ‘`U­Gz?Î.ç­T$Ž8çûâl Ô°u°‡3z΂…úéDZñu@Dx2a]¢ ZPV° §æQÚve.iaÛ&¦Ð©\ˆUX²|è°ÙÞ‡wâɃ\Ò^Êe Ó4ÈãðXžà ÍÕƒ<©Ý—à©qþJؘ¾¦*Î3,€*`f{‚g¥×ïKq4_ëø Cõ½ð”óh{ZûD7#–mA,8±àpz>ì+lþ"ÍY…E•ÍY-âž šÇÒQ<‡çJÊ[q›‹Åx^½Uéü8×­s.…Ú/ËðwoJf^^ÈÇ“çE6>Á/Rô RÜæ)OÏ+#{lLNI·Ö~W ðDކA^bIui3¤ØØ2ó yªa"·Öv‡#Á§ÆyUõ^>=ÎgU×:1ío/w&x}œ7 ò¨uùÊ]q>·Zþ ÒuÀØ›àójó|ƒm¯:Hî*¾RîKðÆÞ‹Ûç¯ZÃ×eØK â|±<WÆùRyäm¢×oÅùrëõJy½*Î×éõ8á; ¾q€·cq;lõy§}/ηBÌߟïèÝ5Æà»x÷>þñv*èn² RÁVÐßb´Eõ^W‚t¤ÜVÊ …x²©Ë‘€¹3²3ˆ¤‚P $dƒÄy°ÖcÁ=,2ÊǦÛ= ~d€ÞÇäÂÄcq>˜ÅéS û)›Ó§ùú8ägÛùùv‡Ós‘à_I 8¿°(^/ð+˜zÅçßËX¼0·´vü‡~s¯§”ð:Nù³žá¿ÇùŸ6UšŠw0ÿÎ ¿‹}ÿ1òûxü`€?²èøoŸ ¾ò‚ò<‡Ãå**çOñ*zt8³'¶»œNWa±75±;t#/{ËG®<§£°¸Àš(÷8Ü.¼ÚëåùO8"YqžË™š)÷ºŠó²|ÅQì΀Ð(ÖXÒ0︊=É]Õå¥ü9’Hu\quÊõx-2ÑUßFÝw5ŠˆkPÝ]‡˜~=JŸP½ÜˆÄy\óF¸ä­H¡·!uÞŽ|s'Âé.Š! žÄ¸©ñ º;v#þߨÝH¥÷cõºãýÈè!zš¦g‘G^Àø2ý”Ñô6¤÷éIú”žaù1ÊXzŽ+èyöÑ/ùXú7Я¹™^à3èE¸—~ËéUÞJ‡ø*ú_K¯ñŒß¥7ønú+ßOã½É`|ŒþÅ/Ò»ü½ÇoÑûü}ÀŸÒ”›>V£éUNÿU_¡ÏÔú\M_¨…±[Ì^µ– àBµ…‹Ôå\¬náÑê.Qû¹LJõ*Soóxõ9—;Šy¢ãpžä8Ч8Žã©Žzp ál‹²’ÑÑ ”N&ŽÊÀ§¨Ø1O9• ¡y¶£TåaÎIËÔg:€ºèLõÐ:³‡”©<*ŸÜ¼‘ŸU^äno媫ùü"÷(s šÞT£ðT€à¹´ –ý(Ñ$DÊ6ù&_•ökU¿v8œÎB˜‹CÊþ úH¨R_•„'ËT–]z¹Øã(®LX8Ƈ+ €2‘lËûßH!Ïs’žáHìõŒ4¹‰xñTÌÓi4I¹’ã4 –Uƒù¹\Móx&’ß,ZÀ5t’aÏ¡å˜oãy´©pMgñ|2ùÚÀ (†ù~®¥M\G›y!}Zº„§ËænÀüM\OÛ‘²vÀjïà%t/¥{x=ˆù‡ø$z˜i?ŸLñ)°ö&X{3¬ù$XskF"=dÛK=¯5Íè#‹a¯–.'ÃV¤SkMŸ…å…ºø,´ŠÏB«ø,D¹©&•ZÅgáø|)5 ÇHEZ8Æ@)Z^X>Ê*/ ³Ê˹b´|̪\Kcùtš ÷›Æë¨ŠÏ„à΢cùl •¯§îÐÄ_¬k“ÖTЪ&Û%f«šb—˜­ò£:]‡´Êét‰Ù*? ÓUW«|þÐ%f«üRN—˜­òs8Tò$ŦUúJ)j觧霛§™Š´X~Z”QÃÈùÅ’[| u¸ä¢„:"Ík¡ÐÂÝTÀÀk £)Nvò]ÅÆw¬O—›qU©¾G.çnÇîìR†ƒhŠ’hä—6šívûU·OÍjÚ«f·?I“×”ª¹ûÔ‚öûÕì]T4¨jמ…â8¡ê)UÇÅU}3JAu⣪1®šïkæûp |"/W­áZ NÍìË$¡jŽÂ´cÐÖÆŒ °.Y]Ñ1j…jQÕd¨•j•p§V«56™5©¦ùÕ>¤\ã-9æ|¹,·7×Ú¢2Iµ'Ô¾¸:kHÉ_ƒØ/ÌÀc¨³•_ãY¯:†tÁ£Ó¡vÐtµ5UíS†êp+|œýâ G4åÓè]5øQ”uD#ò¨°µ¹p¢º•œ{¤»˜W=ªp³¯:¡¢é“&ˆmò¥½—Ñ(ÞF…|9Mà+h*_™!ß [¯bºŸ”}Vï ä6ßvä›ÀšØúËUÔÆhj¥*U›t£¯ÎO÷úÜ\õ¨ÚØÞ/ÄÂEªmФmšWßÚ§®nÞESj#î¶ëmÂåÎÕuŠ`Hç׺Êèð·ÓT½¯Üeµ^¥ê†ÔÆ]T/0W ½ t£ ¤vì²ÉN¯Ý’ZÛ£¯w¨!e›-r%ÄW#‰]™]K|=Î7Б|#͇<x;-E2_Ç7Ó™Hèݼý×­ÔÇ·!ÔÞŽÐú}ºï@ý ]Zæ+ôuÖË©¨ó²–4£#Š«ïj™I{ õÐ º'¸¬týKá9·ªÛðÔMç©ÛAœÔGêûHÏ.rÊ·m%w`EŒsµÜ•lsÈ-‰¤¡äCH? æ‹«¤Ë]±§A0Ÿ¶{ê®ú$ã…•Tpè-âêî´mù¤Aç»uï¦Þtuds/ùøÇ4þ~<ï¡Sx/RÒ.³:éËjwêvg•ݹñUA R±¢ «ûx@µ§,‘à‹JÉÅûú¤2þIî $-¦ÃäžÓ>â„$P~ ©LîbÒ(}%£îßE§øfãqõ >] Êé¥êaXŒx?•GÝN©ÇãêÉ&t\ã|ƒêév¡ùç SÇÕ/†f¥‡ásûi4 Ò': Ò›Íb¹ÕûÔ_³L× ‹à¬?‚Š>FXü„Žàÿf05=§¤Â¢¡/R„‰îSël¦&gwx{•îìð”ͨ%É/PúŠŒ˜&¡ÄN3<9ÅðdÛŒê­Ãó“w>éô%be‰e¹%ùð{ %ßåþ¹ü%䢎÷¢²+Cõ> u{Nrxô•©|ضºÂ®æú€ófŸ‘üÝjûèÑôþÆi…¼ÈEtõA2à=xÜéó—p‰Z2O•P‘*Åùe4M¥J5Žfªñ4%XZgsSô̵hUëF‘G}ˆZTiÊŽH߯«ÿ¤³nvjRWòÖå¾G}¬>±7N·¥—¿Ï¼Õ¶|íóa;ÿ›sg¦æôNå²S©OõÿŸ©ÏuÎðò$=_‚Àýö¸Í¯´ÇöxÀŸ±Çw­Q=mÿPKk1nv{:PKʺ$-(junit/extensions/ActiveTestSuite$1.class…RMoÓ@}‡¸q IÓmi)¦$vƒÛ3 *Uª8(=»ÉB¶8¶ä¿¨åX©Áîü(ĬeP…¢Æ–wgvÞ¼73Þ_¿¿ÿ€†ÂöiÈÄÄ2 b÷Å0‘SÑqÒKe"¬}D¨zSÏõ½àÛGÂéÐ¥d,ckiº‹xžʽOA2‰–¦žo%$4óÜ·‘7Â轫’o(L$âÔgÔú\Ô›,ÊØÒ3ÉÑç„ãÖâRæ ^'ЊáH´V{`ÂDÕ@57P*£€º‰%”•Õ0a ¢¬&¡Ú•xNNDÔ÷N|ίwáç¼H*??,ªA¬…µ[ûܬ¥¡1¯^„ÍÖõ½˜XÇf÷±EØZ¤¨c›PaÅCžp<#ÂÝùü³…Gb‡_/L£¡8”ªÁƬOÔ}"˜GA ¢ß‹ccgVønÖÕXAСžºíÇûÏ+ðgâ&û·Øz™34ì¯X¶VìÝnÛV/2ô^,Ëb$÷’å“ÊÁ=¬ñÎw ÕœoÂHwǾd–K¬~ÃÎP~uŽÊîÏs”ΰÜåÀŠ|ÁãÏt‘‘Õøý+×äf€6ŸØØ€ƒvØê\‘vréÇÔÚæ¸*“²B¹å?PKfc”Cî³PKʺ$-&junit/extensions/ActiveTestSuite.class”ÙRA†ÿÎÂ@Mˆˆˆ QC£"n(Š(Z%ˆåChÌ`œX3—ÇñÊkªª´Êðe|õïž‘`تäbæ¤9çûÏÖóã××ïˆc r+ ÏUEù^I/pë^Pœ®(÷­œ—šk¸JZ‡C¯eßy-ßÕýWÅMÿŽ \nÝ–ŽªÎÔž%¶k.C§âù‘ÄL}IڰОB)tÙõ䣯ëEéÏ;‹5)-×+NmÁñ]ý;:L¨ª •÷ÊwR ;_^qÞ:Åšã½,ÎÔœ ˜YК­Ù%ЮªÒœ tmqe9›ãç”ïz/#ÀA èa6¡3Ýâ'pr«úN¸>;ÂÖø O` _Þ®ÍOdШ)‘D[b°q ý:v¼s\õÔSnm–ªrÉÆqÝ݆Ù}ßD Ý-`1} 0±}“»çÆÉì5˜ás Ïò{ð2Ðý<Â(Æ2Í~ÏW}é,Y( $åøÊÆ9ݳ8¯—ʔܳ½÷Wý;ã6ùÀãÅYQ.§Gaãªæ_Ý:4?º \ÿ’ë˜Òs»!ÐßD”<%}¿ñFÉ¥;ï+òbS,LSŸ;–+ïîH™NïïðyWw R‡WWîò‡éZÍÆÝ0Í{©¹zïÈYW_´î–aœÑòvÉó¤oÖYäv%ÜÒKI«¶ežü5ηà;YXGç*l>õRûšÆ>ZvèÄ“´ñ†F€)zjß¶Âè:²­„,cBOè´uÝFœ—u;Ö¡VVY‡v`õâpÄê‹X%~7ã|[…ÑÓë8Ú ëcÐË…n0+JL[£ÍKaG)¦ ñ/Èé<‡ k8ÑÄgM»û™ë¥rÄnÊ9½!“ÆIœ29ç1Á_0JGg¾aô¹ÉûÌ£±5Œ7éûM²ÃèD‘„³†\c6È\À„) c4bôNâ".16§¿8‘Z5*¥÷lÖpí’åÕÂgVµ†›ÿ\¥_œ5¤¸:¡zŸY qžNðô"¹—x>Ω\ÝTco”I'ãgp›ÏAÜÁl¤ú€ÑaŸS*ñâ‹Ñ+µ–xS´oìм°Ä(›É ~Uô_öPKøŒôU9PKʺ$-(junit/extensions/ExceptionTestCase.class…TkOÓ`=/«vt•;äâ@„­ïEŸè·2Þâh—¶~€Â_àgFýî2ž·ã&%1MßKŸÛ9ÏsÒß¾ÿD ³X˜Ümznd˃Hz¡ë{¡½zP‘ˆÇ F+N(u¡¶_5pöä¾¼·Ï¬)ÎêêACV"¹-Ð[Þu>8vÝñjöJÝ Ã«‹.£—¦óç¬ëQàzµ…„aS@[ñ·¥Àà%þ…M: 2&®àj':pM »ìzòUsoKÎVÑ}e¿âÔ7ÀU÷ãZ´ã†Såÿ3'rÍ#a•)ƒ¬åI€€4ã0T^á7N“±VÿYðÆNàï+ :†Mdq]Ñè9sy½µËVêH×d÷„9ò…D£LÜDÎÀ8&Èþ‚QÇ-fuÃå0tkžª¸ø{ùd¿ß™¸iS˜È^dú²Y­Ê@G NÆœ;¥žK£hÀB†Sv éQ¥ó5Út ‰¶ó’Äl•až|#¿mS8“ô½‹{Ê÷¾ÂyA‘d*öí!§Vuܺ‰ÇJ%ðäŸ œFg(”ÈÊ—Xi3ÖýfP‘k®’M6¡Ž9… ŠO øR‹\;xÖ‘æÚÉÛÞSÜ3Vñ¦UúŠ®ÃØ©›kWlaà( Œ¡‡·\Û½èâS?âô ²€*GÝpâ7–q¡Œëà>oaô3IY_ÐUla²…ü'h‡Å_?`½í+aVYZ¸ÓƒoxzçÖù,£çƒŽiÒ˜aµ<ëYF 6 e¶]ëešû3,1“Àó˜Ý‹¿PKŒ—ÞjePKʺ$-#junit/extensions/RepeatedTest.class}T]OA=ÓÖ¶¬K–RŠ­¬¨Ø¤ øÉ‡ò¡I“F $ø¶m§eq»Ûìòü&¾øÄ‹š(5’è»ÿÄ?¡ÞÙn€PàefîÌsî9swÿýñAÜÅ*Cv×54§È÷nØšiØÅuÞâªÃk›Üv"` ×»RÄÑ*¯š–ê˜VA¹¾©5¹Ý¹ËÀJ áy®-2ŒäÊ„º¥6ù[ÓzãÌ•ò[ ¡³ÆÒää·dD Iá*ÃØ®º§uÕhKºÎª¾d5Ü&7œûUÞr¨¸z2¢G±R5]ÃQš®í(®,*ÓQô1$‰ïkñ4£ás Hˆ!.ã Â=`¡¯¬ü•Û¬pkS­èTm¼lVU}Kµ4û›!gG³FË—::'if:_1gù.ƼÚÅîŠjsÂæò%Y\~ŒRl¹1žïÝ:·]]8H/pñy7${ÇtõÚ†c¶<’×2nc\Â-Ü‘qc‚.ï&®¿—Òëk QÇìØÊ0˜Ëw›MúÏî-»õ:§vš–1…¢à¼ÇÐ6+‚Y†Èžª»|­Î0~ú!×*»¼J’»éd<Ä# ðX â$9gù¯’B˜®¶Zܨ1Lž×][Z v‹ñ™¨\iÃt­*©‰Ž8ýðS‚Ì .€ÑLF«­#ˆÒØCQƒ¾Ë ÍéÂDræzÛŽ÷·‘øUÈ|Cò 0Dã½4ÆèjèÇ0¢]¥BqðV#¸Fb•!Ú­©|ÒY/¤BJá+’;ŸŽYÂÞIÂC•;Y>*á#X”-•àÂ’‡È½Gø ¡¢ð.À2õã¿?'Õxâ…†áSýi Rÿe‹ÚRG˜Ù&÷¿ãIOãó‡x~ˆ¥ÏgädOÉIËYö²VþPK‘›éâÒPKʺ$-$junit/extensions/TestDecorator.class}’ÝnÓ@…ÏæÇN“¤¥$ „6…ù¡XBÜUBA•"Ú*÷Ž» ©-­mࡸ ŠÊÀC!f×+'DQeÙÞ™óùÌŽÿüýõyà€ag–~ìðÏ1"? "çŒGñkî…ÂCa‚14Òš á^òO¡øà¼Š".by†­Õ=)7Qd(^È%©GëJŒ—>åZÝõ%½1Cažs†|·7¶Q†m¡€[6L”ÊÈ¡ÆPù›\N¸8s'sªÝ…ž;»Â—±Nâ÷~ÄÐÝÜT¶K7ò½“$`Ø]ïï„GÉjí8 Bu(ÎD‹äsða0”¡vP$,qŸ”8•ç©ú¨Tó£ÄÒÁa^ŸDYk›'to±K(÷¾&úDê($¸g"n)™å±žâ¦# ìо2nþeᝠ»íYf5éô ¥½ô£$Û¾%T=8X(£€š·Œ·D¨t£D¾ÏORš„Z7 EÜ*2ñu²dˆVglÕÚaÎh¬Ó~sÊ‘65„úTîIÚÁ ¡ys?«„¹Lê㑇G†Äó ÿEìË0UB§ÊÁSÂÂ@dQx˜'„µöl±<<Ãs-¼`˜–Bí§ç‰‡ÎxžÏ>þüó—cÿþóãÊxˆ>aó,=”—ZFIGÉðH&úPêtâ‚ÂõéÇJèX¹(*OÖì6zãLþA‰sy«ÏV=Ú=&8ûñ©¬b – +ã ’¯Òó©ŽÄI( qì‹ðX¨ÀÌó¤£? ¡=žotdTvÑ Œz‹œ,æ›ß¿î¡‰ÓÂ)]¬ªìøµŠµôµ<%<™SÚ²ùS<{â6=¬ã&_“²ôY- ]hBØZÈ%,%R¿e]¹gªæ=»ôåD›Zšg⋆"ú8œ¦]t ËZ u_ðEx‡qª|ù<07\›–ï‘ÙÊ¿þ"ФÚE’È;(ñƒ1Ÿ2ï‡{—g{œ/ñXé¾ãÊWŽJð¸÷lö+k¸ÊQ+S¡Ê9ب†fVQÏYï˜]æ±þÍ÷†×z9è?ø†ö [³‚UŽ×¸_·è[Ù¦)ºŽ-té1t›WñÜæñNnÿ®=nÀL›á+6ѱØj¶˜cÜûD·QÂ}Û÷°k Ä—dý6þPK`V‘è PKʺ$-junit/framework/Assert.class—[xTÕÇ×&—™&C(á’$WŒ Òr1˜Ìd4q С`ÒÒö$9 “98 Z«B[¥Š—ZÀˆZP*J/B­ÉT¼´ÚB¥íEÛ~_ûÒ>µO½<µýú_{ŸœLNöˆ_ó0{fuþë·Ö¾­\þï«oP­¢?Z°;›ŒgZ‡R戵ßNíimO§­TÆGBÐÜÝæ>³5a&‡[7÷ï¶`-Tº1Ž7Ú54nT²­•P©AÅä4'OZ=Ù‘~+µÍìOX‚*£ö€™Øn¦âüÛ1gvÅÓ‚Fõ¦ü¶-•…û‚†èM,“Š'‡7ôÉøCf~¿‚æðû4[áDÌDùV+ûbA+ô @(2k°3•²S>ZÊ5Ë2ªPZwd¡&h>ê-¾ÆÂù—ZŽÈ´ L:ôh]Í3³RP9—ªÇv¨ê8‡FA~ëÀ^ø[ƒÓ‹ã¨ ˆ9Á;‚ê5At\Z®Ä[¯˜]A g7×kõу®ãlj½uÙ#{±ÆÒªðÙ”å£¸è« ZK÷°HTf_Íìë±<5ï„ÃaZØÎbMûèF,Úxº+9Ä;„×xC˜g`ÝdPµ+Ãvf ±!,¨bJä63³ËGì+³?­\ú…º º™º±(á^2h%2&æ£AB0éF&ݬ'D"L:gêA$a›ØÆŸdýˆbÛfPŒ>¥ ’mnW†ô1Á§AáÈR”#oåÈŸT¥‰ÜÝÍó²‹Úƒ²´„,ÚÑ¡DÓ,z—^4bÑySöÐ.3…½cáø"+‡”ò½ÝC÷A9ÄÊ¡R¾›•¿¬WŽÅ<3Ûeó1ý«Æ”êW :LB5ƪ±˜R½ŸUÑ«vuy*Ú•ÌXÃLû5ÖíRº_7èq: Ý.ÖíêRº±îNu–á\éÉ&¼'qÞAu…í—wtœ §Yû¬6[ZÝ»€#è”zþ¬kŽáÀíoü+@ßTçÏó:­¾½ªÞðóÊý[êžøv€Î*÷ï "?ãÒCÝ‘â}wÊ>3‘µ6 Z©ËzfÂú>½ÂظA/óM jüô>`÷îµ’8~[t÷Ø “B€Úz…^G.[=4¿AùMú!ûþ>yÜ×$íLMðÓÛ¸‡ìÔˆ™‘×À×…¯ßè§‹¸‚IæÁý”¾ƒ©i«Ùo¦9+ý i·ùéH[EÔýÿÞ€ºDߥ÷x…õ1™‡ýäèÏf˜… ïÃ!fgSV$Î-Élus_Ã’T …bâ¿zŒhoÓ_×aÄÒ ’¦ *;/³ÈÀ'$š ×> ŸÒ c9Æ2î#NŒì[Vý$ùšr4oJ¤]Ñ<ˆÌÇÚ J¡Ê– ¤)ƒ¥ ,¹Ð‘¼>®T,ÊÑ"/T50çA•JVªv¡"ðdߊ¦ê1ò¡âbÒr$S—GUáRU¸TÕzª%^­FP5i©Ð²¹µ.’ÏÊ.в^Ô»öMW¤T>h͘, LNV£|‚yÓê¬n@×JUat,Îk6âòL,i¾Dþ–KT|¾ù"š[Æ©~ ?šš[rÔ4%·ñˆ6bÊn„L(6!™›Pôv)_£ÄÜb-¡fj‘dKЄ·@…ƒ_ãßoò‰¦æ]륾ÁnÉ›Ÿ#ùm•”e±Õn&%2xíŒL®çL.ÐÚ^d3AŸ˜ªì¼Bt²éÔf0omk^&µn&µ”™Ô"xÐÉd6“ ÞLv “Û=™ÝL‚N&±Sð–Û§>GcTSßx|ŒÖ7] ¶Þú êä±#&æ ÕÕ7çèÖ…%OäµL «ÎÂjM²p±ÞêŸD F ×åh;êP·âè­C’±Þº êåqFY‡åu+†rô™«©2Ìðð–a"ìG  £Ø\wRˆîÊ+CØ-C´;e Ý)ià݉\˜ö³m7Þãìü,9ú¼· ÷Áë`^üR—ä·UN¿ÔUKËttyíð2 "­Þe4Äc-FÍ–y؇ó‚Ý4‚7,ƒnØßå®_UjŸXZ“£Ý^Ù‡Áðˆgý»ëwØ!Þã«ÈÄ#½Õd󸣆ø($®r‰«œ {gì¸EÕ9JyeO€ø)q•K\å츴†8ËÄxñ ñ³ |® ñ¨K<êß©%þ‚Wö¿è!u‰Gâ»5Ä÷0ñAA|PCüÏ$>ärˆ¿¤%þŠWö{ˆ¹Ä‡âû5㙸!Aü†ø5¾^øˆK|Ä!~XKü¨Wö-¿í!>âqˆÓ?ÎÄÇxñ1 ñ; ¼\ø¸K|Ü!~BKü¤Wö]¿ç!>î—Ä'°Ò½}º­oxµÞG>LëCNÊû”žžÑáöô£;*ÒtGÄÉù§ÝÑIçf>¥§zΫõgPýEKuJGu©0Õ_Aõ·+Pv;ŸNçSÞÜòüd§sfJ²Rž‡Ü?€ôOÀý+ovË]ér·Ã)w;œÓ:œ½Äÿ†ô®Ðáœu‰·À‡ƒLÌýôw<ý´àöïˆYy¨†‹j¸¨†‹z¶êKTáÇô•}(ªÁÿY:bû±5•ç£M©ê½Ü à‰ ÊU¾:NoŒÓ[Q¶5;¶+Û´ÖUvg"@E¢PT-æÐj17a“Z.ðŸÈ6Êà††§`—Wyåùž =l[åØ.ÁÖ¨‚ Z@!QU°uhq[‡9}í’´Z .iÔYІ\„¿žÙÀ‹E˜Ôê8©~þ¯ÐQ>êÔ ý#Öà·“5øÀSƒsÓ7†XŠ,CjP€Ú¼äÛ]°v¬ÝM¾ÍI^Ðï¤ÞïÿPKÚ!5#K  PKʺ$-*junit/framework/AssertionFailedError.classOMOÂ@}C …‚ (&MŒŒöàCbŒœ/˜ÞXëb?’m«¿Ë‰€?Ê8[š˜¨÷0of÷}Ì~|¾½ÃÂ9„“u‘¨Ü{Ð"–/©~ò®³Lê\¥ÉL¨H®nµNµ"ôÖâYx‘HB¯º´+Åò)ÁŽ‚}“®du4\Øh²ÈW‰¼+â…Ô÷bIBßO—" „Vf®.íüQe„Sÿ?ÛLƒ¡ÿ½Í<×* '£ÀwMpàÄ2ËDXþ¢ÜyZ襜)“~ôWÊ…Qá5ö3§2ÿâêðtÉHŒõñ­×òÙåê2M–´Ð殳%1î0ƒne0e¦á6Ægìþth—ãp¸eU¦ÛC¿ ß/5_PKGƒœÍPKʺ$-'junit/framework/ComparisonFailure.classSÍOGÿ½°Ù1˜â°Î'¡¶›’”œ )„JDH•©‹=¶ì]´^'½UŠø*µçT¡‘*UJ¤Æ Tê±­zë¹·ª=öÜ[é›õXm3óÞoÞ×¼÷›_þyõÂÇ —6¶åeJ®Yãw33çÔ¶Lת;ö‚iU.WÁ†NšÍÖëÜõ¬–/λ®ãª3t–æ?Ýâ"KæC3S5írfÕs-»|‹A-ͼ†YeP¦- šc˜Jœ6|$¹Æ Í9EÎm"¹¦£g4HÐuÈP:B—µ%õ0t/Y6¿×¨­s÷¾¹^å¢d§`VרB@É«Xu†+KÿÛ,ñ¾¯×Í2¹uð£N(fðf­Ì½åCƒ¾D²]‡z±û×y$ŠP1¨#†s ÄúÛÏCÅÊUrÜšé1,þw[WÖ7¨º6H›¢t\Âe q…¡çä­Š«”µÊí²Wa'’yo!¡aI†®cóeÓ«¨!›še3ȉ|^ØŽ!­a R¨˜î,•.%òÉ9ocBD¹F´ª7Öë~6z¼ðkWã;˜æ7DNÜÞi”Jœ:EÉÓétniÈB“ÙÚâ6h´ƒNA­8”+‡Û"»4fÏiÝé¸#”űà¡Ymð•Ãpâ5;<QýûT¡_ËÓ²hmÐÚ$ê¬: ·À,AÉþSÔK‹4¦Ñ´‡ã}I N*´k¤»žÔÈÞH¾Dwjì%ξð-#´Güû^ŠÒGQt£Ÿ4 Õò#4 øR?Åg¾ô&I!_ )L(Q¶•14J~*ÀSß¡ûGhtœý ½©=œˆP÷1ô\ÈM¤„JÇ>ƧÃ3»0l4q]àâü Ê.Îl‡˜1øôàÏÀI*æ?©8)íâ¢ÀãWT:tëÛ–¶ÃQÉxŠŽ¸±sðm }á’U„CVÞÅ—~Þ¸ôI7[¨•Zšl ~1ã ’ß#ûQdz31¥‰Ù&ÞË*Ç@rü¨ÈÄÄ}LÙÇ]2‰LzE¥£òmä6²èWLøÐó£YÙ¤ýºè‡žÇeŒc¸Jbwé/~@ò*’x@Ó«`›ôÝ>£÷˜ä/Èò ®á®ã[LânàgÜį˜ÂDæ¿1Ã$äØ9Üf â{ŽX.xð1q‰¦ð`œîóX¤YO°Ê·H•=À_X")L9Ç2I¾!MpC¦éEÌQ(÷çÄpÏÝÊ¿PKÞ×Qd¶­PKʺ$-!junit/framework/Protectable.classMM;‚@}Š&–TvZèžB[M4öËfUY².âÙ,<€‡2¡ÐI&ó^æ}ÞŸç >’¼.3'ŽV^ucìEl­qZ9™:ƹ¼KQÈò$6iΟ>!ª:ÁŸÍ„xõPºr™)o„Éϲ?[ÓtY}VíLm•^g…æà¿¦eë§ð  =„à"fßoÌØÃð PKdî?/š¿PKʺ$-junit/framework/Test.class;õo×>f]nF‘¬Ò¼Ìý´¢ÄÜÔòü¢lýÔâvFF¬Ä²DýœÄ¼t}ÿ¤¬Ôd (3#_r~i^ H‘sbqj1#³†¦',*Ícd×ðÁf\PjqiN‰µf#Wp~iQrª[fN*#'HRd ›" 0±02°2°10iv P!Hœ PK(gØõ˜¸PKʺ$-junit/framework/TestCase.class•VëSUÿÝHX–Ré›HQ1<Úh­J¥Z,(-ú°ê6$°dq³´¶µµ¾Z£Ž~訣Ž3TÇíŒM«öƒ~òrüÝÝe IhÇa²»÷Üs~çœß=ç\þù÷·?QøT`ód.“¶cIK›ÖçLk*6¬gí-«‡ 6ïÈfuË¡B`}9Ë**“” ÔÇ'µY-fh™‰Øm¥3]U{Ó4먈¶{Ìq]E5A¨*BW#€5uñtFÈMéÖ°6f8€fB3F4+-מ0h§ÒY†øj™Ðé†hi(Ž÷Œèš„™ËØKúY'¶>5aéš­׳9Ãhж•õáîÓKÃê»!4(Ø •ÐV.£b3¶(̲I 9z?жˆHÝíäÎòBÙvÿ@Ëc:d¸ˆÊhZBŒæ f‘åð|BŸ±Óf†ù¯[fk8e™s’éÚy´YÝ>1£¢SžW;\ ®"æÊÛºf2ç˜è.Wø¤@­æÔ΀iä £èLŽŽMê 7ݧð´,…gÖ‡àºÝcŒaÊñua—Š.ìUðžgm†°O šöýº2Çö—©‹3%…N,=i0’˜‹@opPÁ~ôÈf)‚:˜K&u+„à ÚÕ´„ñ‚¬öõ zÁ«Òffô #é,W¡%"‘^_B\"ô Ô´D2¦I²‚ÇÃ8*É7]e¶h´‚ÆÇp\±þ“ZÚPqBÆĈ«dÂI6„¤ÎO'Óº•Uq›œÂYù¥fž^gS:;˜3Ò ºŒöµVñ*^Sð 46uK$›2sÆxdLÌ8ZaP±*™5§X™{ÊÊ™2µS*R¡#)C$k“iÃèË ÙZbjØÒÞ´‚¿Ði–Ƥ‚L t”fÖǸšì”aÍ"#~ã„0Ít()’«0%^3l÷e¼s(—H¹ô`X‘e¥>ÃÐ'4ã@"¡g³ZÕì¼¥BnX½DsÝ€cêí(²j²Ôo‰?(ή£¤ ü·88ˆ&ï d=pqEÇ»ÕÂ%jÎjFN?šh-73Ê•ø;¸¢à2ÞeòÑ0Þ—JxÑÆUâe]ÏzCfÎJè½iy‘Ô.ÍÈ0¸!Á:ä/ ¯%µüæUÅg W{)|+íwPÛ.n£îW¬ås /X`Çhqq¥ºÚ¨Ç:¾%Òz©—V©£ Ò‘FiqÒAÚèj{Hòkãc‚ÜÙäav:k¢ñ±ªÉÙ‚hFP^Ižå./¯ð]l=uÛnÙëöa?›Fßþˆ—ÚžGs¼½#–Ž›EùdPÉ®P0SêaU’í‡ñˆ?/?µÛC­ê ìcËü(Žt–VsXU>7U>VÔÑms²eg;¨:¿d<ÍÝÉß ¨î¿šÎ{7Pµ%NÙîŸÄ-ªiPã»m 0pžÒ‹”^"}—±¥Ü„+ô4ûôÆJ‹Fº–ÎϵÿŠºE<+¤·n¹yŠ/ ¹ÿ.zOÕ¹ƒ¥4úA>ò^Ä(y}yc×ÑT¢4¾¬Ô^ñöç‘]ÀÆþÎ<ŒQ>^¿ç}޻Ūyr[å<Ÿà_Æy[Èy‰v£ŽÏ«<“kÔüŒšŸ3ù/xO‰}øŠÚשÿ5RøÓø––ßë{Ì㼉2vót˜¦GF5ufyZ[ü/doÐSŠôÌS?@Û¿Î9Ý×¹‚´óýNµñ·\nYþ\À»ðyßõ n–ò¾ôjplɽVÉ8ÏêíE¼GÚë? ßòèòøPÒÍ¥¿¸on ·úè|ô˜×±•ò‹/0®ô?òGˆßEãÃm¿hó÷*í±4:>vl>ùPKÛæ[  PKʺ$-!junit/framework/TestFailure.class}TkOA=C -e¡P ”Wå¥öE«ˆ¢€( øZ ¿mË´,”.ÙnÅÄ¿äM¤$’˜øÕe¼3»”R¿ÌÌνçœ{ÏÌìï??~ƒil3 U˺•)˜Ú ?3ÌãL–W¬uM/UMîcè>Ò>j™’V.f¶rG`HÅÔæÃ[ø—Ò†/(ø`˜`h™ócª‰À)à¿÷Á}†^—æ|ˆ“eEnmðJE+rIŒ@JÁ°XE‘¦âs’Ü»M‡¡Õ2µ<SŸÌÐ '¾gê–ðáQ³Â‡Þ«ð6E­«è 8mQÈÞ]°oÎÓæðLACº/¤<ÐKËgmÍÈ5¶V<Ç’hçC;u¹âô1ärŠuÇ–±"Š]eP* =ÈåÒ›x&gNF¿kôäøÕ t|¦rôŠsiå+ùÀ0Õ|/—+n ý¬×LÓ ¯T:°£jæùº.ÞEwÃýO yŒ“O^@ŽôàhåÏfúy¥;èkŸ2<4èJ$ÏÑH#ôMB{i Iš>û Fè t§$ŒvÀ\ “« µÐzƒŽL†fkM|G÷×:¹ ‘„Šà2qØ.àP3xÂL÷Ö—©Îšg.Ý¿À5é,D%5L†îÖÄ5LÓª† {Iš¯•ºd¯1ê*N?ç„T Û¬Ž¢Ÿvà¡,t¦®ý™p½ÉKÌ’äcõsûÉ Ìo$jXLÕð’t^mNß S ?Òè¡Þ‰8JÔB4aÓÕE‡±†uë¡cz7Ä%´(ÄC»oë…Ì8ú….5Úlâlƒ‰þº‰ïðÞ ÿ _šðs®øM™µõPK€4Ò»1ÖPKʺ$-"junit/framework/TestListener.classu±nÂ@ †C R#K·v(yÔ¦HŠØâ¶IÓ;ÉwwëÐèCUÜ…¡þ-Ëßoûç÷ëmÒ5[—Ö±f‰A„Q©ö*­”~KŸ·%ï\Œ6¡§ò|)b„0»Ï.™Ì³?pý.æ ¶Ï6„ij+UTµ0aq•>ë>YËâ £ʧå]Ì:arÅ+Lõ­SâNsÉ‹©eÇ+ïCÿÿxnîÞ¡…!¢ˆÐA×~zö‘4z„Ï-ÜPK©bÔVPKʺ$-"junit/framework/TestResult$1.classuP[/AþN[¶­¥U÷û%¨P^DBò}©ÊžCbƒ‡L÷Å·`¦f›9 ¾Yôql³·Íqœ)¾ W\}ÂàCŒ)Ä(óÓˆy†Ø³Ùšì0FØFÑψ1ö b"æÛbÏ ÒÅG >cö7[“µ\ÿ`KwÙ˜‹ßy,ÄXŠÑ@áPKcÌ#_„ŠPKʺ$- junit/framework/TestResult.classVkSW~6Š4hp©X´¨k/ˆ€@+¨EÛêJ6$º›¨µV«­µ{ÓV§~h¿t†/¶Sg*Œu¦:õ[JûÚ>g÷°‰qa€™sNÎyÏû>ïó^Îþõïï QÜQžÌ¥“ÙŽ¸¡Méç2Æ™ŽQÝÌÖÍ\*냢 jR;«u¤´ôDÇÁÓ“ú8wK”Çûµd*g覂à %’Ë&SG)1ºøâ}†‘1xˆ&ͬžÖÅòøá\ZXàZÙ§ 4>’ÍLs}\AYw’Hv((iYT·7ÓU,Ce^TÍ#)0ãC0€jT©(EY9¥§³ V¶ G†úT¬GDÒª r<•Iëä¯hYÿ|¨T¦A{€¤tÐÝÖNÙÚgdûÒ¹)ÝвÉLš6b“0ñ A¸ŠøÐ© "­ŸÏ:hÓ…pU¼Š­Ø‚×Ȱ óØ} ìKh®@7¶3v ÍÊzŸƒ–s\ÅNìÚzDØx[AÈ=L7A kHxư×,à»; vÑniê†Ð ®êv®XÑÚ‡ý© Ö-í‰%‚yb4¹C˜°RÌŸrÄ—fÒúT欞7°ÌÞX<ïHþFERaM[y§â¶Š7Ø ôtlÔŠHíŒ .Žã„àâM’¬ _{39a±e£ðšÉ Ôy '…NÝB—ýEÛáâþ¸Ó˜JŒ\ZAƒ»É^Í´ °ÜÌjFVl©Hà„(…äùh|óFΈºœ …)" CF&K*ô˜‚-KÍ yG¶L ëïˆ,„ÆÍ,eÓlXT#© .ÉÊs]¦@Ò‡ó Ñ´½¡â*+ð.Þ(ˆ×¼”Üôáò|G˜/*]‹íѵl‡+ ª]ê͇j+¾$ªÍLdr©˜ýF¬p£Ã‡ë¢Ó /çÙ1U|Š“øŸ‰|JŠŒ´Yðš–¢eç4s$7>®›f<—RIåÁ×*Þ¶W7iy$“3Æõþ¤x–çƒß. 2äûÒ¬ŽÞ”FL4ñŽà3äOW^ñY³_Î|„8{ÄÄ9E¼l—ó—ÁÇXá¼!2‡"P=6‡Ê/Wå—áHÉÔ‹¡ñ¾¥ñEŽ´„h§†W!ŒZ¬åA:PÕ%µ˜.`=ì°&ëYÚ¨¤íÎZ¬Ÿs¼î¨K‰º¾Øå\äR']øjÉ˿Д}#“⢂Ô GZ£³xˆ£í—î[€Êùÿ5Wãª5‡ð‘´¶†„¹w‰™}™WèÒUK¢×Ѐë’Vkmt\kt ·Qº ÄK¸„÷=\]ãªÆÚë·Šùcìrq¼±Øñ®Ž'œ:ùY:ÞÚø\ÁöÈØðŸ‘12XŠ­:úteѧó+-(¢§a±ˆø}Ç…67ÙÞoñä[¬äÜ€ÛhÁ~=ß&þï šXÃEä‡mì¡¢¬•e&üþÒyz6óD¸Uñ>ó ØçºûcóeN¢å0×-™ FfñÍ]¨œnÝE©÷^I1?h JMú$Æïè‹°ªð“JüÿPKäÊ×O|¤PKʺ$-!junit/framework/TestSuite$1.class}MK1†ßi«ÛvW«õ«Z?.µ~T/^A ‚P¼´ôk¬Ñm’ÝŠ?KPþ”8YÅC›ÙIÞyÞ™¼¼¾!‹¬ª7‰Vqãʈ¼‹Ìm£#mÜNT,kûˆPùKÐVzÈü¡ki­èKB¹u#†¢ Ýo´c£tÿPhßëøZƪG?R ;&¬oü–þ>ÙìrÍè’Ñslväá‘C` ãd0I(µ”–çÉàBšŽ¸ÓÆ¢ž»Â(—æâke +­ž€û÷kBGú~%và™D»{Bvõ7?Z|b­4±‡6¸* °èZ¬`‰PlG‰éÉSåì'lvÝd„àLkiš¡`‚ÅÏ’ÀÍ»Ñ8zp+Ã_΋ü×ä<Ëѯo?c¢¾õ„ÒC*šâ½èÄ4Æå„iÎçÓbŸ3)ÊÇ,ƒÍß}8’³¨?¢ô‚ê(̓Gù”|é¾i,§û VS-¥^@ùPK¯$ŠxmPKʺ$-junit/framework/TestSuite.classY xTÕ=7™É ð…$„eØ'“ PY"È¢Ñ$¢A تÃä… 3qæ ‹U°Ô¶¶*µÕVƒ]\[±²HRqi+.]´Új7kk[±«ÚÅVzþûÞlÉúùñÞ›{ÿ{îÏ¿ÞøÜC!jÕb…òÉhجïˆ7ñMõ«Œ„Ùš ›† JaäÆà–`}$ÝPÑúFÈt¡P¡$ß"œ Eò™P(nÒ+“f8R¿šëbñ ÎŽ®HOjØV3Žnà¤+ &Sg*ŒÊš^*ƒœÒº=jvf8”–œÅ톩HƒB¡¿jµ‚ci¬ÝðbFzà@qJý,%\(¡˜¿±jµˆ•yPŠ1^¸à‚”+Œh G–äæõF|Up}Dë #«ƒñ°ü¶fg˜‡¬l”=ª<Ý?àÏ-j— ´ôóy¨Õ$8a˜s¥þ|^LÁT‘¦à&KƒZFõšýÀ]¨"ä†d‰¿j ¦Õ¨ñ €Z/†À#ìÔ“ .’.Ef<)„*ÌΣ}ÖHÜèˆúú¬5DŸ…Ù¢ï eý÷>7ÙÑaÐPgѼÎçÆ\aƒ'œƒ³9ìê2¢í 5ùÈ0dáqÏX(‹|Á„/óu%×GÂ!_(£›OŸ/˜0üÖjŸpXåËž¨rãá9fIx±D¨šƒsÉêÖ`<Ê1…@~Ýò¸ 5[†åÂÆ ÛÛeéÏ/-Ö>"‚—i޵‡;ÂF<¡Ã Ñ‹&4‹éZ*Ú!%íÂJ"œX©)°‚b— Õƒ‹±Ja¸/,™6In¬–h)¶¼`™ÁŒí͆ÙkçÎãýU—屺5Ï#¶aèt™Â0ûˆÖ”Âbÿàë&‘¼‘òa\.|\ApêÖšì2â!+Fç8·µÂ‹ Ö‹2!/†Â+¾m¤rZ]ší:ÑÑ šÒÕ‹[¡2í4—Âc£àoR˜™l‰ééeFÇŠX2Ú¾<—t´™:fdVuÆc[%ŸSðˆqD"¸Ií*q².Ä=ˆJŒ '–$á Q‘^mΟFhÑ$¶ˆ2[iâDøj"m÷(ÅÕ´dKÌgJ¾öuˆJ¾p”±vÂÄl­[“¡NËË·…Œ.3‹º°CÁ×o³–˜i,#u‚"m“šNƒÇdéIˆÕìÄå” ãÛµ9å^•§p.næ¿F‚е–GŒÍFÔì—*­â¥åÓ¸QŽ“dqieùÁe{ªNè,A"nk8v0m\øœ·²¶ÂͬbÃÑÄ ªÐ4ŸÇD•Ûi‰T fGÆøSD†,ïÆqû;©i8‘YèÅ—¬‰/3ȰϢ‘ñ‘ çù´ô]d,7‚¦a¥œÿWÁ,‰Ýƒ{eÓûh :cÅ©ì5þ”åÁ…ØÐ÷We“¥x{—¸CInŽIEÛ×ñ _Ã^…¡Qck#q‚Ñí5ÃYÚyñ <,ûÄ®y'Yß…”;ai0*i1¬72äO‘/D1¡õBÏïFOa¤\|•]-ª²YN|žÂEÅŽàQáô(9eÕyŒ´¦cF‚5«nÉÆ+Td¶1º…ŒÖ!'«Yñù¤]ÒsÇÆädÍŒŽ^| ßöà)|‡õɦ! 1Eå2p<';4¦‰"xÖîÏæJE"Ɔ`d‰†Ë’zžf e÷OÓ\ä¶—¶&7N# ÕæÁ”¿þ y°@*‹È„c¶Y×Ä™Mèä/yð²”Óѩ镜5S³?–ÚÕ”š²Fí®ðU^ÁOØ×uÉ‚V3Ú´*›Y‘¦—ý ?—òñ Ù”Š’™×ÆL&‰,=uzÌ£?劶Ú¥yweb=0S$yÝ´.å)ÿÒ•}y4¹Ùˆk†éaoâ÷âò l^ÞÒ¾ÍLgúÜ6ÕoãOCqöâwhŠ"ü•œ±ñkŽÅ {­Õ21•þïˆì»ÔQ+ÍDCæÌ´q^ ·ˆÛw:Q¡Î"ÊÿzLN»|†`;}¿üN²ˆÓnpÐ å~5EêN‹<öZ}Ð%†™ŒG%wzU‘t<·*—»s.u–¦.å‘ lãfbMØì䞱Ϋ¼j˜G UÃy°ÌüêX¸Ý¥FR·Um+—{U19Q£ÔhºˆqU2IxU©T:‡*ã6]©¬ÎSxâii‰x’¹gbþ¾÷#‘Œ˜úºT1ø¼K“ƒtÆ’‘öV3ÖåUðŽGWÙLÞªsg ÒZŸzc¯š¤&Ó5Õž+®GÆjWU¨J:žšÁâúKt_ß8H e‡aXn¹D·/ù¼ZU+ö¥Š †3m7¶¥úËkÝ6)Ÿ%Tªô=«Vîà ûÊAï«Sg¹Ô7–IÙhúü—Îêlš«æëFM·©$¿5–Œ‡Œa¹&OÃ× SKc4jwyF“¨™ƒ.]Äg\¾yÝäÛ-­9ç†ú×ð¬_eüâŸÏQüµLcÅ>ŒEiÛHOÆBÅ~WÉçpò9’>®™qüåµVa<&ð-ˆmÄ‹¹J䇪û09PÓ‹éý¡êàD=©¡|–¸ %_3lø¡ðC ð> ^õR"Πp ºu‡0³ú0Î\Óƒ©ÍœÓV<¯óe¦ Å‹ùèÅÒÃ8¯îçèE‡qéL(¹&W²Y6êÃÚ–ȉ>4ßQ8ÇÙƒQrG©sv-OzåõNUê,w»ûäÛ”ho>€Ž¶ã·¦¸ó0"mÑуG]wE/}0§Ð¶='AE/>²ã-%®Í(‘Ù_þ¼BƒOÂN<€‡ð>jó¹ŽææÙ¦9›R (µ“±ˆëœËgŸ›°¬àíçŽ q ßw¢wqü8.‹X‰·hF±Íùt,r¶Í Û6“¹ß.|ŒZD±×s¬€¸[ˆç¦5wR‡Oà“Ôj5ºŸ¢½Å†SmY£]“׆YîRLA`µ}¼5<ìZ­V™µ<­Öí(’ày¹·7YB‘" öæ ¬GO\N]¯È‚’†‚ÝøŒ†»%åwXnë<Œú´‰kkÃäB$¢# rXr>«‰+ë¶ ù!|7Q»Ûæ;jʽ¸£Žý9_܃éòþJwÊ3î¶<ã¶ÏЋnÔ–;ãþ:„,Iý&F|c±™Šb>bt”«ÈQœÐŸié’Ö¸ _EÃ&mÖý%æ/$æ ͸ƒTñæb‡æ1"Æ«F`s|-é° À}ôÿ‡ŽíÁ„šÂÇÀ3ìo©}»Ñ]ûò˜ô`wƒSm…Õ­2݃ó°×"¢¡ø0rðoÊch[î‰\¹^<=¨è3§ƒ¤VEû´7ºùßNL£'®Åsú}-)ïñ]›û2\CÉkÉÐÎîB-ÃeCeÙ<ŸÁ±–a±Ž÷éëp#goâê›Ú»ñNìÑÅôG.5ãÐ_–;Éÿ÷ð}ù{%¯TÖ×®p,äÅÄø¿.å?ëë%®±¾Ö1‹ï :0«øïE~=¤Ç~È/ܘlß4(-i¹ò(^fâûQÓQ¼"^ÿÓfɯ‘«_î릷ó¸wpq7OVf¯Äëø•&n4~ßè <ø-ÞЙݥ½åõº þÂ…t—?ÒÊjŽà/ ¤¾¥²öþ¦påB½§°ç䛕{ÓûWèŠpÝKäûP‚ûéÆ÷ò`=Z€…k»vÇÿAòYxY´váŸ)±c¾ïY˜Í‘QRJãN­Û švfZzd ­ðÞ·rû­Üþ~¿ÜÞÚÄD¦Ô¾æ; _DÎóW0sûYÿꈛÍÝÃÝÏѬ‹‡²È<Ûü~ŒTªP'n²k1vâÊìD1‚›Òw/í†Ó±·0ÃO‘ã#Y¸eé0/³Ã¼@þîaãÞÄ_Èu’nš êláÃ=ßQË€­¨­†ôªÝYî8 JzÕ˜þûYgzŒÇhÇ™zžÈJ1ué½ëì½tF«Ò{0UUâz#1A•óì´4‚iÍ 5ví!ã©—¯E´sÆWµšr”×3)q‚®fÇé‰Ï0@Ÿ¥žÏQ¯çYÍŽ£š¡”ñ•š´Ž5jšš®uœnûÊ8òiùŠ’¦6Ëâ!îêš#Ê_€þ¥áîýbVT¸Ó;¸íjÃ/½£BU©€»Ø¶±WÊXe¯ªÓ‰(ײ¯dYÖ›ÆõªzíåJÍLÇØl]Õ¸“Ývô÷‘ײš;wº¹ã­2ïzuFMÞÈ»~ ù´Ö/µ×bPœù4aøÚèSge€¬ñ-Òur ÍŽJNI· 6=Ej¶~ýI—f{/‹œ¢49E鎡:­\½­œ“‡›Ùÿdd)â´a<òÿìÅsìFÚ{TÍm ŒVóúÔ‚~Ê™…áU u.P‹ô³A£•š«,þPKáy»+ hPKʺ$-!junit/runner/BaseTestRunner.class•Y |Tõÿý&“Ìd2‹+@@ÉäRùAI8Á€Š/ÉK20™‰óÞpX{h©mñD©ªR•6ŠØÐI4Û=JÕmíîÖÝvw»=í®]·ÛK·{¨ýþþïeæÍdÒe™yÿ÷ÿÿîûÿ|탗.RÕò+L3÷ÅÂA³> ‡õhýZÍÐÛuÃÜ¡^=ÄLû´Z}H ÷Öoíܧw™Êbše¡õDµ~ý`$º¿^°šƒ†©+¼làµ]ßÔ¾aoˆöM[×·®iÙÀTÔœ¤ÕfFƒáÞF¦Ië"aÃÔÂæN-Ó™²XÐÔ½äcò÷l‹ê=zTwéÓ4 =fCõÛ¢‘=ju$Šzz[´C-ºah½z³î5û˜¸ ´{z7C¦m3µ®ýØÛÍäíiŽhÝà劮Pj¬dʪ¬ÚÉä^éÖý4™òsÉEÓüT@…²šÁäë×õ[¼T Ò½º™”ÂUŽW®©ªÉO³¨Ì³™ò›ƒa½5Öß©GÛµÎ.‰ti¡Z4(ïöfÎ %“ŸæÑ¹é ?Yb,€„f_¦(kþnƒEraѨ)[L%•Í™œÕ( {͈%+Ӕʪñø©šjDˆZ¦<XmBWïfššAߪ~ª§+EÝ«DTÅ~ZfîL“ § KÐL²~š$X1œ8“{ÓˆÌSc|˜LÉ´ï¡>º–®`ò„¬¸ðÒ*>ƒ£×0'±6iFŸ)NòÐ:„Ì@ ê-wÚÁJÆñ;Uã·ü´6úh=]zT”¥^BàæGu­Û¡—Ÿ¶H0¸¨g†v@OÑÙ·áP—>`‘Hcò#õM[ÛÚËŒ %ô­1âÃoºÖï¡ÅTC rx̘6„n§ëEÄNaeꙸiÝà£6êðS5 Ü&òÒM’Öf$ ’ÕI,§ ™£i/Ý"ÞрߊÈÍ.±C!³z"P·´y"µ¤¶©Iº0CÐfb (L$‡Óœ<1^&'ï£ý¢Aòî×A*û€U溓>ÿw…tMÚ†Cò}ÚJ¾Ï ÞH‘h“µ.¤ˆ¿™…Hl)0ÄÁQº[HÜ3– ©öôÐ}°(4³›˜Ÿº{?CM§¿6ÖÓ#Mö!ä "_Ž˜å=‘X¸»|ž—>'iˆ0:N@Am`‘ÆTóÈé$ qOÐI¡ðÄH>&k´€\ôË~ú¢ªOÀ#Ê5 å^zJD\~šþú2•zf_ҬΠ͞qVsʇ,!£ê- ðizÆGƒt}#“Ë•ãÈù/ô¯‚ó6* êˆ /lF ˆFD©5ÑÞX¿6 iè{.§¬I»ª GÞ@ ýÖ˜2ÒÙ±\B²þ†~+½àw@Å,¸3¸+wKõx—Þ“ê÷Ÿ(Nßþ‹ÉU‹þH ‹Dµ.Ón—U‡a…÷éáðajë:ŒV¿‡q/ËŠÄ’ÝãÏ6àM>~Îbw.»÷°é-AÃÉrIøò.«_@/{âÛù°ü€l„Â~ÎCgû¡:âNÌ &—‡D·¥#žaë:S¼^ïÑb!³|ÖAkC£Šz¹XÌ*w cWPúoÆëÄn?OåiðOÑ:/— ö ‚¯[?´µg´&?ÏäY‚V¦äê4±Þ”ÉÔ<‡Ëz. »’žòâ FÆ©Ë]ÓD˜ ³SsÈT‘) 2!Wr• à˺:hW% «OJ¸éýÊ+«Roz‰ÖfA€J=Kæ«wòÌ^ Jøy ÝÇWóRÜþc†¾C·ó" C EpÁr¾F4`ÖIa0ž‡WøXݨæ§À£†»µh÷8ðU>^-·ÜY*ây­´ÎðÎ5›a1?¯·¸o€] k´®/"¡{U„Æ&t?7ñŽ*áwÞ<Ü,ù#bÔ $î|^n•þôq ãbäšH'bS8y=â6·Ëf-Å,ÏHÿ%²rñ rßLd G& ^»|óNæ${“o–‹ŒKnôS3’IÙOÞç….t-t”ý°©÷Š5AÐ; E ¨`ú¹‰€†àŸ“„uÖèdw”¬uw÷„Leÿ±Ï1³»"ýuÁÎþºØþ:3 uëõÎXo[l` 5½ÜØGJKÎø9"Sî Àèpõí5¤ª*3ŽËõ”1­­]QÄ ”3}“ÈJ­[c§qt‡µkÍz|ØÇ‡Í9À*t¨E¶T:ˆ)ÞÎÅ@˳rÒšý.ÃÜÌŸà; "ßéç¨ÍG‘†C‡Äg¬4Ý sÎAbjF‰Ði‹0c"0…˜–Z~£/rPé¹C;èç{­4ºoœewèV>àãcra˜6vlQÔ»ÇJ1®µk÷s>>Σ¢[}P>sùùóR¹]|B æá•/ÖÉ£¸Úá1ñe­ú2 >ι øÏ5 Œ f²9â´3iqr6J‘ÔG¾ÈŒ¯j@bü­“*´N3PKž‘Q>ÃéÝ@Ûòò³c7Œ´sUüüœTŽ´cëꊒþÕgã tˆë’Ÿé¼|NÌ­NµƒfÚÙ…Y«Ò_°§Ý:‰€:{B¬³ÆÇ:kˆ¯ôò023huJ?¿huÄ—Tu0á%ùVäk‹Ä¢]ºõ±§8õ+b0pÏÅâ–¡²©„<äÅ:cœ‹òÈ'_åH¾ïL¦|õ, B5ä©ç\ìÓ`LÅÛZàÈ¿i…üû 4Ý}JŠfž§é#4¯çÍr…ëÆßBp,"i SÁc®:•áq^‚Þ ì0ž¾À0͸_ Š$É”…¿“@©ÒZø~ šR¥’­Š6¥5Àê¹ê8ÕÅiQ’O”@‘REdšh‘ÕbºdTG°É-ÆSXe.ÐòtRei¶CžlºFÙP}0³ hJz¢Úó´üUŒÒµôÄð^´ºhmœ6í’åfk9B-xJ0*…éDÁ«€® ™4Ÿ*h^˜0d.µÂ.ÚŠµ¸w»b|+ ëêQjë¡]ô{ËÝ(º9Nƒ”Ûò4åÕ¼ò4å ’¯9'ý>ä<šŽ_*ûjìÖb·Ìëa¬Xûª„Þy€ì¡^åÑ> Úz7Ûì}àY]§þ]éÖ»‚/QTÊ-È„#|V±)«V.@ Lèa#ðr \ó'=<—LŠÙä6ÃfÂÞp‹œ‡Ó©­@¢\ëÓ› æµ©Éê6úˆóvúè8ºÙé®Ý5—A÷cär³|‰‡sY¾)ªç:¨ þqú„ÅÏU~â¬w`•»ƒuâôYâ±Ò½-ƒ´©µ6N6¸KÜ—(§ºÁ¥ãEÓçKÜqz´èqü‰Ó©8=ÉC­ÖáiéKŽn­)ÊËz™ãôlë øŒÒs5Ã44èFhô$åŠ^¶ܵl!|ãëôçÿõ%î¡AZÙmñùK";N¯§òJ?vž WAÊåÓ ü¾­žëè ÚKýø½AÇè ~—ÔóUúkÛöG‘GDÛ`ûíÜH×v`îî.T†hu ÈwÃ{àAñ&ZO7ãm/Vþvz7²‡ ýíø»hÝCûé>œÃÉ)ëixê Î"Ò.!Ö^…¿^§Cô3:Loëmĉø~RÀg ß¿C£B?Ÿ~HK߃Ô%ü7éï#s ÙßãÔ ‰J°÷}ìí¥{éôXE ‹ì¹!ÃAnp/ÃÞ?ÂJ¯#•ߤŠAùŸ©”m×úùœ£Sè­Hœ~™,>9*8RiRBÐIôo šþ~e“ûÞ¤Þïã–¬•ƒtsuÙ¢¢_Çé÷'Yqú‚P¶þ[mù²Ð4i©ìü¯ÚYX}±Ì}Ëi*Tã¹(΄°õŸçœböÆyÒ‘,$À[°*«¾øÄ‡OÖ$em@Ÿ ¸ÁƒxàŠ"º*?€Ry õêAZFÑ*:Žºô0]OÀD'”ñúèQ¥_À’<¡ß>žÌùÐËE}\ jã}!“…Ýwé=[ç•v5Ê ÌLéZV’?ŸvØ/'A?‡¥¯JsyŸ>°iím*­.æ)qžq‚ «±,ól÷-qž7TÔ×êŠÏ€Ïï³¥ ¥|…Õãy~‚‡¦B€¨ÝÚuŠªHwayšæH®²°Žó®FÒs­•r[éŒÏCø h Ï;Ú_=×¹Ýò9Yõ¢£t·£/}[ °Ê6X^ ΋ª_äe.J¸o8´ÉKh“g§†[¾àÛÚT«"ˆÿÎ¥‘ø–C.¶I°\¯mÄ&{à˜)Ÿ£Œ¾Ì+‡Fy5žkÒÕýbê øþ»²Óm²n¹TÛd7Ùdg­áuÒÒ×E#¼ñ$ùÏSÅ ÊvŸÍ:›&ì÷TgÛT}ò?çiêVgÅżi„·lå–Ž@1oæíIA­€û>ýA‚œ‡ü¼C|‚Ó- £=l·æE Jíj6àë·Èd‚^=Ì»FX0̃TÐø¦rÕÞAr·œS¾›ßv$Ö•øm·¹W¨Aò‡xûJÄ?ÔOõsÌ*oòÞN8ÖEWò-¬ám$}“;Õ(:+¦‹lCz-IºÒCä‡É¼j\ …_fãßg6ž%ø¡eæÊšK”]v¶f„ûP˜²Üeg0  SyŸMx6ÌEôk ý«ß"Þ~ˆwó|ýG•(±bÅû)_±šbO**⪹ò¹Ã§Å#ó‹9<·î¤œ-YgÝgí!LJàrÌïcçCÊÃá$v9-—ªðД£lؤï+Ñtá(ǺšGùPGõ0¤%PçWÇù“ÒùOIçáO¥–œK^öQ!çÑ4öÓLÆ|͓˫-²j´#Ïá»øÓ`ZÈÏðgAe&Âë(ß 0 ò=ª5åÊ]Ùsp"6máûù¡q"Žò±ŽÀ0?Ø:ÊÇ;j‡ù‘÷ –dðÉ“”[ƒ®Ï_ÀxÂw4d_úð—¨ÿ 9!ètj j¨’¿Ä_†®õ4-É ;mWkµ•²íU .ÌOÃ]9¤nì¶»–Ù7§éE›“"÷<•œÌT8˜ò½r ·‰¼fÏ–íÞ—éÎŽ¬b>ÓÖá.æ³mÙÅü•¶´Ì¡¶O1Ÿoëðóóm؊㽑¶æ¬k1»ªg¡ÉŽ>.Œ¸x–´Ô_9$X)AÔt×#¯¤b¾ ]„@XL øju -楴0Ëy9 { ]Ç Ô„õ^á˜mÛ•Id2ŸÅ_Smµf¨fŠ,ç—…#_ü#PKõr—@ÜÉ$PKʺ$-)junit/runner/ClassPathTestCollector.classVk{e¾'ÙÍ:MÒ I›RZj[ØcB©4 »$ØlkZ*L6ÓdÚÉn˜™­ˆâë1Q<ÕCմ覭¨×åÀà°ÞÏ;“í&Ù(¹®ì;óÎóÜÏ}?‡wæŸÿyçÚ‘Ãß5ì;[«X^Þ©U*¦“/؆ë7¼¹IÓõ UÛ6Ë^Õ‰@ÓÐ}Ö8oäm£2›?6}–û´kعÆ}WXÃÖ“OŒ?ùLq´ôÈ䣴q Ñ‘²mÑ눆ödꔆP¡:cjè(Kø(ô5ÑNzŽU™ “¶Y™õæ”߸Žnl‹£ DchÃmºŠVÅ,Õæ§MgÒ˜¶ ›(Vˆ}Êp,¹6;F;#„~²ðæ,WÃâûÈȰ½ìßÈ>Ýú“©¢â\ó,;?Z©Í›ŽáYÕ M»ä/n`PQìY«ðy×3ç#Ø«aˬéwª ¦ã=¯á®dq}†S·tìÃþ8>€TгlÓ¯s ©ÍqÝG wΓÄên$ãLeJCO ƒ2, i›ófÅsuöÐî8²Ð+¯fJR¾!Sî˜nÍö4ô¶Œ¬¡Ó]°-¯p æÈWΧüZè8ˆû…ó!r^+ÿDµ*ÅYÕßìµ™þpX°†ØÉñÔ)鑸àjÉš@"øP‰z]=²ªy ÁQªlÙ <Ì"WÌ Þ¨ŸC ·%›KêÏyŒá‘-g¦·U±Çâ(àq ˆbBz‡Y3%]ÃWÀix#FËð1—|„;g¸UÇ ÈºjòžÒq“Bî aÇOqbc†9휴훎žÿËÐWù´¨ü(ÈrÅNÇÇ1)[ÏP²åª¹”žÙ$Qdk`Zô”5lSMZ2æÍ1§:2;m8Cm 5ïVâšË±q§eÍæ`I«œeïØ–+­žL=Ýj^mÌ‹‚І¾õOÖΜ1ÙY "ç »f;³nZ0h;påHôâxNc«k.LxÕ)Ì RÐñ \ˆ16—caÁ¬Ìh¸=Y؈æ!æ'ñ)û´†ìû:š_ÇÏòÄðªþ³õíÞ þ9|^l_^=Hdry$¬í RåFŠ(À<´}ÛX£¶Ü.W+žß°=- ÀDX2¸<õ;å@h¤)Šoð,¿Õ±¾ÃdõœY±^²|SÃÝ-²°Yï~+Ž‹ø6ÉÉÈ+ß©ñ= qcf¦qô¶ª1AqI¸þ€âƒiT8<|(spo¾!€×Þ*[¶¸©”a9Ç+3îiË›ÓñS‘.üŒMgUfÌ Òtrþñ-û \–G¿ä†ÌZ¿ÞdÒ”í±ý­0ªM»AÉû’ãã-‹þ{,‰ùUFuÌÛ(›b\hÑŒ4~ ã?²xQ,3{®g8^ àm_À;Âm³`‹?ÓŸmÑæádµæ”Mi'æªõ«~@ B{yB„À‘áÿùÜão qîlá]Ž«üÅ[ëèy ½WyÓ†>þÊñ~­Dщíj fÕõ>®âN/cçz·ãö(7Ý7ÂíØ¥îÀîà4-Û¹nKÜywÓ™:ÒÙ:òK °NeÐGÛ!)€wúN`¡îÁ½„Ôd¬ÚxÍÏ H‰Öb¯§ÿƒu Od—Ö‘ÝÅõŽ&l=À–+[ì|lÈ«6À~"C\® ;Õ=³Œ#ŒñáÒeìL¯ 0•{üp|]Ë(&JTv‚;ür¼tó_MvR°ò)ÔÅo¢ö#Åu§´£Áé ÷¤â”8uÑr O)î| úì´(óáŽ-T2Ùe|l(ÔªãÙEìJ“ÌÌ"zd çúÃýá:ξ*Õ!Þý‡Úu\F2YÁsSÙë¨-ãü5¼PÇgúýƒu¼TÇrõr‡ÖÛѾñæÍ÷nµÁ sêØB–=È}–úr¼Êóê^òd&ïÃêy–ë9RjO¨&µjm|_R-dãËôkSW¢»Ø¾Â§!"ÇðU> sÿ0¾†Wx5ÌÚ½J´•³ûƒš-Ò:Ì5¿‚‡¦–ñõ‰Äkl¾Ò .NerËøÎPè2ô¬¤áûu¼.ë.ÝüwS¹v«¤&ðÛsý!ÕY‚Ê;¢DôC4Däƒ6в1Y¼6zîŹ×Nÿ>¼‰Ÿ¨Vâ+? Y¦HÝ“‘Áüù"¶gº÷×ñ«×Ñ™Iü¦Žß½pèJû•­>²À<<Ìeè©Utú|¨=*“<å+"øRÐË©L;{¸çzgê¸6‘eÅ»ꨗr‰ëu¬,"–cNn,å–Ö…~Œšçˆ©l‚:KMÍ›j„N¡;¹óUÎåwU&4üUaþí¿PKLÑÍLê PK‚³E, junit/runner/excluded.properties]»ƒ0 Ew$þÁƒÕ–¾–L¬ù+1¯RáPøü¦H•&KçÞ{œ¥IUË`;ñàjàUÛÙ°é'5®oj7µŠÅ—$\Zy82<CšüfxP2˜ÿ‘£ÒnÀ==)75è†&¢…êéMkÄÎ_ã¡ËV‹Ðuó-…F¾ý'·-Y‹²3ßÕÈûnì0ÿPK¿Cûö• PKʺ$-$junit/runner/FailureDetailView.classeN=Á@}+ˆÏ•ÒÐ%÷”ŒÊŒ‚ÑŸÌ"wæ\ä¿)ü?Ê¸ÑØbßî¾Ý÷öùº?àaŒ.ad*¶ÂdJ± §™á9[WlcÎ}¡—È›©T±Ú%Y¡s`;Óç‹V¬,¡„ËϞ̭øÍ§„öõ¨óR˜0 –_ǽ‘gε9‰ _mÉOÃ-¡¥, Á Š®µÖ™‰x§îºÿ÷à¤ð¬PAExU'€:àÐGãƒM´ã>q¹‚ÎPKê´ë¿ÿPK˺$-'junit/runner/LoadingTestCollector.class…U[WWþމ$Æ —DEP¼ 7Am«T¬‚A6¡¶P(Ø–ÉŒ†Œ™hûú èkxáÁÞ€UWÛ·v­þ¨®~ûLš‹¤‹ÌZs朳÷þ¾ýí}Nþþç×ßÂ5¼TèZ.Ùþ¸[.•,w<í˜9»”_²ˆÏ݋ߔü‚åÛY…–»6£ÝS -+„SNÎ2ÃɈ+ô…A[ íˆ8Ž–8†„B[Ú.Y å­ Ë]27Š–B"ídÍâ²éÚ2¯,†ý‚íQ„ô‘b‘ôIÛÓK‚¬pz°.¯EߥÃäÐÓÓ™GÑ­Ðþ¦Eç¢V)ç­Ø~Á@/ºbèÁ…¸öšu­Y[˜]iþ’úq1Æ”/)œ<´=´fà,®ˆÁ€Ù¸½àø³N¹”{øuÖzîÛN)‚A…ÞšÕ‚£íf¬ÍÀÎu¥†«dItÁÜÒÚâÊû5±bU N:´·xÖÒ8"ÝÊ’ë¸!}q“1mQ‹åœ•3ð¶ÙŽw[dõ*°Í¢®5Sñ6&Äý]ºWÉ)´Lo±lûVÆò QîZ¾g ‚¨tÚ}Ê®[glÓ¥ËKÇ}6&=Å4{ð œRrŒW¢x(•›Á¬V4Y³]*¸ÎKiÏæ™eÞò3–ç™yKJÜT“Žá}dþ§)—å4}Ã#–¬f°¨`˜“³7mËõôœ7ð –e{E¡»Ûµ6å\ŒÿgÁ*Ûö—7Šr¨ÃƒóÒ|OðY køœÔ©e°™bønY•õ@Ñ/Ž{¢t¬ÎY$W˜j’ѓÞnBMG <9X’ÀfƒÊuM_PP÷tºÉ.û¸+¸ªÖWn‹Šì}’ nŠjZ 7›œÅ&ë|ȳ'†->úƒ†KÛèäð龨&=~šý6A ^æÐÐåaÞ£,ï5Ü '™ýǯۇ\êg*UêsZ/)éÝ*a«¢Rr$‘ ý†™=äWvЂ…wµi+»A£[\¹Mù'¨Ó:’U d¨~OñLÓX¯B®sûøÈ¾j‹òñÀîseŠ9O³•Su`ñ*X¼vBƒù|+”uY_ü PK®2Hį] PK1‡,junit/runner/logo.gifs÷t³°LTcbøÎÅ `ܦÀ, `ù„,þüa£`èƒüRÿþƒ©ÿ`(þdad`àbÐ)å Ž… ¢2læ–r90aa‹€²“ˆ†á£m¼âI2¸¶*8wétl\rx¢†wÑ O]§ê¯+¹¸Äs†FnÞ™™Á©Gûí…'ØX†^vÔ©ÀeÝô,ŒAœ'¾8 äåoÿíže4vižˆ (K‹Öí\²ŒìJï·>ÓG &­ ålÀ¢Õ,XE›,½stHµV¢Öæ”þ—Y£7ÅýCmŠGŸX-ÅÚ(T%K~=ÆŽ*aO*Ô—%ÕRÔ)ìe`klÍÀôè\“Ï©ìõ9idDó+6¯np¸Hê̵ۜµûL©Ž~PK…È"”íPK˺$-&junit/runner/SimpleTestCollector.class…ÉJA†ÿ2“ÅIL⨉{܉Asð¨x BP!¢à­´¦e2#3ñUñ ¼x‰àÁð¡Äê&nØ UÝU_UýÝoï/¯H`k„¥«¾¯âFØ÷}6ÚªwíÉcÅÍÀó¤aDXýB5=EG"î~„ÔŽbp—¨ÖNV3èÈ’HÙ°!ZÊ—ýÞ¹ Ź' N+p…w"B¥ïàwUDXiý§n›U‘ iQ„©jëJ܈†'üËF;•¹];ca›®2(Šß‰4BFúèTÅÝ&Q°1)BZùy{xÁ’ªûµýʘ֩è©Ìý1Ó° š]$Œ™á{Ê“¢gý£€`·ƒ~èJM¦yì¦.Â2Fø/õé¯e›æÛ{bŸ\Æè“IÛlmö@–KrlÁÖ@ìÇØ[È£0là2©ÙJÝ t‡r½¸6Àì=òug~€Ê’Öcâñ³u‰ÛEŒbï9>/r»¬É™VÃ1ú´ÄʵÂS¿úPK¬l‹…PK1‡,junit/runner/smalllogo.gifs÷t³°LcdøÎ `ܦÀ, `aaùÆ £` }pàÀÿ@ê?Ã0õÌ$(/8pD0rÈxlXàØÈ%Äç³Â!¡‰…Y^nŽG¡’3 ¿jZ‹Ç„…‡š$µ•>ÜXr°[ÂrÙ›…OÜ;ùBgÍñ V99‹;~UKf`ºËLØiON +žœ¤-û(&ÊXÁPK›¾#GšsPK˺$-!junit/runner/Sorter$Swapper.classmN; Â@œ—Ĭù‚……•`¡…î,! XÒ¯a‘„„ÝÞÍÂx(q-}żfæõ~<áb‹ aQvua¸êêZ*ž6ÊHµJï¢m¥b ´7Á+Q_ùùRÊÜ0¸O[ a¾> rgŠŠgVlÔ>I6!L›NåòXT’}sw½—'}סZKM˜ýYÀØo†¿„ý‘GÁ·ÌpŒÀþdy„Ø>PK'ï\}®ÝPK˺$-junit/runner/Sorter.class}SÉnÓP=/ql2@KÒ´»”NÒ”A]„@ˆHQJ‰8©I]9vä!üÁX³)âbÍ×ð”ó슡Tµ¥wß{î¹÷]ÿùõi4pK ´¹vØô#×µüf×óCË× ¦÷̉ÙtLwØ|Òß³¡†´€z×fø=tµÖP6½«€ Ôœ˜êØ®µú–¿möK Øñ¦Ó3}[ÚGN%ܵrç„ê-|@­ú¶;dÔíj'æ…¶Ó쑉ç·Úí“RWº¯Ìñ˜’Ûôñ$ ÓY˱F–>Y¾Ú®uŽ·Ù* ˆRç1óÏ:f‰1ðFcÓ·¶=‰Ñ9Óªµ ¸€Js¸( ŸBTƒÁa4æNl³Ö+àò˜ÇåÎa*‡–xÓ‰¬@Î÷¿,B:ÖK6(ÚßîRׂ¤¤Àü©£c†—d«ÞQjzdïü.ôw£¹®ùë‘-o5Ÿ@­É8B[Âo:fHžÚQ,²òIAÈÕá©ÑjR ÊLý²ãÏ9žjì, ŸqåYʬG’,V)A&ú†bldêºñ"ãì£ü swÔP_ Q×»¢îCsøCzS‡µn$þÄ«ïPl0ÿ 01ºñþð ¬o‘¯S4>cY/g¤E!­?l·PâYäßU"ó¾³ÜîeKÑ@ë”÷éyñžòn·±€gÍs,aˆeŒ°‚«qדÎèYÇ6Á\'1A•Z*ÖjÄOó p>…ÕǸN-C}Ö]£'Å!K¦ë¸A™#Æ<­›jöPKL+ÓÓhPK˺$-*junit/runner/StandardTestSuiteLoader.class’ËN1†ÿÈ(â¼+^£$:;£qct5ÁÆ}aª–ŒÓéKW>€e<*hâ¦ç´ýÏ×ÿ´}ÿx}C»Ø`Øl'JO'J í5 W×Á…ˆM#‘Fø„vÁ&Ûüž{!W×Þy³-ZÆE†¡ü£~ nˆ!w$IqÌ©T/²'Q p1œGy† _*QOn›B_ðf(J~Ôâá%×Òλ‹Ys#c†mÿ?†IRưUñ¿|7Œ–êú°úmé$äqLòüéCKÜ):d­o¿™³(QAOãbŠŒ÷©\Ì0¸W‘®ó[êpŹé¢|¤.>4*mÜ‹#dVtÔu%Â=æyñDwG0kÖ\›2c/NÅÄ[Ó–ANUðÂWDç«|ÉŽpL˜` ÖЍNat wfAXîè¯2“¦ˆWMˆtîe›ÂpA .iö†aLJc³^çÑÉ‹f ²ÙÊÜ ~iÜðˆ$G`ß+Ì%ñn3Y/d=Qᨠ –“ü˜‰“écŒ‰ÐjPeA”1[„ç°ÂMQ³ÇŒ¥öƒ|ÁÊ5Œ@ëž‹SÄñS™ÒÕádk36Ê)öQ(*²—B}Óúe‘^ ½ßúñ¾dÊG¨l|?ƒóùûµ49ÿ;|(:~Ÿ-æd¼øˆ™•3%Û¼çøòãø„xs%/@…úʃ+|`ø þ*.ü-?»ù<ùGY à¿üø'þ-;^‘1ó®·òA²hÛ¦aÙANKo8ѱ:"MωÛ0Åܦ•Ý1 Ž™é³Ë*sÈÐê`^å³0²[qieέüj˜_)þ,ç-zÕp§óìV#ÔHvò}>,ÌÝýªÄ¯JåìpIK¡«•Cfy¨2UNYuoEöE~tz¨ÌçJS,ÝcòN$90T@*»†Ò1OīƱ~ä —»– ½Äeo ê05a˜¯—{Eö§ŽÿÇÈ­;é1Ôdi¼“oÃ*èSU,¯¨[ŧªåê0IÕÈ¥-½2©9.ÇÌÐ1{R¨:U/âS˜Wûhû—4Ô1˜/žLø=^Ê[ ¥wúPråg†Ðw›ä†±¾mYLSà-¡NöãpöKÀ¯CnÓ9ärÏçÁæPÏó;\¯sޝüÅ'p^ñé–”îD`c·kùq2Ç'PC=µÏ‘aIâ0LàS´jkYGÛ"{dpƒž‡0©ÝY2yq»«¤rq»»$¸xj‚Õ¨çú1û L¦j`*Gãèêx:vß»& Çò÷8> Úx¹eÀ6.£©:<‡¼¶Øn\KM’Œ©%Ç1–Öà Žoé@hf bf{uÍfµõaxð~̨͠)ƒf>Z7ïýdŸSã™?`sB)¦snMžˆj>ÁIÚ™ e&çÌTÛiÓyG‡`!ßÖ¾„E¶ƒÓ´Ã€»z'NëÏ™ôèÄ6æÅéΩvc©V­¤d ¨Y¾¿š¹Ÿ£†—M[ÍyôÎÉg•óÄ>Zͤ¬›AÇ#˜”A×&¸]wmp¨±2Áš-{ßuÞ•3UN…àûŽóqZàø(,¦'XJs¦«lÓbÖ(Ÿ‡£1>ãš¸Š·qçj­­Áê ÒmµOÂ]Û/ãó6¡XžëÛjûC®Ú=8B¸ôµ+àÚƒaƒ8§}_8Xp9®Ý\Ô6v|A"ûÍÚ~ª±üœc»>“¼Nc¶Ä­Ó!×ïÑ8‹$ZA©³B'&¤Û]¨ã‹EVš5Ìk7ƒêµÍ…Øj‡(£Kñ-Zòà\†o3ULÎwp¹®PÞËûc»n»U«sf 7ÇY0„\ƒ¸²½zdÝÈú ®Ý‰ønÉæ nÊ`KÈ ¸2¸}Fpp`kk {|gk ÓWÓ¿Á©Æ‰B àVI3w×Ã9ët{èå¿sHû‘ä[~Š K£‰ici/Âz,áúJ:?^'P»› ¾wÛøFt ÒÎÒH;©ïdÜy%˜ÂJ¾—#IÜ­9 Σ´µ¼ºd{÷o†Q]’á@³/oµ/È£vyÎ~9lû¼ïÚz{ìNÄ.]ö´‘mBQ°vö«}US¢7PÅÅÜz é|i^rf:¥G÷ê÷“Iáq†é««mú î“ÍÄ’í§ZñLû(çx¶}!ª%[ËÜü¤F`üY{ƒÛqËÞj2x•޾Æï›ý­ª_Û›ÅÏÛC»œó &—/+¸šÞ^Ã⻚¬¼–ýü:ö©ë¹c#Y»IGrªîhsr‘ÌÁ/è5Ï;J¿ƒ_Róhö­wñ+FRÁ¦ükÍÖñ\ º Ý({äw +NõÿK%mSmJˆºK‚ýMÈ`Pm†[õâýv!ãl¹ÞGõ×2¼?„<ÏYx2øó¥ ÞZü=ä*ó25>gCQ*Èb_YQÀ·»¬¨3ƒÿ4øËŠÊüg7ñáݲ÷=¦ç¿_¨x+âþ¯ÃBÆVãá­ðô¡<4,àzÅ’ÚÿõÁ¾m“é"t“ùy›¬¼y^DÈp?Ù$'Ø€ùï&y3ü…´ØÂÝ·q÷í¨d‚èÃÑØÊö°i¼ƒšîb¢ïfÅÜÆ/+¦ŸMd;Óv/kê>ÖÒý´¸ƒÖ2´¶“¯‡»¨íjº“šÒ@màáÌ„æ€Ú–£Ü6›r|ËçØK Üôã%d6+E@ÝôË¡ÊIúµÊ¥¤±œÌª\E/¼ôlª®Oý›¢<œ+¢‡^ ­Ÿ~8”—{‡ÓÆ”ìõ@=FýBžçòÏÒÎ}(•sßšŠcxŠnPªBþìÞ²÷Ã`F—gÔ¨–ê=pmT¥íjtkMuFéÃȶ­(Ùr Zn ­‘!Wµ“g›«&£Æ’0‹kw©‰ º \¥Ê:“N”jQGj–©Jy”ª î%·S&k]u´%P{"ÝJ6Sß± ›÷Þ±Ùkdç™G¼yf-`|+Øì»rø¯áaf]NF©¬Ò¼Ìý¢Ò¼¼Ô"ýÔâçüœœÔä’ü"vFF¬Ä²DýœÄ¼t}ÿ¤, 8;3#O2DH}1#ƒ¤†¦X]iIf޾k^injQbIf~ž5#Wp~iQrª[fN*#ƒŠz =lŠ L , ÀÈÂÈÀÊÀb1°I&PKÅsõë«PK˺$-"junit/runner/TestRunListener.classmPÁNƒ@œ-ÛZµ­1ñâ Êxj $’&@{5k»i di`ñã<ø~”qk´§Ù™ÌÌ{û>>ßÞaà— ×y#3åU”¢òRQ«¸‘QV+¡¹ Æ0Îù+÷ .·Þâ%keÃ`$é<]&Ï~/b2 KY+.ÕŠ0J:_0£eì“ÚÓªú”(^)±a˜¹Ñ~L¢ªLnÂÛ•žÓ9}¹!Ÿé>‘ºÏ—»é'$ü´M´Q¬O®®É¡wÀ³‚ˆë†ÿ‡;œ¤lªµtaòç`÷±nЃIÅŽ`ÁnÙ±æý_ÜeêÕ141jñ´Ã1ÎZ<ïð:)¦mvöPKC {í ÅPK˺$-"junit/runner/TestSuiteLoader.classmMŠÂ@…_™Lâ?.\ºPPpcàrЕè"^ …tÝÒéÏæb0‡¦ƒ ¢E½÷Qúý»ü Àº„Aî”´‰qJ±I¶\ÚÔIË+-ölb¡—‹“H ¡Éf—sfc„°ða2]ÝíÔ©óÏé»e9'4çŒVjU†OþZÛ¥vjcbÔ ‘ákÆxúrðmDªÉx) &ôŸ>™U|4B !ªª…„D Ä~ ýlx¥‰Ö£â»]±èüPK¼ÔŒðÄ2PK®»$-junit/runner/Version.classmOMKÃ@}“4M­ÑÖX¼‹—V0Az,½ž‚*¹oÒ¥nˆØ&þ.= üþ(qv-â.Ìç{3o>¿Þ?àã“!ŽBÄCx"ì!$L¦³¬Ï"­…Þ¤«Ö(½¹&øÓYNæÉUrIè/”Ví’лiÖ’0Ê”–wÝS!̓(j®œdUÇÔtZK“æÒlU£yPœ5¥¨sa”îÐÃUÓ™RÞ*›D;pbe<µ&Œ%Ý•,[úßVÔ>ª-NùBöyüù0ðÎRöÄ>8CïÕµ÷Ùö]1ÄÛè€cŽÀÔ±ëZò™ë~L/¨‘£Ú„C¾PKëãY›ûhPK˺$-!junit/swingui/AboutDialog$1.class}P]KA=×Dפ«‰ÑúcK4¢ß -EÑ ¡ JÞ'›1NXgewÖàÏü€>øüQ¥w&ADªÃý˜sÎ=sŸþþyDÛøLXégZ™ (ÝËT°ß‰3s¨D÷껈Pî‹+DB÷‚£N_†ÆCŽPu]10¼’Úû¡Q±n©ÔH-ã„ s®Òz“G´Þœñ•P8¹Öæ\2å›bàwÂÚÆ;œÍ6!w%!·±ÙöQÄTyLûð0YÀÊ„RKiù;»èÈäTt"ÆVZq(¢¶H”­Gͼ5Éßy{\}—M–„ûß±LÎâäBv 5vø¿ü°¹³Xz~ yX$x]•^Æ©ô±lM/a…@ìcõ=5Bñ$Î’PþTÖsù…»K#ø¿4¯ý i*S4yyð:ùVìN8`Ïß">písö…k×i< ÔغÃÌÃTʾTÎ,g>GÛÃGŽ„y,ŒTö8Zìdã3÷X}­QcëNc~ˆiجŠ5Ç®9Î:>9ÖP¨üPKìW©PK˺$-!junit/swingui/AboutDialog$2.class}]KA†ß£Ö¦­iö]¦]x‘Fmt‘XR Ýv=êPÛnìGÒÏ ú€.úý¨èÌ(Q.,çcÎûœwæãóíIlb°r{*r¾ò®båÔ;~)áúW• D(Þˆ{áˆ~äÈ{éEÎ¥òz~¿Þw‘ ,$ ãѵ +ÛÌjý Û#¤Ï¼èZFªË’}Ń„ÒúMµMH5üž$$׫m˜Ì ÛÆÆÓH`Šk)OžÅ·\ˆŽË³…–ßn[J×ÃfJ›$¬þ¿®²Ã&³}s½†ë‡<@(³¿¿î¬sc0÷}>ÀX˜'X=Þù¡´±¨-/`‰@ì¢8ŠFÈœûqЕM¥çxÛÒ2‚}êy2h¸" eˆm~€¾±~Žô—ài®3œír­;™Ú+²µgäÍL^÷ÌI“)„iÎlŽº[ÀŒáÎbnH9äh¸µ'ä^°ü›q»O c~¸ÀÐÙ ŠF½j4%”jÀ _PKyŽPK˺$-junit/swingui/AboutDialog.class…Wù[×=3Ë6ÈŽm“¨‰ã€XdÈâÆ8Gà.Nëti1CG#0N—$ÝR»¡{Ó=é’ºkš¥H4J“®I›&ÝÛt¯í÷õèOmÏ›‘@Lýù›½w—sï=÷¾ÇKÿyæ9Ô¢ÿˆœÎ[¦ÏÍ™V:oÆ{'í¼{ØÔ³vZØvZŸÕÏøÛñc•Z%™Õs¹=ûR&žÕ)Ñ/{‚£ó–›1\3)PФ‡× ìlI¬²6àèÓFOë¸@ ßNÛ}¸>çÆýÍ“­ã!¨Ø¤!€ÀÖåí ’-¡œáŽ9ó¬>™¥‘@‹§Ô€F [Ø’6Ü~Ûr ˽C·(±£¥uÅÜÑMËpzBØŽ+¤£YÞ?꘩>=Ðç™»j[|PWjˆ I ¼Ö–‚f怸|5¦ªÈüµ!ÝÒÓô*m]¨†«ðšÕ¶¦gl‹˜\ËlÓÖ¨y–àëZ¥ÎuØ«a®çŠW3­*ÅÆLW¦áŠ–ª²Œº3îùjC»ÌKGu2O˜VÊžS§šm'u×´­#Ë÷¬1f/×n54Ï`º5ìà W®¦Ò˜‘sG¬‘tm&ä&*IÃñ½…°_*ÞŒ×^J²¾¼ëÚ–‚ ­?kç e¾‰»¤QÓe»§KÁ!«ˆõr"=~íú4ô¢_B®òÜ;™s=éV!·õTª7)“‘0sdá\S• c–!ÅWKx.Žâõ0(°‰ô±í2÷"eî-G[Ù"ýnGBÒoˆUXWDÁqè°1¥ç³eœ».é+݃ñŒh¸£ef-‹$ôI#«àN¦øØL•ŠÆev7¯t -Éw’ œòR§âM+<¨¦•OH§4Ü…»Ëͳ쪊ȺOdi˜€ª›Ý.“)‰”†I•¬rÓ—Ÿš’•& sT…©!#Ao÷ëíä-æ?>n89S0+Pc¦ä\i]‹: ¶†iÌР>3cX”l_¯kÖ,ùPhÁAN"`4ÍÑÉùèíŒ2Úg$ï‰êV*zÄ1“™èQ}zZW1Ëætm_=„3ÒsóZÒ1t×HØi{e0­.ýÜ‹·i¨ÁÛ%ù/Lœ9’µ¦åæ¼SÃ}r$Õ¥¹yF@ †ðÞäê»Ë«ó!¼×_yG”\™3Sn&„÷û«çˆI®f 3qCø€¿üL’•ÌØNô—>ÄQÈöh]w6TeíøäiN¯ÀÁGå¨ûXõø´H ¢ÿéÁéV¡Ó'5<ŒOѯéí/4+*ÌÌgðY‰åsŽ…nhxT6¼lhmÔЫ%<à_Ä—ä˜ûr¥^`Ãöh>™2ÜŒ:â8rÎ}…‘%x ç§' gÌ?“Âr¤fÇuÇ”¿Ë‹7c2ª¦ †ƒŸÑC¶ËöõÎNV˜†š ¢L]RNQN•uÇ}d%ÍºÖøðÙWÙï&â¬GÓÆä çeÕæÄÄìYG‡æÂUk>j¨¤»®êP$ûK•wú}ÞÙ§ç yÈŒx?U|¯Bª•«ˆ‚çIª)Ûfº®û?íí__Bø~¨áûøÏ’êÔzÛ¾vÞªÔû'åãË—Ë8öœ,¯‚e#î‘Ëñ ág²çŠ—4¼ G–*sÙ™6§T¼Â¾öèô£RðKFE;ƒIy ç켓d û[Ö ¾\d•rJ í×ø†_á·Ë7„Uû~çý^žˆ^âcØvýÐÏ$×±$+̤<…Âk­1£àS¾¡ŠÚR˜W‚A¤gÜÈ!Ê*0;²è|+ÿj¼• Ÿ¼ÌU¾ÅB¬-PÄæXmÛbì,!2QÄ5Šc8W@K,ÌÎX[7^€:[Â-%ôL„o-â¶¡öz'bE.àÅ†Û +a|"üÆ"&†;J¸k"üæÚ†=E¼¥€)¹SBf"|ºˆ{–ðÖòá9> 8KñH ¢°ÅW Éw¨+á>¢ºÿ@}¤¾~ï‰Ô×.âÁH}`ç½çB¤¾A[će‘ú>^ÑP"JÔPRC~Ÿ÷¾"ʲF$QªTÔˆê©ÈçƒÞó|DõTTO%¢–ððDƒZËÿE|zŸ—FÚ#j•`$èÙz@ƒРg#¸â¶.¤J¬„Ge¿PÀcO²:­¼ váëõUVíqÞ5-¬c6¡‘—å0®Å6Jí ÔNtc¯M8„ݼŒ5cï%Æx­=Åû­…ë±€<‚C;íuàt²}âx…£øUZ¸ˆð/܈ã&ü7 ×Ém¸E\ÍÛczD7ŠÃ¸U ã6q‚wÃ$z…>1˳à~^ðÀ€8Ç÷Côü5¢!R2 _Ç7$ñøõM|‹‘u“—ãÛŒìm='ùuJìÃSxšH-à;ü ç?±È¯:J_DEF‘ßKüRˆì^|—_*±ìg,Er: wŸÙ°i«†ïøSxvâEì>~n ?žxÏ^ÀÖ^8yw?/âåçÿXÂï’‘mE¼ú„×›ùçËŸÊ©×<3ÃØ‹ã^X;|³å°öÒíŸñjÕà¯^{ý ç;̯^¯áÂ<,½÷ÿPKœí¹ ²*PK˺$- junit/swingui/CounterPanel.class…VitW½cY–4ÙŽ“8qm'éâD–Ý8 iÚ8Mˆ·F‰,§±ãÖmC3–FòY2£Ql‡¥ÐÒBËRÊV(ûVhÒM²CY mÙ—R¶rà7œ?øÉî{3–e[>G~o¾÷½û¾w¿í½üŸKÏÃkñgWœÏgL»;7cfRy³»/›Ï؆uJÏiçõ ú¬³Þ}•{Ô'cù© ÃNXVÖÊ)Ø]¡:jÌÚƒ¦‘Nô(ØPRÔÍtÞ2¨,ÉNç3üÖ–Ö"ñl†ç®@2â¨ÎaŽFMr4këiJ„‡M^ãˆO¨cLAu_6a(hÝúŒÝ}“e&zõTTŸËæm6h¨C½ŠFlTЊ–ô…!=£§ «§cLèmVQ& R+­Óžá‰óFœ8[øS†Ý—Ös¼ÂÆPGtYG {4\Íh% & Ïu'{îN™I?¶‘¸•.5r6)É–;H4ñÅ…O¹lÞŠóVCkN)ŒØqz:Öò§á*\­âJ\£!5€*ì$¾c”!ˆuL i¨u–ô9nºm çíé¼ãOAX¤c=gkèµ*÷îÖàE@Ù£ÁçÌöið;³×­Ž¬¨>!"ë:^‡ü¸žþ ­½XÄqÊ!Á¨/¹.’Év·øBþ9ŠGUÁëôDb4+â@Áž2÷e§¦³#c÷ˆ=ýý‘Ht¤ ƒ^ô‰[õ×}eÛÂÍ»w;Oq"Ÿ¦Wª`êZ¸6ÆŸ¤MKé@Œ!Þ%jf '+Fõ‰´!² ×ÓcºeŠoWXmOšŒ¶Öèú©ÛãÆþZù0ÂŒÙãÇ£‚ÀÆ×)ËH2ŒÄˆyQ¤ÍR úÍ)#“3eüÜŠq±ë¶Õè%}¸CAIb:Nå§¼-¡Jp‚Š7àNgqÎݤÏ.mÒ0á,Åy—Žg-ób6Ã|?–6SbØ$"$ù4V¥ÖdÒˆ­Ûùœ Õ“l÷GûïŽ ªK –w{#ÒœÇýÊó„ô‡V©‰ã²˜ǽIÁörl2ìð\ÆÝTK´„i»¾ Ý&0ò¸ ÂÆŒ‚ærŒÞ¬•0¬A=ng­9æJé705mÏ9« ÚB+³oBÊÝͼɛññVÞ˜g/íÚºÌ&aÓ]x» üÌÀ3aOrLºù¾ºŒö±bØ–nfD¾Ý«â>QF½).Îjx7‚Jîw%sÞãHÞKƒ„D¢kx¿#}e]H' 35ikxÈ~˜‘¢YÆk¿†ã#BþÑ’œÀsdgý×3ñɬ¥áÎöO’ꤙNkø´#ø uL™Î$uM†kø>/Ô¾àÖ%·40àLYˆ¿Ä΢ £b鈮n ’Ñ/ã+*Åc´%NU›*íeˆÄ—ù¤{£—¡›Ú^Ö ƒÁäY5Çôtž¡ÕZ¯&Ë,yO‰ö´M0R…gÙ»á6QïE„+ °‹Ù´º¦õæ“IÁÇsdqy-“âEbÚYGUÁæ¥>±¢*jøžWñM|{EKuV}ø.,mN*تÀl%Èïã*¾‡Ä¡š¡¬º?Rq /2šºýxY„Ìô´‘¡K»*íX#rnΣ~‚Ÿ  Ÿ•õÁuô~!ô~I·‡Ö¡á×Bá7NÅîÒð[a¥W÷Ê㺢^T%§]¸oZxŸé3"ƒ¦(0ÊÛÀnq*~0@ G¶dΪDC–£ßùc­;2F8 ˆwÿ7Ê_ù\R8Ö‡Ñ8>MóØÑÖ¸}íìr>:äGg8ìŸGw{—&ûÃᆀœ ÀÁñÆ<ó8ìñTW×Õ5¨žE÷ðoÇŠ‡ŸÅj®m W½rµÁ_Z–*uzçõ®)S£ÂÞšÿƒ£Ò.â» Ê~ÿº(OI†ùÿ tòÿ&’X‡­¤­›±Mìõ[pŒOÀ^þ¢|žF ΠçøGüMb¦±9ì`%nÃÝ|¬ÝÃßC¸ãÔÜZSÀÃüÜÄ 8NGFèÈtØI:#J{†HdŒ÷ÆQÚ>H›‡hµ¸ÅE¹/VºE _Å×Åœ±1]ÌØåmc¢ ÊÜŒ‰¾Çì3v:™•1Ñß${1ÑÖdfÆD?#'bÆ–ñ’Àׂ«o,å*n'¾8õJ™ŒÔgd/Mȉ§€Âò•›äñg8ÆD¿…Žº•N_ŽçZ #/ét„»Å¥jÂ-+ÐT)½ƒ˜g%B“£U"¦óÒd %¬³¤Bhµ qi¼eßYÀçñRã‹ø9Å…"~UÄ+EünõQç˜$zÙQí¥£ÚKGý¾tT/ùZªä‡±ýÌj¼‰0ÊðÔžZÂûCe¼ý•ð&‰g^¯Jôhï$¿D„:[ÉA…ë¦Se‰(ÁðG²«ÈÙ¼ 9’»_ûPK«É×2ùPK˺$-?junit/swingui/DefaultFailureDetailView$StackEntryRenderer.classTßOAþÚ;8O(…V+TAÛ‚TEPÂK±±¦Ñ„’>ôm{¬¸¸½kîà¿ä“¾@âƒñÙ?Ê8{­ ã%»377óÍÌ7“ûþãËWŒâž1lF® ËÁ±t"YÞoy¤Â—*òÅŽIiIq¼Ô ¹óþ…úv…»/|á›` ‹‡üˆŸôÃ7dV…RŽ£ Æ–¤<Û £…b‹!Qõö…$ Œ1L6¤+^GÝŽð÷xG †tÃs¸jq_ê÷1¾“C¥ñßeWæÄP‘U¯Ûó\ᆠۅÆï]½Ò®•ØTVœ o:‡Â +õv»Ø·òã°|Oø© ßf膉ƒé‹žâ5‘-T«ÅÆŸNiL[˜ÂŒ Ljb²DÃåZxG(7 .áž8¡z3…a¬bËÆ-ÌZÈaŽ^Â8/ÕÄm† ãyjOö4œyv D¶¢Î¦¯ ƒ!yÄUiˆ«KãUu¢ö„ÕÉ ƒ¦PôQì“¡Í`;DþKÔ<' ô\ãVÒûÃ0s5ÓVÓ‹|GÔ¤Þüß¶`MÇRʺëÒ A)—ÿm…L¬S]Ã{D<Єô3B‡64ÒÊ$™¶”Î0þ9þlÑmÄÆu\£Ûî;¼N’éi‚?’ßÉÒê7L¥ÆSó§Èl¥•œ‘Ï$2É3ÜØ4K9ãùø¾›3?gÈ"ðœ070‹M, ‚ûØŠ3îöQµ¶ˆ¥¸Šîa9n¡DÞú/h­H'k+t’•Ç*ý1 BžÄ5iRÌÃ8÷#<&iÚžà)Æ~PKXÀ`a`PK˺$-@junit/swingui/DefaultFailureDetailView$StackTraceListModel.classTÛRA=“â†KB¸Š\L6H¼rS £A bÁÛ&`aÙTíN€²üÀ´J“*©òü¿@íÙ]CŠ‹eùÌôL÷éÓ§{öûϯßàÇm¬1ÌìWL]¤ícÝÜ­èé%¾£U ±¢éFÅâK\Ð&¯óãÑ ¡6-­Èsº-ÖÊ%nÁöµ#íÄO/lA.¢ÁÅÏм“ÓMn3DsÒ9]º‘Îó¢([³t;§"™gd(NA¡03´Ÿ B!·D6™—n­aDЦ  Í-𡃡Mf{U9,pkS+\æ-5#¯Yº´½Ã€ØÓ‰Ó\îÿ öÊ.Ë?ä¦X q¢åih¤ÇzaŸ(“[ ÿ㣠=’sC“n–ø Ë2 hCÃÈØd( tfÙ\8ée–†Â"泎vvQ3Œa4LRŒ3Ävt‹gʦ ÔvfÜy‰¡;q‘bÖ‘3¤T]%jÂM½˜‰.‹×,†‹–ø¢axØ Ò²qÜaè=kœ¹Y>à&UEœbð…#!ÜcH\RÌÅ“m·Û˜ÆCÒÓä'ÂÁcèL$/ú+xŒéLtýZ©tN4¯êä¶‚y,HÂO"{š½V¶¸ƒk; ûE<“8blS‡ûsW–E©ÂåŠUä+ºœ°«fiRBÐìdM“[C³mù:ÆÿmƒxA½diV|Ô<€˜Êç@;ù£—D'-´[¢[FkT­ášzŠÈV{g í_ýD§>Äè¿•¾  ]è µ“,ÅB]z7z<ÄyŠòÑÚ¢~F´¿Šþu f'¨Ûèr<¹»Žºg¸Ajʱ„ªbäÃ9¤þ*¡:•›õâ׉²ÌSS5ÜRU¿‡SEê|uƒ¤ÎÕ3Ü@.V'Ã}%™Éºr«žrqôî_áGIò1‚o`÷à}òqz o‰†ôW=ÐSLo¥¢÷ý58lr7t‡!‘û»”(°²ÎÝ”µõÒ2¹Iìz#?U«ºjxžT !Ö‚ºŽà/¡‡aâïB\­ü¢hke.\Rž†„c2â"Íã‰}ê„É‘’Pㄌ^œdh )f,“Â÷“€i]3¬õN1ôú(~™ ®MPÉlÖ‡8-cg(Ñ}Y„™J8Ë 9ÜÀ$r"·/”Çã2†1BÝ@†nPè–)ˆR^ 1œ\/Ù”tG§úä­jʪ˜®Õ¿¾Äpë_d›6]ûMž›«Üæ¶„+2ƽæ )nõ†Áƒ:î5ðÒ¸†ë‚à †Vgê!NÕ»gÍÖ¶xÕ²_¨EîÔ)%E{ƨi¼º0L‰†ùïÊSc%1)ScÝf8ñ‡°îÐr…3CW½I÷XÁ=Ü—q©)x÷5‡ ¨¼·•0M…£2ºá’«Et¸AÓ4 3ƒYdIÒ=ðînäM"?@N´öCjªµºÀ}Ô—Ò,\³,Š×Gž!$|ð]ýŠ¢Œä‚U±ËœòA~W†‹ˆÞ}Vˆ‘24ÇáôÇèlPê݃]‡A*VèÁÑñ[ ±™Öô¯¢±•v*Íâ®ytmïiÁa}‡6´Ó¨øèÀš):ç·ÝÂètCft½Ë;ˆ/oãø6ú>¢[\ì``ùè`´CÙÆP £â(ZÃE1Çj¸ì›Œ“ÏÕnŠÝ»F?qÒ4N“¸œ§‚^Å,&‘ÅÕk—ÞBHï&z3„¡¹r›«!ý s5Ìïf){×yZ<¨ß<€«<òZ » 5~E["²Ë{ˆÅ´ˆx<Ƶ£Ud[Cé+â»9û’>ßÑB<ñÆ% *C„4‰à)…§ùb?PK­V>x)PK˺$-$junit/swingui/FailureRunView$1.classQ[OAþFÐÜ*Bk­RC0íê›I›Æ„xKˆ&Åð>À Y‡d/¨?«I«Iüþ(ã™>èæ›LÎe¿Ë™3OÏ‘Âl ”F±V‘Þ(=ˆ•w"•ô3ÖE7ÕB 7’éùR¼Ëîˆz‘ƒ”À®éÞN™MHG^K…Q›|F¨±6i Ì ,DCV÷Ù¯•døM Ó¾ÓÑ"ÕcÖwÅØ•Z2­ÞH7Ç}HÕêY¼Ë"e3˜CN`¥¥4]Ä×] ®d×gl¾5îI¿#eêY3mF(':VxTw"ý˜šC^ õêÅg:ŠxénÈ}ßÀ犠"¾hV¬å·Õq¾èWúŽcoXõÈìeö5LÎÛRÝ5Ø¡«zÚ¾œcmewV9«ì<_È>Ë“§ÀòÖ¥ÍKÉúˆMNÃ2ßÐcÓ[vʧ…(³+;= &TyI×HÇ&o²™S3 ´#jVTW=6¾¾ŽeKÀÁöa7§¬,¯ªNI`Ãÿ55ì \}ÅÄ(‡FÀo—1áN ×nþsŽƒ€¸Ëq\ãéCé.üª^ä·?T½N7C4Æ%žŒH„ú;ßr´Bmu7”¦—äÀÐÆ~Åxtx#fÏËÊDÆ%h"áíc/:šŠr–®;¶!±ÓŒÀQiÍ•bÔ…î0b8ÈäÓp°˜uÓ±G•¤•1å¨}’u\àØV%´] –5nØIÃ5Ü ‡qõõt±~ÇËïµÖ(ŠÇp\ºˆðü”™6g-cÜYr²vFÃIÝÃ,«-Ù¢¿LA[ùY:ÆX~-z2)9åu‘/†-™÷37–)x¼¬­Â|ƒ’åYŠ0bÚÆXviÖp'uF°Fœ9ÝšÒ]S¾û‹•™3]Ú*è2¿sk]U?¿–@#)‹™ôeŪã)W_2V÷š*s‹¬3NP쪞Àˆ$:*¢‰*] Ñ"/ 4–-î Æ9hÞ2–(Ä 7²xF6¶Ê$žªÅظmå¸ùqY œâ‹Œ†gp!Œi<+Pez„E‚ß—¤¶É&]GR¢Àî²bøiÒ™·e=CS-c¤óúhHÊ©7ªY̧Gqþ/pqÖH^ÒmC ¥æ¢Í‰9×±,¹„)'I¡óÝšïêka,Âòô²ô4« !¶^JµH%m8rÖ]gêMVA:n¸®ãöÍ›©X¡-eç›-Ò¯–Oi'ëÎ1´±¥£§xJYÆJY0%¡µq‹d0¹`tXÌE‡“êðrÙ!…åîË%*èÄ«£eÆ^©ër2–áLYçñz¯á 6Öuú`6Më.ÏW‰a!•4¬QŠK*²‹Kèq¸» º5¼V‚;cåR–Laû-©áCo¶}Ä¿Y#kú¬“ÍL:ÝeZoâ ì*sŸµ<çUé¬) ¿ÚUk¬ï­Nðjt³ö0/éô‚ì„ì;¦ ºä+jŸoqKÞŽßQÙ Ulæq ÅìOêÇ€²FUýÉ[·y“[…7_€ÅOÆü„¼O!ÿxëóâz-4>·ñížo3Ó½ŠH÷Á;ˆvßÇŽéîß½‹VU쾃v¾¶ßÇÞéèmæÐ#—*r8äm™^ÅÑNÈ·Px«ÓD=“ÃÐoôÀ9>ûèè'»ò9…Ý8C¼NbÃ8‹1Zã<'Ú9\åÀ=Oë&!÷SqÌàqFÂ'µõãxKE žsh üÊ_`·½×'G{ÚîâéþÂôXoWnç µRÐmˆƒ|.¡žî›9ƒ÷qKçݬï<„vÒš¡ÓfDðž'Ê>TAÇ,J Ì¡Î'tTªºsHâ«X.tZÁkž‘/Ø‹ >ÀM®J×÷±(óÑiŠt¬bi”€/DÓàæØÁèK½=ÑWrx³à ª]!»«ŒmûɲGg^ÄNJö6]EЈwð.O·25ïá}ǸåÓ䎤\ã'üã±ÌR”¹uyªÉ»¨¡,Ÿ(>Åg>ÜþWÈH 0ÕJ‚”‚èð6óŸ+ùí |É_ý7˜ù?Á*åíåƒ (p NÖ>5þæ.¾`c´m—Öe®ÎGàõü?©$ø«.€Ÿ©Í€òýPK¥½;Én PKœ‡,junit/swingui/icons/error.gifS±k“qýB *¶[ÅÉ‚.:Q%T ®œ"f„.âeÌ ®.Bè©â˜áŠC©ÿátÒ©'Eá|÷;H¾ãîݽ÷î»·³}ãæ£ÓÝZ÷£«¶ß°=†ímÁøºØ?ìyÙëu·þPKƒÀsý(dPKœ‡,junit/swingui/icons/failure.gifS?kTq|%*°PÄÂW+IH±!ÆJ-Ò ƒ )ÅBH#ì+ürÕüS\!b%¤Ø 6ê}µ³‘#ˆÂ:û[¸{ewvgfß›[kë÷NtgºŸ]ÅÐ~C{ ííñýðí×£•••¾ïWWW777wvvvww÷ööÆãñd2™N§³Ùl>Ÿ/ ¨¨Š©¸J¨¤Š˜ÀDMÌÄMÂ$MÄ.êb.î.é"!Ñ ñÉIAЦXЧDJ¦ˆÂQ& ›XÂD…8@²J+¥ S¸"©«"5˜Á aHƒxµ©ÃîG:$ Hð@2 YК°„'"‘ ᤢN¢¤E\™ Öx­Q& ›J æ¦êª¡šM2®È”™ºi˜f‘K³È\Ý5\³ÉJl³PÐlB“,ÕS#5›ô(+(¹`B…Í´×ÛxÓºŠ{]~XŠ2XPKD·•ŸWUPK˺$-junit/swingui/ProgressBar.classu’[OAÇÿÓ ¥Ûí…*Ð EnW¡Þ5Á˜(XS ¦¼-e¨K¶»dvø*ò)€hM|ðø¡Œgv7„¢>ìÙ™sùÛüúýã'’Xà †¹ÃÀµeÛ?±ÝA`·? o ¸ï¿±DŒaöÐ:¶N#sûݘ5É0q°%„'Ø.]^ÚDzÅ4Z=†Ô¦·Ïud0©!MGY$ 3\îHKþ¦ç¨ð²ÑêªDmëD¶C݆ŽŠù—ªcElzÃ#Ïå®Ì Ì÷¹Üö/p÷*ÆMR«§c3*¨2»¶Ë?Ã=.>Y{§ä]¯o9=KØê+Sò³í3ÔºÿÏõ1ž)ƒ:5/8UQú»,fq †4!¸«ãN¤¹KbrÉ0I²g9*Àè¨ÂWÑTã3ÈÇ—– |Þ[§ö0긙ïëXQsN`¥'-‡vÒ!Š/ù©ŒÎ®ÚIú8‚k~ÐïSùi;^ ú|ÛV}—®u¸®z@ƒ¨)Œ>Za(™Z+É,ÝÞ’]ÙÊæwäÌä7äM:Mpë‚´ Ì*[H(ÌQLS(aŽ4z‰yÔB_ZyL}Me+š_‘ÿ‚Ì%–Î/±|~…,Э4C»Íaæ®㘚IŒëÄEVÆ 4“#´nV9GýÍ#Oˆ2ê×°•+¬‰fŒÝ¦Èý5³6š9BûâF‹DkïRHªFÞ1IàaØé#<Ž™ù¨ÈÅl©öÏ0]?CÉLýs¶UÊ,“\¡©®Ò(šô¨Za¾FDºÊ·€'a>uzJ»TCy’žÿPK‰Â^PK˺$-junit/swingui/StatusLine.class}TkwÓVœ‹;ÊËqœÙ ¸ï–&@ÉÃÔT$ií†BT¶/ލbåH2¡ýØD8˜žö~?ª§s%Åvm>(ºÚÝ™Ùݹ~ûÏ_oÃ5Ô..mmVF •Y4übÉiùËÉÕ-c=Š®Ôm‹4·bz~G ¾æ4¤À𱢆Î7,ÓvšƒæûJT4¥‡ð¶Iߥšår9¿£ac)h×0€óIœÃ„†Dø6©T±‘Íö^MºU³f“1m8uÓÞ1]K£q=ÂJ¦Ç´@“¾RÄ|ýDc*ñ"fUâœÀ|ÿ||Ž'Òš³·ï´¤jiA`ˆh Ë?"{¤0q9…K¸"ëÇXu܆tKfÝwÜßxW`¼îJÓ—«ò™´Ã¨Àýeµ U/kБOá* '7Ø'l‰+¢°äÿ*Á×QLÑ2ï Œ5¥¿íÊ'Òue£býΦ²z¾7§ukO¶<ËiQȇøHêcNòtÇ$>ÃäðNqLégQ(i+¸©¤Ñ(q×ò¦ÿr59²„û bndΦq½]ç ÜzâLžáAeå‘nášc;nwÙSÍ6뿲 ãx)ã^_ákš?0™+›®ÓnQ„~2[õv›ª·­Ð”Ê\¾AIyç[~Û“žg6cŸR§Lù®ëpÁ16¬áAHÿ=u+8DZ«Ö~ˆúH¡^üw^0/öQ·¥ÉZ â1/|Åi»uY²”G{3½®˜©ç >sê.ò-§n"ÿ°|I§»<«¿ù¿¡=LÄÆ´×H¿D&<Æ£cöE5Åçªu=‡1‡!\" Ü()BÐ?øEeé…ט)"ÛÁ|!ÖÁ;…øŸx¯ƒ |riæ– KÜî¡/R0FéãÄNóm‚ Ìb’±,/ÑTÀ¸âãKÜ äëXÅ ²Ï²j ëDØ@)ÒSåYiÌPKFi9„ÑÁvR*=ît0°iŽi†]^$ólÀ• k»\â}Gd.ÃOCî¨ÛC<ª\—*GàêçîÆnÍq…ô/ ]C×s•›Ö9Š|€ª…ùª€d×þPK@¨Þ±xPK˺$-*junit/swingui/TestHierarchyRunView$1.classQ]KA=cRפ[£ñ3~¶ÔDìê› H!(‚‚ yŸl.fÂ:ÝÙ¨?«P-øÐÐUzgÖ§"šá~žsîÜùó÷ù7rØÇ–@uje‚äNé›TmJÌwE±ŒÃþÃuª;Šîª‡„ÀÌ@ŽdI}\u9›½ÏðH› µ(â5ÔM•Ò{ø 0iú*©°jó}ÙcBëA›>2öD1â”wÇ×:ùưG¹ÝZÇGŸŠÈcÚ‡‡©&0#Pj*M—ém—â¶ìFÜ[nCud¬lü’ÌÛ±¶ÇЭòØþHF)5ú¼*ê Ôxà·—tfSnä­÷%<,³„áJ†§žû¸ V¹AÇÑ(¶†iÒ¹²¯¬¼&öÕ2±Ü…æ?lD2I(Áo/þ¾e»N¶Ø3Á·ˆûìqì2õ_(Õ÷1ûÃõ”]—­,9ž9ö|¶6;¶‹\ËX¾±µ½SõŸ˜}ÂÚÿž`Åq,f}/Ö[džCo:Ìg|q¨Œ(ÿPK¬»Ÿº— PK˺$-(junit/swingui/TestHierarchyRunView.class•VùWWþBDvˆ¸€U kׂK•‚R (u©È`˜Á™  Ý÷}ßk÷íçöœÛrÚãÏý£zú½™I€d ­ž3dÞ»ïûîýî}÷Î_ÿþ'6 ?JØ1“Ö5;f-hútZ‹ª–}ZSMÅœLÞNëcšº C’P1£Ì+±”¢OÇÎǪ“¶Œ "…§s‡‚ÂS£¦ªž4K5%l(4Ik¶:¤èjª×±çRŸ¡Ûê¢íoOxoŸöÅG4î“Ð]ß´uLB ÏH¨6D[ÇÂ(Cyl £¡R¡R–õ¼“QB8 £D¨“ O«¶PBm´u@´èžŽ˽a4 "Nm–°óßuÞ¹WÆ -~±äÛöºAl a+¶K¨, —Ñ,¡AI$ÄˈšbÆ4CÐ,[ÕE.:¢«VçUÝŽùÚ:T÷ag;°K¦MWÏ¥g'TsT™H1øªcRI)¦&޽ŀÔ,†ý_b¡’“Ùœ —• f#š§¨21¡&D.œl–Pû¾”b‘£Úß­Ng‘Òw!&2¼‡ûÑ­X2KÛ5­M• ›òøÖ C–±Ÿ’!Γêe¤ÍIÆt(ZÀ³baÄ6‰Ó»º9ˆC!Àa å‚¥)'A z(àhRm²Åzryýˆ„ú5Á’ŒrR»6Ê‚ë3fç Yöó™îÀ!Ç ¦n޼ÛkêOõmVŠ Ù/ uµs IMˆ€©µH’#÷”©Ìª †yÝœâœÂiqIâ„UXyóŠMö°Ð# Æ€¸¯E”°Ñd­*©~EK¥MáfÔ7[$ƒ¼õ)ö’¼*pêÝÙ§cXTøˆ„ÆÂ²ÈÊx$Û Ó¶–ŠÑ?ƒõr!„‹Øä¶„aÃ`À5«ªÒ홤y—BÃeø¹-ã*ÝžÒtO¶kD·Öjžc½­ñ0®A”¼SK»å¶@.'  §§È7iÌÝŒë¶!¡.z©ÐkQIhÂzÆ»yI-•p[U¾qÜ7ìf…º~YR줌9ÑÓÈsìPV¶†ØŒÄ¾H¢Ů㥴H⼄²Yåº:¦Y»Q‹îúM&h*[8uþŠÖåôôjŸŽ.!8ëÖÓVŸÆ¶\N´›Ÿs\®*Ì 7™_uQ‚wn›°«öÑ›l2vdõÞFkµ8ëhÃû¤Li{Ô±“ˆþO]±¦Sî [Ic!kobH\Ý·$l^û Œw˜öõåéÓìO¿j伇÷CxP.KŒaÎÓÁãlXÏMr™i½Ÿ_VRe‘–›ê¬1¯f±ÃøÌ¾-JÜwì/9Èø’ò'=Áɶª#}¡2|…o$„FœùЯ‰¹ñ›p]"3/.†‹38T ͤ€Qñ/ÄWÄ?~ŽðYÂõ2„ùÜÈ7‹v¦¥í.*ÚÚï ªm 5ãwQ{õm¿ >ƒÆ%lçvS»¦iZøÜFX šÇk\ËgQÏi^‡Ýürˆr·Î…F+ÚZÐNX›œžWä÷"ÐЖÁÞª}¿âþÁöªÞA]u4ƒ“ËŒåŽ]šÉ³ÃahrÏæЇ‰¢õCèçIIÌ«Ûá¦n`g~Êa;ë»̰kãaJ8K,÷ü>ï|¾ž[v,ä„ÙJ)ÚVsç1äHÛ¹Zʵ´§ì`G£÷0vn ©ùxO ³½3ƒ+÷ðX$ÁäÁ`mð6ââ÷tàÚôG‘â ®GŠÝÅDwìýîŒÈµÁ Œ‘%Üß…ÕSÒ)É`ÁyÞZvø M'cìBbˆ`ÝË·nô0ÊØA~S\¡e‡ ã0Û_Üe7€œâi<Ž'^ fñ$ž"CTÍ‘œõHJ=ðÏóÓz’à}+€KsÀ¥9àR8 ¾%<à#]$nëå‹ßðmòÑûi{jEÑ”{èEøÎy~[‡³êPKÝh:Ê,` PK˺$-"junit/swingui/TestRunContext.classU޽A…ϵþ5B%ÑèlÁ<€R¢Z‘ úa¯5kÌ&»3x6…ðPb‡ÊmnòåÜïž×ûñD€ :„aꌲ¢¸)“8%¶\ص3óÌX¾ÛˆÐMåU -M"Vû”% ½“4±fŸß°.)Ç„Á8ú鎹¼ð-ËÏ_á,Ü: Û…TÚå\ødyïý÷YDª°Ë,f=#´7™Ë¼Pš ýÿFST¡‚*üTª„ê@¹h–„ÐòíPK¥ÞA·æPK˺$- junit/swingui/TestRunner$1.class•TkOA=C‹ ë`±È»à«b»¥øBAP •šF ~ê—Ýd‘Æo&‰üþ(ãiC+R¢MfæÞ¹wî=÷ìIþúþ1Ì È0¶¹v˜ Žlw7²sÛ27#ו~:o€1ôï‹C‘s„»›{³³/«¡C²u«²ÅŽ# t3˜‡ÂI¡£€•z·>¸áž í*Ã¥pÏÒsԳܩé"C*Ò ÃP3¯æ‹yäùïu&åtë†Ár Çöžï) ¿´dÓ»e†R¦s«ÒùÕÏ-™­0Ä Þ;ÉËd+ý0Ç5—{Ñ…!=ÊáàèSÖÇ$”•bH”mW¾Žv¤¿­j‰e¯*œŠðmå7/ãŠ$†TGÜé< ó#—a¤SŽÛD¤¨Ve  _¸€†ì™PÁ‹ÜPúo…+EŽ;˜2‘ÆÝV½ü¿Õû“ÖMDNHõ²°T½éSå—g`†´$}ßó5Íz‰#‡9³Èÿ%ÛvÐî3ô2\Wï+‰­™’úlñÈÄKU0‰ù•j-ã­ý®",Å…&BŸÇ£± ‡,¡é²bfy!µ ¾„FEº§#Yëáá¥9WÉV—Pë-êq@(ô/µ9—F…¬8T\÷‰é­Å’ö;ŠN$!Ûj}ñºˆÞøð/ ƒ%B©§´ü‘NG2ˆÑ„k+½(“¡ˆ•çÉœ‘Û-ìÆGàKÂm÷SƧQ<•'„5ð_øj}7buÒC•PÅÑ,‘6{4I"5»Ç{Ô Ä£5þ×€PìGiÊoÊ®Qz¦ïYÁÿnƒ9]>J|_~{%¶Ø/ïˆWûì}äØe:w(uvnP¾r5WÅhÛq–9öÙÚì Þ²%¬âÝœò™­¥ä;×(ߢñ7£ÚޱúT7gX¯‰N½æ4ëØpª'PùPKRW¹PK˺$-!junit/swingui/TestRunner$11.classußnQÆ¿ìÂvD-Ð?þiQF·½Ó´61D#ñ¢âí&p*šÝ³­¼¯`¢5ñÂð¡ŒsNIzav““3ßìÌï|3þþú<ž¡MØ8Mµ2ar¡ô$Uá€sœjÍqsß§ÑyF&äsÖ&|Ï‹×ãèÌpì!OX1S•4÷ë½,Ò¡Ô_h3e£FÒq¨¤îˆ°ÕÊni …î|Ì„|«= PĪ‚7°RB·åžÒü!ý|Âñ :™Imµ7E³a+«—É‚µ(Ïe¾&£ŠÇâ'^ g<&lгÿ¦~cg¬žò°FX5üÅt§‘žð8@Ýú®¡A¨e =lü IH[ì&îØÂ}›x ÎâT÷Se8À£+Ü6d²F¦M!öçi<â·Ê® |íñ¹m!ï¬è΢$á{²Ð٠ݯÜì—“SDI´/Ñ Ñ6ãw~âfg÷Êß\MÅæìz)ÂmÑÜ6[Åǽ‹{KÊÇ%¥ÞùŽò%Öw/ñ°âªÓ;×̪õDðèz…9öÚUÿ’m£& =‡'®÷)ZîmruÂùPKc_,¸ñPK˺$-!junit/swingui/TestRunner$12.classuR]OA=·]\º¬m©ò!ˆŸ x"ÁøÒ¨©ÙhbIߧ妦l“î,è¿ñ/˜&>øüQÆ;Ã&˜Ýdr?æžsϽ;þþú2öÐ"¬³D›(½ÔÉ0ÓÑ)§æs–$ujX>æ÷ÌH§ÍÂZ\Ôá„Pé~M̈âµ–º7„V1d»GðÚÓ3&”[Û½îðP ác¾‚ê„Z¬þ˜÷yvªú©mÄÓšôÔLÛ8OzV¢´+ì&+u-³u2ÜÉøìFáÝùßZÏ)\-ºõ±J¨ÙüÇç&é„XÃz€Gxlá‚|CÖs ç±€ótÛ»[Æp‘xU7°Í²ïî…%ÝÕp‹*.:“Ç{܌㽆óÞoñu†âe> ÁÖ–lw°×h.D•›‹Óq\W±‚¡ãë…lä ºà—ä†Qnë{‚›’ëeÑ•³Pœ9Ú; 7QTqÒꔪc2ÌFÍ‘£Vž„p ·ejQ§7\Çq|BšïKGÆ.£"=?¥)¡rŠe8ÝŸ°3ŸásÉÜ>©£ùã/ …~Ðz•+ßwŠþ¾”H_QÛÈ2Žo: ®ÿÛ¼Œ=:6e£üÜž°Öú q8¶$‘©l,LʱÙ!Xáë^8X ¬HwŽzØÒbDjKRËnà|Í’‹kø0VV†bÐnJeÅÖ…àó´{¹ å~A~’rG¾Ðúª$]#éFÛ'‘™{ŠáÌÙ'ÉÌ>Áèo¡åXhKŠEˆtIôûjˆ—ÀNÒ_M&[¨l„¬e´G™Ç„÷£Mœ‘bòÍ&Þibîš<“MäÇm¹+¿PÒòjË¿bžŒ g¦øÅ>yø+w’«O±&•ñ¾J |œ\§G„|­»m‘@¿N~Û„)eÖDµ‰ÝÃÒ1Dâ.cŠƒ ÅEZ¹‡óЇeÅǪ ¨ìÃQ ®Ôñ“ò*ßãg凊LHÝ£6ø6jDÁ*5Ø!©EZ°.I}q/Œ{^H* i¤æü PKyë,ŠÙâPK˺$-!junit/swingui/TestRunner$17.class}P]OÔ@=Ó.Ö-£ «+_" û°T´údÂW$$˜&îfß§u³©Ý¤þ£?Ã4ñÁÀ"ÜÛ%,B“ÎÜ{{Îé9÷üâï?¸x¦À\¿H óc“&ìêÜ~.ÒTgÍwï=‰¾:Ra¢ÒƒðSÔ×±õà ÔGS†«(ÑÆü#•4£ÂÚA*Ðh3êd(~Ø)ÇëÕηÔjkbª™¨H'$Ú©vlF$?Ø0dpK hÝ)w›³Ò¨ì¾h·µÒ“¨ù¨`BÂÃÃ*Ô%|ŒsõT Ö6©þX|tÖåìc«¤§2ÃýÕ°bM.0ß¾gad×Í J>{Óév”ÛLÅvhØÃœ€—kÛÕ'–vÔº+€Ä<^øxŽZigPd±Þ3ì¢6úßæ È}nv•ç:Ç[ÊTmSr\ª«à§Î‘¯;‡^‰GÔ?¦j“z—îZð“Á«3< VÏÐøUŸÑé3Áù^JO•TÁpLc†nÊKõPjüM§¤rŠÆo,þ¯óãÎÏ:òJÇÁRy¾Är‰¥M²~ PK=Áã±PK˺$-!junit/swingui/TestRunner$18.class•RkOQ=³-,]VŠ…V°¢ UÛò(X•*蚘4i”HÓï·ëµl]v“»»–‰øúà >þ‘qî–ØÄP7ÙÝ™¹gΜ;3g¿¾|E ëØ!±ïFµðÄõû±[ëÈ0zû¾T¥­† "Ìı¨yÂï×^ôÒ‰L¤¹QTÃEÏ“&&SÇÂ+ELB(´‡Ô¯•8’'z“sÉÌÁ[?:”‘ë&£C7,m®¶Ç áŒÉ]—Ïžêåñ°‹ËUº„t3x% ©r¥kÃFÖB³6,Lg` gÃÄ”¶æ Ù¶ëËçñQOªŽ¾ß´8Âë åjÿ<˜Ö² KcÕp÷XwJÅ>aþ"a&Š„'ˆýH»MÊ0‘ز±„ëÓ¸†„…qü&V¸ÙÂqd–ê„í4¦ò×Ѿ úŠóö„Ú±q % 7q›°8fâ.a"Œ„⹦Ë-ÝÇ ªÊXÉà)6þCFSß]ª}áKu¬cCë¨ñ*ŒÇ™Øâz¡Œ:A$<u-âHGÔ"XA¬ùÌգʎ$lè¥%Ø-í4=rϱɃOƒwL¯‚Þ¶3ÐONoÈÏàׯ%ögØzÂ~ŠÿÙêG\®®žb®ºvŠü»X௥Œ³„úJ’JŽ,òŸ/ÉöJ0R“¯Tß#ÿË„]¶æ>áNñÖ†æ&›Fä9¦…ñ –ñyã–ŸI‘Â輈ű‡Øæ2Iî#ê1*޾jËÀ äu\ÇÍߦâ4…†Û sR(9&wBõI -u)E”t°wr—aç?:Ù÷½¾Ou{ܧF6°©)3d†\vÂò0t"µ][¨*µÄ±4FÃ6É“xÃ0Shu•ÌÔtÜǽㅾ%Ûj.²±°M5Ý FKM‡K)$*4e)ÐÀÒÊ©±£= õ$hé˜#Û SìÈSú„liý#ÞG9¹(KEÌç Ú•÷<.ÐÎp™ ФÿSÅvK°ð+ß°=>]8F¸5±Q‰}'§{#<Œ‰sD <'ªXC ¼<%`w" zônGÉb‘\ªþ PK·æ@ž)1PK˺$- junit/swingui/TestRunner$3.class}“]OA†ßC íbù, ˆ¨Uúm¥ (*Ĥh¤Þ-e¤S·»É~½ô'4&þ¯MDÅ ãµÂ¢žÙ墥IwgæœóœygÞýý÷ÇO„0‹Ç„ËUß’^Î=Ö¾/s;Âõ¶|ËN¢ }U£näLÃÚÏ=Û­Š²§!Dh®ªlc×: ]^Eº‰þûÓlG'?øŽ[¼g·b‚ÖS üIë(¦±„en>Š~ֱ„¬¤‡xl‚Íó üPK’!R‰ÒPK˺$- junit/swingui/TestRunner$4.classuP]KA=×D7Y·F£Ukµ±’èú`APJE*B[ªä}²NuBœ…YÅ$ú*X”>øüQâ1P(îÀp?æœsÏÜǧ¿(a K„¹^®•͹ÒǹŠ¥±¿r­eÖÜ @„ñž8q_èãøG·' DXð]qncy&µw«RÝVÆJ¦&ŒØeš<¡]4b›P=¸ÐöDZ•0cG1î3«/SV:„ò^z$ ¥å•N„oB”1!@¥Š!Œjm¥å÷ü´+³CÑí3¶ÞNÑïˆL¹zÐ,;‹„ùÂiÍM¶Xþs?eö;ÍNå¡Áþ^ûÿW—{‡³EŠf ‘$Ò˜æ§s ñï $½“b]BxæY"÷•3_û'ºîX„è›+öúÂi°Á«(ƒ·Ê·îvñ w†ø†å:âl‹kßiÝ¡ÖZýƒ‰©{”{¹ô:“œE]w o9¦13PùÂÑa+­[LÜcþ+vpí5¦_p —-àƒg7òøÀC¡ˆ1”J-©ÄIzÝÉïô [iÅï·y"m=jæ­E†åÌiµ&Y,q·Ü‘üŒ“kÑe¨’¿÷öÿfsçp>KÑÃø>ŠþŽxg,bÃ]rιçÞ·¯—W¤±Ž†™v¬¤ö¢[©š±ôj"Ò±R",m9` …6¿á^‡«¦wÖh _;H3ÌÛ.¿Õž¸J{¾–ªÊH ¢:ècè×-•6iB5iÄCöòNé–ÐÒ'Æ®$Ü©—“)«u†Ìap%ÒåÕº‹†rÈ`Ø…ƒ,R(0ä«R‰Ó¸Ûa7:„-VŸwê<”¦î53Æ"Ã\â´ÒYÌs»Ü¹¯ƒ°+®Éßû™Ü:œJRt0EKkv¥âZ¸˜1ö§1ËÐg¥¬dq†Üe‡¾8–fƒü¯ò†a1¸'¦8ìð(6éÐiéÍ(fa¾½©v)Û¦Úv*ÏÈWÖ1ro1E‹2Þ­Î(e.EÓÃ8E† LöTö)ì@å#O˜û«ñA>­ÆÄ®§a²y,Xö¢å,aÙ²~ô€â7PK£í&ˆ³PK˺$- junit/swingui/TestRunner$7.classuÝJAÇÿ£¦i[–••ivá…µÝQHA ]”Øõ¨CMèlìÎ&=VÐtÑô Q/… Ú…å|Ì9¿ó?çýûõ qla¡p*©Ý`(ÕU(Ý–ôy¨”ð+õCñ†ßq—µ+î„Òî¥T=oxÔã·Zø)Ä’úZ•B5£X{ é‹{¥¯…–]êØ—TwÀPªF·l´ ¯'âÕ¶ƒILe€ã`É4b˜aÈ6¥gá #üïô©6×ôº¼ßæ¾4ñ8™0i—Èi•:IœÚÝ}/ w†2©ûoùcã[}ËQ¼ò´2]h ×ÂÁ²¿„&¬h0CæÂ ý®8‘F{ö—ºmºœS4ú<D€ºD­nC6óÅèŸDšâ y»›L¦ö‚éÚæ²¶fÖäìËQæÈsÈšl󖻀Å1å¬åÖ‘}Fá/ã“fYF~<Ä0Þ*ж»d{ÖP¶]#ûPKÓš©x”PK˺$- junit/swingui/TestRunner$8.classuP]KA=×D×ÄÕÕ´µ~§J4R×Ç@K©ˆ‚TTò>YouB2 »³Š?«P[èC@Té1 ˆ»0Ü=çÜsïß¿ÿ ‚Ø"¬ £mœßksSèøŠs{QÃY«€óu§â¡27ñYÀ‰ P!¬û®º·1ß±±ñAbujº:·,Ô“„){«óÖ¾Lè–øD¨]>{ËV'Âø¬÷EÔ·Ë);=Bõ0½fBe{§¢ŽÙ:ª˜ `º† Ì¢®6|ZŒúœ]©þP°nš¨aOeÚÕãfÕY$¬•NkuÄb¤ürçœ}K³_šâïµý\î.•)X’¥-g#m”å+Îþ2V ÄÞJ¹0¡~™YÂÇÚ¹žU÷‹ž¸âp¨òœsìË-ª³Êk¸ãH¬Á}òꘑ:”¬#µï´!jï>bá»Ç4`Ó³žô€ÆPKÏ“˜ˆ¯PK˺$- junit/swingui/TestRunner$9.classu]kA†ßmWí¶F›X“hÓ/¢!Y/+ ¥EZ(H[jð~\§fÄÌÂî¬ÒŸÈä¢? ?*äÌD(”îÂp>ö¼Ïygîîþ ‡#ì¶g©V&H–JOSœÉÄüLµ–q«çë3±Á\èið}<“¡ñ#4]W,M R›àShT¤*1’¥žž›s•´º¼aµâ„PþÖæ\²âTñܦdKÚ#B¾M$!wÐù(áe y¼òá¡PÄÖ åÒò[z1–ñ™Ïy¶:ˆB1‰XÙzÕÌ[‹„Fæ¶V-–…»ÜÿŠâ 9!첿ÿÝÿ³ÍÃzÑCPˆS=L•‘>¶­û-ìH:'Ù\Bi¥q(¿(k¾üzlUÿ«-ús‘$2A—Ÿ"~U>Uû6‹°ßŸ^písöžk×éÜ¢Ü9¼FåÒÍTÝÿ¡-Çy͵ÏÑv7°É‘PÛå#GK)t®P¹Aã_ÆÔlóÇÂ@?¾!]‰)+ý,)èXívõb@Ф4À«~ oFcáö@&çu4„·†³XnðoÑŸ‡uÔ†{!ÖÈ:(Еä*9õ+¦,!A£Ò­ìÅÂ!Íô`Úþ)ÈêXÀ'~B"1¬7Ú a Æe J~[Î+7ÛùÒÆù¶*à ÏÐ+Xúü£Å¿EPY:Ûhg&0uxdžh !ìoǧÄ~gîOg íD{†u8Úǰ£®fôÆ‚]s7Ú°] ²¥®¹¥vmCC]-´î¸ÃëZÓU¨9\ÞmVîêÒ+k»üѨ—æ@ «kê6¬¯[Uׂ—õu›l %)rpf=mã×éxž‚DgõhÞŠubÁ6hüAAnì¥|öFl_-´Â¢E´Ø$ƒ–~&3ZfÒrZjÑlª( I *æ]iêíÞˆ@]æ-ÜæïÚèù·3hÄ:ƒÑìMš6ëO·?U]~T¶tfo4DåÁœ#1‹VÓ*YƒeþÈV€.ͱ ¬EX%G–g‰‚9.É\à¡Fp”1ÕCk!Õ­X“íÊgg#²èZoÒ:j¶¨Ö¦l3 ö™üའ´ š[^ŸÓ7,Ow*áí,7Må¸ÁD6}ž‡6 ª/\¨ÿ7\¼ùG›tÃXSt¾™ÿÜEÆ‚ä8l0´-|b ÁÓ&’*`ÆíBôÓ“Ž'V·¨¶blpn¢à±c ï‘Ið±›yïYŠ£Ês©@gŽ®ìíèà¸q"TŸéÂÐ2Ÿ—º™ÕLê"x¿|OO ¨U¹ f Ù ±å'Q„!€#o,l³¨—õ ‹¶a°'Õ‡:Âí`\’vòL°a+R¿Ö…Ú™Otg¨­sC½E§²ùI:m¨}Ÿï¡3Mbßí½<ˤ3é;PÀ¨&ÎFëb:úXTJ#ÙŠ¿ yæŒ@:dBóëÚƒ:ôLrt?131Ñþ‘\@št>]”¡?éó<ô}æ8«º3örí–àj4ý—Òe…t ]¢L¯M¾åooo Š Žì´©c05¬:åõ³³AYôcº‚‰º;8©×ßçf‹~BW›ÔD?žH ;¼-€m6hº–®cP×ã{0 D\Ü£sÔ+n¤›xÅÏàmXðvîv„óÀ‹vÙàn8‡RµG†.üœnãÏ·ãsüXÀáÚ¢;l%¹“Ý!‹¦Ä6wûwtÚS¼t7¢`®‹ ¬P[ ƒFG½ëOÅÙå÷c‰³¾!ÚëÄoÛ4œ@#¨ºüÿèPÆÐXV±ûܼ.}¡ØC°¾˜ô =ÄÞi‹‡«Ð‚º®@w „Pð(]fÒ#ôv)<zýËízôGÛþ.—þ²AègRŸ¢§Y¨ÏÀD6è(/˜ÓëB½Ýˆ?DBcѳô‡Ï9æ“5ÅC/Ào…•:¤fWCG/Òoé÷À—Ó¤9Â{è¥Bz™É+îôGÑ@K%ÔÊû ½ÊP^ƒ6YK6Ýøº-;‰LAÄ “K¸7Ön¶cípÁ›øWA‹ÝÿÁÓ]–í_èm&þoŽ×k¶•¶J½9H´“}ààþn‡þ!hÁþnð]]Dï›ô}€¼¤ ©:'Ý©)­öhC%µãÿê¡Mú„“’á6h;Æ;GgøÊÃGdzès$0z¿üÛcs×D‚í þØý®²¼ÿÙÌ|eÒ—ô5öϱežnOmô‡ü[]×ÿ_“¾ ýÐŒ\Ü#Pf)HÎ+”)$!@ùhvXägøíš-ˆþ¶Xb—c Âïíì70E¡) „5Ô.ôˆ"Ss8ã­iced£è{j ?0ÙPlnú fK #O©#C=™ë>¤ˆñb¸hA)ÀzzÂ!LDòôAKŒcM1Z”q ’º#sïÞ˜äV§•ÌÂìÿ]ŠÌüF)\BŸ˜ Ÿ,|\x†#vì›ñ?Û™­%¦ŠiÈEÅtí}¶×ë ¸-`‰™ô"Ï‚ÚM¨G̶h±NT Z ­ïj÷…Â1ŸÍ½ÏYáK.ñÍñõFA¯Ýö×¾mô ”/cÒ丶‡·•¥és¡ ÑÎðöFT¯ÐÝUAWx« Ù9·/g’ æ‰ù¦8@,€dÓUÏ 9X[dŠÅl´¥I€u;Úš.À‡]A9IÚ¶Dq•žšº+°§Å¶PÛüP/§¶ÏÃ\ f zÄ·ÄõR¯¨1Å!œÂÆCÈ?B\¦åµÌé*QÇÊ¿:3Yc(œ9xÄ¡ˆ\5츫««½â0SÔ3°ÁMr‘G4š¢‰Mò€òlzèò|èq¶›u Wa§dÍ„û–hFr‚-H·|u;‚1ŸW YÅ,öˆ#MÑÊdÝZ|¥9…§ºƒó²Šq— ý}>dçØ§ÝËÉr‰nΈìQØbŠ6Ù°®°¿]Õ·qsbDyŠï¨ï†ª‚ÿ€è@º  ¯Eî7r1‹Ó[,Ö³ÁQy&ÞÒE—)NÈ‹ªéV(Ʀ‘$<ÝÇmXô€JqR"éàï+Ñö@ĉššWîÄ Ñk¢¨ÚÆ)t fO°ÄDx¼CmÊø¶)NáM)vñl †Úð Ólnÿʇ§ÏÐ<Ÿ!Î4Åéâ,n>Ù{dµK2%„Xcï¥Ý£ÊÚJ»KeÑ|ZÀ~ê¼DŠYm{µêôÖ¡W\ÀnÏ5র¶j¸‰Õéíu‘ qQš[pSY@ÅbbOe‰KQæ‰KÄe¦¸˜5Æ Ç®ÞìðŠBb[íÍGîpê½$»1˜+Oðǰß?W°š]™©²š{ø‰[ˤ­³7ÿ§¦¸Z\#H¶Ñ+®Ã&µH;߯@$ ÷ã¼±.-8Ÿ<E‹ ¶[b3{³¸Å©¯SëDÛ9{ÄÏ*Öwµ{ZóZâvT½â6ñ A¾ æ›Â1[êI¿ËµLó”hŽ¥ñãÚ5Û{ÔÎã3Ý÷?YÃ+Xb}ÌVŽ9:§<Çú\¾Nû¹}¦Ø+î…,º·èæE.Änbà´‘D›0YCäê ŽïÖºì†cK"5¶!Xâ!z•“€_fèxDÐX{½OG­@ÔÓ‹ìôE8½{,wÑ·ÙV'Lñ¨@‘t0höù}m½(ýºm0¾.M/öElè±Î€‹ I*–§ ÿÁÐÆšÃ€ÇÏØ4ÿÚN7£A%~Ã9âmÅRAoBD(E6Ãooa!•ØâKmÉ”›ÛJÜo-õˆ?˜â%LN,7:¯Oöš_} G¼jŠ×xµS-¬„ˆ+3¼r"5:ä¾ ïaWø'ƒµ%æqËß\]¼<â-S¼ÍXó·h|®8R›â²J•´¶øØÁ¾yÄ?¸"€ý¿'ÞOBN9€ÈVÐÄ·–Ú ÷nüz+?ÆVÒùâH’£JpkglS€ÿ\îéíqŠK|jOû ²t[H®Ì,ñ…x£.ÿR4ó<â+S|­7$[ðñ_¸D¢Ã;“ahrVJùÌBÂ;˜b¿”`ŒuÛm&+D ¼Èyp+2Hzç{¤×”:l‚.ÎL’„ù²Ký®‘J 2“Ãa(ž[¿6é%e1¼d›½iŽ‚¦@ŒÏÜÉ´Ã1ƒ|òÈ‘¦ÅÊ‘q¶ædω„#hÊ U¸sþfGYfʱrwGãþj{»>x™P>(qÌüD9‰—MF&‘âÐ` â´uît‰™bÊ©À?&¹' ã·“,1QLâ·¨EÓh:OîÍt Ím‘pW—Íáv»)ôØr'<¶¨'»éWFtjyŠ)wÈS-ñŽx—ñnÑšÊøÎ´Ä‹ö¾|Ç¢Éö¾œc‰ïŠïñØw-*£q>ª¼q‘ы҂ºÒ”WÈ«ìÌ9­ú“&ßDñÇ„_-ÊšyöBm'Zò:®¶O—×Û¦ÂG¯),y#—~ûåMœ†é”Òέ­-i ÍÈÜéLwýŽ4 ¢"| Çî•y£,}8¶!·„8×ÍÜS}9#æbQ¼Ã”wêÞ­øﶇ¼òNy—3²Ó’÷Ø#}|ꃑíÁöX§%ûíѽgBma¸‰{í¡hÉv˜ ¿«,y¿|€Çä« Á®.KþÒžø°;Xµ'=–ZøÖ‡ [Ðø„)Ÿäîk~P¸GìÉ9pOɧÀ3\:ÌG¡-ŸöD‚6DmÁ¤ Õ0/¹Àæ'6 !™å¶ê|ë*Aä•/Û'Òœ?Xò>=¸D¾j{¸äõL—zóÃ9¾ÚÐÓîçNüô\ApU¸­—£JÝ6[eõ!ìŽX"8É?ëS(‰ä6O/@rð?¡@d¶ê»v=d'Üû©É)LÓ¾CÒ—ï0ïæLéí`É–üŸº'ElÇœ¡ ÛÖù)ß—ÿ„ ƒÑºîVPÚ`ìcAÇ4…í¿ÖoD(f«M]–¡RòÇìr)ênÅ^´ûf¥!˜å F}ÑÞžž0ŸfûP…óí_O—?†Òª»Ú+ÿ•ª}v_Ô#?ã®ÎðvK~ÉËÏå¿íVƒ›hmø Å:ˆüÚ¢sõ©³ü/w4“R0çúx8sf.©&Ó\p<ÊÈÕ5N›“Õ0viôª|n¤Bov÷t2pxMUÀ£¨-íÎŒ aÑnW—Û’QVF×ý%î+xT8fCâK•ˆS«á™mFw7¥Üt<šSÈÒíKöõ.l=jT¢`Á·ÕÁ®@b|LbËb1Žò'd‰²Ò™¼ÜRe Ù³Tãa/åéß´rª‰¦«&%‹øj£p¾ûL5ZM±Ã¤Ö 5OIÏWÓÁ0_YãÊÐR3¡,˜8‹ËŠ®p#³¡ZAš+·¸î<›CÁäyµÑ¥KT.í#Õáî€W~¿fg”{Ôj¾í¤ÖôÀýì´ÔB1ÙT ’X+•MZ‚}¬ÖJ ã~”W(hVŽœ2×U–ÁrS-U8&hÈa¡G}Ëvƒ0æÆQcªCÔJȹÛî B?øÚG³sÕeœ‹Ã£N²»CŸ­®¢…*¢@Ͱíþhso[T±£·ËRÛ8^Õ(¤žm|ÿumGÆdâ -ǤکN6©I}zè\Ä«`¯:bpÇ\›¿¥NçJ´F|Pȧ?{ÕYœBSlƒ°ÔÙ¶®œ¯mÏôuØùŠW}W‚n<:ê>.'무œG¤Îut;oײ0!dc–ºˆS”OÔÅ(œÔÅÚÉPGªKQ‹ Å×FÔel1½¡Äý<¾—¤Û×êGܾ.P?¶¨˜JP–¨+Ùuö†œË F4î±ÔÕŠkߟ0"»k©k¹*ÕuvÔ¹Rj©¸+f¨ùÛÅœ@²±¹©·ÕÍ–|‰o‘Iu‹æÙÒ¨È]NçV­Ÿ«ÛÍíýÈ–ø`³=¼>ávÛŽa¨ FNÆRwƒhð|ð:>Œ6ƒQ¯ê·ë»rpª‰ŠÜõnNg©ö©{åÀ^q±GÝÏWfÝ¡9ö k¯BÖ^÷¾2˜Ûþ¥©P[r…üÓô(¢e²)4%·Õ¥6„Ôãê Þù'ùv‹æSiÓ¦Û£žá»ªˆ©¿VÏræßpûYÙæT NìùŒì!1þ[Sý.#êÛŸ¶~oªÔ`]úþ–¥^æ›PMêPýí­¶crh‘.ÜÕ«ê5^þ'ì}(°ÝÎÞ`Ê_Poò:%Øž+%php.÷87Ò†Øä%õ7&÷^Sý]½Ã]o§Ò¢ÝÎó:é\H;Ç·Ôû¶Ä?°äŸäëüöaFŠ—¼.¦>¶ ¨:·E¦þEWªOÔ§P~ûʇmŸ«“T_ð6%QÚ}ÛÁï®i]øR}ÅåkÛ^›ùšú/ÝÆXöÃkt¸5Ù˜A+2OGßÄ!Ñ™â=j™D}jiùì©Þ3<пžH˜½tMdk¯s7lVÎëÔ9<¾Q`˜ðF¡%k%_a6†™b¿xÎR?Ñ…žQ2ä¦.õ#L£”oZ 1ë@1Ê4FsÚ>̾A\jßäÆ,c¬¾)l”i5ŠtC:ò´£=œ™t§Ã˜h©çlz& RáÞäahä:°‚ä –× †¦S ÔcJIß„fÅ|l€>VS>»ò%®K3R:î)@<RcOt…,c6m”Üì`š«è:d¯ÆœTRöúÜ’CŽþŒlÊçñ&^æt$ÝC⩃öK熱¹Ö7€§…Æ"“Ö‹Á;B¬e,µyDj\¶É±ï7·¹ÉœNå¦z ’?ÕÇí^ãàdM‘«½‡ñ-Ô>Æ!:JúO><†ôù¼êÀÕ¥¯À,}G0«a©/ 8«±Æõ7_a½ij–}1ÆrÝÆf•æ¿Ñ°t¨+ÏCßãK@™÷Í  ÒO@AsèÿO0J¿${/ß|•FsþûÊÀ7å5ý¯%€,L¹¯›ˆ?ë/«$Ö.²Ôa¶®nN.¶ŒÕöà1ÉÁ%É×¥É×9ê±6²$d@Êû…­ú:›t6éÜK›éR0Ó¡À /ù:½¡½©‡Þ¤?ƒRƒë<‡–³ôo¬OÒ26• ¿µþ®\zÞʤç<Ðs> _)œßzQ =.=ôŽCÏ—žB—žw]zêË6@ïµ²ôÿ™ÃÉ\ §w ´àªæ¢æ 2øPÙ;ßq°Þúö_»]ˆùzü§)ŽÕë@2øÄÙY¹Ö¢Úú¢u€¾lU†Êë§ÿô j¨²µTý"¯Ox*îÃø9 Šá^DI\Œ¬äßq1nSeõT%ºñîHåFÈî&¨òÏàåo‚ƒ¾ dÜžÂ`­CV) Æ‹ Ì „;^áèTÕˆy{Å”†ÊÇi¢h¬Ü+f4VÅEùC¢bw(¨*Õ{ű¸µ_,Ùµ|T]&L£h7„²®ê.|½a¡sâˆýˆ§÷¦ìn•CQ>ÍË´é[4V,G‘˜mÒëâ Þ]¾ÇèPù&ÖñÊcÄ!ÙÊ~QÛPYrX\¬õ8¼_44V ˆ&ÛZˆ­ª¤+ÁÃúM•q±Áž¶ Óšæ ˆVž¶Óæ”ìàisô´¤€WêÄâa(Ú#`ãQÌc0‡Ça4!xžâ׫¿°ŸƒxŸG8~¡ôyû—à÷_¦£è•vqØ-¤õâ(q4Xš@5âq,°ÕÒ8qÞ˜Ýã…ßa÷‡Ž‡Y2 ÚlvÛ@qgcÕãäe¦Bà)2 b­Jõ‹íqqrå€8…™:5.¾“ÂÈL•¼Ôo€¥7á¢ÿŒ=ù 4æ-÷6Ôû-hÍ{)¾h‰Kl•8fƒŠšf‰sŬ'|QÁ!ñ!°Æó¾KœßúMÜT*.„Ö´Þ-Îß…X/.Þ|\\\Þ/~ð`©øÑ^q“Žá«[«úŵ ðÙü^*®ï74Tr°.7!Zï·Úñ:.î¨Ü­í¾ˆF‰Ý?ã 3ã,§¡7Ÿ`>…?£ÍôyŠÀvxXDJìÁ9eÎ[9-7winî÷¸y™~ÍÊŠ¸ˆÇÅÀ¦ÌÐû$ùuŠU™®Û0Å}â~mUˆxÛé̸‡‚½ÇÇ÷‹_5Â’žo{ųW’· ÿ|Ur»lööó?Æ@Ãâ4I(š&Œ”-šá Î#ŸxAü(‡ÓHñ;°ÆL½(~ïqŒãËl?åσ¨ÅK¬'/³kI"ÖY˜T( ÉÀÒ1"…ß2W/ŠÄi’æ÷U‡ƒjRÒ¥5TðfÀ÷ãûS:>ͨ |c¨DŒ³ìMÆÒ19ç$g)rUçëâ g§ƒÓgãü³ÆY*þÊš3 Þf¬Ë…u°N§b•Š™4ÏI¢*«ÏÅ:JüÝÁúŽx×ÁºÈÉà Ä{­ÃÅ)ý⃌˜ H‰ …‰˜À7³?s”ãà:îô#-©!ÉŸ#Y½xŸøRЀøšøO\*3éÙEFcå€,À 4ã²HÛÆL8¢jYâ Ÿ”$’W,¢ab18\ î„ò,…Ÿ]IÕ¢–æŠÕˆkh)žËÅÚ®võÒ" ub®ù •CòÝŽÿ­£Zóûåè†9–ißÈñ¿*.'TUÆ¥o@NåÑiM<:£s0:„ÏäáYqY™²:wÍT 6€Øð„›h²h¥r±DE‹Ä1´¾qž5¢=ÅÀkÝRh™¬‚¬yrެär/çÊx›ä<7‹ÜàxVq\—‹ãò@ä* •ûäA‚2RÑ ’‚0ÀrØÀòȃáIYF+ä·²RYÓÚ/WfªEw®Tözù|Љy/UÄåêÆ±@Ö4U@ŠõUø£A;LÙ‡¹Ì¨Àœu}ô=~®ï“-Ø€#ÁUK\‹‘ã—åñ‡-}²½b@vÎÖ>ä¡ûd7J£G0ê£ûy¨§O.À#²,ŸÅúä¶¹£À¶í“߆÷]âë—§-óð×3úäYü<»OžËÏïõÉóub#/Ä‹Ô,óV”yË ¥òòŠK†÷ËKñSW†‘(Ë3 C%¿ËŒä•˜î@»ÊËW)dPå§”ççå3ŒBw [yò’@äå éÊ›²Ê–à AUâBW à…F”yúåO–0}ªÄ“g$éÍÏ+ñ0}Idg©’†¤øÜ¼’‚UeÞ¸¼›rCÕpzÿ—?Kqó7p?Aœ7¥F¡i1xÛm°ÔíT)vбJ2­§Pƒ8•6‰Óè8q ΢ˆøíçЈÈ?B4¾FœG7‹óéq!= .¦_‹ï#ß¾„Þ—ÒÅå¢XüXøÄbž¸J¬?ÅÕ"$®§‰kÅÅâz¼Ý(v‹›ÄÃâfñ¤Ø%ž·ˆß‹[µ®vØú˜ˆtx³‹Ì<ñ[HPÿ´Ž~¢úäÍð°¨þÜ%oADÙ”†3Î|PºRÞ*ŽJâ1NÞ†1/xÚ,o—¿ ¾ïx±ü¾mb<æpIwbw/3Ë̉}òî2s”Ñ'ãxäõÉ}xôÉûÊ̱ž>ù~å÷ÉGFå×RÁ¨üü먠Ì,î“—™òÉÖQÆUä-1áBÕÄěǃÝþUŸüueUüéo2*Z²Ä4Z܉tx7MGòP‰¤a¾¸sX죭"N!ÑŸªÜDJ–ÏéD›ßž‡(¤~{f¯ôÛoñfè·ßá-O¿ýoùúíEù€®YÃ|â) ù{ùà0øXÔmua<›×ä)•Üí4öÉ׸ kJjœíÓî%@ô»/Åwˆ|Žä€žë€Îã‚6Ó=”²8Ï]ü†|ÓY|°®äyq\þ5#‹">–âQó\‘åÉ·äÛŒWþÍuÚ7:Qg @ýçýV.E?Dq"?¹’ ”&òS”&{0ò%þ÷Ÿ¦9È‘ÙkîO"¯ÐŠü$÷W0¶§j< …}ûú,¢ÍohŽxŽæ‰çm^H‰2KÜ– 7… 8úbçMò6gwR×ÒR5o¯ZÜ0 –¶V–ªeýêहÙól6µî(u›T–Zá´Ív¸-¿dDÂ]U›Ý‘‚ 0Ç’žÜ]µÊˇÙ`×h°‡æ[°&À¤¹°›žªþ¹ 9ÞnÔ®Bòê$Ìaß:-W~§šéÒ¹¢ª_‘ч’ci„„ùÉq4Qާ©rBJ©5ÍÍø†;_™j­î@K¾[æD­+ V—*©š¯¢ ºý\ª6èþ³:ÒiA«£öÀ<¤š›*âê8|hÛ§‚’–eÆœ¸:a¯êiÜE“Ý ¶ÚÉ,—UeÆ>Õ+ J~ä²<6ŒWÒd½®,o¯:+KÕiîÂ]TÃsÎ4®ËšôĤsw9d'¿}ÏýÆf4 iw­ë¤š ‰$'#öÑd9…|rd7fÉY´X–S­œMu²‚Ž‘•t¬œC[‘œ‡‘–÷")?UΧ+åºA.¤äbúƒ\¢e¾^w‘Ü|ov/r*ÅÕyZæ³hZ«ÎÇÞ,†¢^'gPö„œA[é$u¡vG½Ô¦Õ81ÿ"WIN†>‹³Å¸ú>§•quI²ó†œW].H÷qÕ’Š¢ G¹ Ì.§"y†2L–+h&’ÿd4œ•HêÕ]ËIÔ£ØjÎåLÕq\]Q!úÔUýa¹ª]KŨFʺÜŽqNá Š›Õ‡Ú««§aÜy«kvÑÜ ¸Ðëãê&hÛÏ*JÕ.h^om¨€Vý‚ bSu'[Å] <ÌÖCë‡e4À2iºl¢Ùr-Í•ëh<‚–Êõt°Üb-+:gÃ1Ú™â\ø†wk¹–^u(^áä#÷Šg¯¢bN÷ãªïJÊ3nW·SZº!LðHþt¸üDßw«#àəܗ0×¶˜Ç»2÷ò°w,Ø;žFI?XÜB“d Eä“]‘OvºÂ’oŒ¹gùzÖÒ ½£jo¿º¯b@=ßXªêW`sQ©Çúè-&¯¿b¡?ÍDÆÕo2N'd'Ê êÖ3hš<“*åYt€<›–ÈsR(ZêR´Ô¥è9(Af}JÏ®hó€zqôwN}±_½ÔÀA>÷HÙT9GÁó¼W¯ƒº?§ü¼¢£(ÇÔ¼DL50é/·{tÔƒ3 ´üJ~Jåù4V^U¹ªåE4¿k‘Ú7ËKh“v‚GPï¹ÛêhÓDö Pž"öçW’Çàâ]t韙¯¥1ò:š ¯OÙ­‰.‰Ž“|eËAsæpÖ¿(–C9>Òάª‰ûÔg™ûƒâêß•7këØÆÞþ?’ö ù™Xµʯßÿ¢ë®2ò\y"çÏ „›á«vÑ8ÔÓä­ØŸÃto¦ƒäpÌwjZÚT¸´®vh- †0X…4O݌2PÅëL¦Õõo5ŽÀ ¸&®Œy™a‹åÝ)‚)p‘¸‰ÆÙƒ‚óf‚‹\np‰ƒÿaLܹÎÙaŒÏ°+*ªâFQŸ¨â$Å9?Œ¸Q Ohá“Ü_7†'1ê<\ÞOù¨ÇŠåƒðúÁK<Œ0÷ÂÜ£°ÓÇST¬Ê¥¤Ê9GF®Ý ³´:ÇA•Qʹ”12‡?…íûtø…Ar)G¥øßJtËA[rÅÆèÖ~cÌ^ct¶a­êPöDà¶CÍáÿ^¦a(ùŠŽ%]lâÈ]ã]ÐÝ)FNªè7|»hXÃ]ÆôRcfܨT{jFäõEn?Òv´¢w0ú.Dø8‡÷a(ä0”blà놮<ù¯U¥på¹²…cœÕ5)æ7ægŠî#ìÓÇÐúOr¹_?s@/v‚îæÄ™šöÿ™µ²='ÎÔ{8vGiÖÊ@ΕÆÖLœY+;`-hÉÜÌéY O0NÌ¥yê¾Lœ?ÈZÚetgS›–ÞÛH'd¬”FHÿ6zð¼ yÐQz|é<ß³Ÿ¢Øy69ÏVçyŠó|Éy¾æ<ßvž_ÛOYàà8Átà)fçX \âlàª'\ž»G8ÿPKòµâŒPK˺$-"junit/swingui/TestSelector$1.class}P]kA=7‰n·¦Iµ~5­JÚ”ºí›`¥*A )yŸl®é„ílÙ™´øPê_´üþ(éIÛ…á~sîÙûë÷Ÿ(cO Ëã‰Ñ.±'ÚŒ&:Ùgëzœqêò¢½ cu¬’L™Qòq0–I„2¡ºêÄ%|ÌÆ%¯S§sÓÕÖ±á" ÂMw m{Kvt¯^ò‚Pí}6î€N…³£ù’°ºvi½O¨ìæC&”×Öû1j˜¯¡‚Û1"ÌUQ¡ÞÕ†?L\ì«A&Øf7OUÖW…öõ¬Yñ6 +×ìko‹Íº ¿¸Çŧ¼8äáÔãÿ®ðÖçÁcýÏüVY>ŠpŸ µ=Ê-Çxè]?À#q8ÓÕj„Z/Ÿ)¿ÓÞtão{Ï<¿7rúÝLYË[r„ ä¢òšþ*«ð_I^ ·¤Ž%{.uèt.Pïl|GãkÀ4ÊONƒÎ¢d±Dß½ƒ» K¸7Sy%Ñcç:ßÐ8Çò¿gâàKÐXšâf>ka%°Wç1žÖTh^PK¡eÀì”®PK˺$-"junit/swingui/TestSelector$2.class}QËJ#A=e¢mbkLßï! h‹+AE„ B$ûJ窕i«¡»¢ø2ó;êÀ,ü?J¼UÉBÄXPÜGsî£^ßþ¿ ƒuü˜kµµ2Az§ôU[”šEš8)oy£-y+ƒHê«à¬Ñây—•w& [Ò&8ŠuU¥†4%ú̵JË›\£Ú»ÈŽ@®v¯Í52gW1rO`qå;Òj] {7I ³²Z÷‘ÇpYŒøð0˜CF U¥é´}Ó äB6"Æ–ªq(£ºL”»É¬mS`á›zå-n³ ݈ç”\ÆÉ 5;=~µ…#ë»gzkz˜ÈÇ¿:15}ÌØ¦1+ È-­·63kq; éXÙŠ…7,OÀ?Ñü‡‘LSJ±É+É‚÷Ë·dwÄ6{úøæ1ıÏÞ6Ç.Sù‡Beí Å¿Sr(ûòàtÆØóÙÚ쌳˜ÀdWeŸ­ÅVQ|ÆÜgßÜÁ§1ÑÁu5¬7Ç^tœ%,;VG(½PK²®¦zŒ¼PK˺$-"junit/swingui/TestSelector$3.classQ]KA=7I]³Ý¨‰Vm• &¢+ø"´%¤Pô!’÷Íf0×YØØþ ±ÿ¤`[èC€?J¼3¦P ]îÇœsî™»¿~#‹l*£TÉÄo¤ºL¥{!â¤+á'aT?¶@„¥‘7öÜÀS—îyÄ7²„]ÝýüÌsÅX¨ÄíÈ?\*]%" /sÉPÆõ#žÖ™>î-!ßý¢’¡H¤Ïœw’‘§„ÚÞ,R£Gȵ d÷=6 6rXp`a> –‹©ÄYzÝÑ…×[ꄾô¼HêzÒÌi›„êŒyõc¶éŒ½ ­!¯D  68{mÝ2VËÓ¥-¬ þPøWm¥ rPÆš×xC 6¸óƒv7L#_|úYÅ¿§j~ÂGÅ?§xq,bñšràó)é½qÌC>6^rípvµé4b±¹ÿÅoS2(}skt–9s8êî ^q$¬bm¢ò~¢’oÞ£¸ÿ•EîØÀW#²ú œˆèlU–É f8›Ø2,28 ôPK¶e2NšÛPK˺$-"junit/swingui/TestSelector$4.class}PËJ1=±µcëhµ¾µZ]hE§‹.E”ª 7-u;¡FÆ™¤¿Dô/àÂð£Ä›´ˆˆ6î#çœ{r?>ßÞ‘À&Vò—PjOueØîH¯!”®‹@´t+˜Aðîñ®öĵw&C?êøüZ‹ØA‚!¥/¤*– Zû_m‡!]¿ õ…вEœ]IÈ=†ÂÚ Òz“!Y|ÁX[oºÁhI¸.†‘Jcã Ùš Åiçê\Ä ~6W‹ZÖm)jµ Tm©¶núVcÒ¬6iJ« „÷nd²;HøYMZ›ô¡? ?ªé£ Á}˜¹_çÌ9wÿþûýI¼EEàÍå(TÚÇ*¼)¿I±nPŸÚz•¿Ðd×U¬)¤( !P¸”×Ò—cíÓ5…Úç©9Ô¦H鮊Ëï6ë‹©?d“PwI«6cO lUU[N0è@²RmyÈ`É…ÏÃ#¤²Hà‰@®®Bú6º:§¨)Ïû<»\´e¿%#eòYÑ12xoÞ?ËÎôhÒœ ©ÃYìÜ*NL`•®/h¦±&à^æBЕ‘5xxŽ‚‹uŠ‹5¥±É†z·ÂL+è˘8•À¬ä¶\”°- Øea¡B–ÐŒ¢6}Rfùû€÷9dÏ–žøüÜ:°Ã+w°$óøNÃ|¦šA–s—³÷œ'øvk¿ð¸¶ÿ¹ïvæ)Ÿ|EžOÏÆ.s­XÎU<›1ϼÚäöo°qƒ;×öN±„3˳6ñ˜è%^1Se‹y]‹2•öàüPK0•@­PK˺$-0junit/swingui/TestSelector$ParallelSwapper.class}RkOA=Ón©Ô•–j‹å%bÅm , ñƒ<C4ihĤ¤ß·uh·Ùn›}@üY$¢‰üþ 5>Ð3 )&{fæÞsÏœ»_O>AKx&P˜þ¡í¶CÛÜ“~P—Žl}¯øÖò,Ç‘NýÐ ¤—„Èt­Ët,·mî6»ÌK".0uÊâ…®+=³Þ÷éÏË#û»AGzÙZD¶c6¢6ë¼ :¶_\˜®]/‡y£õ÷.i»Åš ›™[«ÆMEWÛ•Úvÿˆ¥†é4dtŒ"5в:’¸¥Ð=tÍvå›°×”ÞžÕt¤zB¿e9 ˳ÕþìPSOX¼A˰Ÿ|P¢êŠæóH`¸*·ZU‚3ÃçIÌÐ2÷¤¼ rFµTκŽ˜Kat_¯. òÆÕôªò㊪â1=>°œPòYš#÷Y"ª”ìÙíq<è ÎÇy™CyѬ ¤êýÐkÉ×¶ògü²˪ˆ‚ªêsÙv,ßWM&¯·.‰UNbÈ?ÌqB(“jd\³jˆ<» õSç:îp?F´Ã}œ1]þ„ñråwË‹ÇÈE‰y®cÑõ7R|'þ îòI÷Qˆ(Ó˜d£)§0}F|ĺÆÍÊôGÌ¿Ð*•Fâ…JA#\(@.ºJ(¤þÿ.$TÎ…ŒY¾øÉõÆñ›­ÿ`'XÃ_lD²¶NžËÚÄÊ2PŠDo¢L'ÏsT°H¯æ)z‰(Áû娟‰FåXŒüOûPKãšKPK˺$-1junit/swingui/TestSelector$TestCellRenderer.class•UmSU~.$l––H¥´-ÅdyI-­ÚBÑ6µm(-Ê[-¾õ²ÜÀâ’Äì¦_~ˆ3Žã7¿ôCÑ”ÑÇ~òG9>wwy 0£Éd÷îÝsžçœçœ{ò÷?¿ýVŒà[¡õzÙñóÞ3§¼ZwòóÊó甫l¿RÐ庳ª¼¢jªf@\X—Oåfè¿­J²îúÓN³a«@²4­d©hWÊééý^zo\ Uš«;¾ -Ú&Æ1)КÍ- Ä •e"d 1´ tÌ×”u#Ä:zöc.Ȳ\ÕÜ'ŒU凸ƒÙ€:ïJÍ,¯3³ñÜáhLœB:…Nt™ˆ£-‰ôœ Hm·â©•ö´ #|ÝË×ÓNY=¬o,«Ú¼\v•γbKwQÖýmÆü5Ç™þRSž³Ì¡YØBe£Z)«²/0™=Å”6?œkqi)L7/Ÿùù]&ü*úµ¶¯ tîyÍù5¢¸@ÅW¯êÊ­p«IÉp3RòÀ–‰‹LQ 77]Wgæ%c½=_Ö|ï‘㯱xG¡-™Âp ¡–Ó“ËÊ5gm½Úöd2·hâM\NáÆBÛyµéÃGÛ«xKÛ¾Í2¹TP ëYâO¥[W;|@a&¶Áfu‹,Ѧ€(rÃñÂʪn, ˜6‹xOzw*v­ lr S Ý•žàÏ”h¶˜+šxw´Rw2Í.·ê¥’> %éÕ—½¨‚=t<ª`÷1­‘P¯ MMrü¹iržÁÚùC}X)åæx†ûGúXà©–Õ*[W`ø?5O7Aá# õ˜¹e‹Çý±æý„]æWvz´;{¤ígø\Ã=¡6¥ôÊ Ö2éoUUTµÔ†ôí5åÝW[šó0H!·tL±6Jºã@›½&k7ý°HÖu”_°¯ö< ´‘lVhƒÅõ+ T©VžÙ‚ö« šB_²WØ/-6OŒ(ðç0Ô¹J½f«;Žž-§öO‘QMÁf+–˄Ӊ*:Ÿ9~ìøŠ§¿yö Ÿ¹Ä^¡‡!ôÇîq=“yMñé-ï§­—0­ô‰mtÿŠŒ•~%Xœù9€èã5Àãõ<:8x2¤8Ë3tç›ó¼ =’"è¿H—à}Â>×뉿Äë×Û†ÿÄÀ6²×^#m50úNXÖ/8ÓÀ•ŸÐ®—.­^£wzÛ^ìòŸgøà\êÀ ¹³dÉqÐ aŒÿ×0Ä2òE±èÕ5\â›À8-Áê&ùÏ©Wïâ½ « Üä*Nì 6±Å{ŠïZð5¾Aâ_PK˜Zþ~™ÄPK˺$- junit/swingui/TestSelector.classX xÕuþ´ë•×c[’ŸÂÈ–y®W’Æ`Á–d-ÉFp펤±V;Êî¬d ˜¤äÑ$}¤ ¥š¤vÒÆ­dÔÒ”@)IIÈ« iÚ†<É£4é3ô?3ûÒÃúúí§¹3÷žûŸsÏ랣ç~÷Ä”£QÞ+8çh&i»Mé ;9”±›z­´Ûc%¬˜ë¤BÁ𣿏yÌ_oÚßj› g(„rAh°ÅLƬ„`]Çš½×u’Í‚òÁƒ#‚à`‡v 4—J'I³r°'–r +îSÕÌ¥ò™I‹´Æ`«•Ž¥ì1×v’‚µóÍ+á#zò[ñv×T{dM “D=nŠ´$Zv•ÍSï4EüesÂmÚ—2G­æ_!©L2i¥<}´¨|ªæm}‚@‹·È}ÁÆÃÛú TbM¬%ßÂr‹3:æ$­¤Âzê-m¹=ö„FÚÛuÏFÔ„±çVöä}.Í ÝVÚ¾ÃHpW â1ÚŒ-aÔ¢®tÓMv2îL„pmÂMNÌTUu[ ŽãV¯#ØP"vA®f¼†q>."Ã笔f ¢ eØFÕª6êòîQzAùôÚ® ¶.²PÓ Üˆí*iS©¤-™TZìRúÅåJYqkÐNZqAÕÛ¾­cy³Ë°3Œ¸\°œŒ‹Ä H•ñðF=Ñ•‚U±”eº–Šï»Ù%‘%ÍìÃe\;ÑÔçOhÆUª†«•”¸Õ43‰‚k"‹I{ ®Ui÷ªø~-E••rò½¨-ŒVì3PåËÉõzrU¿ñTO“vz>ˆxþ³”ºCPö`¾À;¢•Ht[ɸ•²¨ü.†hÄgw(Œƒ¸R­– ¶Fæ„™Š^Jà‰Ûƒ^àFº×Y¢7„›” éfôc…žê–ùéÅO!ÜÆõ³KÞ¤éAG`b™nŒåÂknð‡@¬÷\ç[už»Æf:½«Ca *„• qTPvð@B>hR“a èž´›2cn^¨1A˜êiKjÆ ¤4ߌ´`¢Ûq\=)SXÎ Âå—èŒkz˜ é% aÒ·tο|Þ‚‘Es¬*ÿ-¸3Œ;pãÖ¡sÒɸÞªV-ÃÛ¸`ƽôjÑÕÓîõÞ.ØT Ø.§'î´Üa'Þ–JipÞGè `WftÀJõúé§Z³J¢ÏLÙú› ¸Ã6õpnÇÙýO“bfáç§N¦·4‹P‹Æ§@È´¶c éIHx¡^½0Ę„‡òIx}iä¶Ú£V2Íø¢©þ¤Yùiu÷:NbÄv5×”ÐçfIý'øS¥þ75„?ãù”!³•T¶þ\ÑÄC¥÷D{æí0aÇÝaµÝÀ_à#Ëñ>J[öÐ0­û—þÔ z_Iª7ðqÿ2ù7Æòwä¼lϬ=F_óÏ¿v±Ó«§„¥1–H+—†pJ°%²”éýó™0ÃãÌ…ôÆ=^Ëû¤à¼’ nSȦ¹DÓp3K ´#„'˜UNÛ— ku2tÝ–„É3 á³aœÑ•±Óɤ­¢„[H8‡Àð)|Nuÿ·‚†%8°&ý÷"ß¿ ãi廊|¹\äºe×’eç3xVy~qi¥\—Âx^ylÌ%ƒÂ]RäÖ07Ëø ¥õXÿ=^дÿ•¥Yï áÂx1oy¿ªXÊòs) üÚŸþ7&»A;Á«ìßý‰ß0QðúvRþßúO&½ oÛ1¦†VÿÿÑùÿ-Ì“ùëÞ×KJµö$µI Y°ú%k¥ÂR.Aò±½u·cÞ–fCBR¡xËYhÐô‚m‹VŸ%yüàÀQzªTVˆA•ÊJFcBo÷=rÿâjfúZ­¹ÎŽ•ÎȜ滛W_Ì¥‰ [±ÿ‚?x  îñÐ6î—Ï~QXh3‘±Jî Rr®Ô*§Íù;¨¤IUXÍ:GØ„âvzÌI[†\ µ@­\È9;Ý6:æNzræA¾Zf&V4*´·D¦Û$ªLëçU4’4ò.• +d»°¨Ég?ïJ×ÚLëØUᚢÔ-æ–^ŒC¹ŒÈvz?—ÚãT=h[©×L¹þ¾Ã†\.W„e§¼…enKX¼ÆÜ=®–×í‹*êJÙ¥âPÓ+\çÆ±1+Õb¦-¯Å«e·â]CCŒš.}"ͤ«™faãñß#{Y>KKižsCÚ¼â\öÑj¼\3)Ë›oO÷Ùi›nfÈõ>A;]²ØWäJCh]ñ °¶ XÖ˜!]j°å ËטVäõÍ´á,F"•Í?*zu©“zÝñ\W*ôÇ眽ú I¿¶ˆþ§®¤‹âWYmĘ́•òê*û¹u…–Ûò^YRˆ…Ä+î„åv1y´–F,[6èD<çQ 0C2HÃ%­cyS2,µ+dHOfžÉMÏëHKRˈ$”¿R!aNúgˆ.ÖÃ.œ2Ä‘1µù›©Óa3Ý餬×´AEGT ]â^{yÚyþ>Rõ“ê06㜇ÛÁ›¸ÃÄ pW G7nçŽA>‡0Ìß8l܇üx£xI?ždEÿyöÒÏ ß#—´ uŠûñ.À{{7ÞCëÛ{ñû”h3õþ>¼åäù>@ÄrZ-‚ }»+À Â3~°ƒ²x¸3Úð8>VÏ¿x0Áד|=É×,>yªpÎjÏ/Æ)Áí~ cÒ“©Îǣ̟âd%úWøkr[‰Mø4ßÊøcSãÿQTÞ›©ßø,ë§r§²8­êžÅ¬~þÿIkžÑÏ'³ø¼ÿù´~~!‹çüÏçõóËY|•6|Qß¿–Å7‹òîö¼òNò»‹žz'¿Žc µ¼‰ãfj­‘»Š:»–úºžã|lU{9ÞÄTÏfø²æô]¦ÿ5ðÏQ`TÐrUø³øýîå,þu¯ðíGõåSø©>^­LáWúxM¿­¯¬šÂÕ¯žÂïêWM‰ÔÏJyeEeEyeÅ´,›’°ò€#õYY•ƒëlP¸îµ!D8}{M¿m¨ ®AáøiÈÃéoÞ­ E¼®Æ ñôñj£Š§×+WªQÊÙï4÷ï Ô–¡& 5Åðž¯Õ<”šÀÙ`â5â­t/ýø0sÈ#XÏV¾¡ç~Mø.g¿ 'p Nâöî·á“°èg=m’^v7½ë8}ì~œ¢ý#Âg¸2Å_–‘3/b/à4['ðs|¿Á)Ó² OÉ:|N"lF/g|"K®ÈYz½ÔÉj©¤­-|UªøVFÔ{¤šoåĹVÖðž,k‰ä{ö!®”qܨÊRÍJMÙÃN  I¥xæ°G÷6¦Ïx¼×ûû Q½ï“sˆ*²©7m¤Q_\õ¡·<%[§äühV.*¯òBñ9Ž_â¦çK\xM\äbÛ‡¼ZYxbÃi¹Dð‚GË-@.óH^XêRÙ‘ƒúŠw[Ý9¨ÎM3òÆ8U¾ûšjOËUeTúVu.];#­ÂZ%®ÍÊu¹qÿ©ãåRë‹ñÈë_ž‘ά*nùƒ­r¾ÆXþ:síK̵ßÀV|“±ü-zË·y¤ï0î_b,³uÅË%9³» Ýn¹Aº)wöKô½WÊô»rbÕJÑÕ²7É͹Ó5åŒ>.çzžj~P¢š`!Q43µø›œ»>­úÓrDÐ9+·÷WáÙièÒWF•Å÷]ô’Í<úQñÔl¬ f%Y¨ ÎHŠo\ÊÐ8¯¿¬ô¡¦&P®dâ³2Ñmœ–;fämEá¶{wôÉüŠñ#l¡ çá'ÔÔOqûè«ù½¯¢“Ýs ¿ô±Û´ )Kîa\±ùÁ¹WÞîiªGŽ{wÊì“ûø b¥§³ »§w(y§(Ú^jø ¿îçx†£VOs|72Áñ=Ä{ÌãSÙÜø|n|ÑÿPKit#Þ ‹PK˺$-$junit/swingui/TestSuitePanel$1.class…TýSU=âZJ ­±´E 6…4Vk%E[¢µ©"‰Q¨J7áA—]fwC©ãïÎ8~·õcúW8#Á±£ãÏþQŽçm"Ô’¦Ì„½ï¾óν÷ÜûÞßÿüþ'z1ªÀÉõ†múï–i¯5ÌLYz~©aúrÞ°¥Ïj‡×-#cöZæzu]Ö| ½Ñ}ïBöª%5„úüºéÅÏ’ºØ;'0Pºmûué›5þ-ÊûDmŸ[u yËq? NQ¹½iØ+b‰¡.š¾.p!Ñ=VgÆ¥dE ”wV¤@o"YÑqC„Õ¡¡=ÑÁSÊ:ªCÇÓÊzF`°hÚr®±Q•nYN5ŠNͰ*†kªuÛRRŒuM.žei½nÃþOè†oZ™ ev\ §"CT`´…†ç© Q«I/P~ú r$;l—])g)…•ÓÇx/àEã]€Úšô‡mIö‘A!W é’8C@§&h˜dꫦ½Rš9ѹWó>"X.YÐqYò%6À3?m5—î—ñŠó<ãÕœÍÛÛw8l‰³V£p¯)ô”@Lío·4Èø¬>£$˜7üº†‹jfœ§ppÕtå¥É×I&9¤§ÅÇÎT˜K¸¬r¡¤vË| >¢/L.Ó×GärÕMÎ"Pš=ûPKž-¸.¹0PK˺$-7junit/swingui/TestSuitePanel$TestTreeCellRenderer.class•U[wUþN›6i:Ü -¤´P¤”I å’"…j°´µ­¢¢ÓvB§fâLB+^ïx¿!Vß|Ñ'.%°Ô%ðâƒ?Êåwæ„´1Y¬åËÌ9{ï³/ßþÎ>ÿóÛŸ¨Çn|'°w¶µò oÁÊ^(X‰qÓˬ¼9bdM»[nÇ]Óì7m{ÔÌN›®é!ôY㢱¨Ž%ò´Hœ43FÁ®a]/Μr]ÇMM9Y–Á•g¥¬O ˜žSj-3`XvÁ5Õ¶ñˆÅüŽ ÔëÑ @¿3mjhB8Œ4&Û1¦¥©§aµ”ÖaÀšA+kæ'Mwܘ´MÕ™2ì õä¾$ äg,O`ÿàÿ)¯•e$lƒE OΚSù ZBÌ|¿mxt»^.ÛøÂ> ±)Œ6D˜¤%ÓN˜šÞ V&„Í›ªS-d³ÈN¡wYì¨é9wŠ%Ô«b¬Œå]úé‹VC®a+ºÂØ‚mÐØDܶ|•’3§òÙ¡!¨t;Ö)]FuGD5„”Á.â1ZnÄpÍl~Æô$²=+³S(õE«ó#lyG­6è5,4$°Gâ¶·x¥ b?d±3‹ÃvUOESÁ0ÆArÄ+Lz%ïmz*UÓÿa$¥9sÎ}’Vä-éb.æ+uåêsë)öè¿téwæsN–¸Ó+šqZšöUGK§Ó©t)Qc!Ÿ({`ªý8)ÙŠ=©rÄ㊄gxQl-zeóý»* }=¥p:Œ'ð¤Àæjê• ƒ8ÃÎ(ƒŒkÌ› Ž;ç›1,@$I*Ò*C„UÒ­lþ‰B&#¯çcËÖ“#æ%[Ï‚/vÁÎhÈ¡W2ì¥rQ•wtBŽ5/ dI£‘Ë‘;ñZ¦U"•»y Òâüðª¬&ŽãŽc[9•×+2Â,^Õ8ý{å°|]­´oHíY\‘Tgç9ÂjpU Á/‰œ÷$ÃDš›‹9ƒTgÂÛ4x ë]gòÃp¦ òjL‘@µøLóŠ«b*›”'J´î¬1²WÚ bØV›T2ð˜?@,ù¬¯œø½2 Ôœ»þL5y¢ãADß°¼Z/ºˆràƒ[''-Wurªúÿÿ—Z¾hhæª!%±[X+bíϾé:~WÓ °‰"<ÚŽî4eŒõØø6÷§µÔé1zio鸇n¢[mzüMIó7ñå8-~JXÅ÷¡ÅN±K/Ç"‡J±\Æ’gÚw±ïL|­^Ä¡£ïÑ¿¯ï,âȲ÷6Âlç·›wPÖC;ý1奡â(c4 á=Ègþ8Nøµqªøâ&ñXEû;±]ñÎÖ@kCkckð’!&4˜lŠ4ÝÃЮGšîb(ŽßÅH²¹e4©E‘æ"&–‰ýŠø_hŽÉϵœOj?à˜ÒJß]ÒwKý”Ôw)}f m”ë%½.õ3tº‡Ù%l‹„îböwØç·sî-"Z/q©ˆ×b1Æ»\Ä›‘Ð2HiÂ$^Gˆ7òñÛŠ=„i/âØÇÕ~$9IŽóKáFpˆö‡aPj‘?9‚v‰°]!dW ÚÇ„ëÁú§ð| ßVp•¾ƒ·(þêž­óWïâ=Ÿrwð>Wu•«õý6ú«) 2ן𣅘ñøŸ’–=܆ÏIÊ8m¾À—lׯúŠyiŒrͯøk\ç_·Kø¡PK„²p7‘£ PK˺$-"junit/swingui/TestSuitePanel.classVkWWÝ—‡ c@TmU D‰h­¶ø(Æ”’(íÜÁa†ÎLD­}úhµµï÷ÓöèZ\u-W?õCTWϽCôKfî½çì}ξçœÉ¿ÿýõµØ‚?º¦³†æ„í9͘Êjá8·XVsø¨jpÝÆ˜V/ª—òá£î~mÁ3m©3|δ.Hߨf;Üà–õ õé¸Å9Ck´Bl2,OÇ’–©ëy›U¥6ù#AF–ËÒ#fŠë k¢‹£îòXîÖèx/Cm°÷C]„öÚrXsÂûM+Å­¨zÙÌ:4ûп‚:ƒÑ‚YÞ`D5Ô)n öžvm êÐîª!­h3ܰ5Óð ƒr ç-W)X‰Õ +JŠ˜3³¦Á âíbh¶¹3jñ4·,žŠiW(ÊŽ¢ Ð’¼k¬Á:†–E:zð¢‚õøà·5ØÈà%pW°µÁYò/&À7!(z|ä6fÎáÚTÆ!ñ‚2Ÿ6‹ó- «‹‘⦩ǵYW# ~;£R6Æí¨F’2êöF«û ú0€m ¶b;%fñ)Q9VA¦Â,VPƽ/ ß MRˆ~]3x̹¬s/^¡J2¦tžò‚ª¢e6ëDtÌá’‚‹ m«­oÓ¨ÍÇØµT„$ç¿-íeƒèéÈgg̹§e(UJù!ÃÀRý°á©G„ëúÝ ·DÇ^WpC|HšhŒŸÐWÂÅV²*>ÂÇBÓ[Tª–i’HÝKÆ1àÁ§ »‚Kwï­ÑˆÏÜÁçe³=&~O:š®9·=ø’¾ÕšqѼÀ£ª#ê(žT‰F¡Ù¿Æ7 ¾Â·4áø¥YÕ ædb~$“ܶ7leØóŒp{Ÿñ‰oˆ]6œ w´äìÃögÃV(%ff­$?¤‰aØZêÒ/¨F† È]¥®¤šk«tùXG¦”4ý«ª_b€ž4îå“& =—Ó9ýÝ ß&Z=@=½é¾ÇhIÌ£u+èue¢…mnNÍ£3‡h½žŽ6Äaa}80œÃ‰û2ŽQúí“1£h¢èÄzpý8t:„×iw g£§(r%íÆèÉh÷¤›ÁIʵ–žMÄ2Êál_¨no.Pùåñ8‰qšÞn]ÞÅ…o*&%E’H‘'#êtŠLeгDqŽÞÏ?…&)¦1áR“7¶@1Óª­@‘" NïiI±"ﲈ‚Á(ï$ÙÔ2…^Á ¬abÖ…8O6ª;ÓN4ôZCOêî¢1T»-‡+ãê=v¯€ , Õ¦w]Èqu»\^Z¿ƒw%×{xßå Ë5P/¸î•…|µ¨ê ¥ðA!×4 Š*ÀD"4k1.€„¨nÕ>Æ ªå›9ܾ_ð5B¾Žšžq³(àž‚8=øDŠS#>æ.gœ"7ãŒ;‰¾P×<¾x„ïÊïí6•û-j»ßŠJÃ_ÀõJÃïñyzñ#~¢§`ØX$Éx¹$ÍP„ù³„òâüZÁq‘–þ2ÇŠMüþŽ»R‘Ò¡àyøPK=¯ÛP#­ PK˺$-!junit/swingui/TestTreeModel.classW‰vǽ­Ù4£ÐÂ,Ë‹¤a±e6´€ŒYRd 9KKêAgºåîw‡ÍÎbg±6‰í,8‰â€ƒ†`lg!çø3rüù€8·ª[­z‡ƒºººê¾ûÞ»ïUÍçÿûèS„Ð ÖȺ“¶OêÆñ¼žÕlgÔÒ´Ãæ´–AQ°ê„:§¦³ªq<}tò„6åÄRP/fO¹ÛÒ7¤‹vED2æé(¨tñ3–šÓNšÖSÒÂn•¹xP·ÍÐ,[AÕ ´”wôlzŒvL‹Ëâ™~UÏæ- jŠTíGÌj\ËôY–) â™á¼! p}H§á= R-ÁZÇ„{HBA¨¥u,‰JT%ÆšEŸ‹˜ÄP“@-Ö$G"Ž2¬U°&€M õ ¬ë*ëîIb…;º7‰•îè¾$b(£fÆaP7´#ùܤf sJÍŽ©–.޽ɰ3£Ó©{—IC¶dÔ«Õéiz1Ä ZZ‹Ó¦Íi†“¾m Lù”i8ªnˆ°»»Š%°»õX[Ð!bÒ© As}Y-G¸ËÝ­Ø&–oW dl¼+& ê,-gÎiάp¿xv“xÐ¥³“Ü3º1-"£`_‰Ü—š½U€­’öt^ÍÚI<$,„ñ°‚ ÝFòºÃܤƒ<´ 7ìNâìM0ýû(Î’Ëbè¡m‡¯û!â`H¢õ¡?^H¢».IW2ušåxѵ,DbaPî0ÕcëϺÕ0ÄQ ‰éÇéãšÓ3£g§{Ì|É sÇF…õ¯ÚªÅMD4d}…gUg†MÁv¶n™àP:ÿÓ…û#̤vJt ÝÒŽ«g†Fµi÷Þ¬e¿ Ñ’ðK„¶Ô÷&Y#$8¨ÚŽ˜è1s³¦!å[ÝÒz»wILCK` ªk1 6†4hû tš —Ñ}ŸxåÑ€¼Œ¿ÁEW #LÒÖ\)ØBK­EJï3ò9ÍRÝ4HôiX"ë¢ì—ħü í”ãÞIh˜³Ô|5ó쯂¾H§íçsã²½IFFzô<^¨Àsx‘š˜QíæµØl)\ö¥—ñMÁç´ÔYÉñØ ¶ô)q°”MˆŠ™r©ÈÜZšÁTJRRSÐtg¾Ô0Õ^W"Ø,“YÕ’XUA†â¢öeÉ%ñcQŒ½x4)¿QG3˨0¨@I] ²‘ýL$¹?§Úƒ 1†7¹vÊEÑž{”Gu{PSY î&j@3lzbË]½Ú”IÏÄYù¶»ÍmÁk[J6®_âW œÇ;Tç¤jkîú5sj6¯õ›–,ÌEyl]®Üƒ´ÓÅeäŠ/Ão©3ïøW ÝLYºáŒO͑ѼÇïð{~.;u7¦Ó¨çf]íiÓåøãâàfÐþÄhÌŠ‰¬qKïä :#eýg\Là\b( í䘰螫Þõ‡Ägñw—ì ´€‚¸›\¡ q^‹+“k»31Ã'U›/Ë\™Ž‘‡l웂ϼۭ~‚O…Õ¿‰z³=£qÝöÝJòjG…iv>+J81bæ­)­_—7¡›®7l£a+"ñðÉ[™|òÖ%Ÿ+¼çJù\Ãõ•XÅ¿«ùvšWß2>»Ú® ºíjǯ n)×q¸~ KÃÆ¥aS[û6\’¸ù·ÖµdS)Ñ뉾U¼è¤ðß6ñk­k ›ÑÈQ+³/  íŸ!®«ªÛ.#Õ^@ú*¼áŽ%k+Éô¾÷ÑŸ¦"ôj½÷Ó²@ïòÑ÷{è r×ãK˜ ùe3£×R„—ðñ>/Þ鯈ùpû–öœE$4߯Ñþîp¨+rÛSášH»£mí©hGvÅjbo¡®cK¨€#œ¿ƒhMd¾&6&¢ÔDÄî±w¿ü¼lÞçÕÅü´“&‡m´»uØAïïgÜàlÿ>ˆ‡±{± =ü>Äë™ðaØeçû0ŒÇeÄÅè ŽÊähœ¸!âîÃ1LУjî~_¥¦ÑŒ¯q]”–Rø:çø+߀êùÿ¿ £áã¡õG„?Ax<ÔÆÐ__ÀS#ÝákÈ·µw¤ÂW0Ûq/ÀéŽ^ÀÚTô*žQpÏuÇR±Tä*^*ƒ˜ü–‚s_~±”™M̉È]9}«g«nA?ãp€þ¤Çüw€×­CEúÒ»3ÒãQÉ¿Œßñm|‡×3“ßÅ÷èq ïïßÇ+ôx=~? _{iUd\xÌ‹çqFVP%|ܤãâôôàEå¢Ï·J®"ÆcŒì0«aDrkswúܪðCüHr«ò¸EY¡"!ÎòéÙœà¡÷ÕÒæá-7PN™¼>š¿Åä8ŽÑäKðIi²ÑÝè›\홌²tŽI`?ÁO=C—$`—ïÜÖPW˜2}£›j®ß"r$3ö ©öhMxþLX³2eÿ)Rm“ÌÃ$á¦HhšÖXQ9Î8hÔë IpkÐ'¸ËÉ.œåHÚáÅdw ]òW)6È,E¸òÑ\úiY€PÙ†¥tDåä¬4—txæ¼Åßýîæ½^kHJßÿH¸8¾.Æ\QcHú”“,%—2Éxhy/eÍퟡ÷,ÊÛ¯£÷"ÇçÏb5Çç x÷°ìź©—±xžŠ{ /ÒË—xX¼Ìwº(™Í¾áfÏð:î{OV³‚_ã7…C…ø‡øCÕ|ÞÚê^á–W‹€ã>pÜ/š8þ"“\öŒïÈ}¹¡Ñúëm]ô5>_/ V…]!û‰€¾Ø øŸoÞð£@À¦`À·!.[Ë^ÃÇ> +ŽJ XÀõúx¯°Ò¬ô?óõk…Ë7°Jz^÷ý"ÜZ·ÖÇý{ nƒ‹ÛP÷ƒ;àþƒ}ÅÅ}B¶$–uའh¶q)ÐnOºÌ€.³@_)ªÁ&¿ÿ)wüëÿPK`uú®ÇˆPK̺$- junit/textui/ResultPrinter.classW‰_ç~FY—AeŒŠa†.‹ºi¢&Q£BAIl“8,³²dÙ!³³"µÍÑš¤ÍÑ´é)½’^önlu5I›¦w›¶¿Þ÷}¦EÚçýfvXa°êof¾ï{Ÿ÷zÞ÷ûöåWŸK± ¯hX7QÈeœ¤cžp ™ä ™/dÛíLÎ1íJhVMÇdÖÈKŒN˜)§K54¸RiÛ˜4§-ûžä°™wú3yÇ̉\…†Êô!;C uý "c%îc›ÆäÙÑee “9 Z¯†e;3DÜ¥áªxàþ¶ƒB]Ö˜©ai¼í Ž*¬ˆ „•:–#²KP££ay[­ae&gî/LŽšö°1š¥T´ßJÙƒ†‘oo2äŒgòt§ñ(ÐÒeÓž+S2§!ï €+·£Ol­R[o51 ÅûÄælˆÐ¾«KËݶmÙÔßxY<‘Œ¡I$›5T+É#“-Øf^ÇkÜ•kJ˜=–E[u¼ÖÓ|[á̹¨… ± ¹áÌ$âõ1‚ í‘a ¬É)Š/?f:¥¤®‰·¦IG׊Þ×iX°¡×S‘‚Îætl•$nÁ6 µ;»‡ îßs¬XÊÊ9™\Á ãFòÇ#„â Q2¹c*$[±]dixýüõÎB:-<¼™Î‹GÛcaìÊPb:hš™5¦òæ˜,vä]!ÑÔ×¶P—Ž.ì—º‰fLM™¹1 ƒŒZ0åÚA„[p«h&ÏÃŽURWÔvúeï>¿6ƒÒU‰ZczüY[B*8™l²;W˜4mÃÉX9ÂÝÁndžˆÚÞe„Â,¢^pP‘Új1Œ ºJÏ^3Íj'ø¦ø"ؽÁyy=Þ Ñº“¾¦}–ÞíZq”èÞ¤²CǨkAJú»7m36mä™:Æj}¼÷²áÍHÈ&È\nÏò±= 6–*E†0¦4,ÉsAzR G•``ªrlÝYsÒ”0]š#·RáqLW¡€4,(G^uV⥪t£©¡)¸Ò=½À7áÍÀûXƒãF~Ÿe›ž9y•¶#:Àƒ¢þ- Ú¨euZWÖ,’%¦6å¦<äÌL©F¸ m XFCM™¥nãÒñ¨kËc<ÊV‡m#e.ÚKΈ/Oà"ÿ$ÉêZªaÃe….9q\ó*ñn:zÜÈÌ´Ti˜“÷â}¼ïg–Û˜íÓ$‘0ŠENx9WÚSòƒøP'ñáyeíeû²¼û¨ðîiëÜfô1FÛ‘àèø„”ñI|Ò§»+Çd§‘7U«ÏJœ¡Çl¬=™,+uCÛzEý…&|ŸàÓøËP!•2óùt!«ã xP*닌ÇÀma<Ëg,Æ—Y—4Å+¿snù§Ý1‡V…qAÂxŽ”È‡ñma|4îéèí?0Ø=ÔÔÔÆ×¥¶¸=#”t×oPÿÆX¬t,ÉÔ·¸‡Sî'ß)uj9f“îáÜcÙ“»Ù÷¸™QèÍå#'XW*¼›éôðrßÇ—íyräé•V‹B½ú ~*2?£ûÆØ˜²JÃæ`ï(·­i¹-¨+ˆÖƯ¤”§êƒ¥¹Íñï=ó@ÈJª÷â¤a÷¢Ì›íÈçM[ ºGqZÙïZÔÆŸH˜+“`!ñür+bí"ºu9ó`;î>msÿ ÝCVÁN™$ª4‘KîH›ÅS4±ÐC’ >!w1•ÞÎ8Öp¾ :Çj~ p‡ìY™¸€U‰¥çM´ŸGíYN-AÇ(€ÕkP‹œ­çL½+†5¸J¯ÄZªa'b®÷ÀS¼ÚŠt]"VDc¢½ˆZeh›SQ Žë96Р„ºšŠ•š!à«©Cí„—·¼7‹›i”«°‹ß²V“(âº"nGô¦"vÎ)[¡›”¬â•M”è®§$$—Cðn%û[Ê_À®‘èž èL4ÑSD_ûT$¨¢Š6–…«Å÷£EYOúÊ}ÒSv ¿Ü\0>Ãü;=RÄ]sÀµœ¤‚kÉœ\Eƒ@ þEÓ ×tËÿåuÂ}…_’³™†Y„Î6„žF»™qF¦¡ˆ{¢“ Í&þE-?Fg÷÷Ý»`_ÞßÚ:CÖ´?‡ /ád]¨ˆûO…4N¼UÃìÿ3g~³"÷ 4çFºr®ÃÂN܉›‘åóv+·¶¸ûnÍàRyŸÁÃ^fðÞÆä!ߎˆ*!^<§¹"‰Õí´ûq‰ç;ç'½“%×ÅòÚ[F^Ýשã]xJéÔ=!9Ö=ü1~)n–BÔp`¢³Œ •}¤ˆgTx>>?y½Ìv_™Æf_c³¯±Ù×È‹€ÏRñS#5|ê">¿Îí_„.|H~ãx ¯z„›%à—N£¿¼ÏÝ'ÀWè÷…]‹dR8úüTD¿*Œx±Œ9Ýå@/qÊúfз] 1yÿ®û~˜ï.ˆ‡0çß6eñ¬ÔAú8D¿†åÎÿ‡q#LÉÒárÿq¾?EZÆ]e±˜õc1ë× ¤x±èðÚGõEü¨ñÑZü˜¥ðóg}õËTfÒepÕ>\µ× 4ùçÁ%Õ7P‘8‡Úù0e­¬ÂƒÑð üÒîçn±%¢øë€˜æiø»1áѱU÷O!àÈ9D„Žò¬[Æ%¿ðJ¿ù‡Ò)þO¶‡iø#¸†]aNo«¯·Õ×û/%ÿïÿPK6°ÖG×PK̺$-junit/textui/TestRunner.classW‰TÕþnòÈ Ã°8HHtP ÉLBY*±XH&@IJõ1ó’ Ìß¼! ­Öª­U\j­-¬m\¨… ‹Ý»ïûö´ýÎ}o&“aˆM~™¹ïÞs¿óïžsîË{ÿ¹rÕhÆ¿æÌ¥N‹cqr‰–^+ëìÌ¥Ó–íƒRXà.Úz¦e“™µJ ªü;ìDÚ±l……]“vZÙ\ÒñV[‚=»ÚÚÚ{zîißÓÙ« :f¶eÒYÇL;}f2gUƒ?´ëØØÙµkg»¶“9Ò˜Õ¾§­}GoçömÅÙ*…š;ô·A¡º¡±OÁhËÄ-…9ÍÃfKÒL¶ôÍ:VʇM29Ga^—^LdZ4¯ǶÌTk7bÞtÌE­B]CE“ƾ f£.€*Ô+ÌîJ¤­m¹ÔËî5$é4Ô•‰™É>ÓNȳ7i8C‰¬B}×u¦(7]_2n ,îni˜JY—Ú­Bí6j2b'8+Ss0°,ˆi¨™ÎÅßpᬪy¢ 7zÁj±Ú’f6Û*BÖ»Þl3edìCšrOޏ>4 rSËÑ¢°º@l²ikcÅi—6ÕŽb¥°]¥0Ýá¼v¬pÃ5\Äh™Â´x†z±ÎÝöA–Ûj+{§n¾*8ؘŽï64¯¿[†¼æ:k{ß'”u¸K8}˜,³" sâ€à åte̸ŒÃ 0¯œŠ²º$¾dÒzK#nÚñ2;:Ø,ÊD‡3‘´â - •c(ѵwÈÎŒHrê kX{NŽÒ«‰Ò(3c<âƒLlGœÌ+ÍÖF"=¨¡übµn¥®±ðº=Œ91–”cMè¨psÔ:ë¤Òª»è“DïA¯Æ9„x¼+Áâׇ°¸òá tíÅ>Aùó0–³m+íô&RVw"™”fƒÙÄÇqO€]â^N%<”ÔjÅ@ÄSñˆJMÓå(‰1Õž­²iCÒ ²ÉÌe¥¹4ì•…CHJÌ)NŒè,W{%ÿ=]N­êô¬œ«Ê}[Ù¬tÜ}ò1ÝÑlMR*h‡I ;AŒHg ãˆBU"]ÚS;Óù‰žz?žú …¹ |x”9Šku;ƒøà!|º`¯¨ýHÌv™´Ò>eŠÇÚ†}•³pšŽGaeEƒ©+ùq|N„|‚·Òˆ™íÉÅbV6;Kjz{ƒ8†§$Až& ëˆm4tÊ<‹ÏKRòáÅB7O²3¾Œí¼„S$eÚƒÌ×¹âç³”5¹Ô‹s=P| üxŠ6KVùñÆä{U#úp†©fÝ—3“ٲΰýÀA+Æt§noálßÀÛÌ–æ˜ç Ä[Ì6cnßw{ƲJm¥’,pQnµ¼ öã“¡ÜjSn`@šä’Ûº‹'öã¹µ¨Ñ8®‹×k²}–ÕùõmÉçxß心ïq»9<ÌŠPhú¿è¹ŽIòø¡¸ú‘¢ð£á»ÙL›¬Ø¡0Ûy¸ÝNƛÍTÊôã'Ò93îö ~*žÇñ3…Þ]’ëÃWIxŸ>‰ýa}cò=L„k Y¶NsNdÃÎ7Î èq¯gމÔ~ü"€ÇD°W_¡‘Ê‘UºF‚ø5~#âÿVai[&—Œ‡Ó'ì6sÕôÂú*\OÝ_¦]!/¦Òî¢ÁŸ¼+EØ3iÙ÷¦½pÕùR…ê d-§øèÉäì˜Õ‘—¯ÙÚ-oXÌê6øâhð›¯DÕÃÇ,'´¼N"Àç%ÏA>Ï,yž…Ç|­âç œYË9– ü‘ó˜?†›Îi«ü”>,!úR,ä(èÚanÖo¸|‘ô0Ú5`fdáþèaI9P”M¨Ö5ö€d´ó%·z´«@d ˆD/¢qoäÍy%®bP·—`Š˜D(Ž¥W³•û$„™ãXÞOÜ—pûîršwæú’xgb5Öð[€V–‘›5Žªþ1¬íŠFò¸ãí2¤ÍÔjK ¹YÄmÕ ÖàNÒr³‹äÄjΦ‘ÇÆÝåaïàþR¨%Ès°ÉCö£M#+|„§â"¯*œð86yËÏ=ß_ñt;±ÕÛß©³sçÊ6î×#îbQy…»uºÉH®Ò£.tkõ·a»»F£U€½·$²RØŒ["Ûùþ±)! yźVœ>г»\œDEqÖS¡Õ;6_$ZÍã*ßž*!â+ñia”ºËz‡´RL¥þmÍ‘ hÌcÿ%˜ëŒhóe TAÆ5µ5µ†µÎ/Ë͵þ<Fæ‘nžð»L×ù}ì 6s7ËjwØrô|˜e6‚eF߯ym!é^ku)=Ê`Xw˜•IJdˆ K,ƒ¶uÄsáR2?Ì‘Ÿ³|ƒó"‰ó[2µnÁ çÜ@ŽžÇ'óxd÷(Œîsòß15©ew9×Òð ?âÊÃ|~ó¹:¡]]‘cf&µó|ÖóxŠ6âqEi=>ÙÝ”Ç3'à3.á ÕüE¨û<^àìÉW’ø+𠾪“£Á«=é°¯R³*¯áëºcóŌߣº–ý‘·Úψ%ò³¡×»«7T¯5F‹Î3V…ÞÌãÜqø £Ø®'¾©'B‘裆âscÝ£X­—.ë¥ÛÙ8ÆûCßû—ðý<~zyüœÁŽÂ/¶Ýzwôêéÿžl ½®÷±>Öúå~õn„Êün½©7I&¯7dIcþ˜õìF&šXêžçoA¶} Çy'ÐI^@/ò_¢L/S–SLóÓçÖå«âºM!ÀkÜÿ&>C¤·ðΖ$åÙâŸÕKJÁ_X¿’”oè$¨¦èñW~Çø)Ék§^‹nð÷oÅV±ÅkÙAê¥"†>þÉ­õ=_$÷|Iâ‹<‚ø»×€þQ¼¥6x¨5e7”{\&Ó+%X5E¬ïvRø§Þó¯ÿPK𢗠 ÊPK´¼~,stylesheet.css­”ÁŽÓ0†Ÿ€wi/KÕД‡öT¶”…BËJœ'Í$µêØ+Û ”Uß±ãn’’K%|¨š‰¿柱3›ÀWl0×;°î( ìžÈÁdöj6 d¡V°ŽrBùgÃoýO†ùk¿s Ï;-µYrpuêÀ!æö,ŽAiˆ`qZË Ü¶ÑR먹dZxýÆê‰‡¤ °”d¦|<•M,QÎ;~mìÉeÎAÆyúä.òÝ“lȉNamÊA†Sý†(Ñ ­À_„îüöŽïùˆæŽ¤œ_Ž0¹¸ƒÐã¨çÒïÒ4p4‡x;;Ø;÷Ú{ö õ,vÞVð"îúbm%׋µ'µó¶Þ^]Ù¿Ó]üOÝ¿PK¯Ê@óîdPK ®»$- ýAMETA-INF/PK®»$-/c„10'META-INF/MANIFEST.MFPK rº$-ýAšjunit/PK ʺ$- ýA¾junit/awtui/PK ʺ$-ýAèjunit/extensions/PK ʺ$-ýAjunit/framework/PK ­»$- ýAEjunit/runner/PK ˺$-ýApjunit/swingui/PK sº$-ýAœjunit/swingui/icons/PK ̺$- ýAÎjunit/textui/PK ®»$- ýAùjunit3.8.1/PKʺ$-؉Þ䎡"junit/awtui/AboutDialog$1.classPKʺ$-€¸àeu†ýjunit/awtui/AboutDialog$2.classPKʺ$-×uÔ˜Lt ¿junit/awtui/AboutDialog.classPKʺ$-(äQØ V junit/awtui/Logo.classPKʺ$-äž;lx- ëjunit/awtui/ProgressBar.classPKʺ$-f†¯sƒ¨®junit/awtui/TestRunner$1.classPKʺ$-M ¼31»}junit/awtui/TestRunner$10.classPKʺ$-§ qG\7ûjunit/awtui/TestRunner$2.classPKʺ$-_£Zh²¯£junit/awtui/TestRunner$3.classPKʺ$-±NÓ≤¡ junit/awtui/TestRunner$4.classPKʺ$-±þ*»Nv"junit/awtui/TestRunner$5.classPKʺ$-qø·‹¤%junit/awtui/TestRunner$6.classPKʺ$-D´܇¦ç&junit/awtui/TestRunner$7.classPKʺ$-REI‚¡º(junit/awtui/TestRunner$8.classPKʺ$-³Ž±ÊZ3ˆ*junit/awtui/TestRunner$9.classPKʺ$-k1nv{:.,junit/awtui/TestRunner.classPKʺ$-fc”Cî³(îIjunit/extensions/ActiveTestSuite$1.classPKʺ$-øŒôU9&2Ljunit/extensions/ActiveTestSuite.classPKʺ$-Œ—Þje(ÛOjunit/extensions/ExceptionTestCase.classPKʺ$-‘›éâÒ#›Rjunit/extensions/RepeatedTest.classPKʺ$-9!éº $¾Ujunit/extensions/TestDecorator.classPKʺ$-^?úVéz"!Xjunit/extensions/TestSetup$1.classPKʺ$-`V‘è  ZZjunit/extensions/TestSetup.classPKʺ$-Ú!5#K  \junit/framework/Assert.classPKʺ$-GƒœÍ*%fjunit/framework/AssertionFailedError.classPKʺ$-Þ×Qd¶­'•gjunit/framework/ComparisonFailure.classPKʺ$-dî?/š¿! kjunit/framework/Protectable.classPKʺ$-(gØõ˜¸‰ljunit/framework/Test.classPKʺ$-Ûæ[  imjunit/framework/TestCase.classPKʺ$-€4Ò»1Ö!Usjunit/framework/TestFailure.classPKʺ$-©bÔV"Õvjunit/framework/TestListener.classPKʺ$-cÌ#_„Š"ùwjunit/framework/TestResult$1.classPKʺ$-äÊ×O|¤ Íyjunit/framework/TestResult.classPKʺ$-¯$Šxm!—€junit/framework/TestSuite$1.classPKʺ$-áy»+ h^‚junit/framework/TestSuite.classPKʺ$-õr—@ÜÉ$!Öjunit/runner/BaseTestRunner.classPKʺ$-LÑÍLê )¢junit/runner/ClassPathTestCollector.classPK‚³E,¿Cûö•  Y©junit/runner/excluded.propertiesPKʺ$-ê´ë¿ÿ$<ªjunit/runner/FailureDetailView.classPK˺$-®2Hį] 'M«junit/runner/LoadingTestCollector.classPK1‡,´XWYóÄQ°junit/runner/logo.gifPK˺$-…È"”í+‡±junit/runner/ReloadingTestSuiteLoader.classPK˺$-¬l‹…&ͳjunit/runner/SimpleTestCollector.classPK1‡,›¾#Gšs¬µjunit/runner/smalllogo.gifPK˺$-'ï\}®Ý!޶junit/runner/Sorter$Swapper.classPK˺$-L+ÓÓh‹·junit/runner/Sorter.classPK˺$-Gd¡Ñ‰*:ºjunit/runner/StandardTestSuiteLoader.classPK˺$-Z‰Ãù ?&¼junit/runner/TestCaseClassLoader.classPK˺$-Åsõë« hÉjunit/runner/TestCollector.classPK˺$-C {í Å"FÊjunit/runner/TestRunListener.classPK˺$-¼ÔŒðÄ2"¡Ëjunit/runner/TestSuiteLoader.classPK®»$-ëãY›ûhµÌjunit/runner/Version.classPK˺$-ìW©!øÍjunit/swingui/AboutDialog$1.classPK˺$-yŽ!ÖÏjunit/swingui/AboutDialog$2.classPK˺$-œí¹ ²*žÑjunit/swingui/AboutDialog.classPK˺$-«É×2ù Ùjunit/swingui/CounterPanel.classPK˺$-XÀ`a`?âjunit/swingui/DefaultFailureDetailView$StackEntryRenderer.classPK˺$-˜±¨p0@ëäjunit/swingui/DefaultFailureDetailView$StackTraceListModel.classPK˺$-­V>x),‰èjunit/swingui/DefaultFailureDetailView.classPK˺$- 8§’å$[ìjunit/swingui/FailureRunView$1.classPK˺$-s*œ\~:?îjunit/swingui/FailureRunView$FailureListCellRenderer.classPK˺$-¥½;Én "ójunit/swingui/FailureRunView.classPKœ‡,ƒÀsý(dùjunit/swingui/icons/error.gifPKœ‡,0ôv%^ûjunit/swingui/icons/failure.gifPKœ‡,*ÓÆØ¼{!þjunit/swingui/icons/hierarchy.gifPKœ‡,D·•ŸWU ÿjunit/swingui/icons/ok.gifPK˺$-‰Â^«ÿjunit/swingui/ProgressBar.classPK˺$-@¨Þ±xVjunit/swingui/StatusLine.classPK˺$-¬»Ÿº— */junit/swingui/TestHierarchyRunView$1.classPK˺$-Ýh:Ê,` (junit/swingui/TestHierarchyRunView.classPK˺$-¥ÞA·æ" junit/swingui/TestRunContext.classPK˺$-x{ò±1 §junit/swingui/TestRunner$1.classPK˺$-RW¹!‚junit/swingui/TestRunner$10.classPK˺$-c_,¸ñ!ajunit/swingui/TestRunner$11.classPK˺$-ÀÖs@³ý!hjunit/swingui/TestRunner$12.classPK˺$-Þ.ëï…½!jjunit/swingui/TestRunner$13.classPK˺$-À æì !>junit/swingui/TestRunner$14.classPK˺$-RÀµŽŸ!junit/swingui/TestRunner$15.classPK˺$-yë,ŠÙâ!÷junit/swingui/TestRunner$16.classPK˺$-=Áã±!"junit/swingui/TestRunner$17.classPK˺$-wŒI, !$junit/swingui/TestRunner$18.classPK˺$-{âÆ…!Œ&junit/swingui/TestRunner$19.classPK˺$-·æ@ž)1 ê'junit/swingui/TestRunner$2.classPK˺$-’!R‰Ò a*junit/swingui/TestRunner$3.classPK˺$-•8ŒÅŽ® 8-junit/swingui/TestRunner$4.classPK˺$-¤Ìf² /junit/swingui/TestRunner$5.classPK˺$-£í&ˆ³ ï0junit/swingui/TestRunner$6.classPK˺$-Óš©x” Å2junit/swingui/TestRunner$7.classPK˺$-Ï“˜ˆ¯ ‹4junit/swingui/TestRunner$8.classPK˺$-=3Œ® a6junit/swingui/TestRunner$9.classPK˺$-mÛƒ+»^;8junit/swingui/TestRunner.classPK˺$-òµâŒ djunit/swingui/TestRunView.classPK˺$-¡eÀì”®"Xejunit/swingui/TestSelector$1.classPK˺$-²®¦zŒ¼" try F catch __T:__E -> io:format("~p:~p thrown debugging~n~p~n", [__T, __E, erlang:get_stacktrace()]) end end)())). %% General consts -define(FRAME_1_0_MIN_SIZE, 512). -define(SEND_ROLE, false). -define(RECV_ROLE, true). %% Encoding -define(DESCRIBED, 0:8). -define(DESCRIBED_BIN, <>). -include_lib("rabbit_amqp1_0_framing.hrl"). rabbitmq-server-3.2.4/plugins-src/rabbitmq-amqp1.0/package.mk0000644000000000000000000000141412305126066022472 0ustar rootrootRELEASABLE:=true APP_NAME=rabbitmq_amqp1_0 DEPS:=rabbitmq-server rabbitmq-erlang-client STANDALONE_TEST_COMMANDS:=eunit:test(rabbit_amqp1_0_test,[verbose]) FRAMING_HRL=$(PACKAGE_DIR)/include/rabbit_amqp1_0_framing.hrl FRAMING_ERL=$(PACKAGE_DIR)/src/rabbit_amqp1_0_framing0.erl CODEGEN=$(PACKAGE_DIR)/codegen.py CODEGEN_SPECS=$(PACKAGE_DIR)/spec/messaging.xml $(PACKAGE_DIR)/spec/security.xml $(PACKAGE_DIR)/spec/transport.xml $(PACKAGE_DIR)/spec/transactions.xml INCLUDE_HRLS+=$(FRAMING_HRL) SOURCE_ERLS+=$(FRAMING_ERL) define package_rules $(FRAMING_ERL): $(CODEGEN) $(CODEGEN_SPECS) $(CODEGEN) erl $(CODEGEN_SPECS) > $$@ $(FRAMING_HRL): $(CODEGEN) $(CODEGEN_SPECS) $(CODEGEN) hrl $(CODEGEN_SPECS) > $$@ $(PACKAGE_DIR)+clean:: rm -f $(FRAMING_HRL) $(FRAMING_ERL) endef rabbitmq-server-3.2.4/plugins-src/rabbitmq-amqp1.0/codegen.py0000755000000000000000000001000712305126066022525 0ustar rootroot#!/usr/bin/python import sys import os import re from xml.dom.minidom import parse def safe(str): return str.replace('-', '_') class AMQPType: def __init__(self, dom): self.name = safe(dom.getAttribute('name')) self.source = dom.getAttribute('source') self.desc = dom.getElementsByTagName('descriptor')[0].getAttribute('name') self.code = dom.getElementsByTagName('descriptor')[0].getAttribute('code') self.number = parse_code(self.code) self.fields = [safe(el.getAttribute('name')) for el in dom.getElementsByTagName('field')] # These are 'restricted' types, rather than composite, so they # do not have defined fields. if self.desc in ['amqp:data:binary', 'amqp:amqp-sequence:list', 'amqp:amqp-value:*', 'amqp:application-properties:map', 'amqp:delivery-annotations:map', 'amqp:message-annotations:map', 'amqp:footer:map']: self.fields = ['content'] def define(self): return ('SYMBOL_%s' % self.name.upper(), self.desc) class AMQPDefines: def __init__(self, dom): self.name = safe(dom.getAttribute('name')) self.source = dom.getAttribute('source') self.options = [(self.name.upper() + '_' + (safe(el.getAttribute('name')).upper()), el.getAttribute('value')) for el in dom.getElementsByTagName('choice')] def print_erl(types): print """-module(rabbit_amqp1_0_framing0). -export([record_for/1, fields/1, encode/1, symbol_for/1, number_for/1]). -include("rabbit_amqp1_0.hrl").""" for t in types: print """record_for({symbol, "%s"}) -> #'v1_0.%s'{};""" % (t.desc, t.name) if t.code: print """record_for({_, %d}) -> #'v1_0.%s'{};""" % (t.number, t.name) print "%% %s\n" % t.code print """record_for(Other) -> exit({unknown, Other}). """ for t in types: print """fields(#'v1_0.%s'{}) -> record_info(fields, 'v1_0.%s');""" % (t.name, t.name) print """fields(_Other) -> unknown. """ for t in types: print """encode(Frame = #'v1_0.%s'{}) -> rabbit_amqp1_0_framing:encode_described('%s', %s, Frame);""" % (t.name, t.source, t.number) print """encode(undefined) -> null; encode(Other) -> Other. """ for t in types: print """symbol_for(#'v1_0.%s'{}) -> {symbol, "%s"};""" % (t.name, t.desc) print """symbol_for(Other) -> exit({unknown, Other}). """ for t in types: print """number_for(#'v1_0.%s'{}) -> {ulong, %s};""" % (t.name, t.number) print """number_for(Other) -> exit({unknown, Other}).""" def print_hrl(types, defines): for t in types: print """-record('v1_0.%s', {%s}).""" % (t.name, ", ".join(t.fields)) print_define(t.define(), 'symbol') for d in defines: if len(d.options) > 0: print """ %% %s""" % (d.name) for opt in d.options: print_define(opt, d.source) def print_define(opt, source): (name, value) = opt if source == 'symbol': quoted = '"%s"' % value else: quoted = value print """-define(V_1_0_%s, {%s, %s}).""" % (name, source, quoted) def want_type(el): descriptors = el.getElementsByTagName('descriptor') return len(descriptors) > 0 def want_define(el): klass = el.getAttribute('class') return klass == 'restricted' def parse_code(code): res = re.match('0x([0-9a-fA-F]{8,8}):0x([0-9a-fA-F]{8,8})', code) return res and int(res.group(1) + res.group(2), 16) types = [] defines = [] mode = sys.argv[1] for file in sys.argv[2:]: tree = parse(file) types.extend([AMQPType(el) for el in tree.getElementsByTagName('type') if want_type(el)]) defines.extend([AMQPDefines(el) for el in tree.getElementsByTagName('type') if want_define(el)]) if mode == 'erl': print_erl(types) elif mode == 'hrl': print_hrl(types, defines) else: raise "Mode != erl or hrl" rabbitmq-server-3.2.4/plugins-src/rabbitmq-amqp1.0/spec/0000755000000000000000000000000012305126066021500 5ustar rootrootrabbitmq-server-3.2.4/plugins-src/rabbitmq-amqp1.0/spec/messaging.xml0000644000000000000000000002256212305126066024206 0ustar rootroot
    rabbitmq-server-3.2.4/plugins-src/rabbitmq-amqp1.0/spec/security.xml0000644000000000000000000000757212305126066024104 0ustar rootroot
    rabbitmq-server-3.2.4/plugins-src/rabbitmq-amqp1.0/spec/transport.xml0000644000000000000000000002616412305126066024267 0ustar rootroot
    rabbitmq-server-3.2.4/plugins-src/rabbitmq-amqp1.0/spec/types.xml0000644000000000000000000001352512305126066023374 0ustar rootroot
    rabbitmq-server-3.2.4/plugins-src/rabbitmq-amqp1.0/spec/transactions.xml0000644000000000000000000001022412305126066024731 0ustar rootroot
    rabbitmq-server-3.2.4/plugins-src/generate_deps0000644000000000000000000000515212305126066020325 0ustar rootroot#!/usr/bin/env escript %% -*- erlang -*- -mode(compile). %% We expect the list of Erlang source and header files to arrive on %% stdin, with the entries colon-separated. main([TargetFile, EbinDir]) -> ErlsAndHrls = [ string:strip(S,left) || S <- string:tokens(io:get_line(""), ":\n")], ErlFiles = [F || F <- ErlsAndHrls, lists:suffix(".erl", F)], Modules = sets:from_list( [list_to_atom(filename:basename(FileName, ".erl")) || FileName <- ErlFiles]), HrlFiles = [F || F <- ErlsAndHrls, lists:suffix(".hrl", F)], IncludeDirs = lists:usort([filename:dirname(Path) || Path <- HrlFiles]), Headers = sets:from_list(HrlFiles), Deps = lists:foldl( fun (Path, Deps1) -> dict:store(Path, detect_deps(IncludeDirs, EbinDir, Modules, Headers, Path), Deps1) end, dict:new(), ErlFiles), {ok, Hdl} = file:open(TargetFile, [write, delayed_write]), dict:fold( fun (_Path, [], ok) -> ok; (Path, Dep, ok) -> Module = filename:basename(Path, ".erl"), ok = file:write(Hdl, [EbinDir, "/", Module, ".beam: ", Path]), ok = sets:fold(fun (E, ok) -> file:write(Hdl, [" ", E]) end, ok, Dep), file:write(Hdl, ["\n"]) end, ok, Deps), ok = file:write(Hdl, [TargetFile, ": ", escript:script_name(), "\n"]), ok = file:sync(Hdl), ok = file:close(Hdl). detect_deps(IncludeDirs, EbinDir, Modules, Headers, Path) -> {ok, Forms} = epp:parse_file(Path, IncludeDirs, [{use_specs, true}]), lists:foldl( fun ({attribute, _Line, Attribute, Behaviour}, Deps) when Attribute =:= behaviour orelse Attribute =:= behavior -> maybe_add_to_deps(EbinDir, Modules, Behaviour, Deps); ({attribute, _Line, compile, {parse_transform, Transform}}, Deps) -> maybe_add_to_deps(EbinDir, Modules, Transform, Deps); ({attribute, _Line, file, {FileName, _LineNumber1}}, Deps) -> case sets:is_element(FileName, Headers) of true -> sets:add_element(FileName, Deps); false -> Deps end; (_Form, Deps) -> Deps end, sets:new(), Forms). maybe_add_to_deps(EbinDir, Modules, Module, Deps) -> case sets:is_element(Module, Modules) of true -> sets:add_element( [EbinDir, "/", atom_to_list(Module), ".beam"], Deps); false -> Deps end. rabbitmq-server-3.2.4/plugins-src/rabbitmq-web-stomp/0000755000000000000000000000000012305126066021306 5ustar rootrootrabbitmq-server-3.2.4/plugins-src/rabbitmq-web-stomp/README.md0000644000000000000000000000246512305126066022574 0ustar rootrootRabbitMQ-Web-Stomp plugin ========================= This project is a simple bridge between "RabbitMQ-stomp" plugin and SockJS. Once started the plugin opens a SockJS endpoint on prefix "/stomp" on port 15674, for example a valid SockJS endpoint url may look like: "http://127.0.0.1:15674/stomp". Once the server is started you should be able to establish a SockJS connection to this url. You will be able to communicate using the usual STOMP protocol over it. For example, a page using Jeff Mesnil's "stomp-websocket" project may look like this:

    Don't panic!

    This is a SockJS hidden iframe. It's used for cross domain magic.

    "). -define(IFRAME_HTMLFILE, "

    Don't panic!

    "). %% -------------------------------------------------------------------------- %% -spec welcome_screen(req(), headers(), service()) -> req(). welcome_screen(Req, Headers, _Service) -> H = [{"Content-Type", "text/plain; charset=UTF-8"}], sockjs_http:reply(200, H ++ Headers, "Welcome to SockJS!\n", Req). %% -spec options(req(), headers(), service()) -> req(). options(Req, Headers, _Service) -> sockjs_http:reply(204, Headers, "", Req). %% -spec iframe(req(), headers(), service()) -> req(). iframe(Req, Headers, #service{sockjs_url = SockjsUrl}) -> IFrame = io_lib:format(?IFRAME, [SockjsUrl]), MD5 = "\"" ++ binary_to_list(base64:encode(erlang:md5(IFrame))) ++ "\"", {H, Req2} = sockjs_http:header('If-None-Match', Req), case H of MD5 -> sockjs_http:reply(304, Headers, "", Req2); _ -> sockjs_http:reply( 200, [{"Content-Type", "text/html; charset=UTF-8"}, {"ETag", MD5}] ++ Headers, IFrame, Req2) end. %% -spec info_test(req(), headers(), service()) -> req(). info_test(Req, Headers, #service{websocket = Websocket, cookie_needed = CookieNeeded}) -> I = [{websocket, Websocket}, {cookie_needed, CookieNeeded}, {origins, [<<"*:*">>]}, {entropy, sockjs_util:rand32()}], D = sockjs_json:encode({I}), H = [{"Content-Type", "application/json; charset=UTF-8"}], sockjs_http:reply(200, H ++ Headers, D, Req). %% -------------------------------------------------------------------------- %% -spec xhr_polling(req(), headers(), service(), session()) -> req(). xhr_polling(Req, Headers, Service, Session) -> Req1 = chunk_start(Req, Headers), reply_loop(Req1, Session, 1, fun fmt_xhr/1, Service). %% -spec xhr_streaming(req(), headers(), service(), session()) -> req(). xhr_streaming(Req, Headers, Service = #service{response_limit = ResponseLimit}, Session) -> Req1 = chunk_start(Req, Headers), %% IE requires 2KB prefix: %% http://blogs.msdn.com/b/ieinternals/archive/2010/04/06/comet-streaming-in-internet-explorer-with-xmlhttprequest-and-xdomainrequest.aspx Req2 = chunk(Req1, list_to_binary(string:copies("h", 2048)), fun fmt_xhr/1), reply_loop(Req2, Session, ResponseLimit, fun fmt_xhr/1, Service). %% -spec eventsource(req(), headers(), service(), session()) -> req(). eventsource(Req, Headers, Service = #service{response_limit = ResponseLimit}, SessionId) -> Req1 = chunk_start(Req, Headers, "text/event-stream; charset=UTF-8"), Req2 = chunk(Req1, <<$\r, $\n>>), reply_loop(Req2, SessionId, ResponseLimit, fun fmt_eventsource/1, Service). %% -spec htmlfile(req(), headers(), service(), session()) -> req(). htmlfile(Req, Headers, Service = #service{response_limit = ResponseLimit}, SessionId) -> S = fun (Req1, CB) -> Req2 = chunk_start(Req1, Headers, "text/html; charset=UTF-8"), IFrame = iolist_to_binary(io_lib:format(?IFRAME_HTMLFILE, [CB])), %% Safari needs at least 1024 bytes to parse the %% website. Relevant: %% http://code.google.com/p/browsersec/wiki/Part2#Survey_of_content_sniffing_behaviors Padding = string:copies(" ", 1024 - size(IFrame)), Req3 = chunk(Req2, [IFrame, Padding, <<"\r\n\r\n">>]), reply_loop(Req3, SessionId, ResponseLimit, fun fmt_htmlfile/1, Service) end, verify_callback(Req, S). %% -spec jsonp(req(), headers(), service(), session()) -> req(). jsonp(Req, Headers, Service, SessionId) -> S = fun (Req1, CB) -> Req2 = chunk_start(Req1, Headers), reply_loop(Req2, SessionId, 1, fun (Body) -> fmt_jsonp(Body, CB) end, Service) end, verify_callback(Req, S). verify_callback(Req, Success) -> {CB, Req1} = sockjs_http:callback(Req), case CB of undefined -> sockjs_http:reply(500, [], "\"callback\" parameter required", Req1); _ -> Success(Req1, CB) end. %% -------------------------------------------------------------------------- %% -spec xhr_send(req(), headers(), service(), session()) -> req(). xhr_send(Req, Headers, _Service, Session) -> {Body, Req1} = sockjs_http:body(Req), case handle_recv(Req1, Body, Session) of {error, Req2} -> Req2; ok -> H = [{"content-type", "text/plain; charset=UTF-8"}], sockjs_http:reply(204, H ++ Headers, "", Req1) end. %% -spec jsonp_send(req(), headers(), service(), session()) -> req(). jsonp_send(Req, Headers, _Service, Session) -> {Body, Req1} = sockjs_http:body_qs(Req), case handle_recv(Req1, Body, Session) of {error, Req2} -> Req2; ok -> H = [{"content-type", "text/plain; charset=UTF-8"}], sockjs_http:reply(200, H ++ Headers, "ok", Req1) end. handle_recv(Req, Body, Session) -> case Body of _Any when Body =:= <<>> -> {error, sockjs_http:reply(500, [], "Payload expected.", Req)}; _Any -> case sockjs_json:decode(Body) of {ok, Decoded} when is_list(Decoded)-> sockjs_session:received(Decoded, Session), ok; {error, _} -> {error, sockjs_http:reply(500, [], "Broken JSON encoding.", Req)} end end. %% -------------------------------------------------------------------------- -define(STILL_OPEN, {2010, "Another connection still open"}). chunk_start(Req, Headers) -> chunk_start(Req, Headers, "application/javascript; charset=UTF-8"). chunk_start(Req, Headers, ContentType) -> sockjs_http:chunk_start(200, [{"Content-Type", ContentType}] ++ Headers, Req). reply_loop(Req, SessionId, ResponseLimit, Fmt, Service) -> Req0 = sockjs_http:hook_tcp_close(Req), case sockjs_session:reply(SessionId) of wait -> receive %% In Cowboy we need to capture async %% messages from the tcp connection - %% ie: {active, once}. {tcp_closed, _} -> Req0; %% In Cowboy we may in theory get real %% http requests, this is bad. {tcp, _S, Data} -> error_logger:error_msg( "Received unexpected data on a " "long-polling http connection: ~p. " "Connection aborted.~n", [Data]), Req1 = sockjs_http:abruptly_kill(Req), Req1; go -> Req1 = sockjs_http:unhook_tcp_close(Req0), reply_loop(Req1, SessionId, ResponseLimit, Fmt, Service) end; session_in_use -> Frame = sockjs_util:encode_frame({close, ?STILL_OPEN}), chunk_end(Req0, Frame, Fmt); {close, Frame} -> Frame1 = sockjs_util:encode_frame(Frame), chunk_end(Req0, Frame1, Fmt); {ok, Frame} -> Frame1 = sockjs_util:encode_frame(Frame), Frame2 = iolist_to_binary(Frame1), Req2 = chunk(Req0, Frame2, Fmt), reply_loop0(Req2, SessionId, ResponseLimit - size(Frame2), Fmt, Service) end. reply_loop0(Req, _SessionId, ResponseLimit, _Fmt, _Service) when ResponseLimit =< 0 -> chunk_end(Req); reply_loop0(Req, SessionId, ResponseLimit, Fmt, Service) -> reply_loop(Req, SessionId, ResponseLimit, Fmt, Service). chunk(Req, Body) -> {_, Req1} = sockjs_http:chunk(Body, Req), Req1. chunk(Req, Body, Fmt) -> chunk(Req, Fmt(Body)). chunk_end(Req) -> sockjs_http:chunk_end(Req). chunk_end(Req, Body, Fmt) -> Req1 = chunk(Req, Body, Fmt), chunk_end(Req1). %% -spec fmt_xhr(iodata()) -> iodata(). fmt_xhr(Body) -> [Body, "\n"]. %% -spec fmt_eventsource(iodata()) -> iodata(). fmt_eventsource(Body) -> Escaped = sockjs_util:url_escape(binary_to_list(iolist_to_binary(Body)), "%\r\n\0"), %% $% must be first! [<<"data: ">>, Escaped, <<"\r\n\r\n">>]. %% -spec fmt_htmlfile(iodata()) -> iodata(). fmt_htmlfile(Body) -> Double = sockjs_json:encode(iolist_to_binary(Body)), [<<"\r\n">>]. %% -spec fmt_jsonp(iodata(), iodata()) -> iodata(). fmt_jsonp(Body, Callback) -> %% Yes, JSONed twice, there isn't a a better way, we must pass %% a string back, and the script, will be evaled() by the %% browser. [Callback, "(", sockjs_json:encode(iolist_to_binary(Body)), ");\r\n"]. %% -------------------------------------------------------------------------- %% -spec websocket(req(), headers(), service()) -> req(). websocket(Req, Headers, Service) -> {_Any, Req1, {R1, R2}} = sockjs_handler:is_valid_ws(Service, Req), case {R1, R2} of {false, _} -> sockjs_http:reply(400, Headers, "Can \"Upgrade\" only to \"WebSocket\".", Req1); {_, false} -> sockjs_http:reply(400, Headers, "\"Connection\" must be \"Upgrade\"", Req1); {true, true} -> sockjs_http:reply(400, Headers, "This WebSocket request can't be handled.", Req1) end. %% -spec rawwebsocket(req(), headers(), service()) -> req(). rawwebsocket(Req, Headers, Service) -> websocket(Req, Headers, Service). rabbitmq-server-3.2.4/plugins-src/sockjs-erlang-wrapper/sockjs-erlang-git/src/sockjs.app.src0000644000000000000000000000034612305126066030713 0ustar rootroot{application, sockjs, [ {description, "SockJS"}, {vsn, "0.3.4"}, {modules, []}, {registered, []}, {applications, [ kernel, stdlib ]}, {mod, { sockjs_app, []}} ]}. rabbitmq-server-3.2.4/plugins-src/sockjs-erlang-wrapper/sockjs-erlang-git/src/sockjs_json.erl0000644000000000000000000000063212305126066031156 0ustar rootroot-module(sockjs_json). -export([encode/1, decode/1]). %% -------------------------------------------------------------------------- %% -spec encode(any()) -> iodata(). encode(Thing) -> mochijson2_fork:encode(Thing). %% -spec decode(iodata()) -> {ok, any()} | {error, any()}. decode(Encoded) -> try mochijson2_fork:decode(Encoded) of V -> {ok, V} catch _:E -> {error, E} end. rabbitmq-server-3.2.4/plugins-src/sockjs-erlang-wrapper/sockjs-erlang-git/src/sockjs_http.erl0000644000000000000000000001146412305126066031171 0ustar rootroot-module(sockjs_http). -export([path/1, method/1, body/1, body_qs/1, header/2, jsessionid/1, callback/1, peername/1, sockname/1]). -export([reply/4, chunk_start/3, chunk/2, chunk_end/1]). -export([hook_tcp_close/1, unhook_tcp_close/1, abruptly_kill/1]). -include("sockjs_internal.hrl"). %% -------------------------------------------------------------------------- %% -spec path(req()) -> {string(), req()}. path({cowboy, Req}) -> {Path, Req1} = cowboy_http_req:raw_path(Req), {binary_to_list(Path), {cowboy, Req1}}. %% -spec method(req()) -> {atom(), req()}. method({cowboy, Req}) -> {Method, Req1} = cowboy_http_req:method(Req), case is_binary(Method) of true -> {list_to_atom(binary_to_list(Method)), {cowboy, Req1}}; false -> {Method, {cowboy, Req1}} end. %% -spec body(req()) -> {binary(), req()}. body({cowboy, Req}) -> {ok, Body, Req1} = cowboy_http_req:body(Req), {Body, {cowboy, Req1}}. %% -spec body_qs(req()) -> {binary(), req()}. body_qs(Req) -> {H, Req1} = header('Content-Type', Req), case H of H when H =:= "text/plain" orelse H =:= "" -> body(Req1); _ -> %% By default assume application/x-www-form-urlencoded body_qs2(Req1) end. body_qs2({cowboy, Req}) -> {BodyQS, Req1} = cowboy_http_req:body_qs(Req), case proplists:get_value(<<"d">>, BodyQS) of undefined -> {<<>>, {cowboy, Req1}}; V -> {V, {cowboy, Req1}} end. %% -spec header(atom(), req()) -> {nonempty_string() | undefined, req()}. header(K, {cowboy, Req})-> {H, Req2} = cowboy_http_req:header(K, Req), {V, Req3} = case H of undefined -> cowboy_http_req:header(list_to_binary(atom_to_list(K)), Req2); _ -> {H, Req2} end, case V of undefined -> {undefined, {cowboy, Req3}}; _ -> {binary_to_list(V), {cowboy, Req3}} end. %% -spec jsessionid(req()) -> {nonempty_string() | undefined, req()}. jsessionid({cowboy, Req}) -> {C, Req2} = cowboy_http_req:cookie(<<"JSESSIONID">>, Req), case C of _ when is_binary(C) -> {binary_to_list(C), {cowboy, Req2}}; undefined -> {undefined, {cowboy, Req2}} end. %% -spec callback(req()) -> {nonempty_string() | undefined, req()}. callback({cowboy, Req}) -> {CB, Req1} = cowboy_http_req:qs_val(<<"c">>, Req), case CB of undefined -> {undefined, {cowboy, Req1}}; _ -> {binary_to_list(CB), {cowboy, Req1}} end. %% -spec peername(req()) -> {{inet:ip_address(), non_neg_integer()}, req()}. peername({cowboy, Req}) -> {P, Req1} = cowboy_http_req:peer(Req), {P, {cowboy, Req1}}. %% -spec sockname(req()) -> {{inet:ip_address(), non_neg_integer()}, req()}. sockname({cowboy, Req} = R) -> {ok, _T, S} = cowboy_http_req:transport(Req), %% Cowboy has peername(), but doesn't have sockname() equivalent. {ok, Addr} = case S of _ when is_port(S) -> inet:sockname(S); _ -> {ok, {{0,0,0,0}, 0}} end, {Addr, R}. %% -------------------------------------------------------------------------- %% -spec reply(non_neg_integer(), headers(), iodata(), req()) -> req(). reply(Code, Headers, Body, {cowboy, Req}) -> Body1 = iolist_to_binary(Body), {ok, Req1} = cowboy_http_req:reply(Code, enbinary(Headers), Body1, Req), {cowboy, Req1}. %% -spec chunk_start(non_neg_integer(), headers(), req()) -> req(). chunk_start(Code, Headers, {cowboy, Req}) -> {ok, Req1} = cowboy_http_req:chunked_reply(Code, enbinary(Headers), Req), {cowboy, Req1}. %% -spec chunk(iodata(), req()) -> {ok | error, req()}. chunk(Chunk, {cowboy, Req} = R) -> case cowboy_http_req:chunk(Chunk, Req) of ok -> {ok, R}; {error, _E} -> {error, R} %% This shouldn't happen too often, usually we %% should catch tco socket closure before. end. %% -spec chunk_end(req()) -> req(). chunk_end({cowboy, _Req} = R) -> R. enbinary(L) -> [{list_to_binary(K), list_to_binary(V)} || {K, V} <- L]. %% -spec hook_tcp_close(req()) -> req(). hook_tcp_close(R = {cowboy, Req}) -> {ok, T, S} = cowboy_http_req:transport(Req), T:setopts(S,[{active,once}]), R. %% -spec unhook_tcp_close(req()) -> req(). unhook_tcp_close(R = {cowboy, Req}) -> {ok, T, S} = cowboy_http_req:transport(Req), T:setopts(S,[{active,false}]), R. %% -spec abruptly_kill(req()) -> req(). abruptly_kill(R = {cowboy, Req}) -> {ok, T, S} = cowboy_http_req:transport(Req), T:close(S), R. rabbitmq-server-3.2.4/plugins-src/sockjs-erlang-wrapper/sockjs-erlang-git/src/mochijson2_fork.erl0000644000000000000000000010011212305126066031717 0ustar rootroot%% @author Bob Ippolito %% @copyright 2007 Mochi Media, Inc. %% Changes specific to SockJS: support for handling \xFFFE and \xFFFF %% characters. The usual xmerl_ucs:to_utf8 doesn't work for those (in %% fact these characters aren't valid unicode characters). But we can %% support them, why not: %% %% diff --git a/src/mochijson2_fork.erl b/src/mochijson2_fork.erl %% index ddd62c7..8c26fc6 100644 %% --- a/src/mochijson2_fork.erl %% +++ b/src/mochijson2_fork.erl %% @@ -458,7 +458,14 @@ tokenize_string(B, S=#decoder{offset=O}, Acc) -> %% Acc1 = lists:reverse(xmerl_ucs:to_utf8(CodePoint), Acc), %% tokenize_string(B, ?ADV_COL(S, 12), Acc1); %% true -> %% - Acc1 = lists:reverse(xmerl_ucs:to_utf8(C), Acc), %% + R = if C < 16#FFFE -> %% + xmerl_ucs:to_utf8(C); %% + true -> %% + [16#E0 + (C bsr 12), %% + 128+((C bsr 6) band 16#3F), %% + 128+(C band 16#3F)] %% + end, %% + Acc1 = lists:reverse(R, Acc), %% tokenize_string(B, ?ADV_COL(S, 6), Acc1) %% end; %% <<_:O/binary, C1, _/binary>> when C1 < 128 -> %% %% @doc Yet another JSON (RFC 4627) library for Erlang. mochijson2 works %% with binaries as strings, arrays as lists (without an {array, _}) %% wrapper and it only knows how to decode UTF-8 (and ASCII). %% %% JSON terms are decoded as follows (javascript -> erlang): %%
      %%
    • {"key": "value"} -> %% {struct, [{<<"key">>, <<"value">>}]}
    • %%
    • ["array", 123, 12.34, true, false, null] -> %% [<<"array">>, 123, 12.34, true, false, null] %%
    • %%
    %%
      %%
    • Strings in JSON decode to UTF-8 binaries in Erlang
    • %%
    • Objects decode to {struct, PropList}
    • %%
    • Numbers decode to integer or float
    • %%
    • true, false, null decode to their respective terms.
    • %%
    %% The encoder will accept the same format that the decoder will produce, %% but will also allow additional cases for leniency: %%
      %%
    • atoms other than true, false, null will be considered UTF-8 %% strings (even as a proplist key) %%
    • %%
    • {json, IoList} will insert IoList directly into the output %% with no validation %%
    • %%
    • {array, Array} will be encoded as Array %% (legacy mochijson style) %%
    • %%
    • A non-empty raw proplist will be encoded as an object as long %% as the first pair does not have an atom key of json, struct, %% or array %%
    • %%
    -module(mochijson2_fork). -author('bob@mochimedia.com'). -export([encoder/1, encode/1]). -export([decoder/1, decode/1, decode/2]). %% This is a macro to placate syntax highlighters.. -define(Q, $\"). -define(ADV_COL(S, N), S#decoder{offset=N+S#decoder.offset, column=N+S#decoder.column}). -define(INC_COL(S), S#decoder{offset=1+S#decoder.offset, column=1+S#decoder.column}). -define(INC_LINE(S), S#decoder{offset=1+S#decoder.offset, column=1, line=1+S#decoder.line}). -define(INC_CHAR(S, C), case C of $\n -> S#decoder{column=1, line=1+S#decoder.line, offset=1+S#decoder.offset}; _ -> S#decoder{column=1+S#decoder.column, offset=1+S#decoder.offset} end). -define(IS_WHITESPACE(C), (C =:= $\s orelse C =:= $\t orelse C =:= $\r orelse C =:= $\n)). %% -type(decoder_option() :: any()). %% -type(handler_option() :: any()). %% -type(json_string() :: atom | binary()). %% -type(json_number() :: integer() | float()). %% -type(json_array() :: [json_term()]). %% -type(json_object() :: {struct, [{json_string(), json_term()}]}). %% -type(json_eep18_object() :: {[{json_string(), json_term()}]}). %% -type(json_iolist() :: {json, iolist()}). %% -type(json_term() :: json_string() | json_number() | json_array() | %% json_object() | json_eep18_object() | json_iolist()). -record(encoder, {handler=null, utf8=false}). -record(decoder, {object_hook=null, offset=0, line=1, column=1, state=null}). %% -type(utf8_option() :: boolean()). %% -type(encoder_option() :: handler_option() | utf8_option()). %% -spec encoder([encoder_option()]) -> function(). %% @doc Create an encoder/1 with the given options. %% Emit unicode as utf8 (default - false) encoder(Options) -> State = parse_encoder_options(Options, #encoder{}), fun (O) -> json_encode(O, State) end. %% -spec encode(json_term()) -> iolist(). %% @doc Encode the given as JSON to an iolist. encode(Any) -> json_encode(Any, #encoder{}). %% -spec decoder([decoder_option()]) -> function(). %% @doc Create a decoder/1 with the given options. decoder(Options) -> State = parse_decoder_options(Options, #decoder{}), fun (O) -> json_decode(O, State) end. %% -spec decode(iolist(), [{format, proplist | eep18 | struct}]) -> json_term(). %% @doc Decode the given iolist to Erlang terms using the given object format %% for decoding, where proplist returns JSON objects as [{binary(), json_term()}] %% proplists, eep18 returns JSON objects as {[binary(), json_term()]}, and struct %% returns them as-is. decode(S, Options) -> json_decode(S, parse_decoder_options(Options, #decoder{})). %% -spec decode(iolist()) -> json_term(). %% @doc Decode the given iolist to Erlang terms. decode(S) -> json_decode(S, #decoder{}). %% Internal API parse_encoder_options([], State) -> State; parse_encoder_options([{handler, Handler} | Rest], State) -> parse_encoder_options(Rest, State#encoder{handler=Handler}); parse_encoder_options([{utf8, Switch} | Rest], State) -> parse_encoder_options(Rest, State#encoder{utf8=Switch}). parse_decoder_options([], State) -> State; parse_decoder_options([{object_hook, Hook} | Rest], State) -> parse_decoder_options(Rest, State#decoder{object_hook=Hook}); parse_decoder_options([{format, Format} | Rest], State) when Format =:= struct orelse Format =:= eep18 orelse Format =:= proplist -> parse_decoder_options(Rest, State#decoder{object_hook=Format}). json_encode(true, _State) -> <<"true">>; json_encode(false, _State) -> <<"false">>; json_encode(null, _State) -> <<"null">>; json_encode(I, _State) when is_integer(I) -> integer_to_list(I); json_encode(F, _State) when is_float(F) -> mochinum_fork:digits(F); json_encode(S, State) when is_binary(S); is_atom(S) -> json_encode_string(S, State); json_encode([{K, _}|_] = Props, State) when (K =/= struct andalso K =/= array andalso K =/= json) -> json_encode_proplist(Props, State); json_encode({struct, Props}, State) when is_list(Props) -> json_encode_proplist(Props, State); json_encode({Props}, State) when is_list(Props) -> json_encode_proplist(Props, State); json_encode({}, State) -> json_encode_proplist([], State); json_encode(Array, State) when is_list(Array) -> json_encode_array(Array, State); json_encode({array, Array}, State) when is_list(Array) -> json_encode_array(Array, State); json_encode({json, IoList}, _State) -> IoList; json_encode(Bad, #encoder{handler=null}) -> exit({json_encode, {bad_term, Bad}}); json_encode(Bad, State=#encoder{handler=Handler}) -> json_encode(Handler(Bad), State). json_encode_array([], _State) -> <<"[]">>; json_encode_array(L, State) -> F = fun (O, Acc) -> [$,, json_encode(O, State) | Acc] end, [$, | Acc1] = lists:foldl(F, "[", L), lists:reverse([$\] | Acc1]). json_encode_proplist([], _State) -> <<"{}">>; json_encode_proplist(Props, State) -> F = fun ({K, V}, Acc) -> KS = json_encode_string(K, State), VS = json_encode(V, State), [$,, VS, $:, KS | Acc] end, [$, | Acc1] = lists:foldl(F, "{", Props), lists:reverse([$\} | Acc1]). json_encode_string(A, State) when is_atom(A) -> L = atom_to_list(A), case json_string_is_safe(L) of true -> [?Q, L, ?Q]; false -> json_encode_string_unicode(xmerl_ucs:from_utf8(L), State, [?Q]) end; json_encode_string(B, State) when is_binary(B) -> case json_bin_is_safe(B) of true -> [?Q, B, ?Q]; false -> json_encode_string_unicode(xmerl_ucs:from_utf8(B), State, [?Q]) end; json_encode_string(I, _State) when is_integer(I) -> [?Q, integer_to_list(I), ?Q]; json_encode_string(L, State) when is_list(L) -> case json_string_is_safe(L) of true -> [?Q, L, ?Q]; false -> json_encode_string_unicode(L, State, [?Q]) end. json_string_is_safe([]) -> true; json_string_is_safe([C | Rest]) -> case C of ?Q -> false; $\\ -> false; $\b -> false; $\f -> false; $\n -> false; $\r -> false; $\t -> false; C when C >= 0, C < $\s; C >= 16#7f, C =< 16#10FFFF -> false; C when C < 16#7f -> json_string_is_safe(Rest); _ -> false end. json_bin_is_safe(<<>>) -> true; json_bin_is_safe(<>) -> case C of ?Q -> false; $\\ -> false; $\b -> false; $\f -> false; $\n -> false; $\r -> false; $\t -> false; C when C >= 0, C < $\s; C >= 16#7f -> false; C when C < 16#7f -> json_bin_is_safe(Rest) end. json_encode_string_unicode([], _State, Acc) -> lists:reverse([$\" | Acc]); json_encode_string_unicode([C | Cs], State, Acc) -> Acc1 = case C of ?Q -> [?Q, $\\ | Acc]; %% Escaping solidus is only useful when trying to protect %% against "" injection attacks which are only %% possible when JSON is inserted into a HTML document %% in-line. mochijson2 does not protect you from this, so %% if you do insert directly into HTML then you need to %% uncomment the following case or escape the output of encode. %% %% $/ -> %% [$/, $\\ | Acc]; %% $\\ -> [$\\, $\\ | Acc]; $\b -> [$b, $\\ | Acc]; $\f -> [$f, $\\ | Acc]; $\n -> [$n, $\\ | Acc]; $\r -> [$r, $\\ | Acc]; $\t -> [$t, $\\ | Acc]; C when C >= 0, C < $\s -> [unihex(C) | Acc]; C when C >= 16#7f, C =< 16#10FFFF, State#encoder.utf8 -> [xmerl_ucs:to_utf8(C) | Acc]; C when C >= 16#7f, C =< 16#10FFFF, not State#encoder.utf8 -> [unihex(C) | Acc]; C when C < 16#7f -> [C | Acc]; _ -> exit({json_encode, {bad_char, C}}) end, json_encode_string_unicode(Cs, State, Acc1). hexdigit(C) when C >= 0, C =< 9 -> C + $0; hexdigit(C) when C =< 15 -> C + $a - 10. unihex(C) when C < 16#10000 -> <> = <>, Digits = [hexdigit(D) || D <- [D3, D2, D1, D0]], [$\\, $u | Digits]; unihex(C) when C =< 16#10FFFF -> N = C - 16#10000, S1 = 16#d800 bor ((N bsr 10) band 16#3ff), S2 = 16#dc00 bor (N band 16#3ff), [unihex(S1), unihex(S2)]. json_decode(L, S) when is_list(L) -> json_decode(iolist_to_binary(L), S); json_decode(B, S) -> {Res, S1} = decode1(B, S), {eof, _} = tokenize(B, S1#decoder{state=trim}), Res. decode1(B, S=#decoder{state=null}) -> case tokenize(B, S#decoder{state=any}) of {{const, C}, S1} -> {C, S1}; {start_array, S1} -> decode_array(B, S1); {start_object, S1} -> decode_object(B, S1) end. make_object(V, #decoder{object_hook=N}) when N =:= null orelse N =:= struct -> V; make_object({struct, P}, #decoder{object_hook=eep18}) -> {P}; make_object({struct, P}, #decoder{object_hook=proplist}) -> P; make_object(V, #decoder{object_hook=Hook}) -> Hook(V). decode_object(B, S) -> decode_object(B, S#decoder{state=key}, []). decode_object(B, S=#decoder{state=key}, Acc) -> case tokenize(B, S) of {end_object, S1} -> V = make_object({struct, lists:reverse(Acc)}, S1), {V, S1#decoder{state=null}}; {{const, K}, S1} -> {colon, S2} = tokenize(B, S1), {V, S3} = decode1(B, S2#decoder{state=null}), decode_object(B, S3#decoder{state=comma}, [{K, V} | Acc]) end; decode_object(B, S=#decoder{state=comma}, Acc) -> case tokenize(B, S) of {end_object, S1} -> V = make_object({struct, lists:reverse(Acc)}, S1), {V, S1#decoder{state=null}}; {comma, S1} -> decode_object(B, S1#decoder{state=key}, Acc) end. decode_array(B, S) -> decode_array(B, S#decoder{state=any}, []). decode_array(B, S=#decoder{state=any}, Acc) -> case tokenize(B, S) of {end_array, S1} -> {lists:reverse(Acc), S1#decoder{state=null}}; {start_array, S1} -> {Array, S2} = decode_array(B, S1), decode_array(B, S2#decoder{state=comma}, [Array | Acc]); {start_object, S1} -> {Array, S2} = decode_object(B, S1), decode_array(B, S2#decoder{state=comma}, [Array | Acc]); {{const, Const}, S1} -> decode_array(B, S1#decoder{state=comma}, [Const | Acc]) end; decode_array(B, S=#decoder{state=comma}, Acc) -> case tokenize(B, S) of {end_array, S1} -> {lists:reverse(Acc), S1#decoder{state=null}}; {comma, S1} -> decode_array(B, S1#decoder{state=any}, Acc) end. tokenize_string(B, S=#decoder{offset=O}) -> case tokenize_string_fast(B, O) of {escape, O1} -> Length = O1 - O, S1 = ?ADV_COL(S, Length), <<_:O/binary, Head:Length/binary, _/binary>> = B, tokenize_string(B, S1, lists:reverse(binary_to_list(Head))); O1 -> Length = O1 - O, <<_:O/binary, String:Length/binary, ?Q, _/binary>> = B, {{const, String}, ?ADV_COL(S, Length + 1)} end. tokenize_string_fast(B, O) -> case B of <<_:O/binary, ?Q, _/binary>> -> O; <<_:O/binary, $\\, _/binary>> -> {escape, O}; <<_:O/binary, C1, _/binary>> when C1 < 128 -> tokenize_string_fast(B, 1 + O); <<_:O/binary, C1, C2, _/binary>> when C1 >= 194, C1 =< 223, C2 >= 128, C2 =< 191 -> tokenize_string_fast(B, 2 + O); <<_:O/binary, C1, C2, C3, _/binary>> when C1 >= 224, C1 =< 239, C2 >= 128, C2 =< 191, C3 >= 128, C3 =< 191 -> tokenize_string_fast(B, 3 + O); <<_:O/binary, C1, C2, C3, C4, _/binary>> when C1 >= 240, C1 =< 244, C2 >= 128, C2 =< 191, C3 >= 128, C3 =< 191, C4 >= 128, C4 =< 191 -> tokenize_string_fast(B, 4 + O); _ -> throw(invalid_utf8) end. tokenize_string(B, S=#decoder{offset=O}, Acc) -> case B of <<_:O/binary, ?Q, _/binary>> -> {{const, iolist_to_binary(lists:reverse(Acc))}, ?INC_COL(S)}; <<_:O/binary, "\\\"", _/binary>> -> tokenize_string(B, ?ADV_COL(S, 2), [$\" | Acc]); <<_:O/binary, "\\\\", _/binary>> -> tokenize_string(B, ?ADV_COL(S, 2), [$\\ | Acc]); <<_:O/binary, "\\/", _/binary>> -> tokenize_string(B, ?ADV_COL(S, 2), [$/ | Acc]); <<_:O/binary, "\\b", _/binary>> -> tokenize_string(B, ?ADV_COL(S, 2), [$\b | Acc]); <<_:O/binary, "\\f", _/binary>> -> tokenize_string(B, ?ADV_COL(S, 2), [$\f | Acc]); <<_:O/binary, "\\n", _/binary>> -> tokenize_string(B, ?ADV_COL(S, 2), [$\n | Acc]); <<_:O/binary, "\\r", _/binary>> -> tokenize_string(B, ?ADV_COL(S, 2), [$\r | Acc]); <<_:O/binary, "\\t", _/binary>> -> tokenize_string(B, ?ADV_COL(S, 2), [$\t | Acc]); <<_:O/binary, "\\u", C3, C2, C1, C0, Rest/binary>> -> C = erlang:list_to_integer([C3, C2, C1, C0], 16), if C > 16#D7FF, C < 16#DC00 -> %% coalesce UTF-16 surrogate pair <<"\\u", D3, D2, D1, D0, _/binary>> = Rest, D = erlang:list_to_integer([D3,D2,D1,D0], 16), [CodePoint] = xmerl_ucs:from_utf16be(<>), Acc1 = lists:reverse(xmerl_ucs:to_utf8(CodePoint), Acc), tokenize_string(B, ?ADV_COL(S, 12), Acc1); true -> R = if C < 16#FFFE -> xmerl_ucs:to_utf8(C); true -> [16#E0 + (C bsr 12), 128+((C bsr 6) band 16#3F), 128+(C band 16#3F)] end, Acc1 = lists:reverse(R, Acc), tokenize_string(B, ?ADV_COL(S, 6), Acc1) end; <<_:O/binary, C1, _/binary>> when C1 < 128 -> tokenize_string(B, ?INC_CHAR(S, C1), [C1 | Acc]); <<_:O/binary, C1, C2, _/binary>> when C1 >= 194, C1 =< 223, C2 >= 128, C2 =< 191 -> tokenize_string(B, ?ADV_COL(S, 2), [C2, C1 | Acc]); <<_:O/binary, C1, C2, C3, _/binary>> when C1 >= 224, C1 =< 239, C2 >= 128, C2 =< 191, C3 >= 128, C3 =< 191 -> tokenize_string(B, ?ADV_COL(S, 3), [C3, C2, C1 | Acc]); <<_:O/binary, C1, C2, C3, C4, _/binary>> when C1 >= 240, C1 =< 244, C2 >= 128, C2 =< 191, C3 >= 128, C3 =< 191, C4 >= 128, C4 =< 191 -> tokenize_string(B, ?ADV_COL(S, 4), [C4, C3, C2, C1 | Acc]); _ -> throw(invalid_utf8) end. tokenize_number(B, S) -> case tokenize_number(B, sign, S, []) of {{int, Int}, S1} -> {{const, list_to_integer(Int)}, S1}; {{float, Float}, S1} -> {{const, list_to_float(Float)}, S1} end. tokenize_number(B, sign, S=#decoder{offset=O}, []) -> case B of <<_:O/binary, $-, _/binary>> -> tokenize_number(B, int, ?INC_COL(S), [$-]); _ -> tokenize_number(B, int, S, []) end; tokenize_number(B, int, S=#decoder{offset=O}, Acc) -> case B of <<_:O/binary, $0, _/binary>> -> tokenize_number(B, frac, ?INC_COL(S), [$0 | Acc]); <<_:O/binary, C, _/binary>> when C >= $1 andalso C =< $9 -> tokenize_number(B, int1, ?INC_COL(S), [C | Acc]) end; tokenize_number(B, int1, S=#decoder{offset=O}, Acc) -> case B of <<_:O/binary, C, _/binary>> when C >= $0 andalso C =< $9 -> tokenize_number(B, int1, ?INC_COL(S), [C | Acc]); _ -> tokenize_number(B, frac, S, Acc) end; tokenize_number(B, frac, S=#decoder{offset=O}, Acc) -> case B of <<_:O/binary, $., C, _/binary>> when C >= $0, C =< $9 -> tokenize_number(B, frac1, ?ADV_COL(S, 2), [C, $. | Acc]); <<_:O/binary, E, _/binary>> when E =:= $e orelse E =:= $E -> tokenize_number(B, esign, ?INC_COL(S), [$e, $0, $. | Acc]); _ -> {{int, lists:reverse(Acc)}, S} end; tokenize_number(B, frac1, S=#decoder{offset=O}, Acc) -> case B of <<_:O/binary, C, _/binary>> when C >= $0 andalso C =< $9 -> tokenize_number(B, frac1, ?INC_COL(S), [C | Acc]); <<_:O/binary, E, _/binary>> when E =:= $e orelse E =:= $E -> tokenize_number(B, esign, ?INC_COL(S), [$e | Acc]); _ -> {{float, lists:reverse(Acc)}, S} end; tokenize_number(B, esign, S=#decoder{offset=O}, Acc) -> case B of <<_:O/binary, C, _/binary>> when C =:= $- orelse C=:= $+ -> tokenize_number(B, eint, ?INC_COL(S), [C | Acc]); _ -> tokenize_number(B, eint, S, Acc) end; tokenize_number(B, eint, S=#decoder{offset=O}, Acc) -> case B of <<_:O/binary, C, _/binary>> when C >= $0 andalso C =< $9 -> tokenize_number(B, eint1, ?INC_COL(S), [C | Acc]) end; tokenize_number(B, eint1, S=#decoder{offset=O}, Acc) -> case B of <<_:O/binary, C, _/binary>> when C >= $0 andalso C =< $9 -> tokenize_number(B, eint1, ?INC_COL(S), [C | Acc]); _ -> {{float, lists:reverse(Acc)}, S} end. tokenize(B, S=#decoder{offset=O}) -> case B of <<_:O/binary, C, _/binary>> when ?IS_WHITESPACE(C) -> tokenize(B, ?INC_CHAR(S, C)); <<_:O/binary, "{", _/binary>> -> {start_object, ?INC_COL(S)}; <<_:O/binary, "}", _/binary>> -> {end_object, ?INC_COL(S)}; <<_:O/binary, "[", _/binary>> -> {start_array, ?INC_COL(S)}; <<_:O/binary, "]", _/binary>> -> {end_array, ?INC_COL(S)}; <<_:O/binary, ",", _/binary>> -> {comma, ?INC_COL(S)}; <<_:O/binary, ":", _/binary>> -> {colon, ?INC_COL(S)}; <<_:O/binary, "null", _/binary>> -> {{const, null}, ?ADV_COL(S, 4)}; <<_:O/binary, "true", _/binary>> -> {{const, true}, ?ADV_COL(S, 4)}; <<_:O/binary, "false", _/binary>> -> {{const, false}, ?ADV_COL(S, 5)}; <<_:O/binary, "\"", _/binary>> -> tokenize_string(B, ?INC_COL(S)); <<_:O/binary, C, _/binary>> when (C >= $0 andalso C =< $9) orelse C =:= $- -> tokenize_number(B, S); <<_:O/binary>> -> trim = S#decoder.state, {eof, S} end. %% %% Tests %% -ifdef(TEST). -include_lib("eunit/include/eunit.hrl"). %% testing constructs borrowed from the Yaws JSON implementation. %% Create an object from a list of Key/Value pairs. obj_new() -> {struct, []}. is_obj({struct, Props}) -> F = fun ({K, _}) when is_binary(K) -> true end, lists:all(F, Props). obj_from_list(Props) -> Obj = {struct, Props}, ?assert(is_obj(Obj)), Obj. %% Test for equivalence of Erlang terms. %% Due to arbitrary order of construction, equivalent objects might %% compare unequal as erlang terms, so we need to carefully recurse %% through aggregates (tuples and objects). equiv({struct, Props1}, {struct, Props2}) -> equiv_object(Props1, Props2); equiv(L1, L2) when is_list(L1), is_list(L2) -> equiv_list(L1, L2); equiv(N1, N2) when is_number(N1), is_number(N2) -> N1 == N2; equiv(B1, B2) when is_binary(B1), is_binary(B2) -> B1 == B2; equiv(A, A) when A =:= true orelse A =:= false orelse A =:= null -> true. %% Object representation and traversal order is unknown. %% Use the sledgehammer and sort property lists. equiv_object(Props1, Props2) -> L1 = lists:keysort(1, Props1), L2 = lists:keysort(1, Props2), Pairs = lists:zip(L1, L2), true = lists:all(fun({{K1, V1}, {K2, V2}}) -> equiv(K1, K2) and equiv(V1, V2) end, Pairs). %% Recursively compare tuple elements for equivalence. equiv_list([], []) -> true; equiv_list([V1 | L1], [V2 | L2]) -> equiv(V1, V2) andalso equiv_list(L1, L2). decode_test() -> [1199344435545.0, 1] = decode(<<"[1199344435545.0,1]">>), <<16#F0,16#9D,16#9C,16#95>> = decode([34,"\\ud835","\\udf15",34]). e2j_vec_test() -> test_one(e2j_test_vec(utf8), 1). test_one([], _N) -> %% io:format("~p tests passed~n", [N-1]), ok; test_one([{E, J} | Rest], N) -> %% io:format("[~p] ~p ~p~n", [N, E, J]), true = equiv(E, decode(J)), true = equiv(E, decode(encode(E))), test_one(Rest, 1+N). e2j_test_vec(utf8) -> [ {1, "1"}, {3.1416, "3.14160"}, %% text representation may truncate, trail zeroes {-1, "-1"}, {-3.1416, "-3.14160"}, {12.0e10, "1.20000e+11"}, {1.234E+10, "1.23400e+10"}, {-1.234E-10, "-1.23400e-10"}, {10.0, "1.0e+01"}, {123.456, "1.23456E+2"}, {10.0, "1e1"}, {<<"foo">>, "\"foo\""}, {<<"foo", 5, "bar">>, "\"foo\\u0005bar\""}, {<<"">>, "\"\""}, {<<"\n\n\n">>, "\"\\n\\n\\n\""}, {<<"\" \b\f\r\n\t\"">>, "\"\\\" \\b\\f\\r\\n\\t\\\"\""}, {obj_new(), "{}"}, {obj_from_list([{<<"foo">>, <<"bar">>}]), "{\"foo\":\"bar\"}"}, {obj_from_list([{<<"foo">>, <<"bar">>}, {<<"baz">>, 123}]), "{\"foo\":\"bar\",\"baz\":123}"}, {[], "[]"}, {[[]], "[[]]"}, {[1, <<"foo">>], "[1,\"foo\"]"}, %% json array in a json object {obj_from_list([{<<"foo">>, [123]}]), "{\"foo\":[123]}"}, %% json object in a json object {obj_from_list([{<<"foo">>, obj_from_list([{<<"bar">>, true}])}]), "{\"foo\":{\"bar\":true}}"}, %% fold evaluation order {obj_from_list([{<<"foo">>, []}, {<<"bar">>, obj_from_list([{<<"baz">>, true}])}, {<<"alice">>, <<"bob">>}]), "{\"foo\":[],\"bar\":{\"baz\":true},\"alice\":\"bob\"}"}, %% json object in a json array {[-123, <<"foo">>, obj_from_list([{<<"bar">>, []}]), null], "[-123,\"foo\",{\"bar\":[]},null]"} ]. %% test utf8 encoding encoder_utf8_test() -> %% safe conversion case (default) [34,"\\u0001","\\u0442","\\u0435","\\u0441","\\u0442",34] = encode(<<1,"\321\202\320\265\321\201\321\202">>), %% raw utf8 output (optional) Enc = mochijson2:encoder([{utf8, true}]), [34,"\\u0001",[209,130],[208,181],[209,129],[209,130],34] = Enc(<<1,"\321\202\320\265\321\201\321\202">>). input_validation_test() -> Good = [ {16#00A3, <>}, %% pound {16#20AC, <>}, %% euro {16#10196, <>} %% denarius ], lists:foreach(fun({CodePoint, UTF8}) -> Expect = list_to_binary(xmerl_ucs:to_utf8(CodePoint)), Expect = decode(UTF8) end, Good), Bad = [ %% 2nd, 3rd, or 4th byte of a multi-byte sequence w/o leading byte <>, %% missing continuations, last byte in each should be 80-BF <>, <>, <>, %% we don't support code points > 10FFFF per RFC 3629 <>, %% escape characters trigger a different code path <> ], lists:foreach( fun(X) -> ok = try decode(X) catch invalid_utf8 -> ok end, %% could be {ucs,{bad_utf8_character_code}} or %% {json_encode,{bad_char,_}} {'EXIT', _} = (catch encode(X)) end, Bad). inline_json_test() -> ?assertEqual(<<"\"iodata iodata\"">>, iolist_to_binary( encode({json, [<<"\"iodata">>, " iodata\""]}))), ?assertEqual({struct, [{<<"key">>, <<"iodata iodata">>}]}, decode( encode({struct, [{key, {json, [<<"\"iodata">>, " iodata\""]}}]}))), ok. big_unicode_test() -> UTF8Seq = list_to_binary(xmerl_ucs:to_utf8(16#0001d120)), ?assertEqual( <<"\"\\ud834\\udd20\"">>, iolist_to_binary(encode(UTF8Seq))), ?assertEqual( UTF8Seq, decode(iolist_to_binary(encode(UTF8Seq)))), ok. custom_decoder_test() -> ?assertEqual( {struct, [{<<"key">>, <<"value">>}]}, (decoder([]))("{\"key\": \"value\"}")), F = fun ({struct, [{<<"key">>, <<"value">>}]}) -> win end, ?assertEqual( win, (decoder([{object_hook, F}]))("{\"key\": \"value\"}")), ok. atom_test() -> %% JSON native atoms [begin ?assertEqual(A, decode(atom_to_list(A))), ?assertEqual(iolist_to_binary(atom_to_list(A)), iolist_to_binary(encode(A))) end || A <- [true, false, null]], %% Atom to string ?assertEqual( <<"\"foo\"">>, iolist_to_binary(encode(foo))), ?assertEqual( <<"\"\\ud834\\udd20\"">>, iolist_to_binary(encode(list_to_atom(xmerl_ucs:to_utf8(16#0001d120))))), ok. key_encode_test() -> %% Some forms are accepted as keys that would not be strings in other %% cases ?assertEqual( <<"{\"foo\":1}">>, iolist_to_binary(encode({struct, [{foo, 1}]}))), ?assertEqual( <<"{\"foo\":1}">>, iolist_to_binary(encode({struct, [{<<"foo">>, 1}]}))), ?assertEqual( <<"{\"foo\":1}">>, iolist_to_binary(encode({struct, [{"foo", 1}]}))), ?assertEqual( <<"{\"foo\":1}">>, iolist_to_binary(encode([{foo, 1}]))), ?assertEqual( <<"{\"foo\":1}">>, iolist_to_binary(encode([{<<"foo">>, 1}]))), ?assertEqual( <<"{\"foo\":1}">>, iolist_to_binary(encode([{"foo", 1}]))), ?assertEqual( <<"{\"\\ud834\\udd20\":1}">>, iolist_to_binary( encode({struct, [{[16#0001d120], 1}]}))), ?assertEqual( <<"{\"1\":1}">>, iolist_to_binary(encode({struct, [{1, 1}]}))), ok. unsafe_chars_test() -> Chars = "\"\\\b\f\n\r\t", [begin ?assertEqual(false, json_string_is_safe([C])), ?assertEqual(false, json_bin_is_safe(<>)), ?assertEqual(<>, decode(encode(<>))) end || C <- Chars], ?assertEqual( false, json_string_is_safe([16#0001d120])), ?assertEqual( false, json_bin_is_safe(list_to_binary(xmerl_ucs:to_utf8(16#0001d120)))), ?assertEqual( [16#0001d120], xmerl_ucs:from_utf8( binary_to_list( decode(encode(list_to_atom(xmerl_ucs:to_utf8(16#0001d120))))))), ?assertEqual( false, json_string_is_safe([16#110000])), ?assertEqual( false, json_bin_is_safe(list_to_binary(xmerl_ucs:to_utf8([16#110000])))), %% solidus can be escaped but isn't unsafe by default ?assertEqual( <<"/">>, decode(<<"\"\\/\"">>)), ok. int_test() -> ?assertEqual(0, decode("0")), ?assertEqual(1, decode("1")), ?assertEqual(11, decode("11")), ok. large_int_test() -> ?assertEqual(<<"-2147483649214748364921474836492147483649">>, iolist_to_binary(encode(-2147483649214748364921474836492147483649))), ?assertEqual(<<"2147483649214748364921474836492147483649">>, iolist_to_binary(encode(2147483649214748364921474836492147483649))), ok. float_test() -> ?assertEqual(<<"-2147483649.0">>, iolist_to_binary(encode(-2147483649.0))), ?assertEqual(<<"2147483648.0">>, iolist_to_binary(encode(2147483648.0))), ok. handler_test() -> ?assertEqual( {'EXIT',{json_encode,{bad_term,{x,y}}}}, catch encode({x,y})), F = fun ({x,y}) -> [] end, ?assertEqual( <<"[]">>, iolist_to_binary((encoder([{handler, F}]))({x, y}))), ok. encode_empty_test_() -> [{A, ?_assertEqual(<<"{}">>, iolist_to_binary(encode(B)))} || {A, B} <- [{"eep18 {}", {}}, {"eep18 {[]}", {[]}}, {"{struct, []}", {struct, []}}]]. encode_test_() -> P = [{<<"k">>, <<"v">>}], JSON = iolist_to_binary(encode({struct, P})), [{atom_to_list(F), ?_assertEqual(JSON, iolist_to_binary(encode(decode(JSON, [{format, F}]))))} || F <- [struct, eep18, proplist]]. format_test_() -> P = [{<<"k">>, <<"v">>}], JSON = iolist_to_binary(encode({struct, P})), [{atom_to_list(F), ?_assertEqual(A, decode(JSON, [{format, F}]))} || {F, A} <- [{struct, {struct, P}}, {eep18, {P}}, {proplist, P}]]. -endif. rabbitmq-server-3.2.4/plugins-src/sockjs-erlang-wrapper/sockjs-erlang-git/src/sockjs_handler.erl0000644000000000000000000002224712305126066031630 0ustar rootroot-module(sockjs_handler). -export([init_state/4]). -export([is_valid_ws/2, get_action/2]). -export([dispatch_req/2, handle_req/2]). -export([extract_info/1]). -include("sockjs_internal.hrl"). -define(SOCKJS_URL, "http://cdn.sockjs.org/sockjs-0.2.js"). %% -------------------------------------------------------------------------- %% -spec init_state(binary(), callback(), any(), list(tuple())) -> service(). init_state(Prefix, Callback, State, Options) -> #service{prefix = binary_to_list(Prefix), callback = Callback, state = State, sockjs_url = proplists:get_value(sockjs_url, Options, ?SOCKJS_URL), websocket = proplists:get_value(websocket, Options, true), cookie_needed = proplists:get_value(cookie_needed, Options, false), disconnect_delay = proplists:get_value(disconnect_delay, Options, 5000), heartbeat_delay = proplists:get_value(heartbeat_delay, Options, 25000), response_limit = proplists:get_value(response_limit, Options, 128*1024), logger = proplists:get_value(logger, Options, fun default_logger/3) }. %% -------------------------------------------------------------------------- %% -spec is_valid_ws(service(), req()) -> {boolean(), req(), tuple()}. is_valid_ws(Service, Req) -> case get_action(Service, Req) of {{match, WS}, Req1} when WS =:= websocket orelse WS =:= rawwebsocket -> valid_ws_request(Service, Req1); {_Else, Req1} -> {false, Req1, {}} end. %% -spec valid_ws_request(service(), req()) -> {boolean(), req(), tuple()}. valid_ws_request(_Service, Req) -> {R1, Req1} = valid_ws_upgrade(Req), {R2, Req2} = valid_ws_connection(Req1), {R1 and R2, Req2, {R1, R2}}. valid_ws_upgrade(Req) -> case sockjs_http:header('Upgrade', Req) of {undefined, Req2} -> {false, Req2}; {V, Req2} -> case string:to_lower(V) of "websocket" -> {true, Req2}; _Else -> {false, Req2} end end. valid_ws_connection(Req) -> case sockjs_http:header('Connection', Req) of {undefined, Req2} -> {false, Req2}; {V, Req2} -> Vs = [string:strip(T) || T <- string:tokens(string:to_lower(V), ",")], {lists:member("upgrade", Vs), Req2} end. %% -spec get_action(service(), req()) -> {nomatch | {match, atom()}, req()}. get_action(Service, Req) -> {Dispatch, Req1} = dispatch_req(Service, Req), case Dispatch of {match, {_, Action, _, _, _}} -> {{match, Action}, Req1}; _Else -> {nomatch, Req1} end. %% -------------------------------------------------------------------------- strip_prefix(LongPath, Prefix) -> {A, B} = lists:split(length(Prefix), LongPath), case Prefix of A -> {ok, B}; _Any -> {error, io_lib:format("Wrong prefix: ~p is not ~p", [A, Prefix])} end. %% -type(dispatch_result() :: %% nomatch | %% {match, {send | recv | none , atom(), %% server(), session(), list(atom())}} | %% {bad_method, list(atom())}). %% -spec dispatch_req(service(), req()) -> {dispatch_result(), req()}. dispatch_req(#service{prefix = Prefix}, Req) -> {Method, Req1} = sockjs_http:method(Req), {LongPath, Req2} = sockjs_http:path(Req1), {ok, PathRemainder} = strip_prefix(LongPath, Prefix), {dispatch(Method, PathRemainder), Req2}. %% -spec dispatch(atom(), nonempty_string()) -> dispatch_result(). dispatch(Method, Path) -> lists:foldl( fun ({Match, MethodFilters}, nomatch) -> case Match(Path) of nomatch -> nomatch; [Server, Session] -> case lists:keyfind(Method, 1, MethodFilters) of false -> Methods = [ K || {K, _, _, _} <- MethodFilters], {bad_method, Methods}; {_Method, Type, A, Filters} -> {match, {Type, A, Server, Session, Filters}} end end; (_, Result) -> Result end, nomatch, filters()). %% -------------------------------------------------------------------------- filters() -> OptsFilters = [h_sid, xhr_cors, cache_for, xhr_options_post], %% websocket does not actually go via handle_req/3 but we need %% something in dispatch/2 [{t("/websocket"), [{'GET', none, websocket, []}]}, {t("/xhr_send"), [{'POST', recv, xhr_send, [h_sid, h_no_cache, xhr_cors]}, {'OPTIONS', none, options, OptsFilters}]}, {t("/xhr"), [{'POST', send, xhr_polling, [h_sid, h_no_cache, xhr_cors]}, {'OPTIONS', none, options, OptsFilters}]}, {t("/xhr_streaming"), [{'POST', send, xhr_streaming, [h_sid, h_no_cache, xhr_cors]}, {'OPTIONS', none, options, OptsFilters}]}, {t("/jsonp_send"), [{'POST', recv, jsonp_send, [h_sid, h_no_cache]}]}, {t("/jsonp"), [{'GET', send, jsonp, [h_sid, h_no_cache]}]}, {t("/eventsource"), [{'GET', send, eventsource, [h_sid, h_no_cache]}]}, {t("/htmlfile"), [{'GET', send, htmlfile, [h_sid, h_no_cache]}]}, {p("/websocket"), [{'GET', none, rawwebsocket, []}]}, {p(""), [{'GET', none, welcome_screen, []}]}, {p("/iframe[0-9-.a-z_]*.html"), [{'GET', none, iframe, [cache_for]}]}, {p("/info"), [{'GET', none, info_test, [h_no_cache, xhr_cors]}, {'OPTIONS', none, options, [h_sid, xhr_cors, cache_for, xhr_options_get]}]} ]. p(S) -> fun (Path) -> re(Path, "^" ++ S ++ "[/]?\$") end. t(S) -> fun (Path) -> re(Path, "^/([^/.]+)/([^/.]+)" ++ S ++ "[/]?\$") end. re(Path, S) -> case re:run(Path, S, [{capture, all_but_first, list}]) of nomatch -> nomatch; {match, []} -> [dummy, dummy]; {match, [Server, Session]} -> [Server, Session] end. %% -------------------------------------------------------------------------- %% -spec handle_req(service(), req()) -> req(). handle_req(Service = #service{logger = Logger}, Req) -> Req0 = Logger(Service, Req, http), {Dispatch, Req1} = dispatch_req(Service, Req0), handle(Dispatch, Service, Req1). handle(nomatch, _Service, Req) -> sockjs_http:reply(404, [], "", Req); handle({bad_method, Methods}, _Service, Req) -> MethodsStr = string:join([atom_to_list(M) || M <- Methods], ", "), H = [{"Allow", MethodsStr}], sockjs_http:reply(405, H, "", Req); handle({match, {Type, Action, _Server, Session, Filters}}, Service, Req) -> {Headers, Req2} = lists:foldl( fun (Filter, {Headers0, Req1}) -> sockjs_filters:Filter(Req1, Headers0) end, {[], Req}, Filters), case Type of send -> {Info, Req3} = extract_info(Req2), _SPid = sockjs_session:maybe_create(Session, Service, Info), sockjs_action:Action(Req3, Headers, Service, Session); recv -> try sockjs_action:Action(Req2, Headers, Service, Session) catch throw:no_session -> {H, Req3} = sockjs_filters:h_sid(Req2, []), sockjs_http:reply(404, H, "", Req3) end; none -> sockjs_action:Action(Req2, Headers, Service) end. %% -------------------------------------------------------------------------- %% -spec default_logger(service(), req(), websocket | http) -> req(). default_logger(_Service, Req, _Type) -> {LongPath, Req1} = sockjs_http:path(Req), {Method, Req2} = sockjs_http:method(Req1), io:format("~s ~s~n", [Method, LongPath]), Req2. %% -spec extract_info(req()) -> {info(), req()}. extract_info(Req) -> {Peer, Req0} = sockjs_http:peername(Req), {Sock, Req1} = sockjs_http:sockname(Req0), {Path, Req2} = sockjs_http:path(Req1), {Headers, Req3} = lists:foldl(fun (H, {Acc, R0}) -> case sockjs_http:header(H, R0) of {undefined, R1} -> {Acc, R1}; {V, R1} -> {[{H, V} | Acc], R1} end end, {[], Req2}, ['Referer', 'X-Client-Ip', 'X-Forwarded-For', 'X-Cluster-Client-Ip', 'Via', 'X-Real-Ip']), {[{peername, Peer}, {sockname, Sock}, {path, Path}, {headers, Headers}], Req3}. rabbitmq-server-3.2.4/plugins-src/sockjs-erlang-wrapper/sockjs-erlang-git/src/sockjs_ws_handler.erl0000644000000000000000000000356212305126066032340 0ustar rootroot-module(sockjs_ws_handler). -export([received/3, reply/2, close/2]). -include("sockjs_internal.hrl"). %% -------------------------------------------------------------------------- %% -spec received(websocket|rawwebsocket, pid(), binary()) -> ok | shutdown. %% Ignore empty received(_RawWebsocket, _SessionPid, <<>>) -> ok; received(websocket, SessionPid, Data) -> case sockjs_json:decode(Data) of {ok, Msg} when is_binary(Msg) -> session_received([Msg], SessionPid); {ok, Messages} when is_list(Messages) -> session_received(Messages, SessionPid); _Else -> shutdown end; received(rawwebsocket, SessionPid, Data) -> session_received([Data], SessionPid). session_received(Messages, SessionPid) -> try sockjs_session:received(Messages, SessionPid) of ok -> ok catch no_session -> shutdown end. %% -spec reply(websocket|rawwebsocket, pid()) -> {close|open, binary()} | wait. reply(websocket, SessionPid) -> case sockjs_session:reply(SessionPid) of {W, Frame} when W =:= ok orelse W =:= close-> Frame1 = sockjs_util:encode_frame(Frame), {W, iolist_to_binary(Frame1)}; wait -> wait end; reply(rawwebsocket, SessionPid) -> case sockjs_session:reply(SessionPid, false) of {W, Frame} when W =:= ok orelse W =:= close-> case Frame of {open, nil} -> reply(rawwebsocket, SessionPid); {close, {_Code, _Reason}} -> {close, <<>>}; {data, [Msg]} -> {ok, iolist_to_binary(Msg)}; {heartbeat, nil} -> reply(rawwebsocket, SessionPid) end; wait -> wait end. %% -spec close(websocket|rawwebsocket, pid()) -> ok. close(_RawWebsocket, SessionPid) -> SessionPid ! force_shutdown, ok. ././@LongLink0000000000000000000000000000015300000000000011564 Lustar rootrootrabbitmq-server-3.2.4/plugins-src/sockjs-erlang-wrapper/sockjs-erlang-git/src/sockjs_multiplex_channel.erlrabbitmq-server-3.2.4/plugins-src/sockjs-erlang-wrapper/sockjs-erlang-git/src/sockjs_multiplex_chann0000644000000000000000000000060612305126066032617 0ustar rootroot-compile({parse_transform,pmod_pt}). -module(sockjs_multiplex_channel, [Conn, Topic]). -export([send/1, close/0, close/2, info/0]). send(Data) -> Conn:send(iolist_to_binary(["msg", ",", Topic, ",", Data])). close() -> close(1000, "Normal closure"). close(_Code, _Reason) -> Conn:send(iolist_to_binary(["uns", ",", Topic])). info() -> Conn:info() ++ [{topic, Topic}]. rabbitmq-server-3.2.4/plugins-src/sockjs-erlang-wrapper/sockjs-erlang-git/src/sockjs_util.erl0000644000000000000000000000232012305126066031156 0ustar rootroot-module(sockjs_util). -export([rand32/0]). -export([encode_frame/1]). -export([url_escape/2]). -include("sockjs_internal.hrl"). %% -------------------------------------------------------------------------- %% -spec rand32() -> non_neg_integer(). rand32() -> case get(random_seeded) of undefined -> {MegaSecs, Secs, MicroSecs} = now(), _ = random:seed(MegaSecs, Secs, MicroSecs), put(random_seeded, true); _Else -> ok end, random:uniform(erlang:trunc(math:pow(2,32)))-1. %% -spec encode_frame(frame()) -> iodata(). encode_frame({open, nil}) -> <<"o">>; encode_frame({close, {Code, Reason}}) -> [<<"c">>, sockjs_json:encode([Code, list_to_binary(Reason)])]; encode_frame({data, L}) -> [<<"a">>, sockjs_json:encode([iolist_to_binary(D) || D <- L])]; encode_frame({heartbeat, nil}) -> <<"h">>. %% -spec url_escape(string(), string()) -> iolist(). url_escape(Str, Chars) -> [case lists:member(Char, Chars) of true -> hex(Char); false -> Char end || Char <- Str]. hex(C) -> <> = <>, High = integer_to_list(High0), Low = integer_to_list(Low0), "%" ++ High ++ Low. rabbitmq-server-3.2.4/plugins-src/sockjs-erlang-wrapper/sockjs-erlang-git/src/sockjs_session.erl0000644000000000000000000002734412305126066031701 0ustar rootroot-module(sockjs_session). -behaviour(gen_server). -export([init/0, start_link/3]). -export([maybe_create/3, reply/1, reply/2, received/2]). -export([send/2, close/3, info/1]). -export([init/1, handle_call/3, handle_info/2, terminate/2, code_change/3, handle_cast/2]). -include("sockjs_internal.hrl"). %% -type(handle() :: {?MODULE, {pid(), info()}}). -record(session, {id , %% session(), outbound_queue = queue:new() , %% queue() response_pid , %% pid() disconnect_tref , %% reference() disconnect_delay = 5000 , %% non_neg_integer() heartbeat_tref , %% reference() | triggered heartbeat_delay = 25000 , %% non_neg_integer() ready_state = connecting , %% connecting | open | closed close_msg , %% {non_neg_integer(), string()} callback, state, handle %% handle() }). -define(ETS, sockjs_table). %% -type(session_or_undefined() :: session() | undefined). %% -type(session_or_pid() :: session() | pid()). %% -------------------------------------------------------------------------- %% -spec init() -> ok. init() -> _ = ets:new(?ETS, [public, named_table]), ok. %% -spec start_link(session_or_undefined(), service(), info()) -> {ok, pid()}. start_link(SessionId, Service, Info) -> gen_server:start_link(?MODULE, {SessionId, Service, Info}, []). %% -spec maybe_create(session_or_undefined(), service(), info()) -> pid(). maybe_create(SessionId, Service, Info) -> case ets:lookup(?ETS, SessionId) of [] -> {ok, SPid} = sockjs_session_sup:start_child( SessionId, Service, Info), SPid; [{_, SPid}] -> SPid end. %% -spec received(list(iodata()), session_or_pid()) -> ok. received(Messages, SessionPid) when is_pid(SessionPid) -> case gen_server:call(SessionPid, {received, Messages}, infinity) of ok -> ok; error -> throw(no_session) %% TODO: should we respond 404 when session is closed? end; received(Messages, SessionId) -> received(Messages, spid(SessionId)). %% -spec send(iodata(), handle()) -> ok. send(Data, {?MODULE, {SPid, _}}) -> gen_server:cast(SPid, {send, Data}), ok. %% -spec close(non_neg_integer(), string(), handle()) -> ok. close(Code, Reason, {?MODULE, {SPid, _}}) -> gen_server:cast(SPid, {close, Code, Reason}), ok. %% -spec info(handle()) -> info(). info({?MODULE, {_SPid, Info}}) -> Info. %% -spec reply(session_or_pid()) -> %% wait | session_in_use | {ok | close, frame()}. reply(Session) -> reply(Session, true). %% -spec reply(session_or_pid(), boolean()) -> %% wait | session_in_use | {ok | close, frame()}. reply(SessionPid, Multiple) when is_pid(SessionPid) -> gen_server:call(SessionPid, {reply, self(), Multiple}, infinity); reply(SessionId, Multiple) -> reply(spid(SessionId), Multiple). %% -------------------------------------------------------------------------- cancel_timer_safe(Timer, Atom) -> case erlang:cancel_timer(Timer) of false -> receive Atom -> ok after 0 -> ok end; _ -> ok end. spid(SessionId) -> case ets:lookup(?ETS, SessionId) of [] -> throw(no_session); [{_, SPid}] -> SPid end. %% Mark a process as waiting for data. %% 1) The same process may ask for messages multiple times. mark_waiting(Pid, State = #session{response_pid = Pid, disconnect_tref = undefined}) -> State; %% 2) Noone else waiting - link and start heartbeat timeout. mark_waiting(Pid, State = #session{response_pid = undefined, disconnect_tref = DisconnectTRef, heartbeat_delay = HeartbeatDelay}) when DisconnectTRef =/= undefined -> link(Pid), cancel_timer_safe(DisconnectTRef, session_timeout), TRef = erlang:send_after(HeartbeatDelay, self(), heartbeat_triggered), State#session{response_pid = Pid, disconnect_tref = undefined, heartbeat_tref = TRef}. %% Prolong session lifetime. %% 1) Maybe clear up response_pid if already awaiting. unmark_waiting(RPid, State = #session{response_pid = RPid, heartbeat_tref = HeartbeatTRef, disconnect_tref = undefined, disconnect_delay = DisconnectDelay}) -> unlink(RPid), _ = case HeartbeatTRef of undefined -> ok; triggered -> ok; _Else -> cancel_timer_safe(HeartbeatTRef, heartbeat_triggered) end, TRef = erlang:send_after(DisconnectDelay, self(), session_timeout), State#session{response_pid = undefined, heartbeat_tref = undefined, disconnect_tref = TRef}; %% 2) prolong disconnect timer if no connection is waiting unmark_waiting(_Pid, State = #session{response_pid = undefined, disconnect_tref = DisconnectTRef, disconnect_delay = DisconnectDelay}) when DisconnectTRef =/= undefined -> cancel_timer_safe(DisconnectTRef, session_timeout), TRef = erlang:send_after(DisconnectDelay, self(), session_timeout), State#session{disconnect_tref = TRef}; %% 3) Event from someone else? Ignore. unmark_waiting(RPid, State = #session{response_pid = Pid, disconnect_tref = undefined}) when Pid =/= undefined andalso Pid =/= RPid -> State. %% -spec emit(emittable(), #session{}) -> #session{}. emit(What, State = #session{callback = Callback, state = UserState, handle = Handle}) -> R = case Callback of _ when is_function(Callback) -> Callback(Handle, What, UserState); _ when is_atom(Callback) -> case What of init -> Callback:sockjs_init(Handle, UserState); {recv, Data} -> Callback:sockjs_handle(Handle, Data, UserState); closed -> Callback:sockjs_terminate(Handle, UserState) end end, case R of {ok, UserState1} -> State#session{state = UserState1}; ok -> State end. %% -------------------------------------------------------------------------- %% -spec init({session_or_undefined(), service(), info()}) -> {ok, #session{}}. init({SessionId, #service{callback = Callback, state = UserState, disconnect_delay = DisconnectDelay, heartbeat_delay = HeartbeatDelay}, Info}) -> case SessionId of undefined -> ok; _Else -> ets:insert(?ETS, {SessionId, self()}) end, process_flag(trap_exit, true), TRef = erlang:send_after(DisconnectDelay, self(), session_timeout), {ok, #session{id = SessionId, callback = Callback, state = UserState, response_pid = undefined, disconnect_tref = TRef, disconnect_delay = DisconnectDelay, heartbeat_tref = undefined, heartbeat_delay = HeartbeatDelay, handle = {?MODULE, {self(), Info}}}}. handle_call({reply, Pid, _Multiple}, _From, State = #session{ response_pid = undefined, ready_state = connecting}) -> State0 = emit(init, State), State1 = unmark_waiting(Pid, State0), {reply, {ok, {open, nil}}, State1#session{ready_state = open}}; handle_call({reply, Pid, _Multiple}, _From, State = #session{ ready_state = closed, close_msg = CloseMsg}) -> State1 = unmark_waiting(Pid, State), {reply, {close, {close, CloseMsg}}, State1}; handle_call({reply, Pid, _Multiple}, _From, State = #session{ response_pid = RPid}) when RPid =/= Pid andalso RPid =/= undefined -> %% don't use unmark_waiting(), this shouldn't touch the session lifetime {reply, session_in_use, State}; handle_call({reply, Pid, Multiple}, _From, State = #session{ ready_state = open, response_pid = RPid, heartbeat_tref = HeartbeatTRef, outbound_queue = Q}) when RPid == undefined orelse RPid == Pid -> {Messages, Q1} = case Multiple of true -> {queue:to_list(Q), queue:new()}; false -> case queue:out(Q) of {{value, Msg}, Q2} -> {[Msg], Q2}; {empty, Q2} -> {[], Q2} end end, case {Messages, HeartbeatTRef} of {[], triggered} -> State1 = unmark_waiting(Pid, State), {reply, {ok, {heartbeat, nil}}, State1}; {[], _TRef} -> State1 = mark_waiting(Pid, State), {reply, wait, State1}; _More -> State1 = unmark_waiting(Pid, State), {reply, {ok, {data, Messages}}, State1#session{outbound_queue = Q1}} end; handle_call({received, Messages}, _From, State = #session{ready_state = open}) -> State2 = lists:foldl(fun(Msg, State1) -> emit({recv, iolist_to_binary(Msg)}, State1) end, State, Messages), {reply, ok, State2}; handle_call({received, _Data}, _From, State = #session{ready_state = _Any}) -> {reply, error, State}; handle_call(Request, _From, State) -> {stop, {odd_request, Request}, State}. handle_cast({send, Data}, State = #session{outbound_queue = Q, response_pid = RPid}) -> case RPid of undefined -> ok; _Else -> RPid ! go end, {noreply, State#session{outbound_queue = queue:in(Data, Q)}}; handle_cast({close, Status, Reason}, State = #session{response_pid = RPid}) -> case RPid of undefined -> ok; _Else -> RPid ! go end, {noreply, State#session{ready_state = closed, close_msg = {Status, Reason}}}; handle_cast(Cast, State) -> {stop, {odd_cast, Cast}, State}. handle_info({'EXIT', Pid, _Reason}, State = #session{response_pid = Pid}) -> %% It is illegal for a connection to go away when receiving, we %% may lose some messages that are in transit. Kill current %% session. {stop, normal, State#session{response_pid = undefined}}; handle_info(force_shutdown, State) -> %% Websockets may want to force closure sometimes {stop, normal, State}; handle_info(session_timeout, State = #session{response_pid = undefined}) -> {stop, normal, State}; handle_info(heartbeat_triggered, State = #session{response_pid = RPid}) when RPid =/= undefined -> RPid ! go, {noreply, State#session{heartbeat_tref = triggered}}; handle_info(Info, State) -> {stop, {odd_info, Info}, State}. terminate(_, State = #session{id = SessionId}) -> ets:delete(?ETS, SessionId), _ = emit(closed, State), ok. code_change(_OldVsn, State, _Extra) -> {ok, State}. rabbitmq-server-3.2.4/plugins-src/sockjs-erlang-wrapper/sockjs-erlang-git/src/pmod_pt.erl0000644000000000000000000003244212305126066030277 0ustar rootroot%% %% %CopyrightBegin% %% %% Copyright Ericsson AB 2013. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in %% compliance with the License. You should have received a copy of the %% Erlang Public License along with this software. If not, it can be %% retrieved online at http://www.erlang.org/. %% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See %% the License for the specific language governing rights and limitations %% under the License. %% %% %CopyrightEnd% %% -module(pmod_pt). -export([parse_transform/2, format_error/1]). %% Expand function definition forms of parameterized module. %% The code is based on the code in sys_expand_pmod which used to be %% included in the compiler, but details are different because %% sys_pre_expand has not been run. In particular: %% %% * Record definitions are still present and must be handled. %% %% * (Syntatic) local calls may actually be calls to an imported %% funtion or a BIF. It is a local call if and only if there %% is a definition for the function in the module. %% %% * When we introduce the module parameters and 'THIS' in each %% function, we must artificially use it to avoid a warning for %% unused variables. %% %% * On the other hand, we don't have to worry about module_info/0,1 %% because they have not been added yet. -record(pmod, {parameters, defined }). parse_transform(Forms0, _Options) -> put(?MODULE, []), Forms = transform(Forms0), case erase(?MODULE) of [] -> Forms; [_|_]=Errors -> File = get_file(Forms), {error,[{File,Errors}],[]} end. format_error(extends_self) -> "cannot extend from self"; format_error(define_instance) -> "defining instance function not allowed in parameterized module". add_error(Line, Error) -> put(?MODULE, get(?MODULE) ++ [{Line,?MODULE,Error}]). get_file([{attribute,_,file,{File,_}}|_]) -> File; get_file([_|T]) -> get_file(T). transform(Forms0) -> Def = collect_defined(Forms0), {Base,ModAs,Forms1} = attribs(Forms0, [], undefined, []), {Mod,Ps0} = case ModAs of {M0,P0} -> {M0,P0}; M0 -> {M0,undefined} end, Forms2 = case Ps0 of undefined -> Forms1; _ -> pmod_expand(Forms1, Mod, Base, Ps0, Def) end, %% Add new functions. NewFs0 = maybe_extend(Base, Mod, Ps0), NewExps = collect_defined(NewFs0), Forms3 = add_attributes(Forms2, [{attribute,0,export,NewExps}]), add_new_funcs(Forms3, NewFs0). pmod_expand(Forms0, Mod, Base, Ps0, Def) -> Ps = if is_atom(Base) -> ['BASE' | Ps0]; true -> Ps0 end, St0 = #pmod{parameters=Ps,defined=gb_sets:from_list(Def)}, {Forms1,_} = forms(Forms0, St0), Forms2 = update_exps(Forms1), Forms3 = update_forms(Forms2), NewFs0 = add_instance(Mod, Ps, []), NewFs = ensure_new(Base, Ps0, NewFs0), Forms = add_new_funcs(Forms3, NewFs), NewExps = collect_defined(NewFs), add_attributes(Forms, [{attribute,0,export,NewExps}]). add_attributes([{attribute,_,module,_}=F|Fs], Attrs) -> [F|Attrs++Fs]; add_attributes([F|Fs], Attrs) -> [F|add_attributes(Fs, Attrs)]. add_new_funcs([{eof,_}|_]=Fs, NewFs) -> NewFs ++ Fs; add_new_funcs([F|Fs], Es) -> [F|add_new_funcs(Fs, Es)]. maybe_extend([], _, _) -> %% No 'extends' attribute. []; maybe_extend(Base, _Mod, undefined) -> %% There is a an 'extends' attribute; the module is not parameterized. Name = '$handle_undefined_function', Args = [{var,0,'Func'},{var,0,'Args'}], Body = [make_apply({atom,0,Base}, {var,0,'Func'}, {var,0,'Args'})], F = {function,0,Name,2,[{clause,0,Args,[],Body}]}, [F]; maybe_extend(Base, Mod, Ps) -> %% There is a an 'extends' attribute; the module is parameterized. Name = '$handle_undefined_function', Args = [{var,0,'Func'},{var,0,'Args'}], DontCares = [{var,0,'_'} || _ <- Ps], TuplePs = {tuple,0,[{atom,0,Mod},{var,0,'BaseVars'}|DontCares]}, G = [{call,0,{atom,0,is_atom}, [{call,0,{atom,0,element}, [{integer,0,1},{var,0,'BaseVars'}]}]}], FixedArgs = make_lists_rev([{var,0,'Rs'}, {cons,0,{var,0,'BaseVars'},{nil,0}}]), Body = [{'case',0,make_lists_rev([{var,0,'Args'}]), [{clause,0,[{cons,0,TuplePs,{var,0,'Rs'}}],[G], [make_apply({atom,0,Base}, {var,0,'Func'}, FixedArgs)]}, {clause,0,[{var,0,'_'}],[], [make_apply({atom,0,Base}, {var,0,'Func'}, {var,0,'Args'})]} ]}], F = {function,0,Name,2,[{clause,0,Args,[],Body}]}, [F]. make_apply(M, F, A) -> {call,0,{remote,0,{atom,0,erlang},{atom,0,apply}},[M,F,A]}. make_lists_rev(As) -> {call,0,{remote,0,{atom,0,lists},{atom,0,reverse}},As}. ensure_new(Base, Ps, Fs) -> case has_new(Fs) of true -> Fs; false -> add_new(Base, Ps, Fs) end. has_new([{function,_L,new,_A,_Cs} | _Fs]) -> true; has_new([_ | Fs]) -> has_new(Fs); has_new([]) -> false. add_new(Base, Ps, Fs) -> Vs = [{var,0,V} || V <- Ps], As = if is_atom(Base) -> [{call,0,{remote,0,{atom,0,Base},{atom,0,new}},Vs} | Vs]; true -> Vs end, Body = [{call,0,{atom,0,instance},As}], add_func(new, Vs, Body, Fs). add_instance(Mod, Ps, Fs) -> Vs = [{var,0,V} || V <- Ps], AbsMod = [{tuple,0,[{atom,0,Mod}|Vs]}], add_func(instance, Vs, AbsMod, Fs). add_func(Name, Args, Body, Fs) -> A = length(Args), F = {function,0,Name,A,[{clause,0,Args,[],Body}]}, [F|Fs]. collect_defined(Fs) -> [{N,A} || {function,_,N,A,_} <- Fs]. attribs([{attribute,Line,module,{Mod,_}=ModAs}|T], Base, _, Acc) -> attribs(T, Base, ModAs, [{attribute,Line,module,Mod}|Acc]); attribs([{attribute,_,module,Mod}=H|T], Base, _, Acc) -> attribs(T, Base, Mod, [H|Acc]); attribs([{attribute,Line,extends,Base}|T], Base0, Ps, Acc) when is_atom(Base) -> Mod = case Ps of {Mod0,_} -> Mod0; Mod0 -> Mod0 end, case Mod of Base -> add_error(Line, extends_self), attribs(T, Base0, Ps, Acc); _ -> attribs(T, Base, Ps, Acc) end; attribs([H|T], Base, Ps, Acc) -> attribs(T, Base, Ps, [H|Acc]); attribs([], Base, Ps, Acc) -> {Base,Ps,lists:reverse(Acc)}. %% This is extremely simplistic for now; all functions get an extra %% parameter, whether they need it or not, except for static functions. update_function_name({F,A}) when F =/= new -> {F,A+1}; update_function_name(E) -> E. update_forms([{function,L,N,A,Cs}|Fs]) when N =/= new -> [{function,L,N,A+1,Cs}|update_forms(Fs)]; update_forms([F|Fs]) -> [F|update_forms(Fs)]; update_forms([]) -> []. update_exps([{attribute,Line,export,Es0}|T]) -> Es = [update_function_name(E) || E <- Es0], [{attribute,Line,export,Es}|update_exps(T)]; update_exps([H|T]) -> [H|update_exps(T)]; update_exps([]) -> []. %% Process the program forms. forms([F0|Fs0],St0) -> {F1,St1} = form(F0,St0), {Fs1,St2} = forms(Fs0,St1), {[F1|Fs1],St2}; forms([], St0) -> {[], St0}. %% Only function definitions are of interest here. State is not updated. form({function,Line,instance,_Arity,_Clauses}=F,St) -> add_error(Line, define_instance), {F,St}; form({function,Line,Name0,Arity0,Clauses0},St) when Name0 =/= new -> {Name,Arity,Clauses} = function(Name0, Arity0, Clauses0, St), {{function,Line,Name,Arity,Clauses},St}; %% Pass anything else through form(F,St) -> {F,St}. function(Name, Arity, Clauses0, St) -> Clauses1 = clauses(Clauses0,St), {Name,Arity,Clauses1}. clauses([C|Cs],#pmod{parameters=Ps}=St) -> {clause,L,H,G,B0} = clause(C,St), T = {tuple,L,[{var,L,V} || V <- ['_'|Ps]]}, B = [{match,L,{var,L,'_'},{var,L,V}} || V <- ['THIS'|Ps]] ++ B0, [{clause,L,H++[{match,L,T,{var,L,'THIS'}}],G,B}|clauses(Cs,St)]; clauses([],_St) -> []. clause({clause,Line,H,G,B0},St) -> %% We never update H and G, so we will just copy them. B1 = exprs(B0,St), {clause,Line,H,G,B1}. pattern_grp([{bin_element,L1,E1,S1,T1} | Fs],St) -> S2 = case S1 of default -> default; _ -> expr(S1,St) end, T2 = case T1 of default -> default; _ -> bit_types(T1) end, [{bin_element,L1,expr(E1,St),S2,T2} | pattern_grp(Fs,St)]; pattern_grp([],_St) -> []. bit_types([]) -> []; bit_types([Atom | Rest]) when is_atom(Atom) -> [Atom | bit_types(Rest)]; bit_types([{Atom, Integer} | Rest]) when is_atom(Atom), is_integer(Integer) -> [{Atom, Integer} | bit_types(Rest)]. exprs([E0|Es],St) -> E1 = expr(E0,St), [E1|exprs(Es,St)]; exprs([],_St) -> []. expr({var,_L,_V}=Var,_St) -> Var; expr({integer,_Line,_I}=Integer,_St) -> Integer; expr({float,_Line,_F}=Float,_St) -> Float; expr({atom,_Line,_A}=Atom,_St) -> Atom; expr({string,_Line,_S}=String,_St) -> String; expr({char,_Line,_C}=Char,_St) -> Char; expr({nil,_Line}=Nil,_St) -> Nil; expr({cons,Line,H0,T0},St) -> H1 = expr(H0,St), T1 = expr(T0,St), {cons,Line,H1,T1}; expr({lc,Line,E0,Qs0},St) -> Qs1 = lc_bc_quals(Qs0,St), E1 = expr(E0,St), {lc,Line,E1,Qs1}; expr({bc,Line,E0,Qs0},St) -> Qs1 = lc_bc_quals(Qs0,St), E1 = expr(E0,St), {bc,Line,E1,Qs1}; expr({tuple,Line,Es0},St) -> Es1 = expr_list(Es0,St), {tuple,Line,Es1}; expr({record,Line,Name,Is0},St) -> Is = record_fields(Is0,St), {record,Line,Name,Is}; expr({record,Line,E0,Name,Is0},St) -> E = expr(E0,St), Is = record_fields(Is0,St), {record,Line,E,Name,Is}; expr({record_field,Line,E0,Name,Key},St) -> E = expr(E0,St), {record_field,Line,E,Name,Key}; expr({block,Line,Es0},St) -> Es1 = exprs(Es0,St), {block,Line,Es1}; expr({'if',Line,Cs0},St) -> Cs1 = icr_clauses(Cs0,St), {'if',Line,Cs1}; expr({'case',Line,E0,Cs0},St) -> E1 = expr(E0,St), Cs1 = icr_clauses(Cs0,St), {'case',Line,E1,Cs1}; expr({'receive',Line,Cs0},St) -> Cs1 = icr_clauses(Cs0,St), {'receive',Line,Cs1}; expr({'receive',Line,Cs0,To0,ToEs0},St) -> To1 = expr(To0,St), ToEs1 = exprs(ToEs0,St), Cs1 = icr_clauses(Cs0,St), {'receive',Line,Cs1,To1,ToEs1}; expr({'try',Line,Es0,Scs0,Ccs0,As0},St) -> Es1 = exprs(Es0,St), Scs1 = icr_clauses(Scs0,St), Ccs1 = icr_clauses(Ccs0,St), As1 = exprs(As0,St), {'try',Line,Es1,Scs1,Ccs1,As1}; expr({'fun',_,{function,_,_,_}}=ExtFun,_St) -> ExtFun; expr({'fun',Line,Body},St) -> case Body of {clauses,Cs0} -> Cs1 = fun_clauses(Cs0,St), {'fun',Line,{clauses,Cs1}}; {function,F,A} = Function -> {F1,A1} = update_function_name({F,A}), if A1 =:= A -> {'fun',Line,Function}; true -> %% Must rewrite local fun-name to a fun that does a %% call with the extra THIS parameter. As = make_vars(A, Line), As1 = As ++ [{var,Line,'THIS'}], Call = {call,Line,{atom,Line,F1},As1}, Cs = [{clause,Line,As,[],[Call]}], {'fun',Line,{clauses,Cs}} end; {function,_M,_F,_A} = Fun4 -> %This is an error in lint! {'fun',Line,Fun4} end; expr({call,Lc,{atom,_,instance}=Name,As0},St) -> %% All local functions 'instance(...)' are static by definition, %% so they do not take a 'THIS' argument when called As1 = expr_list(As0,St), {call,Lc,Name,As1}; expr({call,Lc,{atom,_,new}=Name,As0},St) -> %% All local functions 'new(...)' are static by definition, %% so they do not take a 'THIS' argument when called As1 = expr_list(As0,St), {call,Lc,Name,As1}; expr({call,Lc,{atom,_Lf,F}=Atom,As0}, #pmod{defined=Def}=St) -> As1 = expr_list(As0,St), case gb_sets:is_member({F,length(As0)}, Def) of false -> %% BIF or imported function. {call,Lc,Atom,As1}; true -> %% Local function call - needs THIS parameter. {call,Lc,Atom,As1 ++ [{var,0,'THIS'}]} end; expr({call,Line,F0,As0},St) -> %% Other function call F1 = expr(F0,St), As1 = expr_list(As0,St), {call,Line,F1,As1}; expr({'catch',Line,E0},St) -> E1 = expr(E0,St), {'catch',Line,E1}; expr({match,Line,P,E0},St) -> E1 = expr(E0,St), {match,Line,P,E1}; expr({bin,Line,Fs},St) -> Fs2 = pattern_grp(Fs,St), {bin,Line,Fs2}; expr({op,Line,Op,A0},St) -> A1 = expr(A0,St), {op,Line,Op,A1}; expr({op,Line,Op,L0,R0},St) -> L1 = expr(L0,St), R1 = expr(R0,St), {op,Line,Op,L1,R1}; %% The following are not allowed to occur anywhere! expr({remote,Line,M0,F0},St) -> M1 = expr(M0,St), F1 = expr(F0,St), {remote,Line,M1,F1}. expr_list([E0|Es],St) -> E1 = expr(E0,St), [E1|expr_list(Es,St)]; expr_list([],_St) -> []. record_fields([{record_field,L,K,E0}|T],St) -> E = expr(E0,St), [{record_field,L,K,E}|record_fields(T,St)]; record_fields([],_) -> []. icr_clauses([C0|Cs],St) -> C1 = clause(C0,St), [C1|icr_clauses(Cs,St)]; icr_clauses([],_St) -> []. lc_bc_quals([{generate,Line,P,E0}|Qs],St) -> E1 = expr(E0,St), [{generate,Line,P,E1}|lc_bc_quals(Qs,St)]; lc_bc_quals([{b_generate,Line,P,E0}|Qs],St) -> E1 = expr(E0,St), [{b_generate,Line,P,E1}|lc_bc_quals(Qs,St)]; lc_bc_quals([E0|Qs],St) -> E1 = expr(E0,St), [E1|lc_bc_quals(Qs,St)]; lc_bc_quals([],_St) -> []. fun_clauses([C0|Cs],St) -> C1 = clause(C0,St), [C1|fun_clauses(Cs,St)]; fun_clauses([],_St) -> []. make_vars(N, L) -> make_vars(1, N, L). make_vars(N, M, L) when N =< M -> V = list_to_atom("X"++integer_to_list(N)), [{var,L,V} | make_vars(N + 1, M, L)]; make_vars(_, _, _) -> []. rabbitmq-server-3.2.4/plugins-src/sockjs-erlang-wrapper/sockjs-erlang-git/src/sockjs.erl0000644000000000000000000000121612305126066030124 0ustar rootroot-module(sockjs). -export([send/2, close/1, close/3, info/1]). %% -type(conn() :: {sockjs_session, any()}). %% Send data over a connection. %% -spec send(iodata(), conn()) -> ok. send(Data, Conn = {sockjs_session, _}) -> sockjs_session:send(Data, Conn). %% Initiate a close of a connection. %% -spec close(conn()) -> ok. close(Conn) -> close(1000, "Normal closure", Conn). %% -spec close(non_neg_integer(), string(), conn()) -> ok. close(Code, Reason, Conn = {sockjs_session, _}) -> sockjs_session:close(Code, Reason, Conn). %% -spec info(conn()) -> [{atom(), any()}]. info(Conn = {sockjs_session, _}) -> sockjs_session:info(Conn). ././@LongLink0000000000000000000000000000015000000000000011561 Lustar rootrootrabbitmq-server-3.2.4/plugins-src/sockjs-erlang-wrapper/sockjs-erlang-git/src/sockjs_cowboy_handler.erlrabbitmq-server-3.2.4/plugins-src/sockjs-erlang-wrapper/sockjs-erlang-git/src/sockjs_cowboy_handler.0000644000000000000000000000463312305126066032506 0ustar rootroot-module(sockjs_cowboy_handler). -behaviour(cowboy_http_handler). -behaviour(cowboy_http_websocket_handler). %% Cowboy http callbacks -export([init/3, handle/2, terminate/2]). %% Cowboy ws callbacks -export([websocket_init/3, websocket_handle/3, websocket_info/3, websocket_terminate/3]). -include("sockjs_internal.hrl"). %% -------------------------------------------------------------------------- init({_Any, http}, Req, Service) -> case sockjs_handler:is_valid_ws(Service, {cowboy, Req}) of {true, {cowboy, _Req1}, _Reason} -> {upgrade, protocol, cowboy_http_websocket}; {false, {cowboy, Req1}, _Reason} -> {ok, Req1, Service} end. handle(Req, Service) -> {cowboy, Req3} = sockjs_handler:handle_req(Service, {cowboy, Req}), {ok, Req3, Service}. terminate(_Req, _Service) -> ok. %% -------------------------------------------------------------------------- websocket_init(_TransportName, Req, Service = #service{logger = Logger}) -> Req0 = Logger(Service, {cowboy, Req}, websocket), Service1 = Service#service{disconnect_delay = 5*60*1000}, {Info, Req1} = sockjs_handler:extract_info(Req0), SessionPid = sockjs_session:maybe_create(undefined, Service1, Info), {RawWebsocket, {cowboy, Req3}} = case sockjs_handler:get_action(Service, Req1) of {{match, WS}, Req2} when WS =:= websocket orelse WS =:= rawwebsocket -> {WS, Req2} end, self() ! go, {ok, Req3, {RawWebsocket, SessionPid}}. websocket_handle({text, Data}, Req, {RawWebsocket, SessionPid} = S) -> case sockjs_ws_handler:received(RawWebsocket, SessionPid, Data) of ok -> {ok, Req, S}; shutdown -> {shutdown, Req, S} end; websocket_handle(_Unknown, Req, S) -> {shutdown, Req, S}. websocket_info(go, Req, {RawWebsocket, SessionPid} = S) -> case sockjs_ws_handler:reply(RawWebsocket, SessionPid) of wait -> {ok, Req, S}; {ok, Data} -> self() ! go, {reply, {text, Data}, Req, S}; {close, <<>>} -> {shutdown, Req, S}; {close, Data} -> self() ! shutdown, {reply, {text, Data}, Req, S} end; websocket_info(shutdown, Req, S) -> {shutdown, Req, S}. websocket_terminate(_Reason, _Req, {RawWebsocket, SessionPid}) -> sockjs_ws_handler:close(RawWebsocket, SessionPid), ok. rabbitmq-server-3.2.4/plugins-src/sockjs-erlang-wrapper/sockjs-erlang-git/src/sockjs_app.erl0000644000000000000000000000040412305126066030762 0ustar rootroot-module(sockjs_app). -behaviour(application). -export([start/2, stop/1]). %% -spec start(_, _) -> {ok, pid()}. start(_StartType, _StartArgs) -> sockjs_session:init(), sockjs_session_sup:start_link(). %% -spec stop(_) -> ok. stop(_State) -> ok. rabbitmq-server-3.2.4/plugins-src/sockjs-erlang-wrapper/sockjs-erlang-git/src/sockjs_internal.hrl0000644000000000000000000000241312305126066032023 0ustar rootroot %% -type(req() :: {cowboy, any()}). %% -type(user_session() :: nonempty_string()). %% -type(emittable() :: init|closed|{recv, binary()}). %% -type(callback() :: fun((user_session(), emittable(), any()) -> ok)). %% -type(logger() :: fun((any(), req(), websocket|http) -> req())). -record(service, {prefix , %% nonempty_string(), callback , %% callback() state , %% any() sockjs_url , %% nonempty_string() cookie_needed , %% boolean() websocket , %% boolean() disconnect_delay , %% non_neg_integer() heartbeat_delay , %% non_neg_integer() response_limit , %% non_neg_integer() logger %% logger() }). %% -type(service() :: #service{}). %% -type(headers() :: list({nonempty_string(), nonempty_string()})). %% -type(server() :: nonempty_string()). %% -type(session() :: nonempty_string()). %% -type(frame() :: {open, nil} | %% {close, {non_neg_integer(), string()}} | %% {data, list(iodata())} | %% {heartbeat, nil} ). %% -type(info() :: [{atom(), any()}]). rabbitmq-server-3.2.4/plugins-src/sockjs-erlang-wrapper/sockjs-erlang-git/src/mochinum_fork.erl0000644000000000000000000002442012305126066031472 0ustar rootroot%% @copyright 2007 Mochi Media, Inc. %% @author Bob Ippolito %% @doc Useful numeric algorithms for floats that cover some deficiencies %% in the math module. More interesting is digits/1, which implements %% the algorithm from: %% http://www.cs.indiana.edu/~burger/fp/index.html %% See also "Printing Floating-Point Numbers Quickly and Accurately" %% in Proceedings of the SIGPLAN '96 Conference on Programming Language %% Design and Implementation. -module(mochinum_fork). -author("Bob Ippolito "). -export([digits/1, frexp/1, int_pow/2, int_ceil/1]). %% IEEE 754 Float exponent bias -define(FLOAT_BIAS, 1022). -define(MIN_EXP, -1074). -define(BIG_POW, 4503599627370496). %% External API %% @spec digits(number()) -> string() %% @doc Returns a string that accurately represents the given integer or float %% using a conservative amount of digits. Great for generating %% human-readable output, or compact ASCII serializations for floats. digits(N) when is_integer(N) -> integer_to_list(N); digits(0.0) -> "0.0"; digits(Float) -> {Frac1, Exp1} = frexp_int(Float), [Place0 | Digits0] = digits1(Float, Exp1, Frac1), {Place, Digits} = transform_digits(Place0, Digits0), R = insert_decimal(Place, Digits), case Float < 0 of true -> [$- | R]; _ -> R end. %% @spec frexp(F::float()) -> {Frac::float(), Exp::float()} %% @doc Return the fractional and exponent part of an IEEE 754 double, %% equivalent to the libc function of the same name. %% F = Frac * pow(2, Exp). frexp(F) -> frexp1(unpack(F)). %% @spec int_pow(X::integer(), N::integer()) -> Y::integer() %% @doc Moderately efficient way to exponentiate integers. %% int_pow(10, 2) = 100. int_pow(_X, 0) -> 1; int_pow(X, N) when N > 0 -> int_pow(X, N, 1). %% @spec int_ceil(F::float()) -> integer() %% @doc Return the ceiling of F as an integer. The ceiling is defined as %% F when F == trunc(F); %% trunc(F) when F < 0; %% trunc(F) + 1 when F > 0. int_ceil(X) -> T = trunc(X), case (X - T) of Pos when Pos > 0 -> T + 1; _ -> T end. %% Internal API int_pow(X, N, R) when N < 2 -> R * X; int_pow(X, N, R) -> int_pow(X * X, N bsr 1, case N band 1 of 1 -> R * X; 0 -> R end). insert_decimal(0, S) -> "0." ++ S; insert_decimal(Place, S) when Place > 0 -> L = length(S), case Place - L of 0 -> S ++ ".0"; N when N < 0 -> {S0, S1} = lists:split(L + N, S), S0 ++ "." ++ S1; N when N < 6 -> %% More places than digits S ++ lists:duplicate(N, $0) ++ ".0"; _ -> insert_decimal_exp(Place, S) end; insert_decimal(Place, S) when Place > -6 -> "0." ++ lists:duplicate(abs(Place), $0) ++ S; insert_decimal(Place, S) -> insert_decimal_exp(Place, S). insert_decimal_exp(Place, S) -> [C | S0] = S, S1 = case S0 of [] -> "0"; _ -> S0 end, Exp = case Place < 0 of true -> "e-"; false -> "e+" end, [C] ++ "." ++ S1 ++ Exp ++ integer_to_list(abs(Place - 1)). digits1(Float, Exp, Frac) -> Round = ((Frac band 1) =:= 0), case Exp >= 0 of true -> BExp = 1 bsl Exp, case (Frac =/= ?BIG_POW) of true -> scale((Frac * BExp * 2), 2, BExp, BExp, Round, Round, Float); false -> scale((Frac * BExp * 4), 4, (BExp * 2), BExp, Round, Round, Float) end; false -> case (Exp =:= ?MIN_EXP) orelse (Frac =/= ?BIG_POW) of true -> scale((Frac * 2), 1 bsl (1 - Exp), 1, 1, Round, Round, Float); false -> scale((Frac * 4), 1 bsl (2 - Exp), 2, 1, Round, Round, Float) end end. scale(R, S, MPlus, MMinus, LowOk, HighOk, Float) -> Est = int_ceil(math:log10(abs(Float)) - 1.0e-10), %% Note that the scheme implementation uses a 326 element look-up table %% for int_pow(10, N) where we do not. case Est >= 0 of true -> fixup(R, S * int_pow(10, Est), MPlus, MMinus, Est, LowOk, HighOk); false -> Scale = int_pow(10, -Est), fixup(R * Scale, S, MPlus * Scale, MMinus * Scale, Est, LowOk, HighOk) end. fixup(R, S, MPlus, MMinus, K, LowOk, HighOk) -> TooLow = case HighOk of true -> (R + MPlus) >= S; false -> (R + MPlus) > S end, case TooLow of true -> [(K + 1) | generate(R, S, MPlus, MMinus, LowOk, HighOk)]; false -> [K | generate(R * 10, S, MPlus * 10, MMinus * 10, LowOk, HighOk)] end. generate(R0, S, MPlus, MMinus, LowOk, HighOk) -> D = R0 div S, R = R0 rem S, TC1 = case LowOk of true -> R =< MMinus; false -> R < MMinus end, TC2 = case HighOk of true -> (R + MPlus) >= S; false -> (R + MPlus) > S end, case TC1 of false -> case TC2 of false -> [D | generate(R * 10, S, MPlus * 10, MMinus * 10, LowOk, HighOk)]; true -> [D + 1] end; true -> case TC2 of false -> [D]; true -> case R * 2 < S of true -> [D]; false -> [D + 1] end end end. unpack(Float) -> <> = <>, {Sign, Exp, Frac}. frexp1({_Sign, 0, 0}) -> {0.0, 0}; frexp1({Sign, 0, Frac}) -> Exp = log2floor(Frac), <> = <>, {Frac1, -(?FLOAT_BIAS) - 52 + Exp}; frexp1({Sign, Exp, Frac}) -> <> = <>, {Frac1, Exp - ?FLOAT_BIAS}. log2floor(Int) -> log2floor(Int, 0). log2floor(0, N) -> N; log2floor(Int, N) -> log2floor(Int bsr 1, 1 + N). transform_digits(Place, [0 | Rest]) -> transform_digits(Place, Rest); transform_digits(Place, Digits) -> {Place, [$0 + D || D <- Digits]}. frexp_int(F) -> case unpack(F) of {_Sign, 0, Frac} -> {Frac, ?MIN_EXP}; {_Sign, Exp, Frac} -> {Frac + (1 bsl 52), Exp - 53 - ?FLOAT_BIAS} end. %% %% Tests %% -ifdef(TEST). -include_lib("eunit/include/eunit.hrl"). int_ceil_test() -> ?assertEqual(1, int_ceil(0.0001)), ?assertEqual(0, int_ceil(0.0)), ?assertEqual(1, int_ceil(0.99)), ?assertEqual(1, int_ceil(1.0)), ?assertEqual(-1, int_ceil(-1.5)), ?assertEqual(-2, int_ceil(-2.0)), ok. int_pow_test() -> ?assertEqual(1, int_pow(1, 1)), ?assertEqual(1, int_pow(1, 0)), ?assertEqual(1, int_pow(10, 0)), ?assertEqual(10, int_pow(10, 1)), ?assertEqual(100, int_pow(10, 2)), ?assertEqual(1000, int_pow(10, 3)), ok. digits_test() -> ?assertEqual("0", digits(0)), ?assertEqual("0.0", digits(0.0)), ?assertEqual("1.0", digits(1.0)), ?assertEqual("-1.0", digits(-1.0)), ?assertEqual("0.1", digits(0.1)), ?assertEqual("0.01", digits(0.01)), ?assertEqual("0.001", digits(0.001)), ?assertEqual("1.0e+6", digits(1000000.0)), ?assertEqual("0.5", digits(0.5)), ?assertEqual("4503599627370496.0", digits(4503599627370496.0)), %% small denormalized number %% 4.94065645841246544177e-324 =:= 5.0e-324 <> = <<0,0,0,0,0,0,0,1>>, ?assertEqual("5.0e-324", digits(SmallDenorm)), ?assertEqual(SmallDenorm, list_to_float(digits(SmallDenorm))), %% large denormalized number %% 2.22507385850720088902e-308 <> = <<0,15,255,255,255,255,255,255>>, ?assertEqual("2.225073858507201e-308", digits(BigDenorm)), ?assertEqual(BigDenorm, list_to_float(digits(BigDenorm))), %% small normalized number %% 2.22507385850720138309e-308 <> = <<0,16,0,0,0,0,0,0>>, ?assertEqual("2.2250738585072014e-308", digits(SmallNorm)), ?assertEqual(SmallNorm, list_to_float(digits(SmallNorm))), %% large normalized number %% 1.79769313486231570815e+308 <> = <<127,239,255,255,255,255,255,255>>, ?assertEqual("1.7976931348623157e+308", digits(LargeNorm)), ?assertEqual(LargeNorm, list_to_float(digits(LargeNorm))), %% issue #10 - mochinum:frexp(math:pow(2, -1074)). ?assertEqual("5.0e-324", digits(math:pow(2, -1074))), ok. frexp_test() -> %% zero ?assertEqual({0.0, 0}, frexp(0.0)), %% one ?assertEqual({0.5, 1}, frexp(1.0)), %% negative one ?assertEqual({-0.5, 1}, frexp(-1.0)), %% small denormalized number %% 4.94065645841246544177e-324 <> = <<0,0,0,0,0,0,0,1>>, ?assertEqual({0.5, -1073}, frexp(SmallDenorm)), %% large denormalized number %% 2.22507385850720088902e-308 <> = <<0,15,255,255,255,255,255,255>>, ?assertEqual( {0.99999999999999978, -1022}, frexp(BigDenorm)), %% small normalized number %% 2.22507385850720138309e-308 <> = <<0,16,0,0,0,0,0,0>>, ?assertEqual({0.5, -1021}, frexp(SmallNorm)), %% large normalized number %% 1.79769313486231570815e+308 <> = <<127,239,255,255,255,255,255,255>>, ?assertEqual( {0.99999999999999989, 1024}, frexp(LargeNorm)), %% issue #10 - mochinum:frexp(math:pow(2, -1074)). ?assertEqual( {0.5, -1073}, frexp(math:pow(2, -1074))), ok. -endif. rabbitmq-server-3.2.4/plugins-src/sockjs-erlang-wrapper/sockjs-erlang-git/src/sockjs_service.erl0000644000000000000000000000032712305126066031646 0ustar rootroot-module(sockjs_service). -export([behaviour_info/1]). behaviour_info(callbacks) -> [ {sockjs_init, 2}, {sockjs_handle, 3}, {sockjs_terminate, 2} ]; behaviour_info(_Other) -> undefined. rabbitmq-server-3.2.4/plugins-src/sockjs-erlang-wrapper/sockjs-erlang-git/src/sockjs_multiplex.erl0000644000000000000000000000502412305126066032230 0ustar rootroot-module(sockjs_multiplex). -behaviour(sockjs_service). -export([init_state/1]). -export([sockjs_init/2, sockjs_handle/3, sockjs_terminate/2]). -record(service, {callback, state, vconn}). %% -------------------------------------------------------------------------- init_state(Services) -> L = [{Topic, #service{callback = Callback, state = State}} || {Topic, Callback, State} <- Services], {orddict:from_list(L), orddict:new()}. sockjs_init(_Conn, {_Services, _Channels} = S) -> {ok, S}. sockjs_handle(Conn, Data, {Services, Channels}) -> [Type, Topic, Payload] = split($,, binary_to_list(Data), 3), case orddict:find(Topic, Services) of {ok, Service} -> Channels1 = action(Conn, {Type, Topic, Payload}, Service, Channels), {ok, {Services, Channels1}}; _Else -> {ok, {Services, Channels}} end. sockjs_terminate(_Conn, {Services, Channels}) -> _ = [ {emit(closed, Channel)} || {_Topic, Channel} <- orddict:to_list(Channels) ], {ok, {Services, orddict:new()}}. action(Conn, {Type, Topic, Payload}, Service, Channels) -> case {Type, orddict:is_key(Topic, Channels)} of {"sub", false} -> Channel = Service#service{ vconn = sockjs_multiplex_channel:new( Conn, Topic) }, orddict:store(Topic, emit(init, Channel), Channels); {"uns", true} -> Channel = orddict:fetch(Topic, Channels), emit(closed, Channel), orddict:erase(Topic, Channels); {"msg", true} -> Channel = orddict:fetch(Topic, Channels), orddict:store(Topic, emit({recv, Payload}, Channel), Channels); _Else -> %% Ignore Channels end. emit(What, Channel = #service{callback = Callback, state = State, vconn = VConn}) -> case Callback(VConn, What, State) of {ok, State1} -> Channel#service{state = State1}; ok -> Channel end. %% -------------------------------------------------------------------------- split(Char, Str, Limit) -> Acc = split(Char, Str, Limit, []), lists:reverse(Acc). split(_Char, _Str, 0, Acc) -> Acc; split(Char, Str, Limit, Acc) -> {L, R} = case string:chr(Str, Char) of 0 -> {Str, ""}; I -> {string:substr(Str, 1, I-1), string:substr(Str, I+1)} end, split(Char, R, Limit-1, [L | Acc]). ././@LongLink0000000000000000000000000000014500000000000011565 Lustar rootrootrabbitmq-server-3.2.4/plugins-src/sockjs-erlang-wrapper/sockjs-erlang-git/src/sockjs_session_sup.erlrabbitmq-server-3.2.4/plugins-src/sockjs-erlang-wrapper/sockjs-erlang-git/src/sockjs_session_sup.erl0000644000000000000000000000114412305126066032556 0ustar rootroot-module(sockjs_session_sup). -behaviour(supervisor). -export([start_link/0, start_child/3]). -export([init/1]). %% -------------------------------------------------------------------------- %% -spec start_link() -> ignore | {'ok', pid()} | {'error', any()}. start_link() -> supervisor:start_link({local, ?MODULE}, ?MODULE, []). init([]) -> {ok, {{simple_one_for_one, 10, 10}, [{undefined, {sockjs_session, start_link, []}, transient, 5000, worker, [sockjs_session]}]}}. start_child(SessionId, Service, Info) -> supervisor:start_child(?MODULE, [SessionId, Service, Info]). rabbitmq-server-3.2.4/plugins-src/sockjs-erlang-wrapper/sockjs-erlang-git/rebar0000755000000000000000000033665612305126066026401 0ustar rootroot#!/usr/bin/env escript %%! -noshell -noinput PK0XJ@,ìX“§Œ getopt.beam…YkpU–îö•ä¶â›´ÜJœ@A ÈNÚ‘’XN ×–eá†×`ÉRÛ–-KBj‡dfMâ É0Ìû½„–÷c€À ,CÈ𘭭­ekj«fvÙ**[Ôþ˜KíTíníÔTíwºÛŽL2»®:êsÏ=ïsî£ÝC»¯ë–¤õóÉþ]ýVeF’Ø’$íòM˜V¥jy«¹ZÝô™µR®<Ñ4YðÕ­Z±<á³*Óf¹îµ&k•Û½f­V©yKźUo®™{MH4U¦½{s¥YSŽxÇs¥º°–*å‰Qè-VÊÍÓæþñb¹Ð2[.˜@ÌÂÊb2Å‚Ëpþ"£¹z½8ÎÑ\m¢m9·MªWKEk×9g*)›û,šòXµY³Í™¯OVj–Ëà/Öê–‡ØÎ=svI\#çGË œv@îZ“«VMÐRn¶´(ToA°3æÌ˜YÓr…%—o/Z“$¶þ ZCgLge¾h;Ñ\,[æ„Yk«TJf®Ü6S„hCÂj—ÿYùb9_3g̲•+™ÄÊ£õª™µöWÍf«b?½ã¥JÎò˹Ú~OM²Šj=Ši×:_Ûœ+GŽDëâ$[î2º¤D¥`JRÛ§Xêäüü  CV›Ú. É¡•¡Ðdp`ÿfIÓ»6ëBc"%iÍ!µ/)ÉB4éBŽŠ&M°„ð°€Ç“>T ¶…49=Œ˜¬7µ^S hRt@S3z n&zÍDòÄ—-é=«0š–çzþ1ÑŸÈä{Žgú3õƒ‘ãõ–®žãû>ðläùZºb=Ûª Ý#òAOˆ6«!ÁtÔ`\èÁêÚ2Ô¬:ÒRž ±Ô[)­MÕä‘Oˆgó¾*Wåc„$ü2ùÍÖlUhaÕ„æ Áb"?(2#PeüSÖû5 0I`ªùZ;ÿZïýZO‹MèL„õ@80â1øŽ;½ªð¢"¨ ¦‰Á„ˆ1oúPV>ùšRCRr3ž¨7N~›M´ªâY ÆŽDó?k_í`ò7MmÿQ•µµZ x+ˆ<™ H ˆ˜Ð…6âQù¹q`½ò>ïë"œÁŒˆEÉ÷A]˜wޝ¢€(è¢%ô4é8× di'è>ÀŒh„·Eýê5JjP5Е ZÚìéÓtð° Ífù…˜Ö0Dd%ŠÉß– RPRš¢f1DXÊê¦6¿6'+kZçæ„Vúˆí•NñÕhPdÂ"ÑA¡[¶«káê:r5W =Â×iÁo×ýECÁTø´!èn§X=p¿pXÔíZá”y»e²²š]®c9{œ]­Êʹ´˜æ3øy²²žˆ†¬œ×Ã/Ðúµh"Â϶ôµªij–„]Uî*Kyh ¢Êùj(ŒêºH¸Z.ˆñõ&Bж&++Æy(Ó H·ÎežŒd dŒ:U¾~–ÊgQÈN~q¸Éï•Âënƒw°mŒw´‹Sü";¿XV.êá—„ûÃL› s,lÝm<P£…•WÓp3“²R,™Yª¶‡ªðbÁÀH @k=Ü6Oõ©p„‡ÙuA¢LYT];ùlYâ´։ÿbtG`D±€¬ÃF÷œ®ÃâòHËÊ%W…e¥ƒÒ})r±r™È×…]Þ7Ç#²r9Q¡8ÒÃ7Õ[æúë-$Rq¡Ý9™È{RTlÞîœntNl±ÉU·É;í&éó‹M¾´b`‘`ÕUY•N›3Æ»,b'æÑðò䉫ʷ€« …¥‰(Cs¾ùÛi<¢#ƒ–˜GæYÚANg`diƒP6DøF©§Ôæ)[}]¶ñ[Ô›dŰ»8J^Ãÿ9yR×èu7¼f§úxTV6Åøåu_ú¬DϺ,Á£ÔoF’ÏEê·Äùf´áf´áBMXG\ž^ê@jKT¡>ßÉ{Ôƒ epÚ°Ú°Úp+Ú°WV¶öðí‹m؃ֳÝÅþg< ]8¿¬ ƒv—wẪ‡º0¾Ô…ó)ëÌ.DPqêBâïðmNníZk±¬j±í,œ7•s;õm%ï $o}HV®ìᬟéÑ8ï×{é]M è¡L„÷'¨íú3ô+4Y5 ò÷dJ‡âN¯¨jj $Yé_Âbü &N1p%`å|XìáW¹VR°’"+¬P»T&Ô*²5LKZö’ÇÎ5hÏ$v½´Ý Ø8“š‡õñ!YIbk•! â¤Â™rü”•«bj4òc~„Й;â| l˜¥[ÓÖØ ÖWB°°kê£õ`ðÝÔ»ÛÚáêSüY¹°“ô Ä–z@K ¢àJ†¡Tê]K¥<Û†ƒýc•𸝡=?L¾ïy7U& _/„¯×Æy¾¦Yz¥ _£äëdŒ_wÚÙh¸Á‘°ëH¬ µR®›ŠExfÉ‘ðÙA¶2äñÀ*.WÊž8Õd(D'tVéܧýÛà7PVn@Vt~½?Ì¿#+×/•%@Ö鯤|g‰æo_"Þ°¸–/n\˰x#,_‚çMq~#,ßxvË·’å[mË7Ãòweåæ~‹§ßô8¿r·Ø l˜*6Ì[ô úSD 'ÜPH‡+,©;;å–³¸üݳ¹|ëŸsy.wàŒÍÆy¦s¶i곜ÁGé9†KÁ˜óJÚ2/+cSj?†`Lÿe|Ü9ŸðGø$+ÊŠ‰ž½Fņ0n#ÇdeÂFÞ”•I9!+Å•*]T›Õ/p¨"CÕŸÂnŸÛSÎ…Wåû ^&Ke»§OñY™ÆÂ´¹JÎʘþn¦¨_!š2u_žo oc)‚Äu[„×X*äŽj^g)ÃÕ#Üb)ᎬŸe©´;šð½,•uG{Wx¿a©*¡·ÃL föEø~–šsöGø÷XjÁ}/¿ÏRÇÜÑ÷#ü–zÓÝáw²Ô wtg„ÿ€¥¾pG?°Í|Eè_ÀÌfÔa.ÎïB-Õgó]ÆÈΡö,ò~u8ˆzÌËÊdƧò£²rÐÁ“•y{HV¹V~Õ[ úî8? Õ÷,©¾[VCõ=v¿úÉÊ‘V‰J†ºÜï÷**cmÔüh‰z´z³}þ6z¥£+ñþ°Tjƒ/ò:®~‚ÂÞ++?Aɽ(8xﵫ»à^çüÝ)Úßuq<ïïá`7Öp/}@kéÂÐ íçñ ØzÁöPÄf»”?¬µøm‰kKÌ;.>ã27%BpëáO¹‚C°ƒ?AYy<ŸÔZ6ÈÊŽ¤õIGÉS1þ袒¿„’íÈëÓÂß§ãÞùŒ¬#vÄg þS½Õ0Úýô0²ñÒÒ› ïàÕ$Éš¢IO4š Fu‘ú†vWÅPÿ)4F}‚?'+Ï’FlÏüùh«¤¯Xôº;S霣4u‡I±¢ÒI@š¡æyhNøÒüYù+ÒŒ­ü…Öl/AÑ .zLhƒ"12!‘¡&ò ÷»d…Niv8$š ¥­ÑêKo\ͪ¢ýÿ^¼ÓHÿK°€>|EV^& rùJË=~_Æñû²žn5.ìö¬fpÚçq×#%Â_¯ûüUœûê\6™I)–lébø¹™éÉ–ŽÓ÷g²òj'-žcÕd¾çLÆ×D“ƒ¼ÞÉ߀V:À2ˆK ¢-“,¥´Ab;‰…ðãiP¢¤9²otò7óŽlÞ‘UÔÿKøL oBÖÌÚrš-çÌËÊÏð”dA÷0~íòVŒ¿ÌœÕ‰(($+o#£ƒÈñ;­’Š4SOOÇdé~·‡à¦û8Ò}ÜN÷òd‹:½Õ×|ÿÜÊ?Ò:MX|w¥POÞáU•ÕL»Óª¶¬Ñ´þKYS·†$IUC9­CÊÝÕ¡Þjz;¤µCõ¢ù³’ælw‹û´æ²F=¡&Ã)%¨%™æÖ/äühI-ÈÚ 8òKUi[äºOsù Ú=æþè]Ó™°Éàq1 #¬É×vÇWêà'e\hâ:éü+0_B~"ÚpÌ*keåS¢@ü3ʈ!e¬|â.Ôù×qþ9¶þÏOß<èmØ(½0È$IÊXµú'ÖðLOy;Ðs4åÈ/Àh´ü.}orùyêÒš]~ÂÏk๠§³§«ßЀolðÇh + x´ÁŸ­.ý À•.슼¿A6Ñ€§b¼ªA玞ߛ’û(‡6NùºÚÿÌÅéïÀv7·Ï¹8É?ãâdçi÷iÃÐl™t®wuíré¿võIìÀCƒ;‹ñ<ï¾'÷ü]Ÿÿ¤P½_ýÃÚ?<ûÔ‹ S÷{-YÎ=6vñÛm­oõÉEG¶ÿ×e?^ë{øÞýTŽL^=ø»ß‰ì0šÛõ§«þ¿÷ýmêú>z¢íÑÔ]×§?;µ±ï½½ÿªÅ9w¼ñÑëÙÿÓŽW¯øáî÷}x÷7ÿ“Ëžxû"O™é>ðñ‘Þùã=_†ÿ´%öŸ·ýËo_Þò`å÷­—J;+yê­øxá·bvãú0äæâC@Òåy0èò¼p鯸8Ñ_rsG}ñ`›K Ðëââ.~? ÇŶ¸:ïlvñ9@ÌåÙØäâUÀ¥.OÐáÒ³€K\úM€‹\|3Åu- ÔÐGç»<ƒn} §>=WrÖ ùµVrú;ââD¿ °Æí1Ò½Z:½¶V»þÍ•%ÞU®¬êÚ¡\)ý–UÃó˃%Ò0ÙTØÞz™rY•¶]÷ö›Ç³7ÿÛ‰“Ãÿ]ëœ"_nÖš¬Ôlž‚¤MÍæÊS‘¯Ì˜¥R®¾¡R›°ÙV˜ûªôI‡>oo3ûC(9‰†-4´¿a9ceñãˆ3äuú±ø¿}‡¶ †ª•ÙraÕ×8XáþßßQ45•.Ã?Ú1zˆ£ÙýZ@ìØŸ"Fë³33¹Ú~G߬U(Ö¦%9V,E.NKÍÅr¾4[0áøÒµI†¹BAòìÞ98:2¼+9-­Údto26u£ÝÝFww÷"“r}"3:|ÍÐîiiÅDÑ ™cc›¢±Ív¾šé»œš–¼± [6Ĉ汊3æ¤o Ùû2×”óçVääÜ ÛÁze¶–7§¥ðÆId~#7§7Ökù5s,W³1çóâ³Vš’úÇêíÿ PK0XJ@𪎠T mustache.beamX påÞ½ï.·w¹%{·?6 d“½ü\øå.É~B„í ^.w›äHrwîí ,t¨Êˆ"3E+-ÂT:µ@¤Ó±SD‘ZÇ™–™ÊT¬T­Zµï··—\k3¼»ï½ßûóì÷-Û¹|EEñK}mËÚ´ÄEÑŸRµI§´pdP±F#ÉØ°Â(êp( ÇóRš‹˜C6"J†Õ”’¯_Cʺ¤šÒ •»ÃÃŽ¸²6Ô‹GÁ:e&: HÓŠ9’ˆ*–dZPlÉp4ÔáóFÑô°b&¼MU ©IU¬ª’GÀòÑ[:Uúcq%š§*Àªæh,¢!XÊ AŒPÈ’ÒªbŽ¥´”µ8¬iJ@:Ímâ:l«‘ØaD¸luŽ7Àÿ­§ˆ^Ðõú³ÀAC‘½Gy(ßÉl¢™âÅ0¨)dpÝÜ š™ #› ó+ñ²ÓÄ ì)Ù'rþ*všlw;¤ƒ+ýn=W,­ã‚G ŽÌdáqbœ{gœ»’åÜã"†›`([›€P‡­•\î —ÕºÚ¥«±®†‚[E&‘uç'"Ç'àÆÅ…9b½Qñä Ç"ÔÓÆ{3z3à<ÃË–œK³p–Î¥ÎI€sP‡sT‡óL€³ gA‡³`ÀY8 ¹pt8ÃÐ;º FÁ`TðRc¾QöèfÑ;V†ypªýû Û‹ƒ7‚npºô@ ˜¦HäAfFAÜNfé,s¶ëð 0Å:.{³Í‡\9ƒãÝ›’Óß^*;­Yˆ‡ò4΄~4˜©<´%yc3´t|³`•0ÑË΂!Ìâ…Ì8B™8åÛoá&ÓØ^…À·ì^ f8Ê–Åné Í”ƒ÷<€wE3;µ!Ù_Í–Ë­2[^„m¥ìlÛzvÍÌö°å~H«„„˜C~Lâ$/[ ÏC¥þ< x`¹JØ,± ¸7ë¸0ÓøÂ×tTs«Ørd¯ú?ãÎøÁ¸3¸•ÆÌÑL”Z ÷y Nj²73‚—R.³x'Á¾Œj¡›5Ml-"r“3ˆ,-0n/+‚¥\Kp´À£.’G½»E8ª,[!jÿ_w3¯Ÿ|º“Dމ:’ ¥¾‰•‘qNò™È)™]@vH† öŸL|Ä÷æÆ÷ê/Žm…xøìÙn(œ¬Ìd D­ˆõa»Ì6Ø=l#Í4”ÊÈy §\’#ÞКFâG‹N÷<›À³™fšˆYw£ ·flB. €ã%¸mÒ`­Õì|À/SD3ók؈lËÈDf"¢n)¦™»X¸hf!xߎ^pÄØÄç ¬fÚˆÚàkf]Qnf;a#ñ¯¬f;ý­~¶³¨×6ŸõÛ²í¶ ¶ƒfü¶s¥ÞàL"ïLìóÆ‹ëƒØíå74è˜0¨¸¡A'¼1uˆ<<^(“dÀöÁøI!Sif¤Ü f]Íì"H™=ì"ѯn°?ÃtÍÜ£y¶nÏL ôo1ø,€ûì"Q¦ÑÌR"(ËÈÒ.Ү鈢Vjj¼Pw$áN;4”ˆÊ²<d3ÞÁ o29€XÆ𓠞¼¯; ÞÄq‹€Š8„Ÿj¬Y4-ÇÞdÉif/äØÌ2ä$n™‡Ø”Gžõ““gÁ“¤›:CNøúœ˜†¼ ¨Ù°'9·|‡'6óslˆïœ˜„7u¬#=×ÿ/“´ÀÐ/3xò·¨Õwy Õyռɨg²!/0x“²ákËékžq'rÓÒ˜ù˜À¥×=™^ñå—¸ÆûY<õÔÏGNm“JK|MŸyï-ÜýQ,±~X>ÿ§îц›ö¿â\ÔõåÉ Öºú ¶]¾üÕ‘«k‹xßœÒóW+‡m'»íÇu?³rŸ/ïæÊãßö½1üÛ÷¢Ç^:ú£ãÿ:Ûþõ¼¿ì›?)½sÉ-ï=+ü¦¹òÄ+k·ix|ð¥|ñM¼ãÏîG",zùãýwnÛØðöÜ¡©Í{ÏŽ9½ùhþS¥ï#õíU… ž«ýpÏ{ >|ðaÇZ·æ ùmû!¶¾ðŽ×_üâÎ}I[Ûã'«Šž›òdÁ»‹åÛ¥UïE—Gš.¾o[ÿÇ“¼¶ïöó'ÿª¼ó¡§^¾:ß¿kôÖš [ó/¼ÿÂŽ/{î“;øsûÕKÛV-®ØZ|º¦ýÌÈ´eëÛv̾ýæ÷ŸÈ¿2|m½å¶Íÿüå¯Þ~húgŽ=wùëÞ5›¾¸õT¨ýÈÅòú§»ö¤Þðv|^ó³øk~:ïý+豯þ†ºöÕ¹Àè–ؤ·î«¿ïW¿?½qëÅ÷^÷òW6v>T÷ècM%Û--÷l{mÛ]}¿[¿åÂ’§÷4νkóO欗Ÿýà…ê~þüÁ±ÏÖLméÙÕ°óй3ƒ—Î<ðꥥ´–Ì8uÅÙùñßÌÛpdû§]â«¿¼ëÅG®^üÛqæ£ËÁO΋ýØyxÇÙÚŸ>¼¼ïtèU™ßë^wèƒÕ‰×?-84él”Zšˆl& ¼x œø€ ¼\Vü<ƒî*€* {hnÎ30;ç9/5ä—Ó ÞÕ¦i*Üm&;‘iÐ¥ÐÝ©8ùAÇ9ê›ÛVÉ£žç÷mý…{Æy·k 1È §µÁ„:D¹‚‰¡GURZ"^}«¢Æu¿+ÞÎ_ëñÌÄÜšH’ï)"È‹R¬þ¡%”JŒ„Õ{ôx‰´A<³Ò‹ ¢¬±xd8U¢ÔÄgžAºh”²ûnéZÚ v-ë¢ ꥺz©¾N ÕÕIuuuY#f•e¨«»sù•?Ó¥¯¯^ö4è%XÉÇHjˆ²xjk)6š4¥Í‡$"ߣ)ŠzÌjÅÚ-Ûk¹ÚÝÏ_­T”o€vw¿¬=ï];ã•ÄÄnV+ÏæÝÃsâÇèæ |ÓLÜ”÷R«5³Ðs»nØÓ$À VšÙ|ó-Ù7ìqæ} û®5Þ¼F0›.>-«øþ€àÖìé-Þ»çhìx¯Æ¡ôÞH cL0ŽôuÁK$Ü=wP‰>h5Êå³@x¸"Cú¼]¹ §>Vò¡Âc±VÂåIwP’ÈyŒAKƱVà˜Þ‹ðXA¡&Î@{“N9ï4ÚúJ`cµ×}GW*ˆÀ=¯ ,`©Ñíã œ¿ƒ´Ð¥‹’¸Ð i‰Ðö9y†Áì,D»2~¶0^zv൹jˆ}pž?€mçna']ÌD¼ä‹íLGÒÕÿVÁU5Òã¼@Ùg=Üá Ô!9a¢Š}…‘ô,ö ;êÞÉ;E[w´­£NZmc,×pËÙOÝ»3~Z®ÙçKW/]<;içdÔ¾EÜθ ¨;É^fk—µ/4DžÓŽh£”lªx½r{UóX8g`£Ê¬T.µVªp­²oÙ–G Aúµ ˜5ù ²,)?Á) >Á)é4ýš¢p´¢&Bä ôõ|¥v›k–‘>3 h’Ø òý½9{¦4pþ«í³ÿ–01®ô2bª[Éάéçöõ¶ù PK0XJ@w·f)p rebar.beam…X \åÚŸaö2,Œ Ì¢‚+‹H¬ ,A`¸® "* Çuvw`öÖÌ.Jæ¥cžÐÌì|YG1»Zfi–eif–ZieFjšÇK–¥3í 'Ó¾ç”Ów¾>~¿gæyŸ÷yÿÏå}Þç¶zòÔ, ê,¯*›Tðy0Lq†a.¥ÀÛ8Aáá\^%/>AÕÆ¹Ü¼CÅ nÎÛ®prî@˜¯3ÌåSµù „ 7‚óûÝ.;pù¼ ·s(Û8·ÈÓ¼—³¹y«_ðµ¹Ü.o{¤nµû¼m®vM;°¶»}6έA^Ù†ô”ª[Z«9/çîy5±rÁ¹*»Ðíø”b€á!4·¯]áòºQ¡a—èµÚ9»“'ø€Hxù9j^´ . "ô²z9O"pĨ9›ˆÞñ–3áA¯ƒosyy‡ÒÁÛ‚íˆa.·¨F~Ûç8H'òV‡KÐøü¼ Å.þ dGT ïíRtø\^52åvÙ4.Ñ*ðíA7'DH+å, ¤DàiÚ΋" <ÎëNÞíGX>@¹v^ãçXÊ í¢RbÕ!WÅpX [ Ä!È=Îí¶vqî /’hhóùÜJØ.;/ ;|6Qáh$é©BÞP( ¯ÕÍwñnu/Ø|"O.脤JÉŒÂ͉¤ BÜ$]JK'ßu;“Ö67×®¾9V—·ÍgõpÝ6ÞŠ*ˆ1fµ;!‚(«èçíVdBåòÁÛ¦vy|;/DB¼ aŠ*1 @=©¾NÞ+F"ukÀgå £ò:µÀ#/yJ6)í¿8,¥iƒ)à­ÿ6¥äl>!0\ÚåAr(*¯ÃåuQåá=6^Hp‰ÿ‡†Ê/À¶ÌUÙ8lUòïõÄ Í:Ç'8n/x¥ûHýÿuÑ9ˆðøA8Y(­QÈÓAã;Œàzf–ÑmO™e‚·É˜düO{“™ml zÙ<õÇÓ&c¬Q>³ÿf’BRàB:Ðp*|ÃÂ뀥±Ð_h8N‡Å$Ó¸.’¦K¹ :ˆ›J㪈Â&BWN`L9Aë ML¶¡I_ÎF$Ñ8kh"„šÁh]E„1¬#Ô:z`~vXÌÓ4îBËÆjZgXO¬–ˆÖ*hj(’ö1ìYXc2¬"4Ѭ…%Ö©XÒŽ!Hm­Uë\ PUc³Y‹æý£cðE V¯`™A3n…ͬ %½O‡?9À·„Åhâh|wA?QF0ú‚~¦ŒÉ©0öçåôdzá]GÂçðC†þ ‹Éܯ„æŒQ)¬@Ä` ~‰Ù[â8Y|9’[d ´„ ÆV²–†Õ ‡HžÏ-ilQÓ»Yæ’`î«Ñˬ)”2=k™ ’Bm:£Æ.(§IÊ8pwGÒ¬Åá‘ÑÒ"Ë"Äǰ„^Œ‰bˆ"‚bâYM4E÷QÑ8IÓ:¬J°W`³ "©k‹©œŒ#cq2¦‡¦A‡Œ*RGÆÓ8ÉÔ8©…Ì‘±º 'ãBác-Oè–Ö²›!Yr(LŃJ,:Ä)I‘´R˜èð:a•DÝ* •Ä1TR<›M%Ô0\ÒуŽj*×c9åzº¢ª"Œ¨Ê!ÀÔ!†ÍFîK¹—ªÊ„“Ãn­,` me4P‰P`)vJÜ0)›R6‘P‹„ÑðlHFÀFéXÍx±:j ¤eÒãšÊKm"ÇRà ¨@&Z„° RÂjX™4–Ahô’56¤1‚…ó %zLà)iª²•ˆ²š„ò;òVyÓEb´´¬\ò×L"À‡‘ÅT2NŽ‚­Ñád²bZ@hDR5?¼Ã*5)T@8 )Ë£äï°°A:HÄÈrÄkåo5ÄÇÊ:ñ@CeyÐ0™”(¯M)Ëu@£ÙM–uÐÚÑ@P*ÐYùŸ.ë€ÆÊkŽQæ3€2a&þŽÇdÞ$Ëá`,[Æ4åbè«"ÄçËòq@…ƒø"™G8Å2&’—Ê>ð±TÈ:hªd»(çå¹N–×Ú—)@SeÅ>MÖA|£Ì#Ì&™Ÿ"ç!LÎÛ ™G:3ñ­ƒ0 y­h¶°i{ðTá·©wm{'ÿØé#/&Rªy‹ßÅjµ¯U\Úuýæ1€îýr_ËãŠÊCSSj/Ü×âü×;†œ__f¸XvmØ{?įyŸãUkHðlÍÿÇýÏO?ò:—ZUoX Žü©÷™Í‹òt/Ÿý²À™ò÷Í¥ 33¨ýçŒGw–xX×{`yÇWþxhï󨩼mw?ÖS=w£³ øÝßæî_üþ£Î ÜËoÝäݬ¯Ñ/(äãÞ¿PøÒ´ƒçm*½úçgJÕ={ë6,àqdVOàÍô½•ïhvêÆ û+×Ñ—¶½<Ù:‰Ÿµ£÷¾¹õŽ¿]MniýFõÛUûNY{:v¢³J1zµ%;*vm­cûÍg9G[¾¨ÉØ»Ñ7âü¯êWï_¥’xþ"#áÅÖ9ûgLݳ´û:ÙF×]{çØÞœ³pK>9}U•óÙ s O³3íõƒ÷<øÖ‡e7Îÿ\õ†æpÚ ­Ø%l[ørúÊÄMÛ^;ýê†ã¾äÅ/®-ê<ý\òé GWEìV¦î° ìùÑxË9§¹ßç0,éí)*¸ùcxÇrß§Ôg{”'>p½ÿMeéØOµ» ž›òaÒòxã]ñ}ÛsØÜK7.|Âzíæ<ý×}°5×þÚë¤{,Õ·ßøÔ·é§ŸXôXóškâÓ§§Œ{øäú>åéÔäÿпÐùÆ„U‹“žëç+߸~òêñGÌ+ÿøx|l³ªäÑŸë{µ…);êÇW]il¾:åä+^)þµæ£enYù›÷ZGqÇ…†{æl3Ÿ¹rø­æb²ñìæ=Þ¸—×§õկعI3}TóvÅc'7ZÂÒ&=ü;ø•鯸Â`sÇk±÷?°#¢¤µ4ðòL¹`dŸâFâóï\r6îuéó¶Ü\~ÿU|»…™u%ï‡oø%½ñ<žwó{·âËÚ¬‰E ¾¦Y*m»®}µiÞó˜ßDÖ‰/çŸX꥗·~áülñãKR²^¸y¶ëÍ>GßÙ’uÆGoìüê×ñÏܧÔG=þpîæY5_í¬X7mƒñݨÎü3勵ÙüfvýÓÒ¯—uùåƒUŸ÷¾óIj漢ŸðûæîW²6?3cù舵«ï~¬bù²éñ;òÛÊýÌÇÛ½÷.zíd¸þ úÁôþ’ß¶\wÏñ¡ÂS»w~½+rýGkØÿ7õ®üOú_j½äDxüeUr û1ÝÛ÷7–|{ºdù>ÒøåÆêgŠfçi£—êÎ$i>Ÿ_·Î³ôÒÁNžìžu¸K¦®)K¿ø¹áç”sBd⾃Çïþëö qzÓÖ²y{>|5{ÃùÜ’#wõ~rêc ™:Ÿ½Qn½±¿ëÓN™wÿ®Oî̓û±CîÕè®ád¾I¾Gî¸;eÝ…-2~ Ðtìö×,c–5Èú讘$ËÑ}÷G[dîù©££¢Æ‹bþEÒW }uèGN TŒ’~a·ŠA‡º‘‚Ê 8\B'¦àm./’à®NLíòÚÝAïÀnÿ8í$`ÎáÀ4åM5u•ÖÆšIUXT¶)+Û”e²fe™²²²”ÈæŠiÖšúêÉXD»+ ãm¶ìsn‡ä“ü#n'ÜŽyf$S\Þ©‚›]ýw.ŒÓpÎEHо `ç;1}¦Óçá3Áq¾3Sì™ÒÙ·¹ ^pC%”ÙÄÚ„ÿPK0XJ@x‰VS@(rebar_abnfc_compiler.beammUmŒEžÝÙÞn·×cÛ-ô>øXé’wÝö 2÷Ñ«…㨀ømÙ¶Û»½¶»u?Ž3&zæ$^ˆ0!‚!&†D/ ‰„DAT"?P#â©Ñ#D~:Û.z!6yºï>óÌ;Ïûîd¦wõš´Ðï\Õij%ˆ,`~@—3’ž–2j>›Îj¥²R”uÚ ˜œ–Mëšf²†féY9-˜´f™éœ¢³%-g+T¬%u€lmå«Ù2’!ÿ› ê–ÊVókeÓ¨­J²ššWà€lÖ`VÑTwY×ÊEÅ0 7&ÓÃRђ霜—¬¢ÉU§+Fº¬Ë†¬š® AeµœìÚ8¨dá²ð²ZUS±œBQ¼ÎòÕÊ(S·dW^*2“Ǭ*•dÆviWBh.UÓ2C”=Jj—¬ëšî®z-jÃeêÚFS·¢æµi¶Ó)ï¾6gÕp´-o©mbèÆ ëq¯9Pýc4b¸ ŽôÏ¡.Å!ØCqqy…ˆQ‚Œ`3Šñ¨ V ©Æ!;Î@ªÈ€§€ 5P źQsQkÉ#˜E=)s)B$ý9!2„òý¢@¤Hÿ±¡VOáô· Q¼; ʤŸõqĨhÁ¥Ð Ž®ÙÝÙõFæ=bJp'ö¢„€ˆÄÿG±Øˆ/j@,iy\)È¡ðÄEtá>*õR(0¥vì²×NцŠÝj+ªJ¾’·ƒ;Êõ ¡;+ã!2Ô+t$ØÙ *Þ ÅÙ9!i†´Pnõú {—_ä ÆÇ!.IoÆY"?.âZæBZE n ?J¤xÜÄÿãW@‚ àZçá—éÈû¹½3Ã&8‚ Úæ0'LL=ææ‹ÓP#þךú:{S$Keû¹wÐ iï Öáì1/Ęæì);`LÇ Ý gnÆL'æ1'a4;sm}Ë”¹wß“ñ‘Š·ùŽ~ž3tbà¬MÞF¯¥®sÖ%¦Ìkp´€nü³¾O1mÍïX²sd÷žÔ‘þQmlëÒ½ûN¸î{°åf2poOrõ¯–|¶yË=WÔçÏ·Ï9q˜¿vñ£ÆG;®Ÿ®ÑK?ñí­_o¸qòrüÌØ±¦±W77*Î?üäßþNÓáYÃ+Ž£Í-ÒÊåß;d}“ß·ß<<æÝßkM,óS³_9våñ—O|¸iË­qž=t|æé•'äÛ§ê “åw?¹qí¯[×'ìúeá3ÉñÜë¯ER?ïˆl_´ÿ¡Åb˧ë'G÷|~óì[Aáúâ­Júܾ'äC…]G^º4¹drÛûiÏò¦mìüö\î÷÷ŸiØsîÙÇù±ÉS|: ú´¬]wFͽ©Ÿò]ýN«ìoísúhï‡:§Çö\ÃS¦©Û¹ÆŠ63Hæ6Ôʋʿ|³î›‘ïn]ÍH5\=pvh¨;©æñ˜»¢§l=]=ƒ ›¨ÉoåôKV©$éOÙ‚|êãC¿(9£¨6C(@+j¶håäp[*>«UÎ B<–˶ëd_Oz]rU¼¦EÅHTŒFÄt$"F"‘Û"f}÷Út²¿wuxS3™hGláPÅÓ°¬ØT¸bí‹Úc6G™JI¬Éà=tA"%VòH„䩬ÞP j%9ŒË…°¡gÕ3ü¿èŽ«®ß]C¸êÎŒaÚ ÿPK0XJ@ZkÛ›Ü rebar_app_utils.beamuVol[W¿Ï÷Ù~±ó’?'i’.}­“.©›ä9vR'iÖg§Ž•ªÍÚ¦Eü)¸þó’8±ý¬÷ž»²"QúekV¦1~¨:1 ¬ |´²R• $4 BИ¢"Ð4¦ibã €sž_S´(çÝsÏŸß9÷œ{¯ïì“'#„ø—L%Ž%,½Lˆë0!d²ÕÐrY#“­V35«X2}EÓžІ¿®²ÅÞ%ÍÊäŸ*‹Å’VÉ–5~E/V¼8+sÂSÅR!Ÿ5 ¼eÔ4÷b¶djnÍ0t£©ŽQÒ—(иiäC×-òhF)[Y¢Ó#Ó-Ž.céh&䲦Ë ¨²y}ÕÍé†ÅPT*æ³VQ¯˜Í/jÏ™/¬Ý(òçò&ÊZ sµX­jhªU Úb±¢<¦e+KK_Õ*¦XÒ³¶AW)l1*Á#ãÍCœZÉò7Ä¥ÕšÅjí|UË[oiFÙlÂÚË–jZSÕÐÁÖ´ÌVÌA+Õ­ÀmK=e­œÓ @hòø¡ðiGIA«Ä¥’žË–D”âJlã¦9a‹ó—õB­¤eŠ•E½æ;‡þ· #‘¡R¾ï •¡fLÇnl•O°T`Œ Íèwö#õ¿Ë@I Ç\=„“› ñ‚ KN ãÔVYf* ¦‚iB½Œ1œñ)>Ípæerü4MP)»bŠ<+ÓôÕ´%îxìe2?™¶ñmÁ-_DR¶|µºoíß³±UoPd«6†+¤¦Ué²LÔ êUÔ‰»ˆ:uÇÿO·æ NÅÅþP"ã(G•d”,$£,ŸŒÊfXì_ð=ûg˜rQ5yL'Ÿ6±¬ù Wþ€©ÄI ˜æíúìo?;[O}0MñXlÔ…°÷Hˆ‡îS8a YV ;ÐK¯,°°8e@8NÙ8e´}÷Û~˜…›™l¡M‡é‡;Õâþ«â'ìg ©ŸCÞ.ÿÐV†±u#Ø:€P!¢íT¯Š‘â('Dµ¿Qôÿá„1Õ§@~›°•"t^œ0ª(¨¨¾˜£sTqPƒjB Ðy&Ø$J ÅSØxÊB‚0Â鏸…• !Úë›C•ðxMà ”r®á‰˜xÂx'ÁQ‹‰OrT1ñ•(Y°ŒSx‰Î•«0rpu’ Ä;÷«ÈÄû^%‚ã­èØ¢M+˹—ÛåRƒ<Ø ÷8<úw6È{|”?æÈe Ý 8}ŽM?Ð^‡Gù€cÚçðC@à ±Fí4øhÀŸ@yê<ÖÄþ}ñ;¶SO»=ŽóëuxÌ»Ûáw8Ä9µhwøüÍj¨e‹Ãûœ<8§.'–ëhÑÂ|ÞÕKç¯iWŽùî*ìÒ©o?üõ]ØqbýBëæ›3÷^^ùáüéç§Çoÿèë+ìOÇÎø· Ñ®ûøZdü;ÆÓ¯Lýý¥ÑÛÏ_ó¼òÆüá}‡.ì|ïû?z³/~»û£ßßøÉþxâ÷NËË/l~nmýÌW’Õû»³×n¥z>¼ùò;kâ±õçÖßÿ×äò¾©üCø’çfâ§åÁ“þÞÀÆÉCËo÷ž‰ÈVúWŸýí¯Î|ëî¾g_íúÌÉÂÛϽÞ<þËÞçóâ½ï½»ëÇ¿xš¾~øß/ÜùüÏÞ˜{¿ùµÖï]‰|ö/ÞÚ3Õ+Gõ<®ñÓÎ^›tê Å~(êÔ{6âðcNý±^ ÐþGöö| aYŽ_-!Ú²«@ð©fO*ŒÜ|÷Ë~í»Rêá [Z¿[Y™™«,‚Ž·íy´÷êUûɇOˆö»3cÖÊå¬ñE4ðè5 ž«„×rÅ J¸â*ñ+ùR­ Èöp™‚®P ¾äé¹£‡3§æŽ¥VIë¨UF#J&Q"‘È–‘ð©™…ÌÜüì“«Ä¿T´d-—ÆÆVìœÎi† I­wlx|8†2Þ*–µeO ùVÖ•õeýY.ë·4õš‘×VÉÐȲ^ÖF qmuÂ#öëy›Û~¦ëy%‘3-,ôPK0XJ@<¡| rebar_appups.beam}Xlõ¿ó]ìËÅמ}NÒ¦Mrí¹´iêø;­“4pqâ¸éÏЦˆ!„ãø.‰ÛgÝÛ²‰­RùQA™: ÛûÁ i¬ãÇFé&Ú1Ð@ cÀ~Uc ˜ªŠhiï¿n TXzòçûÞç½ïû¾ï{ç\&öìQT€M¥Gw:f‰¢˜·)ŠÚ뷌ٜ•ÍU*ÕŠ½|Þ(VÎ1"d]3ZF1[u E»¥hæôlÞ,Ïæ[ç 'ëä,üªä,£ìdõ‚µÒ]ZÆÁ‚YµÑÑÈÙØn®P4ʹ’Á0 åȳcšÅK´ByÎ ÃW”^Ã*æÊóÌHt¤¥–’›_±ÌJ6¿`äYǪž‘~®PÖ³¸•í19 G±ýõ¨¸hÒÙê|s-PÑœg@š1T±`;¶ë³hÜh7¹KÖ6-§Y롈ê¯Væ­œnè©i.W´ P¹pþ¹9oµd@M<‘ˆ³È:fÍÍÂY\`™¦ƒ@‚Z»UÎBàüB-M7 ¸äà†¼:TÀ1Bõ;©ÝQílÍÕ²nÀQ ÝTtAWOo/7käJ°˜åò¥ Þˆí?£¬ûÊæ¡¬íXÞrg½s‡¬‚c°Žw¡ÙS0½s¦UÊ9KûÊàVÍ;³ìË/À=º¯–›Þ”Ó¡ÞüBµ¼h 5e¶dêU &;/*›ÓæÊyCçíjŰ ÐÞjEZKÞÔlm«ZËÕ⸷8k,ä »,>ç8Va¶ê@5P0W¬B™‰µ™€ªµ¬`gâùŒÃ¸Q›5)aK-ºÛiË1TÃzmäråÆ#Å|ø†þh,ÒùVJ (±o§¨@Q#ÁH½WA=W-ƒŠikT/±;#_›Ôhƒu ŽKQ¾ßÀ|‹Tís dD¢EOp­LË˦dMb|"¥1ã>QÔ˜„’EML3)@‹ª1’6ÎhصÁfh€ABŠ¡¤´äQÒ l ÂKûä)ÂR(ň¬6ަ¯èã WZšfXp÷(Z†’´8ëS+½ÌÅ–¦#!¶¦¥c²JÔZXÒXE 1«î¯…RER‘Ci6#»ÉfTÉ'Ÿ`Eaóq¹ò{èÉ(ËS)Vd‚PuCkž /©ôÔ2MÕ”0@¾‚jL( 4Iã[Ÿz ƒ$˜@8p‰‘H'1u‰B+?äZÃé0Zg.Y˜OÝʦY´V–¬þY-¤- $ Í$ì0OÕË %~µ†1ó ©5jBe2á ›I5‰ž³uªteã-’"Ψr<#e” YÊ0™8Ü»DÑø.ø:Än™¾™ í‚DÜÍXÈ·Ž%¬ž(úä 5¬I,æëbNæD‘>1ÖŠôY?%úD.À‰\¢_å:™>ŸüTòËò¨¤„0¬a9ð”܈\P“üžH_HüU’hz“ß Ò\ )HʨÄøˆœŠSûRq1Š<(òr*OÙ©¼x´WÚ|6¦xázi.è?q"ÀBáBǵ}X>mlZctí¨£Ù7Ãî­PÀtsäfè®Mœ†Ïœ`Ò™û™¥¶k:³Ät.ï1±» ë¹öA!Ä ¨8ØøØšPghÇø¥²ÁB­õ&”7¦‡I‡ "+AÇÀ¾+°RÓnZæTmw2˜!d¹9†|·R<+¦EVQÒˆÂ(Lzš‘zÀ9&V´ÌY?®£~3°XÕ ™òAQ¦ ‹¤@BË¼ŠœÕpZǬ J9CsRBÍ#i™óÌn°Ó\Ɔk…KÚ,Ó\›*´2ÃŒÐÚ>ÃoÚù¤°‚VÒXViD†®JI£e.à):…¨R‡ûÀ*)½B‡ÄA­€Z‘S <5‘óCyÖ4.ŒÉ1$¹Õ°û ?%»~;JTEln~8|w¹•—%l]"tàaVÁaF ãV'…NiTŠõ ]qþÊ„Ð55ŸPÁå*˜þJwh¸N0K|Ï&¡[á{h®«ÖÈÌpbÚ]ßrÔÝ42ì•inÍ2|ÞÂèŽaÙ»\˜vçJƈkèg8-?óÕkƒ"¸+àžUæÌõÙ¶ä®!ìV…õx!ëÛa¶…u…+hnÆ÷ÔŽ{²\´~;|DÛNÑ\dv‹Tt#j ~/F ⯡¹M Ü ÊHRècü¢8ÊH¬Æo§™ÐÖx?œ–aÜLûÂ&ÂÁü£¤&*HŒpúAâ'@â ŒûŽ7àɆv4ä°£A?…8}ï‹Ú@ê³p{ ÆOñqe¢Zž&µBÞò½™p)Ï»áò΂ƒ=pÈÅÃ?+MíÚÁÄÄ;»¯}Ôy¨k|ÚaÛ§s¿üÝȇ£!þ»=­¿òvù¾]©»»Ý‰~ùîî'žüèÜØ­÷~vÃ;¿¿9ö¦qüù;zÎ>=¿ýÈ=Á;‚ÛŸì{ë¥Ñs_V®ï ¾sòÂc·½¾9šä>”q·· -Lý}K_µí®ÿ¼pwéÅ­÷M­úÑŽÿ)§'ŸŽÅíÉ?ÇÖÜöë'?ÿÃ;ÍÆ>¦7J~Ï™ãŸEÏìùè†ìío¬{ä/Ï¥~"\8röƒWŽo2·?¸ÿéÒËÖS;ߺîÉGKûÎì{øçÞû‹‡“·ªÏq­×}|õÙ‡ûoïß–ß4þBäúýï?³÷Ù{NßòýGî¹wù57ý@í~ùä©ÿÞýÅ»ÞÚüT©Ôö¹ý¯=¯¿ÿø{ÿ¸í58â}ñ;Ûží¹ö¾ï™Ÿß­ùÍ?šþêÐÉ ÃùÞpºãŸ~AOÍ Q;Í<ÖúO¤Ç÷’Zƒ\Mî+ùµ;ØM0öË.‚±—vŒ}—!û7E0öø‰¹šÄªÏN½7p¶Ö=ÎßZâ‹sÙMô8¯„3"Ü4 o=ëh½<:Å´Ëî¢,RÇ_ÛÖ´ÉüÔûÒëËïrŸ\»BMÁðrebar_asn1_compiler.beammU]lU¾3wvgØ.pwg¡SZ¤iw¶­ Ô[Êv©–Ÿ0Ñ—éìÎÝÝÙŸ™u~ EC¦¤…&¦ÄŸŒ¾˜håÅÄhàÅ_ >F‰/614áEcðÜeVׄMÎî¹ç|ç;ß¹s÷ÎÔ‘ÙBñµýù‰CÛDH8ŽêS=V4=ÃôœQr›-»Á<9rä2|5ì¢rÒnX%Ó³"pÑôÙ¿`ì…N¬Ô`¦Cfy‘vÃï±XƒÌ`f©*ºõdTÒn–`Žz̰lOáŽÙdR͵um)n+ð“ùJ®S¶+¸Â‚˜ãºÅZœJAŒyžëÅ™×0J,¨zîI… ãDâà ØœWhT˜Ã<3`V[—kØ~àÇÊnÃjô4]+9¶Sv7½ÑµÞ6ôˆâìèP9t†ô!ÅsÝ€7J E3eG¢Ô¤k1ØÛ5Ø[‚~–ÀS"¦wh‚¶A#gha™ Š¥ ¢2J Ú$-èý´@QI¥¸D3XiMÐÅ´§ 4‰§©´p0:–ôod¢ žÀWÒHŽÄœ˜¾ª ­¤¦szÓ~I&úàGø -Ìñ:,k´ùC¥b?•pJ’õ£„’|"ûó…V¿ memîÙE¼gkû1RWÔÈ=‹ÒÒ„³ƒ+œpÜ’†dí,-,«²¶L1ôÐxh˼×¶ü<.ƒ¾U1Ø¢ דJ´WÑH^*\VùZ…íXå;"Â’KSôëD¸EÛp‡¦ñarC¸Ç—DPï!펠¤ ÖK%¤4¼::@Õ1™Ü“ AЃ@>%Õ|FÅ© ôj?„U:-ýy®e@M ð׉qZWE…v}º dâzˆÿ¡éf‹ÿÞKa0 L‹ÅÁd~ÀÖEqŽIFþz° `btn:j£3´© ¿¹+þxäsþ'"¿ÃÉñ[ÁžŒ89~{ïøbg‡_ã~þT{®±hžmQžD>ŠzȇԥWœ N-_÷Eý3Q^*ñyz£ºtÄ-ÆþÜuqÆxí›`×N½·ïÂĆs:É–wL|Ø÷Á¹üÛ…3ëWÄoç6úê+ãù›3?ýõÜèÓ©÷ßXÛrzç» ¯×¾_J¸ix÷¼Ð³W¸xm÷Õ]?_j÷¥_÷n]‹½¼Ú{þ³»EcqØœ}çÁêÊß·ö}|)uIúí“Ï¿»wfáöW‹áöÓ³·ùQ_ÿþ¾x&»sB3n©{/ºçéžaK׳í‰|y"<ø=üzƒOX-„ç}‡/‡ ó›zÄnMºûÖ…êýÞß¿¬q@Ü ƒªëµ1J{¡W-šEsÍÃÅS«!49í”!¯´y%^&ÃÝi»ŽÏq ­oß“†6›¦·ÐæuîÝ:’XÑvxD°ëH¶R#´˜…Ö…ŽÅʶì*†œe¡ÄþÓ3ŒãÓ‡òu´qDÏè#9ÝÈåô\.×)/N3¦O©£žŠh¬X{¦=Š<Ï<DÕQllx×ðIÝdÕx6çS4f)˜É¶@ß ½«£\¶ê6Y„³zÖ÷JÙöá?ïÿ¯­axÔ&Š~ÀÏÖ?PK0XJ@‘¬8£ô rebar_base_compiler.beamuWklÛÖ&u)‰¦uZ”üJâЦb'QlSí8vÓ\[–U§yhµ·aA6E²(›Öƒ I塘‘"¨‹µhd+ÐìGº0 Ã llÚ û[dÙþm- ¤Y†bÃòcŰ(v®tÝ*ëfàçžsîy|÷ÜcjéìS Ž ýu!3zÞ³kç‹s7«8f±àä‹×̯ٵ†U5ä4ë>»0j¡¾.¸fµj›­Ùõ²µ.®›^~Ó.ºþ’Yl®wµuU{ù«–ë¹È5/úâñéYUW*[õR¾ Ü]kæZ%_-¸^¾f—ºŽÝhmky.Úvµ×µjêg)å/;…FÃtÏišþr¡êšAê©jñŽ«l™¥ [±À°ÔíꋉôQ/ÔÌ`Érè[¤ÕRFØ´­zØ1kö¥V¨š]Ï7 ކ߅t<勊D%ÚIÌ,¬mV½lû,;P¶ZÁÃ;º‹M³i uóŠ'” VUdò’߬5¼«~oñ/ ‹g¿z&P§«’Y5=s×gEÛNÅt®ÝtÖL¿é8¶Ó …6AE#î¦v¬ñ8œÛäÌx¹Y×Ç{تºû†>™I fÖŠà¯X(8m½Ñ¡Çn£p¹ë–g;˜éÛÞ¸´]29.ð-è™kÿm-õð²/G²²Øjò`¹Å7B[[yD)‘¬ª"®@Ö"d%FÒA‹D[ ªD¾ gºÎ#-ÓuXƒÇ„¦U’#%Bœ ˆæF$™fT/#EÓ4ãÕÈc]&‚¦¥ˆ‡üäÀ¿å KJŽI¿žžK_ï#RäÇRô·ü­PŽô4¬‚H*B´AFPn@¥d3ö†€HD#†Bb=©‡s ÿ:‘úeÞ q„¤ÒDK‘´:Náï@¤ÿAˆäÀ3`Ž‘”YSø‚òÍ=¢p«E¶e=¨¾ÔBŽ|(# %S(ßÒù‡àmHåE98+°ÿuzj°¹ƒ´Ã2/ö€) .†g°‚æ‘–‚·2¯¤WâXIkd…‚S^TÎÈ·x1öÃ:/FCœþ¤ªã>4‡p@Ó{“¸—{i9bßIÄ‹ý`;¶3x }!ƒbåµz'ªã!º}¨µ}0‰÷ðâ ¬rívÑ@BÒhÇÇ{yqO[C¥YÇú/î%1¥…3òC'^Ügà~í Ñ öC£Pjàa¤´uûàBOGúðt ÇÑcÇûˆŠµ>Ä‹Úâ”$k:Ž+s ¨¶¤1“âQÈuL:„òb,:ƒÄd]Ÿ¡Ø’ªd¥á,œŠÐ¼ ± I0ðxŒH‡•/hF£²ªg4ZmNÙ&»Ù pŒw8^û\¯+ ‹Gd ƒä塞Z@$‡R¤#q|8-Gé)d ç× ‹p-ëܒвB6Òê\c[—ƒêìfB¯†h¹Lš¦³õ¿Ò÷ã^<2@Ÿã'c¼8ðOBLîÎé0RDƒ+-ÐÆj,›Šð¢Þ‡þShO#u'å8žV¤áè㜠¹hˆ,jÐ:´ix1q"¢cƒvŽÑêœd§x1ÙJüög…m˜,€ W†$Ú4ÔŽÉ¡ÿkbÈwä%UËJzV È/©©¬”È¢LJÓZ[f5CÛ9®5öh¯OA²H:¥k¸Ýât?GGèsH4ÇH‘òâ,–sô‚Lañ-^<"[´/éLù×/E\H†»Oû† ½»izƹïÂ?§ ¿OÌàÒU¸ap·`4Å‚ªØ£ã4)M&RÏó"¡#0B[ä¤7ß^m«20¬aŒ ° E,øqzUÒD: Ç+†Áz¢Í@´Ì ^B!¢Ñ›ŒZJTØx´Gu˜ét¸dàEê0 NfÁÙtü)I)@q+ž³Jÿù,×ôý ägÿ—@AÆwI@¨(äcö˜ñ»€v3¾(Ìø^ > hhO¿—ÙP~_‡|?ãc@:bÅ™œæ0Ñ!O1ùïc6Ó6‰›c”Ï\iÕNXÍI¦Ÿc<Çìè~‘aáco‡_ßR³NýL6Ëpz‚ù@ü꟟gzêç8‹à¾ó”åѽ¿úÛ•ïŸ~áMé¶¹n_—>½5òÔ;óÏÌþ%>ó‘æ5Ž ?7=Z[̽|äé‹vÍÿrã_ïËs8î×çÞýøW¿öþòŒR–âo¨gïÝh<ûQÿÉׯ+/Øïn;o¯þĺÿ‹Ûƒwû£¿zñÐÐW—+þ±WG^ÌŸ»ÿbí;?ûyþéîùøî—nÞ}Nøã/{›ïß“»<ïŽþ0~~ì½s¿ùQvü÷×¾÷É{¯…O=øú'þÍ ÝLï?e¯Ñüo°žè¬}†á‘šbü‰ÿÂa’ÙÓ÷(³QF˜|h˜ñQ¦ó±Þb¼Ììü¬ÆwÍ{žïƒÏT)⾇.¹õÖ¢.s7_åç^Y?ÿÍŸŽ|úî—~ð÷ÍÍôr½ :±e/Pû Ýð,»îRA ÄáÖ·cÞmÖjç*5ØM¾†+œ`­:•ðV… Zõµj³d–¸®f½d»YÚ@ +•8iáË˧ó«Ë§3nwRO$õdBÏ'z"‘Ø1¿’^É/ŸY:[áº×-O5‹ÅdʘÚlåtÉt\HªÂù‰é ƒÊϪ™"4çŸ ¾‚Tè.ð…P+ÁöWo…KLnØ5s7+“®³6ÙúIñ9÷èO— øÍ²9_t=ÚÀÿPK0XJ@I“Ð| rebar_cleaner.beamURKŽÓ@­¶Ï$b%[lPÛX;)ÒL‘À ÉøÓv:¶»£¶=À„`=Gàpœ€%‡àt{1Xz®ê×ϯJåZ^½°Tí|1»œ,€ÓSŽ}»AŠ=Šy£ŠÝêíF$Åy¯¾g4"±㢑’¼È[ãØ vÝŒ…eŠ]B#ÖÄ<õhÜ"÷ÝUv{•tdŽô[Géî–IóÏ\‰fæ,Ä"¸:Ü>±À‰€†teðÀ@Æ=]w”‡Ž=l™à¨Z Ž6lºŽLeðã Ôµn ç⤣7Ž:”„a¢ƒ2ø®£OkÝQaSð­4_e†¬QGU )ÐPêút'—|OÎOò‹w•Ï£úÛv­mÖ9ÔÞÊË’JýýZ×­ãQ h3¶/X°­çðŸfV\Öú’Jf§„ ^ç´:P~þ™ýø ¥ß^ÿºùš¼ýHöûùŠŠÑ"¥ÒkRßb‡‚0šK¢Â)æœq7/³Ìã怒ÉÊ"$< û„J‘Z„iâNJâˆPîTq†Ð9¹ºxænW—‹ú¶iÙ¦m™®e™–eEíWó»Z/¯èƤ0°ïÛgÓ'ûª§kÌsÑTéøéx*9­ Þ5}ñ#~{Š×ñºòzUƒ9+y€x<Ù± ODã8™ä<˜T«õ/;®õXlæ`æç…œï_PK0XJ@µ )»ÍÔ rebar_config.beam]VOlÛÖO’hIL(QvâÆIXSI˲(JN,h»Šà4qÝü)0`¨LIÏ6cŠÔHÊMN :ô°:¬Ø¥ËN-ÐKÓ¢9mÈ c¾-@l;äT» è¡ß£^µøñ÷~ßïû}ï‘Ô»øöÕ B©¿/7–®,…^!ü!4ŸñiÛò[ÏÝ´·Òm+ xèX¡í¹I–LÝݨ"\Çn—nÚ.í¦ì µKý¶бa¶ãmI0i °Iw©“äóøçQ¬x–0`¶.ñ.m¶ä ì6ÉçRQ-¯ñh-’>¨ùM÷¼îÀ¡`|Ó;ÊGî³%ØŠ²Qr:…÷*åJI/": •lîŠ×¥ Ÿ@(£áo Æ0,ÇrÓ2VëãdqœèË)ËDՊ㊑‘u³‰Ó ¦&$UdÅH\½/c=–»Š°™A(‰dÙ”/êJÓh’fÌTHD×a^Æ>$˜&‚ K3õYuXAÖŠå¦û£|åË îÖ 1Ò fS&¢ªÊøNýY¼1âñ†bD5’Pïã ¦Šïet5 2y“†Ú|L1I¾‘WH:âfÈâÁK3úò†rpÌüú‹âϋھY Y![nMVåÆSB~öüPS+d™ÄÂV±TM˜þvÄ5K6›*Iª*~rØa¾IX‡º‚¿‹åRY‹r]Ê’E¬­*´µR”²UX抲¦¯c1k6u²&o`19yÈQº$c1·ãp;^—&@bbTb¢jdÔu¶ Ðü Û@A•f£ÔÌ<õu‹‡ÊÇ@jãui¤&#) ¤ªEiR‹ÜT•5µÅÉÜW ç8”?Q—¦ gj´ü”××a †}@yؤzG^—/ªUX¡Q%šYPÌ xùT¦uO‚î ðrª(©$5uA:­ddöÍdxïÅS(‚%8]’Ô³YXëÏMöZ3S§AöTSÑXkú,¾Ë-ƒö4ËQ>“T¿­KôPy<¥{>£§Qdw$¥AÝè¶p‰`ñ Ø, ,ž="ÃKð$’z v—-ôt:þáä×€wx¯›`LÁ£*Mcñ 3àoF‚ÇÜ7„˜f6M`IRe(%ÊbE`–Áòì‚4G–ˆ;RÒžÂZ¬Éb‹%h¤¡)ŠYeʳXœ«IEr8]†lªëfŽ!à§ÂÐ5˜cU1Å*€5k Òy(¢h³Ò¼ò”}´¨%þdØÓ<{åÃâùšT%€\yXX¹@ýÇ £õ¡ÀkÒ¢t-ô¯³Ój¯WÌÂq4 1 Ä>7ËÇ8ž‚‘æÜ£üÇðû¾Á ÏpÃp&yÌ8¯ŒðOŽhžâÆ«œÃâiŽŸq–{cü×GðYÎgŸâ9®©Ã¨ŒèWÇ·Ø: OaaðyƒÄ5Îñ˜Õ+ðøìÈš1'xÌz8ν0l‚ãÇùZ~Íó˜­]–ÇlMãÜC‚Çh¤Ãc—íyaüþÖŸ:tcCÞ~´ùäÜ¥+—f÷ßzô·þv9yw•<üæq®\½–¿ô|Ü®\Ë?»ûYþYêÙó;ûWM»òéþ/Í_üö¿™¿æþòÍÇ{ÿü÷÷{çç¿üÊ0ÿœ{ôÿÛï×Ϥäw>¬Ý«oüŸœž/{VÛäÞæ¹§5³k™ûe{2Ãñž=KKaèÃõ¿qXçÛ±."»Ën°+£½ÆÝ½}¼÷»ëÿKÿkãÇ7!MoõáÔÓ o÷iDd ?6Y(¢$¼¾õ«Ÿ%‡³ÛB ,Í*æÓŽçw9‚dzhbH¾ ?ø/_u7€#ÓN™-]$EÇ­V0èõ,ÿö°ø ìÚþhÛv‚í”´ÝŽ3èÒ.zy¼aeq·‹RË7V/¿Ùº¾z¥±ƒŽzÅЊުTôJ¥ò‚$¾»r­µºvñí”Þ²C•¶ÛFµ6õËA˜ÚAñÚÜù¹ÄÐîÑíD^âY1+e¥-le"ƒ7ð;tÍ”·½-ƒqºSüN9:c½Œø‘tްh©°g ýPK0XJ@d©;ˆÌP&rebar_core.beam|X{tՙ׸ެ±¬FçI& ŠÈ$`çA®m9 ¯`b…R^²c[‰, I΃òHiC¡((´¡mØm»¥Ô}ÐÒ–Rvié‹RïÂn¡{gÏÙÿ9{ÎþÝý}wFöX|εïã»ßó÷}ßï»öàö@`óþáÑ¡k†Úõ™@ ´%<n:ÅB3_ª7­u¤ÒÈ—+Ín§Y-ԦؔÓî™­•ÉJÍ)«íæ¬,;ÅÙ©÷Nµ>Åh4fÛ]õ#½•V¾Ã 8Y¨¶œžÎ²¥7šõ’ÓjAÌÌL¡Vn«•V»š„ÔBi:\o8ÍB»R¯µz]Ö³íJµ¥;Ç Æ¥²“oÚÓ!(”/+«-§Ýb5çXW¥Þ 3…ö9î½£­Z¾ŽE_Ù©:m'_¨Vóõâa§ÔnÛÓÍú±ÞŽ:Ð-4Y©:ÕJ±»"—ê±B³¦Ò^¨å ÍÔ˳U§”z FµR’ÊJuœÚÑèLáD.1ínÍNNVŽw åBs*è4›õfßǨlOi°t ^á¹°á”i3²Œ¶P;A“¼§NW"n4D­Ô&ë½…r9“gœZ»·Qoµ½C£‰­™¢Ó$sò­Ù"ÙY®”ÚÁÉzµ\íw«Ö eü*ªpxm²2é ƒ†Ç«R›Ê -‡TÑ:“09bªZ/ª]{ö,ª-C “<•¢¥éz\òpo¯ëó|ûDà 5ªŒy=ßЮô 1òHhêQõ:ÇÒl›ÜêDç0ÝX\Tg§*µÞ!Ô­î÷}\^.ºÎs/+µBóD¯rJËsH¦o½6ù1YÛ¶'áò¤dµz{cò¬Ú–JVKñ[w€rGòÓ(¶ƒbû§RØ °“ë’Ÿr<6])MGjð84]•\ŠØ¶>ÚžÅý•I"¶¥=“VdwéfÈ+ ë“Aì2]6$?uìû¸À›ÛõÉO(sÐÔÕ"(Y¬I~´- M[Nr±gm³}BVž@ÏÔîÏÆb\ªè]}›tÅ¢hètmµ¢¸³5Š–‘ýKŽý(ýûDjDX)aHdfßfÝcüJEËâø ï_~üw|ޝ„®Œˆ1ŠšÁK%êÐZ¢²t› ‹u‹> õ0ã*Ü¿쯎4•hœŠbdŒÓÝqF¥ƒŠqYµ¹“æc Î z”š.¨JUÏÔÖÛüY~ˆÐvM‘P´kÖ †ºîùõt~=AâÀ¿VÑP×oÀ ×ý輺ÐñB`£*e󇲷i¶T¸¸ìÌ1ˆ=ÈÊ]Ö(³ ^“ýWQ)L6¶ÛEÙ¢†…î¾Fä Û.WùuÔÐ*¨!0JHìWíº½ê r~ 4 ü¶Â©ikúÔüƒƒ<8å,XJ%x.NP±bõßÿ.+_Ϙ…Äè']krŒÆ0Êä--Šf‚Õ8nSe“ŠæRs€_Oåç6òJ^É/—oÔ ·K®.×%Ž}އ>¡c]Oàü Âü™€¢Ýà>Dî êÚF•1?`´ŸÅùgáæW !úá­mJó›˜ßÌúL(s9? Y²úLPäAHõÈ("*ñ¿™Íëv€2'<‘Uå­›©‚Ýö°¿uçáä[üN¾ÅOD6=-tþøœŸà¬ØqA,|³ûVš f0+ºÅ^bÜ6í!–Rå{)6šÊjd¶¶ã4O á¤)ÅÚ­Ú†¬å,Á£”æuâ]ÛIl9|šE¸2ä2*†7Ø]8ÈC÷Ã~ÝáiüƳ|7¢a£¤iÙ¼B0¯Ì'ø”¢MRåKÓ{‰Tl)7E+ì-nL§y™”AyØ¢hŠÛa2ø4;‚óê¯á5+†ØÞA%‘2DInÄ¢zÆÜ¼Ï4ÌA>M뮦 ^Œ=`d$.úÆ`ï €¾X§Ð¢ "PJji~„¹þ®“ ˆ¯BümS+¶¼8¨YTðžÓu`á7È”‰ ͈y×gð·5țЪ¹ä?lX»-Þì6o›ü˜¢µ#¶Ý)ÑÖƒYð|ÂæÇÉ¡ÇÉ¡³ ü¨¢Íê²'žÚÔ¬g Ñ;J¸¡’}Œ›&ñJ—*¡ÑE©£B´L“úxÄʆYF²}f*¾- :Ëý&Ñ.F^'œ€-,nL¯þÊwð«è£I$ÕçpÞ†ƒî@ƒñ@qª˜äYx§k„Jî¿ *ÞIäðó]ün„-t-´EálÉpâ9<ââŽnΓpÜI?ðNâ©e¹¥]t^#Ë[ã]Pèî4¿Ók' HŸ‡äYrOD~‹‰ðQƒrÚÔ¶‘C~§¨Å1Êj@ò!P~7Ž#x§D—Ñmòûí^ÚÁÉ}ü±M¤IL¢ò˶ùƒ©©Ü_äsŠv?A?Þéœ÷Áþ9á_=æ÷2·'ô’¿¿Hjâè¡4m@[I< hCàjs1hûŠÛÝ$&=fdz1*ì@ò#`ð%b?<’æ§S^KŸÏZàvz…‹å”… =1ȇƒ_r0Ôét,S·òGc]d…|µjçèÔ—ä+ó1E{”ŽTyÔOGòY£hy…pÞ«ƒS¾ …>Åž@}‰ÊŒ5d§¦rŠFu‡!JÙ©¥U‚?ÉÐy´Uä.(³CÑž$ãÓT)_ÆÁj»)LÖÞãz´çV&š ˆGé…ó‰Á΂å½l-MÒbÞ„Í馻kÈO]â ?¢÷»ÎŸí¼ßÁëE¯Œ¨n!»¾“G'£»— ò§áÎgüx}†ðê¾ ŸÆŠ¡gzoÏg(â_“ÏÃiÏNQê>‡Õ=X}^¢Ym­áò½t?¾Ï3»Ãw˜™)›?oì2øóxm%ø×ç9>¬¿® ú΢W¥ü:ÙÁï ¥ð£Z@÷7±ñ<Éþ¤BL¾Ióê}ùpÙ ÿĽà7ã#¼©Ã<.™¯—Ìqý[8e ô5¢ÊCÂÃyωxkΤïsxz`Ÿë³~Öge+9 <Çœ%À¼@þ4¼uæE¥É ¢}›v`Àw(6ÔµŠö]l>€HüÊåb8¨íbný޾ˆ£ø–'íUºÍç)eç)e¿_ä/)Ú÷ôEö’»‚òÀXç[àiþ=JÍyRò‡ñTúÑÿ1Cà ‚ÐóµÅ%Dùoÿ8ÍH·‚‹ãâËü§‹òi™Õ6n .qxÙÏá§iþâð3pø8¼2ÀÁ"¦äà>woå?gáÓøôqõŠÿúÏé€=øåiþ3âôKpzëWø¯ý~ ?fˆ¨E¸íýurØëä°_ùkŠö«E‡½ ‡½FÙ~ÌÂSZe ú.ô{ðU¿ ¿Nó_’Ü×Ƀÿ áÃŒéF+S´7°ü2Øýf€ÿß1©‘^þ¦¶'šßÊ;nÉÅÆžoŽ[ŠöÛˆ9†Bï}Ö ëc^¢ÆF æfê› èÆ‘¢ý.Íß ±¿‡ˆ'aîø7ì• @ýpÔ°äCJ¶Köw<¨üü1ÍO¬þV_òo ð¿,Áå6_ -¿þ\äo+ÚŸ]Ï¿Ño/Ææ-?Û¿¤ùŸˆí9æ_Áûixâß–e¨,4ï Þõ§Ñ»Æ¼/A£q”6ɤòiRf‘#Þ*Ðò\ÝØùj—©Š‚ê½ú.iðïÐà«°î?–þ%é¶,4—¿âì9œ½7Àÿ†8xÖ¼oìÄ0‡ ¼> })l¤ÌáT`|8¥—üýqT÷÷GнA©DØ~Ïï€÷± ¼§hKó¿2ƒñv3Gÿx½b¦¿Œþ;„AG*†‚¡aôx{4Â]>š€÷ÿÛ¨·o`ļ}š¯ôæçbô{óU«=úµ뚦O·c>š>ýo÷Ù[öæwúæÄç.–ârÒÛÿBÀ}—§ó½>ýï ,arÎgËœOîƒ>úG|4Ox4ä“§¼}’ûŒç³´?zœòBÆ®ã~ö;4ÿ?ÿÿ]” PTUÇï.°Èc€ š$awy†=§»ÊS‚”ë>î²ìݸ»‹lŽ‚ ‘ˆ/¡P¥8ͨ°¨Xa©9*>Hˆ)¨l• í»ø55ܙߜÿùŸÿ9ßÙÝo/ñüél6`ƒ0Ï*„˜ã:£ÙÑ:*F` 4¢?‚ûÎù©a¨L€›¸Î2w{ÏÆC8Ä3 VBÌ&Êp~÷±8ǦcZ¨Å~¬ÛùMúmÊ$¾ãÕò[)Á×ø%^Y©%)3Ã\#ëyƒÁû÷Uy¯=/Ü=Ü.ÐÍfîÒÅ¥êÍvQ¡!xæÎî~cs„…³}¸ UûË|µ¦ëd§hËVƒvNñ`nÍçkc¼ü´¤a8Qµ9¹qÓë?î7~ëW¹ÕE~¢Ú¬q}¢²f5uÉÅSÿsSnÓøÿ.ÓÒgΓ%׆䣿ù?Ìxâ¦míoh¬TåºÖ´èì|åA²…ɱÕm·Fβ|g3®ýe1WdãÜoQÓëq´ÌøÓyibv4©kÌÅÖîn‹“ë™áøÉ£¿»z%ÅñúÛoׇçss#úf}ÞpŽÔOoë8è ¼?è8Ǻ§·šÏ:WòÐ[¸ãÔÚ½°cºãüZù®ñ>²Nnè]tZzr©‚Š:}¬òûG}ƒ\c_=Eæ›íy`”{?ͨõ· ²œ¸W={nÐK²î1{Áý¦ë¯—w޵øÜȵ×jÓšY[Q¸KD)Stkužªr=ÿ@Ñ@ª×ÞñˆÙ¸ûÅwK FÏиùVkÿwüžiÙDYBÈÛ±u3R£Æ£%Î^Póo#o2êú‰ä ‚6Å¡ŸëK«{ ƒ7Âù"‰ÿ¿šÁßÕíŒTe§e’£úWg õ’+ÍéŸë¿²îž¼˜Ö+xê8dÑúÝ—î Ó®$ ^šÊ–LœÉûø‘g]HtåÙãžï1j)Ó‘Ð/< {ktE_þ¿ëп ÔbÏ]j03´¢Gb¦øý> upõ) óÝ+zºÏoöaþ°u°óŸ˜? èð¿V…Úkæc¾5 ëèÐgêh3à#ÔÌ9…€3*ÜËx9˜É”¨OŽuI@ŠZˆqïN õ`;¾Ò€X<'Ø‚÷aF!ú„ÑÑ@8Þ- aô[@(î ÞÄZ@f¸¸Æhœs€uÀâù{l à…þ+€ Öu Ójif­ˆù´¬,¶Œ0ÉÓPËÊŽøæÒ@zÌæŸÿoÈ"5"I$Œ‹ŽWV™ ­)‘øùf/ß)¤5p)%aàäÀx¦Z…ŠÌâÀ¯g>.f‹-ÅVb–xÕò5j-%•„7K­"¹pqRÉÕÐR.MJÄôJ$UÓ¤/Içda ÓWÄ?PK0XJ@íHöõ è rebar_ct.beam}Xpåuß½ït·:kí=íéÿH^û„,[–´'lIXòêÏé,[–eëä‚cù´w·’Î:Ý*»{¶ qB“*néBIp!JÚ44&ƒ]BË`Bmh ÁÐ CŠqÒB\ê)m¦}o÷œM§šy·ï{÷{ÿßûVs½{ö…F¼ÔéÜÝiéS Cz†æ -¡ñ¤åJZž¤O¥"*Ò³céñÂqÍŠgô¤š\6ni¦Oŧ ÍÔ²–w,Ñ2é„'m¢fÁ˜š15·eä4÷QÕÈ:–2ú8ré“Ü’ (ÑŒ„njÍȨÙqWm-ѲG–9*9+1]æDa2£9|ZÖÌšíF3 Ý(°& ý¨7«›–áÆH|G´¥Å‘-LNhÉITôÀ·éì8ioh'ímí®´îÓ)ÕâÌ Ð„ª¦lMnJÔâÉ©”SOMq(ͪSšû°žÎzÕ„i’zJã ]·kÆ!vZµ& sÙ”6–Îj)oDjjªÐ®Þ„nZž´‡bdÒ¦ezÇ2ªeiY5µËPAßP§ÌÉëÏEvVܜ֒¦NêP:ÚÞ9@|‰Œ–*Hi‰ÜxšÐ «(©g2(Žgô„oLÏ8é™ü’Ü>y!xL§ÀœÎ¤-Ï”6•ÐŒbêÒqa±a†6žË¨Æ '†¾²GÄÌAå=ö§Y`?JPœÒ`R’ª¥¥ì0ÔŒÇÒ'¡“+ D)GÉ.›]¿¤ Ã><9øeSz*—Ñâéì˜n;Î;—Õ}ä¹!T—IV’á)וÖå§ÞÐX7–Ë‚xU]~%oÐXj: Qqè“bíœÆÒ3ž„šRq†é†I`˜Â¿…}çodL9+¸Š×K¬T$IŠèV¢LPiðÊŒâ*±@ŽH¬ì*NȬR$ËJЭˆ…TyAΑ›I®L™ž×ØAAb"U® ÄYPþñÊ’²HŠ‘;h­ŠÈ÷ÊìôNÂs¿/³w/ ©rK¼Ôz™´]&RaÜ]D ‚[à/#˯€—WÊ”ù¿ž;Í>„–¢ñJŠBÄösì)%*‹JÂ1!R()ìp>‚p ‚%‘=«¸É¬ !è!¡W F£J4 º‚½RSÔ'Fƒ‘&—èx¥A|‰Ä^€ /í ìW±¯T`9¡H$^a´•÷“6^´ã!Þ`-/оrA’ѪgFñ•ÛEˆNN˜fXÎ(²èeŽ)Ñc¢“‚½›&c‡Èx¥»kùb²ˆeãŠÁ?'B \¢¨€(J–Ë‚­õQÄ*TŒžKƒ­|9ÄSžO¹¸¨DÏŠ V2{hYÁ)ÂBüœrÁù,aI-_ꞇÆ@Ë Þ«”è%QnŒ¼´–/#×á®üŸ¸2œ‚€ äÂId–+Ç$VBüUÿ*ZEá‡0.`‡ùJh1_ “įžç×°ÜjZ áR+_‰Uä'V!.:uFÅè¯ÁQ fè®k¶|VK,'-?³Rˆåe®€ŠóóJÒG¨Á£Wàü ƒ¨dIDçœ¯Æøªaùusüz–[ RÊá¯Zj#W†}lçƒ,·^qû *3\1VŸá è0`0裂$D„øÃPÇÐ+‡þqt# ÚTËW_=¨”€¦b}Š[I! F8+Dˆ‹DÜ0å=@ * 0ýnÀ_åÇV¢V)äT¦ AY ¦ü1¡òW,´µ ÝÚ\'&aÁPYpèÅdø”ååh¿EÙ0ÄOÙñÇ(›"þ”]„›X®ÊÉ»½ÛI(AëÿÏú.ÈÂo݇åäáùSN8ʸ¶ùá±ÜMˆŒr«D¥‡ÌN èUaíŨ; :sR#²F$ cYcÏr³8 Ã(mán*b0³Z_Í-|-é$b0Ìo†õæÖÀØ)€­…3Q|õö5Çm†´8¡Šy :0¸±¾H°/Ù9ðÕ" +óM8XM8X s|#Ë5€Z^ŽO™ú û~ޏñrá*EÅ×j/žý¬E?° @‚ è $çr€.'ÂN±7ghqå Öˆ_bIš°$aöf¶™¾H`œQæa˜›Ð™«*Î r+±íðÜúR_´ÚI=vnÌ·aŽm¸Ü-ó|+˵Øw„›Kà³U¡L:¿LvBHÛ– Xú H'ŒVÈüv4´‹Õ>Çw°\»“~M¿—ÉÉd;SÀX7È;c7]o¬õ ±®9¾›åºcÕÔX÷ÇÆzÐXŒõ€¼—^`¾¢7@'{¡¾\e-…­ulÔPð’á6¢×µ ‡^@O‡±þQn!öæC0 ;ÀxT²oé-ÌÕÚïà¥÷‚ß}]èýz?tç<¿‹åv:—.ö|³8+}ò½³k©Èý˜Ênð¶¤E @ëa–va§¤Z~¦@'eÓÄ::à´ž{•b2 pëXnJ Ë!‚PâàbŒpd2ÜÂï'M';LtCæ}x¸qa•``V–ŠÛoWy˜Á›šû#°0nñHüV–»Ž{ÁËþS„XwD´'¸Þ¾œ¡X¾|‹Ÿ ó·¢Åƒ`b˜iáÝh¢á&FòM óÑDL AP£-|’ÉVÒ‚LDœ|sA™Oa_R8RêŸ`9ÕÉ·.}x&œÓ¬$,½–¼$Ã|½¤ß0tŒ«’ 3d1üG­ojžìY`or /ÄA+žÊÝyÿçùŠ\@ Ê£nÕEÌJÊ#fÕ] ´†â+ÖRñR¿Žòë‚”_Mã]²¹Ú¬ÚH1Èo¢˜Z Íƒ|å+óð @2•‡ò|55åùjËËq­úê ä·Su•<|Wž(­'ưƒb°¶ýy¹äÕp /žX¦1‘ì£ímî¦zC”Ç¿½TǦÞ\6Fë¸A*¿…böÐ̃ýi 0®„Õ6óÀÔÐȤ¸Wøåþk÷ž9³oûã+»]ÿËÓ%·ÿ{ç?mézúLbÑ|ü½¹æ¯ßvßm¿;sü‰†ßú«…«Õ_èªûé÷·Þöëêãó߬9¾_?ÿÒÈ‹? þñ_Ìßü«ø/jôŸÜ6tù–±¿“ž$·l.û9ž”Nöëɘ3Šö2DçqhÑ:Ãȸaf÷P~h'aÜ—>*ÇgÕÅß}º)ßI‰¥»ÜNñ[n¦|3=#_´…âñn çí|5ÅH@UTŽw]å1¯RÊãý¹‚îj!‡òîNË2ÐÞDNÀò‘#fÖ>dA©c:ôäøÅ÷»½¥Â1_úêáÃÝ}Ù1øòCïF¼WŸ¶ÒzÖD'ÅðöEq375¥ŸA€GÏY©´1ɸµD:‹6=ÉxÓÙd&—ÒRÌÇ?áLø.•b|]Ã}ý=ñXßîÈ$³¢Q5Ê!9 É¡Ph ÄíïŠ÷ ôî™d–§-IK$›Â͇혎h† AM2áú-õa”¹­ô”6áIÀÅøºêR}ê2•U‹ìM=g$µI¦ºaBŸÒ pm²Á4’ öcsñ¤U¯™ÃØÄ„iaÓÿPK0XJ@EsÝß¶´)rebar_deps.beam¼Yý{\UŸ›s“9æ”;¹SZ ”[îZ†ÐÛΙ´Å“L'*”¡‰ÒÊK2™¹IÆ&3ü¤å½âª…¢VPWÅÕ‚o(¸‹o€øÙuÕ]Q@AªˆE¶»¿ðìó¸Ÿï¹ó–Rì²?lŸgzï9çûþò9çÜŒ\¹sc °þááôÐCµÒ\ Ð}n ¸-Tñ&³•ñ¼W®†Ê¯\)å¼j•Óx<_¨ôú˹Rqª0šöjãÓ³¥Éì¬NKh<[Êa8U(æ»óÞd}z‰Ï1[šføuOeg«Þ’êžBYéèž-TkÕàT©âes3]¥=KË¥j­¡µÇ«Ìf‹Ó b—Ô‹yB½|·WÉV½`®4W.ÌB’W«—ǽâ¼^«Ô½®RµÔvÅb¡ÜŒ—ÛÓ¯ÔÔf*¥½KjÈÊõÚÒz9Ÿ­yj¬C{~iÞ›õKÈ,õ¶Ô7¿^+ÌV»³“¥Jͬ¶¼o†%Ôžë¥ 4çù$lU/S0¶˜óô÷— Å¥*P…IZÑs¥¼l –ûFùü´0^ÎÖf†AªW¬Ö+Jæ’l>¯Ö³ˆI¥TYBAW¬ÁŠ7ïU%Ò“Û›çÍ•à\¡Z-§»³óÙÂì)ÍéñBQ™ÍåüÌÃcÎ+ÖB~Thº§ |Ò Å©’ᇅŒjĦ27^™Z^ñn¨`^µT¯ä<äe93À˜-—Ç•Òìä¬wŠÏMsŠ9Ô P6àI ÒË|µØUñX¥^ KsÙZn¦[ý¯ïÍVŠÜÛWör5/Ïf²Uƒ.”ŠãðP‘Ò Ç•²:T¯6­ì*”zP€ ÓúOÉ—ögKÙ|cMj¬:_ìš™f“7Uz&+Ùbn†Õ²Ó*µ¤£§P¢\§f³5T^NÐtW.ßU„úÒ‚ š‹ÂãÇeÙ|)Ÿ-`™ÜTãµÒ8Ê{Ö[шk~|1•ŸAoŸ—«×(°K E#z&³ùleº·\)€Ø×(|?£¥s¥| ¤„žB¥Ò1>£±¦ ñþÙ\ôzgÃÆ~§ÿ”¦qìM{³¿Õ/6õOÕ‹ 9­¿£Ÿ0Ûæî®LöÖßÑ ‚ ØØ¢ŸõÔþf /bxË´Oéo#@Ë®•ýmX;ŽzÑ‚Ojâ]Åã>h*3XõðÒøÿà÷_ø9šÑÕw¶¥YË,C²ˆì2å&´’™2ÂtKXrÒ”]6áHÐ1hþšß”L³Á4³ Ëf}˜‘´:7`Ê{XÐÁB ¡ à Gü)©3ÝçÉS>GJb2ךHÝ ZŽæ`ù€Åk†cŒX¦2\&MÖ05y)Ó2]}¡°¥M,3¡nÙÇbuŠH×a}†©•%Ó142†±1ë´°\§ZÚ¡KÚa VÚ#¡„<Æ1 ˜pÀŽ3C+¥+™´õ 1û)[hs¥«o}^{Þ¦— ":ì/7ÌÄ"™©=c”4ë2G,Ûu3®ž¶MeÚQØþ&ŸaiÜXfÎIsq0EĦfB„M2/KSŸ6¢FQ’îãÆþ€Æû¶3›»b#½‹]±Ë•X ýQü^¢eÊ:¤t ¶|9 ä§B”Q+ŽZ£dõEü~ûVö•àD ñÓzáÓU`Å*(^ÕZ±ŠbkÇå¤3׳µÍÂ|1ýtKË*2òt¨²¡êŒ· ãjÈXÝV›gÚ@«À¦¼3 ËIÛ¨w·Ì¸uØÐøjŠèYÐp4X ±Æ¤P¸ûm¹©©fHAð×9Ôë0¶eë1ÄZGiÂÖ¶*´Þï(²íeLh3ÍL3­›TöAãÉfÕ¯lU=?Ò·´saIÐx&&Ö1÷tû«ëNÀ±ÀqÞ€èg°aˆ™È†câ—6lØ4âæ•6јpXÈ‘vDŽš2nËU¾îˆ|Rl@ 7øtÄs³)6¬¡•"¶ Î×xLºP„õ uTºOšðoAã͘¸€… j~…Ϙ­Ö­Á µ¾RãçQºuB¬g€^@YÞ@‰@©E©st<ß§.Äs“#6²ÍLl\!ïñБÐx\ºoÚ=ޏHã ”„ÿv!18¿ÈIbHÃÅ`ÐøÅ ‘4“"iâgõΰ¨Ø™×'Uo£dhЯîG—ºq€x¥Ív`UãÉq¡9dÆSŽŒ™gÔ».7ÜP$=š2}[“bk|K\l]!-±Ù[4¾y8Ž9Gl5&Ê#NÜusÄo²mr"Ó¤Ž[Ui'$‹ÊTd$ts@¬xªÔr†Iq RvI«öãR·e"N0‚òŒEHFPÞ ˆÎÖ^CR¸iH‚.–Öá¿ËÃŽ¸„²ñ.Ärh‚†!–ñ5H4õIåc[S¢Œ!2a–Љ3A&Å¥`¾´ÉlùRbFWØ ÖúÁG#¿;)\P»Íús©þ\Ô_Rl Š´Æ·© LçúLÝ`‚¾tŸ…,’â2H¸¬Sße-}meÄß\ª¸K;*î²æ;·Ã™Í˜ƒUÛÑGÛM }dS9b»½ÙÛWÈq9šã _Žh«í'éÆaÊË Äí*˜rUÛ”aæ 0W‘9)ª&j½fße@šiú!¿3$}¤_©ñÍÍ-éonüÊæÄ`c"Cž\ÕaýNX¿%£ñQGì¤VØI­0†V¸Zãc˜#˜CX߃ð¾WãïIŠ©Aüp&È §P€)#—»Ð/»ì 5KLìR°¡0c “£ºÌápÀ#Ø|ÓL7É Ó¨\¼÷KËérôxi×TÒ®^fd’b7˜w7™w/bNéŠÓ"N¿ewuduwG\Þ‡¸\‚ç5I1Ž˜7ÓC{Õ8R`P•IH°Ü×Sì®Wx킸Nã×¶0Ž÷ãeå ýTH½®µ_O o·Æô¦@‘¤£?“ÄÖ¶4I-—Í64h^Hé„uê|3Š&I'ТF:Í&°&pæá+’bN:7Ü‚Úp¬Œ‰iìF:Ÿf6 )žfñx:‚_T=mÚ®\i9%(XNx˜®r !( ï^èr1¥qϘ¤£Ê&‚²ëT3œ¡+Ô ~mîp£j›ºÒŒ86á©kª‰ŒkÁ²+áûT³˜Wº 51}R²¶J–N´T¬0ÃÑ·ªˆ4T$«¸j±ŠÄ§:¤.¡R·Ò<€½!l" Xvºz“…X ¾EÖöÈ„vsŸ¥ÔÔ\LM-)ªˆµ«(¢ÖƒŸÆvX‡5^\6a%Å€ò‘Ö ¾Ö¤-AFØüm]íbî$§îjƒÏAò0swR$˜9H0óQG|LãmÃÌÁÂÌÝÿØb˜9H0sPÁÌÇ3ŸÌ| 0ói<)îÌÜÛ 3÷ÌÜ«`æ`æ?$¬L§±E Á6âòsØñÒF \ (eðâoËî[øÏ:ÿ= XxBGï…ä Ý^þ–Hò'…aQÁ¦Sj?]÷·Êåö©ÅäëOBþéÅäç„üï‘ô)Ëgh¥_Ÿ?`XtsÃõ#Κéˆm§™MÆh÷„–€¶i´óbâ‹l\_TWÜÆË :ߤÐ&Åýè¤û;;é~“z]mü.ï·Ãtl^•‡Aw¸“ܿ0ýÛª —Ë¿î§Fxê ˜ý’# .|@9üe8ü8üU8ü5:. ÛýWð²^¾Š‡^¾†—ôò ùA_wă$èAÚ-¾AÐÃúM£7Ã&Â(¤85kÂÄuö ?ä¯^Ø\½hÑêÃþêÅÍÕE«ßôW“ÍÕÁE«ÿãö ØÀšGɸG•qÀ¸ïÀ¸ï¸ïiü‘^¤Ë¤xnn}¡ÛcÄñƒ¾€ú¶Æ¿’-Aê‹ÔQÄu9t|[õ;½†­f{í»­ÙK:f¿×š}WÇì£T?ôXóãЬú|Ѹõ<Oæðü~R<Ž\?~<?Nh2N¥tüºJ©žë§CÃQD4~ „xOâýÐ?ÒøÛˆ÷O&d:ŽºuùP«r‡UoÁž³ ëGðO))žÎ=Õ‰sOÎ=œ»NüX÷ÿ¢ËJt®%8Õ)ø'' X¤ùÉtœÜÀ§@’Q$©Á¶N‚¸j†""Ð TºsùŸ¬žÿ"ûhÃX«ñŸÒ Rð¯þ—Ô?Gã?Ãä ˜üù€øë5Œ!¦®mç¶¾GQR.tæwß/âg”æcŒÿÞcˆïkü—Ö›§Ä3l™c 1;žÏáÂüœa¶ Äù9º4£tR¸7ëôýÑùa#ž¥b}Vm¥¿Z¿Öø¯šZ®ñ·MÜžÜüzÑ虄ø%ó,mÏ5ÏàXø Ì™‡u¿ϳeFãkä æ ~­¯‘1ñ‚ºÃÓ'aúÂÜéæó ñ’üBÇÍýwºÏÄï™/ñ$Q÷ü5&ŽìùkȆkç‹#ñP„ÑT_6 ñ¡Î€¾Ø©é8æ4þû„øéüô샞—ÄÛÆ¿ U/wÿr§ñ/uŠücBü½ÜaüŸ ôF<ˆ?7Œ_iÿJÛøWŽ3~O§ñG;5½âTãNˆ?‘ÎW¡ç&èù¤xþꢯO¸qJTÁ«tCEu§pRŠã¤g«{Ù•äé? 7CÂkâ/m÷_‡±¯wºÿz§û¯uõ—„8F¦¼Þáþz žÿ™oÀ¬7:¿º¼¡>&R—¬gÑZeŒþPuÙ\Oí¿ÿGÿÿ]• TSWÇ_Ù‚¸´¢ Ä€"`6‘¡ «P6K¨³¼,Ä,¼$Èd*…‚up+‡"™ŽÀ-ÇQb , ŽJ¡ÂªwÂ܇×Ów|çüÏûåŸÿýÞw_à~‚x™Y™A¦‘¬l Sìaf ÐZ äõ6üM„¼3Áw¾;á¹Û ã=yÁü ä7>žaqB}_ÈxÏþñgíD^_xæ=¸/¼NÌ„…AŽŠ"ðGCŽzÖIJ%ì—KØK:Ìg2xoûâúê –2™„ýªßâ7yŒðtÐ/:Œû‘9j¼çRø«`Ö¿ºèpÐÈøïì ù] Í×ÁΫáw$Xÿè[9@¶„÷Eé”x?qð}êáÚYØ BùÇ…óà–ýIxG̪rÁM?÷Ázéiî­8™Ô$ß«?Î9[ÊSÝõ_Ç=›\?×ihGßm±ßtß7›Òv­SËÌž7·¨‡ƒ-VK˾–nw ORþ‹re²ê!Ý}aJ¶ýéWýô³sšhJ¨ÚɼkâŒïíŸû=nÍxÝĽNÇÂüä3Î;KÊË(«ë»7q§mýræ¼ÅîTBÖ7äù¬ »Äļ週› Ô?ÌQo˜Æçƒækmë Æ?ò?5œt³kxÃöÙ.1[LYÛékÙk$b÷f/‹Gõ']ïÒ7þáHú% ŽáÿËÒç:C?*kqœ®® X¬¸q\ét¹»˜Æ=m¬ðÈ<~Ý1ä ME?!vxÔÓØ‹´X˜­QÑÂê[íɲåˆï¥Æ ‹r¹`]ù‹š=CØöÝ¥j}|kÿÇV¯îf{¯ÅÄqæ7VI´‹ÝnÎöäiÖŸNkOb´¬3G}R>-bê]š®Ö2ß1Øi¦MoiJâ–e«8ú§žCªÿˆt¼äè‘x¹€•xæcˆ™ð˜÷”/mü¤`kíï«ÿ§ÖKî‘øåúw]º%-{ìõçWÔámEýUüîUëû«»÷¿mÛ¡ÝÛPûðòõ[öˆèû î­•6/Ö–s&Úûz¾Hí÷£GM DýoÜ£3ÏðÀÏÿ¢ÏØbkPßbà…;ƒ¡*äéËòºÎ¿ì•u\÷rZZŒHŒôÉ<àQ§?æ|5‰GÜ_ϳÉÒКrÙvç–jß¹\ZûU Éf‘ñëÖ<^ÝSMuÜlߣ1e0YÜdXþ[ÄÍdÕ¾çêÞ¶WûÎòá4£iýÃ'ówy£.ç'Ê=ã{‡ö[>Çøìëæ²] «ö=+}¾G•6â2[Øysl¦¤¨JsîaÔO&ûæå¹|ÒV™](|peÔ+åËfÏg®ÉHœJþ—I××3ƒx>äCžzë|È…<”ùÐ!È·²!iáÙñϷΓ,Èß)aæ2ú@rè7I ß$ƒ\}ülûH ó§!ã™ ô+ ã~1Pôñ}$CV@&ÁçGÀúøºpèãs%2(y=ëñu¿ƒub ‡CÆó»ü`MÈxŸ»Lä·Ùå ŸßÝ!ã>C¶Âµ®¡Z->—<ŠâI©™!gk”+”«‘üÒQ«bÍfgrTýó¹øÌÌð%þ~–Wòæxž¢Rke*¥7,EˆŠa*,C£S(øX.°Té´"&GÌQL‰;$™¡È”ƒ:*B¬tJ*–)Q‘” ¾‰ë°Ô˜¸ˆŒ”˜øH9bÏa±9,›•Áf³Ølö›Ð*nxrFLBT¢±‘È´®¨@ÀññõË\é)Å4 )9báËðgøâž¹V¦@¥–0}îñÍøÖ|>‰o»Ò F¥Ã„¨ñ`JU ” GåL &db¨€ýF"T­a ØÁL$T Áÿ>‘ÿPK0XJ@Ÿªnï0rebar_edoc.beamMS=oÓP½ös“4I‰‡HVËP©R›¤ ÄðšÒ–HýR?XÇ~IÇväRC%„Ô‰NL ýÌHH0± T6@ü$v¸ÏqE-ùžsß½ïù¾•Íí €4]_^\_ =~!.g}ÖÒ}™žA…!Õ- ­~0Ö÷t3¦m«ÏDÏåNÍ„A~h5<·muH‡…OåÐÛ· =´ŽT©‘m\àH…´\Fò…n“"(Bù¨Xü ÂÖÒ@)‘$x––·fš$R”¡‰¦XÌŽƒp˜t5骬dÔÇ(O€ðšɆ|(¼áTÞóvQQ nh'ôwù΀¿Ÿ ²ž’ð%2‰6z.ŸCä ÉYå’sãz¡$z q!".ñ9J—ïü%ò9ŠÆ…•@kõuLU¡úwã%Œ°¨zZçÅ`SPÕ=!½Ó¯KŸ&xUv‹.y‡=%Dõ”šÀé©`¿îG¶Å«$_IÕïõ“æET=¥ý_"|^$¨§tˆôAd"%.rDUu¯#“šôcV4TQó´>õ&®ðC@òƒPt㟪 kzêŒßÔõÔ9l«|û4¶ôÔ L…u˜¦%v×è8¢ $¨´H­‚_ìó´*­AqîÖkÅ-5q²i@ÓýkôPŒÂPüpt«OëÓ¥v}+T}GE"¥@2€ÍÔ;~]™Ž@ôf3a¸c=ºÇï ²UzÌßó'õvZ×¥ØpŸƒØ{D×Nt’z$¨ëT¨'MtJô$ú³±SYÝ/éQ¿ÞïÈÂïv©¥Ý™¶ë©Ox€g|깎S’ÒâÞàaúÔw|ê{D\ ¯ñ£Ãd­DáºîÝz¤OõéŸð<¨²ZååÙ8±NÏ תâ¹&Õ‹r­ß§É-Õp6’Â\ór+â<ˆ*¶x¹“ÊbI÷c!ûµ÷¥Òûmº²äMeÁß‹o¨A!©,õJ­ª_|‡ª¬²ýªøÞIüæ´ («jÐÑ¢ÐkVŠ‘NUèRˆ £tJzˆŒLWu5é•üÉ”¬úÍr ”Å ¬µ1„€é@=(ÏàÂ.ÛÖͦKË1‚qIðÇ%5¤±éþ~6>w1¿Ò¢ìWu-òHɤSr‹¿%Àk­jÂÚ ”ò¦<­AØ Pí=Q=„ ‡êtÖ¦#8yêÖE¹­Q×õ¨Wt;@€xfv³ypažÛ…yäÂ<¸ÐÂf*+´W\!=¢ñšˆ‡‚ýñ–í`ó¢ÊÊve¿rƒÆfeá[õ—g!i7°9¢<ëz6»JEöÁÿVœyvm{v7›Ÿ]ŽŒgIcWH-·ø׳ù Av[V”çè~QÞ¨“(XÄw%¼I´à£_Ñá1ôÎsôÚñ¬z䨻ÊFš>'yU›k·ÁÆ\58™´A»Sô ¦-í-”Â+x)o«Ïæ}šù²¢Bâš(·75‚"LÍ.á('^¿”¯Dº¯cR P/4³h@Q¹}•°“0kíf(\ÇTἤ§è*Ò×.ÑiUå¹ úýÕcKg2J‹ã`Ê¡Lcí[„£Â¡è Ø5Êv­(_S=îæqÞåÕ Nª}êÚ`(¥¤RíÉ㓊 ìf áÔªSl! ìœjÊ˵º²®:[mÓ%YEªDy!´G^^Œ°7 ?áFM#“N~èä¨òüÖI^§äh;²Zí;SdåF§Ó{%4X:’)¹M ásf¨Ö¶äP7‹À»ˆëÂzÄ9nK€÷¥¢¼¤ƒEBÊM70x² ª°„üS©®žòcÖTŸ$‡(ëS LÖ¦„’ØIFàfPb5xue‹ŸÎ«'äøMyM¤”þ”7™à}fk>E]ÀÅußùe.ù›¿@~»Kþ+.ùë! RÞÕ¨éÔ2t©½Š€•„€•º€å¢Ü ˆ8÷ ®LäÐÛhi/¡Æ+ŵ¯¨ÕXCàËÓl…;+)7Àú­ðbU[-¡5öHÕRòld/X»UÞÆéf«TQ^c7 ûҡסb&H=1'°_AÄx#îêÙ’sã9¢2@*Ê °ß†ç&àÊJ0ôƒ¡_‹÷ Ùx¿jÇûƒ¸ªF³Î–-[ÛÂɸ­žÛÚyltdÏ*wjlôüŠól±[lD±Y^”GºØèžÞ…ôH_Ðã„_Å/¨ŸÆ/h *刪”ÁÑ .§-Þ  -øTZñlÀ¹mhQÊôð+•}—ÚLCkh£vB”óºbSœ£Õc9†p'ÝB73®é„B¸YKt03D6ͨ² 0$´xBè'Ôl<ÆÌ~g ¶™ÕqaÀ…}2žÕÎbë€#{’Â5Ï®8ËL„»‹+»YQ”Ç!…$™N’Î#I¤wÁÞ‘º Ü…ÏwçA‚ü,þ¿¸ÑÍö·Y Ž^Æ÷wVAwñ8^ º…ý»ñ´»ØÚš’ꥥil's§Î2ÀYårõ½ÓFº*Õ~¶D1f‘á„Ô]Ð~xwÓ‹©ó:§¡NŽÔxïÂ6^aå=]lo ¡üõi ¡{ÜÊ÷ÆØ]¤ünÞ Á}]ìž/Üç¼'Æî&ÁI€àþ.vÀùÒ°˜ÝëW7â;OˆËíwËÝ 2Nï~Q>c“¤á>h¸v±C.ÓnÓ«ÌOmÄ›ôsU‡bì>Rp ¡ƒÑ£ =Õ¡z-åûA?Œ\íb÷û{ü¡(žÑžh¢Ïþžþ¬c÷Ûz‰.‹„ÓÇB1ØZ¯±©L¶ à = ìÁØÅމòê¤lÇ‹·7à‡þdÌ_}9VÛ€è…ÐÆªÒ†·]JJ|³&ñ\;׎w±G¤Fmêî“è½$ª±“äÀI§‘žVåÕ/ Ùq4’‡«+¼‹Ð÷7w~‰±‡()'uå(ÝQ1p? k ç¾²aÿž§»Øãµ à[ }»¸Š¾ñ\‡r,øÞ]’Ón«ÇØcdõ hzšžlè6ìê`OáõÈyzŠÞxžÆþIì?ÓÅž½h /Oô‰·4Éÿ89ï©.kϸ­=cO“µç íQh;ÓžêBNwõýì¢ð·ðWcì9~§œ³õ ‹ò X>†å‹X.å¯ay˯c“„þ²µ•þy±~¼„§ç5L—cx1ê0$Œz   †Ñ„!b4óÿƒx¸l€ËÎÀhãóY³9Ïsøœd¯äFˆÿŸ…xÚ]ô«ù¼æ§—Ó¯átZ/äúiÞÁõ“?a>'ÎOô¨‹~Ÿ/øÞ5_Îù)–U|¾Úå?ñôp:Å’påj ç!þµ.[s9­uW®Öszƒ+'½|¿&»ÑEßÄçT£>W>oçtÒ½ƒÏ02.ý†ËÏa—ÿ£.ž1—oã®<Œ»lísÑ']ü]úïwÑ»8ýAŒ‡x½ˆ~Ü¥ç„+®Gø¼V#1¹‹0ìÄOX(ðýA>x¬­\·Ìçίñ[Ë«gm¥b#û4—ý:×'xö½ù[<ãô¹MA˜öâïñyŠÓÏr}‚ø‹—ÞÆãaÎ÷$ßÄOþ)†Çœ~Šû!Ô}ô"Õï0—?*TÏ¥Pßôañç;Âcðxî9Gµ¿‡óïªgBô½¯â¹—ë¿“Ç/·¾Jgt‚óSž¦9þŽlÀÃäþ óüˆ¾C7ÎîÍ—)'À­çÆ]Ooþqñ‡šZ>óZ<¿íåÖ^¹ú… /)Ü'¬þééuÿ2ãðk¹ÃÊ ‹Nÿg×ùe‡æüöÝ>zû£ Ç^Iýègç~þ­oüÅ–÷ÄÒöo~ØÛ¸mïÈ?÷zÃÿÞæ—ýqë+o-kŠ?±bñâeÏÿdàwØêOØŸ&¾[èþã¤z´ò]ã/‡³Ïçž=óaÓ?ÞÿÓüÛÿ4Í]tõ±u¿<Ñþô«Çþ{Û£§>¨ÜÒŸþå·³`ׯÀÇßúh`ëÀê;ÿ݋շÕÛÇž8úøöºÓß[’Üú»[_ÿá;©žæº‚æù°»­xúçåÁÞz ó·Ÿmxôà7^úã݉ß<Û÷¾u{ŸZðï_{ð{¿ÿö+«îû«?¼üÖûÝþoþùÑ?ûxîÆÿðFâûû×'c׬øìÿY¼oþku7½ôÜŸi­øõ–O{Gß>×öƒ¦È꿽óOC{Ö<ô8kf)Ÿ?ª=Ë17®ÜXz”×ñ ÆI>æ2\ãóÓ—áê¯õñËpåÆÒ}œŸÎê>ßq/Ÿïãkšï¹ owsº}ÞÜsãªÈyry>¿ c„ÏoÁÈrYêqiN§žx§¯å2D§Þ:“Ï©ÿÞÊyVq]#õšmÜêÓ›ùœÎà>§»!Éù`Ä9îžnNoã2¤Ÿz‰Æçt^Ë}hè)—-Zp:Òˆ''HvÑYUaÎáý/¬žóúÛMß?ûõÎ>M¬/aOvø½Äï3Kôc¢M„úœÀœ_HÓve|“HÈ ‚ã³cBÒÀø☴„-£Æ±/Îaûλ;`c ?“Òv]ÑÛ¨mݦiUÇB×±NíZV¤¢ZØ_§X'mÒ‘è`b›¶÷³/ÔôæÞ{ïùžïy>ë®w`(LQÜ©îXצ.SËS”í EQkty$©'d=·?mæ)-_Pr²î´6­¥º¦™.C+ê)9!ï3ZÑL¤Ý•×ÒÅ\)ä€õI5cknÊ|#IC¾O†ô¢êžÝA+˜†» JiꨒAÙt@TÑÔª‚®rŠaULìM抲3-&‹9snªh€î„™Ìd÷j‹=¤N‹œIiiÙ>>¦¤ÆÜª¦‚2àRÔŒ]ÖuM¯*ïšÓ2ÌnŽéÚ8cêEÙ>šÌ²ÓÈ*…‚œv¥µYå6-[m%©&ó2; ±’CÒ#Žî3æt¦9Œâxœ*Ëic–ÅI–å”.—4Ìð)£Šœ¶—òDIuÿ\]•uYMÉi’ŒÁ2p¡%ÈÃx€”«Ã(JVûÇç vDI=Q¨½S*4s5È%zA[ ù²¡X”9~L˜|8ùZ¾˜§Ù:7Å;ù‰ÏÛùcH8h§„-~ìXé4€æ¨ ò[åõ0¤ÀÔŠ{®” g9·AP²rUbeøRwxŽýI‘gD®T„A¬x ¶¬Ö H³ ÷‡ÂI]#rŠ3¼ÈÇ|¶ÖòLò]ûôʼn3Gã·ƒµu»îÞ¹®]Þ¹ï³ ;zìâ÷ñ»uXk[UÿƒÙ'òü×ß8=~^yìnþÙã§¶ù_x!”z5~$"¾øZvêÝáñ¥™Â•ž›KÞÙ¾9¹­cûü‹;Ök·?8ܱþø¶›ÇF.,k{éö寽<¯n׿®™zù¿ñŸ±iÝ+¿Új»²á]ýí?½¾¿ÿ½K¹ÔIûGô^Û3¿M}ð=—rK«ÿÝ“m7ÿ³}à©_>ôí¿M|eš¦ŽŽ3O7œ{þÈožûéïvœ¹Û©mùðlõfè¥ï\kË óûŸißùÂëw~ÿÖzωW¡ ýZŠôìE°9ô¬²O]–Of|½å“Ù_gõÌO«µ¶,ha*懜ÅžÎÂÍžYúø,{, ki"<°j+Ît™¦NxäHdÌ–¦Ð^C-ݨ8ë;M„bI„PfÀµJ¦[´¼²k·}Ë•"Ï>gEKf»] |»á‰Ìk™M«?Ât:¨²ÓZµ«½UË/6œ²ÙVí†Õ°K’Õò×*Vl7æÔ»™v«Ü`•½Ëm˜­j,ÆçìvOÙµLߊ[®ë¸»`¯-ZU ÅoÆÊN³iµ|²ûl5ƒ¢éV=b; Ûó‹¾S,Ù-Ó}‚gD¤u×ö­"s{;|NƒÅýšë¬ï®•pˆ­:½7=\rܾr š[ŦS±âå†e¶H§Dˆ •é«X ê[f¹&3 ˜R%Ëlz¼,ø2¤ S¡¯“æÅM¨ï‹ëv£R6ÝŠÔp"^ïMF"ûÇ„æ×»%‡MAl6ïõ§ ¢:Àúv=ߪ695Þ(-ë“™q}|dü6†·­!4T¯ÃÙ ¨ó· ¦‚I‰%«œº§ R¼@,DU(Ö覚!è„â1¨é ¼E_UhŒ-°hLáÕ·(Nѽ‘•|'^¸:ßK½ÍÔ¦t)\ûÌÿ:æ.Æ’Ò¨Ê]î'*“¡{D<Þ$†AT’Ã1,’kˆ» p˜èÎÑ¿ã~ª&øYŒÇ¨’¢’)† ÞHÿ ç/åŒèw‹êÇ”»ŽŒ`ªð‚*ÊkÔ€ým×åC”W6‰ –Çqõ-•»al+ÜÇÐðˆÊ‰„ÜMW⪗…£!ix)§,ÁÄÁ¨êT½¹avp ˆi¬YÖ€ã9Æ&…H#§@S ÍF ù e„–|÷$ûÒ.6ÛðÉõƒ» VÆõ€ QLëâ +ƒÅÀö€ D†OF>à FxVw_„Ûß…îÂŒtÕ?áYüPä³ß–;"ÌØQüK`wE>ãywä§Á¾ÜUçž®ú“_ð»ñ\î,Ó‘vä£h?£Qž}†vÂöYî!E?û“S?8öôo)¹ð»·•W®ýùþ§câÞ—¾zíúoýè§ÞùkóÕëfùÒ×>ɽ³úÄjõzuèð0yä—ÿ{ñ>çx}çÙøÊiëìÈ…7¦?Xþ}þähíõBì®7†_xà©>óÞçG&¶ß=üŸÑK¼óä»WjßüäþÏê—þü̳ÒòçOË/Ol¼!<¾sÍrpú;ÿþ«õÉg/hǾýÒöºuñÒžíïþeðÊý9çÇÏ¿ùâô•×.üíƒ#ïy…OÿñÊÔc§…oýìÌòòž f¾ñ‡­»Ÿ{|ùúRpÊlo'¢Yg¢9²ùèÑþÙ Ç#½R‘æ±è\‰|ö¾8ùý³¾ï²™}¯Á²j± Âg¼VøÐ"èÉí¹ÄÐûëvþçòÛÞq_[›_l­Âây†¸…8-z*HïE/h6á­Î=Nàà µŽÂ—,‹pv ìjT¬ ê ZkÕnY•†µJIs§O,O.>˜«£)=3¥Oeôb&£g2™]øØüRqñ¡ã×Q_ÕöU«TšÊ÷®…œÎX®¤ê(nLÜ7a°ïÛM«ÖS‚/ÕûfÌ”Ì>“3å çnÙª£ñÉšÓ´&¸UŸôÜòdx¸åݺ~MÀuhm¶äùì0þPK0XJ@rs'@¿<3rebar_eunit.beamŒXkUvîžÛ]÷Ì÷LË¿ÀmKfY¸mÉ0c3v{ä±/öà1Øì²hz¤°F-É/Þ…°&ɲ°XXX ËÂîòòš÷#Ä„lò+)*Uù“üáGþ$U©¢*•üHUjóÛ­ÍÚ&q•¦»Ï=÷Üs¾ó¼ÞwðÐVEIgÆÆ÷ܾ§Y›Sý_Eùçß›vý¼×ª–›ù·Ûó+nµÔ•LFgʯRžÖ½j£å{ùbÙïªÓ µ¢ÇK^3_w›³ËÜbQ¾¸ZÓoy Ÿó¡àV³\iè3åj1OÒ‘J¹ÑlDfj•bÅXˆðõ½Š×ôòž[˜Õ õ¼o†Úù•B¾P›«ƒÓï+Öš ´¿#Óž;×XVwýf¹Y®U»R©~ßk@=w|eËê~­.O^FŠw+-/2ãV^Ä®ùMÞ͉*ž[øsyf™ÜJVGiSáD‘“ªUwÎÓî«•«Ü›.WiYÔ=¦†=ÁY­jуÁ^1Òh•›^o`C¡V)—t’TªÔ¦ÝŠF¢@²ÖôÍîFÓ/WKÝÍÚ1 ÞG¬ µz³¡—ùãž?]kxú"Uú ë hÁ)œð¡å6UB%I 'ö䙲ßhnYN;:¾¹w!`ÇK/ަo÷¸[®°ñ;²='°%†îà}9xBªdëž8tpbüвŠ|yF-’DS(ŠGËÕB¥Uô¢DŽd¢ï•Z×gõV3Rô¦[¥e|•Z‰á·u¡0„ü›‡K¦+^1ür«nåÔ¼©¸Í¦WÕðo{(¨ºÊµnÚî6Í€¹À›m=­PÆ=ÕÚ=")z°Z¦D‘¯‘FAñ|¿æ/w+8 x*/i^QÕÞ’_kÕóˆ¨"¸ePjåêL-Òœõk'ú—¨›Ÿ«»ñkU<.Ü’ ×"'fË…Yéò[yÞ+vO»E×/ ̺!1O”ŸiU{!y:ˆnÕ‰eVªÐÚDCIáUjX(öVkÕ¼wa„ðëÁ9mNÉENë.̶ªÇÂFŒº ©¢·Ò­”KÕ<’‚½"¨­jSM…¦ðþP¤èŒÈ÷Õ—Ðó ¯@YÛ]®Ñ1±N¯´aP¯¡§ÈìuQ¼òÍš zÑPðªMbJFPª…åØé•À²J·^ÏSÚ6zðV)\:Ò lÏw&Ü×l5òÓÌbí(x’ÈÀäã^·[È7Ýiæ!ñÜFÉœóêsE­Ñ¬Õõ*Ž=æùU¯Òs¬\ÁÊIàÖˆ´(Wùò@¶ n^õ8j’ßÐ(¸ýRk–5¢ÄÙª4x–Ÿpáh \®ä‹ðh4Ô,:Wþš¯í=xä€Ù,ÏyµV3OÌpg–hðmóêºÛjxáöEõò¤nÝ+®ü#R~Æ¥Pˈ`¯x^}9éÖ`SW2eËÖ‚1e§d…õš¯c­÷ÚxÚ©^Â’œG~^‘êÀnAâê?¢vl‘º-G),—äüî9onÚóõbYFœëŸÒnì@®¡·-oÕ5’¾>uI OÚŠçÖTDV¥é*Ò¥züÊ;¶á¹-…¶"qeÎÀŠ ©ËDểcmjIT/Y»:u¹ ÁÛöõË[SÝèo¥æì×rÙ©xꊉ¼%ôólýð­—ðlÙ®­J-7AX†Òï—§[M!à¬Ô¥er âQïdyÙøÆÀí«R‹M <0ðnléB[½K¸¯(& àv§¦º;˜ZÒ!YÞnÈ*‰k/á[Ôëòk—_ Y“êœ'–€%ªµ¼ìÌ2ËÖ¦– ?K„˜%@éT&¡8ŠÈÒå@§Ùp.·ˆä~­Ö¤ _¾°„Ý1º”æi·!Ç5 ºYô+EYó÷x5”àßYEQ{ñÌ©F×ÀFKµú¦ ‡Ö”wœbF-%jÉó5å—¢Šå°½à‹6¾/€!j8ôæä ÓÉY,jM8,|ÙÁW¢¤8™¸Óe:,µ§¢FDÑw"îÄX'1"v)NÎÁ±g$í0Ó q‰±?µŸÀ ‹çpPÉÀ–¨u~¤Åv´˜5ÆsŒ1'Ã3£)æ038úH¯ÏhQ!Jœ ð?‹Óñ‡™Ïh–صTd<Ù2}'ÓQs˜æ$ˆS³þÓaiz‡rؘÎô'4[l–'BæûãeNºwôÕ,ja{l'ó Ûõuãªíh¬_Óýª³ùÎ Ó¯õ ñ¥:áìeg§à€¯$Ì>PLuê6¦Öoaê™®}½¥J@ÜPϰAQÏûQ…÷bÜâŠz ›õ‹……©páK,\c©_õ9pm¨9úéè×âpnv4H°^âÏcIa„> ÙŸèÏÀþеE& ¦Ê (ÍûéH[åI‹ëC½†µK¦cÆé¸8¼BåænMîˆõZö®˜X!­‡ë+¡Ï;€ ˜WìŽ X`^ ɶ¡òÁ^­AÝA[¬Úb-à«ôubµÊW9¹3lT¬Qùj§ ú¬!'êÛL§+=´µÁ]4Æ-âÖn¾²3ø¸ªÏ1(~±€á±À8úv¹=½š£ß¸„€$”ñÅbyý‰ð5 gYÆxî Fÿ_R$‹Ë而Õ$M6É,’¨„«kPëj¨·CQùzxØÉïN¤àyv3´CtŒ>Ê"–ˆƒË÷.<7Hî‹àÞ î/Àí,rïiso÷˜¥ò¸-6š;M±‘ÀLÌM*OÆ>ËÌéÙ7»¼°É‘k°k¯£ò¡>ÛÑ#| Ë&ÅõY}ˆà2™£ïƒ35' øÚ¤¸–å¾tôuðËu*¿¶íÛDÐ:•_¤±cÆÎÈWŽ2®u±ñ È}eö÷ÒWS Q$\ïdÙ€—$´¸Á¶¹×¶±ŸŽÔ×ÁÞ€/ëP¤$Ž8â0¦hÔ¾Á)Šœ»Æbm )7t¼ÛÛTn#qÆVl9ˆåm‘6RšŽ£|Ò¨Ð!P;dF!†ÃþŒ@™Ò`ñv•g‚0@!°Ä¿«|»¬ÿë-r¸Á7 ~PS,qoÉ8±‘’‘†å¸Aé—8-Çû)IŽ~§)•‘Sm1L “E7¢›T~£Œ=…Nˆƒ³o¢CÈ SÔÀ´»^;’b'ÓÆíìU(µ7%ÅÍ̧zÄo¦¼ïÝ“]¶ØKçìÄéb÷4wC«ÚëôYüå¯ãl~ 5Öã^ãØwØã‹1•ïcñøYcq%=7DciýÛ†=±Ïb9?—Uù؈ØAû:ŠµØ‡jãä-BAÂcÚÐXQ4ª-”ü¿Ú]·oí^$Ý ÂÂâþ/ˆc<¾Ìˆ,ÃJJ÷³Hgýž€-Ç7øõ€4[²Û}ü§vŒîEå£ ãQ£f"çvðqBÁš¬Pné³ G/‚× c79"öÚýî'÷:¾¸ Þ¦ò[Á÷/"B„¬5–U&DzF!)ö§T&5§@FÝ.“”ÍÂ%ᛲýðÛd)‹ÙÍÆ”$#Ùx‚²‘¯2±c†pÇ~2ç°d–Ü”gtÈ*’-U~2VS2‰Ãà>(ûÀ„au¦œC dSX»ïÃó"ÒÑ™uBÿ¡'Âoh«: Ž9åá^‹R‰BZÛâ{dpJ¯Š;õš¸K¯‹»T~gPn ¾eD´G;娩'#£âˆÊï£Ê@Õ5æYµ›Û—ÝრôúFzXMïIg'A„ŽJàX zäÈ k¬a<œG'ჳ†â<ŒICü]§UG)0î†i-äÖ7mqwzgZÜM ~ Þ£òoŽØ|k¼?n8ö>;c93wÒ”÷\Jú6$H÷öÚV¿Fu‹jJ€Ugîäa`¾ÓÀ¼L³µ2u¥Î6ÐÐîc¬ä ¤ÒH@ÓYÇÆ86’øuäa .Þ¯¢ ¢?±H¸š¥µKÔ&ù)ÈSPûê®›Óñ 4MSÝ“›iðœp4R=rkjD DaQû –Ùû(´cr>3Ͱ<TÞ`%5 Ì7,…¸ú‰iÕ˜°¶q ¡4Juò¤Ea²qÙñ eIšT “Š0é´GÉ ÎÐlµ`Á ,˜¹œP½ô±ªÄx:bð [ý‡?Èæ“㉠h¬tŽœBw£1EÖ°ñß„ÌÕñ]ƒy‡'è ©R‚*§¡ÊlPí·ƒaˆî†#ÛÌx.HCÊ`}ñs_Rc*þ˜*¸¯%‡ëU¬Ó‹ßÈLÓ¸ÉÂ%İ\6¤¸æq¯R† |,+YEú°†”|djHabÏMŒúÚ0D]‡i—^ÁAã9̱#èYâ³ ò£xÖúP«1‡"ð•H…ï¦Ör${ŒÄÝL‹cæb9-—µDv»:DÐuÿˆ¨å:szm@'´6Æ,)Å m§&ƒ²ÌW9‡™ ×~=5$O8ˆ€}¿]Pç•7dñÇðÍ.P郒²ÀR¿EFƒ¥“Rc™ô¸°€Ð ~Þ„z?„z­>Éø4 ¡–š„C.fÄqê@›åÀÙžƒº‚û8Ž('†ö~ž„°“ÃâAÖ7aìa™½8Ù¡XgÖ/pÈ“»â%E†pÛCÊ7Š„”Œ„°ö禘9®™A匫üÔî^Жçä|g½˜7ýa1ßO£ ͧ±š¶ÇÒèBi£0–¶Pç'õG2bm~¾qM?%FÅ*Ÿ—ûA;=kÙAâ¼Èº ñ¨Êÿ„(ÐéѤø>SýyºÝíUù÷¡ßlLœ î6ãβ"ùcßéˆÂ·jýÁ5òÑrp:{®^1ýü5õ2pÙ²$@ü@ÇÇ*qS¾ü)Î<-þÌ Ór*ÿs¢@‹$ Zü•?âKÐý‡#âqàñøBQO/ÌÆl~«ÊŸãËØýä°ø1ÛÃÌøˆø‘¹? 7º1Sac¦¡CÄmÁð‹Y¨ý!g} Áðv¡åbã& 4þš `zRå?Έ'ÀŸà¨WpÔOAþŽÊŸÂç«ø|zX¼Ìp[ÛÃpe’û“âg 7Š¡ŸIGÿ&tô7’âZ‘7gUþ ð²)inWù³ù¸¾é¯±€óç œÏ«üçRÎëáÒsKÏÉ¥7X æy[¼@Õã9ÿâ‚xQå¿Ç¨8§ò¥*?—/™Tþ"¼3*~©ò—è¢Ce:­¶Ò ,Þuô7ÃVs•ÿ2øÜáq›¤"A}McAοœOV¿8oÁ¯ ‹_Ã-ñôfñj\?ßk;ÔÃ1¦cViLÐ\Œ‹ÑoÑ^ŬÐj¥ò_gįHÖo ëß‹7!‹æš70×¼‘µz'¦0Ú@“w®ýÀä^ÂÁoÑäõ–áµ âu•¿”• •¿.kŸuGRœGCeÙp….0.+ƒFƽáL²nÐTþfFÀ¥ñPÑ·hꀈ÷ âÃañq¨ÈGPä#Ó^¢È‡Š|(ò¡Ê?ΈHÊ'ò>¼ø#âdá'ÌÆx‹DÔ(Q˜²{ÉÈä|ÖiÈC‰¤N¿Mvzø‚>Àó/Għô)$(LÆíb”8ÄØ¸öŽ‹í&òv~„5">ÃÎϘÝ.Š À¢ÏL æd‘å“§#SüÆlœÉçdÚ4ì©}VœPQŸCÔLj°¿ŸCÔçLbÁp[aF'i¢›ŒËhJìývøŸ&íê÷áõ{rõß@Ú'ö·‚Ìý_ÿÿuVTWža&]b!šŒ®FWwŵ„X²TKp †¾*EÊ.ØKBŒüŠQCÄhì5š"Æc4b§J±¡!¢FF±€ÿûàÞñœÎùv¾¹sï÷î}åîÈ*NV«’$ƈ&ÎŽ3)8UŽÈȼŽs”x/òÃò§ì:*‘Xþôá7 5r¢ÚÈI:0¨À ’Œ*ÆÏ¨ͳícxo?5×r7ëT¢6Æ_Rp*YÍ©X¾¤TÉ¡¤Š‰Ã’ø‘,_ ïû2ƒp†óåÔ ^¡ jPW‹f£ZŠ7ªµ6¡ÂOù+üš;ÀO¼ÒLæT²‚¬<¨\ßý%U€k€Â¤1 BÿÐ ×ˆÄ (‰›C„°opZQ$;RæHè¢ÀRƒœ G->D¸Ž·8 ¼TÂ-•µ#B·9–ÿÔJAí¶A¸ÃITélnÓ5ÝÑ ’4þ‚À2˜Ç»á>碕 ЕlÛ–=;R+<à†qƒβ²›p¯Ph`ù{ÿ.Ì]ب ô†¾Kp_/üEx é=„QÊ!½G¡±-=˜¬`:½Gtt£^xH¢› °„§-ëØ_x¢Ržqµd©ZâÓqOZ—ê1Ë?Õ MDá(T‚ÂsƒÐüÿ†~NK4ë…g$ðo¬‚Àá*0‚|Aþ£þ&/!°Fd݃†m „ù I[Kk*ØÕ /!ØÝ‚ÏA0gÐ(¨QÇÁ^ðV9J -ÀÑ ½ÆŽ؃ÀppaD âÍÎöüxŽåÈ~qw8Sîük’$«Èž ʤ«Lp”áY-·ŒÙM«q†Õ×8w– 5NÊn%ëî$JŒIáÚ²•Ý•2ç`Žcs¦5Œ+hj:Ü@#ð†Qìö àNLëE¸’²» ¯aìëõ::¢á*ôq¼>$¶úØÎèCÞuAîx“òïŽv’Ã[”¾DåÓsVz¡_@?ä€þèOž5xð¤ü½P‡pæ@ø`ä&jN¨9 D;ñ B{`¥cBNjŸš‡PŠÁضZˆÝ £j‡ö ¸ž Ú£¨ùŒFN|bЇØã¨ØIh#µL¦òŸHñJ'íV€k•Û ä³¨œ‰ÏGŸCéÏ£ìSöO ˜Oå¿€â9È¡.`1Ú?§8™Û¥èó ímëÈbþ_R9|Eåö5Ú‰æZŒ]XOùox…Ûaþ›˜öý³…òùyÛžo;S;^·Mg5'‹)¾›òÿ ídoaÚ×î4Ó¾î%LûùªfÚÏÑY¦}ï§ò¼HÙ/»ié'Œžií#Éè»9ƒëñ6Æ9á½þY©ËÇ1k[í,qŒÝªI1p»ÐªÉ¶õ&ÆnЙÙp+Æç›¨Ç°)>¤wœÀç:Ì™QLv'gïÚK0W–™Þ™Œù Úɼطè¼]8n1þ$ÓÚÖOöýÏh?p$±Š“kà~uŠ˜Ö½Ä8¼{žì¡ýh?Œõ3ŠÛȹڇv2~kå܈þV¬k9À™øÛw$û`#ú/a°;Tlí5"1æƒ>hŸ=cµ%l|Zµ,FÕn]ù}~ä¼N¾áa=]7‹Ç49e콺}Ì{·íÙµ;yÚàù÷—®ø'ãP÷“‰Ýð9´r|ckŸ¦ƒ®!¿©âå´yQ‹§/‰/<»;âæé™g<Öw^3Ò×_Zïv§§ûÞ#ï>Ûäæpâ‹„ù.©£Ö~³qcÿµ·½Ýz›Ö[_pÉxt°¨aùˆïV/™»©!¦`ÍM箟®7t¨aø' Ý{4ªÛ"wùöÝèy­§æ‰-¸$bL¤9oÍÅôåëz ùáʽôS¯ONy'Bµ\ØãÖAÿ$fzòíÍCývö뻣htÝ©Äî¾Or¾üjߢnóËo]ÝúF¿_œoîœ]»¥jǪýEGΛå:o-=vÀ{Nà„Þ¿Ú­ZðÒôAˆ_ÎþÛzÜjê”W>:rÆó>£“ü-¬Ù¶{xÁ†Y¿qûqË`ÚªréýæØëuÁ˻ܩ¿{í\tNÿÁ‡–6HuÕ!š[½ï9½3|'ç­›‘z´qÒ†ê¤Õ¡+"WÆÎÝw÷ÊŽàÕûú5­I¸|ú­f½˜÷ûúuyų£Ÿ.tXºæ‹áÝ–øzþ›]CaxͨÆ3¹Sƒïí>¨ä'§çýUJÇnÆô¨‹ù:ÙÿìHöœMÑ‚öÞL·B¥ÿ§AøÞuvZýÌ%VÏâØJ—£QÜÕȜǫzÄ5}YªYsðÒÊ!ûï¹ýÞ%îĤ›Ê”> šw—LÏiô/YW|›yx|þý<ýÑéÛgkö¯íq87ØÔ踩ô¿Þp@F¤Å“³áÔï•þB÷”sÈÉ™®ANŽ]žÃ€JäÏÈÊ‘?”áù¼ (EûíWúÔ)ä×±¯~啞uy-ö;̱ý«°—Øá˜t_£{Ý¿èžE÷)º7Ñýh/ŽEþCö '¶‘"H%½©cIïÚ†>+^ée›‘/{¥—­FûgÈÉEþËòÑ>cŸ1„gº"ÏÀxr¥²‘OÌű’³Ñ àCäÀLœŸXÀtôÂ1HP‹ØÃP‹ÄŽA-ÂGâ‘“oÀñèïˆ@ûPÀhk Æýȉ|Ÿ¾‡ö>#ÓþŸëƒuõ@-r‘ÿV=ê“od-ròMýjvDÞö]ÑcÔ"—³of&ùžsÏ&_z컆›fKmyH™¹1çˆ8czà vYDùš¤$¿ ÔId¨ñwLKÏLLKµƒC#X¬Ö4k´-kêÔXëLâà–•™hMf–¸ÄTba“ÇÄÔø”¬K㔕š`™”˜jI˜ÂÁ»„Fi ñ^tXÐHS2óú@­×@í@/m´——ÖË˫͉ð3GòÌ8ONÌ”,qquúAI-9M³XmT2c¯à=@OlŠÌÄ©–)ðìx9Ö.VëËÆ - ÚÒ²¬ñ–d¦¯ç”´©OHÜ’ìi³Æ{Z-q±ÖvmÉJMÌ`±¦$ùÆÙ2ÉþPK0XJ@÷­Zsx rebar_file_utils.beamuWklÛÖ¾Ô¥$FZTâØNjÚ’ß‘EYrbKyÐödÅëdq³Z™’(›¶D*•ÄXáfvÞ°vÁ–"{t›Û"ØÖ¡«a¬ë­C°!-tk€ {¡M³nhú£@“aû ÛÎ¥h[õP<<÷Üó}çq¯¤ñc'"yK£É‘GL½ˆõB(ÊJF6Òyµ ¤+¦Z(;bÚÈ;ô2m.–çU‹ÐM=ë&>5ÜQ ¹¬lä\ŠQµYG(äÐ\ªž†EW^7вé,¨e³ìÎdÓT´º*†ÞQž£³¥´áGEÎιʦ¡j³ô¼®jŽâi†€hrQñh²©ž¶T§bºQ—S Š©¤É&šx¹ª—¢éŠfn«bôY â4ç ýÌŽš-éœj¤­dêÎfõÒbUwج9ç!ŒªÚ4*Š3/Ê “‘˦(/($MvºÔ2ÑY¥œ•KJº\’³JÙa(nC)@¯+ê¹ TSÕòúöYÅL×¼ûC›HáP¾¢…ÄP½eÜxõ­¿²ÁGÅpL|Èj è›6hÞ˜žSrõ‚Ê¡êgD©§8‡¯£/ÇI˜v#4¬à¸‚…QŒxQá¼Ò(Ì$)Q¢qí¶ÜhŽMH˜‹ÄÓnA€÷}'ñ–9o-ä͇xJÚ0íå.‰¼”BØ-ˆnN’RkJÖ0q?~S3G1Urø<>:ç@°Ÿ»‚ãWlbW€Ø öLæu f‘äç—äfìH+’7øwHJ‰Sâ$.I;I ŽRJÚÂâ•M«Àâ2°¸,v Ô-¯(4Ðï—pð`y©2ay ÂòÀåß¶º#±›;5|P*và$y‘:þqÐaÖ¡|ÕP£˜ ô±>~-ÆrÂDä)Ê’~Äü²´gìœÈ |ÊÓ”‚X¬™Àn’RQ€_8«î› Rª´%qÀßÈœñAê ¹3~H¾™£˜Cì.츌­Fpç‡ÙF`ÝT˺‰÷4õ±;ž=Ð 'Lƒ@1;9ILØRêœUuOv‹+RêJ+[sÙCr±ÂµÀ¶Ý1¶Ù·‡$ö„k˜ÖÚŽ~r·V·v« òn«Í»_{Ì)^à.V ðzÓ„­M»üÉMk#¼ÚWx†Ù€è± Ùž@"Àö4Jž6èéd;)&^ÀÝ+¥nÁ$Þ‰’aJb|‚¥~˜Ã~ɇ§8v„‰œEŒ㧘Eèπň ΀EǺ|¤†úÁTDíúE z öF`ï  Õå}öò>²¼–ohˆ^Ÿð궯Wr…‘y§1öq°k8Æî'‡Qؘb}ì|2 "{'0{ºÔÉ€N¤˜ÕS‘&«í!—xmàC16N>Š1BÓ¦ñù¢˜(–àIu¬ Úþ»1¨º¸ Äâñ‚°¶^²Ýö!ß= 5vÞÖývl¢7‚ì²ý[@vÛú ­6>Ájp¶NövÕèë1Iœîš˜=¶ðïµí{ABvn$f¸&>Ñɳ¤hÄÒo¯‹¶Žìg³m'Ø;krõÙ:c?‰c¼¢‘˜1Û±Ÿƒv<Šªç¢Aìö>ÊñÑ×.Lª&é ÔúÙÙg99ö[‘{â’祣¯RÁާŇ©q×ø*_êþCýÏ+ïÍ$Nþ2wµõö_>ݳúÙ3ýúöçãíñ®çO½úüs=‹ó-ôå¯Lýí©C‘^¿öfü¹–®î~C¹´ <’}qòáïÄÆ¿×ñ|ûî‘—ãÿþ?õ…Ì—ï=ùÃaµè¸ëzïäOþôÍÅë÷nß}⧯‡0³tÿ»á þcnŸvá¥búšºöJãØÍÄ¿¾õÚÈ‘ŽïÿÃqðý·Þþc@ºØ6³ÛQ×ì§ÞMƾx#<õxûͱ_½ófå~b¥ëÏ]úkûç¥Sz÷×ûÿûþýW?wíw¿‰ðÆjëïóÿ9>ñ¸1yøÂÒ[Ïì÷Þ‹ÖÅOܺøî·?4þ‰&õ,©kήwÔ®[¢¦†C[ê][㾚™Úv2cí¶Næ°m}žFLÓ óõ¥±Ì9rŸ.kÖ‹Æ¡2»üâÕ›7n\m¼xnðÑùù± -kNËŸ&þn½dªºV&W±Ö¯Øt¹R,ÊÆ"qpé~H. Zɨ±Pêr«Z¶PÉ)9´­¢å”¼ª)¹9 k¹òŒžœ˜üTú¡‰“ hû€"b:#‘Ⱥó™±éôÄÔø±T7«š‚’É Dcƒó§ÓŠQR Èëß×#6ÚT‹Êœ+çmÙ!{ä:™’Y‹`Y¯Yeõ‡çô¢âÊB¸ldÃÖíM­æïC?ü)˜‡ŒG2e“ ûÿPK0XJ@ÑQò6Glrebar_lfe_compiler.beam]TleþîÇÚ®íØ­s(q·5’ÑõÚKÄo­]Ýܯ8†Šè­í}momïš»+Û‚#à˜¹À$b†.?@`1Û&D·™Ñ¨`c€!1$FÜŒ¨HŒßu· 6yîÞ÷yŸïýž{{÷5´=ç Oðë[ê59 XÀ(u((VøT ñQ9SH1A¡NÆDEÕð5…Tû’4*K11n‰#O‰ªæ\b#aõaJÉJ6#Ñ[[–ÛÓQY@y= 1š°K²Ä£^ÜA”âyHQd%ßð"Ç) RRa\ÒŠÜcÁ /g4Õ¤ Œ¬h´îˆ”“¶´,dñ&¢“ uKÿʋ܆ÏËJnÎ8€ àÛ} ,ýöa`ä é¨` vË@Ò}NH›9):`TÀ!ÖC\¤q5 ‹)K†a Žt¼ÁÐÎrx 4ù`ñ·ü+eÑŸ^¸î¾rØ5Ó±ñèþÉÚé›_µ—™Žñ«:Çf6Ö V|hû`ÏÉ—ƒÒ±‘Ñ…ŠÛÝ u.ŽõûiÏ^e×ÎOÅ›ƒÛÆ'}'ïù&.:R·h–£Ëó$ÿ7O‹Óõš¦èÿÑî”>õ)j‡*å‰[_{ï2[Óé«ÙKŸ˜ïî4J1\3çô´®7ãOT”%U'L(È}Ö¼šM§ÃJŸ.0ÉYM•$ QD”t†“À,JÑTV@ÈÏJЉ® °ú;›Ÿæ·4¶“ ÐÇy}œÏËñ^/çõz—E–­¾±µ¡- lqQcQ$â«®Yßó´)*6•y5UµU5:Gkb%Lü‚_ “akØ&Â9ƒªœU¢( 8OBN#6Ž’U‰zr‡ÓÃè?Gf>žºA}DÕôwóPK0XJ@²†œYTrebar_log.beamMTÍoEŸÙñÇúcšµ×©Ó$m6^§Iq>Ö!A¢UÐ8i‚Ò$jÚ {í];¯wÍzq±Ì‘ Dê !!!U½ q©øÄ¥‡^rG9CÅ{«d¥Ÿæ÷Þ¼÷{oÆãwoïA¡ÈÎúfé~Éw[á„ó̪î•m·²Ë›^Õí˜É¡»æ:u«o˜~¹a»UÝ=Ñ="ënØô<× fµÛˆu À6M;BC($ôvÛ¶jºo¹N”G™Î±à6c· ÑÆÐë:†Y·Ó ¼ßëšáºnẅéÙºÓ Ár#u×ké>…P½k‰cݶŒ!'-Ë!-ý$1è.Øô8äñΡ۵ ~Þ8oµíAÑ“DË5º¶Yæçá ]²á’6\ÃDHh•ÐðÛ,’XÒ9„•$B!DÇ‘Ù2‰*($ѱ….¹CºÙ^juz?*šXcU–ž"̘7$û¬?$v:$íî é$üuI왕ýN¢šTø‘œ§‘Œ¿ûàçB:.!üÊòØW”÷ÿ"·Ïˆ²N¼N$µp&Ÿ3•ðŒ? g$ž†RÜx þtYâ”Ô4FòLÎ U˜âB4Cn.¤h´ò2È…zC£2ŒÊYÏÐT|”¦±˜by’ÊégXFNe¢ŠÆB²¨0(’fç$­ÉX”¡²˜îÅQ¨?ްx5w†Å,˜Ç®(#™áE†`™ä÷™!\oŸÓ•Š‚ÅkpòÇ& <易¬ÈÍë`*ª¼Q5ÛóèTŸ*U:}JsXœš§ª|ºÆ©2OsrªXœÖ€Þ‘i.Ë<ªžrWNÈUåk”§¡Ñæ¹r>Û«Ò›íÓ¹Sz ‹7Ùâ³lKâëÛRøz‹mi|}่–&»R‹óÜŠ üxàSzøÞCþȶ[m¾¶1ÄßBa€ €+ðTà¿ È| pí’ò¿~‰«|‰ ›'ƒºŸ¢€\°¿pþãçyrЋté?oŃÜXPÂŽåsýU;ù¶V©TôJåµóG½2ò$yþâÁ~ï³µÿ^ýûͯÏJ¥7¥Çíg_ý|ðÓoOôÁ .²ãÖx> îc:¨Áç™Ô¹˜ êM6 zžâÇJ¾ïÁ:÷¥Í=‡‚ÈqÇŽ„Š/_ìª3—ïFúŸö÷¾ÿøèhcÛ©Ãæ›A|ˆÇGÝ6Ÿl§N§ÛjéÞç< âv}Ãòš(dV-‡{°ÕDQË©Ù]Ã4ÐÅØ;$°g(¾þh{çnùáöýÍ&YÖŠËÚrQ+‹Z±X|$>Þ8(oïÞÛk¢DÃò³Z]~weõhÐŒð4ÕDá•Å÷W¸/ä[-ó0R…ô•.èq=¡cì¸]¯f6ÑìÒ¡Û2— q³¹ÔñjKƒù}ÁøÈ\„Y|„P©ÚñùeþPK0XJ@Ë"íª rebar_neotoma_compiler.beamuW l÷¿óÿb_9ûL’.qàäüRÖ Ž ã«¢M­f.öÙqìÜYwg L°¬”Öªº–!Ø`¢ôµQÒ6öÁ×Övˆ5¥šÖ©bS§MS‘ÖvUéÚ½ÿùL=P-=ûÝû¿ßû½w§óðúÑEy>ŇÖ™Ú$E9^§(*Ѥ+c²žT Œr2¥MsEwÙ ›ÖRI]ÓL—V2“éœîžÔÒ¥‚’T¶›NE/ÈjÖÑ×'T’ŒÉ†r;ÒKª§šV+š†§â”ÒÔL.‹²ŠékNS닺V,ä Ó¨cr«\()®´’‘KÓmh%=eUk°¨.;/“ÒÒJݶñ\jÜ£j*¸Ašœš­St]Óë+ Zԙ㺶1õ’R—‘ †â2ò¹bQI»ÓZ4›/UžTXÒ Q<XÒÔ’2ÔsVzwÅ’Ég‡–çTEIÕ.b-䯏‚ Ëä”tÕ’Õ‡u%£èŠšRÒÉ¢’5CUÙÖ §ÓI¥ L*ªÙV UÝÅI4G`È¡+.])ä”┡5]ŸÑµIË™5Jc¦.§LÆÈíPêJ*ðÜ`O.§f´FÂtÍuGðÎì‘`!ÕýÍð@(ºsFRW²¥‚¬©g%3W0ƸÓ0u˜ÓÔòŠj4ÿVH)©Lßã VmaÛ¶¶€¢˜waŸyªò)ƒ,"×4ïðu‰´8óE>Ž‘€Ã ÝŒ¨`äÇÝŽ!K}á€u” —HaÄd)ܽ'øf6b£v8!8ŠØ)Ó’Ã÷ Ocìàg„u’Hopø®Šô(b ¿3)àG¬E‡ÏÍóô”TBƒ¨Ô<;>àö>?z†Þ‹è#P~Nb|ŸoŸDO{$ £nì"ƒ¿‹Ç}Eî&œÀ/Kv7#—´'6 –ßBÑ×±_À ô…‰k’8/”ã¼ÍØÝö¡»ãé›·Ïë$Nh–ÇîÙÈ' 4ë]hÖ•;À,ÌÀP:ŠÈ&0VC`‚€ —X®* Zy ÐÅOñGøa1pw%P<à ‹‘„;ðÇ#^¿·Û¢º’goçGî~óqä@ñ(—Ø"”ñ]=²3ä\ÙüxÂ!Ø9bB Ìãš]WZkdYÞ‡ç0ï²È3"7«šOò4ÛYûDšu{Š.êqðÄi^äã~G¤2Õ2Ïãa¸­’ ÌS.ñ:Ëßp­&àÚ<Øç·Àu±Šn/PÉX W„§"8±Wpa˜„UËë`}.žõ’XF€á*¿öi/Ãs]àá*]"+¨<ëïãÚ íY<¶ØüM{Çý•žEðžI8+C6  ú €—ðìCëx¶‰fç 0"’š`Ùfšíã »–p=È#òC1•Â-7—¬Ù\X³v.ànãºiÖ*0¡@·ÅO@„|< ì‰r°ëì\²wó ûrðí]ÂÍGœˆÅ!dm¤×¶ÏY`Û‚íç0Ñûkì5ºddžA" Œ'jÛÚÏ𪾸&ö+5ö%58—Ùöª^ÅyOM__­ÁŒm}$fû¯YY“s˜èñí„s«_ÂÕR;N´uÊž…£*Ã%u“Ý ¹NØqQÛ—¢w÷^âöyØÎG#çê×ÖäL2ßáhÝöÃOß·|ýE‰/?}tUyÏ¿6uvv.’O\bÊfÞW>üñ.Ûjn}ägé7æümßÕðEîÚÙÿb[2V>Äÿåø;åÞßmØ|ãð©È“ù…-o^|ÿØ=£cßÿÁAm4°sUß‹ûË×®nÿô½Ï…Lû·~»ÔxëÕKá̾ýãk^ΟëZÀÎ8ýáPëÅ_6œØ·³wÛý¯p.¿ñw¿¼z_öÚ³·Nýf$s€v~@?üÜñ¬Ðº¿C^{âáØc§Þ8x~ó£n)ûnŒ…¾6¯ãù+#ÙCëw=®¿túÓÏðüô©WòìÞ'N×µ<ý½ç‚½k??ø“3??{ùDR}då“ûïyóØ’]W÷<&g®ø¸}zÇvÜšÿÇ×_|àÕ_ßxð¿?ÊÇZZO­~â»ýÕè¥CÏnoœ:_·ûC_¿xáü;¯M|¶ëò[g‡Þ;Ö|hqÇÆ9ûó>{wõá÷÷o̾}ôŸ»?ú ~iö-Eæs„»c>µ3¹×Öû@–Û:ÙA{^] !;¶Íö#>äžškÛ›ìÝ@öýã³uR—·ó°öuuçܶ2MÔÜMîvzÜ‘¦ÐVCµ.TžúäçÄwB¯ÿyÕ O…#ƒ›˜˜X1¢fà¬Áògˆ¿«òšmƒ3MqÖ»qÒ(MNÊúCļÏ›}žb”±œJ,t.O¹rjªPJ+iª¾¤ÂëxNUÒãÎÒiÊ»dÍÊ䦑µñ<Õ–Ba)’’¡ …ªNìæ“#ë†×穆lΕ±±p$ºh´UÑ •§ê¢ý‹û£ÄƘ¹IeÜ9³?ÉÙ-7È´ÌY+ÿòTt`\›T¸’0ôÔ€õù…v×ߘ~ø‹2A &¹çþPK0XJ@†LüU@” rebar_otp_app.beam…WlÜv·ïëÄÎåœ~sv“æG·—¶i/—ó%—’´ q.·lmZõˆiãâ»s'>û°}íÚ¡QRVeê@eDµAc…"ím ­hV FÑ€²v¡´ˆ÷õ9ɱ éÅÏï}Þçû¾Ÿ÷½Ë7£{ö%(*ôàpjh÷k(*p–¢(…·µ¬jg,·˜Q‹E6gŠº¡­*G!’)¹ºáuÇ{qìãÚ%­jR57,5ïÅ'¡¦J³mË®-WzUUjֲ݀5#V =¯ºš.Xù’¡9¡22g™“ú¡šCš›1¬œj°~º¦h[ECw\ÇË,›34Õ¬ó;ɸácÈâÕyÍÐ\­Z3-ÍtƒE[ƒòœæ8Õšm¨æ¡@4Ê’²ÃމÀª8­ÐöÚ$ß‚`„@¼8ãÀÙ‚É€$0×ôÞ²\=ôÞÂK†£ ¶@¥D'ƒ`œD)³Þ>ÒEÄaN hn=0öã†(‚<%á"›>.Ü‚”?€‚‡‰ŒI§"t'z/¢ßËê$ߎø4×G$ ¹¬br´€üt9$¡×dª"ùz±\¿ ùnP$n¡8'ÌÉ·ng3l§ž!ø[—^ äPÞé5Þéðܪ„Ñ8æšh.J" r'Ù%®™æb€`WG!Œ‡Àxl×R"0„N ˆ[>2ñ$#3’¡xŠ}|7|ž%¯:%Àg"}±|”W•ÝI^&=@ A²ïýÉJ‚Þ$߃Díwíä t¬P„'MüV0ƀѾÏú~ X,@¾kÁêü<ù®÷ãä]ðñ"Øjß_ÖTiöãd½µþzm`’!µë}XÄÇ¿Ý÷7‚mòý(X§ÏMjcxÙç!=$*úéöý$Xo…¿ÍÇ“Þ>T±÷þŠž·Wðìü€ðñ&~ꢭÇKö¸ÃÇvú>ùÙ öëBþÓ³]ºKæ}Ò×ï9{÷é;FâÉS—g¿zjöØÅçîœs­‹Å·þºù‹7ÿtWË‹»‡jøfçû¯?óÀ±˜ïßóðß×öWÃgÏ>ÿç§_>¹zcúÇc©Ÿß;ýÖpÿø–w×/D'¾>Ø)/´>Vú̧&Ú˜~÷ß?½>û»ŸÝ·o±fñòãÑ+¯Ü~²ïqóGçŸøÎÖO†þp£é¼ú­WkG ÅW5gƒ‹üâÍËßýÆåoOi?ùã•ÅËoŒnú[çç.<{ÎlJݽ§žÿýôS'ÞÎÞñÀÚºçª6V~F~äÙ7žäJã1>ýâ+kšž9%ûp÷è9>øƒß¬;‡þ™yðó5Gþ¢?Ôqç™Ûðë[wþòÇv~åû×½Ôúµ§N¼yxÿÇN•o{¯fóüý»ž¾öé3m»~/²ê 콯ÛÏÇÿõÛ/令]VŽè^ôg¡TÌwÐ÷ÉYðý.°>`=g/îûm>néll®˜{£¹®M8N$;ÈSä^齘˜ºv¥ë¾wŽ/ ¾pl×û/_zç½éé‘1srÏ:²?36>ºg†ª=¤»’–Ív÷${§½žk¶MÍPUÉ®m]Ic\½ MUgá â7j@ ªµ*­ò^ƒŽU²sÚ OY-k3q¸™Ç½‹íŠ·ôïE\Ƨ)j(ë¸dÿPK0XJ@3óÜ*rebar_port_compiler.beam„X{xÕ•×èÊÖ•ì댟²s“3Õ-»ááÒé@z\&®Ø`¹™Ë7`òd¾Ò´­ÆŒÝƨMÜhZM1oÉI¹6X,7¤‹'òM èvCå¸Ç>ܲ«Ír­ÊµZ‹öýåZ'ü;o1xÍß<lØíFÓîrTɵŽÔmVlUÛ.6Û) *ùf+7]+–'ËvQÙvv+åê”Ç6?ÜQ´'fJþ;x;kzòõzåE$?Si5År¡šlÔ¦¥ƒ;¦íFɶjrÕ#WRéÜÁ|#Xk =€ 5×tèK{åüDÅî°Z££ÙBª¨î>ö Q­VïÈOÀßþ†Í3Õ˜ ÇÎ4 Vkrœ²ÐZID]ZäÊUð¨Ì¹†Lã?ToÔê23C”^«Wò[ p6i’q†žÍ.7ð4çv£ÕÌ!PB­hËHÐ*HnGhºšGš-{:GÇ¡‰Š£ÓYk¥¿Öì„DÌúšÈùÂìÌâ[6³ÛËÎØCìf÷ÏÜúì^ÔݣλZùIYÐí™Dpn¡"lš„Ù¤¿˜ "í ÚÑ:ШêrƒNVËÕBe¦h3:‡Øfù¨-Ïe¼h§]-7Q®HV´y¨Œ ¨X©äj R{RЩœftºÄ3p¹{iáY/Iœ!eC2SœHü_;Fbqb°Rˆß`lÀF4áDqƒ!œ t0;šH¯– #£QÑ*v_b6—€3‡«Íƒ“ ɳÀ6ž6p˜‘X‘8óôl0=â'æâ gÍž«ÎQ,OÌ/\ó´_–ø@AœÕdeâ…uãe‰”äYÚå‰ùåž{µ„l$.3' faƒù8]$ákc"€vÓì–9ß„m8¼gâ |€ÊH„Q‚gòÌ ÁfP|¾ELUŸó;ŽqcHQý½«uEï±tK‹[,fmÔ¬¬/i 1+f-Ÿe΂lþúgÍêKæ&f=Èz-M1,•°Û‰™?i™šåÏXQ°‹FŪôÛ:Âô!æÓ†˜³4lh uÕŠkDc²HˆF93Pèg²û²Ã#§k{ vC _qV™b˜™âbœ:@þrbAiäqDòâ›;,¾&IR5õk Rørâ%pÏ•¨õ—¦Ä(ë¶ TK“j:]pÚâˆê¹i±Æ^î5örD5êDUjޏ^¦ð½Ø ¸Àø2Y7éÚÑ £¦¸Ä ßå$ù H¾ ð1ÙHdÑùyV‡“k²—€­³Œj²ËbIœ/Lâ±Hã_ Ûöϵô•¨€÷Æb‚dˆk¨X_ƒb=*® _!®VøU³%áj”pgv ©ó!°Ù6×ÒµbÂû5êë,Z/Õ©Ïs’±tÂ9:HÊgBûAvþ¯K‰¼{FöǶÇÄþ>Ë×ëÁ¹~î´˜C1ÝÛ'H¿ è·VÜ€†’Sø ê¨ê¼™ÄÚÍø:¸)gyWã¨íà™Ï1BÏdÇFbš†zæyÂó¦ØOÎÞ‹j¯ð 2°M¯‡¿Š=𥯣²§\9_WG*c–/aÚH@c(ýð… ’H&q{ÉÈí§q­z ¶&a÷C”ȈŒØ"Êá’¸QáeHFƒ¯(üFgVWø€g%%¦ÜÚ:¥…âXÉÚŠU2”ÁÊ-’ST$§d¥]#ª Ÿ6ÅJ _JT~!Ë—a½œÖ5p/ƒ{=%j.÷šä^s¹×$÷šË½FÜk’ûMàÞPøM¦¨÷sˆ[ø.÷´n‚ûàÞBŠQÿ3Ä!²ùl.‰Ø}Pá3@^éäÓALugzˆ<äS ?âô5.ü0\xà ÀN‰¹:•Ýæ¨ÛmŽR·9Ú7²ÅGBMqs¨(>ªð-“å« ›t»ÙY®†ûiùQgs—3ÅQæbƒ¼iÈû¸¬—èUÙ tžè·°,«uß.=¼Š›A–¯Ù¥³løâ¬†dX²[dŸ¾Ln‚ò·õh² *w§÷Ÿ(Âêsq/9­C6eùy”Ok‰#§0Óp‘„õýÔ-ÂM—0Š´Ú@ÅÛÇ #oà|]Á³ü|æ,û³» ˜ Jd£r/ìqw{½|nOC>äs£|&åÓ”ÏMò¹Y>·ÈgJj™Æ}Æ€™·Ã̃0úŽ´¸µïNª}*eò ¿s¶ß¸÷O*Nî}‘ë*œsÜß»5õ®Õ@8áØ7Ð/î†[¶RkRÅ`~7¦Ò©÷@ÚaîM‹{ íܹŒö+ê\žÜ jJÜç¦ÊýH{Qw4á;èê:ÿžF7œûLq?ÃöNþYÐî'ÍÈŸ€fG`ʉnàN:>ê¼ ÅQb7ö‹Xø¨lÔ¶QêöØ-D“‚ï'©~ž’ï)< ;×›÷Ð|®·Ìq}”¸64 &EèÃRîÊp…‰·XJ³ ™“TÔ¤-ܦOï(üa"Ñ6Há¸owŒRÉïØö¨|~ºCÌ>eõRµÜ¤ðOZþ 1í¥«Âf…ÿ-€·ø™´x !zŒ*…HEˆô-·Ç0> Ô[úwiq¨'™P‚÷)…Ÿ¤î”ÇrPžH‰Ïáž®¢ëÒ«á½Þ÷Ä'ÈÀöõøs¦xœ?ÂÛAødJ|A&BZ<…§§èÅÉ—¼@<•ôw«†ó^Ozy<02øI…ÁŸ'n_·;Àí锸R[ ølZèµÐ-ðmÊ«ÔÓ^†_2ʼn͗Áæ.ô‚gRâ+ N°¡7Ù=ª¼ÀhÎG 4t¼Õ<ã¥ÿŠ)¾LôÏ‚þn¤Ãߧųl;ÏRï<¥‹¯*ü2Þ‹ÃÓx:jeèKÀ™œõ=8‘*Õ®hû¥†²ø«Ý:'å)JžPÝ£~ð]è Î=ðÊ? rÅ0Ý7F´½¸o(üŸ°{/Œýç”xN6ü„x.¶-&ž“Ýäk¡KÄ7þ5l&“™1lf¶eÜͯ£Õ|Cá_ïÏeù®nô–]â$;ù& É,ß=yã_ û>hö¯‚jl(Ç’#¡«’x\Aá¤FW‹¬/†È¥Ûµå[ ¹4ϧċ2cRâmPKfLñnÎò>I¡}Þšœ\y^á/šâ[¤ŸO Hߦ3‹cÎ{(¯4ÄKÔ_’oÅßÁeæ» ÿ|,Øwé²¥k>Ç ^¢žø=°;µ¾Ÿ?h§Þ¼DzÍójôS|ôø!áË)ñ#‡lgH®^â—½Ä?2ʼnø?âO‹W(Ó^¡Lû±.~¢ðÏÒŸ¸‡ôU ?„H¿–?uÒ:ê~xÍ­&§ Édû©)^%ª×Aõ0Dü,-^'¯“ˆ7tñs…¿Ñ®Î×9ÜÔ" ÿùüOvð`ò˜¼™¿d¹ +"¬i#¡„4ïM¯y¿4Å/Hö¯@ö(4~+%~ýÿÄ·¼ô¿6ůˆþmÐbÿ#-Þ&Ýß&Ý£‹wþê@y‡Ü„ÿßõS@}7%~ç©`wxCð®WÆïLñ["|„ŸFügZ¼‡êøze¸ŸaôÂ¥ÅKô1‰¾ññ¤Óg·zßV·Â¸­j#QÍéÛ0¶;_N`XÂïS2¾/“ñ÷HÆ?(ü÷ôu@~ïäiÇ-ŸóÍ“>­ÒÑúƒü°*ZôƓՎnÈoƒ1êlqz›t>‚Íû ï0èh<þ>åôÁ´ÏÀ'ÿíÜþˆåcXþ)-þHÞü#yóϺø‹ÂÿŒ› 9šïèeJ=þ"¡¾3 Ý͘o¬ÕØG˜/š®ãßÿ'Lwbt`tb0Â]~ уÁ0¸ß§ Þ‹¡a(}‹]øŒ¥îœàË=´+\8ñ_íÇ]8ép®Ës†îÎû1.ðÌžy[Í7xà† ÀØèáoºs’»É#+íÎI·­=·{ðwxp.táCôùÞ…Ó|ص‹æ#.<‹±Û£ÃE.Á÷¸s‚_êâìŸÌãŸË=ü÷xàc=÷yôi˺ãϹñ½#çs~D›wù/ø_ÿÿ]V 8”iþfœY+á§ÈaвŽ#Y¤ƒ ý k3f03Ì0fGë°DŒCI»mH •Æ©)Ú«ƒ-Z«6»åÓ¿ÓÁé/$ÿûêíú]¾ëº=÷wÏý>ïó½—ëy è8ûôà࢑G€‡<ó‡kã×HP <‡¾Gy`δUz¼£µPÏ^±¯,ÒO8!òS+¸ â?Bî’íân”#u…7Õ[  ŽtyUT‹,ŠËpå³AœàÊÈ/Á>?ã6lð· Õ8òyôÎ`XË äŽ~ÇäˆVƒPŒô^ée§´ „£Hÿ ÕÉ9Öó+@ëo¢ú0YX‹ù¯A+Ôñ𕯠ä¡:šÐ·á0ͱ æ"ÿ…å< G˜ Aù/¢óÇË–9ì1ùP‚~©£á1 ¤#½à‹e½¨ƒŠÞ¡þ1™u¹$œ¡´ H]P~ÜÏ›Óo³Æ¯ÜúáãVFŸè©UÈ€,ÿ’öÝúaÂ]+Qf͹²oŸ(ë´ÌfàÒJÆý› UåIþÏN,Yìß`ÜÓH‹Ú{ðåt§¸@ïÞÆ7ê.sÁÞÅ£ûë§ST$r!œŽðüø4ÿݦYíÒ§°¸™´½<³?ÆE¤Eþ…˜¤‡—“S£Œ CbÅVÞí$×úš}çû´RùѦ>)î±;cÒSÍdNÚÅa&é­ ï•SÅf]{xýw)ã릮'HTóRê ²·©~Ä%ÍQ½_—<ÿ.im¹{¨^AëÂù†ŒïpÓ“VJ—:uJ3×F ³…Y;]\¤®Þ,^¼1ÑòË›¼8íÛ¶Äè˜šÓØÍ¿<”^_Gnýˆ‰+}låkŠŸz(ˆìJ³F»6ßö„2èß0' ®aÙôþöÀv_Ú›çñ2Š*´º+¼Mþ®½]±±ÁQïƒ@6ÚÂ^Y·È-`ZPÐ¥R}1½I¡oþÀ§³÷H¶Kþß’õœGƒ¯ 8cæZïî$\l×Êû±(Gí5ÞK¼KZpx¸>lá·ÇØØ£/åÙJhz¿–\¤&(‹—¯ÞÙt\ˆköT!sǾˆeÎÙØÅU¤1¶‹HçXöÝÆ×Vá۶;½a¸e¦§{2R=_ÞcN?»ªô£·ÌUñîoy*ž9n=$#¤‡ÔH³¿©LaÆiW¨Tê|ßm!ô£tF‘vÙéÒŠý%9­Nj#nÚ¤Ú½Nš‡©ª¦ë­SÆ3nÓ~×?ýq“9Mç¾ÝÞ®x"ß6'î}P¦ÝLélà«Û-Wq?C$v;ò}É·lê†n¼™Â÷\ëTßMô ýt¢7ÊLá~‚¹üÕ•Ã ç(La·d¼»ëÉþdYÇÙ Qɼc~I[x@îÛà>«w^"‡l‘ílå­ Ã&m“Ú¿=Ü_¹zü:•˜»µ¹§ç{©q­_i£uój“yFõ÷ÜPÕ6±€_ªÈ4)LÀgS=ÍŽôQ F›;WTņ¦Û‚üã ¼+gó{}¿©ª=%ºpY5k³ÊȱÜÍ×—Áª—>ø{‡n!¸y^žÞ s”–ã6Ú‘Y³ô6ìEWΔRø¦‰3ªE¢ßôRíå¼vN¼7½‘?ý²¹wÒËôúÃ¥5¥±)òö¢Z{»íE:ÏÌâuSñCq½ýéI7Y¯¦Îl:Þp«³ÑùÊFæÚ ›óiõê×þíg:ú`¿·ÆÙq¿óÍ[hEžÎýEwª#žÍ( :œ~¨ñ´ r4¤mó59-{ó<úî×ii j–ô%ëF•åT–tÏüwž¹®$¹þŸ'$&#s‡üný<X×wÆŽä+èY 3çuC Fõ »q^…»^ ŸïŒi Ä0'ôüh';Võà•ýfe.EúЪ\‚úb?Àq¤?]Õ!OϪ~\„ø}€BÄ;Wõæ|¤·¯êÍ+ûñʼ²ïæ O@òÔd"ï?³ª7¯ìÇ)('üŽDÄa½ È“‡4)´gÒáž°·chŸ(¤Ã;:qx¿³‡¹™ˆÃÙ€8œ"‡ëÂÐwA-å‡Z0âp†BÑÚÈ}ü°Owåôë÷ !Ýqè‡s‚+Ê ÿgߎ}š  ‡ˆÞ¡n`‹¸ € òl0Ç>ÝÅð>ÿ ytŒ‘GÀé‘® ‡t8[l@:œ´ÿ­¢#Ç…{f,Ÿvž†IÅŲ—_Øk°ƒ…i_á:=ú_Ø¿+æ1™NîlpŽ8ùe¿4ôËq¢y ; ²4L™Îår¸äX~T…› ²>Æà²0i:•Á† ŽÁÂäìÐH>NÃøl=ŒÁ¦Ó"¤Ào4¦¸Ç×äLöq÷taa*V–D+K+¢%™H´$‰ŸMò~NÈî^®ûX˜R8ƒ§O§R­¶Zoc.×GçÆ‚¢X˜Œµ¹¹5Ô¤yŒ(z„,˜äþ¢à)Š% Žòår±>7”Έœ(º(œÎ²ˆå†ZpéT ÷ÿŒÍáòÈ¡œ¨hF$kNçF2©±Ë3êÿPK0XJ@ƒe–›ð rebar_protobuffs_compiler.beammV}lgÏï9¾Ø¾äµÏùNÚkìõ˱}μ‘Â.Î\“®kK›v°i¸gûu|‰}çÝÓnC(ZW˜ˆºMc©üµ1þéTUEQ„Ī}hYµiˆNã£ðJ'Ô?&ž×¾°ôøžû=¿çû=ûö<œF¨ûz67óÐŒcÖâ>D¥†,ZÔ¬BÃ2³Ø¬TìBɬ7ôµ|®h3šŽ^³ýÝ(*€Ús‰w¬&õV´šM½Ô²L«»M­™ ¤‹Z5ÍXð:UË<á-Õ¨fxâñ¾ŽTº ‰©M 'ü¿ð%³L½'ªz©Š§SÓAÃ4 ô¤n;º±Ð]¤Z½U‡À¾ ­N…¢f·•ªUk™‚•Ç wxü¢©@6¬¢AiùN2ƒjzQ¬i¶S¨›e½¢Ó2÷¹ k/P­TõèfWÅ´êšÓm—4£ÆO »iÑBY·H»{†¶§å©/Ê´F¶;Ï,]m ‹&´€LM ëFÅì] ­Ì÷R¢5²Ôd¢VŠ}%J'҉͘˜’èK¸5nBgaxáÛ°c‚ÚŸgAà  ^ŽxÂã2'÷¤æ‘¤æ öÉ(sVã0‘8EÅ<.*Óµ˜³ŽrªÊãg ≘òqq‡Ô¼,©ž(€êÓØ§5¯`Ȉ;¾s Oø™[Ùœ…%ℊ%¦JìfWû&Äûd%óâFg ÅVÂó„ÿ¸óA„T? jÀ{û#8Œ$nÍö÷î­ ‚Ī䓫ùC’ +ˆ»¦AÂÝè4o›èÜ?D8!´Ù²•ä°GÊå´Ñn¸#À•6êä®lp#À•9¡/HdhS• Ü•Î>Òð‘3wZ=à=ÇãV»B?xËi`JÁ3XŠîû¥û@” ªd%„³™ÍJ2¯ÎJªQqLfxYìSÄ1Ø‘8K-q˜a¹˜F~F~^A浸8„«ùsR(¦æ€¿å#×ââ(’Á¡ˆO¾Ñxp]ÙLYÙXQ›2Íò µ›Ã¹ŽªùóRˆE ú“à#0a5ƒÙiQ9a$#ö³õB·£_Àœ0‡DØ}·N‰ã8(“Œ¡9Ž@öˆ2¾OŒb9‹‘”Å$£ÒÓⶨ7Q•\Ró,õ¤n§·q‚ <|˜¶AWìAãq‹›:Ê²Æ kvv—ƈâ„í :v°ý( aNØ `À]Sân$¬8vb¥MÇ—È$·±ÅÝq'KÇ$8NL‰‰ÇP§ãD§c"#Æ™cSà˜šTHˆo$Æ“uv¨b˜'·X”D‰°G‘'{)ËóùHN‚p „Q2bK¡#Ž5Ïü¹zƒ]¯ƒH `A<ˆ¤ÄïbxÖçê=.'îÀ%ïèЇ]ÎÎô1-¾[]þ6qWg¿OÑßag¾1¿ d»‹ïÙÕsâ¿tOîd«ßŒÛgܵïpuäÆÝx‚{mÉ~Ýa¾¿—èɳӫ—öñ3䙑K¿[—`]§ú½3Ÿ¿;¯|Âõ”^¾:vö{CO.œz0ù£×ÿØsåö_ýkrüòöúGßxõöîøÖžÏg¿œÝ³õâå}óï¸0XùËŸ»t÷×Wgß8;¿·û;]»÷‘Þýý§?ûÅ;W¾ÿ…ÌÀú+ßîìãŸ~ézßj
¾tnýáÉ‹ÏUPaå¥ÓOÝZëklÿÕéûsú½ƒÇV®®]yjôù›É¯ÞüÚÄÁ«äOËÃ_»Ö}ãFaäÖ¾cSËÂͼ9ò·#ïÿdöŸŸ|¼óñÕÚåû¹úiªÿ‹‡ŽBƒûÍÒ¼ûŸÀæ–rgÄ®IWg³L¸ú.w~œ»CÙÕÙžGÝÙõŒ¸8;#C®ÎÎÏ «÷º<ί»ÀŒãXl·§jÌZõ”^¶ÖAÐ ßÝ‚.\þõ‰'˜K¼öüŸgçŒ ØzZ|žñ}fÃÑMÃf@W‰­7’‚ݬ×5ë Fè2›üM/!žuƒ!œ¾„|ºQª5Ë´Œº›F™Â -W1ØÊeäÏÛÿ@a~î¡ÜêTÒ“ÊdZ)¤ÓJ:Þ Çfæì=¸„ º#ÓbqòîÌ=‹­š–©eCQKÈ›IÞ›Ì0Œwô:­vò}¨y4¿Ð8­§U m6­]BŸIUÍ:MAát)e[¥TëÍâ?Úÿ{]KÂÛÖ"B3EÛaý7PK0XJ@&0é ü rebar_rel_utils.beameWl׿ó;LJ“ />“@ÊÁH0IαóÃ’‹c”føƒn5ûœ\|æ|æÇÆ&V´*ÝJPY§ ©,õŸMJéè˜J·.k褭U”­k·±ª“VÔMV2±­Òö}çâv–¾~ß÷}ß÷ù~¾ß÷ÞÝ»¾ÇöF¸Kô>Úk›ã ãºÈ0LÏJKÒ¬”¥©¢5 ÞlÁéd²VeiÈ1{Ft;•>‘ᇳ†žÓÆunÔÌæ<¤gd‡J“FІfq¶UÔÝÚQÐW“9€e›¦AZ]+è©lnØD…S†yËÌÙ‚]¨0Ls¬˜çž'mæ EÃv™cnmÈ´l?Åù†‡vª–µ|¾P³Ô!8©¼f­Ð-C˸þDÖȤ5+ã²t˜œ7´´^=”ÍiÖ©”m¦5dzÞÒgÍbáA4ƒ¿h­*Õ¨gG¼dÞˆaiF¥ajjö@ I©2 )§ìbÞÐÝNž1ýÔp6—©&c¶f‘ÜWsìzÆ»lôhC‚³ªÌ7¯YzÎu „6dt\· ºË6J1Mg”_R* ¶•͸õcEÍàNhVnE)ÃA \ÚÌè¸6 ÓUñ@ªã¥Z?™×r™ 5s^ Nëç£#¤ätÔs<]H/ä*ÇÍLÑ(­ÕJ¨¬_ßüyÄÖ¶f#Ýð„ÒlVšaSÆ ÃT\3¥ßH?ˆŸÅ.߆•ªÆÃ0nœ`X,˜UWb 'P’AŒUÄy°¤Ñ6T¬S/œÒÙ¬0}J^Hr>,²GÈ_~7bϸ|×0;Ùuõ"QŽ\£WE)&2rLÄ¡ÀUy¦ŠQÕ¨Î#¤DfQt©1Ĉ1„å’BYq+*–“!#²—;¿…ª(5rE¯#iiFàºèõ©2r㋘Æ“à\¢šÄˆ—0ûÆ.Äι|^?f?\FXDÑÅ2„E@èZ”{åP<²Š.†ÔXˆŒ…p:°8è]YLGÓR,Íbi|6¼ÇÊ$aWHž%9/|1(ID‰åkª‰“„ÕnüÃò>°Ö¨¸LDð£(È2ÁO¸þÁ‚á%:J†OXðÇU—FnIˆ ÿÿ¬"¡€@í‚ êÀ\æÕU’¤Šœš”Dù=Ò|Ú…IÁŸŠÄ'¢ ˆ=8ß%¬qV2,¬‘Y¢ê‡µ;~ªKV94~Ê™’’=xRE²Î!Uæ¾JðTc ¸Ö…è<´†­§N‰ªw ^õhŠä—¨&§}è A0ÞÇòmP;%(ÜT@ Ïð"p—;>í¤XÁ}’˜ä’h7Ø:Iuº ËN8,‘.aìk9¢rDÂ’šEQ ¡ 8€,Åj¥›÷×Ȉ4ëe¹OŠ'á镈—ym ]üíèô.mULÎ'ýt°^î€Õ«>´óu,¿“X f‚¬%~5Ë÷±â&»„]òƒ'‚rÖ*I’#ÏÈrq7 ‡J«µ+,ô! ÚÖò‚êÏCË* ®A }w¹A*@XÆyg1<Õ«AV‚¸è{®†ÚÉ\‘ÚWS<ûõy¤žúŸµÔ.¬§þ$®LíA6QbßBíDßZæÓLu‚ÙBu¸72m3 ÒNq:@š#ñï¢>'Jó'~ÛËré.Ã'º+q’Ôy“Ö`OPüâ ­ÔNÚÕ ïÍeܨNòß@õG¨0´fue\j©^K…¥u÷S{ Õ—Öª’ê+è8KstQ|×Þ¬Mö¬)ûí“—¾2ùúžxÐ?;8½Ï1+ó•Ý_®ßyw.aãúÛ?~nÁJÝüÙ͆þz0qú;ÿ½ñÞ«‡íw¾ñ™µo깯V÷¼~élßßCÿöýགྷUí?}éÝ~ÉóüSÛ7Ö\øË3swºe4¼²¶ù™»ß¿û‹óOOœ¿7—ùÍþOúwœ~ßxûÊ÷6ÝÚ8ÛÒÚñøoÿô‡?¯¨¸uçÙ“ã‚/<9·ñ­[S÷;vãÚŽ‹{žýÉùÓáÚ…víà•—÷U·¿uhè õÅ[O^ª´^MŒzk?øôñîo~íG‹Ÿ¡ÝÏow¹ïÿ~ÿåé×f§ùOßùäŸç&>¾±søšÿvîºumúÍ…ØG5[ßmo{jÿþøû‰×^:óó=_¿ïúõß¾ÚÀì5ÓèÞ!õê¡5K‚l£º ¡:Y÷NªGzmÛ‚¶ñ¬A*~Ô•aÜ.N3÷^<ÿñÓßýÝÛ‡¬ÉTÛì¹wFGãý¹aãŽø{̼ —Ì1TdA·,ÓJŠããpõ'fцòÃéð=@,lvŒñdsi£˜Ñ3Ìò¥ü(‚±L†ñÆöïÝ™:ÐÿhbŒYÙ¦Û”¶ ’ •`0¸äÄŠ¦ú÷õ=6ÆTŽdmIj …ÛGNôæ;ƸÃ--abãìì¸~´búmÍ¥yµJÕª‚³h¥õ1¦¹õ¨9®·q}¬µ`¥[+ü²¶ü×ß=£½C›lÌÿPK0XJ@%TЃ^Hrebar_reltool.beamX tוžÑYcÙc<2¶± ƒ¥AþYâG6?Ï–eaclƒmBø‰¬Ÿ±-¬¿Œ$Œ œãÚ4q¶¤!°]6I7a›¤íö@ M›ôçJÒsZqCÒÓÓ’„&íf7ÝîRöt“4›fï=‘ží.ç\ôæ¾ûîýîwï»#«³o»“a*q»¯mk[&gî Ã0IASCA- ©±L2ãGÕ„ª3jé‚:ÍDcé¢X2 „“‰‘è¨0ªféÉt “MÅT=ZœÎ5ЫÚ~U3$Ǫ¦%µ‚‘`4¦F T-LŒ3cZr¢0ç;–E ¦ä~²9i ÇÔ`¢„øGä#ÕÄœéøÈá0jñ€6RQcjF ¨ÁðXaxL ö§\8QM±hˆœ,ÊÌ †’Z†'^Á¸Ê‡‚i}QšÒ’a5P•$*M‡|ª`ˆ&F’&ØOG“‰"È:£ÆuÁá0ßJX xUˤu0‘h8S8¢%ãX41e’ú'圤b@³fÑÔt2¶_ ìjÑ`(¦¦Ä,mW'G¢‰ˆ‰øODŒ#ÁXZåHàbŠ–IB )ýD!±ÜŒeÕÂl"¢Âa5Rœ‹–+›™ŒÆ’¡`ÌWx‰^SâE'%Ô Ž,L`ŸÎÆ2ðJ½ ‚©TAþ¸4ðiM@=@b—Ì“–«¾v¹Œ–UMÀc\MdŠ´lbžÜÒ¼*§Sj¸X'>™ÌÕ\…¸ù»B|<¯%øxp\%‹UnIjaµ0’§të‚(a:dLiÑD¦„PîCÑDP›4OhQH‡$YªPÃYx lBó¤&ñqpÌíKFš ,j&b îÌ*P¢éqM ¤{Œ5”åçKi™_&¢±H8¨E š ÏÐî@3ñÃÏïæX$Ví8šã&‚Z¢ š&¾¹p*@z …Õ‚\± šZž…è©®Fɹ¡Ð¥@ql2w9Hc”,ÒKo%›{ÎÁ l÷õøÚ|¥ó>LDbªVOF²ó¶„ì¼çª†ÏÐÕänÉ&”†¥ Ñ%MÍ ±°ý¥É û‹òÛ¶rÇ/ÜU†)n…$2¹³ à VV4”Õɬ\‚e,Ù1rsÌËØŽ,v“È`ÿ‹¢,bdõY È$ʵ¨HnGŒÔŽD›C•¦±UÂ6&œ,ÔnäVc·„í6lE«ÅnqsаœU6qjÊ;9$w Ù¾Šý âE³Ø1„¦Ë°ÄöC@2ذ_”ðqdRð‚ÍðfĦ e7evª˜¼€ˆ1Š‚È°Ç efQfO-¨Mb¿IÆ~N¦ö,ì—3ìùb†Á!ØŸr¼ü 6HØ/cØ9“xjÅo‘Ÿ†‡áÜÆu<ʉ½.jD–KQg¦rªLâY ¡ÈNä°y èÎc.RÈ$ω7ÄNYò›—ù­>É uÊ6¿¹ÎÏùlRnmó#X# g¯c»4–c70'Ræ!œ [tVo"ì²›Þâ,²,P¡Lº¹V(³agbø2Œlà []˜CF,¬SXÞ6È\ýS~Í ˆW0èËtŽ‘táI’y+$Û(³|y‰"C²ØÜ™ð' $k³S¢*kNÅ2تDv‹–“ü9Ð@ ¾Ü.«¾ ‡P‰ÌÎ^†_Äò•Å¢¨çÊWx„jH¨úVBŠP-µJBu>.TM ‹Y¾JÄŠÏf@>Žp{Šà‡‹¡ûxñ:¬ª»y ÄñòZP#µ€Èíck—D—C¨±™[ŠE  .  åÈ\ ±e„s± S–Ì­:ÿà*² Vº…%ˆ4ƒ(±ü’…69Kq,…C„]j /œ§ËÙ@V§v¤7ªd#4Vy@°åÒw6¸Wf¬÷0ës+»GX†ŠŒüb B²PÇòw€Ïv`wy V°Í («=B=xªÏ'²žYOˆ\1-¬dù¢Lˆlsfù•ذ65”´žÁY ¡ÊŽ@á2ô CŸZH¿wÞÇqŽ/x¾iÛ ¬bù;aM³ü*Ý'\œsÜ:£bVaNls€zšô+Üi ÌA:±žµÒìMãB¿,ñ ¸iÎß #Eh¶™7cÿ èÏ.½?BòÃ♚%³_âœ0n©M¢Ìø82ox‹»·Í†å𠦤¦N¨™r näÎÊì¦Wë ØH—U}ú©‹†ÅüR-ë“/#ÆË cõ|ã¬!AÖ‚ÿ>¨ËºuB7jCÞÐå]ïº*¦dÁ£ë±ÐÙ/øYÞÓîeÂí^1­]áÖ0`s¿ÐbÞ&´²|‹8<Õ©xýæ~ÚoðyPL–oúñ´¶«z†Œý«/íç%¯Ïå%e¯ƒ‹ èl9ªí¡G/ˬˆáñŽ…ùÌÃä7ߥ³E¾„ÝóïŸÖî•gÀM™w Ìw ›Ì»„6êeù Å©cÐSV,uà´þ*q‘÷Ä3@±wP0Vˆ¾Â`Z@òêÞ—%ã:øöyè;$A–HN/‘nö=ÂFðµ%ß×háü)ד’bù°GXô7Œ„^Ýñ­æY$ÍÊýó|äf!ç‚–'|ô³ü¦âaHÏ §íØåƶ, ŽêýÓAक„F˜Üy(ü‡Œ"¿ I‡Œ2¿ÊJ(p06HP»´* Y‹˜!oiŸ‘JÉbŸGÓaÃzu¬:ša–oË¡‘Ü„ry{ÃíÇxfPgÐý— J–ÁÞÚÿOÞªo©]çíM‹áŽýš¼Ø|/ÌXÚá¶ÒêýF*n½½â"@v(´ [à6Ô f,øX¾CŸ4–÷LÀ”tVÆp¼þ³p€ÔÎü.n÷*'ÐÉæ8uª³îUîÕŒÿDþÝòöD»?™;U|ìl^£ÖíäþA£?Á'2xæÈÿ»Ý¡_2ˆ¼éÁRÄ¢ÏÏWG¼>sØëÂGÚó ¤Ý­´l›ÿJÙ¬zÙjHÙŽ±üæ\Ù†_öŽ ²OÊW+Y2–#³rê)!Ü”.q¸_ÿ£ú½2ò÷K0ÖºÝÂZòö„å2A{È˜Û cn^‰½Å"¼I³5z„>Ù—²¶ItˆÊ|hèÐì#NúÁIÞÛŠœÈ%Ð:VòЩÃ^JŽë|͉Ãd|éùú8øÚeÕ\?/Ó[¸œd7¾véï;ø" L*a;@ȇ6÷Æã—ÑoPÛA8@R€ãð&Âe¨Wä,¿ƒhàõq)(e¾™åw‚2Çï&yØ8I‚7ò©Ü¼še‚ Ðw*ÀíN?_%+*“!Ì.8šw¯ö¢bEnCä0¸°Ã ªs{È}tÍÊ"ù:Cf8‡r/œ=¹#¨!ú^·°‹ép™„çÜB 1müáÐOÁ§a –.°tm¤ë]ÓµRBm‰X¨¾ DÊ[[ézH]W‚T@ƒTçÅ­Í‹µ4o-S{;ÈTOÖËézÈJjs'È*êÄrп•š@jÓLóž÷é¦öd½†Ú¯YGýŸëéz#È&z–`k£k•7/—Ž<}TG|ú©~ HåøÙJõĦ7Ÿíy9P=©áÕ›yëíÔ†øÙMõÄ~O?{)÷ž<›á¼Ú©}$DqŸ£y8ǨÍ>h^.±¼Ú‘µÁw€ôƒ™\oÓý»èš¡ùˆÔŸ¤”®yú©Kg61HëEž“4õÁ˜”Ož€8ÕßMã°×ÙÊžh†ô<àäŽøJv`oŸÕi­´–ÏtÊ›g_;úhýÅû—n;ZúÒéÂþļóEçS­¿oüroëwj#í¿8ùÉ»ïÙ#ö¬yìW_õløá½Çí·?R[»ç×?yêìÏw>¾ç?\ÿÄùÿ|á_”G~uõçÅG*¾R7|â¾—¬ïùÍŸJ÷ÿäÛå?­~r»é¯îô8Ö¾>8·çÔk_¸þó^aÅ]‹¾ðÌã§?êvÔ|„Ú\ôÌWû›Ã÷,ÞúV߱ׯ¸ŒáKâ÷LÿØ*ìW9!¿ð`äƒß¿|¢ìòd‹ÿàý»Ÿ~2ùDá§OŸøöV<>!…LO8Ö~÷ìÍ—çð”íxæ›Þ·¯º?¹·ûðÀ¾’ñ3cV½yrƽò¦ý½ñ¾¹·vTTýíɳ÷6oí£•sŸ?nÃ+Ÿë>²dåÅu«µý—[Þß}âb¢õáµç_¼¶Ê\ñ›¾So/»6Ù]rµèðë?^{ßÁ¡ƒ‡/þýÇßÙê¾yéùðÅoÝ{­¹ðòÓÏ\úüÜš›VÆ.Ž\½üáñ‡î=s%¸þúõï&Ü~ÃSøß/íª>mÛé»s^xÑý¥FÞ:õ§ÿþÙé?üÍKÎ_¾÷w3?}óg›.=p­çûÏøÁåÿ\uúw‡ÏlœªÝQóèƒïÝ¿¹éK>\±êÀ’Eg.=$ðØúäñ¦c{â>~ñéwªÎ­w~¹þŠ<º±Uþšã}ïÿëO5ß^qòꜯŒWü±v ÓtôŒú³«Â®o¼ ~ýŸßY;ù¦9°ëÁS+VŸ+7ñü•‡žãNþùèk†ožÛû›iqÑ+gJÞmzýkÛ{ö›k® ¬ lyBºã ÿDÝ¡Cþ­÷ƒ‰ñï~¿z·˜üÕ?7ü¹àÉ0é×çi?ç÷k‚öðîÏôk”®·ŒP2úèý"3©›ö5¹tÝÒNÏ’¹¸ž­ñÐ5™¯«©}=Côå 5T/Ògò¯¸-“ÑàsåŒ~£Ç íO'ô‡„È<»O}õ{Žf>UYôÀ‘¯ïÛçíJŒë¦ÛsÄÞ”L‘_ÞÒDQaý7î@:µIbPÌf"QmœáÔP4A4ltœ1EáX6¢F˜[¿ÍŽ!Ø‹DsûPWOG`°k«oœ)mVœÍJ³S 8ŠÓéœ7âwx]½}ãLÑh4#«¡P³Ë½zŸŽ‰þ8=ÎÝkÝDÇe¢qu¬&éZÐ4‹‚l°D˜Nfµ°:Î8šÆ’qµ €«ãMi-ܤÿV|k5ÿ[m£ªÅ`"¶…ÒBâÿPK0XJ@±œd‰Ürebar_require_vsn.beamUT_hEŸÙÙÛ½ìÖdï ÂÖ“Vs{,¨æ’\¯iÒkLbi}¹ÛÛ»Û»ÛÝëþ øP}ð)„Š…Š%RK‘ õÅ'ûpôÅ)>J‘h|ßQgöö4øñ}ó}¿™ß7³³ßéóøï«•s•Àµ?QÌ¥<ÒÒ½†G.‡–GÛ¾#®=´$ABÇ ¦.1úmâù–ëøÊ„H¼Àgìcãõ†ë´­ê@Œ©ñºÓ‘ý? vÃrÚ.çä…NÂÖ£+:nd&i…©ñ6·ƒ(äñ, ¬ŸÐ[®ÌLtÝ`Èdef=2 ºOdÛ5É$fh#s°äšX¦gUÀxÔ)R ¨pégT¨ —.ª3wK/*°9­*¸rx#ƒQVÔF<~‰ *9ÌgDMÕFè4šÃÂÃwápœU°Rå¹R•r¸¦fR<þ‰š¶ð¼z”«¢KÖ4$ªîb)›‰ä²(ŧÆzY,=ùŸ`ö1Áýïà'qšm˜(â ÕKjš KGz¸¶Ž’*Vá7güŽKK³þˆÓ¨®¬ÃßÙTI£ ©M´x[ìÂVì!³)D !¶ˆbŠB¢€2ű8®ÄwÌü4E†‚‹ùs1âsÕ+Ñþìñ³q^‰}6¦ã½¸˜ÃM°flíuŠ¿®|l4›Mþ2N,¼ ®Þ~Iq½Þk]~þö üH8óåò%ê‰Õ»´°5רŠÏãú™*AàQûÜ;ér&@ôiGGµûß>}qôÏY¿pc¸|f{½¥§MsBÄç_t‡û-Y@0ÁÄó\¯á‡¶­{;Œ ¸a`Z^ð¤e9,­>-Ç„&1ÁT蘤m9Äì"š3M -¾¶²¶ÜØZ9W탙¢V(jÅ‚Ö(´B¡0!%/,m6Vê§Ï÷ܱ•´ZÅRùÅ^TSÜú Qž?5_f1>°lÒZôáü sº¤Ë:Ô§£}7ô Òù|×µIžNúyß3òQøß;Ú¢æioéPiù{ÿPK0XJ@–h´{×´rebar_subdirs.beam]U]lÓV¾Îuc7©ÛÛ8%ma`–²MêÒ:maÔÉMICX)] {ë‚“Ü$n;³Ò¤!öÒI›Æ Ûx@hâ‰Ö &m/¬Ò$Ä~ؘ´I¤MšÚš4iÛ¹®³""}ɹßùιçß\Ï[L#¾šÉNöìB\!¤H-êNÁmˆãFšm:v‰ºntÓÑò ÓªÔ+”N•E˜®kÓY²­ŠQíd^Ó.éf¤M;4j¸·n4™œ÷œí¨è¦KùSºcunÊL»Š¦áz®P ½T ÙõH©FKupÛM±b˜ÔÒ”_± «Ç¡®m®Ò‚{¦aVg^H¦— lmØå–I †U±ÃÔ1u«ÚÃJ{ŠŽ§¶r¦S•–•RSÝÿgð5,«o Á>Ôql§?µ5œÑ±”YzS…j ÍØeŠPè5˜'A›Ÿ5Àv€À‘Pìy…Sº¢á¸€†ÇµEY %µ8ÖÆã‚ <¶@µ…âVB»¼wý§Ndy-‡pL‘9((‡‘פm`AU}'’¹æÉ—E¦8Ò«ÅeÇ äi€¨dV‘s‘ÞÖd?àäaÌ5çø#2w6‹Äw¾‹-§ÈP ,@Â*Š™»Þ>Â]ëBD ''oá·°’ÁHÎ`’¾%ÆI?ñMHü=ˆûw_‹áyÒäþdK‰ФÌ(å,'ö·]åÄX4!óZ2®á!œŸ”d|°•[’!9ÐI “÷3I4žI*3@Gžƒï™ÈNmz¿4sÙoqJŠs¢LT4«àÜznˆã“R2'¶2«RB>(K ˜µÔ·.mãľa)‘Œ eùÎa˜µ*k‘]XTU¨usç4¢©¾?Éü OùZ¤ÇT™û¡;EáÄýÒ îR”i ýÉXK¶Ç ¡¼Ì~2¾Fˆÿˆ’å1f³'¤~,c´ä9ÇÙAÊ7šì÷m@€|pÆÂì|œèp Ðð=Á™ d@<°·~0øŒÝÖì`|ö´_ÃKAÎþ@Kû…Ú˜mYÇÛ±Áÿ€ÅÅm¨c9:5gxLspïôÅ ¤»7TÂxXÙýúÂÒ¥¥÷Ï;'(_¿¸;ø[ÓIü|åðÃvý~húØ_ Þ Ý £·?__ÈŸ6&G¸îW¾‹½7uåÔß×âò“ØgŸnytá^ö§}?xSg~}üår>º´ºm®¶¼º¼údñ¯ê[¾O3Åë»÷˜ê‡Ú5úã•^½z÷ÆØà·ƒóÿ®DßA#]š³K¬Æ‰`æJÐßÀ3=õ}Fƒ5³;§=Ïa3{×dL-TFxÕµü…EÐ'î~ôôèe£ø`Ïí+¬¬Ìä­ øB¾žgzÁnz†m¹Œ—‘ä_BpQ7ºs† Âv˃۵ŽxZ4,ÆpF †U2[eZF-«L+†EË5 ¾rE2'òs‡ ÇóG³uÔ3¦¦ÇÔ±´ZH§Õt:݉oÌ,òó³Çê(Z5<…‹cã{WüšV©ãBQuÔ11²od‚q¼g4h-\„Ãø‹Ò#zTçôn¿@×n9%ZGã5»AG¡pZuÒ¨ÿزگŸ¸µWš.º;(ÿPK0XJ@)¨2rebar_templater.beamY pÇ•žÙi‡Ñ¶˜Õ,‰!„¥E#iIÜZiµüHüXíÏHZiÿ<» È?1e°Ï?‡Í¹bBŒ±sgsÑùBÎ9Lޝ‚qp*²9çb'¹Ø¦ÎgÇ©º;ßëÙ–´8JÕU¶êí¼é~ýÞ÷^¿÷ºWêÚ°©ãʾðúÚ×µg’qŽ–q78Ý4BA31â©X0c˜RØ4àé¦Râø #'N&¢ƒRÚÈcÉP0VÄdɈQ‹¦3îñéBÃŒƒ¶ÚZ[4Y84ãÁŒ-9R˜[Q1BÙÁi9µ±ä š¶'hFƒ¡˜‘. ªÒöct šˆ‘h8ƒÆÞÃ4“fQnQ6¥ ‚¡¤™™–MD 4"ÁXÚöÍGµiip³0vp%e¦ ˜Éx€š+ˆæ ! ™ðP,§í™dn°‡ §i¤“±=–¶HËß…¢‰ 9ZÎ$M£Ð4‹i3 »i€ù°!ƳéL0ÏýU(õKݱpÕn½¾Á­» £42¡J÷{Y¯ç V¹§N„›„™M@兇溧È?È&@Nvçê²¾‘ Ìqß\Î01©•ë€èp\1´NærŸ€îšÍ˶’ù*¯:T• QâçÒˆì*G…¸PzŸÊë¶’Ê“D\–ÛtCœ.»~œ¿{ ›#Á ¸èɹ ˜ìòy™È>d¹¸S,Ü0 S m…´ý‘äþqÉ*…x xN÷Lw·|¸ð!ÅÙÉÄýÇ!U4ÄÕDª4‚:ˆG!¶^€[Ð×÷ð¢¼ñ¢s|•ØJ¤*/*ÍxjGZS vi­@ªWã:¼šÜ» »zz?饮“iª²ËoBÊR(VL4ðåU¶ë×s!*d^IT,/ÎðàX »$–‚½°7Ó!«V ŒøóMÄÿ¦b'7ˆÿ:{½a½ ЍŠ2èšËê8^,ƒÂ´ ÀÚj·å¥íÔ]-¸6ºâÒ¨ð¢m|Þ‹Ô&KfU öjmöR%+t¼’W@(Q-ö"ɉ²8V®¤ƒ_E‡ Øx/í¥øÖ RåVYWY<•Ü$tû!î²8··Ãž¶çïi»rAV¡ÿº4šp9ÁB;Ý_ï;hÏê—»ÁeŸƒèN:mF s¤UîrùÅ™µx œ¼Ømf*jñZt¡ûss~Aê¡§ˆÇƺ¼8‹ž£+ð*^ôß!ÐÈAÚ†+‡¼´T(¹ =xI†ÎTE…Z¿=M¤S#U¤ º—D,¿ñâÖaÆ+hZHTŠ&¶QÁøaaJû–qA¡—8±’Vs_îX÷Lœ¥pZg c_ Þ>Uà[“vÐ,Í @̃hl¯Ã;Y4vüypnÆqÛŸ‰ã6+wxqçÔa‰],NL•±J„ š Zðîÿ_:T²tØÍ ¦Î[èÇýê~ÒÛG::iH´*zwL ¾0½XŠóÇo–8¢³ƒÞöúƯOP®A^M¹ßƒC½ìÖ-†à‚—³axV³£_£á'•"Qסi‡G î#´ø (þ]02@JÐzY\È‹ƒt‚!º0¨Š5¼…Á 7ã„Am;Rvþ. -iÑÄŔڦv”;EG<8J˜¨‚Šx3N ‡ 8çq\îÉkóü ­IxpŒ®Iš¬I5ã4´&EkÁ¦Ò ¿rt¯ÂÁO‰[L5½ôÀÙsK-¾I‘Ü] ¤Æ ¸ó ÜNãsÐXMHÎÜ%*íÁIj5V hœY‡Jè5 ’·Éµ–cz?ò).d&{@rN‚½ ¯ûàuàŽ6ã;Ü;îW§p¯7ëº÷3ͺîÈý*›æsiši Ò °ý¨ˆ£ ïŽÄQ^¼Óƒ÷!õfÌ>úãou<O›l-Td¢cÓ/1~:û툀J€Æ»€f°ß”3f1yªs.ãçUñL^Íã+óôÌÏ×OñTç/dò‹€nav¨5ÌŰ˜Éеzž_MLÏ ¥Œ§Skf<]ÛÂäéøŠ<ü·æaðæéì`ã@¾¼ø¬fãk€Ö2~Ðú<~ã©þî<»Íyv·äoeòÛ€¶çÉÜÆxjwg^Üv…§2ýy{Jc¦˜}ûh>p&»‹­b<ý |%Æ OóçÅÃÎøBFã¹`§®l‚Úò°÷³½Ì‡×ýð0غ,ÃÂñ/jŽîh†æí¤ëƒû¾ùdß{”vy塊M/Wl<ñTCíðÓøØJå•ü½Ó×<õéïýè#×;´{Ïïw”{+þ½â÷W_|÷ˆÝóÖã_»«é½W_¿ëjÍC[žªÙÑö¾¢õÏüÍücFjç[¿çÞ¸{ßDZÏÎöýàÄ£¶¯8ûYáù¿à>Ù%¼°±ôFà¼ÿÅý«Ç~è,~lûáCéM/¬ü§Æ§[Þ9]}êð£å÷”ut÷lþÍÉ·9yöÓçGþºÍYjœûÁÐôy·F|ëØ#wÏÙ·{ÿ³ØþøÖ%Ýe‹{±B­Dú/Ízã‡ÿ9ôÜÁó÷T öUà/ÜpÚßsòƒáË‹ºÐ÷:ê»øÓÚYŸê‹O_½4(½ôöü'–÷=ó£+u÷® ;_«ùÍo¸ž^utñû¯üí¥»ôyçÏ<üó+Æ®®·¦äåU‹Ñ±Ÿ_½ç¥Þk߯ùÙÄÖÎMTžÚ!ûÍuÿøÔž£ßÚrßûkZÒ·ùØ«âw;sîFù_~¨»ë´<í±ûÇf iÎ]yfÞÛkvýÜýäÁÒsóï®+«[rQi:û†ÙWôГ¯~ñùö£×ë¶ÔU¯~åèñ÷𮜿áíÊ•ï¾þå†o|÷ÙšÓŸ.­÷í›ÿô.ßòg7?9·'ö?³}ß(çYÿZïµSÛ>ºTúüºmßýò¹çîý‡þ«è•Ï_ºýLðïžþøJ[v°áÌŽoÝÑxÉkþý¿pü×}U‡¿-d×ÏØ«Û¾<øú'{³Ï_ Nû—íášOþJœ¾h]˻Ϳ8~Æù¢øäÞÏ—\v¯ýúÉÐ¥Gn7|¸²öûå/Ü—YQºÉ~ð¸z®ãrä­cÛ*¢ßYøüÿJÿúÁÌWN?ö“êÝ(Çþí¤s÷KŸðþê6ñܼ{T!lýÉ_ïTç™ov'Ã4çÍêeåôèWò??çCL&d|(Àøa ¬ÆÖ³þXª`|+7Ùwiÿhg5Gk0¾h%ãi?mc|5[O?[C?´_72žên`ü :Æ—µg2&íbÔú-¡=é„õ’¹ÖM÷ÝýµŸýîò©6ÇÕ¾ááŽÕ ˆ/Xò•·'S™h2‘¦…[ÿJ¤³ñxÐ¥…Él&5G8ÁEt„Žpöh"ËFŒ7ùO†!s‘'y7¯îî ô­^çá¦7ê zcƒhhÐÆ…Ä-½Õë»6ŒpEƒÑŒj„BMž%Ã&úÇm5Âx/]ì¡cB&7† a·ìׂ¶ , òÁb `:™5ÃÆç®JÆznŒÔ§Íp½õçéInò_9‹ 36ÜJghÿPK0XJ@HAÆñg ´rebar_upgrade.beamuXpÕß»·—Û\rd/{IHa“]r„lr‡õ‚!Kr—# ˜ibÿˆpÙÜm’#—Û›½=þL+Rk5þgÐ(TT¥L+j+¥¶•*¬0;âØj‘ 2XÇV:hë¿©ýÞîK²0x3ß½ï}ß÷~ïû÷Þî]çußm¢¨Ò}íÑe+—ÚE9ߥ(꯮ö+z<ŸÔ•¤ÊªUW µJ,µ®¦ãy#•Î¥5%Oh™Ô`Ù jÄ EÇCVÑÕŒO¦ô6)L+M­®®OiùÆQ•œ æÆ3J«eD¥×i©Lª§•Ì 3 ZRe,PcÈ© 39ÂÓ†žW=z>O ©‰áœ#¤Sý©Þªˆ„‚ýôdu-k™ÍÄP°±¡ié)R™ÍO ­­¨µ±Õ{æ³4ÞüÉnb6¤ÒÉ„¢']éTÎÈ(Ù¬šIz”dÒô,§c·r›rx—3ÉxF”aãç³.U×5Ý¥ôkºáJªýùÁBËß´6ˆ€ŠLÓ\BOe Æä!‰ž~M3âØ‹œ%ƒ0ZŽ66eU׆T&Ø\l-Û4’Ne†Ý8¢Ä†¤;GFH*†q« ]IIˆÔPi œGà»+‘Örª3¥ húˆb¸ˆL>놩ª$† ú#Úzs׸¡«*KæJ:m9Uˆ¿Í¼Í€ÉøÔ´@ÍhЖ»fJ]J:§hÉ<±+ÁÛæU —nÑØÜ0Ï4H …à…š04}ƒk€rC^曥dÔëfYEä^˜ò2 ¹)‰•Ù(rrч|7+˽ØÑüõáŨe1’XžmG”¿±B;âƒr0" b´0äd¹ùnÑnªOF=²(È‘ ìçdº6{z}~ºûgÅhBAˆhþ7r„Ãf!ä Ñ’—µ¶àŸ ,æ&,­OôE°µä-ƒa´›¥Yo¥‰3–r³Y˜xXy•RœCZ޲³ÔããÝf 3Ê-àv´×)È1ŠsK[*^¨w…UÔ¢Z{BL!ÂH ÎCò€pªd‰D¼B~ÿ4Npü8mì½H…· ‹\‡z9$cv „‘^KÈsø)ñ¸Ÿ¶Ä7ÊvÛÌE"—9Ÿ8)feªSB1,£K»9Gd# Ù¨êvl)–¡6!™åX7®•¤å?T ₊£(P4Ö‡¸¨ÈAb%3jÁ4†[’ÞˆeIR°ÊšÓá1Ô2F*7ÆM°<õǶ ŸÌÜìyHœŒüQ1¶Ù4ÀF$¢¾I7¸¨< ´ ä Œ¡ \Û­Í.ˆ¦–wì÷²<8''ÇveNpËLiøj9‚$+Ó¼8ÂyD–—¢¶ÚžáXÇ!9vˆÃ©óÌCn‰ñÃz‡›gÊÂ'QËIÛú“öõãdý¸;}™õ8Lyø,j9kC8kG8ONË1†½š—åç!¸€ä`ØbI‚Ž+μÌYid*^ú>Æ”"»€ÝÙvšÅƒ/†CSš2qSḬׇ̀Z€Ì*-ô–ržFã4?š¬5Sf+ö.«~t9äéÚ3•榔íÃUgʧÛôÐ3[ÌZOi¾ét€Z€¬>òrÐHdÅ4äE€ß8ÊòߊHǘ™:ÍlRÓ?­±c޲¬ –º,,îO†ƒeüPÄz(bYq·ä£}~™ Ab+áȉpÕš7¤ÊQöVFÅÔ½ ¼àž,A-ÁØH4´Œ]RVƒ…Yþ*Ò¯³,•³MÞªs9—O:WuÆA‡p¡­ §EJ.BÉEÛMB6C_ˆ/⣊c·ùmúì`ʧÚ,£è BßñLÍåãÃYæíÍwªÄÌ!Aõ™çADÓ"s?–á'ƒ•Ø©$à †ÆGŠ™ÏT-ë`*pògBò—À¤r<ÈÌTsñQíÆq\î*óO¦ârJœ§9¶<]ªÇ%âIkNÝ¥"‡G¤ào3ž©3+ Ï/(\•u§1UØíjp»Üž…Ÿ0Ç•E¼·ÆÁÌÍRÞÁÔÚ£Y™æ à:0žª6ùbü‡“Æa¯9¦s.yn ç*dè­ðÖ9˜Ú€W<Ë&ŸžŒöаH´J4?J&bBÌÚžÖÙEø¾bó[Ä!Ìo"”ƒ™'—¢U,3×Á\%àß|Ü< ä™yf;!žúVæ!T!Ê $‡>ìm_&/Pë#àmà&ÂÞ…B ÐévBí­·yÚÞ@ÐÓßœ'f„+&1lñÀzY°Þ9¼500,3< Xìl`BijñdLp@‹ÀÓk`ÒXL±Öù’HÉàÁ U¡÷⬮‘,ŒŽ¯­Â*ÈAx—/°ñnò~ƹ¨È T ä%6˜/!6¥@áý@eS¹ ¿‚à`Ì™6¾’ðÕ@³1g“µ5@s÷å _$Øð¾sÉÚ+€æ“=±Í"¯#ù˜Ük!ÁiZDâÂrÉfÓd“7û PÈf³Ø&¿’È1ÿâæ¯"6a bƒãºÚ†#Ì·Ûò½„Ÿ´_n³ï²Ùˆ˜nÄ=0•‡ÑÏ'<þÌ#X&uæ3½¶¸®!öÄ–*xeÎÛ0t}=Ñ;\›^õ¬H°Ö sºxãÎ{zÖh¥Ëükö-_½òÉÍG†Vf~<~CþÙ;ßü4ö¹|Sð¶ÿºñÁ/Þá8ì^ûù™G+w¹wh^o=÷Þ‹·_»Ml¼_ ¯¹{Û÷[ýðªy¿\xîÔ;•]¯¬zé?‡_zà‚ÑüÌû'¿3Ø÷Ò7G{Joض`îî¯}.p°¼lÉò®êëÆÎqþ†[}§¶7{¾‰½õ“ÿyO×Á7×Î_¹ùÕø' Wï¹ûÞm¶î|oûóý_'/ýürÖúÖWOÍ:µò÷Õ îÜs×ø©ê¹?ÚýÚ–GÚ_Ùñ—‡äÇŸzÚ«ò·®Z²¾ªùà™Þ?ÿÍýqѶ5'nüÁo–Øûz ibiñÑüž¯î ììê9{û¹Ð3g~QRû‡÷‹ü¯5}*|]–ÝðÐÇŸÞ{Ó¹33ŽÇÆ_h¬<~!xþù5®}ç‘ÛúËEéy¯éÇÿý§–Ýw~üå÷vT5¾}píãÕMkuó#[Ž©‰O|0®¸8zxyÉ¡ÔÑŠš7Þ~r½øYnã?ÝväÄîß>ñ“zçæ_]}}Ù £Ïòò±—ç6lŽ«úö‡÷¾ðñ¬ãò’µ›w¬øyÏSçÞüßÕwýë.ñc¹Ø™ßíoo>Y7çŽ[ÜòÑ-?6¶cþšqêö3˃׊­ÒƒÏ=[¯~xë™ø‘¿ëïžýdö}ªðÉÀÕûöŸ¸p„}¸&Ù>Ñ–Ù™ÝùéXÍö¶ê6 7á -ûÿÆ+º¤ì½ÓFäø,/µ‡V"Ç÷ÀÂWRÓ÷¾[„Ç¿'kÉZ¼WeÝmøþò¹k™aè¸ïšÆhCÎ$…Öç2æ$ÃRÍY·¼óX>£l¾÷ÔžÈÿê×­ëèÊ €ÎiÚÓØÞ­e”–ÉaAA’òšÿÄsù‘Eß„ ´¼?~‡)ZíOe°Ä‘¦Ü©L"OªIª0ŸIª©ŒšB K&)Oûõ]+"ñÞ®•Ñaª¤Yjj–š›¤xS“ÔÔÔ4iÄ|¯£'Þµªóºaªh0eðjs0´xéÓzUÏSÔ+´èÊE!,£Ôˆ:TÐù{ŠSñ(EŠC™a:˜ÓòzB¦CÚˆÚŽ«Ã9=Ñhþó1ÍMþý´HÕÓë(jYÎÀgÿÿPK0XJ@ÐbÝH'Ìrebar_utils.beamY xU–®êê¤+T¨¤‚NºA †tÒ $M¥ÛNó&Þ;ý¨twÒ/ºªÃK$€(*OŸƒß§Ž#ðÍ·;ìè,>fgu–_ Ž®Èè¸ß¬"«³êŒ;;ûßêÛ¤ÕuwÂwºÎ=÷Üó>çVÓ]ó62̘îιZ"Æ0ù£†ÙW˜Rü¾”7­E¢ª)¤hÞÀÚ ±/U ‰SDõúR°!¥p©tL3•²ñ©DB# yä¬Z®ÄÒ(OÅû­ú3)ë´̤·ñ b$¼ùj" (…Ùt!Iœ:7„CœÂÑŠ³[‘ø`b@)„ºtTÑçÂâœõØúÿUqƒ£Õ]ßXÿïÛ닯ÕÂß ÎñÿˆkªQ¯G£¡‘Š]ÿ½ä\Û«¬ÿvÒé†ã‡6hãE5ÕWշܚ虪úïölƒn™|~•¤¶¬~x€]‹˜X¯†!$°Ýb‡{=ゆ);Bd2;XÑPZ˰–"†11L[ 7­…³89Frr¢µ®ErÊV®”‘Xû Ž• ¥ E¶»HeÎhdŽËÆ*¥£É.Ú·síÜö y«roší•r¥¢Ä&åÓúshÇî5”>ϰ‡‹-Œ‘ù¥Ì•ɯq&ÑA²Y$þ¹ êˤ’2“ÅžYp’läx‹Ýž4”šKöl±È„oÊýDĸ)O”·p/v‹ìù~cÝGœ¹¼î#É~4ÔÚE–¿®ˆM"/¶ ÕÐ[S®Bµ„ª­æFÙ©—-_­ŽÁÑ&ø;¶ˆAÒ­zÎÊõ„– :ø¨°€¥ÎÕpHL —‰T•Ö ã8OR6·Jr£•l™ì¼dl¨yÁV!jO V–¯%BÄl\ž]ˆC˜õ·óe ØHôÇoÆC_;¼¹>ã ÌžÀÖ€åHÙ3$e¡–Ëø2G: d’]˜H4O¬O uG…X¾N–`®4ÏÂ#—7€·¼2ÜšŒ– ‘~51|¥ldåÄíx0 Šªàþhð5€ÿfȶ÷‘üT.ÜçPÕüuuB#ºßÆ•Ú!¹QöìEOF†N: í/óÕè (q—!™ešXöœ%é#ö=çõˆ{.9H À =MÐ7qŒíRôœG 7 Í$ôPÒ­A g¢¯0]ø1‘f½x›û›ë„ÒåB ió2Òè§©è´T—EòÑ;8³Ç¢ôõS-¤õ 2JçBéÔáÞ…µmÂ4ÔÑ´Ü®šFºjºjžÐjž/´±|«hA_Ø0%àûU©¤9;lm¤Õ­\žE’Y~šŽ2pKn/JF¼…ÄÀ¦;dák@¨µ $$íG…›X¾]<˸ âFÎ]@Z¢`BêáK8Ém“H°EÞ °µáð4@ŽÕÄê}Lw 7²üô:¡Ãj^tmŽñ¥¹†c:dí½Q”©wœÛÆN œ;,–,3JÆÂ@í8ùÒ²DB9GÕÜ4,ºŒíÙ¤îuéÈu)z\æeXtÒþB½š—gj Ÿ¿¾Npqæå:ÍÆeNô’sÒ¤w’ì°í°ˆ‡³¡LtÞ¥3Ý «à‹{ªà±ÙeZFZÄìÂL홤]gœºX¾‹ rÔCÙõ™ ¬äºŸX'Ì fQƹ >ÞÌ$®Í"š±˜-¶»­«›³ZÝ’5óä`ƒ‡/çК“X~X{Qs‹[I÷áëê„yœ‡²Ùe 5ºSツ܀õÊäáGI`À\'³Qÿ÷™ýuBÀÅfÅr;ì¤ïªLâU5çp.׸diŠ,c¯˜™„\—…ó˜Ë=ú‹¬nayeùìC¸âP*ʼƒéê†V!Ìur.Ò0j“ .\úk_en$~2.ŒÔc˜\bˆI!oý™K ïD|#ÝÀ–†­hæu14„W ÒÆ~´þ2a$/Ø/ÄųsWÞˆ™”MmBÙKç–yš”yºBv Ì:•å­BÚÚiu¸ðtuº=xötö8x:µYH«m‚昰8 çtˆ¸À5RÉ*y­4¯Ö˜× )–OŠ™+Éè‘27 ¦&®!–Œ!ýM.ƒÖSç 9´¹*4n¶üýT¥è“ÃgÏþ­gU}öh³,Ÿ&óf!Û€ÐáæZ‡ÐÜ– Mp›džÆuvà×m˜…õæ[… æMÂFóm­,¿ZªIËm2† Œ%È­úë™F›È4Ù’Ñ¿ hM½-Ûºó²­»ÆlF% L·5sÐ#¹­¾–TKs›°&nÉ}IÛ‚/¸BH†XéE²…TÓVˆÂb›\ÊÍù–¿PàévµRÒêSXþ·‚x'´ï¾ ø]àŸÊòwc¹Ë{°µøÀwe¶vcy'ìÜ#Z,nN7_IÌ;×}mÂ^Ì™½’…¼ YéD¹»wáÀ}ÃîénÈ·+YþA,ïÁò!½^2®¼äý‚… ù2ò^d4a¥wÒ$rgé0¼»À{ MxqzX“qrd^èdy?‡€q7’†•È[@+y·âèxÛ{±ýè°±‡AÚÿ´ G94a'‡/m¢Ð}­É·ýýŒËÈ8Ú,ÆQ†éÑR‹È—Ä™±$ž†“@ÛØa ôûc>£_ÔiÅ€–â%”àR^FyFªèÙëÕ”Nð±”?‹gy¬9rÆQüzÀ@` ŽÚv žòL&ßq©|ÂoϱÓAñ)€©9ô¬¯Ó­Ÿh§<7n¢8&ª‹Èé¤6LÎ9KpgŽ.ÅÝ€.z–ÄÓ0ffÓ³Ÿ“ãKwŽ râ°ð;t–žïÉñkqŽÞ¥t`eŽüÕ'ô[(7'ž$>ê#ѕȑ™µ‡Ð“9ùZ“c[2W)Nâ÷Ï'¾yggó¦¿~ýÀϦ¶ý^¶w{^š3ç·Õ÷Í;1³b‰Pó´|bàЇ”Ø¡/_:pøØîSK__ÉýdpWû½«ÎÊÕ÷,Ûò8›n:Øÿè³ÿÐuÛ©I9ý´O¾œÿѺ{÷éæ[[§½Õñõ»¶šÂºž+ì¤ÂçNxì±ùhè¸ðkÿÁ ï.X9kçíã·¸ºÌ»yÜñÝ—ö½Ütø¥—ß-âNm;þÆš®#§¾°?V8åÉ¿hîS§ßh=Þ5ë¼í|t»óÌó_w~¼±ìbéÜê’‹[O®úåÙ©Ïý¡6ñIjÂÓßM‘Ù‡~UóÕÛþÓå/,ÞØôÞÞão|˜÷³•¿)ŠVU4÷}pdž O¹Þ\SðMôñ‹ã¢'¿|B—Îû” ×}zʽÆ;ܺíùϪÇ,ìé¯úч»Þ~èO£G¼û_~oÞ®%‹ßڳ뾟|~ÿþÉo¶<{|ų»7lþŶ‚ÞºtcˬySfV¾#̨YÝ_¾aùÓ_D_|¥ÚøÊÏ‹µ)8õ×?¯¾ò~˜Ï?T±ù¯ÿßæ/ªyëкs³¾2¿ÓiN"@æC%1ûhýùάȹ3!·ßs{<·¯sgEn_çörnÿæölnŸæöæfzv°Ò×ÒT>™ñŠ“;/LùÉ]¢üË~Š“{·—òÌ¥@ð©šFîŽ ÛÈ-† A†Tãú".2[\Õc7ü]eÿÆÏºþÝüç‰þ~×Ìx©ó ¿)‘$?ò©„dèoj:ó¥Ö†üDZ FRŒQñGâ„ÂFS$ˆ¦ƒJþ±+Ìa/dÌÎÅ3çÜì]4s®{€Ñdol²75Ú½öÆÆÆ,¿ÄÕã9¯kþSŠhÅïor4·ôë6‘ŸaÔ“×ä¨è6šØFRQb`[Œ3ïÃH${’ØFqœ±.cò*FŒ—R„ë”$§~’BIÙƒÈôå“”‘ØÆXj§(`þ6p/µdA¬ ¯tÕ+< &¸ÌuŠ8%+m>ËŽˆ¹.„EŸWº®<‡Ž£ç:±~ŒëHÒ æ:Ðä"êz#ÐÙýËÿ#«q5zÉ’}^‡ Úè«•PÆ+È$»†é@„ïF1$‡¢ü~yHiÁ8. á¸,ùA ˆC>ðn Ê÷€‰$AGîX¢¤¡dH¡/ýmaœÂK¶†ØÀù˜f»Ã°ÛBb”€µ©ÉnÎãHIø€È‚§Ü‡A2’ )ž üVQe¸~¶£ð£þ4(Gù£âÐ|\/E!¥t€?âbaþ(Dr4í”ù) ¥ü©D»©;HP(›ÇÅ-æQÒžé-š$]2éM@í†q;šØý4;B8p… `Jìš 3©Ð,¸F-X‰¡ßê]·‘ë ‹a¸ü>„¸‹8ˆÈú¬}d«/;>ìG×(HpW!»ä¡úfì@S‡Ã|tô1°?­5ᣨE‘bpÁ>.J~.7~¢®H~\ç#4;^?càuÄ^]“†t—Áh˜?Fð'07!Û ÒÇÁÖ4$àD„?é¤~R?)*-‚ÙgìÛê„gxÀ£Yèƒãñ  “‹ˆKÀMâ[§¬wÁ’‹.kz7¹ì•L|äf!™ LíÞOö…Õc_sq@úä#áO;÷Kš8!K- Ü/”úØC|\X¦1Ť|)?\duBöa“fO‡ùñ9 ¨ç}*§P‹ “ÁܼŒ¹´.Ô_9Ä7wð©0Ÿ$êÓ ~œš‰ð³·I`*üYR¥³ðâÏ@¡î¦Ù3õ*Í@ÞïvWiÆm`6ÌO#A’’¢‡Ø9KZxŒ-‚¯ç¢ü³¹ÝSOŽ0¡ds¢$\ÅP28,Bº~Ý¥äöºJº»ƒfçë"`-Dø´Sñó ~^„l’Š#P÷‘‰ì'Wµ;}dá#owXXïz?,ˆØÂç&ý¼Ý( 4›óó$š `ü0¾("*mêÈœ™ò:Œô0•€<@ˆvæ ÎÈ59{dÎ9¿‘Èö8c«ëwTP»3|.™»[{ö¹ø\>t»d:<âk¯KFvñýΜÈ÷»æG\8G]ü€‹?äÄ8¤82£®9Á?æòsÂÑ=tÂ%sÚáïÌwø)ÿ¬ÃO‘ZÐÉ+¤Ô€ãC‘Uœ9ùvåÚ3U«ùYGþG~Ñ‘¥¼ïýý¤³&üsÎH¡ï®’šÌ8kìàQ ÷<=[4 æo`«ëÊ÷ 6{‚-nݸ1a¹á혹 |å“GþtñãCϼ%?þ³oÌ=ÿöÁñg~ñÀ‹üà•õuýÞûžH¦^¹ùÎâÏßìùZÏøG¹×ÿüä°§÷åŸ.=õêè¯qs[µ¥ûè½¾ÀûÞ[¾ùÎÆs…ÒÜÀ¿¾óÒá±__»vú­›ï¹÷×Wzßߨû͛߿ñÂ_KÿøÖÖûWÓï<ý·í¨°üü¥ßM¾1ùÆ_ùö/³ãÂCv=9^|ó‰n–·Ÿÿ÷¯¤Ó·¸¿xêŸ/üþkž/¿v4Êl5GâúÌé?w®.:ó…ÛruÞÉËŒ+wS@s?~[§ù GŽÈŒ%ú>Š:2¤ÆaG†ôkÈá÷]=²Sory—£Od:€;å&qræmùÛƒï<¢³Y"Z+ž<….kQ¨û•Ÿ<üê~;ÐýÔ‡øƒéÕÕÄL¥›ÿ±ä"ï­®“Ï(ƒ0óo}fŒZ¹¬êD ±Z3áSmb´l±B8tqò+¹R-¯å©Ýò{ù<ÅÅgfOg.ÌœM®Q­£JpT *™`P ƒ;BìÅD:337unj^.š’–ÍŽ†ÂÇV-Ÿ.iºN­Q áá±á0á1f±¬­4f¡÷ßV=*§6«´Új9hh¯Q#+Õ²6Žkk#†ž±þ;³;³¾‡5½´JÅàß$ð¿PK0XJ@¿…jjD–priv/templates/basicnif.c½U]o›0}çW\1©J[Ú½Fy¨:"EË҉ѾT•ei­;2&Ëøï³ÁHP³uRy0²}?Î=÷pù@yÌŠ„€K$Cœ¦Ÿž]ÇÉV4†@² MC’‹BÆ$*·Äƒý>IÁHU¡0øq{Þ°€ÍÝz=w¥M’B®d+gïT}ûgÌF´ÙlߥP˜ç‡dámVKá·¾'?' €ï< |çå °|Š}Î?±à¹†×¾»‡Çéü\î¬L +*øÿAø $CΗ:-èn “?x„…&Ó„Ø»šׇKÿˆ£Ê·÷fmvå—S9U/åû3ßVs,š·–1åcÆDŒ¤UàdD|ÿÂ÷äôéä$ÿTwÂÜ0ëôS-¤ ¿QMŠõm\k#IÁyÏn`"‰*$ï…SÅ–‘ÏM°î+‘5g®xq§¾¢ƒTÎÙæ½›tm+Oj:B_ƒ¶˜w‚&}¬-K(Ö¬ñb{‚Ø8x&a›mæÁM±"€y IÉqFc-–jÅ`EÈH&d©g‘zGù©ÚÀ›µÑ^Sâ©L¼©Æ27î]Q†UÁ8ÇïÁVÒJ°ÂþIãƒ(OE[Þpð.~Ê!­×ÅÁ3ŒÐM\GüîŸE×_ƒÛû œj&¸<`=ÒÙì³jtéÐèáácŒ4š+#$Enx]*Ô@5V¼vMÁHwâ`­±t<9¿Ì3úÃ?ñYœD:°Jè§QI¯m8jã"H–êeã‹«³ûIΔOf! ÀÊWAïòÛ; .U#+,hšPêÒ5Œ·ý©UýZbå󃺪åÚâÛZrLJQ)„ÑÜû¸D¯&S­û´²6ÏH!$×b‹ó·åêÄR¡‚<òøáK#ãûËéŠ.c;`Nçóká¦Û`– ;SW Ï5]1ÒZûÙÑ–¬È´SQxýñäÌ6ç†ÉýdéwîeÇéä2wËïãz,ãnüÃz1)¿jkÌÞ9þ»˜üÞïqP»ú¿P¿ol¯5–<0¬õ¶æ…/nág‘:9u Öå¯P4„lô"´"ýÐi±¿PK0XJ@ý+¡R‡ priv/templates/basicnif.template«.K,ÊLLÊI-ÖQˆ®ÎÍO)ÍIÕQPÊ­„0•jckõ¸ªKRs rK@2I‰Å™Éy™iz©E9J@~qQ²~5Tcm-X—Ždúäx4É õPK0XJ@Ȫ8’‚priv/templates/ctsuite.erlÝXmoÛ6þî_qÀä¼ìc¶nhÓvйC’~ ¶N1‰ÔH*‹çê¿ïŽ”l)vìd±S`úbŠâï幇GïïÃXç¹V±CëÀ–Ò!¤ÚÀlƹNªª×Ðo™a¿5_~;¿útpØH5ÎÊãLŽú{-eGõ‡£±;œ˜lÖöô½¤  m\,²Œ§÷÷[xH |.ÕØI­Nƒ+ýü ç*Õô‘¿óÞÁµ+ ²âà†ç¾Hò]§p‡Ó£{‘•…ÆÖBÑŽ,‚Þ t¥Q²ZÆk²à4Xt`*ÊÌAatÆI´a‡ÖÃÑu 6[ µÃS¸j¦Ž!­=iA«l 9 åxŸBi1á¡ñư‚fãD8ÞÒd Ú1¡¦ i_l™`ÕÞÁ­D¾ì뙓9:#ŠfÇZ%dÉOÇUu³£Lß]¶Þýw~¹©£ê_(Ý3?Š£?牉ü¤}¯’+Bë™°h«¹¯%AátÞ?)ää(žæ¤ÓØoË„…N†V! Á3øNˆø«D5F^NÊ4Íx4»À…»š «ÁÒjhá SÎ6ÍH*Lçæu¬æMƒ<)÷VEs*škú­š—5Î ð\0¦U~ÇÆôw`NÔÃè1©jn1ÈYÀ—ŽP*¡ƒ6 š ‘„8-R9¼EÓ?ˆVŒ¼ÖE¬h½ñ/´{Ä¥r2c‰õݪÙTHÊÂRvשé*išeéŽcÁ%.I Rð2Õ™’‰sëI#•Þ£YG"bA#MÈ®¸ž¥’Û­ÒN¡ìª)ða‡e ¶«r Á‘ûT]—aÛªÍ'ð¾Bh-ÛsÁ7© a$BM¡`— & ÖŒÝÔC³‹†Náôáîþæu|0rád ŒtS&{ð@UÓ v[ÉkòÕcƒ®a ÊnRj91ÜPûãëÇo_>†v –t˜RÅÖ’Ÿ}L¿7øQq¿ |Ôìi*3GeуõyýYK}WL©È,þ¼IœŸþŒ<ú/b\n1Ñoì³èäåP%¯S7BΔϗiûºI†Lleö`W$ÐeÿL«TÞ{˜=.Oü¡r'‹è…ÕªjÞ‰‹“ØŠ{¬?Dõúª.¤Z7¡³Q´ÔÞ½Ÿ—î£/‚‰Î©n}}/ècì5•¡K: çïMª ÅCÓ„ÜÔ±µE£¬ÓÝu(åœi]dò¯¸Ï‰§;BjÿÚ­`jÐSŠHßÒ=òˆ?±ª ÖsO$"FtR褢Ë,á×+¢òåÈ`®ïѫŠÛÊêA¶vî¬DÜsÂ뎀Ø)É6á^ËÄÓ3WRþCÀµ„³ŒZ}êDJê"c+ê%~”}·kRðhÑ“Ã.ùaSÛÐMNh¾|óMÅ&FºôW.SØ:7¶æR¸h\^Ä8Ü.´znMl9ªêÀ;ªŸÉH(Æ“U-ÕV€ñ á§ÂÛRÃËÐø,Úx æ¸í·“úJñvxÛ@B;C7? s8²‹ìa¿¹7ì–œ6ÜNº8Ù1+m½Z³zéüŸ{¡'‘ö¶ì÷RÀ¯ç?žçÿMš:x Ìw@„Û€8»÷<„¯cЭsç àÄKãÖ_ù­ëÿŒÿkà"ºž%zí±¶ÆÛ–„+ú^uãÿÕ]Òø¸§ ä¸Gu 2§¤åTV”Ù½ê°÷/PK0XJ@}Oê­P_priv/templates/ctsuite.template«.K,ÊLLÊI-ÖQˆ®.I-.ÉÍOÑQPÊ­Ò¥9©Jµ±µz\@‰Ü‚œÄ’T LrIqifIª^jQŽ Ò¢_ ÓY[êâ –jPK0XJ@ôävÞ priv/templates/simpleapp.app.srcmŽÁ „0 DïýŠà9,ì÷Ȳ¸6HØn-Mñüwk[P\s 3/ÌD‡CâÙ#¨fÉv]Ñ@oÔ’Œ‘C¥]·û ‹ìâÙT¤‰%Q$‹Ð¿ªw ,I×ùRôäð†H²Ž?ÿ EÿæÜ£Ç§ï¼KqÅä—¢L¾˜ PK0XJ@¤yE†\Ï!priv/templates/simpleapp.template«.K,ÊLLÊI-ÖQˆ®N,(ÈLÑQPÊ­²”jckõ¸ªKRs rKRÂÅ™@f*PJ„‹‹’•@‚EÉúÕµµp \:ãA R‹r0tÂ%pê,.Å¡&Ô PK0XJ@À­À‰œk priv/templates/simpleapp_app.erlÓÍÍO)ÍIÕ¨®N,(ÈL©­Òšz\\ºI©‰e™ù¥E@‘œÌäÄ’Ìü<Œªª‚#BD!91'')19»˜K7µ¢ ¿¨D#º¸$±¨DßHG¡¸$¿@ß0ªË–r€Ûr*™Ïv»F|0ˆ ©,HÕQ€°‹Ò‹5tí¸€ZÅ¥V`-ñ9™yÙ Ÿ‚< 6 $®!?[ PK0XJ@‡O³Ì priv/templates/simpleapp_sup.erl­RQKÃ0~ϯ¸—A ©ë|TÄ +LÔ§QJ–¦.,MJš¥ä¿{uÝêÃÞìA¸»/Ü÷}GâÊ­–´ëx]«"„¼iëèŠx+wü lë(¾HwPu}a6ƒ‡×”Äò«¶ÎÓMã¹ó¹Vf?O²¡áíŒÁµÞr±oF„2ÊÏ§Þ•ÔØ ÎB‰ˆB Í2Ÿ vJN°%ŒC¸¥2’>®Òõ’¦ Þ¿k1èÒã'b°ÉDVÜHã\'Ir`-ÍÂ0ÄíÿcÊÖ¯¬i¦ú—Œ|hñŒQŽ›?åN[Ô›ÁýóËòcýη^ˆi©^´x*Æý†PœøÄ¶³he‡ÉÈW$ÇŒV2X$á×bÈíPK0XJ@Û"'»ŒÏpriv/templates/simplefsm.erlµS]kÂ0}÷Wäe¡Õ}ø´‡ Á Â6‡2_DBÖ^5˜ÞHE‘þ÷%ÚÙV»½ØZšÜsOϽ9× U°‘@‡yŠ Iš­†û K¾jÑ 3{À\ б7šx#‡¼¾{_ož‰4îîˆ{ó²,ÝÏéoÐ×B!ñvké¸"ö† G>:54“WíûY¥òÓfÕ_‚@¡Û1¥h`ÈCh?vOYr $0Øj³oß•â=úi´sF œ+›¬! ºB¦¯`¾. Ý©¶u…›ïY§ ûYYë²K§Mâ¾kJ¯ë9;HåsiÌ}ryr¶¹C¦3ûÔë— ·|”u£E|®û V9þ‡K–™æâ,i»–)ó¬U2¶GÂNŸðyÿ¥°?(X?RáSk¹wˆÕVJ”÷sQÍG,v‰ÊÑeSP*¯”:§ôf;J” Ìû™çA¤lt’ìÉ3F¢bÎ2)t“ÀIÿöÝ‘”õa9Ú«üAÝýîwwäÝñøf?Ì`­Jž×5“×'þk&dÉ¥Õü#¯3xyþ[vef^^Šš´ŽßfPÙS¯ Öœ¾sƒÜÒÛÙ×?CH [¥Ð[^7\ÃE¡Ec¡R„´\³Â dp#ìjñ‘; ´¿£52~¥¯M³Ÿµ‚S0–i›óf]ÆIê–Ñàë[KŒÀ.90TqëÛsn,¤p‰‹Üþ¢ÑªàÆä${ù"… ¾’—ˆÛ_p¢r¸ä ÅFkLP}z#%ý%!aŸ”²)Üð'u WLÔ§`†ÃVr›¯¸–˜å¥(1Çy¡¤ä…Í 9î(&),+×Yƒðý7 *éü³zÃSh”¼~hCÔ>juÒÉå(Ä&„„Ê0ŸkfãˆÐáSCôAsƒ˜%yfóìoa:&‹ûöY²ÚÆ/·Æeèo³Ð§>6ZŒaÄßU>¸V”LŒvÅtÚ…ŸÕš³ò.P4¼$†ÌqLÁ(øgc,”›u3FeQœ¢CþÓKô19éQ4V5û{JŸÝYÁ꺗©O‰À@~wýôŸd1°€nÐnþZ#æ1;WJ}3„òˆ•¦@„÷ªÜÔ¨óûFb‰Pîá¼)hì™wÛcÒ`-ŒÍ­Ê™UëØ#&£Õ´‡Ï¼5Ý2îoÂöÁ²2"Ö½9Ù[ß^±9§¸¯™QrïPMÄöüÏ3Ú§x¼*, ¼Ì vßg7>XíØ>Ÿüþ‘l<š£Œa)_›‰´¥@q{e.¬ÆÃõ?¤‹£Ù }ÉciüÞó«–þ$Z“N~ñH¾&{@î}çBÀK‰ÿeØ5 ¡ÓÖªè=¬ûPPîý‰ ÂØUvúÑëe¤'ÏŽŽ]•jÄ«¢èwÞ]ßÒf0™ÆG£X2èÐ'#¨hf¸-”Z Ž~¹TUä#Vüˆ”¡jîuc×fÇ{ÑÃ%!LÃd`Ÿdk"dðψ\¾ãt‰ÍuÚS`MƒÑt­?7›ª·qB”Óøcó(ÛªÑð2=&)ž·¨èv1bcŸñ‡Ì’`Ïf2á™ù~\3K¥í·ó «ÊÈ•í&Í ì ‚²‹ Œ{þ¨?¶Êóú¢LVà"½Éf—øúéSˆ`V2¾V²u^­¥/0^kk~ò7¡«ÂÚDe¥ÐÎ3nÜ4žù¯Ü­µ[Øeé"Òn CB8Ü–9¿åÅ/5}>:Sƒ²Z±µ¦Êþ¤É¢<‰2QŒÎÔ¦.ÝôIÐ@äŸ}ÚEiü¬¹ojuÅêר}Èf'q¸ÐNéï4P’¿ÛeÞõ íâc\¯Ê¬ZqiB£_¢A|æ¹ßÖù[…[pllP¡œ^×vã÷XcŽ3¾‡:Ù' Â"ÌPÏ'=lÓWhlÁ&gî©¢J°‘$½HLœvïò…ûó¡ñæ>˜)’ÞhJ{Ï~#è’8`þ¹@~‰…a@Âø ^Š%Þ;¼Ë€÷æ+!™¾£»¶=¼-ÒEšn/dnKñŽÃ܉ÏÂôãsBlÇ!„¸Y"´0>§n¥ r¢ö‹ë4«£Çí*žòN׳qkÊþínß”CÿZ±3%m°B-|gl¾¹)˜l3Ý“oÛRI7b$}SowÕö*‰b“Ã5‘KgÌ5“§ß‹aœ©ÝI—‹Ì}æÿØc¨;ýí¨Ò´ˆš¡7L¥-W’róØAfû3ÑÖ CøNVêQ/{r‡ËÜv­4§JÚûñîeùE ÎbÕmôPK0XJ@Ó0fLj(priv/templates/simplenode.reltool.config•TÑŽ£0 |ïWDH+í®"ªû‡û‹£‹Bârц%ÙêzÀ¿Ÿ -¤¥‹z¼eìqÆö„.œg¿vlú:£«RiOØaà3 >Ô5N•ÒYÅ™¯O Î:ѶåQà,D¯Û!%ÞÇ–ˆÃYÖuÖ)Ðj2<ýÈæø¢‰±Oð³ D…BS@„4¾T±Ãêê…¥4 ,Ýý_W?,[9ËU[IBëÝ4 h*PЦ7Ç´•æ2Zø#Í—‚tüˆ”ÂËß8rg„qCYþž¡öòÂ~:f]d—V}aC¡á¶n;åTÚî±*þ çï{B^•æü|Ï-ø·d4¾™úªœìµ=ºžšÁzÐ7ÂöÁË·ì°jhòÆUL‘×:êÚ:Ù…ø´`ZM:¨Ë5÷†ãW<™}Ùñ“ÙËj¿eì®ÞÈw»]VC¤Guç ºx#Î<µ^Ô|NéÆÕ{ê<1Ñ—®ENFf {¬@ ,ºb|¦å)Øb(†q“Ûâ’šèÜ÷æ„­*·˜hý¿&¢sÞQ×Dħ" LJð0 IÒž“‘ËF­¥Œè¦œñ€3Kù·àýÔä¸ë°ÙÊ5gHÊOþPK0XJ@fê({õ priv/templates/simplenode.runner½XmsÚFþ®_±!j»Ø~r†¶—©y„“é$)ÈÒW zw2vMþ{wOï@Ò¤3©flÄÝÞî³ï{<}ÒºáQK­¬§àœ8 ½gý:ÿñ%i—”³;xHDHÊîÏA«ö 6øiËš\‡½ÉÌíLúãé¬ÛŸ´íç~öãéw­“ðìěภ{uáöRªÇ½“t §ëM;)ÙιÓ~Ns5º‘ÞÁ|³ÞšÏáI{â%±Œ,À‡Ý3圪dàp°OÁþÅZð:ÐÎÛ.TLƒ'“pã)—9kGëúq´&2_ ù€ò¹ÒÊZßâ8qq6sžìSôðŃ1CfŸÈ[3+õt{N¢iáÎIÔØ“ˆE$$ áò¢˜Ô x´–;½˜Lg½ÉU{î{zm+;¥ZJ{RϘ ›§½¹Õ›LÝÙwˆÁVðø0È.ÆãÝõ§'ð‘À\£ø‚!Ò´îÖMO.ʸÎ# WÆ·˜~N–ºÙa¥ ÷aÚ™øüLÝÁo“Kw6¾˜þÚþ& û4‡,¡Jò4JöÔUªé‹hÁ—ÿ¦1FxFùUJ—êzwFÃ×ýË/׻§Tý “\õp®}ïkƒ¯Ó*fÁ ‰°à™p……kó5uìðbЛ¡aÛs¶”,†£?õ3]±ø<3¥y~d'ƒý•€FVc¢¼\ywhWNfÇø¢Ì[ìIüÐL6Y@Çœ}Z _ˆ[άÎhô[?]`F×™ÝOÃ.}9pJΟ‡{@‰ ب® ‘H<¤WiÆïí~¬ާ4u/âæ2ĨïzM5Y¡ƒµ¡±9ÏŽº½éht…ñPpo±¬.U–ˆX Ì_íQé쌃‹a÷@ÊÒ|a§5?U¿dÌîc!uC±Y¶–¼7[jÅ'ÙZ`ÐÙ%®Š#Qêà’Ušýn¯‚†i¦ŸŽá¤Dˆ¢~iÀ?=+¾|ieŽqÕ¯o=žÆC€iP®ã"|0ôÍf³8a"ež˜4wÔ<—ü¹âQr¿ízXz£íkÉØ+·»íJo)¢×áÃvÈ4-ŒbáçqíhŠgÜï®…ó÷Úó#àÁ´é3K¦ööýÞzL!Ù÷vó¤õîæóÖ­·¹…£Gœ}03ì³Gó=>h¼êW7‰Fîï°E=Õ¦ÿzç÷Ë·ýáÉ!ðמӿéôwp§ýAïKôy»ýJ¤?ü R¦<¿L•¢|P,ËXYìŸwk •'bpz¸ŽPm@šCÕa³â˜6ó[b&žRv1Z»kEIÎKp¨1U!CÝÏ*ÛÛË:Év êS˜¤k&ñÞ `ƒ­”fJIs9-ãHî3¥˜"cø­¬Qâ¾â³°+¥â9NZ VÌìŠ"ÎdÇ Îß?5œz—1âž7݄߱øâjûFè<­=u¸Ëf µï~]Oý/HkÝ•šúg:ëŽFõNWé—ԧʧ…épû 2·DÖ¶¶ÙçÌÇé9ª¦IÑ‚1GõCÌ}/Ä€û3Á¡&ï|Ï9{‘ßdÍ@\=¾vÇä Óév“,—¨à Pç>¾Æ°MïbFn* mñ¼HÂózï«NIÅF û8ÿþj4š¾î_õÚ9¸*\W³B_AñÉz˜‘7XWÉþJð®À^JËA~‡~i(^õ‡é~JxhX-"jpÝ&QÅÂx2º¤‘/9x‡ßâ]=€#…õþýûV«U)îZ©8”šÈpŒ¿àÎdç†óðõ ”ådW>»r‡zéÌÄHõªŽöãÙ÷ œ‰>îÍt¨ÞîRf”ÝåT‰ÝÕÜVÅ?Ýd‹î¸‘™·égz¡0q"cª–ÜLöÐ:ç¨Ô ÛØÙ™ Åp'ƒÖ¨J»i³0±“” ’dÑÝLcȦaøÎ¶?4 á!¡Hâ#·R×wRíåleˆH1^+oÉ΋„|4€¶Ô´·Y/ئUK5k{0ç·iM¬ù©6Уt“ –Y?µþPK0XJ@8&’¬M$priv/templates/simplenode.sys.config}޽‚0…÷>Å I·ª˜ˆºêŒ#! b!$`MË ’¾»—‘8p·ó÷å¦ œ#9%1 }/ëŠa°¹mR†ïyG*c´‘®*e†²n”@@z3Æ+¯IΉٖ|2e×?¨îKÿñD•m)oµ™Q'>=ŽXW P6ý ÍŸ×¾SV`îŽÑaz'‰Ëc|¶~©eÌX#Läð;ŽÈÏíšæ™cÙš±7PK0XJ@¬d(ÄA"priv/templates/simplenode.templateu‘˃ E÷ý c·†nLÚiš†Z†¡Cø÷‚Õú@7drïÜ30¸Ž_‚A‘ÝÒ”qZd¹ìc™û‡G'g™l¶,èÀCÉ¢‡ VkˆV¯ó`n”­¸ØÄ˜ˆá‘èÃ%hC7yK¦ßÎײLÌ8pý•CÚª#EšRÌÌ@7®Äûcä¦'…B‹-ýB íxÅ­DØÔ0§&á8ÒqEuãC‘tï1ƒ¾Ù ûŒ¿µb¬å€øPK0XJ@Wš8±!priv/templates/simplenode.vm.argsM‘MO1†ïû+ÆìEcÁøãE‚‹A àÇt»³Ðìî”´S!üw§xÐôÒvÞ÷y;Ó4…7Õ"Ø x…@¶Ä$£x³ßǃ)‡‡Þåm§+«—$i kkƒPY¥ñìLK@×(Z&™GÖ¿Š?ÂÑ÷ŒÊqŠ¡U¤–Ø"ñ=¨À6sèYŠ>Ç`*0,dô jÛÊ6hÖ–¼Ù`„>¯ŠFr‹”X©Ðp§<ÂÖð ´`¥“3Ñf«||BNÑ5:ÂÖ¶i@Q *Ü‚ò;Ò2‡ªô¢>v!¦÷áúè!-U ¡ÐèâÔ´%œ“^„'-\x«käÈ6OG‹qÿ{1yŸÎgpÕ½»9’æ[T5< €-¸@ÐZ?‘þ‡£Ñì+Ï'‹þpžO¡×M~PK0XJ@ žJûKÀ,priv/templates/simplenode.windows.runner.cmd}T]oÚ0}ϯ¸ŠäŠª$+}DŠÄÃèÔ½0mÝ2ñ…XMìÈ6° èoŸ8Á¡ty²}Ï9>÷Ùi4¥ÌiE3»!®­0;Ýš³óÙ†Vð͆M@ײÜ„ššŒlÎjªP`\an¤ú;n)‡‚çp Të]…ÌÁר0œ8()MÍ6RÁ—gˆ–¼ÒY „¼0ŠÉ;«Ó4¾&ábÐñ2BÞ7/޶©F½²2ÒcȲ ø~P¥æ?_Á•æR¬£÷g%+І*³BU¦Œzqiä MÆO£$4@–Cjk~ýf¶Ô%L­ç•Q¼TF¯ºk­ÚMpߣ{Ÿy#°æbµ;LH¨M–ã)Õžç¾Í¤ï8Y‘«‹ˆ%ð ÄdgYÌ…M«,c˜m¥í£ß†ˆ¸Âô!ª)N‡h6è¬/AY‡1…×ÈÆáîî3©\ -KìÔü¶„×Å×Ũ14/ÆPs±ƒ—÷±¶•Œ¢éNÓ­å`^HøíÖS pôyú O ÷ä,¼ÐÉßxŽZÓùâÙ*ö%!]ï\ÃJ­ö)þ±Ï‹1 a‹$9ÄsUR±mŸMÐ37}AçcH´;@’C¤ ·n.‚yÍ+ U[ 1<< dúm“Í•æÆM¤nš~ŒîÓx˜o0·3¶ý{¼Jz®+Ö@“7îtByßöÛÒmC¯•‡t7cŸ±í|ýÜ”¿ç¢rpÅl»9‚«ÿLJ¶ }åÏÿÚ§K&y ÿPK0XJ@­Ò.´Z/priv/templates/simplenode.windows.start_erl.cmd•TMkã0½ëW ¦i]ÚÞ_ZØî¡Ë¶GƒQâq*jKF£ í¿ßñGd'4t×Fï½yoFvÆj·ÕµR™§~iÏÚïþ4d'@¾f¿O胠õÔ’-¹«M)ç!8¨Œç«U2H=‡7òŽå%lÇ&g¡ìU„*8éÞ#Ò^.TV‰ÐÍ#,JªMÃéj%²ïd9½½º»º_â0.°ãàJÙ…yz%ñUôj‚ª¬†µœÁ›¬+©°º!Qz:ðÎAüTK5XôT“fâ¢4>ňÁüp0N¯í§÷ðûõöä¹K«my ÇZå]´…XNJ¦èSàYÜy̘úh 'iÈ.]Ï eŸážbðn¢²ú£Ìè5Î¥1ß›w†;7-*S õØ<ž´“JÜ JWS}¹Gßòø““­³•ÙÁìè¶-†ê÷'µªeCg„æéÃ6—£Èû/Ëû&鿇Y›}3^Ùä~á4JœØŒ ñˆã&ðð• \oú‹w%•q 8¥—b‡î€c/ÙT¼@ÃÂñ6Å;•íœüÖÏê/PK0XJ@“Ù–”\”priv/templates/simplesrv.erlµR]kÂ0}ï¯È‹!]·ù¶‡ Á Âġ̑Ùk ÆÄ%©8Jÿûçú±½ ÖZrsï9Ü{Ï *Éà<7úÄ“¢èßáìØ‰«Lã$5 O ý{[./âù2žô4^Ÿc— z=þûx–áË3¹±\IŸJ[Ó{Â…¯ŒeÚRÁå>º]·Ú~µ¯î§à’Û莠“‰ºaBDƒZhlt_†\n• ô},è—Ì‚/Ú¨Ä!\i Ñ Ý4yqmm•–¸ÂÇË€• µt.”Û‘³í—‹ÒÀ­ÖþëÜ ŒïùðP§¦>W{‚üKáÆ©yÓ9¼g`,At¬Õ …uòW8 GñA‡_2 ¼±˜NMú $Õöâ ‡éÄýÿ€)Íè›dFI×c¤ö®¬fSLg"Yy%qõñÙjÖÜBÉßšªéZ•Ltªé'PK0XJ@Zƒ`óJV!priv/templates/simplesrv.template«.K,ÊLLÊI-ÖQˆ®..*ËLÑQPÊ­,N-*K-Rª­Õãª.IÍ-ÈI,IÊg™©@uz©E9J ¢dýjˆÆÚZ° PPK0XJ@,ìX“§Œ getopt.beamPK0XJ@𪎠T Ðmustache.beamPK0XJ@F8{ GÙ  rebar.appPK0XJ@w·f)p wrebar.beamPK0XJ@x‰VS@(Ÿ0rebar_abnfc_compiler.beamPK0XJ@ZkÛ›Ü 6rebar_app_utils.beamPK0XJ@<¡| ã=rebar_appups.beamPK0XJ@>»BMÁðŽHrebar_asn1_compiler.beamPK0XJ@‘¬8£ô …Mrebar_base_compiler.beamPK0XJ@I“Ð| ^Vrebar_cleaner.beamPK0XJ@µ )»ÍÔ  Xrebar_config.beamPK0XJ@d©;ˆÌP&œ_rebar_core.beamPK0XJ@íHöõ è •vrebar_ct.beamPK0XJ@EsÝß¶´)µƒrebar_deps.beamPK0XJ@Ÿªnï0˜›rebar_edoc.beamPK0XJ@BvDS§< ´žrebar_erlc_compiler.beamPK0XJ@€KNw ¤ ‘±rebar_erlydtl_compiler.beamPK0XJ@»žv`´ Ûºrebar_escripter.beamPK0XJ@rs'@¿<3ªÁrebar_eunit.beamPK0XJ@÷­Zsx —ßrebar_file_utils.beamPK0XJ@ÑQò6GlÊçrebar_lfe_compiler.beamPK0XJ@²†œYTFìrebar_log.beamPK0XJ@Ë"íª Ëðrebar_neotoma_compiler.beamPK0XJ@†LüU@” ®ùrebar_otp_app.beamPK0XJ@3óÜ*rebar_port_compiler.beamPK0XJ@ƒe–›ð Grebar_protobuffs_compiler.beamPK0XJ@&0é ü #rebar_rel_utils.beamPK0XJ@%TЃ^Hl,rebar_reltool.beamPK0XJ@±œd‰Üú;rebar_require_vsn.beamPK0XJ@–h´{×´·?rebar_subdirs.beamPK0XJ@)¨2¾Drebar_templater.beamPK0XJ@HAÆñg ´"Urebar_upgrade.beamPK0XJ@ÐbÝH'̹`rebar_utils.beamPK0XJ@NZ%ú ltrebar_xref.beamPK0XJ@¿…jjD–5priv/templates/basicnif.cPK0XJ@éz›ï°priv/templates/basicnif.erlPK0XJ@ý+¡R‡ „ƒpriv/templates/basicnif.templatePK0XJ@Ȫ8’‚„priv/templates/ctsuite.erlPK0XJ@}Oê­P_c‰priv/templates/ctsuite.templatePK0XJ@ôävÞ ð‰priv/templates/simpleapp.app.srcPK0XJ@¤yE†\Ï!¤Špriv/templates/simpleapp.templatePK0XJ@À­À‰œk ?‹priv/templates/simpleapp_app.erlPK0XJ@‡O³Ì Œpriv/templates/simpleapp_sup.erlPK0XJ@Û"'»ŒÏopriv/templates/simplefsm.erlPK0XJ@¥DŒrFS!5priv/templates/simplefsm.templatePK0XJ@Þùƒ8[nºpriv/templates/simplemod.erlPK0XJ@þ6ÛöV’!Opriv/templates/simplemod.templatePK0XJ@+]çI;D"äpriv/templates/simplemod_tests.erlPK0XJ@DV^$_‘priv/templates/simplenode.erl.scriptPK0XJ@ì,?¯ˆÓ"÷“priv/templates/simplenode.nodetoolPK0XJ@Ó0fLj(¿™priv/templates/simplenode.reltool.configPK0XJ@fê({õ Ì›priv/templates/simplenode.runnerPK0XJ@8&’¬M$ÿ¢priv/templates/simplenode.sys.configPK0XJ@¬d(ÄA"í£priv/templates/simplenode.templatePK0XJ@Wš8±!ñ¤priv/templates/simplenode.vm.argsPK0XJ@ žJûKÀ,h¦priv/templates/simplenode.windows.runner.cmdPK0XJ@­Ò.´Z/ý¨priv/templates/simplenode.windows.start_erl.cmdPK0XJ@“Ù–”\”þªpriv/templates/simplesrv.erlPK0XJ@Zƒ`óJV!”¬priv/templates/simplesrv.templatePK;;N­rabbitmq-server-3.2.4/plugins-src/sockjs-erlang-wrapper/sockjs-erlang-git/Makefile0000644000000000000000000000276712305126066027011 0ustar rootrootREBAR=./rebar .PHONY: all clean distclean all: deps $(REBAR) compile deps: $(REBAR) get-deps clean:: $(REBAR) clean rm -rf priv/www distclean:: rm -rf deps priv ebin # **** serve **** .PHONY: serve SERVE_SCRIPT=./examples/cowboy_test_server.erl serve: @if [ -e .pidfile.pid ]; then \ kill `cat .pidfile.pid`; \ rm .pidfile.pid; \ fi @while [ 1 ]; do \ $(REBAR) compile && ( \ echo " [*] Running erlang"; \ $(SERVE_SCRIPT) & \ SRVPID=$$!; \ echo $$SRVPID > .pidfile.pid; \ echo " [*] Pid: $$SRVPID"; \ ); \ inotifywait -r -q -e modify src/*erl examples/*erl src/*hrl; \ test -e .pidfile.pid && kill `cat .pidfile.pid`; \ rm -f .pidfile.pid; \ sleep 0.1; \ done # **** dialyzer **** .dialyzer_generic.plt: dialyzer \ --build_plt \ --output_plt .dialyzer_generic.plt \ --apps erts kernel stdlib compiler sasl os_mon mnesia \ tools public_key crypto ssl .dialyzer_sockjs.plt: .dialyzer_generic.plt dialyzer \ --no_native \ --add_to_plt \ --plt .dialyzer_generic.plt \ --output_plt .dialyzer_sockjs.plt -r deps/*/ebin distclean:: rm -f .dialyzer_sockjs.plt dialyze: .dialyzer_sockjs.plt @dialyzer \ --plt .dialyzer_sockjs.plt \ --no_native \ --fullpath \ -Wrace_conditions \ -Werror_handling \ -Wunmatched_returns \ ebin .PHONY: xref xref: $(REBAR) xref | egrep -v unused # **** release **** # 1. Commit # 2. Bump version in "src/sockjs.app.src" # 3. git tag -s "vx.y.z" -m "Release vx.y.z" rabbitmq-server-3.2.4/plugins-src/sockjs-erlang-wrapper/sockjs-erlang-git/Changelog0000644000000000000000000000132712305126066027152 0ustar rootroot0.3.4 ===== * #41 - fix a traceback when websocket is too slow or too busy to prompty process incoming and outgoing data * #37 - make porting to new cowboy a tiny bit easier (allow 'method' to be a binary) 0.3.3 ===== * sockjs/sockjs-protocol#56 Fix for iOS 6 caching POSTs 0.3.0 ===== * Fixed {odd_info, heartbeat_triggered} exception (Isaev Ivan) * Changes to pass sockjs-protocol-0.3 * Fixed sockname badmatch (Egobrain) * Updated README * Introduced parametrized module API (to get multiplexer working). * Introduced Multiplexer example. * Fixed invalid catch in sockjs_json:decode (Isaev Ivan) * Bumped Cowboy version. * Specs were moved around to make R13 happy * Dropped milsultin support. rabbitmq-server-3.2.4/plugins-src/sockjs-erlang-wrapper/sockjs-erlang-git/examples/0000755000000000000000000000000012305126066027153 5ustar rootrootrabbitmq-server-3.2.4/plugins-src/sockjs-erlang-wrapper/sockjs-erlang-git/examples/multiplex/0000755000000000000000000000000012305126066031176 5ustar rootroot././@LongLink0000000000000000000000000000015000000000000011561 Lustar rootrootrabbitmq-server-3.2.4/plugins-src/sockjs-erlang-wrapper/sockjs-erlang-git/examples/multiplex/index.htmlrabbitmq-server-3.2.4/plugins-src/sockjs-erlang-wrapper/sockjs-erlang-git/examples/multiplex/index.h0000644000000000000000000000542312305126066032462 0ustar rootroot

    SockJS Multiplex example

    ././@LongLink0000000000000000000000000000015200000000000011563 Lustar rootrootrabbitmq-server-3.2.4/plugins-src/sockjs-erlang-wrapper/sockjs-erlang-git/examples/multiplex/multiplex.jsrabbitmq-server-3.2.4/plugins-src/sockjs-erlang-wrapper/sockjs-erlang-git/examples/multiplex/multipl0000644000000000000000000000421212305126066032606 0ustar rootroot// **** var DumbEventTarget = function() { this._listeners = {}; }; DumbEventTarget.prototype._ensure = function(type) { if(!(type in this._listeners)) this._listeners[type] = []; }; DumbEventTarget.prototype.addEventListener = function(type, listener) { this._ensure(type); this._listeners[type].push(listener); }; DumbEventTarget.prototype.emit = function(type) { this._ensure(type); var args = Array.prototype.slice.call(arguments, 1); if(this['on' + type]) this['on' + type].apply(this, args); for(var i=0; i < this._listeners[type].length; i++) { this._listeners[type][i].apply(this, args); } }; // **** var MultiplexedWebSocket = function(ws) { var that = this; this.ws = ws; this.channels = {}; this.ws.addEventListener('message', function(e) { var t = e.data.split(','); var type = t.shift(), name = t.shift(), payload = t.join(); if(!(name in that.channels)) { return; } var sub = that.channels[name]; switch(type) { case 'uns': delete that.channels[name]; sub.emit('close', {}); break; case 'msg': sub.emit('message', {data: payload}); break } }); }; MultiplexedWebSocket.prototype.channel = function(raw_name) { return this.channels[escape(raw_name)] = new Channel(this.ws, escape(raw_name), this.channels); }; var Channel = function(ws, name, channels) { DumbEventTarget.call(this); var that = this; this.ws = ws; this.name = name; this.channels = channels; var onopen = function() { that.ws.send('sub,' + that.name); that.emit('open'); }; if(ws.readyState > 0) { setTimeout(onopen, 0); } else { this.ws.addEventListener('open', onopen); } }; Channel.prototype = new DumbEventTarget() Channel.prototype.send = function(data) { this.ws.send('msg,' + this.name + ',' + data); }; Channel.prototype.close = function() { var that = this; this.ws.send('uns,' + this.name); delete this.channels[this.name]; setTimeout(function(){that.emit('close', {})},0); }; ././@LongLink0000000000000000000000000000016200000000000011564 Lustar rootrootrabbitmq-server-3.2.4/plugins-src/sockjs-erlang-wrapper/sockjs-erlang-git/examples/multiplex/cowboy_multiplex.erlrabbitmq-server-3.2.4/plugins-src/sockjs-erlang-wrapper/sockjs-erlang-git/examples/multiplex/cowboy_0000755000000000000000000000544512305126066032575 0ustar rootroot#!/usr/bin/env escript %%! -smp disable +A1 +K true -pa ebin deps/cowboy/ebin -input -module(cowboy_multiplex). -mode(compile). -export([main/1]). %% Cowboy callbacks -export([init/3, handle/2, terminate/2]). main(_) -> Port = 8081, application:start(sockjs), application:start(cowboy), MultiplexState = sockjs_multiplex:init_state( [{"ann", fun service_ann/3, []}, {"bob", fun service_bob/3, []}, {"carl", fun service_carl/3, []}]), SockjsState = sockjs_handler:init_state( <<"/multiplex">>, sockjs_multiplex, MultiplexState, []), VhostRoutes = [{[<<"multiplex">>, '...'], sockjs_cowboy_handler, SockjsState}, {'_', ?MODULE, []}], Routes = [{'_', VhostRoutes}], % any vhost io:format(" [*] Running at http://localhost:~p~n", [Port]), cowboy:start_listener(http, 100, cowboy_tcp_transport, [{port, Port}], cowboy_http_protocol, [{dispatch, Routes}]), receive _ -> ok end. %% -------------------------------------------------------------------------- init({_Any, http}, Req, []) -> {ok, Req, []}. handle(Req, State) -> {Path, Req1} = cowboy_http_req:path(Req), {ok, Req2} = case Path of [<<"multiplex.js">>] -> {ok, Data} = file:read_file("./examples/multiplex/multiplex.js"), cowboy_http_req:reply(200, [{<<"Content-Type">>, "application/javascript"}], Data, Req1); [] -> {ok, Data} = file:read_file("./examples/multiplex/index.html"), cowboy_http_req:reply(200, [{<<"Content-Type">>, "text/html"}], Data, Req1); _ -> cowboy_http_req:reply(404, [], <<"404 - Nothing here\n">>, Req1) end, {ok, Req2, State}. terminate(_Req, _State) -> ok. %% -------------------------------------------------------------------------- service_ann(Conn, init, State) -> Conn:send("Ann says hi!"), {ok, State}; service_ann(Conn, {recv, Data}, State) -> Conn:send(["Ann nods: ", Data]), {ok, State}; service_ann(_Conn, closed, State) -> {ok, State}. service_bob(Conn, init, State) -> Conn:send("Bob doesn't agree."), {ok, State}; service_bob(Conn, {recv, Data}, State) -> Conn:send(["Bob says no to: ", Data]), {ok, State}; service_bob(_Conn, closed, State) -> {ok, State}. service_carl(Conn, init, State) -> Conn:send("Carl says goodbye!"), Conn:close(), {ok, State}; service_carl(_Conn, _, State) -> {ok, State}. rabbitmq-server-3.2.4/plugins-src/sockjs-erlang-wrapper/sockjs-erlang-git/examples/cowboy_echo.erl0000755000000000000000000000274312305126066032170 0ustar rootroot#!/usr/bin/env escript %%! -smp disable +A1 +K true -pa ebin deps/cowboy/ebin -input -module(cowboy_echo). -mode(compile). -export([main/1]). %% Cowboy callbacks -export([init/3, handle/2, terminate/2]). main(_) -> Port = 8081, application:start(sockjs), application:start(cowboy), SockjsState = sockjs_handler:init_state( <<"/echo">>, fun service_echo/3, state, []), VhostRoutes = [{[<<"echo">>, '...'], sockjs_cowboy_handler, SockjsState}, {'_', ?MODULE, []}], Routes = [{'_', VhostRoutes}], % any vhost io:format(" [*] Running at http://localhost:~p~n", [Port]), cowboy:start_listener(http, 100, cowboy_tcp_transport, [{port, Port}], cowboy_http_protocol, [{dispatch, Routes}]), receive _ -> ok end. %% -------------------------------------------------------------------------- init({_Any, http}, Req, []) -> {ok, Req, []}. handle(Req, State) -> {ok, Data} = file:read_file("./examples/echo.html"), {ok, Req1} = cowboy_http_req:reply(200, [{<<"Content-Type">>, "text/html"}], Data, Req), {ok, Req1, State}. terminate(_Req, _State) -> ok. %% -------------------------------------------------------------------------- service_echo(_Conn, init, state) -> {ok, state}; service_echo(Conn, {recv, Data}, state) -> Conn:send(Data); service_echo(_Conn, closed, state) -> {ok, state}. ././@LongLink0000000000000000000000000000015200000000000011563 Lustar rootrootrabbitmq-server-3.2.4/plugins-src/sockjs-erlang-wrapper/sockjs-erlang-git/examples/cowboy_test_server.erlrabbitmq-server-3.2.4/plugins-src/sockjs-erlang-wrapper/sockjs-erlang-git/examples/cowboy_test_serve0000755000000000000000000000671112305126066032653 0ustar rootroot#!/usr/bin/env escript %%! -smp disable +A1 +K true -pa ebin deps/cowboy/ebin -input -module(cowboy_test_server). -mode(compile). -export([main/1]). %% Cowboy callbacks -export([init/3, handle/2, terminate/2]). main(_) -> Port = 8081, application:start(sockjs), application:start(cowboy), StateEcho = sockjs_handler:init_state( <<"/echo">>, fun service_echo/3, state, [{response_limit, 4096}]), StateClose = sockjs_handler:init_state( <<"/close">>, fun service_close/3, state, []), StateAmplify = sockjs_handler:init_state( <<"/amplify">>, fun service_amplify/3, state, []), StateBroadcast = sockjs_handler:init_state( <<"/broadcast">>, fun service_broadcast/3, state, []), StateDWSEcho = sockjs_handler:init_state( <<"/disabled_websocket_echo">>, fun service_echo/3, state, [{websocket, false}]), StateCNEcho = sockjs_handler:init_state( <<"/cookie_needed_echo">>, fun service_echo/3, state, [{cookie_needed, true}]), VRoutes = [{[<<"echo">>, '...'], sockjs_cowboy_handler, StateEcho}, {[<<"close">>, '...'], sockjs_cowboy_handler, StateClose}, {[<<"amplify">>, '...'], sockjs_cowboy_handler, StateAmplify}, {[<<"broadcast">>, '...'], sockjs_cowboy_handler, StateBroadcast}, {[<<"disabled_websocket_echo">>, '...'], sockjs_cowboy_handler, StateDWSEcho}, {[<<"cookie_needed_echo">>, '...'], sockjs_cowboy_handler, StateCNEcho}, {'_', ?MODULE, []}], Routes = [{'_', VRoutes}], % any vhost io:format(" [*] Running at http://localhost:~p~n", [Port]), cowboy:start_listener(http, 100, cowboy_tcp_transport, [{port, Port}], cowboy_http_protocol, [{dispatch, Routes}]), receive _ -> ok end. %% -------------------------------------------------------------------------- init({_Any, http}, Req, []) -> {ok, Req, []}. handle(Req, State) -> {ok, Req2} = cowboy_http_req:reply(404, [], <<"404 - Nothing here (via sockjs-erlang fallback)\n">>, Req), {ok, Req2, State}. terminate(_Req, _State) -> ok. %% -------------------------------------------------------------------------- service_echo(_Conn, init, state) -> {ok, state}; service_echo(Conn, {recv, Data}, state) -> Conn:send(Data); service_echo(_Conn, closed, state) -> {ok, state}. service_close(Conn, _, _State) -> Conn:close(3000, "Go away!"). service_amplify(Conn, {recv, Data}, _State) -> N0 = list_to_integer(binary_to_list(Data)), N = if N0 > 0 andalso N0 < 19 -> N0; true -> 1 end, Conn:send(list_to_binary( string:copies("x", round(math:pow(2, N))))); service_amplify(_Conn, _, _State) -> ok. service_broadcast(Conn, init, _State) -> case ets:info(broadcast_table, memory) of undefined -> ets:new(broadcast_table, [public, named_table]); _Any -> ok end, true = ets:insert(broadcast_table, {Conn}), ok; service_broadcast(Conn, closed, _State) -> true = ets:delete_object(broadcast_table, {Conn}), ok; service_broadcast(_Conn, {recv, Data}, _State) -> ets:foldl(fun({Conn1}, _Acc) -> Conn1:send(Data) end, [], broadcast_table), ok. rabbitmq-server-3.2.4/plugins-src/sockjs-erlang-wrapper/sockjs-erlang-git/examples/echo.html0000644000000000000000000000401712305126066030761 0ustar rootroot

    SockJS-erlang Echo example

    rabbitmq-server-3.2.4/plugins-src/sockjs-erlang-wrapper/sockjs-erlang-git/.done0000644000000000000000000000000012305126066026251 0ustar rootrootrabbitmq-server-3.2.4/plugins-src/sockjs-erlang-wrapper/sockjs-erlang-git/LICENSE-MIT-Mochiweb0000644000000000000000000000207712305126066030532 0ustar rootrootThis is the MIT license. Copyright (c) 2007 Mochi Media, Inc. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. rabbitmq-server-3.2.4/plugins-src/sockjs-erlang-wrapper/sockjs-erlang-git/rebar.config0000644000000000000000000000057312305126066027624 0ustar rootroot%% -*- erlang -*- %% This is the default `rebar.config` for SockJS-erlang. %% {erl_opts, [ %% fail_on_warning, bin_opt_info, warn_missing_spec, debug_info, warn_export_all ]}. {deps, [ {cowboy, ".*", {git, "git://github.com/extend/cowboy.git", "4fb2a6face6e7d6ff1dd34a02c3bd8b63d972624"}} ]}. rabbitmq-server-3.2.4/plugins-src/sockjs-erlang-wrapper/.srcdist_done0000644000000000000000000000000012305126066024461 0ustar rootrootrabbitmq-server-3.2.4/plugins-src/sockjs-erlang-wrapper/hash.mk0000644000000000000000000000003512305126066023264 0ustar rootrootUPSTREAM_SHORT_HASH:=3132eb9 rabbitmq-server-3.2.4/plugins-src/sockjs-erlang-wrapper/Makefile0000644000000000000000000000002712305126066023451 0ustar rootrootinclude ../umbrella.mk rabbitmq-server-3.2.4/plugins-src/sockjs-erlang-wrapper/package.mk0000644000000000000000000000123512305126066023737 0ustar rootrootAPP_NAME:=sockjs DEPS:=cowboy-wrapper UPSTREAM_GIT:=https://github.com/rabbitmq/sockjs-erlang.git UPSTREAM_REVISION:=3132eb920aea9abd5c5e65349331c32d8cfa961e # 0.3.4 RETAIN_ORIGINAL_VERSION:=true WRAPPER_PATCHES:=\ 0000-remove-spec-patch.diff \ 0001-a2b-b2a.diff \ 0002-parameterised-modules-r16a.diff ORIGINAL_APP_FILE:=$(CLONE_DIR)/src/$(APP_NAME).app.src DO_NOT_GENERATE_APP_FILE=true ERLC_OPTS:=$(ERLC_OPTS) -D no_specs define construct_app_commands cp $(CLONE_DIR)/LICENSE-* $(APP_DIR) rm $(APP_DIR)/ebin/pmod_pt.beam endef define package_rules $(CLONE_DIR)/ebin/sockjs_multiplex_channel.beam: $(CLONE_DIR)/ebin/pmod_pt.beam endef rabbitmq-server-3.2.4/plugins-src/sockjs-erlang-wrapper/0002-parameterised-modules-r16a.diff0000644000000000000000000003433012305126066030270 0ustar rootrootdiff --git a/src/pmod_pt.erl b/src/pmod_pt.erl new file mode 100644 index 0000000..db21974 --- /dev/null +++ b/src/pmod_pt.erl @@ -0,0 +1,461 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2013. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +-module(pmod_pt). +-export([parse_transform/2, + format_error/1]). + +%% Expand function definition forms of parameterized module. +%% The code is based on the code in sys_expand_pmod which used to be +%% included in the compiler, but details are different because +%% sys_pre_expand has not been run. In particular: +%% +%% * Record definitions are still present and must be handled. +%% +%% * (Syntatic) local calls may actually be calls to an imported +%% funtion or a BIF. It is a local call if and only if there +%% is a definition for the function in the module. +%% +%% * When we introduce the module parameters and 'THIS' in each +%% function, we must artificially use it to avoid a warning for +%% unused variables. +%% +%% * On the other hand, we don't have to worry about module_info/0,1 +%% because they have not been added yet. + +-record(pmod, {parameters, + defined + }). + +parse_transform(Forms0, _Options) -> + put(?MODULE, []), + Forms = transform(Forms0), + case erase(?MODULE) of + [] -> + Forms; + [_|_]=Errors -> + File = get_file(Forms), + {error,[{File,Errors}],[]} + end. + +format_error(extends_self) -> + "cannot extend from self"; +format_error(define_instance) -> + "defining instance function not allowed in parameterized module". + +add_error(Line, Error) -> + put(?MODULE, get(?MODULE) ++ [{Line,?MODULE,Error}]). + +get_file([{attribute,_,file,{File,_}}|_]) -> File; +get_file([_|T]) -> get_file(T). + +transform(Forms0) -> + Def = collect_defined(Forms0), + {Base,ModAs,Forms1} = attribs(Forms0, [], undefined, []), + {Mod,Ps0} = case ModAs of + {M0,P0} -> {M0,P0}; + M0 -> {M0,undefined} + end, + Forms2 = case Ps0 of + undefined -> + Forms1; + _ -> + pmod_expand(Forms1, Mod, Base, Ps0, Def) + end, + + %% Add new functions. + NewFs0 = maybe_extend(Base, Mod, Ps0), + NewExps = collect_defined(NewFs0), + Forms3 = add_attributes(Forms2, [{attribute,0,export,NewExps}]), + add_new_funcs(Forms3, NewFs0). + +pmod_expand(Forms0, Mod, Base, Ps0, Def) -> + Ps = if is_atom(Base) -> + ['BASE' | Ps0]; + true -> + Ps0 + end, + St0 = #pmod{parameters=Ps,defined=gb_sets:from_list(Def)}, + {Forms1,_} = forms(Forms0, St0), + Forms2 = update_exps(Forms1), + Forms3 = update_forms(Forms2), + NewFs0 = add_instance(Mod, Ps, []), + NewFs = ensure_new(Base, Ps0, NewFs0), + Forms = add_new_funcs(Forms3, NewFs), + NewExps = collect_defined(NewFs), + add_attributes(Forms, [{attribute,0,export,NewExps}]). + +add_attributes([{attribute,_,module,_}=F|Fs], Attrs) -> + [F|Attrs++Fs]; +add_attributes([F|Fs], Attrs) -> + [F|add_attributes(Fs, Attrs)]. + +add_new_funcs([{eof,_}|_]=Fs, NewFs) -> + NewFs ++ Fs; +add_new_funcs([F|Fs], Es) -> + [F|add_new_funcs(Fs, Es)]. + +maybe_extend([], _, _) -> + %% No 'extends' attribute. + []; +maybe_extend(Base, _Mod, undefined) -> + %% There is a an 'extends' attribute; the module is not parameterized. + Name = '$handle_undefined_function', + Args = [{var,0,'Func'},{var,0,'Args'}], + Body = [make_apply({atom,0,Base}, {var,0,'Func'}, {var,0,'Args'})], + F = {function,0,Name,2,[{clause,0,Args,[],Body}]}, + [F]; +maybe_extend(Base, Mod, Ps) -> + %% There is a an 'extends' attribute; the module is parameterized. + Name = '$handle_undefined_function', + Args = [{var,0,'Func'},{var,0,'Args'}], + DontCares = [{var,0,'_'} || _ <- Ps], + TuplePs = {tuple,0,[{atom,0,Mod},{var,0,'BaseVars'}|DontCares]}, + G = [{call,0,{atom,0,is_atom}, + [{call,0,{atom,0,element}, + [{integer,0,1},{var,0,'BaseVars'}]}]}], + FixedArgs = make_lists_rev([{var,0,'Rs'}, + {cons,0,{var,0,'BaseVars'},{nil,0}}]), + Body = [{'case',0,make_lists_rev([{var,0,'Args'}]), + [{clause,0,[{cons,0,TuplePs,{var,0,'Rs'}}],[G], + [make_apply({atom,0,Base}, {var,0,'Func'}, FixedArgs)]}, + {clause,0,[{var,0,'_'}],[], + [make_apply({atom,0,Base}, {var,0,'Func'}, {var,0,'Args'})]} + ]}], + F = {function,0,Name,2,[{clause,0,Args,[],Body}]}, + [F]. + +make_apply(M, F, A) -> + {call,0,{remote,0,{atom,0,erlang},{atom,0,apply}},[M,F,A]}. + +make_lists_rev(As) -> + {call,0,{remote,0,{atom,0,lists},{atom,0,reverse}},As}. + +ensure_new(Base, Ps, Fs) -> + case has_new(Fs) of + true -> + Fs; + false -> + add_new(Base, Ps, Fs) + end. + +has_new([{function,_L,new,_A,_Cs} | _Fs]) -> + true; +has_new([_ | Fs]) -> + has_new(Fs); +has_new([]) -> + false. + +add_new(Base, Ps, Fs) -> + Vs = [{var,0,V} || V <- Ps], + As = if is_atom(Base) -> + [{call,0,{remote,0,{atom,0,Base},{atom,0,new}},Vs} | Vs]; + true -> + Vs + end, + Body = [{call,0,{atom,0,instance},As}], + add_func(new, Vs, Body, Fs). + +add_instance(Mod, Ps, Fs) -> + Vs = [{var,0,V} || V <- Ps], + AbsMod = [{tuple,0,[{atom,0,Mod}|Vs]}], + add_func(instance, Vs, AbsMod, Fs). + +add_func(Name, Args, Body, Fs) -> + A = length(Args), + F = {function,0,Name,A,[{clause,0,Args,[],Body}]}, + [F|Fs]. + +collect_defined(Fs) -> + [{N,A} || {function,_,N,A,_} <- Fs]. + +attribs([{attribute,Line,module,{Mod,_}=ModAs}|T], Base, _, Acc) -> + attribs(T, Base, ModAs, [{attribute,Line,module,Mod}|Acc]); +attribs([{attribute,_,module,Mod}=H|T], Base, _, Acc) -> + attribs(T, Base, Mod, [H|Acc]); +attribs([{attribute,Line,extends,Base}|T], Base0, Ps, Acc) when is_atom(Base) -> + Mod = case Ps of + {Mod0,_} -> Mod0; + Mod0 -> Mod0 + end, + case Mod of + Base -> + add_error(Line, extends_self), + attribs(T, Base0, Ps, Acc); + _ -> + attribs(T, Base, Ps, Acc) + end; +attribs([H|T], Base, Ps, Acc) -> + attribs(T, Base, Ps, [H|Acc]); +attribs([], Base, Ps, Acc) -> + {Base,Ps,lists:reverse(Acc)}. + +%% This is extremely simplistic for now; all functions get an extra +%% parameter, whether they need it or not, except for static functions. + +update_function_name({F,A}) when F =/= new -> + {F,A+1}; +update_function_name(E) -> + E. + +update_forms([{function,L,N,A,Cs}|Fs]) when N =/= new -> + [{function,L,N,A+1,Cs}|update_forms(Fs)]; +update_forms([F|Fs]) -> + [F|update_forms(Fs)]; +update_forms([]) -> + []. + +update_exps([{attribute,Line,export,Es0}|T]) -> + Es = [update_function_name(E) || E <- Es0], + [{attribute,Line,export,Es}|update_exps(T)]; +update_exps([H|T]) -> + [H|update_exps(T)]; +update_exps([]) -> + []. + +%% Process the program forms. + +forms([F0|Fs0],St0) -> + {F1,St1} = form(F0,St0), + {Fs1,St2} = forms(Fs0,St1), + {[F1|Fs1],St2}; +forms([], St0) -> + {[], St0}. + +%% Only function definitions are of interest here. State is not updated. +form({function,Line,instance,_Arity,_Clauses}=F,St) -> + add_error(Line, define_instance), + {F,St}; +form({function,Line,Name0,Arity0,Clauses0},St) when Name0 =/= new -> + {Name,Arity,Clauses} = function(Name0, Arity0, Clauses0, St), + {{function,Line,Name,Arity,Clauses},St}; +%% Pass anything else through +form(F,St) -> {F,St}. + +function(Name, Arity, Clauses0, St) -> + Clauses1 = clauses(Clauses0,St), + {Name,Arity,Clauses1}. + +clauses([C|Cs],#pmod{parameters=Ps}=St) -> + {clause,L,H,G,B0} = clause(C,St), + T = {tuple,L,[{var,L,V} || V <- ['_'|Ps]]}, + B = [{match,L,{var,L,'_'},{var,L,V}} || V <- ['THIS'|Ps]] ++ B0, + [{clause,L,H++[{match,L,T,{var,L,'THIS'}}],G,B}|clauses(Cs,St)]; +clauses([],_St) -> []. + +clause({clause,Line,H,G,B0},St) -> + %% We never update H and G, so we will just copy them. + B1 = exprs(B0,St), + {clause,Line,H,G,B1}. + +pattern_grp([{bin_element,L1,E1,S1,T1} | Fs],St) -> + S2 = case S1 of + default -> + default; + _ -> + expr(S1,St) + end, + T2 = case T1 of + default -> + default; + _ -> + bit_types(T1) + end, + [{bin_element,L1,expr(E1,St),S2,T2} | pattern_grp(Fs,St)]; +pattern_grp([],_St) -> + []. + +bit_types([]) -> + []; +bit_types([Atom | Rest]) when is_atom(Atom) -> + [Atom | bit_types(Rest)]; +bit_types([{Atom, Integer} | Rest]) when is_atom(Atom), is_integer(Integer) -> + [{Atom, Integer} | bit_types(Rest)]. + +exprs([E0|Es],St) -> + E1 = expr(E0,St), + [E1|exprs(Es,St)]; +exprs([],_St) -> []. + +expr({var,_L,_V}=Var,_St) -> + Var; +expr({integer,_Line,_I}=Integer,_St) -> Integer; +expr({float,_Line,_F}=Float,_St) -> Float; +expr({atom,_Line,_A}=Atom,_St) -> Atom; +expr({string,_Line,_S}=String,_St) -> String; +expr({char,_Line,_C}=Char,_St) -> Char; +expr({nil,_Line}=Nil,_St) -> Nil; +expr({cons,Line,H0,T0},St) -> + H1 = expr(H0,St), + T1 = expr(T0,St), + {cons,Line,H1,T1}; +expr({lc,Line,E0,Qs0},St) -> + Qs1 = lc_bc_quals(Qs0,St), + E1 = expr(E0,St), + {lc,Line,E1,Qs1}; +expr({bc,Line,E0,Qs0},St) -> + Qs1 = lc_bc_quals(Qs0,St), + E1 = expr(E0,St), + {bc,Line,E1,Qs1}; +expr({tuple,Line,Es0},St) -> + Es1 = expr_list(Es0,St), + {tuple,Line,Es1}; +expr({record,Line,Name,Is0},St) -> + Is = record_fields(Is0,St), + {record,Line,Name,Is}; +expr({record,Line,E0,Name,Is0},St) -> + E = expr(E0,St), + Is = record_fields(Is0,St), + {record,Line,E,Name,Is}; +expr({record_field,Line,E0,Name,Key},St) -> + E = expr(E0,St), + {record_field,Line,E,Name,Key}; +expr({block,Line,Es0},St) -> + Es1 = exprs(Es0,St), + {block,Line,Es1}; +expr({'if',Line,Cs0},St) -> + Cs1 = icr_clauses(Cs0,St), + {'if',Line,Cs1}; +expr({'case',Line,E0,Cs0},St) -> + E1 = expr(E0,St), + Cs1 = icr_clauses(Cs0,St), + {'case',Line,E1,Cs1}; +expr({'receive',Line,Cs0},St) -> + Cs1 = icr_clauses(Cs0,St), + {'receive',Line,Cs1}; +expr({'receive',Line,Cs0,To0,ToEs0},St) -> + To1 = expr(To0,St), + ToEs1 = exprs(ToEs0,St), + Cs1 = icr_clauses(Cs0,St), + {'receive',Line,Cs1,To1,ToEs1}; +expr({'try',Line,Es0,Scs0,Ccs0,As0},St) -> + Es1 = exprs(Es0,St), + Scs1 = icr_clauses(Scs0,St), + Ccs1 = icr_clauses(Ccs0,St), + As1 = exprs(As0,St), + {'try',Line,Es1,Scs1,Ccs1,As1}; +expr({'fun',_,{function,_,_,_}}=ExtFun,_St) -> + ExtFun; +expr({'fun',Line,Body},St) -> + case Body of + {clauses,Cs0} -> + Cs1 = fun_clauses(Cs0,St), + {'fun',Line,{clauses,Cs1}}; + {function,F,A} = Function -> + {F1,A1} = update_function_name({F,A}), + if A1 =:= A -> + {'fun',Line,Function}; + true -> + %% Must rewrite local fun-name to a fun that does a + %% call with the extra THIS parameter. + As = make_vars(A, Line), + As1 = As ++ [{var,Line,'THIS'}], + Call = {call,Line,{atom,Line,F1},As1}, + Cs = [{clause,Line,As,[],[Call]}], + {'fun',Line,{clauses,Cs}} + end; + {function,_M,_F,_A} = Fun4 -> %This is an error in lint! + {'fun',Line,Fun4} + end; +expr({call,Lc,{atom,_,instance}=Name,As0},St) -> + %% All local functions 'instance(...)' are static by definition, + %% so they do not take a 'THIS' argument when called + As1 = expr_list(As0,St), + {call,Lc,Name,As1}; +expr({call,Lc,{atom,_,new}=Name,As0},St) -> + %% All local functions 'new(...)' are static by definition, + %% so they do not take a 'THIS' argument when called + As1 = expr_list(As0,St), + {call,Lc,Name,As1}; +expr({call,Lc,{atom,_Lf,F}=Atom,As0}, #pmod{defined=Def}=St) -> + As1 = expr_list(As0,St), + case gb_sets:is_member({F,length(As0)}, Def) of + false -> + %% BIF or imported function. + {call,Lc,Atom,As1}; + true -> + %% Local function call - needs THIS parameter. + {call,Lc,Atom,As1 ++ [{var,0,'THIS'}]} + end; +expr({call,Line,F0,As0},St) -> + %% Other function call + F1 = expr(F0,St), + As1 = expr_list(As0,St), + {call,Line,F1,As1}; +expr({'catch',Line,E0},St) -> + E1 = expr(E0,St), + {'catch',Line,E1}; +expr({match,Line,P,E0},St) -> + E1 = expr(E0,St), + {match,Line,P,E1}; +expr({bin,Line,Fs},St) -> + Fs2 = pattern_grp(Fs,St), + {bin,Line,Fs2}; +expr({op,Line,Op,A0},St) -> + A1 = expr(A0,St), + {op,Line,Op,A1}; +expr({op,Line,Op,L0,R0},St) -> + L1 = expr(L0,St), + R1 = expr(R0,St), + {op,Line,Op,L1,R1}; +%% The following are not allowed to occur anywhere! +expr({remote,Line,M0,F0},St) -> + M1 = expr(M0,St), + F1 = expr(F0,St), + {remote,Line,M1,F1}. + +expr_list([E0|Es],St) -> + E1 = expr(E0,St), + [E1|expr_list(Es,St)]; +expr_list([],_St) -> []. + +record_fields([{record_field,L,K,E0}|T],St) -> + E = expr(E0,St), + [{record_field,L,K,E}|record_fields(T,St)]; +record_fields([],_) -> []. + +icr_clauses([C0|Cs],St) -> + C1 = clause(C0,St), + [C1|icr_clauses(Cs,St)]; +icr_clauses([],_St) -> []. + +lc_bc_quals([{generate,Line,P,E0}|Qs],St) -> + E1 = expr(E0,St), + [{generate,Line,P,E1}|lc_bc_quals(Qs,St)]; +lc_bc_quals([{b_generate,Line,P,E0}|Qs],St) -> + E1 = expr(E0,St), + [{b_generate,Line,P,E1}|lc_bc_quals(Qs,St)]; +lc_bc_quals([E0|Qs],St) -> + E1 = expr(E0,St), + [E1|lc_bc_quals(Qs,St)]; +lc_bc_quals([],_St) -> []. + +fun_clauses([C0|Cs],St) -> + C1 = clause(C0,St), + [C1|fun_clauses(Cs,St)]; +fun_clauses([],_St) -> []. + +make_vars(N, L) -> + make_vars(1, N, L). + +make_vars(N, M, L) when N =< M -> + V = list_to_atom("X"++integer_to_list(N)), + [{var,L,V} | make_vars(N + 1, M, L)]; +make_vars(_, _, _) -> + []. diff --git a/src/sockjs_multiplex_channel.erl b/src/sockjs_multiplex_channel.erl index cbb8274..5afcfa3 100644 --- a/src/sockjs_multiplex_channel.erl +++ b/src/sockjs_multiplex_channel.erl @@ -1,3 +1,5 @@ +-compile({parse_transform,pmod_pt}). + -module(sockjs_multiplex_channel, [Conn, Topic]). -export([send/1, close/0, close/2, info/0]). rabbitmq-server-3.2.4/plugins-src/sockjs-erlang-wrapper/0000-remove-spec-patch.diff0000644000000000000000000010055112305126066026545 0ustar rootrootdiff --git a/src/mochijson2_fork.erl b/src/mochijson2_fork.erl index 355f068..a088d9d 100644 --- a/src/mochijson2_fork.erl +++ b/src/mochijson2_fork.erl @@ -91,17 +91,17 @@ -define(IS_WHITESPACE(C), (C =:= $\s orelse C =:= $\t orelse C =:= $\r orelse C =:= $\n)). --type(decoder_option() :: any()). --type(handler_option() :: any()). - --type(json_string() :: atom | binary()). --type(json_number() :: integer() | float()). --type(json_array() :: [json_term()]). --type(json_object() :: {struct, [{json_string(), json_term()}]}). --type(json_eep18_object() :: {[{json_string(), json_term()}]}). --type(json_iolist() :: {json, iolist()}). --type(json_term() :: json_string() | json_number() | json_array() | - json_object() | json_eep18_object() | json_iolist()). +%% -type(decoder_option() :: any()). +%% -type(handler_option() :: any()). + +%% -type(json_string() :: atom | binary()). +%% -type(json_number() :: integer() | float()). +%% -type(json_array() :: [json_term()]). +%% -type(json_object() :: {struct, [{json_string(), json_term()}]}). +%% -type(json_eep18_object() :: {[{json_string(), json_term()}]}). +%% -type(json_iolist() :: {json, iolist()}). +%% -type(json_term() :: json_string() | json_number() | json_array() | +%% json_object() | json_eep18_object() | json_iolist()). -record(encoder, {handler=null, utf8=false}). @@ -112,27 +112,27 @@ column=1, state=null}). --type(utf8_option() :: boolean()). --type(encoder_option() :: handler_option() | utf8_option()). --spec encoder([encoder_option()]) -> function(). +%% -type(utf8_option() :: boolean()). +%% -type(encoder_option() :: handler_option() | utf8_option()). +%% -spec encoder([encoder_option()]) -> function(). %% @doc Create an encoder/1 with the given options. %% Emit unicode as utf8 (default - false) encoder(Options) -> State = parse_encoder_options(Options, #encoder{}), fun (O) -> json_encode(O, State) end. --spec encode(json_term()) -> iolist(). +%% -spec encode(json_term()) -> iolist(). %% @doc Encode the given as JSON to an iolist. encode(Any) -> json_encode(Any, #encoder{}). --spec decoder([decoder_option()]) -> function(). +%% -spec decoder([decoder_option()]) -> function(). %% @doc Create a decoder/1 with the given options. decoder(Options) -> State = parse_decoder_options(Options, #decoder{}), fun (O) -> json_decode(O, State) end. --spec decode(iolist(), [{format, proplist | eep18 | struct}]) -> json_term(). +%% -spec decode(iolist(), [{format, proplist | eep18 | struct}]) -> json_term(). %% @doc Decode the given iolist to Erlang terms using the given object format %% for decoding, where proplist returns JSON objects as [{binary(), json_term()}] %% proplists, eep18 returns JSON objects as {[binary(), json_term()]}, and struct @@ -140,7 +140,7 @@ decoder(Options) -> decode(S, Options) -> json_decode(S, parse_decoder_options(Options, #decoder{})). --spec decode(iolist()) -> json_term(). +%% -spec decode(iolist()) -> json_term(). %% @doc Decode the given iolist to Erlang terms. decode(S) -> json_decode(S, #decoder{}). diff --git a/src/sockjs.erl b/src/sockjs.erl index 68163ca..98b1173 100644 --- a/src/sockjs.erl +++ b/src/sockjs.erl @@ -2,23 +2,23 @@ -export([send/2, close/1, close/3, info/1]). --type(conn() :: {sockjs_session, any()}). +%% -type(conn() :: {sockjs_session, any()}). %% Send data over a connection. --spec send(iodata(), conn()) -> ok. +%% -spec send(iodata(), conn()) -> ok. send(Data, Conn = {sockjs_session, _}) -> sockjs_session:send(Data, Conn). %% Initiate a close of a connection. --spec close(conn()) -> ok. +%% -spec close(conn()) -> ok. close(Conn) -> close(1000, "Normal closure", Conn). --spec close(non_neg_integer(), string(), conn()) -> ok. +%% -spec close(non_neg_integer(), string(), conn()) -> ok. close(Code, Reason, Conn = {sockjs_session, _}) -> sockjs_session:close(Code, Reason, Conn). --spec info(conn()) -> [{atom(), any()}]. +%% -spec info(conn()) -> [{atom(), any()}]. info(Conn = {sockjs_session, _}) -> sockjs_session:info(Conn). diff --git a/src/sockjs_action.erl b/src/sockjs_action.erl index 3f13beb..4310963 100644 --- a/src/sockjs_action.erl +++ b/src/sockjs_action.erl @@ -45,17 +45,17 @@ %% -------------------------------------------------------------------------- --spec welcome_screen(req(), headers(), service()) -> req(). +%% -spec welcome_screen(req(), headers(), service()) -> req(). welcome_screen(Req, Headers, _Service) -> H = [{"Content-Type", "text/plain; charset=UTF-8"}], sockjs_http:reply(200, H ++ Headers, "Welcome to SockJS!\n", Req). --spec options(req(), headers(), service()) -> req(). +%% -spec options(req(), headers(), service()) -> req(). options(Req, Headers, _Service) -> sockjs_http:reply(204, Headers, "", Req). --spec iframe(req(), headers(), service()) -> req(). +%% -spec iframe(req(), headers(), service()) -> req(). iframe(Req, Headers, #service{sockjs_url = SockjsUrl}) -> IFrame = io_lib:format(?IFRAME, [SockjsUrl]), MD5 = "\"" ++ binary_to_list(base64:encode(erlang:md5(IFrame))) ++ "\"", @@ -68,7 +68,7 @@ iframe(Req, Headers, #service{sockjs_url = SockjsUrl}) -> end. --spec info_test(req(), headers(), service()) -> req(). +%% -spec info_test(req(), headers(), service()) -> req(). info_test(Req, Headers, #service{websocket = Websocket, cookie_needed = CookieNeeded}) -> I = [{websocket, Websocket}, @@ -81,12 +81,12 @@ info_test(Req, Headers, #service{websocket = Websocket, %% -------------------------------------------------------------------------- --spec xhr_polling(req(), headers(), service(), session()) -> req(). +%% -spec xhr_polling(req(), headers(), service(), session()) -> req(). xhr_polling(Req, Headers, Service, Session) -> Req1 = chunk_start(Req, Headers), reply_loop(Req1, Session, 1, fun fmt_xhr/1, Service). --spec xhr_streaming(req(), headers(), service(), session()) -> req(). +%% -spec xhr_streaming(req(), headers(), service(), session()) -> req(). xhr_streaming(Req, Headers, Service = #service{response_limit = ResponseLimit}, Session) -> Req1 = chunk_start(Req, Headers), @@ -96,7 +96,7 @@ xhr_streaming(Req, Headers, Service = #service{response_limit = ResponseLimit}, fun fmt_xhr/1), reply_loop(Req2, Session, ResponseLimit, fun fmt_xhr/1, Service). --spec eventsource(req(), headers(), service(), session()) -> req(). +%% -spec eventsource(req(), headers(), service(), session()) -> req(). eventsource(Req, Headers, Service = #service{response_limit = ResponseLimit}, SessionId) -> Req1 = chunk_start(Req, Headers, "text/event-stream; charset=UTF-8"), @@ -104,7 +104,7 @@ eventsource(Req, Headers, Service = #service{response_limit = ResponseLimit}, reply_loop(Req2, SessionId, ResponseLimit, fun fmt_eventsource/1, Service). --spec htmlfile(req(), headers(), service(), session()) -> req(). +%% -spec htmlfile(req(), headers(), service(), session()) -> req(). htmlfile(Req, Headers, Service = #service{response_limit = ResponseLimit}, SessionId) -> S = fun (Req1, CB) -> @@ -119,7 +119,7 @@ htmlfile(Req, Headers, Service = #service{response_limit = ResponseLimit}, end, verify_callback(Req, S). --spec jsonp(req(), headers(), service(), session()) -> req(). +%% -spec jsonp(req(), headers(), service(), session()) -> req(). jsonp(Req, Headers, Service, SessionId) -> S = fun (Req1, CB) -> Req2 = chunk_start(Req1, Headers), @@ -139,7 +139,7 @@ verify_callback(Req, Success) -> %% -------------------------------------------------------------------------- --spec xhr_send(req(), headers(), service(), session()) -> req(). +%% -spec xhr_send(req(), headers(), service(), session()) -> req(). xhr_send(Req, Headers, _Service, Session) -> {Body, Req1} = sockjs_http:body(Req), case handle_recv(Req1, Body, Session) of @@ -150,7 +150,7 @@ xhr_send(Req, Headers, _Service, Session) -> sockjs_http:reply(204, H ++ Headers, "", Req1) end. --spec jsonp_send(req(), headers(), service(), session()) -> req(). +%% -spec jsonp_send(req(), headers(), service(), session()) -> req(). jsonp_send(Req, Headers, _Service, Session) -> {Body, Req1} = sockjs_http:body_qs(Req), case handle_recv(Req1, Body, Session) of @@ -236,21 +236,21 @@ chunk_end(Req) -> sockjs_http:chunk_end(Req). chunk_end(Req, Body, Fmt) -> Req1 = chunk(Req, Body, Fmt), chunk_end(Req1). --spec fmt_xhr(iodata()) -> iodata(). +%% -spec fmt_xhr(iodata()) -> iodata(). fmt_xhr(Body) -> [Body, "\n"]. --spec fmt_eventsource(iodata()) -> iodata(). +%% -spec fmt_eventsource(iodata()) -> iodata(). fmt_eventsource(Body) -> Escaped = sockjs_util:url_escape(binary_to_list(iolist_to_binary(Body)), "%\r\n\0"), %% $% must be first! [<<"data: ">>, Escaped, <<"\r\n\r\n">>]. --spec fmt_htmlfile(iodata()) -> iodata(). +%% -spec fmt_htmlfile(iodata()) -> iodata(). fmt_htmlfile(Body) -> Double = sockjs_json:encode(iolist_to_binary(Body)), [<<"\r\n">>]. --spec fmt_jsonp(iodata(), iodata()) -> iodata(). +%% -spec fmt_jsonp(iodata(), iodata()) -> iodata(). fmt_jsonp(Body, Callback) -> %% Yes, JSONed twice, there isn't a a better way, we must pass %% a string back, and the script, will be evaled() by the @@ -259,7 +259,7 @@ fmt_jsonp(Body, Callback) -> %% -------------------------------------------------------------------------- --spec websocket(req(), headers(), service()) -> req(). +%% -spec websocket(req(), headers(), service()) -> req(). websocket(Req, Headers, Service) -> {_Any, Req1, {R1, R2}} = sockjs_handler:is_valid_ws(Service, Req), case {R1, R2} of @@ -274,6 +274,6 @@ websocket(Req, Headers, Service) -> "This WebSocket request can't be handled.", Req1) end. --spec rawwebsocket(req(), headers(), service()) -> req(). +%% -spec rawwebsocket(req(), headers(), service()) -> req(). rawwebsocket(Req, Headers, Service) -> websocket(Req, Headers, Service). diff --git a/src/sockjs_app.erl b/src/sockjs_app.erl index 1b8e77c..54aceb6 100644 --- a/src/sockjs_app.erl +++ b/src/sockjs_app.erl @@ -4,11 +4,11 @@ -export([start/2, stop/1]). --spec start(_, _) -> {ok, pid()}. +%% -spec start(_, _) -> {ok, pid()}. start(_StartType, _StartArgs) -> sockjs_session:init(), sockjs_session_sup:start_link(). --spec stop(_) -> ok. +%% -spec stop(_) -> ok. stop(_State) -> ok. diff --git a/src/sockjs_filters.erl b/src/sockjs_filters.erl index 15aa8e3..fba43cc 100644 --- a/src/sockjs_filters.erl +++ b/src/sockjs_filters.erl @@ -9,7 +9,7 @@ %% -------------------------------------------------------------------------- --spec cache_for(req(), headers()) -> {headers(), req()}. +%% -spec cache_for(req(), headers()) -> {headers(), req()}. cache_for(Req, Headers) -> Expires = calendar:gregorian_seconds_to_datetime( calendar:datetime_to_gregorian_seconds( @@ -18,7 +18,7 @@ cache_for(Req, Headers) -> {"Expires", httpd_util:rfc1123_date(Expires)}], {H ++ Headers, Req}. --spec h_sid(req(), headers()) -> {headers(), req()}. +%% -spec h_sid(req(), headers()) -> {headers(), req()}. h_sid(Req, Headers) -> %% Some load balancers do sticky sessions, but only if there is %% a JSESSIONID cookie. If this cookie isn't yet set, we shall @@ -31,12 +31,12 @@ h_sid(Req, Headers) -> end, {H ++ Headers, Req2}. --spec h_no_cache(req(), headers()) -> {headers(), req()}. +%% -spec h_no_cache(req(), headers()) -> {headers(), req()}. h_no_cache(Req, Headers) -> H = [{"Cache-Control", "no-store, no-cache, must-revalidate, max-age=0"}], {H ++ Headers, Req}. --spec xhr_cors(req(), headers()) -> {headers(), req()}. +%% -spec xhr_cors(req(), headers()) -> {headers(), req()}. xhr_cors(Req, Headers) -> {OriginH, Req1} = sockjs_http:header('Origin', Req), Origin = case OriginH of @@ -54,15 +54,15 @@ xhr_cors(Req, Headers) -> {"Access-Control-Allow-Credentials", "true"}], {H ++ AllowHeaders ++ Headers, Req2}. --spec xhr_options_post(req(), headers()) -> {headers(), req()}. +%% -spec xhr_options_post(req(), headers()) -> {headers(), req()}. xhr_options_post(Req, Headers) -> xhr_options(Req, Headers, ["OPTIONS", "POST"]). --spec xhr_options_get(req(), headers()) -> {headers(), req()}. +%% -spec xhr_options_get(req(), headers()) -> {headers(), req()}. xhr_options_get(Req, Headers) -> xhr_options(Req, Headers, ["OPTIONS", "GET"]). --spec xhr_options(req(), headers(), list(string())) -> {headers(), req()}. +%% -spec xhr_options(req(), headers(), list(string())) -> {headers(), req()}. xhr_options(Req, Headers, Methods) -> H = [{"Access-Control-Allow-Methods", string:join(Methods, ", ")}, {"Access-Control-Max-Age", integer_to_list(?YEAR)}], diff --git a/src/sockjs_handler.erl b/src/sockjs_handler.erl index ebb3982..b706453 100644 --- a/src/sockjs_handler.erl +++ b/src/sockjs_handler.erl @@ -11,7 +11,7 @@ %% -------------------------------------------------------------------------- --spec init_state(binary(), callback(), any(), list(tuple())) -> service(). +%% -spec init_state(binary(), callback(), any(), list(tuple())) -> service(). init_state(Prefix, Callback, State, Options) -> #service{prefix = binary_to_list(Prefix), callback = Callback, @@ -34,7 +34,7 @@ init_state(Prefix, Callback, State, Options) -> %% -------------------------------------------------------------------------- --spec is_valid_ws(service(), req()) -> {boolean(), req(), tuple()}. +%% -spec is_valid_ws(service(), req()) -> {boolean(), req(), tuple()}. is_valid_ws(Service, Req) -> case get_action(Service, Req) of {{match, WS}, Req1} when WS =:= websocket orelse @@ -44,7 +44,7 @@ is_valid_ws(Service, Req) -> {false, Req1, {}} end. --spec valid_ws_request(service(), req()) -> {boolean(), req(), tuple()}. +%% -spec valid_ws_request(service(), req()) -> {boolean(), req(), tuple()}. valid_ws_request(_Service, Req) -> {R1, Req1} = valid_ws_upgrade(Req), {R2, Req2} = valid_ws_connection(Req1), @@ -73,7 +73,7 @@ valid_ws_connection(Req) -> {lists:member("upgrade", Vs), Req2} end. --spec get_action(service(), req()) -> {nomatch | {match, atom()}, req()}. +%% -spec get_action(service(), req()) -> {nomatch | {match, atom()}, req()}. get_action(Service, Req) -> {Dispatch, Req1} = dispatch_req(Service, Req), case Dispatch of @@ -93,20 +93,20 @@ strip_prefix(LongPath, Prefix) -> end. --type(dispatch_result() :: - nomatch | - {match, {send | recv | none , atom(), - server(), session(), list(atom())}} | - {bad_method, list(atom())}). +%% -type(dispatch_result() :: +%% nomatch | +%% {match, {send | recv | none , atom(), +%% server(), session(), list(atom())}} | +%% {bad_method, list(atom())}). --spec dispatch_req(service(), req()) -> {dispatch_result(), req()}. +%% -spec dispatch_req(service(), req()) -> {dispatch_result(), req()}. dispatch_req(#service{prefix = Prefix}, Req) -> {Method, Req1} = sockjs_http:method(Req), {LongPath, Req2} = sockjs_http:path(Req1), {ok, PathRemainder} = strip_prefix(LongPath, Prefix), {dispatch(Method, PathRemainder), Req2}. --spec dispatch(atom(), nonempty_string()) -> dispatch_result(). +%% -spec dispatch(atom(), nonempty_string()) -> dispatch_result(). dispatch(Method, Path) -> lists:foldl( fun ({Match, MethodFilters}, nomatch) -> @@ -163,7 +163,7 @@ re(Path, S) -> %% -------------------------------------------------------------------------- --spec handle_req(service(), req()) -> req(). +%% -spec handle_req(service(), req()) -> req(). handle_req(Service = #service{logger = Logger}, Req) -> Req0 = Logger(Service, Req, http), @@ -202,14 +202,14 @@ handle({match, {Type, Action, _Server, Session, Filters}}, Service, Req) -> %% -------------------------------------------------------------------------- --spec default_logger(service(), req(), websocket | http) -> req(). +%% -spec default_logger(service(), req(), websocket | http) -> req(). default_logger(_Service, Req, _Type) -> {LongPath, Req1} = sockjs_http:path(Req), {Method, Req2} = sockjs_http:method(Req1), io:format("~s ~s~n", [Method, LongPath]), Req2. --spec extract_info(req()) -> {info(), req()}. +%% -spec extract_info(req()) -> {info(), req()}. extract_info(Req) -> {Peer, Req0} = sockjs_http:peername(Req), {Sock, Req1} = sockjs_http:sockname(Req0), diff --git a/src/sockjs_http.erl b/src/sockjs_http.erl index 9754119..5cdf431 100644 --- a/src/sockjs_http.erl +++ b/src/sockjs_http.erl @@ -8,22 +8,22 @@ %% -------------------------------------------------------------------------- --spec path(req()) -> {string(), req()}. +%% -spec path(req()) -> {string(), req()}. path({cowboy, Req}) -> {Path, Req1} = cowboy_http_req:raw_path(Req), {binary_to_list(Path), {cowboy, Req1}}. --spec method(req()) -> {atom(), req()}. +%% -spec method(req()) -> {atom(), req()}. method({cowboy, Req}) -> {Method, Req1} = cowboy_http_req:method(Req), case is_binary(Method) of true -> {binary_to_atom(Method, utf8), {cowboy, Req1}}; false -> {Method, {cowboy, Req1}} end. --spec body(req()) -> {binary(), req()}. +%% -spec body(req()) -> {binary(), req()}. body({cowboy, Req}) -> {ok, Body, Req1} = cowboy_http_req:body(Req), {Body, {cowboy, Req1}}. --spec body_qs(req()) -> {binary(), req()}. +%% -spec body_qs(req()) -> {binary(), req()}. body_qs(Req) -> {H, Req1} = header('Content-Type', Req), case H of @@ -42,7 +42,7 @@ body_qs2({cowboy, Req}) -> {V, {cowboy, Req1}} end. --spec header(atom(), req()) -> {nonempty_string() | undefined, req()}. +%% -spec header(atom(), req()) -> {nonempty_string() | undefined, req()}. header(K, {cowboy, Req})-> {H, Req2} = cowboy_http_req:header(K, Req), {V, Req3} = case H of @@ -55,7 +55,7 @@ header(K, {cowboy, Req})-> _ -> {binary_to_list(V), {cowboy, Req3}} end. --spec jsessionid(req()) -> {nonempty_string() | undefined, req()}. +%% -spec jsessionid(req()) -> {nonempty_string() | undefined, req()}. jsessionid({cowboy, Req}) -> {C, Req2} = cowboy_http_req:cookie(<<"JSESSIONID">>, Req), case C of @@ -65,7 +65,7 @@ jsessionid({cowboy, Req}) -> {undefined, {cowboy, Req2}} end. --spec callback(req()) -> {nonempty_string() | undefined, req()}. +%% -spec callback(req()) -> {nonempty_string() | undefined, req()}. callback({cowboy, Req}) -> {CB, Req1} = cowboy_http_req:qs_val(<<"c">>, Req), case CB of @@ -73,12 +73,12 @@ callback({cowboy, Req}) -> _ -> {binary_to_list(CB), {cowboy, Req1}} end. --spec peername(req()) -> {{inet:ip_address(), non_neg_integer()}, req()}. +%% -spec peername(req()) -> {{inet:ip_address(), non_neg_integer()}, req()}. peername({cowboy, Req}) -> {P, Req1} = cowboy_http_req:peer(Req), {P, {cowboy, Req1}}. --spec sockname(req()) -> {{inet:ip_address(), non_neg_integer()}, req()}. +%% -spec sockname(req()) -> {{inet:ip_address(), non_neg_integer()}, req()}. sockname({cowboy, Req} = R) -> {ok, _T, S} = cowboy_http_req:transport(Req), %% Cowboy has peername(), but doesn't have sockname() equivalent. @@ -92,18 +92,18 @@ sockname({cowboy, Req} = R) -> %% -------------------------------------------------------------------------- --spec reply(non_neg_integer(), headers(), iodata(), req()) -> req(). +%% -spec reply(non_neg_integer(), headers(), iodata(), req()) -> req(). reply(Code, Headers, Body, {cowboy, Req}) -> Body1 = iolist_to_binary(Body), {ok, Req1} = cowboy_http_req:reply(Code, enbinary(Headers), Body1, Req), {cowboy, Req1}. --spec chunk_start(non_neg_integer(), headers(), req()) -> req(). +%% -spec chunk_start(non_neg_integer(), headers(), req()) -> req(). chunk_start(Code, Headers, {cowboy, Req}) -> {ok, Req1} = cowboy_http_req:chunked_reply(Code, enbinary(Headers), Req), {cowboy, Req1}. --spec chunk(iodata(), req()) -> {ok | error, req()}. +%% -spec chunk(iodata(), req()) -> {ok | error, req()}. chunk(Chunk, {cowboy, Req} = R) -> case cowboy_http_req:chunk(Chunk, Req) of ok -> {ok, R}; @@ -112,25 +112,25 @@ chunk(Chunk, {cowboy, Req} = R) -> %% should catch tco socket closure before. end. --spec chunk_end(req()) -> req(). +%% -spec chunk_end(req()) -> req(). chunk_end({cowboy, _Req} = R) -> R. enbinary(L) -> [{list_to_binary(K), list_to_binary(V)} || {K, V} <- L]. --spec hook_tcp_close(req()) -> req(). +%% -spec hook_tcp_close(req()) -> req(). hook_tcp_close(R = {cowboy, Req}) -> {ok, T, S} = cowboy_http_req:transport(Req), T:setopts(S,[{active,once}]), R. --spec unhook_tcp_close(req()) -> req(). +%% -spec unhook_tcp_close(req()) -> req(). unhook_tcp_close(R = {cowboy, Req}) -> {ok, T, S} = cowboy_http_req:transport(Req), T:setopts(S,[{active,false}]), R. --spec abruptly_kill(req()) -> req(). +%% -spec abruptly_kill(req()) -> req(). abruptly_kill(R = {cowboy, Req}) -> {ok, T, S} = cowboy_http_req:transport(Req), T:close(S), diff --git a/src/sockjs_internal.hrl b/src/sockjs_internal.hrl index 4f696d8..629b2fe 100644 --- a/src/sockjs_internal.hrl +++ b/src/sockjs_internal.hrl @@ -1,32 +1,32 @@ --type(req() :: {cowboy, any()}). +%% -type(req() :: {cowboy, any()}). --type(user_session() :: nonempty_string()). --type(emittable() :: init|closed|{recv, binary()}). --type(callback() :: fun((user_session(), emittable(), any()) -> ok)). --type(logger() :: fun((any(), req(), websocket|http) -> req())). +%% -type(user_session() :: nonempty_string()). +%% -type(emittable() :: init|closed|{recv, binary()}). +%% -type(callback() :: fun((user_session(), emittable(), any()) -> ok)). +%% -type(logger() :: fun((any(), req(), websocket|http) -> req())). --record(service, {prefix :: nonempty_string(), - callback :: callback(), - state :: any(), - sockjs_url :: nonempty_string(), - cookie_needed :: boolean(), - websocket :: boolean(), - disconnect_delay :: non_neg_integer(), - heartbeat_delay :: non_neg_integer(), - response_limit :: non_neg_integer(), - logger :: logger() +-record(service, {prefix , %% nonempty_string(), + callback , %% callback() + state , %% any() + sockjs_url , %% nonempty_string() + cookie_needed , %% boolean() + websocket , %% boolean() + disconnect_delay , %% non_neg_integer() + heartbeat_delay , %% non_neg_integer() + response_limit , %% non_neg_integer() + logger %% logger() }). --type(service() :: #service{}). +%% -type(service() :: #service{}). --type(headers() :: list({nonempty_string(), nonempty_string()})). --type(server() :: nonempty_string()). --type(session() :: nonempty_string()). +%% -type(headers() :: list({nonempty_string(), nonempty_string()})). +%% -type(server() :: nonempty_string()). +%% -type(session() :: nonempty_string()). --type(frame() :: {open, nil} | - {close, {non_neg_integer(), string()}} | - {data, list(iodata())} | - {heartbeat, nil} ). +%% -type(frame() :: {open, nil} | +%% {close, {non_neg_integer(), string()}} | +%% {data, list(iodata())} | +%% {heartbeat, nil} ). --type(info() :: [{atom(), any()}]). +%% -type(info() :: [{atom(), any()}]). diff --git a/src/sockjs_json.erl b/src/sockjs_json.erl index e61f4b9..d3dae20 100644 --- a/src/sockjs_json.erl +++ b/src/sockjs_json.erl @@ -4,11 +4,11 @@ %% -------------------------------------------------------------------------- --spec encode(any()) -> iodata(). +%% -spec encode(any()) -> iodata(). encode(Thing) -> mochijson2_fork:encode(Thing). --spec decode(iodata()) -> {ok, any()} | {error, any()}. +%% -spec decode(iodata()) -> {ok, any()} | {error, any()}. decode(Encoded) -> try mochijson2_fork:decode(Encoded) of V -> {ok, V} diff --git a/src/sockjs_session.erl b/src/sockjs_session.erl index 66c5df0..7e4ae00 100644 --- a/src/sockjs_session.erl +++ b/src/sockjs_session.erl @@ -11,39 +11,39 @@ handle_cast/2]). -include("sockjs_internal.hrl"). --type(handle() :: {?MODULE, {pid(), info()}}). - --record(session, {id :: session(), - outbound_queue = queue:new() :: queue(), - response_pid :: pid(), - disconnect_tref :: reference(), - disconnect_delay = 5000 :: non_neg_integer(), - heartbeat_tref :: reference() | triggered, - heartbeat_delay = 25000 :: non_neg_integer(), - ready_state = connecting :: connecting | open | closed, - close_msg :: {non_neg_integer(), string()}, +%% -type(handle() :: {?MODULE, {pid(), info()}}). + +-record(session, {id , %% session(), + outbound_queue = queue:new() , %% queue() + response_pid , %% pid() + disconnect_tref , %% reference() + disconnect_delay = 5000 , %% non_neg_integer() + heartbeat_tref , %% reference() | triggered + heartbeat_delay = 25000 , %% non_neg_integer() + ready_state = connecting , %% connecting | open | closed + close_msg , %% {non_neg_integer(), string()} callback, state, - handle :: handle() + handle %% handle() }). -define(ETS, sockjs_table). --type(session_or_undefined() :: session() | undefined). --type(session_or_pid() :: session() | pid()). +%% -type(session_or_undefined() :: session() | undefined). +%% -type(session_or_pid() :: session() | pid()). %% -------------------------------------------------------------------------- --spec init() -> ok. +%% -spec init() -> ok. init() -> _ = ets:new(?ETS, [public, named_table]), ok. --spec start_link(session_or_undefined(), service(), info()) -> {ok, pid()}. +%% -spec start_link(session_or_undefined(), service(), info()) -> {ok, pid()}. start_link(SessionId, Service, Info) -> gen_server:start_link(?MODULE, {SessionId, Service, Info}, []). --spec maybe_create(session_or_undefined(), service(), info()) -> pid(). +%% -spec maybe_create(session_or_undefined(), service(), info()) -> pid(). maybe_create(SessionId, Service, Info) -> case ets:lookup(?ETS, SessionId) of [] -> {ok, SPid} = sockjs_session_sup:start_child( @@ -53,7 +53,7 @@ maybe_create(SessionId, Service, Info) -> end. --spec received(list(iodata()), session_or_pid()) -> ok. +%% -spec received(list(iodata()), session_or_pid()) -> ok. received(Messages, SessionPid) when is_pid(SessionPid) -> case gen_server:call(SessionPid, {received, Messages}, infinity) of ok -> ok; @@ -63,27 +63,27 @@ received(Messages, SessionPid) when is_pid(SessionPid) -> received(Messages, SessionId) -> received(Messages, spid(SessionId)). --spec send(iodata(), handle()) -> ok. +%% -spec send(iodata(), handle()) -> ok. send(Data, {?MODULE, {SPid, _}}) -> gen_server:cast(SPid, {send, Data}), ok. --spec close(non_neg_integer(), string(), handle()) -> ok. +%% -spec close(non_neg_integer(), string(), handle()) -> ok. close(Code, Reason, {?MODULE, {SPid, _}}) -> gen_server:cast(SPid, {close, Code, Reason}), ok. --spec info(handle()) -> info(). +%% -spec info(handle()) -> info(). info({?MODULE, {_SPid, Info}}) -> Info. --spec reply(session_or_pid()) -> - wait | session_in_use | {ok | close, frame()}. +%% -spec reply(session_or_pid()) -> +%% wait | session_in_use | {ok | close, frame()}. reply(Session) -> reply(Session, true). --spec reply(session_or_pid(), boolean()) -> - wait | session_in_use | {ok | close, frame()}. +%% -spec reply(session_or_pid(), boolean()) -> +%% wait | session_in_use | {ok | close, frame()}. reply(SessionPid, Multiple) when is_pid(SessionPid) -> gen_server:call(SessionPid, {reply, self(), Multiple}, infinity); reply(SessionId, Multiple) -> @@ -154,7 +154,7 @@ unmark_waiting(RPid, State = #session{response_pid = Pid, when Pid =/= undefined andalso Pid =/= RPid -> State. --spec emit(emittable(), #session{}) -> #session{}. +%% -spec emit(emittable(), #session{}) -> #session{}. emit(What, State = #session{callback = Callback, state = UserState, handle = Handle}) -> @@ -175,7 +175,7 @@ emit(What, State = #session{callback = Callback, %% -------------------------------------------------------------------------- --spec init({session_or_undefined(), service(), info()}) -> {ok, #session{}}. +%% -spec init({session_or_undefined(), service(), info()}) -> {ok, #session{}}. init({SessionId, #service{callback = Callback, state = UserState, disconnect_delay = DisconnectDelay, diff --git a/src/sockjs_session_sup.erl b/src/sockjs_session_sup.erl index 4197ce3..71c7ff4 100644 --- a/src/sockjs_session_sup.erl +++ b/src/sockjs_session_sup.erl @@ -7,7 +7,7 @@ %% -------------------------------------------------------------------------- --spec start_link() -> ignore | {'ok', pid()} | {'error', any()}. +%% -spec start_link() -> ignore | {'ok', pid()} | {'error', any()}. start_link() -> supervisor:start_link({local, ?MODULE}, ?MODULE, []). diff --git a/src/sockjs_util.erl b/src/sockjs_util.erl index be3f972..9b9969d 100644 --- a/src/sockjs_util.erl +++ b/src/sockjs_util.erl @@ -8,7 +8,7 @@ %% -------------------------------------------------------------------------- --spec rand32() -> non_neg_integer(). +%% -spec rand32() -> non_neg_integer(). rand32() -> case get(random_seeded) of undefined -> @@ -21,7 +21,7 @@ rand32() -> random:uniform(erlang:trunc(math:pow(2,32)))-1. --spec encode_frame(frame()) -> iodata(). +%% -spec encode_frame(frame()) -> iodata(). encode_frame({open, nil}) -> <<"o">>; encode_frame({close, {Code, Reason}}) -> @@ -34,7 +34,7 @@ encode_frame({heartbeat, nil}) -> <<"h">>. --spec url_escape(string(), string()) -> iolist(). +%% -spec url_escape(string(), string()) -> iolist(). url_escape(Str, Chars) -> [case lists:member(Char, Chars) of true -> hex(Char); diff --git a/src/sockjs_ws_handler.erl b/src/sockjs_ws_handler.erl index bcf463d..c011c89 100644 --- a/src/sockjs_ws_handler.erl +++ b/src/sockjs_ws_handler.erl @@ -6,7 +6,7 @@ %% -------------------------------------------------------------------------- --spec received(websocket|rawwebsocket, pid(), binary()) -> ok | shutdown. +%% -spec received(websocket|rawwebsocket, pid(), binary()) -> ok | shutdown. %% Ignore empty received(_RawWebsocket, _SessionPid, <<>>) -> ok; @@ -30,7 +30,7 @@ session_received(Messages, SessionPid) -> no_session -> shutdown end. --spec reply(websocket|rawwebsocket, pid()) -> {close|open, binary()} | wait. +%% -spec reply(websocket|rawwebsocket, pid()) -> {close|open, binary()} | wait. reply(websocket, SessionPid) -> case sockjs_session:reply(SessionPid) of {W, Frame} when W =:= ok orelse W =:= close-> @@ -52,7 +52,7 @@ reply(rawwebsocket, SessionPid) -> wait end. --spec close(websocket|rawwebsocket, pid()) -> ok. +%% -spec close(websocket|rawwebsocket, pid()) -> ok. close(_RawWebsocket, SessionPid) -> SessionPid ! force_shutdown, ok. rabbitmq-server-3.2.4/plugins-src/sockjs-erlang-wrapper/0001-a2b-b2a.diff0000644000000000000000000000212512305126066024330 0ustar rootrootdiff --git a/src/sockjs_http.erl b/src/sockjs_http.erl index 5cdf431..837b64f 100644 --- a/src/sockjs_http.erl +++ b/src/sockjs_http.erl @@ -15,7 +15,7 @@ path({cowboy, Req}) -> {Path, Req1} = cowboy_http_req:raw_path(Req), %% -spec method(req()) -> {atom(), req()}. method({cowboy, Req}) -> {Method, Req1} = cowboy_http_req:method(Req), case is_binary(Method) of - true -> {binary_to_atom(Method, utf8), {cowboy, Req1}}; + true -> {list_to_atom(binary_to_list(Method)), {cowboy, Req1}}; false -> {Method, {cowboy, Req1}} end. @@ -47,7 +47,7 @@ header(K, {cowboy, Req})-> {H, Req2} = cowboy_http_req:header(K, Req), {V, Req3} = case H of undefined -> - cowboy_http_req:header(atom_to_binary(K, utf8), Req2); + cowboy_http_req:header(list_to_binary(atom_to_list(K)), Req2); _ -> {H, Req2} end, case V of rabbitmq-server-3.2.4/plugins-src/rabbitmq-shovel/0000755000000000000000000000000012305126066020671 5ustar rootrootrabbitmq-server-3.2.4/plugins-src/rabbitmq-shovel/generate_deps0000644000000000000000000000444712305126066023432 0ustar rootroot#!/usr/bin/env escript %% -*- erlang -*- -mode(compile). main([IncludeDir, ErlDir, EbinDir, TargetFile]) -> ErlDirContents = filelib:wildcard("*.erl", ErlDir), ErlFiles = [filename:join(ErlDir, FileName) || FileName <- ErlDirContents], Modules = sets:from_list( [list_to_atom(filename:basename(FileName, ".erl")) || FileName <- ErlDirContents]), Headers = sets:from_list( [filename:join(IncludeDir, FileName) || FileName <- filelib:wildcard("*.hrl", IncludeDir)]), Deps = lists:foldl( fun (Path, Deps1) -> dict:store(Path, detect_deps(IncludeDir, EbinDir, Modules, Headers, Path), Deps1) end, dict:new(), ErlFiles), {ok, Hdl} = file:open(TargetFile, [write, delayed_write]), dict:fold( fun (_Path, [], ok) -> ok; (Path, Dep, ok) -> Module = filename:basename(Path, ".erl"), ok = file:write(Hdl, [EbinDir, "/", Module, ".beam: ", Path]), ok = sets:fold(fun (E, ok) -> file:write(Hdl, [" ", E]) end, ok, Dep), file:write(Hdl, ["\n"]) end, ok, Deps), ok = file:write(Hdl, [TargetFile, ": ", escript:script_name(), "\n"]), ok = file:sync(Hdl), ok = file:close(Hdl). detect_deps(IncludeDir, EbinDir, Modules, Headers, Path) -> {ok, Forms} = epp:parse_file(Path, [IncludeDir], [{use_specs, true}]), lists:foldl( fun ({attribute, _LineNumber, Attribute, Behaviour}, Deps) when Attribute =:= behaviour orelse Attribute =:= behavior -> case sets:is_element(Behaviour, Modules) of true -> sets:add_element( [EbinDir, "/", atom_to_list(Behaviour), ".beam"], Deps); false -> Deps end; ({attribute, _LineNumber, file, {FileName, _LineNumber1}}, Deps) -> case sets:is_element(FileName, Headers) of true -> sets:add_element(FileName, Deps); false -> Deps end; (_Form, Deps) -> Deps end, sets:new(), Forms). rabbitmq-server-3.2.4/plugins-src/rabbitmq-shovel/src/0000755000000000000000000000000012305126066021460 5ustar rootrootrabbitmq-server-3.2.4/plugins-src/rabbitmq-shovel/src/rabbit_shovel.erl0000644000000000000000000000160612305126066025012 0ustar rootroot%% The contents of this file are subject to the Mozilla Public License %% Version 1.1 (the "License"); you may not use this file except in %% compliance with the License. You may obtain a copy of the License %% at http://www.mozilla.org/MPL/ %% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See %% the License for the specific language governing rights and %% limitations under the License. %% %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is GoPivotal, Inc. %% Copyright (c) 2007-2013 GoPivotal, Inc. All rights reserved. %% -module(rabbit_shovel). -export([start/0, stop/0, start/2, stop/1]). start() -> rabbit_shovel_sup:start_link(), ok. stop() -> ok. start(normal, []) -> rabbit_shovel_sup:start_link(). stop(_State) -> ok. rabbitmq-server-3.2.4/plugins-src/rabbitmq-shovel/src/rabbit_shovel_worker.erl0000644000000000000000000002350112305126066026401 0ustar rootroot%% The contents of this file are subject to the Mozilla Public License %% Version 1.1 (the "License"); you may not use this file except in %% compliance with the License. You may obtain a copy of the License %% at http://www.mozilla.org/MPL/ %% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See %% the License for the specific language governing rights and %% limitations under the License. %% %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is GoPivotal, Inc. %% Copyright (c) 2007-2013 GoPivotal, Inc. All rights reserved. %% -module(rabbit_shovel_worker). -behaviour(gen_server2). -export([start_link/2]). -export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]). -include_lib("amqp_client/include/amqp_client.hrl"). -include("rabbit_shovel.hrl"). -define(MAX_CONNECTION_CLOSE_TIMEOUT, 10000). -record(state, {inbound_conn, inbound_ch, outbound_conn, outbound_ch, name, config, blocked, msg_buf, inbound_params, outbound_params, unacked}). start_link(Name, Config) -> ok = rabbit_shovel_status:report(Name, starting), gen_server2:start_link(?MODULE, [Name, Config], []). %%--------------------------- %% Gen Server Implementation %%--------------------------- init([Name, Config]) -> gen_server2:cast(self(), init), {ok, Shovel} = rabbit_shovel_config:parse(Name, Config), {ok, #state{name = Name, config = Shovel}}. handle_call(_Msg, _From, State) -> {noreply, State}. handle_cast(init, State = #state{config = Config}) -> %% TODO when we move to minimum R13B01: %% random:seed(now()), {A, B, C} = now(), random:seed(A, B, C), #shovel{sources = Sources, destinations = Destinations} = Config, {InboundConn, InboundChan, InboundParams} = make_conn_and_chan(Sources#endpoint.amqp_params), {OutboundConn, OutboundChan, OutboundParams} = make_conn_and_chan(Destinations#endpoint.amqp_params), %% Don't trap exits until we have established connections so that %% if we try to shut down while waiting for a connection to be %% established then we don't block process_flag(trap_exit, true), create_resources(InboundChan, Sources#endpoint.resource_declarations), create_resources(OutboundChan, Destinations#endpoint.resource_declarations), NoAck = Config#shovel.ack_mode =:= no_ack, case NoAck of false -> Prefetch = Config#shovel.prefetch_count, #'basic.qos_ok'{} = amqp_channel:call( InboundChan, #'basic.qos'{prefetch_count = Prefetch}); true -> ok end, ok = amqp_channel:register_flow_handler(OutboundChan, self()), case Config#shovel.ack_mode of on_confirm -> #'confirm.select_ok'{} = amqp_channel:call(OutboundChan, #'confirm.select'{}), ok = amqp_channel:register_confirm_handler(OutboundChan, self()); _ -> ok end, #'basic.consume_ok'{} = amqp_channel:subscribe( InboundChan, #'basic.consume'{queue = Config#shovel.queue, no_ack = NoAck}, self()), State1 = State#state{inbound_conn = InboundConn, inbound_ch = InboundChan, outbound_conn = OutboundConn, outbound_ch = OutboundChan, blocked = false, msg_buf = queue:new(), inbound_params = InboundParams, outbound_params = OutboundParams, unacked = gb_trees:empty()}, ok = report_status(running, State1), {noreply, State1}. handle_info(#'basic.consume_ok'{}, State) -> {noreply, State}; handle_info({#'basic.deliver'{delivery_tag = Tag, exchange = Exchange, routing_key = RoutingKey}, Msg = #amqp_msg{props = Props = #'P_basic'{}}}, State = #state{config = Config}) -> Method = #'basic.publish'{exchange = Exchange, routing_key = RoutingKey}, Method1 = (Config#shovel.publish_fields)(Method), Msg1 = Msg#amqp_msg{props = (Config#shovel.publish_properties)(Props)}, {noreply, publish(Tag, Method1, Msg1, State)}; handle_info(#'channel.flow'{active = true}, State = #state{inbound_ch = InboundChan}) -> ok = report_status(running, State), State1 = drain_buffer(State#state{blocked = false}), ok = case State1#state.blocked of true -> report_status(blocked, State); false -> channel_flow(InboundChan, true) end, {noreply, State1}; handle_info(#'channel.flow'{active = false}, State = #state{inbound_ch = InboundChan}) -> ok = report_status(blocked, State), ok = channel_flow(InboundChan, false), {noreply, State#state{blocked = true}}; handle_info(#'basic.ack'{delivery_tag = Seq, multiple = Multiple}, State = #state{config = #shovel{ack_mode = on_confirm}}) -> {noreply, confirm_to_inbound( fun (DTag, Multiple) -> #'basic.ack'{delivery_tag = DTag, multiple = Multiple} end, Seq, Multiple, State)}; handle_info(#'basic.nack'{delivery_tag = Seq, multiple = Multiple}, State = #state{config = #shovel{ack_mode = on_confirm}}) -> {noreply, confirm_to_inbound( fun (DTag, Multiple) -> #'basic.nack'{delivery_tag = DTag, multiple = Multiple} end, Seq, Multiple, State)}; handle_info(#'basic.cancel'{}, State = #state{name = Name}) -> rabbit_log:warning("Shovel ~p received 'basic.cancel' from the broker~n", [Name]), {stop, {shutdown, restart}, State}; handle_info({'EXIT', InboundConn, Reason}, State = #state{inbound_conn = InboundConn}) -> {stop, {inbound_conn_died, Reason}, State}; handle_info({'EXIT', OutboundConn, Reason}, State = #state{outbound_conn = OutboundConn}) -> {stop, {outbound_conn_died, Reason}, State}. terminate(Reason, #state{inbound_conn = undefined, inbound_ch = undefined, outbound_conn = undefined, outbound_ch = undefined, name = Name}) -> rabbit_shovel_status:report(Name, {terminated, Reason}), ok; terminate(Reason, State) -> catch amqp_connection:close(State#state.inbound_conn, ?MAX_CONNECTION_CLOSE_TIMEOUT), catch amqp_connection:close(State#state.outbound_conn, ?MAX_CONNECTION_CLOSE_TIMEOUT), rabbit_shovel_status:report(State#state.name, {terminated, Reason}), ok. code_change(_OldVsn, State, _Extra) -> {ok, State}. %%--------------------------- %% Helpers %%--------------------------- confirm_to_inbound(MsgCtr, Seq, Multiple, State = #state{inbound_ch = InboundChan, unacked = Unacked}) -> ok = amqp_channel:cast( InboundChan, MsgCtr(gb_trees:get(Seq, Unacked), Multiple)), Unacked1 = remove_delivery_tags(Seq, Multiple, Unacked), State#state{unacked = Unacked1}. remove_delivery_tags(Seq, false, Unacked) -> gb_trees:delete(Seq, Unacked); remove_delivery_tags(Seq, true, Unacked) -> case gb_trees:is_empty(Unacked) of true -> Unacked; false -> {Smallest, _Val, Unacked1} = gb_trees:take_smallest(Unacked), case Smallest > Seq of true -> Unacked; false -> remove_delivery_tags(Seq, true, Unacked1) end end. report_status(Verb, State) -> rabbit_shovel_status:report( State#state.name, {Verb, {source, State#state.inbound_params}, {destination, State#state.outbound_params}}). publish(Tag, Method, Msg, State = #state{inbound_ch = InboundChan, outbound_ch = OutboundChan, config = Config, blocked = false, msg_buf = MsgBuf, unacked = Unacked}) -> Seq = case Config#shovel.ack_mode of on_confirm -> amqp_channel:next_publish_seqno(OutboundChan); _ -> undefined end, case amqp_channel:call(OutboundChan, Method, Msg) of ok -> case Config#shovel.ack_mode of no_ack -> State; on_confirm -> State#state{unacked = gb_trees:insert(Seq, Tag, Unacked)}; on_publish -> ok = amqp_channel:cast( InboundChan, #'basic.ack'{delivery_tag = Tag}), State end; blocked -> ok = report_status(blocked, State), ok = channel_flow(InboundChan, false), State#state{blocked = true, msg_buf = queue:in_r({Tag, Method, Msg}, MsgBuf)} end; publish(Tag, Method, Msg, State = #state{blocked = true, msg_buf = MsgBuf}) -> State#state{msg_buf = queue:in({Tag, Method, Msg}, MsgBuf)}. drain_buffer(State = #state{blocked = true}) -> State; drain_buffer(State = #state{blocked = false, msg_buf = MsgBuf}) -> case queue:out(MsgBuf) of {empty, _MsgBuf} -> State; {{value, {Tag, Method, Msg}}, MsgBuf1} -> drain_buffer(publish(Tag, Method, Msg, State#state{msg_buf = MsgBuf1})) end. channel_flow(Chan, Active) -> #'channel.flow_ok'{active = Active} = amqp_channel:call(Chan, #'channel.flow'{active = Active}), ok. make_conn_and_chan(AmqpParams) -> AmqpParam = lists:nth(random:uniform(length(AmqpParams)), AmqpParams), {ok, Conn} = amqp_connection:start(AmqpParam), link(Conn), {ok, Chan} = amqp_connection:open_channel(Conn), {Conn, Chan, AmqpParam}. create_resources(Chan, Declarations) -> [amqp_channel:call(Chan, Method) || Method <- Declarations]. rabbitmq-server-3.2.4/plugins-src/rabbitmq-shovel/src/rabbit_shovel_config.erl0000644000000000000000000002222112305126066026333 0ustar rootroot%% The contents of this file are subject to the Mozilla Public License %% Version 1.1 (the "License"); you may not use this file except in %% compliance with the License. You may obtain a copy of the License %% at http://www.mozilla.org/MPL/ %% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See %% the License for the specific language governing rights and %% limitations under the License. %% %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is GoPivotal, Inc. %% Copyright (c) 2007-2013 GoPivotal, Inc. All rights reserved. %% -module(rabbit_shovel_config). -export([parse/2, ensure_defaults/2]). -include_lib("amqp_client/include/amqp_client.hrl"). -include("rabbit_shovel.hrl"). parse(ShovelName, Config) -> {ok, Defaults} = application:get_env(defaults), try {ok, run_state_monad( [fun enrich_shovel_config/1, fun parse_shovel_config_proplist/1, fun parse_shovel_config_dict/1], {Config, Defaults})} catch throw:{error, Reason} -> {error, {invalid_shovel_configuration, ShovelName, Reason}} end. %% ensures that any defaults that have been applied to a parsed %% shovel, are written back to the original proplist ensure_defaults(ShovelConfig, ParsedShovel) -> lists:keystore(reconnect_delay, 1, ShovelConfig, {reconnect_delay, ParsedShovel#shovel.reconnect_delay}). enrich_shovel_config({Config, Defaults}) -> Config1 = proplists:unfold(Config), case [E || E <- Config1, not (is_tuple(E) andalso tuple_size(E) == 2)] of [] -> case duplicate_keys(Config1) of [] -> return(lists:ukeysort(1, Config1 ++ Defaults)); Dups -> fail({duplicate_parameters, Dups}) end; Invalid -> fail({invalid_parameters, Invalid}) end. parse_shovel_config_proplist(Config) -> Dict = dict:from_list(Config), Fields = record_info(fields, shovel), Keys = dict:fetch_keys(Dict), case {Keys -- Fields, Fields -- Keys} of {[], []} -> {_Pos, Dict1} = lists:foldl( fun (FieldName, {Pos, Acc}) -> {Pos + 1, dict:update(FieldName, fun (V) -> {V, Pos} end, Acc)} end, {2, Dict}, Fields), return(Dict1); {[], Missing} -> fail({missing_parameters, Missing}); {Unknown, _} -> fail({unrecognised_parameters, Unknown}) end. parse_shovel_config_dict(Dict) -> run_state_monad( [fun (Shovel) -> {ok, Value} = dict:find(Key, Dict), try {ParsedValue, Pos} = Fun(Value), return(setelement(Pos, Shovel, ParsedValue)) catch throw:{error, Reason} -> fail({invalid_parameter_value, Key, Reason}) end end || {Fun, Key} <- [{fun parse_endpoint/1, sources}, {fun parse_endpoint/1, destinations}, {fun parse_non_negative_integer/1, prefetch_count}, {fun parse_ack_mode/1, ack_mode}, {fun parse_binary/1, queue}, make_parse_publish(publish_fields), make_parse_publish(publish_properties), {fun parse_non_negative_number/1, reconnect_delay}]], #shovel{}). %% --=: Plain state monad implementation start :=-- run_state_monad(FunList, State) -> lists:foldl(fun (Fun, StateN) -> Fun(StateN) end, State, FunList). return(V) -> V. fail(Reason) -> throw({error, Reason}). %% --=: end :=-- parse_endpoint({Endpoint, Pos}) when is_list(Endpoint) -> Brokers = case proplists:get_value(brokers, Endpoint) of undefined -> case proplists:get_value(broker, Endpoint) of undefined -> fail({missing_endpoint_parameter, broker_or_brokers}); B -> [B] end; Bs when is_list(Bs) -> Bs; B -> fail({expected_list, brokers, B}) end, {[], Brokers1} = run_state_monad( lists:duplicate(length(Brokers), fun parse_uri/1), {Brokers, []}), ResourceDecls = case proplists:get_value(declarations, Endpoint, []) of Decls when is_list(Decls) -> Decls; Decls -> fail({expected_list, declarations, Decls}) end, {[], ResourceDecls1} = run_state_monad( lists:duplicate(length(ResourceDecls), fun parse_declaration/1), {ResourceDecls, []}), return({#endpoint{amqp_params = Brokers1, resource_declarations = lists:reverse(ResourceDecls1)}, Pos}); parse_endpoint({Endpoint, _Pos}) -> fail({require_list, Endpoint}). parse_uri({[Uri | Uris], Acc}) -> case amqp_uri:parse(Uri) of {ok, Params} -> return({Uris, [Params | Acc]}); {error, _} = Err -> throw(Err) end. parse_declaration({[{Method, Props} | Rest], Acc}) when is_list(Props) -> FieldNames = try rabbit_framing_amqp_0_9_1:method_fieldnames(Method) catch exit:Reason -> fail(Reason) end, case proplists:get_keys(Props) -- FieldNames of [] -> ok; UnknownFields -> fail({unknown_fields, Method, UnknownFields}) end, {Res, _Idx} = lists:foldl( fun (K, {R, Idx}) -> NewR = case proplists:get_value(K, Props) of undefined -> R; V -> setelement(Idx, R, V) end, {NewR, Idx + 1} end, {rabbit_framing_amqp_0_9_1:method_record(Method), 2}, FieldNames), return({Rest, [Res | Acc]}); parse_declaration({[{Method, Props} | _Rest], _Acc}) -> fail({expected_method_field_list, Method, Props}); parse_declaration({[Method | Rest], Acc}) -> parse_declaration({[{Method, []} | Rest], Acc}). parse_non_negative_integer({N, Pos}) when is_integer(N) andalso N >= 0 -> return({N, Pos}); parse_non_negative_integer({N, _Pos}) -> fail({require_non_negative_integer, N}). parse_non_negative_number({N, Pos}) when is_number(N) andalso N >= 0 -> return({N, Pos}); parse_non_negative_number({N, _Pos}) -> fail({require_non_negative_number, N}). parse_binary({Binary, Pos}) when is_binary(Binary) -> return({Binary, Pos}); parse_binary({NotABinary, _Pos}) -> fail({require_binary, NotABinary}). parse_ack_mode({Val, Pos}) when Val =:= no_ack orelse Val =:= on_publish orelse Val =:= on_confirm -> return({Val, Pos}); parse_ack_mode({WrongVal, _Pos}) -> fail({ack_mode_value_requires_one_of, {no_ack, on_publish, on_confirm}, WrongVal}). make_parse_publish(publish_fields) -> {make_parse_publish1(record_info(fields, 'basic.publish')), publish_fields}; make_parse_publish(publish_properties) -> {make_parse_publish1(record_info(fields, 'P_basic')), publish_properties}. make_parse_publish1(ValidFields) -> fun ({Fields, Pos}) when is_list(Fields) -> make_publish_fun(Fields, Pos, ValidFields); ({Fields, _Pos}) -> fail({require_list, Fields}) end. make_publish_fun(Fields, Pos, ValidFields) -> SuppliedFields = proplists:get_keys(Fields), case SuppliedFields -- ValidFields of [] -> FieldIndices = make_field_indices(ValidFields, Fields), Fun = fun (Publish) -> lists:foldl(fun ({Pos1, Value}, Pub) -> setelement(Pos1, Pub, Value) end, Publish, FieldIndices) end, return({Fun, Pos}); Unexpected -> fail({unexpected_fields, Unexpected, ValidFields}) end. make_field_indices(Valid, Fields) -> make_field_indices(Fields, field_map(Valid, 2), []). make_field_indices([], _Idxs , Acc) -> lists:reverse(Acc); make_field_indices([{Key, Value} | Rest], Idxs, Acc) -> make_field_indices(Rest, Idxs, [{dict:fetch(Key, Idxs), Value} | Acc]). field_map(Fields, Idx0) -> {Dict, _IdxMax} = lists:foldl(fun (Field, {Dict1, Idx1}) -> {dict:store(Field, Idx1, Dict1), Idx1 + 1} end, {dict:new(), Idx0}, Fields), Dict. duplicate_keys(PropList) -> proplists:get_keys( lists:foldl(fun (K, L) -> lists:keydelete(K, 1, L) end, PropList, proplists:get_keys(PropList))). rabbitmq-server-3.2.4/plugins-src/rabbitmq-shovel/src/rabbit_shovel_sup.erl0000644000000000000000000000620212305126066025676 0ustar rootroot%% The contents of this file are subject to the Mozilla Public License %% Version 1.1 (the "License"); you may not use this file except in %% compliance with the License. You may obtain a copy of the License %% at http://www.mozilla.org/MPL/ %% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See %% the License for the specific language governing rights and %% limitations under the License. %% %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is GoPivotal, Inc. %% Copyright (c) 2007-2013 GoPivotal, Inc. All rights reserved. %% -module(rabbit_shovel_sup). -behaviour(supervisor2). -export([start_link/0, init/1]). -import(rabbit_shovel_config, [ensure_defaults/2]). -include("rabbit_shovel.hrl"). start_link() -> case parse_configuration(application:get_env(shovels)) of {ok, Configurations} -> supervisor2:start_link({local, ?MODULE}, ?MODULE, [Configurations]); {error, Reason} -> {error, Reason} end. init([Configurations]) -> Len = dict:size(Configurations), ChildSpecs = [{rabbit_shovel_status, {rabbit_shovel_status, start_link, []}, transient, 16#ffffffff, worker, [rabbit_shovel_status]} | make_child_specs(Configurations)], {ok, {{one_for_one, 2*Len, 2}, ChildSpecs}}. make_child_specs(Configurations) -> dict:fold( fun (ShovelName, ShovelConfig, Acc) -> [{ShovelName, {rabbit_shovel_worker_sup, start_link, [ShovelName, ShovelConfig]}, permanent, 16#ffffffff, supervisor, [rabbit_shovel_worker_sup]} | Acc] end, [], Configurations). parse_configuration(undefined) -> {ok, dict:new()}; parse_configuration({ok, Env}) -> {ok, Defaults} = application:get_env(defaults), parse_configuration(Defaults, Env, dict:new()). parse_configuration(_Defaults, [], Acc) -> {ok, Acc}; parse_configuration(Defaults, [{ShovelName, ShovelConfig} | Env], Acc) when is_atom(ShovelName) andalso is_list(ShovelConfig) -> case dict:is_key(ShovelName, Acc) of true -> {error, {duplicate_shovel_definition, ShovelName}}; false -> case validate_shovel_config(ShovelName, ShovelConfig) of {ok, Shovel} -> %% make sure the config we accumulate has any %% relevant default values (discovered during %% validation), applied back to it UpdatedConfig = ensure_defaults(ShovelConfig, Shovel), Acc2 = dict:store(ShovelName, UpdatedConfig, Acc), parse_configuration(Defaults, Env, Acc2); Error -> Error end end; parse_configuration(_Defaults, _, _Acc) -> {error, require_list_of_shovel_configurations}. validate_shovel_config(ShovelName, ShovelConfig) -> rabbit_shovel_config:parse(ShovelName, ShovelConfig). rabbitmq-server-3.2.4/plugins-src/rabbitmq-shovel/src/rabbitmq_shovel.app.src0000644000000000000000000000073512305126066026136 0ustar rootroot{application, rabbitmq_shovel, [{description, "Data Shovel for RabbitMQ"}, {vsn, "%%VSN%%"}, {modules, []}, {registered, []}, {env, [{defaults, [{prefetch_count, 0}, {ack_mode, on_confirm}, {publish_fields, []}, {publish_properties, []}, {reconnect_delay, 5}] }]}, {mod, {rabbit_shovel, []}}, {applications, [kernel, stdlib, rabbit, amqp_client]}]}. rabbitmq-server-3.2.4/plugins-src/rabbitmq-shovel/src/rabbit_shovel_status.erl0000644000000000000000000000361012305126066026412 0ustar rootroot%% The contents of this file are subject to the Mozilla Public License %% Version 1.1 (the "License"); you may not use this file except in %% compliance with the License. You may obtain a copy of the License %% at http://www.mozilla.org/MPL/ %% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See %% the License for the specific language governing rights and %% limitations under the License. %% %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is GoPivotal, Inc. %% Copyright (c) 2007-2013 GoPivotal, Inc. All rights reserved. %% -module(rabbit_shovel_status). -behaviour(gen_server). -export([start_link/0]). -export([report/2, status/0]). -export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]). -define(SERVER, ?MODULE). -define(ETS_NAME, ?MODULE). -record(state, {}). -record(entry, {name, info, timestamp}). start_link() -> gen_server:start_link({local, ?SERVER}, ?MODULE, [], []). report(Name, Info) -> gen_server:cast(?SERVER, {report, Name, Info, calendar:local_time()}). status() -> gen_server:call(?SERVER, status, infinity). init([]) -> ?ETS_NAME = ets:new(?ETS_NAME, [named_table, {keypos, #entry.name}, private]), {ok, #state{}}. handle_call(status, _From, State) -> Entries = ets:tab2list(?ETS_NAME), {reply, [{Entry#entry.name, Entry#entry.info, Entry#entry.timestamp} || Entry <- Entries], State}. handle_cast({report, Name, Info, Timestamp}, State) -> true = ets:insert(?ETS_NAME, #entry{name = Name, info = Info, timestamp = Timestamp}), {noreply, State}. handle_info(_Info, State) -> {noreply, State}. terminate(_Reason, _State) -> ok. code_change(_OldVsn, State, _Extra) -> {ok, State}. rabbitmq-server-3.2.4/plugins-src/rabbitmq-shovel/src/rabbit_shovel_worker_sup.erl0000644000000000000000000000310412305126066027265 0ustar rootroot%% The contents of this file are subject to the Mozilla Public License %% Version 1.1 (the "License"); you may not use this file except in %% compliance with the License. You may obtain a copy of the License %% at http://www.mozilla.org/MPL/ %% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See %% the License for the specific language governing rights and %% limitations under the License. %% %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is GoPivotal, Inc. %% Copyright (c) 2007-2013 GoPivotal, Inc. All rights reserved. %% -module(rabbit_shovel_worker_sup). -behaviour(mirrored_supervisor). -export([start_link/2, init/1]). -include("rabbit_shovel.hrl"). start_link(ShovelName, ShovelConfig) -> mirrored_supervisor:start_link({local, ShovelName}, ShovelName, fun rabbit_misc:execute_mnesia_transaction/1, ?MODULE, [ShovelName, ShovelConfig]). init([ShovelName, Config]) -> ChildSpecs = [{ShovelName, {rabbit_shovel_worker, start_link, [ShovelName, Config]}, case proplists:get_value(reconnect_delay, Config, none) of N when is_integer(N) andalso N > 0 -> {permanent, N}; _ -> temporary end, 16#ffffffff, worker, [rabbit_shovel_worker]}], {ok, {{one_for_one, 3, 10}, ChildSpecs}}. rabbitmq-server-3.2.4/plugins-src/rabbitmq-shovel/README0000644000000000000000000000024412305126066021551 0ustar rootrootGeneric build instructions are at: http://www.rabbitmq.com/plugin-development.html See the http://www.rabbitmq.com/shovel.html page for full instructions. rabbitmq-server-3.2.4/plugins-src/rabbitmq-shovel/test/0000755000000000000000000000000012305126066021650 5ustar rootrootrabbitmq-server-3.2.4/plugins-src/rabbitmq-shovel/test/src/0000755000000000000000000000000012305126066022437 5ustar rootrootrabbitmq-server-3.2.4/plugins-src/rabbitmq-shovel/test/src/rabbit_shovel_test.erl0000644000000000000000000002244012305126066027027 0ustar rootroot%% The contents of this file are subject to the Mozilla Public License %% Version 1.1 (the "License"); you may not use this file except in %% compliance with the License. You may obtain a copy of the License %% at http://www.mozilla.org/MPL/ %% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See %% the License for the specific language governing rights and %% limitations under the License. %% %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is GoPivotal, Inc. %% Copyright (c) 2007-2013 GoPivotal, Inc. All rights reserved. %% -module(rabbit_shovel_test). -export([test/0]). -include_lib("amqp_client/include/amqp_client.hrl"). -define(EXCHANGE, <<"test_exchange">>). -define(TO_SHOVEL, <<"to_the_shovel">>). -define(FROM_SHOVEL, <<"from_the_shovel">>). -define(UNSHOVELLED, <<"unshovelled">>). -define(SHOVELLED, <<"shovelled">>). -define(TIMEOUT, 1000). test() -> %% it may already be running. Stop if possible application:stop(rabbitmq_shovel), %% shovel can be started with zero shovels configured ok = application:start(rabbitmq_shovel), ok = application:stop(rabbitmq_shovel), %% various ways of breaking the config require_list_of_shovel_configurations = test_broken_shovel_configs(invalid_config), require_list_of_shovel_configurations = test_broken_shovel_configs([{test_shovel, invalid_shovel_config}]), Config = [{sources, [{broker, "amqp://"}]}, {destinations, [{broker, "amqp://"}]}, {queue, <<"">>}], {duplicate_shovel_definition, test_shovel} = test_broken_shovel_configs( [{test_shovel, Config}, {test_shovel, Config}]), {invalid_parameters, [{invalid, invalid, invalid}]} = test_broken_shovel_config([{invalid, invalid, invalid} | Config]), {duplicate_parameters, [queue]} = test_broken_shovel_config([{queue, <<"">>} | Config]), {missing_parameters, Missing} = test_broken_shovel_config([]), [destinations, queue, sources] = lists:sort(Missing), {unrecognised_parameters, [invalid]} = test_broken_shovel_config([{invalid, invalid} | Config]), {require_list, invalid} = test_broken_shovel_sources(invalid), {missing_endpoint_parameter, broker_or_brokers} = test_broken_shovel_sources([]), {expected_list, brokers, invalid} = test_broken_shovel_sources([{brokers, invalid}]), {expected_string_uri, 42} = test_broken_shovel_sources([{brokers, [42]}]), {{unexpected_uri_scheme, "invalid"}, "invalid://"} = test_broken_shovel_sources([{broker, "invalid://"}]), {{unable_to_parse_uri, no_scheme}, "invalid"} = test_broken_shovel_sources([{broker, "invalid"}]), {expected_list,declarations, invalid} = test_broken_shovel_sources([{broker, "amqp://"}, {declarations, invalid}]), {unknown_method_name, 42} = test_broken_shovel_sources([{broker, "amqp://"}, {declarations, [42]}]), {expected_method_field_list, 'queue.declare', 42} = test_broken_shovel_sources([{broker, "amqp://"}, {declarations, [{'queue.declare', 42}]}]), {unknown_fields, 'queue.declare', [invalid]} = test_broken_shovel_sources( [{broker, "amqp://"}, {declarations, [{'queue.declare', [invalid]}]}]), {{invalid_amqp_params_parameter, heartbeat, "text", [{"heartbeat", "text"}], {not_an_integer, "text"}}, _} = test_broken_shovel_sources( [{broker, "amqp://localhost/?heartbeat=text"}]), {{invalid_amqp_params_parameter, username, "text", [{"username", "text"}], {parameter_unconfigurable_in_query, username, "text"}}, _} = test_broken_shovel_sources([{broker, "amqp://?username=text"}]), {invalid_parameter_value, prefetch_count, {require_non_negative_integer, invalid}} = test_broken_shovel_config([{prefetch_count, invalid} | Config]), {invalid_parameter_value, ack_mode, {ack_mode_value_requires_one_of, {no_ack, on_publish, on_confirm}, invalid}} = test_broken_shovel_config([{ack_mode, invalid} | Config]), {invalid_parameter_value, queue, {require_binary, invalid}} = test_broken_shovel_config([{sources, [{broker, "amqp://"}]}, {destinations, [{broker, "amqp://"}]}, {queue, invalid}]), {invalid_parameter_value, publish_properties, {require_list, invalid}} = test_broken_shovel_config([{publish_properties, invalid} | Config]), {invalid_parameter_value, publish_properties, {unexpected_fields, [invalid], _}} = test_broken_shovel_config([{publish_properties, [invalid]} | Config]), {{invalid_ssl_parameter, fail_if_no_peer_cert, "42", _, {require_boolean, '42'}}, _} = test_broken_shovel_sources([{broker, "amqps://username:password@host:5673/vhost?cacertfile=/path/to/cacert.pem&certfile=/path/to/certfile.pem&keyfile=/path/to/keyfile.pem&verify=verify_peer&fail_if_no_peer_cert=42"}]), %% a working config application:set_env( rabbitmq_shovel, shovels, [{test_shovel, [{sources, [{broker, "amqp:///%2f?heartbeat=5"}, {declarations, [{'queue.declare', [exclusive, auto_delete]}, {'exchange.declare', [{exchange, ?EXCHANGE}, auto_delete]}, {'queue.bind', [{queue, <<>>}, {exchange, ?EXCHANGE}, {routing_key, ?TO_SHOVEL}]} ]}]}, {destinations, [{broker, "amqp:///%2f"}]}, {queue, <<>>}, {ack_mode, on_confirm}, {publish_fields, [{exchange, ?EXCHANGE}, {routing_key, ?FROM_SHOVEL}]}, {publish_properties, [{delivery_mode, 2}, {cluster_id, <<"my-cluster">>}, {content_type, ?SHOVELLED}]} ]}], infinity), ok = application:start(rabbitmq_shovel), {ok, Conn} = amqp_connection:start(#amqp_params_network{}), {ok, Chan} = amqp_connection:open_channel(Conn), #'queue.declare_ok'{ queue = Q } = amqp_channel:call(Chan, #'queue.declare' { exclusive = true }), #'queue.bind_ok'{} = amqp_channel:call(Chan, #'queue.bind' { queue = Q, exchange = ?EXCHANGE, routing_key = ?FROM_SHOVEL }), #'queue.bind_ok'{} = amqp_channel:call(Chan, #'queue.bind' { queue = Q, exchange = ?EXCHANGE, routing_key = ?TO_SHOVEL }), #'basic.consume_ok'{ consumer_tag = CTag } = amqp_channel:subscribe(Chan, #'basic.consume' { queue = Q, exclusive = true }, self()), receive #'basic.consume_ok'{ consumer_tag = CTag } -> ok after ?TIMEOUT -> throw(timeout_waiting_for_consume_ok) end, ok = amqp_channel:call(Chan, #'basic.publish' { exchange = ?EXCHANGE, routing_key = ?TO_SHOVEL }, #amqp_msg { payload = <<42>>, props = #'P_basic' { delivery_mode = 2, content_type = ?UNSHOVELLED } }), receive {#'basic.deliver' { consumer_tag = CTag, delivery_tag = AckTag, routing_key = ?FROM_SHOVEL }, #amqp_msg { payload = <<42>>, props = #'P_basic' { delivery_mode = 2, content_type = ?SHOVELLED } }} -> ok = amqp_channel:call(Chan, #'basic.ack'{ delivery_tag = AckTag }) after ?TIMEOUT -> throw(timeout_waiting_for_deliver1) end, [{test_shovel, {running, {source, _Source}, {destination, _Destination}}, _Time}] = rabbit_shovel_status:status(), receive {#'basic.deliver' { consumer_tag = CTag, delivery_tag = AckTag1, routing_key = ?TO_SHOVEL }, #amqp_msg { payload = <<42>>, props = #'P_basic' { delivery_mode = 2, content_type = ?UNSHOVELLED } }} -> ok = amqp_channel:call(Chan, #'basic.ack'{ delivery_tag = AckTag1 }) after ?TIMEOUT -> throw(timeout_waiting_for_deliver2) end, amqp_channel:close(Chan), amqp_connection:close(Conn), ok = application:stop(rabbitmq_shovel), ok. test_broken_shovel_configs(Configs) -> application:set_env(rabbitmq_shovel, shovels, Configs), {error, {Error, _}} = application:start(rabbitmq_shovel), Error. test_broken_shovel_config(Config) -> {invalid_shovel_configuration, test_shovel, Error} = test_broken_shovel_configs([{test_shovel, Config}]), Error. test_broken_shovel_sources(Sources) -> {invalid_parameter_value, sources, Error} = test_broken_shovel_config([{sources, Sources}, {destinations, [{broker, "amqp://"}]}, {queue, <<"">>}]), Error. rabbitmq-server-3.2.4/plugins-src/rabbitmq-shovel/.srcdist_done0000644000000000000000000000000012305126066023340 0ustar rootrootrabbitmq-server-3.2.4/plugins-src/rabbitmq-shovel/Makefile0000644000000000000000000000002712305126066022330 0ustar rootrootinclude ../umbrella.mk rabbitmq-server-3.2.4/plugins-src/rabbitmq-shovel/ebin/0000755000000000000000000000000012305126066021606 5ustar rootrootrabbitmq-server-3.2.4/plugins-src/rabbitmq-shovel/include/0000755000000000000000000000000012305126066022314 5ustar rootrootrabbitmq-server-3.2.4/plugins-src/rabbitmq-shovel/include/rabbit_shovel.hrl0000644000000000000000000000170012305126066025644 0ustar rootroot%% The contents of this file are subject to the Mozilla Public License %% Version 1.1 (the "License"); you may not use this file except in %% compliance with the License. You may obtain a copy of the License %% at http://www.mozilla.org/MPL/ %% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See %% the License for the specific language governing rights and %% limitations under the License. %% %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is GoPivotal, Inc. %% Copyright (c) 2007-2013 GoPivotal, Inc. All rights reserved. %% -record(endpoint, {amqp_params, resource_declarations }). -record(shovel, {sources, destinations, prefetch_count, ack_mode, publish_fields, publish_properties, queue, reconnect_delay }). rabbitmq-server-3.2.4/plugins-src/rabbitmq-shovel/package.mk0000644000000000000000000000014312305126066022613 0ustar rootrootRELEASABLE:=true DEPS:=rabbitmq-erlang-client WITH_BROKER_TEST_COMMANDS:=rabbit_shovel_test:test() rabbitmq-server-3.2.4/plugins-src/webmachine-wrapper/0000755000000000000000000000000012305126066021352 5ustar rootrootrabbitmq-server-3.2.4/plugins-src/webmachine-wrapper/webmachine-git/0000755000000000000000000000000012305126066024235 5ustar rootrootrabbitmq-server-3.2.4/plugins-src/webmachine-wrapper/webmachine-git/scripts/0000755000000000000000000000000012305126066025724 5ustar rootrootrabbitmq-server-3.2.4/plugins-src/webmachine-wrapper/webmachine-git/scripts/new_webmachine.sh0000755000000000000000000000143512305126066031241 0ustar rootroot#!/usr/bin/env bash SCRIPT=${0##*/} NAME=$1 DESTDIR=$2 usage() { echo "usage: new_webmachine.sh name [destdir]" } if [ -z $NAME ] || [[ $NAME =~ ^[\.\~\/] ]]; then usage exit 1 fi erl -noshell -eval 'halt(if is_atom('"$NAME"') -> 0; true -> 1 end).' if [[ $? -ne 0 ]]; then echo $SCRIPT: \""$NAME"\" is not allowed as a project name echo ' The project name must begin with a lowercase letter and' echo ' contain only alphanumeric characters and underscores.' usage exit 1 fi if [ -z $DESTDIR ]; then DESTDIR="." elif [[ $DESTDIR =~ /${NAME}$ ]]; then DESTDIR=${DESTDIR%/*} fi if [ ! -e $DESTDIR ]; then $(mkdir -p $DESTDIR) fi ABSDEST=$(cd $DESTDIR && pwd) cd ${0%/*}/../priv ../rebar create template=wmskel appid=$NAME prefix=$ABSDEST/$NAME rabbitmq-server-3.2.4/plugins-src/webmachine-wrapper/webmachine-git/THANKS0000644000000000000000000000047212305126066025153 0ustar rootrootThe following people have contributed to Webmachine: Andy Gross Justin Sheehy John Muellerleile Robert Ahrens Jeremy Latt Bryan Fink Ryan Tilder Taavi Talvik Marc Worrell Seth Falcon Tuncer Ayaz Martin Scholl Paul Mineiro Dave Smith Arjan Scherpenisse Benjamin Black Anthony Molinaro Phil Pirozhkov Rusty Klophausrabbitmq-server-3.2.4/plugins-src/webmachine-wrapper/webmachine-git/priv/0000755000000000000000000000000012305126066025215 5ustar rootrootrabbitmq-server-3.2.4/plugins-src/webmachine-wrapper/webmachine-git/priv/www/0000755000000000000000000000000012305126066026041 5ustar rootrootrabbitmq-server-3.2.4/plugins-src/webmachine-wrapper/webmachine-git/priv/www/index.html0000644000000000000000000000011712305126066030035 0ustar rootroot It Worked Running. rabbitmq-server-3.2.4/plugins-src/webmachine-wrapper/webmachine-git/priv/trace/0000755000000000000000000000000012305126066026313 5ustar rootrootrabbitmq-server-3.2.4/plugins-src/webmachine-wrapper/webmachine-git/priv/trace/wmtrace.js0000755000000000000000000004475212305126066030332 0ustar rootrootvar HIGHLIGHT = '#cc00cc'; var REGULAR = '#666666'; var cols = { 'a':173, 'b':325, 'c':589, 'd':797, 'e':1005, 'f':1195, 'g':1402, 'gg':1515, 'h':1572, 'i':1799, 'j':1893, 'k':1988, 'l':2157, 'll':2346, 'm':2403, 'mm':2535, 'n':2554, 'o':2649, 'oo':2781, 'ooo':2801, 'p':2894, 'q':3007 }; var rows = { '1':221, '2':298, '3':373, '4':448, '5':524, '6':599, '7':675, '8':751, '9':826, '10':902, '11':977, '12':1053, '13':1129, '14':1204, '15':1280, '16':1355, '17':1431, '18':1506, '19':1583, '20':1658, '21':1734, '22':1809, '23':1885, '24':1961, '25':2036, '26':2112 }; var edges = { 'b14b13':['b14','b13'], 'b13b12':['b13','b12'], 'b13503':['b13','503'], 'b12b11':['b12','b11'], 'b12501':['b12','501'], 'b11b10':['b11','b10'], 'b11414':['b11','414'], 'b10b9':['b10','b9'], 'b10405':['b10','405'], 'b9b8':['b9','b8'], 'b9400':['b9','400'], 'b8b7':['b8','b7'], 'b8401':['b8','401'], 'b7b6':['b7','b6'], 'b7403':['b7','403'], 'b6b5':['b6','b5'], 'b6501':['b6','501a'], 'b5b4':['b5','b4'], 'b5415':['b5','415'], 'b4b3':['b4','b3'], 'b4413':['b4','b4'], 'b3c3':['b3','c3'], 'b3200':['b3','200'], 'c3c4':['c3','c4'], 'c3d4':['c3','d3','d4'], 'c4d4':['c4','d4'], 'c4406':['c4','406'], 'd4d5':['d4','d5'], 'd4e5':['d4','e4','e5'], 'd5e5':['d5','e5'], 'd5406':['d5','d7','406'], 'e5e6':['e5','e6'], 'e5f6':['e5','f5','f6'], 'e6f6':['e6','f6'], 'e6406':['e6','e7','406'], 'f6f7':['f6','f7'], 'f6g7':['f6','g6','g7'], 'f7g7':['f7','g7'], 'f7406':['f7','406'], 'g7g8':['g7','g8'], 'g7h7':['g7','h7'], 'g8g9':['g8','g9'], 'g8h10':['g8','h8','h10'], 'g9g11':['g9','g11'], 'g9h10':['g9','gg9','gg10','h10'], 'g11h10':['g11','gg11','gg10','h10'], 'g11412':['g11','g18','412a'], 'h7i7':['h7','i7'], 'h7412':['h7','412'], 'h10h11':['h10','h11'], 'h10i12':['h10','i10','i12'], 'h11h12':['h11','h12'], 'h11i12':['h11','i11','i12'], 'h12i12':['h12','i12'], 'h12412':['h12','412a'], 'i4p3':['i4','i3','p3'], 'i4301':['i4','301'], 'i7i4':['i7','i4'], 'i7k7':['i7','k7'], 'i12l13':['i12','l12','l13'], 'i12i13':['i12','i13'], 'i13k13':['i13','k13'], 'i13j18':['i13','i17','j17','j18'], 'j18412':['j18','412a'], 'j18304':['j18','304'], 'k5l5':['k5','l5'], 'k5301':['k5','301'], 'k7k5':['k7','k5'], 'k7l7':['k7','l7'], 'k13j18':['k13','k17','j17','j18'], 'k13l13':['k13','l13'], 'l5m5':['l5','m5'], 'l5307':['l5','307'], 'l7m7':['l7','m7'], 'l7404':['l7','l8','404'], 'l13l14':['l13','l14'], 'l13m16':['l13','m13','m16'], 'l14l15':['l14','l15'], 'l14m16':['l14','m14','m16'], 'l15l17':['l15','l17'], 'l15m16':['l15','ll15','ll16','m16'], 'l17m16':['l17','ll17','ll16','m16'], 'l17304':['l17','304'], 'm5n5':['m5','n5'], 'm5410':['m5','m4','410'], 'm7n11':['m7','n7','n11'], 'm7404':['m7','404'], 'm16m20':['m16','m20'], 'm16n16':['m16','n16'], 'm20o20':['m20','o20'], 'm20202':['m20','202'], 'n5n11':['n5','n11'], 'n5410':['n5','410'], 'n11p11':['n11','p11'], 'n11303':['n11','303'], 'n16n11':['n16','n11'], 'n16o16':['n16','o16'], 'o14p11':['o14','o11','p11'], 'o14409':['o14','409a'], 'o16o14':['o16','o14'], 'o16o18':['o16','o18'], 'o18200':['o18','200a'], 'o18300':['o18','oo18','300'], 'o20o18':['o20','o18'], 'o20204':['o20','204'], 'p3p11':['p3','p11'], 'p3409':['p3','409'], 'p11o20':['p11','p20','o20'], 'p11201':['p11','q11','201'] }; var ends = { '200': {col:'a', row:'3', width:190}, '200a': {col:'mm', row:'18', width:116}, '201': {col:'q', row:'12', width:154}, '202': {col:'m', row:'21', width:116}, '204': {col:'o', row:'21', width:152}, '300': {col:'oo', row:'19', width:152}, '301': {col:'k', row:'4', width:154}, '303': {col:'m', row:'11', width:116}, '304': {col:'l', row:'18', width:116}, '307': {col:'l', row:'4', width:154}, '400': {col:'a', row:'9', width:190}, '401': {col:'a', row:'8', width:190}, '403': {col:'a', row:'7', width:190}, '404': {col:'m', row:'8', width:116}, '405': {col:'a', row:'10', width:190}, '406': {col:'c', row:'7', width:152}, '409': {col:'p', row:'2', width:116}, '409a': {col:'oo', row:'14', width:116}, '410': {col:'n', row:'4', width:116}, '412': {col:'h', row:'6', width:152}, '412a': {col:'h', row:'18', width:152}, '413': {col:'a', row:'4', width:190}, '414': {col:'a', row:'11', width:190}, '415': {col:'a', row:'5', width:190}, '501a': {col:'a', row:'6', width:190}, '501': {col:'a', row:'12', width:190}, '503': {col:'a', row:'13', width:190} }; var canvas; function decorateTrace() { trace[0].x = cols[trace[0].d[0]]; trace[0].y = rows[trace[0].d.slice(1)]; trace[0].previewCalls = previewCalls(trace[0]); for (var i = 1; i < trace.length; i++) { trace[i].x = cols[trace[i].d[0]]; trace[i].y = rows[trace[i].d.slice(1)]; trace[i].previewCalls = previewCalls(trace[i]); var path = edges[trace[i-1].d+trace[i].d]; if (path) { trace[i].path = [path.length-1]; for (var p = 1; p < path.length; p++) { trace[i].path[p-1] = getSeg(path[p-1], path[p], p == path.length-1); } } else { trace[i].path = []; } } var path = edges[trace[i-1].d+response.code]; if (path) { var end = ends[path[path.length-1]]; response.x = cols[end.col]; response.y = rows[end.row]; response.width = end.width; response.type = 'normal'; response.path = [path.length-1]; for (var p = 1; p < path.length; p++) { response.path[p-1] = getSeg(path[p-1], path[p], p == path.length-1); } } else { var ld = trace[trace.length-1]; response.x = ld.x+50; response.y = ld.y-50; response.width = 38; response.type = 'other'; response.path = [ {x1: ld.x+10, y1: ld.y-10, x2: ld.x+36, y2: ld.y-36} ]; } }; function previewCalls(dec) { var prev = ''; for (var i = 0; i < dec.calls.length; i++) { if (dec.calls[i].output != "wmtrace_not_exported") prev += '
  • '+dec.calls[i].module+':'+dec.calls[i]['function']+'
  • '; } return prev; }; function drawTrace() { drawDecision(trace[0]); for (var i = 1; i < trace.length; i++) { drawPath(trace[i].path); drawDecision(trace[i]); } drawPath(response.path); drawResponse(); }; function drawResponse() { if (response.type == 'normal') { var context = canvas.getContext('2d'); context.strokeStyle=HIGHLIGHT; context.lineWidth=4; context.beginPath(); context.rect(response.x-(response.width/2), response.y-19, response.width, 38); context.stroke(); } else { var context = canvas.getContext('2d'); context.strokeStyle='#ff0000'; context.lineWidth=4; context.beginPath(); context.arc(response.x, response.y, 19, 0, 2*3.14159, false); context.stroke(); } }; function drawDecision(dec) { var context = canvas.getContext('2d'); if (dec.previewCalls == '') context.strokeStyle=REGULAR; else context.strokeStyle=HIGHLIGHT; context.lineWidth=4; context.beginPath(); context.moveTo(dec.x, dec.y-19); context.lineTo(dec.x+19, dec.y); context.lineTo(dec.x, dec.y+19); context.lineTo(dec.x-19, dec.y); context.closePath(); context.stroke(); }; function drawPath(path) { var context = canvas.getContext('2d'); context.strokeStyle=REGULAR; context.lineWidth=4; context.beginPath(); context.moveTo(path[0].x1, path[0].y1); for (var p = 0; p < path.length; p++) { context.lineTo(path[p].x2, path[p].y2); } context.stroke(); }; function getSeg(p1, p2, last) { var seg = { x1:cols[p1[0]], y1:rows[p1.slice(1)] }; if (ends[p2]) { seg.x2 = cols[ends[p2].col]; seg.y2 = rows[ends[p2].row]; } else { seg.x2 = cols[p2[0]]; seg.y2 = rows[p2.slice(1)]; } if (seg.x1 == seg.x2) { if (seg.y1 < seg.y2) { seg.y1 = seg.y1+19; if (last) seg.y2 = seg.y2-19; } else { seg.y1 = seg.y1-19; if (last) seg.y2 = seg.y2+19; } } else { //assume seg.y1 == seg.y2 if (seg.x1 < seg.x2) { seg.x1 = seg.x1+19; if (last) seg.x2 = seg.x2-(ends[p2] ? (ends[p2].width/2) : 19); } else { seg.x1 = seg.x1-19; if (last) seg.x2 = seg.x2+(ends[p2] ? (ends[p2].width/2) : 19); } } return seg; }; function traceDecision(name) { for (var i = trace.length-1; i >= 0; i--) if (trace[i].d == name) return trace[i]; }; var detailPanels = {}; function initDetailPanels() { var windowWidth = document.getElementById('sizetest').clientWidth; var infoPanel = document.getElementById('infopanel'); var panelWidth = windowWidth-infoPanel.offsetLeft; var panels = { 'request': document.getElementById('requestdetail'), 'response': document.getElementById('responsedetail'), 'decision': document.getElementById('decisiondetail') }; var tabs = { 'request': document.getElementById('requesttab'), 'response': document.getElementById('responsetab'), 'decision': document.getElementById('decisiontab') }; var decisionId = document.getElementById('decisionid'); var decisionCalls = document.getElementById('decisioncalls'); var callInput = document.getElementById('callinput'); var callOutput = document.getElementById('calloutput'); var lastUsedPanelWidth = windowWidth-infoPanel.offsetLeft; var setPanelWidth = function(width) { infoPanel.style.left = (windowWidth-width)+'px'; canvas.style.marginRight = (width+20)+'px'; panelWidth = width; }; setPanelWidth(panelWidth); var ensureVisible = function() { if (windowWidth-infoPanel.offsetLeft < 10) setPanelWidth(lastUsedPanelWidth); }; var decChoices = ''; for (var i = 0; i < trace.length; i++) { decChoices += ''; } decisionId.innerHTML = decChoices; decisionId.selectedIndex = -1; decisionId.onchange = function() { detailPanels.setDecision(traceDecision(decisionId.value)); } detailPanels.setDecision = function(dec) { decisionId.value = dec.d; var calls = []; for (var i = 0; i < dec.calls.length; i++) { calls.push(''); } decisionCalls.innerHTML = calls.join(''); decisionCalls.selectedIndex = 0; decisionCalls.onchange(); }; detailPanels.show = function(name) { for (p in panels) { if (p == name) { panels[p].style.display = 'block'; tabs[p].className = 'selectedtab'; } else { panels[p].style.display = 'none'; tabs[p].className = ''; } } ensureVisible(); }; detailPanels.hide = function() { setPanelWidth(0); } decisionCalls.onchange = function() { var val = decisionCalls.value; if (val) { var dec = traceDecision(val.substring(0, val.indexOf('-'))); var call = dec.calls[parseInt(val.substring(val.indexOf('-')+1, val.length))]; if (call.output != "wmtrace_not_exported") { callInput.style.color='#000000'; callInput.innerHTML = call.input; if (call.output != null) { callOutput.style.color = '#000000'; callOutput.innerHTML = call.output; } else { callOutput.style.color = '#ff0000'; callOutput.textContent = 'Error: '+call.module+':'+call['function']+' never returned'; } } else { callInput.style.color='#999999'; callInput.textContent = call.module+':'+call['function']+' was not exported'; callOutput.textContent = ''; } } else { callInput.textContent = ''; callOutput.textContent = ''; } }; var headersList = function(headers) { var h = ''; for (n in headers) h += '
  • '+n+': '+headers[n]; return h; }; document.getElementById('requestmethod').innerHTML = request.method; document.getElementById('requestpath').innerHTML = request.path; document.getElementById('requestheaders').innerHTML = headersList(request.headers); document.getElementById('requestbody').innerHTML = request.body; document.getElementById('responsecode').innerHTML = response.code; document.getElementById('responseheaders').innerHTML = headersList(response.headers); document.getElementById('responsebody').innerHTML = response.body; var infoControls = document.getElementById('infocontrols'); var md = false; var dragged = false; var msoff = 0; infoControls.onmousedown = function(ev) { md = true; dragged = false; msoff = ev.clientX-infoPanel.offsetLeft; }; infoControls.onclick = function(ev) { if (dragged) { lastUsedPanelWidth = panelWidth; } else if (panelWidth < 10) { switch(ev.target.id) { case 'requesttab': detailPanels.show('request'); break; case 'responsetab': detailPanels.show('response'); break; case 'decisiontab': detailPanels.show('decision'); break; default: ensureVisible(); } } else { var name = 'none'; switch(ev.target.id) { case 'requesttab': name = 'request'; break; case 'responsetab': name = 'response'; break; case 'decisiontab': name = 'decision'; break; } if (panels[name] && panels[name].style.display != 'block') detailPanels.show(name); else detailPanels.hide(); } return false; }; document.onmousemove = function(ev) { if (md) { dragged = true; panelWidth = windowWidth-(ev.clientX-msoff); if (panelWidth < 0) { panelWidth = 0; infoPanel.style.left = windowWidth+"px"; } else if (panelWidth > windowWidth-21) { panelWidth = windowWidth-21; infoPanel.style.left = '21px'; } else infoPanel.style.left = (ev.clientX-msoff)+"px"; canvas.style.marginRight = panelWidth+20+"px"; return false; } }; document.onmouseup = function() { md = false; }; window.onresize = function() { windowWidth = document.getElementById('sizetest').clientWidth; infoPanel.style.left = windowWidth-panelWidth+'px'; }; }; window.onload = function() { canvas = document.getElementById('v3map'); initDetailPanels(); var scale = 0.25; var coy = canvas.offsetTop; function findDecision(ev) { var x = (ev.clientX+window.pageXOffset)/scale; var y = (ev.clientY+window.pageYOffset-coy)/scale; for (var i = trace.length-1; i >= 0; i--) { if (x >= trace[i].x-19 && x <= trace[i].x+19 && y >= trace[i].y-19 && y <= trace[i].y+19) return trace[i]; } }; var preview = document.getElementById('preview'); var previewId = document.getElementById('previewid'); var previewCalls = document.getElementById('previewcalls'); function previewDecision(dec) { preview.style.left = (dec.x*scale)+'px'; preview.style.top = (dec.y*scale+coy+15)+'px'; preview.style.display = 'block'; previewId.textContent = dec.d; previewCalls.innerHTML = dec.previewCalls; }; function overResponse(ev) { var x = (ev.clientX+window.pageXOffset)/scale; var y = (ev.clientY+window.pageYOffset-coy)/scale; return (x >= response.x-(response.width/2) && x <= response.x+(response.width/2) && y >= response.y-19 && y <= response.y+19); }; decorateTrace(); var bg = new Image(3138, 2184); function drawMap() { var ctx = canvas.getContext("2d"); ctx.save(); ctx.scale(1/scale, 1/scale); ctx.fillStyle = '#ffffff'; ctx.fillRect(0, 0, 3138, 2184); ctx.restore(); ctx.drawImage(bg, 0, 0); drawTrace(); }; bg.onload = function() { canvas.getContext("2d").scale(scale, scale); drawMap(scale); canvas.onmousemove = function(ev) { if (findDecision(ev)) { canvas.style.cursor = 'pointer'; previewDecision(findDecision(ev)); } else { preview.style.display = 'none'; if (overResponse(ev)) canvas.style.cursor = 'pointer'; else canvas.style.cursor = 'default'; } }; canvas.onclick = function(ev) { var dec = findDecision(ev); if (dec) { detailPanels.setDecision(dec); detailPanels.show('decision'); } else if (overResponse(ev)) { detailPanels.show('response'); } }; document.getElementById('zoomin').onclick = function() { scale = scale*2; canvas.getContext("2d").scale(2, 2); drawMap(); }; document.getElementById('zoomout').onclick = function() { scale = scale/2; canvas.getContext("2d").scale(0.5, 0.5); drawMap(); }; }; bg.onerror = function() { alert('Failed to load background image.'); }; bg.src = 'static/map.png'; }; ././@LongLink0000000000000000000000000000015200000000000011563 Lustar rootrootrabbitmq-server-3.2.4/plugins-src/webmachine-wrapper/webmachine-git/priv/trace/http-headers-status-v3.pngrabbitmq-server-3.2.4/plugins-src/webmachine-wrapper/webmachine-git/priv/trace/http-headers-status-v0000644000000000000000000144573212305126066032432 0ustar rootroot‰PNG  IHDR Bˆå°vÍsRGB®ÎégAMA± üa cHRMz&€„ú€èu0ê`:˜pœºQ<ÿŽIDATx^ìÝ œdey/~LâÕÄ«ÉÿÞĘ\·˜`î½IÔh”qÉ¢‰&¨j£(*Š‚ƒˆÄ]@EqAed†e€a‡a؆Fd“YØ5^ù?UO÷Û§OUWï]Këó~šÓ§Îò¾ßsªºéúÍó>áñÇßȃ @€ @€ @€ @€]ˆ“ @€ @€ @€ @€º(°QÏíÔ @€ @€ @€ @€1&· @€ @€ @€ @€]cêòpz @€ @€ @€ @€æQŒé¶Ûnk½Þk×®ÔM0Ùí'up @€ @€ @€ @€˜Ÿ3cЍÐöÛo¿xñâVÍêS{î¹glÖáGè¼Af’ÆÚ¦µ×_}l\ëUv©m¼©íÝpÀìºë®óóF1j @€ @€ @€ @€³'0ó1¦Í6Ûl¬SyêôÓOmòqØa‡Åú6•5±©£ê·Wª®yì±Ç¥u}lI£8`¶ªßÖH™aŠ-'cŠ Sl,Æ4{÷¢# @€ @€ @€ @€Ì[îĘªÜ‘"+ùT6‹¼QÛüÐXëcãxꡇª¡®ŠUF &cŠãDÊ*¶œ~Œ)椋„Vô*bàåQ»ÿªOårƶâÑ6tÕº}N~W;Kn–OµË¸¯„L˜`m~½±úܺ¾:œÖÓÅaË`óÙêš2eãZÇâhÕ½ªwE‡ÁÖNT¶Œ£µ?×ÔN4ÖÅ­ÝünƒØrùòå¡_[»É8`ÞQåöhK}‹Ç½¸6 @€ @€ @€ @€tK`0cL‘í¨æ“"ð‰¥’>ÉLR|üǸ1¦Ø+O%‰tÔ4«1Åî£É U°Ô”Ê› s]ùTyd%+HµÞ+åPeû¨›å,x幜OµK‡1ÏGˆÒV9-`ªsŸcËëeHeÊwRt£LuW ëD¾$zXzÕ6«”+ÆÔy­Ù 8Nç]Z‡»TãGa‡ÍlÍX«d‚gìcK&OT¢fÕÄO-x1²Lbu¸Ž­Ã‰{ IbL倭۴=W‡³dð®:мCJ©Ü-yäè[mD­Ú9ð)ß½v$@€ @€ @€ @€̪À¬Ä˜"TIŽÚ#£EµB;1¶Ìµ®¯; Ï´B´]ŸéjÞ%úSêU2‘SuûiƘb÷Rª5¬S‚2"A]Œ1e©¡Ú%ˆTM™¢®sÀ(vœƒS\èˆþDW«5ZCEYʨÃëªÕ¹dVcLåàåf¨v2‹`åšZŒ©\ˆ²}[í¸‚ó­ Ó%—\òOÿôOo}Û[·Ür‹-ãË[·|kõñ¶·ÆSok¶üOs¡ÙF=;Æc‹-·j[lñ–-ÞÒã-úüú׿þ‹_üâÃ?<«?Eœ @€ @€ @€̈À¬Ä˜2EÔú˜S™Z«:kXœ¨Z7¨VئÀÍeŒ)'§+§n1•lMfhâkõ‘;vˆ1ÅîÕí³|T‡Ó¥I‡]j·Wk‡«tèsÙlâ1¦Z .vÌ”[ç³d£<],”ÄXkð¨6É`ë ©Õ¹$áf5ÆTÎÒV»Ú«ˆ4Åcû¸ÏËH«i«o›ç›‘·’Þ<ÈvÛm·ù–o>ë‚3NYvÒ©g.]vÎégžæ9ËÏ>Åù+.½ð²•—®¼æÊ«¯]uõuW_s}£ÅªÕ+/¿ê²‹.[qþEçŸ{á9gæç.;í¬SOYvòI§-9aéâãO>Ž=æ„ï½xQ´EÇuÔqG6Ú±mG{DlÿÝŽŽãTÛ1K¾Gk<;áCuØòÄÓ–ìðÑžö´§}àèÍ«£W @€ @€ @€ @ *0+1¦¶¥•ƪº4ÍjL‘Xªå¥"Û‘³³å£sq£q'•«bM§S­šQkN¥ô3AJ*+:=jÍrUS\1„¶“ÊÕNQÛ¥ö:©!:SöÍXL‡>—ãÌHŒi,™8KµXQµþVÛ)Þ:w&‡S½¯J%ª™1u–qcL1Þ¸ 1äØ2¯~mŠÀ¶ÌI÷æÕ;à—¿òåsWœ}úÙ§yÞôÒEç­¸tù¥W^rõu«®¾~ÕE—\xÖ9gž¶ìÔÓÎ8íô3-Î8{ÙòD¼iõ«›y¦ /¸øüsW4òLËÎ9íÔ3O9yÙI'ž¾dñ©Çgžé¸9æÄïF)bIjKŽŽ£}ç¨oïÐ~{}ï¯î÷•½÷ÿê~ ÷=äðCŽ=ñ˜Å§?‰£}Ò8ÈÒ3OÙúý[o»í¶óê¢, @€ @€ @€ô©@ßǘÆedÔ£íå™ËjLµøKkN%RDYL¨7'•‹‡daÌ2NŶCŸË.1ÕbpŪóY2u”ùª\ÎS·²2VÔdëE[+ûTÝrfcLÕ²[Õ³´1Å|pÕ‚^ÕÎG˜¬v“·ÕŽqûzéÓ7²±ºý•½¿rá¥dŒé¼ ÏY~ñòKW^ºêš•—\vÑ·¾shÌ÷ìç<{£'lT}üÏßÿŸ¯}Ýk¿¼÷—/¸¨fºòê+¢nSäŸÎ>ÿ¬eç,kĘN?qÉ©'J#Ãtì’c¢,S¤—²,ÓDZlõ–>¿çç_ýšW?éIOzâŸø”§<%~ã7~ã…/zá.»íñ¦H Mü€N1¦÷m÷¾±n›»Ö†C€ @€ @€ @€ý.0ø1¦Zþ¦zÁz*ÆT õfŒ)缫ÍUW2=]1eħ:G^|}ŽË=‘àQíeÜa8eKkN®mý§ÖwŠg©ÕîÊ}ËÒZT©õPmcL¡4cL+.[ÉE†é‹/¸|Õe«®½êØãyã›Þø›¿ù›™^ú­ßú­§>õ©OúÓï÷~ï¿ý·ÿV"M/}ÙKúæW¬¼|åê•9æVœÖg~öéKÏ8å¤ÓOÌÙå¢xRVN*ÌuN2EòéÛG~k‹·mñ¤'?9Nú‚¼ ¦½ûò—¿¼óÎ;ÿÝßýÝÿøÿã Ox¦¯Þtÿ÷#O$Õy›SÎ8ù½Û¾WŒ©ßNë? @€ @€ @€æ‰À€Ç˜¢ÂM‡"@scªMjs´E5R¨ë1¦(VT‹+å‹¡:½]|›™˜ÈÖÄòÔbLµyÐÊY¦P©:‹\§¤‹ª¡¢¸"!S¹•ic¤9a_õÑa8yG• ø2>•y©òh1Mö,©öå£z‡Ä·qÒÚ³y!Ê£ím«mVøà}ûÕ½¿zÉ•;”aºüº›®Ýï€ýžýìggVéþÏÿùÿðŸøÄ'ân‰[⤓NúÌg>ó–·¼%6ˆlSlð»¿û»øàöË/¾àªÕ+W\ºâ¼‹Î;óü3¢¶SăNãÜe§uêÉËNjL-7º SçÚH'œºxÇ?üã?ú£cŽ9&Ïû­o}+Öl½õÖùíºuëÞµÕ»bÍæ[l1©idcê—U?  @€ @€ @€ @ <ÆAågÚÆ˜"êÕzÆ*49¹¢3µ,QoÞ‚Ó)Õ†Úö0Bš~ç#ÔZ iú‡Ô"¯6µE!0ñÎOù,1–¶·bcçg«™ëšÎl1¦•«¯¼øò‹¢Ó7=83LOyÊS¢êÒÏ~ö³ÎŒÚHÿëý¯Ø>fÛå»\wãµ—\yñÖùgŽd:åøãN<¶Qfé„Eç•‹éä¾ñÍ^ü’?íiOÛwŸ}~òãçÙ—.]úÿïÿýÜç>W:sÙe—=ç9Ïy泞¹ÇW÷ˆ½¦“dc€{Ø @€ @€ @€ 0f8ÆqHêÄL[­‚c=Õa—r8fÛ`ÍXëËŽ‘P©–Þ©õ*O]+¼Ô¡S<Õ9ßÓù¾‰M'5g7eky¡Ù8uhÌ͉:w>.èÄÓHSv˜›³tîÞ¸/–)®—wüÚ>_[uÝÕW_·êÌsÎxíë^™¤'=éIŸÿüç'Øç“O>ùÿøc¯?ÿ߾軋®½ñÚ—^xÞ…çžqÞ²SÏ\zÒé'F¥FA¦%Ç|wñÑcL'ž¾äc >‡zÛÛÞö_ÿõ_ÙŸÿüçwß}÷š5kn¿ýö˜`®ôj¯½öŠ-cú¹ØKŒi‚Ëf @€ @€ @€ Ðï3cêwŽÙîLéÕ!V5Ûgwüy+¡±(6‡ÿµ}¿u˜®¿åº/~ñ  úßøw¼ã?üðÄ)?üðßþíßnÄÞþ¶ëo¾î’+/.Ètú)ËNnÌ+wÊqÇžxLdúî $ÓX©£(Œôž÷½û OxÂ>ûìSÎoo¼ñûoÿíéOúATÖŸ}öÙO~òo¿âU¯ˆ½Ä˜&~±lI€ @€ @€ @€}- ÆÔ×—Oç è$°Ï¾_[sÇ­K—ú÷ÿ÷¢Jþççw^îÕÖ­[µ¸6lØðË_þ²¶ò¾ûîûÕ¯~+ï½÷Þw¿ûݱïŸþÙŸvÄw®¹nÕ…—,?wùÙËÎ9}é§œxÚ’ÅÍyå¾»äèqcLïÚz«ß}ÚïVg–<ôÐCãÈùØzë­ËHV­ZõüŸÿò¿ÛDŒÉýM€ @€ @€ @€óG@Œiþ\k#%0ïöÙwŸ»ÖÝuÐ!ýþü~”bÚn»í’à®»îŠÿê¯þêyÏ{Þ&›lrà>ðÀ1¿Û'>ñ‰¿üË¿ü“?ù“W½êUGydÖm:öØcë·~ëIO~òÇvþØM·ÞxÑ¥+FÍ+·tñq'{Ì ãWcŠÓSÿûS9æ˜r¢ÔS‰1•¾Å³+W®ü“çþÉߊ1ͻր  @€ @€ @€ 0¯Ęæõå7xƒ-°ï¾û¬»oí—öüb¤…~ÿ÷?bC1ÞH,Eé£X³Å=ëYÏzò“Ÿüßÿûßyçßÿþ÷Çʧ<å)Ï|æ3c¢·ßû½ß‹$SlAF¶)žÚâ­[¬¹ýÖ‹/¿èüçyþ§uÚÉËN:áÔÅÇ|ìD&•{ïû'ýâ¿XÌ£êR„¨båsžóœj•¦SO=õ7~ã7_õšWªÆ4Ø÷§Ñ @€ @€ @€ @€@U@ŒÉý@€ÀÀ ì»ß¾Xÿù/~>¢BñqÑEÅPO9唨®ô›¿ù›ýèGcò¸ÈmµÕVÿùŸÿù;¿ó;±r·ÝvûÁ~ðÉO~òMozÓÕW_ÛÇÜsïxÇ;âo|Ó¿wÇ÷.¹ââ .:ÿ¬óÏ<í¬S#Æ´äÔŽ?ù¸qcLKN;a×ÝwtÔk_ûÚÿøÇEüÛßþvy›m¶)kþë¿þ+2UQ;ê?Þó®ØkÑñGM¹E ê½Û¾wûí·Ø l` @€ @€ @€ 0@bLt1 …ÑÓƒë¿ð¥FŒé5¯yMä“âùÃ;,¾éä–-[V6?ꨣbåŸþéŸVWæ³<òÈŽ;îϾéÍo¼íΈ1]2…Säœ=âWÿëã8Ÿÿüç{ì±<ø¡‡kÞýîw—žœp O{ÚÓžÿçÏßÿÀýc¯)g˜bG1&/ @€ @€ @€è#1¦>ºXºJ€Àäª1¦W¾ò•·ß~{ìÄGDr(¦“;ñÄãÛŸþô§ëׯ?è ƒb峟ýì¨Õ”+×®]û³Ÿý,–£xÒ;ì0ÍS„Š¢´ÒîŸýTL`eŸ¾úÕ¯F:*óÇýßÿû?÷¹ÏÅò/~ñ‹ÓO?ýÏŸÿçQjëm¶žf)&1¦ÉÝ+¶&@€ @€ @€ @€n ˆ1uû 8?³&04©Ü>!¤ç?ÿùçœsNœêì³Ï~êSŸkb.¹[n¹åÃþð_þå_Æ´nÏxÆ3båvÛm+?ô¡EÎiñâűýÝwßý–·¼%žÚìM›MyR¹½xÑñ'÷Áà)Où'?éÉQáé†nˆëxà˜Û."V‘mzú<ý‰O|âë^ÿχ}ØwO8z:¥˜Ä˜fí¶r` @€ @€ @€˜1¦YauPzA`ß}÷Y{ï={}u¯¨oô»¿û»Qr)zõÐCí²Ë.ñm$“žÐ|üŸÿó>øàÏ~ö³OyÊSÊʘ`îøãí¯ºêª¿ø‹¿ˆõoÇÛoýþ-_~Ñù+Î;óü3N;ë´“—t©‹;ùؘý-RGTê<ŠmŽ=ñ˜wÙé™Ïz擞ô¤'?ùÉ/|á ·ÜbËø‡ˆdU˜~ÿ~ÿmïxë·úö4§“Ën˜T®nB} @€ @€ @€ @€ lôðÃßÙî1ÁýmF€ DÙ¡Ö7›{î¹g‚»Oa³}öÝçöÜ~äÑGn¼ñÆ‘CzÏ{Þ·Åq~ô£zè¡Qcé oxûÞõ®³Î:+VF÷¾ò•¯ÄšýוQ´é×ÍÇ‘GûþÎS~g·Ýw»áæëW\ºâ¼çžqÞ²SÏ\zÒé'ž°tñq'{Ì Š1eM¦ØþÀoøŽ­ÞñÜ?yîDý¥?|z´?þ_üú}ýÞûï9§qãP¬Ò$Æ4…{Æ.´ˆy0ýºèÞ @€ @€ @€˜mâC© Û=fûÄŽO€À|¸õÖ[[ßl®¸âŠÙsØg߯Ý|ÛMË/^þ¶·¿-¢HÏ{Þó–.]:©ÓÝqǯýëcß¿ü«¿<áÄÅ«V¯\~Éò³—Ÿ½ììÓO9ã”O[²ø”ã#x4ÁjL?Š”R–n:ê¸#<öˆl±OM¤¤Ó3Lª1MêBÛ˜Î6lð뢛„ @€ @€ @`¶Ęf[Øñ ˜ûÓ¾ûí{Óm7G’é€oìÿ;¿ó;‘FŠbK÷Ýwß/ÉÏþó/~ñ‹±×oþÖon·ýv·~ÿæ+®¾âÒ•—,¿ä‚s/<÷ÌóÎ8íìSO9óä¨Éy¦%§ž•™"Õ4ÁÇ.Õ6©Ý'r–3/8cÛn»ýöÛOp¼6#@€ÀXbLî  @€ @€ @€93ÆÔvê+  0eU«VÍq5¦=÷ÜsÙÙg\~ÕeW^uùû¶yïžð„È$½ï}ï{ðÁÇ}{ýÙÏ~¶ï¾û>éIOŠ]^ö²—ž~ÆiW_¿jé²¥G}Ä·ŽøÖ7¿}ð‡.<àà¯ïà~û}cß}¾þµ¯}}ïh{ïÿÕÞi}ëÀ-Þ¶Å;ßùÎ)_2; @ n¸áÕ˜ÆýÁa @€ @€ @€i Œcjûa••˜YYTnë­·~îsŸ»×Þ{]óu§œvòËÿîå‘IŠÇ[ßúÖk¯½ö¿øÅXo ëׯÿüç?ÿä'?96þ£?ú£}öûÚ-·Ý|Ô±G½bÓWDjšìC>2Y• µåižeè€OØèo|ãÌ^2G#@€@˜æ¯¡v'@€ @€ @€ P0©œû9˜ûIå"Æ ¡?þã?þŸ¿é{7->qñ‹_ò⌠ýÙŸýÙþûï%F¢2Ó£>úë_ÿ:¦{衇֮]»xñâW¼â¹Ùÿøÿã3Ÿýô÷ï¾í»‹Þäo7©&¦¼ü”§<åùÏþ ^ð‚§?ýéqßÿýßæÑžúÔ§>ç9Ï™ò‘ÛîhR¹9º¿†À@ ˜Tn /¯Á @€ @€ @€zE@Œ©W®„~xnŘ"Üóìç<û«û~õÆïÝtÒÒ“^ý÷¯~òo7Ê,Å#2C[n±åî»ï~Ì1Çì½÷Þ[mµÕ _øÂRiã7Þ{ß½¿wÇšS–òºyÝL¥‹¶Ûn»‡~øšk®Y¸páŸüÉŸl»í¶K–,yÆ3žñ¦˜ïÀœ©åqĘþ•e€æ@@Œi‚ @€ @€ @@ŒÉ=@€À t1Æ”I¦¯|í+×Þ¸úò«.Ûy—Ÿù¬gþöoÿvÛÀПøÄ§ÿáÓß²Å[N=ýÔ›Öܸdé’×½~Æ2LqÆ \|ñÅ/}éK?÷¹Ïí»ï¾¿ñ¿ñ|à ƒÚqÇ¿ùÍoþæoþ¦ÓÝ‘NC€À„Ę&LeC @€ @€ @€© l4õ]íI€ÞÈIåÊãþø>ý¹ÿ¼èÒ7ÝzÃ]°ë§>ùŠM_ñìç>;"Mdzžù¬g=ëEý¢í?¸ý)§|Ó­7^¹êŠC¾sèLÍ%Wºå‘¢ÓÊ•+£SÌm—ëwÛm·¥K—F¤if3Lª1õöªw @€ @€ @€ 0" Æän @``j1¦Èô<ñ‰¿µÙÿíèc>oŹW\}Åu7^wÃÍÑ®¿ñ–¢ÝpËõ×ßtݪÕW­¸dùIKOüðŽþý?øƒÏ}ò“Ÿ¼âŠ+¢Ó—¾ô¥o|ãyü˜Øî¬³Îšñs‰1 ìÍm` @€ @€ @€81¦»¤D€À°@kŒ)sBO}êS_ûº×~qÏ/~÷øïžxÊ’%'Ÿ°ä”F‹åã—·ßû½õío}Æ3ž1¡¢8æ[ßúÖ˜_鍊nŠS™Bn»í¶‹yåfãŒï}ï{Ý @€ @€ @€ @ ÷Ęzÿé!SØa‡:ƒžÐî1Y¢Ú1cò¸'>ñ‰qò²>;2ã§þíßþíOúÓSä³ @€ @€ @€˜C1¦9Äv*æV ænÛx~<ž÷¼ç=ó™ÏüÓ?ýÓÚp#Ãôë_ÿº­úÂ… 7m>baj—eýúõSÛ±ìµùæõ”CNðØÛl3t„\Ƚb@SÓ¨þÄ1׬™æ§ÞŸª@fµ7Ñ·¶ë'ÞãVÿ‰ïkK @€ @€ @€̸€ÓŒ“: æZ`Æ ^xáÃ?<ÁGziÁ‚«šm¶Ù&–'¸cu³Í§‚ÙxãúiË!'xìÚöùí{4Úô›núøªU£‡­­™ÈY¦ÖŸª@[èIôp:Vÿé; @€ @€ @€˜¦€Ó4íN€î L*Æ´hÑ¢Z)¿õ‘jÚ£™ŠJK±5Ãõˆ–/_žk–.]D §¨ü”•œjÇ–±WîËñ (b4ñdœ0‹'År¬Éoc!¾>òHce,ÄÊr˜QZ´hhÇ\({Å‘ËʽJ9¥ L*Æ¡¥Ì*ÕQ¢)ŸŠXRD”"® ¤Xi¤xÄB„œbM<߯r>ÇBl|*Žk2Æ9§“ÖEŒ&¦E‹8NăJr(¾Í€N$b!óL™pÊàQ)MûæÌk¹PöŠÁÅÆÖ‰ðM&ub9K+Å¡²‚Q5oTÛ&RGm4t´Ü+ÖäIc!ŽXkªOåªkb›X§ÎlVõQžÛäs÷8Nf¤R Œ.–³3I‘89–laÌ5 [Ž_ÎÏãĵçS)Ü:–oì5ÁBYóéõg¬ @€ @€ @€ÌŒ€ÓÌ8: º(0©SfŒZ{›A¥XÏÆLsÕ)çy䑈+ÅS%ÏËYÃ)K4åÑ¢žSìX]ÓÙ¤Z (絫MW7-B6µ¹ïÊ”je¡uR¹|ª:=\qâP­1¦Ší£cyê2…\ ?åšÖ§Ê–%'Tz••ª2ðìI9W,T³D¹K'j;ef«ä™ N¦âÙRö©vüê©«=ÏÍJ‚*1©ÚXªã³Ls&»Î·„g  @€ @€ @€˜ÏbLóùê;"0©Ó‚ j1¦ˆD5Æu•âÛ|D2)2LZÊåx*ÓNcН9Í\<²DÓbL%‘Óc*Ñ¥j¤)ÎÙ|ª,4;ÓXS(ej§Äzʳ­1¦ê6¹Wkâ'#GåD9êÜ,žÊM“*»³Œcʳ‡±W¶E~-£‹üP¬‰g³ŠRìR@òŒñl´ÌK•±äñ³·‰ºG­Õ˜2TbLYµ(ùT|›bCóÁM¤SÆŒ²ÀR>"®”ÓÌåXÊ0c³’èÊ(R ZµÕbLC‡nþ§ ³ô¼º&§ö«%¶l ?Ui™ @€ @€ @€3" Æ4#ŒB€n L*ưQ–MŠ…È0Õª1Åñl’b!&’‹ rû¨Æ ‘sŠmbÇØ&æ›ËóPQ·©cŠ-sã¶jÚ&³8YÍ(“4‘ÚÉ2E±&–cƒÌ U‹•oóø¹Wk5¦ˆe-¢,\²&Ž–ÝÈ,Qìžkrö´2½Z‰1e€) ÅK¤Ü7×äÆq®hÕmâÛœ®5fT6Žã4kc ¥”>ÊÉæÊ5cLÑÏZö<·ïcÊaæqªÏ#$NëXĘºùòvn @€ @€ @€óF`†cLW^yåâÅ‹gOʃ_ýõQ d¬~úé±Á”»ûÆÆ=Ë”?g;Ƶxì±ÇfötE¾ó%˜ÈI£o³z·L¤¶!0“1Ũ#oá¤x#…Dˆ¸RU#ª4UßfãÙXGn)y„œ].±P–˱¾ºÜJ]BBͳ=Ÿ+£S¥àPÒ¥Z^¨o*je^³œ¹¬Túi <åle¹c­@QíDÕøN9QìGhÛ‡RL(7.ñ r–ìX~›sÏÅfÙáêñ3UÍNµ]m›¶Y«ê]UMU#GÕüSn_ªCå·U̬¨”jÔ)ëBeZ«æ©¦Çªò­Óùå|‚µGµÃÕ^ÅrõZ”³”ÉûÊqjQ­ªŒeŠ€“› @€ @€ @€ú]`bL¥|QZä´k9›X†‡r}©WT%«Vú)¹–Zž&B6qÌêüqµèO5áT1mÃIÕþ”n”’N¹&ž}γä³"T<Ê wÕþä69äj«íèªÁ jE¢¶Õªª£¨v¾Š\RÝ`,Ì(”£‹þW§É‹oÛ²Wm‹I^Ù0*çªæ¨b˜­ ¤ê)ª÷C9KUµÚÉ~™é?Ù˜lŒiýúõ .Üc=-Z4Û}ëpü=ö˜îÉK÷«ãˆLiKѽ©œháÂÇyd*;Öö™~Ú^¥è[ôp:iú¯_ßpž¦Ò4q¦0@û @€ @€ @€ 0³Ó1e(§Vtg¬zH­³¹•yÇr6±Ro©3bCY+(žŠàK&oªQ¡,UŽ\ ÄÄS%~”“Á•I⪈9„œ7-NWž ùlNuÙl³Í2“޽òŒ¹q-ôÓvtÕmª‰ÚVŠÊˆXŽ¢Ì—uªE•r8Å*ûVŠEŸDÈ£•#d"ª”’ÊKYU›º®Š“+±Wémö°5ÆTN-â–Ã)“ÊUû0³w¼£HIŘ"ôñÆ/X° bLÛl³Í¦›nÚ-“7®Ÿyó͇֔…Î}+}Ï…Ü+Ò9Ó èäI㘫V:Dvjk&B7µþTÚ^¢èÉ4/]«ÿD†S¶‰qE©UiRqj8¥ÓG¨ ¹Ã7Á{rR†6&@€ @€ @€ @ *0ÝS­|N:")‹‰òBÕØP,Gº¥¦Ÿ•2¢!›͉xPfƒÊšLùÄ6qØj‚'–«ßÆ™ž‰ÍªYŸ¬ÔÚìO™ý-²ÏÕ³ä©óìq®øš{e'³>S°ÊÙsƒ¶£‹mJÀ¨º}mß:Ÿ¦èU³J72ÅUb!7®­•=ŽS2jÅ$ K9Qœ«ô°(U¯xu8ÕÎT{[[³¯vÛø–šÀ¤bL‘^Š S9BĘ֬Y“ß®j>ÊSe}.<Ò¬MT6ˆ8T,ÇײýX»u½"F‡Œæùc931™M)+c¡*Ë‘¡É¸R.”½2SÛ«Ùó‘ãĹJ¥¥rÀJ,Ç×ÄÁ«kâ©ÒóZu¨ÚÀc÷Ø2wÏTPK]Œ=;S(J!¢X+ cUa«7OAÎaÖpš—®ÍXÊxó\ùHÉšR9~Y¨ö'6Ž ]}t¾Xcõ'¡òk^∗•‹•Q³]v;£Nyõ+ù½Æ6¹2S½[µk÷d!/V‡ãªo @€ @€ @€O`ðcL0Ê FãQLîùÈEe£\˜Üζ&@€ÀŒ L*ÆgŽ$SdŒ"ÌÈÅš… –MY®©mŒ©l;f *¾F¤)Ž_sL™yšÈø²SnÊ W¬)å»r\e›Ì*å£R*gÌQ”ê\ÙùVíX™OUïɼŽ_•·L€ @€ @€ @€À¸ƒcŠ9Ñ"l4ÖtrãuØ i€éľ˜¾ÀdcLåŒñ©£Ì!EQ¥\Ÿ¦¶1¦Ì<Å#bLÕnÇöŠªF£ÆW9F‰†´Æ˜JÆ¥‰#Gh&³)e!–[+-eФÚÙÌú´Æ˜ªÛä^ùux¼ÿ–SµÎT)É+³8PÙ}سMŒ©úTœe£,­Œ¥:º,õÏ”U‰ÐOYŸ×§ k"©“½Ê…2¨RN©zêØ>~¬UÇlÝ+ð³8V«RkŒ©$º²oÕþT/Dq·?Õ‹•§«î’>µm²8SÜãÕ³§a¯Ê„Sé|M»<ÕcʧÊñǽím@€ @€ @€ @€ÀXƒcrí  0ð“Š1U+'…L$“Ê#¡"ÕÃM<Æ•œ"ÆT2,Å'šHŒ©ÄJ"}R,²;Y³§,ÄòX1¦jÔ&ò7Yü©THÊnÔâ8cL±q©ëSjÿd¨µìX²;¥ÖT¹k1£ZB+cF9–2º~))T­Æ”•œ2QT­Æ”çÊZAQj(cO±Pfö0¾–8nž:XK ';V®ËDbLe¼Y̩ڟ¶1¦qûSXJ@UCKe‰P®Td˜²DSÑ(‰®Ì6•qµj—§ZcLµã—«l @€ @€ @€É ˆ1MVÌöè9IŘ"o”sÉEÞ(H11Üš5kbedÊgãk¬Ì5‘jŠ…Ø8ÓN9ø˜].£Nñ5–c³,à 9ßÜ#<ï,ÕcÊŠAñˆ§"t’5u"Ê““‘e^¤L?—ÙÈÓäBÙ«5SªÅ¡ò¤±ù›ˆFåšœž,Ni¡X“›ÖjLñl†â¼¹{¦‹J‡s÷xäXb›Ø2ûßæ$zµSuãØ=ÓZyÀ2º ÖÄÑrñ5ó4cŠå$*IŒ1U9ÌX¬<ÖdÊ'0ÛŽ¥ZÃ)NZËTÿ2–êB0•µ›¢õb•vèO²§ÆÊšH*ÈY­*X­ {¥vjäˆòªµj—+R|òBäëø£è}C€ @€ @€ @€ÀxbLã yž=/0©SŒ&bFHвLñ5–s|‘dÊ R©«™¤ø6ÒH±&bIñµ:f¬Ïgs÷Ø8òL倉1•„M„{ò0‘ÅÉêAYÁ(“:ñTÎt–Ü«ÄhÊB¬Ì½b˲qIE„%3%ó”‡õYÕ©œ=ó@ñ(û–“ƾyüØ ÏUB9Ùó<~W®ÉŒQõ€ÕWÇ‘šÒ™<~utÙá uE+h¥'‘.Êþ´=þÐ ›­ñ-'r´ê6Ñ]wÝu¬nÌÞy'ÛÏ®lÿÐCu>ï¸t¥ÛNJ`€&cêŠÚlk³Úí •(U­fOëy«…šfµWƒqðêŒoƒ1"£ @€ @€ @€ @`6z1Ætúé§G„¨ÃhãÙ Ê\ýõpÀŒ»¬]»vûí·¿òÊ+ãøÕƒWÏÛ¹‡3Þ¥Þ9`\ÎæãnÐ;cÑ#0¨1¦êäesp±"ɳƒEËÙë:qäHÅ#V–ÅcMl•“ÊÁ3`ÈBÅrìOeu¥ÖkSíUž4ÖTO‘»´ž·Œ±Úɶ/'ãGgòø±¥žZûœa©ìpHìU’Âùhí|¢e9«µŒòÔf+aRÂ'6.õ“ª§(y¦’Œ‰sU£6Õ Oѯ–kÊ•cu ª!—«É8Q-ʨc¡š¬Ê«}¨n™ËeyüR䩊ƒdÈi¬Î…Vº]Û¡Õ[6+H•™ìâÚU§ºËaÆ6±ë«TÇ[íXlV;l¿Ht@Ï ˆ1õì¥Ñ1 @€ @€ @€˜¬À ĘªóµÕ2@Á‰tNLLVI¹A)ATº›ÅâÛR§šì)uŒªÇ/ɘê–e.¶8o)æ‡-á§rÆZ¨t Êí«ç­&uÊYÚ¼v1ª}¨–\Š,Tú$WîUê•…XYŠ0Õù*EégÛöí@µÃÑ¥œQ.I³‡e¯ZY¦2Õ]õ°e¼y„ZÛÃNö®µ=) ÆäN @€ @€ @€ @€˜S)ð“(XÉ9Ñ"=S&›++3îqœLäd´%·ŒÉÚr÷ئzœ¬á”ÇÌÂ?¯)ç¼N–>Šc–2Hµ°QkŒi¬Ôêå jç-a£rê±^n”Z¬ª0ûœ!¡œú-GWfÊ‹5iëKÑ£zåŒ%QÔö°m;P½­‹d†Ò?'΋…œ.°tu³Í6+W-7È©÷òBG -—óªåŪv`^NB`ŽĘæÜé @€ @€ @€ @`öf ÆTfË^f¡ œ‰,“+ñÈO®Ì˜Kmef˜"ÚRŽ–A™,/T›•Lõ¼™Ô)y 8Tdeʉ"&U¦B«RV{•ˆG¶,—kç-㪞¥íÀË¢¥$U®,}ާÊfee™“.“CµÑµÕ‹NVMªþ­‡«¥'%~TUÍã¤O,çÍ TV޵A¹ía«Å2xä‘G®m÷øÅ/~1ñƒØ’ @€ @€ @€ô‚À ĘzaƒÚ‡Ú\uƒ:Lã"@€ @€ @€ @€˜çbL=}D§Z±«žî®Î @€ @€ @€ @€˜’€Ó”Øæj§˜e/su6ç!@€ @€ @€ @€ Ð1¦î¸;+ @€ @€ @€ @€E@ŒÉÍ@€ @€ @€ @€ @€@—Ęº|œž @€ @€ @€ @€.ǘ/^üØcÍÈe¸þúë—/_>#‡šþAfp\¥3§Ÿ~zŒqú}Ë#{tr¦Žæ8 @€ @€ @€ @€¦#ÐåÓöÛo?ÞW÷PN}fêhÓ9N$„öÜsÏé¡í¾»îºëm·Ý6S‡DTp¦Žæ8 @€ @€ @€ @€¦#0“1¦‡z¨µ+k×®m]™[F(§–¤i{„¶Ã›ø–ÑiÛÉÎ;Nj—‰÷¶ÃaKä«õhc¿íú\©¯Ã;l\œj­¬I yÜ#Û€ @€ @€ @€ @€@˜™S’âQ›މ LYY¦{»òÊ+seylذÁÅ#@€ @€ @€ @€ @`0FbLwÞyç7¾ñ‹ûáqÔQG-_¾|0.€Q @€ @€ @€ @€ 0*ÆtÈ!‡¬é‡Ç’%KĘܻ @€ @€ @€ @€F@Œi`.¥ @€ @€ @€ @€èW1¦~½rúM€ @€ @€ @€ @``ĘæRN} ëׯßxãÍÓ7uÁnï—/›o¾ù6ÛlÓíî8?^Xºt馛nš¯Ž ôJ·ôcªïÃñV3ôâ(©·Ê]W~è­þéM ì±ÇÕ{&Þ©z¬ƒº3Pñ¿–q•w'?êêvL\÷x·)›ÄrõÛùã`¤ý"wìªU«ú¥·sÜω·ñ9>i/Ÿ®ö†jðG†^¾^³Ñ7¯ˆÙPuÌ® ä/íÕnÄÿ·Øõë2ÙÄE\¸paÙËo8UÀÉâ«ÿ7™ì­eû(x‰Û;‹-êñëÉ ˆ1MVl·Þ~=íëëZýŸˆ1Ugíëqé<éÄçgñÒ(›ÅKÃÿ¨LÇÓ¾âf+Ä›°¿oºaæ@ z×ÍÁ霢ß„ úý öQÿã·¯ê?’‰¿£ù±ØG—oš]­}6àgšžvŸm¸cŘÆBcªÉTßÐ|:Û¯ÍÞ<¾ßgzóºèÕ4Z?ùδÇ4k÷9È@Õ ò¼~Ã)þñã;4Ræ‘G‰A¥çøætºY¨þRZû8lVÏëàæL@ŒiΨ{÷Dùƒ¼ü8ïÝŽêÙÕÿ‘ö—b· ˆÿ-©ÆÏã].Š3Á!0Kµ@IÜ~¥³Dí°E@ŒÉÍ0)¿"NŠËÆÓhýgþEàt<ûk_1¦þº^zëC¾÷€S §ü*å_ºÏÛ·1¦y{é{àùË[)¿¿·Ç/óbL}wѳS¹Ž~éþ鬤»be$™¼™÷Ýí­Ãjÿîµïn<1¦Á»¦“Qü}"†¬TÉäìzfëøÝ+ÿžQ­g.‹ŽtYÀü]¾óìôµûM\`ž]ÿî 7îºüå-fîÎe蟳æß¦Ë ¼ëŸ¾ëiŸ ø¬Ï.ØŒv·Ì×ÿ²?ÿGuFÏà`fRÀú;hŠ1ÕpÊßÜ|º?“/¾:–O¾ûêréìDòGa¹½ãÿã_z£›(_Ïl—W°ü£J¿áä•iûË œž¹mudâ~Ž?Ç­x÷®Ve›£;˜ÓÓg>ó™×¾öµ/yÉKâëÞ{ïÕæ§öX²d‰jfêæÉ‰–â=Nµÿ™"ûãäGyÆœ{gìM¡õæuÔ^‰1 ê•íåq‰1õòÕéÁ¾‰1õàEÔ.U&æì²,ƒz­[ÇUý+jüÿ©+5.}ŸŽÔçX.œS '~•Šgùg7Í>}ÉO³ÛbLÓ´{o äÂø„(ë§Æ[\|+ÆÔ›«C¯ò *ÊeˆÁo8i%ÆÔww²OV úïˆ2‡:Ù#Øž@ ÌQŒé¤“NzÎsž³ÑèGä™bý’LbL3xW•B>åÈgðà57µÿ‘öÿÕsÃî,=.¿ÃU¯ñ¿pñÿä=ÞgÝë_ZŒÉ¤rý{)û¨çš}t±z¡«ªÄõÂU˜'}¨M죮Õ9Ÿ'ós˜&•›Ÿ×½GíC¾Ökõ³d£S '«1ÅÊüØ?¯íßþ”{îÏ­S¦³c/ 䜯#’Lñcêåë5VßÊTN-ç7œ2µZÔÊÕôã®Ïc øc‹{càæ"ÆtÉ%—” S,TóL‘dcêâM¿ÖT?×ÏTÔÅþ8õÔªÿ#×Ô?˜˜£½L k —ÿQ‰÷:1¦»Ä=5œj $þúãï›=uuµ3bLƒzegi\bL³ë°­ùs°|¾›÷*\1On1¦yr¡f˜>äk½”ñ‡Áüg“ Õpª¿J…’¿¼ ÌûÀÄâó'neË>(? sFàè¹S]¾ÒÕêT|ÀÕ$â:öã@f¼ÏA®~"à‚vÀî ˆ1u×ßÙç@`.bL;í´S–aŠÐRDš"·3Ê•ÂLS˜]N5¦™º3jÕJâ°ÂÈ3e;—Ç)“5Ä‚?ÃÍ¥¼sõ¸@ü1ÿ'<2L=~±ú½{Õ÷áø{AüªÓï#ÒÿÞ¨Þu¹Üû}ÖÃ. ˆ1už:?ü· Ó¼ºjs-yç™WW¿›SçôcÏgµÏåÝÛ´UçÚšÏAgõ&ì̓×þÿ«7;©W&+P~FÚ#ÿ}{üdôÝ'ËØõí«ÊFâ7œrQâÞÎOÍ|@ÐõUf\ÀdÇ3Nꀽ&01¦-·Ü2‹0UKiÊ$S„œ&[IŒ©×n#ý!@€@Ï ”ôì¥Ñ1 @`°âoèƒ=@£#@€À@ øŸè¼¬E€æ­€ßmæí¥7púZ`ê1¦L&Å£5‡ôÚ×¾6ŸŠS‰(e¦ò(SË}æ3Ÿcêë{Hç  @€ @€ @€ @€LS`ê1¦(Ÿ›å”"TÍ!E\©D”b²ð¶¥±ö`žI5¦i^u» @€ @€ @€ @€è)©Ç˜ÆŠ+Eq¦Œ7Å´q­±¤x¶„œbᤓNš`t©º™SOÝC:C€ @€ @€ @€ @`šS1E®(&ËÄRuò¸Î³ÅE¶)w‰Gì~öÙg‹1MóÚ @€ @€ @€ @€@¿ L+Æ´÷Þ{׿•‹YäÚÎ4W²J1\dŠØSÙìàƒžl’I5¦~¿íôŸ @€ @€ @€ @€@U`Z1¦ˆ•ÚKiŠoK>©ZŸ©mJ©Ì=GcrS @€ @€ @€ @€˜ÏÓ1•4RÌWM5EY¦Îá¤K.¹¤D N:é¤I%™TcšÏ·¬± @€ @€ @€ @€ žÀtcL%™¤˜.§Š{ÉK^R%Å6TÊrMÕ‡ÓàÝOFD€ @€ @€ @€ @` Ó1E,)ê0•ôR.|æ3ŸiWª&™¢\Sn³Ï>[5¦)\<» @€ @€ @€ @€ ˆ1UI‘IŠKµLRÉ9ÅS9\ÔgŠŠMmK7M$ÏdR¹Á¸ùŒ‚ @€ @€ @€ @€@ Ì@Œ)‚Gez¸H&m¹å–µ(R[*ÄB>J)¦˜Šn"Ñ¥ê6bLn_ @€ @€ @€ @€ƒ$031¦vÚ©Ä’¢8Sk,)²JÕèRnkªÓÌM<Ì$Æ4H· ± @€ @€ @€ @€˜™ÓêÕ«#É”i¤Ï|æ31—\>b9¦–›xtI5&7+ @€ @€ @€ @€A˜™ÓÔÒHSÞK5¦A½‹ @€ @€ @€ @`~ ˆ1ÍÏënÔ @€ @€ @€ @€zH@Œ©‡.†® @€ @€ @€ @€˜ŸbLóóº5 @€ @€ @€ @€cê¡‹¡+ @€ @€ @€ @€æ§€Óü¼îFM€ @€ @€ @€ @ ‡Ęzèbè  @€ @€ @€ @€ù) Æ4?¯»Q @€ @€ @€ @€è!1¦ººB€ @€ @€ @€ @`~ ˆ1ÍÏënÔ @€ @€ @€ @€zH@Œ©‡.†® @€ @€ @€ @€˜Ÿ#1¦ 6ìµ×^‡ôÃãk_ûÚå—_>?/˜Q @€ @€ @€ @€<‘SŒ-’LwöÉc𮄠@€ @€ @€ @€˜·£bLóVÁÀ  @€ @€ @€ @€袀Sñš @€ @€ @€ @€†€“û€ @€ @€ @€ @€. ˆ1uù8= @€ @€ @€ @€bLî @€ @€ @€ @€º, ÆÔå àô @€ @€ @€ @€ˆ1¹ @€ @€ @€ @€è²€S—/€Ó @€ @€ @€ @€ Æä @€ @€ @€ @€ @ ËbL]¾NO€ @€ @€ @€ @€€“{€ @€ @€ @€ @€. ˆ1uù8= @€ @€ @€ @€bLî @€ @€ @€ @€º, ÆÔå àô @€ @€ @€ @€ˆ1¹ @€ @€ @€ @€è²€S—/€Ó @€ @€ @€ @€ Æä @€ @€ @€ @€ @ ËbL]¾NO€ @€ @€ @€ @€€“{€ @€ @€ @€ @€. ˆ1uù8= @€ @€ @€ @€bLî @€ @€ @€ @€º, ÆÔå àô @€ @€ @€ @€ˆ1¹ @€ @€ @€ @€è²€S—/€Ó @€ @€ @€ @€ Æä @€ @€ @€ @€ @ ËbL]¾NO€ @€ @€ @€ @€€“{€ @€ @€ @€ @€. ˆ1uù8= @€ @€ @€ @€bLî @€ @€ @€ @€º, ÆÔå àô @€ @€ @€ @€ˆ1¹ @€ @€ @€ @€è²€S—/€Ó @€ @€ @€ @€ Æä @€ @€ @€ @€ @ ËbL]¾NO€ @€ @€ @€ @€€“{€ @€ @€ @€ @€. ˆ1uù8= @€ @€ @€ @€bLî @€ @€ @€ @€º, ÆÔå àô @€ @€ @€ @€ˆ1¹ @€ @€ @€ @€è²€S—/€Ó @€ @€ @€ @€ Æä @€ @€ @€ @€ @ ËbL]¾NO€ @€ @€ @€ @€€“{€ @€ @€ @€ @€. ˆ1uù8= @€ @€ @€ @€bLî @€ @€ @€ @€º, ÆÔå àô @€ @€ @€ @€ˆ1¹ @€ @€ @€ @€è²€S—/€Ó @€ @€ @€ @€ Æä @€ @€ @€ @€ @ ËbL]¾NO€ @€ @€ @€ @€€“{€ @€ @€ @€ @€. ˆ1uù8= @€ @€ @€ @€bLî @€ @€ @€ @€º, ÆÔå àô @€ @€ @€ @€ˆ1¹ @€ @€ @€ @€è²€S—/€Ó @€ @€ @€ @€ Æä @€ @€ @€ @€ @ ËbL]¾NO€ @€ @€ @€ @€€“{€ @€ @€ @€ @€. ˆ1uù8= @€ @€ @€ @€bLî @€ @€ @€ @€º, ÆÔå àô @€ @€ @€ @€ˆ1¹ @€ @€ @€ @€è²€S—/€Ó @€ @€ @€ @€ Æä @€ @€ @€ @€ @ ËbL]¾NO€ @€ @€ @€ @€€“{€ @€ @€ @€ @€. ˆ1uù8= @€ @€ @€ @€bLî @€ @€ @€ @€º,0ÑÓ‚ V­ZÕåÎ:= @€ @€ @€ @€}.°ùæ›·Ž`B1¦È0m´ÑFbL}~è> @€ @€ @€ @€n ¬_¿>2Lo¼qk'Æ1-\¸p=öØtÓMŘºy › @€ @€ @€ @€@Ÿ l³Í6‹-šbŒ)Ç.ÆÔç÷€î @€ @€ @€ @€è 1¦ž¸ :A€ @€ @€ @€ @`> ˆ1Íç«oì @€ @€ @€ @€zB@Œ©'.ƒN @€ @€ @€ @€˜ÏÓŠ1m¾ùæ«V­šÏ|ÆN€ @€ @€ @€ @€Àô¦cšþé @€ @€ @€ @€m6âB€ @€ @€ @€ @€î ˆ1u×ßÙ  @€ @€ @€ @€x\ŒÉM@€ @€ @€ @€ @€@—Ęº|œž @€ @€ @€ @€1&÷ @€ @€ @€ @€]cêòpz @€ @€ @€ @€ĘÜ @€ @€ @€ @€tY@Œ©ËÀé  @€ @€ @€ @€cr @€ @€ @€ @€ Ðe1¦._§'@€ @€ @€ @€ @@ŒÉ=@€ @€ @€ @€ @€@—Ęº|œž @€ @€ @€ @€1&÷ @€ @€ @€ @€]cêòpz @€ @€ @€ @€ĘÜ @€ @€ @€ @€tY@Œ©ËÀé  @€ @€ @€ @€cr @€ @€ @€ @€ Ðe1¦._§'@€ @€ @€ @€ @@ŒÉ=@€ @€ @€ @€ @€@—Ęº|œž @€ @€ @€ @€1&÷ @€ @€ @€ @€]cêòpz @€ @€ @€ @€ĘÜ @€ @€ @€ @€tY@Œ©ËÀé  @€ @€ @€ @€cr @€ @€ @€ @€ Ðe1¦._§'@€ @€ @€ @€ @@ŒÉ=@€ @€ @€ @€ @€@—Ęº|œž @€ @€ @€ @€1&÷ @€ @€ @€ @€]cêòpz @€ @€ @€ @€ĘÜ @€ @€ @€ @€tY@Œ©ËÀé  @€ @€ @€ @€cr @€ @€ @€ @€ Ðe1¦._§'@€ @€ @€ @€ @@ŒÉ=@€ @€ @€ @€ @€@—Ęº|œž @€ @€ @€ @€1&÷ @€ @€ @€ @€]cêòpz @€ @€ @€ @€ĘÜ @€ @€ @€ @€tY@Œ©ËÀé  @€ @€ @€ @€cr @€ @€ @€ @€ Ðe1¦._§'@€ @€ @€ @€ @@ŒÉ=@€ @€ @€ @€ @€@—Ęº|œž @€ @€ @€ @€1&÷ @€ @€ @€ @€]cêòpz @€ @€ @€ @€ĘÜ @€ @€ @€ @€tY@Œ©ËÀé  @€ @€ @€ @€cr @€ @€ @€ @€ Ðe1¦._§'@€ @€ @€ @€ @@ŒÉ=@€ @€ @€ @€ @€@—Ęº|œž @€ @€ @€ @€1&÷ @€ @€ @€ 0ß?üð×t|üMóÑy›yõì_þå_nºé¦‡|æ™gÎ÷Ëø'# Æ4-Û @€ @€ @€ @€ƒ(qœÏé«K–žUÚ §œ•mñÉöÖ·¿kË·¿ëø“Ïj'y\³{âюɶ$۲﷣OXmQ´ÅÃíøeG5ÚéG·#Ž?ýˆã¢íðc‡ÚaÇœí;ÕöÝS¿Ýlß:z¨ºhii‡,ZÚhGòÍf;8Ú‘ÙN>øˆ“j¶›ma´Ã‡Ûa'ã°“¢ð¡öõïœôõmÿoµý¾µ$Ú¾Ñiúçñ¡þk‡,i¶öþæp;ø„¯6Úâ·¿g‡­·Þzocš-1¦Ù’u\ @€ @€ @€ @ _"Ɖ¥µülí–vÏýfûÁýî´àSÑî¾ï§Ñîºw¨Ý¹á‘lwD[ÿÈíö“Û×ýäûÍvÛÚFûÞÚïžF[Ól·þ Ú¢Ýrw£Ýí®hßí·ol¶îˆöP´ëoo´ëšíÚïÿ0ÛêÛíšhß{0ÚÕÑÖ<¸ªÑ¸êÖ¡¶ò–¢]yËývóýW4Ûå7E»ï²h76Ú¥Ñn¸ï’îvñõvQ´ë¢mXíÚ f[½aùêõÑ.¸¦ÑÎo´uç_½î…/yù>‡.9wÕºhç¬Z{ÎUvv´•kÏj´{>þé}Řúåþï‘~Š1õÈ…Ð  @€ @€ @€ @ kcŠ’K%·TÒK`úA3ºô±ŸŠvw 0ÝûÓ‘S%Ô¦Q¦fŒ)3Lk¦FŒit†éG Ó]C¦fŒ©™aªÆ˜Fg˜1¦’aj‰1­¼µ‘aŠ1 g˜®hd˜š1¦Q¦ÖÓ†ZŒ)3LµÓyˆ1í,ÆÔµÛ¹_O,ÆÔ¯WN¿  @€ @€ @€ @€™ˆÓñ'ŸÕ -5rK]i÷Ř¢Ó¨ L#¦GJ¦IÖaÊ0ÕJ1Ê0M¶S3Æ4ÙRLÃÕ˜š¥˜*Õ˜†2LÕjLW¯ËSL'׬Æ4ªS³Ó=ÑĘfêæœ?Çcš?×ÚH  @€ @€ @€ @€öÍÓ™C¹¥á’Keò¸XøèÇw‹64\3½Ô:‹\ 0•¹äjE˜&P‡©QŠiò¦‘åÚ–bjÖa]ŠéƨÃ4ÅRL1£\5ÆÔvF¹³®còZ›´€Ó¤Éì@€ @€ @€ @€ ˜@ĘŽ;éÌÌ-ÝY)¹TfŽËS%½ôÈíë‡æ«Î"WLe"¹æ,r#ÉÅtr7G»+Zc"¹R„©9—ܬd˜®¸y8ÃTŸQîÞKn¸7Š0e»èºh-ÅT‰1UJ1]µ¶”b:³czËÛ¶ jû¯_ýzÀîÙA1¦Ät( @€ @€ @€ @ /"Æt̉gÜe–ª­Yr)«.íøñÝ¢Et©:y\kù¥’^Š:L#¦ü(ÒK•Sû‰äêu˜¾ÿеßÿa¶Õ·5Ú5Ѿ÷`´«£­‰ LÙ¸êÖFk[‡©s†©Ä˜.jĘÚg˜bR¹ ®i´óm]–b*1¦±J1cúÙÏÕ—÷‡Nω€Óœ0;  @€ @€ @€ ÐÃÓ’3"®4Ü~ÒH,UBK;î¼[´Zá¥ÖÚKYä†Ë/•)ä:˜Æ*ÂtÝèÓd˜†bL×n¸0Ûê `+Ãtîªu/|ÉË¿vÈ ç\Õ¨Ætv³Sµ“Sßì½Û51¦Þ½6zF€ @€ @€ @€Ì@ƾ»dY¦”ªí¶uCs¢}dçÝ¢ å–Öþ8ª.ekä–²UÓKÃå—êSȵ›E®aºîö‡­¥S3Ã4\„©Z‡©Y„iFê0™aª–b®ÃtÞªucÚû›S#Ã44ÜÚ³VÞ¦lm'•Sinîç>=‹SŸ^8Ý&@€ @€ @€ @€fL bLGŸ°,RJ¥}/²J¥ÝóãìôÉhµÜR5ºT­½Ô¹üR³ÓCÙ®¿}¨e†©6‹\k¦á¹ä†L%Ãtå-\yËýWÞ|Ì"×h7Ýy£ÝwY´íÒh7ܳÈe»øúF˹ä¦aªÇ˜VF€©‘a:k8Ã$Æ4c·æ|:Ó|ºÚÆJ€ @€ @€ @€´ˆÓ¢ÅËFJ+UË,5—?¼Ó'£ÝZ)¹ÔÈ-Uª.U£K7GÕ¥lw>¡¥Òn¸c(Àtýp€©c¦^ó½Ö"L¬j[„©’aj˜š¦`ªd˜2À4Í Ó9«Öf5¦j¦j†IŒÉël bLS@³  @€ @€ @€ 0Pc:êøeÃ)¥GD©Ö"ôÃÇ>Y¥j»ùî5Ú]Ù†£KH/E¦áÓÇ©ÀÔn¹F¦[­^„éæ±Š0 ÕaÉ0]רô"Ûµ.̶zÃòÕë£]0ö\rQ‡)2L1—ÜPŒ©]&“Ê Ôkc#Æ4‡ØNE€ @€ @€ @€ô¤@ĘŽ<þôZJ©|Y¥È0EN,5rKCõ–ÚU]jNW™9®eò¸ë¾ß&½ÔœB®Q~)ÚÕÙÖ<¸ªÑF*0•Y䚦Ê,ræR„©ãDrækG2L`jd˜®i´ómÝùW¯;/Ûªu`*¦ˆ1½ ª1|Bë\r™aR©'oó^ïÔ„bLË—/_¸páš5kz}4úG€ @€ @€ @€˜¼@ĘŽ8îôjJ©V`éCÛ5ZÎW›*.çŒkæ–:E—¾~Èw/¿þY{é¼Ënþäg¿ú­£OèR3½ôÃs.½é“ŸýÊIç\YI/5L‘[ŠöÍ£NùàN»ïòé/ŸqÑcT`jÎ"WHî†û–^pýv;îöé½îô©½&=‘\%Ô¦s›E˜¢5&’kƘ¾Úˆ1 …–JzIŒiòwß¼ÛcQó±~ýúÚÈÇ1m¾ùæÛl³Í{ì±é¦›.]ºtÞÉ0 @€ @€ @€ 0èÓ±§eD©mJéCÝ5ZÛÄÒ w<íúJÉ¥‘9ãbò¸fnié¹+ŸýÜçsÊZ:÷²›ÿúoþöÃ;ÿç›ßú®wo³CÔ^:tÑÒxv‡vó–ïzÓ–ïÊ L`Šö¢—lòÆ-¶úàÇvßê};<ë9Ï;áŒË¯¸ùþl—ßÔ~¹KohÌ"÷ª|Ã;¶þÐß9éßÞò΋®oT`šH®Y„iÑÒKßÿáOŽaj;‘ÜÕõ"L ÓÊFkƘ·¦—Ęýµ2Ýñm¼ñÆ ,È$R-É4NŒ)*0Å>yþU«V•åéöÈþ @€ @€ @€ @€žˆÓaÇœ6\QiT]¥L)}ð£»FŠ+N, - ç–²êR¶ˆ.ýÃëþµc:ù‚(¼Ñ¥(¼”3ǽè%{ö%7ýýkÿõ {œé¥-xÖeò¸H/E†©1\s ¹Ï}å ø6LÇ/»ìðÅ眶üú˜?.Úq§_é¥ïα§_¦cN»ô½É§÷\¦ïžzi˜N:ÿÚC9ûÄó®½ðÚ »iáÛßýÁ3.½í‚1&’.´îœj¦•ks"¹ˆ1}EŒ©gnà~éHL¦ìm$™âQíùøÕ˜ÊÖq (ËÔ/ÃÖO @€ @€ @€ @€À"ÆôcN@ÒXíƒ;îúw½.RJÕöý¡bKÕÐRæ–ªíÝQõè³_‰ÄÒwO:?£KGÇB#´ÔX^tÒy]:êÄóJí¥ƒçyQ~)f‘{泟·×GÆDr±ðïïùзŽ=û¯þúe‘aÚ}…±}‰¯{ìDd˜^ù¯ß÷Ð%\³þüF[wþÕëÎnm'’‹"L™a:ëÊ{^ðb1¦ Þ\6k/1¤˜Z®úÜDcLQŠ)j:µNJGš @€ @€ @€ Ðïcj(Å”p9+ÜvüD´Z\©5±饨·tÍmF±¥l1a\LWÒKÃÑ¥ósÚ¸ 0}h§Ý߸åV‘[ŠSÄ’>ø±Oeí¥H/Å·GDŒixò¸Ëoºï²›…—^øâM.½ñ¾h ;ù/Þ$Ê/EŒéœ+n¿øú{#À´íŽ»]tݽ/øë—zìÙÑ"·å—"Õu˜b¹%ç®þÔ—¾ñÍïže¡†2Lc˜Î‰YäšÉ ˜VÞ“ÓÆ‰1õû=ßÝþG€©uR¸ ŘbÏÈ0E’©»pv @€ @€ @€ @€ÀlDŒéÛß=µCQ¥í?ò‰hµ2KµÄRæ–"±4ÔÖ<%—¢ÞÒ!‹–.:éüH,}á«•èRN׈1-9/L[½ïC¯ù§7lõÞEkä–š¦˜9.bL1s\¦—rò¸S—_¿óî{½së]rÃ}‘^ÊS¤—"¥_c ¹(¿´íG>å—"½SÈEkĘVGŒéO"Ã-¢KÑ2ƘJ¦±f‘kf˜î‰–&1¦Ù¸çÕ1c^¹Ö SŒcÊô“:Lóêv1X @€ @€ @€ 0¯"Ætèѧ6cIÕ6RT)cL¥ÆÒ¨¸Rä–š‰¥œ'n¸=õ–¢ÒR¶$½ë};\xÍ]oÜb«Ïå æœq¼ð%›,»è†e+nX¾êÎŒ.E™¥Ó.¼!L]Š“ÇÅÌq‘^ÊÚK_9ਨ½ôãÏÉ L‘[:åüë^ð×›Dz)bL]·!ÒKQ~iÛ2Ê/UcL‘^ŠS˜b ¹?¹ÇÁGŸù¾vÍYä:˜†f‘«f˜TcšW¯Ž™lÌ%¶Ç'Æ饨è=š… ÎlÏ @€ @€ @€ ÐuFŒiÑÒ‘BJÕ¢JÍ”ÒvþD´–¬R†–‰¥U·6BKµõ–í–F‹ÂKG.9/f‹;øÈ“#«tä ç.øÏ/G¦ˆ.}î+m¶ÅV‡/>÷ãÿ¹×«ÿé ¥ðR¤—Î[yG䟶ßñS]úô^ £ðÒ—82ÒK]ŠÉã¾uÜ9¯ú‡7Dí¥0EŒ)2L+®Ýå—Þ?c:䘳¢Ež)ÒKo{÷_ÿæwüÝ3ãëÛþã}æ_¾èe‡Ÿtqf˜ÎYµ6æšB®Ý,rbL]¿K 9#\Æâ±|ùòê Æ‰1ÅÖeO1¦¸  @€ @€ @€hˆSLýV©¥4NʈҚ¶ûð.ÑZƒJeM5±”¹¥(¶¡¥¡vóý»üç—KÉ¥ƒŽ89j2}ࣟ*U—>ûå7{Ë;?¾û^¥ðÒ¥7Ü-§ÛùS{½êß°ÝŽ»sÚ¥9sÜÙ—ßé¥h»ï¹0ÓK]ŠvÆ¥·í÷­%Q~食ÜcÙ%·E‹ÚKQéükÖí¸ëQé#»î‘˜>ò‰=>ò‰/ 0­\ÛœB®}&“ÊyíLS bLÕ$ÒäbLÓ<·Ý  @€ @€ @€ @€½/1¦ouJÛ”Ræ“¶ýð.ÑJi¥ *•6WŠÜÒÍC-'‰+­™XÊÖ˜-®Zr©mt)LZ*-ÒK]­1sÜPkæ–²En©´ V7&Ëùã"½t~sæ¸Úüqç—_ªÀ4áS†™^ðâ—åàŵMÕowþô¾oyÛV·­ýIµýìç¿êý›A»%0N5¦nuËy  @€ @€ @€ @€s&1¦ƒ @€ @€ @€ @€³)1¦¯礋®‹(R¶‘@R.¿÷6fJixJ¸¨®T/°4\l)RJµV -Ô['·´n"Ñ¥³VÞÓ!„4ý§Ä˜fó~œ§Çcš§Þ°  @€ @€ @€ @€"Ј1}ûÄ !µm[àãÑFMW›®]u¥’[jM,u-5ª.­Š¸Ri£f‹;'ê-e]ui¶£KÕð““—ÏŒ ˆ1Í8© @€ @€ @€ @€}&1¦ý¿}bÌòVmÕâIïÙþãÑZ+*u*åôpÃsÃLW›!®%´T¯·TË-U'Œ›Ëè’SŸÝÖýÖ]1¦~»búK€ @€ @€ @€Ì´@ĘöýÖ’¡šI«×7š ¤Ò2ÆT[Y¾Tž.²JmâJõ2KYo©^l©sKµyèTcšé{Ðñcr @€ @€ @€ @€ó] c:tÉpiÝùEÝÞ½ÝÎÑ2™TZ£ŠÒXmÔ”p¦‡‹ÄÒ¡¥µQi)[-BÔ ßŠ1Í÷×Ì,Œ_ŒiP’ @€ @€ @€è+ˆ1ísè’±¤Œ17f8iTPi¨ºRÔXjF”ªíì«Öµ•kcn¸lg µÞ -µ§Ä˜úêïΊ1õÇuÒK @€ @€ @€ @`ö"ÆôµC–Düh¬öÛííœvɤ1ƒJ™X;®Ô¨´te/VZšHµ'1¦Ù»çí‘Řæí¥7p @€ @€ @€ @`H bL{ó„‘RI¥fÒð»¶Ý9Zk!¥v)¥‘ÉàʬpýW+Ò$ÆäÅ3ãbL3Nê€ @€ @€ @€ @€@Ÿ üË¿üË‹^ô¢3åãÕ¯~Í&/eµ=ç¹Ï{Ö³Ÿ[[Ù•oÿèÊyk'ý½ßûÿþê/îГçýÙó·~ÿ‡n[û“jûÙÏÕgw†îΡ€Ób; @€ @€ @€ Г6lX^yœwþGŸ°¬Ö?æäÖ•s½fÉÉß¾ø%s}ÒŠèÀD4n¼ý~1¦ž¼ß{´SbL=zat‹ @€ @€ @€è–Àýê×µüM|{Áš/²j£Ë¾Lôg²ÝP©[·t_œWŒ©/.“N @€ @€ @€ @€s'Л1¦5÷ÜÄ51¦ï^÷‚Éæ‡zd{1¦¹»‰ûðLbL}xÑt™ @€ @€ @€˜MÞŒ1e)¦l}ZIŒi6oÛ¾?¶Sß_B @€ @€ @€ @€fV cL¥SƘú´ “ÓÌÞ¨v41¦» †C€ @€ @€ @€LWàÿýú×ëxtí?ëÐnºóGwß;Î60©g/¾ý«¥S.¬ºûøIaV7þÁý^ÇÃãž"òaÓ½6ö\1¦Á½¶FF€ @€ @€ @€ „À¯þßc‹®{F-Æ´äæ Äà ‚À€“[ @€ @€ @€ ÐÓ×ß»_-ÔßÞùðÉ=Ýo#01¦ÉhÙ– @€ @€ @€ 0·mK1eŒIA¦¹½Î6»bL³ëëè @€ @€ @€ @€é<üØ-«Ö}6ÛÙßS¤—–ßùž²æÑ_n˜ÎÁíK wĘzçZè  @€ @€ @€ @ “À­1¦u?YމÀà ˆ1 Þ55" @€ @€ @€ @`0ĘóºUS@ŒÉ@€ @€ @€ @€è1¦þ¸Nz9%1¦)±Ù‰ @€ @€ @€ 0çbLsNî„s' Æ4wÖÎD€ @€ @€ @€˜Ž€ÓtôìÛãbL=~t @€ @€ @€ 0$ ÆäV`1¦¾¸†F€ @€ @€ @€ ”€Ó@]Nƒ- ÆäŽ @€ @€ @€ @€ô‡€S\'½œ’€Ó”ØìD€ @€ @€ @€˜s1¦9'w¹cš;kg"@€ @€ @€ @€LGà?:óU­Þ°×tb_½) ÆÔ›×E¯ @€ @€ @€ @€uŸüâΈ1­Z÷Y4O@Œi𮩠@€ @€ @€ @€ƒ)ð‹_=¼jýçÖÿdù`Ϩ淀Óü¾þFO€ @€ @€ @€ @ Ęzà"è @€ @€ @€ @ E`óã6§B`þˆ1ÍŸkm¤ @€ @€ @€ @€@߬Z¿JŒ©o®–ŽÎ„€ÓL(: @€ @€ @€ @`æÖ<¸fÓÃ6¶èºEfÚfé6±+7>`ã<É• ÷¸hXˆg£å–3w~G"Ð1¦. ;% @€ @€ @€ @ ³@„“¢ SlÑ¥Œ(Å·Wʽ"Ø´üÎåñ5òLñí#¿x¤<–@Ÿ ˆ1õé…Óm @€ @€ @€ @`²ðR5ºT*0Åú-­d}l5™²‰1 òÝ0?Æ&Æ4?®³Q @€ @€ @€ @€ý#¥Œ%U£KQŸ)*0ÅÊ 0eÂ)¾F‹õKo]Ú?ãÓSmĘÜ @€ @€ @€ @€Þ(E˜rò¸ì\†–baÁ9 "Ò fŠ…Ø, 2õÖô†À$Ę& fs @€ @€ @€ @€À, d5¦E×-Š|R9U|é¥hQx)ª4ÅúXÈ52L³|A~.ĘæBÙ9 @€ @€ @€ @€è Æäö @€ @€ @€ @€ @ ËbL]¾NO€ @€ @€ @€ @€€“{€ @€ @€ @€ Ðþ׆ÓÖ¼f̓‡÷Gwõ’ÀdĘ&£e[ @€ @€ @€ @€@÷~ò‹;YµÑªuŸí^œ™Àl ˆ1Í–¬ã @€ @€ @€ @€fV@Œif=­§æWŒécûØF&/°zõêžzݶíÌÃ?ü‚ýÍ™gžÙû]ÕCs&pçwþùÿù«¾x Ï™‰ @€ @€ @€ôµÀ}ÞõW/ú›ƒÙ¾¯G¡óÚ Ì¯ÓÖ[o½ß7Y÷àÏFµ~¶v¨=ºï7yÛ¿¿kíÞsÿHûÁý6Ú}Ñ~íîÒîýé]•vç½?½sÃ#Ùîȶ¾Ñnj?¹}ÝO¾_i·­ûÉmk‡Ú÷Öþ¸Ñîi´5¥ýàÇ·µÝúƒÝr÷H»ùî5Ú]vÓ]µ;¾±Òn¸ãáîx(ÛõÑnj×ÝþÐPûþ¯­´Õ·ý°´kn{ðšï µ«¿÷`£­i´UCí«ni+o}`å-CíÊ[¸ò–ûíæû¯¨´Ëoº¿Ùî‹vY´‡Ú¥7Þ×h74Ú%7Ü;Ô®¿÷âJ»èº{/ºnC´¥]»áÂJ[¾z}i¬^Á5CíükÖ7ÚÕë¢WÚªu玴µ‹N½üÿèYç\µ6ÚÙÙV®=k¨ÝsÖÊ{μòž¼øåË—/ïñwÈ0ýÍ&›uÂÙÿÚ7H2õøÅÒ½9ˆ ÓßlòŠãN½0¾J2Í» @€ @€ @€ÌžÀÈGÃÿä£áÙcvä® Ì»S•"¥Tk÷ ç–ö=à·þû»2Ã4fz)bLõÓPzi$ÃÔ 0uÊ0 ˜"É4¦áÓÄ2L?ìœaZµ¦CŒ©C†©cjd˜†cLC¦fŒi$ÃtÃè Óõ‘acºvÊjŒiõ†Ž1¦F†©cªd˜Ö³j$ÆT2LÃ1¦F†©_bLñƒê¥›lºø´ #ˆvÅ ë^ãÇU×ÞQ¸‡"ï‹3.\¯‹«nÉË$™zèêè  @€ @€ @€À|4<4»ô—Àü‹1pHµÒÒH\©™[ÚçëS½êR–_]Š:LwÞÛ’^®À4Á"L·UŠ0µ«ÃÔ(ÂÔ¦S³ÓÍ¥S,t®Ã4Í S³Óp¦X?Ã4“¥˜1¦Ù*Å4~ŒéÊ>¨ÆÔøAõ·‘aZµµ"®´Ë¯—dê¯÷a½yF†éo7=sŵåu±ü*I¦™wvD @€ @€ @€9ðÑðœQ;Qæ]ŒiŸ¯³}J©™UúÚ׿1¦¶¡¥œ?®L7jò¸úüq1‘\} ¹˜N®L!W«À4͉äÆÉ0Mn.¹–:Lsœašt)¦‘éä¢&S™N.š3ÊSŠ)&’ËIå:”bêñIå†~P¾"êl•¸FdÎ.½ní«ÿQ Á.¾µ:u72ÃtÖE×–×EÌŒ¯‹ V~_M¦n^ç&@€ @€ @€˜ª@ëGÃù˜†§*j¿˜w1¦*e ©m‹g·|û»š•–êÅ–Úæ–*U—ÚG—¦–^jSéî¬Àô£›J¦;§[„)S/¥]sÛƒÓŸKnZu˜&ašÖtr‘aj1µrm³ M'¦Œ1ºìœþøç¥ýìç¿ê…tþ :áô×ßþÐuߊ1åϪ«n}à’k#ÉôúÓ—Ñ ]Õs&¦³/º¶ùºh–(»í‡åuqþÊï¿øe¯Xuõ5sÖ'"@€ @€ @€ 0M OÐî}$0ïbL{ïÿÍZE¥ê·ñì–oßꎨ®TÚúG"«TÚíë#®”í'Yr)Zd•ªí¶Ñ…—†fŽ‹ùãîjkîùñPûÁojmæ»%¢KÃé¥Z€éÆIÏ"×ø8?rK¥0_„iÕ­#sÉ­¼õF»¥Ñ®l´ûíæF»¢´›î¿|¨ÝwùM÷]íÆ¡vé÷5Ú vÉ ÷–vñõ÷–vQc.¹ÑÓÉ]»aŵ.,mõä2Lç­ZwîHk˜ê1¦•kÏ®d˜Îj˜JŒéè–U‹iÅ=Óõyþ Z²ì¢š“–RL͸FãbÅE¹hõ=¯úÇןrê²Iõvýúõ›o¾ùÆÍG,¬Y³&v_µjU®É•ñˆ•e³òÔÃ<ãòåË7ÝtÓ|v›m¶É•±I¬,]Š#çѪ,çÍ•±}ŽO—ª O|DñYU~œŸÅAâcßÖÝ—.]š+ãS¶üÌ7¶ŒÏ£'~"[ÎCycúê~߬ƒjËñìoߪ’UWjM,ez©pÉåïEh©’[ªM·¦cz©]#½TŸ?î·o¸#ÚCÙâcûˆ³d‹7¯¡öýñLÃE˜"þ2ÔÖ<ØüÈ?Û™‰)­˜š¦v¦›[Læ¡S3Ã4V€)’LÈ0žK®2\Û¹äÆÊ0E’騜Tnì SVcêµS-ÃTûY+ã‘*[qÍ&›dŠŸ4 .ÌwÃø¹߯’Œ1•·ÈøT²Gµ§JÀ"2L±K|ͽ,Xé¥ü‘ßæúØ=×Ç1ËÊü1–+3®9Ø+3UÚ ” SfûZK”å»V¼.νâ{=¥$SføÊ dF.DÜám«ëpðx9´M>u(¯£¹RB€ @€ @€˜{ ç,=Óüh¸$â#°òð¸ÃŒsó®üy¬qó€ñqsl–oMê,ãvÃ)0cLg ¥j+µ”¾²ßÁ[¼m«Zu¥òmk\©¹¦™X+´”…—ZsK?øQ[ª¶Ñ饇;Mך^j`U~©e ¹ö˜&`É0T`ŠRL3^„éºÑE˜®³Ó׬o›aªaZwΪ‘:Lg_µ6Z‰1•¹äªu˜z³Sü zÙßnzⲋ¢(Wf×ZgÎjÄ5šy²¨ƒµüê¼ò&Z“)~l”²Iù–Ñ¢xÔ²J%{ŒcŠŸI‘Fª¾oƳH5EÒ"#M™p*‡ª¥C2)RýW~ä{±AMS 2Lñº8ûâë"ÜY/Å4\¢läuqã}g_>é$Sü‚7a~-½_ì2Û”¿áeb=¥ZR,äšüM.^_ùËY–‹GüÒ¬ýn—IÁüÅ®Z±,ÖÇ·q„|”Íj‡*'-½*ö:šæfw @€ @€ @€Àœ Ô>UÞ¢ñX3Æ4s —hóƒªR„"ÿÍ|ùô*‹0å'\cŠ5ùiWõ³³œç$?ð*Ÿ…å|>sèDý(0ïbLTj™ôm¤œÒWö=ø-oÛª]\i8«4:®4ªÌÒpb©ZŠ9ã†g‹'·ô£›ïê]ŠÀJ³ðÒèÚKSK/ —_º¦”_Š…‘òKÍ L•òK™ßÌ)äj³ÈM.À4E˜:O$·þü«×E;¯Ò:g˜¢ÓQKÕ˜J†©L$W]è©jLC?¨Îhd˜†JÎTg”«ÌœW§cj²_pÕÝL2ÅÏŒZ¥™ŒeV)¾æ#~•´ÓX1¦ÖâIeʹX(?ŸJŒ)~te!ÁøqXj8•wÕÚTtýøn«Ï³'¦s.¾näuñý¡™›Ó,ŽÊ¡7¦¹l¾.μtÍ_ÿÍ$f—‹;3_%„—·qÖFÊ„S¾LòwµøÍ,îÛ|¥T#P¹&~‡+õÉjÕ˜J¤¯l“¿–£årt&wŒnä1³S¾”âÛèU-2ïu4{7¡# @€ @€ @€fV ÍGÃÃ5>량†Ë¿Ì¯ö¼ü«ø2N|–,Ê µjLùmëggµÏªòc¬Rÿif¹m`æ]ŒéËû4T<©]¥xö-oÝ*ÂIÕÖ(§ÔÚ~P­±q¥‘ÄRD—j•–òÛÚlq£rK‘aº³Ñâ3øj›ht©Y'ê-UÛêÛ~XÚ5·ýðš1ÒKµS}þ¸Q¦ærÑ¢êR¥EVf¸Ý×È O!× ”6z¹K®¿7&+müYä&_„©>‘\K¦œHîÈFŒé™g­¼§µSI2õNŒ©þƒêŽÆÔYg+CiÕ¼m3ÆÔ¸1_PŸ·ò®Wþý¿œrê²Îo^ñc£VB©Ä˜6Úh£ŒeÒ¨§CŒ©6­i5Æ»—:OÕ¼m-“Õ•e޹yç5h“ajÉöÕrèåuqÆ%k^4á$SþRUñ•)s8Õ*e¹&v) ¤üõ.Ö”°y&ŸZg‚‹-Ë‹%guŒCÅB™Ø1ŸÍ9³XZž.•iª8o-èu4ƒwC @€ @€ @€fU`œò3ôÑpkŒ)>`ªfòó©ò)UνkÚÆ˜jŸÅfµSë‡Ñ³jèà}*0ïbL{í{PûXRsê·½öiĘbatE¥zJ)k,Ý2F\©]bit±¥1BK:"£'Œk”ÛÉvûP‹ØÊHë]jD[¦”^êP~iú¦jz)–'`Z¾z}LWZÛYäF˜ÚL$טNnåÚf¦¡SÛ"L½cj›aÊé䢵+93TŠ)cL]·áœ+ïÚt¼$Süh©F”â}-¾Íy¬Ê§Ú›ÝX1¦Ö mþXªþôŠ5QQ¦Ô¤©¹üäËoµr5}ú†«Û3.¦—Öê0• Sç×EóýgÅuN¿xBI¦ ×ÒE‰1Å+¨ìUûµ/#McLñlÎÜcŠ•¹{‰ý•CE’)§®+)(¯£¿÷ @€ @€ 0KÕ¹ä230RÞb6?ÎùFÊ´<ùUù Y“"¦cŠ}k©¦YÒsØ~˜1¦}*½µ.ì¹ÏA›¿õmk)ÕV•VÊKwU[en¸œ'®Yf©µÒRV]ªÕ[jÍ-E€©’[§êR&Zª…—:Í·æjí¥O/ÅœM )m ¦ W¯ÜRiT2LÍÓ$f‘;'¢KÙšE˜Ê,rGžÒ¨ÆÔû1¦øAY%ˆç’kþ Ê\C¥˜š5KÉ™Z)¦‹®kÄ5.¼vÃÙWÞÙ9É”u\J—Œ(ÅÊ)Ęr>¬R©T‚©&?âD9mj¼“–‰´b¹LÑÕïï°ú?«™a:»:—Üp†)³}YKs¬RL‘í[qmãuqÚE·¾p¼šLqV •e¥ê¯q±Au*ßLÆfe–Æœ¸dÌóµ>YW© U~í+³ÂµT®ºcõPÑF¬ÆgõZ88 @€ @€ @€ÀŒLû£á¡À&øÑp)'Qæ)å-bMÊšÎ1¦ÖÏÎb÷üû&.0ïbL{|í Q ¤2×[s!žSK2©cJ)³JcXŠ+µK,ZjäTÚä–2¹ÒaθZt©6mܪ[G¥—VÆ´q£fŽ{ ÌW«½tEëäq™?®Y ¨íüq A¶k‡ÞI#O­š^jWiL1‘\¤—Žè‡SùAÕ ½5êrÕ3LÕš·4¦ü‹iþ“ú5“dYŠ)U# væw¾â5f—ˉ±Ê#Sˆ1Å^ñƒ*SJñˆQ9—V­€Mä-ò‡_< ¹q™]5ßËTcšø{úüÙ²d˜ª¯‹òöXæÊ0 ½.î+¯‹,Å4ôº¸fýÒ·¼ð%/¿òª«Ç¬U#+‰¥åM›±ôüõ.ïä½'ç¾ÛãǘÊ[›jjîû:ý3n½õÖ{|íÀ¡ÔQ‰UâÙ7oùΑ † )u(§”)¥ÎY¥‘¸Rez¸œ'nô$qíCKcä–~ŸÓ—Ö¨;RÚš߼廞ýœç½è%û…½Žb$]zÍkÿõYÏy^|Í L]zÍ?5×üÓ¿®¼e8ºtËý]:舓_øâMâÙh›m±Udb¢}ࣟŠvYD—šé¥Øà[èÒÈÊd]{)Ó3c˜†ÒK­¦Õ£LÕòK1‘\û)ä®^wvΪµQx©´¶˜2À”mš1¦_üêáu?Y>ý;³Ã*?¨†¦Ì‚ÑþcÏó^ó±S¢½i÷3·Úã¼S/»;"hqù¶ÝgÅ«?zÊ;¿xîwÏ»­™a×8ÿêuË.»ãï:&™²?¥Ò48Ùãä1ù(ð௙Рj(ÃtÑuCï®Í÷ÒòVù™ÃWÆ‹â5—Æûpý¯‹¡ôd%Ï»zÝÉËÇI2ÍÈ™xy$Éôw @€ @€ @€@—}øñÕ'O¤c}4%Nª 7>[2öG`•É?Á†'ûyîDÆb¢jCæçªSâä.ãǘ"=—eÄrľ¶ŽÓ—ö>°<ª-dzcª­¼a¤RÎ÷PÛRŽ´fD©´QY¥áR:9#Xk«UZž'nì©âš'UK.}h§Ýß´åV‘UZqÍ]/zÉ&g^|c|»Ë§¿Ñ¥øúÆ-¶ŠÜR|åøt?×T /E†)ÒKqr¦—¶zï‡"±Ñ¥í?ú©hZ&7Þ÷‚oË3–^j-¿4Æüqñ>iƒ¡VI/E’©`J/µL!W 0M3ƦUë>{øêß»ð®­gïE‘?¨N8}EãÖºsF²ÔX²âŽ Ûîyô5[}鼏޻çÊm÷¹0.Ó1çݶÙngÔJ1E,ô‚ëôKoÿ»WwªÉ4{ƒrdc D†i»ßç5ÃLæk+¯‹¡ ã 32LïÚã¼Kn¸/^ñ¶ðÆÝÏ8â¬5»»ñºˆ·¬ÈöÅë¢VŠéükï*ñº8é‚›_б&Óô¯ÝÄcLÓ?—# @€ @€ @€t_ þ%|öÅu3ûÑp| – yÎ÷¢ªÅÒKî*åGã>[ݨâ£áî_}=h'SßDY‡xÄB-H7~Œ©TF‰jL1aM_#7bL_]8V)ÖdzoÚò¹Á¨XR~;:œ4NP©1%ܳµ+µÖXª$–&ZŠ·ªF½¥5#SÅ}âÓ_ŽS–\ŠÓQK΋XR³äR£êR,}m^Škr!sK¯þ§7|öË^žU—† /-<üäŒ1e†é3{õ–FZká¥f ˜Ëld渉LWI/M°üÒ¹Q~©RiÌÓpù¥R‡iÊ1¦[î¹ç¼5»E€éUE›½Sþ Z|ÚŠj€)o›k¢}ïÁˆ1°âŽ¼Ð‹—ßþÆOñä‹ïÌi³"òõªOiøÏÓ× m†ÀB, N½äû/õ?Ÿrê²¾~Qëü@ dŒ)Ûa¦Ì0µâÚÖ`_ΧE˜â&Ï×E¼×yÖšS.¹«ýë¢Yþ­üUÜâu±äü›^ðâN³ËM\±±iÚ @€ @€ ÐgcÊ6F˜©óGÃñX|4üéÃVæG`ª%Ÿ:㸠¾?îGÃY ÄGÃ}vÃ̃îFz©D—Ê´ƒeÜãǘbÓ8DÎYØï\cúâW¶M#eÁ¤/DŒi‹w¶)žTýíû#ù¤¥]j[]i¬Kù1|m†¸j¥¥ZŠyârz¸ÒoXÍ÷¬Ò>ò”¾d“ZÊ’KZŠ.5sK±Ü 0Ý—Ñ¥øö¸Ó/‹(L^ŠÖ0íØhïØúC‘aŠ–¦ÓÆÍFzé¼±Ë/eþ ÑV6ÚYvO¶Zni:1¦0sënß¹úw3À4«1¦øAõ7›42L×5ï·¼†n›¼CÖ4~Ví|à¥ÿyØÊÿüÎÊøAuð©7ÅuÌ«öÅ#¯Ž¼íW»6æï»°Yìª *9Óàj-½X’©ßßÕ«ÿÕS»0Sd˜âuqæŠkÇz]D°/bL%Ôozw¶Úë¢%Û×ø._WÞ³ä¼ÙM2 Ö53 @€ @€ @€ŽÕS»0ÓÄ>>#>^|áíQÞâ›§Þ՘μò“øhøJ »K{N j2m¾ùæFªõlB1¦Ø'æ•‹£ SÏl2ŠÓ¾²p¬ÚH±>ž}ãïè°ÁDÂI%·Ô(™ÓhF8©µµ+µO,U*-uÎ-e½¥lqrLwÄ çVë-]1ZjF—FrKZÊOºüúœ0.ZÄ•¶Ûq·lÏ|Îó>½çÂWýãb93LQ˜®Ñ&PxéÂfá“j»`bµ—&™^0Q~iŠ1¦·˜2ÆtâÍ/ŠÙåf¶-¿e׿ÙäÇŸva5½Ô(Â4`Ê4[NzzüòïG½™íöYI¦üA—,&›‹ Ó¿í¶lé¥w¥ùHÉ™fÞ¶¼†’L{/xüÔÏjº,pø{F¢è%“>\™©™azÅ®•êýº8aÅíñK[³øÜýµ Sëë"Þ‚j¥˜Êëb(Étð.]ñªìG ~ü—MæwÛ @€ Ð ¬ö| @€˜#ã?Úþ#°fe¦f†iB ǧ`oÜýŒøPx«/{ÐÒ›&ôÑp³Hý£aÓõtãC³U *åìrK—.­>;~Œ©Ì€I¦~/È1¦Ïea‡òHñìßòŽñê' ‡“ÆÈ'eb©žRj–Ï)­C©¶Æ¬pÕ‰áÚÄ•FWZúœ~8´ØçgöÙ>÷•ƒ2ÔóÄUë-År–\ªæ–²êRF—¢ØÒ—8²:gÜ þz“H/Et)ª1Etéäó¯{泟÷õïœÔvθœÂ¬´ D—U‚b²³œïl¤M®öÒDË/M!ÆôÒM_úí‹^^­ÀT]>ôê‘ÊLcm3Ùõÿ¶ÝF[¾ã½#%»Ê5tÏ •àŠSd˜†³÷ÇO¬cοmÙåw_2”-Û1¦£ÎþÞP)¦¦mµäL¡8ôøåÿç÷ŸôÃ÷?¥ýÏjšÄ2n ,xÆÖoù—òžó*Ö‚}Y„)~‹ ÓðD™÷xÊMŸúö•ñºÈØeÔ'«½.âEј›²ñ ÜÚêûÃ'¿tà¿müÔŸoÿ$¯ “ˆºb @€ô¸Àgþ÷¤ÕïÖÿ;/ @€,ð±ßûì¶[lÿ‘Otþh8>‹†ÿó;WÖþù,>¸o÷Ñpã#°œ¤| ¶ßw–¾èÅ/}ôç¿êñÿiÓ½ˆ SŽqæc1¦˜Ž®D—.\ú+bLŸûò7ÚÖFÊ•ñlĘj´ $µ›÷mìˆRÆ•†‚J­“ÁÕg…kW©±”%Fj¡¥’^ÊÐÒW¦ ®º£Ô[zõ?½á+ß8*rK ?ùÕÿø†ˆ+Å×X¡¥…‡5ÖTCK‘aŠÜÒ)ç_—õ–"À߯ÇÿÛ~d·h]Ú}Ï…õ×/‹@@„–j¹¥F€itÕ¥FŒ¦Má¥õ]ª¥—š‘‚ÒÖÆTñÞZZËÌq“«½Ô:Áܧ\þ‡ôÌÎϽàÅ/?ú„e+ïX¶øúW¶’θí_ÖýdùŒ·Ï~ö³ñãjäÞ`šñt÷ÆŒ§9!`˜"½?¨Þÿµ ¿päÕIý®ÝðªO9þ‚ÛëÓÉUò¶1ðØä导ðœóo»lù£7^øx|ú®è–Àùûµù#ò‚g<~Þ~QÞ&o~ó›~ûø¡×E3šï®ù.šáÎ^ÅÉòu±üšõ›}ꌽ¿¶ý뢖í«ÌAùÅý½ö_þíÆË/‹×ÅÏoò¢ 0a“>Ù¸‡Å˜úú—E'@€˜'»=÷ñøwÏÝúÿ_ç%@€ @`^ \ul›À>ö{ZP>ÿ–1†q?Þý;WæG`¥Óø G†©ò؋Ί†¯¾ùžÛÖþD’ižüïoosÑ¢Ee.¹Xˆ0Ò$bL±iL$I¦|”ÊL½9Ôq{ÕxýïõjU¤Úr<»Ù[ÞÑR*©V9©|;œLʈRósôέ‘>ÉvK½U烚nì¸Rä–2±4ÜÓÃ5Þ°š-2LQl©´ÃŸsÜé—E¥l±¡¥cO¿´¬‰åL,•Ñ¥¨·é¥h¯ú‡×÷ÔK#³íG>­D—þuówF«êÒ¤¢Kµiã²2J=ºÔ Š6²¢CížxíæF;G‘Æzvâ1¦x+Öfºð®­Ç½ñ¦¶A$™¶ûð'Jn(¨1œÕˆ([T ŒèR¶ÌjD¦Ó/»{³Ý–EØ6ÚG¾~q3ô~¨ÓèéäF2L—ߘ£óãjjWÊ^3&¿°VÓôærüL2ðíãG¥—†ßQK¦m›s,F‹—Ænߺ"ÞÙNkóº¨Ô'íÊ0Ý~y]üü—é3v‘ü@—.Æ4à—Øð @€F bLû¼f`Fc  @€ô´ÀƒwŽú¬`*ÝŽ$Ãg÷úFç†wÿvĘF2Lc|6üÑðèéäâ£áj†ÉGÃ=}ÃÌÎE¥Œ!µVSR¹$вL`•/þI£xöß6ÿ÷qÓHíg|#Ÿ”‰¥fJitQ¥Žu•j–jq¥’X*ÃåÂÈÜpÃ3ÄE½¥Riié×år‰+•’K9ÝÒE×ekÔ[ŠvÒù×6BKc–\ÚÐy¸ Ð4Z»ªKm¢Kã§—šÑ¥™H/•TÓdcLù†~õ]gœ¶æ5Y™iöbLñŠ‹$Ó¶Þ%§Ê¾‘†f¬&mó*_ÄF¦¥—Þ•I²’aÊpXµfàP¦J†É«x—ëï!”SK€©Œk(Éô­ãK$´ä>‡óCo†']tgû×E›lßÈtr­¦|]H2õ÷­5g½cš3j'"@€ 0M1¦iÚ @€‰ ”S»S9L 3äGÃc}6æGã?‹†õA†§“kÍ0ùhxâЖs,0ÑÓwk–N¯üÏìùÖJHeM<1¦”§ÚÇ’"™”m¸ÒX³¿•”RK]¥F¸Ò²ºR£5SJ¥µ+UKÕIâj•–òÛÖÐÒPbi8´Ônª¸zniÌ’K× ÍW›0®G¢KÕÊLS‹1ݹ¡1McL$a¦Y1ÅY"ÉôþvÉ›*o›Ì´å]wB‰¦e-/\É0Å%hNÒ7œa®8V†©õÇÕ÷–-ºæ;{üòÑ¡™)ËkóÑÖßµbé,½Tvž DŒiìS1É$Óþ‡×òºz·¬½.2‹9ôºhù®ší+ÃTM2­[µ<^ñµv¼"æéM[¶“û€ @€@¿ˆ1õË•ÒO @€ 1¦Ž¦2ÄÈ3|zÏ&øXëGÃ9EOëGÃce˜$™àæÈ!Ì»ÓÐ˾äFGŽ>½Çcª…Ê·ÕìÑ„–GÍûVŸ®: \kP©Mi¥È¬Ü0Ôª)¥‘åÑÕôR#±4Tii¨ÌRã­´kð· -5£0mê-EŸkFÚP½¥‰æ–Ö3ºäR£>Pi³0gܸ3ÍM'Æ”ïþrCÛ·†MÛtý#3SÃ,“L#•f†LCÁµÌ¥5/hÎñ×È0 ×ÁšN.ë0M,ÃTýqõÀÍ«–n³i$™ZÇIŽhù¶hP]ˆÙùØDÎ^’LÕ LCo›ÃÅÉF½.V¼.Æú®s†©$™ŽÛ|ãxEüèî5µ~zELä þ6bLƒ @`PĘåJ @€>ˆÏ¿âS°‰=I¦=ë£á¡’%>®—·èœa’dšØe±Õœ Ì¿Só5?V‹w„Ýü߯¸éþhÃó¸»0R<©M¥vµ”ÚOW™n¬ºJµ)áje–*q¥‘‰áF%–:TZjZj-¶42OÜ„sK°gÇÙâšñšFÂfÆ'Œ7ÃL?ÆÔöõºjýªØx̓ C|/y¦òЍ­÷Š˜½{ ,ÆÔ‹WEŸ @€´cr_ @€ ЫïØê?vßãëí?«–·hóÏø×5ʈTÊ[L$Ô ÷*†~ÍGycúÏxÁ—™ÚZâíà_ßüïõ FOèV›ß­Ó\o™L*m¸–Rç”R‰§´ nh>¸¡êJS‰+5 ö´”YʪKŒ®´4~héêu-óÄ5‹Ô•[j¾iç–º]š©Iå:¼a,8gATcZ¸ráò;—o~ÜæÑö¸hRŸ)rK±»o³t›hÕ§:3’Lïûà‚¡â[£Le¬öY)e˜¢'1mVž‰S,¬øÂ6Ñ¢ÞLd5r.¹x*¾Æš\߯féˆ reì8ßSy2É´ÏÁǶ}]”âdï‹uÓÌ0=ò£½`óh7¿0 2Õnõ|EÄ« ×ç×X Œ…9´qª. ˆ1u Þi  @€LZ@ŒiÒdv @€ @`îI¦/}}b þ¬òѰ ÓÜ]0gšQycŠWû¨hÑè¤Q<û†7ÿ{û *!¤2¹[.´Ÿâ-Šå´¶1æ}«&–†Š*µ *ÕK+u¬®ÔŒ+µ™n¬ÄÒTCKç‰ë½ÜR­DÓ,UcŠdR´x©Fž)‚JùšúL¹ñ¦x6N¹fÑu‹rûÎH2½÷ƒ †¢l9-`s¹¼Ð™B;?²ecLz:ñ:L¥™ÌˆjL‘ÛÈ•9sVÔ›ÉLF|ͧ"½-ñ5·Úïzz~2ÉôµƒéðºhÌ}9üºÈe5„>‘¹ä¢ÓÏÙ¡—;¼¼"râÅòŠÈ _lkb›êLs±^•²¸ä=~1¦¿@ºG€ @ ˆ1¹ @€èmH2}ê‹_ŸòGÃ2L½}yõ®“À¼‹1}ª„ÛÅŒâÙ7¼éíãÄ’®šÌk¬jIãTQÉ'ª¥¥6)¥JPi(°’±•j[=fu¥¶–*q¥õçWæ†ËùGµUQZ©Þ!€ÑÅ–™€ÒšÅ–zªÞRç©åf)ÆÅ–¢äR¼òb!ç+˜b9ÒK‘aŠxS<›µšba"1¦Ø·‘dúÀÇGLó]Ö±³SÈ0•dFœ7‹ÐD˪KYŸ)ÖGù¥X™%šbûx¶º¥w_s I¦½:¦ì+ÅÉF2LWM+ÃcÉÄR,Du¥¼Õ³ØRyEÄSñÒˆB–bŠ…Ø l)Æ4÷C—O!ÆÔå àô @€&, Æ4a* @€ Ð-H2íö…ýÇÿ¬åŸñË0uë’9ïŒÌ¿S3±8V‹<ãëßôöÖgG*$E©´ë"‡TmRkk¼­´m×6Jé”V'Õ³JI߯j­“ÁE¨eq¥ösõ™.K}Zj4ÍRŒ©^* ¥>S¼ncåúGÖG hé­ÙÙâõ™&þzŽ$ÓÖøx)µU 0e¦¡ËT™ôt ¦èOIfä,ZÙÃŒqDD#Ödž)·Œ¸FÎ(—›Å69÷œ9È$ÓW<¦íë"ã˜Cï]•׍ê0•û?âæÏ_¸HºH€ @ ) ÆäF @€ @ O"É´ëç÷ç£ááÀd˜úäªêf'ycjd[çe^ÏþËß>Na¤±vï8¹[§BJcG”FWTªÏ×f¸œ®ÝdpÃÓõ™nT¥J\©MbiåH`"!¡Þßf–bLQ])Ú#¿x$&+¯¿,Èu˜Jí¥H2ÅšI•b*G‹$Ó»·ß9“j¥ØLãR6L%«1µ:Ly–H)•B2iŠ–u˜â©üšÛ”§âÛÜ ZViò 0—™dúò7Ž®¼.† ÈU‚}SË0Å@Jù±XŽSÞçY„©¼"bMí%[Æ+e.)œ«kbL]£wb @€“cš$˜Í  @€è¢@$™>ñ¹ýÆúh¸|(/ÃÔÅkäÔ3(0ïbLTì0;[<1¦´>5T*) &u $Uk)UJ(e-¥u6n-¥L)M$¨Ô¬>ÒÚÎŽ˜Ki+‘—lÍâ=ÍøKiÃÍÞ"M§‡³cšÁ—h‡CE’é?¶Ûyd¹«†.b™N†in†à,fV “L{ptV& ö­*Â4å ÓÌöÓÑV@Œi`/­ @€ œ€ÓÀ]R"@€ 0Ø‘dÚå³ûuøhX†i°o€y5ºycŠ”âX³³Åúx6bL6h)T&t«ÌìÖH*ù¤6³¼•dÒp>©c-¥¬»Ó¬¨4‘ RûÒJó1®4VÔ©¯cLñVÕH2m»s#š6ºØLΗ·ÉË_yáå7Þ¶ö'Ú£?ÿÕ¼zË3ØÈ$Ó¯‹êìŠSžKnàÅ p&ĘfRÓ± @€̦€Ólê:6 @€³!I¦ŸÝ·íGÃ2L³î˜Ý˜1¦ZÑ£ê·cúçÍÞ6‰ÔQ-„4•LÒÐŒ`ãæ“†*‹TË)år›¢J£ƒJ7ÜtÊ/Õöí÷S¼qD’é]ÛîTf‘ËÊ0uë-Õy{A “L_úú¢Úëý‹û/zí¿üÛ·ßß!Ø·öŸýü—²}½pû³bLýyÝôš @`> ˆ1ÍÇ«nÌ @€ú^ ’Lÿ̾µÀd˜úþºÀhycÊJkcµxöu›½­ÃxjmTK)˜4Fͤq¦{k7ï[eê·–”’ ÒT§À€S&™¶zÿNæ’óöN d’)rKåu!Ãäö˜ 1¦¹Pv @€3! Æ4ŠŽA€ @€ÀÜ D’içO$™d˜æþ8ãl Ì»S”Yk•5ñìëþím6èðT£0RçV)›TJ(5ç<ª¶{ΊLR­M5£3ƒU‹õPƒcŠ·‰’dR‡i¶ß4¿_ªI&¦~¹j}ßO1¦¾¿„@€ 0oĘæÍ¥6P @€ƒ'P’L2Lƒwq(æ]Œéí[ï°÷7Oh´ƒÛ´·¿{‡¿yùkÚ>U[ùÕƒO£-þêÁã·¯¼XëO~éÀÿïþAçž<ïùqô ˪³Pݹá‘|ûˆ$Ó›ÿýý›¼ü•^~c‡9³â©Gnά¼€º4ó‘dú—7ükÔ*ûÇþsÉͼ¯#¶ ˆ1¹+ @€ô‹€S¿\)ý$@€ @ @$™â#°M^ú²«o¾ÇGÃ_1¦c=ö5£‘ù¨¶¼è%¶ñÿ®­ôí ¼t“W<ëÙÏí<ÀW½æŸ.[}[ïǘâ½i¶—a°÷hÙ¦À÷ŸýÏ[ÿ÷3®9¢Ã/pkøÙÏ)Û7Mi»7ĘÜ @€úE@Œ©_®”~ @€ ÐVàÁ;?ñ7¿}õ·¿(Ãä<ùcj½~_Õž%ÐV 7«1=þËÇ_ðŒ^vJ‡«¦ÓཉQgu?Y~Ȫ.»}ÑX¯ &·ÐL ˆ1ͤ¦c @€˜M1¦ÙÔul @€f]àÁ;ßn£.ÙÃGóNís. ÆôI“èÑÓyûÅϪǿø¢þøçmG$Ã4ço°NØ}Œ1Ýúàá÷>ôXëëB†©ûWhÀz Æ4`Ôp @€X@Œi€/®¡ @€˜ÍÓã§~ÖGÃóájÏ·1Š1‰1˜´@/Ƙš¥˜?«¢­>¹õÇ• Ó|{s7Þøù¯Ž$Ó£¿Ü˵$“ “›dæĘfÞÔ  @€ÌŽ€Óì¸:* @€s$Ÿ¯Yþx„™ÜGÃsdî4s% Æ4éËd+÷Ø~ðz1Æ”¥˜²}ñEµW2LsõŽê<]xätîAI2É0uùR êéŘõÊ @€Àà ˆ1 Þ55" @€ƒ(ð½e‹®ùο|´þØ£¬¿kÅÒ2âj’ÉGÃx#̯1‰1‰1˜´@ÏŘª¥˜† 2Å;Yþ¸òƒj~½©ÏãÑ.½ué6K· ’L?¸ÿÑŸÿòWãni“cš4™ @€tI@Œ©KðNK€ @€ÀĸyÕÒm6$Së.‘mŠV]ï£á‰ÃÚ²Çæ{Œé§ýW¼ž;´{ø³~ôXçm<;Hq¹ï{hœ+·Mo½°«¥˜*™¢“²½u¥ôfÖ¢Ó‚sìqQã×µ5®‰¯«Ö¯*˱°þ‘õyòÿ÷ë__qϪ|ÖƒÀ ˆ1Í0¨Ã @€˜51¦Y£u` @€fD *0]¾ÿ‚hYŠéGw¯‰TSaʃG¼)¾­­Ï†c}>åA Oæ{Œ©O/›nh-ÅT)ÈŠÀ<X~çòØ8’L‘gÚô°M7?nó¨Ì+K}¦XÑ¥H8ÅB¤b}lîë˧óÄ˜Ü EÀϪA¹’Æ1ƒbL3ˆéPã ˆ1od  @€½! ÆÔ×A/ @€˜¢€†§g·>cꃋ¤‹&$àgÕ„˜l4¿Ęæ×õîúhŘº~ t€ @€ÀĘ&e3 @€zSÀGýy]ôj&ĘfBÑ1ô‚À/{|ÍòÇã'–ÃbLî…9cšSn'#@€ 0 oýûã‹?6ýíJ€ @€® ˆ1u•ßÉgU@ŒiVyœÀÌ \ó=Î^°ù÷–-ªzݪåñÔÌŸÏ ô³€S?_½>ì»S^4]&@€ @€ @€ý' ÆÔ×L'* Æ4Q)Ûè¥Ûlúèë[;sùþ n<~atR7ôˆ€S\ˆùÒ 1¦ùr¥“ @ ?îZ±ô¸Í7Ž?¤´v·íÊþ•^ @€ @ Ę܃+ Æ4¸×ÖÈNà—>Y¥ø\Æ•âk”_*e™âpܼ*ÖÇšX_"M‘yŠo£ýèî5Gb@Æcr‹Ì©€Óœr; @€qV|a›H2µn*cr÷ @€ ÐßbLý}ýô¾“€“ûƒ@? Äà"ɤøs[•"·k2±ñ¦ø¦X“ë£åæâovÑü…®Ÿ®´¾Î€Ó A:ÌÄĘ&æd+ @€s ÉRLñW”ø«ÈÙ 6ÿÊ+N½nÕòXŽ…ÚúX{å–sÐC§ @€ @€ÀÔʦngÏ^cêõ+¤ª¥äR^Н‘jÊJK™RŠHSþ….–ãküõ­”kŠ-s/óG@Œiþ\ëž©SO\ @€ ЈšÖù/¾â!ñ§’ø6–óï*Yµ:¾ b}´ü[J¤—ò¯(ñוø‹ G @€ô®€Sï^=›®€ÓtíO`.ª€ËDkâpñW¶H)eOb9þú–ÿp0žÍD­Ä›æ²ÃÎE`î|tõ!«6«ÝùðÉsß%gdÕ'?¾ÝFc¶Ïä± @€ÈôRv0–£Sþ%ÿ%XþC¯Xˆ¸R<Ëe}<MA¦¾¶ºF€ @€ÀãÿxC㳉ã?Æ‚Àà ˆ1 Þ55¢Èâò¯lQö<Ê¿,Œ S¤—²üRŽ?ÿ$_c¯ÜÒ¿#Ø;ÃÀZÎþþ›ÛƘ–Üü"Zf^à‹/jcŠõ @€tI ”\Š¿‡d±êø;Iþó°üšüÇ`Yë:ÿÁX¶(ÈÔ¥Ž;- @€&&1¦#¶žØ¦¶"ÐObLýtµôuž Ä¿Ì(Rüq-âojñ5ÿôV*-Å·ù§· 0åB~-³ËÍsFßcdRŠi>\ý.Œq¬‚L±Þƒ @€. D&)K.•ÐR$“ò¯%ùÄbƒüGbùÏÀâ¯.¥Sü½%Ÿò @€ @€@ï ˆ1õîµÑ³i ˆ1M‹ÏÎæR **EË3f…ó\(_kOå·Q¢)¶ÉšLæ@kA&¥˜æÏÕïÂH[ 2)ÅÔ…Ëà” @€FÊŒr‘IŠåˆ(Å¿ûНñ¯¼ò‰EP)N±¦üÓ¯\ÎâL(  @€ ÐëbL½~…ôoŠbLS„³ô²@kA&¥˜zùzõ}ßZ 2)ÅÔ÷Õ @€ @€ @€@ ˆ1õðÅѵéˆ1MGϾ лÕ‚LJ1õîu˜žU 2)Å40—Õ@ @€ @€ @€@o ˆ1õæuÑ«i ˆ1M›Ð @ 'ª™”bêÉK4XªdRŠi°®­Ñ @€ @€ @€žcê¹K¢C3# Æ43ŽŽB ûÞùxü¬:õ³Ýï‰è,ȤSÏ\AïHdRŠiЯ³ñ @€ ‚Àyû?~Ùƒ0c @€ @`Þ ˆ1ÍÛK?ècô+l|óG@Œiþ\k#°@dRŠiÂ`6œž@dRŠizŠö&@€ 0»=÷ñ}^3'r @€Ì’€Ó,Á:l·æWŒiõêÕŸíøØ}÷ÝwØa‡ÎÛxvÀ¶ß~ûÎ#Úk¯½{ì±n¿T'pþï¼üÍ=¶d÷ ljóHà˜s¶ŸG£5Ôn ¬þ»Ýç'@€ @`|;?ô̇¿´éøÛÙbÂþîÚ/2¿…>üðÃãÜóŽ{L_ >ûˆO@:çÎ;ïœðëÞ†æ…À~ûí×ùUãý­æ3.H΋[Ç Ì€ÓÜ8;Ëœ ̯ÓÖ[oý/oØìãŸØ½´?±ûHÛe÷~ýfñ—/Øy—OEÛ©m[ð©|êcc´.Øí£oÓvüønCmçÝv¬´ì¼[¥}ò#; µïôɶm‡}²µ}èc»µîú¡JûàGw­·wýàŽ»~`¤}â;Ž´í?ò‰¶m»|¢Ñ>\m»l÷á]¶­µvÙv‡]Þ?FÛæC»4Û‚Z{߇4Úëí½\0ª}`Á{?ðñh[·kïÙþãmÛ»·ÿx£m·s­ýÇv;—¶ù;Þÿߟú´ÿØvçh覆޵íNïzÿNøGÏ\¾|ùœ¿6'}Â3Ï<óo6yÅ›ÿñåýºšôøì@`*‡~øŸÿŸ¿ŠÿšÊÎö!0I¸Óâ~‹»n’ûÙœ @€9ˆéãO(Ñ"{1§'è“UÿîZû‹ëλìkýç×ÿ[üÝuÔ_\ÇþCkëŸXÛþ}µõ/«ü›jë_S;þµÓ_PÛþítÔNÇø«iÛ¿—¶þ±´õo¤üióO££þ.šÝh£ Í?‡¶üE´ñ·Ðç=ÿ/&û?¶±}\Ü6ro\úÆÕÿv;<íw·þ÷ö±þÆÞáìíÿ´Þéêüsú¨`Ô_ÑÇùûyË 0úÏæcÿͼõ¯å¹úmÿBÞú·ñÖ«!ëþ‡ü¬×ýÛ[ǼúÛîôòWÿs¼–ú½ÊàLN ~gˆ·¯|«|˜Øø ±|Œl³í­V–Õ>"¬ýüªýðýÆÕüpø³¿‘7«vïTµÏø*íUÞšÚ½/Uß‘jïE#?†šŸÓUÕÞ|òç-ÍÝò=g¨ÕÜìô”§>Mbrr7¢­ tcr{ ¨À¼‹1í÷CÖ=ð³lk‡Ú£kjû~ã·þû»î¹ÿÑÒ~pÿ£v_´ŸF»»´{zW¥ÝyïOïÜðHiwlxäŽõCíöõ4ÛOn_÷“ïWÚmkRÚ÷Öþ¸Ñîi´5¥ýàÇ·µÝúƒÝr÷H»ùîÝ|W¶‡oÊvg£ÝXi7Üñÿ³÷'Psgž/ÌÌ9÷Nß™3sû;÷»§Ým Ý=—¹ýMO»ñбeÛm›Õ Œ1›mÚòÂb±ãÆľ#‹Ù$!B }G í•’Ú­ ±·ÀÆØúþ™ÿ¬§¢r«¬zkÉÌú׉óž|³r‰üGTdÄ¿xž·Vn|“iÒ† =¿áM/­Gzã¹JZ¾î KËÖ½±lÝ®e/yi©¥µ»úªiç’5Õ´xÍÎÅ/iÑ‹¯{iµ—:iÁ ¯ûé5¤g‘Vé™U¯yi¥—æ¯ÜÁôôŠjš·bǼ瑶#͵ôÜö9Nš½|›¥YË·ÍZ¤™Ë¶Í\¶uæR/ͰԷuz5m1qÁ_ýõ>Ó–l™jiñ–)AÚzÔQG‰d*i‹­ÇjLÑŽüîñhÜ0~ÉÔ˜v:ºqPÇ£¾}çèã5ø6~7!¤€R@ H) ¤@“ ø Ó€Is–?2qÎgD25©bÌi@Ìî5ºÂÖzã­ÝÕl­‰†ÖŠ•ÕL¬±öÕËj¼YµÆ¦jÕÀšêTÍšj¦T³£FÔ oš5T×|šd8XMÍdjöÒ°±4ÁRê›Ii’uÔ5ÖÚEiÆ4­o Ì¡U‹èâ-Sͺhó7ÿ^££Zìñ?غ+ÞäŽÒ_°tõÞûü-6\c{l¨1°WlìQëzš]=΢î•~`Q¯šÓSJ¶ôŠ=Æ„îÙÏãK&ô³¹ÙÌûWú^,äÏmŸk Î6n†q³Š³ôÿù3^w×–~PjKÿì_ß(Œ©uí¢®TÐmØgß¿­Ì'3‰›wÖÌ!¢}{¦ï¶i6oÈÖ¬öEV"d#V3-Xi»^¬Ì²Õ²@6Y|[Õ¼ªÖï)ç åÌ i²é“1LAŸ)‚19 ÓVôŸÂ“;l[¼yÊ¢b`Ld˜¿°Í+¾—vÝö»Ñ"™ZÝTêzÅSÀg˜N`û†ß\ʉd*^)'Ç>Ãt¾Õ·#D2§ì”S) ¤€R@ HžRsfŸ;`Àä9Ï¡÷aÔ„9Ÿù¼|2µ¦ }H±»ÂÜzí®é+E]€©añÖˆÆ.M^a˜ÚI±¸¶S[ÿéÌûVÓ˜eŸ5k>mÁgüjÏÐRÏ8ŒÉVxú‹7ì.﬇1yK:amcòÖ'XÝQúÏúSÆÒLü‡W·‰a “ÞJà4†É5žWÇ2LAé» ±Å,÷ ¯õmÄæbLFø[Pú˜ZÓ ê*%R=ÂŒL)V¦=t‰S`jŽa²ÙÀò²݆ˆÛmIŒ©†³´y½Ê¤_LÁ\^å­TõAPƒ1Õ8HÁ˜j^=Œ©2…&½ÖFS‰~"z”( Œ)… ,´CžÃ˜0`ºU7KUgK7Ür'F\Õ… ô½ƒ.E|/…©êL LpÅ0Uü0Å.rqìŒ~˜f˜B J²2Lž+&oiQÅS00ë'ÃäàÞÃÔ +&0àQŒ)äŠ)ÿÞ˜<†é[‡-^½Ý¦Ïa7¹U$S;ÚK]³8 x Ó1'` g¿ ˜“àÑ]$SqʰH9E½‚?g«opdˆúvøÀã]½Z¤gV^¥€R@ H) ¤@ð¦/ ˜2÷9  \ñʨñ³E2µ¤01ÕØ]=ßö5îí¯7»kÔÖZÏÉ}"ÀqoëÛ¾Q?L=ñd¤Xü ã°÷ú¦\1ÅxÂðüa4âŒ'ðÆ”äŒÇ÷Lß4ÆTµº;¥Ïø˜àÇ4?-í!c{8ÄA_sC¬s¬ë­%Ø22Lîà ŽA½ ¸bª5•[È‚p¼‚ÚU¾Ñ0QWLæÅÃ˜î ¼1…œ£0.0¦–´‡ºH™ Æäø>ð^m5sˆ;<ŒiþcŠú“ 9“³F,ÖS:Ãä»bª‰¾Â¸+t˜Å([FV‰wÅäNÞŸbª¼ƒª®àoLt.`-½1ÅbLþì›ÇË c*ÓoDÏÒ}„1u¿ ”ƒ¶(ÐsÌaJ©Â*a…oùþIn´8n‡\.µƒ.…|/…ãÇÕÐK¾£ÈÊ»(rÑ@rµ®ÍŸdµ+S‰%g>Ý$!€©~˜ZÄ0ÁeeáäÂëàA× 'GW–Ęj—žTWŸ`ä–sŒ‰ Ó’·‡¦ÏѽånùdjK£©‹æ_2L´9²¡#V‚ßÅOOÉ”ÿ,XÉ0yõÍ·`Á“Õ7‘L+KeW H) ¤€R Ô  Ó¼çÜ/¾#Ÿýiùdêwécб»:ÌŠkwÝäÌõV ­ÛÞƒ‰5Íý‚'ˆÂ˜ÖÆ…{±J¬—çåj 9ךjzÚÂ0ÕºbJd˜ZI±Ä»br1¦Xg<ýÁ˜¢kƒXÂ?¦ù£®JBA—²”~8 ÓæwÖ"¹¥_‰Ç[ú±‘»Â0‹~Í÷IBé{±œqÄeq¢Ž¸‚ r>Æc÷-á˜úÝêeS€Sˆ[ Í!î½Ï¾O/~!ô:KІióƒ^Ûå4_¡Xr«1ý~šÈ0Ùd_œ+¦°—¸ì®˜,vJöˆr˜†s1¦š¦•ˆrhj„1•íw¢ç鮘º«¿îÞ6zcŠRJ>¨ä±J×Ý ŒéDw Hu(U -9cªÀ«m]Â"!so`§ÐK1!äâ<0¹#®€Éx×xÁ8a âyWWù+Ò*îpk¢z{Èv…Ú®úŸŒwŒÌˆr­ðÃÔJ†É 'ÇøßUŒ)NÎ_}bÓ˜ñS¶ì|ßÒëoý¾m?É. †éß:¬ïÅí±Óç(š›ï~äÃŽØýþû \Ô?´¯òiôÄοvíÚ¶Þ´…ׇ¨-¼Z[ŸºÐÃtÔ1'xæ'ßõw°¾ÖؼšüäôsϿ𒦟åØô¹ž­0í»;ïÕ¾ë7úìÑãÓsÕ*ýçÖªß#¦ÓÎ<ŸõÍu‰‡ú†%êÛa:ìžæÿ½÷Þë@£»àÓ\»{VÕz6qVwSw—R@ H) ¤€h‰d˜¦Î{>vÅ L(#ÆÍÉ´s×›-¹]o^„SÌêЊ§%×†ÖŠßx%db]ë©_K‹¢‰/¦ÖR,ž£zßF:Å£è^{íE»¨²¸ÑŠ-Þ˜е…n{£ŽuÖ˜„µÁoLðcš?ꧤ\ ‹)ýt|-3ÀK°Å®vœ`åÒ.ÏÓ½p¹–ó?Lé¥??[8¹G\né/‹ &è¯ïÝbޘ¥_1†c:ö¸¸¥í?~ôçÞlÖôÔR crßn!-Ú·y‹_‘¸æG0êF.0¹s‚tc©Ä’K÷ÔÊ0íê« 'rÅTÅjãJú„3‡psÝIºåñ®˜ˆ1ýUà©&¢\àŠÉom€1-Xö¢ÛÔìz'“nªóR  c*d±)Óõè9Œ æGµ•‘óµ>ÆÄÞ†%š¶ô.±ƒXŠBKQni½.%8^ª¬ ‚Ç¥ÐKv¯ãCÈU<050…`>Àätçô4¬»; îîLîìY¬)±TqJÉXïæ#×íÍC¯ÈRËü0U& ׇÓS2ÃDoL#Ç<åBi¨Bõ[m>‚ ÓÒ5;°V,ºŽÓç W¿~Ó]|hc$¦xaÎà¸ß~û <¸}O³mÛ¶#F4zý &pv9äœtÝL2¤Ñ»àʡѳ¢Ç#«¸rˆÜâÓÿ ê I T¦·¢¿ Z‘ø»tÚàó.h†d:t(~¨´-,«ÌÑk¢Ú„ ܽ…·¶KYU¯{ý”ܶ#cnùÛIÊaT«è^­…¿Ç Ãô–;k&]Y};ì¨ã†ÞÑ ÉĸµÂF›J´M4­ÍUsWK'éu0hÐ HŠoqâìÙ³›»©Î’R@ H) ¤€(¢Ãôôóq+^üÞ;¢«¬~}øc³>ý¹/Šdjºˆ1¹v×*¨TÁ•®½©jwÚZݰq)ðJÇöÞpÜ¢PšRCÕŒN˜|7öÁ*P %æšOÓ §°E0eôÔ‘b±hba†)™b9”Sl@1.éÆtÍÃB tÓ+†1U×GKÞ"cŠ–|K{J黾—²”~]|-» ®Ú Mµ¥_³¸ŽÙöÄPé¿ÿûšnt¢(º>ÆäQ˜Ñ–ÍÚ40wÑ œ:LŒ‚ºùj#ç>°òæò09~˜Vn¬‰%—•Xrýa˜z>*n cª 'gá‚©ºÊ<_@³ÜÆgéV0LÆ41À˜èM Ôà°©Æ4gÁª¼Mº½®*ÿ½«€0¦Þ-û’?yÏaL0×bI.¢ôÞµ7 ûî÷O4P)–Uª2Ô?Æö®  ¥XnÉw™Ž.£¬„àqqî—‚î‹ëö¶J/ùˆR¢Èycï Àä."É 0ùtS0Å3L+_{¦!†©6Ú7"¾× ÑC+‚wiÍr“ÚXr5 úO†1 Î(ànÊ!Æd SÅŽœEÂÌ7޼vÃ7D2hpç†á¥£åóèn³ŠÛ51ƒŽSBxG]<¨îÑÆ¾Unm¨VZQòWMG צT]19¾h˜ÆØìÙ^ûqS$q´ºÌ\C­Ìvzç1¦º9OÉmÝs[r@ÿ1¦Vý=†é¬ó3Ö·C'™@Ë‘%m-pm ‹‹1%Õ¨ØÖžøO×Dµ%UZ‘R@ H) º¨zÛÑéŠ}(Þ.Ëóâ°þx夯M¬ÁÀ'Ëíbégš¾oÒ‰ýq f˜©’/ypìÌO‰dj¶ü€1¥Ú]ßõì®Çž˜dnm™Wû—=?î¢Ð½T3 Bl¹X„¥7<¾átµ—e˜jV{fˆ&žHNe˜ˆ1¥P,McL¾Q½ÆÒîÂjs­Â4K¿})X sº%cתŽLjã1Õ˜<ûª¥'L¾¦¸Ò¯‰``á ,`S¥Ÿ‘`«ñÔ™aBéW1¦`YïfÃaÆÔlû§óʬ1¦HûVãïÌY¸ŠS‡îëÌ|î—B0+-X½MwÂäø tZª¸6*ÕSV†É‹kYq7PË0A(‰1ņ“³ÖFS™3z¶Î+ Œ©óšëŽQ ç0¦knZÞáþ‹o1œN•Rˆ%Ô5+B’¸%Ç·-GYî ¡ÇK‘V(x\"½Të÷8?Î]< !×O€©ÒïiÒ S¼¦ÃTñTb½oÉQ†És–kÉ[qBŸÉÆ€ŸàycJa˜rèÉa˜".gÌ ˆá¾û«†ÊN2ÅbLt?CgB0òʱYvîÄw:œ´I `n“¸‡3Ít7rȺ.KWF8‘¶Tœ‚mlÐvbþâc—2GM¸ vâÞÛ–%>.NïS!›²aL<€Y¥5™Çó©íjø–ÏʿۘÛ:ÒÂ÷ÐM SªaÚó ·òµŸÚ˜O&Ð$Q‡@VyÈ6Yí2"Tð/]ÂðwäVf;×~¬cîoÄ ž¤:º>oļEŒx"«½¬Ì¼>ûÅY5rsËãy°ý -Ãü*)“Ñë»p·í\Þ™wÅ^!ª•µ9íø=†¦ õíÐ#¿ßO&6§VëB%Ȇ(©úYéXcËÓšJ·iˆbLѪhõÊ*§U'ÖO«<î‹ ÚròÊ–«Pƒj°B-3Îe9#“Äêê>£½¡ø[s/n—ê¡&R*¤€R@ Ä)À¾ zèQtÀ_cöu2Àš¦vl¥PZ=ºJÁöXw:u§¹åOÌ9¦?ÿ…Óž~&5:Ý ‚GV¼p%L(÷™!’©¹rÆT×îõòB[kÝ¥¡nظæ\Ú›7 × D,3À°¤’‹8½ð î‚Oc˜,ˆOtþ8¼È3[41³‹SÅÒ<ÆäÕ£æwLðcš?«e,ýÐÂàk­ë ÑKñæt‡^ Ò£Qä]pù~ÝbK?Í WBé›û“ØÒoša‚Iü“ôÆ”\úòÆÔ\¨³J¬1¦¤YE¶cÆäûJ Ïâ¿ÈÞö^a1á/Øj°Ëܶ \’aŠz „Ÿx7¾ŠCX:dmF?L3L˜ 0¦pôRš4÷˜Jü“Ñ£uAaL]]·ì„½‡1E<âºÃ'øËÅpº:r® GP)Ì*W KÕ8q¡qu·T³<.—B^—¼þŠç\¤ÖñR4rœgˆñl1ȸ+ÎýR \¯c±ré Ùz9þ0,ÞS“»²$À”ì„©Â0yN˜è¸ÒK!†©0¹~,+SxÝIn½1Ã三¸bªDÎò¼ÎøÖ¨}ÝYI&7¨ç›É@`þÛÜ&‘ÅÁ.î4ò)Š1átºÁŒ²MuÛÚPlDÍ‘Ñ᲌Ì5TÔ´Êém›òç¶Ûˆòw?20[½dOÄieÆM I±4bÉNá’© e٠Љ¦½Çîá0Lµl_È0]qQÃ4cYþë)çd.g« 4va|Ë:Àê:€¹he@â¯Æ~V™y«xذƒí'ÆQJ³SpYþìWý1Ú̲äbLÌ<+QÈû‘ûÓãO›²¸ø#)™Œ^ eÁ¥°+›Ë+f2D®D¯ÕŠ'¶ã÷è0LuXR›a};¤’ ùg}@pÃJú¤T?ûÊZ*Ûc­™5Ñù­”ªh~Œ¬òu« /m9Ýæ·àÚO&„…žŽÕ™gÅ&0Êûâ_VWÈÂ:Ég$ÿÊߚ뇀î{ƒk_õ¸R@ H) J«@*B‡ÁúÀض'z5ècð[ëT`§õêÙùaïÂ=ØŽ$ÒÍýî-Ø“áuØñ#ƺNÇ–ÉSBÎ;¹ˆd7Û²Çþ¶e˜6cÈ”»‡½¬P_1”m{F\Öô±g±oyüå0ʺmì³ñ°ô§³‡j´:º Sàµ7à ôÞï{tÆþŸUt¹FõÞãaLÉvW˜[¯¾ñŽÀîZ1±¦Z+ÜR̤odQèÛAüz+BãâÇÕXSÍ­Eü*PobØRm±æZíVîÒ oäÈd “ñ™[ñá2LÍÇµŽši´fm§³°ÓØo©®ê¬uKß4ƔĨÑö>{ÁJLó‡&øã+@k E_µ±»^—ܰq5Ž—’}/¥„2Èî)`rçõ0½ðLµžµ–)#ÁV»Ê7c$AÇ0^]Ù /\Æ4ÌØ<'Lµ~˜T®áVO'ô†èN ùŠR˜.€ûñ½÷E+ |F0ã¼Ç…âÇÅ:KŠ"翪_q±o¨8¼2Þ”-_Fµo¢Æü0ñ½3r¢ç; )œœ‚ÊõÆïFOÙY„1uVoÝ­c ôÆ„³ÑHî:^…áô÷N¬:x$¢ä€JNÏ£f(`ÔNG¤ÆŸm5NœçÖ¸:´®q›äâ8hÅ¢KÇKñ¾—¢Áã|z©Žû¥ÊÜ]GâúÂu–’4à©>À•Îȃsw‰‰ë'9À$çºM~ÐóÆ´w4\>1¦†)b€óÏNä,Ã5°vçºÛ3‘LÄŒpaRMøàrœKƇÖX×ÄiÛv¬$®« Z0£“o7r/kóÓ¼µåÁææ95NëªÛ’òZ¿ôádŽ:B†lû—b:2áeí03´e&šfƒWèXãÞ;72†ÉY\°}žÃ9õ pÌJ˜EŸí«`Lø]œœ™dB¡ãç€r¤wŸP…gevë«DôWÙ ~‹_.h¿#Ô[ó@ÃB·º¬·ý"²ü]DÉõuÄ_ Ÿ4 c²Ÿ™À³mºÆIÊdôúð‹šàN~0QŒ)z…¨V”¢å¿ÇÃÄÅÜ|óf©o'“O&<>[|¢ÍŽ5)n+ǦÛÕœUÈê‹’ÍÌT…¦¦x|´*Z-ÅBœh’7¦PËIFÍ* (šg{:û Ì6™<»ïK, Ø”6çax@ûa¿¡]¦Œ6¤€R@ HžUö"\Ä;±‡}ZãõÑqãÒ²7E&ûéåa÷†›ªtl]SvÒÜ[°s…芰lWÃ5ynðÏ˺ùg§‹Ý¼þÅïÑftLæ9z…¨Víø=Æ1L!fn—±¤Ñ‰Ö·,$'X^6Éä–[Nk<­ú…ŠØ*¤GY0¦Øªh xˆx³ŠdÙcÆ¢-§ÛÀrªÅÊ3ë ®€ÆÙ¾bãɉ={(W\¢1o®Ç)\×±#‰Ò¶¼!Ò¥€R@ Hâ*À¾+ûä¬büu?l ;çè±Ø콸#ÊâvEB] Þ‚øµ‹YÜž:<ìDµy;vÙ¡²î"¯cR»ˆÛ½·n˜ O¬›m·Ðíq¤õc٥繮±C•ô§³‡Ê^Ó0ãø¹/ ˜êÇ’ ûar½ö&¯xA×ýžG¦Ë'SvÍq$0¦ v×\sk’­5€–+kÝE¡¾'ûºèRØ“}]÷KuðÔ "Ö„Å[ä™HÎõOo “M'Ã(êcL5Á}B¶Ðoþ½¨c­ôÊûŒoTÛmÏÌgW`š¿¹Ò_Í•À–6½U\‹ePÇ ¡ÒÐT5ž¯vB5y*™|P j3¯ç‚+`˜Rœ0U*ÀÌeÛf. (H$Øü@rðÆtí°GSÖô*¨\Cížîˆ1ŵoUôÌxvEüŒa0]˜ØˆÙË+Îe`µÕ²&+ì’Qä,ÊJM¹³’3?LQw€ž£'X _@ÖþÐ`¥åÙ‚i¸*ÆTñü€ÆÔ ¿=cçÆÔ9­u§Ž*ÐsÓ•×ßêL¸ÿâÛß;!z@uð*Õ.rT±¸GY¡¡uZJt¹T'`\(nÍ’‘°ã¥„Èq5¾—ªÁãšs¿TãÙqDrŒœ´²$ƒ¦: ot˜,¹cõêz£Å›_ ŒÉ&vj¹z,ðÿQ1À™Ë™Nî…—3\¸3ÇÕCëLfÐdSÄic.åäì/&2F0ÐjÉÅv6,ü–]–_|E~È¥Ìl½‘™_Í Ù#3‰bƒžð9w œÄ#ù-­¨\ñÉÕ¢<×rËœ˜ ÛlÇt¹¯Ü {æFg˜h] åŸWÃÔò—›Ã0½Éa^<Ôl˜ö~Ë·Ãûë‘L4ÁÛ#°òÐ(ÏpüQX…$†­ 8€UÈs¼c¥b=¤C&VïÐÁ¶|9¶Ž¹¿ˆèÜ@ôÇh{HþYÅÆ6áE[nn¹Å²J”…?pþ´qY†HÉdôú†6â DXìçÌ)ôFµbY´ð÷è1LgžÌ‚4Uߨ£¾}»žO&Ða±B·¼°RýP QjèII­¹sËԆȮE«bc2ïG¶ªÞšV|Åù°hËÉ Ãß‹Ur^ÙòÌŒÙÓ±¦á[¶ÞøkÏB•XßX]ÍOßY|䧦¸åM±.(¤€R   °o™go„ÝZöUðáëÕËFw†¥îÁDšì`»rhñ@ôÖ“±‘,»²îÕÜá[ä|6óéöp’0&ìg‹£ZYX76°‰yàNöôBʸåîbL¦6B^œM7à’åž}ºF1¦†Éõ¢Zwzïw?<ýŸ?sàÎ]o´žw8ÛÀ˜²Û]kl­5+B#nìãÜíÄ»\Š'WÒÐ¥¤àquØþ-ªæS¬c±T¬'»&µUÕ OV„%Ñ “k­µ‹nö0¦H 9w޹YŒ)ƨnföÏxS8|Ax=p“¥Ÿ3®^ƒe¾gåï%§ô=+º9ßrÝ/5„¯¹QäÒcº¦rr!#y8Œ`ЦŠm嬋H/áxŒÀŸ˜³âÒ«oç,9Ž#±Ã>ᓟ> ƒáO~ê¤_]t•C/¥ööW–lß{ß¿‹™»>*èÝzH†‹öœúƒ1}ô§Vì¸iÑ– ZQ7¯A†©ïÅí³‡Õ8ò’ÉG^쥓†Ìøê™ãåè³^8¹#.šôÐŒu4À™+&(IцܚF25ñD!ß!M\¡U§ÐÏG«®V÷:0ÓM4üVÝsu@Ó €a:ò˜\«4¹OZ¥ñ‹ð“~vÃ\c˜b~þ0 †iþ.~ðÓD’©é¬†Nt×4·êšÝºŽëð)vÝy·2Öòû‚a:õÌó£õ Ó?üpÛaÖ·GgoHªoæŠÉêÛ·O$™Zõík™1Å>¥ù@ª›gLåFó¬{¢R@ H) ¤@›0fšnl… az. utas»X\¥`kfb{Ť½IŠs¬Šë»·À÷:ü7„1ÙEx.Ž1軎cé6‰Ô¸ÑB¼ ÝçâºXn{Ü‘ 9šm+Ó„´ýbòamNça\AA¸§îÓÙCÕ­ Ã4ï9ócmË]ŒaŠtݹ&”ï\4iÔÌuI+^0Z6j*ü—È'ô÷›žX{ÐÖwgÇ–EŠÝ•ÆÕ+’í®ßøöá°©"}ì¸"ôècOªì9Ɉ¥{GM„55´"†V˜"¯¼a˜Tô“_ìû‰¿wç€ã½.Å9°w]ïÀ"jü –HzÖEØóÏŸ>À'‰cÝ/Å;à©õXï#,Û}Õ§L~1HýÁ)@X~|ÚùH°l¤#,tÂÔ&Œ FõX{;KA1ÍŸbfwêÀI´®‡êÀ7|+º¥ sm®­÷Œíx¨!Nøamp½.¥ KQßK^pVÿô/‡¢ô±ÓjÂ觤ÇËŠ¯¹Ð@(~S\ AÐK¾v*ÀÇ÷ý»Ä(rà †ÉÃ×Xú˜ê¾Jt@*0ú¬=/ݳû­èãcжonƒ†Ê6-K…¼¬qjà8^¢qû¨ïô‹³/ñ_[p9ÿ¹WðF[Zyaíÿ™/øé€Ë®½ƒ/,{O]ûpLöÙêÄ=-Ú:=pÛÞtžE‘«LáUÞGæ ®^ 9(k˜.Þò ‡1í¼RÞ˜zôW¦ÇnŸ˜ڧ­®Ü)h$ Ý-Æ£}Gw*«íº†Ó0¯DL77¡Ó½@oW\{»?5^¤ÎQSlÂP '8U"_rFNâXzà±'a…ÑÔ‚•›q=7ÐÇÒ/ιCnZß|×Cø74´®‰«…–²pKîxÛ§þêb,ላ -Ù±è’3ö~ý«ÿrh°~Èw€|ߣÓ~~æE^G‡ie°R-ä ÷wLÛ{ß¿O¤—¢‹ŠœÎ1¦$÷K5“³Ä$fˆîCß•q–›øCµÅÞP-”šÃ˜6lÛ €iÄó»«o¯9/ŸÜ®úºg¦¯ë°%`˜*ëÉÌ•(j&Î኉l0Lß¹xRÀ0½ðÚO®Ÿó•3Çœ¾=Øù`úÜwÅD\\ü[ZI2µo²¼!yaýDN¢®˜ºHCÓ&K{t'ïÛP&Kv0¦(ØG«ô)7Í;çŽgÌ?Ù‰WL¿qÌ ²}ÎïÂ[SRý]¼½0”'µ™dBU Em(héÐyežn¨ ú,éÙ&Ã[ßà‡é ³ÆÛ2͛Ƭ¨¶Ã¡úV1AzTn¥¾á=…®I>™Z"fûZfó½d~Y2ÌÙ,¶™YŽ×1R@ H) ¤€h·Сcãb@¸#:·`µ1ŸWÝп ÖfùŒuÁ‹Ø·¡[ð¦6R°ÃÜ«Ñi“»‡§X>Ý<à07jž{ßhNBKqö„nÄ‹G³mûíîÈS¹{¨§K;1ç?ŽŒÕÖ­!d˜¦Ì{Ηª Å-ráߣs6âH#­ÿôIDATc2/ª?½a†š±ŽÞ¬C®˜Ì„rÇH‘LžØÀ˜` CŠ…™hw­ÁõÌ­–*v×°¡õªïÂBV 6Ò'f,A2\ K@A/Á²jëBCìah…õ ÉŒ«8“¾ñäJ=tɆu1=lþ-Žøî‰§œ‰% ~ŒžJð¸¦ð¸˜l‘§ëýÂ]äé®ðüÒס Ó¿žv>ÌL¡(r†°Ð.Ú>Œ)2…_-ý©óžÿ›½÷M2³_iu`C¸ è­0‚5·»$8Zög¨ãsËóº”6ŽVô¨ 5!;½„æ¥Æÿ–=°!ÿ[¾fNP*SPô‘Ò÷ ãŽI\S»»º~Qxàä=àÎúË(ÌDŒÉ}9ÛÁ íÛTŸ¢vÆGbñã $ù ¼àÒkÑv~öÅœ¼qØH@KûþíßÓýÒyÿvõI?>啕Ë^Édó}h¦à~ 핹ˆC…fêö¯ñJà9#H˜ž2ên+31»d“tUÿµïø~#Æ”îöOÞ˜ŠúKQ¾ó©€0¦|–‹r•Y.kc¢ èr`L—_;4XÁc·/ÄøöÈïžàzNŠns,ýè§¿À¨Ø<Öb,}ïCÞ’ ÐXl]h #jÀÔ.·tóÆ„¡õ×C§äkß< 9ÊB…xõ~ú¯.†Áź,§ýêb$ ´ðý*ỷèÁL~z¶ò.rÀo¯¹ã¼Õ!Ÿ9`Ìä6êv;4¶lÐ†ßø‹oáu _ýÆ¡èè`ܶ±ñoWÝKpÓKz Ûî0 Û÷ø×!ÝýðÔúÔç¿üõCð÷–ß=n‘ãlÏM÷ŒuûCÀ˜œØº^¯+Šþ×þŸÇâ Éð=åâ_&ô“ð÷KŒ¿ßçïn>ièðI¶ç¶á“ÌYnJ¸÷F1¦µ›_Ÿµöê–ÿ­6mŘ<†é›‡-Y½Ý¢™löb1™»ŽÐïœøp ŽŸ¯ôù³n›Ä…“|ŒÉwÅTër†Z b/¿yDJt¹ÌÍ‹”SÀc˜¾{‚­· [¥_ÚuЙÀJ*1_|õßc˜üßÅ™þïbÄôuU†ÉqÅäý.<'Û›Oüɯ’¢Ëuî9u§|(à1LgœŸTß’†êæ?ž¹¾¡úÖn’)B*R@ H) ¤€R`Oû {ˆë1L ˜2÷¹Jï=ð×8aª0L0¡cÂòzQ½ö“oÖ˜¨ó§èÊí#¦`ú¿Ç}2Æ 3cб»:Î'’ì® kAa#¹àEXY½Õ¡•å €T0üÇßßù¦×P8Zéz‡Ž+Ÿ¶®,è»b丙fk½kÄâÁ¿\‹rçðñ0Ÿ¢Jà¯ÙQaa›4o쨞ÓÏxNw\×õ¼âÙß°Ú †S˜L‘`#ý·«oDzϟŸqÑñ'Ÿ¶÷ßþý¯¯ _õ_ùÆ¡HtZ XM¯ºåØ%ŽûÑ©4bψ ÏÀ^zØÀhAE"ÀtìOý'ß zÈQÇ£B90“šiô#‡Éôà#Ätþe·b›k;O?÷Š“O=/„°´c –œ…Lî• €Ÿ'¦ù“,íá:ðlPhöAѳ0¡Lvµ»$øt«¾E½^8€k€­  u! P40¨¾ã¥Hظׯ0v Vt”>ë}/a#¦Üo}𞇧¡”?é1ÊšìÚ÷ýš€tèQÇ£Üï50’ãï…W܆ @Ãø…—ßêÆï1™¾‚E Uâ‘Éˈ¯aÛ"" „1é},â ÆÄT 3¡á5_nãæ¼ÚØ¬á€j'¤&È©ç× …[r¢íÂä æ9ˆ·fÇM]ˆ9A¶Zh¦Ìa¶ÍUš©Á—\Ìõ8sñF2L'œ|ƒ¨ š (¸!À_LHôÈWÚ(Î%…£È¹eÅÅ@È MëHY&Ý„1é—(Z©€0¦Vª©kuZ,X‰äú“¶Ô÷Æ„¥óQ7Ú~‚ÝÃéË®Z+ÝíRlxßzäžÛ¤ÀsÌ¡®ÆŒgWsÍFMn˜mKî ŠÃfðIŽw¥7ÐÁΊûGoiÈMÃFN}æl<ýÜ+c_~Ý0ôW¦Î¡2´Þuä1'Z². 1&¸ŽÄHÛó¹f'º)çþúêSϺC/,ˆ ÿ]‚ÇcÄêvƒµ‡ ŸsÉU{cô… tk®¹m8¶É-ÑëŽGÿæÞÑÓ~vÆ…ØÀP –~}åPôxÇKÞ’5oÕÚ=OÅðÛè¢ëƒq8é%ìG{0ã¨Ìã–÷KwÓÁ9ºÓ;.’ùFÆ1wŒ˜„†å¿8ï ŒÓž¼ ¦ë†½4jÒRìI÷ZÉ!\–Fw#Ç<L˪S[1&2L‹_ØŠ0¸ãò{±Œatâ30aîüþ)kQŽ“¾zÂåÓQL®1í%7œœ¹ p _‘L-j]t™N(0L•±_5Ú¦öat‡èø-í«ÆX|áµIÑß…?£kóè†Öƒ-ƒH¦Ngîï†é0Lõê]7³¾1EPßV8íp¤¾‘%e}É”ûº  J) ¤€R@ ´@èÚÊ\Ô¿æ?{À€Ésž‹šPhE1ªè½ž½ývôÞ'/òì'0|c –%x³æ´ºî"™BSfªow½†v×[+ÊÁ`E<8ÃV8ê¥Äð:H£÷L¯ž›%ßÖ­…­6XTQÜXð ÷\ Ëêˆq3±1bÜ ˜79üØ”…ØøÎ1'>ÖT˜Rý1çw«@=ûê%W£†À§…!,œ¼‚=¤—°=ôþÇaõ¼×ûNë.=üä3°šÒ^Š[(&Œáè SŘ$†áôÊ[€itʳëA±À^Šô“_\€D3)§A®ÜùÐ ,°‹Òõè¥_ž?qÄ,‚¬ Y` Å OúÀ0|ÚùiÂ"ÊûûnÔSKca´ÉSuÕY­½¦xüB1Ío¥××§ÜÝ:b ÉJ?¦¬Ö(qÌý»u€¶ôaŽÇ2àƒþå0®þeéã/€«†˜Û-”¸‡1ùñ &Î^ËÎX´ÆX€k °ÁrGðÊýäÓ`3»z Ë}=³ùsÞ¢S°g^xåÅC†æÓKHà–θ`Š5á©ùë`$G¹?:u9*Š%Îr(w²ð{Pô(qü=æ¤S¼ °xËy¿½õÛß9>).‚ʵ꽣ë”Pcª…™ˆ1ÅÏ*V¦qÀ¤9ËC¸’­¿M rꆹĜ p[ó_`AW,©‡1Áö ­ù^Zø‚Y…Ñ4=ò䳈¬‚„ x% ½„„ µŒ¦BÞäÝÃSѯ¤åÛÑyÁ ™òÀD/•„¼CÎÿ̧@ÆI7aL%ü鑺¨€0¦.Н[÷[0L yß°7&8‚fàx{.‡7¦Ë®Û™àN|ûï²zDýa°û=ŒÉß`zèñYðXË¥?–¦ù|Hjo–ÝOô±„õ@TcŒí§gbÛBÛb{Äc3Ð/±Õ!è¾`;è² TÜY3ÑÙWa©Ð˜I H)a…ГsWbÄ… th*#.oÔMKìÊ ‘ËÆ)ØfÀ8`ZùÇ]ÞÐËǘп!½4~æóƒaÜrï8s¼Dt‰¸é™Çf<‡ž7&÷c˜ð×Ð%ËýÎç{ÉØ*‘ÝI/ž²—aƒsŽÍ¸ÊÄ<$cî—ð†è^úçÏa@þ»1sÓWfìQ}úóÜ?õgD&kî^¸e2ÿLýß8kèÿþµoºè…mnݳ­YßÀ0=:{çÎoxtè ®¿|úC3Ö¡t€1 Ÿö’Nn›ùBw§ÏE2õ»Õ:¤&´Ï5? ƨ,«èùij¯à‡b˜Ð¦9¿‹§†OuÕ0‹f˜6’鈟üûÿsÖ ªÀá?Ûë”3ÎK¯oXÆÔ7%7^¯Ä˜²Ö7Ç©»G2ü7ÕU_¶üKR ]ÁÛóêòµÂºR@ H) r©€Ï0} s‡!Š;Z¤mCÅѳ<Œ ó|è·£÷^Y–൷âŠÉìK$™nœù¿t¤Ó¾l#ÌÜœÅî5´†V„"¤°UñGýž_ ?¼ÒC¾w%3±Ò ¯°šÂÙ&€a4óÿzTz¬·i`:±ÀšO¬ÿ´`a´©Â(Š„S¯pb˜vT?pX5fÑ%Ø0= ó)]\0Á"Šb˜OiA½š*†½”^êi5½D¿;Ę`&¥—úA§_0ì¡)ƒN?æP:^Â&’+œ?·Ïô0c‚¡ïäSÏGÂ,ò·¿sÜy¿½åÞ1s¿xÐÁIvÑ6aL®Q=j~ÇÓüé¥ÏoA¤¡ø¸RPîVPâ0³c1pPÖz‰³þ•:°u€Vt«\L€u­Æa°­ø¥uå~ÿ£ÏûÀëRmÐ@Ôs¼„u¿°œ{À÷k‚'¾æ©Æôy¬øõ æ~¼úÜ"¾†mp¨]qñ5Éi*G)[ä&àk VÀ¢÷9¶-°£ô cBxxÒ2ü z å~í°GSLâòÆ”ËWY2µkÓž ?!ÃTŒgýå[ÃÏü‡Oì4«È†ëo>¾ïSµ]ǯAÍtaõæ7_ŒGÇKçýúj´]lÐb#œ¢E2‡nK…WÕßõ˜Zâ•À•¼W’ß4aÎHÖb‚Í%4MÞ\ÞsÛú‹ Ðá„V‹Þ˜ðJÂë¦ÆÔ[laLCSÂÒg'LÖòdñ Œ)?{e¡D c*QaöÚ£]BD9uÉCÏ2ÖÖ3bÅÇ`©imºeüg¿0àÍ]º±&‚{¥GXßÖìÆëçÎQ¾ÞôùŒuÇ_>ÝK—MÿÊã¿ð©Ñ³6@yPbÃäcòær†ýë>öÄmo¼ÿ§?ÿ¹Ð?pe¾Ü ÀEð¾…«¶ñwa+ûh•V2uñfþ.àßûòáK# ò»˜f¿ ˜‡ª¿‹J˜E·ÑVò“KŒ^~xkݺZQ8ëªúÉõ )êC °¾áßI ^©o>­›Ä’Nxzý_ýö½?ùæ×¾ç†ƒ”¤@V.ßß³¯=s¹=R@ H) Òxë­·:è ‡'Ω1¡8Ë]l"ËÀö.c×ãÄ#`?™½‘QTèµ×ï½{&oÅ‹³>­¿ðµÿuý“?›ðâ7Š2ºia>ǯùB5çå“~Æ1Q»kÅÊêùOªØ]öVXVï1Áu«sþ¥×À©’-=ÿß®¡‰«@Íu=­H6ã ;ê wŒ¡b A½å /z¶$àJp¶D¿¹æNQ¸M³*È•YK6ùÕw˜01ìÂ+´ záÃ>ufˆa5ešºpÃOyáOyÃôëŸó=^TÜÕc{ìôå0‚_1~þ _\n‰ ×y`‚÷Ÿ~>øl€^BºÜÓæ€‡î—à™6RcZLŒÉ !„ ËwOüù¹¿¹¥ÓÓÑ5kÏ‚HItµî'1}|ß$c»Õ.FªÖŸTCà2àhpgý­Zbéó/¼myEÏ:P)wÖ,ÆJŸiôSÏr­/Ëݼ.1d05ÒYˆ°ôïAzxŠžø*ËÝð5bL´“£ôÁ0!n <0_»ñî± :Ž—BËzY>ñ€Ê Žœ£|’3”ò†Ðèyx ’ï± ’õHð•-˜ £k/0Ü‹ÁŠl`QÙbpÅ·¾‹ã‹0ÊÂ¥è+]Œ²ÐkÁh clô]Žøî‰ç\r5 % ½µÌ\²£ƒ1ö9{Ñâèi ûáLò¾ÑÓÀ-11h76È-`⬲rh0m ´èréâ+‡¢¯X›èR5UBŹè| c$vÅMp4Ž!Ö…WÜ “Ðå7Þo£2ÒKô‹ËtûˆI¶¬„K‹à×ñìϱÀƒ´ó~s V^ÂhCtlc×BŒ AåÖmy÷Ùõ£¢0Ì4ýýÆ¿|ùr˜áæômpz·AÖÁîvã˜0Àaùà×búåè-öz~Ê ¼ÎÔමJ$#c˜ðtH"™ÚQ”ºf É„¦oÁŠ­)¿‹!#–᧺Fï¾Ékñ»¸wÒÿwáµ]ø]<8u-Ù>†“‹5LƒaºæÆaü]¼ñÎï[øºT€0¯KP³4ªÒûFpD£@{dÖú‡g®C;ü“ë瀙«´ÃÕúVÃÌEXÒ€a9Nõ­@u#/Y];[S^ÊBùR@ H*3½·ïÃÕ„Yn]w8a„–d ψ Xp#®Q´~Þ¾ßß{ï=÷"¸£ë ÞFI|°NãŠÃ%”öUC#É4j§÷6¡ØòôÞ1f„q,èº{Þ¬“½ö:Á éÍú›¾jÃëè½?³jç?ê¹Å`±Aå`Ã~–6fw­ØWÁ0M™·ü$l\vݰ)ó_pö0eþ*˜XÌu°D[ë©¿º c4˜XñíØÉ ]gK ”Pú×ß>TNÃÊ Ó(Ö‚rñ' ª°£ÎZ²ÀÁì¨G}‚gRxt3x%˜&¼â›O™0O|ØÑ'À7uÁz,ø|hâ3`˜¸à8 ­¦tQsÕc¶Ø|/\Ë2ì!S!B€ ôÒ wÅž‰ó^‚íâà#ÿÅyWÐRÊå°‹dáÚÎÇç¬Ãô£SÏ£- K:ËÒ&oLiFõ—v=1{¦ùCnHÌÆž\^ž·üe+M놬™™n–²ÀêÀ˜É ÍÙI5”ûu‘:0ú)¯Üî[×aHÇÚ$=¬è¬(ú T˜c×Xð½›xôÒ¯.¼ˆ@€¯Uʽ‚¯yåÎЀØ`(@¹ÃZŽ„2}rþK(zì¹àò[ƒøqþ*_˜Êý °å{¾C&w}/1&TcòÊVq”»Uƒ$ø0¦†Þ/=t01&Øzö *÷TþÊ1/¨œÛ|ÕN)²YÃOÌZfmšùXªlxЭ5\¡Ìp[rKt^À~ ½ !Ä ¼.¡±Bë‚,A/Ñ÷b›¢uºõÞqhšðzºê–ñn M(Ä3§€x%Ñà÷ŒÅ+ÉbYžqþLn¹Å>äM'Lê-Œ©g=zðî+ Œ©ûe ôWf¼1Ù=a˜(º+&§/½ê¶H¢ê¹ßbÄåö-¸¬§&Õ"ÒŒ§Î„m Kö/‚¬c”Déú;FX_„”̶]LÌ{ðqKô[‹o§Jc‚=„–ãöÒ«ïÀˆt‹s.¹ Ãlô]ð/vÒi$Z ¯‘®¹m8F\ÓŽ ¸%ŸÅœ-îŽ}o·„–ÐÅõ„×Å·\ Ão ¹ÑÅ9ñÀ¦,𢶛ç[ŒÃáý˜1ËÜ„UD¾î¹d3m9Æ`Lt¼„Þ¶çqOÊ/}í`úÈEbdwŒÒ±„ÀÞ{½·€U²ðÞ˜á_þe' °áo–ˆrÙ½1cbÌ4ÊñÌÔ&Œ Õ•$Óì%ëkúµdðýþëOo˜ ÓÒMÂôùcó6Ärtí¸brú S­Ž~˜ìÑD2õ·•ÕùíW€$Ó³+¶˜[2¶®ö»Àˆî†GŸÇ²Zð%øi¸ ~?¾vvÌïÂtÙ@Ëe˜D–´¿Hs}Ÿd:Î ¤H­¾Ÿÿ2a¶Ã×~Îe˜âê[e1w¥¾…&Õ·\׆fNS EY’R@ Hâ(ÐÕzf†ƒI-]˜¨Á®Uˆ¨ <)îÎ<Ø¿¶ÑÏ#§å^$Ä!¹“¹mÛ6ðLÈ’•É*\P¿j4cÉ4~v’ Å\¨Ž›· &c˜@ ºn\1ËÀ–9‘Ç“&vÝ{d aL0±¼2Û]öVâ)0¢"1’ü*qÏe×ÞAT ˆmªî¤/ ­H0 Œ™´Ͱ¿OÎ]‰ $ØNɬ[á4°—à—ëäÓ<[kÅŽê¦?ù4ü K)’‘+°¹Á¡ö^¡g Ô¤ã~t*XM¯¼ù Kg^x%é%ì¤Õ~w`2¼Gõ؆½î£Ž§ôÂËoÅ6l¤øK§¿håúœ©Ã´¼Èœ÷W``ôý-áÍeÜ›"a*ï,4Yh¾øÂ¢Ï4Vh²à¤Àæûøª"YËè–ø{É•C¹¬÷,Ÿ°D´„v‰ÍcYÂÞJx%ÁZ!Ï¢Lž1“ɃhëLlTN­Šè´˜:­¸î×z ŽÑåÜOVoL­ÏN7®Èát”z¶=øöðÇÅ÷0*æØ‡;~®Ìq.éø1H~wÄí”R]ݨvPª=¬ B ØN4nsklž–ÜEB6Ò6jG\ÕQ·3ðfϦš*¡âB.—nºg¬ÃÙã1n‰¾dÏÙ‰Œ3‚ÛbÆUƒéVPîj(Ü+ Âëºp7Æä×ø¡¾ÇÍY“Ñ÷Rt—¥G…E*.ÆCÕ¦íïmzëñ±«÷‡'íöaLø‰dš¹x}µS[‰^ÄFt²eýTúaò Ë¡'ࢠ“|2u£YÒ=V$oóŸÛ÷»¨:{·õ‘lÖŒ¹Lgû¢ “È’†K¨\'€dBÇ J/U@RÚO‡¤„iËN¯o3Ë0©¾•«ú´ùi„1µY`]^ H) Ê­z/7ïAðÄ=!Oæ‚®Îq ¿‚} <˜ž“¢{Hð¸ËÍ_:µ={6¯`÷ãÊ@yH2át3xðàP‰àâI_!3üЏó€!Ùö‡®yYÞÎnA 'ò©í²¼ KeÁ˜p)†LƺBÊXI2||vh­ ¦PïËÀ¼Þ»T¦J$èŠU3C¹~˜ÜÅ`½F2ƘXF Ù]Lªkh5T%£qµ2ï[5«z¥_–,þŽë·žäJÈŽj¾vlÃE—Òl§µ >CVS†‹ÚKÝužµ'˜6ŽN'8À°Ež4™v8¨\Ô¨îÚØ'Î\ö×ß§º&-›¥Ý/ýZ{=Ózmð ¥&Jßu¸תöó8Ëyhů[†=4…>·èv+âï¤â5Ü1•ÓùV :Pú(ti’7¦Œï( Œ‰S-ÀDq€1Yó•4·ˆ&Ì\–ôF«iÇ’1‡[BÃÅ~‹Ø4vâÏ}UÙKÊ}CÙ¼žÛ4Ù\ž½’⚣X€i³»8©É2éöW½÷œ«Ü>&Ýô{”R I„15)œNË»=‡1ýÛ•·E‘#Ûƒo1⊠¹(R–TN2'1”’gL±Ë*²ö–ƒ8áÜ€Üa\©_Ç·ëAKá8qSão °6üßÓ®íñTÇá¡ÁX¿Ð%ÇKŠÛ1‚¿%:^Âß”pïé P²ô¨b1¦  ûÖã+vÜû+ßöÞ¶÷þЂŽI¦‹ÖtãPÜ&Y‚áteî<†a꣦-f€Kb˜D2å½ÍVþ|<’é‡<½|³ó»–Q²mtWÖšU:&ÆbíâÚ$†)…,Y»«áUÂ*ÃÂ)@’ÉES µ Se1nu$½¾¥0L¡ú¶ìÞ!S|驚ÀÔpîeƒ '¦2ÜJ„1µRM]K H) zN€2@pðî'*ÂC¤œD]Àôu¢!là_Ì=ø»‡ÎŠp$¯ÉÅ…Àž¸ÇÍ€ˆóÖæ6 ‘K2 ÃíAì-QoLÌŸž‚ò‰è—Û8‘¹ÂGhÈeÄ”1ê‹26]I27Ë5¡¤/?ˆ2LÕÈã{TÄ®û#‹g÷É´ûÃí±‹ SŠÝæÖ_vWgÁgÈâê¬ÿtãéDWFX¥À¸Z ¨O,E¡%3¯ÅN ÓéNÿÐ¥`µ§ ¯ÔÚK·ÄÐK¾ß‹jìžTz &PxâÁRÏtWL8¬MÞ˜l Pìrßñ3<Œ©f¹o³¥oR§¦õ:Ä’o2Š-ý¬Ü’Ï>†çQpÍYñ¬õõÙµa#'ÃßI,½ÔOv …Ž¢Ï@Aåš~Å”üDaL“¯b¹è‡S쬢ñI8`üŒ¥YÝÔL:ÍW”[ Ý5 mÒ{*xIÕ¶QÉôRí[ÉdI?pÖFÄK˜§kÎw€0¦’7)z¼+ Œ©Ã‚ëvR ç0¦_¹5ÆR…1·‡ <.倸¯âɤšE?@më?"•âý*UWñã«d\)˜O­%–b=-Õ…–ØÑIô·TY?T[ÚêÆê{]ÊÜ%J§”ê~ÛOŒ)åwºß­žI®%’LÓ® Ö‘fsÐÿGeaغ¿‚Ç3yT–a¥3LœAýíZ’y]D ´II“&}å‡Ì]¶ÙÖ¦„µ+k˜’êï"aâïâÝݺ3ð‘³7ÍnÓê²¹Rà¾ûî;ì¨ãl wœ&Ï^u%·o²ä›&€PLϺ ëÛ¿ðGˆ0aЀÝ;·EÕØÚ7xS®TRf:­€0¦N+®ûI) ¤@©@c&úC¢g&n×± œ‚¯ c2‡ç€rp|ÝãbL8‘çE\‚‡§×Œ5|DÉe•ð/om@T¸nj(¿â-¸§À1I¡%-rsEhÉ2ŒLº¡è¨^`1{!Œ‰·èg=Éô¥_þجŠ¿ Ì÷U¸ìu–~˜b˜†LûÝ/»]÷W_ßÝÏl—ãt`L-±»Æ!JK­°}Õ™ñ±¬&KQfʼnD y܉ZPSœîTÕÇy©÷‰–BöÒx×;­6“¶ cJ7ª?>})¦ùëZÝ[^ú kIKt¹”¦À-}¨zÞª²kž×/%;ÖªkúŽ Œ©ímëŸBS²¦Ä˜Ò›/€V®æ˜¸ +Õ·Xíû«ê¿ @-¹¥PTÓXt‰ÝKQßKî\^ô}û&j¨µÉ2é&Œ©õ¿b]±—ÆÔË¥_êgï9Œé’!·&‡^Ç·•yÊšá±ë-)ÞsRœkb×ëc§bשReD*Å®ªqhŒ²"Ãl['ä·bˆ¥ˆ§¥zÐRBœ8ÌÔ:#ðŒÑâjÖµzH–±_•¥G•â)©q2o0¦¡‹‡Â!Ó„5FÃT1yda˜¶ì|ÿOþs©›>=\?ñ)L³—¾ö1À"£Ä3%1LÛÞ¨ù]àÇ‹Ÿùài^¨þÀñ[Žý™£ÀWö«/ƒô=ù wÝs/zY! ’ÖÖ7†U­e˜‚ú–‘aÚñæî~oÁ̓¸ßªÑÞ+™à™‰Ûø`)º{p ¾zyn7KOc¹ZS¹ÊSO#¤€VJ¤…\ŒÉe’1ºÂ_¸)2Œ g1ÏÀ˜ÀáÛèž$ŒÉÝ+r èC¾Êö»î…IP¹tskWã²`L<+„1™ÿ$>]ŒÉ¸Ë-á©› 'ªA2zä÷«¡<+˸³×·ì sˆ°q ™Þ~e-þb{çê> JtÂ/Møl÷ã/cÌa?ŽÁlÀcSsOª³Š¡€0¦b”“r)¤€9U€Žˆ˜9 B j\fð þµ¬¾ã•3À×Y»v-N‰îqÁ »¼(×aŒ6Þ"„þ`Àa¸¬eù1'F8W¶s!oLîƒð¦I“›PJtÝd¹¢,&2‹1írËØÍ'ö‘îr3I‹®úï~)¶†‘dºÌ Ç„Rõc»Ü¥!† ˜žß´ã«w;|ñ“¿ÿð#Œ á¬—ËØ¸Öì„];9r„ýÇäô÷ТlcjÎîšhn­µ¯¦-M Ub•hx¸Ø•ŸQ#jÈW}·6œ&˜LŒ×*‹hû0¦£úcSû0Í= í¥Ÿ!X-çnj´ô›×¢èRGVù cjQƒWºËcJ.RbL)í¾Âhåb´šYÂ0®”Ï4Ö9\LDËZ¯KÑp–Kk饸ÈqÁ,^#L뾌²Lº c*]#¢êª˜º*¿nÞ>zc 1Fî¿lzäqÙñ£4>)yüœ¼&•J)TŠw­-U‘a»v™ýI†FÝáq—ïO"‹³¥,ÜRk½àÖí0Õ= Kª Œ F+.¿sÁØ­€;`'éضð-Û°jeáH2MzfmP1*ìGcQÖúÿðѱÍÔA~˜Ú×’êÊ]T€$ӌůÔü.|ß¹¦eS'¶W¿ü0ñaÒß²£C?sü䱇ÇcnémÖ]¬»5H¦CŽü>_ÖEÎ@Rÿ•šXße˜¼·ƒÏ*aƒÁ3[ÂNlÃKþ‚X¿ØoßfÂÞ˜è®IŸÒ* Œ©´E«“R@ HN(@oL`hÜgÜZȆzcâ~¢<ÜÃq¢Ø=Ęx5";ü‘¢#%° ycbNHGñþkÒb–’Nç·Ä˜˜swdÌ?‘ÝšÏèzKâÒÎE¾°c'Î¥¿(^*ÄZa?¯æJÝ*oL¼#I¦{¬sü§1ÇS—]~óˆo|øª ¯3âslúŸ7ÃÄ•-t¼sFˆÁ#W°f ô¬ ;QÅ»qbLYì®u|ÖPÏÄê¸VJ5«¶ÌW}ýPqþ‚Ït)ˆÑSC®TÖy¶4dX][(hÆäÕ£Õ`,0¦¿Ù'=ALŨWú©‰T6ª§”¾ïÆ;&D`Œ³%oÈÓkŒñ<¦ _àš[+„1u£u,Â=…1%—’‡1ùÍW4ùŽ”<8 Œ™º$éí–äÅ ‹kÀtÈÒÆ…ÂYz3z•äIJŒ¼˜ZJ/YS“eÒMSÚå±8 c*NY)§ )ÐsÓE—ßþœ= |‹éÉtßHu¿ :UïÄ„“ÂéDÉq§”Îq½ëZ)˜¹OÕª#®ÌÄRxì b©ZŠ„û.—² ž»xL–UWÚy&¿ ºäÙì|>ô% Ëõ˜2œ"ÉôÔÓk][A'µ0Ųb˜jup±ðI¦ƒ§/zÙ<“E­ÒÁÊÚ%¾•°b"lΓûC޵SÛÏœçìgnäb±äUnC d `âJ°ùH;¼%í=ØÄû’U¬œ0KâßÝ;·f‡`]4á/·™, ±œ c*g¹ê©¤€R  ¸Û‚‚Ê-åà (‡OØŽ\µ$<\?µ H¦Ñ3jL(Œ9î/?°0ОËY–…ašºzÉ—ïýrH÷ÛÌ*=0aƒ ذí K¿²í®I¦×&ì®U+kFãj…VIZÿ™è¨>bJ­»ìÓ™Îä¥~Š_Ç‚Ôqtɵ¾¶ cú~J陲äc³O]»zL€‚„M¬þM³¥ûk}-5Zú!j-ºÖ×/ý®k˜úù6é‰Ó…1%30¦ºÍ@+—ôYÔ2Ý3\ŠSÀ4t)â ®åÓsY&Ý„1õDâ‡ì˜˜:&µnÔYzcºðò["`ÃŒv\x™‡1U¨£Düˆ ¹BÉóÊ”œ!t>©B)͉¬ÉâWÉq­DKÁ‘Fp¥xb)#´”7gKu{`YzTM`LF,Ù XfÕ¢‘Ë–èa›ëö²|H2=1o Aõ-–ÕÔEXSh@2 øÚÁSmªL®U:`±éXr¦’K+ºvj÷gî:]cpÉB‹¬Ì› ™þÎ÷k<á¥Ö·æ&c•À-!¨ï8 ¡âàu N˜Ì÷ý6á_PM<ÛîÎúfQáRaL…,6eZ H) J¢@ÓSIž¿8A’éžG¦;þz«~¬JÕ•u†iËÎ÷/Ÿ}ýj㯭L3+ì<ðÌä:èÅx0‹îâH“S`LÝ5@ŽªWÚZ»kŒeÕ5´Æ›Xkí«Ñ@`¶§Ù•ŸivÔ´ÅVª¶Óh¨¸Ž «kµÚ„1yFõ˜e½A5xt²‡1Å.ôÍdcÏn]O6ª‡ÂÖ†)Hö´èQkrKù±™ËS¡›Ù6f^S²¸Ä˜¼ö-þíæ½ÑpÀ£“×iÍÒAÛÊRÉð<`2aéº\ª¦ç0äx©²Lº cjãÏY—îA„1õ`¡÷Æ#÷ÆtÁe7§ðFøöïx.²¤”ÑrüWË·§ÃIÖAñÆTqî”"ƒ«P)žUJ —ˆ+ÅKþ¢4gÕuuåPöÁyÊ‘YzTÍaL°a]²•v\‹ÌXä™`ÀâÓ¨’Lç®!©ÆåƒtÂZA¨Xr½Ñ’ë)=H2M^¸É]VkViwemÿ&Ü?düœ±avêèÏœßâ0üÆ dTi•C’L$†mwl}kŽa‚Jd•°ðp¨A€™ð/ü3WÕDOKøÛø {Â)ØC§MF8•Cp=EŒ˜T-¤€R@ tO¸/ y0Šîé^îtçH2Ýýðt¯÷ž`B1WF† ±ähÏÁš4óÀÄ -?øŠëXhó¡-Ȣ˕µ„€1ÅØ]+kºÝ5«¡5uågŠ—zgñgWʼò3#,ên§b;Í…¿¥t«iû0¦«{¥Œž´ÓüI&÷–~½u¿1Ð’_úþ9K¡(*}aLemûû\˜’$ÆnßjçqZ¹$G€Õ&.ŽU ÖI6ê°6–e|ÕAtÉ}ïd™tÆÔß߬Η®˜TJª@/bL)ã" §1+éö*æøìQFü(i­Ou 'Å#JŽ;¥øÀÛã6;àZª«CjÇZIQá\Éqt\ b)vŸ¥GÕÆËS®%ìa¤9þÅËò°Ýœ‹$Óø9/Íx³ª+Å0•´ÝÖc%*’éK”n]„1¦¨”Q) ¤€R û d6jªkBq—»4Ê0uÿ‘ò—`LQ»«ke Û]@9)ÆUÇ‹Ršq5–Sñv&ÚTc\ì$¹¨úÚ)´‹úöaL!«»[ú£žZ„iþº Z´&D¬ëÕi~ZÔÓÄǃK³¥WÝ,•Y‹ÚÉ…1å¯íÌGŽ„1ÕØª’M:³‡hßF=¹(óDa§€ñaLS}ÂÑ&¤nQÉ2é&Œ)¿|å¢, c*KIê9B ôÆtÞonŠC‹‚a0¾ýv#&=JÀlÈ”eì X[Oªƒ(¥ƒJ‰®• µB¨!,©Ñƒ³ô¨r‹1áÇL’é±™«£1þÎþõG{âº-捻-;ßÿÓŸÿ¬fQ ”LL_<èà‰ó7àwjZ⇩dréqú©€G2~l`BÅÃÔOauz}„1Õ×HGH) ¤€R ªI¦;FNå$Ÿ;ZÃÔ’ŠŒ)³ÝÕ·²f°µ&ÂIÙüÓ{¿#áÀR\Ô;¦ÔÊdp¨m˜âŒêUûCOz#³·¬ôë,ýM,ýXK=Rú˜ZÒÜ•ð"˜êaL)³ŠhÓо=ôäÂèDagOÙÖCl«qârÄ-…,ðY&Ý„1•°Ñ#uQaL]_·n§=‡1û››RÀø–bê¤>o)SœûÙº;·TGÑq±Þâ#mû!üTñ É ê4âT©ŒcìF¥,ÇgéQåc2’iìŒÜçÃÔÎfS×.€ ™üê·Á‘¸¿ 1L(¹bf$j—[ÙÄ0³$‹–kaLE+1åW H) ¤€èº$™n1E S;ÊS¿ì®ZëWkÜê$TËŒ+%™FÛ…1¥ÕG>±Óü)N³1³×/ýÇZ=‚+%•¾0¦v´~e¸¦0¦zSúŒ!Ú7´rÁ1õ' FlÉ–ÄÙÀšqù…–¢­M–I7aLeh7ô ùQ@S~ÊB9i©½‡1]zS xtî¥7!:Ll`l€G5ìQÂR·Ï»Bœ”Æ'9}”Üx†Ì åÿ˜,=ªœcLQ’I SKI]¬¨ „H&1LE-È‚äÛ%™Ä0¤ÐŠŸMaLÅ/C=R@ H)ÐyB$“ü0µ°<Œ)«ÝÕ³²6mk7®Ö.ûLBU  ®U†Ö6aL Fõ`¹ïȉ ÿêoö©XÝ»Qúþ¢_UaL-lôJu)aL©“Ó|…\­9qAàÿ¯QÏI¸RÄyd«Þí¾N–I7aL¥j@ô0]W@S׋@h=‡1 ¾ôÆÒß"4LiäRGÑíÈ€Ù<'9>“â<'œ$/J Ü›¥G•ŒÉ%™Ä0µ§©ÔU ©€‘Lb˜ Y~EË4I&1LE+·"çWS‘KOy—R@ H) º¨€‘Lb˜Z[ À˜’ì®´µž“ÝîšÉÄê8R¢eÕ‡TĩԟnÆtø±IVw”þð‰ þê¯÷Éduo®ôE)e3ª cjm»Wž« cJǘþzŸhûæ6hhßÐÊÕ4qqMYbd•ÚX·u›ñœeÒMSyZ=IÆ”‡RPÚ @ÏaLû|âÿùägLJûþÝ~ÿŸÿëÿN9 ÓWŸ>ã¥B(ð?ÿé³ÿûÿþŸÒ³ú_þë9æ©u[Þµ´iû{mø1ö÷’}K—í¿ÿþG{¢›Õèö–ïÿéÏîïÍt¾(ˆãGÄ èšß\šþ»Øö†~)Ñ|góÆÛ‹ú6ôþaéõmÇ›äû9”»‚( Œ© ¥lJ) ¤€9T€$Ó7>|Õ†×Szï0¡üþÃr˜ÿ|f S+í®2®¶Mÿðÿcº-æñ›n¿/ôÓH¯u÷ߺQý~Ò·Á&›åÃ_µíñ a²n_&ÿëûË¿ßïS®_ññ?*ý÷¯–0Ÿínër%Œ)cªÛ|ý§¿ø?þáŸ>ßÄõ^köÿëÓ$½ƒ¤s¬Êÿ¤[ë~cº’h§˜ک®®ÝEz cÚ¾}ûìÚð”Pºýž‘ÑÚSb²”xhä–OŒ íÈúa§ïyg{ºN S\ݺ ¬½ñÿyݤ‡R~b˜ºP.%½åš]÷_õÔ~ö¥Ù)õM SI ¿%Œ©ªëžR@ H) ¤@iX¾iäÓ«ÇŠajaö‚ÝuÄè ¿¹ëÄ¢›I›°…â—’^U>øàƒÕ}Ìø)峺£ôQ ]²”þÒÕ›…1µ°m,Æ¥„1¥–Ó‚ Ü&nâSÓòپͽý¤<´Qu›š1geÒ­?aå²ÇÆÔã ¼ß[S´Óý%è[)«@N1¦w¶ï9ý/þøÈÙ¨ç±Ù–¦ò¶äz²düiþÝsLjÍÄ0©ö´P`Lwõíµ~ל¤ú&†©…jëR{„1©H) ¤€R  Œ]½ÿ˜>SI’ E~˜ú¡npjù슓WÜyÍôÿÑ·¾¯|V÷‰­I?®º7Êí(w”>ê@nsؾŒÉS£õ¿xÇ cj¤ÌÞxç÷íû¹õçÊ¿ÿ·O"õç ]<7§“nT +º¦€0¦®I¯·WaLÕHa]|CëÖÅR §=ªÑg×ðH¦7·GI&1LímJuõÜ*°yùžëÚ³jòîßmgÄ0å¶Ü š±Wß™üÄÚƒví^[ßÄ0´Xó›maLù-åL H) ¤€È»›Þz+6¼ùx¶P,¹V•_±Ì}us»öÕ]·Ì> ˈ…?«{pùh´V”cB¹£ôQPÊW¾éO$Œ©Ñú_¼ã…15RfùʶÍåMýl/l±Êé¤[#CÇJ®) Œ©kÒëÆíU@“0&)аyìQù®˜ØOÝ3ú¬?~ôg—dÃÔÞvTW/ˆ!²D SAÊ­¨Ù Õ71LE-È<ç[SžKGy“R@ H) ò­\1cÂÆŸþüg—·ÃÔ¢+â4jJžéЉ©25Z1J†1ÑS:dÆÔhý/Þñ˜)³|bLðÃÄé¡‚:dÊã¤[#µBÇJn* Œ©›êëÞmT@SÃKÉFàzœ&ÈcŠ®˜˜À3½³ÝH&1LmlAué|(°{ç¶ ƒ ½ýÊÚPŽæ^6hkßlÛid‰¦|]±s1dÞô°ú&†©Ø%ÛÜ cÊmÑ(cR@ H) ¤@¾0WL$™Ö¿ñ°‘Lb˜Z[tMØÜr{йb"ÈÒƒ™­%Ø芉©2 cj´þïxaL”Y1&sÅT\‡Lyœtk¤VèX)ÐM„1uS}Ý» ô:Æ„WcúðxéÚ]«6¾Û!´2ÖrPÜ(ôôËbÞÆe—v]1U2á2 ™Ä05!§N)œ/=5bÁ̓c³ ¶ “ûÈ1L…+âf S]Œ Ùþ÷þ(†)‡ÅW’, c*IAê1¤€R@ HN+`®˜ˆ1xþcýé’L¿ÿð£Nç¦Ô÷+“ÝÕuÅT2‡L«_y{ñ‹o¤ÛB›˜]ÆX8ýšYl°-7ü6wA×SÉ2­Ýü΂Õ;ÓeÙ°õ½?üñO¥n«ôp{öcj¤¼»ûÃô_M–_VsÍQÒYæŠ)Ÿ™ž_ÿ&RÁ&Ý©:V tYaL].ݾ] ô:ÆÔ.]u])ÐI\WLŽC¦NfA÷’ÝR Ó#÷®„—çN˜:x Ò²{79ø ƒ—&î‡s&æpÏÎÕ}Ýʹî[\FR@ ôˆ˜z¤ {ï1…1õ^™ë‰K¦@Ô“2•¬ˆõ8õ Ë%|€%mí› J {à tË„st×ÄÃð-3ò©Þåõ½+D  öº|@¥Ù›fóP°M œpLß¶>&9dR5j½˜Z¯©®(¤€R@ ”\XWLrÈTòRï÷ãźbbµ‘C¦~«[€ D]1 ,@±)‹* Œ©QÅòs|¬+&ÎÉ!S~ŠI9‘mU@S[åÕÅ»§€0¦îi¯;Kþ+ðá{n9xÏ yéê/ìùù^{.úDð/ö`ø¡(»æQ –À*aÁ&7f¸%üK/Mø–„“qNeIÏ×b€+KrÑ%z`ÂN|‹mFšÃ_&O-΄.'„1©H) ¤€R AžÝ|Ökbz`ù_Þ»ì/ìßkðb:¼WxõíÉVOF­ø–ñ/~Áöìþp{¯ѓωòµ²¦/·Ñ«þÁö nô¤*zè2* Œ©¸¥ŠUîœB:ë/½dÿâ+}¤€è„1õB)÷ä3 cêÉb×C—R]›<Ä~⥥|8=”HR€Aâð­ùd†Šã_| oL<Çà/cÏáHûJ Kì LÂñ†.a˜xÒK†:ah§ k¼°†úHV* Œ©•jêZR@ H) ¤@Ï)aÔÊOôÜcëû§@ßÖK²¼û‡Mý»ŒÎ.¤[ßÒ_³ëþBæ^™–é c*G !À¤½¦€0¦^+ñžy^aL=SÔzÐÒ+ Œ©ôE¬ŒS˜ài ß`Ü\.LÂßÝ;·câ]1ZbŒ9R  àZ ÃÆÙéØÀ„4xÚ`D‘Ã~lc'ö4q"ê( ŒIUD H) ¤€ýP@S?ÄëÝS…1õnÙïÙ#Œ©—K¿üÏ.Œ©e,Œ©娧* Œ©QÅt|AÆT‚R6¥@]„1Õ•HH) ¤€(˜JS”z) ¤€R  cê†ê…¿§0¦Âa?@S?ÄÓ©¹W@Sî‹(S…1e’IIÒ) Œ©tEª¢˜T¤@YÆT–’ÔsH) ¤€¨¯€0¦úé) ¤€R@ $* ŒI•£ „15!ZiNÆTš¢ÔƒÄ( Œ©ÕBS9ÊQO!U@S£Šéø‚( Œ© ¥lJº cª+‘R@ H)P„1•¦(õ R@ H) ¤@7ÆÔ Õ OaL…/Â~<€0¦~ˆ§Ss¯€0¦ÜQ¦ cÊ$“’¥S@SéŠTD„1©&H²( Œ©,%©çh¥»ßÚƒ™þ···òšº–HP`÷‡ÛaÖüýGoI!)Ð „1uBeÝC H) ¤€(­˜J[´í|0aLíT7ïׯ”÷Rþú£€0¦þ¨—Ÿs…1å§,”)ÐI„1uRmÝ«ƒ cê Øº•h«˜Ú*¯.^P4Í_Ђ+f¶×ìºÿ®¾½`Ù,fö•ë¢) ö­h%¦üJ) ¤€¹R@S®Š£(™ÆT”’jG>…1µCU]3/ cÊKIô/˜ú§ŸÎ–EU@SQKNù®£€0&U)P„1•¥$õ­T@Óü­TSת£€0&U‘Ž* ö­£rëfR@ H) ¤@ÙÆT¶íÈócêˆÌ9½‰0¦œŒ²Õ„1µDÆ®_DS׋@]Q@SWd×MÛ¯€0¦ök¬;HÎ( Œ©3:ë.ÅR@ÓüÅ*¯‚çVSÁ °hÙWûV´S~¥€R@ H\) Œ)WÅQ”Ìc*JIµ#Ÿëßx˜1ðoÇÅuM)Ðe„1u¹ZtûË÷ß’I) zMaL½Vâ=ó¼Â˜z¦¨õ ¥W@Sé‹XØ„šæoB4Ò¬˜šUNç5¥€Ú·¦dÓIR@ H) ¤€ ˜TšP@S¢•æ”Ñ«þ`¦Ò<‘D TÆT‚ÚðÎö=@n9¸¢GR 1„15¦—Ž.Œ˜ STʨ¨£€0&U)U@ÓüªT@SÅÖ­öìQû¦Z ¤€R@ H~(0uýQ£V~¢Щ½¨€0¦^,õÊ3£ÅÿâzY={™ÆT‚ÒåôŠR) zMaL½Vâ=ó¼Â˜z¦¨õ ¥W¸ýõ©ŸZúrÖ6¦€¦ùÓKG÷KaLý’O'7ª€Ú·FÓñR@ H) ¤€p˜óòɘT#U`í®ûáÇk÷·7z¢Ž/+_»yí®Jð z)£ÀªÉÞÌÂæå§À pzE©½¦€0¦^+ñžy^aL=SÔzP) ¤@* iþ,ôî=²0¦îiß“wVûÖ“Å®‡–R@ H) Z¥€0¦V)©ëH) ¤€R@ H)Ð5„1uMzݸ½ cj¯¾ººh­»wn›0hÒÛ¯¬ ]ù¥§F,¸ypko§«IÂ+ iþÂa‘@S‘J«yUûV‚BÔ#H) ¤€ÝS@S÷´/Æ×îZ;aÍ„bäU¹lµØêKêzR  L<3 «F 冓¹È¢2QOÌ¡°P”*ÄzRé{)Ð3 cꙢîµÆÔk%®ç-¶)¬ÒÜËáÛb?žr/Z®€¦ù[.©.˜¬€0&ÕŽŽ* ö­£rëfR@ H) ¤@ÙÆT¶mõó ¸o@ß¶¾V_U×+€(waL('e±qRX%L+`r¡ñKêŒ.(†éÃÝïEo¬BìBaè–R ' cÊIA(­V@S«Õõ¤@Û@Oô‘û¡ŸŠ xcqd ºhŠîyî)È©m%£ çXMóç¸pÊ—5aLå+Ó\?‘Ú·\2'¤€R@ ä]aLy/¡®æoЄAûݺYl™7ÛCñ|°€Ð0|‹mQ/]-®VÞ^¸@°!¡¬Q Æ6ŠEŒ¯p'üeqó+$ÔVæ@×’íQ³˜>Àägð—SŒù?tÑÚ¯™…ö”FóWE‘Ýõ™½èŠ)©—Ý;„…‹âÃa6a¤PÍë®3¥@ÎÆ”óRöšU@S³Êé<)Ð 0ØØ¹Ú[ fè}¢cŠ=„à¯uOÑ‹ÅØckßlâùHØÀ’‹näZ÷”ÝS@ÓüÝÓ¾ï,Œ© ½›¬ö­›êëÞR@ H) ¤@áÆTø"lçl{oðÜÌ x&P,ïýá=À+柉ßbÁ&ÐË2dÈý*ŸþgíZ$(ßOŠO±žË ¥ V‰™G5àJ;ñ×JܧŒiE?ÀÿNŸŒéý@ìë“K³ì‚µýHc•lÁ30Æ’ã\fHº`Çhf¡íEÒø –ἤB$¯†P œ0²‰$Eóh\o! ¢€0¦‚”²Ù¨˜ULÇKn*À®'»¡H$ë1®À6»§ lŽ—ì[€~*(}¤@) iþ*ìî<êî·o}w6ÓÂ-çßշ׊7Ù|Ûlé®eU`÷[{Ь1ͼiƨãίîÙµ©¬Ï­ç’R@ H) ¤@ËÆÔrIËtAƒT\>‰è>³7Í&¹ÂÀsL 9d¹~Å:t(€2 hÏRDŒÉˆ%Û`Yó¡@/¡zÐ Ü5ÑSWCñ1ܳmÛ6ü[Vˆ •\S®~׆³`©³AKdb8éDtË„frU|Ì æƒ¸¦=©±…ˆI".hGirV sF+»¶Hè¼ÆFM.Ìó+£R  „15!šNiD€J¿[ö —¢ û…15¢¥ŽÍ À‡ìü1^ŠM¯.Ïp "¤€R@ H)à) ŒIõ E¸ÛÀ„€ªZ†ùgÂ6¾5~…H<>ã'„1õËÂs DÿLüGòß ¼Ø@îžÙ³½ŒáxB0ø‹m Î º¾eûy¯Áƒ#?ØÀìʼ¾rïèn‡.‹¼ñ^6£,y8ÌuÄeè ×uËD]F°Y¨ÁŒùw1&œQ^ذÂ1ÂsññMC^Ùö° ¬Ä­ °Ç ÑêkEôú–[Üwä½Pô¸¸•u´¾¹¼·CÙÆby¬B˜2ÖŠÎFV‰Þz0YÀeÏØ0ÿ=øì vâHÒ0šYèLÑd¿ Y´ôBÄÕPp(>zÛb4Naæ(û½t¤…Q@SaŠJmLaL饣¥@0VÉVN˜kPŒ.Ðeg”94—¡ì›ÕÅüëÖR  cê‚è=wËg7Ÿ‹1aÏi¡î€3|'LÑtÇQ¸¹n!¤€R@ HÒ( Œ©4EÙŽ¡›%\àZ° µ ºúdâÝA;MX`FYòàrôTD¤‰¬È#ZHÑiÓ{ï½Gd‡‘J!ùPÉHìáÁø‹cð/X"lã\|H5…®ïfW#=ÃÓ±a>¢ìØÆ‡Ã;F/KR‡÷-ÆdÍàq”ˆ¤š§Éâ¡tÑ„¢'¸†¿ 9âÂ)2²è±A‚Í ‹z’ "»†Ã¬hH± ¬ÄYjø—µg¹erÄñÑë[é³¢°p¢}DEë.ÅÌà‚±—µ13˜²49ÆX%w³ X29wú€ûñW3 )ìwá¤OR!â+À¥ì¤—øÿb' T«Ü³K­#¥@‘ÆT¤ÒR^P@SbéP)Ð]È*!ôÆ—K膮„HÜOÊGÒ,÷(¢\w‹Owº£{oÝ5Ö!“\1õV%èäÓ&9d’+¦N–‚î%¤€R@ _aLÅ/Ã6>À²)æ0øìÚbØ 6p’ñ.ód)ó´ä²M¤”ð—°¯l’°séu‰¤ˆ‹1qO4 [ôú–as… òv¼ ý*…ãÁ¸;Ý….ëâ5@^Š…1Ñ&ðItÄ…Ü/±J`5wÿmècä5méE‰EF/VÐ–Žšè+Z±“+´eÞ¢×·<[=‰^0Zß,È$¶£—ukqº†ÄÑÁíS€¬®Ož ó˜kà”6ð-¾â$þ2ÒœfÚWÍ]™³?é…ˆR¶"”µ;aÄRÖG H* Œ©„…ªGòƤz ¤€åU@SyË6WOuÈ$WL¹* ²e&êI®˜ÊVÆz) ¤€R í c‚SÕ¶ßF7q Ðÿ ¿èã¢'æ¢ p’‰^‘Ì÷öðDóäÔÆÄë[î\ŒÉ½ ë{ ó0sÃÃ̸.ëÒ0Ø.ÆÔ ëú(²ˆr.„m:å'DÐ-䋚71ÙõÝŠ„íXŒ)Tßp={±ÒF³íbL¬ T·R@ H)ÐÓ cêéâ/óÃk¸^æÒÕ³I) z]aL½^:ôü!‡LrÅÔ!Ý{ö6Q‡LrÅÔ³•A.¤€R@ 4«€0¦f•Óy-PÀŘp9PJtkd®•EŽ ïǯ,|÷0ê9eq $^-t}÷I’0&ܾÂé=ˆ.yŒ¾ ]ÖÉèi-¬D—p1&(I@Í-,F‘+F„ˆtQ´ \êˆ×ŒrH,,œ½¾)šâ)ZßpÑ%ÖÌèeC1…1•¨æêQ¤€R ¯ cÊkÉ(_ýT@S?ÔéR@ H)c„1å¸pJ–5×!“\1•¬póø8®C&¹bÊc )OR@ H) ¤@ÞÆ”÷*uþ‚Ø#2xœa(€NÈàÒBøËãIq'90L8—aÈx þ;‚¼6ð1÷ú–c•ìtRS8€ÐoÊgøXc/K¦Š¹ÆªË.Æ„¯PŽÔ™…ee’5ÙIªE ÂJ“á۬ȬPXj¬¡ë[®\ŒÉª%«A´¾±½â¢—u÷c*uK¦‡“R@ H|( Œ)å \´\aL-—T”]Ràý·ö<ñ›=€6ô‘RÀƤÊÐ)Ì!“\1uJòÞ¾ëI®˜z».è饀R@ HæÆÔœn=~Ö¶wg÷mûÍ>z«­:¸±ÞÚq£6]¿M—m‡Í]sÆÆã´f©9étV€a3 »6 «Êb’œ’H5D ô ˜z°Ð{ã‘…1õF9ë){A 3ð®šxi/<«žQ dU@SV¥t\  C&™5[ ¥.‘E:d’+¦,Zé) ¤€R@ DƤJÑ„}[/Å ïÝ?ljâ\RtF­üÄk*úS(ÿR ^gî÷, Z ]èúÁé!¥>R@ ôš˜z­Ä{æy…1õLQëAK¯€0¦Ò±° „15!šNiV8dºù_âo³ÐyR èIËìÑLÇJ) ¤€RÀƤÊЄ˜š­4§c*MQêAbÆT‚j!Œ©…¨GÍ) Œ©9ÝtVîè-Œé¦›nÚK)Рÿå¿þ·M›6åþ·¼gÏ;ÛÏú§½–ß~F²ª,JŽ) Œ©cRëF{ö¼õÖ[ÇŸôü•R  |ðÁÇÿ¯Åè¢t@ÝB H) ¤€ * Œ©AÁt¸§ÀS‹ÏûÊw÷zý5’£8þ¬ÿûò{?Ûƒ®GîÞšyïÉÿc¯·–<Ñ [Ögüൗ=3ÑØëÊú€z.) ƤÊQRz c:ùä“oºí®­»Þ§ïoñÒîo»ëØãNÂÆf¤×«éÕ×w{é5¤ÅI/ïøw7mÚþž¥ÛßÛ¸-H¶½ç§w7l}w½“Ömy·’ÞyiË;/mÒÚÍïxéÕwÖéí5¯¾ý"Ò+AZýÊÛ^zÙK/¼üV6½µÊI+7¾µrã›L+6éù oiýÏ9iùº7,-[·kÙKAZúÒ./­õR_vö­Ù¹¤’¯Ù¹øÅ -zqç¢_÷Òê×:iÁ ¯ûé5¤g‘Vé™U¯yi¥—æ¯Ü¤;žvÒ¼;æ=´i.ÓsÛç8iöòm–f-ß6kYf.Ûæ¥¥[‘fXêÛ:½š¶Œ˜¸à¯þzŸiK¶ MeZì¥)^ÚŒ4yÑæO~úÀÙ³gç¿@õ|ñÏð¥åË—ç?·Ê¡è˜:$´nã1Lh{ÍЃ:H$“*D»Ãôõozñe×£Ö‰dj·Úº¾R@ H)PJ„1•²XÛúPèx£ûNøQG…y[ïÕ­‹¿çbï¾víÚ¾¾¾ne¬ë÷½ôÒK|ÊY_ûæ¡“'Oîzfú™%®Ršøª—ËºŸòñôªEë«_‘E«ˆ%ˆ<ûf¢Ãd&*hñ)ÛR ¿ cꯂ:?§ ôÆP ”Rlºtã­w}︓ `r饀©–^ɘ* S"À´Õ&l´aÚ†)À˜<†©‚1ec˜Þ3L>ÆTa˜°Qe˜3ÕbLÃTƒ1 “‡1y Sc &cª2L+ë3L`LÃäbLôuZ_cŠe˜ „1aºìš¡ÑæömøÌçE2å´ÁU¶º €0¦.ˆÞ‹·ô->F?1íðÃæˆdêÅJÐÁg¦qêŽûE}{rö2¼÷E2uP~ÝJ H) ¤€(‰˜JRz Ÿa0iÎrt‡þntÉH¦mÛ¶1Zñ?QQ 4pàÀÁƒï·ß~…XíÙÚz†é”3ÎÇzà…«¶ô/ý%™bnm†S®> E‰P”±‡ 0Å6’˜¶ŽåV7ꀰh}N­ÝÎ[ÈLÔNuum)P„1¡””Ç&è=ŒéÖ»\7K!béc¢×¥ã%Ï S*½’)‹&xcrœ0½ã„)ꇩ℠ޘ2ùaê'ÃTqÅøaê'ôš~˜ZéŠÉŘsÅ´´ÆS}ŒiQ1¼1aºüÚ¡KÃ’mΑLM4†:¥¤ c*iÁæê±<‹Ï<úÄ\k‡GÉ”«"*Uf<ãÔ·»ãþ1Vßž˜%’©TE¬‡‘R@ H) :£€0¦Îè\Ž»€a oòÜçØ ‡ÉôÖr‘L@[ÈÖÄbLpÞ¢…E9aÂÛ.GáÖ} 0L§žqþó»ë‚•[ûI2‘"êú'c:t(&æ ÔZw‰«®KÔ E«¥,3Q Q ú«€0¦þ*¨ósª@ÏaL7Ür'%7Yœ¸ëo¹SðoZbü8×ñR€.ÅÆ‹†«ë)5\À0ùäV[ 9l¤Ç’kÔSó S+ÂÉ5êŠiùöTŒ©Ž+&’cP¹WLù*G† ~¶l:~³f-^/ŸL9mt•­+ Œ©Ã‚÷Þí‹Ï“s­†EíðCÏ–O¦Þ«mb§¾ñ­Ã†Ý?&Tß&ÎÉÔvñu) ¤€R d c*Y¶ïqÈ0M™ûÜóë=ãÛ2c ïÖ{š÷É:Œx |°Ì$Â6üeoA'ôbcÕî ã9í®óŸÛòÕo2iÒ¤&Í´…˜ŒÚF8,¥ Ý¯Há«BÜãV*ì!œD<äáB{¬"1vAîQMM<©Nɳµ­7eÑÊsa%å-j&¢¿@6S2±L•g)Ф˜šN§å]žÃ˜®»ùÎ;%÷_|{Ì÷Oä/Bœ¥mïm¬¤ Û€+1½Kn ¸’›Ü°qièR„^ Ln¹4LÀ´î—*˜ª“?½š0Uœ0a0Ä’[» ‹KÐãñÓNÎ--^³sñ‹AZôâë^Zí¥…Nj,–\£~˜žK÷ômæRÏÓ K!†©Ïc˜j0¦Å[¦.Þ2ÅK›½Ta˜ˆ1ó”[¦`àòðËö¦ën÷JܦÏKŠ×OEM_´îÓŸûÒ¢%KÊ-Œ¡eUI«¬0BîÌ¢ ¼9xFNh¬Éø±åDYŽ…{Ç£ÙB%n¸ƒù,´cg®{³¥l ®ƒû¥€0¦~ɧ“Ó ÅgìSóB6Mÿí¹/J¼‡›uà—¾ÒÉd†ãÎC´©¯»Ä­b¡í×Ì?>IÍ{Cšpy´‹[^j4NÝùÀX¼÷CKÙIC}{|úR¼÷ׯo’dBþ;S ´ÑãÅj3.ëQ¤”KR}NéK´»Ð[^‹tA) ¤€RÀU@“êC]* Óó)ƒ>LzD£$ˆ³aýaP&f†Úk¯½6…¸dØx&‹þ†‘#¶éN‰“Ñ'ØÏíƒcÈ»ØÄQO4¨ôð`ÊP˜ºÒ•à0L§y~Åî†<`w}zùæ¯|ãqãŸhôaMs·Ð©­•]¨ ‰£ñFt§äzÌ≡€€(;s×äÖlÂ~#ÕpM‚tø`C S£ÅZ¬ãÛgÑ2çp¡ IÛ ìVÓ ÍæÜoæB6yšnh]W C«i®™ÓC©ƒfÉ~š‰lf$ÿ‚§˜õB¿J{(Ò½î4“}åÎvY¥µæ±î„Qh‚©¡f!£•5ãa ݺ­kj¬­òV/.Œ©CBë6V ç0¦ko¾3N"¥tíMÆ„ ‡UªC,‘^ qK £Kµî—2ÒK«¢ôRƒ“OÙï ;aª˜‚NOÀ”î„éõ/¼†ô,Òª =L¾&¤ù+wiÅŽ§4oÅŽyÏ#mGšËôœ—æXꧦ ÃŒi8ƒÊ%3L±(·NÿR#÷«0Lo¥XR@•M_øÒ§?÷ņH&w}o+ûC£‘6iÂUhè#"cEg'™êÎÁ[žÍ^c{Ðé´El0-a»¹É]æOA»@öÌ·IÏž»¬0¦ž+ò=°Y|̦r‰›&°´ÃÛÙÉDûNkñGZ±c5Š6õI¿nVõ‰ÞêÛàͦ>É>›]¼nhé E£Õ9Ý2NE]0›C}7­ïSŸûb$ƒ4 ìÆ>rl}cô ¾aqåjy"¥ª'•ëCôÛ¤¾D» ½åµH”R@ H) B <»ù¬»úzË.ª:ÐÃôôóî Ïõ¿ë úüõœ7Þõp£$“‹1‘G1‰]ed5 ÆÄn0¶’‰6×X`ّ͋Ù&[#ÃØL™´Ù4Y¸š;²¡5¸œ»­™½ ¸º7:7«ºÀñô}ÖTÚûÂmYà¡,Ù^ŸÇ„žÑjЉÃÇwÛ^Ûæ¹ö aL¡+à")š„²áŠSÿj´vÓ8u×cclèWáÕúöÂkc§6C2qòõ\×­o¡Š‘^ßøÔ ÃDà‚KH+¼•Ž•µí±ë³|Y”ö[pK$TÕí^¼>k)».Vñ¬'ªc4ª²|C7mk¡7ZIt¼R@ H)Є}[/ÆÔ„n=rŠÃ0Ń,tt†‰ƒ¾†5F2¡3ɱ{Èø‹¹ˆÅìrY0&v¤í:貤‚ø–CB.W@?×dP9ëÍRÃcì+f,4{ÝÜ¿ÂÕa:Ëc˜ê.[ÂòÝÙK_ýò×óÉd%k›HÁ˜XO &ŽÄ ÌÑ=+[¬8˜_Yl¸Œ‰0œ;ÀÁ¹ýñ)R¸ï© ›E+“…¡q‹–kH‡°¬x48˜ÎhI¸ßZ0~åú·ÆWöspçÜŸIOœû°!3QR¤ŽÀ,Ù¸™Ê»+±íEbu´Ã&}\ 2Ï9³Ã`‡!ÛN’¡‰Wà·Ì›µx¬®!ÈÌY¡¹·RÙè/Ü•õ Õ4ìq5 ÕsžîN0Ùƒ„ÚR›£®,$­k ÉnfÕÐT®2½ÚC™Ô|‰G‹ʸE“dótí«Vš|R÷t÷ú®yÖ}Iõì·.Œ©âêÒÝT ç0¦kn¥”ÖNòù¤knvô±'F]+qÏK[Þ©¦Íï€U²T-Õ„Š{ÄSˆ[zñ•·k½.…Ñ¥Ré%]Š÷½”?ŽAŽÃî—‰¬rý˜úå„)[ 9—ašîÄ’›æ8aÀÄ4|‚ç)…aÊ¡7&aºÞa˜".Cµ§%šOyvmv’) cb?iÐ ‚®ú@<‘]:l`ù²=6f6ÀˆŽdqeןÅmc;…ÿX‡’¡»³¯Él®çb³ŠÎ™M퇚d7†:™Ëe|KZŸËž¢÷²«ñ”Pï¹›ÍÜ[St“ŸÇžš—fÓ¬Z´=g„h‡ï{tFC>™Ð¬Ñm‹_­y¡±2Ô ¢mÁñlޏÁØ´r Í5‡Át$ã~e­™™/Ùbóv\¨ä2.¼>ö[°´A„ÞvdñhI7#)oÍ’=¾â1Ñg´’g;ÏÖ†ÌØÛ„M7vR®¸²ü›a"t¤IJ6h}na} ŒSz SȆîv"Ú êÛ˜)KòÉÄBD¶-0AÝú­)õÍ>¡ZįP¨¿•NlyÙ«–u½‹ØŠaUÝnmÝ›b-uP¬¬',JÎôà_[Ýn7uªµ…ÞÂú£KI) ¤€) cRõHR }Óž~>´€fÕ¥îB‚còÏÃßüõÃFe÷ÉD´ÝH")Ì ¶Ù©æD£ŽqÝ YÏýU|È?áÃE€ØãÌÙaæ•y/žË›áÄ‹¸_á›FÅ‘=⩆aJˆèí.[BéÏê{¥!’‰CfÚ'Yè,…”‚渕emCiŽYl[v8†_Ù ½Õ»‹;Š1FŠµÂ½”Š2)МEëþF,Z®!æzƒ–\%m Mà Ù÷€qb_…<—©t2>KŒ™(ÃôPCf"Ú=ðâp'2’¬Ž´ïY»²Xš†íÂ.f<4CP’¡‰76pYN$рÛš!ˆÖ›2aC•ŠùqUiküØêÚ›Ô- Ø+›`²‰ÁÌtF_eœk3ÑøP4Ør#d¤BøÛÉbz =8N¡õ×gÑD¯oMy©)ß)QãÏÕÔXÆxó‡ cj^;™kzcºúÆ;jh$—LÚò¾=ú{'º|R"¨DK5n–ªÄR,´å–V».—°á–Baã¼é«DzéßK½”!~\ß/nnÝrô™l ¸ŒŸBÈE£È­¬EÎ$W"‡mǼ1ÍBªøaÊà„ik Ãä’{ÐØöž²x3}/EÓ'?}`~¼1Õ0L¡±t²%1û&Í_»ÿg3ùdâ#Ô-s»)ìŽpû[<غŒØfÒí²K„l;Ñí¥Y‡¦n§Ð½—Í,ZNxw\„'æ{ØÿCW,šUæ6¶µv{¥6ø7×ͦ³½—]GºÖŸ\¿Ê”9aLe*ÍŽ„JlÏ‘=ükÔ©e ¤)½B’&IÙH²²5]së§j]1ùS0ƒ‚úöèäÅxïgŒ.g¢ÓS·¾™aÂ*FJ}3’$ŠÖ™¤òbM ½R£%‚ Z². «±Õy^ÇìõÌ?íGn=g_"zS>TË ½éÚ¢¥€R@ HFÆÔ¨b=r| Ù!®ôÁìYô]wGV’ÉíçSXýùÌ[ûrå0L.ØÛiW¯l‘eKóW옱$ÓÁãÆ?Ѧ¼¹€–ßÂ]Ôò‹ë‚ùQ ŽE+ÎÙs-޲ùA‚xlíu DIȦ¤[H[æGÒÎç$l&J™ò'ïš6Ñ¡Š åBkdŠÕÑ,oÆÄ°|] Lh¾‰æ›ŽáœQº¡É®Àzåšzl®Š† ‰+‡À8ÞK+­~vãºY²Ë²pùD¬Ìf§â-\£¦µnõ&¥gUžâ,÷›W`%·{ET†1™z6¿2½º¿&Ì£[4Ñë»%E˪íq1&^Ü5 ™é8TôöŒško‹!Œ©½úêê]S ç0¦«n¼#ì9É ‡o1Ÿ¡”*Õ°JI¸R•X‚Ë¥—-9qâ|h)™[ŠÄŒËæxé9då&×÷’·jß’·|ßÒξµz©?ޱSãǵ`ªa˜–o¯‰"˜¶…£È-ݚ䄉ä¼ä3LpÂ`L SÞ‚Ê9 SÍXš«Áâ]2T,)Ò÷äÓ™H¦hÀöTÜž¥áAè©ØZ.wLÂéCûÊ:I˜Èò³·gýEëù¹#–P·Ïºè`Ùt¾uͼb“—–Oö5ùq!}>»VìÌYGÖZåP¯ÿº¦œÐÒ%\$t/^'”á®5ù=xcaL=Xèm{ä˜UkfÎŽ·i.ñ`Óœ·bÇÜç·ÿnt&ŸL&¸t’&ƒP#lªû¬nãÃѵÛ@Ù(—-Ûp×m÷زv?îÂ)^“ËÙº²ÁŒ¾/BcàÐ1ö€n–Œ¦²á.³äfƵ ðA(ÛsüåRþkžÿðúp öòŠ^Á^+¦OLÊ_­ª€iÆ©ôúæcsxï?2)+Édõ¦ÃïØú­Iõ óÝŠlM›©k‘¹ûæNÖ«¤òâ18˵rFK$Š1¹ÇXVùî}ùÊæïŽ= ;8tS«™-,ôVU]G H) ¤€È¢€0¦,*õÚ1Œ%Wã‡Ée˜âÒÿ® ú®½=É”sŒ‰¾1zmÆ1Ä0ùqšÞ¤±Ý\á&-[Âøkú¢—|­]$“YP[þ“ä@Þ\·üº`[´\ü¥ž…¡!‹VÈnç¬u¡ŠG÷3<2ºd(d&ʃªÎC¬™ˆ¨e³ÀÚ˜§ŒŽÒ™Èt8UDCeÈ"Gë E€å„vH.°ŒZ`\à±ÎwbÔÐäÞ®`; Ê¡aÇ Aô9Ç«¹u,Z©p–­ë³Ò$WŠ­ÉvLl=w'˜ìÈÐëÞ2ïîw­”Ì­R| ‡ŒTfà5Œ‰‹š^£yˆ-÷ú¡_ïeWŽÅ˜ÜÚ{}>‚;—×áN¯ÜNS¯”tÏ=gïaL7ÜaQÞ¢WÝpÇÀïpR(QájX%BKµÄR2´Tñ·”[ò†Oa¯KñèRÔñR8r¦1¾—¢ô¦ZßKŒZRã~é/h ý ù=¤jZ‘ÉSSR¹éN¹(ÀDLĘ’ü0å cò¦ë*±ä|¬þ·bÇÒ!Ö~ÞóÞô9¼[=1oMŸLèš®NÞˆÁP߈{ˆÛ£cŘð­uPlÛ¦ Ñ›D‹½±P¯×m‰q¢»Ì‚]F÷^œéŒÞèP?‰¾ ¢[/3úõJéź­Ö³öȼ/¨ ò]{» cêšôe»1,>0gucÉUÌÙ.KšbÓä îžG¦×.çnØ”¡©t‡|„A ¿]A†Òp 6×8ÀZ!kÉ9¼´ƒí:¡ÖÌÀ¸»-KB\bÃFÎÖî%¥í"ô‹1Åf‰·³7QôYÏÜVÝ |=áÃ76ìA\AÈê#í Iš¤d£Uõ>0N=P‰%ç[yï^-~jQ]ŸLæh™çk·n}‹VŒ”úæÊz«âß5eïôØòÂ¥`U±¯Ì¤ªü!ŒÉ5Ä >Ð0Š¿ôÉy)\™F.ÖUëKDoju¯U…®ëH) ¤€V@S‡ÏÿíÈ0MucÉE®ÀšºØ!vü¡dñ}Ë·_sûCÙ£Ëå_–É¡Ç0y> õ^0„Ô`Ãxê¢Mí#™z¤ ô˜íP lѪXˆ¿d¡ô²[´bñ[oƧ3"ãq›nÀ~‹~@Ó„Y½L“^æíúm&ÚÁBÌb&rÍ;´–cŠZ a¡×"Y¬&c ™c Mv‹Œ2i0\QŠ­T49†¬Ø²•qa›UÅtŒÉµ@í²ëbL–yºK©²›^í¦6¯-šèõ]5¨¹)µ—ºEF”Í~¶f|Ã45ÖŽ†=|MaLPY÷è‚=‡1]yýQ‰{À$ ¹Þتp’¿Óq§Tõ«*UX¥XKÅKÑ8qÞ0ÉMëƒY++nŠñº”]ªu¼äM¸:èRÕ÷R½Ô¼û%ûö<xN¼á=Ós† <0¹ÓŒ>× Ó–¤(rðÀD€‰Qä_ Œ ÓÞ˴±tˆµw\1Adã›0wÍ?æÀEK–¦´7\t…~ Wä4J˜øU¬‹#z-"÷chvà, {ÌÞ° ï‡òfÞ5Øæˆ;9Ôa.câSðúìfñôXŒ »^F’z¥ìµ»dGbÖ¿݈g±ïB«ßk·ÆÔk%Þžç5‹ šÞ‹ÛMó¥cñy1ðÛ¬Ê]¸b‚±Àk‡—m»ëáié$“5˜|‹e-*[QÖ²ñ06Ȥ? ñ`ë ˆ•µTtiÃAi¨5ã~A‰¢†LHlºÝûb½…°W^„ (ŸŽfæÍ "6Ô¶‡WæYöâ=#%ââ0f’¯ îw·M.^ŸYBþùFˆ½B’&Q©ív-©€4NÝi »…n}‹±¡W\UÖØõmù¶‡ž\„÷~Jt9CŠ]1íÕiåªoÑŠ‘Rß\YðÊæÛ™U—¯i·Î°\’Ê‹—r_µöq+¿û^æ)nþQ‚fƒ#®dõ¿«K¬E8׺4!³—kÆjIéë"R@ H) ¤@ÇÆÔ1© q#c˜Bƒ¾¤i~. ¹b²AßÕ·ÉTˆrg&†éÍ4†)Õî ‚ CþÉ 7}é vùd*¤Êj~ˆµhEVIí VåE,Z˜Íáêèì-×;‹é€6N®yŸËϸß,?<%JœÐÅN~„ídN:l&¢ÝÆLŽ”=Öêè–5ír±ìŒÅ˜lЦ•XCSCmžî´‘‹ÅbL|´¨Šæ 3BrRÉ = câ“Ù< ír|"×fvQ.û´_ ¶£F*Ͳ˜^í¦îÁ!ãXôúT‰Ù ÉŽzÒâÊ"¶Ò´"3[tèúÌåwò'Ó‹÷ÆÔ‹¥ÞÏ\c²Òl4 ­ cr½u•TÙƒo:æ„øüpÑHpßøöáD”˜žœµäª›îòG¼oÝ7jâƒ/a¶7 bÚðæ7¾uø3–`ƒS¡=iâŒ%þU&h‰1¹—9ÜR(`œ_¬&lz¢nòÐ¥ÇK‰‘ã0,?ç’«‘\÷K_ýÆ¡G}‚ë{ {ξè*×ýú¸n½tØÀšø 6’&tˆÏ¼`È?}êóAÚÿóÿ´ÿç=êxÌûÎdZºµ†^ª !WÏSÀ0™û¥þcL»v/o÷‚ S@¼9s™§Ü4ïÈ‹'#sÇ3W\ÆÕ`puñï]ä§ ïYèû ­l@½ñs^¬K2a>æ–É…¦ÍQêì~YgÎØ9Il*á+»¦ïöc×U`'ú:¡Q¯½šÝ_Ù)Øp[°hV±'öÖÑ¡—Ûíæ|¼› ´hÁÂШEË’GÍûVG÷»ƒt»B¬é>‹9<¦%f¢\9cäôuK+KÝ~vãÜ Ï¼Œé¼+F,³7ÿG§‡ÒÍDfA¹„fm\ÃK¨8Bÿº˜Xã Ùšù%dh Ù3™±èD’kGrmžföቱ•Š_ñ¾î\˜Ý ;£ÓâI¶ ›`ŠZ–B™wm§f˜µc\[nèR|ØŒ¦W{ðuÔŒc|ö¨…-jLf&M^ûMÅÚÐÜë‡r›ÃcI²$Œ©$Ù£a ãñ^pÛ+ÈQc""Í—J 0&º´IJøSÊ+}ײ•ôæÉ?ýÅß~â¿sœƒôäÌ%Ÿúì-W:ãœKŽ>ö$üEºwÔD×ÇÒ¾ŸøïŸeâpÖ¨ñ³Rœ-eá–jÑ¥_ÕE—N=ë¢ÇNOç--:åÌ‹~~æEÏ:‘ãöùÛ¿Gò‚Ç­ôÒÃO>³×^{ýìŒ g7D/™ï¥O~êów?¹­íŠÇ0];4X ä84F•ÀHã–ÇVŽ™»ñÑ9ÐIýÙ sYŽ_=s¼×O½Ç0¦ÊH£bI™Þ·uܬ՟¬ç“©­ÏUЋÓ?ª-,ÀSDWôÑJ›maL¥-Ú=->cžœm‡ÇÍÛtÐYãÇÎ݈v °’_Ý>í0¨_¶Ã´ø€â­aJ–m…Eí𰇦Ö.×χä~^¤%§³3‰Ìp5OÆkâHZ²B oÆÓsuØÖwgßÕ·ú é0¦¯ë°a÷Izï\æ{iôìõ¨o˜A‘ï}`L5õÍyïýŸLý—+?õ­ÿÏ¢+H) ¤€½ €0¦^(å,Ï0Lóžs:áÏ»~¸¥ƒÎ0Ls6`¬wã˜ô¡þ“ëçpÐwÏSkB üAß–!"™²@›Ž¹ð{.ßÏòÇÓ/†éTŸa²ÅÆ®ße˜^1þ2† ËHÀ0ýô†¹Ý;iM°ŒÄ&hÆûO>³á‹òÉÔ¦’Õe¡À3÷ï9ý/öŒ>+fJ±hafá±¹Ѹ¡’“aBõ¾rIJøá¨‡g®Ã¤Ú:aò1&—Òë˜E«ôåÜ3Ì’(AÑ`™=k=¦‡`&:ë¶ùœB‹ÐÖí|¤{›7uñ¤P9`âvsÓü w`Â|$§$ÛWQc/ÃT 2hiÆ0âXš# o5ØE“PˆÏ\ÂåÓQRDÊ‚Õ`΂ ZR ר™/|òÓu¢ËµïÑ ze œ!˜.ÒTЇ*y¶…1•¼€Ûûx´ø<úÄÜ ^ï’[÷&3g£F{ +"–ÂâãµÃ+kÛáŠMo4 ÐO]²åö‘SÚJ2¡½ ÑëíÕ+õêÀ@Ñ`6êC˜$>c›úCû”õba¦*Ãx^¬©o|ïÃï—…&»ŒuÀW _®oÎ{ß«o}^}{p¼÷ÛG2媾º¶(óR@ H) ¤@g Æô‡ÞêÌít—|*@†iÊÜçb}¾%6XŒûò\­ €µ÷,)ãµyì ‘LýhPtj!ÆTˆbÊe&añùìÃä·ÃÁ[žïqr%Æd«ÖhñÔÖûo´cB;¼hóí#ÚK2åRÚ^Ì”kŸŠ…™<†é›‡Ýqÿ˜¤úÆ÷>ŒS|ïcúdüü—ñÞ3‡„÷þN1m]¬ë¯à½ïÓÛm%™z±hõÌR@ H) ¤@a Æ”1òoaŸROS }“ç>—Ô § óÁè„ãï_ÀBÌÃjŠ1ÍãÛñ—M E\²„X] ƒäå7‹dêF=4Œ)fÃtÊç§Ø]Qú NH°Áî:áéõ"™ºQö=pOØ`¦º-X°:5F†+G.ƒE 5ö„+¦c‚§gXо!]óðsA8¹Šsq³0È¢ÕŸªÖ ™(~zfIÌÍ¡œúRÅ,¹¨%Z*o†èŒñgÜ:_f¢þ“Ε…Q@SaŠJ +€X™`àS úº>Ædœ°Æºè$“Ç…\3”î‘,¹N’ðíw¾{¼»'i{à÷NúÝCÉ*¹|)!q6à` dô—^ûµo†YOK8 Ð,!c«„„ Ɔ;ò˜“FŒ›ùµo†qSZ„8EŒgÓþŸ9£)¤ß^sÇI?>ýÁ±3-yý‹¯ÿæš;'rÖEHk!aÏß=ñþG§Qââ!¸_ºïÑi‡+½ÿql#a?ùéˆ.}ÑU Ç„¾È$ûûÐÏ6ðø[bÂ6"Ç!aã¸JKX“„\ Ð1¦áãç]3mù±?d:ä°ÝÏOU¼s þXஆœG-Ìä3Lç™Ù?X°TY³Ä!?ŠÞØfo0† ös„“›µtÌã—=¸´.Á†¢H¦îê܃÷ì§§ü±ócªwÅ3S‹7 z¨ážy™®±ì†GŸûòÐŒu¿{jÍmãVÁB诜ñø#³6X$2Y´Zehj‰™È3K®Ù †‰…H³$¦¢yδVìtÝœß<Ðvè{웉ÖolË»V•R 3 cêŒÎºK@8‹à1hРP4ú“›¥·NmÈyë/ Œé·× 9FrÿÅ·ß9úø”øÕøi‹Á!~ö%HþÆÅÆ'aÛý×@%l¯õ¦?áT ”’£x ôþ1n˜¤¾ ¥¿J/LÂNpE¿½ötJ°Ah‰Aâ;ýÄŸFhéÁ1œOK@—-a{¾ú/‡^;t¸-½gKØD 1êF‚›%ü‹á7® nÉÒ½£=Œ‰ÜÒ½LcÀ8KÀ˜0P¨tÉ•CÁ*ÁëR€1ýâ|J‰ cbW `˜îÆ´ÿçÑ:ô¨ã±7KHˆgôR<®ÏǘFLŽã§-øwÂܵ¤—†Ÿt ý-t¦± ÷K'Ÿz¼1ýãþŸûÇöH¦bL¿›ÿO±³Øy÷Ò FLÒMì?üg{¹õ>B­þp ͱôèÙë9wÎõ@ž;kYÅ£õ·>}þ] Œa ¹qY®ï³ïï?ü¨õ?9]Q t]aL]/‚bf Ôa0Š”ÖLÚ²¹×&:m†½ ˆéé¯ËüeL;ì…õäª\KgÿúÆÏü_îìûM¼2tJ 8ûÂýü—çYÿÓ}ï³£hïýKî]dï}NŸð½ÏuÀ‡_øÔð©/Õ¾÷½úæ¹`têÛ5Ã=àãÿù?ÿßbìž®‰_Û%Và¡SŠÙ6+×R@ H) Z©€0¦VªYÀktÐA÷ŒœXí„W–ºƒ>†éÁ@ÏÓó:\•œuÛüh@1Ló3œœqÉfˆ9î;ñ'¿:ç³ÿõO?ûê„w]Ù—‚-vü*}†¤Ý ŠÞÓdËH¼µ£!G5‚+Hÿê¯÷Þü¯ÿµë® ô„gýåÉßûŽ;±h z¨átá3yÑ«p3†Œiäôuæi «£yËÓçݹ€kÎ1A#‹VglPÍDf–hKÖ–fI›ºõ±•°e2øå?~ôç¾Ì•e) |„1©"”B &À-“û(u0&¸r2LÑ“ § f%sõm®W¤Ð6¾>’r€aItž„>  19ýW#aÌ3nê"øRâä‚ÄTâÄ'ÓAß<ì²kïà¤ÔÜe/!šüô*pKžk%Œ×x”Òð±3ŽÐÒõ· %ÉS°J§žuA%BKt¼äxZò÷œyâÄ´tÂɧž–üÙ¯ŸŸqÑ}£§1NÜôEÈ-ZõÄ3GnéW¾7&¿ÿêM’!Uz –€+Áy2q%DŽûþN¥'€›î‹tæC¾ÿÃSá…#:àJw>4 (Ò0ÿ/Ñ¥cpÊO?ßè¥ ·äaL·˜„Î1Ó÷N:èÒ—:ôÐ%œŽi`àx Óéç^ñÝL˜ŸCj!Æ4rÌS÷ÆÄºêÒK6‘D;¾Ø‹vLwÖ³—mC·þ~rýœÛ_…2B¡ “z׫Ãci‡µçXú€¿NÌÓ½w ÃøëÝyðžrJÔ³[ÏS]‹j8VGûæà‡iéO¯Ÿ[, ^´úéëàÂø §x¿à©;'®®iÜdÑjEhŽ–˜‰h–äôJÿ™Öu<œÂêJ€héÓC™hÁ*L‰dêñ®‘¿À c*páõzÖGŒ¸pTAåBqåê{c÷'N¸6úúú -'1&†ƒ‰M¿¹ê¶#Ž>>ô•ùLŠÝ€_%ƒ“°ÁXoœã“tä1'â_lе’Í}޲@Òw¾{"œ-q}GpKˆ<-áïAÿr(þâ†Ã¿ØŸ„ ðI€–p:âÄax¦YK62$ÜGŸ\ {f.Þˆ¿Jø _MœµÜ’yZŸ„íÛî÷ë+‡‚[¿‡}†d‡}‚-î¯|ý8[·¤ç|ŒÉ‡ rKæu T¸%ü‹á{aãàr aã|ziò°‘“±ñèÔå ”@/aÞÄ€qæxišöû‚ÇÑU)Ò½ÍÞ놽„Èq؆Ë% Kð½4nÎŒ ±têyØøÝ˜¹­Å˜ÐCŠÂLs^n×<ªë¥WÝV©uÕÊcfÆ”aÂܹ7ØX± f1/¸kÆ?¾vvM£`,]uâ2L|@‘L…nâ”ù„1©Z4«I¦Qãç…l/q¶ÃX”ù?å¶Ã0àín‡Cë2k™2LKWof#¼eçûú³?5[f9>ThÅúïþa“eqå@2Ýú»Ñéï}/¨\å½Wÿcs7žyÛü#.| ï}Ì\=j¹oœÚVµ0Æ2L¾qŠI&ªך¶eíÂOcj›¸º°R@ IaLE*­öä•$ÓÄY˃>M)C‰!¡ŠÅs†ºò5‡Ù LtÂayƒtôز¶ÆOm'Üc˜>|Õ†×Ùßö†}í)ÎÐUÑéu½«V&; $ÓÏ~q^Êø‹šjÆ_ó6ò@¹_p·WîN]ëzᢣ×.#ÊÝ;rœ¿ÞÝýaG^7)»ÏÜ_S½+áäì±k-ZOqÑÃ"y z ”i€&,ZÆ4í%0Lhèоará_¯daE«?õ¬%f"£lñ†ÂêJX)š¾îÉg_Añ!L¦€²•™¨?E¥s¥@!ÆTˆbR&ãضmbÁ` ¹bÂáõ1&z 0.Tt…+\HàÉÅÊ ÔÈá3Þ(ˆñIô¢4¾–½ÌE$“~{Í“æ­â¿‹‚äÅ€Cöàãð·4fÒt"äÑI 8BžÝ·‰ØóÀ£ÓG?µ€Qá ]Ì™>´Vé‘'ŸÅý-ÑÓ÷ÐÕ-½Ý"H-!ÁÙ’EˆûÝ#Ó¦-ÜgK=ñÌU·<øÐÄgèr ÐÒÝOEÂÆ”gד[bº{ÔTocù¶ãç3`ܤgÖ!Ñëü-Ýx÷XN¤ùi+Ð¥Ç=ýÄÓ/ÑåÒãžÆßÑS–#fÜýãžÆà‰.Y¢Ë%†óF€~º÷KŒr냓È*aÃÅ•ðoF?L< °9üú¦OŸüôðÆdNlÌßp稕Ÿà|dû0&üÜXcmŒaëÆãO¿ 7¡^š±î©¯˜³Ð‰Ï¼|ÍÃÏa,M†Éuúꎥ£ “H¦¢7qÊŒ˜T-ú¡í>=>;¶Æùa6Â~;ìÆ’«¶Ã.SaIC‘Lý(«¼ŸêÚ§B“e= ™îTßz“Õ70sæéýÑÙñÞ=kCˆ]¦³w 'ç.°s{5"™ò^{Zž?aL-—T”R@ Hb* Œ©˜åÖâ\$ÓÌe5ü¾#|ó¼‹N¸MlÄ´uÓ—l™±½ôì “H¦—_Êå cŠLvH¦ŸþâÜ èÿ[ï&¯« Á0þ@?L罄ñ×øù›jã4m ¦Š£š(ÃÄÒÉÔ¹:Pâ;Ƙì¡ëZ´0»clܸ*ÓCcæläjøU£–ß?emÀ0É¢ÕêêÔ3Ì’n¼Kx d@@âÝO¾è…épÜÅEQK™‰Z]ªºžèž˜º§½îÜfûŸè¥2aL-ÉA.(äß®º¼Ql·À˜ˆeL!2‰|R|8ɇ@ñ©‚(«„~¤%oÅ¿è'”Ðˬ†‡óq%$°JæiÉ %#–ÜJ¸ N¹%ó·„¾ŽË-“O,¹‰Ü’› ]bÀ¸ T\eÃq¹äù^Š¢Kt¼ä¢K·´xóy¿½¾—ài‰È1¦,þ–ÒicÚ´ý=Ôç5»îÌÔVŒ wñ*í•·Y²´”©e¯tRéñµ–a ¥“&‘Lyh©”‡V* Œ©•jöâµh÷ñø,FtuaÏ«¼·w•Ç  “z•oÏJl¯À/NÔXË0‰d*k%£}* `²§&ÉtËÝ£Ý÷>;‡Vßê¾÷ý¾VepņždœŠúdÚ¹ºïÃÝ^?'ôÁþ²–NÏ=—0¦ž+r=°R@ Ä+ ŒI5ƒ d?cidÐØcCƒ>ØNi& úhät„ü0¹k à“é½×·Æö±Ñí«¼SÞd€É.å‘L§Ÿ›ÅîJ†‰¥OÛx8’ ã…+‰aÊB2¡V¼ýÊZÈ+î^;S2ÀdbТ5òñÙÍX´bñ—Š…A­þ׸™‰úÿ°º‚mW@SÛ%Ö º£@ÏaL¿¾òÖÒÈ¥Ž^|ßcJâ²2I!V)Qò¢ÕÆ€J ¬’Å[ªàJœ4¾hÃÙ]e¸üñÀ¯Ò¯.º*Ä-yÄ’7ÖªK™ ¥Ê¨¬!n)Œ.UCÅ1fÜ–tt©âxÉC—èx‰|,vîÆ$!ŠœûoÓ·”är);~Ôª#Û„1 Ä óÖýà6£o[þ¸oþb'ý3á/¶±1âùø Ûø[÷÷’éâ+n±j;6wÖIs™Yü0‰aª[: H c*Riå:¯´û<0ff€×LfЬkÎÎÂ0-X½L‰+Þx­àeÁ7ß,xÅðm‚6ð/7øZÁ)¹T™KU€&ªî|8ã{¿fúÄa—³3Lô·DoLä™°_zÊ«H؉ ¬ç~FMØiGªH £€0¦Â•2*¤€íU@S{õ-àÕI2Ú;è3?%u}u¦™£¹ûûûÉ×ÐÆjö¨‘ »ÜØ@ÛzÚôØÄc¬‹^@seL?>mpdüU ?'m ÉÆè'ÃÄ¡k‚7דpDݯY®kUn2X´ÆÎ¬‰íPYÝ‹¬[¶|èâ¡\¶'‹VJ•iÖLÔäR71L¹ùù*#R ›˜²é¤£ §@ÏaLõ~TÙƒo=긔¢ÁÝè6©Žó¤«äÏ}¦§Z¿Jɬ’ã])W Âu»á’ˆ%o)I¶‚ƒaÂÄXMÊ-1„Yo´Tá–ª.—ZÅ!õó:m˜¬ó.8æ’ßûÃ{h¬kŽ©e„œÛöÞ6£—pN©Û|€dºèò[ `òœ0ùQäj‚²/³¥`ÍÄ’ÃT·t@ÁÆT°Ëuvi÷¹ïÑ®'¼ ¦AÓG $õâ¨âmè8mnŽa¢(öÁ%×?_(À›ø6Á{' ›k¹{>s4Q]?lTúV}ï‡ë[v†‰b›eœ$ö˜&L–€sZvïÚзöÍÆ16Å‚=ø ëƒ{¾Ð "€0¦‚”²)¤€íV@S».âõI2™²$¥îÙN}c)ü0M‹ úê2L°¼mÙù>&t§Ñ¯6§§èr£û=¤Xð/W § TÝoö·?ÜýžÂ=·©jy$Ó©ƒ+v×°ó{[;J;¹Wú¾õÛ‹0Ð † Å‚¶BçcÒ?Gd6@C5@=ш¬M5¡”—Í›E +ñÌl[ÖìM³eѪ[ñ¢f¢êôo–Œ§l_ê&†©nYè);„1å®H”¡Ö(ÐsÓEWܦÍ'ðí¡G~?倘¯êI!\)à“<ÚÝÒvt8Ü4xŠ›*aàâA%‚,•žJƒ¸¸¥*±” Z †èª¹)[Úl¡âúɵéô6aLX:€Î7~£èŽs+ Ü®9I&ÆIhlg ’éÂËnöªG À™;W,¹Ö´“ºJ‘ÆTäÒËaÞi÷¹÷ÑuÛá¨9»? “½D\Cy`2.„_+„hs( ²Ô4Q]wǨ&ê[£ “YƱùL–p©7Íè4ÓcöcrÿbÆÛ8’xþ6ôt:¸k cêšôº±R@ äKaLù*Üä†$Ó£“W;á5ÓÃÃä›FÝ…+¦ßø‘Åc_šnx@¥Øò-t•JWLØfÇISû* H¦=å x>¼pÔ_ý[Fз»¶Šaâ‹°× ôY1lD† ×#—Fdí« ¥¼r®,Z¶RÃ~»–,ZYj]ÌDb˜²„Ž‘¹S@SîŠDj½‡1UœÙÄ:C‚«›CŽü~VWIŒìVßdRKâž0œÄ=¢”F)¥‚JˆH<8Ç»R=\)>6\Lx8¢Ku-q—ÿÔ&Œ‰oüF]ç¨`•ø«ÅNNHf„46è±)Ë$Ó—Ý\õÀDçþ@:i)˜bÉeVÇ”SaLå,×n>í>¿=Ãâàm[i„mQf«ü0áiñšÀº4l¸†×É‘&FšCA;a·rWŸ¢+@Õµ·r=/†ßû‘é“&&Eû8£WÐÍè¶äÆtìä„ ‘&lã[$l`ApÑÕî•ü cê•’ÖsJ) ¤@„1©Š$)@’é‘I‹ëúh¢ºzèȘ÷¾_ß (oŽaB6±Ì—ñ ðÁz_F‹ƒMôæTEŽ‘æød˜$:jÒ§ c*F9)—R@ H)ÐvVì¸é®¾½Þýæ¶ßI7(¦$™zb¡3è‹Y=Ø(Ã1ÐÁ6G§ìNù)ãÇ‘Jq{Úô½D¯“jÝ&Kª'ùŽ”’})ÑõÎoüÌñ«”Â*ù˜K°jÄ[»oiQǽ 4RÓÙ.4Æ„¶$ÓàKo¤÷,׃¦|7¼Ê]ÆÔA±{ðV´û {hªµÃîûH SV‰¶>2MTCn[ßÄ0µUüR]\S©ŠS#¤€Í+ Œ©yízéL’L#&.¹ááЯ¡Xr½$[IžÕ#™~zv¬ÝU SIʸ‡C­~KÌDb˜JPôR`0&U‚’*Ћ“‹…¶1}ûˆcSHó”ê6©–äFKã“,p˜7‚rS%œ*ù\‹X¥TB«èI¦sþíF‹&C3ŠbÉ•´ÅÖc5®€0¦Æ5Ó )@»Ïí#§„Úa1L ɨƒ3*@Õ·ŒÕ71LÔaž˜T¤€R@ ø cREȨI¦',­¢ÔQÀB’餟þ v·ôÅ0ºL•yS@­T†~š‰Ä0• è¤€§€0&Õƒ’*Ðs‚pÑ×Q(ù.޶âÛoq,·[‘ŸI n“B¾”ÂpRmÜ·ZD)B)XêU§J=ë‰íH¦³}£‰ †©¤Íµ«)„15%›NjHÀî3bеÃb˜P7¤MT˜2±ú&†©!u°0&Õ) ¤€T@“jBvH2¡ãmp1LÙÕ+ú‘ ™Nüɯ¬èÅ0½@•WY´JPš6‰a*Aéë¤@ €0&U…’*Ðs"p±Øâ"²áÛo~ll˜¶†vÆÓHæ<Éñœ2‰©ë-.â›Ï' QjšUJ9±Þ˜Ø4É$†©¤mµ«Y„15«œÎkH×î#†©!étp ¸&*1LMØë§ÈS¯×=¿R@  cRUhH—dÃÔt%8ØH&1L%(M=BHY´JP%š0‰a*A¹ë¤@UaLª %U ç0¦s.½1…1·À˜ªÄñF¹µ’Ë$Õ†u« ñ&2©dRC×, Æ„ $ÓÏué~yâÔùë¶¼›’ÔI-i{®ÇŠS@“êE§ðì>_ßx|áKKWoNi„¬Þ¹û÷u*_ºO9 ‰êç_ùùœ³`Uú{_õ­œ• é§ÆÔ´t:Q H) Ê¥€0¦r•g'ž†$:áß<øðU^Oé„oÙùþï?Ô ¯…Ò±{€d:öG§øÕoß;r\úøkÇ›t,Wº‘h‰$™<‹Ö_–E«%’vþ" ™‰4=ÔùÒ¥@{ÆÔ^}uõ®)Ð[Ó¥—^º—>R AþÓú‹©súÜê¦íïuí'›zãŸýð1Lù,åªk cêšô½xã7fÞ{ì?ü—¥ÓžÃÔ‹ÅßñgÞ´sÎü/#§Ý,†©ãÚü†Â˜ ^€Ê¾R@ ´JaL­R²§®’験ŽÃÔS…nûëß\.†©7‹¾ž$Ó±Çý@ S¡Ëzç;›²˜‰Ä0º”•y)¯€0&ÕŒ’*Ð[S´Ó'~ô­ˆU ·ÓžË÷ß1‚ü0•´¹Öc5¥€0¦¦dÓIM*ðÌýúùܲdNR;,?LM «ÓâØúîì;—ü‡ùF¤¼÷å‡Iu'FaLªR@ H) |ˆ1¡O%=¤@vví^þàò½_yí­¤N¸ü0e³ˆG¾ñÎïSÆ_òÃTÄ2UžM?ýùÏhÁdÑ*n•x÷›êš‰Ä0·|•s)¦€0&Õ’* Œ)-ö– )P$Œiùã{ð®Éôæ±ÙV'µ¤Í¸+UaLª Tàíí{ÖÎþÓ¿¿k÷ÃÔÉ¢è…{aÊ o«wÞ¿íx;£¦^¨Í<£0¦fTÓ9R@ H)PB„1•°PÛÿHS×…Nøòm·ÄúÄ0µ¿º‡$’I S÷ËF9è·I$“,Zý–¶Æ”n&ÒôP'ŠA÷]Q@SWd×MÛ¯€0&aLR arêéòý=Œ iùãQ’IÔö7§ºC.Æ”Ëb)z¦VºìÞ!ѧØÚ7ûíWÖbÔî#‹OÑ =‡ù‡}ªoÛov½¿õ-J2‰aÊa‘å%K˜òRʇR@ tYaL].€Þ®˜0CŒ4âùýþÃ÷C$“¦i“YŽ’Lb˜š”R§åOY´òW&Ysô‡ÞJ1iz(«Ž:N QaLE,5å9ƒ˜FXä H äc¢+&&ðL{ö¸$“:©CRR„1•´`»øX˜æ^6襧FDó0aЀ«û¸ßµûˆaêby•æÖïýá½”g ‘Lb˜JSîmyaLm‘U•R@ Hâ) Œ©xeÖíÓÓŠ7ýñ£j&1LÝ.œNßß%™Ä0uZ}Ý¯Í È¢Õf;qù™HÓC]÷]T@SÅ×­Û©€0&aLR aòˆ1™+¦ŠC&´$™ÔImgªkç^aL¹/¢beΖÀ*Ãhɸ%<È#÷ããp?í>Ï®zLIèÈb=µrÛu&¬™0h ôl˜‰J S×Ë+ïÆ”÷Rþ¤€R C cêÐe¹¹b2‡Lýé’Lb˜ÊRÈ=I&1L©¦£ ¢€kÑ*H–{.›î°í½m)mf"Mõ\åÐ÷ ˜z°Ð{ã‘{cÂ+CŽ”´uçîo~Œ¾-“¯½ùÁö7v§?Qîz~®+&Ç!ºªšËì–\O™¬€0&ÕŽ–*€pr`•àéÃÝïgZpó`lcc÷Îm$œp·©ƒb?ŽD;¼c=”ôá„-ÍŽ.Ö ÀÓàiƒ‡Ìóâ®ÝåE-ìÛæ9ýâ6>f·B}{öå>~«HT@“*‡R@ H_aLª )àºb2‡L¸H¦ßøQC—ÒÁ¥Qàß?øcižE"B ÀÂðþïÕ¸å´^Àò³ß­ûÑ.„¿° ᯙ‰Ìd„B|~Ûœ<åô!•-) ²+ Œ)»V:²P ô:ÆT¨ÂRf¥@‚!WLŽC&I&z]aL½^ZüüÆ*aãå¹xuÆ’ƒ‹&€Jøô]4yíªikßl;²ÅÒåz@Ù›fÃ8’ <Û |d <3a§ùgÂNؤ`®Âh'ìÇÁ= Œ±Y„15«œÎ“R@ H’) Œ©dÚÖÇ ¹br2µõ¾º¸R@ H¨0ûÀ4tñPX‡`&B‚9Èü3ÁF„mœ’û•Ä”R œ c*g¹ê©öcR%W êŠÉqÈTðgSö¥@¿ÆÔo uWc•*Obb,9xZb°9àM›°¨¼4áÛБ’T 4ª0&ž‚ :[‚ æ*Û‰ TDX¯¸‡æ*}¤@¼˜T3¤€R@ ø cREÈ®@Ô“ë)ûut¤R@ Hþ+£vƒg²Enf;‚½ß’pâ½F8Ò8IN)][E‡ ³@Ñ.B'LpsWày`]{Ê~ÙC cê¡ÂÖ£J) ¤@š˜T?2*ëŠI™2ª§Ã¤€R å ˜QŒ%g¶#lsð&ºôF¢÷î–gC”R / cÊKI(-V@Þ˜Z,¨.':ªÀ‡ì¥Á´äá=xWÝÿ£êží/v43º™È¡˜rX(EÎÉ$<@0IôÉDP‰>™W û1á+ìÁ·ØF\9lc*ráw-ïXEÇ q¶ØÛ*1Ša&fHÓ„5AÄîeZ7γ˜ò\:Ê›R@ tPaL»Ø·z÷›¶¾;›iö¦`Z÷æÃ¶ç½UìÇSR h ¸N»™÷ɦ!ÐKf2ÞE{PåW Hl cʦ“Ž*œ˜ WdʰHP`×&cšx©’R ª€0&Õ†–*°ìÞ`é`&lƒO2LØæ­°Á¯ø/œ0á_$L-Í‹.Ö+ ÀEŒ (z`‡Ñåà;ñ{€1Á,…õvØÆÔ+•£¹çÆÔœn:K H) J§€0¦Òi'¨oë¥À˜6uâfº‡R@ H8hr—´Ñv„Øà:7‹è´ÉöHK) J«€0¦Òm¯?˜0¦^¯zþò( Œ©‹F¹’mW@SÛ%Ö º£€0¦îè®»JÖ+ Œ©õšêŠÅW@Sñ˰HO Œ©H¥Uø¼n}wö]}{aú­ðO¢è°˜:,¸n'¤€yU`Ó[£7…>U^3¨|åQaLy,åI H) öìy÷›d&RE=ª€0¦-øò?¶0¦ò—±ž°WÆÔ+%­çlDaL¨¥cû«€0¦þ*¨óP@SbéPWaLªR@ H) |Ø›ƤêИ’KK) ¤@ÇÆÔ1©u#);„1å®H”¡Ö( Œ©5:ê*R û cê~(ùS@SþʤÌ9ÆTæÒÍݳ cÊ]‘%C˜ŠRRʧR@ ´YaLm¸œ—ÆTÎrÕSI) Н€0¦â—¡ž@ 4«€0¦f•Óy9W@SÎ HÙ“™Æ”Y*ØC cê¡ÂÎÁ£ cÊA!ôN„1õNY·øI…1µXP]N H) Šª€0¦¢–\Wó-Œ©«òëæR@ H)¨€0&U)л cêݲ/ù“ c*yëñzHaL=TØzÔÌ cÊ,•l˜Z ¢.‘UaLY•Òq!„1©JH) ¤€ðƤŠÐ„˜šM§H) ¤@ÆÔ‘u )S„1å´`”­þ* Œ©¿ ê|)>ü`ˆ ÀLúH)` cRe褘:©vÏßKSÏWfÆÔ¬r:O H) J¦€0¦’hgGSgtÖ]¤€R Q„15ª˜Ž—åQ@SyÊROR£€0&U)P0^zjIJ{‡|¸û½P¾wïÜöòÜ {eW ´[aLíVX×wƤúÐA„1uPìrÝJS¹ÊSO#¤€M+ÀÞÔ«oOnú :±ÆÔƒ…®G–R@ BaL…(&eR ´EaLm‘Uí¾˜º_ÊÈ®ÀÎÕ} É=lRöKéH)Ð cê‰bÎÍC cÊMQôBF„1õB)·å…1µEV]T H) Ч€zSÅ+³äXS AYR@ H„1©ZHÞU@Sï–}ÉŸ\SÉ XW&àiÁ̓‘èŠéíWÖ‚j‚&>#ð&üÝ=ØÏ¯ô‘=§€0¦ž+ò®>°0¦®Êßk7×Ä[¯•xËžWSˤԅ¤€R Ø ¨7UìòëRî…1uIxÝV H) ê( ŒIUD ô®˜z·ìKþä˜J^Àz¼2)°µoö#÷Æ„¹— B‚û%ÐKŒ%‡¯ð{¸ÿâ0ìÁ„Ÿ°Q&5ô,R “˜2ɤƒZ¤€0¦ ©ËdQ@oYTÒ11 cRµR@ H)à+ Þ”*B cjB4"¤€P@SDÖ-¤@NƔӂQ¶ú«€0¦þ*¨ó¥@' «oL«Få}K>™H)á/¿ÄäFšÞ$ŸL,,Ý+ cÊE1ôL&„1õLQçáA5ñ–‡R(d„1²Ø”i) ¤€h½êMµ^Ó¸¢0¦(d=¢R  c*d±)ÓR % cj‰ŒºHþÆ”¿2Qޤ@‚Æ*áû©ƒ2Ñëý3a?"Ía§ë¢ Û<Ò¢ÎI`)ÐC cê¡ÂÎÁ£ cÊA!”; »?ÜþÄÚƒ˜Æ®Þÿ®¾½F¯úÛóêÛ“Ëýøzºæ¸ç¸=7¤ÓÿbϹ«þ;ú¬æ/«3¥€R@ YaLE.½®å]Sפץ€R UaLª R wÆÔ»e_ò'ÆTòÖã•Ic•À$™7&ÀIÀ›àu {È3á‘~ø ×MÁN)“&z)PGaLª"T@S'ÕîÕ{M]è¥hñüÇ>úÓ½ªŠž»ž3nÚ‹FlZþx½“õ½R@ Hr* Œ©œåÚæ§ÆÔfuy) ¤€hRaLM §Ó¤@ ÆT‚BÔ#Ä) ŒIõB F²JÈ.1&Dˆ[pó`âJô´ôÒS#¸ñòÜ ÜMŒ%‡¿8¸0ªŒJV) Œ©UJê:YÆ”E%Ó?ví^‹1­ØqSÿ.¬³K­À‡ìü±ŒéòýKýØz8) ¤€i cRýhBaLMˆ¦S¤€R  cê€Èº…È©˜rZ0ÊVÆÔ_u¾è˜ ”̵&$úaBøc_q€'ìÁþŽåS7’9R@SŽ £²"Œ© 9uÈ$WLy(—¼ç!Ö!“\1彨”?) ¤€h£˜Ú(ny/-Œ©¼e«'“R@ [aLÅ.?å^ ôGaLýQOçæXaL9.eM H) ú©€0¦~ ¨ÓR@SCréàfˆ:d’+¦fµì¥ó¢™äŠ©—Ê_Ï*¤€Q„1©V4¡€0¦&DÓ)R@ H)Є1u@dÝB äTaL9-e«¿ cꯂ:_ H) ò«€0¦ü–Ms&Œ©Œ¥šÏgr2ÉS>Ë(¹ 9d’+¦<’ò$¤€S@Sç´.Ñ„1•¨0õ(R@ HR) Œ©TÅ©‡‘ ) Œ©!¹tpqÆTœ²RN¥€R Q„15ª˜Žï˜ú£žÎmD×!“\15¢\oë:d’+¦Þ® zz) ¤€€˜T šP@S¢é) ¤€è€˜: ²n!rª€0¦œŒ²Õ_„1õWA/ò¢À®M{ð®šxi^ò£|H<( Œ)¥Ð;yÆÔ;eƒ'¥C&¹bÊAQ* æI®˜ UnʬR@ ´CaLíPµôׯTú"ÖJ)  ª€0¦‚œ²-Z €0¦ˆ¨KäQaLy,åI 4£€0¦fTÓ9eW@SÙK8_Ï'Œ)_åQòÜÐ!“\1•¼˜[þxtÈ$WL-V”R@ H* Œ©€…Öý, cê~(R@ H)§€0&Õ )л cêݲ/ù“÷ÆôÖ[oÍ®÷yâ‰'ê¢ïK¥@–ÿàƒ ÐìÚ´ý$yc*@A)‹U@SGåîù› cêù*Ða&ôýð£?¡‹Òa]t»TÞå‹•HR@ tWûï¿ÿÒÔÏ™gž™~€¾m«_|ñ9眓~‹Ç¼»µHw￘ú¯a^ASºY H)P„1¢˜”I)Є1µEV]´û ôÆtÊ)§ü?ûý¿_üÒWÜtà—¾bi¿ÿ÷ÿ÷Wûë¿ôåÄôÅ/øÅ/¡ÁtÀ¿¤¿|@bpÀAúüâÓ|>.}î 2¥|­¦/}ö€úé3|ÉKŸÏš>ýù/ŤÏ}éÓAúâ§?WMŸúÜ3¥Ï~ñS~Ú¿‘ôÏŸý¢ŸüçϤ¥ÿôÿÇ?~ò³8擱éÓþÕ_ï}ÕUWuÿÇZ/Ë—,ú»ÿ¾ß¥?ÿ~½õ½è%„1õRiwÿY…1u¿ z(“'Oþ›ï‹‰ðzf=j¿À¢ôÿ:ê¨b0úý~^]@ äSM›6ý·ÿóÿ<缋™ÎvÓ¹Ÿ}îEH8`ÐÏNÿÕ¹UÓà‹~5ø¢³"éÌÁžyNM:㜠ƒtö…gTÒ/Ͼ°’.øå¯¼ô‹¸túYÔ¦óO;ËOgVÓ©gž_MgœêçŸRMçrF~þËóBég¿<ÏK¿°tîOá¤ÓÏýééçþ$. :í\? ¶ôãÓ{éÔjú×SWÓ)ƒÿõ”sNަŸŸó£HúáÏÏùáÏÏþáϪé?;û‹}û¿ÿÄÆ~꥓ÂéW'ýäW{íÕ[ö´|þšú™+aLý°7OÆÔ›å®§–R@ ä_aLù/#åP ´KaLíRV×í²½ev9ùä“oºí®­»ÞÒÎ÷·î|‹—v3ÝxÛ]ÇwÒæ×w»éÕ×w{é5¤ÅM;þýe'mÚþž¥ÛßóÒ6/mÒ»¶¾»ÞIë¶¼ké¥-ïxi³—ÖZzõ5Az{Í«o¿øJ5­~åm/½ì¥^~+H›ÞZ夕ßZ¹ñM¦H‚ôü†7½´é眴|Ý––­{cÙK»˜–2­ÝÕWM;—¬©¦ÅkvzéE/-òÒë^ZýúB'-xáu?½†ô,Òª =³ê5/­ôÒü•;‚´bÇÓ•4oÅŽyÏ#mGšké¹ísœ4{ù6K³–o›µ,H3—móÒÒ­H3,õm^M[¦õmù«¿ÞgÄÄÓ–l™Ê´ØKS¼´ÙK‹6Ÿø“_af—©õn¿|ùrjó–n„¥8ÿ¹­÷4ú^ ´NaL­ÓRWª¯€0¦úéˆÖ(†éëßð8ùdêÕ‘é¹=†é Ä• Ö]¼U$S&ñth½À˜@)ÕØ%<ßÏžûgã–pÀ3}/Dm›BôRªè°ñÁ]:õê;®ÙÁ|?§{}6—Ïa†©ÖÈuÅd Se}Ôξƒç¶¹bª.‚JrÅ´¬fá7“ïŠ)ðÆäºm^ä­wÆÔúßFǯ¸ãßÜշך]÷wüκaÆTàÂSÖ¥€¥V@S©‹W'RƤ RRzcºþ–;c(¥J¨8|û½ïŸä®q´í·L®Ûv]B¹°ï¥½´Î !—â©™@r›H.ˆ%ç[K®_~˜úÁ0erÅä"W.Q®ÖS ôÕüÃcNŒ)N¦ÉœcLd˜žyn–Àr:b„ÿCÔ¿Ÿž.’©¤Í¶«!„15$—ú) N¯§¦%/n¾÷E2Õ¯w¿¦'çZµ!õŽîâ-÷È'SïV =y Æ»zÊPá€ùK^ 9ÂE—B†ˆ¬!ìã}?ǯw#×',—ê7Äkl89ß»sBxz‹(uÅdáä<‚늩֑s4}’+&cºÑ *—QކaL]üµêÖšík•’=uaL=UÜzX) ¤@PǦ@…¥¬J+ Œ©Å‚êryQ 1¦XJ‰;1óýÝ q¶@K•ÅŽà–ê¢KÙé¥Ê:Èw€.…è%,‹´‘pÂô‚9a ™€ie,ÀT× Óº]˜Ò`Ь•ô쌮©Ó‹‘ÒcÉå€aJ'G£dÆDÓ$1¦³Ï½xËÎ÷-íxóƒ?ýùÏ]ÿ“azö¹M+¼Âõ0&xì7Œ ¥ó“ÓϽð¢_w=ŸÊ€è¦˜º©~ïÝ[Sï•y'Ÿ Ó7¾uXß‹Ûý÷¾ïS§ö½ØÀã†Ýõ»¦³Ô×××ô¹ž¸víÚÐ)MÜ=z‘F³Ñòãßó?¸lRÞ}pÈÒÏÇ$Ã4æÉ¹^µ‰Pïè.Þ|÷#‡ñÝï¿ßœÈ¹­èà~ú© ³Ê*×’KEŸ½‰ËòÛ*£.žˆ1EíÞÒ©Š³¥½÷Ù÷éÅ/Б}UßÏk<ßÏõ¦Z—϶VÊ55TbÉÅG«Æ’sÖGµ’aš¿¢•ÞI¿i.S\89oùÓ² ySm zºbB ŒépcŠqÛ\1cr­Ø~w÷‡ù©fÊI4Û—E%îµn½N¼Py¤ŒR@ H\) ŽM®ŠC™‘U@SGåÖÍ:§@ÏaL×Ý|g,¥Dãàµ7{SÈJ!–K¶¾ P)”\»¡¿ýÎKɾ—êÓK`˜ê†ëÀÄ9°T€©f­d0U¦E/ú+&ýE“5ë&ƒ@rÍÄ’k•¦, ScJpÅDŒé—g_*Ù?~ÔeŒ‰ Ó‚ç_ÆZØÐÚzg€ÌP( W¿>è´sÏ»à’ε(º“È›˜òV"åÎ0¦r—oWŸŽ ÓÒ5;Òßû‡Õ$Éêb¿ýö1bD Ÿr„ I0Ç€BÄîÞЭq:.ÒÐ)éoÛ¶­ÿ?Äÿ¤ä-ûƒC:ÅSF†iN#áäÀ0Áss ÆTk+°õNÀ˜BV¬wj®Jè¬n) Ù¾n)_èûÊS¡‹O™—R@ ”XulJ\¸z4)PGaLª"%U ç0¦koº“XRœô¾ýî÷Oô³¿¤­1â ]Š@K©ÜÒæwÀ-…Ð¥xßKè¥UQz)B.ÕS<Àäǘ¨ÃSkœ0­z확¯Í_¹ÃRøøÈ2Ê9XR™!–\F† k+=oL ¢Ü/möRey¥ycÊÆd S0)·¶žÓ‚^ûñiƒE2•´×ceP@S‘tHËÆÔ2)u¡ŒaªÀ(áH²€QH“ã½hS$ø 3­ƒôÄ–evš'©*´c‘á–Ô¼–`Là` «ŠÊ•%Ÿa†©Ò]dD9—zGµ¹ñ·› ™CÔœF´ôÌÇnÑrبµÙÎR"IulèСfágتz˜%K:¦[ cªÄƒƒñ!šÞÅs®Š_:UË-Á(á.Z ³ƒ¥]J£—V›¿ç—ß‚‘ÁRš¦Z; –2:a"FÉdË¢ðc2€ ­Sç¦é}žÏfbLæŠÉlÆ01¨œ0¦nýˆZu_ÍöµJÉžºŽ0¦ž*n=¬R @ ¨cS ÂRV¥@‹ÆÔbAu¹¼(ÐsÓ57 ‹ºP²=øö»Çžv°±VlUaOK/m~)d7ŒrK  Kµ¾ÜiR Ûãé%o~ËMaÛbrÙ&ß “YƒcÛœ0=·Nà-Í 9„‡Oøe[k¦¥Oxz†ÇªJ’c¢Q’SÔCoL`˜>ïûaBM»dpÖÖ£h`ÿ…Ù÷™U¯ýøT‘Lyis•N+ Œ©ÓŠ÷öý„1õvù·éé†)òÞ÷aó©ã½÷}XüÐ#¿ßht9Løkþ“H5Ñ!¾°‚m×3·±“´ ¶bغwâí\søÄ+ã`ÛcLIè²®ªîW Bp ogô•À=ÀAyÞ‚“žÿ?ªP¶é‰ù™={6.Å=Ì1”7¦V=82Öh20Lè.>öÔ<Œè@%6!{òì.Þ0lT£$žR@[€8T¦n=±zEÅPŽtAD%Y‘¢ŽÁb1&«rv<2–³*A6þì׳ªN–1œB‹BµGòIæ)TëìÑà¨,”O«ç8ÝÄlS“¢ËæAbL)v |…æ,\·nªZ › ê­›rÖ¿•°~càÉk=*Ö† „\€É R_Ï “Ï0ÕúuŽ:aò^mLÎj¨š¥PÏ'Æ’kÔ¦ŒÉYïä2L˜òðSê8Û·|ûUý¿”®Ð; cê²Ö“J) Š¥€0¦b•—r+Z©€0¦Vª©kåHÞØnk äÎknvô±'ÚÁ¢ÆÚ¨p4†q¥Š§¥,ÐÒ‹p¶ÄŒÃ†cCLD—jݹ'ÐK˜¢H¢—RÜ/¥x`Bx2/EÖJö`Z¹£íN˜j¦-.Ãd«*á„ ÓƒÆäùa Ù%sè‰ ÓÂç_ö6NJE\2T"ÊÙt&œíÿkf’‰ó‚n+•´Zsu9jϺLJÕÍ‚D«+Q‹ÆÔbAu¹T„1©‚´Zc˜êÀ(Œ˜ë…·Kt±i„d¢OäݼÂ`EÅÂW€?Ð`¬+¼Èð¾3n{ÙË ~Áƒy$=èð Ø07Ev°õ:xJô²¦¨}…l0˜K>á_ò4<×§çsrcùG&q…袞rb³M8_áv”‚w´GvƒÊµäÁ ë4T³\†)ä¹3ÎS@¿¡æ\×ÉD$3À+¥ž°ÔBõ eá–# ž$oLDøaM³ RA܃rÁ+ƒ‹l²=v_V7Üc? ^ÖíñF+žŽ(³aõÉ áŒ‹_4U±€iCÈ!ÕÚaˆlÔ ÓŒª-²ÆiN˜`‘¤Qò¯þzocª $çòL'þäW9 *Ã0…ãƒì¢K×§3¡íɧœ“%ºœ0¦¦[n›ñM¹‚0¦¦åmòDaLM §ÓšR@SS²é¤$\†)Ä.Œ’òÞ?ä;Y}2”1ßEÈOèm’æ2%`5€•`Y%|ˆŒ¸Aåp€¹áᡃ‰E/kâ.±Ý,áFäZˆÑç ‘£Oû é;*z£Xz&”mþ‹Ó ÂÕ쎦››·~>¸Kbeü¥Ôa˜j=w2!|œXwñºÛ³údBÞÈ÷àA ~l=qKGR|:Ó·ia›{Xj¼2· ‘7‡D[%Ø ‘÷n5ã¥ÜSŒ|â5ù/ïË\`ú9ÄÖR`I/E8É®ªuöhx>¾ëx ·³Ö2>¤¡KQgϼ¥2.½”´PÊ‹Wññ¼Ñ*™ªêwö%Ú^§¦8¿Î‘(r)N˜üAn¼ ayÕ€`.œ=€)™a ­z:çß<Œ)6–œÙ T®¸¿A˹0¦bçASç5×¥€R ‹˜²¨¤c¤@9ÆTÎrÕSíé9Œéªî ù/”¸~ßüÞ‰•µŒaD‰ R «TÅ•j<-Å8[zÁJþòÇ*·äÍW9^Ü«–Ä`5d×¥xt †Å—v1¹†Åï¥z)ê~)bg\ø‚³ÌO¯!!X2¯ïî¢INXr—Nö`ª $˜œ%•®&³Hcz`ü‚X?L¹òƆés~,¹ª&c˜Ö½ò…Ç~o.3êŠÉ—ph°ý¼>É”„1a¢…kè1ÅÂ)@›Ôá‚uNX2$‡¹CÀtãn˜ó¶»<8€§ÛÅÝé.;˜á”'Æõ]fˆËëÝ+Gs‹cx=…ùç1œ3‹îáSóNnñFÔ„3R<‘ǘŒ>û۔ª^AP@S'TÖ=* cR]h1 “Ë.»0ŠãŠÉëwaZ·òÞ?8ÉDŸ:ˆð•ír8 „§ÐûN+ ‘I8‹8$!ìâÂ"䜨O4Œ)J«ØaÖCÀ¹!î×çë/\{¢}‚ý<†ÐUèFQŒ)šmæ–!êØ!Á‡TM¬7¦þ?¸õ—2Ö,0Lè.2–\ØS†î":äè.^sûCY¢ËáéЋc±²c[OÜRC‰àH«l,Gë±Ch˜¢ýÃtŒ‰™qƒ$²Üí:é“)Ûnç-ZyP:¤ôX1\ÜZªc¨«ì6³p‘=…“ËXÏKp1¦¸õQ4Ax Ì|v…™ Z¸bjerœz'rœ‰²)÷Káðô¶8jÛÀª`Š"‡·[¬%!º*Ñ S(½c70†É,À˜¾éaL‰>›å©¿D<‚0¦r”c‡ŸBS‡×í¤€R £˜2 ¥Ã¤@ ÆTÂBÕ#y ôÆtåõw˜‡¤è¾ø½RÖ5ÆxWаJŒ·ÉKQb)êl© -ÅF‹ó½¸‡,‰uÑ¥tzÉu¼Dü%&xœodlØý’¿b²`rlŽžg ï÷=0®à}+d“ëN˜ 1¥0Lð¶UYöêyÒJrÅDïú0éÖ%™’0&.aÇDÀé% ºÁý6™‡ .+Ç)øp®‹S•œ­äL&o8ÊI,Î0¹Í3 5e¡:èõÁæ¥BÓEœ Šæ×áyæÙa²é[柹â1¡=ä´xG|Å9Z›³‰(; Ïhn¨ g4õþ霘:§µî´g0&Õ‚)` w²ììøÁûE<»\ëSÇ{ïû¾(¾]d²WóÎwwè Î75_‘ Ëe/D¾Úx_yá Ç˰ÐZ3+z°a@|ÏÚeMÑÐ+8Š1‘ÁñìfÐ3“½sÙÁ·ÄS¢ùwyÞ4šm>>ö³¾ 9cêÿƒ»½º•‹ ÓØ8†É«9—”jw1âŠ) ÞQm®Z‡dŠºb¿(©ž°ãdõÊ*’u¨Øû"e`“=rÈ«bc²N#Š˜49/Å*Án›Û‘³‹„ª“ubÉðá\·ó­‚1Rn­³G³N)q>&;ÌuKY”CbL)f|…f<³"ìÝ9}¹T\xzÏòÌ-Õ¬•Šêûx^›Ñý’0Õ*k¢¼eQîš([…EPAJ˜|GÎEnÎòmÆ0etÂä’3† Kž|Œé{)>›…1•ãÇ(Œ©åØá§ÆÔaÁu;) ¤€Ȩ€0¦ŒBé0)PB„1•°PõHžY1¦èú×"êwòÉ'¹þŽ0Šä˜ñíÀcNXý2˜$7½µšLRlòA¥$VÉ1Ö¸YŠzZªñÜø[Šá–Ð¥ÀåR£Ž—zéE}a ÖGF}/y!'Ý/¦Æ(½Të~)`ŠÄs°Bšý±B/Á|ãÓ/„\`¢³¥ücLÆ0ÕÆ™ËŒ™” ¹d¨D”#Ãäk¸õ‡?;;%º\ Æä΢ Ácñ;Ü .µw²Óö¢›à‰ˆr'®l›¥¡ˆ!ø6Ê$…f.q ïhüS,Æd3I\cB{¢ËúÝñ`›îâ|*‘&c³}¦ˆígQó,Œ©¨%WÌ| c*f¹å-×Ãä;欼÷'-ÜüؼMcçnD3wãs6]ŒòøÓ›<ßµ®˜‚÷þÒ­ß>âØawý.é1É»ßb]ÈÐ ab¾]Gƒ|±A2‰Çð‚dV,ì/Åw%Y(÷`{á†.ëf̸̮^éÆyæéø;ͽ¹‡4D&t#$<×˜¡þ1W‹äZ%ÞÑò½B£žÝ“1Lè.†Ð·qó6=T›Aµñ»‹?ýrPmBÝÅå^Ü¥«n™â“É5“ Y%Á­'ÜÃá¤yßdwˆ}$À=Ñ‚ÀN|‹ÃìcµÈª®/åV'þKàŒB4O¡Â¡êdCy$»µ¡ªèV~ÆSèÓ®ªuöhæ¶ÓNĹòÆ”·¦¸­ù!Æ1;ÔX!pÀôùϧ[!žœµ$ÆÇ³-=9sIÔòðÈ„YO˜5qÆÏ÷Rè’ÏD&s- t¿ôàØéxUÍîÛ„Ä(r4,Œ~êY`rM IÓCŸ¹çá©Hwûiʳë€)ˆ"7é™uO=³ÃÞáÏ ‰kŸ¶Ü7n‚ÎGãÎà 1¦ŸÍ˜ÚúéØÅ…1uLê2ÝHS™JSÏ"¤€(“˜ÊTšz)И˜ÓKGçQØÕ¼õ1&Î@ðÓЂàjàcL·'š_~kÈu·uÌ Ä’RȤäxpaV)ÖÇÒ7¾uø§>û¤¯ëpºmÿÑO±ï'þ{FŸežÛg<»úëß:,´{ŽúÞIXˆObéô³/FŠ wã°‘ˆ2†€q3î o6ü±qèRÕ»{ÈñÒNÿê¿j‘ãâJÆÑK®Ë÷XzéÊ[ÀºÉš¥“>g㦽÷ý;X™0›â§VLýǘÐ5\´å‚¶Vu2LÏ>·Éf¤`k&Íöƒ+gtÖøƒÎäÅ“O2câÿŸ½?º¢:÷}aîýƽgŸ{î9ãܱ¿s’½wº}ÌÞ÷ËÞÆ£QQ‰‰‰½ ‰ ˜Ä„hì[T@ FÁ^x;}餕¾WîDD@Pà[DQùþUOÕ³æªnÕê«ù¯1ǵjÕªšó?çš5k>¿ù³÷ô3zO¿ÌË–øîU5gÎiÛõ›‹£H&'d:ŠqHŒvhÿߊí/ùVÌ6b1bCò¯§—_ɲ~UX+c2M‰9JÏ,§îJ®%†Iÿ)«ê¥øú2e11&9À¼¶‰1Õõ/ã=91¦†Êû‹cÊ}¨^a˜Ú6îV€IïûgÝ:÷}ÜôϺe:R·¾sq߇©7ý€û¾íŠ c§¹«vá¾ÿ‹Ó£H¦ê³í¹•×ä„< xiǵû¬))…0Lãž!yw›Ór&/ÙÜlìˆræp±ßÀ(’©d®â`Ž‘âß°c0F5ñý´?7L7^(¦‚1æ%Üùs"Ìzqm _gÙÙû/÷~ÄǪô?ûåéc¦Ì—Àô]|¥Ì9 9Ä’=óðì¤ù:tЯ0 )ˆÒ^—¼è’7rœxvWFûæ·¿‹GÔK¯í}é5½1±Ðí÷—cVᩱ³OøÙ©’>0}`0úCxäéš^wY“}¿ÓÔýŠžHŽœùï‡)³¸j Q¢È=òÌtc2LwN˜®¿SÌæœîÈ1¥»þš”{bLMž—¥T€ P cb¡ùU€S~ë> %Ÿ)òò”§4Æ$øñ3Læª?¥ªcê{ÿ#Søö¬_uµ§=ÉZÖ˜d–ÐI[­ófJ©(myOp%IàQú=8¤Ë¯/Ä>â+™C|bÄ™[´ˆ%Z·tØ~‚©F J‚.]qÝ-H6®¤Éá–-™aã0î°õÌø¹þ¹Eº¤ë#1É8lìì~”éã½0ÏX¦ï% ¦1‚Çwâ)¾ßM÷K‚1ÓK¶MÎH;1)+)=‹)=0™«*+óÆôþ'o,Ü~ÑcmF­ûNýþÂ0-yy[ÁY×–w5¦ ™ðÇ€ªGEß5bu·¾sPwƒ'¿ÚµïÌcÆöø«'M}éMÈnºbs&Tº0œdÀHÊ¥QÞün‡tðI~Œ ¿ÕÅñâ~'D—"=‘¬†0„í0ŒIŽ—ðDöx47/-Çûs‹ HW&ûbR’[ÿdXý:H©=Â:{½¯N楾ê×lxæ"ˆ1±A4RbLT;‹×Ã`}%&wô(t»8_Ä}ÿÏO­<] $™¶O5K‰I|;ù1&ìÔÜJ08n%“ré=?hÉÌ­I¦M˼}.òéQOöˆ'*zcjèM„SCåÎýň1å¾ T#€Å0Aß°[¢ü(ÀdÞ÷o{j…É0á¾Â5“0v5w3¢†É}_`Ó“ pßG|œˆèrÕdž¿­“‚1I „™,†é¨Žc§. .âñ“É0*@³Y Íæ§Ùˆ‡TÓ“ï|¸5"º\ ÎÓRl+Œ ”R輄M&မ‹^ö¬’RÈ~Á'¹¬Ò{Ø:ÒZ¥Þ'ÏY!÷‘‡µ0&å–FM´0&](5rÂ<™sÀ»$t˜‹@Âö÷vV¦°, ó xöÄœ¶‘0« aãdzSHèdž_´˜UÀ;æ%0±€é¤3ÎIoLxb:fö¡‡%“ ‡NÀ Û§Ýó ˜1ù+ÙŽœcRßK­“c'fþã°#Oí|V@u¿âf¤Á#ŒI6Žýé)x¤u:nˆ÷?:ÎÚÓéd¼[“2LÅÓƲýÔÒcÊIE×¶˜Ä˜j«'ÏF¨ µR€S­”äy¨@ú Æ”¾:cŽÄÈ.®Rü¢”Ƙ`ׇé§À†‡JÆÀ˜î¸¯%ÀC’»äßžuNW¿ÿ$“€%I „“ü;=ŽÙõã•×ߊyCàJHVx8{Ƴ‡ØÙÃæ º„ |,ö´„Žj0èÒY¿ê†ùDÁ˜°ayZzÎò´„ DÌ*b£ÓÏO³Ö[KÚ`%Ì!7 S‡x_°r6n¸õØÀÎ8§ë ·ÞÉDìÁ;¸%Ì*þùžG°YE01ØFÌ3ZBÂfo»«óŒ˜pÄD$J^×ënÌ6úœ½Ï\º³€“îzx8VLâ`¼Ïxi‹½1ÓŽø ïýŸiÇi‹7ÇÉǾý‡Ã<&8èuç@`L (m'L•»_òÀLñ1&ÀTWŒ ÓGu\¼z›69iB2ãŒæ†€2×?²äÖ¡+nº Ó)¯Â??6þøÀBD”;£×ô«¾è1J©+&kºÖž¨ #™ðﲓx1~7åkRe xfŠuY/ˆ1ÕKYž7HbLl•* ÓŠWw{ïûöMFe¹ïƒ>Áû™H½§_üà"Ü÷±§ësz=±,ü¾oßð3!ã’L•VQs~gbL~˜ †‹Ãä>¡ø‡‹@ÌfsI`³ ñÜi[÷­fC’©9ÕÏ«fWÁ˜"æ%ð˜±ðåÀYˆßýñJxt_Î:¿¿…1MôFˆÃ´Ãã#&KHz$Ì<`:BbÓ#aÂA¼;c¡Të„yè10Ï 3 H˜Àr)ì¹ìº[0ðpÕvL2`”ÐK˜aÀF[ï‘qêŒ9‡acçÈô‚,‹²0¦õÆß&½„YL&`Mfð޹øÄdÂu½îÂdÂÐc®À CoF”Ã|æ0{€9 @/‹ þpÅÍHB/aÞï<6\æè«ÿé›ÿŒ"ö´<3ýÛ7öýþaGʪ'ÿz'bLÙýÿ•ŒSN*º¶Å$ÆT[=y6*@¨¨•Ęj¥$ÏCÒ§1¦ôÕsì( <€À“ˆSubaLr´ø2Iµ®ÆtoK‡„oÏ<ç‚À°$ÿ~' œ N' ±ñâËoÎZòª€J˜4|¼u²ƒ.Ù*lÛ³‡Ö6p%ÀI¦Ïö®dsK<ÒzÙµ· yz’ -a¢SŠX ©ŽÜeC¦‘°»’¬ŒÔYEY‰¹E¤–§&N’Å‘xÿÆ·¿ ßKH`˜0½ˆyFk’‹þmŒ èVÿ?þì,L,Âñ¦/¾²ç¯´6àx öËŠÉó~{Ùc6ÆÔÑv½„ÉG$ñÀ„YÅ!#f½$~àK³ýÀ¹‚šˆ¬ÆÓõ¾ÜôÀ¤Ëâ±ñäê¿›º©SmÓ€IGqÔ±/®~CâÈ8){ÞYm™h 0dö÷ ü0 Ÿ¹ F)X4Q•˜`Ë´ý1ìAP¹1 Þû˜Ø-0L¶K$‚dJõÿ½ÜÌ×c*7<¾. cª‹¬r0 Í$a—qßâe—Ý0²æ(øòYÝÿ}ü+§T9\áÏ @Æ4~ÃaÓ^x¨S§NÓ®‰.â!“<&`¸h5›õn³±£Z“}Øì…2\TÏÒxiyÔ!ÿôÚ§IŒ‰ ÄWàÏÿvSiŒñU¬€…1ýÓ·Âæ%dþÉ3WˆéBAO:tÚM·Ýc:iÇG+ Ük{®ÞnqK.±\  ál·í˜C|ÚC¼ôÚÞ˜mÄ;&±!3‰}D+ÈÈÏO·ò q¶$I1&kA¤mú²0&{nQfÅëf‘àŠéºÞwËôâDY%¹v7/ÁÁ&1]BÒyFÁ˜né;èÔÎÈl#0&Y.‰ G˜FÄëû‘3AÕ`VÓŽˆ‡iGñ½Œ©çO9ë‚«nê‡ùÇ)/lÂD$f5aQ¸“|¾—* —Ôž?¨Ü ›‡øa&û¨Gc‡c D[·«¸9†L44 pKXU/ &ñÇWLWZŒšÂ´¯åiþVÃ(µË1J¯­ô~ë;›w~ôգ,<'h¦Ęš©~þ®MŒ)u^«ƒdr† …¥3tœ]îû×µ,†&Üô­4w3†pˆ${ÇðU˜ xnðå’0 ¦«®ï…›>ÒG>¯Uþyž:)à*€iÛûår !@2M]°Z½uš¼»4<>`ˆ(ÃEa˜œfóô* šÍfµ0LÃE‹a:ú¸Uv Ù´¿ûÉ—_}U§òò´YS€·ÅŒ)zÚ8ÿî õQxH„gO zYeM>ØXæ-!!0œrK‚1霃ÝQX}…åÑÙî1°JJ–H-°&L5`ÂáŒsº¡×%v_Ë3ØoM5Øâúh$z{†‹£0«€¹Ì'ˆ×%ñå,âËyÖÒ-O<; ¾—]º¥_ fú=l…Ã3,ÞųD¢½$3 H–çæ‘30 Ì¥øo¾ã¡aè¸ðncL;ùÍHˆ2LR:“dÂ_Æ¿¤·2_UºDŠYŠf•·ÁòæîrĘrWåM-0íµM•?í’IoúâyQIÜ÷/¶È"á¦/iü¢7àÊ¢ûý .ŸÇì’ì²É0‘dJEƒ11&`ÒÌ É4eþê€áâFk¸ˆÔµï,lÇŒÿe¸èm6áÃE“a’fC’)'™äm1¤cŠœv؇ä¯íMöâ($ÀIgýª›9B,=0¸ÕŒ ,Iq%8uÆ3¦Î9Ès¥ørVïÎð·$s –$}×ß_ŽÉk>aìlL5\ËÝòÐ:–gŸ_"ÐÒõ½ï5u ú£Ç´öŸvvWܪ®ëuf°& “𺄠L&<7÷e|”Ô:i±L&`C¸%lKä8õ½4|‹0 vùÀcã홄“.|ÖO=÷•7õ½â¦¾wò™È츥ïöc¼?9n‘Ì`éw—ÝôË3Ï'Æ”ˆ¾¢y™ ÆÔ<íS|ebL)®QlEɆ–< – +­Ý#k"%Tœ“lKHB,Íxi‹l,´GšÉ\%)sŽöl£3á¨Ë%9G;fœ‘ŠbÆÐ¥…‹FÊŘÄ~³á§Ä°T?Œ Í$¦¯Ýé6§B›1WÕŒRvLTÐä%Û j”rÂÊìT5$–œøa2H&‰ )/ Œ­­­1ûô5ñ‘#ÿÁø-vÂëÛ‚ ôŠÕ‡³DJæ˜&xM\›W/ùCtˆ1%½†²•?Úk³UŸ/ H& Dul)ffÊðO¼é80Š{ß/ ‡Qü I¦ÆWq¹W”Ñf À¤§’iò¼Õq‡‹v,9Þ»ÃÅvÇ“}Xú&’LåVb®çm1¤úñ·ý‡úfô´˜2oµyLaÂõß2ÿ`L>Øsž™sÚÁ†>p¶Á?Ïà™džaXku5þ¹g>!hVÁœRLŸFöÜ\é§ëo{è¤Ó=“СCÏ£ôž÷>Íõ_>……'Æ”ÂJk~–‰15¿˜*@¨R€ÛȯĘò[÷/yî0¦?ß5È?Ù§{ð­e=òM º4R“¤|’1E1QX˜4´cÀùç £Y%1_’Í*àJB/EBK2«hN,>þ¬N¡¥ˆFËæ!Éuð^‚[ÂrÉ$¡KætdeÓß¾°¢i¼¶oØÔMÂ:‰Mû6UßX$ÓÏNyqÍÓ©aAœª·+ZªÒ†Ì‚RÖjTw7Œa’yX¸àR¿mð²^Ý┤dL×G8›ÿ`ðCÀ‰ÀNµ´´èå€1ŸÂEåŠB}Æ),I‡ĘÒQOYÉ%íµY©É&–CH¦â›~!˜‚Ë!÷}×ÿ¢Ë.ë}?Œa $™j2€i¢†Yºô¬-5„\D¹„dš4gUŒá¢…¼2LÆä‰>Æ0’L‹îè>¹{ÇÞôŽ~wµ-X=´(¨y–*ˆe)¡o‹! Æ1/¯pÀ¤¹«ÖD…Ì?xÖD…³J%ÖG•„–„£5“.‹òÏ0˜k¢dz!b5TÄ:(ï"(èyOÜùJé%( Æ”“þSN*º¶Å$ÆT[=y6*@¨¨•Ęj¥$ÏCÒ§1¦ôÕsKÜaL·õ¨ëýø¦£ˆÀÒ_ÀIÂ*9¾”Š(¥ §J^PÉ¡Éë])W’€âfÉN^hIlž‰ÅÖÉK-9Ü’-ù¹¥R.—à~©™^—ÂVRVƒ1EüɺŒî²`Û‚XÿÂR É´hõgu¬Ë±œ13LŽ-Óo”Šf˜FO^pÂÉç~ðñçš/u°Ex©c7pHp_${€á0OØ–èlدl¶x<÷NæÁz! SâÉã ?‘S)`„c䣻ԼÉ1MS~¥Þ˜ôñ/%ù÷¸›ÂW8¬Tðûô(@Œ)=u•…œÒ^›…Zl~@2Öù|Çí¢ëI™ug€g(~ÿ‹€QF'&Ã$HÊÇŸþMJ^ÃLó¥ÌS@EÛñø ³W9ì4|wE#ïå2LÒlÔïX%`LöPïKî±~LOÏS°¬ò¶Ò cŠž[Àç¬*9ÿà[å|p|9ûfŠp%cÎ!®;çÀIßô‚®± säÛ…sÑL‚ãxÉï¼¹jz‰SÞz.bLy«ñš”—SMdäI¨ T æ cª¹¤k¾ߺv#¿«$ÝS$yc½…D|ÓÐo”RP)ĵ’,‚ Ä•Šü·KgK¾q‘ΖBâÄø[*Í-Yþ¬´ÃIµ›vŒvÿ^+oLaÿ¶–-‡ <¤Çìûÿºòk“[×¶b¨&›ðQ~‹~/ôÃ1ÑÜIS¦ÿ³S®zËšnvc:µ/µ­6aV!ËT¯;>þ¤ÎânÊ|R'IÂ*ŠH<6aC,áA‘€ÉWêcIÝÅtÝ ÊäðÑ$$W¸€$É­€Sš[ý9öhXMœÐÌ¿g–¯ÊëGyt’ Æ”äÚÉ^Þh¯Í^6©DC{#RgÐç¾aØ*+\ïlŸCh?L£ìÜûÉ—_Y÷}ÀÈ6Æ-¥`0¶ÁW:ži’N¼l‘›6oùá}nV[Ðp±(œ'–\e šÍgŸ€ašÕ£ 6ðÐÜ/½>Í I M{7XD»g¿xi¢£¦Œ7bÞC*X0¦ˆy |…\0Ñ»&Ê»2*dqTÙ룂|9»ìlaYTD z7}”Ë¥Âj¨U»°ʳ*Vèyã¥;â?ûÇ?’Þ˜2Þ;¹Å#Æ”“Š®m1‰1ÕVOž P*@j¥1¦Z)ÉóPô)@Œ)}uÆÇR wÓ-}˜D‘gߊÑ(~ò®b ŠøV—’xTŠ•"X¥2p%+ÜX»Ç‹»|ô„‡3<- %¯³¥ª¸¥&£KõƘÚÚÛ:>Õï0òaCL€ˆ´¡ 'üAñìrpI×MÉtâ)óÛÞT7þâdKƒj=JMÚ2£ý0‰-óÞ‡Ÿ8îø€HyÀƒ4´x }IO#Œ”L·LòêСƒDmÓxsæÁ äT¦&³÷2ƒÊá0@Kx×ó‹£&/çoOò½œøgÒüˆ&9‚MrEùm¬¾“¥EbLi©©lä“öÚlÔc2J’éÔ³Î3LJN,`\vÈ®Á8­=â¾_Ärë¦};Æ*º€´ö`jc'Æ;9ÉŒ¹°’iܬ•Þá¢ÄvÃ9E#ïѱä}† ¯Ïì«nI6€+[‚s&qÂ4º‹5è•Ø/Gn_4Yð&ìÿÄÊˬ¼-†T­`LÑs8T¢ÿ˜ÐùÃ…shÐy{ÚÁN?úcÃN5…žŠçŸ^ˆr¹d?·©¤×%w&¡Î+ ˆ1e¶_*.1¦œTtm‹IŒ©¶zòlT€ P*P+ˆ1ÕJIž‡ ¤ObLé«3æ8–yĘŠ&þŠ'û€1zÖùf7ÿvpX7E‘ü¯ìY²®Ñœ@t& }1à“•xÜÑäzkW„Å;™+Z*Ž Wnµ³&²2h AL<Þ]K â–56f*æ–l?‚¶+AI¡ãà¹Îè’9Q@Œ)›’¯T>ßýX[P)9)/‹Yˆ1ÕDFž„ P*@j®1¦šKÊRÔ(@Œ)5UÅŒ–§@î0¦Þ}DÌâ[ká» I [ªgL*ÀIEÎØƒ%#æ CA¥p×Ja–Â|,Kñ<-M2Ú–3Iž8qœmŒï%^¬Æ&I°$µüa[<0á%ßÂì‡oñ.)fX›d:yÎòíE“¦I 9Ǔϖ“a’Xr yè®$TÈ!Ù)qâðnb@Š1Ià9|3„ éˆ1i”ºˆ~ËãIü6álà$«TIP9É›xf’ÜjÌxÏã‰áäÊ»¤âhbL©¨¦Ìd’öÚÌTeb "$S4Àdù_´ïûÖÌ5ñVÀ0éźéÏî’Idð `$ðœ`”ÉNŒf̈C2™¾¢äpÑj9úV䬒8[±€ `>Âñx&©Ù‰8‡Në,³ ð¶Rµ‚1‰¿½°É‡¯ÿã7ÇÍ\gÚÁëN)deT˜çÐ9‡xŽœ]OKQ^œ£¹¥Â¬BÐ|Bø5ù 1¦ÌöK¾‚cÊO]ת¤Ä˜j¥$ÏC¨ µU€SmõäÙ¨@š Æ”¦Úb^ËP wS¯;ÑE˜ã3¾uV½ËN+h—?Y â#R‘Û¤p/JQ|’„ ‰*¹VªW‚S÷HæšHïÊÈ0h©±K$k2AYŒI"Ê™–?ñÀ$M !³Ÿ± 1ÿ¸ ™:þôäYË·¢Èe¬ŠóÙ2Ëb˜$à{$ €$%TÅ9Ž?¤’0C À„ÃäçÂá…„üG”Ýt’¤WÄ%äüÂ!!‡’1œYÏa§äÖD²°G²äÏ?ާ7¦˜-0e‡cJY…¥<»´×¦¼“™}L'Ÿyž ©›äŒû~ÁMEe “ QdƒMû¬Û·cº“”°¹ÉÔ-ç¹’èrÏN[2\4Ð7×}We tVV ¢Åaü-‰&@Kø‘ã$Àœì‡O&õÀ´«mð¦œWV–‹ÏÛbHíc¥0/aL>à€±3Ä­ZÀR(s:"xþÁðß¹2*À»RŒeQá.œ½A⬹ÏÄBˆÿæð&h¥º\Š˜O Ɣ宩¸lĘòS×µ*)1¦Z)ÉóP*@¨@m ÆT[=y6*&ˆ1¥©¶˜×2ÈÆÔóއ#0#|k-y÷°G>÷H²`Ñ“¼aÝE ÜYÚ(3†…yCPJq@%#\°k¥`ïJ¡¸R¤›%#<\b&«á™ê„1Á,i¶@¸.€µû…g‚ÙOöà˜r=É4sÙ¶bC¦e‘ò¬ª‡20Let!<” $\bL ¯ ŒeöÚŒUhbŠ#$“x^Ô(râ„É߯˜aBq1DÁ@êÉ?€‘oqF/Šh'F*f¤ €L£ž_®ÃEÇggy/à3L¸ž°J²ÈqÀ’ð.“«„ØÌsòQ£Ë±ò2¨o‹!•*SÔò§µ»q|ªÎ<”ðÙlÎ?¬Ù½0ræ!ÖlÃ*Zòó>¶aJÁ“"WC…øo®æq¾N¿%Æ”Á)¤HÀ˜–ï왟ò²¤Õ+@Œ©z y*@¨¨‡Ęê¡*ÏIÒ¡1¦tÔsY¶yĘ"x#`L°•’Ö´GOš(’Ûš(Ô´ÚŠæO†cvÛ^%É= •BY¥²q%70\Öˆ¥À)Îz`LíûÛÅ™éc †@Ù)ïxÉaâí ÜH¦c;<}é2q,+\­…­Fd2LåªÊã3¨1¦ Vj‚‹D{m‚+'íYÉôË3Î żïK$_áTÃ0éÈæàÄ?€TñßKÿôIDAT‘ÁŒŽgÒ®m†ó/$Óˆ©ËÜ–<\¬†a‚z&‡„@rHØi¾ã#<0éW"¸çc†k!×Eãm1¤úcŠžvÀ£%4¤…"• ‘§ œi‡Òs±f|¸’ëfÉ~5Sˆ³%cn!þ–¢ù'bLù黀1-Ü~Q~ÊË’V¯1¦ê5䨠T  cª‡ª<'H‡ĘÒQOÌeÙ äcºù/ý#0#|«a;‚#Å€bI€“‚ù¤(Dɦ”‚Ö;ŠAË ç›FŒˆ†+%Ä‘{VzN[Œ©ì?bE?’éù—¶š“YwôÃT‘®üQ¶ Æ”­úLzih¯Mz ¥; ™~qƹaà2†7U2LéV‡¹Q@H¦Ö)KMß]æp±J†‰ÂS(x[ QG0¦èåO8q!K®€*µ&Êv0ÖD•¿,Êv°4ÏP –Ü ó6\[´ª1õ5¿ 1¦ütnĘòS×µ*)1¦Z)ÉóP*@¨@m ÆT[=y6*&ˆ1¥©¶˜×2ÈÆtÓíý#fúðí/Ï<¯Ø’ GžäzHòùI2}&•`’€%iŠâ“bQJÞ0pî4"@¥`VÉŽ—+\)lf3½þè ™ŽétòÔÅ[á‰ÁtÆ@?Leô‚<4Û cÊvý&­t´×&­F2—‹d:ý\ñ¼èÅ‘aÊ\m׬@B2=3y©¸H†©f*óD ð¶‰1EO;c)A!ÃW@•=ùNCÂ…²J¹Š8¯“ĘòÓ«cÊO]ת¤Ä˜j¥$ÏC¨ µU€SmõäÙ¨@š Æ”¦Úb^ËP wÓ·÷/ÀC&Hdoã[ ØQI²Q¤H‡I:EX˜+,éE)À—’;L¥(PÉgâªù"Å œ0Õ“C2ðËÉ/n1ë‚~˜Êèyh¶ Æ”íúMZéh¯MZd1? ™N:ýמ¦,Vu-Ë$$ÓðIKÍ–C†©–ó\ĘÊiâ)zÎHDÈÐTz)TÑ´ƒãQ)Žóæ’k¢Ò®Ê™ bLå´ètKŒ)Ýõ׌Ücj†ê¼& T€ ”V€SixȪƲZ³¹/Wþ0¦>ýílÁéÆ>ý­#â÷++‚›¦Â„`ˆ¯uA‘ü©È»ÀIÅ3†ÅˆR‘ovYNMJUÎNâçiǘ„d:Ú ™È0å¾c§†ĘØ©1¦FªãkyH&2L9n eÝC2‘a*C;Z±¼-†HŒékÿøÍèi0bÊ2ãgþ¡‚ɇ€icA”á¼¹xÂ!ßΛ‰1Uü¿O݉1¥®ÊšžabLM¯f€ P*@ ÆÄ†Aò«1¦üÖ}ÆKž;Œ©GŸ‡Â "ìÇ·Õq@@ì6ÅüÅ“ƒ>ÏI˜% "“È'5vqg0&“d"Ôñ>›Å+WbLå*Æã«Q€öÚjÔãoËQ@I&2LåÈ–÷c•d"Ô÷¦Ð°òó¶1ýÃ7£§¾ößl²4îüCÐ̃=Û É^åI}î®~R#Ï@Œ©aýDÓ/DŒ©éUº cJ]•1ÃT€ Pœ(@Œ)'ÍbRˆ1±YdTÜaLÇœpò…_–àÒæ_¾÷ýˆܯ®»ðâØé×]h'Ø™˜¨Àù¯ÿ­óyÝ#2vèáG_u}¯Í;?2Óß¾ø*i}|2!«'|úú­ïxrk~ܹ÷“f>ib2?ÙQ€Svê2 %¡½6 µ”™<üèw¿÷ý«.¹$⦯pßÿò«Ä Z2S ©+H¦;ì_ýñ÷VmØ=\üìó/RW:f8q ð¶Ž1ýŸÿç:ôGGG$ðoÿqxô1Þo?σL5Qà›ßþ_ÿÏßÿèSuèÐÁÓ‘îyïÓÄý ™¡R c*¥¿÷*@Œ‰m‚ P*@’©1¦dÖ sE¡1¦F¨Ìk4A|aLkÖ¬éSüžb¦K®¸îüßüÁ³“³­ÀÙ¿îV²€ —®O>Æ„þcÁW®ß´‹ SºR^2± cJlÕd2c´×f²Z[¨M ÿê¿lž>2ú¾O†)±جŒ=4ýŸL½™ S³ôÏ×uy[ ¯ï¥K—.0^S¦Í1nš™ú~ʳ']‡Íºä™ÉƒÒ•g3·ÃFM|ä‰ÑùŸ2k11¦ ôiĘ2P‰ .1¦ ÎËQ*@¨@Lˆ1ÅЇQ *@Œ)ƒ•Ê"Y ä cò×yôúu~KÂH¢C£w¼âïÌ–gúab¯ŸGˆ1å±Ö›WfÚk›§}¯¼cÍÁ:}´jFÄ}Ÿ SF©2Z÷9[º/Y¿7°å`¸H?L¥$ä÷±àm1¶Tï~øY–½7íxgøê¯MXz– §,ôÆ»É'è@bL ªŒ”d…SJ*ŠÙ¤T€ äNbL¹«r˜ ¨ĘØ2ª1¦¢Haqf¦x €IĘÆ\{÷ª_?°ÿc‘aÊhÎb•R€S)…ø}- ½¶–jò\qøèÀç÷}2LqÌÙqÀ˜n¿¬’Ÿd"Ô³¶Pÿâò¶[ãŒaLó7Ý4iÍ6¯¿¢lO&cŠÝät 1¦UFJ²BŒ)%ÅlR*@r§1¦ÜU9 Lˆ1± d]bLʨ@% $c²]1YÒÜþ>ûœ &Ôõžœå W€[G# ½¶‘jçãZö¶OîÞéƒ77yJ¼èŽî»ÚÈNÉ„û>¦|4ªJé!™È0U¥&¨o‹±F–0&qÅ$SÞ2cŠÝät 1¦U³B¨ T€ T¡1¦*ÄãO©@Ê 7¦”W ³¦1¦J–l¯ déâ(8ŒI\1IêñõƒŸª$&Þr­1¦\Wà O{mÃ%Ïü_ŸÖºôáÅÛÈI¿R’‰ Sæ[Eü¶µ·E¬$¦øªòÈ2àm1¶XY˜ÔS2cŠÝät 1¦UF"³²iŸw-A"³ÉLQ*@¨8HŒ‰€ äWbLù­ûŒ—<ïÓÖöý˜µH¯lý`óÎÇDŸß¦K7÷X¹éÝèNVV3Þ£²xÉS€Sòê$Ë9¢½6˵ۄ²aÝåàJØ€7¦Y=º Á “d_áÝÜ’é­w¬ÚOŽÜ»¡ÂÒ„"ñ’ TV·ŽOu,yALÛvïÇ{É#y([ÞcKöÁÇáAÍÕ5¯½õáKë߉³Þ¦¹Ç˜®˜2æiù†}¯nÇìPÔB8àh±ëœ&EbLI©‰Dæ£Ëè. ¶-HdÖ˜)*@¨ ^ˆ1±MPü*@Œ)¿uŸñ’çcáñÉg_D¤?ý[ôü6{ ”¬ôÄYzLWL†C¦Œ÷^,ˆ£1¦8*ñ˜Z)@{m­”äy\À0 ¤pδzh?ìÄì®´}ÑdloZ?¦_ ç¤PË|*°ÿ¯û{ÌîŒ ¶7$¸ejYÑ‚~/ôA9‰Y®};v"ÑÙ@>›J}KÍÛb}õMâÙ_ÙÓ_è%3í;°&‰yež¨€­1&6„00v:dà!PáGÉÈJ~‚²Ñº¶C)ýHI© T€ 4EbLM‘¥‰P€S"ª™¨½yǘj¯(ÏH¬€ß“á©Áyáå¨@â Æ”¸*Ét†h¯Ítõ6¥pâr /`IH ”À- ®„„ý šÄ]“†ãwµ-ƒ…sâ+· tŸÜæ4ðLØ€/ØLÿLblÃÔiòk“‘â¸nÊ­˜,x… ð¶X¡piýÙ_~Úºöë~ŒiÖ–Îi-óˆ1å ’+,"(pŒŽðŽñx& ¨0^»bL؉SƒsÂN†wåÅ+¼$F¨ T  ˆ1U!JR®1¦”W ³¦1&¶ *rü®˜è)åUÊì×RbLµT“ç*¥íµ¥â÷e) ((%0I —dÞ͘qà–ðQöcÂI9§²®Èƒ³¤ oâ` 66±·á6)£˜åðx“ì{²¤ËÒ|x[l~44®˜„j¢C¦†Ö/VŽĘÊQ+_ÇbàeÆ`I6dª 9 ._×Ãò¥KK¨ ÉP€S2ê¹ ÍP€S3Tç5 1¦ˆÌKPº)ðù§œ|ðÁNVºç'ÿÔá`ïï8±gýŒº]˜'¦)Q€SJ**#Ù¤½6#™”bˆ×%äF#Ê ¨${ðŽoáI²+ûñþùýØÀoõ«¤”‡ùh¬â!/µ®TÒp'ò-Þao“¤ØSc³É«eZÞ3]½þÂÍ}ãü©›:IºúùïúqÍî»s&‹›ˆ1¥¦ªžQ‰º‹Ëb¥Ø·Ž¯ä[ <§£)åÅžY^ P*@¨ÀAbLlT ¿ cÊoÝg¼äĘ2^Á,^ŽØ·í îUSúä¨È,*(©1¦’ñ€*@{m Åä©\tGwxZ‚â .—@&T:°·]0&ÙWL-IŒ9ÙI ó¬€x€Ø0ýˆ¿%˜âä[õ( ±çò¬Ë^x[¬‹¬é8é¨ußÃ”Ž¼2—ùV€S¾ë?ªôâºRÆKâáRÇW²îš0¦Ò¨&7GU© T€ 4^bLלW¤IQ€SRj‚ù¨±Ęj,(OGš¦1¦¦IÏ 'XbL ®œ föÚ V*‹DR©ÌlKNüHÀ3Á€&ìÁ·0ÂÉ»ºHe™éd*ÀÛb2ë¥!¹"ÆÔ™y‘(@Œ©"fôaԄ©&ÀLØÆÀ ûÕÛ%öà#`&Ý“Q=X,*@¨HºĘ’^C̨ŸĘê§-ÏÜTˆ15U~^œ ÔPbL5“§ÊŒĘ2S•©(íµ©¨&f’ äCLð±„d;a3÷ã#v¶ïoχ*,ecàm±±z'êjĘUÌL„ĘØ<ÂÀèH¼1‰+&yÉÀ ò./l›)) T€ P¦(@Œ©)²ó¢T  cJD50µW€Sí5å©@s ÆÔÝyÕd+@Œ)Ùõ“µÜÑ^›µey¨ T  x[¬B¼´ÿ”SÚk0?ùrõß-Ü~Q~ÊË’R*@¨ YU€SVk–墥 ÆTZ#‘Jˆ1¥²Ú˜i* €`Lv:øù§Ô‡ PGbLl T€öÚFªÍká¾?õöƒo­¡T€ P„*ÀÛbB+¦Ù"ÆÔ•yZ(€¶JŒ©BòT€ P*@¨@“ ÆÔä àå©@ ÆÔDñyéz*@Œ©žêòÜT ‘ €^úó¿Y$ìš|Q* cbKh¤´×6Rm^‹ýÛ@E ¼ýñÒ÷?ÝXÑOù#*P¦¼-–)X–'Æ”¥ÚÌvYÐV§o>9Ûedéj«ÀGŸmÛõÑ‚/¾äÂÚêʳQ*@¨@µ cªVAþž ¤WbLé­;æã%'Æ”ñ fñò¥1¦|Õ7KCšùcˆÄCj¦íµ5“’'Š¡û·"ñ¿T† 4BÞ¡rB¯A4$¡Ãlù`[e£(WbLå*Æã© T 1 cjŒÎ¼ H¢Ę’X+ÌS àv Dä)¨@R Æ””š`>£Íü‰©Š\d„öÚ\Tsb Éþ-1U‘®Œ,Ü~1¦tUYŠsËÛbŠ+¯Ú¬ ©VAþ¾Q °­6Jéì\‡Svê’%¡T€ dKbLÙªO–† ”£1¦rÔâ±)R€SŠ*‹Y¥¥ ÆTJ!~Ÿ;hæÏ]•7µÀ´×6UþÜ]œý[6&ÆTy–8 ð¶G¥ŒC4$£›Áb±­f°Rë\$bLu˜§§T€ P  ÆT¡püÈ€Ę2P‰,BĘØ.¨@†€©àN?Ü¡"±(T :hæ¯N?þº<h¯-O/]ìߪÓ/·¿&Ɣ۪oBÁy[l‚èI¹äÜ7ÎiǵIÉ óAÂ`[eë(WbLå*Æã©@SX°`A?ûÕÞÞÞ” Ä¿èþýû[ZZâäP(][[›ù“M›6ÉWØ0÷·¶¶b§ž_Ï Ë©â\:Î18[ ‹sªÆƒ&”–¶DŒ©1M‚W¡IT€Sk…yªĘj "OA¨  U€fþ„VLF³E{mF+6¡Åbÿ–ЊIz¶ˆ1%½†²”?Þ³T›,  T€ Ø cbC ÉW G]ºtôäC™™ð•)‘žÇà‡òÑS=FÔÓÌ›ê…Iç9•ªóxÄ—#¥RÌz׋ªtšëiµîô`ˆ,µæ©M³.—¦½6—ÕÞ´B³kšôé¾01¦t×_ºrÏÛbºê«üܽ ÐCÒº¶µeE R—Ñ]°Ý}rw|…óµïoÇ66à_É·å_‡¿ Õ*€vˆ†Šˆa.İ« R¾’o¥­V{Iþ>» cÊnݲd™R@(Ð*@O„ãш`Àt„¤Á»øæ›"!lð+lãxuVGX"=XeÒH>â*Âɵôø­„´3}#éaBÕèWÂåÈy«òXR"ez$cz ͘ž'ƒŸà¥‘æôþú–̘…Õ‚èÁz9Âd¿ê)ù·OâúH&9L+B¤Võäç8›†ÿócLòάgÃÏE@óü‚%ÉåÔO•Ö¦‰1IÕ›d’Ô¾çüfÁM ýê%a1¦$Ôó@š£1¦æèΫÖ]bLu—˜ 5Tàóû…UÚ»¡ 0>bø({ð`?’ÐN —^ŸfM¯Óž©†™á©¨@  ™?•”¡,Ò^›¡ÊLAQØ¿¥ ’’˜EbLI¬•¬æ‰·Å¬Ö¬Q.0¨KÈpKØ/"‡,ضà´Óþ¿îG†Ãh¤huâ6 €Ú'&´F´XõÏ$ß*i‡„Àã‹ ø¨Æc¹²b;OµÚ@*6ðã‡~o1©Vƒ™O”Â3Yã“â—é‘H0áH‰kÖ¡Cópù¹§\8³8ûÁKøÿ%Äð`Læ¯<¾ #¸’¸Ò—8 Âñf´@oL7NÂ3éŸ4,¨œ`L& „Kk$úQ‘ G$’â˜P!)Ž HêIKg:sò\ÅQSdù¡y~%Òä‡&_¥ÕdÖ¦§tžJTN î©*îâ<ͦ®‰1ÕU^žœ $ZbL‰®f®rˆ1U®I¯€²J¸4¶wµ-€+&pKÀ•°!n™@/WÂWØÆ~…œp<25¾ÊxÅ&(ðán+–œ¤yýb 7áæÂž}Ûš%^2' Ð^›“ŠNH1‰1%¤"Ò}Öìúh¤é›O~¬­ƒ~ÄÆ_~š†B0)Q-†a†acºƒ4¾²¥€bI@C„OR^Û=f÷Mx/‚4„½²ÕÒQq†¼š|’ÆCi‡V*ÞŤ¡"Ñ!S:ª¶¹¬Æ$h…àx™„A3ŠUí5áפb˃T›þ>÷ x(èáaY°G}©Zâ•Gý!™ÿ`ù• â‡NO(¿ªc¿I\1‰S(Ol5Ø„Ã$œYíRÓ±Y‹Æ˜T19§ ]zþ8“,°¦BŠ`˜ÌŠ0)(‘Ýì üLNÈ^žó›ÅT:-Г–NF†ýç—ÃP¹Š¬%ùFŒ)ɵüQú*@Œ©¾úòìMS€SӤ煩@ («P n–'‰& JØ–sb?襥÷ÀñuN2UpQþ„ ¤LXÈ®ø;Ël˜ÞZ“²â0»)R€SŠ*+Y%Æ”JlT^ÙÓèR`¿á°Få‚×ɇh…Á°ŸÃ°Ìµq¼d¢KÊ‹`¿@!81¼$l‚œÌÉÀ%]!êKqæi´øVÚ'Ð%m«r<_TÀ¯@m1&=¿I€?0ñØÎÅÞ¯$îÑxX²¡,΀ î€_y~î9¿æûÁà`lÈNÙ#|’^T¾2Y l›“çüz¤rž »€_iqQúg⿯€ÅW„A ^†wl£± ^ƒ=&u$’6~‰Œ&ˆ¡ü<ÐÃ$ò_¢,ŒI.*ð N+DŽ!òcLÖÝ­{w)¯dXq%‰%'ÿ/u†„ã#0&¿³€•8 %RDR#%1&QLtƶÀaøh†ç“>ÄãI*CÎÍN@/*âàHþókÝáºr Ù#1ædÖ¦\T[…ÿüRjbLÕüù[*@¡1¦F¨Ìk4AbLM—¤+ ¬’ KxL’Xrò޶/²´Šß&ødRLÀžä+¾¨@ösm° mpçì—%l¢Ęš(~/MŒ)‡•^i‘áo©uí×1¦mïO¬ô¬üQí@’‰Ã°Ì5 JâÏF‚ÇIù„‘9áGôøÌ)Á%]!ê¤5ŠÛ0màêÐPñQ|2II4ZbÒ Æü5CÚbL~oLŠAȆØÔ…»»Çèn5l_Ô*ìû=~Ž_á' xÎoJ¨ÄƒÚþeÌÿzQÅ5„™ÀÏ£ 䄞_ýKyü øK¤ À"R¢fÔ-¯™)ÐV¥5*™„âIÄ1õæA‚üq°þÜωç&è¹>z(Ck°ä†Š8F)@!üðQQ? aqë)°¼RdáŠÌâ8”Pr¤¸&ò{YÓ™dœMÏéù­ ÊbÊaæÏUd)¸ðFf1õ¢ÒçˆòZ"Ïù¥txéiå'xaC~e_ðMÝã?¿'·IþŸÐS’k‡y£õU€S}õåÙ›¦1¦¦IÏ S V /0IØ¢—Kx?°·]¾¨ {ð>™°G¶Å9SWäO¨@*sÈD©¬ÎôdšSzê* 9%Æ”…Zl\2ÑSã* WW sÈÄaXæš‚pÿ€û%pKx—òM~m2H $'Pöà0l+J’9%X ¤+€æ'­QÉf’f WLJ/I+EÂΤ‰ùkž5ĘÀ÷ÀT6Ô‚Žmq©"îR$ª”Éa(´ ÑĘü˜Äµ‰çü¦Êù#1©wÁ•Äý ®®yPŒÉôX#Žd<SX‰ôHœÜãý¥yµÍ+S(Lö…JU¯€@“8cªþä991¦œT4‹I ÆÄf‘Qˆ1e´bY,*@¨@Îð;d¢€œ7‰ŸSDæ%TbLl å(艮˜Ê‘Ç–£€ß!‡aåèÇc© T ± ÔcRw#JЬl“N€~à)ßb¿crBBQDcLŸ+þó«Ô&<$WÑkIfô%¨ä_ÞcBnM*’1Æ„ƒ=%Òü‹‡'¨æo&±­‚˧ø#øåSŠZ•Z:C¼V²2I‰1U¦E² 1¦,Ô"Ë 1&6 *@¨È¢~‡LôÅzNV™ˆ1%«>²žbLY¯áš—Ï㉮˜j®0OXPÀï‰Ã0¶*@¨È„õÀ˜ Œ¸;  A…—„@ô#÷Á»îîG1 ua¢{$¾•ü\b0yÎoÖ‰òFz݃ éE5º“DªŸL¦7&Í¿‡…’ð[%ßQÂ0™ T&š A¨hĘ$4/C¨1¦V ³T ˆ1ÕBEžƒ P*@¨€é‰>XAÙË1¦ìÕi’KDŒ)ɵ“ȼy2ÑS"k)C™22q–¡ŠeQ¨ 9W N“F¬&Aâ€ûèB¾GŽ”d|…wÀFê!IÀ ý9Î _ùϯ*ŸälâI1&q³„¯ô<ø;;tè G*ÆdfF*œS€'9¹¿D ]É•»ÊyKcñ© å*@Œ©\Åx<ÈŽƲS—,I‘Ä˜Ø ¨@†€Esêí?y?CEbQ¨@ ˜™è  !ùÓ¸ cŠ««…Ęj¡bÞΡ™èŠ)oUß„òš™8 kB4ù’o¼tß5MÎ/Ob(À¶C$R¤@­0&¸,òDMÂGñc$þŠÌo )–„@;yöèGù•çÌžƒýç— G…ƒñ.{<±dîñ Å Ì¿:j2³d)‘騿¨ T ˆ1U B2¢1¦ŒT$‹áU€ÛÈSúÄíjß¶ ‰E¡Õ) ™è :ùë¸ cŠ««…Ęj¡bÞΡ™èŠ)oUßœòŠC&Ú£~“¯:jÝw¦nêÔäLðòT †l«1Dâ!E Ô cJ ¬ê{©)y#%›šru^” P*ˆ1e Y*P¡Ę*Ž?KºĘ’^CÌ(CbLeˆÅCó¡€8d¢€|ÔvóKIŒ©ùu§cÊSm×°¬pÈDWL5Ô“§ŠR@2q–ËVB4$—ÕžÊB³­¦²Úššé cLñ­Y/¸€jnšUp^— P*P+ˆ1ÕJIž‡ ¤ObLé«3æ8–ù˜ž}öÙN‘¯Ÿüä'ÿþïÿ} ¿Í’Çü÷¾÷½è|òÉ»wïŽõjöAïï3¤#½15»Ru},w‹nÿÇsLÉÿHÂû„›N;4á9ŒÎôG-Dƒ»[ªÚ]v3KŒ)»u›Ä’cJb­¤ O[¶¾vû=W¤ £ÌbúøôÓOû_}AúËÁT¢À¥}ÿ¿&QÉ/ù*ÐXz=úÍÛŸ<´±×äÕÒ­À ›útëÕ¦âtƒ¹/_aÆ͘1£üßñT  `èÞ§O¼§#»ÌeĘØ.¨@~ ƔߺÏxÉó…1]tÑEW^Ócüä™iÒÌq“f^qõ N< Hc'Ò˜‰3Ý4cÌD#M˜1ÚHÏ>7]Ó¨ç¦[i¼™¦?m¤‘FŒ›¦©uÜ´Ö±ÅiÌ´gœôü3cžÚHÃÇq°‘>QSËð‰-ÊÓS[žš8è© N:a ‘ `§ç éÉç6Rÿ'Ækzè‰ñ=||¼“ÿ@!ëÝoðÿó÷ÿãþGÇÒq÷wŸ•ÆJúî÷¾Ô#ù=Áûï¿ÄQÇþê‚ßã‘#ù¹e¢ZËyüÆÛ%Ú} ¤ÛûÞ÷ý?TûCO¨}à³fu€Å½Ÿv}#Æ;ýžÕéyú½ Ïß×iG÷Ô³á½\Pçسi·Ô§y{³Ð~¬¸Ó,¢ï*ê¸|½–Ù_ýË÷¾Ù ·ßÿ˜ÑM¡Ë2º©swîn iQyÏ1¦¼·€Æ–ŸScõÎÆÕ¶mÛ†áb·‹.åp1šäRÀÒ¹sg46ŽR’\MuÊ ½gžsz›5kÖÔé<-¨‰ ~zÒ©HDj¢gN™·<Ôr`åÖÆî"· óÇÐýÄ“NýÓU7aO’)½ÕMŒ)½uÇœSj ÆT­‚ü}BÈÆôРÇvîýÄNüé¡ýúü w¼s@Ò[’ÞFúéM3íùx»‘¶íÞ¯éÝû­Ôn¥­NúhkûG[w}´ÅH›w~ä¦_ßùáë;œ´iLJNzëÃ׬ô¤oÒ†7?ذ]Òû¯JÚöþz#­Ûöþº7ÞCzEÒV+­Õ´åÝ—´fó»šVo~wõëû$­Ò´i_[!í]ùZ!­xmïŠNZ¾ñ+m°Ò2M¯¾³ÔIo/}õí—Ö;iÉú·­´îíÅëöhzñ•=š^xeÏ k‘v#-’ô²•iÁšvMó×´Ï_í¤y«Ûç­Þ5o••æjjÛ5ÇM³Ûv¶NYúµøæì•;giZ±s¦•vHš±|Ç¡‡|ŒÉžIé8fêBÔ#9hšJh›¼l¡©\ã-þÎpÇ^§Àtô±Ç™¡ö„}`@hö{»´ßûHû=ÔÝôuE½\xçïÜœž-¬O³;´åVòöfÚ•i?æïÄŠz0³û*î»ü½–vYÚ_IgõƒýÀcãÐMI²:«VÒžêúÛ¢0)ÿ-bLI©‰|äƒS>깆¥´¦ŽÓ®Áñk¨,OåS@¦Gž‹Ævû=ƒ8PÉU¡÷¬sºb¶aѪ7~D’)WuŸ¶Â]:ñ¤Ó–¿Ú¾|}{§Ÿ“dJ[ý5#¿ žykkkëÒ¥K`AKÎRêo±Ñ±cGœï%Õ QÓqM½µ-cw‘Žc.ËSÀf˜N“¡{Ë“cH2•'_’Ž&Æ”¤Ú`^¨@c ÆÔX½yµ†)?ŒiàcJ)y6`§ÐƘb¢K0áoC*0dŠ˜lC¾Ë0ù&‡aÚh0LÀä2LÀ›a*`L[Þ[Á0m®˜a²­þ¶á¿À0m(Í0U…1 °€b†©ÝË0­*0L€0¦b8`æòt`L˜IùñO:Žº“ÅxÞ¢qÉ•$™Ö‹¦ûBÀ˜®»±·¿Wt¸¥wÀýÒÑÇâ &8ƒØÍ€~Ï 6+a˜<¤fPÿ¦€¦2L«‚0&å2ý½™Ÿa‘1)…€`šð¥I^c—Š1ÁSaò`LËwcJПS‚*#Y!Æ”ƒJ®aÁ0a¸8cÑË.ÖPUž*Pa˜' kcúÜM’)/E ½k·¼'U¿°m뎤O¦¼Ô~ºÊ) ÓŠWw[muó»K×í"É”®l|n›2ó¶iÓ&IA&õë×/Z¡—pŒÒKØsÈ!‡4^· \±èÖÆî"5Ê"+`1L¿8ͺ"É”ÚFBŒ)µUÇŒSª ÆTµ„7“Ãn=aQ7hD޳z?¿ç¹¢ß+t}Žû%7næ›h ¹˜N˜LR³ÏV²Ÿ·5¡[“T~,9ÇSÕ ÓžàIÒˆ+&ÇÜ|7æ¼ÕíóVï2]1®ãvaLÅ=•xŒÆtö¹ÝÌ> Û$™šóß'ÆÔÝózUbLy­ù²Êí2LkÙ.ÞÔóÖ²N«c„Ö°áÆ–žkù÷TVŠø¿ÒAoÉ`.ñÏ=Æ#ŠéÏFDÆ`×Ä·bݬÇK¦G‡x6¹­ßÀsÏ¿ð˯¾*+ò /Øn#ì”uÂì>*yÑT?×¢™Á0i0wùæÃ|ìò•«Jêà9@Ÿ+aà÷4`QÌ|êDÛ(÷¿³¦äŸXVæ+è ¤Œx‰;¾ê¡€0Lmwk[Å3£x(Ä|Úê‹kvÿ³S&M™VîÕÍnJýß ›S%ÒÞ°Ó3ß"ÇÔ»—.·D<^¨ßÌ0# EÒLïJØ–;†C‡€=8RÛ’bLدm Ûr¤d[Ð(­Dü\)¾â+࿵դ»ÐQ þò¨J³Ã—»^ž¡Žt: 6ÇEr¼|•êDüzᑵR@¦è¡ûÃ>ùÔ3|òI­.ÊóÔ[bLõV˜ç§ÉU€Srë†9«JÜaL÷=ühÁ¯~•\Ûü}ý-ŒI‰%ÃN_ –¶ìZòsK›w~Š.‚(9V|ï%XôÕ–¿a{‘û¥W‹&ÛýÒ{’0e,î—"<0ÉÊH¿¿0Ùþ´1‰ã&ÀH®ˆazõõ\²ôÕ·5ÓK@—$­³Òâu{4© l¼€´Ö"‚!;0Sd,¹X~˜À0!=#Aå¦@Œ „GU»ZüXgRÌÉbϵTJ÷Ë{”K2áAÚœ )9,Íf±0?âyêÆŠéËû÷„ # Ëäܳž¬ZæúÆtC¯¢^Ñ@6ÑŽ?ý¨cŽó@Kþn0]Bè£—Ìøqf¿gõx.²ÈkvtÀd»"óL& ‰‰i+ÝZ[—éÇ´ÿ8š*òÃTÃ4·à:Îò'“ºb2ÃÉE`LðÌ”ë–ݬÂcj–òù¼.1¦|Ö{9¥v¦׺ÃEð5íµ.âN‡ábe$f5P¢QŒµþ¶j¼bˆy-Sa˜V½¶'°­¢§’njÑêJH&Ôš¨´(ÁSdÒÃì¯8ÀÖž »Þ½tL‰x˜GºÎ¼¡yh›A“þMú1cÂNuÔ$¬R Æ„3€ž4û@óŽSóÑZæ›Jô­­šîÂÕ˜Õ-q=}ˆt#r’N @1&ívpKõ@"óÍ)T†©äнÿcÏ’dJ` †e‰SŠ*‹Y¥5V€Såé’¢@þ0¦þz})‰G%;Ý×È9çv •‰¥üÐR‘Ë%›[rí÷‘èRˆï%/½ä`2é¥`L>€Ékéw¦:aZüÊžò&× `&ug2ßrgb§UENM `—Æ’† X€bLJÌ´½›˜Éï©éfRŽ´ý0훀Cav)Ðc¸¬<’)ÌX‚™s©¦H°G׌â+6&Y3mBK{ô·²ÎU®%=¥¹ì,>ü””^6ÙùÆtõ ½´,l¸ñ1GŽŸvÔÑÇiïÖ VLmFÓKa®æbLïÍ s/Wä[n£eW3û4À„ÿQÇT3ÄT ³b?L† =UcZ±3°§ ôÆDŒ©9ÿÊËs†Àæöç5ôF­®±ÑŒ¨g-}ý‡e’LÒ!HoãéjÐ0Ðÿ˜t£ Vzþn°þêÏÍ>GþÔžz÷Ô8> DåwÈd¶.ó/o¶.O#D6ôTfï$Î6¤=Ä«bÞ x˜*  S¨ÉÖŘÐV®zë¸ËóÉ„~Éì½¥› Ę´ "q’ðöYï™7ô` bÊR@ôþ rB¹‰VÒ%â%{tȤñæt†™K¸ÈÉÌž÷Öæ‡³îbA™Ý…gT#(jÙëË]ÏB+l»f·Ã‰Ód¶¥dæJ¦øC÷%ɔ̚ È1¦ÔT3Jj®1¦šKÊ&CÜaL÷öâ·Çë|ëÍS©Çõ±d8) –bIR!j’Á-½Uˆ$A”L$Eaã?.8r\±ï¥ôR€û¥!ä¬dÞreL®É†ÿõNªÐ “Œ ¾— iM{‘¦Õí —$iT&30“—a²é%e˜,Œi²å)‚aJ 7&™IynÚ 6áQðÛ_äŠÉx¢F-€·ø}9$“ç9YçÖež“ñ€-Çèê1Y¤óÈ:u"È#™Ôóì‘)i™ƒ–‹òHožM{KY[Fû5¼}XÓõ½(%70"*cò,s %¿¿%·÷‹¦6Kú^²Ú¶Ý¼ ~æÜ¾®l€©'LÑäLrážäŠÜÈ}WÁ‡\D,9?ÄþêPñÆÂ0…•#ÆTÿI§"ÆT†X<´jˆ1U-a†O† ÃÅÙ/®5†‹A®˜\¶cu.–E2 À$c9Óש ²¾ÈxO{22ÄÐ;Ù“™âB‚¡˜KÏ^ÁÏu1ºYý§Õʸ"Î&¾Udä©™D¡äÒj~FõºÂˆíÙ?j5ëñ| ƒ[üDx3Ú ~…¯Äâh’‚2h1=g0ÕÓ²ÈEýlÄo'«òà0LO[ “çÙÄÊ%NSáÙÄÂ˜à—·÷eLƒ xBe©Úø(„Šh+ÇCaSù‰I‡(d 58Þl-øè?¿jåùJRp9¹¢Fèµ¥NÅ“4oiuÒ¼=fËt=ï†^.é'Ø^µ3Ï|iSY$“ô¨tyÞ4A"©M©;H*–~©VÏŸE üòsóOŠ?<ޚϞ¸œÇiÎŒ#=W|Œ•çYù§ë?×Ó,qÁ¤ahïgþµIWù÷äÏUƒaŠÛVç·½YÉT%ÆT¿^šÍ 20ó&÷üße"éÐdX¢Ý‘ƒwéÐÿȈHçåð­ÜeŒ[êJ0W¦j*~UÁ­­¬îÂ3ª‘q‹ÜL}„i“Á¾ $ªÍnG›®D*šDÆ2é0LeÝ2Š>™Rш1¥¢š˜I*Pˆ1ÕEVž´ù äczhˆaÿ°àEÉŽwÏCƒ1Yz7’gÃA””UòºY*KV¼$´äã–Œ€q6·€.Åt¼TVIâ+Åt¿Th©ÙSh ¹r0­‚ï¥BB`&ÀdEhZ±óicÚ1s…× “:dJ”7&g&eºÁ0¹«‚ÄN šåZF–;ۓŰKÁåÕï/½!ft9L|tèÐÏÃò’fa—éxu’)xéÏô+™nöì÷ï1§hå·æÙLóºÙo~Ç™¡cºêú^è d’Ä´7ZÇcêhö„Þn0ÈÕ\Ü@™>^Ó<.’^ ‘é„‹0m|'` tÂdÄTOr¡0•a „/•¼œ»j—$£Ë²bÉ)piaLCÆEЖôÆ” $1¦UF²BŒ)•\Y¦ á¢„Îï8æp1>ɤã48[s\‡~bÔÇ Ûbu“ê${„KP¼FMt¿I†ˆæàSL>²'ð´r•è+"KþLŠíG²¤lŠƒåºøJ1&ëʳ8ŒIWÏ›pƒDA‘‘U”WmTz~†ðŸA/gêé©QOe´xUÖÒð«†ÉllÅ ‹øãÑÆÖ뎇cF—ƒ泉È%jˆ†ÑÁ‘T¤¶"GÔL("C9Æl-8‰ Gžó«Pþ¯¤ ð’ a#†ImR5x&OlÕZ;ØN×óŽzÅ —×Þ…(D®ôlpÆ<}ɦΈ]N°Ù’ERQÿAùkˆE_ªÕÿg‘¿’4Q^H5Ï“lüÿ‚ÿ1Vš“¢úO÷4Kyà•ƒ%Ÿê»K®.'‰ŸYRe˜L´Wž%£ÛêÜ• ™Nž4eZÉKHÓ’N@^rwÀ†‰&H£•³is5OŽž¤¶½tœœó¿™y«•ò~Gqµ:sÏSñ­-~wNÀì.䮤£Õ\o"‚YËô¬çîàï.Ò5Èakz‘¦ØC÷û“djz–Î1¦Òñ*Uˆ1eµfs_®ÜaLw?48Er±$|{ö¯»°ÍóÅñà*±Ja¸RX*ĉûÀïoÉÏ-¹A”bx]²' e®P“]zwµß÷’mÝ7è%¯û%Y2+–ìXKHïXiƒeí0,vzÛ±÷Wàé•=/¬E*raâqÂT \‘&øa²¢È•å„ “¸6±1¦oD0L‰òÆäIyã=x¦‘Ù·Õ¥&à€Y ÊÕEñH&ÓJ$¤‰É cR LÌ)¤“t2qlNÛ©UFžÆå¥3þr]sõ×Mçɹï½k#0¦+¯ëÑ+c:òèŽA=áèý4‰{93Åw5g;^*Ã÷R½+„œÛ³vkn‡EÎöÓ S¡3øKoÌâ^«ˆa*vŒé> c ¥-‰1ÕæÏP“³cª‰Œäão„/×s§9\,I2aȧ»¬ü†¼¦ýU!‘{F˜2ðSÐÄÃ"˜žœä´æÏ…°—=§Õ±¥iò\Q‡¦:ŽH&ûâ9¿ønÑlûG­ú[ÕD[¾’A¯™a¡XÄàIÕòdbRz¼ÿ ~õ´"<lɆiM¯òïà0LÃÝXr³ÄÂ÷lâqÅä4¶—wßü—þ%}2)Æ„<‹ã%)YÃaAÄΧfB))öHõÅÁ˜Ä9–ÿüfmê¶´+yÒG%l´ýËÙµA)„rö¦VÌ´<ï˜w†©.éÄ@ZV×ÀkéÔ^‹ã“Ƀ1A:é 4rd4ÿG¢³ÿψ1yº©²ÿc¬Ô¯ß“§YJÏ#]4a³d[ÖŒGjšNæJÑK^ßrÅ[€W9¯K¹õo{pLõÀ0 &¨iM»2LÊ_ÚQäÚ=®ã"œ0‰Ç8ôT‚1EЖĘù—)q-bL ªŒd…S*¹¬"*Ã$Ïò@¡O þèÊ•X \WL¸—9ÃÅK® ™üŒŽ 8:®«¼gà'e< S®Xv1ü I!9FÌ6Ø/ŽLÄÅ…l/2@‡£þÓªtW”o&ðgוK#cx†Á’m¼ûG­ø‰üV|ð˜5ˆÂrIdùJ\òÑ" ÈuÍQ±‰1yÎàWOÎì`Ëåje †éÑCˆNÎ _hû¶T8@ÛM·— ™<?e>Tm݃š’¦"Ð’ì×VäiEE–ÊUšD+ÐÐ~­PÏWP°$%lp9T«<éˆÝQ.!­-Y*W·¤ÂúhzíõWFW#¾QÛ6Ù¥&bT‚ µ?yÑk?øÑÑËW®Šèë<“y¤þ¡›þcòüYp0ZªFëNz!¿7&Ç•Eàc¬8RŠÎì Ìf)ûÑT$øhZ©‰1•uã‹>X&gÎÍl«®7kA{-äe5¤­Î\¶íØN%|2bLr»”ö`vør"ÆTÃê®É©<óV“<ó$5Q êÖVÜ]H¤‚jº‹@ŒIî².T†1Š+¡£Ð!±ŒO´ÈĘjRûy8‰0L…¡»¬–wcß숅ÈãAC÷{ZFdJl³!Ɣتaƨ@Ý ÆTw‰yæ(PcÂèÙ|5'›5ºêE]ÔïÁ®Ï¤÷Á!ic|¿éü«®†y%–lD)TŠÀ•‰%´äŒ#ÍPqbèûÀ5ç?1bJÏ>÷Í~éUE—o|çýCf-yUó(ºtùu·˜iÑêí˜Uô8^²#ÇYþ…«¶Ýxë=&½´ mÛ ·ÞcZú[†OD‚¥_Ò’õo· ›ˆäñ½à~)Fü¸…†ùßãÉJ„ ˜” €I˜€ê1¦¿~ñ~šgèit&Å?ûÖgØÊ?[4nÑsÚvÊdñèù[ž·eÔ¼ÍH#çn;02ÂûËo.‰"™§nÍéxäÕ<Ù˜‡•)`™…×)xÙ/f-ñ¥äß#Fý­9u‹ _Õ%Óúõn 5?¿1Ýìé Í>pøè©@èbú–sz¿â q½ÿrŸv}CGMé}û}ó–nTsS殼ê†[§ÌYá Žyåõ·Îyiƒôx@—zö¹wñËoJw縗‹ŒŒ9ýÅõ—]{‹Ó¡—B¼Ê½Ùj+™“Ç™\„&ûÏõÇ+{: “‹`bOt¹¹m»\†i§b—³Vî´RÁiœ\Â!ܽÕ`L›æÕ¼Ùð„¡ cbãh¤Ę©vâ¯e0L^°`äÜ-Öpñ©·Ù鮫124‡‹Ï½ðFa¸hßÈt¸F2a8ç1ó Î0®3±"jÈ$qM¡cŒ[ûbè5Yɵ[,\òÞQ/˜»E&p!ÏÌ~ýéY¯cìmw5Öc騹›GÎÙ¬®˜„`CtøI 7F“Lª‰_ÙÓþYäÿ%j›pó_,—ˆ‰1á<ž™ùÿÒN ‡é_[›%.$ÖßÕ˜ù‰ù—Ì×aû¶Å,¯0Lm÷HOeÛk´O—÷ŒZƒù+´Õ± ·Ž]°uÌü-ÒV%ʪ,_WLÚV§/}#šd’J÷gO€,ÓŽ‡É‹çøˆ^:fÁy˜WØý[ÄÌ&%pk31Í[‡.Ÿ´x»yw.®Ì™7VV}ˆ]õE·¶âî·6Ô¬éü^» ¹µÉÂѲº ÿ¨FuÀmBX[s.TnB¾šcì÷w;MHÔ·.yö0tÿâËOãH£ “è³Â½£Ö˜‡ÏÜ3šðhýºšdè~×@’Lq´oÂ1Ęš :/I¢1¦„T³Q¾êu[`$›•3•À˜Ä·¿¼0ŬKÊÏF"~Œ©ïýxb™ñ-få"(6ÒøUˆ00*\@l8{¾~OKΖ:ÿúÂÃŽøÉêÍ–ÿ·Ý¯ÀÇ+®¿å°ýD¸¥ŸžtZç_]\ {f.~UfÛl\é›ßþ®bL—]wËÂUÛÅ´o£K½„F1ð7燅 áî‘ÆL[zÆ9]ÍÈqº¦7è%'­{û’«{!©Ï3x\\÷KÅñãdªHS °8  €ÌÀ<˜L§&Õ`Lû¬™µ¥óÂíÕµqËLʸçéRW}ÃLJ§k'‰àúG–œpͤ§gmš¼xû™½§#Ñ{úñ×L:£×tÿd±±úÍÅ%|2Õµ\^¦!ÃÆ‰Ç/Ó¯ƒ—œuË il—<´è¬[¦c$VÔÞ®žtõ Å…Ææ2sx6éÑç¡’Ñåb–…‡•­@¯ï~ÑÁR€ ½gY S•T| õnÙøíñ9Æä·]!6~ï“©aã3ª~Âü p>í“©ìñYUmupçƒo­‰.&ÿÒÖcJùdʪð).×”>ï<ìàš‰ÑEˆžyü&ßÔÕÚÌ%.šø¢ÕÅaæÍš|»Úš|+J­–¡gÞš×vª¾µ¡Þe%€ÜÚdp·¾sÌ[Ûó/½é‡³­îb »‹æU}>®ŒA{ëÚ¯¿²§4Ì$ †îaf³sƒ=wÃ[†.Ÿøâ6§ëeõo§÷šæ<'C÷~$™ÙÒˆ1%²Z˜)*Ј15Df^¤ `Õ$‘̰ì¸\\ë&`(ÓÛy=2Ú€sZÓ}øcº {„Ô÷¾™˜ LN$™¶s'ïdöÖLêe¤°a³J¸R ±¤HZBê?d¬øHâ†~1çßqÿ³~u!¸%Øû-niÓ^!–L£>lùÊ-©×¥i/¬{zÜœqÓ—Š]¬½†iØX cº4lìlÇÆÿêÛ£ŸIü”<5v6’…1]Ý[|/ 3I0&¡—FM]òäèÙ“æ­•àq#§,ÁÝãÏÎ1e é½Áãüô’0…º_²ç4™ñã SÁI!„œ?*SeÓ+o-ÀôX[¤ºbL2“2 “¸{µ#ƒèì›5“rMa&E&‹%>*kþªvL¦ž¨µõN„ºðâ뢣Ë5à_ÉK4W`L—]ssX§‡ýOš‚F¨x»ÁÈÞ^—À'¡¿’v«ýöHw7iö x›3Ãb ÆtsŸ{¥¯Cï×:až K­ÏÍ}æ¹¹ÒËÝqß`KJg*š‰~ŽåÎ<§›I/¡3í%¥—г¡CSsÊüWЛ=ûü‹a²»2thèÍFNE'¶gÖÒ-‡þðHteÒ=>jRëä%Æ´¦ÐÒø9k5sÜœ5B/aLcg­>Jׇmø–9ÑêÊÀh±\ßû‡h'ÜÒ·¾ýÝ ³–ã}æâõèëг]znæ2l€Ô<óWÝ:ýü44{0Lذ¼.¹]æ•ÐÅ À„NÌõ*÷ú7 ˜gœmunx Gß…"ýÛäùko»»èÇЭÝvW z³Cx¶/¾ªçñ'žrþï.0ô9tbèÊðoúyÞï.CØ8°JèÖà¸O<¥ûÖž;ûÀôOÀ˜VíêyçÀ?ìÈ?\qsÇŸžÒóŽÂ0™äe€Ó87äee¦/®ý€‰SƒÿƒÄ˜,xÎ/GŒ)ç @¦£:ÎXô²=\´ aÿpQ 0ÞKܯ*Vä=0—¸bÂp>Mq?Âp±®$k2 ¨-$ f†ið°qaÏ&æn¼D½cºí‰BއG€,㾲ȳÉõ·‘djFsP[oÌd1LçtužÌ~S6Œ µïÄçZ°åº–Å– Ì6ôÂÆ¯O¦ö€BäJ]]ƒ0Êãç¾J’©uŸ¶kzÚªf²¦“N[±a·Þ «í¶* c,ŒiÁVa˜ðÀxñƒ ï|f•N.€G±M¶h«“_Ür4I¦5ŘB`¦83oh6ðP‚µšh90ó†RöÝÍê↷qæ-q¢ê[êÝE»È£â¹ŒY‹z ÊlÞÚØ]$®Ud(Cž¡»f²¦“N‹º  ‰0Ðp¡jq½ÞÄ!\ï'—«oÂî÷/üËð63άÏT³Â“dJV«"Æ”¬ú`n¨@# ÆÔHµy­ú(†ÉQ׉…1!|{ÚÃɉ¤À˜î¸·E©#ÿ¾=ëœ <Š¿†(é~‡Ur½+âJ²,Ì5É ×:a.’K°å+º$Û-Ÿaø‘ÆÍXjrK0äkêôóSÅ´?å6<}Í_ù†mæþ{=#þ–°-îI`ì‡ÿ©1Æ%x—@K ™`쇫˜ù%fÜù]t Ž—`æ·\•¬Ý}×€á°ôcê{f¼´ãÝkzÝ«¿]’ùÁã¬èKz©8x\P®û%Ìß“`’)þé›OÞõÑ‚š§o¯=â¨cÇN]èÁà¤åèìfRºõ›+>± §Öb'˜¶ôM{­³±ˆÐ³¶Þž€5H2Õ§ËMÇY1]zõM½¢´½'GNAS,ÙúûÀ+¯¿µgŸûÐõcB£ió—Ò€N‚ÄuèÐáŠën‘€“ì9e; æ&+&º»›n»§ÓI§aC0&K<Ò*1Ñ›^‚W¹Ë®í­.—dㄟŸúÈð‰èÙ@dÞpëÝøS€ÂìsÏ#Ò³f‚&œ_:´AOM4tz*q¿4{ÙVlã¿óîÃ¥C³z¶—wƒÈDW†íšžý¤CŸÖýÊžâ{iÚâÍ —îì? Üz0`Lx¶Çû° /â Ê ¯c;`òz`2{ª˜Þ˜‚&™«}Sƒèÿ3Gðyý2Qz+ðìV{›p³å–‰)— l[ý"îÑÓ®1é%Ü‘•w—»* 0%jzvÞf.Þ?æe`"‘Û  ÃEL5ñò„ÉQ`ÙΛͥ˜Éa˜žñlã®s²˜Îx²ô`[yïýr÷ª•ã( œ †ãÙÄ!™Ú7°gkœ=¾î…à ÏL6ÃT˜$ñ@!v 9Ë· :3>j_&÷ÉÔrhê\©f0Œ~’iáìÆ<—÷ŽtËØV]˜Éf˜N]þj{Ô[|[”E€h«cl†iÆò·¬pr¶»ñ”à²Z0Ù¢­:hÂø±é3'íØïú7×3¦83oh3VØÁ[¦cò -–Å%tá½(œ\É™7„D̉òM/fÕ·6Ô»‘yè EÍ•áät%€ÀÙÚ]ŒŸ469C>æ$ Ýf²¦S‰ºã9QM¼ƒaÂs_×¾sÀ0!É ~45œ\ÄÐ]H¦û–eCØ´—bó{Ïâ9®d ðt-˜K*@ÊR€SYrñàä)ÐÚÚèØ>Æ„@tžXtÉ+`¬ Æä™è7­ï¹·å̳/(É$ù|)ÁR°G%…N ŽF VI¦üŠ“e¿o³'V4dÒY¿êû=b'Á?~æ²gÆÐ%lÿàGG9Ð’½ÀúGž‡dõÕ‰Ä@L%€•‘VZoL‚.Ip%¼ƒ^Ò€q@—e $Ð’DYÆô„½Î~àx >Kn Pìýš0M‰mD\Â`á–c’ K’""ÇÅ¢—l¯BEî—|¾Lý0ÉÎ8ÓáG5tÑñþi}Ùóøª‚g¦°c*Øÿ‡ñ̸YEœø?·ÛÚŒ4ëIÃ]X?xò«Öì›m'¸fÐâ«-FÕè‚WKjÇUam½*sÚÙ¿¹÷Á±þE<([ cúÓU7EtzOŒ°0¦ˆìÞÏÛζ}ÈOBÆ$VXL›Ô—r¦c9“Δ¶mEôÍ`@—n¼íttOŸcù–³]Ê¡‹ƒ'9$„—rnz{êÂWp¸%$q2‡?:1™Ò³I4Lì‘M’Ùqa½ % ‚ (!ä°Gè¥Þ}aû?;ô<0¡tIøK˜@/a»¾ùÏ<3]Ý/Åïµâ`L›ÿ÷“³TŽT€ P*9Þ¿¨Ãßÿÿ9qÖ²€á¢‹‹_#î°ë‡ÉuóĴׂ±×ç„9Š>éô_wíýW0¬åOR¡À£†»YO†fî—§Ÿ}Oÿ'<ÍæÐØ®d‰˜ú0TëŒéÉå]ïœ_®VÞ'¦mT'òlâ·öI“ûýå=¯üáÿýå%ÿ‡7MW`A¿ßyž SFW(Ä4ôŠ LÆÞÖ“éÀ‹½p›K ÉôµøÆžßÿ§¦œHï?ÿ_ÿßÿX¾¾½ÐS¹kÀÜ™7ë1Sž1Á£Œž¿E¦È®´©À0™Þ¬ChKA¾û½ï¯9ï?§N(f¸ À‡ÅœyC›Áä›Ä’ôۃcת«̼¡‹+cæíøÿÆ*hº1omÁ£h3Hn9ÝÅŸÇüçT ™É´(1tÌtÞ…§ÁÈÓ¬@søÌM}[W?5cÆo½žX†¡;ð&tnVÿfûÑô Ýá²W@=IX„ðãSþ¯GWþoiQ/óù|å퇳e¾`i¨ˆ¡1¦"ñ$+oJ*çÏa,Œ)ÐS’K–7`L·ß;ÈŠà˜^ßwû=ƒ€1™®’¶‹°$åK\Ê$Щ’éhÄÃ*)´$ÖÄŠ=·‚4äéI—]{ R·?\Û<ÌùÓ^Xg¡K¶-Èð‰ˆôü¢uA F}˜íM£>~¥Ð¸%$ì¯$bÝŸ2ÿÁ•Ôº/sÍ×õ¾Ž—`’w a±bûÖ»Z-]²ü-ÁUÉË»oéׂXK0óc6nÍnpKkI ÿŽš {¿—^² ÿñ#ÇEù^Š F2ÅÁ˜À´N1}ãåO¬ú;ÿ0÷¹ ‡µíêSó4dÔŸ~ ×Yëv9æ—^R€IZfRd!fßf,{ ÕN`…lXðê."4äz¤uæQG·jÃŽ=ï}šÆÿ5ó\‚1Ƶ”Þá,aºð÷„¡}  *½¸æMxW’„ÀpxGl8€˜Âh>úÌ$Йˆ'.—ÔÉ\`4Ìi‹Ö‰?9éÜð.}ÝçtësÏàacç\z 0&‡ËDÿgK‹)]Ü:«‹ƒ¿%íâ¤gS.}ÜÈÁë’z’CŸ†® ÿôf­“—ØÓ‘N?&Ó3£[7{ è%ôiݯ¸Y}/Á7|‹@š`B8ËÓJ Dj†©»Œ€,Ë *·ÿ¡3þéžìõíƒL SàÖCÞÜÁN`¢P`À/>wóAË`Ê¥ï¿!d¸è,‡ë­pŠ3t¹ ÕyÞ㯞äGÞ=aôf„U¶'þâçã—ß³àõ~5÷ò„IP`æ–³'ô§nê„EÉkÖ¬Á€pQÛVÿ³ låöéY¯ƒ qš46B,ŒÉFÆÑÞŠžMV Ãðl‚´£Ž:zá#··»çË\þµ›Ð¥_ó߯ǃh¹¶OkÌ“-Ð*f% AW#O¦˜|°0¦'œ¥ügôš6váŽ&ÓO‰ƒKZ‘+5—¼·× ›G=ðÙ¤¿4A¶·ä+ØVásenÿƒŸê<Û*½T˜E)ܵ‰òì¼-²´ÝÔs/¼aûa ñfmDYÕ¶ ŸÖWuÿÚê‰w²­&Z<—²ì¶/xðŠ3ó†fƒÙ6JÁÌmø™3¿ÕÅ-p»¸¡2óväOV=yçžqw'Z±ä÷1sXÅ­ÍØØät­aRϽcøªž[êÖ†î¢ûU¿›²æ%ÛîLÂyȆaC÷Y[:ï;°fÛ¶m:uz~Áꈡ»šÀ0!¸ª,Ä$¾ áŠiÌ‚7†)rè~äÑÇŸÙoöÆ{V쬽‰$õÕ°RŒzå;x¦ÛùÑÜjŒü- ©T€S*«™.(pÈ!‡Ê c ûqê– ¸ ßžqö !ù7|Γ‚|)Ù‘·›ü…ƒa¦Ä¶?fŒ P*@ªS@†‹/E%¶—<hМÖ9›ax ÅJЇ‹`˜N:ùôõ[ß‘{Í»~V]®ùë$*€ÐŒI&Í+H&Œ ®Üñl‚P;0ôm]5jÞfx79þšIbiýºÆ¤w¼áäÄW.ÖW,\º^[û»Ÿ|ùÕWIÔ+cy±dšù]€IKiM¤Ü=(´ê7ZPˆà’2ó†ÉµYO¦Â0ù—ò›‘+QûÃôЩz¤Ï>ÿ"c2³85PÀÓV]€IÏl=Þ^y“¹†Ð™E±¹^‰ %uÐMɺôT†©d[µ¦ë{i[=ðÛj ê¶^§òâÁ˜Ü(„rÅ83oVäz crppôop1(f~íâì»›Aèræ­^5û¼eÞÚË–)zé.pkÓ0[¸µ þêµÿÌì×cÞÚØ]Ä®0Xžþ¡»Lz!™¦Î_mV@]¢cU0&tnxNDÿæ2Lº—W;Mü- ú—Ì\ºô’W½\ –þ‡Ÿ|N¼.á#,ýýŸ/S“ݯìyîo/ëÕwÐKŠ.=ÿâë°úcºڬ¸F*B— Ž—üa㪦—”g* c’Y*ÀL3_»âÉÕŽg¦úaL:Ÿ²díNu~.ÏÒÂyXOÔ6À$«]åqÚö˜µû/ÃÛœ¯¦À·àÕÃ0‘djvÕ„ëÛó¼7FôŠ=3 &«²;@{ÞGœÉ¹Ó@{Á*Áub_*  D ö×Ûïlv}èèlKާ1xs“_ÏÀÿW’eOJÞ`ë ˜4“˜Nùó]ƒJV½„T.Äç‡Éf˜Šý”2LU’Lh ý*IRZ]eù@C ˜ô”ÖCî7–ÛV ¼]¸O@(muå‹ËwoyReµZß_ Æ0饛5ó†{Y=F†õ•4-g¯ç­-Ï-¾µ…uÓÒ‚žOº‡Lšy!™&Ï]]òž¨K£=f Ýí)Ъ†î 3KÙ#Æ”¥ÚdY¨@y c*O/r‡1Ýv×À"7H¦K¤ïà[`L¡I%±¤"Ë}œä¥”ŠX%Ãr+•M,•-ɃY\n)0Zœ3Ø-×ë’‹.Uä¼$>1P1Æ$qÀLo}0#ìïÞï…~5é ìù”S^X³Ã];h-tÀ{U½9S\Ä‚É6"&’L5©µ´œ3¼ÔÞâþPzÂ!OO<üÈcõq×Ãeªc°0PÉh´á€fq§WDg†¡™®³%¥—?ýøŸ²hõ[‹TÑL±Ç ºm”*8B7<—d˜ð\½dÝ;Ÿ}þEûž.y ˜Ó»]ßàáÆäÿ*¼tú½hOr–⣙gK¥=ÉE☊.•t çéÊ|˜6Nç­âtAqŽ©cJ^«cލ ùT`ý˜?x!RÀâ^½&“¦Ls†‹.UàÜX€©Èg§,ð¯¯-É0a¸øæžÿöÅWšóÚŽ~«„g¨Ÿ«V¯>üÇÇÎYözégÃéWÃdx,(É0yb6…ý_"þbõ“"‡g¾ Ûoní7 PõF”%›• êjô±Ôµ¤æ’ jÏ{±°­ P¡a@I®ZìM=oí~y[u—•h«žÐ9ŽU¹àçÒMíx瀩0Û[êÚ[ƒgÞ@¿½4gAàÌ[MF†©Ó¿‰»µÅì.lƒ… ¹Ý…bLíï~ÒÄòVpiŽó+-9?ÙúÆ?9æ¸ ³ÛJÝ5°gùAECw6›Æ·bLלW¤IQ€SRj‚ù¨±¹Ã˜0ã¦t‘ßžÖù|ÿ~k˜‚<'™ˆ’NŸ$ÛÅH4¥¤^vãÁãJAQá"cÃiï œ-yãÄaRÒ*®4·äñYRsÃ8ÇÔ cj]ÛzÈÀC:>ÕQ–´¬hé2º‹¹¡Çìøˆ3ôø ©­= ˆùwÓÔ‚Uo)êa®ª×…Îžà ŽQÊx؈Ã0-Ý°×³Ž°ÆO—€1an7¢W|Óñâ˜Ú†÷½_©N/ª¯+3üåÂRnä"Ð%3`œõ²½Sh å/ÝEº1;Ÿø‡cJÌß…¡T€ T®ÀëÓZa‘‚e€™°!epF8g‹;‡È~¼‹Ç&9F~çÚ&M-. Àä:aò Þ½2†içÞOLÛ9úÅÈ`Œ„1¾Å¶ä\‡»2ôÅ·øIœBñ˜d*°|åªþø˜YK_÷=›sÅë+Ê7„|tàsÑÿü•ä¿£áÐBþ)žýØ©ÿ¬dŠ™º\×õ7·ôà­zÓß›àk>\N$Aw؇a‚¡÷˯ ¸dI­ÄÿxcžÉìE¥‘H¯+mI<6I·Œè¥äEy@bÉô‡Ë{VËß%Ô¸´U+ĪÁÛy¢^F@ Q€1á}ݲ•“þxœ¿½±SJlóÌXÃfÞÆÜ~ã½?ýÞÔÏG¯U¿‘aºÄonn=·6`*ÿÖ“a*ëÖÖ\epuŽó›^Õg`Ë–7Ž>öøñ³ÚÊ4+xcÇ\~€¡;›MõµVÁˆ1U B2¢1¦ŒT$‹áU w¦Û<žÌøS({¤’gÃ`’J“I&ÉÉoÂ7<Ž@¥ïJ‘–Â|,éd ækÌä±îÇ–ü–~¿¿%/·Tçhq1:aLøŸÁ6³ÿ¯û±ž ж3©&|Û¾¿%ôl<ØS²Â|Êq'ž2å› 0YNhì©7'.»Ì¾­5J‘a*)rÞŒ)Â?\˰‰°QEõŠÅ Ó¿iGçÙˆì÷<áÊð$烖üý›Ó³­ÚàrÉû2(`\ ë¸º¡KfFŒ)oÿJ–— P¬* pÒ®¶ê“ {`eÇa2ðQ ꫇öƒ¡Öt8rÀÇÏì* $†‹óìá¢`ÒábQl¯òcÉa¹‡a’*àW7Q2àÊXWø~l`lgô›ÕÆr É4sÉ&÷ÙĈZh“ÁN¿ª`˜ ›ü5ôo"JŠ× üM` VO<øãàŸ¥˜ üDþS|U¯Ì½½ûðT½iÏ—å€Yºõ`˜¤\ ´ É„=Ú*¤‘ %H?ŒîWVz mT¯Ï,’é²N[ åz‹C^Ú~ÚV£¡„ycFƒGÁmqá loì”’Óbæ¤13oëÖ¿1îâŸKGTבaÌRó0(Pý­-“ “´ Žó3ð’iÜÌ•f…ú ÝÙlßlˆ15^s^‘ $EbLI© æ£Æ äcÂ\[„•ßžzÖy%Ìð™ç=ˆ’Ã'9N××ëb³×´HÜ)izÙV$É¢±€dËwÌù6àR’XŠ-E:[ ‰§s@1£ÆV'Œ ˆ’fàrI‡ì0Û,ضÀ|üÃW؆)&Æ„ßÊ|ÊÜÛ SÑ“FÔ B2L5î>3q:`L˜Õèô=5ªÒ½b .3̇\¸’Kì•øÒß³År¹TÔ›Ùãê3®d_GŒ)5‚ P*Pˆ'tqÆBÑ ñØkº¸bÂ6¾’cÂ…dÂpÑzŽp ¦$j¸'–\ ÄA¯Œ~Ía­z`Ò±1F¿Â6!cÊÀ¿BH¦é‹7•|6ñ;ýŠ¿˜Û ÿA‘FÁÿEþJò—‘#Mo(ò_“ÿ¶ñžÙR˜{{Ýñ°Ü9ji®ã/Ü©Ãq„UÂÀPÔ¸´•¤‘ˆÇ&ì= Çã[i$Ø)$ _YR$Óï/íÝVçÚ+[d=^YÁ¡&Üç‚gž€c•°öÆN)m©Þ3o ·,[(;^õ¦± š•çjnmf˜8ÎoVƒ¬ùu…d;cEÉ¡»x¦7¡Þr‡îl65¯¾8'$ÆG%C²©1¦lÖ+Ku0ÓÎ’ÁÀèE½ïpÊYç…6*ÜÍYñ,LR0™ìHÉð¥T‚R²LøÖªÖ°$®°Ãq%ËOx" À•‚bÃÙ–~oL% ®äDVrÍü®³%kÉZ³Œý%iÿu˜'I ¬D‡+&éiÄ6ð­DÙ0 9ꨩd·dͧüôäÙË·«Ÿ-Ǻí„Igß<d˜J ›Ï€1ýÞ]œØÅ jaL½bʬ-—i‡cLþŽ®|r!¡â¼šÓ›UзÔð'Ęòùßd©©Ș°‹«Ë%@•à*F]Èà[|DSö‹ó¼‹»&ñÒÿe‘L2\tï§¶ÃÎÀ¤ÆZsnºb†I½âdÔô?ª4?¾¤IÆÀHO~­¼BÅ/>l¤ ™;â˜ç_ÜõlRµ!DK$„ þA ÿAO„öÿ|ÄMb2Ê_ ò/ã«V ÀÜÛóŽ‡Í€õ¾®Æ™:0¹º2L(št­¦SÚƒÐoÚHrrÛÒåj#©•8ûB)v¹[Õ{d¿à<²²[[œî¢Ü0©É© Žó“SÕçDH¦ÑÓW”eV(—aâãaõ5UÙˆ1U¦E² 1¦,Ô"Ë @î0&Y/–ð-0¦ˆœõ[?Iþ†ç¤Ò.”Ô¯R¸Ù^mù–ý¾V)WòFP²–Å"–R-5 cÒ`˜$¦^jÈG %ì‘Às°÷(í§£Â|JÇŸžkyk¸Ó¸ NÏÛ㉩՛p¥Ð^.!/µË"Æ”ÞÿsN¨hºɤÃE70´8 ÔMõ SÓ‹É $AL?øÑÑl4ŸM<Kņ$yˆPæÞoﯓ²’º´¦~˜XAT ŽÉtÉõÑm5”†é˯¾ŠsE“vj5óf2Li×$'ùsk‹Ó]¤aÊIuç°˜B2˜²ŒC÷,Õ>1¦,Õ&ËBÊS€SyzñèÔ(;Œé¦¿ôW;º‹1EPò«b ɉààÇ’N ‹øæØïÛvÍ ¶ÜÇ€+v: *¹K!1œO\)ÌJª1&t3˜O9¦ÓÉÏ/ÙªK]Í™b2L©é‰›—QÁ˜"z¶‡·0¦v}Á”’pK¡=žÎ××ù},wqIŒW[&bLÍûðÊT€ P,(’É3\4oFd˜²Plj)ƒLæo|6!Ô˜ŠªKF`îíÑç!`*b%É0ÕEqž´R@2ýæâë ÁU ®m5”@†©RíÓú»êgÞÈ0¥´î£omqº 2L)­úœd[H¦Ö)K9tÏLcÊLU² T lˆ1•-ò‡1ÁÛ¹¸;2“ cúåç*cTr#ÊâP¤™ Qr‚Aœd&›R 6äïRÖ]+UÀ¤crH¦Nž²x‹ 01–\::àäV£FôuÀ˜`ŽòP^ïW‚ȬÄ{œAdº¸RF»8bL ø£0 T€ Pt+`‘LAÃE2Lé®×Dæ$Ó¡?:zü¼WM_x6!ÔÈêªq¦`î½áÏyªž SUæéj¡H¦ /¾ÞßVã@ d˜jQé;‡E2U:óF†)}õmä8ìÖ§» ÔêªÏIæ…dzzòRYC÷”6bL)­8f› Ô@bL5‘§H¢¹Ã˜àê<ÂúŽo1‰SO²NWœvÎW"AEÔR”#%°J¢êQɶâ{ÆÀ=ùùI0&!™Ž>á—“_Ü¢G?LIìn™'Á˜B{Ŷ]>faL±ùKO'·ë‹Adæ(Ø¥§&Ɣȿ3E¨H™ ™<ÃE2L)«Âôd×"™?züÜWuHCCHzj¯ÚœÂÜ{ým™£Ù“Nÿõ½ ?"ÑÐ[­îü}ù €d…`¶Õ8P¦ò•ÎÎ/*›y#Ô࿵Åé.xkË@Õç¤B2a¸Î¡{jœS*‘E *@Œ©Báø³¤+?Œ©ÏC ŠÌT ‹Úv ú/Î8×Ü<ò£H%˜¤â(o&¢4s¬õ’ #º½|G~£”4“‡d"Ôô~7IùÆô›K®èô\ìòþÇÆcª¬'ôÂI>“Dfœ^ŽS’þ1Ì  T Å ˜$¦Wd²n’Ld˜ÒPcµÌ£iî%ÃTKey®Z+`’Lq 2Lµ®ôÏ$™â̼‘aJ_‡äؼµÅé.È0e¦êsR“dâÐ=Õ•NŒ)ÕÕÇÌSª ÆT•|üqrÈÆtCŸ‡,ën\6|û‹ÓÏ8@B—LŠÉ$¹Þè?)Ž-¿ÇdcR’©ÿÐÉG}ܪ ;"V».ݰ÷Àg_$·[bΨ0&¸Óèôît"ƒ„¯ôw†¾Þ/Çd§¿C#ÆÔÀ?/E¨ȸB2ýù¾'O:ùôõ[߉.ÂXûÙç.f¼=ÔµxB2‰•wáÒõÑÎx>:ðy]3Ó7X1÷’aj°ì¼\ ÉJ ÃT¼™ü‰LqfÞÈ0e¬È­-NwA†)cUŸ“âÉtﱺ§ºÆ‰1¥ºú˜y*P•Ęª’?N®ù˜®½öÚ|Qò˜2k±9ó¾m÷þdþ§1ŸòƒÃ'ÔÌÚIf®† Vþ‚¿HœW]ßËcü„¨b2ÿrÌ T Ù €d"ÃÔìJÈËõg¼ðô?þË7ïi2Ly©r£œ0÷2–\ë=EÉä˜òôZd˜ÒX³õË3fÞ;üÇÑ3od˜ê§Ï|Þÿáª_Æ0©M¬^º® l™ùôÑÿøŸNÏ¡{]u®ëɉ1ÕU^žœ $ZbL‰®f®rò…1ùuŠ–ñ[*¨@b1¦ŸïûJ'úaª¼Gä/Dóæ? câ¿™ P*@€çúabóh€»>Z0xùšûêȈöF?L ¨ˆf]bÏ{ŸFT=U4«^x]¿ï~øYômñ˯¾¢nTÀTΣ' è=› ¦×wöÜ×™·¶lV.K– ûÛŸþ+rèžÞæ@Œ)½uÇœSj ÆT­‚ü}B ÆôQÌÕ,BƒH,ÆôÒŽkkë°ñíI‚0–\B»á„e‹Sƒû“:]ŽSÂþXÌ T Y „‘LŒ%—¬zJyn€1áÙdÝžáa£2L)¯áÒÙ#™È0•ÖŽG4V0’‰~˜[iºZÉD†)MYV^{}çàƒxk+K3œ&– ;xI‡¿m\ˆ{_àèC÷ä×&1¦ä×sHê¥1¦z)Ëó6YbLʨ@Ù $c‚+¦'WÿLã7æŸO!ÃÔä¾6=—'ÆT'®¨Á§%Æ”žÿsJ¨hŽ~’‰ Ssj"»Wýè¯ÛÚÚoß÷ÉšÏ>ðZACHvk¾¨d~s/¦œT}êŠé'™È0¥®œá@’‰ Sƒk¡¡—³1&\‘·¶†Ê΋5L·ÖœzûÁ}ÛþöÅW~’‰C÷†ÕC5"ÆTzü-H·ĘÒ]Ì}¨ĘÊFXlŠæå¨@21&qÅ$iÛûÍù2L¼ ÄW€Sûœ ²DŒ)~›ç‘T€ PÜ*`’Ld˜rÛ SpÉDCHcdOÈULs/¦„T ³¨€I2‘ab#‰£€‡d"ÃG´ãbL’‰·¶×i^³¾wCÛçöûKý²ÓC2qèž––BŒ)-5Å|RÚ+@Œ©öšòŒ‰P€1&*P¶ ĘÔ“`LpÈ„FæSÈ0%¢¯MO&ˆ1UÀ %ð'ĘÒóŸcN© ÍT@H&2Lͬƒ¬\»Çì›ömŠ(’L4„d¥ÎË(‡L4ô–!m’B2‘aj’ü©¼¬’Ld˜RYeeÚÀ˜ð;ÞÚÊ'GÑ]YtG÷í‹&{²ôÁ››&wï¨;•dâÐ=9uW2'ĘJJĨ@f Ɣ٪Í{ÁòŽ1á‘ÓiÓ[mÛóqô1ü6K  ºQéÑ%Ú÷ágIë9LWLê ™Ä4 gR’VY ÏÏ{ý5ºýoÙµÿÝû³ô¯OWYÞzçÀÆ·>ŒÎó®½0Ýð–ÆìQ*@¨@BÀÄ4ø’„d†ÙH¯‡ <¤dæÑÒh)©RVøàãÏ¿üŠÔ¬Vo¦ÊõÁÇe[ÍTÖ¿0œy«¿ÆÉ¸B1Æ„<ñÖ–ŒŠa.ÊPþ–LVÉüåú1-KîaîÁÔ"‡îeˆ›€C‰1% ˜*Ð$ˆ15Ix^¶Þ äcª·¾Œ)}E`Žó­€ø[oLÂ3ÍêÑï¯Ok…0؉{Ûe?M`›° ä[¿”žS *‰Y¤uR€S„åi›­1¦fׯOªVÀïŠÉtÈTõéy*@¨ T€ P*@¨@¨À•-ák¼QÚÿ×ýØÆ¨&l´ïoǶ¼Ë)L‰²R*@¨ T  cJA%1‹%V  É„ õÏP œÓê¡ýÄ'Ó®¶r°ÒK`›p%N²Ę’\;̨¯Ęê«/ÏÞ4ˆ15Mz^˜ ÔD@WLtÈTmy*@¨ T€ P*@J*€õÚ ¶-Àa•d/ 3'LpÎÔc¶µ¬¶{â‹ P*@¨ éP€S:ꉹŒR@X%OK –Ä“€Jp¿„wñØ„ýÀ˜ðQ¾Å‘r°O|%VbL‰­fŒ Ô]bLu—˜hŽĘš£;¯Jj¥Àž—¶íê#I†ª/½uîäT« ñxs“¿ØŸâR1ëT ZbLéo!ĘÒ_‡,¨TbL•*Çß%\bL ¯ f ”¡1¦2Äâ¡T€ P*@¨ T€ ÔSQë¾Ã rõ˜ç¦T€ P*@j¬À¬]–>ÜÃs^€M“»w¬ñÅx:*ˆ1%§.*Í 1¦J•ãï¨@ú Æ”þ:d  ÆÄ†A²£1¦ìÔ%KB¨ T€ P*@R®1¦”W ³O¨ T w ŒîrH`™×iñ³M¹S‡ΰĘÒ_¹Ä˜Ò_‡,¨TbL•*Çß%\bL ¯ f ”¡@ûG ÚÚoÿëï—ñJ¨ T€ P*@¨¨ƒÀ˜fmé\‡ó”T€ P*@¨¨½ðÃŒ ïˆßKØÀûëÓZq¥Ewt— qׄýB5a§Yû ñŒT a cj˜Ôu»1¦ºIËSÄ+@Œ)ñUÄ V¦1¦Êt㯨 T€ P*@¨ T€ PP€1MÝÔ‰Q*@¨ T  €I®„¬â$6„gÂÞWN?~~`?`¦{Û5ÒÜê¡ýà±)Åd&©@€ĘÒß,ˆ1¥¿Y*P©Ę*UŽ¿K¸Ę^AÌV‹ƒ(  T€ P*@¨ T ± cJlÕ0cT€ P*@¨€_8Xiû¢ÉÀ’Äë’€MlÎtÑ„ãñG"aïT• ¤UbLi­¹B¾‰1¥¿Y*P©Ę*UŽ¿K¸Ę^AÌP ­½[ T€ P*@¨ IV€S’k‡y£T€ P*@< ˆË%0LØoL6©&Ù¹«mÀ~ 9‡HØ€‹&JJÒª1¦´Ö\!ßĘÒ_‡,¨TbL•*Çß%\bL ¯ f xØ´oSǧ:"µ®mí÷B¿³{`»eEË!‘C±ýدºO¶– ñE¨ T€ P*@¨h˜ã7Æ r S›¢T€ P*@ªT@\.‰k%lN¼ƒXOKòâ{ ûÅW“€MU^?§ÍT€S3կ͵‰1ÕFGž… ¤QbLi¬5æ9†ĘbˆÄC¨@€+&8dB¦€(UÂ>b[² hiÁ¶€œ”^Âñ€ŸVf‡ P*@¨ T€ P,+†‰S–+˜e£T€ P*!ìm& /„Š“hqØÿL€–*a?5ÉWz$6dË,Jþ Æ”þ:'Æ”þ:d ¨@¥ cªT9þ.á cJx1{T @u¼ä÷À„£Á3µïo'LpË„¤ØÕ¤T€ P*@¨ T€ ÔOWßÒ¶«¤Q¯|I?â«ú]—g¦T€ P*@¨ T  ÖÏ8ø`''ýùßþ©ÃÁ;+ìÁ·|¥JbL©ª.f– ÔTbL5•“'KŽĘ’SÌ ˆ¥€ J8T¢ËÉo*Á6ð­°Mx‡‹&IðÌëÔ<ˆ P*@¨ T€ P*P…¯ìéÿX[‡À„¯ª81J¨ T€ P*@¨@íøüÓƒ=¾~ÆoÂ~|ËWª Æ”ªêbf©@M ÆTS9y²ä(@Œ)9uÁœPX hü8ÀIQ/ðLf{€4aï-+Z°wÙàT€ P*@¨ T ® |ñå§­k¿îǘ°_ÕõÒ<9 T€ P*@¨ e(0·0Æ„ý|¥MbLi«1æ— ÔNbLµÓ’gJ”ĘUÌ (­€xcÃ>I<0á…`•&¿6Yè%øj’=-Wú¤<‚ P*@¨ T€ P*P <Î1ÑS-¤å9¨ T€ P&)ðÄùÇ^Û¤kó²T n :d¢+¦ºé]×cª«¼<9H´Ę]=Ì\å cª\;þ’ P*@¨ T€ P*@¨ð(0~Ãa&ÉDWLl!T€ P*@¨@ºèõƒvJw˜{*¨€ß!]1¥³©cJg½1×T  cª…Š¿øåϰš(ó%e© T€ PŒ+@Œ)ã\¯âuîÜùûÿq¨X£ ;TÁüô¯ÿöÿûÚ×ÿ¡¤É)ĺbN2LH¡f£"S‘e$úé1G™Ö¢h«P‘ ¨Øîjî)eÙSÎßÿ¯}ç_þÕcÐ1 7ßüÎÿºôÒKëUai>/1¦4×óNªS€Suúñ׉U _ÓE]ÔÐc»ö}RH{?Ùµ÷“V:€ôРÇÎ=ÿÂ{ìx§Þz瀕ÞFúéMM{>Þn¤m{öoÛí¤7vï·R»•¶:飭»>Úb¤Í»>Ú¼ÓI¯ïüÐJ;¬´IÓ[¾æ¤^{ëƒoÒ†7?°Òv¤÷_Õ´íýõFZ÷ÆûëÞxOÒ+H[´vë{VÚ‚ôîËFZ³ù]M«7ï[ýº“V½¾ÏJ›¬Ô椽+_+¤¯í]±ÑIË7î]¾ñ嬴ÌHK_}ÇNo#½„´ÞIKÖ¿m¥uVZ¼n“^Ùó¢›^xeÏ k‘v#-Òôòî…FZ°¦]Óü5íóW;iÞêv+­Ú…4WSÛ®9…´³uÊÒ¯ýÃ7g¯Ü‰4KÒŠ3´cæŠ3–ï8ôð£±J ±ÿaÍØŒ3~zÒ©g-ÃóƶmÛ’Ÿaæ P*@¨ T€ P¬*†éÒ«ozdèXoH2eµ–Y.*@¨ yQ€S^jºÆåìÔ©ÓøÉ3Å¥F(Ø¡ÔüôàÀÇ~}þ…ŽÉÉ56mÛó±XšÄÆä˜\ӒڕĢ䘓\C’X‘\ãÑ–ñ¨ÈfT°¹v"ÇH$¶¡ÕH¶aHLBŽ=È5‰%Hm@b»}ÄÜ#†ž‚•Ç6ñXöŸYG :óV[vœ_žqî·÷w-8–ÕÆ1ܸ&›n{f¾×S&NGŒ)ÕÈBPŠ ÆT‘lüQòÈÆPIˆ%M&´ô=jÄ ÒA—bÐK ™”^rF–.ÀÅ0¹H¦*&{*)šar1&gljaL “3TuF«>†©mS0ÆäŒ_mŒ)ˆar‡³.Æä0LƸÖ3ºÅ07cz¹h°»pÍîHŒÉûš“Á0íšÝVÀ˜”ar1&‹aJƆéÄ“N[þj;6ž_°Þ³H2%¿ÿe© T€ P*@¨@&°¦›±l'ƒžC’)“µÌBQ*@¨È‘ĘrTÙµ,*0¦q“fŠ)Ê´C¹+ç?~`À£‚1é‚ù¢¥òå2LîbxÁ˜<–#Y÷®+ÞÅT¤ ÝMŒIW¶Û“± Ý^Í.ëØÕTcROÆäšudQº½"Ý‹1Á|CŒ)~s$Æ_+I²¦1¦¬Õ(Ëã(?ŒiàcŠºX%×ßÒƒ,Œ©Èå’ø^*v¼$cJ“^òLLí>'L!“œ‡+&Ë S€&Ë S9~˜ªd˜Lî¾xØ ŸLÅ®˜Þ pÅäøaJ¢+¦ÒÓòtxc²¦_œ¶bÃn±à1cÊ|’Lìå© T€ P*@¨h‚`˜.»úf8Æã Ösãñd I¦&Ô/I¨ T€ ÔNbLµÓ2WgÆ4vâÌ";”ôC#~cúÕyzìMëÃ63 L%ü0Å`˜c tÅdyc*åŠÉƒ1i‰¿áºb*òÆdcLn¨ ×S!¼†bLv< ËSÇ“`LÅ14v\OoL!!bL¹ê[XX*P¤1&6ˆŒ*;Œ ãÂBT83Bœ½íÀïAÐ’Å-aã ^=}/ùé%#„\LLáäB0!¨\‰XrUùa*Bïc1LŽOÑJ¦x®˜ áä0ðÕpr&¿አƒ` *áŠ)ùAå„aZ¹a·i'À:‰)óH2e´Ûf±¨ T€ P*@¨@R°¦knFLs8C0&¬áø}2%µÎ˜/*@¨ T ¤ĘJJÄ‚Æ4fâ ¯AÊ0? ÆäñÀäFù(Z!£’iWòÆ’« ô٠'WXÙ^­+&ËÊ+¢\»Øq Œ)À¢gc û«cb'Dò«1¦üÖ}ÆKžGŒIýsú7œQ£ÏÓR´À-ÙP¼]ÚRŒ.y襂û%0vB;˜6ºƒNO$ã‚#P_¹€©'LvØckZÀícÇ’s|Û•hQ8¹rý0Á’ã1LÅáällßãƒ4šaòcL3ÝËNNÒ¡‡=eÚìw?üLÓÇŸþ-!¦Ÿýâ´¶»a'WL–ÀvšGY“æ®:üÈc·ly#!¹e6¨ T€ P*@¨Ȱ`˜.Ãô†ŸÂóxòðã£Ï<ó¬Ÿ|’aX4*@¨ T › cÊf½Ö½TÀ˜FO˜á±Cm3ÌO÷? Œ©›å~©ÝJå¦%M09Ö%Ø’$9¥¢h±äJûaŠf˜—à 'WQNÂÉ!»bÚ³x•`âq­z)ÂýÒpKš¶½hÉL^L¥&á]4ÁÏ¿`*HζF®ÅáÙõ&Ú(?L†+&£l2LsÛvÍ)$äÆôŒzcr¦˜L†I0¦㦙Պ6ÓÜÿ­\Ýe˜öxìpÅ$¾²ãoâœU‡ÿø˜ÊH¦ÖÖÖC9$º¤ ,ÀýìWLMÚÚÚºtéó`=Ls‚ßv´_ñ¯Xîµx< T€ P*@¨ å* “e +&w•…íŠÉ~<ÍcÃ; ™N>õŒ²H&óAÛxHÑŒáÑÀóÀ‚=aÏ›6mÚ¿?à9®¬g&a¿ »~ÎÇ™rÛ§T€ P*ˆ1%¢Ò— `LÏ>7Ý´@9ã\ÛÓ}ý=ç¼nžàq3Óë;-»RÁ´0©IGj9Â]FéVÚò.,D¦‘H–¸cèn%ktQ\B&ËúS`˜Ö#–œ?œœQÎ '·p³:}¾mÓQk&¤_8AåŠ\1Ͳl7ŽÕÓÙçvóØà>:ðyúG­sLŒ©ÖŠò|T = cJO]1§e);Œ ãBa’Ʋ1¦`€éåâ@r^'LVå"'L«L'L»Ô©‚c Œ%g•KÆäe˜‚"ÊÁ“Ø Pãg•M2µ··Ã ïÒGgR¤I–8Ëêg˜ 0õyYX¬VÙƒN‚ƒñ?Ç`°-?—vÊ™qÙ£“þ=zôÀG/F “[¯mMíQyq*@¨ T€ P*;,†éZ‹a uÅd{еO¬ÇÇ”A2Ƀ :tèàñ´$.Zu'žDðà Ï/xpÐg <5à£NØÐ¯tI†ÿYF«Pj°Ä’>Ýà·ò|äy™™¢½1ÉÓ„ä´°!}ú§}QoL8^–CàéC–dxže´¼ê›VO‹G$ìÄ™å*âÉ Ï2òQ8'Ù/—ÀµÄ]®e2L|œáߊ P*@¨@Ê Æ”² KJv1yH›Ö(@K÷<4©€åñNä8ÇÆ´1€^òº_’@rûQQ¹÷œ09F"'\!–œ’3íAb rÍ@޵랰/¬ucÉÙ¡6$ÎF ä‹ÒÁ0™“é‡É4Üc kÜĘ’ò·g>¨@ã ÆÔxÍyņ(;Œ ãBú7¬Q㯃F‚(izëÃM…qdibÉïo©(ZœÍ-x]*F—"é¥w5žqˆï¥xî—loÿšt¨Zˆ|\€Ér.ŠdkC£ÈÅsÂdúa’Q¯›œPÊŠßvFŠô´…1}Ãb˜ŠÉ)ÄC?:9Þ˜”a*¬uÞb=„X¶Z{Qq¦+&Á˜ óØ+‹M2a"“õ˜|Ç„»ÐEf´?Æ$Ë‹ñNfÄYô¬Î“<“bRÂ9ÉUÄÉ“éoÉ„–ÔÑN’¡T€ P*@¨ T Xƒa²–XXklìg¤Ãäy<±#ŒãðþÁ±H&Æ„' Y!òÀ"+(Ä««>8àHðFXž¡È‘M…ç1Gže´¨¸´<žÈŠz™ÕðÖò•<þ NÉ95‡È²gž–3ü;Q*@¨HŸĘÒWg‰È10¦Ö±Ó RblºÛ6HYÛÅÜ’µ0Þƒ.ÁýÒv+9ÁãŠÇ…ú÷ €É2%(Àä.q0 É‚öâ¥ì…°;ØN˜¬á½ ü±äÊb˜æ´íüÅé–7&a˜lWLÞÅçĘÂZ61¦Düç™ *Ј15Ev^´þ äc¸ÐC#a€¨éîwùu7Û‘’'}€£™ÌA¤ºñ,8ótÇ”2²ôBK!Ü’ ¦\.ù¹¥²/Ù‘ãœñh‘ï%ð8?½äw¿T<`õ ÷•…«`r'¯¶¢È’óLve?Àd’Û!“ -ù·“ƒ10Lf89s­³²A&€bˆÓ7zz,’I–{¦ìãcL~PIöÈT¾ù-vj:lÃÆ •}¥ÛާXëIÐ^–}ß#¥I&Æ$aãÌ•xpT/}ÖÐPnoLžGAŽÌ%fÜjcÂ1êWɃ1á$ ”ÄQ“ÐNŠ1á+ u‡ýX%""òq†'*@¨ éS€Súê,9¶0¦1ÓL ”Çðd¤ºŠá)Â̈.yÌI?®`BÚòn L;ÑÞ6wq{i'Lvh$—a²&e˜t½:,í—Ë0ÁˆŒé`L! l7ĘÂZ61¦Düç™ *Ј15Ev^´þ äczp°—F2ˆw=`=ãÅàác!ö°CÁGàJ~OK®‡Ïr¸%{a«=ýcPYój¡Kþ°qöÔ9NǦâ~É¡ÑKUij1| ‡ìñ=ôRLL/ÙŒš 0E‘+PüÈÿô¤Ô`Lf,9 qC{P†)b­³ëŠ :‹ãÖQÓ–ÿ ”O&1hÿ£N’€É½zc’=þ©Ô û1&œV~./|”0v²ÅÓºÓ½Sý;F^ P*@¨ T€ P(,†éš›±Ž&ƒa XbñŽeí°×j Æ$'÷´ŒŒŽ.W2¨r)`6”RÒ_™@" `-ÃSŒ®£=æ: ó£F‹ÃÙüAåÄç“yœ×Ò_á+¹› T€ P*Vˆ1¥µæšœo`LOyÞZÄꤩ ^{Óû‘è’7xœA/¸_²ÍF–û%¿&ÓHäF‘³ C>'LÖRv˜Ü}‘&{ï˜{Ü@rKnþšö‚eÇX—aaL¶0&¿&YNŒ)¬Mcjò¿—§MT€SÅç¥ë©@î0¦~ vF„2.,Nø¶Ë¯ºº.”L>Éò¨àT ~•\×Ja¬’5±ë¸Y*ò´TÂÙ’ ©Äá–¢½.yÑ¥bÇK½d9. uå{ ñßvÜ/ÙÃV½wüz)ØýR1˜ï “lÑKî·¶“D‘žŒÉ`˜Þs‚5ø¦6»rCÖ:[®˜ä™2Žœºì?:zË–7Âú3$Ž‘H’eÍ2õÒH¢'˜“¬-–ŸÈ‘fˆ1-È1z6|”¸uúÓ `^Q2ÌåËõ¼)ðÜT€ P*@¨ T „q&;œL K_}ç¥W½®˜ôñäžA#"H¦ŒIŸ ðø Þ[åYCäá_ɰdBBW ؤ5þg-¼@Qò’ÀpòX„pZÒËÉÕõZÒN¾Õ¸r|œáŒ P*@¨@ú Æ”¾:KDŽ1 ó|‘Ê ßáØžÄ U –Bâxñ0/ù I²âÝ´!ⳕ6íksR`¹S˜&{•‚íoU’Ë0Á!ÉÃ0Í]µK’0L³Ýxˆ%'SÃDŒ)¢YcJÄž™ MQ€SSdçEë¯@iŒIfî0ßgúM©Æêr…‹.º¨ß …Cr¾í,£ÆmEIœ'E§0V©€+ÙKTÍdJš¶XÐÒK¯¼õ­ï|W-ø‹Óðï:ôÄFÿGG^qý-‚Ï+DÃFL˜§^—~zÒi­æmºÅLq/ >‘ã.½¶÷¥×ôƤ³JÓKßøöwÅ÷Òb7²ÙÈx|—^úÆ·¾+è’•Üq­gtëÆkŸW"„\,L0IªcÚ·íàŠgëÒX“ ÃÔ¶q·:a’˜Öh ®d¥k&]ØoîŸZd1Lß=Ë™½§Ÿpͤk-ÖµÎÖÃÚÝx`˜·ºO#¦” ™ê](žŸ P*@¨ T€ P4* “óœk,¿ÁãɈ9›ñ`‚ǤnýæNYò¦,ã¾®e1OÎè=}äœÍv¤‰Â <âáñä®Q$SsU’Xr|Q*@¨ ¹V€S®«?²ðî>8·ÿÁÏ? <ȘFOõ¤ ÛSßû-ƒ”ÇðdCKEKâ—­ßñ­ïü‹ÆŒ;ñ§ã#ÞÍeðKÖZv%½„=7÷¹·Øf4WMEf¹yÆãé›ßþ®™ž;Û^ÁnyWï„IƒlÀ*ÑýŠ›‘L€ÉÃ0Á ÓI.ƤϽ1…5GbL쥨@~ ƔߺÏBÉeµ¡zE1‹TcR·êfȧ”ªŒ ãÂÉ3j4È$ïÀ“¶f²ähŠ`•ÜIÞ@7K‚. ·$ÃÍο¾°gŸû'®gŸ{±-Ķq0&%è¢ÿÖ·¿ksKض‚ö££žy®xH/ff™‡#ôÞ‘°pÖJ1|/ =[¸¥bzÉð&ZÌã]²0¦5–— 3‰ã%ÃýR»7~œ‹êœŽºÌ>"(Ûw’DÙñAjLÕbL˜†_t°þ÷0Lh+7îÖ§i'ÖZŠ×÷a²kßÂÔ.ypÑ]#V£úÀ0š·Ñ©ÿøÀÂ;ž^%Ë t­3”´:ìl²ôÐHŸL)ý›3ÛT€ P*@¨ T€ ÔI0L—]s³:ˆÕ8×x<™¶ì-<ž´ÎÙ,'ýǽt 'Ž}åââñdäÜÍÇ_=Éz<±±ˆI'b½è—`’©Nbò´T€ P*@¨@j Æ”šªjxFa&€ Ç×a&`LÞhV©ï}œõ«®–&ÃÆ„!·pK¾£Ë¯/ìuû}0àÛºú]ìJ…Èq¶ï%ØŒf.~U†èb3RzIE‹ÿÔN??Cw$]І©‹#ÀTÒ Ó®¸I0ÁBSNÁšc’Æôën{(Œa¢7¦ˆöMŒ©á~^ $Fú›ªSTf$k ˆãs, Ä >•Ê,aiŒ ¿‘Õ‡â2=ÕòXÓ}-I?b*öÎûZ0j,b’N*&“B=*ù\+©S%ÿ†é]I·-ýöWêpS6WÂ6Þáo©ó¯.üM÷+.¿îõÿ)܆•&·$CÒñ3–]ví-gžÓ­ÓÏOëö‡ËeTzÙµ½1*EêöûË10;})—KgœÓmÌ´—Nøù©8[Ÿ{ùÓ5½Ï8»ë ?;õÐÃúó=`êéOW÷>þg§" zj¸ûë{ß}Û]-‡þð¨»>˜¬oOD:åÐy]¯»ÀÐÜ5`øq'ž‚tK¿q¼tÞï.ÃÇS;_ðoý³ß¹heî—Ì!¯>YÒ+˜ÌApÞ˜¶¯_¿H7ëáD`¦º½,†é¤ÓVnØíxír&a˜Ð°ÊYcÉÝ:tù-C—£a-€€¨šk-îùIJÃäºb²ì ½Vì|zòÒCŠ.W·’ñÄT€ P*@¨ T€ ¤L‹aºúf<Ë㉮¯Ç“Kû¿p÷È5…P×ßyhÜ+x<éûÌ*q;·m0¦¢%¶+&}<éûpkDt¹”‰ÅìR*@¨ YR€S–j³¶eŒI’fÆôÔ¨)¦ʳÞ2HÓUíMEá;,hÉâ–€+ýζÉð[×ÀcnÙ6;KßÛý 1!©ï%Yú~Óm÷t‚‰ÁŽ×aÙŒÆÏ½ßKb!êqë=ÖºèsºÁÛ‘Ã^ÐŽ=–=¨`:ýì®bš8o-Ö'ÀÄ#Qä®éuÖ«ÃâóÇ+{v<ñ”Ž?=E¬<=>ÛH§t¾à—ßì$;…mͱì8À˜ào‰S”S¢ñ'T # ÔÙT•XŒD*n “dM=+iNKcLêÊ f mÛ°q_Ë3°)`e»FäÕìø-L?’®ë}·,_¿õ®€ð‹&+Ô†½j$ òaîéÕw =€–B¾Wÿé[ÿ0ÉcɇœÒ§æiÆ¿ÿéI§.µ]âÇy&ÛÐàxiì‚­clÁBç®}ç\ײ•#Áýc^1gs÷ûö|li!^CñZg±dÊõÍ…§T€ P*@¨ 1°¦›<ËuÔs°K¬g“…[…a¶¤ÞO.`ÌÚ îœƒÇ“AÖÞkš?ÚµxŠUºÉÔ©ãñ·Öü!‹'l´o­‰Ñ¸x T€ P4(ŒéÚÿ~ðÁNLTÀ«À=?)xcR·L®g¦N'ÿäÈ)% Ra&'ؘ~ú‹Óf/yUˆ%~›.—„[²íJë%^‡šÄxdaL÷N{a6¦-Z'6#؉à„I¢s<2|¢0­9ðnº_úF1Ƥ‹ØÅOëä%Æd/Që =Öªu× BÈ`½$˜zÞ1ð÷—ß\$gÓP« 1¦Š;DbLKÇRÔ+@Œ)õU˜ßˆ7¦ €D’ S‹“üF~ ÑéR-$¼1ýåÞ– ßžyö‘þ“lJÅ^”NÒ$1à¼iS‘3Oׯ’£X!á6ím0CI¸÷DêСƒøùX^’Œ8%!N’C,Ù¡‹‘d *Ä’õ±ài CÒ·/½¦7襖áqª®]Ž˜qê{ ˆ’ŒP±1tÌl$¡—„µhI\.áÝöºÐè%M‚.)}Q¬?ÎÂ*ÆÔýÊžW÷ìtéёƄ¸ð& $_ãj’¡­›vÎv!}O¼ä˜ÁãÂÜÆÄ˜¶Þþóà§óɤ¦Û¿ûÿyhp«—^²W9K›±V9Ûª^CVã㨹›1¡¾PAS^Ú;ž"àï*p­³ÊÒùü?Þrû=ûâ«TÿÁ™y*@¨ T€ P*@j®Àûï¿Øa‡M[¸Æ gÇ+˜¬õHÝúÎÅâ }<Ábn<˜ô~b9ÞÁ0áñŒXhqϨ5ö“ NÎuÅ$'“_ܱSÎþÚ—úßüÆËÕXzF`¯y;ç © T€ D)ðÄù5¾KÖt&™yK¨wÖéÈÞ1% u»m ´7ÁÀ4bÂ<@K ”`3»¹^¸%è(²+ýü41!‰ñ_ÉøÜbtHtŽ3Îé Ûø^’%î° c²ãÇY Ú‘`_€­Ç²2X†ËÖ0aÞË–¦—­Q=V&`û±Q3-‰õ¡û=‘`ƒ€ï%1ô`²0¦Vc‚}ç‘g¦cše¯aÐ(rà 1¦Š»bbLKÇRÔ+@Œ)õU˜ßÀƒ’:Q‚[%øT2µ(1ÒXr“'Oö{sJ—®À˜n¿g‡:2?â[kÔÈ!EÂIf¼ábDÉ¡”„UÂÈÒ ®ˆŽbÉeä±oŸ<ÒŠáæ§­HpÖÐÓ&–.»¶÷¥×öVbI6º½@ôÀ•0BºdzZB„8‰†Iý‚>eCK —dx ÄÑâ€+ÁÓ©‚1YCUczâÙYÇŸxÊu½îRâ1ã.¶A{ñ*ô=ü-÷ÛË0~•'¢Ø#¾—0–ÅG8Ì„áìó/¾Žqm^*B—À09þE‹Ð¥Â0× ‹V–ï%?Ìc1nZpD¹ºÝ>ýôÓÎ;zrŒÃÃ9ôR`ÒUάáÎgVÁBðÜ oرäö Ž<·îü;fK¼¨m3a–¤æZghÒí×]u}¯Í;?B"É”®>¹¥T€ P*@¨  P`Û¶mˆˆ1uÁêâÇçñVcŸžµ Ë*†ÏÜdÅ’[ÿöôeoác¯'–ÁbÉáñŒXe1zþÖ‹¶0cH´ke˜Ž>á—CGLÀ³ÉνŸ|ùZ4 zës‰º=,×'»<+ T€ P*@*RÀTN8¬™ˆÓaýxëäˆeð0Hqö:Æ3“»’YÖ3;&8^[À?8¸Cž™„m]ú¾Ü¶+© IlFسÌ6!ÁëX(Xˆn¸åî3Îî*¢ÓÏîz}ï»%‡ÐK’Ô÷’µÁ¿ëÏã£faT?~Θð>mñfO91÷`B¹13WÓØw~uá¥]v³».}‡zc5­6Ę*j…Öˆ1U,HR¯Ÿ¾S_…ù-@KK‹¢K=zôÀGS‹ÒAåð‰H‡¨¦T iaLw  Z#Â>w[£F‡¤ãÅ¢£C&EÂI”’=ÃëIb\+¹ŒÂ`$ô¸%$‰„^‚mÛê{ &!Xˆ$‡¬`GêÿÄxµ a±:ìçþö2ØwÎýÍ¥ð½„A>V­‹¡gp«å{ öˆ›ïˆŽítòÉg^ŒÉZ—î®aðÛeˆ1Uܦ‰1U,HR¯Ÿ¾S_…¹.œ( †ä÷¦TcåÒ0I)€1a\æ ûñíé]Î8ÀüJý9>8ÉáMJÉÙ¶ý* Œœ\L~êÂu~bI†žfV iôó/I„8Ó ¨º]ìõJÖ®A-ï ’ÄÞ§ª§P°bC-é|‡ŠË%IÖô´,À0N3ÇŒ t¼d 8ÑøQœoËŘd2}ÇÆW‚^ß¿uØÐb’é‰1B/™“:a’ÕêëUê4fþ–CWÃT¯ÁôÃ$E#É”ë{ O¨ T€ P*@ÂpH¦y«K>žL[ú¦3)¦Aª`o XoEˆ3íJÏ/ZWdTrmIºâ=ÀrdÅŒ+ gú^’Èq¦ï¥‚1hMÁ¤6 5ý…Ú(Ùð„‹˜ä¡€SÅÿbLKÇRÔ+À§ïÔW! p°½½Ý¯B\Œ)úcúó]ƒüÎt¾Æq€í6I’1p4·]8©¢$èRapé8öT×J#ï’ò¸’Ã-Ù¸R0±dx -¹Ü’I,ÉvIn©€.­ B—¼ãv5 ]2ñ¦Ê0¦m»÷[ÿ<¢€a ˜^ŸÖºzh¿Ï؇¯]m >x³<—fB2=üøhõÀ$“ÕB\³Ÿ=_¯.ÄÐ~Ž‘`µá‡©8^CÃD’)ÝKA¨ T€ P*@j®€L“æ®Ò9ºäÆóxb¯ävVo˳dÄ ¿¦rI&©(\¥äó«äÌÿºÞ•âàJ>–7KÖ`T’ÏÓR8´´Ðžhö$¿¥Ü’Ïå’5À ÉΆx]*ÉæÇñ·}LU“ü§>ÿÔóßÚ»¡mr÷Ž ™üÿ9ìÇ·åöF ™Î:Ë"™-Â0 ”aj³¬g×_k4ÃD’©Ü:âñT€ P*@¨ T ' €d:þ„&ÎYå,®(^_á:aªÃ3ºÜè.‡àÌ¿hlRNª&YÅäDj²êƒ¹¡T€ P*@š €…1 Ÿf‚í ©Óºœ¬£d¤ Óá.w/pKºþÙYíÚBÑ¥âÕìž—¬ØÐAôRÑzuÃýRy½1UÙ@‰1U) NR¬Ÿ¾S\yÌz”yÄ˜Ä ’&]çVŒ;Ÿoî‰Ü~ÛtžTp×).”‚))_Yš¬R¤_%fúU*rûéÕŠ£ááá,¾¾,hÉgŽYôÞërÉË-`ŠF—ª'“Ê:C 0¦âÿ<0-}¸’¸bÂ4:¸%¬–£0·.žý؃Ã"§Ÿ|rò©g<ôè³æg& S°ÐÙFǬ¥å0LŒÝÀ[ T€ P*@¨  lÙòÆÑÇÿܬ6ÿ㉳¾ÂŽs-'0~X!'ìåÚX¨-„ºÄ"Ú“údÚóžwõˆ™1LX1" ¾ð`¥<“®$ñì/ùƪ¯VN¤V« O¨ T€ ¤^`Lƒ‡O ÊáDç0 R^c“e`ZïMEv%'FG´äá–ÜõÏ^—ÄšàÄa.e·#Ç…ÒKÖªuwÉzÅî—<Özcª¸ÑcªX:þ ¤^>}§¾ Y€`r‡1ÝÒo@12y#{ßcòKî Æ’Qrù¤°Ðo‚(EƒJ×JÕàJ!Ä’L.û’™œAª;Nõ°ö·ä‹ç÷·T’[j€Ë¥°©æ¢€UÆ„EwtGÂÚ_L#fÒ±?"öÈ~)aæ°_vâ‡a}•LyÖl'âdËyä@r>#Ã0¹Ž[ãøa"ÃÄ; T€ P*@¨  É4~V[ñ㉓BÌ!…8×õe˜°€dV.HëÇ´Ïd>[ÉJ}§¾ Y€`ò‡1õaÔxjçó=N8eŒèO&{kû+øWt2F™Eaà¼~• ×JžÑg`èâ’±á áá OK~gK:T56Êö·Ô\nÉ3z®9Æ„ÿ™L”c2Óèò·“@˜R¨$3æò&Ó‘0áŽw92z]H¦†Œ²˜6˜ŒUÎÃä.ð.t&ÃÄ[ T€ P*@¨ 5U@H¦q3WЦÀdúˆµã\×Ï“H©ôL"}Ó¹’GbŽ1#Íá­‚Àß52£'ãDjF+–Å¢T€ P*@â+`aLÃ&FØ›,ƒÔYçÛ«ß½N•<&'¿]©Ø–T -¹ö£‚µÈ]fPà–Š—µÛô’….† £—,«+vX©:z‰SüFv$1¦ê5ä¨@ZàÓwZkŽù.¡@î0¦Þ}D GøöԳΠ8 ~ N*€ðÎ$¯Lõ:¾6’R”^¶–±J*nší®aÉï`ÉÀ• £Ò7KÁž–ÀÚ—†–\îÞ¿Ön[¿ý«šcL:Q.“é’ÄëVú‚dÂ~¸_ÂNqÑ„ãñ­ydô_VH¦ûÒVáD‘s&ÇBàÖ臉7*@¨ T€ P*@j¨€Lcf¬ð>ž¯¯xv,9ÇÂQ“XrZ!–ðÏ\òl%ΖÄE®† }§µæ˜ï äcêyÇÃ?0·5Fà|UÌ!©Ï¤ž“C @”Ì®ÈÁ’+KªÖåoÆJI×õiB¤9Þu0þˆ²,X¾ÂG9I¼4Å|9$Ó xðZž]ˆÔPXèL†)¦ž<Œ P*@¨ T€ PŠ’iäÔe…ÇY_a’Û©’5÷Ä «¿[l`’+qÂ$!ääÏ3—)Q¿ùª‹œH­‹¬<) T€ P*&€1=üäs± R–¥iwXPŽèEïq9Š %¿¿¥Ü’»ŽÝö¥ÚÈDŒ©âöMŒ©béøC*zøôú*d‚ÈÆtó_úGŒñ-0¦¸ƒE@H’l·ù1“1¦Ô¸oÖrUOòŒ2ÃIù P©x *îyrŽ+… µkî©‘=Lw ¡“¹ÊYŠÜí×]u}¯Í;?ŠH;÷~òåW_52ç¼ T€ P*@¨ S@H¦S–…=žÔƒaʘ†™*'R3U,  T€ P*P‰À˜ú?1¾¤AÊ13•µèݵ(’ŠV¶»±8¹%3Zœ†n$ºd^‹S%íÌþ 1¦Š¥ã©@êàÓwê«V wÓM·÷àð-0&ÿAì‘BH®«$Ÿ·$“LŠÂ’‚=yzø$ùh»S ¡”¼ R°k¥¢xpÙó®Tîð:ÕþÓB2õ8B&O…’abÇO¨ T€ P*@¨@Ã’é™)Ký'd˜V I¹'R“RÌ T€ P*Ð4€1=ôøx½É46Á õË3Ïs÷Ø9|q9BMK^\É0!¹+Û½ëÛWH¸gI;$•kR©ëñĘ*n¬Ä˜*–Ž?¤©W€Oß©¯B€ÓÁƒ]tÆ…JùÇ7bÔxƹ±#3Ž›»m×ÜàAd œdñI%¥J)¨äC[ê:ÊLÝÉÓŽ1)ÉÔ÷áVød˜ØëS*@¨ T€ P*Ð`„dzzÒRóñ„ Sƒk!—ãDj"ª™ T€ P*@š©0¦aoŠ2HE˜\sR1®TdB²‰%?´”ð•íĘ*n¯Ä˜*–Ž?¤©W€Oß©¯B€“1ÝØ§¿íÖ(8áÛ_œqnÄ!_Y£Æ‡TÊg’Fy ˆõ2I’;Ê,kaòÊË'|è™d¶)“’Lw$&vùT€ P*@¨ T€ 4E!™ð¨%O‚d˜šR Í¿('R›_Ì T€ P*Ðd€1=ðØøØ)Ÿ™ÉG)X” C’ÇÍ’?zC’-5’7bL7YbLKÇRÔ+À§ïÔW! @ŒÉƘzôyÈC™ñí/N?7â€X’¢H!LR™TëÍõçI>©Þël`L’‰ û{*@¨ T€ P*@š¨€’Ld˜šX M¾4'R›\¼< T€ P*Ð|€1Ýÿ踘)g}{¤uÉ•|æ$›Ê@"ÆTq«%ÆT±tü!H½|úN}²Ä˜lŒé˜N¾ðâëÃÒÑ'üò_¾÷ýˆB¾ºî‹c¤?^wá¯b”:Ÿ×ý¿ü×ÿŸ¯ýÃ7FŒ›¶yçGš¶íÞŸÀåÀ'Ÿœ|ê'œtæU×÷2sëßÞ¹÷“/¿ú*E`–¨ T€ P*@¨Ȇ ™Ž8úð#Žî4tÄ„èÇ“=ï}š"³E p"• ‚ P*@¨ȽÀ˜°l¾ƒT¨™)9&•ºæä»ßûþÑÇÿ"â0á}n7ÏóÅG>Ï}[;HŒ‰m€ äW>}ç·î3^ò/_qñ,XЧøàÃL¿ûãågÿº›g'?fX˯¾ñ—§U²€«6ìH>ƄƒiHï+È0åª[ca© T€ P*@¨@2ùÂy—?ü?É0%³vêž+N¤Ö]b^€ P*@¨Hº% R—\q R¦uj@“h{gÍ97ˆ1áŸ@Œ)éÝóGê§Ÿ¾ë§-ÏÜTò…1ù¥ŽžQå·T Pdzc²š÷š‰_^ñŸÛß|3¬â臩©ý-/N¨ T€ P*@r¤ÀÂí Yñà$ìñ„~˜²Ü8‘šåÚeÙ¨ T€ P  Á¥ cBs$ÆTá’?£P€OߨD!HbL…Haõ?ñœ™T ¹Ó‡¼¤Ã—c®m7ÀT@†‰w*@¨ T€ P*@¦0¦ÇÚ:ü틯I&2L «ˆæ\ˆ©ÍÑW¥T€ P*@­@&Í%M/1&bL‰þÛ3sT Þ ðé»Þ óüMR€1&*P¶ ŘÖLÃd¥+þîËÚ=$¦&õ±¼, T€ P*@¨È©ïºq×G Px?ÉD†)ûm‚©Ù¯c– P*@¨([¦?™Ì1&bLeÿù*%øô¥ÚdY ˆ1•°drœÇB•¥@B1&Û““Æ\ûåW_)ÉD†‰Ý> T€ P*@¨ õS }ûþ¿î8¿I2‘aª_E$èÌœHMPe0+T€ P*@¨@R(Ë Áƒc*@Œ‰SRþáÌhŠ|únŠì¼hý ÆDŒ‰ ”­@1&uÅä:d:øán!™È0Õ¿#娠T€ P*@¨@®8dà!%Ë’iÇ;È0•*#p"5#ÉbP*@¨ µT &—ÃÃÊR€1¦ZþKy.*:øôº*c†ã)wŒé¯ûò“ϾˆHø[ôü6c |üéߢ …fïÿÕÀ£LWLB2¹—É„ÔÀ|ðRT€ P*@¨ T€ äK~/ôÆÔ²¢™&¿6¹um+¶l[€$Bà£l \öÆ1ù(Ÿ¥åDj>륦T€ P*@"(i*i›È˜9¦dqâÂF¦¾vÂcmvü"Õ T w ðé;wUž—çcÊK=³œÙVÀãŠÉpÈ”ír³tT€ P*@¨ T€ 4]PJÝ'wß´o¦ŽOu¨€ {c_Mø G¶µ·aC¿jzæ™z)À‰Ôz)ËóR*@¨ T€ P¯ĘØ&¨@~àÓw~ë>ã%'Æ”ñ fñr¡€ß“á) °T€ P*@¨ T€ 4I³{ˆ¿% K`˜$`•Ú÷·cC¸%NøV¾‚7&=¬IYæeë¯'Rë¯1¯@¨ T€ P*@DbLl T ¿ ðé;¿uŸñ’cÊx³xÙW Ð2e¿âYB*@¨ T€ P*@)UBV]¶x` ÄR—Ñ]ð-Þ%i˜¹D€™¨‡œH­‡ª<' T€ P*@¨R€Ûȯ|úÎoÝg¼äĘ2^Á,^¾˜Òç nWû¶å«Ô,- T€ P*@¨ ÍS@‰%ÝL’# !WLpÈ${°½ÿ¯û›—_^¹! p"µ!2ó"T€ P*@¨ T cb3 ùU€Oßù­ûŒ—œSÆ+˜ÅË—ĘòUß,- T€ P*@¨h¾ —à] èÜ,In6íÛ„p„xsÂ3d’=8F£Ë5?ëÌAýàDjý´å™© T€ P*@¨@±ĘØ"¨@~àÓw~ë>ã%'Æ”ñ fñò¥1¦|Õ7KK¨ T€ P*@š¯ %$äÃô±„=iNÞñjßߎm9’¯ì+À‰Ôì×1KH¨ T€ P*ˆ1%¥&˜*ÐxøôÝxÍyņ(@Œ©!2ó"T 1 cjŒÎ¼  T€ P*@¨ T€ D(À‰T6*@¨ T€ P*Ð(ˆ15Ji^‡ $O>}'¯N˜£š(@Œ©&2ò$T  cJF=0T€ P*@¨ T€ P\+À‰Ô\W? O¨ T€ P*ÐPˆ15Tn^Œ $J>}'ª:˜™Ú)@Œ©vZòLT é cjz0T€ P*@¨ T€ P*À‰T¶*@¨ T€ P*Ð(ˆ15Ji^‡ $O>}'¯N˜£š(@Œ©&2ò$T  cJF=0T€ P*@¨ T€ ,Ü~ÑcmœsÈkCàDj^kžå¦T€ P*@¨h¼Ę¯9¯H’¢Ÿ¾“RÌGà”båé¨@3 ÆÔLõym*@¨ T€ P*@ cÊukàDj®«Ÿ…§T€ P*@¨h¨Ę*7/F¥Ÿ¾UÌLí ÆT;-y&*Ðtˆ15½ ˜*@¨ T€ P*@lˆ1åº!p"5×ÕÏÂS*@¨ T€ 4TbL •›£‰R€O߉ªf¦v cª–<h®ŸzðÏÿv·«}Ûš›^ P*@¨ T€ P*@Œ)×m€©¹®~ž P*@¨ T ¡ cj¨Ü¼H”|úNTu03µS€Sí´ä™¨@s½„{Õ€“›› ^ P*@¨ T€ P*ˆ1åºp"5×ÕÏÂS*@¨ T€ 4TbL •›£‰R€O߉ªf¦v cª–<h®‚1!®_T€ P*@¨ T€ Pf+@Œ©Ù5ÐÔës"µ©òóâT€ P*@¨ ¹R€S®ª›…¥E ðé› "£ cÊhŲXT€ P*@¨ T€ P*@š§1¦æiŸ€+s"5•À,P*@¨ T€ äDbL9©h“ (ðÿgïO å¨ÎtM˜î¿‡ªÕ]·ïß÷ïUU]¶Ëö-nßÕUEácd—'fmflcËÌ3¶0 FƒBLˆQbš%40‰£Yh@H$el¶þ7â‹Ü¹3"r:'2OfÆsÖ^gʼnŒŒáÙ‘ybïýìï£õÍmÑ¡И:´b¹¬%°{{÷ÄýT>xs]ì_›“"-É^2WÉÐØzm©õZp TÁqÍ€ @€@SìþÓ¶{—üUªÆ´âíáM9ÒèHmzà, @€ò@)µÌ5B ­oîŒ%€ÆÔ¡Ëeu"s•teI!—$-9]i÷ön[¯ßæ3½1o¢6°5d”ëÄ›‚k‚ @€@kH ÈD(¦Öª¤&œ ©M€Ì! @€ @câF€@~ ÐúÎoÝwø•£1uxsy€ @€ ¦H ÈD(¦¦ño•Ñ‘Ú*5Áy@€ t>4¦Î¯c®åÐúæÞèPhLZ±\ @€ @ /Ä2Š©/*¡¯IGj_×LJ @È4¦üÔ5W 8ZßÜJ©C+–Ë‚ @€ ôX@&B1õE%ôõ1éHíëàø€ @ù!€Æ”ŸºæJ!'@ë›{¢C  1uhÅrY9$ð§÷¬›³gǦ^:— @€ ´‰PL-U/Í;:R›Çš#A€ äSÞï®?Ïh}ç¹ö;úÚј:ºz¹¸\À¤ÿU“†æê¢¹X@€ @  ¸€L„bjÁÚiÆ)Ñ‘Ú Ê€ @4&îä—­ïüÖ}‡_9S‡W0——#hL9ªl.€ @­N@™ÅÔê•Ô¸ó£#µqlÙ3 @€J  1qG@ ¿h}ç·î;üÊó¥1Í™3ghÅŸK/½ôg?ûYåmxµœxâ‰C† ©|!›6mj³OÿŽMSÞëã'†´Ùisº€ @€@'è~wݘ§/èÄ+ãšj @Gj Ø€ @™@cÊ#;@[ õÝ–ÕÆIW'/éä“O>èÃ/ºdˆ• ýrñ /òƒƒûçÙç‹/S¹ Y^vÁÀËÎ/SÎxÙy N–s/• Ÿë•s.ì•Aç\•³/”,g?(µœyþ¥Q9ïÒ3½rÆy—–”s/=ãÜKO/–KN?·XN;ç’Ôrê9—ål¿\|Ê٥嬋O Ë/Ë”g^–~ùÅ™£rÆÀ_xåçg ,)§üù驜œV~vÚE©å§§]ôÓÓ.üé©ñò“S/tåÿ›ÿÔÿ¸_þä” OŠ— N:å‚“~yÁ>_Ü_’SõP+m1zôè¾ù£~ðí?þ¸•΋s @€rG`çÎ_Þó;S§NÍÝÅsÁ"@G*· @€šE©Y¤9Z­ïÖ«Î(¹Ó˜†ß>jëößo‰Êî-ÛKÊÍ·:ú¸“6¿»ÛÊ[®¼ó»·ÞùÝ›®¼ý»7J˦m»\Ù¸mWPºƒ²!*mØúÑë^Y¿å#W^Ûòák›£²nó‡QyëõAù@eÊ›QYýæAy#(¯¾±3*›v®òÊÊ;Wn|ßÊ • QY¾áý ¼®òÞ²BYºþ=W–¬oÉúK^ ÊbWÖíè*–í¯¬-–Ek·/Z•…kÞ Êêw_öÊ‚Wß Ë;*/©¬ŠÊ‹«Þ ÊÊ ¼°òí¨¬xûy¯Ì_þöüåÛTæYY”¹^™³´Û•ç–t»2{I÷ì%[g/Þ:Ë+3»¶Ê–][þöï?=vÒ‚¯l™neQP¦e³ÊÔ…›Oüåí¥1Éa:òG'¨*GÜûøQG…É”É÷#; @€z@ t˜ú=þÌÜ…«ºüî!˜L=`Øöo¡#µí« € @hhLmSUœ(2'@ë;s¤ì°5äNc’¨ä,¥äÂM·S`/½£Rª.ÉaJÚKoÿ..0…öRSÁaJL‡© 0ÉdÊÀa 4¦¢Ã$™)®1…SQcªÓa*§1¥8L¡ÆTt˜V–:L+ä0UÒ˜J¦¥1‡©[S‰ÆTt˜$35¦T‡©5&s˜T³ªMÕÝí˜L­ñõÊY@€ @ ‡ä0}åkýÆ=3ÏÚ› VnÅdÊám@4¦ö¤x¸ÒK ¿¥+dŽ«{I‰äÖ«ÄRÈ¥E`ª"0Õ”H.Ê%$’+ä’‹É…ScrÉõÐaª#\˜Q®l:¹x(¦ S¥PL¯l1éAÓ˜JÓÉM ¦6J*g“ªÛiL$P@åþ»õnL¦†|i²S@€ @ •€9LãŸ§Ìæþ,‹®uÛ_X¾å[ß9˜ìr9ºsèHÍQes©€ @}L©+€ÃC  ÐúîCøº‘ò¨1ù–Ò&)Jž¥tã-Ò˜NŒç‰sÞRR»ÉdÝåê=wZ’þÔ)G69X=ø‰,‘œ~4KXÚ€…JÒJ­‘d{Ó^ÕJ[ÐÐoÛ¾0u,Û³ÖÛqmcûm“ûqbSû|Ór¦€ @èLr˜¾úµ~ONžη)›ðÚͲPóä¹®7¿QÉdµÔXжBãEñ“¬A¡v‡ ïjo·iö’š$Ú‰Z%®ybRlâ„iLjªÄÐZÇ '½Ë5U´¥­±ý¸HNÚ^'f (ý¶íÝ™ø·ˆ­l㛆ŽÔ6®Ý™tèw2—@€ ö ‡Éw˜^ šœQ¤ØBÂk›e¡É-ŠÈ;sÑý¾]“ÉÓ˜,–’~L9²æF²ñ¢ JÖ/ÚÆiL±6Ej›¥–:°´îÇeÁ¶Pµ®Md‡¶ÓpiéÜÆ–ÂÛ¢4Ù[,n-'ÐÒÛБÚÒÕÃÉA€ t4¦ŽªN.u õ].6n¹Ó˜®½éε%éÞ$$Y ¢(éÕþGŸ`Ë~Y“È秇‹,Y¤¥ 7œ•¯ÆJš´Tˆ·”ð–ÊG]Š©K–PÌ/å2ÇÅb/¥ØKa22+Šù•Õïjâ¬+šA[(ï,xõ—TVE% ¿”H!×ËLJ'—šE®$S,‹\™ L˜,‹œ4¦1øá—bË'þò‚s. ÜõŸü¥?Ú~¦(YCíƒ+ÞVª¾¹Ë¶]ÇÃU³Ë¹N|›OìkLþlãÔhLþ€u¾×®19¶æK¹pM±N|›âÌ @€ Їä0}åkýžp¹ä¼l×jœé˃¸¿Ûâ·N®ŠÉfY(“øŒ…5™LÉhLj2X°Ø 5d,’k\¤jLÚ¦7“Ó•Ôl±ltnâ‡ÉEx²H·ÚÌÚY.“µ³ÕÝ™÷a÷öÐt¤ö– ï‡ @€@­Иj%Åvè<´¾;¯N¹¢@î4¦k~{§o Å–õª4¦²ŠR‰¥TÆU2u©Œ±”*-Eñ–ÊzKïWõ–,§˜²Å¹ô[)Iô#WÈWÁ^²a‰ÛK5†_ ºªÃI·ê°ú¬­TL!×I“Œ¥¶Ó˜<‡)J,¸<Õaª8H0wé6!½nD“Éuâ«K]=éJ*§o ’LcÒ‚VÚK±hL¶¥¨_>– ¡B4&õþÛž]·¾[˧€ÆÄ?/@€ ô-¸Ã´á}×< §‡) ÅΊ æÀ¸PL…YjžL{yÓV‰ÉT5©œh$/¦1©‰¡…/rŒ¬¥c™²]§ÜÔ‹ZÚ6ãB{³=kÁ2kë|th•LNRcG§ášT¶^Û«I¥Í´ÞO¥ÆÔ··7G‡ @€@Û@cj»*ã„!4¦ÌP²£Ö"P“Ƥž8SÚýçä“OöÛ;½€I~ð¤`yØoïèÿãR)¥ÅUJæƒKË Wf)i,)I\Iž¸ ï¾âç-Mœ¹èì‹.×oriÂŒEg_x¹~Þ’§.uá+=5{ú ¯V¼¤Þä¹KÞ¸øW×/dÏ8ÿ2+W\ç˜ñ3á— öR-á—ªæ«&0=—]¦éA¦(“ ¹Ô^SÌaÒÁò׃\r×?²ì×£_ùõèEcg®vÁ›n@ªÖÕc?5S”¯Á$óñm½öö‡*Ädò;Í]ß½zám2±´R_úZp?¶Þ6Ðof°/ o¶}l¥¿gõìûÓŽíX±ïŸZ†Úý›Šó‡ @€@Ëp“K€î;LÍ\ÿëûýêþEÎxÍæÉ¨i©†ØÕ-—ðZZl–…Ò…OY°±²ÉäÚnÁÁ©Ðx‘cd ½ËotX‹CÚ³£RÛ,5¶;$EiK5d¬¥£F °dõ›TZví›bo±3±`N±æRËÞÕOŒŽÔêŒØ€ @Ù@cʆ#{@; õÝŽµÆ9{Ì:H"©®1ij &ªOͦ-¶5Õ@cºñ •äŠï]}ãGýøM¹å•å'¹ò¾:pý²B¡•¬„–’+€â—׃HK~°¥a7üÌg?oÒÒ-w=ü…/MÒ’~kYÒÒð»Þ÷K_“«¤ßÃG>ä‡\úÌ?~þÌ †¨üdÀYZ5vB,g\à¸x9ã|bÖ¿}i?—6náêw?ýŸ?ñçgž~þe*‡ÿèDýY%öR2y\©½f (~éÿ~°rœei·:¯]ñ&õh‡ekIþ¸Å[gÕ‘B..0™ÉÔcé“?¼âíáÖ|­i9LGþø„ÀnÝ!G™zÑ/Ú Á‘C¦\~ß"Uè˜ië¾uÞ„Ëî]øËßÎUqùÜ Á¬Å[gvmv[%“©iWÇ @€ 6"`Óøgç¹<×6ŲœŸ4l–Šš'ÖB9õ¦yr˜F—¶PÔH´„×|×Úz“_Úðõj1™Úˆ§ #•û€ @Í"€ÆÔ,Ò­G€ÖwëÕ gT; HšKÍdo¯¢1Y`vÛT³-(zûþHcºú†;J $ßFÚyõ #L©\ÊYJÉÐJ‘´”ЕÔÏëŠuøªÌ|iµŒ%iL–$nß/íé Æ‹¯Ê[’´¤ßOÍX¨Å[Òr——0Nê’Kg>“%{bÚË2–T —Þ?uÁOÌ9æéûâ~.ä’ä-7Ó©Kzuèuw(ì¿Êýãf¨¼(o)T—Tî{|ƣϾ8sáͦÕï/o.£rïc3œ½tÏ£ÓU¢äqË·=4ñÅ»™þä¬eê°Ö¿~á«c'¼j/…ƒÂ²8.0É¿ñÊ–][f¼•é¯l Ê¢ ¸ðK–B.Yz 1­Ûüî²î›Ç.ÿ»Q]{=²ò³Íù˜Ãd>œ Âdw‹n iLãçm´z7gÃC¦¨O¸zæMã–«¦T5‡ž2~îÆ’A‚%Á ÁÌÛÕ·b25§9  @€:€9Lãžç" [«Ö°×?²ôô›ç«•jSh4ÅâˆË¦(êRÔBYYl¡˜Ãd¡˜l–…š'ϼ°áëßúÁ„I“;× t¤r@€ @ YИšEšã@ õÐún½:áŒj$ ˜åЦdÇR6iM©««K”½Ù_®ñØ­¶™4¦«n‹äÿ©WüÑ ©Ä)¥Uòã*ù¢’ëÛuÆ’¿àÒÃÉLzø©ÙÒ˜d¨ÈUÒBoiÝŽÐRŠ~›½¬ E%+’lAýÅGüèÄß\§¼¥“~q––•'îÀï¢HK ¹¤eùIŠ·¤ß¦1…Þ’Ê;¡Æ4ã¥0gÜìEõçˆÑOˆÙç‹ûpò™*ßúÎ!2cT´æø“Ï<ì‡'ìó…ýä-zî`•ùaì¥O}æóó—o{xÒ‹²”N9gСýOPQÏõ/Ï–õ[ë‡Ý2æ¼AÃ>õ™Ïé·MÀu¥œ½T~i«o/©¿».©ј$0=·îº1KþV“•æhLÃô£ &\ä½ÙÝ!¡Æ´ÁrÉ]óÐÍuVUj¨à‘Ù냚ZhL÷L^Mt.$49^WÝ2¶Bv¹Vûür>€ @€@_¦ýú{fž›_á‚0¹æ‰²];‡IÍϰ½ùNÐB™´P4ãåðÁ“ïy¶ÐB)„b²Yš‹2ñù×÷Çdê« Îü¸t¤fŽ”B€ @  4&n ä—­ïüÖ}Û_¹ÒÁéÇ.C 2™üKªžTNј,Þé"3µ)iLWÞ0"EH ¢%ùÝ®¼^Óñ–è-–î-©%ÅÖ¤*Jneä*­ß¡ÞX1WI©â.zýâÐOÒïTiɹJÎ[ òÄ…‹^:𻇪(Uœ–rI“_/¾ü:ë;3~¦IKzé¹W6Iv¹aăZ£>åÀ[ Õ%½äŠD¥ÓλLQ—.¼ìZéJf/I]’®tÁe×jÁb/Icºç±§œ3XÆ’ì%Eý‘ƤßJ7dØË'oÉb/™´4åÅõ*Zè÷íƒãöR˜<.–?®žðKQþ¸iiá—b™jŒÆ”˜š¦1ES!jWñF ï»C”¦AåÄ«g)“ÉÝ4n…*ÔÒÉ©¾î¼ö›çN4jA,_ƒ$0&˜LmúmÆiC€ @ iä0}9p˜æÆ‚ [ÛV-5O9˰䖥™´dÞ’~/ Ê»*úSÆ’IK7Þ(JZ¸sÌÓŠÃd—LZÒf‘º´êEW²œq–-N/Ýÿø ©K¿ºöŽOýãç'>·\*Œ¼%™I®|ó;‡hÍ)н´\±—¶É^RÚ8ýV ’Ç- 4&S— oùœ¢.)Ó¨G¦…+?'{éÁ§_À¤?öRÝöR2\ ö’“™jј†Ž<ÈÀäB1 ‹£°L%+ ±šz¿ò—×ìuÐa?Œ‡ìò&K$'‡I¹äTûªk]šL¦©/¿¥<ïöŽ¿jæ¹·=¯òàô×,äÕì(\¯!Ì»W̵'“éÛßùÞŸÿò—¶ÿ¶ã @€ ¬ |üñÇûìûåÇ&Í-i¡&kÕúÍ5KÍaR E“Ú•®…rÎmÏ?0}¥“S0H'ׄ×õ›'2™¾¼ÿçßùW½oXuÞ_õß³®Þ†íŽÔ†¡eÇ€ @ˆ@câ–€@~ ÐúÎoÝw•;ÖL$-¸ÈLvaÕ5& Ť-¸ìtmJEј®¸~„g…ù¹¼¢W¥1•³‘ÊRªj)™«ä•íÒPü”pó–¼qæC¬H':ã‚!Ò•öýÒ~Sæ¯2iIË2–iiòü•æ-IK2iÉŠÞe Š´ôÌÜ•¡®¬¼cÌÓò–î7CÛ[È%S—&ÍY¡KÀ´2(êY–ºtßã3,ð’\%Kš/«‹½¤œqOÏ^þôìeEiiù6å‰S¤¥SÎ$QÉb/ÓÒnKÃïyB}Ó*˜4Ñö®‡§Yì¥s û—}¿*¥&Иoå—® Û+[üäqQ渤½äé8±Kþ¬Ecºà²s§¬9óžÅ)½çc–ýç®­CW&½|Þ׿ñÅgç,q“›]&˜,‘œ‚0=þÜëVé ©¥A%k˜¼àMåà³àX‡ ž<á…M%ƒ¢ô½Ã޾þæ‘Ýïý“©M¿Ù8m@€ 4”ÀСCO;ç×"öš'jçFÉÍ/¿o‘ò\—­ÎÃ/›2øž—Ÿ}éMµò‚ʲB ¥˜N®0Ë›”rÇØi_øê>οêÅMW5®ÍÕŽ{~bõ¾³ZÑYÔ,i²/@€ T"€ÆÄýü õߺï„+W@%» å…“Éä_Rõ.0 PŠÃd1™œÒÔ¦TéºÛS¬£B´$½zø/Ù 6É‚'¹øI 3©’¥dÞI¬¸|p&*¹ÄU E¥3οìˆøÀø™ú­euŸ®Q†8ýÖr¡ƒ8°Xô®Óϻ̊Œ¥N>Ó¤¥ëoP“ÃiYÒ’ÖkYQ—$'Ic2i)(+Þ–tïc3,[œ%Œ»`ðµR—öùÂW¯½uÌ݉᮹uÌS³– ·Œv˽E“òÇit¥cz†â-I]ÒKZ#uéêáÚæsãg,=ø¨ãùé#šzî¥Ã´,{é>ó¹+ohL¥ö’¯.qƒ¬,ŠÊ´0Œ•Ú¥¥ä–µhLç\8xý–V½µ>)3=²ò³þlÚ´éÀ|æ¹%Þ-W˜Â@\ïqÙ” F¼ YΖ¦AƒªÊ[6àÆ¹ÎxíŠ1]Ç]9# Åêb–N.Åä ˜Ã¤+UÁdjtµ²@€ ´)™L§ž}IJó$œb´aW-”®žyÓ¸åÊ%§Ê7Ï› T×7X ezÔB‰GŠ- Å$‡i¿ý¿±xõfk¡ìþÃ'mŠ«§=÷“ј–}B€ @ Ý  1µ{ rþè94¦ž³ã}L@¹ä$ IC’ŒË(§3«®1éý²ŸôÓî“®VÓÐko¯` éÕÃx\*É/kK"'¥:Iµ[J¦+¹dpf,Y>8+æ'Y¹âú;e, ¼ü:‰JV†^wçá?:ñ¢Ë¯UŒ¥(=Ü«Á<×Óλ̕£Ÿ¶ù‹>˜»ÿ´mé¶k+B‡Í–ÕÐ/ÿôIDATGØL¦ 3Û LÎar#æ0F ƒ–K.ŒÃ8LʼnÎå&L¦¬*Žý@€ @ # ÈdúåY{ÍoŠ…Mªñ¦XTq˜ ¹Â+8L©&Óĵ×íXבx+\SÞjœë… @€@ИjÅfè@hLX©\R@ wÓ¯†Ý–ŒäÖèÕCûWaƒØKiZR”ýÍ÷“Šá”ÊXJ.¬NZh¥”èJUt¥(ÌR¥HKµHK Sê-ã-Õê-É¡iuÉ÷™zÉ4¦ª?]Ý]ýîïWu³Ú7É´ÿß|jÆb‹ÀÝ-%#i“4²R‡É™a•&'xïÃ?Ô~†l @€ ä‡ÀàË~5àÌ‹£v®Åˆ-Dv‰äâab“q˜jv˜Ô<™·üí?ÿ¥ØÛû¶½óCÛ])S+K† @€@-Иj¡Ä6èLhLY¯\Uþ4¦Ë‡ÝVÆ= ¢"]>ìÖC:.f •’ÊOª”ú­ÐÉk àÂÞÞ2¢RakjJ¸BïpIb¸ÔÜp)ÆRt,ž!.UZÊÒ[R@ EQQX i‹6GeáæÌƒ-UÝaã4&Í –ä^õ±ËÇŽX4B¥ÿcýµ¬ßö}£yÃZi Zi¯Vý*zýõ2™ž˜ÞU!°)Î~"9ËÔšg–ÑÏâ0©À œkq˜ºßû½?HPõôØ€ @ÈK]þ‹3Æ&—ç:&¶Ûš'Å\rõ8L Voßý‡O^µ¡Ôà0q€_g Ô‚‹ÏÔ½«[ËZПÖàÒ6Q5hLQ\ @€2'€Æ”9Rv¶!€ÆÔ6UʼnÖG wј†\}kjÖ6[©W¥1U—LEŠ•‚–T]N’Ÿd%4Q*”@RI„VŠ»Ja*±ô¬p^Š1 .±’Œ´T]ZJÉW>ÞR+yK1±©q“>ê4—¢¤ë4W7º¹MöÑTº¼¥9›æhÍ®?îRÑ‚¶©úÁ5“iüôWì†qSr„Àw˜,—œŒ1#€ÃT•3@€ @µL¦3ºV­ª.Ïõ\ŠÅ’hŠE&“NLí)3“4?D)µ­Ôªrñ™ô§iLzIr­VËÔ‘Z.¹o·Acê[þ€ @-K©e«†ƒ@à  151èyÔ˜\$Ï7²Hï\võ­‡ylä9Ù¨®…jf’“–J¥b8ëü­à*¥GW*`) Ï“È —4–Ì}‰—`¾l¬Ä“Ä)Ø\™¨¤Æ[*84Uƒ$5mƒ†jLNKROºùI®ŸÝ:ÓmZ°úÜÕ«®¢^uë^¯úc&Ó¸©¯D·G¨©Í]êa Gz“KŽ8LUk @€ # “éçg L LA;T1bý0±Ê6NtqS,î;m¿ý¿±xõfËjZbq˜ì NKr¡mÕìòçXX\kg©¨96lþ°¨24¦¨D.€ @ €ÆÔªìíA©=ꉳ¬›@î4¦Ë®ºµBô#½zð‘ÇVŽT)Å[Ið¤xº·²~’Â)y•ÊZJC+Õ +©y«\%+)ÆRä¿ÇÒR牫Kj¨Ædó€ýžtú¯½ªßêI·¢™Äš=\ãg×L¦Ç§,rSr„ šåL.¹™² @€ ÐS2™N>ý¢ yF`*æ¹.b‘•äӴ™!¶`g-QÉ"0ÙJ©Kú­v–kp)DSO¯¯…Þ‡ÆÔB•Á©@€ @ • 1µRmp.h.4¦æòæhM#;ið•·Î_n‚Q¬_y‹4&çU^ܣʥë­rÒ7ëðõ»}“ àÜšÔLpšçêEWª®+ÍJ‰±TÈ ΑõK™HKž´ÔzÁ–ª*MÓ˜¬Ç\`—ËÀõ¤kAÝèöªå>Ђ۾öϼ™LN^X˜ü‚Ä,grÉÕΖ-!@€ z ÈdúÙiyS·Ës]2Å¢Ðrìq&;1—?ÎiL¦+Y+Ì^5‡I –Å»öy#õ^{3·Gcj&mŽ@€ 6"€ÆÔF•Å©B chLew­B wÓ +oqRQrA¯|ıå6ð}£:–à ©µ”@QJËþf–R9Q©\h¥ ÞR])èJNèJ%¹áÂhÿV¦Ee³‚ÿeáæª’PëoÐ8IÓ‚Õoni ôÛ>èêCW×¹%’³Îô‰k'j3­±¹Âõ~˜Éôð³ aËe‘s#~¦¦zÙ²= @€ P/3™ü,rÊNnÓc¬yâ’½t˜tbjIYÂ8IÍ+×àR#KÛXp\kp¹vY½ÕjÛ£1µZp>€ @hhL-Rœú€S@çÍ G)n -íž[(ƒ~3ü #Ž­E9ªe›HKªh&%ü$ÅR* §T!\yQÉÃ…®RͺRÁX*èJ$-%µªÆiLÍøÔ†Ç0“é¡g^Žê:m„‡©iÕÁ @€ s2™~zê…aód«µCÙ7œSœ Ó{‡)Ïјò\û\; @€*@câö€@~  1å·î;üÊs§1]ò›áE»È¢yå’+ÉE?êñB¨"ÅÊV’bÅBé”-éá”ÌR D¥rq•â¡•¼èJ)–:%ÆRíQ :@cr&ÓØI RGp˜:ü˛˃ @€@‹Éô“S/ŒZ£¥A˜Ô<Áaêeu¡1õ o‡ @€@§@cêÔšåº PSuFlÑ–ò§1]1<Í1Šb IcúÁÇ(QW±¤¹Gõ©HIK©«\º7ç'yŠRZ8¥(88½µX iàhLõñbë¶!/éôÓOÿôgÿiŸ/í_®|ö¿þ?ÿåÿúÛ ¤¿ôÅý÷¡´¿þëÿíÿý×/W¨5yNC®¸ný–üòŸü¥•?Ù2™þë?ýÓõ7ŒvìÏî÷~ÿç¿´ô…´2dÎ € @¨‘À%?þÖ¾ÿ÷ß,^½¹B eÁêí»ÿðI;ÌùfhL9¿¸|@€ ”#€ÆÄ½ü@cÊoÝwø•çKcÚ¹sçœÒŸ‡ÆOŽ•Ñ<\Éš#PK-'»Ú[\cÒwÕÄ•G­zkq…A¦ÿFçò @€ Ð:ÆœÜ}Êÿ‰Ã”U… 1eE’ý@€ @ Ã 1uX…r9¨ƒS°Ø´äKcJÖLå¸5¼ 6ŠÆ´c÷ÒQ]{M}íG[¶ÿ>µâp˜Úé»™s… @€@»sòžS÷zïÃ?¤6OˆÃToõ¢1ÕKŒí!@€ hL9©h.)И¸-:”SIÖ0¬T Ðâј¦¿~”4&•·?Zš4™p˜:ô;œË‚ @€@«˜vݞߨ“KšL8L=¨34¦@ã-€ @È4¦<Ô2×thLÜJ µheÉB1Y‘ϤSõM&¦ýç² @€ ÐÇ>xsÝöÕ]É“Ðz¥o2á0õ¬ÎИzÆwA€ @ ã  1u|s(K‰›£C  1Õª°¦­¬1¹PLf2Éjr&S‡~{sY€ @èc«1q@¿yWHžÇcý÷Ž­4“ ‡©Çu†ÆÔct¼€ @M©³ë—«ƒ@%hLÜJ ï“ ­©PÖ¼õá†î]•·áÕv'ðÖ»»WlÜYù*¶nßýç¿ü¥5¿üPL. “NU&Ó»;ÿв§Ýš09+@€ @ FÓößÚ5'¹±B1IoJ®ÿ£?îþÃ'5îœÍbИ¸% @€ ThLÜÈ/4¦üÖ}‡_yÞ5¦¯^./b¡˜\@¦|\=W @€ ôaõ¥½d2IZÒo©K n¨SymòX Ѥ?µRE¯êO¥Ÿ³eýŽeëƒ h·C¢1µ[q¾€ @h4¦&æ0hAhL-X)œRИ² È> Ðw’¡˜ü€L}w^€ @èd»·w[È¥%÷ “·d—j¹äd/)ßœýù§Ý»´ «ÉB4ÉdÒŸŠádb?µ@cª[B€ @ WИrUÝ\,J 1qCt(4¦­X.+7RC1)7õÏ…B€ @ o8I~’L&‰J2“LcrÁ–,“^ÕJm¯Wµl%5ë\ß\I›©M*ŠÓ„ @€@³  15›8ǃ@ë@cjºàL2%€Æ”)NvæøäÏwmj奷Γ½¤§U·æ­¦6÷t8 @€ R‘rI1™$'½1o¢.[¿-Æ’ÉL–6N˜ádª“¢1©hK ËÄOíИjgÅ–€ @È4¦\U7 hLÜJ©C+–ËÊþ¸I“¦ü]:W @€ 4›€eˆS±¸JJg—,yœÖH]²Ôr’–,>“~k3ËF‡ÆTo…¡1ÕKŒí!@€ hL9©h.)И¸-:”S‡V,—•?hLù«s®€ @}FÀ/éG™ã´¬HKŸIÒ’e‘“·¤õV,2“ÖÛŸ½‰Ÿº 1Õ…‹!@€ hLù©k®qhLÜJ©C+–ËÊ4¦üÕ9W @€ ä…S^jšë„ @€@ИêÆæè hLT™\ŠO‰ûB©C*’Ë€ @€ €ÆÄM@€ ¤@câÆ€@~  1å·î;üÊј:¼‚¹¼ü@cÊO]s¥€ @€@Þ 1å­Æ¹^@€ ÔH©FPl$€ÆÔ•Ê%И¸ Ð!И:¤"¹ @€ teöV$€ @€Z—S¦uƒÆ”)Nv@€ Î!€ÆÔ9uÉ•@ ^hLõcû6!€ÆÔ&ÅiBÀ#Ðïþ~]Ý]  @€ кИ2­4¦Lq²3@€ t4¦Î©K®õ@cª—Û· 4¦6©(N&Øëнú?Ö_&“–¥4é÷°ùÃF,a›ì}ÛÞú­pMzI›é7ð @€ 4›S¦Äј2ÅÉÎ @€ Ð9И:§.¹ÔK©^blß&Иڤ¢8M¬Û±ÎÌ$©KZØõÇ]Zvñ™ºwukÙ~Û;|à Š€ @€šD)SÐhL™âdg€ @èhLS—\ ê%€ÆT/1¶ohLmRQœ& uiàŒúK¢ÒœMslµE`Ò‚0)8“6P& L*ZÖoøA€ @h*{ŽÛ£Þ4~2"ÐÓÔk÷LUýUûÿ\ôhFØ  @€ '€ÆÄ=ü@cÊoÝwø•Ó¥ØáÌåuYJr•t]N]rñ™´R¯Ês’á¤m”uNE ±‰@€ @Í#0ø³{~ýß›w¸N?RhLŸˆk©eéÓ^?\ @€úŒSŸ¡çÀèshL}^œ@c 15†+{…@ÃXþ8?mœþ´r Î$·IV“L&ùL¶Æe—kرc@€ @ Ò˜n:.YhéÃm{Îú«Ia™ø @€F©ahÙ1ZžSËW'Ø3hL=ãÆ» Ðg,aœ\%?UœÖ¨8{I''ÉVjË>;W @€ ä–S¦Uß“®75 ¡˜2½Ø @€bИ¸% _hLù­û¿r4¦¯`.€ @€ ÐИ2…ÞS2 ¡˜2½ Ø @€’И¸+ _hLù­û¿r4¦¯`.€ @€ ÐИ2…Þ“.9‰PL™Þì € @IhLÜÈ/4¦üÖ}‡_9S‡W0—@€ @èhL™BoÉÈD(¦Lïv@€ ThLÜÈ/4¦üÖ}‡_9S‡W0——»ÿcÛ3ë\·ct~.™+… @€Z—S¦uÓ6“®Úd"S¦÷;ƒ @€@*4&n ä—S~ë¾Ã¯©Ã+˜ËËþ¸iT×^][‡æç’¹R@€ @ u  1eZ7í¤1Y@&B1ez°3@€ ”#€ÆÄ½ü@cÊoÝwø•£1uxsyù!€Æ”ŸºæJ!@€ ÐИ2­¤vÒ˜tá ÈD(¦Lov@€ rИ¸7 _hLù­û¿ò|iLC‡Ý‹ÔIàù_þ×5kÖ´þ7Á;;ÞØgß/|ä´Ö?U΀ @è|hL™Öq{iL'ŸtÂèÑ£3ÀÎ @€ thLÜÈ/4¦üÖ}‡_y¾4¦“O>yøí£¶îø}IÙþû-QÙ}óí£Ž9î¤-Ûwo~·XÞzwwPÞQùÊ›®¼ý»7¼²éíßmÚ¶ËÊF+ÝAÙ•6lýèu¯¬ßúÑú-QymˇAÙ”u®¼õáÚ¨|°ö­Ö¼Y,«ßü (oåÕ7vFeÓÎU^Y¹qçÊï[Y¡²!*Ë7¼•×ß[æ•¥ëßseÉúK^‹Êâ×ve]Pº¢²ý•µÅ²híöEk¢²pÍö…kÞ Êêw_öÊ‚Wß Ë;*/©¬ŠÊ‹«Þ ÊÊ ¼°òí¨¬xûy¯Ì_ñöüåÛTæ¹²lÛ\¯ÌYÚíÊsK»Ÿ[•ÙKºƒ²x«Ê,Wº¶Î,–-c'-øÛ¿ÿôŒW¶¨L·²((Ó‚²YeêÂÍû|qÿ9sæ´ø7ÁÎ;¿¼_¿ÇOÿö÷™:uj‹Ÿ-§@€ t>4¦Lë¸4&õ½\yýˆ#~x<&S¦·;ƒ @€@:4&î ä—S~ë¾Ã¯ö¤0ÒR<ØRª·äE]JW—zf/¥D`zÓ"0}𪠴©·A˜ÌzqEñÞ{ŸK®Wq˜êv˜êK'7«k«Ë(§8Lr˜’Ó´E[²ÙÒÉYÙç‹ûOš<ã½ÿàÊïÿðI+|1˜Ã4þÙy+6¼¿üõHcZüZ:K=Å/,“Étð¤g&·Â©r€ @€@î 1eZå-®1Éaºú†;‚ÆiAcrÓEk“é¾ûîÏ”;ƒ @€"hLÜ È/4¦üÖ}‡_yî4¦o¹+QÉÿS¯þøØ7*º’+Ý»ä*¹²¡[º’•,ä’Š\%¿¬/ ¼eŽSþ¸ÍQY·ùè¼õáÚ¨¤ä[#u©`/ŦUug‘“æòž¼%WªL‰ L]k‹¹ä­Ý”5AY”wƒ²:(/»òê» ¢ò΂WßyIeUT^\õNPVå…•o»òüŠ·]™¿B‰ä‚\rÅtr˶Í[¶m®+K{î0Í,8L%Ó¢-Ó=‡iZÁa2é¡ñ“ý`Zºgúü‹Á¦'&Ï_& t¡˜Â €Ae©Ræ/ÝüÍï5mÑf•T‡©¥’Ê¥8L~7qi(&7ÛUÝIJÄf-zãß>h¤ɵ|WX¥ueZ?oì]®CÓúUõªõçZ±›„j›9ÉY2fähÏþ,Xmæzrõ.ëfõ«>VS…R5&¿Õú¸M2wÇâ0Ù!Ü,FQ…ƒV>ØôãkL®ÛÚÎÁQ#OwJæŠé¬Ûzí“§”ª1¹s‹u=k}lÿFØj¹7Ø€ @µ@cª•TMÛµšÆTâ0ùéäÖ¿W'8Lwô¬ ’ËS˜–×d2¹–Žßäq¤ÊiL®]c-Jÿ½z‹YDÖ@³¬íÐ#ßêÔö§köº $î]î¸H)Y£¦i?. ¯Ó˜\£Lkü¶9?6-Ç®%Ö¾K¾¤f£VÆ®Ô<-ÛÉ5Òmc¥Ø³9LÉ~€šnS6‚ @è hL}AcB 5 1µF=p™ÈÆtíÍw¦kIaê·ko 4&-”FTŠ[JciM])ÍX* ¶TFZ âë”&Œ ÂíXÙ• ƒ˜+ÕÕ¥÷z`/U¿Ô{©îLõg‘+˜¶¦a’ÀF`*hLiA˜œÕÔ"јü\rvcèN°\KünâµA¾¿°›ø] ÅTè)Þ6cáýj3™\ߨÅRgÌqñ5&ëÜLjLNJÕ˜,,ë0µ·ûF‘uຯ<; '¹®g{£‹½dÛ[Ÿ²¥rs¯J²xûNcÒ²u1»^æØA+Ÿ¡ËUg-§1Ùz;D-<-î”ýXG³MÀ5¥,yJõjLÉýëº:©3ÿÿÊ!@€@Þ  1ez´”Æ”t˜lnUÐ> Ök–T<SQc rÇtD•ìrIÉkVÕ˜¬qÓ˜¬B¬µå+A¶Æ×˜Re#¿ÙkÍdýXcÊ5™]ÐNU»M¦h÷Û¡î4ìþ®ìlµ;–ü½¥¾ä·ß]SÔšÆÖ¨´ íÜR–;¹ÊVºÀ™Þ¿ì € @ И—]C Å  1µxqz=%?é¦;]¢·äÂ57ÝÙÿèRc)ÅVF¡•,ÆÒ~ñrÃYž¸0ÌR2Ò’E]ŠÅ[JzK˜ÖSï0Z6ºäþ{ú¿ƒ÷A€ @ 4¦j„êz½u4¦Àaº±K.½qº#Ö8æØ„¡˜¬qªÆ~e“)©1ù¸\67­´E¾×éDU5&méhÚ›ZL¾¾ãÅ6#Åþ´ý[KÓNFµÐ¹nM2“Äu'ov]³1¦1ù»Òé™n¥ ´·ûû±³Š½d F×î³£h?&?(-XcV+¿ó®êºKÙ€ @ O 1õ v – €ÆÔÕÀIdO wÓ°ßÞYb ¹\oá‚^•Æ”0“*ZJæ*•°éJiÆRi)ðTR¼%›àXš0®’ºK×µ¶ræ¸ –eŽ‹Å^z9™<. _%\4Þ•ùa¯åüåÛ¬¨û2(Ë‚¢~LW|{IËÏ-)–¬&Ë"7¦4&ç0…Ò[—+Ía*t— ÅdÝÄRÁ¦¾¼é€«d—³žMs’Ô¿©ß&è¸×Óê¢ø¨?×zB-¨¾ýX€Û‰ÛÀú^­ûU½«¶¥S‚lþŒÅ²©±¶ÞwƒÜnMÓ±W]'ó~t ê!ìŠÊ4y†4& ÈËRgWa徭§Ã嘫[Ù]—u1'¡9à.o‚»XëgwÐ’û7DcÊþ¿+{„ @@cÊôhIÓÕÎaJ6N]®óXœàÒPLs—íSµîpø1#Gݛʩ²ÆäÚ_¹ÖæÃÔ¥1Yê4µÔ¬…¥·›Bdk*hLÖ(³¦Ÿk~º5j[Åd#×Ôzkšùâ˜ÆÛ¹NÉšØvVnÚ‹½dL\*: ¬k,kÁµ‹uÚ•¶´†§]ˆ«½„É”ég—A€ †@cj8b–%€ÆÔ²UÉõŽ@IÝ.Óõ¹Ô½;nß¼ÛžGÖ‘Ó¼½zÔO(nP¤T!œ’YJ•]¥ïüà°(7ÜÆ÷/»â†ï|ÿ0ý¶ç¢Ë­ ¾â‹¯cåß¿hÿ£O²e“–´fÐÐ,‰XP¼KÓ_|ÕB.}û{‡Ê[ª¬.¹ÀKGüèÄ'¦¾Äï Õ¥ñSøÝCætmR,+úS¹É åøyÉJ{éÔsöÃ,“Ô%-?òÌ‹*Zð¦È^J LaW¦+~ø%™L¡À´µß·îe&˜¬ôVcÚ½sϺ9 ½›ÍaÿìüHzÛðþO®™}àùTŽº|êIÃf=ûò[ ²eu:ý•Í'^=3H'†b:ïö¾yî„ÃO~pÆk‘Ɔ°šüÒÆ¯W3™zyQnJh/÷ÃÛ!@€ v%€Æ”iÍ5NcšûF·êùšÃä§gÜ2ÿ†G—¹\r×=²ôÚ‡—ZãT= 7_ñôóoXœà'çoüåoç¸qýÆ©"+¿¼ÉädšrV †äÎÜ-»6©[ãz·LôÑ[,€“[ïÖh½ _d[ºmü½iž‰…ε·«Ôæ°^Õ©&ÏÁ?º{£íÊíÜÂ&¥Bð_ÒÛÝ[´`—YîJý¾>ÿt!8LU?l@€ZS«Õçæ@cjkŽ”1?ñ‘‹“â‚•TÒ˜ä0íµ×^®;ÃÅVÑÄ,÷þŒO¶Á»s³}÷È_Vœ4¦Ø«+‹”,Üû©Å‰JÁB¨(Y9ù”³?óÙÿj‰áä*õ?æ¤G'>'?IËêì{dÂs_øò×ξèriL~¤¥Ï|öó*&0IZzzÆBUÇY1{©˜*NËë{ÉÆ}æ?¯lqé ãÂŒc®¨Wñß¾´ßOÌt—ÆŒŸ©CÈmr—>ýŸWŸcd/yêÒiç]vÿ¸ꋌeŽÛç‹û}ê3ŸŸ0{¹…_Úç ûÝóØŒ{±Ï¾ZŒ½TKø%/“~I Î?|æsQ ¹®­åRÈM/“BΘz«1I`š4tÏùÿyϘ“wÛ¦yvS…A˜Þ—½ôÔüMÁ]ñÚuËd²n⦯;â²)*ÖMüÛÇ—«›XöØØ¯6x²…bLÑ·g_ÜðõoU‰ÉÔ¸ëbÏ€ @€@ç@cÊ´Ž§1êÚëžÅÿSU™)èQ¹aD¬q:tô+Ö8Uůî_¤¢Æ©ºîšôê·Î›ðèìõ–Nîð˦ÜþôªÛŸZ©Æ© ÅdS¥€ÿþaec2eŠA€ @ 3  1uf½rU¨…S-”ئÅhò•& ÚâXÛ\,-Ø­²“f‰YXiÓ˜,¶¶] ¦»Å.¹ÊéX§[9Iëõê‘?>Á6(Ñ’ìOONŠ-›¥/¯¿wßÓBI6’U’±4ë¥Õ¶lŠÒÙ^n–\‰"-­ß¡ Ž:ú¤«oi‚?p–\%iLlé’__æCnùÔ¥Qc'È^ÒŸÒY$Ýõà-_ò«ë¬÷pÊüUgœ?DeüÔ—]Ô¥3οìâ˯û·/î'uÉÅ^=n¦Ö¨Ü0âAS—´7 ¼4ôº;¤.]8äZù1³nüÖw9þä3g.Ü`—^¥¥Ûî{ê›ß9D™N9w°Å^’½tÏ£Óï~tú¿~á«–<îüÁ×üòìAÃn£ù—úýäÌ¥Òkž˜¹ô¼AÃ̳9wÐ0^?c逳©<ðôóR—T®¼yô/κtÐU·Icòí¥™][f¨¼•²S!ü’‹ÃÔciÃë›w>28˜ô¡‘ÿÌa÷Ì<'0Ù#éÉù›mÝŽñó69dŠU´â0i¶«4&ë&>þª™÷N^Øc˶©§X’SÑʺ‰»¶Ô¤^ßÿ[?˜0ir{}Š9[@€ @ = 1eZO Õ˜d2U–™Ôr•¦Âì×8ýõèW¬ËB]r˜.—Æ´fû5c—¨}ªÆé#³×«áÆÇ—slÂÆé9·=ÅèW¬qjLA[~Ú¢-ß;ìèrÙå2¥ÈÎ @€ ÐИ:°R¹$ÔH ‘CÕ5ž›A ^5ÉiL“_Év"CI?Z¨’TÎiL¾ºÔÖ“õ»%‹HWJcúÑ éN’³”^WDœ÷\q9à’ /­xKÞÒ‹ËßrA•Ü‚¤%-ËXúö÷•œ¤å}¿ôµ‡Ÿší‡YÒJYJ–$N‚Ú@&“ü$EZÚ÷KûÉRzðÉY~ïÐ+o¸sÞ’7´FJg‘x¤pJ>1ëÀïzñ¯®›<¥B.ýöŽUôÒ¸) ž·R 7ÞñàÀ˯Sì%©K.gÜèq3ä0=öìKÚ`ö¢²a´ >ÇN>SYáî|†~[Î89L¿ºv„…\rEÓ­÷=õôìe.ö’ì%9Lw?hLò–ôû¼ÁרŸò–TŽýé²—ŽùéŸúÌçÌ^ú×}¿:nÆR¹JWÝ<ú滟ø—}¿:æ©çe/iáαS>òx§1ùö’ú=#iÑ–é‹‚>P^²ó–z£1I`zïáÁ>÷ÿˆ¦FjLr˜¾¼_à0)ü’K5h®Û‘C¦^tç‹¿ç¹Êaºë™Õ&ÔTWõ«ÊTG‡ž2vÆzÙc"/iÌ´uJÉçf»†”6O|“©ÞïU¶‡ @€j#€ÆT§·j‚ÆTNf’äޒ0Q“Št%“–T~sÃZÖdGIKú½pM 1YÈ¥‘cž>ñçgž~þe*oéŠëï”átúy—©„êÒ;ßúî!Ê §¨KrIËÒ˜$Á(ð’t%EôÑÞÔçø©ð·å‰SÎ8…\º÷±˜‚¨Kaà%M¬T:¹ äÒò@WºõÞ'ÕqhLD“ÙK’–,ü’–Çë÷¾_•½¤ßý¾}ðȇ§ ¾ú¶g]ªrðQÇßùÐT-ó“ÓÍa² LÒ˜\ì¥4{© 0• ¿Ô3iÜ#ãR&Ó˜®Ú7È.—iÙùè¥_Þï€ÇŸ™ëwaºÂI®ê)¾åÉ•ãçmxpÆk§Þ4ïˆ!SÌaRªX±úUMªiLÚ@ÝÄ.iô´uE‡)˜í ^˜LmÿÏ@€ @ 5  1eZ/¦1i|"óböR¬¸4sÃTèH)†‘.4N¥1™Ã¤8L'^-i¡5NÕàÆéóÖ+xó @cZ Æ©ÒÉÓ] ü8Áš†äÚéÉô«s³m_³7T"°nN¦Sv@€ú†Sßpç¨hhL­P œC 1±©÷í7ר` éÕ#~x|… ßÞ“œ”PNJ-’“$*)œŠ-HQ2QÉ\¥ÐOrÒÒv‹±$3I‰á¬H!ÒoÙKr•NúÅYOL{ÙrÃ)Ò’^ÒÆ ³¤ràw‘´ü]½dÒ’²ÅÉI’¨fˆ º-Ø’%ó–´ uIÞ’-ï#ieËG Š·$éÑg_”ºäB.iùžÇf(mÜ=κ„…‹²ÅIcúÆ¿¬"EI¿-üÒ¨G¦©Xø%Å^RÚ8yK*~I~ÒO¿ ‡éÜK‡É^Ò‚b/)yœ\%½dE˜ôûޱSÌ^:àÀƒŠöR8q³®ðK=ИøÊWÞº|ÿ’L&05¬Œì·×ÿ¹Ý‡f/EaºÂF˜ÆÍÝ`‰äTõšáúØs¯IW½c“ée‡žüàô×ÔMhLƒ&žºÖEìˆyš×ðû&îûůìþÃ'=ú†áM€ @€Ò 1ez_,Ü2(Õ7jèÊkü7ͱñí%C:lœN•À¤Ž kœÊarßBs˜ÔÃhL3׫}*‡iШ@cRãTÓ%w½‹ìÚéOÌzõþÓÿ²ùçÓ¸æ6{†@ }Mñ@€ÚŸSû×!Wž@cê)9Þ×ç²Ñ˜tÚÑ®]»´ PNJP×çÖƒÆtÅu·Wpôª4¦ØŠS¥„f’+NNûÔl+2–Æ>5ËD¥§¦½¬>¾©Ï¯Ò²”N)á´ ß27%ìT þ\³ý‰©/+Ò’t%õ žqþe*ã§,dÒ’2Ä)7œ¤1Ù”G½Ë—–x鄟Ÿiñ–$-)=ÜEC®Õoó–¾õC”*μ%•û4&‹åóÈ3/JKRѲ~OyCr)X–ºtÊ9ƒ”-.˜–ÅŒ¥±_ ¦W3,KÉB.9鮇§Yì%˧ù—xIÞÒ¸éKMZR¼¥s.vôONc/m¹qÔøï/ué77ÝoöÒ?|úsžºTkò¸r©åÆLXð·ÿ©Ê‰çöùâþŸ¼åÅÉ¿¿æ)ý}·´G³÷üòá¶Üœ±· :ôÔs.‰n¼‚ú¦[(0Û¤1ÍÙ`1·$0}ë¼ S¾eÝÄšêª LÆ´|ÛoÆtsÛóê&žúòæCMN Ť ¿cì´ýöÿÆâÕ›×où“©÷Ç @€ ˆSÖ·ÂÔו´´âíáÙ–Tê±Uÿ´íwÏë F­~’b¯H4+jœ*“9Lê‘Ã4äÞ…Ö8µDçÍ\¯Æé=Ï®9îÊjœª7àç7Ì9iµÚûÖÀ÷ÁËaRãtÒ„Éë_šóÑŠÒVv¬ÑÍŸÈ„€¢k£1eý5Åþ @èhL}‚ƒB % 1µD5p=!à4¦uëÖõë×ÏvÑ¿ý©…½*ïRÛuuuÙ6cÇŽÕûí§''Òï 4¦ko÷•£Ø²^=ü‡Ç{A’Š)ÞÒV!”Š¥EÉ…SŠÅUÒŸ¿½s¬ì¥3.¢ß¿½c¬:ûf)Xsþ‰JJúfnŠ• =ÜêwU´ ôpêtâ”îð0=œ|¦¡×ÝiéáÿÑ ³_Ù¨ý q³m”™$oIE/Mzn…¤%­9þä3U´ uɼ%å‰s—Îç”s;iiŸ/|Uê’b,÷³3ä-rö )J·Üû¤yK˜ä-YÂ8+‡(ÜOÏ·${ɦÙKºlIÒ’Ô%éJWÞéôŸŸlyß“óU´pò—tÄñÒ˜s^}A©-s\K©vI–JŠÌ4æäÝÚÉtö%áè2ÅMú¥.YQ(¦›Æ-wÝÄê#>þª™Aˆ¬°^ÔS¬8Lr˜®yxIj7±ï0Ùb25¨6Ù- @€rG)ë*·¼rYïuOLcr“;L¦BWIÐb}jŸjŽ"0¹,çr˜.»w¡9LÊ%'iìŒ×¬qªDçgßú¼ŠÚ§Aã´+ˆµì§“‹¦é/XËTå£ÝÊüJÙ!JÜt · @A©3ê‘«€@O 1õ„ïi NcÒÙ 8Ð4¤ØÉÕÝÿÕÝÝÝ—Õ£“Æ4ôÚÛ“š‘[£Wë\… ’/Eñ“,ŠR!’…SrEiàÓƒŠ“ç¯”®4~ê‚ÀU -%EWÒšqSX28W”Î,=>yXzî•*’–T”îú>3g…IK*–ÎO÷س/Y¤%¹J¦+Y1cIñ–f¼¼Áe‹“·¤`KOzÑRÅY¶8r顉/ÞýÈôb¼¥eÛôç”×›´¤…±^p ã4Ãrò ë|ú%Œ“½¤¨K<õ¼~Ë[ºó¡©*н4+¶s˜xéþ§æ[Ú8+#œ¢8Lši±—™²äö§<2eñ}OÌë½½äĦz5&ëNݶ`ÊõvYR¹†iLºÇe2röÅîÖŠ·ð& o‰ ÞƒÀZa-[.9ç0ÙT×§žßÅa*t;zI‡ “©Gß+¼ € @H#€Æ”õ}Ñh))0¹+Éd½%®ßCíÓ‰/¼!KÉú+zŽ¢//îv¥ÆÏÝhSÐ8]Ú}פÕ*%¹Îm¶¶yÒaÂdÊúÞaiИ¸/ @èhLR“\ê'Ðà¡êúOˆw@ ukLÙ¶ö"é××ÜsŒü?õª:æ*là^rZ’?©¸úI®Äü¤ØŸÖåç•ÀR²$ƒ³Rp•lÁRÂËÊ@dq¹áœ®ä¤%ç*Ť¥0O\QZ ’ÄòÄYocIYt>ÆŠ¯.I𠤥 l•´dE}”ÅRP—L`’ºdS0] ¤%+¡ºTŒº”Eà¥Ô˜L=Ó˜6m ²+‰äÔç•Иvoï^rß°U§$^L]YùÓ “é—g]lÒ›Ý9‘ÀTp˜\-[múÝĪ s˜Ô!U±¿œÃ„ÉÔG_N€ @G)ë*mœÆTA`ra&S¢qLU&Ø, ; ÂÎ(N°×8-ç0%M¦lÛÚYWûkChLmXiœ2 @©И¸1 _hLù­û¿òÜiL¿ºæ¶¸xäùF¿v[Ð+W*!Õh#¥¸Jq?)Pœ¥TATJq• ;t%ÅlOêJQ„ž0Ò’3–,ÒRi)œ1™"-…1~\©Ó[ŠBÇWS—2ËW!œ½Ô+ɾ>Üû’˜8 Ÿt¥7æMŒ­ß¾ºK/õàÅL¦‚èim~¦ –à 5íÌâ0yÝÄõ9L˜L=¨#Þ@€ Ä  1e}O4HcÚö»çk“ú[„É¢.9QÉÉi¥â6ÙW‘f—Öò$“éäÓ/²LIIq˜¢:"S-4Ù€ @h4¦¬Á¶”Ƥ‹“ÉtÐÇú)ÎÃŽˆh~”5NcA‚Ÿ˜õê~ûcÒô\NóÔ…÷>üC ^ÚÚYWûkyhL-_Eœ  @5@cª›A   1u`¥rIÜiLƒ¯¼ÅwŒb²Ñ +o‰fšiTK sº%Kz–·dê·òyß\2¸ \˜/,µÌz ­”„V²äbµXŠU6– éáÚ(ÒRå8Löjæ“å3Iê’%u¶JW²¢—ô§t%½$I ’œ´FêU®©ê—“L¦ŸvQÁTóúˆ-S0ÏuË´ðUÈ%W•'@€ @Ù@cÊši«iLº>3™ 3©‚N‰’,祉Î{ì0é@Íikg]c쯵  1µvýpv€ ÔN©vVl N#€ÆÔi5ÊõDr§1ITª éU›JØ“²t[…änÎIŠ-TV”J#*Õ&*• ­´µ^])ÅXZ´ÙÉ1µHB­¿M¶ÓŸvïr•$0ÉL’¥´µkŽŠ¥I;ý6¥ÉrÏéG ú³ÆPLî«K&ÓOO½Ð4µ¨fó\q˜ø¦‡ @€úŒSÖè[PcÒ%ÊdúÁÇxSI&ׇЇ©™mí¬+ýµ04¦®N € º 1Õ…‹!ÐQИ:ª:¹˜"ÜiL—þfx9£Hëõª4¦ $_Š<$ ˜T>fR,’B©H©–XJ.ºR—™+©%Ì—Z©$œ])ºR9¡*[©É_-2™~rê…Aî?˜,Ó¢(S“«ƒÃA€ @%И²¾!ZScÒUÊdúþáÇYäüÁ^ã´7SÖÙ И¸ @èhLR“\ê'€ÆT?3ÞÑr§1]rÅðrÙÙ´^¯ºpè5$qsÙÜü…­Éänš•h%%Ë[le×ÖY•%/¢R-¢Rº«˜.ÅRH=Öú‘“q†m­1é+&0™N¹0)0á0µÅ÷/' @€ N&€Æ”uí¶¬Æ¤ L¦ÃŽQã4œ(Uȇ)ëýeD)#ì€ >'€ÆÔçUÀ @ Ï 1õzÜXyÔ˜œT”\ÆôƒÃƒXèµZG•ͤšœ$?¢R¥@J.âNÐ-è—EA/¡•0O’W©í©Ý5&}=Èd:é” b{ÇØiûíÿÅ«7¯ßòQ…²ûŸ4ö †½C€ @¹%€Æ”uÕ·²Æ¤k•Éô½ÃŽŽe¢ÇaÊú.`Ù@cÊŽ%{‚ @ o  1õ-޾$€ÆÔ—ô9v äNcºxèðò騶êU „Þ‹²EI¾‚<_®„ ¿ª–¸œd¢’§(U²”Jg:Ö¢ï°èI_2™NüeÑdÂajàW&»† @€j$€ÆT#¨š7kqI×a&“ëpÀaª¹nÙ°/ 1õuŽ @€@# 15‚*û„@{@cjzâ,ë&;iàЛ+EzUQЫ*G©¤{HeÂ&¥ÅOJ‹¢dÙßò÷­¡ÆUghLúÜ;“ ‡©îoAÞ@€ 4‚SÖT[_cÒ;“ ‡)ëúgY@cÊš(ûƒ @ ¯ 1õyŽ ¾'€ÆÔ÷uÀ4„@î4¦cO>ëÆ»ÆedJ9ö§g}yÿS_Š­¼aäø2eÜ #«—ëGŽ£´AWßñÿý/ÿWå3ùüûç‡ÆOöS³mÚ¶«!ÇÞíT&Ó¡?ü ¹äzG‘wC€ @@cʤÛM[hL:[3™¾´ß—&M¡r¢ó÷>üCÖØj&€ÆT3*6„ @ Å  1µxqzh 4¦Âe×}I _Ó£>z`霿ì³ï—þiïÿ[ÉŸLà+ûðéÏ|¶ò~óÀï¾´t}ëkLú"ùí…¿\¼bCånâÝø¤/¿r86 @€ hLYWt»hLºîŸþêo®ø'8LYßì/ShL™âdg€ ô!4¦>„Ï¡!ÐÇИú¸8|£äKcJR¬Ü§Æ«H%Кјöüéã=ÿî½É·W¨5¦F}•²_@€ @ F)ë[¢4¦Q]{M[{Z…Æ)q˜²¾;Ø_ýИêgÆ; @hMhL­Y/œšA©”9F@cúSõhQiÖð=ú_%“é½S¯‡©¾b9$ @€rK)ëªo/IgûÑî?¥6Nq˜²¾5Ø_ 1õo‚ @   1µ`¥pJh4¦&æ0Í&€Æ„ƺ ´¢Æ†b 4&•YÃÕ)ë,Æajö—+ǃ @€@Î  1e}´‘Æ´õ£9;?^#I“ ‡)ëû‚ýõ”SOÉñ>@€ZS«Õçæ@cjkŽÔThLu+,õFîaûÎ#Њ“…b²"ŸéOû&SS¿V9 @€ hLYßm¤1ù—î›L8LYßì¯Иz·B€ ÐRИZª:84•SSqs°æ@cBc‚@ÝZNcòC12é[ÄL&¦æ}¡r$@€ @À@cÊúfhA©{Ww¿ûûU½P3™p˜ª‚bƒ¦@cj*n@€@  15.»†@‹@cjñ âôzJ ïÓï>þõ£U(o¿÷ûím(9! ê~çý*5®Û¦§Ÿ¸Æ¼ÏÅädÒÁþã“¿4æì€ @€@EhLYß -¨1]>¶ÿcýwýq—•u;ÖéwWw—»týiË ÞzÅ_Ÿ5öú  1ÕÏŒw@€ КИZ³^8+4ƒS3(sŒ> w©sHdK ŠÉ È”í¡Ø @€ Z  1ÕJªÖíZMc’¢$‡iÀÄs6Í8c -O\;ÑÅg6˜Š.Ok´J-¡›jÅÁvè%4¦^äí€ ´ 4¦–© NM'€ÆÔtä°9ИšÃ™£@ a’¡˜J25ìÀì€ @€@yhLYß­¦1éú¤%YŒ%-ŒX4B úS>“]ºô§“™´Fž1™²¾/Ø_O  1õ”ïƒ @ Õ 1µZp>h4¦æ±æHM%€ÆÔTÜ (Љ€Lƒfw€ @€@ИêVuóÔ˜ö¾mo;m·àKK¶R¿%9IiRqÚSÕ‹e4œSÃs@€šD©I 9 ZS V §”4¦,(²´›öèÕ¤¡­p.œ @€ whLYß­¦1­Û±Î’Ä)À’ËçD%ešs“ÒÏ ‹ØÄZ‚SKT'@€@И2€È. ЦИڴâ8íjИªâu´ 4¦v©)΀ @y €Æ”u-·šÆdö’%ÉI Âd—«5c—•äüq*Zc ÚX¿Î˜5öž@cê)9Þ@€@«@cjµá| Ð<hLÍcÍ‘šJ©©¸9H©pÙ5 @€ P'4¦:UݼÕ4&°ì%K*Ý»ºíü¢I+%6iAëm¥yNÒ›ª^#@ yИšÇš#A€ ÐXhLåËÞ!ÐÊИZ¹v8·^@cê<Þ –"€ÆÔRÕÁÉ@€ @ çИ²¾ZPcÊúÙšH©‰°9 @ %€ÆÔP¼ì-M©¥«‡“ë94¦ž³ãh-hL­Uœ  @€òM)ëúGcÊš(ûË74¦|×?W@è$hLT›\ ê#€ÆT/¶nhLmSUœ(ª@câ @€Z‡SÖuÆ”5Qö—ohLù®®€ ÐIИ:©6¹ÔG©>^lÝ6Иڦª8QT!€ÆÄ-@€ ´4¦¬ë¢4¦Q]{él³Àþ )4¦Lq²3@€úSÂçÐèchL}\¾QИE–ýB ÙИšMœãA€ @å  1e}w 1eM”ýå›S¾ëŸ«‡ t4¦NªM®õ@cª[· 4¦¶©*NU 1q‹@€ @­C)ëº@cÊš(ûË74¦|×?W@è$hLT›\ ê#€ÆT/¶nhLmSUœ(ª@câ @€Z‡SÖuÆ”5Qö—ohLù®®€ ÐIИ:©6¹ÔG©>^lÝ6Иڦª8QT!€ÆÄ-@€ ´4¦¬ë)k¢ì/ßИò]ÿ\= @ “ 1uRmr-¨S}¼Øºm 1µMUq¢¨B‰[€ @hhLY×SÖDÙ_¾  1å»þ¹z@€@'@cê¤ÚäZ P4¦úx±uÛ@cj›ªâD!@€ @mC)ëªBcÊš(ûË74¦|×?W@è$hLT›\ ê#€ÆT/¶nhLmSUœ(ŒÀ¼+LÐïƒ7×Å€líš³ä¾aP‚ @€ ÐИ²®4¦¬‰²¿|@cÊwýsõ€ N"€ÆÔIµÉµ@ >hLõñbë¶!€ÆÔ6UʼnB@ä*IcÚ½½;IcÁ-W=>J€ @€Z‚SÖՀƔ5Qö—ohLù®®€ ÐIИ:©6¹ÔG©>^lÝ6Иڦª8QÈaš>°¿ŠDCÒ’Â/½6y¬‘Qˆ¦í«»’ë哤%½ªtr–`έזŠÌdk™©m/‡ @€ÚÀÒ§Ëv¥é%~zG •5&]ÙŠ·‡—GÙ±{iï.wC И•]B€ ÐL÷.ùëÔ'ð±Ëÿ¾™§Á± f˜5<½ï嬿Úóá¶fŸ ǃ@c 15†+{…@˜«¤kAN’¢.é·iLiik×ý©õÚÀrÌiY öÛe—kÀ©±K@€ @!Ô€LZÉO¯ ´¸ÆT. Óô×êõ¥³4€S ²K@€šI \@&B15³8ú€@¹€L„bêƒÊà"€ÆÔ(²ì™ðSÂ)‘œŠáÿÖŸŠ½ä^²л´Æb2ñ@€ @ ±R2Š) è-®1éS2Š)‹Êg €ÆÔ¨ì€ &Hd"S“«€ÃA o$2Š©oj‚£6ŠS£È²_@€ @€@ Ä2Š)£› õ5¦d@&B1eTùì¦И•]B€ ÐdÉ€L„bjrp8ô d@&B1õMMpÔF@cjYö @€ @È#X@&B1et´¾Æ¤ d"SF•Ïn@©PÙ% @Í'àd"SóùsDô? ¡˜ú¬8p£ 15Š,û… @€ 䔀 ÈD(¦ìИü€L„bÊ®òÙS 15*»„ @ ùü€L„bj>Ž>#àd"SŸUn4¦F‘e¿h6›öœº×žIC›}\Ž@€ @ FÀd"Sv÷F[hLº\‰PLÙU>{j4¦@e—€ ô  ÈD(¦>ÏA!З, ¡˜ú²8v£ 15Š,û…@³  15›8ǃ @€ÊP&B1ezƒ´‹Æd™Å”iå³³@cjTv @€@Ÿ°€L„bêø}IÀ2Š©/ë€c7Š@¾4¦¥K—­øs饗žvÚi•·áÕ#ð³Ÿý¬ò]{íµüq£>‚îwǦGíõñC2Ü%»‚ @€ Ð3›&Ú9ÿ¡ž½—w¥hI'?ñ…Á[ß[H=B ¥  1µtõpr€:Àœ9sªk8IÃs¤«ü óuÂÍÑ€k¸æÁkÀ^Ù% ÐêÜyÉÇï¼ÑêgÉùA ~ùÒ˜N>ùäƒ9ü¢K†X¹0V.òƒƒÿçÙç‹/S¹ Y^vAXÎ/Sλhpj9÷¢ÁQ¹pð¹^9çÂÁ^tÎQ9û‚AÉrÖƒÎ:?¥œyþ¥Q9ïÒ3½rÆy—ÆË¹—žqË%§Ÿ[,§sIj9õœK‚r¶_.>õì‹O‰•³.>嬋Y¦ 8óâ° Œ•_œ90(gÄËÏÏXRNøóÓ/R99­üì´‹RËOO»((§^+?9õBWúÿËÿýoþÓON¹På¤x¹à¤S.8é—üíßJíú?\Í~ÇÔ©S¿¼ßG}·_{HWÍÆÃñ @€ æØ´i“š'xàÎ;›wÔN?R»hL[Úgß/uÔQ4N;ý–lóëCcjó äô!´>= {üOJ†¢.â?}ÿàÃ4 •rŠ 3ÅF— ƒJ)ÃI±Q¤ØÈQqÀ¨8TÅÆ†J‡„¼Á ÄPlÜÇî)â‰îÄÆtl(ç¿þ·>àÀGpâ7|ý[?Ð0_ëW}óÏPXÔþ=ztóÍ!>$ ÓúîÃ:àÐ #;iøí£¶nÿ½Ê–¨ìÞ²½Xn¾}ÔÑÇ´ùÝÝ®¼õîî ¼£ò;•7]yûwoxeÓÛ¿Û´m—+·íÚØ• Ý»Âòц­½î•õ[>råµ-¾¶9*ë6•·>\”¬¬y³XV¿ùÁê7¬ì|Õʦ ¬òÊÊ;Wn|ßÊ • QY¾áý ¼þþ²×ßseéú÷\Y²þ½%ëw,y-(‹]Y·£«X¶¿²¶X­Ý¾hMT®y7(«ƒò²+¯¾» *ï,xõ—TVEåÅUïeeP^Xù¶•çWËüoÏ_®²Mež•eA™ë•9K»]yni÷sK¢2{I÷ì%[g/Ê,Wº¶Î,”][ÆNZð·ÿé¯l™îÊ¢-Ó¢²yÚ¢ÍSnÞç‹û·¾Æ¤Tÿþ½C®êqïãt7ì “C€ @Õ „S¿)s—>6i.&Su^5oÑ“&ÕþóK6ޏoÓšë– û‚S_P瘀rE@OÂOL˜E¡ü±§›n ¤¢Q§ÂxSl˜)6ºT²±$7d£H…ñ£häȆ܀‘Ɖ¢A" ƆÜÀPa<È ÙH² pè§8ècÃ=±â±Áhdgé6Ó±7”óƒÃ¹øŠá…œ-¸‰Æn C6ýêf4¦ä‡HL®¼~„jðˆÉ”«/.6çŠCô¾s~+tèåçNc’¨´y{ÑRò%-ß|[ðÔXV]’ÃTj/ÉdŠÛKµL[K¦¤Ã L t˜–{“d¦R)r˜ŠÓº‹=‡©+æ04¦…‰GXïA6x–­Åaª[cò¦à©·à0ùϾ¾Æä&-¤hL‹¶L÷¦i ÛCc²T‹^íZ¯í¸“©C¿¯¹,@€ ´>9L_Ù¯ßÔ¹ËÔÒÔ@È#1™2«´Öטä0©ö_X²‰ÆifµÎŽG©qlÙ3 „¤1›0-6å?ýöֻɟ0ΖæÉ‡#Mµ8Lë óáÝLxÓ˜l¼›ún“›ñîÏu÷¦¸{“Û£!¡hB»›ÍnóØ£Iì…éë6qÝÍZ÷5&7SÝטŠóÒÃTIÃ7IéB4¦Ä‡+p˜naÃ| Lp8&ß?Ȇ†óQϹ¾ÊÜiL7Ý6*zLŒb,#-)ØRôÔX>ê’E`J‰½”j/UÀT)Sä0Ń0â0EA˜Â8L%A˜<­¾\¦¾p˜ J~!SôDë¹ùMÅ43|¶hLB1µ~4¦àÕ÷]´z›=§òÙº·ÝCL¦\³sñ€ @èÃôµ~Óæ-S«Ó5O™0‡˜L™TG‹kLÃôµ~/.ÝTÒ8ešM&uÏNA©TÙ' xô üøÓÓ é>R2~h@êÇÇžä9• LA–—âÃâ0¹Ì±œ©“<*†b ³vX(¦X²ŽÔPLnN{!S© 1Y(¦`úºÓ˜i7B©˜jâ1ù¡˜")̧DcEc*:LʤL>²g 1Å>ar˜®ºa„Õ¦iLJ«rXÿãˆÉÄW:›@úÐ0­ïήõü]]î4&=ÃyâLxwO~¸XÈ% ¿äž&-y\!s\Jò8=e®÷Â/EšÉO!W°æë˜ª$’+ä’‹„¹äЉäA˜Š¹ä²ŽÃ”‘Ãäõvc¼y¿»B:¹ÀaJjLi¡˜Z\c²T¯¬Ù{NU ×[ïÆdÊß7:W @€ ¾#9L󗹿‰Í²èZ·ý¡§1™2¨˜VÖ˜"‡iÙ&¿ö5ˆBã4ƒŠg "€ÆÔ °ì€ BiªË—Ìõqã-Ò˜N,9• 6Ŧ¸ÃT´ö­ ‘œŸN.š_˜Ÿê0¹¡¢b(¦D:9=Æ[F¹*¡˜B©öPLs]F¹ÒPL¥SJ(&4¦¤Ãtõ #/íõ÷-' iLª2L&¾‡ ÐÁîàÊåÒ|yÔ˜bŠR¤º¿ÈIþScIâÊÞR"ê’ ò.Kq¸ð¡Óä_ ÓûS˜º¸`/yQã´Lõ LÕ¦ð!µ(0EÝÍÁCOX¢ÖØck˜ 9ž¹4—\k8L‹·ÆÒÉ™Ë_ŒÆTÆa2é¡ñ“ýÚ|wçZá{Dÿ¨¾óýC»Öl ŸS£ÜÕî9UUsËÝ|è»ÿûz϶««Ë‹ý¹k×.-ØÿªÖë§ÞC$·í¶Þ®[·®—{¨÷ˆl@€ 8æ0MŸ¿Ü¦wû³ƒ‘5ÛÇ>õÜý¾ùÞûï× Í5Cl¡7­µ*Ýß@Çòÿ´Qìíõ¶AʵžbÇ*w’-«1™ÃôÒ²M6ˆ’¬}5N9¬WÓîîîmÕŽ3dÕ2uð]CØÅn¿ªw‘öº5Zu!îµìªö;¶ÞO–moç¤WgO»Æû¼gÒ“w¡1õ„ï :Hczì©©©)>løé†Pc**ÿцpt)6ÆT6Sa8ÉÉ­É%sɉ;¼8L•¦âÀPqHHóáH—NnµÆ} C?‰PLϯxÛJ]¡˜|Éf¡Gi4‚PLA4& Ö(Ó9±tèí£?þǟ먕NÙTq˜®¾ñe LÎ!‘v¦Ê:´ÿq#GÝ[ï妎UÞIò±¹ÞƒÚö-÷¬Ø³Ëà]h0Ò¡á õí+Œ…¡áÃëntûºÁTŠ»g°¸i¨›p ÜiL•б”œœTXðŸíÙ±4ÒRl©Œ´”ð–Âðžå쥷>ŒÇ^*o/¹GÏà´4…œÒÉ9•>J!—©'S8e6˜\àÐ4‡é]{x-¦CІ°…€¢…˜¢E%¿Þ\r½ŒÃTÆaÒsðƒ–T.æ0…Ä®$5&ÝBMøpV>„ý£Z¼öí Ï©ªˆá£;èúþ]éaqï½÷ön6L ýŸþýûkyâĉ¶^?þö±?kd;hï²Í  S8p v2gΜºÞËÆ€ @€@/ DÓóËm€¤˜Q®08öXýîƒO>·ÿõ™Ljžìµ×^Ö ±Ÿ#Fèlõð_ï9kWj5T~—öo½ðjbhÙoÚhYg2vìX·k€¤îPm¥TÕ#ÙzÒf:v¥s«zz­©1™Ã´`ù©Su#¨Ó gS±5ÂR´㓬 ž5EËÝ®!l»µÛOíͪդ[H[ÆvëßÃv÷ÖrCV½Éu2õºtÉÓRÛõåxºIòôÊ}0ëºÏ«^uf 1e†’A€@:iL<9%Êì‘6Uþ†áwýèØ“CNNÓñ˜bYä\¦@` ¦X¦pðèýhب|.9Ëí'èˆMk/:L=J'e” Ók¸trʰ¡¬…Ä[•XC“Ê÷£¤r願ÊiLíþSÞnAs˜¢ÆWÚ{?ô¨úL&¿ñec@µ4»b͵ׅò­yբϊµ_ [B Y74l-VwÉb³.±WÇa°¸WøZï͹Әô\è%€ó“ÁŠÒ ÃGº§Fßywò{Ñ‚[*¤%.d‹SÈ¥òQ—¢ÀK~´ÏbÌÏBì¥Úí%ÿIÔ%6É•¦KÉ"—©D`Ê.“VôE/Aò +#1ßÓóƒdÉ~¾äy…gÜØ“nð°[xÞ-›K®¼Ã$—ßiL¦ó[ñ¦ÔhL}®1¹T…A‚”Ù®öœª¼Ô7Ýõh]&SÉÿ¦~yû3ùϬj¯nê7a5&{Ƶ}º³j½/[΀ @I î0ºÑ]F9› lÍ“ž˜]—É”lžÄž5:ªV€ó3’¢†>1ÓHÛ”kÅhãT¹$µõäÔ¨ vˆy jLÎaŠ ¢¨ö-Ÿ…_û7×Ù8Õ%árbPÌ3k„Æäî™Ú[¬É³•{§îTW=hTõ®wƒrw]…në 7j¹¦Ö×~Ÿ×{ =ß©çìx' ÔD Иž˜R: Í“·á§ë5 ủÉäUì%?SY©Äa F‹ Q35N䆊ãè0­³|Ð%©9êq˜ÞÑXî ã0=óü9ê.œ¯1&åÓ5¦›-“†Š©8j“)o“¦a7Þ!M->‹ t‰ hTîzL¦XãKá9ky®e›ÔŒÉôÖ¸kÅgÅš>ålæhèаiL®MÝŽƒÅÍ»›u¤ÜiLz.L:InM¹§ÆXŒÊ(C\i¤¥¸´¤´qQª¸b¸¤·KS—*Ç^*o/U ¿d)ríÙ4–B®—ÓËQ¦ ‚0•u˜ ¹˜Ò¦@Ûwæ~àïwù¹ä¶X$Rÿ!øÁ‰A4¦ S jLÞ?ªÄsj¡así9UI©oùHí&S/5&=nºi²ZÖ¿==ƒê·EÎO®‰u [‡¯½Åâ*iÙüYíÖžem'¶Y¬“T/5h<£YßÉ€ @íD@ÓW¿ÖoÆóË­½\Âk ßûÒ«AódôøYµ›L©“j˜bâ RŠõÁiKüÆ5%´“˜Mb~†í_Ëþ«êÅóÃ/é%ÛÌoæX›E/¹·û ­×N\{Ç÷Z¬Ê“ç»ZMcò¦QÂÚ¯«qꘘ1#æ÷±jKëfµêóo ^²ÀWÚ›5Qõ§Ý*¶s­täO+×[‹ËBY“Ó¯YSÖÔ€uïÕ‚_wÖ†uéä쾪pCº†s¹c¹Û)Ù|»jÿ¦•>å&ÐkAº=»öµÝó®“ÚnÑäÇGGtŸ,½×.9öéó?˜1°>ª÷yó¾јšÇš#AÈ)iL?19u@ʆœ®¿y¤K‘æÒÆ•Œ4EcLhhÉ]*¤KÀTs¦õÞ ‘Ëα6Ê%'=c‡iٶذÎì%ÝÅÑœp(GÓ@_còÒÉÙäs4¦Àaúmà0•âîÍ! †‡V¾sð‘ÇÖ˜].Uc²‡X÷àgc4å›]cJO†ÉæXãÈôqß-ô¬˜Óï-.»E TÆà«»7CÃ6&ë>€®…èêZ Ú¨5X~û×õœh³ä—€û&q U·ÆIÖØtíe#¶&¼kfºÇ®!›HÆ`q‹ÞÇužVþ4¦›G&œ¤ày±ðÔx§ž‹ÉàJC+Y€¥])n,yÁ–JSÅ¥…\*AÉOŸû`ú]Æ©s-÷yåOA–¯¢1eI“}A€@ iLŸ*?mþðº›ïüáÑ'–OëªKÞSÜ^ G”ô0feåÆtÉeíÐ ‚•’ L¯¥aò¦pB‚MœV€UMNЃ}”#x¼¯!Se‡©RÃiLA(¦‚ÃäÜä\c*q˜6¶,°–÷EÁPÝ÷pÅǪÑdJ6¾¬µ¥':÷dhC0å›í)ÚeS˜ýÆ‘=…úŸœÖzVä[ -CÀ.(ŒQ\½´¡a¯õ]óа5 cyxüÆ©µò\šu7;Hïò»2üNØ—€k[S×¾[¬nßNÉ[ÖÇš™ÖzMm)3XÜ2wnoO$w“ž ”t’® Ÿ£Ã’“\y+­T]©è*E"|š±”¶¤Å¡®äJš·ä?q³‡[­D!@£@ ÁW•_ÜÃhì‘4~) … 5UÓçÚÇŒ{›D[úØ=¼úϯÅr…~j (”½Ê"ç²&Çr'ׄIOÀöü@éSÉDr­©1¥ý£òžS“¡˜¼çT¸ºñŽšL¦ “û7æ&nÚ?›ä³¦Öû½œúÓÞâÿ3‹õÚ›Kë÷öºYgÑêÿ¢vâ*üÿyv·eo¿y? @€ P‘@‡©´Ý2ʹnt%˜¸ïñšL&kž˜Œb?vR.«:­Ô±4ë>sG¬©â[#¶“d¿yLcR‡šíDñ¶à÷ÙYÄveaoôvkÑ8)ÖêñOÉ:éìí~O_ê­£1Y¦‡©ü J¢ökmœ:Â®î  µ@cšš­uŒÚ=ãš™®:lc'¥ÙÍ`Õçî1W•v¸˜ÆäOò‘ig!¸\ÝY÷®»gÜz‹È¥-õj¹2ÖεCÛ¹éÇŽåvh'ì‚"».àØ™¸û6y¯Ú’ôìüÝ~ü[W·ºQŠ}úÜÓ®ÑNX îÓZã}^á#ñKhLew€ ' iì¸ÉeçÆoþðÚ›‚©µÅ´ñ¨K±&\©‚½TB*ŒU˜vtÕ„)ÕaŠÆ}äÊæ«o‹ç’«ÍaR2ïDc*q˜A˜\ɳÆä9LQ$T jV³•<†•o+ÁŸRûtDõ˜L~ãKrþŒ÷8ª§;³öS›cÏÞ±‡ØXã(Ök¹gE¾Ò ÐR††ýÖwFCÃîCmÚ¢k!ú­Qû[KÙ¾"lÄÖ%…´Î ×L¶d­…¨·X¿þtA‹íî4Ü—‰[ãïÙj¦\K™ÁâÖ¸s38‹ÜiLz.ô -Ý[±èÕþGŸ`ZR¬øÎ»UòK`Á»ò†\%+¥ÆR™`K´ä™ò©ÞROÔ¥BDÐò™ã‚©±)öRA´¢ÏYì¥dø¥È»÷òÇü¢À´2šhë&{uÅeG.›BnÙ¶¹aò8Wž+¤L–ÃD ƒŽ–Lmßâ0%³ÈÙ°ùMcòŸƒ“Ëû|qÿØœ‰MÛ—¼É?UþQùƒklbD8B3!”…:|N»lÛõw<\Kv¹¤`dÿ{\ç¯=ÎÚ—ä71ÚuVÚ¿¿çÔÖø íO¥ç»·zÕW}õ§í·Ø €&W ‡ƒ @€@> Èa’Å2=Ì%ÃT¡½0Xm@5OîylfÕìrÖôHB¶¶†…7W»ÀfDhcËœeÛÇ‚-e¢1i·:f(ZŸ¾ëÅ3Æ·m¬[ß?y'‹Øéù]ÿjËÔV¶E4&—K®¾Ú§éƒ[õ7N}°®kŠZuû'±Jñ«ÃÞëß-Ö\-7ãÞëßEVãö«ë˜ÆäÛuÚ2æ ¹›Äîÿ¬©›jò%ï"]‚%Ôó?/¶Ò€.0†¥ÇSòÓ§ãÚÑ­ƒãîíïóæ}©¢155G‚ SÒ˜||rb@ª8ödRéƒM…a¦Tu)6Þ’;'í% ÕS1SI‚›Ü¾Ð†A˜lÄÁ²¡ŸÒŸm‰Šw¬,­˜K®0 cC9Ò˜.’Æäâ0•:LyN*8L7rÉryC1•z ÉYVUM¦XãË>Ör±üPö£95jL˜í%§;è(-÷¬˜Óï-.»µÔ?4\ ÅT×аûP뮨ÉLÖ8}m:µ1õÛÒ¸˜Æ{¯µpÕi£CØø¯k-Zó¼FI]@vž©ûg°¸µnâ^œMî4¦k~{gRBrkôjÙ§ÆK©Œ«T>=\Û3!-%SÅ%½%ùÓ^J‰ºä©KUì%/ð’Ez÷Ã/Õ`/ySøä ¿d™R¦À^ :.ëH!D`ê…Àäg‘󟀄iÌ„öИbIOíöˆRË ”†b žSÃÃu#ª›Lêy´Nyý'pÝ ¾Æ¤—´ë ôŸ5]w¼´þ\ml±ëcküï.7`Þ® ]è?Ûm Âž•ýµôû÷âÛ’·B€ @ S”Ñ J7z4ËBÍ“»­b2YOºß3eýjX„$×r±‰6ÕAM{£ßTqvHÌñ+Õµ>üfH¬3΢.Ùi¸É–7Á^²ž;³©, ¬,Ѷߣç¢Æ¶L+hLÎa²¬%ÉÆ©% úÒòY³˜ÂA”§F8föX¨®­Ò­ýhÝ þ–U5&kuZÝYMé-Öãé†p\•ÅÎÄÕ¬ÛÒ¯ëXO®3~´gë«­ÉnokJ[Œýä±ÜMk[jaÒï˜Æd{s÷¼b÷ª¯1Åí|ì“¥÷ºQ«ä§Ï}0ÝÆîì„k¼Ïýdc—јË—½C€ÀiL<þl…©aနKŸŸHåáÒÆE#J±ô¯CÉñ£%…a#Åì Š—£#™#M`ª3‘œç0'¨/é.¦×X¼u–•p.º?=И~}³Òhhì&5‡F>£1ÉaºÚs˜‚l-aE§¤“‹¦¸Óy»Y–çäG3rÔ½å>œ1Éž±­ÙeÉö(hFS›ý§ñÊÌzUû¶AË=+ò¾&à —›?¦Ö·Æ÷í«[y?•ôÓ ƒ]GëÛï Ðg_a€­=èÖ[ËTk,°uth!Öõ;=b_Öt5¨öMbcÇúÓ†õ[X_Šë]q'k“êíåZÊ|™ôõ›Ùñs§1é¹°*ÉÅL*.O?>AQ”R)¥%ƒó›¢4gáÚb0ÏPWzîåµ`É•Ù/¯ ìx/IÜ3³^ytâs*“f½>‚DO!•³ÅE9ŒS£.…£Þóhx©¼ºôà³"Å>ü¦?e¥3~¦•0çq1yÜc“_2uÉì¥ûÇÍÊãA¹/,1 ß (Zj/…O´*c'¾¹ù…ø¢ÉÜB¦ üR˜*Lu©-4&ïUpÛÈÄzúùMO=¿Én€BÃ#ê&ž¾hs,Ó3/½i¡˜ì9uö’­×ÞþPÕ˜L¦ÐêÇ=Gê?GÌ`µ ¦Z \o“þOØ|Vý¸7&׸/3ûïeÿ¥ìÇþÓø¾íÇþ9Ù?3ׯJ4¦Ìþ-°#@€ ”'à&7v¢6¬Âè>5“J0&‰,–5調t¥²«m8ó•-QódiawÔ#3*Äd2çÃÿ±FM·pÍ›)h 39´Æ¥¾²«qM×qf³ýku­äT`×ð±öˆ½Ëthk¡¨#ÏÖXÿšõ빎–ýÖS¬¥SKG[ŸkLžÃ5NÕ“àfù[-¦Xœà•o?ûÒ›ŠÉ¦*ÕÒ85žåš{æ!©»S¿Íãñ·mýé¯qç*ºbõãš–6c' `ÜinËä™hŽëš®®®Ý Žk™É”zªÉÒºwõãy$e;·»Èµ‘ý“qG÷û‘“÷ªíÁ]¦;t²¥o··±Ò[R?}n”m¬KnéöhLü³ƒ Æ4æ±gÓ¤¢<Ã~{ÇQ?>!Š·”–¢Yñ¡;þÜËkb“ᣱ¤‚Ñ2ë¥Õ6œ” ¿4ýÅWzjöSÓŒJ†ŠÜüvwA˜ÜxÅõ˜÷س/i (œ¾Í`wA˜îyl†žñÊ%’³Q pÇ&˜|‡I™4 Óæi^"¹œ'•3‡ÉM!ã¥:rSè+¼c¡ TƒáØPY!¨…Å[¿xY“Éo騇ø5¥@xöÔm/%›cÏíå˜íXR”íÁ²mð‡’ÝC mƆ5Mèé‚¡a}©6bh8ÖâB[ Ñ,¶–¯¥ëÑ»Üw‚‘5$c_®Ak€»ïëÒŸnHÚ?1×&uiì’_2 ·Í-ž¨Ë*èNÛ_SEcRõÛ 0÷“\ÓF8,î¢Ü£Ô¢‡B= è©ÑyH• ™àWÉ)J_üòןôœ{ ¼ï‘I_øò×,ž§+Z#c)Е¬¼þžÖ|泟×oWì¡3o)é-U ¹”¢.ÙÓÌçÑ÷ ¼ôéüüãgº'Ôûâ~½4n¦tK-«|뻇h›~~¦Xõ´ª5z<²¢ç×}¾¸ŸÊ§þñó*Zøæw)—<.5ÜÝLÿ×/|µzþ¸% ©ð¤›L!WU`ê½ÆôÇOvvmúÒæóúÐ?ªÿþ¡]k¶™÷¦æ¨Ë§Z9éšYž?áîg׸n⦯;â²)Ñ A˜¯áÞÉk<Ù…bÒ µ†ÝVÝdjèuõxç Ê=(ÇFz¼[Þ@€ T%9L󗹉€š„sÆðùÖB9rHPÆÏÛèºÑ‡Ü·pȽ ý逃î~yÐÝ Š³,Â1Œ‘L¯š]®ê¹ÙêAsÝa6¹¢Æ7¶Åf}«1™ÃôÒ²M~ãtè˜W¢žŠ×vüúþE¿º‘3ØN¼z棳_·¹Ojœj¶ý7ÏàB1Ù J[7NÛâžá$+@câþ€ 4¦GŸñG£bCN±©p¤©8ØdÃL'Ÿr¶6²¥knºË­1uI#¶æ¨£OÒð¶†ÜÈ‘Öìû¥¯Yùö÷M ¿”šB®É Ù0Ðñ'Ÿi£?§ž;ØÒn|ê3ŸïY"¹™a"9(ç{a4&ß[Š-WˆÆ´õ£9Ϭ;ð£?njp­6u÷Ãtƒ¦(,‚rq˜ôø­e\ýnø¾>šCæE9îÊNÍÍ"°á!ébb25õ 9òFàì¿ÞóÔ ª¾bÌ+:^ }/5 »´¾«Bgƒ¦°Ì€þackÊjL滹 PÚErMÓ/§·,üË·gÁ”¢‚#|B,xRêŸQ8¥Ò J?<æ¤Ï|ö¿>6ñ9ÓMιèrý©gG§+ÉXê´¶ùü#žó#-i›³/¼ÜIK?ýåÙ*U¤¥”xK¡·o÷K,aœÔ¥¿{H”6® ×KQ’·d˜$ÁÈR=næèq3´Þ\{•Ù‹6êO‹½¤§Uy÷±Ìqû|a?=¹–&BŽb/¥ÚK.5ò¨G¦Ic²ðK~ò¸‚¡tnÆÂ/¹p£¡À´Å'—<ò¾²EQ‹JRÈ¥ùû=‹Æ´¾{‹¦ÑKÿ󨮽ÔÜÛû²üûíÕ+r˜"ã-ˆ «ÿRÑ,ç×vÈa:rÈë&¾ü¾…ß:o‚4&7H0øž—ÕM|ØàÉ~(&{N««omW“ÉÄrŸ=C€ @>s˜¦Í_fSt,ÏõÅ#_:}ø|,Ñôî[ž\©ŠM>õ¦yj¡Hc &ÀhÒöŠ·üv®Z(—ŽZPèFfY¨yrçC™™L0Fíɦcê±5&s˜^”ÃT˜‘eÓ¡£_q3AÝ ÊÄßPËTµÿÈìõæ0xzÕყ¨ö½Æi±ö‡µmã´cn­œ^SN+žË† Ð<Ò˜îä™ÄPT1qÇÕ7ŒpR± öÐ5{Á1-X¹Y“~ö˳_qƒžÁ4ÀôÒŠ·4~¤A%•«;òÛß?Ô2ÇÉUzjÆBKà ¢LŸùÇÏ»1£#|â%¿º®$üRɆll(,ï¸Q!=Ëi0è××Þaù7T4‰Ý¦oþû!6îhLaÖ`+±<šY­œÅñ´ Lnç{‡-Q©^iýö™˜4X£ÒI“4¯ºa„k|Y"9›@òëÑ‹TË ‚«'ðË¥1­Ù>ñï <Œ˜õļšâ®'ðHc*Ì"Ðhš_ 5&Só¾ 8S÷Ú£RQfJÖ "}ö#EuÝŽÓnž(Œõ Óúæfl.º¶;Ÿäš²“6µ(è.SrM‹\gí§ý×7÷È/…PIz&8òG'Ä‚'ùC(¹XJ…)ðzޔ䥳/ºüÞ‡ƒhLÎXvÓHùIÁ6O?çGZÚ÷Ë_;ëÂË]ŠâŸ8+°æ_ÛqÕ#Í‘×o{î<ó‚!&ÎÿdÀYZûÔ,gÐø½C|r–Œ–“~qÖ¾_ÚO刨¯°)óWýÛ—ö“º¤ßW\§Šl$ýéžM_~5ˆÆ$oÉžPU¤1Yž¸@c*D]šjL“ž[¡œqzru­Î[2É|=¿÷³3öùÂWå'ÚÿËwìÏÎП¶fîÒâã¬iL¾À¤GÛ~ß>Xå_öýꀳ.•yó‹³.=æ'§Ûšƒ<ÞÂ/iù€ÒïøôçîxpŠž½‚R´—¢ Êåö ©ÜšÍ›g¬|ßâÿÞ‰ª1ÿ¨¾wè¢ÕÛ,Ï  «TOÎÛh©w?»úÄa³,ª–&:žDcrƒҘF“µ\(&›ß ÜÒWÝ2¶jv¹Ú?_l @€ t*ÀaگߴyËbÍM|nÉÖBªë —ܤ—ÞTóDÝè7_!‡é2iL…nô[6hÔ‚Hc*t£k^Š5Oî;-«˜LZ }¥1Ó~ý^\º)Ù8µ”0AÉvDQíß5éUkœSXûjœŽŸ»1И®ŠÉQhœvêÛê×…ÆÔê5ÄùAh{Ò˜”¯£Âx“ H¥Œ:½þž9+~ј‘Œ% -i€ÉæÀ?üÔl ¹ÀKÏ/{SN{áU „eûÔçWiLç®'X´Ô¹‹ß°¡„q¦eáÐR0Nôê»'þ;oåÀ˯ӂ¦‚VyKz–•´d§*NcRR9‹êâ…ê(И¾°_2mœVžrÎ ð‡\3ÂÙKZ8oð5C†k,sÜ!GÞ aQø¥%Ýw=_cJÈL±¡aç/곯Djw[d•ptx}ök6…‘Ö7·dëˆ%•Ó‰ùkò§1]?¢‚“äžýgÄZ–å0=üôszŒÐ£¤¯(¹gJ}ÅÈCÒc¥zxõd,„Ñ•¬Xt¥±O;ä××ëYó©é/K¥”¢¤‡K‹«dšEiiÍö‘L8ãü!ò–ôÒÂРW°¥ž˜)iI[šJoϦã¦,°5§ŸwÙ3sWª+Y¤Q\ÐBÂ8Ó˜¿>,’–î|†t¥OýãçõÛÂ/¹œÇ÷>hLÁ3k!ð’©KЍ$É/ÉX’·dO±w?2]/I]ºìêÛM]ºKá—BoÉÊȇ§ÉU²Ìq¦ÚèÏqÓ—Zú3 L®Ø3®"0é·¶qá—´|ûƒSaßJZþ¸T¥©–¤r_é÷•Ñ3Oð#0ùvÿÝ‹£°LþÊ^.ÿlè^ßþÞ! Wu»{/ÊÑNrÕsêøylþÄðñ+ô¿ªîõMuÕsª?H`“)b.\£µèxa2µÎ÷5g@€ V#:LL™»ÔoÛ„ÍèU?šFMÔ¹^4¦"v)Ìz.,šËæ/{åŠð©1x@´â=&VXÖ¤­XP¥ ýpè'ùÏ”ÅmB9É\¥®°¿O*´’õý)9±X2iI¢’_ä*ÙsçÈž–±ôÀø™zô´ôpZ3~¦C{Iâ¬<>yå‰=nÆ ??Ó’ÄéÁÔ¥Šó½%—'NO«½ôØ =ú9㮽íõ>ßó¨4¦¯šº•P]’«ô˳™º¤üq.ÞÒð{žÐí±?=ãÜAÃÌ[ºùî'"?LŠ<ò¡à)Öb/%Ì7ú©ç-sÜÑ?9]Q—~~æ¥*– M“~k›ûž˜oáFÿy߯SÍö’ûš®EcÚç‹û?ðÌu垌Ǯø;å]ζÜ:áËê)~vîR»ë‚ýQ”þ T Æ4ÅÙ¢¿jò„f¸>:ûuKV­©®zNõ dãê9µÂ PœøË ιpp÷{¿ÿó_þÒ'_R€ @hY;wîÔÌ£“æúƒ(®…¢æÉƒ3^ "‡-µL5ÑBs­É)‡I%öÚ‰êF4¦»TèF—ÈòµoÿËý/5ií·³mguÆÞnÔÌ[E›jß5N£öi”¦DÓõ¢ºÚ—ä4‚f°Ù Š^8ƒMµ/Éæå‡ý’8ÁÖH¿ðW7ÿð€}ºoìÿg…É¡@ ÑÎøŸöœþ?5óű @ oôuÏC“¢8:%CQÑðÓ×Ý H•êJÑp@aPàªGZ’¸PZúšÆ•\Ê !ø½CŸœöòÈ'èi\ESßUlÉ/iÀÈÆäškÀȦ»k¨HÓÚ­<öìK§{Ù 'ŸiÚUyæE~éáIA ¹h0(Òôõ@`ZhL6k]“?_}ÀY—ó“ÓIö’Šzî;%ИÂÁ c:¡À”ȧQ‹ÆtìOž±vp¹içÖ~­Ýû/¾a?ÿ®(7<¤JQËëÔ›æé Ü¿5Àwø`{¦P2;lÐäÑÓÖ–›âþĬW÷ûÒ—&]xÄG7ÜÉßgýÕ=øÿŸ)è{å¦d\õ…M ¦ú­ïØg_Mï [ahØ9L5 ûYz¬õ­¡á£Oí÷PWÿIk3ãn÷/á k¾&jíŽÑy{hé“ëEc*јô\Xòè‘pA¯þÃãS6ð"'¹J…Ö‡2*zŽÔÓdà'…el¨"ùaÁ!S„I™4ÅyØØ%zTU][¦jÅ Õsªë&VEÓ É ÌaÒÕ©`25¢*Ù' @€Ú€™LLœkÍa¿yr×3«Õ$¹yü 5WÕ:Sºþ|jþ&ëF—Ã4H“×.‡é’»^*v£'¦~ï ÃVmxWÍ“-Û™hÑ7Ž™LÏÌIoœj¨ ’©›Bµ¯ø[Á JØÛ ÆéØpÅ 6µO)Êu¾5Ç*8LÇœHã´%j=''¡¡,4¦œÔ5— @ è!êî±+ H]HŸ±K›lŒÉÒtX¤%7À¤$ ýæú;•¸CIsošÛµIcCR—Ì[Ry66RÎ8‰æÏÌ]qøOÐhшÑOk»F‹ô̤»ìÚÛïJkf¼¼A£BZ£"›‡`ö’2o¨<9k™ên¹÷IIKš¸®G; )ü’&­1UÝznºû ý¶råÑõ; 4¦ÊS½IåÖlÞœ*3}ôÇM}TÛYvôèщ# €ªÛ`È—ÅûΉ¯*®žÀ­ñõŠð |ÆkÎaÒðÜ¡ƒ&ß?u­¥óSøêXà0íÿIÓ_°'ðvÿ)Ëkh©} þl iñV Ô˜®úž-ËíÔ¢ÖwÚа‚0éãïZßAÉ2CÃj}§ {æ(CÃîýAcjÚg¥WÓ€Ö­[çŸkrMÓ®¤÷R4¦¡×ÞžªÙJ½ª‡'!¥,„“*=GJ~wŠÒÓ^>âÇ':?ÉôpùÄÔ—-œ­Q¨OuüY‘œ$iiN×&KZУ§6p¾¼RÂi~Ëš×Ó§b/iYE çÕcd2þÎ!zîÔ ¶¤GO­‘¨tÝm˜´¤W}6rêͬV~a?‰JÚLнžPõû›ÿ~°r鸟qÊÙƒÆN|Q­‘½öEZQÚ8‹À¤g#=¼*ö’t% "jO±ç^­ùÅY—ºÀKz~’·d!F­˜ÀtôI§KWR¹â¦ûÕ¹yÖÅW«˜¤oö’žkvÆ%_?ð û݇Io©Kc²‡9ÉLãW~ÃE¥kÆdÿ®¾ôÕ&=·$ ÑÎoV‘_¯LVN¹i®X7±’"¸q®å<¶nâÇfoøù sʹöþ?*:‹{ÿ à @€ Щ"“iÂ×v1x˜¶îÄ«gºÊ”—߲扚™W>°øÊ1]Ånô%ÝCG¿òëû_ ºÑéرæÎa²æ &S‹ÜNÖ—ê§QGØ8½fì7 ôê_õàbWûjœŽŸ»Ñ¯ýc3£œÁæ;L4N[¤Þ;ÿ4И:¿Ž¹B@}L@OP£ÆNL HEsà5ü Hõ?ÎRv¤=rÿöα~÷PM}× ‘ ŒŸŒI]ÒØÙäšñ®1#ËføU rt¨HZÒØ½ ­ †~uí iH£B6<ô«kÂ5_Øï”sqf°kúº¤%éJŠÀ$‡Éb/iÜG£9<ý¼Æ€l¸gÌSÏ|äñzÔtåm|û ½ª zæ¿ïÉùq|¹LþÈN-јœø®‡F“™î_òŸÝxMghLºqC“é¸dãKOà^(&“:ÿöôn“êQOàãæl´8L–ÍYÃCÏzÝ"¡úéäbS‡›LhL}ü]Èá=¾Æä Ln‹XëÛ:^T®yh‰>þ~¦:††Kû^®|G¢15óÛ¿ÿØáü5{5óTúüX¦1UôêaýKŸ ¼˜I.xRLKJþé+JÎUr–’=Y–+…§L{Ö,>nÙ­¬ Šž8Ub¹áì;ËŠ‹´ä\z8¡l)’ë“©âb!—ì(VÌ[r%–‚$Œ³RL挳lq…²Å%EÖƒT1²høPåÇ ¢Œziã~tâi×§gܧæ®UĦ¦iLzžÛ´m—’b*,žŽ§19“iâ¬%QœÀÂ$W»7ìfp¢}”ðØs˜T#ª…rÝÄÉTt÷ùw'@€ –%`&ÓCOϱ&°›˜Úf©®ý8Laó¤;jžй&žrÉÅ&L¦–º¬/5Ù8µÚ/iœ†[1—œ ¢øÓh"ø׊O:L4N[ªö;ödИ:¶j¹0@­B@Ow=8¡‚¢ôëp@*x*$ëpãM%ÃL…9ðñq¥h©8ä†J‚£â˜QÚQ{)˜Öîgáðæ±»a hÈúIî±ðKRÈ%ÇtêÕ˜ì¡ñ½]ïvm:zi 3uŒÆd&Sp{ÔØø hùq˜,¸@ê÷T‡©“M&4¦VùRä<öì1)M`Š™L ÷Õí‚ÆÔWä“ÇÍÆôëknYGá³`T~uMðÔX Ñ’ÒןTANr/%,¥4Q©à*™±dÅâ*¹¢tÅ*©º’3¯cÞR`,E]ÉuHKÔ§²·dýѾºTâ--ŽyKú³u)ÊŽì«Kþsí½ãçýó¿}Eq˜ôûâ+nm²ÆdŸ%ÉL¯¾;2õó”:4l£ù©3ˆÜ8{††ú×;”z7S£ÈÖ¿ßÜiL¿v[ÙH¯ê=Ô¢%½\òìèB(¥ÄR*†SJ³”Râ*U ­ÅX ;ˆ“¥Š±JÙV¢ÜpÞBRZryâ*„\ŠyKUC.Õu©g~RïêAR9‹ÆTõ³¶÷m{WÝ¦Æ “é+<5c± ¤”ˆöÉT¢„l-´*ÿ£²GÕw?ø¸ÆÓc3@€ @ ?d2Ðï›>ù\r~EÔ‡î;L ‹¥^‡É™L>aÍéw¿ü0o+Uãôëý¾5Ncúš x³ÀS{Q£dƒ­²ÃdµÿöûAãTc$«¡q”$ÇúgÖúnÔœI3 15ƒ2Ç€ kÒ˜îót}R)ãMQz8?ÌR|ê{” £$GGÊ,÷0Zj,#‡?Bä UнT2q=ȰQ̳Qgø¥Ø8No4¦>¹Õ4¹¢Ñ “ûî»ÿÐ£Ž³Ì-nÑ L)Hzç0Ùøþô‰ñ¬à*i.^íìu©nd¼¡ï ­ï ­ïž û3ˆz04,‡ ©ïo…ŸAî4¦Ë‡Ý–)²Žôª{ pɃË-D)ÞJs½ùñ“*ÄRŠ‚*À• ªT©S]¥¨‹0`©ä1´¢±”i©i)ž'.%UÜÖXª¸2ÞR!äRi¸%¤ÞoÖ ©¿ºQoÛ{ÀÄê^8c ¬X|¦î]ÝZÖ‚þÔ–*Ú¦ò·Ðºõ¯ñ+_bz—‹ÀMqNÎr6ÙÖ Mä<®åÕ–í¿ÿó_þ’ã/F.€ @(Kà½÷ßßÿ€o>ðÄìbó$TX\ºËe›bÑc‡Éu£ëœvýq—P-˜³iŽŠFF,¡×¹¦v–þ´–—uºe(—¼þúFÕþ“~ã´¶Ú·.‚0«ÈfkË×â0©qúŸüE“Ù2™uI&Ó’û†©lí jyûê.Í×Bl½ÖhXE›é½ÔÒ  1qg@€@ƒ HcºcÌÓt\>ìÖp@Ê•ªÎ/ *ùIâ|©Å%æºÞRqÌ(1¹=U]*æßð3ÇU°—¢Ç¼*6ªè´—Æd“+44vùX5IT4Ö£eý¶;K);´Òl$H¯öà¦9ê^Ý'i¯âüvo AÏã0EIú>üƒ¤§õ®‡m-¸Ø¨²—¢« C4%׿1o¢EQm!É ©·oiÖú®04ìç‘L.´¾{04¬ï+}¿é[NßuÔ¶¯8[66꙱έ±¯¸`–Á))ˆí"wÓ«o-gi½^ÕÓ@걜neÿôÌ$ÉI•ý¤Ê•›z")&ƒ‹[ó•u%[JË —j,%3ÄÕ"-%óÄ%½%? ²:.]ßeՇׯmÐ I_îf&ékݺ×ÕÕîâ3éOû–×K– AV}~•Éô…¯|}üôWbSRË›åì u÷àUF_5ì€ @èf2?Ëš'±DQzé‹L&#h=hjdYg™S~|&yKzU“\0Piô éΩ×Ú®ÄúR]ãÔôµ`lÌÂ<[ã46 ¼“NJ®’FPôÛ²ZhhÄÖhÔÄ”&mcëU´^›ÉyÒ‹6ÓoÛ€Ä  1qO@€@ƒ Hc1úéªR)ƒM%àKb,¥K¥3ÞK½%÷V&#‡‹ºòóo$3ÇGz~©Ý£1©=¢æ†î#ÂWÄo˜hHM©=¢Æ‹Š´Mî;™L‡y¬…¿-6¾¼,ÞþÕªÌêÈ ÃUÍ%s˜ì$õŒ­'jAÙötm!Q¥+é \ zêÖüÍ4Ð[4÷@E ©±T{pù½} So òþ>#k}Gñc­oŶH oÑ ‡É.ؾ»´ n}¡iY-n ™}¡9AS/9éÏxeq`4¦,(f³µú®77_›IcRѳl-qùÌd7õ•hòD¡áaÕmµiuç=¤ŸSq˜²ùÖd/€ @€Àž=f2Ý7nV‰Â²,PX\ó$%Ll¡íª[Æ~ï ÃVmx׺ËS‹"ñøq˜u›h]ixÉͱŽ65²ü¹"j‚Ù~²"`}©ã¦Ó¢ÀTsíׇÉNØ…\²hLnÖkàÄÂ2iÅ/Ém2ÛÉÞ«·h›¬.œýt4¦ŽªN.€@+4¦ûŸö‡¢ÂJV‚ѥ˂©ÀMI-5ä舌¥Xž¸äàQlÀ¨.u)6ƒ= Blö6öRrúz{Ec²¦‡iIj˜Ø‚›ân¯ZF ÙH õìf•Étð‘ÇZ°ƒy‰)~ –hI¯&{Æväzö–À¤Gk=u»çsYM®É6s¯ÚtS úþ©ïë€3è9¨õ]Ïа¹ÇCÃn\[ßc.N‡¾Ä¬ƾ÷LÜ´ï7•ÎÈ„ÆÔó›5ëwæNcºìª[Ë=üi½^Õs@… ª¾ê”–T4“R¢(Åó¾;ô|銟“8¾ö —+þ3¨ž]¬&fTŠºRб”–.zN­UZê㫤yM±ˆ¦ÇØ‹X˜ØÞ8LÖYfcsE\WšmcS¢U\­C¸·ÆeX_j²qö?D³kÜ›žå’sª‘ èO h˜Ä,Ù˜ŠÓ•¤.i½VjKBgÉ,T\æ‹Ö ÇY´ 4¦–© N€@§ÆtÛ}Oõ`@ª8Ì8+%9:Å•ÂpRlü(9r3 ‡ŠRæ´»¨KÑ<öÂ$v§.•L\/ =Ô5"Syã¶Ó˜¬aâOb÷gSØ«úmÃ@6d¡Mzö˜LGUw!K4üçæ·' ö,“ÎйJöîì%­×²‹xªIzä¶Çr=„[´TK ݳ+Íø]hLewÍ&P®õíaÊ|hXÃÖ¦%ÅìLS6-Μ¾Ö´ûг4šíþƒÆÔ:5˜;ið•·†}éE¯tæt÷È&ÆJɃ£ÿ™&'™¥TQQR öJ–R¹LpYèJ5„YŠGZj'i)ùˆÜ )Ù«n_âöÍn¯šÃ¤ %Zûë™LN^XœâöGA˜¼‡T¦ÖùªåL @€ БÌdºç±™®¡Z¶-‹8LbhsBlÁMõs »Õ¿f¯º‰Ñ–{®#á÷ùEY_jÔ8-Dv!¸R{QëÃd×(É…\²±KW¡û­ „I JiaÓÁº¤{/?ˆ@c➀ Ætë}O¥FEcLƒ¯¼%J ª”p•ÒÇ• .‹¯.¥IKQÊ¡øÌö®`H¨¶œqÑHP†ÒR»Gcr “dhXÝYýq ›Äî¶ïÍ}'“é #Ž-ÓøŠÉùSzì0é$«äRËYfg÷|n®’]Ž›c`ÏÞNêÍÅfö^4¦ÌP²£>#PÒúŽÂ—$††ÃlY »qmËiWÍ^rª“^rI6ûŒQFFcÊd»ÉÆ4èÊ[Ruu³‹ôª\f?$Rêr% ©œ¢´´ºœEÖQß_ØýW®”‹«”Z)=º’=˜¦d…+¦4óæêqÇJ Ô3–¼ïÁ†>¶6zçÓ˜,:¨ë.W‚d=³ZøPëj7Cßf»5~¦ÍdzøÙ…6ÉÕ&×Gì?¤‡©F¤l@€ ôŒ€™Lw?:³T`J ¤æI/ã0é Õβ\rê2sSýÔ°RÏš+Ú̆ ìw½ ®žqÈ绬/õ‘°qê Léµß3‡I`5pb¹ä´ ‘Kf¡e›ù­õZ£?õ[ö’ ¥hE úÓ…kÊgqÕ• 1q@€@ƒ „Ó“–ÿ+µØ€Tõñ¦4W©8œT:–TLÊ‘o©0”àÔ¥’A¢DÔ¥f¨KþP{Ec²DKjk¨ÑáZj’¸‘ ›Ç®±!‹ë¦^ôò¾3“É5¾Jæ·CPkFµ7“NÒÍ%°hLzðÖ¶Ó•ô|n©œíÉÜÂ5©À¢¢:ó©—›ÍÛј²áÈ^ú˜€µ¾mh86}(;“¡aõ·¸Ì˜I?öýf=0–"Ó¾Ü,QÊèðhLÌ`7yÔ˜*<ê©QÿþçÊ‘•*$ws/ZR59©4ï›%€+Éþ¦¯¤úE¥‚«”ÈWNWê`c)ÕˆjÆ”ÁG³Ú.d2ýÛ—öè™—mª„Ÿ¦Á=¤fòªÚ‰ð: @€ wf2zdFÔ<±±¥}è™8LZeб‹h«•Hð×ëO­tÝmy¯¤†]¿õ¥§ej¿Ç“N\“¹ÝékÙ/é·"3¹DúÓ½dëOÿ ÀŽÛ–SÛV'@ ]HcºåÞ'K¤ŠcOÛ4~téo†[d ¥ÂÐRUc)!-Å'·GÞRaB{ÉTö䌫:k½½4¦>¼e2ýàðc*Ïoï¥ÃÔ‡W—ý¡Ñ˜²gÊû†@¼õ¦þLö½œøË ιpðú-U([¶ÿþÏùKß\Fk©uê'w“ž S좂ftIøÔX´Ž*FEª0)‘ßÍ´¤ÐLJ““ÊúIa Y¥=ý ŸÅ Ji¢RÜUò¢+åMW*÷|ܾ“¾DÌd;iATÑžeo×Ë?ªÖùªåL @€ ÐÙÌdùÈt¿yâ‚™gè0u6Æ6½:ëK­Ð8íÃÔ¦L8í6 €ÆÔ•Ä)BhoÒ˜n¾ç‰’ñ¦Òï—\H•IÍáååHZ², ~IŽ%3r¤yK…,}á-ÅnИj¿ãe2}ÿðcJæ·{5ˆÃTB©ö‹-[ž@ÕÖ7Cý¬C4¦^Ìðí¹Ó˜ô\Xúðç£`A¯þÀ‚1:åÈÄ£2î‘EHòKòÙ1}MWU9)J=h–±”j•J“ÁuJ>¸ªæ~-´µÆd&Ó>_ÚÿÁ‰ üt§8L~E²+@€ @ Ff2ÝùÐôdó¤÷¹äj<6ë+Ö—šÚ8Åaê«Já¸U 1q‹@€@ƒ ÓÝO¤ HE£Ná€Ô1õ 3¥OzsÃ%F‘*IK-9N„ÆT×-˜L‡ãg‘Ë$—\]çУ1µG=q–µ¨ÐúÆaªbùíИzÏ0«=äNcºøŠáL#½j‘Ë–P?²’pÛk\Sx ,o&™@¢(•†Sò"*!*E¹~kQ—ümÚ]cÒA`2}q]ˆ]ü£Êê+’ý@€ @µ0“鎱Óüæ SíÛzKëK5Nq˜ÚºN;üäј:¼‚¹<@}O@ÓMw?QÓ€Tõ!§-f¼u%o)´[¼‘£¶Tuø©Þ»V&“ ù`‰Ã”©ދí[ž@j뛡áLê )Œ™ì$ÓÐáô£‹‡WFËÔ+‘ÌnJ{ ’S‘ü…’§É0]eTm‘“ä—Â#f郦y+íðÄYõ‘´6è)i2ñ*“/Gv@€ ô€@ÌdÂaêÃö}K¬/‡©}«2gŽÆ”‹jæ"!ô%iL¿õ„7 uºxèÍA^°Ú†œR]%o®{að¨ÇИzp¿ú&S:@4¦ÜX¼¥å ÄZß gUchLY‘ìý~r§1 zsL0òþ.ÒSãaÇ”•|ñ¨¢„TŸ“äÉIøIMv›:CcòM&þQõþk‘=@€ @½!àL&¦Þ`lÓ÷º¾T¦6­Á6SŽ*›K… Ð7¤1Ýx×ø²™7^Ù’2 •˜ñž«¤hL=»SÍdÂa*K©g7ïjy®õÍÐp†u…Æ”!Ì^î*_Óé§ŸþéÏþÓ>_Ú¿\ùÌçöþ/ÿ×ßVØ ÊK_Ü_é½(mDàÿý×/ÿ¯õוOøû›ÿ4~Òìõ[>reÓ¶]½üà5âíÊ.÷ùÿöÏç\8Ø?Õäò–í¿ÿó_þÒˆ`Ÿ€ @€Œ@`2ý?ŸúÞ—þßUÞ­ÐBQóäúhF@}©ÿô¯ÿç÷ŽÜ¿jãô?>¡qÚa•ßV—ƒÆÔVÕÅÉBhGtÐýoÿÜé\Ž4ý—ÿßßj®ÂxøŽÿÉ€ØCæG»ÿÔŽ·G¶ç,“é>õ™IÓ_¨üþÞ‡Èö¸í±74¦ö¨'β'Ôúþç¿ýßÎ9úભo††k䋯T#¨&l–/içÎsJ?9Vî3.¹’5L jÇ&ý'hMIßOt3gùúʃü£jÂ+‡€ @€Þ»ð³®9 ‡)ŸwÂõSÿç§–ŸW¹öq˜òyo´ÐU£1µPep*€:“À¶mÛªkh©ê`ö¶xõf4¦äæ“?¸êñö~Ú€¦] úRå3IZÒ²d&ŸI¯vïêÖŸ&6ÉaÒšv¿dοs 1uN]r%€ œH†bò2åJò²Ñ˜¸Ú™€æ‰©kE“Ô‘¢¢þõ±Ø,2¿[Fëõ§6Ózm`òS2Tv;Ãhƹ£15ƒrmÇ@cª[A U $C1©UëŠó‚ @€@ç°¨æºYJZ–Ÿd]fÖ_fsþ´ .6ëD“Ædë­©n)J¦%)ä’4&»"Ks65®[©ßZ#‡ ©*½£.©£ª“‹ äŽ@j(&2¥ÜhL¹ûptÚ[O‹ú^4%Ì®ÍrÉ)&“uËè·½¤î?ÓœúdˆÉT× ÆT®†nŒÆÔP¼ì%°ûOÛžYw • k¾¦'ÔGV|Ö­Y»ctcÏÞ!@€ ¼pýb6ÉO=e2™¬ͺØìÇVjK“.ÑÒÏiA¿ºÉ.š)dõV>S½Ä·=SãØ²g4•SSqs0@€ 䛀³—Ü$?Ó˜~ɦJTRß™MþÓJ­±e ΔoxrõÒ’oIåd,Y&ýhþT‘±¤PLZ£­´õrå\Fg@cêŒzä* @؃ÆTñ&@câ3ÒÎ\4kÓ˜4OL=*¦+Y¤%‹­ë„ÑzõÉX.9ý¦û¥ÞÊGcª—Xã¶Gcj[ö ¦@cj*n@€ @€@û@cjߺãÌ!@(%@4¦JwŸ—v& KÉ…V’Òd1°õ[×d¿õ£mÜK¶F“M3kçKï›sGcêîiGEcjºàL Ð+hL½ÂÇ›!@€ @È4¦üÔ5W @èthL•j©Óï®@cÊf/w…ÆÔK€¼­B©Uj‚ó€ @€ @ Å  1µxqz€ ÔL©*4¦šo$6„ИZç@cjºàL Ð+hL½ÂÇ›!@€ l ̺eÏKc²Ý%{k[?š³óã5ír¶œgN  1å´â¹l@€@@cªT©hLxËsIh4¦F‘­¿hLõ3ãhIhL-Y-œ @€òJ€Îâ¼Ö¼®{T×^sß89Ǹôv €ÆÔµÄ9B€ P 4¦J”h™Ör±Mû8u¯=ch}gVhL™¡ìõŽÐ˜z@ 5 1µF=p€ @€@H€ÎâßhL9®üö¹t4¦ö©+΀ ÊИ*ñ¡eÊç§³  1eZ¿hL™âìÕÎИz…7C u 1µN]p&€ @€Sžï4¦<×~Û\;SÛT' @€@hL•¡1ñêlhL™Ö/S¦8{µ34¦^áãÍhhL­Sœ  @€ €Æ”ç{)ϵß6׎ÆÔ6UʼnB€ P…S%@hL|€:›S¦õ‹Æ”)Î^í ©Wøx3Z‡SëÔg@€  1åù@cÊsí·Íµ£1µMUq¢€ T!€ÆT  Î&€Æ”iý¢1eгW;Ccê>Þ Ö!°û?¶=³îÀu;F·Î)q&€ @€@~ ÐYœßºßƒÆ”ãÊoŸKGcjŸºâL!@¨L©Z¦|~:›S¦õ‹Æ”)Î^í ©Wøx3 @€ @)è,ÎñmÆ”ãÊoŸKGcjŸºâL!@¨L©Z¦|~:›S¦õ‹Æ”)Î^í ©Wøx3ú„ÀØåcUúäЀ @€@Mè,® Sgn„ÆÔ™õÚaW…ÆÔaÊå@€rL©RåÓ2ÍñG#—ŽÆ”i5£1eгW;Ccê>Þ >!Ðïþ~]Ý]}rh @€ @ &tׄ©37BcêÌzí°«Bcê° år @9&€ÆT©òi™æø£‘‹KGcÊ´šÑ˜2ÅÙ«¡1õ o†@ó ˜8`¯+öêÿX™LZ–Ò¤ßÃæ±h„ÌÞ·í­ß פ—´™~7ÿ$9" @€ wtçø@cÊqå·Ï¥£1µO]q¦€ T&€ÆT‰-S>?M)ÓúEcÊg¯v†ÆÔ+|¼Í'°nÇ:3“¤.ia×wiÙÅgêÞÕ­eûmçæNÍ?[Ž@€ ä”Å9­øà²Ñ˜r\ùíséhLíSWœ) @•  1UâCË”ÏOg@cÊ´~ј2ÅÙ«¡1õ o†@ó (êÒÀu\‰Js6ͱ°LúQ&gÒŠÃ$IEËúÝüó䈀 @€@® ÐYœ³êßúÑW¤1MYûsÇî¥9ƒÁå¶*Eí™=<*gÿõžÓÿÇâŸZÏ @hOhL•ê–i{ÞÕœu­Иj%Uv;©KúµòÒ[ç©CcúëGº5o}0µ×G`=!€ÆÔj¼}H@–’\%€S—\|&­Ô«òœd8ieSÑ‚El†@€@óÐYÜ<Ö-q¤é¯¥Î¾Ô²âíá-qŠœî|/~ P'£Ž:ª'Ÿ­¦¿çÃß½ýÕü›unÓÌ!@€ $ÐYœã›bèUNž21Ǹô6 0uÂמrœ(§@€ª@cªDˆ–iµû‡×Û›@s5¦9sæÔ9ÌÞ~›ÿ—ÿ»ýιÞ3>ÿüó[ÿ¶Ï—ÆtòÉ'¿}ÔÖ¿—í¿ß”Ý7ß>ê˜ãNÒÂf•w‹å­wwå•ß½éÊÛ¿{Ã+›Þþݦm»\Ù¸mׯî l(–^ßZ,ë·~´~KT^ÛòaP6e+o}¸6*¬}ëƒ5oËê7?ÊAyõQÙ´s•WVnܹrãûVV¨lˆÊò ïåu•÷–yeéú÷¬, ÊŽ%¯e±+ëvtËöWÖË¢µÛ­‰ÊÂ5Û®ywáê ¼ìÊ«ï.ˆÊ; ^}ç%•UQyqÕ;AYùÎ +ßvåùo»2ÅÛó—«lS™geYPæzeÎÒnWž[ÚýÜ’¨Ì^Ò={ÉÖÙ‹ƒ2«PfvmueF×–Ÿœr¡ÊŒW¶L·²((Ó‚²9( 7™°à³Ÿýlë’?þøcéV× ¿çËû°téÒÖ?a΀ @èptwx—½¼¡C‡þâôó¿ý½C¦NšW\w«ÐÍ©[ô积۵ÕÏ•óƒ @Õ 1U"DË´ÚýÃëíM ¹ÓèÑ£9þ'%¢EÁ²_¡²`ÉêO}úͲ(øérŦ·Ëk¾PQÁ¦Hó(’…Ó'VnJq' âDÑš(Q&|_bÝŽÅi²„3%G"Ô$œ#á gG85·#J½ˆ)Â%:DèB„"DwR„øþáÇ\<ôfYò|Âù×wà¶þmŸ;I¢’}Šbż¥›ouôq'•|´’ö’4¦RI2SªÀä9Lmð>o’™êv˜<©f‡)ú(¦8LÆ”î0ESø™,jL¥Ë.Ïa’ÏTª1Å?Ÿú Vq˜z©1Ur˜"É9LZð4¦-£1™ÃtçýãT}óº6|高L­ÿÝËB€ @ Ó ÐYÜé5œz}’BN?÷R5N_^Õ}àw1™ry´üEËaú÷ïºðÕnݨ§žs &SË×'@€@hLhL|HòK ùSÆ/~t˜‹©zt˜Bh˜ .LIh˜§ÂE„ÑB<"LmÓ«i!`œ;á‚¿”üRêKb¾”| £½¤†z© 1¥‡wIÄvIjL.¤‹‹çR!Â`.‘Æ:LhLmóÍ hL•ü0KnÙ|À›BÉ¢.•^ Õ¥êöRácV£Àä䲎Ãä9L…PLÑG±W“b2UÅ9L ÅFcêq(¦Y^(¦™¡„X9ÓÔvˆÆdÓÈÑãõ Xh¯í˜û &SÛ|)q¢€ @èXhL[µe/L:Èç^ªySÖ8]°b+&Sþî‚V¿bs˜­Þf½( C~êÙ˜L­^kœ @•  1¡1ñÉ/¦kL."L̲ýŠÝ/u½*©–ÜV iW<(Œ‡)LiU´)Ê9LQ2«”LV.Uà0Å܉rÙ«²ŤtUÉDUÉU)ù©ü¨.‰´T±œTÒ˜*S©ÃTÌFµp3јZñëBÓM·ÞeŠ’+ÅÒ;¿ûí­w鳬I“–‚¨K¥—„ÉÿŒU°—‚L…[d/²ÈU˜ÊaZí%’ó-BEE«’K®SZ:¹ª¡˜V–f”óÒÉéCf” "§•Í(W9Si:¹d(&§1•Ë(×ú“s˜ä¨9I*ès‹^'&S+~qN€ @È4¦üÔux¥ÃtÞ¥~ãTáÖ_Z±å[ÄdÊÙÐÊ—8Lß?ô•ÕÛœl'IöN9ûbb2µrÅqn€  1õü eÚsv¼³ô…Æ”FrEX^ 5&9~‰gµ* ¿´kCw"«UõDr®}ë•5oF%™K®r¦R&¬Tt˜üÔUÉPL^:¹H“péäütUÉŒr…b 2ÊÅB1Y4¦¤Æä2ÊI~@cjŶ4&‰JÉ JW|ìIîOÿCå–ËxKág,ñ1‹ÙK1iÝæ‹%ÒãŸ:}üü,rEI&“-E`J ˜.©QÑjÈ%×8L~ÞG}bo˜Ã´dkÉG·$ÜV—RјN:åÂ@cZ÷ž¶p³>Ʀ1ýã?~ö÷øÄ/þË_Záþv“}Õºy„úU²¿Ù‹^ÿâWX¼dI+œ*ç@€ äŽÅyªrs˜4£1Ù8}aÙ–o}çà)S¦ä‰×ÚŠä0}GÓšm1ÙN“zŸyÖÅ¿:´Ï›s‚ @Õ©!Z¦Õî^ooMט|•"¦+éÏ^ 4¦˜bQcP˜ra"›¢²JñÆ~‰®”ÄaÚð~Q`ÊÚaòÓUÕ’Nî/¼‹‹íâB1“S• ÅTÏE“§1¥„q åiLßüæ·bòC ~ öjÁsjÜ)Icºñ–»Rå$[©W|쉶}¢¼™ºn*6† ô€S%h´L{pKñ–6"ÐS¤R¤óIcúL¥ 0[?’Já—*öRÒ¦ð#0EYä>pEY©|"9_œpÖ„ó%gº–8L5:L¾‘y:¹PcÚòýâhLÉ0.ÃEÓ~û#&?|´ûO­v×çNcºaø]f#¥½*iC·%¿„a–Ò"-Ùgl}i¸bÈ¥Ô´q‰›ñÌBŸÕ~©ÆL=˜ü¤&¥©ÛÑ•R©¶DrÒ˜V%J÷¨…•ï¸hi)A˜z™K®¶8Lr˜ôéuS1“ç0•Ó˜Þûð}ûIö¦þl×@D³nâµAÕH,›ùòk_üÊ×k7™ÔµäzÙ’]c}xÕÖI×ÕÕ¥ŽÑÚOcï½÷¶ÎDëŠUï³Öø]õïŠ-!@€ úÐY\¯vݺà0¥4N-È5Nç-©ÃdR»O­¿ºˆhû¤õ¢ µ íG~Ì^{íUUޱ£KŠ2áIŽ;VV}c²ÅZ¡ùé6¶…Øõê´ý5=Rž;´.ÐÜ/;œ»ä ïõ; l3khë·ö pýÙãID¶7íD y :uÝå66‡iñÚ·Óf‚E²:5oÀ™ë2™Ü «2»s´ÒéhIt=»4Û­W–ë*ÑAS?J½9™r•[áXôÉô¬®y @ vhL•XÑ2­ýNbËv$ÐS9ÑB~ż…ÆŠ‘\±!é-•š¯I¨Hu*ª‡_ª-S\`*É^U)ì‹'0u¥É -ÚËê ÓÕ q˜êw˜¶Í)„bzni·‚¹¤Çs)Äa’Ã$ÿÁ4&ŠÉO'‡ÆÔºqEcºaøÈècóÿgï?Àæ¨Î}O”û²oéZYïè#­ ÕlF‡eí#­£‘5-˜;¥/½cCcú–Æììë¶ ggµÛ²ÞÑÊV7½ì8¶­ùÏݪJö­ôž¡¨ @€òD€Áâk;îú7tµî>Rs¢—íÑzgÛ¬k²Gè¬íVÛoHÖ1t¦‹93É);¡1ÇÙª§-›‘c‘ Miš”­µãÉs˜ª†Ež“l§'ÁÔK•5üM›L6Èàú•tCFÌ1 õ=ëZþÈItT$´YpÃÈÌèa"ª~­×™~dG‡{Ìí"½£— ¿øš5Ðz……ÒíË?6Ý–“i­ó-@€@3Иâ(qeÚLbìè¾ÆTÊS/ùËŒ¹+>½û5äŠoË©°²Æ/UZEÅ©¨L×3UÙ^z«¡½T–(B…g/µ&0ù¾D©‰$L=Uy“›HN ³–†s»ô$v©$a ŒˆR¦Æy˜*"„²1S‡‰IåRz¬Kcºê†!U6’9I•¢O¿ÿ£ãÝQTûpr‡V鸪i,Õ”–¢ÞÒ*eZreC¬KÍ&^ZW%FÂ{)&ýR“Sã Li¶§Gi­µI˜¦…¦ŠÀä;L:€KÓ9õ¦´ec ;Lëß\ê¿8¡n˜Øžvµ8Až0{Í>_j<»œdÙ«{‚ÓdІÆü1e23iÉÏÚ:nœW ö0ŸjpF‘¶5ó¨lU öXgtR9½zÖªá×Í—–l¼LÛLéé‰jA€ @ g,ÎY@«›ã9L±vH%“=c£‹Óióe24fÜøõ5&[ÙÆôr©›ÌÜÒWtµîl*·em'd5µp<9‡)š0¬V*¦ò“`6Šrâ)ç53»œ£}hÊ0*M‘=sU¯ï¹ŽêSŠŽŠ¸æÛf]–/n­=L¬·û}Ì2jGÇyü¾ˆöbÚ“ ®Z¤w\ª3{ß*:6mˌɴÐù  @ yhLq¬¸2m¾'±f t]cRF˜°ká)JÓç.ÿôgö¨¡+™_QKZj4‡U]u©†G¶—ÂEür530U LåYäü‰äšMÂäMQV#^Øê{n"¹°ÃTÏejõ\r.“K 1ýy˜ÈÆ”ÞC\Ó•7 ©Rüª?}*É¡ˆ¢¤¼J=©•zr,Uû€föK^r³*i©4U\t¶¸ÊñÖDÖ¥@]j`/‰—T^ªNƒVJš²—bÒ/Yx“ ëLîX ¹Ø L}˜|ë°·I˜œ(‡IÅå^Š.¤'SM‡I¹ïì„»¨ä0UçB/ ÀU4&ÍÓ÷Ô³M&SˆÜ“‡Æsý!6÷© L¦Ùx«]º¼è˜rhŒÕFÜløXiÁ^VŸ¨ÆdµÒûN·²¯ûcµî¡[Û‚[3½')j@€ Ü`°87¡Œ4$ä0)¢_OÔU•ŠÉ{ÆF§Sç½²ÿ7ãL¦¨Æ¤«?½ij‹)5¦%Ù5 åî5½F—“ör¤öì.WJ"çÆŸͬ gç„Ìëã®UmÁ%-6HþE¨þ´Ô5vaëŒ+[3ª1…jî;OV_F±Jú“aÑËVö­[ÍÇêjšÓ˜üKr“ºÜÆm§f,Ùµ(”ZêOÿð9[mý}Y(-¸n-F5¦¦ŸÓC±DnÆd iL>‡×ROYÛ£}ÏuTë.X®§ it³îq2—TL_&¡Îì`ún5#bSÚätî»–êLï;wÍ:mèØt‡c2-wf¾@hH)W¦ ;+dš@÷5&©¡ŒJž¢ôÌsÆTr*\)çX*Ï^Uˬf‹ëq*f°8§ p˜ÎºÐ†m²û*‡ÉÏ\ŠI‰™õÄ¡]œNž·!ÆdŠjLN¡°ÉÇ¥S¸9Úlž¸è“3Âo—„ºÔu¢]®Úå­ïåØýëÐølLþ%§¾e¹vLïˆÊ7¶åš!ª1ù«¹kj½i»Õ+I»]¶GëYScò[¡ªþþ;ÑlL¡©ßŽÉç잃2z¡—ðÍ:L/OPªR1I¶S/ÕHÔÏÝ 'SHcòƒèwcQ2[.Ú÷\Gu#'5GEÜ–Ýfµ ~âwŒÐabHM5sZ˜z…ŽvTc EÄ=rf™ÙwµM×Ál ¶¯è±i5ïc@sz6¥Y€ ¶@cŠCÉ•iÛ:J%®kL¦RÔ+Óæ,“Æu*šÍSÓ[*?H¢° D”Æ"¬wÌ­TÏ™<.’ù¥JœØéç|ñ•‰ø)ä|S¢¦#Q%0óSmUÑÀHPšL´xs|.›œ 1yÁ¦ ÌÊwËÙ˜j;LL*—ÊÃøã¥1]qݘ#gÐuÆT6þª¼¿@NòJµXí*Õ̱dž`é«%-y[Ô[Š?êÌô³.Å«K&»´Ç^ò¦ò‘?.$zóÇÕ;Jm¨È•g¼Iëf`ê½À4i^pôÊaJ¿ÆdÓíÎaòÎÅe‡©Æ0qí8Á;óÅÏ}q¿y Õ ec qöéÙ.Œ›¥óiÈ°Þ Îa*p—FQÊUg³¶'Á‡©*aXY¶³þ?;ùܘÙåšÔ˜ÌE3tѾW’?*âë¢ædü¾:LÜâÇÔ¥%³m†4&×O\D쳚ûŽš?tc—­:6m/ŒÉ´ÜŸù" @ hLq”¸2m¦±Nv $¡1…\ ߬˜ZÒ˜ªµŠ:)`jK5…Š·Ô;uimyÒª}¢¾½T#ýRiº*=úâJüru30U‰š“ŸØE¡VžJ 0ùSÝ$L%‡ÉÒ¸|÷°÷Ûb¦¢ÊI6&]»ºÿ˜°L'õž$Kÿ.iÐu·­tÖQdAŸõÃãj¬PšÎ•Pî²Z©Ìº’sŸ_±ñÌó.±rñï¯1=pÀï¯ùÖ÷Ó¿þfö!G[}¬Ö8\§µ*0ÙÑÛWéí­«tòå&7úvêM³Žºd¢Jÿ¡Ï]ýð›NÎN¬BÏ<Û À]ûØ Çþqê™·Ì~|Æz“³ޢͣ§¯®g2idÍ=u§fiÙž¥soú'Øu­×:.I¾[-´‚Ê}äÛEþm˜Ì^ö|¡Ü ~­B5±•Mir[Àaêd?eÛ€ @ˆ`°8w¦òãëÞÔÅé5¼à’_õð’+Zbs˹aIJ1³_у‰zêéž /þêºý®›q˨åþÅ鄹ëkšL6Iœ{HwÝç®%íÿ:4tݽêŒ^Hús½i}m!tý½¼ÕWLœò¯7CW¬Íßm¹ÞåªöbÉ¢¶VÉšWë1—íÖ]YG›æ¿#»+Ǿ븊é#›ÝÌÞq«9&º„·¼>!a&k¦7ƒTë˜Ã´põ¶‡©4ãáO¯˜¦'ƒ„奲so›ã²Yß7iÍI×ÍP¼’ŠIO‚iàXãN?­o2ù½1TÃPÓ¡ uÝz”üQ‘š} æ Œmͯ˜í×ßiÍžãïÂH¨ÆŒÆhÑ}Ùf“i²³ @ 5hLqܸ2m­Wñ­¬èºÆT[¥¨HSf/•ÆTv-*rEŒYÑL ˜ž|K¥”K~þ©r'~ö«ßŒ™2ß2¿ÜxûCßÔ;ýN—>á ŠQSæýñÚ¡q¢äN”r¾L|vÅ ¿<}Ÿ/î{àw½î¶áÁEbPv¥¶½ÌUåOTÕL¦‡ÆÍ9ôèã L•Ä.%©î,rSÖNÂ䦢’ÆtnF4&7á’Ž6]ÿÚ³4.ïoܤrZÉæ¹·ãTÔØD(_tVŽbÕSÓå×Þs¨èS{õV¨H5’*U%1«NeJhöÈØg>ÿ¥¯œqÞ%*ò–4’ò›ó.9úG'<<æý«eÔÁ¦Õ~sî%=É–Js‡íñÙ=÷ùâWÜQ§åG=­!˜Ò(Œ_v~ó»‡ú)—xbšÂê9ãj«K¦šºtÊY«Ô9®Qî¥Ú“Ç-ÝzçÓOúÍE»tÅO¿dóÇÝþФÝçËÙ°,0ið¨§xóÇùG¬æ«7…œe`òKë“ì¥ÇÎþøôO|ÜôPZ GŠ9LCïQNÔ_ÊÕ/I#¿£fmxbæúSnœõëf™Ã¤™ãN¾~æOâµbûu-=üâ N]{ë¨å‡ oTmNªæ¨gVí]?'S Uå+€ @€ª0Xœ¯!‡éÔ’ÃäF9tqzé°.Iðoï¯bsß>nå7ÎóÈÓkuq:aîkœ5æÖÑ+†OyI§w>¹Z×§îâô©9ë¾Z''S¾øÑš¾¸þÀ`žÊ9÷ÅoE“†°®Þꢔ<ðì1ÎaRGUÿ´éä4F¤åÛÆ¬|hÚÚÃL¸küê a˜÷$˜†P”¨ÿ„“âr2õ­m|€ ô•SA®LûÚ¿ø~º $¡1Ÿ“Ÿ 4&·Âòž¹ªª¦« ›•â"“VÕ˜*Îå¹üº¡²)ýŒÔ¥}¾èwkîÄ…—^-S ŠQ“çéÍÓΚ±j³+vÿÇ=ÏÿíUŒœ6ôþ1Ÿûâ¾×Ýö@ïì¥Û}æÅ÷<6eöòmVª¦[ZžBîÎG&ÿë翚B®*S›&S ²¢1)¡¯ËL¬Gt´,7I&’Ë\Wc’±d¹ ÝsZ.Ÿ³}?݇líÚÓ5ƒÝÔ‰Ñ}zäóß/§)só,VÏþæ¦] T=³0†­@‰Jf/¹4K:À¦>·Êt%YJúwô”ù:Ø”iéôsš*è¼%­ ÷Úïtó–tÔ õ´&Í^¡ÃOEY—4hxÁo¯²Ïe]Ò(I áÐûG˜8÷üK®:õì‹5^símœröÅúWË· ýØø¹¦.=9c™\Â_Ÿu±Š†Ÿœ¾Ì–}ê9e]š6oý­÷Žú핃O>sÀ#OÍQÑÂ9_iç-÷Œ:éÌ'1Àæw¼ùž'7çìWH]zpì ýäç§~ý[ßt÷:Do¼kä¯~s‘Šy6ò–μhP¿Ó/pù­ÿ²Ï—£ÙÒBé—B“?õ£Kž¦üiQ©ålLë׬}oøÀ¤•ŽiL=Sy¹àñA?1kCÐ%Ö¼>bæú#N°(K`R*&ý«x)FzŽpäÌõÁÌ}/lÕHñý“×X*¦À`‚Ì‘O¯Üû ug—ËâN!@€ `°8EÁèkUÌaêú¨\œ^z߯и„iLº8½âÁÅÇ_>U§?½V&*Oðe÷/Òƒ7zôðÂ;æªø§z iÜìuû}ã߯Œß×ZòýÆdƒ0õe&s˜¬ÚZî¨^vsõÒ@c*åa:~Ð4=&uÉá»þñ¥|`‘ 7_t×óÝ9·ì0y²]ð°ÜüM'üꜘÙårÌž¦A€ ~hLq1âÊ4ý=˜ö…@×5¦JÒ-&ÏzáSŸÙ#ìWx–R(ÿKO¦¥—kKþ¤UfSÔœ´Ê쥣~x‚˺¤wFM~^E‚„f¬’Daù_œ;qÄŽ—,a‰—T† }ü/NÓuâï¯rÍàÎ+MW%wÂÉÁý÷ÛwÕmÁ;g^,;bê¼u|ûcOoÒ’\ê³ûGLýÜöÕ±'iI ò–4[œVÖA¨CQ ò–d/飫?péU·évdŽ›¾L^}ËR—öþ¾:,å~æ÷Ôqxå-÷f=u|Þý蔽?¿ï%W ¾òæa{þËw=2yàÁ1©aJÙKZtÓ°³\¡•u”¼üÖŸüìÔ sÖêM}tûÓ$-Yî%M$wðQÇ}h¢&•¾¦_ª/0µ 1I`zëžÓ>:­"0uRc2‡iÈ}#‚ÞèIoêBGœxóË¥(Éaúõ 3/) ›úÈÓ/k¤XçP€³aâ±s^9àLuµ £•I`6§“ÚÈi˜LIØ/ @€òN€Áâ¼DXÓ)g^Xº8-?]c£º8=aдߕì%Ù!—Ü3_#€z–Fƒ}¦1•/N—§ Ð36·?¹Ê¥b²Ñ7]œŽ}öeL¦¼ô—δÃiLud¦Àaúî¡óWmµÁ:7Ò­a7g;ð¬1öè­†JÔK¥1•ÒÃÐzÌ:êáÆßõÔêK¶Ú•ž³TLÖK5ޤ”Þ˜L 0[… @ OИâðqeÚ§ÎÅ—SO ûÓŽ«éZ˜_1qf 1Õv-š0+|§"$-9›Â©–pWeÒì•2(Jù_ö>jšMg…yK§ž=PÅ&­*Ï·z‡ä‡a#¦Ú,Uþ\UzÿðwÞ%W^}ë'î}|ŠÔ% ºx<÷â+ûþqÒ$”êE¦„®"åHÈ^ÒÂ1'ž¦™ã$HóóSm 9ý«¢)ªäBSéJÓ³—*Óf]~Z.+º­”ž)äüÙ¨ÜrÑL.™Ð˜ÌDr“˜5ÎÆdkG5&ÉPMŤæHcºìêÁõd#½¯OøÁ±1+ÄøI5«Š šX¹èÒ«GO™§…‡F=-iI˜ýkGšcV,»Ri¹îRv•ÝÒR?ÑHñyCæhŒøÜÛæhÜMÿZ 5§1bM$¤­“ÃhL[ÅDÃÄW=¼Ä&Ñ À‰&SêÿB!@€ M g3n¡Z—¦ ¢§Ö0É&=`süåÒ˜æÙÅ©ÆtqªYºtqZzÆ&ÈÜïš¿¼fº³C‚äʲɮÓË&Óýw†/±CWÜüYLܧœÉ†bªe&9Lßüî!óVnñ;ª˜ìÉ@ŸØŒ‡6—\IcÚnÙ¬Íaêwí •žéäBO‚•ziÙd:÷z) PP¯-ÉÅo;€rH )‡Ýš&5I ëS¼J1aÆiLÍd~‰šÁEÜÚ²Pš®Ê©.óKE¨Ø9kÉ+ò%.»fHH]2‰¢t (éâ ñR)ë’“–Lc*=ßb%P&T,Õ‹ŠÔ¥s^yïcST´¬l/Jõb×Jï"AB šŸê®G¦hÐCj~*Í'A²ºØ¿*ÃÇÌ6AÂÍL˜ü¬.5&6ª)[“ÊÕÔ˜”¢ÉMW7SMI_Ë®ÃdÓ®\Ï7Òûúôˆï³‚—©L’•ðáTû¸ªˆJ~v%›ÎS—vjÙš©˜Æäþ Rœ•4&SOøåé*š¦ñþ‘Se,Ùd*NWÒ›ÁqX9öî{<Иt*åR0OÜÊíò–ôŽ%@Ó±g“ŽCÁ1{ÉiJ¶dE&Ó]¥ÜK–MÉ( ².Ic*%^òËY rsÆéàÜÿ[Ë^’´¤iãtˆZÊ%Wθp4¦ò±ºpó×¾y°;VÛk/9™IÒ©„Ü&ÿÏacæ~ïŸ?ùá™ÿ{ñ2쬭Ë7î·Ûñ'žÒ#™z³ ꤬‘âÇg¬s£oz3û•`˜xÅö²ÆT&~`òKœ9F“—±¿’Š©2§ÆÞ6|Òûç½ßÿÛMþ ² @€ ÆИ3JûÓ§OÿÒ¾_«z²’@Zƒº8•Àd6J ‘Ã4ðžyæ0iœÁ4&ç0雲ÃÉì®Áõ˜ÍßÿÃg¶üâÿÓÍ pö• ¿öì¥ê˜·.ßÿSŸÞcÖ¢õ=Cvn¥ü `0ȦÁç0©—êOßaR¦‡)4\%“ë¨{a¿qGüÇlpkëhM†ooMû7õƒ I ©ŸF—t_cŠU)ÆKcúôu¥ºfEÙRr•4K.ù‹“–,É®+Ê·$wâ× ±©âL]²¹ªL¢0}BsU©„².I“PÎS—Ì[ÒtUÍÐ-k¯ô ¿h–ª[î%ABÉ)÷’ Kò"uIš„þô‰ácç|fÿâr/‚Dlú¥¸ùãJ“,ùÉ\bÄ}”‰lLvô†²1ICr“>í…ÆäÛO=1HcúýU·ú9ÇBËúTS½jB‘ÃÉŸ.rhy•¾ùÝCg-~EG×ÌůXj%QOLz^ 67œéJ:Òªó›•Sœé+nŽF]æ êÀ³É%-ÉRÒr0"óC$-9sÐIK.å’Þ  -/‡Ê´$iI™–,—B‰„¦1é°ÔÑXÊî³M"¡ŠR¢Ù„qvXê©J¹„¦+}ý[kª8;,å0iæ8½ÙO¹—Jçþß ŽÒ¡Æt¡’éÏ?ÞpŸyKr˜ž|ö%iLãf½${é¾R6¦ÙK½Ò˜>½û½ËÆÔŽ'#OüÙOÕ{ºœ7ôväÀ Ò˜lôMä5ô6úÙ ¦£iŒøðl˜øñéë5L|ÿä5áéäªàäií»ß×gÌ]±vÓ;˜L=³Qm@€ ¤‘S£Òë:)ӯϸ 'g{%´Æ7tqZžå|u0,(‡iàÝóìâTC Ò˜œºÖò0Y’`=ÔNÎ]ž[6¦{† ]ûÜôwWÌ(hžvŒ'ä]ÃlLz–oùæÈºåÑm ¡hðÄ¥²Ö µþôæ’›põ£/X&—Í:”0Ìec:ã7g©—¾±¤:37±ƒrO`؉ÁmÂ×7ôú§”/@è<4¦8Æ\™v¾²‡$ $¡1ŸOM_,©öp½Ð*vúsUùÞ’=Ie9_FN|^fÅý·´ÃЉó/¹Êt%›¥ÊŠô K¹Tv'Vl—2qø÷+bh¸W~ãÛ‡H“Ðlq,±|›t¥+o¹ß&§’,1åùuÒ'®¼ù~?Ï‹2¼(ý’å^šøÜËv])5BÿJc?g­nÓ?0z¶æ§ ®4‡'óí¥à Ô›“Êe`j˜~)d5eTc’äIáüC©YIOàí¶Ûnú¾½|*É#³—û4¦+ouù¢ úôðïë'Lª¥"•'}ó>*KV<0tPÙŸJ¡¤#êÔsêß?\=DÇØu· Þ9;xGËîHsùÍüIå-¹?o6ZAQš¥glС¨#SE+<9c™9-wâiîØsÒ’æ‰Sѱ'oI“‡NZÒ1&“Iù–tdÊ[:録u4îýù/k*G›3îÁ±slÂ8Ë„VN‰V:&U,1š~ü³SuLêàTâ%•ÒÁhL²—†>8Qº’¼%›9î—§]ø£Ÿž¢ÙK]v‹~qÚ…_;ð @cZ$™¤JSÚùAñR Å‹‡õ>m&“4&)>*µe&]¢wæ¥îzé•·–g¬¸¥:5k¤ø•‹Ëå¤ëgX”LJ¦“ sÙ”Î}ØEã-•‡¦½¬sŸHºŒýbâ;LÖFL¦Î“­B€ @ x,ÎKÌe2ü› ܳ6¸a§ÊÀäÔ9Lß=Ï.NUtq:|ÊKzöéÂ;æ§Ê§¿»g³CÜE}Ùazp”]™ª¼û> ƒóÒÚÒŽë¬J£ÓËœûü k^9e%nÙfEq½ÔžS‘·Tžñ°4„¢?m.€‹î|^y¬Õ?­\zß [éY;PãQóƒ(ÿY¸3Îàzéo¿ß–Ʊ@ Æ]ŠÆ”HQK’S\ع2-äAQ Fw]còUЍkñä3ÆëW4«U¸Ì/&-Y±LKVt (BŽ„•Ç'Ì}jær-ÈX:üÇ[Úó–,É‹¥\rîDpaøíCT”ÒEj„¬‰`θeÛl¶8•‡Ÿœ#ƒBÓÆóóÓdJèþû¡G§"_BY]´šR.ɈqÓ]O\|ù­&HrÔ±*$è}¾,GBv„œ»Òt¥æäqµ¤ˆ^YÔ˜ ¤ÌLÎD¦¦~ÔðÍò±ä9€þAåZ;GLœûû«‡è_—WiüÌåzGG—o,M_¸AÅY\Qr3;ÞL|tüs¤<õX*ã¦/³âìñ2›¯qê¼u*îðs ´t¦¤%Íà8Y%Pa–n4÷e91*R—nºû S—‚yÇαÇÔîxx’-È(4©pÄ”%7Ü9R3Ç™ºôÔì—žzö%;8å-Ùñ©å[Ò!úؤ%×Ý1rÈð N0¼÷‰Y·=0AÂÍ=O̲$i~ž´¶ØK½ÍÆä†¨LfzoøŸþ‰òZÇ4&\Öc}±T}fììW}æåGžVY;qÞköœ«¾©Œ˜±Þ’c)Ó°Ékî›´æÞ‰/Þ;áE&HVܯ¨Ã„É”­µ… @€@ª 0Xœêðô®r2™NúÍùÑ‹S]~–Õ•Û§—r0[‚çòÅéÒàâô±gÖéúT§÷éâtâ‹O=÷Zȉ:L˜L½ OÖvSD`r­7“iÎÒMn°Û†¶m¨M£(ÁHš{ ¬<ãá¶Çg¬`òK*Á(ʤ5æ¾Öã0Ug³Öƒp¾Ãd½“©½6B L‰®¤˜S\p¸2Mq×¥jm Ð}éècL®¨éNŒ{zñ?|z÷†ZEyx¡ŽVá»JΦ°g¨ü¢«T”ðÅŠ“–47œ” gPhaÚüõ*vK݉NŸP¦%MQe÷ÙUîztŠæ§²”K£Ÿ~A³TÓÆ•d ó%,ý’oJhr*™ʺtùÃôoi¢¤ ÷Òý£žUn_蜽ää‡ iL’ìzä›H“ôf© Oš6!)äwWÞZåÙáQ)úTST?Šy§t õxNôªèq:Ì|Q©²Üã*ù“2F=Á²·T:êBž~6€*Á q¥Iâì ´"yP%˜*®r(:iÉÜ ŽnA9áÝTŽ•c²'%ZÈ+¬NŒ¦'Ûªr£õ†‘)Û«.ù™™z•©êy;̓þØÙÌT_czw疫ʇŸüíÝ]*Mê´¿½â–r¿*­‡Ø<¾ÃT h;‹”¥ë¯5{oáC d‡SvbEM!P@hLqAçÊ´€‡D¡šÜu)P)œ\áåI2›bì´@cªgVÔÕ*VWpVB…û³Ú¦¨ö(*i–Bɖ̈ê ­‰@–¨øU²DéâÑ/54‰EÁÌq~â¥ffŽ«JéÒ·Ù¨2¤1Å©…Ó˜zŒJÂ1_<Ò§:öB’;lü…z‡PôýZŠR9ƒ™ŸWɬ”hqÙ•ëJ•|<µ¥¥ÀXª’–ÊG '-)Ù’ŸoiFõqhÇdï¼¥RîêÒŒºÔ¶9ãÎ4׺Æd–d&•Z/ N=zô^3/ë'™)ôùäþG÷jŒ50™ÝÒ3ôV{ôm›Ok9LáDèñ&S¡þ{Cc!@€ Ð) wŠlbÛ•Éô«ÓÏ÷’FW«!¥A yð/N[v˜B&“.¥UæÞÔ?Ô~]}í·bPØqw4 »d2¦êÓ•;ž÷æt«ã$…µ$7é[9‘REÉŸ|±GWªˆµS+ÕO°Tˆ‰äX²ÇË¢ÒR(ÓR]i©Wù–d6ò–Bgç&Œkè0i…¾jLõû›Æ§¢£«¶º†´z{üü丟^2èæ‡´2Q`Ïè[ø B—‡)ü¨k3“ãÞy÷o½­$ëC€ @è!À`q{Ãù ìwZÿPz`7ËyOz›I‚{—‡É9";Þz?þR:æê; M Œ7þ€o=øÈŸÄ¬Ð“ŽÌ²%¹²ÔÒ&ÕÐ’êÊIì«V”â,¥:GZYa±L<‘ìJÞ×3+\m]©Nš¥&3-…“-%:O\3°[§C“ŸÒh©¤l ˳ô¯>Õ“y*zSUrµÇFõ¯Šȳ,Mõ^2™.ºì&Ën“KÂäžs †‰½'q˜2y¢Ò€ @È4‹3¾&*/“éÄSÎë¹8õ2—/N#Ø´æ0¹ j=ä¦âÒ…³iö ùº ÖŸ2Hlºv»Ê¶ì8M4ˆUrH@&Óþß×?£cA¦Ü™·dR=̦÷-͘þµtM¼ ô@cJol¨ ð1S\'àÊ”C$ß’Иb\‹Ç'ΗÆÔدˆ8á©ßBBEå¹'B¥/©^J·×«JÝdKiõ–BþS&xiLJc#éÓƒŽøIƒã¤¦‡ä¿¹dKÍe5«˜yß"ó/ÚDŒ›ƒRšˆ±®¨T;µRYs©™`©JWòÂì¦Yj2'S‡4& ›Úv6&¥"IÿêÉQ³—ô²ø*–{É$µ¤÷Í]2™.øýžÀŒ»Ñ·I•ù5q˜šÉ:€ @€@û 0XÜ~¦iÜ¢L¦Ÿýú¼ª‹ÓZØôÅaò/¥m¶8{þGæ‡þ”¨ä_SG/ºíòœW‘ ÈdúÚ7š8w½ž =æ§²î‹ÃdМ¤ÐXÞqŠ’MçÔ9íO×o‹&Ú´@cJ{„¨ M).ü\™úà(@ã»®1Å«N4¦f]‹%µç}kRTªž–ªñÌTQc©lMÔœ!.&ÃKå.|“6B—WCcÊäa/I9lêéDz_ŸêØ‹Y!æ£ò´nõçwsZR%‰ŽiI®TùI ,¥’¨ÉiæTÁMõ\¥FºRNr,5:èÆÔÃC&Óù—Þ<äZkŒXp˜ºö@€ Ô À`qaº…L¦Ÿž|®qRCúâ0†" í,Àd:ð ñÏ­·<ÖÑÇÀúè0u¶ölH4¦4D:@u 1¡1qp—@SŒ/ñÈøyÒ˜šq-ÊfEdÒ7_¨ˆW)ì1•%’`©<£QkÓR¥[ZŠJhL™<HcR›Näÿ©O¥1ŬP'CRHHªäLòÒ&¹üIq)”Ü‘VûèòšÅ‰J1®R%»Rát¥zbS¦5&„2™ú_zC0ñŸ—¨ß‹Ã”É“•† @€@n 1å&”M4$0™N:×]œº Áº8Åaj‚«tƒ€L¦¯xÐSsÖ¹Ôãþ`QËsÉu£êìH4¦4D:@hL-ô®L[€ÆW2D )F¥xø©@cŠ®P-$5ÈóÒØ¦¨«RÔ5(‚ñ Wæ7ÖójM 1eèðí©ªiL¾QZÖ§ÿvøk®PWè«'úùïÇeN M¸X9ºjù€ö¸XØRªž®ö!7£ÆýaÄæóå{ͬkLêÜ2™ÎûÝ ¡àâ0eò E¥!@€ ' ç)šM´E&Ó '3i~ð\+8LMc•îL¦o4nöË¡Á.¦îÅ€=A »И²;j S\¹2-À!Pè&v]cª§R˜_ñГÏKcjì!õ.‘RUª—`’¢:E•«3+\IœÈ«Æ”É‚4&MÂeÓ±ùÅM…¨O¿wøkÍŒ’šù3’z¦TŒÕ’êúIu¥êtJ:Ø•Z:Ýä@c2“éÜßÞàζ8L™<=Qi@€ 䌃Å9 h͑ɤ«l¦&P±Jbd2í÷“`ç:*SbÁ`ÇÈ4¦lÅ‹ÚB `ИИ Öåi®G )F¥xpÜóÿ©Ý{éZôB¨¨'*yy^ÂsRåØXªib¡1eò!I3p•½Z^‘>ýÞa?vRQË áC¨Vš2KVæÊ¤`R0+%')TÈ¥Ô’¥ÔУ̇Æä›L8L™<7Qi@€ äSþbÚD‹œÉD¦&h±J2|“ ‡)™°Wd‘S£F!PhLhL…éì44B ë“2ÂÄÃÇÍýûؽyÅ¢®SQíQÔµ”Èó1(И2yšÆô“O¿ööõÊO~~ú—ö;ðÚ¡#z[®:"R¿fhãrõÐÇ) øÎ¡?R‰©ÀE—ßöéÝ÷X»é¿¼ñöû)<”“é§]´ï~_Ÿ1wE¨Â¡?ßy÷o)¬?U‚ @€rE)WáìEcd2ýøç§+áÍ=ŽŠ¿8Ýöæ{½Ø.«B }ÌdRG=ãÜñ½tÓο|øÑGíÛ3[‚2K)³¡£â(4¦¸(seZ„c ÈmìºÆ¨!×Â3+.¾|ÈÿñŸþsŒhQË©eQשHÐ"Èè® ýì´˜ÊÿúœK¥¤_Ø­PÇõСC¬~)H~ùçÙç¿ìù‡ÞäÏø§ÿç¿«Ä7ðØŸö˄Ƥcù¤ßœˆÃT¨s… @€@z 0XœÞØt¼fGœòÜò¦Žƒf} ð»;÷;âä=q˜ú€¯B `И pš l@cBcÊV¥¶í$Ð]iîܹ!×b¿¯àßgÿû~íSŸÞ=ÇjAú›&×eï}¾_Ï¿¿ ©‡a'¶?ZÁ§¨I Ù˜t€Œ\µÏÂWÆÆDuƒ @€Ú@€Áâ6@ÌÀ&výuW|-}“ ‡)-d}“ ‡©]€FC  hLM@b@ )hLhLIõ=ö›<4¦vH<½Uò·~ ]4&4&ôš@ 5&—ŠÉ%dr&S Ï;Éÿ¨S@€ @ ÓИ:M8Ûï?¥ÿð¥ÃVÄL&¦† X¡Cö¿wÿ-»¶ÄoÜL&¦…€ÍB ИòEÚÜ@cŠ -W¦¹íø4¬D ©R¨]cRH4šS6ï|wçŸÞ‹_‡OóD`Sÿo¤ê·ÑOÅä'dR%ÿò~ºªš*nT€ @è ‹;7›^óúÙ!c_«Ú,ܲÐþUr&—ŸI+XEeÌ~eû3µ§…! n¹×-{Y÷Ó¿êú×ïnyÙ–l^ØPx* 9 T@c¢G@)&€Æ®LSÜu©Z$­1éNt¼' ÑbëïæÉ%È\[¤»4¬ó‡}Ô†ÞØÖM]cj+L6d„R1ù ™’©{… @€ À`qÞûÀàùƒe‡ š5H •Ϥ¢äL~~&}ª”®Ii5ç<å íKõIõ=u×é¦ýèÑ*ÖMW’ä¤e-ôÛOÅÿ(]Í 6€@âИ€ê@cŠë\™rìä›@ÒS¾éÒº  1%Ÿ]C  ¢©˜B ™Ú°6@€ @ ·,î-±¬­ïüÙ!&‚襗öÆÞÔ¿–ŸIÖˆ ’¬µ’úfž€Ì$“íä3IT²ö˜c§—ô&}j†“½#ñÎÖç@ ŠH14¦¸àpešâ®KÕÚ@© ÙD  1¥1*Ô Í¨™Š‰„LÍdM@€ @ #,îÖmÔÙ!Z b5óíË̤w,Ž•5€ªƒ€D:›ôÐ9vÎÀÓ›ê“r˜¤7éS뢖<¬lh% ÐhL½¡Åº€@—  1ÅçÊ´ËÝ‘Ýu™S—³»n@cêiöøàÃ÷6¿3ÝÊÚ7‘½4}ÃÏÝ;o½·ºûd“€ @€š À`q2½Šùj‚ÓDBvˆ&éM’™¬™c_k‰šxA ›œZ眧jèM˦þiµrN^7+ɾ @cÊ@¨"ŠK).ö\™÷È(FËјŠç¶©€A§Éù$ðÎ_7HcÒÿVóÙí’/C¹$€Æ”˰Ò(ä…S\$¹2ÍK?§µ  1Ñ3rJ)§¥YÅ#€ÆT¼˜Ób@€ ¤˜ƒÅ)N[ª&9ÉæÞ2™É^˜ô¦™LöŽ26Yò¦¶`g#½% ®¨²ë¯»,y˜½\ŸtUÝØŸ±·{a}@ ÿИòcZ @cŠ W¦îÚT½ hLM@b•,@cÊbÔ¨3j@c¢[@€ @)"À`qŠ‚AU @è4¦¾ñãÛ€@G  1ÅáåÊ´£'N)ñPÎ@cê W¶ ®@cê:rv@€ Ô'À`1½€ Ü@cÊM(iòH).ª\™æ±ÏÓ¦hLô†œ@cÊi`iVñ 1/æ´€ @)&À`qŠƒCÕ @è4¦Þñbm@ «ИâpseÚÕÎÈκN©ëÈÙaw 1u‡3{@Ç  1u1;€ @€š'À`qó¬r·æ“k|aÛU¹k Êç6ž=mý1¹j:J©£xÙ8 Ð7hLqü¸2í[ïâÛi'€Æ”öQ¿  1µޝA mИÒê@€ B`°¸Àá¿cán3^9±ÀhzH¶{xùg3PQª¤„SJA5 ZИâúW¦5ù&€Æ”ïø¸uhL>MÏ4¦|Å“Ö@€ @ ã,ÎxûR}4¦¾Ðã»Ý!€ÆÔÎìù!€Æ”ŸXÒäS\P¹2Ía—§I4&ºCN  1å4°4«xИŠsZ @€ `°8ÅÁétÕИ:M˜í÷Sß²‹S±âMk!1hLqãÊ4cÝ™êö’S/±zV 1e%RÔ l~gºFŠWî )@€ @É`°8ù$V4¦Äг㦠 15Š!4&: bhLqÁáÊ4Å]—ªµS ²‰4@cJcT¨Z `Ó‹¯ß×Âwù  @€ 6`°¸Í@³´94¦,E«¨uEc*jäi7Z%€ÆÔ*9¾tSd®L»ÐÙE‚И„Ï®;I©“tÙ6ºHàýÞ’Éôîß¶vqŸì € @€@ ¸k 18ø™i:SfBEE!hL) Õ€j@cŠë\™rÔä›S¾ã[àÖ¡18ø4€ @€ Ð! wl6‹Æ”…(½ŽhLEï´½%€ÆÔ[b¬t‘Sl®L»ØÙUИ€Î.»A©”ÙÚK`ÿ{÷ß²kK{·ÉÖ @€ ´“ƒÅí¤™±m¡1e,`…¬.S!ÃN£!ÐhL}€ÇW!N@cŠ#Ì•i§ûÛO–S²üÙ{Ç 1u -†@g,ܲp¯[öZóúm^ÿÊgÒ¿ö§½Ü²´2ÂSgâÀV!@€ X ¸ƒ 18ø™i:SfBEE!hL) Õ€j@cŠë\™rÔä›S¾ã[àÖ¡18ø4=›úOé¯lLƒçž¾aúÑ­2hÖ —ŸIÞ’–Õ²~cû©øe³¹Ô€ @È&‹³·¶Ô©-ÙHG  1u/‡@  1å0¨4 ù!€ÆK®LóÓÓiI-hLô‹œ@cÊi`iV~ ÈLRQûä3IT²†*?“-HoÒ§f8Ù;×·õyA€ @è‹»Ç:u{BcJ]H¨P„è4¦Þñbm@ «ИâpseÚÕÎÈκN©ëÈÙaw 1u‡3{@Û(Ù’R.isZ°ùã\&-Ë^’Ã$½IŸZ®&- 1µ>‚ @€š$À`q“ ò¸S£š‡6-Ùz¥ì%+ÖüÝ=‹?áþœ¶þ˜<´6@í%0羯?°\.þìÇ¿Þí㫾ÒóÎÛ[Û»7¶@ ehLqè¸2m¹cñÅL@cÊD˜¨dï  1õž߀@¢\â%·àò3©^zsË®-²—ƾ8Öª©üL‰Ö—C€ @…$À`q!ÃnFc*pðSÝô×ß]¢ÎY³,Ûvcª«Nå DHT:ýëî`´ 9*‘±S@5  1Åu ®L9lòM)ßñ-pëИ |šžM•”~Iy˜”fÉZ IÌéM-Ø›šHÎ’6¹w²ÙVj @€ d–ƒÅ™ ]ß+ŽÆÔw†l¡C&¿|TTc¾ô“|ø^‡öÈf!lxììÚÓkK²Ý.jä‹S\<¹2ÍWo§5ahLô‰œ@cÊi`iV~ (»’Ê®¿îÒäq®•–Iy˜\î%™Lz‡TLùí´ € @é&À`qºãÓÑÚ¡1u/ï š ™HÅÔ¤|9'P3!©˜rušì@cŠ‹W¦ÙëÑÔ¸7ИzC‹u3D)CÁ¢ª€ @€ Œ`°8#êD5ј:A•m¶‹@(!©˜Ú–í@ ·¢ ™HÅ”Û`Ó0d•S\ä¸2Íj¿¦ÞÍ@cjŽkeŽSæBF…!@€ @©'À`qêCÔ¹ ¢1uŽ-[î;PB&R1õ)[€@Î „2‘Š)çñ¦yÈ$4¦¸°qešÉNM¥›&€ÆÔ4*VÌ4¦lÅ‹ÚB€ @€²@€Áâ,D©CuDcêX6Û..!©˜Ú…”í@ çü„L¤bÊy°i2I).l\™f²SSé¦  15гE)[ñ¢¶¨K`ó;Ó5Rüâë÷Á€ @€@ò,N>‰Õ)1ôì¸9.!©˜šÆZ(<—‰TL…ï €@:  1ÅÅ…+ÓtöZjÕ.hLí"ÉvRF)e¡:h•S«äø @€ Ð wjV6‰Æ”•H¹žJÈD*¦"wÚ^°„L¤bê58¾tƒSe®L»ÑÙGrИ’cÏž;J XÓ† .} 8ð¼ó΋_‡OsFଳΊoÑ7ÞØÑƒ°]—ÆtÅ8²1µ 'Û @€úF€Áâ¾ñËô·Ñ˜2¾‚T~óóžYvYAK3ÛH`ëÖ­mܛʷ·n½î¨,U˜ºBE"€Æm®L‹t,±­hLEŒz!Ú\,éÄO<èÃÏ»` +ç^0°§œ?ðß>üŸÿeïsÏ¿ØÊ9ÑÒÿâsú_|vrVÿgW£œyÞ€r9wÀ™^9ãÜ^¹èŒsÊå7ç\T³œ~öEÑrÚÙ–ËYžæ•SϺ0\μðÔ3/<¥§\pÊ™=å×g\P³œ|ÆAù_Î?ù7çŸ*§ŸÒéçÿªNéwÚù¥Ò?T~yZÿ œ.¿8µU9¥ÿ/N9OåÄZåç¿>¯fùÙ¯Ï ÊÉç†ÊOO>ו£ýÕÿ÷û?=é\•ÂåœN:ç„_ó÷ÿð™éÓ§§ÿ|0æÉ‡?»ç^ý/î—þªRC@€ @ ÿ,Ό붩ÀÁÏFÓß{ï½£Ž:ê_÷ù’žxÌF©e:èIH ¾-Y²$Õ¡]%@ô»Š›A½$€ÆŒ+Ó^v'VÏ4¦ŒŒê6K pÓ·Þ±ùõ¿egP6å]Wn¸õŽsÂÆïºòÚŽwƒ²]åÏ*¯zå•möˆ­»\Y¿uWP¶e]¹¼³nó;/{eí¦w\yiÓÛAÙ”5®¼öö‹åò§_ûÓêW{ʪWÿ´ê+o­teÃ[+¼²|ý[Ë׿ie™ÊºrYºîÍ ¼¬òÆ ^Y²ö +‹ƒòúâ—‚²È•5¯/ì);¼ØS濸sþêr™·zGPVåy¯Ì]¹£T¶«<§²¢\æ¬Ø”åA™½|›•g—õ”Y˶ÍZª²Ue¦+/lá•éK¶¸òÌ’-Ï,.—§oyzñæ§eš+ 7Oí)›†›û÷ÿ°û”›&»2Ó¤rÙ8iþƉó6îý…ýÒ¯1Mœ8ñ[ß=dÞŠ-rÑtQÝì €õ @€ tˆƒÅ›…Í¢1e!JÅ­£9L·ÝûøøK¾¸ï×0™ŠÛzÙr ¸é‰ÐY‹Öi߯a2õ^æW'ú™! €@Þ  1ÅE˜+Ó¼÷ÿ¢·©è= ·í/œÆ$Qɤ¥*ž®dË7ÜhL1êR 1…ì¥mî­À$™És˜z¦ZS 0µßa 4¦ÚSIc*;L=Óš×yÓÂÃTјæ­Þé4¦^8L%É9L5¦¶Îô5¦%[«4¦ŠÃ$™©¦Æä9L›§,ŒhLó7Mö¦Ió²¡1•¦Cç­Ü„ï¥×•: “)·çl@€ ¬`°8+‘ê@=ј:•M¶‡€9LCî¡Gû4ŠòäôÅ_ü2&S{Øæ{+%‹åBë63®S·ÁdÊwÄýÖýâÄš–B »ИИ²Û{©y_  1õ• ßO)ÂiL×ßrGÙR²4KåLKådK×ß|»4&?åRÔ[² L¾º¤åZé—”‡)’©J`zÇe`êE¦J&? ÓÊ^åajà0LU*¦Ã´¦q*¦ZSŠ)ÈÃTIÅTÎÃÔG‡é…j‡)œŠiK|*&%a gcªÖ˜”Š)ýÙ˜‡é{‡Î_µÕFR;åÍÒ”˜L)=éR-@€ „SA]«™hL~ª›nÓÐûF(I¹FQ”\iÈÇ=ƒÉ”ꨥ¡rd;õÌ •ÞÞßÔm¦/ÀdJCdºQ‡ úgýn f€@_ 1¡1õ¥ÿðÝl@cÊvü¨}]…Ó˜®»ùö°¥äæ‰Ûög}úßœš-.–"ÞRH]ªš<.b/U§_*ÙK•)䚘4£\+ÉUæ’+O$˜ìÚÛ›N®y˜4¯\ãéäÊsÉ5;ÜìvN'q˜ùÓÉ©˜œÆTžQ®V*¦”kLæ0-XµÕI‘Ƥèœt:&§~@€ @ 9hLɱO|ÏhL‰‡€ D 8‡iYi|Ìž+eß9öéÅ_ '¦³XªºMð áÎg濬nCN¦|w/úo–&1$6 ½*údäÊwèi2G )s– ·SÛP²¡t(¢Æµ”Ê –¶ýùÚ@c:>”i©ÇXRÖ¥-=eÝå[²d]R‘®äoæ¸`¹&í¥SÈU20­zå-? Ó / Óò o-_¯ò¦Ê2+ëÊ¥žÃT-0E’0•‡r‚ ³R‰$ajv.¹fó0ùӳ˶ÍRYª²Ue¦•ðtr[jN'WšK®)‡©Jc 9Lóƒ¸ÒÄp×ÜhL¾«dËž±T’–jå[ R.Uϧ.m|{Íko¿X.’ºk/ý©Sȵ 0­m”„©áDr«wÌ[µ£Ö\rÛËsÉ­Øþ\©´8—\Éašá•*):—ÜâÍ¡éä¦.ìIÅdy˜¬<0nîßÿÃîA6¦ù›&•ËÆIžÃdÙ˜1Þ—ÒÔ…?!T¦mõFRæ­"Òï´þ-˜LG}ô^{íÕ|uŨ¯hýzßÚÿýCWÝÑwÜh—>êß¿¿6hÛä@€ d’ƒÅ™ [{*ÆÔŽl¥MœÃ<û¤bê™QÎZëI0kš²è ÿ㫽2™Ü0ˆ†2ôš>}º«²½ãþTzõ½AÚ¦vêß¶íÈßÅØ±ckšÍTFmѰLTF‰o‚ ­¦ >¼æwUÿ~¥—Z}Ø«-˜ÅRî6ÞŒr=ÝfõŽ©óÖªÛôÖdR-pöRóU±zñНsÃ<n…@+Û¾ì¥xí¶ÛnÚ¯{§áÖšh›õw¤î¤wj91}#Z™nö–E߈ZŸ÷O Z%ÿHÑiȈªjì€O}EËÍæÑutÆpS V™f6ÕLLj_Çê]§Þ™Su³1äƾׄ-@ £ИâÇ•iF»5Õn’S“ X-k §1]sãíÕNR•¢¤Oð“ã¨T3Ç’Ë·•–ÖÚlqÞ„qUsÆ5R—Ê3ÇÕɽ´Ò˽¤–§•[È'Ì9€ @H‹S†d*Æ” wö!`Ó÷, ©õ¤bÒ™FÃüœ:%)H">bò‚æM&7H¢*¡{í÷ÐЊÙð3â¸1KªdÚ˜‰ ƒX~7¨â7KoZ{Sb‡­¬e{ß½¸¬*ZpY%U™Ð¸M4‹’ÖÑ·¢AhÇš©mÊSÑún;n5UÏÆ‘lDÈjr5¬-Ú‚Ó³ïËÅrvà0…R1i(µÜmzì· ýüäçzg2EžšñrÃhÁšè\'@äÍ1´¾g©˜ÜíSS^ô©“ÉÜ ‹ ¹eú3´}û®þ…”,÷‘{BÒ*o«…ý:‡z—*:4\£:Ú[b¢_<ætîco£oÌëÒ²?ò)Ô~ú%}d«Y«C[ÇßÎZÁ dúbÍsŽmÊÎö ¹ƒ–Íq¶êÙ¦¬Úþ€°>r'+;ÒݩƣܦBY‡7Î8Xý•̵ËÎ]Ö |¶/÷2›3ñ“€@âИâBÀ•iâ” t”SGñ²ñäOcºa¨?;Xhùê†~ÿÇÇW)J‘ìJJ°α¤4KU™–l¶¸Š´ôÚŸä*ùe•ò-YyÅÊ[=sÆÕR—*öÒ›ºr¶¢§Çô ˆ•žÜKAZìªÜK5ì¥hú%iL=öRp%Ö9I>ÍìåÛÊÅËÀÔ”ÀT„I ™žYÜSž^¼åéÈDrÓª¦ž‰ä4—œ9LšH®¢1•¦y%-EKª&•s“{LAžª?'à"ü‹Sš5™t­hãhî¡]Ú@’7é:Ù].Úµ·{ÐÇ.ueëòQÛ;ZͶàžãqíîj9$-ÙøHrçFö @€ ôƒÅ}ã—éo£1e:|¹©| ‡ÉϪRÒüœ:Jh-I£(#&-øü—šš]ÎÝ;ÞD·q»%oC%zYl#¬q»7ïŒKGäËCQWÃ6ë†n´`6ƒ¶£•m<ÇÒ˜y`÷øM°›šÚJ3’™aõ·aÛ»Û íÚÏcëë[p5Qóý=úGÇÕ\¡GQªÊ«Tž.<1\EWªi,Õ”–ÊSÅyù–Nš3®¬.Õ™6®ñÌqmµ—bÒ/ÕžB®Õ LO/Ú<­Rz%0˜æo6&“s˜–¯[ß(£Ô~ˆp‡ùdþHÊŒ’ö³X“É¿¶Ëf{¢Å`Òµ«]HÛÕ¦?dæ.­môÊ¥>Övì+~êi» ¶Çí9E7D‚ÔÓ_š@€ P$ )Ú¡¶¢18øÉ7ݦۇ Æß4„RÊÃq˜^/O'WÿI0 ¡<üÔ¼Ï}q¿uë××kUHcòWóµ †(]Æ@l ÅnÕkœÄ†D|WÃÌ$}×ÒóÔ›TÎFlÌEð-³o¹)·,㎭l;µ ÖÔ˜šЉãh_6ó”¹NVð¨˜ÆdµgÛ¬’N]Rµý æ’êCÅrÖ…®Û”2ñx“?¡X¹Û”ß*©˜d¿éBu›q3_üÜ—ö‹ÏÉ$\¾fÑqñÒ§¡PšÌd£gÎA1P½Õ˜|¼¾vfѱ­¹Îé"Õ˜b3ÔFBÉn³Ö™ýNXsPÑú†ë]nƒ55¦õ–f£_'WOôg5ˆ~HcòÃáL;„}—+Ç?~R9ÿðwYú'sÈÜËfy³ƒ44'¦ß[L³s'+7®ë¶ìöå¶ýÈl­ÐX±ÚåF•CzVè¬b[Žê€I@Ø/'€Æ®Lï T £И:Š—'G ×“Ë(›\[ßó‰'ž8èº!«^1÷¨FѧGÿð¸ÊGoÕ“ä'¹RÊ«T/»’.z=])7ñË“O/d”Š´ôôÜÕi©<Â2í¹UyfìÔùrV¢ÞRìK£&Ï[Ì5¦²SÅŸ6.”xIóÇ)ëÒˆ‰sg,Úàr/M_¸A¥ôt‘+•ÜK½O¿t×£Sf-Ý6yîË*Á“mV¼ôKÃÇα ~W†™ýÌ’-Ï,.—§o ʢ;½$),0-ìIÂ䦫d` ’0©X²¥LhLžÃô5dô³F=»Á¢¿¨4ŒbÁUg½°Õ쉙ë]*&QI¡ûÙÉçÖœ]Ξtñ0Kamï¸kE´¬—=J¨ut]m_´uì)1½lÂ>µËW½ì"Üå[²+swjû"Së§9¾ @€ ”`°8%H¢hLIPgŸç0é1°Àa*=&‡IC@å„:¥Q”© 7)¹ÆÁlÈkÔ¬ 5ŸÓÔƒO>c2¹¡’hFÐȆ³vܘ‰qßµD#j…콩ђaà˜¸7&cÙtLnpã3ö|šîôÛG6Èãç³±zº4ìFþ0Ž ÙWlâ³he¬ ²lÉróزÛWçòë4lŽ[!d±Œž½Áw˜FÎ\?{ùvJµ¤õê6ÊLoÝæ©ç^µ ^6ª©Á·±3V«ÛĘL_÷ Å+J5nf¡ùí²ïúý-:¸gý*Ê9wÛ‹m\Ñ´=šSRsûÖ ýràüÍêS»›`[ˆ*º¾áïÔÜWƒè-¡èë¤1iÞ¦ž,\Î`{qçäýèŸûj)Û¶æ£ïHF?]Óü@Ô‹ˆñÑËé_¡cÙmÍEÊu wB¨ S4¡ÍEÖV EÁ‚ng½œÓÚ—ë«¡j¸tSwýéêot{·úX9×d·Yǧùƒ5!WhLq‘åÊ4¯ýžv4&zBf „¼£ÐŸ 4&ýGÐ)ív™}æ#CdJÓmÎ=Š. ºö¶£~x\½Jf&…Je28 Ž„]% —œÙÿ’=>ûÿ³ræy—hôäŠëoÿü—¾b%IY÷æ·¾w˜ýyôN0WÉ•£~t‚[ù[ß;´’o©Îlq/½®”K~֥ᣦ}ó»‡ÖP—ê'^úÜö=åì‹5ˆc唳.V)9Lá™ãâ&+Íï™4º¢ûÌ{êªþ¤3.R LºÎ¿óáÉÿúù/;IöÒíMú×}¾lSI` ì¥Ó‚)°—œÀÔiÎ}»´£‡€9L WouI˜Žºd¢•®˜vàÙcî|jµs˜.¹gÞÀ{æ#)+¶ß6zåg9|À„ÃŒ|úzKÅ$Œf}ýô¤Ú&SGÛÂÆ!@€ `°¸@Á7©ÀÁO²éæ0 ½od9åy%•µžÓ(J0)XIGx`ÊKGœ`2ŠF‡Ž¸xÂá¥rí£/„Ÿ[¤pÜÜøœLI¶™}ÇШJ/Y,§žu¡ßm4àæ,–SnœuäÀ‰nðíøË§>úÌË)ÕàÛÙ·Î.¼ƒoe‡©2ø6zz“©‰z•WÑh¾Pü,VÍo¡ˆkö&úÊÂåG_êŒá‹} nã¬1öø¨¢Ü§Zôû];£sÑ/bìh3 Ð4¦8l\™¶Ô©øRf 1e&TT´Š€M¿îÞ2Þ—ïëjL2ÜÍ»7ÉRȺ|¶)™°¼·Ñ–Ætùµ·ÕV‘‚DÓo]~ÍmGþð¸’T[Kò3*•Ó)YR¥êÉà¤+Ùó^Gÿø„›ïxÈt%{ükÏîùܲ×t%ü›ó.QtýPùIæ-ÉX3e¾®‘¬hY++ÝÎâÒëb=]¤k3+z̨\–—Ó&ë©#WjÚKR—zr/IcúÍE*ººsÅÔ¥;žd“K¿$é_öùrmiaU¦)^ú¥) 6E20Õ˜úª1ébXÿõéðoƒ&ur˜*]HýDÒzLÐz‚& ½Y¦“¯Ÿ©kéwϳ0iîîñ/êû–Q˹lŠKÅTÒ˜ÙëL¦ÞžAX€ @hžƒÅͳÊÝšhL¹ iTq˜F¸ÇÀ\6¢HC1‡é·÷Î×àI 1•ÄNº~ÆÅwÏÓ¼`zjî€3Ç”sêT? ¦!”ÆÍÝ;vv¹ *`õä¡îôc+3™Ãê6Ò˜Ìb‘Ãôëf™Å2nΫ’ÞÔyúe ¾Mxþ5=@8máfu›3oyö÷úÁ7=@¨±Ê'žY¥n?»\“aqO“{¦IbÁs§­F_g _|´èß>nÕƒèÛã£×=¾ôØ?N-¥bÚzØ€ñM_ß¹è7ÛdÖƒŠM).þ\™ûèÈë;|«:ÿialfa§1¹ŒÂª‹›^¹®Æ¤/ÛôÆÑ †õü‡¥ ÍÜKÓ¯Öœ‡´þM}zäŽ3 )¦ôhIÎO*[J¨dÅ™I7Ýñt¥»§w4=œ\%³”ݳ¬?g/}mŸ/}eÊs+u…leÊœ•Ò˜î>Ö¤¥g_xÕ’-ý´ßéû|ñ+*Gþð]G)åÒ‘?<~÷ÜSÿîóÅ}-÷ÒÐÆøÝC9íÀï*ÁåWùÜ÷=ð;‡¨h˜æþS¥+iYÿ1ÕŸ3Î4¦À[*©Kr˜iÅö½¿°ï7¾}ˆŠvôÈSsä-ðíCTôþÞŸßW×lZ¾åžQÁÅÛ²mzç¡qs.¹bðÞŸÿò׿u°’0 ¼b°’ëjAêÒ¯~s‘Šô‘ŠÔ%³—nxÒgöø/J¿¤²ÿ7–½4ô¡‰Æ´hóE¼E zSÿ6ž?NÓü L JI`*ÍW³´0©Üö§†þû{WÂV†Ø¡!p˜”LkÕÖ’÷¦›UPÒš*ÎFßî|jÕñƒ¦)Äcç¼rÈer˜‚Ñ·RFëÙ¥XèZZÃ(¿¼fºä0—ŠÉL/‘9þWçÔœ]®C-b³€ @€@0X\ `‡›ŠÆTàà'Ótç0U#ìEÑóE)eÓy]#f—Ü;ÿþÉ/IF±Ñ0{L£(N]«„:Êîæ³tà ¡lÒÒÞ_ØoÝúõÉ´½¶@ÀD+ud¦Àa:óÂÊäƒ=ÝFSÈaÒàÛíãV›´Fçá§×z³nS·Q>ž«^RJ'ßÓm489rÚJu›¶˜L-(ôWúý'<ñÑO?fö+Ò˜ÜIæ“ÓùAÓ˜Ùˆ~¡û‡@  1Å+ÓtQªÐA¼UÝÁj³ébÐ|ÁÊ©ägc2Ê©$=Éf—k0©\Hc²Mze¬4¦Ë®\WBZ÷¦>•Æä†<äŽ8-É™I¡yߢºtJZ‡ô³_ýæ7ç^"{éòë†J]’«d –õ´T$3–.¿v¨Ö”ŸJ³tÃеÎÿ¸§æ†»ìÚ¡ºpºìÚ!ò“ÌU’·tÁo¯zà‰iR‹f,~E—ÓÒ˜FN|^ Güàø¡÷¾äTÙKãg.× Ón&‰;ûâko{@®Òa£5XóäŒà£ž ãVn×Gæ-YÊ%Ó˜ôPšV»ç±)Ö9öÄÓN>sÀ­÷ŒÒ‚å^’´t÷£Sn¾gÔß:DÒÌè§_½¤ øC>nÔ´d/Ùlqò5¦ïù“Ÿj¹—ä-)ñ’Š4&˽tðQÇžyá !Óã“—|zÿò䬗4rtÑe·|í›Û#MºJt%’~©±ÀÔB6& Ló¦NjLæ0Í_¹Õu0ëWê-zS9aÐ4 LºxÖè›kÙè[YcZ ÀÙó@Êä§ {f]p-]€ ¸iÎ`2eôlFµ!@€ v §=B¬Sá²és˜†Ü;Âݹ¡9Ke=²¤1©¬KÙ¬{æe™(¾Ãô«ëfhðäêG_Í e“= ¦!L¦Œõ>_d©%3Éa:åÌ Ý£ƒ6‹œ ¾Ic:å†Yž5æÊ[·qƒo¦1¹GÌX/‹EEƒœ=.ìé6˜LÉt›>DßÎ&>†¢¯‘XÿñÑk}A§Ž3n~–è'eö xИâºW¦,ù&€Æ”ïøæºu!Iy”ôŽ2ÑZ£{§1Ùw4£\FØÓÕƒc<$}zÄŽ ­àkI —KŠRy8—WI £§Ì“¨ô`I]2W©¼\J°¤¢K#eWºàwWk¡<7\)c­ÊÄgW\vÍ)J§3PEF‘–U´ dKJ¹¤e›$îüß^uü/NS¾%}$¯E™–,ß’þ}~e ¹XѧzÇÊn»íöèSϹ ã”]ɼ%]ËXRÑÂgþqOe÷‘#cIïhA¹—N:s€Ô%ÉIw=2YÆŒd/óóSÏp…ì% ýœ5àŠŸüüT—oI–’.ê,“¬šîÙïô‹”cI–ÒЇ&)÷’ì%Sm®¿s¤Þ7iÈð‰ZA V>½û黽ä235™é¹›Ï©!0ÙÈùŸüøúÛ[9á¿ó»‡Ì[¹¥gÜ­4†b=GÒ#f®³ éG,«LÊL¨TLß5Ï9L…;ž\uÀ™£COƒÙ&S®Oþ4€ @‰`°8QüÉî)Yþ…Ú»9L·Ýû¸sP Å¢”Ü4Š¢Yä4ŠŒž­ÚñhIcr)Ul¼ëÉç^)=V53ÔÔÒCtîI°“ià~íbk! Ÿ!—É_(ef*9LÔë6˜~}ÃLu »=>}MA¨o+·.iÚZë6åY_ØúûûüäSüƒ<ñ•‘·²Étî¾if»‡%sRÉ>DD 1Mˆ:LŠ~ 1yÚЫ²à_zß?ÑÏI/*ÚÁ%ùW–  1ÅE+Ó,÷mêÞ˜ScF¬‘RÑlLª¨æ…“Œ¤…^hLn"9M3—Ñ„LÒ˜þpõàIŸñýc+*REHZûº’'ùNRÍåžDJÝDïS•,¥É³W*©Ò¨Éó¤1•D¥×‡zZ9–FM~þŽƘ®d–’-«üáš!§ž3ОùP1]éÔ³ÿËÓ•fÉʈ sm†8]K[Ñòï¯"™I—Ö÷=|dÿÊq±©â$-Icº÷ñ)®Xâ%S—œ·:n†©KV¼Q”`„M£(K±Q iEc)–ReðèÓn6E u&:3”ÿ$˜|”}ÿy¯%ç~éÃë¿É}ú´¨'²œþ‰;ûÄã¢qàò p¤ÛÈV ,–Õ;¯xpqÏ„+ƒTiLM[kƒoW?RÎà¥Éæ½h¼›…Ðeð²Á·±Ï¾¼ß7þíž_øþußI;´Üx}ˆ¾1ÜЫ3Ø}u {|TY¸îzjµ ½^pûÜ nŽèÓ·³Màì¿ &ßä•ehLhLYî¿Ô½oИúÆo'HÀiLšnúôéVÍ7§—z¡1iC˜ô9Pz%ؤ–w-é÷WÝZÓ7²7õéáß?6fs’übfI­²sÒìR—†šfÀðËÓµ IÓÀÙ;ʱ4ô1zGSÂÍXôŠþpõ“–TÆÏZ!ßHN’ÆYÆÏZ®yâN=ûâ¡ÃFËI²âôNÿK®²dK.ÓÒá?8^ßzlüsòZ$*é#Ù-úWËZ8ìûÇ;ðÊo|ûß]y›¤¥{›¤Y*KV”cIÆ’þÕõØ•·Ü¯å‡žœ£y¾µ ‹s%^:錋T$-iˆGӯ飛î~B—mO”–¿þ­ƒuýfÒÒ„9k5gÜvª¦Ó0ÍWÒ˜.TùñOOўͧôK–ué±IK”²[3Ç]vý·•&=÷¦?0AC§_pù×<(x¢¥\6j,É=ÛÔ¤ºä¯Ö¤Æôàˆñk7½ÓåIåüÎ!s—ovö’ÍÅôœ”„é±é/+ ú á‹ƒIÙKÃ( ¨&Å+H‹uÙ”«^¢@\ù𤈪=Dè?d“ÊÉaRëT0™Z>·ðE@€ @ L©À}©ÀÁO éf2=h¾¬Ù:>Dß4&7”¹ME§ýÎcÛ]ãWK|´Ai»^ñÐb¢ßz°øfHaDcJC úP4¦8x\™ö¡kñÕ @cÊ@¨bmNc’ä$J»J/-Xr¥“t%ÙO¶á±cÇj.9}3£“]^zå­õÅ£×õ©4¦êvº)Þz* “\æ¤z × ~àw•Ÿ$‡É䤑Ÿ×Lpîy«wJNúÜ÷UÑ‚ sEÃ+C†–Ëb³¿röÅ6àréUC¾Qzó”³.Öà‹Œ¥ÃpœeZÒ5ÕàûFþýãl’8%^’·¤kl9LR—TŽ=ñ4Ó•øö!š?Nÿ>üäK³äŠì¥½?¿¯„$å[ºòæavY.9IÿjXçÁ±s4UœŒ%½£rèÑÇ)åÒY 2u风½ñ®‘ºz·¬KÊ®¤¢ÄKúW“šÿ.Ú|Æ…ƒTd/٧ʺôËÓ.<ã‚A÷zV _ûæA•~qÚ…nî}bÖAG+{I“Þ”ÌôoGxKV*™™[°—z;©œiLV$3ýû{ôd¥vb‡Î='NTôŸ[¶Éõ.KÍ¥Ñ=fEÃ(£fm°a…õ²û]6l‘"%«L‰Ðe2vÑx%µ~xÚËÁµ´9LÕÓÉ9‡ “©Cqd³€ @((‹ ø ÙhL~2M/›Lc¦÷ØK•ìæz8pììW4–b“†Ë4ò«ëf¸IÁ¤1IGÐÊMO,ïq˜*ÓÉùó‚9‡É†PÔTL¦dâÝä^}‘¥Z`r¨Œ—í%—ÿøË§º‰äf,ÙrܧÊ~3õMG™xlðíæ'–ÿä²)²Xä0•’ñ„ 9L˜LM†® «õ!úcç¼â†^ƒÑ×ëfXò6EÿØ?Nµ¡rEÿÂ;æêÔ¡èWR1ý6ÄM$F)1ômÛ1SJ®LÛÖÑØP*  1¥2,TªRÜjÊÀ$ I/KŤW©™dh»4qôéaGSs…à:6T*i“\þ$A~R©ì¨*ž¥dõK0°*Û5Ôâ&†3KÉ•ò¬pöTPez8óZB%d,XYfsÉÙ´P× ²Ê£(¡2 åçar£C˜LiïŒ&²Ô˜\å5\ü»+oõ»˜Ì{«ÑmJƒo64|ó ¬é0a2u©Û´;úN|´¡W¢ß¥8²›®@cêêŽí)-W¦ëxl8:|«:m¤…$P8éwW”¯KkºGúTSi°Ã•j)¤%•´’P©+'9i©†¥<æŠK­Ô²®dˆÄJKµ¼¥’´Ôo)¬.U{K–e7F]ªØKåÄK}É·Ô)ÉÎ’™tU\ýzeæØÉýžyY‰k¾æ L¦oüì’ÞÐ[Àd²ZÏè[èBzqÈaêÉhíÏ%çÀa2ò‡€FC€ @ ,îÔ¬l)+‘ÊY=Íd>ú÷è ˜z+¢Øã|u¦p6ëzSÍœL‹ï¤A¡—Æ9ðý׿…ÓõQ΀§½9¯ô§‹©­L¦ß^qK¸ÛD¦Òƒ =Ý&þ‡iÉÂÃÏÿõøþ?ŠVID]%í`3Q¿´F¿¦ÇVï¼!Ò- &g">T2uИR’^W)W¦½îP|!SИ2.*Û<ÂiL¿tKŒf¤O=ú˜ÆR4‹Rm3©ü¼W E©2\HT*?âãò*y©•jfWª§+U§YŠË´Ôš´ ÕHýçO¯®!P]&ÐLôCâcL üøè»§Iýè×;oÈikm0¹ËÙ] 1e?ŠhLq1äÊ4û=œÄ@c¢ä”@á4¦ÊitÖ¶à}zèQÇÔ›ÐÍ·‘™“LK*=¦S³¿UÏWWTª“Z©œƒ§gV¸]©æÜp5Œ¥Êìc5fˆ«ž$®-Þ’•Kç'Œkè0i…¶kLzzæÑ£÷²ìôìÜ(•–í}{OÅ liý©4NõÎ3£Æ<)“iú¢×\"kKÂT~¬z¥êBº¤ŽMRFëy H3Ó–7þòáGá‘”œži @€ Ð w†k&¶ŠÆ”‰0åµ’o¼ùæ~_;àþ‘O—GáJy¬«+¥²ž±¤4—œ=¤WžK®‡IRÂ;ïþM0ÿöî.¹J² êqi™ì™·è`‘††lŒy%ñù“ã~:ðò›ktKÂäw›ª)]·)'A·X$0Ývìwd2mÚü†‹¾ËÀ¤þ#Ñ÷ÝXbâ”òZ¦¢_cÊÞEß9LÛÞ|ÏH†Îõ“Cï»3LÌ`r^#E»:E©Sd»·]4¦8Ö\™v¯'²§$ 1%A}v@á4&]ŽÆhFúTS¼ŠT#a’Ÿ<)b&INŠó“4’k)Å»J½Ð•‚š`Êöhy&b,5#-M‹ÌÍ·ÔÐ[êNÊ¥Ÿ©í“®*mdJCWÊú«[Ùs3.K“-è}-ØûZÖ;ZˆI-“éëß:ø™…¯–‡ÞJc(îI ˜Ñ·Ò }8L]8² @€ @À#À`q»SƒŸŠ¦›Ét߈iö XÍÇÀœÃ4mÑæ©¥1®ò09‡Éš­ IHrC=zǬ&ÓS4jdƒEúWE¶ŠÖ”ˆ bcD¼’% —åâËoîñÞ*“KÂT_}+?@Ø0Ï‚gçIcZ=¾‹¾úƒº‡º ÚP¡õ ½¯Õ¬{øcŒÉRÊëÞ»}Ó˜œÃ:oÔL7šLÎk¤hWG 1ukW7ŠÆ‡›+Ó®vFvÖuhL]GλC ˆ“yE5‹4¦CŽ<&ôQpíÚZ) ”4,ABªŒJUI•¢R)ïŽ+ÁÓcÑRzž¬÷ÆRðð™+Ä©*½•–”u©V¾¥Ä½¥ÒÔvÉ¥\²gì4ab“±Ò;ƒ°ge´Ž]ˆÚÑ®7-]S½—™LÓ¼Zî•Ð[¬M>³¨y£oäaêι”½@€ @Õ,.p@c*pðÓÒt3™î}|Ú¬¥åT:å$å–„ÉFQ*C(Áƒy½ŸK.ä0©å.å’ ÙCn–iɆ†ì‘6K¼¤5"äÒ5iMû¯d .ËoŽë6‹Ë#o¾úfž &õiLž|˜Ú¨4<–¦Ýì%³”Ô ôŽËée]ÅŸiÝ­£Ý£ýj}­üìhyè5ýf ¶šSô¼L7z5˜ÜQ\l¸ÆºR­‰áJ‰|4‚“Gi)ªIµ]c2WIn|ÊÄ&˺ä†ì<ÿÁ;-ëI¬†§™Lûó Éó6ØÐ[)âe­»Êè›Ë}uü¯Î9ãÜñ£o[ÞøË‡}Ôpï¬@€ @ ) 7…)Ÿ+¡1å3®l•™Lw?:­Îc`ÁDrír˜Ül6#˜hiÇ ™âr[öýkùx´¦û(ƒ˜sXåÀeùÃMUݦÎà› 66é0Ébq®’ú† jÌÐÍ%g“%a²¹äBFÆçqÏa$’hRç¢m‹o½Áäèy£…Áä$(²Ï¬@cÊZÄ¢õEcŠ‹!W¦Ùïá´ Žý#§ §1ÓD UÞѧҘzVˆ¸Gþ„n¶\{Z·zï/iEÉÍd·®c)…E¥F©•‚LK5²+Y²¥º’¥Ñî)¥¹áj¤YR¾¥tgZj&·S‡4&h0Kɼӈ•eZ’ÆdZÙ¨–†*´‚%mj~ÄÊL¦IÏo°ÄZ6‹œ{Ì‚Pp˜rzö¦Y€ @H7‹ÓŸŽÖ©£xÙx¯˜Étç#SŸ®Ì"g£(öüž†¿,§¸ "µœ‡IUr°iÈF~lPH¹LKúÓžj3=Åì_7»\¯ZÇÊ# —å‚ßßtO`ª9øÖ¼ÃdÁÜ5-Xg°ä:zÇz‹ëê?ö¤j™”] whËŠ~´þî¼3˜:o´6˜Ü5tì(«И²¹žz£1ÅÅ+Óì÷pZG‰þ‘SEÔ˜bÄ#iLñ“+”ô£øyÜœTo¡l&Õ—“*™utyìÊæÐp5ç€3Q©«É®TOWÊ«±TÓjj»ÆdÏKé¥ÙK¶àþµô¾ŠYè¥ý龨ä©F&Ó×:L©Ì:.ǶüØû×ràmøÈ# ™i¥\–óc¥ÛTåîrÏvöÊaŠvØ04¨èº•vÙ¯h'¢¥âŸ7&»¯·6˜œý˜Ð‚N@cê$Ýîl)Ž3W¦Ýé…ì%)hLI‘g¿&P8éÂ?ÜãéSiLá”H–©‘~dR´xNRœœT×O*åÚ‰µ”‚4<õò*9»¥8 –šIÂäÖi»ÆÔá¶jóf2=5g]ÙHó´’‡©›á`_€ @€@‹ Ü!И ü”6ÝL¦Ûž\ï1°¾äaJi›©V;.Ë¥7Ôë6½u˜ÚQ#¶Ñ=¥èßHô»Gœ=%H)AømÚ5SH®LÛÔÍØLJ  1¥40T«¯ §1U²ûz–õé¿ñ“ZâQ@¸§, fòŠ/{ÔL‰Ë¢d3…U¦~«•NÉ®£Ây•”»2\íÔJ¹˜®WºR½•3­1éè—ÉôÕzrö:å?Íñ‡ÃÔ׳#߇ @€úB€Áâ¾ÐËøwј2À|VßL¦!Mög‘ëû\rù„E«<rYλô†h·Áa*B7±è—ØËSOÚIƒè!úÅj#SöãÆ„Æ”ý^L Z%€ÆÔ*9¾—r…Ó˜,p½¢Oÿíð7¥yI’êÏææ<¤èB%’ä¤^ùIR”ª-¥º¢®Réª2¾d]c*›Lßø7]<û-ÅaJù™—êA€ @ ÿИòãº-Dc*pðSÝt3™n>ÉB!Sªc–ŽÊÉe9÷·7øÝ‹%‘éF-ˆ~7(³Ä  1%‚>W)!W¦}î`l ÕИR*×:âiL—ÞXIqTÃ1RžØïþãú+îQyú6ÓIH.[’¿P5¿›iI®xY”ü裮ՊA€ @%€ÆTÐÀÍFc*pð³Ñt™Lû|ùÿùç/}vÜäÙñ£(ï¼û·l4‰Zv…À?ú®Æï~à±øn³íÍ÷ºRvÒUGþè ¢ßUâ쬛ИºI»3ûBcŠãÊ•igz[M 4¦´D‚z´™@±4¦­[·N¯~IOñË}¾í®Coòg¾ Ü8äÞ† M¤ScÒ¹aài«^ýSÌH S›Ï l€ @¨G€Áâ÷ 4¦?3Mdþ×Þÿ¯8L™ X:*ª›ÄýïùOK7¼Ósp˜Ò«öׂ跟)[L4¦ôÄ¢Õš 1Å‘ãÊ´Õ~Å÷²A)q¢–½&P,)Š'~´‚O!P“@:5¦—7ïúÞ…Óyú•zQÃaêõ ’/@€ @-`°¸etÙÿ"Söc˜ÿ<¹æÀ‡–ï¹iç_ꢇ)ÿ ÷-´›Ä붯­×mp˜z53ß ú™ mS ÐRö4¦¸€peš²îJuÚL©Í@Ù\Z 1õ̆²& ¤ScúýË¥1ýäò9¯¿ý>sÉ¥åK= @€ PX 6ôL*WàÐg¨éÒ˜^þÙ?ú¨¦É„Ô¡Pv³ªî&±t¥èàS7cÑý}ýî3gÝ#€ÆÔ=ÖÚS§úÛM?4¦ôLj¶D ½&BÉR1YõìF ·ùƒ)äajéôÈ— @€ >@c꼬•lLY`¡ê5™p˜ ÕZnlÈdÂaj™d¿Hô³5êG)ûý )û½˜´J©Ur|/åИz­°4™°‡ÕrL …“¥b²¢„Lý÷ɄÔò³0Õƒ @€@>  1å3®Mµ ©)L¬Ô-c_»æõ51{óM&¦n…%íû4kPÃ*:—‡©!«Ì­ÒPsˆ~æbJ…ã 1e¿ 1ÅÅ+Óì÷pZG‰þ‘SEטä£ÄÛ6ó_ܹbýŸrläдeëßZ´æõx,¯íx7U'?“KȤjèmóÎw5—ªÚR@€ @ ,.D˜k7©ÀÁOcÓ÷ºe¯†ÕÒà‰F{p˜‚*È ·,ÜÿÞý›i¬\¦f@ek£=zú†é ëLô"b…Ì@cÊL¨êV).†\™f¿‡Ó‚8hLôœ(ºÆ”Ó°Ò¬bðS1ù ™ŠEÖB€ @©"À`qªÂÑÝÊ 1u—7{‹# AS¿±ý”[¥ÿ”þZ°b©V¶ìÚ¢e-èO­©¢uZpê r˜Ôm†/>xþ`u -ë_#£ü^zÓ¬ÛèÓ‚CËSó\EßNZ–ϤÔ\ú׉M}½w}äþÌÚR8hLÙ9S\ ¹2Í~§qИè9%€Æ”ÓÀҬˆ¦bò2 … @€RF€Á┤›ÕAcê&möO@žÓä¦HDØõ×].?“þ4I)ô'J JÝ@Š’8˜¥$ÝÍÜ&#£¥N¢Î£wÔT´ uà––‹Kÿ*¦&Aª3è_§1Ù Ä´H­¦›™‚0phEn  1e?´hLq1äÊ4û=œÄ@c¢ä”SNK³ C šŠ‰„L… > … @€@Š 0XœâàtºjhL&Ìö›'à´$—2Gj‚ï£XºÓT,½JóÛgÍ\pZ’„󓜧e}jé»Ôs¬ÛXÿÉ%Š6Jº’eÞòSp¹.a’“‘Çæ2uMÎ 4¦ì).†\™f¿‡Ó‚8hLôœ@cÊi`iV1¼ùÎ_Ï¿c‰•SoZðoNïwÝ<÷΂ß(Z @€ ¤ƒÅé‹I×j„ÆÔ5Ôì¨!3N´šS—¤&X&{Ó¤%V‘½¤¢—s¥áÆY!¯,ÝŽ¯ªøiºìSýk}ƺ\–¼Ò(Z»,¦jµ¥Ý²æ»nö©M¶ž44¦¤#Àþ;D©C`Ù,ºM©ÛÄÙ @€ C€Áâw4¦Ÿ¦C€ 5hLY‹X´¾hLq1äÊ4û=œÄ@c¢ä”SNK³ŠG©x1§Å€ @H1‹SœNW ©Ó„Ù> @h4¦¶¡LlChLqè¹2M¬c²ã®@cê fvÒ}hLÝgÎ!ÐhLÁÊF!@€ Ö0XÜ·\| )aÌy#^wÉö?ÏÍy#i^» ¼óþ†ÍïLÿàÃ÷Ú½a¶—D?A¢Š-@cj]j¾ˆÆ ®LSÓQ©HG 1u+MžSò1 h 4¦¶`d#€ @€@{0XÜŽ™Ü S&ÃV°J?¹æÀ‡—¶`¦¹}%ÀMâ¾Ìò÷‰~–£GÝ@cjD(ýŸsŽŠ‹W¦éïÁÔ°/ИúB輦SŠƒCÕ ÐhL½¡Åº€ @€@‡ 0XÜaÀiÞ<Sš£CÝŒ=¡Ü$nZn¾BôsJRƒSö»稸rešýN â 1Ñ?rJ)§¥YÅ#€ÆT¼˜Ób@€ ¤˜ƒÅ)N§«†ÆÔiÂl¿ïИúΰ€[à&qƒîšLô‹ýü·)û1æC®L³ßÃiA4&úGN  1å4°4«xИŠsZ @€ `°8ÅÁétÕИ:M˜í÷Sßp Ü$.`Ð]“‰~‘£Ÿÿ¶£1e?Æœ£âbÈ•iö{8-ˆ#€ÆDÿÈ)4¦œ–fSñbN‹!@€ b §88®S§ ³ý¾@cê;Ãn›Ä ºk2Ñ/rôóßv4¦ìǘsT\ ¹2Í~§qИè9%€Æ”ÓÀÒ¬â@c*^Ìi1 @€RL€Áâ§ÓUCcê4a¶ßwhL}gXÀ-p“¸€AwM&úEŽ~þÛŽÆ”ýsŽŠ‹á]Ç|üøÙÙ2-€@hLtœ@cÊi`iVñ 1/æ´€ @)&€Æ”âàtºjhL&ÌöûN©ï ¸n0è®ÉD¿ÈÑÏÛј²cÎQÙ!-€@«ИZ%Ç÷RN)å¢zh–S³¤X€ @è4¦.@Në.ИÒêÕC‰ÞÐn·-7_!ú¹ % ©A)ûÝ‚sÔÜ›úí·ÿäþG‡‚ùîÎ-z?û¦¨O‰Þ‘ShL9 ,Í*9+v~ïÂéú·xM§Å€ @€@ú 1¥/&]«S×P³£–  1µŒ®È_ä&1Ñ篊 ¶ç–SöCË/”\¥¿½»+É—ÆŸyY¿ìG˜@ >4&zGN  1å4°4«x&/Ü*I9™Š×tZ @€ ¤SúbÒµ¡1u 5;j™SËèŠüEn}4¦"÷<·)ûÑ-ø/”’0ÝñÅÝ,Óâ{iAå•™cõ§²4­xlpôý?½ºÆVÓ Ù?-(64¦bÇ?Ç­GcÊqpiZ± 1+Þ´€ @)'€Æ”òu²zhL¤Ë¶ÛC©= ¶•‚ß$.X´ÃÍ%úï9o>Sö\ðs”Œ%ç0Yî%efzôè½´ ,M;W-”´dSËiÙ_ïh}elÊ~ &€ÆTààç»éhLùŽ/­+4¦›¦B€ @ ýИÒ£ŽÕ©chÙpÛ 1µ e‘6Tð›ÄE u¹­o½·zó;Ó­Lßðsýº­}ó÷Î_?x«€Lhr>  1e?®ÿ…R&…Qö’D%iIúÓt%û÷Ý[´ ÄKZПÊÏ${Ikº•³ßhA  18øùn:S¾ãKë D©@Á¦©€ @H?4¦ôǨc5DcêZ6Ü6hLmCY¤ ü&q‘B]n놷Fë­f¾ô“|ø^™Ðä|@cÊ~\ þ e)—F-ÈUÚ¼pºL&-»$Las›”ºÉV3ùÉÖÏ~ &€ÆTààç»éhLùŽ/­+4¦›¦B€ @ ýИÒ£ŽÕ©chÙpÛ 1µ e‘6Tð›ÄE uO[G®Ú§¦Æ´lÛÅB«óI)ûq-ø/”¥\’Éd3Çé¥dKR”$3ÉRÒŸZA‰š´`ö’ý«?õ¦¾bñ‚@V  1e5rÔ»4&ºrB)'¤€ @È4¦|ı¥V 1µ„/u•SWqçeg¿Iœ—0ö®52‘Š©wY;ýИÒ£F5,ò/”æ‰sö’&÷?ZÅ4&ý+“Iðä-ÙG–¢É¾bÚ ¼ ahLU#€ÆDÿ€@N 1å$4€ @ù €Æ”8¶Ô 4¦–°ñ¥®@cê*î¼ì¬È7‰óÃVÚMÈD*¦V8ò4@cJstš«¿PÍqb-ä‘S£J›D‰nœ@cÊI i @€òA)ql©hL-aãK]%€ÆÔUÜyÙ7‰óÉÞµ#”‰TL½ÃÇÚ™ €Æ”‰0ÅV’_¨ìÇ@ UhL­’ã{)'€Æ”òQ=4K©YR¬@€ tS §uhLi õê!€ÆDoh7‰[€–¯ø ™HÅ”˜ÒŠ*hLÙïüBe?†´­@cj•ßK94¦”ˆêA YhLÍ’b=@€ @  Иº9­»@cJkd¨W4&zC ¸IÜ´||Å%d"S>J+ÂИ²ß'ø…Š‹á´›>~nXöƒL P‡]#§ИrXšU<hLÅ‹9-† @€@Š  1¥88®S§ ³ý¾@cê;Ãn›Ä ºk²%d"S‘û@žÛŽÆ”ýèò C®L³ßÃiA4&úGN  1å4°4«xИŠsZ @€ `°8ÅÁétÕИ:M˜í÷Sßp Ü$.`Ð]“•‰TLEî9o;SöÌ/T\ ¹2Í~§qИè9%€Æ”ÓÀÒ¬â@c*^Ìi1 @€RL€Áâ§ÓUCcê4a¶ßwhL}gXÀ-p“¸€AwMÞ°aÃiçü¸Èh{ž  1e?ºüBÅÄpâq»O½«!Fcê*nvÖ=hLÝcÍž ÐQhLÅËÆ!@€ Þ@cê¯\­Æ”«pæ´1hL9 lg›ÅMâÎòMëÖKÓþf,Y²öß_u+&SZE½ú@©ðRòU~¡jBêÒ·¾{輕[æ­Øràw0™Âô·ûîÿ¸iç»~Ù¸ã]+¯•Ê~_ýºì¥W·ÿùÕm~¥T6¨lÝ¥²^eKPÖå—7—ËÚM屮´éí—6¾½ÆÊko¿”?­~µ\V½ú§U¯üiå+o©¬ØP.Ë׿µ|ý›ËTÖe©ÊËo¾ðò*ú ¶²xíë‹_z}‘•5¯/ ÊÎ/e¾Êê Ì[½cުϗÊÜ•V¶?·"(sT–oŸ”m*Ï. Ê,•¥[gZyaëŒR™¾d‹•gåi•E›|òùO~j÷i 7O-•) 7MY°i²•ù›&eãÞ_Ø)%'Fª‘uhLY õ‡@™]€ @H4¦£ÛUAcê6qö×{hL½gÆ7>æ&q;nñþ¯ì?qæ vU7M/½“©€!ïMFcÊ~„ù…ŠÆÐ¦ù+·–Ü—7æ.ߌÉ¢¤ß¸ÏìþÎ[òí¥×¶ÿYEöÒW¤1šhSà0•&ç0•¦]ëœÀ´9˜œÃTÖ˜*“Ó˜|‡ieµÃhLÎa 4¦Àar“â(‡©¬1•¦×–&§1Í«¡1mhL=S¼ÆôL-ɦ©%‡©¬1Í7i#SöϦ´ EИR ª¾@cê =¾ @€ ´™S›fishLYŠVQëŠÆTÔÈ÷©ÝÜ$î¾ ~Ù¦I3_PB§1)ñ&SƒI•c  1e¿ƒð Šaà0}ïЫ¶Êƒ 4¦Ræžç–mú9™x̸ñM‘õVr§G;7ÿ²“ª‘š9£ê§!ôÑü¾zµ¦iL~¦%7g\Ù[ÚºKÓÃ#'¬·Éã‚òŽ›Bî劽žEΘBÉ­zåO+_y+(ѹ䪦ª¹äJÓF¦f¦“Û™Nnûìå¡TL[g-Ý:S¥’Šiú’-VB©˜LcúûOíQÎ¥b2éÁãmr=+¯íx·WqéõÊ'ïöñ°{ý-¾Ô@cJ}ˆ¨ š#€ÆÔ'Ö‚ @€ºB©+˜Ó¹4¦tÆ…ZùИè-à&q вøç0³ÛÔ¹ >oÕŽçWí8èæÞšLº3m:ÎÑGÝ¿ÿ^¸Þßk¯½|{¦_¿~z§!C[G+K{Ò‚þÔ¦´¬wâ¿ë*ãVÓMz}]ÓGúúþûï¯T¥¾;=joÆį`ÍŒVF•\¸paÍïÖû(Æ;v¬¾e&“5¿/4¦ì‡™_(‹¡9L‹^ÜVSB5Ig{m2I-²³«^:¡5<Áº>¥³–Ö׿vFªwFÕûv*ÓXײþm~/­uá’Æ´Çú­»zÊ–]2–¬˜·´o 1÷Õ¥°½´éí—6e•×Þ~1(rÓêWÿT"¹`.9K¿¶^¦f¦Š¦¹Å ë¼ ì°_ç 41ܳË4—\d:¹*ÓÉùÓ¢Ír˜iœiL›4—\y:¹›&ÓÉ3ÊÉaª©1É k-@Í~ ©YR¬—1hL Õ…@=hLô @€ @ EИRŒnW©ÛÄÙ_ï  1õžßø˜›ÄE躧ûeÍ%÷ìÒåëߪw\7Ju‹tîÊÏ­Ø>ðòÞ™Lv \îgû©˜ÄÖ7‡ µÖñ5&ÝÕö})GúÓÄ#­l“ÞÑŸ¶š½c ¶¦‹ m*ª1éÝAw«©ú®Ò‡Xž'· ·eÛc´Vþ ¶5·N´2~UýeÛ²Û”5ÓUƶi$£Sè#cåVy5Ó%¾ò?’4àܲA*oÇSö#Ê/”b覲„ZÉ¥·(˜4˜QÎré•NàÛg,zíëßêEN&‚ü³¨ÎîOÿâΓvÂÑyFg;áØ)Å?‰ÙùÐzŸÖ±_úlÆdíKç5)H°ä—ÍUù–öÝïë¿ÖK¼äç^ªm/½ö'©Ke{IS$ÓŠ ²—)ê0)ý¡e`²¢TˆA6D+ANÄòì®1“~ Ke»~¦UæXY^•‡©ÊaŠOÅTq˜œÆ4Åט*Ó¤’ÄÆÔ—Éw!"€ÆD—€@N 1å$4€ @ù €Æ”8¶Ô 4¦–°ñ¥®@cê*î¼ìŒ›Äy‰dÝv˜Ã4åÙ¥¥;¬õS1Uî‚붨榹ø½0™ÌRÖ KzäO!g¹[ã’i´‚S”ô¾yNv‡[ŸZ^ýiëØ rK餵lÉ„,Ÿ‡mÙî—[Û¸Þ÷qØfu+Ý¿[ïl'}¤ïÚ.”µÈvjwèm_ú¢ÕS«…$-«¤5Á*c[°—ÞtëÛ²¿/·«³­` «BSè#K°ä[bú¢j¨Æše…²ž(4!k!Ïý)ûÑåÊs˜"ªÓ˜”°Ç$Ô•×òÌÂW›4™ìäí&þ9ÄNÎZÍΓv"ÒyFÚ Ç¥í$柜uÒ³}þ‚}¥£}Ó4&eWòKÈX’Ƥ)Ò^RÊ¥JÖ¥u)”{©b/¹ôK½˜–F&ßa* LÕÓêy˜Úì0-ÞütEcÒ\r–©'“s˜*©˜Ð˜:ÚcÙxÑ 1-â´7oÞzë­ûî»ï˜cŽùæ!Ç|÷ÌßüîaZ~ä‘GÞ{ï½¼5•ö@€ @"€Æ”¡`µ»ªhLí&ÊöÚO©ýL °Enç;Èe‡i¶ç0U2yy *é‚™k¼»àÒ˜”ÑaÀe759»œS‚¢™~ì#ÝÆ¶ÜlR!swt{ÛI?v;ܽc¶Ý;7›Çþ4I·Ø]2³y즻…Ò<¡PXmãú–“œ|Én±«†&c9õGËVËDâjå6î*i­óó‘èOW+Û»>uÓØù{ךö§>uY£B$£©á¡”Næ{X_Ÿr:”å¸ ™XyîÿhLÙnÁ¡œÃ'¡ö¤b ré¹y–m›¶@&ÓAcÆï¦%E׉žœ£éNk¡Ó¾ý韜uÞ³‰,}#S'®¨£Ùö~ª¾Oヌ²+•,™«Tm,í»ßþÃ_ž0®ä-ùÓÆù3ÇÕ°—^yk冷+õ209É%aZ\; Óë «'’+Í%çM$WúuV¦¶åaªv˜JÓÜ¿ÿ‡@cš\šK®4ÜF7Ù˜ÚÞEÙ`Á  1¼ÐülÐÎ>ùÉOîVëõ_ÿë;wn¶›Gí!@€ ì@cÊnìú\s4¦>#d'€ÆÔqÄyÜAÁoç1¤=mª‘‡É9Lkß虨tÇÔ&$rwÁg-Û6séÖ‹š3™B÷³åÜèž·^&Ù½m»Yn‰=Ìþñç²Õ|wÇ¥‰jLzG#Çæ$ÙËeiÒfÍæñëàGÙHå ‰Dî‹î}÷-G¡ð¾\¥eÕ94ñœ%ari™´_­£7Mågcòwº÷ýÈ6ë¶æê¯Û¾{9©Kë;*ß=¿Ü:4¦ì‡¹È¿P5¦úªÀ-—^iZ±­Sç½²ÿ7˜LÑlL–²®™“sMÉ?[ï Ê¢ªk':i 1}fEI–’_JÆÒ—÷ÛÿÇÆ¿øÚÛ2–¬¬ö².ù3Çõä^jd/-[÷æR+• Lf‘k<‘Üón"9.¹`"¹Vç’‹8LSn^Ò˜b&²1u¢£²ÍÂ@c*lèix¶ ( Ó‰'žXS`ò߼袋HË”íHS{@€ d”SF׎j£1µƒ"Ûè,4¦ÎòÍéÖ‹|“8§!-7K÷qÿÇWöŸìæ’[Ü[u·Tå0Y*¦ù/–&¯‰¤bÒ]ð™/l±dë…¸±aN¦Ðýl¥ÒÍl½´àdv‘êç’¹,&úøw¸M{ª™)t§ÜöårŠ˜¢ä×!4œU©É2ùwôC½9É ›;å÷+¹ìMÛ”Y¡½‡ª¤,m•Û”¯1ÙGj”s’\5ÌXÒîdkÙwýXr©|wûªÖ¡1e?Ø…ý…jà0¹é䢩˜*ÓŒ¶Nž·!Þd² mþiÁ,OÿT=9›cÚPcÒO§Ð¨‘Ù…^i“ó“¢ 2–4×êý=%]É•U¯þ)(¯Xyk¥+^⥚¹—ØKõ20­Ù¹ ©$LeÃX’qà[­åÛ¬HY ¬µ’¸üjÛw¥L_²ÅÊ3‹ƒòtPªæ’S&9LJÂTÖ˜êäa"S:-»(4¦B…›Ææ‡€fŽkè0Ù §œrJ~šMK @€ ¬@cÊJ¤:PO4¦@e“m&€ÆÔf ÅØ\aoç;¼a‡É˱¤tKµj:¹:©˜t+Ôn^ðû&Sè~¶ÏÖ}$‡ÆI<¦Ý˜ô#ÏFwÍí›!NïØÊz§¦Ædïk­©[ì6›{G·Ø]þ!«‰œË~d[¶ Iõ4&}dÓ'ÙäGúSÛ7s(j)Y%­¶‚›ÎAÐ:ö¦iLZÍ2BÙ›~6¦Ð®})ú‘iLZG»¶zšËeê€qsM°Ê 1åû¨ÏeëŠù å&ÍV¶lý›fɘ„ªYÉ,‘^c µtŸôü†¯—“Ée“S”ªR+Ur,)[á°GŸ\¹á-s•ü"¬TÞ´RC]Z÷æ€ß_ãÔ¥±SçÿæÜKÆL™oª™Ô¥;‡ýãµC-^içÂJú¥Ë®rê9ÿpõ ˆ%{IE¿ÅA©)0•’0ýöÊÁ'Ÿ9à–{F©T’0Õp˜â“0M+ L›§”ò0©h.¹ÆÓ¤ùUœ·ZØû û=8büÚM︲ak‡Óû¼ÛÇÃNléÌÁ— 03ìý—N‰î§1™Jþ)-4”í3áö±{ŒÀÖ­[?ùÉOöJcúìg?ËÔrë&4€ @I@cJ: î)AøìºIhLM‚b5Ÿ@oç»”¦Y/¸º>êÙ G]2ÑËÃôzp üÅ÷O^ó³ÆÓʲä;£‡˜pÑsý»àÒ˜4ïLÿKoh8»\¾ÙÒºŒ@cÊXÀjT·h¿Pr˜¾8L[Ý |Ò¼:{Ÿrã¬ßÝ·à¼!s»§ÉÁ7ÝþÐç¿ô•ÓϽdŸ/~寡J]úæw=ê‡'œ~Î@½3jò<¥Îré—FNz~÷Üó„_ž~êÙøÁñŸû¾e{©ä×ÈÀT™Eî‘§æ|æ÷”ÆtÎÅWªÌZ˜ÎpÅO®‘„©ÎDrÎaR¦ûé3êlõ&²1eñ¡ÎI¯éÏG¬jØ žÎ㬫1It’qï§¿Ó—-©SRád¿o¼±W“­|ë»>üè#B€ @è4¦.NãnИÒêTM‰Ñ¢Ý$nQ†¾bÓ$9L•Én,WĨY޼dbe.¹²ÃtÎm³¸xBIcÚÜ_¤b:ëÖÙ‡ÑsýTLº n Îû&S†ºC᫊Ɣý.P¨_(s˜¬ÚZ>¿LUöÓ+¦]ýð å‰ÉÖ¼~çS«Ž8A)|&/ب¸ÊÅwϳDzr˜ž|îÕÃŒ—Ædó*SIB NàOÎ^÷ÕoüÛ˜qã³ß)Ê-°¾¡•™ôSø©Ïìár)Õ\Ðoå= t1ÏXªš*®Ú[ò猛úÜ*yKÒ˜,ñ’\¥ÑSæÉ^š>y7 RMàÔÿ)5‡)i…@~¡V¯^­ø¼[zNàcF'áÏã T;ë¤ýÈÓÒ˜ýEÓ€»ž/M'÷Ц“Ó üþÉk¤1Ý7i›NΗPÍdÚóŸþùwý/Q(7ï ™úߥ19ž5¤1ÝõสÍjcÉý†Ú/©¼%•I³ƒiã†zZ)—d/)Ù’IKnÎ8-+L÷œö¹/î{àw¹î¶ôo9ýÒÊOβ19{ÉÍ÷orõ-è·XŦ» þµlÛ¬¥Û”{éÎG&«Hc’¦&‡I厇'éÏ obe9iLCšØ3‹\MÉœ6KÂäý¦£1µrzâ;¨OÀiLn:9-è¥9âô¥f³1Y&½†®´LR¢`$Bà“Ÿüd &“ËÆ$iÝæ]ÿþÁG‰TžB€ @E!€ÆT”H×h'SƒŸ™¦£1e&Tiªhn§‰w§ê¢dßÔ½Òå›{î¼–¦³Y䟱N“Ý/%a*%Pâ‡Û8kŒnë^©&›Nî˜Ë¦üäSn·ªç.xé–§s˜n>iß/eÑ}W¿1rÐÇã.¥@ ¥NÿÄǧü¿;uȱݮ(È/Ô¥—^úë3.pù~Lš±Yätê¾ãÉUÎ@6iÍO°>ÊÜ#‡IE¦‹R.Y"=•¯Ÿ9ú‚ÛŸs xl>P_BíwÆÏÇ-¹nΆ? ovË“/~£¦w5ã•W¼ôì§>½GEÉJ%—’¿ éÎácî’g,Ùh¥ì4™læâWN;g  I§ž3P¡Ñ´qf­áÕ;d/)Ùáa£M]ÒÂá?8Þ~sÍ^Òäqƒï$^*EPI˜4sÜÉgP±ÜK¿½bð¡ß?Né—ö.å^²ôKw>-hLø—I ›w¾›ÊÆQ)@€ @ /ИòÉÚÆÔ4¾ÒehL]žÝä&q>‚ß ™LÊú0wÙfwÛU÷\-EÄãÓ×)Ç%÷̨r÷¼Ë‡/2‡I‰8sL)ßÃÖ™/lUš¥v¸àö¹º^/“Gà0í÷õE«6Ú¨ìo¿_¶´1“Îþ;4¦LΫtq~¡d2ü› |oÆNàîì­‰än±LgòÛÆ¬4F'p9LÝù¼L½g, Nà’Z¤1Õ“P•HïŒs¸{jï¾ÿAv{ˆõ ¿H`zç¯Ô¢`R¹OïQ΢TILhé”\ùâ—©ÚU ¼1+?Tôc*iÉ•òlq«wœzöÅGüàxM§O9ûbÙKr•®üÀ}O ¤¥a£-ë’ýìÊaÒ{åmʺ$ué3ÿ¸ç˜§—>üd0CÜ•·Üó=£´pó=OXî%û]Vî%9L.ýR¿ß\¤ÄK ô¿îóå3/4ôÁ‰ÿ²Ï—/»á¾_ž~áÁG;nÖKá)äb&ó™Ð˜²{ Pótp“«^/&•«™u‰TLéŒ4µ*ý/­é²+oô5&-“© †fB€ @ hLÉpOÅ^јR*K‰ÒâÜ$nNæ¾b&Óœ¥›Ü7–ÃcÖ [M`R¹øîy|`‘ÝW⇋‚L=“îŒ*ÓÐq«jN'r˜0™2×CŠUa4¦ìÇ»P¿PºGvÒoÎwú©é2:Ož¿Q'ðã.ŸªøÄç_s“Nàwñ®ñ«}‡IsŠo©˜J xüDz!‡ÉNàÙ5™|É LÖåKÓîÎIªZ¨ÈIÒ˜n`L]]©ÚX*¢4%«Êª ÈU2cÉÊ¥W QÖ¥ó.¹Ê².=9c™Ò,©ø‰—ìgWeì3K%0ðíCôï”ç×ÙÌq›£ÉãTä0É^šøÜËg ¸Â"{ã]#'ÌY«"iI¿Ñ7Ü9RåéÅ›k©K*r˜ñÇ&-ùåi^{Lj&30ù ™Ð˜²²¤é" ôI¡ )“¥bÒ«A6¦t5…Ú@¼uëÖO|â½2™þóþûç–¬ iLï¼û7pB€ @è4¦N‘ÍÀvј2¤ÂW©ð] …ºIÜ  ¬}G&Ó7¾}Èì6¹®•Yäv”ç!ª¤ñæ’[Z•‡I÷GŸ^¼ÅÒxL]Xš‰FsÐTf#ªé0ŘL;W-üÓ«k¢üj¾™5ÌÔ7 И²¥ø:í*0™N?ßM!gŠŒ? ¨eÑ›]š},0P«ó0Im©—H¯¦Ã”i“ÉúFH`²î$é>½»¯(‰”ª‹4¦¡÷ñ³+U¼±Š®T1–LZª*Á$q®”g‹s)—,ë’ÙfN]2ɦ³bö’‚hq J)÷R¹”rkYy¦”dË~ ƒ¢iã\ñç+ýj—§›7…\hF9²1eÿLI 2F)c£º¡C‡öJcºñ¶{CyŒéH€ @€@g  1u–oª·ŽÆ”êðP¹4&:B Šv“¸D™ûJÉd:xÖ’õ¦ð-ðÒ\rµ¦ùÁt3*1SM“irÿ£UæÞÔ?JïÑ£÷ÊR*œIhL™ [U¥ ø %“éW§Ÿ˜ÊfL%‹^y&Ð’ÃT6]Á%ä0õH¨1S=“éèGNy÷ÙüÎt›B.ú2©ìòZ ¥Hù‚4¦a£-µ’K°Ö•d/EŒ%%[2'¸¾·TκԤºäÛKN]ªi/ùSÉ6Êß^*ÉÇ”ÎBŽzK¡wÈÆ”òÞNõrF)g¥9E!pà6i2vä£SQ: í„ @€@RИ’"Ÿ‚ý¢1¥ T¡4&ºH  x“¸J™ûʸ'Çðíƒg.~ÍIˆ,„ \ÖôÝaÒ¨ì«Ûþüï|ä@Õs•”Šil¿ý3Ç“ g’S&ÃVUébþB]pÑ%ýNëè2¡x9 SU½Ê ¼â0•¤–Àb©$Òkè0é¾qÇ»>÷…[¦_cŠéݦ1Õp’¼¤JÒ˜† -K©ZT*ç¾²¹ájK¡dK¡|K5R.ÕʺT/ñ’E3”{©¦½d[N¿„Æ”ý³#-È04¦ ª™€þ{ñ•¯|¥¡ÉtÀßY´jcMéOfR¹"÷ Ú@€ @cê0à4o)ÍÑ¡nF‰žÐbÞ$nTæ¾2f\`2M_ôš»ÉZžÈÆ›¼&šÆ£g.¹¦ó0ivÓο¼ÿ·"åa’ƤõŽ¥e’ºd™™^?|æeýj¾¯ulÍÌ¡¦Â)%€Æ”ÒÀô¢Z…ý…’ÉôËÓú÷(2=ÓU&’³,z–H¯4ŘKÌSJÆSN¤×ŒÃ¤ø‡õH¨k^_³ÿ½û« _:|ЬAý§ô×òàùƒ÷º¥œHOËz_Q´Tú Îêéy™ÆäT¤š _ø_{G©w¼X»D °7‰‹™L_ÿÖÁÏ,xÕ L³J7S5Q9 Sõ-ð¶8Lë\¥Å÷ Ò²¡¶üL’™V<6x窅¦+ýíÝ]R—ÞݹÅÙKúŠV(BthcÇ  1uqÇwPä_¨Àd:µùì˜1Àd'pÏ@õ¦Rnž>:LQ‰¨JȤ)Jr•‚ÿ*lY¨eûTÒÒô Ó%99{IëK~êxohz¦1…æ}ëImUÊPøyiL÷ŽŠJ5]¥èôp=qñ¤¥rŒ*‘Šñ–ü9ã*êRJ_]šV™6Ο9.±•vØKNfbR¹¦;+B  ИڑM@ AúÆ€K.Ûw¿¯ÿ‡ÿøL²—´<ð÷W=·dmŒÃ´nË._O°þì€ @È'4¦|Ƶ©V¡15…‰•%€Æ”(þ¬î¼È7‰³³ÞÔÛL¦ió_q÷¿ëÞ/ÍPãß¿mø$ ÉÖKŠoƒ´¡’Ætã]#k®XJQÉIK=ºR­4KžgVwª¸ZÞ’æÜh¥µtJ}üS>z>­È 4¦¬DŠzB )ï¾ÿÁ†­»¢2“’0½ùÎ_›Ú+A€ @è;4¦¾3ÌìИ2ºU©@Án_S¹IÜ>–Ø’L¦¯xÐSsÖYâ‡ÐÓ>æaÊ@û©b¡ 1e?ÜüBù1”Éôӓέi â0ù Lc %L ý)é†;GÖOªTš}µ"*)–K…e¢’+%±,Tª&‰ë‘–*ù–J?¾ {K!í )û'KZ%hLYŠu…@“$3½ñöûJδå¿háwÿ¦\MM~—Õ @€ ´S fuhLY\‘êÆT¤h·­­Ü$nÊŒl(0™¾qиÙ/û9<ÈÔ‘èQÍÞ@cê ­t®Ë/T(.2™N8éÜhΞãuÎ爟ÕdÓο䆚iLe©ZE2!Iås_ÜOS=9©ÊUª!*™·TÒ•J© ýRž!®Ž´”T¾¥øtMhLé<R«¼@cÊkdi @€ @ 9hLɱO|ÏhL‰‡€ 4$€ÆÔ+D p“¸€½B&Ó~ßø·±Ï¾ìîk’‡©€Ý ÿMFcÊ~Œù…ŠÆP&“¤%ßJÁa Q2)”6)øsaO‘ÆtÝ#kåRr©•6Õ•LZêÑ•ÂÆRO¦¥tJKQ¥ )û'KZ%hLYŠu… @€ dƒS6âÔ‘Z¢1u+m+4¦¶â,ÊÆ¸I\”HW·Ó7™p˜ŠÙòßj4¦ìǘ_¨š1ôM&¦("iLÿ©Ý{$$—6ÉËŸ$éÚÛG„)ÕÍ«ä‰Jš®2+\•®JpŸý(mŸ¢1eÿdI ²D)KÑ¢®€ @€ l@cÊFœ:RK4¦Ž`e£m%€ÆÔVœEÙ7‰‹éH;Ídºñž±ûî÷õE«6ÆÌF¤©ˆÞÿÛ…EóJ)«‘ë©7¿Põbh&SM>Æô»WeK %OZ°ioiLCG˜“*“æËOre£2*õ”yÓf µ¥>hLÙ?YÒ‚,@cÊR´¨+ @€ @ И²§ŽÔ©#XÙh[  1µgQ6ÆMâ¢DºV;o}ð¬=þÛ'æ­XÃTänÛ¶£1e?´üBÅÄð×§žö›s.ˆ9{ë#I¨~ôQö;BïZðÖ[oýÝßýÝn¼ÚJà?ü‡OLž±Ðïo¶îê]`z»öÉ»}<ìÄÞ~‰õ!~hLé5„ @€ dSÖ"ÖÆú¢1µ&›ê4¦Í÷f¹IœïøÆ·NÑ¿íùÿué†ëÝ'S‘»GæÛŽÆ”ù~Ì/TL —m»qÎË·ÆK¨t˜j{çÝ¿Åû^|Ú4¦ìŸbiA2И’áÎ^!@€ @y&€Æ”çè6hSƒŸ™¦£1e&Tiª(7‰Ón×Å¢¿ýõ5ï_â0u;쯽ИÚË3‰­ñ Uú¾7|é'Uv¼õv½8“£‡ÆÔ‚¥Ôð+hLIœÙg 1å!Š´€ @€ .hLéŠGWkƒÆÔUÜì¬%hL-a+ú—¸I\ä°åé ·üþ¯¼õîû„nXâ0¹cä¤íhLÙ$¿Põb¨TLº6QÑÂo¿=ã0ùèИ:I-¬€Æ”ýS,-H†S2ÜÙ+ @€ @ ÏИòÝmCc*pð3Ót4¦Ì„*Må&qš¢‘d]|“ ‡)ÉH°ïv@cjÉä¶Ã/TMö–ŠÉ4&-èOßdÒ ‡)Ä ©K©áWИ’;5²çl@cÊvü¨= @€ @ ИÒ•.Õ ©K ÙM 1õ^q¿ÊMâ‚Ä~øÒá*ñ5“ ‡© ]"ÿÍDcÊ~Œù…ªC—ŠÉ%dÒjf2á0Õ$†ÆÔÐIja4¦ìŸbiA2И’áÎ^!@€ @y&€Æ”çè6hSƒŸ™¦£1e&Tiª(7‰ÓÖeÿ{÷_¸eaÃÈdzÿo4\ hLRƒ*ò ä§bò2iÍ?ýù¯äaªÙ¥þúïJðŠ)¯íxwõkoǯS¨O7lûóÚÍ»â›üúÛïwösòn;±³»`ëH‚SÔÙ' @€ @ ßИòߨ֡18ø™i:SfB•¦Šr“8MÑèT]úí·Ûïw;úÑ£µùLZпƒf <°ír¯[öÒ¿òœÜ§k^_Ó©Ú°]t‡Sw8wr/üBEé†R1ù ™: ¶ ®@cê:rvØhLÝáÌ^ @€ @E"€ÆT¤h‡ÚŠÆTààg¦éhL™ Uš*ÊMâ4E£Su‘“$?I[—¨$cÉÒ2¹üL[vm±OÝ;Ó7L7ç‰2L)ÃÁ+W_¨P £©˜B ™²sZ 4&úBN  1å4°4 € @€ 4¦á'½k4¦¤#Àþ@cj̈5"¸I\„N¡¬Ký§ôWK•Éô² Lz _:\隤.é­`ÅÄ&^È04¦ ¯\u~¡B1¬™Š‰„LÙïé´ 4&úEN  1å4°4 € @€ 4¦á'½k4¦¤#Àþ@cj̈5"¸I\„N!KI®’ZªK–ŠÉågÒ²>•ç$uI úTeì‹cm5^È04¦ ¯\u~¡B1\¹c¨˜X¶äï^öY÷§>Ê~Ài<hLt‡œ@cÊi`i @€ @ AhL ÂOz×hLIG€ý7&€ÆÔ˜kDp“¸ÂÍçr,ÉR²eKÂ$«ÉĦ]ÝesÌ¡1¡cä¼hLÙ0¿P11|xùgõ¿ì™@ 4&ºFN  1å4°4 € @€ 4¦á'½k4¦¤#Àþ@cj̈5"¸I\„N¡‰ä”‡I-U¾%×^½£¢»ç^6l(2Úž[hLÙ-¿P11DcÊ~§±Иè 9%€Æ”ÓÀÒ,@€ @€@‚И„Ÿô®Ñ˜’ŽûoL©1#Öˆà&qa;…¦#~pìøK¾´ï×0™ Û òÜp4¦ìG—_¨˜¢1e¿ƒÓ‚XhLtœ@cÊi`i @€ @ AhL ÂOz×hLIG€ý7&€ÆÔ˜kDp“¸˜BÓ‘?8î…—ßX²ö§¦/þâ—1™ŠÙrÝj4¦ì‡—_¨˜¢1e¿ƒÓ‚XhLtœ@cÊi`i @€ @ AhL ÂOz×hLIG€ý7&€ÆÔ˜kDp“¸€"p˜~xÜÒuošÆ´è¥×Ç=ƒÉTÀŽ÷&£1e?ÂüBÅÄ)ûœÄ@c¢ƒä”SNK³ @€ @ @cJ~Ò»FcJ:ì¿14¦ÆŒX#B€›ÄEëæ0-[÷æÒ—ߔô¸¤1-\óú¸§1™ŠÖòÞ^4¦ìG˜_¨˜¢1e¿ƒÓ‚XhLtœ@cÊi`i @€ @ AhL ÂOz×hLIG€ý7&€ÆÔ˜kDp“¸PBÓQ?¨ôÒ:öÝéÓ§kaÿý÷×.\ÿÝÐî´²¾¢ïê}½úõëçªÚpS}éÚ×àÁƒ}½ÚÕYíÕ¿j~_jRôï¢1e¿ð C4¦ìwpZK‰’ShL9 ,Í‚ @€ $H)AøIï)é°ÿÆИ3bn¤S˜Ã´bÃ[JÅTšQî F¹@cZ½sÞªsWîxbÊÂÏ7m29s(ªÉÂÑË›LHŠî4&SÜŸkÖ¬i©šu;v¬}Q“™LÍl*~_²‹¶lÙRo³¦Ü jr¯4&g/é[Ñ5„À =И²ßø…Љ!Sö;8-ˆ%€ÆDÉ)4¦œ–fA€ @€$€Æ” ü¤wÆ”tØchL±F„7‰‹Ð)ÂS%“?£œR1=_Ò˜ž[±}ääfM&ól”:h·Ýv eZ’Ž# ɽ)ŸI‘Ó˜´lÉ™L÷‘dê}ËÆ¤e}Å” û®éGÒ’lM'Hõïßß¾•~ôŽSˆvíÚeJ“mJ “´Kzä6eÖ«Þ¾¬·¸Úú’–ëH–É5ÜiLnãúº*ã²CùMÓ}ç ©O‡'SŸð¥âËüBÅ„)}”JtŽSçØ²åD  1%ŠŸC€ @€rI)—am®QhLÍqb­$  1%I?³ûæ&qfC×lÅ=‡é­eë{¦“[¼öE/½^žQ®”Š©¤1mŸ³bûìåÛFLZðù/5ž].>“ŸOHZ,"Ó˜œ„$kÇÞ1ßHrÉOöŽþuÙ˜L’¤­fѵ‚ù@æ<… Ø›¶M—„É6¥wlS®’nS6­[t_¡kƒ&fY…ÝË©]6µœÛÕÓv'yKïë_½ô§L,k‘Ÿ)JëÛû¼Z$€ÆÔ"¸}_¨˜` 1¥¨§R•N@cêU¶™hL)U€ @€ äŒSÎÚ›æ 1õ†ë&C)îß+7‰3ÀÕw“7Ü›/ØŒr/½¾h4¦ó_Üé§bš³<Иž]¶íñ‰ó÷id2…4&Y8Òt,Ÿé;rq,e‘Óƒ´ìûF¶šËÒ¤•c4&Khdn“e`ò§l³XüœF’ä9[ÈyEN?²/†f‹î+ÊÚ4,—WÉV°Ö™Ÿdº’5Ð)JªŒ 'ý«¯ë¥W· 7^¾ûgg[‡ÆÔY¾ÝØ:¿P1”јºÑÙG‚И„Ï®;I©“tÙ6 @€ @ ˜ИŠ÷R«Ñ˜ üÌ4)3¡JSE¹Iœ¦h´¹.5&:¹ú©˜ä0ÍZºmæÒ­Nh`2…4&óŠLÙqù“,÷’M—f)ˆœ´¤‡4&Ë“¤÷kfcòÕ"-KòÝ#›ÇÍæ‰Ó¿Ê´dùì¥?m›Qɾ£1پܦÔsô¯MŠç¿›ZÎ5Эi–™‰e¬”YÊס˜N® S &¼ ~¡b€Æ”pïd÷&€ÆÔiÂl?!hL g·€ @€ @cÊqp5 ©!>OžSò1È` ¸IœÁ 5Ue.¹åëß\¶Î›NNy˜œÃJÅTšQ®¤1mñÂÖéK¶<<~Þçêçdj8©œêjb“ülL–-ÉOYd­’£1É…r®V³?M0r–’OGÕS*&{Çí½žÆÚTt_nËfeÕ ƒo ITÚm·Ý´k-8Êef² ï¬ÕZÁUµ©³RChL ¥~~¡bB„Æ”úþKûF©oüøvj  1¥64T € @€ YhL™ ]ß+ŽÆÔw†l¡ÓИ:M8—Ûç&q.Ãê9Lo.3‡éåÊ\rkß0‡É¦“›¿zç¼U;æ®TÙ>§Ça R1™ÆôÌâ-=ùü羸ßË/¯²ŠÑ˜l9}Å-˜Í£ù:–0Iÿšd³³Yv¢š“Ûš%|ÒŸ¶)½ÜŸ~’'ûH)ŽL¢²—ÕÇ6e)‘lµÐ¦\­¢ûj¦·ø“yZÚå ²& ˆmGÛw@Bé—ÈÆÔ êë 1µb›à*&hL ÷NvßihL&Ìö"Ð@cÒÝÔÈ–wÔ^~^ЄjÎn!@€ @H+4¦´F¦ õBcêdvÑGhL}X̯s“8q7‡I˜\¦ÑÏnøéÓ–¬}cqÉaZTr˜”¦ã/Ÿú| 1mnÅö_]7ãð‹'>@eücÓ×Ó’-O/Þ2mÑæÇÕ5™20:õ[&ªM%ûD©OøRñe~¡b€ƔŠ>J%:G©slÙr‡ 8?^ûq.»dœq“&Kãi5ÔŸ²—ô§^Ê;Úáj³y@€ @€2K)³¡ë{ÅјúÎ-tšS§ çrûÜ$ÎYXå0ùÃã,“›HnÔ³ŽºdââÒ\rÎaš²`“¦oœ5F©˜ä0)“¦[G¯>å¥&¿äR1=½hóÔ…›§,ÜôÀ¸¹{×ÉÉ”3†4''И²H~¡bbˆÆ”ýN b  1ÑA2H@Þ¼&?§¦ì%%5ÉTWc’±¤L¡.}¨V5õÉ}3ƒ@¨2 @€ @]!€ÆÔÌéÜ S:ãB­|hLô‡p“¸h©ýJà0ýà8³—T^xù %a5kÑ'º¹ä,ÓÉ×ϼaÄ2iLÏU¦“S¦'Ÿ{õ)‡©’Š)Иlš<Óýcçîý…ڳ˥– +.4¦ìÇž_¨˜¢1e¿ƒÓ‚XhLt Pî%M”Ò˜ä6ù&RƒIå|I² ‰ý73ˆ…*C€ @€ ÐahLœæÍ£1¥9:ÔÍ 1ÑZ ÀMâ ¥ó+æ0SÉ^2)˜Hî¥×GÎ\/i¡7—ܼÕ;JsÉíÆ¤{ù¶g—m1cý̶j:¹3n~ö77?ûôâÍÓlF¹R*¦IóÉ™Lc枣ÎC) —ßx$…‡@*¡1e#Nqµä*†Sö;8-ˆ%€ÆDÉ,?“&…³vô/½´Ð i×®]‚¿ÑÌ’¡â€ @€ t†Sg¸fb«hL™SÁ+‰ÆTðÐZó¹IÜ·´}ë ƒºížÇuɳ—$0- 20IcZwäÀ e‡iU9“æ’{nE 1™Ã4kéVéJr˜”‡é¦‘˽h|ÃTIÅd“Ê7¾{ÄqÿÃÐùÿ“~)E# y"mý¿v}И²§¸Zò C)ûœÄ@c¢ƒd–€o9É%TjVc’å20 J! ªÔ9Yú¡Acê\?èÖ–ù…Š!ÆÔ­nÈ~"€Æ”xvÛwNc’}Ô¯_?Û ô§hLÒ•Ü\rJßš‘®ï•c € @€ äSƒÚl“Иš%ÅzÉÈÒÝåä(±çnç¦K˜ÉtËÝ-\³SÅ&ËÀôØô—•uÉ•ãþ8Õ&åa:àÌ1ÊÃ4si0—Ü1—M9lÀøÃ./©j:¹ùå$L!‡ “)7§ù†d釩ù¸¦uM~¡b"ƒÆ”ÖnK½ÚD©M ÙL÷ øÙ˜d%™‰ä|¦S´º[¶lé~Ø# @€ @Y"€Æ”¥hµ¹®hLmÊæ:@ Kw—;Ð|6Ùn·Æ-ß*›Lw=fö’ŠËÀôüªsWî°‰ää0I`š½¬<—œ9L3–ÓÉ=³xËÓ‹6×›NÎÏÃd&S:{Bçj•¥4¦Îõƒnm™_¨ÒhLÝê†ì'!hL g·&Ðk©Óbû€ @€ džSæCØzИZgÇ7»E Kw—»Å„ý4$ÀMↈ²µ‚™L7Ýù¨æ³)äL`š[˜, “&’+Í%WÎÃdsɵæ0Õ3™nY˜-tÔ¶Yú¡Acj&¢é^‡_¨˜ø 1¥»óR»>@cê3B6NhLéŒ µ‚ @€ d™S–£×Ǻ£1õ _ï,Ý]îvÑn7Ç)KkÉd:òÈÀd*ÛKÕ“9L³ÌaR¦‚$Lu¦M“æ•§“«—‡©^N¦5¯¯ÙÿÞý³Dº6G K?4hLÍÅ4Íkñ 4¦4w]êÖhLm€È&ÒH)Q¡N€ @€ l@cÊvüúT{4¦>áãË]!¥»Ë]ÂNš!ÀMâf(enwÿò—ƒ9ü†Û±)ä,S( “s˜ž åaZ¸iò‚M“æ÷ÎaÚòÆ_>üè#µë¯»úOé/iú†éƒçVZ¦A³éMýk+HrÒGZпzÓ½Ÿ9άp–~hИ²ßAù…Љ!Sö;8-ˆ%€ÆDÉ)4¦œ–fA€ @€$€Æ” ü¤wÆ”tØcYº»Ü¸5¬Ñ%Ü$îè®ïÆL¦ë‡>˜\¦K‚8LÖÐ~cûI`’º$™éèGûâØ-»¶¸üLò–ô©ÞÔ;’œ´¬uºNˆ¶B K?4hL­D8]ßá*&hLéê¬Ô¦íИڎ” ¦ƒS:â@- @€ @y"€Æ”§hö²-hL½Æê ÈÒÝåð°ËÚ¸Iœãža&ÓuC¶)äz&"¹Å[$0ùS_ò09˜ò“”rIêÒ^·ì%™Iï+ñ’Ü&[Áì%[ǽ“ã@ä©iYú¡AcÊ~Ïã*&†hLÙïà´ –$§ИrXš@€ @HS‚ð“Þ5SÒ`ÿ déîrãÖ°F—p“¸K Ú™L×yئSQ¦h¦© 7Y¦¶8Lj«ì%ýë«KšfNY— ƒ>•À¤•„É•„±ÛÞÈÒ Sïb›Æµù…Љ S»,uj#4¦6ÂdSi"€Æ”¦hP@€ @€@> 1å#Ž-µ©%l|©«²tw¹«`ØYn羘ÉtÍm—¦òDrA¦r&s˜4‘Üü“æmœX*ß=ìGWß0tí¦wbÊ–7þòáGEZ¦%½o“ÇÙ –I ×ײ?Çœl'­™û@ä£Yú¡AcÊ~Ÿã*&†hLÙïà´ –$§ИrXš@€ @HS‚ð“Þ5SÒ`ÿ déîrãÖ°F—p“¸K Ý™LW ~è™Å[žV©LSn–Àä&˜úè0©¡Ò•”iIr’?mœ².)!“+ZMïhš9½ã¯–('vÞ˜@–~hИÇ3íkð !4¦´w_ê×GhL}È×ÓJ)­‘¡^€ @€ ì@cÊnìú\s4¦>#d'¥»Ë‡Áš%ÀMâfIe|½²Ét냖)˜ü‰äæ—¦¾;LÆI&Ó®¿îÒÌq>6½©wô¾Š[ÍR4ñÊ ,ýР1e¥WÕ¯'¿P11DcÊ~§±Иè 9%€Æ”ÓÀÒ,@€ @€@‚И„Ÿô®Ñ˜’ŽûoL Kw—·†5ºD€›Ä]‚ݘÉtÅ-:É&’sI˜Úå0¥ ­T¡S²ôCƒÆÔ©^нíò é{‘=%B)ìì´óИ:Ϙ=@€ @€ŠF©h÷Ú‹ÆTààg¦éYº»œ¨ù¯(7‰óc¯…f2 ºåA˜&Uf‘kË\r…"YØÆfé‡)ûÝ”_¨˜¢1e¿ƒÓ‚XhLtœ@cÊi`i @€ @ AhL ÂOz×hLIG€ý7&¥»Ë[Ã]"ÀMâ.NÍnÌdºü¦á~&ò0¥&>i¯H–~hИÒÞ›×_¨FhL;kdšS¦ÃGåë@c¢w@€ @€ ÐnhLí&š¡í¡1e(X…­j–î.6Hék87‰Ó“Ž×ÈL¦?z&ÓwûÑÕ7 ]»é˜²å¿|øÑG¯;H7,ýР1¥»/5S;~¡b(¡15Ó…X'ÃИ2<ªG‰þ@€ @€@»  1µ›h†¶‡Æ”¡`¶ªYº»\Ø ¥¯áÜ$N_LºQ#ßdÂaêñ¼ì#K?4hLÙïuüBÅÄ)ûœÄ@c¢ƒä”SNK³ @€ @ @cJ~Ò»FcJ:ì¿1,Ý]nÜÖènw túv˜LßùÖ—ö;#d€ @€ „ 1¸K 18ø™iz–î.gjþ+ÊMâÜÇxñ=ƒ&÷?ú¥ñã-yY?÷¦o2á0å¾W´ÜÀ,ýР1µæÔ|‘_¨˜P 1¥¦ŸR‘Î@cê W¶š84¦ÄC@ @€ @¹#€Æ”»6ß 4¦æY±fR²tw9)Fì7B€›Ä¹ïcûíÿîÎ-Ñfn^8]z“ÿ¾™L8L¹ï}i`–~hИúét|—_¨˜8 1¥£“R‹Ž@cêZ6œ,4¦dù³w@ÿöþÚ®ªÎ÷ÅwüÇ{õÆxï¾úûƨÆÒ²¼—ûêë^ %jÔÒRA!TÙ ¨h”^ÚУ ,A1ôBГ„.}K’œä¤O šä¤%A"RRHþßµ{ϳöÚÍÙ{Ÿ½ÚùÙcŽÃ:{¯µæœŸßÜk-2?ç7!@€ "@c*bT[ìS‹ Ø-Eyš]NUW`’¸À#â­7.þŨGF¾öÑ1ê¦2)3“më¥m•Èû2™T´>zeÞäákÈÓ©³gé(îPM¢Æ”¥¡J[b €ÆTN™hLYˆm€ @€ ‹S±âÙVoИÚÂÅΩÈÓìr*€¨´&‰‹=.´lœL¦×~Ó§ŸÚÞ»¾GŠ’%aR–&ý*·ÉÞ×O[cNïk½£ el*6z×.<ÝhИÚnööçÕ$&hLÙ°´¨«ИºŠ““e‡SvbAK @€ @E!€ÆT”HvÐ4¦ qHÂò4»œ0ªkL€Iâbs•ÔGû)ŸIÞ’ÞÔ¶²4é§Œ%ýª÷ݧ&3é¥lL–®‰<ÝhИò?p¹C5‰!Sþ8=hJ‰RPhL ,Ý‚ @€ ¤H)EøiWÆ”v¨pyš]¼7ì‘&‰R5æ*é%WII˜¤%ÙÏ7öö›Ì¤—‰M–¢I?mÛŠ[.¥æSmæäéFƒÆ”¹áÓvƒìõÆ[;Û>ÒƒИ<²ß]Dcò;þî=SƒK× @€ @)@cJ |ªEcÊBhCsyš]&–™!€Æ”™Pt¿!ÎU’·¤Eå¬ÉIZ*NEY—”„Éå^²¼MúUV“í©í·Þ8ØýfqÆ<ÈÓ)Ï#ÍÚnw¨ü÷#– 1Å‚•“f‡SvbAKºJ€»ZWqr2@€ @€DÉãa€ÆäqðsÓõ<Í.çjñŠÆTà›«¤jy8YJ’™ô«ò3IW’Õd™–ô«¶õ‘vö¤CôŽ%mr†Sѵv äéFƒÆÔnt³·?S“˜ 1eoÀÒ¢®@cê*NN–hLÙ‰- @€ …SQ"ÙA?И:€Æ! ÈÓìrÂh¨®14¦åRré””xIö’:« ÷Óú®÷í#{IfÒ¯¶/DäéFƒÆ”ÿá‹ÆÔ$†hLùàô )4&HA  14°t € @€ "4¦á§]5SÚ þÁ äivyðÞ°GBИM5(<ÝhИò?äИšÄ)ÿœ4%€ÆÄ)(4¦‚–nA€ @€R$€Æ”"ü´«FcJ;Ô?8<Í.ÞöHˆSB ©… § Sþ‡S“¢1å€Óƒ¦И %€ÆTÐÀÒ-@€ @€@ŠИR„ŸvÕhLiG€ú'§ÙåÁ{à @cJt6«Ù·õPßœCo½™ÍÖѪ ÈÓ)ƒ¨Í&¡15†ÆÔæhb÷¼@cÊ[Äho‹ИZÅn€ @€ ´L©eTÅÛ©x1-^ò4»\<ú¹íSnC׆?}õ!MJfâÖäéFƒÆÔZL³¼S“è 1eyèÒ¶.@cêDN‘EhLYŒ m‚ @€ ä›S¾ã7¤Ö£1 'B O³Ë‰¡’V 1µB©°û 16´qu,O74¦¸FArçEcjÂ)¹HM©@cJ;•ÆO)~ÆÔ@€ @ð“oõÉãàç¦ëyš]Î Ôâ7©ø1nÒC4&¯ÃßIçót£Acê$ÂÙ:©I<И²5XiM×  1u)'Ì4¦lÄV@€ @€ŠD©HÑl³/hLmc÷äiv9O74¦N"œ­cИšÄ)[ƒ•ÖtSבrÂl@cÊFh @€ @ HИŠÍ6û‚ÆÔ&0vO@žf—SÀC•õ  1y=2И¼'ÏÓ©“gë4¦&ñ@cÊÖ`¥5]'€ÆÔu¤œ0И²Z@€ @(4¦"E³Í¾ 1µ ŒÝS §ÙåðPe}hL^ 4&¯ÃßIçót£Acê$Â@ И²ZÑuhL]GÊ !@€ @Þ@còx 1yüÜt=O³Ë¹Zü†¢1?ÆMzˆÆäuø;é|žn4hLD8Ícæl“fõ®»ÿ`ÿÁ?Ìpib €ÆTN™hLYˆm€ @€ ‹S±âÙVoИÚÂÅΩÈÓìr*€¨´4&¯Ç“×áï¤óyºÑ 1uáÔŽ³t̨é£R«>Û~ëáÙn ­ƒ@ Иb€Ê)³@) Q  € @€ b@c*V<Ûê S[¸Ø9yš]N•Ö#€Æäõ¸@cò:üt>O74¦N"œÎ1ÊÃ4â‘#'TÎ!ùL=ý=£ç¶mkÐä“-‘öÔG*é44ZÕYiLB!â0~ÕxmÛ¯Ö½czS;kŸ4šIè64¦nå|!€Æ”‘@Ð @€ @€@ 1(˜ív©]bìŸ<<Í.'O‡@còzh 1yþN:Ÿ§ S'Nç9Ãîfþ6¤4™¯ãò3é;}}zS’œäëhŸtÚšx­ê¬/u_@Ô}‰Jr¹´a  C¡wÌÓËó%%*ŒS P9e 1e! ´€ @€ P,hLÅŠg[½Acj ;§B O³Ë©¢ÒzИ¼hL^‡¿“ÎgýF3ÿžC³n)—sþCgü§_õþ:é3Ç$BÀÖMë?د Ë3$‡Éå²OMf²æ8'‘Ö¥Y‰8XV*ÉL. •ë¾å¦(}j­”ìåU¶ª4cCݱ@cŠ/'OSzì©€ @€ PThLEl ýBcj»¤L ë³Ë)ã¡úúИ¼hL^‡¿“ÎgýFó“ÒÌwÝ"«‰WV X!µNi„œŽã¤%ûT“d&er%«½ér»,•Nª i^FÉ%£²Oõ«e±²âãërS8’$€Æ”$mêJS‚°© € @€ à 4&O]¯›hL?7]Ïúìrn@úÕP4&¿âé-“×áï¤óY¿Ñl_ÕPczê²N:Ì1‰°”BªJ?‚c˜ô’ؤŒD2x\ "y<þ$r܆ÃeÉ« ‘Ë\¥mKgÅ ù&€Æ”ïøÑú†И€ @€ t›S·‰æè|hL9 –·MÍúì²·ÉvÇј²Ÿ˜[‡Æ3àâ>7šº ™HÅ”í±(/G9„$ß„—“ £÷%0é#yKê6Li ï–ížu¡uâ µËR.Ùéô«¶MfrY¬ —!êB­œ©@cJ=4 hLñp嬀 @€ Ÿ  1y}4&ƒŸ›®ç`v97,=j(“GÁ®í*“×áï¤ó9¸ÑÔMÈD*¦N¢è1¶nšVŽsµ*ÕÞÔÏð›zÇöôç¥îpŽ%ÇÁÁ1\aVþ ¢§Å$€ÆT̸ҫChL @€ @€ºM©ÛDst>4¦ËÛ¦æ`vÙÛØd¸ãhLNüMCcŠŸqÁjÈÇ&’‰TL…tð“Qö²hL^†NC€ @€b%€Æ+ÞlŸ)Ûñ¡u|Ì.«Œ@cÊX@’mS²¼ P[>n4‘„L¤b*ÀÈ£ €€oИ|‹¸7ýEcò&Ôt€ @€ 4¦ÄPg¯"4¦ìÅ„E äcv™¸eŒSÆ’lsИ’å]€Úrs£q ™HÅ”ça÷ú¿oÝñúœ<÷ ƶïþýâ}oôÆX§†@ºИÒåOí±@cŠ -'† @€ xKÉÛÐ:„ÆäqðsÓõÜÌ.熨 Ecò"Ì:‰Æäuø;é|nn4.!©˜:‰sVޱ;TVZ“±vLXó^}3Ö(šî@cêKΔ)ÜÕ2@€ @(4¦B„±³N 1uÆ£’$›Ùå$¡P×`И#TèÏј Þ8:—§2‘Š)ŽAà9јšÀFcJp$RUИҠN @cJ2U@€ @€<#€ÆäYÀÃÝEcò8ø¹ézžf—sµø Ec*~Œ›ôÉëðwÒùÝhz§=6ö‚;é$Çd†ÀÓ/ž÷Õ ™ð­Ëï|÷/'™™XÑt›S·‰r¾Œà®–‘@Ð @€ @€@ 1(˜ív©]bìŸ<Í.'‡@còzl 1yþN:Ÿ—Mooï‘GóåO;vl'ýä˜ غu«‚xò©g\}õÕhN¶š0eÊ”O}ö‹â£¡ž­–Ñt‹S·HržŒ@cÊX@h @€ @ И ÄN»€ÆÔ)9ŽKŽ@^f—“#BM-@cjRqwAc*nlcêY.n4%‡iØ +¶ônzõK˜L1 …˜O[r˜†=?·WA<ý—`2…yËaúôg]²®þò-ÂdŠy(rúÔ 1¥†žŠã%€Æ/_Î@€ @ð‘“Q/÷Éãàç¦ë¹˜]Î MoŠÆäM¨ëuÉëðwÒùìßhä0}ø¨a z·®Üüª ˜å/íÃdê$Ò©#‡éÃG›2o¥ âiç`2•CbÓÒu;5¼WlzunÏËú9™R¯T4¦˜ÀrÚ´  1¥ê‡ @€ SñbÚrИZFÅŽ©Èþìrjh¨¸14&¯G“×áï¤ó¿ÑÓÑÃön]µy¿IÒ˜zúö7âë¬.×I¼Ó8Ʀ©óV*ˆÒ˜\¿ÎÅäd ¦Ï»lýÎU%KoÅKû–÷훳l3&SC•:c&€Æ3`NŸ4¦´ÈS/ @€ @ ¸ИŠÛA{†Æ4("vH@Æg—SçCê@còz` 1yþN:Ÿå9L‹Vn]õr ¿8É£§oïÒ{1™:‰wâǘÃ4mþÊÕ/ï›:ÄïíµÉ$‡é3r˜6쌌ðe÷ÎZºùƒädJ|¸Ra¼ИâåËÙS#€Æ”z*† @€ –SaC;xÇИgÄiÈòìrÚl¨¿!4&¯“×áï¤ó™½ÑT¦WVoÙï$KÅ$Éc醽K6ì9vÄ×ïºçÞv»=f̘ѥWOéå·7ÝK»é#ý9ínsæÌiå̓êTýýý¶³6Úmyîö/;L/¬ ÑAÜQ&ÓåWü°Ý®¹ ~8ˆ:O__ŸÖFø´ãÇ×›V½Ü\ìt*½o»ég»Mjws˜z6ì ¯Š¨á3—lúà‡Y²ly»gv= põ×:h/më•:„v»Æþù&€Æ”ïøÑú†И€ @€ t›S·‰æè|hL9 –·MÍìì²·ÉEÇјr¦¸‰ÆÙž7›7s˜¯zeÍ–ýY|*+Ê•5¦õ{¯Ûsì m›LÆ 1b„©ÚÖË¢{øá‡5*¢1éÍHìkws“ûÈìýÖ›¤1I]Ò›RdôÒFij)Ø sS%ˆU+ʹ ¾¸~ÏȳFµk2…ƒ¨hº *‚ÚvÁ9r¤QÕ›ÚÖûÚAä‹‘ýjû+ŽúU»ÉþÑOwlq1‡iùÆ]‚S•Š)õö‘™ñ¢L¦µk2…‡¨uÜ„<ërºâË93M)Óá¡q@cêœGB€ @€ PŸ“Ç#Éãàç¦ëÙœ]Î >_ŠÆäkäKýFcò:üt>ƒ7šÃt 6‹-F¦,>’<¤1-Z»û‹Ç·g2E|³[ÄNòG$¯½ÁZw7Û'ü‘9R‘c-Ó½iI'1ËÃ1r˜>¢µä^XµfKý ÊÔ ñ»g¶g2E‚¨_;yHæúUÌõQø}¹J.'“> ‡XF”£[ún;LáTL‘Цɇ’ç¬#u5&ëQ*º“óä‰Sž¢E[Û €ÆÔ,v… @€ @ %hL-a*æNhLÅŒk±z•ÁÙåb.foИŠ×{…ÆÔ"(v«ÈÚF“ô—W½²vëf©˜ÊÓî…kw/X³ë Ç­õÕå">‡s_ИÂãNÆL+—¥2ÒÍašþªPƒTL½‘|ZÕAüN;&S]Éi®×"lf’¥\ªM1xܵFT·H†¦Á+¼f¢Yzë‚>uQ_[&Ó5¦ t &çÉ4¦œŒæ¶J©URì@€ @€@«ИZ%UÀýИ ÔÂu)k³Ë…\Ì¡13®-ö ©EPìV!©M‡éå²þb‰jjS1™ÆôÂê6L¦ˆãRõHþ¿\ЦÈ`©»›íÉÆtØa‡…wŸÇ-õU¼‘Xv˜„¦š †—T>-ÄïœqQ‹«Ë  ØÚš€ne@mLž<9ŒÔW«ÈIr²p„W‹««1é$Mrn %dÎaª+xÕákv/X½ëù…}GÙêêr2Ê>¥6·žÉ:„¡äØ|@cÊwüh}ChL @€ @€ºM©ÛDst>4¦ËÛ¦fjvÙÛ(ä®ãhL¹ Y7ŒÆÔMš^œ+;7šA¦p¢šê,>r˜æ¯Ú5oÕÎϹ¥œL©gcRŠ °IS¤qV'“s˜¤b 4¦’©3uÄS[3™DÙ9’ôr9–êfcŠ,3g>“ã_Wc²%꺗:STðÚç/[QÎ ^óWí|î…VM&iL¶”ž^ê¯uDY©Â‹†×4LBשrÂ<@cÊS´hkИڀŮ€ @€ ´D©%LÅÜ ©˜q-V¯²3»\,®ï SÁܼ{hL^‡¿“ÎgäF#‡éÃG[^K®®þ²qô'œÅG’ÇÜ•;çôö·b2E4&ç¾$¶¨œ,Ó«“heû9L â4·–Ü–ý«*A´åäÂÙ†–„M³|Z ⼕;çöîüöéƒçdŠÑÀÈ݉HK¶rߘ1c"˜Ünu ž°îÓ-äƒ8LÎÒ‹Œp ^8áÏÌߨJN¦º#Y²´Löa±íÄ t &çÉ+4¦¼FŽvB‰!@€ @€@·  1u›hŽÎ‡Æ”£`yÛÔŒÌ.{Ë?§GcÊiàºÓl4¦îpôè,Y¸Ñ8‡iÍ–k¶ì_ýr•þâ–“kœ¨&ÈâcÓìýÿü¥¯ÞuϽMB(…Å2Óè%™Ã-’?äyØû.WÞ¬}§v7«.²¨\äX§.RcŠ:L¥ ®ÚüêÊͯÊajÄH*&ÄovaóÕåêjL ªàŠ°ÔœHpõ«Þ4ÕÉ­=—ŒÁã¦Ú¾¢’¤ÊL\ºaoCÁ«4Ÿž·ñ?ôÑ%Ë–7áu5&¥e²©.kkÛ%jJ‚GWUºÚˆc£ ј”3ðàÁƒ®ïúU×b—H° Lè @€ @C#€Æ44~¹>)×áó¤ñY˜]öu‘º‰ÆT¤h¶Ý4¦¶‘ù~@L7š}o¬j‘lÈaÚÿðìÍ?·lɆ½æ¾¨<÷âotßÒž¾Êb[öŒ›Ú·x])ÓšÝÏ-þ͵÷/¿ç¹ –Ågvoÿ¬ý3—ïø\S“IIhœ™$©Åµ3¬+9)ò¦v®»›D¹™J™4‘=ó§1ýng‹AtS`¡•D´kÆ-›ÛÛoA”ÃôÓ‡z¬Ù]Ñ6ì¹ãéuå ® ² ýì‘•7=²Ò‚(SÇ‚øÍ¦&“‚Ø(£•b*MGÒR8¸êˆådÒGá¯ÚÜK-ecjNÈa*ÃQOozxåÕc—=8s³KRep&/xEŸj99áOÎßrù=/>>wKYð*Á™4wCs“)<Ô·¤Ìás“vèB‹ãƒÝ `И ¹%àäWëî#º§¸ i3I;…W*uWá°Q›[,4€ @€ Ø 1ņ6û'FcÊ~ŒhaL³Ë€-64¦bÇwÞ¡1yþN:Óf\ïŸ_õW/¿úHó6™Ã´håVç¾ ?² §¿œqóüáçM Òb[§ý|Þ•¿^²hÝî…kwßûüÆ/]þüew¿8ògspë –ŠiÖò2`fôlÿÜqƒädê–oÇŒ;õÐχê›Ó¼ße‡iþJ b) ÓþáçOúæõ3]¦ã¯œòØÜ—-ˆ£Ç¯øòÏ[/ñÜ[œ{ë Ç]þ\$ˆßüþ 9™Ò ˆþ/R|ömmÞ9LŸþܱ=v:8c&®œQw,úÑØegÜ2_d”‡É¦i˶‰Ìó6Û‚‰˜NúÉŒËî^,2¿|rƒ3£gÇSsÖ¿°œLi¡nÔ%€ÆÄÀÈ'IKÊ`çÚ.Ô–£uiíjL²Ÿ¤+…Sä¹)SD¶Í'Z @€ @€@<Иâáš‹³¢1å"Lž72¦ÙeÏ©¾ûhL…q³¢1yþN:ÓF“´TšÈLæ0-”ÃTq_®·ìÌ[æŸpÕ[ikyß>IŸ:gËO'ô–^Γ³Ö¿ÿƒƒ¬.—*†@]hL ŒP?3‘¬íRš¤1Ù¶$%Kï×Pc²•ã\6&-áiI˜ä@á0åp0Ðd@€ @€@‚И„µªÐ˜²ÚSK ¦ÙeP›S±ã;HïИ¼'éFã4¦F2Sà05lAïVKÞcî‹–ÙR‘º4kÅãg¼tám %vH™¿rçÔ¥Ûä0]!iMYò?ý¥ËîZ|͸žHiLS—nŸ²d&S'cÂã4¦2Sà05lʼ•á Z&-É:Ͼø[eÒ’“¤TCÒ˜³yÉú=ÌÞüð¬Mòu,ˆrÑ´& ‚(mÒ‚­á|Z.ˆ'/“&“Ó˜ÈLÃôÙc—®ßY‚ o•[ŸZXz%‡Iv—ò0)s˜ðI ^ÑB{"hLkv?4s“àüê©5‚sã„•¶Öž’W‚WÏöiÁßöÄÌu˜LCáœ04¦„S]7˜¨ä4&[.ÖV§uK”6[TN‡5¦Ã;LGšÏÔÒ ¦Ýèç€ @€ @ Иò³®µ©k(9Qlbš]Ž­½œ8И2†´Æ”ùÜÖÓ&¢1Ed&9LGuÌ‚[Ìí0ñEåGc—ª(?Í õÊðP–šÇæ¼Hë÷¼¸~Ïâu»å0©Hyau«FËÉ=0í¥ïÞ4çk?ž.ói ‹ÏÒ@òÆ„É4¤јªe&9LGÊašÛkAtq”££"IšÎ ­8yôL%Óú²4¦Ù›-ˆÒt¾tÅóD™:Z1íîg7\3vÙ'ÎX•Š)Ä,šL©Zf*9L_\²®¿v„kx[†*·–œFx‰L'ИfnœglúûoMä.D—ܹ8:ÂKÓiH#œƒ&€Æ”0pªë°Æ¤m¥RRN%m ’ÉÉÆdošÉÔ½r&@€ @€ŠE©Xñl«7hLmábçTÄ4»œJ_¨41hL‰¡ÎbEhLYŒJ¦Û4qãÑæ%Vn›ó®÷¾ïðùË·8{IKÈY~9L?¼o鳋£ä=Jásòu3•¥¦"yìÖ2dr˜´™ô—ù«I+‘y˜zû?~îIJÃTITc“•#?:|Òÿ¬¼˜é&”¡xóÆO(ˆÏÍí­ ¢­•¦-WŽ=ñ›·|<Aì½ñäÿuÄ‘KÖö×Âùå“k”l¬,0mÜ«µä´Z¢F¸9L‚#2ÊÃ$8ã§o’½d#|Ü´>Á ¯µç,=3™Þ÷ßÿ¡oÓæL_hhD‰a[aIËÌY?,3“6ZÍÆ¤5æÜ‰Ð˜r;h8 @€ @ hL‰`Îf%hLÙŒ ­ @cb!ýå'¿ÿÙáÃ×ÞÿÓ7&þä¾ ”Ö üäˆú¾—²4íÛ:vìØ/ŸxRmGEPQS&§éèW­%gA´åÒÄù«v~ýÚé7>¬˜¦ ÊÔ¹Ï4& b%Ÿ–LÛÆO=êÃYþ럼þÔuY‰ày^Îù4ï§žzê5?ýU-œ™Ëƒ%ä´œÈHÑSš±+ï]òýŸÏ+ð5ƤÒrr#GŽ´µ­1é˜#Fèr˜l#]£ € @€ d’S&Ã’L£Ð˜’áL-C!€Æ4zÞ‹Æäm胎£1yþN:¿qßX=íx}N'7>¦vQ9˜Ü2™N;ç’ÊêZå¶ä0]ußR˜d{HdQ–múËšÝZiKÓeÒ˜V휷rç¥w-Örrã¦öóËùß¹iN]ý%p˜>ÜÚ—÷HòPyãßñ<Ú‰sí¢r%ÉB&Ó—N<)D9L˜‚¥KšŽD´ëƯÐúhJÂ$‡É–K 4¦R•ŠI9‡Ä&¬0S'p˜–Õ8LýøòõÛ,ˆ¯¿ñV;}ˆmßÈ¢rÉÕ˜L7üªÎ-O¬–¥wóã«•žJ“@MYò[‘±.2ÊÃ$KOy˜äxi­=ÁÑš‰?ºoYÝî&ƒƒÉ[¼9q7 1uƒ"çH…€Ó˜T»Ö‚ÓŠrZNNʯ¤wÉÆ$]éàÁƒ®ÝúU“Ö¥K¥'T @€ @€@> 1å#N±´)¬œ´«ИºŠÓ—“¡1ùéºýDcò:üt>)"0¹VÊdúþ9ÛÒc–¹çþi/Ý?­O/–¢F əᡕ¶îynã=ÏmЧ¶ØÖ z« jý%â0a2µ=>ÂSµÀäN%“é¸_Ñò ]uï Ln­´Ÿ<°|öò~ ¢tœkÇõ¸ ÞùôzYhçübþ“ó¶N/¯ 8°œ\‡)ä0eÈdrSÀäàÈdºú†_Õ¹jŸ¦o\7ãºñË-C•á׎[.‘KÃ{no0¯»L#üú‡VÔ¼"&SÛ#œ&€Æ”0pªë[<Î^ýýýZWN9™d2Ù;ƒhLÝkg‚ @€ @ÀhLÞ„º¶£hL?7]GcÊM¨²ÔP4¦,E#ñ¶ 1%Ž<ïƪ15˜´Àd:ûâò[•ä=%÷eÏ¢ÊBrr_LÑJ[–¥Æ&-C6kEÿÌåZik‡ô[lË-'W×aÂdjo¸šÆÔ@`r§2“)İÃÖtDËÃÔ(ˆá5ë:LY1™ô‘&G&Ó®ÿU½¾»j„¯¶¾³<ÂKSi„ï(ðš$Uu&L¦öF8{'L)aàT—4¦¤HS @€ @ÀhLþ妧hL?7]GcÊM¨²ÔP4¦,E#ñ¶ 1%Ž<ïƤ1Í}edx ¹&”d2}ïì‹e½TÄ—É¥¨i`xT9Lþ²tÛ”%Aiâ0ÕšL¯Ì›üȈÃ'VÛȺoæ=âm´éÃá%äšh&S“ .ˆh:5"ÚŒ’ˆb‡©ÖdjÄy׎ÜÑ3§^·¸ëÜ;½q •}e2ýpô­!8Ó`#¼â0ÕXzM&L¦V‚Â>é@cJ‡;µÆN)vÄT@€ @ðŽ“w!è0“ÇÁÏM×јrª,5)KÑH¼-hL‰#Ï{…1iLma¹üŠŽ<ëb[B.¼ÆV9 “e©©äï‰d©©Õ_u˜äyüvÏzçk¤4I0µ ~co¿ïS;Q¼ëž{=áëA+i´ÌÑ© ¢%ÓH5TÑ:p˜Ä­;Dõ@AT(ÛéJ÷÷=éäo^5úÖ:#¼lw5á–i,,x ê0 Îö½è~78#†Hiˆ9<«И²Ú@€ @È/4¦üÆnÈ-Gc2BN;4¦Ø±4¦"Fµå>¡1µŒŠ@4&5ã’Ë®úîY£Üêc–¼Ç%aê®Ã$Ãã?Þp˜,Ók¿é“Ì4mÔ•÷ŽV“”ÂGÛÚˆ¼¯wd>ÙžŒ¢0;îúõOøú@KKvÄAó0™¦óïo½mµ+‚¨OõQÝ *ÊĽë{ˆã×¾ñÍ+¯ûed„Ï/$gªl-¹åUy˜:p˜œà•@ר­@cj•ûåŒSÎFs!@€ @9 €Æ”ƒ ÅÕD4¦¸ÈrÞî@cêK΄ÆäQ°k»ŠÆäuø;é|F4&5=0™ÎU^}¬¢w˜ÀTÎßÓÛ?«©áÑJ¦°Ã¤Jßzã i.rY$3éWmkC¿Js1ŸI;è}³$¾¼ôÜx½¿öÑ1h:^Üc“éø¯…-4—IË1¬ét–‡)ì05¢…µ6ˆŠ¬ÅÎí@Ld2]qÝ/ËjWÝ®áÔ@$¨"-hLi‘§Þ˜  1Å ˜ÓC€ @€<$€ÆäaÐ+]Fcò8ø¹é:SnB•¥†¢1e)‰·)qäy¯0;“HÊdúΣñ¥²Šœ&¥¨©,$×,KM“j [,ÚV& .ò–¤+™Ì¤}´!åEiÛ½¯THÈT;þe2}áø¯)ˆSËAl7“ÕÞ$ˆÎE Q‡(Ä ¨1É¥e2]~í/«Fxi‰=7ÂgºNŠÆ”8ùÝJ4&¿ãßaïј:WŒÃИŠÇ{‘)Iý–Ét꘸/3zvL¯1<:s˜TÓ\$*©(Í’¼ËÏd?í¥÷%»,þÅ([‰ÌŽRQB¦c•›ª“éË_« ¢­•¶"X+M¥n;s˜š1¼fœ ¢…ØÑrn%ö’ÉtÙµ¿p9Æj½r†ªeÛ§.Ý>uɶ)¥ráo>ñ«'k5½&EIªp˜‹#uB©j“hL9M„ @€ äŒSÎÖÍæ¢1u“&犇S<\ ~V4¦‚¸y÷И¼'ϚƤ>Èdúöé™Þq_ê;LªËi.NZ’™$cé½ý–¤G;¼2o²6,mRø¸ LÒžì#^µd2}þË_ qVE`ª âÒ²¦Ó±ÃÔ$ˆú¨nõ¾-¨ …[vZ”Étéo˜ÂvWÏöÀÒ“À´tSÂq¡ºØ  1ÅŽ˜ Ò!€Æ”wj… @€ ™S‘£;HßИ<~nºŽÆ”›Pe©¡hLYŠFâmAcJyÞ+Ì Æ$¤2™¾uúEJÞr_‚$LÎð°5*Cq˜T‘[PLN’¶¥(IjÑOeîÑ;ÚA¢’”½£Oõ¦Þ±mKΔ÷èÇÚ~3™Z âP¦&At.Zm; bZËÊdºäš[Â驜Ýe“áäaŠu”ròD  1%Š›Ê’#€Æ”kj‚ @€ øBÉ—H×é'“ÇÁÏM×јrª,5)KÑH¼-hL‰#Ï{…ÙÔ˜D50™N»P«Ùd¶\°ÌVÈð¢Ã”÷Øe¿ý2™þùK_-Ñò ÕqˆSö!4j¡L¦‹¯¹¥j„W'ab-¹ü—–×'€ÆÄÈ((4¦‚–nA€ @€R$€Æ”"ü´«FcJ;Ô?84¦Á±G 4&¯“×áï¤ó™Õ˜Ô™Lßüþ…æ¾DRÔ =S'°8¦}2™>÷¥¯6 ¢·“”É4êê›ëÚ]8Lí5ŽÈ<4¦Ì‡ˆvF©3n@€ @€@chL4&ƒŸ›®£1å&TYj(S–¢‘x[ИGž÷ ³¬1‰­L¦S¾¡20M­¬"וµäòµ|µ?0™Žûjm=w˜,ˆ2™.úÑÍác6ÂYK._ƒœÖ¶D©%Lì”?hLù‹-† @€ dSÖ#cûИb„Ë©»D©K ý: “_ñŽôÉëðwÒùŒkLê’L¦“¿w¹8LÄ8ÇÈdúìq_ ‡É…E&“¤¥0¦ ŒYš4¦ rÊ,@cÊBh @€ @ XИŠ϶zƒÆÔ.vN…S*Øó^)SÞ#8¤ö£1 Ÿg_cRTÂ&ÓO~1þ³Ÿ?níË{6m½QÙ¾÷ÿñö;>†3Ã}›L8L‘@…M&¦ bš64hLCãÇÑ™%€Æ”ÙÐÐ0@€ @€@n  1å6tCo8ÓÐr†¸  1ÅM¸çGc*dX[íS«¤Ø¯L “Új&S®®™L8Luƒh&S®G8„C¤ И Xº@€ @H‘SŠðÓ®)íPÿàИgÄ5И¼hL^‡¿“ÎçEcRß¾~æþÇQÿy˜: sfŽ‘Éôÿû‡÷/_¿­y2­ëíÌ49¹†|íƒï:ñÃÿ­ }¤Lcz‡LcÉ…šºI©›49W† 1e(4€ @€ PhL d'Ý@cê„Ç$K)YÞ© © ì¬hLqóø¨iLº'Þ»äÖ’Ëûh}ý·p˜êñò÷îºé„æpp˜ò>þ½n?“×á/rçјŠ]ú@€ @H‡S:Ü3Q+S&Â@#š@cb€t@©hÅ9©8±L¨'ùÒ˜&¬yï«¿û÷ºž‡²ÔüÇÛd©IhØ ±šF&“‚èg¦2ÏÒÿ™îÚÿf£ŽÃ4ÄÇá)@cJ9T4¦¸Èr^@€ @€€¿Иüý!4&ƒŸ›®£1å&TYj(S–¢‘x[ИGž÷ s§1 x­É„Ô»qXk2ùî0)„3qhÑ8ý·Ödb-¹Üp\‡â И Xº@€ @H‘SŠðÓ®)íPÿàИgÄ5И¼hL^‡¿“ÎçQcR?Ã&S'ÏÀ1a“É+‡iïúž×~ÓW½ïÞ ›L8L­4¡ИºA‘sdSƒB“ @€ @9'€Æ”ó¥ùhLC¡Ç±É@cJ†sÁjAc*X@ÛëS{¼ØûPŽ4¦}oôîþýb33™p˜r=ˆÍdòÊaš6j„Êâ_ŒŠNbÓä‘ÃÂošÉ„ÔëNã« 11 J© ¥[€ @€   1¥?íªÑ˜ÒŽõNipFìQCÉëAÆäuø;é|f5¦ƒ<8h^ûý[ÿñö;ƒîÆY& “éßßz;Ë-ìnÛqxÝ®}tL­Û$WïOï0»Ζ4¦ôØSs¬ИbÅËÉ!@€ @^@cò2ìÖi4&ƒŸ›®£1å&TYj(S–¢‘x[ИGž÷ ³©1MÞ8yää‘ygKû!! “ÞTцR4姯´5И%€ÆTÐÀÒ-@€ @€@ŠИR„ŸvÕhLiG€ú'€Æ48#ö¨!€Æäõ @cò:üt>ƒ“¼%Ó’´!WÉze˜´aI˜´®œd&}jÅiO à$EÀR.…WŽ“¨d«ÅY¦%í`&“å^Òû¶‰MI5“z 4¦x¸rÖÔ  1¥@€ @(4¦Â…´õ¡1µÎŠ=Ó"€Æ”ù\׋Ɣëð µñhLC%èÝñÔ˜”uɉS& ‰•l9“™ì#)M“7‰mxA Ë”„Éœ$½lµ8ýj®’~•¨¤÷-9“}d{ÚÂs*Jã”åÞÑ6 NipFì‘KhL¹ † @€ dšS¦ÃoãИâåËÙ»A©½;“w!wÉëðwÒù jL•LcRš%ËÀ¤—­.7~Õx½©ŸzG“„'­+§ 4¦NbÏ1€’$€Æ”$mêJS‚°© € @€ à 4&O]¯›hL?7]GcÊM¨²ÔP4¦,E#ñ¶ 1%Ž<ïfPcR¦%™LÿxÐt%{ITÒ›ú©¢ôŽ’0Yº&™Lyí‡ P|hLű§=Dcò4ðt€ @€ #4¦áfýÔhLYí;t‰QÐ4¦ ç4¦âÄ2¡ždPcJ¨çT@I@cJ’6u%H)AØT@€ @ð„“'®×M4&ƒŸ›®£1å&TYj(S–¢‘x[ИGž÷ јòAÚ_3qhѸât‡ž@ B‰!QPhL ,Ý‚ @€ ¤H)EøiWÆ”v¨phLƒ3bhL^ 4&¯ÃßIçј:¡Æ1ˆƒÿgUΙhLÙ‰-é*4¦®âäd€ @€ ˆÿXìñ0@cò8ø¹é:SnB•¥†¢1e)‰·)qäy¯0G÷ļ6Ú?þÏ”!RlhLÅŽ¯Ç½Ccò8øt€ @€ þ±8&°y8-S¢ä{™²õ}tÔ4¦Ž°å 4¦¢D2±~ 1%†šŠ 0þÏ”!RlhLÅŽ¯Ç½Ccò8øt€ @€ þ±8&°y8-S¢ä{ј|õ©#lE9©(‘L¬hL‰¡¦" B€ÿ3eˆ›S±ãëqïИ<>]‡ @€ ÄD€,Ž lN‹Æ”‡(ùÞF4&ßG@GýGcê[QBc*J$ëSb¨©ƒàÿL"Å&€ÆTìøzÜ;4&ƒO×!@€ @1à‹c›‡Ó¢1å!J¾·É÷ÐQÿј:ÂV”ƒÐ˜ŠÉÄúÆ”j*‚À ø?S†H±  1;¾÷ÉãàÓu@€ @€@LøÇâ˜Àæá´hLyˆ’ïmDcò}tÔ4¦Ž°å 4¦¢D2±~ 1%†šŠ 0þÏ”!RlhLÅŽ¯Ç½Ccò8øt€ @€ þ±8&°y8-S¢ä{ј|õ©#lE9©(‘L¬hL‰8l–ÿôIDAT¡¦" B€ÿ3eˆ›S±ãëqïИ<>]‡ @€ ÄD€,Ž lN‹Æ”‡(ùÞF4&ßG@GýGcê[QBc*J$ëSb¨©ƒàÿL"Å&€ÆTìøzÜ;4&ƒO×!@€ @1à‹c›‡Ó¢1å!J¾·É÷ÐQÿј:ÂV”ƒÐ˜ŠÉÄúÆ”j*‚À ø?S†H±  1;¾÷ÉãàÓu@€ @€@LøÇâ˜Àæá´hLyˆ’ïmDcò}tÔ4¦Ž°å 4¦¢D2±~ 1%†šŠ 0þÏ”!RlhLÅŽ¯Ç½Ccò8øt€ @€ þ±8&°y8-S¢ä{ј|õ©#ly>hí”C²—¬üÛ'išðÑóÞùÝÎ<÷¶ÇN _Ó¯WüÙo1¤cTþÏ4îÔš4¦¤HSOÂИNu€ @€ ðŹQј<~nºŽÆ”›Pe©¡hLYŠF"mùmo .Õ-?9"‘PIŽ äHcêÝyƒÞv¼>'Ǹi:šÐeüž¯C…%€ÆTØÐúÞ14&ßGý‡ @€ tŸS÷™ææŒhL¹ •Ç Ecò8øw©svù=òöêkL½óÛ'Zž iL9jj2±£–¢@ò(ZDéO5F8#¢ И Xº@€ @H‘SŠðÓ®)íPÿàИgÄ5И|u2‘ŠÉÇ¡ÐvŸsä娩m‡ H ƒb`„;¾÷ÉãàÓu@€ @€@LИb›‡Ó¢1å!J¾·É÷ÐQÿј:–ÿƒj2‘Š)ÿQM 9rƒrÔÔG$€äQÀ Ò¥F8á И Xº@€ @H‘SŠðÓ®)íPÿàИgÄ5И<‘„L¤bòt´Ýí¹A9jjÛaàˆ’àØáÅŽ¯Ç½Ccò8øt€ @€ 4¦˜Àæá´hLyˆ’ïmDcò}tÔ4¦Ž°â pB&R1"¤ t"GnPŽšš@ਢ€< Tº"Àg8”SAK· @€ @)@cJ~ÚU£1¥êœÓàŒØ£†“¿ƒÂ%d"“¿ƒ ížçÈ ÊQSÛ@@<Å&À/v|=î“ÇÁ§ë€ @€ ˜ 1Å6§EcÊC”|o#“ï# £þ£1u„­(YB&R1%ž ô#GnPŽšš@ਢ€< Tº"Àg8”SAK· @€ @)@cJ~ÚU£1¥êœÓàŒØ£†“׃B ™HÅäõh»ó9rƒrÔÔ¶ÃÀ$†A± 0‹_{‡Æäqðé: @€ @ &hL1ÍÃiјò%ßÛˆÆäûè¨ÿhLa+ÈAS¦L9úÈ8p  ý¡ñÈ‘”£¦Æ7j("$"F•> `„3 J© ¥[€ @€   1¥?íªÑ˜ÒŽõNipFìQCÉÛA!‡éSŸýâO>|8&“·Ã ÝŽçÈ ÊQSÛûC €äÁ8(6Fx±ãëqïИ<>]‡ @€ ÄD)&°y8-S¢ä{ј|õ©#l¹?HÓ§?{ì’uý½›^}xò\L¦ÜG4©äÈ ÊQS“Šõ‹’G±âIo¢ጉ‚@c*h`é @€ @ EhL)ÂO»j4¦´#@ýƒ@cœ{Ô@còpPÓçŽ]º~çÊͯJcZþÒ¾ “0™<t9GnPŽšÚI$8HŒb`„;¾÷ÉãàÓu@€ @€@LИb›‡Ó¢1å!J¾·É÷ÐQÿј:–ãƒÌaZ¶~çªÍû¥1­(iL=}ûš8‡œL9ŽkRMÏ‘”£¦&=ê)$bÅ“ÞD 0Â%€ÆTÐÀÒ-@€ @€@ŠИR„ŸvÕhLiG€ú'€Æ48#ö¨!€ÆäÕ Ãô™ÏÛ³açê—‡I©˜V¼´oyŸ4¦½K7î?qö'‡uÿ~¯˜ÐÙ¶äÈ ÊQSÛ ;C LɃ¡PlŒðbÇ×ãÞ¡1y|º@€ @ˆ‰SL`ópZ4¦:ê?SGØryPÅaÚµzËþU!I©˜–m 4¦%ö<ðÔìó‰M¦žžž#F´ËbòäÉ‘CF}øá‡Ï™3ǽ?f̽ÓüÌ®vµAÛÚyذa:JgÓ«ù±îVïv¶vŽ9Ò•‘–«…j˜^ÚèëëSóÚê`ÂøñãER/¤¿¿?òiŽÜ 5µ•qÈ>ˆ@ò`L›#¼Øñõ¸whLŸ®C€ @€b"€ÆØ<œ)Qò½hL¾€ŽúÆÔ¶üdÓò»ÖlÙ¯TL«,SeE¹@cÚ°wÉú=‹×í¹ÿÉY-šL’‡$»´Ë¢Ö|’ ¤ó„õ ’šŸÙÕnâŽûõ`éÕüXßÌ'{É ªõuܧnçÈQÚ!õ–« â6jÔ(k­HÚ0&¼ÄAä  d²Ú`åÈ ÊQS;ˆ‡@à’ƒ ØáÅŽ¯Ç½Ccò8øt€ @€ 4¦˜Àæá´hLyˆ’ïmDcò}tÔ4¦Ž°åì ¨ÃToE9¥bz±¤1-Z»{Üã-™Lu5&™=r_ôrn<{Gn<K&¨C´³ó–dÒXz!ÛÇn¦‘}jç7eG;èÌf>i[ò^z_oFZb^Ž^µ“½¯æÕ†ÖvÖ™u~m‡ ¡˜Z®„U‘ö4j¹Z«=­¿ö²mc¢—Zh]8ÜÉ--V-%×AÙ]µšZŽÜ 55gš›H ͈‰#<&°œ6mhLiG€ú!@€ @Å#€ÆT¼˜¶Ü#4¦–Q±cjИRCŸçŠÑ˜ò½–Ú[h9¹†©˜ÊÓî…kw/X³ë¾Çfš“©Vc’øâ%³dÕ˜@£,ßRÝlL&?Ùºr:Äl'ÛÙÔ"—gȽ£³™dc¹Æ¸EåtK¹¤èeRŽò éM÷Q˜ ô;gdMºæÙ˜ºÞr×Në¾d£æ-7…K/ë£õÈ1±žª×¶áN¥w´å^ Sr@ì´µ+æÈ ÊQS[ú&³"<Å&À/v|=î“ÇÁ§ë€ @€ ˜ 1Å6§EcÊC”|o#“ï# £þ£1u„-7…¦ÊrrûWÚŠr/í[Þ·¯§oïÒ{é˜Lczaõ®{3™êfc2OH*’ù1ò`´!ÃÆ-âf“íf†‰G•œçdÚv /-g™ÂI›šhLæ*Ù™-Õ“Ó›tZU^TÎ…Ód©ðòvú(¢1© Ör}GËÍ‹²3kC©my¸ ÖxµÇV¸«ËD;X§²£"” §nnª¹A9jjn.(44S<2ÓuŒð®#å„Ù €Æ”8Ð @€ @€@‘ 1)šmö©M`ìž4¦ ç¿J4¦üǰaê8Láåä^’ôoÙÆ½K78©œŠIÓüU»æ­ÚùëG›ådª›É¤%óÌõ±¥Íœac“<'{Gέ1QÉ,"G¹‚‹šÙ Ãb“ªn6¦° cç<ÚkLªÈ–¨ÓO[º.üŠhL–±ÉšGËÓ¶Ã|Ô*ky¤ µ­0q6јÂ©ŠÚ¤YVKŽÜ 5µÀW!º#$árê `„g 4!hLqP圀 @€ ¿  1y4&ƒŸ›®£1å&TYj(S–¢ÑͶ4s˜6½ºÜ9L R1Í_µsîÊszûï~dF£Õåj5&K}dݰlLzÇ-LæÖ‰S²¥pW@#;Ç--ç²1™odËŸiÃIE:m“lLaÊÖ³sÙžÂ'±f裺™‡ìÓˆÆwËÃík›Kåãš!bRìW·T\#)|*CíD1·ê_óQ˜#7(GMíæ7ŸsùCÉßXûÙSF¸Ÿq÷ ×hL™.B€ @€&€Æ”0ð,U‡Æ”¥hЖúИ@cêZöqS°œÊËûW¹z šQŠ01,aÚÙÔ¨ZJ™lLÙÿšÓBß yø>ŠÞFxÑ#ìmÿјÜJÌzÂs²öüê-2:@€ @€À И<"hL?7]GcÊM¨²ÔP4¦,E£;m1‡©gîÀa* L_ØúÍëgönzuEÃtòu3JÓžëXþ¥+žÊå*ÏüÙܹ½;g÷öÏZÑ?sùŽ;˜LÝiqœg‰d~гª”Ï6ÃÚmJë”r”â(GMm7^ì€’ã ØáÅŽo¡{çŒ#·†²ùHf7Ó˜ä0vØaε7Oß~—{³Ðèè @€ @@cê[1Bc*F‹Ý 4¦bÇ7¦Þ¡1Å6­ÓÊaútà0ítI˜Vm~õ©¶žpÕ”ˆÃ4}Ùv9LŸ'ûß4¦ìLj‰’Çðqpæ 0Â3"؈@DcRŠ&­çvnOc’Ã$“ Ö€ @€ @ 4&Ç“ÇÁÏM×_øÍ¨´Kà×+þìoÈÍ@§¡õ}ôÑ<>Í¥_’½dÓò Ó¾Çç½|ü•Ï/­ÎÃ$‡Iy˜¤1Y¦ù«vÍ[µóçNš´`kt9¹ SÙa2“éØ¿ù/þïìùOí6ö/onÈþ)û1¢…C"€ä1$|œyŒð̇ˆ6"јôkxQ¸ö4¦Úêà@€ @€¢И<hLŸ®€¾Â¬ýoEè }€@=>|ø„Ésu©b/¹Uä›hLZHnÉúòZr‹J“ò0}â¼IÎaztέ(^NnFi9¹iK·O-ÙKVNþÞ?¸ðòMÛ_ß¾÷zçl@cÊf\hU× yt %'Ê$Fx&ÃB£Z!VúúúÂ+ÊéðA4&¥_êééqÕ 1µBœ} @€ @¾@còx 1y|º^hLEˆ"}hJ l2Mšëì¥` ¹R¦GçlVÖ%W¾ñ“ K“ò0)ý’åaš»rçÓ^úúµÓg¯èŸµ¼þrra‡I&C2ËИ²ÚÖH]€È)2L€žáàдæÂê‘”$‰Iáýј€ @€ @€Ú&€ÆÔ6²â€ÆTœXÒ/  1yvï:m&ÓCçöRe 9ËÀ¤²xJ) ÓÚ@` ¯%'‡inïÎr¦!‡©z99—‡É&L&ïFX®:ŒÆ”«pÑØö y´ÏŒ#òD€ž§hÑÖ6 1µ‹]!@€ @h‰SK˜Š¹S1ãJ¯¼!€ÆäM¨}神Lã'ÎvKÈE&K´`õ®ÒZr;-Sc‡i{íZra‡ “É÷—áþ£1e884­<ºA‘sd—#<»±¡eC"€Æ4$| @€ @€@hL 4&ƒO׋@©Q¤­ÉôÉáÃxjv)ýÒ@¦ª$Læ0I`Z$aŠæaêÙ>-Èô}ê’m¦1ÕÍÃÔ$'SÿÁþa÷ k­½ìX 1Å‚•“f‡’GvbAKâ Àƒ*çÌ4¦ &@€ @€ F©`m§;hLíÐb_dŽSæBBƒâ$ðêþý=æ÷?9Ë– L. S‡iú²íÓÚq˜ä3mßû‡?½óŽëÓøUãG<2âàöíëÓ›=ý=î§í£lCÙ§¼ Ð]hLÝåÉÙ2GÉ#s!¡A]%Àï*NN–hLÙ‰- @€ …SQ"ÙA?И:€Æ!È4¦ìÄ‚–$CÀL¦qÏ –[,!W˜’0Y¦Ù½ý³VôÏZ¾cæò3zvLïÙ^v˜–¶š‡©Öa’¢$‡iää‘s¶ÎQN&Ûçg=´Š '}ª }:jú¨d°P‹?Иü‰µ§=Eòð4ðÞt›îM¨}ë(“o§¿€ @€ ø  1ÅÏ8³5 1e644 ­@cj…ûŒ€™L÷=6s@`ª³\ÈaR&ËÃ4‡ÉÊO²K‡ßz¸KÅ$ŸÉ>Õ†ÞÔOyNnÿ‚Á§;©@cJ=4 ^Hñòåìi`„§ê‰SL`9- @€ @ÀchLÉãàÓõ"@c*BéCûÌdº÷±™óVíTú%ËÀdI˜f+ ÓŠr¦ SÉaš:´µä\e/iÛ\%{Ó20Ù¶>Ur&ýÔ§Vl^è"4¦.ÂäTY$€ä‘ŨЦî`„w%gÊ4¦L…ƒÆ@€ @€ A©aì¬hLqã(d„SFA3’'`&Ó¯Y-0 $aša ÉuÏa²ÕâÔÓ°ºäò3)“¤%·v“Ò4yãääÉPc±  1;¾ôî’ƒ ØáÅŽ¯Ç½Ccò8øt€ @€ 4¦˜Àæá´hLyˆm„@ChL Ÿ ˜Ét÷#3J˜ÂS„)p˜B ÉMY²íäï]ðƒ /ß´ýõ&eûÞ?üéwêRU&IKÿxг}ôÎøUãå0œ¥V’®¤ã$*ÉI²bY—,'“6¤7i[ïKuÒþúÔí‰ÆÔ>rŽÈ 4¦¬D‚vÄDÉ#&°œ6#á Íè64¦nå|€ @€  1y<И<>]/4¦"D‘>´O@KÅÉLÒq.å’Ô%ËÏd2“e`² ½ïVšÓ;Ò›$6µ_'G@ И2$øØræ,`„g! ´!hL1@唀 @€ Ï  1y<И<>]/4¦"D‘>´O@f’©H’–¤%YN&[TÎd&åjRѯ˜ô‘$'ÛSò“K×Ô~µô  1¥Z+$XñròÔ 0ÂS ˆ‡S<\9+ @€ @ÀghLGÉãàÓõ"@c*BéCûVÜ;Ú’̤m¹JÚÐÏ=sTì#ýjÙ¯z_¿ªØ’s¼ ShL9 Ín•’G«¤Ø/ŸáùŒ­”Ó ˆØ€ @€ 6  1µ ¬H»£1)šôÅChL.C>@cò9ú^ôÉË0{ÜIF¸ÇÁ/v×јŠ_z@€ @HƒSÔ3R'SFA3 Ð4¦Î¸q œ@cÊiàhv«FÝ‹>£1yf: @€ @H”S¢¸³US¶âAk Ð&4¦6±»Иüˆ³Ÿ½Dcò3îõÉã`{ÙUF¸—a÷¡ÓhL>D™>B€ @€’%€Æ”,ïLՆƔ©pдK©]bìï4&/Âìi'ј< ¼?ÝFòð'Ö~ö”îgÜ=è5“A¦‹€ @€ „  1% ÷Éçè{Ñw$/Âìq'á¿Ø]Gc*v|é @€ @ hLiPÏHhL Í€@gИ:ãÆQ'€ÆTð{Ý=4&¯ÃïCç‘<|ˆ²Ï}d„ûýB÷©Ðá¥s€ @€ T 1¥‚=•¢1e#´@cꇛS±ãëwïИüŽ¿½Gòð È^w‘îuø‹Üy4¦"G—¾A€ @€Ò!€Æ”÷LÔŠÆ”‰0ÐtJ©SrWhhL…¯çCcò|¿ûHűß=d„ûÿ÷©ÀÁ¥k€ @€ ” 1¥> Õ¢1e! ´@cê™S‘£ë{ßИ|…ï?’GáCìyកâv©¸±¥g€ @€ ´ 1¥E>zßþÓ›ãWý¥Ô‡ºeѶóÓhuB­øã¸{ùjô~rÃZ=ûA `fÞrHSƒuËÙvèw; Ö]ºã-4&oC_ØŽ¿õæ¡QÙðþ(ÿoRØÈ{Ú14&O_ün£1?Æô€ @€ 44¦¤‰§\ßê]·Ôu ~½âÏÞx‹‰Þ”£Cõ”À´M'4Ò˜ö½±jÐÃÙÅ$Ðd"œYðb†ÜÓ^¡1yøbw»‘‡Š„Zì¸ûÙ;4&?ãîA¯Ñ˜<2]„ @€ $L)aàiW×(!©˜ÒŽ õC %2‘Š©%|ìT`u'™/pĽì“—a/z§y¨H¨E¼ýCcò1ê^ôÉ‹0ÓI@€ @€@¢ИʼnÊj2‘Š)¡h@Ý„L¤bj {—@݉pfÁ‹p?{†ÆägÜ‹ßëZ µøQ÷²‡hL^†Ý‡N£1ùeú@€ @H–S²¼³P[mB&R1e!.´-¨MÈD*¦ѱ[Á D&™/x¼}ì“Q÷¡Ïµ*ªq÷°hLÝ.£1ùgz @€ @H’S’´3SW8!©˜2V D2‘Š©UpìWl‘‰pfÁ‹n/{‡ÆäeØýètïÄC2<¬ ¡ús{‰ÆäcÔ½è3“a¦“€ @€ D  1%Š;+•…2‘Š)+Q¡h™@8!©˜ZÆÆŽp ™˜÷ ÚvÉà{ÔåŸQÖ˜P=Šºg]Ecò,àþtÉŸXÓS@€ @€@RИ’"µz,!©˜²Ú ¸„L¤bj‘»yAÀ%dbÜ‹x{×I4&ïBîU‡-!ªWA÷­³hL¾EÜ›þ¢1yj: @€ @HŒSb¨3V‘%d"SÆÂBs Ð*KÈD*¦Vy±Ÿ?”‰YpÂíYOј< ¸ÝUB&$TÿÂîQј< ¶_]Ecò+Þô€ @€ 4¦”ß|óÍn¸áꦯoûÛÍwÈø§7Þw쯿(ãlÒ¼K/½ôôÓOoÞþ‰'&ñ=¢¤Aà®g?ÿrÿ‚4j¦N èrÚüz{^é•ú=å'?ºrÆEŸI½j@+ [·nõq0ÑçN ø 1éK1è÷÷k_ûÚ ûø³ƒ.¼ƒ>;¶ÓA—èqsÆÞxà·}‰VIeH’S’´©+AhL ¦*@€ @€€'ИzΜ9ï~Ïß^tÉ•V.tåâ+/ Ê*ÿùÿþ¿Gžvö_1PF]q~½rÞE—Gʹ]^.^~n¥üàÂË+å²\”sjÊÙç_VS.=ëüR9o œyÞ¥åÜKÏ<÷Ò3Ê%gœ[.§ÿà’H9í—åW.þþ9¡röÅß?ûâïÕ”‘g]\*£Âå»g Ê™å;gŽ(gŒúÎZ[N¿èÛ5å[§_ô­Ó. —ožvádžÿóýïÿ o~?(§T• Nùþ#¾þ½÷¾÷½ž|•é¦oz{{<ê˜áÇ8pÀ·¾ÓßTèrúý3Ω¹!wC» ý±«\Ps¬û‹ÞøêÜò"7»È.|«ÜàêßÚÞÔêßËndá[Xó›Wø¶ܰNnXÿçÿõŸO<é{ÁMÊJôVuÁû?øQ™©D“JsJÀI_Šó‰&—={ë ¼Î¥fÔá«Mä1»ùvøjÓäRzœ®sµ©~„nöðylnø´\óyB¶ÇãcJÏÃÚht©qR>ž‡§L™rÌ'>ÃMN¯N4»%hL-ab§ü@cÊ_Ìh1 @€ @ ëИDHÓGùÄŽ½°²=(o¸²mÏ*óî¿]¼|ýo÷¼”Ý*¿ÿM¥¼²ë÷®lÝyÐÊ+ý_.—×_ÞñúæJÙ´ýu+/mÿÝKÛ‚ÒçÊo·1(¯©løM¹¬ÿÍkë_ ʺWe뵕²fë5[ö[Y­òrPVYÙüêÊJéÝôª•*/íSYn¥/(=å²wÙÆrYºqïÒ AY²aOPÖïy±R¯ÛS*»©¬-—…kw/\”kvYyau¹Ì_½kþª*ó¬¬Ü9·Ræôö»2{E¿•Y*Ëw¨Ì¬”=;.¾ú–Ï}é«Ó{¶O_”iV–nŸ”m*ã&-FcÊú%ˆöuD ä0 {aÅ–‡ŸžË„_G9¨mºœ¾¸bCén8pC´»¡Šîƒ² Tì>XÿXsï«{׋Üïìf¹Ó­ÙR¾Í…op‘»[Õ­­öŽºUßËndv ß¿J7¯àþUuçêÝi·­ÖŠà†õ—ýîŸyQw+•ª[Uå>uò÷.@cj{ ú}€'“þ` z©Ù;p©Y´|½žÀËÜ•çí­»~?ð°íž´Ý3öŽªgìòvåéÚ­#ÏÕÕ¡ÇéȳôÀƒ´{ŠvÏÏÕÏKìá¹ê±ywðØ\zf®½ÔèÙ•#ÏÉåKMøj³|ÇÅ×ÜòÏ_úª]jf„ŸŠ+—šû'çàyXÓ§?{ì’uý<Øø}‘+zïјŠaoû‡Æämèé8 @€ @ 6hLÍ4¦oÓ¬IeâÄMÖÚ|­Š&Qõ¬ ÛK¿ ÙKšÄ­˜Â“˜´1T‡é•‡Ió.ó»Q‡i¿›åÕFHc ¦°ÆÔÔa*ÏÄ4ט‚)™ÐpØa æfJÓÀn&¸®Æ4»fJØ9L3KS5e©ä0¡1ÅvàÄ™# ‡éÃG [°bkà ¾´oÂdL¦ÌŨ ’Æ´xÅúÈ=1,òZ2Bw¬² Þ†ònH,pv[ Êžn­¡[ç¾VÏÊ­õq«Ä‚ZiàæenD½5ïV7,4¦B~Òí”'“²»…ŸºÝƒ·ýÍÀžuÆÔèÚu˜*!ÐĘŒüI@Ƥ{T®oL–žƒKMɘ\cʼÖoÓÒuý<ؤ{…¡öØ  1ÅŽ˜ Ò!€Æ”wj… @€ ™SS©X¦¡:LÑTLÎaê©ü)¹2u;S?1æƒ[NÅј\*¦lLKÈÆTäK—·} ¦£‡-ìÝj&b`öí›0i9™¼‰u\“’ „½¥ˆÅkSp §E ç ¬I@É>Ø(ï`ÝTLC JÉ#™#9ëçGq©˜ByëæG)kLO[6¦n»Ô²)ÉÆ”Øè-LEþhLM.5 –Sä‘ÛÒV¶[Ñ%ƒ§ë -8L.³i©˜ú5&ÃSÝÄoÏN8LŸ;vÙú<ØæJEG@cbp”SAK· @€ @)@cj¬1ý±»Eâ6Bü­IM¥„§l#‹Ç…&T´\ÕrÑ L­-$Zó¢´\kÉ5ÊÃÔ5‡)¼¢\“TLnEž!¦b*iL76JÅ4)Å UÇC ì0­ÜªÉT7Û'ïP¢áƒ1™âÎY+¤1™¹YËÉ­wÞE—«„×uðw]AµfíÔÆy˜‚åä­—Zg¥Ôš5R«¬Ü8R1•ò£„5¦ºbÁÔ%hL|»Ú&à‰Æäuk|©y!ИÞÓh½æÅš«’s‹5—tÉ’ÃT½LsÕ+K™M:L›j³™†–cv‹WFbn¶xeýTL•ÄoUÉJK—iLZd¹‰1™eIÓgä0mØÉƒMÛ—È#4¦i[GéÍpíWÍ{…Ï£=¤I5}äfÅt†Ã;¬¶%Vï¨Q£T«±S–×!iL2wîƒvC,Ý í>xîE—«´—z°¡ÀT¹ß5° \r”fÓ`y˜–T¥bªŸ¥±Ày·ñ×ï~ðé¥bj¤1ýÇÛhLQóDc „ÈðSwõ¥fÞ’@cjr© ?i÷é»ú»y&÷\Ý<å[°¨kó$«ÛæºZט4§¥kf»“±ünv°î" ÈÖ7D“ì&æ®ÖGsK¤Õñ š' g ßï*é#wºÚ•RëeFÙ×SJ+d ßÔ*Sw¦ð*¨nýÓÒʧҘƗ4¦ºbSZ#9×õú¢1U„ÈÈǹõìí– nz©©o/ $7máRãþ$À¦AuI—Ç4òülºdÕZrͦæËÉU/µ\Ö˜JÏÆ&÷—ŸŠ³ªõ‡¦î?ؘg£Spô¤!Çå†t ޽cb´%†´¬Eæ?éW=ŸØy&OžìTÌ®Öûa»Ú.).‘¤êuж=äØi%WYKLZ²ýÍ1ŠœSGé}× KHiz–Içö‘9èÚÕd‡hÃÞ´Ú;nÃ:>›5/r6{ÇNâºï.›µÏõ5…Æ£1¥*“ €Æ”eê€ @€ øE©A¼McªU”Ü;š8Ñ$ÊœÅkÂi–”i©*ÙRU¾¥o©‰ºÔhå¸ Es{©:ý’û“ñʤKu¦&«È Ìõ–ÿˆÜ­…ÑúBr Vï’½dÅ9Ló4%Sš•Q)§²XY^#C+eÌÏk±ŒÆkəär‘ecr³5¡O4¦j!2ú·zöÖø/5å¿ ( LåGëR²ÃV]É©tµ©½Ô è’åõ—«“0E˜Ût˜ìÙ¸¼Èr泓â0 ö`£«q+6Nñ±{>qO#î©fÐlLvÍp:TXf²Â“~ kLNZÒŒ-!çòPª=&ˆ‡5&w}²sÚ£Žt+»¹‡4Û¡‰Æä29¹*"SØ·¤˜µgs]Sk];ՆȳbQ.«Éö)YÞÔ–4¦ÄPS @€ @ÀhL BhLG««%¹75‰2sájûµì*U’L˜®TµB\½•,LZФ\Šd]ЍK«šÛK¥?ø{ñªÅãªþjca 15¼ÔÔ·$ƒ›iý´¦›µZk§®äÀBÌ{ÂÓ@¾·JÊ·Ê¥¦j!9—µ´=]²’¦Ôùý¶ÈrƳ“:‡©Ñƒe·Ò:¹C|°qRŽ=̘ m’žsLâÑ£EDcÒ¯zrêe‹4ý(,B¹g•°ßcW§©Fm»³Ù†=eÙu&m;=¨öœúH;kÓŒt;¹=­ÙsZm6&ílKÝYúÕÉ[ö‘ÄZîr>©åµg³§/ÛÙe`BcêÎå©;9Kæ ¢1éÂgKuÚËþÆý©JæzCƒ @€ @È4¦Q0ÉÙHu74‰2}ÁªÜNT åXzvö2ç*ÕJK³_Ü Rë-=õBiñÓª•O¥1ÝhL S¢1µ9Ùý?S“Kž½õ^{© ?o·°"sQòº»CeúÂuîO~ò³;TÂKÈ]{Óí*fÛDþ à±çŸqÞ*åççµ»g-Ýrá•78]òágžvîåÓ_|¹’„©áBrÎõf*­·Îò@vÒ¥Áj•µ%u­?ä0 <Øüjâš«Ç.»õ©5µrö¸©}ö`£ÿãxrÞ–Ëïyññ¹[Z|°q¶fÌÝƒŠ“~ô޶%ú؆~µ‰uKJä1ëHï¸çð¤ø¸3»«’;•ÞÑÃŒö×n–¾È¤%«ÚÞ ·Íš>§•\íj°-Âkga£(ì Ûû¦%ÙI´³m˜3`ÕÙÜ>uÏfMr¹¬¬hLݹ¡1u‡#gI€.áZuñ ÿŸZ3ÉìN÷1&oêþË:D•€ @€ dœ€çÓ£çzúêCo¨’þ­öÃG³ß"ÅM“heÚ «j-¥r‚¥­®øñÏ>xäÑö÷ßV>óÏÇ=òôì@MÐöçŽûÀ‘G[X*îåýOš}Øa‡¹ÞóÞ÷M˜80•Y3.¢.•ü+{­^dÇfyßý·ïÓÏ3Φ^4×{òwÎÒäÁ}Mÿäg¾¨)„r¾ŠHú¥ÒÂU®hÞwþª`2æ}à#árÞå×Soÿ@‹Þþ‘g_¦rçCSÿç‰L3+Ó3¶ŠÜwκTeÚ²íA LšÖ$Í…Cјöm=4îÔC Çfü Jó|#`Ó¢•[À´ª´Ì}ñ¿rÊî[jËÉé÷Éó&™Ÿ¡/é÷þmî—®xþK—??ògs]*¦@c*¥m¸c´AM&ßPÓßZ;^Ÿ3mó ûÞè­ GÓôV5º!êÆwÖy—ª„…Ý[ïžð·ïý¯ºªH]Ò¨¾þæ;ëÜø6ï¿üš›ô~d9'Ýþ¾õ½sœOpćŽ~ð©YáÛœ¾*S^XûcY¡%äÎ<ÿ ÝF¯¹ñvgå꾦;ÝÀ-äãºÙ=LÿŽÒìãŸþ‚4\9Lóž÷iû{ç\¦X•UP;5IE_1ÝÎnÿü€t[ºa™ÆÔ$e _Ãv x¢1éJ¾ÔDž´õì­'ðê¿ ('[ªM¹TÓ´~Ž7»Ãœ‘gŸ}ᕺÔL[¸N—m|säÙ*G|è(»Úhã”ïž­¢ K¿ätI]dþñƒGéAúôó®ÐÆ—Nü†ì%=K¿ÿƒG-X³KåÞG§ë’òÃëǸgæ–’0…V[.¹’Q]²²ÈòW­°<È"Ë¿í=tû ±>ËaúôçŽíÙ°Ó=ØL]²ý„«¦œqËü]vÑí ‡Ÿ7éñy/—LnØsÚÏç]ùë%öc&®ÕƒÍew/>îòçn|xeÙÏŽÿÁÆòuëνԭsrž¼@cÊkä|o·þq,|a´”½z¹Är 5&K(g –Ew¢p.8ßÓ@€ @€j x®1IdÑ?&žÿçµ2“iLk¶(— D¤ìÿkiLóW†-%·­©fÖ²÷¼÷¿j^V3(*ÏÌ\¦m½£4K’–®ÿù#¾zŠ%[úö÷ÎÑ ®Mߪ(ÿ„¦R\ ŠË®&w5¿bS¹Í׌‹¨KVŽ ç¨0©´þÅnËTQk/…Ó/5[?®¤1)wEm¦ðp)CLÿNѼ¯› L;Ü2r˜N5©´Š\Ó"”Ö¢3iïËIqWAc⪘%æ0-”ÃTJNc É•&-$÷Ò>iL?¼o©¾×w>½þËW>/)p˜Öí~jþV9LúnjrTS}L{©’Š©ß Ù·?ˆÉ”¥`g²-Ò˜îê9L¥®Ì$iÚüU5·Â{àÌó.U kºyÝ;áiç[ïzèÓŸ;NCZ7ÁÅk¶éÞ÷ƒ‹®:碫l„Ož±Tw=íI1¨7Uî?Y>)㟚Ukè>ðÄÌ3Ï¿2P *K£ÊÊþO_üä?}ÑnmúŽÈ*ÐÎr¢Ô&4«@yu ĂҚŒº—é׿I˜*VAIcz ИÂ7¬¿ø«¿Q4¦Lö¼6Ê©t%‰>u»gl={ë ¼®±dÜP½`\$¡iðh½©ü\}éÕ7JW²´@g]p¥Ê]ã' ÿì±f/ÿ¯'Ë•¼ãþIÃÿéX»Ô|ù_N6QÒ\ÉÛÆMÔE&œìMöÒn¸Mê’iL¿.Y’úiÒT`*%P,_mÖ¬Œê’ÁÝ<œò­ì÷oël‘å}k—SÌÏÃæ0-“Ãdq)™Ùß¼~æV–ÿ£oßÝÏ®?þÊ祢N[¶íËW<¯rů—èr-nr˜ÆÏØ$\z°Ñãå˜LàÁ&’0rˆ× %grK³ ñTž{hL¹¡0]ÉÙGa5ÓeYj¨1Y.ßp6&[­ÓÎIñä#]ú @€ @€@#hLöÏ÷52“iL–6©ª”&H¬he꼕îת‰“—÷kÊö—w=dZ*M¢hû×=­_e)é_ð­þ­ŠÍà*Û„\%ç-)÷’&nÝÌÊCOͲ'|彿ž¢)–O}öX½íÏnלîOÎÔß…kºE?Ÿœú¢–º°¿WÑD‹¦[”šB&®i]ͲèMº<;o¶5Ëk“»šzÑŸ«èÏÇõëq'~ã¾GƒlLöç㚃ùÄg¾¨ ˜[ï}J‰+´¡_?ñé/êÏʵøNx2ÆiLn>fü¤ÿëˆ ûÔôó 'œ$iäÙ—ªÜ^јnøLÇ|ê .›…ì%m[9õÌKk&›nWczeíÚßÝ~r9Ü1OÛpÉ@»‡é¨a {·ºy>7áê¦ú4Ï'IS}WÝ»dÒ‚WJSy99iL ¸lû'Îôèì-úZ›õ”Z!ð¶ñSÉÉÔn\¼ÚßiLue&iLSç¯,ßC·Bw<óÜKUÂÉËÛ›_•ª;â+§èöçR.éNç¼%MrßrçCº£E<Ý÷üíûî?Yï[ŠAÝÑt³“R ›ÝïÌ^Ò­M·­°R „(áôK<»H75í³`ÍîÈMÓ/ï}êýøˆ².Y*A LA6¦’Ãô7ïù»/žp’eÔêòë~¥»’ngæàêËõ…ãO²[Õ»Þýwcx¾Jº]² É«¯O2õEc:÷ÒðÓud[ÏÞz¯{©ii!抺To‘ÊàR#iIËÆ™Ìd‹ÇéRS*W¨Ø_¸ ¦ö7_ú—oè:œ¾ô‡7ŒÑ£rpÁ)ÙKz`¾ça9L;ËSÉ•´˜Ìõä{+'aªv˜Üãq»ÏÿíYðû›Kày8p˜>{ìÒõ;Ã6êïðó'|»¶ëª®ç™É _‘BªÇ{¥b 4¦5Ƥåä”cRÓÈ›æþà—/ˆLÙaâÁ&™+µtSבrÂø Øj˜‘lLôÒ›¶Øe³EåôqXc’äÃ" –Çß j€ @€ @ oИœÆT-3ékŽóûç\f‰+¬„W”öé/h2F³¿×Ý2.˜’Y±ã]ïù;MÌ|÷ìKULc²µxþí®ÇeZ<2e…f‚õSïØdð?ù¤Sϼ$œ)œÖ¢õi›:SÞ®UÅn¯&]p¬Øâ²²•ÓÒ”æù*«hí•ÆtÕ½KõÕ¶ šö &MKS}çýj&Mø¹UW\Æ‚ ŸYIþÃd*ö@bï"SDf’Æ4eÞÊèm1ðtUWåŒs/QqcØmÈRÒMmÒô¥auI÷>ó–´ŠÓu?»Cª®~ ö`z[w=Ýæl '[ÎI‰—t/»ø‡?µ„(Òp{~ñ¸ÇgèWY?.P œ•û£ŸÞ¦”ß8õ¬ŸÞzÿßÓÀMKÈ•îh¥$‚º£­Ü©UPMcÒÏ»&LU‘}kw1•ǦõêöÌ /ékuÙµ·J½ÕÏÏ’-$g“³ ìV…Æ4ÄÉáµ<јΨ"+×]jžŸÛ«'ðÚKM$ÙR$»Û ÙLKÕ*˜t©‘½dê’]jL` ԥʥF®¤ŠK¿$ÝÿÆ_=Pºwäpú%]gô -WòÊëǸdoQ)¼`eUäê&a ìävµþ:SlÏÃe‡i]äÁæÉy[”ZÒ=ØØZrJ0ùÈìÍ–?OÓ÷,Cý¯Çøé/éÁFy˜T~ñij»,Ç$6\!sI)—a£Ñ°Æ¤ s¦!¹Üu­jLJÎäN$ ª»¹ï @€ @…" )âñðk)3ÓÖ[¿ý©UwŽÄ½ù×ïzÏss{]%·qσOkÖV¿º)ÛÒºÁªp𦕥䤥›ïxÐ2-s·%YAÅŒ%û+p[ÕBÿÄoù–lŠÅÒ,Y‘¤ ]ýtë阺äòRh~W½6ÝR^3(õAoJ` VØY»[³/šz9íÜËU4m ?×êT¶þŤY«ôÓÜÑt¯¦a4Ý«)Íøª(_…2I“1½å¿&×ìï×ýê·¦Z)ÙKý—ÿäV¥_R Íkú!ИκԒ0Íè f]î¥Ã;L3ÁúÕ&ƒoºã1iLVäiEcúäßÿU4##Ðû/‡yÔ1/¬Ø¾˜¸,¥\ûlÈ’Æ´ÄéÒ˜ÌaúÕĵ'];Có£ú2~÷¦97LèÈXPZåÊMvšÉô÷ü/7ÏùO&©P Ð -3wÔð¿–=ÐD8ý—¨ÔÞuû»ûÁÉ2™,¹ mó–´`œ2 Ú¯”uioxÍ8ÝÚ‚T(¥»ž$ÝüÐQ÷?1C?Ÿ›·ÆL>Kˆ2ö±î§»›³rÇÜ71¸ÙMmM à†îhAN˜ô¾3q•‡I Þ·[˜4¦pAÝÂÜÝJÛJ¨bÒí¿žrƯ©l 1êQ9KñFcª#Dºk‹ž½õ^÷RãR™ÖJKöŒm·Ôȥƞ®]*SY5N]¸Ô”®6îRc®d9ýÒšÝÊ÷fÐ&ߨüðú1z~V&]atyðé…Ú?ya‹“[j¹j¹ð"Ë%W²uIÏÃÑ Lq> Í9î°c>ñ™%kû]˜ìÿƒtñ×_5 ?o’]ê-Ù•hëyæáYÒ˜‚ ¸&%aCý¯‡&eiÒeY=ýø¹¦š›ÿ÷ƒ΃M+wó¶ö™°æ½oÿéÍ,]óß4¦üÇÐÛ8ûHÙ”ÜB™ZoN¿ŠI«SxE:åq’ å-P:@€ @€À æÞqèçÃý-ÿe}‹ë'G¬ÿ‰UV©H¡¢I”gç®'R²íË®¾QÓ±¶è[° ÜWN)[J%)–JS)×þìýúÔ´%á9•ž’±¤¹[›Sq3+JAüuø†àŸûµ!KI³¹Ay|ÆÜž Á’M´¨È[Òb:]õSû›æÛÆMÔÊqnºEÓJ¶dê’–3BÛúi“¦ 4㫟ÊTL«vZ¾ [9N“»NfblÆ4¦ðršôÕÔoyEŒÒ”k!9å^R ÍûêO¨å0©Ü6>Е\ ÙKV4üG|Ø&ƒo¼ã±oMczßß¾{ï“?}û‚¿¨èý½¿ƒßç/~Æú~àºaÃ?ô?~z®»˜„sÒè",$WIW0zü ûjßåó&ÙŒéew¿xÙÝ‹mmšŸNèýÎMsl99i‚úŠI Œ¤1þ¥÷_ö/OoüÔ3}Ã)pžXDÝ Î±½Þ³ãê¿ÿ‡*s·ú†ÜûLc ßu7t·?Ý u¿«¬xKºK^ò£ŸºQu#S®A7±­›]ÉÐ f¸ï¸¢Ô[s•©ô-ØSºÙÝ %×|§œ~î¦èîví÷ŸtêYúš¸l‚n!TÝÑdw´Š‰+I÷/»‘ÝñÐT[<®œA°¤ÞJÀÕÍë¶‚rêY—ªAéô_Ýÿ|Dº%á]'à‰Æ\Ijžº¢ôìœz_jÜu&üW•§ëŠ·z®vO×ö\mE¤2]¤2Õã´e6u—š«z›ŠV^¶Kr¼ýè†Ûì)ZEKÈé™Ù&Sÿ?ñé/\uý LºÎXÖR=0k»þr¡ LN`²;xvÈJéR$(­Ö%[_dy÷³w¼uÉ{ê?ßvü¡§¯îb9ðð¥ÃüŸîÁÆÅÅ‚"'û®gÖ›À$Úã¦ö}ùŠçíÁFHå0©ˆ¡®ÕÒ˜Œ˜ŒÒc/{îÉy[=ØüÓñGM[wã²í×ènEé =è‘àõ?níúuÌë¢1yþ|wÞiL£K/ëÌøñãMijUcÒ®R—¤>ÉgÒ‘îDùfCë!@€ @€@× Œ;5ú¯ù?9âPïDÕ£Eå>tÔ1ÑyË™T)šDyfΊð”‰ùIî¾+é%þø[óµãŸš)WéÎ&i‚V?%-©Ì[ñJØX RPT¦Ul×RPØäŠ[!nNÏV›Ð•¨tõOo×\‹&tµ}ã˜ôþ¬¥[LZÒ¼KyÁ¸Òô€å¥Ð¯þvÜ–½Ð$®æ]LcÒì‹fb¦-Þ¬eã‚©—’ºtåè1š€ý‹q¶àÎß¼çïlRAkîhVF“¾®h–÷އ¦Ø¢Vôε7•Q¡ŸÒ˜ôgå–ÁBsÀ¶xÜ1Ã?ÉoÕÜŒ&efÒÒWÿð¾µ4üÏ_Ö²uCÊÆô®w¿gÓö×7¿²§¾Ì´pl×Ç'„@80|øð “ç†sE¸k‚&üî|zÝü•;å-M|á[Å&ø.Ÿ7ÉfLo}jÖ[™¶d»¾•A6¦‡VT­ºšòT³¿z²¾*Û÷þáOï¼ÓAk9¤¨j•3éoP—µ¨ÜÀ-¯únh÷ÁÓ~pÉiç\¾ JT’°«Ië’¶{”Òo Ã=9Sc[Æ’o*KKòwCª®K.6te,)]Ÿ/iC‹¢ê[ðÌœÕÚA?¥1év^ÎÉY¹˜tG{è™…¦äÖÞÑô•‘º¤$‚³{ûϽl´¥_ ndN±•O©¤ÞÚ¨ºsÉ*8û’ëtçúÙÿÙ8w£Š»m…M&4¦¢~SRì—'“.&MžÀŸ™hLÕÙ•Ü“výLKîRö–ÂyL%-ézbËÆ)å’þ@Õz–¾iÌZ-NfI‹ÇÝú€Šý€Ë½¤{±®BzÀþå½OêùùØß0{Iº¿=9Ûc³®6_ûÖ™î™9HYº<0þËÏÌ|\Z1­e©õlLö<¬R_fŠáy¸ü`3©ÎƒÍcs_ÖóŒ²K>:{óͯÖöm“× bKZ˜&ÉÙ–`räMsõT#Ïéêû–}íÇÓ–“ãÁ&þËîþhLÝÇŒÆÔ}¦œ1!Nc²uá´"œeVÒ¿›©ƒhLò–üI÷=9_À*÷>9ÿó_>©ô—åÛ?6üóÊÀ¤Ÿ¿~|ž¦dä0i[嬋¯SÊ¢rnÚÆÉLº0”™)†i›Ü} hpFT&üæ„Ó°Y®Íó)QÊ•¿^âòÍè»|ÒOfXºÍ•^z×b™LÇ]öÜ%w.j´êJØaÂdÊHÜ3ÕŒ°Æ˜¬‘Ò˜J·¼è­ÐÝO;çbyºn ë~7_ôDcÒ•¤ÑuFW˜É³Vè <Ÿ—šêôKã?X(­Í L‘µb;xÞµÿÍà1øò÷Æú<ÜèÁÆþï¦êÁÆœ°&6¥Åõx°Iì’…Æ j4¦X°rÒô  1¥Z@€ @€@¡Hg)-!Wû2©VHªäL 2'ieÒÌåUZ’S”B~R#EÉM܆D¥´uu¥r"–jcÉ–`¨*-zK¥$.UÞ’ì¥ÞòÊÎ^ªQ—¢s0ÁÔoåïÈKöÒÀdÌ€½40û;T{ÉÍÜt¦1Ó6z½õf 3­R¨ñLgb&ðÆÞþÉ#‡©¼ö›¾HU/=7~ñ/F ½~›ðÿÔì°ÈèæùÊ_öòT_`¦Úaê/ça*͆NSª³ŠiÑÈajd2õí뛼qòлÃòE`ß½n ¹Ú–Kcš…Æ”¯ñŸ‹Öú¢1}qõÚÊå|¥vyѳ·žÀ»x©¸Ú´{©)=H7%뺒µé—:s%;ÎÆ¤»ùyXã^2Sƒçá®<ö´ò`SÎkUÊœ×TÎîüÁÆ}ÁyÂiñZ‡ÆÔ"¨övCcj{ç†SnBEC!@€ @È;iLüÈ1áÕmj·5‰2qÆòæûÔ(JU¢Ò€«T])ª+É[*ͬÔ1–*kèDçtKÐÍ·T×[ZYã-ÕɺTO]ø#òª…04SÏ^*Íþ.­Zp§õÄKu÷’Æ”÷JûÓ ÐÄUšwíH}Ú•FiÂïcÇ|â'g—¯¦-VlE·~M–—ª©ÎÃTv˜*_·æ“™Lý¯þ!Üøa÷ ëéïéJw8IaHcj~Ë3©êžXå*Õxº¡œ‚õ¤¥*C7|«Ÿu)âTßÚœ[^uyý ·t «£´ÿBc*ÌàÏNG<ј¢W’êå&u!ÒxÓKM° ¥•HúRËcZNíV~®îê¥&"J6X<.z©ÈTÚÉ£r|ÏÃÝzì l†Ul\ìÁ¦’„)È;èƒMkr¶=Ø xZÕ_`žpZ¼ ¡1µª½ÝИÚãÅÞ¹!€Æ”›PÑP@€ @€òN И>|L Éæb÷hå©é=n¦$²Q^ú­ÆOj¸\ÈUª«+Õ® WþÛå²±ÔPZŠæ[ªñ–ê­¬N¥Õâ" ÆUg]*嫈Lú–fb¬Lm?wE[bS|Ó6y½´?šÌ{dÄáJŤ ecš6j„Šì%«ËR4Õ¾¿âÞѶçÞõmXA{÷íÿè1Ÿ÷ĬˆÀTZo%ÈU0øT_;Óö½ø·ßqÐFNyø­‡xd„ÞÑöèù£µ=fé˜ñ«Êž–}¤|ÚP5½ i¨âçì.iLOM_ÞÄÍyÖ(•*{ Á0² jé–M+ØÄ[Ь…: %¢.…”ܺ« º„(ÝU Ü ©»#³‰€'Óȳ.n”©TW={ë <ÆKMéV[»ìrË—š†iÞê^j:ÈôyZŽéy¸³ÇžWæM¶ÇžˆÛýêþš˜=Ø(Õkéï%ì4Œ’Ë>uâWO6W©Qу͟Þx°i÷ Çžì!ÇÛ+S,¡GcŠ+'MŸSú1 € @€ xB ¤1},¬ÕnkåÉi=îýyY÷wÞáJ:¥FI•ܪp‘¹[÷kðýMŒ¥J¦¥ZiinoxI@Zª›o©â- ®.U’UD².% .…gnbš¶ñd„ÓÍÈU2Émh!9‰JzG†“~jÞNxÚÞ´öÑ1úÈ<'¥CÚªÑL¦±ÏtþbyJÕÖ¯)-þ¨/r g yª/ì0©‘ýû•«@•ä3I`:øÇƒšÉsù™ìS—Ï@S}Îpj«ìœ/Ҙ·¼Ú{¢iLun…¡Û_­®¤{_í]/t¿«– jR.EB ßÝʉ—ª³¡Ø¼¸•ºn\4¦|ð\´ÖiT“'p]ˆôžÀ¥&òD]wyÊÊšqeû?Xg¹Rš‹’ágæ¶$þÚã{n÷±gGÏòÖU´¡5éÂ_+3™ÜƒMD`*?ØÙ%»ð`S×ajý GÏ<ö`£G =ääââÐõF¢1uipB4¦X°rÒô  1¥Z@€ @€€'¤1}àÃsK¹ÕÝø«¿~÷ãÓ–9ýhðÒŸ7/u]¥Ì•D,šY±þÓpÛŽKµÒRdÆ%*-iö¥2Å[™€©J¹ToÁ¸à/¤ƒRYëaˆó1-ß´'ƒœn¶KÀ\%½¤%©X¦%éJÎR’Õdéšl7í¯)=Û¹])¨¥d2ÝûØÌ*©j!¹.LõE&Õ«©;›´ ÏÞ™º¤×œ­s,9“ö‘ؤ¢ý•±©]˜ìŸ;Ò˜ž˜ÖS{7,™IA.¥ïž9J¥Ñ­°C·l,UÝòêÝ隈¹ƒªKA6”¦+ÇuñF†Æ”»Ažý{¢1éJZLÙ®09Ûôì­'ðü]jªWŽëâ:Ëñ=·ûØãŠôØ#»6¥™Lö`ãRKV¯ÛoX`šŠX÷ò0Ù·»•'9Ü&j[ñ6!S,w4¦X°rÒô  1¥Z@€ @€€'Lcj®ý¥4¦©Ë5“–~«J§4°bEtéŠW©®®T›cÉfv#™–j¥¥Zo)ô÷â–£¢·TY0®”¬"u‰lLž|3ØM§"ÉR’“äì%½o‰—¬Íò–4g 4ÿ§÷]é Se“éÑ™aI±ü¥®Ìó¹©>ûV¶µäJ­Ã¤Fj‘8YJÚ¨$iI.?“}*iI3|¶¡¢ ÛW± Hcj~ËûΙ£T¦VªÉ&ØÈÐè¹ÍÝܰ·¹»U¥Bi°þi¬÷24¦b#Ré'SÝ+‰»¶èB¤'ð„/5•Çé: .‡Ÿ¢-µë¥&&©ÝÇ}#Â=»•“©ökR6™Z°©ü„ºÙñZr®­<áØZºö„£bOD¾Ð˜b :S,X9iúИÒ-€ @€ @ÀÆtäÇæ¯’lÔ°hå±)K„Ôh#økãÚRI§Ô(©Ry·´tTÝR«+…Œ¥òÚu2-ÕI¶Ô¦·Tñ$ZÌ™ßn1MÛx2Âéf»œ«äÖX1QIçQÊÙKÒ•4ig§µ÷õÓæðt¬û¨ÝzÍdºç‘¤¸"(³*‹d•¥ÃRº‚p:´§úê:Ljž[-N˜ô޲X6&­.§eæô«9LöŽ>ÒÏvûÅþ¹# é±)Ë܃DJß9ã"•ð­°ù½¯6›`d…¸ºnno©:•`MÖ¥*·”A0æÛSîyöì‹ÆtƨšKÍ@¶6={ë ¼þ߸çíÐcöP/55 SF²–6U—ÊÒ|Ã:sLÏÃ<öèICú5OBi&SäÁf SÉ:íìÁ¦ÑZrî«ÝÊŽe´CäsOÞ,ìá )– £1Å‚•“¦O)ýÐ@€ @€9S^ÆvŽÚ鉯dW’FEÏÞz¯ÿhØ¥¦6Á[(™Ø¥&¦çá{^™7YÏE.'e“o–™Lw•lœÀ¤ƒƒ͠S‹O8¶›o,ñdŽ®Ým*Swy–φÆ VNš>4¦ôc@ @€ @ð„€iLÍæHzé‘ç–JEÔFj˜N©’^Å’¬„Keî¶”y¥2}[w7ô¯ÿQc©vy¸*iii @D¥%%¨¨,ߨLgÅ4mãɧ›ù"`&Ó]¦›•h&b)WÁÀBr]q˜ò……Ö&I@Ó#Ï/Þ7(ºÍ}ûô‹TeH­ÔàÆWk, *-Eîqeo)ñ¬KnahLIŽOOêòGcrIIí NÕöðsKôÞÅK=H‡KäZ¿Ô¤òÓçá²ÉälL`êôÁ¦‡É“«D·º‰ÆÔ-’UçAcŠ+'MŸSú1 € @€ xBÀ4¦ÈI)T4‰2á¹%µR“wBr’ü¤:ŠRQ)˜_‰¦V2oi{]]©nš¥üJKµóÄ9¶ñäD7»NÀL¦;&L+µ«&¦®ç„Ò˜‚[^õ}pà×e©µ;ààznm*ÁÚ;]o)™ rŸBcâKÔužhL"£—šë?áÙ@cjt©©~ÒŽïR“¡”¥ù}6“鎇†ú`ƒÃÔõKNˆÆÕChL±`å¤é@cJ?´€ @€ OHcúÇ#?Vc™{T.šDyèÙk³%™Š)µê]çú–RÙUª] .ºtNh:ºR~Ò,µ˜œ)¿Ó6ž|‰èf× ˜ÉtûƒÓ¦Ö|‡¾–\×[Ë F@ÓCÏ.ip[ \o~¡J{·¿nnÝû]=i©bdò‡ÆT°¯@ºã‰Æô­Ó/ªc#YvÒ;ôì­'p.5îi9×ÏÃf2 åÁ‡)¦KS,`јbÁÊIÓ'€Æ”~ h @€ @ž4¦}´¹{¤I”Ÿy±®Ô mRdÑ·ê\JZ%ª´PTÝ20}[í*ù +5²šr=mãÉ÷ˆnv€™L·Ÿþ^à0u3'¬% ©þ-¯²Ó·N»PŶp,ÝòêÝõªîwy^ü‰ïQ× ø¢1Ù•¤AÑ…HOà-^gÊYÜ }©Éûó°™L=Øà0uý"ãNˆÆ [4¦X°rÒô  1¥Z@€ @€€'LcªYÔ¦ÊCú iLO/¶5ݦIl^¶±±”¢~R¥T_T*ežÈ¢9-fNŠc·¼OÛxòU¢›]'1™p˜ºN˜Ö%hLO¿X}[,ßþì&øÍÓ.T)ß» Öu• &æ¢1ñUê:O4&]I*—šª‹Œ]jÆ?½XOà­Øà0uý >!S,xјbÁÊIÓ'€Æ”~ h @€ @ž0©61RxFä/þêÝ<½¸¾‡d6’J%“DíÆÔ¥Z Çʶ:Å{KiPó©Ó6ž|›èf× 8“©Å©¾ÿxû®·úF@“ìú‹™–îw§|ÿB•F~’» 6¼÷-Ù6èe?_; 1ùöI ¿¾hL‘+‰{¨.mèÙ[Oà‘U&?f׿ï¿ý÷ì?Ëd:úcÃZy°ÁaJàò…Æ d4¦X°rÒô  1¥Z@€ @€€?d2)'“{=õô´.\n»çÁÈ;üš$±&Þ=î±æ5N›Û“ýi¾Sô´»¶mï—¥ÔDcÂaê.pÏ϶uëÖð=qêôY‘˯.Ⱥ,'yÈx]­<$¬}y“ç߬¶ºïƒÆôæ›o†/5Ú~|ÒÔÚ«MÆ¿þ 7oÐçá¹‹×æâyxÚÚ³Öþvyó¦¶.ïŒÆÔ1ºf¢1Å‚•“¦O)ýÐ@€ @€¼% ,>ͳžði.ÉÛ¯p!;®Ä-L&¦BF<;úÿ¿‹k~îI6¦ì ò ¶Ä©{sa7wßñŒ48ƒÏÃo¼µó×+þlê¦Mlp˜».¡1Å‚)¬œ4}hLéÇ€@€ @€ à-4¦ŒÌ» ±œ¶ñö;EÇ»B ®É„ÃÔ¶œ¤ 4¦!ÞŒŽÆÄ÷® 4¦˜¾wž6ƒÏ˶WÏa*{~ß[k2é¦$/hL±ÐFcŠ+'MŸSú1 € @€ xK©s<œ¶ñö;EÇ»E b2á0u ,çAcJþƇÆÄ÷)B€lLq\ˆ²öÔ!€ÆÄ°€ @€ @€ @€€wИ¼ ¹gFcJ7àûÞèUê–'Ö‘nÛ R;SAI7¢И€ @€ @€ @ðŽ“w!÷¬ÃhL©|ÚæêjL[LL½mEhS¢Hê@cbX@€ @€ @€ @À;hLޅܳ£1¥𺠙HÅÔµ¸ 1u %'Ê4¦lŃÖ@€ @€ @€ @ hL @¦Š  1¥ßU]›‰TL]‹ S×Pr¢l@cÊVmiP¦e›ÊgûÊØ±ccÌõO‹Æ”(n*KŽSr¬© € @€ @€ @!€Æ”‘@ÐŒ˜äKcz|ÒT'-ÙÆ6•’·¤ró­Æ4ˆÀ´ë÷USlÓ+“d¦*éåÆTÏa 4¦’ÃÔ\cZºÑ9Le©ÖajQcš¿ZS 1SDcêÝ9 1•¦æÓôŠÆ8Li SLßcNë#4&£NŸ!@€ @€ @€<'€Æäù(|÷ó¥1=6qª“–².•/½ñó_Þ)©nú%åaröR9 SiG9 Sçy˜Zu˜ö»_Ó#OM [J‘í’Ætr8ëR9ñRT]:ørÿë/ïx}s¨(ñ’+/mÿÔ¥{iÛïúBÓÆß¾&uÉJT`zåÀº­kɹ…äÖlÙ¿Z¥ÁZr-æaj×ajq9¹*ËÉ•W”[Ùj*¦™Ëw”KÏ L¥²ÝiLnE¹p*&Ó˜îºçÞ?üûÛ®üû[oÇû5;í°CãN· Î4 1¥A:!@€ @€ @€ *4¦TñSyìò¥1=üäóK)üëM¿4¦-i)šu©V] å^ ¯N¿˜œ½4¨ÀÔ, ÓËûWm~Õ­%ç’ÓÆŠMûV¼”åVúöõ”ËÞ„¦ËÉÍé퟽¢\f­¨¿œœ4&-'g“s˜¦-Ý^Ö˜J©˜Lcºñæ;ÂÒ˜¶ãåhLñòåì©@cJ =C€ @€ @€ @ -hLi‘§ÞdäKcšðÄó&'Õ–—ûÞtËÿòµ“µ$[ª‘–,÷RD  /Ur/5²—Âé—:˜”‡i••ÀÔ, SµÃ´,¼–܆½KK%XH®ÁZræa²Ã$i@cZº}ÀaZZv˜Ð˜’ùRS‹'И< 4Ý„ @€ @€ @€À4&FC± äMczN‹Á…Kxa¸o¹ã_¾zr£¥âL`ªï-iÙ¸•ã~'oÉJgé—ÂKȵ.0µ“„©ä0­Ê‹•²xÝžRÙ½Hem¹,\»;(kv/X³ËŠ–seþª]ZH®¼–\7&Ó˜‚TL &4¦b_Lè]ÂИNu€ @€ @€ @HŸSú1 qÈ—ÆôàÏmRF%+%-)\´ZÙ‰_=Ù½S6–BÉ–ò-µà-•/ýæµõ¯eÝ+Êeë­çÊš­ÖlQÙ_¶—¶ì—º4`/µ©žÀ¤åäöº$LK7–30u„©®Ã4µ¦Ã´r缕;çVŠ–s¥Åµä$0Y 4¦ÆSœ_eÎí4&ïBN‡!@€ @€ @€ €ÆÄ(6|iLãn@Nª^NŠÒOo¾ýįœ¬¨®TÊ´¤²q ”ó-ER.…׌«R—ä0uÉ^êÝôê •—öYYn¥OÞ’+­ LJÅÔI¦ÀaªJÂ4à0õî˜zûÍašeeù•™•2£g‡•é=eI“ò0™Æ45(ÛTä-EÊgûŠl³ˆïWì´Ã;5Þ*8;Ò €Æ”uê„ @€ @€ @€@ªИRÅOå±È™ÆôØsÁêoµ¥d)Ýðó@c ¹JËÃÕ.g Æ­·RÊ·õ–šªKíæ^jd/…¦½=»/0…’ë0 ÓŠ*ifE`š!©â0 ɕ֒“ÆTv˜j&ó™Ð˜bÿJS7И¼ 5… @€ @€ @€@…c¡Øò¥1=ðè³&$Õ9I×ÿÛí#¾ò ó“jKÄX*yK•uâlck4å’VŽs Æ5[6®ñÊqe{iSuî¥Æé—´œ[BnɆ½K6ì Êú=J¼äJ‹˜š L«ªV‘›Û~¦Àaª,$ç& L%iÛÔS±/&ô.ahL §:@€ @€ @€ ¤O)ýЂ8 äKcºÿÑgÃ~RÙLª$U-é_¿áR+U6ª]¥ÆÆR -5õ–VKWreóþU›_]Y]$-¹Rgå¸Ö쥥!{),0Uì%-$·{‘ÊÚrY¸vwPÖì–·äÊ «w¹2UãUäV¬"§åäl¹ÊBr’0 ,$ç&·œ4¦Ú…äÂï)Îo3çö‹À Óøñãûúú ÉÁƒG5räÈ9sæø‰ÞB€ @€ @€ @ XИŠOz%/iÜ#Ïi“”ÑÿvÛ ÿúò§õR+ITrEÆÒì7žúýsNüê)·ÞýK¶¤w>ó¹ãn½ë!IK*OÏ\6â«§¨h#ì-Mž±ôG}ÙÕ79oiÆ¢õGyôÄéKV¼T{©oߥ?ºñ’ÝØÓ·oê‚u=}ÁÊqÃ?{¬~†s/•쥽_þ—“~q£ôKN`ºèÊÞÿÁ£T.¼ò˜Ž;ñ?»°y¦ú óVîœ[)ò–\i&0-ß1£²œ[EN©˜ÂI˜‚ L¥$LhL\b ÐERÜÙ¤$ICÒ;ýýýöf3iòäɇ~xOOí:lذ1cÆèWmè£.6‘SA€ @€ @€ @I@cJ’6u%O _ÓØ‡Ÿ «H‘íë~hLöf%¯RtU¸ðÚpò®¸æ¦G&ÏÖÆ½ž–´ôéÏwù57=lï<ô´¼%mü⮇T´¡ÜKNZš0qö{Þû>½é².]võ’x|jÖòRÖ%yKVκàJ•°½tæWÊ[²âVŽ“½ôÓû_øÈy—_÷„iÁÆe£e/ýÍ{þN?¿ú­3¿xÂIw>4U?Gž}™¦w½ç﮽yìÏï~âñ™L—]{ëŽ?éöñS~pÉuÇ ÿ|‹“ÉLhLÉ…©±ÌDj¤1ÉpÒ§Í•ÓÇNc²m©OsæÌ‘…ÆTÈC§ @€ @€ @€Þ–À„Æäí5„ŽÇG ²¨ÜøÒK&’^ª´ I{['•‹/Zœ€ @€ @€ @ @cJ2U¤H _Ó=>]×F²7,éÄ“";”— ƒ ü¤ÚâR+Y‚¥å}ûTlÛò*•Ô¥òÂp2–¬HW2I?ŸŸ¿vø?+iIÛ÷?!©,-¹¬Kgœ…Šì%K¹¤RÒ˜vëW·fœt%˜L] — ®¸Á¼%•“N=ëûç^>Õ.­g‹Ç]yý§.Ùâqóž÷)ýÒ×¾u¦-!gê’~*ë’ì¥àgiå8+Ò˜ô޼%+Ÿ?þ$ÙKç\r¶ßõî¿û×SΘ¶tûÔ l J)åR“B6¦¿ËT]<áÄI}}}ÒÆŒ#“iEå D8“ —v«Ó=‚ @€ @€ @€@á  1>Äžw0_ÓÝã'×U‘ìÍk~ú+iLn·\t£$*M[°N¢’eWºùŽmû=û>K*J­tÊwϾóIÃ?{¬yKÇÿëÉw<0iéÆ Ç’ÊOÓ’ {/þáO¿ü/'«HZR.%­ç¤%—uéŒó®P){KëvK]’ƤŸr•ÆŒhkÆé¥\Ò;÷>:]+ÇýôÖûÍ[’Ã4ýÅ—µlœ©K¿¼÷I¥V’½”•;•uIÒ’Ô¥R¦©æ-IZºkÂÔÿuÄG¤.©Ü\Z-nÖŠÒ•ä-éç3/¼¤G§ö*ý’r/)Óôží²—”I嚟ßwï“óe/MšÛ'“©E‰lLž_Iè~œÆ¤5æ$0YZQN«Ãi£lLJß${I2“ܦþþþ8ÚÊ9!@€ @€ @€  1%™*R$;ɲ%Õ-Wßð«/x’[÷­f#ð“Ê¥d&IQ’œ¤|KRˆ~~ûx½#uIïœyÁ•–cÉ,éM• ¤¥=å²~ÏýÏ´$QéÙyktøíã&j[ïŒ}lÆmã&êyKJ¶èJëvŸ~Þ*ò–>ù™/wâ7f.Ý¢÷¥.YÊ%-'oÉ–ŠÓšq¿~dú„gjCY—¾þí³Þÿ¸ÄK¦.}ýÛgJZúÞ9—}íÛgÊaºâº_I]Ò;R—¹—†}ê Z-näÙ—Êaºöæ±&0éçe×Þªw¾{Vðþ¥×Þ*{I_9åŒSKïÜûÄüŸÝñø?ñ‘Sϼä_O9ýcÃ?ß<ýRäS²1¥ø]¦êâgc’€$ I2’6¬§ƒhLJß&"õÉì'^€ @€ @€ @€@~  1å7v´¼ùÒ˜îz`’[Ö­vCÓq#¾Þdû(Ȩd¥”TéÇ7ÞnÆ’Š²+=>åÅkn¼ý¹ùkci}Pî7Ñ,¥Hyô¹Å¶BœÔ%eZRyä¹E’–¤+=òì"­÷ÌœÕÚP²%yK*ò–T”lIY—ì§\¥[ï}ʼ%˽ôÐ3 -ëÒÄY+•xé™º¤b ÆYyrF¯ì¥[îy≽ºÔÛÿÀÄ–{IËÆÝñÐT-§rûƒST›Ö+{iFÏŽÛÇOÑO•ûžšÛÏß÷ä|9LÓJeÌÏË^*-¬7áùå·Þÿ¼J[“vFcjåKÇ>h‘@OOOxO­~g©Å:Ø € @€ @€ @È4¦‹¦v@ _SxY7ÂåG×SíûNQ’¥4QÉR+•D%+µ¢’½c®R¨Æ’J`,•¤%W‚åá\)IKr•ªJÉUrEÓ=L7o©*åR=uiniÁ8W¤.™·dêR©ê’Ф%WÌ[²b+ÇY1{)(eu)°—TÚõ–ÈÆÔÁ—ŽC ÐhL]ÁÈI @€ @€ @€ 'hLyŠmmŸ@Î4¦û'6ñ~8úViL­˜IµÆR#W©®®$o©ÖXTZ2{i¾JÅ[ºàòë§.Þä[ªë-­Üö–,ëR»êÒ ©KµöÒRg/êÒÐí%'3‘©ý¯ G@ ChL‚ã0@€ @€ @€ ä—S~cGË[!/©îânÎI’Æt숯×I Ó)U%UªÎ«d –ª\%ýZJ°TGW*¥\ §YrÛaiið|K5ÞR .UR.µžu©¾ºTJ¼TɽT²—– 5÷Rmê&4¦V¾tì®@cê FN@€ @€ @€ <@cÊS´hkûò¥1Ý6nbÔ=r‹»­Û}åè_{Â×k×z ¯ûV¸ê•àš¸Jt¥Pš¥z+Ä5H¶4··Y¾¥æÞ’– /תº4äe㚯:‡ÆÔþW# Ð!4¦Áq @€ @€ @€òK)¿±£å­È—Æ4fìÄh†¤PΤ+¯ûåOøzÝåÞ\"¥F¹”ä' ”ÒêoJ%ÁÒ€®¤4Kå…áBËÃÍ[¹sn¤ÔHK‘uâõ–föt¨.Å‘x©®Ï„ÆÔÊ—Ž} ÐhL]ÁÈI @€ @€ @€ 'hLyŠmmŸ@¾4¦_Ý÷T•ovÖìºBÓñ_«³CS-)¢+–’Ê*+;Ã¥ÊUª$Xª£+É^ªg,5––úg­Ø1kyP”c©ª4õ–¦k8W" ÆÅœu©QN&4¦ö¿‚  1uŽÃ @€ @€ @€ _hLù-o…@¾4¦[ï}ªIž¤+~òË/ÿ5·CYH2-iÀLªã'™«µ”B¢R}W©±®Tk,ÕfZª#-E׉Sî¥íÓU– ”zÞÒö©K·eɶæ+¾%ð)S+_:ö@W 1u#' @€ @€ @€@ž 1å)Z´µ}ùÒ˜~yï“‘ IîWIH—]û iLul¤°¢´r§œ¤p‰.ýV³ÜÜÞ~iIÊìÞ~)Já2k…²+Y)çXj-ÓRi©A¾¥ yK5 ©ý¯ G@ ChL‚ã0@€ @€ @€ ä—S~cGË[!/é¿~²‰u$éó_þÚ Z’YJ½*Íä$'-–R¨dÒR«º’Ö‰‹® 'c©%iiÚRKi)ù–š§tBcjåKÇ>è 4¦®`ä$€ @€ @€ @È4¦‚¯4?¿‚ïPGcŠ—/gOSjè©€ @€ @€ @i@cJ‹<õ&C ×S2ˆ¨%ßИò?Z߃€ @€ @€ @Þ@cò.äžuɳ€û×]4&ÿbîIј< 4Ý„ @€ @€ @€À4&FC±  1;¾ô И Xº@€ @€ @€ ÆИÅ&€ÆTìøÒ;4&Æ@Q  15²ô € @€ @€ @  118ŠM©Øñ¥whLŒ¢@c*jdé @€ @€ @€@cbp›S±ãKïИE%€ÆTÔÈÒ/@€ @€ @€ 4$€ÆÄà(64¦bÇ—Þ¡11ŠJ©¨‘¥_€ @€ @€ @hH‰ÁQlhLÅŽ/½Ccb •SQ#K¿ @€ @€ @€ Ѓ£ØИŠ_z‡ÆÄ(*4¦¢F–~A€ @€ @€ @ !4&G±  1;¾ô‰1PThLE,ý‚ @€ @€ @€@ChL Žbx¦oøÊ]?-vé×N;ìиS½&@ç J© ¥[€ @€ @€ @hL‰Ñ@ ÇИr<šÞŒã€ @€ @€ @Þ@cò.äÅíðä“ûöõ·ô õ 11. J© ¥[€ @€ @€ @hL‰ÑQ‡ßzxaúBG Ð*4¦VI±_Π1å,`4€ @€ @€ @C'€Æ4t†œ! F<2BÓÈÉ#•iÔôQÚ°bù™úök[úU{ªhŸ,4›6@`¨И†Jã3J)£¡Y€ @€ @€ @ˆS|l9s’ƯofÒ˜¥c†Ý7lÎÖ9ÿxÐågÒ¯¦1飞þmèW’d © ±@cŠ+'MŸSú1 € @€ @€ @H˜SÂÀ©.&NKR¦%ó“”IÒ’U'ÃIz“Šv“Ƥ¢}FÏSc8-’#€Æ”kjJ”S¢¸© € @€ @€ @Y €Æ”…(І¡±dëÇ9uI¢’e`²7¥.é§|&ÙK*ÚPЦ¡×Ë 24¦”@õq@cŠ‹,ç… @€ @€ @€@f  1e644¬-ný8§1™®¤“HW²OÍaÒ†Ö›ÓnúÙVì ,@cÊbThS 1u"§€ @€ @€ @€@¾ 1å+^´¶‰J¶`œËÀ4yãd¹JZcNkÉé§´eæ´­Ÿ¶ð/äžSîCHê@cbd@€ @€ @€ @À;hLÞ…œCE"€ÆT¤hÒ—4&† @€ @€ @€¼ pàÍ =;®¶2móñwõ6gë·Ý;úÔ t€@ 1 ˆt¡4&Æ @€ @€ @€¼ ðöŸÞ¿ê/e/Õ½¯O½ @'!€S‚Hê@cb\@€ @€ @€ @À«wÝRWcÒû¾  Ÿ~èé¿æ•×&ùÑWzé%4&/ÃîC§Ñ˜|ˆ2}„ @€ @€ @€@@ nB&R118ŠG@ºÞÜWN-^¿èÊИ %€ÆTÐÀÒ-@€ @€ @€ Ô#P›‰TLŒ”â@c*^LéQ4&DA  14°t € @€ @€ @õD2‘ЉaRHhL… + €ÆÄh((4¦‚–nA€ @€ @€ @ pB&R11L I©a¥SИ %€ÆTÐÀÒ-@€ @€ @€ 4 à2‘Љ1RThLE,ý*@cb(”SAK· @€ @€ @€ И€%d"c¤¨ИŠYúU&€ÆÄP((4¦‚–nA€ @€ @€ @ 1%dzbýú $’S!ÃJ§ 11 J© ¥[€ @€ @€ @hL ··÷¯ßõýŠGàÍ7ß<æŸùÎùG¯kôehL …‚@c*h`é @€ @€ @€½täQÇ<77ø‰ÉÄ0)9LŸþì±·Ý÷Øé?¸äꫯ.XïèÊИ %€ÆTÐÀÒ-@€ @€ @€ Ô# oéÃG {aÅ–ÞM¯ÎëyùCÁdb ‡€9L·ß÷¸†÷ŠM¯ž†ÉTœØÒ“jhLŒˆ‚@c*h`é @€ @€ @€jÓÑÃôn]¹ùÕÀóxißœe˜L ”‚¦Ï{ÇØÇWU†÷ò¾}§s19™ `º&€ÆÄx((4¦‚–nA€ @€ @€ @ š€9L Wn]õò~Ó˜–¿´¯§oß쥛ÉÉÄ`É;9LŸ1‡©2¼eéIcZ¶qï÷1™ò]Ú_K‰QQPhL ,Ý‚ @€ @€ @€@ˆ€9L‹Vn]ýòþr®šŠÆ$ÏcÖÒÍüÈ1K{–à y$Pq˜ž†wµ¥§á½tÃÞï}ñ•Wý(]£Í¨O‰‘QPhL ,Ý‚ @€ @€ @€@…€9L‹W½²zË€äa¹jzúö.ݸwɆ=3–lúà‡?¶dY&Óˆ#/½´1lذɓ'×EÞÓÓ£ê~Ô××wðàÁÕ¨máªG—^zgüøñêŽ^jvÍ£Š¡0‡éÎqO¬Ù²ÀÒÓð.%3iÉú=#Ϻø’Ë®j½" Þ6ÂõÒpmýðøötuÐ*Ôf}ûšï¦Þ zžXwp×Ú9sæÔ­‘/f4¦XÇ%'OSzì©€ @€ @€ @ñpSEò¨ZQÎI/®ß3ãÅ—>ÐŽÉ$ÑǼ½ä ɇ¨ëH¤Ðžu;ªÃÕ,ºB¨‘G>¹Ù!ò–Ô“«ÆŒÓÊ]i!'éŒ@Èa:ÐÄÒÓð^¼N&Ó¨ÖM& †ð¸ÍÎ`ÐàlQþSûý~¥®1¹‹€Ybj°»ª„‡_Ì詳KGežSæCD!@€ @€ @€ Ð)ÃT_ò0É$EkwO[Ô†ÉÖ˜Ô@çyHG°ì5£FÒûaiäÈ‘ö‘Þ×nR(tmD w·ö#D¢ƒ;vv¿ZzI«²´¡$.–PÇ* ·MïH½²wì´¶D5°: Çu“€9Lw{bíÖU©˜B &Z*¦Òß½píîïžÙªÉј4ŒñÆáÁfãG_ 97ü¬Ãnˆšê§3Ø>Î4r#6¬ÚI´g˜šÎ¯—$òE{í`'wûë§åé›bcÞuÊȨ̂Úö¸6X÷urk˜ë¯{'ÜÚÈi#_ô‘}=Õ$ƒãΣm™[|1«¾ê€b“Š:8‡ ‘Àê]·¼ý§7=‰s˜lx›¢wÓÃ+O¸jÊðó'å”]ÚÓ·/Þ‹¢Ã{Áš]'ýd††÷ׯî,½YËwh„³±ÉmÒïvZ;ÅÞl2„œf4hØ¡9ÈŠràª"€ÆÄ€È!S'íeÍ8Çz§¾Æ¾Hš6eRž£]‹¹ìæp0Ðd@€ @€ @€ ‚¨8L[á!½CåÖ§Ö¬¨,¶5ü<ÙÏ/ݸWÓͯ^¼n¦/]ñ¼$9Lã§oÒz[#6÷§z•ŠiÖŠ@ò˜Ñ³ý©Ùëßß8'SÁ±Ò½ø ÜÕsØøUÙ\f’ÃôéÏ{ÇØÇÝð^µyÿÕã–i„K¹“¢'OŠÞ…·-, ï™ÞZNîáY›¾|ÅóÊ4ö½›{íý˵`â5ãz¾{ÓKÅTÞ;¦/Û~Ê÷æd*÷^Ó£ç:ûÏ;uP̧Ѝ•”xEŠ‚ËñÖÊ!~íƒÆäW¼‹ÐÛð—ú‚+›­°i}“˜¤Å^µÑ0“ËÌf“[°VÇ„·‹€Š>@€ @€ @€ @ çÌaZØ»ÕRÔØ2[2<®»LnÇò—ö-ïÛ÷‹'WŸ~ó @€ @€ @€he˜žþµ­ßËÓK‘ðH»Èzâ%Ÿÿê÷^}ÚUч)B±ÓÖóß=¶ò Ó)Ÿ¼!v”‹Gl'˜RÈãÜ Û>þËù~[—vBy’é¼ ¯ßr÷I²zbLÅ0ÓÏúñs8è̶˜ÏË*ü;DmÇ&‰)¢—2LÑf,Êû3W~7õaJå}õÍ÷\ÕŠ1EyoÚ–Uø3"Æ”¶“Û²#:¥ Sí$ÓÀSŠ1ò„ß\|’A z1¦Fü|';ÂE)2H{cJ¹¥|§ÉâŽtñ[±ÍÜ jš2 @€ @€ @€º uÔQ§žþÏ©ýRJ/e{lµZÔDŒés_½ã“—}'ú0þ¹›OûÜÍ‘ðˆœGêÃ]j^vÊå‘aºê¦{â=cŠ„GŒsZ1¦!ÈyÿŽ3ÿœwÖµÿóÀè‰ ”(ðÑ­ÿË™çÿÅþÏüÓ妈1Eg¦Û² S´‹-ä¢JóòŽ S«Âc#¹,ÆåÛÉEŒ©+¥×É0Åç~qóÿûÿýçïvl–X2Ô\àÂãëöß#÷C`´@ôQŠ$R¾_dì+»Ë¥C¢3S|O†n*œâ‘XŠG:Ež‡Z½zujÑäA€ @€ @€ @€@µ±åÖa‡ö¡^E—:l¥5±ÁÖg7Ý ØH.5aúôÆ,Æ!7|èê´ÙV4ªI›mEÎcõwEÈãï?üõ·üú,ÆtýެS!äqÊÖpà!·Þqßí;ü寮vâ®ÞþäS˜¾~×úÕ®˜ã9çœó¢¿,/ï´…\êÀôÆ3¯yÕi_M¦(ïW¾ÿ«¯|ÿ¦¼¼ó Sì–xÔÉ—}ð ·DyǾŠGþãeíòînŦ}÷{ƦͷFyÿè¶~sÖa’Lç¾¼1ì&B€I ÌÏÏG)~MI¤Ý»wïܹ3’Hñ$ñ$¾ŒûcJMœòGä–â­fŠ&Lñb†šä|\‹ @€ @€ @€)ÉtÆG/Èãi­´‹\$<Ž›»ú˜w\;m¿ñö£O¹ü+›øÌ×1rKùˆÍ¶N=Û!Ç9ú0µ[1E†©;äQÌ0EÎC’I5–%PŒ1Lùù#Éô¿¬XÞ©Â#ÀtÜ™WG¦çÅH¦¯|£¯¼oÜuÁ•wD¿±TÞŸºâ»íäväÛÉ3L©¼ôÓ_þæ‡ÛzÃLbLe­ºó 0c‘5*&‘Rï¥<ž”wSÚiƸL— @€ @€ @€À ´“Lÿ|AÊv´÷Øjµ¨‰¦´‘Ü51n¹÷ê[ÒN[Y¦hT“o¶µqëÝ^uçÀF5ý&I¦).—šÝzŠ1 0åwI¦CV••w¾…\k¹TÞ}íΞòN{É-”÷¶·îLå}ù–=Æú3L I¦¸ƒb˜IŒ©fÅãvh˜€SÃÔt @€ @€ @€fT %™>ð‘ÏDû¥ï`ZØi«µ—\ôašß¶36ÛŠÇ7DÂãîhT! …íä†e˜F$™vÿ÷Ý3º ¦½ç£LùùR’©¯¼ïûz'¢ù¼vDoP†iã w·+<í–xÝ]©Ó° SW’)n"…™Ä˜ö|}A€¥ ˆ1-ÝÊ;  @€ @€ @€ÔZ ’L‡¶’L­öKíLƒ»ÔŒÌ0C£3L“Lk.[³î¦uµ–rsuxèW»–x;‘d:xÕQ ù¼îcň^O¦ñ2L½I¦¸Ë‡~¼Ä[õ6C@Œi 4‡ @€ @€ @€¨©@$™^pð Oû§O·ÓK·f[ÈeãæöFrŶ:}˜Ú]j6Ûê4ªYJ†iÇý?ÿõÃäÛؾòã+×{}¼²eç–ôk4gÊû3ÅÒ›wîÞ¿•YSP·U3³ÿé£vT^Þi“Ävy§&L}½® SÖilI}˜R†)ƃýªfn‡cjìÒš @€ @€ @€Àl ¤$ÓûÏþt¾ÇÖײxG!áqck#¹ö^r¶Z{Éíi¦ž S€Ï]7·âŒk¯ZÏ#Ï#š3û3ÅïÆoE»¦ø­x[žyšÍÅ2ë1"ÉtСGuåó:¦¼ SÏV‰Ùn‰QÞ2Lcp;„cš ¶K @€ @€ @€˜ˆ@J2½ïìó‹¦þ„ÇB—š’2L1¹h°ɤx2ç|zx’º.¥^Mé•ÔŸ)z2­ú̪‰¨¸Hs"Éô‚CÌÊ»;À´iÛ€ˆ^»Í˜ SsÖßLh¬€Sc—ÖÄ @€ @€ @€fY %™Þ{Öù±ÇV 0õ'<®¸áîÔ¥¦”>LI;,¥VLñktfJ/¦LñˆWRg¦x%ÒKù˜å•2÷ñR’i¡¼[=Æò&L#"zç~qó¾û=cÓæ[ómã>±—Üxëâ(ì€ÓÞè9– @€ @€ @€@}R’é=gžŸLý B—š®»ë’k³qÊÖpà!·Þq߈Gÿ^r¹B$“¢S|ý–¢3S<Éû3ÅóøÝÈ0¥0S:dý·×§FMöT ’L¾èÈÞòÞší“8,¢'ô§ÈÞO€I ˆ1MRÛµ @€ @€ @€LT %™N=óSWnݹ1F+ÞÑNx6’ÛÐ 0í}†)æé¥*Å“¼SŠ1ů‘^Šc¹ñ$LñÎø­ør¢(.Ö ”dj—w!À40¢'ÃÔ •7š) ÆÔÌu5+ @€ @€ @€I dúÐyy€)Ox\zÝB¦R2Lq¹'¥MåR˜)="À/¦$Sz%:6¥íçd˜ê^ D’éù/:¢PÞ]û$æ=¦½tv8& Æ4d— @€ @€ @€ P¥@J2½óŒóR€)F 0å ²2LUNÒµgX ’LÏ{á—o阮òîŠèÉ0Ípu˜:Ó$ Æ4M«å^  @€ @€ @€Œ'’LkÏ8¯`êJxÈ0Gê¨Z dI¦Cޏ´ÑK›$¦!ÃT«•r3! Ƥ< @€ @€ @€Ì„@J2½ãƒëŠ ¦™XûÙ˜d$™8äðb1¦ÙXy³$@ 9bLÍYK3!@€ @€ @€ 0Z %™NùÀB’)žpà!·Þqßí;6vÜÿó_?ü[õHI&}˜ê¿RîĘ @€ @€ @€(&™d˜fhágfªy’É^r3³æ&J€@sĘš³–fB€ @€ @€ @`)Y’éÀóŠãxÞAú0-EÌ{¦K ’LÏ:àEû>鉛6ß:¢ÍXüÖƒýjº¦æn  Ðl1¦f¯¯Ù @€ @€ @€ ð‹«?¹æ)ÿû­›.µ—œúh¤ÀÇŸÿ[›Ö¾R†©‘‹kR4X@Œ©Á‹kj @€ @€ @€†\sÎo^µÏ=7ÌËyì¸ÿç¿~ø|¦UàUû<ø±Wˆ1éÃ4­+ë¾ h´€S£—×ä @€ @€ @€ hŘ~³}þžýEÔC†IÕL½@”÷¹/¬ÒÀ$“ ÓÔ¯¯  ÐP1¦†.¬i @€ @€ @€Xš@O’I†iilÞUoíó¿Ùu[Üb’I†©Þ+çî˜i1¦™^~“'@€ @€ @€h¶ÀWO^½~õÊŸü`{Ï4·~líÝ[æóó$“ S³ë¡a³{èþQÉ·^0×?¯â‹Å$“ SÃjÀth˜€SÃÔt @€ @€ @€´"¨1¦ˆzô‹ôg›"Ét×}ýúáGð˜(ãˆ+}ÿ«ë{nøþom‰ß*¾˜’L2LÓ²²î“™cšÙ¥7q @€ @€ @€& D†éÒ5«bēԴ¦Øé3«V¤ÉG $^ÿΗ×ýG‰ S¼9½³É4æÖÈ*Eǯi6ñ$^¬áüõÑ‹ÎdñÊÀl_#TL‚Ó- Æ4Ýëçî  @€ @€ @€ øÕC»£!Mä“"±O¢cMŠ}¤GêU½š"Æ”¾ŒwÆ{âI|/Fþ ,: lþÀš¨çH,EIGÝÆ“x%vJïÅ“ôzÔyªçx#^‰×%™ê¼¸î™cšÙ¥7q @€ @€ @€† ¤–K‘gJ‰WJ)¥|Ä+‘íH»ÎÅ{Rì)! ¥gO®†K™Þ äeñ»¼nSͧ”RÊíEaÇ+©Y΋О–cS¸æn™æ ˆ15Í @€ @€ @`R‹š˜x$6âIjB“Bñ<õª‰Gz1RMñþx’ö¡KcÑLyŠ¢Œ£¶S…§Š:O5Ÿ‡ðRyÇ;SÙÇëù;ئh­Ý*³# Æ4;km¦ @€ @€ @€3$ÙŽÔr)oHÑ¥<ä½j¢™MŒxC´«‰÷¤½çP¼SÈc†je:§šZ.¥ø]j¹5Y¥h”Bxy § _¼}›Ò\Så{ @€@ÝĘê¶"î‡ @€ @€ @€@ ‘aJ½j"íÏSŒ#•RO¦È*Å“x=~7½žö˜K_æ»t•p+NA`R§SD—"¢uõœFªüˆ+ÅoEUǓԖ,¾Œßµgâ2,ˆS @ 1¦‚ @€ @€ @€@ÝŠ9¤ˆn¤/‹¿Æ—ÑÌ&~+F~ó=_ÖmRî‡@ˆöKyG¥0E2)RJ‘Ì‹O¢°Sy§HSÊóÅ#žÄ—Z1©"ÔV@Œ©¶KãÆ @€ @€ @€ @€ÌŠ€Ó¬¬´y @€ @€ @€ @€¨­€Sm—Æ @€ @€ @€ @€˜1¦YYió$@€ @€ @€ ° pÍ9¿yÕ>¿Ù>Ï„@3¢¼Ï}y3§fVh®€Ss×ÖÌ @€ @€ @€ cRÍcjöúš cjèš @€ @€ @€Ÿú«¬Ó®Û h ÀOweå}Á85S"@€@£Ę½¼&G€ @€ @€ @` @ì·9xàά¼/>©‘“3)4XÀ& ^\S#@€ @€ @€ 0D@ŒIi4X@Œ©Á‹kj4Z@Œ©ÑËkr @€ @€ @€ ˆ1)Œ ˆ15xqMF ˆ15zyMŽ @€ @€ @€À@1&…Ñ`1¦/®© Ðh1¦F/¯É @€ @€ @€( Ƥ0, ÆÔàÅ55- ÆÔèå59 @€ @€ @€ĘFƒĘ¼¸¦F€@£Ę½¼&G€ @€ @€ @` €“Âh°€Sƒ×Ôh´€S£—×ä @€ @€ @€ cR cjðâšcjôòš @€ @€ @€\àÖK~sñIíqÊ~óª}¾Œ×õ T¦X 8/ï ^Ÿ•÷ûžµðJ¿Ô^@Œ©öKä  @€ @€ @€”"ðÃmY¶cà8ë°R®à$ªˆ2VáQü P{1¦Ú/‘$@€ @€ @€ P–À°œ‡GYÂÎS¡À° ž”^…‹âÒØ1¦=Ñò^ @€ @€ @€S-00ç!ä1Õkêæ‹ƒzRzŠ„S" Æ4% å6  @€ @€ @€”"Пóò(ÖIê Ðԓҫú¸,M@ŒiiNÞE€ @€ @€ @ =9!f,«Yä=A=)=µA€écšžµr§ @€ @€ @€J(æ<„¼ÎSý÷V{¼’|WÍGñ.ûüõÅê¿øÑÈ> Ýõ_þ‡ß~ÔïÿÁŠüõâ'"=ÿÃ?úãôÃT±ÝuÛ*ݬnÛ¥ÛªÞþî­áV畼=«ä®b.ÔóO²znTÒYUg…UuVØÝµ}S§¶óòî­ðV‘wê¼»Ô¿•z»Ú|_Í·Ê>¯ü¼ø;õ¿«]ÿÅÀí@ßag|b\ÑñYxÞ xÓI§u}" Šø\¼ûìÏ>ûÙÏ^ê’{¦D@ŒiJÊm @€ @€ @€Lƒ@„?¢KôR 0eãÞŸEŒé}­S 0eAV dh†©c*f˜òäGÊ0å±ÞÀG+ÆÔõøn;Æ”2L­G'ÃÔcº®ìèÊ0µ"]¦þS'ÆÑ‰1¥èFWŒ©Úè1e&1¦å¬ö,ÆtÔ±]¹¥B­¦ôRTrJ/ 0õ–n'ÀÔÂ+%Ô'óºÂy½¦…ˆÞèS+«7,ÃÔíõåöǘRz¯˜aÊbL­ ßèÓ•}y¾b†i!ÆÔJõµƒ}bLËù¡pnj" ÆT“…p @€ @€ @€MH=lÚ¡¥vt©«“ÍáGf1¦¦¼MjÂ4¬Óè Ó^·bz`¡S+Ætmw7¦E[1å1ެS¡M;ÃTLoä1¦‹S7¦®VL­nLw鯴ŸŠˆ1Eœ.Å•ºÊ5Ë-µ£KQÉyû¥LKÊ0E§±¥µbÊ3L[:-Ç¢à»{‹µbjw +4!ëkÅÔiEÖÝŠiS'É—‡ùÚmÉúZ1¥ÓšèÆÔaÊ[”m¸V7¦åød8'Õ ˆ1U¿î€ @€ @€ @ 1ÅðÇÀM¸^zä±ïýà‡{:0 ØH®» Sÿ\û0 È0µ:Ö¤íäòœÇB+¦ÞíäZÔ lÅôl;¹îVLKÛQn@+¦ÖŽrínL­ÓÀå"®aS¹Ò?)Æ´PŸÅ ã:{F%ÓKùæqÅÎa…-äú:0 0 ÜH.ßqô^r£ú0-9ôØvr½û'ÆFŠ­‚·Ó…M ;ÊhÅtEkwÅa1¦´ÍbŒKĘJÿT8!õcªÇ:¸  @€ @€ @€Fô„?ÚÝk ;ǽôÈcÞóo×îžÈB¦b€iÇO&?ŠÉ}ëû?I{ÉîÃ4*ÃÔ·\ÖŸæ¶ÔŠé¾æH£ôVL…SÿæYí¸FĘæÎúçýô—ùøÉÏ~Õˆb©lcŠ8]O¥žÐRTr¶kw]êm¡÷Roz©ØBìö¦‡u``êjÂtg¶=b]›$f¦¥î%·L¦«o¾':¥qU¶£Ü"ÛÉ-¥S1Æ”ï±XlÅ”bLO_ùÌâç"žÿG©¬ª\˜eˆ1•¡è @€ @€ @€Z=á…üGD@Z),Ætú‡ïØ9*ÿÑþµ÷VW€)ïXÓõøÑ­-·ôaZ,Ãtmw†ió7ïMµÚûjÝrol§•ƀǻ6µÆˆVLcúßý½ó.þưVL׈Ó»O;;21ù½_?,®1þG®c:¦˜Rêj֪ը䔴ëÎÛ ¨ÛžèR1½T á ÜBn`¦b€iŒ&LQä[o`kÞil¡Â³fcCö’³Ó3LC·“ëô$‹BŒÔ‡)u&{Þ!íMå²ÓuÙ(¶bJ1¦}÷{FñsÏ|HÂoüÏ…# ¨ƒ€SVÁ= @€ @€ @€4D`xø£•ÿØùàKŽ8æÝ§ŸÝß{©þèé^³h€i`¦ÖFrí½ä ½j–!ÃÔŽ12LY7š¯Æèd˜6mkǘº6Òj…6Rn£cÚ|ÙõY7¦Bb£ÝŠi`Œ)27bL{óI1¦bJ©»ÁRÔjcJ{ÇÝæå:°nS’&ÏÞõô^*¦—Ší—Æ 0õïØ›Ï‹ S+Àã†4¶Gz)û£ÍX>R¿±¼åX×+n$—…öй½ÂŠYzoi}˜ö4Ãtù–ì³bLy+¦ž “ÓÞÔ¿c ¨³€SWǽ @€ @€ @€L™@„?ú3ÅW^1¦Bo¡,ü1rã­Û~ø“´…\!öÑêÀT0µ:Ö Üo«¯ S'ä1,Þ10Ø‘ö’ëëô„ S§ÓÀ Ó­Æ3cZ×cJ‰j¤ÑßIŒi/?cŠ8ÝèB-VrOËŸ…È]§t÷,ºôƒŸÄNˆ ›!vWr±ýRq ¹½ 0nÂ40ԘڽǺ3LùFrÙ^r7 ÝKn¼ SŠ1ý]Š1õõaJŸ ݘöòSàpê) ÆTÏuqW @€ @€ @€S)áþÌGþJ$–"ÆtêigEì#íùh7^úit¬ÉšÖ H/ýdPzi‘ÓbÉ=Ç;®ûv¡9Mg#¹NgšeÈ0u¶ÐÊcL]‰N†IŒi9>cŠ:Q¨ñ[©’Û1»BØ®·n£€˜o:‡õt]*6^•^ê¤ñÚé¥bS±;þõ¦­ó±Ð]lT¦®&Ly‘lÂTìÃÔ߄难-³ÓÈ S¾b<¹rk{lܺsã½äR¦4Ú1¦!&1¦åø\8'ucªÃ*¸ @€ @€ @€†Dø#(õ>ú©‹c¤Ž5Ñr)Æñ'½'k¹”í±õÀß¼ñÄY·>F–öØþ@JuDÚcËö,äã’¯Ýú„'ïû•Ö¯yš÷ùÉÈvÄxŒlÇ_Þü¬çãÕ¯?!¥:yñÑÏúÓƒžù§ECšñåq'¼+¾Œñ©‹¯‰ñèÇ<ö¿<ñ©ç­¿fÓ»^uô3þë bdŽm;OûÈçW>ç1^pØËVÿÍ›¯hŘ:M˜î¾¬Ø‡©ÐxFŒiòÅ1¦ˆÓõjO­F%w3Ì+6OÚuÕm§t{ö:Ì÷=Œ¬Rp$ðRË¥Èá}ê¢+Ÿó¼ƒ£€SË¥H)wáÆ(æ7¿ýݶúo².b­ôRÔs*é(ã“ßsVD‘¾ºõû]úë7œ# ûs—|#•tJ,åã³_ÙÜÊ-uzŒ}óÞ“N=3Š‘ŽÈsį¿øès¼ëƒçFn#6ÒzåkOyŽHr¼þøµ`zÇÎGd8þãcþàìO]ò/_ûÎ~ÂSÿ2bLí]äºL…ͳR\CŒiò¥žÅ˜^rôèBí­äVÀnDݦÄR±tóç­ìÝòMâ"º¡¥(ãvt©ÕB,ž¯»pã…—^q¥È-Ee7ŒK1¦O~þŠˆ.Å>q×Þ1¦bD×¥´[\”w¼I¦Î¶q÷ýÕëOˆßÊwŽË{/½úu'DµG‘ì‚Ëýû]¿ñ¦h¼u~Ù7îˆ&L‘^ŠöKÑo,ÒKÑr,~ÜRTû®¸1ê?ýzÐa/‹²âçQöÑ{ìßÚг…bO†oLbL“ÿD¸"È»1¥$ÒĘ" •Z1å1¦ /žË @€ @€ @€L‘@„?ò4Ÿ¼è%/‹ÓÀ´G¼˜š-åH/E¼#Û-.¢KÇeÑ¥Ô¢¦Ý{©Ðu)Õä»kEÈ#¥—¢÷R$<"ÞãßÌ‚1ò}µ"Àô¸'í˜Z;jŸ'RéH#òm¼éqO|jt`J[È¥G¾…V4¡YýÚãÓþq)À饔Þ8þ”3þò5onõaÚqÙõÙÈv‘+˜6\—˜Ä˜ª*ìˆ1EŽ.ÔþJV´ÃâJ©ŒÛ{Ãuž¤ S$–Ò>q­'Y¿¥,¥ô…+bĔƋS÷nq÷G=âó—g…ý¤}£—Ø_½á„‘Ì‹>Lyt©¸m\´\ŠwfåFgÛ¸¨ùOÿË5Wß|O¤ô^öò×D³±¨öW¾î-ió¸(ø¨öDŒéµÇ§šSÔ|Œ(øÞñ¡xåÃçoˆôRŒh<é¥h®K€Àr Dû¥|ƒ¸t­¥Æ˜â°ž S,Æ´Ü æü @€ @€ @€Ó+áÑi½øeÿðî¹bV)-u>¶?{lÅÖZ'¿÷ìbt)µ¨I1¦ÈyDò#¢ÿøî³òmã¢?MŒÔx)‹z´¢Kñžè½ÁŽ|ó¸v|ü‚,Æ”6‹©Žˆ.¥HÇ+ÿ6Æñ67Z.E˜#ºÑĈGl¡•bL±…\cje˜"Æã¬óÚ1¦ˆnœµî’ˆ1¥S;½QØE®'±¡Óä«=‹1½øe£ µXÉívJÝ»¼nû³Ji£Ã4:{ÃeON~ïYWZ÷…+R§èÒÂóÏgÅüìç#®ù¤-¥z.v]J»ÅEã¥(ì“N=ë…/9:k¹ãÖ{ãõ¼ëR;¥×I/E…GhéŒ]—¾¸ñ¦¨ö«n¾'ÕyYV怜ÇX|ô‹:O5äûëcŠÛ&Fã±Nï¥VŒé†»£ñXÿ€öK ßÀ߆NŒ¯?À¤Óä?®H€ÀÄ"tÔ“aŠK/)ÆÔŸ~J7-Æ4±Ås! @€ @€ @€©ˆøE1ÞÑQzaĘNýP;±Ô‰zô¤=¢9͆«o Sòˆ¨Ç6|#b©EMä<>É7¾|Õ-‘ÛÈZÔ´r±¯V{|ó¾g=÷ HxD㥬÷Ò­÷¾ðÅGG€)¶‹í´Rï¥gþéAúø…cŠŒ'›nø~4[ÊBKÜRöB=· ;byç|öòVã¥{S2/Jú3ÿòõ<º”vEŒò.6^zÛ»æR…§ ã"À•Ü[Þ—bDyŸwñ5Ñx)FÊêEŒ)~ýÈù"½ÕûÇÅæq©÷R<ÿÄEWgeßé½e饈1|Ú9­ÊÏÆ¢í— 0‰1MþáŠLF G±)\ÿµ1ÍÏÏÇ–âøô(&¡Ä˜&³x®B€ @€ @€ 0ñ¯lÅö3ýÏ#ÆtÒ»>4,ê‘g>}é1‘ÏÈÇ_¿áÄH{󗯉´GŒØ$.rKñkñ=­ ã²GŒ”íH#/ÍsQj¼1¦x#žD¶ãmèÒ3ÿëA±—V¤:b/­v¤‘ÒKñ$‚1âIJ/½îøµ±…Ü[N9#ÂéHãø“ÏˆGüÏŸþì<4ß¼yÑ“M媪ðˆ1EŽ.Ô!•ÜÊ' J)KéyWŠÒ¦b¹¦ø]´\Š|RŒx÷YÅÜRk{¸(æ4²’Žd^4XÊ«:j8bLQÛ¯~Ý ñ<ÂIíÝâ:­Å¢¼ÏÿÒ5ÙëOÜ7Fd˜ÞõÁs£È/Üxcªêøõ¨?ÿë(òÔiiÓ¶]‘[Š×ã×è:¡½È-EÁGû¥ˆ+Eañg¡½xž÷^zús^eÿ·Ÿ}"Þ|ò]íÇ|í ßÓKyÂϦrU}:\—eX»vmÄ•ò$ÒÜÜ\~¡ÅcL»wïÞRxlß¾=?¸ø|™nÝi  @€ @€ @€L©@„?úóÅWYuTĘòWz¢)ð±°C\¡?MOsšžGÚT«]Š„Gj¼TÜ6.u¦I;j]uSŒ¬'MÚN+ß<î’¯7E:bDÔ#¶ÐJÝh6fãîHr¤ý³bD†ã⫾Sì@“µ_j86ŒìÀ¤Sµå1¦¨ÃÑ…:¢’ÛEÛê¨4p\{ÛýíÖJ…îjVhö¥M·ôsÖB¬»žó­âRUçý–Öv¡¼ÛÑ¥¼Èó:Oí—Rç#•zOÁk>•ýô^ºî®aÛÆ~]Œ©Úψ« Pº@ÄŠI¤&å—ˆ×óçû”~a'$@€ @€ @€ 0³þ–íH¯G|äíïüP+¨48ê10í±hÎ#‹w Jxä¹¥aÑ¥bª£+ϱ- sD+š³?µ! 0ÝP0-Ä8vä[h`Ò©ªIŠ1.ÔžJn•k_Ñv§”†•R¯Pà =–Ú‰¥!¼!%¢KÅÂn×v!™W çõä–òˆÞBt©Uê…èRwµB{ôÒBÙ·wNìï½4nzI7¦ª>®K€@MĘj²nƒ @€ @€ @  þˆ0ǰaŽƒWõ¶µgô´VÊ¿ìŽzd{i-’óhw¦Yh¹Ô“ðȺ.eñŽB×¥Bã¥þ†4=yŽO\øµžöK)ÉÑŸ^ZèÀtížµŸùG=úÜ/nÑ™&ÚÒ¼û´³oßñ`>îܵû×?Ò„r©h)Æ4¢Pã·¢’‡UéÀ×ûRJƒ²J#z,uBxý–úCKýý–ÚÍ–ZµFªíöètÞu©]Ñxéò-“H/‰1Uô™pYê" ÆT—•p @€ @€ @€ ÈÂß¼/ýÙŽƒ;ê­kÏè¼Þ* ‹+uí¥µÐl©+´4$·´'Ñ¥Þn4];ÇwÑÊÓKí&4×íÙþq³JbL“/ûˆ1EœnH“¤vÛ¤¨ä!ɤxິ\Úå°Ý*,ÒÊÞ Œ+ L,õ‡–š- Í-umé¥+ E^Ü!±'·Ô³gÜàèRï¥=Œî-e›9›ÊMþsáŠÔA@Œ©«à @€ @€ @€"ᯧQ´ ¿uó=ýÜ•UWÖf)K,í*òÒóžfK~Kƒ·ŠÝr©˜Õ‹­vKl…ö–ÒH©”÷ˆ1MþsáŠÔA@Œ©«à @€ @€ @€"áÑ!zä §|pDÂc¡ÁR;çÑ×fx£'Þ1h#­ÑÑ¥Á—ŠIŽR"Å“ˆ1M¾ô³Ó¡GŽ.Ôv%ß|ÏÕ#I+9먔F__¥®ýà •=–ºxéËA‰¥Q¡¥N³¥=Ú*n!·ÔÕr©œfcc^Ę&ÿ¹pEê ÆT‡Up @€ @€ @€ ˆðGoË™<ÒÑz1¦·œüÁñŽÞ„G„<öXžð‘[ê vº.-]ZÖ&4bL“/ýˆ1EËÒ¥RTr_ip,iÀÖo©t ªzRJí2TêÍ*uº+ Ž+Mg¥%f˜âmbL“ÿ\¸"ucªÃ*¸ @€ @€ @€†Døãò‘yŽçEŒé¤Ó;ïÉz)-;†d;†µ¢éo³ûg-='Q“wŠ1M¾ô#Æu8ºP«ä¾ÒÒE)ª7—F2©gt† ,æ´\ŒšÔê$oCŒiòŸ W$@ bLuX÷@€ @€ @€ ÐsýÏŸwÈkN:-½> ÕQè@Ó½\aÛ¬Èv4¨ÓäK?‹1rÄèBQɃë6¯çB2©¯†ûʸA•\nÈIŒiòŸ W$@ bLuX÷@€ @€ @€ ÐûÊ7ŽøG¼ß³ž_xÃqǾrÐxÅqÇÌÆø·ÿî·;rõˆÉ>öþøÝ§}ûŽóqç®Ý¿~ø‘†TLÓˆSÔáèB]´’×m^̯8îØÙ(àeúœFÙï÷Ìç8yäœöÝïÅÏE<ð¡_UQP®I€ÒĘJ£t" @€ @€ @€§Ÿ~úI…ljo}ûß¾ñ-ÅñâÃùóW¼¦çÅYþòùúš×½i´À¦Í·Š1•øáºóÎ;‹UÏßø¦{–à¹Ï?x–˲ò¹/åÅY=_Œ©ÄÏ…S P1¦:¬‚{ @€ @€ @€h¦ÀÏùpOÎÀ—{/ S韖÷ÿ|ï×Å*Щô† 0a1¦ ƒ» @€ @€ @€À ˆ1-G°CŒ©ôÓrêäÏ)ÆTúGà ˜°€Ó„Á]Ž @€ @€ @`†Ę–#É!ÆTúGHŒi9 uòçc*ý£á„LX@ŒiÂà.G€ @€ @€ 0CbLË‘äc*ý#$Æ´…:ùsŠ1•þÑpB&, Æ4ap—#@€ @€ @€˜!_ü÷‡'ehüï¸{÷¯~d†Êhù§z÷ý5¾lfa‚bLËÿYq–W@Œiy} @€ @€ @`Æ"É=™FŒŸýâ×£ß0k¿»(È/õðŒUéÓXØ¢e¶èº,zoØ¥ø—^NH€ ˆ1MÜå @€ @€ @€ @€ècR @€ @€ @€ @€T, ÆTñ¸< @€ @€ @€ @€bLj€ @€ @€ @€ @€ŠĘ*^—'@€ @€ @€ @€ @@ŒI  @€ @€ @€ @€ P±€SÅ àò @€ @€ @€ @€ˆ1© @€ @€ @€ @€*cªx\ž @€ @€ @€ @€1&5@€ @€ @€ @€ @€@ÅbL/€Ë @€ @€ @€ @€ Ƥ @€ @€ @€ @€¨X@Œ©âpy @€ @€ @€ @€ĘÔ @€ @€ @€ @€ ˆ1U¼.O€ @€ @€ @€ @€€“ @€ @€ @€ @€ @ b1¦ŠÀå  @€ @€ @€ @€cR @€ @€ @€ @€T, ÆTñ¸< @€ @€ @€ @€bLj€ @€ @€ @€ @€ŠĘ*^—'@€ @€ @€ @€ @@ŒI  @€ @€ @€ @€ P±€SÅ àò @€ @€ @€ @€ˆ1© @€ @€ @€ @€*cªx\ž @€ @€ @€ @€1&5@€ @€ @€ @€ @€@ÅbL/€Ë @€ @€ @€ @€ Ƥ @€ @€ @€ @€¨X@Œ©âpy @€ @€ @€ @€ĘÔ @€ @€ @€ @€ ˆ1U¼.O€ @€ @€ @€ @€€“ @€ @€ @€ @€ @ b1¦ŠÀå  @€ @€ @€ @€cR @€ @€ @€ @€T, ÆTñ¸< @€ @€ @€ @€bLj€ @€ @€ @€ @€ŠĘ*^—'@€ @€ @€ @€ @@ŒI  @€ @€ @€ @€ P±€SÅ àò @€ @€ @€ @€ˆ1© @€ @€ @€ @€*cªx\ž @€ @€ @€ @€1&5@€ @€ @€ @€ @€@ÅbL/€Ë @€ @€ @€ @€ Ƥ @€ @€ @€ @€¨X`‘ÓöíÛ{n°ÿ•Šgàò @€ @€ @€ @€Ô[`gëQ¼ÇžW†Æ˜Ö¬Y³²óHÑ¥þWê=wwG€ @€ @€ @€ @€@õ«V­Ê“Hénú_cЬS™ŽY¿~}ÖÿJõós @€ @€ @€ @€Ô[`ݺu«W¯N÷}”æææú_‰ßÚ)ß<.Řâ­ý¯Ô[ÀÝ @€ @€ @€ @€ P±ÀîÖ#ÝDŠ1õ¿¿54Æ”ß~´ešŸŸ/Φÿ•Šçêò @€ @€ @€ @€Ô[`Ë–-+V¬(Þcñ•Q1¦h¿‰¥hâ”ÜÿJ½çîî @€ @€ @€ @€¨^ v„‹$Rä–ò[éyehŒ)މ#ãÝù‘ý¯T??w@€ @€ @€ @€ @€@½¢R$‘¢ƒR~›ý¯ 1E§Øˆ.¢KñH§è¥ÞÓww @€ @€ @€ @€T,0??¹£ø5%‘vïÞÝÿJÜâàSjÙ”?V¯^ÝÿJÅósy @€ @€ @€ @€j/°fÍšb):+õ¿“Ú©ötƒ @€ @€ @€ @€4D@Œ©! i @€ @€ @€ @€¦W@Œiz×Î @€ @€ @€ @€hˆ€SCÒ4 @€ @€ @€ @€L¯€Óô®;'@€ @€ @€¡÷ð5K¾IDAT @€ Ð1¦†,¤i @€ @€ @€ @€˜^1¦é];wN€ @€ @€ @€ @ !bL YHÓ @€ @€ @€ @€ 0½bLÓ»vîœ @€ @€ @€ @€@CƲ¦A€ @€ @€ @€ @`zʦwíÜ9 @€ @€ @€ @€†ˆ15d!Mƒ @€ @€ @€ @€Àô ˆ1MïÚ¹s @€ @€ @€ @€ cjÈBš @€ @€ @€ @€écšÞµsç @€ @€ @€ @€" ÆÔ…4  @€ @€ @€ @€Ó+ Æ4½kçÎ  @€ @€ @€ @€4D@Œ©! i @€ @€ @€ @€¦W@Œiz×Î @€ @€ @€ @€hˆ€SCÒ4 @€ @€ @€ @€L¯€Óô®;'@€ @€ @€ @€ Ð1¦†,¤i @€ @€ @€ @€˜^1¦é];wN€ @€ @€ @€ @ !bL YHÓ @€ @€ @€ @€ 0½bLÓ»vîœ @€ @€ @€ @€@CƲ¦A€ @€ @€ @€ @`zʦwíÜ9 @€ @€ @€ @€†ˆ15d!Mƒ @€ @€ @€ @€Àô ˆ1MïÚ¹s @€ @€ @€ @€ cjÈBš @€ @€ @€ @€écšÞµsç @€ @€ @€ @€" ÆÔ…4  @€ @€ @€ @€Ó+ Æ4½kçÎ  @€ @€ @€ @€4D@Œ©! i @€ @€ @€ @€¦W@Œiz×Î @€ @€ @€ @€hˆ€SCÒ4 @€ @€ @€ @€L¯€Óô®;'@€ @€ @€ @€ Ð1¦†,¤i @€ @€ @€ @€˜^1¦é];wN€ @€ @€ @€ @ !bL YHÓ @€ @€ @€ @€ 0½bLÓ»vîœ @€ @€ @€ @€@CƲ¦A€ @€ @€ @€ @`zʦwíÜ9 @€ @€ @€ @€†ˆ15d!Mƒ @€ @€ @€ @€Àô ˆ1MïÚ¹s @€ @€ @€ @€ cjÈBš @€ @€ @€ @€écšÞµsç @€ @€ @€ @€" ÆÔ…4  @€ @€ @€ @€Ó+ Æ4½kçÎ  @€ @€ @€ @€4D@Œ©! i @€ @€ @€ @€¦W@Œiz×Î @€ @€ @€ @€hˆ€SCÒ4 @€ @€ @€ @€L¯€Óô®;'@€ @€ @€ @€ Ð1¦†,¤i @€ @€ @€ @€˜^1¦é];wN€ @€ @€ @€ @ !bL YHÓ @€ @€ @€ @€ 0½bLÓ»vîœ @€ @€ @€ @€@CƲ¦A€ @€ @€ @€ @`zʦwíÜ9 @€ @€ @€ @€†ˆ15d!Mƒ @€ @€ @€ @€Àô ˆ1MïÚ¹s @€ @€ @€ @€ cjÈBš @€ @€ @€ @€écšÞµsç @€ @€ @€ @€" ÆÔ…4  @€ @€ @€ @€Ó+ Æ4½kçÎ  @€ @€ @€ @€4D@Œ©! i @€ @€ @€ @€¦W@Œiz×Î @€ @€ @€ @€hˆÀ¨ÓüüüÜÜÜöíÛó¹Æ+ëÖ­Û¹sgCfo @€ @€ @€ @€,¿@„ŽzrGñe„‘ò+1­ZµjõêÕk×®]¹råúõëã€â+’LË¿v®@€ @€ @€ @€ @  +V¬X³fMJ"¥ÜQz%ñJšáàSt`Êß±eË–t|ĘÒ1qÆx4AÈ @€ @€ @€ @€XNØ.âJé )w=•òW"˜ñ¤ø­Q›Ê¥ƒãDÑ–)¿ÕÈ3ÅÁņNË9 ç&@€ @€ @€ @€ @ !CнäòÉDi‘nLù[#ëœò-äR—¦xÄ“†Ø˜ @€ @€ @€ @€Ë/¦<´WK_æÄêÆo SêÚT|D[§â— ®@€ @€ @€ @€ @€À Ä.rGñzl3cJq§¼S<É·–‹`“Ó…['@€ @€ @€ @€ 0AÈåÑ£¸l4Qš››K× Ó¨S„–¢SÊ:Å#Ñ¥x’2Lé` @€ @€ @€ @€ŒH;Â¥R<æççS6)ÂLñˆ'ñJ>¸Sü^~dcŠããy£âÔè  @€ @€ @€ @€ °¨@dŠI¤ZŠ_£ÅR<Ò—ñº©Ü¢ð @€ @€ @€ @€”" ÆT £“ @€ @€ @€ @€ 0¾€ÓøvŽ$@€ @€ @€ @€ @ 1¦R„ @€ @€ @€ @€ñĘƷs$ @€ @€ @€ @€¥ˆ1•Âè$ @€ @€ @€ @€Œ/ Æ4¾#  @€ @€ @€ @€(E@Œ©F'!@€ @€ @€ @€ @`|1¦ñíI€ @€ @€ @€ @€@)bL¥0:  @€ @€ @€ @€ã ˆ1oçH @€ @€ @€ @€Jc*…ÑI @€ @€ @€ @€_@Œi|;G @€ @€ @€ @€ PŠ€S)ŒNB€ @€ @€ @€ @€ÀøbLãÛ9’ @€ @€ @€ @€RĘJat @€ @€ @€ @€ÆcßΑ @€ @€ @€ @€”" ÆT £“ @€ @€ @€ @€ 0¾€ÓøvŽ$@€ @€ @€ @€ @ 1¦R„ @€ @€ @€ @€ñĘƷs$ @€ @€ @€ @€¥ˆ1•Âè$ @€ @€ @€ @€Œ/ Æ4¾#  @€ @€ @€ @€(E@Œ©F'!@€ @€ @€ @€ @`|1¦ñíI€ @€ @€ @€ @€@)bL¥0:  @€ @€ @€ @€ã ˆ1oçH @€ @€ @€ @€Jc*…ÑI @€ @€ @€ @€_@Œi|;G @€ @€ @€ @€ PŠ€S)ŒNB€ @€ @€ @€ @€ÀøbLãÛ9’ @€ @€ @€ @€RĘJat @€ @€ @€ @€ÆcßΑ @€ @€ @€ @€”" ÆT £“ @€ @€ @€ @€ 0¾€ÓøvŽ$@€ @€ @€ @€ @ 1¦R„ @€ @€ @€ @€ñĘƷs$ @€ @€ @€ @€¥ˆ1•Âè$ @€ @€ @€ @€Œ/ Æ4¾#  @€ @€ @€ @€(E@Œ©F'!@€ @€ @€ @€ @`|1¦ñíI€ @€ @€ @€ @€@)bL¥0:  @€ @€ @€ @€ã ˆ1oçH @€ @€ @€ @€Jc*…ÑI @€ @€ @€ @€_@Œi|;G @€ @€ @€ @€ PŠ€S)ŒNB€ @€ @€ @€ @€ÀøbLãÛ9’ @€ @€ @€ @€RĘJat @€ @€ @€ @€ÆcßΑ @€ @€ @€ @€”" ÆT £“ @€ @€ @€ @€ 0¾€ÓøvŽ$@€ @€ @€ @€ @ 1¦R„ @€ @€ @€ @€ñĘƷs$ @€ @€ @€ @€¥ˆ1•Âè$ @€ @€ @€ @€Œ/ Æ4¾#  @€ @€ @€ @€(E@Œ©F'!@€ @€ @€ @€ @`|1¦ñíI€ @€ @€ @€ @€@)bL¥0:  @€ @€ @€ @€ã ˆ1oçH @€ @€ @€ @€Jc*…ÑI @€ @€ @€ @€_@Œi|;G @€ @€ @€ @€ PŠ€S)ŒNB€ @€ @€ @€ @€ÀøbLãÛ9’ @€ @€ @€ @€RĘJat @€ @€ @€ @€ÆcßΑ @€ @€ @€ @€”" ÆT £“ @€ @€ @€ @€ 0¾€ÓøvŽ$@€ @€ @€ @€ @ ¡1¦õëׯ\¹rÅŠ«V­*^i~~¾ç•RîÃI @€ @€ @€ @€h¤ÀÚµk#‰5kÖ'¯Ç#½24Ʀ-[¶Ä;æææV¯^Þ½{÷îx=ÎØH/“"@€ @€ @€ @€ @ \èšq£ÈÅi#†´nݺtþx=’H‹Ä˜â°H/¥"Ì”ç–âDñºS¹Kål @€ @€ @€ @€š*q¥x¤ÙÛ/¥æL‹wcÊ]b ¹”ŠSYL55Õμ @€ @€ @€ @€(W m·sçÎ8mtSZ¿~ý’6•K7¤åâøÈ3Å1¦r—ÇÙ @€ @€ @€ @€4^ ÒGÑ~)uSŠStSŠ'K1¥ÆMÉ(މ/#É¿F**e›< @€ @€ @€ @€ 0Z 'Eâ(e˜â‘2Hñk¼˜¿¾Ï°SÄ[c¹þßÕIÙ @€ @€ @€ @€ °DèÃY¥õ¿ñnL}JY§ôHÛÉ¥Gœ±øåïÆÛ @€ @€ @€ @€˜AØö­˜DŠèRްxŒi½L™ @€ @€ @€ @€ª†n*WÕ ¹. @€ @€ @€ @€³& Æ4k+n¾ @€ @€ @€ @€j' ÆT»%qC @€ @€ @€ @€fM@ŒiÖVÜ|  @€ @€ @€ @€ÔN@Œ©vK↠@€ @€ @€ @€Ìš€Ó¬­¸ù @€ @€ @€ @€¨€Sí–Ä  @€ @€ @€ @€˜51¦Y[qó%@€ @€ @€ @€ P;1¦Ú-‰"@€ @€ @€ @€ 0kbL³¶âæK€ @€ @€ @€ @ vbLµ[7D€ @€ @€ @€ @`ÖĘfmÅÍ— @€ @€ @€ @€@íĘj·$nˆ @€ @€ @€ @€À¬ ˆ1ÍÚŠ›/ @€ @€ @€ @€Ú ˆ1ÕnIÜ @€ @€ @€ @€Ycšµ7_ @€ @€ @€ @€µcªÝ’¸! @€ @€ @€ @€³& Æ4k+n¾ @€ @€ @€ @€j' ÆT»%qC @€ @€ @€ @€fM@ŒiÖVÜ|  @€ @€ @€ @€ÔN@Œ©vK↠@€ @€ @€ @€Ìš€Ó¬­¸ù @€ @€ @€ @€¨€Sí–Ä  @€ @€ @€ @€˜51¦Y[qó%@€ @€ @€ @€ P;1¦Ú-‰"@€ @€ @€ @€ 0kbL³¶âæK€ @€ @€ @€ @ vbLµ[7D€ @€ @€ @€ @`ÖĘfmÅÍ— @€ @€ @€ @€@íĘj·$nˆ @€ @€ @€ @€À¬ ˆ1ÍÚŠ›/ @€ @€ @€ @€Ú ˆ1ÕnIÜ @€ @€ @€ @€Ycšµ7_ @€ @€ @€ @€µcªÝ’¸! @€ @€ @€ @€³& Æ4k+n¾ @€ @€ @€ @€j' ÆT»%qC @€ @€ @€ @€fM@ŒiÖVÜ|  @€ @€ @€ @€ÔN@Œ©vK↠@€ @€ @€ @€Ìš€Ó¬­¸ù @€ @€ @€ @€¨€Sí–Ä  @€ @€ @€ @€˜51¦Y[qó%@€ @€ @€ @€ P;1¦Ú-‰"@€ @€ @€ @€ 0kbL³¶âæK€ @€ @€ @€ @ vbLµ[7D€ @€ @€ @€ @`ÖĘfmÅÍ— @€ @€ @€ @€@íĘj·$nˆ @€ @€ @€ @€À¬ ˆ1ÍÚŠ›/ @€ @€ @€ @€Ú ˆ1ÕnIÜ @€ @€ @€ @€Ycšµ7_ @€ @€ @€ @€µcªÝ’¸! @€ @€ @€ @€³& Æ4k+n¾ @€ @€ @€ @€j' ÆT»%qC @€ @€ @€ @€fM@ŒiÖVÜ|  @€ @€ @€ @€ÔN@Œ©vK↠@€ @€ @€ @€Ìš€Ó¬­¸ù @€ @€ @€ @€¨€Sí–Ä  @€ @€ @€ @€˜51¦Y[qó%@€ @€ @€ @€ P;1¦Ú-‰"@€ @€ @€ @€ 0kbL³¶âæK€ @€ @€ @€ @ vbLµ[7D€ @€ @€ @€ @`ÖĘfmÅÍ— @€ @€ @€ @€@íĘj·$nˆ @€ @€ @€ @€À¬ ˆ1ÍÚŠ›/ @€ @€ @€ @€Ú ˆ1ÕnIÜ @€ @€ @€ @€Ycšµ7_ @€ @€ @€ @€µcªÝ’¸! @€ @€ @€ @€³& Æ4k+n¾ @€ @€ @€ @€j'0*Æ4???77·}ûöt×»wïÞÒyÄóÚMÅ  @€ @€ @€ @€ PKu­ÇÎ;ÓÝE$)O"¥W†Æ˜V­Zµzõêµk×®\¹rýúõñÖx¾bÅŠø2oªå|Ý @€ @€ @€ @€õˆÐÑš5kR)%™R)=R—¥Á1¦ø½xGšMäžÒó6ÅózMÑÝ @€ @€ @€ @€ Pcè—¦tƒ‘dŠG<‰`SÏ-ÚT.½5Nm™âI„™âŒñk:— @€ @€ @€ @€–.1¤´µ\dây¾M\œa‘S´_ŠèSjåݘbw¹x%N‘'¤–~ÞI€ @€ @€ @€ @€ÀÌ D€)m ;Å¥}áÒ6qIŠGŘâÈÈ0õo$©¦þ¶N3ëkâ @€ @€ @€ @€ŒH»Àõ¿'JiŠ×‡Æ˜Rú)õaŠÇîÝ»ó½ä"%Ƥò @€ @€ @€ @€XŠ@lþüóóó‘MJ_ÎÍÍ¥ßcJý–"Ñ¥xÄ»ã­ñJ¼‡ @€ @€ @€ @€ÙH;Â¥R<"Ãx%ö’‹G$‘¢§RÈ Ž1Å[ó#óSd›ây¤ŸÒvt @€ @€ @€ @€-1¦b)‚Iñþø5Z,Å#e˜â1tS9¾ @€ @€ @€ @€˜Œ€Ódœ]… @€ @€ @€ @€¡bLŠƒ @€ @€ @€ @€ŠĘ*^—'@€ @€ @€ @€ @@ŒI  @€ @€ @€ @€ P±€SÅ àò @€ @€ @€ @€ˆ1© @€ @€ @€ @€*cªx\ž @€ @€ @€ @€1&5@€ @€ @€ @€ @€@ÅbL/€Ë @€ @€ @€ @€ Ƥ @€ @€ @€ @€¨X@Œ©âpy @€ @€ @€ @€ĘÔ @€ @€ @€ @€ ˆ1U¼.O€ @€ @€ @€ @€€“ @€ @€ @€ @€ @ b1¦ŠÀå  @€ @€ @€ @€cR @€ @€ @€ @€T, ÆTñ¸< @€ @€ @€ @€bLj€ @€ @€ @€ @€ŠĘ*^—'@€ @€ @€ @€ @@ŒI  @€ @€ @€ @€ P±€SÅ àò @€ @€ @€ @€ˆ1© @€ @€ @€ @€*cªx\ž @€ @€ @€ @€1&5@€ @€ @€ @€ @€@ÅbL/€Ë @€ @€ @€ @€ Ƥ @€ @€ @€ @€¨X@Œ©âpy @€ @€ @€ @€ĘÔ @€ @€ @€ @€ ˆ1U¼.O€ @€ @€ @€ @€€“ @€ @€ @€ @€ @ b1¦ŠÀå  @€ @€ @€ @€cR @€ @€ @€ @€T, ÆTñ¸< @€ @€ @€ @€bLj€ @€ @€ @€ @€ŠĘ*^—'@€ @€ @€ @€ @@ŒI  @€ @€ @€ @€ P±€SÅ àò @€ @€ @€ @€ˆ1© @€ @€ @€ @€*cªx\ž @€ @€ @€ @€1&5@€ @€ @€ @€ @€@ÅbL/€Ë @€ @€ @€ @€ Ƥ @€ @€ @€ @€¨X@Œ©âpy @€ @€ @€ @€ĘÔ @€ @€ @€ @€ ˆ1U¼.O€ @€ @€ @€ @€€“ @€ @€ @€ @€ @ b1¦ŠÀå  @€ @€ @€ @€cR @€ @€ @€ @€T, ÆTñ¸< @€ @€ @€ @€bLj€ @€ @€ @€ @€ŠĘ*^—'@€ @€ @€ @€ @@ŒI  @€ @€ @€ @€ P±€SÅ àò @€ @€ @€ @€ˆ1© @€ @€ @€ @€*cªx\ž @€ @€ @€ @€1&5@€ @€ @€ @€ @€@ÅbL/€Ë @€ @€ @€ @€ Ƥ @€ @€ @€ @€¨X@Œ©âpy @€ @€ @€ @€ĘÔ @€ @€ @€ @€ ˆ1U¼.O€ @€ @€ @€ @€€“ @€ @€ @€ @€ @ b1¦ŠÀå  @€ @€ @€ @€cR @€ @€ @€ @€T, ÆTñ¸< @€ @€ @€ @€bLj€ @€ @€ @€ @€Š†Æ˜vîܹfÍšU«VÍÍÍå÷Ï{^©øö]ž @€ @€ @€ @€z ÌÏϯn=Ö¯_Ÿît÷îÝ)›”¿24Æ´råÊ-mÙ²%Ž_»vmOâàâ+õž¾»#@€ @€ @€ @€ @ b覴bÅŠˆ+Eî("IiŠŠ'ëÖ­+¾28Æ´}ûö-¥¤wÇéâ×|Nñ†Šççò @€ @€ @€ @€Ô^ âJùvpÑM)ñJžMŠTRtfŠI íÆ”O0:0ÅÁ)Ì”Z9åg©=‚$@€ @€ @€ @€ @ .©S„‘"€1¤x¤mââ±HŒ)¢O© SĘ¢¹Sêé”vª«ËäÜ @€ @€ @€ @€µÈCG]J»ÃE¦´»\Üû¨S™o$—º1¥ÉŸ×~ún @€ @€ @€ @€Š"z”7NJ[˥ʟ1õ´\ŠôStcJGO¦<ÒTñü\ž @€ @€ @€ @€z ä-—ÒmFû¥ØN.=_³fMŠ4 Ž1EPiŸ}ö‰ãÓ#%¡â˜x’z:¥Ýå< @€ @€ @€ @€ 0B âFÑ>)O"ÍÍÍÅ›ãË#Å#žÄÖrñÊàSü^ì—?¶oßž®OâDÑ™ = @€ @€ @€ @€ˆÄQ1‰”BKñˆ>JÑ–)?|è¦r‹^À @€ @€ @€ @€ PŠ€S)ŒNB€ @€ @€ @€ @€ÀøbLãÛ9’ @€ @€ @€ @€RĘJat @€ @€ @€ @€ÆcßΑ @€ @€ @€ @€”" ÆT £“ @€ @€ @€ @€ 0¾€ÓøvŽ$@€ @€ @€ @€ @ 1¦R„ @€ @€ @€ @€ñĘƷs$ @€ @€ @€ @€¥ˆ1•Âè$ @€ @€ @€ @€Œ/ Æ4¾#  @€ @€ @€ @€(E@Œ©F'!@€ @€ @€ @€ @`|1¦ñíI€ @€ @€ @€ @€@)bL¥0:  @€ @€ @€ @€ã ˆ1oçH @€ @€ @€ @€Jc*…ÑI @€ @€ @€ @€_@Œi|;G @€ @€ @€ @€ PŠ€S)ŒNB€ @€ @€ @€ @€ÀøbLãÛ9’ @€ @€ @€ @€RĘJat @€ @€ @€ @€ÆcßΑ @€ @€ @€ @€”" ÆT £“ @€ @€ @€ @€ 0¾€ÓøvŽ$@€ @€ @€ @€ @ 1¦R„ @€ @€ @€ @€ñĘƷs$ @€ @€ @€ @€¥ˆ1•Âè$ @€ @€ @€ @€Œ/ Æ4¾#  @€ @€ @€ @€(E@Œ©F'!@€ @€ @€ @€ @`|1¦ñíI€ @€ @€ @€ @€@)bL¥0:  @€ @€ @€ @€ã ˆ1oçH @€ @€ @€ @€Jc*…ÑI @€ @€ @€ @€_@Œi|;G @€ @€ @€ @€ PŠ€S)ŒNB€ @€ @€ @€ @€ÀøbLãÛ9’ @€ @€ @€ @€RĘJat @€ @€ @€ @€ÆcßΑ @€ @€ @€ @€”" ÆT £“ @€ @€ @€ @€ 0¾€ÓøvŽ$@€ @€ @€ @€ @ 1¦R„ @€ @€ @€ @€ñĘƷs$ @€ @€ @€ @€¥ˆ1•Âè$ @€ @€ @€ @€Œ/ Æ4¾#  @€ @€ @€ @€(E@Œ©F'!@€ @€ @€ @€ @`|1¦ñíI€ @€ @€ @€ @€@)bL¥0:  @€ @€ @€ @€ã ˆ1oçH @€ @€ @€ @€Jc*…ÑI @€ @€ @€ @€_@Œi|;G @€ @€ @€ @€ PŠ€S)ŒNB€ @€ @€ @€ @€ÀøbLãÛ9’ @€ @€ @€ @€RĘJat @€ @€ @€ @€ÆcßΑ @€ @€ @€ @€”" ÆT £“ @€ @€ @€ @€ 0¾€ÓøvŽ$@€ @€ @€ @€ @ 1¦R„ @€ @€ @€ @€ñĘƷs$ @€ @€ @€ @€¥ˆ1•Â8ÎIV­Zµ}ûöqŽt n¨¥•­ÇÚµk×­[‡‡$°sçÎ5kÖÄG#>#ëׯÇB`ùÒ÷áø5¾ÏÍÍ-ß…œ™@.ÿ×?ý °zõj8FÄ·¦T* FLF þƒ˜ÿ e2Wt•:ÄŒŠ?Ås?Õa]ÜÃ0¨X/7 'dâ§MÅ“ ô|C‹¿jðã÷¬•‡OĬ­øŒÌ7¾•õÔ¶ïoÓ¸ô±ˆóóóùû §¸ˆñ#M€¤¿7+*MãB»g=©¶ãߺã/aüÑF…4O@Œ©š5¬‰pª†¾‰W]±bÅ–Ö#~‹º’djâ"›Ó D†)>ñWùGC’i°d(¶øÞ›Š-ýùaɇz#1òªK?ø“꘎3sXüuFü¥Fª33Ë^ÍDwïÞß ¢äR±ùÏb5ËPÑUÓÿZ“_<ž¿¬è¦\–ÀP¨Øø6h @ÈÄ7s8¿¡õÿ«?¨Yð‰˜…UžÁ9Æ £¶‹ÙŽøÒ_jM]%ô¬šŸpòŒÈÿö,>uëë† H¦ôw/ñGï¨öøG1\š$ ÆTÍjÆ7—”8©æò®Ú,â¤ýMq³ÖÖlƈ¿X,þ«I|ËéÆ?# ŒHqÒü-¥êe=U7+ºÄT øqª—oºn>~âêù¡+~*‹lÓtÍÂÝŽ' Æ4ž›£ªð|#äŘzpò¥â?jú0Uõ™­öºbLÕú»ú2 ¤Ï¿­Å_Ÿ¦ÆÏËt9§]&ø‹˜ÿ)ÌO8Å¿¡-¦ôâÿôÍ|™ŠÐi+èù¸Ï~%«à¢Ë* Æ´¬¼ƒOÿ±L? ÆÏçT°»dO7&½1·Â&4Ž€àGÍ1ã ôÔ›¸À¸ŽÛžnL"{`7“oíéÆ4“&=!q6!èZ^&V?í±›éy-ïÔMÈ|¿QbL=8éÛšƒ³ü½Ã¿|Ïòê7xîé¶ÏË;ýs•ÓÔ­x¬`ü¥PZM?áäË70´äÇ¿©+o7õçêf-¯ÙŒ)Ðÿg ¿1)¶žSÏž†K8·ØcaÍ=&›ít‰›íõŸèìóÿ 8ýÅqú»c-y&ºÕ]¬g­}ç©n)\yIþk“SNú_ãÅÔ¶$þòmIEæM ð×­ ZLSYHÿ)Œ¿2oqñý-þ߃Éd5È¿A¥ ¾ý„“¯Wÿ·níjj^ÌnoüeËqyó4 ˆ1MzÕâ‡ÂH/åWÍÿ<éûp½ +¶mÐM…À ô|w?‡¿÷îñé@`¤@1P’:¸ú{m%³ÜbLË-ܰó 4lAë<´Eq§K³Vçõ*÷ÞĘÊõt¶åð|ýÂñçô¿qûgìœâRA䯖ûãYÃó‹1ÕpQÜÒÞ äÿ)L=5ãï²|ÿß{ÕÉŸ¡ø *ug‰uœümÔðŠ=›\û‚®‘[ÚÙ²7zŽ 1¦I/Sü‡³ØDïœI/@¯WÜ"$žk9ÓÄE6§qRÓ»”gŠél 3¢c–&г½—ïÃKcó®½è©:ÿ”²Wš3p°Ó ,r¦ÿ¾›vÞIOÒ¿ˆÔèþÜʲ ˆ1-­/‹€S?kú[ÊÔÈA#½¢OÏR|–å3Yï“ÿüå_õ^+w·ù Ó߯‘bL{ÀW›·öü_îûì³S¾8)¢çjS­n¤L?‘–©é\µcšô²ôÿáGŠI¯Aã®—6kHÆM΄ì•@D—R?ä½:‹ƒ ,&àûðbB~¿|bÕù |߯1Zã»ã4n~&T;ø‡ðh¹^9òÚ­ÍrÞP,wñ[ï<ˉíÜ%ø51¾Ç¢áôàô|C‹/ý=C ©:EÏŸ¿¦êÞÝ,¡ùwûø¶–ÿþ0uÓóŸ$+س‚á㦮ªÝðRzþ¾”C¼‡Àt ˆ1M×z¹[ @€ @€ @€ @€ cj࢚ @€ @€ @€ @€écš®õr· @€ @€ @€ @€(ðÿ×Q’úšê÷IEND®B`‚rabbitmq-server-3.2.4/plugins-src/webmachine-wrapper/webmachine-git/priv/trace/wmtrace.css0000755000000000000000000000275312305126066030501 0ustar rootrootbody { margin:0px; padding:0px; } canvas#v3map { margin-top:2em; z-index: 1; } div#sizetest { width:100%; } div#zoompanel { height:2em; position:fixed; z-index:10; } div#preview { position:absolute; display:none; background:#dddddd; border:1px solid #999999; } div#preview ul { padding: 0px 0px 0px 0.5em; margin: 0px; list-style: none; } div#infopanel { z-index:20; background:#dddddd; position:fixed; top:0px; right:0px; bottom:0px; left:75%; min-width:30em; padding:5px; } div#infocontrols { position:absolute; top:0px; bottom:0px; left:-5px; width:5px; background:#999999; cursor:ew-resize; } div#infocontrols div { position:absolute; left:-15px; width:20px; height:49px; background:#999999; cursor:pointer; } div#infocontrols div.selectedtab { background:#dddddd; border-top: 1px solid #999999; border-left: 1px solid #999999; border-bottom: 1px solid #999999; } div#requesttab { top:2px; } div#responsetab { top:54px; } div#decisiontab { top:106px; } div#requestdetail, div#responsedetail, div#decisiondetail { height:100%; } div#responsedetail, div#decisiondetail { display:none; } div#infopanel ul { list-style:none; padding-left:0px; height:5em; overflow-y:scroll; } pre { height:40%; overflow:scroll; } div#responsebody, div#requestbody { height:70%; overflow-y:scroll; } rabbitmq-server-3.2.4/plugins-src/webmachine-wrapper/webmachine-git/priv/templates/0000755000000000000000000000000012305126066027213 5ustar rootrootrabbitmq-server-3.2.4/plugins-src/webmachine-wrapper/webmachine-git/priv/templates/priv/0000755000000000000000000000000012305126066030173 5ustar rootroot././@LongLink0000000000000000000000000000014600000000000011566 Lustar rootrootrabbitmq-server-3.2.4/plugins-src/webmachine-wrapper/webmachine-git/priv/templates/priv/dispatch.confrabbitmq-server-3.2.4/plugins-src/webmachine-wrapper/webmachine-git/priv/templates/priv/dispatch.con0000644000000000000000000000006512305126066032474 0ustar rootroot%%-*- mode: erlang -*- {[], {{appid}}_resource, []}. rabbitmq-server-3.2.4/plugins-src/webmachine-wrapper/webmachine-git/priv/templates/src/0000755000000000000000000000000012305126066030002 5ustar rootroot././@LongLink0000000000000000000000000000014600000000000011566 Lustar rootrootrabbitmq-server-3.2.4/plugins-src/webmachine-wrapper/webmachine-git/priv/templates/src/wmskel_sup.erlrabbitmq-server-3.2.4/plugins-src/webmachine-wrapper/webmachine-git/priv/templates/src/wmskel_sup.er0000644000000000000000000000417012305126066032525 0ustar rootroot%% @author author %% @copyright YYYY author. %% @doc Supervisor for the {{appid}} application. -module({{appid}}_sup). -author('author '). -behaviour(supervisor). %% External exports -export([start_link/0, upgrade/0]). %% supervisor callbacks -export([init/1]). %% @spec start_link() -> ServerRet %% @doc API for starting the supervisor. start_link() -> supervisor:start_link({local, ?MODULE}, ?MODULE, []). %% @spec upgrade() -> ok %% @doc Add processes if necessary. upgrade() -> {ok, {_, Specs}} = init([]), Old = sets:from_list( [Name || {Name, _, _, _} <- supervisor:which_children(?MODULE)]), New = sets:from_list([Name || {Name, _, _, _, _, _} <- Specs]), Kill = sets:subtract(Old, New), sets:fold(fun (Id, ok) -> supervisor:terminate_child(?MODULE, Id), supervisor:delete_child(?MODULE, Id), ok end, ok, Kill), [supervisor:start_child(?MODULE, Spec) || Spec <- Specs], ok. %% @spec init([]) -> SupervisorTree %% @doc supervisor callback. init([]) -> Ip = case os:getenv("WEBMACHINE_IP") of false -> "0.0.0.0"; Any -> Any end, {ok, App} = application:get_application(?MODULE), {ok, Dispatch} = file:consult(filename:join([priv_dir(App), "dispatch.conf"])), Port = case os:getenv("WEBMACHINE_PORT") of false -> 8000; AnyPort -> AnyPort end, WebConfig = [ {ip, Ip}, {port, Port}, {log_dir, "priv/log"}, {dispatch, Dispatch}], Web = {webmachine_mochiweb, {webmachine_mochiweb, start, [WebConfig]}, permanent, 5000, worker, [mochiweb_socket_server]}, Processes = [Web], {ok, { {one_for_one, 10, 10}, Processes} }. %% %% @doc return the priv dir priv_dir(Mod) -> case code:priv_dir(Mod) of {error, bad_name} -> Ebin = filename:dirname(code:which(Mod)), filename:join(filename:dirname(Ebin), "priv"); PrivDir -> PrivDir end. rabbitmq-server-3.2.4/plugins-src/webmachine-wrapper/webmachine-git/priv/templates/src/wmskel.erl0000644000000000000000000000242312305126066032011 0ustar rootroot%% @author author %% @copyright YYYY author. %% @doc {{appid}} startup code -module({{appid}}). -author('author '). -export([start/0, start_link/0, stop/0]). ensure_started(App) -> case application:start(App) of ok -> ok; {error, {already_started, App}} -> ok end. %% @spec start_link() -> {ok,Pid::pid()} %% @doc Starts the app for inclusion in a supervisor tree start_link() -> ensure_started(inets), ensure_started(crypto), ensure_started(mochiweb), application:set_env(webmachine, webmachine_logger_module, webmachine_logger), ensure_started(webmachine), {{appid}}_sup:start_link(). %% @spec start() -> ok %% @doc Start the {{appid}} server. start() -> ensure_started(inets), ensure_started(crypto), ensure_started(mochiweb), application:set_env(webmachine, webmachine_logger_module, webmachine_logger), ensure_started(webmachine), application:start({{appid}}). %% @spec stop() -> ok %% @doc Stop the {{appid}} server. stop() -> Res = application:stop({{appid}}), application:stop(webmachine), application:stop(mochiweb), application:stop(crypto), application:stop(inets), Res. ././@LongLink0000000000000000000000000000015300000000000011564 Lustar rootrootrabbitmq-server-3.2.4/plugins-src/webmachine-wrapper/webmachine-git/priv/templates/src/wmskel_resource.erlrabbitmq-server-3.2.4/plugins-src/webmachine-wrapper/webmachine-git/priv/templates/src/wmskel_resour0000644000000000000000000000052512305126066032630 0ustar rootroot%% @author author %% @copyright YYYY author. %% @doc Example webmachine_resource. -module({{appid}}_resource). -export([init/1, to_html/2]). -include_lib("webmachine/include/webmachine.hrl"). init([]) -> {ok, undefined}. to_html(ReqData, State) -> {"Hello, new world", ReqData, State}. ././@LongLink0000000000000000000000000000014600000000000011566 Lustar rootrootrabbitmq-server-3.2.4/plugins-src/webmachine-wrapper/webmachine-git/priv/templates/src/wmskel_app.erlrabbitmq-server-3.2.4/plugins-src/webmachine-wrapper/webmachine-git/priv/templates/src/wmskel_app.er0000644000000000000000000000076612305126066032505 0ustar rootroot%% @author author %% @copyright YYYY author. %% @doc Callbacks for the {{appid}} application. -module({{appid}}_app). -author('author '). -behaviour(application). -export([start/2,stop/1]). %% @spec start(_Type, _StartArgs) -> ServerRet %% @doc application start callback for {{appid}}. start(_Type, _StartArgs) -> {{appid}}_sup:start_link(). %% @spec stop(_State) -> ServerRet %% @doc application stop callback for {{appid}}. stop(_State) -> ok. ././@LongLink0000000000000000000000000000014600000000000011566 Lustar rootrootrabbitmq-server-3.2.4/plugins-src/webmachine-wrapper/webmachine-git/priv/templates/src/wmskel.app.srcrabbitmq-server-3.2.4/plugins-src/webmachine-wrapper/webmachine-git/priv/templates/src/wmskel.app.sr0000644000000000000000000000057412305126066032437 0ustar rootroot%%-*- mode: erlang -*- {application, {{appid}}, [ {description, "{{appid}}"}, {vsn, "1"}, {modules, []}, {registered, []}, {applications, [ kernel, stdlib, inets, crypto, mochiweb, webmachine ]}, {mod, { {{appid}}_app, []}}, {env, []} ]}. rabbitmq-server-3.2.4/plugins-src/webmachine-wrapper/webmachine-git/priv/templates/README0000644000000000000000000000174412305126066030101 0ustar rootrootProject Skeleton for the {{appid}} app. You should find in this directory: README : this file Makefile : simple make commands rebar : the Rebar build tool for Erlang applications rebar.config : configuration for Rebar start.sh : simple startup script for running {{appid}} /ebin /{{appid}}.app : the Erlang app specification /src /{{appid}}_app.erl : base module for the Erlang application /{{appid}}_sup.erl : OTP supervisor for the application /{{appid}}_resource.erl : a simple example Webmachine resource /priv /dispatch.conf : the Webmachine URL-dispatching table /www : a convenient place to put your static web content You probably want to do one of a couple of things at this point: 0. Build the skeleton application: $ make - or - $ ./rebar compile 1. Start up the skeleton application: $ ./start.sh 2. Change the basic application: edit src/{{appid}}_resource.erl 3. Add some new resources: edit src/YOUR_NEW_RESOURCE.erl edit priv/dispatch.conf rabbitmq-server-3.2.4/plugins-src/webmachine-wrapper/webmachine-git/priv/templates/Makefile0000644000000000000000000000034512305126066030655 0ustar rootrootERL ?= erl APP := {{appid}} .PHONY: deps all: deps @./rebar compile deps: @./rebar get-deps clean: @./rebar clean distclean: clean @./rebar delete-deps docs: @erl -noshell -run edoc_run application '$(APP)' '"."' '[]' rabbitmq-server-3.2.4/plugins-src/webmachine-wrapper/webmachine-git/priv/templates/wmskel.template0000644000000000000000000000236112305126066032254 0ustar rootroot%%-*- mode: erlang -*- %% Basic Webmachine application skeleton %% Variables: %% appid: name of the application to build %% default = "wmskel" %% webmachine: path to webmachine from this template %% default = "../.." %% prefix: path where the application should be created %% default = "." {variables, [{appid, "wmskel"}, {webmachine, "../.."}, {prefix, "."}]}. %% main project files {template, "README", "{{prefix}}/README"}. {template, "Makefile", "{{prefix}}/Makefile"}. {template, "rebar.config", "{{prefix}}/rebar.config"}. {file, "{{webmachine}}/rebar", "{{prefix}}/rebar"}. {chmod, 8#744, "{{prefix}}/rebar"}. {template, "start.sh", "{{prefix}}/start.sh"}. {chmod, 8#744, "{{prefix}}/start.sh"}. {template, "src/wmskel.app.src", "{{prefix}}/src/{{appid}}.app.src"}. {template, "src/wmskel.erl", "{{prefix}}/src/{{appid}}.erl"}. {template, "src/wmskel_app.erl", "{{prefix}}/src/{{appid}}_app.erl"}. {template, "src/wmskel_sup.erl", "{{prefix}}/src/{{appid}}_sup.erl"}. {template, "src/wmskel_resource.erl", "{{prefix}}/src/{{appid}}_resource.erl"}. {template, "priv/dispatch.conf", "{{prefix}}/priv/dispatch.conf"}. {dir, "{{prefix}}/priv/www"}. %% dependencies {dir, "{{prefix}}/deps"}. rabbitmq-server-3.2.4/plugins-src/webmachine-wrapper/webmachine-git/priv/templates/rebar.config0000644000000000000000000000015612305126066031477 0ustar rootroot%%-*- mode: erlang -*- {deps, [{webmachine, "1.10.*", {git, "git://github.com/basho/webmachine", "HEAD"}}]}. rabbitmq-server-3.2.4/plugins-src/webmachine-wrapper/webmachine-git/priv/templates/start.sh0000644000000000000000000000015412305126066030704 0ustar rootroot#!/bin/sh cd `dirname $0` exec erl -pa $PWD/ebin $PWD/deps/*/ebin -boot start_sasl -s reloader -s {{appid}} rabbitmq-server-3.2.4/plugins-src/webmachine-wrapper/webmachine-git/start-dev.sh0000755000000000000000000000015512305126066026506 0ustar rootroot#!/bin/sh cd `dirname $0` exec erl -pa $PWD/ebin $PWD/deps/*/ebin -boot start_sasl -s reloader -s webmachine rabbitmq-server-3.2.4/plugins-src/webmachine-wrapper/webmachine-git/src/0000755000000000000000000000000012305126066025024 5ustar rootrootrabbitmq-server-3.2.4/plugins-src/webmachine-wrapper/webmachine-git/src/webmachine_error.erl0000644000000000000000000000354012305126066031045 0ustar rootroot%% Copyright (c) 2011-2013 Basho Technologies, Inc. All Rights Reserved. %% %% This file is provided to you under the Apache License, %% Version 2.0 (the "License"); you may not use this file %% except in compliance with the License. You may obtain %% a copy of the License at %% %% http://www.apache.org/licenses/LICENSE-2.0 %% %% Unless required by applicable law or agreed to in writing, %% software distributed under the License is distributed on an %% "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY %% KIND, either express or implied. See the License for the %% specific language governing permissions and limitations %% under the License. %% @doc Default HTTP error reasons for webmachine error responsesf -module(webmachine_error). -export([reason/1]). -spec reason(pos_integer()) -> string(). reason(400) -> "Bad Request"; reason(401) -> "Unauthorized"; reason(402) -> "Payment Requested"; reason(403) -> "Forbidden"; reason(404) -> "Not Found"; reason(405) -> "Method Not Allowed"; reason(406) -> "Not Acceptable"; reason(407) -> "Proxy Authentication Required"; reason(408) -> "Request Timeout"; reason(409) -> "Conflict"; reason(410) -> "Gone"; reason(411) -> "Length Required"; reason(412) -> "Precondition Failed"; reason(413) -> "Request Entity Too Large"; reason(414) -> "Request-URI Too Long"; reason(415) -> "Unsupported Media Type"; reason(416) -> "Request Range Not Satisfiable"; reason(417) -> "Expectation Failed"; reason(500) -> "Internal Server Error"; reason(501) -> "Not Implemented"; reason(502) -> "Bad Gateway"; reason(503) -> "Service Unavailable"; reason(504) -> "Gateway Timeout"; reason(505) -> "HTTP Version Not Supported"; reason(Code) when Code >= 400, Code < 500 -> "Client Error"; reason(Code) when Code >= 500 -> "Server Error". ././@LongLink0000000000000000000000000000014500000000000011565 Lustar rootrootrabbitmq-server-3.2.4/plugins-src/webmachine-wrapper/webmachine-git/src/webmachine_decision_core.erlrabbitmq-server-3.2.4/plugins-src/webmachine-wrapper/webmachine-git/src/webmachine_decision_core.erl0000644000000000000000000006357412305126066032536 0ustar rootroot%% @author Justin Sheehy %% @author Andy Gross %% @author Bryan Fink %% @copyright 2007-2009 Basho Technologies %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. %% You may obtain a copy of the License at %% %% http://www.apache.org/licenses/LICENSE-2.0 %% %% Unless required by applicable law or agreed to in writing, software %% distributed under the License is distributed on an "AS IS" BASIS, %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %% See the License for the specific language governing permissions and %% limitations under the License. %% @doc Decision core for webmachine -module(webmachine_decision_core). -author('Justin Sheehy '). -author('Andy Gross '). -author('Bryan Fink '). -export([handle_request/2]). -export([do_log/1]). -include("webmachine_logger.hrl"). handle_request(Resource, ReqState) -> [erase(X) || X <- [decision, code, req_body, bytes_written, tmp_reqstate]], put(resource, Resource), put(reqstate, ReqState), try d(v3b13) catch error:_ -> error_response(erlang:get_stacktrace()) end. wrcall(X) -> RS0 = get(reqstate), Req = webmachine_request:new(RS0), {Response, RS1} = Req:call(X), put(reqstate, RS1), Response. resource_call(Fun) -> Resource = get(resource), {Reply, NewResource, NewRS} = Resource:do(Fun,get()), put(resource, NewResource), put(reqstate, NewRS), Reply. get_header_val(H) -> wrcall({get_req_header, H}). method() -> wrcall(method). d(DecisionID) -> put(decision, DecisionID), log_decision(DecisionID), decision(DecisionID). respond(Code) when is_integer(Code) -> respond({Code, undefined}); respond({_, _}=CodeAndPhrase) -> Resource = get(resource), EndTime = now(), respond(CodeAndPhrase, Resource, EndTime). respond({Code, _ReasonPhrase}=CodeAndPhrase, Resource, EndTime) when Code >= 400, Code < 600 -> error_response(CodeAndPhrase, Resource, EndTime); respond({304, _ReasonPhrase}=CodeAndPhrase, Resource, EndTime) -> wrcall({remove_resp_header, "Content-Type"}), case resource_call(generate_etag) of undefined -> nop; ETag -> wrcall({set_resp_header, "ETag", webmachine_util:quoted_string(ETag)}) end, case resource_call(expires) of undefined -> nop; Exp -> wrcall({set_resp_header, "Expires", webmachine_util:rfc1123_date(Exp)}) end, finish_response(CodeAndPhrase, Resource, EndTime); respond(CodeAndPhrase, Resource, EndTime) -> finish_response(CodeAndPhrase, Resource, EndTime). finish_response({Code, _}=CodeAndPhrase, Resource, EndTime) -> put(code, Code), wrcall({set_response_code, CodeAndPhrase}), resource_call(finish_request), wrcall({send_response, CodeAndPhrase}), RMod = wrcall({get_metadata, 'resource_module'}), Notes = wrcall(notes), LogData0 = wrcall(log_data), LogData = LogData0#wm_log_data{resource_module=RMod, end_time=EndTime, notes=Notes}, spawn(fun() -> do_log(LogData) end), Resource:stop(). error_response(Reason) -> error_response(500, Reason). error_response(Code, Reason) -> Resource = get(resource), EndTime = now(), error_response({Code, undefined}, Reason, Resource, EndTime). error_response({Code, _}=CodeAndPhrase, Resource, EndTime) -> error_response({Code, _}=CodeAndPhrase, webmachine_error:reason(Code), Resource, EndTime). error_response({Code, _}=CodeAndPhrase, Reason, Resource, EndTime) -> {ok, ErrorHandler} = application:get_env(webmachine, error_handler), {ErrorHTML, ReqState} = ErrorHandler:render_error( Code, {webmachine_request,get(reqstate)}, Reason), put(reqstate, ReqState), wrcall({set_resp_body, ErrorHTML}), finish_response(CodeAndPhrase, Resource, EndTime). decision_test(Test,TestVal,TrueFlow,FalseFlow) -> case Test of {error, Reason} -> error_response(Reason); {error, Reason0, Reason1} -> error_response({Reason0, Reason1}); {halt, Code} -> respond(Code); TestVal -> decision_flow(TrueFlow, Test); _ -> decision_flow(FalseFlow, Test) end. decision_test_fn({error, Reason}, _TestFn, _TrueFlow, _FalseFlow) -> error_response(Reason); decision_test_fn({error, R0, R1}, _TestFn, _TrueFlow, _FalseFlow) -> error_response({R0, R1}); decision_test_fn({halt, Code}, _TestFn, _TrueFlow, _FalseFlow) -> respond(Code); decision_test_fn(Test,TestFn,TrueFlow,FalseFlow) -> case TestFn(Test) of true -> decision_flow(TrueFlow, Test); false -> decision_flow(FalseFlow, Test) end. decision_flow(X, TestResult) when is_integer(X) -> if X >= 500 -> error_response(X, TestResult); true -> respond(X) end; decision_flow(X, _TestResult) when is_atom(X) -> d(X). do_log(LogData) -> webmachine_log:log_access(LogData). log_decision(DecisionID) -> Resource = get(resource), Resource:log_d(DecisionID). %% "Service Available" decision(v3b13) -> decision_test(resource_call(ping), pong, v3b13b, 503); decision(v3b13b) -> decision_test(resource_call(service_available), true, v3b12, 503); %% "Known method?" decision(v3b12) -> decision_test(lists:member(method(), resource_call(known_methods)), true, v3b11, 501); %% "URI too long?" decision(v3b11) -> decision_test(resource_call(uri_too_long), true, 414, v3b10); %% "Method allowed?" decision(v3b10) -> Methods = resource_call(allowed_methods), case lists:member(method(), Methods) of true -> d(v3b9); false -> wrcall({set_resp_headers, [{"Allow", string:join([atom_to_list(M) || M <- Methods], ", ")}]}), respond(405) end; %% "Content-MD5 present?" decision(v3b9) -> decision_test(get_header_val("content-md5"), undefined, v3b9b, v3b9a); %% "Content-MD5 valid?" decision(v3b9a) -> case resource_call(validate_content_checksum) of {error, Reason} -> error_response(Reason); {halt, Code} -> respond(Code); not_validated -> Checksum = base64:decode(get_header_val("content-md5")), BodyHash = compute_body_md5(), case BodyHash =:= Checksum of true -> d(v3b9b); _ -> respond(400) end; false -> respond(400); _ -> d(v3b9b) end; %% "Malformed?" decision(v3b9b) -> decision_test(resource_call(malformed_request), true, 400, v3b8); %% "Authorized?" decision(v3b8) -> case resource_call(is_authorized) of true -> d(v3b7); {error, Reason} -> error_response(Reason); {halt, Code} -> respond(Code); AuthHead -> wrcall({set_resp_header, "WWW-Authenticate", AuthHead}), respond(401) end; %% "Forbidden?" decision(v3b7) -> decision_test(resource_call(forbidden), true, 403, v3b6); %% "Okay Content-* Headers?" decision(v3b6) -> decision_test(resource_call(valid_content_headers), true, v3b5, 501); %% "Known Content-Type?" decision(v3b5) -> decision_test(resource_call(known_content_type), true, v3b4, 415); %% "Req Entity Too Large?" decision(v3b4) -> decision_test(resource_call(valid_entity_length), true, v3b3, 413); %% "OPTIONS?" decision(v3b3) -> case method() of 'OPTIONS' -> Hdrs = resource_call(options), wrcall({set_resp_headers, Hdrs}), respond(200); _ -> d(v3c3) end; %% Accept exists? decision(v3c3) -> PTypes = [Type || {Type,_Fun} <- resource_call(content_types_provided)], case get_header_val("accept") of undefined -> wrcall({set_metadata, 'content-type', hd(PTypes)}), d(v3d4); _ -> d(v3c4) end; %% Acceptable media type available? decision(v3c4) -> PTypes = [Type || {Type,_Fun} <- resource_call(content_types_provided)], AcceptHdr = get_header_val("accept"), case webmachine_util:choose_media_type(PTypes, AcceptHdr) of none -> respond(406); MType -> wrcall({set_metadata, 'content-type', MType}), d(v3d4) end; %% Accept-Language exists? decision(v3d4) -> decision_test(get_header_val("accept-language"), undefined, v3e5, v3d5); %% Acceptable Language available? %% WMACH-46 (do this as proper conneg) decision(v3d5) -> decision_test(resource_call(language_available), true, v3e5, 406); %% Accept-Charset exists? decision(v3e5) -> case get_header_val("accept-charset") of undefined -> decision_test(choose_charset("*"), none, 406, v3f6); _ -> d(v3e6) end; %% Acceptable Charset available? decision(v3e6) -> decision_test(choose_charset(get_header_val("accept-charset")), none, 406, v3f6); %% Accept-Encoding exists? % (also, set content-type header here, now that charset is chosen) decision(v3f6) -> CType = wrcall({get_metadata, 'content-type'}), CSet = case wrcall({get_metadata, 'chosen-charset'}) of undefined -> ""; CS -> "; charset=" ++ CS end, wrcall({set_resp_header, "Content-Type", CType ++ CSet}), case get_header_val("accept-encoding") of undefined -> decision_test(choose_encoding("identity;q=1.0,*;q=0.5"), none, 406, v3g7); _ -> d(v3f7) end; %% Acceptable encoding available? decision(v3f7) -> decision_test(choose_encoding(get_header_val("accept-encoding")), none, 406, v3g7); %% "Resource exists?" decision(v3g7) -> % this is the first place after all conneg, so set Vary here case variances() of [] -> nop; Variances -> wrcall({set_resp_header, "Vary", string:join(Variances, ", ")}) end, decision_test(resource_call(resource_exists), true, v3g8, v3h7); %% "If-Match exists?" decision(v3g8) -> decision_test(get_header_val("if-match"), undefined, v3h10, v3g9); %% "If-Match: * exists" decision(v3g9) -> decision_test(get_header_val("if-match"), "*", v3h10, v3g11); %% "ETag in If-Match" decision(v3g11) -> ETags = webmachine_util:split_quoted_strings(get_header_val("if-match")), decision_test_fn(resource_call(generate_etag), fun(ETag) -> lists:member(ETag, ETags) end, v3h10, 412); %% "If-Match exists" %% (note: need to reflect this change at in next version of diagram) decision(v3h7) -> decision_test(get_header_val("if-match"), undefined, v3i7, 412); %% "If-unmodified-since exists?" decision(v3h10) -> decision_test(get_header_val("if-unmodified-since"),undefined,v3i12,v3h11); %% "I-UM-S is valid date?" decision(v3h11) -> IUMSDate = get_header_val("if-unmodified-since"), decision_test(webmachine_util:convert_request_date(IUMSDate), bad_date, v3i12, v3h12); %% "Last-Modified > I-UM-S?" decision(v3h12) -> ReqDate = get_header_val("if-unmodified-since"), ReqErlDate = webmachine_util:convert_request_date(ReqDate), ResErlDate = resource_call(last_modified), decision_test(ResErlDate > ReqErlDate, true, 412, v3i12); %% "Moved permanently? (apply PUT to different URI)" decision(v3i4) -> case resource_call(moved_permanently) of {true, MovedURI} -> wrcall({set_resp_header, "Location", MovedURI}), respond(301); false -> d(v3p3); {error, Reason} -> error_response(Reason); {halt, Code} -> respond(Code) end; %% PUT? decision(v3i7) -> decision_test(method(), 'PUT', v3i4, v3k7); %% "If-none-match exists?" decision(v3i12) -> decision_test(get_header_val("if-none-match"), undefined, v3l13, v3i13); %% "If-None-Match: * exists?" decision(v3i13) -> decision_test(get_header_val("if-none-match"), "*", v3j18, v3k13); %% GET or HEAD? decision(v3j18) -> decision_test(lists:member(method(),['GET','HEAD']), true, 304, 412); %% "Moved permanently?" decision(v3k5) -> case resource_call(moved_permanently) of {true, MovedURI} -> wrcall({set_resp_header, "Location", MovedURI}), respond(301); false -> d(v3l5); {error, Reason} -> error_response(Reason); {halt, Code} -> respond(Code) end; %% "Previously existed?" decision(v3k7) -> decision_test(resource_call(previously_existed), true, v3k5, v3l7); %% "Etag in if-none-match?" decision(v3k13) -> ETags = webmachine_util:split_quoted_strings(get_header_val("if-none-match")), decision_test_fn(resource_call(generate_etag), %% Membership test is a little counter-intuitive here; if the %% provided ETag is a member, we follow the error case out %% via v3j18. fun(ETag) -> lists:member(ETag, ETags) end, v3j18, v3l13); %% "Moved temporarily?" decision(v3l5) -> case resource_call(moved_temporarily) of {true, MovedURI} -> wrcall({set_resp_header, "Location", MovedURI}), respond(307); false -> d(v3m5); {error, Reason} -> error_response(Reason); {halt, Code} -> respond(Code) end; %% "POST?" decision(v3l7) -> decision_test(method(), 'POST', v3m7, 404); %% "IMS exists?" decision(v3l13) -> decision_test(get_header_val("if-modified-since"), undefined, v3m16, v3l14); %% "IMS is valid date?" decision(v3l14) -> IMSDate = get_header_val("if-modified-since"), decision_test(webmachine_util:convert_request_date(IMSDate), bad_date, v3m16, v3l15); %% "IMS > Now?" decision(v3l15) -> NowDateTime = calendar:universal_time(), ReqDate = get_header_val("if-modified-since"), ReqErlDate = webmachine_util:convert_request_date(ReqDate), decision_test(ReqErlDate > NowDateTime, true, v3m16, v3l17); %% "Last-Modified > IMS?" decision(v3l17) -> ReqDate = get_header_val("if-modified-since"), ReqErlDate = webmachine_util:convert_request_date(ReqDate), ResErlDate = resource_call(last_modified), decision_test(ResErlDate =:= undefined orelse ResErlDate > ReqErlDate, true, v3m16, 304); %% "POST?" decision(v3m5) -> decision_test(method(), 'POST', v3n5, 410); %% "Server allows POST to missing resource?" decision(v3m7) -> decision_test(resource_call(allow_missing_post), true, v3n11, 404); %% "DELETE?" decision(v3m16) -> decision_test(method(), 'DELETE', v3m20, v3n16); %% DELETE enacted immediately? %% Also where DELETE is forced. decision(v3m20) -> Result = resource_call(delete_resource), %% DELETE may have body and TCP connection will be closed unless body is read. %% See mochiweb_request:should_close. maybe_flush_body_stream(), decision_test(Result, true, v3m20b, 500); decision(v3m20b) -> decision_test(resource_call(delete_completed), true, v3o20, 202); %% "Server allows POST to missing resource?" decision(v3n5) -> decision_test(resource_call(allow_missing_post), true, v3n11, 410); %% "Redirect?" decision(v3n11) -> Stage1 = case resource_call(post_is_create) of true -> case resource_call(create_path) of undefined -> error_response("post_is_create w/o create_path"); NewPath -> case is_list(NewPath) of false -> error_response({"create_path not a string", NewPath}); true -> BaseUri = case resource_call(base_uri) of undefined -> wrcall(base_uri); Any -> case [lists:last(Any)] of "/" -> lists:sublist(Any, erlang:length(Any) - 1); _ -> Any end end, FullPath = filename:join(["/", wrcall(path), NewPath]), wrcall({set_disp_path, NewPath}), case wrcall({get_resp_header, "Location"}) of undefined -> wrcall({set_resp_header, "Location", BaseUri ++ FullPath}); _ -> ok end, Res = accept_helper(), case Res of {respond, Code} -> respond(Code); {halt, Code} -> respond(Code); {error, _,_} -> error_response(Res); {error, _} -> error_response(Res); _ -> stage1_ok end end end; _ -> case resource_call(process_post) of true -> encode_body_if_set(), stage1_ok; {halt, Code} -> respond(Code); Err -> error_response(Err) end end, case Stage1 of stage1_ok -> case wrcall(resp_redirect) of true -> case wrcall({get_resp_header, "Location"}) of undefined -> Reason = "Response had do_redirect but no Location", error_response(500, Reason); _ -> respond(303) end; _ -> d(v3p11) end; _ -> nop end; %% "POST?" decision(v3n16) -> decision_test(method(), 'POST', v3n11, v3o16); %% Conflict? decision(v3o14) -> case resource_call(is_conflict) of true -> respond(409); _ -> Res = accept_helper(), case Res of {respond, Code} -> respond(Code); {halt, Code} -> respond(Code); {error, _,_} -> error_response(Res); {error, _} -> error_response(Res); _ -> d(v3p11) end end; %% "PUT?" decision(v3o16) -> decision_test(method(), 'PUT', v3o14, v3o18); %% Multiple representations? % (also where body generation for GET and HEAD is done) decision(v3o18) -> BuildBody = case method() of 'GET' -> true; 'HEAD' -> true; _ -> false end, FinalBody = case BuildBody of true -> case resource_call(generate_etag) of undefined -> nop; ETag -> wrcall({set_resp_header, "ETag", webmachine_util:quoted_string(ETag)}) end, CT = wrcall({get_metadata, 'content-type'}), case resource_call(last_modified) of undefined -> nop; LM -> wrcall({set_resp_header, "Last-Modified", webmachine_util:rfc1123_date(LM)}) end, case resource_call(expires) of undefined -> nop; Exp -> wrcall({set_resp_header, "Expires", webmachine_util:rfc1123_date(Exp)}) end, F = hd([Fun || {Type,Fun} <- resource_call(content_types_provided), CT =:= webmachine_util:format_content_type(Type)]), resource_call(F); false -> nop end, case FinalBody of {error, _} -> error_response(FinalBody); {error, _,_} -> error_response(FinalBody); {halt, Code} -> respond(Code); nop -> d(v3o18b); _ -> wrcall({set_resp_body, encode_body(FinalBody)}), d(v3o18b) end; decision(v3o18b) -> decision_test(resource_call(multiple_choices), true, 300, 200); %% Response includes an entity? decision(v3o20) -> decision_test(wrcall(has_resp_body), true, v3o18, 204); %% Conflict? decision(v3p3) -> case resource_call(is_conflict) of true -> respond(409); _ -> Res = accept_helper(), case Res of {respond, Code} -> respond(Code); {halt, Code} -> respond(Code); {error, _,_} -> error_response(Res); {error, _} -> error_response(Res); _ -> d(v3p11) end end; %% New resource? (at this point boils down to "has location header") decision(v3p11) -> case wrcall({get_resp_header, "Location"}) of undefined -> d(v3o20); _ -> respond(201) end. accept_helper() -> accept_helper(get_header_val("Content-Type")). accept_helper(undefined) -> accept_helper("application/octet-stream"); accept_helper([]) -> accept_helper("application/octet-stream"); accept_helper(CT) -> {MT, MParams} = webmachine_util:media_type_to_detail(CT), wrcall({set_metadata, 'mediaparams', MParams}), case [Fun || {Type,Fun} <- resource_call(content_types_accepted), MT =:= Type] of [] -> {respond,415}; AcceptedContentList -> F = hd(AcceptedContentList), case resource_call(F) of true -> encode_body_if_set(), true; Result -> Result end end. encode_body_if_set() -> case wrcall(has_resp_body) of true -> Body = wrcall(resp_body), wrcall({set_resp_body, encode_body(Body)}), true; _ -> false end. encode_body(Body) -> ChosenCSet = wrcall({get_metadata, 'chosen-charset'}), Charsetter = case resource_call(charsets_provided) of no_charset -> fun(X) -> X end; CP -> hd([Fun || {CSet,Fun} <- CP, ChosenCSet =:= CSet]) end, ChosenEnc = wrcall({get_metadata, 'content-encoding'}), Encoder = hd([Fun || {Enc,Fun} <- resource_call(encodings_provided), ChosenEnc =:= Enc]), case Body of {stream, StreamBody} -> {stream, make_encoder_stream(Encoder, Charsetter, StreamBody)}; {known_length_stream, 0, _StreamBody} -> {known_length_stream, 0, empty_stream()}; {known_length_stream, Size, StreamBody} -> case method() of 'HEAD' -> {known_length_stream, Size, empty_stream()}; _ -> {known_length_stream, Size, make_encoder_stream(Encoder, Charsetter, StreamBody)} end; {stream, Size, Fun} -> {stream, Size, make_size_encoder_stream(Encoder, Charsetter, Fun)}; {writer, BodyFun} -> {writer, {Encoder, Charsetter, BodyFun}}; _ -> Encoder(Charsetter(iolist_to_binary(Body))) end. %% @private empty_stream() -> {<<>>, fun() -> {<<>>, done} end}. make_encoder_stream(Encoder, Charsetter, {Body, done}) -> {Encoder(Charsetter(Body)), done}; make_encoder_stream(Encoder, Charsetter, {Body, Next}) -> {Encoder(Charsetter(Body)), fun() -> make_encoder_stream(Encoder, Charsetter, Next()) end}. make_size_encoder_stream(Encoder, Charsetter, Fun) -> fun(Start, End) -> make_encoder_stream(Encoder, Charsetter, Fun(Start, End)) end. choose_encoding(AccEncHdr) -> Encs = [Enc || {Enc,_Fun} <- resource_call(encodings_provided)], case webmachine_util:choose_encoding(Encs, AccEncHdr) of none -> none; ChosenEnc -> case ChosenEnc of "identity" -> nop; _ -> wrcall({set_resp_header, "Content-Encoding",ChosenEnc}) end, wrcall({set_metadata, 'content-encoding',ChosenEnc}), ChosenEnc end. choose_charset(AccCharHdr) -> case resource_call(charsets_provided) of no_charset -> no_charset; CL -> CSets = [CSet || {CSet,_Fun} <- CL], case webmachine_util:choose_charset(CSets, AccCharHdr) of none -> none; Charset -> wrcall({set_metadata, 'chosen-charset',Charset}), Charset end end. variances() -> Accept = case length(resource_call(content_types_provided)) of 1 -> []; 0 -> []; _ -> ["Accept"] end, AcceptEncoding = case length(resource_call(encodings_provided)) of 1 -> []; 0 -> []; _ -> ["Accept-Encoding"] end, AcceptCharset = case resource_call(charsets_provided) of no_charset -> []; CP -> case length(CP) of 1 -> []; 0 -> []; _ -> ["Accept-Charset"] end end, Accept ++ AcceptEncoding ++ AcceptCharset ++ resource_call(variances). md5(Bin) -> erlang:md5(Bin). md5_init() -> erlang:md5_init(). md5_update(Ctx, Bin) -> erlang:md5_update(Ctx, Bin). md5_final(Ctx) -> erlang:md5_final(Ctx). compute_body_md5() -> case wrcall({req_body, 52428800}) of stream_conflict -> compute_body_md5_stream(); Body -> md5(Body) end. compute_body_md5_stream() -> MD5Ctx = md5_init(), compute_body_md5_stream(MD5Ctx, wrcall({stream_req_body, 8192}), <<>>). compute_body_md5_stream(MD5, {Hunk, done}, Body) -> %% Save the body so it can be retrieved later put(reqstate, wrq:set_resp_body(Body, get(reqstate))), md5_final(md5_update(MD5, Hunk)); compute_body_md5_stream(MD5, {Hunk, Next}, Body) -> compute_body_md5_stream(md5_update(MD5, Hunk), Next(), <>). maybe_flush_body_stream() -> maybe_flush_body_stream(wrcall({stream_req_body, 8192})). maybe_flush_body_stream(stream_conflict) -> ok; maybe_flush_body_stream({_Hunk, done}) -> ok; maybe_flush_body_stream({_Hunk, Next}) -> maybe_flush_body_stream(Next()). rabbitmq-server-3.2.4/plugins-src/webmachine-wrapper/webmachine-git/src/webmachine_log_handler.erl0000644000000000000000000000746112305126066032200 0ustar rootroot%% Copyright (c) 2011-2013 Basho Technologies, Inc. All Rights Reserved. %% %% This file is provided to you under the Apache License, %% Version 2.0 (the "License"); you may not use this file %% except in compliance with the License. You may obtain %% a copy of the License at %% %% http://www.apache.org/licenses/LICENSE-2.0 %% %% Unless required by applicable law or agreed to in writing, %% software distributed under the License is distributed on an %% "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY %% KIND, either express or implied. See the License for the %% specific language governing permissions and limitations %% under the License. %% @doc Default log handler for webmachine -module(webmachine_log_handler). -behaviour(gen_event). %% gen_event callbacks -export([init/1, handle_call/2, handle_event/2, handle_info/2, terminate/2, code_change/3]). -include("webmachine_logger.hrl"). -ifdef(TEST). -include_lib("eunit/include/eunit.hrl"). -endif. -record(state, {hourstamp, filename, handle}). -define(FILENAME, "access.log"). %% =================================================================== %% gen_event callbacks %% =================================================================== %% @private init([BaseDir]) -> webmachine_log:defer_refresh(?MODULE), FileName = filename:join(BaseDir, ?FILENAME), {Handle, DateHour} = webmachine_log:log_open(FileName), {ok, #state{filename=FileName, handle=Handle, hourstamp=DateHour}}. %% @private handle_call({_Label, MRef, get_modules}, State) -> {ok, {MRef, [?MODULE]}, State}; handle_call({refresh, Time}, State) -> {ok, ok, webmachine_log:maybe_rotate(?MODULE, Time, State)}; handle_call(_Request, State) -> {ok, ok, State}. %% @private handle_event({log_access, LogData}, State) -> NewState = webmachine_log:maybe_rotate(?MODULE, os:timestamp(), State), Msg = format_req(LogData), webmachine_log:log_write(NewState#state.handle, Msg), {ok, NewState}; handle_event(_Event, State) -> {ok, State}. %% @private handle_info(_Info, State) -> {ok, State}. %% @private terminate(_Reason, _State) -> ok. %% @private code_change(_OldVsn, State, _Extra) -> {ok, State}. %% =================================================================== %% Internal functions %% =================================================================== format_req(#wm_log_data{method=Method, headers=Headers, peer=Peer, path=Path, version=Version, response_code=ResponseCode, response_length=ResponseLength}) -> User = "-", Time = webmachine_log:fmtnow(), Status = case ResponseCode of {Code, _ReasonPhrase} when is_integer(Code) -> integer_to_list(Code); _ when is_integer(ResponseCode) -> integer_to_list(ResponseCode); _ -> ResponseCode end, Length = integer_to_list(ResponseLength), Referer = case mochiweb_headers:get_value("Referer", Headers) of undefined -> ""; R -> R end, UserAgent = case mochiweb_headers:get_value("User-Agent", Headers) of undefined -> ""; U -> U end, fmt_alog(Time, Peer, User, atom_to_list(Method), Path, Version, Status, Length, Referer, UserAgent). fmt_alog(Time, Ip, User, Method, Path, {VM,Vm}, Status, Length, Referrer, UserAgent) -> [webmachine_log:fmt_ip(Ip), " - ", User, [$\s], Time, [$\s, $"], Method, " ", Path, " HTTP/", integer_to_list(VM), ".", integer_to_list(Vm), [$",$\s], Status, [$\s], Length, [$\s,$"], Referrer, [$",$\s,$"], UserAgent, [$",$\n]]. rabbitmq-server-3.2.4/plugins-src/webmachine-wrapper/webmachine-git/src/webmachine_router.erl0000644000000000000000000002157212305126066031241 0ustar rootroot%% @author Kevin A. Smith %% @copyright 2007-2010 Basho Technologies %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. %% You may obtain a copy of the License at %% %% http://www.apache.org/licenses/LICENSE-2.0 %% %% Unless required by applicable law or agreed to in writing, software %% distributed under the License is distributed on an "AS IS" BASIS, %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %% See the License for the specific language governing permissions and %% limitations under the License. %% @doc Module to add and remove dynamic routes to webmachine's routing %% table. Dynamic routes are not persistent between executions of %% a webmachine application. They will need to be added to the %% the table each time webmachine restarts. -module(webmachine_router). -behaviour(gen_server). %% API -export([start_link/0, add_route/1, add_route/2, remove_route/1, remove_route/2, remove_resource/1, remove_resource/2, get_routes/0, get_routes/1, init_routes/1, init_routes/2 ]). %% gen_server callbacks -export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]). %% @type hostmatchterm() = {hostmatch(), [pathmatchterm()]}. % The dispatch configuration contains a list of these terms, and the % first one whose host and one pathmatchterm match is used. %% @type pathmatchterm() = {[pathterm()], matchmod(), matchopts()}. % The dispatch configuration contains a list of these terms, and the % first one whose list of pathterms matches the input path is used. %% @type pathterm() = '*' | string() | atom(). % A list of pathterms is matched against a '/'-separated input path. % The '*' pathterm matches all remaining tokens. % A string pathterm will match a token of exactly the same string. % Any atom pathterm other than '*' will match any token and will % create a binding in the result if a complete match occurs. %% @type matchmod() = atom(). % This atom, if present in a successful matchterm, will appear in % the resulting dispterm. In Webmachine this is used to name the % resource module that will handle the matching request. %% @type matchopts() = [term()]. % This term, if present in a successful matchterm, will appear in % the resulting dispterm. In Webmachine this is used to provide % arguments to the resource module handling the matching request. -define(SERVER, ?MODULE). %% @spec add_route(hostmatchterm() | pathmatchterm()) -> ok %% @doc Adds a route to webmachine's route table. The route should %% be the format documented here: %% http://bitbucket.org/justin/webmachine/wiki/DispatchConfiguration add_route(Route) -> add_route(default, Route). add_route(Name, Route) -> gen_server:call(?SERVER, {add_route, Name, Route}, infinity). %% @spec remove_route(hostmatchterm() | pathmatchterm()) -> ok %% @doc Removes a route from webamchine's route table. The route %% route must be properly formatted %% @see add_route/2 remove_route(Route) -> remove_route(default, Route). remove_route(Name, Route) -> gen_server:call(?SERVER, {remove_route, Name, Route}, infinity). %% @spec remove_resource(atom()) -> ok %% @doc Removes all routes for a specific resource module. remove_resource(Resource) when is_atom(Resource) -> remove_resource(default, Resource). remove_resource(Name, Resource) when is_atom(Resource) -> gen_server:call(?SERVER, {remove_resource, Name, Resource}, infinity). %% @spec get_routes() -> [{[], res, []}] %% @doc Retrieve a list of routes and resources set in webmachine's %% route table. get_routes() -> get_routes(default). get_routes(Name) -> get_dispatch_list(Name). %% @spec init_routes() -> ok %% @doc Set the default routes, unless the routing table isn't empty. init_routes(DefaultRoutes) -> init_routes(default, DefaultRoutes). init_routes(Name, DefaultRoutes) -> gen_server:call(?SERVER, {init_routes, Name, DefaultRoutes}, infinity). %% @spec start_link() -> {ok, pid()} | {error, any()} %% @doc Starts the webmachine_router gen_server. start_link() -> %% We expect to only be called from webmachine_sup %% %% Set up the ETS configuration table. try ets:new(?MODULE, [named_table, public, set, {keypos, 1}, {read_concurrency, true}]) of _Result -> ok catch error:badarg -> %% The table already exists, which is fine. The webmachine_router %% probably crashed and this is a restart. ok end, gen_server:start_link({local, ?SERVER}, ?MODULE, [], []). %% @private init([]) -> {ok, undefined}. %% @private handle_call({remove_resource, Name, Resource}, _From, State) -> DL = filter_by_resource(Resource, get_dispatch_list(Name)), {reply, set_dispatch_list(Name, DL), State}; handle_call({remove_route, Name, Route}, _From, State) -> DL = [D || D <- get_dispatch_list(Name), D /= Route], {reply, set_dispatch_list(Name, DL), State}; handle_call({add_route, Name, Route}, _From, State) -> DL = [Route|[D || D <- get_dispatch_list(Name), D /= Route]], {reply, set_dispatch_list(Name, DL), State}; handle_call({init_routes, Name, DefaultRoutes}, _From, State) -> %% if the table lacks a dispatch_list row, set it ets:insert_new(?MODULE, {Name, DefaultRoutes}), {reply, ok, State}; handle_call(_Request, _From, State) -> {reply, ignore, State}. %% @private handle_cast(_Msg, State) -> {noreply, State}. %% @private handle_info(_Info, State) -> {noreply, State}. %% @private terminate(_Reason, _State) -> ok. %% @private code_change(_OldVsn, State, _Extra) -> {ok, State}. %% Internal functions %% @doc Remove any dispatch rule that directs requests to `Resource' filter_by_resource(Resource, Dispatch) -> lists:foldr(filter_by_resource(Resource), [], Dispatch). filter_by_resource(Resource) -> fun({_, R, _}, Acc) when R == Resource -> % basic dispatch Acc; ({_, _, R, _}, Acc) when R == Resource -> % guarded dispatch Acc; ({Host, Disp}, Acc) -> % host-based dispatch [{Host, filter_by_resource(Resource, Disp)}|Acc]; (Other, Acc) -> % dispatch not mentioning this resource [Other|Acc] end. get_dispatch_list(Name) -> case ets:lookup(?MODULE, Name) of [{Name, Dispatch}] -> Dispatch; [] -> [] end. set_dispatch_list(Name, DispatchList) -> true = ets:insert(?MODULE, {Name, DispatchList}), ok. %% %% Tests %% -ifdef(TEST). -include_lib("eunit/include/eunit.hrl"). add_remove_route_test() -> {ok, Pid} = webmachine_router:start_link(), unlink(Pid), PathSpec = {["foo"], foo, []}, webmachine_router:add_route(PathSpec), [PathSpec] = get_routes(), webmachine_router:remove_route(PathSpec), [] = get_routes(), exit(Pid, kill). add_remove_resource_test() -> {ok, Pid} = webmachine_router:start_link(), unlink(Pid), PathSpec1 = {["foo"], foo, []}, PathSpec2 = {["bar"], foo, []}, PathSpec3 = {["baz"], bar, []}, PathSpec4 = {["foo"], fun(_) -> true end, foo, []}, PathSpec5 = {["foo"], {webmachine_router, test_guard}, foo, []}, webmachine_router:add_route(PathSpec1), webmachine_router:add_route(PathSpec2), webmachine_router:add_route(PathSpec3), webmachine_router:remove_resource(foo), [PathSpec3] = get_routes(), webmachine_router:add_route(PathSpec4), webmachine_router:remove_resource(foo), [PathSpec3] = get_routes(), webmachine_router:add_route(PathSpec5), webmachine_router:remove_resource(foo), [PathSpec3] = get_routes(), webmachine_router:remove_route(PathSpec3), [begin PathSpec = {"localhost", [HostPath]}, webmachine_router:add_route(PathSpec), webmachine_router:remove_resource(foo), [{"localhost", []}] = get_routes(), webmachine_router:remove_route({"localhost", []}) end || HostPath <- [PathSpec1, PathSpec4, PathSpec5]], exit(Pid, kill). no_dupe_path_test() -> {ok, Pid} = webmachine_router:start_link(), unlink(Pid), PathSpec = {["foo"], foo, []}, webmachine_router:add_route(PathSpec), webmachine_router:add_route(PathSpec), [PathSpec] = get_routes(), exit(Pid, kill). supervisor_restart_keeps_routes_test() -> {ok, Pid} = webmachine_router:start_link(), unlink(Pid), PathSpec = {["foo"], foo, []}, webmachine_router:add_route(PathSpec), [PathSpec] = get_routes(), OldRouter = whereis(webmachine_router), exit(whereis(webmachine_router), kill), timer:sleep(100), NewRouter = whereis(webmachine_router), ?assert(OldRouter /= NewRouter), [PathSpec] = get_routes(), exit(Pid, kill). -endif. rabbitmq-server-3.2.4/plugins-src/webmachine-wrapper/webmachine-git/src/webmachine_log.erl0000644000000000000000000001646312305126066030505 0ustar rootroot%% Copyright (c) 2011-2012 Basho Technologies, Inc. All Rights Reserved. %% %% This file is provided to you under the Apache License, %% Version 2.0 (the "License"); you may not use this file %% except in compliance with the License. You may obtain %% a copy of the License at %% %% http://www.apache.org/licenses/LICENSE-2.0 %% %% Unless required by applicable law or agreed to in writing, %% software distributed under the License is distributed on an %% "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY %% KIND, either express or implied. See the License for the %% specific language governing permissions and limitations %% under the License. %% @doc Helper functions for webmachine's default log handlers -module(webmachine_log). -include("webmachine_logger.hrl"). -export([add_handler/2, call/2, call/3, datehour/0, datehour/1, defer_refresh/1, delete_handler/1, fix_log/2, fmt_ip/1, fmtnow/0, log_access/1, log_close/3, log_open/1, log_open/2, log_write/2, maybe_rotate/3, month/1, refresh/2, suffix/1, zeropad/2, zone/0]). -record(state, {hourstamp :: non_neg_integer(), filename :: string(), handle :: file:io_device()}). %% @doc Add a handler to receive log events -type add_handler_result() :: ok | {'EXIT', term()} | term(). -spec add_handler(atom() | {atom(), term()}, term()) -> add_handler_result(). add_handler(Mod, Args) -> gen_event:add_handler(?EVENT_LOGGER, Mod, Args). %% @doc Make a synchronous call directly to a specific event handler %% module -type error() :: {error, bad_module} | {'EXIT', term()} | term(). -spec call(atom(), term()) -> term() | error(). call(Mod, Msg) -> gen_event:call(?EVENT_LOGGER, Mod, Msg). %% @doc Make a synchronous call directly to a specific event handler %% module -spec call(atom(), term(), timeout()) -> term() | error(). call(Mod, Msg, Timeout) -> gen_event:call(?EVENT_LOGGER, Mod, Msg, Timeout). %% @doc Return a four-tuple containing year, month, day, and hour %% of the current time. -type datehour() :: {calendar:year(), calendar:month(), calendar:day(), calendar:hour()}. -spec datehour() -> datehour(). datehour() -> datehour(os:timestamp()). %% @doc Return a four-tuple containing year, month, day, and hour %% of the specified time. -spec datehour(erlang:timestamp()) -> datehour(). datehour(TS) -> {{Y, M, D}, {H, _, _}} = calendar:now_to_universal_time(TS), {Y, M, D, H}. %% @doc Defer the refresh of a log file. -spec defer_refresh(atom()) -> {ok, timer:tref()} | {error, term()}. defer_refresh(Mod) -> {_, {_, M, S}} = calendar:universal_time(), Time = 1000 * (3600 - ((M * 60) + S)), timer:apply_after(Time, ?MODULE, refresh, [Mod, os:timestamp()]). %% @doc Remove a log handler -type delete_handler_result() :: term() | {error, module_not_found} | {'EXIT', term()}. -spec delete_handler(atom() | {atom(), term()}) -> delete_handler_result(). delete_handler(Mod) -> gen_event:delete_handler(?EVENT_LOGGER, Mod, []). %% Seek backwards to the last valid log entry -spec fix_log(file:io_device(), non_neg_integer()) -> ok. fix_log(_FD, 0) -> ok; fix_log(FD, 1) -> {ok, 0} = file:position(FD, 0), ok; fix_log(FD, Location) -> case file:pread(FD, Location - 1, 1) of {ok, [$\n | _]} -> ok; {ok, _} -> fix_log(FD, Location - 1) end. %% @doc Format an IP address or host name -spec fmt_ip(undefined | string() | inet:ip4_address() | inet:ip6_address()) -> string(). fmt_ip(IP) when is_tuple(IP) -> inet_parse:ntoa(IP); fmt_ip(undefined) -> "0.0.0.0"; fmt_ip(HostName) -> HostName. %% @doc Format the current time into a string -spec fmtnow() -> string(). fmtnow() -> {{Year, Month, Date}, {Hour, Min, Sec}} = calendar:local_time(), io_lib:format("[~2..0w/~s/~4..0w:~2..0w:~2..0w:~2..0w ~s]", [Date,month(Month),Year, Hour, Min, Sec, zone()]). %% @doc Notify registered log event handler of an access event. -spec log_access(wm_log_data()) -> ok. log_access(#wm_log_data{}=LogData) -> gen_event:sync_notify(?EVENT_LOGGER, {log_access, LogData}). %% @doc Close a log file. -spec log_close(atom(), string(), file:io_device()) -> ok | {error, term()}. log_close(Mod, Name, FD) -> error_logger:info_msg("~p: closing log file: ~p~n", [Mod, Name]), file:close(FD). %% @doc Open a new log file for writing -spec log_open(string()) -> {file:io_device(), non_neg_integer()}. log_open(FileName) -> DateHour = datehour(), {log_open(FileName, DateHour), DateHour}. %% @doc Open a new log file for writing -spec log_open(string(), non_neg_integer()) -> file:io_device(). log_open(FileName, DateHour) -> LogName = FileName ++ suffix(DateHour), error_logger:info_msg("opening log file: ~p~n", [LogName]), filelib:ensure_dir(LogName), {ok, FD} = file:open(LogName, [read, write, raw]), {ok, Location} = file:position(FD, eof), fix_log(FD, Location), file:truncate(FD), FD. -spec log_write(file:io_device(), iolist()) -> ok | {error, term()}. log_write(FD, IoData) -> file:write(FD, lists:flatten(IoData)). %% @doc Rotate a log file if the hour it represents %% has passed. -spec maybe_rotate(atom(), erlang:timestamp(), #state{}) -> #state{}. maybe_rotate(Mod, Time, State) -> ThisHour = datehour(Time), if ThisHour == State#state.hourstamp -> State; true -> defer_refresh(Mod), log_close(Mod, State#state.filename, State#state.handle), Handle = log_open(State#state.filename, ThisHour), State#state{hourstamp=ThisHour, handle=Handle} end. %% @doc Convert numeric month value to the abbreviation -spec month(1..12) -> string(). month(1) -> "Jan"; month(2) -> "Feb"; month(3) -> "Mar"; month(4) -> "Apr"; month(5) -> "May"; month(6) -> "Jun"; month(7) -> "Jul"; month(8) -> "Aug"; month(9) -> "Sep"; month(10) -> "Oct"; month(11) -> "Nov"; month(12) -> "Dec". %% @doc Make a synchronous call to instruct a log handler to refresh %% itself. -spec refresh(atom(), erlang:timestamp()) -> ok | {error, term()}. refresh(Mod, Time) -> call(Mod, {refresh, Time}, infinity). -spec suffix(datehour()) -> string(). suffix({Y, M, D, H}) -> YS = zeropad(Y, 4), MS = zeropad(M, 2), DS = zeropad(D, 2), HS = zeropad(H, 2), lists:flatten([$., YS, $_, MS, $_, DS, $_, HS]). -spec zeropad(integer(), integer()) -> string(). zeropad(Num, MinLength) -> NumStr = integer_to_list(Num), zeropad_str(NumStr, MinLength - length(NumStr)). -spec zeropad_str(string(), integer()) -> string(). zeropad_str(NumStr, Zeros) when Zeros > 0 -> zeropad_str([$0 | NumStr], Zeros - 1); zeropad_str(NumStr, _) -> NumStr. -spec zone() -> string(). zone() -> Time = erlang:universaltime(), LocalTime = calendar:universal_time_to_local_time(Time), DiffSecs = calendar:datetime_to_gregorian_seconds(LocalTime) - calendar:datetime_to_gregorian_seconds(Time), zone((DiffSecs/3600)*100). %% Ugly reformatting code to get times like +0000 and -1300 -spec zone(integer()) -> string(). zone(Val) when Val < 0 -> io_lib:format("-~4..0w", [trunc(abs(Val))]); zone(Val) when Val >= 0 -> io_lib:format("+~4..0w", [trunc(abs(Val))]). rabbitmq-server-3.2.4/plugins-src/webmachine-wrapper/webmachine-git/src/webmachine_request.erl0000644000000000000000000011474712305126066031420 0ustar rootroot%% @author Justin Sheehy %% @author Andy Gross %% @copyright 2007-2012 Basho Technologies %% Based on mochiweb_request.erl, which is Copyright 2007 Mochi Media, Inc. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. %% You may obtain a copy of the License at %% %% http://www.apache.org/licenses/LICENSE-2.0 %% %% Unless required by applicable law or agreed to in writing, software %% distributed under the License is distributed on an "AS IS" BASIS, %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %% See the License for the specific language governing permissions and %% limitations under the License. %% @doc Webmachine HTTP Request Abstraction. The functions in this module %% can be invoked using either parameterized module syntax or regular %% invocation syntax. Since the Ericsson OTP team is removing the %% parameterized module syntax in version R16, we encourage you to write %% your applications using regular function syntax. %% %% To use parameterized module syntax, you create an instance and then %% invoke functions on that instance, like this: %% %%
    
    %%   Req = webmachine_request:new(ReqState),
    %%   Result = Req:some_fun(Args),
    %% 
    %% %% where `ReqState' is an instance of a `#wm_reqstate' record. The runtime %% then ensures the `ReqState' variable is implicitly passed to each %% function invoked through the `Req' instance. %% %% To call functions using regular syntax, simply explicitly pass the %% `ReqState' variable yourself; note there's no need to call %% `webmachine_request:new/1' to perform regular invocations. -module(webmachine_request). -author('Justin Sheehy '). -author('Andy Gross '). -export([get_peer/1]). % used in initialization -export([call/2]). % internal switching interface, used by wrcall % actual interface for resource functions -export([ new/1, trim_state/1, get_reqdata/1, set_reqdata/2, socket/1, method/1, version/1, disp_path/1, path/1, raw_path/1, get_req_header/2, req_headers/1, req_body/2, stream_req_body/2, headers/1, resp_headers/1, out_headers/1, get_out_header/2, has_out_header/2, peer/1, get_header_value/2, add_response_header/3, add_response_headers/2, remove_response_header/2, merge_response_headers/2, append_to_response_body/2, send_response/2, response_code/1, set_response_code/2, set_resp_body/2, response_body/1, has_response_body/1, do_redirect/1, resp_redirect/1, set_metadata/3, get_metadata/2, get_path_info/1, get_path_info/2, load_dispatch_data/7, get_path_tokens/1, get_app_root/1, parse_cookie/1, get_cookie_value/2, parse_qs/1, get_qs_value/2, get_qs_value/3, range/1, log_data/1 ]). -include("webmachine_logger.hrl"). -include("wm_reqstate.hrl"). -include("wm_reqdata.hrl"). -define(WMVSN, "1.10.0"). -define(QUIP, "never breaks eye contact"). -define(IDLE_TIMEOUT, infinity). new(#wm_reqstate{}=ReqState) -> {?MODULE, ReqState}. trim_state({?MODULE, ReqState}) -> TrimData = (ReqState#wm_reqstate.reqdata)#wm_reqdata{wm_state='WMSTATE'}, webmachine_request:new(ReqState#wm_reqstate{reqdata=TrimData}); trim_state(ReqState) -> trim_state({?MODULE, ReqState}). get_peer({?MODULE, ReqState}=Req) -> case ReqState#wm_reqstate.peer of undefined -> PeerName = case ReqState#wm_reqstate.socket of testing -> {ok, {{127,0,0,1}, 80}}; {ssl,SslSocket} -> ssl:peername(SslSocket); _ -> inet:peername(ReqState#wm_reqstate.socket) end, Peer = peer_from_peername(PeerName, Req), NewReqState = ReqState#wm_reqstate{peer=Peer}, {Peer, NewReqState}; _ -> {ReqState#wm_reqstate.peer, ReqState} end; get_peer(ReqState) -> get_peer({?MODULE, ReqState}). peer_from_peername({ok, {Addr={10, _, _, _}, _Port}}, Req) -> x_peername(inet_parse:ntoa(Addr), Req); peer_from_peername({ok, {Addr={172, Second, _, _}, _Port}}, Req) when (Second > 15) andalso (Second < 32) -> x_peername(inet_parse:ntoa(Addr), Req); peer_from_peername({ok, {Addr={192, 168, _, _}, _Port}}, Req) -> x_peername(inet_parse:ntoa(Addr), Req); peer_from_peername({ok, {{127, 0, 0, 1}, _Port}}, Req) -> x_peername("127.0.0.1", Req); peer_from_peername({ok, {Addr, _Port}}, _Req) -> inet_parse:ntoa(Addr). x_peername(Default, Req) -> case get_header_value("x-forwarded-for", Req) of {undefined, _} -> Default; {Hosts, _} -> string:strip(lists:last(string:tokens(Hosts, ","))) end. call(base_uri, {?MODULE, ReqState}) -> {wrq:base_uri(ReqState#wm_reqstate.reqdata), ReqState}; call(socket, {?MODULE, ReqState}) -> {ReqState#wm_reqstate.socket,ReqState}; call(get_reqdata, {?MODULE, ReqState}) -> {ReqState#wm_reqstate.reqdata, ReqState}; call({set_reqdata, RD}, {?MODULE, ReqState}) -> {ok, ReqState#wm_reqstate{reqdata=RD}}; call(method, {?MODULE, ReqState}) -> {wrq:method(ReqState#wm_reqstate.reqdata), ReqState}; call(version, {?MODULE, ReqState}) -> {wrq:version(ReqState#wm_reqstate.reqdata), ReqState}; call(raw_path, {?MODULE, ReqState}) -> {wrq:raw_path(ReqState#wm_reqstate.reqdata), ReqState}; call(req_headers, {?MODULE, ReqState}) -> {wrq:req_headers(ReqState#wm_reqstate.reqdata), ReqState}; call({req_body, MaxRecvBody}, {?MODULE, ReqState}) -> case ReqState#wm_reqstate.bodyfetch of stream -> {stream_conflict, ReqState}; standard -> {ReqState#wm_reqstate.reqbody, ReqState}; undefined -> RD=(ReqState#wm_reqstate.reqdata)#wm_reqdata{ max_recv_body=MaxRecvBody}, NewReqState=ReqState#wm_reqstate{reqdata=RD}, NewBody = case get(req_body) of undefined -> NewB = do_recv_body(NewReqState), put(req_body, NewB), NewB; B -> B end, NewRD = RD#wm_reqdata{req_body=NewBody}, {NewBody, NewReqState#wm_reqstate{ bodyfetch=standard,reqdata=NewRD,reqbody=NewBody}} end; call({stream_req_body, MaxHunk}, {?MODULE, ReqState}) -> case ReqState#wm_reqstate.bodyfetch of standard -> {stream_conflict, ReqState}; _ -> {recv_stream_body(ReqState, MaxHunk), ReqState#wm_reqstate{bodyfetch=stream}} end; call(resp_headers, {?MODULE, ReqState}) -> {wrq:resp_headers(ReqState#wm_reqstate.reqdata), ReqState}; call(resp_redirect, {?MODULE, ReqState}) -> {wrq:resp_redirect(ReqState#wm_reqstate.reqdata), ReqState}; call({get_resp_header, HdrName}, {?MODULE, ReqState}) -> Reply = mochiweb_headers:get_value(HdrName, wrq:resp_headers(ReqState#wm_reqstate.reqdata)), {Reply, ReqState}; call(get_path_info, {?MODULE, ReqState}) -> PropList = orddict:to_list(wrq:path_info(ReqState#wm_reqstate.reqdata)), {PropList, ReqState}; call({get_path_info, Key}, {?MODULE, ReqState}) -> {wrq:path_info(Key, ReqState#wm_reqstate.reqdata), ReqState}; call(peer, Req) -> get_peer(Req); call(range, Req) -> get_range(Req); call(response_code, {?MODULE, ReqState}) -> {wrq:response_code(ReqState#wm_reqstate.reqdata), ReqState}; call(app_root, {?MODULE, ReqState}) -> {wrq:app_root(ReqState#wm_reqstate.reqdata), ReqState}; call(disp_path, {?MODULE, ReqState}) -> {wrq:disp_path(ReqState#wm_reqstate.reqdata), ReqState}; call(path, {?MODULE, ReqState}) -> {wrq:path(ReqState#wm_reqstate.reqdata), ReqState}; call({get_req_header, K}, {?MODULE, ReqState}) -> {wrq:get_req_header(K, ReqState#wm_reqstate.reqdata), ReqState}; call({set_response_code, Code}, {?MODULE, ReqState}) -> {ok, ReqState#wm_reqstate{reqdata=wrq:set_response_code( Code, ReqState#wm_reqstate.reqdata)}}; call({set_resp_header, K, V}, {?MODULE, ReqState}) -> {ok, ReqState#wm_reqstate{reqdata=wrq:set_resp_header( K, V, ReqState#wm_reqstate.reqdata)}}; call({set_resp_headers, Hdrs}, {?MODULE, ReqState}) -> {ok, ReqState#wm_reqstate{reqdata=wrq:set_resp_headers( Hdrs, ReqState#wm_reqstate.reqdata)}}; call({remove_resp_header, K}, {?MODULE, ReqState}) -> {ok, ReqState#wm_reqstate{reqdata=wrq:remove_resp_header( K, ReqState#wm_reqstate.reqdata)}}; call({merge_resp_headers, Hdrs}, {?MODULE, ReqState}) -> {ok, ReqState#wm_reqstate{reqdata=wrq:merge_resp_headers( Hdrs, ReqState#wm_reqstate.reqdata)}}; call({append_to_response_body, Data}, {?MODULE, ReqState}) -> {ok, ReqState#wm_reqstate{reqdata=wrq:append_to_response_body( Data, ReqState#wm_reqstate.reqdata)}}; call({set_disp_path, P}, {?MODULE, ReqState}) -> {ok, ReqState#wm_reqstate{reqdata=wrq:set_disp_path( P, ReqState#wm_reqstate.reqdata)}}; call(do_redirect, {?MODULE, ReqState}) -> {ok, ReqState#wm_reqstate{ reqdata=wrq:do_redirect(true, ReqState#wm_reqstate.reqdata)}}; call({send_response, Code}, Req) when is_integer(Code) -> call({send_response, {Code, undefined}}, Req); call({send_response, {Code, ReasonPhrase}=CodeAndReason}, Req) when is_integer(Code) -> {Reply, NewState} = case Code of 200 -> send_ok_response(ReasonPhrase, Req); _ -> send_response(CodeAndReason, Req) end, LogData = NewState#wm_reqstate.log_data, NewLogData = LogData#wm_log_data{finish_time=now()}, {Reply, NewState#wm_reqstate{log_data=NewLogData}}; call(resp_body, {?MODULE, ReqState}) -> {wrq:resp_body(ReqState#wm_reqstate.reqdata), ReqState}; call({set_resp_body, Body}, {?MODULE, ReqState}) -> {ok, ReqState#wm_reqstate{reqdata=wrq:set_resp_body(Body, ReqState#wm_reqstate.reqdata)}}; call(has_resp_body, {?MODULE, ReqState}) -> Reply = case wrq:resp_body(ReqState#wm_reqstate.reqdata) of undefined -> false; <<>> -> false; _ -> true end, {Reply, ReqState}; call({get_metadata, Key}, {?MODULE, ReqState}) -> Reply = case orddict:find(Key, ReqState#wm_reqstate.metadata) of {ok, Value} -> Value; error -> undefined end, {Reply, ReqState}; call({set_metadata, Key, Value}, {?MODULE, ReqState}) -> NewDict = orddict:store(Key, Value, ReqState#wm_reqstate.metadata), {ok, ReqState#wm_reqstate{metadata=NewDict}}; call(path_tokens, {?MODULE, ReqState}) -> {wrq:path_tokens(ReqState#wm_reqstate.reqdata), ReqState}; call(req_cookie, {?MODULE, ReqState}) -> {wrq:req_cookie(ReqState#wm_reqstate.reqdata), ReqState}; call(req_qs, {?MODULE, ReqState}) -> {wrq:req_qs(ReqState#wm_reqstate.reqdata), ReqState}; call({load_dispatch_data, PathProps, HostTokens, Port, PathTokens, AppRoot, DispPath}, {?MODULE, ReqState}) -> PathInfo = orddict:from_list(PathProps), NewState = ReqState#wm_reqstate{reqdata=wrq:load_dispatch_data( PathInfo,HostTokens,Port,PathTokens,AppRoot, DispPath,ReqState#wm_reqstate.reqdata)}, {ok, NewState}; call(log_data, {?MODULE, ReqState}) -> {ReqState#wm_reqstate.log_data, ReqState}; call(notes, {?MODULE, ReqState}) -> {wrq:get_notes(ReqState#wm_reqstate.reqdata), ReqState}; call(Arg, #wm_reqstate{}=ReqState) -> call(Arg, {?MODULE, ReqState}). get_header_value(K, {?MODULE, ReqState}) -> {wrq:get_req_header(K, ReqState#wm_reqstate.reqdata), ReqState}; get_header_value(K, ReqState) -> get_header_value(K, {?MODULE, ReqState}). get_outheader_value(K, {?MODULE, ReqState}) -> {mochiweb_headers:get_value(K, wrq:resp_headers(ReqState#wm_reqstate.reqdata)), ReqState}; get_outheader_value(K, ReqState) -> get_outheader_value(K, {?MODULE, ReqState}). send(Socket, Data) -> case mochiweb_socket:send(Socket, iolist_to_binary(Data)) of ok -> ok; {error,closed} -> ok; _ -> exit(normal) end. send_stream_body(Socket, X) -> send_stream_body(Socket, X, 0). send_stream_body(Socket, {<<>>, done}, SoFar) -> send_chunk(Socket, <<>>), SoFar; send_stream_body(Socket, {Data, done}, SoFar) -> Size = send_chunk(Socket, Data), send_chunk(Socket, <<>>), Size + SoFar; send_stream_body(Socket, {<<>>, Next}, SoFar) -> send_stream_body(Socket, Next(), SoFar); send_stream_body(Socket, {[], Next}, SoFar) -> send_stream_body(Socket, Next(), SoFar); send_stream_body(Socket, {Data, Next}, SoFar) -> Size = send_chunk(Socket, Data), send_stream_body(Socket, Next(), Size + SoFar). send_stream_body_no_chunk(Socket, {Data, done}) -> send(Socket, Data); send_stream_body_no_chunk(Socket, {Data, Next}) -> send(Socket, Data), send_stream_body_no_chunk(Socket, Next()). send_writer_body(Socket, {Encoder, Charsetter, BodyFun}) -> put(bytes_written, 0), Writer = fun(Data) -> Size = send_chunk(Socket, Encoder(Charsetter(Data))), put(bytes_written, get(bytes_written) + Size), Size end, BodyFun(Writer), send_chunk(Socket, <<>>), get(bytes_written). send_chunk(Socket, Data) -> Size = iolist_size(Data), send(Socket, [mochihex:to_hex(Size), <<"\r\n">>, Data, <<"\r\n">>]), Size. send_ok_response(ReasonPhrase, {?MODULE, ReqState}=Req) -> RD0 = ReqState#wm_reqstate.reqdata, {Range, State} = get_range(Req), case Range of X when X =:= undefined; X =:= fail; X =:= ignore -> send_response({200, ReasonPhrase}, Req); Ranges -> {PartList, Size} = range_parts(RD0, Ranges), case PartList of [] -> %% no valid ranges %% could be 416, for now we'll just return 200 send_response({200, ReasonPhrase}, Req); PartList -> {RangeHeaders, RangeBody} = parts_to_body(PartList, Size, Req), RespHdrsRD = wrq:set_resp_headers( [{"Accept-Ranges", "bytes"} | RangeHeaders], RD0), RespBodyRD = wrq:set_resp_body( RangeBody, RespHdrsRD), NewState = State#wm_reqstate{reqdata=RespBodyRD}, send_response({206, ReasonPhrase}, NewState, Req) end end. send_response(Code, #wm_reqstate{}=ReqState) -> send_response(Code,ReqState,{?MODULE,ReqState}); send_response(Code, {?MODULE, ReqState}=Req) -> send_response(Code,ReqState,Req). send_response(Code, PassedState=#wm_reqstate{reqdata=RD}, _Req) -> Body0 = wrq:resp_body(RD), {Body,Length} = case Body0 of {stream, StreamBody} -> {{stream, StreamBody}, chunked}; {known_length_stream, Size, StreamBody} -> {{known_length_stream, StreamBody}, Size}; {stream, Size, Fun} -> {{stream, Fun(0, Size-1)}, chunked}; {writer, WriteBody} -> {{writer, WriteBody}, chunked}; _ -> {Body0, iolist_size([Body0])} end, send(PassedState#wm_reqstate.socket, [make_version(wrq:version(RD)), make_code(Code), <<"\r\n">> | make_headers(Code, Length, RD)]), FinalLength = case wrq:method(RD) of 'HEAD' -> Length; _ -> case Body of {stream, Body2} -> send_stream_body(PassedState#wm_reqstate.socket, Body2); {known_length_stream, Body2} -> send_stream_body_no_chunk(PassedState#wm_reqstate.socket, Body2), Length; {writer, Body2} -> send_writer_body(PassedState#wm_reqstate.socket, Body2); _ -> send(PassedState#wm_reqstate.socket, Body), Length end end, InitLogData = PassedState#wm_reqstate.log_data, FinalLogData = InitLogData#wm_log_data{response_code=Code, response_length=FinalLength}, {ok, PassedState#wm_reqstate{reqdata=wrq:set_response_code(Code, RD), log_data=FinalLogData}}. %% @doc Infer body length from transfer-encoding and content-length headers. body_length(Req) -> case get_header_value("transfer-encoding", Req) of {undefined, _} -> case get_header_value("content-length", Req) of {undefined, _} -> undefined; {Length, _} -> list_to_integer(Length) end; {"chunked", _} -> chunked; Unknown -> {unknown_transfer_encoding, Unknown} end. %% @doc Receive the body of the HTTP request (defined by Content-Length). %% Will only receive up to the default max-body length do_recv_body(PassedState=#wm_reqstate{reqdata=RD}) -> MRH = RD#wm_reqdata.max_recv_hunk, MRB = RD#wm_reqdata.max_recv_body, read_whole_stream(recv_stream_body(PassedState, MRH), [], MRB, 0). read_whole_stream({Hunk,_}, _, MaxRecvBody, SizeAcc) when SizeAcc + byte_size(Hunk) > MaxRecvBody -> {error, req_body_too_large}; read_whole_stream({Hunk,Next}, Acc0, MaxRecvBody, SizeAcc) -> HunkSize = byte_size(Hunk), if SizeAcc + HunkSize > MaxRecvBody -> {error, req_body_too_large}; true -> Acc = [Hunk|Acc0], case Next of done -> iolist_to_binary(lists:reverse(Acc)); _ -> read_whole_stream(Next(), Acc, MaxRecvBody, SizeAcc + HunkSize) end end. recv_stream_body(PassedState=#wm_reqstate{reqdata=RD}, MaxHunkSize) -> put(mochiweb_request_recv, true), case get_header_value("expect", PassedState) of {"100-continue", _} -> send(PassedState#wm_reqstate.socket, [make_version(wrq:version(RD)), make_code(100), <<"\r\n\r\n">>]); _Else -> ok end, case body_length(PassedState) of {unknown_transfer_encoding, X} -> exit({unknown_transfer_encoding, X}); undefined -> {<<>>, done}; 0 -> {<<>>, done}; chunked -> recv_chunked_body(PassedState#wm_reqstate.socket, MaxHunkSize); Length -> recv_unchunked_body(PassedState#wm_reqstate.socket, MaxHunkSize, Length) end. recv_unchunked_body(Socket, MaxHunk, DataLeft) -> case MaxHunk >= DataLeft of true -> {ok,Data1} = mochiweb_socket:recv(Socket,DataLeft,?IDLE_TIMEOUT), {Data1, done}; false -> {ok,Data2} = mochiweb_socket:recv(Socket,MaxHunk,?IDLE_TIMEOUT), {Data2, fun() -> recv_unchunked_body(Socket, MaxHunk, DataLeft-MaxHunk) end} end. recv_chunked_body(Socket, MaxHunk) -> case read_chunk_length(Socket, false) of 0 -> {<<>>, done}; ChunkLength -> recv_chunked_body(Socket,MaxHunk,ChunkLength) end. recv_chunked_body(Socket, MaxHunk, LeftInChunk) -> case MaxHunk >= LeftInChunk of true -> {ok,Data1} = mochiweb_socket:recv(Socket,LeftInChunk,?IDLE_TIMEOUT), {Data1, fun() -> recv_chunked_body(Socket, MaxHunk) end}; false -> {ok,Data2} = mochiweb_socket:recv(Socket,MaxHunk,?IDLE_TIMEOUT), {Data2, fun() -> recv_chunked_body(Socket, MaxHunk, LeftInChunk-MaxHunk) end} end. read_chunk_length(Socket, MaybeLastChunk) -> mochiweb_socket:setopts(Socket, [{packet, line}]), case mochiweb_socket:recv(Socket, 0, ?IDLE_TIMEOUT) of {ok, Header} -> mochiweb_socket:setopts(Socket, [{packet, raw}]), Splitter = fun (C) -> C =/= $\r andalso C =/= $\n andalso C =/= $ andalso C =/= 59 % semicolon end, {Hex, _Rest} = lists:splitwith(Splitter, binary_to_list(Header)), case Hex of [] -> %% skip the \r\n at the end of a chunk, or %% allow [badly formed] last chunk header to be %% empty instead of '0' explicitly if MaybeLastChunk -> 0; true -> read_chunk_length(Socket, true) end; _ -> erlang:list_to_integer(Hex, 16) end; _ -> exit(normal) end. get_range({?MODULE, #wm_reqstate{reqdata = RD}=ReqState}=Req) -> case RD#wm_reqdata.resp_range of ignore_request -> {ignore, ReqState#wm_reqstate{range=undefined}}; follow_request -> case get_header_value("range", Req) of {undefined, _} -> {undefined, ReqState#wm_reqstate{range=undefined}}; {RawRange, _} -> Range = mochiweb_http:parse_range_request(RawRange), {Range, ReqState#wm_reqstate{range=Range}} end end. range_parts(_RD=#wm_reqdata{resp_body={file, IoDevice}}, Ranges) -> Size = mochiweb_io:iodevice_size(IoDevice), F = fun (Spec, Acc) -> case mochiweb_http:range_skip_length(Spec, Size) of invalid_range -> Acc; V -> [V | Acc] end end, LocNums = lists:foldr(F, [], Ranges), {ok, Data} = file:pread(IoDevice, LocNums), Bodies = lists:zipwith(fun ({Skip, Length}, PartialBody) -> {Skip, Skip + Length - 1, PartialBody} end, LocNums, Data), {Bodies, Size}; range_parts(RD=#wm_reqdata{resp_body={stream, {Hunk,Next}}}, Ranges) -> % for now, streamed bodies are read in full for range requests MRB = RD#wm_reqdata.max_recv_body, range_parts(read_whole_stream({Hunk,Next}, [], MRB, 0), Ranges); range_parts(_RD=#wm_reqdata{resp_body={known_length_stream, Size, StreamBody}}, Ranges) -> SkipLengths = [ mochiweb_http:range_skip_length(R, Size) || R <- Ranges], {[ {Skip, Skip+Length-1, {known_length_stream, Length, StreamBody}} || {Skip, Length} <- SkipLengths ], Size}; range_parts(_RD=#wm_reqdata{resp_body={stream, Size, StreamFun}}, Ranges) -> SkipLengths = [ mochiweb_http:range_skip_length(R, Size) || R <- Ranges], {[ {Skip, Skip+Length-1, StreamFun} || {Skip, Length} <- SkipLengths ], Size}; range_parts(#wm_reqdata{resp_body=Body}, Ranges) when is_binary(Body); is_list(Body) -> range_parts(Body, Ranges); range_parts(Body0, Ranges) when is_binary(Body0); is_list(Body0) -> Body = iolist_to_binary(Body0), Size = size(Body), F = fun(Spec, Acc) -> case mochiweb_http:range_skip_length(Spec, Size) of invalid_range -> Acc; {Skip, Length} -> <<_:Skip/binary, PartialBody:Length/binary, _/binary>> = Body, [{Skip, Skip + Length - 1, PartialBody} | Acc] end end, {lists:foldr(F, [], Ranges), Size}. parts_to_body([{Start, End, Body0}], Size, Req) -> %% return body for a range reponse with a single body ContentType = case get_outheader_value("content-type", Req) of {undefined, _} -> "text/html"; {CT, _} -> CT end, HeaderList = [{"Content-Type", ContentType}, {"Content-Range", ["bytes ", mochiweb_util:make_io(Start), "-", mochiweb_util:make_io(End), "/", mochiweb_util:make_io(Size)]}], Body = case Body0 of _ when is_function(Body0) -> {known_length_stream, End - Start + 1, Body0(Start, End)}; {known_length_stream, ContentSize, StreamBody} -> {known_length_stream, ContentSize, StreamBody}; _ -> Body0 end, {HeaderList, Body}; parts_to_body(BodyList, Size, Req) when is_list(BodyList) -> %% return %% header Content-Type: multipart/byteranges; boundary=441934886133bdee4 %% and multipart body ContentType = case get_outheader_value("content-type", Req) of {undefined, _} -> "text/html"; {CT, _} -> CT end, Boundary = mochihex:to_hex(mochiweb_util:rand_bytes(8)), HeaderList = [{"Content-Type", ["multipart/byteranges; ", "boundary=", Boundary]}], MultiPartBody = case hd(BodyList) of {_, _, Fun} when is_function(Fun) -> stream_multipart_body(BodyList, ContentType, Boundary, Size); _ -> multipart_body(BodyList, ContentType, Boundary, Size) end, {HeaderList, MultiPartBody}. multipart_body([], _ContentType, Boundary, _Size) -> end_boundary(Boundary); multipart_body([{Start, End, Body} | BodyList], ContentType, Boundary, Size) -> [part_preamble(Boundary, ContentType, Start, End, Size), Body, <<"\r\n">> | multipart_body(BodyList, ContentType, Boundary, Size)]. boundary(B) -> [<<"--">>, B, <<"\r\n">>]. end_boundary(B) -> [<<"--">>, B, <<"--\r\n">>]. part_preamble(Boundary, CType, Start, End, Size) -> [boundary(Boundary), <<"Content-Type: ">>, CType, <<"\r\n">>, <<"Content-Range: bytes ">>, mochiweb_util:make_io(Start), <<"-">>, mochiweb_util:make_io(End), <<"/">>, mochiweb_util:make_io(Size), <<"\r\n\r\n">>]. stream_multipart_body(BodyList, ContentType, Boundary, Size) -> Helper = stream_multipart_body_helper( BodyList, ContentType, Boundary, Size), %% executing Helper() here is an optimization; %% it's just as valid to say {<<>>, Helper} {stream, Helper()}. stream_multipart_body_helper([], _CType, Boundary, _Size) -> fun() -> {end_boundary(Boundary), done} end; stream_multipart_body_helper([{Start, End, Fun}|Rest], CType, Boundary, Size) -> fun() -> {part_preamble(Boundary, CType, Start, End, Size), stream_multipart_part_helper( fun() -> Fun(Start, End) end, Rest, CType, Boundary, Size)} end. stream_multipart_part_helper(Fun, Rest, CType, Boundary, Size) -> fun() -> case Fun() of {Data, done} -> %% when this part is done, start the next part {[Data, <<"\r\n">>], stream_multipart_body_helper( Rest, CType, Boundary, Size)}; {Data, Next} -> %% this subpart has more data coming {Data, stream_multipart_part_helper( Next, Rest, CType, Boundary, Size)} end end. make_code({Code, undefined}) when is_integer(Code) -> make_code({Code, httpd_util:reason_phrase(Code)}); make_code({Code, ReasonPhrase}) when is_integer(Code) -> [integer_to_list(Code), [" ", ReasonPhrase]]; make_code(Code) when is_integer(Code) -> make_code({Code, httpd_util:reason_phrase(Code)}); make_code(Io) when is_list(Io); is_binary(Io) -> Io. make_version({1, 0}) -> <<"HTTP/1.0 ">>; make_version(_) -> <<"HTTP/1.1 ">>. make_headers({Code, _ReasonPhrase}, Length, RD) -> make_headers(Code, Length, RD); make_headers(Code, Length, RD) when is_integer(Code) -> Hdrs0 = case Code of 304 -> mochiweb_headers:make(wrq:resp_headers(RD)); _ -> case Length of chunked -> mochiweb_headers:enter( "Transfer-Encoding","chunked", mochiweb_headers:make(wrq:resp_headers(RD))); _ -> mochiweb_headers:enter( "Content-Length",integer_to_list(Length), mochiweb_headers:make(wrq:resp_headers(RD))) end end, case application:get_env(webmachine, server_name) of undefined -> ServerHeader = "MochiWeb/1.1 WebMachine/" ++ ?WMVSN ++ " (" ++ ?QUIP ++ ")"; {ok, ServerHeader} when is_list(ServerHeader) -> ok end, WithSrv = mochiweb_headers:enter("Server", ServerHeader, Hdrs0), Hdrs = case mochiweb_headers:get_value("date", WithSrv) of undefined -> mochiweb_headers:enter("Date", httpd_util:rfc1123_date(), WithSrv); _ -> WithSrv end, F = fun({K, V}, Acc) -> [mochiweb_util:make_io(K), <<": ">>, V, <<"\r\n">> | Acc] end, lists:foldl(F, [<<"\r\n">>], mochiweb_headers:to_list(Hdrs)). get_reqdata(#wm_reqstate{}=ReqState) -> call(get_reqdata, {?MODULE, ReqState}); get_reqdata(Req) -> call(get_reqdata, Req). set_reqdata(RD, #wm_reqstate{}=ReqState) -> call({set_reqdata, RD}, {?MODULE, ReqState}); set_reqdata(RD, Req) -> call({set_reqdata, RD}, Req). socket(#wm_reqstate{}=ReqState) -> call(socket, {?MODULE, ReqState}); socket(Req) -> call(socket, Req). method(#wm_reqstate{}=ReqState) -> call(method, {?MODULE, ReqState}); method(Req) -> call(method, Req). version(#wm_reqstate{}=ReqState) -> call(version, {?MODULE, ReqState}); version(Req) -> call(version, Req). disp_path(#wm_reqstate{}=ReqState) -> call(disp_path, {?MODULE, ReqState}); disp_path(Req) -> call(disp_path, Req). path(#wm_reqstate{}=ReqState) -> call(path, {?MODULE, ReqState}); path(Req) -> call(path, Req). raw_path(#wm_reqstate{}=ReqState) -> call(raw_path, {?MODULE, ReqState}); raw_path(Req) -> call(raw_path, Req). req_headers(#wm_reqstate{}=ReqState) -> call(req_headers, {?MODULE, ReqState}); req_headers(Req) -> call(req_headers, Req). headers(Req) -> req_headers(Req). req_body(MaxRevBody, #wm_reqstate{}=ReqState) -> call({req_body,MaxRevBody}, {?MODULE, ReqState}); req_body(MaxRevBody, Req) -> call({req_body,MaxRevBody}, Req). stream_req_body(MaxHunk, #wm_reqstate{}=ReqState) -> call({stream_req_body, MaxHunk}, {?MODULE, ReqState}); stream_req_body(MaxHunk, Req) -> call({stream_req_body, MaxHunk}, Req). resp_headers(#wm_reqstate{}=ReqState) -> call(resp_headers, {?MODULE, ReqState}); resp_headers(Req) -> call(resp_headers, Req). out_headers(Req) -> resp_headers(Req). get_resp_header(HeaderName, Req) -> call({get_resp_header, HeaderName}, Req). get_out_header(HeaderName, #wm_reqstate{}=ReqState) -> get_resp_header(HeaderName, {?MODULE, ReqState}); get_out_header(HeaderName, Req) -> get_resp_header(HeaderName, Req). has_resp_header(HeaderName, Req) -> case get_out_header(HeaderName, Req) of {undefined, _} -> false; {_, _} -> true end. has_out_header(HeaderName, #wm_reqstate{}=ReqState) -> has_resp_header(HeaderName, {?MODULE, ReqState}); has_out_header(HeaderName, Req) -> has_resp_header(HeaderName, Req). has_resp_body(#wm_reqstate{}=ReqState) -> call(has_resp_body, {?MODULE, ReqState}); has_resp_body(Req) -> call(has_resp_body, Req). has_response_body(Req) -> has_resp_body(Req). response_code(#wm_reqstate{}=ReqState) -> call(response_code, {?MODULE, ReqState}); response_code(Req) -> call(response_code, Req). set_response_code(Code, {?MODULE, ReqState}=Req) -> call({ReqState, set_response_code, Code}, Req); set_response_code(Code, ReqState) -> set_response_code(Code, {?MODULE, ReqState}). peer(#wm_reqstate{}=ReqState) -> call(peer, {?MODULE, ReqState}); peer(Req) -> call(peer, Req). range(#wm_reqstate{}=ReqState) -> call(range, {?MODULE, ReqState}); range(Req) -> call(range, Req). req_cookie(#wm_reqstate{}=ReqState) -> call(req_cookie, {?MODULE, ReqState}); req_cookie(Req) -> call(req_cookie, Req). parse_cookie(Req) -> req_cookie(Req). get_cookie_value(Key, #wm_reqstate{}=ReqState) -> get_cookie_value(Key, {?MODULE, ReqState}); get_cookie_value(Key, Req) -> {ReqCookie, NewReqState} = req_cookie(Req), case lists:keyfind(Key, 1, ReqCookie) of false -> {undefined, NewReqState}; {Key, Value} -> {Value, NewReqState} end. req_qs(#wm_reqstate{}=ReqState) -> call(req_qs, {?MODULE, ReqState}); req_qs(Req) -> call(req_qs, Req). parse_qs(Req) -> req_qs(Req). get_qs_value(Key, #wm_reqstate{}=ReqState) -> get_qs_value(Key, {?MODULE, ReqState}); get_qs_value(Key, Req) -> {ReqQS, NewReqState} = req_qs(Req), case lists:keyfind(Key, 1, ReqQS) of false -> {undefined, NewReqState}; {Key, Value} -> {Value, NewReqState} end. get_qs_value(Key, Default, #wm_reqstate{}=ReqState) -> get_qs_value(Key, Default, {?MODULE, ReqState}); get_qs_value(Key, Default, Req) -> {ReqQS, NewReqState} = req_qs(Req), case lists:keyfind(Key, 1, ReqQS) of false -> {Default, NewReqState}; {Key, Value} -> {Value, NewReqState} end. set_resp_body(Body, #wm_reqstate{}=ReqState) -> call({set_resp_body, Body}, {?MODULE, ReqState}); set_resp_body(Body, Req) -> call({set_resp_body, Body}, Req). resp_body(#wm_reqstate{}=ReqState) -> call(resp_body, {?MODULE, ReqState}); resp_body(Req) -> call(resp_body, Req). response_body(Req) -> resp_body(Req). get_req_header(K, #wm_reqstate{}=ReqState) -> call({get_req_header, K}, {?MODULE, ReqState}); get_req_header(K, Req) -> call({get_req_header, K}, Req). set_resp_header(K, V, Req) -> call({set_resp_header, K, V}, Req). add_response_header(K, V, #wm_reqstate{}=ReqState) -> set_resp_header(K, V, {?MODULE, ReqState}); add_response_header(K, V, Req) -> set_resp_header(K, V, Req). set_resp_headers(Hdrs, Req) -> call({set_resp_headers, Hdrs}, Req). add_response_headers(Hdrs, #wm_reqstate{}=ReqState) -> set_resp_headers(Hdrs, {?MODULE, ReqState}); add_response_headers(Hdrs, Req) -> set_resp_headers(Hdrs, Req). remove_resp_header(K, Req) -> call({remove_resp_header, K}, Req). remove_response_header(K, #wm_reqstate{}=ReqState) -> remove_resp_header(K, {?MODULE, ReqState}); remove_response_header(K, Req) -> remove_resp_header(K, Req). merge_resp_headers(Hdrs, Req) -> call({merge_resp_headers, Hdrs}, Req). merge_response_headers(Hdrs, #wm_reqstate{}=ReqState) -> merge_resp_headers(Hdrs, {?MODULE, ReqState}); merge_response_headers(Hdrs, Req) -> merge_resp_headers(Hdrs, Req). append_to_response_body(Data, #wm_reqstate{}=ReqState) -> call({append_to_response_body, Data}, {?MODULE, ReqState}); append_to_response_body(Data, Req) -> call({append_to_response_body, Data}, Req). do_redirect(#wm_reqstate{}=ReqState) -> call(do_redirect, {?MODULE, ReqState}); do_redirect(Req) -> call(do_redirect, Req). resp_redirect(#wm_reqstate{}=ReqState) -> call(resp_redirect, {?MODULE, ReqState}); resp_redirect(Req) -> call(resp_redirect, Req). get_metadata(Key, #wm_reqstate{}=ReqState) -> call({get_metadata, Key}, {?MODULE, ReqState}); get_metadata(Key, Req) -> call({get_metadata, Key}, Req). set_metadata(Key, Value, #wm_reqstate{}=ReqState) -> call({set_metadata, Key, Value}, {?MODULE, ReqState}); set_metadata(Key, Value, Req) -> call({set_metadata, Key, Value}, Req). get_path_info(#wm_reqstate{}=ReqState) -> call(get_path_info, {?MODULE, ReqState}); get_path_info(Req) -> call(get_path_info, Req). get_path_info(Key, #wm_reqstate{}=ReqState) -> call({get_path_info, Key}, {?MODULE, ReqState}); get_path_info(Key, Req) -> call({get_path_info, Key}, Req). path_tokens(#wm_reqstate{}=ReqState) -> call(path_tokens, {?MODULE, ReqState}); path_tokens(Req) -> call(path_tokens, Req). get_path_tokens(Req) -> path_tokens(Req). app_root(#wm_reqstate{}=ReqState) -> call(app_root, {?MODULE, ReqState}); app_root(Req) -> call(app_root, Req). get_app_root(Req) -> app_root(Req). load_dispatch_data(Bindings, HostTokens, Port, PathTokens, AppRoot, DispPath, #wm_reqstate{}=ReqState) -> call({load_dispatch_data, Bindings, HostTokens, Port, PathTokens, AppRoot, DispPath}, {?MODULE, ReqState}); load_dispatch_data(Bindings, HostTokens, Port, PathTokens, AppRoot, DispPath, Req) -> call({load_dispatch_data, Bindings, HostTokens, Port, PathTokens, AppRoot, DispPath}, Req). log_data(#wm_reqstate{}=ReqState) -> call(log_data, {?MODULE, ReqState}); log_data(Req) -> call(log_data, Req). -ifdef(TEST). -include_lib("eunit/include/eunit.hrl"). reqdata_test() -> ReqData = #wm_reqdata{req_headers = mochiweb_headers:make([])}, {ok, ReqState} = set_reqdata(ReqData, #wm_reqstate{}), ?assertEqual(ReqData, element(1, get_reqdata(ReqState))). header_test() -> HdrName = "Accept", HdrValue = "application/json", ReqData = #wm_reqdata{req_headers = mochiweb_headers:make([{HdrName, HdrValue}])}, {ok, ReqState} = set_reqdata(ReqData, #wm_reqstate{}), ?assertEqual({HdrValue, ReqState}, get_header_value(HdrName, ReqState)), ?assertEqual({HdrValue, ReqState}, get_req_header(HdrName, ReqState)). metadata_test() -> Key = "webmachine", Value = "eunit", {ok, ReqState} = set_metadata(Key, Value, #wm_reqstate{metadata=orddict:new()}), ?assertEqual({Value, ReqState}, get_metadata(Key, ReqState)). peer_test() -> Self = self(), Pid = spawn_link(fun() -> {ok, LS} = gen_tcp:listen(0, [binary, {active, false}]), {ok, {_, Port}} = inet:sockname(LS), Self ! {port, Port}, {ok, S} = gen_tcp:accept(LS), receive stop -> ok after 2000 -> ok end, gen_tcp:close(S), gen_tcp:close(LS) end), receive {port, Port} -> {ok, S} = gen_tcp:connect({127,0,0,1}, Port, [binary, {active, false}]), ReqData = #wm_reqdata{req_headers = mochiweb_headers:make([])}, ReqState = #wm_reqstate{socket=S, reqdata=ReqData}, ?assertEqual({S, ReqState}, socket(ReqState)), {"127.0.0.1", NReqState} = get_peer(ReqState), ?assertEqual("127.0.0.1", NReqState#wm_reqstate.peer), Pid ! stop, gen_tcp:close(S) after 2000 -> exit({error, listener_fail}) end. -endif. ././@LongLink0000000000000000000000000000015200000000000011563 Lustar rootrootrabbitmq-server-3.2.4/plugins-src/webmachine-wrapper/webmachine-git/src/webmachine_logger_watcher_sup.erlrabbitmq-server-3.2.4/plugins-src/webmachine-wrapper/webmachine-git/src/webmachine_logger_watcher_su0000644000000000000000000000227712305126066032644 0ustar rootroot%% Copyright (c) 2011-2012 Basho Technologies, Inc. All Rights Reserved. %% %% This file is provided to you under the Apache License, %% Version 2.0 (the "License"); you may not use this file %% except in compliance with the License. You may obtain %% a copy of the License at %% %% http://www.apache.org/licenses/LICENSE-2.0 %% %% Unless required by applicable law or agreed to in writing, %% software distributed under the License is distributed on an %% "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY %% KIND, either express or implied. See the License for the %% specific language governing permissions and limitations %% under the License. %% @doc A supervisor for monitoring webmachine_logger_handler_watcher processes. %% @private -module(webmachine_logger_watcher_sup). -behaviour(supervisor). %% API -export([start_link/0]). %% Callbacks -export([init/1]). start_link() -> supervisor:start_link({local, ?MODULE}, ?MODULE, []). init([]) -> {ok, {{simple_one_for_one, 10, 60}, [ {webmachine_logger_watcher, {webmachine_logger_watcher, start_link, []}, transient, 5000, worker, [webmachine_logger_watcher]} ]}}. ././@LongLink0000000000000000000000000000015000000000000011561 Lustar rootrootrabbitmq-server-3.2.4/plugins-src/webmachine-wrapper/webmachine-git/src/webmachine_perf_log_handler.erlrabbitmq-server-3.2.4/plugins-src/webmachine-wrapper/webmachine-git/src/webmachine_perf_log_handler.0000644000000000000000000000746612305126066032516 0ustar rootroot%% Copyright (c) 2011-2013 Basho Technologies, Inc. All Rights Reserved. %% %% This file is provided to you under the Apache License, %% Version 2.0 (the "License"); you may not use this file %% except in compliance with the License. You may obtain %% a copy of the License at %% %% http://www.apache.org/licenses/LICENSE-2.0 %% %% Unless required by applicable law or agreed to in writing, %% software distributed under the License is distributed on an %% "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY %% KIND, either express or implied. See the License for the %% specific language governing permissions and limitations %% under the License. %% @doc Default performance log handler for webmachine -module(webmachine_perf_log_handler). -behaviour(gen_event). %% gen_event callbacks -export([init/1, handle_call/2, handle_event/2, handle_info/2, terminate/2, code_change/3]). -include("webmachine_logger.hrl"). -ifdef(TEST). -include_lib("eunit/include/eunit.hrl"). -endif. -record(state, {hourstamp, filename, handle}). -define(FILENAME, "perf.log"). %% =================================================================== %% gen_event callbacks %% =================================================================== %% @private init([BaseDir]) -> webmachine_log:defer_refresh(?MODULE), FileName = filename:join(BaseDir, ?FILENAME), {Handle, DateHour} = webmachine_log:log_open(FileName), {ok, #state{filename=FileName, handle=Handle, hourstamp=DateHour}}. %% @private handle_call({_Label, MRef, get_modules}, State) -> {ok, {MRef, [?MODULE]}, State}; handle_call({refresh, Time}, State) -> {ok, ok, webmachine_log:maybe_rotate(?MODULE, Time, State)}; handle_call(_Request, State) -> {ok, ok, State}. %% @private handle_event({log_access, LogData}, State) -> NewState = webmachine_log:maybe_rotate(?MODULE, os:timestamp(), State), Msg = format_req(LogData), webmachine_log:log_write(NewState#state.handle, Msg), {ok, NewState}; handle_event(_Event, State) -> {ok, State}. %% @private handle_info(_Info, State) -> {ok, State}. %% @private terminate(_Reason, _State) -> ok. %% @private code_change(_OldVsn, State, _Extra) -> {ok, State}. %% =================================================================== %% Internal functions %% =================================================================== format_req(#wm_log_data{resource_module=Mod, start_time=StartTime, method=Method, peer=Peer, path=Path, version=Version, response_code=ResponseCode, response_length=ResponseLength, end_time=EndTime, finish_time=FinishTime}) -> Time = webmachine_log:fmtnow(), Status = case ResponseCode of {Code, _ReasonPhrase} when is_integer(Code) -> integer_to_list(Code); _ when is_integer(ResponseCode) -> integer_to_list(ResponseCode); _ -> ResponseCode end, Length = integer_to_list(ResponseLength), TTPD = webmachine_util:now_diff_milliseconds(EndTime, StartTime), TTPS = webmachine_util:now_diff_milliseconds(FinishTime, EndTime), fmt_plog(Time, Peer, atom_to_list(Method), Path, Version, Status, Length, atom_to_list(Mod), integer_to_list(TTPD), integer_to_list(TTPS)). fmt_plog(Time, Ip, Method, Path, {VM,Vm}, Status, Length, Mod, TTPD, TTPS) -> [webmachine_log:fmt_ip(Ip), " - ", [$\s], Time, [$\s, $"], Method, " ", Path, " HTTP/", integer_to_list(VM), ".", integer_to_list(Vm), [$",$\s], Status, [$\s], Length, " " , Mod, " ", TTPD, " ", TTPS, $\n]. rabbitmq-server-3.2.4/plugins-src/webmachine-wrapper/webmachine-git/src/webmachine_dispatcher.erl0000644000000000000000000005631112305126066032046 0ustar rootroot%% @author Robert Ahrens %% @author Justin Sheehy %% @copyright 2007-2009 Basho Technologies %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. %% You may obtain a copy of the License at %% %% http://www.apache.org/licenses/LICENSE-2.0 %% %% Unless required by applicable law or agreed to in writing, software %% distributed under the License is distributed on an "AS IS" BASIS, %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %% See the License for the specific language governing permissions and %% limitations under the License. %% @doc Module for URL-dispatch by pattern matching. -module(webmachine_dispatcher). -author('Robert Ahrens '). -author('Justin Sheehy '). -author('Bryan Fink '). -export([dispatch/3, dispatch/4]). -define(SEPARATOR, $\/). -define(MATCH_ALL, '*'). %% @spec dispatch(Path::string(), DispatchList::[matchterm()], %% wrq:reqdata()) -> %% dispterm() | dispfail() %% @doc Interface for URL dispatching. %% See also http://bitbucket.org/justin/webmachine/wiki/DispatchConfiguration dispatch(PathAsString, DispatchList, RD) -> dispatch([], PathAsString, DispatchList, RD). %% @spec dispatch(Host::string(), Path::string(), %% DispatchList::[matchterm()], wrq:reqdata()) -> %% dispterm() | dispfail() %% @doc Interface for URL dispatching. %% See also http://bitbucket.org/justin/webmachine/wiki/DispatchConfiguration dispatch(HostAsString, PathAsString, DispatchList, RD) -> Path = string:tokens(PathAsString, [?SEPARATOR]), % URIs that end with a trailing slash are implicitly one token % "deeper" than we otherwise might think as we are "inside" % a directory named by the last token. ExtraDepth = case lists:last(PathAsString) == ?SEPARATOR of true -> 1; _ -> 0 end, {Host, Port} = split_host_port(HostAsString, wrq:scheme(RD)), try_host_binding(DispatchList, Host, Port, Path, ExtraDepth, RD). split_host_port(HostAsString, Scheme) -> case string:tokens(HostAsString, ":") of [HostPart, PortPart] -> {split_host(HostPart), list_to_integer(PortPart)}; [HostPart] -> {split_host(HostPart), default_port(Scheme)}; [] -> %% no host header {[], default_port(Scheme)}; _ -> %% Invalid host header {invalid_host, default_port(Scheme)} end. split_host(HostAsString) -> string:tokens(HostAsString, "."). default_port(http) -> 80; default_port(https) -> 443. %% @type matchterm() = hostmatchterm() | pathmatchterm(). % The dispatch configuration is a list of these terms, and the % first one whose host and path terms match the input is used. % Using a pathmatchterm() here is equivalent to using a hostmatchterm() % of the form {{['*'],'*'}, [pathmatchterm()]}. %% @type hostmatchterm() = {hostmatch(), [pathmatchterm()]}. % The dispatch configuration contains a list of these terms, and the % first one whose host and one pathmatchterm match is used. %% @type hostmatch() = [hostterm()] | {[hostterm()], portterm()}. % A host header (Host, X-Forwarded-For, etc.) will be matched against % this term. Using a raws [hostterm()] list is equivalent to using % {[hostterm()], '*'}. %% @type hostterm() = '*' | string() | atom(). % A list of hostterms is matched against a '.'-separated hostname. % The '*' hosterm matches all remaining tokens, and is only allowed at % the head of the list. % A string hostterm will match a token of exactly the same string. % Any atom hostterm other than '*' will match any token and will % create a binding in the result if a complete match occurs. %% @type portterm() = '*' | integer() | atom(). % A portterm is matched against the integer port after any ':' in % the hostname, or 80 if no port is found. % The '*' portterm patches any port % An integer portterm will match a port of exactly the same integer. % Any atom portterm other than '*' will match any port and will % create a binding in the result if a complete match occurs. %% @type pathmatchterm() = {[pathterm()], matchmod(), matchopts()} | %% {[pathterm()], guardfun(), matchmod(), matchopts()}. % The dispatch configuration contains a list of these terms, and the % first one whose list of pathterms matches the input path is used. %% @type pathterm() = '*' | string() | atom(). % A list of pathterms is matched against a '/'-separated input path. % The '*' pathterm matches all remaining tokens. % A string pathterm will match a token of exactly the same string. % Any atom pathterm other than '*' will match any token and will % create a binding in the result if a complete match occurs. %% @type guardfun() = (wrq:reqdata()) -> boolean() %% | {Mod::atom(), Fun::atom()}. % This function or tuple representing a function, if present, is % called after a successful match of the host, port, and path for a % dispatch entry. The function should take a single argument, the % request data object, and return a boolean. If the return value is % 'true', then this dispatch entry is used to service the % request. Otherwise, webmachine will continue with the next dispatch % entry. %% @type matchmod() = atom(). % This atom, if present in a successful matchterm, will appear in % the resulting dispterm. In Webmachine this is used to name the % resource module that will handle the matching request. %% @type matchopts() = [term()]. % This term, if present in a successful matchterm, will appear in % the resulting dispterm. In Webmachine this is used to provide % arguments to the resource module handling the matching request. %% @type dispterm() = {matchmod(), matchopts(), pathtokens(), %% bindings(), approot(), stringpath()}. %% @type pathtokens() = [pathtoken()]. % This is the list of tokens matched by a trailing '*' pathterm. %% @type pathtoken() = string(). %% @type bindings() = [{bindingterm(),pathtoken()}]. % This is a proplist of bindings indicated by atom terms in the % matching spec, bound to the matching tokens in the request path. %% @type approot() = string(). %% @type stringpath() = string(). % This is the path portion matched by a trailing '*' pathterm. %% @type dispfail() = {no_dispatch_match, pathtokens()}. try_host_binding(_Dispatch, invalid_host, _Port, _Path, _Depth, _RD) -> {error, invalid_host}; try_host_binding(Dispatch, Host, Port, Path, Depth, RD) -> %% save work during each dispatch attempt by reversing Host up front try_host_binding1(Dispatch, lists:reverse(Host), Port, Path, Depth, RD). try_host_binding1([], Host, Port, Path, _Depth, _RD) -> %% Host was reversed inbound, correct it for result {no_dispatch_match, {lists:reverse(Host), Port}, Path}; try_host_binding1([Dispatch|Rest], Host, Port, Path, Depth, RD) -> {{HostSpec,PortSpec},PathSpec} = case Dispatch of {{H,P},S} -> {{H,P},S}; {H,S} -> {{H,?MATCH_ALL},S}; S -> {{[?MATCH_ALL],?MATCH_ALL},[S]} end, case bind_port(PortSpec, Port, []) of {ok, PortBindings} -> case bind(lists:reverse(HostSpec), Host, PortBindings, 0) of {ok, RevHostRemainder, HostBindings, _} -> %% Host was reversed inbound, correct it for remainder HostRemainder = lists:reverse(RevHostRemainder), case try_path_binding(PathSpec, Path, HostRemainder, Port, HostBindings, Depth, RD) of {Mod, Props, PathRemainder, PathBindings, AppRoot, StringPath} -> {Mod, Props, HostRemainder, Port, PathRemainder, PathBindings, AppRoot, StringPath}; {no_dispatch_match, _} -> try_host_binding1(Rest, Host, Port, Path, Depth, RD) end; fail -> try_host_binding1(Rest, Host, Port, Path, Depth, RD) end; fail -> try_host_binding1(Rest, Host, Port, Path, Depth, RD) end. bind_port(Port, Port, Bindings) -> {ok, Bindings}; bind_port(?MATCH_ALL, _Port, Bindings) -> {ok, Bindings}; bind_port(PortAtom, Port, Bindings) when is_atom(PortAtom) -> {ok, [{PortAtom, Port}|Bindings]}; bind_port(_, _, _) -> fail. try_path_binding([], PathTokens, _, _, _, _, _) -> {no_dispatch_match, PathTokens}; try_path_binding([PathSpec|Rest], PathTokens, HostRemainder, Port, HostBindings, ExtraDepth, RD) -> {PathSchema, Guard, Mod, Props} = case PathSpec of {P, M, Pr} -> {P, undefined, M, Pr}; {P, G, M, Pr} -> {P, G, M, Pr} end, case bind(PathSchema, PathTokens, HostBindings, 0) of {ok, Remainder, NewBindings, Depth} -> AppRoot = calculate_app_root(Depth + ExtraDepth), StringPath = reconstitute(Remainder), PathInfo = orddict:from_list(NewBindings), RD1 = case RD of testing_ignore_dialyzer_warning_here -> testing_ignore_dialyzer_warning_here; _ -> wrq:load_dispatch_data(PathInfo, HostRemainder, Port, Remainder, AppRoot, StringPath, RD) end, case run_guard(Guard, RD1) of true -> {Mod, Props, Remainder, NewBindings, AppRoot, StringPath}; false -> try_path_binding(Rest, PathTokens, HostRemainder, Port, HostBindings, ExtraDepth, RD) end; fail -> try_path_binding(Rest, PathTokens, HostRemainder, Port, HostBindings, ExtraDepth, RD) end. run_guard(undefined, _RD) -> true; run_guard(Fun, RD) when is_function(Fun) -> try Fun(RD) == true catch _Type : Msg -> error_logger:error_msg("Error running guard ~p: ~p~n", [Fun, Msg]), throw({error_running_guard, Fun, Msg}) end; run_guard({Mod, Fun}, RD) -> try Mod:Fun(RD) == true catch _Type : Msg -> error_logger:error_msg("Error running guard ~p:~p/1: ~p~n", [Mod, Fun, Msg]), throw({error_running_guard, {Mod, Fun}, Msg}) end; run_guard(Other, _) -> error_logger:error_msg("Unknown guard type in webmachine_dispatcher: ~p~n", [Other]), throw({unknown_guard_type, Other}). bind([], [], Bindings, Depth) -> {ok, [], Bindings, Depth}; bind([?MATCH_ALL], Rest, Bindings, Depth) when is_list(Rest) -> {ok, Rest, Bindings, Depth + length(Rest)}; bind(_, [], _, _) -> fail; bind([Token|RestToken],[Match|RestMatch],Bindings,Depth) when is_atom(Token) -> bind(RestToken, RestMatch, [{Token, Match}|Bindings], Depth + 1); bind([Token|RestToken], [Token|RestMatch], Bindings, Depth) -> bind(RestToken, RestMatch, Bindings, Depth + 1); bind(_, _, _, _) -> fail. reconstitute([]) -> ""; reconstitute(UnmatchedTokens) -> string:join(UnmatchedTokens, [?SEPARATOR]). calculate_app_root(1) -> "."; calculate_app_root(N) when N > 1 -> string:join(lists:duplicate(N, ".."), [?SEPARATOR]). %% %% TEST %% -ifdef(TEST). -include_lib("eunit/include/eunit.hrl"). -include("wm_reqstate.hrl"). -include("wm_reqdata.hrl"). app_root_test() -> ?assertEqual(".", calculate_app_root(1)), ?assertEqual("../..", calculate_app_root(2)), ?assertEqual("../../..", calculate_app_root(3)), ?assertEqual("../../../..", calculate_app_root(4)). reconstitute_test() -> ?assertEqual("", reconstitute([])), ?assertEqual("foo", reconstitute(["foo"])), ?assertEqual("foo/bar", reconstitute(["foo","bar"])), ?assertEqual("foo/bar/baz", reconstitute(["foo","bar","baz"])). split_host_test() -> ?assertEqual(["foo","bar","baz"], split_host("foo.bar.baz")). split_host_port_test() -> ?assertEqual({[], 80}, split_host_port("", http)), ?assertEqual({["foo","bar","baz"], 80}, split_host_port("foo.bar.baz:80", http)), ?assertEqual({["foo","bar","baz"], 1234}, split_host_port("foo.bar.baz:1234", http)), ?assertEqual({[], 443}, split_host_port("", https)), ?assertEqual({["foo","bar","baz"], 443}, split_host_port("foo.bar.baz", https)), ?assertEqual({["foo","bar","baz"], 1234}, split_host_port("foo.bar.baz:1234", https)). %% port binding bind_port_simple_match_test() -> ?assertEqual({ok, []}, bind_port(80, 80, [])), ?assertEqual({ok, [{foo, bar}]}, bind_port(1234, 1234, [{foo, bar}])). bind_port_matchall_test() -> ?assertEqual({ok, []}, bind_port('*', 80, [])), ?assertEqual({ok, [{foo, bar}]}, bind_port('*', 1234, [{foo, bar}])). bind_port_match_test() -> ?assertEqual({ok, [{foo, 80}]}, bind_port(foo, 80, [])), {ok, WholeBinding} = bind_port(foo, 1234, [{bar, baz}]), ?assertEqual(2, length(WholeBinding)), ?assertEqual(1234, proplists:get_value(foo, WholeBinding)), ?assertEqual(baz, proplists:get_value(bar, WholeBinding)). ind_port_fail_test() -> ?assertEqual(fail, bind_port(80, 1234, [])). %% path binding bind_path_empty_test() -> ?assertEqual({ok, [], [], 0}, bind([], [], [], 0)), ?assertEqual({ok, [], [{x,"a"}], 1}, bind([], [], [{x,"a"}], 1)). bind_path_matchall_test() -> ?assertEqual({ok, [], [], 1}, bind(['*'], [], [], 1)), ?assertEqual({ok, ["a","b"], [], 2}, bind(['*'], ["a","b"], [], 0)). bind_path_fail_longer_match_test() -> ?assertEqual(fail, bind(["x"], [], [], 0)), ?assertEqual(fail, bind([foo], [], [], 0)). bind_path_with_binding_test() -> ?assertEqual({ok, [], [{foo, "a"}], 1}, bind([foo], ["a"], [], 0)), {ok, Rest, Bind, Depth} = bind([foo,'*'], ["a","b"], [{bar, baz}], 1), ?assertEqual(["b"], Rest), ?assertEqual(3, Depth), ?assertEqual(2, length(Bind)), ?assertEqual("a", proplists:get_value(foo, Bind)), ?assertEqual(baz, proplists:get_value(bar, Bind)). bind_path_string_match_test() -> ?assertEqual({ok, [], [], 1}, bind(["a"], ["a"], [], 0)), ?assertEqual({ok, [], [{foo, bar}], 4}, bind(["a","b","c"], ["a","b","c"], [{foo, bar}], 1)). bind_path_string_fail_test() -> ?assertEqual(fail, bind(["a"], ["b"], [], 0)), ?assertEqual(fail, bind(["a","b"], ["a","c"], [], 0)). try_path_matching_test() -> RD = testing_ignore_dialyzer_warning_here, ?assertEqual({bar, baz, [], [], ".", ""}, try_path_binding([{["foo"], bar, baz}], ["foo"], [], 80, [], 0, RD)), Dispatch = [{["a", x], foo, bar}, {["b", y], baz, quux}, {["b", y, '*'], baz2, quux2}], ?assertEqual({foo, bar, [], [{x, "c"}], "../..", []}, try_path_binding(Dispatch, ["a","c"], [], 80, [], 0, RD)), ?assertEqual({baz, quux, [], [{y, "c"}], "../..", []}, try_path_binding(Dispatch, ["b","c"], [], 80, [], 0, RD)), ?assertEqual({baz2, quux2, ["z"], [{y, "c"}], "../../..", "z"}, try_path_binding(Dispatch, ["b","c","z"], [], 80, [], 0, RD)), ?assertEqual({baz2, quux2, ["z","v"], [{y, "c"}], "../../../..", "z/v"}, try_path_binding(Dispatch, ["b","c","z","v"], [], 80, [], 0, RD)). try_path_failing_test() -> RD = testing_ignore_dialyzer_warning_here, ?assertEqual({no_dispatch_match, ["a"]}, try_path_binding([{["b"], x, y}], ["a"], [], 80, [], 0, RD)). %% host binding try_host_binding_nohosts_test() -> RD = testing_ignore_dialyzer_warning_here, PathDispatches = [{["a"], foo, bar}, {["b"], baz, quux}], ?assertEqual(try_host_binding([{{['*'],'*'},PathDispatches}], ["quux","baz"], 80, ["a"], 0, RD), try_host_binding(PathDispatches, ["quux","baz"], 80, ["a"], 0, RD)), ?assertEqual(try_host_binding([{{['*'],'*'},PathDispatches}], ["quux","baz"], 80, ["b"], 0, RD), try_host_binding(PathDispatches, ["quux","baz"], 80, ["b"], 0, RD)), ?assertEqual(try_host_binding([ {{['*'],'*'},[D]} || D <- PathDispatches], ["quux","baz"], 1234, ["a"], 0, RD), try_host_binding(PathDispatches, ["quux","baz"], 1234, ["a"], 0, RD)), ?assertEqual(try_host_binding([ {{['*'],'*'},[D]} || D <- PathDispatches], ["quux","baz"], 1234, ["b"], 0, RD), try_host_binding(PathDispatches, ["quux","baz"], 1234, ["b"], 0, RD)). try_host_binding_noport_test() -> RD = testing_ignore_dialyzer_warning_here, Dispatch = [{["foo","bar"], [{["a"],x,y}]}, {["baz","quux"],[{["b"],z,q}]}, {[m,"quux"], [{["c"],r,s}]}, {['*',"quux"], [{["d"],t,u}]}], ExplicitWildPort = [ {{H, '*'},P} || {H, P} <- Dispatch ], ?assertEqual(try_host_binding(ExplicitWildPort, ["bar","foo"], 80, ["a"], 0, RD), try_host_binding(Dispatch, ["bar","foo"], 80, ["a"], 0, RD)), ?assertEqual(try_host_binding(ExplicitWildPort, ["quux","baz"], 1234, ["b"], 0, RD), try_host_binding(Dispatch, ["quux","baz"], 1234, ["b"], 0, RD)), ?assertEqual(try_host_binding(ExplicitWildPort, ["quux","yes"], 81, ["c"], 0, RD), try_host_binding(Dispatch, ["quux","yes"], 81, ["c"], 0, RD)), ?assertEqual(try_host_binding(ExplicitWildPort, ["quux","no"], 82, ["d"], 0, RD), try_host_binding(Dispatch, ["quux","no"], 82, ["d"], 0, RD)). try_host_binding_fullmatch_test() -> RD = testing_ignore_dialyzer_warning_here, Dispatch = [{{["foo","bar"],80},[{["a"],x,y}]}, {{[foo,"bar"],80}, [{["b"],z,q}]}, {{[foo,"bar"],baz}, [{["c"],r,s}]}, {{['*',"bar"],'*'}, [{["d"],t,u}]}], ?assertEqual({x, y, [], 80, [], [], ".", ""}, try_host_binding(Dispatch, ["foo","bar"], 80, ["a"], 0, RD)), ?assertEqual({z, q, [], 80, [], [{foo,"baz"}], ".", ""}, try_host_binding(Dispatch, ["baz","bar"], 80, ["b"], 0, RD)), {Mod, Props, HostRemainder, Port, PathRemainder, PathBindings, AppRoot, StringPath}= try_host_binding(Dispatch, ["quux","bar"], 1234, ["c"], 0, RD), ?assertEqual(r, Mod), ?assertEqual(s, Props), ?assertEqual("", HostRemainder), ?assertEqual(1234, Port), ?assertEqual([], PathRemainder), ?assertEqual(2, length(PathBindings)), ?assertEqual("quux", proplists:get_value(foo, PathBindings)), ?assertEqual(1234, proplists:get_value(baz, PathBindings)), ?assertEqual(".", AppRoot), ?assertEqual("", StringPath), ?assertEqual({t, u, ["foo","quux"], 80, [], [], ".", ""}, try_host_binding(Dispatch, ["foo","quux","bar"],80,["d"],0, RD)). try_host_binding_wildcard_token_order_test() -> RD = wrq:create('GET', http, {1,1}, "testing", mochiweb_headers:from_list([])), Dispatch = [{{['*',"quux","com"],80},[{['*'],x,y}]}], ?assertEqual({x,y,["foo","bar","baz"],80,[],[],".",""}, dispatch("foo.bar.baz.quux.com","/",Dispatch,RD)). try_host_binding_fail_test() -> RD = testing_ignore_dialyzer_warning_here, ?assertEqual({no_dispatch_match, {["bar","foo"], 1234}, ["x","y","z"]}, try_host_binding([], ["bar","foo"], 1234, ["x","y","z"], 0, RD)). dispatch_test() -> RD = wrq:create('GET', http, {1,1}, "testing", mochiweb_headers:from_list([])), TrueFun = fun(_) -> true end, FalseFun = fun(_) -> false end, ?assertEqual({x, y, [], 80, [], [], "../../..", ""}, dispatch("a/b/c",[{["a","b","c"],x,y}], RD)), ?assertEqual({x, y, [], 80, [], [], "../../..", ""}, dispatch("a/b/c",[{["a","b","c"],TrueFun,x,y}], RD)), ?assertEqual({no_dispatch_match, {[],80},["a","b","c"]}, dispatch("a/b/c",[{["a","b","c"],FalseFun,x,y}], RD)), ?assertEqual({x, y, [], 80, [], [], "../../..", ""}, dispatch("foo.bar", "a/b/c", [{{["foo","bar"],80},[{["a","b","c"],x,y}]}], RD)), ?assertEqual({x, y, [], 1234, [], [], "../../..", ""}, dispatch("foo.bar:1234", "a/b/", [{{["foo","bar"],1234},[{["a","b"],x,y}]}], RD)), ?assertEqual({no_dispatch_match, {["baz","bar"],8000}, ["q","r"]}, dispatch("baz.bar:8000", "q/r", [{{["foo","bar"],80},[{["a","b","c"],x,y}]}], RD)). guard1_test() -> %% Basic guard test. Match everything. Guard = fun(_) -> true end, DispatchList = [{['*'], Guard, foo, bar}], ?assertEqual( {foo, bar, [], 80, ["test"], [], ".", "test"}, dispatch("test", DispatchList, make_reqdata("/test"))), ok. guard2_test() -> %% Basic guard test. Use guard to prevent all matches. Guard = fun(_) -> false end, DispatchList = [{['*'], Guard, foo, bar}], ?assertEqual( {no_dispatch_match, {[], 80}, ["test"]}, dispatch("test", DispatchList, make_reqdata("/test"))), ok. guard3_test() -> %% Check that path_info and path_tokens are passed to the guard... Guard = fun(RD) -> ?assertEqual("a", wrq:path_info(a, RD)), ?assertEqual("b", wrq:path_info(b, RD)), ?assertEqual("c", wrq:path_info(c, RD)), ?assertEqual(["d", "e"], wrq:path_tokens(RD)), true end, DispatchList = [{[a,b,c,'*'], Guard, foo, bar}], ?assertEqual( {foo,bar,[],80, ["d","e"], [{c,"c"},{b,"b"},{a,"a"}], "../../../../..","d/e"}, dispatch("a/b/c/d/e", DispatchList, make_reqdata("/a/b/c/d/e"))), ok. guard4_test() -> %% Check that host and port are possed to the guard... Guard = fun(RD) -> ?assertEqual("0", wrq:path_info(x, RD)), ?assertEqual("0", wrq:path_info(y, RD)), ?assertEqual("1", wrq:path_info(z, RD)), ?assertEqual(80, wrq:port(RD)), true end, DispatchList= [{ {["127",x,y,z], 80}, [ {['*'], Guard, foo, bar} ] }], ?assertEqual( {foo,bar,[],80, ["a","b","c","d","e"], [{x,"0"},{y,"0"},{z,"1"}], "../../../../..","a/b/c/d/e"}, dispatch("127.0.0.1", "a/b/c/d/e", DispatchList, make_reqdata("http://127.0.0.1:80/a/b/c/d/e"))), ok. make_reqdata(Path) -> %% Helper function to construct a request and return the ReqData %% object. MochiReq = mochiweb_request:new(testing, 'GET', Path, {1, 1}, mochiweb_headers:make([])), Req = webmachine:new_request(mochiweb, MochiReq), {RD, _} = Req:get_reqdata(), RD. -endif. rabbitmq-server-3.2.4/plugins-src/webmachine-wrapper/webmachine-git/src/wrq.erl0000644000000000000000000003266212305126066026352 0ustar rootroot%% @author Justin Sheehy %% @copyright 2007-2009 Basho Technologies %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. %% You may obtain a copy of the License at %% %% http://www.apache.org/licenses/LICENSE-2.0 %% %% Unless required by applicable law or agreed to in writing, software %% distributed under the License is distributed on an "AS IS" BASIS, %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %% See the License for the specific language governing permissions and %% limitations under the License. -module(wrq). -author('Justin Sheehy '). -export([create/4, create/5,load_dispatch_data/7]). -export([method/1,scheme/1,version/1,peer/1,disp_path/1,path/1,raw_path/1, path_info/1,response_code/1,req_cookie/1,req_qs/1,req_headers/1, req_body/1,stream_req_body/2,resp_redirect/1,resp_headers/1, resp_body/1,app_root/1,path_tokens/1, host_tokens/1, port/1, base_uri/1]). -export([path_info/2,get_req_header/2,do_redirect/2,fresh_resp_headers/2, get_resp_header/2,set_resp_header/3,set_resp_headers/2, set_disp_path/2,set_req_body/2,set_resp_body/2,set_response_code/2, merge_resp_headers/2,remove_resp_header/2, append_to_resp_body/2,append_to_response_body/2, set_resp_range/2, max_recv_body/1,set_max_recv_body/2, get_cookie_value/2,get_qs_value/2,get_qs_value/3,set_peer/2, add_note/3, get_notes/1]). % @type reqdata(). The opaque data type used for req/resp data structures. -include("wm_reqdata.hrl"). -include("wm_reqstate.hrl"). create(Method,Version,RawPath,Headers) -> create(Method,http,Version,RawPath,Headers). create(Method,Scheme,Version,RawPath,Headers) -> create(#wm_reqdata{method=Method,scheme=Scheme,version=Version, raw_path=RawPath,req_headers=Headers, wm_state=defined_on_call, path="defined_in_create", req_cookie=defined_in_create, req_qs=defined_in_create, peer="defined_in_wm_req_srv_init", req_body=not_fetched_yet, max_recv_body=(1024*(1024*1024)), % Stolen from R13B03 inet_drv.c's TCP_MAX_PACKET_SIZE definition max_recv_hunk=(64*(1024*1024)), app_root="defined_in_load_dispatch_data", path_info=orddict:new(), path_tokens=defined_in_load_dispatch_data, disp_path=defined_in_load_dispatch_data, resp_redirect=false, resp_headers=mochiweb_headers:empty(), resp_body = <<>>, response_code=500, resp_range = follow_request, notes=[]}). create(RD = #wm_reqdata{raw_path=RawPath}) -> {Path, _, _} = mochiweb_util:urlsplit_path(RawPath), Cookie = case get_req_header("cookie", RD) of undefined -> []; Value -> mochiweb_cookies:parse_cookie(Value) end, {_, QueryString, _} = mochiweb_util:urlsplit_path(RawPath), ReqQS = mochiweb_util:parse_qs(QueryString), RD#wm_reqdata{path=Path,req_cookie=Cookie,req_qs=ReqQS}. load_dispatch_data(PathInfo, HostTokens, Port, PathTokens, AppRoot, DispPath, RD) -> RD#wm_reqdata{path_info=PathInfo,host_tokens=HostTokens, port=Port,path_tokens=PathTokens, app_root=AppRoot,disp_path=DispPath}. method(_RD = #wm_reqdata{method=Method}) -> Method. scheme(_RD = #wm_reqdata{scheme=Scheme}) -> Scheme. version(_RD = #wm_reqdata{version=Version}) when is_tuple(Version), size(Version) == 2, is_integer(element(1,Version)), is_integer(element(2,Version)) -> Version. peer(_RD = #wm_reqdata{peer=Peer}) when is_list(Peer) -> Peer. app_root(_RD = #wm_reqdata{app_root=AR}) when is_list(AR) -> AR. % all three paths below are strings disp_path(_RD = #wm_reqdata{disp_path=DP}) when is_list(DP) -> DP. path(_RD = #wm_reqdata{path=Path}) when is_list(Path) -> Path. raw_path(_RD = #wm_reqdata{raw_path=RawPath}) when is_list(RawPath) -> RawPath. path_info(_RD = #wm_reqdata{path_info=PathInfo}) -> PathInfo. % dict path_tokens(_RD = #wm_reqdata{path_tokens=PathT}) -> PathT. % list of strings host_tokens(_RD = #wm_reqdata{host_tokens=HostT}) -> HostT. % list of strings port(_RD = #wm_reqdata{port=Port}) -> Port. % integer response_code(_RD = #wm_reqdata{response_code={C,_ReasonPhrase}}) when is_integer(C) -> C; response_code(_RD = #wm_reqdata{response_code=C}) when is_integer(C) -> C. req_cookie(_RD = #wm_reqdata{req_cookie=C}) when is_list(C) -> C. % string %% @spec req_qs(reqdata()) -> [{Key, Value}] req_qs(_RD = #wm_reqdata{req_qs=QS}) when is_list(QS) -> QS. req_headers(_RD = #wm_reqdata{req_headers=ReqH}) -> ReqH. % mochiheaders req_body(_RD = #wm_reqdata{wm_state=ReqState0,max_recv_body=MRB}) -> Req = webmachine_request:new(ReqState0), {ReqResp, ReqState} = Req:req_body(MRB), put(tmp_reqstate, ReqState), maybe_conflict_body(ReqResp). stream_req_body(_RD = #wm_reqdata{wm_state=ReqState0}, MaxHunk) -> Req = webmachine_request:new(ReqState0), {ReqResp, ReqState} = Req:stream_req_body(MaxHunk), put(tmp_reqstate, ReqState), maybe_conflict_body(ReqResp). max_recv_body(_RD = #wm_reqdata{max_recv_body=X}) when is_integer(X) -> X. set_max_recv_body(X, RD) when is_integer(X) -> RD#wm_reqdata{max_recv_body=X}. maybe_conflict_body(BodyResponse) -> case BodyResponse of stream_conflict -> exit("wrq:req_body and wrq:stream_req_body conflict"); {error, req_body_too_large} -> exit("request body too large"); _ -> BodyResponse end. resp_redirect(_RD = #wm_reqdata{resp_redirect=true}) -> true; resp_redirect(_RD = #wm_reqdata{resp_redirect=false}) -> false. resp_headers(_RD = #wm_reqdata{resp_headers=RespH}) -> RespH. % mochiheaders resp_body(_RD = #wm_reqdata{resp_body=undefined}) -> undefined; resp_body(_RD = #wm_reqdata{resp_body={stream,X}}) -> {stream,X}; resp_body(_RD = #wm_reqdata{resp_body={known_length_stream,X,Y}}) -> {known_length_stream,X,Y}; resp_body(_RD = #wm_reqdata{resp_body={stream,X,Y}}) -> {stream,X,Y}; resp_body(_RD = #wm_reqdata{resp_body={writer,X}}) -> {writer,X}; resp_body(_RD = #wm_reqdata{resp_body=RespB}) when is_binary(RespB) -> RespB; resp_body(_RD = #wm_reqdata{resp_body=RespB}) -> iolist_to_binary(RespB). %% -- path_info(Key, RD) when is_atom(Key) -> case orddict:find(Key, path_info(RD)) of {ok, Value} when is_list(Value); is_integer(Value) -> Value; % string (for host or path match) % or integer (for port match) error -> undefined end. get_req_header(HdrName, RD) -> % string->string mochiweb_headers:get_value(HdrName, req_headers(RD)). do_redirect(true, RD) -> RD#wm_reqdata{resp_redirect=true}; do_redirect(false, RD) -> RD#wm_reqdata{resp_redirect=false}. set_peer(P, RD) when is_list(P) -> RD#wm_reqdata{peer=P}. % string set_disp_path(P, RD) when is_list(P) -> RD#wm_reqdata{disp_path=P}. % string set_req_body(Body, RD) -> RD#wm_reqdata{req_body=Body}. set_resp_body(Body, RD) -> RD#wm_reqdata{resp_body=Body}. set_response_code({Code, _ReasonPhrase}=CodeAndReason, RD) when is_integer(Code) -> RD#wm_reqdata{response_code=CodeAndReason}; set_response_code(Code, RD) when is_integer(Code) -> RD#wm_reqdata{response_code=Code}. get_resp_header(HdrName, _RD=#wm_reqdata{resp_headers=RespH}) -> mochiweb_headers:get_value(HdrName, RespH). set_resp_header(K, V, RD=#wm_reqdata{resp_headers=RespH}) when is_list(K),is_list(V) -> RD#wm_reqdata{resp_headers=mochiweb_headers:enter(K, V, RespH)}. set_resp_headers(Hdrs, RD=#wm_reqdata{resp_headers=RespH}) -> F = fun({K, V}, Acc) -> mochiweb_headers:enter(K, V, Acc) end, RD#wm_reqdata{resp_headers=lists:foldl(F, RespH, Hdrs)}. fresh_resp_headers(Hdrs, RD) -> F = fun({K, V}, Acc) -> mochiweb_headers:enter(K, V, Acc) end, RD#wm_reqdata{resp_headers=lists:foldl(F, mochiweb_headers:empty(), Hdrs)}. remove_resp_header(K, RD=#wm_reqdata{resp_headers=RespH}) when is_list(K) -> RD#wm_reqdata{resp_headers=mochiweb_headers:from_list( proplists:delete(K, mochiweb_headers:to_list(RespH)))}. merge_resp_headers(Hdrs, RD=#wm_reqdata{resp_headers=RespH}) -> F = fun({K, V}, Acc) -> mochiweb_headers:insert(K, V, Acc) end, NewHdrs = lists:foldl(F, RespH, Hdrs), RD#wm_reqdata{resp_headers=NewHdrs}. append_to_resp_body(Data, RD) -> append_to_response_body(Data, RD). append_to_response_body(Data, RD=#wm_reqdata{resp_body=RespB}) -> case is_binary(Data) of true -> Data0 = RespB, Data1 = <>, RD#wm_reqdata{resp_body=Data1}; false -> % MUST BE an iolist! else, fail. append_to_response_body(iolist_to_binary(Data), RD) end. -spec set_resp_range(follow_request | ignore_request, #wm_reqdata{}) -> #wm_reqdata{}. %% follow_request : range responce for range request, normal responce for non-range one %% ignore_request : normal resopnse for either range reuqest or non-range one set_resp_range(RespRange, RD) when RespRange =:= follow_request orelse RespRange =:= ignore_request -> RD#wm_reqdata{resp_range = RespRange}. get_cookie_value(Key, RD) when is_list(Key) -> % string case lists:keyfind(Key, 1, req_cookie(RD)) of false -> undefined; {Key, Value} -> Value end. get_qs_value(Key, RD) when is_list(Key) -> % string case lists:keyfind(Key, 1, req_qs(RD)) of false -> undefined; {Key, Value} -> Value end. get_qs_value(Key, Default, RD) when is_list(Key) -> case lists:keyfind(Key, 1, req_qs(RD)) of false -> Default; {Key, Value} -> Value end. add_note(K, V, RD) -> RD#wm_reqdata{notes=[{K, V} | RD#wm_reqdata.notes]}. get_notes(RD) -> RD#wm_reqdata.notes. base_uri(RD) -> Scheme = erlang:atom_to_list(RD#wm_reqdata.scheme), Host = string:join(RD#wm_reqdata.host_tokens, "."), PortString = port_string(RD#wm_reqdata.scheme, RD#wm_reqdata.port), Scheme ++ "://" ++ Host ++ PortString. port_string(Scheme, Port) -> case Scheme of http -> case Port of 80 -> ""; _ -> ":" ++ erlang:integer_to_list(Port) end; https -> case Port of 443 -> ""; _ -> ":" ++ erlang:integer_to_list(Port) end; _ -> ":" ++ erlang:integer_to_list(Port) end. %% %% Tests %% -ifdef(TEST). -include_lib("eunit/include/eunit.hrl"). make_wrq(Method, RawPath, Headers) -> make_wrq(Method, http, RawPath, Headers). make_wrq(Method, Scheme, RawPath, Headers) -> create(Method, Scheme, {1,1}, RawPath, mochiweb_headers:from_list(Headers)). accessor_test() -> R0 = make_wrq('GET', "/foo?a=1&b=2", [{"Cookie", "foo=bar"}]), R = set_peer("127.0.0.1", R0), ?assertEqual('GET', method(R)), ?assertEqual({1,1}, version(R)), ?assertEqual("/foo", path(R)), ?assertEqual("/foo?a=1&b=2", raw_path(R)), ?assertEqual([{"a", "1"}, {"b", "2"}], req_qs(R)), ?assertEqual({"1", "2"}, {get_qs_value("a", R), get_qs_value("b", R)}), ?assertEqual("3", get_qs_value("c", "3", R)), ?assertEqual([{"foo", "bar"}], req_cookie(R)), ?assertEqual("bar", get_cookie_value("foo", R)), ?assertEqual("127.0.0.1", peer(R)). simple_dispatch_test() -> R0 = make_wrq('GET', "/foo?a=1&b=2", [{"Cookie", "foo=bar"}]), R1 = set_peer("127.0.0.1", R0), {_, _, HostTokens, Port, PathTokens, Bindings, AppRoot, StringPath} = webmachine_dispatcher:dispatch("127.0.0.1", "/foo", [{["foo"], foo_resource, []}], R1), R = load_dispatch_data(Bindings, HostTokens, Port, PathTokens, AppRoot, StringPath, R1), ?assertEqual(".", app_root(R)), ?assertEqual(80, port(R)), ?assertEqual("http://127.0.0.1", base_uri(R)). base_uri_test_() -> Make_req = fun(Scheme, Host) -> R0 = make_wrq('GET', Scheme, "/foo?a=1&b=2", [{"Cookie", "foo=bar"}]), R1 = set_peer("127.0.0.1", R0), DispatchRule = {["foo"], foo_resource, []}, {_, _, HostTokens, Port, PathTokens, Bindings, AppRoot,StringPath} = webmachine_dispatcher:dispatch(Host, "/foo", [DispatchRule], R1), load_dispatch_data(Bindings, HostTokens, Port, PathTokens, AppRoot, StringPath, R1) end, Tests = [{{http, "somewhere.com:8080"}, "http://somewhere.com:8080"}, {{https, "somewhere.com:8080"}, "https://somewhere.com:8080"}, {{http, "somewhere.com"}, "http://somewhere.com"}, {{https, "somewhere.com"}, "https://somewhere.com"}, {{http, "somewhere.com:80"}, "http://somewhere.com"}, {{https, "somewhere.com:443"}, "https://somewhere.com"}, {{https, "somewhere.com:80"}, "https://somewhere.com:80"}, {{http, "somewhere.com:443"}, "http://somewhere.com:443"}], [ ?_assertEqual(Expect, base_uri(Make_req(Scheme, Host))) || {{Scheme, Host}, Expect} <- Tests ]. -endif. rabbitmq-server-3.2.4/plugins-src/webmachine-wrapper/webmachine-git/src/webmachine_app.erl0000644000000000000000000000325512305126066030477 0ustar rootroot%% @author Justin Sheehy %% @author Andy Gross %% @copyright 2007-2008 Basho Technologies %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. %% You may obtain a copy of the License at %% %% http://www.apache.org/licenses/LICENSE-2.0 %% %% Unless required by applicable law or agreed to in writing, software %% distributed under the License is distributed on an "AS IS" BASIS, %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %% See the License for the specific language governing permissions and %% limitations under the License. %% @doc Callbacks for the webmachine application. -module(webmachine_app). -author('Justin Sheehy '). -author('Andy Gross '). -behaviour(application). -export([start/2, stop/1]). -include("webmachine_logger.hrl"). %% @spec start(_Type, _StartArgs) -> ServerRet %% @doc application start callback for webmachine. start(_Type, _StartArgs) -> webmachine_deps:ensure(), {ok, _Pid} = SupLinkRes = webmachine_sup:start_link(), Handlers = case application:get_env(webmachine, log_handlers) of undefined -> []; {ok, Val} -> Val end, %% handlers failing to start are handled in the handler_watcher _ = [supervisor:start_child(webmachine_logger_watcher_sup, [?EVENT_LOGGER, Module, Config]) || {Module, Config} <- Handlers], SupLinkRes. %% @spec stop(_State) -> ServerRet %% @doc application stop callback for webmachine. stop(_State) -> ok. rabbitmq-server-3.2.4/plugins-src/webmachine-wrapper/webmachine-git/src/webmachine_multipart.erl0000644000000000000000000003311312305126066031734 0ustar rootroot%% @author Justin Sheehy %% @author Andy Gross %% @copyright 2009 Basho Technologies %% @doc Utility for parsing multipart form bodies. %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. %% You may obtain a copy of the License at %% http://www.apache.org/licenses/LICENSE-2.0 %% Unless required by applicable law or agreed to in writing, software %% distributed under the License is distributed on an "AS IS" BASIS, %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %% See the License for the specific language governing permissions and %% limitations under the License. -module(webmachine_multipart). -author('Justin Sheehy '). -author('Andy Gross '). -export([get_all_parts/2,stream_parts/2, find_boundary/1]). % @type incoming_req_body() = binary(). % The request body, in "multipart/form-data" (rfc2388) form, % @type boundary() = string(). % The multipart boundary, as taken from the containing message's content-type. % @type fpart() = {fpartname(), {[fparam()],[fheader()]}, fcontent()}. % A single part of a multipart form. % @type fpartname() = string(). % The name from the form field of a form part. % @type fparam() = {binary(), binary()}. % A key-value parameter from the content-disposition header in a form part. % @type fheader() = {binary(), binary()}. % A header name and value supplied within a form part. % @type fcontent() = binary(). % The body content within a form part. % @doc Find the multipart boundary for a request. % @spec find_boundary(wrq:wm_reqdata()) -> boundary() find_boundary(ReqData) -> ContentType = wrq:get_req_header("content-type", ReqData), string:substr(ContentType, string:str(ContentType, "boundary=") + length("boundary=")). % @doc Turn a multipart form into component parts. % @spec get_all_parts(incoming_req_body(), boundary()) -> [fpart()] get_all_parts(Body, Boundary) when is_binary(Body), is_list(Boundary) -> StreamStruct = send_streamed_body(Body,1024), getparts1(stream_parts(StreamStruct, Boundary), []). % @doc Similar to get_all_parts/2, but for streamed/chunked bodies. % Takes as input the result of wrq:stream_req_body/2, and provides % either the atom 'done_parts' when no more parts are available, or % a tuple with the next part and a function. That function will % have 0-arity and the same return type as stream_parts/2 itself. % @spec stream_parts(wm_stream(), boundary()) -> % 'done_parts' | {fpart(), function()} stream_parts(StreamStruct, Boundary) -> stream_form(StreamStruct, "--" ++ Boundary, []). stream_form(_, _, [<<"----\n">>|_]) -> done_parts; stream_form(_, _, [<<"--\n">>|_]) -> done_parts; stream_form({Hunk, Next}, Boundary, []) -> stream_form(get_more_data(Next), Boundary, re:split(Hunk, Boundary,[])); stream_form({Hunk, Next}, Boundary, [<<>>|DQ]) -> stream_form({Hunk, Next}, Boundary, DQ); stream_form({Hunk, Next}, Boundary, [H|[T1|T2]]) -> {make_part(H), fun() -> stream_form({Hunk, Next}, Boundary, [T1|T2]) end}; stream_form({Hunk, really_done}, Boundary, DQ) -> DQBin = iolist_to_binary(DQ), FullHunk = <>, stream_parts(re:split(FullHunk, Boundary,[])); stream_form({Hunk, Next}, Boundary, [Single]) -> FullHunk = <>, stream_form(get_more_data(Next), Boundary, re:split(FullHunk, Boundary,[])). stream_parts([]) -> done_parts; % browsers are fun, and terminate posts slightly differently from each other: stream_parts([<<"----\n">>]) -> done_parts; stream_parts([<<"--\n">>]) -> done_parts; stream_parts([<<"----\r\n">>]) -> done_parts; stream_parts([<<"--\r\n">>]) -> done_parts; stream_parts([<<"--\r\n--\n">>]) -> done_parts; stream_parts([<<"--\r\n--\r\n">>]) -> done_parts; stream_parts([H|T]) -> {make_part(H), fun() -> stream_parts(T) end}. get_more_data(done) -> {<<"--\n">>, really_done}; get_more_data(Fun) -> Fun(). make_part(PartData) -> %% Remove the trailing \r\n [HeadData, BodyWithCRLF] = re:split(PartData, "\\r\\n\\r\\n", [{parts,2}]), BodyLen = size(BodyWithCRLF) - 2, <> = BodyWithCRLF, HeadList = [list_to_binary(X) || X <- string:tokens(binary_to_list(HeadData), "\r\n")], {Name, Params, Headers} = make_headers(HeadList), {Name, {Params,Headers}, Body}. make_headers(X) -> make_headers(X, name_undefined, params_undefined, []). make_headers([], Name, Params, Headers) -> {Name, Params, Headers}; make_headers([<<>>|HL], Name, Params, Headers) -> make_headers(HL, Name, Params, Headers); make_headers( [<<"Content-Disposition: form-data; ", Names/binary>>|HL], _, _, Headers) -> {Name, Params} = extract_names(Names), make_headers(HL, Name, Params, Headers); make_headers([H|HL], Name, Params, Headers) -> make_headers(HL, Name, Params, [cheap_parse_header(H)|Headers]). extract_names(NamesString) -> Params = [{K, V} || {K, [<<>>, V, <<>>]} <- [{K0, re:split(V0,"\"",[])} || [K0, V0] <- [re:split(N, "=", [{parts, 2}]) || N <- re:split(NamesString, "; ", [])]]], Name = hd([binary_to_list(V) || {<<"name">>,V} <- Params]), {Name, Params}. cheap_parse_header(HeadBin) -> [K,V] = re:split(HeadBin, ": ", [{parts,2}]), {K,V}. getparts1(done_parts, Acc) -> lists:reverse(Acc); getparts1({Part, Streamer}, Acc) -> getparts1(Streamer(), [Part|Acc]). send_streamed_body(Body, Max) -> HunkLen=8*Max, case Body of <> -> {<>, fun() -> send_streamed_body(Rest,Max) end}; _ -> {Body, done} end. %% %% Tests %% -ifdef(TEST). -include_lib("eunit/include/eunit.hrl"). body_test() -> Body = <<"------------ae0gL6gL6Ij5KM7Ef1KM7ei4ae0cH2\r\nContent-Disposition: form-data; name=\"Filename\"\r\n\r\ntestfile.txt\r\n------------ae0gL6gL6Ij5KM7Ef1KM7ei4ae0cH2\r\nContent-Disposition: form-data; name=\"Filedata\"; filename=\"testfile.txt\"\r\nContent-Type: application/octet-stream\r\n\r\n%%% The contents of this file are a test,\n%%% do not be alarmed.\n\r\n------------ae0gL6gL6Ij5KM7Ef1KM7ei4ae0cH2\r\nContent-Disposition: form-data; name=\"Upload\"\r\n\r\nSubmit Query\r\n------------ae0gL6gL6Ij5KM7Ef1KM7ei4ae0cH2--">>, Boundary = "----------ae0gL6gL6Ij5KM7Ef1KM7ei4ae0cH2", ?assertEqual( [{"Filename", {[{<<"name">>,<<"Filename">>}],[]}, <<"testfile.txt">>}, {"Filedata", {[{<<"name">>,<<"Filedata">>}, {<<"filename">>,<<"testfile.txt">>}], [{<<"Content-Type">>,<<"application/octet-stream">>}]}, <<"%%% The contents of this file are a test,\n%%% do not be alarmed.\n">>}, {"Upload",{[{<<"name">>,<<"Upload">>}],[]}, <<"Submit Query">>}], get_all_parts(Body, Boundary)). body2_test() -> Body = <<"-----------------------------89205314411538515011004844897\r\nContent-Disposition: form-data; name=\"Filedata\"; filename=\"akamai.txt\"\r\nContent-Type: text/plain\r\n\r\nCAMBRIDGE, MA - February 18, 2009 - Akamai Technologies, Inc. (NASDAQ: AKAM), the leader in powering rich media, dynamic transactions and enterprise applications online, today announced that its Service & Support organization was awarded top honors for Innovation in Customer Service at the 3rd Annual Stevie Awards for Sales & Customer Service, an international competition recognizing excellence in disciplines that are crucial to business success.\n\n\"We have always set incredibly high standards with respect to the service and support we provide our customers,\" said Sanjay Singh, vice president of Global Service & Support at Akamai. \"Our support team provides highly responsive service around the clock to our global customer base and, as a result, has become an extension of our customers' online businesses. This prestigious award is validation of Akamai's commitment to customer service and technical support.\"\n\nAkamai Service & Support professionals are dedicated to working with customers on a daily basis to fine tune, optimize, and support their Internet initiatives. Akamai's winning submission highlighted the key pillars of its service and support offering, as well as the initiatives established to meet customer requirements for proactive communication, simplification, and faster response times.\n\n\"This year's honorees demonstrate that even in challenging economic times, it's possible for organizations to continue to shine in sales and customer service, the two most important functions in business: acquiring and keeping customers,\" said Michael Gallagher, president of the Stevie Awards.\n\nThe awards are presented by the Stevie Awards, which organizes several of the world's leading business awards shows, including the prestigious American Business Awards. Nicknamed the Stevies for the Greek word \"crowned,\" winners were announced during a gala banquet on Monday, February 9 at Caesars Palace in Las Vegas. Nominated customer service and sales executives from the U.S.A. and several other countries attended. More than 500 entries from companies of all sizes and in virtually every industry were submitted to this year's competition. There are 27 categories for customer service professionals, as well as 41 categories for sales professionals.\n\nDetails about the Stevie Awards for Sales & Customer Service and the list of honorees in all categories are available at www.stevieawards.com/sales. \n\r\n-----------------------------89205314411538515011004844897--\r\n">>, Boundary = "---------------------------89205314411538515011004844897", ?assertEqual( [{"Filedata", {[{<<"name">>,<<"Filedata">>}, {<<"filename">>,<<"akamai.txt">>}], [{<<"Content-Type">>,<<"text/plain">>}]}, <<"CAMBRIDGE, MA - February 18, 2009 - Akamai Technologies, Inc. (NASDAQ: AKAM), the leader in powering rich media, dynamic transactions and enterprise applications online, today announced that its Service & Support organization was awarded top honors for Innovation in Customer Service at the 3rd Annual Stevie Awards for Sales & Customer Service, an international competition recognizing excellence in disciplines that are crucial to business success.\n\n\"We have always set incredibly high standards with respect to the service and support we provide our customers,\" said Sanjay Singh, vice president of Global Service & Support at Akamai. \"Our support team provides highly responsive service around the clock to our global customer base and, as a result, has become an extension of our customers' online businesses. This prestigious award is validation of Akamai's commitment to customer service and technical support.\"\n\nAkamai Service & Support professionals are dedicated to working with customers on a daily basis to fine tune, optimize, and support their Internet initiatives. Akamai's winning submission highlighted the key pillars of its service and support offering, as well as the initiatives established to meet customer requirements for proactive communication, simplification, and faster response times.\n\n\"This year's honorees demonstrate that even in challenging economic times, it's possible for organizations to continue to shine in sales and customer service, the two most important functions in business: acquiring and keeping customers,\" said Michael Gallagher, president of the Stevie Awards.\n\nThe awards are presented by the Stevie Awards, which organizes several of the world's leading business awards shows, including the prestigious American Business Awards. Nicknamed the Stevies for the Greek word \"crowned,\" winners were announced during a gala banquet on Monday, February 9 at Caesars Palace in Las Vegas. Nominated customer service and sales executives from the U.S.A. and several other countries attended. More than 500 entries from companies of all sizes and in virtually every industry were submitted to this year's competition. There are 27 categories for customer service professionals, as well as 41 categories for sales professionals.\n\nDetails about the Stevie Awards for Sales & Customer Service and the list of honorees in all categories are available at www.stevieawards.com/sales. \n">> }], get_all_parts(Body,Boundary)). firefox_test() -> Body = <<"-----------------------------823378840143542612896544303\r\nContent-Disposition: form-data; name=\"upload-test\"; filename=\"abcdef.txt\"\r\nContent-Type: text/plain\r\n\r\n01234567890123456789012345678901234567890123456789\r\n-----------------------------823378840143542612896544303--\r\n">>, Boundary = "---------------------------823378840143542612896544303", ?assertEqual( [{"upload-test", {[{<<"name">>,<<"upload-test">>}, {<<"filename">>,<<"abcdef.txt">>}], [{<<"Content-Type">>,<<"text/plain">>}]}, <<"01234567890123456789012345678901234567890123456789">>}], get_all_parts(Body,Boundary)). chrome_test() -> Body = <<"------WebKitFormBoundaryIHB9Xyi7ZCNKJusP\r\nContent-Disposition: form-data; name=\"upload-test\"; filename=\"abcdef.txt\"\r\nContent-Type: text/plain\r\n\r\n01234567890123456789012345678901234567890123456789\r\n------WebKitFormBoundaryIHB9Xyi7ZCNKJusP--\r\n">>, Boundary = "----WebKitFormBoundaryIHB9Xyi7ZCNKJusP", ?assertEqual( [{"upload-test", {[{<<"name">>,<<"upload-test">>}, {<<"filename">>,<<"abcdef.txt">>}], [{<<"Content-Type">>,<<"text/plain">>}]}, <<"01234567890123456789012345678901234567890123456789">>}], get_all_parts(Body,Boundary)). -endif. rabbitmq-server-3.2.4/plugins-src/webmachine-wrapper/webmachine-git/src/webmachine_resource.erl0000644000000000000000000002062412305126066031545 0ustar rootroot%% @author Justin Sheehy %% @author Andy Gross %% @copyright 2007-2012 Basho Technologies %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. %% You may obtain a copy of the License at %% %% http://www.apache.org/licenses/LICENSE-2.0 %% %% Unless required by applicable law or agreed to in writing, software %% distributed under the License is distributed on an "AS IS" BASIS, %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %% See the License for the specific language governing permissions and %% limitations under the License. -module(webmachine_resource). -author('Justin Sheehy '). -author('Andy Gross '). -export([new/4, wrap/2, wrap/3]). -export([do/3,log_d/2,stop/1]). -include("wm_resource.hrl"). -include("wm_reqdata.hrl"). -include("wm_reqstate.hrl"). new(R_Mod, R_ModState, R_ModExports, R_Trace) -> {?MODULE, R_Mod, R_ModState, R_ModExports, R_Trace}. default(ping) -> no_default; default(service_available) -> true; default(resource_exists) -> true; default(auth_required) -> true; default(is_authorized) -> true; default(forbidden) -> false; default(allow_missing_post) -> false; default(malformed_request) -> false; default(uri_too_long) -> false; default(known_content_type) -> true; default(valid_content_headers) -> true; default(valid_entity_length) -> true; default(options) -> []; default(allowed_methods) -> ['GET', 'HEAD']; default(known_methods) -> ['GET', 'HEAD', 'POST', 'PUT', 'DELETE', 'TRACE', 'CONNECT', 'OPTIONS']; default(content_types_provided) -> [{"text/html", to_html}]; default(content_types_accepted) -> []; default(delete_resource) -> false; default(delete_completed) -> true; default(post_is_create) -> false; default(create_path) -> undefined; default(base_uri) -> undefined; default(process_post) -> false; default(language_available) -> true; default(charsets_provided) -> no_charset; % this atom causes charset-negotation to short-circuit % the default setting is needed for non-charset responses such as image/png % an example of how one might do actual negotiation % [{"iso-8859-1", fun(X) -> X end}, {"utf-8", make_utf8}]; default(encodings_provided) -> [{"identity", fun(X) -> X end}]; % this is handy for auto-gzip of GET-only resources: % [{"identity", fun(X) -> X end}, {"gzip", fun(X) -> zlib:gzip(X) end}]; default(variances) -> []; default(is_conflict) -> false; default(multiple_choices) -> false; default(previously_existed) -> false; default(moved_permanently) -> false; default(moved_temporarily) -> false; default(last_modified) -> undefined; default(expires) -> undefined; default(generate_etag) -> undefined; default(finish_request) -> true; default(validate_content_checksum) -> not_validated; default(_) -> no_default. wrap(Mod, Args, {?MODULE, _, _, _, _}) -> wrap(Mod, Args). wrap(Mod, Args) -> case Mod:init(Args) of {ok, ModState} -> {ok, webmachine_resource:new(Mod, ModState, orddict:from_list(Mod:module_info(exports)), false)}; {{trace, Dir}, ModState} -> {ok, File} = open_log_file(Dir, Mod), log_decision(File, v3b14), log_call(File, attempt, Mod, init, Args), log_call(File, result, Mod, init, {{trace, Dir}, ModState}), {ok, webmachine_resource:new(Mod, ModState, orddict:from_list(Mod:module_info(exports)), File)}; _ -> {stop, bad_init_arg} end. do(#wm_resource{}=Res, Fun, ReqProps) -> #wm_resource{module=R_Mod, modstate=R_ModState, modexports=R_ModExports, trace=R_Trace} = Res, do(Fun, ReqProps, {?MODULE, R_Mod, R_ModState, R_ModExports, R_Trace}); do(Fun, ReqProps, {?MODULE, R_Mod, _, R_ModExports, R_Trace}=Req) when is_atom(Fun) andalso is_list(ReqProps) -> case lists:keyfind(reqstate, 1, ReqProps) of false -> RState0 = undefined; {reqstate, RState0} -> ok end, put(tmp_reqstate, empty), {Reply, ReqData, NewModState} = handle_wm_call(Fun, (RState0#wm_reqstate.reqdata)#wm_reqdata{wm_state=RState0}, Req), ReqState = case get(tmp_reqstate) of empty -> RState0; X -> X end, %% Do not need the embedded state anymore TrimData = ReqData#wm_reqdata{wm_state=undefined}, {Reply, webmachine_resource:new(R_Mod, NewModState, R_ModExports, R_Trace), ReqState#wm_reqstate{reqdata=TrimData}}. handle_wm_call(Fun, ReqData, {?MODULE,R_Mod,R_ModState,R_ModExports,R_Trace}=Req) -> case default(Fun) of no_default -> resource_call(Fun, ReqData, Req); Default -> case orddict:is_key(Fun, R_ModExports) of true -> resource_call(Fun, ReqData, Req); false -> if is_pid(R_Trace) -> log_call(R_Trace, not_exported, R_Mod, Fun, [ReqData, R_ModState]); true -> ok end, {Default, ReqData, R_ModState} end end. trim_trace([{M,F,[RD = #wm_reqdata{},S]}|STRest]) -> TrimState = (RD#wm_reqdata.wm_state)#wm_reqstate{reqdata='REQDATA'}, TrimRD = RD#wm_reqdata{wm_state=TrimState}, [{M,F,[TrimRD,S]}|STRest]; trim_trace(X) -> X. resource_call(F, ReqData, {?MODULE, R_Mod, R_ModState, _, R_Trace}) -> case R_Trace of false -> nop; _ -> log_call(R_Trace, attempt, R_Mod, F, [ReqData, R_ModState]) end, Result = try apply(R_Mod, F, [ReqData, R_ModState]) catch C:R -> Reason = {C, R, trim_trace(erlang:get_stacktrace())}, {{error, Reason}, ReqData, R_ModState} end, case R_Trace of false -> nop; _ -> log_call(R_Trace, result, R_Mod, F, Result) end, Result. log_d(#wm_resource{}=Res, DecisionID) -> #wm_resource{module=R_Mod, modstate=R_ModState, modexports=R_ModExports, trace=R_Trace} = Res, log_d(DecisionID, {?MODULE, R_Mod, R_ModState, R_ModExports, R_Trace}); log_d(DecisionID, {?MODULE, _, _, _, R_Trace}) -> case R_Trace of false -> nop; _ -> log_decision(R_Trace, DecisionID) end. stop(#wm_resource{trace=R_Trace}) -> close_log_file(R_Trace); stop({?MODULE, _, _, _, R_Trace}) -> close_log_file(R_Trace). log_call(File, Type, M, F, Data) -> io:format(File, "{~p, ~p, ~p,~n ~p}.~n", [Type, M, F, escape_trace_data(Data)]). escape_trace_data(Fun) when is_function(Fun) -> {'WMTRACE_ESCAPED_FUN', [erlang:fun_info(Fun, module), erlang:fun_info(Fun, name), erlang:fun_info(Fun, arity), erlang:fun_info(Fun, type)]}; escape_trace_data(Pid) when is_pid(Pid) -> {'WMTRACE_ESCAPED_PID', pid_to_list(Pid)}; escape_trace_data(Port) when is_port(Port) -> {'WMTRACE_ESCAPED_PORT', erlang:port_to_list(Port)}; escape_trace_data(List) when is_list(List) -> escape_trace_list(List, []); escape_trace_data(R=#wm_reqstate{}) -> list_to_tuple( escape_trace_data( tuple_to_list(R#wm_reqstate{reqdata='WMTRACE_NESTED_REQDATA'}))); escape_trace_data(Tuple) when is_tuple(Tuple) -> list_to_tuple(escape_trace_data(tuple_to_list(Tuple))); escape_trace_data(Other) -> Other. escape_trace_list([Head|Tail], Acc) -> escape_trace_list(Tail, [escape_trace_data(Head)|Acc]); escape_trace_list([], Acc) -> %% proper, nil-terminated list lists:reverse(Acc); escape_trace_list(Final, Acc) -> %% non-nil-terminated list, like the dict module uses lists:reverse(tl(Acc))++[hd(Acc)|escape_trace_data(Final)]. log_decision(File, DecisionID) -> io:format(File, "{decision, ~p}.~n", [DecisionID]). open_log_file(Dir, Mod) -> Now = {_,_,US} = now(), {{Y,M,D},{H,I,S}} = calendar:now_to_universal_time(Now), Filename = io_lib:format( "~s/~p-~4..0B-~2..0B-~2..0B" "-~2..0B-~2..0B-~2..0B.~6..0B.wmtrace", [Dir, Mod, Y, M, D, H, I, S, US]), file:open(Filename, [write]). close_log_file(File) when is_pid(File) -> file:close(File); close_log_file(_) -> ok. rabbitmq-server-3.2.4/plugins-src/webmachine-wrapper/webmachine-git/src/webmachine.erl0000644000000000000000000000566512305126066027646 0ustar rootroot%% @author Justin Sheehy %% @author Andy Gross %% @copyright 2007-2009 Basho Technologies %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. %% You may obtain a copy of the License at %% %% http://www.apache.org/licenses/LICENSE-2.0 %% %% Unless required by applicable law or agreed to in writing, software %% distributed under the License is distributed on an "AS IS" BASIS, %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %% See the License for the specific language governing permissions and %% limitations under the License. -module(webmachine). -author('Justin Sheehy '). -author('Andy Gross '). -export([start/0, stop/0]). -export([new_request/2]). -include("webmachine_logger.hrl"). -include("wm_reqstate.hrl"). -include("wm_reqdata.hrl"). %% @spec start() -> ok %% @doc Start the webmachine server. start() -> webmachine_deps:ensure(), application:start(webmachine). %% @spec stop() -> ok %% @doc Stop the webmachine server. stop() -> application:stop(webmachine). new_request(mochiweb, Request) -> Method = Request:get(method), Scheme = Request:get(scheme), Version = Request:get(version), {Headers, RawPath} = case application:get_env(webmachine, rewrite_module) of {ok, RewriteMod} -> do_rewrite(RewriteMod, Method, Scheme, Version, Request:get(headers), Request:get(raw_path)); undefined -> {Request:get(headers), Request:get(raw_path)} end, Socket = Request:get(socket), InitState = #wm_reqstate{socket=Socket, reqdata=wrq:create(Method,Scheme,Version,RawPath,Headers)}, InitReq = {webmachine_request,InitState}, {Peer, ReqState} = InitReq:get_peer(), PeerState = ReqState#wm_reqstate{reqdata=wrq:set_peer(Peer, ReqState#wm_reqstate.reqdata)}, LogData = #wm_log_data{start_time=now(), method=Method, headers=Headers, peer=PeerState#wm_reqstate.peer, path=RawPath, version=Version, response_code=404, response_length=0}, webmachine_request:new(PeerState#wm_reqstate{log_data=LogData}). do_rewrite(RewriteMod, Method, Scheme, Version, Headers, RawPath) -> case RewriteMod:rewrite(Method, Scheme, Version, Headers, RawPath) of %% only raw path has been rewritten (older style rewriting) NewPath when is_list(NewPath) -> {Headers, NewPath}; %% headers and raw path rewritten (new style rewriting) {NewHeaders, NewPath} -> {NewHeaders,NewPath} end. rabbitmq-server-3.2.4/plugins-src/webmachine-wrapper/webmachine-git/src/wmtrace_resource.erl0000755000000000000000000003120212305126066031102 0ustar rootroot%% @author Bryan Fink %% @doc Webmachine trace file interpretter. -module(wmtrace_resource). -export([add_dispatch_rule/2, remove_dispatch_rules/0]). -export([ping/2, init/1, resource_exists/2, content_types_provided/2, produce_html/2, produce_javascript/2, produce_map/2, produce_css/2]). -include("wm_reqdata.hrl"). -record(ctx, {trace_dir, trace}). -define(MAP_EXTERNAL, "static/map.png"). -define(MAP_INTERNAL, "http-headers-status-v3.png"). -define(SCRIPT_EXTERNAL, "static/wmtrace.js"). -define(SCRIPT_INTERNAL, "wmtrace.js"). -define(STYLE_EXTERNAL, "static/wmtrace.css"). -define(STYLE_INTERNAL, "wmtrace.css"). %% %% Dispatch Modifiers %% %% @spec add_dispatch_rule(string(), string()) -> ok %% @doc Add a dispatch rule to point at wmtrace_resource. %% Example: to serve wmtrace_resource from %% http://yourhost/dev/wmtrace/ %% with trace files on disk at %% priv/traces %% call: %% add_dispatch_rule("dev/wmtrace", "priv/traces") add_dispatch_rule(BasePath, TracePath) when is_list(BasePath), is_list(TracePath) -> Parts = string:tokens(BasePath, "/"), webmachine_router:add_route({Parts ++ ['*'], ?MODULE, [{trace_dir, TracePath}]}). %% @spec remove_dispatch_rules() -> ok %% @doc Remove all dispatch rules pointing to wmtrace_resource. remove_dispatch_rules() -> webmachine_router:remove_resource(?MODULE). %% %% Resource %% ping(ReqData, State) -> {pong, ReqData, State}. init(Config) -> {trace_dir, TraceDir} = proplists:lookup(trace_dir, Config), {trace_dir_exists, true} = {trace_dir_exists, filelib:is_dir(TraceDir)}, {ok, #ctx{trace_dir=TraceDir}}. resource_exists(RD, Ctx) -> case wrq:disp_path(RD) of [] -> case lists:reverse(wrq:raw_path(RD)) of [$/|_] -> {true, RD, Ctx}; _ -> {{halt, 303}, wrq:set_resp_header("Location", wrq:raw_path(RD)++"/", RD), Ctx} end; ?MAP_EXTERNAL -> {filelib:is_file(wm_path(?MAP_INTERNAL)), RD, Ctx}; ?SCRIPT_EXTERNAL -> {filelib:is_file(wm_path(?SCRIPT_INTERNAL)), RD, Ctx}; ?STYLE_EXTERNAL -> {filelib:is_file(wm_path(?STYLE_INTERNAL)), RD, Ctx}; TraceName -> TracePath = filename:join([Ctx#ctx.trace_dir, TraceName]), {filelib:is_file(TracePath), RD, Ctx#ctx{trace=TracePath}} end. wm_path(File) -> filename:join([code:priv_dir(webmachine), "trace", File]). content_types_provided(RD, Ctx) -> case wrq:disp_path(RD) of ?MAP_EXTERNAL -> {[{"image/png", produce_map}], RD, Ctx}; ?SCRIPT_EXTERNAL -> {[{"text/javascript", produce_javascript}], RD, Ctx}; ?STYLE_EXTERNAL -> {[{"text/css", produce_css}], RD, Ctx}; _ -> {[{"text/html", produce_html}], RD, Ctx} end. produce_html(RD, Ctx=#ctx{trace=undefined}) -> Dir = filename:absname(Ctx#ctx.trace_dir), Files = lists:reverse( lists:sort( filelib:fold_files(Dir, ".*\.wmtrace", false, fun(F, Acc) -> [filename:basename(F)|Acc] end, []))), {trace_list_html(Dir, Files), RD, Ctx}; produce_html(RD, Ctx) -> Filename = filename:absname(Ctx#ctx.trace), {ok, Data} = file:consult(Filename), {trace_html(Filename, Data), RD, Ctx}. trace_list_html(Dir, Files) -> html([], [head([], title([], ["Webmachine Trace List for ",Dir])), body([], [h1([], ["Traces in ",Dir]), ul([], [ li([], a([{"href", F}], F)) || F <- Files ]) ]) ]). trace_html(Filename, Data) -> {Request, Response, Trace} = encode_trace(Data), html([], [head([], [title([],["Webmachine Trace ",Filename]), linkblock([{"rel", "stylesheet"}, {"type", "text/css"}, {"href", "static/wmtrace.css"}], []), script([{"type", "text/javascript"}, {"src", "static/wmtrace.js"}], []), script([{"type", "text/javascript"}], mochiweb_html:escape( lists:flatten( ["var request=",Request,";\n" "var response=",Response,";\n" "var trace=",Trace,";"]))) ]), body([], [divblock([{"id", "zoompanel"}], [button([{"id", "zoomout"}], ["zoom out"]), button([{"id", "zoomin"}], ["zoom in"]) ]), canvas([{"id", "v3map"}, {"width", "3138"}, {"height", "2184"}], []), divblock([{"id", "sizetest"}], []), divblock([{"id", "preview"}], [divblock([{"id", "previewid"}],[]), ul([{"id", "previewcalls"}], []) ]), divblock([{"id", "infopanel"}], [divblock([{"id", "infocontrols"}], [divblock([{"id", "requesttab"}, {"class", "selectedtab"}],"Q"), divblock([{"id", "responsetab"}], "R"), divblock([{"id", "decisiontab"}], "D") ]), divblock([{"id", "requestdetail"}], [divblock([], [span([{"id", "requestmethod"}], []), " ", span([{"id", "requestpath"}], [])]), ul([{"id", "requestheaders"}], []), divblock([{"id", "requestbody"}], []) ]), divblock([{"id", "responsedetail"}], [divblock([{"id", "responsecode"}], []), ul([{"id", "responseheaders"}], []), divblock([{"id", "responsebody"}], []) ]), divblock([{"id", "decisiondetail"}], [divblock([], ["Decision: ", select([{"id", "decisionid"}], []) ]), divblock([], ["Calls:", select([{"id", "decisioncalls"}], []) ]), divblock([], "Input:"), pre([{"id", "callinput"}], []), divblock([], "Output:"), pre([{"id", "calloutput"}], []) ]) ]) ]) ]). produce_javascript(RD, Ctx) -> {ok, Script} = file:read_file(wm_path(?SCRIPT_INTERNAL)), {Script, RD, Ctx}. produce_map(RD, Ctx) -> {ok, Map} = file:read_file(wm_path(?MAP_INTERNAL)), {Map, RD, Ctx}. produce_css(RD, Ctx) -> {ok, Script} = file:read_file(wm_path(?STYLE_INTERNAL)), {Script, RD, Ctx}. %% %% Trace Encoding %% encode_trace(Data) -> {Request, Response, Trace} = aggregate_trace(Data), {mochijson:encode(encode_request(Request)), mochijson:encode(encode_response(Response)), mochijson:encode({array, [ encode_trace_part(P) || P <- Trace ]})}. aggregate_trace(RawTrace) -> {Request, Response, Trace} = lists:foldl(fun aggregate_trace_part/2, {undefined, 500, []}, RawTrace), {Request, Response, lists:reverse(Trace)}. aggregate_trace_part({decision, Decision}, {Q, R, Acc}) -> BDN = base_decision_name(Decision), case Acc of [{BDN,_}|_] -> {Q, R, Acc}; %% subdecision (ex. v3b13b) _ -> {Q, R, [{base_decision_name(Decision), []}|Acc]} end; aggregate_trace_part({attempt, Module, Function, Args}, {Q, R, [{Decision,Calls}|Acc]}) -> {maybe_extract_request(Function, Args, Q), R, [{Decision,[{Module, Function, Args, wmtrace_null}|Calls]}|Acc]}; aggregate_trace_part({result, Module, Function, Result}, {Q, R, [{Decision,[{Module,Function,Args,_}|Calls]}|Acc]}) -> {Q, maybe_extract_response(Function, Result, R), [{Decision,[{Module, Function, Args, Result}|Calls]}|Acc]}; aggregate_trace_part({not_exported, Module, Function, Args}, {Q, R, [{Decision,Calls}|Acc]}) -> {Q, maybe_extract_response(Function, Args, R), [{Decision,[{Module, Function, Args, wmtrace_not_exported}|Calls]} |Acc]}. maybe_extract_request(ping, [ReqData,_], _) -> ReqData; maybe_extract_request(_, _, R) -> R. maybe_extract_response(finish_request, [ReqData,_], _) -> ReqData; maybe_extract_response(finish_request, {_, ReqData, _}, _) -> ReqData; maybe_extract_response(_, _, R) -> R. base_decision_name(Decision) -> [$v,$3|D] = atom_to_list(Decision), %% strip 'v3' case lists:reverse(D) of [A|RD] when A >= $a, A =< $z -> lists:reverse(RD); %% strip 'b' off end of some _ -> D end. encode_request(ReqData) when is_record(ReqData, wm_reqdata) -> {struct, [{"method", atom_to_list( wrq:method(ReqData))}, {"path", wrq:raw_path(ReqData)}, {"headers", encode_headers(wrq:req_headers(ReqData))}, {"body", case ReqData#wm_reqdata.req_body of undefined -> []; Body when is_atom(Body) -> atom_to_list(Body); Body -> lists:flatten(io_lib:format("~s", [Body])) end}]}. encode_response(ReqData) -> {struct, [{"code", integer_to_list( wrq:response_code(ReqData))}, {"headers", encode_headers(wrq:resp_headers(ReqData))}, {"body", lists:flatten(io_lib:format("~s", [wrq:resp_body(ReqData)]))}]}. encode_headers(Headers) when is_list(Headers) -> {struct, [ {N, V} || {N, V} <- Headers ]}; encode_headers(Headers) -> encode_headers(mochiweb_headers:to_list(Headers)). encode_trace_part({Decision, Calls}) -> {struct, [{"d", Decision}, {"calls", {array, [ {struct, [{"module", Module}, {"function", Function}, {"input", encode_trace_io(Input)}, {"output", encode_trace_io(Output)}]} || {Module, Function, Input, Output} <- lists:reverse(Calls) ]}}]}. encode_trace_io(wmtrace_null) -> null; encode_trace_io(wmtrace_not_exported) -> "wmtrace_not_exported"; encode_trace_io(Data) -> lists:flatten(io_lib:format("~p", [Data])). %% %% HTML Building %% -define(TAG(T), T(Attrs, Content) -> tag(??T, Attrs, Content)). ?TAG(head). ?TAG(script). ?TAG(title). ?TAG(body). ?TAG(h1). ?TAG(ul). ?TAG(li). ?TAG(a). ?TAG(canvas). ?TAG(select). ?TAG(pre). ?TAG(span). ?TAG(button). html(_Attrs, Content) -> [<<"">>, <<"">>, Content, <<"">>]. divblock(Attrs, Content) -> tag("div", Attrs, Content). %% div is a reserved word linkblock(Attrs, Content) -> tag("link", Attrs, Content). %% link is a reserved word tag(Name, Attrs, Content) -> ["<",Name, [ [" ",K,"=\"",V,"\""] || {K, V} <- Attrs ], if Content == empty -> "/>"; true -> [">", Content, ""] end]. ././@LongLink0000000000000000000000000000014500000000000011565 Lustar rootrootrabbitmq-server-3.2.4/plugins-src/webmachine-wrapper/webmachine-git/src/webmachine_error_handler.erlrabbitmq-server-3.2.4/plugins-src/webmachine-wrapper/webmachine-git/src/webmachine_error_handler.erl0000644000000000000000000001046412305126066032545 0ustar rootroot%% @author Justin Sheehy %% @author Andy Gross %% @author Jeremy Latt %% @copyright 2007-2008 Basho Technologies %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. %% You may obtain a copy of the License at %% %% http://www.apache.org/licenses/LICENSE-2.0 %% %% Unless required by applicable law or agreed to in writing, software %% distributed under the License is distributed on an "AS IS" BASIS, %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %% See the License for the specific language governing permissions and %% limitations under the License. %% @doc Some fairly minimal error message formatters. -module(webmachine_error_handler). -author('Justin Sheehy '). -author('Andy Gross '). -author('Jeremy Latt '). -export([render_error/3]). render_error(Code, Req, Reason) -> case Req:has_response_body() of {true,_} -> maybe_log(Req, Reason), Req:response_body(); {false,_} -> render_error_body(Code, Req:trim_state(), Reason) end. render_error_body(404, Req, _Reason) -> {ok, ReqState} = Req:add_response_header("Content-Type", "text/html"), {<<"404 Not Found

    Not Found

    The requested document was not found on this server.


    mochiweb+webmachine web server
    ">>, ReqState}; render_error_body(500, Req, Reason) -> {ok, ReqState} = Req:add_response_header("Content-Type", "text/html"), maybe_log(Req, Reason), STString = io_lib:format("~p", [Reason]), ErrorStart = "500 Internal Server Error

    Internal Server Error

    The server encountered an error while processing this request:
    ",
        ErrorEnd = "


    mochiweb+webmachine web server
    ", ErrorIOList = [ErrorStart,STString,ErrorEnd], {erlang:iolist_to_binary(ErrorIOList), ReqState}; render_error_body(501, Req, _Reason) -> {ok, ReqState} = Req:add_response_header("Content-Type", "text/html"), {Method,_} = Req:method(), error_logger:error_msg("Webmachine does not support method ~p~n", [Method]), ErrorStr = io_lib:format("501 Not Implemented" "

    Not Implemented

    " "The server does not support the ~p method.
    " "


    mochiweb+webmachine web server" "
    ", [Method]), {erlang:iolist_to_binary(ErrorStr), ReqState}; render_error_body(503, Req, _Reason) -> {ok, ReqState} = Req:add_response_header("Content-Type", "text/html"), error_logger:error_msg("Webmachine cannot fulfill" " the request at this time"), ErrorStr = "503 Service Unavailable" "

    Service Unavailable

    " "The server is currently unable to handle " "the request due to a temporary overloading " "or maintenance of the server.
    " "


    mochiweb+webmachine web server" "
    ", {list_to_binary(ErrorStr), ReqState}; render_error_body(Code, Req, Reason) -> {ok, ReqState} = Req:add_response_header("Content-Type", "text/html"), ReasonPhrase = httpd_util:reason_phrase(Code), Body = ["", integer_to_list(Code), " ", ReasonPhrase, "

    ", ReasonPhrase, "

    ", Reason, "


    mochiweb+webmachine web server
    "], {iolist_to_binary(Body), ReqState}. maybe_log(_Req, {error, {exit, normal, _Stack}}) -> %% webmachine_request did an exit(normal), so suppress this %% message. This usually happens when a chunked upload is %% interrupted by network failure. ok; maybe_log(Req, Reason) -> {Path,_} = Req:path(), error_logger:error_msg("webmachine error: path=~p~n~p~n", [Path, Reason]). rabbitmq-server-3.2.4/plugins-src/webmachine-wrapper/webmachine-git/src/webmachine_sup.erl0000644000000000000000000000440412305126066030523 0ustar rootroot%% @author Justin Sheehy %% @author Andy Gross %% @copyright 2007-2008 Basho Technologies %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. %% You may obtain a copy of the License at %% %% http://www.apache.org/licenses/LICENSE-2.0 %% %% Unless required by applicable law or agreed to in writing, software %% distributed under the License is distributed on an "AS IS" BASIS, %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %% See the License for the specific language governing permissions and %% limitations under the License. %% @doc Supervisor for the webmachine application. -module(webmachine_sup). -behaviour(supervisor). %% External exports -export([start_link/0, upgrade/0]). %% supervisor callbacks -export([init/1]). -include("webmachine_logger.hrl"). %% @spec start_link() -> ServerRet %% @doc API for starting the supervisor. start_link() -> supervisor:start_link({local, ?MODULE}, ?MODULE, []). %% @spec upgrade() -> ok %% @doc Add processes if necessary. upgrade() -> {ok, {_, Specs}} = init([]), Old = sets:from_list( [Name || {Name, _, _, _} <- supervisor:which_children(?MODULE)]), New = sets:from_list([Name || {Name, _, _, _, _, _} <- Specs]), Kill = sets:subtract(Old, New), sets:fold(fun (Id, ok) -> supervisor:terminate_child(?MODULE, Id), supervisor:delete_child(?MODULE, Id), ok end, ok, Kill), [supervisor:start_child(?MODULE, Spec) || Spec <- Specs], ok. %% @spec init([]) -> SupervisorTree %% @doc supervisor callback. init([]) -> Router = {webmachine_router, {webmachine_router, start_link, []}, permanent, 5000, worker, [webmachine_router]}, LogHandler = [{webmachine_logger, {gen_event, start_link, [{local, ?EVENT_LOGGER}]}, permanent, 5000, worker, [dynamic]}, {webmachine_logger_watcher_sup, {webmachine_logger_watcher_sup, start_link, []}, permanent, 5000, supervisor, [webmachine_logger_watcher_sup]}], {ok, {{one_for_one, 9, 10}, LogHandler ++ [Router]}}. rabbitmq-server-3.2.4/plugins-src/webmachine-wrapper/webmachine-git/src/webmachine_deps.erl0000644000000000000000000000726512305126066030657 0ustar rootroot%% @author Justin Sheehy %% @author Andy Gross %% @copyright 2007-2008 Basho Technologies %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. %% You may obtain a copy of the License at %% %% http://www.apache.org/licenses/LICENSE-2.0 %% %% Unless required by applicable law or agreed to in writing, software %% distributed under the License is distributed on an "AS IS" BASIS, %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %% See the License for the specific language governing permissions and %% limitations under the License. %% @doc Ensure that the relatively-installed dependencies are on the code %% loading path, and locate resources relative %% to this application's path. -module(webmachine_deps). -author('Justin Sheehy '). -author('Andy Gross '). -export([ensure/0, ensure/1]). -export([get_base_dir/0, get_base_dir/1]). -export([local_path/1, local_path/2]). -export([deps_on_path/0, new_siblings/1]). %% @spec deps_on_path() -> [ProjNameAndVers] %% @doc List of project dependencies on the path. deps_on_path() -> ordsets:from_list([filename:basename(filename:dirname(X)) || X <- code:get_path()]). %% @spec new_siblings(Module) -> [Dir] %% @doc Find new siblings paths relative to Module that aren't already on the %% code path. new_siblings(Module) -> Existing = deps_on_path(), SiblingEbin = [ X || X <- filelib:wildcard(local_path(["deps", "*", "ebin"], Module)), filename:basename(filename:dirname(X)) /= %% don't include self filename:basename(filename:dirname( filename:dirname( filename:dirname(X)))) ], Siblings = [filename:dirname(X) || X <- SiblingEbin, ordsets:is_element( filename:basename(filename:dirname(X)), Existing) =:= false], lists:filter(fun filelib:is_dir/1, lists:append([[filename:join([X, "ebin"]), filename:join([X, "include"])] || X <- Siblings])). %% @spec ensure(Module) -> ok %% @doc Ensure that all ebin and include paths for dependencies %% of the application for Module are on the code path. ensure(Module) -> code:add_paths(new_siblings(Module)), ok. %% @spec ensure() -> ok %% @doc Ensure that the ebin and include paths for dependencies of %% this application are on the code path. Equivalent to %% ensure(?Module). ensure() -> ensure(?MODULE). %% @spec get_base_dir(Module) -> string() %% @doc Return the application directory for Module. It assumes Module is in %% a standard OTP layout application in the ebin or src directory. get_base_dir(Module) -> {file, Here} = code:is_loaded(Module), filename:dirname(filename:dirname(Here)). %% @spec get_base_dir() -> string() %% @doc Return the application directory for this application. Equivalent to %% get_base_dir(?MODULE). get_base_dir() -> get_base_dir(?MODULE). %% @spec local_path([string()], Module) -> string() %% @doc Return an application-relative directory from Module's application. local_path(Components, Module) -> filename:join([get_base_dir(Module) | Components]). %% @spec local_path(Components) -> string() %% @doc Return an application-relative directory for this application. %% Equivalent to local_path(Components, ?MODULE). local_path(Components) -> local_path(Components, ?MODULE). rabbitmq-server-3.2.4/plugins-src/webmachine-wrapper/webmachine-git/src/webmachine_util.erl0000644000000000000000000004603412305126066030676 0ustar rootroot%% @author Justin Sheehy %% @author Andy Gross %% @copyright 2007-2008 Basho Technologies %% (guess_mime/1 derived from code copyright 2007 Mochi Media, Inc.) %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. %% You may obtain a copy of the License at %% %% http://www.apache.org/licenses/LICENSE-2.0 %% %% Unless required by applicable law or agreed to in writing, software %% distributed under the License is distributed on an "AS IS" BASIS, %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %% See the License for the specific language governing permissions and %% limitations under the License. %% @doc Utilities for parsing, quoting, and negotiation. -module(webmachine_util). -export([guess_mime/1]). -export([convert_request_date/1, compare_ims_dates/2]). -export([rfc1123_date/1]). -export([choose_media_type/2, format_content_type/1]). -export([choose_charset/2]). -export([choose_encoding/2]). -export([now_diff_milliseconds/2]). -export([media_type_to_detail/1, quoted_string/1, split_quoted_strings/1]). -export([parse_range/2]). -ifdef(TEST). -ifdef(EQC). -include_lib("eqc/include/eqc.hrl"). -endif. -include_lib("eunit/include/eunit.hrl"). -export([accept_header_to_media_types/1]). -endif. convert_request_date(Date) -> try case httpd_util:convert_request_date(Date) of ReqDate -> ReqDate end catch error:_ -> bad_date end. %% returns true if D1 > D2 compare_ims_dates(D1, D2) -> GD1 = calendar:datetime_to_gregorian_seconds(D1), GD2 = calendar:datetime_to_gregorian_seconds(D2), GD1 > GD2. %% @doc Convert tuple style GMT datetime to RFC1123 style one rfc1123_date({{YYYY, MM, DD}, {Hour, Min, Sec}}) -> DayNumber = calendar:day_of_the_week({YYYY, MM, DD}), lists:flatten(io_lib:format("~s, ~2.2.0w ~3.s ~4.4.0w ~2.2.0w:~2.2.0w:~2.2.0w GMT", [httpd_util:day(DayNumber), DD, httpd_util:month(MM), YYYY, Hour, Min, Sec])). %% @spec guess_mime(string()) -> string() %% @doc Guess the mime type of a file by the extension of its filename. guess_mime(File) -> case filename:extension(File) of ".bz2" -> "application/x-bzip2"; ".css" -> "text/css"; ".eot" -> "application/vnd.ms-fontobject"; ".gif" -> "image/gif"; ".gz" -> "application/x-gzip"; ".htc" -> "text/x-component"; ".html" -> "text/html"; ".ico" -> "image/x-icon"; ".jpeg" -> "image/jpeg"; ".jpg" -> "image/jpeg"; ".js" -> "application/x-javascript"; ".less" -> "text/css"; ".m4v" -> "video/mp4"; ".manifest" -> "text/cache-manifest"; ".mp4" -> "video/mp4"; ".oga" -> "audio/ogg"; ".ogg" -> "audio/ogg"; ".ogv" -> "video/ogg"; ".otf" -> "font/opentyp"; ".png" -> "image/png"; ".svg" -> "image/svg+xml"; ".svgz" -> "image/svg+xml"; ".swf" -> "application/x-shockwave-flash"; ".tar" -> "application/x-tar"; ".tgz" -> "application/x-gzip"; ".ttc" -> "application/x-font-ttf"; ".ttf" -> "application/x-font-ttf"; ".vcf" -> "text/x-vcard"; ".webm" -> "video/web"; ".webp" -> "image/web"; ".woff" -> "application/x-font-woff"; ".xhtml" -> "application/xhtml+xml"; ".xml" -> "application/xml"; ".zip" -> "application/zip"; _ -> "text/plain" end. choose_media_type(Provided,AcceptHead) -> % Return the Content-Type we will serve for a request. % If there is no acceptable/available match, return the atom "none". % AcceptHead is the value of the request's Accept header % Provided is a list of media types the resource can provide. % each is either a string e.g. -- "text/html" % or a string and parameters e.g. -- {"text/html",[{level,1}]} % (the plain string case with no parameters is much more common) Requested = accept_header_to_media_types(AcceptHead), Prov1 = normalize_provided(Provided), choose_media_type1(Prov1,Requested). choose_media_type1(_Provided,[]) -> none; choose_media_type1(Provided,[H|T]) -> {_Pri,Type,Params} = H, case media_match({Type,Params}, Provided) of [] -> choose_media_type1(Provided,T); [{CT_T,CT_P}|_] -> format_content_type(CT_T,CT_P) end. media_match(_,[]) -> []; media_match({"*/*",[]},[H|_]) -> [H]; media_match({Type,Params},Provided) -> [{T1,P1} || {T1,P1} <- Provided, media_type_match(Type,T1), media_params_match(Params,P1)]. media_type_match(Req,Prov) -> case Req of "*" -> % might as well not break for lame (Gomez) clients true; "*/*" -> true; Prov -> true; _ -> [R1|R2] = string:tokens(Req,"/"), [P1,_P2] = string:tokens(Prov,"/"), case R2 of ["*"] -> case R1 of P1 -> true; _ -> false end; _ -> false end end. media_params_match(Req,Prov) -> lists:sort(Req) =:= lists:sort(Prov). prioritize_media(TyParam) -> {Type, Params} = TyParam, prioritize_media(Type,Params,[]). prioritize_media(Type,Params,Acc) -> case Params of [] -> {1, Type, Acc}; _ -> [{Tok,Val}|Rest] = Params, case Tok of "q" -> QVal = case Val of "1" -> 1; "0" -> 0; [$.|_] -> %% handle strange FeedBurner Accept list_to_float([$0|Val]); _ -> list_to_float(Val) end, {QVal, Type, Rest ++ Acc}; _ -> prioritize_media(Type,Rest,[{Tok,Val}|Acc]) end end. media_type_to_detail(MType) -> mochiweb_util:parse_header(MType). accept_header_to_media_types(HeadVal) -> % given the value of an accept header, produce an ordered list % based on the q-values. Results are [{Type,Params}] with the % head of the list being the highest-priority requested type. try lists:reverse(lists:keysort(1, [prioritize_media(media_type_to_detail(MType)) || MType <- [string:strip(X) || X <- string:tokens(HeadVal, ",")]])) catch _:_ -> [] end. normalize_provided(Provided) -> [normalize_provided1(X) || X <- Provided]. normalize_provided1(Type) when is_list(Type) -> {Type, []}; normalize_provided1({Type,Params}) -> {Type, normalize_media_params(Params)}. normalize_media_params(Params) -> normalize_media_params(Params,[]). normalize_media_params([],Acc) -> Acc; normalize_media_params([{K,V}|T], Acc) when is_atom(K) -> normalize_media_params(T,[{atom_to_list(K),V}|Acc]); normalize_media_params([H|T], Acc) -> normalize_media_params(T, [H|Acc]). format_content_type(Type) when is_list(Type) -> Type; format_content_type({Type,Params}) -> format_content_type(Type,Params). format_content_type(Type,[]) -> Type; format_content_type(Type,[{K,V}|T]) when is_atom(K) -> format_content_type(Type, [{atom_to_list(K),V}|T]); format_content_type(Type,[{K,V}|T]) -> format_content_type(Type ++ "; " ++ K ++ "=" ++ V, T). choose_charset(CSets, AccCharHdr) -> do_choose(CSets, AccCharHdr, "ISO-8859-1"). choose_encoding(Encs, AccEncHdr) -> do_choose(Encs, AccEncHdr, "identity"). do_choose(Choices, Header, Default) -> Accepted = build_conneg_list(string:tokens(Header, ",")), DefaultPrio = [P || {P,C} <- Accepted, C =:= Default], StarPrio = [P || {P,C} <- Accepted, C =:= "*"], DefaultOkay = case DefaultPrio of [] -> case StarPrio of [0.0] -> no; _ -> yes end; [0.0] -> no; _ -> yes end, AnyOkay = case StarPrio of [] -> no; [0.0] -> no; _ -> yes end, do_choose(Default, DefaultOkay, AnyOkay, Choices, Accepted). do_choose(_Default, _DefaultOkay, _AnyOkay, [], []) -> none; do_choose(_Default, _DefaultOkay, _AnyOkay, [], _Accepted) -> none; do_choose(Default, DefaultOkay, AnyOkay, Choices, []) -> case AnyOkay of yes -> hd(Choices); no -> case DefaultOkay of yes -> case lists:member(Default, Choices) of true -> Default; _ -> none end; no -> none end end; do_choose(Default, DefaultOkay, AnyOkay, Choices, [AccPair|AccRest]) -> {Prio, Acc} = AccPair, case Prio of 0.0 -> do_choose(Default, DefaultOkay, AnyOkay, lists:delete(Acc, Choices), AccRest); _ -> LAcc = string:to_lower(Acc), LChoices = [string:to_lower(X) || X <- Choices], % doing this a little more work than needed in % order to be easily insensitive but preserving case lists:member(LAcc, LChoices) of true -> hd([X || X <- Choices, string:to_lower(X) =:= LAcc]); false -> do_choose(Default, DefaultOkay, AnyOkay, Choices, AccRest) end end. build_conneg_list(AccList) -> build_conneg_list(AccList, []). build_conneg_list([], Result) -> lists:reverse(lists:sort(Result)); build_conneg_list([Acc|AccRest], Result) -> XPair = list_to_tuple([string:strip(X) || X <- string:tokens(Acc, ";")]), Pair = case XPair of {Choice, "q=" ++ PrioStr} -> case PrioStr of "0" -> {0.0, Choice}; "1" -> {1.0, Choice}; [$.|_] -> %% handle strange FeedBurner Accept {list_to_float([$0|PrioStr]), Choice}; _ -> {list_to_float(PrioStr), Choice} end; {Choice} -> {1.0, Choice} end, build_conneg_list(AccRest,[Pair|Result]). quoted_string([$" | _Rest] = Str) -> Str; quoted_string(Str) -> escape_quotes(Str, [$"]). % Initialize Acc with opening quote escape_quotes([], Acc) -> lists:reverse([$" | Acc]); % Append final quote escape_quotes([$\\, Char | Rest], Acc) -> escape_quotes(Rest, [Char, $\\ | Acc]); % Any quoted char should be skipped escape_quotes([$" | Rest], Acc) -> escape_quotes(Rest, [$", $\\ | Acc]); % Unquoted quotes should be escaped escape_quotes([Char | Rest], Acc) -> escape_quotes(Rest, [Char | Acc]). split_quoted_strings(Str) -> split_quoted_strings(Str, []). split_quoted_strings([], Acc) -> lists:reverse(Acc); split_quoted_strings([$" | Rest], Acc) -> {Str, Cont} = unescape_quoted_string(Rest, []), split_quoted_strings(Cont, [Str | Acc]); split_quoted_strings([_Skip | Rest], Acc) -> split_quoted_strings(Rest, Acc). unescape_quoted_string([], Acc) -> {lists:reverse(Acc), []}; unescape_quoted_string([$\\, Char | Rest], Acc) -> % Any quoted char should be unquoted unescape_quoted_string(Rest, [Char | Acc]); unescape_quoted_string([$" | Rest], Acc) -> % Quote indicates end of this string {lists:reverse(Acc), Rest}; unescape_quoted_string([Char | Rest], Acc) -> unescape_quoted_string(Rest, [Char | Acc]). %% @type now() = {MegaSecs, Secs, MicroSecs} %% This is faster than timer:now_diff() because it does not use bignums. %% But it returns *milliseconds* (timer:now_diff returns microseconds.) %% From http://www.erlang.org/ml-archive/erlang-questions/200205/msg00027.html %% @doc Compute the difference between two now() tuples, in milliseconds. %% @spec now_diff_milliseconds(now(), now()) -> integer() now_diff_milliseconds(undefined, undefined) -> 0; now_diff_milliseconds(undefined, T2) -> now_diff_milliseconds(os:timestamp(), T2); now_diff_milliseconds({M,S,U}, {M,S1,U1}) -> ((S-S1) * 1000) + ((U-U1) div 1000); now_diff_milliseconds({M,S,U}, {M1,S1,U1}) -> ((M-M1)*1000000+(S-S1))*1000 + ((U-U1) div 1000). -spec parse_range(RawRange::string(), ResourceLength::non_neg_integer()) -> [{Start::non_neg_integer(), End::non_neg_integer()}]. parse_range(RawRange, ResourceLength) when is_list(RawRange) -> parse_range(mochiweb_http:parse_range_request(RawRange), ResourceLength, []). parse_range([], _ResourceLength, Acc) -> lists:reverse(Acc); parse_range([Spec | Rest], ResourceLength, Acc) -> case mochiweb_http:range_skip_length(Spec, ResourceLength) of invalid_range -> parse_range(Rest, ResourceLength, Acc); {Skip, Length} -> parse_range(Rest, ResourceLength, [{Skip, Skip + Length - 1} | Acc]) end. %% %% TEST %% -ifdef(TEST). choose_media_type_test() -> Provided = "text/html", ShouldMatch = ["*", "*/*", "text/*", "text/html"], WantNone = ["foo", "text/xml", "application/*", "foo/bar/baz"], [ ?assertEqual(Provided, choose_media_type([Provided], I)) || I <- ShouldMatch ], [ ?assertEqual(none, choose_media_type([Provided], I)) || I <- WantNone ]. choose_media_type_qval_test() -> Provided = ["text/html", "image/jpeg"], HtmlMatch = ["image/jpeg;q=0.5, text/html", "text/html, image/jpeg; q=0.5", "text/*; q=0.8, image/*;q=0.7", "text/*;q=.8, image/*;q=.7"], %% strange FeedBurner format JpgMatch = ["image/*;q=1, text/html;q=0.9", "image/png, image/*;q=0.3"], [ ?assertEqual("text/html", choose_media_type(Provided, I)) || I <- HtmlMatch ], [ ?assertEqual("image/jpeg", choose_media_type(Provided, I)) || I <- JpgMatch ]. accept_header_to_media_types_test() -> Header1 = "text/html,application/xhtml+xml,application/xml,application/x-javascript,*/*;q=0.5", Header2 = "audio/*; q=0, audio/basic", OddHeader = "text/html,application/xhtml+xml,application/xml,application/x-javascript,*/*;q=0,5", Result1 = accept_header_to_media_types(Header1), Result2 = accept_header_to_media_types(Header2), Result3 = accept_header_to_media_types(OddHeader), ExpResult1 = [{1,"application/x-javascript", []}, {1,"application/xml",[]}, {1,"application/xhtml+xml",[]}, {1,"text/html",[]}, {0.5,"*/*",[]}], ExpResult2 = [{1,"audio/basic",[]},{0,"audio/*",[]}], ExpResult3 = [{1, "5", []}, {1,"application/x-javascript", []}, {1,"application/xml",[]}, {1,"application/xhtml+xml",[]}, {1,"text/html",[]}, {0,"*/*",[]}], ?assertEqual(ExpResult1, Result1), ?assertEqual(ExpResult2, Result2), ?assertEqual(ExpResult3, Result3). media_type_extra_whitespace_test() -> MType = "application/x-www-form-urlencoded ; charset = utf8", ?assertEqual({"application/x-www-form-urlencoded",[{"charset","utf8"}]}, webmachine_util:media_type_to_detail(MType)). format_content_type_test() -> Types = ["audio/vnd.wave; codec=31", "text/x-okie; charset=iso-8859-1; declaration="], [?assertEqual(Type, format_content_type( webmachine_util:media_type_to_detail(Type))) || Type <- Types], ?assertEqual(hd(Types), format_content_type("audio/vnd.wave", [{codec, "31"}])). convert_request_date_test() -> ?assertMatch({{_,_,_},{_,_,_}}, convert_request_date("Wed, 30 Dec 2009 14:39:02 GMT")), ?assertMatch(bad_date, convert_request_date(<<"does not handle binaries">>)). compare_ims_dates_test() -> Late = {{2009,12,30},{14,39,02}}, Early = {{2009,12,30},{13,39,02}}, ?assertEqual(true, compare_ims_dates(Late, Early)), ?assertEqual(false, compare_ims_dates(Early, Late)). rfc1123_date_test() -> ?assertEqual("Thu, 11 Jul 2013 04:33:19 GMT", rfc1123_date({{2013, 7, 11}, {4, 33, 19}})). guess_mime_test() -> TextTypes = [".html",".css",".htc",".manifest",".txt"], AppTypes = [".xhtml",".xml",".js",".swf",".zip",".bz2", ".gz",".tar",".tgz"], ImgTypes = [".jpg",".jpeg",".gif",".png",".ico",".svg"], ?assertEqual([], [ T || T <- TextTypes, 1 /= string:str(guess_mime(T),"text/") ]), ?assertEqual([], [ T || T <- AppTypes, 1 /= string:str(guess_mime(T),"application/") ]), ?assertEqual([], [ T || T <- ImgTypes, 1 /= string:str(guess_mime(T),"image/") ]). now_diff_milliseconds_test() -> Late = {10, 10, 10}, Early1 = {10, 9, 9}, Early2 = {9, 9, 9}, ?assertEqual(1000, now_diff_milliseconds(Late, Early1)), ?assertEqual(1000001000, now_diff_milliseconds(Late, Early2)). -ifdef(EQC). -define(QC_OUT(P), eqc:on_output(fun(Str, Args) -> io:format(user, Str, Args) end, P)). prop_quoted_string() -> ?FORALL(String0, non_empty(list(oneof([char(), $", [$\\, char()]]))), begin String = lists:flatten(String0), Quoted = quoted_string(String), case String of [$" | _] -> ?assertEqual(String, Quoted), true; _ -> %% Properties: %% * strings must begin/end with quote %% * All other quotes should be escaped ?assertEqual($", hd(Quoted)), ?assertEqual($", lists:last(Quoted)), Partial = lists:reverse(tl(lists:reverse(tl(Quoted)))), case check_quote(Partial) of true -> true; false -> io:format(user, "----\n", []), io:format(user, "In: ~p\n", [[integer_to_list(C) || C <- String]]), io:format(user, "Out: ~p\n", [[integer_to_list(C) || C <- Quoted]]), false end end end). check_quote([]) -> true; check_quote([$\\, _Any | Rest]) -> check_quote(Rest); check_quote([$" | _Rest]) -> false; check_quote([_Any | Rest]) -> check_quote(Rest). prop_quoted_string_test() -> ?assert(eqc:quickcheck(?QC_OUT(prop_quoted_string()))). -endif. % EQC -endif. % TEST rabbitmq-server-3.2.4/plugins-src/webmachine-wrapper/webmachine-git/src/webmachine.app.src0000644000000000000000000000041512305126066030416 0ustar rootroot%%-*- mode: erlang -*- {application, webmachine, [ {description, "webmachine"}, {vsn, "1.10.3"}, {modules, []}, {registered, []}, {applications, [kernel, stdlib, mochiweb]}, {mod, {webmachine_app, []}}, {env, []} ]}. rabbitmq-server-3.2.4/plugins-src/webmachine-wrapper/webmachine-git/src/webmachine_mochiweb.erl0000644000000000000000000001477012305126066031520 0ustar rootroot%% @author Justin Sheehy %% @author Andy Gross %% @copyright 2007-2008 Basho Technologies %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. %% You may obtain a copy of the License at %% %% http://www.apache.org/licenses/LICENSE-2.0 %% %% Unless required by applicable law or agreed to in writing, software %% distributed under the License is distributed on an "AS IS" BASIS, %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %% See the License for the specific language governing permissions and %% limitations under the License. %% @doc Mochiweb interface for webmachine. -module(webmachine_mochiweb). -author('Justin Sheehy '). -author('Andy Gross '). -export([start/1, stop/0, loop/2]). %% The `log_dir' option is deprecated, but remove it from the %% options list if it is present -define(WM_OPTIONS, [error_handler, log_dir, rewrite_module, resource_module_option]). -define (WM_OPTION_DEFAULTS, [{error_handler, webmachine_error_handler}]). start(Options) -> {DispatchList, PName, DGroup, WMOptions, OtherOptions} = get_wm_options(Options), webmachine_router:init_routes(DGroup, DispatchList), [application_set_unless_env_or_undef(K, V) || {K, V} <- WMOptions], MochiName = list_to_atom(to_list(PName) ++ "_mochiweb"), LoopFun = fun(X) -> loop(DGroup, X) end, mochiweb_http:start([{name, MochiName}, {loop, LoopFun} | OtherOptions]). stop() -> {registered_name, PName} = process_info(self(), registered_name), MochiName = list_to_atom(atom_to_list(PName) ++ "_mochiweb"), mochiweb_http:stop(MochiName). loop(Name, MochiReq) -> Req = webmachine:new_request(mochiweb, MochiReq), DispatchList = webmachine_router:get_routes(Name), Host = case host_headers(Req) of [H|_] -> H; [] -> [] end, {Path, _} = Req:path(), {RD, _} = Req:get_reqdata(), %% Run the dispatch code, catch any errors... try webmachine_dispatcher:dispatch(Host, Path, DispatchList, RD) of {error, invalid_host} -> handle_error(400, "Invalid Host", Req); {no_dispatch_match, _UnmatchedHost, _UnmatchedPathTokens} -> handle_error(404, {none, none, []}, Req); {Mod, ModOpts, HostTokens, Port, PathTokens, Bindings, AppRoot, StringPath} -> BootstrapResource = webmachine_resource:new(x,x,x,x), {ok,RS1} = Req:load_dispatch_data(Bindings,HostTokens,Port, PathTokens,AppRoot,StringPath), XReq1 = {webmachine_request,RS1}, try {ok, Resource} = BootstrapResource:wrap(Mod, ModOpts), {ok,RS2} = XReq1:set_metadata('resource_module', resource_module(Mod, ModOpts)), webmachine_decision_core:handle_request(Resource, RS2) catch error:Error -> handle_error(500, {error, Error}, Req) end catch Type : Error -> handle_error(500, {Type, Error}, Req) end. handle_error(Code, Error, Req) -> {ok, ErrorHandler} = application:get_env(webmachine, error_handler), {ErrorHTML,ReqState1} = ErrorHandler:render_error(Code, Req, Error), Req1 = {webmachine_request,ReqState1}, {ok,ReqState2} = Req1:append_to_response_body(ErrorHTML), Req2 = {webmachine_request,ReqState2}, {ok,ReqState3} = Req2:send_response(Code), Req3 = {webmachine_request,ReqState3}, {LogData,_ReqState4} = Req3:log_data(), spawn(webmachine_log, log_access, [LogData]). get_wm_option(OptName, {WMOptions, OtherOptions}) -> {Value, UpdOtherOptions} = handle_get_option_result(get_option(OptName, OtherOptions), OptName), {[{OptName, Value} | WMOptions], UpdOtherOptions}. handle_get_option_result({undefined, Options}, Name) -> {proplists:get_value(Name, ?WM_OPTION_DEFAULTS), Options}; handle_get_option_result(GetOptRes, _) -> GetOptRes. get_wm_options(Options) -> {DispatchList, Options1} = get_option(dispatch, Options), {Name, Options2} = case get_option(name, Options1) of {undefined, Opts2} -> {webmachine, Opts2}; NRes -> NRes end, {DGroup, Options3} = case get_option(dispatch_group, Options2) of {undefined, Opts3} -> {default, Opts3}; RRes -> RRes end, {WMOptions, RestOptions} = lists:foldl(fun get_wm_option/2, {[], Options3}, ?WM_OPTIONS), {DispatchList, Name, DGroup, WMOptions, RestOptions}. get_option(Option, Options) -> case lists:keytake(Option, 1, Options) of false -> {undefined, Options}; {value, {Option, Value}, NewOptions} -> {Value, NewOptions} end. application_set_unless_env_or_undef(_Var, undefined) -> ok; application_set_unless_env_or_undef(Var, Value) -> application_set_unless_env(webmachine, Var, Value). application_set_unless_env(App, Var, Value) -> Current = application:get_all_env(App), CurrentKeys = proplists:get_keys(Current), case lists:member(Var, CurrentKeys) of true -> ok; false -> application:set_env(App, Var, Value) end. host_headers(Req) -> [ V || {V,_ReqState} <- [Req:get_header_value(H) || H <- ["x-forwarded-host", "x-forwarded-server", "host"]], V /= undefined]. get_app_env(Key) -> application:get_env(webmachine, Key). %% @private %% @doc This function is used for cases where it may be desirable to %% override the value that is set in the request metadata under the %% `resource_module' key. An example would be a pattern where a set of %% resource modules shares a lot of common functionality that is %% contained in a single module and is used as the resource in all %% dispatch rules and the `ModOpts' are used to specify a smaller %% set of callbacks for resource specialization. resource_module(Mod, ModOpts) -> resource_module(Mod, ModOpts, get_app_env(resource_module_option)). resource_module(Mod, _, undefined) -> Mod; resource_module(Mod, ModOpts, {ok, OptionVal}) -> proplists:get_value(OptionVal, ModOpts, Mod). to_list(L) when is_list(L) -> L; to_list(A) when is_atom(A) -> atom_to_list(A). ././@LongLink0000000000000000000000000000014600000000000011566 Lustar rootrootrabbitmq-server-3.2.4/plugins-src/webmachine-wrapper/webmachine-git/src/webmachine_logger_watcher.erlrabbitmq-server-3.2.4/plugins-src/webmachine-wrapper/webmachine-git/src/webmachine_logger_watcher.er0000644000000000000000000000477612305126066032550 0ustar rootroot%% Copyright (c) 2011-2012 Basho Technologies, Inc. All Rights Reserved. %% %% This file is provided to you under the Apache License, %% Version 2.0 (the "License"); you may not use this file %% except in compliance with the License. You may obtain %% a copy of the License at %% %% http://www.apache.org/licenses/LICENSE-2.0 %% %% Unless required by applicable law or agreed to in writing, %% software distributed under the License is distributed on an %% "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY %% KIND, either express or implied. See the License for the %% specific language governing permissions and limitations %% under the License. %% @doc A process that does a gen_event:add_sup_handler and attempts to re-add %% event handlers when they exit. %% @private -module(webmachine_logger_watcher). -behaviour(gen_server). -ifdef(TEST). -include_lib("eunit/include/eunit.hrl"). -endif. %% callbacks -export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]). -export([start_link/3, start/3]). -record(state, {module, config, event}). start_link(Event, Module, Config) -> gen_server:start_link(?MODULE, [Event, Module, Config], []). start(Event, Module, Config) -> gen_server:start(?MODULE, [Event, Module, Config], []). init([Event, Module, Config]) -> install_handler(Event, Module, Config), {ok, #state{event=Event, module=Module, config=Config}}. handle_call(_Call, _From, State) -> {reply, ok, State}. handle_cast(_Request, State) -> {noreply, State}. handle_info({gen_event_EXIT, Module, normal}, #state{module=Module} = State) -> {stop, normal, State}; handle_info({gen_event_EXIT, Module, shutdown}, #state{module=Module} = State) -> {stop, normal, State}; handle_info({gen_event_EXIT, Module, _Reason}, #state{module=Module, config=Config, event=Event} = State) -> install_handler(Event, Module, Config), {noreply, State}; handle_info(reinstall_handler, #state{module=Module, config=Config, event=Event} = State) -> install_handler(Event, Module, Config), {noreply, State}; handle_info(_Info, State) -> {noreply, State}. terminate(_Reason, _State) -> ok. code_change(_OldVsn, State, _Extra) -> {ok, State}. %% internal install_handler(Event, Module, Config) -> case gen_event:add_sup_handler(Event, Module, Config) of ok -> ok; _Error -> erlang:send_after(5000, self(), reinstall_handler), ok end. rabbitmq-server-3.2.4/plugins-src/webmachine-wrapper/webmachine-git/rebar0000755000000000000000000035065412305126066025273 0ustar rootroot#!/usr/bin/env escript %%! -noshell -noinput PK’KAžxè[Ø getopt.beam…Y}pezßõêc-ü&+­ˆCaaȎב’H&†×–e%!!9áø”eimË‘%¡]rœIL.)_æó88îRwwŽÏ+Ü•@{ý§Ó)NgîZÚaÒá¯ëL™ÞL;ÓÎÍô÷ì®…äZϼ»Ïû¼Ïû|üžçýXylï-‚pég#Ùá=ÃvcN¤Aؘ6íFÓö7K-Ë ˜­Z©>Ý1S Xv«ZŸØfÝòÛ3­Æ½~³Õj´üµªe[Á–yÐÄŒŽÆÿÁRmÞãþ©RÍ2ÃŽ¢b­QŸ.BoµQ0MUë•ÎùzÅaVVUë˜S­xΛR,YVu’ÅRk:r®´Ã²šµª}ŽÔºó•ÔÍûlòÙ­y3âŽ[3–í ø§ª-Ëö‘Ø¥ç®LWÉùbœ³ˆ}kJͦ >B*Í×–'YvΜ›4[j©²âò½U{†¦­?×ÁyƒÕ9DY®:N«uÛœ6[ÁÉF£f–ꑹ*¦¶Öš¾öίÖË-sάۥɚI¢ ­h5ÍrÑ>Ô4ƒvÃyû§j’˜¬ÖK­C¾Šd5庈aÏ:[î;’«–{å.Í”ñ®5î5[ÉRÖ.ªZd¸H©†‡º¼¾S3ÔqS ÖjtÚ#—ê {x^àÄ¢®çu× [w6ÝÎŽ¶±‰éŸ·JÓæ*Ë.ÕáV¥è”tGµ˜j´æJ¶ªQ«Ô‚Sµ’m›õUŽp±ÇBÿ–¾©ùzŸÑ'dS"b +‚ûw íS´Qéˆ\©‰Ú*M›‰îã’/´EPõ¾-:W%žÔ ¦ eE=‘ó‹ Þ¡r)Ã}RØçË?\F4UÌÏFã¦ÔJ›ê ©j#ªQ•LÜLN›™A3£a>ÉMÔt•ÞMÍ‹ ©È g åÔ{…á‚u$þžÕÙ—zïÈð‘§OÆ_}º³/ùìÉ.­Éu/G}ËK:ª0Îõè1E j†2¡ŒijΗ“Æ4)÷vN(ª¸ÄË~²h2EÍÂÒ y_†÷ex´À“ ò}TçÉ¿ÀÖ@Q˜Wt>€ú‚F>ÍTL‹Jy7hM‘ŒDœE¡pœEuŸ¢iY  : ²B¡@KÄ>ˇŒT Ñ v%†U ˆ b ErQ êpN•• ŒF–|qG$¤.ˆòš®…®V¸>îx¥S|òBŒg’<1ÊuÛqµ®®#W5¸jèq¶Nö²µzÈ É/+Ç8Gzná.ú€7æ¡ÏE¹¤3CìQ^»ìY4;뜹ä¬Ëç¬#—/…Ë+¢¼ž‚¤ ¶A”/#¦!ÊRLS‡ÕD&Î.Otu)y*™Œ“[ÃÉ­”óÑ2@^åË-ŸMè:ÏxZ´$»LÅÀжfB”¯L³+ ƒhù®…‰°o¤ Ø#âü[È éìeWÅ:B~!¦¢¼ ¶QºNb»ù¦‡ºÙU¢¬§XOl8&©31ãªî•Ò¨Òòª(y¸YÈÙ9)[Xɹrö…“áÑðx¸B+>Y€§±ÙX/»Z:L+šúW¡Âã<Šeb3òP¸ÿl–A^”¯V–‚Ö¦¢pR ƒtÏŽ˜(o$¸¯kQ.×ò²ÅC—” ¬W”ãÄ…\oŠ%¬®¥…aëˆ Š+œú9"ñ²¯ ¢ —úÙŒúÙ²\êŠWê}N©oÑ—K}eÝÀ"`[îÚé]å>G2É6Ù$IŒ£ì1ËW&©&Û©M0Èm•'$€p(Îú¥P7õÇu hóE ´x̘ }ä,Bã+Û„Üg†/t ©]$èÇË„æeãkÜ;DyÀ)òy wBëʤ®ÝëÍðš ?)ʉ$‹[ü✼àâ„ô‚~+@¾ÐoK³­(í(Ã¥&ŠÐB9^ª@*KdÁZìeƒªÁŒŠ4¸ex=•áõT†)”á (§Rlh¹ Ó(=Ç]ì‚vØ×V…‹çTaÔ©Âè¹U¸„ªKSnw«úƒqv‹ƒutësª± ëë. yÇ%·{u»˜³Ï¯[à6Du{=wÀ[¯‰2O±Œ4,é‰4ÑÑò#º’ѵBœd¨ìF ôVEÅ0HÙ§91 ?àçM5LÀ±$Ê#+T&Énø R£°²V²)¶Ó³²VvVŒÈÝŽ‚ÖÅ'F гä¡5ã,y쯉dÐXˆ³1lÔy§°fUŸ4Är¢<†­A”sÀyë;\?²¢¼3ÉF‘2òcüаÿݘf»°ÀvIù®¼56Šõ•áR̳GyNÒz0Xž*"ßÍQ»Ï°›Dy7*aëI)œ\©57Š€?Hu†öPª÷º©¦þM´åÇÈ·ýØVözé½Ð¶‚ñà^{6o°Yj8e\;Ãê¢\ÃÂt¤æÜ•Qç¡IV¾@4 ª>\zC›Ñ¹§—µ¤œâ<5çi8Oî<óqfI9l8-h&5ÖEþ¯¤\“H’Ð0ßËJ¹ç¹ähØô¥Ù7Þƒ+èåoè#¦»'€Ö·€Þý@ñQþâ (ì¨(ßïRO‰ò.õ¸(?èYù6To…ê…4{ªWTã°~È@ª*; õGDùp—@@ÍGB~Y‘¤ˆ5GV¸GÛ¸‹î¦÷0l¤ÀÑU¸û¯$È`ÇIùq:d¾ƒtåï Q~¤ ²Çœœ÷.a¡m\nZþêÒx?’bbUq§|TíìÃÅÍ íQ÷õÄ!öxŠ-9bÙj§ggZ]~Âuq)É“ë*y.Éž\Vò](Ù\Ÿç¡!·ÅDù{ÄÂ>ö‚Á^Ô» 8О¥Ç€ÆË+_è¼ÏŠ¬Ô‘Èú‰l4¡óÜW´gʆÆô¡1àì%Qþ>iÄ^õ’Á~èâœ4âóˆ>•’ç+]p•F®â)–Ú¿I3Ôüš3<Ãû!iÆ|¢k"˜D”Î=ÉÕQžŸÈPù„íöM²Bg¯tLãACŽ´[}¹ýk)¨ÈêÿïÅŸÂôàP‡¯ˆòIâËWRì§Þ¡y‡æI=ßep\³“S)àŒ.ãµÜƒ Î~l…½ìUœÖÊÂD¶“ÃR¶³OÂãIÏvj:ÎÌ×EùÕ^ö£2dN4³å6™óÄ;\âǽì5h¥c§€¸ä(Ê2+åäfl§i¾6%*Xª;÷µ^ö“²;·ìΕ•ÿkòù~‚¹ÎÄ gžêÌsÇEùu|·d¥¨wľ‚rùi’”ÜÕ‰ÈH Ê?¢£Àø.A̔ųƒ§0˜Üo¦Ø»ܧ÷)îsÁæ}‘[.Þ?/Ó½è-ÇCîzç¶“óïˆò[ _È:€jŸîr~goSŠÀïì+· ¼­œvXË .½x$WJ”ßá>úaᘦàZþ¾[jûMDön’òî:ï!ž1 ñþ6ö µ­‹/ì­ªÉûýŠ|±¤>àךkTµ‡} ªÊ6ME+©=Bé¡ånÓß#ô(=BÑâŸèh¯û?©5yrZÉÆrrTÍJª—<Í}¨Y5*E xñ"G–¥žTÝp¢Ny=⫺;çØaðú3°1}HŽv»ŽÂPûH”@s5LR¹ÑþÂ7"‹¿âœŒòZQþsâ`úǘšŒéÓ`îA’?I³ÓØ÷OŸ½,Ð0îœ úÆ}_„‚ݧŸvÎ5ñ·ƒ\‡†Á‡&¢ùÑhhh!¿Lwxò¬MFñxÔ‚ž<Ñ—µÉ\Þ&ÓÛ&Ó×Foj£ûÛü1Úørhóg›Ç¿íGvy=Ü67ÓFçÚbÜѦsW›Ìî¯ÑÙûC‡&¼nôÆ?öhúûÚvÛ—<šæ¿àÑdçyïí´±ù:é\ïéÚãñ?ñô ÒágGwWm’ù.Dü÷}ßß …>åŠÿ‹¿[ûû“/½¶4ûĉ7²õÒ÷&¯z'ÒõÎyåcuÿ×5® <÷Ä¡ÇgnýíïÆŽÇwÁî¿øÃ'ÍÐßþ:·ÿŸ;y>÷Ðþü_éúàà¿ÊQ¾îþ7?>5ñï±Üõ³ëîý0ðû÷ÿ~çoÅßH/¾óßñ~^8üÉñ×FÞýŸG>ýakò?ïùçß¼¾õ™ÆïÂÛ6 »eª­%øxÅ×bØéÅõ!Ú˜‡ÅûhYOæM´QOæ ´ÿŠGÿe;ª‹h×yü§Ð=úq´´G?‚–òè£h[= h[<úZÒ“™GÛìÑ÷ môd*h=¿„vµÇ¿íJÞïÅLqÝ‚¦y4ÕÃO&ëå—hŽv©à®ªßµ‚[ß½MükÑÖx5Fv.ötnðhÑÓ§zsIvµ7WñìVò°m·ðÞ{¤FÜ™ŽŠ ´êÔëŠðo¿\õÚ+Ÿüú_Þ¸ûÔïݺq–¥y{¦Ñrd*‚:;_ªÏ6x¹1gÖj%kS£5=;+dvÖ§0¾ÎÑë£iAï—ub+s~¶/Zóss¥Ö!GocÞ®T[Ÿ9Y­G¬‚Õz¹6_1+ÂÙ>ÍH«T„ÐȾ»G‹ã;÷d«7›ÔÀÖâ@bs*™^’÷g Å7í= \4]µµr:5µµ¼2¼w<ï nHŽ 'È ýúwþä¦m›’ÄóÙÕ9s&0 ÿ?/É%¥ÄJëKŽëVc¾U6×ôχþJ³ÔšªÚvÿdÉšiô·ÌÉR«ßj•ûÝÿÔm2[µYl<“–Më÷PK’KAß±«F p mustache.beamX påÞ½ï~ö.·d/{!lØ„Ÿ„$›ìåçÀ/wIŽð"œhõr¹Û$G’»soO°`¡CUF™Éˆ(Zi¦Ò©"Ž"ŠÔ:δ ÈT¦bu *ˆ˜ѪUû~{{ÉU°6ûûÞû÷½?Ï·ß²+VÖR?àko]Þª%†)Šþ”¢¨EÌp:¥…#Š-’NƆFQ‡B©H8nMij,ÞoJ Ú‰(VSJž~ )ë“jJ7Tî9ãʺPo,ë”™è, M+æH"ªX’iµ_±%ÂÑP„·'¢é!ÅLx»ªR“ªØT%9Ž€ä£)öt<ªôÅâJÔª*Àªæh,¢!XÊ AŒPÈ’ÒªbŠ¥´”­o(¬iJy/[,ƒZ|2µÊ'sPø[ý©- H"%øRÔˆ/ÅíÅ–Ö-£ÇA1 ŠQÁ7Jörç=lñqìâñ*kGÌXtã‘2¼×ƒO·áóA›4v¯ºî6ó÷Z†ãÁ¹·rI…ZWFI„2.Aˆå2—;ëåÉ(Ú2ЍËãjFm8¨#Uè†ÎÐ}yìqXµ¹ÊÌ;`ÆCŒ°èÙ* ™N$æ6síö5Hl· "\6Š:Çðë)¢t½¾˜"h(rÌÆQÊ·@2›i¦x j \w’f¦ÂÈæÀü¦yÙ±ûDJö‰œ¿’-‘n§Ôm`rå±ß­ç p#€¥c `‹áÀ1‚™,ƒÆ™Ð‚Æ3•‡‚¶&ol&€–Ža ¡† zÙY0„Y¼C(§|û-Üd;*ø–ÝkÁ 'BÙ²Ø%ÑL9xÏxÏnbç¡V$û«Ør¹EfË‹°½”cßÀÎ¥™9¶ÜiM#!æ’“8ÉËVÀ~¨Ð÷‚ýËUÀÃË€{³ŽûSÂÿ¾¦ šWÉ–#GåÿwÆÆiÄ­0žÀÍTB©UpŸï¤à¤&ÏfFáR*ÃeÏà$ØWQ t³º‘­Aä Cnr‘¥Æíe%@°”‹` ŽØê"Ùê…Ø-ÂQe‘Ø:Qóÿº›yýäÓ$rLÔ’$`(u¬ŒŒs’Ï,@NÉì²S2TðüÉÄ÷@|on|¯þaáØˆçßÈ!Ç­ …“•™,¨±Þ"ìÙz‡‡m ™z’R9á”KrÄZÓ@ühÑ徑g#x6ÑL#±1ën”áÖ„M¨@àx n›¡´zBK»ðËÑÌ‚jv!"ed"3Q—ÀÓÌB‰]D, hfxߎ^pÄØÄ[ÖG3­Dmð5±€®(7±ð ñ¯ªb;ü-~¶£¨Ç¾€õÛ±möÙl;Íø=lÇ*'¼Á˜2DÞ™xÎ/>¬b·M”ßР}Â`ö :à©]äa{¡L’Û ã'…L¥™År ˜u6±‹!e^ô°‹E'¼ºÁó¦kæ…Èstp›xF`¦Aÿ–€ÏB¸/Å$J Í,#ˆ²œ,]@Ú5QÔ*M ’êÎá$Üé!`g†2Ñ@V ›Á3@vãœð ˆ5l?ÉàÉûºËà €x#nP±‡ðS5§•䨛 "9ÍÌá…›Y†œÄ-3â›òïȳ¾ssò¬6x’ƒ”cSkÈ _—³Á75ö$çæïðÄfAŽ ñ]”“ð¦öõ¤çúÿeò€úåOþ–µòN ¯Ác #¯:ƒ7õL6äùo2âO6|í9}µw"7-‹i |Qzý“é•ÿXñw‰kèvœÃSOÿ¬aøôv©tš¯ñ3Ï‘}…{>Š%6 ÉþÔ5RÓW\‹;¿<µicþº‚ÞüíW®|uôêº"Þ7·ôÂÕŠ!û©.ljGÝϬÚï³Þ\qâÛÞ7†~û^ôøKÇ~tâ_çÚ¾žÿ—ý &¥w-½å½g…ß4U¼‘xeÝŽ£õ¼”'¾‰wþÙýH„E/|àÒ®í›êßž78µiß¹Qׯ¬É{ªô}¤¾½ºpás5îýqwþ‡>ìTk×>!?£í8ÌÖÞñú‹_ܹ?io}üTeÑsSžÌw‰|»´ú½èŠH㥷ñmþxŠ×öß~áÔ_ÕCw>ôÔËWøwÜZ½q[ÞÅC÷_Üùe÷ýor‡~î¸zyûê%³·Ÿ©n;;\²|CëÎ9·ßüþyc£Á×6XnÛòÏ_>ðê]ᇦvðøsW¾îY»ù‹[O‡ÚŽ^*¯{ºó@êÝ~oûçÕ¸Šß¸æ§­ï¡Ç>¾väêÚWç#OXb“Þº¯î¾_ýþ̦m—ÜwYÜÇmêx¨öÑǧõï°4ß³ýµíwõþnÃÖ‹KŸÞÛ0ï®-?™»A~öƒª^8ôùó‡Æ>[;µ¹{wý®ÃçÏ\>ûÀ«——=Ò2mÆé1WÇÇ;8ãÑŸvŠw¬9ñòî¹z1ðoçÙ®?¹ öýaבçj~úðŠÞ3¡We~w¬kýáÖ$^ÿ4ÿð¤sQjY"B°™4ðâ5pâª7ðBpYeðó "¸› TaØ‹@óröÀœœ}^jÈ .§|A«¦©p_¼…<‰L¦(…îNÅÉ:ÎQßܶZñ<Ÿ¸oÛ/Ü3.¸ Ök8­ $ÔAª ˜ºU%¥%âU·*j\Q×ú;ã}à[¢Ç3s["I¾_¤ˆÀ¥XýCK(•«÷èñi-ƒxf¥7':6HÙbñÈP:ªD©‰Ï<tÑ(åðÝÒ¹¬-ì\Þ>Hå×IµuRSmC¨V®kòx³FÌjÿªPgWÇŠA*¯?¦ µoS_Cd\½"Øm¨­+k=>IÖ‹³‘Ï$î eñT7V{ˆÌ¬Å†•k/äÿV˜ sa6\®ÕSO%ÒjD¤*kÃJM4VûbšVÓN $jT¥7¬Ö¤ÔHMö Zµ¢­míMiäaóPK’KAYÖwKÝ rebar.app•VMoÛ0 ½çWr’ ÛzJÑ˰ýa·"0d‹Nµ1’¦¬…Ñÿ>)67¥M‡Ä&ê‰zÌrÉÖÖì lXäj?~­¥ üá¸ew÷Ó»ç­[x%1E/–KÏ[æÝÃsâGïÆ$ üb1pcPvÜK­VÌBËíjÁ®³ÒŒæ›ïɾe߯¸/A¢`?´Æ›×fÃÑ%ЧÍíæv²Ä‚[±Ç·œïÖÉØðVõ]Ó郑Ƙ`ék‚—H¸[î ’½Óª—{Êgð pE¦ôy»rN}¬Ô Bw„ÇbÂé(IwP’¨¹IK c_#8–÷"ÙfZ’®þ/° ®ØHËy²Íz¸Ã)¨cLrÆD%û =èYìvÒ¾³wˆ¶æd[E­´ÚÆ$ÙXÃ-Gd?uëfñéuÅ>_†qõÒÄca±“:pNFý›Äm;š³ìe¶vÉ}¡!rðœ~äpDå dSåÀ“è•»+Î#qÎ@'{Ù•¬0—Z+1\cö­Úòh!‚þA-ˆÈš|PU–”Ÿˆ) >SÒiúgŠÂM„5™ˆ!Dž@_ÏWj¹¹Fa©Iá3ó˜€&‰­ ßß›ÙÒÀù¯¶Ïþ["Àĸ"ÐÓˆ©n%˜YÓãîu³ø PK’KA\@‚¿.° rebar.beam…X \WÖŸaò"£@A4!<A ¢0<#" ¾ŠÆI2„@’‰“Ä‚´•VÛ¥ZÅÏZíC­¶Z»¾ªm?ÛÚµZ­Ö¶Z«öáëºû³ëj}õ×ÚvÏ Êv÷ëÇïwæžû¿çž×=÷̲I56ð¢ÒÂÊB¿àÆ0Åã†5)EÞʉ 7çô(yQDUçtñv/º8CÑȹü!BsˆSP5¢›óbÀÓóz]Nçw …KàìÊÎåãiÞÃY]¼Å+ N—Óã“”[l‚§ÁéÐ8x¿ÅᬜKá¼²É)‘ªVup ¯æ<œ«ÕÇ«Áˆ… ´¨lb«×/(}~Nô‡µ¹‡Âéqú§s}‹³5òï÷þ5ﳉN¯¿_p°x87O"åˆQsV5¾û΄ž#\Àå¢JÉŒÂÅùüHÀqt)-Í|뀙´4¸8‡Ö×(%Ã׃!©±v¥%D5¶Œ5W1¬&"Y×^³$±CMïc XkÇY^fÁ”éYól@µñ‚»Þ+Eòqj5‚^޲8íFÃôÿêú °lƒ£ÚC:NÖ#|š‰<PGÂeœ â–ÊJ„¡®õZT·TƒZv¥‘²!÷l(…³ÁC'gßO¡”pÁY\ú…5‹š…|´¡²ƒ­p‰WÁû'`ꀩ¦Ù8ÙÓF˜:a…“M0u‚·Í9”‹€oT©Á«ÄHÕ©@/ð¾¦\YT2å†M°Ñ£¢ðá4Ù/Ö¢©r·Æ*`áÿ>L ¤ÂH P  ~@a2>@þ é#ƒð FƯ•¿Õ)ËD ”ñA@12?(NÞ;h¨Œë€†õ±/Ë ½ÃP(#€eyä²,cJ‘÷"=©2Ÿ”ÞGgÜïxLæ2Žò’)ëÌ…¡¯Š ÿŒçîÃçÉ<Ò3VÖ‰ðÙç^¾7–bY¦¨T¶‹r>N–A1Nès.•2? {pF5@“eå¡V–A|Ì#ýSd¾FÎI¯þé2dîÃÏ죓÷Îâä9Âí}l!>¤´Õ•ä3ª'›¼>Sæ1ÙF™Ì'eË2¨>L2%ÛFxHYÀS+ëGùo’q,‹© êÃÐ(Oò:†½;}<2îubêö~ÈNƒŒór<˜²`¹c‚Ó¶”p¦ý>iY½dŠ[`Ìt¾.ô»ªŠ“‹Bjg»ÃKU¦5Ú+ߌgÃ#Ýy¦ñ±w9w¦õî;8GWÔ=.þƾòuÛ3•L½a÷‘sGÇäå™òŽ) ¯ÓŠw—¾=ûÒ¶E-/.c5Ø`-{ö½ÜŽwÂ;¿ÚJ®oQ.Ze‰]s¸~³Á,÷à+-kc_é\ðü´i«”¯$*³v×߸wx|[DZaߟZ¸³Æ°5Í(üNùñËçbv­Š|¥ãÇ}7ªÓzfoi~ÿÙ÷bVìW¼vG½ù þê¿Fäo»wç“ÏË„Zö«×¯ž}šv>x…q voëúÖ#Ýõ-_lžö ½ï¥¤ùKS~œk¼üzÁåÖ¤]»Ï^[6vé-ûþº [«–ŸL³}ÿö¹Í ¥î剥–/徎ëªü ¥kDÄ/çFLŸ¹ßyzÖðŒM/&Õm[|L¹ú›„7O_ìÚl>ÔcJ9å8Õvõ—³w¶×ïË=ëZÁÙW)§ÎÝÕ–÷í{Ôê=myÜ_÷gÿÖè±g*‡ü8íqjYºÁºù×ת¶÷|þþ,½«øÇþûN}©t±ç›¢’Ìÿ‰?§KŸr·3±%?ôµzïÁ•÷îŒKÚÚù^ÉÿNykwÉu×À²2ïÔØÜŒ$qëOG®ºvõí–®bvÏ”'l™òrWÒ:¡ykÿtÍ!UËgïäîÿíâ“êQ+Žr­¯Ø±d[÷ÎÙļy¶ˆ§_Ï›)¬®¸:zIÁg_ÛÛqirš/ùÕS}¬;Õõmº³¥jÿñkÇ&|Q÷™7zòİC—KF^èžÜ¨êSÏ”ÎY{ëÛUQmC«¯™Ÿ¾ÿ£äcDrTòror¤gÆvìS±k{ŠuÑ¥M•ççm<ñÐÒÒ´•!ß·mѹtÏé ¨KîĵëZÆv¿qmáª÷‰¸|÷W׫:S¾ÛÛ¼vƒؘïÚRõ=kª{k”§ Ö5›ŠÏÚŸ»|p?³çBé©Ïæì˜Õ“œPêýjI“¶½kÚŒI®Ÿ½ÙoçÑK¶ÎçÃyWœ|ì·ÍëóÜV¹ãü­;[Öæ·.?Ùýªz˱¿Ç­˜¿={ËÏÏóÛþÒèýek véÍ(Û†mNl}þÆ”äÄš'Þ·Þ]3?ñløçµ|›Lg­kœ·×96í²Þ;²¼dÃO‹Ï_¬YS¾øç–·¦ÝºùÒÝ› U1©íc~Ðjw>ººn¿óOc6VÅ>ùÏâ÷¨‹?ŸŸ¼1‰rϹ¼Bã©9ytÝíÎôM[¦ͱ{iz}ý‘ê'Z{ô{VZ3ž:2§!ju§1~ÖÚ«ç^P~TÙ~ólîÜÍŒx©3¦.êÑsîÞüi»ê‡õûV¹knØk‹W/Þvåõ‡§ÞÞPß^ô…š*|ôÞƒºÇÚ¿[{u¹gè!na”»N_óFœ1vQÇ®Žy#×]Ê~!ëDæÜ¶A8Z[=ïø²øËµ_òov=·áX†+!×1ôèñІSæ=4Qõý(}½³ªËàß|`ÄËkæãŸ+Û4Ðü[­Ü‚#ׯ{{sóïúußÝ·/ór϶Ye¾Vž÷¾ûêe½gÈúÑûsšÌ£wìTYg!Pµ,ÞÛe<¨BæÑûh¼üNÈy$Þ™å2Ÿ(ëêýƈ’yô­¤‘yu¡ß/Â8r !!v ý0*M<4F]v>U±n}ÓÔ±ÚÛËššŠË=;>H’W yuðwOÔvŒ’~·øn7'¶"•ðÛb3¦à­NBpg3¦vzl®€·c~¼n$`ÍnÇ4EuåJ,µå•¥ÍØ€LcF¦1'#Û’aÊÌÉÊí"§O¶”O,›ÔŒõs8ýº [nNC¶íþò¤Ú*yYU“‘Ud45IÞÊ?ÿ6cʬ´‡Ò²¦ð;Ý|£ ÎN}†#9š£¸Á\†äºOˆ6¾™Þ(¸ùt»—œ~º•ó5 éÒïàé>ÑäÒxÑ… ©Ðêó£CúPK’KAboÛSDrebar_abnfc_compiler.beammU}leïÞk{½­ÛµW؇ƒ´|.£×®Œñ1}÷ÑÕêØ–1ŒÑr½^Û[Û»zw &"FAcÑ £(ýÃD3 „˜Hâ’1êþ0$F31è€Æ|¯=ÈBhòë=÷{~ïó>Ïó¾yn`x4 €kco¬gS© $À ¿.§D=)¦ÔŒ””´bI)ȺË6è´&%uM3C+ë’œ”w˜.­l&ӊεt¹P¡œ²^Õ,ÙÖÆU£¥DC¾ êe•©Æ×J¦Q[•HššQ²0+›NÌ*šê.éZ© ¦áÆdrB,”eWZΈå‚ÉV—+F²¤Ë†¬šŽ AIZZvlÏ)Rv‡ºkUMÅéàŠšõØÛW+£L½,;2bÁé fU±(ÓV––q%„æP5-5NY^RË;d]×tw5ׂ–…3§kÛkìº5£Õ[™Î{÷¶Û»†"홲Ú.´ƒ>œ"d#î5 ª¿}Ín‚%}Kx‚¯aì§Ø‚Š@ÄE)^F0ˆ¢ê…ÛoÙ£U;`Ù)ˆYp. Heòw h µ‘‚ê‡t‰!Òw‚%"è7$ðÄ黯ÛjyqO±/#гbû!-`A‰ô1^–Ø-”áXnØ=:™ê}?uŠ8€â,䈣(ÎãÇ4"ñÿ ûq¹ÄpÐÅ¢Çd pÄØÙ(¿× ‚—B?.ŒW‡{¸Ä4yX¦Ùã#hoîõÛ}èÅ}ðWê¥^í8Ë ®rñÛ*éV[QUr•¸ì ;ÀâÌ¢8ŒÈÀßgÇ©XG cZN$]|©Íã…ÌÃ>#h/‹Ø$a,ˆ£ÆnŸ€kY]ÂnGf‚ö¡ø‡›ø ÷8$h?®u~Y€|pˆ=JÐ -‚%è+9ÌñÓ݈¹A79…›p³©Y—"Q,YÏI ÜEà 1Hëž`06gù<£Þ¾S–íÇX€Aغ…öÚ‡0Zl›Ãàm;€´×Zú¥óÖ.¿Ï&c;*¹­°õËlƒm{oò.Ê꘽/1o]“­®æÛƒŠiin`É›;Þ}ïÀ™áóBícfÑôIÉýÊ¡ïÿ :9ñÒ/jóÖ¹±¡UW–>qçÙÙ gëÞ>üÑíëÉÂëß5IêÁcŸ|øØž¹üÕ·OO^uzAç¬rüÛk¬©;VxQ×Y½øÆÑ¾Ö‹‹8y|ú¹ÿ;÷Nû«ýÇ3Û;Oî|jÿ¡¿Ï ¿°kýŸC3ý uêë•=­ŸÊëîñnüìùOï”–zÎ\Õy×\á¨/'#éÉŒ§Æq®ÿr¢eæ¯Ùá¯>¯¿üóÆú¶Ù5uéãûç¾Y“ÿ!IÙ²êlËr¢»uNÜ£Q²óןZmÿÇóÅÞ]Ï€AM²êÄpÞ×›Æyçê³[eµ×î£uêì[kklžê1MÝŠõRÁbrdÀ C­¼¨,Xçs¯níým sýVàµ%mãã} 5ƒ}U=eé]ÕlX„+ <•é—4ÊÅ¢¨ï´N<õñÐÏJN)ªÅJ¸U*”Ór¸Ë*žÕŠ*§sûÒiÀônI ö'Ç›byP¡+Ü™ wDº¢ëîŠè'û6'CÃyP“UL>,­ëÊtJ÷ÜÃc#¶Û9Žö ã•l'dÝÀéæ#ºzíê¨ÅQ¦R”sÎÎV¤EVôˆ-b¸’zõÛ•kC9­(‡Ò%QÏ(¦Âó?§…*#>dèRèA_ÂÕøÓ6Þ“2Lë0þPK’KAY«¾O°ü rebar_app_utils.beamuVolIŸõ¬í“M&^'iþ\ºí&½¤nâuì&NÒ\×N+U›¶I‹øSH{“lb{­Ýu¯\‘¨€¢~¹k®œŽÓÑUOœ® |tåJU*ÐQø€§¨t:N§W¾ðx³ž4&袼7ïÏï½yof[.ÏW£` Ûä «¾ªrÅþ%Ý™Ï=›‚^Êu~Å4J~:+ ³F!ŸËZyÞ±*ºw1[°u¯nY¦UWÅ(˜Kh ܶr‚ešòéV![Z‘‰F¦›wLj&,dm7–'¨ÊåÍUovÁ´B%@#—u ³d7ÔNüT{Þ.ùaÔ Sþ|Φ²FÈÂ^5Êe=Oê*¥¼¾h”ô¼Ïv,£´äsÌU½d‹3ëÌÓU [ †Jð”ñç N¥àÔ×ÄÅåŠC*%ýBYÏ9ïèVÑ®£µ;Ÿ-Tôº²e‚­íØM4½Pµ¯+õõâ‚n Ô„6O?>-T’×Ë–qÀc©`.d "•Ò•¸ÆuO8a‹«/šùJAŸ7J‹f5®™w üo"ÑB®ç QÕšŽÛØ*Ÿ`©Â˜4ó:BÞ ì%‚ªW€R@AŽx‚{'7 ä’Fœ ÂiM²L4J‡2û !tƧù ¡3?‘gpKJü²BTyJÆ™k)(KÜÉøeLd~2næ›C[¾IÝòÕ«¾•¾çâ¬ÝÄ”-»EËhÒiدªT‡$îÕñTwòÿtkžà#ÂÝh DËœ“ e¿¬Õ{Oò‰ÄÝöAÂÝm@®Ú/ŸÓ2eÊ–´Ì%,È—÷ŒZ·I10ÏqϨ،a±¹MSÿ)‹„û(…‘”ÂD ‹ÍR US\pÔŠ7ˆ¦¦Nóz  ×'4Åœ„»`"ÕFh¥Z!‚’ÅNUÁdkucH¯hvìUÅ>pnÙÖº#Ø ¬•kƒ`0ÙÕèv¡¬“ë¤ÁÚe±ƒÚ·ƒuÒ`!¬)¼ŸÜ€ Ç4^ÒB» k±ÐBxÈd‚|p;¶óèÜÎ#Dó¸Mó9¡“æÑytƒýS@þJ×ăaq7ìn$,vG»HKÙ­eîB_îBºí ½²¨‚ûîmÅÄE2àþö4É*™’¥L@Éà€÷¡¤ŒŠ{•1qŸëWS Š¥29¥âL 5ËLÒÍ&ì ƒ¢K°]7GÅ^<$o­L{¥qIìmÓ­¢²!öp‚’{•¤›ãÇÔT Í¥b$—ŠÉvXì <{'‰zI³yšN.cÓ²æB~ù#¢!–@(û ô¸ß^r®šzÓc±Q=¾£ '< ܯrB_ƒ¬Bw —~Y a±Ê€p XÙ²²÷»¾ûÁíÌ DvƒÐ¬Šƒx‹ƒmÚMñÀ5q€UÏ!ï–`«ƒ´uÚ:€Pk!b"Ö¦]£7Å!Nˆî€r¿1êÿ℃Z@…ü6a+EñŒ*9aT1Ph8Sdª¨†A5ªñ lŒJ Åã´ñ ”…'a„ ñ *‰!C"´T7‡&Ñã57Pš]Â3qñ†ñ08Ž£–“Ÿä¨Õ:&ãâa,a4çX§é%:],ÃÈÁÕ‰Z0ÏîW/ˆCÆS[‘ÙR›& »—›OåR•?Åä2ОœfÓ ´ñTÞÇlÂ@û?4XkˆÔ~¤Æw¤”ÊÓhMÜß—z af;ÎxÄìö29ͯ›ñ4ïÆïbıZ´0¾‘þfÕÔ²‘ñ–Çzàa±<Ç ‡æó¨^¹p]¿zqú$Sûf£ñ”[q³=¯[6¤»Š¼ñÁ‘Á8•ñŽQÔ—} ÿ;Y!K²b¶+uS·ÍŠ•ÓWÑPdÙ,ê‘|9k-ާñ²q×x1Gv¼âáQ½‚’ ¶Cñ_PK’KA‘i Å” ,rebar_appups.beam}X lõ¿óÿb_.¹öìs’6m’kÎ…¦©ãs|i´‹ǤM›Ð¦ˆ1„sñ7¶Ïº;·e[¥òQñ1uÆ“Æø i¬b°Qº‰v 4&cÀ>„ª1LULliïþ»1PQééÞÿ½ßûø¿s®“3{㌤Òc»Ç\«DQèMŠ¢ö¶Úæ‚ngõJ¥ZqV/šeÓÖ]3JÎ5¥m³U·PtZŠ–ndsV9_Xl[4ݬ«ÛøQÑm³ìf‚½Ö;ÚæÁ‚Uu°¡©;&èÝ%6_(še½d2¬By ÆÚµ¬âX¡œ·ÂDñ9¡ß´‹zyÆF[j)yépÛªdsKfn™qíªéåò…²‘Å¡ŸµÌbgp§µîš s¡ºØ\sT´P3vU,8®ãÙ,›×;MÞ‘q,Ûm6@{h ¼¶V+‹¶n˜öԔ׋ŽÉ—ÅX¸>ﯖL¨‰/mÅYd]+‹/Í.À]<ƶ,3"ÔÚ«rç–jiznÀD‡ù ¨€k†ë=©õ¨v·æjÙ0᪦ъ¡Ø›úúûÙS/ÁaÍ•*¸#Žì̲([‡²Žkû »àϲ ®É`wœÇzž}ËŸ·ì’î®Ä-”Á¬šs V9[‚>˜F –›Ñ¤P n©Z^vøš0[²Œ*8a».æ*«õrÎ48§Z1íƒ(´¿Z1Ö’³ 3[ U¹š¯‹ æ’ÓesºëÚ……ª ÕÀòƒz± e&ÚfÂTíU'Ûà/`®@GĤ„-5ïÞ¤­Æ®νы•?–ˆs‘ëcñè`ô+!q€Ä¿¢D‰†¢õYq¾Zmo¯ »¢_ØÔØ`ƒv®KQ§a¿ªöïÐe@"-øB½-­š•4JCAР$AÒÈ'¦U¬Q4$jHA¯ ¡‘!„)D‰iÑ'§Ut*Á©ÀGÒ,Á(œB£M`Õçä Ë-Mó ˜ûd-C‰Z‚ (•þ!ôQKÓ‘0S â1I!b-"jŒ¬…Q0Ì(ûk®A‚T¤pšÉH^²E HÇßóñ°Ò;ØÉƒŽ)£ðA ¡A¹Ñš/ĉ =»JS49‚ ÝN5N‡qš¨qm( œÄNTŒ/ Ô´Š³aŒ`¤‡=m$ÁÚù ZçS×2ik++ZHÿŒ– UHs",Rõ²B‰_©ñ8s ©;4jRA™H†É¨!M¤çán] ]Ù|“( óʤ”ȈyR3(“€¾‹ôë†ÇqöHôý«$‡0$âc ß:/âê B@:_ã5‘Áùz<+±‚@Ÿ½}¦•d6Dѯ€p£DŸKþ[l•¤1Qc·2¸eÁRô<²aàš¤wú¼ú'Q¤Y˜Mn“B³Á$/Êcrb|˜#@R*AíK%„r ÈI©å¤rÂÑ~>äp}Ú¸ì‡öÒl¨õøñ u„†Nhûpù´ñ9 ÚQWsn„èmPÀtsôF˜¶]˜‡ÏGéÌýheì#šVîE5$ž.˜z¶c˜£ o|<šPgGõBÙà¯Í&”žOJ‡Á##ÂÄŽ@Ü5¸Rs^Zæd-:YÌ0Fy9†»V8#¤]XEF–Ó.„d”žCbÐºÇ„Š–9ëÇvÖû8‡uý)$ ¦H ªZæŒYÍÐ"xÍš ”ó4+ª¼ k>QËœC{@O³aX¶ š´U¢Ùv…oCÛßÖ1Ïmã;¸$¿†æ×Ò¸mâS•)¤eÎã[t óP¥Nï5€«$÷ó"± bYJÉðÖ÷‡òô6n#N‘äÖCô5­”äøy  VÂó@«ˆ¾…ü½P— ua·uÙ µÄ'к~=Ác^jˆ»ðr'šðÂcÌ%„Çþ/m°ÝÜ€é'ò-@цXƒó‘š(@q‚J^jð3Bxw¢ŸjÈaWC»䳘OÆý¢6‘úì$Ø-„§È|uš¬–çH­0n†<·,å{;Rž.¸x.úèðJ³»w¡¸pGÏÕ¹wO̹LÇœ{ö'¿},Ì}£¯í‰—ß,ß·;uçã·º±ÏÞÞóó'?8;~ó½_÷Ö¯nŒ¿nÞþüm}§ŸÛyä{¾Ðm¡O¼ñû±³ŸU®í ½uâüã·¼º=šdß—±·v¼§-ÍþeÛ@µýξpWéÅ÷Í®ûî®ÿɧ¦žŽ'œ©ßÅ7Üò³'?ùõ[ÍÅ?¤7‹­¾Ó·;=óÁu›™[‡^ÛøèŸKÝß?ræ½—oßbí|pÿÓ¥—짦߸浩ÇJûNï{ä¡÷ïýñ#É›•çØ¶k>¼òÌ#¿ø‡ÿÏ«o˜x!zíþwŸÙûìݧnúÖ£wß»úª¾­ô¼tâäïúô;Ýol}ªTjÿÄùûÌ«ï>ñÎ_oyF ú_üÚÏö]}ß7­ßýCó뿱üé¡ç·ç8tjөξÿ)=›?¦¦­®õoÉŒï%µÞt%é×ðz°‡ðxNvÏÑ4áñ¬e¿(Eø^ Qâ÷v+µ²;õÙ,_El°-ÞË"ÇûÚEðxGDÂ7Á—öu´ˆ­–|…:eïP¨Ý30ðÃÐÜÈ×ó3]5ýŸãŒO•ó “<<ƒñ«‚¿Á,oÚ¶egj©¤Û×c€ßªºðñ¸L1æB¡Œ%ta™ ʹb¾ø¨•Ð%:à¸Ôþ©é‰ìÜÔîô2µzP‰*ÉøÖl<1˜T‡ë öªñ}Ù©=“3ËTËbÁ•â¹ád~kî‚zfn–¨ý{ãjJIð²=hÚ¤»L5©ÛT,cÜBÉ\ò/@þÓY]Ðy}½÷Rwà«/g.S±Ø’U2cFE·ó×Á'ø’ó>ûcŽ‹5þÏÇ€iŒ-8.Þ»ÿPK’KAª`h`rebar_asn1_compiler.beammU]ˆU¾3w’™f³íd&íjÇMDèv7“ÝeÝV¥wwMcdÛ®ýà :;™¹If“ÌÄùÙ¶öÁ¥¶² è"¬ˆÖŠød] Rð¯ e±¾ÕAhJ©Jú"X¼7½[‚4ð%çžs¾s¾ss¹w×Þ}yÄ—Ç c»ÇB¯ 7Ȫ>.›¾anÞ°¼fËi`_d†X!_ §,q¶eú6K.›~˜ ýÈY lºòƒ(%Qè4‚.7pˆ lZ5Þ«'¥Ý,Ý ò±a;¾D®ÙÄŒ縫ÚR¼V$Ô³<·âTa‡1×óÊ3qš`…1ìûž/Q-”Ç~Ãt«|__ W£†é ¡áXÅl˜oÎÆÂšïQ ݨbûfˆí¶Ú Öp‚0ˆU¼†ÝèjzvDD:nÅ[CšëMý ç†ú+‘Û¯÷K¾ç…TKªŸMšd!&<À«dÏeðà3OðÄɼҫqÚjMF0ŠŠ2@P¨T”‡PQ›@E=ƒŠh?T-”†RKÖ8W|CI@ò4§HŽýž(k}á9¨ÜÔ ›æ• :×Jj:-¯B”DYïûžCÅiʃ¢†V<«ˆÏ ¦QŸ’‘\H(0S(¶2*i+jÓÛOÁËP‡@í[Véç¾áæú–i)™f¤Ò¢ÖBÅ9UÔæ$Å5Zœôå}>—{PâñÓ‰õ_p ¤3¥Ìk@ÔÎÒæTðYt*šÊ-¢â”äE[zrWÉ7x%±Içî&e2‡€2°*Ëš\ŠgUºVÉ®-ÑãÉ’N éWeN"{›Ð'¥÷È78I¡P©<âÓîrRšøz'­M"”"¥Óh(‹ÔaQ–d‚‡´ #Ñ ¼ZH«tRy©ý-ª¤Û¼¬?"NõdÕT–†¨V]å¤u¤_V礞¸A°?ôÐQj¶èïu…AŒ N ÒóB°ŠùiN’ÙÝ« xvÆR,®2ÏrÖ2{A³!;‹«¿¡#gãÿêS{3ÁÆ£9O0ÿŠÝÙk…›¡váh{Æa6›Æâ*³Ó-²B‡v~Wä®pé:Ëú÷0à[´/ã­ôæÁ½Ä¶I'¤Üw.ýøà{c«Oèr¡x²wìóü'' ÝÅÞÉîÓüÏÓ=翾3¶îüŸ?ì|ó#å—3óç?ûò™Ÿþ9üÖ¶Êø»?~ßÖW˜¼8zaäæÒ“£­ÛÏn¸{eqËÛ_ß¹yó·'K»ï_>t߸¶þýß®¼{%[ûqýídæÒ)|üVé«O_NßQ^ýÔ¯mÝ&=«s/:çéœaó¯!èb¶8†>ùÝóVƒNXãmg—.8W¹×Æ?ȾñáKw¾7’·æ.34!nFaÍóÛ96Pü( 7&*›eóž WÖ y&Jn…ÄŸj×(M$w±ã¹uˆ6ènß»F5›¦¬]׋Br׀ˎK=œS¢ãZÈÆ6X¹6®8.¶kÄl$Æ–&Ÿ7”vê`Í žÔGó#F~hptxûJ’thb¿QÚ³kotUPË[ÛG+#ÖÃðÞS,ß—ׇÚCгØˆÜ:ˆ <=0L}Bè4q-^&ú¯›’)›ÝæF3ß–x‘oá:ÉÕ¼&ÎÙ-Ó¯8a˜#ÏJÍ˵ \à[¹G¼’äÅ™cå ¤gï?PK’KA1 …· rebar_base_compiler.beamuWklÛÖ&u)‰¦uZ”ŸIÚTì$ŠmÊbÙnšk˲ê4-ö6,ȦèAÙ´TH* ÅŒÁ\¬E; [f?Ò½€V`+0`+ÐÝß"ËöokQ Í2–+†u@±s¥ëL];‡<÷œsÏã»çSËgÏÅ9‡Ó §<»Æq¾ÇqsŠcòN®wÍ\Ñ®5¬ªé §Y÷Ù•€éTóõuÁ5«åPÛ¬h×ËÖº¸nz¹M»àúKf¡¹ÞÕÖUíuä¯Z®ç"×¼ä‹ÅºÛª¦gU]©lÕK¹2pw7Ìb%WÍ»^®f—ºŽÝhmky.ØvµÏµjêã”rWœ|£a:‚ç4M9_uÍ õTµ xÇ‹U¶ÌRЭX`XêöòõEDú¨çkf°d9ô-Òj)#lÚV=ì˜5ûr+TÍ®çyoÃïB:žòyE<È í$fæ‹‚U/Û>Ë”m§–÷ðŽîRÓlšBݼê å¼U™¼ä7k ïšßÛpì+ÂÒÙ¯ž ÔéÆj dVMÏÜõ¸hÛ©˜NÀµ›NÑô›Žc;ÝPhT4ânZ`ÇOÀ¹M%'ÊÍú„>ÑÃVÕbôúT$šY+€¿B¾à´õF‡»ü•:x¬[ží`¦o{ãRvÉä¸À· gd®ý· ´ÔÃ˾ð(áÕNˆ! («)dM JTÐñ q4B¦QXWx½‹C$ªAYçŠöAN–U™ !-ø4’áru ¶e•ô  ª“ˆÒTœ¡_ŪÊÙà³$#»­&–[|#´µEG”ɨ I â ¤!«Q’2Z"ÚZP%òE9Ýuié®Ã<&5…¬A,))âA47"É4û z‘ ²”¢¯­Bë240%(A<ä'¶ø-_XR²üKúÔ|êF?‘"?‘zÇßeI@Ã*ˆ$"D‹dåTJ–0ãoˆD4b($ 1ÐÓz8«ð¯iQæ­GH"E´Ii ãþ.DÌò„H<Ö©(I5…/(oÑÜ# ·Zd[ÖƒêK-äXÑȇÒRÒQ‰òmÞ†U^”C€³û_§§›;x@;,ób˜êb8‰´€´¼•%µÃJJ#«ì˜ò¢rF¾Í‹°Ñy±7ÄéO«:îGó÷4¸o÷ñb-Gì?‰xqlGÁv0‰÷¡Ñ2(FP^«wzu'NFyqàŸ‚˜ÚÕa:$ˆWZ Õx&áE½ü¢9<ƒÔ”cxF‘FzŸŒà8ÍECdIƒÖ¡MËñ´sŒVçLOã/N·Ò¿a&‹`Õ¡‰¶Í#±crèÿšò]yYÕ2’ž(òËj"#Å3(дÖÖƒDÑv–k=ÚëG!Y$î¥k¸ÝâÌGÇé3 L4³$ŒÎÈxqŽ Ëyz A¦Š°x„Æ/‘-Ú—t¦À|ƒë— . $CÈ> }ÄÞÝ=ãì÷àˆŸ„G¡¿O$ñ" é*Ü0¸[0š¢AUìÑqŠ‚”¢ƒ ©/ð"¡#0B[䤷Ð^m«20¬aŒ ° E,øIzURD:Ç+†Áz ¢%!Z:‰—QH…hô&£Ö„6^#íE¦;.x‰:Ì€“9pöŠFJGܪç¬Ñ>+µ}ÿ($ùÙÿ¥Pñ]@ê ù˜=fü. ÝŒï 3¾¨ˆÚÓÁïe6”ß×!ßÏø(ÐŽX1&§9LvÈL¾Ãû˜ÍL‡M¼Ãf–òé«­Ú «yšéçÏ1;º_dXøØÛßá׷ܬS?“Í1œžb>¿ö—癞ú9Îâ¸ïÄÞøl•"¾á+qè²[o-ê2wëU~þ•õ ßüÙÐè§ï~é‡ßÜL­ÔË oÙ Ô>h7<Ë®»T,q¸õí˜s›µZÞ¹F vÓƒ¯á '˜«N%¼Uá‚V½Xm–Ì×Õ¬—Lø`7Kt¥'-~yåÔRnmåtºÂížÖãÓz2>“‹'¦“ÆìŽ‘ø•ÔjnåÌòÙ ×½nyj¼8›,ϫϮe™:p.n,ê‰ÍV¶—MÇ…t+œß˜<6iP™àY5s#P€üÿœórç÷æã­ÔÛßÃnfjî™S¥FÞ)[ž7_õöTëǔ맾à—Í$ü¤Ùä ®Gü?PK’KA-й+,rebar_cleaner.beamURËnÚ@?0$„2‚mô±èl”’‚„”@”Ю*¹Æ›Áö ÓvѪj×ù„~Dû ]ô ºìGô:ã˜*±t|gÎ=sîÕÕ-¯l´gãéèbÄi ¸h4Z{ÌõäÄ*E¬7Ä ÊŽÊ<%!Ž´ñJ‚3žUCÊçoê) ò¹˜„Ô@,ñHÔ"÷Ýìvf¿æ¤kuá£twsŽ“¬ÂR—…¢™ ®w_$p  +Pm=é(G:êS§ß®ZÀÑô8z»ÖP±ÔÖ 8NK[ÀŽr)nPyëhmIt,e§¶~@åó:¸æl%ÍçéNFG "k”Q0ªjYÿP@¹w–ü‘œŸä§ï ŸçåÛZ©5Ê3(½Õ=f9‘úãRW/ã^ ”ë^ÿœú«r4#Ι¬õ5‘ÌF €v“‘âB øõwôó£ž|óûö[üîÞn's"F«<.ôºÔWéŽcJ2ITÐ@ŒQæfyšzìƒ4çf1ÐÑÉ(8ULü$Pr l4‘ p8~5?鮿Ó4û–Ý·†ö©kŸô‡ƒ³½¨özríγe êæÛ?†§þÿôruY¦+{0¶N¶E·7ˆe¢ÝT½½ätŽS´1Ö¢ÿ?^̓^Ã;öì¢õŒæÌG1°Ì M‘ì<bÎ͵—m¨Ylž™1ß|°õ=±¸[1Ñ:ãrþÿPK’KAþW| rebar_config.beammW]lÛÖ&u)‰’Å„2e;®Ý„5Õ´‰"›²\Ûr~LY‘§ŽíÆN°ía*%ѲbZ4H*M±(’èúP¤ëöÒX€¬Ãô¡C±‡P´èK†aÅŠ`Z¬EƒmOÃúÐb?ÀŠ}—ºvÕaxϹßùîù#).®^ÌqÜAa¡\¼PôŽ ½ÂqÜù„kÕL·ZwÚ›­f_Íô,¶Žt/ñ¦åW›¶S3mÒ¶žêëÂ;~Ëö¢t«þT#äl‡ÍšãúâfË¶ÚæŽ%\qZí°åºŽ±ÚŽÕööS7íˆåÚf»Êd|c»®³k·<ß‹Q¦«¦Ý±Dº¢¶À8ǘ¶}€]»@x–iX¶å[q,±ØÁ9tÉÂE5ï åªúNµÕö­¦å’óK¹‹ê3wCÝô[N;J­öÕàD\cvÃÚlµ­F¼åU¯ZnÍñ¬X×Ûvš6ÍŽ0­«–eûü™ zx%ô(€Ö%f]ó­¶G¡ªÝªQR×jvlÓ oš¶g ¾Û±Â «Öið eB£U÷Þï¸VxÓòë[ò¹ÙnT-Ô$²^º¸´¶)­®,.U"^ÝmíúI×Úq®ZÕ®VE á âQ1»žÕç»OWS¨æ‰hP@–@¯«µV»Ñj7½ð¦c7ìxЪ³ oº‹õí8Žm¡¸›ÎAšužÈÖ¼‰\v³ÓÎêÙ>³ÑØ£Kfá=1™µëéoç€Ð³½–\–ãJNÃâ¸èã˜Q™ëþž‡\†Œðr¨LæÕ™ Æá”¢j™e2!ëF…SŒIbhBTå ¢ «¯É¼ê¿ÈñÆ™‹r²A“*òš¼h(•ÉŠP Uˆ¡~Yá×”ù'g¾K¨¦Y:^è¹Q»GÉZ¦£Ü0´Ôÿ%Ju‰T…ß• ¹LB¤œB™ˆªªòÏ.‘¹K=Q_R&ƒ5Q_ãoáp•¿ÐÕ¤`()ƒ¤qåI…ÄRN)$Šq*ê™»÷UTú=å¤roÈxç—7ÞãßÈÜÓ~o¤IRH¦]•U¹ü)!§ÿÌ¿ «¡¥“”b½kV(0U l¿¿µ@êlTTEàŸ –¯¥šª¤»©ê ÿY¨?žÔyQ.HI2¡ùå‘_)#%ó“@%eE_ãŤQÑÉŠü$/öÃ'%¢K2/¦ @(Hƒ ì¥ÌO&Ô5ZT¡D{+¨R)h®f¤ˆ¨¯©¼8¸Ï<ªAX¤aP T¨òiX ¢É++ê./ïû<ŸC8~¤ Âg´÷øQ¯¯!ÿn8­ˆªÏÒR¨yB(ç‰f¤#‡XnetŸ÷AðŽ –ÃI%ñÑ鈒U4Р¼½7 Òa”àHVR÷v“(ú†€¦kFühß@5zÀ°¢¿Í‹…úÀ=F}íDÕ÷ ’†Ò=+¥éÄó-RÄ5œ¨éó„F˜iŽ÷Ç'Õ#è.-ôX_ø3ÂÀw ¸G£˜YiŒÁzñïÞ1QY”3R†T 4S6k¤¤8P3FÅP`Ŭ!K“º4NNi|ȈK'âR–OÈ*‡‰×ŒÊšò<Æ?®“¨.ö#bQ”¥•IF:N3˜@ ¡ôzAÊ!ùÜ^u40‡ÊkÝ¢FH]ŠU·H{ÎÜ~Ï&A5Þ|AšÕÔÞü蘟©¯æGàÅ©}§Çà4§i ·ypë ÝžTzâG6(ÈIù6&G©Äg1:JHYTµJ¼P!eM¡õ*v§BTÅAÄ5⓸Î&8š• ¤Ht± Ä|hZQË#ÉB>¶ ­T,­×¡­ÇZÐêźwšs¡Ý,Þ|ù´—cuhwŠwÞ|Ú›1Ú»Åw?¸íƒØ¸qŸÖym.œCeçÀp2!Ëݦ)i…™ïyöHóxøHóxúH§nHgxñTF:'P¨;7§eC/kݧŠQÙ¥ÏB0ž‘U½,„òôŽB«¼ÖSªÀož¶Ö@ó€»ãÕähœxˆ–)EçXÔÅa”~¸®¥Y©Œih×YíS´kÙðâYÜ%¨0Ž¡c[âÅò”´@ö·á}9WV8ñ^<µ uÉè§€^¥/,-¸ÏØ3Z ÝÄ×è 6^|bJZ!°\Áy¬ÏJ—ÁÆ× Ö{ 6ºë¼xiJºH­ûî}‘.íìâÊÛX†ð‚D Qö¾¥ë³Ç!} {½“©½¢@³'†Ú‡z0ÃlM1ôàìá<Ì0*ä!†¡ë1fr”ÅFñöÄ–a<' Y¶¦ø㙄ä™} ò³Óõ4㡘9¶>9Íð¤ÈÎ¥ö…ßpO<‹=¹,2ê{ŽâË×h͹÷!IH™agë -=¹æ{j CŽ3<½cxšš­i]özH9FØšÖôã¡¶Af§¶f§×[+,>º–Y~ôÜHO®{çP{h±Ó¦y2½Âö.0,Y~K_nùsòÙµWw^üõwôÄsÙÈ—Ñ£?»}n1a?Ã]þþÒtë{ÏÿîÒ𛟿÷‹ÐBíógžú+yö÷ú¿£'–~xã…»üÖÌëûƇ=7}¾¶»õê­Cÿ®dïgïQ=Õ|勼ôÜ7¥~÷¥è_¦&f Ç®—%]ÿËõÍ¡æ3ÍУ¯¿5}zNÿ¸úãwü±­Ó¿¹µúSåG/~üØO®ývõßùgßïÎå–:õ:׫ó,¯uÖº^ýŸ<ϲT©­Äìô:ÏðtvΰõI&t= ™aøiVß`ž‹¾ïÒþÞ¤w(¿jpäª×”¶Ìݾò§‘þËwþõ¨2?ßg*W®”–Ú›ØS¼@ñQüKÇ—†G Ñ'ŸbU¯³³cºOS@Äéø–»Í þ–S ßÚæ¢­vÝî4¬÷Õ§ÏÁ^£ÁÅ.--Ÿ­n,](os'õܤ>››®âÍ:;U؉—KëÕ¥•ÅÕm®¯ÙòÕ\½0»9]ßß^ÝXcÛ‘‹¹©=%ˆ–~Š Üm.<5>3>Em‚ßÚ±¶"5Äÿ‘)š²)™£f.Ýs:nÝÚæ&&¶œk¢±kº›-ߟÀÇë–3|žMxn}¢÷Ëv6WŠ5ϧú/PK’KAÃ9XÊÌÜ'rebar_core.beam|X{tՙ׸ެY7ŒzÅh»>„¶'ÂM·XhæKõ¦Ë[+|¹Òìu›ÕBm†Í¸íóµ²;]©¹e½Ýœwƒe·8?³Â»S­Ï0ùvOý`_¥•ï0Nª-wEgÙ2ÍzÉmµ fn®P+·‚ÕJ«Ý MCj¡4®7Üf¡]©×Z}ëùv¥Ú2Ü[ Æ¥²›oÚ³!(”/.ë-·Ýb5÷pO¥Þ s…öiÞ½C­Z¾Ž.EÙ­ºm7_¨VóõâÍn©Ý ¶g›õÃ}u [hºRu«•boE-õÃ…fÓ^­0ç† Åý²Z½­Óf¨åiš«—ç«n+¨Äöj¥¤,P:ºµC½ÅB¹Ðœ ºÍf½+)†e±½­ùééÊ­ý§8¾%`é¡°Òǵá–i3rm¡v„&y_žÁÁp£éú$z¥6]ï+”Ëyà0çÖÚ}z«íšMlÍÝ&™“oÍÉør¥ÔN׫åꀧXµ^(ã¿R¡ /Ô¦+3‘N¸ÐÂôyUj3ùb¡å’*¼3 3Õz±PíÙµkImåo˜ä«-ÍÖë¸à¼}ž#òí# 7Ôt«ÊI„~}lhWaCŒ|šúT}î­ni¾M°º‘¥9L7—Õù™J-Ñ#$C¾]ÏSDFè?ZÐfȧî¸JFÁ°kuµÕ;]@L”{+t»l4+µv°P¬7ÛaçÅ*µRSÙš_smИo” Pe)¸9X¨dYAÀ)ÌWÔêùÒ,2ÑÕ‰ŒÓ‘†É§4iœmº­62©‹W˧<ÍO¡oýæz¥ÆWªåR¡Y^Ù‚JíNô·ÖšozN‡UÞntz¾V"ó`ËÜ2œrÈm¶Ü¾æ|­sUeÀÏàðòì oþ‹¶$†«¥øm Úö‘[A±õ#)P8Ãë†?â0xx¶RšÔ”÷6´Œ /{kË6_ÕK{ª@âwÕpWDlIútk>°»,)ä׃õÈؓôÙ0|J¨c¿‹ Ð$ß®þ궤mP±X;üÁ¦´L€4m¹ÃKýk‹Ó%$HCx °º„þi¼ ÿ…±]3zú7šušá»-3»)ËÂÁ€i;ûìö¾¹÷‚â¸æ–%M}œõØ20e“…CM©3nY†&å Öo˜ÚÄ[›êéÙÐ'³cÎSl'{j@ïÜû°vÔÔî—‹ÌÔŽïaÚs=ýï´—"hð'hˆwÚë=ýÿciE&¬¨²LRšñ™€d1=ðŠd¦Œ±h,dIp÷ÇB‰AeÅP`J2=hÈŒ-ã¦d ¨Õu)bŠ þ/‹V`<ÓcFcÑŒÌ,dÕÞf,G†×²q¿Ô‰{ÐúoGãFòMæÝýLƒ¦Æ£—2÷ˬŮ4ŽkÜìéŸ)5‹4$)ËDRÚiNJVÏ9b¬ä¢XU«5¾Št(šŽ)ÙL–¦ UW@òÕ² U^’,މnÌ;b±XG,Šât¨±S㧇ƒ¯3dÅV$ÎñSf¥²Œ¯QœÞg²rÒŒNÒ=Kl—l׋€K†7C‰s@þ~ T;0¬10ǘaãšyB–MiÓ¥´,'d&-u[&sÄL&£™èd´¬O‰0Öëc;cb=-Ö.Š34¾Ö×GÁ’ðt::ô7`æ:?LƒY&MèÉ ¯ßÓø™„ñÄ·ïð”Æ7¦„å,¥\ ʵ’bSiPlj핉’42 5Ó2gK–“%Ö;%†5¾)Ò8 S¥™‘-€2ÅdN—é˜LÄ¥*‡,uÄÙîÙ®]qÛdr¶Á¼ÓÍtº™lŠ/г4—É„Œ§)ÆbƒÔK0(Øç64~–Ì$@i3ådNÆYšàäì3v3™xLÜŠs#S YÒe.&ÓËAÂþ”8¶v;fЄ¯q›¢è(å¤Ô'&(ˆô€˜êÒy d‹®@$ñC¿ ‹á”ÊíÀ°"÷OQ$åÇÆrFž¥`'Tœ,é¦fôÚÖ­×6Ì13z !øL™´e;!à !Qò–@ •¤E’Bëóÿ'º‡ë6#>Lï0𲟛†e ðÇcÂýÂäI„_ªDÍèb—d™N*lC*øiµ•|»•|{þ¢Ø¢ñó I™ÉÆ'X‡ÁÛ=žl—@=ØÓ0&¡ò§»U¶¡ršÄ¢xL2Š0; ©WÐúX7¤|$8Ìù[ToÒј·yØkÜ‘ŸQ@Ù™h÷c´£˜IûØ‚ÕP,ã¶œ¶#&áÒÅs,<Š$8ùXÄ‘²”° ‘²Ì°hf ¡ ¡*Lw¢g+…Ç6JÅb$ei<¹’ZAlÆPu–¯RöØÔ¾ç€î"ünÔ2¨B9"E §(½.,Š_Hô@ütD¥HÔܾ»;# {ÿ%„Þé}A¾FgéE ›Ðø®!Ydjb”Áµf’ò@$})[k1J¢GÉ¿/ŠK4~1Õ£I‚è%ª…K ÅH:’š ²áòzˆŽPbÑÉc‚Úˆ26¡zKž"Zh"“â"8šÃ(Ù1 3@!="ÆÙ(³)1fïÀ°"޳lÌ6âž²¤KS"ƒ@ÚÝû»‘ÝŽ³ÛbÙxÖîwÀ8ƒMd²ßœDÑ8žcLf_'¹»InrÇ!÷RG\N†_> ûÅeá¬Ø£ñËPt®48Šòo¶Nã—«>Ì?†{—ÃŽ+d:'ii'¤i“k³ïP½ZãW‚âc ¸êŠ÷}Š P\Ü®ŽLP†ˆî:†"¶žÈb†¤ØÅÆ™„:°êI3Hù ñ½à29¹HcÂo¦ö¤„¿Ì]/å¤LÀÝeÝsIq-óZJmOt¦ªiñ ޏ‘P¸‘"o²(öi|ÒkPÚ;¿‰Îo¢ðØ·(®Ñø>zÉPgº†úq`Ê^=l\§jÀ Õ¬¹c D¯EoVÏäZD‡~>ÎlÈçQjsª —mªChá G.ÖÅurRµ”ä8C:f°ßÖøu—è)qÂ`w\o†‡†Ä;<©ñëSb?‚h¿m!‚ƒb"PL3Nõ’J=i ‚{T½“È÷]#â³p+šiÕµEnm)·â=öâJ9¹u.tàjvWm?µIÞ…>›wúMrês| >¢¾.eøV“rÛâ[ ¤áÝÔìe7Bó‹ ünÜ'Þ-{Ì^KÜ«ñ{h'÷ŽˆXı.1…”gÛñ yìAªÿ÷Åý¿O}Žtzè½°ésO­HŠ{˜×ü8úbRÊÐöe¯½Q°X\=·cê4Nýe0ø1_NŠG~s?‘µÁí‘•^L'l8éñ”x ?¶ 0Ôé–éCâÑXY¡Þy|OM Ϙ]â+”Žtut:©ŽÆ¿âÄ~=|ŒðwPèv(ö8êLTe®I_Eª¬¢cÝaʽJv"Fé5(¾Êö‚í‚ Ê$5þU2>IóE¬5±{&g˜þÓ||Ŧ› ˆGé­sœÄ`gÑVáâ€óv’ó· lÁ°¼]S}¼/Hø ½þ ñõÎ뼞_ UNÈ®'`Ò§ÇéùÉèî…)ñ5Àùdw¼>Iñê½%¿†Cõ_¡O’ÇÿL>о>#±õVǰú½I³|éñI‰§Á÷iætøŽ1+ሧͦxï®!ñÍâ[ÿ¦!é+Þ”úëUÇ¿oQŠ!~tÑýl0ÏPÀIŸt»ÐŸïèÒ“îîôiwùûš?—]²F»ø¤ýù¥«OOr÷tɽ²k~U—žWûwÉÞ½þþ>Œk|¬ Ïk»äÞàÏIŸ›ü½<Æ”¯?Í >š—»ðœîÂy¦‹¦Ò¥ÛAÿ—t«úû¤C£K7åÇÿÿÿ]” LSWÆ/¥´L™Š²áDp N±”² Ý€¢R‹¼A Rû¸ØR¸•ÛDeøDTQ¨°©†Ól‚ø ‹²€ CyÄ¡8«t5L’YSÐ1Ýο ñ&¿œï~ç;Ûžó'‘…°AÌBè Ä*D.hœÙÚ±´'" tþçÙÙ•ˆ=àïGx– ÀºX„<æ+ðßê·ù£à㽕NÉ—AÆq2xÝÊ)™o°¶mkjEâd/‚ÆObÌçàÇÀy6ôcÍX£§âà7±C| ~Œ#X×¹ ¦öñúmˆ¡ÇÞ¨=ïí0'Á4%G£¦Þ[aÁJ?ošBð/á(Ë4¯ˆT:´Æ&dÅo«Ì‹íSÏ vnb™"2ƒ×/©ªz˜œñú—¸Ûìès³_ŸuŽö¢¨ÞerËî‚ñ’ü^͘µÛþQ»¥«k¯ïKÞ1ÒlZÖn]æmî2: %¾'·ï£5O;¾LmÉiÕŠ§g»þáq§µ!fú`›ÛÂò¬Á‚””³•3¦}àß’=Çt¢íAwàcAv^[¼‡Õ}¡åMâݺúrþßßÄ<©-ºÕœ¿µÅ¡m¼¶vèþ¢g5…ÊÒj¨h8µÛiဇï˜ç€x¤=?”o“4´gS™ØiÇG£—•¯þ5Zâ`•=ü;'¨bÕ¢â#†ä›l¹5ju£¡‡÷$±ŸÝ¨X:|µhîš»åžQ<3¼þj±Ð,/ÖWU‡ÖªÖ_<¢eÿ~%lDymןAz )žEÕ¤í@G…‹ã'Ùƒ>ÑG­žö\aîÙœÔ3—ïÖÿëðÛ-wÎÛ}RºÎ2®Ù¸·7uöË+Þæ±AaN¥óo4¾´¤•7Ù›º.• †ª*ãÍFãMι[ê‘ÁšK7s¨Fâ€K¢žÕäö«ƒßq¹¯³Ag¼¬à s‰uÀó!Ý]¶aìN]̲/à ©Â™5m†Ñy¯ªž&¸ô.5%íO½—g8šqÌmVíëê(uöÈýNþ42ºž*ý^vÇõç1ñõO\WòÂ^%»‰šÇ~ÐÿãÀÊ;¬>“û¾9:ùÌή€Ö[^Û×YN×'ä v®åíúÂ(ÎrOq}eǰÊsî¯OX%ÎôðáfÔÆ–üfz¾Zøy€ú‘Y8²2öv>ñÜ׈/ŽFŽÏ™I_Ä)8»ýïœû©gÝ~¢În7âd:ß¹SÏýð[‡Aÿ„0€¾†(‚ü•wîF̱òß"ö‚®Fì†üiDäñwäÀÝ*}\o¶Cþ0hX?|\«²¡€fÂúzÈàZ¨±¸¦RÁµ64®ÁJX{$èt„ÆâZ›Z†H"&ŸÍˆ(ØC,"‚˜¬u¸¦ˆÀD¬ûÃ`oëСˆÈàz»Öú >"´?ÂÖòApˆÉ:¹Þ±ï˜ß8;X§£Q»xožYÉP¶ÙZjâ…r&Ô¯õKòžJW¾µ7­„—žN¡o¶™?‘gâ<[³U§ÒPZl°„#IÓZ¢ÕgfJé\`iô:…ŠVLR¦¢°c£Rl%ÏÐ+HñžžRi*ŠT(mQŸBAL ‰ $qáajb†Ÿ/×Ï7€Ë—py~þoCö ¡±’ð k"ÕÄô-*Ý®<0 /ÿ¿;2. ºY1\ÿ_^úÄn³IZ‹¶«&ìü—¯Xî=¦N•I*Yèÿc÷Jí¥ÎRGé<)wbëZž–“j‡£Ôd’ÅV)¦Òé82©V©áФLJs´´|RIäš\NÒè„Ë´øüÿPK’KAô‡ÚS  rebar_ct.beam}X tÕžÙ»Ù,˜Íl<6†@Hv’l ‰$L›%B ªHØÌîÌ&K6;éÌ,ÄW‹ZÛ”Ö >êƒjS[íÃ=BÕÖ#jA[­â«ÔŠQ´G­RË©­ØÓþwæFìiÎùwÿûÏ÷ÿãþ÷NÎvnÚRCQügm¡Ö­¦6JQ¨“¢¨~FWc²›Ž¸éŠ›Q%©ç“–N$‡r‡T3šÒârŠ×3騩f4™ˆŽéª¡¦Mw"™RSɘ+i`Ïœ„œ2T§©gTçnYOçÚL)m8´f–ûT=¦ªKÕSrzÈQY‰Ôô®9¶KÆL¦ ‡1œO©6ƒGM]µÂ¨º®é9æ°®ív§µÝQÃÔ8Ïn=iªQ¬æÆ‡ÕøvtÁÓdzÁj4£æ¦fGRs%4}T6cü©ÊŠåÉŒÊ#j4>ª¸qéñÝ ƒ­iyTuîÔ’i·3¬E\STF×4«g ÆŽÉæpn&­¨‰dZUÜi0ÉÊh®Õ½aÍ0]I- ÍÊI% Óp'R²iªi{ªã¦.ƒ¿.óâg¯ó¬4̨1¦Æ × udX{ùÅRª’£¨±ÌPŽÓt3/®¥R*8¥´˜'¡¥ìò vÖn­Ü<.'ÇK%Mר:Sõ|Òañ†éêP&%ëóì>dˆ‘λ¬O#Çú*ÀfE…I‰Ë¦ªXiÈ)—©ÀN΃)¶“Õ6«q†xðÊÆÏÕ”LJ&Ó Í œµ.ªúäiåS<=<˜­ åˆ7ˆôØzDïqä,Ò×Î *s ¬Ðx5DB¢œmˆC‚“c97%Š/A”—Ф©O¤ïÀLa¹IB|óú€yɇ Ü.”+ Êm±?ü°ôO–œh‚0è®Sð‡ÃRØò;üB]ØÃ‡ý¡:ïõ¹…^æpl@ƒ$O¬Cô)G¾§£.ã$êEnn°‘õ¢&–·òå!_%ËóžbN1«ä'8Jò[M!†£hÆ (4ã¦öHá=¼]‚¾–c¥H¹…k+Ù|4ƒÛÆäC|†‡DdQYÌ9Ëë$ñeØ1|˜zÙbȧ8;Ÿb~F æ%ܨìŽ99 ù³ÛëÈF•l¡s 6¶ ú½@ Ÿà%(àÜÌ +Ù"tîÔÿÄá)ð9 A†CŒpL¤™b\Ä|È¿ ò_@ºh!¼Æ1¼Ãl)l1[ “Ä.œbÑÌBÒ îD#[…•dVÂÏØ}Æù8 ^„Gƒž•àp¥¸g‹!f¹@3ÂÜ=0ÛŠ„L7u \x˜ïˆ[` ‘XÂ@E^º9Æ+¡ ˜ fMdÎÙrœ_9Ì »d’]J3KTÈC;¼e³ÛÈá}lfý4³Tr@x?v¦˜|Ü}Š¦Ã€Á r "ä BÀ¯öñáÀ¦•lòTƒKxJæ©8%*¸Ã\9PÈ SÞâ) "Þëôú¼e^\Ã|ìU5IÈ/Exp–üŠ7)TCý’‰¹Öà°–ÖŠ‹0a¨LXtâ3I±=Ø–U£‰¼&Qƒ?Q#È!ª‚¼ŠÕ„óh¦Ì®»G·Šüæÿ¯Ã<«¨ÂkžS‡i×áx» <ÊøØf§G3çad˜YÀKhbŒÃQ9Ž=v†¡B{NÊñˆ,ƒ ÂXVX³\Ï÷ˆ0JËÁ¸ Œ+ò(hò«¾­D­ˆ÷Ù•p¼™E0v`+a$OµuÍ1+¡¬mvª|¨ Wà VçqÖ%; ±x¸aE¶V¬À$[K3p+ÁWS$1küœu?‡œøraJyÉÓh<'޳Ç„E"|m”`ßA6ÐagXƒ§Y'g x1ÅàV‹â–Ôá–!Ùó!ÙzòF@¾!Jš‚a®ÃÁíÐq¦—™ˆU€l†ïÕŸ#¡ô íò—â[$²M¸Æ&|¸¦ØFši°î'Ê f£D”&ü| l…”ÖÌåpëý<™ -Ùµ˜h-nVó$ÛB3Ívùe¤ü|˜ìJÖb2 ÈÚÁÞj“w6Y&ëÀdm“l;Í´Ùd儬ý ²L²°w’ ÌÂèe°“Ð_¦´’ éµ9*¼d˜å8êb°Ã^Àžöãþ‡™Y'vÀ²È» “]³oa¦ÒzϾ¼Î³RïÆ©wㆮŸb7ÐÌzûÒÅ{¾’Ÿ¾üÞÙ0Ûän\ÊFˆ¶¬=y@«a–6à*ÙM¸2)›ìM¬"3Ü Ná{³”z8f ÍlÁ¨²Á(0p1FÀ¸ *éo`·"¨¦ÁÆ;¡ò.|8ñ•ü¾ Ž›mœ~«Ë[ƒlÞÔÌW€¡.p ìjš¹–›!ʶö"Ä‚gˆ·&¸Úºìá pø²/ ²bÆí@±(ØçR¾D1M±#ÈnÇQ èƒ¤Ø8Ê¡,?”•ðxð‹˜ñ‹¬‚÷EÁ#%O²1š‘ízsàÒ‡÷`Ì^MÜì[`6J<ÈFqEòôÃŽ1e"¢úL=‚ÿQëƒoú0¨ç8Ar@ˆ„¡A`+)–ØYÿçyAòA >¢cß"â‹1ó‰Ž1 ˆïBE_ ²˜è/déKˆ¾ÄOô…$ßYÎe„³d9Á`}ÁT‚¬$¬W½4 ‰½&+V-H]V¬¦¬×~áX-ƒõµDǾR¾-‹'Lú‰sXG0¸·ÝYµ÷dõ°'+ŸH¦cBãx­Ø˜s#ñë#:þÛL|,é̤#¤ÿ×Kì,E�;iÆ¡@ZMã·ö Œð›¹×·ž¹áС-kïœßvïÒ×\ö·Öß­j{ôPlÆxàÞÉú[/½éÒí}(ðï·~0}ºüʶÒÄ3·ÝÜxé;å{§~T±w«vô¹gŸñí{ãìºþä}Úóž?Ú—œ¾÷¾} ßUo~_žóZÉØ¯ÿòÒ«COœþΚº#{©_Ñ;v–½¿në%ûÓþÀ^þô±‡ŸÎ}cßu·ûö¼ºç“žî~å½xßÇÝ'¾=7uφéON$îÿ~hCêž{/¼MïÅN§äEOô=ßp¼³»ù2nzý¾ç¦Þ«?õÖONÆ~‚6w,»éÝÛ[v]²ÿ*×§ÓO7ßvwÍ'wýèë‹×½õçk*¶_ûÒ=øêÿz:RÚäúÙØgìÁ'Šþûí»®ÿð‡/6Ýé¿åÛ—;Þ~îÌŠ@íëfúMÕÞOïºûÃ;ËãÉØÊÿ´¿â”ÿzúã©}÷ï\vxÕžk>|rûS å¯Ô8rüêö¾±ä_=8wè÷™m‘ùþ¶‡Žu¸zpÿÌ«žƒí¿{€ ¾zeÅŸŽ^ó@EEuÁ›÷ž(©¿ùg—/›¿õ'y|û塨øbmГ{dó{gôÅ7ÿíéSýÄ­—=µ® ¥âà{M®»ó“ëÒåüéë˜|á߇[+·Übl1Žì::óÏSWýÔìÜx…ëÀõソíƒW¤¯Þ0“\rÛ›½V{ëƒ(y9:¹ññÆÜQШQ{ŒºÓ§<[W=pêÐsû4?ù­7Ç_yÿLßÄcû6«Cõ«‹2W<ß9úä7 gÔ½Gþ:ö‹ÇYùSýYyø‘3'ñr× müþåOÕ¿}¹Bûã¥}'/HüRxõ\°²è3´7.ìïÖâ{­;¤Ìã È2£d†±¾íœ™ÝDô~õd„ñyé"vüÝA|ñï>íDo%B“³ÜLð«AÎ'z=Yc½dÁã»%˜uæË F)#v|ו×UHt|Î#g5ÄEtg«iê˜ïªFÃáC»Œ´µHƒSËXÍÃCÇ?nw~ƒ¡¾yãÎí]é<[dáïÖÆÌ¤–6°Á­P¬õcQÔÈŒŽÊúÅàÒ2¦’ÔG(§K¦±…NŽPîd:žÊ(ªB}ñÎ0‚gŠByÚú»º;¢‘®¡j^­XS+6Ô¬ŠÖÔÕ6gAÌÖö¾hWOç¦jÎPÒjâ ‰UñÏoŠô’Ç®-5Á6±n§•í.U7 Ý*'X½º:ˆmN39ª»bÿk2#s2+/’k¬Ô -£ÇÕª20¬ªeLÖIÓ ÄdcX X¿ =˜ýU¯ZÕS;[c†‰â¿PK’KAB}a0¹+rebar_deps.beam¼XktÕ×øÊö⛌vûäå––î£e[h¡-%-ÍÂ~Øs8{Î~Ûsº¿ÿ=“Д~XŸ3Ö̽ÿ÷ã÷¿3Ã7ìéóù.ûß¡ä¶ë·•ós>_û&ŸÏw8Pt'SÅñŒ[( E·P̧ÝR‰Óóx&[ìò¶ÓùÜTv:0í–ǧgó“©Y?,¢çÙ|SÙ\¦=ãNV¦y³ùi†«}*5[r•ög JGûl¶T.uNå‹n*=Ó–ß¿¸/•«Z;Üâl*7Í vQ%—q!ÔÍ´»ÅTÉíLçç ÙYHr˕¸››÷—‹·-_ò—ܰ`­- ¤gÜôþ^¥«C“×2m¤­;4µ‰%º/Ð.»Y¤Â!騬[7´‚d~¬uê#ºí61ûiã0¸–›Ú±StkÇñУk'—@O\:ÀeÂ.X¡Ò uú&"O3GJg„my^{R:L{–t8()DN³…ª"§à„¶üvŠBãgA§yØ‹nªŽ€„Ñ^× z’µæå8‡PÒ‚w¦¡qîñ Œ»ÐÔx÷]§O­!"cu#& Ctå:7¤áŸÖÆ#º‘”Î1Æõc>‡vBì2ˆ]±Ë»|çÛ±=J,¥çU\¯Ð6‚iW:ÞC®€¨µµòLQuJX_ÆõÛ³Ù/§ÎU]ðù½à¯†âÕÍÁ_­‚­–œŸÉ¨ÿ [,ÌóËÏÕµ¬&#/„ª0T]ôFa4!Ãl¨‰5Ðl°&onÚI =ágÜ<©kܤˆ®…†õа.&,ƒB᜴䦚šM }Á·H „„A½ÏË6Ö¡‹õ¿„V l}£é—y]‡ú:YmA}BGIfI¿A­Ñ©?[ëŒõÎà—BZ/¤m€%ú©ˆ¸Œ9¨×g½ÝËÎÁ‡ ŽËûÅF¶1Ê‹MÆ®‘!Ãdž =:d˜‰!ÈM,Ї–£†ŒZ2Á¤å÷Ûb*.úÈ>/¶è3 Ñ×#+DBã½Ò9Uëˆ×¥óºïpשs="lÐ !dpݨ¨uT+4~Ú¨`oŒ‰«†Ô¦<÷Q*6;ˆjçÝ ‰Â¯«ð³E” 2í‘w‰+ëÄU¿„ÝV‡-ú5~Ê»»š8l÷Ûb8‰#ŽÇcbЈ‹Ak—Ù¥ÛC"céd á5;ʆª!ö{¦Ž ^i±ÝØÕø`¿¸ÚØfD¶ØÕ'F†íQ'ê8Y %G†gËæ¸ØÝ[{¤)¶ØâoŠúF‡¢zÚ[Gõ‰Â°uF4±Ekl×91R£Šš%iÅ$ ËDhx(ØbÅS¢¶ÓÅP\H¤MÖë?*ý–Œ%‚±#ºM?"Þ‚FŒ ¿­]º¤Vôñ. ÀXÒÿªv¡3߆XÆñ hH°OƒDc' *!œÔxBå ¡éÖøvbBÊ’q­¡ãb'¸wÖ¸Mpï$n´†ÅÐ-ða½}tóõq±Ô;jE¸ƒŠpŠp@ …£ña5¹À´Ácjô9 v¯DÄÅup]³¾ëêúʈÎí ¢ÛÙ\t×Õ°½ îlÆ"ìÚ…vÚe˜h'‹ÚÉ»¬AKìê‘ b7zäïFÀÕ¤p¢0æ†%ºŒ‹Q3Ú0fˆÙ‰ˆ%ƒTPÔµöÛÒ=5Ï÷ç{Hú¤ß¨ñúðæ ¿±¶0X]ØC¾Œ6›?ó·Œhü-¶£v£vx+Úáf¿k¤kˆìÛá›4þ¶¸K àÂùad("Lè鏨‹žÙkPÃDÄ^ ;Ö29ê—i$ø2 ê$ód‘á„T:nzÓÒÒ~9z¦´c(i7/ÑGââ0ßRc¾¥…9áWœ&qzm»·9±·4Gæï™­ø}{\¤öT-C4µRÈàA•'áÁr[LPô&î[ãß×»e@ûmU´ƒtGøx}”OPNRM 2 ÅÛA’º£? c}Be¨ó\Ð$ѧSBJ;è'0Âh•d b¤ty ac8½ðqq+¼Øß<{÷«Ù[uaeDd1˜üD|~\‡¤h’E£É®°úµhr9¼§îM˜aÁºʆtÄ`?b°KL®3ŸÖ'|ɰ²‰„ìZic2°[¹îÕç NXM¬'4l[«Ž¡nt,"X@‚%|Ÿ©ô '¦²™’Å05Y2VWq Ÿ­"TUkU±§UÅ­ˆ zÈ]Lån•qC¾*l§XF…2¸Ÿ28‹ŒŒ!ks²@/¯ñ­ ªòQ0´¸¨ þ•fˆ¬ ŠêÇ ¾ší6Oj¼°dÂŒ‹ƒ =¨h-làB¸0 ¾tD´¬B2JÓH¦Ãr4&Û%ó*ñeááÂm(Æ¢ÆoÓ¥—„í ±ŽAÙ…8nðÕ2Lp—–ÛYp;á^\ÌCï|sÌS„±±`|» rÌ † h-%~Ùí:¿Ð4˜ù eŒHª?†Âíx€ì Ù0”ÀEZ‚¡e—tIÑ`É15k.¢Yeu¬cÁ±ú±b¬~¬˜Ç±ÂÛS‡ˆyj•ëž@^*MM5O]s€u°Þä}9º 9º=.› qˆ&ñ¶x§Æïhàø!ÂqlnïìwjüÃ6Jáf5Ö× ã·küÎ.SÒ‰†<ÛÞOGI(@ `à<Ý&…þ"¬Á)›ÜÄAñ5]t«ë; }ï ìï Œ‹÷&Äû4þ®¸¸ xyw¬¥-îwú”8˜ïÖøá.»àÙêh˜â5÷ÚÚ@‡EAêçµ ƒj°àJo,×aª<Õ» l¥¾·Q{9|]¯Aí'jr Øôîÿ+¬óXqW Ñ:g¶îî²GȾ:éí 3OO³}á7°/Ì‚áš}8Ç+¿Îgß{þ²5+ª‘R¶„ϰ利ŸË 2Fãï}Sž^ü7zzÉy<}ßßàéú7ééû©Í ©§ð𸸘soóÙJF#â^šÞRbl¢Ò者Éóðï(è6ãßQàßâvnÃŒŽ†øO¶¸‡0ö5í?¸ >¤ñÖ06F Ë/mAذz- ãÀ þc¸ï¶Pª1á š12ôñ j´ÜCˆu”œº· Ìî#ZÇââ>B­ûµ>l‹jüà ԺPä>…Z÷µ>¢ñûÏîƒcÿˆðI©bU°{.€úh+@UE@} õ)Ô§PŸÑøÇâⓨšê¨@}õ \˜#œ [’ˆYæpz)n-«Ìà%…ÌãŸxCþÈYüÖ9ø?ƒ…ç ÆA‹æŸÄ ãü>’E’¨ìl&ø)\5!á«êºæíF°nÃï¿ÈnšF—hü_i)ø7ïðn“¯×øÏ°XÂâÏûų¬K×·1õ–yiý+õ)åÂϼ}6&~Fiþw0VÀø‹]<©ñ_âq¹y®_üš-±ÍmÌŠÆÅ‹xÅÑ{ŲtÄùEzÍGé$ð¦ï§/—ŒŽ'lñë jP?¿ ~¥ñçk_‡Þî e¼´<PúUËÓ¯câ—dÌ 4~_¬¿0`ç7°ç Ìûm¿ø[¢W?¤¾d àªHˆ—ÔgúšMÇ›ýü]Lü†D¿Ôü­á÷z¿/÷‹?0Oä)ˆ<¥DîÿsDœÚÿç@z,z¹8 „8 õUVhéËͪNØcM㈉ߓÒ?BÏíÐóJ¿øSÃúÓPuºÙúÓÍÖ¿Ò,òO1ñGtºÙúÿ€Ô;ðûj¿øÏªõ¯Aäkuë_kXÿÚÖÏ5[ÿªþÿÿ]– Tׯ'L$ ޤ¨h$€ ²„D œÂƒYEA$ MvTĪ´îGT\*•`RSF£¶2ŠÎÀéÝTU ÁøÒƒ1úüÔÁvb 2'K…ô%8†aáje° ôL0šÐ:Q¦™ ¦Á¸9ÐTÄ@ÓQƈ DAl…Øhöñy.)Ã"ÍOòm‘ïäHêabØßR”wrEüɇw .)Ã#Õ_†ö¿1¼õ 3Þh°ŽÊ€ü V’8ÄAˆW­Fu"¢HëF¼‘äÃ~bIýđ֛DZ£˜´–RÍTÒÜ4RFùÊ«I¿Ãfäm~@6ü{ÀvbŸwÊÞE ?w€ìÑ<øü؈á3^€>sÄ3æ‘î? ÕœŠ®Aß hbS4NJ¨É€ý£ß³Í}‰zÁh—+¿C>òûЈM¹L‡s4èû¨F‹±ð–©AMü ø6’}¼ rµbî bÓ½|Á1]Ö&MÂtç¥ma»=}Âëgýf‰kšÖ„˜Îlu©¨¨ql³oÛ“ÿ{cQƒÍoq^Çkif×Gwp‡îÏ¥^•TWãͫھc¯ ‡ ÷8M¾oéù÷G-p¨1“Þ­<î[˜]ñô[»[lVm»h|GiqÇ©/LušÙçX‡Ìklz¹þIP¶²ÝûÖ¨Ù½½yzí™YZ]J—¨«Žf(]ìÉJ›¶]zj‚ò Ãåy£³ÿ£›nßsœ6:zàà]ïoü|]ÿ˲þ=â¢ä†>¥À…õkÖùù]eeLÖå[§=éU9 ÞüZÜj.k®Ï§GïØ9‹v&ð:gíöÆ“ŒìJÞ°í2[üRù±WÙ÷ê›vÞÍXkNر&t„çuxz0yëelKß¾ä˜À;{Œ#nW_rÛ·»æB³®¡ÓqAJÓZÙÛùg?(/$ðïkˆ/·/­ã¯ §>ª_ýòJb½÷Ni²²Ää¬Ù⇕ö¦CÛS•w ó,v%F{ü¹£qߎ~n=Å8^ßÝȰ?yøùºÙyû „Aý^úðõ6›S<Ûvx³#þjÿbw¿0lö퇤ÇoSÏQ*k×¾«_ °Ì{Õ<çA§œ?fø¹Ü¥¯Tíýµôè™û·(«MV'±£ÝX¼!©Ö&%<ö¦U«§^šÒjl.O½(ø¡p{_÷!¯EÀù±BÒÈSùÖêÓ_[Y­ÛVß‘®¹=/4×Î.ìô/ßoÚkˆu£æ”œ,7f Š›»Â^—´ˆœqšÀkßUûõFû/ñö?eŒ‹sËÜYîSà<“ø{ÛJ§n[oßyêçHk\Ÿ²JÜ·mød†a‰v~ÔÑ:-ÁÍúãÝ …k_K“à~ìÅÐòÙúÅñ¿ìÌQ\ÑÕ]Œoá1ª¿èÜâkö ìì7ÿ*ÜRõO«9‡žšë”ö©²w=K°ªˆ9²wÜúœ¾ômÛ†ëãxÑ´†ÝfJGt7;W²´c¡_á#ùŽ×•£ôMÛ£\´oŠ–¶T¹kËŸ„©»géJy%DJ³¿ ±¸ÔœöäÆWÃ6ŸW¸wvæÆƨ¼æ²^^ÀϽÒà:¡Ï)9Û6Îû³>5Ø0RaÚÓU2" äžÌ{S30b䉜 Ø¼àF¬Hÿÿ”£=“¼§ 6|¶§ä!îÊEü (qP6âÇ@Z´ß´~¶©ÿ(e®){JG~- ùç€äˆ«÷C¸÷IQþ[Ä0s(ùûCÐzäÃuD V ¦ û úpž?òáYôÄðŒòÂ>¾+À3îKTg âÄŸÎÐå¨&1ÌÀóÙ eàîŒx1ä…ˆ1ô¼¢¹v¾j5<×OžzR1†kU“_2,¿)íö®êg-ë˜Ë‹ënñºRSý‚2Àz(ó'óT˜§)2Õ2E† 41Æ(• e¼J“ž.RæÀ€©B£Ë”rŒ*I”e@‡"“c4YFRšF,cfš ±$Y–!KqpM,ÆÌ‘AÁþñAkäØtw7Ž»Ÿ³<žÃuçó<>…èQ~áñA!µrljŠLmËIòà'/Oúÿ嵡è²i‡'pã¦Nv«•(U ]96…ç²Â…=ªZ–.‘š&‚þÛEt!bˆX"Îdë*…F™$‘cήREºÄUœ)R&ËÔj×D‘JªpUJEJW•2é#Å‹%™*‰2 ¼Mø&ªà;ö?PK’KAÊ Å Prebar_edoc.beamMTÏoÜD~ö8ñ&»é:륩 «á€‘ÝÍ’T&’v¥´‰¶).ÞYÏì®w×Ë—‚8DBH=TjNœ8pèÀ N\Tnñ ñðÆq –>ù½ïû<ïÍèNúë^÷pÿþ¾’ü…x}9C–ú‚Ë€ ê—)K?Wá<[™KÆ‹tÎ…)gKÚéËDeµKk ãQ8&c¡,-UÑ;¦B[䢒 å'LM,•梎YžøZ(ÈʸT—çEÀ*bÆ>Óêe¢[û‚yE·³HXSÆÕHò|.ü0ÉE‘ÎY<®kã+ôVÂ}þpàòyŠXA,ŽÙ¸å^Íó¨kQÒ´à%.µ¦¶{;äÎiw ¸]⬭ï¸}º¶E‡.5×h“Э¦Ývè]p)Ñù*¦ÞúéãO=°6&¿Ð>i€k´ïƒš?Á8½æ€ ”Ë‚/lçt] É" Ç5hJÌÆò*ç5@×€ÞuÜŠ—€qôu0¾¦ òÀ97¾Ñ©c|¯ÛEÆ» ¸¡‡*=ÓìE‰~†XFhÉB —¨”ÜÒ+zQ+=:®—gU-ÏMó „[òMÄkqCÏQ鹊ÍÃ'Eï”ë_/õZCYÛ¼Âq¨´ÿâ'_ƒÁ`ˆˆ~ ^’ÍÝóÚ—/_üô>¼ùùàXÚ{³üvµ\OïëZ/ì+•êúŸÏuå‰É<Îâ"‰øöù¯Gÿl\¼ýûßÏ>ýèEóÇéô P{«ð[Úoããgš°9¬ˆ4•©ŸåQÄÒO´aQæ Çt–žXÍá ì0æ9–ò˜‹Q >!¨qËÝG½ãü³ÞýÃÔ7ÛÍönç¶ßÙÚÜÝÞ»2U>&¸U¶E—Ü#‚žBzBaô„?©»Á‘nsë>ÉSVõ½$…ùeUOhLäñÏ‹øõ„‘ˆ B¤ÌE©ªî¶ec^Ìü¦*j®öçý¢Þ¢Âµã^H¿ŠÎ`<ãQµMOœõzüºž8m•oŸÂ–ž¸ÊQˆQ‡iZb7ªKdà* Ò&µ ^qÀÕ®´ûÅA¸Û¨íË´Ôı–AM÷®Ða CñÂÑMm@—:õMPõç*)ùâ>l&ÞöêÊT:¨û0›Ãe»EwyÝ~¶\{ÛÂÿ˜ÞIËcºÐÃ{èÚñÈ)©_ò"§ýP,r*ÖK¦Ã§ÒºWÒC^=iËÂïN©­Óžvê‰Ox€g=êù®S’Òæ.ò0=êÛõ="ÎÓWxQ€‘A²Ö‰Bp]wo:4 zôOxTY­óòl_%‰g‘‚ªx¾EµÁ¢,ðz4¹­ÎZ2ãB˜7¼܎8ÇQÅ67wRY(é^,d¯ö¾´Lzº®,zC™÷âEÕ/Ä•n·Ô®zÅ·©Ê*Û§Šï­‘ÄO`Nó‹²Ú¬úmí }ª]1Ò©Ê>] d”^I‘©ª®ÆÝ’7žU¯­Ynƒ²0”µ7ûý0m¨ûåi\ØÇe§÷±©ÒR T¼QI hlªw™—M…ÏæUÚ˜O”½ª®Å.)îƒtBnó¶ùx­UMXé—î„«Ý»>ª½+¤á@ƒÎ¦Ã‡©Nž‡útQžÞ¬ëzÈ­|º· @<3úX\èpºÐA.tÀ…66CYÆ®m®¸z4 „¢5 ø“Ñ€–îb!ey»6©Ü¬±™iø–Fýå™HÚÍl¶(Ï\ÂfÕ©¨ÓøßŽ#Ϛ؞ÕÇüé¥þhZ4vÔæsŠ_³„ùA‚ìn§¬(ÏÖ½6¢Ü!=,Q°ˆïZxkÃGRÑá1ôvØz+Ñ´:òxÛBÖQñÑG§ê‹W ¾Àe×aÚÖÙF©¹†§×—p·ë°ØAŒWYô¯I‹òõHoTå9Í~ …&ä+³GÊ8¢qŸÛ+ûåkQŒãêDФB>=@e¤UÂXX¬½Ý€‚Ü0Y7éã¡_Gú:%:…*üIÈ^oý8Ò„ŒÒf;€r(ÓØ-À` PÌyl®²ˆÍå¹õclcçXö ‘uÿ˜: ®ôJ"ÑØÙ©ðËþ>6Nͯ;ÕÅæšöi¥¼àÜ®ªÏæCÛTIVåëäBÞ 8Êò{ òÓÕ¬idÒÎUžÓÅ4ò:!OC;‘Õz?™$+·ÚÜ-ápã ÒQKÈÓ¥>g&Ú‘ècÝð®Û‰ánÂp·}ŒÇAQ^ØÅºÊm7³E¢Dćü*,!ÿTª¹“~ÌœìÎcäe}²1É‹&D8Ý Fö À  ôNÀ­+½t]ÛoÊk,¡$îxŒ÷M!ø-.Bß ù°Cþö/ßâÿªCþ&Èß”/nÖt:ÜHN¹ÔYGÀRBÀRK€€ˆ(/Dì{W!rènóµu–Qã>d±o¢Æ}5ÖxÄ®1Íúœ)XJ)Xë[áÅò»YBËë—ê!$äYÈžâ¾Sy{¦Ë•-WEùæ0[†®J‡ù+P1¤[ÂL'°_CDBT?6îÄF” @¾”gSséÀ˜æ½]å8î†õa÷®Så¢ç}WòŒ!W¶ivá4®y%$Rx&p·@Ñ }l â^ãDÏBÏ»®‚V‹ò*@väøÈYÊœ2䕵ãаÓzË_C‰¸ŠÓpem„mÂ}õ±d`y€%§ë»Mg¢|ú'z§ŠÞéGïLÆ”L³VÖ“t»èiŸ¢sy£Æ6SÍ6Û5[‡š­åuê€`Îá„/pø‘ǵ(ÂzݹpZ@‡®p+ú·RA/îÔCáÏÚCEyƒ:(¬ÔlCÜTØV€mÔ«$îÊx¯%!©QÞf·REQ†.QÞL9¹9É"U[U6$Ê_Å2‡å͸×í“·Pcw‘wÑ5ͶÂ;Ey+ÝÔnµ„k%4Ï DîÔë·|齊ò(ÿ=z;™Ã™N|ƒ2ýr·( Aа´›À¦wÉ“W:CÔTÝR]y:Ì _‚%¤ÓìcY #+é@GèˆE%-ÙŲ!¥ŒÏ˜² I0$µhRHG“j%šôã²É¦í­ ¶*z´"œˆVÔsÑŠv['lÙsÊve/,»À²ˆÝbÃJ…ˆòp„eÇûÇ/½ éK¾¤G/ ?^R?^ÒšTþÜÿT©‚£I]JZ´IšÚð©6µãÓß„œmjSªôð*µ0˾K ¥©=°N;.Ê#ºR¡8³õ˜C¸;Ým}¬€p v¸„‹µX+Èf!¤ìC 1-’јšŽÆüÀX!ioáÊ-¤u\¹ã¸rODÓÚ9lÛ²'(ܹeçXáîb£Ên–åQH!I;I¤KHÒ»à¿`K]RîÅç»×C‚üÌÿ¿¸Ñ·î#îB=¸"‚۔꠻ü¯^·ïÇs{„UÑÀlÔ¯'Mc5gͧpVDÙª¿9nGº*õÎÛ ª†Y™ ש; }xwÒ«¥ý9»©Aî™àÝ…í`|w„Ý;Pþ4‰ÐÝNå÷†™Šû ø ÷DØý_&¸Ç)x˜ÙYÙ Áqî‹°ì×þ…lÌ«,lÆ·–—Ûç”§wŸ(?f{IÃÐð4ŒGØCÓ½NÓãö¥å¥6âŽ{¹ª‡ÂìAR°  ƒÐC1=ÒcFuŠòAÐ"W‡"ì ·ßáêÅ’x&û“éJ˜¬4ëezEÙ},†­„ÆŽP™ŽLÄzX¹c;,Ê«cB¼¯ÎnŸNxãaoýMåðĆDw8€6Vß8BîN).ñÍ ‰£pí\;aÇ¥fmò–“è $¤±ÇÈÇìFú°ò¨(?RÕÈŽ¡‘'Ùk9ÏuœîǸžëŸƒàÿ+!žN}.ŸOøéæôùœNë¸~šwqýäOÏIgç'zÈA¿‰Ïc,qÌ—r~Šå+|~‹ÃâéçtŠ%æÈÕ ÎCü+¶:8­uG®Vsz“#'kùþ„ì:}=ŸSù¼‹ÓI÷=|>ˆa8ô›?GþosðŒ:|+8òPpØÚë 9ø÷;ô?ì G8ýÆ#¼^DÔ¡ç¸#®Çù|¢Fb|aØŽŸ°wÄGsÇÜÎuË|îâüŠp¿yu­¬¡SlæqŸæ²/r}‚kï¿Âã N?Çm ”ƒÏSœþu®OúÒ[x<Æùžäû‚øÉ?‡ñ8Âé'¸BÃG/Rýryú?!K¡±å9ÂâÎw€Çàrí;OµßÇùw õ3!zŠî×ðÜÃõ—xü‚°õ5:£;8?ÕxŠíÏÁž5œü3y~DÏ[g­ÍU)'À­ëÖ]Ï6ü°ø}M­ž}=šÛüòAK¯Í}aÍKÊïö ·¼szÕ¿N;øzæ ò§ÿ¹°øÀì_½ûÑGo}téè+‰üøüO^ýÖàŸm|O,oùÖk›bwîÉþËÚ½ïmxù·¿²ãÍÅ-ѧ–-\¸øù þzݼŠú#öûßɯúøz¸öó/FÒÏgΜý åŸ~ç{ÿþ¿-7Îýo¶êgÇ;Ÿ}­÷èÿl>yê—µ;’©Ÿ}ûÃy»Öù>~õ£ÁMƒ?lì}ôïï^¨¾¥®Û2úÔá'·4œþî¢ø¦_oýëï¿èom¸GÐ\ôM/žþIuè—o1þî³5'÷ó¥ßÝûðÌÀ7VíyfÞôîøÆ±ïþæÛ¯|å¡¿úíËo¾ÿ7ÿõÆŸ~ñ³;ÖÍûÇ‹±¿|äü¿=ž¿ì³þváÞ9¯7ì_ÿÒs¢µÿö?]»-øésÓ¿×ÒsËñßÚùûýûV<¬-¥)Ÿ?ê=ˉ1'®œX:Éëx†c…æÏ\…«£|~ê*\âµ>v®œXzˆóó!rL=Èç„£ø|÷Ux»ŸÓ·_…7'Æœ¸*rž!ŒŸß‘åó-i.Kg;Åé Œ»9úéœŘ!\îÇ[9Ïr®—b¤Þ¼™û@çnŸ÷b¬ásº'✿“ë%:Ý-}œ>Ë“~ê%ŸÓ]¸€ûÐÔ_­Z´·;RÖ•¤•¢½(ªÂ´?|ðñÆ‹Ù3MRÿÙþê;nÛ[]ÆÞ|›ßMüžR™~¬Á“˜ý+gªR+ k71ðŸG·9”+EÌ þkjF˜R+òŸ\³ö2A‰n^½vEjÓêÛâ£Bk¯ÖÓ«Ez§zB½‘pß“|{,™Z½nåúQ¡i$Wõ÷¤û"ËӓÛë7 ðíÆ=á¨Úf{K¿ÜÁÝQ¡!¼hÉ¢0ÑÜÕ\ÁÌ6¢ÆžŸ²¡̘môØ®WJ5+mŽ ‹»³¥‚Ù)Öp®Zí2*ÙR·ý;wwÅJw[ÿ'ÿÿKMJ,ŠO-ÊIŽOÎÏ-ÈÌI-Òò²“ŠK€PK’KA¢*Ò(‡ drebar_erlydtl_compiler.beamuWl׿ó;û.NÎ>“ á‚ ‚ãsâ@ýó☰¦%´©­9|çÄľ³î΄2h£¶¬aÝÖ•þÙÄÐÚJkW1V:ZZ5¢[[ulCH« ë4ÖÁĶvCŒuÝоg¿ ¯]#}¹ï¾÷{ß÷ûþ¼KÞÀ-·ÅfÎ}ÉÞM½®U`ÏU†a†êmc«f§ ;·îæÓ«PÌå ›§ —±tC3ÜtQsÇk+à’›Ë;<1f&u! 0S+Ü6+g š®—¡œk— A·2iÛ²\¿c•쌑6v¸¼UrÓzÎö,½”/›|]3Ç>°æ,³¦h[Å|ÎqBr»–/¼ndµRÞ›)9~ÚÕÆB£–†IƒSž:÷NŽç2ãu¦e;p“3Ǽ†m[vM%`ÞC ^wܶ&½Y-ï¼3‘+ ݯ[³Ä=ÖD-Í‘”G IÅåsÇÙ¨ÏqmpísJ[AMÃÐÙÍ<©j>·UÌkŽ›7¹lÎнå¤fÞ=×6²†m˜C'Ì ä Ó˜¬% 0òFÁ0ÝZÝÈÏê¼k¥ÉnéãÛàm£˜×2†OƒL½&kCXj®­e\ÎÉí4¼%Š;›SÎÌZsIy«Þ›£ŸôëŒæ3‘»:bñhGÔŸsÒ¶1VÊkög"「G?sY…e5Êgóšë¦Ç÷¹Ö„a: Ñÿ) ³%ì 謭ƒÚ˜õ0Ó ãýÌ¿ÄT~¦AÖ‚XÉ\¢°Êœ-F£œt;Fý<Ã`”à §™W^RÛºÐ!Ü/ã#ˆSJEˆ~¢¢‡ˆ~º¢‡‰þ>Âá~òš’`7ƈcpÿzêÄÜf c”Á§¢@`tZUù©â•CÓŠÄK[Êá8”dVÝ€Xì úC;‚=aìÉÃj‘ݦ…-Ö) –9`ÁIû1' !$¨S ;ˆ…»O݃֡= =>U”³ÙµGɇw°P„';êRÂÑo²ÄGuø3ˆ‡bj@X¹ôNì ÅŒL1ó@ê©m>Ȫi¦˜%ÔF|†©}QULÂaEUÜ•UzÅ­‰R| D¥øß‹é ˜H͋諫ìkªônº—ü]ZGëBüÜ@ísc•~SÕÞ›«ì˜Ú Ͼ*Î}ÔNxöSûlg9§¨Nz±¡*ÇÁ*ŸŸ#zré#³œæÞK÷-¥:Ckꙕ’9Jù‘÷!º¯‡b>7Iléúêe;8”sÉÌÿa÷îxòÛ·ýpøuU*ÝúÐÁ`R©QöÔìÛpà›.¾õÖ}Ëû‡woZ´îH¬ïÎ#—ßìyfÓöc-;{>~õ•ã -?yLzüx}æäQc×ÉŸ_ÞvÏKï.¼çëo£¥ÙŸýóÉ·ð.<üÖþûÚGÿ~`Å›Ü^ˆh¯t$Ÿ~sðÁÔ}åâËGyï³ïœ8>1³d¥Â¿ë{ø fç´³g¾øò÷ßñi×þá¿îÓ?ÿÍ7º†;~Ðñq.²»ùÍâÛS‡ÿöü}}›Ïž?ynåÞ?=“¸sížÁßÝ¡©Ú^¾ºxè£Ç_Øvé»{[ž8sìÔæÓõ[Ü¿<õÛ©Ó×ÿþÅøƒÞû÷êä]{_ßžw5v|Ã?/žÊ|xCij¡• N¾òÁš.ŸZ=3|nÅ/μóá¾Ë÷µ-ÐïêÎ_ýڜѺËyä23ÿÉÎó>`š›víŠ>Ó__úøØßë“OošYµÏ¯¼ö•à3ë.œ<ûܧ¾sÍóì’—®‘&YÒ³ç@æ|¢gÕ} :™ý$ÕÉ™XO{ØJ÷½ H'ųØNít–žœ×eÔNÎqÕɹ_H1ä{Ð@ýÍÎm¯ëÚÄ×ýyb÷è Úî˜åSb½·Áû‡á§¾|¯pïÚ5ç„Ƕm[?hfameÏ<_¹T8ÄÀëŒX¾ ¤R¡ Ùw€n4p“˜`8ckÎ$67lfò%ÝÐ™š’ —œièãÖtñ÷Ý>8ÔŸÜ”œ`æv¨ñµ;¾:ïìèNôÌ‚„ϯߜ¸e‚©˹J<ÓÓ]¹¾|Ëè]öÝOô©ÛÊl·¶t'o¢}M{‚Ø87W0Æ}[ÿ{š Iš¨5iñ2õʽl‚é‰[#¦5;›sÝ\VÆ­XùºsìLìÿßÛÁ° 8Ü_È™ý/PK’KAgÇ”´Ô rebar_escripter.beam]V}hçOïÙw–}ñ+œ8v_sêÚT³u²n‰å-ìõ‡¢¹K5NÚ0†å³t’Ζtâ>â4c4c8¸ôc ÚAƒCËØKÛ¹tÌŒ–ý3Ö°uÐŽ’…±Q¶B×Ñu”AaÏ{:»NôÜóüžçù½¿÷µï=qêt¡žßMç§šòì&B‘8B(Óï˜K†S2ݲcµ=Ó‰†žuÑ SF»]ò=«áŠÌkM³/Ät:¨²ÝªZµžšé•vÙhU«a6¬¥¨Ùr}Ç,U,'b¯Ä¶+­V¹Á:»Ý¦Ó0ZµH*…/Zíî²cžÙe:ŽíôoƒÝ:ŒhÕ04߉•ífÓlydûÙlú%é¹Ä²–ë•<»´dµ çqž‰®:–g–˜ÛÓáÛ°k¬Ë«;öê˜Z ²@¬j÷ìxxÉvzËun–švÅì*7L£E:-T LoÅl˜Ðß4Êu‰IÀ”Z2¦Ë›À‚/C©b0z;ÅA]—ý=qÕjTʆS‰6ì†Û³ÃHd_Lh~Ù¶ZR0Äö`ñn/pòCªýlî®çÁÑÏ»¥ÇGåä‚–ÎŒj£Ã£w0¼#‡Ð PE¿gƒ ÎgL‹r$?¬pÊž¢Bñ,•±@=-S¬ÒYLU]ÐÅI(©5¼A_‘i„%X4"óÊ›'hÉ´@0¯H„&äXBP4Š!¤¨´ ”æ|<éce#yUóå/Ëþ>ºñ¥(9Ëi9_ôUeZEÙi•̤ülA£Ñ4 ‡™„ )æiT†X±3YM@`1eg!F.‘|""籌ó³XÎó2Žñ±DlV ‹ŒQ J;—¿ƒLÊ—£„P-¯Fp^‡UÚrL§QC.ÑÂ%Ðã GS>Þ8nrÅ;€W›½ ºÄ`¹–[Ók»&­É¹5urM½ÝYk{&µ–øvWñÆLeôÖ‹HP¶˜Òq$sí1wék˜»‰GGîZQ˜ »·ˆÇëÁf…äq‹ä&ânvtkâï¸*1~ ã$•4ªB‰.(·SÂ…kDAy=úÝÀ¢òån[F0•yA åUªÃúÖ‰ÆkÒ!ÊËëD 7–Ç]Ê› w[ß4–¹`à… #¸].w)Ò0áÄ$€dòöï\¯ããcŸ®\ýóÓÏD>{JúÙØÚëÂc[ÿùê¤.ùçÞèýï¿Zú‚zü[/m®šW®îÙüÎ_®ËÛÏ?÷Æ‹¹ë¯^þÛûGÞu‹ŸüãåñGÏ ßüÉù……<éO~ý÷ÿð±…[óYtÒ.³µ ÷:î#Û-\?ÛÃÑP¯D¨y$<GBŸ½/‡~ß”ç9lϾÛ`UõHáón+xhôÄætlð½U«ðSé­î¹É//Ï̵ªS<Ïð‚ ·»å²€PARp'(¹~³ ouè¶}^¨+(xɲg­ ]-üŠYA=~«bV­–Y©cÈU*(:}vîäléÌÜCùÔ?®eƵ‰ÌÑR&;>¡ç¶Aâ£3󥹇OœZA½5ËS2åÜDõhy'}êL1LwŸÎèÓZv9`{Þt\ »‚ºô±cc:‹ñžÕ4ëÝKÀÿ=C4ˆ!ŒL@ݵ}§l® ñtÝnšéJÛpª–祗 ·n§ƒ+BÚuÊé»ngcp[ZFSK®ÇëÿPK’KA\ 8ý#P6rebar_eunit.beamŒX[pÕ™îÖéѵtä–zlùn{Æ·<H6²Û’å ¶° 6 aÔšif†ž_DœÀbɹ@vÙ,† ! sI¸$a¶jý²oûÀ>míÓRµµ[µUÙï?§%°MÖU£îþÏþË÷_μÿÐáaM»ãîñɽ÷ïmÖæ5­û5MÓþ½; fü0´ªåfLþí Š_-u ÅgË• Rž1ƒj£ùb9ì¨0 µbÀKA3_÷›s]~±(_|£¶‚¥Ï…Hp«Y®4ÌÙrµ˜'iX¥Üh6b³µJ±b)¢+¾îbP šA>ð sF¡žíȺ°RÈjóup†½ÅZ„ÅïØLàÏ7ºê~Ø,7˵jG:Ý ˜çÏ‚OyÖUku©¹‹ ?éWZAlÖ¯4‚˜?S ›¼¹+T¿ çóál—ÜJ^ÇiSáT‘“©U>0«•«<˜)WiYÔƒp¶†=JW«Z àpPŒ5ZåfУ|(Ôª³å’I’J•ÚŒ_1HX¼¡$Í Ñìl4ÃrµÔÙ¬â½ÄªL¨Õ› ³ÜÈŸ ™Z#0—©2äX¢)-œð¡åþEª„J’4ö)òl9l4UXVÑŽ¶o<^PìxéjúöOúå ›|`¢›à¶ÄЩÞW'¢J¶Î©Ã‡¦&w)(òåY½HbM‘/W •V1ˆ8’‹aPjUüÕ[ÍX1˜i•º|•Z‰á·u¡0„ü›GHf*A1úò«~åÌBŸ­øÍfP5ˆo{(©:ʵNÚî7mÅ\àÍEÝŠV¨ãîjm‰“S­–©Päk¬ÑDÒÅ‚0¬…«ü Ïä%-(@¢ÚS k­zU·LJ£\­ÅšsaíTß sóóµb'~­JÀå‚_ âÑZìÔ\¹0'£@q+/Åο臥þ9?"æ)ò³­j·’'Ellû˜I,sÒ„ÞÈ?• EEP©a¡ØS­UóÁi¤Ò¯zY8­³0תžh9ê(¥ŠÁ¿R.Uó@J Š ¶ªM=¹v*DúÃbp:&ß×]EÏ7‚Umg¹FjíQY„A¿5‚ž2³ÇGóÊ7k2éMdC!¨6‰i(†þS-¬ÂΠæˆEPøõzžÊ¶Ñ·J¹à“J[ùžo#5l„¯ÙjägJ˜åÞQ Ë'ƒN¿oú3,@⹃Éš êóE£Ñ¬ÕÍ*ÔžÂjPé>Q®`å4pkÄZ”kÃu [e[P=‰ž6 J.eqXjÍóFœ8[•&O§ªîžv†Þù ,RŠ”P,š]³am^z“«ñ‹¨+1dp›Ïø ÙÖâ(Bz®[——’"~‚Õ)¹† —+ù"’*Ÿ¯ÁôZhì;tì Ý,ϵV3OÌȨ<À4^Íë~«DÛ—Êbõ ¨—c´…U ‚úš¯0äg}JÉUä}[ޝM¯D`ûŽ4ª í¦·¤¯óöaÉ2œ–ÝÔ¿Èê¦oú:–J!õ¨‹§›î!œ)÷(MW§ÛB¿$iÝW¨m›#0¥_«Ð !K–Ťs>˜Ÿ B“Œ˜ùá3åWÁÔæ"N­ºAÒ7¥¯:#MÃx§c²©vËD"[ª'¯¿cž;Ò8Õ"°®Ï©¼Øœ¾FmwÛ86¤W劵Ó×jx;¾~y8݉ã¹ÔœûZ.7L_·mÏDŠþ2Ïðÿƒ‡|½Šg)Cצ—{3ˆË táä Ë3­fÀpNúê.¿ñxpºŽ¶ÒøFöµéå3,R¨¢›X¹°hÞUÜ×%ðâ AÇÆ@zÅ·„ȪÅUB-eÃU|Ëv]{MYqí5eÈútû8´,Q­åå`!«lCzÅì¶Bˆ­„¬Ê¤.ÃÑ€V.+›ºåyy­u%’‡µZ“’~ÕÒ¢J%6¶sl%ÍMk8c5mãqÌé–¦þ½¢iú<ïÓ­Žþ-ŽîôN[;jhz9ÍŽ;Zܲ†Z,4´YIˆkŽÇö/n¹ø¾ †¸åÑ›—³l/ç°¸3屬úrÕWª¤yÙ¤×a{,w§ãVDÑw*é%X_;1 "vi^΃Ús’v”–¸D€Ø—»/â…Å­‹PT²°%î\m±-æŒ3ÍgVÂË2ÏÎVºßc¶Òá|N¯YÏhqQRàLá£ÇcIR”yɬáˆÝ+E&‡Zvè%†&j3¼qÎ{,Cï03Ù¾”áŠmR#ŒÞ bßQ¼ ¦ËIÏ\Çâî7`»X0à]¾ÝÜ8©»žÁú 0=®{ÛÌ0}F œ_èSÞ>vaøR²~ÍÖ§ïezýn¦Ÿëè779ºä Å-ý"›5ýR¦Å5ÞGˆq‡÷kúçXتéW–¦£…/°p“£Ùë!´) æ™ƒ¶gÞ åÜnˆ|HÈ­ð^âÏCŠb¦Ù—êËÂÿ~ʃ]p­e&ƒõ[¶Î-ÍûH¥«óþ!‘Hšƒ=–³Û¶g'I]’¯Ö¹½Ç;=Ž»;!VKµõh} ÖåJ1¯Þ“èwÀ¼’]Kç=Ú€¹®Ø´ÅÀ-ÖšÅ:¯õrçØ˜X¯óu^ìYOA4wØ^Gvz#î‚¶Œ;ÄmÜ|#dgñqC¯gQþhbÃc3€ñÌÛåö,S{ ϼcI(“)ÊEMÛ—Š^XÐåX“¹>“"YRfd¬#iæˆMn‘Ds4ZåXƒY7¼šÎ7!Â^î"xw¡/Á±»`$5æ‹9" .Ü»ñÜ,¹?÷p_··Ì½w‘{ ¸Ç']±ÅÞe‹-f `nÕyÊš²ö;vΜȱI»ƒ! [=ù¸ »öy:ìu=3Æ×³‰!që„9HpÙÌ3÷#˜†—|ø™å¾ð̈Ë-:¿y1¶ýÈ :¿E•±g'.XÈ7Xž6it°É È}i÷!÷Ò7R¢Q&ÜêM°~/C°â~$Û¶×Å~Rin„¿_ ;6y  HEóÄm`LÓ˜}›+Ò”9irv;œÅÚv2Êd4lÔÜn>Ièï'Xs€µÊݽ®å™EðQîŠðæ@;‚Á^(îˆ÷êü0ÁË‚0„3>¡Ÿ° Câ@&EÝéˆáÈ©ûeQØòp£ô@Kø†ÂB?ü^ÙÊ@v›5-ɨD6™¢jäkmìX‚!Úq€Ü¹žÌÁ“ûU{†¢Ã®˜¢T™¢”<ˆl9¤óƒ±ŽŠH÷!yLY®ê3åú!›ÆÚøž‡‘‘žy®kúoÝ1~Û¢©GÀ1¤<ÚãP)QêÁjW#µÇ¦ÍªxЬ‰‡ÌºxHçªvkñí£â8 =Þž(Çms92&Žéü!0êüL]o_°Ð»¹{Í!¨@ÿ8¡oeFÄñÌÞÌÄã2D Ö‚Ù¹rÃoXOeÅñ#ˆÁKóžÂ¤!þµÝ«ã”õjë®x8³+#&¿ Ñù7ÏÆ\>œìKZž»ßÍäXÎÎ%½ Uà#W“¾I§Ò£=®ÓgPߢž¢°j¯<Ì·;˜—e¶A–£ÒÙŽû+yh©4ÐtÖ¶1‰$~#EÂ÷h‚èK-n¤Åei‹-j«ü”ä €i˜}}×ÏŠ™¤jM3Ôw“f<§<ƒÌ߄ښQX¶^õr û¥vBΧ`¦–gTçUÓ(™Q`¡åhÄÕGL›¯Ç„µ-+¥iàPªS$J“-àHÊßÒ–˜¤Kr©—ž@BTìðàÍVK̃ÙkyÓK/«NŒgcϲuþ³<|r<¥Žƒ•.RPèÄÝbM“7l2Ç·¢r F|7aÞá):K¦”`ÊY˜2§ºýí`¤»€åÉcf2§Ê„2XŸDþ<6$N0lÜ7S@NôhÎÙ˜Ãï`¶mÝéàb9>Ô|{Ðz4ˆ jƒ>ºŠƒN‘>œA-›ÔØ·±çNFçÚDÝ‚i—^¢§ðœWsì(άÆgägð¬õ¢WibMàŸ¨Ej|§šZwÉ‘ìYw ,žKäŒ\JöyÚÕ!‚æ¨ÇGE(×™×ãZ: qæH)®h» ÑpPe¡ÎqpØC¢aãúÃo¥Å "`Ão7ÌyAç Ùü1¼À²¤Ö#eƒ¥óþC™ –NK‹eÑãÂB+øyæ½óZ½’ñp„ŽÔ!äó¬8I'Ð69p.ÎAjà> ¥KÑİ8…Ÿ‚°— ìôˆøë²ö²ì>hö(—£™õ ”\Üg¨(²„Û^‚P¾Q&¤e&D½?7ÍìIÃV3©ó3{RxÁ±¼$ÚûÅ‚Žˆ…äÞd§ÐB«w<ƒS(cÆ3úàÂóé¬XÀ1¿PÈz åÓOÈ¢1ñ„ÎäÄþµ(óe2r¾ -çÚµœ£«šQú<:2²9ä>BCCŠèI°?ÙÎþ$.=ÔÖÏêüÛØÌÌGPÀ:?Ù© Ž«Ò,Oü6{ l´»+mŽ£ ±ÀßÉŠSL5¦'©¤ÎÑ)ø] ÿSË÷FÅwíø9²ëŽÛÈ5Û¢ã÷iT)ò♥©~îûʇQú‚š[B*uù$¨û# •Õé§ ëg0äi:qs|»­ºtNM›>°ínOº³]R0.-^Iè~ˆ­aî3jZQ= Ï·cxž{^6+ÎOx™è6ÅÝ+q~1/@Øë <;,~ÀzKÞ3Þ ¯^ÏÁ°{`ß+â9?7 ¾ÏFÅóÐó<›ZÔƒ:ÌŒ3Éñ¼mþ3æø›4VÓ¸O3Õóki÷÷׋çÖ Zk,W£)Ñ|3—@§º^ü@Eã¯aÇ[h/x¯³NK¼¤ó‰Ë^Ú&~Ìt˜6—?TwÈ^W‘Rí¾³1}êºþRYÝ9ø®¸?BÒà¯m–¤»¢CeØ*I[¾üØ3ߦË:F³Ÿ@ç Xñ²×O”ûuþ Q`ÅO ~Pçâ;èÊ‹,…€Wñù.\ù»Qñ*àyuéXÍ,ÝNºƒÔÏÀx Œßéˆïéü5|¾ÙGÄl/³“£âuäßëÈ?ÇEö1dŸ¡¦º©öü˜ZÊ<ê ÑuÏÈ%&m¦\{vÄ‹:#+^#ÿªÞ‡ªŸƒü¬ÎßÄçøüňxŸáú¼—±,µg‹?0$Þb¸RQ¿%“á#™â?<$~I+òJø+ÿÀS;¢ó_Q+Â}Úü=l‡·‰_'íþ˜©­oƒ ó_«Ý¿ÑùÛrõ¦öÿÆïRW^PÞ¹,.éüpŒ‰ßêü]²Î;$Þ³/ëüâ7&ðò]9éÀTCîúOšå[§ùitè•­ã²ú¿&ÏÎâ^Oíš& ƒ©x?+Þ$>*Ÿ!<Žˆß!ÉÌ6ñQÒüCëÑ4…{A&¡@z¦ñÝPpEý‰ð¦6ÄôCÿ.+> Y¿‡¬?aüxDü²hÂü ægNÏÔ4†Lcòö›¢ÿ›9²ppÅiþ£á“ËâS¢<áOå)ä)§Ž ‰?a´aÿ'ÿÿV Xeža`GEÐrjµøÃ…•p_w]ïºHj&à‚rÐò’–I–R©4ñZ^È?3--+ïo¤(T”ò’âýÒ¾ÝC|ùüÿóüû) LÖŠ³Äh€£…½´ê>¢>–߯{8ð•} rÐ$ⴲ؋ã4*çï)òÃUNR5œ*i@å 8Dì#K1þ1«b2P)Â"QûAâ°I(ÅDŽ@"G$Ãß9L'rÄ•Èa–/U„¢rTÈ,,R8ÊE´²læ™fN¶¨’¿j‘T#§‘…t1Q´rnѳúCž1¼‘ãe¾¡ƒp=)¡ã $!R ”õêtw‘Áq/ '5®\NªÊ€YÌŸ#…2`–qX[kÁ•I2”c1K¢m†{"aÑqΫÍ(‰†Ä>².†‹‘ 0:R‡ ,:R8R§8g/8*- hSuÕ¦ƒjTÉeõ7¸º=GdydªÑ_å:AE#»ÕKŽ?7G¡ü*zGU»î¸ƒ:U…SÅòç¡’d2< »´Ö$Ôã.­ƒúëœõ¡~KˆPgô.ƒÎª½Äòu®]ZËòõŠp¨\•Ÿ¡ÎK&¡ë¼ u^ÖÉÍu†—m,|Y¼õZqyÀ äz‰Îõ²+;X¡A.B•¸ÊP?êWMÂo¨Þê-êà°Ã&›mŒÝl¡vïÑZy¦*éÔ’:ÙYFÿþò_ý¸ Š®¯²üoŠp…Tò;¬uî\UÙ*¹é¬œŽ£WÉíÄò×áv9´ë†IøÛuÚu“´K„¼ná‡Q6!/#©ú¦Å¡¡aª Œt½7]}¼Áò(Âu²ú-?ò·MBÓßÇÎ(zìÜþ/c§In‰; Qw#…;°ï#&:Ï9G¨©ªs,DèðTø×#…{x#Ó@ îI®#v±û vÔ˜„‡‘„@¥/ͺ¦‡ŠpŸ¤ñˆ¿B›„?9­A¢?Ù¶Î=k3è.šÓ3ªwáÉVá)Ë?ùëÁ<†ú”ÞÐéþT„G°@0?˜…U*E6ØÍ¤çšÓƒf ¡ÒÓ»Qì`Nѳ„­bÝMzOçsì¢÷¼«É Ñ!Ïæy8•Þ öTô¢ÀƒB (x™ôÞÿki/ZÂ[Ñó„èÄó@ÔšôEMµ4QPô>„è ÄZ ¶2éEú£’±öMnE“EEïKÈ­\d?“^¢V{¡›ä)3´€- )úÖDÀ.@-#"‰éãÎ'p,GöKp[hÙà_Y†?%OU2‡%k eø­Skv0èƒÈÓ P·êÛywвÁíD™±jü[98PEÔãl¹Ž8>±™áªY0 ŒÓ€¹¹ƒy€±`<˜ãúìMùµˆ0_ä¶Q¯5˜Æ,aŒ?XŒ!ܶC¸CîµCÖžŠý$‡ç)}™ÊçEÌYÖ ãÿö â°.O~ëñ FÅwE‚˜ÁݳR=‰¡zØý$&ýýÁP:VĤö!T†Rxr›k!~XUËô{s&þ1T?“˜DŒ!þ±wúH-ã©üGSx¥3 ý°j­7©Ü¦ žFåLb¦SømJ&å—òÏBüØl*ÿ(<ñ<°ù_ö!úP˜ôvÆ,+Dósd1ÿ¨˜%ˆ?[Fá"\Ÿàåè'Ïk%ÓòìVQµ|NÕ¸ý$·bÌá °Tü—Ï`7ìÃf¦en¥b¶!n>;Ígó»gÖmÖÙEõöC ï¡â¡Ÿœ‘LË8Ë´ìŸ_˜–szi9uT.Ry^¦ü¤W¬u ™KŒÂ¸æQÆ.EL>Ÿ€uDž^Ö'/ ¸ì¬µÁågǸ-——K.M¶ j3n¯–Í€Kþ¾‹z ÔƒÌ ÓøûæÌhÆ“3|ý¿b®,39€àRô“^¸;u:n —#È'ýòpúvr~£Ÿ¬ãI¸š’“+àZ‚:?3®=Éxt¯ {ñ úO`ýŒæ‡ ä|@ÿ1¦yNsADÿ¬k-˜‰wèKöÖ×Oú®uö!?ú\¾Bÿr|v,÷ãÚ¹pÝ„y’}ïëÌÇÿÖ;Òr¡çôÉ}ñ”å)q¯gŸ6øGØ+&TvcÃg¥ñkü•NeñïyMª>pzmiì ¢Eå¾Û£ãŸ¸µç‰†Âõí‡|qmÇ£ûÑç·ˆu+ıw¾ôŸ¿âÝ®‹ºÉ›…-°o=óÍÙ†#S‡, ‹.2È¡%ÊYëÄ ½Þº5²P‰_PÐùˆoà©åŠ?û¬ËÊÆíA­‹–È Ó¼jœ}¾ÿ§#"_(jÓsõ˜îGÂÛ·LÉ8Es4ªîµ+ヶ×ÍÖ;¡Ä:êzÃGŸlZ·}ýKÑókCwïq$®©®]Ü?yÓ–OG Œ;[‘Þûf•¥êÚ…š×{÷<÷ñé¨Y7ZOþΰ;ôDpnŸ “®Ç ¿Òº8ûZû¦ÐãÏhã»#tÙªïK|™Qÿhíp·.¦ÞO8³MùhNˆQkݼmi—'[goxçDìñâ>…ÓLÑ ÂèÍA¯åoo×¶wjú¬5ÉõóªVÆÍÝòüÜ㦬?gvú<Šhì¾sâºóågŸKÜw:*ј?^ZÓÍ{E|}AÔôïN®l?zèÜÛñëv­ZV}«mdtõÌ„ÍE…¥ÓÞH¸?oÚôÏ‚ÿ³ÃÂ>¥ƒ~Xq¨æÚĸòAMe™ýô+9jÞ›¾­2v@„—ד-"aˆ¹—ßÂÖ7WWÞ¿]ѽ୷µåÅÖï‹n4-(xmx»GGÿž>ênÒô+gëŠîõ/N ŸWó$ÞÞ(wY;¦Wcr"sÄÐyE¶­”ä¢oÞ‘?~n«Ï•Šœ` U;3ãëM%Víî8Ýþt[’¼d­­_Éʆ’o;¨„ÜiÉnŒZd-\ÒyäÀáƒTöhïg z)§ãE« ´]w±ÃuíÖâÅÖèø¼êšÚöëúØ·×—¯’fU(ïÛ‡h+ÏÔùîYé#¼Wfï1#RjìÉ.ÝüžÅÇ>ß1-°ÿB÷}Ù»_vÊwrÁcZ씲ÚWu\|òÃÛ¿¤%,/[ØvS«+OŠŽ8.W§ªó¯fm†¡GªN]xr·ü™S (^½o€Ñ×gcv»®ž ýªó‚n£ž‹÷iz°¦@öyÏía•²íä|$3®÷z&Ñs¨1y_ªELfØyÄä|Ö &g¾ 1™/•ˆ›g¹>;‡çþÁ3³í âÛ`åˆo<3çN!¾ŠóÇ ó=‰ñµ8gÜ0zÒóžyôœ£g=Ïè¶×"¼}ˆIì^Ä些qÍÞ`?!—ü÷}‹1럙[¯~fþÑ3žs0þ_ˆÉg!ØôÏE-Â}lÓòß¹ý³OüSOpX âIÈ'Ÿl°|Ä™`ï N:Ø ŒO{ q ØTÌ™¼ËOÆø1¸éÏ(Ô"þ8Ô"Üa¨Eð@0;b²WGb|°xôG Ƶ‘CôC?y¯îþ—ÁÌLË|¬ëÔ"ò_® >y·7 &gä%ÔôCÜüÓ¹j‘O¯Ü\òœOÞØT·d†{3'Ëù#KdÚN˵¼ÈfߣMÕ-=Ý1=Ý›5Žü;;ã5$Þ3{bnZvVqx&3BŠÃ‘íHÈÉËÌLrL%Ùy¹ÉiŽ F“26-‹xØ´ Æ3-Ë>!/9%™ñÊËJN—–•’œ gžMNf¼ÍÃcôNˆ‹hÍ`Z…º†L]#ºÃMJdso±%Äê38ƒñŸ–+wµGšÆEØÿº=8nÞöÖU1ŒéÎlßLqä@ºŒ»Ú-T!>MnZfJª¼Ó{V%ñIb’Ô!©«3õœì<‡=%ƒ KÍÎL Kž˜ä—–›66)'5;Ì‘26É–ã°»PBJ^VZnhŠcB:ÓklN.iðPK’KA–ØœQ¸Ä rebar_file_utils.beam}W lç¾ów¶'_|ο q|Ž “BÏ Ž @ ¬[÷ã8öپľ3wg~4ZQu?ÙZVÚuEl£?¬ÒT&”i mPÁ&4D;Ú©k)•¦ý FY'­­ö~çsp#1K¯üÞû½ßû<ïÏ÷=¼ykˆ¢¸SƒñØÃ1S+Rý{Š¢Va]OéɬR“eS)N½˜Ô³Í`Ì=%Ù¹KQýLYUv»‰OAgw)…L:¥g\²^H©9G àÐ&]Š–„EWVÓ‹)ÓYP Ópg )Ó”Õº †Þaä™t)©»ÁQN¥ó.ÃÔ5ÇLhŠê(îd ˆš*Ê5e*;-Õ)뺦×eä‚lÊI²‰!^®ŠÁ%«š¬šs*-‡@œf^×v5ÖlIf=i%S·;­•öTt€å̼‡0ªXS/ËÎlª`Èìxʰ°ÅÔ¤Lx#©Ë¹r!¥{dÕ(ë–•!ñ\°:'éTIN¥TZ6ºìÖåRôº¢–)C5«ÍËÉf²æÙ¸‡ì dËj@ ̵Œ3Þêc!Ýþe1°Zú=5¤edŠrýz‹©Êg dd.Þ¥˜ê1–㦨¨Œúe$ "Še~€—›¥­«Æã´(1¨q[n æbâÁ"ñŒ[๱k;šÃ¦àiyòR<-͘z±€ãÈÁK ¹Ñ%)y·°\‚4ˆû–Ï zl=¢K¯Ç+Ðûê$ä#ÄΡþs6±s@ìûîøQú@ä(ÉÇO ”[³#‘|¨Á¸k¥„0%,á8ãðÇ‘Ÿ8J i‹ŸßcqXœ—€E“@ߨ…Fâ}j'<8õƒT˜pNÑlø£išm†Æ9aršm‰p>€A+Ÿàm¾ [ˆ`4 8©fu„ŽÌÎaÉÁ ·¶-Œpóíp‹HB‹!ÜR€YRÛÉûwéøì.µA¾mµù¶ñÓ{â?êäU›%ÌnÖ™û7«ðZ ¼Ú—?ÊõDሰÈõøü\O³äYƵ{:¸.šm/¼xa§†y< ^CC¶×2ðê¤Ùeõâ$FÒh%ÍKä¤ú*'õ†ßêæ:PâR'’tH _X¬ir\n‰å`Qí¬‡S5ŠHµÂЋ\ .hÁ.Ø4»œäÎX¯œ¯÷Ï}…”¸E,>lC”[ Ékë„yªNcdñý#®„-äú©ä2‹×ÿ¯[7$ Ùn’%òY…c쪑bÂT;†Làü0dz ÊÂ÷Àz£×b%ØütõHõK ó¤‚/oGC ˜D”ÃÕöøÆ3M¸w—±Ar&D21!˜˜€÷B=à„±Þ0¹ß6I¬fð(‹H^´ ³4»ŠXÀ}5‰ Fm¢ÙÀØ S×g#Ça†•ßbe]¥’A¡Q»ŒQ‚ß{ðw ž*ËÚË’å5°¼µ}ÜCÕs[¹ì—¹É)fòbØõP„[CŽ©WÁÆX·îS· WlœL[šÕÁ BÆhv°rÖcÀd¨Ò%òJª ¼.ÂI$p|=B£¦¾¼ôFŠ%ø¦[@mA Œý>„{bAh9 H=gësAæÙ>ä=ÚPcçmÝÒhë£Åö_²ÐÖƒ,±ñ –Pƒë·u²·³F¯Æ$q–ÛvÂyE¾²«Ëö'önÛÞ´s&X¡\¢;â»I}¨ .Ñ^_mëä™oÛ §¦šxmµ¿‰c¸¬n³÷[Øþ°ãÑôÜwÂw¯mï³÷Ñα•…ŠIúµ–æì>ü¥çbP-]¾ÒôôÔbßc Åk^ØþìâSì'ÔÙ/¼T8ôú‰ßuL>¸¹ìà';’ÓøÉAñοN¿µá×-ò3åkÆÕÕ˸±ëƒ'“^?v±)÷ƒ·¿õ\ù‹×¾ý³WÏm<¼hÁû¯ ?¶ÿ«¡·ß’~qÖþ¶'ï=|rhù¦-fg#w½Ô{ôúñWðÅ §ñ Ç^¾Ú=ïâ«O>ûñÓ×ö®tv¾¶âùÒ+\í¢ÔÜ7ã8}½ëƒ=Y·âðÇšÿèü£‹¤\hÌ‹ŒÉu{ùË¥ o,ÿï7ws·õèå+ÿÜ÷äçéøëŽïDÆÿxvÿKâ/?:ôá{ù¶Gÿqä½3?|ãOë•Äå ¯}]}¼Ü|*ôD¾ÿvù/Ýï—?ÿÓKøû×uá·µé™ó;Þ½q÷ÊŸO¸Çv~ã7·ÜÊC-µÝí;Øöæwž:|sdÝ÷G7Ïîß ÍÕÒ¤»O«ìzÇì}í¬>Õö&`û[»m'3»ÔÖÉ\·Uç0fš:™×§ Ä’wd(´ÓP­Sá ÅôéG>¼ùÎæ—}·óÊ‹C#jÖÚ-†ø»µ’©hªA î ÅY¿ú“F¹XLé{ˆƒK+›ð{’bäqE%Z™¤ÜŠš.”3r†šSV3rVQåLÁZ&Cy·l\—Ü6òp|’š×+†zžÐêd(ÜÛ‰VØÏ&G6 ož¤êrŠ)„ÒѾìêôÌòæm[ìe×ÖPdP OXlwʺt')g¤çž±1¦R”ó®qàÿNŠMá—Z˜ YÔ ­¬§åI*ÌkE9˜)¥ô¬bšAø‹‘ׂÖ— ¡§ƒ³ÿõÀ¬‰Ø¸a’ô?PK’KAA]n[Œrebar_lfe_compiler.beameT}Le~-›,.zÒ„iféµ| p1ײRamVX¦ K¹{Ûmï.w×Áô-ˆ:ãÌMæ‚q™FF2·%Ä ÅÄ©Q£d‘…0£ÑŒ?¦q›Š‹ÑÍ÷Ê¡F/yî}Ïïyïs¿»{[#»¼˜†A‡_“r€ë•ö%”x6 㜔“…,T,ÆÄ®“IAQ5tÏBµdMÊIbRHYSP‹gUs®±} õŸ „’‹@/m]/OrMiK—ˆ’‡ƒ¨‚ ¦LPQ$¥Èð"¥3T² ”ÒÒŠ4`EA\’5Õ¬@YR4Rw„K™âœÄçÑ&‚˜”캥ÅånÂÇçNæE7ãFÜ‚  áw ¬]‡JL…;ªhŒ.£)w±>'KTXÀd °!Pˆ¨6D»ØcI”åØ Â*S4ÆàŽ!cKh-aG ÖEZ(zk1φX'*vˆìaa6%¬ °(ksè–$ÊI´ ÕKmN õºÐMv9Qñò m‚D3$èœ[¡Ó¶µm ´ë5jјŒ;lvu;©^lD)ìU–pê -co!¦’ÁÞ33A€˜¦têÎÉúÈ#XH½HÌ6„b ¡ Ánhôþ•|Bnðwüúöº×X»ÑÈÛŒ90<àëhÍ‹º~³¡«4Ö•Z€?sö£vAC¬ áéÁ—;FÞÌ3>kKoßô'1ûƒùž±G·ËµæÏQ×–#——ž;¿0*~@éY=ò󥡥 O|öÖ×G/TÎðÚØáž›ÍÏoq»`›=||¥¦zðÌO¡ÑS›®öl{XÚ3v}ðpðí½OI§^šûôÚ³7­+g#_´äzºûz®˜†Ÿ¬w4øO¶M}µ:¦=6  ¤o e.¿>±Ô:15?ÐÝÜöÆx׋ZÝü ”ûcU¶žß±8~gjîm§#ßj«¿œ.zçñÛ_¸V=×°úfÕÂkÍ¥øäIß n¦lyw“ÿ;ÓÅߎ_˜ýæ¾úìÌÄädìîEmqêsòêC+SÎìˆ|â}{úWËôýÃÊîw…_ùäRôØž£»Àôrö í·ÞOü?ý´sÒ¯iŠþŽžÈê]Oã< ö©b!)pî‘Xlðû•‹'ûù\SÏ­þþ–°˜D¹ê‚žÔõô‹ ’¨ê„…¥…ß:®æs¹„²_˜¥¼Æ J°Ou2À"ˆ\6ÏCåE&òiåxØ]áöñÎpG0ì>Æëc½ qo­¯±®i]dÝÝ‹‡w¶F2 8%h´—kjL6p§#Q#mÞå­ 0µý·û ¢"»`ª«ÙVS§s¤&ä`Ú܇ü/'¬ *QšØœð¬«R^á`Ô{ÒRzx9¡$Mó £/-y g—GU8ÏÿOÔtzõàïS5ýÛý PK’KAÿ¢Ä¦qtrebar_log.beamMUÍOGŸÙñÇÚxÂÚkbÂçš„Ô|¬ I!ÕB($í©öÚ»6‹×»îzM¨z±è±—)·ÚJ•*UŠªæR©—¨@ÕKÕK¹p¯8·Uߨ›„•~šß{óÞ⦅ììåŠØ«ë…‡ßm „§BjÌ3˺W´ÝZÈr,?zlze·e&zîŠëT­Z¼fúÅší–u;ôD÷ˆ¬ºaÓó\/l˜åv-Ö‚Û<6íõX¸«Ð§7›¶UÑ}Ëu¢<ÊtŽ·«½NˆÖzÎXÛ1̪å˜á½ø^Û Wu»eFLÏÖšË –©º^C÷)„êm;è;ÖmËèqÒ°ÒÐOúºÝûÝ{<Þ:tÛ¶ÁÏç­6=(zÒ×p¶mù¹úyC—l¸¤5×0j@%Ôû¶s€–„Ô$ÂJ¡¢CŒÈlD’èàl›Ü#íL'y{b?Ê›Xce–ž"̘×#»ì´GJì¬GšÜRßIøË’ØÏ2#*ûD5)÷=¹H!ó>Á? ©¸„ð (ËC`_Q–ÿ$wω²J¼J$5w._0•ðŒ?rç$ž‚RÜxþ†tYâ”Ð4F²LN÷T˜âB4MîÞJÑ4hee )tL£2ŒÊOÓd|€¦°˜dY’Ì©§XZN¦£ŠÆB²¨0(’b$¥ÉX”¡²˜†îŨ?„°x5w†Å ˜Ã¯(#éÞE†`á÷™&\o—Ó•’‚Åk0ùC sÌ–çæ(˜ DA£*oTÍt<:~J•28£“XŸ¡ª|¶Â©2C'åÓªbqBzO¦“æQõŒ»&á„\Qeñ¾fAyÒh–+g32½îѧtúŒÞÄâu¶xà ¶!ñušm(|½É64¾¾ð\ÄK‘m©‰ÅîÅY~<ð)‚ö}ï€?²ÍF“¯M@ ñ÷…P (à €<ø¯2\»ä¹ÄG/q€/qaý¤[÷#@0ìÏœ9ÀPÀyžô"]úÀÛDñ 7Ô㟰eù\ÿ6€|])•Jz©ôÊù½Zê’¸x¾·Ûùdåß—ÿ|õ˳Bá¿Âãæ³/~Üÿá×§zï³>.²åVx> îc"¨Áç™ÔŒõF=ñƒß÷`þÜæžCÁ@ä¸åt GBùÏ·Õ©¿Š÷#§Ÿî|ûáÑÑÚ¦S…½Ñn|ˆÇGÝ&Ÿl-ö¦N«ÝhèÞ§< â¶}Ãòê(d–-‡{°UGQË©ØmÃ4ÐÛ±wH`Ï0P|õÑæÖýâÁæÃõ:ê_Ðò ÚRþN1kaiqùuøxm¿¸¹ý`§Žúj–¯ä+ËKÕ;•7Û;»Ávd/¿¸ªÝ:êv ýíÖQxqîݹEî ùVÃ<Œ”¡ÿ—º¨K:ÕGô|·õ–Ûö*fÍ̺ sÞhê^Õòýù²Ct¾;Þç[^eþÍ?ÈŒê#¸‰B¹åóËþPK’KAeÕ3Ǻ$ rebar_neotoma_compiler.beamuW lw¿óÿâ»8¹öìs“¦ùè%ÎG“4ñùciÒ®í?I/£¡Cc€{±Ïö5Îuwn»ñ¡LÝ b¢”je¬UÖƒ­ÚªA›(*BŒR`TtŒR"( B[& ±Nl¼ÿù\LÇ"½øÝû¿÷{¿÷ñ·ÎÛ¶G(ŠoKŒnµYŠòœ£(*Ù`ªÓŠ™ÒUŒJ*m̵‚j²®ÂeŒtÊ4 ›5Jv*£™¾Y#S*¨)u¿íUÍ‚¢ç<ýýbdZ±ÔÛÈ,éõX£h[õe§´¡gµÊ©¶¬š¡×M£XÐ,Ûªcj¯R(©lFÍ*¥‚í³Œ’™v²Õ¹À„*ëâ2i#£ÖìËké|½nèà0šž«QMÓ0kË FÔØyÓØÇØfI­É*Ke­­XT3¾ŒQ!Íe៮̪)…(õ„XÊ6R äó–k÷B+Š%›!Îc†×U5cU Xb-hÓ|A@вšš©qêCŠþàRSͪ¦ª§ÕLª¨æ,ÆRá@W÷Õ)™LJ-¨³ªn×eÔBEg!9‰îŒxL•5ÕbAI«^ Ñ3µYÓ˜uœ9«4m›JÚf,í!µ¦¤CŸëÜÉizÖXJ:]õÜ6p'z86PHw~"Ž D|š•2Õ\© ˜èÏȳÇÐôô‘ÁG`³ŶU½®<Ÿ’­,•÷Z¶ ³óÚÆŒª[ÿÓVÈ–t¦ïöTlQ×6[@QÌeØg*ÿ̓ÜEžiÁèhi 0Š3B#G;IÅ(ˆ;E<†=Dô퇜£$%²…“£pç8N 1ÌìÀÁFiìqR²pqs¦eOà„@cì áâVY¢§<‹½»^’°È@Fx3"IDœ EOÀ'ôœ\BëP©qnìHôˆÏÿõí§éC8)#‘^€|ðq {àÿYðÈô…zYƨûD È`1È ¸ÿOÈ×€“X„äó2…}ˆ•§pr qÂnо‚ƒ"f .ÄÈ|ƒÌû!ïoľæ·|-¼@ß¼}^#ó¢Lsöµ¢€,Òœÿ^DsÈÜfq †ÔqBnǪ˜Dè+¡Wå:Œü ´æ„aB %}I”yBR,é %ƒ‰XA„?èïtZ]Æ9ÔÏ‘¯+€EPÀByP"ÍKîçñûjä–Én Ùýñ3¤C¤AЇ¥‡odT].­˜åg"œÃ¼ç%‘ø¦2iN:%ÐÜr@í—h®éöYê,qÅ ‚$$‚žXyªó‚€c¤ÃÍe€yb¥+œpÈ­˜k®Ç¹ C®ó¿«èóC+gáŠPâ\ '‰,†I8¹üA ÖÏ œŸÄ2"`D+ýuOW1ßh%+q"¡*pÁ~¾ÑPžÓÇB[¸éîx°\³ÞËHÀÊ h†z[ðoôUàhn%±@G$’Œ×Hsí`\ÆŽa¾ ÕKÂ(BL9ñr™ï&kÖ kÖ‡|Í|'Í9 €&$èt:$Ò¤‹ BvÅùvØu®›ì] ¯ßUÃ|/â%,"gãÉò$Ä”Â5¹ócȬ 4¢¯7Î÷¼>€ÚPýÃ| æª P"¹€PBD¡Dò”º'Ï’6ð2Z "!JCBHæeqÈËPT¿Ú×ÈÐÜjœ¼ €€–õü Í Àu¥¹Á÷3ë¯fŽó}„™L*½Ð‹Ö dÍ`Wëj¸ÖŠk N“°=q¯ükDQ;ls'ùr›œ-Â']µ Ä Â‚x@8Z÷³¤"©% K]=² „YÒäÚ Î ×¾Dr1‰½Ýµ‹ ®½d•kïésí«AÜïa¢VÙÃUºìÆFAb Œ‹wí«ÝïðŠ>T»¦Ê>\Ås­k¯èžwWÕµ¡Š3võQ1×dSæÑûIÏzI¯FÜ8ÉÕ)wžŠL”ôn-ä9éÆÅ]_Š>ÐEú’pÏ£.í¹2öâfÍ&ó}Ž6ïêØ‡×oû‘,”>´caüKBÝokÛÛ¾çh„žVÁŽžtã`ë±Ö§ïó'/í;?/xëú§nüî azð‘áë—:>{|Ùºäß6/®¨{µñØöísÚÙ>ýÊởYüW—lûì“w}d1¯)ïœù˳ùkolÑÚðmëÝOžìUòçú"‘ß|îÝ îàb+å}¶þjÂwÉå _n¼ñzË™æM¯ž9wòGo-|LÜûú}‹™çŸZûÕ%¿q:÷ûÅ5Ï5Q›4™ÏÇ|ªg²ÑÕûAÖ»:Ùuî¼:@"nl³ëG|Èêví în ÷þ\ä\Î}®ìœÏµ3£¶m’œÈm§óž …öZºó  Ô§ÑìÙ¦?Üuë+'ÎÝÚ³g|RÏÂYŸã϶üšm›¡xçÝ8e•fgóAâ@ÞgáÍ~†bÔiM'Z›¡XMOJ5CÕ–tx×t5“Gp–ÉP¾±]“›7¥vNnIÌPK£r$*G†R‘Xt8>Rqâîß‘šÜ:±m†ªËi¶I g‡Ò··íœr½Û#ñ19¶Ça»W5- ;CÕÄ× Æ‰±µY5ïþo(œ"(¼Ò¢Dêåß3ÔH8o̪áLQ1³šm‡áý=o„̰e¦ÃÿÿWÎ ü‚Ù—Ú²ÉüPK’KAD¶¦U° rebar_otp_app.beam…Wlw¿ó÷’»8¾ôß5i~´¹ÖI“6q|NÜ.irqp¼lm¥-ˆiÃ9Ûçæ’³ÏÜÛµCPÒ­êT@eDµAÆÆ(”‚öÇÆºŽ `B+‚ ƒR4`¬]hÒñ¾çKê­BDz¹wï}Þçû¾Ÿ÷µóÍØî©(Ežˆ'Fv8fž¢|§)ŠRxKK«VÊtŠ)µXd3f¾¨Úªr"©’£¶_·ÝÛÊ0ŽUÒªrªak¼aªY7žƒš*ͲL«¶\éVU©iÓr|æœx@5ô¬êh.8ofK†fÊÈŒYÈéûkökNÊ03ªÁz隢e Ývl7 °lÆÐÔB×IÊ1 C¯Îj†æhÕZÁÔ Ž¿hiPžÑl»Z³ µ°ß×ÝÍ’²vU¹ÄÜœvÈvLK«…”¡gTG7 Õº™2ôtuδòªã?héÐ6Y‚#¿ j^c³ºå>Õ´MžLÆÌjœšÍ¦Šª3sK”ªe×” Y-§´,¿rɽ3kÊ æ~Úì’áí‡VøíÈZ\ZµÝ&d®0Ì*gÆ2â¤'!kZY[s–™O‘Î.¥KÍ8lÎPG+´´^XÆW¥55o36 ­¶J‘6Wý+ޛÕE9ldÚ?*G¢a9\KHW\~?‘>h4ü?Óe¦QД¢ª†àŒbªüsl+Oc_pƒDKYªgÔ®HA"‹)ymG‹ÊÔ–t‚–Q¨•vÄH|ph­("¢'] \D;PÒä=G”G8Ô½(ÌcEN„|(!"AIRˆ“$™..âHêÐ9`VBHé‡ÅE`oS~ (S!Xª¾•å•.J>¢0Âq,)Kˆ•HT%ñÐýIå ʽp¢Ïú‚þ D_ì…!{á1Ððx~‘¾I¿…õŸdñôàU´í*’VÚ¾*Ì÷Ü ùè׃X ¯bxr˜¹z n”h.X§H йôíD¾$à@^y‘æ„>¾á–íDLtPhN|;§Ä@Q Å̯ÆŠï“xL %—’Ȇc™•Š D=jµ FÁâ#X`Òß’DJ=CD( b•“xÉ¡¤]R,ÓÀ$“h¸’»”´J"–t¶›_ÎA˜ÅXü ‹_')¸B¬¾„h j4‚˜æÖÔa¬ø»BŠ“ëæ›¿KIÊ‚âƒØfÄÊ×_¹¸ KI0I*Âr–´@±˜!›Ñ6°[ãà›A— RPÝL–nU{a­üZ4‚Býƒ|Kh˜ÄcY‰‡¨ÑxïãDÔMîQ„Ñc”±rdZ¡íµ1¾ÁxpF€³-“I`®Éɲ\=ôÜÄK†£ ¶@%D'ƒ`ÓÂq‰RæÝ}$‹ˆÃœ@ÑÜz`ìÆ Ý|Hðwñ”„ˆlúˆp6Tþè "&2rXP$ŠÐ辈^/«c|;â;h®ŽH r X!ÄähùÉ rHB¯dª"öz±\¿yn#PDo£XŽË·o§¶3Ï®ü•Kž%äPÞ é5ÞéíðܬÑæšh®›D@ä²J\3Í…!8ÁÞ>‚ qÙ$®¥<E`-œ·|d"1>Lf$Cñ0Gø>ø$KnuB€ÏDòBù(ß"ˆVôÅx™ô±~Ëÿ#ˆUl‰ñýH@ðe¹Ç±ö’/Ïñ|ž4ñ[ÁHŠ£=Ÿõü0?˜|Ï‚Õyyò\ïÅÉ»àáE°Õž¿¬©ÓìÅÉzk½õÚÀ$Cj×{þ°‡'~»çw€môün°›Ô†+ð²ÇCzˆVôÓçù1°-þVOz»£bïƒ=o«àÙñ>ßçá?@üÄýD[——ìq»‡íñ|ò³,èÕ¼§k;u‡Ìú¤¯Ýú¾“CwFÅcGg.ÎùÄüá /ܳøÖZ‹oÿµóó7þtoËË»â4|½çßWÎ?|8\ˆ î~ôïëüUcüô™á—þüÜ«ÇVw$4žøù³oÇ'6½»þl÷ôW‡{ä³­O–>õñé¶{_ŒÎ¾ûŸŸ^›ÿÝÏ>1µT³tñ©îK¯Ýulà©ÂÏ<ýÍÍ üázÓõ‰ËµcùâåÇ óþ%~éÆÅo}íâ7&f´ÿñÒÒÅ7Æ6þ­ç3çž_(4 ¥¾-'ž™øýì³Go¦ï~xmÝ UÕùûj¯’{þg¸ÒD˜O¾üÚš¦óg.¥í{úÂcG†¿ÿ‘u èÔ§?[sð/ú#]÷œúÉ“~½wóŽ_þãðŽ/}÷ÍÇ_lýʳGß:°çÃ'JKwþ«¦sñ¡Ï½ùÉSm»†ö}'´êsìW¬—"ÿüíwQÔN3Ct/z³P*æ;ìùä, y~/Ø€7.°þгñü6·|6:+æÞèŃ#ŽcŽ£ÉÎø²¹Sº/LuW&¾÷ÎÞW/-œ?#\þöµÙÙÑñBrë]¦\exZÊ¥z£©Ô¼|a[K¡ìåÇcu¯1Q%‚Y^­œ wtÌ-W¶æËCEo¤4îÕ£Áœ8û¨YõF­4>¹¼ROÔ¼j9_ð†¼] o¼^ªŒóèGÂÆ¦AµJ¥A ¹ú“ê¶Œ@‡2+Öv´Nb”p#ùrÝ‹4j^¸T™‘Çò )ÃõmÑš·Ã«Õ=1îyÅú¤a£´i¹´U”óõÆÐX¥X)yEmCÜ_U.oww³±ü®–¢·ub4¼±;F )cÆ&Æ}%‹ V®òå94švR¸R4vW½öixµ&Œ~4$Zªåk…mb‡½øÎR¹XÈ׊|,¿Ý™Ž”ó±|Õ‚ÊÖ˽B£ó'ÕFOŽæåwo…Ùv–…mÓ¶N€Fe¨X.Uj@y6šRn®ùjÕ*N#òŬRvÙª$»¹ST¾kÚi>C7>ŸàŠ3m„ðvUóãÅIPO% ŸLƒ9¢¼›B,?QnÔ#ÅR¡©UƆ(H[ƼڨmTÔlŽš©¸Ú‘¯E+µ"-ÀaE#Ø¡A¸R~kÙkñjµJ­¥Þ@ ë8A¥RmÉo…ÈášÇjã-ˆ*ÛD èxEÍ¢Û½Ý4×ÒÉ€–C¥qð(Oxs ìZ«TU^©ÈQK¢AFÉ_MRùž„œ±ÉAÝ ’éWÊÆ‹ϽZ£>T,Õ"…JÑS)D³(E?\?»¾»ÞðƆ(Ñg!ùÁcV¥®R|ñ×^÷ʈ¦É ÂbÈÕðBdÑQ8$àþh–Oá’Žòi 8»‘¯‘*”­Mã5 ÔÈ}F¨B@x1Eø´¥±­VÙ9;ˆR!Z/”'Šà ¾¯—®ð81¦°›üž€d¤ú\6Í“iß«ít¹ºlÍê5é5飀6€vº¥Ï5Yòu°ìÍKOzK¦—¶5ƒ‘µé̱ µÇ‚Ö ²ÓKÒGÇäj§i«ù险±zm@·<ý$ä I¥g$?¨§qí驺2¾0Ý\|f°[š>¦ÞÍÀ/NÏ,“3øÎOO߈风ՙ@Ið›qøÌpØÜ´:³¦,¢û•*¿_ÚAe„¾*‰É=‚åkÒœuõV|u(Š:zŽ£¬NÔT¨†B9¤](Ô~g¹òûðü«éá¶e¦f¶Úf""¤d–\kH7”‘½LZ©¨ ÉÔ¨ÆfίQó¤‘HÊ‹˜â¤NuyÌìe!£—éV§guy–Ùk…2½–ž³·ë-íò–uû5ÛÙ’q¶ää#¬Í64‰Y0mØÉLRæRQS—)ƒ¤JBœdÄóu€X¤?¶¤«òµÍQHeDM²È%nÚ¶6|Ӫᶸaj{æè¦ñ0ë:Ü$âa«ëp“ˆ‡ â!ˆxÛÁ‡´›œCçQ7´û1 †Ë\dÔ”ÚDמÄ&Ïb“¤®½,ÃÆ,SèÚš›×}ò¤4R‘ø4ðâZÉ RÈHFtqÍ,‚m¤kXÀJM.°}º5¥O–Hªa«o€ ûtë j"Œbçµèb{Hã ÒŽÿ¶ÖPˆøÆç³¨9€m_—® “ O×Pêú&Óp]é²~#ÌÚB†Æ /†ÉVÓ”)Õ«J$òH‹-æy-²5>¯U·¥‰š{”i¤®ñv L æ;bShhµ‰>lpû&¬Y Ã_fÌ’b‘Ƃ’_”KXkU&"‰dc›e&%-G}’ÜK•!hò'Øb)[ÏÄÒvO‰Åñåâx/ÖÍP‘¢f˜¢F¦Šûl‰ØQªÒÉÀæ-{ï/ÅUæ~es˜ìbÚ£ý&Y´d$##QŒHq¥2åÆW¸N¿†Y&‘TFö³%7+ÎU/qÄB„6;ORãKÏb7¡oŒxB«n"¤Á¢ú³¾Ó¡ Ƴ[^Ž0v|Ö®ÆZË)£5¤+ì¦ù¾JÍ(ÒdýmTç”'«:Är¦‘HIÒ±Ï ÉøZÊ_îS/×%Ö'±‚õGƒîMF°dv OD’¬ÍĪ! N â!¾N„…ÍÛ:Ä _ßcSì;¹º­bê  eü}VøAìãO ð·LãOƧa‡SšµY M¢!n(Z‹òä¶øU@ž&ïy‚jå,]¼ªñ4¦ë1]Õ)Òléöa)VÛbµ)•«Qà žÔ¸M†ýtµ¶S¬±6Xb dlá˜bÆ3­Ã6$J…Ók™¹^ËÞ,YŸÌ1Êo]œFi©‹N2¼C‚?@éìøéì$(¡%A6SIks¢õzUß4l¸ñ®ãnv“nÄWgâ8ú€=Y›°áà&i¹7çºáY¶X«ñuM _§ðöÔp[/´?­UW±?Ý KÆW­ü8•¤|ðY(Më:a´W4Þ…i.X/ ‹,n1Ô´—4¾ð>À»;ÅF£ Ùk„¬^CÏtˆV|EkHÊ =ð òaÊ11ÀßéàѲCô0÷~±gNã=>ºèM$çKŒDÏŠ>Öà «Cô±Ux[îÃÒ}Ò/Š!ª5î³TlPãúÑϤû2áüòÓ‘ÊœMàëb[wŽDܦ$süpJún:—¬s¡ÂÙa~,Ÿ¥b™ùîÄÙ7‰•Ç_p-H±D ©ÖŽS©ŸQÅ8‚ŠÁç´ E ~—ë”Ô|a·8SãgÀ¢‰”¢à©Œe¹ÌuÔQšp`pñ"Ÿ%ëgkü,•J8À¼¨ñ³ ¡"¡â9Pñè|. ØÃϽ ÎÇa°:KÎÅ’óaóç5>€éy˜^Ð).d]xÌé|¸0ȇA¬9k6ÿ?!´ë`à‹:ÅðÚÂLÔ3°³pÈRQ“†œõø2h†aR€|ô°¸¬.Ί|àò<\Ž™Õceri‘Ϭψ|»ŒåÄ;cq‰Æß™ïÊõä X:À»àò¶n1¬ñw9"ŸƒTX]&j˜ ®“=±ªx7˜\Û%.‹uˆ!¿;+.-ôê{ÁwWÐ錄“Âää2›¤ÚfÈŸ§ñáI|ƒy4Ø ….„M T,©´'GeSeç‹§Ú5Iª>GÕ6Øöx®ó%ðYLÞ&^VlƒU¬L§(Z]xÌV)‘ù ™ïwn)ŠL“/í#ð@iºÇé%ãj£",k³[Œj|`¿„àak ¥ñѠȦØ>[è_äôpÎ6GÐ)Kê•èøºâ] øöÉ„%­Tó@†¨¤¶L«p°ŽuˆñŒFX—·³óL¾LããYñ(–ìå\³ux¸7Úܛө¬¢íÃêùD²À’™ˆtPr!˜Õ)*P´Þ¬h݈ç)}tñ4DI‘}NЉ•¢Š:ík¶lûtd-WwU·¯?ç÷™tª+±áÜ ²xAãUecò=Ž(3GÔpS[ƒí–ÿJ?Ž«]Õ"ùI™D†¢?LÝ͘Æëd³¬1‚3f"+v±Vi£½qè0µ ¿Q„WtŠÐmw³n»áĤïD%<ܸSã;€ 7FÀx' ¢"…ÎlöÞåˆFà­Ý´óØyð+[Ñ'ZôØØëdê€\¾:IbëO©v’¦Ô2ðżŽ7¸ä§@·÷‚Ïvøõ*¿Ö,¡K©ÚX¶ØC×t^yñ¾xA\­ñ÷M5W£óG{Hœ¿›2Ø\3==5e0 åd|̈ðXct`jdÔï9Ùè?eŒ#T÷‚¾‚ÿk³âƒAnì¥C{o»´Åu¦Ø§ñ릳„NìÙ9Cù–´Åõ$éõt¹x?úÄhüýú@ˆj±ã¦ú­H°Óµ0ØdólŸ>@Lq"냴çq¿eèëpP^«ñ:b/™]uyד¦‚¤UîÃs`Ô_©Ji‚&­«2cÂdFÄ`HüU0Êß‚dHn@ç’ÕˆéÏ¢Ž? Ð@í‚Þ7ÙâFÒáFè°LÜß-nÑøÍþ™z«ÆoñGwh|?®Ï[³bPZ÷±fª´b–‰å0 jä~ª‘ûU¡½-v±¸]ã·9b?À(”nÇzÔ¼e˜[4?îW‚ûYq à~@q?p? ¸¸ î÷;Áý.ßéˆÄ=EÜîÂú€»:>îï÷»kÔQÙâ>Òù>è¼[ܽïÕø=X|¢X÷bx’?¼,?ȯùª_®Â‚…ú>@?šŸD>¨ÎšƒÁYsΚƒíÃ1O<«‹‡bEñ1?ˆe9=l|7‰ö?=¹[|\ãó'§hüãð¡?ሃ,XúwØðjløIU'ÑKìQ‡€Éí•âSÌåêü”^ m²q>îÁÁèò•›LæÆ/q „Äÿ=˜ì…ôŸžc£¿–ÊÜ'Q÷qü0´NÔPè{N._Eµš±~Ø”F†ß§¬¢c"~]@™D\­õ[ë ºþq›î._ÃüéZ7Òo0b—aÈq“ n‹©½N½OUïÓÔ;«ÞêÝ¥ÞëÕ{ƒzw«÷Fõ>]II€ 3üôÜ=ÿQ¶Q;âhüa‚ÀÿD¶k£“Ýø#^à£YqH9±S<†¾ô1Õ—fVŠÇ2á©+'~”ªÉ«ÔcÔÕ¦ñCŽx„<ôpû¸}6+>‡«ªŽªU{¨¶©NêTØï´©ó›Ò±™áçñbóy°¹¹ùxV|áàÔôÈÙº:\ ÿ;†g¼™þ Žø<Ñ?úq8üs§x‚n,OP-û¢)¾¤ñ/¶Ú6ŽƒŽƒ\/3“tí°ŽálžÓ)ЦntsûR«IÄ'Q¨þBýl}fWIb= qè’þ/°BŽLÑGA¿qž¤Hÿ2°7CÙÍŠ§TN‹§¬õ–xJe÷Wb爯iü+@fz2¹A sësò0Rÿ«?Ü!žtù¦nñuÕŸ¸jò5L2.?Cã_o A)•ÒOáù7lz DúwA±b™þØE¼.¤W_Æ ï†,¸,;Ùÿ4ûAótV|S…JV–ÏKÍ|^vĈÏÁçèùJVüd:·èJlΨWš‰âˆñOA|'ˆ_ÍŠ_Ì4Ò*[¼FFzMég0ÒÏ5þ3ßH¯BìŸOéÕfÆ¿pÄO‰ñkd¤_‚û]ðǯ²â× ^íaåÖŒåïBó¸–î‘ )–™Ô>SWšXþÚ¿$–¿·@ÖßfÅï&mþžC_fšé~çˆß}/¼Rüg§8‚¾ïr‰nö²ÜpŽdâ[í*‰UÀ²‚ÉAõ‰Ôæä¿=Mª/Màô{p¼’¼ž`QφÑK+A^oäŽø= òÈîÙuŠ7 ÈJ4 &.r÷ü7ŒøF¡£{ÌDú­050]ÓøÑ› ~{ÿ±S¼ â7'µ0¡… ´x“´¨ÊA¦ZÞ¤,Ðm\æúÀj}óíhýäý-Q‚ðtO}‚C§ùùþ-åû?Á÷ÖøŸèWŸjXÏ4ö „ü¯ÃôÕ–ŠÇŸ‰Rw“;ýl$#’?íI#ºfÌê˨ú0˜¢{L"…Â:óKéÛïȳ·(Þ†òÂÿÝ)Þ†òoO[®C¼ «M]6vˆ¿°G”D9ƒ±Ð`£¶™>ÊŸ9VÅøžŽ§Ï,<ÓÀÓÀÃ3/ÓúÁx!žEÁøx'üÿÿ]V <”Ùþ t1Ji‰P*%ãÒN›KnK”B%1fcÌÅ\Të’M«”KîÑÅJTúÛ¢b©h#­•Ö&­µº(¤Òu%û?Go»ßÏü~Ïœç{Îó½ç=çû¾÷‚ !,F  LA0®°AÁa9ðÙ¦àÁÜŒä7'y,AŸ†À€±¬¬‰Ï?<– ÉoÇîuEpÏ·¤<±Çt]I{6"lsˆ¹/è›¶æ¾aä¨íœeç‚*ÂIð‚Õ²­5…ïè§(œÈÆïÊq¸~ñâm£'ú? þWÐ*V ¨Í‚ëvxf„‚š¤5ç̇P¸|[é÷:¬Ÿ5sÇ9þ«8Eì§t†b- â×ý;ÏÐ}Ã\)š£ú¾Ô wÍö}áÕí<—±F-+ÃÁïcѺªæc†§¦Ÿ¡qÂ϶ÊMøù'UþMk®¹§Õ×x¯ó˜£eÊHñî¦ñîºïšÊò_N鱉ëé?ý¢nþ—}49Ï»]·„Ô¿°£õÝNk}õ‹ÆÔýM¿ÊÎÏx©¯ESò§Eœv>Ëj_Ê´Lýƒaû=±E]>ä>ÞuS•bºë¶üžbƒZÍn +%N½7Jñ-àC<÷»Äúx¥âŸõÔFmÕ¸øíuɱüX“û-Çè©~Te;ѳ,¿ù°t­;Gã€uÿ÷c7Øú¦v1ïóóuG ”ïVk6õ¾™´yQQgÇboÉÁÈ¥Õ¥=Ï\E† ¶Ö5¥ƒ´ý˜1=¯–ý”!sj‰³j¥r£slaÑߪÁ-qO$÷•Fê~ý}0øý­íÏyñ¥×TZ¥¼¾§kÒÕRúC‚È#©Lóü`~]dØ;Ýÿ-Qºsfp ½Ö\¼RÇ­?³2ù‚懿Xþ?ãºñû²âës, T»zå1ììÔ÷UR1§íýÍõ¦Î~?„éžÈ>µ7Ñ#36êÁ({ ¦‹ÑSÀç;ÎIË•èìYþª®#Ïh¿M‹=¢ÐÀ]Ð0_tyƒ°þÈdž·æïe¶k_;H7h·^½¡VãÛØðe<Ûˆ#zõ½v4X—Ç™WíÙvQwë»_ëÒ^L[î½'Q/ZÞ?Ssôô‹ 5ªR±•Š…qÉîûa½›e«Ž?NåÆÝH‘Ç'V\8ä›ëN‰>×icÞ}©3©=‘3æÿëÔ£Óòã¡O—˜w±Ê]Z ;u¢òöQÓM 77؆³^RSšoØÛ©²\#Þ[eóæ~¼Êô¨È—óÎŒ^))»ºµ)iÍ£¯½ýNÍ2^ûhËŽöäÀÖêîÖYÌ_æÖ<4¸îicsÇì’r˜xgГè36 'âî»ËÖü|++ï¡üõö’¡Æ[×oÜhksSæ]]žÙRvt“à{IZ•œÅ[þI=>5Èß)èNáÃ2í¶Ó×õ>}’÷8äé¡¿ìÎ뢨βÓt)£­ ÑùÊ*¿÷Y J†Âû]?Në7ŽHî¨I½{÷’oòÚ«¹þ,Åi.z-ZZ.÷R» ™ãçµ]DIú_ËR½–©6k¦?ùùr^Ñ'§!m­é#:~¿™T¿I?”Ü‘ð¸9nN…$tØuWÓÇ3S?>ª¼iôijÿŸ³­5c~FUžžFNµNF¹>qF‚ÅuÆ'sõuÇ·FG÷]½Vè°oMΔ†‡OŽ_)oò™$½ê{Ó52sÏt•Nyº ¸¶`ÛøkµŽ~ÂëÕŠ¨ÚpÖmÏFgæyG®êΈq¿ÝSÜÇ<\“Ö$1“<¦TZÆzSÒ®iŒ|{þ^ýÆê * BªŠóu˜TÉ5‘\=©}!ôA„<Ð#Þ‡ µïO„à¸Ngƒ§sR=Íýö¤zJ®¡äºI®•©à©A8ž*„À/ $À–P†°ôR„8àx¿ŠŽ×&8^ƒhàx~ßǹï„qq^Qç"Ž÷R!xö"DÀ½xæÇc†Ÿ÷ÌWŸß3ì·†Ü1_ > @¡tBýcâyíK䀈ôÄÏýžßóýžý[H#äçrùé'¦³ŽóB(5hi%Å*6,Ó1KÍJÅ.–ÍzC¯i–ÏUmFÓÑk¶¿¢j±¨í1WXÇjjÞŠR³5¯fY¦ÕݦÖÌ% Ò¥Y5ÅXò:UË<ë-×4ÅðÄ㽩tk¶f8áÿ-€-›ªæ=[ÕËU<•š ¦QÔÎé¶£KÝ%M©·êàè?C©k\I±ÛJÕªµLÁÊSÅm»lêF-+ohšºÌG¡š^âkŠí릪WtMe ºö¢¦”«Ý쪘V]qºí²b´Âø5ÃnZZQÕ-Òíiyê«U«iNÛ¥–®6Ð¥&´€LM ëFÅìYÒZ™·ž…Dkd©‰D­ûl:•N¤;1 0)Ñ›pkÜÎÀðÂ`ǵÿž3€zâ ‰Œ¸‹ ¹€¹@°OD™ay‡‰ÀH2fYtMÒðG°Ö/—òÖ)F–YüñŒ\˜8QBÌm0 æn§éLÛÄAçþAÂp¡~È$=B¾Ð pÃÀ®°3P'wm‹îˆÈp½A"B›²å®u†ô‘†\Ünô€÷2‹[ír}à-B¦þ,?Œ§±äû„‡A¤ ,å„s™É "+ϲ‘qLŽfX‘ï•øQØ? Kâ,~ˆá`ù˜F~F~EŽAæ8?ˆäÂe!“ Àßð‘Ûq~„‚ AŽàPÄ'Þm,¸®í¤¬m­¨M™¢yÛÍá| GåÂ!Ć"}û$øLcHÎ`zZd†Îð}t½ÐíÈÇ0ÃÂ!ávCßû¡ï=Y~ E214ÃáÈ$/â‡ù(s 9L¢q>*<7ÎïúYÊG!5KSo@êvÚ)~/ÉÀà ·º¢§ªËð»ÝÔQš5Yã°³‡ä0>A¸Ãí£Ô±Ÿî@‘ 3ÜÌò‡pÐâè‰v_"’üÖeø4I“à8žåŽ¡NÇñNÇD†SÇ$8¦À1•å%”Hˆm$Æ’Mz¨b˜%÷i”D‰ÐW‘œ!G%¡+°…H^€p„‘2| ¡“޵H_üÙzƒ~Þ@À‚XH7ˆßÅ ð®!ÆÕw¹œH¸\¼¤¿Cr9[8ÕGAvwøîqù{AÆ\~?E;|‡\œúÆ\ü!}.~ä`GÌñÿÒ=ùs­~3nŸq×¾ßÕ‘wãqîgKŽëõý¸DÏ]šZ¿~Œ&_¾þûMÖu¾Ï;Ýøñ[‹ÒûÌ.ué;·F/}kð™¥ó'¿×ÿÝ?íºùàµWÿ–{›üzóÝ/½úàéÏìÿÊäGsŸÊMî¹vãß_þǯTþúý®~ûÎúÌ//-íþÆ“·|úÝ·þðÁ~òæÍo?z5Ó¿ùò×ûž|¼Ó»ž8aÊ/]ÞüÄĵ*¨¸öÒ…gïoô6öý죿¸ð›¹Ók·6n>;òâ½äçî}~|îùóêÐGowß½[¾ìtv•»÷ʯ†ÿ~ò·?˜ù×ûïxj½vãñ¾Ÿ®êûøü)hð¸Y^tèÜRîŒègÒÕé,®~ÐãîPtuºçwv½ Ã.NÏÈ «Óó3àê=.qçßãî#0í8ÝíùµV=*«¶Ñz0úê7w£«7~~ö™ÇfSï¿ø—åå™Y£¶D‹ÏR¾Ïl8ºiØð©ˆoÝHŠv³^W¬§)¡Ël:ð3½‚X­¤aôäÓr­©j*ênªM­b°©*òçNͬ¸8ûD~õLHé )›>RLžÈf&·HÜ陓ÅÙGçVP`IwÄty2[9RÞ6Ï-λ殅t&'^nU»ªY6”»‚¼™ä‡“бŽ^ת]%¨ÿ…SˆÂ+#JºUºm6­²¶‚IUͺ–RŠUÑ'—žª™j]%®D’àŽ€;¢&"ÌX"‚³à–ƒ9 欜È2V"‹ÏFE_‡.¢Vú¬K,ï{’ï'³Ë,/y™“Åån,b†å`^îº*Rõ@ª¾šT½Cªž’ªRõ‹¤B@ªHEÅú¤ óe‘[·`ýÿ1h SƒÆG ê€A˜W‚y¹ZDâÔ´JûŸÂ) EðwI)NB> ˆ=øT¯¸ÂYÙ¨¸BqF•$Ò;¤Ë$Õ¥@+\€¸ÐÅJR<øšJÀ9¤*ÁW ¾ƒÊch~,¿è4­UÐÙê<ôÇZ@½W£y’_úÉü«ICðk º†Ê‹å»›¡|ÍÕåk&Q™ß%ü8R$†5W8 ÖôEZ¨µº®Š—ÁªO"¼4øý˜ØØ­ì Ø* >‡E è”Þ5J¯6¿€‚´¾ÂNÚ ŸöJ>A$´pNqL|€·Wo—„ö~q#Ëo&à ü•˜Ø¡mÕ¡mÀ…À‘íD°69XêcX~–ß;„ÇŸ§MÈô z¬\ÚÈ´ò@¾,P˜t½ó°ð¼Opó~„ˆCHMßFN B°†wFE`T×RŒ+Tû€I_5Õ¾EªQBõa]¢¤.1±›ëcœœà œ#á1IˆÅ)—‚œÍ#Bmð6X8Azd^ ‰½pp‰½ ê¼½)nfù¨š¾ëô£ÐCN(–ßL)Ò Ü|PìžáÀ¹§ ׉é%uˆá”¥4—FÃ`ë#ÚYÆ`Ïlí·A{+‘˜Ø¯ôÈp¦IR#¨ö!Ë÷ãQµÖÍ×ùD.ÍŠ2('Óp¢¥’UQÛ¢âHþv€ÞÐ*ÝŽûOUÎÊÆ¡žñêzÆI=9 öT6ö°C8’|i´Øa>Ä«p$°|v)9¤ùÌÓóÀ2ˆN¯ÀÁ‹#pø&(4Áï•©I¤Žqj¾âAUJ þtÒà€´7’ÈíЃªíÆ|#˧‰fÝA– Œ2ßÄòC`ŒÃÌýâS²„ã!™ó$I•# $ ù8ÉÈvgeÍžŠŠCHBc¶9N†Cs%¸²[A]‚@8úœtƒÔ€°Œó|dxÈÚ—‚,£ã$òL¥1u õ4†ø«Æ®¢öÕ k¨ŸàËÔ®€´Ðx¢¯£vÂg=Õ7‚l¢c‰½£*&T®âßEõÍ Ý¿$Jó%1}ÔNÆn¥µ sl£v£VaÝ•:JjÈü˜¾cl§þT'¿AµT'× ÕInªjÐJuR—fŠCj·’r!뵂êTgi훨]¢:K¹aª×R?KstQ|×μMúêɾ~ôêÑþöîj®_ÛÍ7¯ûʉóçØæºWjϰÏGëœøògýWŸf›‹­ùÉÛ®º¶÷Ž¿{òäá¯íA×ùóo_z}ì[löò[ß±ÿp`÷­—WÜÚóêG/†ÏµØûþÔ½ðÝèóퟔþù»Ï]Wîþàðè+ßï÷N7ãÏà ί÷Ì÷Ÿ8óæ™-W·ûoI),d~ûÌç/_ÒTsgã¿ÞØuõˆh¤ìS}™™R£w¦ý‰UBw}kOp×鹿<ç=ýÚø±,û¾krèÙ…—.ÞúúO¯üÑÌ´MMÄì7Íúmßzæø«ÿpý7úÆùßßÿäHþ³,¼yÅÛðâɯþ¬ÇõÚ/½s)øß¦Óoüõ“g÷ Úøî ïµþÊè _:øÂÞÿægØèWÏÿ^(ì8í%RÏ8­é0H?Õ“ [¨Nú&Fõ­qÛ6ÉÚŸ-™v导ÎM3—v·•.¸o?ÿÎÝ_úðßC'ff’CÅIð)NGH@Q¶áE}–átøF!6?ËxòÅl¡œÓsÌ£oƒi¾\Ž{‡vdƇv¥f™e]¡pW¨7Ü Gºz£±Å þ ɱÌÐîÁ‘Y¦v*oËál¬w²;ûÐ=2>JÝ5{ÂÑD(2ã°¥/곌;ÚÑÓ%6ÎÎÏéÓ5Àÿ7¯aMÔVja‡ºe”ͬ>ËtuNszg>O&ó¶Ý9¡YÓF§óáÔi™ÙÎ'¾F;às†‰OX6iìÿPK’KA)aû««Ìrebar_reltool.beamY tWvžÑHÖXöØ# Œ=X"†Û²%ÀÂü<[–„ÁØÛ$À‚,iƶ°¤ÑIŸ¦Ccv» ’͆ YØ&g“ÍÒæ@šMIÂÉÏI³Iv7-IÉ.IvósÒ&4iÚMÒÞ;›!»ÝÖç*ÇÇ"ãÙ´9®H²5™ˆáÊ’ÂÊ¢hLQs,zIGS2‹f5£<£*q9›èæá®z8ø)üH"=¬Xa<›PÒ%uNNi}&·Ûv (²€XYÍe50R"ž+V•T$™Èæ¬9EûÔy'™$ЬÚU9«$ÇåÈxTMDcI9kÁiYë˜<1œHKVôß#Y†£É¬lÆKu´¸$[ !d´Å8s<šÌËÅù´$ÃbY*-ìVH› 'Œ$•X4iIɼLË)zÑfÒò3V˜ŸÍ'svð–¥&ƒh&“e ~ÌYàÓ=y/î]6CZ!ûh5çÔ¼lSr:W¢æÓ3ä–²œÍÈñRxE)ä\†}£\jÌ ón%‘¶"NÈ´M¤ªŒýE²†Å2¬¨q™MEÇ´ÞRxLEsMŒÅR>•Ñ\%01KFM¤seÈ_K¤£ê„mš€˜q‡ry¯ÏÃN9(,3aIávª ,«V0QJIŽåGØ™¼ÚgŒÈžDRŠGU©(®Êð 8GßìÌ NJÉ"ÐæHnÔ¼'ª¦‹Y-Òx&‚ÂGq¹¨9“*Wæ!æL2 K%ƒÇ¤Y|'' 'UR6»‘öX~-¨ÂsNdK°;ØÞì/Ÿ‘ûh4-%eµ$¥Hù™¹È¼á¹ªá´4ù†óéOCmÃH¦©¥!wíò45Ãøœ£va¨°,ç–¢J÷@=â©ÂÖ¦84Í›*êDZ,#"\„ñ™©×ˆ‹±»¬âˆ“)f‘«Yk^N|q9‰ƒ±;ì.»ÏìáêiÏ:³?Ȭ4¬»?\#ÓÄ=Èì« Ý[““„)f¬ ó ËBÍZ™õ =iªøD¤•R€PQž³Sô S…éÓ³ÝV¾ÏÊÃJVf(ú)¯¤èWJ)ŠÄ`|Òý;&ì!&„ ʇ(ú²•?QÿÖÀÀPaà ÙÇTPÍ[¶jžfíe^£§¾¬üi?ç`VAƒy3±Õ@ßS„Æ*¾Â_áC¢¶- ;‚‚I‰Î°­.l:…‚í 3`3v³•¿L\p9‡0ðp…˜è!vÆK쵟0Äë²zX»Ÿ«€-«œ |²’œÄi¶RlaœàŒ8¼ÄÌX׿¡Ù ˜ÃØ–‘ð¤@€j[Ãz<Ð/hDÂxáÉ,³•l£H³sÊ<"Kl +˜ynFmkô.G¡Ëúh¶£tÂ$S M².âõg'F4u"|€´i=jªö°7ÞbáY7#ÜbY7ød@]Á‰›º´M« C¸#Í@±xÃ]šžç v× šN'вãÐÐ ÑlgàCʽxóCÑ ýdj@cÐ÷‡ öYÞ‚ÿ'o 7Ø)¨ñv¦j8g‚¦lF SŽY9\—ZMo˜qÇõ‡ò2lÚÆp=p–qaáÖÓlX«z84»1_Òi‘Àò†oÂwUÜðqƒ’mq~òD¨ÎUÎÕTøˆñlmøæŠŽ9YXUzè´AèȺ Ïý¤DŽäÈÔþÿ·ÜA/9_`&Ö±0»P mRÀKöÏ äNØF”»COÛÆ?‘6‡–¶LÛ!šÝXHÛÌÁØ~Ç1}µ‚=gß?-fþ—ÂI鿇ú´÷¤áp $2áÃaÊÚ&· /]0{°„öb™ëƒ277éæRnQ[“ŸÛ ·An€‚^DEÖ=zÑÜ‚NúÁÉn8¥GÀb,‚tøj‡tj°ár¯Wø¡BÙ‡xƒfx[sh@˜­ÓOa F'ÞÖ´k^‚Éf?7ж¡m5\”¬Sñ„~è€[1Ô›`n“›IÓó-4» {àþØŽÉN‘…{kt¦aù·0§! p‘Ÿ(Ô«i^Dd€>än·…Íð¶)8˜ ¶Ù KàqW+7Ä”zÄvƒ *€Á÷­tM‹<¾a 73… 'R±@7ì>äãvb’¢à2Ï18…CõçÔüÒÑ•ÊÀ§)¦Í Öm‹nA³êv ´R}œƒVf˜o×í h‚Ávèöhsu{´*h&hó¡-0øY¨Ûè¿Ö`‹ú|´Åz?Ú7èv=´%úœ¥ÐnÔýá^ný{V4>§š×às†´WèóWBkÕý£ÏÕº½Ú:}-bk×mä*`ˆ¥ÓÀaPïÃxÃúüõ˜}îÕm°7év/´>=7¸×fÜ-öúo2Ìÿ–nã¾; \í2ä4b˜5ä1¦Ï‡ï®ÚwU³îsÔà?¡Ïƒ¶Û€9eÈ#Ú¦à^ÔE¨‚Î’úøvÝÆ¿›©Â÷cô‡º+×íbýSk¡|z@Ï>gô8bºÊêùê>øHëý3ñÓ¦ØÑÖîDõ?0Ïï½7ß¿³×ÑìX8ÀWN…ÄõÓw~ïžeÏÜ^»ù/Ë/<\|ð êíï6Ÿjû·Æ»{ÚÎB¾xô«w~0>|1èy=™þøÜ{—²ënè:\ßuxuuÍâO¿Ü~¯£îÓ}GNÿÓņùŽÇì÷.¨ÙõÎ Òü»ôãOUT_=pÿù¯/ln‰øäÙE_u‡žµÿrá³å¾-u)Ç¿þÉ/^¸;}¸Þýí£¿°…¯öõ½|xÉ]ÿxìhèÈÊ_Ù]g>í¾ÿ?mÓM½Ÿ>þÄÏ~ðdÏÊ·.ÝöèW‘ñw»Šß]½sò\xðƒ÷¿œ{þÖN}ôêSÎ*·•6ì}ì;ÏÕ<áŽßV~øØûá{þzÝËŽmxiÑOmòž|âoýE9uî‰ýüÿrU6ÿnñ©û7…6¬ª-Þ.î}ò§ÛÂ=Œ<ï{>º|l[xç˜ú|jÅgs>ÿéÙïž·|Ñå1vùËÏGŠÞñÆï·gøÍ]ÊieòÍK¯>×ÝõíÊq×Å×¾³ÀE?¾zËëÂö›ßµ»øãÛ«Ú>w4½×qÇÈÙú[^ Ü[~ßщ_?¯¸óàgÏ^œü›²“‚ñãïUWoüùß?´ZšeË;^QìG;Šïê½m[U×ó¯¿Úê8úðÜ[ëê¹ß$³Þý`æ·å‡V|i—Ï[…ªº/ì—6žlÙõÛ¶ã¡«w¬~S9sß?ÿühæ‘å/Xo=õvÕ£«×›VÞùýÿê岃¬Í?½kùg¦ÓÜôÌ•fïKîÊÁïÉ®¦;NÉ›¿ý£ÚøöÎÜ#\D\´¥Ù×áñîÖÐê?Q_ãÊFö™s‰”ÊE«£Íô¬’WãòåiURr“”‰ªÃ‰\®)ÍŽ*MÚÏÕMY5ÞtÝÿJ4Êj“ÜËâÝLýPK’KA¤aE" ürebar_require_vsn.beameT_ˆEžÙI²¹¤½ÛüñDak´ÁËæçr0¹»4Mïš‹w±´¾$›ÝI²ù³›Îî=ñ¡*úàÓqT¤(T,'µˆÒ¾ôI‚/>HŸ¥Èi|ñEuf³)-|üf~ß7óýfvvNoneü¹R,œ+8ÖðÃ\Œ’¦Jë”\r Jê;¶)jÖ`hôI¸¦áLk¢õê;„Ú†eÚÒDH¨csõ±ñ|Í2[Fµ‰#úÒ¡}ÕlGí]Û!ƒºa¶,D]38P­#š–ƒ:iºí©ñ2}«¢ã‘ë};¨6-êÌL|-gÈm£ÍLNq‚ù…E†‡Ñž.UQXÆ2üú,‚ß ñÈ,€?â8ªHUø;J0,a”à)¹¶ZãV y¼À 2„üˆ¦" !ÊpÌÏKþó~œ!Á øú9_?é ÅËÞúüf}^òû¼Mûk ¾F˜`ÃpøÜk _þXk48ú¥:¹ü¢¼~kI<“m)Êá©S³W¯Î|¦þüà׃¹W~Ë¿™XßÏmm'ßߊ®çÞºù²pâ›ù¼8ºö×îùˆ;ŠÜÝÁûÑ›÷“7ïKŸ|ö£ý믱÷aýÓ½h6¬n¼Ú}£¬ÝX¨Þxù½â?' ®TºÍK/ÜZ>‰„Î|µvJpý6+lÃÒjþ~ _?¡‚ãPŸ§Ï3Aˆ]mo`J ôíwO_ý{ÖÎ\®Ý†Énwµl¶÷œ§p½h þ[ò„¨ƒã„R‹Ömw0Pé.„,×Ñ ÚÒ4LžFˆ†©õ]è`Ê5uÒ2L¢wãtDV^+o¬ÕkåsŘÉ*™¬²˜Y¨grÙÅüÒD>¿º]/WNoö@´m8rF[Zl-héÍZÕ§C[™üŠ’ëzÕúOCóó/Íçy.àÒ 5Yý?¨aUR«O©¯tÛr©Fz ŸîX’Ö‡*mŽ“nªvÇJ{ODÚ¦Zú/Ø<{zºìD MÛá—ç?PK’KA×G 0rebar_subdirs.beam]UMlEžõl²›u6™xÝ8 -ÝÔ†Vª¯Ó&­‚6N7UÚ˜$åVܵwmo¼Þ5»ë¤=Q! D…è-‡PN ¨Á¥Tê •ŸPÄ*U‚ ª8UHHÀ›Í¦ µôÙ3ïûæ›÷ÞŒ<³ ‹„¸#¹üôÙißi"Ę¡”èeÍ-yí²nºžÐr–ëT Ï‹nmß´<®fø¥ÊšÎƒ¬DuÝÛdű«f­‹²–SÑ,~Í´ôŠæê\Õ´ Ë,w®¥Ù5¾©5ŒRµmwX¦ç{\ÕÒü¦Öv\\#jz%¯a¶¨;ë»m££ªYžÁ®i®Ýµ-³œpUk•zÄi•ºQiá´xº¡­5 vÅ1í^×ðkÕ(y—›–i7XÊ‚¦—è4Útô¶e”L»êôÒä÷Ìã#»¦éÌä<¢ŒôØõ%0‡pÂɹ$Ï%å Ãð=#RSPûÍIPã”gx‰(hVÆ¡¯bøø¤˜ïÄ®·"&¤“’˜  ÷ }b?Ãï;*&’q¢¢<Áù††+’*$1¯!ß~JT8ª€OR¾¸‡«~S$†€ S2ÃNˆC¸[–§1Ô(a5¹ÓZXÊJôj$ã„Ç$“<‹1í7?”°„áb-ùî2½hsÍý}Ð  ÞÁNzÿ˜ˆ†cª@ À$@|f_¨ †cz§÷‡zêùìSãLãùKAnGBÏ¡–„cîÙÁlÛ^Þã0\ µæpÏ›>Õlî_Ú¼öv¦çŽBØwNËÃ/—®/=û`}}“¿8\Œü­å&~Ü:ýðùƒ¿Ÿš^øäó¡{‘ÛèÖ—Tœ»dNŽ2=Ç¿Ž½9µµö÷¸ô8öáûwÎüqí~þ‡cßúw¦.ÿòè³ sÑ¥Õ‰ùú…Õ «ÿª½ºùð-#W¾9üœ¥Ü{¨îW¢ßoýóâßÝújèÜ¿+Ñ×Ðè£S×ç Í1žE*¬o𩚆Â:é¹$Âq×´ï»´g¯[4Rè¯zv0± *¯_½•Ÿªýôëèæ[ú§Ó++3sv¸á@ÏR=ç´|Ó±=àt$_ð4›š{™ :¶Å ÄeÓ¦Æl δ+V[7tÔÕ¶u£jÚ†^ÇÀé:rççæO•–çÎæ¨wLÉŒ)™c¥ÌøØDvrGÄ¿<³Tš;7»Ð@ÑšéË™ÊäDõXå ½°\ éÎÅL6§Œ¯Ù®®é6PGvôøh–ÆXßlõÎ2äÿ³ÆkDµýZ&HÝsÚnÅh %]wšFZoinÕôýtYóêN:xLÒž[Iÿïå…—jº1]ö|z‘þPK’KAÇP@u_rebar_templater.beamY t×™žÑ[ƒì #0l/ì¿ è–ÈXšFlÅ—Fßá_ƒ Ù.Ø$ÐIa€„+Dz¸l pVi„8L³i@ì«vœ¿1…àHg`LôdÍLVé¼D$?2MÜýÌݰ KÀmº¤ýç¾1N§L<ˆ:<+{õ;p‚Y~aŒyD¶·0öÀqp‚“:8j‰S%¨™xdbi¸yx]/J«/ÚWÀW‘¥È6GáE¹OEMH­õb‡Ú¤øT®Ù§JíuØÑ^¨u’vj:ivZ§UzR–B1}¢‚-ɪ]ɺ(ì‘x8Q> yqªÁnˆ’X ú惾i…’bÖÀ¾–^•­ä \a¯×ÌWAQY·À¶…/N‡Âè1 À µË´ÒÂbu`ÕD»Ï€@ÏÈMÃò(Í\›¼"3ƒÚ>„VÃKI!Ç™òjÌÌÁ¥4uh‰ðwG)-,qð×À[™-O”AV¾„wò¢³˜-Ÿ¬ÐŠSiqD¨It@ùQ@,¢/SaV–­ŠXLáÓ1|A˜² _2‹[f¦(Rž„ y6hh€§:†Ó¶$ Ôi5«^tš"Á¼bàœ;–‚—çÖãù,ªs ªsT¥¬k†3 N•I­ƒ 'à˜Vç!AÒ¸å xÎ"rç5'<—ðâ|žƒ$Eñ˦ŠÑ:¥“+@Ý2P·@Ãh ÂPR.\i›…òbådIÉ:Ìl ´_´W`DÉ•%RQ‘ZrÔm·LÈ8J©Ù.È*ÐO@¿»W3s50W»‘ÄÖš ¥N"«¤]&ÍˆÔ ¹éê†Ó$M£†ÛŠ*®öà–³5’&-WdºÂfjAa(ôÔãE¨PSšrRwB+âôlíÓÌü+Õáu‹<¸–I[ ÒÊ`ª®×#ÊýÍ‚ò5ÜÀ‹õ‹ðbTÈIà‰ãKy°QöÒ}/6LV4h²„W!ýgzq3ZŠpó4¢à%^Ê‹Knx®Y¶-'¶€ î#•Ê+–Ž­ûRkò¬ðbŸºTÅ>*¤QÃËx±\‰*±Ù`(‰%°sÿÊ,@à}´—â[G1¤Ê­’¦0ÊE ˜IhøÁï’XêÅMӦܘ6É£’ýס҄ËÚšh|}«T^l¦=«L^&û ‰f¨Ñæi2gAZ-ÄËqZ%^'/.‡¶ +e•x5­ÄìZ@°µÑSÄca]^¼…ž£x/n^˜Nxqt`»“ SDÅ‹Wô5¹Ð×ä_z|‰3h߬„E4jÖÑ*˜ž‰ÌájjÓjÎZ0g=кz܉Nyq(¼4ŒCÔï­nçÅV_˜ò…¥Ã -¢K6;n³mÀëy±¤P>´t^\_ØÎmPR"“È´³VMTIuìåÔ^¼ðë¹øõü)ÅßÏ‹`g-ñ@7“HàvÒa#°Ü>†ÍVNŽã;nkǶ¼©o†°Õ¶oçÅ.Üw†‚<,““@$rPÎöâ"ìCˆüiå,Šr/n\ˆ;Ñh#ÖyqSáÈš ÝAš¤â"wT„œL“ÃÃà• Ó6\Þ+àÛ@J™œ½у—¤éŠ3*TâØí©%-*q6“(èv1íáÅÛvÔ_i@3l"Q(XØL 凅 õ›Ê™^âÄrZÍÙcÝ3~–ÂiF‚†ý^¼e"'À·jÛÚˆoçÅ- ñÌê­ÿ?µ7ëÛö×õñâí´0Òàðxü^Éú°ÍL^¼cbÇvù“%§!ˆF~Žÿo‘/g‘2ŧ(p„p§²´wæêÕI¯‰)Á¦wHqöØ%’_´4Ó‹]ÇØM *³Ëƒ×Bÿíôàp;»`‹a¸ OKàÖϹì”W©D¸«ÙŠ‘¨iП#}Pâ:­ón¨ó;`¦‡¡u’8{é ôü(L*â|^Ü“A˜ì«Ç1„Al’vÔΡݧbüJuS½Ê˜1ÞAÏ’8ˆˆD=N¢B $p¤ã„Ô–=Âf@ Û“ôà8Ý¿l]°gg=NC’U/NÉ @ðƒFóÉÜúÇ/,séýŽ™•Ø@¶HöÚ vŽ)på(0¨a zh ò3{_J{p?Õš­:ôÈB…Ðäo­c5Çää—È<8vg74ýÝÀ¯ƒðÚp÷Ôã;ܽw/ÀÕ(\Á'Ã导ÙÀUL5o6R'¸Ê¢úªêGª ç10Ìc¿Ÿâ·7 q/ÞéÁƒHF\{Úè ?ôVÆûáiaX $åY€èÜ$6¶°ñö;ÉlìšÊ~?Nº…ñS™¥l< ¨ ˆgüJθ1åã‡?ýðÙ]ïðkwŸ=v,ùî±Ë_Mº}ëÒüCG±ç·¦n©ºï=oIÝ•Ç.]uJx¥y÷GñOÎŽ<ïºÏky±ôòƒ çÆ•m~°þ£ë·žìÝW¡Um_X×PÞw ¡ë®ÄpëS§ÃéMsÔE^¼óªÒÃòÖ-G§¾ñý‡Žn˜r­fúk¥¸:¼äëO.~c$qmÙŸ¦?µ²ñ£—ª^}á\ëÿlkZ}ß{ÂÚæ¾þÇ·?üñÕ{^xéÂ÷ïo|¥òšç¿s}ý¢ÃwjãÛî‘ÖÉ5ßy¨ìÅTýcU—W}–wíÔ7ÿiÇåÀO>Ÿtç=çßi<ñ£¯ ºÀ¹ÔwíÕ¿Í_Ž_<²é‰¼Ô;kÞö[^Øðóìym¤òU'½§?Åwò“ž*¿û‘ç6\¼jàӯܱñw=øÐqÏ¿^på쟆>÷«§Olso=ˆŸ9»ÿéMÿíû¡ýœ£îöÿy×öâC«+6µml_~tàê.í3ôüðõÎí_qÆ3ü¤oæ}½/—¿vWÍPõ«·T ÿ‡ïýßG{¯øÝ}‘3e­k¦U¹Ûþ¹r á깞»ïùmäÅ_q–†ï)þ³¿íç§üGñõëÅeÇ>äÎEþ§k_Ø<<ïÛZ_ï{OŸ~Êzè“¿=¹â¹¯®kºøÝƒ£¿MëBñŸüËsÎS¿ø›oTµå?w×ÈÛúéäÚŠŽï½ýí­÷ÿøÒgåÁ\jßs¼ÊYñ³ÌüÝ¢¡ë³v|ŽV¼ÿÙ½oÎ}©ä¡Ofîýø»«´jË‹;_¾ÿBÆýÓ)óÿaïñ‘Äæ¿Çoñ±òoLÞòË'^YwàÃêo6(ÂàK¿<{èüò=wöñ÷öŸ~ö— ~fiâbÁcG¯•ìz°ÿÍG7ýºò­¦kkË>ø’}ä7ó“¯nzëì0y2Lsÿ}V7=,·÷|¡rs¿‹ñì ±q(ÈÆ}@ëY­­c}±^TÆÆ ÜþKûH«=Zƒ„Ý@ËØ˜öÕ¥l<—í§•í¡Ú·kؘʮfã …l<½)6hߊQí½–‡R ó%!qï½{ù »c3‰ÊÆ¿þû×WïØÑ¼2~àU“_ üÖd:šL¤è„5ÂaóßÁT&ƒ”!?™IG¢F'è]Ñá£}œ5šÇ2=ÂÝøÇB/‚µH„³ù6®\ÓìX¹ÖßÇM©Ñªk´úêÅÁêÚšzwŒIÜÔÜ\¹nykWÐM+Õao}÷âðørkG[ÎßPíñiµ;L´ôOÝ·ËóTÕUy蜎ÆõÞ|ˆ£õßBbH áPI¨Ú„žJfŒ°ÞÇÕ¸{“qÝéÝÑtÚÝJõ&Ýæ_¬Ý)#ìþÂwªt#¶ƒkêJ¥©“ÿPK’KA£ž’õ~ Ôrebar_upgrade.beamuX pÅ>iOÖY¶â“O¶c;qξKH¬8:[ DŽ/¶dŇ›>‰|–ζbY§9ò˜–óÎ I ÒLC(ZÒ”¶¤%0ÂÐBCÆ!ÊÐ’N å5¥ÿžÖö%4ókÿýÿ¿ý_»wRǪë)ªôD[d銥†6LQö÷)ŠºÆ­«}ŠËet%¡²jZÕCm ‚’¼ZWS±œ‘Le‹Rš’ˆÅµtr l@5b†¢ã!£èjÚˆ%’ú4‹¦•¦VW×'µ\ã¨JVscéO¦Ô´2¬Òë´dº@ÕSJzÀîóÑq-¡2yPcЮ 1YÂÓ†žS]z.‹ªñ¡¬#¤’}É,Þªˆ„‚ýtet-“7›Ž¡`cCÓR“$Óýš—(.Ú[ZP‹¿Å{æ24ÞüÉlb6$S‰¸¢'©dÖÈ(™ŒšN¸”DÂô,«c·²›²x—,3Á¸†•!ãç2U×5Ý¡ôiºáH¨}¹Â¼¿)m™¦Ù¸žÌŒÉC]}šfİÙ¼ ´kYÚØ”Q’é@Sq~Ù¦áT2=äÄÅ7$œY2BR1ŒSÝhèJÜ(H@¤†Jkà<ßñ”–UíI­ _ӇÇD¤s'LU%>ÕÖÖ›»Æ ]UY2WR©¼S…øÛÌÛ4XˆMN Ô´ ‘—b×L©£_IeÕ¢a-‘#v%Øc˼ªáÒ-üM ý¹tƒÔP^¨qCÓ71¸Ø)'ăGOqÜßHŒ©vh"Š*T ÇY*ÿ‚3@M³±öÒ:ÞÆOëåe9YJF=N–•QXî)/£ “’X™ ; sÈv²²ÜÃÍ_Zˆš"‰åÙ6DyÛ+´!> ² F cN“ï’í¤zeÔ-‹‚È^N¦Ûa¹»Ç㥻~æ[ˆÆe„ˆæ#‡9lDž -¹Ùü<às¾…Üx^ë=al-¹Ë`ébiÖ]i¢ÀŒ¥œl&.VG¥g“–!›l/uyx[—hØŒr ¸é± r”âœÒVŸŠW„!ê]!5«ù=!¦ a ¤ç! y@8U²ŒD"^¡¿ '8^œ6€ ô\¤Â[ÐEŽC=’1;‰ÂpO^ÈsøIñ˜—΋%n„í²˜‹D.sqBÌÊT‡„¢Þh8J—vq¶^ÈF²QÕeÛR,Cm‚2'ÊÑ.\+9@Ëí^¨ÄG¡H´q‘ƒÄJfÔ‚i ; 4¶$½ͤ`•4§C£¨y”Tn”gy*ânA/˜9Ùó8y#bt+²h€HD½np/x AiÈãE㸶[!š]M-oÛïfy#pvNŽî Èœà”™ÒÐÔ|IùLó‚ïçY^ŠØj?bx†cm‡äè!§Î59%Æ ëqNž) DÍ'-ëOZבõcrôôeÖã<0塳¨ù¬á¬áÕF ‡žÙbÖzRó½H§CÔ ”ï#7”‡¬˜‚¼°âûGXþ{é(3 B§™Mjbz§4VÌ–µÀR—…ÅýÉpРŒŠXE,+î’<´Ç+sAHl%9®Zó†ôB9ªBî À¨˜¼Ÿ»Ü“%¨%{#‰†–±+PÊj°0Ë_EúuF^@cåL“Ï×¹€Ë'œ+‡:ã ƒ¸Ðù 'EJ.BÉEËMDCO/⣊c·ømúlcʧÚ,£è Ž@ßñLÍåãÃæíÍwªÄÌ"AõšçADS"s?–á'‚‘ØÉ$à †ÆGŠ™‰ÏT-kc*pò§Còär<ÈÌTsñQíÂq\î*óN¤ârJœ§Y–<]ªÇ%âIkNÞ¥"‡G ào3ž©3+ Ï/(\UþNcª°ÛÕàv ¸=?aŽ+ƒ xw™ š%¼©)†4G°2ÍAÀu`< T­0òÅø!'Bnr.Lå\r ÜbÎ-TÈ.Ñ];1µ>· ¸–N<=1äa‘h-”h6"~”ŒG…¨‹5=­³ŠÚñ}Åæ·ˆC˜ Þ„)3G.E+Yf¶¹KÀ¿¹¸y@È3slÌ<v@<õ%¬ÌC¨B„H!/|Èݾ4L\ ùw Ÿ»¹ç Í@§Û µ <´Þ|äjõ¹}W;|s®hþ \1a‰ÖËBþÃ]Ã2sÁ3_ž ì|(M-žÌƒIhxz LüÅ›?_)¼c x¡ê6ôü‚Õ9œÑö-°õ@XEÙï°ðÞIÞÏ B"wÙŠÜÄó%Ħˆ#¼¨Œàa*·àWŒ9ÝÂW¾há1æL²¶háñ¾<áë€Þw6Y{Ð\²'¶™Gäu${Í'8 @ H\X.Yl-ò&b ZlZäW9æ¯">`~± 5×Õ™Ø`¾Í’ÿÈ%ü„ý2‹}§ÅFÄ|d#îÉ<„‰~.áñgÁ2©#—î±Äu ±÷[ªàµYïÂÐAôõDoslzݵYݸöW7?¶å˜ßùÔGcŠã‰þ£‡—•J­¨yëݧ׋_d7þÃ÷ÉGNìþíS·ÔÛ7ÿúèêëË^yñ³WŒ¾:»aslHÕ·?º÷¥Og—¯Ý¼cùÏ»Ÿ9ðæÿ®¾çì_w‰ËFÏün[ÓɺYwÝzàÖOn½ðä±Ñs׌QwžY¸Vl‘~áùzõãÛÏľ ÿ]ÿìg3P…Ïú¯Þ·ÿÄ…#ì£5‰¶ñÖô¾ðÌŽÏGk¶·V·J¸ —kqÜGø7^Ñ%}díV"Çgy‰å<´9¾¾’šºÇðÝâ#<þ=YKÖ⽪¨ü݆ï/‘;–†Žûþ¶F´'(´>›6'i–jÊ8åÇrieóý§ö„ÿW¿n]{gºtµ¦=íZÆHjé,8”Ûüÿ –Í +ú&lP å øñ;DÑj_2%¶äåL¦ã©\BMP…¹tBíO¦ÕÄ ]"A¹Ú®ï\Žõt®ˆ Q%MRc“´¨ñÊXc iQ04aÄü ½;Ö¹²cÕU44øÆxhQÿ•ñIõªž.¢.¸®1Ø&Ö™Þ®Wõ,¸;D9‚ ®ZÄ2ÚH«ƒ}àÿ £°Š[™¡4š®gµœW‡(É?¨ «þDFÑû“†áïS²ƒšßücÄŸÕãþ‹þZ ê©u¥}Yß ÿPK’KA+xVÌt!rebar_utils.beamŒX |Uš¯êê¤+T¨¤h C5 4‘&„%•4V.A;}T:ú¢»:  r‰f”[@Žêeº¬èᜠQj³"y› &t{2hÄúò(Å0îÑëe¨@|d+=fŠ ±eô>=ƒœgAa¬ˆ#"–‰‘bD¡Â=ð§ãÁ°në g}Ùä¨|ò€ÂAØt#[O¥VçÒNBOűdVÏ%L"0Ý–K®F\“B8)§’á aíMŒŨO õ̇¿XO¦  <K3kÏQ&í1ŠÈ§t5#¢§3:”è‘@4ž ã%¹dDGôHYÞ=éŽEíÄœçPÎ’#½fLL$\­þª³¹(÷f陘}d«8¡'B¨>ìYb©²ˆ®…@O0nXéÃŽ£…r±8*Òj¬MëET@™¢l\×ÓòYVñ˜!†0¨ÆÊ(^´Ä ²cD061“JÄPD²Ùj=‘Ccèo”¿M02hm›9@út+ñgS¹LX/®ÔˆíKZz¢Bh3ʇ·bɾÔj½ærqÝœH£(”ëñõÿ«áižzd·~zýÿ½ï®/?SŠƒ:Ïÿ£®¡~T½iÓ™úsë¿•œ3{£ë¿™t¶áù®éßµñªêÇÖŸ]iÓ˜ÌØú³GÆ47Û²CYJmUýÈè<1¹>Û%ñ°ó7ì¸ëq)y¡‚ãFý¨Ìåÿ¸ˆ—-•8ÞQÆq6Žkš!Ìž!8ÚNidÕ5CiÓT¡’Sx÷¥¯Y*—È|G™,k‚ÕÊÑüœªY• «Í-»· ÍÂÖm³¾'Çwi‡„JYáÓÚù½qžÀï²T>ÉñÊœ•û¹&Ti/ 6ÙEš]& ÿ|%õUJE•ÍáÎ/E³ ¢Ãíà[*핪\æz¬¯h~S"f½®HÖ6 ‚(wÈüé^«ëÁ^íú@±Ÿ£Ù+‰£pÿݸª/ŸBUƒårÍ¡)NMh´reMö5Z<>Á£j~‡¢ÙG 6w—ìà|N (nPÎ%Šæ×Í)T8á£MN[eé1 ^ÚÇ Pesl¤s9±væÂJ (°×Axq6 V‡Ô³Ø«pjö `= ù;:¶[nw¨~»ÓßHÌ*¶Ž“<ÅØê–ÒM’"ÌœI[R”fERj4{µTÑ&Uòb˜T0©MU´*&ç;*5…+ÍO¹«„ó„jíZì–jxñ¢¸y±¦ÌíÖT«¦Ti‚3ÊiVUìÍÆi.ÈŸ¦Ê%M†Lg'aY­ù7*Ã0AÈŸe2Dæ@É·4™,O®Ñ†$×!i*/º4î*‹â9¼8¼õàmÁ±.DËD©_mœX£YM@9 ƒ2‡Œ†¡1¢,Žß4ð{¡ÛMÇGòKP¹8¾€ªÏuIÓÑýN¡Ò ÍÓ5ÿ.ôÄd踺Ðþšx:F|UHf•€&Öü§(}ä¿ÕÚŒ¸ÿ]̰Ó{~dÄ3Js;¨è¿ÒÓ(5Rèa¥[‡@_оÂtkcfñ6ö6º¤ÔåÒ jó*êFôÓLtZªÝ¡ø­èÈÁíq(}Sjµ>!Áè9Òû²ts“4u4»°«fSWÍFW-”fÙIM¼8Kv /œ˜8û§JEãðDpæm4Q««B‘CºUãÅÙf8ªÀ­øü¢¬`‰ã)Nó@ÑB[j¡4¶P›Isx±Y>ÅùJ’VÁWB-QÒ‡!õ‹‚âs*lYœ@“µÀë–B¯[Èës\Ü&]‹»¤ÕÞyfމ•…Žc: û{‰¬±Ó >§@œ 8Žaf”ŒƒƒY§vi¹BA9ODÕÌQ]E²{X€êÞÔŽ\·PÑãò°/Ç¢US=šýJµX“¼¼ØFT8à-Ó4š‰fk6¨ó]Ò\Á~¥FòI”©y Æ’Ól.4ª§qÐ-cB.…Qòâ\3)>h_ ííšÇ ›žâéR^ôµƒ/-ëèЄ¹šÒˆ£kö«ó½½BмVÍS…ª»@sbôyµF´L§6W)ê’VAî2È_­óF´.àÅùDÅî‚oj ü­ZB¾ ZÍ”.WËÜëëÁIni Ëš6‹‡$H\θ̛‚BjÆÍ “]Òb„ˆ;h RÓ..œLK‘†%”“N²‰ÅRù€Û§ZTŸ ª>EÍ °î«Ì”)¼xX#WËò·¿f×Í}Ÿ&¡Ë-­$ßV’oˇ$^N7·,N…Ä•˜<õ.i…àÏÑJ"Ô Žì®ÈO,xñª1ÒU¼¸’<»æz»xqUYW—¦6j^US²šG¡¬g­Óª©UfÏÕÞNªg¸fF ù{(™,Ê+]ø¦àÅ55Ò€Ð$õ#Pý…†~¼úU<¼n©ßÓì‘ú1Ï )cÏI9^Ì€Ë .¯£ÍËu¶yå0¸:›;M®>)kï— ^̺¤~ÅYgJbÌ0ž@´Âd«¢Hã cò‹c0஥ú±*àÿ6sÎ%õyùaµÂ ›fá›ü)‹ZÛH.úÎpi^ç Cfì’ó·“Ðîüöj¿ùûGKkxq` }®E¸`l]Yþ]lÞÓfIë…VAÁãf=j“.\ÞæÓPtc9¯q:š©õ¸ž×B͵ÈÛuù‡…ÐÈö¯ÇÖõØÚoâèF<ÿ¨£üâ¹æÏJ<ìoß$n{ !q~ñ4.i·b_Æ[Ü á\»1¶JÛì7JÛí7I;ìƒÒN^Ü+µÔrÛŒ#dñ„ì4ŸØ4v™óÓ/:òöw­Ë£»‡[wápëî3ßC%Ý*qfÔìI¿âSý⪖™MÒ^¸¸·ðá¼?ôp­S†ªìrßKÕtTÝŒÅíZ¥°HgñâDÁI廊UR«ãytˆÛ@¼Ö÷ßüðÏæÅ{±Ü‰å~lÝ|ðù­ƒX‡d‡Ã'˜®ßÒäõp“t?æÌýŠƒ­*›(G°{+ŽŽüH{Aú~±CJòâXÞ†åƒf½ä; \|;ÈKòUôVµZhX™4…Þ1V6Ì÷ð>Ò$CœŽ™qR'Ïðó„~3ÁÇGÁx'SÃ*t‰5Ó{W`·Ë lßí¡gÒ>œÿ±YÒ4a«€Ò²>S€ô‹Ò|3 y?l”~QŽë42Ké‡ûe‰4¾-/½€ÎÂ~Ósæox“Và^ÁøW ð*Æ30–Éž¨etÂÇ3þa|˜G-Ð3‘á&ŠS.æÛT@=ã¹0é'~7ÃgÐÿGø<‹ÙjÌdx3`6ã¡ó_Âp‚¦ŸôhÌî…²„·Øjcø\€ÉR ÛV 5`“%|~ÿ—øÐQpöÅgÑy&¿¤à\K ì.cû+WÄsUÏAF'ž£‡ âIüÝÜHÞu¦ŸbeqèÄ |[[àðÿD_W s}ÿºü:†S^62þÆ‚8Ó^Mž[ Î~ £ߎwî Ú滸|ýÝÌöïd8ýݸžÑ7®e8ù4Àt“¯F§øv1{KN¹]¸†Ë×é†ò½’Ñ/e8Ñ©&–3=TC~fËð2:Õq ó“ò6‡Ñ©†kö&Cô:n¤fÇs#}@½5™é¡¾<Ÿñ×0œø« bLÿ§WÉøËПƒgßÃsÂÒžKRœ)îàn¶7Äö9~âGO³¸ý8ÓÁÙ^¸™âv£?2¬S8o=õù­l}”Ë÷'¬y»åŒè3?0-¼ÿ†ÏÛýAv>Î’Ûü|íeôï³Øs\ïÓTË{ßa.?çx˾Çèÿ0w3þCÑôs`š†¯]Ìï€R“ÿôß;}?‹oÛý_ã{;£ß(!\øñ_(/ÛýnSÞ²øË¹ bÍááâc÷\·tååJkÕ8yײ‰=¡÷'¾~êmã¡íT*·?U:zÛ_Ú–m~©ïÃÿ¥Á“8øþOÿ´ó«ç´ŠÐûs>¼ç’?4¿sòW ÿ´ltøùóÇüÆóÄŠŸ}|ôñOWѾ—Úyßé–{­O½ÿÏW¾÷òèÛ}kä•‹g=qÏŸÞȾ¦i>ºâØaõ…ÃCwÙ~v¿Ârøªé[û_°>×»ÍöâO=sûçO–=Þ5ÿñÄé1oïyuì¹mŸøß}¼ëËßÝõ™–iI×í;¹ öFwüŽ’e'',n?®ßóirmvaók^=±õâWŸýò£ö“÷:SGm«Æ=·Òvzgè•Ò“[Êf¼3æ¡ ‡-;î{ƒOÌþbÀ1MÛ¿ýÅÏtõ½×ž[°/Z÷aøÊñãïMþöõUǯù¯)o²pôÇÍ[>éã^=ºêdfÇ¿{ºÑ˜úúnìÝøñ¸sǾ´ð/G¿zs[ãuýóm?šÙô{ÍÝáfÁ‚_×Þºèèe5ˤºGµ£«÷_²_Oìÿâ™}ï8±ü¥•Â#}Û›÷\}J«½åÊMð¹†{{ï{âÇíן˜ò‡/. jï0°ç·m¸vÖì×[þü–³®ÔÕù1?¥ôÉC“î¿ÿòFMkyõ—¡{×½µxå¼ë„@ïË¿~ÏÛ±oÑ܉Gv¼»ûÙ†Ï<ûV™pbË‘—×´<ñ¹zäDéE}møN ½<ëHû¼ÓÎÓñ­m'ŸüsëÖW½V¹°¶âµÍǯþù©™?ûã„Ô‡™IZ‚sbó÷ÿ¢îË7BCÕ-O]±¾áí]G^þ]ÑVþª,>¶¦±û½×M:æ}eMÉWñ^›?þŃÙE¹¢„×G'|k¼‰³¶<ùIí¸Åá½=Wßù»ÉíoÜñæGñƒ»ž}{ÑöeW¼¾sû­|¶÷® _™ñÄ‘«žØÑ·nÃO·”|ðÖÌåëgÌ[tÑe£ß”.­[Õ[½nÅ£ŸÇŸ~¾ÖúüOÊÁ¯KNüuÔOj?~§G,Þ_³á¯­ÿðßöÏk÷Ÿ|}ÿÀsó¾´=wþrLò©0Í7›?ûXý?vÖ¬(œ…3¡°ß {¼°¯ gEa_öraÿölaŸöæ÷˜,é¾ÑéÞØÀôodžd°†ñÇNwìjÆÓESˆÍ5º›—ÿÿÿ=;OÃ0…oÛÐPEÙ‘èÈ”4ièclHQ EPX#'vˆó°+۩Ć„Ä/ágõ—0á„Çp|¯Ï9ç †–§µÒjjMæJ =/Þsý6’&†ÖN²úÃú°ïß .¯byúÙðÞ–iêù,ÖÙyÝ7ª~‡oåLVFCÁE Ë¢@âµ*´y©0$¤¬r4ƒeQ^b‚á°d˜Ä”œ´t†1-žüÕU°ño¯38q†¶3œÚãÀ9SwöWê>{w³Îàø…ªͦñ8ú×›û߸ý`»‹á(­iwDH›ÁkNL·ò E ’´CÍ¿G]ÔG=t†ì]òRD$ÓJxA,¼E"¦JY!’ · ‘°¤ˆ~¶ T4—&y óP*}øPK’KA5îÀ¶ „rebar_xref.beam…Xkp×ÞÕ][ëµ/¬½Â&`Ì 06¶V–É`¸’…ÁcÙ<Ò òJZÙÂz8»+ˆÓÌ”–é”6 C›fšNò#3´i'móhË$“™¦™6üèLäWš–L†6M“þÉcRÚI'=wµ–·LB5suïž{ÎwÎùιWÑ£SA†‘ˆ'c1«ZfîÃ0w †žÕŒÌ}†^àè[“ii†å©.ˆ¦neJŬ¡K™EÍšÇt;sN3*ÅÊœÙTÐJ¦ÞV·ÎU+…âšÓ-¡hfÎêF¶jê^gæ—MZ)b^/hµ’…µ|>“/zΪK\®š×y0·µÖAkV±dz©0w.ÏŠ%½¢•uîLµXá©5Uå,£¦·ÚåæõÜ‚)ê÷-V ËÌTªV¦fêù¦RÑ´Ìæ²^ÎêÆÚZü+z>S¨UrV±ZÉä´RÉl³!î­éFQ7HxÓ †3­ê¢—¾-êùfÝ(i•¹&kÞ¨žë´=fnwèÕ*Zié~ ôÔU¾È«·P5t-7ßZW£î—Ø{=Åj3l”5«…ÒbG!Aú–nd´sÚR¦8W»|SÍǨ¬-z %ͲôŠg¡à]ЗÀU¾-_4K \.h¦P‡£ëæb•µÅ‘´6S+轤—õŠåuf.yrlº9«å5c®¥ýj LA2fµfäôÕ´6Õì¨aÆ.`V×ʽ97_«,˜XËš–¡9»« í\¦!9lb¶fé­-¿LMGƒ#Êh¡ î[ËÕ|­¤gŠ•BÕvêzÞ0p[Tà@)ç?­Â¬løâÌ¡&Ý0ªÆô†`Øð-øɘ­õ=ûDµdõyílâòô÷ßÉGæà£­ç³ªh'ßBÛ(«Aßw 4z% º ¼”[Z8—pÜzîÜ‘`[OhÇÿWtE5@“ 9¶LBa˜–oÂý"2õ×Ez×ÀXËŠžŽÍ2+¯""Aa²yE&z _Cr1Rÿ5)Î1x-AÝ“Åþk(N²1F^U&ÈïeTñIqTVR?O¡¤âAtù›”?© ©Ýo›’bê“·{™Yb‘jxåó^ñ2¸:‰Ð%‘”Øð"a-"’Ï+?©^E{ÐÕ.bì:“¬J„N42ÃŽy‡$H!>Ð]ˆò?ººÐYcgmݯ³‹R;{ž º%â¡^H(l;âæÂIíœW~ŽzõƒS¿W|¥¥ç5º”ÅY&é÷ d¡¤òôµûÛÃÄ@.ŸBçGÙË$Ž:ˆÄ>IR2âÅ„}îb_9ˆØ×<‚°7V‰ $W§çÃèM4|³NO‰JÿM)NĉxI©„ÇÉXnmâE΃:D‰ý€x¨¡°•aùvjý2î@Ã0VÀpÇ2Ú MT„D½2ßî‚ã;(žx½"Ëû¢X Ém²è pn×ïˆâNØít;è”âMáP?^ƒ qVM2t‚ÍÒE™!)±ñÐ@¨ƒkhI:dXuRÏ]àyd²2Yi –ö '5Éx⺠´`^·J†®õÍѲÍ‹xEÞGëÆ¡‹¢ŽÖ€ ³.ãa0ZÆA™å»ÛD™H i§¬zU¾+Š7@:=îtz$ø²‰ÙOÈ M=PC~# …IŽàM(†”PoT†a¨m„Ä1Wd?Ø@ ù ºQ¼\lF2˜e/6A~To%J”D 4Sj²Î'An¼LX~SoDÐQÂfÊ—!„!)+€¬ 3³ è8’CɧKR³r-œÉ[Àxoâ-`¼…0ÁXVèI®-º¶ÑnHºèÛÇáíPlßÏEqàô¹ì“„(ˆ–>EŽ+LD!a˜{êDöÙïýº"‚ú¡©mêr>†#¢×„ȯ‹b4T¤®øP%?I—€iˆsý²‚ìVˆƒbPë1@m¬&b‰t6Ò°‘–ãiÆŒ§Å  n Ä@|AŽ_`‰_¯€ø!ÆjV!®Ä® )Šà-@k²Ây©‰~„8¼+íð ™Í„O0~»¨J;G® NÅ»"xHR¢xP†1— JILÄ%9ÝCÂ0„LÓ>Q•QÊŸJt¨@Ýl Qeê2!i i{^ay•vIè…Ú ‘tDä»Y>D%@x˜ Êü–ß Âƒ*ËC8ÔFÔ ùíÞ•H;½O‰†Û§·ïF–HÑçíð죱Æ#WÏnÏ‹ªHe1É¡zÉw76›`š:Æ;iGGÁÿ´Öp 6UŽ!ÀÿPx¸Uñ>¸Vñ>z¯â=ÞËò{Gc¢Þ[º(‹=è.‡#a¥øûˆ0 W0ßÚûÁ×a €DpÜ¡>ÔÇ$µMT}®~O7N dÍ cùx杻 @”ô"Fá&ñ-2ö‡Õå¢Û^¡@ýI¡1 GL[­ÜOõ kcýš£ÅIú1àc4‚:÷K š8¥Èm*Ü/ŒúØOBü¨8+ŽªRŠKùà³W‚˜i'¤`¿6Yþ`'iÌc€:è‡"ø0jEHž#BZ!Â4Zë¡PDˆÍüá0£æã`>AMDðämEyYÅÇh•ŽÁ'.>…:ÊòGUšÞº«4áv0ÆãH”å¤ä¡~ŽÑžg'!ÖtOÁ1›Z9õô˜J6%Éây%ƒÃ"¦×]F‚Þ^—iwà4`¬™>áTü8˜—€MZqæ>úA¢øéUí&b+}ðÑ=xð7¾ÐÏÑÏ%ýx½QfXþDOÓlN‚ó»Áù)û|ñJ[Æ4ý"6V^„™½ ËM0<0è6묛œ™‡Ñâìѵà|£{Ø™éXåÌ«]ßõÚat8k †Ï¥³ÆñuŒuŽœ®7¸tz\ñltÖ4ÖÍ.¹ß™©|‹ g›+¶íÎܣߥ3èŠ!à’«.ù“ûN—-õqÅ9âèߥ“rÅœrɹ䓎ü8 ú;œMÞGëÂô:~Gݰ³fœ˜–sóŒÖ*TÜÑ¿ÛÑ?åè2M·þv¦“Ž<íÌ wÏ¢cGŸ8x 7\xz¼hQÌ÷akì¾'f&Gs±¶‡ÿò»¥Þ“ü¶7¸Ö„5Üãÿé:þ'l>òÓÝ/.ýköê÷ Ÿ½øÇG¥g[–ÆÞúòÇÍL'£nÜwãâNÿò+ë†ö îÝO¯âà6eÓãßyŒ|P|áôcã_zUßøjäzíï÷lïúíè©Ð¥à¯½ýú¿/½{¢ïå´<øÐæ[?ùÖ Ï~ûú£Ï|`ýêþÁî_?ÿTßü–›ÝÏW®n;úã÷oq}\ÙòfïŸ_zê©â—ßè=ýÖº7GR;{Î<[{¨öô÷>þÈxbû¾c{¯õï~|þÆïŸI_z]ÛóÑc=öÁûŸl˜nÿÑn}ÒôÙH×þM1½ Ȩæ¦zÖÜÆå)g=s—3o0¦9­ï1G>zLJ51æè Ã8èÔoŒ½ŽÎ»^gÊ·:ý@×´ÿCŽŽ #謻a 8:ë,úZë`Q¹ÏÁ¢/zVg½*?b©Þ…Õœ÷ät֬ؑ¹7µçá‘wÒzM?}ñ½÷ªgÎ$Æ*Øë±õ9ªï­.Ò߈&xó ¶\gÌZ¹¬KT¡¹Z³àwèÃéÙb…JØâã-Vr¥Z^Ï3+ÿ6Ì#ØËç!>36~ 3=6‘\`V©Á!5Ü• ††"áè²<‘ÎŒ=ºÀ´Î-9˜‹F »rí£Ó“ÎvóT0WCgìhÏê† á.0MáÁ݃a*ã¬bYŸoÎBüoj¼&jXëÖ‚vèõÿ˜À|µ¬ò‹šQ(ZV «™óÕ€ý§UÀ4r•Ôu£t†abYÓ¢ÿPK’KA¿…jjD–priv/templates/basicnif.c½U]o›0}çW\1©J[Ú½Fy¨:"EË҉ѾT•ei­;2&Ëøï³ÁHP³uRy0²}?Î=÷pù@yÌŠ„€K$Cœ¦Ÿž]ÇÉV4†@² MC’‹BÆ$*·Äƒý>IÁHU¡0øq{Þ°€ÍÝz=w¥M’B®d+gïT}ûgÌF´ÙlߥP˜ç‡dámVKá·¾'?' €ï< |çå °|Š}Î?±à¹†×¾»‡Çéü\î¬L +*øÿAø $CΗ:-èn “?x„…&Ó„Ø»šׇKÿˆ£Ê·÷fmvå—S9U/åû3ßVs,š·–1åcÆDŒ¤UàdD|ÿÂ÷äôéä$ÿTwÂÜ0ëôS-¤ ¿QMŠõm\k#IÁyÏn`"‰*$ï…SÅ–‘ÏM°î+‘5g®xq§¾¢ƒTÎÙæ½›tm+Oj:B_ƒ¶˜w‚&}¬-K(Ö¬ñb{‚Ø8x&a›mæÁM±"€y IÉqFc-–jÅ`EÈH&d©g‘zGù©ÚÀ›µÑ^Sâ©L¼©Æ27î]Q†UÁ8ÇïÁVÒJ°ÂþIãƒ(OE[Þpð.~Ê!­×ÅÁ3ŒÐM\GüîŸE×_ƒÛû œj&¸<`=ÒÙì³jtéÐèáácŒ4š+#$Enx]*Ô@5V¼vMÁHwâ`­±t<9¿Ì3úÃ?ñYœD:°Jè§QI¯m8jã"H–êeã‹«³ûIΔOf! ÀÊWAïòÛ; .U#+,hšPêÒ5Œ·ý©UýZbå󃺪åÚâÛZrLJQ)„ÑÜû¸D¯&S­û´²6ÏH!$×b‹ó·åêÄR¡‚<òøáK#ãûËéŠ.c;`Nçóká¦Û`– ;SW Ï5]1ÒZûÙÑ–¬È´SQxýñäÌ6ç†ÉýdéwîeÇéä2wËïãz,ãnüÃz1)¿jkÌÞ9þ»˜üÞïqP»ú¿P¿ol¯5–<0¬õ¶æ…/nág‘:9u Öå¯P4„lô"´"ýÐi±¿PK’KAý+¡R‡ priv/templates/basicnif.template«.K,ÊLLÊI-ÖQˆ®ÎÍO)ÍIÕQPÊ­„0•jckõ¸ªKRs rK@2I‰Å™Éy™iz©E9J@~qQ²~5Tcm-X—Ždúäx4É õPK’KAȪ8’‚priv/templates/ctsuite.erlÝXmoÛ6þî_qÀä¼ìc¶nhÓvйC’~ ¶N1‰ÔH*‹çê¿ïŽ”l)vìd±S`úbŠâï幇GïïÃXç¹V±CëÀ–Ò!¤ÚÀlƹNªª×Ðo™a¿5_~;¿útpØH5ÎÊãLŽú{-eGõ‡£±;œ˜lÖöô½¤  m\,²Œ§÷÷[xH |.ÕØI­Nƒ+ýü ç*Õô‘¿óÞÁµ+ ²âà†ç¾Hò]§p‡Ó£{‘•…ÆÖBÑŽ,‚Þ t¥Q²ZÆk²à4Xt`*ÊÌAatÆI´a‡ÖÃÑu 6[ µÃS¸j¦Ž!­=iA«l 9 åxŸBi1á¡ñư‚fãD8ÞÒd Ú1¡¦ i_l™`ÕÞÁ­D¾ì뙓9:#ŠfÇZ%dÉOÇUu³£Lß]¶Þýw~¹©£ê_(Ý3?Š£?牉ü¤}¯’+Bë™°h«¹¯%AátÞ?)ää(žæ¤ÓØoË„…N†V! Á3øNˆø«D5F^NÊ4Íx4»À…»š «ÁÒjhá SÎ6ÍH*Lçæu¬æMƒ<)÷VEs*škú­š—5Î ð\0¦U~ÇÆôw`NÔÃè1©jn1ÈYÀ—ŽP*¡ƒ6 š ‘„8-R9¼EÓ?ˆVŒ¼ÖE¬h½ñ/´{Ä¥r2c‰õݪÙTHÊÂRvשé*išeéŽcÁ%.I Rð2Õ™’‰sëI#•Þ£YG"bA#MÈ®¸ž¥’Û­ÒN¡ìª)ða‡e ¶«r Á‘ûT]—aÛªÍ'ð¾Bh-ÛsÁ7© a$BM¡`— & ÖŒÝÔC³‹†Náôáîþæu|0rád ŒtS&{ð@UÓ v[ÉkòÕcƒ®a ÊnRj91ÜPûãëÇo_>†v –t˜RÅÖ’Ÿ}L¿7øQq¿ |Ôìi*3GeуõyýYK}WL©È,þ¼IœŸþŒ<ú/b\n1Ñoì³èäåP%¯S7BΔϗiûºI†Lleö`W$ÐeÿL«TÞ{˜=.Oü¡r'‹è…ÕªjÞ‰‹“ØŠ{¬?Dõúª.¤Z7¡³Q´ÔÞ½Ÿ—î£/‚‰Î©n}}/ècì5•¡K: çïMª ÅCÓ„ÜÔ±µE£¬ÓÝu(åœi]dò¯¸Ï‰§;BjÿÚ­`jÐSŠHßÒ=òˆ?±ª ÖsO$"FtR褢Ë,á×+¢òåÈ`®ïѫŠÛÊêA¶vî¬DÜsÂ뎀Ø)É6á^ËÄÓ3WRþCÀµ„³ŒZ}êDJê"c+ê%~”}·kRðhÑ“Ã.ùaSÛÐMNh¾|óMÅ&FºôW.SØ:7¶æR¸h\^Ä8Ü.´znMl9ªêÀ;ªŸÉH(Æ“U-ÕV€ñ á§ÂÛRÃËÐø,Úx æ¸í·“úJñvxÛ@B;C7? s8²‹ìa¿¹7ì–œ6ÜNº8Ù1+m½Z³zéüŸ{¡'‘ö¶ì÷RÀ¯ç?žçÿMš:x Ìw@„Û€8»÷<„¯cЭsç àÄKãÖ_ù­ëÿŒÿkà"ºž%zí±¶ÆÛ–„+ú^uãÿÕ]Òø¸§ ä¸Gu 2§¤åTV”Ù½ê°÷/PK’KA}Oê­P_priv/templates/ctsuite.template«.K,ÊLLÊI-ÖQˆ®.I-.ÉÍOÑQPÊ­Ò¥9©Jµ±µz\@‰Ü‚œÄ’T LrIqifIª^jQŽ Ò¢_ ÓY[êâ –jPK’KAôävÞ priv/templates/simpleapp.app.srcmŽÁ „0 DïýŠà9,ì÷Ȳ¸6HØn-Mñüwk[P\s 3/ÌD‡CâÙ#¨fÉv]Ñ@oÔ’Œ‘C¥]·û ‹ìâÙT¤‰%Q$‹Ð¿ªw ,I×ùRôäð†H²Ž?ÿ EÿæÜ£Ç§ï¼KqÅä—¢L¾˜ PK’KA¤yE†\Ï!priv/templates/simpleapp.template«.K,ÊLLÊI-ÖQˆ®N,(ÈLÑQPÊ­²”jckõ¸ªKRs rKRÂÅ™@f*PJ„‹‹’•@‚EÉúÕµµp \:ãA R‹r0tÂ%pê,.Å¡&Ô PK’KAÀ­À‰œk priv/templates/simpleapp_app.erlÓÍÍO)ÍIÕ¨®N,(ÈL©­Òšz\\ºI©‰e™ù¥E@‘œÌäÄ’Ìü<Œªª‚#BD!91'')19»˜K7µ¢ ¿¨D#º¸$±¨DßHG¡¸$¿@ß0ªË–r€Ûr*™Ïv»F|0ˆ ©,HÕQ€°‹Ò‹5tí¸€ZÅ¥V`-ñ9™yÙ Ÿ‚< 6 $®!?[ PK’KA‡O³Ì priv/templates/simpleapp_sup.erl­RQKÃ0~ϯ¸—A ©ë|TÄ +LÔ§QJ–¦.,MJš¥ä¿{uÝêÃÞìA¸»/Ü÷}GâÊ­–´ëx]«"„¼iëèŠx+wü lë(¾HwPu}a6ƒ‡×”Äò«¶ÎÓMã¹ó¹Vf?O²¡áíŒÁµÞr±oF„2ÊÏ§Þ•ÔØ ÎB‰ˆB Í2Ÿ vJN°%ŒC¸¥2’>®Òõ’¦ Þ¿k1èÒã'b°ÉDVÜHã\'Ir`-ÍÂ0ÄíÿcÊÖ¯¬i¦ú—Œ|hñŒQŽ›?åN[Ô›ÁýóËòcýη^ˆi©^´x*Æý†PœøÄ¶³he‡ÉÈW$ÇŒV2X$á×bÈíPK’KAÛ"'»ŒÏpriv/templates/simplefsm.erlµS]kÂ0}÷Wäe¡Õ}ø´‡ Á Â6‡2_DBÖ^5˜ÞHE‘þ÷%ÚÙV»½ØZšÜsOϽ9× U°‘@‡yŠ Iš­†û K¾jÑ 3{À\ б7šx#‡¼¾{_ož‰4îîˆ{ó²,ÝÏéoÐ×B!ñvké¸"ö† G>:54“WíûY¥òÓfÕ_‚@¡Û1¥h`ÈCh?vOYr $0Øj³oß•â=úi´sF œ+›¬! ºB¦¯`¾. Ý©¶u…›ïY§ ûYYë²K§Mâ¾kJ¯ë9;HåsiÌ}ryr¶¹C¦3ûÔë— ·|”u£E|®û V9þ‡K–™æâ,i»–)ó¬U2¶GÂNŸðyÿ¥°?(X?RáSk¹wˆÕVJ”÷sQÍG,v‰ÊÑeSP*¯”:§ôf;J” Ìû™çA¤l_\_Eðö5Ÿp¿ÿãôüä"8©môA&Œ@ªd©t-ìpÉÖ“ZH æçú\ÔÁG¥JÉϯX¡0x)²R¸!~7>WBh=±BÛ4—Æjy³¶RQð)Œ¼Û*#øfèž½t“%™¨ª`ÀŠ@·ñÒ• ¼BÁšŽv÷-ÊÖ3B5‚ã®(]ìc_ŠéµÄ|“<44`δcšv…š/#øÄ:ïÌøï G'[!'%‰+WU}r-‡?ˆÿw6;òè xÚZÿ»‚ªÜYáZ”˜6È=I<Ï?ÜqC\¸ÜøÌÚnNûf•$mb¬j‚7®×wi×ëÙ¯®Ç=ËvÜSâ«Þe,Rz)s' ¡MKÔÄÃíƒó'³RÚ»™M¥Ú±N »d>vàáyT+f˜Z• «ê ãÕ9=?OÍú›­Ô2W«»§•ÌyÝp8"Ì:Ÿ17óy4’бÍ=¨eovgõšsk÷›ÂmŽ*gƒ]ÊFb‹Ñ°”¦>'–”åV1Œ™K·õ8 fÿ»×y`²÷øXë¶¾”?­™ßw[jÖ«>g¢_”± ¿Ü4N¬*‘Là´pš8m:¡X©éûiGã‘fîÃ$\æŒ3›· À¦v·w·´UÏãy´tÝšgB§ «LÂù42BþPK’KAì,?¯ˆÓ"priv/templates/simplenode.nodetoolÍWÝoÛ6Ï_qTZ宊=(Ȱ.ëÚ>t’ìÉ3F¢bÎ2)t“ÀIÿöÝ‘”õa9Ú«üAÝýîwwäÝñøf?Ì`­Jž×5“×'þk&dÉ¥Õü#¯3xyþ[vef^^Šš´ŽßfPÙS¯ Öœ¾sƒÜÒÛÙ×?CH [¥Ð[^7\ÃE¡Ec¡R„´\³Â dp#ìjñ‘; ´¿£52~¥¯M³Ÿµ‚S0–i›óf]ÆIê–Ñàë[KŒÀ.90TqëÛsn,¤p‰‹Üþ¢ÑªàÆä${ù"… ¾’—ˆÛ_p¢r¸ä ÅFkLP}z#%ý%!aŸ”²)Üð'u WLÔ§`†ÃVr›¯¸–˜å¥(1Çy¡¤ä…Í 9î(&),+×Yƒðý7 *éü³zÃSh”¼~hCÔ>juÒÉå(Ä&„„Ê0ŸkfãˆÐáSCôAsƒ˜%yfóìoa:&‹ûöY²ÚÆ/·Æeèo³Ð§>6ZŒaÄßU>¸V”LŒvÅtÚ…ŸÕš³ò.P4¼$†ÌqLÁ(øgc,”›u3FeQœ¢CþÓKô19éQ4V5û{JŸÝYÁ꺗©O‰À@~wýôŸd1°€nÐnþZ#æ1;WJ}3„òˆ•¦@„÷ªÜÔ¨óûFb‰Pîá¼)hì™wÛcÒ`-ŒÍ­Ê™UëØ#&£Õ´‡Ï¼5Ý2îoÂöÁ²2"Ö½9Ù[ß^±9§¸¯™QrïPMÄöüÏ3Ú§x¼*, ¼Ì vßg7>XíØ>Ÿüþ‘l<š£Œa)_›‰´¥@q{e.¬ÆÃõ?¤‹£Ù }ÉciüÞó«–þ$Z“N~ñH¾&{@î}çBÀK‰ÿeØ5 ¡ÓÖªè=¬ûPPîý‰ ÂØUvúÑëe¤'ÏŽŽ]•jÄ«¢èwÞ]ßÒf0™ÆG£X2èÐ'#¨hf¸-”Z Ž~¹TUä#Vüˆ”¡jîuc×fÇ{ÑÃ%!LÃd`Ÿdk"dðψ\¾ãt‰ÍuÚS`MƒÑt­?7›ª·qB”Óøcó(ÛªÑð2=&)ž·¨èv1bcŸñ‡Ì’`Ïf2á™ù~\3K¥í·ó «ÊÈ•í&Í ì ‚²‹ Œ{þ¨?¶Êóú¢LVà"½Éf—øúéSˆ`V2¾V²u^­¥/0^kk~ò7¡«ÂÚDe¥ÐÎ3nÜ4žù¯Ü­µ[Øeé"Òn CB8Ü–9¿åÅ/5}>:Sƒ²Z±µ¦Êþ¤É¢<‰2QŒÎÔ¦.ÝôIÐ@äŸ}ÚEiü¬¹ojuÅêר}Èf'q¸ÐNéï4P’¿ÛeÞõ íâc\¯Ê¬ZqiB£_¢A|æ¹ßÖù[…[pllP¡œ^×vã÷XcŽ3¾‡:Ù' Â"ÌPÏ'=lÓWhlÁ&gî©¢J°‘$½HLœvïò…ûó¡ñæ>˜)’ÞhJ{Ï~#è’8`þ¹@~‰…a@Âø ^Š%Þ;¼Ë€÷æ+!™¾£»¶=¼-ÒEšn/dnKñŽÃ܉ÏÂôãsBlÇ!„¸Y"´0>§n¥ r¢ö‹ë4«£Çí*žòN׳qkÊþínß”CÿZ±3%m°B-|gl¾¹)˜l3Ý“oÛRI7b$}SowÕö*‰b“Ã5‘KgÌ5“§ß‹aœ©ÝI—‹Ì}æÿØc¨;ýí¨Ò´ˆš¡7L¥-W’róØAfû3ÑÖ CøNVêQ/{r‡ËÜv­4§JÚûñîeùE ÎbÕmôPK’KA‘®?WÚÛ(priv/templates/simplenode.reltool.config•T[n¤0üŸSXH‘’1ÊöË»‡µbld{FËwO7 ày¡,î®*÷£Lç[Ÿ²ß;6}Ve!•£ØaH—0¸@¡®¶²ÖÈ”Ipê rHYÇ›¦8* )óÁ©fˆ‰·¹5ã@§,é:c%(9 ž>’%¿ÖÄØ8ƒè5àƒÄBã÷q~U]b‡»«}à.B7t÷]ýP¶´6wmE€ÆÙiP— %MoÉ)#ôe´ðWè“„xü)¸pä4Î㆒ì=ÁØË ûe™±]0¬eìfod»]‡.« Уºñ%íœæm[/ª¿&¸¶Õž:L4æ…m“™ühy—Ï´8{“ù0n’r[\ª&Xû\`l©\?b¢=ôÿ1µ¼'Ñ-é c—1ÿ:¸EW±Z§¦r\B^àO*ÌBÏÒ›µ>C?UE*ø7î1LÃÅÃ2Û¶¥v®3´ß”š1C$CÖûPK’KA·Ì£rÀ priv/templates/simplenode.runneríX[oÛ¸~ׯ`]µiÓÊNŠ}JáÝ&±“_`9-Цk+móDuD*N6ÎßRw«iÚE‹c ¶B g¾ΕOŸ´.YÐKã)±v-"KkÍ<¹<øå- <H –„µâ=˜D@Joˆí_ˆXÕ†1> ºã©}<î&ÓNoÜ6_¸1ïöžµvïÉóç$\{/3º£C»«©î¶v↔®;9Öd•}-*Ý”ælxZOãó`pI‰\Â_ä0Ÿ "|G, ˆ9ê4©‘>µ[r¶¶X¥²Îíî¸m×¾sE‰ˆ#dÍnÄBIà)Šƒ…8B uÂ0âaÄ lN>“'Äú“4ÌÓù‚FúLfë%wVlFž´·(Þ"ËÀ ð¡7Ôù'VLŠdÄbÄÜ#æ;cÎÊ@?v  ’H®pÒˆ\:‚EVEëòv°&RWòèä3!…±º‚%b…ÙÞä0`g½‡Ío•ûΊú¤Û3 w†¢FNXx,ID}ЏœÀ#4’‚°`Î {r8žL»ã³öÌuäÚV²K´„t"9¥‘ßôéÌŒîxbO?Øp¶ŒÇ3Nv8Uןî’{sâ3†@Óº^5hPæ„ÉD}ÂA·hÍ„:[ˆ7%ÓÇlÑü·aš‰øtOù€?ôǧött8yßþ&õý:‡$ rrí%[êŠ[Ñty0g‹oi žP~—Ò¹€²ÞÇÃÁIïôñzøäª×2IUϧÚwo 7¸Rg 0 DH O¹+™G|¥þÕ;8ìw§`ØöŒ."’?,ñî³`ñYb ótK%‚Ý%'Ô­J=q¹t®Á® ÍL,€ÃƒPO¡Á¤Q³‘$8˜ý%µ¼ uåjà» ™ãq·o¿7Ô÷tòiÔ­V™lˆ³¾";wˆ¹ýûYBŽ$ß"ƒäÅ<ó0¾z&f¯Ñ<ÔØñ}¾&«Ø—,ôÑ Wa]å „®Î” ’Š[€ ÎÎ8SA3ȽK0æ[”ÖÉ»2ÒFÂV+¾–FSØÜøŠÃ¸œ_1j‡¿÷ÉüÂD½ýº‹äÛï$É9?쇞G0 ¨õ˜Ã‘#Ø$—:;ªHÙ.²{-3MŸØ) 7›Ê8}W+t.`Á$#îkσ³2ÃNw2žÁ¹dÜ[4©…%$–væT´D. N=H,©ï×IVRÕ•EF~ñè´€ÊoI<^R÷Jé2g‘,¯ÀëT¼°@È(v%ã0\¬Q s¿ËÊèªð¼Tø)w ¾¡üXúu¼[8AåÚIËíwíöÌLHBx7Ë^*ŸA·:„•š~´ë PˆME&²ž4Ê´Ú[ÒÁkÒG±ds šà €Ï™98 Xy|؇NOÑœ4.vž‰‹Ò€ï¹!Þw±ºûýÃA§&«c jê¶@ÛPwÍ=JoB¯J̲—y#’vrÙ«‚C€öØËs@ŸBXí_HC5X"çV+yóëóÜBo߉[ð°è¦½) íÊ+È~’ú·Š¾Ùlf;”ŸÍb•Æ-1K½-ýœ± ¾Ùt(ËÁæ$¢ôÈîl:‘³àÁ‰»P‰ Ãðû²´Uãõ:¤jÏôïÚ³üç†X\Ñkão‚íÍÅÖü¨Ä·}ÌÍÝÖçË/ÔY56ÛE¥ÊŒWü׎ƒ¡ý£à-:/¢Ç\úB?þtú±7Ø­àQ~M&Ÿˆ=éA}z„>7߉ôÍ7Rá¸yÈdÉ}1[†¼dþVÍD˜ˆ¬€’½ú,„™hêrËzÉ |fW ’ºµ‡ÁØjyôºľ?ËÁy¼ÄTøtß/¼èVÔE´šŽŸ’±^S÷¡OÖÐfá¼ qfÃe×\*D)†?Ë9îK΄]H/ ‰dIÕ[žB„~ýe­ÈùgãÇrUBoSŠÜðª±kZƒ/,ÁŸ„ΑÒq—õ5:)Ç=ûû*ò -Õfl ¨ËÊ¥¹P±^å¥NrUé¶ËaîgØSM“*ö¯µˆžpªÊÇá"r¼‚Öy+þæ¡vªÏ„ÀL‘ì‡Ú½r4k5{ÎP´mH·Þ¥{Õ ÷ûºÝƒá¤[GKúçö„À[h\?öô|Õ„ðo.þ„Ó›ÏÙÍ·š¼Ù#Ø)ZäQ³hÆ2ò`1ÕÃSº3êçØtsÝPS×(â°Ãí49ñfFœa&f ÚòÔ$>7ÉïÔõ©£µ‰IL⫉Ÿ¹ ñ–ü'†É%õ¸Œ¾N/#•ó·/ùš^ÓèµjH=z/p¯‰à0N²T}¦äjYpXPvæ±PnQ‹£Pö"I/éÿGÃáä¤wÖm§à*ÍRYÍ}ÅWÛ–t\¼„ö&÷ÿÆ,¢¹v¢¼œ_ÝeqFpÔè÷š°nNI»ýó6ŠÊFãáiñZdü/9v´e­V«à‚Ç}…´8œTUº²”qíe¦†!ênžÐÕ%õŒÇ`*0,dô jÛÊ6hÖ–¼Ù`„>¯ŠFr‹”X©Ðp§<ÂÖð ´`¥“3Ñf«||BNÑ5:ÂÖ¶i@Q *Ü‚ò;Ò2‡ªô¢>v!¦÷áúè!-U ¡ÐèâÔ´%œ“^„'-\x«käÈ6OG‹qÿ{1yŸÎgpÕ½»9’æ[T5< €-¸@ÐZ?‘þ‡£Ñì+Ï'‹þpžO¡×M~PK’KAš/Á”œÞ ,priv/templates/simplenode.windows.runner.cmd¥VßoÛ6~×_qÀ"A+­É£~q‡í2¤é^æY¥%Ê&,‘*I;Éâäoß‘¢dJqׇùÅ:ÞwÇûî—4×ÌÔ² uÍñ„,Y.hò§'ûÌËçgT)ÖÀ¯¨6[t­e½7 Zj¶`¤;l©bÂ@É+ŒTï:›û-/¶À5P­÷ +-|Íœ…õJJ“FóJ*øåÄ%«y£³ù\ÀEL^Êö}šÆ—PJ8Ehí2B^ª>nÅjF5Ó9F‘C–½Â“øƒ*Í`q{÷Li.PQöæÃY¥dÚPer¦ê´¤†ž¢4rDŽήÞ]Ÿ%ad96í‚¿ˆsÌu 3Œ97Š7À”Ñy-z; òÎÜoÑ¥gÄŒ¢…AG5(¤ÜqÖ84)UÝeèÐäVÈ&‘’‰o²¬ß â½fkZì¾CO< ˆ«¸(µAä– ^ä þ>òíTº.ļCd–DäÏ1k.F…³‡ ÓC–ˆñ&š©/|«’¡kIþŠp$A®â,C*tÃb˜o$6¢B-X·ºîõ^Ù‹ f8Q®ú= c­lOJÙ†:Åz[ߨ‡7o~äªgq äÅñ}ÏÔc¯wB¨¥ÆÐbÛ«;iD·Ý(Zž։ќ[ _ÅNÈ{·6 ÎÐÌEŅ̃µÃØçñþò™Z‡¤­ŽŽ’ý“íêèÙ¯ŽžÈêè"^»Èа à廓g¶¸ù€ }#Ù:¤ì÷UY û…@R@¼èæÅ­¡ lSmC¢íù’܇HšP´MÌÑ”ØA€Þ¾¹Äá&Ì޲pìEn\ù/.ÓxÌ7è¹óŒq-È›ƒÛ¦tÐdÇ­ŸÐ½ï²ó®ò•ç±¹méYc;ÿ—ñÐÁþž“—{›Lñ³?Ýb£z¡ÛŠo~n¤uê±®fyÅë`•é…qø~ÀΓ¯¹~9öÀ]dq{{sûiñçâÓÄg?•Óm¬à­ÔÆú Vm”ÙWÊÿNf×Ξ H°»ô6ÌÁœô· òu„ð…0Úþ’Ãfq»çÚîžü Ó-’Ï\kŽãêø½QìpµÖ¿+„  áÎéáO=~mßò6ÄçÀâ÷›»Å9|þúåÎj1ÍE½/»—“‘nþ½¯*þй9q¹—_Š·Æåzº#üç>ÆÔcG+b’4 דaó_ÝK‘\ecÀ¿PK’KA­Ò.´Z/priv/templates/simplenode.windows.start_erl.cmd•TMkã0½ëW ¦i]ÚÞ_ZØî¡Ë¶GƒQâq*jKF£ í¿ßñGd'4t×Fï½yoFvÆj·ÕµR™§~iÏÚïþ4d'@¾f¿O胠õÔ’-¹«M)ç!8¨Œç«U2H=‡7òŽå%lÇ&g¡ìU„*8éÞ#Ò^.TV‰ÐÍ#,JªMÃéj%²ïd9½½º»º_â0.°ãàJÙ…yz%ñUôj‚ª¬†µœÁ›¬+©°º!Qz:ðÎAüTK5XôT“fâ¢4>ňÁüp0N¯í§÷ðûõöä¹K«my ÇZå]´…XNJ¦èSàYÜy̘úh 'iÈ.]Ï eŸážbðn¢²ú£Ìè5Î¥1ß›w†;7-*S õØ<ž´“JÜ JWS}¹Gßòø““­³•ÙÁìè¶-†ê÷'µªeCg„æéÃ6—£Èû/Ëû&鿇Y›}3^Ùä~á4JœØŒ ñˆã&ðð• \oú‹w%•q 8¥—b‡î€c/ÙT¼@ÃÂñ6Å;•íœüÖÏê/PK’KA“Ù–”\”priv/templates/simplesrv.erlµR]kÂ0}ï¯È‹!]·ù¶‡ Á Âġ̑Ùk ÆÄ%©8Jÿûçú±½ ÖZrsï9Ü{Ï *Éà<7úÄ“¢èßáìØ‰«Lã$5 O ý{[./âù2žô4^Ÿc— z=þûx–áË3¹±\IŸJ[Ó{Â…¯ŒeÚRÁå>º]·Ú~µ¯î§à’Û莠“‰ºaBDƒZhlt_†\n• ô},è—Ì‚/Ú¨Ä!\i Ñ Ý4yqmm•–¸ÂÇË€• µt.”Û‘³í—‹ÒÀ­ÖþëÜ ŒïùðP§¦>W{‚üKáÆ©yÓ9¼g`,At¬Õ …uòW8 GñA‡_2 ¼±˜NMú $Õöâ ‡éÄýÿ€)Íè›dFI×c¤ö®¬fSLg"Yy%qõñÙjÖÜBÉßšªéZ•Ltªé'PK’KAZƒ`óJV!priv/templates/simplesrv.template«.K,ÊLLÊI-ÖQˆ®..*ËLÑQPÊ­,N-*K-Rª­Õãª.IÍ-ÈI,IÊg™©@uz©E9J ¢dýjˆÆÚZ° PPK’KAžxè[Ø getopt.beamPK’KAß±«F p „mustache.beamPK’KAYÖwKÝ Ïrebar.appPK’KA\@‚¿.° Arebar.beamPK’KAboÛSD—0rebar_abnfc_compiler.beamPK’KAY«¾O°ü !6rebar_app_utils.beamPK’KA‘i Å” ,>rebar_appups.beamPK’KAª`h`ÆHrebar_asn1_compiler.beamPK’KA1 …· Nrebar_base_compiler.beamPK’KA-й+,ûVrebar_cleaner.beamPK’KAþW| VYrebar_config.beamPK’KAÃ9XÊÌÜ'crebar_core.beamPK’KAô‡ÚS  úzrebar_ct.beamPK’KAB}a0¹+(ˆrebar_deps.beamPK’KAÊ Å P¡rebar_edoc.beamPK’KAOÒÒ« H¤rebar_erlc_compiler.beamPK’KA¢*Ò(‡ d)·rebar_erlydtl_compiler.beamPK’KAgÇ”´Ô éÀrebar_escripter.beamPK’KA\ 8ý#P6ÏÇrebar_eunit.beamPK’KA–ØœQ¸Ä  çrebar_file_utils.beamPK’KAA]n[Œ ðrebar_lfe_compiler.beamPK’KAÿ¢Ä¦qt›ôrebar_log.beamPK’KAeÕ3Ǻ$ 8ùrebar_neotoma_compiler.beamPK’KAD¶¦U° +rebar_otp_app.beamPK’KA¥º(t,° rebar_port_compiler.beamPK’KA @÷¤® &rebar_protobuffs_compiler.beamPK’KAþŸd“ Äø,rebar_rel_utils.beamPK’KA)aû««Ì½6rebar_reltool.beamPK’KA¤aE" ü˜Frebar_require_vsn.beamPK’KA×G 0lJrebar_subdirs.beamPK’KAÇP@u_ºOrebar_templater.beamPK’KA£ž’õ~ ÔK`rebar_upgrade.beamPK’KA+xVÌt!ùkrebar_utils.beamPK’KA5îÀ¶ „ó€rebar_xref.beamPK’KA¿…jjD–ÖŒpriv/templates/basicnif.cPK’KAéz›ïQpriv/templates/basicnif.erlPK’KAý+¡R‡ %‘priv/templates/basicnif.templatePK’KAȪ8’‚µ‘priv/templates/ctsuite.erlPK’KA}Oê­P_—priv/templates/ctsuite.templatePK’KAôävÞ ‘—priv/templates/simpleapp.app.srcPK’KA¤yE†\Ï!E˜priv/templates/simpleapp.templatePK’KAÀ­À‰œk à˜priv/templates/simpleapp_app.erlPK’KA‡O³Ì º™priv/templates/simpleapp_sup.erlPK’KAÛ"'»ŒÏ›priv/templates/simplefsm.erlPK’KA¥DŒrFS!Öœpriv/templates/simplefsm.templatePK’KA—¡49A[priv/templates/simplemod.erlPK’KAþ6ÛöV’!Îpriv/templates/simplemod.templatePK’KA+]çI;D"cžpriv/templates/simplemod_tests.erlPK’KADV^$Þžpriv/templates/simplenode.erl.scriptPK’KA?6X8’®1v¡priv/templates/simplenode.install_upgrade.escriptPK’KAì,?¯ˆÓ"W¤priv/templates/simplenode.nodetoolPK’KA‘®?WÚÛ(ªpriv/templates/simplenode.reltool.configPK’KA·Ì£rÀ ?¬priv/templates/simplenode.runnerPK’KA8&’¬M$=µpriv/templates/simplenode.sys.configPK’KAT_ë»Ô"+¶priv/templates/simplenode.templatePK’KAWš8±!?·priv/templates/simplenode.vm.argsPK’KAš/Á”œÞ ,¶¸priv/templates/simplenode.windows.runner.cmdPK’KA­Ò.´Z/œ¼priv/templates/simplenode.windows.start_erl.cmdPK’KA“Ù–”\”¾priv/templates/simplesrv.erlPK’KAZƒ`óJV!3Àpriv/templates/simplesrv.templatePK<<­¼Àrabbitmq-server-3.2.4/plugins-src/webmachine-wrapper/webmachine-git/README.org0000644000000000000000000000407312305126066025707 0ustar rootroot* webmachine ** Overview [[http://travis-ci.org/basho/webmachine][Travis-CI]] :: [[https://secure.travis-ci.org/basho/webmachine.png]] Webmachine is an application layer that adds HTTP semantic awareness on top of the excellent bit-pushing and HTTP syntax-management provided by mochiweb, and provides a simple and clean way to connect that to your application's behavior. More information is available [[http://webmachine.basho.com/][here]]. ** Quick Start A shell script is provided in the =webmachine= repository to help users quickly and easily create a new =webmachine= application. #+BEGIN_SRC shell git clone git://github.com/basho/webmachine.git cd webmachine ./scripts/new_webmachine.sh mydemo #+END_SRC A destination path can also be passed to the =new_webmachine.sh= script. #+BEGIN_SRC shell ./scripts/new_webmachine.sh mydemo ~/webmachine_applications #+END_SRC Once a new application has been created it can be built and started. #+BEGIN_SRC shell cd mydemo make ./start.sh #+END_SRC The application will be available at [[http://localhost:8000]]. To learn more continue reading [[http://webmachine.basho.com/][here]]. ** Contributing We encourage contributions to =webmachine= from the community. 1) Fork the =webmachine= repository on [[https://github.com/basho/webmachine][Github]]. 2) Clone your fork or add the remote if you already have a clone of the repository. #+BEGIN_SRC shell git clone git@github.com:yourusername/webmachine.git # or git remote add mine git@github.com:yourusername/webmachine.git #+END_SRC 3) Create a topic branch for your change. #+BEGIN_SRC shell git checkout -b some-topic-branch #+END_SRC 4) Make your change and commit. Use a clear and descriptive commit message, spanning multiple lines if detailed explanation is needed. 5) Push to your fork of the repository and then send a pull-request through Github. #+BEGIN_SRC shell git push mine some-topic-branch #+END_SRC 6) A Basho engineer or community maintainer will review your patch and merge it into the main repository or send you feedback. rabbitmq-server-3.2.4/plugins-src/webmachine-wrapper/webmachine-git/demo/0000755000000000000000000000000012305126066025161 5ustar rootrootrabbitmq-server-3.2.4/plugins-src/webmachine-wrapper/webmachine-git/demo/priv/0000755000000000000000000000000012305126066026141 5ustar rootrootrabbitmq-server-3.2.4/plugins-src/webmachine-wrapper/webmachine-git/demo/priv/dispatch.conf0000644000000000000000000000020712305126066030606 0ustar rootroot%%-*- mode: erlang -*- {["demo", '*'], webmachine_demo_resource, []}. {["fs", '*'], webmachine_demo_fs_resource, [{root, "/tmp/fs"}]}. rabbitmq-server-3.2.4/plugins-src/webmachine-wrapper/webmachine-git/demo/src/0000755000000000000000000000000012305126066025750 5ustar rootroot././@LongLink0000000000000000000000000000014500000000000011565 Lustar rootrootrabbitmq-server-3.2.4/plugins-src/webmachine-wrapper/webmachine-git/demo/src/webmachine_demo.app.srcrabbitmq-server-3.2.4/plugins-src/webmachine-wrapper/webmachine-git/demo/src/webmachine_demo.app.src0000644000000000000000000000055212305126066032350 0ustar rootroot%%-*- mode: erlang -*- {application, webmachine_demo, [ {description, "demo"}, {vsn, "1"}, {modules, []}, {registered, []}, {applications, [ kernel, stdlib, crypto, mochiweb, webmachine ]}, {mod, { webmachine_demo_app, []}}, {env, []} ]}. ././@LongLink0000000000000000000000000000014500000000000011565 Lustar rootrootrabbitmq-server-3.2.4/plugins-src/webmachine-wrapper/webmachine-git/demo/src/webmachine_demo_app.erlrabbitmq-server-3.2.4/plugins-src/webmachine-wrapper/webmachine-git/demo/src/webmachine_demo_app.erl0000644000000000000000000000077512305126066032433 0ustar rootroot%% @author Andy Gross %% @author Justin Sheehy %% @doc Callbacks for the webmachine_demo application. -module(webmachine_demo_app). -behaviour(application). -export([start/2,stop/1]). %% @spec start(_Type, _StartArgs) -> ServerRet %% @doc application start callback for webmachine_demo. start(_Type, _StartArgs) -> webmachine_demo_sup:start_link(). %% @spec stop(_State) -> ServerRet %% @doc application stop callback for webmachine_demo. stop(_State) -> ok. rabbitmq-server-3.2.4/plugins-src/webmachine-wrapper/webmachine-git/demo/src/webmachine_demo.erl0000644000000000000000000000231312305126066031561 0ustar rootroot-module(webmachine_demo). -author('Andy Gross '). -author('Justin Sheehy '). -export([start/0, start_link/0, stop/0]). ensure_started(App) -> case application:start(App) of ok -> ok; {error, {already_started, App}} -> ok end. %% @spec start_link() -> {ok,Pid::pid()} %% @doc Starts the app for inclusion in a supervisor tree start_link() -> ensure_started(crypto), ensure_started(mochiweb), application:set_env(webmachine, webmachine_logger_module, webmachine_logger), ensure_started(webmachine), webmachine_demo_sup:start_link(). %% @spec start() -> ok %% @doc Start the webmachine_demo server. start() -> ensure_started(inets), ensure_started(crypto), ensure_started(mochiweb), application:set_env(webmachine, webmachine_logger_module, webmachine_logger), ensure_started(webmachine), application:start(webmachine_demo). %% @spec stop() -> ok %% @doc Stop the webmachine_demo server. stop() -> Res = application:stop(webmachine_demo), application:stop(webmachine), application:stop(mochiweb), application:stop(crypto), Res. ././@LongLink0000000000000000000000000000015200000000000011563 Lustar rootrootrabbitmq-server-3.2.4/plugins-src/webmachine-wrapper/webmachine-git/demo/src/webmachine_demo_resource.erlrabbitmq-server-3.2.4/plugins-src/webmachine-wrapper/webmachine-git/demo/src/webmachine_demo_resourc0000644000000000000000000000357212305126066032552 0ustar rootroot%% @author Justin Sheehy %% @copyright 2007-2009 Basho Technologies, Inc. All Rights Reserved. %% @doc Example webmachine_resource. -module(webmachine_demo_resource). -author('Justin Sheehy '). -export([init/1, to_html/2, to_text/2, content_types_provided/2, is_authorized/2, generate_etag/2, expires/2, last_modified/2]). -include_lib("webmachine/include/webmachine.hrl"). init([]) -> {ok, undefined}. content_types_provided(ReqData, Context) -> {[{"text/html", to_html},{"text/plain",to_text}], ReqData, Context}. to_text(ReqData, Context) -> Path = wrq:disp_path(ReqData), Body = io_lib:format("Hello ~s from webmachine.~n", [Path]), {Body, ReqData, Context}. to_html(ReqData, Context) -> {Body, _RD, Ctx2} = to_text(ReqData, Context), HBody = io_lib:format("~s~n", [erlang:iolist_to_binary(Body)]), {HBody, ReqData, Ctx2}. is_authorized(ReqData, Context) -> case wrq:disp_path(ReqData) of "authdemo" -> case wrq:get_req_header("authorization", ReqData) of "Basic "++Base64 -> Str = base64:mime_decode_to_string(Base64), case string:tokens(Str, ":") of ["authdemo", "demo1"] -> {true, ReqData, Context}; _ -> {"Basic realm=webmachine", ReqData, Context} end; _ -> {"Basic realm=webmachine", ReqData, Context} end; _ -> {true, ReqData, Context} end. expires(ReqData, Context) -> {{{2021,1,1},{0,0,0}}, ReqData, Context}. last_modified(ReqData, Context) -> {calendar:now_to_universal_time(os:timestamp()), ReqData, Context}. generate_etag(ReqData, Context) -> {wrq:raw_path(ReqData), ReqData, Context}. ././@LongLink0000000000000000000000000000015500000000000011566 Lustar rootrootrabbitmq-server-3.2.4/plugins-src/webmachine-wrapper/webmachine-git/demo/src/webmachine_demo_fs_resource.erlrabbitmq-server-3.2.4/plugins-src/webmachine-wrapper/webmachine-git/demo/src/webmachine_demo_fs_reso0000644000000000000000000001206312305126066032523 0ustar rootroot%% @author Bryan Fink %% @author Andy Gross %% @author Justin Sheehy %% @copyright 2008-2009 Basho Technologies, Inc. -module(webmachine_demo_fs_resource). -export([init/1]). -export([allowed_methods/2, resource_exists/2, last_modified/2, content_types_provided/2, content_types_accepted/2, delete_resource/2, post_is_create/2, create_path/2, provide_content/2, accept_content/2, generate_etag/2]). -record(context, {root,response_body=undefined,metadata=[]}). -include_lib("kernel/include/file.hrl"). -include_lib("webmachine/include/webmachine.hrl"). init(ConfigProps) -> {root, Root} = proplists:lookup(root, ConfigProps), {ok, #context{root=Root}}. allowed_methods(ReqData, Context) -> {['HEAD', 'GET', 'PUT', 'DELETE', 'POST'], ReqData, Context}. file_path(_Context, []) -> false; file_path(Context, Name) -> RelName = case hd(Name) of "/" -> tl(Name); _ -> Name end, filename:join([Context#context.root, RelName]). file_exists(Context, Name) -> NamePath = file_path(Context, Name), case filelib:is_regular(NamePath) of true -> {true, NamePath}; false -> false end. resource_exists(ReqData, Context) -> Path = wrq:disp_path(ReqData), case file_exists(Context, Path) of {true, _} -> {true, ReqData, Context}; _ -> case Path of "p" -> {true, ReqData, Context}; _ -> {false, ReqData, Context} end end. maybe_fetch_object(Context, Path) -> % if returns {true, NewContext} then NewContext has response_body case Context#context.response_body of undefined -> case file_exists(Context, Path) of {true, FullPath} -> {ok, Value} = file:read_file(FullPath), {true, Context#context{response_body=Value}}; false -> {false, Context} end; _Body -> {true, Context} end. content_types_provided(ReqData, Context) -> CT = webmachine_util:guess_mime(wrq:disp_path(ReqData)), {[{CT, provide_content}], ReqData, Context#context{metadata=[{'content-type', CT}|Context#context.metadata]}}. content_types_accepted(ReqData, Context) -> CT = case wrq:get_req_header("content-type", ReqData) of undefined -> "application/octet-stream"; X -> X end, {MT, _Params} = webmachine_util:media_type_to_detail(CT), {[{MT, accept_content}], ReqData, Context#context{metadata=[{'content-type', MT}|Context#context.metadata]}}. accept_content(ReqData, Context) -> Path = wrq:disp_path(ReqData), FP = file_path(Context, Path), ok = filelib:ensure_dir(FP), ReqData1 = case file_exists(Context, Path) of {true, _} -> ReqData; _ -> LOC = "http://" ++ wrq:get_req_header("host", ReqData) ++ "/fs/" ++ Path, wrq:set_resp_header("Location", LOC, ReqData) end, Value = wrq:req_body(ReqData1), case file:write_file(FP, Value) of ok -> {true, wrq:set_resp_body(Value, ReqData1), Context}; Err -> {{error, Err}, ReqData1, Context} end. post_is_create(ReqData, Context) -> {true, ReqData, Context}. create_path(ReqData, Context) -> case wrq:get_req_header("slug", ReqData) of undefined -> {undefined, ReqData, Context}; Slug -> case file_exists(Context, Slug) of {true, _} -> {undefined, ReqData, Context}; _ -> {Slug, ReqData, Context} end end. delete_resource(ReqData, Context) -> case file:delete(file_path( Context, wrq:disp_path(ReqData))) of ok -> {true, ReqData, Context}; _ -> {false, ReqData, Context} end. provide_content(ReqData, Context) -> case maybe_fetch_object(Context, wrq:disp_path(ReqData)) of {true, NewContext} -> Body = NewContext#context.response_body, {Body, ReqData, Context}; {false, NewContext} -> {error, ReqData, NewContext} end. last_modified(ReqData, Context) -> {true, FullPath} = file_exists(Context, wrq:disp_path(ReqData)), LMod = filelib:last_modified(FullPath), {LMod, ReqData, Context#context{metadata=[{'last-modified', httpd_util:rfc1123_date(LMod)}|Context#context.metadata]}}. hash_body(Body) -> mochihex:to_hex(binary_to_list(crypto:sha(Body))). generate_etag(ReqData, Context) -> case maybe_fetch_object(Context, wrq:disp_path(ReqData)) of {true, BodyContext} -> ETag = hash_body(BodyContext#context.response_body), {ETag, ReqData, BodyContext#context{metadata=[{etag,ETag}| BodyContext#context.metadata]}}; _ -> {undefined, ReqData, Context} end. ././@LongLink0000000000000000000000000000014500000000000011565 Lustar rootrootrabbitmq-server-3.2.4/plugins-src/webmachine-wrapper/webmachine-git/demo/src/webmachine_demo_sup.erlrabbitmq-server-3.2.4/plugins-src/webmachine-wrapper/webmachine-git/demo/src/webmachine_demo_sup.erl0000644000000000000000000000326712305126066032461 0ustar rootroot%% @author author %% @copyright YYYY author. %% @doc Supervisor for the webmachine_demo application. -module(webmachine_demo_sup). -behaviour(supervisor). %% External exports -export([start_link/0, upgrade/0]). %% supervisor callbacks -export([init/1]). %% @spec start_link() -> ServerRet %% @doc API for starting the supervisor. start_link() -> supervisor:start_link({local, ?MODULE}, ?MODULE, []). %% @spec upgrade() -> ok %% @doc Add processes if necessary. upgrade() -> {ok, {_, Specs}} = init([]), Old = sets:from_list( [Name || {Name, _, _, _} <- supervisor:which_children(?MODULE)]), New = sets:from_list([Name || {Name, _, _, _, _, _} <- Specs]), Kill = sets:subtract(Old, New), sets:fold(fun (Id, ok) -> supervisor:terminate_child(?MODULE, Id), supervisor:delete_child(?MODULE, Id), ok end, ok, Kill), [supervisor:start_child(?MODULE, Spec) || Spec <- Specs], ok. %% @spec init([]) -> SupervisorTree %% @doc supervisor callback. init([]) -> Ip = case os:getenv("WEBMACHINE_IP") of false -> "0.0.0.0"; Any -> Any end, {ok, Dispatch} = file:consult(filename:join( [filename:dirname(code:which(?MODULE)), "..", "priv", "dispatch.conf"])), WebConfig = [ {ip, Ip}, {port, 8000}, {log_dir, "priv/log"}, {dispatch, Dispatch}], Web = {webmachine_mochiweb, {webmachine_mochiweb, start, [WebConfig]}, permanent, 5000, worker, dynamic}, Processes = [Web], {ok, { {one_for_one, 10, 10}, Processes} }. rabbitmq-server-3.2.4/plugins-src/webmachine-wrapper/webmachine-git/demo/README0000644000000000000000000000233712305126066026046 0ustar rootrootProject Skeleton for the webmachine_demo app. You should find in this directory: README : this file Makefile : simple make commands rebar : the Rebar build tool for Erlang applications rebar.config : configuration for Rebar start.sh : simple startup script for running webmachine_demo /ebin /webmachine_demo.app : the Erlang app specification /src /webmachine_demo_app.erl : base module for the Erlang application /webmachine_demo_sup.erl : OTP supervisor for the application /webmachine_demo_resource.erl : a simple example Webmachine resource /priv /dispatch.conf : the Webmachine URL-dispatching table /www : a convenient place to put your static web content You probably want to do one of a couple of things at this point: 0. Build the skeleton application: $ make - or - $ ./rebar compile 1. Start up the skeleton application: $ ./start.sh 2. Test the basic application: Visit http://localhost:8000/demo 3. Change the basic application: edit src/webmachine_demo_resource.erl 4. Test the filesystem resource: $ mkdir /tmp/fs $ echo "Hello World." > /tmp/fs/demo.txt Visit http://localhost:8000/fs/demo.txt 5. Add some new resources: edit src/YOUR_NEW_RESOURCE.erl edit priv/dispatch.conf rabbitmq-server-3.2.4/plugins-src/webmachine-wrapper/webmachine-git/demo/Makefile0000644000000000000000000000035712305126066026626 0ustar rootrootERL ?= erl APP := webmachine_demo .PHONY: deps all: deps @../rebar compile deps: @../rebar get-deps clean: @../rebar clean distclean: clean @../rebar delete-deps docs: @erl -noshell -run edoc_run application '$(APP)' '"."' '[]' rabbitmq-server-3.2.4/plugins-src/webmachine-wrapper/webmachine-git/demo/rebar.config0000644000000000000000000000015612305126066027445 0ustar rootroot%%-*- mode: erlang -*- {deps, [{webmachine, "1.10.*", {git, "git://github.com/basho/webmachine", "HEAD"}}]}. rabbitmq-server-3.2.4/plugins-src/webmachine-wrapper/webmachine-git/demo/start.sh0000755000000000000000000000016212305126066026654 0ustar rootroot#!/bin/sh cd `dirname $0` exec erl -pa $PWD/ebin $PWD/deps/*/ebin -boot start_sasl -s reloader -s webmachine_demo rabbitmq-server-3.2.4/plugins-src/webmachine-wrapper/webmachine-git/test/0000755000000000000000000000000012305126066025214 5ustar rootrootrabbitmq-server-3.2.4/plugins-src/webmachine-wrapper/webmachine-git/test/etag_test.erl0000644000000000000000000001064512305126066027705 0ustar rootroot%% @author Justin Sheehy %% @author Andy Gross %% @copyright 2007-2010 Basho Technologies %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. %% You may obtain a copy of the License at %% %% http://www.apache.org/licenses/LICENSE-2.0 %% %% Unless required by applicable law or agreed to in writing, software %% distributed under the License is distributed on an "AS IS" BASIS, %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %% See the License for the specific language governing permissions and %% limitations under the License. -module(etag_test). -ifdef(EQC). -include("wm_reqdata.hrl"). -include_lib("eqc/include/eqc.hrl"). -include_lib("eunit/include/eunit.hrl"). -compile(export_all). -define(QC_OUT(P), eqc:on_output(fun(Str, Args) -> io:format(user, Str, Args) end, P)). unique(L) -> lists:reverse(lists:foldl(fun(Elem, Acc) -> case lists:member(Elem, Acc) of true -> Acc; false -> [Elem | Acc] end end, [], L)). etag(Bin) -> integer_to_list(erlang:crc32(Bin)). etag_list([]) -> "*"; etag_list(Bins) -> string:join([[$", etag(B), $"] || B <- Bins], ","). http_request(_Match, _IfVals, _NewVal, 0) -> error; http_request(Match, IfVals, NewVal, Count) -> case httpc:request(put, {"http://localhost:12000/etagtest/foo", [{Match, etag_list(IfVals)}], "binary/octet-stream", NewVal}, [], []) of {ok, Result} -> {ok, Result}; {error, socket_closed_remotely} -> io:format(user, "Retry!\n", []), http_request(Match, IfVals, NewVal, Count-1) end. etag_prop() -> ?LET({AllVals, Match}, {non_empty(list(binary())), oneof(["If-Match", "If-None-Match"])}, ?FORALL({IfVals0, CurVal, NewVal}, {list(oneof(AllVals)), oneof(AllVals), oneof(AllVals)}, begin ets:insert(?MODULE, [{etag, etag(CurVal)}]), IfVals = unique(IfVals0), {ok, Result} = http_request(Match, IfVals, NewVal, 3), Code = element(2, element(1, Result)), ExpectedCode = expected_response_code(Match, IfVals, lists:member(CurVal, IfVals)), equals(ExpectedCode, Code) end)). expected_response_code("If-Match", _, true) -> 204; expected_response_code("If-Match", [], false) -> 204; expected_response_code("If-Match", _, false) -> 412; expected_response_code("If-None-Match", _, true) -> 412; expected_response_code("If-None-Match", [], false) -> 412; expected_response_code("If-None-Match", _, false) -> 204. etag_test_() -> {spawn, [{setup, fun setup/0, fun cleanup/1, [ {timeout, 12, ?_assert(eqc:quickcheck(eqc:testing_time(10, ?QC_OUT(etag_prop()))))} ]}]}. setup() -> %% Setup ETS table to hold current etag value ets:new(?MODULE, [named_table, public]), %% Spin up webmachine WebConfig = [{ip, "0.0.0.0"}, {port, 12000}, {dispatch, [{["etagtest", '*'], ?MODULE, []}]}], {ok, Pid0} = webmachine_sup:start_link(), {ok, Pid1} = webmachine_mochiweb:start(WebConfig), link(Pid1), {Pid0, Pid1}. cleanup({Pid0, Pid1}) -> %% clean up unlink(Pid0), exit(Pid0, kill), unlink(Pid1), exit(Pid1, kill). init([]) -> {ok, undefined}. allowed_methods(ReqData, Context) -> {['PUT'], ReqData, Context}. content_types_accepted(ReqData, Context) -> {[{"binary/octet-stream", on_put}], ReqData, Context}. on_put(ReqData, Context) -> {ok, ReqData, Context}. generate_etag(ReqData, Context) -> case ets:lookup(?MODULE, etag) of [] -> {undefined, ReqData, Context}; [{etag, ETag}] -> {ETag, ReqData, Context} end. ping(ReqData, State) -> {pong, ReqData, State}. -endif. rabbitmq-server-3.2.4/plugins-src/webmachine-wrapper/webmachine-git/Makefile0000644000000000000000000000052612305126066025700 0ustar rootrootERL ?= erl APP := webmachine .PHONY: deps all: deps @(./rebar compile) deps: @(./rebar get-deps) clean: @(./rebar clean) distclean: clean @(./rebar delete-deps) edoc: @$(ERL) -noshell -run edoc_run application '$(APP)' '"."' '[{preprocess, true},{includes, ["."]}]' test: all @(./rebar skip_deps=true eunit) rabbitmq-server-3.2.4/plugins-src/webmachine-wrapper/webmachine-git/.travis.yml0000644000000000000000000000032012305126066026341 0ustar rootrootlanguage: erlang notifications: webhooks: http://basho-engbot.herokuapp.com/travis?key=66724b424957d598311ba00bb2d137fcae4eae21 email: eng@basho.com otp_release: - R15B01 - R15B - R14B04 - R14B03 rabbitmq-server-3.2.4/plugins-src/webmachine-wrapper/webmachine-git/www/0000755000000000000000000000000012305126066025061 5ustar rootrootrabbitmq-server-3.2.4/plugins-src/webmachine-wrapper/webmachine-git/www/index.html0000755000000000000000000000771712305126066027075 0ustar rootroot Webmachine - software shaped like the Web

    webmachine

    Webmachine is not much like the Web frameworks you're used to. You can call Webmachine a REST toolkit if you like, and we won't argue with you.

    Webmachine is an application layer that adds HTTP semantic awareness on top of the excellent bit-pushing and HTTP syntax-management provided by mochiweb, and provides a simple and clean way to connect that to your application's behavior.

    A Webmachine application is a set of resources, each of which is a set of functions over the state of the resource. We really mean functions here, not object-methods, infinite-server-loops, or any other such construction. This aspect of Webmachine is one of the reasons why Webmachine applications are relatively easy to understand and extend.

    These functions give you a place to define the representations and other Web-relevant properties of your application's resources -- with the emphasis that the first-class things on the Web are resources and that their essential properties of interaction are already quite well defined and usefully constrained.

    For most Webmachine applications, most of the functions are quite small and isolated. One of the nice effects of this is that a quick reading of a resource will give you an understanding of the application, its Web behavior, and the relationship between them. Since these functions are usually referentially transparent, Webmachine applications can be quite easy to test. There's no need for mock objects, fake database connections, or any other wastes of time when you can write tests against each component of your application in terms of the input and output to various functions.

    We believe that by giving Web developers a system with conventions that directly map to HTTP and REST, we help them to write and extend Web applications quickly while not dictating the shape of the rest of their application. The resulting applications are straightforward to examine and maintain, and have very easily understood HTTP semantics.

    rabbitmq-server-3.2.4/plugins-src/webmachine-wrapper/webmachine-git/www/images/0000755000000000000000000000000012305126066026326 5ustar rootroot././@LongLink0000000000000000000000000000015400000000000011565 Lustar rootrootrabbitmq-server-3.2.4/plugins-src/webmachine-wrapper/webmachine-git/www/images/basic-trace-decision-tab.pngrabbitmq-server-3.2.4/plugins-src/webmachine-wrapper/webmachine-git/www/images/basic-trace-decision-0000644000000000000000000024713612305126066032313 0ustar rootroot‰PNG  IHDROÑÍÆasRGB®Îé pHYs  šœtIMEÙ;6°yîtEXtCommentCreated with GIMPW IDATxÚìÝw|ÕÚÀñß´mɦ’„@h¡#‚ÈéUA±+( bAQì‚`£¨¯½ "‚€`AiÒAº R¤BKÝd7;»3óþ±!J¦žï玗ìN9{fwçÙçœ9G²,Ëâoš2eJ‘Çš6mŠ ‚ ÿ]²¨AA.õØ?ŠËF‚ ‚ œ+‘ÉAá‚POõDÀŸ‹Ïo€¢æDu%‚ Âß 2ü™»™1ñ¦üì!¼rerþú ädx¦?-ë–ÁÆy²~ýz~¿ÿò+Û†}ÈrÉ“\î0*WN⚆uÅ A ™»–ñÀ3ïQªÁ=¼?¶#qN²gýžzíI~êðÃz5Æ)êíœY–ÅòåËq:T®\™°°°Ë®ŒvW)ÂÃJ~–3³j×¾’ÄÄÒ8—_Èv$ÓKdDx‰·‹ÌÎÁ´,~[»‘­î¢fdñ Aø+ȉï_¿ˆ_|&­nkE¼VtÅŠW·áJ›Ì÷ŸýJÎ9ý„×Y8úi’’’Š,õº=Îøi‹Ù{Ô{^^”éOáùö-¸yÈlgdßê/¸¦qCïʽà•mš&ëÖ­£|ùò”-[»ÝvY¾)ô@ aœrÙ±cG±kvå+”!!1ž9ó–c𦸄 ‚ ˆ Œ`èbî.þÂ'ÙÉÑ$ðïÇ“wG’l´é;‚ÙÝÀ±‹Ù³o7Û¶¬gü Ìyê^š\U‘ß®Ãø›/JRÜt|ô1ž¾ã*´3¤ìK%7åÙG‡Q%Ú~áó+†AZZ‚Á ¦i^vK  »d¤g²pþ|2Ò3‹<§äåéDFG°sO*†aˆO˜ ÂX‘¶›Z|×N+˜Çî<Ô¿wß«‚ €ääDIÅ厥v“nŒß؈îjÇðÇ:ãŽ[Ƀ-Ë{¡ÆÐ¥ï€³ZוP—‡žº8u]GQ,Ë*èðùwÆ[µ 6lEN™NFZ6’ÍM”»äÁ“߯ã÷ëÅÐbÁ‚y|üÑ{¸##éС’,z}¾†a¡ë:š¦‰O™ Â=“aºèéAãnrþº_  ž£¬Z8w¾žE~kG¶ü@ýÖ·ñ¿§1uêTæ¼wOõ¼Žc×bʾã'FÏü‰~7]·Î#Œ{gK¾~–Ñsþ*È"lõè¬^q¨H³eY¡ C’ÐuÓ01 £Ä‹ÐhÙ÷9*ãÄ’ ïã÷!sÐt>Ì_kÆóáÓ£Ùï –ìf`°è²pÁºNBB=Àüy³ ¯0ðùt$I¦©"ÀAAFH\Íf´s«¬ýá'öæ½8l^1€î·4¸ð·°Ê.¬Ã¿ÐÿÓ*†çñëÒ•¤æú?ò72®¡Ç ‹1ünâíjd ^xµ7]Z”GÓbiyóýôº%¡`wº7”¥Xº|;†G¯!=°™öØÊÜz{÷¢€,¦{‘òÞ¤sƒÒ\q]Þ¸#‘iÃ^f‹'šw?F«p…¾ï̧gǦ´îÒƒ¢4rõPfF¶'óñòßX:®;Žbúƒ¨ªŠD¨iÁ¯ûóû?]rnbÔ}5‰'¾ÂÝÌùm_ÁsZteÔ«Mùª.Œ`áíü†Å Û9ªð¦€ðZ¸äà)SÜâ÷ЋY:tì§_L,X®ïtc¡çý¯/Y–E3‰ ‚pBŸ ¹· }œyGñÔ€)üß;7Q&\‚ìXñ-¯}µ‘ú·Žî-ÆñÁ¬ßèZ'þ¤5½º@áJr…:«J'Ô–ï[TMC–e$YF–e¥hêGvñÑ‘Ìïú?ÂT‰°:x¹Ù«¬Øzˆúe*œ:Y–PU=V0“_Þõ%Ƶ·¸§ï^ý_½Ð•ˆ b³Ù°ÛJÞaÔ±, Y–°‰ Cá?¯È"ö¨Štb ¯èιsØ ›´º÷~ÚžçCS ߨbú÷ðÞí¡;BlK¥uÀ7—O~\ÂOe_?݃U©¡‘:&M_y¼s¥•Χ½ÈÎÜÂWÈÜ:‹Ù»KÑkèd–Oÿ„º6™ÏÚX¨c¦¦ªÈ6¥*Ûæl&ó„~©V04~G|„ë„@¤0ç ñ îCZ§|Ý’$!KŠ¢ iZ‘E’,ÐJápœðx´†nQh=§,¡œð·ØËë/Íࣗî¡åu=Ù¶ú”IƒX¹ÇWìqNµØT›M+²¬Z¾„wß^°,^0§Ð󊦠È2’$¡iªøt ‚ ˆ £xUšÜȧCcZ,þây™ËžÃYÿv_¾Ð{ËŸ)VÜÌÃü¾ä{î©Û‚S} þlªEâ.=ãíLxª3/|<“ ¬æƒ1!æÚ6jD¿D'³GÝÍ}CưtÅ^¨ß€­ïÌÏzø8¸'Ô‡C$%Às¯ÌÀkYT¨×ÛE&I°ç`Hqt5Ò?bô› ‚—Ÿ§~KíûÇqe‚Šž¶‹é™Âlj¡ìDZ̆éßÃÓ ® Ã³3ß sR–@’$$IBQTU-²D$]A¯ˆ¥ü°bªªâK]Ã3ÓÓ¦^¥üu$TÉÀ 0B«*šÃEE—ÂÆ]™¡¿]vd &,¬Øãœj±Ù5v[‘åšÆÙ¹c+kW¯`˦õ4iÚ¼Ðóª¢æ ÙD!‚ð_wÚ+AÅ«;1q\3voÿ“­[w0éÝ‘x¤JÜûؽT‹-a:ÜÒYøéãÜ3ìG€Pÿˆ‚4@{ž~î]_w-ÕÊ„æòíxê‡qìnc_y€±@‡'?gâ€f¨’Ä Ÿ~@é Œ¢1ððÈoyâæêXÁTÆ<7€áË2Gyùšx´ÔH[þíúìä¦ÄuŒ×ïáëj‘ºa&ƒnéÊžÜù Ñ“?¦[‹~ÌüÌ¢Sïü¼¢?µvÉöÚÙðbkTã ï=þ?ñõcû‘±ì-¦gà±k©W~5ÝÏ0䆚ŸÉ$ EV°Û‹k–¨ÀàŸ&Ò»e[ÊzB)•Q߬¤urÙ;gܰghÕ%W1 ê~ÖnNw5žøè%ZÝpåï©ïðïiQ%{ šK6{±åŠ‹‹ã®ž}xû×¹óžûH,“ˆ,ÏìAtY™ AÉÊ¿ÏpÊ”)çuÇM›6=/û±‚>²rü¨váΓG#5ðûtLEÃy¿œƒºŸßÂívqÝ€ÏCz¶Iuë.Q™ƒºSv`;a.˲ÈÈÈ`ÇŽT©R…ˆˆœN'Çéú”x½~T›³Ð¾ÎÄô{ÉòøQ]nÜ®’_ìß´WXñu”•‘Á§Ÿ¼Ï}}úWè¹<99¹¤gdñ׎]tëØŒèèh1Qš ‚Èd\¦Qê$*êT7Í*ØK0Á˜jsâ>ËéB4§›§ûÜ*ÕV´L’jÒÈÊÊB’$œN'aùͧc·»J^»gĹ׹ÓåÀå*¾^].'ô@BBœ;hZ(KãÍÍC•Í‚¬ ‚ ‚ á³ÙlèºNnnnAÐq¦ ãRp8NŸa©P±Bñ!Ÿ¬Ð˜f§-ôzAdüg ƒ@ ˆ×—G0¼ “z¦3ÜÍêßÖ‘‘CRÙ²¸\®Ë®Nr¼¹F ÄÛù¼>ö8Àî;(Ñô YŸ2á_AQBµ]Nš¦¢*â½-"È8C€‘ç÷“•å!Ë“K®7ï‚–eaI6Ò2rü¹“CG2°Ùì—]½øƒŠRòfžŸ¬ÌL¼Þ<,ÉFÊ#¢¹DøWa.‘î0"#Ý8ìvh‚2N`øòüdddq$=“£éYx½¾ü ¾.ËgxY9^ޤgþ«æ÷$ ›Í†+<‚ô¬2²sÄ'Lø÷²‚Ëåĉa˜DGGâtˆ@CDqÃ0ðë:YÙÒ3=äæúÈHOÃ0 ‚A㢔Á¦*ØT翲~ƒºŸ îŸ.á²tèpö9eØ118í6YAVddYB²ÙйW„ÿh¡ ²³s8’–AN®”ý)D„‡Q.©,áîpñ®„±½)‡O1>ÍéegyØ·o?Û¶ï¡zõŠX˜(²Œ‰S‚pùÇÆ­PT Íá@“$ü>»óÌw%|i¤ R¶\BhÌMKç`ÊA܉å;Ø]'Ç›GfV99TY¢f*”-Sæ”·n ‚ðï`X á%ïpíñxÑl›·lçÈ‘t‚ÁHÂÃÂs9qÚÅT‚pÙzæn¾ûrƒFM/ôxï‡îã³oãùcÍCÄœ"iSùø™Î¼úõ!b›¾Áʯobý×ùeÐhÐê³dã$ŸáUåùu<9¹dfyÈH?J•Jå©Z9™ð0ª*&ö„3MÓp8O}‹öî]»¨X©R‘ÇeE¥’*s õ{÷D’e"#‰t‡áõ*—E‘¾cuZõg{&-ZC“ª¥Q€Ìëy£óMà»L/Ä„¿½¤&òÀ«30RÚ11ʆŒFãÛžá{sÓ0•³Ó0 t=€’——GDD8²$aš&¦iŠw… ü‹`±ÏåxrX8>Ýn¾¥HÓiÐ4MÂÂÃÙµ;=D×ôŽ4AAF ˜Þ<c_Ðê3mé'\]úxÖ ªL]†-›ÎoõžãLYÙEé NÈ:yØp‡Gplòµ3¦‰eYƒAY.øâ‘e™K{³‡ÁÆÅ Pj¶¤f‚]¼;/1=sóVçѾ]mÎW~Ë ¦óóœu\Ù®5±6q{ï¥à÷ëøýz1'ÇbÁ‚y|üÑ{¸##éС’|ü麎?OGè˜&ƒA,ËÂ?Láò2þ\2‘é™: z’º¥‹~mË®Z¼ýåÓÄØC_Æ?}>‚ç:Ê[ç“ÚéEƾt/åÜg÷uoxv3zØ e”#,m:áÞgÔSí±éûÛ»¾ë¤F‚Šœd†i•,“‘µík’oñ²w]/ÂÎÇxV ö&~ì:ªÇ‰f›K-'õWîèeߺš(çi¼3ï Ý_÷%ZAÆ% ÁbƒÌŒL&Œ‹eÁįÆÒðšÆDEGÏd˜fèw $YúWÝ~.ÿŠ Ã“q€Š•9U_ìj°kÉXúßÊ’?PɾŸ¶däÕxïÎÚgu¬‹ßb¼ç^–~Ö™¼½]húä^B_+:)A#ÕKõx7²,#Iº®c³Ù0¤³O}ºÊ´å—ïØL“ó“05ÑÊk¨²%R°ÿR”'ò[³oޭʹÅ|Š ’†\ÌùÝ6ëiîœÚ„Ÿv-Q–Ã’dZÇ^‡i†2.à  m.Y¸`]'!!€`þ¼ÙÜxÓ-ǃŒ€ÏšeXV,D!g"_´#Y9lY²€úUâθº¢EBT "œ6ÊWwn?û˜H²Å³wÁ÷¬Û›MXùæ|xoåÐ ¶'óÄ;ïqç 5$P”Ð>u]ǯûóÛk‹.[—|E»¤ÒÄÇÇ3ä» <‡×òî„ÕxôÜݼÒgK–ÏàÖäDâËvdî1÷Ó¾ÄÇÇÓìÑ1È x˜þÚc|·xCo¬B||Ï_oóŒá¼öÝ[f¿Í“æ1á•úÔì6žì@€” s¹¿ZYâã㉯6ˆ¿²t/«¾=ôXÙŽÌýã0@=÷Oî«ÓŸ¿²t¶-ø?€14!¾ÆKìÎÑ äâ‡÷mÏÓÖà œººA©r>~™ÿyh›ÊýùeOY{æÑ¬çìù±eËvdþŸ™ùu6…¥?}Xp¾6ïÞÂÛ÷×">>žgF/Í?V(Å8ÝqÅrA¿?€^ÌÒ¡c>ýbbÁr}§ =ïèx}yHÈ(Š,®‚pYe2¤p®lÙ¦gíŽT:ÖŠ<íêåßÏÞå©Ìþôú¾<€¾ÝÏþpQeªïcº6©E»‡ßbÄã·àÊOy;##±çä…ŠuB›kž/^1ƒHYGûÐs\7z!“Å’Äãñ}8• ßæñTš/m‹ÞáÝe0kÎ îžý2w]Û˜žÃ'ñËŠûÑé&ÞÞ†ë«ÛHMYÀ ½r7yw9ðT—;ù°ü\ú7‹%/`âËõàñX,û¸+_1„Í[?cûü¡ô2o–eá£ØþpcÊfÿÂ3WPÙ¿’®õ:°mþgì­vfVúY–¥ø©Z=™iLúôqÒfÙÏwÜÍ«ín qÄL¶~Å/^Ï›Ó*0°u9–}ý8[~Èæ± ñfççñàM_ÏÕm{ñÆä…|P7†õÓ†Ó¦õ›¬ZörZ?ÎÌcØt íèvvø³ðxŸ¿Œf?|Öe)6‹¤PúyFömC¸ú‘•Œ9”GוÓ»ÕÉsÓÈ®•‡ªÚ(wEÖö¹‡·£ßçŽ.­‰RURv.‡Ä¡\W¿<6àï§ÅÐüu´?5í2›°É2’šxJ1|4zf2w· 5‰íYö+D÷á¶W).à—eSÀSãÇbdü Ù+ÑÍah®ê5ˆ9f’XÊÁ¡ø¢Ýá`âç yò‹.$ºíà®G¿ÁxrÖîk–TìAQ ˆ’o†÷ B‚¬*õ‰õÛQU'±¥*“\ŠøØ(ì@ ¿ÎÞ~ò:Â%hÖâJ¶5ŠÎõËcéЇª„êüø ¼"ȸl6ös˜3ÈÈïè)IRA‡qA.£ £JóÜõ9Ó?ïÇ¢[ÿ c­˜"ëìY·”@R]~}ëiÊw~—go® 䑱/Ý空i®›1‰øënã«-›Xôå+ÜýÂG¬Ûý0åkEbè~Œü %Ô'C–$EAÓŠka×èôô"æ·]Ìç#zñÂЇø}ETUIAÕ44KERKæÐÐ4 Íáɇ¦ihX€¢ihš†D„9 Ž%)²¢¢iŠ$¡hªšGв¸®C;:_ƒßhGÇ£ ³ÅÒúÑv ž5z¿ïã‰÷_gCjfÏ®ÎooÖUB ¤ŸuYŠ£©*±ÉQ¸lBo“n F„D»vípÅ”AÓ4j´’5‹Ûð×#iUÿa~\½ƒÈ€Š»ÚÞ²T$À’Ôо+ºòËÙ¯]R%¢¢ Ê¥ª (a¡ýœx=V Z×hß¹.–¿î°“nC+˜ÈJ~K~ÃÂé8^ïvUB–-äce)®ª$ž_’*!óÏ“•‹$«¯ãä:s¸¢‘óBÏ[– ,4 MU‘%U ᪊ÍVôŒ/Y´€_W­(ø»ÎUõhß±sÁߺd¡˜¦2¡.ê'EvUcðW#èӾ߭ø‹@~íDÓ;BË¿µoï‚,Y·Õs>äÅ%鬙3‹åì$`å°kqVþå?$8~Pô Lþy7Há´¼ý>êÚdÂ*¦õëË„…Û±,¥PH’„¢*ù¿0OZ$?©s©Ù¨#Cßú?HŸO®© ¢Ç· ]<ò·QòcÏÉR(C¡ª8c5-ÿ€ª"ö³p\* ª'ZOs$Ñ®WY~^}˜J5¨Q£eJE ©*5ZÜÈï>Ç4©ÕK'P¿S^{âEîyñâ´’•¥Ø…´}Ç·HªÉce]¬Û«S¥F jÔ¨J¬ÛªJMM%ªjCú ~“¢4d(_· ¤<Åï{½¨ªÊÞ53øY»‹ZåÂCûÞô;G}ppà nxz¥ùÇ•äÊU±Ns8ú6?­Ø¬ªè¹Y%'õÚÞͶYK!¢<5jÔ RÙ8쪊ª9’JPRQU;±‰vöz¨j¨>;Þ’À»_¯*¨÷i#æpCÇ« ;Ëz8±|î„ʤíöTŠ_W:鵜x>$$õ4õ/– ºØì»­ÈrMãÆìܱ•µ«W°eÓzš4m^èyUQQdIYôÉ„Ë/“xU6®¨Ì'¯ôb@– 8Ṟ/ŒaÃo툶KnëÓ^âÞæòðˆ1Œ|¤O½÷S¯©ÅæñÏóÎ~/ì”—¯‰§½c!· ÀÇóÒ+Q5oölΡ‡&kÂ'TêKWrÁI·ÇûÒý:QŠÓÀô§ò^§¦L8ê¯1ðƒyTv›®QªR»ÍކHUA³Û±Û%ì6•RUì6;vLœ²Œf³a·Ù°EªØ4*eoàŽ¡ßÑ«Y9ìø‹ÕBëÙ]´{ti/·§V…G¨Øõc–Ö¨Šõy¸Œ ¹o+¢ìvª5ì Œãæ–Õ°Ûí˜g[–SÌß`wž°¾ÄÀ¹ÓÖ¦3å„ú²ôú`)£zTä—o¦ÿ¸ý¡_~}ߥMíRD¨mXùí(7¯Ú¡«#Ó}@ù0;fÕ&åŒÝ4nÚ”{ŽPÍnçšîOѧ}'ʾq?kÿN§ç§²ë‘ŽT){_~½ͳ×WÉg®‡&”¯R½ŽÜèíH­¤ç˜ôË®)fÝ(ÅVp>d)ÿ|(6"5[þ¹.>‡Í^ì{?..Ž»zöáí7^çÎ{î#±L"²|<= ÑåÐÝ%’ÈdÂY‘¬ü›½§L™r^wÜ´iÓ3®“™FŽ7ˆ¢(DDÇâm¸\ê9Öñ‚éøt §] SX°” IDATœöOòû¦¸ÂŠŸ»$+#ƒO?yŸûúô#&¶ð]pyþ<<žöîÝϾ”DE†“\¡,’J“˜'*V.‡LƉ"¢b‰ˆ:Mál'NV¦`+ñD .wÑIlÎ0\ölšJnއ a (*aaa§ì œÓÌÅ\ö÷ñ› ް(agÞÂ~A.b>¼óÏþšGò±;l¬ßñÕÿœE£n:õ¯{»«Øòÿ2ì8\g¿ŸÓÔ@±û9õq ­„ó´õynõp¬\v‡øù§qº§œÑårò@ÿ$$$ÀIç^ÓT#tg‰e`ÓTì6 EUE¥ Âåd\*v› §ÃŽËé 33“¬¬rr½DGG#çßerá¸yhý^LÅ…zIg‡vs÷[ó¸û?ÿõð_ãp8O›±¬P±B‘Ç,Ó´¬üyüȲ„ËéÀé°c·‰XA…¾dl„‡‡å&-#ƒ½)p8lÈŠBtd$Šz1Ú[³Èï?A¸è, #X¢m à ''‡ÔHOK#,ÌIt”›ðð0d‚2N|ѲŒËiÇNd„›RÙ½' ‰èè¨"iRAþ=rý&Z Ç(±L‹Ì¬l:D à'..wx8.§UtdœHQœN'±Ñèz‘™ÅÚu0 CL|$B!Rþ8:aáá”-“HÙÄb£#p:§ÀO„ÿl © ááa”TE%Âí&#+ ^ÃS7 ‚pÂIÆîÐˆŽŒ$:2‚R¥¢CSE€!"È(î…+ N‡UQÐT w¸‹ØèH|~]Ì€*Bá CQpÚm„¹œ„‡‡æDÓòºA§ 4TEAÓTÂÜx}yƒAd‚P$ÈPU—Ó!‚ A¸,ƒ KgÑ—ƒ¹û…¯ ªpýK|÷Þý”¾Ä# 6œ1¨’ ‚ œ/¯[´d£uÏáüöÓ[Üþò,Ýû"ëçÎ&Õ+:t ‚ ¿/ÈÈç 26ü¢s÷ʱtzh ‘áA„‹¦ ¹¤G缓s™÷ÄÌŸ55çПü¼ôg¾™¼—ÞƒZ3µO&§é zgß|¾C±|ÙÆ]Eû[0÷Å!,Î1èùâxžîÛŠ´U_ñø¨Å¨qWóÑGýñþòF-¥ï}9yÓšÝ2€&•Ë1dì2îo®òZ³Öì¾k4=Ú Mc‚ ÂùvÉG‘±Œ<6Î}Ÿù+Çr[¯ÜôÅdž¿-QOa[†IÀ{„_ÿ‹ÓçòÖ7›ô5\ÃØ—ïæµï6Q±Ñ­Ü[u+—l'ÛåßͰ»X½qºñuoå›Qwƒ³=3Vlà®I€ÎVÎê‡]<Aá_d¸ËÔ¥c›–àlÏ•¯ÐôêÜñÀ`¬eÏÑ•qgï;ÁÝiã{ó¿zôöÜkã§)¿áA£z³k86ˆŸªQð·j '*\‚èVT.…Ó¦"Û“ùxùo,ׇÈb‚ ÂQÐ\r¾§z/ -,Ô£8ò£éX”ÏнùÿÈŒ\hwg"“?]ÌïÙLm•Clr8'î5<6Vœ}AA¸€.“A÷½%Þ""¾D\MäYÞu%N¶ ‚ ü'‚ Y;‡ŽÝbå°qÎzjw®EÄ wŒG–\…þ†pö®>P(” ê>ô ¸¥UA.À bæÇC·hk‘]×Í[P¿jÂy9`^NYi9…#`6yA °‚¡[O4õXšÂžqü¹s(åkF²{Õ· [šÁ—¯^ƒ&I€ç[–®éO£˜Ý´í÷1³–>H϶ÕBϧÏcã–¶ø¶¦Y§Š nØšßۿˬ‘D¿ AA¸P™ IM S¿¡ íÛ€G^ÿ„É_O`ô‡#(—ñ#_x”oÖü{G²t}†«;`Ò‹7Ò´ïg¬ûu*|¾¹ôô»÷¬á™nðÄ 7Ùt(¯`½Ú]A§äò4»eï}¿Š¶ÉaTnz37DiîîØ³Ž’k@éš !°–;Ú·ãHé 8ÅyA„ N²òç5Ÿ2e {VŒã©wfòÄ›ci˜ºçþ…{y‹2­0òÁ&œm+GÓ¦MÏ[!·LŽvÏÀŠ_‡où°lá8mR‘ Æ“Äåv¡`` pâØ[~ŸS9¾]P÷aÊlªÈb‚ Â…pƹK¹ÞK^HÅæó(Šªà°»O.Ùp»mǶàäÁ=íÎÂÛ©6‘ÏA„ ©ØŽŸ^¯€/“Ý[WòÎàÑÜ|Ý•h— €™62cÌ$ð|ËÊUá5A០ØLÆG/>ÈGùÿ.ÓªïÝÙ˜øÇ%)`úa |ÁÔ'%¼ÙGÈôèDÛÅl©‚ ‚ð 2žzû3"6á…Ñ+Pí*‘—(ÀH¾ª1Éâ< ‚ Â?N±Í%†a§jÛû¸³–“½sÞç½i›‚ ‚ üí #4~·›ÎO¼È•6™Õ†2kýQ[‚ ‚ œ[áóe„þ_†ž ¯ÌÃÃú0Y—â5&‚ ÂÙÇFü2z>Û›1³7cQ•Z3´o[^¢3×µ&‚ ÂŒë|:Ÿƒq ‚ ‚ðÏ#‹*AA‚ ‚ ˆ CAd‚ ‚ ˆ CAd‚ ‚ ‚ AAd‚ ‚ð Š*Ž3Ðu ›Mý[AøóÏ? DEE‘——G0D’$ìv;š¦¡ª*š¦ü[Q ÃÀï÷õÏ 2Lo*ˬ 7ö*Ú7©Œò/:‰ÞCëùòëE(‘•¸ñö.Äۥˢ\Ûf¿@›—ê°cåm8¤¢eòû|HŠvA3[A¸ðE¡L™2”-[Y– x½^òòòe¹ À8¶ÈŠŒi˜ø|>t]/²¿KÒ\²oõx:%—'))‰Ÿwæ]ÁÒ™1ªw<8€m©žßIT$Dè {õGr‚g¹‘•Å;«³tÞ+WBåkŠ}\÷üÅGOÖ§rÕª$'W¤^—dÚ šJže±eΛ$UêJ¯›º‘””T°Ü=x i…£Ÿ=V©+½{÷¦SryêuI¦×ˆ9ä…F´?í±A„‹dȲ\P¸Â\”*UЍ¨(TUEUUdYFQEAUBÙ E)>pI‚ŒÌ}¿²>rs–þÂÿÊ»ŠYà íO/ÎÝÊ€›¯*aÃÀë ES¦îç[ç\Π®£­böï+æñ³g­ÎM=ï •³˜ ºî+˜·PŒÌduF^ÿé_»ÿo•-f³ÐÓù¨ýõ¼úÓuÌüe3›ÖΤÍÈó„Ž‘X³5ØNêùrâD&NœÂWŸ¾Ê¢I³ÉÒƒ\7û†æ«;3{ölîø`<úÝÂo¿e>NqÇA.ªcA„$I ú²,4•Øívì6;6› U;Þ|rÙª&[½Õ*–!L->5®!!©FAfcλýéqo’ê¼Ê~è·-ÿWôõµzòÆÐ>4½¯7’+Q­j2ϼ>œjT§jõY¾'ûŒe2ý)¼pueêu{œ¥Ûö°hì3TLN&¹êüv0”=عzjþþ«’\±O[G ÿ׸Lgþ¤QtJ.OÓÞ¯±pù†õ¹’^#†Ö±rXþÝ{¡_ò7=ÏôÙKYì;~üô‹¸«F’“«R5¹"?ž‹'ß™û62ï§9,Î1X:w6Ë—,aþ‚ŸÙ—(.ÖMŸ¤¤ ¡lCÅrLý5¥ÄçE +ÇÓUãÄ·Ê¡õ³µ/—É? ¦nÙ"êòÜWÃØ».ÈE•¯ÏMw_KõºmhÛ¢µ«T¦I›æÔ5æàÏ Ò´Õµ´êБV1íiqm :Ýz/e7Ìå ÷ôÇA.>넘¦IŽ'ǃiš˜¦‰eY˜fè'¡Äé›·/iŸ н¨XÁÃ,ÿ#›ë= Ù¸¢y+VŒÈøy¿«dë>‰JÍïæ[¾fbLîêY«k|#§0<~#ïx‰O¦-Ĝߓ¯—í¥i…Ú§-‹l‹çá~$fЭÜÞæÚ=üóÝÉæiWHýý+Zt{†¾_F»«Ë½ïWvìÊ}&¯ß\‘q´åùÅ-ûõ Jÿâù»z±^7ùjÑUhä1mصôÿº_~7Ÿ$vóòí}@íÆ±Ëï³èŸÿ¼š8—„†„4°‚¡ $ ªƒ Ñõ‰rþØ‚ ÂE0, òàêºNZZ¹^/`³Ùƒ šT.Û £8»VñÙû2=·Ä¿ %]Õš~‰Np»Ø³ø!®(óˆ÷ ¦èÜÛ³¥œ$Vvß Õµp¶çWUų¿sdg, ¢ìÜw¯×î Kyï¥ÿcóÑFÀ®*$ÄE£g¤°`Ò'9zÂ9–ÎÜwºÑ¢Uk¾ÝšuÖç£jó;i¥¦çËS8ã QÛkipEep¶§^õh¬`G¦‘wô(YžLìQQø3²dþt2óïfòû|d=Bº?ì´4<o ówçVvA¡„_·–EZZsæýÌœ%ØyЋlsá¦T©(âJ'R®rMÜ1eÙ»ï‹-b×®]ÅÞ¾zɃŒSÝI Ûi{u$’ZøgoX¹: (ë¢qó+H®Uº6™;ÚÔB±t~þ ;£öåòbïO9(ÇsC”Æû“×`ÆÖaÅ+·°xûé;zöͧVíÆŒÚ—ËÓ75£VíÚ\Ñâ#ŽägBª¶ÈäW’èÚäJ’’’¨^»!C{¸¶M lZ"ƒfÏ «ô!m®©Oƒ6/SíÙBÍ!RMû†zó†Ð¢þ•Ô©-?ò‚o.ý^š‰uùxP nkQ‡ÊÕê2hÖaÜÖ˜75cüÊÔü@'’®ïãÕ;[Q­ZMšw¼½Â$ºU*7€[ƒoѰfe®¨ßŒm­èvårº^;˜½ÞPùMý0¿þxžážIg}ŽÔ¨+ýó4ZnJÚ•IJJ¢v“Ûh}Ç D(°eÚkÜ1ìgf¾r WÔ¬Í5«Q»aWÔiG”- ÌÙš:×Ü̹kètÍU\7höƒ¾Bï“s,» ‚Pr7nföòõìÏðàv; w;wâ sî""ÌA…äd¢ÊrðÐaÖ¯_Onnn±û’¬üÇ”)SÎk!›6mzÊç¶L”Û&´bͤnhÅ ¼dùøâÎk°=6‡;&z*àó`há8T ¯ÇƒÝí¾¨u™º\¿…Ýi枦µÉJᮺƒy}íç”+h20ðz¼Hv'Îb´òû<°î´6ã’g†:à~ÝÕŽÓV´NsvÍ£Fó^ °’û[–;§×îõd@Áiw^Ô‘9ÏGÙA„3Û±c'MgòÂ?¨‘\– I‰”Š$&*’˜èÜî0\.'6UòLÖ¯]‰Û¥ÑªU+’’’.L†€´eÒ£û@~Ù[Lô#Ù¨Þ¾OßÔ€Cæ4hN7Žü[2\9ÀeYœ¸Ý®S†çOÞ2˜Áƒ‡±8}.ÿ7fÙ åWp¹ÝÅv§û´€¤Úp 0Bûv»ÝÅG÷BÜãtirî™—;ŠH·û¢ý}>Ê.‚ œ™ßïg݆¿ˆ‹âæÎmhßæ*W*‡ÃeÇátâr¹ #":’è˜XÊ–¯ˆ×ë%33³Øý]’ŽŸÕ:¿ÌŠzâ7J7—B“{ǰªå^ W|ñÙŽÈÝ;êMzzwwV¬ý?Ê»þþpÖ’=šz-Z‡ÆµínEv–A¾ †É.×à~R~ÿg¾éÿÉeAø'±,‹Íî£ÿ€»©UMdY"×ëgóÖhšŒÝnÇå Ãår **å+&³sëz‚Áàåd¨¶HÊWŠ<ÃÕÚFR¥*çåxaåÛ‘’’rQ^›l‹§YÛkÅ;UAøG¹¹~jV©ˆÃnÇ0LvE“ÑT6MESì6;ª¦{ÊNŸ—,ÈAáò#Ë2²ÓAD¤M“A ;v› ›=4„¸ª©8ìl6–a`YVh|âö'ªT8Qæ¾õ|3é[¶-SQdU•±Û4ì6;š¦bÓlhš‚ÃiÇér†æ99UÐ"ªS8Æônãáv]x|Ø2²ýÇÛ×rvÍ¢RÕÚ´êx ã~O+á^ –¾‹Zurãíw°1ýäYduü¹Š~÷vâíÙ‰“ ‚p‰¹\6TEF4UÉ44TYFSTlZþÌ«’Œ¦jH’$2™yöoa±Ñ–ëþ†eà +ׂM[¶ðý¨Öç°W…ú·¿ÏÖmëy¹ELѧ¥Hn|t$sß½‰•¤bˆÓ ‚pIU,—€$ÉHr~†Â²Pò§—d I Mo¢ª¡LÇéˆ>Âñ뽪K>œôx8‘n·G½½Dî(°|h§™­OÒ`ïoûñ[®ËànA„ÿ29?Àd IVT $ EQÐì ²"!«¡ ãTM&"“!3‚¡Ð‹cð÷úLN³}0dUñ†A¸‚ EV%Y‘PPP$MQQdÉ’C}6Î0!•øNÀò±vö—ôëü(µ{t!Ñyñ‹P¡^Ò–?É ø+# Ή Â%%å÷µ™PSIh†V@’Pó¤”Y™èÜ»›Å9®ç)?S8]3†Áá}»Ø¹cG<ÅÊj.)>êµ¹Bƒ²M¿™LoÑžy™©ìܱ”CÙât ‚ \`²,#Iäª*#É *2š&!I¡K…%‚ áLk$úaÓ¢øõãÉì÷~ÓXAYžLŽM#A–'“_á@ÂôþÅÀv­hѪ9OÚ>Ï“IfæQ2MƒìÌ£dgz °}ù×”jòÛ6¾Jý²ŽÂå³° ‚ \ÜËB~çÎPa!É2ª¢ É– >4åôÍ%¢ã§püM¥jÌÆ8)‘úûDv’ÿ×ÏÌ|ú}8ŸºÔ(X'sÏfçÜ9rW–ÒN|Ìx¥MÈŸMvY3ž¦ü²ƒ&'ªæÆ’ŠŸ·EÌÂ*‚p‘3’ /¬Ð( fÐÀ´,Nü}h Ad%L#Ç×ñ@¡LƒûII¹ÿ´›íX7œíéÙ±ÎI‘‹“î#VÓ}Äé¶6ÈHÛKù«;b/¦©Æ{` cû:¡+1âÎA„ Î0-@Â0 °B›†…a˜ “`Ð ýŽ4Oÿ,šK„îruèWj3í¯ªÄôm%h–°|ܶ†.Ï=BÍè¾¥¬#¼Ò =^XL·æ•‹í±!faA¸ÈAF~†"BXX–…aX¦¡ÿaš¦iœ]&£Gç\˜)S¦ˆ3ò/ ©I<·d=ö¤—V‚ t²Š.çtÐú~ÿw(±$—‰.v1 « ÂÅeš&¦i`Z&†#ˆa–I ¨c¡@ä ÉeÑ\"";c©V#ö"Q!¾\âEÕ ‚ \6,3”©°L 3Ä2LÌ ‰eš˜¦‰aXX&Ó÷ÉÍ%ÂE¡ë¡7bP×O?t¸•Åæ; Ý}bAô`0 öSÇŽiA‚Æéo·:°c‡¼ÁóvlA„"˲š†e4ÍÐbXV(1,“€ažv?™Œo¾ùë<΂¹|ùrš6m*Δ@ö®©uý"–.y˜‘­Ûqý÷븡Zd±ëî]9†öý¼ü¾ö9âòûžn5ûg¶çûgíüïÚI,Y÷9ÉagÙÔòñuÏF¤ôú›å‰ÜûMM~Ô G1H Ï&¶êÈ—Kþ$!YýûÇAøÇ¦2B<±BM'FÐÈï—a4L #ˆ ž}Ÿ ˲DPðfú÷0âîŽ|°"›Ç?]Ì«œtñÿ&·¼FƒknáÙw_)4Ú™ØÝ¥Co6»›nÚ)ßÔéL~ü#ž|oqÚù½×«‡¹éõ›w-6ÀØ<ïcÊw~—¦•\â !Âûš`š IXf0ÔËS3h`Y&LJà:SrB4—Ç~dzé\ÆÍZÂÝËy6ñª;XE–ÀE‘‘8ëÁ¸TÚôÁìî`ÈØÅìÙ·›m[Ö3~P æ o…OIÂhô®¶0ÈåÌdø#4&Ž;bÌ›„Í!\p &+ʤLÖ¸2¶2lz*ÏÝq%rͪè¹Ñ³™ýÀK {í>ê…T,‹!bÁÅšÉ$|†„Ñh@2€Q6`2IH’Ž7ùëÿÁ®b»K a„ˆ})%&³Ÿ¸Ö$c-cþ­LÖ@ã¼jäµw~¢]íŠïÛ¨è¹âz…~½WøÜB!V \”y ‰YwÉ`ÀèÛq¢kÞàC–Á$WpºÄÿã›U¬þ¼È² Y¹Ëé?èV¾Z}¸DóÑís¸¹é5,°y(Q]»*¬¡±í¹çÖöÎbTJT¬|q IDATVŠäÆ{Vñà@(Ä ‚‹2“!IœU_ÕuMQÑtÂ+%TܪRu™ {Z³3Ý4¸¹µ, Õe©ÏG+~éèX¢KÊ•Å6ëŇ+~Ã¥š©Ql°®„ k¥Ãí¿ñÜ…X@p‘>wjÞ2Ÿª¦‚îý]S½¥ÆUCñ•3Ð5©bA†ÉX´Is¥òîǘðd¯2K3 þ¥Hâ]Vf³ÉCƒF1¢ŸàR2| ïH¯ûtKTtMïhšP»¤”ü²wEgòÞ£¨ºBž-ík¾çžÖݘqÂÉ„OWpCâV‚KÅíÆ­ˆ]G@ðoGÓ44MEÓ5T<ª‚ª«^åUŪx¼H€|C±ŠŸpϤŸxýÁ^¼~¶ÉÒ‡gƿÄ믣IÝj¢÷/bli;Y¶n?-{÷£Y’¥?Oìø•Ù«Ó¨wÅ5ÜzÝçÖRøÔNç´~›ùO÷Àt3]nûQV­Ú„ËÇ5×u ÊX¾sçdgß_ˆiÞ‘F¥|f]É%iË&öÏ¢ZVôéÒ$è5$§ÔÉœ1^F‡æ¥ûrffÓ–]œÎrѬkZ6ˆîKÀ™Îæõ›8jÓIhÕ™v‰5Ëéëݬ߾—¹WvìDýè*íW€C[ã„ܘNmé³ÊÚ.Î/ºæÍT蚎¦(誆¦hèšæUeUut Tl&ÃHÏïsôèÑ’?û?çÑá·ˆãb\ûÝ»?c&­#ÇUú…c dï'o0ù“]¸ŠÕJ‰hj¡i­ß‚¡àÙ·øyF³§b6»RyîênLüi;³ŸLßGæ`º†‹ÊïßÅå­;0`ÈPvŸÉ/ÀØ’×¾7 }‡ã§3p+rÐFnÊB%¶ û·óÕöÌR_sxËL[_Íóóv‘™cÇ¥ë«T&tíÌÈþ$?gý{´åýå‚î·ÓÉ?Ò¢ó ,=˜MÚò1tn7˜]ž*êWßcKÆtp£^ßPäZ©¬íàü£¢¡ë:Ц£ê:ЦyT]÷ ª®áQµ`3‚Kû±dV©½X¿ûm”Q7¢ÆeWóìôÿÐÿsѹ¶€ 0Uœn‹¹äYÝaG6WlÉÑMó™­ÜÉæ_¡VvâÛÜÊæ”›é•L@,Ó~È{ì¹Keî=J åü0Ÿ7Þ¹6ÈL€L‡A/³æÅ~¼ðáç¼ÿú0žÝÞƒá=ª¦_õlfÝõ,o~6˜:¡2S«Òv@pÁÆ #Ùà­&.ûÊ‹û”X ¯~‰?Ät‰t'Û–Ìáí'&ÐâŽÿ£N¡(ÿŠUÕž"iâ`"% Çñs^*Ã:7Ì‘4hInýv_ô}W¿ýÝ^YÀÈþm¨{Ãh–UƒÔèdkî~èqöÖ=ˆÃ5Œƒ+ýQÌaU7Ûûo~³šW†1ïå~Œxã –L½¾J¶êN ¬ƒX²rµÝÉ<Þg0 Zoah»ZA$q\œÌW0……b±zoã“™9@ ÎíÊ÷rÑ¡V¬a AÉÀfwCAv£âýz|ë<^u<ÀÎË#ÈÝoO陹4¨a­ÛÁ0|Õ=%]G–$d£ŒA–1ʲ7Ðe$ h—ˆ C¸9yä0«rU:T·@U† ý¶„—o€­R´r[³žwÒ¬ðÙ=:~…Qð*ÏÈÅl%.6¢Èvaô'Ö&ƹ„ô´#äºÀ[ŸšÖ’—½wº¤èªˆØ†MÀÒ‡k;'`1IÜ8tÏ´á"ýQºm…ó¥÷—딇#ïàŠÚÀ• º%–ùÉéE‚ ]É&-í4š1ŠúõkXx|Ïf›Ÿcß+&Itoj¤õý›xø†&E2¥Ú¦;YòÊKtyac‡·ý,{;3mÕfþ§EÐýZ–mÙ'Âé¯hÿvÁkû=RƒMßÝA¨$i{`Ÿ ‚ó‡,¼º%’Ž  FL>=Ù ²l@ °‡UL—@Šä¦/‘´ò}6ϘͱBJ¦õZô€ùlÁœ±ÛIùóWÆ=þ#’–IŽÛ;äØ2ɶÛÈÌ9ƒ''Ëûo›U²ÐñþÁüøü3,ý3‡ÃÎÑýÛ:×¥1aצd2NßÃü¦òÝú´Âí¥+JfÚ÷ùÏMå¯ g®æéŸÓ¹¥cÃ"ïíO¥5ßnÃfËÀ¦©äØ2ȱÙñø¦,"ê4£µºœuÛ¡(ÙlXú) Ú„ 0ü©°êŠ“l»ŒŒÌ‚~ÉuúÖ^H:Þu›?^Àž ÎŒ=¬]œAÏÄ¢ÏNlŸG—kº3ôÕh…¦R"¢êAÆ/ì?îÝÉ_Û~#&!¼è ]f¿YhÔ=šŒƒ‡Éré¸s³wKmc#ËÕ¯eÙ–xýËìÛ¿Ÿ¿vïdѬç úÃü4ã¶‚~ÁØ^e]@P™ ƒ÷~• ’AF2‚$K IȲŒ)DÆ KŒ"“!6Ö0š@É)¢KѨ7«¾}îCná S{º‡Hì\?‘·\ëý,L¼¶³3Ï.î[ů“KÖìøŒÄžOñã;3 oׂ÷¼ç©x g|ÁïM{ޤËäþ´ùöQºÝ1žñ7W?7àøQ:m3„Ï]NŸ6^‘³g?YÁUÅÄÖÊTiÕü2¹7OÌ:áý}ÝÕ<ÌÙt€.õB1Fµâ£ùÿ¥S¿N< `ÄOKŠÖñgÛ‰íßÐaàK¾ßVóëdùÁr^èïÍã4èü Ÿ?ö×µi@‹ûÞb|ëÚE20¶ÿÀ”bµG"/ëÎŒ1K¸©cS_z©ß-)Z‰×Ÿmmo™N—o¥¥¯Ï›Ü9…Y…ôW÷kÙ¶ÍfŒ@òòW¸ñá¯xìãÎõS‚±½Âʺ Š‚ ²AFÓÀ {‘‘%“lD6‘tïz Yò¿/NÒ}KCçÌ™C×®]EÏ^Âä¤,äòž±tË<./öÅ®¹ä¹tBÃ-Zà=^ÁŽÅ\Úñ*.§Šd2a.Vô)7eÍ®ÎÄY¸ÿÚú¥ÛnËD“ɲ–,¦µùÛÑÜ:ÁÁ²ÍŸ–_D ð8íd;TÂ## ­€mȳÙÈG&&ÊZ,r‚W;wã·îo³pêM¥–òÏ·ÛÈuCdõÈ~ l›JŽÍކ™¨¨°rõk0¶Ÿí•õ™@ ¨III<÷߯yýùÑÔ‰­®ëx<*ûSÒˆŽŠ$"ÂJddV, .W>oLz޾}ûrÅWˆL† l¬õ[1²Æ_ôiÓˆK¢_¡òñ³«¹QqÀãeB,¥GÄÁ(FD•¡«R Òúa…+“ÅJ2«B…µZT¥UŸÐU7Yn•çîQæ j"”ŠÚ&å×¶²ú5ÛQ¦íUà3@PùL†÷Ö–0$ŒF’Œ²“IB’t_»ÿéLd ŒqŒ_³‘Á©g¨÷Ï©îZ)¥Óó¬Òz>UX ! ykç¡‹Ò¶¿Óg ˆÛP¢@Ö]GG20úvœèH’„,ƒI–E!(Çàa‰¡I3¡¶*—ôX IÞðB÷ÜÒM×)\ÊGUÁ­­]"@ªæ-ó©jÞÒ⪦£©ÞR㊪¡(Þ*Ⱥ&¶° .t7{¶,áÛù«° ¹y@ ¨\áËPxCݧ[¢¢k:xÿCÓt¡]"¸48¾u&× ¼ŸÒð‹1Ò¶Ì䦄ÄÅűúP±’库ï_îH\\CÇÍ$³œŠæJeÊàˉ‹‹ã­E%•DløÀ«ërÛ6+§F‡îfÉ;£ˆ‹‹£ëˆOKئ¹RÛ:¸¸¸R5cá·_*i{ ~9¯¶ Ÿ Ÿ ŸVº_4MCÓT4]CÕÁ£*¨ºêU^UܨŠÇˆX÷-‚ ÁEAfÚÜ<ƒ/ß¼‹š¦¢W½-m3;#gÉÚM\Ù ØVMÉB¯Q?°`Öˬùi%Ùå–&QIú3¯®áîÎ%·‰Öi3”U ?g˦¹œÉSÊýÞ™{6Òâ¾wùæ•Ûˆ*¶}Ö`®ÃS‹V0ã©øš1Áà·_ªÀvýr^m>>>­t¿èš7S¡k:𢠫š¢¡kšW•UÕÑ5P=þÏ)~ . d$Úu»¬ÔF“DLÓF4‰¯[j{d­º4ɯë}mEvcš{qYÓFÔ*E Þd‰¢qó¦ô‹ªxA©+Û·¤al)J®’™Úu‘P\3&HõK¥m÷Ó/çÛváSáSáÓÊõ‹Š†®ë(šŽªë(šæýQUtÝ€¨º†GÕD&Cpñ“•ñ'’®ˆÙý´©•;¿?¥v]S±+Z…ß;Г‚JåÖ øû蕵=‚ýù´]øTøTø´ý¢{y¢{§NTEõ­ËÐQT UUPE¬É\ܸ퇙ÿÑËÜ1émâ"E‡A iHº®zWyJ )*º®¡s®—®‹b\‚‹Å‘MÒ¶]XJ))^RY­çWmô|Ú^– ë¥Þ/§§‹O è#YG$Ùà•y÷)± ^ý‘É\´„ŶfÂÇó™=á26$§Wý ü¨¬VÉÓÂùT=϶—¥Âz©÷‹ð©ðéÅàSƒ¯º§$,IÈFƒ,c”eo !ËH0Êd.~¢k´B—üGÔ™±ô§dZއ 29Ÿj£ÁÚ®UÈö²UX«‚`ûEøTøTøôüøT– H’„Oñ£ÁˆÉ§g"$ÐA– Hˆb\‚K?VïÄî'R÷÷Õ`’K¿QÇ“ù"ÝÅÄÿÝBu?7¨Éø›d’±K¿ÕìX–> »±•¿ÛÝïg7›*i;å·]WÒYóÉfš ™AÇFaê¶×/§§§ç˧_t!$$ƒŒdI–@’eSˆŒA–0E&Cp P¯åùu,Í/ÑbéLÝ™ëcð 'Ùt¤x‘7K?~†AÝ*õ}*™ª Y¹Ëé?èV¾Z}¸DóÑís¸¹é5,°yp_Á] 6úh™j£.›ÂÌ'z0ê¥9dëÅ‹üeÚÈAôzø{dsùm÷Û/l¨Â _üÚD¿Ÿ Ÿ Ÿž_Ÿ dƒŒA2b%dddIÆ$‘ F$Ý»C–üW’î[:gκví*F+Á¿–ìSiœ°ˆo\·È ¥¸³9~ì4.U&¶A<æ¢7[fZ gòL¡ÑÄׯQ¾“êNŽ>†SѱD×#®Fѧ3“'³p©fêÆ×§Z97øŸ9žFf^>’ÑJ£Fµ‹>+:·µfjG•oák ~©”íúå|Û.|*|*|Z±~IJJâ¹ÿ~ÍëϦNl t]ÇãQÙŸ’FtT$V"#£ˆˆ°b±Xp¹òycÒsôíÛ—+®¸B@ Jçl1õÅǨ]«:ºŠ¢r0õ(V¢##‰ŠŽ$,¬KùùNÞ˜4¾Ì CL—@ (‚$Q 뮣# };Nt $IB–Á$ûŸ.A†àâ «Pi‚ 1HgÕWu]GST4]§ð’U·ªˆ CpñãO…Õo»PŬ˜íBSøTøô¢ö©ªyË|ªš·´¸ªéhª·Ô¸¢j(¾2æº&¶° .ü©°úoª˜²]¨b Ÿ Ÿ^Ô>U} oOë>Ý]ÓÁûš¦Ô.eÅþTXƒiª˜å·]¨b Ÿ Ÿ^¼>Õ4 MSÑt Uª êªWyUq£*o à=E&CpQH…5P»PŬ˜íBSøTøôâô©®y3º¦£) ºª¡)º¦yUYU] ìdþÕRa*­@P‘ EC×uMGÕuMóþ¨*ºî @T]ãú¼Ät‰à_M Ö»J«Pżøl>>ýWô‹î]ä‰î:QÕ·.CGQ5TUAU”€k2D&Cð¯& ë¿]¥U¨b^|¶ Ÿ ŸþúEÓ4$t]õ®ò”@STt]C‡‚É=Àç-‰$Iâ÷߯RûEQÁ…"ºF+ô|c…Û+ü T1+Õ/T¨_„Ò©ð©ðé…ð©AÝ`Ä ëH€$¼2ï>%VƒÁ«_Tqûí·W¸æÌ™# ÁßJ ë¦XK¹Éµ¥ XÊÊïÅYÿpUÌRl¿ ª˜³þ᪘§§§¥ö‹ÁWÝSÒudIB6Êd£,{ YF€Q*¬‚K*¬Ú…*¦PÅ>>>-ÎI$I§øŽÑ`Äd0 ù²è ˤ{X Ò*ƒÈdþ ”¥Â¨]¨bVÌv¡Š)|*|zñùô¬@ÚkÏ=Ll­Ÿ «Æ¾Ã©DGFa :*’ðˆpªYªáÌwò¿×&VaA†@ —6IIIŒ›òÓ'¥fL´7ÈP>ND¤•èè("Âà ·V- W~>¯û‘zÓ%‚ ‚Û—cTÜnÊ[FWÜŠ¨ï#‚óƒ$Ð4õÜDˆ®{•X% ]Õ¼U>}ªØÂ*ø»ÉIù‰„ÖãH9}€GÛ5eá¾òm!Û³ðIº^ÌÉÔßH¸b‡ò‚O¾93ÓHNN.øÙsàžbÉ»S¶2oþéîsíé»æÐ¾ûVnßÀ]ýºò~aDÝÍŠwûÐoèý¬[4ކòç)O¹ÎÿoVw—胡ÝEž#EUQ4 Uñ—çÄåòàp8Éw¹q:Ýä9œäååc41 "Èøãü)(š¬5én8Œn¶R;!”òІ„Åß±!‘ÕLÕ™šaÁ+#1`êrŽ=êýIzzgEŠt'Ë?|./ÌåýÉo±ìÓ{™òÔ|Nû´à•ì=Ü;5…–&1í“M¼Ò9… w—Ëö³º£@ ¸ô0 H’ÎþCix<Ü.n7‹át8Éw¹ÈËË#בG^n'ŽÅb±`4–^/C”œã¼)(šé6|Ñ!FjvE½:aå::¶IwnÆŠ%¦&Gèå΄¤çda³¥ãp™ˆ.X•®¹O°vM÷i @“®Ci}#'³£f ެ¨þ0#@’èzO?¦ýß^ÃÚdÁ³º£@ ¸ô$‰øšáü´tQQÕˆ´†cÏu››‹ÑºAGÓ4ÜŠ»ÑDJÊ¢¢¢ A† 0Š”±ƒª¢*„†8FŒóîÃîùàCå>¾Zý® õ=¨ßÿ`ír>ë묟|;-&{oØ÷eæM»Ÿ:aÞAÙ®hÔ‹ñÉ„É;ã eHl'sysÎJÔnÚÌTg…Ò*eË©uÇÿ} Á Ë2W^ј/~ÝÄ—ßýJƒºuˆŽ¶R=ÒŠQ–Ñ1 yòóó1HÇÓRIhXððpd.=]=–u›_%¾nnûA&]Û‡o×_Ï“×ù¢¹-F¹XAÉû»âÈÎ5²èN@p‘c0¸æêvìØ{˜'Nc0šÐÑ0H !áVTò]!˜MFl™éD„‡'‚ Áù¦rJ¶ã‡9š­Ñ(±Q¹‹ôø;wx­xÎ^úfk c•vr$ËAóèpPŽ8Tb}Åpj$´ sï@(pêÐnb6.¡ ÔÁÅdÔ­[›¡zðí‚Õ>žŽ¤k(šŠGQq¹\„YBQ]¹Ôˆ áòæÍ©W¯aaa¸Ýî’ï'ºTPTF)PsbtÏk¹¡w7&ÿ¸·êέç²{ÃÏ­(œÚ¿Oæžäò¸HïÅo®C¿Ûkóþœßqèn6ΙÄΘ¹¬†w° mNwç;ü¸þ(šë(óÇI¿¡W]!ÔÁEdFÚ¶mÉ“ÝÁ€­©bÀ–MFFy9g0¨vš6ªM§«Ú“˜˜Htt4f³Yd2•~ð-;Q EI¶Ð©•Uël´mYn³Ê>·Ê¶¯Fðü‚Óy`ê<†ŸU”Ì\ÿ䬿¶/MÞs¥?­Z  fkÂëß¾I§~™4¹ó-~è߸è@} ¨; ‚K É`Àl2Ñ8!žø†õ½»L|51dY&¬ZáÕ‰ˆˆ 44ƒÁPfQ.dŠp~Ëx_cF·“n³¹ü—d™ç–"¹÷ÃíÜù?;N—Šd#2¬è”­MyeónÆf;0[«S­XÝÿ¸¶ƒIÙ߇lDÇD•˜®¸ÔÁ%dø2f³£ÑˆÉdòʺeLFF££ÉˆÑ'ó®ª*šVú£”˜.øšÏ¯‚b`ä Áœ;Äb%**ªD€q.ȱS"À(Ä-QÔ(%À€‹[ÝQ \âÁ†$yƒ ³ ‹ÅB˜% ‹Å‚ÅbÁlò ’$TXAÖçSAñRå߬î(.=RSS1›Í„„„`±X !$$³ÙŒÉäÍbȲŒ$IH’„ªª(Š‚¢(äää”x?1]"ð…›â]Vf³ÉCƒF1¢ŸÊ‰ÑIƒF‘ç§_ø,`»@ œgDžT ÁùyÐ] (Œ-m'ËÖí§eï~4«Rèï»Y¿}/.s ®ì؉úÑ"õ.ÿˆL† Í±Ñ½û3fÒ:r\çV!žNþ‘o`éÁlÒ–¡s»ÁìÊðˆ_D&CP€ýX2«Ô^¬ßý6 nÚ4OÍeÚãALè±Î|³ê S5&‚2™ A’ÑWÍ¡HMûi7¡gödÂ$²Iħ@ ð)ç"NÕÆâÚ2½Ì°kúñBþ$êØ–0e{VÏH&ÿãŠèº“m‹¿däÍÑbpêXŠ6»ò½E¤¢C­XÂ’ƒÍîý&¿ˆL†psòÈaVåªt¨n)ª‘¡;YòÊKtyac‡·ý,{;3mÕfþ§E¡÷Šž@ (ŠÈd@Šä¦/‘´ò}6ϘͱŠœ’…FÝ£É8x˜,—Ž;÷8{·äÐ6¶h)¡è)‚âˆÇMÁ¹xÂh%µ˜˜^Û[¦ÓåÆ[iùí£4¹s ³ŠiuEO@ ˆ Cà%“\‡aç…°ØÖLþcOÛìh˜‰Š*©*=@P1]"(ÀZ¿#küEŸ6X°/»X«LDTT©†PôAiˆL† ÉÇø5œz†šqÕÊq …þ/m¤¿èB@ ˆ CPK Mš µU@ TÁ˜"º@P(n7* « Šª Û@ ‚ A9ÐÝìÙ²„oç¯Â¦¬u'ß »Š7—¥p`Õt{äòuPÙ¹ä+¦Mÿœ=®¿Éæ²l2ÿŽoÉuïgÁ†4<¥ŒÓm×Dsœ¢ý5Mõô2…YY6ýeö¥çŸ§ "›é›²ö˜ÿ÷/Í6@ ˆ Cð!3m nžÁ—oÞEMSÑÚ•æA’%ðdc+ø«Ìå×ôgH§hBBC@wãt—žEÐ7nw٥ʷ·Û+?¯9ÎÆ–¬|~%¥Û&dþ1ÈH´ëvYѲ㒙Ëy˜è™¨„ô­^( pcˆ’™úîdâê'˜PŸO–ï-$œaáGÏP?>„„â®ÏÚý§ Úݶƒ|8®=ñ ‰$$Ä3pÀe<4}*`KÛͲEKX•«²véb~_³†å+V“fóg›@ Î+bw‰ h²2þDª¦”~t¾Ó[ ”ÚR<’ —ÉϪÃo›¶‘¿g}G¾Áõ;?£%Ùã¯gÜâ,X³•ËjøséWÜÑ£-_¬LâºÄH®ÎŒ´§H>|&ç1|p;ÍÄ£ë8méìÚº€Cû’Ù+E““uZtLAÙ&dþFÜöÃ,øæ ågE–ûx†±] IDATçQϾ|MêYÐkõ¦»e=Šjn*3ç⛕ciÛ0€®·>ÆÛ+¾å§Íi\—IhdS2ÇÛïeÑ VMÂ/Ë·v!T’¨Ó²'c[4áÀ÷ó4z ½B…³à„˜.Dqd“´mkH¹7!qv%…®yÿ/É «*;ݦ¹èë­ç~¯}Å Ì™3‡öõ#1“Ëžß'3ð¶9é[yª9ÝØ ¥ÂŸOW²9’r€Ãi¨ÂÝ@ ‚ Á…#,¶5>žÏì —±!9½\Çzœ62Sò9}: €|[«ì™äd:0FÆñ|C+Ïÿ÷;Ò²(Š“ä ³=ë8Ýš×`ÿÒ‰¼ðÃ):Ý<„¡C‡qïà<ˆÛ·ìÂ`‰áªèP¥Äá°“²k-ï¾ü6ex‚¶ñÄöyt¹¦;C_݈&¶· A•!¦KA]£z~9.ÝÉOûófZ<ð×oõG€ç7õy•õ¼ÊˆÅ‹0OºÎ-Ÿ+8lúœuÜÖÎdCâØ÷í£´ö)ÀLød õÂ|‹O¥HnygWìΫ¾ö1¯|Nk°vªØþSžîQrQ«@ *Œ¤ë•t›3gN‰¿uíÚUôîEÆ®ïå¡%W³dÆ`¬U<»œvÜ „XÂ1Ͻ·®¸ñ`„§Ó…±X{á×åk`6›‘Ëq^]9Á«»ñ[÷·Y8õ&QCC \Ò¤¦¦b6› Áb±BHHf³“É„ÑhD–e$IB’$TUEQE!''§Äû‰éAÐÔky#G~KóËÇpÄUµÓ !+V«µD!͘’ÑLX)í…_g)g€ «n²Ü*Ï?ÜC@PňéAÐTOìKÒ¶ œ°¨e¾8>“!¤!oí<$œ+"ÈüÝDÆÖ'2Vôƒ@ ‚x] ¸PœUC½˜lÓU·¢jAÙsÁ¿áS@‚ä·s*­€æ:Ľ-Yº/ûgvelÛ³ðIº^ÌÉÔßH¸b‡òÎ}î£;~eÚô̘1ƒ%ÛO\ÐÏäÊHâÓéÓ˜1c3lÃSh}wVÊ:¦M›vÁm*¶´Ý,üy>?,^MZVIa·ý(KÌgÁâM%®5€S¶2oþÛtåܹuµhT©;ìÈf¹B×Ñ¡MÓéðÔ\¦¹ÇÞ\ÄN‡øfÕÁs¢Mó™­ÜÉÜ_á‹us9òëX6§8 ²Ë?|./ÌåýÉo±ìÓ{™òÔ|Nû¢^%{÷NMქILûd¯tNaÆÂÝAû4¤F+&ÎÙÈSõ«q2Û%nz@‚ E™*­€ÁË}£Ýb*…ÓñêÎÄ´¿™ëÛÆf­C·k¯‚èkhoõ dþUZíZÊ]Íhœ˜Hø8nJhÀâý¹@*­eÙ$±Mºss+–˜fLqY,[aÜe¤uìÇwòƈVÄ'$Ïð×çpÜ~îµ7Ìæ¦„F$&$Ðvàž¾­ï-Nñ=Íåÿ^ºƒø„š$&Ðæ¶WÙsªä“µG-=€Ðgëâ¹¼t{sš$&ÐÿõÈ,´-Ù¯mº“ußN¢~¼÷ÜmoHýVÏsÄ¥£¹ÓÙ´fëwl`÷†Õ¬]¿†åË—³+%«X„âfך_øø‹ŸHÉp ªì§Ý„F„\Ua’Ùd,8n÷ʹ ?”º& cLK¦ö¯ÅÊ]iÞÏå>ÁÚ5YÜ׫%Mº¥uötNf{%GV T˜Î‰ …Óõž~ü¾x/ŽB™À>5Ó(É(‹›^ A†àB‘•ñ'’^ƹÉí§^ˆTl„Ì][ùmýfÖ¯ßÌÊ [ˆ©ïñf%ô\f¿žïG°`ÍV’“ÿ`ö¤ê éÑ–åû³A?ÍÿÝ÷]?ZÍÑ£©ü±v Âd<º7§QB¥5ù/vïN&Ç¥e[0T«ß•¡½âAªÍý_kC±ýÉW÷ãT»)lÚ•ÌŸ›—Ó!ã :tû§=:i[>ãÚÛÇÒoÚ\6oÛÌÇ5æ›M¹¤Éóµ ÑÍþâ5›Ø½kÏ6þ‘I “Ëe{êŠMt¿˜-kçQïë'Y¹÷LP¶å¥­ãΧ>fáÖ¤Þ×ö÷It—}É»ÙwÜÉ™”’÷$³?i7‡3Š®}ÐÜGycÄ#Lzáž_°¯H¨ÚaÐˬy±/|ø9ï¿>Œg·÷`x„‚ ÄvÊExÁÔ–LTlöBq£]ѨíÍÒHf ÂdŽñf:l'sys΄­Ý´C‰LO°>MJÍ7½@±…UPi*§ÒjG»ÿl€È;¶›jÑ-¼ÃI •ÖË⹬GãFNÃóxkjÖ°Òkâ´©ãÍoÿ“UZ÷oœÍÎè§ù桾DJD7ã¡I3ùåûؘrÙo¿C·W0²[êÞ0šå_Õ 5:ÆÛ7*¨9pc·QïÙàæÃÚD £{ré6a2×·m4dð½õø~× µŠ `ÛÜX+–Öfÿ}ïm®n܀굙1ãqê†,5æî‡go݃8\Ã1(±ô§s-F½9‰V‡TúöI(ÒæÊ÷$Ñ¡V¬a AÉÀfwCDéþ3‡{V’Ûb”‹e$ïïŠ# ¨](¤©’™Ý[ðìðÎDNûŽ»tÅj…ܑɜ*£Ò*ã!¦ã½<2r$#GŽäчsdÇÙyþ*­R8×Ü÷!³?êGˆT{&?>?’±³vž{b®•Ö|Û ØÏÑS9:^¦”Èc9¢h*^%Ú,q6T=ÄRäf=ïäú¶u@w2oü­Ìr\ÅÆÉ:¼Ÿ¹o(õ†ö7ˆV9wöÚÍÚ[7À6CX=&ÍúŽû»· ¾‡ùMå»õiç‚?×!FvíL÷k:2qþÞBÁ‡…FÝ£É8x˜,—Ž;÷8{·äÐ66² ‹Ð¾ÿƒÌn*e¸8sp5OÿœÎ-ú2$uèw{mÞŸó;ÝÍÆ9“Øó"—Õð!á±Íéî|‡×Eseþø/é7ôÊ ²?…¡óW3òƒåÌœt7µŠM³iŽƒ<Ù»;ݺ_ÃI—Põ\ÚˆéA•Q^•VÍuˆWï~lîšχC²è5ЫÆúö‚k˜2¨™_•VÍå$6Dfâ°^L<ÛhÄü%ל[|ZI•VÍÎæŸNCì³ÜÓ-®\ÑÏôäéŸÏ]«¸b2Pýa¶nOíØŽl]6“qoåQÞÀ F§1,ùí„IÐó)~|çcô='4xÏSñ@Ïx$z<úWß~33,}x幑̞0…ÿ¼Ô…So"eÉkô~ø«‚c;¶ôöЧ+÷ÐÊ6›Á/¬V±òƽ4=0!¾ßWÜ´‡ýÛ–k¬Î¥ÜÜåò‚÷ïqßÿèÔ8¢à÷¦=GÒerÚøÔs»Ý1žñ7W?KÈ:µ±²j¶ ŠN±µ½e:]n¼•–¾c›Ü9…Y]Îõ}l›!|öèrú´i À³Ÿ¬àªÚ¦‚ äú'¿`ýµ}iòž ,}øiÕÐA?CX^ÿöM:õëÌ ÉoñCÿÆå¾ÖMH´nVúõ`Ký‹U¹*ÿ™ú -k˜Äƒà’F¨° ªŒ¿C¥Uq»‘Ìft·§K'ÌVêAEUZsS–ÑìšáLœµû¯­zMÅaw "cµ†•ä8És)C±˜¥RÚÊþÌçÏ6·[Çl–p9ݨȄYÌ¥ïrªH&SÂvgßÇXj[ŽÍކ™¨¨Ò·çØ2Ñäp¢J™¢Ó'¶lfkuª™KžÛã´‘í€è˜¨r÷æ:ÁkWw£Õ—[éyÉ5H›¿Í­,Ûü)Í£E²XðUXE&CPeÔky#GAóË7°~ÇÛ4©º@#Äb¥´ÕF³op3[°úm“Œf,8oVƨ9†þ]âÎS¯É„Y­e¶ü|.C€Ï|þl“9Ûí!‹ßãC,²ßv³¹ì¶ˆ¨(¿ÖEDÅøñ·…蘲m3Y¢¨Q "ïÈ2šv–>,«Vjëä¾­ôÿ¡0‘ÉT5Ù§Ò8a7߸®N\thîlR¥^¯±å\ä,ˆL†@PI„J«àbÆ`ޤq³HÑA°÷ŒèÁ…àliê²kEŠ@ ‚ ÁqKWaÍIù‰„ÖãH9}€GÛ5eá?P‰µ¢øSìdUDY*¬!Vo…Ecˆ•fV3ÿ¦M}•QdUDY*¬&kMº£›­ÔN%¯”Y…²ÔD ·û›Žðn¥ÄO»‡³üÓÔDý)v 2‚*¢lV3݆#:ÄHÍî£hQhë_ 5ѳ*¬gÕ@‡Žy’¸+Æs0Ç[Úq*‰7F´¢qb ãâxyÊ8î~éò}›¦Îµ'Ò$1ž&Ìæ„CGWNðþÈÖ ~ð¾ÿy>OßÖŒ¸ÄûøbñNòõàÕDƒQad•¤,VCH#Æ À*™éùàC4>7ûUÕ,xµ/#¦¹˜µp [7¯¢oä1ÈþФ£vTû^F\Û—•±O±býVÖ-û–S³æóçž\4@µïel¯›Éëü»öä@òF†þÇU×~JŽ\“c§a^;“ÇžYKß¾çÇÏnfî¨~ }g#î ÕD+ªÂ*—b « ÒTF…ÕŸšh¨ós¾=Á‡?OæÚ&áÜõÒ‡DÔ[DëúVŽlÿŒUæì˜x5 P›·–ÎcÎj& óðNØ<Œt`ùóQÌáœÎõ@Æ/d: ¾WýsÑúÿÑ2Ú\ÎÌ_Zõÿ„ã|”š¨@ D!8TX…Õ§&:/ñ6îK­(#Ûæ>ÅØÕESlfc¡ËTªNÿÿÀ~L‘ZþAXÝö â `7˜ÚÓ¾eCb ЉÿùŒ_î §vàVAnKh¡²ÓæÐð¢T 5ÑÀaéiGÈu5¶>5­â–—bºDPi*£ÂêOMÔ`‰¡wêLzýköŸÊÂaÏäåŸÇúcù4jw#œz·¿ù3vÙ§3÷ÎÄuúŽ|]§zýËÁ³tg$­®êL‡+[Åi~™¹Œ,ßS«´“‡^úš}Ç28‘²•×o{”=¯/²€ÓŸšh „"§@ ™   (¯ +’% šèÝo-@{} =Ú¿ì=ÆÔž©_¬ c½PdÚ±cåL^x7­žñJ·7¼a¿Ìéë]Q£[—}θ}x>×—°ôaê‡c|F÷zÇèÙ± }—P ðHM4B‘S \ÊíA•QQÖ`ÔD½*¬r¯ñª…b )S Ônw` ±`)¤ø©{R¹»ýDÞÚñ±öR-¡È)þMTµv‰øÖTõZÞÈ‘_ÇÒüò1)ÇÔ€ÁlÁ@®<Äbõó¯Zh醷Ýjµ 0”tf½ú4«Î,e̸ L}çGÒË´Y&Äb.w€qN‘óQ`‚K1]"¨2ª'ö%iÛNØ Ô2ÿ³m•d+m®Á—=Áèq£˜ªSM®ê“XèÿÒFú‹KC ˆ C ¨<ÿVÉB‹Î½h!\&ç ‘ÃüC¸xULÅ¢VléÓ¿E½öø]œrÚàýú÷ùSq»q+çy§“žÍ_»áÑÅŽ*dÍq‚5 æ³hýÁ_°û¿@B·¹åÀ/t'ßÝ}%O~¿·Ü‡þ[ÔkU{ºßÈî“.t%_¼Ãç?o;oÌÑ¿2mú f̘Á’í'þQ}Œmšë÷µJü{ü©;ùnØU zkåy Žløœ>C¿ÅDÜ™•²ŽiÓ¦7_º2’øtú4f̘ÁÌÛ.hàówžûŸb›2èËÍÍ/odèóDslãŽe|Y}F\\<ðo‹#ŽV¬JkEtөמW…X=›é›²öX~À—þµl n~‡®Âä”Sß1}Ö~ú8‹/fˆ·Y°>µô¨<  «¿v‡ÓY¡r •V$ Íoh…£=H½6à¹ñnv8åNÍëŠ-Yù8\²S®T>˜ð Ï>ÖË[›DŠä†!/‚ä Šå!'&rÍC_ñ;œ-ù^>ü©þòyò’·ˆK¼Y‹–óÑKÇøisI³—ì—²lK^òqqq ¼m ›Žä ü+û³=ŸåYæ=÷À|²üp‰Az߆ÙܔЈ„ï½2ãç^EbŸ_}ý3fÏxšø¯O7É)%:Ìå×)SöÚ}Ôöe1]oál]<——noN“Äú¿þ™.oIÿC;6°hÅzÈÞÆÊ5kY½b9k7üE¾îfÉ;£èzß¾{8g§¼N¿fMIl:€ßS‹ÚçQý•f)’šÖÐ"ógû/+æÐ·é¸ÿr'&ÒçÉטô`š$&0uÞŽ"X s—Å™+¹«YCILˆçÉK±ûî×c •iªÀ6dþQèJ:¿ÿ™Sf{XÝN¼‡…ï^Æ­ØrÒƒ¥v&N¿Že›·p*_ÅhÌ`Ëæ%LŸõ&­cCpÚÒÙµuŸ7Û—ÌÞä¿Ø½;™—Z̧'øò©Ïy㽊_3AöW¤Gþ‡ÍÛÖ2¥ß:žÿl]÷k»!$Ž!SGñËøjáo¼ûÀÞû¶‹VÿBç/³1%¯òסÕß@>oÜq´ÝÈ3CoKÎ%ò¯WèÜu*GƒœÆkÔq(ë×.¦ý‘_HÏWŠ\çþ‡ÙŒÏ,µ;°~ýZîï~šéE§Tö¯˜NÏÛÇ2üÿ‘”œÌÚEŸ³à‰þ<õÍN¯_Þ|’Þ{‰¤þlÞ¶–·îØÀsï®)1Ÿsx /n¹’û®k\ä¼þ®·³¤®ØD—ñ‹Ù²võ¾~’•{Ï€®r:m{¥€û${’ÿ"y;ö%_5ÑéŽÇ´†ŽSç°è›—ùúý÷5o9>|šïÖ èÇ©½,\°ˆåË—³jǶ.YÀ’åËY¼x5Çíþï•î{1jTÉò“,^ú-M–~‚½ó;üüų¼3õOU°ÆÁåÔ¹yê7lܶ‹?ÖÎcïÔøý€÷>ðw=sûW™¾kCÄVÁy'+e#Ÿ¾÷0 òZñhõò­NP²÷óĬ<Ûý‡è´2ñþÏÐý‰k8²ýW¿*¬þÛóÙòó{`jíÄŸ|?g=¡Õ$¬F3§þÁ‹·]AÓV P÷F¾{övÂ$‰ÖÍßÀj_ϤÿÛÌuS¯ÿÛTZekc¿çÖÜ'X4÷4ƒ}›—ñG®ŽIwðåo¹jh3®ºa4[ÅqÕWñ"0kM×&xt«µìÉØM8ðý|C¯„ÐRí8±ý¾ÐGñçU5‹µx æÒ•HIbàˆyî®,ïÉe5,ŒúäWFÞØ€æï/àpÛîüqx4q—V ªCƒÈâ‹ÞZÅá@¶× Âgs$ D’[¿ä ä7}ö%]^XÀ k¯ ²e>žõ,˜ÃóƒZŸØª?ÌúR]’¸ùÞñŒ’‹ÇRžàømÆËtÿ Õ¤"çõw½èž\ºM˜Ìõm |o=¾ßu‚A­bèØï^Zµ®ÅìýN~h`Ñ‘Z Ôil¡ÖUWÑÔ” –>\Ù&û±«Xb<¼¹§I=”Šl•8u"ŸÔuGHí\ ‡ÝDü•]¨kõo{Bý\YïZZ\ž@×VÔêÕ•ÖÑ‘õ§wc­V¹ëU2™I[3N£6P³™Ón tï}`ެï÷z¼¹qÙ*Óit"¡Ú…ù¾A†à¼“g;ÉÎ_Ï@资‡•ï’;´égˆ¼yßZæì„˜Á·²ù£ù¤>x5jVÅ_»îÄíPix]š7¨ƒÛ錌˜ù=Xë"I¨;1ÌEÒ}5‘ù» Õ÷åúwª´:wï¾-‰«c%ߣc25fÁ‚눩ßà\°Rèµi'³ Ð—¾ætcW4ʘÖÏ0÷±éŒ›¶œêŲO2Ó´gŸQ%¹dÚԟ황 é:’9ŠÈ|@Wñ ³d$?™³lÒÒN££¨_¿†÷È Týû\ÅeSˆ‰8÷ô-Cˆ1—Lû³íÜç.¹Â ,Åá`lè³ö‹ (- 9p«€ê!æòæ%0þäù'Ö3zÖq–íj]zpìçz¨rn²´v³vè…‚·ËMæ¡bAM!ÛuUE•<炱R¦«J[ÏÝèj~üjöÖL"óúGJ}`ðg»êV ®Q—Ë+ìØÝ… ªó—o;ÁñŒ\ÌÖXâb½SJÖ\yÝüwöo$MŠ'”LÞéqí¹*àõXe:ÛÄt‰àO\Û|µs%ÝõØq8'øAÔ~˜9/|ÉÈ)÷ððãOðì³OðØ#ÐOþ‰o–'Ñ0€ «_•VBiÝg©ëö#Å\F—.]h}yö´­ü¸b?š®µÈü}ïÌßDzF»Ö|Gÿ§~c䨮ÞEŽ>þN•ÖÒÎm0GѶe8{Ó=ÔkÖŽ.]:Ò0ÖÄž5?ñÇ‘ltÅɾõ3iwãh>[³‡½ëÿg_ÍÔy; æk –®ŠåPÚI;)»ÖòîËoóW†÷‹üÌžå¼™s·w*¹¸ïtF™3Évz€39 ÚÉq¶ýLF†÷µ¾q8=' YÞ5'»l» [ÎÒsN{ÿmw˲̣Ë5ÝúêFŸ/}O®~T}Æeû­oæ•a/ðÛŸ‡î*¼ IDAT‡È8u˜ß™ÈY-hT+, mºâ$+Ó†=׆C×8}:ƒ›\§; âp0¶û÷™JŽ-“l»Ìœ3xr²¼ÿ¶ÙQ¥pZº‰5¯½Ëšä“¸…Ì#Û˜zï:Œ¼ƒzagJø4£˜OUÖÍzžOÍ¥I±ú¯7Ýíë¯,o_w’‘y†ãé§ ÒúÆ08>ž]GläÙÒÙ²â;þûñJòœ62Sò9žaãêà\Jf®&ﵓ¯ë(î\l6;§}6gÚrÉÊ´‘_l¡wþ™Ýœ)1%èÏv7™E¯Q›Ý;¸»W‘ã îܺ›¥ÓÒ­{æí9·­Yqz³qujФõ¿2ý˜ƒœ¬Œ‚~ t=úS™.Ë6‘Éü+1˜ëЫ]$’1ȸYw³pò`fœp¨ë0˜Ö2þ†p¦ô¼™6±ëî=Œî?²<ôy%–™£j3ªÿËåaÈ'µøíÉVÅæý?O2ö¶7 Såž×+3ªU –=~ ;¬¦rÓ2<Ðïܼz?׎gÿ:â?âBꎢfõšüƒ 5v­›À›Ï¶Í ¯—Âõ7xç :4z½i÷µçþL•òM`Ò¼7|ug¸ø#HÞl© ¨×jP^a-iÉË@>ãKtJÌ{H:ÓÝûyí¦¶LÌTy›6Ò·ŸÅ뿤^Ï—˜l|D¯×²wç‹_ñÕÀ¦Hî=Œò×iÏa•YøA½ÀßÇ&2ùٶ虫é÷~ ¿¯.Ï;/Ù…5Øö\XŸ ZžîÞ1ó¿ôû³Ë>¹µÄã_:—ÖàÇv»x …P›í¬Â¢†W%G‹Å’—ÞÈfÆ÷s¨×»16éœêílË-xžÓx£Ykæ·yÏ󕊬ï¢}ƒÖ¹¡òÃ=7Pá͵t¬~á‚ÌÁ‡KãX\d•ºì\œty 9—DNú~Y ÷ÜÞø‚†ß½ªŠŽŒÅrõ<ŸÜ;‡Z­úóÚËpSlÑ×0VÂOo»J8Kï2]óíª¼úꫯžk!mÙ²¥ÐgÕªU7VA>9+ãr,gðàÿ2;».wµID9o‹ɘ­VÌf嬶KŠ«ÕŒ"çÝäÝyúÎÿ°aóŸì:~œ ½×%D»“YA‘ÏÜ¥uÍoo¢tA¿fUÎú·;¶ÉlÅb6Ÿu¿¨$+˜¥`z)„¤u(c–ιÞΪÜJ*VÏ1þÿ5ÞC(K±õ}z™”Tçûþù†¾ïLgý¡,ö,^€½îT-sþMfk‘ù –÷ë¬ÔõmÆjµbVÎ,µ)¼ jW¹àýï²¢ (WW/ú®…|9¿!︅0E*æ.Üv;}.ÓÃøbéB¶Ìb÷ö$]W“°RˆùììlEÁd2DE®°PY–‘e9 2 Ã@×ut]Çív‹H†àRF3TR÷íG³U zÅ2—uVUG*ËWnC2[PU'QÕÓ(©¼¨Ã«˜’êEâ%Bd.§龿¥3\{X)ágëd*‚Ó††î‹Xhš†¢(¾¿%=ðU]×Ñ5_”£(Dw‰à‚âñ»$=êë ÉÉ:ÊBG&'2þí2³¤-Ú¥°4.†çêd*  Ðü]$¹/MÓÐt-ï½ÿ¥ºˆd.…V™ñvO¿Kâÿ¸eÝ(–½6<étiÿ2ËּǞ/sïèÅ$—Âù[¸µF;‹q Ìïbx.N¦@ ÈCÓ4dYö·ð‹ ¯æ-àW Kr?=ޢˊ ®xÎÝÉT »wïFQBBB0›ý†yfs!³´\±¡ëz`YqÉ\}.ïXM÷>C Α\gUMÓ$©ãªay>%|Q /Ša6™…È\mWD(Ý_ù‡î¢$àœQ…œœœ€àðu—hy‘ CGÑ”ÀôUÇËI‡ƒ +fš‘! °(0™ÈÉÉÁëõ"¾Y&y3LTCÅ0 TUÅétbµZ±‡Ûq8Bd.? ͋NjIBU ,qZŠ:—]×)_¡‡ÄãñJhhh`<†ax<<n·YQˆD:NGtb .ÞÉëLcñ”ÉÌX¶»ÀêÛ¦£Í£39œ2Ÿ„ºƒØsêß1 5uý4ƾ?žñãÇ3k]Ú¿ê\ø·Ö¹@pÙ?‘ÄÅÅát:9räGŽ!33“ôôtŽ9ÂáôÃp˜Š-7·KE ’7¯êB²„¢\€ZSUfBÏ¢;CW]äh` -œ·ÒÔ¹@ ¸øäú“˜U«TÁf ÅåtšÎj±X0›K^—HD2 3’I+ôyÅmèZÍNht-^t ùO[ÝÊׯÜE\B5’¸®×lKÏ lw¦oaô ú$&%P=&†Wß|†û^™ps-iûžU¿Ó%!žII$ÄÅ2þ¯õx ç¡¥Ü[«:C_þ˜_|›. Õ¸ã¡Q,K>ê¿aÅây,[¿œÍ˱dÙbæÎ˦½gnò¦zŒ"ÅÅú)SDÞ~_™ê/“^l”Èco}ÉÄñÏ—DõÚO²bÿ‰‘£ó¾ãÞZÕi1p~ü”þ=“è?z>;DLÒƒ,ÝŸÆaŸ nžL[w$üØ®Ü[«: I$%Ä1lülù–ÔÉØû#õ"&¾_ý9ƒoF!¦þìw`d3ç›ç©–D$_Þ–ìµsc²Ò6òÛ/Ë “°›d¾³–—zÕ¥fý¨Ò‰ŸŸ¿›$Ñ öhìŽeŒøz%íÇÜÂ}ƒŸ`{•Ý8ÝýÔ;©¨šòÕï6[Oé†êÆ(×ûoo‚¹Ä›ª ¨üùVOú­ô {o*”7+Ä%ÅCÔÃ<Ù¯Q’D×^àé>'ñfã$kÇþÁÛ.§SýÞþ} µîÓˆ­`ÇBµjù ÉB…Ø4hÉÚüŒÙÂÅci:t9åY8ªê`ø¢P)«¾æÚß1üžv(@íW?áàôIªYIMcƯéP v¬œÃÚ“fÃç®ûíüÝÜз–¸ ‚+"š‘/!ÉX­Vrrr X½ç !2—”SY‡Ù0í„ÜD¸í N9ÃŤngRÒëü³þi*DšXóëpž^ä Áy=.0G`ÎwŽÛª4¦_ßû Û ªS£zûŽÔ®VÕåL úþ7±WÆ*IhÑñ–á¾2åãÉ\š…˜ÉíêЊD¨ìݹ†ÔŠ„æ É×]36¥ˆ‹tǬ7éñÔ)¦L[Ę˜r8/¡ÁÍßcÊ->ÍCtÚœ.ÙdÿåX'§ŸÈP½n¢«ãÁÀqÒ „:¶÷øZ®o7ïLœÏ–q„ɸ¶7åYçJe8‘îÄc(’„¡99®jÞ¼rèй1•íäx ÌæD¦LiOtlµ3‘—ÂYW ¸†0HË]ÕÀb±°iÓ&5jøÞéVðE!ºKœ˜†·ñ݆´1~gý¾g”Öå¥QBU¢Ë˜Hß¹†IoMÇ™™Æq—F|£NþïMXÊ1‡“ìô}ü:º1M&Ç0‚o'„o#åïHÑ×мysÔ‰Áq`5ÌÛ‰n@2—>øÉ+8’‘Á¦Å?Ó}ø|† mQ ¼¿iE2N'Gmcò§cøyÙdk O¼ýo¿þ:#FŒð½^‡Qçu 8Yd;²È:qŒ#'ŽúÞ;Ü~ áÛ5T,_õx*ó~ú€£¾™9Ç22ÈÜI¶K üæà„ H¡´Ð×ïjÂ{?þÉ´IP¿Ãó„•µ¢ñM#øîÏåw:9¸m!ÎÏàXÆq<†×å‹<ÄT.G¶,›Æûœ8žÇ0Hjq/eg¥Ë3Ÿ0kÎo<Ó¸53U_ƒb‰¤a½p¶ñPµV#š7¿‘êÍl[ü'k÷g—ºÞ…³®@p9„4òÞ¦¤¤ðù石oß> ÃÈ[n<_׉‚K†l©ÌÍ"Lg0B ¥ícÃÿHW’’hÖý+®}bËßäžWfâlÈúß“þæ}Ô¯]ƒº[2vg7¦þÒ™IÂT¶QÐíIí†1qd =š×#&&†š×6áµ…Ú·«åïÎpprÃW4ºî::õ}†‘_Ìb`ë˜@k¶BóyÏp]4lÒžÉ;¹¶zT©¢4<׎ºµ¯åβldêÖ¾–k[¼ÃaAb«ÁÜå}—&µ©Û¸%;Ê´¡g½¥ôhÿ2ûŽïfTÿ‘ö=‡ÍDõ¤þ8vOÜ<Œe3¾Ã’º–äŒJ|õÑ NW±“úG |?”z5jpc‡YxRcÚÈ;˜·ë!•0~xkîn]ŸÄ >ýOÜÝŒa··äûåi„T¼‘_—Ïá¡–þÂ-ã>ã®è\ŀϦÐ)ãe×N$&¦:šßÊnëu4I*WêªκÁ¥fœÎO?ýÀ¤I“Ð4-ð’ÆdVÁE:k]|}ÏXžœÅ=M*ŸQR]uqÊm`³ÛŠŸ‚êp‚ÉZÌ×àÛs÷o µ`1å…åwÌü/ýþlŲOn-!‡n—†d6ŸñØ’öëp81Yà µœÛ~÷/ÿ˜æOE±cù]ØrlyU\ž`Ó‚x°^Ìö@.[èÞ Ãæ&ssBXÁô†B¨ÍvÆÓk…³®@piHMM%*:šªUª`2›X¹r%Ÿ~ú)999Ȳ̃>H«V­°X,ȲŒ¦i¸\.Nœ8!"‚K„d¡fÇú™¾›õ›÷¢›mT¯MblÙó¶o]Ífãš d8 ÊV‰¥n­x1 U ¸ 8pàÑåÊ"3¦Ïˆ ·Û,ËȲL§NèÛ·o‰‘ !2@ U«`2™;5MãøñãX,L&S`ÐÜm¢»Dp…£¡ª^Q ÿ"¼^¯vvÏ@¹çŠWU‹˜`,¸uze"D†à²!ëÀ~ýiÛ2Ü…¶í˜ù" ­ ,.¸Ê1\ü|ßõ ûmû'=±÷O<ÃÞ£»x¬QM¦ïÈåy‘êlÝâYLš<ƒég¶ò­+óÉÉÉ×¶] ŒÛ Z§†‹•³~cê¼ 8Eû D†@PºsvèÎS#þæ„»pÄ¢bâE4j*³Æõ%&¾Þ΋Ÿ.9£¥¾ÑÍæýf5Yr0çÌÊÂïMÒð¶ô¿½'111|¹hß¿ò¼8ß4«½&«Zv‹ðE¹(çºÊ¼:Ò­ïþžñ m›öecº§ÔÉw-C‡¯ö=>âˆZÚ:U9´ý†<Ð…±3w‹º"C (Œã`2 µ›Y¶þ=šT +âÐ=èù?’j·}Œg:îeæÌ•|óÖ;lË,ºKÅí bÕp©jñ7}Õ…Óå:ã­áÍbÕñœî3¼(-‘ôzÿ3¨¸Š´º]ùæ›oh_ôÚ^UÅéRƒîÏ«º.PxYÃír¡zÏNØ-W)”Ú·Ö÷¯Trf˜íåi#ïðة”Â)ïÙÕé…*7ÛWgÆYt•œw­Äsâ|ãÍÞÆcöòñì-Œý|¯7ÛËøé›K^Aâ¶1sIMMõ½¶Œ¢ªU*]JÜöøf»åÓDWŠA÷“9·},úÆËsÔ8í F¡Z½f\W7‚£¿â?·ìc‚O2%¹°î^>‘. ñ$%$аçS<Û«Î܈Dç&Z’KkÖÍÌ™1‹…'5–ÌžÉÒÅ‹™;o²Jñt'EаÕÍtêÚ†š ZÓ¾}{êT+sZ´£xwÚÒ¸´êÎ4&½ÿ,111<ùÞL0Ž. Õøuíö–èÒZ¼ClîSmq°£t.­eb;rgãØ³8›,´îß²VåÛ åÚʶÑ¥âŽ]*wÛ ”Xn†‹¿Alœ¯ÎöèIlýÿúœkK+.ï'öΡsÍÛ1ö+^¹ãZj$%pëËɃÛ3äÙ1T~üsÚ×-OÕ’\Zƒ8ÄBpX3¥siHjw?-ÂÎü\²Æ0è™Û°KÚ=4˜šeÍ›|°c—ÆÝ6%•Û©s÷ðϘ¾zömãÛÇnõ0ÞÒŒg.!ïöØ&<ñˆÏÞy™&ÿ™Êª%ÿÛóÌÚr´ÀnR7üÅá/2l`VïÏ ±íœ÷>­{¡n¿¯˜ýçóýc/~0•WÞíM%«NÖ‘Ã8p€#GŽ^©i)÷/ƒŸuø Ñuj“k1S©f2SJƒÑ0X6ò®½¶M×£õ /Hs%×iþhŠÿü7µs#::š˜ØXêÖ­Ã Mn E‹´nÝšV­ZѬY3š7oN³f͸þúë©_¿>5jÔ råÊDFF¹?á:$¸´.ÖÌú…÷ž|™kïúšÊ¡g–|ÿºYl0’¹o7W8Åòýé^'ªDÖEï£õëSÒ½!Un}”¹ß•#¥l4z)ÜDƒ¹´Îs O_[ƒ]¿M¦÷£OqsBÈi!ó3wi5¼Ù$oË$©n—)W#§`¹X"k2ðégðX¡ÖŒDT˜µ@÷Dˆ"£z5 ÍMÚž]¤\ºÝ'ˆªK= \µdnß…Ò÷l&ºzbÁ1T†‹”]»È1U¢f|Á…íÂ+ÄJÌbãúÑÌKÏJ/2,6_­ýþýVúݧÁi"#X¹ „È\­Htô [Ú^GÝî98¤i_Á8¼m/->Æoo?,šº®M» `퀭4nÔ Ò»óÞ„ëx¼{#çfÓ‡§~‚]ËïâÆwòüÀçè~í8Z^űƒ[x¯w_¢ßšÇ ·úÜD§úÝD+ÚMٟ̼ß'Új0ÕÊÙÈsi£_›kHß:—îÃçóßßð­~Í eCØsà0ÎJIß½ž©“Wsó£R§œÏ¥µ¸¨Óá ##~œlG^MA:å ~™Ž¾¾(wÚµ9îÒ¨l3ù]Zu²]!þ¿ÑtN¨P!¶cºW S“¼;®/Î _ðâ‡{ò1§ðø¦¼õçr:Õj‡3åoþœŸAX}ŸK«Ï!¶Æi±6Žf8¨Vµ -ô£í]MpŽþˆÖý ~r4ÕºŽóÝh-¥)×R<Ù;w3¬CžÔ˜±~/åí%§)ͱƒ–›5XùnÌÁÊÍ™2Ÿ÷Ï`ê¼±ÜÔ¾ º³)É_OâTN>j¨Ì~¿'C?Oå™—ó¤ÿfXbÞ£MdddrD?NŽaB™'Žq(Ûwì\ñ®;÷ðH“›™"dõš¨d–@²Ð±Ï?ü ~y‘±fþþqãÓ\|H¦ të78hÙ†W¬M×ãü±ìNú]/1ù…oéöÂôËØgïšM‹¶0aé.ZW <,lþ'[õkˆ©`çøÞøü×ÃtíqFMÉÎ¥?S®ù(–M¼¯Àqƒ•«@ˆ Á¿Ek˜Ìà=VÊ! º{¯Ýñ(··yŒ%›¾¤RÚ šv{€^=>gÝÊa¬_ð=/õ¼úÏùúû«ß:4Ÿ ëpþ÷·uÎ[öþáŸ2°]U¨[K IDATH>›‚öZ/×Îk`‡¼ø!ÜDó¹´>9€‘_Ìâž\—V)‚ãFвgÞð§xêõ¯¨\ÂS·îNáéf73%Ë,bÚÈ|+>Ýâs§myGWÆ„väõÿ aâËorÏ+Õ™6²ŽÏ•5ËCÏa•YøA½ÀßÇ&2ùÙ¶ô·€¸°pùbb¯‡Ã°BÍ v×ï<¥ãÔû2ß³èÈ;èyó6ÚµÌ]Þn4©ý–¯Lþû"=ë½Gö/³lÍ{~Øë˜2}É×òÕGƒ>Á¿s¿Kkðr-™³ri-áØº{O‰å<Ò¼ÜZšÂÀ5›®Íë6µ}ð]š&æÝðtõ+ÿ< Ÿçþ|n¿%åýľ9ô±XÄOVÑ&ç'ú¼¸XȼN[¸µ†ï†upS²< ù¸—O`øóÝüñü`}—{»µ ßGÐ-rf©ëC¶Õà­ŸÞ¦i·f¼ Ô¸ûüÞ=±ÀwÌ6¿hˆ¸Ÿªe-Dõšïñß)yãGŽ™Dÿü¿¿473³C*Úk§Ør\ø¶],+.¸8±w:uÚ}ÊìU“¨sÞ­½KãÂê-Öí´87ÑÒº´^•,Ë™›…#%ºÓ–ÃÅ„GZ°¢ÝÞï]«@¾‹wi-½ClQ°Áʵ4œ«Kë¹»Äâ,¶Ü4TÕÀb‘üSª•Bß9¹wµZõçµ—3à¦Øóž÷u“£Û‹ ‹W¿GBXðz›xO"__Á-§' †Ç•E¶ÊFG™7ëâ¡h·b·ËË­!YlDØ,g|/ûæÞLÌϵ*tìÒ”«ÀÇùö.‘ Áe=¶>CÊm¥ãuñ|2 ÝjDœÇ½û\X‹} ³„bÒ¦YCíXOos]ZO~ËÐrý¹ñ¦x ý5ÅDi,„^€2+)ß% ‹ß^kÃëë¯åèêY`nÌ_/ÇÊ·ÍT|™Úƒ”éÎyïÒvà":\·•9«\üç›……BØE•kióîsiýä¬]ZÏúØ¥ŠÊWn Kîñ‹>#Žgì‡òOѽyÌùÏ»á"eå î{ý»â†¡²ä»÷™³ÛÁW‹2)÷Ü—4øa(•JÙ…i¤\hð²±û]gs¡GÙ¤9ãÓ\ŒøeL‘â¦4å*È_¦y±‡víÚ±hÑ"ŽÍ‹4Ùívºté"\XWº+“])Ç(_-ž²¶Ë[ÿ^ù.­’×±ý`!¨Y«Î ž,‰ é+¸°çÅÎÕËHÉrc±XP=!\Ó Dš¤Ë:ÏGìå¤MBqž+©©©DEG"+W®äÓO?%''Y–yðÁiÕª‹E¸° @ (û÷ï÷­•’$1zôh6lØ@bb"ÇÇf³a6›‘d ]Ó… «àÊÅм¨^/‰õòC½@Ž˜¹N›†æ=k'V@pvÕ Ò§Oz÷î¢(ïHr ‘!¸l(Î…uÛôa´yt&‡Sæ“Pw{N‰›ÎÅ$mý4ƾ?ž_çn) (t÷¬Ÿtþ]N ?÷»·çìe×ÂÑ´~äwá¾+\’'¼¼·Õ«W硇"..I’ÐuÃ000Ö!"D†à² $Ö+ó=;ÖË sxÛ?ÍÈÏ7æ ¡g3QÆtaÆÏ4L,îL§q«¾uGÁEiäkÎ ƒºuëbFžÀ0 0*4„È\saµÚ*wcu"ÂÌÙŒòE¬×¤ª.\AºR®$ÖÓóæ,Áé4˜[¨WUƒv1•´ Ü5-yþý{@*¸º©l­Îȵ»¹)ˆ¿ÈÙ:™ºx <Ùd‰ËC ¸x|§ ˆÀµìõþ¿uß¿Bd._ÁÄ…µb6t­f'4º¯ º¦ÀÒÆÇv-àÞZÕIHH")!Žaãgãȧ¨¯HV?{VýN—„xjøNÇÿµa”Ê-Ôðcú§Ï—@BB}ŸFLÝØ}Â×8m`ô úíýßú…C޼rsel÷¹pÆÄðÂØ¯øyâ_„åó?Jžõ?bbbèÙë)Vì?•×@•ÆÉ´$—VÉBG¦¬U!2¡'cÃÅ"\$NHä §Óš¦¡éšWC×õÀKˆ ÁeK0Ö°Øô½9¤J x¨mйÛeÐuÌþY³‰µK&±}Ì@–îòÝô®dÖ´u?кçc ùy1»öíaí’ŸùûÙ¼7VÉláÀâ±4ºœò,Uu0|'û•ëÂZŸU}æÆd¥mä·_–&a7É|?f-/õªÔ-Tq¥ñËOi|ò×Hnªá‹ÜûÊ'”©:ƒ±vv.Ȇ²Ï2apg"$ ÊÖbðˆï™úÛ­ü³w 5÷|ǰályíNßö¤gøëT ýÿÌ{ ‰¬Lµˆhâ’Nï» îk6‚»´ ‚K/2RRRÈÎÎ&''¯×‹$IX­VÌf3&“ ³Ùx¯( š¦áv»‹´{"Cp‰9{Vïñµ\ßþnÞ™8Ÿ-#â!“qmoÉ·æß•ìª:5ª·ïHíj•Q]ÀÄ ïã{e¬’DN·Ð\,ùdJQtè’=PjèvB ¡¬EÂð‚æ1@¶Ø^T½haQðã`y+Kk)šÂ³vaÅS³fͳJZÌ*¶u1®íÛ·£( Š¢`ò7€†a Ër`0 €ÇãÁívúdYôê®LdYF’$E ¬ù/Îgàß)0 #Ð.˜L¦Àý/÷^˜Šü·hY–ƒNÍÌÌ$::ºØí¹SOó“{ìÜ.víÚõo;xðà¥dx<ªT©hh _ ‚$¡y½dff²yK2·§°u÷Av8FNŽ/*š 5㫈³TpYãÕu4†W×0+2•ËGR¯F,Í×¥J¥ ˜L&$YFLÊ®~Œ<µ€®ëe¸ à ''‡œœÊW¨@dD’$ùD„ä[â*¿(0 I–÷Ì¢p¹\D—+ÆÍØŸÎ(FÄèºNJJÊyÿýUdDFFRµjÕÀÓ].ªª’œœÌœù³lÃ.ŽfçiçázpM\,¡6+èà/uIF–%ÿ¡äßÈ’„¦hš×?­4ô@åÈŠ"Ò‹ô,½+Çí%¨ª—½)‡X°t sW$³s_]ÛÝÈuõjb1›EDC ø7ˆ ÿTÏ\Å‘;¨2w ¤×ëåÐÁƒXÌfââ1)ù»9)0´`X¢ðGYYYT­Z%ˆÒ):¹"#;;û¼ÿþ‹*2rÍUÌfs ðTU%55•%Ëþa麸<Õ«V SÛÔ«“DˆÕ·6:ø˜,Š"û–6•¤\Ó8#Pòº®¡ë¹Ómt$d ‘^¤¿ éUÕ Ïb«T¦|¹Hþœµ˜ô#™L_¸šÊ•Ê‘W ‹ÅR*C@p…‹ŒÜ©ŸºŽá¾¶Ã÷òx<ìØ±[X˜Ï˜ÌdÊFÑ‚¢(T·;0¡T!–|"Æãñ“sþ¼¨"Ãëõâñx0[ÌHHè†Nff&[·neÓ¶}¸51•ËU–ÈÈpYFÓC÷E2d I3%ÃgÊ¢ƒ,çÕ€a€¦kH€nøñêþÉt/†lB2Dz‘þÂ¥÷êºï/ $CBÓ5ÊØÃ©R¡fEáPúqþY³…ê±U1™L¥oÁ‰®ë¾1ý Vå¾rÇ_ȲLhh(‡ƒ=»wc³…R.º²$±ÈÉÉaþüùtîܹб<O‘^"Ó§O§]»v„„„Ž„H¾µ0<^ïù_mù¢¶p’$át:±Ùl’Á©S§8åôÍÁuœÒ¨\!Š å")c·ã8噓ã›&£È€¡ƒŒ„H²‚¬x5_è:°¬©ÿ‰R3@÷zÑrCÝÈŠ"‰ô"ý…Kïõz wæÉ¦M›øüóÏ í÷øñã…>s8E~îvç(mذ 6ðÐC Ïr§ÏšÍæ+[dä®–û¯®ëx½^BBBU ÂBC·Ù°‡…a³Ù°Z¬˜-&ßl$Û7ØÎ/6ßà“"#É’¯O]óõ¥k†o€WÓÐ4Ãð)H“"Ò‹ô.½¢˜ÁÐÑ ¯GÃb±à6ç`r)h^/n·‡H»EQ0›ÌBdÿ‚î’Ü1^¹ÇsE†nè(Š¡¡¡˜Íæ@tÓ0 5jÄsÏ=ǤI“Ø»wo`¿‹¥Èù¢>Ï߯ÄÇÇÓ»woâââ žI’tAƈ]ôHFn4Ãl6ûÂÒQQQÍ:„5ÄJHˆ•Ðl¶l¡á˜Ì¾F]òÙ—$ Eö-b¢È&_co–0üë‹x5_ÿ¹Ç«ú Ï÷™È’¯°Ez‘þB¥—dÅ?¨YC×t\®Ì& C7QUBCTä2!ØÂlŸ¢»D ¸ºE†lÈè’^@<膎¢)¨†ê[€Rõ-Ë;ûR"/ÚqÍ5×0|øpV¯^ÍäÉ“q8E ‚܇ø¢D†Ýn§W¯^\ýõ(ŠXƒ#w!.I’®üHF®ÈPL¾n]× #>>ž»öp"óÊ•Ål1a Åf Åb±`2›@ÝYñE5ÌVÉý´¨<¯×wCм4Í@÷¯{à‹‚HÈŠ"Ò‹ô,½â›‚†×ãñ}×gÙîr§z•hÂÃÂ1™M§@põ’_\È’(#oµMÇCŽ+‡š5k"¹ÑŽÜ® Ã0hÕª×_=Ó¦M+RØl¶"?ïÔ©]ºt!444Ðæä·lÏuT½jºKò/+.Ë2 4`×®]ìOM#í`å¢Êú"&³Ù„ÙbB–|ßWdE‘‘ Å¿h‰$¢@îx—ÀAÍÐÑüÓrdYFBéEú –>wÅ^M×ð(fdÜ9.I"óÈ!ì¡2‰ q”)S“"ºJ‚KwÉé‚#wꨪª¸Ýn¢££©Q³F¡}nWF.V«•¾}ûùpb·Û‹¼™ûýüK’ÖïÀ@öÊÈ’|åw—(Š‚¬È¾P,!á ÏDEEѪU+,X@úáý¬Ÿ»½›–óÝûÏ2êëÙÌøú9bbbˆ‰ïÁäeû0¼G˜0f8ýoïÉçs÷qŒ¯_ÌÀ·óäû È1 æ¾s Oþ˜Æÿ}Ž˜¤Yy0‡´õ¿Ãô­ÇÄÙ"Áå*24Õ÷oDThÑ™  ¢Uç."ÜÅI›X¾x''\P­Ù}Œ¸·"«6@5 Bƒ»øõíû ´#S—mâÞV•9ºo /¼=_zMáøcÂ;4ÖñÄ-Yv¨ w?ÚŸ9+W‘–Rý_C+ó^V&Gn¼ç]Xdú¼ü¶¬}Ÿ†U¬œÌÜ Àáã9âlàr¹„š‹žÔb¨'Ùæð`’,ÔlÙÞÿÞ·Ýäï]1I`²„.AÙ6$ÆFj I×~¼Üª,M†ÿʳw´áúÖwóõŸï0oÕ> „n‘æ|G´VÆ(ˆ°èJT³)DDGa·c–$’Ú gýÚõÜ×¼²8[@ ¸l#8py¼En—,áÔ²ûnúÞRå)WãFºEšq€ì†Ë(>‡§Ô™¢\…rbz­@ —³È(S.€}{úoçQ3S™˜©R­u3*ÙJ·Ï°È’¿cS „P¡@ ¸ºDFì R9”™~ÍŽãz¡í+§~ ÀÀZaË9PüY²øÂÙ¿ê?>R4º#‰™*IUÊä*òE2ò¦¥äŸ f)Øãv©âLàr’©2Cú\³éÐî=vwû6*ë§¼Cß‹hôè—ômæÿàõŽI,Y½“}ɳ¹yÈxpLbú’x ÷ýØ6'ocÖo‹pr¸ÂŒ‰ó8ì6À8É_>åŸ¢Û •‘,¢-2ß¿òëS²â·§yòÇ4œG“ÙrÀÈç߫װsç?ü1o7û—}AbRÍÝ'Î@ .W‘uMv¬™Å³7ÿÈMõiñà@bbèúøÞþq“ŸëHˆ?Š‘Ø¢Ý"ÍkÑ¢E‰éœŽ,œª0QôàJCÅqÒ‹ÍnCACC)еáv9ЕpB-.&<Ò‚­·üÂÈîÕò¥+ˆWu‘£)„‡Zðª^LºG4œ'ÝXÃóÒ¹]*ÖP‹8[@ 8.©AšÍI‰ã;% v{î ^)$¬¡öÁåeGÚQ®É—î´m %<ðþô"P°…ÛN;†@ œ)WÕ»¡²gõ4^Z|ŒeïOdYr*9ÂlM ‚K†éjù!†æâXNe~ýýwLxÉ>tORUBL¢’@ "ãL\ߪµ¨Q@ .dQ@ „È@ D†@ !2@ „È@ D†@ !2@ „È@ D†@ !2@ „È@ D†@ !2@ „È@pYsYZ½«ª‹Å„WU‘,QOÁeÍ¡]›PªÔ¦¢Ítuý0#›­[2IªY’.ûìæ¶™²æECÁ¤HâäœÛ·oÇãñINN^¯I’°Z­˜ÍfL&f³9ð^Q4MÃívy‰ CeÛê¬Ûo¥S›ˆ4ù.†{ÿ¤Nç,Yü(cÚv óoëéV#¢äÝy0õ‡Ÿ9Õ‚ûº5:ÿ ‚q’…?O`c¶ŽE²ÓáÎ;I,k>/»N[?›‰‹öÐî®~Ô¯rŽù<ÆŒï~e{–™¶½ûÒ jÈ¥=cK(7wƾÿq^kaUoàî®®ˆÆürçLÊ5mý4&.:@Õº­¸½}Ý3õšc MÚtâÛÅÛ‰,³ïœCĵ¸ýæšçü€p®y;Wö/ÿŠŽCœ¬[ó¦Ô¿ùöÏÕÔ¾é.niXù’ÖYÑך‹Ÿû5%µÿô’'ðÀ¯µ™ÿIOBÄõ$8E¡J•*T­ZY–ñx<8Nrrre9 0r_²"£k:.— UU íï’u—Zý=í{`ÊòxŒ¼Ï­öJ>õcµSËn!øm\ãÀ¶õìI?…¤Xñ¦ÿÌû?îÄä©äýf5Yr0ç¬òl‹ªL%k:#_Ž­GÏugë7í!Ç0ΤiäÝd•xç푤œpŸû=]Sˆˆ aÎû¯²ÿTÉû+)ïV}OL|º$Tãã9XðÍ#4ìÑ“ž·`iÊ©s*7$åcbQ²ðÎAêNpfœA¹šÃ#ØþùhF~¾ w1ç®f²q}2oáí[猧Z×q´ˆ·!™LìûöF~¶®Ø} ¥É[þ›ìöõ›HwxÏê:,J°O|êžùà~Ê›%LV;ß}ÀÔ­™A#gÝÆ©³3ic&–Gw¦Ó¸U !0g%2dY [˜råʉÉdÂd2!Ë2ŠIAQLŠ/š¡(E?\2‘‘y`=ÕºŽç۷良9ïB0ÛËÓFÞ‡a±S)!„SÅ´é»þaô †4kß•_6)‚[û¼’O˜x\.´BÑŽ,VÏÁéQq©¾ ÙR8MnéÆýÐ-Ò\@ü8Ó×ѵSk®©óóÖ¥à)¡!8=ïåkÝÄ[­£‘LÖËÍ«ª¨ª7H;AónÐïÖò¥ª‡’ò]­ ¤ulôíêU£Æ÷1¤A*{•F$”·|s¹pºNË[r°FפG¯^ÜÛ·™)ÅŸ†W-R%Ÿ·€‹WEU‹»Áºpq>]4TU-ù؆Š+ßyQÚr(wMKžÿ,…¾gxO²vÞÏt«ÕÎ];pô´kGw§ðñËSyþñ› ‘$,‘5¹ÔÝ„•-é¡tu,o…v&cïíNãÚq|2éoŽ»Ïì:<#›§óþÉÞÜÝ<{•Ü÷Zd«ï:uºÔ"~SÉmL^»¢ØG°:+mã>àAR$ðd“%î—‚³ WDH’H¾ÿ!Ër «ÄjµbµX±X,˜ÌyÝ'—•ÈPhÔúš"ÂZ÷ïGY«‰òm†rmå‚7²Ìý;¸>Ûôæ/ýn¾ù}O·À£©dnZÍ÷㇟”DõÚO²f¿ï %ëÀfæÌ˜Å“KfÏdéâÅÌ·ˆYtw /6JdȰ§‰K ©îÞzs0‰II´üÙù.h]Uqxõy ¿…s&1¼ËAèÖ‚økÿËâ­©…n Åç]CŽTغf>Ÿ¾2˜˜˜^xÿ8òže‡60zP}âHHˆ£ÿ[¿pÈ‘—¯ƒ›fól¯ZÄÄ÷à£'1ñ1ÌÀ‰½sè\ó6ú÷Lâ3ö‚‘ʨ»z1pàíô=k\Ç y·U¨G¿[ËÓ}ÀÔªT–ªµ›ró ͹鮎T¶Iþp £Õ'1)‰IqÜúòDÒœÆi7êÂå–¦s#:ÆôOŸ#6.„„bê¾À’GÏËÍ{ñgÐð¶Œ;Ú¿ÿX>›±%¯ÞŒlæ|ó<Õ’¨á?Ÿ–ì<†Ê¬qC¹sÀ@bê¿ÁAÿÍlǬÿ߃ÎudéþâŸdsÒ×ðpƒÛ8 Ã>]â;žáâ·×îæÎ·Óô4r /;–O¤KB< T‰aü_ë}O²†Ê¼†߃Q_/`ËÊ߉‰M )!Žæî+U¹º2Ó"§ IDAT¶óÍè!¾smìWü<ñ/Â" F’—ÿN×uèþÀ34x|³—m"!¬àõºûï˜b{¶µË䕬Ç`ÿ¼©üðÍ8º$T㎇FñO¾:+©NƒåmÉ·ÏÓâÁt®y‹÷«xÒ—ro]ßùýãJƒw-à“‘óÆ“wS/1–of¬)} Ö†äeò$ÓÞC¿QR)ßCN8«gþÊ+wÔ¦FRÝßúLýkcŽlúƒÎ5}už˜”DÇa£ñÐuÔHJ`̤õÚŠ¢ê¬TmŒd¡Î#SÖª™Ð“αáâŽ)8»‡®|ot]ç¤ã$‡]×ÑuÃ0Ðu_{.*R¡w =ÎÌOñTß&dØÅÁl™ Dzt ­ZÖçÀüq´»ãiú=ƒ-ÉÉ,™ñSžìÎð @²ÐðΙñm7>~é>n鿊ßf/à×/Þ¦v…’£ašc;µìÈϧÚ2kÁnM8ÆÓb÷‹;poíZtèû ý>ûƒuÉ»õä½Ô©Vö4˜Æ·Ã¿bô‡·b/ð°`×l~O¯Æ»sç1¸­—Þm2cë±ë´¤¼5¼µ?6-âPƒÛ©_ÅŒ¹BmZ×ßÍö /ÑáºB£ãèÖïYöïÙÂÌ_Ƴéù;¨ËO‹w—² ñqbßb^Zu=¶O,T~)óVÐü…™¬Z2‰ª? cÁöc>q¤)W³C‡ÚHV†1söOÔ˜ý9Žfãøë›ç7f#ί¥„ëÔ÷fw?Æ •B¨xÝmôi'î–‚3ov ü磪ª>|˜Ãééœü?{çEþñ÷ÌlÉ&ÙB'¡„ÞA¤ ¢D½OQQNÅ;EE°¡ž]QO–ņ"J¢ˆt= Y²!›ìNùý1k @Àçý"/Ý™g¿ÏìÌ3Ï÷™ç““C  77—£G …ÐuÝþ|I™‘3ý‚þÌšöc&¦0ajl™×Óƒ9ØeÏç{«$YÔý0T»—;nèN¬¢0dä¿yè¦,BA­Ö—r«&¤|6“¡£ï¥wrá‚Èú ‘Щ·iÂæ¸ä_×кacÚ·ôÔËž(wGÆ_ÍžªÈøm;Ù¹:zTé¶ý÷¿·„}0æµÙ¤uèÉ/;GÓx÷tÖÆÿ“i· VQ ¾·?þ!_v9?¥ÞÄ‘W^fÈ3s5¨Éæ’1· ¡ðôÉÅ7ü“ë^ø–ŸSÒéT»*¿};‡!“> sݘRm[f¯g]K3h±cƒ­Mø®pçZfùBŒÊßÏü/f¢»¢IÏ AÆ×dæÞFlT%r 9»øðÓƒL[p?íëÙþê~õ=¼ðýG|¹2>c+u,ÆVO¦ºæ`âÄ›i^'«z_zy–…3/ûùö“ƒÐ ¶®œÇ/9N+Àû?lçÕ.aT-x#Ùµð.úܧ²bÝ«è{‚Ü<¢ ‘%Í…+:÷¦ü†7"ÀûîàÛËÞæ‹ûâX¨ÝÈsª2ÿæ÷éöÈ,†^ÜÒ¶µu?Þšú o›ÁÃCÛR³Fm\¹µ¡Ú½¬YyŸ=娢q™¾÷ö¥°0ê6LfOÇòÕÑ]Üò¥}²ÈËIgaŽÞTIˆÃëq¹ýk>ç=ëN~ëxâÔ\.Ô~’ÿu‘ŠBÓäñLÏùÿß2.ùwƒ}Z7á£m‹®Ñ”;Þ}‚)ƒ¦²ßÑÊ_’ÅŒèylÌU§‡*Õªâ ?]q(Ýt–ábO=ý0å1zŽ{ó¤ÌÊ¡çøI\Ö¾Pa7×á³uûÚ&¡”sLÉIU¹°ÎÅ´j‘L÷61Tïݶñ±õ*é¹ÁUñsŒ œ*TUE! ²gÏ6nÜHFFGŽ!''‡ˆˆªT©Bƒ hÛ¶-UªTAÓ4,¬³#ÈÐs°áçux¼î2¯çŠkÉ„O6qOÚz¾úïDÚßµ”V·LàÙ¿ ¢uƒjá8š6à÷­*Zát°Sö:Eÿ(3wiY(®8bóË „Þò±; ¯CEq.rñíÛÌüOÞåÏN£^ÿûø|Áj.h\3¼fl©¶Dzއ¢¹‰w…÷òƒÖ´ð·A¼Ká÷dêvšrŠvhv«îzŒ~e4=F@›W’øç‚ž,{®eÙl·X~“›ŸÃÈAv´¥ÎF^ñ‡=Îth]UG· ñïðõÍÑÔŒ¤Ôq;¶´ˆs½a°6hât^êôj'M}JÛMN>xk$QÍ[Öúpðh™F¡ã ï€Ö$Öò’²p:2kV’ê‚É€û.çõO¾¡Õæ_ p˜¹s¾àÓWòvØR÷•ÔŽQŽ;™5»ß °þ“9Ìjì¦ý_ûSÍaÛqb‰ŽÃf.Á°Ù !š6 ÎQÒýoß:dê.t-Í6€„V˜Üÿiýx>Ãhuët?Ee2Y±èk®½íapvàÅ÷>cc×6ĸìm”åw˜·£§îcÞº¶EŽi÷1ëj6»ËÌ¥cŒ Qp^ÉÏ7P= ôò€C)Ùg¥ŸcÊ>MX±ßŠðgÁ4M ]gÓ¦M,ùq9?¯KÁávGí!ÚÏþŒÝlݶ””zôèAÆ ‹Íhœñé’ÈmÿÖL¦oÄòM‡Ê½~BR+n™0”õ«x¨].ý{´çÅEi¤gd¹=“#û,|8# ?Ùá)NÕ“@Çøv¤ 7×Oêº%¼òØ lÌq8#Ãþlø~(; ' YY`ñù|ø2°;× ý@Ù>GrurRgÓªS~u_Ì’_·²ôíûèXÄ¿8ÛÍ £¦ÉÄÛ&³xã.22Ò˜÷þóLÉhAãZ‘4èt#ìÇ;³~!;_'ψÙSa¡v#íêW§ñem˜ùÐdý¶¿ÿ?~üžØå'à;VúÕ Ç_x°ÅG\wã8îýÏê†ïúJ³Ý2üì[“ö}{8ª[èÁef_z!Ë¢JR ýÌ¡@,m:v¥Ó…mˆ#¯?œGVÇí÷ •Ïç'=<þ™¾²2}äéŽØD®çåáç>&-+]°iùtFOÝGÏæÕý(r·s_ß^ôìÕƒùeŸ¢ |d¦æ‘žže_\|é,ôg’éGuÅѾu4[…¨ÓìºuëL½N6/þ’_vÛS5M»_Üçï㫘'Y8ëyÆþ'#.§¦» ýJ5?t9ÝõO®ü¿y¼ûîý×ÛÜÖ¿%šMÛ¡W°øÉWX¼éA]'s÷ÏL¾yùì1 W{PÒ¸Öiu ìŸÀ;³~á°ßOêoß0vÌ(ffÁoEqxhÔ¾o¬Oå—%_¹ù:w¼ƒGí}Þ<Ÿg³¯áÚ.‰'eÒ÷=cyoÖ/¤ge²mÕç xàÆÜÓ…¨¸’}ZÛP¢üàXöÄßýì.žÝ °ô=<Ð¥#cgfòÙ¼¤îø‚¡·-0Êrƒ§>L§>¡I¼zÒwóeæP¶}ìcÈÈ<̾C酘şcŽ’‘‘Yø¼âóÛnð{2²óKôYYÏ1¥^@*ø[þ\Ó%™™™Ì™óŸÎ[Åo;c(.¼1^ªT©B•굨Y¯1î˜ê¤îÚË‚ HMM-¶ˆ[±¬Ê?g6cÆŒ“ÞëÞ½{‰ëlüì^Ï»“W‡7«Ü€èAL‡ %wuèÍ,_ˆ&7ü—9O6gLû^Ìò…è4ö#>ûGv®šÎECî/XÿÞ‰ïrËÐ&¥ù´L¶Y‡™Ô©3ïøˆi»°—«B¿C ÈÏXAÃv×ðùêT:Ö,\-¿oÕ;tò(ï.ÝBÓ”é~ó'}Qç˜k»…èÖûvžž>—¸Õ·3ê­ž,_2’÷/ëËÊ¡o2©Å|ë3O…Î1'R¡ßŠð§b×®]¬[·ž·ßûšíYy4nHb­ªT«G\¬—ؘ(<8÷’ë;DëV-èÙ³g‘O˜üaAƺÏîæö¹1wʰŠÆÎ@¤¦É3Áuvµô ¸=EÙfëÏÅ@Ãë=y>9?à'„›è¢æÐ­<Ò¡;ͧ,çÆNÕOƒå~.·ëÔ§`ó~‚:¸=Ѹ…—•æêñ¹Ì[ù_šÇ«§eß!KÃy’OB?†3š‡B®ßÛë-×1•íóçE³‚ør,âN˜B´ô9ý´Œ« p4ß""ÚSΦOGøöÃy´z ‰‘J)c@qFœä³Ò|ZšmGRfÓràw,^ýÂIu•!ïàÏÌX 7^Ý¡R熳õsº+¹OJJ Ó¦ÍäO¢~“º4®W‡êUãH¨OÕ„Xb¼Qx<‘¸öùhý¯+‰÷ºéÕ«‰‰‰'mӺ?»ïIóËݽ!‡ ÏYê`Åá¢øÎÌ‘^o±ëº=^N¬rÉÏØÀ«¯L'mïL>=”O§e[Ö±Úi誩á-Á¶ÊRÔw³Ïæl]Í qoœ¶“f±ûœoAý@d¾L\xÅEœ·¨ãÁÃéVÕåÁëªÈAKÿ¿-ãØy*4®ÅÙ¶sùt^›½žýŸ|9+×ÞOr·¤S6&5:ð׫ÏÓsÌø­ç>ùùù¬ùu;u’krÛ H¨O–ÏOn^o41^/ÑÑ‘x<‘¨ $&Õ'}ßv|>ßÙdTi<€ ?/g¿_¥ºK{ºpFV¡sÏž´söá꿆P=µQϧ.€Š‡AþÄ qõŸ‚èšÍ¸ìâ\}ûò÷P*µ¤„üV„S‹Z[÷gsרèra;šFÎÑ\6¥ì$**oL4±11x<‘85«qv¥¬C׋.vþCK‹ck$[Cœz:Q#kqQïZ2ÂyAÕm ?å-Âi 2òPhÕ4™(Ó4‰ôDአÒã&*ƒÇí&:ÒîZ£Äνòü’pÆ)).;÷ö-‚ €Ý'#ÒëÆ…Ãé@7L\(¸#\¸\\nN—ƒO.—Ë2°,Ëî¯QÔöÎÖ/jæîgñ¬™|»lû¤qúÈ=¸–7^z‘·Þû’CgÑcd[ç=¹âº›©³î;ä–¼oAáAUí)EUPT ÅЦ€¢ iN·†ª)¨;Œ(nÊ䬬²³ôC,ý-›¿¿¡¸lÕËÉ÷ñá¼5¶êešBƒá¹k?fZ•;¹iD=¬ÁƒLžÁÓÕ×Óøc¼ùÕ˜óGðñ»é^¯UÉêªÎè/¾¤Ê×qÃ¥ŸÐwô+Ì_p#—m!Ö­±Íÿè9äAÞøìGú^P›ì´•Ü×0»‚ßðÔ5õùàîÞ<¼ðbÞûøkªêÛyø¦[X4ùß‚v8Éã«ÇûpçÇ]xæ|ÙÉÄþŽ!šù‹+'OãéÎ-påná–ÞÃXÚ{#—7Ž>YÝQ‰';jµê 8Á20\µyï³ï¸ ymÒ–¾Ã·½ÏE?³…³ÊHdí.Ü}sá÷íXAB÷çèpœªhBë›ØóÓqѬž;›ùqµøÏ=_óâO¯ò΢UT‹Tp¢Ô ,ÝJBAÀA½øÄE–¼oAá 2T4UÃ4AÕBhØÓ#NÍ®ÕP,Ms )%Ï5œuAFVêOü÷Õ;˜u´ wW9vJlW²êeÍj5ôP½cGš:sÀÓ Û5Æ¿·#sýeøšŠ‹šIMHJˆ`ÔkÓyd°”4kÜÚ–ýþêUpvÀ·ÿ7>›±Œˆ(¯CåÃÉ¿p_Çý<<+ÏW?nE܆isuZZJrÝxŒœ¼ùþ>>Zò4=êDMxû»whÜ{¿Ïl(Ni‹_¤ËË©v‹ô  –É)MA‚@/Ÿˆ•aÙgïPüA¨VÉÔ€Ãé%35ˆþ¾ûr GN"]S¯+ÝšÛÂR1nÜ'UàÐ<ÔL²}wÓ´µáLÑq¯;™7–Þ%¿bA„³%\ka¡*ªª†ZEÁá°¯«ªVò„ÈY7]rÔw€µß†ˆDßúR©Æ€û.gê'ßðí׿@à;æÎù‚i¯¤KÃ~WÔ´ C·§ #¬êXf ò}:[7:iI0× ^Ÿ~4¯[‹úõëS³ZCF~øs¦õÃaØû‹>NYRsDž „r}¬ šÄºus¸í‚ ‡zÖ/\Øçz’†<Á†­;øé㥌©YH´$uÇ­sŸbð?~âoÏ-bÛŽ¬]ö!èÙ8Nˆ­ò|ûÙ‘²=³Ë甼4²u[66.¯3‹Ûn»“ômŸÊ¡U׋éÑ} ÿùfµ”Ý<}×;¤1öJ{,WØvA¡B™ E!h(8*ŠŠ]üéTP {†Ä:·‚ŒÄöWñÁÚô²>ç×…/(%©^þ®¨¹/ÃGȰ ð™9:8mEÕÒ´ô ÙG2ÈLÍ##〭ê (Úö»Š]?nCIhD·nÝhÛ"Új¾ø~QIíUËÃèIï²uïAö§®æékî‡-nQ½ cêDò§§²ã`‡næµñwàËÎEØÅ‰µªŸ ˾᥽¹dge”AÝ1„òCd#jT‹'˜µ‡ï?z€ôŒãžÌ±‚|÷Òzöº„O7)³?÷¸‘^Á·1qûr"èÒ»[6O?Ú7ÇÒsÈÈÈ$/#ƒ#~î¸8ò},ž? _¸?K~ €/#Ãù‡ÉÎÌÄïÏ-ßAQAÛA„ æ1øý²ia¡¨*MCQ,Ó>4 œšvnª«½/ˆEq6>*© cêDÒµGK’[´§­Keø¥-Ь ‹^ʳiGù÷mos@­ÎÀ8'¯N_™Ð†e“®eá¶’ï€ýióiѪ+Ϧå_W_D‹V­hÙó‚»ñÆ—ÞÇôI‰ îÖšÄÄDš¶êÄ„…~ú\Ú —³ÌùšÁÊë\Ú¹/H“‡þ `O‡(Õ¸ë«Oh?ïQzvhM›}Xt0ß1ê±¹P«-SèÉõ=ÛаI[˜}ˆ1×w徫/âÃåûÃeðËóĽhÒ¤9=úß@°^Kjy4ìq;×éÿ¡Só†´ìp[cz1¤õR÷Ïî\Û~3xˆ•_¦CùkÏÄ2ûÂ×’·}ÅÅ›'ЩyCiÕíz.> 6}õ$Ã_Ä7“®¥eóV´lÞ„V³¯M_â\v€0wò%´é| ¿]ÍÛqÙsÊÕ£¢¶ ‚ ¼+Š^XöŸ©˜–Åñ§nÀ Qr†?L…µä;×ÿwcg\ÿ˜Ë ·Ä®¬êeeù]Òíqár”PëaíᦶãyêçwH:NV=ן‹RŒ¢f‰*ªÇe\ŠVwü]5ëäbÏœÔy4ëq ¦.çÖ‹+&(•ë÷BÃãöœÑΜ§ÂvA¡t6lØÀCÏýÉÿ¾‡Õª ¦a²-uUâ㈉ñCtt4ÑÑQäæxvÒ8 @Ë–-O¾Q=;ó4.šökð«;òá­ï0ë±~ª¡•U½¬|–¥dåJÿ…ן›Jºy€…‡¿ã…w䙑…í/¿ŠêICS¬ºcÉ*¨Y»¡Ú½ êVñL@¤7î9N…í‚ BÙ1 ûÊkg3 ÃÀ2-°ÿaš¦YrŸŒ³T(B£ÛÍïòÓÅ»1"«WZ–üèîy4ívKñðeÙÏ/P7²òꤊ;žö={’‡“>}¯;kTO“:ÞÊž5çæÁ~.Û.‚p.bš&¦i`Z&†!Cǰ Ë$¤1ôˆ”ry;{Õ¨‰ ’MEÕíËž={Έ٪«:õî#G¨ ‚pÎb™v¦Â2-L]Ç2LLÝÄ2MLÓÄ0,,ŒPÉ5ª ¥ ‚ Çc`bYºiaXºiÚ†eÙˆa™„ S‚ ¡ìøÒÖòÉGŸ²9£°HJ(à#eÝrVnJ¯Ðv³3÷±zÉbROØ.V€•s?ãëï×’+ ¬‚ g–…a˜`ÙS'†n„ë2,tÃÄ0t ]/µ&C‚ ¡3w+£ûâÞÇ$;ÿX ,'u6 ·¢Wÿkù`Mf¹ãá¥oÝD‹¶¸ê†á¬?|¢Šl}[~bÔÍWðâœíâA„³áz`š (X–aWy*`ê–ebq¬Wi¨J!àß»‰…Fo–ýúêD¼•Ô“ ›6ñÙ³—T`«nx•Í[×2±g•“+±\uÏd¾{ùj–ÿ¶CÜ ‚pV * ªTMµ»‰káöâ hª-ï®i%—v:d…‚ë½Ãù{òá„÷£‰õB´;òÊ¿ÝoXœ%”!+NØýË^ò-‹È³àiA„?u€îî©Xš¢ 94TMáiv ¡i(¨8Î5íá<¨ŒPA+ô¢0¨\ÍD¨„õõpgU9 Aþx4EµuKÂ÷|Õ3¬g¢© X i*J)ϰÊ9]+ÀÏsÞgÔ•÷ÐjØ jyμ õÚ"séXxf*Û³BâA„?ò¦3](ª‚¢j(P4MÓpº5TMAuH&C(• vïdaŽAdO±ÍÏ´#VƒCi©ìHI% ™ü IDATÝ_ôsÓötIÑMà]‘¶4üçnÄ—{re†¨° ‚ œÉ CES5TŪ)hhhІSs ©Ë®ÇДsP M8Ã(±\1òQ6,x•S¦³7¿ð´†¥8â÷‘‘‘I(;‹#~9„™»ûúö¢g¯8aý<¿Ÿ/ŸiíË Ûç/P—ýmK?¦j·'Ùºþ :Ô‰(lŸ¨° ‚ œé CXæTŸªjwøTaí.µ”š )üŽR'èÙ'$ö¯™F§!†_-â›I0êõù<2¨YÁg|»6²0ÇàÆÉ_Óºªó¸!Àדúò©a5Ù/â_ÀŒ)t;.˜p8½XJÑ¢0¢Â*‚pæ3vR[AUE‡¦ât*(Š^nI!”=“œ\" µ;ÞÊž=·–¸ZʯóÁÓýÛœ¹xúÌ*†>SÒÚY™»©{AÜELÕäîÛÄ{‡ò™0u0UäÉA„ÓÓ©P ëna¡¨*Žð'– Š¢ iàÔdºD(#Þ¤6Œªº‘~í0kk9¦%¬¶®fи»i_ÎCÊJgRÇf {d!Cz4,²bCTXAÎp&CQø]}Õ²,LÝÀ´,ŽŸé6 ºd2„2F®ŽDÆ-þ‰a»S-1ª+zôèO ªÐN«0ò³o®%\;¾Èˆ « ™Å0í6Ÿ†iwü4L Ó°[놉®Ûš%–©H!”#zõ$ФYÂÜ£Fõ¤FT—¡A8{‚Œp†Â!¬°n‰eZ`ÿÃ4-Ñ.΂Aû€ÕƒÁ’[‡[Gظ~G¡§O,C'¨ë€Q°òðû>-CG7J.RÚ—²Žƒ¹ú)Û· ¹ˆiš˜¦i™„ Ã2låU=ˆ¡‡ì@¤”29 2„ÓNvê—$·Kjz w_ДÙ%Ô{ì^þ.ý†„ï¸ëùæÙ÷Ñkôìúä–#Ùq´G­èȳóRIYø =ïúœ¼b} ÿ:õêÏúù§fß‚ ç(–ig*,ÓÂÔu,ÃÄÔM,Ó´UY Ë#¤K!”!jÍßÅSÃZ˜˜ÈóߦqñÄÄD†\s/+÷-×¶ÝÞš8Ü^šy]8‹=ª3ýÞ7ûÊ_©æ<µO‘´oX 3÷ z4!¢˜'T6ΛBÝ+_¦{ƒH9 AøSc`bYºiaXºiÚ†eÙˆa™„ S‚ ¡l‡Ô†ßŽòÁìÅü¥kÒIKkµÎÂÙï²jÅ'>Z¾i§·½ÔX./5“#(nõCëgóRÎP®?á)wd êw®Gl”âºR­œ1@~ZÈn‡:‚¯„ ëõñ_óà=½ !•Ý· ¹™Ê°‹<±ì©C7Âuºab:†®—Z“!…ŸÂ1\½iÔ´ÕÝ'ßé;=q4lÞ”qΊl˜ž·Œ Þí Z¯;©S«ˆ+µ•Ã7OMfÄ“ŸQó„,F&½¸/ž„jLiQ. -[#.y²£‹üØöÿÇ¬È Lnsêö-‚pŽbš&( –©ÛUž ˜ºe™XkÁeYÒŒK(º¸‹ lM¿n–{›ª;‘‘cíìÄ¥¿½ÈÏdï\Ì¿W]Èâ·ž´,*©;ÃÃÉ•[ÿ^³œ{×èzýÝöÿÖ¼ŠŠú^ú~Þà]ž™²ï S)•Û· ¹‹ª€¥:P5Ëî&®…Û‹‡•XUÕÖ/‘ C8»±‚ü0å1zŽ{“ä¨3ßÑsÿšÏyϺ“ß:V_‚ j¸»§bYhŠ‚æÐP5 ‡¦Ù†¦¡ âíáÌ`p(m79ùà­‘D5oÙ­¼ýË=uóÖµ=ãûÆ:Ì'÷¼ÄØçW¸eyžo?û2rpykX#FAÎy4EµÒ p¨œa=MUÀMSQJy†U ?…SBI*¬¥?N}˜N|B“xõ ïožÏ³Ù×pm— ¶,…XAÎÇL†jŠª ¨Š»€^QÐ4 §[CÕT‡d2„S—¬(–bUXK!?c5#^ÚÅç«/D« YÝ7Ö¦ßö(#žœEwŲ¢+Âùd¨hª†i‚ª…ÐÐÐ §æ@S(–]¡)šBÙqºŠ_¦85¼ÅD­Åª°–v7<ùò—\P³âÏmTtßõoŸÈÀ¾ +¼oQˆáüD±§KT Õ|ªªÝáSQp8ìðA-¥&C¦K„p–B'+g>ƒ†^Í‹vž´xÏš\Ù´³|!Nê®] ÖˆøëÕ*œÅ¨”¬Kÿ¿%1²âÁ(Ä ‚p¾f2…p ¡àp¨(*84§SAQ,ìû*y„U(ËåIâÍï  [xâO–+«Ñ¬7o|ÿù†‹ÚõO(n¬Œ k¥ƒí?p߈B¬ çiC¡@ÖÝÂBQUá'N,Ó>4 œšL—e¼X'6hTìb§'º dœAþ 7žŠb‡–ÝpËÔ LËâøÞ[†AC´K„3„ ÔE@Lá\Ç0í6Ÿ†i·7L Ó°[놉nÌh™%O7K&C(„/m-ó~ÜFë¾iVõäÖŸûý†é‹Ò¨Ó²W÷iy¬– ðñˆ.Ìhû3ÿy Î3XôïaáÂä;éѧqŽòí;;s[7¦Ð¼3 ŠøÎ–žÃ†U+ؼ/‹¨Zmè×­I™kHB»R6qØÑˆNÍ‹nöÈÜÉŠUëHÏʧY÷~´®[¶^fà+—­`Ï"¹MW.h\­œ¾^ϲ5[ÈwUåÂÎ]HŠwŸÒqرúök éÒ¾^¡1«¬í‚ œæ #œ¡°õVX·ÄÀ2-°ÿašV©Ú%’ÉŽøs·2ºï î}üG²ó‹N9£cÙòö3Lz{ù'ô¬iê¡iõ˜pš­ìló0£§m®˜Íù»x袞Lør Óÿ1ŒwÍÀo•5›b°ô­›hѶWÝ0œõ‡óN`|Û¡ —™}éu­ÌFNêl4nE¯þ×òÁšÌ"?³sÕ‡4n{ºŽÌl?ùFY}µ‹ñÝ»2êõßÈËÞÌ KÚóÚü”2[ú¦/hÕõr¾Û~„´ù÷Òõ‚a¬Ë¢qµÑ3~¡çUåΧ—:V*k» gàz`š˜¦i™„ Ã2låU=ˆ¡‡ì@¤”Ó½d2„ü{7±ÐèͲõ/P·˜¾U]ă/ÝÈ ·]…#ÔR 0 Aëägd­\?š«bÏ—ìY1“éúõ¬|c"Õ ¢~»«Y™z%½“£Ê°¶F‡^eóMŸÜvÉÉ‹­_=5‚éÖ­¬Ø<®Ü½4¢’z²aÓ&¶|}'q}6ü¸ëº‡4ñS^¹¥K¹ž°É9¸÷Yùñ8j;:TõÑ÷‘ÕÜÒ»!‘eòv¬x‰N|‹cº‚5Œˆ½]™¶p;O mv ư‚Ì~íNêõÂr>V*k» §Ë´3–iaê:–abê&–iÚª¬†…e‚’š ¡Œ(çïñ@![xï™Q$&&2îÅwùxúWDÅ[~t÷<2doÏßyÒv·/ŸÎÉ hœœLû!÷òÏkšñêœTÌà!V,þže¿.gýòE,Y¶˜ùóç³.5«Ì²õ >aȸáÔv*8Z3yPu¬K+ówŽðÆí‰ÄYD8žwè7þ1u?ÿ›9š:n³ãM¬×K´;¾Èå»V~ÁÚØ1ŒÞK×˵m@ä÷ØLs-ÇÚþô 1ÁV¤¢¢9§l\³w~Ë_ßʇý‡£YÁSh» g˲ÐM òÐMÓþ3 ,Ë@ Ë$d˜de¼p!pÄœp·½…¿_Ô^ÂÜ ¸<ù0¯Ì>L„÷ØEÙS³Ë–-áÖ^é¬=TxÊ!mÕ;\|íý |ñVþ¼’·noÈ´9¤>Š•ïgë¦õlÝàpj*›6obÛ†õìÌ8ZæŸï`>ÑnGÁÅ2®†¨üß=TijÞÁ\{Šã¦KZ’˜XvCŸ'%#¿?V«È,ɆŸ¿ô¸°aõë×güÿ-(ó”Ddí6Œ‰þ”ëÆ¾Àÿþï%.½m&ϼ|q3†>Æâä‘7Þåµ§GðàšK¸å’äS3®Ö¦Þô Ͼ3ŒZ*™»N¥í‚ œ™T†]ä‰eOº®Ë°Ð ÃÐ1t½Ôš ™.À ðóܼðñ´ºîÿ¨å9. ±ôF=À† ÈUh<–¯Žîâ–/] UW,uëÆ’“täÞî¢^¦çÄYŒÔ€Ú—fþUÙŸ€æ­Å_nÖÚÛÉÍÁÈ¡+ýU\‘§.n޻垶ˆ«.ŒäÓÇ2ò™–Ì|Ù))lµ&x‡2wÁãÔ nbL¿aÌj»ŠáT/C'Ÿy:ÎÈJ·Gfqÿ-íÁŒgKW^\˜Â‡7¶*ó¸gÛ‘Û!ýÚÖ¡à³ïªÊН#BQÊh{%”uA8%¨ XªU³ìnâZ¸½xX‰UUmý’·!Ã( ÄrÅÈGÙ°à5VN™ÎÞã”Lë´ºöOàY¿pØï'õ·o;æ 3“ì }1ÈöerÄï#3û0¡ì,ûÿ}~ ÅCç[‡ñÅÃÿâ»ßv‘›ëg϶Ÿ¸¿m2O~›ZÈ„u+6‘‘›Kú¾ÍÌ|s2/K;þ¶½h¥SÅE‡AgæC“Ù˜‘Ïáí‹øçW‡ܹ^ሼ•Ö<¿Ÿ/ŸiíË Ûç'ŽÌcj5£­1Ÿ×ìE×°ü»ÿR·]t¡£$VKpÄï###³`\ráÚ ÅCç›nbå[³Øœ‘K c3Kædpiã Ïö¯ù”n=z1ü‰Ÿ0»cˆ‰«_³m_.X6þü ÉÑ…ÐÅŽ›‡½âÉØ¾“¬|‹`Î>¶¬Ê¦}Ørkq¶5¾ì1¶nÛÆÆõkùvêCP徜r á¢,¶WFYW„S`„»{* hŠ‚æÐP5 ‡¦Ù†¦¡ âÐD…U(k¬áp‚žq\R!¦A_~ô$½nÌ3Îôr+¬]6fõà‰&\| Ó3/î[È7“O?ÿú/}€/^~‹«t/Øæ_x“Û.­_ðºé¥£è6ií>º€ž×cÜ•UŽ]pJP:­ÑîÞ¹{>ýÚÙ"g¾ý=O[+V¥Õ ðõ¤¾ücê~ûõñ/`ÆŠºÕ‰À׆7g>G—]¸À;”/çîR’mû×L£ÓGïñÍ$õú|dçqêvý;ïÞs;}Ú5 Õßžg\Ûš…20)k~à©zÄ6êÅ”{çrEç¦áôR?>žÛ»àB^šmí¿D·þWÓ:<æM®Š©Ç鯔>®ÅÛæp¹p›æO¤ÿpÏ[] ú§”Åö +ë ‚pJÐÕÖ-Q, À¡:p†õL4U 4ME)åVŲ¬Jß&̘1ã¤÷ºwï.^:ÇÈNM‹Kßä»UŸÒâ„» p4ß""ÚS¡z{}‡;«¨õ òŠÓ‰ë„¦O9©óhÖã&L]έ'm»/S‹&Î{r3­•æêñ¹Ì[ùßò‹¨¡€Ÿ#¹ѱ±DTÀ¶Ò8êó‘‡FBœ÷„LÈ~žèÚ“z½ÀìÉWºŸ‰É Bl•Ø“üRºmÙ>?&.ââ"Ë5®e±­4J²½²>¡blذ‡žûO>t5ª'`Y¡ÉÖ»ˆ%ÆC|\,Ñ1ÑDy¢äøÏ“ã0`-[¶”L†P<Þ¤6Œªº‘~íðÆØ$öXêÌåÁëªDê­Ôõ5Üž¢;E”Eé4&®]••Ö7*|±rz¼TõPaÛJ#*.Ž¢ºOXF¬ ÁÃw\RìE<ÂGµM#&.®DÛŠײØVÅÚ~ |&BåPUMÕ0MPµš¢áÔhªŲë14EÒ„2¢8·ø'†í:LµÄ¨³Æ®J)žf•ÖөªºëñüÚç¥m¤ÏA(Ó1,ón¡á‚OUµ;|* ‡>¨R“!”ëâáI I3Q[AøS_ Âõ  ª ‡Š¢‚CSq:Å //¹âBr‘‚ ‚ BQ(u·°PTGø‰ËEQÐ4pjšŸ+ÈæUsùhæB|"7/‚P)l¡K[}Õ²,LÝÀ´,ŽTÄ0 hˆv‰ð'`ßêé3äVf-O#tBŒ‘¶êC®H®Kbb"‹vœÐ²Ü ðÙcILLdøØÉ,g€bæïâ©a-HLLäùoOVݽüu[×åš{Y¹·œV¹/ßIbb"ÝGþ÷$ÛÌü]Üß6™ÄÄÄ"5cJ£Äq©¤í¥Ëiµ]|*>ŸVz\ Ónói˜vkqô0 »Õ¸n˜èº­Yb™ŠÂùOfÚ¯Ô½r ï?{Õœ…z_ÚJÖÆŽaî’\X÷„G5½ïüœYScñ— 8Rniƒ ¿åƒÙ‹ùKד­Õn8 g¿ËªŸpø¨^îmgnþ‰V{…i¯!î„ÇgUW-øö{¦­ô¸á …ým¬°n‰eZ`ÿÃ4-Ñ.þh(\гQ‘=<N…„¦ hR¿v‘Ëc«×¦I^mû³yÓÕ›FMP½)x§'Ž†Í›20®â ¥.ìКz5ŠPrU\Ԭ݀ä5cÊHiãRiÛK—Óm»øT|*>­Ü¸˜¦‰i˜–‰aAÈÐ1,ÃV^ÕƒzÈDJñ…d2„󂬌ßP,½”˜½„eFåö_’R»eøu³ÂÛ6B¥}¯ÊÕ ”ôÕ+k{i ö§Óvñ©øT|Zñq±L;Sa™¦®c&¦nb™¦­ÊjXXféß[‚ áœ&èßÉÌ7ãºÇSh—+"‚p 00±, Ý´0, Ý4í?ÃÀ²ìİLBFÉÁL—ç4zî6ü¼O-ÅO¥©¬Vö§|:ÕFO§íÅ©°þÙÇE|*>=/|jÙEžXöÔ‰¡ẠÝ01 C×K­ÉL†pNY£-ãßšÉôñX¾éЩßA *«§‚Óª6zšm/N…õÏ>.âSñéùàSÓ4AQ°,îòTÀÔ ,ËÄâX ®ÒäÏ$ÈÎ â«¶ÁRJ¾»¨ÈŒeIJ¦å¸ *–Ó©6ZVÛÍ Ù^¼ ë© ¬ã">ŸŠOOŸOUTÕª©v7q-Ü^<¬Äªª¶~IIÈt‰p^``ñË¢µøohŠ·˜RI§§Vô:¹û6ñÞ¡|&LL•~ ÎÄß§†×Qt<Ÿòë|ðôcDÿ6%XWr‚ÓåTЬZ/³í”ßvK?Äâ·WÒä†)tnY¡q)Éö²‹øT|*>=]>òDát:Q E…èèh"=¢<‘DF¸ñDzˆˆˆ(=P‘Ë“p>P§uvs?Í[ÜËîÒ™V2¼‡aCïcÅî›üùî­1´×íEn·T%SC'+g>ƒ†^Í‹vž´xÏš\Ù´³|!‚'a¨Þ]¬Úh¾OçÃ\ÂÎàˆub“Ÿ=¼8j(½ïø ÍU~ÛK—Rl/U…µ”q)Ñö2Œ‹øT|*>=}>ÕM“²cµìzŒP(„iZC! Óž:1 ]–xnV,«òo3fÌ8é½îݻ˕O8£9˜Æ~¿Jý†µ ý ôàöíM'ßШQ·>1®Â?¶Ì´Tçé8#⩟Tµ|;µìÙ¹—€nቯCbÕÂw ¡@&ûd‘o¸¨]?‰¨r>àx_™GóP^4¨Yø^é¸}{«Õ¥f\ù _K—JÙ^ʸœnÛŧâSñiÅÆeÆ Ü÷Äÿñô#wP§V tÃ$ÒÙ´-•ø¸Xâbcˆ‰‰ÁëõâñxæçñêóOpÅWТE 2AA(š 6pÏÄÿòøØÛhP/ ÓÐ †L~Û¸…„*Uðz£‰‹%:*Šˆˆòƒù|ðöKôïߟfÍš´=©ÉA°%ޚʦm;©S»&¦a …ÈÍâÎÍCÓ44‡ Ð ƒôC‡ðx<8E‡dçVÍ«°f·›þƒ/>I? Ôå‚ Š¢P«Z}1¸X/ñ±^Žøâ÷Å¡ª€Ýj< ât8Ø™šB\\\±E Rø)œ”¤ÂZârQŬ˜í¢Š)>Ÿž—>Õ4ÖM’H٘ʔ>gú—óYµf#~þ£¹ääÅw$›¬,™™‡9°?š5k-A†pþR’ kÉËE³B¶‹*¦øT|z^úTUUºvhI×v 8î#ýp69¹¹ÍÍÃïÏ-hìLÝF¼7’ÄÄÄbƒ ™.Î JRa-ËrQÅ,¿í¢Š)>Ÿž>UU•Ú5«sÓuý™>g)û3’ã!ÂíÆír¢i–¡Ülâ½.Z¶hF:uˆŒŒ$ J!œŸdeü†¥Wxù™PP,îôtJÝŒí§DÓ}zÆE|*>Ÿ–ß§ªªâp8hß¾µk×bñŠ_IÝ{¼@¿ +D”#’ÆõjШaj×®×ëÅápH!œý;™5í=ÆLLaÂÔØr/ANH®¨*.§“ääºÔ«W‡P(D0Ä0 4M#2*’è¨hbbbˆˆˆ@UUŒb„Ò$ÈÎiJSa=×UZEóü³]|*>=ÛÇE g4\.‡Ãn/®ªh §Ã‰ÃáÀátàë–†a ª•‘Ë”p.Sš ë¹®Ò*ª˜çŸíâSñé¹2.Š¢ØA†Ë‰Çã!Ò‰ÇãÁãñàrÚˆRŠèšÂyAi*¬eQi­Ð @T1+5.Th\DéT|*>=“>UPP[uUUUE)5¸ C8¯(Pa-æ.¢´åeRP,‚Åÿœåª˜EpFT1ÿs–«bŠOŧâÓRÇ¥2H!œ”¤ÂZÚrQÅULñ©øT|zz4ἡ8ÖÒ–‹*fÅlULñ©øôüóé®]»p¹\¸Ýn<n··ÛËåÂé´‹>5M+˜2±åÞut]';;[‚ AAÎL!Ó%Â!Î1êÁ åíõc:A]Œ‚í‚ g?d§ìÔ/In;–Ôôî¾ )³·–ï²Í³ï£×è9ØõÉ-G²ãhÙ“oÌ46mÚTð·9e/¡’wSVóéÌOY¸fWN€5‹çòéÌoÙvð¨8SA‚ ¡¼œNE··&·—f^Î3ø½RM¦oß¾}¿Æ¡ã:ßZ7ƒ½®bÁšåÜ4°;¯¯‚hùþ•~ ~+?~;–Kº ç·ƒ¡ríÿ\VwA C8Eœ>E§·½ÔX./5“#(¯ˆ¡;²õ;×#6Ê q]©Yöu5®š<Ÿ={öØž¤Îï"EV€ùoáµIÏ3ï¿7óÔ3IkÁëG6sóäT^ÿn/¾½‚‰]S™2{}¹l?—ÕA$ÈN¿+QÝ\9B=oA¼ÛAµ^wÒªVd¹Ö®Ñ¤WÖõâIhÆ„‘Ê 9”…Ïwˆ}³ Õƒ˜Áý,YœÅßz· I÷á´=òŽØûܬT¨r]Ç€M÷¿déœ-ä–£Vúx…Ä¢*ÒO™ºcQéÇ«; ‚ üˆv‰PˆÓ¡ ¨º9Ö~ûÒ¿ß^îõ£’º3<|£~ëßk–ó^ßbÙ¤ki5É~]oÀc|úâ­ÔŠ´/ø~ݤN¼;|MöP7Rcïá\ZWÅw`/ -šó»T@ͦÈܨPd~.«; ‚ H&CŠ ÁE÷óãÊìÙ³‡›qÉê§øhÙžcÐÚãÐNè"¨Ø¯õܬBok2œ‚ d‡ÒRÙ‘’Jº¿ü™úöídý¦Õ­Sºïèêõ©_ÛVtyësaßR)¼ÊZvgå†7£³;× Fxê¡jr+2·¤^ÊÁëI¨w²F@žo?;R¶±ç`ö)UK?ÂîÔv¦e”ûÑßÓí3A 2„3Be”ÍüŒ¾ôb.ïÛ“I_l9uû¶rX¿|;öeÔun[ÎÛŸ Eb¬}ð»j1ðÚš¼6c)¹VŸf<ÎÚ„Ó¨ª=?]£9½/óŲ=˜ù{˜9î}¿Èã»‰Šº£ B±HM†Pžßâ3•PPT4]ÚyYø£öucËŸ)vß?0’‡g¥¼sÛäO¹åwµAÅÅe÷½Ç²‹ÐäÕ|ðôãË…Ãñ†ƒ5² Oô,]ve<Ðäúçù|PÃÂê?º£ ‚Â)áô*(³]G-F¼–‘A —«ü‡d±ûVb¹ù5\ÿ?|ÅIldá/¨y›2qåzî?’‹Ë[…¨úþ'¶Fê¶~É…ø„¸“ê~o%/ IDAT2 T §žåêŽy§Ög‚ eA¦K„ðMóéUP,­BFYöíöx‰‹‹;)À8äxˆOH8)À(¸ˆ{â¨ZD€ç·º£ Be4¡à¢s:ÿ¬œËꎂ üù8Õi2]"„ÃM‰ »ØéI nƒ§râpÅR·Aìé×R|VêrA„ÓŒäIAA8=7Z2ÂñøÒÖ2ïÇm´î;fUÝǽ¿žek¶ïªÊ…»/©wA¡d$“!`ænetßAÜûødç«BLßô­º^ÎwÛ6ÿ^º^0Œu!0A¡D$“!àß»‰…Fo–­ºîcˆ;V¼D§>áÅ1]ÁFÄÞ®L[¸§†6“AAŠE2BŠ#ÜÍ¡Ps(zˆ˜ˆðkHEEsJ|*‚ ”Œ\)„c§GÌ ïjtú#z 䑼ǩå›ËSk.aÑ”d0A¡äëŠ €àç9ï3êÊ{h5lµ<…ççÙM¤â#¼x#ëžÏ”qAJD2äÀî,Ì1èTÅSX#à 0wâ£t{d÷ßÒ¬Áx¶tåÅ…)|xc«ã¶ap(m79ùà­‘D5¯Z‚ v$“!€Ë#eÂ×X9e:{WäT<4èOÆödå[sö±eU6íkn0%Šž‚ ‰Èí¦p,žp8AÏÆ8A´ýà—èÖÿjZt7M®Š©'huˆ¢§ ‚ A†P2z&9¹:D "k´eÒ/[ù§Ï‰‹¸¸“AEÑSA8™. ð&µaTÕôk×€Y[œ°T#&.®ÈC=A„¢L†P€âHdÜ⟶ë0գʱ¢‡AþÄ BAA‚ ¡8TOMš‰Úª ‚p ®)2©@1ËÐÑ KlA$ÈÊdóª¹|4s!>ý¸‹µàãyv^*) Ÿ¡ç]Ÿ“gY€ÁÚ¹ðâKï²9#ÿ²¹8ÛA 2„³†}«?¤Ï[™µC®jÄí/-Ç|ië™÷í\æ,ùnK/fþ÷‹Hó…Êf› ‚pZ‘§K„2“•ñJ”^døÑõz»(5¯â†#Ùh¼¬Zü°âgò6ÏbÀ¨g¸lí;Ôõeú¸Ë;ç*f-^M£j*¿}÷×]Òž÷l OãX¶/y‰)i°içu8{™õúµ¼±'“eðbÝê­ìغ‰-J<ÙyP«UgÀY&ÛA 2„? '³¦½Ç˜‰)L˜[îõ{òyð±¿Ñ¤Ž«z_zy–¡[`äìâÃO2mÁý´¯@÷«ïá…ï?âË•iôiKDlS2—Žå…W³¨[½Ñî癫»¡(Ôj})÷·jBÊg3:ú^z'Gˆ³AÎ"dºD(=÷~^€Çë.÷úN~¯¤°Lû¿Š–a°6hâtk…?ï=öºfËË™1c’bq‘Ãæ¥“rÍWžš ~ÝDG¯ð÷³ô#ìNMagZ†¸[A‚ áÌY£-ãßšÉôñX¾éP¹Ö |d¦æ‘žž@ž/‹…þL²3sqÄ&òp=/?÷1iY¹èz€M˧3zê>z6¯À¶ï&ðÈçérå >‚›o íÃeª'ŽñìH;@n®ŸÔuKxå±ؘ*³û×|J·½þÄO˜òx« Â)C¦K„2_µ V^9+À—ñlÚQ¸íy.[ó$Ë&Œ„ÐA®è÷Ë~y‚‘s¾Åõø5tmýPÁj/Íø‘k.°ƒ ‡;‘­ÝMÛ°,Àø·çR'2\|ªÄ2øåǹhH/ž/¿wâ»Ôò–ÕNƒ”5?ðÔ?/9¹¨UøöÎ;<Šâ㟽šŽ„BK †ÞQ:HW:HQ°""ŠAQQô'` Q©¢ôBï%ô¤rÉ]®ìíï»\’\º:ž<ÜÝÞìÎÍÌî¾ûò Á #)ÊÍ?º-\¸0ßg­[·¥û/ãèÒ1<·¶ kç Âp‹oƳ«ôÞ¥Ñirö­Ø­ØÐ¢Å†ÙlAsÝöÜßËr€N§C]‚ã*öx>hÙŽMí?cÕôb @ðŸ&&&N‡^¯ÇÛÛ½^^¯G§Ó¡ÕjÑh4¨Õj$IB’$dYÆn·c·ÛIOOÏ·?Ñ]"(6Uêw#våkÔ®ó*±–[Û­ ÷6`0ò I£C§‘4:| Øžû{Þ%Šl%Å*óöó„À‚[Œè.ÿðîß¿“x£Š@Ý¿ã7©ô!|zø¼¨\@ "Cp·ñ­ŒoQ@ (ƃœ(Á"Û õß”7E¶cµÛÙ½ì¹àŸ¨S@ˆ Á=yu.Ä¥pXÎótýpÖN»ç²}3y;¹j,í_\Õ˜M„ÕÉùÌœß}ñÐJfΚÜ9sX{0þŽþ&KÒq¾Ÿ5“9sæ0où~l¹Æw§DogæÌ™w/YÌ–ƒ1´S3#Ö²xÉjÎ\Í,QZSϱì÷Å쉺"Îw@ˆ Á¤(—V€RzM®›{ ›TgÐðÚ ûx-g,#(´Ãú…3ãï³·HøÏ¥õú¼Ý 4^¾T¨RŽ´_±âDò­ ICù `Ô©›ùä×3ä^5D£7ôËç·5O§×¼Í‹¿¼¡´‰Q˨×òaÖK#në´l2ˆ£¹Ö=qXbx³M;&ÿu¯ ¢û 1æQ GÒ´}_6ÜɽZóå† y„ðÆÏ»ÒkÈ3l_=Ž-†päjñ×TQì™\út¹Ÿ=—²ÄI/‘!¸SxriE¶s†T«è“Óøtt7Èm-y¬k]*‡6ç§š²þd:Ô¼îâîÉ¥UÆb6ØÝQ—Ö‚òV\ô>¨Ö<ßRZðkIù\»¨X« ƒ  o¯ö(RáÆnµzˢ=ºÓZ1™óo×Ô¤Oÿþ<1d(É1yOtCå†<9¹*½sõÖ‚Ò'oŠ=çØŠœWU*&#jú†ÚÑùݳh6~3_ÎK3"x·Åy~Ûr.'B´{ ì±èë÷ùiû"bW¾Æžh“;J±áëh5q_Ný”õß?͇ã—èR½ö´“<==š¯Ögæw»y¿e4sV+vêË5`òÂ]Œ.Å•4‹8é!2wŠB]Z•w†¿Ø/ïS©4ÍÛ´$ iOj„¡í|ʶ¥a5ƒëFæÙ¥õÒÑuÙ€jaa„…UcØG ¹lÌùî¹ èJxXû½ÊëýkñÅšh×ÓüE~œô(Õ¨F£þpòjþ'k›\°€pPš}k1i`mj„‡Ñû£?IÎ5-ÙcÞ3ÛŸBp5ç±÷éGpƒ·‰µ(8¬ ìŽØHä¡Û¹•m‘lذ£Ñ)×)+G#VðíOdÉ#ªŒ‰V¼Êx¹[•¤B­Õ¸ÓÛ¼ˆ~o ¡²VBPŸé½Ù|4Îù»¬ñl‹Hax§úÔh=„†i³¸’æJ¦”hðž–áe@*Më§z±cÍ)L¹"!EשހP/$Zœô‚;EJÒ$¥'rÉ—c†QE/]w„ä£ûع‡ÈÈ=lÞ¹—€`›3*¡d°à­‡ùe–Gì#*ê ¦ø3¸Cc6œI%‘‡¿@ëo¶rñb ¶-¦ª›âŒiäsi:Á±cQ¤[äbå­8” nÍNÕ@ªÈ3Ï­ {êkÓ‹«M>d÷Ñ(ŽìÙ@³¤iÖî$ÚâöÎåÁ¯Ñkæ"öìß÷ÏUç·ÝÄ]ËtÝkí”­õ8«#vsìèN&T_Æ”UQ%Ê{ÌÆÝ´zk {·-¦Ê¯cÙ|êZ±ò–·ÇÆ˪}g‰»p’ŸÇtëìvP,FNGãôe3×¢£‰:Å™ãǸ”wìƒÃz‘G¾À”‰/ðöòÓy¤j³ïñN/&~ý_~4” ;0¬C˜[„¤^µPÚݵ¥Æ¯‚c.Ýh´;¨RÖ¥‘tÞTõQséš3Ò‘zåuj“½ lÅšÍòEzŠ[§ÇcRÄI/˜Â*¸inÎ¥U ¦ã;Ryé¥ÊÖsÞNŠri½¯÷uðcܨ™Ø^nHùr:MþŠF•œñí{Ù¥õÌ®.û:¿=×_I‚²µxnÊ£Mõªø—©Èœ9/SÙÔRuž|îeNU>‡É2”‘ ~ºÑ2zÆœ—éÞ5,Ï6K–S”õ2`ð {©F+”)¸þt>×=+©£Q_eœïí¦ b.IsH:ª¶¯Ç„a-ñùOômA#rD$Cp[¸—V56š?Í £F1jÔ(Æ<;ŒØCÙýüE¸´J¥i;ük|Ó‹JeôÈÆd–½=Š×æÎyb¾.­Y©ñœ?{†‹WÓo(½šn@6#¨Ëä Å«½(«“Èùë½ó$©Õñ1j\ 3‹ßz„ù¦Øu(ŠóΰhFßOhO7Q}ÎÑ+Öj’3n¤ˆ¼©|ª0eþ<Ó¾¥õ©q{õtvd‹ »‹Èä`©4 Zuá‘Þq_å\ƒ3kߟD«‰ËymØ@žzi*Ÿu9ÌÌ-góD.L¹v•mƠ͉l¤ÃĦ¸¾!Û‰5ÉTðs¶ËraõH>íNõü1BÀQÂ5øy$s¾Ÿ)“Íù³Ñ$ÅXÁMq3.­)©F’Ï\æªÑÈ\¾š²‘t+Eº´:,çy£oNXƒè;x0O ưÑUI:—äž²yÓ.­Š•u³úÑ®}Ÿ,ÙW“1•4c*©é×HHOt¾6:Ç„6{.¿ÅÜåH·ØÉ2&°jÎD¶¨§Qµ@š?3ˆeo¿Áº#1˜LF.žÙÅk ضÚ9&Ã’j§IXÊh¸zf?‹?Z…)9ž×ÏnÍ 5ÕHb’³<“S3HIN%Ë®€buå)ÅYNŠ™¤äk\NHĦ(Eä­ Æ˜Môyê{|k<È!C>rèÈÌÊ{C=º;Š$“‰ÄË'YòÍtþˆŒË–óŒjÝ’öm›3yÉ©\âÛÐöeI:w‹‚5ã2§ö¦Ó¸‚¯;ŠÐ´÷³,ys:'’,\;·•×ÿN OóW„¤½VäË…;0)Vv-œÂá€w¸¯œS„”®P›öæÙ,‹¼ˆÃr‘%oýL¯!÷+ú“[Z²•Q_m`Þ”' ¼®›Ía:ÇØ.íi×¾-W,ÂÕWðßFt—n%uiuXÎóÁ“ï@ª'¦TãëÁ)têçtcýly[>PË£K«Ãb¦‚^Í䡘œ½Ñ0€%kÛæ >½I—V‡5=%B… <Õ.¨D7¢eotäõ¿³E×êNüŸgßþ·¨X¡9ûÖÏc\¿Gøx´S”kñ*k7½@U :ŽgÙìoéÛ=Çhð©ñß0¢c5$:ŒO›=™àÝ•÷ßÅ‚w?äñI!¬šÞƒèµÓèòü/î´Íë;KèûÍ'iº€A·[ØÜí5ÏÎd°ëýÆ'y8ÜsÞ24¥À¼Žž­ê¸÷ßaøÿhQ½Œû}ÍŽ£h5µ7\î¹í}‹·zúçh µ7-ز=•ÆUóv±5î3‹VÝ¡¾+mÇ>d~«œ²¯Ðh0sÇl k£êLøn#TÔºEÈCc"òÁîÔøÂÞ]ùkË·¡ŸÊ§ý>ƒ½Zò.Pã±Où³wõ·u- kÜRcN°%Cæñé+¨_N+. ‚ÿ4Â…Up˸.­v«I§C±š1[| >vܨKkFôzjµÆäù;yæÁàÛPj2&£ 5ƒO"ÇL¦ÅŽF_oTÀ¶ÂóíË›ŒÕª ÓIXÌVdÔøxë Lo1ËHZm!ÆvÙûѸ-=Õˆ~~O-NOMÆ¡._]tŠÝLjš ÁŸRºüǶ™SI3AÙ¿—ÃÏ´6íhðó>z×É?iÏï/òÈ»&ÖïùžÚeE°XðÏâV»°ŠH†à–Q¥~7b_Ií:;‰<ôUõ·Nhè½ 4ÚC£sÝÜtÞ<˜¶IÞ7pÜ”¤X(ÿ*½[ݦRSãc0ºUåáw©ŠøÍ·/oj²‹]ïíí1½Þ[íq»NWø¶2~~sWÆ/ÀC}{S6 ð¼i½ý(w "3v=5[ ﮬ¯äS`ëÊé}ô~ëk!0ÉÜjÒ®ÆoTQ­zea.ø×á°¦}>ÒUªR¡„ƒœÉnáÒ*ø7£ÒùR½–¯( ¸çŒ(Á {iê{Ù‰õFŽ@ D†àŽÜq vaMþ‹°†ãˆN<˘&5Yu:±Þ(ž;@ˆ àQ˜ «Þà\aQ£7PË ãŸ4©ïfÜD@ˆ àQ˜ «ÖPžöª (:üÈ, W¡07ÑÜÛ=uG8§Râa»“¹äÝE¹‰zrì!2‚[Dá.¬:Ú JY½†òíGS/×Ô¿¢ÜD³]X³Ý@‡¼:– ºoq.ݹ´éêq>Ù€êáa„ñÞ‡ãxrÒ ²\“¦r¶‡S#¼¿»€x“‚bçËQ ôìD–þ½„×û×"(|8?­9L–R|7Ñ⸰ ÁMR˜ «JÄÈq}1H::>û5ËæÜŠ=º‰*f–Б3-Ì_Á¾=[èî{ Ò~áøE#²ñ#ìÎæ ãÙ¹íëçêü%9™§x­SO2[~ÅÑÓç8µ‹aªÿñÀƒß“®.O¿×f¢Û6—ÞØF÷‰KY6·'‹F÷bÈì]X‹é&z£.¬@ð_@LaÜ47ãÂêÉMÔËÏÂßãùúï©nIP‹?ÈRüƒë€m? f_<Ð’f÷7ÀDVÌ[OŠkŒ©A:Ìs“~åô¥$â£÷ñQÿ1TíøPžœžÜD‹B8r Én%uaEò.ÒMôÉO—ãø¨š¾çL£mÊôŸ6Ò¼Šjšphó<Þé÷$ ÞpZ·‡<<š »;ÇF”k¾õ?0®_WÞÎpE#¼»2ýë— Ð.¡Ñ¾Ê%:6o@¿1Ÿó瘾nƒ·¢ÜD‹B8r ‚ÿ2»Dp˸QÖ⸉:]XÕ…|ÇéŠF_¨¨ÑhB£÷Æ;—ã§b‹áɦ“ùôÐ\*¨<å·(7ÑÂŽœàŸÄ­ö.W=Á-£JýnÄ®|Úu^%¶]*7†"ìÊõÞßqº…,0œÛ C^aO`þ¯³åÚ:^÷.Óg/#¡Ð<«Ñ{ëJ,0r9Ç!þ“ˆîÁ-Ã?¼;Ç÷ï$Þ¨"PwoçURhôÐH~îø›»ÖŸRê[}ozOÚEoÑ4ÁÍóqa•¼©×²õD• ÁmCÄp÷ÿ^S»ÝŠ]¾±¡Oÿ÷ÚËgrÕ$\h‹_¯w¯>íV+Vûmžé¤¤qâØylŠ˜Q%D†@p‡p˜â‰X¾„Õ‘çò]`O¯™HX»EîåÀÿ5(fþxò~Æ.=Uâ¤ÿ÷ZÙxœfí»qìŠÅžÀòŸfóÃßûoÛ æâ¡•Ìœ5‡9sæ°ö`ü=UÅÉ›Ãržá ÂïN}*fþú>Ý|[@ìÎè:äwR‹¡;S¢·3sæÌÛV—–¤ã|?k&sæÌaÞòýwTøÜÍcß+y"Cp‡.nVVÌèÇç_æt¼1ßæ Õ›r±šKPP#FŒ ßÀO‰5Ý["¤¸.­7â›V”{ímuˆUÒ˜Õ²&Û.eùÕëçPµçlZ‡ú ©õدþÁ¬ùg°Ý‚r+—/ª”#íÀW¬8‘|Oµ‡âåMM5 e4š»RgejzS3° ªÛµ¾r¯~͸ϟÊc”Xh™é $ýò¹ÇºÌˆ^å^ÿ¦ÄHÊ£NÝÌ'¿Þ./ìü“-g®ÝÚ²(æ±ï w(oBdîÔó.ɧL|µî$/÷oTÀ,8l8®û´|ö|?ýeÖ¬YÃÞŸ±<2¦`U^¤ «§í2&³ù†BÈE¹´"ySûá˜n ÄŠr¯-òØ8§›Ìæ‡æ{*{S²0YŠˆNYbøêÝLx©“smÉ—‡¿’SÙ 9vQyWìVÌVÅUwy÷Q±V@ß^íQ¤»Qåú{£'o*}SœãÁ°R…æÍS×aay/V¹#Ïv!3µä"»rìVÏí)áØ*fe à±VAÅ*3Cå†<9¹*½sµà‚~›Zm•Öà 4ÙÎa5»Û€> &}ú÷ç‰!CIŽ)ü¦g¼¼Œo·_º±¨€»Êyò_Üc…ÕjÆ|‹»“oUÞ„ÈÜ3h‘4_ž´¥‚yã…ùžÖ½ªÓ¢q5ʵ|“¹3Gòá›ëIËõ4S|Ö‚·Ÿßû'=ÂB©NXµ`æü}›¢`º¼ƒ'j…0úݯX4=ª2ðÙiDF%º.dÅsi(Ü•AMƒo Ä v¯-Ö±•4Öÿ4ªaáÔ'¤ö+ls=¥eÆ®§{; {¤«Ž$»sýy† Ð>D^Ê"5îëW¯eK†Ì¶ukØÁ†[‰KÍÿ¬snû¯,÷™L‡Úerä¢l%ùè>æÍM¨ëØûc3‹Ì»ÃÃÄ&Õ5ö5‚«…^÷>úð9ª‡‡Óö¹_òÔ;d/ù^2<¹þUçQk?%(|8óWoà›IÏÄ[3gÌ_.…å-jí§ѯÿ«ìŽÍ¼N$xvö”÷âÔYfìzç±ûõã» òݤOï\@°PœçÊœ¿9‰]õ2棹,˜ó:Õœuº;6½u˜Áʧ3tÚp*º¢Eµ7¥Ù·f“Ö¦Fx½?ú“d‹sIÿó‡v²zc$¤ígsÄ6¶nÜÀ¶'ÈR¬¬=šÖÃG¸Îá0&|ø½jÕ$¼f_vÄäÍŸMö,*u’/å ^y>ó”÷Ò½f_FµAâj|1Ûc‰iY “QKµû[QÙà9ïaÁ帿ʃԫFëeìÔš†e}!å MOb(usíUÒꈋ˜I‹Ñ;)ßDG¢ÕŠó<Ðù{l=«î27¢E=÷d ‡ÜBAÁ¡8P)*$I¡8œŠÄ%J„ÈÜ2S¯pxå5ðzÒ>%krçwÿ ¾O¡>½…‡!`Ð#ìùf 1϶A.Â…Õîi»bÆj’ éÜ•ÚU+a5Û #ç-åC%ô’„l3ªËî+S>”ä©È®‹ëÝti-êØ]º×'¨’,›‚V[åË;\5G¬äúnÜ•ÈuÑw˜­íìÒ¬\cÑK³7sþ×EŸÔ@@ÍP²ŸQ%uþ°©§¼'Ç€CQt~øfŠŒ 広ÉCä,¸¸D?‚ƒË9SÃõ×sËXRí”Éyú–4ztùžò–ó»ó0(Ìq¸8y/²ÎŠÈæ:ewp˜°Ê€l# Ní|˜sÿò¬øH^œ™õG,Ž=´7}NgiÅZMPr‰«ÅJòùëDM®¼+²Œ,ÙrÄXÝUç(Ú†ç_nÀ©òÇI~è…<å]¶Êî6j±8Û{Cî‚‹Zç/+5žËIè ªàìz´§àþÎñÉ‚MŸR /’™ÝáÁœªÈöX´Ët¡yËŠ‚âpF,dYF­V;ßK9£çÙåÝ%‚»BPã¾ürx3í•?9t!½ø7QãNü™Q>Åó/¿Â„ ¯ðÒ #è¥þ‹ß6'¤V.­xѰk_b¶ŸA ¸V­ZѰNƸ},Ûx‡¢$ïÇì%»IHJâhÄô¿‰Q£[;9º¸›.­[¥ó£qýÒœJ°Q¥VZµjNH-'#þâ@lŠÝÌéÈy4éö"s#Nr*òG& jÃôŇÜýµ*ï(ëÅù¸+˜LF¢nãó÷>ãD’óB~íäf¤÷g`‹üƒû“’H>—LšÙy¸–”²‘tkÑy¿–”äü®ë>œž‚ŒŒ‰¤ç˜“1•4c*©é×HHOt¾6Z®‹²,¦UÛö ù`—«.]O®\]Æ…×9à¬ãý¡Ùtä±;,çùxØTHµ1xR0k¦ÕfÚ°w!ÕÆ¨¯k±ô•¶…æýÍ®Ììû$[yüýJLk[ƒÈ—²¥Ë>*µ(ÃÓC?¥Ó¾il£#¯ÿà:âêNüŸgßþ·\ƒ eÎÜÀ‡¯wÈ ¯Ãõ×sga5Ê ý+ŸìÌSÉVÊ7{šÅ?pÖbf™‡¼ù\ÜLý¶#s k[Þj žS¤ã0PdÞ½<Ô™ÃËä;° ÙêÎÛÊ©ÎýDšKý~ï°Dù’þ]îwgoÐÄøaD $Ëy¦¹ê´ßØJlù¼¾ûýˆ™ÕYòzÉû:+†?÷埵rrõûÛ[?ßu š¸ØÂæn§¨yv&ƒ]ï7ö8ÉÃá¥)Ü’¹¯÷¦k×¹jÀWsG±ý‹̈˄ßÑzùCôòÓòÅ‚}¼Ò ‘ÏdKÇㄜúØ}|€æõ'ðýfç¾³©ÞóWf{;ï*óTfNÙ lå÷úkñkn`Ô°™tÞ6’ZïýÉÔ:è^ıÖöü•&ðT®k‹W¥†ÌߎÇÚ5p]›Fóòc-ûH2îax˲ۣå» s™ŽZ;­Àr‰ˆˆ@¥R9Ç[¸Ä…]¶£R©Ü¦h*I•Ç Íf/x¬paÜ3?>ÞÝ+ky¼Y¥[¼ó¢]X=mÏvuš åèîÓkÞfè_m‰üúá"÷\Z=Ûb6bSÔxûøp#Ö,ŠÝJ–t:]Nz%ÕóÖS@‚|¤›ª·-7ÏyŽçƒ–íØÔþ3×ÍW*°¾ rôõX犕_€ÀÐ5D}ÛNOŽÃÅq,.°ÎŠ]vf2Ìö|ŽÅE‘uu? wÀã4E}/#v«*tºÏóqFôzjµÆäù;yæÁà‚Ïaô”¾þÚUD{,¾Ët^Î;‡Z­ÆËË ­V‹^¯G«ÕºXs»°fG=²]X ì&{ï½÷Þ»ÙB:~üx¾ÏªV­*n¬‚\rV…Ù¸“çž{›uiuy´}uÔ·l1 Z½­V}CÛ%µ½^‹Z•s“·$áµAorøØ_œMI!ÉQ•Faþ…î_£U£V•Ü¥uÿÒQ÷œÂЖ•oø·{:¶F«G§ÕÞp¿¨¤R£U«ó¦—¼oX‡2Zé¦ëí†Ê­¨bµ]ãï9?òÌ'Ó©á¯+´¾¯/“¢êü®ŸòÉ*]Nå|Äf u›S¥Ì­wÔhõæÏSÞ‹¬³b׷릢.YjMéÊ4¬]ù¶÷¿«ÔjÔêW/ÿÕ³[˜»©1ŸMyˆRj©s8ÿµËS{tºLåû[8y)•s§Ò oT“RÅó©©Î.•ëz˜½$)ÏÐ쮫͊ÅjÁáp V©E$Cp7£V.^ˆEö $¤B™{:«VãEvî9‰¤ÕaµšðiJ“ðò¢ÿÅUçIÑû8t>֎Ť¡V‹VûiEÁ î Û£bæØ®H®Ú´n—é­KdÄÄÄ••…N§C¯×£×ëÑhµh]Q I%¡V©ÝÓWm6;F#Ý3M„È@K—.‘””„F£¡T©Rxyyåé&Q«Õîu2¬V+&“ ½^OXXFc~Ë1ðSp cµÊèt:Q@p—p8” äò¥KØl6¼½½ñööv EQ°ÙlØl6, *µšÐÐP÷ !2÷$ñæAÛ‰847ÏB>–¤ãÌ›¿»Þ‹RU౞Mò¯ *‚[‚¢(øùú¢Ój9}ú4F£ooôºœõ8,V Yæ,¨S»6þþþ˜]Sn¯G¬“!¸'°Ûµà]ýõ²÷^v1‚ÙSUCÃBiÔ¸1eË–Åfµ‘””ÄÅ‹INNF£ÖP³fMZµnE`` Çý‰H†àÎ)d»›C‹N—?üÀ“\<’?Ó)°&æX&/KªX n#Ùþ$µ†*•+ãããÙdÎ7U§Ó¡Õ=ðY\³·™ˆo_ qßg˜>óc‚«…Ì·«»VVìñüïѺ4îÆ+³ÖæsÌæv; À9eW—´F£¡\@9P«Õ¹¶Bdn#jöÓú]ü¶£4ëwïgÝoï1å¥O‰ÉtŠ IÈ“Ÿ­áûÑ/°92E™@ Üm¡‘ë…J¥¢TéR”.]:×öœ•?Ù€êáa„ñÞ‡ãxrÒ ·›kQÛÏïý“a¡Ô'¬Z0sþ>„MQ0]ÞÁµBýîW,š?ƒaUøì4"£]7ÐvGl$òÐNŽíÜʶÈ6lØÀÑè’›¼YmJââÐò/ ¡º+oî¹è*“&6©Î˜æ²`ÎëT '¤ö+ìŽÍ5G]±rdã/”UÝùmXcdã)F>ؤSÙÙ}æ>øGêÞŠÜðWÚõ›À×K·Ó¥IeÒãö0¶[b¬+™Ö·oÅó³§qñ…ÿ1måJbwýÊ .ùnݺ9uŒÓ—Í\»MÔIÙhÆì[‹ú¡eoAÉȺÊü´tMjW&nÇ\zŒø™6ûߢ¼>ˆÁ3ÆòÐÓ“(ûþìÙÿ<Û¾~Œ7?`íôh%‰ƒKߣ׸ã|7ÿO*k™3|kcÑÐû ч0Ôð?®eÙž˜±€k}û°îÜ5z4tE~zNÿš×Ag:ŰNƒØÑ釗&=v Ú>Á‹ÿÀúWÙõLJLœ»ƒ ßm¤Š.‹¿§<Ä»G²aß î+§âÄ–ŸèÞ¡î‹æŠÚ"ë\ Ü=(WŽ*U*£Ñh܈4»D¯×»·¶—‚ÛNJô.¾ÿây–g6`ŒÉââ² rúºµíþ¬jÏhLCqõàJ¶èFrhò”SI@E>]·˜…[mhXÛ³Øû÷ mJjü–.ŒÄ«”„A£bÞô¼Ó¿.5„Aånü1a >’DÃÚc0F2åÇ=tžþO>÷2§*ŸÃdÊÈáùDÕòþäŠVç~JW¬”ryê‘fh‹œúe¬üõQ?†îq-¡n€Ñ åµjª…‡‚ÿó¼2´5þ’DϧßâµÁØ­’Á™Ë˜ñ×Nº5ð`ÆŸÓ©õ¤Lp ^Ôªåê²’t× a ?ä:º¤Õ1“£wR¾‰ŽD«g*fïÔ{æÆ?Þ5Pû½¯¹´ª9á5« YãY½è*Ô‚Ó{Ös CA«8ÝuÞtކÔ'„@ðBˆ Ám'3õ ‡W^¯)íS‚&§˜YüÖ#,Ÿ]‡^#ÐOÃþEãym«³ŸÏn3ƒÖm®ûµOå¦ ì|íq»bÆj’ éÜ•ÚU+a5Û #ç-åC%ô’„l3ªËÓ§X¦|(É;R‘-Ù]r+ÑgösÑ«ÞÙ‚B1a·Ôt§ÍF]€UòéµÒçÕL–¯ÜÊô r˜®l£a§yh²‹O¶P§6×K6•kª` éÆLÀ)2¬v !îÄØP0fX€ÒùŽmO9Àýã“›8>¥^$3»Ãƒ9Ö¹RÒ¯š°) jIB‘M¤Xe{N9té^Ÿ J²l Zmu–/ïL@pÕ’ÈKâbɰ€¡B0å âR%üc2· Æ}ùåðfÚ+rèBz‰ÒZRí4 «B@ WÏìgñG«0%Ç“b– mÒ ®~Äg¿íàšÑDÚÕ ,ú¸%A-þ KQŒñ¿ÙV¢¥·ÿMcVËšl»”U²²py“4îû ÃéGPPs·^øO¶‹ñMӜ˔kôjtÂ厴u+?ïJ¯!ϰ}õ8:´‘«¶b'?»u:]ºtqÿuîó% ÖâÖ©•˧v1êéÌ\sNÔÅ- iäªbE¡nݺ(Š’#0< !2÷ÆKQl‘;yè3šU)UÀ7là°‘§§PRS»ÃÆufÍš=üôÑ'œL.¸KÅböb•1[­…ßô­fLfs‰C´Š=•½)Y˜,%K§ÒùÑÖ·<]a/ñu{òÓO?Ñ2´àµ7ìV+&³ÕãþìVóm /ËXÌf¬övËUò¦öà \+•” ­¡<íUPt*†y‘i¿±:½]妨sêL¹î ¢ó.Ù&n5ö´“<==š¯Ögæw»y¿e4sV+vz5}§oàâŋοãÓ¨¢—ŠW§’/}_šÎºÙ°óH¼èJ¹Ù¾ë„»Žíö|CÁõÞáü_ˆ Á½+˜5ÚìëcÁ7ŽRÁ¼ñBëž`ÔT­ß’Fu}ññ¼ùÐ~Û’÷I¦(Ös;Ð#,”ð°0÷{•×û×â‹5ÑîHDan¢E¹´¦ÆcýêµlÉÙ¶n ;""ذq+q©Åxº“|iܶÝz¶§fÃvtîÜ™:UË\í(ܶ8.­S<‹g½NPP¯|ö++~›M°ª,:@t‘.­…;Äf?ÕækSŠçÒ P&¸+ƒšß@kÒÑnØPÊê5”o?šz•|òD— ;v±Üm=Pd¹)f¶ÿ>…àjÎ:kܧÁ Þv:×32VXÞÓ£×Ó½f_¦ÌüIëQ#<Œ‡ß]@òuûv˜.²â÷ŸX¸fÿu] 2ç÷®`Ì#5 íÃüÕrœu3SÙµq 6lÈó·~Íœu)Ñàÿ<-ÃË€TšÖOõbÇšS%ê¾HHO!55ËWS ¸ x¨ÓìÓF ±.a]&7'‚¯+¿l!a2™ÜâB–ed‡Œl—q8î?!2÷,*ٚ§µúTnÁ˜§[ä3“Ç™13†½:3à™ç˜÷ÁJ]ÖéÙ.¬›+Œgcä>¶¯ÿ«ó—päd nï\ø½f.bÏþ=|û\u~ÛAܵLPÌü=å!Ư(φ}'¸pá$«>¿Á°÷Š ï@§Këß?Lc^lÓV®ä©Vi êÒ˜Õ'®aNMàè¾Óœ?Å©¨;Eº¥øÏYV›‚l-øû9î´»9vt'ª/cʪ(gYº\ZÿübÇõ½Ù³Ÿ>º“7?pÝä¯ñy§ö|v,„e«VóHõF½>J/}Gçºå©Òàa†¶æqiíw„uç\B —C쑨c¬üþUÆŒøü÷p SIDATÙ]î—¾G÷Kxü‡?ùjdS¶}ø5¯ðÖÐûÑ’å±\sÞñ)Ú„•*y[Ò1r\_ ’ŽŽÏ>GͲZ÷MÞÓ±‹,·"(ªÜ2ã¶óØøoYµï,qNòó˜N`½‚½8㙋Ȼ!¸/¿à÷Ÿ¼K³7W°wÛ2B—N`íñÄ<»¹xøoFŸÈØ}Ø›b;³qíú¢îÐX÷×—eâç+˜ô¿TÔ;HM¸B\\ î¿‹ñ1¤¸–ÁO½r‰€:µÉ¶˜©X³É1Å¿ÁÈ(DNH½zMhÖ´>íF~O¼I)ºNsGS\íOÜÔn2>)ç›Í†)ÓDRR©©©Øívìv;‡Ù.#Ë2vÙîrÁ×*1…Up—e³™ýkòÙ+ïRïÑ©ä]²ä±×rXiLò…sØÌ¥!q;Ï £wÿ"]X·~6›vï/gTïÆT~øE6üRŽ˜²8Šá&êÉ¥uíô‡x­^ Î.]€_¥S˜×u!ó’»´*ö4¢N&^7Ń;­äÙ¥Õ·Ÿq™lÞ0šðR4¨Ï_×þä—Ò!”ÕK  .Â¥ÕƒC¬Æ³¬Ã}×\Z‹S§žÊMSDé|=—›¾LêT|òÅg´©^ÿ2™3çe*ûÜš¼W -G«‰ËéÑÄ9mùé—B˜•À&îýT¬Ý‰I/¥“Ø„ÆUô9–¹?1ôË-Œêíœb^gÎ:’š¶¦jXtj(W%-Ú<‘DÅfÅßÏÙ®í¦ b®cÉmóÛ÷|@µÊe°Ï1åÁ®üùc;?’Ò¸7É/ cüÇv^yîQª—£qnTdÄÄÄ––FVVv»I’ÐëõhµZ·Í{ökµZ,ËX,üüüòG˜îäb\§NB­V£V«Ñ¸VWT•Jåîç°ÙlX,whF¥ÚTðШTH’„Z­v/Ç+Ú³@ðß¾‰+Šâ¾.h4÷ý/û^˜{ iî[´J¥ò8“#99™€€€B·gÏ É#`]ÇÎŽFtìØñ†Û¥K—în$Ãf³Q¹re÷…Vq– H²ÝNrr2ÇŽGqäT 'Î]â\Ü5²²lر"[!µš¡•E+ÜÓØd›ŒÝ!£U«¨TÞú5‚iÙ´.•+¢ÑhT*Äú˜Á¿%G-àp8Ü+d*ŠBVVYYY” ÄÏ×I’œ"Br®>‘[(Š‚¤R¹ï™a6› (Wˆ¡+Rˆˆq8ÄÄÄÜòßGE†ŸŸUªTq?ÝecµZ‰ŠŠbý¦íD>KbZ~žº÷U ÆÛGp•:jI…J%¹ž%×þ@%IÈY¶»F¼‚ŒÃ]¹*µZ¤éo[zs–ÅÙ7))X­v¢c.³yÇ~6ìŽâÌ…xzvlN£ú5Ñiµ"¢!üD†kF¶âÈï=†Án·sùÒ%tZ-¡a¡hÔ¹n˺ f:#55•*U*{P:ç/[d¤¥Ýú5eî¨ÈÈ^÷\«Õº ÏjµrñâE¶EîbÇÁ3˜m !UéÖ¡5õë„ã¥×"©$À¥ÀT’[ ¨UÎUÇ$)ÛÏEq—¼Ã!ãpd„u€$¡’éEúÛšÞjµƒ„û³àÊ•(_οÖFp5!™U[öQ©b9ªUE§ÓË`H üÃEFö¬ גݲ,»®Î?›ÍÆéÓ§ñ)UÊé¢Ñ䈥`AQV‹Å=¡X!–\"Æf³‘••uËÿv»›Í†V§EB¡8HNNæÄ‰=y‹¬!¨RYüýËâçWµJ…ì‡3’¡’d•¤ ©$P©rj@Q@vÈH€CqÎݵ;\‹…8ì(* ’"Ò‹ô·/½Ýáp¾“@R$d‡LCi*–C«Vsùj »ö'$¸ ¦ø@ðÄáp8«r­%‘ý—=þB¥RáííÑhäü¹søøxS. *IU`Ä"++‹M›6ѽ{÷|DzÙl.ó½jÕ*:v숗—WþHˆäœ¦j³Ù°Ûo½uýÂI’„ÉdÂÇÇERÈÌÌ$ÓäœcÌ”©èO`9?Ê 3͘²²œ#XÕ*@Aq€ TjTj*Ùºv¯8æz¢”pØíÈÙ¡nTjµ$Ò‹ô·/½ÝnÏó„ Ë22Mø–1¸„ˆDÌÅD§ØÖjÝ‚[ ü»#ÙâÂ.ÛqÈÎqvר ooo¼}œBÃl2cò6Qªt©¡áb÷îÝ,Y²„¤¤$zôèQ  )(:ºdɶnÝJÿþýiÞ<ÿêÉŠCÁd2Ý–Èêz½ž¬¬,222P©Tdff"iiiè}JQÎß??_| ¥°X¬œ9Ñ’VKHŠŒ5*•‚F¥AÒ€çˆ}F…¤Rá°ËÈ®·M¶£Èç <»ì|²ÔµH/Òß¶ôé™fW[Ùæ@v(ØmV| ¥$vÙAZZ:V«•J…N+ºL‚{$rÖŸP©TȪœîÅá@£Ñ ×é1¦ÑjµÎ{£kÚ¨N§#&&†ßÿS§N¹ÇP´.Eî±× ÄÄD¾ùæ¶lÙÂàÁƒ q?™L&²²²Ðëõÿl‘¡u v3™Lîùµ:ŽŒŒ JûøàçkÀ×P __>zo4Z ­IÊÕ)%IhU*$µ„Zr^ä%hÔjŠ‚CvMÅQdvçMBQvI­B¥V‹ô"ýmK¯ÒhœÑÅŠ„ÅjÁj±¢·ê@%9÷ms.^£Ö8§¯‰ Á¿¿»${= ·¸È%²»Msßè³gž=z”ï¾û.ß~SRRò}f4 üÜbÉYxíðáÃ>|˜gŸ}ÖíE’=}V«½õk‹ÜQ‘‘½ˆGöÿ‡»ÝŽ——ÞV…RÞ^”öñÁPª>>>èuz´:s¶Ž+’ílçjçàZ…¤’œ}ê²³/]Vœl첌,+(ŠSAjÔ"½HûÒ«ÕZP8v›ŒN§Ã¢ÍBcV#ÛíX,6ü zÔj5ZVˆ à?Ð]’=Æ+{àx¶Èp(Ôjµ[px{{£ÕjÝÑMEQhÒ¤ o¼ñ‹/&::Ú½_NWàƒ|AŸç¾Æ„††2`ÀªU«–Ç‹D’¤Û2FìŽG2²£Z­Ö–¶Ùð÷÷'1õ2z/=^^z¼½¼ðññÂÇ»4­ó¢.¹†ìK’„Zå\ÄD­Ò8/öZ ŵ¾ˆ]vöŸÛìVWá9?S•ä,l‘þÿíMOW†Ÿ{ï öŒ=@ìˆV†¶1F¡tÃÆ[ÿÄ’ÿƒŸÅ’5ûˆ RÕMh•¢¤.TQ¥8êàß;]Ìv0R*ÅQól,YslK–î¼s>Þ#ñ‹ŠWÚMÍgq|ƒï)2—QO‚z‚^®6ªñSÊ%‚ð¸E†Î4N¹ñà2‡±†$KrÊ$wÌ,§/·ÙŽ­­-ŽŽŽ8;;ãøø˜Ñh4W”ñóDFEÐï÷1ÆÌ¬k/3,>“QŠ ãåeçFƒn·Ëë‹ßøðþšµçÏð—< –––ð|¸ ´É³~Í 2]ÒYõçM&ù ÁNR¬Íp…ïAžQhc$^âŸaòé,“4ͯ'#Xþ‰câÑßüÐiÓl4ñ|¯zªáñ2-.´*|¢²[·Í4M¹‰oØÞÞ®2e¶£,edYÆ`0 ßïsrr2W„a8÷ý½½=ö÷÷ ‚ :s¦·©–ËÎM¹dÚV\kÍîî.\¾2|WçyëYž±ð4¾ïá/yh•_o´Á6 S˜–(Æ@ÙïRÝØÌa‹±­5 -ñ¿°øÒ±×:Kj|PšñMŒQŠ÷×šÞæ –——ñŒ”Já©”K>åèh’$ŒÇcÚí6/·_޹ї¥Œ’Z­Æááá܇“(Šæ6o–×O[’O¯k×Vúá—KŒ1h£óTV(òôL«Õb0pzzÊÕŸ—¼úøï_lÒÝìÑn¯‘$ßóP…ÀP(´§óÆ»b¼Õ7†ÄNȜ¹|À¦Rëp.2ÆËëç/ñ Š¿'dÎŽ4±üu}Åïo~eøö’°æ±³ó#N§šW¿os¡ Dd …ÓNŸe?bšæ“Ú~ÚÙ!¨3q uçuF¨|B™©¸/“¢Ôìç•¿ CÕœú E†µyÚbgžàŒ1ôz=´ÖœŸŸ3yóúg~9E’$•’“´²ðð< X]]å»Î·lll°¾¾NEÕþAž€Èœ-‹uéišòq4¢V«ÑíviµZ÷ŽŸ~î½/ ÃÏ>WÊ,FefÝBΤ¯*2Æã1qcŒ™q+Œ:+++\]]U»ëá¶3¶|±!üßQJõzf³I³Ù$ ó†Oëìmˆ‚ HIEND®B`‚rabbitmq-server-3.2.4/plugins-src/webmachine-wrapper/webmachine-git/www/images/site.gif0000755000000000000000000000153612305126066027771 0ustar rootrootGIF89aPPæ{{{€€€ŠŠŠ“““•••˜˜˜›››£££¥¥¥¦¦¦§§§¨¨¨ªªª«««¬¬¬­­­®®®¯¯¯°°°±±±²²²´´´µµµ¶¶¶···¸¸¸¹¹¹ººº»»»¾¾¾¿¿¿ÁÁÁÂÂÂÃÃÃÅÅÅÆÆÆÇÇÇÊÊÊËËËÌÌÌÍÍÍÎÎÎÏÏÏÐÐÐÑÑÑÒÒÒÔÔÔÕÕÕÖÖÖ×××ØØØÛÛÛÜÜÜÝÝÝÞÞÞßßßáááãããäääåååæææèèèéééêêêëëëìììíííïïïñññòòòóóó÷÷÷øøøùùùúúúûûûþþþÿÿÿ,PPþ-H° Áƒ*\Ȱ¡Ã‡#JœH±¢Å‹3jÜȱ£Ç CŠI²¤É“(Sª\ɲ¥Ë—0cÊ\Éa‡™/À8Ò¤çpJÜ0¤§ÑžB4…Èã¨SKšpJµDT†6¨:­qua­GƒtUø¬ÑcÞ0ÛóF…´_°mòâ-Ü‚%æ’ p·à†¹øö%hÄl ‚ ÄaöbÅY˜E1Á.äf9P°¬ø‚­I&$†l¡,UI œ¡õEeÕóR ±¶…¿N™T­ºˆÓ!©m3>j#8lNW¼¶m„SÚœUspj7lž>Û6ݵuÕ5ŒÄÊXÎÜ‚ £&j—·Âh‡ïª10i„|ÕBÑμ 䭷›hÑõgŸzëY DÌÇD(”wÁZíl¬5l!Ì!¨Ã\1¨Ö[<¨–Ã\9¨†[-8˜VK˜µÄ6¦•‚Y%ðw,äxÔ&4 $\þe CFðÐB <à`»IàÀt¹€ˆõ˜V–4À@„iàˆ mìf_œ Öiçxæ©çž|öéçX;rabbitmq-server-3.2.4/plugins-src/webmachine-wrapper/webmachine-git/www/images/bg.gif0000755000000000000000000001155112305126066027413 0ustar rootrootGIF89aYÊÕ ¬¨™¸¸¸ÖÖÖåååæææçççèèèéééêêêëëëìììíííîîîïïïðððñññòòòóóóôôôõõõööö÷÷÷øøøùùùúúúûûûüüüýýýþþþÿÿÿ,YÊþ)H° Áƒ*\Èp!€‡#JœH±¢Å‹3jÜȱ£Ç CŠI²¤É“H,À@ в¦D+YB ðPEŸq AÏÎ4fO¦ 0€H„x&åiS@Ò¡-àIS@˜ (€ IqNÀÕ€´ ÐMð0M¡M$Ы`nøX0QåC>Dä ©Ñ4%õY€(LÅ?žLI§VÞ9tÆ‹š†(YëCTê¥ÚùöCo%î@ êCÌ\0ÖKS'E¡Œò,àóki瀃ýÛZ¥Yçªþ0 v§ËÙ¼§Ñùqˆ ü¢…I è˜B…>@@>¶Ú‡v-@³ÝP<µõeP, hoM€V}} ES`´6ToMUÀTBEä“Vl½%PØuS…Óa7M„Õx“÷›Dy=´ÀTVØÖml)UžQÒDÙÃåä€P<Áål `ÀLÙA¥uH‡Ö T7[lÔÇWƒÇuFZVåðD|u¨0§So§{k0€QÙ%åäSeUUD]þ†“PP"€hý–`n‚±4¥Ui­(@vÿUV)U—±'O|E(šƒt 5•Zÿéú¡4à”<1@qtV%«t5À挥ñ„ÕbnOD@UäÑçUhyQÆPzY'(˜ïQ…SS\Æë_»ª$”NL†Z©{%…€‚.-ºê‚„G¥—³­Ö²§Jd\«@2ÓK@6<ÑcMp€·ìá”K¹Áf«—ZJš©8ÁF“‹,JU»ûG—|…([’8Ô¹¦F$éD´ò¥l‰:±„Ss% Ú¼LµÚÀx - -c˜ÀÒž¡Õ ”“> ×R¦=`T”]M@ºC9 XFt@]!5œÅ7@—‡éSU$ ÚŽþ¾WL,·T•^¶äRcêôiË‚ìX¥ÎN‡o·&Ó)'X ¤—¯’9üÙn‹2.O ZK&ïÍ·dù”çM:¡Å„)›Pª-:ÜÞ*É zÒ=Ã-ÍY¢d2}eû§qÒåÓºÁd@¥>©´vPw5ê´W«}0·[þÇ^&¿&¯@:°£îÑhyÛ·p°ÛqÊNƒò½`îÉï ­Œ3Í[Tr?^%€20Ašsr¶‡%?JyOP©¯ŒjhAHSˆò(âèi8ê ñb"– ‘CØbT!YÇz¡™LæÆ»D`Zx‘]@”ˆD` þU1Ö¢ÊD ,¤Ls*÷©QÉf7¸±°`ó-Ü4J4üƒˆtà×’ÕÍK4˜^E¤6·˜üˆ+Ђóx¶€‘9…,ÀúJàTb”$ˆIr˜”x¾è±“ÂÏtHK°$EðÍLÌXŽùeô€±´DGä ~p2LrKCÌ‹G±(ƒ P€NØs±µ¤òo¿ñZÒ`å hue\Å  ˜S²J4ÎB“ù,*• øK`ÊîMf-gá×n2 ,óµŠ~^RŽ^*%"õÒ4~;ŽìV“›ù8, kΪ`DÎ …?¦A‹QÜ7›+"ãSÿœ©Äê¹”¬q¥©f€²*³TÎK:±Ý`ô"4Æ„jŒÊbh˜·Õ™N)÷¹Èê$¢’õ•(ïIŠŒÂ­½Ñ hÿÃØú¥_í€z™ŽKv"æòŸÀ£K¥9³H‡2Mù’HĽ¶iÆ}:Iá†j³kªF+ °dÅð²J}Ɇ-˜!¤RH®‡eN<@¶Ì(ê1iCðCJ a©A72ÊA%ä ¦Ád&­’ºÍÝ(‡íH7×d)³%…p«iÌCÈä—Äz𕙤f3ÔIL5bâ}†z϶ýí5§Ã _†XþõÒ¦aWÁ²åœ½î(Kdò%þJX"<¦|òòΪΓ²²‡m±˜*ï¼2}e7YÅ\{ÃwÝF%£­”ÈvR¨ÀÊ4Љs£±”¨P”L(K¤€µ+ôdŠYû¡‡˜­>ýŒhöÇà+š‹,]ÉÌ²Šµ¬’ŠoSóÈEUvË=@^Î ¬¥ˆñGÇŠb€Ú̉3" »fZ`h¢V=‰«6¡_ÍÜS¢ë¶mK&•WKÀéw"¼K0–°kN”ÉÒº¹·g®VÝœlÞª¸A¹ÇÈ•Bÿ¶Ðlíd×dÝy™²hµ%…ª fàhe<ÖOmä•lø"à72˜pb“#Òmò=ÛœH˜K”ÖÞçq¥YO½Æ•4˜”)sâ5ð•¦Í ufZXy±ù›P+Ť:yžô€c»˜Pf°PlÊš?œÀvk#M´ëÅ¯ì …jTµqËT»åT*‹t9@‡lcëÜ{“º¯ÚXr4¡Vf›î M§T޵ªe’A OVÿ• pÚ!E(ƒ1£8`¬\|â[ÿu½ªXÐ9?UÇ·äÄNˆ5=hܳu›s"6u­V]Ì7ŽnD$“€-FO×ð+vÃ[²–yì=YÄ Ö?†M‚Õs(`‚nb“Cå³"ziÀ×ätPÓE3¡dUkOMTŒNkëCá—¥¦àä¬{gy‰b ‰›N'ZBDÀ40‹€1•ÀŠ\I5jQjfÏEqâš0½¡6&VG¢bVÂ+BÓoº–a@ñbSÄCå&*í1_4dÁ`8RÅ Ø8Ä=Ôùó°†WO÷ØQV‹Åb+1a'’2<ƒu%&—·ed8–SÓ‚AÄab½VM±>uóV ƒtp˜ ̵XÔÖá’l~×BÓFNR0Dãÿ˜v!n¶[‚ÆQyèCt5XB#^¼±6¶seZ‚zBñ2´+<3#”Å0‘”B1µ€'ƒ"uD0{ÂE !"rhœ‚?uck X HlÇõ 75|Aß GDpƒ‚0‘s1Fa` g¿R “W–„P‹4nn˜SsÒµ§UÊ5|¿Q9?„zø2sídg†\Â×n€Æ„ŽÑgC=2N²'éc_¿qz_Gäx3‹Û8x¶EZ1N±Øw‡ À$lA²’,‘i€Wï²|D8æDM!z¼¢VD‹ö¶Lµ#•#ÿ@™Q%b, ÒX[U#H§v:„¶³=[Ö"°§?Å(ßâ@å…Dy R©äzm–W9æL d(:!ËÄŽû–ŽÓh>0\áhDø¹ADc'Nl÷Åvî¥S~t$§— íAÔä±'ë“zt(‘c‚‡Ë2=4‘sIÊX#Ä%=a2±‰÷yå5óögë ¡ Ú†‰5Šzê…‡yòHH>ÕœåSdr:ÿs‘(j“Hˆ‡ÅqXÌyß †÷‚Ù2PÍÉ<ÓÂóƒE)ª)8†’B ÐÅÖ‰€m¤&—¥ÁVüb¦£´“±²ÂãæD˜}ré‘ã"¿é‹ƒpENJuLCpñäÖ±…Æ€`!G Ä* b³>"/€ÑUôbHSTî!+Çšn\òô5wó$ñ49hA  ô›ÿU/c!#íùjû6CçŸ]k9†$5­†ª{-к®ûº°»²;»´[»¶{»¶[º»»¼Û»¾û»À¼Â;¼Ä;¼p¼È›¼Ê»¼ÌÛ¼Îû¼Ð½Ð{Ô[½Ö{½Ø›½Ú»½ÿÜÛ½Þû½à¾â;¾ä›½p¾è›¾ê»¾ìÛ¾îû¾ð¿ò;¿ô[¿ö{¿ø›¿ú»¿ó›þû¿À<À\À|ÀœÀ ¼À ÜÀüÀÁ¬ÀPÁ|ÁœÁ¼ÁÜÁüÁ Â"<Â$\Â&|Â(œÂ!¼,ÜÂ.üÂ0Ã2<Ã4\Ã6|Ã8œÃ:¼Ã<ÃðÃ@ÄB<ÄD\ÄF|ÄHœÄJ¼ÄLÜÄNüÄPÅR<ÅKÜV|ÅXœÅZ¼Å\ÜÅ^üÅ`Æb<Æd\Æf|ÆhœÆj,ÆÐÆnüÆpÇr<Çt\Çv|ÇxœÇz¼Ç|ÜÇrü€È‚<È„\Èÿ†|ȈœÈŠ¼ÈŒÜÈŽüÈÉ’<É”ÌÈ pɘœÉš¼ÉœÜÉžüɠʢ<ʤ\ʦ|Êœª¼Ê¬ÜÊ®üʰ˲<Ë´\˶|˸œËº¼Ë¼Ü˾üËÀÌÂÜÊ"PÌÆ|ÌÈœÌʼÌÌÜÌÎüÌÐÍÒ<ÍÔ\ÍÊ<ØœÍÚ¼ÍÜÜÍÞüÍàÎâ<Îä\Îæ|ÎèÜÍ$°ÎìÜÎîüÎðÏò<Ïô\Ïö|ÏøœÏú¼ÏüÜÏþüÏ÷\=Ð]Ð}ÐÐ ½Ð ÝÐýÐÑ=Ñ]ÑíÐ&ѽÑÝÑýÑ Ò"=Ò$]Ò&}Ò(Ò*½Ò,ÝÒ%}ÿ0Ó2=Ó4]Ó6}Ó8Ó:½Ó<ÝÓ>ýÓ@]Ó(0ÔD]ÔF}ÔHÔJ½ÔLÝÔNýÔPÕR=ÕT]ÕV}ÕOZ½Õ\ÝÕ^ýÕ`Öb=Öd]Öf}ÖhÖj½ÖlÝÖnmÖ*×r=×t]×v}×x×z½×|Ý×~ý×€Øv½„]؆}؈؊½ØŒÝØŽýØÙ’=Ù”]Ù–}Ù˜ Ù,°ÙœÝÙžýÙ Ú¢=Ú¤]Ú¦}Ú¨Úª½Ú »®ýÚ°Û²=Û´]Û¶}Û¸Ûº½Û¼ÍÛ.ðÛÀÜÂ=ÜÄ]ÜÆ}ÜÈÜʽÜÌÝÜÎýÜÄýÒ=ÝÔ]ÝÖ}ÝØÝ•Ú½ÝÜÝÝÞýÝàÞâ=Þä]ÞæíÝ0Þê½ÞìÝÞîýÞðßò=ßô]ßö}ßøßîüÝßþýßà>à^à~àžà ¾à Þàþàá>á^á~ážá¾áÞáþá â">â$^â&~â(žâ*¾â,Þâ.þâ0ã2>ã4^ã6~ã8žã:.ã;rabbitmq-server-3.2.4/plugins-src/webmachine-wrapper/webmachine-git/www/images/splash250.gif0000644000000000000000000000326612305126066030545 0ustar rootrootGIF87aù´€ÿÿÿ,ù´þ„©Ëí£œ´Ú‹³Þ¼û†âH–扦êʶî ÇòL×öçúÎsA â`4‡Ì¦l):§T‘”ˆ8®Õ®7šÐj‘Û1ÒüM«ÃlÅ­„¯ç̱øh7äôþNGÖfg”Äç‡8#DZ˜øôcqxyy‚Wèè`i‰ "ùõ6Џ§T6º•+ÊVH$õÆ*»ë#ØÉ‡ëËðÉ[ì¦KœeÌ¢¬ÜMùŒ<-z Ë ­ êÝÙjý]îìMk.›Þ6]«W«Þ\ÙJ=.Ç. ¼Lî[ ˾bh^Ák”„Ì© ïQ(•Ð᫆å&"<¦‹b,þƒÿÝ:“%œF/ŸD>49’ÊÁ ô® LI–HNa‚Ã.%›¨ViÐÇÓX0+^­Ã%`»šÉŽòWášQ§Blí, f*ÕH3¬dtëš;œÒ•t(WaÇUÒšÈZ|·úa›- ½axwiµŠ¶/¤¹ÛÜPƒ+x ±gˆ‰xõ®ã¹XN ™éÒ˼¾mÌYMeÍ¡¿]ÚÜ\Щ±n ;¶ìÙ´kÛ¾;·îÝ·ñfæò÷<‹_‘§ëñÁ¯—7Éçœ_׿Ño˜­~‰:öÚ·ÿñžXwð,Ø'Ü.ú±ê×§Ùë>æÛøïù¶¥ßå<þžþôï%ÌfÿÁp_¿ H`N’!XBAš˜Q„ ¢@T NhŸIʶLþåvšTžp†è‹‘7„òõ™„&zÔÁ†…xׇ²1V"Œ?ÍH\Š¥ãŽ7â™6‹¡fº½–ψüÈ¡Š‚9y#X6©  !9P]èeT/…T$@§å‘–M©¦›.v¶*`Êy¦…Y•CVç,sfi˜žX$¡õùøÂDF)ɧÅôg‘&J¦NçÜi‘’îá©BU>„)i0Ú“ÔTgqghy–Fõj ßw2"WÇ@”g«ŠÖ(£-̺ `žþÒ—=:3ª ¡N‰ç †EmŒËâú…ƒ)@VP55­Õb­'flULM·¦0ðxö ´Ò^Ûl=g4ö,KšŠæfùäJG ‘뮚Úç­~öú‘ï’ )¨^Õ ¼—’Êi< OŒ,ž[V¬éVÛ,µªl ²kg½´¢¯`IR'ÂxT§®)ã+S<ÁÁeHÇ–KóËÿÒ®ÅqÄ óÁ¢…Ì?Wa™Kû`Mç9=ç}âCl/Yý3p†„œ;(Ê÷VcH˦"´RÏ*t»ö¸TO-¡y]ÇíuÂR—üöÙµ·Lêg‚ß³´„Ìaoß:p¬PVjä^êþמÿb[y€ÉäÓò͈NèOƒˆ7N¡‹BIT!òˆ—Ç©+~U„– ´¡Ôå­zPÔßÂì¸ÂÈénˆ±cŸ@ÒèGÖhk€YÑG)DJKt¢¤'7”ñŽ5a£^óÓ;N&eŒh)¥ÊH´¶mÛÆš5kxñÅÿйs#FŒ ¨¨h·û±ù1×/„B!„B!Äþ¢4÷¤\»v-Ó§O§G >œN:ð¿yófæÍ›Çúõë7n={öl³Ü›½½~!„B!võßÿþ—]eýhÒ›R!„øíRtC7W¬XÁÓO=ÍþðŒÕjÅ4LPˆe6AA9® Ó Ã@QT‘ ¿XÈìÙ³¹ì²Ëèwp?TEâe¨ØüÀëB!„¢=3f̤¢B!:Œ¦Çtf¾1“¾}ûÒ·o_LÃ$¢ $æZ<棄øœŒŠ¢`&&F,@¯ƒz±qãFÞzë-z÷îj'é´Ø´uýº®“›—KNNO<ñ^x!š¦É;C$(Š‚ÕjÅív“ššŠÛíÆb±H`„B!„BÑa´Å‹‡tè¡èºN$ÆjµÅ“oÊѲÓ41MÃ0ˆ„#` CåÍ™3Y²d ‡~8¿¦ØÔ¿DÞ¨ •«ÇãRö|ýº®³mÛ6¶lÙB0¤sa!ëׯgõêÕôë×U•Þ”bG{‰D"ÔÔÔPSS@nn.ÙÙÙÒN„BÑB8XGc †b±“ìucU ŠB!öжxñbúôéC²ÇC$AUULÓDU-¨–xBå×›ˆ0c[¸¸ûÆ|¼•»;À=¦F‰„#Äb1’=z÷îÍÒ¥Kéß¿?ORþZb“Tp"ËÞ‰b5 Œöb¡˜`B(bõªÕD£Q¢‘(º®“ärQTTDqq1=zöÀaw0=hEÇ+//gÛ¶môéÓ»Ý.B!~ã«xzÊ8|u;™ƒ£rÉ×`Ä”ç䬣{J²R!„{¤Ö××Ó¹sgT‹ˆF£!B¡¡`ˆp(Lõ÷s8*ÓËñÃçÜ1çrî¹'0yæ Báõe˸ol<É<Ù£™ýõFBá¡pˆ’oÞ⌼<É3‰e[ë…CT?‡+o~‰y³Á“ì¡ëˆ¿òíúL9¿+žd7>>Ʀcìüô—ñúÃWÅÏ•ìáá™_6•«ãÕ[ÏgÖêêx¹†bn<ívÖÔÖ󿤓y£&ÊY³}×[ÔA‚Á ‘pÃ4PUÕb¡sçÎÔÕÕìMl‚ ÅÜ12Ÿã‡ÏIçžÃ¹cÎåâ»gP¿Ûú¶·`Ã:îº`óþ÷f,_¿…ï—½ÏâëNfÚ‚-ÄbQ¶¯ü”Æp(Qöû•k ÇTŽºð1ØT¦¼õ%]s V#>Ì@QTEÁb±`Õ4RRS°Ùlñ$d(ÄÞÄF·ärõÓŸ3ý¥WyüŽóy÷ÝwqäçÂîê»›¸EÃ~6,x˜3.Yƽ WòÚ½œ{ì¡,p^ÌêóøÁ|º¦f—ØÄ6Ôðâë•ÄvŠïõ35¾ùn%Ï\ü%w-‘H„âââ6¯_³Xð${°Z­D¢Lä¡KìÕ«W'Ú”B!~[ŒÀZîs=x/à•G/¥ÀcoPlô9z<ïý߬|æ ž|ý:O¤®„—'_A—®=èÝ»'={ô k—n}àïõ¿Š-(Yø"ùùùíõ½Íþ3ÿrÄîËåç3å5íÖEo\EŸ~ýØû/„Bt$5)) «ÕŠªª‰Dœ¦iX´øfUUÑln2²²°ÖÃqãþÉ=¯-âÌCrˆU¯ãáŠ>\=úp\šÎOåǦó¿•ålÿþÈŸÌɇbÓÜñ‡+œÊÚŠ(M‡¼IÁ¬º(c&ަ³½õîÞÃÎåX·…‡ï|Ÿš}ìyX»q>£9š›Ÿwðò‡‹ÙTZJii)ÅË>&§äeÐ’Ñè2x«< ÀI_dMI 6l`Æ ¬^ö1¹¾£:#´=Ê­O½ËÊïÖóý²8-ÅJÆ¿±|} «—/äï—æQi¿®Åÿ£ó©ÓÈsÉýB!:’Öœ”jN©UQQ%ñ«]Æ¥GŸÃ•/àšáÝš’1°fb³Z°X0,©¡˜‰ ‚êÀªªXCS7âÇÏìîÅn‰o³9RQBñD ¡6 ?VU,µE"$¤›8lÖÄÊÂVUA!ª‚ª€½)Ii¨&µ1â×cªøt3Ñc°ùXÍ ç(ª‚¡X,t]Çát&z…íml0«y|ÌpÞ=ìaÜyEÙm}u£ý¸©ªŠ¢eâ´Æ¯_µ9@ Ä㉉¤éÎ,ª ŠŠEmŠoÏ,\Mñ5L“ÊÊJ,KâúMÓŒ¯ò­Ç‡¼ëºŽÝŸ·©ƒÄ^*//'++KVýB!~côHü_oš³ÍíªÓK¶ÝuÔ -é‡ßlàöÓ.a¹e8s>}ˆþ;>¸3zqíc³Xs资›rŠJÓ£H—¢’4-QÖ–Ñ‹?=w†ÝDëz#ãNêWQ0lN\…´BI6 ŽôΚð Õ Û©aÑëÏsö˜·pÈ<›B!D‡RU‹J(ÚÑÃPÝ©wž¦¡ijd w =…†Ë¦sçy¿]ÇÀ‚·óÁ\ž<Ÿ×?݈¦iÊqý›œxh 96_Ë’M4M£dÑ›|¬]L¿B7T*KÔÄñ±¨‰šfAAAÓ¬‰íš¦autæÔssøç¾ l± F¶ðÆ}ï2ê´ÃpkVTUaé†JÐkøÏígñ™‚M³bMJ¦[’F0÷‚´´¼¾¯7cQU¬Vk¼å^ÄF³yûžáܵj³ÿ=šÕ@×Ùm}³ Û[ëë·Íç‹_g‹ó7}Y ÐÔÓs—øj=I$[[ôPUvôD£;’¹òÌ%~ ŸÏ'AB!~£œV­Í×ÍˆâÆø(mž/×}ú2³ê¢œrÓ•-”Ík!S>|œN{èÕ¸fö?YaïKA²—³o‹w7 FGÞ±\{æAmn3‚%¼þv#úçÈMB!:˜êrºðâªh­uòËb!Pö On ñõCç‘—’BzVÇÜ8›˜VÀ½óÞàëËãõz)è&Sßù†ãŠ<¸óç›YS9}Pg¼^/‡]Á î¥ÀiÅj·U´#‰fS’;Ω( m׺Ø9õžÙœUqy))¤æþŽÚ«^âúSº¢Y=œxýÍ<2î0Ò³zàr;‡XUMÃêèÄÙwŸÏ„cz0øÚYÄ,­¯Okú+k(Äétbwر;ììMlÔH%ï¾RUSé——NJZYÝNy̶›úvn7nš¦áÕvº~‹Ú"VEAÕZ×E³YÈ*²`Ñ´6ã ùw$fw*ÞÜû- a·Û±Z­(’¥<à 4ˆk¯½¶ÃŽW[[+AB!~ctâÏÊÁhÛÓ)67yâÏÚ1ó‡}Û¦r:e¸[m«,ÛBYY~ÓFCy)µuX¿êK.ú‚/¾ø‚Ï>šÉ¤›þÌȾÞÊ5Ÿ±bÀdŠRäYY!„èhZAA•••G¢ÇàÎCŠ3>pä¼¶Ð}8³«#h6';ÿµÏˆ+.!ѱ;¨M¿ËÓ{aˇ;ÊrÁ Òüµ7³·¾Ñö¹¼=¹ùÕ-\b`ÃéÚ1´ô ×h¼œ6œv /¾,±í¨ñÿ¢qÜàZ±i †a`˜¦a¢(J|á™`††òóóq9ãŠÝ›ØÒ‡—·µ×ƒ¬ýú¦µ7ko^Þ¼ãú[ÆÊÊåï•¶y¦Ë¹Ûˆï_W®"‰?˜5_?&ñ!øºN8Æï÷sÛm·íuãY²dÉñ&ƒ¼þúëÌ›77HII¡OŸ>Œ9’N8UU÷{=Þ{ï=6oÞÌ„ ~•q”ž”B!ÄoOrF>%+Ñ9ˆ]'~‰T—òZu„Œ!‡ùCçp4ƒlüæ ºx[nŠùX½ð=œxË#¿¿žW§]M^Óöµë7³¶s#z} |:çÿè«ÕYòÎSŒÿ² õB!ö-//7RYYÙ´’uÓï¦!Î{yß“Ÿûñ‹o7ýc/¬»<£6/Ü…=#Œ]†Ÿ|îúX±{<ìËÓ|íÚ/X<‰'34¹ñB!Ä~ ¹’\tëÖ ¿ßOqq1¦iÒë ^¿‰Uz Ã`ݺu“™™I·nÝp%¹ º=6†a°eËJJJHMM%??‡ÓÑf‚rãÆÜvÛm8NyäRRRZ>´ÕÖ2mÚ4>ùäjjjHKKã˜cŽáŠ+®øQe ÄСC?~<<òß}÷N§“Ñ£GsÅWP]]ÍÃ?̧Ÿ~J,cðàÁÜqǤ¦¦îñúß|óM6oÞ̽÷ÞÛ*AÙìÐCåÐCýQu¿üòËyøá‡Y½z5n·›Q£FqÅW´ˆó AƒÚüÿÎCê›7aÂüqV¬XÏçkQæ‡ÔoW¡Pˆgžy†¹sç²mÛ6²²²èÛ·/·Þzë÷B!ÄoSZ÷X»äž¼{ Çü0§_|1 ÿ΂ðïxðù}|ŸVÉŽÕëèó8'ýY^{æR>:g#û´öm±µ½ŸºËB>ªÍ ÕœqÔK<ûõ}äX›ë³·Ïõ:ß¼ÿo.ºã\2Ô[!„Ø/4UQIIMáA‡P²±„Õß­fåÊ•RØ¥¬Ì,¬VësÁÑh”í•ÛÙ¼i3›6mBUU:è ºuÁív£*;†¨ˆ±‰F£ÔÖÕ²­|ååå(ŠBQQ¹y¹¸\®×߬®®Žë®»Ž@ ÀÔ©SéÚµk‹í\|ñÅ”——sæ™gÒ«W/Š‹‹yã7øú믙>}:III?¸l³ÒÒR&NœÈ¨Q£8õÔS™3gO=õN§“Y³fѯ_?n¸áŠ‹‹™1cáp˜G}t±˜7o.—‹#FìUìöµî7ß|3gœq§œr ³gÏæé§ŸÆëõrÞy;æy4i/¾ø"k×®eÒ¤IíÖaóæÍ\y啌9’O<‘ŠŠŠU¿Mš4‰÷ߟN8 /¼MÓ(//çË/¿¤®®N’”B!„h—+»/×=ñ-ÇΚĩz€1÷ý…ó†÷ýQÇU]]¹õÕGyí„ \vb_¦Îø§îŠUQˆEªY[¼:þŒÛTÞÔãÿ~¶xµ#:“¤@,¦¾b=¯Ü:ÇEÓÈ´îH2êuÛ(nŒjˆ`ì¦F¸”7^(ã’ åf !„û‰b6Ñ4LƒP0DEE%›6±½¢‚H$‚iš¨ªÚfïº_ÓŒÏE©( 6»¬¬lº’Ãéh3Aw ÄfãÆñkiº~«ÕJjZy¹¹¤¥¥awØÛ¼þh4ÊUW]Å’%K¸á†;vl«2ÿú׿xöÙg¹çž{8ýôÓ¯¿ùæ›Üwß}\zé¥\yå•?¸,ìèUøì³Ï2`À >Lû¤“NÂçóµ*ÓM71þ|Þÿ}233w“ãŽ;ŽÂÂBžþù½Šá¾Ö}úôéôí@Œ9’ÜÜ\^}õÕÇ¿öÚkùì³ÏÚ]¨ùx“'OføðáR¿¡C‡2uêT† BÏž=÷:m9äC䧪Bñ1cÆ Ž<òÈV¯¯úøiF\øú]ü]6’îy騴}fŽÔ­çž`â”—[¼žyØhnšp£Fôgû—Ï2tô=»=Îä™K{x% _dèèÛZëéÇ`P§Öê×ÿ_úž[Áw‹¯úásk !„b¯$ÆA¨ŠŠË墠 €ôôtêëë‹©„ÃatÃøÕ_¬EU±Ûí$%%áõzñz½¸\®‹ê´å@ˆÏïÇ¢ªX­VœN'n··ÛÃáØíõOž<™%K–ðÇ?þ±Í%Ä{$¦§§sÚi§µxýŒ3ÎàñÇgþüù‰äØ)Û¬G‰%€Óé¤W¯^,Y²„3Ï<³EÙ0þ|6nܸÇ$¥ßïÿAó9îKÝ{öì™HP¸\.zõêÅÊ•+÷é>æææ¶™ Ü×úíÌëõ²yófV­ZÕ¢ÎB!„?Dßãdzqíé¬Zö ‹¿^Æ”ë.£NíÃSïj3¸7l)Ýs탌þÓÝ46†Ñ±àp¹p;wŒ÷î2øRJK÷~±Ã.ƒÇQZ:n¯Êz OdéÇVIP !„ûQ«ì”¦i$''ãv»ÉÉÉA×ut]? ÅP%±ðÅbAUÕ¬_ql¬š†¢(ñ•ÉUu¯®ÿ¥—^âÍ7ßdРAÜ|óÍí–+++cÀ€­z”ªªJ·nÝøöÛo÷©l³¬¬¬V¯5¯À¾ë¶æ×Ãáðc’””„ÏçÛëîKÝÛJ”:νª_[ ;´~;›8q"wß}7\pYYY 0€#Ž8‚#Fàr¹ä§¥B!öþÙÓ•ÅàwCF0þÚüðbs“šþÓ/¨Ú¼dÙä¾ !„ûS»]èš“YÒ|”öò+ŒÍM2}þùç<òÈ#äçç3eÊ”ŸõZw7œ¾½m{“8îÖ­kÖ¬!‹í±7íþ¨û>½aµý·šä°aÃ8ì°ÃøüóÏY¾|9K—.åÃ?dÚ´i<ñÄtéÒEÞüB!„B!„Ø/T ØÕ† ¸í¶Ûp¹\<òÈ#x½ÞÝ–ïÔ©7nl•4 ƒõë×Ó©S§}*»¿ 6Œ@ Àܹs÷ªüþ®ûMhvDý<'t·Ür ¯½ö=ôUUU¼øâ‹òÆB!„B!Ä~#IJÑBmm-×]wÁ`x€¢¢¢=îsÜqÇQUUÅ»ï¾ÛâõY³fQSSÃqÇ·Oe÷·Q£FQPPÀ”)SXµjU›e–.]ÊÛo¿ý“ÔÝáˆÏÑöiÿ[¿úúúV¯õïßÿGÕI!„B!„boh±³‰'²uëVŽ8âêêê˜3gN»eO>ùd.¸à>üðC&MšDqq1=zô`Íš5¼ñÆrá…&öù!e÷7§ÓÉÔ©S¹æšk¸è¢‹8öØc8p n·›ÊÊJ¾üòK–.]ÊÕW_ý“Ô½OŸ>|øá‡üãÿàðÃGQFŒ±×ûÿØú9’!C†Ð¿RSS©««cÖ¬Yœzê©òæB!„B!Ä~#IÊß›ÍF$Ùc¹o¾ù€¯¾úН¾új·e›“”‡çž{Žÿûß|øá‡Ì˜1ƒ´´4FÅ„ HJJJìóCÊþ yå•Wxýõ×™7oO<ñÁ`äädúôéÃ}úH D‡êÓ§ª*?J„B!„B±ï$³ðc·ÛéÛ·¯ô¨?š¢(ôíÛ»Ý.ÁB!„B!Ä¢µõ¢aD#Qìv;¡Pˆ@ €®ë‰Ä–a8t]'ššŠª¨¨ªJ4Åjµ&zV‚ª"ùÐ_ »Ý΀¨¨¨ ¼¼\"~°ÜÜ\²³³¥¥B!„B!:D›IÊ€?Àwß}ÇÀYºt)ùùù,_¾œƒûL,cíÚµ 8ââb (ÙX’X”åÛo¿eØñÃp9]TVVòùçŸsÚi§ÁNkjD"*«* ‚¤§¥ÑÐØ€ËéÂn·ãIö°yófœ'‘H„H$‚ÍfCQ”Äâ>ŸŠŠ ÒÒÒ¨o¨Çåt …ÐuÂ.…`‚ÏçCÓ4jëj‰F£äååQS]ƒ×ëeëÖ­x<²²²(++#‹ár¹ðx<444PSSCff&ééé‰óy½^‚Á ªª’””DeUéiilß¾Ô´T’=É8λ9†a‹Å@‹ nè`ít„´¨EA×uLÌVÛUT4«†ªªäææ’••…Ï磶¶ŸÏG4Å4MygˆEQ°Z­¸ÝnRSSq»Ý²HŽB!„B!:T›IJEQضm«V­¢¾¾ž!C†PVVF—Â.Äb1jëêÈÉÉaÑ׋¨ªªÂív éÒ¥ ˜F<ÉåõzÉËËC7ôIòòrÈÌÌdݺu†AQQÛ++IJJ¢lk]»vEÓ´xB³²’””5ž™Û¼y3iii”––â÷ûéÚµ+6›h4Šª¨D¢V®\‰Õj%“™™IÀ`ÅŠtêÔ —ËECC©©©X­VJKK±ÛíTTTPTT„Ïç#‰àr¹¨««£ªªŠÊÊJòòò(--%‰âõb‡òòrºvíÚ!7F7t–.]JCc†nRZºÕ¢P_€jQ›z·Æ0 Åxl*·o'‰™•…ÃaÃ0vÞn †øýáƒ),,â«~{½^¼^¯¼„B!„B!ÄϢͱš†a“›Ë€ðz½Äb1 ÃÀ0 t]ÇÐub±™™rÈ!tíÚEQ°Ûíhš†nèÔÔÔÄ{@¶1Ô0 ìv;555¤¤¤àr¹0 ƒh4JeS¢R7tœN'n—Ë…¢(4Ô7‹ÅHNN¦ºº]×IJJJ ?OJJ¢±±ÈËË#¯SMÓ¨©©¡{÷î„ÃáxÀï÷£ë:éééôéÛ‡ÜÜ\ÊËËINNÆëõbš&@|¸z—¢. 0€p8L Àëõ¢i†iÄÿoÑ0 £ÃnŒ‚‚ÓåÄðÎ;³ˆ„#|AÞyg¡P”T/6» ͪaÑ,hV•uë¾'Œàq'³îûï‰D¢‰íMÅ¢Y@_“B!„B!„¿ŠÙÆØ^]×ñü${’ihhÀãñÐØØˆÇãÁÄÄ×èÃíqãkô‘œœL$!û Ì¼ IDAT¦Çp9]¬V+>ŸÔÔTp»Ý-æ¤lN’iV ›5Þâ«O†¢(¦Íjv {Öu›Í†Åb!c·ÛûZ­VLÓ$ ârºç2LƒX4†ÅbÁb±`š&ÑXMÓ…B­æËl^nš&º®£ëz‹…Ab±X¼îM½<›Ë67w»Ýrc Ã`ÅÊ<÷ܳœ?v;wFÓ4–-[Æ{ïÏá¬ÑgÒèóŽ„1›æݺ¥ŒcŽ>–E‹Ñ·__¾^ü=zõ ÓwÄÞïg@¿ôêÕKZ¿B!„Øg3fÌàÈ#”@!„¢C´9ÜÛb±ìI 9¹å¿ J«×l66â Åæ!Ò©©©ñ2MÇÙYs™fV«µÅ¹w¥ª*6›­Åk͉Ã÷U¥E‚@UZî«(J"ù¹kÙæki.§išÖ2D;¿sÙŽœ‹À4M蔗ϧŸ~ŠišlÚ´‰³Î:‹üü}hV ‘(˜¦ à÷ùQT•ªíU‰Ä­B!„B!„¿dZ}}=.—«E²Oì_¦iÒèkÄ¢ZHJJj³Lób%ápˆ¢¢ÞÔÕÕQTT„aèÁxRT5±évLÃ@QävÊåã“äJ¢®¡†ƒî h;å}£Ñ¨¬ÈüŠÅbl6‡C"„B!„BÑmÕªUäuÊÛì•^w?‘X,FII IIIôíÛ·Í2¦iðûñù}ØívÆŽ‹®ëÌš5‹F_=‹}ÍöÊ ôX|ñ­)Y]]‰ÓåbîܹìXà[ÁÄÄÐu²ÓsÈÊÊB×u¹û™Ï磬¬Œüü|òóó% B!„B!„8 ¬Y³†h4JJJ ¡PˆX,–X³Æjµ¢iV«5ñ‹Å‚®ë„ÃaRRRZOËÍÍ%-- w’[¢û‰Åbdgg·¾k™ç~ÄwÅߋŸü‹Ï0M“H$Ê–-[øÛýoµONN.ŸÀŠå«X½z57nlU&))‰sFÁ“ìAUT ÓØ)‘Ió"à{MQâ_m­¤(ÐVÞ»½×DV«Ã0:l®R!„B!„Bˆ_‹ÅB^^:uBUU¢Ñ(@€P(„ªª‰eó—jQ1tƒ`0H$iu<­¨¨H¢ú³Ùlî¶ŒªªtïÞ/¿ü’p8BZZ†a°ukU•U 6¬Õ>)))CA¼^/ýúõcç{k¦i’™™Ivv6±hŒÍ›7“×)/17§iš„Ãal6[b#UU‰Æ 2±Y!§KAü“` ²2L@UâçÓu¨o0q»L¬ÚŽädM­IZêŽò‘(D"&6›B,j¢ªàp(fËíî$eÇõ˜;ÎõKæñxðx<Òè…B!:H,D±9±H(öJC]N¯KÔOm@%=ŵÿNfFØVº OnIÚOÿ°^¿½Œˆ3‹LO|Pãvjò²“;ü\ûëØf,H½Ï$e/î“ñð÷´Y4XMyUŒNÙ?Ë{¿eÛÒ©)+CIÉ%Õ¥m«#Þû­IÆ"4ú(šÛ¾Wm¸Ñ,x<{wí±ˆÌ·û Ö±¸I²5o×ñ×5bu{±ýDï“tê1-6ÜW‡½, ªªîHHÚ¬¸\.|>@MÓPU‹fI,h­£·¹ ´³º·øå0LC70šº*ªªÚîÍ41ÑcM7[‰/rÔ, …HIIÁ0 Š‹‹±Z­ÔÖÖRUU•HLF"’““ñûýQTÔŸßÂÂE:ÍSY&%)de(C&ÛMªkMr³ì6UU…FŸÉÖr“Âüx’ÒnWðL¢Qp8 {W•u ‚AG ;S!5©­‡,*8 ¹Ù ›J jëÀn»-ž(ÍÊPp°™^S!„âçñ³¬îmÖ3uÈát}a §õ”‘*{üHÚ¸ŠÂÞ#¸þ‚“yxúFM~ŸGÇöÛ÷%ÂÂWÿÎè‰O‚uŸ¬|‹®I?]B«|Ù[L<÷ZøtŸ»ŠÓûxÁ òß«†rý{ù_Ÿýxì­ æä©…,~eVEi'9±—î»›[Ÿž}ÀÞÓ×Zδ[OåþW+H?ò,|õ\ÊÏÛ¶Œð&®t,kF>ÊžÒî}ú5¶­{ÿí' ›¿âÊÏfãØ4÷}N¹óE¦N8G;×S»q>yêYPýò èçO奻ÿ@ún‰:oÝ2˜ù‡½ÄÔ³z´ùÞxíüè¸ò=®92/þRtã>šqsÖ0¢ëþ_‹â‡ÆaÛwó¹wô%ÔŸx>êœé,°]Îûï]G¿NI?º.[¶l!##ƒ¼¼<4«†Ò4Õ`ÀïMi³Ù°Z­Øl64MCQ•DOʆ††VÇk3Ňihlhÿ–é:Á`0>T‰$Z3¿ßO0Üë ‹F£-¾7Lƒp8ÜnyŸÏ×j{,Ãï÷PskªŠŠ¦iñÔ›oª¢´ù¥*ñ̵ªª¨ŠÚr[Sfâ‹òdddàóùp:äååaµZQT•ôŒ ¬6ÉÉÉddd 6ôê®’•©àq+&6¸“zvWéÓKÅë‰'(u=Þò¡zvSÉÌP ãÃÁl6ÈÊP1MèÒYÅáˆ'(ÝI`µ*¤zÁj'5;(X­àõ(dg*8ñc${rs$½.„BñÛÒP²ˆ)[üüë¥Ï‰þ‚k7~ɲÍþý¾O{Œp9 ojõzEñÿè|ê4.»á*Žu[Èth?ø{E±1øÜ[™9åà(â§îp—û»?0å¿SHtlRlô=w"·Üs=™®¾Ç|ì“_¿õ Wþù÷»M")Z£¯¾ò€¾§;®5— ÷ÏæÖ¡)$¥Úø©û¨´Õ¶‹‡‘×\Ç-çý®’}:Ëç¾OyÀüE´­{ÿízã*®<ñl:Ýý6Ÿ?û4›×~‚úØ%ÜóÊò6ˇ«–rðQã8ò‰ÿ1ý¾IÌZ¹€CgßÄØIïjã÷‡.åoçœÉœoË)<|8r­¬ùäi†L˜NulGy#X ‹‹8éàü›0jô?)©SùýÀɱU3óÞsù×G%¿˜8˜±R¦œ{)ýÿõ /?4‰ÿ|WÌãgÎâòIó;ì÷¨¹Ó ÃÀ×裱±Ã0£z›s†;w¦kK›M¨xM1±hŒ””TU¥°°uëÖa³ÛP•ÚÚZRSSغu+éééx<ÒÓÓÙ¶meeedffŽDHöxÉC»ÝN$Án·SßPË•DaçÎ,ÿö[ÒRSINN&ÉĆõÐ ›Õ†§i‡Ã¢(ƒABá˜àv» ‡ÃôìÙ“ââb|>iiièºN²7™NyäiŽøPîæä­¢(dee‘••µWû:-PÔ%Þ Âa§£ý†ePYe’/SØYÁaWhëgaaÁžÍäË-B!„è,zý/¬œþ8+þ4ŒCr¬?{­ÂUßòç‘çpÎ;Åün?îÓþƒ¾™wŸÎ‚/2øÐ–I‰E¯?ÏÙcÞÂí áÑT"šöÃŽñ“Zw2øYîC’{×ùþ-ô9ú\ú½?îqÇ»Åç¨` O¾•ÇCwä챬Õãþyï©aÉÜ™Ôçϰƒ3÷ë½Um)ä:¡ž_DÛR´4N¿üÚ9vÉÂç9åªÏùbåˆo·ûÚ¶:æý×ñ–ϞƂðïøpdÿx»puåò{Oå´[ÿKF>M¯Ô–¹… _ë †öïœ(É”«xþÂ+XtÉ:Ž.t´jgÃ/ÍÜéeÚ«s€éŒ¹äFî;‚ä³n[õuÇ]@g‚ªtaÜ)ßòЄἹÈÏßÚÎu·œÍðži¿˜8Dê¶SÜ£O¢;é~ðáøWûˆ?ö·¨iš‰EG"‘ÕÕÕøâSÆb1¢Ñ(III‰!á»}¿ïúBCc JbNBEU…BTTT°­|áHUUq8lß¾P(„ÝnG×õxòRÚºZl6>Ÿêª*¶mÛF]]]bŸòòrü~?v›ˆé1¬šF8!‰P_W®ëD"Qjjjhll¤ºº:Ñ{Òî°…QU•­[·Æ3´f|þÄÌÌLÂá0Û¶mkÕ;SìhDÕÕÕ,[¶Œ@ @$Á0 "Ñ¡PˆH4B4M¬þ›”o3¨©5©¬2QˆÆ ºÆdC‰Á÷ë "Ñx9Ãð&ÖRƒ†F]‡h´ynI(Ýj ë ™ÄbÐÐ`²½ÒÄç7©®1©o0‰ÆâÛMãçÅšŽoÛXbPQiRQiR[g ÅÏUZ?~4Öòœá°I$ ‰Ñô>òûMêêMÂáø¹ #^^>B!„øe‰Õ.ᢗÿÈ;3ÿ Ñ%<ýÞò6'‹g=F~~>ùùùœwãC,ßêßó6 äë79¥kgòóó¹òž)©b«YüÉ,þzù™L{û=™ÐŸüü|޼ì!Š«Â„«–òÇÃOeOçOÃzpñäw ™>þ¿óÈøO¶†Í6^míc¬ZÅäËãÇøÇ;˜÷my|Èí+SÙ Üqãåüý¥|òÎSÜxÃeœwÓÓl›|ô\÷R9oÝq ù=.aÑÖP")ñúÛŒè¿#)®ÞÀG/ÿ5ƒ—ðUSÏÀ]ñÅÚ-,þd·]ñ7­þ:Q¯»ŸûŒúÆrf<ø§D65ìýg®Æ²åLžpg_:žüü||}QÓÄW±žÞx’óû_Âôÿ>Ïù’ŸŸÏO̧q/¶·¥¾¢„Ï>z•óÝÁ¿¹Ç6Ð^ÝÚº_ÛÛûì3ªªª‡ÃñÞ•í¬ØÜêÏ.N‡“þýû'|ÍĘèi±XÐ4 Ó4«÷lݺ•üü|lVݺvÃf·¡ F©®®¦±±‘ž={¢ë:XmVš†"[Tz÷îM,Ãér&zH:t]GQ”D7ÑæåËóróˆÅbX­VLÓÄfµQTT”F±;ìò4×V»ÆÄçó±eË*++ã ÁjÅïó‘ššJcc#@€ãŽ;ŽÔÔTBaX¾2žˆÔ,ñ9%órTB¡xb¯²ÆdýF»=Þ‹Òb‰'ú*¶›äå45zêëA7L²3tÖ­7Ø^OzvÊUñLjêLlÖx¯Ë¬ ¶WšÔÔÆ°Õª€ Y™ >¿™HFz’@µÄ‡‚—o3Y5ˆDãDzXš’“$W|h¹Ã¡ Y ªÚÄá€úp: 9Y¡®Î¤Kg…~}d:v!„Bˆ_Šåï<Ê™wÜÍ!‡¥sE®“iþ‡›Î´Óœm:_¼p WÎ9†¥ë·\Á‡œÊŸü]˜÷ïÓYÚî¶QT.þ7C/òåÊMxë–ró‰g1tNˆeŸÄÚ…ïò䜯àÃO¿öOýþU.»ë!†/ó°ò‹ ù×k÷3tÔm<4ó3FöÎÂNEq1ø„c€}׌ýZícõ­æÂ¡'sáÌoØò8¼vû.8ùf|µŽ!cnÀŒ\ËÙwÌá¯gþ…îÖÕ¼öéá,ýìR²ì GŒ}ˆÿMŸ»nãγúâjZ@¡rÍg¬0™¢"à²(¼r÷%ð×™;ç÷üíì˸þo0ïߣZ#¸m9Sþ|-¯UGxñãu¼ôÆ«ôí÷WÜu.ÏÞ÷?÷³^ÌiçÝδ'óÀYíŇóŸšÀ£‹FóÝÒЋ_§ß §2è5¢TòÅ«³ ¦‘•ÿÌÓ¯¼ÊÁÿžÀ£“Æ¡§¿Ï̓|»ÝþÀYýZ%жo^ü×îgAàø¦¡Ê»k§¶[·aw½_l+þ¼Õ±?yò$Îû¿#ùߊtõÔ2ýÏ#øÃÑñô¼Ué±rîc|´°†.6xíÅ×èþòÜÓ=œ8ìMz§ª`Føæé\8~ÅÆà=Üw#üóßS{ŠF¾½eJÁ•w÷>PMÿã.§ß¥§ádáÌÿrÛG+8²0‰ªußðʯ¸m™ºï—/â™IÏP{â#M½¾ö­m3àþ;e£ï®`öÇÿ¤WŽ‹Òå öoÛ²ærñ¤»øÛÐã˜æ;…+ïéMåퟒôçL<«j¬†ÕŸ¼É½Ífsý“o3ëå.œvÞíûÞCrõ£|8÷¿¼tþù\>æ¾Zz?ì­]¦aÕJ?U)t@‹•ó·cŽcÑYO°nË¿±E¶ò·¡ÇñɠɨÀ÷?ͯ¬¦ÀÛúXzC=}FcÍçu¤˜ÑâGªÒô‘}ù÷Û9£ËÞ‹±(œËšòFz¥ÆçÉ´XâÇ/­ µ:.å¶Qg¸â9æ¼Ð“ ©Gc¼3Ž“ïÌá‹â·èlW0‚¥¼þv·ÜîÙ¸i.§ž}=½1‡¿¿?‡^cŽaêéçòÆ]ðâØƒ~qP´|®}ißœr)WŸþ{n{þ3®Þ¥C~7†‹ñÝwßñég Y²buÁ(v{Én'n{˜òªÍ¬ý~=ëÖ­ã¨£Ž¢[·níNÓØ*IÙÜõr×.˜n·›H4‚ÃáÀb±‰Fšnr|užnݺµ(ÛÐØ˜K1==‚‚‚ø 5 »½uòÐn·ïx]!±"òº\.LÓLôøs:;.LÓäI® ÉÉÉtéқ͆aD" ;wFÓ4êëë›Æ× û[hh4ñùLüHö@’K!'[¡ÑO^Ãñž¡l-74P%Ù­ðýƒ´T…ôTP- î$‡C¡? Û+ 4­y>K…Ü=Ÿ—27GEUÁé0é”=—K!Ù/¯iPWïmi±@Q¡Jn¶I}ÄbñÞ—6[ü‡Q,ORZmÇçÔô¸ P 3#~ IfºÊNMI!„BüÌŒð&žžjcâ§ÝAQ¸à¡ë˜6æÞüäjnÙ€PÅbξsÏ|ò4YvlqçýãùŸÙcû’v·iz%¯^ý=¿‹ÍË5̪‹Bݽl\Ĩ1gqó£³yüÝéœÔÇ ‡÷ç…Æ-\øà½,ÙrGd¤œš‘X9vô?ç1<`!«E/ÍFÆ.û,}e ôã[[ÌÂEsÆ÷{eÁ:†ŒíÇà±wpÅcp÷Ù‡s·óD>\Ôt@Rz]¼é)x›>CÎ’wžbÌø—q( ÐMNŸ4‹)tο$Ÿñ¯•á×!u—cx=C¹ûõɼvâøpÑÓôNU1º_DZ¿KÁ}pá ÙGÆ>Êã_­#tf¯vlh‘ uZ;ñx<ŠÂöXüs^4#µçï;~,Ϭ¬âÇÓÙ®pÈ#o±ý«á¼7c)·Ÿ9nÛûîr& =Á¹5_óägU{lÖÝÔMÑ’v¹_n<»;°õSΛ´ž;^úÝR­@cxœÊƒO}ÊžÂÈaÇðè|?óÞGÏd•~ž»¹ÿÕ«ØTÙHïT/F¤”—_)ã–k:%®aw÷Ÿážš±¾`|]ÍâÃW¥¾±8ˆ‰Ñ¼zrZ“yãþ?pæÐû¸÷¥… íOet߇zìÅψŸªm)ZÇœy)•‹žâ¡¦áçûÚ¶4›—·©ÇÒ­ §¢´j·û£m©ö|®™1•iG]Î1}^§ç˜iÌ>³o|µg-‘—\ÉiÎ ÷Þ÷¸ñäƒÀìç?Âcú-¼zËp) ãî=‡ço´ù‡˜ø9 ùû¼Ï ÛÒq( ›¿x…iuGñÉÕÇÅÛ•-ƒ†¥0§)†V—‡ƒò2q¹Zÿ1’’pÛ,8- ¡Æ¶[Á6^.8˜ÎÝ÷ü‡þOŽ'G«ägn`pŸÜ6êœÏ£Ÿ/%5=…9÷ÞÁ݇òâ=Ÿ2ôÏáÄû®rÍV ˜L·¦^ŒÉE#Y¶üt2Ò*ùÓ¥O9î:¦³”º˜÷€ÌƒçØL˷ƧnxãýO}Ta‹Ÿ'ûªy¤î‡}¼ū Fr²2ÈLO%-ÅMR’ ‡ÝFc]%›ËˆÍŸªªäååí]’2‹±qãF¢±N‡ƒh4ŠËå"‰ ‡q:Øl6ÊÊËIöx=Ãá0Ý»w§¶®¿ÏOUU={ödõªÕ†AVv~ŸŸ¼¼<E¡¼¼]×q{ÜD#Q¬Vk¢g¤aÄWúÙy.J¿ßÏADii)Á``0ˆÛíÆçó¡ZTòróðüD£1ºu늪ȲωÆl”o+'ààt:±Ùl¤¦¦&æÝã|dg)‰9& ƒ«jçdïÚH¡WwÓCYnŽJ; ’“™±çÞŠ©)»ãädÇçÊT•iؼܽ‹Mv–ô–B!„ø¥+]ú.³¶@§éO¡Àö%Óxøö·¹`ø dZ"mà<‘ÙÍl s7ƒ†o·»Íl`ƒ?Êﺧ1b±df̘ ÄÈÐ ¢Áxç ›Õ’Hzòùðà'Dc1Œæ>æŽÁ•Vg Y»ù£wbÉQS3Ȇe_Òëô ¸•øç±®#cæI1’r:5%Frùó+S™vìå¤:•î-žãçõGZ&u_~¥Œ¯ÌoqÞ¼tgâ û„§–R†T­õ1- ´t’š?ÄZ4<šŠSiyÞPccon¢b㤛?ç÷[âC_}÷ËøÒ¦ãé‘À·EurÂØ\^{j•q{ÜžÑÆ)ûÀnÛ°Ûºµ¸_mÛÔã£{ìèÁ¤y ùÉiÜûÁrªï;kR6hU8šªh-;ãT­ý‚)“yr§{»ûûþÓßÓ†oÓ÷¸ë[¾øéY¼s׎o?Y³…®I ‡7%X§ùNá¸CówIôýÊÛ–iñíi[à#½«»Å¼€?EÛJ.:™™SÆñlj/rþ¨Ã[ û5ÖsŸÙ<¨·&æ l¾/»[PÉ›•—ˆ×ê/ß÷qµ3ue—Áçð×Á»Ë„UòXO'OË6×§_çÖs@&ÌG/ü…áþ…¡?вnm.8e!5=þ‰žÃnæ|·Yé¶D»\>ë)ιèåD¼ÍMF:˜1'O¼Ÿî©Tg:i¿ 8`ÖóòUÇñÞÑ“ùö®CyãæÓ¸÷ÕÛøC£¦§†|¯\ù/úŽú té”IvF:i©^¼É.’ÝIØí6²3ÒÙ¶u Û*JY¾|9^¯·ÍN‰­îL ÀjµRQQArr2‘H„`(ˆÕj‹¯Ø ª*N‡ƒ`0ˆiƇ{SR0 ƒúºzÂá0©ii8N¬V+^¯—úúzjªkÈÍÍ% ¡( ÕÕÕ˜¦‰ßïÇ0 ’ÜIX5+Á`¯×‹ÏçÃç÷SSSƒªªèºNcc#ÁP§ÃAee%ªª’œœLii)6›H$"OqmˆEcDcÑV«°ï uù_E!‘ ÚMPv$U‘{,„Bq@2kxó†©ÜýÔkšaC”#ž¥ ÷Jîzöaæ~3ޱ‡g¡â‚à\6V„éÚu—v³¦gÕA‡ÆÃ[.,‹Å4¶NPY,¿`OПÃïÞeåÝçŒ}Àÿ³wæqQUïßY™aP7qßÒ´ÜJsÏ¥ÜKÓܲÔ2sksIÛµL+ÍÒJ-K-µÔÜ÷}ß W@@f˜õþþ@ÔoúKí¼}Í gνç>g¹÷ÎýÌsžRv`SdKÚW7z­ëƹ=lóŸïJäÜË+Xa7ƒÊÿ޳6æ©s{î!Nü:ž®cbñ޳¼úîª4€£ˆ0lþAÁ¿F-$Ý¢ü–Ï EÍÿÁ¶|{gÓ™¨k´ óÍ‘u(fTƒ33{ÍEö͉uß0lÒÏbÄÝjÜÿ?ÇT_îIÖ®] ¨P©2YÖïyt›ÊÔnU±g¹½NËêsN7lN0ýΧ?õâÛW‰¹åÅ6߀cn9ÉJßÀÄWæòôÁw(}“WE¾[W7×c,`KÁéEŽHŽ>Îßqi…®ˆu8ø•©HéPç6]Æ ïÚôä ¨ª-Õ‡,§½ËĦ­ÙÒà#T,:uz¥f]¨tÓg.k<+–^eÈÐà‚ˆª8^ì}_öƒ5å"ãV&1okkŠûûñÒ7Û ,݆‹Ö“`êÁÿŸ‰)v»£§£HH±P1¤4%‹aô÷Ãhô%À߃¯½^‡Z­¢xñbÞŸNBB‰‰‰ìË-÷óõÃÏÏR¥J¡R©°Ùl¨5jvZ­–¬¬,OFôŽéüt­3#ë¹§ÎóÐxåÜ~·çTi¤,G¶a±+ÐiŠAåÞG‰F¯$vÑ+ìw–'³…Gê ‹dö¢žøX¢y½ÇXæ-û…CúóRŸy=0Êc+€¯çXNŽ®û†þï.( xùæµG­/ nä-÷h¬g˜üî"^™½“¦a¾Xb¥ì>¸é¡:çxr§Ö§fÇø+óI^Ê-9¸’Ò‹Øã}~´˜Øë¶lS{ )–ã”q:.¨+I˜œ„4{”@ ¤ÕGÖx–-¸ÂÀMùØ]æ¨;÷{?¦j}µjyæx•þdU«EÕˆJ„±uŸ<‡vüB¾ŠžÅkô`SËÓ´Š0þc;\÷ÙÜrýã¹åGìÁ+ù§ÿ¹•xt½ç½Àïó¡{ÿÉLù¥-³<ú¯×yûÈa³àPøà£ÒZ·:¬\Èå䉔+çS`ð¯ìŸGï1+¼ÖÛåÓu kñ ,ú„ø”a/áîÇ´«‘`èî¾{ŽkC¥ÉuUTitøádË·˜Ÿdeþ˜vù®V‹•NwË阵“UúÉ|^âÎB þÛýu#Î=ç”9ùBŒ´yqÌBªÉþ>ÿhÌ­V+gc¯R¡|IºwhA@€¦L V«ƒ?ôzô:’$Q1¬1çO‘ššZ¨HY@ÍS(($…Ç Ò×× ­V‹R©Ä××­Vë‰M©R©<Él|||ÐétùêÉÙÆÇÇÇ#,*î2ZC@@¥J•Â%»Ðëõh4”J%µ½Þ-jæÄGÔëõøøøàãããÙV§Óy>׉`‚…_,T*4j ’$\@ ÿI’ؽ{÷]}@Î`ù¤ t{»U>Àþ8o5 yÏ;l¼…Gx¥ŒŽuÓú2pÒìܳ™ñõÕ¢uª×óZ^¬"Ï oDòÞiýütv=Á¦_¦ÐìåXuÌ»¿s_$NÀš|‚/FOçw^#Ü_ìp ‘g/pbóbö_Jaå”'ˆ¨1„È…g'ηϖåø4 @Ÿ–½ùmÓ~ïYÍ3õ:Òñ­Vè±³nZʰžv=ÁësÞ…k_0õçÃùêÜuè0çÏïcźÝ,[p…g Í+…ûAø@dl¶ç•“K'ÖŠrêøcóE®_Ë’³Xât`r¸ Q|ð,UuØó¹¬—Û 5q<ÁB1ÄÖí›9é‰ wêÈ>NG_ô`ú³QnÉ%fßïLÙyƒ±/>–í]Zty΃mjvÌěũ¢æG­«HÛ Œqlf¾º}Ë7bFŸ2¬œð,Û£ÜeY G·2‰W‡4Å'Ç>G:YÙ.t9uªUZR£ö³J÷UK庋÷kLó ‘vdœvGîN8º€!+ûðf÷&t:žNjú÷œÇU»û¸wnGÑÛÒòÙõïÎ- W/Y<öü“¹å°×7r*ò ë—oÏŸáùÍ-—ù£ŸŸÌ’e}y¼å |9¸+'<˦ói9£ŽÉáÊ#p!ß)ó K9}ä²^âÍ5¨Tm'“]TjØ€®m¦pð|Gw.fä¢ϲåZ=¾ **Êëëó^5¨òDO:¨™õû~œ€Ëżñ‹éûþ`ÂýÝdÆn¤BXÓ×^ÈwÙ:ýÞßÎG‹vyÄr€´ kˆ Ã¤Õ·Ì®}bã·ô·ñeľúÁ¯tUšû)Y¶ý¤Ç7ÿü‘]P|(ƒþy²iY–¹v#“öO5æ‘Ú• ¯B•° øêõè|}ðÕûbô7b4P, •"*c6›q8^+̇Íf“/^¼(_ºtI¾pá‚-;vL>uê”)»\.Ùn·Ë/^”###åÈÈHùÊ•+òéÓ§åsçÏËgÏž•£££å¬¬,9þr¼'Ÿ>}ZŽŽŽ–O:%Ÿ;wN¾xñ¢|õêUùêÕ«òéÓ§åÔÔT9!!A>xð |áÂùôßË111rdd¤|éÒ%yÿþýòéÓ§åóçϻ˳÷@ K–,)ðŠ/ðš7"TdÔõåÏ–îÍ-‹‹’Nìã.Ë~-Ù}V¾xl½<¼±¿ç³W§þ.GÇÅÉñññE–ÅÅ‘?î]:·>c?yýá r||¼ü÷ÎïòÛýI>—½ï¥Èírÿ ­ Èõ^ýVŽŒ=/Ï~)XF×FÞx2ºÐvØ'.F^ÿý[ùŽñÙÒ]Ùí|FäÁSWËñññòêoFz¶é9áw9:.F^úá³îÏ ÝåeË>•)õ–™§mŸ nâÙçÍYË䥳ßÌ×–›ëøù§érs?¥ È¡íß–ÿXó[nß©ëËß®Ü.ÿ6mˆ§Ža,–çyߨý0yýá rìÅÝr¯@ Ès7ì•?ϱC]_ž»äOÌÝpBÞøÍ+žýëh2 µ|Ÿ§ÏŠ*?¸ö[½¨ëË_-ß#/›™ÛO%*¯?|Áûˆ;]¤mùÇëkya!uÇ^<(2¨¬ ÈÏ ò¤ù›Ýö­þÚcsH‡ä]»ÿ;¨=ûOx¾”ÜmƦ›æwãþÎ\ùÃAÿΘæÚx^þ¢s)¹ÿ¬mùæöÞ»÷)ù†|,6NŽ>ügîØ”|C^½ü«;²cèäoå‰Ï—ò¼ø¾{Ìþ­¹õåoÉ“{7ÎcÏb9:.îž[G7~íÙç“%[ ·wsn]<¶ÆÝoº6òÊCÑr|ÜQùõrzÏ1§ÿø³üÚÓÅÝïumäÖì—Í|ÙSÞüòê¥_yŽÚn˜¼ø×Y7óϼ-§åø¸¨|ãZ¥GO+?ÿ•|!ûZu;¯sþt·O]_®£QÈ=Çç^‹Ý×ëoe@~iÆ&9êÔ.ùË÷GdϵQòª' Ôçéu}yËß±^{q·ÜÜO)ÿv(ú¶mÍÙïßî‡øøxùØÖŸ<Û·n “1ö“ÿÜsöŽÚâíµvíZ9ü±®òò¿6ËGO•Ÿ8#ï;|R^°d¼jÃnyÇþSòÑÓQòùØ$9:áºü÷ÅËòˆ#äÕ«WZŸ$ß”÷;Ý”NLtŒ;ë³,“a2¡×ëIOOG­VS£F dY&22—Ë…¿¿?‹«ÕŠR¥"ÀhD­QS®l9Ž=ŠÑh$11‘âÅ‹£Ñh°X,( ¬V«{ù¸ÕJhH‡‹ÅBbb"’$¡R©p8 &“ Žàr刋‹£bÅŠ”,YRü„-@ ü ,]ºô®ÖפI“»T“«Å†K©.d¹uQežšŠ %†ƒÇw(=z Õ› aÁŽÓ´Ö`v*ñÓinòŒ´iÏóùm,÷.°`·˜È´:ññ3z’`Ün›ÍV´~z$[Éf5Aú;î·œ:îjHy9ƒÚÍKïÌáÛ©c)SºN§ ‡ÃŹ‹—0 ðÇÏÏ€Ñh@£Ö’‘ibÖôiß¾=µk×.P_–øü G­Q»³ngǣ̉ý R»—o‡„„`4‘eÙEe¶Û¹R©¤î#u‘(_¾<{©±ÍfC©Rzêt8žeà’$Q>¤<Èàt:=ÉrTj.§ ¥R‰R©Ä`0 ×ë@ ‚ü(Ñz UTøÌ`‘›$G‹Bãƒ_!ûI*~yŸ¬$ ·Ð² î¨utÿ[›õ~ÙÏG#AšXÇ]Ãɶ¯Ú³§Îl¾ÎNT‘·ÿ%•†S•=¸’Qª”øh ­»EùݘÞló6^…áˆïZäxÏÎ…»?¦÷ ÏÜÒê ·=Ou d›¿êȱ6?2(Ô'_[µÙåäÿ¹Ÿ ï}–Ó×JCUoѵ²#Ú÷fÞÊìkz‰ d?ä»îÍpËîp  H¸]E‘$dYB’$$@©Vy´Aoz™õõuO}Z“ïo^êÖ­{KCsöË›V<'f¤§îìX“9Ép”ÞRAçÉ÷âçç'¾{ @ ‚{ŠË–ÆÑÝ›˜¹t-û5'¬l1Ñ1w@>«hXôƒqê•S¬þáW0¥±wßZ>^›by2 ߪ\ æ–˜[÷’’Gž[IË B®—²ø GØ».…Ø”l~¹!í þ—¼}xcËß^³ƒÿwúáŸawÚ—ìt “ÙÑ/e\ ¹@’qÉ2²ËÈH’äÑoF%Î@ @p§ü5g ·ž)ðùãm»óD³'¨Qêo£Ý”Œ3¨3+VtÃn·˜NhÙbçÒÙ{‚’b·öܹžd¢Áë?²bŒ„9ý©&Å´ÚÛ.ˆ¹%æÖý7>Ń ÿAGvZˆÍ û¼%<‡ƒ¬¬ëXårw”æn!©tˆ~ø§$_NÆf·c·;q:8.,–,4 >>>h²¬¨ÕZ”J;v›³Èº„H)@ L&>²Ã†Íqo#ƒ¨ 牻’HÖ-Žaµ˜HMM½åvw×>é©©˜2îã‘ÖAšùÿ÷Þk6¥zæ´@ð_D¡P`4øp1&—ËÝéÂérà”]Øvlv«‹5 ‹ÍJbR":•ªð蓊›šË—/##sãÆ Nœ8ÁáÇùáû8sæ *õ¿Â2++‹ ™^ýßÀÏÏråÊaô÷ÿïNHIAñâÅq:Øl¶¾=þþþ¸œNÊ”)óPŒ‘R¡$44ôÎB:Ü'h5Z<Ú€bÅü,š …‚%J R©Ðjîï`܆ P·n]¯7‡a<Š+†^¯¿û_ÂeÙã¡©ÓëîÉøÔ«W’%KÞמ” IR©Äb±––öŸ¸'*UJJ”(AÍš5 C­¾?¹ª”*‚‚‚¨W¿F£ñî_«µZp¹\÷¤þûõþT¥J}ôQÅ ðÍ„¡¼ÐÿeÞœ4ƒ”ÆCøj݃ïîr³ž¬ËšsèŠ9ƒƒëæ\>ŒjÕªÑçùZD„U ÷¨V·:ÎFñó{¯V•÷þŠz š–•xœI=»ìyMüqvYÆ–z–{Ö¢zÍ:Ô¬YЈô­Y•-1ùW4˜Oóå˜z„GÔ¤õÀ—¨S³Ë—ç—M§oK¬¼¹•¡5+ñÊ”ÏÞ ¡µ?äÔåÌÛ.8¹üý|m¨ÑâkLÙ‡¾½•ªE0üÓ©ÙBäÞÕô­Áºsé÷`^]cÖ 3~ÖT5¬ÏS¯þEV!ýå4Åðã¤^„×~Ϧ ¦R…òüºãâ=Ÿé±ûé[3‚ö£ÆP­j8/ÏÙZ¨}.k£ë„僜צóE÷NVOxЉk¢ÿNeG?OjHåÚ/òÆ€z„Öþ‹7ì^mÛüeïBÛ4eÙq<ØŠ$Rš;r*2Š«‰ÉDÇ\ÆnubͲbͲ‘e¶’™‘IÚTâb¢ ÀÇǧðï­yߨÕj,X@Û¶mYµjƒ¦k·n9rƒÁ€ìúw^¸٫ôt|U.Kë¾Ç¥vžÑ– Ý«ÃX·x-%}þý ]ÖöŸ´ÑèÑ[ßw|JÕaò’Eԙܜó.3wÃiÚW7‚œÆ‚·ŸcÖùAº8ŠÒZ‰Äó»Ýi3b¯Ae÷s^ÒÉ?¨×þUBŸ~½‘/RÞ ÙÆß;Ò¦w[šÃoïuÀàeÌeG<ÓžDíY;údyøüVNiÁ÷ë°ý›¨œ—‹,WK.ó9fO>̤Ogà+Ù°ZM”©ÙrZ kòj5ëË»‹v1ôÉ ¸ÞÀĦ­é#©ùã½øxµ+‰Å³f³gû¯lËpòÂ?V'Ç7l$¨i[ÊèÝÇ<·~ŸÄŒ'ú×^\îý[‚ 97œìü±/3Î çܹ^è%‰!=fÓ¸÷(ê_AeÅ=™CNÓi†µéI¹‰òsﺸÌQ oØ’Iþ+ø´wÝÛ_Øö KÏñåìfè5 "zÓ›|øW3*–Òz^}Òïuê¾;“І­¨SZÍÙó°HêY} T݃k„laÕ‡yku?ŽžNI•uÓZðd+#G÷ §¤:ÿ1ÉÇyqê&ϘE9?-v™'yyäLÂË7Á¯74¨U‰?·Ÿà·U[)W¦$ÅŒŒ~hmjÔ·÷´ÝaG¡¸z%ŽÐàÒ^5¾|W" ‰Ö­[óå—_z„A—ÓÉã?ΡC‡Z@ @ð„§–ˆ–éS]Gìú¯ùjåß÷ z½“¿¿À©…³9™x„T°&Ÿàµö½ˆË*Bä‘ml˜Ù‹W§ðÆÜmŒè\ßlñD¡ âé!3ø¢s)2 6øaP)°ýÛÏ^rË'vfѹ;i é¨V¿“û¿Ùæ»l)œØ“F‰|5îÏJE4åóŸÞdïwœn—ù“žŒýøõ«An@ÒPý‰Á¬ý²§¾…ïÖy÷ú³¥&qÆä@“Ç–Jµ’y#ûm”œ^÷«T­hÙª%½z÷fÀ€—i× €¨½¿ƒº>Mk‡¸ÇMÆÀiÃ9õý+ˆõ¾„YRñüëïññç_Ü•a‰Ù;Ÿ×bWæÎ­[7R×ݲ º0°s]”…ÌÁäËYøÓxD€â%Ëý0ɦ{·"îøê9l³Ö¥ûÚž~2¹#‹&}ÉÙ7­‘-ÄÞ¨ÊÑcÒµs{ÚµkG»v­hòhc*wlGˆ¡ à¨ÐÐj@Ž,œB§×2±WSæm21¾Ï£ø+ïM›2ãv1ln<“§?ã$% Í_œ ‰Ÿ°ê`BíãÏ_bñ޳ êþ íÚµ£Sûv´lôèÚШFIq<Ð( šï\€ ;—²*ÕÎóc{¢-(DU{ê9šû)ùbü:®{Y&¬ â‘5“ú4â#ñ¤Äîbì˜?è×ÿQô’tËr—õ³'®†ÄOx¢~-BƒƒY°é¦ØèªÀ\‘ «ÀÉóWoÙ· %fïOté:ˆ/Ï"Ù%›ý¾Kω7Ë\9ø=M{Lˇ—绵»ø¸W]F.J võzvíÊÈ™; _/i ¯Lìê¼óí6ÒL ¬øî}›|F­²îPDéÑ æûíqžÝ’£w1´fEºtéÂ#]Þ`Æc™z»K”e gvî¦DƒŽ” È×°:íÁ²3q7%“”t´z®{>ODÙ‘ÀÒ©kèÛ£^ážÓ’Ž2¡•ˆ¨”»Z °J‚ËÏÞÞÉÞ_ß&¸ÚHþN¶{®‡×¹¯ƒw¥÷èéL3„uçn/êùo|´ž-ßtAJ9NËçG3uåqz× dÿ‚¾t뽌Óxî_¿ú&Û2œl:•Áfþì¹nãâ¶éüdz‘ó:’Û™&cbqqgÚîÓóXŸéÔù¦Õ'¼Íøî5Ðûi‰9ãNdzõFÖíœTœn³ßgZ§Qœ]òM—¼Çóþâ¹¶µ)_ÖÝWÎlG>cñÂc9+tFJi•`¾@ªŠ²ª^Róú¢9í0ˆW;?ÀÛów1¼U…Û*WhÊ0eÆ_Ža몯øô‡=¼Û¿%ªåéÓ° ;`ÙÀÙUйãï*•nûãS³îʯðx/^ŒøŠWWH·@X£¾Ly!’öïÆa“!¤N/~›vY½ùsª”Ö£xr3%FµgÖõQ̙߃¤ñAIÓ>bÌáN|öA_–~M>cïb÷Òo€ŒäX.\s âéÑ©Ûl_¯<ȳõʽ•êÍú2dæ \Öx¾?… ®ÂcÏ^¿äbàC8¼;•âmJ7"»”íáxü|ÏÔ.z¹³)î(óMO²½j‰BË]ÖxÞîÒ ó+?²fAe¢Š=ke_ž_š=gþ Dcãò±M`J !ýCª—Ps`ñ º~PžíÇî/³gÁëô|w ó†L#3n7o½ñ#šÐÂc,gHáônT˜äìvèÊ2Ùn)HËŽV}Kß9õî›ÁÿŠB¡@¥RQ§FeÊ”*Á£‘\¾šð¨K IDATLzzN»›¯—Ÿ†²AÅ ¯X²eËb0P©T…æ5Q€{™wNÖn­¥B‰ÓéÄh4b4q:ù²{ @ ‚ÿ.͙Ĥïö0ûíÁü°îoœ@@ÅLÒ€Gà¯ãWÿñ±\ÖKÌ›©áõö•@*N¿é#Áô;+ò$ýÈJ`Ö{1Ë2¡4`⤟‰¹a%Ëϲïß Qõ»”pSÒP¥i«|íTe¯|WI Òøà'A±æ„—@§Ñ¢ÕP̨F_Ü£N‡^ç=L€BJ›6xÞ§ÙÀ‘èÜD>eí˾{ÿl3X=íMB:~I‡GJàW6Œ^,2HJ Æ’e(Y²d¡¯òÕƒP«@§”È2îýj¹˜‘Û§QùÙž….õPhƒùj÷–|’ø]ß³,ÒE×I;9règ·W®¤£ë{9pø$-Ã|±&ï§ëØ­L™û*áþ @IÏä9WU”©^Ök»Ê”ôG ݉(Wð|÷1HÜ*º§)î(óoÔ¤‰áU xÐ ´Z-CËÓ½SK†õïÊàçÚÒ³cS:¶jD»–ÍhüøcDDDˆ’¢ðsZåp8°;(î@x”eù¾Î(*@ î-^™L‡W /«ÚrKZ¹kÇŠ?ò«’ÖSná·” éð¾xçOúµEIµ„Í|tmˆ(•í³%ihôüDéÑz-s™£ˆÊ´S·RqÀÃáÏÒ¥Ë%T.ì·§‡FàNÉ£O¿Sw`w8p©s’ÜžT '7ðçî(´Z-²5’õ»ñD±Û0r(¨ó/´v{˜{„4+ÔàçÈóDî]Á -DZ-à Æ~QËi—AåJhTP¶2XæðLãê´~u:Ÿ¾Ñ=ºÈvçx†eæut‘4”úß„CÙ:¼½äOoX@‡A“9·øm”,Dzq-pbÀâe垤ñ£ªAÅq8dûW-æèZ d¥[iܽ?uÊZùex Ö>ñ)'&<ʲq˜¼ømž5iX?§'Ò‹.¿éy¸Bƒ¾,Ÿ¶Ÿ®SvpÕÜ…°ŠO³iÁ{´zñ=šÖú8ß¶FU¡ãÞ);žåÝ%ƒÀ0?ÔEláÍ–ó›§ÓfL*kÄuð{:Ás-û±öàïÔ*¡ICpEwÌM—9‰;nðôGÕóxû91;e4¸cmö7ùÂÁ5UÖás“À˜sÔ )Ú‹2Çãð…¯káq¨¤X û‡‚ÊOã?£{i{`®Ë²B@ÙìÓ)+5€ÐÒ¹ž’NgnVn}ÙÇxgÊcEÚ¹ê0ýÄùËrÓ2î¬ô[ÿ¹}•»ö*¼ nJFƒJ¥B­V£P(Pª”¨UjT**µ •R•}Î9½jŠªÐÐPl6ÛyGʲì>¨¤£!@ îòuVŒšÉĹKx´„' =öåË cÂ_°áh_ú4 B,ˆN´–?»xQe9Fê×k@ã†ù³¶;̦;rãó+•Þ%"kF"[¢|€gZ Õ+t@âQέÞNì„g¨ìëg¯|â Ý *T’;ãöŒ~­X(dãÉnlù§F&YWP­žÚX’1]ú³ñëQlüå<»¶?Wd»¹Ké®Enä¢Oc¯è ’†:m_âĶ Ôn>€#‹’2ªþ%Üq:c¢¯á¤j¤/¶”x–¤ØéЈÒzçcþæX´_ ®Ç¤R«S_¬)·2‰y[[SÜß—¾ÙN`é6ŒX´žS4¶¢Ë …Œ‰N+º$úlçĪ-Õ‡,§½ËĦ­ÙÒà#TÔ“´¯à¸ß+|Š./l"g°ëûù<1qµKƒNcØf  yï÷Øuú*µž,_èy—áå¼ÌàØ¾#˜d…å§q8T¬U›Ò¡:ÎmºŒÈ9óÒ“ÝBa`€¶Èväxn©Yú¶ú¥R³.Tº•˜¢Ì9 wã´¥ÆpðD,R¡‰«8¥´…î뮸îã•=Ëç í¶láµ×Wõ¼f„T$Ir‹”5µ[°ÌyI’„B¡Àé,úæ¢Òëõ^V @ Á¿IÚ…L³½Æév1æy¨0LfÂC˜öÙ::/é‹+Ûê×U{ybDs·ç•|¹¯~Aƒ—÷ZöÔ/¢WJL›öm~æIÚ½c:?]ëÌÈzîã©óˆWÎíw{f–6@Jþò ú²´Qß›”‰æeð—¿óù/½˜ýJ£ÂŽ5å,Ç®iPÙýÞW“G$Që!ÛÛ0fׯL߯ªcƒ(©–¸n3çÕH åØê_ jû?Gžfë‚è;þŽ_êPd»ÇwT´°ZlhušÛ?5©¼üözöÿÚÅ#Ê ­L¯@ KœYà‚ò žæ•2Ÿ0çë9ׯ ÕŠåw†9°z6ƒ_l†^ÒÑöµOi{ó<9ïNö¢Îމd¤Í‹“`ÞRM6J™‹.Çß§€ívk•Ûv S*?œlùvó“¬ÌÓ½$>îyPáûè²Y°âƒN“;¿•Ùã©Üc¯ôŒ¯±¯äýn¦0[dG—Ï[(ß1׎ðÆíèø1—Ó€òÙãkA¥Ó!eëû7%mH}Œ’„¤Pæ±9‰Ïôu{òzaö†ÓÔhñ ,ú„ø”a/án_ÚÕH÷réÒ¹ñ,6*Mþy¹}!m ÷8̱óöx;1[œèud‡û:±çD<­"ªæŸ€åÚqzõî½*]6n|ˉ¨$Z†UÀ–z•%)6>­Q:OŸÛp©4ùlô¯µJ‹‹»à¡%'¤¤B¡@¡PÜQØHá )@ îOä –Oš@··[å(ŒáóVÓ’÷¼ÃÖÈøWx„WÊèX7­/'ýÀÎ=›_¿Q-úP§z=¯eáÅ*òÌðF$ïý˜ÖÏOg÷Ñlúe Í^ŽePÇÜLÜ;÷Eâ¬É'øbô÷t~ç5ÂýÑ#òìNl^œ' wÞ'6 ­‡þ@ÿ -}Ѓ±s6lvd Î\Ax–\•5!è@dl¶3£“K'ÖºëQ‚Õî%7n;ÀÅÈ-¼?v8Ò9}è —S³—­:ÒÉîQi;É’í1 ùñäó©£Qàçv[íÞuè0çÏïã͉Ý3ðˆ0fmŠñ2^Nïú3»Íîv¨}K’²kæïœõ8ùÂ9–¤Øh8è)Jj%$U†ý:,hýÔ\¼aÍ®ÏÆ±UŸÑ{Êvê½ú=½yýèWº*Íý”,Û~ÒãzþÈ.(>”ŠAÚ[–Ÿß<àˆ¬?ÀÕÈ¿èZ´‹VÆÛšÊׯº“Ò¨Uù½]ÖKŒmPƒˆƒ8q5Ë Çô;;'&r-_™¦ßY³óvYv—_ßÈ©È3¬_¾3`3ÝÚíURQ¯c M[O¼Ù=æ„K,I±ÑâQ·@™pôgÂ#"è0i5Yº`žéW–ä=“ùé\Œ½ÀŸ³?aUª móO'**Êë«Cu#UžèI§5³~ßpY£˜7~1}ßœ2c7R!,Œék/ävsNr™çëð8L»°Æc§Y¾E`KÙÆº©OP9"Œï·Ça(W‹Nj¾{½ 6çÒù}|øì«¹×•ˆŽE¶)*ò;ª…6dÞˆP>»œ«Vp²mÁ((õ”ζ?ž «Ñìå…˜òعãWBÚ¾(–z ^"¥@ @ ¸/Y7­-v\gÙØ7Y¼'.Ÿð°eî§|²+€amj³ç²?c×þÁðÆþlýaÏ÷|¿1‹˜Ò­ ’ªŒ×2PÒlà|Ü»4Éû¾ W§§éÿaë·}B9m®0oܳ„^÷iì/ýÀgýëàWº&ýƒ´|òRÆ4P½|á«Ô”†*LÙ·—Ùú°ôƒÔ­\àà`ÊWˆ Ç§Q¬Û–ÎÕ,úp«Ríùª³ÿÜÏž•³üå%0ýΔ9Ûy´=Ô|9²;ý¾ˆbðãÁ²—†ocÿŠ/h=t!X6ðDÃw9qÕuZ¥Öóyÿf¼õñ' ¯ß–*ãШ¢¡Èv+´¡ôÛS?Œ¦EçÅT® ؼŽUVâqÆu„‘‹Ü¢*Ü…ºTÔ¸N §rùòt á‘Öè>æ[æÜãeV¼RkÎ^ϸ–‹x²V8M&¸|GìdÚ¢Í,{³M‘Ëc•†*ÌX5ùóç ­ø ºDÐi"ü¹z$%ÕÒ-˵z#X60¨ÓãÓmúYÖ:KÃrnE[j ËœJpùªŒßΪ'è÷d…[ObÙÆ®_§Ñ¸Ç$¾ýè~XyûÍâše—¯[ oÒNjÆôzЦ½OòãÜI`èŽ6-™L'”®Öì‡éݦ5I%õüú拌[™Dìêô}ù N'zË4®¤ÝØßx¿Ób¯\žÁƒ»R¥Q/&ÍßLëÊn¡UÎV¶O­8Î ›š6¯þ˜ÅÙøõk<Ù¸9'\¡ùjT©4h4Þ_J@¡¯Ìç~GñuoB+>C§jÍ‘‡~Ï„n5<õ8³Ó»›2sc’šâ0?ÉJóÚå ´Äfwojá\âM·Î¾cǽÍá¨dú0¦üöu4 Þíß&OGø«}óõSQmÒ¨T ih7v_=·ŒGÃË3 KUÞÚÿ4›Ö¿äù1Ev:±8eb¥“ñRv$°jæz>ß@,õ¼ ɲ,‹n@ wÂÒ¥Kïj}Mš4¹K59±Zl¸”jtÕ”Azj*.” ñ,=z Õ› aÁŽÓ´Ö`v*ñ»i¹³ì°i/ø¹7ì–TRn˜‘”J´ú Ú;k¢lÜúìã¶T¶°~1›Ì¸T:ünÊ]X»=ûdXÑúé=ŸßérodY üt*¬f³ IãWd›Í¦TÌ6 ÂXÜXDÒoí4aGƒŸA_Èr`ï囋դÒK›)‰¨Ä,Ê”-Q¯¹»'“œÁ‚aÍ»‹–a¾ Û0e8Ðô(qâD™ÏN«Å„Ké—oyø`µ˜°Xøø³,å’•¸›JOåô¡áÙ‚›{ÞHZ?|—Sÿ 4Öðq÷ªw|^šLf”ªÂ3ß¼|[vذØèuºBkËJÜO¥v»8qdÅoc~œ\ö"§¿Í/ªzÎÙ ‹½Á€-vû3oËiÚU6Þa_ZpB¡v:lì7-ã·Z,(||îpN ÷/—.]B£Ñ ÕjÑéthµZ´Z-µÚ4G©Tz–|;N‡ƒôôôõ©D— @ ‚‡%Z/ÂFÑeàP0#In’- ~…ì'©tøÝÁ“•Z@i]ÀÿÞDIƒ>O3n-PºÛ®7n»Ýž}üò{†Þ‘@™m«Ÿ.g_ZÝ­wÑÐÿƒñ×þ§r•F‡ÁKó4† ªîÅ|u²í«öì©3›¯+ê=}fð¢, ´juÿÌoã ;âù }?æ/>˜'¼Bíîeå¾Õÿ4.ƒ¡›t7SO¢‚v&ðAûÞÌ]tð¶Ê„£?ÓþƒÚÚW%ß9›cŽÍêÑ V©þ‡¾ô>¡U]Á¥¨íXî-@ …â²¥qt÷ff.]KÔ•¢Sw:}Vñí+îïº@ÞØò7­*/ô\8²yKRl¬]½¸œ¸¡ÿ ¼±åoÚW/~[[«Ôž³GQZ[°ÓcXõó‡ìÜw’L‡Xh*ü›OJ@ @ (»)gPgV¬è†Ýn!!1вÅn3£°@p;()p_X"©tx3ÅnJ&C]‹+V Û-\KN§|±’÷…ácôRâ$%!ŽÐ¶_³¢£„Íbáz†ßµ˜–Á ²,#Ë2.—Ëó7çÿ9Q&eYÆóÏKäI!R @ A!hÃy²e¸è8ÊsAIXÝf„‰áþ19Âc^RFÆ%»PÈ $IÂ%»ÈÎc%DJ@ @ @pÉë)ér{Q:N”J¥û½äòlêr¹p9Ý^–…!DJ@ @ @pǸ\nIgöÓéDR¸³zçxNº\.\²Ë«'¥Hœ#@ 6 NÑ wŒ”Dn˜È —ã®õ€$¹öºli$¥˜ïhŸ,S W“±Ød\¶ RMV1±Á§Ó™‹2[œt88NN‡Óó>G¸tØØöBë"¥@ @ x0Ó˜õd]ÖœËx ÌŽÙûÁÁÁÞ_5Þ!Öüÿ+ &œü‹ª†RµN}vÆdwðGkÔmÑ™D¿ÞM{eG?NêEHX Þ_uÛûÙ<‹JõÆ2îÉúD„•'$¬*ßïº"ÎU@ð߸-Ër>2g9·Óéô•»»ÝŽÍfÃn·c·ÛqØ…Ö'DJ@ @ð@s€iq™ÌZ´»|ÿxû݈ÞDZXïBY…F}9½í;Úý‰³11DEEÅßÇ6Ó_IJ¦ãÿÕæ2µ:0mñ44ÙAÀJ„5áíS¨TLû@̇»i¯¤ ¢÷kïÒÜOIIŸÛ‹ŠfMÞO«?fÕÞy,<¾c{P·JÐmíï²&°÷Ð%qb ‚–œ¥Ü9‚¤Ýnw “Ùÿ·ÛíØnÒf·‘eÍÂ’ež”@ àAÆÉßßàÔÂÙœLtÜVY“OðZû^Äeýh%)Ý+T,¯J…F£A£Ñà_¢ C|—>ÿÿ¶/žï½¾T†H¥êbFÜm{5Å)¥Ub¹Mý;%úºSÊ(¡Ð–¡ûˆQt PcwÜÆÜ”3X>±3‹ÎYÄ©-X”J¥[€´Ù<ž”Žœ¥ÞN'6» ›ÕFVV‹³ÙÂë7P« ¿n ‘R @ Ü÷8n¦ÿ/]Y¹üs°fÞÚã7’mZõµguïÑÓ9~9óÖe@ÌÁt !88˜a“~"憗%…C;V1eH7æü¹–/×&88˜&/MçL²kòº6ìȶ 'CŸŠ`À§‘u‡žgWÎIm ÊÔd$žå¯ß¿£ñì:°™ÑuÂfæ²c¹q8‹l£…ÃëæzÊš¼4CQ×óõÏþeŸ\ñtíB÷æ=E.[gîdÚ˜!l:Ÿ†Ë’ľͫ˜òòK¬>p‚¥Ÿ>ç>Þ˜ŸH²æ¶1ùÂ.†Ö¬H—g+ñH×wYºv;»wì!.ÕŽËÏ "öØÃž={صi9ïùd²3‹S¾fÓÞù<7`3]\»ϕbÚ˜Iœ»áºew|׎gFG³ýd4q1G¢ú‰gŸ¨ÍºsiX<ˆn“­ì>±‚—ͧo÷R»ì¦dömYÄÌÅkpÈ€®_XËw­å•®Oc®ý g¾ÎŽÅoóÝú‹î7æÅ6½©÷áOe åÙ6Å™¼þ8qýÝõ•.á›[îãO9;„¢Ýy“­TåÝdW~H‡Õí¡™|Í~h´îºµyôH¿À@ï+ið3V€Ô½$˜aô—(Y&Tþ¨%@ò#¢’È×øö¹á̘ØC¶ày³½9ï½U^\–$¶¯Iæé*¡Î®/oûd[F‘óÂ&GnYH£AÄîN`ÝÜ·òþ"†xtU÷±2³›tÉ-¸ûk(³bE$uY´·ð΂ …B$IT «ˆÞ×—¨‹1™L˜ÒMdee¡Óé J•*T®R§Óéµ>HY¹re|||D @ þF´Zí¿çÌ _gŨ™Lœ»„GKhpÒc?ðìÝw|uþÇñ×”í»)¤‘PBQš"HÇŠ"XÏÓ³sö†zÅvžwêé5Ïz‡õ΂gûÊ©§è‰‚ ŠØ•žlŸ™ïïÝ, $€Šåó|<ÉÎî”ïÌî̼÷[ÊŠ§pãwñêÒÉœ9¢?D_euUœòòö÷5ÛšF:Ï6t8cF´•Ù²,"Í­ë±ù¦Ê0:¨%ÞRż÷–P–“ݸ†=i7ÝI¶ËŸ6•./‘æf<¡éüfpÛÑzÏ÷ùªMŒ/o "Ýäf»À㤷s«A]\ÃèYÚæ.èl ™¬^£¹éØ|®;óŠŸý=Mÿ¹‘îÇü…ýÊv|´í~ŸÑÉœõ£LûÅ@øõÓüúîÿÝ&˜ûäÅ»¸çëÝó#ºíÀ=ëŽì«ty|°º{óŸ;|\숺¯þÃ~‡žËEw¿Èúu¿ç…ëÆñF'e®©ß&qåö¡¤e+0$¨BìzÇA)…i˜t+)Áï÷Dq¹\x<\..— ·ÛÝé`9íÏsiùùùR !„B!Úq»Ü„B!<Ïÿdù_Ígjâ N8†¡Ã‡3|øp<`84·4 IDAT?þéÍL½ãeš•¶S >=gáæAZTÓ/»¯šN[qðS§þ“MÉÍ Òê·îäOÿ·&ó·ËÌÔï`ËR5»†¶šÞsôdf?ò0ùË_¸ûág¹hbŸö7`.³ýßnFt9'tk»åwd[ÛX‘Hýý麚v¯I4Ût?è@òÜ©ëõ«¶º4¶Hè6o«ÑázøÒy™f2tô`u2®–M”ý4ó<5SÓÀJDIXoWnÏA\Rìcò1=ØT™àÊ×?á²#6—Y¬j¿úù“义˼ë?œÏúˆêpßl_ÙD¢ ÀÀoh,~üýL•šžz,àN½~GŽ‹ö B¦Žf ¢¼|ç¯è~ì½üú¤ý›úu±­^Ѻ¬’}CôUü¿6B©(3u ‹7ÆåƒH±KÒ4 ÒŸù¦i’Ÿ—O^^FúÄ’š¾ãó“s„B!„»&ÕÂs7ÝÀI¿>¢]Í:€ìÞ£¸n\5 ®çåõdõ<€KŠ}¼â®«áøë¯ w–޲RÁáò_ñÑë3YTîxSÒ•ûÞ^ò1õñÔȧ‘H3•«?äîs‚÷œ‰¸´Ô šÕD,ìµÎßez¶¹ƒúáî3‹ù× ?â¿«Rë«ü€kÿUÍå#¿{êµOÿö8ÿï š›+yé±›!ù>?õU•¹9\»1ÕŒ;Q»š9 ÉLÖZ¶Ö¬ Wü‡~ó“ö/#ÊÂmÕ±|ù*šÒ©_˯†dâ¯;õü³çÏ‘ŸÐ» ›ì,?-V²²"=ÐŽjdÖï.aYÂáž[Ï ‹¦¡¬jž¿ýy¢Š­Öw{û •àõ{¥_ßrþþ®Î)W U·rÕís©jnæ³·^dVm‚7þû*+jºìÐqAó3DÒû*Q»ž9 IV­k¢µ9wÅë/òÖ‡_òÞ+Ó¸á­:–¼2—w>ZEk]Ì·—¼Ï—_¾Ë¼•¹œSèaƵÇòÛ^âãÞão—ŽbF—+ÙM* !v]Z›_t]'  ÛL×2å(¶ýeœ¦”ôÂ+„B!„øffÏž½Sç7vìØ­{ùö±\pïZp ãŽå´1e© *Á¼é7ðÓ[fdž;ëXÃS~Âß4pùíÏpÕé#qiñšO;¦¬jž¼þh~ýÔÆÔ̲Ê+ónd`‘—¦ÕspÐEíÖkâ5OpïÏůiØÍ+¹é ü£:ÎÐËdƯŽnW“`ÍÂG÷“›¶¹ý·=÷‡»pÁƲ„C÷cþÄS×à¶c~œ†$ù#/eÆ´«èc¬ìt;œx%Oýé®{d§Ÿ{.OÿýïÜô×¹ðˆT ÄHÕûÜ0á'̪MÕ,xT/¿5Š›ÿ|:ÃÊ"ÜqöÏRù¸†qïS·°æî3¸óFðM`ú?.¡þí;¹ö¾·¸ó¹÷8©ÿ&Î~\»Á(ø%K_I¡SÁ5#cé„{™{û1žS±à.Æœò—­?þ÷/ðÇCª|pªì † §§ï½÷dÿ”þ1†»'_–Yßûf=Àø‚¥ÛÜW¨/O=Œ î]KÞØ;Xøô^¹ã7\qïœÔ2†ºÙôA‚‹®¾•ãN8ž!e±N‹Š…O0æ'¿ Ç¤+¹óŠÑ¼ù׋¹on¸†ñàsÓÙ§ù_zÆïRûé¶Gé¾þQ®½ïmNÿý ÜzÎ=þ NùÍ :™WçßFid S&œ‘)ωW?Â]?Ÿ°Õñ$„»ŠuëÖQPP@qI1¦ifÉd2IccãVͽu]Ƕm¢Ñ(MMM[ÍOBJ!„B!Ä7öC„”ߎM<šÀ1\øÜæ7˜M 8„rB™†Î­!åco}Êa¥n"¶AÐ×¾NeE '·~üû³íí7ÔÒ·ð†òÈöo]‘æº/ˆ×t°1:iÔ½}Ÿ¿þ~ñÖ>̾~“XñÞ•”ú¥ µBì 5Ð~úé§xæ™g°m;óœíõIiJq !„B!ÄÖ’Í5Ø…Çóüó'‘LF©¬j¢GIî·®}¸GÑ|wí|Fžö%k«ê/ÝÊ(+Éßáò1B™öáÇ\µü+ª›#¸C¹t/+§0Çó½í+o(OöBì$º®£éíë?.Z´ˆ+V°zõj–,YÂA”:ulg¨o )…B!„¢ž¼Þ2¾·D§ »ïKa÷o?Í ÒgðúȾBˆÝŽR ÚÔ¤ŒÅb<ûì³íjW>ûì³xàx<ÛÿJš{ !„B!„B!¾¹6}LΛ7šššv“›››y饗ؑq»¥&¥B!„B!„âÛIç”G}4Çs ¶mS__ÛíÆ4M\.×6Ìi%5)…B!„» +Å–b‚Hs ÍßêýàDkY·¡I Q±K‘R!„B±{Püí!Ìý¢e·Zí5 Ÿ ´´4ó3ö¿±1®dŠo÷6°ªyò¦ôÛïl~yîPzì÷GVÖ'·ùšÈ×o¶;»÷ÝŸE5I)L!Ä.Eš{ !„Bˆ½V,£¾¾žX,(º¶ã¯ß‘˜)Õ§¼hºFVv699ÙèšÔø¦šÖ,fêº0ƒf¼ÃÄßMÀ¥i»ÄzÕ¯~—µÆ`†tt8½çèÉ|úf½ˆîÇÞËë÷ŸˆwYw±›QQæüñx®{ñ§,ýâ2 Ì$/O=ŒCŽÈfé»—Qàêà¸R ^{øN¾êVÆéÄqœP?ŽÜEÊS±K‘R!„B쵪ªk¨¬Ú„Ûã§®®]7ÈËËÇQŠÖ+¥…rÀAá8©h²uZjdËÔïéI8ŽB¥Ÿ†ijhÄa]óšØ¯¿›@ ;à±YüÌïøäñi||éá íêúŸ¯U¼æ#®˜t*§þës†lãyš‘úâ‘$ ßZxÝÛL™¾ž›gœ$Ýzöípï©ÌyïÇœ7¦d«×ĪßcÊô·yhî²o7n9þ„»& )…B!Ä^Ë0t²³»›‡árahù…Eé`”“ U:¤T(@¥ÊÖÇÚ†šNúwJiD"͸Ü^Á,,'JS8‰Ç§0õÝ7,8å”S¾õkgÏžý_cÕ¿Ï9Oý˜=WÊñ?¾Š‡ÿ½ŒiçØþI*Á’âG—Þ ÀÁ§^ɯ®¼˜ý»¶= XóÞó\vêÏY–p8þü?sí/N£»·‰Þ[ÀÜ'ÿAá1›û+îx©Ž“®ä‘?_F/>åÇ#~IJ„Û‡÷å¹+äþkþN!dó†eL»ù÷¼oå°à•—ùÙÝ/òË“ö'^ýÿÿ_þ9«‚ ®9Œç/¼Yµ ®¹çE.?iFzû—½òÇ\ÚÆãÏ»ž“'Á´ƒtáCn¸ë¿˜C¹ÿþ)D=Éϧ¾ Æî{ìJJýZ§ËviÚ6ç}ÀèÁ„Œ&^þ'λe¸†ñ›;®çÜÀ«i8ñõüiÜa¬9ë!îÿÙ¡Ö€Ö|ʽןÎ}së(q6ùÝå¾_!/æÍyÏóòº~\4^qÖ…7ƒoOϽ‹ƒúfwX†k>Á/§¾¹ÍmݸüU®>yÁ£ ¨Z]ä‹§rÑÄ>ϯÃc£žÅ ñêì1ôü+ˆ¼ñ'®¼ïm>íÏÜýdz(ôh(«’¿u$¯p/Ï^{X¦ßå!N¸àV&NA${hŸ3ø¢©Lì—½Ýã£bÙ"z–m®éÎ)åÔ<7O>ÿgŒ.nü©ó¸€‹ŽÀ‰WÜÇï®úy¦„•Bˆï¦¶¶–h4JCC‰xœd2‰ã88ŽCss3.— —Ë…ßï' áóùðûýèúÖ-J$¤B!„{-$m‹DÒ&™´±u…eÙØŽ“žªgž·9¤tÒ¤Âth™®Ué¨Ôsl'U«RÛr°mǶQ lÇ!i9(G.!ÁŽZö¯û8é772tx—ûxàö'¹ú”a”ZËÐfÁcç1eî!|°r]¢sÂÐc¹4Ü“y÷ÏN;‘MKîgÜEQÞýd-Ù pí„“77Ƈ¯Oä‹…/ñÐÜEð‹‡g=ÆôQ3¹ð†;9âß,8›¿Íú#ãNü5w>÷6“ú~·Z’*ÁÓ/æ¾Å?aùWbþ ƒŽ<–aCW0Âã“WÿÊk ëxí\‡YOÌ¢ÏS—ðÇ«obÂáÏÓ?WgÃ’‡9æ‚[™ûaøsÆÈOµ¹êö'9÷'§qvß¿rù¿B4E¡|ôdn9k9“~³Ž„Úö²Ç—¶9ïýFÅø×-Gñr÷»Y½îVVΛÆgŸD…z™?Ÿ<Hðys‚Taÿ ¶¬ÿj7Ê…ãŽæìç–²n̺þ(~zôcÌ^ô]c™uÏL–%ZòdîœG¸ýô‹øÕ_^g^'Íæ{Ž:•³ûÞ·mmäù ~ΑO¼ÍÙCóøø¹+¸¿2Úá.Y÷Þ´ß>º¯þÍC/ý^ú7˜>‹ÇïÆOþk:x4¿=¾ÊNðé'ajr"ؤ¶{ñÌóùñÊøïgôÎR,xìçœò›¹<|ÑTÂëÞáº_þwŽÃÊ­7gŒv:˜’:'Öœ`«©š›q—?Ë[gTóé;¯réoïåùû®àˈŸ9»P— BˆÝS^^yùùtëV‚išhhhšÖáèÞ'3-ÒÔ´õà]:€ã8|úé§TWWK !„Bˆ½‡J…Œ–í`Ù¶£2ÿ;Ô74°råJ>_¾œ?YFÅÚ5TVV²ò«/ظq#á–Zš›X»fkW¯¤¾¾–ƆÉ$¨TÓp'Ól<dþÙ=ÔÕÕ±zõjÿgëàÄ×òð=n~>©h]øé¿€ægxþ­•™çĪ–pÊoßä¶['SèÑ0³÷å·¼€ãîŽSý~§ÓL{3/¿›~ã ©øp!¯©dNC*o¦"Ò•O?€i/=ÎÄ0éÜ?ñصCåͼ¿.I~~Y¹ù„Bþï¼­nŸÁ™×Œ'¤i$¬Tœ—´,B%û3éðCÀ7y ÿÀØ¡Ã9ãâ!ù>k75ƒJ°|áÓP|=ò4Ìü¡\tå8(ø%“O;„—›}Æ@k:3¶þÝÙ²·7oï¦EL™¾žžÁ‹ç/¤2œ üž¸ý"J¡{Êyà˜ÿøÉ†ŠË^|€7íñXõŸ³pñçX¾Ôsž~ó+ÊœÈÉ£rè~ì½ÌüÕÑìwÀœrzñ¶ QÛö¶:‰f¾Ž&xú…ר+w5?”»õǃUÝé±±º>—‰“Á¡Aƒ‹îys&å°ãOá¸á„•ºÙöôàÖyïð­GâÕ4â5‹øñ5opËôËé¥ûvÂæÕ6LŠ”PPPÐáOqA:QLßn[kÞÖáȸYy%”÷Âqç\ËÊ_áœBŸïmˆË9@±K1!õ-pcc#999R"B!„b¯¡Pض"i;ضèX¶ƒ¬d’µkV³¾b-^¿Ÿd"I} @(Â0]´´ldÓ§›@ƒD,NÒ²CäåR\ÒÝo¦›}§j^î®’É$‘H„P(ÔîñoÓdûÛZÿÁKÌ©~…n?H¾Õï?À]×ÿ?=âJ \‰ÈFðM o‘'õ"ÍÍèÓod4дúÿ:æDV±*œdHŸ.€…ee1{ös€E¾éŒ&p»ÒJbpàÑgÁío‘´,œÖj*U›­òãWù¿wVáñxPñ& †ÄqÃKwlC57¯}‡Që–qÛÅ'sßKï¦nÚÒA›+Pf Þôšéj÷Ú`vOhXHeóùdgi÷3 —ö—½yW¯M…ÅYn #g Ï??ÍU‚'Jóò:yFYõá»ìsüÅ5°,‹ò£þÊs-]»*ó@ck½fƒ¾C'<ƒo]Þº§˜ÃÎÉ?n¿Šý½Š§¿Äù“ößzÕ-Û<60LBææXP9öVóÈ.ÜÜGd¬¡€]7×”´íÍ#lûKFrý-#·¹îËçüšŸà˯ÿH÷òöýÚÆš:¨I¹Oþ@®™u'ÿ8ì2šÂqÀ+'!Ä.#Rz<BY!)!„B±÷P©Ápl;õ£´ÖZ” ¥”vïEvN–eaÛ6þ@M3hnnÂ0Ýôè•…ÇíEÑhÇqðz}h†m§Ú{ïÎ%ø|>|>ßÿhÕñü•÷pãôY˜ïÆ´‘RV<…½‹W—NæÌ…èø!ú*««â”—·^¶5tö8lèpÆŒ(l7ɲ,"Í­ë±9€2ŒÎ쉷T1ï½%”ådc7®a@Ïcvh3›jkñuÉféÌøñ5O0ó­\þ›ì3æ\¬Ì1Ùæ<ú|D'sþÕ2íyà×Oóë»ÿCö5éµYüôo;]ö¶æ½¡¦|˜pÄ!mšß§ËÐV`lùÑpWF½EócT¢ƒg·|Çò6Å#<Ûíoœôó»¹åÂcxùê§ùç/j=vèØH·²&ºƒïñÖÁ“”Ýñ  kxï£ 4³£^Ù,l-O‡¯MÍxȨ~øw`_‡ºõçРARÎBˆ]Œ `š&Æ “ÒB!„{EªÏHËv°…a§û‹L'‹Oa•~rj@‡Pv.J¥Gðv”ÒÈÕÒ£{+…m§æ¡íý½Aáÿnù_Ígjâ >8¦]ØÖ7t37ÈÀnƒ9.ÇÅC??‚Ù/qh(ÓO½|ó1Ý÷XV­šÔùûA×qÿ¬\ó§¿{%]=o>v%]DZÃS!¥²ÖsÈC˜7ü&ž¿q® ÃnœÁ§Œ%¨à®S®æ’{æÐ/K—s€b']O¥þ›;w.Ï>û,J)âñ8º®£ë:“&MâŒ3ÎØî—·ò©$„B!öZ¶Rıx‚X"IpÕŸø÷;‹™y÷¯˜Óä‰_ÁìÅ•›W&ú*_×EÐýåÜòχØß­ó›sŽaìÑÑûò¶µ@ Ünwç?¦™ê;ôš9ÜwڳػŒsOÜ—ëÍk¯\˜ ò•mµKšÐ}©/ þríiôïYF÷?£ÿ=ÿá·Çï+'!ÄÎÑæsøðÃ'??¿ÝäP(Ä1dzC­K4¥öÆï}…B!„€ªêj¾Z¹–ÚÆápM×ð¸Û7­ÝòbYCÇ¡¥,t-ȶ¾÷×4 ˲H&˜¦‰¡äççѯO9y9ܮݷÎÀìÙ³Y»àq®½ç%®½û1†·©5éÔñü-W2sy”3®ÿ+'ì_°Ýù;v'­™M<šÀ1\øÜæ7˜M 8„rB™p­iõ\t½õ)‡•º‰ØAŸ»ý1bE '·~üÛŠG£˜>©f»I\4“ÞâѪcÖõG9ៜ94H$"Z½ˆÑg×òŢɩþ U‚æ ÈÑ.HìhÙ.êwhÞÊŠÒØÇôø·*‹Î›{o–Œ6ŽÛxƒÙ™Á¾Ûó¶·UY Z¢q<¾àVëµ|ÎÏø}Í…NlÀßA±V"J/>·–ÙN访BlÃúõëé’—G·’L—‰†ÆâÅ‹yðÁ‰ÅbèºÎyçÇA„ÛíF×ulÛ&ÒÔÔ´Õü¤¹·B!„ØkRXXH$jŽY©>&•Bè0#ÑEMóKÄ’«ÉÏÝ …Ýé2´ôŒT:îT <.=§®@jdô6ô.}ÅÕÌœò{žúÛ"Æ?t,Álm <ò³­i•“³õ+2ƒäxÐÝÞ·C3}wâUÛuÔL7;}6¯{—«Ÿªäæâñ…ðølÖ¬ÚÈ I½2£l£¹ …Ü™ò0v`ÙM«wlÞšé#'§ãò5ÝÛxÉå ‘³3ÇgÚζjfÛé›U.}’#oìÁ»ï Úæ±±]*Áë÷ˇþÎù=¼íŽ—Pº;ÈD<œÚvÓüNÇIGåmng;…â»rå´¿9r$o¾ù&Ë–-£W¯^xà™Z”j;×>R !„Bˆ½šø½&>ïŽÕ/Š'k¨ ¯%n‚Ç3’üì~¤{ËÛ¾TW‚éØRÛ£ËÕUÀ!ƒÿÆÖЃ w÷Û'ÑÈÒw^àžÙÿ¦×O¥¼$w—\|;òN IDAT×@~ŽËqqÎa~ —÷–ÄtÞ_˜qãaß©öÜ÷9ï]QnŸI¬x¯ ïZ›S38à´1¾°ãc¦±j sžü#óßý˜QÝG~÷e !Ä}ÕA3îÓO?eË–qòÉ'cFæ9Úv®}$¤B!„r­mÿ¹•×Gi—ãèšs8!ooôΫ]v° ½°pu/®Ý4ÅJ6×`ÏóÏŸD2¥²ª‰%¹»d(g„2íùjùWT7Gp‡ré^VNaŽg—ž÷®ÈÊÛY{….……Ú6µ•ëèqÔ_yþXD4J]‹E Ç…Bì–Ôæëœ=zpá…Ò³gO4MKÕ¸T*3à`g$¤B!„âÐÐÑu]¹Ñ4“½3yüœ¶ÍW6Ý•xòzsÈøÞ»Ï±ié3x}v³yï ʇD¹„bϹ@ÊPJ1pà@”R›J¥@±Í RBJ!„B!¾!C÷‚R;4RåÞ*R½šÿ†mòFìG¯”‡B±§Ù2€l *-ËÚ* T¤ÿvRÿwDBJ!„B!vP$¦6\ƒ¡éøÝ¹4FÃxL¿'°ÃÍÅ÷D†Ñ~”r•¬âÙ›ÿ À9§ˆ4`B!ö<[ÖˆT(”£ˆD"™pÒ¶mlÇF·t0RÁ¦„”B!„B|G‘D˜_“°âÄ­q+F¿ÂôÊï!e€µ›Z\J<ÜÈú¯>bæ÷óqÂá¬+ï`D©_!„bdÛv&tL&“$“I"‘±X ]×Ñ4 MÓ°-]ÓSµ)mÛ¶;œŸ¦¶Õc¥B!„"#aÇI$ØÊÂvhšÏÀëòíueqÝä1Üöä­'¸†rêYc1ü@Jóv¼÷رc·û+%W¦†ËëÅ¥iÄ£ <>÷nUv±æjê"^Jв~°e*+Jm]ŒÜÂÜ]~4îd´–Ê‹neEÿ£òB±}+V¬ ™L’““C,ò,4MÃãñàr¹0M—Ë•ùÝ0 lÛ&“““³ÕüvZH©”bíÚµÄÉt›sÃ0¡ƒÙ£ªÎ^Óúˆ¶ý9v2Ùvlt]4BÁee¥ßh›,XÀ‚ 8ÿüóÉÍÍÝkÊÖr¸à‚ :<È„B!ö4M-H$Ãd‹q¹‚{eÌž={§ÎoGBJ!„Bì¹vZsïd2ÉŠ¯ÖPÞgêjj¨««¥OŸ~ض"=‚Okਊֿ­ýkªô?[ýÞúœ¶ÏOO£Ík3+Õþï6Ël}½¦|±üsJËzbº½D¿üŒÒÒ4Mß¡í]°`o¿ýy…ݘvÿL¹ô’NƒÊÖB5RÕ\å o±µ›v¼ž*‡·É+,Í”ÃÎ *•tH/„Bˆ]L8¡b]„ú†fz”ùéVìÃ0Œv×/À6¯aäG!„¢½R*¥‚ävÉǶŽ£ÈË/À²¬Ìô¶¡akhÙBÒ.€ÜL¶}mkø¸9¼¤ƒðróüTG¥ç¡9¹]ÈÍËÇãñ²®©šMõ1òs|èÛéO¨5 6êzöéÏ’wç· *Çá³Ï>#S__×ë%’››‹iš(¥¨««£{÷îTUUá÷û1M“¬¬,zöì¹Û<­åð±GPÚ³KÞ}‹iÓîç²)—’“ƒRŠªª*êêê())Á¶íT_¶mÛ$“I‚Á †aÇÑuæ–f¼/±X ¿ßÏÆÉÊ΢gžònB!Äÿ\8¡býFlÍC^×îTÕÖãØ•”•£ë:Õ›ª©­­#à÷ã÷ûq‡¯¿þšX,FII †aÐØØˆiš”””•%ÍW…B! MH¹3¾Íµl›dÒ&‘´HZ6‰„•é Sµoùݦ¶£ÚbzkMIMÓpš–ú;½ Ã0p8éyovª-Ê-CMP([kÓÁ§ÂQФÍvË PŽ>”žåû`[6û ƒm+þ–èáp—ËEEE‡r---hšFee%½zõbÅŠ455 …HZÝËÊðû»ÍÓPŽ{$Ýzöƶö6ÇVüuÚý\>åRBYYTTTPQQAUUh Å—_~INnY¡, IJ>¢©±Ã0ðx<ضÏç Ê;U!„ÿsáH„uë7’°MüÁ,¥pû²©¬­GQIiI±hŒD[—¡T©aÛÍ|]7Ÿ®9ã0­ÃÍå!”öèË'+kðz ’–MßAñU*¨üÑ ÇãóûIÄŒ3Ó4q{¼èºFI·n466²ÿ@9DãñL Ïh4ÂÚµkwÑ+S‡dÕ—h†ÁêÅ|Àð±ã)*ëÅêÊF M#KÒo¿‘Ø*TN™r  bà A4¦CH }û÷gãÆ”––á÷û;v,ñx—Ë…å©õ877·Û-ïT!„Büàì–MØõëуÄݹTl¨&fD’.Ö¬®E×!àsãw‡X¿© æåáõy±,‹ž=zàñx@+iaYJ)|>>Ÿ—˵[”CMM õ äçåíÕý° !„âû•úúV®ëÔÕÕ}ëÀQ´l[¥,»5 t¶C',¶ù[)0ЈÆb455„hniÆåò'C,[ºŸÏOirlG¡œ¶}P¶ &Ó+µeÿ—[Ó±VÖü’ˆµ†„u.3;µN™>…`þÛÓµ[?z” ‹‰'IX6¦©ÓIÐoÀT®_ÍsÏü“’\_›\vë@´ýÀ?›—³ëR8-5¨X5f1夬W?ššcX–ÛmOÚD" ú JåºÕ¼ðÔß9m\/@#7³­¹º‚Ê5(ÇÁ«ix5-µ“¶ø†ÞÞàÍtðÃÑ ÞÁÇ é¦|J±'R6ÉM«I¬yÍåýÁ?c„» œ†õ$–¿‚ãÎbc¯“ˆ #”“KmU …iÄI¼nº+@ņ\¦IY·®{TQèºN,%HH)„Bˆï ©&Î………ävùnŽ£°[kSÚ*X:éL®µQwë b›ÿTë°2 GrÀíñÒoßA©kDÝÄešøü~ª«62îÐ ¸\.‡LsíÍý]¶ïË`ûùŸƒ¡çѽËo°˜Oqî$^”RxLº®ã(ÅÅ̃>Ê‚·^áÀÑãéVD×4–ƒI’׿WoŠó¢iðeõçTÔ®¢ «˜H¢…X"ÊèÞ‡0åÒK™6í~ÙŠnjDz,ôh˜7æ>C~Q ã8Ÿ?†IíúU8Vå8©‚JÌ/¦¨ßÝî@Ñ߀I©r.½ôRîŸv?ŽŒ8˶ˆFÂÌ›û E%eŒŸ0Ÿ×G¤y#áŠO¨æ3 ·ǶÐt’AcðwÑŽâ Íôȧƒ{4 4Íô¦jR !DGÊùå˜ùå¸ 7«×U ;xüƒß »kOÜþ.…ø²ópûCxB9{Ä“•Å¥S.eÃÚ/xoá<"‘óæÎ¦¨¤Œ#&LÄëñò›té’MVQwÜ,y]qûƒx³ó1¥ŸI!„Bìfrs²éUV„N”ææfI›Æ6¥ßç!pãuï9µ(…B!~(;õ«ÞH,FcS3ÍÍ-´4·ÐÒƲ쭞׮¢c›jjËçt2mg0 ƒh$B$Á¶‰D¼Ýô’œ²N_ÛTN:••Ÿ/¥GßÁŒ~€ Ï$+ àrKËÉ--ßcžì¬,.½ôRîøË|õÙûôê·GL8 ÇCÈï"à5Á›‹7$} !„bÏ›“M`Ū Tm¨¡ /‡’âÂT@éwáuRHB!„ßÂN )].åeù44oÀŠÅ𹡾ª¢ÝÈÝ»MƒÜ,‰p ‰°FqQ!º¦ïp …8ÿüó™óÜl; Ÿ?DЧgʽEvvç{ÿzñY0>¯Ÿ O'èsÉ»K!„{¤Üœlö-i ÀÃÌÉÁï÷òx]P !„B|[;-¤Ô4¡CöÇr ±%¦i8J±+·tÑ4ms?–€cÛßh}•ÇÕ\AAÝ»˜=N#èÙ»Úõ(u-54Ç›ø³)È ‘HÆú²å%„Bˆ=ðâG®¯ÆN&q»Üäc™n#‰[—€R!„â»Øé={›:t í¾µ ¿IÿAvÃ×(ÇAßôA÷)ÀÞuqê8këV±¦z -±®~€;H^Öáèš.ï.!„BìY×>¶E´±ŽºŠ(ÇA3 œdoV}È-”BB!„ø–¾—á÷–ŽÂÍü^˜y½|&ì…¡œ®ëtïÒ wÔÏÆÏk\2—é–€R!„{$Í0tÃå  M7P¶ËçÃÌ‘B!„øL)‚ït©šþOßüû^µõùÁBÂÞ0¦fQœ‡®ä°Bì”Ú5;MBìº×>šŽ7˜…7˜…ÝRJÄ0BÅh.¯ŽB!Äw$UÞ¾%ÇJ¦.V ͽw_˜*¥°UËNÈ!„Ø=h yü{ýç·â;\ÿÄ£8‘”\ÿ!„BìR“ò[pl›uËæÓh¹HØ ÕUhz Þì.øB¹{ãe:j©Mª@7öÆÊ±Bìñìd‚Ú5Ëqù‚hš¦ÀÕP‡nêÒTSñ i ËÅ‚B!ö^k×®Åívãñxðù|x<<n·—Ë…iš†¦ihš†mÛX–…eY455m5?©Iùmnrí$Že§:M·-jVƆOm¨ÙëÊBaÓþŒ–ØZVU=ŠÂÙÍ7È&þÅ|Âÿ™Jø‡A9rÀ ±G}h9D›©úâ6._JÕKY½èej×®²B|3­ù¤t!„B±SHMÊoSh.e„[ƪÆù”<…޹6ÔÐ xËÐ4È @ÛÝsoMÇÕu4ÃÁÕµÿ^9 ’{2Ãå¦ë>CHFÆrl”¦az¤?]!Ä7½fÐ$ B!„؉vZHé(‡Ï>ûœD"‘ª¾™´ðú¼(€ÌõÛÖrÛº¶ëlšêôyj›Ïk7AƒX$‚ÛãA)ÈÍÑ¿ÿ>;xMª¡»Ü,xw1_­ZͺµkèµÏ ½òr”bá;˨­ o,‡ÜÝ{f¾8O×çRooÊä3Bˆ=,TÐñ²py|Ô®ÿ —×GNמ?È¢#‘_|ñ%L$@·Ë>‡©ížÿ:xZ'çÃíŸ Û&™Lâr¹q™%ÅE””H&ذ¡’ššZ44‰¯‡6ÕÆ¶¹®;m=(¶eá(p»\ø}úö)ÇëÝ{ûM$Tn¨bSͦ-öOÇûdË¢VÛØm§YÉ$Žãàr»ñy<ô.ïA0”Ï!„Bñ½Ùi!e2‘¤jS-ýö̦êjZjèÖ£;–m¥PUí.€[SªõZ¡Z'õx»ÇÒ¿Óæ'=MSí_—y^ÛÇ”Jõ™¨JSèºÁŠŠõ”uïËãaãW«ÙgŸ¾èúökÎ9ŽÃÌ™3I&“Œ{=ý,gœá¦_¿~힣”Â0ŒlgÚ¶ýƒ.¯µâñ$#ÆLà±<ÍYgIŸ>}¾—å)¥Ð4m§®Ûýݺ=áHŒMà‘'f0ù¬3éÝ»ÏÿôMúCïW!ötŽãPUSÇ—• LÓb€¯‘œììïw™Ê¡¥%LKÔ¢¬G/Ö¯«@× r »a[6J)µù³®õÜ×zÎsZÏiŽ‚ôy͡͹5ýz­ÍùÒi}½N*ñKÏWI„ÙXYOi÷žXá(ö†jŠ‹‹Ñ4ˆÇÔÕ7È.Àqê6|MAI º¦¥ÖƒÍ!Xf½Óç['zµ®kÛórêïÔóR=ƒ¤·#ýZ8­ÏIo¯m[Ô5Ôb;6yy¹Ômj ° ×»×vœˆ'©khÀ*MQ»~=yÅÅhš– m'µORû+} (g‹k/…ãlÞ‡ …²SÇŠã84„ë ‡£uͧ®¶ÜÜz štÁ(„B!¾';µ¹·ÛíÅëóãõðE£xý,ËÊLo{S“ºŒnƒ¥Ô–µ>+}cä´}]ëM–¾ùq6ߨ@ûy¦ÿo{ó§ë@@0€Ç㣡ڠº>JA®cAekFé¿ÿ(º–ô ”Ý…O=Å™gœN¿~©Ú˜ï¿ÿ>›6m¢ÿþx½^lÛÆï÷‡Ñ X4FAAÑhÛ¶‰ÇãD",Ë¢¤¤ŸÏGuu5>ŸMÓ0M“D"AKK Á`0„¶Y7ndè°¡¸]îä&æÌ™„Ãö6Žü®¥øCAž|rF&¨t”Cee%U«(++öm4M#™L¢i±X Ã4pl‡úúzü~?@€ÜÜ\"‘ÑXÛƒRŠp8L}}=eee‚6Uo¢K—.D£ÑÌ~-(, ¾®ÇCcc#‘H]×q¹\Ô××ãóùðûý(¥¨®®fèС¸\®Ìö´´„2âPºvÅçðÄ3˜<9T:ÊaÍê54·4ÓµkWP©rWJ-Í-ÐÔÔDqq1›6mÀ0 ,ËÂï÷£iÑXC7H&“†A^^ÕÕÕ¸=nñD¦#Yx=Ö­[ÇþûïO ÍQÅ®/³zõjº÷èŽßçÇQ¦i¢•é(Y¡¨«­#//…"‹c˜FªSeÝ@)E"™ fS Fêý¢ë:õõõCA‚`f~Žr0 ˲0M4plG9$â ¼^oêñÖ€²zk¿®¥¸´'±xœO>_Ë }z“óý•š®áñúðúx} SÇç ¤?GÚ„{´ý²-0¥¢¦ÍçEGmb:[›ªm0™šãl>kšF  3t¢‰&à ².4MÃešx}”ãàóðùýèšÞæüK›/U›p¬M­¼¶Ël}^&¨Ü➟Óöœ­À²“Äc1,GHÆ#Ô5'ÉîâàuíÝq¤®ÜésøýôùÅhp·ÅN¦§h;lgŽ—6åïlqœØéš¶(ƒX‰( -ù ¿G¾4B!„»xH©i`ÛɤƒeÙX¶CÒ²ÓÁ”Þ.LÓ5ÛqPÊÁår§/ªuœÌ %zë-¶£H&â i¸ÝÇÆNßì*¥‘ˆÇq”ƒ»µ?HMÃI×ÞÔu=ý¿–j¥¦ÀQ6NºÚGkÈ—©uâèèÚöÊH4Ê€ýGQеŒ¤eÑ­¬'c;ž3žæÌ3SAek ÷öÛoÐ¥K à R__ONN†i0jä(æÍ›‡iš‡q¹\TVVÒ¿*++ ‡Ã444P^^N(bñâŸ\.Šºv¥¶¦†M›61zôhŠŠŠ0ᅴѶåþŽ#·°„D"IYÏ>Œ<øhžx2U±¼¼œ _o`Æ Ô×7 :Ží°jÕJ²²²ÈÉÉA)ņÊJòòòˆÅ¢„[ÂŒ9’††b±UUUØ–MQ×"ZZ¬]»–þý€R,\±Ã0¨¯¯'Ž0qâQ¼ÿþû躎išÔÕÕc˜:w*°ÌÉÍ!ŽÐÜÔÌÈQ#),,L…¤íÊCÈÉ+¶lº÷ì‹uФLPÙ³g/ªªª¨¬¬¤¶¦6s<¯[¿žÂ‚T: ‰D¢„ÃaÞ{o ùùùøý>š[ZPŽƒË墦¶6LVUáóù>|óß~‹ÜœÜ̈Wš¦á(‡â®%áÙ‹›6ŠÝ‡£b±ëׯgõêÕ„ÃarssñûýTWW£ë:$óÉ'Ÿp¹\(¥hiiÁëõRPP@YYK–,!++‹d2‰Çãaà ,]ºMÓhnifðàýˆE£|ùÕ—¸]nrrsñ¸Ý466ÒÜÜL  ;;›8Ó4Û”yEÝPŽÂ4]ø³ ùpù†ôïANÎ÷7·†–97Z¶ƒ–:Of¾ÌÓÒå¨2ç3 -Pj€†ÂÉ„HŽí`ºÌÌ9NKŸèZcBMi(-õe^jÖv¦&£“®éh+'µi%ql…év¡éúæoÓçåT¿~¤ª¢P¶“^ Ûi­š ÛRµÿÔæuÝ[ßkŽ"i9 œô1å ë›k«¢i™2r…í8©PßrpÃe¶9.@)Ûv2!·£T*èÇÉ”wfºB!„ßgH©”âÃ?¤[·n~‡T…å¤.˜m»õ‚Wç‹/>GÓ4"‘0ºf“›Cå† Ô××QÞ»/@¤•ÄçõcÙ6±hÝ0‰E#dçtáƒ%‹èÞ³×K¸¥ÇQ„²²ÉÉíBUåÖ­[Kß~ýÑu#SÃp¹pl‡X,š¹ØVJ‘“‹Ïls·YÌZÏÊ (Ë?·™µÕô§gÎ"‰3`È(ò Kùð‹*²’¶MaQ)#9–3žæŒ3NgÈ!†ACC‡êêj\.@]×ÑuÛ¶ ƒLš4)UsÅå"¢i7n¤¸¤˜ÜÜ\¢±(.35t»×ëMœ†A<gËÅ¡‡Š?àÇírÿ?{odÇqßk~™µž}éèF7ö @‘ ’–)‰m]Ûãð"Ëc%Ù÷†gîDLLÄDLÄ<ÎÓ}šWOÜ+Y¤dÙ¤${lÉa[‹¯hY²$[ -‰ €Øˆ­÷³/µeÎC>èAб›È/ö9uêÔɪÌÊåWÿåM¹«¿]žyæ:Ý÷ÞÿÅê$ç/×ñ\‹v7dbÛ,÷?úËüÙçþœ#÷¢T*‘ËeèõÚòMm›¤Ýj¡TDœ(ÆÆF( ò9®]»2’¡ZM…Ì(ñ}›DY\½z™D%4› ,Ë"ŸÏR,æyùÔI¤ÇI­< Å–%AkªÕ4Xf¥R¢Xʳ°¸ÀÊÊ/^àôé3h÷ÿE¼Â(/_"Ÿué1“ÛçxÏ#Oògöçüþï}”c÷ÞÃÑ#÷Ðl5qÂÊÑ#‡YZZJ­_³Z­6ý^_úÐärYº./z‰½{öàº.Q¬xõÕ ìžÛÁÄÄD*Ø~ø—±'],À´Öx®G&›Á­¢[«0 BÚ=ÃF I&“aÇŽÄqLELNMôFGGQJ155E»ÝæàÁƒ$IB.—#Š…"NH­ …GŽ>ˆ(–Jd2öíÛ‡çy,,.22RE Èd2ÄqL·ÛÅuÝ ý¬”˲6 ”ãÛé‡1‹«=â8f¬’#Sãù/pìÐ,åòí‹»§tD½s’n8A)Mœ¤‡M£Ñàä‹?M-¾])%SSÛxù¥Éfs˲™,Ò¶éu:H)©7j¸®ÏÙWN1½c–b±BGD±Â²,„”(¥†îÝhèöº´[ ªc“”JåT@|£nCC<7“D% õÚ*çÏÅ’ –¤R©råÊe²¹<¥r™ŒŸEHI·ÛA+M¯ßÇó|.œ;ÃÜ®}™ZÓK!B"m‹D)TœZØFQB§Ó"Ÿ/R®Ž`Yöõ0[  ‡_ßî±@µ—/~Ÿ¨0‹Öñ@Ì]›s]·¤t{^½x˲ét:ØŽC¥2ÂêÊ HI±XI#l‹Œ—%›Ï§–”¬sÍW¦_3¤¬®®R«Õ¨V«T*sA ƒÁ`0Ü9‘2 CΞ=û¶'JA+’DbqsþÜY&§¶§V–¤Vk!Qó¯ßû®ëR.WPõU‚ $›Í‘Ée9tø(ý~Ÿf³A°¸@»ÓÁ÷}æ®1:2ÁôŽ9Í&¯¾zÕå%Šå*cã„AÈÒâõ[CX‚ˆô˜ÂÃßât”§4ѪHyd’F;‰ëí>­NL¥èáù”†3?ø&ÛTÒ¢´V¦Aû(úÒ+(¥ÈII~Í:eASŽ—A¬þp¸Ð.û¢¸|šP)²R^‡°^LÔšHëôdÉçó´Z-|ßÇ÷}Š…"ÅBÚîØ±càšªÈår)X\HåóyúAŸJ¹2,G·×ã•óW™ÜÖE +.Q¬¨3©KºSà[?øGŽ‚-7>ʺÕ;P«ˆÕî¸ZûëC$üz:F& E¢4ý ¢ßë26>BF ++Ë,//ã/-"…¤×ëÑj5ÈJŒŽ‘/JüÛ”r8¼Óguù*ß{îo¹ç¾<ôðÃTò²hm²^ÇrITŒ%¬ÛšçíÇ1O=õ4ÿð¥gxüÉß ”óÈfÒ8•«Ëó|ï¹/sï{Npøá„YÚóäG& {Üli9BlÎøhZÅ/ÿwtÔ7"¥áŽ¢”baa_|)%“““”J%NŸ>M±X$ Ó˜«õzL&ƒã¤î¿»vîäÊ•+äóy&&&8sæ {÷îåÔ©S,..R«Õ(•J |ß'„d³Y&''iµZ8ŽÃøCr¹###ŒŒŒGñðAŽï{Ø;Ë©³W)ŽNaÛ’]ÛË$‰ÄŠíÓïÔØ¿÷1´‚±rÏqPƒòïo­#ʽcLW~ ìåä+ DIœŽ‰„å°s÷lÛŶllÇFJ›‡}| ¦†8nzßFa4‘ŽÛwì$Šbú½.®ë£´&Ib‚~Ûq‡qŒ-ËFX’n»M¯×¥\yC¹5 º5‘2Q©—„ëeس÷–å`Ù×Ë€Ö<ò ïK-DãxPVMÅh­RâûYö8‚R J§‰ëº6­V‹‘ÑÑT°•’ q¥Z­&Åbå¶ |?ß!ußww?Š3±ïö¶³Š½ýv~š…¥$ M’¤ÿÔº:-WF¹ÿ¡ÇÒ¸ž«f?“¡X¬Ðxgia[6Qa»nêÞ¯u&Àtg†عk'333?ƒÁ`0 w/ƯgõòVX{šŸ¨Ô=,N4I’€°°ìÔ=¬\ñ‡îO(WÆÐhævíÛhµ2 讟€/–ÒÐìî}ÃàïŽëã¸þº…²fjÛÌ0[hšT%ÍZª_7–•Ʊ*LþBÀùå—¸¸zŽÑü8µî qó {?ÀÇ?þqž~úi¾ñ_äñýX\¼š ”‡ïç‘GÁq][¾k3Ú¶ÍÇ?þ1žzêiþñï¿ÈãOþ&JÃÒ¾÷ÜßrøØC<üðÃ8¶m jÝž¿ô¯”2’•îï™yˆ‰âÔ¦9ŸO|âã|úÓOñÜWþŠÇŸü-”Ö¬.-ð½ç¾Ì=Ç桇O`[:ê±zîE–^ù).¶•RTwìgdvßæ­4!ãîm¸Óí,1™Ïçé÷ûH)Ó$Xƒä`kV###A€ã8CñѶm´Öôû}úýþpß™™vïÞM†4 *• µzŒï3::Šã8ŒŒŒpíÚ5Ž=Šçûè[yi]Æn)$##ö)Í‹¯\¡42…,RkýÕöîžCº‚S ?b¡ëáÙ>+íEv`×èÞ[»$¡œ=ˆÒŠå¥ÕTPŠSQI£–C¥:¾.Ljqîg €&‹n÷3b]2¸48¤ãx¸®—&E ¬Ù|q8Öù™ÜpLÍfrÃñ¯Ûë¼± ¦5:¸{Çé¸n;åjæzÜÂA€Êµ²2(+Z£3b0þ¦1 ýLvè~®Ðø~–ÊèÄ0ÉrÃÑ Å46hœÄ[ôV·=ĆÌUñ÷=NÜî /Å !Öæ[*íá¯7lÛIÚ®ŸA)M6_$“+^Ϻ®5Ž—Æú4^·ý y[Ö ƒÁ`0 o¨ÏÜ΃i ‰‚D§ÿ”Jß_·„¸žûº"™ P×´þ©«ª^÷Å£.p†žÁëƯ½_;îõÄ$©¤)×Ò ¤±-!)e+öÑzØ–ƒ%,\ËCJ9*Ÿûê9xô‘ëå£â¸.åœK.c¿»Î@Ø{ê©§ùÆWþ’Cƒë ”à8ÅœKÆ·HȰwü¶eÓ Úä¼y¿°éÎçÿð|úÓO Îçß}îKÜsìa>‘ ”¥‚‹'-˜ÝG¿ÝÄÍHÂ>*IÈ”GLob0‹X!©V«<öØc¶ïß¿Ÿ~¿Ïónj‰süøñáëÙÙY¦¦ÞüƒŒ™3?ÓÚQ ÉèX•ÃÀON_"_š"NBš« ìÛ3G>—Çr"nß…k{4{ üÊ,•Lõ¶]#5HP‰&QÉúáoð?õšjZ¯¥½a㘨xÍ~býØ·îµi²)$rð7M~óÚ]éå↲¿´±¬ÃLåë£?«c·Þx6¦Ü!øH%È¡5«0[†íhmzµVGRÝpýõÆùÙš¨üšöBštIH1¬™  J‰"Mxd0 ƒÁ`0ÜimævHA«Õbqq‘F}…z}•¥åe’uVoÞh½p©×›ܩŴeÑhÔ©ÕVq]?MX³nñ3^˜|ýïJÉÇ?ñq>õÉ?埿úŽð®(‡g ìýéŸ~šþêçyàÄxðÁãØ2ç§×¡à)øÅ-q>ôGÈýoŸäŸ¿úy|ä xðÁ¡@™õlÀ¦2½×ôÃ[éo¥¼ãqÌÞ¬;öšPyøÑ çÑÚbßÞ9òùYORÌe#í¯¶•gnkµVÔj«Xn–•Õe,ËFZö {òÍö_?FÞ8.Šë·z˲‚^·K½V'WX! |;aM*ÔZÑë4K€¦¶ºB._†´¸Qüfé^_V½þ÷,´N6¿üËâïþþ¯yàÁc¸ŽK!gmÙó1 7ï¿GGŠ>$éô,òù2YOS̹wô7K¥"÷ìÛF³Ýc´’OŒE['äI·…rþ´NÞÚ—5ä}Mfz‹€lÖbtd|àVßgïÎí\]X¦Ù ñ&G°Tו_wà”$ºO¯w×ÁµË ìÿÞt9m ãåLz4P¯’Ïïj×äLÆgÏÜ6®^[¢ÙMëÇÖ}Ðo  qY?™’Ü$âÚ€jÁ¥R°‘LŒ(—«ƒ¸—–éD ƒÁ`0 w„ÛjI¹gÏn­î ¸¿Ò×݇6Z¿Æ-\©„·IRG=dý¥K_Åyäñí»Ë -z,œzžâÔ¹ÒX!I7[á6Gø95 Ååú«Ì7¯áºyÜLB×Éz¦§0Þmý—j²ØûSl1J1{˜¬ïÜñßô}ŸCFÐ "Ä AÜ[]¨TÈ¥•/±Ðø'î™ûŽ}k–…‚5rÖ ËJý ÇaÛ¶)&&'éô“aìÂÁ`ÿ–ÆÙf÷g¾Édé}L¾w“úÖËšöÕ–¼{ݾmÛfÛÔ$tú j#ô ëGƒZ:…~õ«Pz ë¾¾aò¤áu××­xµÖØÒ¸Û ƒÁ`0îà\÷vÐ’PÎ;[ôr¼µr«ö2X.u|ën³.ÐDý>Ýúõù dŠ#í*V8Ç£4¹cˑҚùÆU–š t‚6ß9û5¦JÓLUÆ6mænƒÁp+½—"JÚ-‘–Àq:@éçòÛððœ['㤇ßZ¤”·q%JÙ±;RVK ŠÙ[Ÿ&(©Å\HÆkPÌ$á˜øÔN"BÑ¡çùØvBÎ Žqß6 ƒÁ`0l.ŒëÛY Tf°*ÓdO|ÄÝæþ$ðry¦þIb»>Ià«[òŒ¤”ìŸ8L)áÚK‹¼wß“8Ò1¥Áð®ë½$9o;»'ÿW,áâX¥-U~ÛÊ1;ö{T{§)emÞ>Ux”s÷²[þÏä¼#P¾“mÞrp·F¾÷Gf«F 4 ƒÁ`0lÎµŽ¹o­!‰îÊS—¶C¦T^zwâÒËoÝE‚b¦DÍ^Ý£’Í#…YÈ ïÊ®@G¨-hŸz÷Æ$*ÜCdB¢z(ßeíëg'§ù¹—I)tÔ›À`0 ƒÁ°)1"å-‡}„í!üü]}-´Ö¨n â¼wÉùèˆD%Èw‹¬o9îÁðnF †À­zW¸Nœ·m“÷¥ KºdÝI|§|7 †(£XÙêæñ°ÐŠ$Ž‘–È”~ÑtƒÁ`0 †M‰)o8èñêóߤ»„QÂò«ç¶M¦_@Ý8^__¾Ö~åú‡ƒ¤¯Ù¼î;ú†÷ÃÃrãÖõEЃÿ !i5d²9„”” Ž?ðž79çh)ùö¿|‡WÎ]ä•Wΰïð1ÓšÞ(­øÎ·Ÿgéj†ÆÒ(£…­>Ïüõ?ðâ©ÝüÇGÇØeªØ`ØÒ!°¤Åj}‘« /säÀ†ŸI)©V«T«Õ7}<­5H)‰âˆ(Œn‹Ø'HËÙîÔ¹xåvÍÜG&sÝý<“ɰwÏž7ÝÅQŒã8DQDœÄd3ÙMY?Ò² À¥Kg±É7A£‘X¶¤×î1ñ4#“3G&ÌÍd0 ƒÁ`ØtÜ6‘2Š"zA¡{ޱ¸¸ÀÊÊ2»ö"Žã¡0¨u*®éˆz T¦Ûô ÛôP\|ͶÁ1^»mí7ôks°ßÚ>–esqþyfǧp½ W®œ&Žlûg[(¥xöÙgé÷N<þËüù¿Äï—C‡ ÷‰ãxè6·¶ÈZWëF’$º½½N‡ ^³ £•¨w4×VG)Å3Ïûçüîï~”ýû÷oX,k¥‡õú³ÖkuÇ1öÛ°´ãiÉáñÖŽÇ1aÞtÁ¾v>Ív—‡ÿ0ŸýÜ3|ô£¿Ã6J©7<Ÿ$Ièt;d3Ù7}7¶÷^¯‡e[¸ŽkšÁð6ÐZÓh49uv)g8uæû÷îÒ8Íf“ .†i Z)%JklËÆrTJ‘$ ŽãÇ1ív›jµŠmÛAÀ=Gî¹-÷j§Óåìùe:Á$§ÏÎs`‹7£:§OŸ& ÃÔ¢OkÇAJ‰‚$IRI’†!£cc$qŒRŠ{î¹çMõÃ?oÂ(äêRKuß³‹KŒ ë.”RØŽMF¸®;Üà8¾ï¿&>èÛ¥×ësîò«Ý,µ+uöºÙá|CkME$IB&“¹¥±3mgŠ~¿@ ¥$Q ¶eÏÏq›ŽU7Æ!½Õû"´ ÏóLGa0 ƒÁ°E¹­þÉRJ4!%BX $y=Šqá1µª×Ìuâbºïzáñú¶5+M­Ôà3‘nÓzèZ•$ê&b'XRâ9ŽmãØ6±‚ÅZ‰‘–o8öÙgi·;;þ‹ŒŽo£P(òùÏ|ä·9|ø0§N¢T*±¸¸˜NÖ“„|>?´q€v»Íìì,/^ºÞ%I2-³Ù,–eÑï÷©T*œŽ?úA*#cä29žyöóüî@¨TZqéÕKœ?ž]»v¡´¶IÛ¶QJ12:ÂÂü¶m³°°Àììlº˜U KJ,Ë¢Óí0RÁ¶mêõ:RJºÝ.¾ïÓívÉårÃkuÏ=÷˜ÆfØ4¤ÂÈÖé/µÖÔ N½ÌÈØ6„´X]^â¥Sg9¸7J)Ú6—/_&¼K¿×j±ººJ±XÄ÷} UKKKìÚµ‹ÉÉÉÛ&Pž»xáä+çi6š¼xú‡öÍ E¸(Џrå ù|žb±Èòò2–eaYžç±¼¼ÌÄĉR¬,/333C±XܼåµE–j]&§¦éç//£ÑLŒÓëõ8yò$×®]£T*‘Ëåh6› –”8ŽC6—eçÜÎ IÞ.½^Ÿ ¯^%H,¦¶MÓnµyé•KÜ3C¡P ÛíòÒK/Ñï÷©ŽŒ¤ Û¶‡ó|>O­VC)•>„•’$ŽI’„(Ž)—Ëd|ŸÓ§OÓét(—Ëø™ õZmh™;555c‹Å"ív›f«™NF­4Njœ$ÄQ”ºñKI¡P Ùlc©®Å"]›+õû}<Ï£×ë¥ó¤äСC·¢À`0 ƒÁ°‰DÊ~¿ã8·<ñ”Òĉ"ŽUêž•¤ÿ„€8Iâ(145HKbYv*TjÍZ†è4YôukJtjU¡Ôõ'þBJ´R¸žG’h‚°c»aÑn·‚>ÅRiYh¥•¤–$‘So8ç Ÿæ¯(/¹Òý ¤2¶G?ðë|á _ä#ÇcY/^$Œ"\Çayy™±±±ÔU-Ž™ŸŸÇvlf¦gèv».]ºD«ÕbjÛ6õ:'OždllŒÑÑQ–——Ù>½¹¹9Μ93Œ!V«×ù…ÇcÇŽ#P¾MòÁGžÀÍ• ‚ˆ‘É~ü? …ʽ{÷Òh4ét:œ9óÊ0vÚåË—)—Ë‹E’D1?•ÉÉ)úýõz˶éuû¼øÂÉAÆÝËËËh ®ëR¯×ÉåstÚ,KR,yá§/Ëçp—¥å%\ÇEè!ãc£,..Òh49~ü8³³s¯+P>øÈðreÚ½>#“;8ñøà™gŸåw?úQöíÛÇòÊ*½~ŸS§Oã:J+Ο?O>W`ll¥5ÝnR¹„ëyœ=wžÅÅE&&Ʊ,ɵkóضÃ{î˳¸ø*W®\Åq|?Cô(—*Ì/,pøÐ!Š¥²il†Í%R’>XÛ*ec P–F¦¢ĸÙ2Ë­U^9w‘Ý;wP)W8ñÈ#”J%€Á˜ I´F% –e!Eú@oíÌûA@·Û¥\*cÙo_üët:œ»xeeÉdò„‘Âr|ú‰â…—ÏqäÀ.2Ù,÷ß?ïyÏýH)H”¦×í äsÙá\@)…m[ôû!n›j¥‚؄Ԛ@¹¸Ú£X'N n‘W.¦âk¡'Ÿ/°{w–(ŽAk<Ï4•J…R©ŒmÛärùÛ*Pžõ ½Ø¢P¨† Hì/ž~•Ãûv ¨]¹z…‹/R­V©T*ÌÏφ!»víBÁÉ—NÒj¶ð<™™‚  ßïÇ1­f“J¥B¹\fjjŠn·‹ß÷±m›ññqŠÅ"—.]byy™ÉÉIúý~*T6›$I’¶W)Éf³8ŽCLÏÌP[]åÒ¥KX–E&“!“É ÅIß÷‰¢ˆÕÕU:Ää táö³öݶms ƒÁ`0ܹ5šÖZ'IÂW¿úUxàÆÇÇom‚|û»Ï³çÀ–——X]]aß¾( ç^9M«ÕDHA«Ñ`jÛôP ¬­®’ËçA ù"½ Gw!k°€ê \±m´N]_ã(&ûÔk5fwîŠCSK´Ö¼øÓçàá£t:m •9µ}†\®€‚—_ü ;ævãy.{£÷åxŽ]ãÿ®]æÆØ–Ÿöÿ£Ó 8vüqJÕ ~|z×µèõ#öLWXY¼ÊwŸû¿ó‘ßæÀ´Z­aÖÒÔŠScI‹ plg8!RÄ ½~ohÁâº.Q¡µÆ¶m„C+¼0 ™ŸŸÇ²,J¥ÒÐs-‘ÀÏ}ñ¬b‚3ÿ„;}?2WÙr7Áç>÷9ZíÇûÒ+ri¾ÖÐ Òz]¼z‘ûÖßsøÐ~ª£e’( Ó%ôÀ}²ÝiSÌB{Úr,ÛB+5ÉU’ -‹8ŽY^Y¦ZÁ’´¦ÑlbYÅBiÛ$Q”~_ƒJ„%ÑJc¹ZÖõc§u®iöNš…Ë6Z;²Â¿Ÿ^`¬’¥ÑØ3]fþÊEþí[ÇGû7Ø3·˲évÛˆ¡À­YXX`rj w`ñÛjµÈå (•Ežç¡T2´r¶,‰’8ްíÔÂE+•>HÐ Çqoñˆ@Hp¯‹Ãíý"š½³€¦”=¸É˪©Õëœ9•Ru’N?áÜÕ®m¡€ãyÚU¶¸ìšGˆu±˜õðVZwÀuïuêôþp“¸Î? Õ­¼ò-¤_ œz€‹Ë]´ð±Ü,«±ÒtûÛFrt»<ºÞ» ßu6”iC9àõ?»…2Þö:‰¢«/’,Bî}‚ùžËr£O¶Påµý ¡Û(æ<ÆËQ¿ÎÞeª#ylË¢„Aˆë¦Öƒ¾—ºÁ )B¢oñü¢¸ÅJûßH’ˆ’ÿ×®ô"‰t œ»ZCJŠÛÆ „è¨Å¡½Ód|–D¬ä׬&¥%é÷út»]ª#U´ÒƒùX:·I’¥¶mc[6ƒpè²/„H³Ã ˆÂhj`MèZ¿Ò!U -I§ÝáÚüQ³0|¡H£^Çó} À²m|ÏG#p=—W/ž§\®°cçn\/ÃÕÓWÂ>ÿþ£02:†”/¿ô"ãS9úÓ;æ¸xþ,­V ¬,-’ËÈçot£’$Ô¹Öüøåì\»B*ý¤“p)½`…NWR,Ç MƸ¶E·a[ 8{ñ‡¦\¾¹åØÍb2IG]À׸1®ÒšÈãº.;vì0wÃíYjÇ1A“+Thu¥[ÒíG8ދְ\»F¶Ô4‰BÃdr‚Pu âh X&Ë`- Ö  2*Ðz™X§ïó%BÕA‡éa¢h $¬}ëïãDƒ©p™Ê´û¯Ð çé‡G@P(ÐéE$J“(c[ôÃÛqÑZpþäOØé,“ q„Fë´Å Û¤€ù%Ö"Êf„DÕÓ×ÎÀ k­8k‚ˆ¤¥¯ogy!ÑšDßRõ z5Ü÷cš´?†Û>XØÌ$IÂÂâ ZxX¶Cœ¤Cz¿i¢X! gϼB±ušbλAÄÓéyG¨î áÉ/wê´îýO43‡£Õ htBl+}˜k°•¥eÎ=ÿ/ìϤ]æ!V®®Þ¤5"R‘ò⿾ôÂzÅÑÝZ ¥ D8Nê!¡$8üäô9|ÈÅq,$- ŠA¿§oK[Œâ&×_§Ù;˨ףݸ‘ñzA„kIZýœçÐc²žK³-¸xi{ï{ÍœCJ9ŒCì:î뺠ß8w^7>öÍâEÞì–[q‡!n^oŸ7ú}Ãí'ã§.økñn ƒÁ`0îÈL[§ÐétÈf³·ì†ÿô/?bvÏaV—©ÕVÙ³w?qœ cA˲±m›V«IvàÖEBHõU„ôƒ>ãã“Äq„ãxiì#ŠGBH¤e‘Äqj…˜¨ëOô•BJk ayq¥5åJÛv°íÔâв­–”ç_æÄCGq½ÓŒŽÒ #úQŸB¦ˆ#Â8À³]>ûÙÏRovyß/ýa²¶(HhÕùÎ7¾Ä=Ç⡇!—u¨|Ä]`üµÕ-)“$á3Ÿù ­NÀãOþý(Á¶$A”Ð\ç»Ï}™c>ÆñãÏxd³°ÜZ ”)ãÙÂ$À³=ä;X×E£û2ŽÌã;Û7œO˜(Ô@¨l®.ðÝç¾Ä±ãøC'Èx’dõ"¥‰íôÛ-ü| iÛHk“¸siE´p´Â™:hzlÃíkZ:¢Ù;ƒÖšrîð¦/o†¼tæ<½Ø%_,“Ä1ýP büiZµE¦·SÌy¸q“ÒÈqØÇÍÒ1Ïqï˜-²»ÄµËÈL‰$SáòÕE®.µ)VÆèéƒ)$Z'45ŠY‡ÙÙYò›¬Ð©/§et}`û9„Ø›X|Ò*F5QA{|µZ“Óç¯âå*X¶K'$*}Xö»$a›]s³”‹yrE£ß$cû¸NHã4ºÖÛ?ßDõéWÂÁw¶3¿°Ä…+«*ãh ŽÓ<hµx2fçÜ,ù¬K)çÞs–ÛÉÝdIEÑУçvÍŒ%¥Á`0 [Ÿ;bI)„ Ÿû1’µ˜”J“$š8ÑÄJ ,8R³*ÇK3G*­ÉÊ Ó¤7ŽëƒÖŒŒM§”µRoËv“­µä7ÒvŸ¥2Ö׃l¦.¨SÛg†ï×ÿ}- !ÆŠÇ®ÕÏr~å åìÞ*ÍãûžäþàøÌg?Ã7¾òEÞûÁßDZµå5ò8'y)-²žm&û[˲øØÇ>ÆÓŸù Ï}õ/ù…þ&BZµ…T |à1Ž?@á8Šf¯ÎO¯|Ÿ‚_BkÍrg‘v<¶òô;vI9{=»üÚù¤íô·°lI}! GpìþG9þÐ , ¬¸ÃÊ…—X:ý#l7ƒR1Zk&öÝGufÏfQŒ§·á®Çu]îÛÉ‹/£¶Z#_(b[‚PijËóÌÍLR)•V.Òºò"«€íe‰ú¼|‰©CÇÉïÌC$áfq&ö¥ý)0=5ŽJ4W(Vǰ5„Q4(-f¦§±…³!‰ê—ÏÒ­- “ÛóI¢€Ò¶Lî¿SÆŸÒÆ*oÃbåJ‘½(^zå*n®Šã8(-ˆ‚IØfçì|ßÅ’Š^ÔååùG‰@ÐìÕ™ÙÃÁ©#o<“>…Ìîáû‰ñQ4pöÕòå±ô7¥¢Õ¬ã‹„¹¹8Ž…ïXfÎbxCŒÅªÁ`0 †Ÿ·5»·V ”Hÿ‘j“Z‹uNgbè¦Yç#:Ø¢.^CO¯á'kßÕ<Øô 2Íú ö1‰ÖÞ¯ý•ÒBJ‰2a48¢Ò KHF‹ãTò#QŸÉâ6¤´p-!ûƒñ™Ï~†o~í¯8pï#üë7ÿv P>ДՂ‡ïY¦um!,Ëâãaï›_ûKÞ{‚ïýÓ—‡‡M¥è‘ñl„ÈrdûýØÒ¦¶ÙVž¡šÙÜçstãùX* qð¢~ËÍ “4îWndÒ4 û!l´Ž·Ly]Çåð]¼ðòYêµU¼lÚÒ<;¶R­VÈ8‚Êömô ´Ž‘¶ŠûXN7›ÿù•ÓuÙ1=Öš‹ dóUÚ­5r®#)çÇBÉ #³ûÈNÇf­5^¾´iÊ›!…¤R)s`œ<}™À«$!IÐfçÜ2¾GÎw(æÂD³wüŽthM¦+³”3Õ;R.Û¶™Ek8}qL¾J¯ÛÆ s;wà86¥œ‹ïš9‹Á`0 ƒá綉”Bš­W¯^¡^[¡Ù¨‘ÉHâä5û¾6&¾~Íw:•%%«+Ëd²9\/C·×E¬3תfG_1"%ûØÇxêÓOñí¯‘N<Áñ‡4åDz,>ññóé§žâ[_û"'Þû$ï¹ÿÁ %@ÆÍ’qÓ¸¢cLlúóùä§>Å·¾öE~ï“Üÿƒ©@Yôð x'¦MåîBDÚço1ë1×u9rp7?~á,—¯¾Êž¹mŒŒ’q- 9)|üByS”svÇ$J'œ:wñ±Qf¦§7”Ò²ÉU'ÈU'¶|‹’BR­”9¸~üÂY´°Ø½{çP ,äRK4×ò˜,¦˜#ù±;?ѳm¦&FQ*á§/Ÿ£X¬0·sÖ”ƒÁ`0 †MÇm)Çå±ã÷RkvÈÚ%¶•RÝüÖeݸáæoïGïÙŸº Øvð Þ´8*…ä‰'ž j.òÐÁíÛ¥š³@¹•ÑŠ°Ûâþð,Ÿ{‘¤4‡’•¼Mf‹.⤔<ù¡ò÷_ù|à(–eSÊ[xŽi§ƒF£U¼åÊm;6ñŠ'­Ü‡çhŠ9ççšÕøÍà:.{vî`|lŒ –XÖFò݈’Ñj…G¡ÑPÚ ”ïdíØ¶Í¶©2~nœ8®â¹…¬…gJƒÁ`0 ÃfZëÜ΃MOog›†n?Ù"§?H?Ao¹2'I+«ÅRðf܇(æ¦7mcÝ—CG]¤_Á)ŽãJEš2À°…W–8ùÝÚn¡šŠÐ:Ù²§£´¦ÕoÐì×ém~|å_©fG™™ÙtWƒá-uU8V™jî,+@ŠÍ_^Û’w]=I)6…+u¢cZA“•ΫݚýE¿ÄDi [Úæ†2 ƒÁ`0lÌìôm`'‘Åq2G„(·úª?[ª’=r­I{+Wi!ÄÖ\\[ÒâÀä=â —ýyÞ¿ÿ—H#P [}ì‘Y¶W…BïÔ†LÎÃÍð,]cû˜ÙM¢CÀ¾“1Ç`0 ƒÁ°©æ¼M´BÇ¡¹ï Djòƒ"ºô#tlYr ßÉ` ‰R‰Y” ëïxaoIÑ^£Q:DéÈT¢áM´s‰k¹Ø2!ޝàˆÈŒƒÁ`0 †M‰±¤¼Eúíúà úÈlÑ\w×’nË‹“7¢IÐZoÙúÀXîÌn.‚á®A£HT€ÚÂaL ƒÁ`0 ïnŒHy DýW~ò]j" ®žú)Z%'vPœ˜6Ȱ©HT­c¸†cç` 3:Q½U@¢“a9¦B ·¯}¡Q[0»·ÁpëaÞ`0 ƒÁ°y1îÞ·²°ÕŠLy” Õ! »-úÍš™û6_[%¡Õ;G» ËÏn¹Ò«nÎ×þoºßø/è°k*Ô`0 ƒÁ`0 †w)·Ý’Rk}=Æ×î¥ïˆˆ÷z?ªo¹@n&ǶCfÇ8µðæî{ a{Æ%Õ°éX³{ñì2Û+¿ÄÖRÒ2_Å=ô?€ÈLÉTè›$Iâ4d­ÞØÍÿÎu[)Ò,óB¼ûB( ƒÁ`0 ƒáörÛDJ¥ßùî÷Ò¦ýår¥5¤ÿ­cã¶Tˈ†ZoØ÷ºÎ©7hž÷Ñ·ëÔoýŽzÃOk„Ôk«ds9¤´Éú’÷½÷Þ¬ˆÓjµxú©§£ˆ¯}ýë<ùá_5­É°éhµZ|æégˆ"‹|wž'ž8²¥Êÿï}Ÿ¿ûÊe,Ëâÿ<Ú¢P(˜J}º½.ßÿÁóX¶C¯Û# Ê• Jéagª×õ«zCy½SÖëúP}ÃçëûdµþûzãþaاÛMÇ$‰¸ÿè¶MM™J2 ƒÁ`0 ÃM¹m"eE$Úâðác,..°²´ÌÞ‡‰ãx°ÖƒÅñú…ò@x,ˆõº¿këe­×/~õÍ·­ÿ©åŽ^·˜¾Ù÷¤´X¬ý„Ñò Ù|«çOÒí…d|ïgZµZ->õ©OqøÈQ&gòͯÿ ØO~èC¦E6 ­V‹O~ò“:|/Ûwæ›_ÿk„|àî“$ Qáûþ+ŽÓ¸}¶moØfYÖM³#+­7±œëöºd3Y”V Óßw‡v» @>Ÿîûï|‡oûÛ|ðW~‡«—Ïó'òÿòŸÿóÿ2*µÖôz=²ÙìMˬµ¦ßïÓl5©Žl(ûZŸ¥µÆuÝ›~?I,ËBi…@Ðn·‘R’Ëå6ik’Xá¸ö8ÌÒâ"­f“]{öëo­_Ôëúãáûuý¤Bƒº±ï¼ñ{×_+­Ñêz?¯44M5ÏØô~V—X­·Ÿ˜Ä–›ÄšWrKf÷6 ƒÁ`0 †w#·×Ý[’$]¬jJk½Î4‡ë£b°HÔCáP1øL-|„H5ø``ç˜Z]^w-× EjˆIhS \ A ´F ЃßB`ÛR ¤$–ê}¶»Ø–xCáçSŸúÓ3³ì=üÅR•ÿúïówý9К'Ÿ|€F£mÛCa$Q ¾ç#¥Ü à(¥R®oõk>»QøYM„t{]|ßG hµ[ø¾ë¸¦eßå¬ ”Û§ç8|ì™|žýêïòÕ/?ƒÖðÄ@iŹóç9}ê»wï&I„”¬®¬àù>*Ip]—F£AEØŽƒë8ìÚµ‹ 8á¾çáû>A`Û6–eÑívñ<Ý»wóÒK/Q­V‰¢ˆv»M«Õ¢\.ïÏó( ÄqÌ}÷ݤ巾õ-N¼÷—˜žÝŶéYT¢†Be>Ÿguu•oûÛìß¿­5qÓjµp\8ŽƒÖšk×®±}ûvâ8Æ÷}”RDQD½^GA¡PÀó<,Ë"“É0??ëº$Iš}í>ÌçóA0,ãfEQœ$ŠDk’D£”^g5™öÍ úB­Tj9xУÖ­õËkýv*]®™Y"¥$QIúA²Î¾]Bú¯t{³Ó …Œµi®•Œ#ƒÁ`0 ƒÁ`x犔ÍV“ŒŸÁqn-{®Ä>‹cEœ(¥ˆcE’¨áÊùº#· Ói#… V ž—ŠlabY6–e#é1¢×óФe…)‘ÒÚ賨5Zi´RHËB«„0Œ°,{ƒ5Ðõ…¸Z­!…û3…Ÿ5r÷¡°ÜÝ^€°}žø•ßåÿö/xòÉ'9wî…B3gÎ`Û6ý~Ÿr¹<׬²”RÜ{ï½4›M.]ºÄîÝ»BpéÒ¥ÔúIlË"—ËÑívQJ ÅÙ5ë¨ 2µz衇pKF¤¼›¹.PβÿÞ‡ µMØê#,ïÿðïð¿ÿ< yÿûßODT«£\»6O&“%Žcæ¯-"¤`rr‚N»N­V§R-õZƒíÛghµ:ø^Ë’\¸pÛvرc¯œyǵ™›ÛI»Ýeii9íâ„f«ïgX^Z!*#Uº.v™Ó”JU (ÿù[ßâ‘÷þÕ‰¬6{H‡ïû”ÖüÉŸü üÇL»Óerûv^}õÅr™0ŒX^YÂ…bžb¾€\?C¢AX«µ:I¢ˆâ(íc¢aÙ\½¶€ï{Š–W븎íØDaL&›! ºŒŽO°}zfÓ׿RÇš8Ѩ$íƒ Lûb­è®ëZkJå rM¸D¥‹­ú!q!¤…ã:!ÑBöõ:ùBÇõèõ:ø~6M$é!½ÎZ~“’Н‰é4 ƒágEQáØÎ-¯ ƒÁ`0~6@·Ûå¿þ<ôðClß¶ý––(M¬±Ò×_¯‰”ëW…Bó£~¥5™L•$ÌíÚÃK'_@ I©\! ¶mßÁüµ+(¥°, Ëqh·ZDaH¡X" £Ô 2QØŽŠaˆe;$IL6›cÏþÃ$q¼1^šÖh¹>¶š@“Pï=Çü…¯°{âøÎDj¥y]Wå¿}òÏØ»ï03»ï%“+ðãÓ‹¨«ã®me>ð«¿Ï·¾þWt»=~ø!._¾Ììì,–eQ«Õ(—Ë(¥èv»DQ„ëºüÿì½Y”×yçù»7¶Œ\kßU(,Á’HJ")J2¥–%ÛíEiÆj·ÝmÍ9ý0/3=óÐgæœyôé‡omµä¶Ô²¬–7¹Û¶ÚÖ.‘ÖBÑw€ÄŽÚ·Ü—ˆ{ïž?½J½ÅŠ©‘<Çî|7®ððûüo¿ùI&z&ˆ£ám^T*e¼ L…)hÔ{ð|×qˆ¢)J\ÇAkŲ!„`tlˆ£½8®‹Žu'ë"Ú\×Eš2ªX~ ½#Àñq2½pÕ Éˆî8¬Tò€(Ö†z£É“Oü¨íY ™\£ ËK Ôj zz{0ÚÎdp‡8ND\€r©DEO6×K·ŽK¡ÐÃsÏü”‰éýTÊ%ª•~"•ÊÐhÔ9xøöV‘&‹Åb±¼ÆNŸ>Íêê*sss ØF±X,‹ÅrMp! Û+ ÄQü–v¦Mâ½Ó5Uj—ºÑš|¡—¥ÅyÂ0M_ÿƆGƹpþ KK‹¸Ž‹KÂëŽã²xú4™l–ÍuŠÅýƒ”J–ça`p„µÕU67×Éå zúÑJ'E#x=4)Ö¿A9z‚Áü}(]Å‘A;ÇZ"®½u„ÿàŸ˜8pœ8ÖH)ÐíókEŠÅ³/Òj4( ŒÑ?0ˆ”’ááá7h3M«Ùbßô4gg8xð ÜQ)=Žc–––èïïßF0ÛÞÎb¸ýŽÛyì±dzî8 ñ]‰àHI+.ž=A³ÑàÈñifgò8ÒÝ&ÒÕ–´Ö;d¦vi«íº}÷=^e™7Xk=M¥qŽ‹›ORpâÇß+³0á±)2¡GOÖga½Jq•Ó'ŸelhÆò)|ß#2;…”ä˜F ]Oöî 5C l%Œ0‰÷`ûˆ†3IXr¼vv„.'GÝYW¿ÕÎQ1ª¼D0ûnœüÈ5é¥ ‘Ò(£QÊÅ1Òq ÓYŒµ•UFÇ'éídÿL?‹‹ó‰`Yo$aîZ×óÑÚà¸.Q¤ÙX_CÃÐð0ÉôþYšÍËË‹¤‚ÍÍ R©&Ù\!$šØÞŒ‹ÅrƒJ¥‚À¦È°X,‹ÅrMq;÷¼ç=¯(,ñfI u;äÛ bõ OÊÎÜfjß ûg¡â×óC&W`bú@ÒM’³r®Ð×®ne`h¨F(ÚžHq¬ŽÄ˜ÜwH<ÄDñåÊA–é¾ÿ‡lvžÌ4ÅFƒõê ™A\Ç£7xôý÷’ò¾ÅßüÅçy߇?ÎÌxOòýJsêŧ8ùÜO¸û]rä–ã<þç.°¾¾N£Ñ ŽcZ­BÇÁ´½Hh4lll µ¦Õj‘Ëå¨V«(¥ˆ•"ð}r¹¥R‰|>ÿ†EN,77=ø*Öü÷?û<|äãÝ×1‰wó©ÿ‰“Ïþ„ûüGŽ#x”ãy¤p)¤zÐ& ȧ²×õ˜cU¦”L0Á=ÇÖùýßÿb¥9~ç}(¥|z­Ê7¿öeÆ&öñþ~˜f:ÄD4‹«„=4+eÒ=ý€ •ÍíJ?>·ˆ.>:ºV߀ÑÉø›„|k\×çØñ;QZ£µfdl)]‡FRÒÓ×ÏÜ¡[0”NÆKGº“xÔJÇ香@ˆ$äÛ@ßÀ0*Ž™:0‡2y˜C§àK5®Ø›Ñb±Xn„LLN011aä-‹Åb±\SºªäÕÈ/£tb«¶ «W ÷&*×KŠÜ¸^â¹c:^U)Ýîz‰dRÆðÿíOxðÑ_&“Ío ”ï|Ç߆#%ƒ}9굕J…Z­F?Q±´´D6›ellŒR©D:f||œ—^z‰ .°²²B©Þ=84D©TÄu\¦§§ÚQýØby-câ‘GÞ‡Áð÷_ý"}èã¤3YN½øä–@yø(RjRá¹å—‰U„#=–Ëó eGy×Ì{º®Ë@ääp¤jw__ÿê_ý&¿ÿÿ¥5·Üö.šõ*ßi ”¼ÿQ|Ï!ãjjë«lœ{‘•“Oâ¦Ò,Ö«é<Ó÷<Œ—JïÂÞIDÄkiå)m’|¾moö(Ö(µõ°Æq É:¦=ö&…È@ˆdüìÚ‘Ž›x 'É;l É&I…!$NÇ‹UH„1HÏyEú€Ý{¯8X‹Ûb±XÞ)¤.-‹Åb±\{mચß´‘h“xÚhd§lÇ>ßzéü×)ýmÝ;¦]Ù»½z"XŠmæöå7w¬ŽLr;:ŽÓ wM¾_’Ñ£… šªÁþÁƒ€ ôBzè!¾õ·ÊôÜqΞ|¦-PÞŽ#¡'ã2tdŽF# ŸìäÔìV vd·ªl§ÎÌÌ 333;Œ{¥UâÝj¶ÎU;C´¼1BÞÿÈ#€à›ó'LÏÝÆÙ?Ý(èÏ8Žàèèm¸ŽK­Yåðè-¸Â»®å«ÑßßÏ¿n •q¬¹xæÅ-2ðÈgôÐC4 þñ?äïùŽßz+Ž„¾| ßKNXvGˆBt—;_ºì8ÎÖ1v–­.i¹¡ò} ?þÜÿУ=r!Òu’k±&i 2þîòÒí•ÿá?ü OðÈ>„ï»2a ]^ÞÔ‚ä«Q.­ñòIE¹¼I½^GÅQ×[}ûÈj^e€Ýþg’rƒ+Î?V¯U“ß ^+1»—VFßÃùÕ’‡j‹Åb±X,‹ÅrcpÕDJ×óyÿƒïd£Te³”T NŒÜ+5¯½279zoÛAÈšGJçMÙ«GåÜs?掩Æué˺]Òby»1ZQ]_áý<Ì=G&i…ã±S Üíô÷÷111Äí÷#„ä3‚”ïØÎ} ²Ù |ø>6K56+­nõô®«¹yãaV 0hê­çi¨—è Ã[È¡i Ò™$›Í¡”lÿ½UßÍ’ ÆlcX,‹Åb±X,–†«îÝÛÛK¡§—FK!„@kƒÜÍáÉb+¼Àh“äW»Lte³q–ðÅ/“yôßáJëòhÙ-êå" ÏÿÇõŽ‹Öç1Æ™;N¶d—½aµ¼Ìùõ3´”G²Ö8Io~Űö IDAT+r½Î&$ù|žL6Ï@”x±'EÆÞÜØ«2/ÌÿâÖ Œý<)ÿÊŰÎ÷cð;F¾Õû¢Ö¬òüÂÓÒ½äƒKÏ3¢7ÝoÈb±X,‹Åb±ìiÜ«½C) Ü,"‚@æGñ'ïÂ}ãDmËu½6×%?ßr¹Ìç>ûYZQÄ_ýõßñsÿü—öTÇk£y饗9w~0²0?ÏÀà®+·úê’~ê6iûóím.òFŸ®ÁéŸ$Ûw¶ÙÑß—öÿVŸ¬./‘+ôàºi>ðð¶bº…ÇÿΔX8_å–™Ò›vÕ=§5ŸÿÓ?çÅØ¿/à×gß³kÅøX)Ξ;ËÊú<÷ÜÞ‡ãÜxN÷J)Μ;ÇÊúwßö@7àž8vmXZ¨²°¤é¹­…ç%^ ‘«#tu„E!E7er½Vg³¸ÉÀÀ½½½c¹¬k±+T¾‰yÁÒò «k:x€T*uSŒ[õzÓg/ |ìŸâò !n¸¼¯‹Åb±X,Ë•pÕ¬2¥A*ÃÑcw²¼¼ÈÚÚ‡%Ž£®0˜ˆWáÊ´Å0^)zm[o»@ÖYÇlÛv«ºæ%Ûl_¿³ïmÛJG²Yn286ƒ—J±xö9êˆTཡa¹\æ3Ÿù ÇŽßÎÈô¾ý?þ ñW_åcýÙî:µzååe&'&q' £s¤´¢žëÇq×»¢^¯S*—º> D±bßÌ==}D±`öྠ·U,½´]»â¥­»²1Ѻ+ëK·7ìè³-¯Mƒ6‚ZÓ086I*L³tá$åj“l&µçŠYX®=ößýÎwùàG~™…‹çùßý]þ×Oº+Tj£)néí}uË(Š’‚:žëa0øÞk‡ôj£©”+¤ÂÔk®gŒ¡Ñh ”"“ÉÐh4p\Ïõˆâˆ _!øh­ùâ¿HµÖàcÿM~ð¯ñ¹ÏýŸúÔ¯%Ìfsc“f³ÉÐÐΛ(BeŒ!Š"|ßïžs¥R¡Õj]QQ ¥/.°²!ðÃYž~ö%ŽíŠxQQ.—ñ<¥¾ï#„è1ÆÐl5I‡i”R”Ëezz¶r=vÆ¿NØl­V£V«100pÝîw¥..vÏñ™çN¶Ï1ñl4¬®®†!©TŠÍÍMêõ:Ùl–\.÷¶z»i­™Ÿ_b~¹I*=ËÓϿı#³ø^â1¹¸¸ÈOõkDQÄÓO?Í… Ãu]Ç!“Í$9èµÕÕnAŽT*ÅàÐ 'Nœ$h‹„­V )%®ëÒÛÛK¥R¡§§çM žJ)Î_œgy½ÁàÈ*Ö‹š§ž=Áí·Ì!ÉÆÆßÿþ÷Ù¿?gÏÅ÷|¤”¤R)Â0DÁúú:ÇŽ£§§‡ååejµ/ž8A: ‰ã­u7Gb?Õj•BOáuEä«E"P.°´Vchd„Xi67O={’Ûn9ˆ”kkk|ÿûß'æææØØØèn[.—9xðàÛr_h­¹8¿Èür‘¡‘q”Ö”K†Ÿ>s‚ÛŽÂqüöïIÝ*ÕëÙu]²Ù,CCCär¹k& wÊùå2}C£hm¨TÏŸ8ѹ}~ÀÂü?þ8½½½LLL°¸¸ˆã8ô÷÷S«Õèíë£V«qàÀ=3nuÊÈx õÐlD¬×1§Ï2{`¬·¤Åb±X,‹Åòº¸±h~až|.O.—»¢‰vÊ8ÖÄJ£tû5Öm¡ëUB¸Ûb¥‚(jQ«Õˆ¢ H¥ˆ¢ˆj¥ÂðèBH*å^ µ!ŠZ8ÒÁäzŠc›úõÅÉŽç¥Þ¶Ü9~G¦ˆu_¾zî¨íå#w€›a½T£Áƒ?ó+|óo¿„~þc%ŸÏsÇw°²²B³Ùdbb‚õõu¢(ê‡a*¤Q¯ÓÛÓCOOCCC×U Ä@¬ Jib¼J¥0&1¤õf³-Ât†z½Žç%Þ8Éû‚z#)¶à©v& j”!Š[8Òmç¾Ô(mRiŒŠ·yŠDdêxÖJ‰pt­ÙüÛcØ9âF q•.HgOjG ¼ÿÁG) L²¸VƘ½å(cøßù]>ý[¿EÔÒ>t”Õµu²™4ÚhZME£Y%¦qd@¥V%fÂ!ŠFI´(eÈç{i64š1*V-è0?¿@>ßK¥\#Š4•JVSÏKS«VÉd³¸ŽKµ^#f!Ñ:BcHÊr•w¾÷QpCV6êh­¹ç½á‡ßþ*ŸýÜñ?òŒŽORè`}m…$nÅ´ŠG²Yª/ä1Ò¥ÖˆðS!ÚZ‘BHçùh#ðýJi‚t†ÑñÉ7(ÁÄM„—JÊ ó,¯×Éö RkDTk£O>ó"·;L*“eúÀ ùBãêõ­fƒfK‘Ê8!˜D3fgg¹¸¸D³¥ð|0BbhီŸbv|òÚ ”Æ`â:ÂKwÊŵ*½ýÃl–4"E6¡\VüÓ3'¸íØ™\ž»ï}ÙlŽ—Obtbß(äs×7,ÜLÜ@xaW ¼¸\¤w`”j£E­kA†ç^<ÅÑC฾7­Ñ˜¸…ðR;Êlï fL³¥ˆ´ "˳/œáèÜ4½½ýÜ{Ï;Éær,/-388Œ1ÐSècdxŒ|>ëíæ1Ø MòPOJ¿-P^¤¹øé åj“Z#F‘fa­Œ1g98³ïm>fË•P­V©Õjd²™=çál±X,‹eï L?þ8`ddäŠvÔj5ùîãO2sèVÖVWØX_ãàÜabw1³Óö¢#JGòä?baþ"IŽÈT‚r¹D._ R©P*Éær¨8¦ÑlàûõZt&‹ã¸Lw` ñø{ q²ãaé8/<÷S¦öÍ!çN=Áì-¨ÅßàÐè¿Ás{v0ð™ßÿ+feræz{{yêä±28R2Г"pà[_û cCüO¿úñî÷u¼U´ÑH‘„v ’»íŸ_O´Ö<ûü‹Ä"C¡§‡çŸ{†™™ƒx~¢8æ±ï~»]lÁP­–¹ëžwpâùhÅMúúQqÌÌÁC<ûÌO¢ÕlÒŠbêÕ a&K¹\"ÎR*màyz 9rìvÂ0nWzùå'LgY>ùCîrž%œÿéû~ ™îãqMíí˜èü“Iõe/Üûw¹VD~‚7y2ØÝEþþñ'9y~•»øcc“œ8·F³¥q$dÓ>ùLÀ‹Ï<Á‰gÀèhoûéÈÎkC)…â•¡©‚n^¾7ºœŒ14šMßßÚ¸ÜËPÓŠ‹DªB½’ãàÁ[™=zŽŸáìÂBbeèɤS?þÞ×Èx¿úè}É—èŽOxÇ—<ð;Å­’cIrØ%!Ó…Þ¶®scŠÁ ‹‹ÔøŸpˆå¾{X«¹ôôðÜ™u­)ß'ð$Ã}YÊ¥MB½É­!®Óö|ﲺû JkƒãÈ­"\íÿ’ÐÛR=œk˜{Ö`Л©ÿð³8‡?Ìjß½¬T]ú‡Ù,7YZ¯¢µar(ÒšJ¹LJ¯s|"ëH0†8ŽaÒ˜ë}ã¢Ê«4~ôYä¾÷²1üóeèe£Tçä…MFz3TSCYÊ•Y³É‘±OŠëz¼jógþ1|ÅÑw³Xó)ô R©µ¨6"ŒFS1ØR«Vñ:¤B'y¸©ŽtÐZá8Îõoê+9gÓd£òÖ«O0”ù(åõ}Ä"ëgyþì F'÷l&ôÈÔ* šLL¾}¹•®ÑTëôgî&ðúì ø*oœG×6pû¦‘aá†>×ååeVWWb``àªìóË_þò+Þ»ÿþûí…e±X,ËâìٳݴRaAàû>žçu£;i¦’‚Û1qS*•^±?7±wcccW,PvM*cˆµ!Ö[ž”±ÚYåæÕ„ÊX+rù­V„ëùH)pt&ËÀð(ÎE)ÅÈè8¥â&Q¬Èf“¼tQ¬h4 Œheº¹·ç«¼ô»w:ç ŠH-ÑRĪ‚^·â4m©àøíÓüèÏ04~”XéĈ†\è‘ }N<÷$­f¾¡iš‘"ðœ¤lãr›Qþvç\LúH£µ!V¡ÏWkú†h4ê“x«*Óf8{æ4õz Rk4èbc}R±" ¯m6êÔ rÙåJ ¥4aèáøŠV³µ#_å+Ú@LjÖ¦QB×7¹þž”wø&nAܺ† ƒ;r4…š•]rHm—[!Úž·É=qÏÜ$O½x–s§_fhxœtÊ£/ïPkÄdÓ>Õj…—_|Šá±qn¿g””'Ûƒ£»)#ôVõ¦+F:2Ñßä~´‰Ù¬=M±6O ä¿óSú†¦Û‡‚z+¦Ȧ=V–.²xñ ÷ÞvŒf¹„ç&¢ŸpœÎB"þiÝͻի)kç{â’÷^»4¦UÂ46QÕ5âL m\´lè’K{ÄJSÈIŠ!Y߬RÎ4)dÜߺ혥ôG'ĥǼ}Ö×ô:ÓèfSßD×Ö‰²-4ªA$ð\Ò©¤5‰—çúfRºNO.$¡LÔJ~C´¾®÷­i–Ñ•U(/Ñ*Ô0"×~È&é/¤PÆÐŸ’ß0#Ø(V)§ä3Žã¶‹æÈd_Ú\3árG·šhã·çšb¥I&ôèÉ&ïi#¨Ö¬kô»~·`L;è­.g„l«ÔNArýÔM­›ÄªB¤6‰â"±Š1Nrd…t@µ‘MùdB/‰Q‚•"½ƒ)R~’ŸÚ`:^q_ ¢¸D+^lQ:Ë›'¦¡P(ØÆ°X,‹ÅrÍèZšûöí» “vˆã$Ä;V‰è¥”¾Ä.ÚÊO¸Ýhœžabj¥â®Õ!„À 8t´—hYBŠv†dÝ 6IUÚWä½¼ cPŠS}ÿ;…Ü¿& P¬W¸°yŽáܾPmVxäá»È¤¾Ï7¿öîßǘFµ¿ïÄsOrò¹Ÿp÷;ßËñã·±Vl2ÜâÈ݃*R¥A©D`–*)jƒt˜;r ­4ÚlµµFƧPQŒiWýýCLï'é»¶ù˜äø«‘ËP±!Û^2nÛÓM¢_Õà7Äá úžÿ›œ[$è¶U¾o0ŒÑ¬œ>Ž[øa­cü0 ÒapjˆOOÝÎïþÞï¡´âŽ{ßK)ÜŒCµZáÛ÷eÆ'÷óþ~˜ÀÈg4/­ž$Ÿ*Oå©¶jdü …0÷6ž¡&V×ɰìEþäK_âïý0SSû‰ÚjÌÒâÿÆW¹÷¾¹ëžwÒp%ây¢zßÍ ÁOeŽK¶èÚHõFÌ>ŒÌôc^>}žåå%F†PqLâ”n(—+´jë9~: ‘y¯}[ª¨Åâɧ2=h­®‹ç‡øé,an³F“š{™é#Lj3çYZZ¤·ˆÁ‘ŒÚP­ThV×9tô‹‹gPé,žŽããú)Ü E:ß{ÝÝ?pNv€œRˆ³ç™_œ§o`„±þ J'â\µVCEº•J³B½¶JO?Q«…„8žOºÐÿ¦ò“¾¹Ã¼“Ôá÷#ÃÙ¨…¸¸ÄÅåE }CŒæºÅÔjÕê&³ûçè)ô’\‚+ˆò¯4ªœÛ8C_ºŸÀKÑŒšäRy2Áõô|7ôåîaÖü:®“¥ÖWãÄËç©VcÆ (£Ûs’Rq“Ð3ìß÷Šåʲ© ?GK·ðŸtÏ5?âf´Êzõ§ Ë›%ŸËÛF°X,‹År͹ª ŸT''¥6Ér[¤L¦ó;þÛš"wÂÀ;ë™­÷“„xûçj[%pÝ]x‹Ónƒ6-Rþ ¥Æ:Ë¥óT›lÖרµj¼ïð‡ºa(ßúú_òŽ÷þ,ýƒÃœxî']ò¶ã·¡1ôæ‚]/P Ji¢NQ¥‰¥îÕnÑöDí´»ÞÑæZ«¶çêVá#éxds…D¤& ›ì“‰ç¤yƒ‹qúGmªQ¦¸x!]¼TŠúæ¹á)ò}ƒ >ý[¿Åïþîï¡´áøï¡Z-wÊG>ð(®+É¥±n²VY ÚØäL\§Xßàðð­ÂÃoã J\'ÛýëÐáCüʯü _úÒ—¸ëGŸÜ¿C ¼ó®{p„&HŠå…3Dõa¡—zqÜÐ$™ž¾k“#UHd&G\×efÿ$úÔ9–éé@C¥\¡YÛàÐÁYüÀ#€»í¹Q1q­Lyþ4ÂóAkTÔdèàí»C¤™éëžã}“h}ŽùåmçØ(Îâ ƒoR:õn*ƒÖ1Q³ÁÐ̱ë/R ‰“MÂ*Çaßô$ÆœçüÒ<=}Chc¨ÕêÔJËž;ˆï9èFúÆ< K/“ÊäiT6 ²=ŒÝòœ\Ï5:LÑuõ=Ÿ‰ñ$¿ä¹ÅEò½Ch Þ(÷O‘ÏeIùßëøA^>Úhj­2k•* *Í2±Ž86v™`òzv®LuÿJ§Óœ™ä…—α¹©Éds´bEµ´IàjöMO⹠ݥâ2¥† 5¨EUô¤÷:ˆ”Éð«°X,‹Åb±Xv+WÕê5Æ ÛagIÉéPtÖcç{f§pÙ}æ—}±½þôÈŽ‹”)œm…ŒÑ $C¹a2ƒÄ:îFÙTâÕ*¿ýUF§pñÌ ‰@yÛmhmè/„Áî/º¢n{C ´i¿"’V½4¥™Ø™TÔ´ßÛQé’¾IÚù=w)$Žãâ¸îVø·Ñذ´!%ƒ³·Ò;5‡ìä.4ík¥Ý÷…BO:*£VÌÒÅS]Òó\z²>)ßAë wM¿Wz4£®ãâ9þ®;çÃm¡òO¾ô%w=È3O|kK t½YÏsèßw„ÂèþNõ)$ãÔu*âäº.LaÌ9.¬,á!ÍÚ&‡Î¤ò¡K&ôvlã)ÆŽ½ 7Ž‹Q‰ç´ë»òús]—ÙSÎqni‰ •©T@6%¾ã¾öùxƒ”¸ÞÛ>®ã°zcÎqza‰T:G½¼ÂÜÌ a* º„=ˆÇÇÛ]’“ÃàÔÅ%¼T–¸Ö(s¤S.ÙÐãJ²H!éËôs×ô»Rv‹³ùîÛß?™tšÃ³S<â뛣I¹šééI|Ï¥õñœ€Lp7B ¢8‘îT¤Íb±X,‹Åby+6ÏÕÚ‘#%õZ‰—O4÷š%$Åplï™ÚcÏrn~•ÇæH¥r;Î1Ü¥Çîp`"²ž:»ÈÜÜAÂLH&L„¿ä:zû…zßó™šFG N:ÅÌ‘[Éç²oI Üúíò’ß* åî®~ʤÓžçÙgž¡¥=¦÷Áw%…¬OоÏC?½+Ýb±X,‹ÅbyÛí«µ#ÇõøÙG¦X®³^j"¥@k³«£uo?6×-ªãù~RÌåMlpnާ~Äì‘"RøôäÙ3¥”’£G±oj’¥Ço™ãí,©*Žîö…Û®¨llÚ¬›žB¡À¿ý·ÿÕzL¥QÈl ”{ c4çfx÷wc”K>ë๻Ï[Øu]Žžeÿ¾˜R="›zurOÿø¹.GͰzzÏ£ë8ÌÍîgzr’b-&ôeW ÜMøžÇÌX¡xž¸'ïÉK+o IDAT·,Pîö{\G-ÂÀåÎ#û©¶@‡)2$ðìƒ7‹Åb±X,‹å m«jøý}¹\'—áÞH)Ø=NΛ°žbU£Ö¼Àrå§ì~žëï©Î—B’ÍeñRén%ôÝÒÆ\Çu–„Lè’ $ŽÜ›áÿÚh‹óœZ=ÀJu‘J³Ä‘ô1<2»ò˜¦\|ßÙõùußú9î½kK©ÀÅóvqÿ´S9„)/ç#7¬@ ЪUX>ù:Šž—TbwÏ z ÆÜØ'o±X,‹Åb±\®ºÛŸìYO§7m$ Aè25ðŽÔ{ö<Ïæ}´ì~öª@ ts$dƒ$¯íÅͳ„~ˆØ9W› õÂ^¾¶öDÿnŠÒqñÃ,ÕÆ2‚f£J˜ï³¥Åb±X,‹ÅrØlíoÉ8 q}™»2eÄb±¼*RJF ãŒÆø2Á»gßã„;òàZ,7â’×/•føÐíè8†¨†A SY{X,‹Åb±X,—k;Û&x‹ƒ1‘m‹Åòº$Uë“Tè¢(-74Q£Neu-Tn­5Æhnüdá#ÔÆ9ti!$ÂÞë‹Åb±X,Ëea=)¯Z«J#ªã8iB ¥ŽtlÃX,;ôZnjŒVÔ6WXxî8n€ôS˜~ŠfLw_—Ž!pþÜiGŽƒ/|äÑ÷q¹ i¹\泟ý,Qñ•¯|_þÅ_J¬ ‹Åby´Ö|áó À_~é,¿ù-<Ï· c¹±ÄÞÜêõ:/:ÍêZ×õX[]¡·¿Ïó1Ú ·Ï[´AoMuÀÌ¡ëóä‰î\Å´'&íŒ1c¨×j”Ëeú‘Ä››bæÀ~{íX,‹Åb±Xn:®šH©µ&“-0wä–—–Y[[aöÐ-Äq̱;9ßw ‹¦;Éßú×~Τ~û~^)VvÖ1—“Û¿S:¥JÑÉü Åüég)W[dÓ~» ïkS.—ùÌg>ÃÑ[nezîv¾þ·Η¿òüÒ?ÿ¹®P©fiq‰ÑÑQ”R¬¬¬P(‚T+U‚ Àu]¤”T*V×Vñ=Ÿ±±1{eZ,7Zk¾øÅ/R«7ø¹ÿ?üÞ×ùÌúÿò×?…çùh£ÙÜØ¤V«‘N§‰ãƒ¡¿¯Ÿ8ޑޤR®Éd‚m4A½^Çõ\T¬p]—r¹LµZe|bÜV·XÞ"ƒçLï?HxAÈøø$~*À¨D”ìÌ-tÛÅÒhP:™|hÀ(´I¼0uòô­“¹‰Ò†riom•‰É}TJTê1­Hã{ö¶X,‹Åb±Ü\\Õpo¥FD«EŠV«Õ)·yF^âõˆ ®µAwTËöä¿3‘ïxD !¶Ö3„ÀèÄA‘|‡ÖÛÄPvxqšî¾5JÅh¥hÅšb5"x=ŸŽ@96>ÉÑ;î#“Éñ‘Ÿÿ$ýg¼C¨\[]ãë_ÿ:sss!8þ<étš|>O±X$ C\×euu)%A02:`EJ‹å¢#P–+5ÞõÞŸ!_èãáþ<ÿðw_á?ó9~ã_~ œsæ ÃÃäÓW–'MˆÄS VšXëäUTÛ‹ ªÝ™ÔwÊV£I±T¤Q¯“Íæp\Ý¥”¤Â0Ém)”R¬¯­Íåñü€jµŠëz¸®‡t$åRé:¤Ré®Ù‘=·{en ã×G•–qòð*^HÛÊ#·½‹j˥ܨÅš‡>ô+|ão¾ÄŸþ×?ç—ñçQJñÀpþüyr¹³³³„aÈææ&ccc„aÈúú:ccch­ ‚€±Ñ12ÙŒ½*-–„-²Ê;ÞýAŒ“a~¥„”‚;ø0?þÎã?ó9~ý×?ÅÄô>FÆ'‘Bfó•J™0Æu†FÉdÒ)%›É¢´"Žb\ÏA)M®ÐËÀà ŽcJË.b¥B1*´ª`|ŒtQZ!•AÒ†(Ž)—ËÔku´Ñd2Y”64êuüÀÇõ0G›Å"žçS(ô"$(e’û6V4MÒ™ì¶6í9‰°Ùc,»r¹L­^#ŸË†¡m‹Åb±X,×’|’?þ8÷Ü{/gg¯xgJ'"e2 ßZN¦ßíÉÿ–.ˆtO?ýS.œ?ËÄÔ>æçé¢ÕlaŒæìÙÓôõöS©”ñƒÒqXYZ$ÌdÈdrT«<×Ãq]ªÕ*z Ï8rËq‚Tmô%aà[ËŽÜi@‰Vñíÿ—òùoùÀ¿C¦û¶›,üÇ?ùûÌràøýd²^~i…j#¢ÖˆÙ?šç?û ¾õµ?ãþø¿ðkÿË'Ø·oŸ½Ê,–›”Ï}îszú8zÇ» ³N]Ü@)ÃòFžù?úþ?ðïû·ȧ.S™h» ¿ÖgæêûF©Ê¿øÕ_ úˆíHË•!¯ží™ÃVåZÏÿw"¤5ö!½ ©U2·Q†Í"O>ñ ‰‚¨V«ŒON±²¼L¹T$“Íãù>ýƒ¬,/㺱Òh¥RÒj¶Èz™™;Ú~hj/ËîÅÃÂÂ.\àСCŒÛF±X,‹ÅrMp!ñ"œ¥Ï¿åIL¬:âdâM©ôVrÈž”„6ŒŽO¤B¢(ftz)]Òi͹³§™šžÁõÆñä'ÑuŒc®K;‰nÛ\_5òxáäË<ñØ7ù€)-WŒ@fIÍ=„nÕöÎa;.2?ŽãåÀÏ¢”B)‰RŠXk\Ïgßþ9ªµ Kæ1éLžõµ5¢¨I:%É35EXZ¼H,"¹?Ù~›·ÁD;ד13µ-_¥Ñmˆ»ß{ƒñBÌŸ"ÿîOâ!žù!~:KÜlà¥BÏç¶;îBfúøö7¾Ê=ï~”ññ)´J¼+N<ÿ$'žy‚ûÞóGŽÞB©ÖJ³e±Ü´˜™áŸü_øüˆ•afî(…¥K‹çyì_åîw¾—»ï}®ãÐßã#âˆÕó'‰êu\ÏC'p¼€ž‘ÉëvìçÖ*D+5Û‰–·„p<œž±½•"uðþÔ=x‘Fž¾@3VHé·ç8© dtb:™¯$ɰÑíb9CCcÝâ8Jo¥•éíL ætæíùŽVÚ^$–Ý Áðð0ÃÃö1,‹Åb±\S®jáÝ•Ùî½%Rný¿µ·?ßáéøž—w»U»/×KòrQM„—Å”‚õ3Ïãx>R:4+Eú¦ç¸ï¾ûøö·ÿ–Ûïû 㓜xîIN>»%PJýùÒ ”ËMÏÌÛ„Jž™#,-žçñ¶@y×Ý÷âHèÉ88$šqLuõ&ŽñÒê¥ #ӆǻ…Æ®96þÔr³"$Âõ1Q £±rp´AÅš86ÄnŒ6[ó³-ŸMgQ·ÿ3¬;&@‹Åb±X,‹åÕ¸ª"eÜ…Šã¶@©“<•¯eóšWüÏ/Ëíú­mÅÎõÝôloFÈö>BˆmEt4ÁÈ¡;Á¾ð&/þô±®@麂ެï%¾fÒõØ„ÞɃ)Ú)'yýJ‹Å&yø)ƒÓ)¨ ±jg_`[ŒˆÙ9Çé>LEtg'¯öÜÒ A$•¾Eg]û€Àb±X,‹År“rÕDJÇqqL‹3'Ÿ¡T®Ò¨WAGh½Ó“òUl€ ‚ëâm ¥¤¼¹ÂÅ3é:¸B#;€HÉŽ(éx¯Üþ¾ûî£Ñ¨óÝï~ûßóŽÜr+Í@O ×±B‚ÅbÙÉÌÌ>ñÉ_åóŸÿ·ÝswßóNÇì(»ã“ë!]Ï6šÅò6"×1¬ÎŸBiA©T¤Q/áº;°š·0w1†f«E½VCÇ5†¾}Ó¶ñ-‹Åb±X,7%WQ¤tøÐ¢\m²^j"…ĘÝkIÈ;JcpÚ*ÞŒ133ËËO~;óÄþ;èKcJ‹ÅòªÄ:b|jœÿóÿú74#M£))dœW”‹ew n=z˜ƒ³3¬›Äªã.yŸ¤ Úù· H<×E)ÅUv±X,‹Åb±Xv=Wu,„$— SÁmƒó&Â)u£„*-ÀÓ?fà®"Ð^Q‹å(­X(ÎóÒÒ ôgQFQùÿÙ»Ó I®òà÷ÿ“[eíU]½NÏtOÏ®Y¤£ É2’0ƒñµ±Á`cƒ±qùÀýâ-°ÃöñÚdŒ Þàcd¿ À$ Òh›]³ô¾U/µårÎýPÕ5ݳH³ôH£™çuUVVvÖɬìsž|Î9õvû{ðܼ—+¥Hx=%wÙ°0—ž%÷;…B!ÄUhÕoÓ+ÅU3£r|œŽõ¤ïx7Ê’Œ!ÄÙ®‹ ßñY[³ÕR^×ö¤p„¸ì¿¿àØ'Ç–B!„B\Y»˜†‹ã¡\»¸eËøqBˆ3³”EW¶‡®la¼ÈúŽ>\G2(…B!„BˆvÛYŠàâƒ%cÊ !ÎízQig±~T C!„B!„XF2)/€Ž#&=M;hO:ƶ¥ç¥çJ‚”Rh^‚Þm{¨y‡ð§ôl{ &ŽH—z¥p„g«²€ÒL.|K¹ uÿ¢‰B!Ä«”ÖšÉÉI&&&¤0D›1†0 )—Ë”Ëeº»»éêê²d´=!^ʪ)Ëå2 ÑúvrÙL„©PÌÊŸÆ4÷Ï@2™$—Ëóöl×#]êEO`éˆD:C2×)g“âEyvM=¿E8vZ D!„âU¨ÑhpàÀɘçdbb‚ÉÉI6oÞL"!Ãà ñbV-H„ÿóØãt÷ö37;ËÜ\™õCè(ÆÐŒYbÌʟ͇˜öòÓ—-_Ló§ÓzlšOXúû`8¹^{Ko­gÙ6G ³»—D"IT›ågúM(uîw6Ž;ÆW¿úU|?Éçþå_ùàK&ÐB¼h…Vsô`ËRtf<Ï“BB!„xUÕçìß¿_ Bœc û÷ïgË–-¨âE¬ZÒhC6[`ÃÆ-LNŒ“œžbhhssLŽe_ÌæÏ“AÆ¥å+ŽKë, L¶ƒ’Ë—„l/;%hyêö•m³°X¡wÍ:ÒéGîeª\¥#ŸÆ¶^:ýóèÑ£üã?þ#»ox-›¶]Ï·þÏ¿qïßü-ú௵•û÷ï'NF!kúÖpðÐ!RÉ$}}}cÐFc) ˶°”ʼn'¨V«ôôôP*•äÌâ S«ÕxvßaÙFÃSÏìçÚ[ð<c sssŒŒŽÒÓÝÍää$étšt:Ý~= CÂ(¤£ØA£Ñ`ff†µëÖE‹ ‹øIŸz­N"‘`vv– B)%@!„â"i­9pà€„¸``ûöíÒõ[ˆ³XÕîÞqSo„4‚ Œh!QÜl@/e?+‚“Í/§j/‹uÌR?q­us¹R­AY£ÑzYF¦9ˆ…´ŽW;Y–•iŒÁ2Çš8މuD¬5ÕZLGþ<”{naëÎ=X–Å›ÞúsÜßW*‡‡‡Ãó<‹£V«Q(Ø·oZkÂ0dvv–R©„çyôõõœ•B\ajµÏî?ŒŸ)‘L¥#ÍBó£½û¸~×VÇavv–çŸ{Žj¥Â¾}ûpÛ¶q=—t*ã8ÔëuvíÚÕ¾fì}j/ûöí#•Jáyõz×uÑZ³qãF)x!„BˆU499)]¼ÅE1Æ099IOO†gà@3¸¸oß>Ö®]{^c3.§hmˆbMâX·k–_ÇͲÿ+e3:6F­Z¥40ÚÐÕÝËÄø(–eÑ¿v¥l&&ÆH$|޾pˆþµƒ:JÄQŒÁ`Ûqa AHäòt+òdpòdF¥R¦ùÇ¥½c–å0_=@>=ˆ¥ÎÜs)@yÝž[ظízŽŒ.â9Š ÔÜzç;xø[ÿΧîý[~ãC¿ÆÎ;éïïG)Å™LÏó¨V«ä Í}ã(fvv–t:zº»Éd3rV qY Pº~‘J`1VžC)…ëX8vžÇŸÚÇžk·ÒÝÕÇM7&Éæ²tu­!4žë , Û²H¥Ò$.¾ïÓÝÓcûx^’DÂÓ¼þ6¯Åšî®N2Ù¬dQ !„¸h333T*ŠÅ"™ŒÔUÅÕ)Žc™$G¬Š‰‰ :;;eÖo!ÎÀˆ¢ˆƒÇ1»víºð w«‘¼¨\ú ¬s²µ¾Ñ!?züضƒ—HE1–í295ÅüÜ ŠB2™}ýkyáÈFGF€B±„1†T*͉ãGñ lÛ¡Ý ¹BÚD§t_öxÙ>+,ŒZä…™ßgqüûì\ûÿp»Zsê˜eëÁçþá›ì¸v[wÜ@i&g+èVàÓ²?ùæwòûÿ/|ñ_ùÅ_øyººº^²Ìä,â Ïã1_ H—\®Cl J…\¦EIÇÆ`p-·5ê…jqqÝŠŒ Yl¦ KR!ÄQJÑÑÑçy )qÕš››“B«z>IRˆÓ9K•­[·^ôÆbM3“2ÒíŸí å)Y”K Å.Š'{^k£Igò,KÙŒ3jbÝ\!_ìlŽ;kÖ nÄmM*qrRCéóiÆ6ùämlíº×nŽmùÃÅ`èÎõQ®ÎIdÙºù5¼ÿý|ö³Ÿ#ˆb6nÞNED±æ‘þ‹F½Ê›ï~]ÝÔ~ÂA:Z qõ²m›Áuk0f˜ãã#”º×O{D±"Ö1Óãtä¬DÇЈž}œœ_ —È3W›¥¿8@g¦û‚~¿1!a¼€1Z†Bˆ –ÏçÉçóRâª&™”BÎ'!.½UMõÓ±! ãf¥6í.ß+[Í+•1+Ǭ\G²µêÒ¢ÖÏ•ï ,‚ \•}7&@á³uÇr›;Î\m+¿€ÁÁõ¼ÿýïãï?û9¢È00´…ÿùβew7 WQÌ&$@)„À¶mÖôƒ9Á‘Ña ¥â8fvª \;0€Ršb6A-ª“t’XÀ‰òÂ8¤7¿æâ®mH€R!„âbEQ$… ä|â[Õ e…‘&Œ4AFš(6gl6ŸÚ{ј—zÍ,{÷IlÍî­[cUžì’nÚ[¼¶ÿ5(e¡µFY+Ëààz~åýïãïÿþs|î ,ËæÍ÷43(®¢#›É*„m¶m³~p-š8> (:[JK:² <ׯs ¼fà¦æLd¦y=’k‰B!Ä+Ofõr> qé­ZÒq\2 ‹Gžaq±JÔ9¼ïÉìÇËèC+a­ÌäHÄŒãà»–³²(”²°,ëŒÛäïø¾÷ðw¸ù¶7ÐÙÙCÂE”Bˆ3²m›¡u}¨Ú Óåk÷`SÊ&p]û´krB!„BqYµ ¥eY¼ñ ·S­‡”,Kk:Ï\Ç—£YnhÎÆ½4–¥eÛœ6í÷Kí§R 9b3LGÏ ¤ü-äÓ–(…§ÑQÈÂä0ébý=%Öôù,ª˜|Ú] B!„B!®V«>ýt2áâ{ÍÍžì<}ùZ¾§vë~)•ú0A4Ï|ý¿ÙÐ{×yd…WCP«2öü(Ka»>ZkÐÎÐvë6K !„B!„¸ê­zR)®šlÂd¢—´?ĦžwÉ™$„8ÛUÛõèܰ ZÁMfˆÃMªÐ%Å#„B!„Bp ‚”WK¹(eãÚY–ˆâŒ\?IipM\™bìL·ŒB!„BÑ"‘µ‹.@Ë’X¯â¥£çG‰çƤ0„B!Ä«Ê=÷ÜÃüÁ¼ä²+ùó !.-‰®] ã³G™\DzÓÔC‹zX&—,HÁ!ÎNêUroHY`É},!„BˆKåž{îYñÜu]ŠÅ"ƒƒƒÜrË-¼á oÀ÷ý‹ú<ðÃÃüç=ï¹ì>¯mÛtttpÝu×ñîw¿›5kÖÈI!ÄUN‚”èøÌÆg'X¬/ðg8À-~R&ÏBœŒ¾üw3¬Ží#šö16lØpÁÛàøÁ~°*AÊÿøÿÀºÈ›ØË?oEËÖ;¹®eYìß÷,ýkq=ŸÆÂA~ömo<çñâŽ;Æ|õ«øÉ4ÿø_惿þ\ד3Jñª÷?ÿó(Oî}ŽXk’÷ƒŸzË=R(B!„/³×½îuüÅ_ü=öX;H†!¿ó;¿ÃÁƒ¹ûî»Ù°a333|õ«_å#ùŸüä'éííà£ý(_þò—9|ø0ýèGOÛþñãÇyôÑG¹ùæ›yË[Þ‚eYìÛ·û￟'Ÿ|’¿ø‹¿¸è11Ïʼn'Èçó´O£££ü‘)>. IDATÉŸü wÝuo|ãùÖ·¾Åç?ÿyr¹?ó3?Ó^ï|ÊNñÊXµ ¥1†L6GwÏ,å`;.½}kˆ¢•AÊÖ£æãvòdri[íàbkáò äŠ&§<Í)ÁËåË[+–m1=5Igw/‰D’ãÕ&Ë JyËzñnÛGåþáؽçV¶íÜÃ7þë_¹÷o>Ç>x2P9<2Œã8t;¨V«Ôu’É$A#`xx˜R©D.—Ã'†Y¿~=Õj•‘‘2™ ù|?éc´¡Ñh`Û6ããã ±°°€1†d*ÉôÔ4år™îžæØK¿/ŽclÛFY k\·Ù½´^¯£”²,*Õ ãcãìÚµ«ýºâêöÐCñÐCóº7ý4™\ÿúò?a´æ­oý)Œ1”ËeŽ9BÿÚ~¢0B)…ïûxžGEÍëŽRDQÄñãÇ©7ôõöR(¨Õj„aˆÁ0|b˜µk×’N§q=k”R$SIª•*J)êõ:Zëö5KkÍðÈ0[6o!™LÊÁB!ÄͶmÛA<€¯~õ«<óÌ3|üãgçÎíå¯{ÝëøÐ‡>Ä?ýÓ?µ’wÞy'>ø ‡>c—òmÛ¶ñ™Ï|fE¶áÝwßÍÎ;ùÄ'>Á·¿ýmÞò–·¬êgŠã˜¹¹¹öãƒòéO¥o|ãÙ´iÓyïÓ‰'ø³?û3¶nÝÚ.‹÷¼ç=|ãßX¤<Ÿ²B¼2Vµ»wÇADF„aD#ˆˆã¨Pl¥0¢PÍ@£¢Ý0mÅÑFCklG­u3بFkPÆèvPR·–Ñ @jmNfd²”©ZÛ9°\ ˜Æ:FkÝúghDs®Êoeû®0î¼çgùæÿY¨,Ï–Ù»w/7ÝtcccÌÏÏ366@¡P`dd¥µZd2I¡Pà»ßý.Qáû>¹\Žññqâ8&Š" …ýýýضÍ3ÏNÖßÂÛÇC=ÌžÛîB{%F¦æ CC¬á5·ÿ O|÷+(o|Ó›¸õöŸ$›Î0=3M†;:ˆ£P4êuAÇifg»®K„Äqˆëz¤ÓÀÎæI¥S¤Si*‹‹A€²-z:»¸õ'nÇó(¥ZÛ˶Iø òÙ, O2¿…âåR¯×™žnöÜI§Óô÷÷K!^FÕj•TêäD†Ç'‚Ó}'ÛÜç>™«Öš/ùË|ó›ßäĉÍ$ eVýólݺ•÷½ï}Í`„ãP*•èëëkï÷…ìS©T:m™ïûA°bÙj–âÒp F)Åâââw£‹ D±!Ž QÜ XÆúd0в ûö=ÏÈð ú×®£<;ÛÌ~4†Ã‡Òh4xòÇOP,–p=çž}/áQ«ÕÙ¹k7ÓSS<ÿìÓK„aÄžnæÈáCT©×kŒR«V©V+ ^«S,•Øuí ¤sy´>9¾å –…S›Âþ¯ß¢:¶ó¦be»QX€jÎÆ‹á¾øÛv\Ï5×ÝÌÓ'ˆ|:Á|5ÀÃMw¼Gø _øßÿÆ{ßón2™ÌŠ_“ÏçWŸÇqœÝC…—Öƒ>H­VkÏ~ °fÍæçç_4з¢:ø"Ùßüæ7Ù¸q#ûØÇV,_¦ì•p)÷é|ËNñòs<×ÃË{§eú¯“AJC¬[ÁÊVwï¥f«ã%èèìn¿§ÙýZ“LeN3M3»2Wèh¿WÇ1$ÉL®½ŽÖÍh:“£Ù©Ñ´ÆºT­†òò±-ÍK6æé»ŽÌΛP:fü™oàx‡0Zc9.qPX3Äûß÷>>ûÙÏq݆MÛ®%Œ"®Íã} Qå­oÿ9²¹qÔÜ7IB¼’ ÇÎâ¹ÅÓžÙÖÿÐ÷°-‡¾ùenÓÏR(–plë<òàWè_7Ä›îºËqi„‹LzÇó1Ja)(:¶íZóª(‡(eK·!„8‡ÇÒ8ÁBˆ—ÏÞ½{ù«¿ú+ŠÅ"o{ÛÛÚË_ÿú×óÙÏ~–¯ýëÜ}÷ݧ½o~~¾9AkËÒwwi.„åÂ0ëI€Rq™8·ëãwܾ÷ãæ×¿ßO𯱠tl›BÚÅÖ>õÒêó3$3yµ J)lO°B!„çczzšÿþïÿšº©©)žzê)öîÝKgg'ûØÇV #öÎw¾“Çœ?ÿó?ç‰'žàºë®Ãu]ÆÆÆxüñÇâ#ùH{ýÍ›7óÝï~—{ï½—Ý»w·ë|·ß~;ßúÖ·øýßÿ}n¹å´Ö<üðÃÔjµW¬<.å>oÙ !^~«¤¬7TªuªÕ:µjj­NÇ+ÊgJh\¹Ì`ŒZÙ¨6«‚\ÁÖ6AÐhNÖ š³Ò.ý2ËqéÚ¸“®;ÏøÞÁÁÁV ò³Ú÷Žmó¶·¿‹L+@YÈJ7!Ä«Óëï¸|÷¿ÿcƒ¶ðÆ7ßcÛä3~Â2ôn“n2B!„ëðáÃ|âŸh6·B¡ÀÐпýÛ¿ÍwÞyZ³ëºüéŸþ)_ùÊWxàøþ÷¿ÖšÎÎN®¹æîºë®ë¿õ­oå…^àá‡æþûïN)û·›L&Ã>ÈOoÙ !^~ʘÕ@LÍc=Á\%`~±F†¤Ó´Ñ—çWŠÅ…y’ÉJ)Ré$×îÜEW‡cY/ù~c O=õ~ïn»ãn:úÖ“ò, P !Î~݈CÂñçQ–‹Û»íÒÿ>4`’¹Úóôä_wÎï‹ã˜½Oÿ˜CÇžaÏžŸÆ÷äÓ.É„sE‹¿»÷¯¸ã–ëÙøšŸ”“S\ñáÓ•Ñ™¾áŒÃ?ˆóÍGWgq:±’y)óôÅ/~ñ´e·Ýv›Œ¸líÝ»W A¬ª]»vI!ˆW½£Gây‰D‚d2I"‘ ‘Hày®ëâ8¶ÝfK)EÇDQDEÌÏÏŸ¶½UkqZÊâ–›o Œ å…¥æ2Ÿ@áÔ}4ZŸsm¥…lfпð#ìM[Èù–œ¡BˆW5m4åú [¶oeÛŽÍTj6žÍ B!„BqùYõV§c+:óÍlÂWËÄ1Ë÷ó|&QˆÊ#˜(Äžü1¹Äÿ%g“âU¯ÕÙ{âG8¶ƒg'˜\ecç6¶¥vJá!„B!„¸dV=H© 9»6¯ž™­/t?ÒNçÒ¯{Osvp!„x•s-—ÍÝÛpm…ÆÙn:RR0B!„B!.)é¿wQZü(2—·âJø£`»ô0& aO‘OK¥B!„BˆKOÒÿ.ÑÍYË•í <_ DqE‰tƒJcX B!„‚æÌÐBÈù$Ä¥%™” Fžù>‹Ú#Ôó³³Xö‰TŽD&'$„83J9`Ù—ý®ZÊÁ²¤ò$Ä•t²•Ê–¢X­UÊvÚà !®létšr¹,!Ví|Bœ¡*Epþâ°A4˜<´—°Qgüù'8þă,NJá!ÎÌhâéãT¾ýÿQ}è¯Ð•™Ë÷§«™øŽŽÑò·åØ ñ*Å&ææÀØg81ýohJ¡\$]-SækT¾ý¿£#)!®pù|^ AÈù$Ä%&™”ÀõÓôïz-Q¶—Cs0tã0(Ü¤Ü Bœ…²°Ry”—B9>VªpùîªrHûëˆfgH'äØ ñ*g[>I¯e…¸N‡dI¯ÆuÒÏ¢ü4*‘@%s(KªÔB\é$óMÈù$Ä¥·j5*c ¤ÑÐ&&Šb‰Ƙ³¬ÿR<}9×UO}Í,_ëäd7zÏu1@>—eÓÆ çk°ð’iŽŒ3:2Âü|™Î5ëålB¼¸DŽøú`9.¨Ë7‘ÝR©[èñ䒛三«RÇLMM1>>J!®ç ZßÝÓê1æì5ó"uÇÄZã8.žë0°®Ÿ\nu‡ŽQÊ&él¦×ÿ ©kåà®F™Z6zík‰ × º¥(ÄÕÀ¶mº»»™˜˜Â¥»»Û–áW„8“U RAÀÑ£lÚ²©É ffçØ¼e-Q-«ÌŒiVÞ—*÷Æ´þÑ t²ìñR%¾½~kÙÒ6–¿¶bÙòm.ï²m[¶ÍóÏdíàF\Ïㅇذa=Ö9yäüqú×oåÞÏ~žßøÐ)•Jg\׃:ñŠÎw}!ÄåOÍtyžç§]\ÇaGižlve "Š"ǹèkÄÅ^C‚ à¹}£,T†8¤Ž²qÃગǥ¸ÎɵS¬¦FÐ`bršX%ñ<—ÑɬYÓ—H µÆÐР—ê"Úœ|lLóucˆ17ë0zÙkFkæçç)ÏÎÐ×?@ØXÀvÆÉfs«:ÌaŒŒ,26ÙM½2Ï–y\×;ïïŽ|ÇNZ\¬ptV3;oÓïVXë¥W})o!.?]]]LNNž5Gˆ—¢”¢««K Bˆ³XÕ¾)~2E6—§^oÙlž(Ž–i§´ƒŠœÀ\L¤Ì4++ƒ•¬ B.½¶<`¹lÛKûaY6¹\ž|.‡ç'Y˜ab¦Fw1‰e½x ò‘Gᡇâ†×¾ÁÛxüûñןº—ÿÆ)•:8tèÙl–Ç{ ß÷éë룷·—z½Žïûh­Éår?~œ\.‡Á`)‹ ˜™žÁq®¹æ9C…¸h£™žžåÐÑQºû‚€½Ïeç¶ArÙQqàÀÆÇÇéïï'—Ïá:.a’L&)Ï–I§ÓAÀÁƒâرcär92Ù –²°›ZµÖ žŒ1lݶ傂Ï8NŠÞµ9ÆÇlja˦!êõ:{Ÿ~šB¡€|ß§ÑhÏç Ã˲°m›XÇŒ P«ÕÈd2ôõõµÊa†ÎR‰çž{Žþþ~’É$¾ï7ƒ6Z“Éf˜™ž!•J‘Éf¨×ëT+Uæçç›;Ë¢X(P©TÂL:M½^ÇKxÌÍÍãØ6[¶l‘“N¬F3×óð9<Ï#;?O&›'á'0ºhädýCkÓ®o4ƒnÕ;´YÄl¾GƒŽ5ʲˆãˆ\¾À¼a¡Q­Ç¤“«“aLJG™«Fô¬YÇü|™g÷aû–!\×cnnŽ'Ÿ|’d*ÅÀÀ:â(fvvß÷I§Óض֚r¹L½Q§£ØÁºuë®ê3cq±Âñ‘q"‹‹‹ìÙ³G®b•¿¿FX–Ci¢(ÆŽb´n/ˤѺU¿±¬öÍR­ FkŒQ(KaZCΚu’¸¨lÖE4ÆhbmaVi^à 8~b”r%¦£ÔEk’©,‹‹†gž?ÂŽmCh­©V«LOOóì3ÏL&I¥RÔêuÐh4XÓßO:•¢««‹T*uUŸKÊ@»¤3Y´6$ÓƦgÑfŒÁµ½LNNòôÓO·³!;::èïï§\.322Š1š|>RŠ0Œ°m‹d2IE4 z{{Y¿~½tâ2”H$زe ŒJqΔRlÞ¼Yn< ñ€޾€mÙÌÍͱcÇŽ êZ¢T³‚Åš¸õ/ŠcâX7+ÊaƒCöã¸.ÙlŽÙÙººzxìчY¿a]Ý=ÍJ~¬ñ“IjÕ*ÃËrÂÇvxþ¹½8ŽG¾PdíÀz}ø»lÛ¾“T:CŤÒ&'Æéîíc~®Œ6Çv‚€bGg³ñpJ—ó%a4É Ñ_z3žszC÷‘Gþ‡‡zˆ›n½“†ÓÅóG§I¸6®m‘_³!­ùëOý ¿ñ¡²ió&&'&yûÛßN"‘ R©Ë娽{7¶c£cMGGÅb‘ÅÊ"ÙL–……ž{î9Èd2rv ñªp4”^ÅxEŽ/’ð,¨¼HúE~ôôavobóæMÌ–Ë$}Ÿuë¨T*Ì•çXÛ¿†RGét­cº»»ñ}Ÿ6`Œ¡^¯¯hÄ.e>ù¾,]ëâ—Ü×F£Á¾CGYh¸4 ÌTç£DZQvš‘©Eà‡¸ùæ›ðÍ›*333Í¿–jf‡iM­VòmL¬ñZ± ÑÀõ<´ŽÉd²tuvâ'}<¯9vqµZaçÎ y:ŠE¢8¢³£ÄÍ7ßL€Ás]¢¸™…žÏ壃Áu\Œ1är¹VÅï\ Ò¨çp–èfWm+މµ!6†j­Áñ£/07?¥Žë͈¹ò½ýý­®Úʲ>~¬}C5•ÊNgÑFãz üdºÕýûdï­)W§†tænáB;û6'F&›mP7IæFç1¦¹Qhá;O?w„k¶ rûí·Ç1ÕÊ"¶ãG®ëb;6A¢Ë¶H¦R$}ÿ,ߟ+³[r[ãDLRY$[¯µÇ2Ö¤[•¼S—×Ï5øGèê,FÇr¢Š³jö²ÐD±iÝ|5Ø–"Ò†ñ±ò…ÜÈæ±]‘‘<óô“ ,rù<[¯ÙI¬5µjù¹2(Åèð0¥î.v^»?µ¼Nb¡Méê}TǾK&1@5~ÑýS­úÉòz¡\/[ÌÎ RêÞÈôð,•zH!“À²š½S/ÅÔÌÏ?ø¶t9¸¶"¯l01( £›7™½=C­Ùaý´’2aS/£WV6³ž#Ø÷ÆöÛð.êknÃöÒĵžcc DqŒm;XN†CÃG˜kŸo'!Îз¦£ ½½½5@·6ÍLʨU‘µ&ÒÍçݽÜòwà:.½}ý¬ß°ÇqxÛÞB£Þ  †‰ñQ:»zضýºæØ=a€ŸH’ð}ìÉ nûÉ!\/ÁâÂ< ‹ ›·¡µ¡»gMsœÇBËñ0Z“+–H¥ÒÌ•g9~ô^Â?KóUc[%Ö—þ_Œõ}Ö–î"Œ¢8 ™HãZ¡ŽøðoÜɧ>õ7<üà×Ùrííhã{ZÐ ¾uß?ÓÕ»–׿ñnÊ‹ùŒ‡ w.ÄÕ+á{lÞ°Ž}GÆ(æ{p«uÓÌ<¨Ìϰqým䲇ZPÁw“8– ¨U˜8᥇±°m›žž.ÊójµE¶ vb´&ÒÍ+fkfËSt”:ñ‡®'Nht}žt¡‹°^ÅOg[ ïWÏÝa5P}ª5ˆg@)ÝM5¨Æ nÝô>üáó×ý×èØ°çÖ;‰¢˜°Qå‘oý]½ý¼ù®»ñ<ËR â*g)‹Î®Úž?öÐ7Ùví-|çk_l(ïÁó|ri—lJjrBˆf ²»»€½ûOíè#ŽBÊÓ£l\K¡PÀ÷lòiP7èË÷ãÚsµ2ÅT‰ŒŸ}Ùö5‘H°cÛfö>³ŸòlL*“evzš”gµŬGì0õ~‚Z…D:KP™Çr8‰¤pqÅiÞx5Äqë±­#Z÷RWTT º]»YJÒ5§¬h–ÕCPÍÔF¥NÖKšïˆ_²Š¦”EÎϳ¹kÚja×öð]ÙwÚcýº~´>Áèô$™\‘ÅŬ¸Ò P&\²Iß±¡«ÛmÎ@Ýìîâ¥rX¶ô—Ëf3 ­ëåàÑQææð)æçfȵ”)ß#›r°mC1UÂw“„QH%\$Ÿ,Xv|„B!ÄJ«Zó\¬.2=3Ë\yŽò\™ÙÙò)]™VVЗ´C’æ,ë]¶m³¸°Àüü<¾Ш7XžûØ“ë{‘ j–øÃ|üãçð¾'Y¿ioºë. P !Îh)P¹ÓžxöF6 P(äñv{hÏN°±kë+º¯~ÂãÚ[øñÓû>>Mg!ÃÐÐŽ£(f<\ÇÆÍñ³E9°âÊf ÌÎVI$”çÊ$’) ¿¹|\Õ ©·c¨,.°°°ÀüÂ<µÊ"ɹ͞m[6ÅT‰bªô¢ë%×¢õ Žœ&“öÚÊ\Ê%å7«‚¹îµäº×Êq?Ùl†Mƒ}ì?r‚áÑctwv°¦¯‡¤ï‘K»$ÜæØc]Ù),!„Bˆó°jAJ×õعe€™¹Y\Pʧ©-LžVá_AñŠM°+èïëÀÑ¢j…õý͉rι‚šåøÿqßÿæö×ßL"‘"›²%@)„8#KYôtupãÐó5C¦£“¤§É¥/¿±k ë¯Ý„ðaº»vaÛÅŒƒëÊ ßâêáy Ö­é"ŽFY¬-БKaÂQeÕê.HX1]ù$ºQ&ã;”J%tlVý;=´¾ˆrOàûI$dSv;@)Î_6›aK_š.§ ¹<©”O6i·”B!„âü­ZíT)Åök¶iX¨„(¥ÐÆ\Öã2.ŸÓ:Ž8Ÿ‘$c]'4Ç0ÎwÈg~…´/£P !N5&=K¶k ~Â'™M„e’Éôew ‑òq²~–Í›ndnq‘„—Äur ÅÕUArlúz{éîî¥RˆãfGìUÿÎ*À,uóc4«= ¨ASŽ0oþޤûó2w“ð¤Îra…i¨ÎM‡!ŽãQêêF» 7Æ“Ù[…B!.®¾ê´ ˜}µfžß~ׂQŒ±ÐŒò5 •S!Äé Ú(Xœ¦|⎟B‡õæ ’M×RÜzYín#¬sxr?¾—DÇšéêÛûv“Oo“c)®J¶¹Ô«;ãPë:µ`­5˜)zzz°¬Ë$ëGYØÙ.T"…+b§;ä  !.óë²GÆ #»ƒLrP”B!„¸"­ZRÍüq¬ ‚€( I¦Ó­L-³ôß)­Ù•OÌ)ËÌißÓ—š3<1gx÷™ƪ• ~2@wgí×l;çÏëÙ‡ftd„‰ñaÖ®Ù$g“¸ì4 ž}öYɘçE)—¤»‰tüv|·ë¢·7::ÊØØÛ·o'‘H\Ÿq¾a˜ S°7±]ºL !.‘8Ž91<Âøø8q¬ £×v±}êßf³¢F|Z8ÒuÂx7“–æ õƒåkž¡þlVÔ•‚8ÒDq„eÙØ¶ÅšÞn×⹞(!„B\V-H!åù*Ûw^ÇÄÄ8ÓSS¬ÜBEíà£iW˜ ¦´4­ÿµŸ·^_ZߘÖúK/³l™Y¶lYEìä:+·œ¬*‹ãG~ÌÆ-ë1(;ʶ­[±¬sˆ|ä‘ÿŸ½;³¤¬ýÿ©§¶³ŸîÓ{ÏLOÏÎÌÀ ›È"›È"æ ×är£Ä¸€F}%Æ›`òŠæz5¹AM®1‚5øâ^•%ÈffŸžÞûôröªzžßçô™nf€˜fø¾_¯™î®SuªÎÓÕUO}Ÿïó<ðȯÍÒ'ñÍoü€÷½÷Ýtuu7÷?[1uœÃ/bc Öœq´ÑÔª5|ߟ·\ˆÃQ­VÙ¼y³„8b•J…»‡¨†ìص—eK7³ µÖ‡Ìˆ ÃÛ¶1T#èEZëæupóæÍ¬]·–x,Þ¼ÆEat ;¸EsÛC=èG:š÷0mŒ©ßcŒÁ󼃮§µZíAÑ©©)n¼ék,^¾–'¶í ~÷Ý\rÉ%ó®½Q¡”j~Ög_ƒë÷™úµþH3DŸï؄ǗZ­F¥Z#ÙÒ‰£òùq²-9R©4ZGÍú«Á`ôzð¼ú¯™­¿Zõï1­_iÖoçÕ}õº±il[-ÉOLJ¥±,ÅØd‰ÎÎ ®ã!ÕL!„B,Gµ»·ãº(ÛÅv<×Çv<Ìœ.Ðóƒ•Výë!Žs¦ÀdN0²¹N3Àiæ­7ûE›9YœÆ Ë- b±¾ïe1Âøt•¶Œÿ‚Êx€_üâœ}þe,î[ÁÆG2ÜxÓ×yï{þîîn¢(âþûï'—Ë‘J¥ˆÇãA€çyÔj5ªÕ*Ë–-c÷îÝÍÜjµÊþýûY¶l®ëÃÃÃ(¥Xµjmmmr¶ŠÃ¦µfË–-RâˆU*UvîÀ‰gIú1¦¦'Ù¾s+–õECCCttt0‘ŸÀhƒÖšx<ÎÞ½{q]—(Šèèì X(211AµZeÉ’%8ŽC¥Raxx˜O<‘D"ÁD>ÏÎ;X·når™jµÚl”1Æàû>Zk&''' Cúúúð}ŸééiÚÛÛ¤\.ÓÑÑëºø¾1†J¥ÂÔô4Ë—-›wýœššâ«_ý*‹úVpÆ9ob*?É¿Ýþ] pé%—[¶l¡X,ÒÒÒÂÈȤR)‚ À¶m”R¸®ËOðu^o–Æ÷AXk¶î:®‹1i°,”RX–Ei"á8n3²†!–¥•>«™u9/ªi)ŒÑDQTFÎ7™ß¢<Ûê\_Å -3@yú9—нhA²ö¤Ó©šoú:ïß{èèè òù<¥R‰™™”R ÇY¾|9SSSìÛ·(ŠØºu+}}}$“Ižyæ´ÖÌḬ̀råJÚÛÛI§Ór¦Š#2<<,]¼Å«T*ìܳ'–ÅÅCï'™)ؾcýKQ(êëíÜ @"™¤£½ƒ(ŠÈON¢”E±X$”í ”bÛ¶mT*Uº»»Èd²ìÙ³‡¾¥K1Æàº.Ì ”J%â±ÅbÇq™)Ìà:nó~àû.?ü0¾£³³cY8ŽÃôÌ ¥R‰t:M©\¡T,àû>ëÖ¯Ÿwýœ Pöö-猳߄Ö?‘â‚Ë®æ¾;ÿ€ /¼8ŽK±T"žxâ :::QÊb|b‚0X¹rår™r¥ÂÐP½A)“ÉÇPJ±oßÿñðÃd³ÙF–¼Âvll¥È¶´²xñbbñ¸œtB¼ Š Êh¢F=9l4òÔ«®ÆDÒ¢0¤Ÿ´š3xGQXï¡ãúìm]O¬Ô`©F6ŠšÙ—³Áɹ½‘´>аo«Þ˜Ïá×Â0ê -ÒÃG!„Ç‚ðÌ3φ!ù|žõ'®'“ÎñYV½òFõ Øl€1ŒfÃsâˆÚðà¿ÄÅñ\m ýËVðäæMx±8-ÙVªÕ -¹6ÆF†ñc±úÁ:S“y”m“J¥©T«ØJaŒAÙµ †Ž"\ϧR.c;ËV¬!jt9?±Ùè2sà豌Á n¢ðدHùN,ÛÅh=o½~„_>ôœ}þåL›,[wá{6ʲˆw®¦_k¾zã×xß{ÿ7_òf*• ŽãÔ‚fPU)ÕÌÄ9ûì³QJqÖYg¡ŸÃq*Õ ¶ªgÜÄãñ…3Ù„xUˆ¢H&ÉG¬\.³{ßU“d4_ñB"£±-EdFvìÚÇâÞnÂZî3O¯_××õ°¬E„a½a( ÃÆõ®Ñ˜­ݲ}Û¦§3‡Ž"–öváz.S““¸®‡ç{ͬ  ëñ†z€ÏR„‘Ë€6Ä Êå2Ëûáû>ʶ©VÊ€Âvžc£‡Ÿ ¸oÕ¾7rÓwÿ/‹ú–sÊë/b`t†r-ĵm‚HqþeWóó»þ•J¹Ìº5+IÅ<,eÑšN²¸§ £#\ß§·«Æw=Ò‰õ€BPo<3F×3¦\K‡œzòIضš3D‰ifTV+öî|æ5qnuõôO¤äL¼fmÆÆÎiÐ×Í4Gš½~ªÕ*ûöíftx×óˆÅâd³­a@±XÀ÷|P¶í†aXo̯VË(åÐÙÝC,–À4úëÙÿ¬]ª¿€b±Èàà 333$“I–.]*ÃU!„â˜pÒé4CÃCÌÌ̼¤Á³µ†0ÔD‘!Ô†04õ å³2º¢($žH1>6J{G'¾#BR™vl߯øØ(Æ@*ÓÂÔôÁØAP)—±,ÅÄø©tšööN¦¦&¤wQ¹¶†÷11>N{GýËWb´&ÒOÞ3¯زQ3¨ûþ7µ©}TsKA)ÐѾáüÕ&zûVѽdãÛG©ÖB’q—J5¤Z XyÂ÷>Ãï¼›÷¾û]$“òØ–E%q?ždhhÉÒ^:²>”¬Æõ‘ÆØg†Ùæ”g7«Ì½Üjc¨c Ð’NeQ3Ww­‘ï"Sgî%18–±Ls[·¹E ½¿¡úëåþ–g°UŽNz=Ú´×V”*Ž£H&S¬Xw7þ‚‘ÝO¿<ã³½²'fèÉ¥yÏuÂò¤k»xm2"m½| ‘6D‘9Ð{ε2BÊ¥2µ Àó},¥ˆL}Ý0Œ˜šelt˜ZµŠçûAà{>‹úúѦ޳I3§¸¦™‘ùbxžG<gbb‚0 ¥ñ\!„ÇŒÐÑÙA:¦§»ç%È´©%g³)g[Š™­‚5ŸÇK–.§Åjt‹%À‚þe+Y²t9µZ ˲p—õ'@ ì£wQ_½åÙ:ЦV«â6Kú—Vc²— Œ^¸Û« ÑÙ¥˜ ¿Ibò7ÄÖœODÌŒ ’é\Dµ8M,ÝÊ{—œÏ7ÝÄ÷ÝɺÓ/¨?DÛŠr5ÄU÷þø_èéíãâK¯`bºJkÚ—ÈÅË.ŸÏK!ˆ#bÛ6íí9Ê•S¥i–ödÑQ½§R«wï›ÊOÐÖ–#Ö½žÈ3„ӣijm„µ2n.¹ü­ØÊÆwm PŠW„dRŠûºdqÑÞf¦¦H¦3X€ïÙLMLIºtuu¡,®–™x†ñ]Ob»:а”"·ôÒíÝ ç<µlœÜœÜÞtá…m¸÷Çßç‚Ë®&‘J÷]¶lz˜ÝOoâÊß~8JSÞËè3O`ûŽŸ VœÂOfYrÊy¸±„œ0Gü»¢x-«7â+cÔ•ÃúìÜs#‰ÆPŠD" –iŒ+©‰48®‡íxÍõ\·>Ò옒ÍY¾Ck‹{ij{þ!„BmGuvo£!Ò M½åØÌM ÄšÓb<§éxöµ9?ÎÎÖmÑJg~‹só¿ï=û dÍùï¹ö¶”ÂR³“ô¨Æzº~ÐÊ"–n¡cʼn„•2^*CP.b)E¦µë®»–¯|å+<úÀ½¬>éLîÿ·[æ([Ò‰˜#g—xEA … ^äC¨Cÿ’EìÚ½‰É<Ét¶ ìîêÆQNzAëâUÔ*E/†k lb©ì‚>O-Ëââ7]À}w~ŸsÞü; ì~š]Íe _‘N8TÚº±” 8®OP-áx /&'ŠâˆÔ»`×ë¶Zƒ1³ÅõTS8ÐsêÃêØfnÕ÷92%Ÿ«+öì¸è–²°”B)…–Æ!„B,0G-’fY3…i÷099ÎÔdžD2CÔ˜ p®gשæV²^®º, ?>ÆXv,‹jµŠ5§¢è'3øÉCO ”N§¹îºëøÛ¿ý[v<½‰kNæ’Ë.—¥XdVoñR¸®CÿÒÅD»ö²o`ÝítuvâØJx8¶;FºsÑ«ò<=¨4üô‡ß@)›«ÿ½Íe&YÏTŠ·´oi—Bñ¯9P­T-`ŒEazŠR¹L"™jLÐ8¿îûìKãѺRZ@¥Rfzj’J¹Œ²mžŒ-)„Bˆ…å¨EÓ\×ãìÓOdbªHÌÎÐÕ–Á¶#XÀÃÖœ|âÛFC_ϴч½m:æ=ïy?úñ÷¹ðâÓ±•GKÚ‘¥âUÏuV.ï%žœ"•ìFYJ8¸Îññ@kYoºèN9})ÓM*¹˜¸Õ³D…â(ò<ŸåK{HÄ'˜*T2~½Ò/_Ë|ýÊG:£-Ó…²êÙ”étš˜«OX&„B±ÕˆÚ’%‹é] ÅrˆeY >£kî1ÖÇÅÔG4lV¨F»(뱨åñ]é6#„xu«†öç÷’ŠgiË­`ºò†‡‡¹ñÆ9åä“'våà¶/@kÍ=÷ÜC:ýÂc> R©”œ G1!.a[cB,Kn‡G¿5& ê_k%ˆe$X)„B!„xNòTö¸¶K5¨°or©n PŠãÞ©§žÊ'>ñ ®¿þzn¹åÞûÞ÷6_«V«|ë[ßâ®»îb``€D"ÁgœÁýÑÑ××7ï}Â0ä–[náŽ;î`ç΄aÈ¢E‹8óÌ3ùÄ'>Ñ\ïÙãJV*¾öµ¯q÷Ýw344ÔªëׯçÏþìÏhiiyÎmòù<_ùÊW¸ÿþû™˜˜ —ËqþùçsÝu×ÍÛvîöïÿû¹á†زe ©TŠ«®ºŠë®»î°þÞo»í6¶oßÎ_ýÕ_qê©§b¢à u”R\zé¥-ŸÝÿµ×^Ë—¿üeüq …>ú(ããã|ó›ßdãÆìÞ½› hooçœsÎáø­­­‡|¿k®¹†/}éK<ýôÓ¤Ói®¸â >ðງž4fóæÍ/úó/\šrm˜­ŸÇuZ9­ÿïq“òh3A…`pÑØNÊ¿¹•Ô?È}R!„BqhG=HYŸ„À:ðýs­øŠ>§XÔ;ûÍ„9â:±÷öEûØÛÁÅk/E!³ÂŠ×†K/½”Ï~ö³üò—¿l)ƒ àCúO>ù$W]u«W¯ftt”[n¹…k®¹†ï|ç;,Z´¨¹îÿñóÐCqÎ9çð[¿õ[Äb1vîÜÉ}÷Ý÷¼ûþô§?Í]wÝÅ›ßüf®¹æÇapp‡zˆÉÉɃsÍÌÌðîw¿›ÁÁAÞþö·³fͶnÝÊ­·ÞÊ#<ÂÍ7ßL2™œ·Í¾}ûøÓ?ýSÞö¶·qÅWðãÿ˜›nº‰l6ËïýÞï½`YÝsÏ=$ .¿üòUÖ{öìáƒü —_~9—\r ÃÃÃÍ×vîÜÉý÷ßÏyçÇÛßþv”R<ñÄüð‡?ä‘Gá»ßýîAc‡îÝ»—üã\uÕU\yå•üêW¿â[ßúƒƒƒ|ö³Ÿ=hÿûÆ^Òç_¸1·®– °UB”ÇêNëÅqÚ–aÅŸÄí{=X2³±B!„â¹µ ¥Öšz,›jµJ¥R¦¥¥mL}SÎýÁÌÿqÎ÷sÖœóÂ6Ö1ó—b_s×ǰ“c$ÓY,Ë"›ŽqîY‡?q…­l¦ûiCoaÑê%r6‰×Û¶Y±b»wïn.ûþ÷¿Ïc=ÆM7ÝÄ)~O~h IDAT§œÒ\~饗ò;¿ó;üó?ÿ3ý×Ý\÷¡‡âÚk¯åýïÿ¼÷þÈG>ò¼û¾ï¾û8餓ø_ÿëÍ[~íµ×¾àqß|óÍìÝ»—¿üË¿ä¿ü—ÿÀÛÞö6V¯^Íg>ó¾õ­oñÁ~pÞ6»víâæ›ofýúõÍÏsùå—ó£ýè°‚tÛ·ogÅŠ8ÎüK­1†|>?o™ëºuåÞ³gŸûÜç¸øâ‹zï“N:‰Ûn»m^Fã•W^É)§œÂ§>õ)î¸ãÞþö·ÏÛf÷îÝ|þóŸçMozSsý¿ø‹¿àÎ;ïäꫯæu¯{ݼõ÷í~IŸA31ìòE(ûÕס@ÍääããyV­X¶€»P[<=8ÍH-ƸÓM¯\>…B!„Ïã¨=A@¨ë7¼Ž‘áaÆÆFYu‰„a€iÄ gƒ‰õ@¢i,o,ß××£±ìÀÏÍõÁJ3»ýœí˜·lö}LsßsCÙ6CãE:s}x~Œ‘½OQ "\Ç>¬ç½ßfüÿY|ÆZžú“ ì¿Ñ½¢£ùz-¨á8jNæHµZÅ÷}¢(B)Õ .LOO“J¥Ä$BŽT*E±Xlþ|×]w±jÕ*úûûçß’É$kÖ¬áá‡n.ûÉO~BKK ï~÷»i¼À_6›eÏž=lÞ¼¹8;\ÿþïÿN[[¿õ[¿5oùÛÞö6¾üå/sß}÷¤\½zõ¼ý$ Ö¬YÃOçßíÏ~ö3ûÍã,]u"ßüöwùƒ?¸†Þžžæ±„aØ<&¥Æ\×EMP 0Æày^³¼Â0lþK$Ï{Ï|v¯Ž jÁAÙÒB!„Bˆ…㨦X–EA½“·Bƒž—ÕõÇ c™ÆO¦4TDQÔxŸz`Ѳ¬zÒ#Ìé‘=·«¶Á²À«U mtýýIÝxZ€±fƒ”ʲplØJjÃèd™î¶$ö Jv~o˜Ý?&ù')Úú;N²ùcð÷4•üêR©]]]LLL¥R‰lK–Áýƒd2™ærSSS¬\¹’ÎÎN9#Å«B¡P˜÷°¿sçNªÕêsÔæ1öìÙÆ žs Äçó'ò'|êSŸâ]ïzœ|òÉœyæ™\zé¥$‰çÝvÿþýœ|òÉT”R¬X±‚M›6´MGGÇAËâñ8Õjõ°Ž7•JQ(^žLðå/¹ù󳃣³–.]úœï­µæ;ßù·ß~;»víBk=ïõ©©©ƒ¶Y¶lÙAË–/_ÀÀÀÀA¯µµg_Òç_ˆ¢(bϾÆ&«tööR«…ìÜ?„–,^D-¨±é7›˜™™¡µµ•¡¡!ÚÚÛI%“T«Õæù“Édxâ‰'ð}ŸÖ\Ž( ‰ÇãÔj5Œ1¬\¹’Z­F¡PÀ÷}FFFæ•]†8ŽC,£Ô8yÃÉ/xìÚh&ó“<³sŽ®%h ?1Áæ­Ï°þ„•„aľ}ûغu+‹/ t¤‰Çã¤3iFGFI$Äb1ž|òI:;;'™L’J¥ÐZ×ïÇJO$l~æ––Œ1ø¾ßlX Ã5kÖ2ÿ³ŸýŒzˆ /ù¯´wv³1–àßøïþƒkèíí!ŸÏóØc‘H$‚ ¬ìèè P(022BEôôô`Û6–U”Öj5¦gfȤÓ8®ƒïÕþÇ¡µµ•}ûö‹Å¨T*DZãØ6J)Ç! CN8á„1©–B!„â`ÎìÃn…Ôªµ=s¬eÖ†0ŒÈHkÂPFçF\1jõìS_`Y®ç1“Ï“Éd±­   q(… #*•2–mãØ–RXÔ÷iY@##Åócõ`§HGxž_ÏÖhƒ™“©™@µ]^hlÊßf÷-ÃØÿ_œÔ¢•jÄåiª5Ý T¶÷µL&)•JlÛ¶r¹L¹\&•J1::Šã8ÌÌÌ0<<Œã8ô÷÷ÓÖÖ&g£xÕyf»1Ï ˜­]»–øÃÇtß]tgœq¿úÕ¯øÍo~ÃÆ¹çž{øÊW¾Â?ÿó?ÓßßT÷÷R'‡Y±bO>ù$AÌ Ê:ŽÃ™gžùÂhç¹Û‘¾ð…/ð/ÿò/œwÞy¼ãï ­­ Ïó0Æð¡}hÞ0/þóçîž}Œä+´æº¨Vj&™i白# §«“x"í¸(¥Hg2ìÝ»¶¶6|ßg||­5K—öáy>Ú÷¢l›d2N,–Àu]‚0 »»›Z­Æ£7284„ë¸Äb1ªµ€Lº~X¿þDR‡1³ûlåÓ;öÓÚÞK-Òhmpc)&f&yzûnV,]‚ã8¸®Od û÷ 05=CG[;Kú3S,O&ÁRd²Y\Ï'•Î05=E¡XÄC:•fhx˜žž×£X,iؽw/éTšd2I,Çó|ºº»I&ucš'Ìl€òü7_E[g•ZȪõ§ßøæ7y÷»ÿ€T2I*“%æ{ŠEÊ3Çahx„0¨áz>.084„1†ÖÖ6Òé®ç†ãã´´¶0™Ÿ¦Z«ày>(ÅŽ]»IÄãDQ„mÛxž‡m+:;;Y²¤O”B±Ùìéj­Š­êW2Y¤B!Ž`Û¶mDZ36:Ê)§œBú0˜ù¨ ¡Ö„ÚEï£Ù=Ží°cÇvöìÚE"™Ä¶mÇeqßR~óØ£´wtB£+v*ab|ŒT:ËÌô‹–ô1°wél ãc£d³-K%ZZZ ÃééiÊ¥ñxŠr¥„mÛT+UâÉ$«V¯Ãõüf—oŒÁ¨g=Àë¶ÿŒ™½w“<÷¨DëAŸoç¦Ø÷£©?I3¨-FvŽá»6qßaüu𓿉°îï4gœqÚh0õŒ¨gl5¿·U³ûàl–ˆ¯ÿöoÿF©TâÜsÏm.ëëë#ŸÏVàméÒ¥lÛ¶í ÀÝáJ§Ó\vÙe\vÙeüüç?çcûßþö·¹þúëŸs»E‹±sçÎyÝ@¡`ݾ}{sbŸ£éâ‹/fãÆÜu×]u3©~ô£±fÍn¸á†y˕ټ†íÜyв;v4ËçxE!»÷íg,_%™é`×à$Õ Âs´Ñt¶vðôîLPeÕ¢¶æuÙÃåDQÔ÷׃ƒžË }‘±¨w£¶”…ë8h­‰ ãØÀéë—®^Šã¨ú=±ÑHgŒÆõ=QaüÙata”òþwÅ…2«Ø¾o;ÑΦãtd㔪`Û1†óL¸ƒeÝZO^m+V/j§X,ÏOÐ×™feOTýÜïÎ.ÃVЉ6†0PÊFÙzí2lÇÆÂ"Š"ŒÑDQ„eYõÏî:X–ÂR ‹ã˜òÕ@¤yh*ÇüçfÞø¦+±ã­LªŒM–Á²Èô®§øú7¾É%žC{&Rö˜LhbYõ:ˆe5#nÜ7Áè€%åÔ3Ec Œ‰×»Œ‡E6¬êCYõ^Æh@aŒÆÑU&‡w39¼çe8Û,âÉ=Kúe² q\(‹ 199I*•bÙ²e’‘,„BˆcÂÈårLMMaÛv3ˆöbhc#Ci"Óø‡R›ˆD2¥‘68®M¤5ÆXø±8;¶?ƒR6}ýËØ·w/Õj…j-dßždZZqýCƒûñ<Ÿññ1FGG˜žšÆql†÷“JgÇRŠl¦…üdž±±Qú–®ÄqýF†æ¡ž',¬Z{Ë M¸òüAÊ9]̇oOR;§Jzqû÷L`qßiN??Éô£žúú=Ÿíª!-ð¼ã‘=_f” ÝÆùÜç>G{{;W_}usùå—_Î?þã?rÛm·qå•W´ÝÜ™·¯¸â n¸án¾ùfÞóž÷ÌË<+€ølSSSd³ó» oذ€R©ô¼Ç~á…òõ¯Ÿüä'¼õ­om.¿ýöÛ™˜˜àª«®:êåuå•Wrë­·òw÷w,Z´ˆSN>é u^lÆãlÙg»é¦›žs›ÑÑQî½÷ÞyãR~÷»ßà¼óÎ;®ÏÝ0ˆ ‘é®­Ý€£(¢>Òˆ…ã%Øöä“t¬HbfÇhlœ¶‘³À4Ç Ánœ²jν,Â9¹úʲЦ#œwßÔ‡8^c º0B°å‚ü>FV¼b‹qlßµë÷ǦÖƒˆ–í³{×3äjMùÍckZZ-˜Ø^þdö˜,‹ÐÌ?¾æ±[Qó5 ,˜±R1gœèÙÏPž$Øþ ‰]ü:6+ÖN6×ÁH¾ bžM¹†%ËÖ1¸gwßóïtåRX÷?D¼zO6cØ1˜çþðwé]y’Ü8Ä«^,#NS©TšãÒ !„B @{{;¹\ŽE‹Ç_ô›iM½‹wh_çgRF‘&ÍqÚëÏiNhà¸.ëN|žçéÛvš“ã„AµëOFÙ6Æhzzkø~Œ( £Ûq1Zs‰!¶rÃ, £ Žë†!®ëòa~î…Žåˆ.øZj»ð»W1¼ãIÒK*%¼DÛñyÝ?Ác´ƒ=åôþÎ"”e¡,¨…šdÍ¡ð™8]³êºÕägªä2ÒÊ,^FFF¸ãŽ;€úD###<úè£<úè£tuuqà 7Ì˸þýßÿ}|ðA>ýéOóàƒrÆgày<øàƒ¬Zµª™åxõÕWóË_þ’/ùË<þøãœuÖYÄb1vïÞͽ÷ÞËøÃç<®Ë/¿œ³Ï>› 6ÐÚÚÊää$·ß~;À¼À㡼ë]ïâž{îáÓŸþ4[·neÕªU<õÔSÜzë­,]º”k®¹æ¨—£ïû|ñ‹_ä£ý(ï{ßû8óõ¯çÔuËÉårX‰üìg? ·÷Èæ>~ó›ßÌí·ß·?üaÎ?ÿ|¢(â¾ûî{Þ`m__ŸùÌgزe K–,áàÞ{ïåâ‹/ž7+ûñÈ÷=NËqmäñÕo¤R­pâ©olô·ˆÇ\ 3Óüâî[Y¶r ½ùr¾ƒSËS+ˆ¥ZküT JãÇyµö/ÐÕßøÚ×(—Šr3ÇÇÂãÐÑÙAkk+–eIƒ»B!Ž]½ÌîùR”Ðèî"­ßÏRÖ÷¥°l›ÙlÓØÎ‹Å1¦Þ Z›Ù™¼-l·è«·Ú*\?VÏQŽrê™WÊÆm|ïzf(5<Ï>¬_ ÜEë0QHqt€‰[ð’i¢Z•jqš®5§púWÖòëë¶1®÷Ñ~õ"4 ¦¡ôù1ôéë¯[ƒRŒKN¼z=ýôÓÍ ¢ã8´µµ±råJ>ùÉOrÅWt­p]—ÿóþßûÞ÷¸óÎ;ùÅ/~AEtuu±aÃÞö¶·Í[÷þáøÞ÷¾ÇwÜÁ¾ð´Ö,^¼˜7¾ñÏ{\¿÷{¿Ç#<Â×¾ö5ŠÅ"Éd’õë×óñü»š§Ói¾ñoðOÿôOÜsÏ=ÜrË-är9®ºê*®½öÚc6ëoOOßþö·ùÉO~Â=wÿßÿw0=SÀõÀ\pÈmúúú¸þúëùÒ—¾Äw¿û]Òé4ï|ç;ŸsâžãŠe‘L&8ñ„eüfóvÂD;®ç¡”E±P Z̳zÕ |×ÅS!åüãÛgl»Á‹§©¦ðâ)úN¿/þòÌm9nÏÚúß‚V.cóÖLŒ‘δb´&Ò!SC¬\¶„dÌ£´ÿ)Æ #è°‚íúè°F¼¥“Å'…=g–ñ£{œ>N®¨gn¾ÿ}ïã«_½c 'žúF@Q.øÕOoeÙÊÕ\xÑ%¸ |«ÆÌØ ùgÐAˆíûè †—jañ†³ðâ©Wñ '™fâø¢,5¯gB!Ä1y¶0G©ÏF­Vå§÷?Jߊe2?ÆŠUk‰ætŸ»#cžµÄÌù2'ËòÀÑ™ƒ«ü/áÈ•m³uó&úúW‹ÇÙ½íqÎzÃt·%Q–¡<5AP)âÆ’„µ FGijíxñ$•ñ¿¾n…õÒwSþÛñyʶŒçÚrv‰WÄÆ¥jØ" 'våà¶/{Y÷}Úi§qî¹çòÅ/~ñ°Ö¢“ÅMtdÞpÌŽéÔSO}ùÆP(yìñg°üÆh*…ñz€Ò÷É$’1‡ R¢<“ÇR ¥l¢0@Ù.É\Ö+8Î`lÞº±¢E<‘brle}½är­Ä\ Ÿ a¥H½›¶Æàx>ñLîe irr’¯~õF:z—Ñ·rÜûY¾r5\t)ž£È¦<\Ç¢V.R+Í€K)ŒÖØ®K<ÛöŠ–óKQϤ¼‰ Î}+6¼aÁW-Ì3UzŠlbž“9ÊXšhz„p|þò³_3×ô0¿]Êãä–¢âY¹É¡[n¹å eçœsŽŒBñ*²{÷n<ÏÃ÷}âñ8¾ïãû>žçáº.Žã4Çû·¬ú˜÷a6ç–y¶£–î§,‹™éIvîØÆÔä$…™)”í ÃèÐõÙƒ~6‡~áQÊfldDZq\r¹Ôx 2X–"ÑÒ´rÛX›Çé_YÅÃïÜJðð8úl P !Ä«eY¤SIN9q%=ö‚P±î„uø¾WPÆë“9¹ñ$îË”1y$\×eý +Ø´å)v<ÅÚÕëhiÍ’ðmÒ ËŠAºå?Ζ–Þÿþ÷ñ÷ÿ÷lÛ²‘uNã‚‹.Ãs,²)¯yŸôiüDZNL!„B!ÄÑ R:®Ç%žE~ºH~º¥1ߌµ Ç”ZÒýúÆì­†ØÊ%õÁÀsÛX›Gÿ?e¹åÿþ„+®ü]Ç¢u΃—Bˆ…Ê"•Šñ†Ó3]2xNŠD̼j†ép]‡“O\Jg·&æuà:é„÷r&J–––®ÿÔ'ÈÏìAë\Ç%PrŸB!„BÒQ}"kmm%ÛÒJW%¬O^ó3õ.sz» öït1`d²Âã;&ùí û±•%g”B,`Úh†§Èï¦-Õ‰ëøŒ–ŸbEzùѾ%ƒÛ•aªœç©á-t¤»ˆù9FŠOÒ×¶ËZXcÅUÂ2{t@K[Ù8Ê¢ZÛC-|U(›7mKáÚZÏP¨lÆwüÙHfY ÏöPÔ¨†;±­žíˉÿZ¨ !„BñbŸw¤„8¾¤R))!çé ¨‡RBô«4¨bL„6áÂ?N£1Hoƒã’Ñ•2•â4øIÈ,’2B!„/šô»: ” H)ÖÖV&&&¤ Ä‚?OÅñÍQ §(Õ†ñœ®Â’ñ(+a­J~ß6¦‡öbû1,e£öìÂKei_¶Ç‹I! !„BˆÃ&O G„(ÅB"™”BÎS±h]#_|Œ§¿ÀþüÝR ÇcýGÙø© ±t ×OE–UM!„Bˆ#!™”BglÛ¦§§‡ÁÁA) ± õôô`ÛÀ8î¯E*N.õ:–äÞBwËù’Ey<þŽ]lw?Ùî~LXE—'±Ó]ÇlQ=kÉK®Áâàá\­æûZ–%ç¬B!ÄËL‚”/’цᬰ|ÓZ¦/(‘<)#…"Œ®®.†††02‰X`,Ë¢««K â5"¨f)]@Í”Çñ* CFöïglÿ.N8-‡ëºG÷< ö °cç\×cjj’D2‰çú ÆÌŽJýgݨ«ƘF(³¾Þl\Sc@7¾6V.f0€‹“IÄX»f=Ýr½B!„x¹HòEСaÓŸïÂs<º?¼šm¾ïÓý´,ÝÅ ”bݺulÞ¼Y C,(ëÖ­C)ÉN:îÃôL»†ˆ¬»÷N`¡hok«ßG¦\*éÇ©WE,,âñ8ZkÊå2QaÛ6Édm4a¢µ¦X,’H$ˆÇãÏÚ¥!мßì² 0Æ ”jfðj­q§¹M±XÄ÷}b1CñHEQÄÈØ8»G+8él}z'kVõãyµZ™™R©¾ïcŒ¡\)S)Whii T*¡µ&Nr¶z­5ÚÀ¢%ËÉd[Ø»g7mí¤Ò"­ëÁIcÐÔ‘ë‹tãøL3©ë]? Ô×5¦Þø<<„²­9ªÅIŠå‘6Ø2ö¸B!ÄËB‚”Gh6@‰‚Uÿ£“Ÿüü?Yýþ.¶\¿‹u¨ ˆïû¬_¿ž-[¶HF¥xÅY–źuëð}_ ãx×Pnßµ/Ñ‚OP*–xf×ímm EüqfffÈår áy½½½‹EÆÇlj¢ß÷I¥R8ŽƒeY¤ÒivïÚE&“Áó}<×Ų,Â0¤««‹ááaÒ™ -Ù,£££LMMQ©VQV=ÚÛÛËÞ½{ ‚Ïó0¦Þ­7“N§Y¾|¹üþŽ@EŒŒŽ10œ'×ÙƒÖ03cxòé¬]½ c û÷ïgffß÷) T*¦¦¦(‹ô÷÷ãû>Zk”R¬]»öy²0-Â("#"c£ˆ0Òh­ifIb5²)ëJ­9”ÚÔ”Àª%ÿêÎÙ× V£ËwFÊ•ZDÂwÑ5\!„Bm@¥RAÙŠj¥J2™”,—ç07@Ùù¡W½ý*îùéOÉårÜø?¾Å–ë‘@¥XP|ßçä“OfxxXƨ¯˜žžºººäÞòšPP>³kåep½8•J K9à¥yjÇ Æ@*™ ¥µD*…RÉtÛV䧦 ‚€T¶Çv( Lä§É¶fȦ³(åH¥©…†dÚ§X*EAÒÞÑE-ˆ˜šž!•Î0<2F¥ZÁ²žçb{>(›PC©R£R P¶Âõ\–õ.&›IÅr8þ#Z³ÊÝx©6j5A㸠¦ !OlÝÁ «úˆùqòùiŠÅI‚ ‘HÐÑ™ 6=M©TÁ±=ÚÚÚIgÒ‡P´ ëåi¡Ž£ˆ(ÒDQý´®‡Ã0¤Z©„!J)×ÃhM¥Z%•Ê`)E­Z¥Z©`».ŽíéAKÝè2n¨gfZ¶= NÖ3Yƒ h“]ÏEÉxB!„8€]»vQ­Uyú©§yë[ßzP*Q·éÏw°áÓý|þï>Ç=÷ÜÀÄø8ùÂù÷o=(•bÁQJÑÓÓCgg'…B|>O¡Phvâh², ×uI¥R´¶¶’J¥d’œ×c Ó33lßµËËP lÂR…Ñ|‰HCiº[[yrÛ>Vwû¬jw°H² kQ½ëµŽP–BkíØ`ÚÐÆ`a0(,ÛbiªÇuûŒ¡Æ²ʪÐÕŸÀ¶ ´¯ë­gÙYõÜ8m4¶]¢}Eh«‡ÿÙLÂô$áQ(”0Qí¸þ]‡aÈÈè8»óX^ ãSjaD™úÌÞX(åóÄÖ§Y¹"ŲU1”J`ŒÆ¶Æø‘ézwë(B©2–ª2S›{5¡å™úµ Ä”Þ@ÄRÂÈéú¹iƒÖ†jµÂ¶§¶266J,§P,ÐÙÙM,ž@Gû¢}„AéÉ)J•2Ùl ñDŠ\[­­9t£û·ž3f¥8 T*188ȾZ²YÖ¯_ßìÎ/„Bq49ÝÝÝLNNÒ¿l™”È F|ê_¦§§ç-žšœ$?]’ò –mÛd³Y²Ù¬Æ+ĉ‚á–rq»OXÐÇDƦËô´ž*¿8qxç7† ©ÖBq—J±J©bHø.ÅjˆƒBcQ®j÷î&ÓÞMS³U={ͲêrµFÏiD1sö¡, =çv;›è¦]y¢9ßÏno5Ö±‘åÍÛËK£k%LX­€xœÒ¦ž¡hŒ…ãØDº†ïÚàB5Œ°-…60:5M&?N®ÕCE ,EèæïY›ÆlÝÏ®†y µ]”Ë“¸Ár»0Ò„¡!ŒêÿŒ®-]?N<žÂqm2v ®ëá8.ãSS”K%”cã'’`;ÔjJUëÁNSI|¯C IDATϬN%By(‰D‚\.GEÄb±CŽ*„Bq48---´´´Ðßß/%ò<6üM?›þ|›®ßÅï¿ã÷¹ùæ›à/Þñ9*7UXö‹$‹R!Äk޲¹–V,5lÛ5D6݆R6Æ@:éS ¦óäriº—¬'ðAi”r~Œxª°VÁO¤QŽC<Óúªí0­+Ó(ÿIhŒ‹x<ò\ŽÝDÑÃù<ÝmmÐè21KeÊ…<«úO 5›#åÃTuœJ­L&ÞÚÌlíL¶>ï~Œ èÌž‹ö L32UÆodRÖƒ”£5¶òè_± ݆Q=ˆfÕǧÌut žÚt¤ëãUZEZþx_èo[)ÚÚÚhkL|%„Bq¬ÈÄ9GRIs¬f ²ö/qîÿÙ/¸ó§÷ÑU^JÇ¿wÒõñn:OÍHA !„xmÞ'•¢½­ŒaëÎAb©6Ç¥Z ˜™œ —±hQ/ž­‰)ÍÌLž©g˜Ø¹7ž V,êè¡÷Ä7àú¯Ö¡gÌkb( Ïóè[Ò6ûÙ?6F¶µÈÊ¥2ÕBžþ%=d²i|Wƒ263ÈDi eYÌT¦É%ÛÉô½×vŸs–åâ;9ªQ­¢F`2Œ""­›AJ£g·QÍnÛõ‰‘ìÆ¬ß³¿ÀRXJ²&…B! RéØœ@åô×à¿_ýߨü©],úÓºÏÈÖ»; !„¯Õû¤R´·çXƒÅægpü,•òÌ¥£È&=ªw©¶žú¸’J1(Û}(_[|Ï£¿¯Ì~vãÇÓT‹³Ê ß&ð08,ïXÅ2³’ P–…­œç P>[}b ƒÂ Ð(@a,kN/íg`šKfçyy® ]ƒAÙ6`¡l»~> !„Bˆ—•)_̘cqògûùÏOìâñOîà”/­$»*!#„BPTv´·²V<¶y íí‹X´hžc‘My8v=äúq H¾ÊùžÇ²¥½Dz/{†Y¾¬ŸL6Ý PÖ'ÒQ$¼ä‹Þ‡eYè(`ßÞ]x^œ‰ñ1&óy‰8Æ4‘ÿ¯Êµ"™îú„2ð9îØ*FkêuxN+¾—=fA=Ëß•L\!„Bˆã•)…BqTŽk»7 M@qí$–å`+é6{Ã,ÇÃ0Ó¨óòµ5ŽÏYK€!³ŽÜ­çñ¼½¥ÀãñÍÖ·CyÂàyÅñJánÄ!ƒ—€ëà\€³0¿`˜_˜ÀZ‡ç%8Ö^¦3Fîµíñý*ÅxN‹þÈm0pãÆ nܼIc·7rE*Œˆˆˆ¸àðÜa’$! CUDDDD^³›-æÖ’å–Ñ(£RŠ)™uäyNšæìtrê†Ð7€Ù % Æ8rçpöU‚D žafº;o‡qn‰oãn»mü½Áàí¿¾×"Í[t׈ƒ ¿¨ƒ+O¬B¡Àôô4¾ï« """rßÕJ•j¥ÊñãÇU¹kÆêµ*';^ºtƒr¡AÉ3K) SÚ­ MOrèÐa|cHm›ëÍ«L—gCfSf«sÄÁƒÿÐt”mc]Ή¨È“Çó<FCÅ‘ûJ 爈ˆÈ0ÆP¯×8s^øêiÖ Šc†ÃíÖ&‡¦êÌÌÎú–bâ±ÖnÓî0Êúlv×H‚"b8¨=${¤€RDDDDä¢RDDDŒ1†F½ÆS§Ï¿tn¿@>êí”q`¨—#<ÏãPí³Õ9n<¥ñ}M=#""""ò$ÒLð"""r ÆAe§OͶ¯2[/23;Kj»%@à„~HäGÄA¬€RDDDDä ¦ž”"""r lš2tiT+¼óM'ÄÓøÔŠÁm+w‹ˆˆˆˆˆÜ¢RDDDŒ³9íÍe6/?.àlŽçßÀ‹"â#'(Ö§T$y ÷‘Ä q¹Ž³–¨PÆÙòãû*Îc0ÆÇ3ºô‘‡ô}„J """Åx>¥Æ ¥Æ .O±ý¼B £ù&–#¤ˆˆˆˆÈCI§‹ˆˆÈ}ᆲµ—qƒŽŠñÀÌ} ( c @EDDDä^¨'¥ˆˆˆÜÆÞî×'f§1Æïáڞۜިƒs9Åä4’å)ÁõlÍò”ö°E©Ï“å)Æxøž†ö‹ˆˆˆÈÝQH)"""r\ž’­_&oo^ÿöì3xqù¾¦a6àâÆËìôš£íA“Z2Á[Ž>{ÏA¥ÃÑìðÜõχ ž hõ·89}ŽÓ§Õ DDDDä®(¤9ÆópiÛÛ"ßÌ0ÞƒŸ‡3ô#Wç™­Ì1Hû4Š£òôt4 a‘S3çðM@gÔf²4ÉDI+¸‹ˆˆˆÈÝSH)"""rŒO0s¿qŒðä›1aüÀ_Rè‡ÌV“å=úÔJqá@/ÿ Q‘ùè8YÞ¡4P-T;‘×E!¥ˆˆˆÈpÎñ{Ÿþ"—×Ú\û­Oówžþ6jµú]£tÄÿþKÿ'—/_faq‘ŸøØÇð¼ƒ[;qss“ŸýÙŸ%Ë2>øÁò|@ADDDDîšBJ‘{äœãS¿û»|öOÿŒøÈǸòò |üãÿ˜¿õ·~’Z­Î(±º²ÊÎÎQ‘e“S“øžÏõë× ÃN§CEÔëã`szzšrùÞæ´¥#~å—…ajùÈý'üþïü?|ò‰þøáyý~Ÿ¥¥%¢(b4áy£ÑˆÁ`@¡P \.säÈ‘W 6777ùÄ'~óoz;‹gßħþå¯á|çwŽƒÊV»ÅÕ+WI *å2Íf“v»M½Ñ Z­0;3«Æ#""""x*ˆˆˆÈëçœãw÷÷øìgÿ”ïùþ059Í›ÞþŽ<ÏÏ}üçÙÙi’ŽR677ÙÜÜäóŸÿ<ëë묮¬²¶¶Æêê*qÓn·¹¶tþ`Àh4¢ßïßÓëÚ (ûƒ”ïú÷þ*…B÷}ðèR>ù‹¿„µ–~¿Ï‹/¾ÈÅ‹¹yó&­V‹_|‘­­- …N‡<Ï_ñü{å©§xç·}zƒïøÐ_áÓŸù,¿ó©Oa¥ÛéòòË/såòe–––h·ÛcHâ˜V«­Æ#""""û€íím²,£ÙlrâÄ |ßWeDDDäÉf<Œyå çRé6¸œ$:ħ~÷÷øÌg>ÃÛßÿ—±~‘Õ­ÎÁìâ[I³œŸûøÏó?ñPŸœ"ÃãM3‡¥C¬ñåŽÙ¹yªIÎJl7·)–«LMNR*&wõr]6Âö¶1q‰Ì‹ø•_þº½oûöï¥ÝÏ¥Crç8÷öïæËŸýÿøä'‘þë?Ì;Þõnj+Ë« ‡CÎÔ'1ÅRgsÂ0Ä¥lw ¿vˆÍ­m>ñ‰_`îøiŽœz;Í.y#Sä[Þû}|æÿÃ{ÞónÞû¾÷RH \»vz½N’$KÅY¼Gî¿Q:¢ÓîÐétˆã˜©©)½W‘û"h6›\¸pN§ÃÌÌ µZM•‘'–s–aºÂjóßø…;îKóëí?`³óyn|é/°±œð¾ý7¶s¶–¶(ÄÃQ ξƒ(Šùøÿò82³w}ewÇs~îU_ƒ»»gäí5\ž±eê,œy3o{ïû¸´Üb4êÇ!Ý~Jø<ûÞïåËú;ü¯?û?2Q-¼†z¸qH¹s•YO œ{ë»9râÍôú#šíŒAj¦õr‘÷|çò¹?úWôz]¾ïû¾€gžyF ë”e+++\¾|™ÉÉIêõºBJ¹/€ÙÙY¢8bccƒ(ŠTy¢ãxB¿JܹøMw(Å |Ž}ë»ù_ý4×¾úeŽž};Y–“D>ƒQÄ0ÍôÛ|õÅ/pâäž}ú¡ïÀZü0ƺÏ ·û?wO¯Ùõ[Œ®ýxå³|ê?ÇÄìQ榎Ѧ„¾¡’„¤¹esý7o\áÝïx–“G¦ñÌøßö‚ñë1ÆÜA©m¯2ºÔÆ›}Šv |åùÏ3{ä$Q«ÄTô9žç¸zñúý>ϼåíäÖâ{šaèQ•$ óóó$I‚ïûºè’ˆˆˆÈ×ÙÅb‘b±È‘¹#ªˆˆˆˆ¡_¡R8õŠÒ›0Æ ûØy~á> ÆðÖ·i–Sˆa§ÕãÿõoræÜ3|û>Dìå¸ÖMÚkKDA6À#¨@õÐ1‚ð^?(v¸gßÙ >'ŽœäŸþú¯ó­ïÿKÌ?Išæ” pýÚe>ÿG¿Í¿çû9ûÔ3D&e¸ü2é¨Oà{8 LŠqúጹíùßõ1žÏé<'ù7¿Ãïÿö¯óÁïýÅR…Ü:бåù/|šë—¾Â‡?ò£+uÒÌáë3ðG÷L0Õj•jµªbˆˆˆÈ}¾‘Wp8œ³¯rÙíi8Nïf¦§ùØG?ÊÒůð¹Ïü>ÖA³¹Íþë6(ÿÂIG¥àãû.ÑY]bØi²³tÎÆ26Ïà›Ý€rüýÓçÏñáú0ŸþwÿŠK¿Šu°tõö‡¿Å¿çû8sö) ‘¡œxx¾Ï¨³Cwk…ak“æõ ô›ë8—}Íó‡ùú¾Ïw×yÛ³oãwþß_e»Ù"Ë-Ïÿù8 ü«ùQ ªÅ$ÒÐ`ùæ•@DDDäÞÌÌLó±}”OüÂ'G¬Þ¸x+ Œú®‚ƒßÿí_ãð±3¬,½|G@Yˆu©)""""¯zRŠˆˆˆ€™™i>úÑacù§ÎœâýßñÝw”Ïð‚püÕîS@¹Çðôùóüµ¿öa.<ÿjåøuãáù!žï¿z¯mîAß÷ùÐwgΟæú¥çøÁü (EDDDä®éêQDDDä€ÌÎLðŸþÔ¦|QL Ã:#çŸ:ÏOÿôOÓä8çî(_/ç,£^—l4à-Ïœgcu•Ã3ħ€RDDDDîš® EDDDîQf3¶:¬wVh§ñLJj¯F³Ä^òP¼FÏ3TŠwé—†ìܼÌö‹¬ït zl~ñßP¨My+Aœ¨aˆˆˆˆÈk¦RDDDäYgé¥]vú;t†mZýqS/4ˆƒÇ3¬óü€Bc ›¥´Ý*~¸E¡>ER™À C5 ¹+ )EDDDîQè‡Ì×1W;Bf‡€‡ï…DAüØî³„T¦æ¨LÍ1ˆ.]¸Ê‘g¾UADDDD^ßõ¥J """ro †ÀñLÎ(½ ®E$Ìã¿óÎâmlÚSC‘×M!¥ˆˆˆÜÆ`‚¼'ià†Ãºçò'ñ€«Í‹ˆˆˆÈë¦RDDDœK¤7žgðÅÎðâà¬}BöÜ`0X—©ˆˆˆˆˆÜ…”"""r®0|\ž’-ý ¶»…ñžŒ^vÆŒ q[íÏÑ^;ðsŽœ<ëâû%Œñø¹-y>$ëUM­³l7w¸r}Úä<ë;=â £?ÌñŒ¡GD…ˆëËô² ?~ëzÃ9‡sŽ‘ƒ¨fÀ9bcp»ÇʹñÚ»mhƒîxŽKc D†žS€¨À+†i»Ûžçè;ˆj»Ï繃òÔø1Ö:¶ûŽ,ëƒZñœNy¢Yk äyN­^#4KDDDîàÈ‘# ‡CŒgð<­¥#""7cBꥧ(' Ü1½YÞgeçß2YG¥RÅ9ÃFgK/3Už!Ës27âÔÔ9ÊIEÍSäaùMi< …‚F[‰ˆˆÈðMDDD˜ãI]u¥X(púäQoÄÖæ6ÖWàt¶wÊ ÅħXð ¼€j¡F–§4ûØÜâ{¾šˆˆˆˆÈH“ʈˆˆÈ* œ=uŒ^¾ÊòÊ2±ïn (*…c`¦zˆ™ê!LDDDDDRŠˆˆÈÁ+ œ[œ%ê?G<µHµZ£˜x”“q@)"""""r;…”"""r ÒA~k‹B©ÊÉ dq|G)öPŠˆˆˆˆÈ«RH)"""Æ9Ë Ýdí¥?ÇZ‹8›ãœ|†ê̼Š$"""""¯ RDDDTT¬Ð8v–lØ#ˆKäi/I* GDDDDD^•BJ90ÆxÄ¥ q©‚Kûäí5üÊQL˜¨8"""""òuy*ˆˆˆÜ.7oàF}CDDDDD¾!…”""òÊ?&Àu¶ý Æ„xOz =$à«-=îí?ÀhU$¹—·*ˆˆÜ.·=®®ÿ—×~µÖ© wɺ!«Í?àòú?áÚæ?ÇaŸÈ:¸´ÏðÒgéýáÏ3xþ_âl®Æñ¸þÎè¬3øòo‘7WIo~Y‘×E!¥ˆˆÜÁ˜€ba’‘»N99¬‚Ümýˆ£)Ù5"¿†yBÿÔš Æ/×q£ML\Âx¾Çãz¬½Ä8;Â+O© """"òºhü•ˆÈcÂZËòò2;­,K £¸×ò·m”æ3˜þ÷sõb ¼„û&Ïðµ÷:çȳ ?ñ ÌÎÎ091ñDc|ªÉYæ ÿ!3Õ÷?û4JG¬¯­³Ój›í7n;;÷ƒxé æ…—øz-Ñí¶›[ŒÏ÷)$ Gç†á{NÛ)þS GûçÕ}RíÆg¸1††Ãnpú¯Ì¿ö6_¨áüp¸uëM¢8ZDDDD^…”""‰4M¹tå:©Cdéˆ+×–yêÜyrkqnpÀnä€ÝèÑYÆ’cwœ› ˜|;Ãt÷¶ñ}v›ñW‡ÃZvƒÐ½Û`4J¹våÇO‘ކì´.ñîw=!ežç\¿±ÅÚòYì`§ÎVð¾¦á^ØdÅ0nŸ¬³xæáé9踺t“J}ša¿ÏÚúÇpvïõ:œÛk#ìï‚)Ü᜵ØÅ9»{ÿ^{qØ0¦9[[Ô“ØÁ2ÕJ™©©'·gÞÖWZ Û#üß#Š"6ÖשOLEñîù¼{.»[çÞþù¼[ßñ1r·êîÜøÌß;V8ú½íS‡ÈÛÜonÝUHyã3[¬~ÜPnœàsÿÕWyç?8‹<¸ù)¶óGDDDD^…”"" c q’И˜"M‡Ôwv¨OLᬽ#@äŽh|ƒµ·…pGØ´×ËÊÝjp{µ÷ÜÎaÇé'£QJkg‡‰É)ƒ½î;Ý”j1äq^[#Ïs–®ßd}«ÏܱšÛÛ<ÿ• µZz£Á ß§Õj‘œu ò<'â8æØ±cDQ¤? """"˜`ii‰~¿Ï7x÷»ßM’$ªŒˆÈ} ,ÔÙA›ÑÕ?ÃÍžÇaÈ2K–ž,ËØnn±¶ºNúth f¹ÍÁ¢0ÂzÝ.¹Í ‚qLëQ,$ØÜ’[G©T$ŽR”^¯ÇÆÆ«kk”K%N:õDÏ+"""÷Oàùëë묭¯Ñï÷RŠˆÜÆ`üˆÑ¥? ½ù¥{ZÛ]gðÇÿ˜lòùüß$;´H–»Ý¡‘)^¾@·Ûebb p„aÄhÔÃ:¸ðòK4›[Xk9<7O¿? ÓiQ­ÔŽŒ†#<ßÇp$ÅÇŸ`ÐÐ ;|鋟Çôx¾Ïôô 'Ï>M¡XºõÃ_ú4ö¹F×€íüÇð(®xíkpkÌü­»¶ûŽËùqæO>Åf³ËNgDztú)QèÓ˜­°¼z“΃œÅ)ã G+Û”1³¸ÔV="cèÙ€Ú!Ÿžý2ÝöíAÒÁÑ\ãzóÿ&t'q£¢båŽÜ{Ônnm†,ËH EŽ;ÎÕ«Wxñů0==Kœ‰£˜ ^À÷J•k ûCr›3 Éq û“Ì=N-Šõ{âUd¹%ËóÝÞŽ–<¿Õå9ý~Ÿv»çŒFÃñ¹ã±|ã*¥r…C‡’ï’ÖÞ6/è~»ò0Ùí-þ‡ÿíS»·ýæ×}]ßóã?Náé:ÛíiîHSKw˜RˆCâÿ¨Në^幟ûSr¼ðOXñÉmNÀd,7ÀA7—;Œo(NBp <0·eC.¯`Ìmç ƒN>µãxŠ8þ5šƒ|³äyNs{›t4zÅ0|‘»î˜žž¦Z©²¸¸HµZUUDDîㄇž"˜>9{ ýĶ·… ¸ùwâ–zdiJž;²Üâð9{îM †}<ã±¹¹N©\¥X,F1ƒ~Ÿ^¯‡Ís¬Ï]é{>Q”Ðív0ž³·zmËUÂ0à©gÞ @¡P"Œãý!¾Æ*åÊîcövìÜÛ0o'Iç2…gþ˜Gë ®³–~{?ˆðv‡\Qa–#‡¿“jœ„ŽQ6¢&~°;7ßÃ6?\¦˜%tg¹rÅ’fÙnHf ¢„§ÏøI¡‚(æíï¬Òív1ÆE žïSŸ˜ÄYšâŸ4σÜ:²4Å b”Žô‹âUä¹%Ý (³Ü‘ç»”r I±ÌâɳøAˆçyxÆ#Œ"šÛÛ:rlÜëЃKwÛBGw.¸nqAD­ÞàïüðwSð†Ä§¿Q·‹s9ARÂå)~\äÚ¯såg¶|̧|º€ï{àÃ4'åôþÑ6Qœ°ðãç¨c<ÏÒõHÂìN1aðÌAµVŒÖè .íþ¤~¸eo>ÑjµŠçyJ/"""÷M…Ñþ$æ""r?‚Ì£üÚ¥oý1†Ãöêsd¹%Í-YæÈ­ÃCÊQ ÖQ¬ÔvWüu8,I±D¡XÙ›kñK¹Zß_-xw¶;òÝ8ü`¼ºðü îœ4Ð[K:Þ  Þñg)–ÞýHF6²yíé »¿˜ñ}Ji{–(Œ9¹xŒ—/\f«Û¤Ö˜"ÏsªEN·C¿»ÍÙÓ'I’ÏltnðÒÊ—i”&ÉóŒa6ämÇÞE).?Tû].,R.,²ÓjcíEòÝ©¬ƒR©J©R¶û³š†¥Êx!”ñ°b(«ûmÈî¯ ¿S`<5ÁæÆº²¥W‘çnÿƒ‡ñÿÝnH9®©ñ<¦¦gÇsrkø¶uŽéÙ¹ÝE‹Æ·ï“oü;Ê'8ý~ ±!íwÙºy™Þæ*xƒ‡†$35þó9®üÌ&ÞÇ É›«ä™Åe9íŸß&Œ<ÎüÝ‘gºÃ¾xýsÄAL!*Òìp¤~œÅ©Só{‡g"ŒÑtëþ7Ëâ8&ŽÕÓYDDDî/]ɉˆ<&ör‡,w8;’r»·âöxè°/µ<þ~µ»¿PÎÞ-ÎݹÍ×elsûŠWavßÔcƃºw—ó66=’!”ñ}ª³ót·×ñƒd透ܨß& ΜZ䥯^fumZc’N»Í°×Ü(+…€BâSÈŠ,NÂ:GgТ—ˆ‚‡;°ÒýV/œ“»¯i+{ß°»ÿÙ 0_­9ÜxÚR7á±^þ®ÏkÇxá©Ü‘çãs:wîÖ"Xûçq¾ßYw{GÝ w.`娫»Á0>oq`lxAH©11ãE’<Ïæ)Q±Ê¡÷Æx>—ÿûU¶ÔŸMhÿOûeRð©•#ß#´!ócø^@«ß¤š4ºP^DDDD,…”"" çƒÁl§sív›V«}k¾9w+”¸-¡¸ ݶͽJÓ”^·K·×c8B–=Òµõ¼€ú‘Ôœø†Û…aÀÙS‹¸ —¸´t…BÜP– ãaîS•¦*3Ìþ[kŒZm²Ñ€V»M«ÝyE›Úµï¶-CžÛ ’¤Èp8|ƒçà|ÏiÀ Í?o1ˆGô7ú4oìЋ‡»uv_ss׫¡;ÃAQsD{«Åp{H0¼5g¬FÔ/P;¼ðª?þÞYø/àò·J»Ú"¬œù»‹w”¥¨ÌÉé³úE-""""_—BJ‘ÇDøŸŸaym“n?¥ZŠimÞàAä<ÎYÕ„Ak0ÌÎÎðŠN—ëqž:s’Ré&^X&Žï (E…$fþÐË뛤ý”bìÑÞ¼yÀmÆyéxnÁÖ•$¦X*>ÑAåĹ Q% ø{9¹íS³EŒ’™œ»ÓA„cÒÁtI€â_,‘篭îÆŽ}Û4ü×n.ÝàÈ;ßúŠ€RDDDDäµPH)"ò¸üBÎ=Í™3Ðì¤û½(ÄèYc Ö‡[ëð=÷ ŸÅãGŽrrë(%öŸÛ$IxêÜNŸv´zÙýk[Æì·—ñT•vwÎÊ'SR‹xÏ'Γ[è 2²|wxöŸ¬€Ï :ž‡Öâßż¹¹ëÂé?&œù4µ©s”’†J¹û÷Q*ˆÈãÅ30Q UˆÌIä?Vûøæ i[Z›ùN¾•âÃ{É–å}zƒ›ããæ­“:h""""r÷ï7Ty˜( |´$Ñ4‹3ƒÎà µâyDDDDD^Å‘{ä8°•·DDDD䉤RDDDDDDDDD(…”""""òÈsXÀ=Ñ+‹ˆˆˆ<Ê4'¥ˆˆˆˆ<ÒéWוÍÎqÎ2S{¯Š""""òˆQOJy¤EA…zå …¤L½|Zy©'¥ˆˆˆˆ<ƒÁ€¥¥%Z­¹µäYFÇã;{Õ¥x¾v4÷x+C–éßÃÖoâ¸ñªëø¼ÚPð½[²,¾P.9ztŽF½®ƒ$"""òQH)""""Äh4b{§ËÄôúýkk«>v k-ÖƒÅq¶8Ž#÷~vn|ÿxJpî0ΓÛ‡ÃYƳTÚñÊãÖìþó?ÎÁÚÖ ÖBc¢F{«M¹Ò¦^«cŒŽ“ˆˆˆÈA!¥ˆˆˆˆ<Æ‚0$J¬µ$I8IpöVɽ޷ÇñW{[WI›ï˜.Ü/­g÷¾ßÝf÷¹Ý =Ç÷ E,P,é¦Z½œÁ(#‰•""""o€;BJk-ž§i*EDDDäþs€µg–Ì:òÜ‘åç,Î:rgñðv{?:Œça­Å즆v?™ ¸Ü1X7:nA€sãíÇÏaÆÁ¤g ÏÙÍ0wCÐqô¹÷½ÕBá·Ž•s8žÑ{¹?€Ë—/ÓjµØÞÞæmϾj¥ªÊˆˆˆˆÈý寒g¹%ËrrëH³pôº].^ü*ÃÁ€<ÏI’‰InÞX")IâQ³±¾NµV'ð}º½µzƒ$)póÆi–Q((–ª¤éãùøÆ#·9AR,UÇ=7§¥ò ½^7o²¹±A¥RáôéÓDQ¤ÂˆˆˆÈ ’$agg‡ÖÃÁ**ŒˆˆˆˆÜÖ¹qH™Cfsò|Üc/ËÃшõõu¢(&Ë-…b‰~ÀêêAàÅ–õuŽ&qsö©7“å9ÎÂõ¥kXë°yŽ„ŒFCvvš4“œ:ó3‡çÁ½ê:;a@ÇäyN¯×#Ë3"RŠˆˆÈ}¸î˜™™¡Ñh°°°@­VSUDDDDä¾Û›2Íyž“çåã!מ2t‘……Sä»SÅq©™Ã»Ûæ8žgØÙi†Z½µ–(Šé÷û8GN’e)`°Öá°ãEî¶áãòJarøða&&&0Æ$‰Š""""÷Eàû>¾ïë¢CDDDDÞP¹µäùÞœ”ãž”–ñü“ÕÚÄx½žŽÎù·¦Tß[í»Pªì¯ø½·HN±\Ù}ÌÒUÒÞz|Æ‚ ´Þ¦ˆˆˆÜ_ºÚ‘Æ9ÈíxœÜB¾{Îù­aØûa£½ã±·ÖÎqß0|5ž1` Æ€ñ›ä×nþ³Fƒ¡¹µ9ÞÞFý“µE•""""o…”""""ò@”Šž:u”µ&mߣMáÛþk{°y·½F³“epàù#êS5ªÕºF‚‹ˆˆˆ¼RŠˆˆˆÈEÇeþè<ÝÝŸòA0Æì÷ÜtÎáœÃ÷Õ—RDDDä¢RDDDD(ß3T‹¾ !"""òóT¹'Îá°ªƒˆˆˆˆ¼nêI)""""¯‹Ã‘Ûœ(¬Q1 *ˆˆˆˆˆ¼n )EDDDÜ“1—áN¯É +ÏQŒÊ”â*ÝáŸ1[9Ì¡Ú5¹+î-"""r@œ³@Î>ößc ¥¨Œï¬¶nÐêï`†}‹ˆˆˆÈÝSOJ‘à°t—yáÆß§ãÜÜO‡õÇv †Z¡Î›Ž| ÖH³.I4©† """"¯‹zRŠˆˆˆƒGNP+ž£”Ì…µ'c¿ ¤ù6ÑKj""""òº©'¥ˆˆˆÈ]XMPñ~Ÿó„ÌKi-t;9[–©²ãI™SDDDD–zRŠˆˆˆ€4MY]oråšãƲc}csÿ>ç£ÑˆápxOÿ†u–ÑhDžçÅ>[gi6[¼|±ÉvsŠKW–À¹;jr·û|PsZºÝבç9išîÿ,""""'õ¤¹Giš²²¶ÎÊF‡CGæ \¼º†s03=I»Óæù/=O†Dq„Í-Aàû>Î9jµ•J…••‚ Àó<œ/LÓív‰¢ç­vg-µZ³gÏ>Ð}”;\º¶J}âøëÛ›X{•S‹Çé¼ð \¿~…… Å"ž1xž‡1kÇë^<Ï#ŽcƒÃá0 é÷ûA@±Xdccß÷) ‹EªÕ*«««”Ëe¢(buu¤££4e¢Ñ Ïs†Ã!GŽabbBUDDDä! <ßÃæ–$IT‘×(MS–W×YÙhSŸYÞ{÷ÔÑ­°Þú#&Êï LséÚ:™Wa{{Dž÷É2Kf-I³¼5ÄÚÎ*±˜µH >Àh8¤ÓiQ«5ðŸ( ±²gÎáû¾ìþkgyžáy>Ö:ŒÇn]-`‚€¹é:a†>öÈ,çÏ,yž1¥t»=Êå"år‚G†eW‘QòìŽáí£~¿Ï¥K—X[[czzš³gÏDZN~9pÀúÆqï9‘o®×pseƒbeŠæÖ€íÖ€0ðÈ\Nà{x^@FÄs/ÿ9OŸCQæ1Žán[d&µØ< ý||-f‡’äàp ½¾Å±ûð7Pgp…«[ÿ„›[¿O2úëX³HEØ~Á('Í,o0ÆÃ ‹\¹t¤÷'”/ý ‚Sï#,&„J°yÜî>1û?ïñ ø˜;ë´÷½s` €³dÆ8ƒÃáH0$}Gºî¼^ÎføyLXx¬Ûø`0`0àû>¾ï뤑û&8sú4A0þäºT*©*""""¯A¥\âÄñ9.\Yanr’#SeFYNž[0†tÐ't9µð­”“Å‚£;l“„%¢ Þí÷ð¯e8Êš4Êo¦ZxŠÑ0à«——¦†Éz ›çd¹ÅCš¦ôÚ[>~šdòYâwüeâÐ'œ=«ó(¶ñj…sçÎaŒ!Š"Â0TQDDDä¾ ïy<Ïcr¢sðÒ¥e Õ)âÐ'÷=zÝé ÅâñyJåïè [A?¾‘aDcþ•é9¬µøÆ`Á"”""""r×4›¹ˆˆˆÈ=2Æ#LJDq„ißÀ¶ˆKü0zŒwÚ#L ª ’¼Ö5еIâRE BDDDDîšBJ‘âlŽËFOÞtŒy†Ë35yÝRŠˆˆˆgq£ùÎMlg—§OÆng#òelg;計ˆˆˆÈë¢9)EDDD„#ß¾Fÿßþ}ü¹o!<|üð±ßkÛݤÿ¹ÿ‹|íÁäÞÜÓj """"r×RŠˆˆˆ¼ ç,iš=±î›<À@^œÁ{úñjódø¸ÑóM†~{Æ`Ã3?xcCÍ<ÏÉó ŒÁνŽ:…e¼3–¦q‹ŒF£q9îrÈûƒ¬ƒˆˆˆˆÏfóÔ½^šy›ù|ždÑIY¥: ìNǶIUUišrb.²½’Òæ;Ï-»’ö$Ô+¥É¼ir8œg2iÓ_ëû:–’”¶Ít:ϼmÒ´M¦³&ͼ9Y¦Å2¦$©ëE8Ù–4¥=­PÚ¶œ–§÷w7M{Ömzn–¯»GÛæåîʶmSÒžt™6™7mŽFÉxÒdcÍ©*ÀeÑO’/^¤®ë,--euuUU€Km˜%󦤗6ó¶Í|ž”4G éõzg•W663O²²¶š¤NIu’ãUiK“¦iÒëõÒ´mÆãQ––VNº Û—n¯^sãà¼-iš6óy›¦)™ÏÛ´Ms¶ÿ÷ßg0¦îÕiÛ6wû×Éú•\½¶“ÍÍ­¾8È•<úãd2ž¤”’Ùlv21O/«««y÷ÝΛßKÓ–³±)Û¶ü÷fìᵘN¦ùãç`?·nÝÊ{ï½—^¯§0À+×O’§_~™[·n¥®…“Éb6ïÒ´)©”'å`8L[JÖ×73™ŒSÕãÔu?×¶wr<fii–¦ir<8Îl2ËêÚzúKKYY]Íêú•$‹™¬Û.³¹“q4gÍ¢S´™—Å׿ë…jš&£Ñ8ÓÙ<[×¶Ó¶M–—W³²ºžÛwÞÏîóç™NÆi76Ó_^ÎþÁA¦“IêºÎÆÆVö÷÷3Mrug;W6¶ÎÆî,¥M{ÚEiW»ÐÆãqf³ivvv²½½­‹87ý$ùèãRWuú}ãþääVìfÞ¦¤^t6mªºŸ›·ÞÍ›ßKUUg݆u]åÚõ›)¥I3oO_"Óé8MS²²ºvr;sIÛ”TURšŽWqqKö|þu@9oÚ4M{Vƒ¤ÊÖµüå_}”TUªªN]WiÚ6×¶¯çÞž¶i’*iÛÅø’õ7B¬;§¯S’6mJSNƼäM±s}'W¯^M¯×KUUBJàÜô“dyiY%¾¡-ɬ-é7Íb¼Æ¦MÕkÏÆQ<²=¹[µ*Uþßóȶ-©êE—^}Ò­WÜpé)¾¥®’¦™æÑ>K[Õ9ØÛÍx2J¿×{iŽ—ÿI¨XJ2g8f6'í4;›w_Û:–Òfpt½ƒã GƒŒ†ƒÌ¦ÓE·äúó圖#‡9>>N3›¤mæyÿλvB€KFH ð-ëëëù«¿üA>¸?ÊW/Æ/M&óÊt]Ö½:ëëëiÚ&ÉùÏž¼½}5÷·çàx”ãÙÙrtâ´ë²”Ô½^ÖÖÖÒ4SU€KÄ™Àbyi9Û×–secóµÜ†]²Èêz¯iø¿ºZ„¢+«ëÙ¹vq&³9«ƒá+ÕSA¦ IDAT.!%À¡ª’•·|Ò^ô–{662UÐ)!%Ð)!%Ð)!%Ð)!%Ð)!%Ð)!%Ð)!%Ð)!%Щ~’ìîîf>Ÿ§išÜºu+ý~_eà’›L&9<<Ìt6ÍÚêZ®]»–ºÖç¼zý$9::ÊÓ§O“$›››ÙÚÚR¸äš¦Éîîn²½½+W®deeEa€W®N’gÏž¥ªªŒF£¬®­ª Á`áp˜Éd’RJz½ž¢ç¢Ÿ$}ôQJJªT*$IÞyçܸqC!€s×O’ªª”ÀwT•ëàüõè”è”è”è”è”è”è”è”è”è”è”è”è”èT?IžŸ+ p.úI2™LòÁ÷¿Ÿ?ûÓ?ÍÒÒ’ªiæMÖÖÖòÃþ0›››î¸ÎM?I>üðC•^²½½íím…Ήs€N )€N )€N )€N )€N )€N )€N )€N )€N )€N )€N )€N )€N )€N )€Nõ“äÁƒÙÝÝÍd2ÉÇœ¥¥%•€Kîøø8Ož<Éîînnܸ‘{÷î¥×ë) ðÊÕI232 rtt¤*@š¦Ép´¸V8<<Ìt:Uà\ô“duu5÷îÝKÛ¶ÙÜÜT U]åÚÕk¹zõj676³²²¢(À¹è'Éýû÷UxÉÖæV¶6·8w}%þܽ{÷;ÏÍf³Ìf³ÿÖë™Ýè”è”è”è”è”è”è”è”è”è”è”è”èT$mi“$¥θF^‡~’<øüAžûì³L&“K½ÍçóËh4z+Ö§-mÙÛÛKÛ¶ºÎÓÙ4ÃáðÒO·û³gϲ¿¿aÞ?§Ëµ··—áèÕo¦iòüùó<~üøÂòøôôéÓ<þâñ¥?xU: )õ«_å—¿üå]¼ýýýüã¯ÿ1ÿñèÑ¥ÝÚÒæË/¿ÌáÑaf³Ù[±>ÏŸ?Ïþþ~>ÿüó·æBê׿þuŽŽß¸eކù—þç4MóÆo‡¦iòÅ_äé—OóàÁƒ ½¬£Ñ(Ÿ|òI~ñ‹_œ[ˆw¶Ç—_~™/^œËëϦ³<|ø0£á«ÿeÇx<Î'Ÿ|’‡¦ªª ýy: óôéÓKsLlæ‹÷ù'Ÿ|’ÿýOÿtaŽ‹óù<?ÎßÿÃßçáÃ?œËgÆ£Grtt”gÏž]Šm=òé§Ÿæ·ÿúÛ€ÿ¹~W'Ë7oÞL)%óù<ý~ÿ,ÞÚÚZv¶wre}ýÒî@uUgkk+ÏŸ?+:®ªTY__Ï“'Or÷½»oÍ6ºyófš7°»eyi9?úÑrýúõ7ߪ«\½z5OŸ>M]]ì‘6–––òƒü oìçóÿõ}Q×ÙÜÜÌêêê+íRJ†ÃaFãqÖÖ×Îeû|ø‘^]§iš »N÷óÃÃÃìïïg{{û­?&öz½looçÞýûÙÚܼ0Û¦W÷òÎ;浪ª,--½ú“É~?›[[™ÍfÙÜܼ'Ðý~îÝ¿—µÕµK±o¼–ëæRJQ^ÅEùEîèaÑÕtÑÃ1À1Û™Ëá§?ýéwžûÉO~¢0p‰I,x%\”¼ov%àí À%µ:%¤:%¤:%¤:%¤:%¤:%¤:%¤:%¤:%¤:%¤:%¤:Uýìg?+½^/ý~?IRJI]×iÛ6¥”$Él6Ëd2I)åìï¸êºNUUéõz©ëúìoަiRJ9»¾ë÷ûgùßiXUÕÙÏŸæ‚§×…ßüþÛ¾úê«\¿~ý¿üûªªÒ¶íKÏþßMÓ¤išüÎÔŒau_µIEND®B`‚rabbitmq-server-3.2.4/plugins-src/webmachine-wrapper/webmachine-git/www/images/gossip4.gif0000644000000000000000000001146512305126066030414 0ustar rootrootGIF89aóáç·  !!!"""###$$$%%%&&&'''((()))+++,,,---...///111222333444666888999:::;;;<<<===???CCCDDDGGGHHHIIIJJJKKKMMMOOOPPPRRRSSSTTTUUUYYYZZZ\\\]]]^^^___```aaabbbcccdddeeefffhhhlllmmmpppqqquuuvvvxxxyyyzzz}}}‚‚‚ƒƒƒ„„„………‡‡‡ˆˆˆ‰‰‰‹‹‹ŒŒŒŽŽŽ“““”””•••–––———™™™ššš›››œœœžžžŸŸŸ   ¡¡¡¢¢¢£££¤¤¤¥¥¥§§§¨¨¨©©©ªªª«««¬¬¬­­­®®®¯¯¯°°°±±±²²²³³³´´´µµµ¶¶¶···¹¹¹ººº»»»¼¼¼½½½¿¿¿ÀÀÀÁÁÁÂÂÂÃÃÃÄÄÄÆÆÆÇÇÇÈÈÈÉÉÉÊÊÊËËËÌÌÌÍÍÍÎÎÎÏÏÏÐÐÐÑÑÑÒÒÒÓÓÓÔÔÔÕÕÕÖÖÖ×××ÙÙÙÚÚÚÛÛÛÜÜÜßßßáááãããäääåååæææçççéééëëëìììíííïïïóóóôôôõõõöööùùùúúúûûûÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ,óáþo H° Áƒ*\Ȱ¡Ã‡#JœH±¢Å‹3jÜȱ£GŒBŠI²¤É“(Sª\ɲ¥Ë—0cÊœI“äÇ›8sêÜɳ§ÏŸ@ƒ J´¨Ñ£H“*]Ê´©Ó§P£:…§*PR³jm ¦ ®YlK–§W AÅ€¶¬Û·©bè CQ!-”Ë‘ïF¿p42‹®‘[Ú:„„€£[„ cŒ,ÐÕá‹”oYÌyV£ƒ` Oô º"iƒ`LFÍ9°W„—%¾>;âìÁo¬Ýzë …s!þVüáð„ÅG˜¼·T'·•á"wDèÒ©[‡ˆ}zõÝ»þk/hÃùX»­rÜ ðû-Ý Ñ«gÿi½ÀÔåÛOdÿ~á·¤×_ÿ™'•]²ÔGI}õ „…D*Ø BxK‚·,x‹üÝò`~JxËìyh V¼ Ô d¥xK\äâB)–Ñߌ ¥˜H”Ââ‰R­–b ‰‘y’ )i“@6…cyMI‘•A‡•QJUà@86ô¥ŒP69æf—K9qÉ@œyÝ›ÅyKpˆp…¹ §œÜщ l>ÕFŠ,`B 7Ü"AH¥x¨ENDRè¥éR£š †“á*GNLŠé©5€)6Ì2EþF4wI¬9¹bC™¨æjÐa±Ü- kêFxªë±CÚ0êGƒ+²Ð.ä ¡}ä ÕF«­E `á§E8†)Û–ËQ]Ná— l°àá„ ¾>kî½øæ«ï¾üöë¯N6þ+°G3$ÅŠ}B!AÌoÁ !\P‰Iì°¹ä#…êI¡|"‹}ì•ø‰È¶÷IŒçºÈeÌ1G(IÁžñ—Èe”ј@%÷÷ =ûx!Î¥ŒÌÅ-³Ùsϵ2rÇÑE'ËR22{šüÇÈ­ Ä5Ö6Ýå=K2ÓfG uÛp7D)q×­P&vç­÷þÞ|÷í÷߀.øà„nøQm8!¤gFgïá—ÎÒªB–¹Â6ä¹:!C›bÞ%(±‚2k[kt‡úè,ë¹.º³žÓF›±™b„‹¥çh{E¼×N޶˜PñåñÂk¦Ðæ= ýCÒOôì㯉¼CÚ¯Ðö ­‰;àv--ô@ZBT~Ð/R"Pú­ßŸîß¿CòS\âý‡Ûu ÎRðÑŠü§>°î+‹dÀ %íIÈ“ÔÀÞ¢ ^jŒöõ® lŠÂ†¦‡„pCb“‘DNX°•èƒ~; Ôs‹_‰É C+‘ 2¦OÀH þ;\È™(Ñ£6ÏTALKB&øS1Ñ!Nlb¦'Sk" â-¬H‘,„‹XÔ"ø+<˜‚-ÖW@QFSl +dcAÚpEŠÈ‘ t”"AÂå„o­'${jˆ)„.#è`mI 2H8õÑiDvI=&DUàžQ€Ü“šÌÉ,2cɆ$Xš;’ êxGÉ 0§E*—´ÊZ‘²”áã#+™8ÈHº|¤ nR,\*Ew¬ä ìŒÉ”Y-K#ƒ¨%3¥2‹6a˜‘´Á§©P€A›jÈ,.aÍ6„“›oyUÜ…Îvºóˆ¸è‡&Šˆ|/ØŸ/dÅ;*¢‹ '=-JëyÖñDª×<¹ÖÄ ùñ‹ƒL‘OXŠF6‚lL£$/¹JI¶H”-y ,`Åuš 4)TùÊ´2…–¹Ì½:YYuçïþ™±üN …-ñHnáf87d3Öˆ+„<ÍYF&ˆälìgðÊ϶ZÈ s"Ë«Ö gÞ¬\Nù§Ž´@dIibu:²Q (n%V™ÔÆ¡ÝNXu^T7dVMâNíêŒtKqL~Þ Ä•æZÿE^pµJUvy_ûØÈN6Orªì£0›Ÿ¹œ>› ‘t e™ªPmȡԮ6B$:ÕŠ^¦½…S/äÑO€T $ ÷@ц2´¡ 4+ÈJs—-Ý 3HMGV5yäihøiŒ!T¢ªç¨ßV*S U©ª§ 8ã´› ‰ž¡b(34øÁþÓ ò¤Œ"%O¹ÊWÎò–»üå0ïs°r‘YÌ<æ›5‚“a„+Š" ÛyÏòieÇ‹‡gÍëk0$]å,4€|çLýØ`Ò ìrš;7áQhÉú@¶~‹®3d_gË¥Çkj½í„;ìÐ'r ¹Óšºr·H‰a8,yï ¦:à—·¥#Þ8"Ø¥‹D_™ÅÞsW¡Ši$‘ÈÛïïásàòçí È|%ÊAýòŒÎg-Äñ3*ûú£yòUP€)úAüwÀÝBÿsàÈ2:¾‚ ç€,Qïýv¾„)¾ÕMB¾cØøÿF~C”BJÞsO ù-þ_z¦Žû³Ç!ŠÁªƒÑG½öÛt[þÌSdýï'róÌ>vÓT×»Òº¿ý‚õWrñåÁ ÇÅEx(N–‡9ñB~EÒ+pØòGj×m=Èd€xVª@K·g:a'ÈöÐvñDm0|¹wxµ0 =— /ë’~Ö£j)7ƒ?gý'oÍrw1+E8 sM8…×ÂKXdÈQ(p“…³q³qFA}t¸b b¸.Hx)s_(03US £5¥PAà ²°†nΡõÁ1‰ ‚2(T‡…‡þzHPÛb3¹×RÑÁ3>c2‡¸E#²€4`C ñ&­ð3,Õ!‰@4eP ’x‡”8Š!P#o|x*R‡U#ˆXC?ƒxaö5’B(@6¸Øì15Š¸Ø t2“8Œ),Ã…}“”P? ¡x‡ K!z¥¤­æz`)§EÑÜôl8ŽF!Ž! à |@ eð|ÐRò@ ýv °†áaŽGŽ•°ìH ¢ÀŽòh–ðªpªöè/°°œ`#ê·Àª`62®Ð‘·@1‘,V ƒ QiàHÑh@r ‘·Àþ êX‘Qy –PChÁ#,v ´À\'" I‘)tP )¢ ŽA > ´  °à” Ñ3gÐO£DÉ”·@“¤”8é•9Y9É‘·P ¹-‰0´Ð¥@¿1Ãñnymi’Á @™2 ™ð4.™hð4t“mI r)—5t—vé#ø•ƒ°–ÎcD¿A™}3I©fPlÐ MQ i€’@qoÂc ¯«€s¬ÙšA!:öK`€ƒàƒºÂFŲK“&*¶™+ua…>HvÕ›­ mNqqœf´-œ&” MÛ ´#²?Êʆ×Ç@õ­2IKAúÆ#>R:#{Ú*(Æ­QËb%µÒc>¶@¬á]Ή¶¡¶Š–¬5ç¶a¬Â*r˧õª‹·q¡·@Ç·ß5«¶ ¸÷U«ƒ{¸:—©¨Š¸Š UP%‰Ë¨>Û\É©ó5=¦°„_¹ƒðq06P¥[Ô¹Ÿ[y¢›¹ëbM *DN ¬ 4!Q]v«{Kiâ]»A-x@-A-v¼e'‡P»2›Ä[h ÈK-FƒDQšu!þJdë¬ÒûF p #ðføNákg QlŸu¸D:  0 xðiu§U‘!qî»v 1×Êú‹d7)Zþ;Jü©ºï9ÞBœüº²D1 þ;j›c U›bˆJÁ¾,ò‚ÁtAjΡÀB!‚AaÂQÒL¿i*x–½q[¨k­Û$s)`š‹?:·-¦`Mèû«ÕY ,ÞÔƒqaæô/¸©›cx5|›±©›UQÄ®yÅEŽþ¢ÅfÃÅ8^¼/aOu3ÆcÆø‚Æý’UO£¾ÐÒ '…rzã[Ù6…YkÐ7=šmƒ =“R*|3eìS~c4p#ÇXœÈŠ¼ÈŒÜÈ QÉ’<É”\É–|É&êÈ;rabbitmq-server-3.2.4/plugins-src/webmachine-wrapper/webmachine-git/www/images/vclock.gif0000644000000000000000000001317712305126066030307 0ustar rootrootGIF89aæ‚çþ $$$&'+*+-(&*-.2555<<<76<3-2!";=CE;ACCCJJJFDKKMTQQQ\\\YR[TNV\^ghYccccllleckfisrrr~~~tu|ueqcT^A;B´33ÙÚ ÖÛÛÔÚ"Ý#%Ü),Ú%)Ù-2Ü5;Ú4:Á""à..á44â<<ÛW$îížþ3æo;÷óiŸ—/ÿÏ<ú÷g¡û·ïÙ3ø™êǯRûs îá§Ø@áhà&¨à‚ 6è ƒóXÝnfEÎ…fxa9vˆáAìÀA–hâ‰(.ˆ”3ë±s]Æ(£†PHY)æ¨ãŽõÜÇ@•ÖŒDiPUò¨¤ŽŒ”‚d8;Е÷bFd]D$YEz˜[^jRd–Yff¦©æškÞÁ¦™hâgšŒ4Ešd•9H!wˆéçŸ~ö)¦ ƒ (¡ÆSˆ¢Ž(Ê矄¨¡b’)¥˜bǦvÜÁé§vµ©§œYY8.©j‚à,ؤHþO¥”,µWžze)‘5çtÉe—4ÔÁˆ7’äªÈ6ø*±8+­*5óLkZ¤ëCÀnøk¶T›ì¸B2È$ˆÀº(r Jêµ¥‹9¶ÜŠÒ üöëo—‘+p8 "2Û œÌ ³p2‰ˆ0ÂÃÉÙÑ1‘³Ï1Wr$_þ01 74@A½rKNb#“„†8\¨‹©þ8cß3ÎØ|3έœìÞˆPƒ‘ P`èB8rˆ°D$+„ƒLGí4oJ‰à (4„É©œ!.:¹ †œ°p!/4¿ø­!þ<ãó¸ m4NþÃ2S`"$c42@]´[ÍñÚŠ’!û³O×AîÏÉ)‹}¡€°]ÎËäT# kÓÌâ äÌKá:3w² ˆ€„ÞQ ß(ôŽ*ˆ#u8M(ŸRÎÀµä[›ly†¹ˆ@/Ã_ØüòmûÃÆ#•˜ê«¯J€ š¼p`7³#Ž&š„’wb»ó~ÑäU‰’#€A P%þHƒIï\8ÀñŠ9¾p‡443#ÅMŽpyüñ`oITˆB&Ü"šÇÂÁµð--9@8¸&7¤+…£H•~ä‹yD\‘_A2Tþ‘CʃžŒØfÀgØ„þ/éÀL·ª NðãR„Р$MAàÁ  5‘¶8ã:+y„bd(í"¨Cèv(:…m«ŽhYD¡”Èj„ôºÔpÐ àÓ ÞfÉGpô î<_±R¹³îó âþ©a»d סÕÀdךͅºu‚RëªÂ¹TØ"oG,Ôª¶ áˆÇUèÚp šm‘›XcjèŸj[}Ë£‡F²Ãí( ;aiÍ…’s TU¨ï(éèP;TïfèŸÚQmÓz] © §¼ý)A‚Z" Z! Â]’gÖË^¥roÃPÄrWa Ìw¯"@¢Qb´ ×¾¶šÇ,C„!Snq7±–H'É‚tR¡a°ƒ¸…:T•jP]4KAèS‡Lf$‚6x(¬2l—LŒÖ…×K5“¬‰zŽš2©Dnߌ¼ ôÁ„H%Žþ”c$e"½8±3ºr‡L§å( W@ê’Jà!+¯)ƒ£d•LY 1B•¢àb-ãÑæÅ2$-i€Å혦¦/ iN£ˆ²07² Ê gÉ" ÇG*G$FPÙ†ú¬±ÉɂԢÒ{ê‰#Œ©‡‹E1ëí›·µF‘p#Ì£6(µ×e+4‚n™c¯>69îàdmϹ!)’ ‡ ]hG;B9žáíe»ØKQ,Þª*âš[A”H~-'Šw»þ†u¼ï b‚7(ßµÑn‰ ¦ ÏÐÀ îlƒ;è2ø\Ⱦq ½¹ã¿w“þ-~q„äÇÁ2:ž!XcFúœõ‘D&XÜÞ$6B6^ì€+Üç'ˆ2  ÅàQ̹ƒ‘˜¿v±Ý¸WY.qoe\¼X Àõ) ¨UÆu®/I˜î:Õ/ô 7…æѺ4€‘ŒC`ÏÚѶf$ˆ‘¶íêþêÚ»å-Â&µIüc.0 |&#©OҦò£œ:ùÄhÞò´½è§0…Ï”Þó–¡™@QóTKsgçH–wí]F} °DÀ†ÁÞíþ(€A”Ò‰ Yj„ü°Ü-ù{¾ú ¤ÛÇ(÷ 6‘¨þñ{±Eê!?{ˆ•ŽÒ¿Á¯t€ý‚`·Ã»oÖÁKg;³OÎü±*Dçy>Ó Š†*)² ‘hú•m¶v¼@ü~¶—KÏ&+t0€ƒV%â‘añ5"‚Â} #ßu–ó :à¦* DŠ 80¯ppu°P€ þ@ ‘ã<7‚ä%!_‚"s,7 þæ„¢-x<˜# K bƒ>cK 8 "¡Ã36_ <$l§_ ·vg9a :Ð:0VÀr…)’… ¢G>“ƒ ⇠bhþÚ0„þ ¤€ ‘†p!  ²¶2gÙ‚>'…äP…T(6|x""R[xƒ#ˆ'ñT èvª±B‚1R[½w!¥á{žpá2t„7ÈAº€\JÒŽáKòAòä&7†%S2]“øØE0@ÓTþ(P`˜(ræmýÆ‹T( ,¶Ps ü·#áŽíUŽ{\c;Q³$¶· ’Ì;Ñ'9d(9"³I° 9…!4i“ç{q˜-Áà‹ThUˆBâÑú‹D©^ Å º;.Rtà7 {©*9>핈!Ðú`Å3ŽX#(` 6P—p eIäðräP1R÷{:`\@…åЖ¢ø‚)Âtà, RŒáhJò c€)ð Ç•”Í0 ±Œ ñÍè!„X€Ãr"0 *cŸØ‚¡è‚Ɇ"ÿ'+­‰Šä¢Š%¹Wé› þa @怜-×?‰‚bÓ‚;М≖öœ&ÒÙ^á %€!5Qá€ZK’ƒS°"`,B‰'©lªÁЕþpþœä -·R)H$¬¦_79#£Ùä:ð 6Œ €`>òYyDÍw `j:rŒÔCg¼) 1Ê_ax‘qGB, ÚbrVÎö*¨2Ì©Á°™ìÉ- ŠdÄPƒ&z åPƒªâ Ct*  M6†pI[Z#ðˆGHž ¸Ú6¡2R…Ý ; s¨ù Qt~Ò©ã$ á 2>\qH €Ÿ9¦c þ\ÁÁ ó˜oú`#?áÆpS#þ0 äÁ†—s¤€`¦Ù’fBZ¤Uˆz¸ AŠ(HK"¨dðCÚ©e1öp!9#¥q³VœBêwH\°¦À§&€¬™ª«Âª v« 1«´º2n&ܧ“›™‡lÊi›¦­™6”K')š uW€#áä:{29À4Ôq®"Xº]šÈ©3B…£ omº ðip…Ö;æ¡WI"`SFÕjCê9¬ ñ ÆzjÿŠ(åð©Á€Ñ%·`¯ó7k¾¨2G Œ›=1-?«‰áBñŸOGþ$› x 8xGúmzj)´ñ‚RQ"°@‘¼™vÛDZýs–ö§z¥:hpš=9{Br5)e‰ñ´!†JEè!ýæs·€hI»‡ûªZ7ë3V»>Yö¾ÄËŒs[Û!•t‹na+¶5[p§&]qHÇ`¨Øá¼G°N§µô:ew‹·K‹ Lç ÙsˆA%Ðg›"p 3ºZ¤qëqMö 2Òv¶3K³‹k ý:0ûm!¹óqµm{˜›‘ûjåqG²@Êj³s³?ÂÕ¢´™‘¹Q¡ HeF›¸§¢¬$B¶>Ã+t ³;±þK"P¹Q$(g·;kžXá,è:.0ѺV„c¯Ï:ø"#·g}‰+VqUZ•í° üKüû¿ÀÀÉÀ¿ë ô s¹Àsù ¬À'¥ÃÁÀ l5A » Á¬ÁÜÀí ÌÀd±ÁÜÀ< *¼Â+L dÁÂÓðÂ0< Ë0Ã6|Ã8L &x´æ¿qRç»$ªÖÐÁ³² ¿!¿~—†O\¿=|x‘Bæ{UJòŠ+‘1mÄ¡Äïë¾M‚Q<‚e,6¥Ë?âK@ÄÄ6W ßǦ›@Ò ^œýðÿ€£AÆþºÅ,Åȶà Ÿ "&2[Åεá qa‘˜œÉšR›¼É@È„ Pʦ|ÊùÙ ˆÌ 31- …{’œ” ZÒäP–°’òÙE_ÊÇ6ªíYª«œ AÆÊv,òÑ®QËQËЊï Ù ˆ‘ ð0Pƒ˼ |° ø0Ï!¹âÒlÔÜøÈ•‘ lP PtãœÌ² â¼v\%üàWÁ+³Œñ¼ûp § Ú,,àˆêù+΂‘Ê B-ì`Á¸¢²‘<ÉMÁ* C€ýÀþ5Ñ÷A=l îkÑÑ ²ÌH1-ÿÀ"~¥ï\  š2M4­ r`¬j²VÓ Í’<™9ð×Ï þP7‘¡½ Á5B9Ä“ S5 A9ÔsqȬ4/À{E,qÙÜ5Žø˜ñÌ"EQ½Ñ5C?+íÔ©EÖsÁÖaØê܉D¼J1 (PÒñ8AÍ7Rs`\6€ g ŒYÏÏ€á6AØrØÚ11±™íÔ, P080ÙM.&Y=áЙ@-,g]Ïú<ªMê#ì¸0Á\£’þû oðvþÀ6"í¦@ ¹)„Q½ÒúÆàwP¥¦q)ðÙþpÍþ0ÜÍ,=M? Aå¨Í±íÅnP ×ÌÞûð5þÏB`)÷sàÖþ°”0 Á_]ßVQÀ²SQwp†9ý l Þ¦ ˆÔŒïðÚQâØìM›Â"9]ƒ£÷=/:Ôs2qM` ÎÁ,>§0'n%ã­].)` á9nN1q±6Ò[óã@ÞO>ÒÀÞÞ“à-é=N§_½ÍûMa^ãHñ:êÞâï¡£wÓ<Ò!O9/°ÒŽm ½îUŽ”úäÁ ³ã ¡çèßFîç@­‹ä’áÓ NsE1Ÿ.êŸÓÕ,¼!0ÛltÆÁ²>ë³Îé¶~븞뺾ë¼Þë¾þëÀìÂ>ìÄ^ìÆ~ìÈŽì;././@LongLink0000000000000000000000000000015400000000000011565 Lustar rootrootrabbitmq-server-3.2.4/plugins-src/webmachine-wrapper/webmachine-git/www/images/basic-trace-response-tab.pngrabbitmq-server-3.2.4/plugins-src/webmachine-wrapper/webmachine-git/www/images/basic-trace-response-0000644000000000000000000002745512305126066032354 0ustar rootroot‰PNG  IHDRž›ÅÈÿsRGB®Îé pHYs  šœtIMEÙ8ð&ãûtEXtCommentCreated with GIMPW IDATxÚíÝwtUãÆñïf7»é„„ª!š ½)¤È‹ô^¤KñETQ¤Š"Š¢"H‘&-Té Hšté!”Ð ¤'»Ùß  ¯èïùœÃ9dgwfîrŸ¹sg×`·Ûíd‘€€€T¯ùûû#"""ÿ9¨ DDDäi2=üBZ½""""OJ="""òT™2zC|l$ѱ60:âêêŒQu&"""Y6bÂY9÷S¶„ãV¨g΀CAzîK2ù:DDDäÉÃFعíôü=9*uæ‡õÉéìX9pƒFdM½wÙµ Ϊ?É@ª1öØ‹üüÉp®Ãðþ “‚Fb.É_¦!Ÿ¿õBÖ~ËòÝ—²`ñ6q'<*Í©vkwÈ}¢é"""ò †K7±;:šmk’Ë1õ ”•Rf–L "â/,øÆ©Mt,VK–¤Dñ¢tÀÍØû_ùq7d7J¡þ{)^¬½'m"Æžùé"""òŒ† ›5±Ávs7§ùƒÅ /GÄ^"<æÉj ?DÙZ¨öå\Ö¯^ÈÀ†^lúù=zNÜŽ °…¥ïkmx~دìøy*!'·âðC7†Ï;˜ôùô§‹ˆˆÈ36î1›Òj·Æ“þ‡3ptÕ†ì§O^,]…þVÓ'¯3WŽ_&ÖnçàÊIlŽ-K—ú¥—ãR^Ÿ4bÎðï8q;!Ãé"""ò ‡Ç?ÄYmi÷l˜œ(àäôÞ'S¨ÞºUÉyžÆ\”|5;q †?·í G¥F<çiH~OÁ2õ!z=^¸’Áô0mU‘g9l¸eK ¡¡a¤5Âz÷:["m¸úÁÓéÉêêé£á~P°Ûnrä÷ÛÔøÏ‹˜ã®±oG^ùs`y0ä$u´üqìxºÓžº¦­*""ò,‡œÅ«QÇÝľek‰H7Ž. UëJYöèë©Ó˜Û…·¼€³Ñ@LxÚƒ=£íO‘g8làƒ¶Ÿ¼ ñûÔ?€ËñI¬œœÏè_ŽP¡õ`ê”ôÊ’ˆ ùWûìaÍïƒðq1à`v!OQgœÜ i®h©‚yÓ^Ò×K[UDDä’æ—z¹=_‘Y?aÅ´‘¼Û} •_«Käæß8l-@¯Ac¨Y¡@–|ƒ¨-ü½_ëÁŒõ‡(•ãÞs¶näÉïÌÉ —ˆîÝ©¹{ã&ÞÙ½±¤7ÝÓ¢­*""ò yä%Ï´ð3ŸõoÈ®õë8—@Í7ºS;‹‚†Ýʸÿ4¦uÀ!þS$[òk ì£H­¦põ .Þ¼OäΕãàÞŠ"yrR"ÝéîÚª"""ÿ„°qOáªóAg6OÂû?¯çüµ;XÿÊØû|Ô„ñ—¢¸vx “&MbÒ¤Iô-[•yóSªz{:2aÑnl@BìY¦~<ŸN£zPÈÃ2˜."""σݞòk7Ò|£-öÁ§Nð矧9üÇQ ~¼ñÎõvLwþþþ©^;¾öSêô˜D¥ŠNìÙûÀ7ƒeëLàžÏðu1uy^kÅŠÈÒ”1à…A3ù´wM\’žbÉhºˆˆˆüÃÂÆ“J+ldžðð(Œ&g\œMO0]DDDþnÏx mÄÝÝý/L‘¿›8ˆˆˆˆÂ†ˆˆˆ(lˆˆˆˆ(lˆˆˆˆÂ†ˆˆˆ(lˆˆˆˆ(lˆˆˆˆÂ†ˆˆˆ(lˆˆˆˆ(lˆˆˆˆÂ†ˆˆˆ(lˆˆˆˆ(lˆˆˆˆÂ†ˆˆˆˆÂ†ˆˆˆ(lˆˆˆˆÂ†ˆˆˆˆÂ†ˆˆˆ(lˆˆˆÈ¿˜IU """:þ>>éþ»üÄ¿ï²Ç±¤G ¾œõ#>>ù)[¹—£žÎ¢BÿXFÇbù)Qþ%v^ˆÔ‘-"¢°·NÿFÁ’Õxÿ‡XæmÚËù‹¹xñ"G‚Va]8¢N–E Óís»ø#$k „ØPvî=Ÿî{b®Å3xÊ*Ž?é?ÖÑØÓ‘UGsðL0Çîä‹îÏq+îï R™)Ç_­ã„è`fîõ£C›Ìû´)8ùa2Eº1wÃQâív¢¯±kã FöîÉÊ CŒi‹íÎæZ¬ØûiñR#6GØxóÕ"t³Š»èGÓ«4>>>”k1„ß…6BïdÖøA´8•Ík¦$Þò(Òm§î°á«º¼3'”eC>À§H7‚.Ť.œÁ6;Íðè4qåüv¬™Ì°¡1&€[v;1—wóa¯žô~g.œfÝâÉt,ÝY gбX~|||øø§M„ß»µd¿ÃúÉ$®£_S&.Þ<"!ö"ŸV*Bñ›’ÇÀ<(Ír(¼žÎ *x)kÌŒŸÏÖù#wð9V¯˜FMãF>øz#1v;/wG³í†}ÈÑýã)÷œå‰Ê_ r+ºÝÍÏÓçS§]¼ œò–¦DD•[7ÆËzƒÀùß°ùÖzÆ-Œçyóé×À‹£:1zñQ°G³|d]–96çÜ… l˜úŸõoÉ'‹&-!Ž?ÃãØx5ÍÞ¡Ôå°?r~S^ºŽJö­óY°:œ¢¥Šã¸{®õFò~ûŠ8{–JUÇN ÑYôëUj—~þþ‚ã÷1`D(ƒ–¯ä“v¹ù¢ïG¾O®2¯³pl'p~•‡éX=/!Ç7óÝ ±,Ÿö!ƒ—ÄóÕÊt¯x’Þ+S¦î<š_Êï7æç¡mÙ|Zc4DD6r|ë*ΙþíwX:r(¾ ¿¦Q¥<”¨Û—¯ÚçeùÈQÏN½NïPÓÍH¯ñèRߟZMÚÐØÓ‘È8+“™9¼ðÈžww®œÄf[m¬·ÿdgПX{ æm>MÁŠõhUÙßFß1ÿƒ”.÷Ú´Ë›¼:®Þyðu1’ÍÛ“lîî8žð^ˆÁ™êèéK`lg™{¬õËå$»_e:ôèî­X>»ËUáýo—ñº·™5û¹qy7}§\¤€[ AÛv™x;dö—û‰²Ûq°dÒŽýl›Õ*©W!¥‡Ëa Íh~>¼0ÂQãÅâÌxéK>oY#¤YÇ×Olæp™1ò¼·ü(poEà®÷(]´-» †ø}\º…É솧›²×¤P>OœÍJ×îJ×Ö¹ñmø5¿ŽmCñ«Ð¶ssp~ »Çá_º8:÷LÚOl:’ED6R*U£ûN‡¦û¾„¸›œ8‰“‡ëý58S敦¿‹×¢ÀhÂÝt¿ö„” OBòØ£9ûÇ.^hR7X­V Öý% èS5ñ Ü=ŸåŠ1R¤ü«D†Ý›Iâ¼#ï=•kc÷Š™Lúi:Ó§OgâøILëÖJ\ž{™o;äeíS8i'ôÀ2Üú´"cbãl‹‹zp‘8¸ä§N‡¼Ü8°™ã'N%6îf+FϪ,]ºe“k`I nÞÞxX5R2e9®?“áü<ü°dl':6 —BLŠ:NšÿÁSx½ËË)Þ÷`y ¦‡ÇWDà]Ðä›jö¤•38&¿æìí&\’F™:¸xÓØÓQG±ˆÈ3îo·ï–Ý€íûNÓø…4¯¾Ijìŧ\i—¤ëþkÑqÛ>:2•«Ty¨gÂv¿{¨|4aÁÇøãœWÜ £TãN™îÝxµË˜ó_ÖnÂsÇAþûÖ€t?â‘Ë<Êc¼sœ_ãµÿÔ  kʺ³Úì`|¼—È¡™˜Ÿ˜» ë3…{>"%íå$Ä^diÀz½éóèâ§1RÔÕ3ýõÌéS¬{SÔ¸5AG±ˆÈ?-l´iÓæ‰g©÷~¥ =§±bZ6½~ˆú/z¥zÏù?¶ÿ|aò8™8¹îa£›qo,©ÝšxÕŸËÃKsεƒŽ&`Äìb$dN FÁÄÐc ;D¾ÇùqN“ÔWëip½÷l¥Á™ºýÆP7ÝÒ>úñ ¯bÕ\Í“/Þj ÏæøË£?nàȺƒ”lÔ¢%Ã!ú'~úõ cÚ—MšÍüÁoàûö,ª>ï„5.š'Ì~Ö4¹Ï+Ñ“ÒßÕ3i?µ#‹f@«.Ÿ0rn]~ìZ1:†°³ÛXáò _çxœ,ëFÈžËDNxGld˜NÚŲg2,«-ì †[‰¹—:À¼hÒÿ]>]÷=-.¾ˆg¿c>x×"Fn»Íûo¼Œ—oYºä²0gP#>ž´ŠÃ‡ö0áÍÊÌñêÇËÏ;‘{ž*• Þ‡«Ò}Rã^9~?“=ýùEd@»OX°¸•kwä»ϳ|h36$=¥“¢Ž7ÎgÞ‚ñtR5Å-”ðˆ»)“CrGâ ÖxàÖo9þ'ë–l!*võôsŽÈؤ§n¢ïeãò¨ó ‹ŽÕ‘-"òÿ=lä-Û†#¿Ò¯ýÛÔÀ/_>|||(\¼[bšrxÿgäwwÀ¯zVMÌäwêQû½ÑôkY…ʆ3gh-L¶+üøî[L0š5;‚˜ÿí¬‹gö;ÿ! (·<%é’ËÂ=òñwªÔjźi‰ƒßíÒ’¦múÐé—­´*åζYŸ0hù5BV¾Í‹w¸â'úN¹׿aô”íØÌ¾tz¿!G~@­&ó)ZÆ'Ý2ïœ_…–ŒK dÕü[¼Ç¾‡Ætø”¯EM7#¯VðMs]ë” aA_ªµÎ÷KvQ» +–ü Z6‹šnFf|Ú›ú šs Ø—ÌTÌ\Ó;Xò§(Ç _~äü¬7ñ~•zl¶ÕÆÙl"8³æ6]j•`éCuüÑÎh¶Î½F×ó?PÓhñþ2_D—!ŸßËû·[÷Æ£9t%†<Å_‚ø}´­×s?Çþù_ðΜPBV¾Íè¿ñGàRöÿâ÷Ñ®ç7ì>´“±½Úr0.¡¯÷äç€Ùô©ÿ&ï4íÆÒ PÝ""σݞòÒwá…سø{ üýýÓ~7ì&QVŒF#Ù½q6§îúçÖÝ( &ry»?ÖòíÖh"ã¸9›SÌ/2Ö†“[6œL3ÆÁFTD,7²¢³>ìøBŒwfËĆ)Æ_ñuC`ÐHrÙ£±›ÝRÕ‹Ý͈XL—e2q%u9Ò›_¦ëØ n\¿K¶œÞý´Nlt8 F·4·¿ˆˆüïdõ¯¾¦º©n·Û3 YÍÃÓ ::»“ÛÙý‰æo09ãfJ=?Oç'™›7—¿T^[øE6n>ŒWþ¬íþƒgîMÕ0Í.p£Éˆ“Åý‘åò|D!LfçÇ.Gzó{œ:Α+ÇÍÃò„ÛWDDžmú‰¿AÄ•t{3q¬FÉîÓXÜ#eoÇå#¬üy„ßaç®®Ô®\šì]틈ˆÂ†d’‡_}6®ôáV|6ÊT,žêÑß[שÔ:Kˆº{°ð8²[,ª8ù—„„;LÔ†ásSMjÒu-[´ v¹üª¹¿À`rã…²U9½`Ù*T5‰ˆÈ¿Dê§Q²ÑýË–ŒmÀ„Õû¹|–»×RôÚtÞhìÏ7ΩæDDDä ÃFw·Äß"±8»`0™Éù|Izù€ëŽê—6EDD䯅´Ä܉P‰ˆˆÈcÉp€hxx81áQœù3ˆÏ;½@ÿNUÓù=‘Çï6©Ä»Iÿ/Úök7Æ7‡‹jNDDD2%ÃÛ(3·bùØæ˜]ÌäðvV­‰ˆˆHÖ…x›3åÛ~°W²säç~¼ûÓ.lª7ɪ°60xÑmâjºYõikfl¹ š‘¿6Â#®‘ôsÝ&ÏÒŒ[8€áª°9éçÅEDDD/l$}ƒh‹÷—ðNƒ2 ›¾‹x»\¥Ú°dl':Ö*Á´-ÁªAIWªŸ˜øŸÿ꫈ˆˆ<;²ú'æT¥"""ò4)lˆˆˆˆÂ†ˆˆˆ(lˆˆˆˆ(lˆˆˆˆÂ†ˆˆˆ(lˆˆˆˆ(lˆˆˆˆÂ†ˆˆˆ(lˆˆˆˆ(lˆˆˆˆÂ†ˆˆˆ(lˆˆˆˆ(lˆˆˆˆÂ†ˆˆˆˆÂ†ˆˆˆüïÂF\\œjADDDž^؈‰‰Q-ˆˆˆÈÓ ‹Eµ """ """ò ªQØ… … QØ… … QØ… … QØ… … QØy€éá ;vìÈÒ…øûû«¦EDDþ¿†;wî-[¶äZ·nýÄ3 PБ”a#>>>ÃÀ """ò¤œU """òô†«««jADDDžš‡ˆÆ±åOŒ™ý{ª7º~…¶ ªQ¦T1ry8©æDDDäI†™òzó…—ƒÇo Ó ohX!/qÑá\>s9cÆ05.f}GÓ¶F! ª?É€CÚ/ZÈûœ Xœ=ð+ù Ïœ@ÛâÎ,ûñ#–¼®Ú‘' ÷Øl ½Û‹ý0wÂn"T"""òWÂFZÌ9©áj„˜`ÂcT"""’Åaãþ'p4ªEDDäi…„l6U ˆˆˆdq؈ºvŽ-‘6¼Ë”ÆKOÀŠˆˆÈ_ FcÊÉöø«,þ亼^GÕŸˆˆˆdÀ”ö˱œ¹Nù¼>ÄFÞáâéCÌÿj"‡ãèøÞW¼äã¢Ú‘Ç qì_ñ-c~Ù À‚qYpo’cy^ïø]*UÄÇ[÷ODDD$s v»Ýþà Yý«¯ú‰y‘ÿßT"""¢°!""" """"i†Û·o«DDDäé…¨è(Õ‚ˆˆˆ<½°‘Ã;‡jADDDž^ذX,ªyzaCU """ """¢°!"""¢°!""" """¢°!"""¢°!""" """òÿ€IU """:þù R±z?®ÆBèËèX,?%Ê¿ÄÎ ‘:Ê2Ú¾Ô—ÝzéÃ_Ç·` F­}üãÁ~”K–dÕ¼g¿|\—÷L¢Zç ¼[º /”,óÔÖãiž/D6þ&S.Zÿ·/5ÝŒätzô°’„ØPvî=ÿ„ËÈKïÏV2¸š'®ÙÍYZ›t¦Š·o_K–Ì7o©†Œ?s²ÉW©'À·á×ô%Å€Á”—7¿œÅw=ž`Êú£t®Q Š4S¥í`–ŒmN~˜ ·l3Æ.Ÿ¥ëûo–Q}L¹hßoH†Çã\ýs ¾&Q¯õÏü~ùx Ž=ËæÑïƒ ˜ùE†ëqûÜ.þ‰|æÎ" ƒ«§w±aÏEÝÝp79gzÄÙÃÁ’aM˜s2úÉ oö$O~ç促÷®gÇá‹OÜE~‘uKÖpÝæFÁJîÄ„Û1fQ½xzyeú½™-‡sn_{:âäñÐÉÓàLñ “N²™9›qwóHñ’«›YG×cȨ¾Ìž^䶉Îè‚ÚÍá­+9x)2¹AZ4ƒ6íÊãdrÿGì—_×b+!!:˜ÉËž£F©ì3š c{Ó«4>>> ›¾;á¡|ù&>>>ø÷Çù»ñi®Ctèf^¯_™Š-†°6è$1ÖÌu•Æ„]`ÍŒO(X¼2݇¬#Æfw#†„[nœ•¸î~M™´üÄûæI¾µS’oUø÷ÇÞ³·R\µí^ü>~MéÚ¢9­jv»ÒÞ9›6=ÞcØÐŒÀ-»˜Ë»ù°WOz¿?óç7eº.Fà˜ªñq0¤ÑXìYJ¾øøøÐwøl‚oÇ?Þ6>µA-‹Ñ¼ys|Štc÷ë# Ñרµq#{÷deÐ!Æ´ÅÇLJög'7<\?{¿O~‹rͺӼÕöž=Ë‚¯Ó¦{º¶hÎüÀP°_gúˆÞøéFÐ¥˜˾°g6 ^hF×Íù%ðÁ{fãã×”=ZðñO›ˆ·Û9·m*>>>LÙ €-<˜¹cúP®YwôåãI«¸el„ž;ÂâŸFðý¯»Ù‹Wʥ߿p8ä†Z‘ôÂÆíÛ·ÿÆÅÛ¸t|cz•¦BÍf|¹¦sVï`\«bÉ á¼aÝXó ëWÿLMãFÞ½Ž»—;Œ£ŒÙvÃ>äèþñ4œg^¿þÌ^ù#-šN¤òç3iP~Ú–Å+]®'+æŽæüšqLZ&͵)Þxû·-£O©Sôhñ*…‹4cΚÝÜxÄ ³ˆ›Á,ÿi…KV¡çÇSùãbÿñ ¾–Ä“ßùÕ#øhA3çL¤±ë!>íÛˆ©[/6¶N®GÓçØrø‚÷ÓË4›fÕK³ö䂿w§å'±ì8´”é‹gЩUîäå¨ÜŠnEwóóôùÔi×/ƒ§¼¥)DåÖ©ÑòÓÇ*ÇÉ 'øó\0gOŸâÔ©S‡œãÌ¥Ë5º?R­×Y~:ržãA¿b_<Œj¯ÍàN&ï]_?¾Œ µÚRñƒM,]º”uß—`P—ºôŸ±/ã+]#Ü:½†É«ÖЧE¢J÷cÖøþlÿ!“×Iýp¤F»·©|úw¢KT§ŒŸ­}N¾½¿s"g[šUɆœÔmX†r=ºRáy§‹ÎWñuú´¿ÂoÇóSµŒ*¾ÎÌw]Y»Å“Îíjàh0¿BUJgoEƒWò“{žá5j3Ÿ6ì\:•y›çqàË7©à?Ž+1áÙò ýGMeÌ[- 8æH³nƤ*òÝs«)W§+­ö0m*ãg K µ{ qwØ¿q>оHýöoãØe,›ö nÁÄ+ýë'¶s¸Ìü<ï7Èÿ”ý2ÝãËÇå³x£G%œ ÷Ëöq¯.î>Ÿ€?àäüL\}³gI&,ø €qK¶ó]ßZÄ\=ù—γ/_í;Äo 'aýe(õ«–Å¿Çh¶:Ÿ©-òÿ.lÄÄÄüï—j#äðïŒìY–—ë´âûm¯2sÅÎùŒ¥ó'_eGÙì4µ‚±ÝjñbéÚtìæCÈžËDÚÀÕ;¾.F²y{’ÍÝMLš'#¹ü*Òû“ŽîÛÀ·ï¼À=[R¶h¾ž¾šÔVÑŽIDAT¤.Óˆ«g˜7~ÅÊT£ï¨© ùv>œ¼@·&/“Ýò@—@îÁ¬˜Ü—Ú5óÍú_(cv`ö¼=ܺ´ö£Î0äÇ7)”݃)>ŸI³_NÙFô}´xc¦ö$¿»²ñZ×!)nsTïxòœ¾ô6Àq–¹ÇQ¿\ÎL—ã~ø†Îï¾Ç€÷1hÐ ÞíÿƬ|àªùóÿû-Ekç"äeEX<„~™«™ýo¿ÃÒ‘Cñmø5*%^a—¨Û—¯ÚçeùÈQ»ŸA÷u.êuJÜ–½Æo K}j5iCcOG"㬮ŸÑý:¾íÏ‘¹ 8nÇÁ¥ -ßk@Èïë8f{4뾙Ļm+¥¾½`0S­Í`_Äæƒ¡`0S²J%ˆ^ÏÆ—’®è—âùÞ€ëß0gÓmê¼1œ/›ä·á׌9˜žf@}¿‡ê+‚Õ‡ãÛh Jå P•:4ötL¾’w“ µ3é\º4MÞˆWÇÏøm÷1¦nC‘Ü®Éa~ßò)´ëñrŠùYß/3s|%Ä]dî¼ËÔ©ð|Šª›²þ(^z‘*õ›$ï“™9¼ðÈžwwrþëç ƒÉâU1ñð ¶­™E]Ã<:4ðç¥ïñë–ƒÜSèI>çÌ™ó¾ÐÃKzRµ~g&¯¹M“Q‹8ü[j—Ë£!ußýsÞÎÉA éúpw?wbO¤‘qü®`òÆõ^ƒo4ánrÀÙp¿' &<Ž„ Ö1[îb´êÿ%gl¤±§#ß íEÕ²EY´qÅ*Ôàý±sÁëMv¼À›­ª‘Ã%õºûVz—¤ÿ;å-O§V¹‰ºu“È¸ÄÆµh¾û÷»MÙòÓì5/N®;È…«WÈ“Ãõþt'sRßtûã¹—ù¶C^Öþ0…³‘vB,íO+ò82U޵§îߪòmôAË–°téÒäßLìõ@6Œàldýi5—ÂR†×ŸestI5¯§;<ܶ¥wµýˆ¿ïuO7*ú"õÚôc¿×,X³ƒ %ã¨_µ(Î7JUoÁì#GY3÷;ü¶ÿD›:ñï9Ž=§®§»Ì¸py<¹÷ôâÑ 7RM÷}¥"ÞæÄÔÆÀ³©Êf4>xÅ]ÁÕ<óVK>Ü܈r\™gT'“!EEe´#¸ Œ»ëñ÷ÏÄç¶Žcô¯Á4dFÌ.äq2qrÝ1¬68‰=¹<\’‘¨è¸ KJ÷®B3\?C6ê¼Ù‡“óмËôïÝŠûp~õúC«ª>é–£È+M¨iùƒ Û‘ï“Þ4nܔƮ‡è×kÿíU-ñ6…ÁŒoÑ!z=^ ¿¿]î$ î|`_¶Ç§yµl2#.FA³ö%‰18$¾vo¹ü*òöWûÙ¿mƒZ^àƒ )^¤‹¶%Êž8õÀÚ‰tR5uƒü ï—™9¾b/²xæeê”óÉð8x@­£)kÏWϰø§(\² =§ËÇ?°iß1fìN)¿œjaDþΰ‘|Eí™Æ]CÇ”O{2iT/^.Yˆ_/`pH<Iºº³qþКT'‡í{÷qêÔ.–m<í+Á½ž·“›•pkBš Vb'vç6ßIþûÂžÙø,C‹Cðê8œ[°cêGø—J}‹Ç`z褸m<Ík•ãÕ³¹iMGXRÛyaï"-¿ÆÈ^5ðÌW…o;äeùÐfl9›øtMLè~-¿Æ{U#‡o9úäufÞÇ™µåáᡬšù ÄïcÖÜ IO6/šô€GWO¾2Ïl9¢¯ždÁÍ8bî>ÔMlæà¶_S\I7}« 7v~NvãØqàæŽä•Þ!toTk|Ê*¾·c…EÇ‚!'­Æö‡[™üëѤeÜbËÒE”ì>‹R¹M`cãw5)Z¤ Ó¶\HÝ Þ<ÇŠ°ølcòUhfÖ ÅÄqåûÍ¢„§œ¥kñº·™†zâë’~ƒlÊVŒ6íò‚{+ÚVχƒ¥­zù€×›Ô(q¿Q)R¹ eÌ Àͤž†àÿók´¯]ˆãöxBößMó@ ‹ŽÅÁ’Ÿ6ï5€«_0àËÕ\ çØÖ•,¸Ǧ-ë9~éþgït¨KÑ¢ÝÙr†Å3/Óôåü©‚ó¾_ft|=¹›ÎQ,wÁÁ29\¾lwÐã'Nshã|v‡Dþ¥ó…Éz#^§X…ô5‡_Ng÷‘3|Ú§Er{¨eyørqĈ#|áèÑ£Yº__ߌo/8e£HÙšôíÖšbÞ×Ùáõ_Góc`0¡AK±òÇvr†­‚¸c\²”§AÕÒäp;Ë„¯¿cæ’Ú721¶çp‚ãì^p¢L³ÞkÏÂ31Úx”ª¿ÄÍ-éþõîœ\Cœg1þœ×/øsr á^þøÆlçFá.Lýáz6©BÞì®®»ÁÁLîüÅiÞ§'¯½T€ïÆí¡}÷F)œSs‡ñÑW_³m댜ê΢ ‹x9¿+̫ޘܑ«èûöç„Þ¾M¯·†0|ÆFºøçÇààNŦþ\[¼„ï~™Î„ SpÈiàôå4oRŠB}q·$žÝsyràçY¼1t89“.óCv/àZ¡7Ò-GÈÎÙ”«×€;§Ö3o—ÍšV•+üøVM†-¾Àò™?’£B+7mL®k¿²bÍ͛ò ¬Û4ŠBvvÎÿŒ¦ïý qÇ8v*–\7Ù®ÁqvÖìÁ¯jMªT­Aíз«.ưwr?¶û}Êœaõq3'·Î`ùî;¾Zœ7Z•¸?^ÁÊ÷½Ú²óB,{¿Lñ yÙ0Š [ƒ9´v>Õ:P¿Aý´×/›ãýmåè‰ùÆn*µ{“¢^ ¦ì˜#wS¤~ {gð½ #9¼¸ð|:WypÀËóžè袃Sn4©ÄÉïÞãÝ ÁÂ§óæ§‘üºñ{^Ì~“Ÿ×eÄ’ë±…‹Ö‚T­\ŒÛGWÓ¿ißõõŸuð³]ä‡ï¿fò„ ¬ "*ÔFËú )TäòfO9¾Ä5ûs¼üZo:6¯N첯p(Y [+2â½ÊXî5äGrøú<ÓûefޝB¶ùxµz‡¦I!/êê>ÖëÂɘ–/¹BõEÙ>áC¾ æÄ¦yäªÜš …¼ [8æÏâ¸OKš=w’a†>ñùân¶9òótÞøa!ã¾þ’Úå‹àá¤o°“;wî`41™LÉ?¼vïÇ׌F#888$ÿ›Ýn'!!„„bcS‹0Øí)‡Ydé ûûû?Åê°‹ÅÍ%˾¤(«ÅFGgµãâžö:F†Ý$"ÖŠ“»7Ù\L©Ë…ƒ³N¦lSÍ#ìøBŒwfËĆi°ÍjwÃÂHÀˆ»§ûÕy|t8·îFa0¹ËÛ=Õôã+ÞfÔžÌíZꩬŸÝG‚Éœ<íῳŒ=ŽÛ·ng5â•Ëû‰·Mlt8ñXps6c³bÊäWu&ÄÝáF”#¹<]þuûedØMl.^x˜o¾vk4‘ñFÜœõ…s"Éê_}ý‡Gq#.n.ÏôZœ±¤3ÝÕÓ×ôÊçîžüÿ{'t[øE6n>ŒWþ¬íþƒgîýŸ OÏ¿ôyGgwr;»§9-ôÀ/Ô–Ÿ];J>µõ3<, O#hÌd÷Îû{òþczŒïw0g#—ùß¹_ºzz?Ù&19ã¦Î‘¿…½ ˆ+;éöfâ=ñ’ݧ1°ø¿ãqöÂõ9±Ç W“Fðk¿… ù[yøÕgãJnÅg£LÅâ)¿°éÌÉÝ[Wû¥ˆ(lȳÀ`rã…²UT¢ýRDþ™a£M›6O<³¬\*"""ÿ|ªQØ‘¬ÿìN$Ž$šIEND®B`‚././@LongLink0000000000000000000000000000015200000000000011563 Lustar rootrootrabbitmq-server-3.2.4/plugins-src/webmachine-wrapper/webmachine-git/www/images/http-headers-status-v3.pngrabbitmq-server-3.2.4/plugins-src/webmachine-wrapper/webmachine-git/www/images/http-headers-status-v0000644000000000000000000144573212305126066032445 0ustar rootroot‰PNG  IHDR Bˆå°vÍsRGB®ÎégAMA± üa cHRMz&€„ú€èu0ê`:˜pœºQ<ÿŽIDATx^ìÝ œdey/~LâÕÄ«ÉÿÞĘ\·˜`î½IÔh”qÉ¢‰&¨j£(*Š‚ƒˆÄ]@EqAed†e€a‡a؆Fd“YØ5^ù?UO÷Û§OUWï]Këó~šÓ§Îò¾ßsªºéúÍó>áñÇßȃ @€ @€ @€ @€]ˆ“ @€ @€ @€ @€º(°QÏíÔ @€ @€ @€ @€1&· @€ @€ @€ @€]cêòpz @€ @€ @€ @€æQŒé¶Ûnk½Þk×®ÔM0Ùí'up @€ @€ @€ @€˜Ÿ3cЍÐöÛo¿xñâVÍêS{î¹glÖáGè¼Af’ÆÚ¦µ×_}l\ëUv©m¼©íÝpÀìºë®óóF1j @€ @€ @€ @€³'0ó1¦Í6Ûl¬SyêôÓOmòqØa‡Åú6•5±©£ê·Wª®yì±Ç¥u}lI£8`¶ªßÖH™aŠ-'cŠ Sl,Æ4{÷¢# @€ @€ @€ @€Ì[îĘªÜ‘"+ùT6‹¼QÛüÐXëcãxꡇª¡®ŠUF &cŠãDÊ*¶œ~Œ)椋„Vô*bàåQ»ÿªOårƶâÑ6tÕº}N~W;Kn–OµË¸¯„L˜`m~½±úܺ¾:œÖÓÅaË`óÙêš2eãZÇâhÕ½ªwE‡ÁÖNT¶Œ£µ?×ÔN4ÖÅ­ÝünƒØrùòå¡_[»É8`ÞQåöhK}‹Ç½¸6 @€ @€ @€ @€tK`0cL‘í¨æ“"ð‰¥’>ÉLR|üǸ1¦Ø+O%‰tÔ4«1Åî£É U°Ô”Ê› s]ùTyd%+HµÞ+åPeû¨›å,x幜OµK‡1ÏGˆÒV9-`ªsŸcËëeHeÊwRt£LuW ëD¾$zXzÕ6«”+ÆÔy­Ù 8Nç]Z‡»TãGa‡ÍlÍX«d‚gìcK&OT¢fÕÄO-x1²Lbu¸Ž­Ã‰{ IbL倭۴=W‡³dð®:мCJ©Ü-yäè[mD­Ú9ð)ß½v$@€ @€ @€ @€̪À¬Ä˜"TIŽÚ#£EµB;1¶Ìµ®¯; Ï´B´]ŸéjÞ%úSêU2‘SuûiƘb÷Rª5¬S‚2"A]Œ1e©¡Ú%ˆTM™¢®sÀ(vœƒS\èˆþDW«5ZCEYʨÃëªÕ¹dVcLåàåf¨v2‹`åšZŒ©\ˆ²}[í¸‚ó­ Ó%—\òOÿôOo}Û[·Ür‹-ãË[·|kõñ¶·ÆSok¶üOs¡ÙF=;Æc‹-·j[lñ–-ÞÒã-úüú׿þ‹_üâÃ?<«?Eœ @€ @€ @€̈À¬Ä˜2EÔú˜S™Z«:kXœ¨Z7¨VئÀÍeŒ)'§+§n1•lMfhâkõ‘;vˆ1ÅîÕí³|T‡Ó¥I‡]j·Wk‡«tèsÙlâ1¦Z .vÌ”[ç³d£<],”ÄXkð¨6É`ë ©Õ¹$áf5ÆTÎÒV»Ú«ˆ4Åcû¸ÏËH«i«o›ç›‘·’Þ<ÈvÛm·ù–o>ë‚3NYvÒ©g.]vÎégžæ9ËÏ>Åù+.½ð²•—®¼æÊ«¯]uõuW_s}£ÅªÕ+/¿ê²‹.[qþEçŸ{á9gæç.;í¬SOYvòI§-9aéâãO>Ž=æ„ï½xQ´EÇuÔqG6Ú±mG{DlÿÝŽŽãTÛ1K¾Gk<;áCuØòÄÓ–ìðÑžö´§}àèÍ«£W @€ @€ @€ @ *0+1¦¶¥•ƪº4ÍjL‘Xªå¥"Û‘³³å£sq£q'•«bM§S­šQkN¥ô3AJ*+:=jÍrUS\1„¶“ÊÕNQÛ¥ö:©!:SöÍXL‡>—ãÌHŒi,™8KµXQµþVÛ)Þ:w&‡S½¯J%ª™1u–qcL1Þ¸ 1äØ2¯~mŠÀ¶ÌI÷æÕ;à—¿òåsWœ}úÙ§yÞôÒEç­¸tù¥W^rõu«®¾~ÕE—\xÖ9gž¶ìÔÓÎ8íô3-Î8{ÙòD¼iõ«›y¦ /¸øüsW4òLËÎ9íÔ3O9yÙI'ž¾dñ©Çgžé¸9æÄïF)bIjKŽŽ£}ç¨oïÐ~{}ï¯î÷•½÷ÿê~ ÷=äðCŽ=ñ˜Å§?‰£}Ò8ÈÒ3OÙúý[o»í¶óê¢, @€ @€ @€ô©@ßǘÆedÔ£íå™ËjLµøKkN%RDYL¨7'•‹‡daÌ2NŶCŸË.1ÕbpŪóY2u”ùª\ÎS·²2VÔdëE[+ûTÝrfcLÕ²[Õ³´1Å|pÕ‚^ÕÎG˜¬v“·ÕŽqûzéÓ7²±ºý•½¿rá¥dŒé¼ ÏY~ñòKW^ºêš•—\vÑ·¾shÌ÷ìç<{£'lT}üÏßÿŸ¯}Ýk¿¼÷—/¸¨fºòê+¢nSäŸÎ>ÿ¬eç,kĘN?qÉ©'J#Ãtì’c¢,S¤—²,ÓDZlõ–>¿çç_ýšW?éIOzâŸø”§<%~ã7~ã…/zá.»íñ¦H Mü€N1¦÷m÷¾±n›»Ö†C€ @€ @€ @€ý.0ø1¦Zþ¦zÁz*ÆT õfŒ)缫ÍUW2=]1eħ:G^|}ŽË=‘àQíeÜa8eKkN®mý§ÖwŠg©ÕîÊ}ËÒZT©õPmcL¡4cL+.[ÉE†é‹/¸|Õe«®½êØãyã›Þø›¿ù›™^ú­ßú­§>õ©OúÓï÷~ï¿ý·ÿV"M/}ÙKúæW¬¼|åê•9æVœÖg~öéKÏ8å¤ÓOÌÙå¢xRVN*ÌuN2EòéÛG~k‹·mñ¤'?9Nú‚¼ ¦½ûò—¿¼óÎ;ÿÝßýÝÿøÿã Ox¦¯Þtÿ÷#O$Õy›SÎ8ù½Û¾WŒ©ßNë? @€ @€ @€æ‰À€Ç˜¢ÂM‡"@scªMjs´E5R¨ë1¦(VT‹+å‹¡:½]|›™˜ÈÖÄòÔbLµyÐÊY¦P©:‹\§¤‹ª¡¢¸"!S¹•ic¤9a_õÑa8yG• ø2>•y©òh1Mö,©öå£z‡Ä·qÒÚ³y!Ê£ím«mVøà}ûÕ½¿zÉ•;”aºüº›®Ýï€ýžýìggVéþÏÿùÿðŸøÄ'ân‰[⤓NúÌg>ó–·¼%6ˆlSlð»¿û»øàöË/¾àªÕ+W\ºâ¼‹Î;óü3¢¶SăNãÜe§uêÉËNjL-7º SçÚH'œºxÇ?üã?ú£cŽ9&Ïû­o}+Öl½õÖùíºuëÞµÕ»bÍæ[l1©idcê—U?  @€ @€ @€ @ <ÆAågÚÆ˜"êÕzÆ*49¹¢3µ,QoÞ‚Ó)Õ†Úö0Bš~ç#ÔZ iú‡Ô"¯6µE!0ñÎOù,1–¶·bcçg«™ëšÎl1¦•«¯¼øò‹¢Ó7=83LOyÊS¢êÒÏ~ö³ÎŒÚHÿëý¯Ø>fÛå»\wãµ—\yñÖùgŽd:åøãN<¶Qfé„Eç•‹éä¾ñÍ^ü’?íiOÛwŸ}~òãçÙ—.]úÿïÿýÜç>W:sÙe—=ç9Ïy泞¹ÇW÷ˆ½¦“dc€{Ø @€ @€ @€ 0f8ÆqHêÄL[­‚c=Õa—r8fÛ`ÍXëËŽ‘P©–Þ©õ*O]+¼Ô¡S<Õ9ßÓù¾‰M'5g7eky¡Ù8uhÌ͉:w>.èÄÓHSv˜›³tîÞ¸/–)®—wüÚ>_[uÝÕW_·êÌsÎxíë^™¤'=éIŸÿüç'Øç“O>ùÿøc¯?ÿ߾軋®½ñÚ—^xÞ…çžqÞ²SÏ\zÒé'F¥FA¦%Ç|wñÑcL'ž¾äc >‡zÛÛÞö_ÿõ_ÙŸÿüçwß}÷š5kn¿ýö˜`®ôj¯½öŠ-cú¹ØKŒi‚Ëf @€ @€ @€ Ðï3cêwŽÙîLéÕ!V5Ûgwüy+¡±(6‡ÿµ}¿u˜®¿åº/~ñ  úßøw¼ã?üðÄ)?üðßþíßnÄÞþ¶ëo¾î’+/.Ètú)ËNnÌ+wÊqÇžxLdúî $ÓX©£(Œôž÷½û OxÂ>ûìSÎoo¼ñûoÿíéOúATÖŸ}öÙO~òo¿âU¯ˆ½Ä˜&~±lI€ @€ @€ @€}- ÆÔ×—Oç è$°Ï¾_[sÇ­K—ú÷ÿ÷¢Jþççw^îÕÖ­[µ¸6lØðË_þ²¶ò¾ûîûÕ¯~+ï½÷Þw¿ûݱïŸþÙŸvÄw®¹nÕ…—,?wùÙËÎ9}é§œxÚ’ÅÍyå¾»äèqcLïÚz«ß}ÚïVg–<ôÐCãÈùØzë­ËHV­ZõüŸÿò¿ÛDŒÉýM€ @€ @€ @€óG@Œiþ\k#%0ïöÙwŸ»ÖÝuÐ!ýþü~”bÚn»í’à®»îŠÿê¯þêyÏ{Þ&›lrà>ðÀ1¿Û'>ñ‰¿üË¿ü“?ù“W½êUGydÖm:öØcë·~ëIO~òÇvþØM·ÞxÑ¥+FÍ+·tñq'{Ì ãWcŠÓSÿûS9æ˜r¢ÔS‰1•¾Å³+W®ü“çþÉߊ1ͻր  @€ @€ @€ 0¯Ęæõå7xƒ-°ï¾û¬»oí—öüb¤…~ÿ÷?bC1ÞH,Eé£X³Å=ëYÏzò“Ÿüßÿûßyçßÿþ÷Çʧ<å)Ï|æ3c¢·ßû½ß‹$SlAF¶)žÚâ­[¬¹ýÖ‹/¿èüçyþ§uÚÉËN:áÔÅÇ|ìD&•{ïû'ýâ¿XÌ£êR„¨båsžóœj•¦SO=õ7~ã7_õšWªÆ4Ø÷§Ñ @€ @€ @€ @€@U@ŒÉý@€ÀÀ ì»ß¾Xÿù/~>¢BñqÑEÅPO9唨®ô›¿ù›ýèGcò¸ÈmµÕVÿùŸÿù;¿ó;±r·ÝvûÁ~ðÉO~òMozÓÕW_ÛÇÜsïxÇ;âo|Ó¿wÇ÷.¹ââ .:ÿ¬óÏ<í¬S#Æ´äÔŽ?ù¸qcLKN;a×ÝwtÔk_ûÚÿøÇEüÛßþvy›m¶)kþë¿þ+2UQ;ê?Þó®ØkÑñGM¹E ê½Û¾wûí·Ø l` @€ @€ @€ 0@bLt1 …ÑÓƒë¿ð¥FŒé5¯yMä“âùÃ;,¾éä–-[V6?ꨣbåŸþéŸVWæ³<òÈŽ;îϾéÍo¼íΈ1]2…Säœ=âWÿëã8Ÿÿüç{ì±<ø¡‡kÞýîw—žœp O{ÚÓžÿçÏßÿÀýc¯)g˜bG1&/ @€ @€ @€è#1¦>ºXºJ€Àäª1¦W¾ò•·ß~{ìÄGDr(¦“;ñÄãÛŸþô§ëׯ?è ƒb峟ýì¨Õ”+×®]û³Ÿý,–£xÒ;ì0ÍS„Š¢´ÒîŸýTL`eŸ¾úÕ¯F:*óÇýßÿû?÷¹ÏÅò/~ñ‹ÓO?ýÏŸÿçQjëm¶žf)&1¦ÉÝ+¶&@€ @€ @€ @€n ˆ1uû 8?³&04©Ü>!¤ç?ÿùçœsNœêì³Ï~êSŸkb.¹[n¹åÃþð_þå_Æ´nÏxÆ3båvÛm+?ô¡EÎiñâűýÝwßý–·¼%žÚìM›MyR¹½xÑñ'÷Áà)Où'?éÉQáé†nˆëxà˜Û."V‘mzú<ý‰O|âë^ÿχ}ØwO8z:¥˜Ä˜fí¶r` @€ @€ @€˜1¦YauPzA`ß}÷Y{ï={}u¯¨oô»¿û»Qr)zõÐCí²Ë.ñm$“žÐ|üŸÿó>øàÏ~ö³OyÊSÊʘ`îøãí¯ºêª¿ø‹¿ˆõoÇÛoýþ-_~Ñù+Î;óü3N;ë´“—t©‹;ùؘý-RGTê<ŠmŽ=ñ˜wÙé™Ïz擞ô¤'?ùÉ/|á ·ÜbËø‡ˆdU˜~ÿ~ÿmïxë·úö4§“Ën˜T®nB} @€ @€ @€ @€ lôðÃßÙî1ÁýmF€ DÙ¡Ö7›{î¹g‚»Oa³}öÝçöÜ~äÑGn¼ñÆ‘CzÏ{Þ·Åq~ô£zè¡Qcé oxûÞõ®³Î:+VF÷¾ò•¯ÄšýוQ´é×ÍÇ‘GûþÎS~g·Ýw»áæëW\ºâ¼çžqÞ²SÏ\zÒé'ž°tñq'{Ì Š1eM¦ØþÀoøŽ­ÞñÜ?yîDý¥?|z´?þ_üú}ýÞûï9§qãP¬Ò$Æ4…{Æ.´ˆy0ýºèÞ @€ @€ @€˜mâC© Û=fûÄŽO€À|¸õÖ[[ßl®¸âŠÙsØg߯Ý|ÛMË/^þ¶·¿-¢HÏ{Þó–.]:©ÓÝqǯýëcß¿ü«¿<áÄÅ«V¯\~Éò³—Ÿ½ììÓO9ã”O[²ø”ã#x4ÁjL?Š”R–n:ê¸#<öˆl±OM¤¤Ó3Lª1MêBÛ˜Î6lð뢛„ @€ @€ @`¶Ęf[Øñ ˜ûÓ¾ûí{Óm7G’é€oìÿ;¿ó;‘FŠbK÷Ýwß/ÉÏþó/~ñ‹±×oþÖon·ýv·~ÿæ+®¾âÒ•—,¿ä‚s/<÷ÌóÎ8íìSO9óä¨Éy¦%§ž•™"Õ4ÁÇ.Õ6©Ý'r–3/8cÛn»ýöÛOp¼6#@€ÀXbLî  @€ @€ @€93ÆÔvê+  0eU«VÍq5¦=÷ÜsÙÙg\~ÕeW^uùû¶yïžð„È$½ï}ï{ðÁÇ}{ýÙÏ~¶ï¾û>éIOŠ]^ö²—ž~ÆiW_¿jé²¥G}Ä·ŽøÖ7¿}ð‡.<àà¯ïà~û}cß}¾þµ¯}}ïh{ïÿÕÞi}ëÀ-Þ¶Å;ßùÎ)_2; @ n¸áÕ˜ÆýÁa @€ @€ @€i Œcjûa••˜YYTnë­·~îsŸ»×Þ{]óu§œvòËÿîå‘IŠÇ[ßúÖk¯½ö¿øÅXo ëׯÿüç?ÿä'?96þ£?ú£}öûÚ-·Ý|Ô±G½bÓWDjšìC>2Y• µåižeè€OØèo|ãÌ^2G#@€@˜æ¯¡v'@€ @€ @€ P0©œû9˜ûIå"Æ ¡?þã?þŸ¿é{7->qñ‹_ò⌠ýÙŸýÙþûï%F¢2Ó£>úë_ÿ:¦{衇֮]»xñâW¼â¹Ùÿøÿã3Ÿýô÷ï¾í»‹Þäo7©&¦¼ü”§<åùÏþ ^ð‚§?ýéqßÿýßæÑžúÔ§>ç9Ï™ò‘ÛîhR¹9º¿†À@ ˜Tn /¯Á @€ @€ @€zE@Œ©W®„~xnŘ"Üóìç<û«û~õÆïÝtÒÒ“^ý÷¯~òo7Ê,Å#2C[n±åî»ï~Ì1Çì½÷Þ[mµÕ _øÂRiã7Þ{ß½¿wÇšS–òºyÝL¥‹¶Ûn»‡~øšk®Y¸páŸüÉŸl»í¶K–,yÆ3žñ¦˜ïÀœ©åqĘþ•e€æ@@Œi‚ @€ @€ @@ŒÉ=@€À t1Æ”I¦¯|í+×Þ¸úò«.Ûy—Ÿù¬gþöoÿvÛÀПøÄ§ÿáÓß²Å[N=ýÔ›Öܸdé’×½~Æ2LqÆ \|ñÅ/}éK?÷¹Ïí»ï¾¿ñ¿ñ|à ƒÚqÇ¿ùÍoþæoþ¦ÓÝ‘NC€À„Ę&LeC @€ @€ @€© l4õ]íI€ÞÈIåÊãþø>ý¹ÿ¼èÒ7ÝzÃ]°ë§>ùŠM_ñìç>;"Mdzžù¬g=ëEý¢í?¸ý)§|Ó­7^¹êŠC¾sèLÍ%Wºå‘¢ÓÊ•+£SÌm—ëwÛm·¥K—F¤if3Lª1õöªw @€ @€ @€ 0" Æän @``j1¦Èô<ñ‰¿µÙÿíèc>oŹW\}Åu7^wÃÍÑ®¿ñ–¢ÝpËõ×ßtݪÕW­¸dùIKOüðŽþý?øƒÏ}ò“Ÿ¼âŠ+¢Ó—¾ô¥o|ãyü˜Øî¬³Îšñs‰1 ìÍm` @€ @€ @€81¦»¤D€À°@kŒ)sBO}êS_ûº×~qÏ/~÷øïžxÊ’%'Ÿ°ä”F‹åã—·ßû½õío}Æ3ž1¡¢8æ[ßúÖ˜_鍊nŠS™Bn»í¶‹yåfãŒï}ï{Ý @€ @€ @€ @ ÷Ęzÿé!SØa‡:ƒžÐî1Y¢Ú1cò¸'>ñ‰qò²>;2ã§þíßþíOúÓSä³ @€ @€ @€˜C1¦9Äv*æV ænÛx~<ž÷¼ç=ó™ÏüÓ?ýÓÚp#Ãôë_ÿº­úÂ… 7m>baj—eýúõSÛ±ìµùæõ”CNðØÛl3t„\Ƚb@SÓ¨þÄ1׬™æ§ÞŸª@fµ7Ñ·¶ë'ÞãVÿ‰ïkK @€ @€ @€̸€ÓŒ“: æZ`Æ ^xáÃ?<ÁGziÁ‚«šm¶Ù&–'¸cu³Í§‚ÙxãúiË!'xìÚöùí{4Úô›núøªU£‡­­™ÈY¦ÖŸª@[èIôp:Vÿé; @€ @€ @€˜¦€Ó4íN€î L*Æ´hÑ¢Z)¿õ‘jÚ£™ŠJK±5Ãõˆ–/_žk–.]D §¨ü”•œjÇ–±WîËñ (b4ñdœ0‹'År¬Éoc!¾>òHce,ÄÊr˜QZ´hhÇ\({Å‘ËʽJ9¥ L*Æ¡¥Ì*ÕQ¢)ŸŠXRD”"® ¤Xi¤xÄB„œbM<߯r>ÇBl|*Žk2Æ9§“ÖEŒ&¦E‹8NăJr(¾Í€N$b!óL™pÊàQ)MûæÌk¹PöŠÁÅÆÖ‰ðM&ub9K+Å¡²‚Q5oTÛ&RGm4t´Ü+ÖäIc!ŽXkªOåªkb›X§ÎlVõQžÛäs÷8Nf¤R Œ.–³3I‘89–laÌ5 [Ž_ÎÏãĵçS)Ü:–oì5ÁBYóéõg¬ @€ @€ @€ÌŒ€ÓÌ8: º(0©SfŒZ{›A¥XÏÆLsÕ)çy䑈+ÅS%ÏËYÃ)K4åÑ¢žSìX]ÓÙ¤Z (絫MW7-B6µ¹ïÊ”je¡uR¹|ª:=\qâP­1¦Ší£cyê2…\ ?åšÖ§Ê–%'Tz••ª2ðìI9W,T³D¹K'j;ef«ä™ N¦âÙRö©vüê©«=ÏÍJ‚*1©ÚXªã³Ls&»Î·„g  @€ @€ @€˜ÏbLóùê;"0©Ó‚ j1¦ˆD5Æu•âÛ|D2)2LZÊåx*ÓNcН9Í\<²DÓbL%‘Óc*Ñ¥j¤)ÎÙ|ª,4;ÓXS(ej§Äzʳ­1¦ê6¹Wkâ'#GåD9êÜ,žÊM“*»³Œcʳ‡±W¶E~-£‹üP¬‰g³ŠRìR@òŒñl´ÌK•±äñ³·‰ºG­Õ˜2TbLYµ(ùT|›bCóÁM¤SÆŒ²ÀR>"®”ÓÌåXÊ0c³’èÊ(R ZµÕbLC‡nþ§ ³ô¼º&§ö«%¶l ?Ui™ @€ @€ @€3" Æ4#ŒB€n L*ưQ–MŠ…È0Õª1Åñl’b!&’‹ rû¨Æ ‘sŠmbÇØ&æ›ËóPQ·©cŠ-sã¶jÚ&³8YÍ(“4‘ÚÉ2E±&–cƒÌ U‹•oóø¹Wk5¦ˆe-¢,\²&Ž–ÝÈ,Qìžkrö´2½Z‰1e€) ÅK¤Ü7×äÆq®hÕmâÛœ®5fT6Žã4kc ¥”>ÊÉæÊ5cLÑÏZö<·ïcÊaæqªÏ#$NëXĘºùòvn @€ @€ @€óF`†cLW^yåâÅ‹gOʃ_ýõQ d¬~úé±Á”»ûÆÆ=Ë”?g;Ƶxì±ÇfötE¾ó%˜ÈI£o³z·L¤¶!0“1Ũ#oá¤x#…Dˆ¸RU#ª4UßfãÙXGn)y„œ].±P–˱¾ºÜJ]BBͳ=Ÿ+£S¥àPÒ¥Z^¨o*je^³œ¹¬Túi <åle¹c­@QíDÕøN9QìGhÛ‡RL(7.ñ r–ìX~›sÏÅfÙáêñ3UÍNµ]m›¶Y«ê]UMU#GÕüSn_ªCå·U̬¨”jÔ)ëBeZ«æ©¦Çªò­Óùå|‚µGµÃÕ^ÅrõZ”³”ÉûÊqjQ­ªŒeŠ€“› @€ @€ @€ú]`bL¥|QZä´k9›X†‡r}©WT%«Vú)¹–Zž&B6qÌêüqµèO5áT1mÃIÕþ”n”’N¹&ž}γä³"T<Ê wÕþä69äj«íèªÁ jE¢¶Õªª£¨v¾Š\RÝ`,Ì(”£‹þW§É‹oÛ²Wm‹I^Ù0*çªæ¨b˜­ ¤ê)ª÷C9KUµÚÉ~™é?Ù˜lŒiýúõ .Üc=-Z4Û}ëpü=ö˜îÉK÷«ãˆLiKѽ©œháÂÇyd*;Öö™~Ú^¥è[ôp:iú¯_ßpž¦Ò4q¦0@û @€ @€ @€ 0³Ó1e(§Vtg¬zH­³¹•yÇr6±Ro©3bCY+(žŠàK&oªQ¡,UŽ\ ÄÄS%~”“Á•I⪈9„œ7-NWž ùlNuÙl³Í2“޽òŒ¹q-ôÓvtÕmª‰ÚVŠÊˆXŽ¢Ì—uªE•r8Å*ûVŠEŸDÈ£•#d"ª”’ÊKYU›º®Š“+±Wémö°5ÆTN-â–Ã)“ÊUû0³w¼£HIŘ"ôñÆ/X° bLÛl³Í¦›nÚ-“7®Ÿyó͇֔…Î}+}Ï…Ü+Ò9Ó èäI㘫V:Dvjk&B7µþTÚ^¢èÉ4/]«ÿD†S¶‰qE©UiRqj8¥ÓG¨ ¹Ã7Á{rR†6&@€ @€ @€ @ *0ÝS­|N:")‹‰òBÕØP,Gº¥¦Ÿ•2¢!›͉xPfƒÊšLùÄ6qØj‚'–«ßÆ™ž‰ÍªYŸ¬ÔÚìO™ý-²ÏÕ³ä©óìq®øš{e'³>S°ÊÙsƒ¶£‹mJÀ¨º}mß:Ÿ¦èU³J72ÅUb!7®­•=ŽS2jÅ$ K9Qœ«ô°(U¯xu8ÕÎT{[[³¯vÛø–šÀ¤bL‘^Š S9BĘ֬Y“ß®j>ÊSe}.<Ò¬MT6ˆ8T,ÇײýX»u½"F‡Œæùc931™M)+c¡*Ë‘¡É¸R.”½2SÛ«Ùó‘ãĹJ¥¥rÀJ,Ç×ÄÁ«kâ©ÒóZu¨ÚÀc÷Ø2wÏTPK]Œ=;S(J!¢X+ cUa«7OAÎaÖpš—®ÍXÊxó\ùHÉšR9~Y¨ö'6Ž ]}t¾Xcõ'¡òk^∗•‹•Q³]v;£Nyõ+ù½Æ6¹2S½[µk÷d!/V‡ãªo @€ @€ @€O`ðcL0Ê FãQLîùÈEe£\˜Üζ&@€ÀŒ L*ÆgŽ$SdŒ"ÌÈÅš… –MY®©mŒ©l;f *¾F¤)Ž_sL™yšÈø²SnÊ W¬)å»r\e›Ì*å£R*gÌQ”ê\ÙùVíX™OUïɼŽ_•·L€ @€ @€ @€À¸ƒcŠ9Ñ"l4ÖtrãuØ i€éľ˜¾ÀdcLåŒñ©£Ì!EQ¥\Ÿ¦¶1¦Ì<Å#bLÕnÇöŠªF£ÆW9F‰†´Æ˜JÆ¥‰#Gh&³)e!–[+-eФÚÙÌú´Æ˜ªÛä^ùux¼ÿ–SµÎT)É+³8PÙ}سMŒ©úTœe£,­Œ¥:º,õÏ”U‰ÐOYŸ×§ k"©“½Ê…2¨RN©zêØ>~¬UÇlÝ+ð³8V«RkŒ©$º²oÕþT/Dq·?Õ‹•§«î’>µm²8SÜãÕ³§a¯Ê„Sé|M»<ÕcʧÊñǽím@€ @€ @€ @€ÀXƒcrí  0ð“Š1U+'…L$“Ê#¡"ÕÃM<Æ•œ"ÆT2,Å'šHŒ©ÄJ"}R,²;Y³§,ÄòX1¦jÔ&ò7Yü©THÊnÔâ8cL±q©ëSjÿd¨µìX²;¥ÖT¹k1£ZB+cF9–2º~))T­Æ”•œ2QT­Æ”çÊZAQj(cO±Pfö0¾–8nž:XK ';V®ËDbLe¼Y̩ڟ¶1¦qûSXJ@UCKe‰P®Td˜²DSÑ(‰®Ì6•qµj—§ZcLµã—«l @€ @€ @€É ˆ1MVÌöè9IŘ"o”sÉEÞ(H11Üš5kbedÊgãk¬Ì5‘jŠ…Ø8ÓN9ø˜].£Nñ5–c³,à 9ßÜ#<ï,ÕcÊŠAñˆ§"t’5u"Ê““‘e^¤L?—ÙÈÓäBÙ«5SªÅ¡ò¤±ù›ˆFåšœž,Ni¡X“›ÖjLñl†â¼¹{¦‹J‡s÷xäXb›Ø2ûßæ$zµSuãØ=ÓZyÀ2º ÖÄÑrñ5ó4cŠå$*IŒ1U9ÌX¬<ÖdÊ'0ÛŽ¥ZÃ)NZËTÿ2–êB0•µ›¢õb•vèO²§ÆÊšH*ÈY­*X­ {¥vjäˆòªµj—+R|òBäëø£è}C€ @€ @€ @€ÀxbLã yž=/0©SŒ&bFHвLñ5–s|‘dÊ R©«™¤ø6ÒH±&bIñµ:f¬Ïgs÷Ø8òL倉1•„M„{ò0‘ÅÉêAYÁ(“:ñTÎt–Ü«ÄhÊB¬Ì½b˲qIE„%3%ó”‡õYÕ©œ=ó@ñ(û–“ƾyüØ ÏUB9Ùó<~W®ÉŒQõ€ÕWÇ‘šÒ™<~utÙá uE+h¥'‘.Êþ´=þÐ ›­ñ-'r´ê6Ñ]wÝu¬nÌÞy'ÛÏ®lÿÐCu>ï¸t¥ÛNJ`€&cêŠÚlk³Úí •(U­fOëy«…šfµWƒqðêŒoƒ1"£ @€ @€ @€ @`6z1Ætúé§G„¨ÃhãÙ Ê\ýõpÀŒ»¬]»vûí·¿òÊ+ãøÕƒWÏÛ¹‡3Þ¥Þ9`\ÎæãnÐ;cÑ#0¨1¦êäesp±"ɳƒEËÙë:qäHÅ#V–ÅcMl•“ÊÁ3`ÈBÅrìOeu¥ÖkSíUž4ÖTO‘»´ž·Œ±Úɶ/'ãGgòø±¥žZûœa©ìpHìU’Âùhí|¢e9«µŒòÔf+aRÂ'6.õ“ª§(y¦’Œ‰sU£6Õ Oѯ–kÊ•cu ª!—«É8Q-ʨc¡š¬Ê«}¨n™ËeyüR䩊ƒdÈi¬Î…Vº]Û¡Õ[6+H•™ìâÚU§ºËaÆ6±ë«TÇ[íXlV;l¿Ht@Ï ˆ1õì¥Ñ1 @€ @€ @€˜¬À ĘªóµÕ2@Á‰tNLLVI¹A)ATº›ÅâÛR§šì)uŒªÇ/ɘê–e.¶8o)æ‡-á§rÆZ¨t Êí«ç­&uÊYÚ¼v1ª}¨–\Š,Tú$WîUê•…XYŠ0Õù*EégÛöí@µÃÑ¥œQ.I³‡e¯ZY¦2Õ]õ°e¼y„ZÛÃNö®µ=) ÆäN @€ @€ @€ @€˜S)ð“(XÉ9Ñ"=S&›++3îqœLäd´%·ŒÉÚr÷ئzœ¬á”ÇÌÂ?¯)ç¼N–>Šc–2Hµ°QkŒi¬Ôêå jç-a£rê±^n”Z¬ª0ûœ!¡œú-GWfÊ‹5iëKÑ£zåŒ%QÔö°m;P½­‹d†Ò?'΋…œ.°tu³Í6+W-7È©÷òBG -—óªåŪv`^NB`ŽĘæÜé @€ @€ @€ @`öf ÆTfË^f¡ œ‰,“+ñÈO®Ì˜Kmef˜"ÚRŽ–A™,/T›•Lõ¼™Ô)y 8Tdeʉ"&U¦B«RV{•ˆG¶,—kç-㪞¥íÀË¢¥$U®,}ާÊfee™“.“CµÑµÕ‹NVMªþ­‡«¥'%~TUÍã¤O,çÍ TV޵A¹ía«Å2xä‘G®m÷øÅ/~1ñƒØ’ @€ @€ @€ô‚À ĘzaƒÚ‡Ú\uƒ:Lã"@€ @€ @€ @€˜çbL=}D§Z±«žî®Î @€ @€ @€ @€˜’€Ó”Øæj§˜e/su6ç!@€ @€ @€ @€ Ð1¦î¸;+ @€ @€ @€ @€E@ŒÉÍ@€ @€ @€ @€ @€@—Ęº|œž @€ @€ @€ @€.ǘ/^üØcÍÈe¸þúë—/_>#‡šþAfp\¥3§Ÿ~zŒqú}Ë#{tr¦Žæ8 @€ @€ @€ @€¦#ÐåÓöÛo?ÞW÷PN}fêhÓ9N$„öÜsÏé¡í¾»îºëm·Ý6S‡DTp¦Žæ8 @€ @€ @€ @€¦#0“1¦‡z¨µ+k×®m]™[F(§–¤i{„¶Ã›ø–ÑiÛÉÎ;Nj—‰÷¶ÃaKä«õhc¿íú\©¯Ã;l\œj­¬I yÜ#Û€ @€ @€ @€ @€@˜™S’âQ›މ LYY¦{»òÊ+seylذÁÅ#@€ @€ @€ @€ @`0FbLwÞyç7¾ñ‹ûáqÔQG-_¾|0.€Q @€ @€ @€ @€ 0*ÆtÈ!‡¬é‡Ç’%KĘܻ @€ @€ @€ @€F@Œi`.¥ @€ @€ @€ @€èW1¦~½rúM€ @€ @€ @€ @``ĘæRN} ëׯßxãÍÓ7uÁnï—/›o¾ù6ÛlÓíî8?^Xºt馛nš¯Ž ôJ·ôcªïÃñV3ôâ(©·Ê]W~è­þéM ì±ÇÕ{&Þ©z¬ƒº3Pñ¿–q•w'?êêvL\÷x·)›ÄrõÛùã`¤ý"wìªU«ú¥·sÜω·ñ9>i/Ÿ®ö†jðG†^¾^³Ñ7¯ˆÙPuÌ® ä/íÕnÄÿ·Øõë2ÙÄE\¸paÙËo8UÀÉâ«ÿ7™ì­eû(x‰Û;‹-êñëÉ ˆ1MVl·Þ~=íëëZýŸˆ1Ugíëqé<éÄçgñÒ(›ÅKÃÿ¨LÇÓ¾âf+Ä›°¿oºaæ@ z×ÍÁ霢ß„ úý öQÿã·¯ê?’‰¿£ù±ØG—oš]­}6àgšžvŸm¸cŘÆBcªÉTßÐ|:Û¯ÍÞ<¾ßgzóºèÕ4Z?ùδÇ4k÷9È@Õ ò¼~Ã)þñã;4Ræ‘G‰A¥çøætºY¨þRZû8lVÏëàæL@ŒiΨ{÷Dùƒ¼ü8ïÝŽêÙÕÿ‘ö—b· ˆÿ-©ÆÏã].Š3Á!0Kµ@IÜ~¥³Dí°E@ŒÉÍ0)¿"NŠËÆÓhýgþEàt<ûk_1¦þº^zëC¾÷€S §ü*å_ºÏÛ·1¦y{é{àùË[)¿¿·Ç/óbL}wѳS¹Ž~éþ鬤»be$™¼™÷Ýí­Ãjÿîµïn<1¦Á»¦“Qü}"†¬TÉäìzfëøÝ+ÿžQ­g.‹ŽtYÀü]¾óìôµûM\`ž]ÿî 7îºüå-fîÎe蟳æß¦Ë ¼ëŸ¾ëiŸ ø¬Ï.ØŒv·Ì×ÿ²?ÿGuFÏà`fRÀú;hŠ1ÕpÊßÜ|º?“/¾:–O¾ûêréìDòGa¹½ãÿã_z£›(_Ïl—W°ü£J¿áä•iûË œž¹mudâ~Ž?Ç­x÷®Ve›£;˜ÓÓg>ó™×¾öµ/yÉKâëÞ{ïÕæ§öX²d‰jfêæÉ‰–â=Nµÿ™"ûãäGyÆœ{gìM¡õæuÔ^‰1 ê•íåq‰1õòÕéÁ¾‰1õàEÔ.U&æì²,ƒz­[ÇUý+jüÿ©+5.}ŸŽÔçX.œS '~•Šgùg7Í>}ÉO³ÛbLÓ´{o äÂø„(ë§Æ[\|+ÆÔ›«C¯ò *ÊeˆÁo8i%ÆÔww²OV úïˆ2‡:Ù#Øž@ ÌQŒé¤“NzÎsž³ÑèGä™bý’LbL3xW•B>åÈgðà57µÿ‘öÿÕsÃî,=.¿ÃU¯ñ¿pñÿä=ÞgÝë_ZŒÉ¤rý{)û¨çš}t±z¡«ªÄõÂU˜'}¨M죮Õ9Ÿ'ós˜&•›Ÿ×½GíC¾Ökõ³d£S '«1ÅÊüØ?¯íßþ”{îÏ­S¦³c/ 䜯#’Lñcêåë5VßÊTN-ç7œ2µZÔÊÕôã®Ïc øc‹{càæ"ÆtÉ%—” S,TóL‘dcêâM¿ÖT?×ÏTÔÅþ8õÔªÿ#×Ô?˜˜£½L k —ÿQ‰÷:1¦»Ä=5œj $þúãï›=uuµ3bLƒzegi\bL³ë°­ùs°|¾›÷*\1On1¦yr¡f˜>äk½”ñ‡Áüg“ Õpª¿J…’¿¼ ÌûÀÄâó'neË>(? sFàè¹S]¾ÒÕêT|ÀÕ$â:öã@f¼ÏA®~"à‚vÀî ˆ1u×ßÙç@`.bL;í´S–aŠÐRDš"·3Ê•ÂLS˜]N5¦™º3jÕJâ°ÂÈ3e;—Ç)“5Ä‚?ÃÍ¥¼sõ¸@ü1ÿ'<2L=~±ú½{Õ÷áø{AüªÓï#ÒÿÞ¨Þu¹Üû}ÖÃ. ˆ1už:?ü· Ó¼ºjs-yç™WW¿›SçôcÏgµÏåÝÛ´UçÚšÏAgõ&ì̓×þÿ«7;©W&+P~FÚ#ÿ}{üdôÝ'ËØõí«ÊFâ7œrQâÞÎOÍ|@ÐõUf\ÀdÇ3Nꀽ&01¦-·Ü2‹0UKiÊ$S„œ&[IŒ©×n#ý!@€@Ï ”ôì¥Ñ1 @`°âoèƒ=@£#@€À@ øŸè¼¬E€æ­€ßmæí¥7púZ`ê1¦L&Å£5‡ôÚ×¾6ŸŠS‰(e¦ò(SË}æ3Ÿcêë{Hç  @€ @€ @€ @€LS`ê1¦(Ÿ›å”"TÍ!E\©D”b²ð¶¥±ö`žI5¦i^u» @€ @€ @€ @€è)©Ç˜ÆŠ+Eq¦Œ7Å´q­±¤x¶„œbᤓNš`t©º™SOÝC:C€ @€ @€ @€ @`šS1E®(&ËÄRuò¸Î³ÅE¶)w‰Gì~öÙg‹1MóÚ @€ @€ @€ @€@¿ L+Æ´÷Þ{׿•‹YäÚÎ4W²J1\dŠØSÙìàƒžl’I5¦~¿íôŸ @€ @€ @€ @€@U`Z1¦ˆ•ÚKiŠoK>©ZŸ©mJ©Ì=GcrS @€ @€ @€ @€˜ÏÓ1•4RÌWM5EY¦Îá¤K.¹¤D N:é¤I%™TcšÏ·¬± @€ @€ @€ @€ žÀtcL%™¤˜.§Š{ÉK^R%Å6TÊrMÕ‡ÓàÝOFD€ @€ @€ @€ @` Ó1E,)ê0•ôR.|æ3ŸiWª&™¢\Sn³Ï>[5¦)\<» @€ @€ @€ @€ ˆ1UI‘IŠKµLRÉ9ÅS9\ÔgŠŠMmK7M$ÏdR¹Á¸ùŒ‚ @€ @€ @€ @€@ Ì@Œ)‚Gez¸H&m¹å–µ(R[*ÄB>J)¦˜Šn"Ñ¥ê6bLn_ @€ @€ @€ @€ƒ$031¦vÚ©Ä’¢8Sk,)²JÕèRnkªÓÌM<Ì$Æ4H· ± @€ @€ @€ @€˜™ÓêÕ«#É”i¤Ï|æ31—\>b9¦–›xtI5&7+ @€ @€ @€ @€A˜™ÓÔÒHSÞK5¦A½‹ @€ @€ @€ @`~ ˆ1ÍÏënÔ @€ @€ @€ @€zH@Œ©‡.†® @€ @€ @€ @€˜ŸbLóóº5 @€ @€ @€ @€cê¡‹¡+ @€ @€ @€ @€æ§€Óü¼îFM€ @€ @€ @€ @ ‡Ęzèbè  @€ @€ @€ @€ù) Æ4?¯»Q @€ @€ @€ @€è!1¦ººB€ @€ @€ @€ @`~ ˆ1ÍÏënÔ @€ @€ @€ @€zH@Œ©‡.†® @€ @€ @€ @€˜Ÿ#1¦ 6ìµ×^‡ôÃãk_ûÚå—_>?/˜Q @€ @€ @€ @€<‘SŒ-’LwöÉc𮄠@€ @€ @€ @€˜·£bLóVÁÀ  @€ @€ @€ @€袀Sñš @€ @€ @€ @€†€“û€ @€ @€ @€ @€. ˆ1uù8= @€ @€ @€ @€bLî @€ @€ @€ @€º, ÆÔå àô @€ @€ @€ @€ˆ1¹ @€ @€ @€ @€è²€S—/€Ó @€ @€ @€ @€ Æä @€ @€ @€ @€ @ ËbL]¾NO€ @€ @€ @€ @€€“{€ @€ @€ @€ @€. ˆ1uù8= @€ @€ @€ @€bLî @€ @€ @€ @€º, ÆÔå àô @€ @€ @€ @€ˆ1¹ @€ @€ @€ @€è²€S—/€Ó @€ @€ @€ @€ Æä @€ @€ @€ @€ @ ËbL]¾NO€ @€ @€ @€ @€€“{€ @€ @€ @€ @€. ˆ1uù8= @€ @€ @€ @€bLî @€ @€ @€ @€º, ÆÔå àô @€ @€ @€ @€ˆ1¹ @€ @€ @€ @€è²€S—/€Ó @€ @€ @€ @€ Æä @€ @€ @€ @€ @ ËbL]¾NO€ @€ @€ @€ @€€“{€ @€ @€ @€ @€. ˆ1uù8= @€ @€ @€ @€bLî @€ @€ @€ @€º, ÆÔå àô @€ @€ @€ @€ˆ1¹ @€ @€ @€ @€è²€S—/€Ó @€ @€ @€ @€ Æä @€ @€ @€ @€ @ ËbL]¾NO€ @€ @€ @€ @€€“{€ @€ @€ @€ @€. ˆ1uù8= @€ @€ @€ @€bLî @€ @€ @€ @€º, ÆÔå àô @€ @€ @€ @€ˆ1¹ @€ @€ @€ @€è²€S—/€Ó @€ @€ @€ @€ Æä @€ @€ @€ @€ @ ËbL]¾NO€ @€ @€ @€ @€€“{€ @€ @€ @€ @€. ˆ1uù8= @€ @€ @€ @€bLî @€ @€ @€ @€º, ÆÔå àô @€ @€ @€ @€ˆ1¹ @€ @€ @€ @€è²€S—/€Ó @€ @€ @€ @€ Æä @€ @€ @€ @€ @ ËbL]¾NO€ @€ @€ @€ @€€“{€ @€ @€ @€ @€. ˆ1uù8= @€ @€ @€ @€bLî @€ @€ @€ @€º, ÆÔå àô @€ @€ @€ @€ˆ1¹ @€ @€ @€ @€è²€S—/€Ó @€ @€ @€ @€ Æä @€ @€ @€ @€ @ ËbL]¾NO€ @€ @€ @€ @€€“{€ @€ @€ @€ @€. ˆ1uù8= @€ @€ @€ @€bLî @€ @€ @€ @€º, ÆÔå àô @€ @€ @€ @€ˆ1¹ @€ @€ @€ @€è²€S—/€Ó @€ @€ @€ @€ Æä @€ @€ @€ @€ @ ËbL]¾NO€ @€ @€ @€ @€€“{€ @€ @€ @€ @€. ˆ1uù8= @€ @€ @€ @€bLî @€ @€ @€ @€º,0ÑÓ‚ V­ZÕåÎ:= @€ @€ @€ @€}.°ùæ›·Ž`B1¦È0m´ÑFbL}~è> @€ @€ @€ @€n ¬_¿>2Lo¼qk'Æ1-\¸p=öØtÓMŘºy › @€ @€ @€ @€@Ÿ l³Í6‹-šbŒ)Ç.ÆÔç÷€î @€ @€ @€ @€è 1¦ž¸ :A€ @€ @€ @€ @`> ˆ1Íç«oì @€ @€ @€ @€zB@Œ©'.ƒN @€ @€ @€ @€˜ÏÓŠ1m¾ùæ«V­šÏ|ÆN€ @€ @€ @€ @€Àô¦cšþé @€ @€ @€ @€m6âB€ @€ @€ @€ @€î ˆ1u×ßÙ  @€ @€ @€ @€x\ŒÉM@€ @€ @€ @€ @€@—Ęº|œž @€ @€ @€ @€1&÷ @€ @€ @€ @€]cêòpz @€ @€ @€ @€ĘÜ @€ @€ @€ @€tY@Œ©ËÀé  @€ @€ @€ @€cr @€ @€ @€ @€ Ðe1¦._§'@€ @€ @€ @€ @@ŒÉ=@€ @€ @€ @€ @€@—Ęº|œž @€ @€ @€ @€1&÷ @€ @€ @€ @€]cêòpz @€ @€ @€ @€ĘÜ @€ @€ @€ @€tY@Œ©ËÀé  @€ @€ @€ @€cr @€ @€ @€ @€ Ðe1¦._§'@€ @€ @€ @€ @@ŒÉ=@€ @€ @€ @€ @€@—Ęº|œž @€ @€ @€ @€1&÷ @€ @€ @€ @€]cêòpz @€ @€ @€ @€ĘÜ @€ @€ @€ @€tY@Œ©ËÀé  @€ @€ @€ @€cr @€ @€ @€ @€ Ðe1¦._§'@€ @€ @€ @€ @@ŒÉ=@€ @€ @€ @€ @€@—Ęº|œž @€ @€ @€ @€1&÷ @€ @€ @€ @€]cêòpz @€ @€ @€ @€ĘÜ @€ @€ @€ @€tY@Œ©ËÀé  @€ @€ @€ @€cr @€ @€ @€ @€ Ðe1¦._§'@€ @€ @€ @€ @@ŒÉ=@€ @€ @€ @€ @€@—Ęº|œž @€ @€ @€ @€1&÷ @€ @€ @€ @€]cêòpz @€ @€ @€ @€ĘÜ @€ @€ @€ @€tY@Œ©ËÀé  @€ @€ @€ @€cr @€ @€ @€ @€ Ðe1¦._§'@€ @€ @€ @€ @@ŒÉ=@€ @€ @€ @€ @€@—Ęº|œž @€ @€ @€ @€1&÷ @€ @€ @€ @€]cêòpz @€ @€ @€ @€ĘÜ @€ @€ @€ @€tY@Œ©ËÀé  @€ @€ @€ @€cr @€ @€ @€ @€ Ðe1¦._§'@€ @€ @€ @€ @@ŒÉ=@€ @€ @€ @€ @€@—Ęº|œž @€ @€ @€ @€1&÷ @€ @€ @€ 0ß?üð×t|üMóÑy›yõì_þå_nºé¦‡|æ™gÎ÷Ëø'# Æ4-Û @€ @€ @€ @€ƒ(qœÏé«K–žUÚ §œ•mñÉöÖ·¿kË·¿ëø“Ïj'y\³{âюɶ$۲﷣OXmQ´ÅÃíøeG5ÚéG·#Ž?ýˆã¢íðc‡ÚaÇœí;ÕöÝS¿Ýlß:z¨ºhii‡,ZÚhGòÍf;8Ú‘ÙN>øˆ“j¶›ma´Ã‡Ûa'ã°“¢ð¡öõïœôõmÿoµý¾µ$Ú¾Ñiúçñ¡þk‡,i¶öþæp;ø„¯6Úâ·¿g‡­·Þzocš-1¦Ù’u\ @€ @€ @€ @ _"Ɖ¥µülí–vÏýfûÁýî´àSÑî¾ï§Ñîºw¨Ý¹á‘lwD[ÿÈíö“Û×ýäûÍvÛÚFûÞÚïžF[Ól·þ Ú¢Ýrw£Ýí®hßí·ol¶îˆöP´ëoo´ëšíÚïÿ0ÛêÛíšhß{0ÚÕÑÖ<¸ªÑ¸êÖ¡¶ò–¢]yËývóýW4Ûå7E»ï²h76Ú¥Ñn¸ï’îvñõvQ´ë¢mXíÚ f[½aùêõÑ.¸¦ÑÎo´uç_½î…/yù>‡.9wÕºhç¬Z{ÎUvv´•kÏj´{>þé}Řúåþï‘~Š1õÈ…Ð  @€ @€ @€ @ kcŠ’K%·TÒK`úA3ºô±ŸŠvw 0ÝûÓ‘S%Ô¦Q¦fŒ)3Lk¦FŒit†éG Ó]C¦fŒ©™aªÆ˜Fg˜1¦’aj‰1­¼µ‘aŠ1 g˜®hd˜š1¦Q¦ÖÓ†ZŒ)3LµÓyˆ1í,ÆÔµÛ¹_O,ÆÔ¯WN¿  @€ @€ @€ @€™ˆÓñ'ŸÕ -5rK]i÷Ř¢Ó¨ L#¦GJ¦IÖaÊ0ÕJ1Ê0M¶S3Æ4ÙRLÃÕ˜š¥˜*Õ˜†2LÕjLW¯ËSL'׬Æ4ªS³Ó=ÑĘfêæœ?Çcš?×ÚH  @€ @€ @€ @€öÍÓ™C¹¥á’Keò¸XøèÇw‹64\3½Ô:‹\ 0•¹äjE˜&P‡©QŠiò¦‘åÚ–bjÖa]ŠéƨÃ4ÅRL1£\5ÆÔvF¹³®còZ›´€Ó¤Éì@€ @€ @€ @€ ˜@ĘŽ;éÌÌ-ÝY)¹TfŽËS%½ôÈíë‡æ«Î"WLe"¹æ,r#ÉÅtr7G»+Zc"¹R„©9—ܬd˜®¸y8ÃTŸQîÞKn¸7Š0e»èºh-ÅT‰1UJ1]µ¶”b:³czËÛ¶ jû¯_ýzÀîÙA1¦Ät( @€ @€ @€ @ /"Æt̉gÜe–ª­Yr)«.íøñÝ¢Et©:y\kù¥’^Š:L#¦ü(ÒK•Sû‰äêu˜¾ÿеßÿa¶Õ·5Ú5Ѿ÷`´«£­‰ LÙ¸êÖFk[‡©s†©Ä˜.jĘÚg˜bR¹ ®i´óm]–b*1¦±J1cúÙÏÕ—÷‡Nω€Óœ0;  @€ @€ @€ ÐÃÓ’3"®4Ü~ÒH,UBK;î¼[´Zá¥ÖÚKYä†Ë/•)ä:˜Æ*ÂtÝèÓd˜†bL×n¸0Ûê `+Ãtîªu/|ÉË¿vÈ ç\Õ¨Ætv³Sµ“Sßì½Û51¦Þ½6zF€ @€ @€ @€Ì@ƾ»dY¦”ªí¶uCs¢}dçÝ¢ å–Öþ8ª.ekä–²UÓKÃå—êSȵ›E®aºîö‡­¥S3Ã4\„©Z‡©Y„iFê0™aª–b®ÃtÞªucÚû›S#Ã44ÜÚ³VÞ¦lm'•Sinîç>=‹SŸ^8Ý&@€ @€ @€ @€fL bLGŸ°,RJ¥}/²J¥ÝóãìôÉhµÜR5ºT­½Ô¹üR³ÓCÙ®¿}¨e†©6‹\k¦á¹ä†L%Ãtå-\yËýWÞ|Ì"×h7Ýy£ÝwY´íÒh7ܳÈe»øúF˹ä¦aªÇ˜VF€©‘a:k8Ã$Æ4c·æ|:Ó|ºÚÆJ€ @€ @€ @€´ˆÓ¢ÅËFJ+UË,5—?¼Ó'£ÝZ)¹ÔÈ-Uª.U£K7GÕ¥lw>¡¥Òn¸c(Àtýp€©c¦^ó½Ö"L¬j[„©’aj˜š¦`ªd˜2À4Í Ó9«Öf5¦j¦j†IŒÉël bLS@³  @€ @€ @€ 0Pc:êøeÃ)¥GD©Ö"ôÃÇ>Y¥j»ùî5Ú]Ù†£KH/E¦áÓÇ©ÀÔn¹F¦[­^„éæ±Š0 ÕaÉ0]רô"Ûµ.̶zÃòÕë£]0ö\rQ‡)2L1—ÜPŒ©]&“Ê Ôkc#Æ4‡ØNE€ @€ @€ @€ô¤@ĘŽ<þôZJ©|Y¥È0EN,5rKCõ–ÚU]jNW™9®eò¸ë¾ß&½ÔœB®Q~)ÚÕÙÖ<¸ªÑF*0•Y䚦Ê,ræR„©ãDrækG2L`jd˜®i´ómÝùW¯;/Ûªu`*¦ˆ1½ ª1|Bë\r™aR©'oó^ïÔ„bLË—/_¸páš5kz}4úG€ @€ @€ @€˜¼@ĘŽ8îôjJ©V`éCÛ5ZÎW›*.çŒkæ–:E—¾~Èw/¿þY{é¼Ënþäg¿ú­£OèR3½ôÃs.½é“ŸýÊIç\YI/5L‘[ŠöÍ£NùàN»ïòé/ŸqÑcT`jÎ"WHî†û–^pýv;îöé½îô©½&=‘\%Ô¦s›E˜¢5&’kƘ¾Úˆ1 …–JzIŒiòwß¼ÛcQó±~ýúÚÈÇ1m¾ùæÛl³Í{ì±é¦›.]ºtÞÉ0 @€ @€ @€ 0èÓ±§eD©mJéCÝ5ZÛÄÒ w<íúJÉ¥‘9ãbò¸fnié¹+ŸýÜçsÊZ:÷²›ÿúoþöÃ;ÿç›ßú®wo³CÔ^:tÑÒxv‡vó–ïzÓ–ïÊ L`Šö¢—lòÆ-¶úàÇvßê};<ë9Ï;áŒË¯¸ùþl—ßÔ~¹KohÌ"÷ª|Ã;¶þÐß9éßÞò΋®oT`šH®Y„iÑÒKßÿáOŽaj;‘ÜÕõ"L ÓÊFkƘ·¦—Ęýµ2Ýñm¼ñÆ ,È$R-É4NŒ)*0Å>yþU«V•åéöÈþ @€ @€ @€ @€žˆÓaÇœ6\QiT]¥L)}ð£»FŠ+N, - ç–²êR¶ˆ.ýÃëþµc:ù‚(¼Ñ¥(¼”3ǽè%{ö%7ýýkÿõ {œé¥-xÖeò¸H/E†©1\s ¹Ï}å ø6LÇ/»ìðÅ眶üú˜?.Úq§_é¥ïα§_¦cN»ô½É§÷\¦ïžzi˜N:ÿÚC9ûÄó®½ðÚ »iáÛßýÁ3.½í‚1&’.´îœj¦•ks"¹ˆ1}EŒ©gnà~éHL¦ìm$™âQíùøÕ˜ÊÖq (ËÔ/ÃÖO @€ @€ @€ @€À"ÆôcN@ÒXíƒ;îúw½.RJÕöý¡bKÕÐRæ–ªíÝQõè³_‰ÄÒwO:?£KGÇB#´ÔX^tÒy]:êÄóJí¥ƒçyQ~)f‘{泟·×GÆDr±ðïïùзŽ=û¯þúe‘aÚ}…±}‰¯{ìDd˜^ù¯ß÷Ð%\³þüF[wþÕëÎnm'’‹"L™a:ëÊ{^ðb1¦ Þ\6k/1¤˜Z®úÜDcLQŠ)j:µNJGš @€ @€ @€ Ðïcj(Å”p9+ÜvüD´Z\©5±饨·tÍmF±¥l1a\LWÒKÃÑ¥ósÚ¸ 0}h§Ý߸åV‘[ŠSÄ’>ø±Oeí¥H/Å·GDŒixò¸Ëoºï²›…—^øâM.½ñ¾h ;ù/Þ$Ê/EŒéœ+n¿øú{#À´íŽ»]tݽ/øë—zìÙÑ"·å—"Õu˜b¹%ç®þÔ—¾ñÍïže¡†2Lc˜Î‰YäšÉ ˜VÞ“ÓÆ‰1õû=ßÝþG€©uR¸ ŘbÏÈ0E’©»pv @€ @€ @€ @€ÀlDŒéÛß=µCQ¥í?ò‰hµ2KµÄRæ–"±4ÔÖ<%—¢ÞÒ!‹–.:éüH,}á«•èRN׈1-9/L[½ïC¯ù§7lõÞEkä–š¦˜9.bL1s\¦—rò¸S—_¿óî{½së]rÃ}‘^ÊS¤—"¥_c ¹(¿´íG>å—"½SÈEkĘVGŒéO"Ã-¢KÑ2ƘJ¦±f‘kf˜î‰–&1¦Ù¸çÕ1c^¹Ö SŒcÊô“:Lóêv1X @€ @€ @€ 0¯"Ætèѧ6cIÕ6RT)cL¥ÆÒ¨¸Rä–š‰¥œ'n¸=õ–¢ÒR¶$½ë};\xÍ]oÜb«Ïå æœq¼ð%›,»è†e+nX¾êÎŒ.E™¥Ó.¼!L]Š“ÇÅÌq‘^ÊÚK_9ਨ½ôãÏÉ L‘[:åüë^ð×›Dz)bL]·!ÒKQ~iÛ2Ê/UcL‘^ŠS˜b ¹?¹ÇÁGŸù¾vÍYä:˜†f‘«f˜TcšW¯Ž™lÌ%¶Ç'Æ饨è=š… ÎlÏ @€ @€ @€ ÐuFŒiÑÒ‘BJÕ¢JÍ”ÒvþD´–¬R†–‰¥U·6BKµõ–í–F‹ÂKG.9/f‹;øÈ“#«tä ç.øÏ/G¦ˆ.}î+m¶ÅV‡/>÷ãÿ¹×«ÿé ¥ðR¤—Î[yG䟶ßñS]úô^ £ðÒ—82ÒK]ŠÉã¾uÜ9¯ú‡7Dí¥0EŒ)2L+®Ýå—Þ?c:䘳¢Ež)ÒKo{÷_ÿæwüÝ3ãëÛþã}æ_¾èe‡Ÿtqf˜ÎYµ6æšB®Ý,rbL]¿K 9#\Æâ±|ùòê Æ‰1ÅÖeO1¦¸  @€ @€ @€hˆSLýV©¥4NʈҚ¶ûð.ÑZƒJeM5±”¹¥(¶¡¥¡vóý»üç—KÉ¥ƒŽ89j2}ࣟ*U—>ûå7{Ë;?¾û^¥ðÒ¥7Ü-§ÛùS{½êß°ÝŽ»sÚ¥9sÜÙ—ßé¥h»ï¹0ÓK]ŠvÆ¥·í÷­%Q~食ÜcÙ%·E‹ÚKQéükÖí¸ëQé#»î‘˜>ò‰=>ò‰/ 0­\ÛœB®}&“ÊyíLS bLÕ$ÒäbLÓ<·Ý  @€ @€ @€ @€½/1¦ouJÛ”Ræ“¶ýð.ÑJi¥ *•6WŠÜÒÍC-'‰+­™XÊÖ˜-®Zr©mt)LZ*-ÒK]­1sÜPkæ–²En©´ V7&Ëùã"½t~sæ¸Úüqç—_ªÀ4áS†™^ðâ—åàŵMÕowþô¾oyÛV·­ýIµýìç¿êý›A»%0N5¦nuËy  @€ @€ @€ @€s&1¦ƒ @€ @€ @€ @€³)1¦¯礋®‹(R¶‘@R.¿÷6fJixJ¸¨®T/°4\l)RJµV -Ô['·´n"Ñ¥³VÞÓ!„4ý§Ä˜fó~œ§Çcš§Þ°  @€ @€ @€ @€"Ј1}ûÄ !µm[àãÑFMW›®]u¥’[jM,u-5ª.­Š¸Ri£f‹;'ê-e]ui¶£KÕð““—ÏŒ ˆ1Í8© @€ @€ @€ @€}&1¦ý¿}bÌòVmÕâIïÙþãÑZ+*u*åôpÃsÃLW›!®%´T¯·TË-U'Œ›Ëè’SŸÝÖýÖ]1¦~»búK€ @€ @€ @€Ì´@ĘöýÖ’¡šI«×7š ¤Ò2ÆT[Y¾Tž.²JmâJõ2KYo©^l©sKµyèTcšé{Ðñcr @€ @€ @€ @€ó] c:tÉpiÝùEÝÞ½ÝÎÑ2™TZ£ŠÒXmÔ”p¦‡‹ÄÒ¡¥µQi)[-BÔ ßŠ1Í÷×Ì,Œ_ŒiP’ @€ @€ @€è+ˆ1ísè’±¤Œ17f8iTPi¨ºRÔXjF”ªíì«Öµ•kcn¸lg µÞ -µ§Ä˜úêïΊ1õÇuÒK @€ @€ @€ @`ö"ÆôµC–Düh¬öÛííœvɤ1ƒJ™X;®Ô¨´te/VZšHµ'1¦Ù»çí‘Řæí¥7p @€ @€ @€ @`H bL{ó„‘RI¥fÒð»¶Ý9Zk!¥v)¥‘ÉàʬpýW+Ò$ÆäÅ3ãbL3Nê€ @€ @€ @€ @€@Ÿ üË¿üË‹^ô¢3åãÕ¯~Í&/eµ=ç¹Ï{Ö³Ÿ[[Ù•oÿèÊyk'ý½ßûÿþê/îГçýÙó·~ÿ‡n[û“jûÙÏÕgw†îΡ€Ób; @€ @€ @€ Г6lX^yœwþGŸ°¬Ö?æäÖ•s½fÉÉß¾ø%s}ÒŠèÀD4n¼ý~1¦ž¼ß{´SbL=zat‹ @€ @€ @€è–Àýê×µüM|{Áš/²j£Ë¾Lôg²ÝP©[·t_œWŒ©/.“N @€ @€ @€ @€s'Л1¦5÷ÜÄ51¦ï^÷‚Éæ‡zd{1¦¹»‰ûðLbL}xÑt™ @€ @€ @€˜MÞŒ1e)¦l}ZIŒi6oÛ¾?¶Sß_B @€ @€ @€ @€fV cL¥SƘú´ “ÓÌÞ¨v41¦» †C€ @€ @€ @€LWàÿýú×ëxtí?ëÐnºóGwß;Î60©g/¾ý«¥S.¬ºûøIaV7þÁý^ÇÃãž"òaÓ½6ö\1¦Á½¶FF€ @€ @€ @€ „À¯þßc‹®{F-Æ´äæ Äà ‚À€“[ @€ @€ @€ ÐÓ×ß»_-ÔßÞùðÉ=Ýo#01¦ÉhÙ– @€ @€ @€ 0·mK1eŒIA¦¹½Î6»bL³ëëè @€ @€ @€ @€é<üØ-«Ö}6ÛÙßS¤—–ßùž²æÑ_n˜ÎÁíK wĘzçZè  @€ @€ @€ @ “À­1¦u?YމÀà ˆ1 Þ55" @€ @€ @€ @`0ĘóºUS@ŒÉ@€ @€ @€ @€è1¦þ¸Nz9%1¦)±Ù‰ @€ @€ @€ 0çbLsNî„s' Æ4wÖÎD€ @€ @€ @€˜Ž€ÓtôìÛãbL=~t @€ @€ @€ 0$ ÆäV`1¦¾¸†F€ @€ @€ @€ ”€Ó@]Nƒ- ÆäŽ @€ @€ @€ @€ô‡€S\'½œ’€Ó”ØìD€ @€ @€ @€˜s1¦9'w¹cš;kg"@€ @€ @€ @€LGà?:óU­Þ°×tb_½) ÆÔ›×E¯ @€ @€ @€ @€uŸüâΈ1­Z÷Y4O@Œi𮩠@€ @€ @€ @€ƒ)ð‹_=¼jýçÖÿdù`Ϩ淀Óü¾þFO€ @€ @€ @€ @ Ęzà"è @€ @€ @€ @ E`óã6§B`þˆ1ÍŸkm¤ @€ @€ @€ @€@߬Z¿JŒ©o®–ŽÎ„€ÓL(: @€ @€ @€ @`æÖ<¸fÓÃ6¶èºEfÚfé6±+7>`ã<É• ÷¸hXˆg£å–3w~G"Ð1¦. ;% @€ @€ @€ @ ³@„“¢ SlÑ¥Œ(Å·Wʽ"Ø´üÎåñ5òLñí#¿x¤<–@Ÿ ˆ1õé…Óm @€ @€ @€ @`²ðR5ºT*0Åú-­d}l5™²‰1 òÝ0?Æ&Æ4?®³Q @€ @€ @€ @€ý#¥Œ%U£KQŸ)*0ÅÊ 0eÂ)¾F‹õKo]Ú?ãÓSmĘÜ @€ @€ @€ @€Þ(E˜rò¸ì\†–baÁ9 "Ò fŠ…Ø, 2õÖô†À$Ę& fs @€ @€ @€ @€À, d5¦E×-Š|R9U|é¥hQx)ª4ÅúXÈ52L³|A~.ĘæBÙ9 @€ @€ @€ @€è Æäö @€ @€ @€ @€ @ ËbL]¾NO€ @€ @€ @€ @€€“{€ @€ @€ @€ Ðþ׆ÓÖ¼f̓‡÷Gwõ’ÀdĘ&£e[ @€ @€ @€ @€@÷~ò‹;YµÑªuŸí^œ™Àl ˆ1Í–¬ã @€ @€ @€ @€fV@Œif=­§æWŒécûØF&/°zõêžzݶíÌÃ?ü‚ýÍ™gžÙû]ÕCs&pçwþùÿù«¾x Ï™‰ @€ @€ @€ôµÀ}ÞõW/ú›ƒÙ¾¯G¡óÚ Ì¯ÓÖ[o½ß7Y÷àÏFµ~¶v¨=ºï7yÛ¿¿kíÞsÿHûÁý6Ú}Ñ~íîÒîýé]•vç½?½sÃ#Ùîȶ¾Ñnj?¹}ÝO¾_i·­ûÉmk‡Ú÷Öþ¸Ñîi´5¥ýàÇ·µÝúƒÝr÷H»ùî5Ú]vÓ]µ;¾±Òn¸ãáîx(ÛõÑnj×ÝþÐPûþ¯­´Õ·ý°´kn{ðšï µ«¿÷`£­i´UCí«ni+o}`å-CíÊ[¸ò–ûíæû¯¨´Ëoº¿Ùî‹vY´‡Ú¥7Þ×h74Ú%7Ü;Ô®¿÷âJ»èº{/ºnC´¥]»áÂJ[¾z}i¬^Á5CíükÖ7ÚÕë¢WÚªu玴µ‹N½üÿèYç\µ6ÚÙÙV®=k¨ÝsÖÊ{μòž¼øåË—/ïñwÈ0ýÍ&›uÂÙÿÚ7H2õøÅÒ½9ˆ ÓßlòŠãN½0¾J2Í» @€ @€ @€ÌžÀÈGÃÿä£áÙcvä® Ì»S•"¥Tk÷ ç–ö=à·þû»2Ã4fz)bLõÓPzi$ÃÔ 0uÊ0 ˜"É4¦áÓÄ2L?ìœaZµ¦CŒ©C†©cjd˜†cLC¦fŒi$ÃtÃè Óõ‘acºvÊjŒiõ†Ž1¦F†©cªd˜Ö³j$ÆT2LÃ1¦F†©_bLñƒê¥›lºø´ #ˆvÅ ë^ãÇU×ÞQ¸‡"ï‹3.\¯‹«nÉË$™zèêè  @€ @€ @€À|4<4»ô—Àü‹1pHµÒÒH\©™[ÚçëS½êR–_]Š:LwÞÛ’^®À4Á"L·UŠ0µ«ÃÔ(ÂÔ¦S³ÓÍ¥S,t®Ã4Í S³Óp¦X?Ã4“¥˜1¦Ù*Å4~ŒéÊ>¨ÆÔøAõ·‘aZµµ"®´Ë¯—dê¯÷a½yF†éo7=sŵåu±ü*I¦™wvD @€ @€ @€9ðÑðœQ;Qæ]ŒiŸ¯³}J©™UúÚ׿1¦¶¡¥œ?®L7jò¸úüq1‘\} ¹˜N®L!W«À4͉äÆÉ0Mn.¹–:Lsœašt)¦‘éä¢&S™N.š3ÊSŠ)&’ËIå:”bêñIå†~P¾"êl•¸FdÎ.½ní«ÿQ Á.¾µ:u72ÃtÖE×–×EÌŒ¯‹ V~_M¦n^ç&@€ @€ @€˜ª@ëGÃù˜†§*j¿˜w1¦*e ©m‹g·|û»š•–êÅ–Úæ–*U—ÚG—¦–^jSéî¬Àô£›J¦;§[„)S/¥]sÛƒÓŸKnZu˜&ašÖtr‘aj1µrm³ M'¦Œ1ºìœþøç¥ýìç¿ê…tþ :áô×ßþÐuߊ1åϪ«n}à’k#ÉôúÓ—Ñ ]Õs&¦³/º¶ùºh–(»í‡åuqþÊï¿øe¯Xuõ5sÖ'"@€ @€ @€ 0M OÐî}$0ïbL{ïÿÍZE¥ê·ñì–oßꎨ®TÚúG"«TÚíë#®”í'Yr)Zd•ªí¶Ñ…—†fŽ‹ùãîjkîùñPûÁojmæ»%¢KÃé¥Z€éÆIÏ"×ø8?rK¥0_„iÕ­#sÉ­¼õF»¥Ñ®l´ûíæF»¢´›î¿|¨ÝwùM÷]íÆ¡vé÷5Ú vÉ ÷–vñõ÷–vQc.¹ÑÓÉ]»aŵ.,mõä2Lç­ZwîHk˜ê1¦•kÏ®d˜Îj˜JŒéè–U‹iÅ=Óõyþ Z²ì¢š“–RL͸FãbÅE¹hõ=¯úÇןrê²Iõvýúõ›o¾ùÆÍG,¬Y³&v_µjU®É•ñˆ•e³òÔÃ<ãòåË7ÝtÓ|v›m¶É•±I¬,]Š#çѪ,çÍ•±}ŽO—ª O|DñYU~œŸÅAâcßÖÝ—.]š+ãS¶üÌ7¶ŒÏ£'~"[ÎCycúê~߬ƒjËñìoߪ’UWjM,ez©pÉåïEh©’[ªM·¦cz©]#½TŸ?î·o¸#ÚCÙâcûˆ³d‹7¯¡öýñLÃE˜"þ2ÔÖ<ØüÈ?Û™‰)­˜š¦v¦›[Læ¡S3Ã4V€)’LÈ0žK®2\Û¹äÆÊ0E’騜Tnì SVcêµS-ÃTûY+ã‘*[qÍ&›dŠŸ4 .ÌwÃø¹߯’Œ1•·ÈøT²Gµ§JÀ"2L±K|ͽ,Xé¥ü‘ßæúØ=×Ç1ËÊü1–+3®9Ø+3UÚ ” SfûZK”å»V¼.νâ{=¥$SføÊ dF.DÜám«ëpðx9´M>u(¯£¹RB€ @€ @€˜{ ç,=Óüh¸$â#°òð¸ÃŒsó®üy¬qó€ñqsl–oMê,ãvÃ)0cLg ¥j+µ”¾²ßÁ[¼m«Zu¥òmk\©¹¦™X+´”…—ZsK?øQ[ª¶Ñ饇;Mך^j`U~©e ¹ö˜&`É0T`ŠRL3^„éºÑE˜®³Ó׬o›aªaZwΪ‘:Lg_µ6Z‰1•¹äªu˜z³Sü zÙßnzⲋ¢(Wf×ZgÎjÄ5šy²¨ƒµüê¼ò&Z“)~l”²Iù–Ñ¢xÔ²J%{ŒcŠŸI‘Fª¾oƳH5EÒ"#M™p*‡ª¥C2)RýW~ä{±AMS 2Lñº8ûâë"ÜY/Å4\¢läuqã}g_>é$Sü‚7a~-½_ì2Û”¿áeb=¥ZR,äšüM.^_ùËY–‹GüÒ¬ýn—IÁüÅ®Z±,ÖÇ·q„|”Íj‡*'-½*ö:šæfw @€ @€ @€Àœ Ô>UÞ¢ñX3Æ4s —hóƒªR„"ÿÍ|ùô*‹0å'\cŠ5ùiWõ³³œç$?ð*Ÿ…å|>sèDý(0ïbLTj™ôm¤œÒWö=ø-oÛª]\i8«4:®4ªÌÒpb©ZŠ9ã†g‹'·ô£›ïê]ŠÀJ³ðÒèÚKSK/ —_º¦”_Š…‘òKÍ L•òK™ßÌ)äj³ÈM.À4E˜:O$·þü«×E;¯Ò:g˜¢ÓQKÕ˜J†©L$W]è©jLC?¨Îhd˜†JÎTg”«ÌœW§cj²_pÕÝL2ÅÏŒZ¥™ŒeV)¾æ#~•´ÓX1¦ÖâIeʹX(?ŸJŒ)~te!ÁøqXj8•wÕÚTtýøn«Ï³'¦s.¾näuñý¡™›Ó,ŽÊ¡7¦¹l¾.μtÍ_ÿÍ$f—‹;3_%„—·qÖFÊ„S¾LòwµøÍ,îÛ|¥T#P¹&~‡+õÉjÕ˜J¤¯l“¿–£årt&wŒnä1³S¾”âÛèU-2ïu4{7¡# @€ @€ @€fV ÍGÃÃ5>량†Ë¿Ì¯ö¼ü«ø2N|–,Ê µjLùmëggµÏªòc¬Rÿif¹m`æ]ŒéËû4T<©]¥xö-oÝ*ÂIÕÖ(§ÔÚ~P­±q¥‘ÄRD—j•–òÛÚlq£rK‘aº³Ñâ3øj›ht©Y'ê-UÛêÛ~XÚ5·ýðš1ÒKµS}þ¸Q¦ærÑ¢êR¥EVf¸Ý×È O!× ”6z¹K®¿7&+müYä&_„©>‘\K¦œHîÈFŒé™g­¼§µSI2õNŒ©þƒêŽÆÔYg+CiÕ¼m3ÆÔ¸1_PŸ·ò®Wþý¿œrê²Îo^ñc£VB©Ä˜6Úh£ŒeÒ¨§CŒ©6­i5Æ»—:OÕ¼m-“Õ•e޹yç5h“ajÉöÕrèåuqÆ%k^4á$SþRUñ•)s8Õ*e¹&v) ¤üõ.Ö”°y&ŸZg‚‹-Ë‹%guŒCÅB™Ø1ŸÍ9³XZž.•iª8o-èu4ƒwC @€ @€ @€fU`œò3ôÑpkŒ)>`ªfòó©ò)UνkÚÆ˜jŸÅfµSë‡Ñ³jèà}*0ïbL{í{PûXRsê·½öiĘbatE¥zJ)k,Ý2F\©]bit±¥1BK:"£'Œk”ÛÉvûP‹ØÊHë]jD[¦”^êP~iú¦jz)–'`Z¾z}LWZÛYäF˜ÚL$טNnåÚf¦¡SÛ"L½cj›aÊé䢵+93TŠ)cL]·áœ+ïÚt¼$Süh©F”â}-¾Íy¬Ê§Ú›ÝX1¦Ö mþXªþôŠ5QQ¦Ô¤©¹üäËoµr5}ú†«Û3.¦—Öê0• Sç×EóýgÅuN¿xBI¦ ×ÒE‰1Å+¨ìUûµ/#McLñlÎÜcŠ•¹{‰ý•CE’)§®+)(¯£¿÷ @€ @€ 0KÕ¹ä230RÞb6?ÎùFÊ´<ùUù Y“"¦cŠ}k©¦YÒsØ~˜1¦}*½µ.ì¹ÏA›¿õmk)ÕV•VÊKwU[en¸œ'®Yf©µÒRV]ªÕ[jÍ-E€©’[§êR&Zª…—:Í·æjí¥O/ÅœM )m ¦ W¯ÜRiT2LÍÓ$f‘;'¢KÙšE˜Ê,rGžÒ¨ÆÔû1¦øAY%ˆç’kþ Ê\C¥˜š5KÉ™Z)¦‹®kÄ5.¼vÃÙWÞÙ9É”u\J—Œ(ÅÊ)Ęr>¬R©T‚©&?âD9mj¼“–‰´b¹LÑÕïï°ú?«™a:»:—Üp†)³}YKs¬RL‘í[qmãuqÚE·¾p¼šLqV •e¥ê¯q±Au*ßLÆfe–Æœ¸dÌóµ>YW© U~í+³ÂµT®ºcõPÑF¬ÆgõZ88 @€ @€ @€ÀŒLû£á¡À&øÑp)'Qæ)å-bMÊšÎ1¦ÖÏÎb÷üû&.0ïbL{|í Q ¤2×[s!žSK2©cJ)³JcXŠ+µK,ZjäTÚä–2¹ÒaθZt©6mܪ[G¥—VÆ´q£fŽ{ ÌW«½tEëäq™?®Y ¨íüq A¶k‡ÞI#O­š^jWiL1‘\¤—Žè‡SùAÕ ½5êrÕ3LÕš·4¦ü‹iþ“ú5“dYŠ)U# væw¾â5f—ˉ±Ê#Sˆ1Å^ñƒ*SJñˆQ9—V­€Mä-ò‡_< ¹q™]5ßËTcšø{úüÙ²d˜ª¯‹òöXæÊ0 ½.î+¯‹,Å4ôº¸fýÒ·¼ð%/¿òª«Ç¬U#+‰¥åM›±ôüõ.ïä½'ç¾ÛãǘÊ[›jjîû:ý3n½õÖ{|íÀ¡ÔQ‰UâÙ7oùΑ † )u(§”)¥ÎY¥‘¸Rez¸œ'nô$qíCKcä–~ŸÓ—Ö¨;RÚš߼廞ýœç½è%û…½Žb$]zÍkÿõYÏy^|Í L]zÍ?5×üÓ¿®¼e8ºtËý]:舓_øâMâÙh›m±Udb¢}ࣟŠvYD—šé¥Øà[èÒÈÊd]{)Ó3c˜†ÒK­¦Õ£LÕòK1‘\û)ä®^wvΪµQx©´¶˜2À”mš1¦_üêáu?Y>ý;³Ã*?¨†¦Ì‚ÑþcÏó^ó±S¢½i÷3·Úã¼S/»;"hqù¶ÝgÅ«?zÊ;¿xîwÏ»­™a×8ÿêuË.»ãï:&™²?¥Ò48Ùãä1ù(ð௙Рj(ÃtÑuCï®Í÷ÒòVù™ÃWÆ‹â5—Æûpý¯‹¡ôd%Ï»zÝÉËÇI2ÍÈ™xy$Éôw @€ @€ @€@—}øñÕ'O¤c}4%Nª 7>[2öG`•É?Á†'ûyîDÆb¢jCæçªSâä.ãǘ"=—eÄrľ¶ŽÓ—ö>°<ª-dzcª­¼a¤RÎ÷PÛRŽ´fD©´QY¥áR:9#Xk«UZž'nì©âš'UK.}h§Ýß´åV‘UZqÍ]/zÉ&g^|c|»Ë§¿Ñ¥øúÆ-¶ŠÜR|åøt?×T /E†)ÒKqr¦—¶zï‡"±Ñ¥í?ú©hZ&7Þ÷‚oË3–^j-¿4Æüqñ>iƒ¡VI/E’©`J/µL!W 0M3ƦUë>{øêß»ð®­gïE‘?¨N8}EãÖºsF²ÔX²âŽ Ûîyô5[}鼏޻çÊm÷¹0.Ó1çݶÙngÔJ1E,ô‚ëôKoÿ»WwªÉ4{ƒrdc D†i»ßç5ÃLæk+¯‹¡ ã 32LïÚã¼Kn¸/^ñ¶ðÆÝÏ8â¬5»»ñºˆ·¬ÈöÅë¢VŠéükï*ñº8é‚›_б&Óô¯ÝÄcLÓ?—# @€ @€ @€t_ þ%|öÅu3ûÑp| – yÎ÷¢ªÅÒKî*åGã>[ݨâ£áî_}=h'SßDY‡xÄB-H7~Œ©TF‰jL1aM_#7bL_]8V)ÖdzoÚò¹Á¨XR~;:œ4NP©1%ܳµ+µÖXª$–&ZŠ·ªF½¥5#SÅ}âÓ_ŽS–\ŠÓQK΋XR³äR£êR,}m^Škr!sK¯þ§7|öË^žU—† /-<üäŒ1e†é3{õ–FZká¥f ˜Ëld渉LWI/M°üÒ¹Q~©RiÌÓpù¥R‡iÊ1¦[î¹ç¼5»E€éUE›½Sþ Z|ÚŠj€)o›k¢}ïÁˆ1°âŽ¼Ð‹—ßþÆOñä‹ïÌi³"òõªOiøÏÓ× m†ÀB, N½äû/õ?Ÿrê²¾~Qëü@ dŒ)Ûa¦Ì0µâÚÖ`_ΧE˜â&Ï×E¼×yÖšS.¹«ýë¢Yþ­üUÜâu±äü›^ðâN³ËM\±±iÚ @€ @€ ÐgcÊ6F˜©óGÃñX|4üéÃVæG`ª%Ÿ:㸠¾?îGÃY ÄGÃ}vÃ̃îFz©D—Ê´ƒeÜãǘbÓ8DÎYØï\cúâW¶M#eÁ¤/DŒi‹w¶)žTýíû#ù¤¥]j[]i¬Kù1|m†¸j¥¥ZŠyârz¸ÒoXÍ÷¬Ò>ò”¾d“ZÊ’KZŠ.5sK±Ü 0Ý—Ñ¥øö¸Ó/‹(L^ŠÖ0íØhïØúC‘aŠ–¦ÓÆÍFzé¼±Ë/eþ ÑV6ÚYvO¶Zni:1¦0sënß¹úw3À4«1¦øAõ7›42L×5ï·¼†n›¼CÖ4~Ví|à¥ÿyØÊÿüÎÊøAuð©7ÅuÌ«öÅ#¯Ž¼íW»6æï»°Yìª *9Óàj-½X’©ßßÕ«ÿÕS»0Sd˜âuqæŠkÇz]D°/bL%Ôozw¶Úë¢%Û×ø._WÞ³ä¼ÙM2 Ö53 @€ @€ @€ŽÕS»0ÓÄ>>#>^|áíQÞâ›§Þ՘μò“øhøJ »K{N j2m¾ùæFªõlB1¦Ø'æ•‹£ SÏl2ŠÓ¾²p¬ÚH±>ž}ãïè°ÁDÂI%·Ô(™ÓhF8©µµ+µO,U*-uÎ-e½¥lqrLwÄ çVë-]1ZjF—FrKZÊOºüúœ0.ZÄ•¶Ûq·lÏ|Îó>½çÂWýãb93LQ˜®Ñ&PxéÂfá“j»`bµ—&™^0Q~iŠ1¦·˜2ÆtâÍ/ŠÙåf¶-¿e׿ÙäÇŸva5½Ô(Â4`Ê4[NzzüòïG½™íöYI¦üA—,&›‹ Ó¿í¶lé¥w¥ùHÉ™fÞ¶¼†’L{/xüÔÏjº,pø{F¢è%“>\™©™azÅ®•êýº8aÅíñK[³øÜýµ Sëë"Þ‚j¥˜Êëb(Étð.]ñªìG ~ü—MæwÛ @€ Ð ¬ö| @€˜#ã?Úþ#°fe¦f†iB ǧ`oÜýŒøPx«/{ÐÒ›&ôÑp³Hý£aÓõtãC³U *åìrK—.­>;~Œ©Ì€I¦~/È1¦Ïea‡òHñìßòŽñê' ‡“ÆÈ'eb©žRj–Ï)­C©¶Æ¬pÕ‰áÚÄ•FWZúœ~8´ØçgöÙ>÷•ƒ2ÔóÄUë-År–\ªæ–²êRF—¢ØÒ—8²:gÜ þz“H/Et)ª1Etéäó¯{泟÷õïœÔvθœÂ¬´ D—U‚b²³œïl¤M®öÒDË/M!ÆôÒM_úí‹^^­ÀT]>ôê‘ÊLcm3Ùõÿ¶ÝF[¾ã½#%»Ê5tÏ •àŠSd˜†³÷ÇO¬cοmÙåw_2”-Û1¦£ÎþÞP)¦¦mµäL¡8ôøåÿç÷ŸôÃ÷?¥ýÏjšÄ2n ,xÆÖoù—òžó*Ö‚}Y„)~‹ ÓðD™÷xÊMŸúö•ñºÈØeÔ'«½.âEј›²ñ ÜÚêûÃ'¿tà¿müÔŸoÿ$¯ “ˆºb @€ô¸Àgþ÷¤ÕïÖÿ;/ @€,ð±ßûì¶[lÿ‘Otþh8>‹†ÿó;WÖþù,>¸o÷Ñpã#°œ¤| ¶ßw–¾èÅ/}ôç¿êñÿiÓ½ˆ SŽqæc1¦˜Ž®D—.\ú+bLŸûò7ÚÖFÊ•ñlĘj´ $µ›÷mìˆRÆ•†‚J­“ÁÕg…kW©±”%Fj¡¥’^ÊÐÒW¦ ®º£Ô[zõ?½á+ß8*rK ?ùÕÿø†ˆ+Å×X¡¥…‡5ÖTCK‘aŠÜÒ)ç_—õ–"À߯ÇÿÛ~d·h]Ú}Ï…õ×/‹@@„–j¹¥F€itÕ¥FŒ¦Má¥õ]ª¥—š‘‚ÒÖÆTñÞZZËÌq“«½Ô:Áܧ\þ‡ôÌÎϽàÅ/?ú„e+ïX¶øúW¶’θí_ÖýdùŒ·Ï~ö³ñãjäÞ`šñt÷ÆŒ§9!`˜"½?¨Þÿµ ¿päÕIý®ÝðªO9þ‚ÛëÓÉUò¶1ðØä导ðœóo»lù£7^øx|ú®è–Àùûµù#ò‚g<~Þ~QÞ&o~ó›~ûø¡×E3šï®ù.šáÎ^ÅÉòu±üšõ›}ꌽ¿¶ý뢖í«ÌAùÅý½ö_þíÆË/‹×ÅÏoò¢ 0a“>Ù¸‡Å˜úú—E'@€˜'»=÷ñøwÏÝúÿ_ç%@€ @`^ \ul›À>ö{ZP>ÿ–1†q?Þý;WæG`¥Óø G†©ò؋Ί†¯¾ùžÛÖþD’ižüïoosÑ¢Ee.¹Xˆ0Ò$bL±iL$I¦|”ÊL½9Ôq{ÕxýïõjU¤Úr<»Ù[ÞÑR*©V9©|;œLʈRósôέ‘>ÉvK½U烚nì¸Rä–2±4ÜÓÃ5Þ°š-2LQl©´ÃŸsÜé—E¥l±¡¥cO¿´¬‰åL,•Ñ¥¨·é¥h¯ú‡×÷ÔK#³íG>­D—þuówF«êÒ¤¢Kµiã²2J=ºÔ Š6²¢CížxíæF;G‘Æzvâ1¦x+Öfºð®­Ç½ñ¦¶A$™¶ûð'Jn(¨1œÕˆ([T ŒèR¶ÌjD¦Ó/»{³Ý–EØ6ÚG¾~q3ô~¨ÓèéäF2L—ߘ£óãjjWÊ^3&¿°VÓôærüL2ðíãG¥—†ßQK¦m›s,F‹—Ænߺ"ÞÙNkóº¨Ô'íÊ0Ý~y]üü—é3v‘ü@—.Æ4à—Øð @€F bLû¼f`Fc  @€ô´ÀƒwŽú¬`*ÝŽ$Ãg÷úFç†wÿvĘF2Lc|6üÑðèéäâ£áj†ÉGÃ=}ÃÌÎE¥Œ!µVSR¹$вL`•/þI£xöß6ÿ÷qÓHíg|#Ÿ”‰¥fJitQ¥Žu•j–jq¥’X*ÃåÂÈÜpÃ3ÄE½¥Riié×år‰+•’K9ÝÒE×ekÔ[ŠvÒù×6BKc–\ÚÐy¸ Ð4Z»ªKm¢Kã§—šÑ¥™H/•TÓdcLù†~õ]gœ¶æ5Y™iöbLñŠ‹$Ó¶Þ%§Ê¾‘†f¬&mó*_ÄF¦¥—Þ•I²’aÊpXµfàP¦J†É«x—ëï!”SK€©Œk(Éô­ãK$´ä>‡óCo†']tgû×E›lßÈtr­¦|]H2õ÷­5g½cš3j'"@€ 0M1¦iÚ @€‰ ”S»S9L 3äGÃc}6æGã?‹†õA†§“kÍ0ùhxâЖs,0ÑÓwk–N¯üÏìùÖJHeM<1¦”§ÚÇ’"™”m¸ÒX³¿•”RK]¥F¸Ò²ºR£5SJ¥µ+UKÕIâj•–òÛÖÐÒPbi8´Ônª¸zniÌ’K× ÍW›0®G¢KÕÊLS‹1ݹ¡1McL$a¦Y1ÅY"ÉôþvÉ›*o›Ì´å]wB‰¦e-/\É0Å%hNÒ7œa®8V†©õÇÕ÷–-ºæ;{üòÑ¡™)ËkóÑÖßµbé,½Tvž DŒiìS1É$Óþ‡×òºz·¬½.2‹9ôºhù®ší+ÃTM2­[µ<^ñµv¼"æéM[¶“û€ @€@¿ˆ1õË•ÒO @€ 1¦Ž¦2ÄÈ3|zÏ&øXëGÃ9EOëGÃce˜$™àæÈ!Ì»ÓÐ˾äFGŽ>½Çcª…Ê·ÕìÑ„–GÍûVŸ®: \kP©Mi¥È¬Ü0Ôª)¥‘åÑÕôR#±4Tii¨ÌRã­´kð· -5£0mê-EŸkFÚP½¥‰æ–Ö3ºäR£>Pi³0gܸ3ÍM'Æ”ïþrCÛ·†MÛtý#3SÃ,“L#•f†LCÁµÌ¥5/hÎñ×È0 ×ÁšN.ë0M,ÃTýqõÀÍ«–n³i$™ZÇIŽhù¶hP]ˆÙùØDÎ^’LÕ LCo›ÃÅÉF½.V¼.Æú®s†©$™ŽÛ|ãxEüèî5µ~zELä þ6bLƒ @`PĘåJ @€>ˆÏ¿âS°‰=I¦=ë£á¡’%>®—·èœa’dšØe±Õœ Ì¿Só5?V‹w„Ýü߯¸éþhÃó¸»0R<©M¥vµ”ÚOW™n¬ºJµ)áje–*q¥‘‰áF%–:TZjZj-¶42OÜ„sK°gÇÙâšñšFÂfÆ'Œ7ÃL?ÆÔöõºjýªØx̓ C|/y¦òЍ­÷Š˜½{ ,ÆÔ‹WEŸ @€´cr_ @€ ЫïØê?vßãëí?«–·hóÏø×5ʈTÊ[L$Ô ÷*†~ÍGycúÏxÁ—™ÚZâíà_ßüïõ FOèV›ß­Ó\o™L*m¸–Rç”R‰§´ nh>¸¡êJS‰+5 ö´”YʪKŒ®´4~héêu-óÄ5‹Ô•[j¾iç–º]š©Iå:¼a,8gATcZ¸ráò;—o~ÜæÑö¸hRŸ)rK±»o³t›hÕ§:3’Lïûà‚¡â[£Le¬öY)e˜¢'1mVž‰S,¬øÂ6Ñ¢ÞLd5r.¹x*¾Æš\߯féˆ reì8ßSy2É´ÏÁǶ}]”âdï‹uÓÌ0=ò£½`óh7¿0 2Õnõ|EÄ« ×ç×X Œ…9´qª. ˆ1u Þi  @€LZ@ŒiÒdv @€ @`îI¦/}}b þ¬òѰ ÓÜ]0gšQycŠWû¨hÑè¤Q<û†7ÿ{û *!¤2¹[.´Ÿâ-Šå´¶1æ}«&–†Š*µ *ÕK+u¬®ÔŒ+µ™n¬ÄÒTCKç‰ë½ÜR­DÓ,UcŠdR´x©Fž)‚JùšúL¹ñ¦x6N¹fÑu‹rûÎH2½÷ƒ †¢l9-`s¹¼Ð™B;?²ecLz:ñ:L¥™ÌˆjL‘ÛÈ•9sVÔ›ÉLF|ͧ"½-ñ5·Úïzz~2ÉôµƒéðºhÌ}9üºÈe5„>‘¹ä¢ÓÏÙ¡—;¼¼"râÅòŠÈ _lkb›êLs±^•²¸ä=~1¦¿@ºG€ @ ˆ1¹ @€èmH2}ê‹_ŸòGÃ2L½}yõ®“À¼‹1}ª„ÛÅŒâÙ7¼éíãÄ’®šÌk¬jIãTQÉ'ª¥¥6)¥JPi(°’±•j[=fu¥¶–*q¥õçWæ†ËùGµUQZ©Þ!€ÑÅ–™€ÒšÅ–zªÞRç©åf)ÆÅ–¢äR¼òb!ç+˜b9ÒK‘aŠxS<›µšba"1¦Ø·‘dúÀÇGLó]Ö±³SÈ0•dFœ7‹ÐD˪KYŸ)ÖGù¥X™%šbûx¶º¥w_s I¦½:¦ì+ÅÉF2LWM+ÃcÉÄR,Du¥¼Õ³ØRyEÄSñÒˆB–bŠ…Ø l)Æ4÷C—O!ÆÔå àô @€&, Æ4a* @€ Ð-H2íö…ýÇÿ¬åŸñË0uë’9ïŒÌ¿S3±8V‹<ãëßôöÖgG*$E©´ë"‡TmRkk¼­´m×6Jé”V'Õ³JI߯j­“ÁE¨eq¥ösõ™.K}Zj4ÍRŒ©^* ¥>S¼ncåúGÖG hé­ÙÙâõ™&þzŽ$ÓÖøx)µU 0e¦¡ËT™ôt ¦èOIfä,ZÙÃŒqDD#Ödž)·Œ¸FÎ(—›Å69÷œ9È$ÓW<¦íë"ã˜Cï]•׍ê0•û?âæÏ_¸HºH€ @ ) ÆäF @€ @ O"É´ëç÷ç£ááÀd˜úäªêf'ycjd[çe^ÏþËß>Na¤±vï8¹[§BJcG”FWTªÏ×f¸œ®ÝdpÃÓõ™nT¥J\©MbiåH`"!¡Þßf–bLQ])Ú#¿x$&+¯¿,Èu˜Jí¥H2ÅšI•b*G‹$Ó»·ß9“j¥ØLãR6L%«1µ:Ly–H)•B2iŠ–u˜â©üšÛ”§âÛÜ ZViò 0—™dúò7Ž®¼.† ÈU‚}SË0Å@Jù±XŽSÞçY„©¼"bMí%[Æ+e.)œ«kbL]£wb @€“cš$˜Í  @€è¢@$™>ñ¹ýÆúh¸|(/ÃÔÅkäÔ3(0ïbLTì0;[<1¦´>5T*) &u $Uk)UJ(e-¥u6n-¥L)M$¨Ô¬>ÒÚÎŽ˜Ki+‘—lÍâ=ÍøKiÃÍÞ"M§‡³cšÁ—h‡CE’é?¶Ûyd¹«†.b™N†in†à,fV “L{ptV& ö­*Â4å ÓÌöÓÑV@Œi`/­ @€ œ€ÓÀ]R"@€ 0Ø‘dÚå³ûuøhX†i°o€y5ºycŠ”âX³³Åúx6bL6h)T&t«ÌìÖH*ù¤6³¼•dÒp>©c-¥¬»Ó¬¨4‘ RûÒJó1®4VÔ©¯cLñVÕH2m»s#š6ºØLΗ·ÉË_yáå7Þ¶ö'Ú£?ÿÕ¼zË3ØÈ$Ó¯‹êìŠSžKnàÅ p&ĘfRÓ± @€̦€Ólê:6 @€³!I¦ŸÝ·íGÃ2L³î˜Ý˜1¦ZÑ£ê·cúçÍÞ6‰ÔQ-„4•LÒÐŒ`ãæ“†*‹TË)år›¢J£ƒJ7ÜtÊ/Õöí÷S¼qD’é]ÛîTf‘ËÊ0uë-Õy{A “L_úú¢Úëý‹û/zí¿üÛ·ßß!Ø·öŸýü—²}½pû³bLýyÝôš @`> ˆ1ÍÇ«nÌ @€ú^ ’Lÿ̾µÀd˜úþºÀhycÊJkcµxöu›½­ÃxjmTK)˜4Fͤq¦{k7ï[eê·–”’ ÒT§À€S&™¶zÿNæ’óöN d’)rKåu!Ãäö˜ 1¦¹Pv @€3! Æ4ŠŽA€ @€ÀÜ D’içO$™d˜æþ8ãl Ì»S”Yk•5ñìëþím6èðT£0RçV)›TJ(5ç<ª¶{ΊLR­M5£3ƒU‹õPƒcŠ·‰’dR‡i¶ß4¿_ªI&¦~¹j}ßO1¦¾¿„@€ 0oĘæÍ¥6P @€ƒ'P’L2Lƒwq(æ]Œéí[ï°÷7Oh´ƒÛ´·¿{‡¿yùkÚ>U[ùÕƒO£-þêÁã·¯¼XëO~éÀÿïþAçž<ïùqô ˪³Pݹá‘|ûˆ$Ó›ÿýý›¼ü•^~c‡9³â©Gnά¼€º4ó‘dú—7ükÔ*ûÇþsÉͼ¯#¶ ˆ1¹+ @€ô‹€S¿\)ý$@€ @ @$™â#°M^ú²«o¾ÇGÃ_1¦c=ö5£‘ù¨¶¼è%¶ñÿ®­ôí ¼t“W<ëÙÏí<ÀW½æŸ.[}[ïǘâ½i¶—a°÷hÙ¦À÷ŸýÏ[ÿ÷3®9¢Ã/pkøÙÏ)Û7Mi»7ĘÜ @€úE@Œ©_®”~ @€ ÐVàÁ;?ñ7¿}õ·¿(Ãä<ùcj½~_Õž%ÐV 7«1=þËÇ_ðŒ^vJ‡«¦ÓཉQgu?Y~Ȫ.»}ÑX¯ &·ÐL ˆ1ͤ¦c @€˜M1¦ÙÔul @€f]àÁ;ßn£.ÙÃGóNís. ÆôI“èÑÓyûÅϪǿø¢þøçmG$Ã4ço°NØ}Œ1Ýúàá÷>ôXëëB†©ûWhÀz Æ4`Ôp @€X@Œi€/®¡ @€˜ÍÓã§~ÖGÃóájÏ·1Š1‰1˜´@/Ƙš¥˜?«¢­>¹õÇ• Ó|{s7Þøù¯Ž$Ó£¿Ü˵$“ “›dæĘfÞÔ  @€ÌŽ€Óì¸:* @€s$Ÿ¯Yþx„™ÜGÃsdî4s% Æ4éËd+÷Ø~ðz1Æ”¥˜²}ñEµW2LsõŽê<]xätîAI2É0uùR êéŘõÊ @€Àà ˆ1 Þ55" @€ƒ(ð½e‹®ùο|´þØ£¬¿kÅÒ2âj’ÉGÃx#̯1‰1‰1˜´@ÏŘª¥˜† 2Å;Yþ¸òƒj~½©ÏãÑ.½ué6K· ’L?¸ÿÑŸÿòWãni“cš4™ @€tI@Œ©KðNK€ @€ÀĸyÕÒm6$Së.‘mŠV]ï£á‰ÃÚ²Çæ{Œé§ýW¼ž;´{ø³~ôXçm<;Hq¹ï{hœ+·Mo½°«¥˜*™¢“²½u¥ôfÖ¢Ó‚sìqQã×µ5®‰¯«Ö¯*˱°þ‘õyòÿ÷ë__qϪ|ÖƒÀ ˆ1Í0¨Ã @€˜51¦Y£u` @€fD *0]¾ÿ‚hYŠéGw¯‰TSaʃG¼)¾­­Ï†c}>åA Oæ{Œ©O/›nh-ÅT)ÈŠÀ<X~çòØ8’L‘gÚô°M7?nó¨Ì+K}¦XÑ¥H8ÅB¤b}lîë˧óÄ˜Ü EÀϪA¹’Æ1ƒbL3ˆéPã ˆ1od  @€½! ÆÔ×A/ @€˜¢€†§g·>cꃋ¤‹&$àgÕ„˜l4¿Ęæ×õîúhŘº~ t€ @€ÀĘ&e3 @€zSÀGýy]ôj&ĘfBÑ1ô‚À/{|ÍòÇã'–ÃbLî…9cšSn'#@€ 0 oýûã‹?6ýíJ€ @€® ˆ1u•ßÉgU@ŒiVyœÀÌ \ó=Î^°ù÷–-ªzݪåñÔÌŸÏ ô³€S?_½>ì»S^4]&@€ @€ @€ý' ÆÔ×L'* Æ4Q)Ûè¥Ûlúèë[;sùþ n<~atR7ôˆ€S\ˆùÒ 1¦ùr¥“ @ ?îZ±ô¸Í7Ž?¤´v·íÊþ•^ @€ @ Ę܃+ Æ4¸×ÖÈNà—>Y¥ø\Æ•âk”_*e™âpܼ*ÖÇšX_"M‘yŠo£ýèî5Gb@Æcr‹Ì©€Óœr; @€qV|a›H2µn*cr÷ @€ ÐßbLý}ýô¾“€“ûƒ@? Äà"ɤøs[•"·k2±ñ¦ø¦X“ë£åæâovÑü…®Ÿ®´¾Î€Ó A:ÌÄĘ&æd+ @€s ÉRLñW”ø«ÈÙ 6ÿÊ+N½nÕòXŽ…ÚúX{å–sÐC§ @€ @€ÀÔʦngÏ^cêõ+¤ª¥äR^Н‘jÊJK™RŠHSþ….–ãküõ­”kŠ-s/óG@Œiþ\ëž©SO\ @€ ЈšÖù/¾â!ñ§’ø6–óï*Yµ:¾ b}´ü[J¤—ò¯(ñוø‹ G @€ô®€Sï^=›®€ÓtíO`.ª€ËDkâpñW¶H)eOb9þú–ÿp0žÍD­Ä›æ²ÃÎE`î|tõ!«6«ÝùðÉsß%gdÕ'?¾ÝFc¶Ïä± @€ÈôRv0–£Sþ%ÿ%XþC¯Xˆ¸R<Ëe}<MA¦¾¶ºF€ @€ÀãÿxC㳉ã?Æ‚Àà ˆ1 Þ55¢Èâò¯lQö<Ê¿,Œ S¤—²üRŽ?ÿ$_c¯ÜÒ¿#Ø;ÃÀZÎþþ›ÛƘ–Üü"Zf^à‹/jcŠõ @€tI ”\Š¿‡d±êø;Iþó°üšüÇ`Yë:ÿÁX¶(ÈÔ¥Ž;- @€&&1¦#¶žØ¦¶"ÐObLýtµôuž Ä¿Ì(Rüq-âojñ5ÿôV*-Å·ù§· 0åB~-³ËÍsFßcdRŠi>\ý.Œq¬‚L±Þƒ @€. D&)K.•ÐR$“ò¯%ùÄbƒüGbùÏÀâ¯.¥Sü½%Ÿò @€ @€@ï ˆ1õîµÑ³i ˆ1M‹ÏÎæR **EË3f…ó\(_kOå·Q¢)¶ÉšLæ@kA&¥˜æÏÕïÂH[ 2)ÅÔ…Ëà” @€FÊŒr‘IŠåˆ(Å¿ûНñ¯¼ò‰EP)N±¦üÓ¯\ÎâL(  @€ ÐëbL½~…ôoŠbLS„³ô²@kA&¥˜zùzõ}ßZ 2)ÅÔ÷Õ @€ @€ @€@ ˆ1õðÅѵéˆ1MGϾ лÕ‚LJ1õîu˜žU 2)Å40—Õ@ @€ @€ @€@o ˆ1õæuÑ«i ˆ1M›Ð @ 'ª™”bêÉK4XªdRŠi°®­Ñ @€ @€ @€žcê¹K¢C3# Æ43ŽŽB ûÞùxü¬:õ³Ýï‰è,ȤSÏ\AïHdRŠiЯ³ñ @€ ‚Àyû?~Ùƒ0c @€ @`Þ ˆ1ÍÛK?ècô+l|óG@Œiþ\k#°@dRŠiÂ`6œž@dRŠizŠö&@€ 0»=÷ñ}^3'r @€Ì’€Ó,Á:l·æWŒiõêÕŸíøØ}÷ÝwØa‡ÎÛxvÀ¶ß~ûÎ#Úk¯½{ì±n¿T'pþï¼üÍ=¶d÷ ljóHà˜s¶ŸG£5Ôn ¬þ»Ýç'@€ @`|;?ô̇¿´éøÛÙbÂþîÚ/2¿…>üðÃãÜóŽ{L_ >ûˆO@:çÎ;ïœðëÞ†æ…À~ûí×ùUãý­æ3.H΋[Ç Ì€ÓÜ8;Ëœ ̯ÓÖ[oý/oØìãŸØ½´?±ûHÛe÷~ýfñ—/Øy—OEÛ©m[ð©|êcc´.Øí£oÓvüønCmçÝv¬´ì¼[¥}ò#; µïôɶm‡}²µ}èc»µîú¡JûàGw­·wýàŽ»~`¤}â;Ž´í?ò‰¶m»|¢Ñ>\m»l÷á]¶­µvÙv‡]Þ?FÛæC»4Û‚Z{߇4Úëí½\0ª}`Á{?ðñh[·kïÙþãmÛ»·ÿx£m·s­ýÇv;—¶ù;Þÿߟú´ÿØvçh覆޵íNïzÿNøGÏ\¾|ùœ¿6'}Â3Ï<óo6yÅ›ÿñåýºšôøì@`*‡~øŸÿŸ¿ŠÿšÊÎö!0I¸Óâ~‹»n’ûÙœ @€9ˆéãO(Ñ"{1§'è“UÿîZû‹ëλìkýç×ÿ[üÝuÔ_\ÇþCkëŸXÛþ}µõ/«ü›jë_S;þµÓ_PÛþítÔNÇø«iÛ¿—¶þ±´õo¤üióO££þ.šÝh£ Í?‡¶üE´ñ·Ðç=ÿ/&û?¶±}\Ü6ro\úÆÕÿv;<íw·þ÷ö±þÆÞáìíÿ´Þéêüsú¨`Ô_ÑÇùûyË 0úÏæcÿͼõ¯å¹úmÿBÞú·ñÖ«!ëþ‡ü¬×ýÛ[ǼúÛîôòWÿs¼–ú½ÊàLN ~gˆ·¯|«|˜Øø ±|Œl³í­V–Õ>"¬ýüªýðýÆÕüpø³¿‘7«vïTµÏø*íUÞšÚ½/Uß‘jïE#?†šŸÓUÕÞ|òç-ÍÝò=g¨ÕÜìô”§>Mbrr7¢­ tcr{ ¨À¼‹1í÷CÖ=ð³lk‡Ú£kjû~ã·þû»î¹ÿÑÒ~pÿ£v_´ŸF»»´{zW¥ÝyïOïÜðHiwlxäŽõCíöõ4ÛOn_÷“ïWÚmkRÚ÷Öþ¸Ñîi´5¥ýàÇ·µÝúƒÝr÷H»ùîÝ|W¶‡oÊvg£ÝXi7Üñÿ³÷'Psgž/ÌÌ9÷Nß™3sû;÷»§Ým Ý=—¹ýMO»ñбeÛm›Õ Œ1›mÚòÂb±ãÆľ#‹Ù$!B }G í•’Ú­ ±·ÀÆØúþ™ÿ¬§¢r«¬zkÉÌú׉óž|³r‰üGTdÄ¿xž·Vn|“iÒ† =¿áM/­Gzã¹JZ¾î KËÖ½±lÝ®e/yi©¥µ»úªiç’5Õ´xÍÎÅ/iÑ‹¯{iµ—:iÁ ¯ûé5¤g‘Vé™U¯yi¥—æ¯ÜÁôôŠjš·bǼ瑶#͵ôÜö9Nš½|›¥YË·ÍZ¤™Ë¶Í\¶uæR/ͰԷuz5m1qÁ_ýõ>Ó–l™jiñ–)AÚzÔQG‰d*i‹­ÇjLÑŽüîñhÜ0~ÉÔ˜v:ºqPÇ£¾}çèã5ø6~7!¤€R@ H) ¤@“ ø Ó€Is–?2qÎgD25©bÌi@Ìî5ºÂÖzã­ÝÕl­‰†ÖŠ•ÕL¬±öÕËj¼YµÆ¦jÕÀšêTÍšj¦T³£FÔ oš5T×|šd8XMÍdjöÒ°±4ÁRê›Ii’uÔ5ÖÚEiÆ4­o Ì¡U‹èâ-Sͺhó7ÿ^££Zìñ?غ+ÞäŽÒ_°tõÞûü-6\c{l¨1°WlìQëzš]=΢î•~`Q¯šÓSJ¶ôŠ=Æ„îÙÏãK&ô³¹ÙÌûWú^,äÏmŸk Î6n†q³Š³ôÿù3^w×–~PjKÿì_ß(Œ©uí¢®TÐmØgß¿­Ì'3‰›wÖÌ!¢}{¦ï¶i6oÈÖ¬öEV"d#V3-Xi»^¬Ì²Õ²@6Y|[Õ¼ªÖï)ç åÌ i²é“1LAŸ)‚19 ÓVôŸÂ“;l[¼yÊ¢b`Ld˜¿°Í+¾—vÝö»Ñ"™ZÝTêzÅSÀg˜N`û†ß\ʉd*^)'Ç>Ãt¾Õ·#D2§ì”S) ¤€R@ HžRsfŸ;`Àä9Ï¡÷aÔ„9Ÿù¼|2µ¦ }H±»ÂÜzí®é+E]€©añÖˆÆ.M^a˜ÚI±¸¶S[ÿéÌûVÓ˜eŸ5k>mÁgüjÏÐRÏ8ŒÉVxú‹7ì.﬇1yK:amcòÖ'XÝQúÏúSÆÒLü‡W·‰a “ÞJà4†É5žWÇ2LAé» ±Å,÷ ¯õmÄæbLFø[Pú˜ZÓ ê*%R=ÂŒL)V¦=t‰S`jŽa²ÙÀò²݆ˆÛmIŒ©†³´y½Ê¤_LÁ\^å­TõAPƒ1Õ8HÁ˜j^=Œ©2…&½ÖFS‰~"z”( Œ)… ,´CžÃ˜0`ºU7KUgK7Ür'F\Õ… ô½ƒ.E|/…©êL LpÅ0Uü0Å.rqìŒ~˜f˜B J²2Lž+&oiQÅS00ë'ÃäàÞÃÔ +&0àQŒ)äŠ)ÿÞ˜<†é[‡-^½Ý¦Ïa7¹U$S;ÚK]³8 x Ó1'` g¿ ˜“àÑ]$SqʰH9E½‚?g«opdˆúvøÀã]½Z¤gV^¥€R@ H) ¤@ð¦/ ˜2÷9  \ñʨñ³E2µ¤01ÕØ]=ßö5îí¯7»kÔÖZÏÉ}"ÀqoëÛ¾Q?L=ñd¤Xü ã°÷ú¦\1ÅxÂðüa4âŒ'ðÆ”äŒÇ÷Lß4ÆTµº;¥Ïø˜àÇ4?-í!c{8ÄA_sC¬s¬ë­%Ø22Lîà ŽA½ ¸bª5•[È‚p¼‚ÚU¾Ñ0QWLæÅÃ˜î ¼1…œ£0.0¦–´‡ºH™ Æäø>ð^m5sˆ;<ŒiþcŠú“ 9“³F,ÖS:Ãä»bª‰¾Â¸+t˜Å([FV‰wÅäNÞŸbª¼ƒª®àoLt.`-½1ÅbLþì›ÇË c*ÓoDÏÒ}„1u¿ ”ƒ¶(ÐsÌaJ©Â*a…oùþIn´8n‡\.µƒ.…|/…ãÇÕÐK¾£ÈÊ»(rÑ@rµ®ÍŸdµ+S‰%g>Ý$!€©~˜ZÄ0ÁeeáäÂëàA× 'GW–Ęj—žTWŸ`ä–sŒ‰ Ó’·‡¦ÏѽånùdjK£©‹æ_2L´9²¡#V‚ßÅOOÉ”ÿ,XÉ0yõÍ·`Á“Õ7‘L+KeW H) ¤€R Ô  Ó¼çÜ/¾#Ÿýiùdêwécб»:ÌŠkwÝäÌõV ­ÛÞƒ‰5Íý‚'ˆÂ˜ÖÆ…{±J¬—çåj 9ךjzÚÂ0ÕºbJd˜ZI±Ä»br1¦Xg<ýÁ˜¢kƒXÂ?¦ù£®JBA—²”~8 ÓæwÖ"¹¥_‰Ç[ú±‘»Â0‹~Í÷IBé{±œqÄeq¢Ž¸‚ r>Æc÷-á˜úÝêeS€Sˆ[ Í!î½Ï¾O/~!ô:KІióƒ^Ûå4_¡Xr«1ý~šÈ0Ùd_œ+¦°—¸ì®˜,vJöˆr˜†s1¦š¦•ˆrhj„1•íw¢ç鮘º«¿îÞ6zcŠRJ>¨ä±J×Ý ŒéDw Hu(U -9cªÀ«m]Â"!so`§ÐK1!äâ<0¹#®€Éx×xÁ8a âyWWù+Ò*îpk¢z{Èv…Ú®úŸŒwŒÌˆr­ðÃÔJ†É 'ÇøßUŒ)NÎ_}bÓ˜ñS¶ì|ßÒëoý¾m?É. †éß:¬ïÅí±Óç(š›ï~äÃŽØýþû \Ô?´¯òiôÄοvíÚ¶Þ´…ׇ¨-¼Z[ŸºÐÃtÔ1'xæ'ßõw°¾ÖؼšüäôsϿ𒦟åØô¹ž­0í»;ïÕ¾ë7úìÑãÓsÕ*ýçÖªß#¦ÓÎ<ŸõÍu‰‡ú†%êÛa:ìžæÿ½÷Þë@£»àÓ\»{VÕz6qVwSw—R@ H) ¤€h‰d˜¦Î{>vÅ L(#ÆÍÉ´s×›-¹]o^„SÌêЊ§%×†ÖŠßx%db]ë©_K‹¢‰/¦ÖR,ž£zßF:Å£è^{íE»¨²¸ÑŠ-Þ˜е…n{£ŽuÖ˜„µÁoLðcš?ꧤ\ ‹)ýt|-3ÀK°Å®vœ`åÒ.ÏÓ½p¹–ó?Lé¥??[8¹G\né/‹ &è¯ïÝbޘ¥_1†c:ö¸¸¥í?~ôçÞlÖôÔR crßn!-Ú·y‹_‘¸æG0êF.0¹s‚tc©Ä’K÷ÔÊ0íê« 'rÅTÅjãJú„3‡psÝIºåñ®˜ˆ1ýUà©&¢\àŠÉom€1-Xö¢ÛÔìz'“nªóR  c*d±)Óõè9Œ æGµ•‘óµ>ÆÄÞ†%š¶ô.±ƒXŠBKQni½.%8^ª¬ ‚Ç¥ÐKv¯ãCÈU<050…`>Àätçô4¬»; îîLîìY¬)±TqJÉXïæ#×íÍC¯ÈRËü0U& ׇÓS2ÃDoL#Ç<åBi¨Bõ[m>‚ ÓÒ5;°V,ºŽÓç W¿~Ó]|hc$¦xaÎà¸ß~û <¸}O³mÛ¶#F4zý &pv9äœtÝL2¤Ñ»àʡѳ¢Ç#«¸rˆÜâÓÿ ê I T¦·¢¿ Z‘ø»tÚàó.h†d:t(~¨´-,«ÌÑk¢Ú„ ܽ…·¶KYU¯{ý”ܶ#cnùÛIÊaT«è^­…¿Ç Ãô–;k&]Y};ì¨ã†ÞÑ ÉĸµÂF›J´M4­ÍUsWK'éu0hÐ HŠoqâìÙ³›»©Î’R@ H) ¤€(¢Ãôôóq+^üÞ;¢«¬~}øc³>ý¹/Šdjºˆ1¹v×*¨TÁ•®½©jwÚZݰq)ðJÇöÞpÜ¢PšRCÕŒN˜|7öÁ*P %æšOÓ §°E0eôÔ‘b±hba†)™b9”Sl@1.éÆtÍÃB tÓ+†1U×GKÞ"cŠ–|K{J黾—²”~]|-» ®Ú Mµ¥_³¸ŽÙöÄPé¿ÿûšnt¢(º>ÆäQ˜Ñ–ÍÚ40wÑ œ:LŒ‚ºùj#ç>°òæò09~˜Vn¬‰%—•Xrýa˜z>*n cª 'gá‚©ºÊ<_@³ÜÆgéV0LÆ41À˜èM Ôà°©Æ4gÁª¼Mº½®*ÿ½«€0¦Þ-û’?yÏaL0×bI.¢ôÞµ7 ûî÷O4P)–Uª2Ô?Æö®  ¥XnÉw™Ž.£¬„àqqî—‚î‹ëö¶J/ùˆR¢Èycï Àä."É 0ùtS0Å3L+_{¦!†©6Ú7"¾× ÑC+‚wiÍr“ÚXr5 úO†1 Î(ànÊ!Æd SÅŽœEÂÌ7޼vÃ7D2hpç†á¥£åóèn³ŠÛ51ƒŽSBxG]<¨îÑÆ¾Unm¨VZQòWMG צT]19¾h˜ÆØìÙ^ûqS$q´ºÌ\C­Ìvzç1¦º9OÉmÝs[r@ÿ1¦Vý=†é¬ó3Ö·C'™@Ë‘%m-pm ‹‹1%Õ¨ØÖžøO×Dµ%UZ‘R@ H) º¨zÛÑéŠ}(Þ.Ëóâ°þx夯M¬ÁÀ'Ëíbégš¾oÒ‰ýq f˜©’/ypìÌO‰dj¶ü€1¥Ú]ßõì®Çž˜dnm™Wû—=?î¢Ð½T3 Bl¹X„¥7<¾átµ—e˜jV{fˆ&žHNe˜ˆ1¥P,McL¾Q½ÆÒîÂjs­Â4K¿})X sº%cתŽLjã1Õ˜<ûª¥'L¾¦¸Ò¯‰``á ,`S¥Ÿ‘`«ñÔ™aBéW1¦`YïfÃaÆÔlû§óʬ1¦HûVãïÌY¸ŠS‡îëÌ|î—B0+-X½MwÂäø tZª¸6*ÕSV†É‹kYq7PË0A(‰1ņ“³ÖFS™3z¶Î+ Œ©óšëŽQ ç0¦knZÞáþ‹o1œN•Rˆ%Ô5+B’¸%Ç·-GYî ¡ÇK‘V(x\"½Të÷8?Î]< !×O€©ÒïiÒ S¼¦ÃTñTb½oÉQ†És–kÉ[qBŸÉÆ€ŸàycJa˜rèÉa˜".gÌ ˆá¾û«†ÊN2ÅbLt?CgB0òʱYvîÄw:œ´I `n“¸‡3Ít7rȺ.KWF8‘¶Tœ‚mlÐvbþâc—2GM¸ vâÞÛ–%>.NïS!›²aL<€Y¥5™Çó©íjø–ÏʿۘÛ:ÒÂ÷ÐM SªaÚó ·òµŸÚ˜O&Ð$Q‡@VyÈ6Yí2"Tð/]ÂðwäVf;×~¬cîoÄ ž¤:º>oļEŒx"«½¬Ì¼>ûÅY5rsËãy°ý -Ãü*)“Ñë»p·í\Þ™wÅ^!ª•µ9íø=†¦ õíÐ#¿ßO&6§VëB%Ȇ(©úYéXcËÓšJ·iˆbLѪhõÊ*§U'ÖO«<î‹ ÚròÊ–«Pƒj°B-3Îe9#“Äêê>£½¡ø[s/n—ê¡&R*¤€R@ Ä)À¾ zèQtÀ_cöu2Àš¦vl¥PZ=ºJÁöXw:u§¹åOÌ9¦?ÿ…Óž~&5:Ý ‚GV¼p%L(÷™!’©¹rÆT×îõòB[kÝ¥¡nظæ\Ú›7 × D,3À°¤’‹8½ð î‚Oc˜,ˆOtþ8¼È3[41³‹SÅÒ<ÆäÕ£æwLðcš?«e,ýÐÂàk­ë ÑKñæt‡^ Ò£Qä]pù~ÝbK?Í WBé›û“ØÒoša‚Iü“ôÆ”\úòÆÔ\¨³J¬1¦¤YE¶cÆäûJ Ïâ¿ÈÞö^a1á/Øj°Ëܶ \’aŠz „Ÿx7¾ŠCX:dmF?L3L˜ 0¦pôRš4÷˜Jü“Ñ£uAaL]]·ì„½‡1E<âºÃ'øËÅpº:r® GP)Ì*W KÕ8q¡qu·T³<.—B^—¼þŠç\¤ÖñR4rœgˆñl1ȸ+ÎýR \¯c±ré Ùz9þ0,ÞS“»²$À”ì„©Â0yN˜è¸ÒK!†©0¹~,+SxÝIn½1Ã三¸bªDÎò¼ÎøÖ¨}ÝYI&7¨ç›É@`þÛÜ&‘ÅÁ.î4ò)Š1átºÁŒ²MuÛÚPlDÍ‘Ñ᲌Ì5TÔ´Êém›òç¶Ûˆòw?20[½dOÄieÆM I±4bÉNá’© e٠Љ¦½Çîá0Lµl_È0]qQÃ4cYþë)çd.g« 4va|Ë:Àê:€¹he@â¯Æ~V™y«xذƒí'ÆQJ³SpYþìWý1Ú̲äbLÌ<+QÈû‘ûÓãO›²¸ø#)™Œ^ eÁ¥°+›Ë+f2D®D¯ÕŠ'¶ã÷è0LuXR›a};¤’ ùg}@pÃJú¤T?ûÊZ*Ûc­™5Ñù­”ªh~Œ¬òu« /m9Ýæ·àÚO&„…žŽÕ™gÅ&0Êûâ_VWÈÂ:Ég$ÿÊߚ뇀î{ƒk_õ¸R@ H) J«@*B‡ÁúÀض'z5ècð[ëT`§õêÙùaïÂ=ØŽ$ÒÍýî-Ø“áuØñ#ƺNÇ–ÉSBÎ;¹ˆd7Û²Çþ¶e˜6cÈ”»‡½¬P_1”m{F\Öô±g±oyüå0ʺmì³ñ°ô§³‡j´:º Sàµ7à ôÞï{tÆþŸUt¹FõÞãaLÉvW˜[¯¾ñŽÀîZ1±¦Z+ÜR̤odQèÛAüz+BãâÇÕXSÍ­Eü*PobØRm±æZíVîÒ oäÈd “ñ™[ñá2LÍÇµŽši´fm§³°ÓØo©®ê¬uKß4ƔĨÑö>{ÁJLó‡&øã+@k E_µ±»^—ܰq5Ž—’}/¥„2Èî)`rçõ0½ðLµžµ–)#ÁV»Ê7c$AÇ0^]Ù /\Æ4ÌØ<'Lµ~˜T®áVO'ô†èN ùŠR˜.€ûñ½÷E+ |F0ã¼Ç…âÇÅ:KŠ"翪_q±o¨8¼2Þ”-_Fµo¢Æü0ñ½3r¢ç; )œœ‚ÊõÆïFOÙY„1uVoÝ­c ôÆ„³ÑHî:^…áô÷N¬:x$¢ä€JNÏ£f(`ÔNG¤ÆŸm5NœçÖ¸:´®q›äâ8hÅ¢KÇKñ¾—¢Áã|z©Žû¥ÊÜ]GâúÂu–’4à©>À•Îȃsw‰‰ë'9À$çºM~ÐóÆ´w4\>1¦†)b€óÏNä,Ã5°vçºÛ3‘LÄŒpaRMøàrœKƇÖX×ÄiÛv¬$®« Z0£“o7r/kóÓ¼µåÁææ95NëªÛ’òZ¿ôádŽ:B†lû—b:2áeí03´e&šfƒWèXãÞ;72†ÉY\°}žÃ9õ pÌJ˜EŸí«`Lø]œœ™dB¡ãç€r¤wŸP…gevë«DôWÙ ~‹_.h¿#Ô[ó@ÃB·º¬·ý"²ü]DÉõuÄ_ Ÿ4 c²Ÿ™À³mºÆIÊdôúð‹šàN~0QŒ)z…¨V”¢å¿ÇÃÄÅÜ|óf©o'“O&<>[|¢ÍŽ5)n+ǦÛÕœUÈê‹’ÍÌT…¦¦x|´*Z-ÅBœh’7¦PËIFÍ* (šg{:û Ì6™<»ïK, Ø”6çax@ûa¿¡]¦Œ6¤€R@ HžUö"\Ä;±‡}ZãõÑqãÒ²7E&ûéåa÷†›ªtl]SvÒÜ[°s…芰lWÃ5ynðÏ˺ùg§‹Ý¼þÅïÑftLæ9z…¨Víø=Æ1L!fn—±¤Ñ‰Ö·,$'X^6Éä–[Nk<­ú…ŠØ*¤GY0¦Øªh xˆx³ŠdÙcÆ¢-§ÛÀrªÅÊ3ë ®€ÆÙ¾bãɉ={(W\¢1o®Ç)\×±#‰Ò¶¼!Ò¥€R@ Hâ*À¾+ûä¬büu?l ;çè±Ø콸#ÊâvEB] Þ‚øµ‹YÜž:<ìDµy;vÙ¡²î"¯cR»ˆÛ½·n˜ O¬›m·Ðíq¤õc٥繮±C•ô§³‡Ê^Ó0ãø¹/ ˜êÇ’ ûar½ö&¯xA×ýžG¦Ë'SvÍq$0¦ v×\sk’­5€–+kÝE¡¾'ûºèRØ“}]÷KuðÔ "Ö„Å[ä™HÎõOo “M'Ã(êcL5Á}B¶Ðoþ½¨c­ôÊûŒoTÛmÏÌgW`š¿¹Ò_Í•À–6½U\‹ePÇ ¡ÒÐT5ž¯vB5y*™|P j3¯ç‚+`˜Rœ0U*ÀÌeÛf. (H$Øü@rðÆtí°GSÖô*¨\Cížîˆ1ŵoUôÌxvEüŒa0]˜ØˆÙË+Îe`µÕ²&+ì’Qä,ÊJM¹³’3?LQw€ž£'X _@ÖþÐ`¥åÙ‚i¸*ÆTñü€ÆÔ ¿=cçÆÔ9­u§Ž*ÐsÓ•×ßêL¸ÿâÛß;!z@uð*Õ.rT±¸GY¡¡uZJt¹T'`\(nÍ’‘°ã¥„Èq5¾—ªÁãšs¿TãÙqDrŒœ´²$ƒ¦: ot˜,¹cõêz£Å›_ ŒÉ&vj¹z,ðÿQ1À™Ë™Nî…—3\¸3ÇÕCëLfÐdSÄic.åäì/&2F0ÐjÉÅv6,ü–]–_|E~È¥Ìl½‘™_Í Ù#3‰bƒžð9w œÄ#ù-­¨\ñÉÕ¢<×rËœ˜ ÛlÇt¹¯Ü {æFg˜h] åŸWÃÔò—›Ã0½Éa^<Ôl˜ö~Ë·Ãûë‘L4ÁÛ#°òÐ(ÏpüQX…$†­ 8€UÈs¼c¥b=¤C&VïÐÁ¶|9¶Ž¹¿ˆèÜ@ôÇh{HþYÅÆ6áE[nn¹Å²J”…?pþ´qY†HÉdôú†6â DXìçÌ)ôFµbY´ð÷è1LgžÌ‚4Uߨ£¾}»žO&Ða±B·¼°RýP QjèII­¹sËԆȮE«bc2ïG¶ªÞšV|Åù°hËÉ Ãß‹Ur^ÙòÌŒÙÓ±¦á[¶ÞøkÏB•XßX]ÍOßY|䧦¸åM±.(¤€R   °o™go„ÝZöUðáëÕËFw†¥îÁDšì`»rhñ@ôÖ“±‘,»²îÕÜá[ä|6óéöp’0&ìg‹£ZYX76°‰yàNöôBʸåîbL¦6B^œM7à’åž}ºF1¦†Éõ¢Zwzïw?<ýŸ?sàÎ]o´žw8ÛÀ˜²Û]kl­5+B#nìãÜíÄ»\Š'WÒÐ¥¤àquØþ-ªæS¬c±T¬'»&µUÕ OV„%Ñ “k­µ‹nö0¦H 9w޹YŒ)ƨnföÏxS8|Ax=p“¥Ÿ3®^ƒe¾gåï%§ô=+º9ßrÝ/5„¯¹QäÒcº¦rr!#y8Œ`ЦŠm嬋H/áxŒÀŸ˜³âÒ«oç,9Ž#±Ã>ᓟ> ƒáO~ê¤_]t•C/¥ööW–lß{ß¿‹™»>*èÝzH†‹öœúƒ1}ô§Vì¸iÑ– ZQ7¯A†©ïÅí³‡Õ8ò’ÉG^쥓†Ìøê™ãåè³^8¹#.šôÐŒu4À™+&(IцܚF25ñD!ß!M\¡U§ÐÏG«®V÷:0ÓM4üVÝsu@Ó €a:ò˜\«4¹OZ¥ñ‹ð“~vÃ\c˜b~þ0 †iþ.~ðÓD’©é¬†Nt×4·êšÝºŽëð)vÝy·2Öòû‚a:õÌó£õ Ó?üpÛaÖ·GgoHªoæŠÉêÛ·O$™Zõík™1Å>¥ù@ª›gLåFó¬{¢R@ H) ¤@›0fšnl… az. utas»X\¥`kfb{Ť½IŠs¬Šë»·À÷:ü7„1ÙEx.Ž1軎cé6‰Ô¸ÑB¼ ÝçâºXn{Ü‘ 9šm+Ó„´ýbòamNça\AA¸§îÓÙCÕ­ Ã4ï9ócmË]ŒaŠtݹ&”ï\4iÔÌuI+^0Z6j*ü—È'ô÷›žX{ÐÖwgÇ–EŠÝ•ÆÕ+’í®ßøöá°©"}ì¸"ôècOªì9Ɉ¥{GM„55´"†V˜"¯¼a˜Tô“_ìû‰¿wç€ã½.Å9°w]ïÀ"jü –HzÖEØóÏŸ>À'‰cÝ/Å;à©õXï#,Û}Õ§L~1HýÁ)@X~|ÚùH°l¤#,tÂÔ&Œ FõX{;KA1ÍŸbfwêÀI´®‡êÀ7|+º¥ sm®­÷Œíx¨!Nøamp½.¥ KQßK^pVÿô/‡¢ô±ÓjÂ觤ÇËŠ¯¹Ð@(~S\ AÐK¾v*ÀÇ÷ý»Ä(rà †ÉÃ×Xú˜ê¾Jt@*0ú¬=/ݳû­èãcжonƒ†Ê6-K…¼¬qjà8^¢qû¨ïô‹³/ñ_[p9ÿ¹WðF[Zyaíÿ™/øé€Ë®½ƒ/,{O]ûpLöÙêÄ=-Ú:=pÛÞtžE‘«LáUÞGæ ®^ 9(k˜.Þò ‡1í¼RÞ˜zôW¦ÇnŸ˜ڧ­®Ü)h$ Ý-Æ£}Gw*«íº†Ó0¯DL77¡Ó½@oW\{»?5^¤ÎQSlÂP '8U"_rFNâXzà±'a…ÑÔ‚•›q=7ÐÇÒ/ιCnZß|×Cø74´®‰«…–²pKîxÛ§þêb,ላ -Ù±è’3ö~ý«ÿrh°~Èw€|ߣÓ~~æE^G‡ie°R-ä ÷wLÛ{ß¿O¤—¢‹ŠœÎ1¦$÷K5“³Ä$fˆîCß•q–›øCµÅÞP-”šÃ˜6lÛ €iÄó»«o¯9/ŸÜ®úºg¦¯ë°%`˜*ëÉÌ•(j&Î኉l0Lß¹xRÀ0½ðÚO®Ÿó•3Çœ¾=Øù`úÜwÅD\\ü[ZI2µo²¼!yaýDN¢®˜ºHCÓ&K{t'ïÛP&Kv0¦(ØG«ô)7Í;çŽgÌ?Ù‰WL¿qÌ ²}ÎïÂ[SRý]¼½0”'µ™dBU Em(héÐyežn¨ ú,éÙ&Ã[ßà‡é ³ÆÛ2͛Ƭ¨¶Ã¡úV1AzTn¥¾á=…®I>™Z"fûZfó½d~Y2ÌÙ,¶™YŽ×1R@ H) ¤€h·Сcãb@¸#:·`µ1ŸWÝп ÖfùŒuÁ‹Ø·¡[ð¦6R°ÃÜ«Ñi“»‡§X>Ý<à07jž{ßhNBKqö„nÄ‹G³mûíîÈS¹{¨§K;1ç?ŽŒÕÖ­!d˜¦Ì{Ηª Å-ráߣs6âH#­ÿôIDATc2/ª?½a†š±ŽÞ¬C®˜Ì„rÇH‘LžØÀ˜` CŠ…™hw­ÁõÌ­–*v×°¡õªïÂBV 6Ò'f,A2\ K@A/Á²jëBCìah…õ ÉŒ«8“¾ñäJ=tɆu1=lþ-Žøî‰§œ‰% ~ŒžJð¸¦ð¸˜l‘§ëýÂ]äé®ðüÒס Ó¿žv>ÌL¡(r†°Ð.Ú>Œ)2…_-ý©óžÿ›½÷M2³_iu`C¸ è­0‚5·»$8Zög¨ãsËóº”6ŽVô¨ 5!;½„æ¥Æÿ–=°!ÿ[¾fNP*SPô‘Ò÷ ãŽI\S»»º~Qxàä=àÎúË(ÌDŒÉ}9ÛÁ íÛTŸ¢vÆGbñã $ù ¼àÒkÑv~öÅœ¼qØH@KûþíßÓýÒyÿvõI?>啕Ë^Édó}h¦à~ 핹ˆC…fêö¯ñJà9#H˜ž2ên+31»d“tUÿµïø~#Æ”îöOÞ˜ŠúKQ¾ó©€0¦|–‹r•Y.kc¢ èr`L—_;4XÁc·/ÄøöÈïžàzNŠns,ýè§¿À¨Ø<Öb,}ïCÞ’ ÐXl]h #jÀÔ.·tóÆ„¡õ×C§äkß< 9ÊB…xõ~ú¯.†Áź,§ýêb$ ´ðý*ỷèÁL~z¶ò.rÀo¯¹ã¼Õ!Ÿ9`Ìä6êv;4¶lÐ†ßø‹oáu _ýÆ¡èè`ܶ±ñoWÝKpÓKz Ûî0 Û÷ø×!ÝýðÔúÔç¿üõCð÷–ß=n‘ãlÏM÷ŒuûCÀ˜œØº^¯+Šþ×þŸÇâ Éð=åâ_&ô“ð÷KŒ¿ßçïn>ièðI¶ç¶á“ÌYnJ¸÷F1¦µ›_Ÿµöê–ÿ­6mŘ<†é›‡-Y½Ý¢™löb1™»ŽÐïœøp ŽŸ¯ôù³n›Ä…“|ŒÉwÅTër†Z b/¿yDJt¹ÌÍ‹”SÀc˜¾{‚­· [¥_ÚuЙÀJ*1_|õßc˜üßÅ™þïbÄôuU†ÉqÅäý.<'Û›Oüɯ’¢Ëuî9u§|(à1LgœŸTß’†êæ?ž¹¾¡úÖn’)B*R@ H) ¤€R`Oû {ˆë1L ˜2÷¹Jï=ð×8aª0L0¡cÂòzQ½ö“oÖ˜¨ó§èÊí#¦`ú¿Ç}2Æ 3cб»:Î'’ì® kAa#¹àEXY½Õ¡•å €T0üÇßßù¦×P8Zéz‡Ž+Ÿ¶®,è»b丙fk½kÄâÁ¿\‹rçðñ0Ÿ¢Jà¯ÙQaa›4o쨞ÓÏxNw\×õ¼âÙß°Ú †S˜L‘`#ý·«oDzϟŸqÑñ'Ÿ¶÷ßþý¯¯ _õ_ùÆ¡HtZ XM¯ºåØ%ŽûÑ©4bψ ÏÀ^zØÀhAE"ÀtìOý'ß zÈQÇ£B90“šiô#‡Éôà#Ätþe·b›k;O?÷Š“O=/„°´c –œ…Lî• €Ÿ'¦ù“,íá:ðlPhöAѳ0¡Lvµ»$øt«¾E½^8€k€­  u! P40¨¾ã¥Hظׯ0v Vt”>ë}/a#¦Üo}𞇧¡”?é1ÊšìÚ÷ýš€tèQÇ£Üï50’ãï…W܆ @Ãø…—ßêÆï1™¾‚E Uâ‘Éˈ¯aÛ"" „1é},â ÆÄT 3¡á5_nãæ¼ÚØ¬á€j'¤&È©ç× …[r¢íÂä æ9ˆ·fÇM]ˆ9A¶Zh¦Ìa¶ÍUš©Á—\Ìõ8sñF2L'œ|ƒ¨ š (¸!À_LHôÈWÚ(Î%…£È¹eÅÅ@È MëHY&Ý„1é—(Z©€0¦Vª©kuZ,X‰äú“¶Ô÷Æ„¥óQ7Ú~‚ÝÃéË®Z+ÝíRlxßzäžÛ¤ÀsÌ¡®ÆŒgWsÍFMn˜mKî ŠÃfðIŽw¥7ÐÁΊûGoiÈMÃFN}æl<ýÜ+c_~Ý0ôW¦Î¡2´Þuä1'Z². 1&¸ŽÄHÛó¹f'º)çþúêSϺC/,ˆ ÿ]‚ÇcÄêvƒµ‡ ŸsÉU{cô… tk®¹m8¶É-ÑëŽGÿæÞÑÓ~vÆ…ØÀP –~}åPôxÇKÞ’5oÕÚ=OÅðÛè¢ëƒq8é%ìG{0ã¨Ìã–÷KwÓÁ9ºÓ;.’ùFÆ1wŒ˜„†å¿8ï ŒÓž¼ ¦ë†½4jÒRìI÷ZÉ!\–Fw#Ç<L˪S[1&2L‹_ØŠ0¸ãò{±Œatâ30aîüþ)kQŽ“¾zÂåÓQL®1í%7œœ¹ p _‘L-j]t™N(0L•±_5Ú¦öat‡èø-í«ÆX|áµIÑß…?£kóè†Öƒ-ƒH¦Ngîï†é0Lõê]7³¾1EPßV8íp¤¾‘%e}É”ûº  J) ¤€R@ ´@èÚÊ\Ô¿æ?{À€Ésž‹šPhE1ªè½ž½ývôÞ'/òì'0|c –%x³æ´ºî"™BSfªow½†v×[+ÊÁ`E<8ÃV8ê¥Äð:H£÷L¯ž›%ßÖ­…­6XTQÜXð ÷\ Ëêˆq3±1bÜ ˜79üØ”…ØøÎ1'>ÖT˜Rý1çw«@=ûê%W£†À§…!,œ¼‚=¤—°=ôþÇaõ¼×ûNë.=üä3°šÒ^Š[(&Œáè SŘ$†áôÊ[€itʳëA±À^Šô“_\€D3)§A®ÜùÐ ,°‹Òõè¥_ž?qÄ,‚¬ Y` Å OúÀ0|ÚùiÂ"ÊûûnÔSKca´ÉSuÕY­½¦xüB1Ío¥××§ÜÝ:b ÉJ?¦¬Ö(qÌý»u€¶ôaŽÇ2àƒþå0®þeéã/€«†˜Û-”¸‡1ùñ &Î^ËÎX´ÆX€k °ÁrGðÊýäÓ`3»z Ë}=³ùsÞ¢S°g^xåÅC†æÓKHà–θ`Š5á©ùë`$G¹?:u9*Š%Îr(w²ð{Pô(qü=æ¤S¼ °xËy¿½õÛß9>).‚ʵ꽣ë”Pcª…™ˆ1ÅÏ*V¦qÀ¤9ËC¸’­¿M rꆹĜ p[ó_`AW,©‡1Áö ­ù^Zø‚Y…Ñ4=ò䳈¬‚„ x% ½„„ µŒ¦BÞäÝÃSѯ¤åÛÑyÁ ™òÀD/•„¼CÎÿ̧@ÆI7aL%ü鑺¨€0¦.Н[÷[0L yß°7&8‚fàx{.‡7¦Ë®Û™àN|ûï²zDýa°û=ŒÉß`zèñYðXË¥?–¦ù|Hjo–ÝOô±„õ@TcŒí§gbÛBÛb{Äc3Ð/±Õ!è¾`;è² TÜY3ÑÙWa©Ð˜I H)a…ГsWbÄ… th*#.oÔMKìÊ ‘ËÆ)ØfÀ8`ZùÇ]ÞÐËǘп!½4~æóƒaÜrï8s¼Dt‰¸é™Çf<‡ž7&÷c˜ð×Ð%ËýÎç{ÉØ*‘ÝI/ž²—aƒsŽÍ¸ÊÄ<$cî—ð†è^úçÏa@þ»1sÓWfìQ}úóÜ?õgD&kî^¸e2ÿLýß8kèÿþµoºè…mnݳ­YßÀ0=:{çÎoxtè ®¿|úC3Ö¡t€1 Ÿö’Nn›ùBw§ÏE2õ»Õ:¤&´Ï5? ƨ,«èùij¯à‡b˜Ð¦9¿‹§†OuÕ0‹f˜6’鈟üûÿsÖ ªÀá?Ûë”3ÎK¯oXÆÔ7%7^¯Ä˜²Ö7Ç©»G2ü7ÕU_¶üKR ]ÁÛóêòµÂºR@ H) r©€Ï0} s‡!Š;Z¤mCÅѳ<Œ ó|è·£÷^Y–൷âŠÉìK$™nœù¿t¤Ó¾l#ÌÜœÅî5´†V„"¤°UñGýž_ ?¼ÒC¾w%3±Ò ¯°šÂÙ&€a4óÿzTz¬·i`:±ÀšO¬ÿ´`a´©Â(Š„S¯pb˜vT?pX5fÑ%Ø0= ó)]\0Á"Šb˜OiA½š*†½”^êi5½D¿;Ę`&¥—úA§_0ì¡)ƒN?æP:^Â&’+œ?·Ïô0c‚¡ïäSÏGÂ,ò·¿sÜy¿½åÞ1s¿xÐÁIvÑ6aL®Q=j~ÇÓüé¥ÏoA¤¡ø¸RPîVPâ0³c1pPÖz‰³þ•:°u€Vt«\L€u­Æa°­ø¥uå~ÿ£ÏûÀëRmÐ@Ôs¼„u¿°œ{À÷k‚'¾æ©Æôy¬øõ æ~¼úÜ"¾†mp¨]qñ5Éi*G)[ä&àk VÀ¢÷9¶-°£ô cBxxÒ2ü z å~í°GSLâòÆ”ËWY2µkÓž ?!ÃTŒgýå[ÃÏü‡Oì4«È†ëo>¾ïSµ]ǯAÍtaõæ7_ŒGÇKçýúj´]lÐb#œ¢E2‡nK…WÕßõ˜Zâ•À•¼W’ß4aÎHÖb‚Í%4MÞ\ÞsÛú‹ Ðá„V‹Þ˜ðJÂë¦ÆÔ[laLCSÂÒg'LÖòdñ Œ)?{e¡D c*QaöÚ£]BD9uÉCÏ2ÖÖ3bÅÇ`©imºeüg¿0àÍ]º±&‚{¥GXßÖìÆëçÎQ¾ÞôùŒuÇ_>ÝK—MÿÊã¿ð©Ñ³6@yPbÃäcòær†ýë>öÄmo¼ÿ§?ÿ¹Ð?pe¾Ü ÀEð¾…«¶ñwa+ûh•V2uñfþ.àßûòáK# ò»˜f¿ ˜‡ª¿‹J˜E·ÑVò“KŒ^~xkݺZQ8ëªúÉõ )êC °¾áßI ^©o>­›Ä’Nxzý_ýö½?ùæ×¾ç†ƒ”¤@V.ßß³¯=s¹=R@ H) Òxë­·:è ‡'Ω1¡8Ë]l"ËÀö.c×ãÄ#`?™½‘QTèµ×ï½{&oÅ‹³>­¿ðµÿuý“?›ðâ7Š2ºia>ǯùB5çå“~Æ1Q»kÅÊêùOªØ]öVXVï1Áu«sþ¥×À©’-=ÿß®¡‰«@Íu=­H6ã ;ê wŒ¡b A½å /z¶$àJp¶D¿¹æNQ¸M³*È•YK6ùÕw˜01ìÂ+´ záÃ>ufˆa5ešºpÃOyáOyÃôëŸó=^TÜÕc{ìôå0‚_1~þ _\n‰ ×y`‚÷Ÿ~>øl€^BºÜÓæ€‡î—à™6RcZLŒÉ !„ ËwOüù¹¿¹¥ÓÓÑ5kÏ‚HItµî'1}|ß$c»Õ.FªÖŸTCà2àhpgý­Zbéó/¼myEÏ:P)wÖ,ÆJŸiôSÏr­/Ëݼ.1d05ÒYˆ°ôïAzxŠžø*ËÝð5bL´“£ôÁ0!n <0_»ñî± :Ž—BËzY>ñ€Ê Žœ£|’3”ò†Ðèyx ’ï± ’õHð•-˜ £k/0Ü‹ÁŠl`QÙbpÅ·¾‹ã‹0ÊÂ¥è+]Œ²ÐkÁh clô]Žøî‰ç\r5 % ½µÌ\²£ƒ1ö9{Ñâèi ûáLò¾ÑÓÀ-11h76È-`⬲rh0m ´èréâ+‡¢¯X›èR5UBŹè| c$vÅMp4Ž!Ö…WÜ “Ðå7Þo£2ÒKô‹ËtûˆI¶¬„K‹à×ñìϱÀƒ´ó~s V^ÂhCtlc×BŒ AåÖmy÷Ùõ£¢0Ì4ýýÆ¿|ùr˜áæômpz·AÖÁîvã˜0Àaùà×búåè-öz~Ê ¼ÎÔමJ$#c˜ðtH"™ÚQ”ºf É„¦oÁŠ­)¿‹!#–᧺Fï¾Ékñ»¸wÒÿwáµ]ø]<8u-Ù>†“‹5LƒaºæÆaü]¼ñÎï[øºT€0¯KP³4ªÒûFpD£@{dÖú‡g®C;ü“ë瀙«´ÃÕúVÃÌEXÒ€a9Nõ­@u#/Y];[S^ÊBùR@ H*3½·ïÃÕ„Yn]w8a„–d ψ Xp#®Q´~Þ¾ßß{ï=÷"¸£ë ÞFI|°NãŠÃ%”öUC#É4j§÷6¡ØòôÞ1f„q,èº{Þ¬“½ö:Á éÍú›¾jÃëè½?³jç?ê¹Å`±Aå`Ã~–6fw­ØWÁ0M™·ü$l\vݰ)ó_pö0eþ*˜XÌu°D[ë©¿º c4˜XñíØÉ ]gK ”Pú×ß>TNÃÊ Ó(Ö‚rñ' ª°£ÎZ²ÀÁì¨G}‚gRxt3x%˜&¼â›O™0O|ØÑ'À7uÁz,ø|hâ3`˜¸à8 ­¦tQsÕc¶Ø|/\Ë2ì!S!B€ ôÒ wÅž‰ó^‚íâà#ÿÅyWÐRÊå°‹dáÚÎÇç¬Ãô£SÏ£- K:ËÒ&oLiFõ—v=1{¦ùCnHÌÆž\^ž·üe+M놬™™n–²ÀêÀ˜É ÍÙI5”ûu‘:0ú)¯Üî[×aHÇÚ$=¬è¬(ú T˜c×Xð½›xôÒ¯.¼ˆ@€¯Uʽ‚¯yåÎЀØ`(@¹ÃZŽ„2}rþK(zì¹àò[ƒøqþ*_˜Êý °å{¾C&w}/1&TcòÊVq”»Uƒ$ø0¦†Þ/=t01&Øzö *÷TþÊ1/¨œÛ|ÕN)²YÃOÌZfmšùXªlxЭ5\¡Ìp[rKt^À~ ½ !Ä ¼.¡±Bë‚,A/Ñ÷b›¢uºõÞqhšðzºê–ñn M(Ä3§€x%Ñà÷ŒÅ+ÉbYžqþLn¹Å>äM'Lê-Œ©g=zðî+ Œ©ûe ôWf¼1Ù=a˜(º+&§/½ê¶H¢ê¹ßbÄåö-¸¬§&Õ"ÒŒ§Î„m Kö/‚¬c”Déú;FX_„”̶]LÌ{ðqKô[‹o§Jc‚=„–ãöÒ«ïÀˆt‹s.¹ Ãlô]ð/vÒi$Z ¯‘®¹m8F\ÓŽ ¸%ŸÅœ-îŽ}o·„–ÐÅõ„×Å·\ Ão ¹ÑÅ9ñÀ¦,𢶛ç[ŒÃáý˜1ËÜ„UD¾î¹d3m9Æ`Lt¼„Þ¶çqOÊ/}í`úÈEbdwŒÒ±„ÀÞ{½·€U²ðÞ˜á_þe' °áo–ˆrÙ½1cbÌ4ÊñÌÔ&Œ Õ•$Óì%ëkúµdðýþëOo˜ ÓÒMÂôùcó6Ärtí¸brú S­Ž~˜ìÑD2õ·•ÕùíW€$Ó³+¶˜[2¶®ö»Àˆî†GŸÇ²Zð%øi¸ ~?¾vvÌïÂtÙ@Ëe˜D–´¿Hs}Ÿd:Î ¤H­¾Ÿÿ2a¶Ã×~Îe˜âê[e1w¥¾…&Õ·\׆fNS EY’R@ Hâ(ÐÕzf†ƒI-]˜¨Á®Uˆ¨ <)îÎ<Ø¿¶ÑÏ#§å^$Ä!¹“¹mÛ6ðLÈ’•É*\P¿j4cÉ4~v’ Å\¨Ž›· &c˜@ ºn\1ËÀ–9‘Ç“&vÝ{d aL0±¼2Û]öVâ)0¢"1’ü*qÏe×ÞAT ˆmªî¤/ ­H0 Œ™´Ͱ¿OÎ]‰ $ØNɬ[á4°—à—ëäÓ<[kÅŽê¦?ù4ü K)’‘+°¹Á¡ö^¡g Ô¤ã~t*XM¯¼ù Kg^x%é%ì¤Õ~w`2¼Gõ؆½î£Ž§ôÂËoÅ6l¤øK§¿håúœ©Ã´¼Èœ÷W``ôý-áÍeÜ›"a*ï,4Yh¾øÂ¢Ï4Vh²à¤Àæûøª"YËè–ø{É•C¹¬÷,Ÿ°D´„v‰ÍcYÂÞJx%ÁZ!Ï¢Lž1“ɃhëLlTN­Šè´˜:­¸î×z ŽÑåÜOVoL­ÏN7®Èát”z¶=øöðÇÅ÷0*æØ‡;~®Ìq.éø1H~wÄí”R]ݨvPª=¬ B ØN4nsklž–ÜEB6Ò6jG\ÕQ·3ðfϦš*¡âB.—nºg¬ÃÙã1n‰¾dÏÙ‰Œ3‚ÛbÆUƒéVPîj(Ü+ Âëºp7Æä×ø¡¾ÇÍY“Ñ÷Rt—¥G…E*.ÆCÕ¦íïmzëñ±«÷‡'íöaLø‰dš¹x}µS[‰^ÄFt²eýTúaò Ë¡'ࢠ“|2u£YÒ=V$oóŸÛ÷»¨:{·õ‘lÖŒ¹Lgû¢ “È’†K¨\'€dBÇ J/U@RÚO‡¤„iËN¯o3Ë0©¾•«ú´ùi„1µY`]^ H) Ê­z/7ïAðÄ=!Oæ‚®Îq ¿‚} <˜ž“¢{Hð¸ËÍ_:µ={6¯`÷ãÊ@yH2át3xðàP‰àâI_!3üЏó€!Ùö‡®yYÞÎnA 'ò©í²¼ KeÁ˜p)†LƺBÊXI2||vh­ ¦PïËÀ¼Þ»T¦J$èŠU3C¹~˜ÜÅ`½F2ƘXF Ù]Lªkh5T%£qµ2ï[5«z¥_–,þŽë·žäJÈŽj¾vlÃE—Òl§µ >CVS†‹ÚKÝužµ'˜6ŽN'8À°Ež4™v8¨\Ô¨îÚØ'Î\ö×ß§º&-›¥Ý/ýZ{=Ózmð ¥&Jßu¸תöó8Ëyhů[†=4…>·èv+âï¤â5Ü1•ÓùV :Pú(ti’7¦Œï( Œ‰S-ÀDq€1Yó•4·ˆ&Ì\–ôF«iÇ’1‡[BÃÅ~‹Ø4vâÏ}UÙKÊ}CÙ¼žÛ4Ù\ž½’⚣X€i³»8©É2éöW½÷œ«Ü>&Ýô{”R I„15)œNË»=‡1ýÛ•·E‘#Ûƒo1⊠¹(R–TN2'1”’gL±Ë*²ö–ƒ8áÜ€Üa\©_Ç·ëAKá8qSão °6üßÓ®íñTÇá¡ÁX¿Ð%ÇKŠÛ1‚¿%:^Âß”pïé P²ô¨b1¦  ûÖã+vÜû+ßöÞ¶÷þЂŽI¦‹ÖtãPÜ&Y‚áteî<†a꣦-f€Kb˜D2å½ÍVþ|<’é‡<½|³ó»–Q²mtWÖšU:&ÆbíâÚ$†)…,Y»«áUÂ*ÃÂ)@’ÉES µ Se1nu$½¾¥0L¡ú¶ìÞ!S|驚ÀÔpîeƒ '¦2ÜJ„1µRM]K H) zN€2@pðî'*ÂC¤œD]Àôu¢!là_Ì=ø»‡ÎŠp$¯ÉÅ…Àž¸ÇÍ€ˆóÖæ6 ‘K2 ÃíAì-QoLÌŸž‚ò‰è—Û8‘¹ÂGhÈeÄ”1ê‹26]I27Ë5¡¤/?ˆ2LÕÈã{TÄ®û#‹g÷É´ûÃí±‹ SŠÝæÖ_vWgÁgÈâê¬ÿtãéDWFX¥À¸Z ¨O,E¡%3¯ÅN ÓéNÿÐ¥`µ§ ¯ÔÚK·ÄÐK¾ß‹jìžTz &PxâÁRÏtWL8¬MÞ˜l Pìrßñ3<Œ©f¹o³¥oR§¦õ:Ä’o2Š-ý¬Ü’Ï>†çQpÍYñ¬õõÙµa#'ÃßI,½ÔOv …Ž¢Ï@Aåš~Å”üDaL“¯b¹è‡S쬢ñI8`üŒ¥YÝÔL:ÍW”[ Ý5 mÒ{*xIÕ¶QÉôRí[ÉdI?pÖFÄK˜§kÎw€0¦’7)z¼+ Œ©Ã‚ëvR ç0¦_¹5ÆR…1·‡ <.倸¯âɤšE?@më?"•âý*UWñã«d\)˜O­%–b=-Õ…–ØÑIô·TY?T[ÚêÆê{]ÊÜ%J§”ê~ÛOŒ)åwºß­žI®%’LÓ® Ö‘fsÐÿGeaغ¿‚Ç3yT–a¥3LœAýíZ’y]D ´II“&}å‡Ì]¶ÙÖ¦„µ+k˜’êï"aâïâÝݺ3ð‘³7ÍnÓê²¹Rà¾ûî;ì¨ãl wœ&Ï^u%·o²ä›&€PLϺ ëÛ¿ðGˆ0aЀÝ;·EÕØÚ7xS®TRf:­€0¦N+®ûI) ¤@©@c&úC¢g&n×± œ‚¯ c2‡ç€rp|ÝãbL8‘çE\‚‡§×Œ5|DÉe•ð/om@T¸nj(¿â-¸§À1I¡%-rsEhÉ2ŒLº¡è¨^`1{!Œ‰·èg=Éô¥_þجŠ¿ Ì÷U¸ìu–~˜b˜†LûÝ/»]÷W_ßÝÏl—ãt`L-±»Æ!JK­°}Õ™ñ±¬&KQfʼnD y܉ZPSœîTÕÇy©÷‰–BöÒx×;­6“¶ cJ7ª?>})¦ùëZÝ[^ú kIKt¹”¦À-}¨zÞª²kž×/%;ÖªkúŽ Œ©ímëŸBS²¦Ä˜Ò›/€V®æ˜¸ +Õ·Xíû«ê¿ @-¹¥PTÓXt‰ÝKQßKî\^ô}û&j¨µÉ2é&Œ©õ¿b]±—ÆÔË¥_êgï9Œé’!·&‡^Ç·•yÊšá±ë-)ÞsRœkb×ëc§bשReD*Å®ªqhŒ²"Ãl['ä·bˆ¥ˆ§¥zÐRBœ8ÌÔ:#ðŒÑâjÖµzH–±_•¥G•â)©q2o0¦¡‹‡Â!Ó„5FÃT1yda˜¶ì|ÿOþs©›>=\?ñ)L³—¾ö1À"£Ä3%1LÛÞ¨ù]àÇ‹Ÿùài^¨þÀñ[Žý™£ÀWö«/ƒô=ù wÝs/zY! ’ÖÖ7†U­e˜‚ú–‘aÚñæî~oÁ̓¸ßªÑÞ+™à™‰Ûø`)º{p ¾zyn7KOc¹ZS¹ÊSO#¤€VJ¤…\ŒÉe’1ºÂ_¸)2Œ g1ÏÀ˜ÀáÛèž$ŒÉÝ+r èC¾Êö»î…IP¹tskWã²`L<+„1™ÿ$>]ŒÉ¸Ë-á©› 'ªA2zä÷«¡<+˸³×·ì sˆ°q ™Þ~e-þb{çê> JtÂ/Møl÷ã/cÌa?ŽÁlÀcSsOª³Š¡€0¦b”“r)¤€9U€Žˆ˜9 B j\fð þµ¬¾ã•3À×Y»v-N‰îqÁ »¼(×aŒ6Þ"„þ`Àa¸¬eù1'F8W¶s!oLîƒð¦I“›PJtÝd¹¢,&2‹1írËØÍ'ö‘îr3I‹®úï~)¶†‘dºÌ Ç„Rõc»Ü¥!† ˜žß´ã«w;|ñ“¿ÿð#Œ á¬—ËØ¸Öì„];9r„ýÇäô÷ТlcjÎîšhn­µ¯¦-M Ub•hx¸Ø•ŸQ#jÈW}·6œ&˜LŒ×*‹hû0¦£úcSû0Í= í¥Ÿ!X-çnj´ô›×¢èRGVù cjQƒWºËcJ.RbL)í¾Âhåb´šYÂ0®”Ï4Ö9\LDËZ¯KÑp–Kk饸ÈqÁ,^#L뾌²Lº c*]#¢êª˜º*¿nÞ>zc 1Fî¿lzäqÙñ£4>)yüœ¼&•J)TŠw­-U‘a»v™ýI†FÝáq—ïO"‹³¥,ÜRk½àÖí0Õ= Kª Œ F+.¿sÁØ­€;`'éضð-Û°jeáH2MzfmP1*ìGcQÖúÿðѱÍÔA~˜Ú×’êÊ]T€$ӌůÔü.|ß¹¦eS'¶W¿ü0ñaÒß²£C?sü䱇ÇcnémÖ]¬»5H¦CŽü>_ÖEÎ@Rÿ•šXße˜¼·ƒÏ*aƒÁ3[ÂNlÃKþ‚X¿ØoßfÂÞ˜è®IŸÒ* Œ©´E«“R@ HN(@oL`hÜgÜZȆzcâ~¢<ÜÃq¢Ø=Ęx5";ü‘¢#%° ycbNHGñþkÒb–’Nç·Ä˜˜swdÌ?‘ÝšÏèzKâÒÎE¾°c'Î¥¿(^*ÄZa?¯æJÝ*oL¼#I¦{¬sü§1ÇS—]~óˆo|øª ¯3âslúŸ7ÃÄ•-t¼sFˆÁ#W°f ô¬ ;QÅ»qbLYì®u|ÖPÏÄê¸VJ5«¶ÌW}ýPqþ‚Ït)ˆÑSC®TÖy¶4dX][(hÆäÕ£Õ`,0¦¿Ù'=ALŨWú©‰T6ª§”¾ïÆ;&D`Œ³%oÈÓkŒñ<¦ _àš[+„1u£u,Â=…1%—’‡1ùÍW4ùŽ”<8 Œ™º$éí–äÅ ‹kÀtÈÒÆ…ÂYz3z•äIJŒ¼˜ZJ/YS“eÒMSÚå±8 c*NY)§ )ÐsÓE—ßþœ= |‹éÉtßHu¿ :UïÄ„“ÂéDÉq§”Îq½ëZ)˜¹OÕª#®ÌÄRxì b©ZŠ„û.—² ž»xL–UWÚy&¿ ºäÙì|>ô% Ëõ˜2œ"ÉôÔÓk][A'µ0Ųb˜jup±ðI¦ƒ§/zÙ<“E­ÒÁÊÚ%¾•°b"lΓûC޵SÛÏœçìgnäb±äUnC d `âJ°ùH;¼%í=ØÄû’U¬œ0KâßÝ;·f‡`]4á/·™, ±œ c*g¹ê©¤€R  ¸Û‚‚Ê-åà (‡OØŽ\µ$<\?µ H¦Ñ3jL(Œ9î/?°0ОËY–…ašºzÉ—ïýrH÷ÛÌ*=0aƒ ذí K¿²í®I¦×&ì®U+kFãj…VIZÿ™è¨>bJ­»ìÓ™Îä¥~Š_Ç‚Ôqtɵ¾¶ cú~J陲äc³O]»zL€‚„M¬þM³¥ûk}-5Zú!j-ºÖ×/ý®k˜úù6é‰Ó…1%30¦ºÍ@+—ôYÔ2Ý3\ŠSÀ4t)â ®åÓsY&Ý„1õDâ‡ì˜˜:&µnÔYzcºðò["`ÃŒv\x™‡1U¨£Düˆ ¹BÉóÊ”œ!t>©B)͉¬ÉâWÉq­DKÁ‘Fp¥xb)#´”7gKu{`YzTM`LF,Ù XfÕ¢‘Ë–èa›ëö²|H2=1o Aõ-–ÕÔEXSh@2 øÚÁSmªL®U:`±éXr¦’K+ºvj÷gî:]cpÉB‹¬Ì› ™þÎ÷k<á¥Ö·æ&c•À-!¨ï8 ¡âàu N˜Ì÷ý6á_PM<ÛîÎúfQáRaL…,6eZ H) J¢@ÓSIž¿8A’éžG¦;þz«~¬JÕ•u†iËÎ÷/Ÿ}ýj㯭L3+ì<ðÌä:èÅx0‹îâH“S`LÝ5@ŽªWÚZ»kŒeÕ5´Æ›Xkí«Ñ@`¶§Ù•ŸivÔ´ÅVª¶Óh¨¸Ž «kµÚ„1yFõ˜e½A5xt²‡1Å.ôÍdcÏn]O6ª‡ÂÖ†)Hö´èQkrKù±™ËS¡›Ù6f^S²¸Ä˜¼ö-þíæ½ÑpÀ£“×iÍÒAÛÊRÉð<`2aéº\ª¦ç0äx©²Lº cjãÏY—îA„1õ`¡÷Æ#÷ÆtÁe7§ðFøöïx.²¤”ÑrüWË·§ÃIÖAñÆTqî”"ƒ«P)žUJ —ˆ+ÅKþ¢4gÕuuåPöÁyÊ‘YzTÍaL°a]²•v\‹ÌXä™`ÀâÓ¨’Lç®!©ÆåƒtÂZA¨Xr½Ñ’ë)=H2M^¸É]VkViwemÿ&Ü?düœ±avêèÏœßâ0üÆ dTi•C’L$†mwl}kŽa‚Jd•°ðp¨A€™ð/ü3WÕDOKøÛø {Â)ØC§MF8•Cp=EŒ˜T-¤€R@ tO¸/ y0Šîé^îtçH2Ýýðt¯÷ž`B1WF† ±ähÏÁš4óÀÄ -?øŠëXhó¡-Ȣ˕µ„€1ÅØ]+kºÝ5«¡5uågŠ—zgñgWʼò3#,ên§b;Í…¿¥t«iû0¦«{¥Œž´ÓüI&÷–~½u¿1Ð’_úþ9K¡(*}aLemûû\˜’$ÆnßjçqZ¹$G€Õ&.ŽU ÖI6ê°6–e|ÕAtÉ}ïd™tÆÔß߬Η®˜TJª@/bL)ã" §1+éö*æøìQFü(i­Ou 'Å#JŽ;¥øÀÛã6;àZª«CjÇZIQá\Éqt\ b)vŸ¥GÕÆËS®%ìa¤9þÅËò°Ýœ‹$Óø9/Íx³ª+Å0•´ÝÖc%*’éK”n]„1¦¨”Q) ¤€R û d6jªkBq—»4Ê0uÿ‘ò—`LQ»«ke Û]@9)ÆUÇ‹Ršq5–Sñv&ÚTc\ì$¹¨úÚ)´‹úöaL!«»[ú£žZ„iþº Z´&D¬ëÕi~ZÔÓÄǃK³¥WÝ,•Y‹ÚÉ…1å¯íÌGŽ„1ÕØª’M:³‡hßF=¹(óDa§€ñaLS}ÂÑ&¤nQÉ2é&Œ)¿|å¢, c*KIê9B ôÆtÞonŠC‹‚a0¾ýv#&=JÀlÈ”eì X[Oªƒ(¥ƒJ‰®• µB¨!,©Ñƒ³ô¨r‹1áÇL’é±™«£1þÎþõG{âº-捻-;ßÿÓŸÿ¬fQ ”LL_<èà‰ó7àwjZ⇩dréqú©€G2~l`BÅÃÔOauz}„1Õ×HGH) ¤€R ªI¦;FNå$Ÿ;ZÃÔ’ŠŒ)³ÝÕ·²f°µ&ÂIÙüÓ{¿#áÀR\Ô;¦ÔÊdp¨m˜âŒêUûCOz#³·¬ôë,ýM,ýXK=Rú˜ZÒÜ•ð"˜êaL)³ŠhÓо=ôäÂèDagOÙÖCl«qârÄ-…,ðY&Ý„1•°Ñ#uQaL]_·n§=‡1û››RÀø–bê¤>o)SœûÙº;·TGÑq±Þâ#mû!üTñ É ê4âT©ŒcìF¥,ÇgéQåc2’iìŒÜçÃÔÎfS×.€ ™üê·Á‘¸¿ 1L(¹bf$j—[ÙÄ0³$‹–kaLE+1åW H) ¤€èº$™n1E S;ÊS¿ì®ZëWkÜê$TËŒ+%™FÛ…1¥ÕG>±Óü)N³1³×/ýÇZ=‚+%•¾0¦v´~e¸¦0¦zSúŒ!Ú7´rÁ1õ' FlÉ–ÄÙÀšqù…–¢­M–I7aLeh7ô ùQ@S~ÊB9i©½‡1]zS xtî¥7!:Ll`l€G5ìQÂR·Ï»Bœ”Æ'9}”Üx†Ì åÿ˜,=ªœcLQ’I SKI]¬¨ „H&1LE-È‚äÛ%™Ä0¤ÐŠŸMaLÅ/C=R@ H)ÐyB$“ü0µ°<Œ)«ÝÕ³²6mk7®Ö.ûLBU  ®U†Ö6aL Fõ`¹ïȉ ÿêoö©XÝ»Qúþ¢_UaL-lôJu)aL©“Ó|…\­9qAàÿ¯QÏI¸RÄyd«Þí¾N–I7aL¥j@ô0]W@S׋@h=‡1 ¾ôÆÒß"4LiäRGÑíÈ€Ù<'9>“â<'œ$/J Ü›¥G•ŒÉ%™Ä0µ§©ÔU ©€‘Lb˜ Y~EË4I&1LE+·"çWS‘KOy—R@ H) º¨€‘Lb˜Z[ À˜’ì®´µž“ÝîšÉÄê8R¢eÕ‡TĩԟnÆtø±IVw”þð‰ þê¯÷Éduo®ôE)e3ª cjm»Wž« cJǘþzŸhûæ6hhßÐÊÕ4qqMYbd•ÚX·u›ñœeÒMSyZ=IÆ”‡RPÚ @ÏaLû|âÿùägLJûþÝ~ÿŸÿëÿN9 ÓWŸ>ã¥B(ð?ÿé³ÿûÿþŸÒ³ú_þë9æ©u[Þµ´iû{mø1ö÷’}K—í¿ÿþG{¢›Õèö–ïÿéÏîïÍt¾(ˆãGÄ èšß\šþ»Øö†~)Ñ|góÆÛ‹ú6ôþaéõmÇ›äû9”»‚( Œ© ¥lJ) ¤€9T€$Ó7>|Õ†×Szï0¡üþÃr˜ÿ|f S+í®2®¶Mÿðÿcº-æñ›n¿/ôÓH¯u÷ߺQý~Ò·Á&›åÃ_µíñ a²n_&ÿëûË¿ßïS®_ññ?*ý÷¯–0Ÿínër%Œ)cªÛ|ý§¿ø?þáŸ>ßÄõ^köÿëÓ$½ƒ¤s¬Êÿ¤[ë~cº’h§˜ک®®ÝEz cÚ¾}ûìÚð”Pºýž‘ÑÚSb²”xhä–OŒ íÈúa§ïyg{ºN S\ݺ ¬½ñÿyݤ‡R~b˜ºP.%½åš]÷_õÔ~ö¥Ù)õM SI ¿%Œ©ªëžR@ H) ¤@iX¾iäÓ«ÇŠajaö‚ÝuÄè ¿¹ëÄ¢›I›°…â—’^U>øàƒÕ}Ìø)峺£ôQ ]²”þÒÕ›…1µ°m,Æ¥„1¥–Ó‚ Ü&nâSÓòپͽý¤<´Qu›š1geÒ­?aå²ÇÆÔã ¼ß[S´Óý%è[)«@N1¦w¶ï9ý/þøÈÙ¨ç±Ù–¦ò¶äz²düiþÝsLjÍÄ0©ö´P`Lwõíµ~ל¤ú&†©…jëR{„1©H) ¤€R  Œ]½ÿ˜>SI’ E~˜ú¡npjù슓WÜyÍôÿÑ·¾¯|V÷‰­I?®º7Êí(w”>ê@nsؾŒÉS£õ¿xÇ cj¤ÌÞxç÷íû¹õçÊ¿ÿ·O"õç ]<7§“nT +º¦€0¦®I¯·WaLÕHa]|CëÖÅR §=ªÑg×ðH¦7·GI&1LímJuõÜ*°yùžëÚ³jòîßmgÄ0å¶Ü š±Wß™üÄÚƒví^[ßÄ0´Xó›maLù-åL H) ¤€È»›Þz+6¼ùx¶P,¹V•_±Ì}us»öÕ]·Ì> ˈ…?«{pùh´V”cB¹£ôQPÊW¾éO$Œ©Ñú_¼ã…15RfùʶÍåMýl/l±Êé¤[#CÇJ®) Œ©kÒëÆíU@“0&)аyìQù®˜ØOÝ3ú¬?~ôg—dÃÔÞvTW/ˆ!²D SAÊ­¨Ù Õ71LE-È<ç[SžKGy“R@ H) ò­\1cÂÆŸþüg—·ÃÔ¢+â4jJžéЉ©25Z1J†1ÑS:dÆÔhý/Þñ˜)³|bLðÃÄé¡‚:dÊã¤[#µBÇJn* Œ©›êëÞmT@SÃKÉFàzœ&ÈcŠ®˜˜À3½³ÝH&1LmlAué|(°{ç¶ ƒ ½ýÊÚPŽæ^6hkßlÛid‰¦|]±s1dÞô°ú&†©Ø%ÛÜ cÊmÑ(cR@ H) ¤@¾0WL$™Ö¿ñ°‘Lb˜Z[tMØÜr{йb"ÈÒƒ™­%Ø芉©2 cj´þïxaL”Y1&sÅT\‡Lyœtk¤VèX)ÐM„1uS}Ý» ô:Æ„WcúðxéÚ]«6¾Û!´2ÖrPÜ(ôôËbÞÆe—v]1U2á2 ™Ä05!§N)œ/=5bÁ̓c³ ¶ “ûÈ1L…+âf S]Œ Ùþ÷þ(†)‡ÅW’, c*IAê1¤€R@ HN+`®˜ˆ1xþcýé’L¿ÿð£Nç¦Ô÷+“ÝÕuÅT2‡L«_y{ñ‹o¤ÛB›˜]ÆX8ýšYl°-7ü6wA×SÉ2­Ýü΂Õ;ÓeÙ°õ½?üñO¥n«ôp{öcj¤¼»ûÃô_M–_VsÍQÒYæŠ)Ÿ™ž_ÿ&RÁ&Ý©:V tYaL].ݾ] ô:ÆÔ.]u])ÐI\WLŽC¦NfA÷’ÝR Ó#÷®„—çN˜:x Ò²{79ø ƒ—&î‡s&æpÏÎÕ}Ýʹî[\FR@ ôˆ˜z¤ {ï1…1õ^™ë‰K¦@Ô“2•¬ˆõ8õ Ë%|€%mí› J {à tË„st×ÄÃð-3ò©Þåõ½+D  öº|@¥Ù›fóP°M œpLß¶>&9dR5j½˜Z¯©®(¤€R@ ”\XWLrÈTòRï÷ãźbbµ‘C¦~«[€ D]1 ,@±)‹* Œ©QÅòs|¬+&ÎÉ!S~ŠI9‘mU@S[åÕÅ»§€0¦îi¯;Kþ+ðá{n9xÏ yéê/ìùù^{.úDð/ö`ø¡(»æQ –À*aÁ&7f¸%üK/Mø–„“qNeIÏ×b€+KrÑ%z`ÂN|‹mFšÃ_&O-΄.'„1©H) ¤€R AžÝ|Ökbz`ù_Þ»ì/ìßkðb:¼WxõíÉVOF­ø–ñ/~Áöìþp{¯ѓωòµ²¦/·Ñ«þÁö nô¤*zè2* Œ©¸¥ŠUîœB:ë/½dÿâ+}¤€è„1õB)÷ä3 cêÉb×C—R]›<Ä~⥥|8=”HR€Aâð­ùd†Šã_| oL<Çà/cÏáHûJ Kì LÂñ†.a˜xÒK†:ah§ k¼°†úHV* Œ©•jêZR@ H) ¤@Ï)aÔÊOôÜcëû§@ßÖK²¼û‡Mý»ŒÎ.¤[ßÒ_³ëþBæ^™–é c*G !À¤½¦€0¦^+ñžy^aL=SÔzÐÒ+ Œ©ôE¬ŒS˜ài ß`Ü\.LÂßÝ;·câ]1ZbŒ9R  àZ ÃÆÙéØÀ„4xÚ`D‘Ã~lc'ö4q"ê( ŒIUD H) ¤€ýP@S?ÄëÝS…1õnÙïÙ#Œ©—K¿üÏ.Œ©e,Œ©娧* Œ©QÅt|AÆT‚R6¥@]„1Õ•HH) ¤€(˜JS”z) ¤€R  cê†ê…¿§0¦Âa?@S?ÄÓ©¹W@Sî‹(S…1e’IIÒ) Œ©tEª¢˜T¤@YÆT–’ÔsH) ¤€¨¯€0¦úé) ¤€R@ $* ŒI•£ „15!ZiNÆTš¢ÔƒÄ( Œ©ÕBS9ÊQO!U@S£Šéø‚( Œ© ¥lJº cª+‘R@ H)P„1•¦(õ R@ H) ¤@7ÆÔ Õ OaL…/Â~<€0¦~ˆ§Ss¯€0¦ÜQ¦ cÊ$“’¥S@SéŠTD„1©&H²( Œ©,%©çh¥»ßÚƒ™þ···òšº–HP`÷‡ÛaÖüýGoI!)Ð „1uBeÝC H) ¤€(­˜J[´í|0aLíT7ïׯ”÷Rþú£€0¦þ¨—Ÿs…1å§,”)ÐI„1uRmÝ«ƒ cê Øº•h«˜Ú*¯.^P4Í_Ђ+f¶×ìºÿ®¾½`Ù,fö•ë¢) ö­h%¦üJ) ¤€¹R@S®Š£(™ÆT”’jG>…1µCU]3/ cÊKIô/˜ú§ŸÎ–EU@SQKNù®£€0&U)P„1•¥$õ­T@Óü­TSת£€0&U‘Ž* ö­£rëfR@ H) ¤@ÙÆT¶íÈócêˆÌ9½‰0¦œŒ²Õ„1µDÆ®_DS׋@]Q@SWd×MÛ¯€0¦ök¬;HÎ( Œ©3:ë.ÅR@ÓüÅ*¯‚çVSÁ °hÙWûV´S~¥€R@ H\) Œ)WÅQ”Ìc*JIµ#Ÿëßx˜1ðoÇÅuM)Ðe„1u¹ZtûË÷ß’I) zMaL½Vâ=ó¼Â˜z¦¨õ ¥W@Sé‹XØ„šæoB4Ò¬˜šUNç5¥€Ú·¦dÓIR@ H) ¤€ ˜TšP@S¢•æ”Ñ«þ`¦Ò<‘D TÆT‚ÚðÎö=@n9¸¢GR 1„15¦—Ž.Œ˜ STʨ¨£€0&U)U@ÓüªT@SÅÖ­öìQû¦Z ¤€R@ H~(0uýQ£V~¢Щ½¨€0¦^,õÊ3£ÅÿâzY={™ÆT‚ÒåôŠR) zMaL½Vâ=ó¼Â˜z¦¨õ ¥W¸ýõ©ŸZúrÖ6¦€¦ùÓKG÷KaLý’O'7ª€Ú·FÓñR@ H) ¤€p˜óòɘT#U`í®ûáÇk÷·7z¢Ž/+_»yí®Jð z)£ÀªÉÞÌÂæå§À pzE©½¦€0¦^+ñžy^aL=SÔzP) ¤@* iþ,ôî=²0¦îiß“wVûÖ“Å®‡–R@ H) Z¥€0¦V)©ëH) ¤€R@ H)Ð5„1uMzݸ½ cj¯¾ººh­»wn›0hÒÛ¯¬ ]ù¥§F,¸ypko§«IÂ+ iþÂa‘@S‘J«yUûV‚BÔ#H) ¤€ÝS@S÷´/Æ×îZ;aÍ„bäU¹lµØêKêzR  L<3 «F 冓¹È¢2QOÌ¡°P”*ÄzRé{)Ð3 cꙢîµÆÔk%®ç-¶)¬ÒÜËáÛb?žr/Z®€¦ù[.©.˜¬€0&ÕŽŽ* ö­£rëfR@ H) ¤@ÙÆT¶mõó ¸o@ß¶¾V_U×+€(waL('e±qRX%L+`r¡ñKêŒ.(†éÃÝïEo¬BìBaè–R ' cÊIA(­V@S«Õõ¤@Û@Oô‘û¡ŸŠ xcqd ºhŠîyî)È©m%£ çXMóç¸pÊ—5aLå+Ó\?‘Ú·\2'¤€R@ ä]aLy/¡®æoЄAûݺYl™7ÛCñ|°€Ð0|‹mQ/]-®VÞ^¸@°!¡¬Q Æ6ŠEŒ¯p'üeqó+$ÔVæ@×’íQ³˜>Àägð—SŒù?tÑÚ¯™…ö”FóWE‘Ýõ™½èŠ)©—Ý;„…‹âÃa6a¤PÍë®3¥@ÎÆ”óRöšU@S³Êé<)Ð 0ØØ¹Ú[ fè}¢cŠ=„à¯uOÑ‹ÅØckßlâùHØÀ’‹näZ÷”ÝS@ÓüÝÓ¾ï,Œ© ½›¬ö­›êëÞR@ H) ¤@áÆTø"lçl{oðÜÌ x&P,ïýá=À+柉ßbÁ&ÐË2dÈý*ŸþgíZ$(ßOŠO±žË ¥ V‰™G5àJ;ñ×JܧŒiE?ÀÿNŸŒéý@ìë“K³ì‚µýHc•lÁ30Æ’ã\fHº`Çhf¡íEÒø –ἤB$¯†P œ0²‰$Eóh\o! ¢€0¦‚”²Ù¨˜ULÇKn*À®'»¡H$ë1®À6»§ lŽ—ì[€~*(}¤@) iþ*ìî<êî·o}w6ÓÂ-çßշ׊7Ù|Ûlé®eU`÷[{Ь1ͼiƨãίîÙµ©¬Ï­ç’R@ H) ¤@ËÆÔrIËtAƒT\>‰è>³7Í&¹ÂÀsL 9d¹~Å:t(€2 hÏRDŒÉˆ%Û`Yó¡@/¡zÐ Ü5ÑSWCñ1ܳmÛ6ü[Vˆ •\S®~׆³`©³AKdb8éDtË„frU|Ì æƒ¸¦=©±…ˆI".hGirV sF+»¶Hè¼ÆFM.Ìó+£R  „15!šNiD€J¿[ö —¢ û…15¢¥ŽÍ À‡ìü1^ŠM¯.Ïp "¤€R@ H)à) ŒIõ E¸ÛÀ„€ªZ†ùgÂ6¾5~…H<>ã'„1õËÂs DÿLüGòß ¼Ø@îžÙ³½ŒáxB0ø‹m Î º¾eûy¯Áƒ#?ØÀìʼ¾rïèn‡.‹¼ñ^6£,y8ÌuÄeè ×uËD]F°Y¨ÁŒùw1&œQ^ذÂ1ÂsññMC^Ùö° ¬Ä­ °Ç ÑêkEôú–[Üwä½Pô¸¸•u´¾¹¼·CÙÆby¬B˜2ÖŠÎFV‰Þz0YÀeÏØ0ÿ=øì vâHÒ0šYèLÑd¿ Y´ôBÄÕPp(>zÛb4Naæ(û½t¤…Q@SaŠJmLaL饣¥@0VÉVN˜kPŒ.Ðeg”94—¡ì›ÕÅüëÖR  cê‚è=wËg7Ÿ‹1aÏi¡î€3|'LÑtÇQ¸¹n!¤€R@ HÒ( Œ©4EÙŽ¡›%\àZ° µ ºúdâÝA;MX`FYòàrôTD¤‰¬È#ZHÑiÓ{ï½Gd‡‘J!ùPÉHìáÁø‹cð/X"lã\|H5…®ïfW#=ÃÓ±a>¢ìØÆ‡Ã;F/KR‡÷-ÆdÍàq”ˆ¤š§Éâ¡tÑ„¢'¸†¿ 9âÂ)2²è±A‚Í ‹z’ "»†Ã¬hH± ¬ÄYjø—µg¹erÄñÑë[é³¢°p¢}DEë.ÅÌà‚±—µ13˜²49ÆX%w³ X29wú€ûñW3 )ìwá¤OR!â+À¥ì¤—øÿb' T«Ü³K­#¥@‘ÆT¤ÒR^P@SbéP)Ð]È*!ôÆ—K膮„HÜOÊGÒ,÷(¢\w‹Owº£{oÝ5Ö!“\1õV%èäÓ&9d’+¦N–‚î%¤€R@ _aLÅ/Ã6>À²)æ0øìÚbØ 6p’ñ.ód)ó´ä²M¤”ð—°¯l’°séu‰¤ˆ‹1qO4 [ôú–as… òv¼ ý*…ãÁ¸;Ý….ëâ5@^Š…1Ñ&ðItÄ…Ü/±J`5wÿmècä5méE‰EF/VÐ–Žšè+Z±“+´eÞ¢×·<[=‰^0Zß,È$¶£—ukqº†ÄÑÁíS€¬®Ož ó˜kà”6ð-¾â$þ2ÒœfÚWÍ]™³?é…ˆR¶"”µ;aÄRÖG H* Œ©„…ªGòƤz ¤€åU@SyË6WOuÈ$WL¹* ²e&êI®˜ÊVÆz) ¤€R í c‚SÕ¶ßF7q Ðÿ ¿èã¢'æ¢ p’‰^‘Ì÷öðDóäÔÆÄë[î\ŒÉ½ ë{ ó0sÃÃ̸.ëÒ0Ø.ÆÔ ëú(²ˆr.„m:å'DÐ-䋚71ÙõÝŠ„íXŒ)Tßp={±ÒF³íbL¬ T·R@ H)ÐÓ cêéâ/óÃk¸^æÒÕ³I) z]aL½^:ôü!‡LrÅÔ!Ý{ö6Q‡LrÅÔ³•A.¤€R@ 4«€0¦f•Óy-PÀŘp9PJtkd®•EŽ ïǯ,|÷0ê9eq $^-t}÷I’0&ܾÂé=ˆ.yŒ¾ ]ÖÉèi-¬D—p1&(I@Í-,F‘+F„ˆtQ´ \êˆ×ŒrH,,œ½¾)šâ)ZßpÑ%ÖÌèeC1…1•¨æêQ¤€R ¯ cÊkÉ(_ýT@S?ÔéR@ H)c„1å¸pJ–5×!“\1•¬póø8®C&¹bÊc )OR@ H) ¤@ÞÆ”÷*uþ‚Ø#2xœa(€NÈàÒBøËãIq'90L8—aÈx þ;‚¼6ð1÷ú–c•ìtRS8€ÐoÊgøXc/K¦Š¹ÆªË.Æ„¯PŽÔ™…ee’5ÙIªE ÂJ“á۬ȬPXj¬¡ë[®\ŒÉª%«A´¾±½â¢—u÷c*uK¦‡“R@ H|( Œ)å \´\aL-—T”]Ràý·ö<ñ›=€6ô‘RÀƤÊÐ)Ì!“\1uJòÞ¾ëI®˜z».è饀R@ HæÆÔœn=~Ö¶wg÷mûÍ>z«­:¸±ÞÚq£6]¿M—m‡Í]sÆÆã´f©9étV€a3 »6 «Êb’œ’H5D ô ˜z°Ð{ã‘…1õF9ë){A 3ð®šxi/<«žQ dU@SV¥t\  C&™5[ ¥.‘E:d’+¦,Zé) ¤€R@ DƤJÑ„}[/Å ïÝ?ljâ\RtF­üÄk*úS(ÿR ^gî÷, Z ]èúÁé!¥>R@ ôš˜z­Ä{æy…1õLQëAK¯€0¦Ò±° „15!šNiV8dºù_âo³ÐyR èIËìÑLÇJ) ¤€RÀƤÊЄ˜š­4§c*MQêAbÆT‚j!Œ©…¨GÍ) Œ©9ÝtVîè-Œé¦›nÚK)Рÿå¿þ·M›6åþ·¼gÏ;ÛÏú§½–ß~F²ª,JŽ) Œ©cRëF{ö¼õÖ[ÇŸôü•R  |ðÁÇÿ¯Åè¢t@ÝB H) ¤€ * Œ©AÁt¸§ÀS‹ÏûÊw÷zý5’£8þ¬ÿûò{?Ûƒ®GîÞšyïÉÿc¯·–<Ñ [Ögüൗ=3ÑØëÊú€z.) ƤÊQRz c:ùä“oºí®­»Þ§ïoñÒîo»ëØãNÂÆf¤×«éÕ×w{é5¤ÅI/ïøw7mÚþž¥ÛßÛ¸-H¶½ç§w7l}w½“Ömy·’ÞyiË;/mÒÚÍïxéÕwÖéí5¯¾ý"Ò+AZýÊÛ^zÙK/¼üV6½µÊI+7¾µrã›L+6éù oiýÏ9iùº7,-[·kÙKAZúÒ./­õR_vö­Ù¹¤’¯Ù¹øÅ -zqç¢_÷Òê×:iÁ ¯ûé5¤g‘Vé™U¯yi¥—æ¯Ü¤;žvÒ¼;æ=´i.ÓsÛç8iöòm–f-ß6kYf.Ûæ¥¥[‘fXêÛ:½š¶Œ˜¸à¯þzŸiK¶ MeZì¥)^ÚŒ4yÑæO~úÀÙ³gç¿@õ|ñÏð¥åË—ç?·Ê¡è˜:$´nã1Lh{ÍЃ:H$“*D»Ãôõozñe×£Ö‰dj·Úº¾R@ H)PJ„1•²XÛúPèx£ûNøQG…y[ïÕ­‹¿çbï¾víÚ¾¾¾ne¬ë÷½ôÒK|ÊY_ûæ¡“'Oîzfú™%®Ršøª—ËºŸòñôªEë«_‘E«ˆ%ˆ<ûf¢Ãd&*hñ)ÛR ¿ cꯂ:?§ ôÆP ”Rlºtã­w}︓ `r饀©–^ɘ* S"À´Õ&l´aÚ†)À˜<†©‚1ec˜Þ3L>ÆTa˜°Qe˜3ÕbLÃTƒ1 “‡1y Sc &cª2L+ë3L`LÃäbLôuZ_cŠe˜ „1aºìš¡ÑæömøÌçE2å´ÁU¶º €0¦.ˆÞ‹·ô->F?1íðÃæˆdêÅJÐÁg¦qêŽûE}{rö2¼÷E2uP~ÝJ H) ¤€(‰˜JRz Ÿa0iÎrt‡þntÉH¦mÛ¶1Zñ?QQ 4pàÀÁƒï·ß~…XíÙÚz†é”3ÎÇzà…«¶ô/ý%™bnm†S®> E‰P”±‡ 0Å6’˜¶ŽåV7ꀰh}N­ÝÎ[ÈLÔNuum)P„1¡””Ç&è=ŒéÖ»\7K!béc¢×¥ã%Ï S*½’)‹&xcrœ0½ã„)ꇩ℠ޘ2ùaê'ÃTqÅøaê'ôš~˜ZéŠÉŘsÅ´´ÆS}ŒiQ1¼1aºüÚ¡KÃ’mΑLM4†:¥¤ c*iÁæê±<‹Ï<úÄ\k‡GÉ”«"*Uf<ãÔ·»ãþ1Vßž˜%’©TE¬‡‘R@ H) :£€0¦Îè\Ž»€a oòÜçØ ‡ÉôÖr‘L@[ÈÖÄbLpÞ¢…E9aÂÛ.GáÖ} 0L§žqþó»ë‚•[ûI2‘"êú'c:t(&æ ÔZw‰«®KÔ E«¥,3Q Q ú«€0¦þ*¨ósª@ÏaL7Ür'%7Yœ¸ëo¹SðoZbü8×ñR€.ÅÆ‹†«ë)5\À0ùäV[ 9l¤Ç’kÔSó S+ÂÉ5êŠiùöTŒ©Ž+&’cP¹WLù*G† ~¶l:~³f-^/ŸL9mt•­+ Œ©Ã‚÷Þí‹Ï“s­†EíðCÏ–O¦Þ«mb§¾ñ­Ã†Ý?&Tß&ÎÉÔvñu) ¤€R d c*Y¶ïqÈ0M™ûÜóë=ãÛ2c ïÖ{š÷É:Œx |°Ì$Â6üeoA'ôbcÕî ã9í®óŸÛòÕo2iÒ¤&Í´…˜ŒÚF8,¥ Ý¯Há«BÜãV*ì!œD<äáB{¬"1vAîQMM<©Nɳµ­7eÑÊsa%å-j&¢¿@6S2±L•g)Ф˜šN§å]žÃ˜®»ùÎ;%÷_|{Ì÷Oä/Bœ¥mïm¬¤ Û€+1½Kn ¸’›Ü°qièR„^ Ln¹4LÀ´î—*˜ª“?½š0Uœ0a0Ä’[» ‹KÐãñÓNÎ--^³sñ‹AZôâë^Zí¥…Nj,–\£~˜žK÷ômæRÏÓ K!†©Ïc˜j0¦Å[¦.Þ2ÅK›½Ta˜ˆ1ó”[¦`àòðËö¦ën÷JܦÏKŠ×OEM_´îÓŸûÒ¢%KÊ-Œ¡eUI«¬0BîÌ¢ ¼9xFNh¬Éø±åDYŽ…{Ç£ÙB%n¸ƒù,´cg®{³¥l ®ƒû¥€0¦~ɧ“Ó ÅgìSóB6Mÿí¹/J¼‡›uà—¾ÒÉd†ãÎC´©¯»Ä­b¡í×Ì?>IÍ{Cšpy´‹[^j4NÝùÀX¼÷CKÙIC}{|úR¼÷ׯo’dBþ;S ´ÑãÅj3.ëQ¤”KR}NéK´»Ð[^‹tA) ¤€RÀU@“êC]* Óó)ƒ>LzD£$ˆ³aýaP&f†Úk¯½6…¸dØx&‹þ†‘#¶éN‰“Ñ'ØÏíƒcÈ»ØÄQO4¨ôð`ÊP˜ºÒ•à0L§y~Åî†<`w}zùæ¯|ãqãŸhôaMs·Ð©­•]¨ ‰£ñFt§äzÌ≡€€(;s×äÖlÂ~#ÕpM‚tø`C S£ÅZ¬ãÛgÑ2çp¡ IÛ ìVÓ ÍæÜoæB6yšnh]W C«i®™ÓC©ƒfÉ~š‰lf$ÿ‚§˜õB¿J{(Ò½î4“}åÎvY¥µæ±î„Qh‚©¡f!£•5ãa ݺ­kj¬­òV/.Œ©CBë6V ç0¦ko¾3N"¥tíMÆ„ ‡UªC,‘^ qK £Kµî—2ÒK«¢ôRƒ“OÙï ;aª˜‚NOÀ”î„éõ/¼†ô,Òª =L¾&¤ù+wiÅŽ§4oÅŽyÏ#mGšËôœ—æXꧦ ÃŒi8ƒÊ%3L±(·NÿR#÷«0Lo¥XR@•M_øÒ§?÷ņH&w}o+ûC£‘6iÂUhè#"cEg'™êÎÁ[žÍ^c{Ðé´El0-a»¹É]æOA»@öÌ·IÏž»¬0¦ž+ò=°Y|̦r‰›&°´ÃÛÙÉDûNkñGZ±c5Š6õI¿nVõ‰ÞêÛàͦ>É>›]¼nhé E£Õ9Ý2NE]0›C}7­ïSŸûb$ƒ4 ìÆ>rl}cô ¾aqåjy"¥ª'•ëCôÛ¤¾D» ½åµH”R@ H) B <»ù¬»úzË.ª:ÐÃôôóî Ïõ¿ë úüõœ7Þõp£$“‹1‘G1‰]ed5 ÆÄn0¶’‰6×X`ّ͋Ù&[#ÃØL™´Ù4Y¸š;²¡5¸œ»­™½ ¸º7:7«ºÀñô}ÖTÚûÂmYà¡,Ù^ŸÇ„žÑjЉÃÇwÛ^Ûæ¹ö aL¡+à")š„²áŠSÿj´vÓ8u×cclèWáÕúöÂkc§6C2qòõ\×­o¡Š‘^ßøÔ ÃDà‚KH+¼•Ž•µí±ë³|Y”ö[pK$TÕí^¼>k)».Vñ¬'ªc4ª²|C7mk¡7ZIt¼R@ H)Є}[/ÆÔ„n=rŠÃ0Ń,tt†‰ƒ¾†5F2¡3ɱ{Èø‹¹ˆÅìrY0&v¤í:貤‚ø–CB.W@?×dP9ëÍRÃcì+f,4{ÝÜ¿ÂÕa:Ëc˜ê.[ÂòÝÙK_ýò×óÉd%k›HÁ˜XO &ŽÄ ÌÑ=+[¬8˜_Yl¸Œ‰0œ;ÀÁ¹ýñ)R¸ï© ›E+“…¡q‹–kH‡°¬x48˜ÎhI¸ßZ0~åú·ÆWöspçÜŸIOœû°!3QR¤ŽÀ,Ù¸™Ê»+±íEbu´Ã&}\ 2Ï9³Ã`‡!ÛN’¡‰Wà·Ì›µx¬®!ÈÌY¡¹·RÙè/Ü•õ Õ4ìq5 ÕsžîN0Ùƒ„ÚR›£®,$­k ÉnfÕÐT®2½ÚC™Ô|‰G‹ʸE“dótí«Vš|R÷t÷ú®yÖ}Iõì·.Œ©âêÒÝT ç0¦kn¥”ÖNòù¤knvô±'F]+qÏK[Þ©¦Íï€U²T-Õ„Š{ÄSˆ[zñ•·k½.…Ñ¥Ré%]Š÷½”?ŽAŽÃî—‰¬rý˜úå„)[ 9—ašîÄ’›æ8aÀÄ4|‚ç)…aÊ¡7&aºÞa˜".Cµ§%šOyvmv’) cb?iÐ ‚®ú@<‘]:l`ù²=6f6ÀˆŽdqeןÅmc;…ÿX‡’¡»³¯Él®çb³ŠÎ™M퇚d7†:™Ëe|KZŸËž¢÷²«ñ”Pï¹›ÍÜ[St“ŸÇžš—fÓ¬Z´=g„h‡ï{tFC>™Ð¬Ñm‹_­y¡±2Ô ¢mÁñlޏÁØ´r Í5‡Át$ã~e­™™/Ùbóv\¨ä2.¼>ö[°´A„ÞvdñhI7#)oÍ’=¾â1Ñg´’g;ÏÖ†ÌØÛ„M7vR®¸²ü›a"t¤IJ6h}na} ŒSz SȆîv"Ú êÛ˜)KòÉÄBD¶-0AÝú­)õÍ>¡ZįP¨¿•NlyÙ«–u½‹ØŠaUÝnmÝ›b-uP¬¬',JÎôà_[Ýn7uªµ…ÞÂú£KI) ¤€) cRõHR }Óž~>´€fÕ¥îB‚còÏÃßüõÃFe÷ÉD´ÝH")Ì ¶Ù©æD£ŽqÝ YÏýU|È?áÃE€ØãÌÙaæ•y/žË›áÄ‹¸_á›FÅ‘=⩆aJˆèí.[BéÏê{¥!’‰CfÚ'Yè,…”‚渕emCiŽYl[v8†_Ù ½Õ»‹;Š1FŠµÂ½”Š2)МEëþF,Z®!æzƒ–\%m Mà Ù÷€qb_…<—©t2>KŒ™(ÃôPCf"Ú=ðâp'2’¬Ž´ïY»²Xš†íÂ.f<4CP’¡‰76pYN$рÛš!ˆÖ›2aC•ŠùqUiküØêÚ›Ô- Ø+›`²‰ÁÌtF_eœk3ÑøP4Ør#d¤BøÛÉbz =8N¡õ×gÑD¯oMy©)ß)QãÏÕÔXÆxó‡ cj^;™kzcºúÆ;jh$—LÚò¾=ú{'º|R"¨DK5n–ªÄR,´å–V».—°á–Baã¼é«DzéßK½”!~\ß/nnÝrô™l ¸ŒŸBÈE£È­¬EÎ$W"‡mǼ1ÍBªøaÊà„ik Ãä’{ÐØöž²x3}/EÓ'?}`~¼1Õ0L¡±t²%1û&Í_»ÿg3ùdâ#Ô-s»)ìŽpû[<غŒØfÒí²K„l;Ñí¥Y‡¦n§Ð½—Í,ZNxw\„'æ{ØÿCW,šUæ6¶µv{¥6ø7×ͦ³½—]GºÖŸ\¿Ê”9aLe*ÍŽ„JlÏ‘=ükÔ©e ¤)½B’&IÙH²²5]së§j]1ùS0ƒ‚úöèäÅxïgŒ.g¢ÓS·¾™aÂ*FJ}3’$ŠÖ™¤òbM ½R£%‚ Z². «±Õy^ÇìõÌ?íGn=g_"zS>TË ½éÚ¢¥€R@ HFÆÔ¨b=r| Ù!®ôÁìYô]wGV’ÉíçSXýùÌ[ûrå0L.ØÛiW¯l‘eKóW옱$ÓÁãÆ?Ѧ¼¹€–ßÂ]Ôò‹ë‚ùQ ŽE+ÎÙs-޲ùA‚xlíu DIȦ¤[H[æGÒÎç$l&J™ò'ïš6Ñ¡Š åBkdŠÕÑ,oÆÄ°|] Lh¾‰æ›ŽáœQº¡É®Àzåšzl®Š† ‰+‡À8ÞK+­~vãºY²Ë²pùD¬Ìf§â-\£¦µnõ&¥gUžâ,÷›W`%·{ET†1™z6¿2½º¿&Ì£[4Ñë»%E˪íq1&^Ü5 ™é8TôöŒško‹!Œ©½úêê]S ç0¦«n¼#ì9É ‡o1Ÿ¡”*Õ°JI¸R•X‚Ë¥—-9qâ|h)™[ŠÄŒËæxé9då&×÷’·jß’·|ßÒξµz©?ޱSãǵ`ªa˜–o¯‰"˜¶…£È-ݚ䄉ä¼ä3LpÂ`L SÞ‚Ê9 SÍXš«Áâ]2T,)Ò÷äÓ™H¦hÀöTÜž¥áAè©ØZ.wLÂéCûÊ:I˜Èò³·gýEëù¹#–P·Ïºè`Ùt¾uͼb“—–Oö5ùq!}>»VìÌYGÖZåP¯ÿº¦œÐÒ%\$t/^'”á®5ù=xcaL=Xèm{ä˜UkfÎŽ·i.ñ`Óœ·bÇÜç·ÿnt&ŸL&¸t’&ƒP#lªû¬nãÃѵÛ@Ù(—-Ûp×m÷زv?îÂ)^“ËÙº²ÁŒ¾/BcàÐ1ö€n–Œ¦²á.³äfƵ ðA(ÛsüåRþkžÿðúp öòŠ^Á^+¦OLÊ_­ª€iÆ©ôúæcsxï?2)+Édõ¦ÃïØú­Iõ óÝŠlM›©k‘¹ûæNÖ«¤òâ18˵rFK$Š1¹ÇXVùî}ùÊæïŽ= ;8tS«™-,ôVU]G H) ¤€È¢€0¦,*õÚ1Œ%Wã‡Ée˜âÒÿ® ú®½=É”sŒ‰¾1zmÆ1Ä0ùqšÞ¤±Ý\á&-[Âøkú¢—|­]$“YP[þ“ä@Þ\·üº`[´\ü¥ž…¡!‹VÈnç¬u¡ŠG÷3<2ºd(d&ʃªÎC¬™ˆ¨e³ÀÚ˜§ŒŽÒ™Èt8UDCeÈ"Gë E€å„vH.°ŒZ`\à±ÎwbÔÐäÞ®`; Ê¡aÇ Aô9Ç«¹u,Z©p–­ë³Ò$WŠ­ÉvLl=w'˜ìÈÐëÞ2ïîw­”Ì­R| ‡ŒTfà5Œ‰‹š^£yˆ-÷ú¡_ïeWŽÅ˜ÜÚ{}>‚;—×áN¯ÜNS¯”tÏ=gïaL7ÜaQÞ¢WÝpÇÀïpR(QájX%BKµÄR2´Tñ·”[ò†Oa¯KñèRÔñR8r¦1¾—¢ô¦ZßKŒZRã~é/h ý ù=¤jZ‘ÉSSR¹éN¹(ÀDLĘ’ü0å cò¦ë*±ä|¬þ·bÇÒ!Ö~ÞóÞô9¼[=1oMŸLèš®NÞˆÁP߈{ˆÛ£cŘð­uPlÛ¦ Ñ›D‹½±P¯×m‰q¢»Ì‚]F÷^œéŒÞèP?‰¾ ¢[/3úõJéź­Ö³öȼ/¨ ò]{» cêšôe»1,>0gucÉUÌÙ.KšbÓä îžG¦×.çnØ”¡©t‡|„A ¿]A†Òp 6×8ÀZ!kÉ9¼´ƒí:¡ÖÌÀ¸»-KB\bÃFÎÖî%¥í"ô‹1Åf‰·³7QôYÏÜVÝ |=áÃ76ìA\AÈê#í Iš¤d£Uõ>0N=P‰%ç[yï^-~jQ]ŸLæh™çk·n}‹VŒ”úæÊz«âß5eïôØòÂ¥`U±¯Ì¤ªü!ŒÉ5Ä >Ð0Š¿ôÉy)\™F.ÖUëKDoju¯U…®ëH) ¤€V@S‡ÏÿíÈ0MucÉE®ÀšºØ!vü¡dñ}Ë·_sûCÙ£Ëå_–É¡Ç0y> õ^0„Ô`Ãxê¢Mí#™z¤ ô˜íP lѪXˆ¿d¡ô²[´bñ[oƧ3"ãq›nÀ~‹~@Ó„Y½L“^æíúm&ÚÁBÌb&rÍ;´–cŠZ a¡×"Y¬&c ™c Mv‹Œ2i0\QŠ­T49†¬Ø²•qa›UÅtŒÉµ@í²ëbL–yºK©²›^í¦6¯-šèõ]5¨¹)µ—ºEF”Í~¶f|Ã45ÖŽ†=|MaLPY÷è‚=‡1]yýQ‰{À$ ¹Þتp’¿Óq§Tõ«*UX¥XKÅKÑ8qÞ0ÉMëƒY++nŠñº”]ªu¼äM¸:èRÕ÷R½Ô¼û%ûö<xN¼á=Ós† <0¹ÓŒ>× Ó–¤(rðÀD€‰Qä_ Œ ÓÞ˴±tˆµw\1Adã›0wÍ?æÀEK–¦´7\t…~ Wä4J˜øU¬‹#z-"÷chvà, {ÌÞ° ï‡òfÞ5Øæˆ;9Ôa.câSðúìfñôXŒ »^F’z¥ìµ»dGbÖ¿݈g±ïB«ßk·ÆÔk%Þžç5‹ šÞ‹ÛMó¥cñy1ðÛ¬Ê]¸b‚±Àk‡—m»ëáié$“5˜|‹e-*[QÖ²ñ06Ȥ? ñ`ë ˆ•µTtiÃAi¨5ã~A‰¢†LHlºÝûb½…°W^„ (ŸŽfæÍ "6Ô¶‡WæYöâ=#%ââ0f’¯ îw·M.^ŸYBþùFˆ½B’&Q©ív-©€4NÝi »…n}‹±¡W\UÖØõmù¶‡ž\„÷~Jt9CŠ]1íÕiåªoÑŠ‘Rß\YðÊæÛ™U—¯i·Î°\’Ê‹—r_µöq+¿û^æ)nþQ‚fƒ#®dõ¿«K¬E8׺4!³—kÆjIéë"R@ H) ¤@ÇÆÔ1© q#c˜Bƒ¾¤i~. ¹b²AßÕ·ÉTˆrg&†éÍ4†)Õî ‚ CþÉ 7}é vùd*¤Êj~ˆµhEVIí VåE,Z˜Íáêèì-×;‹é€6N®yŸËϸß,?<%JœÐÅN~„ídN:l&¢ÝÆLŽ”=Öêè–5ír±ìŒÅ˜lЦ•XCSCmžî´‘‹ÅbL|´¨Šæ 3BrRÉ = câ“Ù< ír|"×fvQ.û´_ ¶£F*Ͳ˜^í¦îÁ!ãXôúT‰Ù ÉŽzÒâÊ"¶Ò´"3[tèúÌåwò'Ó‹÷ÆÔ‹¥ÞÏ\c²Òl4 ­ cr½u•TÙƒo:æ„øüpÑHpßøöáD”˜žœµäª›îòG¼oÝ7jâƒ/a¶7 bÚðæ7¾uø3–`ƒS¡=iâŒ%þU&h‰1¹—9ÜR(`œ_¬&lz¢nòÐ¥ÇK‰‘ã0,?ç’«‘\÷K_ýÆ¡G}‚ë{ {ξè*×ýú¸n½tØÀšø 6’&tˆÏ¼`È?}êóAÚÿóÿ´ÿç=êxÌûÎdZºµ†^ª !WÏSÀ0™û¥þcL»v/o÷‚ S@¼9s™§Ü4ïÈ‹'#sÇ3W\ÆÕ`puñï]ä§ ïYèû ­l@½ñs^¬K2a>æ–É…¦ÍQêì~YgÎØ9Il*á+»¦ïöc×U`'ú:¡Q¯½šÝ_Ù)Øp[°hV±'öÖÑ¡—Ûíæ|¼› ´hÁÂШEË’GÍûVG÷»ƒt»B¬é>‹9<¦%f¢\9cäôuK+KÝ~vãÜ Ï¼Œé¼+F,³7ÿG§‡ÒÍDfA¹„fm\ÃK¨8Bÿº˜Xã Ùšù%dh Ù3™±èD’kGrmžföቱ•Š_ñ¾î\˜Ý ;£ÓâI¶ ›`ŠZ–B™wm§f˜µc\[nèR|ØŒ¦W{ðuÔŒc|ö¨…-jLf&M^ûMÅÚÐÜë‡r›ÃcI²$Œ©$Ù£a ãñ^pÛ+ÈQc""Í—J 0&º´IJøSÊ+}ײ•ôæÉ?ýÅß~â¿sœƒôäÌ%Ÿúì-W:ãœKŽ>ö$üEºwÔD×ÇÒ¾ŸøïŸeâpÖ¨ñ³Rœ-eá–jÑ¥_ÕE—N=ë¢ÇNOç--:åÌ‹~~æEÏ:‘ãöùÛ¿Gò‚Ç­ôÒÃO>³×^{ýìŒ g7D/™ï¥O~êów?¹­íŠÇ0];4X ä84F•ÀHã–ÇVŽ™»ñÑ9ÐIýÙ sYŽ_=s¼×O½Ç0¦ÊH£bI™Þ·uܬ՟¬ç“©­ÏUЋÓ?ª-,ÀSDWôÑJ›maL¥-Ú=->cžœm‡ÇÍÛtÐYãÇÎ݈v °’_Ý>í0¨_¶Ã´ø€â­aJ–m…Eí𰇦Ö.×χä~^¤%§³3‰Ìp5OÆkâHZ²B oÆÓsuØÖwgßÕ·ú é0¦¯ë°a÷Izï\æ{iôìõ¨o˜A‘ï}`L5õÍyïýŸLý—+?õ­ÿÏ¢+H) ¤€½ €0¦^(å,Ï0Lóžs:áÏ»~¸¥ƒÎ0Ls6`¬wã˜ô¡þ“ëçpÐwÏSkB üAß–!"™²@›Ž¹ð{.ßÏòÇÓ/†éTŸa²ÅÆ®ße˜^1þ2† ËHÀ0ýô†¹Ý;iM°ŒÄ&hÆûO>³á‹òÉÔ¦’Õe¡À3÷ï9ý/öŒ>+fJ±hafá±¹Ѹ¡’“aBõ¾rIJøá¨‡g®Ã¤Ú:aò1&—Òë˜E«ôåÜ3Ì’(AÑ`™=k=¦‡`&:ë¶ùœB‹ÐÖí|¤{›7uñ¤P9`âvsÓü w`Â|$§$ÛWQc/ÃT 2hiÆ0âXš# o5ØE“PˆÏ\ÂåÓQRDÊ‚Õ`΂ ZR ר™/|òÓu¢ËµïÑ ze œ!˜.ÒTЇ*y¶…1•¼€Ûûx´ø<úÄÜ ^ï’[÷&3g£F{ +"–ÂâãµÃ+kÛáŠMo4 ÐO]²åö‘SÚJ2¡½ ÑëíÕ+õêÀ@Ñ`6êC˜$>c›úCû”õba¦*Ãx^¬©o|ïÃï—…&»ŒuÀW _®oÎ{ß«o}^}{p¼÷ÛG2媾º¶(óR@ H) ¤@g Æô‡ÞêÌít—|*@†iÊÜçb}¾%6XŒûò\­ €µ÷,)ãµyì ‘LýhPtj!ÆTˆbÊe&añùìÃä·ÃÁ[žïqr%Æd«ÖhñÔÖûo´cB;¼hóí#ÚK2åRÚ^Ì”kŸŠ…™<†é›‡Ýqÿ˜¤úÆ÷>ŒS|ïcúdüü—ñÞ3‡„÷þN1m]¬ë¯à½ïÓÛm%™z±hõÌR@ H) ¤@a Æ”1òoaŸROS }“ç>—Ô § óÁè„ãï_ÀBÌÃjŠ1ÍãÛñ—M E\²„X] ƒäå7‹dêF=4Œ)fÃtÊç§Ø]Qú NH°Áî:áéõ"™ºQö=pOØ`¦º-X°:5F†+G.ƒE 5ö„+¦c‚§gXо!]óðsA8¹Šsq³0È¢ÕŸªÖ ™(~zfIÌÍ¡œúRÅ,¹¨%Z*o†èŒñgÜ:_f¢þ“Ε…Q@SaŠJ +€X™`àS úº>Ædœ°Æºè$“Ç…\3”î‘,¹N’ðíw¾{¼»'i{à÷NúÝCÉ*¹|)!q6à` dô—^ûµo†YOK8 Ð,!c«„„ Ɔ;ò˜“FŒ›ùµo†qSZ„8EŒgÓþŸ9£)¤ß^sÇI?>ýÁ±3-yý‹¯ÿæš;'rÖEHk!aÏß=ñþG§Qââ!¸_ºïÑi‡+½ÿql#a?ùéˆ.}ÑU Ç„¾È$ûûÐÏ6ðø[bÂ6"Ç!aã¸JKX“„\ Ð1¦áãç]3mù±?d:ä°ÝÏOU¼s þXஆœG-Ìä3Lç™Ù?X°TY³Ä!?ŠÞØfo0† ös„“›µtÌã—=¸´.Á†¢H¦îê܃÷ì§§ü±ócªwÅ3S‹7 z¨ážy™®±ì†GŸûòÐŒu¿{jÍmãVÁB诜ñø#³6X$2Y´Zehj‰™È3K®Ù †‰…H³$¦¢yδVìtÝœß<Ðvè{웉ÖolË»V•R 3 cêŒÎºK@8‹à1hРP4ú“›¥·NmÈyë/ Œé·× 9FrÿÅ·ß9úø”øÕøi‹Á!~ö%HþÆÅÆ'aÛý×@%l¯õ¦?áT ”’£x ôþ1n˜¤¾ ¥¿J/LÂNpE¿½ötJ°Ah‰Aâ;ýÄŸFhéÁ1œOK@—-a{¾ú/‡^;t¸-½gKØD 1êF‚›%ü‹á7® nÉÒ½£=Œ‰ÜÒ½LcÀ8KÀ˜0P¨tÉ•CÁ*ÁëR€1ýâ|J‰ cbW `˜îÆ´ÿçÑ:ô¨ã±7KHˆgôR<®ÏǘFLŽã§-øwÂܵ¤—†Ÿt ý-t¦± ÷K'Ÿz¼1ýãþŸûÇöH¦bL¿›ÿO±³Øy÷Ò FLÒMì?üg{¹õ>B­þp ͱôèÙë9wÎõ@ž;kYÅ£õ·>}þ] Œa ¹qY®ï³ïï?ü¨õ?9]Q t]aL]/‚bf Ôa0Š”ÖLÚ²¹×&:m†½ ˆéé¯ËüeL;ì…õäª\KgÿúÆÏü_îìûM¼2tJ 8ûÂýü—çYÿÓ}ï³£hïýKî]dï}NŸð½ÏuÀ‡_øÔð©/Õ¾÷½úæ¹`têÛ5Ã=àãÿù?ÿßbìž®‰_Û%Và¡SŠÙ6+×R@ H) Z©€0¦VªYÀktÐA÷ŒœXí„W–ºƒ>†éÁ@ÏÓó:\•œuÛüh@1Ló3œœqÉfˆ9î;ñ'¿:ç³ÿõO?ûê„w]Ù—‚-vü*}†¤Ý ŠÞÓdËH¼µ£!G5‚+Hÿê¯÷Þü¯ÿµë® ô„gýåÉßûŽ;±h z¨átá3yÑ«p3†Œiäôuæi «£yËÓçݹ€kÎ1A#‹VglPÍDf–hKÖ–fI›ºõ±•°e2øå?~ôç¾Ì•e) |„1©"”B &À-“û(u0&¸r2LÑ“ § f%sõm®W¤Ð6¾>’r€aItž„>  19ýW#aÌ3nê"øRâä‚ÄTâÄ'ÓAß<ì²kïà¤ÔÜe/!šüô*pKžk%Œ×x”Òð±3ŽÐÒõ· %ÉS°J§žuA%BKt¼äxZò÷œyâÄ´tÂɧž–üÙ¯ŸŸqÑ}£§1NÜôEÈ-ZõÄ3GnéW¾7&¿ÿêM’!Uz –€+Áy2q%DŽûþN¥'€›î‹tæC¾ÿÃSá…#:àJw>4 (Ò0ÿ/Ñ¥cpÊO?ßè¥ ·äaL·˜„Î1Ó÷N:èÒ—:ôÐ%œŽi`àx Óéç^ñÝL˜ŸCj!Æ4rÌS÷ÆÄºêÒK6‘D;¾Ø‹vLwÖ³—mC·þ~rýœÛ_…2B¡ “z׫Ãci‡µçXú€¿NÌÓ½w ÃøëÝyðžrJÔ³[ÏS]‹j8VGûæà‡iéO¯Ÿ[, ^´úéëàÂø §x¿à©;'®®iÜdÑjEhŽ–˜‰h–äôJÿ™Öu<œÂêJ€héÓC™hÁ*L‰dêñ®‘¿À c*páõzÖGŒ¸pTAåBqåê{c÷'N¸6úúú -'1&†ƒ‰M¿¹ê¶#Ž>>ô•ùLŠÝ€_%ƒ“°ÁXoœã“tä1'â_lе’Í}޲@Òw¾{"œ-q}GpKˆ<-áïAÿr(þâ†Ã¿ØŸ„ ðI€–p:âÄax¦YK62$ÜGŸ\ {f.Þˆ¿Jø _MœµÜ’yZŸ„íÛî÷ë+‡‚[¿‡}†d‡}‚-î¯|ý8[·¤ç|ŒÉ‡ rKæu T¸%ü‹á{aãàr aã|ziò°‘“±ñèÔå ”@/aÞÄ€qæxišöû‚ÇÑU)Ò½ÍÞ놽„Èq؆Ë% Kð½4nÎŒ ±têyØøÝ˜¹­Å˜ÐCŠÂLs^n×<ªë¥WÝV©uÕÊcfÆ”aÂܹ7ØX± f1/¸kÆ?¾vvM£`,]uâ2L|@‘L…nâ”ù„1©Z4«I¦Qãç…l/q¶ÃX”ù?å¶Ã0àín‡Cë2k™2LKWof#¼eçûú³?5[f9>ThÅúïþa“eqå@2Ýú»Ñéï}/¨\å½Wÿcs7žyÛü#.| ï}Ì\=j¹oœÚVµ0Æ2L¾qŠI&ªך¶eíÂOcj›¸º°R@ IaLE*­öä•$ÓÄY˃>M)C‰!¡ŠÅs†ºò5‡Ù LtÂayƒtôز¶ÆOm'Üc˜>|Õ†×Ùßö†}í)ÎÐUÑéu½«V&; $ÓÏ~q^Êø‹šjÆ_ó6ò@¹_p·WîN]ëzᢣ×.#ÊÝ;rœ¿ÞÝýaG^7)»ÏÜ_S½+áäì±k-ZOqÑÃ"y z ”i€&,ZÆ4í%0Lhèоará_¯daE«?õ¬%f"£lñ†ÂêJX)š¾îÉg_Añ!L¦€²•™¨?E¥s¥@!ÆTˆbR&ãضmbÁ` ¹bÂáõ1&z 0.Tt…+\HàÉÅÊ ÔÈá3Þ(ˆñIô¢4¾–½ÌE$“~{Í“æ­â¿‹‚äÅ€Cöàãð·4fÒt"äÑI 8BžÝ·‰ØóÀ£ÓG?µ€Qá ]Ì™>´Vé‘'ŸÅý-ÑÓ÷ÐÕ-½Ý"H-!ÁÙ’EˆûÝ#Ó¦-ÜgK=ñÌU·<øÐÄgèr ÐÒÝOEÂÆ”gד[bº{ÔTocù¶ãç3`ܤgÖ!Ñëü-Ýx÷XN¤ùi+Ð¥Ç=ýÄÓ/ÑåÒãžÆßÑS–#fÜýãžÆà‰.Y¢Ë%†óF€~º÷KŒr냓È*aÃÅ•ðoF?L< °9üú¦OŸüôðÆdNlÌßp稕Ÿà|dû0&üÜXcmŒaëÆãO¿ 7¡^š±î©¯˜³Ð‰Ï¼|ÍÃÏa,M†Éuúꎥ£ “H¦¢7qÊŒ˜T-ú¡í>=>;¶Æùa6Â~;ìÆ’«¶Ã.SaIC‘Lý(«¼ŸêÚ§B“e= ™îTßz“Õ70sæéýÑÙñÞ=kCˆ]¦³w 'ç.°s{5"™ò^{Zž?aL-—T”R@ Hb* Œ©˜åÖâ\$ÓÌe5ü¾#|ó¼‹N¸MlÄ´uÓ—l™±½ôì “H¦—_Êå cŠLvH¦ŸþâÜ èÿ[ï&¯« Á0þ@?L罄ñ×øù›jã4m ¦Š£š(ÃÄÒÉÔ¹:Pâ;Ƙì¡ëZ´0»clܸ*ÓCcæläjøU£–ß?emÀ0É¢ÕêêÔ3Ì’n¼Kx d@@âÝO¾è…épÜÅEQK™‰Z]ªºžèž˜º§½îÜfûŸè¥2aL-ÉA.(äß®º¼Ql·À˜ˆeL!2‰|R|8ɇ@ñ©‚(«„~¤%oÅ¿è'”Ðˬ†‡óq%$°JæiÉ %#–ÜJ¸ N¹%ó·„¾ŽË-“O,¹‰Ü’› ]bÀ¸ T\eÃq¹äù^Š¢Kt¼ä¢K·´xóy¿½¾—ài‰È1¦,þ–ÒicÚ´ý=Ôç5»îÌÔVŒ wñ*í•·Y²´”©e¯tRéñµ–a ¥“&‘Lyh©”‡V* Œ©•jöâµh÷ñø,FtuaÏ«¼·w•Ç  “z•oÏJl¯À/NÔXË0‰d*k%£}* `²§&ÉtËÝ£Ý÷>;‡Vßê¾÷ý¾VepņždœŠúdÚ¹ºïÃÝ^?'ôÁþ²–NÏ=—0¦ž+r=°R@ Ä+ ŒI5ƒ d?cidÐØcCƒ>ØNi& úhät„ü0¹k à“é½×·Æö±Ñí«¼SÞd€É.å‘L§Ÿ›ÅîJ†‰¥OÛx8’ ã…+‰aÊB2¡V¼ýÊZÈ+î^;S2ÀdbТ5òñÙÍX´bñ—Š…A­þ׸™‰úÿ°º‚mW@SÛ%Ö º£@ÏaL¿¾òÖÒÈ¥Ž^|ßcJâ²2I!V)Qò¢ÕÆ€J ¬’Å[ªàJœ4¾hÃÙ]e¸üñÀ¯Ò¯.º*Ä-yÄ’7ÖªK™ ¥Ê¨¬!n)Œ.UCÅ1fÜ–tt©âxÉC—èx‰|,vîÆ$!ŠœûoÓ·”är);~Ôª#Û„1 Ä óÖýà6£o[þ¸oþb'ý3á/¶±1âùø Ûø[÷÷’éâ+n±j;6wÖIs™Yü0‰aª[: H c*Riå:¯´û<0ff€×LfЬkÎÎÂ0-X½L‰+Þx­àeÁ7ß,xÅðm‚6ð/7øZÁ)¹T™KU€&ªî|8ã{¿fúÄa—³3Lô·DoLä™°_zÊ«H؉ ¬ç~FMØiGªH £€0¦Â•2*¤€íU@S{õ-àÕI2Ú;è3?%u}u¦™£¹ûûûÉ×ÐÆjö¨‘ »ÜØ@ÛzÚôØÄc¬‹^@seL?>mpdüU ?'m ÉÆè'ÃÄ¡k‚7דpDݯY®kUn2X´ÆÎ¬‰íPYÝ‹¬[¶|èâ¡\¶'‹VJ•iÖLÔäR71L¹ùù*#R ›˜²é¤£ §@ÏaLõ~TÙƒo=긔¢ÁÝè6©Žó¤«äÏ}¦§Z¿Jɬ’ã])W Âu»á’ˆ%o)I¶‚ƒaÂÄXMÊ-1„Yo´Tá–ª.—ZÅ!õó:m˜¬ó.8æ’ßûÃ{h¬kŽ©e„œÛöÞ6£—pN©Û|€dºèò[ `òœ0ùQäj‚²/³¥`ÍÄ’ÃT·t@ÁÆT°Ëuvi÷¹ïÑ®'¼ ¦AÓG $õâ¨âmè8mnŽa¢(öÁ%×?_(À›ø6Á{' ›k¹{>s4Q]?lTúV}ï‡ë[v†‰b›eœ$ö˜&L–€sZvïÚзöÍÆ16Å‚=ø ëƒ{¾Ð "€0¦‚”²)¤€íV@S».âõI2™²$¥îÙN}c)ü0M‹ úê2L°¼mÙù>&t§Ñ¯6§§èr£û=¤Xð/W § TÝoö·?ÜýžÂ=·©jy$Ó©ƒ+v×°ó{[;J;¹Wú¾õÛ‹0Ð † Å‚¶BçcÒ?Gd6@C5@=ш¬M5¡”—Í›E +ñÌl[ÖìM³eѪ[ñ¢f¢êôo–Œ§l_ê&†©nYè);„1å®H”¡Ö(ÐsÓEWܦÍ'ðí¡G~?倘¯êI!\)à“<ÚÝÒvt8Ü4xŠ›*aàâA%‚,•žJƒ¸¸¥*±” Z †èª¹)[Úl¡âúɵéô6aLX:€Î7~£èŽs+ Ü®9I&ÆIhlg ’éÂËnöªG À™;W,¹Ö´“ºJ‘ÆTäÒËaÞi÷¹÷ÑuÛá¨9»? “½D\Cy`2.„_+„hs( ²Ô4Q]wǨ&ê[£ “YƱùL–p©7Íè4ÓcöcrÿbÆÛ8’xþ6ôt:¸k cêšôº±R@ äKaLù*Üä†$Ó£“W;á5ÓÃÃä›FÝ…+¦ßø‘Åc_šnx@¥Øò-t•JWLØfÇISû* H¦=å x>¼pÔ_ý[Fз»¶Šaâ‹°× ôY1lD† ×#—Fdí« ¥¼r®,Z¶RÃ~»–,ZYj]ÌDb˜²„Ž‘¹S@SîŠDj½‡1UœÙÄ:C‚«›CŽü~VWIŒìVßdRKâž0œÄ=¢”F)¥‚JˆH<8Ç»R=\)>6\Lx8¢Ku-q—ÿÔ&Œ‰oüF]ç¨`•ø«ÅNNHf„46è±)Ë$Ó—Ý\õÀDçþ@:i)˜bÉeVÇ”SaLå,×n>í>¿=Ãâàm[i„mQf«ü0áiñšÀº4l¸†×É‘&FšCA;a·rWŸ¢+@Õµ·r=/†ßû‘é“&&Eû8£WÐÍè¶äÆtìä„ ‘&lã[$l`ApÑÕî•ü cê•’ÖsJ) ¤@„1©Š$)@’é‘I‹ëúh¢ºzèȘ÷¾_ß (oŽaB6±Ì—ñ ðÁz_F‹ƒMôæTEŽ‘æød˜$:jÒ§ c*F9)—R@ H)ÐvVì¸é®¾½Þýæ¶ßI7(¦$™zb¡3è‹Y=Ø(Ã1ÐÁ6G§ìNù)ãÇ‘Jq{Úô½D¯“jÝ&Kª'ùŽ”’})ÑõÎoüÌñ«”Â*ù˜K°jÄ[»oiQǽ 4RÓÙ.4Æ„¶$ÓàKo¤÷,׃¦|7¼Ê]ÆÔA±{ðV´û {hªµÃîûH SV‰¶>2MTCn[ßÄ0µUüR]\S©ŠS#¤€Í+ Œ©yízéL’L#&.¹ááЯ¡Xr½$[IžÕ#™~zv¬ÝU SIʸ‡C­~KÌDb˜JPôR`0&U‚’*Ћ“‹…¶1}ûˆcSHó”ê6©–äFKã“,p˜7‚rS%œ*ù\‹X¥TB«èI¦sþíF‹&C3ŠbÉ•´ÅÖc5®€0¦Æ5Ó )@»Ïí#§„Úa1L ɨƒ3*@Õ·ŒÕ71LÔaž˜T¤€R@ ø cREȨI¦',­¢ÔQÀB’餟þ v·ôÅ0ºL•yS@­T†~š‰Ä0• è¤€§€0&Õƒ’*Ðs‚pÑ×Q(ù.޶âÛoq,·[‘ŸI n“B¾”ÂpRmÜ·ZD)B)XêU§J=ë‰íH¦³}£‰ †©¤Íµ«)„15%›NjHÀî3bеÃb˜P7¤MT˜2±ú&†©!u°0&Õ) ¤€T@“jBvH2¡ãmp1LÙÕ+ú‘ ™Nüɯ¬èÅ0½@•WY´JPš6‰a*Aéë¤@ €0&U…’*Ðs"p±Øâ"²áÛo~ll˜¶†vÆÓHæ<Éñœ2‰©ë-.â›Ï' QjšUJ9±Þ˜Ø4É$†©¤mµ«Y„15«œÎkH×î#†©!étp ¸&*1LMØë§ÈS¯×=¿R@  cRUhH—dÃÔt%8ØH&1L%(M=BHY´JP%š0‰a*A¹ë¤@UaLª %U ç0¦s.½1…1·À˜ªÄñF¹µ’Ë$Õ†u« ñ&2©dRC×, Æ„ $ÓÏué~yâÔùë¶¼›’ÔI-i{®ÇŠS@“êE§ðì>_ßx|áKKWoNi„¬Þ¹û÷u*_ºO9 ‰êç_ùùœ³`Uú{_õ­œ• é§ÆÔ´t:Q H) Ê¥€0¦r•g'ž†$:áß<øðU^Oé„oÙùþï?Ô ¯…Ò±{€d:öG§øÕoß;r\úøkÇ›t,Wº‘h‰$™<‹Ö_–E«%’vþ" ™‰4=ÔùÒ¥@{ÆÔ^}uõ®)Ð[Ó¥—^º—>R AþÓú‹©súÜê¦íïuí'›zãŸýð1Lù,åªk cêšô½xã7fÞ{ì?ü—¥ÓžÃÔ‹ÅßñgÞ´sÎü/#§Ý,†©ãÚü†Â˜ ^€Ê¾R@ ´JaL­R²§®’験ŽÃÔS…nûëß\.†©7‹¾ž$Ó±Çý@ S¡Ëzç;›²˜‰Ä0º”•y)¯€0&ÕŒ’*Ð[S´Ó'~ô­ˆU ·ÓžË÷ß1‚ü0•´¹Öc5¥€0¦¦dÓIM*ðÌýúùܲdNR;,?LM «ÓâØúîì;—ü‡ùF¤¼÷å‡Iu'FaLªR@ H) |ˆ1¡O%=¤@vví^þàò½_yí­¤N¸ü0e³ˆG¾ñÎïSÆ_òÃTÄ2UžM?ýùÏhÁdÑ*n•x÷›êš‰Ä0·|•s)¦€0&Õ’* Œ)-ö– )P$Œiùã{ð®Éôæ±ÙV'µ¤Í¸+UaLª Tàíí{ÖÎþÓ¿¿k÷ÃÔÉ¢è…{aÊ o«wÞ¿íx;£¦^¨Í<£0¦fTÓ9R@ H)PB„1•°PÛÿHS×…Nøòm·ÄúÄ0µ¿º‡$’I S÷ËF9è·I$“,Zý–¶Æ”n&ÒôP'ŠA÷]Q@SWd×MÛ¯€0&aLR arêéòý=Œ iùãQ’IÔö7§ºC.Æ”Ëb)z¦VºìÞ!ѧØÚ7ûíWÖbÔî#‹OÑ =‡ù‡}ªoÛov½¿õ-J2‰aÊa‘å%K˜òRʇR@ tYaL].€Þ®˜0CŒ4âùýþÃ÷C$“¦i“YŽ’Lb˜š”R§åOY´òW&Ysô‡ÞJ1iz(«Ž:N QaLE,5å9ƒ˜FXä H äc¢+&&ðL{ö¸$“:©CRR„1•´`»øX˜æ^6襧FDó0aЀ«û¸ßµûˆaêby•æÖïýá½”g ‘Lb˜JSîmyaLm‘U•R@ Hâ) Œ©xeÖíÓÓŠ7ýñ£j&1LÝ.œNßß%™Ä0uZ}Ý¯Í È¢Õf;qù™HÓC]÷]T@SÅ×­Û©€0&aLR aòˆ1™+¦ŠC&´$™ÔImgªkç^aL¹/¢beΖÀ*Ãhɸ%<È#÷ããp?í>Ï®zLIèÈb=µrÛu&¬™0h ôl˜‰J S×Ë+ïÆ”÷Rþ¤€R C cêÐe¹¹b2‡Lýé’Lb˜ÊRÈ=I&1L©¦£ ¢€kÑ*H–{.›î°í½m)mf"Mõ\åÐ÷ ˜z°Ð{ã‘{cÂ+CŽ”´uçîo~Œ¾-“¯½ùÁö7v§?Qîz~®+&Ç!ºªšËì–\O™¬€0&ÕŽ–*€pr`•àéÃÝïgZpó`lcc÷Îm$œp·©ƒb?ŽD;¼c=”ôá„-ÍŽ.Ö ÀÓàiƒ‡Ìóâ®ÝåE-ìÛæ9ýâ6>f·B}{öå>~«HT@“*‡R@ H_aLª )àºb2‡L¸H¦ßøQC—ÒÁ¥Qàß?øcižE"B ÀÂðþïÕ¸å´^Àò³ß­ûÑ.„¿° ᯙ‰Ìd„B|~Ûœ<åô!•-) ²+ Œ)»V:²P ô:ÆT¨ÂRf¥@‚!WLŽC&I&z]aL½^ZüüÆ*aãå¹xuÆ’ƒ‹&€Jøô]4yíªikßl;²ÅÒåz@Ù›fÃ8’ <Û |d <3a§ùgÂNؤ`®Âh'ìÇÁ= Œ±Y„15«œÎ“R@ H’) Œ©dÚÖÇ ¹br2µõ¾º¸R@ H¨0ûÀ4tñPX‡`&B‚9Èü3ÁF„mœ’û•Ä”R œ c*g¹ê©öcR%W êŠÉqÈTðgSö¥@¿ÆÔo uWc•*Obb,9xZb°9àM›°¨¼4áÛБ’T 4ª0&ž‚ :[‚ æ*Û‰ TDX¯¸‡æ*}¤@¼˜T3¤€R@ ø cREÈ®@Ô“ë)ûut¤R@ Hþ+£vƒg²Enf;‚½ß’pâ½F8Ò8IN)][E‡ ³@Ñ.B'LpsWày`]{Ê~ÙC cê¡ÂÖ£J) ¤@š˜T?2*ëŠI™2ª§Ã¤€R å ˜QŒ%g¶#lsð&ºôF¢÷î–gC”R / cÊKI(-V@Þ˜Z,¨.':ªÀ‡ì¥Á´äá=xWÝÿ£êží/v43º™È¡˜rX(EÎÉ$<@0IôÉDP‰>™W û1á+ìÁ·ØF\9lc*ráw-ïXEÇ q¶ØÛ*1Ša&fHÓ„5AÄîeZ7γ˜ò\:Ê›R@ tPaL»Ø·z÷›¶¾;›iö¦`Z÷æÃ¶ç½UìÇSR h ¸N»™÷ɦ!ÐKf2ÞE{PåW Hl cʦ“Ž*œ˜ WdʰHP`×&cšx©’R ª€0&Õ†–*°ìÞ`é`&lƒO2LØæ­°Á¯ø/œ0á_$L-Í‹.Ö+ ÀEŒ (z`‡Ñåà;ñ{€1Á,…õvØÆÔ+•£¹çÆÔœn:K H) J§€0¦Òi'¨oë¥À˜6uâfº‡R@ H8hr—´Ñv„Øà:7‹è´ÉöHK) J«€0¦Òm¯?˜0¦^¯zþò( Œ©‹F¹’mW@SÛ%Ö º£€0¦îè®»JÖ+ Œ©õšêŠÅW@Sñ˰HO Œ©H¥Uø¼n}wö]}{aú­ðO¢è°˜:,¸n'¤€yU`Ó[£7…>U^3¨|åQaLy,åI H) öìy÷›d&RE=ª€0¦-øò?¶0¦ò—±ž°WÆÔ+%­çlDaL¨¥cû«€0¦þ*¨óP@SbéPWaLªR@ H) |Ø›ƤêИ’KK) ¤@ÇÆÔ1©u#);„1å®H”¡Ö( Œ©5:ê*R û cê~(ùS@SþʤÌ9ÆTæÒÍݳ cÊ]‘%C˜ŠRRʧR@ ´YaLm¸œ—ÆTÎrÕSI) Н€0¦â—¡ž@ 4«€0¦f•Óy9W@SÎ HÙ“™Æ”Y*ØC cê¡ÂÎÁ£ cÊA!ôN„1õNY·øI…1µXP]N H) Šª€0¦¢–\Wó-Œ©«òëæR@ H)¨€0&U)л cêݲ/ù“ c*yëñzHaL=TØzÔÌ cÊ,•l˜Z ¢.‘UaLY•Òq!„1©JH) ¤€ðƤŠÐ„˜šM§H) ¤@ÆÔ‘u )S„1å´`”­þ* Œ©¿ ê|)>ü`ˆ ÀLúH)` cRe褘:©vÏßKSÏWfÆÔ¬r:O H) J¦€0¦’hgGSgtÖ]¤€R Q„15ª˜Ž—åQ@SyÊROR£€0&U)P0^zjIJ{‡|¸û½P¾wïÜöòÜ {eW ´[aLíVX×wƤúÐA„1uPìrÝJS¹ÊSO#¤€M+ÀÞÔ«oOnú :±ÆÔƒ…®G–R@ BaL…(&eR ´EaLm‘Uí¾˜º_ÊÈ®ÀÎÕ} É=lRöKéH)Ð cê‰bÎÍC cÊMQôBF„1õB)·å…1µEV]T H) Ч€zSÅ+³äXS AYR@ H„1©ZHÞU@Sï–}ÉŸ\SÉ XW&àiÁ̓‘èŠéíWÖ‚j‚&>#ð&üÝ=ØÏ¯ô‘=§€0¦ž+ò®>°0¦®Êßk7×Ä[¯•xËžWSˤԅ¤€R Ø ¨7UìòëRî…1uIxÝV H) ê( ŒIUD ô®˜z·ìKþä˜J^Àz¼2)°µoö#÷Æ„¹— B‚û%ÐKŒ%‡¯ð{¸ÿâ0ìÁ„Ÿ°Q&5ô,R “˜2ɤƒZ¤€0¦ ©ËdQ@oYTÒ11 cRµR@ H)à+ Þ”*B cjB4"¤€P@SDÖ-¤@NƔӂQ¶ú«€0¦þ*¨ó¥@' «oL«Få}K>™H)á/¿ÄäFšÞ$ŸL,,Ý+ cÊE1ôL&„1õLQçáA5ñ–‡R(d„1²Ø”i) ¤€h½êMµ^Ó¸¢0¦(d=¢R  c*d±)ÓR % cj‰ŒºHþÆ”¿2Qޤ@‚Æ*áû©ƒ2Ñëý3a?"Ía§ë¢ Û<Ò¢ÎI`)ÐC cê¡ÂÎÁ£ cÊA!”; »?ÜþÄÚƒ˜Æ®Þÿ®¾½F¯úÛóêÛ“Ëýøzºæ¸ç¸=7¤ÓÿbϹ«þ;ú¬æ/«3¥€R@ YaLE.½®å]Sפץ€R UaLª R wÆÔ»e_ò'ÆTòÖã•Ic•À$™7&ÀIÀ›àu {È3á‘~ø ×MÁN)“&z)PGaLª"T@S'ÕîÕ{M]è¥hñüÇ>úÓ½ªŠž»ž3nÚ‹FlZþx½“õ½R@ Hr* Œ©œåÚæ§ÆÔfuy) ¤€hRaLM §Ó¤@ ÆT‚BÔ#Ä) ŒIõB F²JÈ.1&Dˆ[pó`âJô´ôÒS#¸ñòÜ ÜMŒ%‡¿8¸0ªŒJV) Œ©UJê:YÆ”E%Ó?ví^‹1­ØqSÿ.¬³K­À‡ìü±ŒéòýKýØz8) ¤€i cRýhBaLMˆ¦S¤€R  cê€Èº…È©˜rZ0ÊVÆÔ_u¾è˜ ”̵&$úaBøc_q€'ìÁþŽåS7’9R@SŽ £²"Œ© 9uÈ$WLy(—¼ç!Ö!“\1彨”?) ¤€h£˜Ú(ny/-Œ©¼e«'“R@ [aLÅ.?å^ ôGaLýQOçæXaL9.eM H) ú©€0¦~ ¨ÓR@SCréàfˆ:d’+¦fµì¥ó¢™äŠ©—Ê_Ï*¤€Q„1©V4¡€0¦&DÓ)R@ H)Є1u@dÝB äTaL9-e«¿ cꯂ:_ H) ò«€0¦ü–Ms&Œ©Œ¥šÏgr2ÉS>Ë(¹ 9d’+¦<’ò$¤€S@Sç´.Ñ„1•¨0õ(R@ HR) Œ©TÅ©‡‘ ) Œ©!¹tpqÆTœ²RN¥€R Q„15ª˜Žï˜ú£žÎmD×!“\15¢\oë:d’+¦Þ® zz) ¤€€˜T šP@S¢é) ¤€è€˜: ²n!rª€0¦œŒ²Õ_„1õWA/ò¢À®M{ð®šxi^ò£|H<( Œ)¥Ð;yÆÔ;eƒ'¥C&¹bÊAQ* æI®˜ UnʬR@ ´CaLíPµôׯTú"ÖJ)  ª€0¦‚œ²-Z €0¦ˆ¨KäQaLy,åI 4£€0¦fTÓ9eW@SÙK8_Ï'Œ)_åQòÜÐ!“\1•¼˜[þxtÈ$WL-V”R@ H* Œ©€…Öý, cê~(R@ H)§€0&Õ )л cêݲ/ù“÷ÆôÖ[oÍ®÷yâ‰'ê¢ïK¥@–ÿàƒ ÐìÚ´ý$yc*@A)‹U@SGåîù› cêù*Ða&ôýð£?¡‹Òa]t»TÞå‹•HR@ tWûï¿ÿÒÔÏ™gž™~€¾m«_|ñ9眓~‹Ç¼»µHw￘ú¯a^ASºY H)P„1¢˜”I)Є1µEV]´û ôÆtÊ)§ü?ûý¿_üÒWÜtà—¾bi¿ÿ÷ÿ÷Wûë¿ôåÄôÅ/øÅ/¡ÁtÀ¿¤¿|@bpÀAúüâÓ|>.}î 2¥|­¦/}ö€úé3|ÉKŸÏš>ýù/ŤÏ}éÓAúâ§?WMŸúÜ3¥Ï~ñS~Ú¿‘ôÏŸý¢ŸüçϤ¥ÿôÿÇ?~ò³8擱éÓþÕ_ï}ÕUWuÿÇZ/Ë—,ú»ÿ¾ß¥?ÿ~½õ½è%„1õRiwÿY…1u¿ z(“'Oþ›ï‹‰ðzf=j¿À¢ôÿ:ê¨b0úý~^]@ äSM›6ý·ÿóÿ<缋™ÎvÓ¹Ÿ}îEH8`ÐÏNÿÕ¹UÓà‹~5ø¢³"éÌÁžyNM:㜠ƒtö…gTÒ/Ͼ°’.øå¯¼ô‹¸túYÔ¦óO;ËOgVÓ©gž_MgœêçŸRMçrF~þËóBég¿<ÏK¿°tîOá¤ÓÏýééçþ$. :í\? ¶ôãÓ{éÔjú×SWÓ)ƒÿõ”sNަŸŸó£HúáÏÏùáÏÏþáϪé?;û‹}û¿ÿÄÆ~꥓ÂéW'ýäW{íÕ[ö´|þšú™+aLý°7OÆÔ›å®§–R@ ä_aLù/#åP ´KaLíRV×í²½ev9ùä“oºí®­»ÞÒÎ÷·î|‹—v3ÝxÛ]ÇwÒæ×w»éÕ×w{é5¤ÅM;þýe'mÚþž¥ÛßóÒ6/mÒ»¶¾»ÞIë¶¼ké¥-ïxi³—ÖZzõ5Az{Í«o¿øJ5­~åm/½ì¥^~+H›ÞZ夕ßZ¹ñM¦H‚ôü†7½´é眴|Ý––­{cÙK»˜–2­ÝÕWM;—¬©¦ÅkvzéE/-òÒë^ZýúB'-xáu?½†ô,Òª =³ê5/­ôÒü•;‚´bÇÓ•4oÅŽyÏ#mGšké¹ísœ4{ù6K³–o›µ,H3—móÒÒ­H3,õm^M[¦õmù«¿ÞgÄÄÓ–l™Ê´ØKS¼´ÙK‹6Ÿø“_af—©õn¿|ùrjó–n„¥8ÿ¹­÷4ú^ ´NaL­ÓRWª¯€0¦úéˆÖ(†éëßð8ùdêÕ‘é¹=†é Ä• Ö]¼U$S&ñth½À˜@)ÕØ%<ßÏžûgã–pÀ3}/Dm›BôRªè°ñÁ]:õê;®ÙÁ|?§{}6—Ïa†©ÖÈuÅd Se}Ôξƒç¶¹bª.‚JrÅ´¬fá7“ïŠ)ðÆäºm^ä­wÆÔúßFǯ¸ãßÜշך]÷wüκaÆTàÂSÖ¥€¥V@S©‹W'RƤ RRzcºþ–;c(¥J¨8|û½ïŸä®q´í·L®Ûv]B¹°ï¥½´Î !—â©™@r›H.ˆ%ç[K®_~˜úÁ0erÅä"W.Q®ÖS ôÕüÃcNŒ)N¦ÉœcLd˜žyn–Àr:b„ÿCÔ¿Ÿž.’©¤Í¶«!„15$—ú) N¯§¦%/n¾÷E2Õ¯w¿¦'çZµ!õŽîâ-÷È'SïV =y Æ»zÊPá€ùK^ 9ÂE—B†ˆ¬!ìã}?ǯw#×',—ê7Äkl89ß»sBxz‹(uÅdáä<‚늩֑s4}’+&cºÑ *—QކaL]üµêÖšík•’=uaL=UÜzX) ¤@PǦ@…¥¬J+ Œ©Å‚êryQ 1¦XJ‰;1óýÝ q¶@K•ÅŽà–ê¢KÙé¥Ê:Èw€.…è%,‹´‘pÂô‚9a ™€ie,ÀT× Óº]˜Ò`Ь•ô쌮©Ó‹‘ÒcÉå€aJ'G£dÆDÓ$1¦³Ï½xËÎ÷-íxóƒ?ýùÏ]ÿ“azö¹M+¼Âõ0&xì7Œ ¥ó“ÓϽð¢_w=ŸÊ€è¦˜º©~ïÝ[Sï•y'Ÿ Ó7¾uXß‹Ûý÷¾ïS§ö½ØÀã†Ýõ»¦³Ô×××ô¹ž¸víÚÐ)MÜ=z‘F³Ñòãßó?¸lRÞ}pÈÒÏÇ$Ã4æÉ¹^µ‰Pïè.Þ|÷#‡ñÝï¿ßœÈ¹­èà~ú© ³Ê*×’KEŸ½‰ËòÛ*£.žˆ1EíÞÒ©Š³¥½÷Ù÷éÅ/Б}UßÏk<ßÏõ¦Z—϶VÊ55TbÉÅG«Æ’sÖGµ’aš¿¢•ÞI¿i.S\89oùÓ² ySm zºbB ŒépcŠqÛ\1cr­Ø~w÷‡ù©fÊI4Û—E%îµn½N¼Py¤ŒR@ H\) ŽM®ŠC™‘U@SGåÖÍ:§@ÏaL×Ý|g,¥Dãàµ7{SÈJ!–K¶¾ P)”\»¡¿ýÎKɾ—êÓK`˜ê†ëÀÄ9°T€©f­d0U¦E/ú+&ýE“5ë&ƒ@rÍÄ’k•¦, ScJpÅDŒé—g_*Ù?~ÔeŒ‰ Ó‚ç_ÆZØÐÚzg€ÌP( W¿>è´sÏ»à’ε(º“È›˜òV"åÎ0¦r—oWŸŽ ÓÒ5;Òßû‡Õ$Éêb¿ýö1bD Ÿr„ I0Ç€BÄîÞЭq:.ÒÐ)éoÛ¶­ÿ?Äÿ¤ä-ûƒC:ÅSF†iN#áäÀ0Áss ÆTk+°õNÀ˜BV¬wj®Jè¬n) Ù¾n)_èûÊS¡‹O™—R@ ”XulJ\¸z4)PGaLª"%U ç0¦koº“XRœô¾ýî÷Oô³¿¤­1â ]Š@K©ÜÒæwÀ-…Ð¥xßKè¥UQz)B.ÕS<Àäǘ¨ÃSkœ0­z확¯Í_¹ÃRøøÈ2Ê9XR™!–\F† k+=oL ¢Ü/möRey¥ycÊÆd S0)·¶žÓ‚^ûñiƒE2•´×ceP@S‘tHËÆÔ2)u¡ŒaªÀ(áH²€QH“ã½hS$ø 3­ƒôÄ–evš'©*´c‘á–Ô¼–`Là` «ŠÊ•%Ÿa†©Ò]dD9—zGµ¹ñ·› ™CÔœF´ôÌÇnÑrبµÙÎR"IulèСfágتz˜%K:¦[ cªÄƒƒñ!šÞÅs®Š_:UË-Á(á.Z ³ƒ¥]J£—V›¿ç—ß‚‘ÁRš¦Z; –2:a"FÉdË¢ðc2€ ­Sç¦é}žÏfbLæŠÉlÆ01¨œ0¦nýˆZu_ÍöµJÉžºŽ0¦ž*n=¬R @ ¨cS ÂRV¥@‹ÆÔbAu¹¼(ÐsÓ57 ‹ºP²=øö»Çžv°±VlUaOK/m~)d7ŒrK  Kµ¾ÜiR Ûãé%o~ËMaÛbrÙ&ß “YƒcÛœ0=·Nà-Í 9„‡Oøe[k¦¥Oxz†ÇªJ’c¢Q’SÔCoL`˜>ïûaBM»dpÖÖ£h`ÿ…Ù÷™U¯ýøT‘Lyis•N+ Œ©ÓŠ÷öý„1õvù·éé†)òÞ÷aó©ã½÷}XüÐ#¿ßht9Løkþ“H5Ñ!¾°‚m×3·±“´ ¶bغwâí\søÄ+ã`ÛcLIè²®ªîW Bp ogô•À=ÀAyÞ‚“žÿ?ªP¶é‰ù™={6.Å=Ì1”7¦V=82Öh20Lè.>öÔ<Œè@%6!{òì.Þ0lT£$žR@[€8T¦n=±zEÅPŽtAD%Y‘¢ŽÁb1&«rv<2–³*A6þì׳ªN–1œB‹BµGòIæ)TëìÑà¨,”O«ç8ÝÄlS“¢ËæAbL)v |…æ,\·nªZ › ê­›rÖ¿•°~càÉk=*Ö† „\€É R_Ï “Ï0ÕúuŽ:aò^mLÎj¨š¥PÏ'Æ’kÔ¦ŒÉYïä2L˜òðSê8Û·|ûUý¿”®Ð; cê²Ö“J) Š¥€0¦b•—r+Z©€0¦Vª©kåHÞØnk äÎknvô±'ÚÁ¢ÆÚ¨p4†q¥Š§¥,ÐÒ‹p¶ÄŒÃ†cCLD—jݹ'ÐK˜¢H¢—RÜ/¥x`Bx2/EÖJö`Z¹£íN˜j¦-.Ãd«*á„ ÓƒÆäùa Ù%sè‰ ÓÂç_ö6NJE\2T"ÊÙt&œíÿkf’‰ó‚n+•´Zsu9jϺLJÕÍ‚D«+Q‹ÆÔbAu¹T„1©‚´Zc˜êÀ(Œ˜ë…·Kt±i„d¢OäݼÂ`EÅÂW€?Ð`¬+¼Èð¾3n{ÙË ~Áƒy$=èð Ø07Ev°õ:xJô²¦¨}…l0˜K>á_ò4<×§çsrcùG&q…袞rb³M8_áv”‚w´GvƒÊµäÁ ë4T³\†)ä¹3ÎS@¿¡æ\×ÉD$3À+¥ž°ÔBõ eá–# ž$oLDøaM³ RA܃rÁ+ƒ‹l²=v_V7Üc? ^ÖíñF+žŽ(³aõÉ áŒ‹_4U±€iCÈ!ÕÚaˆlÔ ÓŒª-²ÆiN˜`‘¤Qò¯þzocª $çòL'þäW9 *Ã0…ãƒì¢K×§3¡íɧœ“%ºœ0¦¦[n›ñM¹‚0¦¦åmòDaLM §ÓšR@SS²é¤$\†)Ä.Œ’òÞ?ä;Y}2”1ßEÈOèm’æ2%`5€•`Y%|ˆŒ¸Aåp€¹áᡃ‰E/kâ.±Ý,áFäZˆÑç ‘£Oû é;*z£Xz&”mþ‹Ó ÂÕ쎦››·~>¸Kbeü¥Ôa˜j=w2!|œXwñºÛ³údBÞÈ÷àA ~l=qKGR|:Ó·ia›{Xj¼2· ‘7‡D[%Ø ‘÷n5ã¥ÜSŒ|â5ù/ïË\`ú9ÄÖR`I/E8É®ªuöhx>¾ëx ·³Ö2>¤¡KQgϼ¥2.½”´PÊ‹Wññ¼Ñ*™ªêwö%Ú^§¦8¿Î‘(r)N˜üAn¼ ayÕ€`.œ=€)™a ­z:çß<Œ)6–œÙ T®¸¿A˹0¦bçASç5×¥€R ‹˜²¨¤c¤@9ÆTÎrÕSíé9Œéªî ù/”¸~ßüÞ‰•µŒaD‰ R «TÅ•j<-Å8[zÁJþòÇ*·äÍW9^Ü«–Ä`5d×¥xt †Å—v1¹†Åï¥z)ê~)bg\ø‚³ÌO¯!!X2¯ïî¢INXr—Nö`ª $˜œ%•®&³Hcz`ü‚X?L¹òƆés~,¹ª&c˜Ö½ò…Ç~o.3êŠÉ—ph°ý¼>É”„1a¢…kè1ÅÂ)@›Ôá‚uNX2$‡¹CÀtãn˜ó¶»<8€§ÛÅÝé.;˜á”'Æõ]fˆËëÝ+Gs‹cx=…ùç1œ3‹îáSóNnñFÔ„3R<‘ǘŒ>û۔ª^AP@S'TÖ=* cR]h1 “Ë.»0ŠãŠÉëwaZ·òÞ?8ÉDŸ:ˆð•ír8 „§ÐûN+ ‘I8‹8$!ìâÂ"䜨O4Œ)J«ØaÖCÀ¹!î×çë/\{¢}‚ý<†ÐUèFQŒ)šmæ–!êØ!Á‡TM¬7¦þ?¸õ—2Ö,0Lè.2–\ØS†î":äè.^sûCY¢ËáéЋc±²c[OÜRC‰àH«l,Gë±Ch˜¢ýÃtŒ‰™qƒ$²Üí:é“)Ûnç-ZyP:¤ôX1\ÜZªc¨«ì6³p‘=…“ËXÏKp1¦¸õQ4Ax Ì|v…™ Z¸bjerœz'rœ‰²)÷Káðô¶8jÛÀª`Š"‡·[¬%!º*Ñ S(½c70†É,À˜¾éaL‰>›å©¿D<‚0¦r”c‡ŸBS‡×í¤€R £˜2 ¥Ã¤@ ÆTÂBÕ#y ôÆtåõw˜‡¤è¾ø½RÖ5ÆxWаJŒ·ÉKQb)êl© -ÅF‹ó½¸‡,‰uÑ¥tzÉu¼Dü%&xœodlØý’¿b²`rlŽžg ï÷=0®à}+d“ëN˜ 1¥0Lð¶UYöêyÒJrÅDïú0éÖ%™’0&.aÇDÀé% ºÁý6™‡ .+Ç)øp®‹S•œ­äL&o8ÊI,Î0¹Í3 5e¡:èõÁæ¥BÓEœ Šæ×áyæÙa²é[柹â1¡=ä´xG|Å9Z›³‰(; Ïhn¨ g4õþ霘:§µî´g0&Õ‚)` w²ììøÁûE<»\ëSÇ{ïû¾(¾]d²WóÎwwè Î75_‘ Ëe/D¾Úx_yá Ç˰ÐZ3+z°a@|ÏÚeMÑÐ+8Š1‘ÁñìfÐ3“½sÙÁ·ÄS¢ùwyÞ4šm>>ö³¾ 9cêÿƒ»½º•‹ ÓØ8†É«9—”jw1âŠ) ÞQm®Z‡dŠºb¿(©ž°ãdõÊ*’u¨Øû"e`“=rÈ«bc²N#Š˜49/Å*Án›Û‘³‹„ª“ubÉðá\·ó­‚1Rn­³G³N)q>&;ÌuKY”CbL)f|…f<³"ìÝ9}¹T\xzÏòÌ-Õ¬•Šêûx^›Ñý’0Õ*k¢¼eQîš([…EPAJ˜|GÎEnÎòmÆ0etÂä’3† Kž|Œé{)>›…1•ãÇ(Œ©åØá§ÆÔaÁu;) ¤€Ȩ€0¦ŒBé0)PB„1•°PõHžY1¦èú×"êwòÉ'¹þŽ0Šä˜ñíÀcNXý2˜$7½µšLRlòA¥$VÉ1Ö¸YŠzZªñÜø[Šá–Ð¥ÀåR£Ž—zéE}a ÖGF}/y!'Ý/¦Æ(½Të~)`ŠÄs°Bšý±B/Á|ãÓ/„\`¢³¥ücLÆ0ÕÆ™ËŒ™” ¹d¨D”#Ãäk¸õ‡?;;%º\ Æä΢ Ácñ;Ü .µw²Óö¢›à‰ˆr'®l›¥¡ˆ!ø6Ê$…f.q ïhüS,Æd3I\cB{¢ËúÝñ`›îâ|*‘&c³}¦ˆígQó,Œ©¨%WÌ| c*f¹å-×Ãä;欼÷'-ÜüؼMcçnD3wãs6]ŒòøÓ›<ßµ®˜‚÷þÒ­ß>âØawý.é1É»ßb]ÈÐ ab¾]Gƒ|±A2‰Çð‚dV,ì/Åw%Y(÷`{á†.ëf̸̮^éÆyæéø;ͽ¹‡4D&t#$<×˜¡þ1W‹äZ%ÞÑò½B£žÝ“1Lè.†Ð·qó6=T›Aµñ»‹?ýrPmBÝÅå^Ü¥«n™â“É5“ Y%Á­'ÜÃá¤yßdwˆ}$À=Ñ‚ÀN|‹ÃìcµÈª®/åV'þKàŒB4O¡Â¡êdCy$»µ¡ªèV~ÆSèÓ®ªuöhæ¶ÓNĹòÆ”·¦¸­ù!Æ1;ÔX!pÀôùϧ[!žœµ$ÆÇ³-=9sIÔòðÈ„YO˜5qÆÏ÷Rè’ÏD&s- t¿ôàØéxUÍîÛ„Ä(r4,Œ~êY`rM IÓCŸ¹çá©Hwûiʳë€)ˆ"7é™uO=³ÃÞáÏ ‰kŸ¶Ü7n‚ÎGãÎà 1¦ŸÍ˜ÚúéØÅ…1uLê2ÝHS™JSÏ"¤€(“˜ÊTšz)И˜ÓKGçQØÕ¼õ1&Î@ðÓЂàjàcL·'š_~kÈu·uÌ Ä’RȤäxpaV)ÖÇÒ7¾uø§>û¤¯ëpºmÿÑO±ï'þ{FŸežÛg<»úëß:,´{ŽúÞIXˆObéô³/FŠ wã°‘ˆ2†€q3î o6ü±qèRÕ»{ÈñÒNÿê¿j‘ãâJÆÑK®Ë÷XzéÊ[ÀºÉš¥“>g㦽÷ý;X™0›â§VLýǘÐ5\´å‚¶Vu2LÏ>·Éf¤`k&Íöƒ+gtÖøƒÎäÅ“O2câÿŸ½?º¢:÷}aîýƽgŸ{î9ãܱ¿s’½wº}ÌÞ÷ËÞÆ£QQ‰‰‰½ ‰ ˜Ä„hì[T@ FÁ^x;}餕¾WîDD@Pà[DQùþUOÕ³æªnÕê«ù¯1ǵjÕªšó?çš5k>¿ù³÷ô3zO¿ÌË–øîU5gÎiÛõ›‹£H&'d:ŠqHŒvhÿߊí/ùVÌ6b1bCò¯§—_ɲ~UX+c2M‰9JÏ,§îJ®%†Iÿ)«ê¥øú2e11&9À¼¶‰1Õõ/ã=91¦†Êû‹cÊ}¨^a˜Ú6îV€IïûgÝ:÷}ÜôϺe:R·¾sq߇©7ý€û¾íŠ c§¹«vá¾ÿ‹Ó£H¦ê³í¹•×ä„< xiǵû¬))…0Lãž!yw›Ór&/ÙÜlìˆræp±ßÀ(’©d®â`Ž‘âß°c0F5ñý´?7L7^(¦‚1æ%Üùs"Ìzqm _gÙÙû/÷~ÄǪô?ûåéc¦Ì—Àô]|¥Ì9 9Ä’=óðì¤ù:tЯ0 )ˆÒ^—¼è’7rœxvWFûæ·¿‹GÔK¯í}é5½1±Ðí÷—cVᩱ³OøÙ©’>0}`0úCxäéš^wY“}¿ÓÔýŠžHŽœùï‡)³¸j Q¢È=òÌtc2LwN˜®¿SÌæœîÈ1¥»þš”{bLMž—¥T€ P cb¡ùU€S~ë> %Ÿ)òò”§4Æ$øñ3Læª?¥ªcê{ÿ#Søö¬_uµ§=ÉZÖ˜d–ÐI[­ófJ©(myOp%IàQú=8¤Ë¯/Ä>â+™C|bÄ™[´ˆ%Z·tØ~‚©F J‚.]qÝ-H6®¤Éá–-™aã0î°õÌø¹þ¹Eº¤ë#1É8lìì~”éã½0ÏX¦ï% ¦1‚Çwâ)¾ßM÷K‚1ÓK¶MÎH;1)+)=‹)=0™«*+óÆôþ'o,Ü~ÑcmF­ûNýþÂ0-yy[ÁY×–w5¦ ™ðÇ€ªGEß5bu·¾sPwƒ'¿ÚµïÌcÆöø«'M}éMÈnºbs&Tº0œdÀHÊ¥QÞün‡tðI~Œ ¿ÕÅñâ~'D—"=‘¬†0„í0ŒIŽ—ðDöx47/-Çûs‹ HW&ûbR’[ÿdXý:H©=Â:{½¯N楾ê×lxæ"ˆ1±A4RbLT;‹×Ã`}%&wô(t»8_Ä}ÿÏO­<] $™¶O5K‰I|;ù1&ìÔÜJ08n%“ré=?hÉÌ­I¦M˼}.òéQOöˆ'*zcjèM„SCåÎýň1å¾ T#€Å0Aß°[¢ü(ÀdÞ÷o{j…É0á¾Â5“0v5w3¢†É}_`Ó“ pßG|œˆèrÕdž¿­“‚1I „™,†é¨Žc§. .âñ“É0*@³Y Íæ§Ùˆ‡TÓ“ï|¸5"º\ ÎÓRl+Œ ”R輄M&မ‹^ö¬’RÈ~Á'¹¬Ò{Ø:ÒZ¥Þ'ÏY!÷‘‡µ0&å–FM´0&](5rÂ<™sÀ»$t˜‹@Âö÷vV¦°, ó xöÄœ¶‘0« aãdzSHèdž_´˜UÀ;æ%0±€é¤3ÎIoLxb:fö¡‡%“ ‡NÀ Û§Ýó ˜1ù+ÙŽœcRßK­“c'fþã°#Oí|V@u¿âf¤Á#ŒI6Žýé)x¤u:nˆ÷?:ÎÚÓéd¼[“2LÅÓƲýÔÒcÊIE×¶˜Ä˜j«'ÏF¨ µR€S­”äy¨@ú Æ”¾:cŽÄÈ.®Rü¢”Ƙ`ׇé§À†‡JÆÀ˜î¸¯%ÀC’»äßžuNW¿ÿ$“€%I „“ü;=ŽÙõã•×ߊyCàJHVx8{Ƴ‡ØÙÃæ º„ |,ö´„Žj0èÒY¿ê†ùDÁ˜°ayZzÎò´„ DÌ*b£ÓÏO³Ö[KÚ`%Ì!7 S‡x_°r6n¸õØÀÎ8§ë ·ÞÉDìÁ;¸%Ì*þùžG°YE01ØFÌ3ZBÂfo»«óŒ˜pÄD$J^×ënÌ6úœ½Ï\º³€“îzx8VLâ`¼Ïxi‹½1ÓŽø ïýŸiÇi‹7ÇÉǾý‡Ã<&8èuç@`L (m'L•»_òÀLñ1&ÀTWŒ ÓGu\¼z›69iB2ãŒæ†€2×?²äÖ¡+nº Ó)¯Â??6þøÀBD”;£×ô«¾è1J©+&kºÖž¨ #™ðﲓx1~7åkRe xfŠuY/ˆ1ÕKYž7HbLl•* ÓŠWw{ïûöMFe¹ïƒ>Áû™H½§_üà"Ü÷±§ësz=±,ü¾oßð3!ã’L•VQs~gbL~˜ †‹Ãä>¡ø‡‹@ÌfsI`³ ñÜi[÷­fC’©9ÕÏ«fWÁ˜"æ%ð˜±ðåÀYˆßýñJxt_Î:¿¿…1MôFˆÃ´Ãã#&KHz$Ì<`:BbÓ#aÂA¼;c¡Të„yè10Ï 3 H˜Àr)ì¹ìº[0ðpÕvL2`”ÐK˜aÀF[ï‘qêŒ9‡acçÈô‚,‹²0¦õÆß&½„YL&`Mfð޹øÄdÂu½îÂdÂÐc®À CoF”Ã|æ0{€9 @/‹ þpÅÍHB/aÞï<6\æè«ÿé›ÿŒ"ö´<3ýÛ7öýþaGʪ'ÿz'bLÙýÿ•ŒSN*º¶Å$ÆT[=y6*@¨¨•Ęj¥$ÏCÒ§1¦ôÕsì( <€À“ˆSubaLr´ø2Iµ®ÆtoK‡„oÏ<ç‚À°$ÿ~' œ N' ±ñâËoÎZòª€J˜4|¼u²ƒ.Ù*lÛ³‡Ö6p%ÀI¦Ïö®dsK<ÒzÙµ· yz’ -a¢SŠX ©ŽÜeC¦‘°»’¬ŒÔYEY‰¹E¤–§&N’Å‘xÿÆ·¿ ßKH`˜0½ˆyFk’‹þmŒ èVÿ?þì,L,Âñ¦/¾²ç¯´6àx öËŠÉó~{Ùc6ÆÔÑv½„ÉG$ñÀ„YÅ!#f½$~àK³ýÀ¹‚šˆ¬ÆÓõ¾ÜôÀ¤Ëâ±ñäê¿›º©SmÓ€IGqÔ±/®~CâÈ8){ÞYm™h 0dö÷ ü0 Ÿ¹ F)X4Q•˜`Ë´ý1ìAP¹1 Þû˜Ø-0L¶K$‚dJõÿ½ÜÌ×c*7<¾. cª‹¬r0 Í$a—qßâe—Ý0²æ(øòYÝÿ}ü+§T9\áÏ @Æ4~ÃaÓ^x¨S§NÓ®‰.â!“<&`¸h5›õn³±£Z“}Øì…2\TÏÒxiyÔ!ÿôÚ§IŒ‰ ÄWàÏÿvSiŒñU¬€…1ýÓ·Âæ%dþÉ3WˆéBAO:tÚM·Ýc:iÇG+ Ük{®ÞnqK.±\  ál·í˜C|ÚC¼ôÚÞ˜mÄ;&±!3‰}D+ÈÈÏO·ò q¶$I1&kA¤mú²0&{nQfÅëf‘àŠéºÞwËôâDY%¹v7/ÁÁ&1]BÒyFÁ˜né;èÔÎÈl#0&Y.‰ G˜FÄëû‘3AÕ`VÓŽˆ‡iGñ½Œ©çO9ë‚«nê‡ùÇ)/lÂD$f5aQ¸“|¾—* —Ôž?¨Ü ›‡øa&û¨Gc‡c D[·«¸9†L44 pKXU/ &ñÇWLWZŒšÂ´¯åiþVÃ(µË1J¯­ô~ë;›w~ôգ,<'h¦Ęš©~þ®MŒ)u^«ƒdr† …¥3tœ]îû×µ,†&Üô­4w3†pˆ${ÇðU˜ xnðå’0 ¦«®ï…›>ÒG>¯Uþyž:)à*€iÛûår !@2M]°Z½uš¼»4<>`ˆ(ÃEa˜œfóô* šÍfµ0LÃE‹a:ú¸Uv Ù´¿ûÉ—_}U§òò´YS€·ÅŒ)zÚ8ÿî õQxH„gO zYeM>ØXæ-!!0œrK‚1霃ÝQX}…åÑÙî1°JJ–H-°&L5`ÂáŒsº¡×%v_Ë3ØoM5Øâúh$z{†‹£0«€¹Ì'ˆ×%ñå,âËyÖÒ-O<; ¾—]º¥_ fú=l…Ã3,ÞųD¢½$3 H–çæ‘30 Ì¥øo¾ã¡aè¸ðncL;ùÍHˆ2LR:“dÂ_Æ¿¤·2_UºDŠYŠf•·ÁòæîrĘrWåM-0íµM•?í’IoúâyQIÜ÷/¶È"á¦/iü¢7àÊ¢ûý .ŸÇì’ì²É0‘dJEƒ11&`ÒÌ É4eþê€áâFk¸ˆÔµï,lÇŒÿe¸èm6áÃE“a’fC’)'™äm1¤cŠœv؇ä¯íMöâ($ÀIgýª›9B,=0¸ÕŒ ,Iq%8uÆ3¦Î9Ès¥ørVïÎð·$s –$}×ß_ŽÉk>aìlL5\ËÝòÐ:–gŸ_"ÐÒõ½ï5u ú£Ç´öŸvvWܪ®ëuf°& “𺄠L&<7÷e|”Ô:i±L&`C¸%lKä8õ½4|‹0 vùÀcã홄“.|ÖO=÷•7õ½â¦¾wò™È츥ïöc¼?9n‘Ì`éw—ÝôË3Ï'Æ”ˆ¾¢y™ ÆÔ<íS|ebL)®QlEɆ–< – +­Ý#k"%Tœ“lKHB,Íxi‹l,´GšÉ\%)sŽöl£3á¨Ë%9G;fœ‘ŠbÆÐ¥…‹FÊŘÄ~³á§Ä°T?Œ Í$¦¯Ýé6§B›1WÕŒRvLTÐä%Û j”rÂÊìT5$–œøa2H&‰ )/ Œ­­­1ûô5ñ‘#ÿÁø-vÂëÛ‚ ôŠÕ‡³DJæ˜&xM\›W/ùCtˆ1%½†²•?Úk³UŸ/ H& Dul)ffÊðO¼é80Š{ß/ ‡Qü I¦ÆWq¹W”Ñf À¤§’iò¼Õq‡‹v,9Þ»ÃÅvÇ“}Xú&’LåVb®çm1¤úñ·ý‡úfô´˜2oµyLaÂõß2ÿ`L>Øsž™sÚÁ†>p¶Á?Ïà™džaXku5þ¹g>!hVÁœRLŸFöÜ\é§ëo{è¤Ó=“СCÏ£ôž÷>Íõ_>……'Æ”ÂJk~–‰15¿˜*@¨R€ÛȯĘò[÷/yî0¦?ß5È?Ù§{ð­e=òM º4R“¤|’1E1QX˜4´cÀùç £Y%1_’Í*àJB/EBK2«hN,>þ¬N¡¥ˆFËæ!Éuð^‚[ÂrÉ$¡KætdeÓß¾°¢i¼¶oØÔMÂ:‰Mû6UßX$ÓÏNyqÍÓ©aAœª·+ZªÒ†Ì‚RÖjTw7Œa’yX¸àR¿mð²^Ý┤dL×G8›ÿ`ðCÀ‰ÀNµ´´èå€1ŸÂEåŠB}Æ),I‡ĘÒQOYÉ%íµY©É&–CH¦â›~!˜‚Ë!÷}×ÿ¢Ë.ë}?Œa $™j2€i¢†Yºô¬-5„\D¹„dš4gUŒá¢…¼2LÆä‰>Æ0’L‹îè>¹{ÇÞôŽ~wµ-X=´(¨y–*ˆe)¡o‹! Æ1/¯pÀ¤¹«ÖD…Ì?xÖD…³J%ÖG•„–„£5“.‹òÏ0˜k¢dz!b5TÄ:(ï"(èyOÜùJé%( Æ”“þSN*º¶Å$ÆT[=y6*@¨¨•Ęj¥$ÏCÒ§1¦ôÕsKÜaL·õ¨ëýø¦£ˆÀÒ_ÀIÂ*9¾”Š(¥ §J^PÉ¡Éë])W’€âfÉN^hIlž‰ÅÖÉK-9Ü’-ù¹¥R.—à~©™^—ÂVRVƒ1EüɺŒî²`Û‚XÿÂR É´hõgu¬Ë±œ13LŽ-Óo”Šf˜FO^pÂÉç~ðñçš/u°Ex©c7pHp_${€á0OØ–èlدl¶x<÷NæÁz! SâÉã ?‘S)`„c䣻ԼÉ1MS~¥Þ˜ôñ/%ù÷¸›ÂW8¬Tðûô(@Œ)=u•…œÒ^›…Zl~@2Öù|Çí¢ëI™ug€g(~ÿ‹€QF'&Ã$HÊÇŸþMJ^ÃLó¥ÌS@EÛñø ³W9ì4|wE#ïå2LÒlÔïX%`LöPïKî±~LOÏS°¬ò¶Ò cŠž[Àç¬*9ÿà[å|p|9ûfŠp%cÎ!®;çÀIßô‚®± säÛ…sÑL‚ãxÉï¼¹jz‰SÞz.bLy«ñš”—SMdäI¨ T æ cª¹¤k¾ߺv#¿«$ÝS$yc½…D|ÓÐo”RP)ĵ’,‚ Ä•Šü·KgK¾q‘ΖBâÄø[*Í-Yþ¬´ÃIµ›vŒvÿ^+oLaÿ¶–-‡ <¤Çìûÿºòk“[×¶b¨&›ðQ~‹~/ôÃ1ÑÜIS¦ÿ³S®zËšnvc:µ/µ­6aV!ËT¯;>þ¤ÎânÊ|R'IÂ*ŠH<6aC,áA‘€ÉWêcIÝÅtÝ ÊäðÑ$$W¸€$É­€Sš[ý9öhXMœÐÌ¿g–¯ÊëGyt’ Æ”äÚÉ^Þh¯Í^6©DC{#RgÐç¾aØ*+\ïlŸCh?L£ìÜûÉ—_Y÷}ÀÈ6Æ-¥`0¶ÁW:ži’N¼l‘›6oùá}nV[Ðp±(œ'–\e šÍgŸ€ašÕ£ 6ðÐÜ/½>Í I M{7XD»g¿xi¢£¦Œ7bÞC*X0¦ˆy |…\0Ñ»&Ê»2*dqTÙ룂|9»ìlaYTD z7}”Ë¥Âj¨U»°ʳ*Vèyã¥;â?ûÇ?’Þ˜2Þ;¹Å#Æ”“Š®m1‰1ÕVOž P*@j¥1¦Z)ÉóPô)@Œ)}uÆÇR wÓ-}˜D‘gߊÑ(~ò®b ŠøV—’xTŠ•"X¥2p%+ÜX»Ç‹»|ô„‡3<- %¯³¥ª¸¥&£KõƘÚÚÛ:>Õï0òaCL€ˆ´¡ 'üAñìrpI×MÉtâ)óÛÞT7þâdKƒj=JMÚ2£ý0‰-óÞ‡Ÿ8îø€HyÀƒ4´x }IO#Œ”L·LòêСƒDmÓxsæÁ äT¦&³÷2ƒÊá0@Kx×ó‹£&/çoOò½œøgÒüˆ&9‚MrEùm¬¾“¥EbLi©©lä“öÚlÔc2J’éÔ³Î3LJN,`\vÈ®Á8­=â¾_Ärë¦};Æ*º€´ö`jc'Æ;9ÉŒ¹°’iܬ•Þá¢ÄvÃ9E#ïѱä}† ¯Ïì«nI6€+[‚s&qÂ4º‹5è•Ø/Gn_4Yð&ìÿÄÊˬ¼-†T­`LÑs8T¢ÿ˜ÐùÃ…shÐy{ÚÁN?úcÃN5…žŠçŸ^ˆr¹d?·©¤×%w&¡Î+ ˆ1e¶_*.1¦œTtm‹IŒ©¶zòlT€ P*P+ˆ1ÕJIž‡ ¤ObLé«3æ8–yĘŠ&þŠ'û€1zÖùf7ÿvpX7E‘ü¯ìY²®Ñœ@t& }1à“•xÜÑäzkW„Å;™+Z*Ž Wnµ³&²2h AL<Þ]K â–56f*æ–l?‚¶+AI¡ãà¹Îè’9Q@Œ)›’¯T>ßýX[P)9)/‹Yˆ1ÕDFž„ P*@j®1¦šKÊRÔ(@Œ)5UÅŒ–§@î0¦Þ}DÌâ[ká» I [ªgL*ÀIEÎØƒ%#æ CA¥p×Ja–Â|,Kñ<-M2Ú–3Iž8qœmŒï%^¬Æ&I°$µüa[<0á%ßÂì‡oñ.)fX›d:yÎòíE“¦I 9Ǔϖ“a’Xr yè®$TÈ!Ù)qâðnb@Š1Ià9|3„ éˆ1i”ºˆ~ËãIü6álà$«TIP9É›xf’ÜjÌxÏã‰áäÊ»¤âhbL©¨¦Ìd’öÚÌTeb "$S4Àdù_´ïûÖÌ5ñVÀ0éźéÏî’Idð `$ðœ`”ÉNŒf̈C2™¾¢äpÑj9úV䬒8[±€ `>Âñx&©Ù‰8‡Në,³ ð¶Rµ‚1‰¿½°É‡¯ÿã7ÇÍ\gÚÁëN)deT˜çÐ9‡xŽœ]OKQ^œ£¹¥Â¬BÐ|Bø5ù 1¦ÌöK¾‚cÊO]ת¤Ä˜j¥$ÏC¨ µU€SmõäÙ¨@š Æ”¦Úb^ËP wS¯;ÑE˜ã3¾uV½ËN+h—?Y â#R‘Û¤p/JQ|’„ ‰*¹VªW‚S÷HæšHïÊÈ0h©±K$k2AYŒI"Ê™–?ñÀ$M !³Ÿ± 1ÿ¸ ™:þôäYË·¢Èe¬ŠóÙ2Ëb˜$à{$ €$%TÅ9Ž?¤’0C À„ÃäçÂá…„üG”Ýt’¤WÄ%äüÂ!!‡’1œYÏa§äÖD²°G²äÏ?ާ7¦˜-0e‡cJY…¥<»´×¦¼“™}L'Ÿyž ©›äŒû~ÁMEe “ QdƒMû¬Û·cº“”°¹ÉÔ-ç¹’èrÏN[2\4Ð7×}We tVV ¢Åaü-‰&@Kø‘ã$Àœì‡O&õÀ´«mð¦œWV–‹ÏÛbHíc¥0/aL>à€±3Ä­ZÀR(s:"xþÁðß¹2*À»RŒeQá.œ½A⬹ÏÄBˆÿæð&h¥º\Š˜O Ɣ宩¸lĘòS×µ*)1¦Z)ÉóP*@¨@m ÆT[=y6*&ˆ1¥©¶˜×2ÈÆÔóއ#0#|k-y÷°G>÷H²`Ñ“¼aÝE ÜYÚ(3†…yCPJq@%#\°k¥`ïJ¡¸R¤›%#<\b&«á™ê„1Á,i¶@¸.€µû…g‚ÙOöà˜r=É4sÙ¶bC¦e‘ò¬ª‡20Let!<” $\bL ¯ ŒeöÚŒUhbŠ#$“x^Ô(râ„É߯˜aBq1DÁ@êÉ?€‘oqF/Šh'F*f¤ €L£ž_®ÃEÇggy/à3L¸ž°J²ÈqÀ’ð.“«„ØÌsòQ£Ë±ò2¨o‹!•*SÔò§µ»q|ªÎ<”ðÙlÎ?¬Ù½0ræ!ÖlÃ*Zòó>¶aJÁ“"WC…øo®æq¾N¿%Æ”Á)¤HÀ˜–ï왟ò²¤Õ+@Œ©z y*@¨¨‡Ęê¡*ÏIÒ¡1¦tÔsY¶yĘ"x#`L°•’Ö´GOš(’Ûš(Ô´ÚŠæO†cvÛ^%É= •BY¥²q%70\Öˆ¥À)Îz`LíûÛÅ™éc †@Ù)ïxÉaâí ÜH¦c;<}é2q,+\­…­Fd2LåªÊã3¨1¦ Vj‚‹D{m‚+'íYÉôË3Î żïK$_áTÃ0éÈæàÄ?€TñßKÿôIDAT‘ÁŒŽgÒ®m†ó/$Óˆ©ËÜ–<\¬†a‚z&‡„@rHØi¾ã#<0éW"¸çc†k!×Eãm1¤úcŠžvÀ£%4¤…"• ‘§ œi‡Òs±f|¸’ëfÉ~5Sˆ³%cn!þ–¢ù'bLù黀1-Ü~Q~ÊË’V¯1¦ê5䨠T  cª‡ª<'H‡ĘÒQOÌeÙ äcºù/ý#0#|«a;‚#Å€bI€“‚ù¤(Dɦ”‚Ö;ŠAË ç›FŒˆ†+%Ä‘{VzN[Œ©ì?bE?’éù—¶š“YwôÃT‘®üQ¶ Æ”­úLzih¯Mz ¥; ™~qƹaà2†7U2LéV‡¹Q@H¦Ö)KMß]æp±J†‰ÂS(x[ QG0¦èåO8q!K®€*µ&Êv0ÖD•¿,Êv°4ÏP –Ü ó6\[´ª1õ5¿ 1¦ütnĘòS×µ*)1¦Z)ÉóP*@¨@m ÆT[=y6*&ˆ1¥©¶˜×2ÈÆtÓíý#fúðí/Ï<¯Ø’ GžäzHòùI2}&•`’€%iŠâ“bQJÞ0pî4"@¥`VÉŽ—+\)lf3½þè ™ŽétòÔÅ[á‰ÁtÆ@?Leô‚<4Û cÊvý&­t´×&­F2—‹d:ý\ñ¼èÅ‘aÊ\m׬@B2=3y©¸H†©f*óD ð¶‰1EO;c)A!ÃW@•=ùNCÂ…²J¹Š8¯“ĘòÓ«cÊO]ת¤Ä˜j¥$ÏC¨ µU€SmõäÙ¨@š Æ”¦Úb^ËP wÓ·÷/ÀC&Hdoã[ ØQI²Q¤H‡I:EX˜+,éE)À—’;L¥(PÉgâªù"Å œ0Õ“C2ðËÉ/n1ë‚~˜Êèyh¶ Æ”íúMZéh¯MZd1? ™N:ýמ¦,Vu-Ë$$ÓðIKÍ–C†©–ó\ĘÊiâ)zÎHDÈÐTz)TÑ´ƒãQ)Žóæ’k¢Ò®Ê™ bLå´ètKŒ)Ýõ׌Ücj†ê¼& T€ ”V€SixȪƲZ³¹/Wþ0¦>ýílÁéÆ>ý­#â÷++‚›¦Â„`ˆ¯uA‘ü©È»ÀIÅ3†ÅˆR‘ovYNMJUÎNâçiǘ„d:Ú ™È0å¾c§†ĘØ©1¦FªãkyH&2L9n eÝC2‘a*C;Z±¼-†HŒékÿøÍèi0bÊ2ãgþ¡‚ɇ€icA”á¼¹xÂ!ßΛ‰1Uü¿O݉1¥®ÊšžabLM¯f€ P*@ ÆÄ†Aò«1¦üÖ}ÆKž;Œ©GŸ‡Â "ìÇ·Õq@@ì6ÅüÅ“ƒ>ÏI˜% "“È'5vqg0&“d"Ôñ>›Å+WbLå*Æã«Q€öÚjÔãoËQ@I&2LåÈ–÷c•d"Ô÷¦Ð°òó¶1ýÃ7£§¾ößl²4îüCÐ̃=Û É^åI}î®~R#Ï@Œ©aýDÓ/DŒ©éUº cJ]•1ÃT€ Pœ(@Œ)'ÍbRˆ1±YdTÜaLÇœpò…_–àÒæ_¾÷ýˆܯ®»ðâØé×]h'Ø™˜¨Àù¯ÿ­óyÝ#2vèáG_u}¯Í;?2Óß¾ø*i}|2!«'|úú­ïxrk~ܹ÷“f>ib2?ÙQ€Svê2 %¡½6 µ”™<üèw¿÷ý«.¹$⦯pßÿò«Ä Z2S ©+H¦;ì_ýñ÷VmØ=\üìó/RW:f8q ð¶Ž1ýŸÿç:ôGGG$ðoÿqxô1Þo?σL5Qà›ßþ_ÿÏßÿèSuèÐÁÓ‘îyïÓÄý ™¡R c*¥¿÷*@Œ‰m‚ P*@’©1¦dÖ sE¡1¦F¨Ìk4A|aLkÖ¬éSüžb¦K®¸îüßüÁ³“³­ÀÙ¿îV²€ —®O>Æ„þcÁW®ß´‹ SºR^2± cJlÕd2c´×f²Z[¨M ÿê¿lž>2ú¾O†)±جŒ=4ýŸL½™ S³ôÏ×uy[ ¯ï¥K—.0^S¦Í1nš™ú~ʳ']‡Íºä™ÉƒÒ•g3·ÃFM|ä‰ÑùŸ2k11¦ ôiĘ2P‰ .1¦ ÎËQ*@¨@Lˆ1ÅЇQ *@Œ)ƒ•Ê"Y ä cò×yôúu~KÂH¢C£w¼âïÌ–gúab¯ŸGˆ1å±Ö›WfÚk›§}¯¼cÍÁ:}´jFÄ}Ÿ SF©2Z÷9[º/Y¿7°å`¸H?L¥$ä÷±àm1¶Tï~øY–½7íxgøê¯MXz– §,ôÆ»É'è@bL ªŒ”d…SJ*ŠÙ¤T€ äNbL¹«r˜ ¨ĘØ2ª1¦¢Haqf¦x €IĘÆ\{÷ª_?°ÿc‘aÊhÎb•R€S)…ø}- ½¶–jò\qøèÀç÷}2LqÌÙqÀ˜n¿¬’Ÿd"Ô³¶Pÿâò¶[ãŒaLó7Ý4iÍ6¯¿¢lO&cŠÝät 1¦UFJ²BŒ)%ÅlR*@r§1¦ÜU9 Lˆ1± d]bLʨ@% $c²]1YÒÜþ>ûœ &Ôõžœå W€[G# ½¶‘jçãZö¶OîÞéƒ77yJ¼èŽî»ÚÈNÉ„û>¦|4ªJé!™È0U¥&¨o‹±F–0&qÅ$SÞ2cŠÝät 1¦U³B¨ T€ T¡1¦*ÄãO©@Ê 7¦”W ³¦1¦J–l¯ déâ(8ŒI\1IêñõƒŸª$&Þr­1¦\Wà O{mÃ%Ïü_ŸÖºôáÅÛÈI¿R’‰ Sæ[Eü¶µ·E¬$¦øªòÈ2àm1¶XY˜ÔS2cŠÝät 1¦UF"³²iŸw-A"³ÉLQ*@¨8HŒ‰€ äWbLù­ûŒ—<ïÓÖöý˜µH¯lý`óÎÇDŸß¦K7÷X¹éÝèNVV3Þ£²xÉS€Sòê$Ë9¢½6˵ۄ²aÝåàJØ€7¦Y=º Á “d_áÝÜ’é­w¬ÚOŽÜ»¡ÂÒ„"ñ’ TV·ŽOu,yALÛvïÇ{É#y([ÞcKöÁÇáAÍÕ5¯½õáKë߉³Þ¦¹Ç˜®˜2æiù†}¯nÇìPÔB8àh±ëœ&EbLI©‰Dæ£Ëè. ¶-HdÖ˜)*@¨ ^ˆ1±MPü*@Œ)¿uŸñ’çcáñÉg_D¤?ý[ôü6{ ”¬ôÄYzLWL†C¦Œ÷^,ˆ£1¦8*ñ˜Z)@{m­”äy\À0 ¤pδzh?ìÄì®´}ÑdloZ?¦_ ç¤PË|*°ÿ¯û{ÌîŒ ¶7$¸ejYÑ‚~/ôA9‰Y®};v"ÑÙ@>›J}KÍÛb}õMâÙ_ÙÓ_è%3í;°&‰yež¨€­1&6„00v:dà!PáGÉÈJ~‚²Ñº¶C)ýHI© T€ 4EbLM‘¥‰P€S"ª™¨½yǘj¯(ÏH¬€ß“á©Áyáå¨@â Æ”¸*Ét†h¯Ítõ6¥pâr /`IH ”À- ®„„ý šÄ]“†ãwµ-ƒ…sâ+· tŸÜæ4ðLØ€/ØLÿLblÃÔiòk“‘â¸nÊ­˜,x… ð¶X¡piýÙ_~Úºöë~ŒiÖ–Îi-óˆ1å ’+,"(pŒŽðŽñx& ¨0^»bL؉SƒsÂN†wåÅ+¼$F¨ T  ˆ1U!JR®1¦”W ³¦1&¶ *rü®˜è)åUÊì×RbLµT“ç*¥íµ¥â÷e) ((%0I —dÞ͘qà–ðQöcÂI9§²®Èƒ³¤ oâ` 66±·á6)£˜åðx“ì{²¤ËÒ|x[l~44®˜„j¢C¦†Ö/VŽĘÊQ+_ÇbàeÆ`I6dª 9 ._×Ãò¥KK¨ ÉP€S2ê¹ ÍP€S3Tç5 1¦ˆÌKPº)ðù§œ|ðÁNVºç'ÿÔá`ïï8±gýŒº]˜'¦)Q€SJ**#Ù¤½6#™”bˆ×%äF#Ê ¨${ðŽoáI²+ûñþùýØÀoõ«¤”‡ùh¬â!/µ®TÒp'ò-Þao“¤ØSc³É«eZÞ3]½þÂÍ}ãü©›:IºúùïúqÍî»s&‹›ˆ1¥¦ªžQ‰º‹Ëb¥Ø·Ž¯ä[ <§£)åÅžY^ P*@¨ÀAbLlT ¿ cÊoÝg¼äĘ2^Á,^ŽØ·í îUSúä¨È,*(©1¦’ñ€*@{m Åä©\tGwxZ‚â .—@&T:°·]0&ÙWL-IŒ9ÙI ó¬€x€Ø0ýˆ¿%˜âä[õ( ±çò¬Ë^x[¬‹¬é8é¨ußÃ”Ž¼2—ùV€S¾ë?ªôâºRÆKâáRÇW²îš0¦Ò¨&7GU© T€ 4^bLלW¤IQ€SRj‚ù¨±Ęj,(OGš¦1¦¦IÏ 'XbL ®œ föÚ V*‹DR©ÌlKNüHÀ3Á€&ìÁ·0ÂÉ»ºHe™éd*ÀÛb2ë¥!¹"ÆÔ™y‘(@Œ©"fôaԄ©&ÀLØÆÀ ûÕÛ%öà#`&Ý“Q=X,*@¨HºĘ’^C̨ŸĘê§-ÏÜTˆ15U~^œ ÔPbL5“§ÊŒĘ2S•©(íµ©¨&f’ äCLð±„d;a3÷ã#v¶ïoχ*,ecàm±±z'êjĘUÌL„ĘØ<ÂÀèH¼1‰+&yÉÀ ò./l›)) T€ P¦(@Œ©)²ó¢T  cJD50µW€Sí5å©@s ÆÔÝyÕd+@Œ)Ùõ“µÜÑ^›µey¨ T  x[¬B¼´ÿ”SÚk0?ùrõß-Ü~Q~ÊË’R*@¨ YU€SVk–墥 ÆTZ#‘Jˆ1¥²Ú˜i* €`Lv:øù§Ô‡ PGbLl T€öÚFªÍká¾?õöƒo­¡T€ P„*ÀÛbB+¦Ù"ÆÔ•yZ(€¶JŒ©BòT€ P*@¨@“ ÆÔä àå©@ ÆÔDñyéz*@Œ©žêòÜT ‘ €^úó¿Y$ìš|Q* cbKh¤´×6Rm^‹ýÛ@E ¼ýñÒ÷?ÝXÑOù#*P¦¼-–)X–'Æ”¥ÚÌvYÐV§o>9Ûedéj«ÀGŸmÛõÑ‚/¾äÂÚêʳQ*@¨@µ cªVAþž ¤WbLé­;æã%'Æ”ñ fñò¥1¦|Õ7KCšùcˆÄCj¦íµ5“’'Š¡û·"ñ¿T† 4BÞ¡rB¯A4$¡Ãlù`[e£(WbLå*Æã© T 1 cjŒÎ¼ H¢Ę’X+ÌS àv Dä)¨@R Æ””š`>£Íü‰©Š\d„öÚ\Tsb Éþ-1U‘®Œ,Ü~1¦tUYŠsËÛbŠ+¯Ú¬ ©VAþ¾Q °­6Jéì\‡Svê’%¡T€ dKbLÙªO–† ”£1¦rÔâ±)R€SŠ*‹Y¥¥ ÆTJ!~Ÿ;hæÏ]•7µÀ´×6UþÜ]œý[6&ÆTy–8 ð¶G¥ŒC4$£›Áb±­f°Rë\$bLu˜§§T€ P  ÆT¡püÈ€Ę2P‰,BĘØ.¨@†€©àN?Ü¡"±(T :hæ¯N?þº<h¯-O/]ìߪÓ/·¿&Ɣ۪oBÁy[l‚èI¹äÜ7ÎiǵIÉ óAÂ`[eë(WbLå*Æã©@SX°`A?ûÕÞÞÞ” Ä¿èþýû[ZZâäP(][[›ù“M›6ÉWØ0÷·¶¶b§ž_Ï Ë©â\:Î18[ ‹sªÆƒ&”–¶DŒ©1M‚W¡IT€Sk…yªĘj "OA¨  U€fþ„VLF³E{mF+6¡Åbÿ–ЊIz¶ˆ1%½†²”?Þ³T›,  T€ Ø cbC ÉW G]ºtôäC™™ð•)‘žÇà‡òÑS=FÔÓÌ›ê…Iç9•ªóxÄ—#¥RÌz׋ªtšëiµîô`ˆ,µæ©M³.—¦½6—ÕÞ´B³kšôé¾01¦t×_ºrÏÛbºê«üܽ ÐCÒº¶µeE R—Ñ]°Ý}rw|…óµïoÇ66à_É·å_‡¿ Õ*€vˆ†Šˆa.İ« R¾’o¥­V{Iþ>» cÊnݲd™R@(Ð*@O„ãш`Àt„¤Á»øæ›"!lð+lãxuVGX"=XeÒH>â*Âɵôø­„´3}#éaBÕèWÂåÈy«òXR"ez$cz ͘ž'ƒŸà¥‘æôþú–̘…Õ‚èÁz9Âd¿ê)ù·OâúH&9L+B¤Võäç8›†ÿócLòάgÃÏE@óü‚%ÉåÔO•Ö¦‰1IÕ›d’Ô¾çüfÁM ýê%a1¦$Ôó@š£1¦æèΫÖ]bLu—˜ 5Tàóû…UÚ»¡ 0>bø({ð`?’ÐN —^ŸfM¯Óž©†™á©¨@  ™?•”¡,Ò^›¡ÊLAQØ¿¥ ’’˜EbLI¬•¬æ‰·Å¬Ö¬Q.0¨KÈpKØ/"‡,ضà´Óþ¿îG†Ãh¤huâ6 €Ú'&´F´XõÏ$ß*i‡„Àã‹ ø¨Æc¹²b;OµÚ@*6ðã‡~o1©Vƒ™O”Â3Yã“â—é‘H0áH‰kÖ¡Cópù¹§\8³8ûÁKøÿ%Äð`Læ¯<¾ #¸’¸Ò—8 Âñf´@oL7NÂ3éŸ4,¨œ`L& „Kk$úQ‘ G$’â˜P!)Ž HêIKg:sò\ÅQSdù¡y~%Òä‡&_¥ÕdÖ¦§tžJTN î©*îâ<ͦ®‰1ÕU^žœ $ZbL‰®f®rˆ1U®I¯€²J¸4¶wµ-€+&pKÀ•°!n™@/WÂWØÆ~…œp<25¾ÊxÅ&(ðán+–œ¤yýb 7áæÂž}Ûš%^2' Ð^›“ŠNH1‰1%¤"Ò}Öìúh¤é›O~¬­ƒ~ÄÆ_~š†B0)Q-†a†acºƒ4¾²¥€bI@C„OR^Û=f÷Mx/‚4„½²ÕÒQq†¼š|’ÆCi‡V*ÞŤ¡"Ñ!S:ª¶¹¬Æ$h…àx™„A3ŠUí5áפb˃T›þ>÷ x(èáaY°G}©Zâ•Gý!™ÿ`ù• â‡NO(¿ªc¿I\1‰S(Ol5Ø„Ã$œYíRÓ±Y‹Æ˜T19§ ]zþ8“,°¦BŠ`˜ÌŠ0)(‘Ýì üLNÈ^žó›ÅT:-Г–NF†ýç—ÃP¹Š¬%ùFŒ)ɵüQú*@Œ©¾úòìMS€SӤ煩@ («P n–'‰& JØ–sb?襥÷ÀñuN2UpQþ„ ¤LXÈ®ø;Ël˜ÞZ“²â0»)R€SŠ*+Y%Æ”JlT^ÙÓèR`¿á°Få‚×ɇh…Á°ŸÃ°Ìµq¼d¢KÊ‹`¿@!81¼$l‚œÌÉÀ%]!êKqæi´øVÚ'Ð%m«r<_TÀ¯@m1&=¿I€?0ñØÎÅÞ¯$îÑxX²¡,΀ î€_y~î9¿æûÁà`lÈNÙ#|’^T¾2Y l›“çüz¤rž »€_iqQúg⿯€ÅW„A ^†wl£± ^ƒ=&u$’6~‰Œ&ˆ¡ü<ÐÃ$ò_¢,ŒI.*ð N+DŽ!òcLÖÝ­{w)¯dXq%‰%'ÿ/u†„ã#0&¿³€•8 %RDR#%1&QLtƶÀaøh†ç“>ÄãI*CÎÍN@/*âàHþókÝáºr Ù#1ædÖ¦\T[…ÿüRjbLÕüù[*@¡1¦F¨Ìk4AbLM—¤+ ¬’ KxL’Xrò޶/²´Šß&ødRLÀžä+¾¨@ösm° mpçì—%l¢Ęš(~/MŒ)‡•^i‘áo©uí×1¦mïO¬ô¬üQí@’‰Ã°Ì5 JâÏF‚ÇIù„‘9áGôøÌ)Á%]!ê¤5ŠÛ0màêÐPñQ|2II4ZbÒ Æü5CÚbL~oLŠAȆØÔ…»»Çèn5l_Ô*ìû=~Ž_á' xÎoJ¨ÄƒÚþeÌÿzQÅ5„™ÀÏ£ 䄞_ýKyü øK¤ À"R¢fÔ-¯™)ÐV¥5*™„âIÄ1õæA‚üq°þÜωç&è¹>z(Ck°ä†Š8F)@!üðQQ? aqë)°¼RdáŠÌâ8”Pr¤¸&ò{YÓ™dœMÏéù­ ÊbÊaæÏUd)¸ðFf1õ¢ÒçˆòZ"Ïù¥txéiå'xaC~e_ðMÝã?¿'·IþŸÐS’k‡y£õU€S}õåÙ›¦1¦¦IÏ S V /0IØ¢—Kx?°·]¾¨ {ð>™°G¶Å9SWäO¨@*sÈD©¬ÎôdšSzê* 9%Æ”…Zl\2ÑSã* WW sÈÄaXæš‚pÿ€û%pKx—òM~m2H $'Pöà0l+J’9%X ¤+€æ'­QÉf’f WLJ/I+EÂΤ‰ùkž5ĘÀ÷ÀT6Ô‚Žmq©"îR$ª”Éa(´ ÑĘü˜Äµ‰çü¦Êù#1©wÁ•Äý ®®yPŒÉôX#Žd<SX‰ôHœÜãý¥yµÍ+S(Lö…JU¯€@“8cªþä991¦œT4‹I ÆÄf‘Qˆ1e´bY,*@¨@Îð;d¢€œ7‰ŸSDæ%TbLl å(艮˜Ê‘Ç–£€ß!‡aåèÇc© T ± ÔcRw#JЬl“N€~à)ßb¿crBBQDcLŸ+þó«Ô&<$WÑkIfô%¨ä_ÞcBnM*’1Æ„ƒ=%Òü‹‡'¨æo&±­‚˧ø#øåSŠZ•Z:C¼V²2I‰1U¦E² 1¦,Ô"Ë 1&6 *@¨È¢~‡LôÅzNV™ˆ1%«>²žbLY¯áš—Ï㉮˜j®0OXPÀï‰Ã0¶*@¨È„õÀ˜ Œ¸;  A…—„@ô#÷Á»îîG1 ua¢{$¾•ü\b0yÎoÖ‰òFz݃ éE5º“DªŸL¦7&Í¿‡…’ð[%ßQÂ0™ T&š A¨hĘ$4/C¨1¦V ³T ˆ1ÕBEžƒ P*@¨€é‰>XAÙË1¦ìÕi’KDŒ)ɵ“ȼy2ÑS"k)C™22q–¡ŠeQ¨ 9W N“F¬&Aâ€ûèB¾GŽ”d|…wÀFê!IÀ ý9Î _ùϯ*ŸälâI1&q³„¯ô<ø;;tè G*ÆdfF*œS€'9¹¿D ]É•»ÊyKcñ© å*@Œ©\Åx<ÈŽƲS—,I‘Ä˜Ø ¨@†€Esêí?y?CEbQ¨@ ˜™è  !ùÓ¸ cŠ««…Ęj¡bÞΡ™èŠ)oUß„òš™8 kB4ù’o¼tß5MÎ/Ob(À¶C$R¤@­0&¸,òDMÂGñc$þŠÌo )–„@;yöèGù•çÌžƒýç— G…ƒñ.{<±dîñ Å Ì¿:j2³d)‘騿¨ T ˆ1U B2¢1¦ŒT$‹áU€ÛÈSúÄíjß¶ ‰E¡Õ) ™è :ùë¸ cŠ««…Ęj¡bÞΡ™èŠ)oUßœòŠC&Ú£~“¯:jÝw¦nêÔäLðòT †l«1Dâ!E Ô cJ ¬ê{©)y#%›šru^” P*ˆ1e Y*P¡Ę*Ž?KºĘ’^CÌ(CbLeˆÅCó¡€8d¢€|ÔvóKIŒ©ùu§cÊSm×°¬pÈDWL5Ô“§ŠR@2q–ËVB4$—ÕžÊB³­¦²Úššé cLñ­Y/¸€jnšUp^— P*P+ˆ1ÕJIž‡ ¤ObLé«3æ8–ù˜ž}öÙN‘¯Ÿüä'ÿþïÿ} ¿Í’Çü÷¾÷½è|òÉ»wïŽõjöAïï3¤#½15»Ru},w‹nÿÇsLÉÿHÂû„›N;4á9ŒÎôG-Dƒ»[ªÚ]v3KŒ)»u›Ä’cJb­¤ O[¶¾vû=W¤ £ÌbúøôÓOû_}AúËÁT¢À¥}ÿ¿&QÉ/ù*ÐXz=úÍÛŸ<´±×äÕÒ­À ›útëÕ¦âtƒ¹/_aÆ͘1£üßñT  `èÞ§O¼§#»ÌeĘØ.¨@~ ƔߺÏxÉó…1]tÑEW^Ócüä™iÒÌq“f^qõ N< Hc'Ò˜‰3Ý4cÌD#M˜1ÚHÏ>7]Ó¨ç¦[i¼™¦?m¤‘FŒ›¦©uÜ´Ö±ÅiÌ´gœôü3cžÚHÃÇq°‘>QSËð‰-ÊÓS[žš8è© N:a ‘ `§ç éÉç6Rÿ'Ækzè‰ñ=||¼“ÿ@!ëÝoðÿó÷ÿãþGÇÒq÷wŸ•ÆJúî÷¾Ô#ù=Áûï¿ÄQÇþê‚ßã‘#ù¹e¢ZËyüÆÛ%Ú} ¤ÛûÞ÷ý?TûCO¨}à³fu€Å½Ÿv}#Æ;ýžÕéyú½ Ïß×iG÷Ô³á½\Pçسi·Ô§y{³Ð~¬¸Ó,¢ï*ê¸|½–Ù_ýË÷¾Ù ·ßÿ˜ÑM¡Ë2º©swîn iQyÏ1¦¼·€Æ–ŸScõÎÆÕ¶mÛ†áb·‹.åp1šäRÀÒ¹sg46ŽR’\MuÊ ½gžsz›5kÖÔé<-¨‰ ~zÒ©HDj¢gN™·<Ôr`åÖÆî"· óÇÐýÄ“NýÓU7aO’)½ÕMŒ)½uÇœSj ÆT­‚ü}BÈÆôРÇvîýÄNüé¡ýúü w¼s@Ò[’ÞFúéM3íùx»‘¶íÞ¯éÝû­Ôn¥­NúhkûG[w}´ÅH›w~ä¦_ßùáë;œ´iLJNzëÃ׬ô¤oÒ†7?ذ]Òû¯JÚöþz#­Ûöþº7ÞCzEÒV+­Õ´åÝ—´fó»šVo~wõëû$­Ò´i_[!í]ùZ!­xmïŠNZ¾ñ+m°Ò2M¯¾³ÔIo/}õí—Ö;iÉú·­´îíÅëöhzñ•=š^xeÏ k‘v#-’ô²•iÁšvMó×´Ï_í¤y«Ûç­Þ5o••æjjÛ5ÇM³Ûv¶NYúµøæì•;giZ±s¦•vHš±|Ç¡‡|ŒÉžIé8fêBÔ#9hšJh›¼l¡©\ã-þÎpÇ^§Àtô±Ç™¡ö„}`@hö{»´ßûHû=ÔÝôuE½\xçïÜœž-¬O³;´åVòöfÚ•i?æïÄŠz0³û*î»ü½–vYÚ_IgõƒýÀcãÐMI²:«VÒžêúÛ¢0)ÿ-bLI©‰|äƒS>깆¥´¦ŽÓ®Áñk¨,OåS@¦Gž‹Ævû=ƒ8PÉU¡÷¬sºb¶aѪ7~D’)WuŸ¶Â]:ñ¤Ó–¿Ú¾|}{§Ÿ“dJ[ý5#¿ žykkkëÒ¥K`AKÎRêo±Ñ±cGœï%Õ QÓqM½µ-cw‘Žc.ËSÀf˜N“¡{Ë“cH2•'_’Ž&Æ”¤Ú`^¨@c ÆÔX½yµ†)?ŒiàcJ)y6`§ÐƘb¢K0áoC*0dŠ˜lC¾Ë0ù&‡aÚh0LÀä2LÀ›a*`L[Þ[Á0m®˜a²­þ¶á¿À0m(Í0U…1 °€b†©ÝË0­*0L€0¦b8`æòt`L˜IùñO:Žº“ÅxÞ¢qÉ•$™Ö‹¦ûBÀ˜®»±·¿Wt¸¥wÀýÒÑÇâ &8ƒØÍ€~Ï 6+a˜<¤fPÿ¦€¦2L«‚0&å2ý½™Ÿa‘1)…€`šð¥I^c—Š1ÁSaò`LËwcJПS‚*#Y!Æ”ƒJ®aÁ0a¸8cÑË.ÖPUž*Pa˜' kcúÜM’)/E ½k·¼'U¿°m뎤O¦¼Ô~ºÊ) ÓŠWw[muó»K×í"É”®l|n›2ó¶iÓ&IA&õë×/Z¡—pŒÒKØsÈ!‡4^· \±èÖÆî"5Ê"+`1L¿8ͺ"É”ÚFBŒ)µUÇŒSª ÆTµ„7“Ãn=aQ7hD޳z?¿ç¹¢ß+t}Žû%7næ›h ¹˜N˜LR³ÏV²Ÿ·5¡[“T~,9ÇSÕ ÓžàIÒˆ+&ÇÜ|7æ¼ÕíóVï2]1®ãvaLÅ=•xŒÆtö¹ÝÌ> Û$™šóß'ÆÔÝózUbLy­ù²Êí2LkÙ.ÞÔóÖ²N«c„Ö°áÆ–žkù÷TVŠø¿ÒAoÉ`.ñÏ=Æ#ŠéÏFDÆ`×Ä·bݬÇK¦G‡x6¹­ßÀsÏ¿ð˯¾*+ò /Øn#ì”uÂì>*yÑT?×¢™Á0i0wùæÃ|ìò•«Jêà9@Ÿ+aà÷4`QÌ|êDÛ(÷¿³¦äŸXVæ+è ¤Œx‰;¾ê¡€0Lmwk[Å3£x(Ä|Úê‹kvÿ³S&M™VîÕÍnJýß ›S%ÒÞ°Ó3ß"ÇÔ»—.·D<^¨ßÌ0# EÒLïJØ–;†C‡€=8RÛ’bLدm Ûr¤d[Ð(­Dü\)¾â+࿵դ»ÐQ þò¨J³Ã—»^ž¡Žt: 6ÇEr¼|•êDüzᑵR@¦è¡ûÃ>ùÔ3|òI­.ÊóÔ[bLõV˜ç§ÉU€Srë†9«JÜaL÷=ühÁ¯~•\Ûü}ý-ŒI‰%ÃN_ –¶ìZòsK›w~Š.‚(9V|ï%XôÕ–¿a{‘û¥W‹&ÛýÒ{’0e,î—"<0ÉÊH¿¿0Ùþ´1‰ã&ÀH®ˆazõõ\²ôÕ·5ÓK@—$­³Òâu{4© l¼€´Ö"‚!;0Sd,¹X~˜À0!=#Aå¦@Œ „GU»ZüXgRÌÉbϵTJ÷Ë{”K2áAÚœ )9,Íf±0?âyêÆŠéËû÷„ # Ëäܳž¬ZæúÆtC¯¢^Ñ@6ÑŽ?ý¨cŽó@Kþn0]Bè£—Ìøqf¿gõx.²ÈkvtÀd»"óL& ‰‰i+ÝZ[—éÇ´ÿ8š*òÃTÃ4·à:Îò'“ºb2ÃÉE`LðÌ”ë–ݬÂcj–òù¼.1¦|Ö{9¥v¦׺ÃEð5íµ.âN‡ábe$f5P¢QŒµþ¶j¼bˆy-Sa˜V½¶'°­¢§’njÑêJH&Ôš¨´(ÁSdÒÃì¯8ÀÖž »Þ½tL‰x˜GºÎ¼¡yh›A“þMú1cÂNuÔ$¬R Æ„3€ž4û@óŽSóÑZæ›Jô­­šîÂÕ˜Õ-q=}ˆt#r’N @1&ívpKõ@"óÍ)T†©äнÿcÏ’dJ` †e‰SŠ*‹Y¥5V€Såé’¢@þ0¦þz})‰G%;Ý×È9çv •‰¥üÐR‘Ë%›[rí÷‘èRˆï%/½ä`2é¥`L>€Ékéw¦:aZüÊžò&× `&ug2ßrgb§UENM `—Æ’† X€bLJÌ´½›˜Éï©éfRŽ´ý0훀Cav)Ðc¸¬<’)ÌX‚™s©¦H°G׌â+6&Y3mBK{ô·²ÎU®%=¥¹ì,>ü””^6ÙùÆtõ ½´,l¸ñ1GŽŸvÔÑÇiïÖ VLmFÓKa®æbLïÍ s/Wä[n£eW3û4À„ÿQÇT3ÄT ³b?L† =UcZ±3°§ ôÆDŒ©9ÿÊËs†Àæöç5ôF­®±ÑŒ¨g-}ý‡e’LÒ!HoãéjÐ0Ðÿ˜t£ Vzþn°þêÏÍ>GþÔžz÷Ô8> DåwÈd¶.ó/o¶.O#D6ôTfï$Î6¤=Ä«bÞ x˜*  S¨ÉÖŘÐV®zë¸ËóÉ„~Éì½¥› Ę´ "q’ðöYï™7ô` bÊR@ôþ rB¹‰VÒ%â%{tȤñæt†™K¸ÈÉÌž÷Öæ‡³îbA™Ý…gT#(jÙëË]ÏB+l»f·Ã‰Ód¶¥dæJ¦øC÷%ɔ̚ È1¦ÔT3Jj®1¦šKÊ&CÜaL÷öâ·Çë|ëÍS©Çõ±d8) –bIR!j’Á-½Uˆ$A”L$Eaã?.8r\±ï¥ôR€û¥!ä¬dÞreL®É†ÿõNªÐ “Œ ¾— iM{‘¦Õí —$iT&30“—a²é%e˜,Œi²å)‚aJ 7&™IynÚ 6áQðÛ_äŠÉx¢F-€·ø}9$“ç9YçÖež“ñ€-Çèê1Y¤óÈ:u"È#™Ôóì‘)i™ƒ–‹òHožM{KY[Fû5¼}XÓõ½(%70"*cò,s %¿¿%·÷‹¦6Kú^²Ú¶Ý¼ ~æÜ¾®l€©'LÑäLrážäŠÜÈ}WÁ‡\D,9?ÄþêPñÆÂ0…•#ÆTÿI§"ÆT†X<´jˆ1U-a†O† ÃÅÙ/®5†‹A®˜\¶cu.–E2 À$c9Óש ²¾ÈxO{22ÄÐ;Ù“™âB‚¡˜KÏ^ÁÏu1ºYý§Õʸ"Î&¾Udä©™D¡äÒj~FõºÂˆíÙ?j5ëñ| ƒ[üDx3Ú ~…¯Äâh’‚2h1=g0ÕÓ²ÈEýlÄo'«òà0LO[ “çÙÄÊ%NSáÙÄÂ˜à—·÷eLƒ xBe©Úø(„Šh+ÇCaSù‰I‡(d 58Þl-øè?¿jåùJRp9¹¢Fèµ¥NÅ“4oiuÒ¼=fËt=ï†^.é'Ø^µ3Ï|iSY$“ô¨tyÞ4A"©M©;H*–~©VÏŸE üòsóOŠ?<ޚϞ¸œÇiÎŒ#=W|Œ•çYù§ë?×Ó,qÁ¤ahïgþµIWù÷äÏUƒaŠÛVç·½YÉT%ÆT¿^šÍ 20ó&÷üße"éÐdX¢Ý‘ƒwéÐÿȈHçåð­ÜeŒ[êJ0W¦j*~UÁ­­¬îÂ3ª‘q‹ÜL}„i“Á¾ $ªÍnG›®D*šDÆ2é0LeÝ2Š>™Rш1¥¢š˜I*Pˆ1ÕEVž´ù äczhˆaÿ°àEÉŽwÏCƒ1Yz7’gÃA””UòºY*KV¼$´äã–Œ€q6·€.Åt¼TVIâ+Åt¿Th©ÙSh ¹r0­‚ï¥BB`&ÀdEhZ±óicÚ1s…× “:dJ”7&g&eºÁ0¹«‚ÄN šåZF–;ۓŰKÁåÕï/½!ft9L|tèÐÏÃò’fa—éxu’)xéÏô+™nöì÷ï1§hå·æÙLóºÙo~Ç™¡cºêú^è d’Ä´7ZÇcêhö„Þn0ÈÕ\Ü@™>^Ó<.’^ ‘é„‹0m|'` tÂdÄTOr¡0•a „/•¼œ»j—$£Ë²bÉ)piaLCÆEЖôÆ” $1¦UF²BŒ)•\Y¦ á¢„Îï8æp1>ɤã48[s\‡~bÔÇ Ûbu“ê${„KP¼FMt¿I†ˆæàSL>²'ð´r•è+"KþLŠíG²¤lŠƒåºøJ1&ëʳ8ŒIWÏ›pƒDA‘‘U”WmTz~†ðŸA/gêé©QOe´xUÖÒð«†ÉllÅ ‹øãÑÆÖ뎇cF—ƒ泉È%jˆ†ÑÁ‘T¤¶"GÔL("C9Æl-8‰ Gžó«Pþ¯¤ ð’ a#†ImR5x&OlÕZ;ØN×óŽzÅ —×Þ…(D®ôlpÆ<}ɦΈ]N°Ù’ERQÿAùkˆE_ªÕÿg‘¿’4Q^H5Ï“lüÿ‚ÿ1Vš“¢úO÷4Kyà•ƒ%Ÿê»K®.'‰ŸYRe˜L´Wž%£ÛêÜ• ™Nž4eZÉKHÓ’N@^rwÀ†‰&H£•³is5OŽž¤¶½tœœó¿™y«•ò~Gqµ:sÏSñ­-~wNÀì.䮤£Õ\o"‚YËô¬çîàï.Ò5Èakz‘¦ØC÷û“djz–Î1¦Òñ*Uˆ1eµfs_®ÜaLw?48Er±$|{ö¯»°ÍóÅñà*±Ja¸RX*ĉûÀïoÉÏ-¹A”bx]²' e®P“]zwµß÷’mÝ7è%¯û%Y2+–ìXKHïXiƒeí0,vzÛ±÷Wàé•=/¬E*raâqÂT \‘&øa²¢È•å„ “¸6±1¦oD0L‰òÆäIyã=x¦‘Ù·Õ¥&à€Y ÊÕEñH&ÓJ$¤‰É cR LÌ)¤“t2qlNÛ©UFžÆå¥3þr]sõ×Mçɹï½k#0¦+¯ëÑ+c:òèŽA=áèý4‰{93Åw5g;^*Ã÷R½+„œÛ³vkn‡EÎöÓ S¡3øKoÌâ^«ˆa*vŒé> c ¥-‰1ÕæÏP“³cª‰Œäão„/×s§9\,I2aȧ»¬ü†¼¦ýU!‘{F˜2ðSÐÄÃ"˜žœä´æÏ…°—=§Õ±¥iò\Q‡¦:ŽH&ûâ9¿ønÑlûG­ú[ÕD[¾’A¯™a¡XÄàIÕòdbRz¼ÿ ~õ´"<lɆiM¯òïà0LÃÝXr³ÄÂ÷lâqÅä4¶—wßü—þ%}2)Æ„<‹ã%)YÃaAÄΧfB))öHõÅÁ˜Ä9–ÿüfmê¶´+yÒG%l´ýËÙµA)„rö¦VÌ´<ï˜w†©.éÄ@ZV×ÀkéÔ^‹ã“Ƀ1A:é 4rd4ÿG¢³ÿψ1yº©²ÿc¬Ô¯ß“§YJÏ#]4a³d[ÖŒGjšNæJÑK^ßrÅ[€W9¯K¹õo{pLõÀ0 &¨iM»2LÊ_ÚQäÚ=®ã"œ0‰Ç8ôT‚1EЖĘù—)q-bL ªŒd…S*¹¬"*Ã$Ïò@¡O þèÊ•X \WL¸—9ÃÅK® ™üŒŽ 8:®«¼gà'e< S®Xv1ü I!9FÌ6Ø/ŽLÄÅ…l/2@‡£þÓªtW”o&ðgוK#cx†Á’m¼ûG­ø‰üV|ð˜5ˆÂrIdùJ\òÑ" ÈuÍQ±‰1yÎàWOÎì`Ëåje †éÑCˆNÎ _hû¶T8@ÛM·— ™<?e>Tm݃š’¦"Ð’ì×VäiEE–ÊUšD+ÐÐ~­PÏWP°$%lp9T«<éˆÝQ.!­-Y*W·¤ÂúhzíõWFW#¾QÛ6Ù¥&bT‚ µ?yÑk?øÑÑËW®Šèë<“y¤þ¡›þcòüYp0ZªFëNz!¿7&Ç•Eàc¬8RŠÎì Ìf)ûÑT$øhZ©‰1•uã‹>X&gÎÍl«®7kA{-äe5¤­Î\¶íØN%|2bLr»”ö`vør"ÆTÃê®É©<óV“<ó$5Q êÖVÜ]H¤‚jº‹@ŒIî².T†1Š+¡£Ð!±ŒO´ÈĘjRûy8‰0L…¡»¬–wcß숅ÈãAC÷{ZFdJl³!Ɣتaƨ@Ý ÆTw‰yæ(PcÂèÙ|5'›5ºêE]ÔïÁ®Ï¤÷Á!ic|¿éü«®†y%–lD)TŠÀ•‰%´äŒ#ÍPqbèûÀ5ç?1bJÏ>÷Í~éUE—o|çýCf-yUó(ºtùu·˜iÑêí˜Uô8^²#ÇYþ…«¶Ýxë=&½´ mÛ ·ÞcZú[†OD‚¥_Ò’õo· ›ˆäñ½à~)Fü¸…†ùßãÉJ„ ˜” €I˜€ê1¦¿~ñ~šgèit&Å?ûÖgØÊ?[4nÑsÚvÊdñèù[ž·eÔ¼ÍH#çn;02ÂûËo.‰"™§nÍéxäÕ<Ù˜‡•)`™…×)xÙ/f-ñ¥äß#Fý­9u‹ _Õ%Óúõn 5?¿1Ýìé Í>pøè©@èbú–sz¿â q½ÿrŸv}CGMé}û}ó–nTsS殼ê†[§ÌYá Žyåõ·Îyiƒôx@—zö¹wñËoJw縗‹ŒŒ9ýÅõ—]{‹Ó¡—B¼Ê½Ùj+™“Ç™\„&ûÏõÇ+{: “‹`bOt¹¹m»\†i§b—³Vî´RÁiœ\Â!ܽÕ`L›æÕ¼Ùð„¡ cbãh¤Ę©vâ¯e0L^°`äÜ-Öpñ©·Ù鮫124‡‹Ï½ðFa¸hßÈt¸F2a8ç1ó Î0®3±"jÈ$qM¡cŒ[ûbè5Yɵ[,\òÞQ/˜»E&p!ÏÌ~ýéY¯cìmw5Öc騹›GÎÙ¬®˜„`CtøI 7F“Lª‰_ÙÓþYäÿ%j›pó_,—ˆ‰1á<ž™ùÿÒN ‡é_[›%.$ÖßÕ˜ù‰ù—Ì×aû¶Å,¯0Lm÷HOeÛk´O—÷ŒZƒù+´Õ± ·Ž]°uÌü-ÒV%ʪ,_WLÚV§/}#šd’J÷gO€,ÓŽ‡É‹çøˆ^:fÁy˜WØý[ÄÌ&%pk31Í[‡.Ÿ´x»yw.®Ì™7VV}ˆ]õE·¶âî·6Ô¬éü^» ¹µÉÂѲº ÿ¨FuÀmBX[s.TnB¾šcì÷w;MHÔ·.yö0tÿâËOãH£ “è³Â½£Ö˜‡ÏÜ3šðhýºšdè~×@’Lq´oÂ1Ęš :/I¢1¦„T³Q¾êu[`$›•3•À˜Ä·¿¼0ŬKÊÏF"~Œ©ïýxb™ñ-få"(6ÒøUˆ00*\@l8{¾~OKΖ:ÿúÂÃŽøÉêÍ–ÿ·Ý¯ÀÇ+®¿å°ýD¸¥ŸžtZç_]\ {f.~UfÛl\é›ßþ®bL—]wËÂUÛÅ´o£K½„F1ð7燅 áî‘ÆL[zÆ9]ÍÈqº¦7è%'­{û’«{!©Ï3x\\÷KÅñãdªHS °8  €ÌÀ<˜L§&Õ`Lû¬™µ¥óÂíÕµqËLʸçéRW}ÃLJ§k'‰àúG–œpͤ§gmš¼xû™½§#Ñ{úñ×L:£×tÿd±±úÍÅ%|2Õµ\^¦!ÃÆ‰Ç/Ó¯ƒ—œuË il—<´è¬[¦c$VÔÞ®žtõ Å…Ææ2sx6éÑç¡’Ñåb–…‡•­@¯ï~ÑÁR€ ½gY S•T| õnÙøíñ9Æä·]!6~ï“©aã3ª~Âü p>í“©ìñYUmupçƒo­‰.&ÿÒÖcJùdʪð).×”>ï<ìàš‰ÑEˆžyü&ßÔÕÚÌ%.šø¢ÕÅaæÍš|»Úš|+J­–¡gÞš×vª¾µ¡Þe%€ÜÚdp·¾sÌ[Ûó/½é‡³­îb »‹æU}>®ŒA{ëÚ¯¿²§4Ì$ †îaf³sƒ=wÃ[†.Ÿøâ6§ëeõo§÷šæ<'C÷~$™ÙÒˆ1%²Z˜)*Ј15Df^¤ `Õ$‘̰ì¸\\ë&`(ÓÛy=2Ú€sZÓ}øcº {„Ô÷¾™˜ LN$™¶s'ïdöÖLêe¤°a³J¸R ±¤HZBê?d¬øHâ†~1çßqÿ³~u!¸%Øû-niÓ^!–L£>lùÊ-©×¥i/¬{zÜœqÓ—Š]¬½†iØX cº4lìlÇÆÿêÛ£ŸIü”<5v6’…1]Ý[|/ 3I0&¡—FM]òäèÙ“æ­•àq#§,ÁÝãÏÎ1e é½Áãüô’0…º_²ç4™ñã SÁI!„œ?*SeÓ+o-ÀôX[¤ºbL2“2 “¸{µ#ƒèì›5“rMa&E&‹%>*kþªvL¦ž¨µõN„ºðâ뢣Ë5à_ÉK4W`L—]ssX§‡ýOš‚F¨x»ÁÈÞ^—À'¡¿’v«ýöHw7iö x›3Ãb ÆtsŸ{¥¯Cï×:až K­ÏÍ}æ¹¹ÒËÝqß`KJg*š‰~ŽåÎ<§›I/¡3í%¥—г¡CSsÊüWЛ=ûü‹a²»2thèÍFNE'¶gÖÒ-‡þðHteÒ=>jRëä%Æ´¦ÐÒø9k5sÜœ5B/aLcg­>Jׇmø–9ÑêÊÀh±\ßû‡h'ÜÒ·¾ýÝ ³–ã}æâõèëг]znæ2l€Ô<óWÝ:ýü44{0Lذ¼.¹]æ•ÐÅ À„NÌõ*÷ú7 ˜gœmunx Gß…"ýÛäùko»»èÇЭÝvW z³Cx¶/¾ªçñ'žrþï.0ô9tbèÊðoúyÞï.CØ8°JèÖà¸O<¥ûÖž;ûÀôOÀ˜VíêyçÀ?ìÈ?\qsÇŸžÒóŽÂ0™äe€Ó87äee¦/®ý€‰SƒÿƒÄ˜,xÎ/GŒ)ç @¦£:ÎXô²=\´ aÿpQ 0ÞKܯ*Vä=0—¸bÂp>Mq?Âp±®$k2 ¨-$ f†ið°qaÏ&æn¼D½cºí‰BއG€,㾲ȳÉõ·‘djFsP[oÌd1LçtužÌ~S6Œ µïÄçZ°åº–Å– Ì6ôÂÆ¯O¦ö€BäJ]]ƒ0Êãç¾J’©uŸ¶kzÚªf²¦“N[±a·Þ «í¶* c,ŒiÁVa˜ðÀxñƒ ï|f•N.€G±M¶h«“_Ür4I¦5ŘB`¦83oh6ðP‚µšh90ó†RöÝÍê↷qæ-q¢ê[êÝE»È£â¹ŒY‹z ÊlÞÚØ]$®Ud(Cž¡»f²¦“N‹º  ‰0Ðp¡jq½ÞÄ!\ï'—«oÂî÷/üËð63άÏT³Â“dJV«"Æ”¬ú`n¨@# ÆÔHµy­ú(†ÉQ׉…1!|{ÚÃɉ¤À˜î¸·E©#ÿ¾=ëœ <Š¿†(é~‡Ur½+âJ²,Ì5É ×:a.’K°å+º$Û-Ÿaø‘ÆÍXjrK0äkêôóSÅ´?å6<}Í_ù†mæþ{=#þ–°-îI`ì‡ÿ©1Æ%x—@K ™`쇫˜ù%fÜù]t Ž—`æ·\•¬Ý}×€á°ôcê{f¼´ãÝkzÝ«¿]’ùÁã¬èKz©8x\P®û%Ìß“`’)þé›OÞõÑ‚š§o¯=â¨cÇN]èÁà¤åèìfRºõ›+>± §Öb'˜¶ôM{­³±ˆÐ³¶Þž€5H2Õ§ËMÇY1]zõM½¢´½'GNAS,ÙúûÀ+¯¿µgŸûÐõcB£ió—Ò€N‚ÄuèÐáŠën‘€“ì9e; æ&+&º»›n»§ÓI§aC0&K<Ò*1Ñ›^‚W¹Ë®í­.—dㄟŸúÈð‰èÙ@dÞpëÝøS€ÂìsÏ#Ò³f‚&œ_:´AOM4tz*q¿4{ÙVlã¿óîÃ¥C³z¶—wƒÈDW†íšžý¤CŸÖýÊžâ{iÚâÍ —îì? Üz0`Lx¶Çû° /â Ê ¯c;`òz`2{ª˜Þ˜‚&™«}Sƒèÿ3Gðyý2Qz+ðìV{›p³å–‰)— l[ý"îÑÓ®1é%Ü‘•w—»* 0%jzvÞf.Þ?æe`"‘Û  ÃEL5ñò„ÉQ`ÙΛͥ˜Éa˜žñlã®s²˜Îx²ô`[yïýr÷ª•ã( œ †ãÙÄ!™Ú7°gkœ=¾î…à ÏL6ÃT˜$ñ@!v 9Ë· :3>j_&÷ÉÔrhê\©f0Œ~’iáìÆ<—÷ŽtËØV]˜Éf˜N]þj{Ô[|[”E€h«cl†iÆò·¬pr¶»ñ”à²Z0Ù¢­:hÂø±é3'íØïú7×3¦83oh3VØÁ[¦cò -–Å%tá½(œ\É™7„D̉òM/fÕ·6Ô»‘yè EÍ•áät%€ÀÙÚ]ŒŸ469C>æ$ Ýf²¦S‰ºã9QM¼ƒaÂs_×¾sÀ0!É ~45œ\ÄÐ]H¦û–eCØ´—bó{Ïâ9®d ðt-˜K*@ÊR€SYrñàä)ÐÚÚèØ>Æ„@tžXtÉ+`¬ Æä™è7­ï¹·å̳/(É$ù|)ÁR°G%…N ŽF VI¦üŠ“e¿o³'V4dÒY¿êû=b'Á?~æ²gÆÐ%lÿàGG9Ð’½ÀúGž‡dõÕ‰Ä@L%€•‘VZoL‚.Ip%¼ƒ^Ò€q@—e $Ð’DYÆô„½Î~àx >Kn Pìýš0M‰mD\Â`á–c’ K’""ÇÅ¢—l¯BEî—|¾Lý0ÉÎ8ÓáG5tÑñþi}Ùóøª‚g¦°c*Øÿ‡ñ̸YEœø?·ÛÚŒ4ëIÃ]X?xò«Öì›m'¸fÐâ«-FÕè‚WKjÇUam½*sÚÙ¿¹÷Á±þE<([ cúÓU7EtzOŒ°0¦ˆìÞÏÛζ}ÈOBÆ$VXL›Ô—r¦c9“Δ¶mEôÍ`@—n¼íttOŸcù–³]Ê¡‹ƒ'9$„—rnz{êÂWp¸%$q2‡?:1™Ò³I4Lì‘M’Ùqa½ % ‚ (!ä°Gè¥Þ}aû?;ô<0¡tIøK˜@/a»¾ùÏ<3]Ý/Åïµâ`L›ÿ÷“³TŽT€ P*9Þ¿¨Ãßÿÿ9qÖ²€á¢‹‹_#î°ë‡ÉuóĴׂ±×ç„9Š>éô_wíýW0¬åOR¡À£†»YO†fî—§Ÿ}Oÿ'<ÍæÐØ®d‰˜ú0TëŒéÉå]ïœ_®VÞ'¦mT'òlâ·öI“ûýå=¯üáÿýå%ÿ‡7MW`A¿ßyž SFW(Ä4ôŠ LÆÞÖ“éÀ‹½p›K ÉôµøÆžßÿ§¦œHï?ÿ_ÿßÿX¾¾½ÐS¹kÀÜ™7ë1Sž1Á£Œž¿E¦È®´©À0™Þ¬ChKA¾û½ï¯9ï?§N(f¸ À‡ÅœyC›Áä›Ä’ôۃcת«̼¡‹+cæíøÿÆ*hº1omÁ£h3Hn9ÝÅŸÇüçT ™É´(1tÌtÞ…§ÁÈÓ¬@søÌM}[W?5cÆo½žX†¡;ð&tnVÿfûÑô Ýá²W@=IX„ðãSþ¯GWþoiQ/óù|å퇳e¾`i¨ˆ¡1¦"ñ$+oJ*çÏa,Œ)ÐS’K–7`L·ß;ÈŠà˜^ßwû=ƒ€1™®’¶‹°$åK\Ê$Щ’éhÄÃ*)´$ÖÄŠ=·‚4äéI—]{ R·?\Û<ÌùÓ^Xg¡K¶-Èð‰ˆôü¢uA F}˜íM£>~¥Ð¸%$ì¯$bÝŸ2ÿÁ•Ôº/sÍ×õ¾Ž—`’w a±bûÖ»Z-]²ü-ÁUÉË»oéׂXK0óc6nÍnpKkI ÿŽš {¿—^² ÿñ#ÇEù^Š F2ÅÁ˜À´N1}ãåO¬ú;ÿ0÷¹ ‡µíêSó4dÔŸ~ ×Yëv9æ—^R€IZfRd!fßf,{ ÕN`…lXðê."4äz¤uæQG·jÃŽ=ï}šÆÿ5ó\‚1Ƶ”Þá,aºð÷„¡}  *½¸æMxW’„ÀpxGl8€˜Âh>úÌ$Йˆ'.—ÔÉ\`4Ìi‹Ö‰?9éÜð.}ÝçtësÏàacç\z 0&‡ËDÿgK‹)]Ü:«‹ƒ¿%íâ¤gS.}ÜÈÁë’z’CŸ†® ÿôf­“—ØÓ‘N?&Ó3£[7{ è%ôiݯ¸Y}/Á7|‹@š`B8ËÓJ Dj†©»Œ€,Ë *·ÿ¡3þéžìõíƒL SàÖCÞÜÁN`¢P`À/>wóAË`Ê¥ï¿!d¸è,‡ë­pŠ3t¹ ÕyÞ㯞äGÞ=aôf„U¶'þâçã—ß³àõ~5÷ò„IP`æ–³'ô§nê„EÉkÖ¬Á€pQÛVÿ³ låöéY¯ƒ qš46B,ŒÉFÆÑÞŠžMV Ãðl‚´£Ž:zá#··»çË\þµ›Ð¥_ó߯ǃh¹¶OkÌ“-Ð*f% AW#O¦˜|°0¦'œ¥ügôš6váŽ&ÓO‰ƒKZ‘+5—¼·× ›G=ðÙ¤¿4A¶·ä+ØVásenÿƒŸê<Û*½T˜E)ܵ‰òì¼-²´ÝÔs/¼aûa ñfmDYÕ¶ ŸÖWuÿÚê‰w²­&Z<—²ì¶/xðŠ3ó†fƒÙ6JÁÌmø™3¿ÕÅ-p»¸¡2óväOV=yçžqw'Z±ä÷1sXÅ­ÍØØät­aRϽcøªž[êÖ†î¢ûU¿›²æ%ÛîLÂyȆaC÷Y[:ï;°fÛ¶m:uz~Áꈡ»šÀ0!¸ª,Ä$¾ áŠiÌ‚7†)rè~äÑÇŸÙoöÆ{V쬽‰$õÕ°RŒzå;x¦ÛùÑÜjŒü- ©T€S*«™.(pÈ!‡Ê c ûqê– ¸ ßžqö !ù7|Γ‚|)Ù‘·›ü…ƒa¦Ä¶?fŒ P*@ªS@†‹/E%¶—<hМÖ9›ax ÅJЇ‹`˜N:ùôõ[ß‘{Í»~V]®ùë$*€ÐŒI&Í+H&Œ ®Üñl‚P;0ôm]5jÞfx79þšIbiýºÆ¤w¼áäÄW.ÖW,\º^[û»Ÿ|ùÕWIÔ+cy±dšù]€IKiM¤Ü=(´ê7ZPˆà’2ó†ÉµYO¦Â0ù—ò›‘+QûÃôЩz¤Ï>ÿ"c2³85PÀÓV]€IÏl=Þ^y“¹†Ð™E±¹^‰ %uÐMɺôT†©d[µ¦ë{i[=ðÛj ê¶^§òâÁ˜Ü(„rÅ83oVäz crppôop1(f~íâì»›Aèræ­^5û¼eÞÚË–)zé.pkÓ0[¸µ þêµÿÌì×cÞÚØ]Ä®0Xžþ¡»Lz!™¦Î_mV@]¢cU0&tnxNDÿæ2Lº—W;Mü- ú—Ì\ºô’W½\ –þ‡Ÿ|N¼.á#,ýýŸ/S“ݯìyîo/ëÕwÐKŠ.=ÿâë°úcºڬ¸F*B— Ž—üa㪦—”g* c’Y*ÀL3_»âÉÕŽg¦úaL:Ÿ²díNu~.ÏÒÂyXOÔ6À$«]åqÚö˜µû/ÃÛœ¯¦À·àÕÃ0‘djvÕ„ëÛó¼7FôŠ=3 &«²;@{ÞGœÉ¹Ó@{Á*Áub_*  D ö×Ûïlv}èèlKާ1xs“_ÏÀÿW’eOJÞ`ë ˜4“˜Nùó]ƒJV½„T.Äç‡Éf˜Šý”2LU’Lh ý*IRZ]eù@C ˜ô”ÖCî7–ÛV ¼]¸O@(muå‹ËwoyReµZß_ Æ0饛5ó†{Y=F†õ•4-g¯ç­-Ï-¾µ…uÓÒ‚žOº‡Lšy!™&Ï]]òž¨K£=f Ýí)Ъ†î 3KÙ#Æ”¥ÚdY¨@y c*O/r‡1Ýv×À"7H¦K¤ïà[`L¡I%±¤"Ë}œä¥”ŠX%Ãr+•M,•-ɃY\n)0Zœ3Ø-×ë’‹.Uä¼$>1P1Æ$qÀLo}0#ìïÞï…~5é ìù”S^X³Ã];h-tÀ{U½9S\Ä‚É6"&’L5©µ´œ3¼ÔÞâþPzÂ!OO<üÈcõq×Ãeªc°0PÉh´á€fq§WDg†¡™®³%¥—?ýøŸ²hõ[‹TÑL±Ç ºm”*8B7<—d˜ð\½dÝ;Ÿ}þEûž.y ˜Ó»]ßàáÆäÿ*¼tú½hOr–⣙gK¥=ÉE☊.•t çéÊ|˜6Nç­âtAqŽ©cJ^«cލ ùT`ý˜?x!RÀâ^½&“¦Ls†‹.UàÜX€©Èg§,ð¯¯-É0a¸øæžÿöÅWšóÚŽ~«„g¨Ÿ«V¯>üÇÇÎYözégÃéWÃdx,(É0yb6…ý_"þbõ“"‡g¾ Ûoní7 PõF”%›• êjô±Ôµ¤æ’ jÏ{±°­ P¡a@I®ZìM=oí~y[u—•h«žÐ9ŽU¹àçÒMíx瀩0Û[êÚ[ƒgÞ@¿½4gAàÌ[MF†©Ó¿‰»µÅì.lƒ… ¹Ý…bLíï~ÒÄòVpiŽó+-9?ÙúÆ?9æ¸ ³ÛJÝ5°gùAECw6›Æ·bLלW¤IQ€SRj‚ù¨±¹Ã˜0ã¦t‘ßžÖù|ÿ~k˜‚<'™ˆ’NŸ$ÛÅH4¥¤^vãÁãJAQá"cÃiï œ-yãÄaRÒ*®4·äñYRsÃ8ÇÔ cj]ÛzÈÀC:>ÕQ–´¬hé2º‹¹¡Çìøˆ3ôø ©­= ˆùwÓÔ‚Uo)êa®ª×…Îžà ŽQÊx؈Ã0-Ý°×³Ž°ÆO—€1an7¢W|Óñâ˜Ú†÷½_©N/ª¯+3üåÂRnä"Ð%3`œõ²½Sh å/ÝEº1;Ÿø‡cJÌß…¡T€ T®ÀëÓZa‘‚e€™°!epF8g‹;‡È~¼‹Ç&9F~çÚ&M-. Àä:aò Þ½2†içÞOLÛ9úÅÈ`Œ„1¾Å¶ä\‡»2ôÅ·øIœBñ˜d*°|åªþø˜YK_÷=›sÅë+Ê7„|tàsÑÿü•ä¿£áÐBþ)žýØ©ÿ¬dŠ™º\×õ7·ôà­zÓß›àk>\N$Aw؇a‚¡÷˯ ¸dI­ÄÿxcžÉìE¥‘H¯+mI<6I·Œè¥äEy@bÉô‡Ë{VËß%Ô¸´U+ĪÁÛy¢^F@ Q€1á}ݲ•“þxœ¿½±SJlóÌXÃfÞÆÜ~ã½?ýÞÔÏG¯U¿‘aºÄonn=·6`*ÿÖ“a*ëÖÖ\epuŽó›^Õg`Ë–7Ž>öøñ³ÚÊ4+xcÇ\~€¡;›MõµVÁˆ1U B2¢1¦ŒT$‹áU w¦Û<žÌøS({¤’gÃ`’J“I&ÉÉoÂ7<Ž@¥ïJ‘–Â|,éd ækÌä±îÇ–ü–~¿¿%/·Tçhq1:aLøŸÁ6³ÿ¯û±ž ж3©&|Û¾¿%ôl<ØS²Â|Êq'ž2å› 0YNhì©7'.»Ì¾­5J‘a*)rÞŒ)Â?\˰‰°QEõŠÅ Ó¿iGçÙˆì÷<áÊð$烖üý›Ó³­ÚàrÉû2(`\ ë¸º¡KfFŒ)oÿJ–— P¬* pÒ®¶ê“ {`eÇa2ðQ ꫇öƒ¡Öt8rÀÇÏì* $†‹óìá¢`ÒábQl¯òcÉa¹‡a’*àW7Q2àÊXWø~l`lgô›ÕÆr É4sÉ&÷ÙĈZh“ÁN¿ª`˜ ›ü5ôo"JŠ× üM` VO<øãàŸ¥˜ üDþS|U¯Ì½½ûðT½iÏ—å€Yºõ`˜¤\ ´ É„=Ú*¤‘ %H?ŒîWVz mT¯Ï,’é²N[ åz‹C^Ú~ÚV£¡„ycFƒGÁmqá loì”’Óbæ¤13oëÖ¿1îâŸKGTבaÌRó0(Pý­-“ “´ Žó3ð’iÜÌ•f…ú ÝÙlßlˆ15^s^‘ $EbLI© æ£Æ äcÂ\[„•ßžzÖy%Ìð™ç=ˆ’Ã'9N××ëb³×´HÜ)izÙV$É¢±€dËwÌù6àR’XŠ-E:[ ‰§s@1£ÆV'Œ ˆ’fàrI‡ì0Û,ضÀ|üÃW؆)&Æ„ßÊ|ÊÜÛ SÑ“FÔ B2L5î>3q:`L˜Õèô=5ªÒ½b .3̇\¸’Kì•øÒß³År¹TÔ›Ùãê3®d_GŒ)5‚ P*Pˆ'tqÆBÑ ñØkº¸bÂ6¾’cÂ…dÂpÑzŽp ¦$j¸'–\ ÄA¯Œ~Ía­z`Ò±1F¿Â6!cÊÀ¿BH¦é‹7•|6ñ;ýŠ¿˜Û ÿA‘FÁÿEþJò—‘#Mo(ò_“ÿ¶ñžÙR˜{{Ýñ°Ü9ji®ã/Ü©Ãq„UÂÀPÔ¸´•¤‘ˆÇ&ì= Çã[i$Ø)$ _YR$Óï/íÝVçÚ+[d=^YÁ¡&Üç‚gž€c•°öÆN)m©Þ3o ·,[(;^õ¦± š•çjnmf˜8ÎoVƒ¬ùu…d;cEÉ¡»x¦7¡Þr‡îl65¯¾8'$ÆG%C²©1¦lÖ+Ku0ÓÎ’ÁÀèE½ïpÊYç…6*ÜÍYñ,LR0™ìHÉð¥T‚R²LøÖªÖ°$®°Ãq%ËOx" À•‚bÃÙ–~oL% ®äDVrÍü®³%kÉZ³Œý%iÿu˜'I ¬D‡+&éiÄ6ð­DÙ0 9ꨩd·dͧüôäÙË·«Ÿ-Ǻí„Igß<d˜J ›Ï€1ýÞ]œØÅ jaL½bʬ-—i‡cLþŽ®|r!¡â¼šÓ›UзÔð'Ęòùßd©©Ș°‹«Ë%@•à*F]Èà[|DSö‹ó¼‹»&ñÒÿe‘L2\tï§¶ÃÎÀ¤ÆZsnºb†I½âdÔô?ª4?¾¤IÆÀHO~­¼BÅ/>l¤ ™;â˜ç_ÜõlRµ!DK$„ þA ÿAO„öÿ|ÄMb2Ê_ ò/ã«V ÀÜÛóŽ‡Í€õ¾®Æ™:0¹º2L(št­¦SÚƒÐoÚHrrÛÒåj#©•8ûB)v¹[Õ{d¿à<²²[[œî¢Ü0©É© Žó“SÕçDH¦ÑÓW”eV(—aâãaõ5UÙˆ1U¦E² 1¦,Ô"Ë @î0&Y/–ð-0¦ˆœõ[?Iþ†ç¤Ò.”Ô¯R¸Ù^mù–ý¾V)WòFP²–Å"–R-5 cÒ`˜$¦^jÈG %ì‘Às°÷(í§£Â|JÇŸžkyk¸Ó¸ NÏÛ㉩՛p¥Ð^.!/µË"Æ”ÞÿsN¨hºɤÃE70´8 ÔMõ SÓ‹É $AL?øÑÑl4ŸM<Kņ$yˆPæÞoﯓ²’º´¦~˜XAT ŽÉtÉõÑm5”†é˯¾ŠsE“vj5óf2Li×$'ùsk‹Ó]¤aÊIuç°˜B2˜²ŒC÷,Õ>1¦,Õ&ËBÊS€SyzñèÔ(;Œé¦¿ôW;º‹1EPò«b ɉààÇ’N ‹øæØïÛvÍ ¶ÜÇ€+v: *¹K!1œO\)ÌJª1&t3˜O9¦ÓÉÏ/ÙªK]Í™b2L©é‰›—QÁ˜"z¶‡·0¦v}Á”’pK¡=žÎ××ù},wqIŒW[&bLÍûðÊT€ P,(’É3\4oFd˜²Plj)ƒLæo|6!Ô˜ŠªKF`îíÑç!`*b%É0ÕEqž´R@2ýæâë ÁU ®m5”@†©RíÓú»êgÞÈ0¥´î£omqº 2L)­úœd[H¦Ö)K9tÏLcÊLU² T lˆ1•-ò‡1ÁÛ¹¸;2“ cúåç*cTr#ÊâP¤™ Qr‚Aœd&›R 6äïRÖ]+UÀ¤crH¦Nž²x‹ 01–\::àäV£FôuÀ˜`ŽòP^ïW‚ȬÄ{œAdº¸RF»8bL ø£0 T€ Pt+`‘LAÃE2Lé®×Dæ$Ó¡?:zü¼WM_x6!ÔÈêªq¦`î½áÏyªž SUæéj¡H¦ /¾ÞßVã@ d˜jQé;‡E2U:óF†)}õmä8ìÖ§» ÔêªÏIæ…dzzòRYC÷”6bL)­8f› Ô@bL5‘§H¢¹Ã˜àê<ÂúŽo1‰SO²NWœvÎW"AEÔR”#%°J¢êQɶâ{ÆÀ=ùùI0&!™Ž>á—“_Ü¢G?LIìn™'Á˜B{Ŷ]>faL±ùKO'·ë‹Adæ(Ø¥§&Ɣȿ3E¨H™ ™<ÃE2L)«Âôd×"™?züÜWuHCCHzj¯ÚœÂÜ{ým™£Ù“Nÿõ½ ?"ÑÐ[­îü}ù €d…`¶Õ8P¦ò•ÎÎ/*›y#Ô࿵Åé.xkË@Õç¤B2a¸Î¡{jœS*‘E *@Œ©Báø³¤+?Œ©ÏC ŠÌT ‹Úv ú/Î8×Ü<ò£H%˜¤â(o&¢4s¬õ’ #º½|G~£”4“‡d"Ôô~7IùÆô›K®èô\ìòþÇÆcª¬'ôÂI>“Dfœ^ŽS’þ1Ì  T Å ˜$¦Wd²n’Ld˜ÒPcµÌ£iî%ÃTKey®Z+`’Lq 2Lµ®ôÏ$™â̼‘aJ_‡äؼµÅé.È0e¦êsR“dâÐ=Õ•NŒ)ÕÕÇÌSª ÆT•|üqrÈÆtCŸ‡,ën\6|û‹ÓÏ8@B—LŠÉ$¹Þè?)Ž-¿ÇdcR’©ÿÐÉG}ܪ ;"V».ݰ÷Àg_$·[bΨ0&¸Óèôît"ƒ„¯ôw†¾Þ/Çd§¿C#ÆÔÀ?/E¨ȸB2ýù¾'O:ùôõ[߉.ÂXûÙç.f¼=ÔµxB2‰•wáÒõÑÎx>:ðy]3Ó7X1÷’aj°ì¼\ ÉJ ÃT¼™ü‰LqfÞÈ0e¬È­-NwA†)cUŸ“âÉtﱺ§ºÆ‰1¥ºú˜y*P•Ęª’?N®ù˜®½öÚ|Qò˜2k±9ó¾m÷þdþ§1ŸòƒÃ'ÔÌÚIf®† Vþ‚¿HœW]ßËcü„¨b2ÿrÌ T Ù €d"ÃÔìJÈËõg¼ðô?þË7ïi2Ly©r£œ0÷2–\ë=EÉä˜òôZd˜ÒX³õË3fÞ;üÇÑ3od˜ê§Ï|Þÿáª_Æ0©M¬^º® l™ùôÑÿøŸNÏ¡{]u®ëɉ1ÕU^žœ $ZbL‰®f®rò…1ùuŠ–ñ[*¨@b1¦ŸïûJ'úaª¼Gä/Dóæ? câ¿™ P*@€çúabóh€»>Z0xùšûêȈöF?L ¨ˆf]bÏ{ŸFT=U4«^x]¿ï~øYômñ˯¾¢nTÀTΣ' è=› ¦×wöÜ×™·¶lV.K– ûÛŸþ+rèžÞæ@Œ)½uÇœSj ÆT­‚ü}B ÆôQÌÕ,BƒH,ÆôÒŽkkë°ñíI‚0–\B»á„e‹Sƒû“:]ŽSÂþXÌ T Y „‘LŒ%—¬zJyn€1áÙdÝžáa£2L)¯áÒÙ#™È0•ÖŽG4V0’‰~˜[iºZÉD†)MYV^{}çàƒxk+K3œ&– ;xI‡¿m\ˆ{_àèC÷ä×&1¦ä×sHê¥1¦z)Ëó6YbLʨ@Ù $c‚+¦'WÿLã7æŸO!ÃÔä¾6=—'ÆT'®¨Á§%Æ”žÿsJ¨hŽ~’‰ Ssj"»Wýè¯ÛÚÚoß÷ÉšÏ>ðZACHvk¾¨d~s/¦œT}êŠé'™È0¥®œá@’‰ Sƒk¡¡—³1&\‘·¶†Ê΋5L·ÖœzûÁ}ÛþöÅW~’‰C÷†ÕC5"ÆTzü-H·ĘÒ]Ì}¨ĘÊFXlŠæå¨@21&qÅ$iÛûÍù2L¼ ÄW€Sûœ ²DŒ)~›ç‘T€ PÜ*`’Ld˜rÛ SpÉDCHcdOÈULs/¦„T ³¨€I2‘ab#‰£€‡d"ÃG´ãbL’‰·¶×i^³¾wCÛçöûKý²ÓC2qèž––BŒ)-5Å|RÚ+@Œ©öšòŒ‰P€1&*P¶ ĘÔ“`LpÈ„FæSÈ0%¢¯MO&ˆ1UÀ %ð'ĘÒóŸcN© ÍT@H&2Lͬƒ¬\»Çì›ömŠ(’L4„d¥ÎË(‡L4ô–!m’B2‘aj’ü©¼¬’Ld˜RYeeÚÀ˜ð;ÞÚÊ'GÑ]YtG÷í‹&{²ôÁ››&wï¨;•dâÐ=9uW2'ĘJJĨ@f Ɣ٪Í{ÁòŽ1á‘ÓiÓ[mÛóqô1ü6K  ºQéÑ%Ú÷ágIë9LWLê ™Ä4 gR’VY ÏÏ{ý5ºýoÙµÿÝû³ô¯OWYÞzçÀÆ·>ŒÎó®½0Ýð–ÆìQ*@¨@BÀÄ4ø’„d†ÙH¯‡ <¤dæÑÒh)©RVøàãÏ¿üŠÔ¬Vo¦ÊõÁÇe[ÍTÖ¿0œy«¿ÆÉ¸B1Æ„<ñÖ–ŒŠa.ÊPþ–LVÉüåú1-KîaîÁÔ"‡îeˆ›€C‰1% ˜*Ð$ˆ15Ix^¶Þ äcª·¾Œ)}E`Žó­€ø[oLÂ3ÍêÑï¯Ok…0؉{Ûe?M`›° ä[¿”žS *‰Y¤uR€S„åi›­1¦fׯOªVÀïŠÉtÈTõéy*@¨ T€ P*@¨@¨À•-ák¼QÚÿ×ýØÆ¨&l´ïoǶ¼Ë)L‰²R*@¨ T  cJA%1‹%V  É„ õÏP œÓê¡ýÄ'Ó®¶r°ÒK`›p%N²Ę’\;̨¯Ęê«/ÏÞ4ˆ15Mz^˜ ÔD@WLtÈTmy*@¨ T€ P*@J*€õÚ ¶-Àa•d/ 3'LpÎÔc¶µ¬¶{â‹ P*@¨ éP€S:ꉹŒR@X%OK –Ä“€Jp¿„wñØ„ýÀ˜ðQ¾Å‘r°O|%VbL‰­fŒ Ô]bLu—˜hŽĘš£;¯Jj¥Àž—¶íê#I†ª/½uîäT« ñxs“¿ØŸâR1ëT ZbLéo!ĘÒ_‡,¨TbL•*Çß%\bL ¯ f ”¡1¦2Äâ¡T€ P*@¨ T€ ÔSQë¾Ã rõ˜ç¦T€ P*@j¬À¬]–>ÜÃs^€M“»w¬ñÅx:*ˆ1%§.*Í 1¦J•ãï¨@ú Æ”þ:d  ÆÄ†A²£1¦ìÔ%KB¨ T€ P*@R®1¦”W ³O¨ T w ŒîrH`™×iñ³M¹S‡ΰĘÒ_¹Ä˜Ò_‡,¨TbL•*Çß%\bL ¯ f ”¡@ûG ÚÚoÿëï—ñJ¨ T€ P*@¨¨ƒÀ˜fmé\‡ó”T€ P*@¨¨½ðÃŒ ïˆßKØÀûëÓZq¥Ewt— qׄýB5a§Yû ñŒT a cj˜Ôu»1¦ºIËSÄ+@Œ)ñUÄ V¦1¦Êt㯨 T€ P*@¨ T€ PP€1MÝÔ‰Q*@¨ T  €I®„¬â$6„gÂÞWN?~~`?`¦{Û5ÒÜê¡ýà±)Åd&©@€ĘÒß,ˆ1¥¿Y*P©Ę*UŽ¿K¸Ę^AÌV‹ƒ(  T€ P*@¨ T ± cJlÕ0cT€ P*@¨€_8Xiû¢ÉÀ’Äë’€MlÎtÑ„ãñG"aïT• ¤UbLi­¹B¾‰1¥¿Y*P©Ę*UŽ¿K¸Ę^AÌP ­½[ T€ P*@¨ IV€S’k‡y£T€ P*@< ˆË%0LØoL6©&Ù¹«mÀ~ 9‡HØ€‹&JJÒª1¦´Ö\!ßĘÒ_‡,¨TbL•*Çß%\bL ¯ f xØ´oSǧ:"µ®mí÷B¿³{`»eEË!‘C±ýدºO¶– ñE¨ T€ P*@¨h˜ã7Æ r S›¢T€ P*@ªT@\.‰k%lN¼ƒXOKòâ{ ûÅW“€MU^?§ÍT€S3կ͵‰1ÕFGž… ¤QbLi¬5æ9†ĘbˆÄC¨@€+&8dB¦€(UÂ>b[² hiÁ¶€œ”^Âñ€ŸVf‡ P*@¨ T€ P,+†‰S–+˜e£T€ P*!ìm& /„Š“hqØÿL€–*a?5ÉWz$6dË,Jþ Æ”þ:'Æ”þ:d ¨@¥ cªT9þ.á cJx1{T @u¼ä÷À„£Á3µïo'LpË„¤ØÕ¤T€ P*@¨ T€ ÔOWßÒ¶«¤Q¯|I?â«ú]—g¦T€ P*@¨ T  ÖÏ8ø`''ýùßþ©ÃÁ;+ìÁ·|¥JbL©ª.f– ÔTbL5•“'KŽĘ’SÌ ˆ¥€ J8T¢ËÉo*Á6ð­°Mx‡‹&IðÌëÔ<ˆ P*@¨ T€ P*P…¯ìéÿX[‡À„¯ª81J¨ T€ P*@¨@íøüÓƒ=¾~ÆoÂ~|ËWª Æ”ªêbf©@M ÆTS9y²ä(@Œ)9uÁœPX hü8ÀIQ/ðLf{€4aï-+Z°wÙàT€ P*@¨ T ® |ñå§­k¿îǘ°_ÕõÒ<9 T€ P*@¨ e(0·0Æ„ý|¥MbLi«1æ— ÔNbLµÓ’gJ”ĘUÌ (­€xcÃ>I<0á…`•&¿6Yè%øj’=-Wú¤<‚ P*@¨ T€ P*P <Î1ÑS-¤å9¨ T€ P&)ðÄùÇ^Û¤kó²T n :d¢+¦ºé]×cª«¼<9H´Ę]=Ì\å cª\;þ’ P*@¨ T€ P*@¨ð(0~Ãa&ÉDWLl!T€ P*@¨@ºèõƒvJw˜{*¨€ß!]1¥³©cJg½1×T  cª…Š¿øåϰš(ó%e© T€ PŒ+@Œ)ã\¯âuîÜùûÿq¨X£ ;TÁüô¯ÿöÿûÚ×ÿ¡¤É)ĺbN2LH¡f£"S‘e$úé1G™Ö¢h«P‘ ¨Øîjî)eÙSÎßÿ¯}ç_þÕcÐ1 7ßüÎÿºôÒKëUai>/1¦4×óNªS€Suúñ׉U _ÓE]ÔÐc»ö}RH{?Ùµ÷“V:€ôРÇÎ=ÿÂ{ìx§Þz瀕ÞFúéMM{>Þn¤m{öoÛí¤7vï·R»•¶:飭»>Úb¤Í»>Ú¼ÓI¯ïüÐJ;¬´IÓ[¾æ¤^{ëƒoÒ†7?°Òv¤÷_Õ´íýõFZ÷ÆûëÞxOÒ+H[´vë{VÚ‚ôîËFZ³ù]M«7ï[ýº“V½¾ÏJ›¬Ô椽+_+¤¯í]±ÑIË7î]¾ñ嬴ÌHK_}ÇNo#½„´ÞIKÖ¿m¥uVZ¼n“^Ùó¢›^xeÏ k‘v#-Òôòî…FZ°¦]Óü5íóW;iÞêv+­Ú…4WSÛ®9…´³uÊÒ¯ýÃ7g¯Ü‰4KÒŠ3´cæŠ3–ï8ôð£±J ±ÿaÍØŒ3~zÒ©g-ÃóƶmÛ’Ÿaæ P*@¨ T€ P¬*†éÒ«ozdèXoH2eµ–Y.*@¨ yQ€S^jºÆåìÔ©ÓøÉ3Å¥F(Ø¡ÔüôàÀÇ~}þ…ŽÉÉ56mÛó±XšÄÆä˜\ӒڕĢ䘓\C’X‘\ãÑ–ñ¨ÈfT°¹v"ÇH$¶¡ÕH¶aHLBŽ=È5‰%Hm@b»}ÄÜ#†ž‚•Ç6ñXöŸYG :óV[vœ_žqî·÷w-8–ÕÆ1ܸ&›n{f¾×S&NGŒ)ÕÈBPŠ ÆT‘lüQòÈÆPIˆ%M&´ô=jÄ ÒA—bÐK ™”^rF–.ÀÅ0¹H¦*&{*)šar1&gljaL “3TuF«>†©mS0ÆäŒ_mŒ)ˆar‡³.Æä0LƸÖ3ºÅ07cz¹h°»pÍîHŒÉûš“Á0íšÝVÀ˜”ar1&‹aJƆéÄ“N[þj;6ž_°Þ³H2%¿ÿe© T€ P*@¨@&°¦›±l'ƒžC’)“µÌBQ*@¨È‘ĘrTÙµ,*0¦q“fŠ)Ê´C¹+ç?~`À£‚1é‚ù¢¥òå2LîbxÁ˜<–#Y÷®+ÞÅT¤ ÝMŒIW¶Û“± Ý^Í.ëØÕTcROÆäšudQº½"Ý‹1Á|CŒ)~s$Æ_+I²¦1¦¬Õ(Ëã(?ŒiàcŠºX%×ßÒƒ,Œ©Èå’ø^*v¼$cJ“^òLLí>'L!“œ‡+&Ë S€&Ë S9~˜ªd˜Lî¾xØ ŸLÅ®˜Þ pÅäøaJ¢+¦ÒÓòtxc²¦_œ¶bÃn±à1cÊ|’Lìå© T€ P*@¨h‚`˜.»úf8Æã Ösãñd I¦&Ô/I¨ T€ ÔNbLµÓ2WgÆ4vâÌ";”ôC#~cúÕyzìMëÃ63 L%ü0Å`˜c tÅdyc*åŠÉƒ1i‰¿áºb*òÆdcLn¨ ×S!¼†bLv< ËSÇ“`LÅ14v\OoL!!bL¹ê[XX*P¤1&6ˆŒ*;Œ ãÂBT83Bœ½íÀïAÐ’Å-aã ^=}/ùé%#„\LLáäB0!¨\‰XrUùa*Bïc1LŽOÑJ¦x®˜ áä0ðÕpr&¿አƒ` *áŠ)ùAå„aZ¹a·i'À:‰)óH2e´Ûf±¨ T€ P*@¨@R°¦knFLs8C0&¬áø}2%µÎ˜/*@¨ T ¤ĘJJÄ‚Æ4fâ ¯AÊ0? ÆäñÀäFù(Z!£’iWòÆ’« ô٠'WXÙ^­+&ËÊ+¢\»Øq Œ)À¢gc û«cb'Dò«1¦üÖ}ÆKžGŒIýsú7œQ£ÏÓR´À-ÙP¼]ÚRŒ.y襂û%0vB;˜6ºƒNO$ã‚#P_¹€©'LvØckZÀícÇ’s|Û•hQ8¹rý0Á’ã1LÅáällßãƒ4šaòcL3ÝËNNÒ¡‡=eÚìw?üLÓÇŸþ-!¦Ÿýâ´¶»a'WL–ÀvšGY“æ®:üÈc·ly#!¹e6¨ T€ P*@¨Ȱ`˜.Ãô†ŸÂóxòðã£Ï<ó¬Ÿ|’aX4*@¨ T › cÊf½Ö½TÀ˜FO˜á±Cm3ÌO÷? Œ©›å~©ÝJå¦%M09Ö%Ø’$9¥¢h±äJûaŠf˜—à 'WQNÂÉ!»bÚ³x•`âq­z)ÂýÒpKš¶½hÉL^L¥&á]4ÁÏ¿`*HζF®ÅáÙõ&Ú(?L†+&£l2LsÛvÍ)$äÆôŒzcr¦˜L†I0¦㦙Պ6ÓÜÿ­\Ýe˜öxìpÅ$¾²ãoâœU‡ÿø˜ÊH¦ÖÖÖC9$º¤ ,ÀýìWLMÚÚÚºtéó`=Ls‚ßv´_ñ¯Xîµx< T€ P*@¨ å* “e +&w•…íŠÉ~<ÍcÃ; ™N>õŒ²H&óAÛxHÑŒáÑÀóÀ‚=aÏ›6mÚ¿?à9®¬g&a¿ »~ÎÇ™rÛ§T€ P*ˆ1%¢Ò— `LÏ>7Ý´@9ã\ÛÓ}ý=ç¼nžàq3Óë;-»RÁ´0©IGj9Â]FéVÚò.,D¦‘H–¸cèn%ktQ\B&ËúS`˜Ö#–œ?œœQÎ '·p³:}¾mÓQk&¤_8AåŠ\1Ͳl7ŽÕÓÙçvóØà>:ðyúG­sLŒ©ÖŠò|T = cJO]1§e);Œ ãBa’Ʋ1¦`€éåâ@r^'LVå"'L«L'L»Ô©‚c Œ%g•KÆäe˜‚"ÊÁ“Ø Pãg•M2µ··Ã ïÒGgR¤I–8Ëêg˜ 0õyYX¬VÙƒN‚ƒñ?Ç`°-?—vÊ™qÙ£“þ=zôÀG/F “[¯mMíQyq*@¨ T€ P*;,†éZ‹a uÅd{еO¬ÇÇ”A2Ƀ :tèàñ´$.Zu'žDðà Ï/xpÐg <5à£NØÐ¯tI†ÿYF«Pj°Ä’>Ýà·ò|äy™™¢½1ÉÓ„ä´°!}ú§}QoL8^–CàéC–dxže´¼ê›VO‹G$ìÄ™å*âÉ Ï2òQ8'Ù/—ÀµÄ]®e2L|œáߊ P*@¨@Ê Æ”² KJv1yH›Ö(@K÷<4©€åñNä8ÇÆ´1€^òº_’@rûQQ¹÷œ09F"'\!–œ’3íAb rÍ@޵랰/¬ucÉÙ¡6$ÎF ä‹ÒÁ0™“é‡É4Üc kÜĘ’ò·g>¨@ã ÆÔxÍyņ(;Œ ãBú7¬Q㯃F‚(izëÃM…qdibÉïo©(ZœÍ-x]*F—"é¥w5žqˆï¥xî—loÿšt¨Zˆ|\€Ér.ŠdkC£ÈÅsÂdúa’Q¯›œPÊŠßvFŠô´…1}Ãb˜ŠÉ)ÄC?:9Þ˜”a*¬uÞb=„X¶Z{Qq¦+&Á˜ óØ+‹M2a"“õ˜|Ç„»ÐEf´?Æ$Ë‹ñNfÄYô¬Î“<“bRÂ9ÉUÄÉ“éoÉ„–ÔÑN’¡T€ P*@¨ T Xƒa²–XXklìg¤Ãäy<±#ŒãðþÁ±H&Æ„' Y!òÀ"+(Ä««>8àHðFXž¡È‘M…ç1Gže´¨¸´<žÈŠz™ÕðÖò•<þ NÉ95‡È²gž–3ü;Q*@¨HŸĘÒWg‰È10¦Ö±Ó RblºÛ6HYÛÅÜ’µ0Þƒ.ÁýÒv+9ÁãŠÇ…ú÷ €É2%(Àä.q0 É‚öâ¥ì…°;ØN˜¬á½ ü±äÊb˜æ´íüÅé–7&a˜lWLÞÅçĘÂZ61¦Düç™ *Ј15Ev^´þ äc¸ÐC#a€¨éîwùu7Û‘’'}€£™ÌA¤ºñ,8ótÇ”2²ôBK!Ü’ ¦\.ù¹¥²/Ù‘ãœñh‘ï%ð8?½äw¿T<`õ ÷•…«`r'¯¶¢È’óLve?Àd’Û!“ -ù·“ƒ10Lf89s­³²A&€bˆÓ7zz,’I–{¦ìãcL~PIöÈT¾ù-vj:lÃÆ •}¥ÛާXëIÐ^–}ß#¥I&Æ$aãÌ•xpT/}ÖÐPnoLžGAŽÌ%fÜjcÂ1êWɃ1á$ ”ÄQ“ÐNŠ1á+ u‡ýX%""òq†'*@¨ éS€Súê,9¶0¦1ÓL ”Çðd¤ºŠá)Â̈.yÌI?®`BÚòn L;ÑÞ6wq{i'Lvh$—a²&e˜t½:,í—Ë0ÁˆŒé`L! l7ĘÂZ61¦Düç™ *Ј15Ev^´þ äczp°—F2ˆw=`=ãÅàác!ö°CÁGàJ~OK®‡Ïr¸%{a«=ýcPYój¡Kþ°qöÔ9NǦâ~É¡ÑKUij1| ‡ìñ=ôRLL/ÙŒš 0E‘+PüÈÿô¤Ô`Lf,9 qC{P†)b­³ëŠ :‹ãÖQÓ–ÿ ”O&1hÿ£N’€É½zc’=þ©Ô û1&œV~./|”0v²ÅÓºÓ½Sý;F^ P*@¨ T€ P(,†éš›±Ž&ƒa XbñŽeí°×j Æ$'÷´ŒŒŽ.W2¨r)`6”RÒ_™@" `-ÃSŒ®£=æ: ó£F‹ÃÙüAåÄç“yœ×Ò_á+¹› T€ P*Vˆ1¥µæšœo`LOyÞZÄꤩ ^{Óû‘è’7xœA/¸_²ÍF–û%¿&ÓHäF‘³ C>'LÖRv˜Ü}‘&{ï˜{Ü@rKnþšö‚eÇX—aaL¶0&¿&YNŒ)¬Mcjò¿—§MT€SÅç¥ë©@î0¦~ vF„2.,Nø¶Ë¯ºº.”L>Éò¨àT ~•\×Ja¬’5±ë¸Y*ò´TÂÙ’ ©Äá–¢½.yÑ¥bÇK½d9. uå{ ñßvÜ/ÙÃV½wüz)ØýR1˜ï “lÑKî·¶“D‘žŒÉ`˜Þs‚5ø¦6»rCÖ:[®˜ä™2Žœºì?:zË–7Âú3$Ž‘H’eÍ2õÒH¢'˜“¬-–ŸÈ‘fˆ1-È1z6|”¸uúÓ `^Q2ÌåËõ¼)ðÜT€ P*@¨ T „q&;œL K_}ç¥W½®˜ôñäžA#"H¦ŒIŸ ðø Þ[åYCäá_ɰdBBW ؤ5þg-¼@Qò’ÀpòX„pZÒËÉÕõZÒN¾Õ¸r|œáŒ P*@¨@ú Æ”¾:KDŽ1 ó|‘Ê ßáØžÄ U –Bâxñ0/ù I²âÝ´!ⳕ6íksR`¹S˜&{•‚íoU’Ë0Á!ÉÃ0Í]µK’0L³Ýxˆ%'SÃDŒ)¢YcJÄž™ MQ€SSdçEë¯@iŒIfî0ßgúM©Æêr…‹.º¨ß …Cr¾í,£ÆmEIœ'E§0V©€+ÙKTÍdJš¶XÐÒK¯¼õ­ï|W-ø‹Óðï:ôÄFÿGG^qý-‚Ï+DÃFL˜§^—~zÒi­æmºÅLq/ >‘ã.½¶÷¥×ôƤ³JÓKßøöwÅ÷Òb7²ÙÈx|—^úÆ·¾+è’•Üq­gtëÆkŸW"„\,L0IªcÚ·íàŠgëÒX“ ÃÔ¶q·:a’˜Öh ®d¥k&]ØoîŸZd1Lß=Ë™½§Ÿpͤk-ÖµÎÖÃÚÝx`˜·ºO#¦” ™ê](žŸ P*@¨ T€ P4* “óœk,¿ÁãɈ9›ñ`‚ǤnýæNYò¦,ã¾®e1OÎè=}äœÍv¤‰Â <âáñä®Q$SsU’Xr|Q*@¨ ¹V€S®«?²ðî>8·ÿÁÏ? <ȘFOõ¤ ÛSßû-ƒ”ÇðdCKEKâ—­ßñ­ïü‹ÆŒ;ñ§ã#ÞÍeðKÖZv%½„=7÷¹·Øf4WMEf¹yÆãé›ßþ®™ž;Û^ÁnyWï„IƒlÀ*ÑýŠ›‘L€ÉÃ0Á ÓI.ƤϽ1…5GbL쥨@~ ƔߺÏBÉeµ¡zE1‹TcR·êfȧ”ªŒ ãÂÉ3j4È$ïÀ“¶f²ähŠ`•ÜIÞ@7K‚. ·$ÃÍο¾°gŸû'®gŸ{±-Ķq0&%è¢ÿÖ·¿ksKض‚ö££žy®xH/ff™‡#ôÞ‘°pÖJ1|/ =[¸¥bzÉð&ZÌã]²0¦5–— 3‰ã%ÃýR»7~œ‹êœŽºÌ>"(Ûw’DÙñAjLÕbL˜†_t°þ÷0Lh+7îÖ§i'ÖZŠ×÷a²kßÂÔ.ypÑ]#V£úÀ0š·Ñ©ÿøÀÂ;ž^%Ë t­3”´:ìl²ôÐHŸL)ý›3ÛT€ P*@¨ T€ ÔI0L—]s³:ˆÕ8×x<™¶ì-<ž´ÎÙ,'ýǽt 'Ž}åââñdäÜÍÇ_=Éz<±±ˆI'b½è—`’©Nbò´T€ P*@¨@j Æ”šªjxFa&€ Ç×a&`LÞhV©ï}œõ«®–&ÃÆ„!·pK¾£Ë¯/ìuû}0àÛºú]ìJ…Èq¶ï%ØŒf.~U†èb3RzIE‹ÿÔN??Cw$]І©‹#ÀTÒ Ó®¸I0ÁBSNÁšc’Æôën{(Œa¢7¦ˆöMŒ©á~^ $Fú›ªSTf$k ˆãs, Ä >•Ê,aiŒ ¿‘Õ‡â2=ÕòXÓ}-I?b*öÎûZ0j,b’N*&“B=*ù\+©S%ÿ†é]I·-ýöWêpS6WÂ6Þáo©ó¯.üM÷+.¿îõÿ)܆•&·$CÒñ3–]ví-gžÓ­ÓÏOëö‡ËeTzÙµ½1*EêöûË10;})—KgœÓmÌ´—Nøù©8[Ÿ{ùÓ5½Ï8»ë ?;õÐÃúó=`êéOW÷>þg§" zj¸ûë{ß}Û]-‡þð¨»>˜¬oOD:åÐy]¯»ÀÐÜ5`øq'ž‚tK¿q¼tÞï.ÃÇS;_ðoý³ß¹heî—Ì!¯>YÒ+˜ÌApÞ˜¶¯_¿H7ëáD`¦º½,†é¤ÓVnØíxír&a˜Ð°ÊYcÉÝ:tù-C—£a-€€¨šk-îùIJÃäºb²ì ½Vì|zòÒCŠ.W·’ñÄT€ P*@¨ T€ ¤L‹aºúf<Ë㉮¯Ç“Kû¿p÷È5…P×ßyhÜ+x<éûÌ*q;·m0¦¢%¶+&}<éûpkDt¹”‰ÅìR*@¨ YR€S–j³¶eŒI’fÆôÔ¨)¦ʳÞ2HÓUíMEá;,hÉâ–€+ýζÉð[×ÀcnÙ6;KßÛý 1!©ï%Yú~Óm÷t‚‰ÁŽ×aÙŒÆÏ½ßKb!êqë=ÖºèsºÁÛ‘Ã^ÐŽ=–=¨`:ýì®bš8o-Ö'ÀÄ#Qä®éuÖ«ÃâóÇ+{v<ñ”Ž?=E¬<=>ÛH§t¾à—ßì$;…mͱì8À˜ào‰S”S¢ñ'T # ÔÙT•XŒD*n “dM=+iNKcLêÊ f mÛ°q_Ë3°)`e»FäÕìø-L?’®ë}·,_¿õ®€ð‹&+Ô†½j$ òaîéÕw =€–B¾Wÿé[ÿ0ÉcɇœÒ§æiÆ¿ÿéI§.µ]âÇy&ÛÐàxiì‚­clÁBç®}ç\ײ•#Áýc^1gs÷ûö|li!^CñZg±dÊõÍ…§T€ P*@¨ 1°¦›<ËuÔs°K¬g“…[…a¶¤ÞO.`ÌÚ îœƒÇ“AÖÞkš?ÚµxŠUºÉÔ©ãñ·Öü!‹'l´o­‰Ñ¸x T€ P4(ŒéÚÿ~ðÁNLTÀ«À=?)xcR·L®g¦N'ÿäÈ)% Ra&'ؘ~ú‹Óf/yUˆ%~›.—„[²íJë%^‡šÄxdaL÷N{a6¦-Z'6#؉à„I¢s<2|¢0­9ðnº_úF1Ƥ‹ØÅOëä%Æd/Që =Öªu× BÈ`½$˜zÞ1ð÷—ß\$gÓP« 1¦Š;DbLKÇRÔ+@Œ)õU˜ßˆ7¦ €D’ S‹“üF~ ÑéR-$¼1ýåÞ– ßžyö‘þ“lJÅ^”NÒ$1à¼iS‘3Oׯ’£X!á6ím0CI¸÷DêСƒøùX^’Œ8%!N’C,Ù¡‹‘d *Ä’õ±ài CÒ·/½¦7襖áqª®]Ž˜qê{ ˆ’ŒP±1tÌl$¡—„µhI\.áÝöºÐè%M‚.)}Q¬?ÎÂ*ÆÔýÊžW÷ìtéёƄ¸ð& $_ãj’¡­›vÎv!}O¼ä˜ÁãÂÜÆÄ˜¶Þþóà§óɤ¦Û¿ûÿyhp«—^²W9K›±V9Ûª^CVã㨹›1¡¾PAS^Ú;ž"àï*p­³ÊÒùü?Þrû=ûâ«TÿÁ™y*@¨ T€ P*@j®Àûï¿Øa‡M[¸Æ gÇ+˜¬õHÝúÎÅâ }<Ábn<˜ô~b9ÞÁ0áñŒXhqϨ5ö“ NÎuÅ$'“_ܱSÎþÚ—úßüÆËÕXzF`¯y;ç © T€ D)ðÄù5¾KÖt&™yK¨wÖéÈÞ1% u»m ´7ÁÀ4bÂ<@K ”`3»¹^¸%è(²+ýü41!‰ñ_ÉøÜbtHtŽ3Îé Ûø^’%î° c²ãÇY Ú‘`_€­Ç²2X†ËÖ0aÞË–¦—­Q=V&`û±Q3-‰õ¡û=‘`ƒ€ï%1ô`²0¦Vc‚}ç‘g¦cše¯aÐ(rà 1¦Š»bbLKÇRÔ+@Œ)õU˜ßÀƒ’:Q‚[%øT2µ(1ÒXr“'Oö{sJ—®À˜n¿g‡:2?â[kÔÈ!EÂIf¼ábDÉ¡”„UÂÈÒ ®ˆŽbÉeä±oŸ<ÒŠáæ§­HpÖÐÓ&–.»¶÷¥×öVbI6º½@ôÀ•0BºdzZB„8‰†Iý‚>eCK —dx ÄÑâ€+ÁÓ©‚1YCUczâÙYÇŸxÊu½îRâ1ã.¶A{ñ*ô=ü-÷ÛË0~•'¢Ø#¾—0–ÅG8Ì„áìó/¾Žqm^*B—À09þE‹Ð¥Â0× ‹V–ï%?Ìc1nZpD¹ºÝ>ýôÓÎ;zrŒÃÃ9ôR`ÒUάáÎgVÁBðÜ oرäö Ž<·îü;fK¼¨m3a–¤æZghÒí×]u}¯Í;?B"É”®>¹¥T€ P*@¨  P`Û¶mˆˆ1uÁêâÇçñVcŸžµ Ë*†ÏÜdÅ’[ÿöôeoác¯'–ÁbÉáñŒXe1zþÖ‹¶0cH´ke˜Ž>á—CGLÀ³ÉνŸ|ùZ4 zës‰º=,×'»<+ T€ P*@*RÀTN8¬™ˆÓaýxëäˆeð0Hqö:Æ3“»’YÖ3;&8^[À?8¸Cž™„m]ú¾Ü¶+© IlFسÌ6!ÁëX(Xˆn¸åî3Îî*¢ÓÏîz}ï»%‡ÐK’Ô÷’µÁ¿ëÏã£faT?~Θð>mñfO91÷`B¹13WÓØw~uá¥]v³».}‡zc5­6Ę*j…Öˆ1U,HR¯Ÿ¾S_…ù-@KK‹¢K=zôÀGS‹ÒAåð‰H‡¨¦T iaLw  Z#Â>w[£F‡¤ãÅ¢£C&EÂI”’=ÃëIb\+¹ŒÂ`$ô¸%$‰„^‚mÛê{ &!Xˆ$‡¬`GêÿÄxµ a±:ìçþö2ØwÎýÍ¥ð½„A>V­‹¡gp«å{ öˆ›ïˆŽítòÉg^ŒÉZ—î®aðÛeˆ1Uܦ‰1U,HR¯Ÿ¾S_…¹.œ( †ä÷¦TcåÒ0I)€1a\æ ûñíé]Î8ÀüJý9>8ÉáMJÉÙ¶ý* Œœ\L~êÂu~bI†žfV iôó/I„8Ó ¨º]ìõJÖ®A-ï ’ÄÞ§ª§P°bC-é|‡ŠË%IÖô´,À0N3ÇŒ t¼d 8ÑøQœoËŘd2}ÇÆW‚^ß¿uØÐb’é‰1B/™“:a’ÕêëUê4fþ–CWÃT¯ÁôÃ$E#É”ë{ O¨ T€ P*@ÂpH¦y«K>žL[ú¦3)¦Aª`o XoEˆ3íJÏ/ZWdTrmIºâ=ÀrdÅŒ+ gú^’Èq¦ï¥‚1hMÁ¤6 5ý…Ú(Ùð„‹˜ä¡€SÅÿbLKÇRÔ+À§ïÔW! p°½½Ý¯B\Œ)úcúó]ƒüÎt¾Æq€í6I’1p4·]8©¢$èRapé8öT×J#ï’ò¸’Ã-Ù¸R0±dx -¹Ü’I,ÉvIn©€.­ B—¼ãv5 ]2ñ¦Ê0¦m»÷[ÿ<¢€a ˜^ŸÖºzh¿Ï؇¯]m >x³<—fB2=üøhõÀ$“ÕB\³Ÿ=_¯.ÄÐ~Ž‘`µá‡©8^CÃD’)ÝKA¨ T€ P*@j®€L“æ®Ò9ºäÆóxb¯ävVo˳dÄ ¿¦rI&©(\¥äó«äÌÿºÞ•âàJ>–7KÖ`T’ÏÓR8´´Ðžhö$¿¥Ü’Ïå’5À ÉΆx]*ÉæÇñ·}LU“ü§>ÿÔóßÚ»¡mr÷Ž ™üÿ9ìÇ·åöF ™Î:Ë"™-Â0 ”aj³¬g×_k4ÃD’©Ü:âñT€ P*@¨ T ' €d:þ„&ÎYå,®(^_á:aªÃ3ºÜè.‡àÌ¿hlRNª&YÅäDj²êƒ¹¡T€ P*@š €…1 Ÿf‚í ©Óºœ¬£d¤ Óá.w/pKºþÙYíÚBÑ¥âÕìž—¬ØÐAôRÑzuÃýRy½1UÙ@‰1U) NR¬Ÿ¾S\yÌz”yÄ˜Ä ’&]çVŒ;Ÿoî‰Ü~ÛtžTp×).”‚))_Yš¬R¤_%fúU*rûéÕŠ£ááá,¾¾,hÉgŽYôÞërÉË-`ŠF—ª'“Ê:C 0¦âÿ<0-}¸’¸bÂ4:¸%¬–£0·.žý؃Ã"§Ÿ|rò©g<ôè³æg& S°ÐÙFǬ¥å0LŒÝÀ[ T€ P*@¨  lÙòÆÑÇÿܬ6ÿ㉳¾ÂŽs-'0~X!'ìåÚX¨-„ºÄ"Ú“údÚóžwõˆ™1LX1" ¾ð`¥<“®$ñì/ùƪ¯VN¤V« O¨ T€ ¤^`Lƒ‡O ÊáDç0 R^c“e`ZïMEv%'FG´äá–ÜõÏ^—ÄšàÄa.e·#Ç…ÒKÖªuwÉzÅî—<Özcª¸ÑcªX:þ ¤^>}§¾ Y€`r‡1ÝÒo@12y#{ßcòKî Æ’Qrù¤°Ðo‚(EƒJ×JÕàJ!Ä’L.û’™œAª;Nõ°ö·ä‹ç÷·T’[j€Ë¥°©æ¢€UÆ„EwtGÂÚ_L#fÒ±?"öÈ~)aæ°_vâ‡a}•LyÖl'âdËyä@r>#Ã0¹Ž[ãøa"ÃÄ; T€ P*@¨  É4~V[ñ㉓BÌ!…8×õe˜°€dV.HëÇ´Ïd>[ÉJ}§¾ Y€`ò‡1õaÔxjçó=N8eŒèO&{kû+øWt2F™Eaà¼~• ×JžÑg`èâ’±á áá OK~gK:T56Êö·Ô\nÉ3z®9Æ„ÿ™L”c2Óèò·“@˜R¨$3æò&Ó‘0áŽw92z]H¦†Œ²˜6˜ŒUÎÃä.ð.t&ÃÄ[ T€ P*@¨ 5U@H¦q3WЦÀdúˆµã\×Ï“H©ôL"}Ó¹’GbŽ1#Íá­‚Àß52£'ãDjF+–Å¢T€ P*@â+`aLÃ&FØ›,ƒÔYçÛ«ß½N•<&'¿]©Ø–T -¹ö£‚µÈ]fPà–Š—µÛô’….† £—,«+vX©:z‰SüFv$1¦ê5ä¨@ZàÓwZkŽù.¡@î0¦Þ}D GøöԳΠ8 ~ N*€ðÎ$¯Lõ:¾6’R”^¶–±J*nší®aÉï`ÉÀ• £Ò7KÁž–ÀÚ—†–\îÞ¿Ön[¿ý«šcL:Q.“é’ÄëVú‚dÂ~¸_ÂNqÑ„ãñ­ydô_VH¦ûÒVáD‘s&ÇBàÖ臉7*@¨ T€ P*@j¨€Lcf¬ð>ž¯¯xv,9ÇÂQ“XrZ!–ðÏ\òl%ΖÄE®† }§µæ˜ï äcêyÇÃ?0·5Fà|UÌ!©Ï¤ž“C @”Ì®ÈÁ’+KªÖåoÆJI×õiB¤9Þu0þˆ²,X¾ÂG9I¼4Å|9$Ó xðZž]ˆÔPXèL†)¦ž<Œ P*@¨ T€ PŠ’iäÔe…ÇY_a’Û©’5÷Ä «¿[l`’+qÂ$!ääÏ3—)Q¿ùª‹œH­‹¬<) T€ P*&€1=üäs± R–¥iwXPŽèEïq9Š %¿¿¥Ü’»ŽÝö¥ÚÈDŒ©âöMŒ©béøC*zøôú*d‚ÈÆtó_úGŒñ-0¦¸ƒE@H’l·ù1“1¦Ô¸oÖrUOòŒ2ÃIù P©x *îyrŽ+… µkî©‘=Lw ¡“¹ÊYŠÜí×]u}¯Í;?ŠH;÷~òåW_52ç¼ T€ P*@¨ S@H¦S–…=žÔƒaʘ†™*'R3U,  T€ P*P‰À˜ú?1¾¤AÊ13•µèݵ(’ŠV¶»±8¹%3Zœ†n$ºd^‹S%íÌþ 1¦Š¥ã©@êàÓwê«V wÓM·÷àð-0&ÿAì‘BH®«$Ÿ·$“LŠÂ’‚=yzø$ùh»S ¡”¼ R°k¥¢xpÙó®Tîð:ÕþÓB2õ8B&O…’abÇO¨ T€ P*@¨@Ã’é™)Ký'd˜V I¹'R“RÌ T€ P*Ð4€1=ôøx½É46Á õË3Ïs÷Ø9|q9BMK^\É0!¹+Û½ëÛWH¸gI;$•kR©ëñĘ*n¬Ä˜*–Ž?¤©W€Oß©¯B€ÓÁƒ]tÆ…JùÇ7bÔxƹ±#3Ž›»m×ÜàAd œdñI%¥J)¨äC[ê:ÊLÝÉÓŽ1)ÉÔ÷áVød˜ØëS*@¨ T€ P*Ð`„dzzÒRóñ„ Sƒk!—ãDj"ª™ T€ P*@š©0¦aoŠ2HE˜\sR1®TdB²‰%?´”ð•íĘ*n¯Ä˜*–Ž?¤©W€Oß©¯B€“1ÝØ§¿íÖ(8áÛ_œqnÄ!_Y£Æ‡TÊg’Fy ˆõ2I’;Ê,kaòÊË'|è™d¶)“’Lw$&vùT€ P*@¨ T€ 4E!™ð¨%O‚d˜šR Í¿('R›_Ì T€ P*Ðd€1=ðØøØ)Ÿ™ÉG)X” C’ÇÍ’?zC’-5’7bL7YbLKÇRÔ+À§ïÔW! @ŒÉƘzôyÈC™ñí/N?7â€X’¢H!LR™TëÍõçI>©Þël`L’‰ û{*@¨ T€ P*@š¨€’Ld˜šX M¾4'R›\¼< T€ P*Ð|€1Ýÿ踘)g}{¤uÉ•|æ$›Ê@"ÆTq«%ÆT±tü!H½|úN}²Ä˜lŒé˜N¾ðâëÃÒÑ'üò_¾÷ýˆB¾ºî‹c¤?^wá¯b”:Ÿ×ý¿ü×ÿŸ¯ýÃ7FŒ›¶yçGš¶íÞŸÀåÀ'Ÿœ|ê'œtæU×÷2sëßÞ¹÷“/¿ú*E`–¨ T€ P*@¨Ȇ ™Ž8úð#Žî4tÄ„èÇ“=ï}š"³E p"• ‚ P*@¨ȽÀ˜°l¾ƒT¨™)9&•ºæä»ßûþÑÇÿ"â0á}n7ÏóÅG>Ï}[;HŒ‰m€ äW>}ç·î3^ò/_qñ,XЧøàÃL¿ûãågÿº›g'?fX˯¾ñ—§U²€«6ìH>ƄƒiHï+È0åª[ca© T€ P*@¨@2ùÂy—?ü?É0%³vêž+N¤Ö]b^€ P*@¨Hº% R—\q R¦uj@“h{gÍ97ˆ1áŸ@Œ)éÝóGê§Ÿ¾ë§-ÏÜTò…1ù¥ŽžQå·T Pdzc²š÷š‰_^ñŸÛß|3¬â臩©ý-/N¨ T€ P*@r¤ÀÂí Yñà$ìñ„~˜²Ü8‘šåÚeÙ¨ T€ P  Á¥ cBs$ÆTá’?£P€OߨD!HbL…Haõ?ñœ™T ¹Ó‡¼¤Ã—c®m7ÀT@†‰w*@¨ T€ P*@¦0¦ÇÚ:ü틯I&2L «ˆæ\ˆ©ÍÑW¥T€ P*@­@&Í%M/1&bL‰þÛ3sT Þ ðé»Þ óüMR€1&*P¶ ŘÖLÃd¥+þîËÚ=$¦&õ±¼, T€ P*@¨È©ïºq×G Px?ÉD†)ûm‚©Ù¯c– P*@¨([¦?™Ì1&bLeÿù*%øô¥ÚdY ˆ1•°drœÇB•¥@B1&Û““Æ\ûåW_)ÉD†‰Ý> T€ P*@¨ õS }ûþ¿î8¿I2‘aª_E$èÌœHMPe0+T€ P*@¨@R(Ë Áƒc*@Œ‰SRþáÌhŠ|únŠì¼hý ÆDŒ‰ ”­@1&uÅä:d:øán!™È0Õ¿#娠T€ P*@¨@®8dà!%Ë’iÇ;È0•*#p"5#ÉbP*@¨ µT &—ÃÃÊR€1¦ZþKy.*:øôº*c†ã)wŒé¯ûò“ϾˆHø[ôü6c |üéߢ …fïÿÕÀ£LWLB2¹—É„ÔÀ|ðRT€ P*@¨ T€ äK~/ôÆÔ²¢™&¿6¹um+¶l[€$Bà£l \öÆ1ù(Ÿ¥åDj>륦T€ P*@"(i*i›È˜9¦dqâÂF¦¾vÂcmvü"Õ T w ðé;wUž—çcÊK=³œÙVÀãŠÉpÈ”ír³tT€ P*@¨ T€ 4]PJÝ'wß´o¦ŽOu¨€ {c_Mø G¶µ·aC¿jzæ™z)À‰Ôz)ËóR*@¨ T€ P¯ĘØ&¨@~àÓw~ë>ã%'Æ”ñ fñr¡€ß“á) °T€ P*@¨ T€ 4I³{ˆ¿% K`˜$`•Ú÷·cC¸%NøV¾‚7&=¬IYæeë¯'Rë¯1¯@¨ T€ P*@DbLl T ¿ ðé;¿uŸñ’cÊx³xÙW Ð2e¿âYB*@¨ T€ P*@)UBV]¶x` ÄR—Ñ]ð-Þ%i˜¹D€™¨‡œH­‡ª<' T€ P*@¨R€Ûȯ|úÎoÝg¼äĘ2^Á,^¾˜Òç nWû¶å«Ô,- T€ P*@¨ ÍS@‰%ÝL’# !WLpÈ${°½ÿ¯û›—_^¹! p"µ!2ó"T€ P*@¨ T cb3 ùU€Oßù­ûŒ—œSÆ+˜ÅË—ĘòUß,- T€ P*@¨h¾ —à] èÜ,In6íÛ„p„xsÂ3d’=8F£Ë5?ëÌAýàDjý´å™© T€ P*@¨@±ĘØ"¨@~àÓw~ë>ã%'Æ”ñ fñò¥1¦|Õ7KK¨ T€ P*@š¯ %$äÃô±„=iNÞñjßߎm9’¯ì+À‰Ôì×1KH¨ T€ P*ˆ1%¥&˜*ÐxøôÝxÍyņ(@Œ©!2ó"T 1 cjŒÎ¼  T€ P*@¨ T€ D(À‰T6*@¨ T€ P*Ð(ˆ15Ji^‡ $O>}'¯N˜£š(@Œ©&2ò$T  cJF=0T€ P*@¨ T€ P\+À‰Ô\W? O¨ T€ P*ÐPˆ15Tn^Œ $J>}'ª:˜™Ú)@Œ©vZòLT é cjz0T€ P*@¨ T€ P*À‰T¶*@¨ T€ P*Ð(ˆ15Ji^‡ $O>}'¯N˜£š(@Œ©&2ò$T  cJF=0T€ P*@¨ T€ ,Ü~ÑcmœsÈkCàDj^kžå¦T€ P*@¨h¼Ę¯9¯H’¢Ÿ¾“RÌGà”båé¨@3 ÆÔLõym*@¨ T€ P*@ cÊukàDj®«Ÿ…§T€ P*@¨h¨Ę*7/F¥Ÿ¾UÌLí ÆT;-y&*Ðtˆ15½ ˜*@¨ T€ P*@lˆ1åº!p"5×ÕÏÂS*@¨ T€ 4TbL •›£‰R€O߉ªf¦v cª–<h®ŸzðÏÿv·«}Ûš›^ P*@¨ T€ P*@Œ)×m€©¹®~ž P*@¨ T ¡ cj¨Ü¼H”|úNTu03µS€Sí´ä™¨@s½„{Õ€“›› ^ P*@¨ T€ P*ˆ1åºp"5×ÕÏÂS*@¨ T€ 4TbL •›£‰R€O߉ªf¦v cª–<h®‚1!®_T€ P*@¨ T€ Pf+@Œ©Ù5ÐÔës"µ©òóâT€ P*@¨ ¹R€S®ª›…¥E ðé› "£ cÊhŲXT€ P*@¨ T€ P*@š§1¦æiŸ€+s"5•À,P*@¨ T€ äDbL9©h“ (ðÿgïO å¨ÎtM˜î¿‡ªÕ]·ïß÷ïUU]¶Ëö-nßÕUEácd—'fmflcËÌ3¶0 FƒBLˆQbš%40‰£Yh@H$el¶þ7â‹Ü¹3"r:'2OfÆsÖ^gʼnŒŒáÙ‘ybïýìï£õÍmÑ¡И:´b¹¬%°{{÷ÄýT>xs]ì_›“"-É^2WÉÐØzm©õZp TÁqÍ€ @€@SìþÓ¶{—üUªÆ´âíáM9ÒèHmzà, @€ò@)µÌ5B ­oîŒ%€ÆÔ¡Ëeu"s•teI!—$-9]i÷ön[¯ßæ3½1o¢6°5d”ëÄ›‚k‚ @€@kH ÈD(¦Öª¤&œ ©M€Ì! @€ @câF€@~ ÐúÎoÝwø•£1uxsy€ @€ ¦H ÈD(¦¦ño•Ñ‘Ú*5Áy@€ t>4¦Î¯c®åÐúæÞèPhLZ±\ @€ @ /Ä2Š©/*¡¯IGj_×LJ @È4¦üÔ5W 8ZßÜJ©C+–Ë‚ @€ ôX@&B1õE%ôõ1éHíëàø€ @ù!€Æ”ŸºæJ!'@ë›{¢C  1uhÅrY9$ð§÷¬›³gǦ^:— @€ ´‰PL-U/Í;:R›Çš#A€ äSÞï®?Ïh}ç¹ö;úÚј:ºz¹¸\À¤ÿU“†æê¢¹X@€ @  ¸€L„bjÁÚiÆ)Ñ‘Ú Ê€ @4&îä—­ïüÖ}‡_9S‡W0——#hL9ªl.€ @­N@™ÅÔê•Ô¸ó£#µqlÙ3 @€J  1qG@ ¿h}ç·î;üÊó¥1Í™3ghÅŸK/½ôg?ûYåmxµœxâ‰C† ©|!›6mj³OÿŽMSÞëã'†´Ùisº€ @€@'è~wݘ§/èÄ+ãšj @Gj Ø€ @™@cÊ#;@[ õÝ–ÕÆIW'/éä“O>èÃ/ºdˆ• ýrñ /òƒƒûçÙç‹/S¹ Y^vÁÀËÎ/SÎxÙy N–s/• Ÿë•s.ì•Aç\•³/”,g?(µœyþ¥Q9ïÒ3½rÆy—–”s/=ãÜKO/–KN?·XN;ç’Ôrê9—ål¿\|Ê٥嬋O Ë/Ë”g^–~ùÅ™£rÆÀ_xåçg ,)§üù驜œV~vÚE©å§§]ôÓÓ.üé©ñò“S/tåÿ›ÿÔÿ¸_þä” OŠ— N:å‚“~yÁ>_Ü_’SõP+m1zôè¾ù£~ðí?þ¸•΋s @€rG`çÎ_Þó;S§NÍÝÅsÁ"@G*· @€šE©Y¤9Z­ïÖ«Î(¹Ó˜†ß>jëößo‰Êî-ÛKÊÍ·:ú¸“6¿»ÛÊ[®¼ó»·ÞùÝ›®¼ý»7J˦m»\Ù¸mWPºƒ²!*mØúÑë^Y¿å#W^Ûòák›£²nó‡QyëõAù@eÊ›QYýæAy#(¯¾±3*›v®òÊÊ;Wn|ßÊ • QY¾áý ¼®òÞ²BYºþ=W–¬oÉúK^ ÊbWÖíè*–í¯¬-–Ek·/Z•…kÞ Êêw_öÊ‚Wß Ë;*/©¬ŠÊ‹«Þ ÊÊ ¼°òí¨¬xûy¯Ì_þöüåÛTæYY”¹^™³´Û•ç–t»2{I÷ì%[g/Þ:Ë+3»¶Ê–][þöï?=vÒ‚¯l™neQP¦e³ÊÔ…›Oüåí¥1Éa:òG'¨*GÜûøQG…É”É÷#; @€z@ t˜ú=þÌÜ…«ºüî!˜L=`Øöo¡#µí« € @hhLmSUœ(2'@ë;s¤ì°5äNc’¨ä,¥äÂM·S`/½£Rª.ÉaJÚKoÿ..0…öRSÁaJL‡© 0ÉdÊÀa 4¦¢Ã$™)®1…SQcªÓa*§1¥8L¡ÆTt˜V–:L+ä0UÒ˜J¦¥1‡©[S‰ÆTt˜$35¦T‡©5&s˜T³ªMÕÝí˜L­ñõÊY@€ @ ‡ä0}åkýÆ=3ÏÚ› VnÅdÊám@4¦ö¤x¸ÒK ¿¥+dŽ«{I‰äÖ«ÄRÈ¥E`ª"0Õ”H.Ê%$’+ä’‹É…ScrÉõÐaª#\˜Q®l:¹x(¦ S¥PL¯l1éAÓ˜JÓÉM ¦6J*g“ªÛiL$P@åþ»õnL¦†|i²S@€ @ •€9LãŸ§Ìæþ,‹®uÛ_X¾å[ß9˜ìr9ºsèHÍQes©€ @}L©+€ÃC  ÐúîCøº‘ò¨1ù–Ò&)Jž¥tã-Ò˜NŒç‰sÞRR»ÉdÝåê=wZ’þÔ)G69X=ø‰,‘œ~4KXÚ€…JÒJ­‘d{Ó^ÕJ[ÐÐoÛ¾0u,Û³ÖÛqmcûm“ûqbSû|Ór¦€ @èLr˜¾úµ~ONžη)›ðÚͲPóä¹®7¿QÉdµÔXжBãEñ“¬A¡v‡ ïjo·iö’š$Ú‰Z%®ybRlâ„iLjªÄÐZÇ '½Ë5U´¥­±ý¸HNÚ^'f (ý¶íÝ™ø·ˆ­l㛆ŽÔ6®Ý™tèw2—@€ ö ‡Éw˜^ šœQ¤ØBÂk›e¡É-ŠÈ;sÑý¾]“ÉÓ˜,–’~L9²æF²ñ¢ JÖ/ÚÆiL±6Ej›¥–:°´îÇeÁ¶Pµ®Md‡¶ÓpiéÜÆ–ÂÛ¢4Ù[,n-'ÐÒÛБÚÒÕÃÉA€ t4¦ŽªN.u õ].6n¹Ó˜®½éε%éÞ$$Y ¢(éÕþGŸ`Ë~Y“È秇‹,Y¤¥ 7œ•¯ÆJš´Tˆ·”ð–ÊG]Š©K–PÌ/å2ÇÅb/¥ØKa22+Šù•Õïjâ¬+šA[(ï,xõ—TVE% ¿”H!×ËLJ'—šE®$S,‹\™ L˜,‹œ4¦1øá—bË'þò‚s. ÜõŸü¥?Ú~¦(YCíƒ+ÞVª¾¹Ë¶]ÇÃU³Ë¹N|›OìkLþlãÔhLþ€u¾×®19¶æK¹pM±N|›âÌ @€ Їä0}åkýžp¹ä¼l×jœé˃¸¿Ûâ·N®ŠÉfY(“øŒ…5™LÉhLj2X°Ø 5d,’k\¤jLÚ¦7“Ó•Ôl±ltnâ‡ÉEx²H·ÚÌÚY.“µ³ÕÝ™÷a÷öÐt¤ö– ï‡ @€@­Иj%Åvè<´¾;¯N¹¢@î4¦k~{§o Å–õª4¦²ŠR‰¥TÆU2u©Œ±”*-Eñ–ÊzKïWõ–,§˜²Å¹ô[)Iô#WÈWÁ^²a‰ÛK5†_ ºªÃI·ê°ú¬­TL!×I“Œ¥¶Ó˜<‡)J,¸<Õaª8H0wé6!½nD“Éuâ«K]=éJ*§o ’LcÒ‚VÚK±hL¶¥¨_>– ¡B4&õþÛž]·¾[˧€ÆÄ?/@€ ô-¸Ã´á}×< §‡) ÅΊ æÀ¸PL…YjžL{yÓV‰ÉT5©œh$/¦1©‰¡…/rŒ¬¥c™²]§ÜÔ‹ZÚ6ãB{³=kÁ2kë|th•LNRcG§ášT¶^Û«I¥Í´ÞO¥ÆÔ··7G‡ @€@Û@cj»*ã„!4¦ÌP²£Ö"P“Ƥž8SÚýçä“OöÛ;½€I~ð¤`yØoïèÿãR)¥ÅUJæƒKË Wf)i,)I\Iž¸ ï¾âç-Mœ¹èì‹.×oriÂŒEg_x¹~Þ’§.uá+=5{ú ¯V¼¤Þä¹KÞ¸øW×/dÏ8ÿ2+W\ç˜ñ3á— öR-á—ªæ«&0=—]¦éA¦(“ ¹Ô^SÌaÒÁò׃\r×?²ì×£_ùõèEcg®vÁ›n@ªÖÕc?5S”¯Á$óñm½öö‡*Ädò;Í]ß½zám2±´R_úZp?¶Þ6Ðof°/ o¶}l¥¿gõìûÓŽíX±ïŸZ†Úý›Šó‡ @€@Ëp“K€î;LÍ\ÿëûýêþEÎxÍæÉ¨i©†ØÕ-—ðZZl–…Ò…OY°±²ÉäÚnÁÁ©Ðx‘cd ½ËotX‹CÚ³£RÛ,5¶;$EiK5d¬¥£F °dõ›TZví›bo±3±`N±æRËÞÕOŒŽÔêŒØ€ @Ù@cʆ#{@; õÝŽµÆ9{Ì:H"©®1ij &ªOͦ-¶5Õ@cºñ •äŠï]}ãGýøM¹å•å'¹ò¾:pý²B¡•¬„–’+€â—׃HK~°¥a7üÌg?oÒÒ-w=ü…/MÒ’~kYÒÒð»Þ÷K_“«¤ßÃG>ä‡\úÌ?~þÌ †¨üdÀYZ5vB,g\à¸x9ã|bÖ¿}i?—6náêw?ýŸ?ñçgž~þe*‡ÿèDýY%öR2y\©½f (~éÿ~°rœei·:¯]ñ&õh‡ekIþ¸Å[gÕ‘B..0™ÉÔcé“?¼âíáÖ|­i9LGþø„ÀnÝ!G™zÑ/Ú Á‘C¦\~ß"Uè˜ië¾uÞ„Ëî]øËßÎUqùÜ Á¬Å[gvmv[%“©iWÇ @€ 6"`Óøgç¹<×6ŲœŸ4l–Šš'ÖB9õ¦yr˜F—¶PÔH´„×|×Úz“_Úðõj1™Úˆ§ #•û€ @Í"€ÆÔ,Ò­G€ÖwëÕ gT; HšKÍdo¯¢1Y`vÛT³-(zûþHcºú†;J $ßFÚyõ #L©\ÊYJÉÐJ‘´”ЕÔÏëŠuøªÌ|iµŒ%iL–$nß/íé Æ‹¯Ê[’´¤ßOÍX¨Å[Òr——0Nê’Kg>“%{bÚË2–T —Þ?uÁOÌ9æéûâ~.ä’ä-7Ó©Kzuèuw(ì¿Êýãf¨¼(o)T—Tî{|ƣϾ8sáͦÕï/o.£rïc3œ½tÏ£ÓU¢äqË·=4ñÅ»™þä¬eê°Ö¿~á«c'¼j/…ƒÂ²8.0É¿ñÊ–][f¼•é¯l Ê¢ ¸ðK–B.Yz 1­Ûüî²î›Ç.ÿ»Q]{=²ò³Íù˜Ãd>œ Âdw‹n iLãçm´z7gÃC¦¨O¸zæMã–«¦T5‡ž2~îÆ’A‚%Á ÁÌÛÕ·b25§9  @€:€9Lãžç" [«Ö°×?²ôô›ç«•jSh4ÅâˆË¦(êRÔBYYl¡˜Ãd¡˜l–…š'ϼ°áëßúÁ„I“;× t¤r@€ @ YИšEšã@ õÐún½:áŒj$ ˜åЦdÇR6iM©««K”½Ù_®ñØ­¶™4¦«n‹äÿ©WüÑ ©Ä)¥Uòã*ù¢’ëÛuÆ’¿àÒÃÉLzø©ÙÒ˜d¨ÈUÒBoiÝŽÐRŠ~›½¬ E%+’lAýÅGüèÄß\§¼¥“~q––•'îÀï¢HK ¹¤eùIŠ·¤ß¦1…Þ’Ê;¡Æ4ã¥0gÜìEõçˆÑOˆÙç‹ûpò™*ßúÎ!2cT´æø“Ï<ì‡'ìó…ýä-zî`•ùaì¥O}æóó—o{xÒ‹²”N9gСýOPQÏõ/Ï–õ[ë‡Ý2æ¼AÃ>õ™Ïé·MÀu¥œ½T~i«o/©¿».©ј$0=·îº1KþV“•æhLÃô£ &\ä½ÙÝ!¡Æ´ÁrÉ]óÐÍuVUj¨à‘Ù냚ZhL÷L^Mt.$49^WÝ2¶Bv¹Vûür>€ @€@_¦ýú{fž›_á‚0¹æ‰²];‡IÍϰ½ùNÐB™´P4ãåðÁ“ïy¶ÐB)„b²Yš‹2ñù×÷Çdê« Îü¸t¤fŽ”B€ @  4&n ä—­ïüÖ}Û_¹ÒÁéÇ.C 2™üKªžTNј,Þé"3µ)iLWÞ0"EH ¢%ùÝ®¼^Óñ–è-–î-©%ÅÖ¤*Jneä*­ß¡ÞX1WI©â.zýâÐOÒïTiɹJÎ[ òÄ…‹^:𻇪(Uœ–rI“_/¾ü:ë;3~¦IKzé¹W6Iv¹aăZ£>åÀ[ Õ%½äŠD¥ÓλLQ—.¼ìZéJf/I]’®tÁe×jÁb/Icºç±§œ3XÆ’ì%Eý‘ƤßJ7dØË'oÉb/™´4åÅõ*Zè÷íƒãöR˜<.–?®žðKQþ¸iiá—b™jŒÆ”˜š¦1ES!jWñF ï»C”¦AåÄ«g)“ÉÝ4n…*ÔÒÉ©¾î¼ö›çN4jA,_ƒ$0&˜LmúmÆiC€ @ iä0}9p˜æÆ‚ [ÛV-5O9˰䖥™´dÞ’~/ Ê»*úSÆ’IK7Þ(JZ¸sÌÓŠÃd—LZÒf‘º´êEW²œq–-N/Ýÿø ©K¿ºöŽOýãç'>·\*Œ¼%™I®|ó;‡hÍ)н´\±—¶É^RÚ8ýV ’Ç- 4&S— oùœ¢.)Ó¨G¦…+?'{éÁ§_À¤?öRÝöR2\ ö’“™jј†Ž<ÈÀäB1 ‹£°L%+ ±šz¿ò—×ìuÐa?Œ‡ìò&K$'‡I¹äTûªk]šL¦©/¿¥<ïöŽ¿jæ¹·=¯òàô×,äÕì(\¯!Ì»W̵'“éÛßùÞŸÿò—¶ÿ¶ã @€ ¬ |üñÇûìûåÇ&Í-i¡&kÕúÍ5KÍaR E“Ú•®…rÎmÏ?0}¥“S0H'ׄ×õ›'2™¾¼ÿçßùW½oXuÞ_õß³®Þ†íŽÔ†¡eÇ€ @ˆ@câ–€@~ ÐúÎoÝw•;ÖL$-¸ÈLvaÕ5& Ť-¸ìtmJEј®¸~„g…ù¹¼¢W¥1•³‘ÊRªj)™«ä•íÒPü”pó–¼qæC¬H':ã‚!Ò•öýÒ~Sæ¯2iIË2–iiòü•æ-IK2iÉŠÞe Š´ôÌÜ•¡®¬¼cÌÓò–î7CÛ[È%S—&ÍY¡KÀ´2(êY–ºtßã3,ð’\%Kš/«‹½¤œqOÏ^þôìeEiiù6å‰S¤¥SÎ$QÉb/ÓÒnKÃïyB}Ó*˜4Ñö®‡§Yì¥s û—}¿*¥&Иoå—® Û+[üäqQ渤½äé8±Kþ¬Ecºà²s§¬9óžÅ)½çc–ýç®­CW&½|Þ׿ñÅgç,q“›]&˜,‘œ‚0=þÜëVé ©¥A%k˜¼àMåà³àX‡ ž<á…M%ƒ¢ô½Ã޾þæ‘Ýïý“©M¿Ù8m@€ 4”ÀСCO;ç×"öš'jçFÉÍ/¿o‘ò\—­ÎÃ/›2øž—Ÿ}éMµò‚ʲB ¥˜N®0Ë›”rÇØi_øê>οêÅMW5®ÍÕŽ{~bõ¾³ZÑYÔ,i²/@€ T"€ÆÄýü õߺï„+W@%» å…“Éä_Rõ.0 PŠÃd1™œÒÔ¦TéºÛS¬£B´$½zø/Ù 6É‚'¹øI 3©’¥dÞI¬¸|p&*¹ÄU E¥3οìˆøÀø™ú­euŸ®Q†8ýÖr¡ƒ8°Xô®Óϻ̊Œ¥N>Ó¤¥ëoP“ÃiYÒ’ÖkYQ—$'Ic2i)(+Þ–tïc3,[œ%Œ»`ðµR—öùÂW¯½uÌ݉᮹uÌS³– ·Œv˽E“òÇit¥cz†â-I]ÒKZ#uéêáÚæsãg,=ø¨ãùé#šzî¥Ã´,{é>ó¹+ohL¥ö’¯.qƒ¬,ŠÊ´0Œ•Ú¥¥ä–µhLç\8xý–V½µ>)3=²ò³þlÚ´éÀ|æ¹%Þ-W˜Â@\ïqÙ” F¼ YΖ¦AƒªÊ[6àÆ¹ÎxíŠ1]Ç]9# Åêb–N.Åä ˜Ã¤+UÁdjtµ²@€ ´)™L§ž}IJó$œb´aW-”®žyÓ¸åÊ%§Ê7Ï› T×7X ezÔB‰GŠ- Å$‡i¿ý¿±xõfk¡ìþÃ'mŠ«§=÷“ј–}B€ @ Ý  1µ{ rþè94¦ž³ã}L@¹ä$ IC’ŒË(§3«®1éý²ŸôÓî“®VÓÐko¯` éÕÃx\*É/kK"'¥:Iµ[J¦+¹dpf,Y>8+æ'Y¹âú;e, ¼ü:‰JV†^wçá?:ñ¢Ë¯UŒ¥(=Ü«Á<×Óλ̕£Ÿ¶ù‹>˜»ÿ´mé¶k+B‡Í–ÕÐ/ÿôIDATGØL¦ 3Û LÎar#æ0F ƒ–K.ŒÃ8LʼnÎå&L¦¬*Žý@€ @ # ÈdúåY{ÍoŠ…Mªñ¦XTq˜ ¹Â+8L©&Óĵ×íXבx+\SÞjœë… @€@ИjÅfè@hLX©\R@ wÓ¯†Ý–ŒäÖèÕCûWaƒØKiZR”ýÍ÷“Šá”ÊXJ.¬NZh¥”èJUt¥(ÌR¥HKµHK Sê-ã-Õê-É¡iuÉ÷™zÉ4¦ª?]Ý]ýîïWu³Ú7É´ÿß|jÆb‹ÀÝ-%#i“4²R‡É™a•&'xïÃ?Ô~†l @€ ä‡ÀàË~5àÌ‹£v®Åˆ-Dv‰äâab“q˜jv˜Ô<™·üí?ÿ¥ØÛû¶½óCÛ])S+K† @€@-Иj¡Ä6èLhLY¯\Uþ4¦Ë‡ÝVÆ= ¢"]>ìÖC:.f •’ÊOª”ú­ÐÉk àÂÞÞ2¢RakjJ¸BïpIb¸ÔÜp)ÆRt,ž!.UZÊÒ[R@ EQQX i‹6GeáæÌƒ-UÝaã4&Í –ä^õ±ËÇŽX4B¥ÿcýµ¬ßö}£yÃZi Zi¯Vý*zýõ2™ž˜ÞU!°)Î~"9ËÔšg–ÑÏâ0©À œkq˜ºßû½?HPõôØ€ @ÈK]þ‹3Æ&—ç:&¶Ûš'Å\rõ8L Voßý‡O^µ¡Ôà0q€_g Ô‚‹ÏÔ½«[ËZПÖàÒ6Q5hLQ\ @€2'€Æ”9Rv¶!€ÆÔ6UʼnÖG wј†\}kjÖ6[©W¥1U—LEŠ•‚–T]N’Ÿd%4Q*”@RI„VŠ»Ja*±ô¬p^Š1 .±’Œ´T]ZJÉW>ÞR+yK1±©q“>ê4—¢¤ë4W7º¹MöÑTº¼¥9›æhÍ®?îRÑ‚¶©úÁ5“iüôWì†qSr„Àw˜,—œŒ1#€ÃT•3@€ @µL¦3ºV­ª.Ïõ\ŠÅ’hŠE&“NLí)3“4?D)µ­Ôªrñ™ô§iLzIr­VËÔ‘Z.¹o·Acê[þ€ @-K©e«†ƒ@à  151èyÔ˜\$Ï7²Hï\võ­‡ylä9Ù¨®…jf’“–J¥b8ëü­à*¥GW*`) Ï“È —4–Ì}‰—`¾l¬Ä“Ä)Ø\™¨¤Æ[*84Uƒ$5mƒ†jLNKROºùI®ŸÝ:ÓmZ°úÜÕ«®¢^uë^¯úc&Ó¸©¯D·G¨©Í]êa Gz“KŽ8LUk @€ # “éçg L LA;T1bý0±Ê6NtqS,î;m¿ý¿±xõfËjZbq˜ì NKr¡mÕìòçXX\kg©¨96lþ°¨24¦¨D.€ @ €ÆÔªìíA©=ꉳ¬›@î4¦Ë®ºµBô#½zð‘ÇVŽT)Å[Ið¤xº·²~’Â)y•ÊZJC+Õ +©y«\%+)ÆRä¿ÇÒR牫Kj¨Ædó€ýžtú¯½ªßêI·¢™Äš=\ãg×L¦Ç§,rSr„ šåL.¹™² @€ ÐS2™N>ý¢ yF`*æ¹.b‘•äӴ™!¶`g-QÉ"0ÙJ©Kú­v–kp)DSO¯¯…Þ‡ÆÔB•Á©@€ @ • 1µRmp.h.4¦æòæhM#;ið•·Î_n‚Q¬_y‹4&çU^ܣʥë­rÒ7ëðõ»}“ àÜšÔLpšçêEWª®+ÍJ‰±TÈ ΑõK™HKž´ÔzÁ–ª*MÓ˜¬Ç\`—ËÀõ¤kAÝèöªå>Ђ۾öϼ™LN^X˜ü‚Ä,grÉÕΖ-!@€ z ÈdúÙiyS·Ës]2Å¢Ðrìq&;1—?ÎiL¦+Y+Ì^5‡I –Å»öy#õ^{3·Gcj&mŽ@€ 6"€ÆÔF•Å©B chLew­B wÓ +oqRQrA¯|ıå6ð}£:–à ©µ”@QJËþf–R9Q©\h¥ ÞR])èJNèJ%¹áÂhÿV¦Ee³‚ÿeáæª’PëoÐ8IÓ‚Õoni ôÛ>èêCW×¹%’³Îô‰k'j3­±¹Âõ~˜Éôð³ aËe‘s#~¦¦zÙ²= @€ P/3™ü,rÊNnÓc¬yâ’½t˜tbjIYÂ8IÍ+×àR#KÛXp\kp¹vY½ÕjÛ£1µZp>€ @hhL-Rœú€S@çÍ G)n -íž[(ƒ~3ü #Ž­E9ªe›HKªh&%ü$ÅR* §T!\yQÉÃ…®RͺRÁX*èJ$-%µªÆiLÍøÔ†Ç0“é¡g^Žê:m„‡©iÕÁ @€ s2™~zê…aód«µCÙ7œSœ Ó{‡)Ïјò\û\; @€*@câö€@~  1å·î;üÊs§1]ò›áE»È¢yå’+ÉE?êñB¨"ÅÊV’bÅBé”-éá”ÌR D¥rq•â¡•¼èJ)–:%ÆRíQ :@cr&ÓØI RGp˜:ü˛˃ @€@‹Éô“S/ŒZ£¥A˜Ô<Áaêeu¡1õ o‡ @€@§@cêÔšåº PSuFlÑ–ò§1]1<Í1Šb IcúÁÇ(QW±¤¹Gõ©HIK©«\º7ç'yŠRZ8¥(88½µX iàhLõñbë¶!/éôÓOÿôgÿiŸ/í_®|ö¿þ?ÿåÿúÛ ¤¿ôÅý÷¡´¿þëÿíÿý×/W¨5yNC®¸ný–üòŸü¥•?Ù2™þë?ýÓõ7ŒvìÏî÷~ÿç¿´ô…´2dÎ € @¨‘À%?þÖ¾ÿ÷ß,^½¹B eÁêí»ÿðI;ÌùfhL9¿¸|@€ ”#€ÆÄ½ü@cÊoÝwø•çKcÚ¹sçœÒŸ‡ÆOŽ•Ñ<\Éš#PK-'»Ú[\cÒwÕÄ•G­zkq…A¦ÿFçò @€ Ð:ÆœÜ}Êÿ‰Ã”U… 1eE’ý@€ @ Ã 1uX…r9¨ƒS°Ø´äKcJÖLå¸5¼ 6ŠÆ´c÷ÒQ]{M}íG[¶ÿ>µâp˜Úé»™s… @€@»sòžS÷zïÃ?¤6OˆÃToõ¢1ÕKŒí!@€ hL9©h.)И¸-:”SIÖ0¬T Ðâј¦¿~”4&•·?Zš4™p˜:ô;œË‚ @€@«˜vݞߨ“KšL8L=¨34¦@ã-€ @È4¦<Ô2×thLÜJ µheÉB1Y‘ϤSõM&¦ýç² @€ ÐÇ>xsÝöÕ]É“Ðz¥o2á0õ¬ÎИzÆwA€ @ ã  1u|s(K‰›£C  1Õª°¦­¬1¹PLf2Éjr&S‡~{sY€ @èc«1q@¿yWHžÇcý÷Ž­4“ ‡©Çu†ÆÔct¼€ @M©³ë—«ƒ@%hLÜJ ï“ ­©PÖ¼õá†î]•·áÕv'ðÖ»»WlÜYù*¶nßýç¿ü¥5¿üPL. “NU&Ó»;ÿв§Ýš09+@€ @ FÓößÚ5'¹±B1IoJ®ÿ£?îþÃ'5îœÍbИ¸% @€ ThLÜÈ/4¦üÖ}‡_yÞ5¦¯^./b¡˜\@¦|\=W @€ ôaõ¥½d2IZÒo©K n¨SymòX Ѥ?µRE¯êO¥Ÿ³eýŽeëƒ h·C¢1µ[q¾€ @h4¦&æ0hAhL-X)œRИ² È> Ðw’¡˜ü€L}w^€ @èd»·w[È¥%÷ “·d—j¹äd/)ßœýù§Ý»´ «ÉB4ÉdÒŸŠádb?µ@cª[B€ @ WИrUÝ\,J 1qCt(4¦­X.+7RC1)7õÏ…B€ @ o8I~’L&‰J2“LcrÁ–,“^ÕJm¯Wµl%5ë\ß\I›©M*ŠÓ„ @€@³  15›8ǃ@ë@cjºàL2%€Æ”)NvæøäÏwmj奷Γ½¤§U·æ­¦6÷t8 @€ R‘rI1™$'½1o¢.[¿-Æ’ÉL–6N˜ádª“¢1©hK ËÄOíИjgÅ–€ @È4¦\U7 hLÜJ©C+–ËÊþ¸I“¦ü]:W @€ 4›€eˆS±¸JJg—,yœÖH]²Ôr’–,>“~k3ËF‡ÆTo…¡1ÕKŒí!@€ hL9©h.)И¸-:”S‡V,—•?hLù«s®€ @}FÀ/éG™ã´¬HKŸIÒ’e‘“·¤õV,2“ÖÛŸ½‰Ÿº 1Õ…‹!@€ hLù©k®qhLÜJ©C+–ËÊ4¦üÕ9W @€ ä…S^jšë„ @€@ИêÆæè hLT™\ŠO‰ûB©C*’Ë€ @€ €ÆÄM@€ ¤@câÆ€@~  1å·î;üÊј:¼‚¹¼ü@cÊO]s¥€ @€@Þ 1å­Æ¹^@€ ÔH©FPl$€ÆÔ•Ê%И¸ Ð!И:¤"¹ @€ teöV$€ @€Z—S¦uƒÆ”)Nv@€ Î!€ÆÔ9uÉ•@ ^hLõcû6!€ÆÔ&ÅiBÀ#Ðïþ~]Ý]  @€ кИ2­4¦Lq²3@€ t4¦Î©K®õ@cª—Û· 4¦6©(N&Øëнú?Ö_&“–¥4é÷°ùÃF,a›ì}ÛÞú­pMzI›é7ð @€ 4›S¦Äј2ÅÉÎ @€ Ð9И:§.¹ÔK©^blß&Иڤ¢8M¬Û±ÎÌ$©KZØõÇ]Zvñ™ºwukÙ~Û;|à Š€ @€šD)SÐhL™âdg€ @èhLS—\ ê%€ÆT/1¶ohLmRQœ& uiàŒúK¢ÒœMslµE`Ò‚0)8“6P& L*ZÖoøA€ @h*{ŽÛ£Þ4~2"ÐÓÔk÷LUýUûÿ\ôhFØ  @€ '€ÆÄ=ü@cÊoÝwø•Ó¥ØáÌåuYJr•t]N]rñ™´R¯Ês’á¤m”uNE ±‰@€ @Í#0ø³{~ýß›w¸N?RhLŸˆk©eéÓ^?\ @€úŒSŸ¡çÀèshL}^œ@c 15†+{…@ÃXþ8?mœþ´r Î$·IV“L&ùL¶Æe—kرc@€ @ Ò˜n:.YhéÃm{Îú«Ia™ø @€F©ahÙ1ZžSËW'Ø3hL=ãÆ» Ðg,aœ\%?UœÖ¨8{I''ÉVjË>;W @€ ä–S¦Uß“®75 ¡˜2½Ø @€bИ¸% _hLù­û¿r4¦¯`.€ @€ ÐИ2…ÞS2 ¡˜2½ Ø @€’И¸+ _hLù­û¿r4¦¯`.€ @€ ÐИ2…Þ“.9‰PL™Þì € @IhLÜÈ/4¦üÖ}‡_9S‡W0—@€ @èhL™BoÉÈD(¦Lïv@€ ThLÜÈ/4¦üÖ}‡_9S‡W0——»ÿcÛ3ë\·ct~.™+… @€Z—S¦uÓ6“®Úd"S¦÷;ƒ @€@*4&n ä—S~ë¾Ã¯©Ã+˜ËËþ¸iT×^][‡æç’¹R@€ @ u  1eZ7í¤1Y@&B1ez°3@€ ”#€ÆÄ½ü@cÊoÝwø•£1uxsyù!€Æ”ŸºæJ!@€ ÐИ2­¤vÒ˜tá ÈD(¦Lov@€ rИ¸7 _hLù­û¿ò|iLC‡Ý‹ÔIàù_þ×5kÖ´þ7Á;;ÞØgß/|ä´Ö?U΀ @è|hL™Öq{iL'ŸtÂèÑ£3ÀÎ @€ thLÜÈ/4¦üÖ}‡_y¾4¦“O>yøí£¶îø}IÙþû-QÙ}óí£Ž9î¤-Ûwo~·XÞzwwPÞQùÊ›®¼ý»7¼²éíßmÚ¶ËÊF+ÝAÙ•6lýèu¯¬ßúÑú-QymˇAÙ”u®¼õáÚ¨|°ö­Ö¼Y,«ßü (oåÕ7vFeÓÎU^Y¹qçÊï[Y¡²!*Ë7¼•×ß[æ•¥ëßseÉúK^‹Êâ×ve]Pº¢²ý•µÅ²híöEk¢²pÍö…kÞ Êêw_öÊ‚Wß Ë;*/©¬ŠÊ‹«Þ ÊÊ ¼°òí¨¬xûy¯Ì_ñöüåÛTæ¹²lÛ\¯ÌYÚíÊsK»Ÿ[•ÙKºƒ²x«Ê,Wº¶Î,–-c'-øÛ¿ÿôŒW¶¨L·²((Ó‚²YeêÂÍû|qÿ9sæ´ø7ÁÎ;¿¼_¿ÇOÿö÷™:uj‹Ÿ-§@€ t>4¦Lë¸4&õ½\yýˆ#~x<&S¦·;ƒ @€@:4&î ä—S~ë¾Ã¯ö¤0ÒR<ØRª·äE]JW—zf/¥D`zÓ"0}𪠴©·A˜ÌzqEñÞ{ŸK®Wq˜êv˜êK'7«k«Ë(§8Lr˜’Ó´E[²ÙÒÉYÙç‹ûOš<ã½ÿàÊïÿðI+|1˜Ã4þÙy+6¼¿üõHcZüZ:K=Å/,“Étð¤g&·Â©r€ @€@î 1eZå-®1Éaºú†;‚ÆiAcrÓEk“é¾ûîÏ”;ƒ @€"hLÜ È/4¦üÖ}‡_yî4¦o¹+QÉÿS¯þøØ7*º’+Ý»ä*¹²¡[º’•,ä’Š\%¿¬/ ¼eŽSþ¸ÍQY·ùè¼õáÚ¨¤ä[#u©`/ŦUug‘“æòž¼%WªL‰ L]k‹¹ä­Ý”5AY”wƒ²:(/»òê» ¢ò΂WßyIeUT^\õNPVå…•o»òüŠ·]™¿B‰ä‚\rÅtr˶Í[¶m®+K{î0Í,8L%Ó¢-Ó=‡iZÁa2é¡ñ“ý`Zºgúü‹Á¦'&Ï_& t¡˜Â €Ae©Ræ/ÝüÍï5mÑf•T‡©¥’Ê¥8L~7qi(&7ÛUÝIJÄf-zãß>h¤ɵ|WX¥ueZ?oì]®CÓúUõªõçZ±›„j›9ÉY2fähÏþ,Xmæzrõ.ëfõ«>VS…R5&¿Õú¸M2wÇâ0Ù!Ü,FQ…ƒV>ØôãkL®ÛÚÎÁQ#OwJæŠé¬Ûzí“§”ª1¹s‹u=k}lÿFØj¹7Ø€ @µ@cª•TMÛµšÆTâ0ùéäÖ¿W'8Lwô¬ ’ËS˜–×d2¹–Žßäq¤ÊiL®]c-Jÿ½z‹YDÖ@³¬íÐ#ßêÔö§köº $î]î¸H)Y£¦i?. ¯Ó˜\£Lkü¶9?6-Ç®%Ö¾K¾¤f£VÆ®Ô<-ÛÉ5Òmc¥Ø³9LÉ~€šnS6‚ @è hL}AcB 5 1µF=p™ÈÆtíÍw¦kIaê·ko 4&-”FTŠ[JciM])ÍX* ¶TFZ âë”&Œ ÂíXÙ• ƒ˜+ÕÕ¥÷z`/U¿Ô{©îLõg‘+˜¶¦a’ÀF`*hLiA˜œÕÔ"јü\rvcèN°\KünâµA¾¿°›ø] ÅTè)Þ6cáýj3™\ߨÅRgÌqñ5&ëÜLjLNJÕ˜,,ë0µ·ûF‘uຯ<; '¹®g{£‹½dÛ[Ÿ²¥rs¯J²xûNcÒ²u1»^æØA+Ÿ¡ËUg-§1Ùz;D-<-î”ýXG³MÀ5¥,yJõjLÉýëº:©3ÿÿÊ!@€@Þ  1ez´”Æ”t˜lnUÐ> Ök–T<SQc rÇtD•ìrIÉkVÕ˜¬qÓ˜¬B¬µå+A¶Æ×˜Re#¿ÙkÍdýXcÊ5™]ÐNU»M¦h÷Û¡î4ìþ®ìlµ;–ü½¥¾ä·ß]SÔšÆÖ¨´ íÜR–;¹ÊVºÀ™Þ¿ì € @ И—]C Å  1µxqz=%?é¦;]¢·äÂ57ÝÙÿèRc)ÅVF¡•,ÆÒ~ñrÃYž¸0ÌR2Ò’E]ŠÅ[JzK˜ÖSï0Z6ºäþ{ú¿ƒ÷A€ @ 4¦j„êz½u4¦Àaº±K.½qº#Ö8æØ„¡˜¬qªÆ~e“)©1ù¸\67­´E¾×éDU5&méhÚ›ZL¾¾ãÅ6#Åþ´ý[KÓNFµÐ¹nM2“Äu'ov]³1¦1ù»Òé™n¥ ´·ûû±³Š½d F×î³£h?&?(-XcV+¿ó®êºKÙ€ @ O 1õ v – €ÆÔÕÀIdO wÓ°ßÞYb ¹\oá‚^•Æ”0“*ZJæ*•°éJiÆRi)ðTR¼%›àXš0®’ºK×µ¶ræ¸ –eŽ‹Å^z9™<. _%\4Þ•ùa¯åüåÛ¬¨û2(Ë‚¢~LW|{IËÏ-)–¬&Ë"7¦4&ç0…Ò[—+Ía*t— ÅdÝÄRÁ¦¾¼é€«d—³žMs’Ô¿©ß&è¸×Óê¢ø¨?×zB-¨¾ýX€Û‰ÛÀú^­ûU½«¶¥S‚lþŒÅ²©±¶ÞwƒÜnMÓ±W]'ó~t ê!ìŠÊ4y†4& ÈËRgWa徭§Ã嘫[Ù]—u1'¡9à.o‚»XëgwÐ’û7DcÊþ¿+{„ @@cÊôhIÓÕÎaJ6N]®óXœàÒPLs—íSµîpø1#Gݛʩ²ÆäÚ_¹ÖæÃÔ¥1Yê4µÔ¬…¥·›Bdk*hLÖ(³¦Ÿk~º5j[Åd#×Ôzkšùâ˜ÆÛ¹NÉšØvVnÚ‹½dL\*: ¬k,kÁµ‹uÚ•¶´†§]ˆ«½„É”ég—A€ †@cj8b–%€ÆÔ²UÉõŽ@IÝ.Óõ¹Ô½;nß¼ÛžGÖ‘Ó¼½zÔO(nP¤T!œ’YJ•]¥ïüà°(7ÜÆ÷/»â†ï|ÿ0ý¶ç¢Ë­ ¾â‹¯cåß¿hÿ£O²e“–´fÐÐ,‰XP¼KÓ_|ÕB.}û{‡Ê[ª¬.¹ÀKGüèÄ'¦¾Äï Õ¥ñSøÝCætmR,+úS¹É åøyÉJ{éÔsöÃ,“Ô%-?òÌ‹*Zð¦È^J LaW¦+~ø%™L¡À´µß·îe&˜¬ôVcÚ½sϺ9 ½›ÍaÿìüHzÛðþO®™}àùTŽº|êIÃf=ûò[ ²eu:ý•Í'^=3H'†b:ïö¾yî„ÃO~pÆk‘Ɔ°šüÒÆ¯W3™zyQnJh/÷ÃÛ!@€ v%€Æ”iÍ5NcšûF·êùšÃä§gÜ2ÿ†G—¹\r×=²ôÚ‡—ZãT= 7_ñôóoXœà'çoüåoç¸qýÆ©"+¿¼ÉädšrV †äÎÜ-»6©[ãz·LôÑ[,€“[ïÖh½ _d[ºmü½iž‰…ε·«Ôæ°^Õ©&ÏÁ?º{£íÊíÜÂ&¥Bð_ÒÛÝ[´`—YîJý¾>ÿt!8LU?l@€ZS«Õçæ@cjkŽ”1?ñ‘‹“â‚•TÒ˜ä0íµ×^®;ÃÅVÑÄ,÷þŒO¶Á»s³}÷È_Vœ4¦Ø«+‹”,Üû©Å‰JÁB¨(Y9ù”³?óÙÿj‰áä*õ?æ¤G'>'?IËêì{dÂs_øò×ξèriL~¤¥Ï|öó*&0IZzzÆBUÇY1{©˜*NËë{ÉÆ}æ?¯lqé ãÂŒc®¨Wñß¾´ßOÌt—ÆŒŸ©CÈmr—>ýŸWŸcd/yêÒiç]vÿ¸ꋌeŽÛç‹û}ê3ŸŸ0{¹…_Úç ûÝóØŒ{±Ï¾ZŒ½TKø%/“~I Î?|æsQ ¹®­åRÈM/“BΘz«1I`š4tÏùÿyϘ“wÛ¦yvS…A˜Þ—½ôÔüMÁ]ñÚuËd²n⦯;â²)*ÖMüÛÇ—«›XöØØ¯6x²…bLÑ·g_ÜðõoU‰ÉÔ¸ëbÏ€ @€@ç@cÊ´Ž§1êÚëžÅÿSU™)èQ¹aD¬q:tô+Ö8Uůî_¤¢Æ©ºîšôê·Î›ðèìõ–Nîð˦ÜþôªÛŸZ©Æ© ÅdS¥€ÿþaec2eŠA€ @ 3  1uf½rU¨…S-”ئÅhò•& ÚâXÛ\,-Ø­²“f‰YXiÓ˜,¶¶] ¦»Å.¹ÊéX§[9Iëõê‘?>Á6(Ñ’ìOONŠ-›¥/¯¿wßÓBI6’U’±4ë¥Õ¶lŠÒÙ^n–\‰"-­ß¡ Ž:ú¤«oi‚?p–\%iLlé’__æCnùÔ¥Qc'È^ÒŸÒY$Ýõà-_ò«ë¬÷pÊüUgœ?DeüÔ—]Ô¥3οìâ˯û·/î'uÉÅ^=n¦Ö¨Ü0âAS—´7 ¼4ôº;¤.]8äZù1³nüÖw9þä3g.Ü`—^¥¥Ûî{ê›ß9D™N9w°Å^’½tÏ£Óï~tú¿~á«–<îüÁ×üòìAÃn£ù—úýäÌ¥Òkž˜¹ô¼AÃ̳9wÐ0^?c逳©<ðôóR—T®¼yô/κtÐU·Icòí¥™][f¨¼•²S!ü’‹ÃÔciÃë›w>28˜ô¡‘ÿÌa÷Ì<'0Ù#éÉù›mÝŽñó69dŠU´â0i¶«4&ë&>þª™÷N^Øc˶©§X’SÑʺ‰»¶Ô¤^ßÿ[?˜0ir{}Š9[@€ @ = 1eZO Õ˜d2U–™Ôr•¦Âì×8ýõèW¬ËB]r˜.—Æ´fû5c—¨}ªÆé#³×«áÆÇ—slÂÆé9·=ÅèW¬qjLA[~Ú¢-ß;ìèrÙå2¥ÈÎ @€ ÐИ:°R¹$ÔH ‘CÕ5ž›A ^5ÉiL“_Év"CI?Z¨’TÎiL¾ºÔÖ“õ»%‹HWJcúÑ éN’³”^WDœ÷\q9à’ /­xKÞÒ‹ËßrA•Ü‚¤%-ËXúö÷•œ¤å}¿ôµ‡Ÿší‡YÒJYJ–$N‚Ú@&“ü$EZÚ÷KûÉRzðÉY~ïÐ+o¸sÞ’7´FJg‘x¤pJ>1ëÀïzñ¯®›<¥B.ýöŽUôÒ¸) ž·R 7ÞñàÀ˯Sì%©K.gÜèq3ä0=öìKÚ`ö¢²a´ >ÇN>SYáî|†~[Î89L¿ºv„…\rEÓ­÷=õôìe.ö’ì%9Lw?hLò–ôû¼ÁרŸò–TŽýé²—ŽùéŸúÌçÌ^ú×}¿:nÆR¹JWÝ<ú滟ø—}¿:æ©çe/iáαS>òx§1ùö’ú=#iÑ–é‹‚>P^²ó–z£1I`zïáÁ>÷ÿˆ¦FjLr˜¾¼_à0)ü’K5h®Û‘C¦^tç‹¿ç¹Êaºë™Õ&ÔTWõ«ÊTG‡ž2vÆzÙc"/iÌ´uJÉçf»†”6O|“©ÞïU¶‡ @€j#€ÆT§·j‚ÆTNf’äޒ0Q“Št%“–T~sÃZÖdGIKú½pM 1YÈ¥‘cž>ñçgž~þe*oéŠëï”átúy—©„êÒ;ßúî!Ê §¨KrIËÒ˜$Á(ð’t%EôÑÞÔçø©ð·å‰SÎ8…\º÷±˜‚¨Kaà%M¬T:¹ äÒò@WºõÞ'ÕqhLD“ÙK’–,ü’–Çë÷¾_•½¤ßý¾}ðȇ§ ¾ú¶g]ªrðQÇßùÐT-ó“ÓÍa² LÒ˜\ì¥4{© 0• ¿Ô3iÜ#ãR&Ó˜®Ú7È.—iÙùè¥_Þï€ÇŸ™ëwaºÂI®ê)¾åÉ•ãçmxpÆk§Þ4ïˆ!SÌaRªX±úUMªiLÚ@ÝÄ.iô´uE‡)˜í ^˜LmÿÏ@€ @ 5  1eZ/¦1i|"óböR¬¸4sÃTèH)†‘.4N¥1™Ã¤8L'^-i¡5NÕàÆéóÖ+xó @cZ Æ©ÒÉÓ] ü8Áš†äÚéÉô«s³m_³7T"°nN¦Sv@€ú†Sßpç¨hhL­P œC 1±©÷í7ר` éÕ#~x|… ßÞ“œ”PNJ-’“$*)œŠ-HQ2QÉ\¥ÐOrÒÒv‹±$3I‰á¬H!ÒoÙKr•NúÅYOL{ÙrÃ)Ò’^ÒÆ ³¤ràw‘´ü]½dÒ’²ÅÉI’¨fˆ º-Ø’%ó–´ uIÞ’-ï#ieËG Š·$éÑg_”ºäB.iùžÇf(mÜ=κ„…‹²ÅIcúÆ¿¬"EI¿-üÒ¨G¦©Xø%Å^RÚ8yK*~I~ÒO¿ ‡éÜK‡É^Ò‚b/)yœ\%½dE˜ôûޱSÌ^:àÀƒŠöR8q³®ðK=ИøÊWÞº|ÿ’L&05¬Œì·×ÿ¹Ý‡f/EaºÂF˜ÆÍÝ`‰äTõšáúØs¯IW½c“ée‡žüàô×ÔMhLƒ&žºÖEìˆyš×ðû&îûůìþÃ'=ú†áM€ @€Ò 1ez_,Ü2(Õ7jèÊkü7ͱñí%C:lœN•À¤Ž kœÊarßBs˜ÔÃhL3׫}*‡iШ@cRãTÓ%w½‹ìÚéOÌzõþÓÿ²ùçÓ¸æ6{†@ }Mñ@€ÚŸSû×!Wž@cê)9Þ×ç²Ñ˜tÚÑ®]»´ PNJP×çÖƒÆtÅu·Wpôª4¦ØŠS¥„f’+NNûÔl+2–Æ>5ËD¥§¦½¬>¾©Ï¯Ò²”N)á´ ß27%ìT þ\³ý‰©/+Ò’t%õ žqþe*ã§,dÒ’2Ä)7œ¤1Ù”G½Ë—–x鄟Ÿiñ–$-)=ÜEC®Õoó–¾õC”*μ%•û4&‹åóÈ3/JKRѲ~OyCr)X–ºtÊ9ƒ”-.˜–ÅŒ¥±_ ¦W3,KÉB.9鮇§Yì%˧ù—xIÞÒ¸éKMZR¼¥s.vôONc/m¹qÔøï/ué77ÝoöÒ?|úsžºTkò¸r©åÆLXð·ÿ©Ê‰çöùâþŸ¼åÅÉ¿¿æ)ý}·´G³÷üòá¶Üœ±· :ôÔs.‰n¼‚ú¦[(0Û¤1ÍÙ`1·$0}ë¼ S¾eÝÄšêª LÆ´|ÛoÆtsÛóê&žúòæCMN Ť ¿cì´ýöÿÆâÕ›×où“©÷Ç @€ ˆSÖ·ÂÔו´´âíáÙ–Tê±Uÿ´íwÏë F­~’b¯H4+jœ*“9Lê‘Ã4äÞ…Ö8µDçÍ\¯Æé=Ï®9îÊjœª7àç7Ì9iµÚûÖÀ÷ÁËaRãtÒ„Éë_šóÑŠÒVv¬ÑÍŸÈ„€¢k£1eý5Åþ @èhL}‚ƒB % 1µD5p=!à4¦uëÖõë×ÏvÑ¿ý©…½*ïRÛuuuÙ6cÇŽÕûí§''Òï 4¦ko÷•£Ø²^=ü‡Ç{A’Š)ÞÒV!”Š¥EÉ…SŠÅUÒŸ¿½s¬ì¥3.¢ß¿½c¬:ûf)Xsþ‰JJúfnŠ• =ÜêwU´ ôpêtâ”îð0=œ|¦¡×ÝiéáÿÑ ³_Ù¨ý q³m”™$oIE/Mzn…¤%­9þä3U´ uɼ%å‰s—Îç”s;iiŸ/|Uê’b,÷³3ä-rö )J·Üû¤yK˜ä-YÂ8+‡(ÜOÏ·${ɦÙKºlIÒ’Ô%éJWÞéôŸŸlyß“óU´pò—tÄñÒ˜s^}A©-s\K©vI–JŠÌ4æäÝÚÉtö%áè2ÅMú¥.YQ(¦›Æ-wÝÄê#>þª™Aˆ¬°^ÔS¬8Lr˜®yxIj7±ï0Ùb25¨6Ù- @€rG)ë*·¼rYïuOLcr“;L¦BWIÐb}jŸjŽ"0¹,çr˜.»w¡9LÊ%'iìŒ×¬qªDçgßú¼ŠÚ§Aã´+ˆµì§“‹¦é/XËTå£ÝÊüJÙ!JÜt · @A©3ê‘«€@O 1õ„ïi NcÒÙ 8Ð4¤ØÉÕÝÿÕÝÝÝ—Õ£“Æ4ôÚÛ“š‘[£Wë\… ’/Eñ“,ŠR!’…SrEiàÓƒŠ“ç¯”®4~ê‚ÀU -%EWÒšqSX28W”Î,=>yXzî•*’–T”îú>3g…IK*–ÎO÷س/Y¤%¹J¦+Y1cIñ–f¼¼Áe‹“·¤`KOzÑRÅY¶8r顉/ÞýÈôb¼¥eÛôç”×›´¤…±^p ã4Ãrò ë|ú%Œ“½¤¨K<õ¼~Ë[ºó¡©*н4+¶s˜xéþ§æ[Ú8+#œ¢8Lši±—™²äö§<2eñ}OÌë½½äĦz5&ëNݶ`ÊõvYR¹†iLºÇe2röÅîÖŠ·ð& o‰ ÞƒÀZa-[.9ç0ÙT×§žßÅa*t;zI‡ “©Gß+¼ € @H#€Æ”õ}Ñh))0¹+Éd½%®ßCíÓ‰/¼!KÉú+zŽ¢//îv¥ÆÏÝhSÐ8]Ú}פÕ*%¹Îm¶¶yÒaÂdÊúÞaiИ¸/ @èhLR“\ê'Ðà¡êúOˆw@ ukLÙ¶ö"é××ÜsŒü?õª:æ*là^rZ’?©¸úI®Äü¤ØŸÖåç•ÀR²$ƒ³Rp•lÁRÂËÊ@dq¹áœ®ä¤%ç*Ť¥0O\QZ ’ÄòÄYocIYt>ÆŠ¯.I𠤥 l•´dE}”ÅRP—L`’ºdS0] ¤%+¡ºTŒº”Eà¥Ô˜L=Ó˜6m ²+‰äÔç•Иvoï^rß°U§$^L]YùÓ “é—g]lÒ›Ý9‘ÀTp˜\-[múÝĪ s˜Ô!U±¿œÃ„ÉÔG_N€ @G)ë*mœÆTA`ra&S¢qLU&Ø, ; ÂÎ(N°×8-ç0%M¦lÛÚYWûkChLmXiœ2 @©И¸1 _hLù­û¿òÜiL¿ºæ¶¸xäùF¿v[Ð+W*!Õh#¥¸Jq?)Pœ¥TATJq• ;t%ÅlOêJQ„ž0Ò’3–,ÒRi)œ1™"-…1~\©Ó[ŠBÇWS—2ËW!œ½Ô+ɾ>Üû’˜8 Ÿt¥7æMŒ­ß¾ºK/õàÅL¦‚èim~¦ –à 5íÌâ0yÝÄõ9L˜L=¨#Þ@€ Ä  1e}O4HcÚö»çk“ú[„É¢.9QÉÉi¥â6ÙW‘f—Öò$“éäÓ/²LIIq˜¢:"S-4Ù€ @h4¦¬Á¶”Ƥ‹“ÉtÐÇú)ÎÃŽˆh~”5NcA‚Ÿ˜õê~ûcÒô\NóÔ…÷>üC ^ÚÚYWûkyhL-_Eœ  @5@cª›A   1u`¥rIÜiLƒ¯¼ÅwŒb²Ñ +o‰fšiTK sº%Kz–·dê·òyß\2¸ \˜/,µÌz ­”„V²äbµXŠU6– éáÚ(ÒRå8Löjæ“å3Iê’%u¶JW²¢—ô§t%½$I ’œ´FêU®©ê—“L¦ŸvQÁTóúˆ-S0ÏuË´ðUÈ%W•'@€ @Ù@cÊši«iLº>3™ 3©‚N‰’,祉Î{ì0é@Íikg]c쯵  1µvýpv€ ÔN©vVl N#€ÆÔi5ÊõDr§1ITª éU›JØ“²t[…änÎIŠ-TV”J#*Õ&*• ­´µ^])ÅXZ´ÙÉ1µHB­¿M¶ÓŸvïr•$0ÉL’¥´µkŽŠ¥I;ý6¥ÉrÏéG ú³ÆPLî«K&ÓOO½Ð4µ¨fó\q˜ø¦‡ @€úŒSÖè[PcÒ%ÊdúÁÇxSI&ׇЇ©™mí¬+ýµ04¦®N € º 1Õ…‹!ÐQИ:ª:¹˜"ÜiL—þfx9£Hëõª4¦ $_Š<$ ˜T>fR,’B©H©–XJ.ºR—™+©%Ì—Z©$œ])ºR9¡*[©É_-2™~rê…Aî?˜,Ó¢(S“«ƒÃA€ @%И²¾!ZScÒUÊdúþáÇYäüÁ^ã´7SÖÙ И¸ @èhLR“\ê'€ÆT?3ÞÑr§1]rÅðrÙÙ´^¯ºpè5$qsÙÜü…­Éänš•h%%Ë[le×ÖY•%/¢R-¢Rº«˜.ÅRH=Öú‘“q†m­1é+&0™N¹0)0á0µÅ÷/' @€ N&€Æ”uí¶¬Æ¤ L¦ÃŽQã4œ(Uȇ)ëýeD)#ì€ >'€ÆÔçUÀ @ Ï 1õzÜXyÔ˜œT”\ÆôƒÃƒXèµZG•ͤšœ$?¢R¥@J.âNÐ-è—EA/¡•0O’W©í©Ý5&}=Èd:é” b{ÇØiûíÿÅ«7¯ßòQ…²ûŸ4ö †½C€ @¹%€Æ”uÕ·²Æ¤k•Éô½ÃŽŽe¢ÇaÊú.`Ù@cÊŽ%{‚ @ o  1õ-޾$€ÆÔ—ô9v äNcºxèðò騶êU „Þ‹²EI¾‚<_®„ ¿ª–¸œd¢’§(U²”Jg:Ö¢ï°èI_2™NüeÑdÂajàW&»† @€j$€ÆT#¨š7kqI×a&“ëpÀaª¹nÙ°/ 1õuŽ @€@# 15‚*û„@{@cjzâ,ë&;iàЛ+EzUQЫ*G©¤{HeÂ&¥ÅOJ‹¢dÙßò÷­¡ÆUghLúÜ;“ ‡©îoAÞ@€ 4‚SÖT[_cÒ;“ ‡)ëúgY@cÊš(ûƒ @ ¯ 1õyŽ ¾'€ÆÔ÷uÀ4„@î4¦cO>ëÆ»ÆedJ9ö§g}yÿS_Š­¼aäø2eÜ #«—ëGŽ£´AWßñÿý/ÿWå3ùüûç‡ÆOöS³mÚ¶«!ÇÞíT&Ó¡?ü ¹äzG‘wC€ @@cʤÛM[hL:[3™¾´ß—&M¡r¢ó÷>üCÖØj&€ÆT3*6„ @ Å  1µxqzh 4¦Âe×}I _Ó£>z`霿ì³ï—þiïÿ[ÉŸLà+ûðéÏ|¶ò~óÀï¾´t}ëkLú"ùí…¿\¼bCånâÝø¤/¿r86 @€ hLYWt»hLºîŸþêo®ø'8LYßì/ShL™âdg€ ô!4¦>„Ï¡!ÐÇИú¸8|£äKcJR¬Ü§Æ«H%Кјöüéã=ÿî½É·W¨5¦F}•²_@€ @ F)ë[¢4¦Q]{M[{Z…Æ)q˜²¾;Ø_ýИêgÆ; @hMhL­Y/œšA©”9F@cúSõhQiÖð=ú_%“é½S¯‡©¾b9$ @€rK)ëªo/IgûÑî?¥6Nq˜²¾5Ø_ 1õo‚ @   1µ`¥pJh4¦&æ0Í&€Æ„ƺ ´¢Æ†b 4&•YÃÕ)ë,Æajö—+ǃ @€@Î  1e}´‘Æ´õ£9;?^#I“ ‡)ëû‚ýõ”SOÉñ>@€ZS«Õçæ@cjkŽÔThLu+,õFîaûÎ#Њ“…b²"ŸéOû&SS¿V9 @€ hLYßm¤1ù—î›L8LYßì¯Иz·B€ ÐRИZª:84•SSqs°æ@cBc‚@ÝZNcòC12é[ÄL&¦æ}¡r$@€ @À@cÊúfhA©{Ww¿ûûU½P3™p˜ª‚bƒ¦@cj*n@€@  15.»†@‹@cjñ âôzJ ïÓï>þõ£U(o¿÷ûím(9! ê~çý*5®Û¦§Ÿ¸Æ¼ÏÅädÒÁþã“¿4æì€ @€@EhLYß -¨1]>¶ÿcýwýq—•u;ÖéwWw—»týiË ÞzÅ_Ÿ5öú  1ÕÏŒw@€ КИZ³^8+4ƒS3(sŒ> w©sHdK ŠÉ È”í¡Ø @€ Z  1ÕJªÖíZMc’¢$‡iÀÄs6Í8c -O\;ÑÅg6˜Š.Ok´J-¡›jÅÁvè%4¦^äí€ ´ 4¦–© NM'€ÆÔtä°9ИšÃ™£@ a’¡˜J25ìÀì€ @€@yhLYß­¦1éú¤%YŒ%-ŒX4B úS>“]ºô§“™´Fž1™²¾/Ø_O  1õ”ïƒ @ Õ 1µZp>h4¦æ±æHM%€ÆÔTÜ (Љ€Lƒfw€ @€@ИêVuóÔ˜ö¾mo;m·àKK¶R¿%9IiRqÚSÕ‹e4œSÃs@€šD©I 9 ZS V §”4¦,(²´›öèÕ¤¡­p.œ @€ whLYß­¦1­Û±Î’Ä)À’ËçD%ešs“ÒÏ ‹ØÄZ‚SKT'@€@И2€È. ЦИڴâ8íjИªâu´ 4¦v©)΀ @y €Æ”u-·šÆdö’%ÉI Âd—«5c—•äüq*Zc ÚX¿Î˜5öž@cê)9Þ@€@«@cjµá| Ð<hLÍcÍ‘šJ©©¸9H©pÙ5 @€ P'4¦:UݼÕ4&°ì%K*Ý»ºíü¢I+%6iAëm¥yNÒ›ª^#@ yИšÇš#A€ ÐXhLåËÞ!ÐÊИZ¹v8·^@cê<Þ –"€ÆÔRÕÁÉ@€ @ çИ²¾ZPcÊúÙšH©‰°9 @ %€ÆÔP¼ì-M©¥«‡“ë94¦ž³ãh-hL­Uœ  @€òM)ëúGcÊš(ûË74¦|×?W@è$hLT›\ ê#€ÆT/¶nhLmSUœ(ª@câ @€Z‡SÖuÆ”5Qö—ohLù®®€ ÐIИ:©6¹ÔG©>^lÝ6Иڦª8QT!€ÆÄ-@€ ´4¦¬ë¢4¦Q]{él³Àþ )4¦Lq²3@€úSÂçÐèchL}\¾QИE–ýB ÙИšMœãA€ @å  1e}w 1eM”ýå›S¾ëŸ«‡ t4¦NªM®õ@cª[· 4¦¶©*NU 1q‹@€ @­C)ëº@cÊš(ûË74¦|×?W@è$hLT›\ ê#€ÆT/¶nhLmSUœ(ª@câ @€Z‡SÖuÆ”5Qö—ohLù®®€ ÐIИ:©6¹ÔG©>^lÝ6Иڦª8QT!€ÆÄ-@€ ´4¦¬ë)k¢ì/ßИò]ÿ\= @ “ 1uRmr-¨S}¼Øºm 1µMUq¢¨B‰[€ @hhLY×SÖDÙ_¾  1å»þ¹z@€@'@cê¤ÚäZ P4¦úx±uÛ@cj›ªâD!@€ @mC)ëªBcÊš(ûË74¦|×?W@è$hLT›\ ê#€ÆT/¶nhLmSUœ(ŒÀ¼+LÐïƒ7×Å€líš³ä¾aP‚ @€ ÐИ²®4¦¬‰²¿|@cÊwýsõ€ N"€ÆÔIµÉµ@ >hLõñbë¶!€ÆÔ6UʼnB@ä*IcÚ½½;IcÁ-W=>J€ @€Z‚SÖՀƔ5Qö—ohLù®®€ ÐIИ:©6¹ÔG©>^lÝ6Иڦª8QÈaš>°¿ŠDCÒ’Â/½6y¬‘Qˆ¦í«»’ë哤%½ªtr–`έזŠÌdk™©m/‡ @€ÚÀÒ§Ëv¥é%~zG •5&]ÙŠ·‡—GÙ±{iï.wC И•]B€ ÐL÷.ùëÔ'ð±Ëÿ¾™§Á± f˜5<½ï嬿Úóá¶fŸ ǃ@c 15†+{…@˜«¤kAN’¢.é·iLiik×ý©õÚÀrÌiY öÛe—kÀ©±K@€ @!Ô€LZÉO¯ ´¸ÆT. Óô×êõ¥³4€S ²K@€šI \@&B15³8ú€@¹€L„bêƒÊà"€ÆÔ(²ì™ðSÂ)‘œŠáÿÖŸŠ½ä^²л´Æb2ñ@€ @ ±R2Š) è-®1éS2Š)‹Êg €ÆÔ¨ì€ &Hd"S“«€ÃA o$2Š©oj‚£6ŠS£È²_@€ @€@ Ä2Š)£› õ5¦d@&B1eTùì¦И•]B€ ÐdÉ€L„bjrp8ô d@&B1õMMpÔF@cjYö @€ @È#X@&B1et´¾Æ¤ d"SF•Ïn@©PÙ% @Í'àd"SóùsDô? ¡˜ú¬8p£ 15Š,û… @€ 䔀 ÈD(¦ìИü€L„bÊ®òÙS 15*»„ @ ùü€L„bj>Ž>#àd"SŸUn4¦F‘e¿h6›öœº×žIC›}\Ž@€ @ FÀd"Sv÷F[hLº\‰PLÙU>{j4¦@e—€ ô  ÈD(¦>ÏA!З, ¡˜ú²8v£ 15Š,û…@³  15›8ǃ @€ÊP&B1ezƒ´‹Æd™Å”iå³³@cjTv @€@Ÿ°€L„bêø}IÀ2Š©/ë€c7Š@¾4¦¥K—­øs饗žvÚi•·áÕ#ð³Ÿý¬ò]{íµüq£>‚îwǦGíõñC2Ü%»‚ @€ Ð3›&Ú9ÿ¡ž½—w¥hI'?ñ…Á[ß[H=B ¥  1µtõpr€:Àœ9sªk8IÃs¤«ü óuÂÍÑ€k¸æÁkÀ^Ù% ÐêÜyÉÇï¼ÑêgÉùA ~ùÒ˜N>ùäƒ9ü¢K†X¹0V.òƒƒÿçÙç‹/S¹ Y^vAXÎ/Sλhpj9÷¢ÁQ¹pð¹^9çÂÁ^tÎQ9û‚AÉrÖƒÎ:?¥œyþ¥Q9ïÒ3½rÆy—ÆË¹—žqË%§Ÿ[,§sIj9õœK‚r¶_.>õì‹O‰•³.>嬋Y¦ 8óâ° Œ•_œ90(gÄËÏÏXRNøóÓ/R99­üì´‹RËOO»((§^+?9õBWúÿËÿýoþÓON¹På¤x¹à¤S.8é—üíßJíú?\Í~ÇÔ©S¿¼ßG}·_{HWÍÆÃñ @€ æØ´i“š'xàÎ;›wÔN?R»hL[Úgß/uÔQ4N;ý–lóëCcjó äô!´>= {üOJ†¢.â?}ÿàÃ4 •rŠ 3ÅF— ƒJ)ÃI±Q¤ØÈQqÀ¨8TÅÆ†J‡„¼Á ÄPlÜÇî)â‰îÄÆtl(ç¿þ·>àÀGpâ7|ý[?Ð0_ëW}óÏPXÔþ=ztóÍ!>$ ÓúîÃ:àÐ #;iøí£¶nÿ½Ê–¨ìÞ²½Xn¾}ÔÑÇ´ùÝÝ®¼õîî ¼£ò;•7]yûwoxeÓÛ¿Û´m—+·íÚØ• Ý»Âòц­½î•õ[>råµ-¾¶9*ë6•·>\”¬¬y³XV¿ùÁê7¬ì|Õʦ ¬òÊÊ;Wn|ßÊ • QY¾áý ¼þþ²×ßseéú÷\Y²þ½%ëw,y-(‹]Y·£«X¶¿²¶X­Ý¾hMT®y7(«ƒò²+¯¾» *ï,xõ—TVEåÅUïeeP^Xù¶•çWËüoÏ_®²Mež•eA™ë•9K»]yni÷sK¢2{I÷ì%[g/Ê,Wº¶Î,”][ÆNZð·ÿé¯l™îÊ¢-Ó¢²yÚ¢ÍSnÞç‹û·¾Æ¤Tÿþ½C®êqïãt7ì “C€ @Õ „S¿)s—>6i.&Su^5oÑ“&ÕþóK6ޏoÓšë– û‚S_P瘀rE@OÂOL˜E¡ü±§›n ¤¢Q§ÂxSl˜)6ºT²±$7d£H…ñ£häȆ܀‘Ɖ¢A" ƆÜÀPa<È ÙH² pè§8ècÃ=±â±Áhdgé6Ó±7”óƒÃ¹øŠá…œ-¸‰Æn C6ýêf4¦ä‡HL®¼~„jðˆÉ”«/.6çŠCô¾s~+tèåçNc’¨´y{ÑRò%-ß|[ðÔXV]’ÃTj/ÉdŠÛKµL[K¦¤Ã L t˜–{“d¦R)r˜ŠÓº‹=‡©+æ04¦…‰GXïA6x–­Åaª[cò¦à©·à0ùϾ¾Æä&-¤hL‹¶L÷¦i ÛCc²T‹^íZ¯í¸“©C¿¯¹,@€ ´>9L_Ù¯ßÔ¹ËÔÒÔ@È#1™2«´Öטä0©ö_X²‰ÆifµÎŽG©qlÙ3 „¤1›0-6å?ýöֻɟ0ΖæÉ‡#Mµ8Lë óáÝLxÓ˜l¼›ún“›ñîÏu÷¦¸{“Û£!¡hB»›ÍnóØ£Iì…éë6qÝÍZ÷5&7SÝטŠóÒÃTIÃ7IéB4¦Ä‡+p˜naÃ| Lp8&ß?Ȇ†óQϹ¾ÊÜiL7Ý6*zLŒb,#-)ØRôÔX>ê’E`J‰½”j/UÀT)Sä0Ń0â0EA˜Â8L%A˜<­¾\¦¾p˜ J~!SôDë¹ùMÅ43|¶hLB1µ~4¦àÕ÷]´z›=§òÙº·ÝCL¦\³sñ€ @èÃôµ~Óæ-S«Ó5O™0‡˜L™TG‹kLÃôµ~/.ÝTÒ8ešM&uÏNA©TÙ' xô üøÓÓ é>R2~h@êÇÇžä9• LA–—âÃâ0¹Ì±œ©“<*†b ³vX(¦X²ŽÔPLnN{!S© 1Y(¦`úºÓ˜i7B©˜jâ1ù¡˜")̧DcEc*:LʤL>²g 1Å>ar˜®ºa„Õ¦iLJ«rXÿãˆÉÄW:›@úÐ0­ïήõü]]î4&=ÃyâLxwO~¸XÈ% ¿äž&-y\!s\Jò8=e®÷Â/EšÉO!W°æë˜ª$’+ä’‹„¹äЉäA˜Š¹ä²ŽÃ”‘Ãäõvc¼y¿»B:¹ÀaJjLi¡˜Z\c²T¯¬Ù{NU ×[ïÆdÊß7:W @€ ¾#9L󗹿‰Í²èZ·ý¡§1™2¨˜VÖ˜"‡iÙ&¿ö5ˆBã4ƒŠg "€ÆÔ °ì€ BiªË—Ìõqã-Ò˜N,9• 6Ŧ¸ÃT´ö­ ‘œŸN.š_˜Ÿê0¹¡¢b(¦D:9=Æ[F¹*¡˜B©öPLs]F¹ÒPL¥SJ(&4¦¤Ãtõ #/íõ÷-' iLª2L&¾‡ ÐÁîàÊåÒ|yÔ˜bŠR¤º¿ÈIþScIâÊÞR"ê’ ò.Kq¸ð¡Óä_ ÓûS˜º¸`/yQã´Lõ LÕ¦ð!µ(0EÝÍÁCOX¢ÖØck˜ 9ž¹4—\k8L‹·ÆÒÉ™Ë_ŒÆTÆa2é¡ñ“ýÚ|wçZá{Dÿ¨¾óýC»Öl ŸS£ÜÕî9UUsËÝ|è»ÿûz϶««Ë‹ý¹k×.-ØÿªÖë§ÞC$·í¶Þ®[·®—{¨÷ˆl@€ 8æ0MŸ¿Ü¦wû³ƒ‘5ÛÇ>õÜý¾ùÞûï× Í5Cl¡7­µ*Ýß@Çòÿ´Qìíõ¶AʵžbÇ*w’-«1™ÃôÒ²M6ˆ’¬}5N9¬WÓîîîmÕŽ3dÕ2uð]CØÅn¿ªw‘öº5Zu!îµìªö;¶ÞO–moç¤WgO»Æû¼gÒ“w¡1õ„ï :Hczì©©©)>løé†Pc**ÿцpt)6ÆT6Sa8ÉÉ­É%sɉ;¼8L•¦âÀPqHHóáH—NnµÆ} C?‰PLϯxÛJ]¡˜|Éf¡Gi4‚PLA4& Ö(Ó9±tèí£?þǟ먕NÙTq˜®¾ñe LÎ!‘v¦Ê:´ÿq#GÝ[ï妎UÞIò±¹ÞƒÚö-÷¬Ø³Ëà]h0Ò¡á õí+Œ…¡áÃëntûºÁTŠ»g°¸i¨›p ÜiL•б”œœTXðŸíÙ±4ÒRl©Œ´”ð–Âðžå쥷>ŒÇ^*o/¹GÏà´4…œÒÉ9•>J!—©'S8e6˜\àÐ4‡é]{x-¦CІ°…€¢…˜¢E%¿Þ\r½ŒÃTÆaÒsðƒ–T.æ0…Ä®$5&ÝBMøpV>„ý£Z¼öí Ï©ªˆá£;èúþ]éaqï½÷ön6L ýŸþýûkyâĉ¶^?þö±?kd;hï²Í  S8p v2gΜºÞËÆ€ @€@/ DÓóËm€¤˜Q®08öXýîƒO>·ÿõ™Ljžìµ×^Ö ±Ÿ#Fèlõð_ï9kWj5T~—öo½ðjbhÙoÚhYg2vìX·k€¤îPm¥TÕ#ÙzÒf:v¥s«zz­©1™Ã´`ù©Su#¨Ó gS±5ÂR´㓬 ž5EËÝ®!l»µÛOíͪդ[H[ÆvëßÃv÷ÖrCV½Éu2õºtÉÓRÛõåxºIòôÊ}0ëºÏ«^uf 1e†’A€@:iL<9%Êì‘6Uþ†áwýèØ“CNNÓñ˜bYä\¦@` ¦X¦pðèýhب|.9Ëí'èˆMk/:L=J'e” Ók¸trʰ¡¬…Ä[•XC“Ê÷£¤r願ÊiLíþSÞnAs˜¢ÆWÚ{?ô¨úL&¿ñec@µ4»b͵ׅò­yբϊµ_ [B Y74l-VwÉb³.±WÇa°¸WøZï͹Әô\è%€ó“ÁŠÒ ÃGº§Fßywò{Ñ‚[*¤%.d‹SÈ¥òQ—¢ÀK~´ÏbÌÏBì¥Úí%ÿIÔ%6É•¦KÉ"—©D`Ê.“VôE/Aò +#1ßÓóƒdÉ~¾äy…gÜØ“nð°[xÞ-›K®¼Ã$—ßiL¦ó[ñ¦ÔhL}®1¹T…A‚”Ù®öœª¼Ô7Ýõh]&SÉÿ¦~yû3ùϬj¯nê7a5&{Ƶ}º³j½/[΀ @I î0ºÑ]F9› lÍ“ž˜]—É”lžÄž5:ªV€ó3’¢†>1ÓHÛ”kÅhãT¹$µõäÔ¨ vˆy jLÎaŠ ¢¨ö-Ÿ…_û7×Ù8Õ%árbPÌ3k„Æäî™Ú[¬É³•{§îTW=hTõ®wƒrw]…në 7j¹¦Ö×~Ÿ×{ =ß©çìx' ÔD Иž˜R: Í“·á§ë5 ủÉäUì%?SY©Äa F‹ Q35N䆊ãè0­³|Ð%©9êq˜ÞÑXî ã0=óü9ê.œ¯1&åÓ5¦›-“†Š©8j“)o“¦a7Þ!M->‹ t‰ hTîzL¦XãKá9ky®e›ÔŒÉôÖ¸kÅgÅš>ålæhèаiL®MÝŽƒÅÍ»›u¤ÜiLz.L:InM¹§ÆXŒÊ(C\i¤¥¸´¤´qQª¸b¸¤·KS—*Ç^*o/U ¿d)ríÙ4–B®—ÓËQ¦ ‚0•u˜ ¹˜Ò¦@Ûwæ~àïwù¹ä¶X$Rÿ!øÁ‰A4¦ S jLÞ?ªÄsj¡así9UI©oùHí&S/5&=nºi²ZÖ¿==ƒê·EÎO®‰u [‡¯½Åâ*iÙüYíÖžem'¶Y¬“T/5h<£YßÉ€ @íD@ÓW¿ÖoÆóË­½\Âk ßûÒ«AódôøYµ›L©“j˜bâ RŠõÁiKüÆ5%´“˜Mb~†í_Ëþ«êÅóÃ/é%ÛÌoæX›E/¹·û ­×N\{Ç÷Z¬Ê“ç»ZMcò¦QÂÚ¯«qꘘ1#æ÷±jKëfµêóo ^²ÀWÚ›5Qõ§Ý*¶s­täO+×[‹ËBY“Ó¯YSÖÔ€uïÕ‚_wÖ†uéä쾪pCº†s¹c¹Û)Ù|»jÿ¦•>å&ÐkAº=»öµÝó®“ÚnÑäÇGGtŸ,½×.9öéó?˜1°>ª÷yó¾јšÇš#AÈ)iL?19u@ʆœ®¿y¤K‘æÒÆ•Œ4EcLhhÉ]*¤KÀTs¦õÞ ‘Ëα6Ê%'=c‡iٶذÎì%ÝÅÑœp(GÓ@_còÒÉÙäs4¦Àaúmà0•âîÍ! †‡V¾sð‘ÇÖ˜].Uc²‡X÷àgc4å›]cJO†ÉæXãÈôqß-ô¬˜Óï-.»E TÆà«»7CÃ6&ë>€®…èêZ Ú¨5X~û×õœh³ä—€û&q U·ÆIÖØtíe#¶&¼kfºÇ®!›HÆ`q‹ÞÇužVþ4¦›G&œ¤ày±ðÔx§ž‹ÉàJC+Y€¥])n,yÁ–JSÅ¥…\*AÉOŸû`ú]Æ©s-÷yåOA–¯¢1eI“}A€@ iLŸ*?mþðº›ïüáÑ'–OëªKÞSÜ^ G”ô0feåÆtÉeíÐ ‚•’ L¯¥aò¦pB‚MœV€UMNЃ}”#x¼¯!Se‡©RÃiLA(¦‚ÃäÜä\c*q˜6¶,°–÷EÁPÝ÷pÅǪÑdJ6¾¬µ¥':÷dhC0å›í)ÚeS˜ýÆ‘=…úŸœÖzVä[ -CÀ.(ŒQ\½´¡a¯õ]óа5 cyxüÆ©µò\šu7;Hïò»2üNØ—€k[S×¾[¬nßNÉ[ÖÇš™ÖzMm)3XÜ2wnoO$w“ž ”t’® Ÿ£Ã’“\y+­T]©è*E"|š±”¶¤Å¡®äJš·ä?q³‡[­D!@£@ ÁW•_ÜÃhì‘4~) … 5UÓçÚÇŒ{›D[úØ=¼úϯÅr…~j (”½Ê"ç²&Çr'ׄIOÀöü@éSÉDr­©1¥ý£òžS“¡˜¼çT¸ºñŽšL¦ “û7æ&nÚ?›ä³¦Öû½œúÓÞâÿ3‹õÚ›Kë÷öºYgÑêÿ¢vâ*üÿyv·eo¿y? @€ P‘@‡©´Ý2ʹnt%˜¸ïñšL&kž˜Œb?vR.«:­Ô±4ë>sG¬©â[#¶“d¿yLcR‡šíDñ¶à÷ÙYÄveaoôvkÑ8)ÖêñOÉ:éìí~O_ê­£1Y¦‡©ü J¢ökmœ:Â®î  µ@cšš­uŒÚ=ãš™®:lc'¥ÙÍ`Õçî1W•v¸˜ÆäOò‘ig!¸\ÝY÷®»gÜz‹È¥-õj¹2ÖεCÛ¹éÇŽåvh'ì‚"».àØ™¸û6y¯Ú’ôìüÝ~ü[W·ºQŠ}úÜÓ®ÑNX îÓZã}^á#ñKhLew€ ' iì¸ÉeçÆoþðÚ›‚©µÅ´ñ¨K±&\©‚½TB*ŒU˜vtÕ„)ÕaŠÆ}äÊæ«o‹ç’«ÍaR2ïDc*q˜A˜\ɳÆä9LQ$T jV³•<†•o+ÁŸRûtDõ˜L~ãKrþŒ÷8ª§;³öS›cÏÞ±‡ØXã(Ök¹gE¾Ò ÐR††ýÖwFCÃîCmÚ¢k!ú­Qû[KÙ¾"lÄÖ%…´Î ×L¶d­…¨·X¿þtA‹íî4Ü—‰[ãïÙj¦\K™ÁâÖ¸s38‹ÜiLz.ô -Ý[±èÕþGŸ`ZR¬øÎ»UòK`Á»ò†\%+¥ÆR™`K´ä™ò©ÞROÔ¥BDÐò™ã‚©±)öRA´¢ÏYì¥dø¥È»÷òÇü¢À´2šhë&{uÅeG.›BnÙ¶¹aò8Wž+¤L–ÃD ƒŽ–Lmßâ0%³ÈÙ°ùMcòŸƒ“Ëû|qÿØœ‰MÛ—¼É?UþQùƒklbD8B3!”…:|N»lÛõw<\Kv¹¤`dÿ{\ç¯=ÎÚ—ä71ÚuVÚ¿¿çÔÖø íO¥ç»·zÕW}õ§í·Ø €&W ‡ƒ @€@> Èa’Å2=Ì%ÃT¡½0Xm@5OîylfÕìrÖôHB¶¶†…7W»ÀfDhcËœeÛÇ‚-e¢1i·:f(ZŸ¾ëÅ3Æ·m¬[ß?y'‹Øéù]ÿjËÔV¶E4&—K®¾Ú§éƒ[õ7N}°®kŠZuû'±Jñ«ÃÞëß-Ö\-7ãÞëßEVãö«ë˜ÆäÛuÚ2æ ¹›Äîÿ¬©›jò%ï"]‚%Ôó?/¶Ò€.0†¥ÇSòÓ§ãÚÑ­ƒãîíïóæ}©¢155G‚ SÒ˜||rb@ª8ödRéƒM…a¦Tu)6Þ’;'í% ÕS1SI‚›Ü¾Ð†A˜lÄÁ²¡ŸÒŸm‰Šw¬,­˜K®0 cC9Ò˜.’Æäâ0•:LyN*8L7rÉryC1•z ÉYVUM¦XãË>Ör±üPö£95jL˜í%§;è(-÷¬˜Óï-.»µÔ?4\ ÅT×аûP뮨ÉLÖ8}m:µ1õÛÒ¸˜Æ{¯µpÕi£CØø¯k-Zó¼FI]@vž©ûg°¸µnâ^œMî4¦k~{gRBrkôjÙ§ÆK©Œ«T>=\Û3!-%SÅ%½%ùÓ^J‰ºä©KUì%/ð’Ez÷Ã/Õ`/ySøä ¿d™R¦À^ :.ëH!D`ê…Àäg‘󟀄iÌ„öИbIOíöˆRË ”†b žSÃÃu#ª›Lêy´Nyý'pÝ ¾Æ¤—´ë ôŸ5]w¼´þ\ml±ëcküï.7`Þ® ]è?Ûm Âž•ýµôû÷âÛ’·B€ @ S”Ñ J7z4ËBÍ“»­b2YOºß3eýjX„$×r±‰6ÕAM{£ßTqvHÌñ+Õµ>üfH¬3΢.Ùi¸É–7Á^²ž;³©, ¬,Ѷߣç¢Æ¶L+hLÎa²¬%ÉÆ©% úÒòY³˜ÂA”§F8föX¨®­Ò­ýhÝ þ–U5&kuZÝYMé-Öãé†p\•ÅÎÄÕ¬ÛÒ¯ëXO®3~´gë«­ÉnokJ[Œýä±ÜMk[jaÒï˜Æd{s÷¼b÷ª¯1Åí|ì“¥÷ºQ«ä§Ï}0ÝÆîì„k¼Ïýdc—јË—½C€ÀiL<þl…©aနKŸŸHåáÒÆE#J±ô¯CÉñ£%…a#Åì Š—£#™#M`ª3‘œç0'¨/é.¦×X¼u–•p.º?=И~}³Òhhì&5‡F>£1ÉaºÚs˜‚l-aE§¤“‹¦¸Óy»Y–çäG3rÔ½å>œ1Éž±­ÙeÉö(hFS›ý§ñÊÌzUû¶AË=+ò¾&à —›?¦Ö·Æ÷í«[y?•ôÓ ƒ]GëÛï Ðg_a€­=èÖ[ËTk,°uth!Öõ;=b_Öt5¨öMbcÇúÓ†õ[X_Šë]q'k“êíåZÊ|™ôõ›Ùñs§1é¹°*ÉÅL*.O?>AQ”R)¥%ƒó›¢4gáÚb0ÏPWzîåµ`É•Ù/¯ ìx/IÜ3³^ytâs*“f½>‚DO!•³ÅE9ŒS£.…£Þóhx©¼ºôà³"Å>ü¦?e¥3~¦•0çq1yÜc“_2uÉì¥ûÇÍÊãA¹/,1 ß (Zj/…O´*c'¾¹ù…ø¢ÉÜB¦ üR˜*Lu©-4&ïUpÛÈÄzúùMO=¿Én€BÃ#ê&ž¾hs,Ó3/½i¡˜ì9uö’­×ÞþPÕ˜L¦ÐêÇ=Gê?GÌ`µ ¦Z \o“þOØ|Vý¸7&׸/3ûïeÿ¥ìÇþÓø¾íÇþ9Ù?3ׯJ4¦Ìþ-°#@€ ”'à&7v¢6¬Âè>5“J0&‰,–5調t¥²«m8ó•-QódiawÔ#3*Äd2çÃÿ±FM·pÍ›)h 39´Æ¥¾²«qM×qf³ýku­äT`×ð±öˆ½Ëthk¡¨#ÏÖXÿšõ빎–ýÖS¬¥SKG[ŸkLžÃ5NÕ“àfù[-¦Xœà•o?ûÒ›ŠÉ¦*ÕÒ85žåš{æ!©»S¿Íãñ·mýé¯qç*ºbõãš–6c' `ÜinËä™hŽëš®®®Ý Žk™É”zªÉÒºwõãy$e;·»Èµ‘ý“qG÷û‘“÷ªíÁ]¦;t²¥o··±Ò[R?}n”m¬KnéöhLü³ƒ Æ4æ±gÓ¤¢<Ã~{ÇQ?>!Š·”–¢Yñ¡;þÜËkb“ᣱ¤‚Ñ2ë¥Õ6œ” ¿4ýÅWzjöSÓŒJ†ŠÜüvwA˜ÜxÅõ˜÷س/i (œ¾Í`wA˜îyl†žñÊ%’³Q pÇ&˜|‡I™4 Óæi^"¹œ'•3‡ÉM!ã¥:rSè+¼c¡ TƒáØPY!¨…Å[¿xY“Éo騇ø5¥@xöÔm/%›cÏíå˜íXR”íÁ²mð‡’ÝC mƆ5Mèé‚¡a}©6bh8ÖâB[ Ñ,¶–¯¥ëÑ»Üw‚‘5$c_®Ak€»ïëÒŸnHÚ?1×&uiì’_2 ·Í-ž¨Ë*èNÛ_SEcRõÛ 0÷“\ÓF8,î¢Ü£Ô¢‡B= è©ÑyH• ™àWÉ)J_üòןôœ{ ¼ï‘I_øò×,ž§+Z#c)Е¬¼þžÖ|泟×oWì¡3o)é-U ¹”¢.ÙÓÌçÑ÷ ¼ôéüüãgº'Ôûâ~½4n¦tK-«|뻇h›~~¦Xõ´ª5z<²¢ç×}¾¸ŸÊ§þñó*Zøæw)—<.5ÜÝLÿ×/|µzþ¸% ©ð¤›L!WU`ê½ÆôÇOvvmúÒæóúÐ?ªÿþ¡]k¶™÷¦æ¨Ë§Z9éšYž?áîg׸n⦯;â²)Ñ A˜¯áÞÉk<Ù…bÒ µ†ÝVÝdjèuõxç Ê=(ÇFz¼[Þ@€ T%9L󗹉€š„sÆðùÖB9rHPÆÏÛèºÑ‡Ü·pȽ ý逃î~yÐÝ Š³,Â1Œ‘L¯š]®ê¹ÙêAsÝa6¹¢Æ7¶Åf}«1™ÃôÒ²M~ãtè˜W¢žŠ×vüúþE¿º‘3ØN¼z棳_·¹Ojœj¶ý7ÏàB1Ù J[7NÛâžá$+@câþ€ 4¦GŸñG£bCN±©p¤©8ØdÃL'Ÿr¶6²¥knºË­1uI#¶æ¨£OÒð¶†ÜÈ‘Öìû¥¯Yùö÷M ¿”šB®É Ù0Ðñ'Ÿi£?§ž;ØÒn|ê3ŸïY"¹™a"9(ç{a4&ß[Š-WˆÆ´õ£9Ϭ;ð£?njp­6u÷Ãtƒ¦(,‚rq˜ôø­e\ýnø¾>šCæE9îÊNÍÍ"°á!ébb25õ 9òFàì¿ÞóÔ ª¾bÌ+:^ }/5 »´¾«Bgƒ¦°Ì€þackÊjL滹 PÚErMÓ/§·,üË·gÁ”¢‚#|B,xRêŸQ8¥Ò J?<æ¤Ï|ö¿>6ñ9ÓMιèrý©gG§+ÉXê´¶ùü#žó#-i›³/¼ÜIK?ýåÙ*U¤¥”xK¡·o÷K,aœÔ¥¿{H”6® ×KQ’·d˜$ÁÈR=næèq3´Þ\{•Ù‹6êO‹½¤§Uy÷±Ìqû|a?=¹–&BŽb/¥ÚK.5ò¨G¦Ic²ðK~ò¸‚¡tnÆÂ/¹p£¡À´Å'—<ò¾²EQ‹JRÈ¥ùû=‹Æ´¾{‹¦ÑKÿ󨮽ÔÜÛû²üûíÕ+r˜"ã-ˆ «ÿRÑ,ç×vÈa:rÈë&¾ü¾…ß:o‚4&7H0øž—ÕM|ØàÉ~(&{N««omW“ÉÄrŸ=C€ @>s˜¦Í_fSt,ÏõÅ#_:}ø|,Ñôî[ž\©ŠM>õ¦yj¡Hc &ÀhÒöŠ·üv®Z(—ŽZPèFfY¨yrçC™™L0Fíɦcê±5&s˜^”ÃT˜‘eÓ¡£_q3AÝ ÊÄßPËTµÿÈìõæ0xzÕყ¨ö½Æi±ö‡µmã´cn­œ^SN+žË† Ð<Ò˜îä™ÄPT1qÇÕ7ŒpR± öÐ5{Á1-X¹Y“~ö˳_qƒžÁ4ÀôÒŠ·4~¤A%•«;òÛß?Ô2ÇÉUzjÆBKà ¢LŸùÇÏ»1£#|â%¿º®$üRɆll(,ï¸Q!=Ëi0è××Þaù7T4‰Ý¦oþû!6îhLaÖ`+±<šY­œÅñ´ Lnç{‡-Q©^iýö™˜4X£ÒI“4¯ºa„k|Y"9›@òëÑ‹TË ‚«'ðË¥1­Ù>ñï <Œ˜õļšâ®'ðHc*Ì"Ðhš_ 5&Só¾ 8S÷Ú£RQfJÖ "}ö#EuÝŽÓnž(Œõ Óúæfl.º¶;Ÿäš²“6µ(è.SrM‹\gí§ý×7÷È/…PIz&8òG'Ä‚'ùC(¹XJ…)ðzޔ䥳/ºüÞ‡ƒhLÎXvÓHùIÁ6O?çGZÚ÷Ë_;ëÂË]ŠâŸ8+°æ_ÛqÕ#Í‘×o{î<ó‚!&ÎÿdÀYZûÔ,gÐø½C|r–Œ–“~qÖ¾_ÚO刨¯°)óWýÛ—ö“º¤ßW\§Šl$ýéžM_~5ˆÆ$oÉžPU¤1Yž¸@c*D]šjL“ž[¡œqzru­Î[2É|=¿÷³3öùÂWå'ÚÿËwìÏÎП¶fîÒâã¬iL¾À¤GÛ~ß>Xå_öýꀳ.•yó‹³.=æ'§Ûšƒ<ÞÂ/iù€ÒïøôçîxpŠž½‚R´—¢ Êåö ©ÜšÍ›g¬|ßâÿÞ‰ª1ÿ¨¾wè¢ÕÛ,Ï  «TOÎÛh©w?»úÄa³,ª–&:žDcrƒҘF“µ\(&›ß ÜÒWÝ2¶jv¹Ú?_l @€ t*ÀaگߴyËbÍM|nÉÖBªë —ܤ—ÞTóDÝè7_!‡é2iL…nô[6hÔ‚Hc*t£k^Š5Oî;-«˜LZ }¥1Ó~ý^\º)Ù8µ”0AÉvDQíß5éUkœSXûjœŽŸ»1И®ŠÉQhœvêÛê×…ÆÔê5ÄùAh{Ò˜”¯£Âx“ H¥Œ:½þž9+~ј‘Œ% -i€ÉæÀ?üÔl ¹ÀKÏ/{SN{áU „eûÔçWiLç®'X´Ô¹‹ß°¡„q¦eáÐR0Nôê»'þ;oåÀ˯ӂ¦‚VyKz–•´d§*NcRR9‹êâ…ê(И¾°_2mœVžrÎ ð‡\3ÂÙKZ8oð5C†k,sÜ!GÞ aQø¥%Ýw=_cJÈL±¡aç/곯Djw[d•ptx}ök6…‘Ö7·dëˆ%•Ó‰ùkò§1]?¢‚“äžýgÄZ–å0=üôszŒÐ£¤¯(¹gJ}ÅÈCÒc¥zxõd,„Ñ•¬Xt¥±O;ä××ëYó©é/K¥”¢¤‡K‹«dšEiiÍö‘L8ãü!ò–ôÒÂРW°¥ž˜)iI[šJoϦã¦,°5§ŸwÙ3sWª+Y¤Q\ÐBÂ8Ó˜¿>,’–î|†t¥OýãçõÛÂ/¹œÇ÷>hLÁ3k!ð’©KЍ$É/ÉX’·dO±w?2]/I]ºìêÛM]ºKá—BoÉÊȇ§ÉU²Ìq¦ÚèÏqÓ—Zú3 L®Ø3®"0é·¶qá—´|ûƒSaßJZþ¸T¥©–¤r_é÷•Ñ3Oð#0ùvÿÝ‹£°LþÊ^.ÿlè^ßþÞ! Wu»{/ÊÑNrÕsêøylþÄðñ+ô¿ªîõMuÕsª?H`“)b.\£µèxa2µÎ÷5g@€ V#:LL™»ÔoÛ„ÍèU?šFMÔ¹^4¦"v)Ìz.,šËæ/{åŠð©1x@´â=&VXÖ¤­XP¥ ýpè'ùÏ”ÅmB9É\¥®°¿O*´’õý)9±X2iI¢’_ä*ÙsçÈž–±ôÀø™zô´ôpZ3~¦C{Iâ¬<>yå‰=nÆ ??Ó’ÄéÁÔ¥Šó½%—'NO«½ôØ =ú9㮽íõ>ßó¨4¦¯šº•P]’«ô˳™º¤üq.ÞÒð{žÐí±?=ãÜAÃÌ[ºùî'"?LŠ<ò¡à)Öb/%Ì7ú©ç-sÜÑ?9]Q—~~æ¥*– M“~k›ûž˜oáFÿy߯SÍö’ûš®EcÚç‹û?ðÌu垌Ǯø;å]ζÜ:áËê)~vîR»ë‚ýQ”þ T Æ4ÅÙ¢¿jò„f¸>:ûuKV­©®zNõ dãê9µÂ PœøË ιpp÷{¿ÿó_þÒ'_R€ @hY;wîÔÌ£“æúƒ(®…¢æÉƒ3^ "‡-µL5ÑBs­É)‡I%öÚ‰êF4¦»TèF—ÈòµoÿËý/5ií·³mguÆÞnÔÌ[E›jß5N£öi”¦DÓõ¢ºÚ—ä4‚f°Ù Š^8ƒMµ/Éæå‡ý’8ÁÖH¿ðW7ÿð€}ºoìÿg…É¡@ ÑÎøŸöœþ?5óű @ oôuÏC“¢8:%CQÑðÓ×Ý H•êJÑp@aPàªGZ’¸PZúšÆ•\Ê !ø½CŸœöòÈ'èi\ESßUlÉ/iÀÈÆäškÀȦ»k¨HÓÚ­<öìK§{Ù 'ŸiÚUyæE~éáIA ¹h0(Òôõ@`ZhL6k]“?_}ÀY—ó“ÓIö’Šzî;%ИÂÁ c:¡À”ȧQ‹ÆtìOž±vp¹içÖ~­Ýû/¾a?ÿ®(7<¤JQËëÔ›æé Ü¿5Àwø`{¦P2;lÐäÑÓÖ–›âþĬW÷ûÒ—&]xÄG7ÜÉßgýÕ=øÿŸ)è{å¦d\õ…M ¦ú­ïØg_Mï [ahØ9L5 ûYz¬õ­¡á£Oí÷PWÿIk3ãn÷/á k¾&jíŽÑy{hé“ëEc*јô\Xòè‘pA¯þÃãS6ð"'¹J…Ö‡2*zŽÔÓdà'…el¨"ùaÁ!S„I™4ÅyØØ%zTU][¦jÅ Õsªë&VEÓ É ÌaÒÕ©`25¢*Ù' @€Ú€™LLœkÍa¿yr×3«Õ$¹yü 5WÕ:Sºþ|jþ&ëF—Ã4H“×.‡é’»^*v£'¦~ï ÃVmxWÍ“-Û™hÑ7Ž™LÏÌIoœj¨ ’©›Bµ¯ø[Á JØÛ ÆéØpÅ 6µO)Êu¾5Ç*8LÇœHã´%j=''¡¡,4¦œÔ5— @ è!êî±+ H]HŸ±K›lŒÉÒtX¤%7À¤$ ýæú;•¸CIsošÛµIcCR—Ì[Ry66RÎ8‰æÏÌ]qøOÐhшÑOk»F‹ô̤»ìÚÛïJkf¼¼A£BZ£"›‡`ö’2o¨<9k™ên¹÷IIKš¸®G; )ü’&­1UÝznºû ý¶råÑõ; 4¦ÊS½IåÖlÞœ*3}ôÇM}TÛYvôèщ# €ªÛ`È—ÅûΉ¯*®žÀ­ñõŠð |ÆkÎaÒðÜ¡ƒ&ß?u­¥óSøêXà0íÿIÓ_°'ðvÿ)Ëkh©} þl iñV Ô˜®úž-ËíÔ¢ÖwÚа‚0éãïZßAÉ2CÃj}§ {æ(CÃîýAcjÚg¥WÓ€Ö­[çŸkrMÓ®¤÷R4¦¡×ÞžªÙJ½ª‡'!¥,„“*=GJ~wŠÒÓ^>âÇ':?ÉôpùÄÔ—-œ­Q¨OuüY‘œ$iiN×&KZУ§6p¾¼RÂi~Ëš×Ó§b/iYE çÕcd2þÎ!zîÔ ¶¤GO­‘¨tÝm˜´¤W}6rêͬV~a?‰JÚLнžPõû›ÿ~°r鸟qÊÙƒÆN|Q­‘½öEZQÚ8‹À¤g#=¼*ö’t% "jO±ç^­ùÅY—ºÀKz~’·d!F­˜ÀtôI§KWR¹â¦ûÕ¹yÖÅW«˜¤oö’žkvÆ%_?ð û݇Io©Kc²‡9ÉLãW~ÃE¥kÆdÿ®¾ôÕ&=·$ ÑÎoV‘_¯LVN¹i®X7±’"¸q®å<¶nâÇfoøù sʹöþ?*:‹{ÿ à @€ Щ"“iÂ×v1x˜¶îÄ«gºÊ”—߲扚™W>°øÊ1]Ånô%ÝCG¿òëû_ ºÑéرæÎa²æ &S‹ÜNÖ—ê§QGØ8½fì7 ôê_õàbWûjœŽŸ»Ñ¯ýc3£œÁæ;L4N[¤Þ;ÿ4И:¿Ž¹B@}L@OP£ÆNL HEsà5ü Hõ?ÎRv¤=rÿöα~÷PM}× ‘ ŒŸŒI]ÒØÙäšñ®1#ËføU rt¨HZÒØ½ ­ †~uí iH£B6<ô«kÂ5_Øï”sqf°kúº¤%éJŠÀ$‡Éb/iÜG£9<ý¼Æ€l¸gÌSÏ|äñzÔtåm|û ½ª zæ¿ïÉùq|¹LþÈN-јœø®‡F“™î_òŸÝxMghLºqC“é¸dãKOà^(&“:ÿöôn“êQOàãæl´8L–ÍYÃCÏzÝ"¡úéäbS‡›LhL}ü]Èá=¾Æä Ln‹XëÛ:^T®yh‰>þ~¦:††Kû^®|G¢15óÛ¿ÿØáü5{5óTúüX¦1UôêaýKŸ ¼˜I.xRLKJþé+JÎUr–’=Y–+…§L{Ö,>nÙ­¬ Šž8Ub¹áì;ËŠ‹´ä\z8¡l)’ë“©âb!—ì(VÌ[r%–‚$Œ³RL挳lq…²Å%EÖƒT1²høPåÇ ¢Œziã~tâi×§gܧæ®UĦ¦iLzžÛ´m—’b*,žŽ§19“iâ¬%QœÀÂ$W»7ìfp¢}”ðØs˜T#ª…rÝÄÉTt÷ùw'@€ –%`&ÓCOϱ&°›˜Úf©®ý8Laó¤;jžй&žrÉÅ&L¦–º¬/5Ù8µÚ/iœ†[1—œ ¢øÓh"ø׊O:L4N[ªö;ödИ:¶j¹0@­B@Ow=8¡‚¢ôëp@*x*$ëpãM%ÃL…9ðñq¥h©8ä†J‚£â˜QÚQ{)˜Öîgáðæ±»a hÈúIî±ðKRÈ%ÇtêÕ˜ì¡ñ½]ïvm:zi 3uŒÆd&Sp{ÔØø hùq˜,¸@ê÷T‡©“M&4¦VùRä<öì1)M`Š™L ÷Õí‚ÆÔWä“ÇÍÆôëknYGá³`T~uMðÔX Ñ’ÒןTANr/%,¥4Q©à*™±dÅâ*¹¢tÅ*©º’3¯cÞR`,E]ÉuHKÔ§²·dýѾºTâ--ŽyKú³u)ÊŽì«Kþsí½ãçýó¿}Eq˜ôûâ+nm²ÆdŸ%ÉL¯¾;2õó”:4l£ù©3ˆÜ8{††ú×;”z7S£ÈÖ¿ßÜiL¿v[ÙH¯ê=Ô¢%½\òìèB(¥ÄR*†SJ³”Râ*U ­ÅX ;ˆ“¥Š±JÙV¢ÜpÞBRZryâ*„\ŠyKUC.Õu©g~RïêAR9‹ÆTõ³¶÷m{WÝ¦Æ “é+<5c± ¤”ˆöÉT¢„l-´*ÿ£²GÕw?ø¸ÆÓc3@€ @ ?d2Ðï›>ù\r~EÔ‡î;L ‹¥^‡É™L>aÍéw¿ü0o+Uãôëý¾5Ncúš x³ÀS{Q£dƒ­²ÃdµÿöûAãTc$«¡q”$ÇúgÖúnÔœI3 15ƒ2Ç€ kÒ˜îót}R)ãMQz8?ÌR|ê{” £$GGÊ,÷0Zj,#‡?Bä UнT2q=ȰQ̳Qgø¥Ø8No4¦>¹Õ4¹¢Ñ “ûî»ÿÐ£Ž³Ì-nÑ L)Hzç0Ùøþô‰ñ¬à*i.^íìu©nd¼¡ï ­ï ­ïž û3ˆz04,‡ ©ïo…ŸAî4¦Ë‡Ý–)²Žôª{ pɃË-D)ÞJs½ùñ“*ÄRŠ‚*À• ªT©S]¥¨‹0`©ä1´¢±”i©i)ž'.%UÜÖXª¸2ÞR!äRi¸%¤ÞoÖ ©¿ºQoÛ{ÀÄê^8c ¬X|¦î]ÝZÖ‚þÔ–*Ú¦ò·Ðºõ¯ñ+_bz—‹ÀMqNÎr6ÙÖ Mä<®åÕ–í¿ÿó_þ’ã/F.€ @(Kà½÷ßßÿ€o>ðÄìbó$TX\ºËe›bÑc‡Éu£ëœvýq—P-˜³iŽŠFF,¡×¹¦v–þ´–—uºe(—¼þúFÕþ“~ã´¶Ú·.‚0«ÈfkË×â0©qúŸüE“Ù2™uI&Ó’û†©lí jyûê.Í×Bl½ÖhXE›é½ÔÒ  1qg@€@ƒ HcºcÌÓt\>ìÖp@Ê•ªÎ/ *ùIâ|©Å%æºÞRqÌ(1¹=U]*æßð3ÇU°—¢Ç¼*6ªè´—Æd“+44vùX5IT4Ö£eý¶;K);´Òl$H¯öà¦9ê^Ý'i¯âüvo AÏã0EIú>üƒ¤§õ®‡m-¸Ø¨²—¢« C4%׿1o¢EQm!É ©·oiÖú®04ìç‘L.´¾{04¬ï+}¿é[NßuÔ¶¯8[66꙱έ±¯¸`–Á))ˆí"wÓ«o-gi½^ÕÓ@걜neÿôÌ$ÉI•ý¤Ê•›z")&ƒ‹[ó•u%[JË —j,%3ÄÕ"-%óÄ%½%? ²:.]ßeՇׯmÐ I_îf&ékݺ×ÕÕîâ3éOû–×K– AV}~•Éô…¯|}üôWbSRË›åì u÷àUF_5ì€ @èf2?Ëš'±DQzé‹L&#h=hjdYg™S~|&yKzU“\0Piô éΩ×Ú®ÄúR]ãÔôµ`lÌÂ<[ã46 ¼“NJ®’FPôÛ²ZhhÄÖhÔÄ”&mcëU´^›ÉyÒ‹6ÓoÛ€Ä  1qO@€@ƒ Hc1úéªR)ƒM%àKb,¥K¥3ÞK½%÷V&#‡‹ºòóo$3ÇGz~©Ý£1©=¢æ†î#ÂWÄo˜hHM©=¢Æ‹Š´Mî;™L‡y¬…¿-6¾¼,ÞþÕªÌêÈ ÃUÍ%s˜ì$õŒ­'jAÙötm!Q¥+é \ zêÖüÍ4Ð[4÷@E ©±T{pù½} So òþ>#k}Gñc­oŶH oÑ ‡É.ؾ»´ n}¡iY-n ™}¡9AS/9éÏxeq`4¦,(f³µú®77_›IcRѳl-qùÌd7õ•hòD¡áaÕmµiuç=¤ŸSq˜²ùÖd/€ @€Àž=f2Ý7nV‰Â²,PX\ó$%Ll¡íª[Æ~ï ÃVmx׺ËS‹"ñøq˜u›h]ixÉͱŽ65²ü¹"j‚Ù~²"`}©ã¦Ó¢ÀTsíׇÉNØ…\²hLnÖkàÄÂ2iÅ/Ém2ÛÉÞ«·h›¬.œýt4¦ŽªN.€@+4¦ûŸö‡¢ÂJV‚ѥ˂©ÀMI-5ä舌¥Xž¸äàQlÀ¨.u)6ƒ= Blö6öRrúz{Ec²¦‡iIj˜Ø‚›ân¯ZF ÙH õìf•Étð‘ÇZ°ƒy‰)~ –hI¯&{Æväzö–À¤Gk=u»çsYM®É6s¯ÚtS úþ©ïë€3è9¨õ]Ïа¹ÇCÃn\[ßc.N‡¾Ä¬ƾ÷LÜ´ï7•ÎÈ„ÆÔó›5ëwæNcºìª[Ë=üi½^Õs@… ª¾ê”–T4“R¢(Åó¾;ô|銟“8¾ö —+þ3¨ž]¬&fTŠºRб”–.zN­UZê㫤yM±ˆ¦ÇØ‹X˜ØÞ8LÖYfcsE\WšmcS¢U\­C¸·ÆeX_j²qö?D³kÜ›žå’sª‘ èO h˜Ä,Ù˜ŠÓ•¤.i½VjKBgÉ,T\æ‹Ö ÇY´ 4¦–© N€@§ÆtÛ}Oõ`@ª8Ì8+%9:Å•ÂpRlü(9r3 ‡ŠRæ´»¨KÑ<öÂ$v§.•L\/ =Ô5"Syã¶Ó˜¬aâOb÷gSØ«úmÃ@6d¡Mzö˜LGUw!K4üçæ·' ö,“ÎйJöîì%­×²‹xªIzä¶Çr=„[´TK ݳ+Íø]hLewÍ&P®õíaÊ|hXÃÖ¦%ÅìLS6-Μ¾Ö´ûг4šíþƒÆÔ:5˜;ið•·†}éE¯tæt÷È&ÆJɃ£ÿ™&'™¥TQQR öJ–R¹LpYèJ5„YŠGZj'i)ùˆÜ )Ù«n_âöÍn¯šÃ¤ %Zûë™LN^XœâöGA˜¼‡T¦ÖùªåL @€ БÌdºç±™®¡Z¶-‹8LbhsBlÁMõs »Õ¿f¯º‰Ñ–{®#á÷ùEY_jÔ8-Dv!¸R{QëÃd×(É…\²±KW¡û­ „I JiaÓÁº¤{/?ˆ@c➀ Ætë}O¥FEcLƒ¯¼%J ª”p•ÒÇ• .‹¯.¥IKQÊ¡øÌö®`H¨¶œqÑHP†ÒR»Gcr “dhXÝYýq ›Äî¶ïÍ}'“é #Ž-ÓøŠÉùSzì0é$«äRËYfg÷|n®’]Ž›c`ÏÞNêÍÅfö^4¦ÌP²£>#PÒúŽÂ—$††ÃlY »qmËiWÍ^rª“^rI6ûŒQFFcÊd»ÉÆ4èÊ[Ruu³‹ôª\f?$Rêr% ©œ¢´´ºœEÖQß_ØýW®”‹«”Z)=º’=˜¦d…+¦4óæêqÇJ Ô3–¼ïÁ†>¶6zçÓ˜,:¨ë.W‚d=³ZøPëj7Cßf»5~¦ÍdzøÙ…6ÉÕ&×Gì?¤‡©F¤l@€ ôŒ€™Lw?:³T`J ¤æI/ã0é Õβ\rê2sSýÔ°RÏš+Ú̆ ìw½ ®žqÈ绬/õ‘°qê Léµß3‡I`5pb¹ä´ ‘Kf¡e›ù­õZ£?õ[ö’ ¥hE úÓ…kÊgqÕ• 1q@€@ƒ „Ó“–ÿ+µØ€Tõñ¦4W©8œT:–TLÊ‘o©0”àÔ¥’A¢DÔ¥f¨KþP{Ec²DKjk¨ÑáZj’¸‘ ›Ç®±!‹ë¦^ôò¾3“É5¾Jæ·CPkFµ7“NÒÍ%°hLzðÖ¶Ó•ô|n©œíÉÜÂ5©À¢¢:ó©—›ÍÛј²áÈ^ú˜€µ¾mh86}(;“¡aõ·¸Ì˜I?öýf=0–"Ó¾Ü,QÊèðhLÌ`7yÔ˜*<ê©QÿþçÊ‘•*$ws/ZR59©4ï›%€+Éþ¦¯¤úE¥‚«”ÈWNWê`c)ÕˆjÆ”ÁG³Ú.d2ýÛ—öè™—mª„Ÿ¦Á=¤fòªÚ‰ð: @€ wf2zdFÔ<±±¥}è™8LZeб‹h«•Hð×ëO­tÝmy¯¤†]¿õ¥§ej¿Ç“N\“¹ÝékÙ/é·"3¹DúÓ½dëOÿ ÀŽÛ–SÛV'@ ]HcºåÞ'K¤ŠcOÛ4~téo†[d ¥ÂÐRUc)!-Å'·GÞRaB{ÉTö䌫:k½½4¦>¼e2ýàðc*Ïoï¥ÃÔ‡W—ý¡Ñ˜²gÊû†@¼õ¦þLö½œøË ιpðú-U([¶ÿþÏùKß\Fk©uê'w“ž S좂ftIøÔX´Ž*FEª0)‘ßÍ´¤ÐLJ““ÊúIa Y¥=ý ŸÅ Ji¢RÜUò¢+åMW*÷|ܾ“¾DÌd;iATÑžeo×Ë?ªÖùªåL @€ ÐÙÌdùÈt¿yâ‚™gè0u6Æ6½:ëK­Ð8íÃÔ¦L8í6 €ÆÔ•Ä)BhoÒ˜n¾ç‰’ñ¦Òï—\H•IÍáååHZ², ~IŽ%3r¤yK…,}á-ÅnИj¿ãe2}ÿðcJæ·{5ˆÃTB©ö‹-[ž@ÕÖ7Cý¬C4¦^Ìðí¹Ó˜ô\Xúðç£`A¯þÀ‚1:åÈÄ£2î‘EHòKòÙ1}MWU9)J=h–±”j•J“ÁuJ>¸ªæ~-´µÆd&Ó>_ÚÿÁ‰ üt§8L~E²+@€ @ Ff2ÝùÐôdó¤÷¹äj<6ë+Ö—šÚ8Åaê«Já¸U 1q‹@€@ƒ ÓÝO¤ HE£Ná€Ô1õ 3¥OzsÃ%F‘*IK-9N„ÆT×-˜L‡ãg‘Ë$—\]çУ1µG=q–µ¨ÐúÆaªbùíИzÏ0«=äNcºøŠáL#½j‘Ë–P?²’pÛk\Sx ,o&™@¢(•†Sò"*!*E¹~kQ—ümÚ]cÒA`2}q]ˆ]ü£Êê+’ý@€ @µ0“鎱Óüæ SíÛzKëK5Nq˜ÚºN;üäј:¼‚¹<@}O@ÓMw?QÓ€Tõ!§-f¼u%o)´[¼‘£¶Tuø©Þ»V&“ ù`‰Ã”©ދí[ž@j뛡áLê )Œ™ì$ÓÐáô£‹‡WFËÔ+‘ÌnJ{ ’S‘ü…’§É0]eTm‘“ä—Â#f郦y+íðÄYõ‘´6è)i2ñ*“/Gv@€ ô€@ÌdÂaêÃö}K¬/‡©}«2gŽÆ”‹jæ"!ô%iL¿õ„7 uºxèÍA^°Ú†œR]%o®{að¨ÇИzp¿ú&S:@4¦ÜX¼¥å ÄZß gUchLY‘ìý~r§1 zsL0òþ.ÒSãaÇ”•|ñ¨¢„TŸ“äÉIøIMv›:CcòM&þQõþk‘=@€ @½!àL&¦Þ`lÓ÷º¾T¦6­Á6SŽ*›K… Ð7¤1Ýx×ø²™7^Ù’2 •˜ñž«¤hL=»SÍdÂa*K©g7ïjy®õÍÐp†u…Æ”!Ì^î*_Óé§ŸþéÏþÓ>_Ú¿\ùÌçöþ/ÿ×ßVØ ÊK_Ü_é½(mDàÿý×/ÿ¯õוOøû›ÿ4~Òìõ[>reÓ¶]½üà5âíÊ.÷ùÿöÏç\8Ø?Õäò–í¿ÿó_þÒˆ`Ÿ€ @€Œ@`2ý?ŸúÞ—þßUÞ­ÐBQóäúhF@}©ÿô¯ÿç÷ŽÜ¿jãô?>¡qÚa•ßV—ƒÆÔVÕÅÉBhGtÐýoÿÜé\Ž4ý—ÿßßj®ÂxøŽÿÉ€ØCæG»ÿÔŽ·G¶ç,“é>õ™IÓ_¨üþÞ‡Èö¸í±74¦ö¨'β'Ôúþç¿ýßÎ9úભo††k䋯T#¨&l–/içÎsJ?9Vî3.¹’5L jÇ&ý'hMIßOt3gùúʃü£jÂ+‡€ @€Þ»ð³®9 ‡)ŸwÂõSÿç§–ŸW¹öq˜òyo´ÐU£1µPep*€:“À¶mÛªkh©ê`ö¶xõf4¦äæ“?¸êñö~Ú€¦] úRå3IZÒ²d&ŸI¯vïêÖŸ&6ÉaÒšv¿dοs 1uN]r%€ œH†bò2åJò²Ñ˜¸Ú™€æ‰©kE“Ô‘¢¢þõ±Ø,2¿[Fëõ§6Ózm`òS2Tv;Ãhƹ£15ƒrmÇ@cª[A U $C1©UëŠó‚ @€@ç°¨æºYJZ–Ÿd]fÖ_fsþ´ .6ëD“Ædë­©n)J¦%)ä’4&»"Ks65®[©ßZ#‡ ©*½£.©£ª“‹ äŽ@j(&2¥ÜhL¹ûptÚ[O‹ú^4%Ì®ÍrÉ)&“uËè·½¤î?ÓœúdˆÉT× ÆT®†nŒÆÔP¼ì%°ûOÛžYw • k¾¦'ÔGV|Ö­Y»ctcÏÞ!@€ ¼pýb6ÉO=e2™¬ͺØìÇVjK“.ÑÒÏiA¿ºÉ.š)dõV>S½Ä·=SãØ²g4•SSqs0@€ 䛀³—Ü$?Ó˜~ɦJTRß™MþÓJ­±e ΔoxrõÒ’oIåd,Y&ýhþT‘±¤PLZ£­´õrå\Fg@cêŒzä* @؃ÆTñ&@câ3ÒÎ\4kÓ˜4OL=*¦+Y¤%‹­ë„ÑzõÉX.9ý¦û¥ÞÊGcª—Xã¶Gcj[ö ¦@cj*n@€ @€@û@cjߺãÌ!@(%@4¦JwŸ—v& KÉ…V’Òd1°õ[×d¿õ£mÜK¶F“M3kçKï›sGcêîiGEcjºàL Ð+hL½ÂÇ›!@€ @È4¦üÔ5W @èthL•j©Óï®@cÊf/w…ÆÔK€¼­B©Uj‚ó€ @€ @ Å  1µxqz€ ÔL©*4¦šo$6„ИZç@cjºàL Ð+hL½ÂÇ›!@€ l ̺eÏKc²Ý%{k[?š³óã5ír¶œgN  1å´â¹l@€@@cªT©hLxËsIh4¦F‘­¿hLõ3ãhIhL-Y-œ @€òJ€Îâ¼Ö¼®{T×^sß89Ǹôv €ÆÔµÄ9B€ P 4¦J”h™Ör±Mû8u¯=ch}gVhL™¡ìõŽÐ˜z@ 5 1µF=p€ @€@H€ÎâßhL9®üö¹t4¦ö©+΀ ÊИ*ñ¡eÊç§³  1eZ¿hL™âìÕÎИz…7C u 1µN]p&€ @€Sžï4¦<×~Û\;SÛT' @€@hL•¡1ñêlhL™Ö/S¦8{µ34¦^áãÍhhL­Sœ  @€ €Æ”ç{)ϵß6׎ÆÔ6UʼnB€ P…S%@hL|€:›S¦õ‹Æ”)Î^í ©Wøx3Z‡SëÔg@€  1åù@cÊsí·Íµ£1µMUq¢€ T!€ÆT  Î&€Æ”iý¢1eгW;Ccê>Þ Ö!°û?¶=³îÀu;F·Î)q&€ @€@~ ÐYœßºßƒÆ”ãÊoŸKGcjŸºâL!@¨L©Z¦|~:›S¦õ‹Æ”)Î^í ©Wøx3 @€ @)è,ÎñmÆ”ãÊoŸKGcjŸºâL!@¨L©Z¦|~:›S¦õ‹Æ”)Î^í ©Wøx3ú„ÀØåcUúäЀ @€@Mè,® Sgn„ÆÔ™õÚaW…ÆÔaÊå@€rL©RåÓ2ÍñG#—ŽÆ”i5£1eгW;Ccê>Þ >!Ðïþ~]Ý]}rh @€ @ &tׄ©37BcêÌzí°«Bcê° år @9&€ÆT©òi™æø£‘‹KGcÊ´šÑ˜2ÅÙ«¡1õ o†@ó ˜8`¯+öêÿX™LZ–Ò¤ßÃæ±h„ÌÞ·í­ß פ—´™~7ÿ$9" @€ wtçø@cÊqå·Ï¥£1µO]q¦€ T&€ÆT‰-S>?M)ÓúEcÊg¯v†ÆÔ+|¼Í'°nÇ:3“¤.ia×wiÙÅgêÞÕ­eûmçæNÍ?[Ž@€ ä”Å9­øà²Ñ˜r\ùíséhLíSWœ) @•  1UâCË”ÏOg@cÊ´~ј2ÅÙ«¡1õ o†@ó (êÒÀu\‰Js6ͱ°LúQ&gÒŠÃ$IEËúÝüó䈀 @€@® ÐYœ³êßúÑW¤1MYûsÇî¥9ƒÁå¶*Eí™=<*gÿõžÓÿÇâŸZÏ @hOhL•ê–i{ÞÕœu­Иj%Uv;©KúµòÒ[ç©CcúëGº5o}0µ×G`=!€ÆÔj¼}H@–’\%€S—\|&­Ô«òœd8ieSÑ‚El†@€@óÐYÜ<Ö-q¤é¯¥Î¾Ô²âíá-qŠœî|/~ P'£Ž:ª'Ÿ­¦¿çÃß½ýÕü›unÓÌ!@€ $ÐYœã›bèUNž21Ǹô6 0uÂמrœ(§@€ª@cªDˆ–iµû‡×Û›@s5¦9sæÔ9ÌÞ~›ÿ—ÿ»ýιÞ3>ÿüó[ÿ¶Ï—ÆtòÉ'¿}ÔÖ¿—í¿ß”Ý7ß>ê˜ãNÒÂf•w‹å­wwå•ß½éÊÛ¿{Ã+›Þþݦm»\Ù¸mׯî l(–^ßZ,ë·~´~KT^ÛòaP6e+o}¸6*¬}ëƒ5oËê7?ÊAyõQÙ´s•WVnܹrãûVV¨lˆÊò ïåu•÷–yeéú÷¬, ÊŽ%¯e±+ëvtËöWÖË¢µÛ­‰ÊÂ5Û®ywáê ¼ìÊ«ï.ˆÊ; ^}ç%•UQyqÕ;AYùÎ +ßvåùo»2ÅÛó—«lS™geYPæzeÎÒnWž[ÚýÜ’¨Ì^Ò={ÉÖÙ‹ƒ2«PfvmueF×–Ÿœr¡ÊŒW¶L·²((Ó‚²9( 7™°à³Ÿýlë’?þøcéV× ¿çËû°téÒÖ?a΀ @èptwx—½¼¡C‡þâôó¿ý½C¦NšW\w«ÐÍ©[ô积۵ÕÏ•óƒ @Õ 1U"DË´ÚýÃëíM ¹ÓèÑ£9þ'%¢EÁ²_¡²`ÉêO}úͲ(øérŦ·Ëk¾PQÁ¦Hó(’…Ó'VnJq' âDÑš(Q&|_bÝŽÅi²„3%G"Ô$œ#á gG85·#J½ˆ)Â%:DèB„"DwR„øþáÇ\<ôfYò|Âù×wà¶þmŸ;I¢’}Šbż¥›ouôq'•|´’ö’4¦RI2SªÀä9Lmð>o’™êv˜<©f‡)ú(¦8LÆ”î0ESø™,jL¥Ë.Ïa’ÏTª1Å?Ÿú Vq˜z©1Ur˜"É9LZð4¦-£1™ÃtçýãT}óº6|高L­ÿÝËB€ @ Ó ÐYÜé5œz}’BN?÷R5N_^Õ}àw1™ry´üEËaú÷ïºðÕnݨ§žs &SË×'@€@hLhL|HòK ùSÆ/~t˜‹©zt˜Bh˜ .LIh˜§ÂE„ÑB<"LmÓ«i!`œ;á‚¿”üRêKb¾”| £½¤†z© 1¥‡wIÄvIjL.¤‹‹çR!Â`.‘Æ:LhLmóÍ hL•ü0KnÙ|À›BÉ¢.•^ Õ¥êöRácV£Àä䲎Ãä9L…PLÑG±W“b2UÅ9L ÅFcêq(¦Y^(¦™¡„X9ÓÔvˆÆdÓÈÑãõ Xh¯í˜û &SÛ|)q¢€ @èXhL[µe/L:Èç^ªySÖ8]°b+&Sþî‚V¿bs˜­Þf½( C~êÙ˜L­^kœ @•  1¡1ñÉ/¦kL."L̲ýŠÝ/u½*©–ÜV iW<(Œ‡)LiU´)Ê9LQ2«”LV.Uà0Å܉rÙ«²ŤtUÉDUÉU)ù©ü¨.‰´T±œTÒ˜*S©ÃTÌFµp3јZñëBÓM·ÞeŠ’+ÅÒ;¿ûí­w鳬I“–‚¨K¥—„ÉÿŒU°—‚L…[d/²ÈU˜ÊaZí%’ó-BEE«’K®SZ:¹ª¡˜V–f”óÒÉéCf” "§•Í(W9Si:¹d(&§1•Ë(×ú“s˜ä¨9I*ès‹^'&S+~qN€ @È4¦üÔux¥ÃtÞ¥~ãTáÖ_Z±å[ÄdÊÙÐÊ—8Lß?ô•ÕÛœl'IöN9ûbb2µrÅqn€  1õü eÚsv¼³ô…Æ”FrEX^ 5&9~‰gµ* ¿´kCw"«UõDr®}ë•5oF%™K®r¦R&¬Tt˜üÔUÉPL^:¹H“péäütUÉŒr…b 2ÊÅB1Y4¦¤Æä2ÊI~@cjŶ4&‰JÉ JW|ìIîOÿCå–ËxKág,ñ1‹ÙK1iÝæ‹%ÒãŸ:}üü,rEI&“-E`J ˜.©QÑjÈ%×8L~ÞG}bo˜Ã´dkÉG·$ÜV—RјN:åÂ@cZ÷ž¶p³>Ʀ1ýã?~ö÷øÄ/þË_Záþv“}Õºy„úU²¿Ù‹^ÿâWX¼dI+œ*ç@€ äŽÅyªrs˜4£1Ù8}aÙ–o}çà)S¦ä‰×ÚŠä0}GÓšm1ÙN“zŸyÖÅ¿:´Ï›s‚ @Õ©!Z¦Õî^ooMט|•"¦+éÏ^ 4¦˜bQcP˜ra"›¢²JñÆ~‰®”ÄaÚð~Q`ÊÚaòÓUÕ’Nî/¼‹‹íâB1“S• ÅTÏE“§1¥„q åiLßüæ·bòC ~ öjÁsjÜ)Icºñ–»Rå$[©W|쉶}¢¼™ºn*6† ô€S%h´L{pKñ–6"ÐS¤R¤óIcúL¥ 0[?’Já—*öRÒ¦ð#0EYä>pEY©|"9_œpÖ„ó%gº–8L5:L¾‘y:¹PcÚòýâhLÉ0.ÃEÓ~û#&?|´ûO­v×çNcºaø]f#¥½*iC·%¿„a–Ò"-Ùgl}i¸bÈ¥Ô´q‰›ñÌBŸÕ~©ÆL=˜ü¤&¥©ÛÑ•R©¶DrÒ˜V%J÷¨…•ï¸hi)A˜z™K®¶8Lr˜ôéuS1“ç0•Ó˜Þûð}ûIö¦þl×@D³nâµAÕH,›ùòk_üÊ×k7™ÔµäzÙ’]c}xÕÖI×ÕÕ¥ŽÑÚOcï½÷¶ÎDëŠUï³Öø]õïŠ-!@€ úÐY\¯vݺà0¥4N-È5Nç-©ÃdR»O­¿ºˆhû¤õ¢ µ íG~Ì^{íUUޱ£KŠ2áIŽ;VV}c²ÅZ¡ùé6¶…Øõê´ý5=Rž;´.ÐÜ/;œ»ä ïõ; l3khë·ö pýÙãID¶7íD y :uÝå66‡iñÚ·Óf‚E²:5oÀ™ë2™Ü «2»s´ÒéhIt=»4Û­W–ë*ÑAS?J½9™r•[áXôÉô¬®y @ vhL•XÑ2­ýNbËv$ÐS9ÑB~ż…ÆŠ‘\±!é-•š¯I¨Hu*ª‡_ª-S\`*É^U)ì‹'0u¥É -ÚËê ÓÕ q˜êw˜¶Í)„bzni·‚¹¤Çs)Äa’Ã$ÿÁ4&ŠÉO'‡ÆÔºqEcºaøÈècóÿgï?Àæ¨Î}O”û²oéZYïè#­ ÕlF‡eí#­£‘5-˜;¥/½cCcú–Æììë¶ ggµÛ²ÞÑÊV7½ì8¶­ùÏݪJö­ôž¡¨ @€òD€Áâk;îú7tµî>Rs¢—íÑzgÛ¬k²Gè¬íVÛoHÖ1t¦‹93É);¡1ÇÙª§-›‘c‘ Miš”­µãÉs˜ª†Ež“l§'ÁÔK•5üM›L6Èàú•tCFÌ1 õ=ëZþÈItT$´YpÃÈÌèa"ª~­×™~dG‡{Ìí"½£— ¿øš5Ðz……ÒíË?6Ý–“i­ó-@€@3Иâ(qeÚLbìè¾ÆTÊS/ùËŒ¹+>½û5äŠoË©°²Æ/UZEÅ©¨L×3UÙ^z«¡½T–(B…g/µ&0ù¾D©‰$L=Uy“›HN ³–†s»ô$v©$a ŒˆR¦Æy˜*"„²1S‡‰IåRz¬Kcºê†!U6’9I•¢O¿ÿ£ãÝQTûpr‡V鸪i,Õ”–¢ÞÒ*eZreC¬KÍ&^ZW%FÂ{)&ýR“Sã Li¶§Gi­µI˜¦…¦ŠÀä;L:€KÓ9õ¦´ec ;Lëß\ê¿8¡n˜Øžvµ8Až0{Í>_j<»œdÙ«{‚ÓdІÆü1e23iÉÏÚ:nœW ö0ŸjpF‘¶5ó¨lU öXgtR9½zÖªá×Í—–l¼LÛLéé‰jA€ @ g,ÎY@«›ã9L±vH%“=c£‹Óióe24fÜøõ5&[ÙÆôr©›ÌÜÒWtµîl*·em'd5µp<9‡)š0¬V*¦ò“`6Šrâ)ç53»œ£}hÊ0*M‘=sU¯ï¹ŽêSŠŽŠ¸æÛf]–/n­=L¬·û}Ì2jGÇyü¾ˆöbÚ“ ®Z¤w\ª3{ß*:6mˌɴÐù  @ yhLq¬¸2m¾'±f t]cRF˜°ká)JÓç.ÿôgö¨¡+™_QKZj4‡U]u©†G¶—ÂEür530U LåYäü‰äšMÂäMQV#^Øê{n"¹°ÃTÏejõ\r.“K 1ýy˜ÈÆ”ÞC\Ó•7 ©Rüª?}*É¡ˆ¢¤¼J=©•zr,Uû€föK^r³*i©4U\t¶¸ÊñÖDÖ¥@]j`/‰—T^ªNƒVJš²—bÒ/Yx“ ëLîX ¹Ø L}˜|ë°·I˜œ(‡IÅå^Š.¤'SM‡I¹ïì„»¨ä0UçB/ ÀU4&ÍÓ÷Ô³M&SˆÜ“‡Æsý!6÷© L¦Ùx«]º¼è˜rhŒÕFÜløXiÁ^VŸ¨ÆdµÒûN·²¯ûcµî¡[Û‚[3½')j@€ Ü`°87¡Œ4$ä0)¢_OÔU•ŠÉ{ÆF§Sç½²ÿ7ãL¦¨Æ¤«?½ij‹)5¦%Ù5 åî5½F—“ör¤öì.WJ"çÆŸͬ gç„Ìëã®UmÁ%-6HþE¨þ´Ô5vaëŒ+[3ª1…jî;OV_F±Jú“aÑËVö­[ÍÇêjšÓ˜üKr“ºÜÆm§f,Ùµ(”ZêOÿð9[mý}Y(-¸n-F5¦¦ŸÓC±DnÆd iL>‡×ROYÛ£}ÏuTë.X®§ it³îq2—TL_&¡Îì`ún5#bSÚätî»–êLï;wÍ:mèØt‡c2-wf¾@hH)W¦ ;+dš@÷5&©¡ŒJž¢ôÌsÆTr*\)çX*Ï^Uˬf‹ëq*f°8§ p˜ÎºÐ†m²û*‡ÉÏ\ŠI‰™õÄ¡]œNž·!ÆdŠjLN¡°ÉÇ¥S¸9Úlž¸è“3Âo—„ºÔu¢]®Úå­ïåØýëÐølLþ%§¾e¹vLïˆÊ7¶åš!ª1ù«¹kj½i»Õ+I»]¶GëYScò[¡ªþþ;ÑlL¡©ßŽÉç잃2z¡—ðÍ:L/OPªR1I¶S/ÕHÔÏÝ 'SHcòƒèwcQ2[.Ú÷\Gu#'5GEÜ–Ýfµ ~âwŒÐabHM5sZ˜z…ŽvTc EÄ=rf™ÙwµM×Ál ¶¯è±i5ïc@sz6¥Y€ ¶@cŠCÉ•iÛ:J%®kL¦RÔ+Óæ,“Æu*šÍSÓ[*?H¢° D”Æ"¬wÌ­TÏ™<.’ù¥JœØéç|ñ•‰ø)ä|S¢¦#Q%0óSmUÑÀHPšL´xs|.›œ 1yÁ¦ ÌÊwËÙ˜j;LL*—ÊÃøã¥1]qݘ#gÐuÆT6þª¼¿@NòJµXí*Õ̱dž`é«%-y[Ô[Š?êÌô³.Å«K&»´Ç^ò¦ò‘?.$zóÇÕ;Jm¨È•g¼Iëf`ê½À4i^pôÊaJ¿ÆdÓíÎaòÎÅe‡©Æ0qí8Á;óÅÏ}q¿y Õ ec qöéÙ.Œ›¥óiÈ°Þ Îa*p—FQÊUg³¶'Á‡©*aXY¶³þ?;ùܘÙåšÔ˜ÌE3tѾW’?*âë¢ædü¾:LÜâÇÔ¥%³m†4&×O\D쳚ûŽš?tc—­:6m/ŒÉ´ÜŸù" @ hLq”¸2m¦±Nv $¡1…\ ߬˜ZÒ˜ªµŠ:)`jK5…Š·Ô;uimyÒª}¢¾½T#ýRiº*=úâJüru30U‰š“ŸØE¡VžJ 0ùSÝ$L%‡ÉÒ¸|÷°÷Ûb¦¢ÊI6&]»ºÿ˜°L'õž$Kÿ.iÐu·­tÖQdAŸõÃãj¬PšÎ•Pî²Z©Ìº’sŸ_±ñÌó.±rñï¯1=pÀï¯ùÖ÷Ó¿þfö!G[}¬Ö8\§µ*0ÙÑÛWéí­«tòå&7úvêM³Žºd¢Jÿ¡Ï]ýð›NÎN¬BÏ<Û À]ûØ Çþqê™·Ì~|Æz“³ޢͣ§¯®g2idÍ=u§fiÙž¥soú'Øu­×:.I¾[-´‚Ê}äÛEþm˜Ì^ö|¡Ü ~­B5±•Mir[Àaêd?eÛ€ @ˆ`°8w¦òãëÞÔÅé5¼à’_õð’+Zbs˹aIJ1³_у‰zêéž /þêºý®›q˨åþÅ鄹ëkšL6Iœ{HwÝç®%íÿ:4tݽêŒ^Hús½i}m!tý½¼ÕWLœò¯7CW¬Íßm¹ÞåªöbÉ¢¶VÉšWë1—íÖ]YG›æ¿#»+Ǿ븊é#›ÝÌÞq«9&º„·¼>!a&k¦7ƒTë˜Ã´põ¶‡©4ãáO¯˜¦'ƒ„奲so›ã²Yß7iÍI×ÍP¼’ŠIO‚iàXãN?­o2ù½1TÃPÓ¡ uÝz”üQ‘š} æ Œmͯ˜í×ßiÍžãïÂH¨ÆŒÆhÑ}Ùf“i²³ @ 5hLqܸ2m­Wñ­¬èºÆT[¥¨HSf/•ÆTv-*rEŒYÑL ˜ž|K¥”K~þ©r'~ö«ßŒ™2ß2¿ÜxûCßÔ;ýN—>á ŠQSæýñÚ¡q¢äN”r¾L|vÅ ¿<}Ÿ/î{àw½î¶áÁEbPv¥¶½ÌUåOTÕL¦‡ÆÍ9ôèã L•Ä.%©î,rSÖNÂ䦢’ÆtnF4&7á’Ž6]ÿÚ³4.ïoܤrZÉæ¹·ãTÔØD(_tVŽbÕSÓå×Þs¨èS{õV¨H5’*U%1«NeJhöÈØg>ÿ¥¯œqÞ%*ò–4’ò›ó.9úG'<<æý«eÔÁ¦Õ~sî%=É–Js‡íñÙ=÷ùâWÜQ§åG=­!˜Ò(Œ_v~ó»‡ú)—xbšÂê9ãj«K¦šºtÊY«Ô9®Qî¥Ú“Ç-ÝzçÓOúÍE»tÅO¿dóÇÝþФÝçËÙ°,0ið¨§xóÇùG¬æ«7…œe`òKë“ì¥ÇÎþøôO|ÜôPZ GŠ9LCïQNÔ_ÊÕ/I#¿£fmxbæúSnœõëf™Ã¤™ãN¾~æOâµbûu-=üâ N]{ë¨å‡ oTmNªæ¨gVí]?'S Uå+€ @€ª0Xœ¯!‡éÔ’ÃäF9tqzé°.Iðoï¯bsß>nå7ÎóÈÓkuq:aîkœ5æÖÑ+†OyI§w>¹Z×§îâô©9ë¾Z''S¾øÑš¾¸þÀ`žÊ9÷ÅoE“†°®Þꢔ<ðì1ÎaRGUÿ´éä4F¤åÛÆ¬|hÚÚÃL¸küê a˜÷$˜†P”¨ÿ„“âr2õ­m|€ ô•SA®LûÚ¿ø~º $¡1Ÿ“Ÿ 4&·Âòž¹ªª¦« ›•â"“VÕ˜*Îå¹üº¡²)ýŒÔ¥}¾èwkîÄ…—^-S ŠQ“çéÍÓΚ±j³+vÿÇ=ÏÿíUŒœ6ôþ1Ÿûâ¾×Ýö@ïì¥Û}æÅ÷<6eöòmVª¦[ZžBîÎG&ÿë翚B®*S›&S ²¢1)¡¯ËL¬Gt´,7I&’Ë\Wc’±d¹ ÝsZ.Ÿ³}?݇líÚÓ5ƒÝÔ‰Ñ}zäóß/§)só,VÏþæ¦] T=³0†­@‰Jf/¹4K:À¦>·Êt%YJúwô”ù:Ø”iéôsš*è¼%­ ÷Úïtó–tÔ õ´&Í^¡ÃOEY—4hxÁo¯²Ïe]Ò(I áÐûG˜8÷üK®:õì‹5^símœröÅúWË· ýØø¹¦.=9c™\Â_Ÿu±Š†Ÿœ¾Ì–}ê9e]š6oý­÷Žú핃O>sÀ#OÍQÑÂ9_iç-÷Œ:éÌ'1Àæw¼ùž'7çìWH]zpì ýäç§~ý[ßt÷:Do¼kä¯~s‘Šy6ò–μhP¿Ó/pù­ÿ²Ï—£ÙÒBé—B“?õ£Kž¦üiQ©ålLë׬}oøÀ¤•ŽiL=Sy¹àñA?1kCÐ%Ö¼>bæú#N°(K`R*&ý«x)FzŽpäÌõÁÌ}/lÕHñý“×X*¦À`‚Ì‘O¯Üû ug—ËâN!@€ `°8EÁèkUÌaêú¨\œ^z߯и„iLº8½âÁÅÇ_>U§?½V&*Oðe÷/Òƒ7zôðÂ;æªø§z iÜìuû}ã߯Œß×ZòýÆdƒ0õe&s˜¬ÚZî¨^vsõÒ@c*åa:~Ð4=&uÉá»þñ¥|`‘ 7_t×óÝ9·ì0y²]ð°ÜüM'üꜘÙårÌž¦A€ ~hLq1âÊ4ý=˜ö…@×5¦JÒ-&ÏzáSŸÙ#ìWx–R(ÿKO¦¥—kKþ¤UfSÔœ´Ê쥣~x‚˺¤wFM~^E‚„f¬’Daù_œ;qÄŽ—,a‰—T† }ü/NÓuâï¯rÍàÎ+MW%wÂÉÁý÷ÛwÕmÁ;g^,;bê¼u|ûcOoÒ’\ê³ûGLýÜöÕ±'iI ò–4[œVÖA¨CQ ò–d/飫?péU·évdŽ›¾L^}ËR—öþ¾:,å~æ÷Ôqxå-÷f=u|Þý蔽?¿ï%W ¾òæa{þËw=2yàÁ1©aJÙKZtÓ°³\¡•u”¼üÖŸüìÔ sÖêM}tûÓ$-Yî%M$wðQÇ}h¢&•¾¦_ª/0µ 1I`zëžÓ>:­"0uRc2‡iÈ}#‚ÞèIoêBGœxóË¥(Éaúõ 3/) ›úÈÓ/k¤XçP€³aâ±s^9àLuµ £•I`6§“ÚÈi˜LIØ/ @€òN€Áâ¼DXÓ)g^Xº8-?]c£º8=aдߕì%Ù!—Ü3_#€z–Fƒ}¦1•/N—§ Ð36·?¹Ê¥b²Ñ7]œŽ}öeL¦¼ô—δÃiLud¦Àaúî¡óWmµÁ:7Ò­a7g;ð¬1öè­†JÔK¥1•ÒÃÐzÌ:êáÆßõÔêK¶Ú•ž³TLÖK5ޤ”Þ˜L 0[… @ OИâðqeÚ§ÎÅ—SO ûÓŽ«éZ˜_1qf 1Õv-š0+|§"$-9›Â©–pWeÒì•2(Jù_ö>jšMg…yK§ž=PÅ&­*Ï·z‡ä‡a#¦Ú,Uþ\UzÿðwÞ%W^}ë'î}|ŠÔ% ºx<÷â+ûþqÒ$”êE¦„®"åHÈ^ÒÂ1'ž¦™ã$HóóSm 9ý«¢)ªäBSéJÓ³—*Óf]~Z.+º­”ž)äüÙ¨ÜrÑL.™Ð˜ÌDr“˜5ÎÆdkG5&ÉPMŤæHcºìêÁõd#½¯OøÁ±1+ÄøI5«Š šX¹èÒ«GO™§…‡F=-iI˜ýkGšcV,»Ri¹îRv•ÝÒR?ÑHñyCæhŒøÜÛæhÜMÿZ 5§1bM$¤­“ÃhL[ÅDÃÄW=¼Ä&Ñ À‰&SêÿB!@€ M g3n¡Z—¦ ¢§Ö0É&=`süåÒ˜æÙÅ©ÆtqªYºtqZzÆ&ÈÜïš¿¼fº³C‚äʲɮÓË&Óýw†/±CWÜüYLܧœÉ†bªe&9Lßüî!óVnñ;ª˜ìÉ@ŸØŒ‡6—\IcÚnÙ¬Íaêwí •žéäBO‚•ziÙd:÷z) PP¯-ÉÅo;€rH )‡Ýš&5I ëS¼J1aÆiLÍd~‰šÁEÜÚ²Pš®Ê©.óKE¨Ø9kÉ+ò%.»fHH]2‰¢t (éâ ñR)ë’“–Lc*=ßb%P&T,Õ‹ŠÔ¥s^yïcST´¬l/Jõb×Jï"AB šŸê®G¦hÐCj~*Í'A²ºØ¿*ÃÇÌ6AÂÍL˜ü¬.5&6ª)[“ÊÕÔ˜”¢ÉMW7SMI_Ë®ÃdÓ®\Ï7Òûúôˆï³‚—©L’•ðáTû¸ªˆJ~v%›ÎS—vjÙš©˜Æäþ Rœ•4&SOøåé*š¦ñþ‘Se,Ùd*NWÒ›ÁqX9öî{<Иt*åR0OÜÊíò–ôŽ%@Ó±g“ŽCÁ1{ÉiJ¶dE&Ó]¥ÜK–MÉ( ².Ic*%^òËY rsÆéàÜÿ[Ë^’´¤iãtˆZÊ%Wθp4¦ò±ºpó×¾y°;VÛk/9™IÒ©„Ü&ÿÏacæ~ïŸ?ùá™ÿ{ñ2쬭Ë7î·Ûñ'žÒ#™z³ ꤬‘âÇg¬s£oz3û•`˜xÅö²ÆT&~`òKœ9F“—±¿’Š©2§ÆÞ6|Òûç½ßÿÛMþ ² @€ ÆИ3JûÓ§OÿÒ¾_«z²’@Zƒº8•Àd6J ‘Ã4ðžyæ0iœÁ4&ç0雲ÃÉì®Áõ˜ÍßÿÃg¶üâÿÓÍ pö• ¿öì¥ê˜·.ßÿSŸÞcÖ¢õ=Cvn¥ü `0ȦÁç0©—êOßaR¦‡)4\%“ë¨{a¿qGüÇlpkëhM†ooMû7õƒ I ©ŸF—t_cŠU)ÆKcúôu¥ºfEÙRr•4K.ù‹“–,É®+Ê·$wâ× ±©âL]²¹ªL¢0}BsU©„².I“PÎS—Ì[ÒtUÍÐ-k¯ô ¿h–ª[î%ABÉ)÷’ Kò"uIš„þô‰ácç|fÿâr/‚Dlú¥¸ùãJ“,ùÉ\bÄ}”‰lLvô†²1ICr“>í…ÆäÛO=1HcúýU·ú9ÇBËúTS½jB‘ÃÉŸ.rhy•¾ùÝCg-~EG×ÌůXj%QOLz^ 67œéJ:Òªó›•Sœé+nŽF]æ êÀ³É%-ÉRÒr0"óC$-9sÐIK.å’Þ  -/‡Ê´$iI™–,—B‰„¦1é°ÔÑXÊî³M"¡ŠR¢Ù„qvXê©J¹„¦+}ý[kª8;,å0iæ8½ÙO¹—Jçþß ŽÒ¡Æt¡’éÏ?ÞpŸyKr˜ž|ö%iLãf½${é¾R6¦ÙK½Ò˜>½û½ËÆÔŽ'#OüÙOÕ{ºœ7ôväÀ Ò˜lôMä5ô6úÙ ¦£iŒøðl˜øñéë5L|ÿä5áéäªàäií»ß×gÌ]±vÓ;˜L=³Qm@€ ¤‘S£Òë:)ӯϸ 'g{%´Æ7tqZžå|u0,(‡iàÝóìâTC Ò˜œºÖò0Y’`=ÔNÎ]ž[6¦{† ]ûÜôwWÌ(hžvŒ'ä]ÃlLz–oùæÈºåÑm ¡hðÄ¥²Ö µþôæ’›põ£/X&—Í:”0Ìec:ã7g©—¾±¤:37±ƒrO`؉ÁmÂ×7ôú§”/@è<4¦8Æ\™v¾²‡$ $¡1ŸOM_,©öp½Ð*vúsUùÞ’=Ie9_FN|^fÅý·´ÃЉó/¹Êt%›¥ÊŠô K¹Tv'Vl—2qø÷+bh¸W~ãÛ‡H“Ðlq,±|›t¥+o¹ß&§’,1åùuÒ'®¼ù~?Ï‹2¼(ý’å^šøÜËv])5BÿJc?g­nÓ?0z¶æ§ ®4‡'óí¥à Ô›“Êe`j˜~)d5eTc’äIáüC©YIOàí¶Ûnú¾½|*É#³—û4¦+ouù¢ úôðïë'Lª¥"•'}ó>*KV<0tPÙŸJ¡¤#êÔsêß?\=DÇØu· Þ9;xGËîHsùÍüIå-¹?o6ZAQš¥glС¨#SE+<9c™9-wâiîØsÒ’æ‰Sѱ'oI“‡NZÒ1&“Iù–tdÊ[:録u4îýù/k*G›3îÁ±slÂ8Ë„VN‰V:&U,1š~ü³SuLêàTâ%•ÒÁhL²—†>8Qº’¼%›9î—§]ø£Ÿž¢ÙK]v‹~qÚ…_;ð @cZ$™¤JSÚùAñR Å‹‡õ>m&“4&)>*µe&]¢wæ¥îzé•·–g¬¸¥:5k¤ø•‹Ëå¤ëgX”LJ¦“ sÙ”Î}ØEã-•‡¦½¬sŸHºŒýbâ;LÖFL¦Î“­B€ @ x,ÎKÌe2ü› ܳ6¸a§ÊÀäÔ9Lß=Ï.NUtq:|ÊKzöéÂ;æ§Ê§¿»g³CÜE}Ùazp”]™ª¼û> ƒóÒÚÒŽë¬J£ÓËœûü k^9e%nÙfEq½ÔžS‘·Tžñ°4„¢?m.€‹î|^y¬Õ?­\zß [éY;PãQóƒ(ÿY¸3Îàzéo¿ß–Ʊ@ Æ]ŠÆ”HQK’S\ع2-äAQ Fw]còUЍkñä3ÆëW4«U¸Ì/&-Y±LKVt (BŽ„•Ç'Ì}jær-ÈX:üÇ[Úó–,É‹¥\rîDpaøíCT”ÒEj„¬‰`θeÛl¶8•‡Ÿœ#ƒBÓÆóóÓdJèþû¡G§"_BY]´šR.ɈqÓ]O\|ù­&HrÔ±*$è}¾,GBv„œ»Òt¥æäqµ¤ˆ^YÔ˜ ¤ÌLÎD¦¦~ÔðÍò±ä9€þAåZ;GLœûû«‡è_—WiüÌåzGG—o,M_¸AÅY\Qr3;ÞL|tüs¤<õX*ã¦/³âìñ2›¯qê¼u*îðs ´t¦¤%Íà8Y%Pa–n4÷e91*R—nºû S—‚yÇαÇÔîxx’-È(4©pÄ”%7Ü9R3Ç™ºôÔì—žzö%;8å-Ùñ©å[Ò!úؤ%×Ý1rÈð N0¼÷‰Y·=0AÂÍ=O̲$i~ž´¶ØK½ÍÆä†¨LfzoøŸþ‰òZÇ4&\Öc}±T}fììW}æåGžVY;qÞköœ«¾©Œ˜±Þ’c)Ó°Ékî›´æÞ‰/Þ;áE&HVܯ¨Ã„É”­µ… @€@ª 0Xœêðô®r2™NúÍùÑ‹S]~–Õ•Û§—r0[‚çòÅéÒàâô±gÖéúT§÷éâtâ‹O=÷Zȉ:L˜L½ OÖvSD`r­7“iÎÒMn°Û†¶m¨M£(ÁHš{ ¬<ãá¶Çg¬`òK*Á(ʤ5æ¾Öã0Ug³Öƒp¾Ãd½“©½6B L‰®¤˜S\p¸2Mq×¥jm Ð}éècL®¨éNŒ{zñ?|z÷†ZEyx¡ŽVá»JΦ°g¨ü¢«T”ðÅŠ“–47œ” gPhaÚüõ*vK݉NŸP¦%MQe÷ÙUîztŠæ§²”K£Ÿ~A³TÓÆ•d ó%,ý’oJhr*™ʺtùÃôoi¢¤ ÷Òý£žUn_蜽ää‡ iL’ìzä›H“ôf© Oš6!)äwWÞZåÙáQ)úTST?Šy§t õxNôªèq:Ì|Q©²Üã*ù“2F=Á²·T:êBž~6€*Á q¥Iâì ´"yP%˜*®r(:iÉÜ ŽnA9áÝTŽ•c²'%ZÈ+¬NŒ¦'Ûªr£õ†‘)Û«.ù™™z•©êy;̓þØÙÌT_czw疫ʇŸüíÝ]*Mê´¿½â–r¿*­‡Ø<¾ÃT h;‹”¥ë¯5{oáC d‡SvbEM!P@hLqAçÊ´€‡D¡šÜu)P)œ\áåI2›bì´@cªgVÔÕ*VWpVB…û³Ú¦¨ö(*i–Bɖ̈ê ­‰@–¨øU²DéâÑ/54‰EÁÌq~â¥ffŽ«JéÒ·Ù¨2¤1Å©…Ó˜zŒJÂ1_<Ò§:öB’;lü…z‡PôýZŠR9ƒ™ŸWɬ”hqÙ•ëJ•|<µ¥¥ÀXª’–ÊG '-)Ù’ŸoiFõqhÇdï¼¥RîêÒŒºÔ¶9ãÎ4׺Æd–d&•Z/ N=zô^3/ë'™)ôùäþG÷jŒ50™ÝÒ3ôV{ôm›Ok9LáDèñ&S¡þ{Cc!@€ Ð) wŠlbÛ•Éô«ÓÏ÷’FW«!¥A yð/N[v˜B&“.¥UæÞÔ?Ô~]}í·bPØqw4 »d2¦êÓ•;ž÷æt«ã$…µ$7é[9‘REÉŸ|±GWªˆµS+ÕO°Tˆ‰äX²ÇË¢ÒR(ÓR]i©Wù–d6ò–Bgç&Œkè0i…¾jLõû›Æ§¢£«¶º†´z{üü丟^2èæ‡´2Q`Ïè[ø B—‡)ü¨k3“ãÞy÷o½­$ëC€ @è!À`q{Ãù ìwZÿPz`7ËyOz›I‚{—‡É9";Þz?þR:æê; M Œ7þ€o=øÈŸÄ¬Ð“ŽÌ²%¹²ÔÒ&ÕÐ’êÊIì«V”â,¥:GZYa±L<‘ìJÞ×3+\m]©Nš¥&3-…“-%:O\3°[§C“ŸÒh©¤l ˳ô¯>Õ“y*zSUrµÇFõ¯Šȳ,Mõ^2™.ºì&Ën“KÂäžs †‰½'q˜2y¢Ò€ @È4‹3¾&*/“éÄSÎë¹8õ2—/N#Ø´æ0¹ j=ä¦âÒ…³iö ùº ÖŸ2Hlºv»Ê¶ì8M4ˆUrH@&Óþß×?£cA¦Ü™·dR=̦÷-͘þµtM¼ ô@cJol¨ ð1S\'àÊ”C$ß’Иb\‹Ç'ΗÆÔدˆ8á©ßBBEå¹'B¥/©^J·×«JÝdKiõ–BþS&xiLJc#éÓƒŽøIƒã¤¦‡ä¿¹dKÍe5«˜yß"ó/ÚDŒ›ƒRšˆ±®¨T;µRYs©™`©JWòÂì¦Yj2'S‡4& ›Úv6&¥"IÿêÉQ³—ô²ø*–{É$µ¤÷Í]2™.øýžÀŒ»Ñ·I•ù5q˜šÉ:€ @€@û 0XÜ~¦iÜ¢L¦Ÿýú¼ª‹ÓZØôÅaò/¥m¶8{þGæ‡þ”¨ä_SG/ºíòœW‘ ÈdúÚ7š8w½ž =æ§²î‹ÃdМ¤ÐXÞqŠ’MçÔ9íO×o‹&Ú´@cJ{„¨ M).ü\™úà(@ã»®1Å«N4¦f]‹%µç}kRTªž–ªñÌTQc©lMÔœ!.&ÃKå.|“6B—WCcÊäa/I9lêéDz_ŸêØ‹Y!æ£ò´nõçwsZR%‰ŽiI®TùI ,¥’¨ÉiæTÁMõ\¥FºRNr,5:èÆÔÃC&Óù—Þ<äZkŒXp˜ºö@€ Ô À`qaº…L¦Ÿž|®qRCúâ0†" í,Àd:ð ñÏ­·<ÖÑÇÀúè0u¶ölH4¦4D:@u 1¡1qp—@SŒ/ñÈøyÒ˜šq-ÊfEdÒ7_¨ˆW)ì1•%’`©<£QkÓR¥[ZŠJhL™<HcR›Näÿ©O¥1ŬP'CRHHªäLòÒ&¹üIq)”Ü‘VûèòšÅ‰J1®R%»Rát¥zbS¦5&„2™ú_zC0ñŸ—¨ß‹Ã”É“•† @€@n 1å&”M4$0™N:×]œº Áº8Åaj‚«tƒ€L¦¯xÐSsÖ¹Ôãþ`QËsÉu£êìH4¦4D:@hL-ô®L[€ÆW2D )F¥xø©@cŠ®P-$5ÈóÒØ¦¨«RÔ5(‚ñ Wæ7ÖójM 1eèðí©ªiL¾QZÖ§ÿvøk®PWè«'úùïÇeN M¸X9ºjù€ö¸XØRªž®ö!7£ÆýaÄæóå{ͬkLêÜ2™ÎûÝ ¡àâ0eò E¥!@€ ' ç)šM´E&Ó '3i~ð\+8LMc•îL¦o4nöË¡Á.¦îÅ€=A »И²;j S\¹2-À!Pè&v]cª§R˜_ñГÏKcjì!õ.‘RUª—`’¢:E•«3+\IœÈ«Æ”É‚4&MÂeÓ±ùÅM…¨O¿wøkÍŒ’šù3’z¦TŒÕ’êúIu¥êtJ:Ø•Z:Ýä@c2“éÜßÞàζ8L™<=Qi@€ 䌃Å9 h͑ɤ«l¦&P±Jbd2í÷“`ç:*SbÁ`ÇÈ4¦lÅ‹ÚB `ИИ Öåi®G )F¥xpÜóÿ©Ý{éZôB¨¨'*yy^ÂsRåØXªib¡1eò!I3p•½Z^‘>ýÞa?vRQË áC¨Vš2KVæÊ¤`R0+%')TÈ¥Ô’¥ÔУ̇Æä›L8L™<7Qi@€ äSþbÚD‹œÉD¦&h±J2|“ ‡)™°Wd‘S£F!PhLhL…éì44B ë“2ÂÄÃÇÍýûؽyÅ¢®SQíQÔµ”Èó1(И2yšÆô“O¿ööõÊO~~ú—ö;ðÚ¡#z[®:"R¿fhãrõÐÇ) øÎ¡?R‰©ÀE—ßöéÝ÷X»é¿¼ñöû)<”“é§]´ï~_Ÿ1wE¨Â¡?ßy÷o)¬?U‚ @€rE)WáìEcd2ýøç§+áÍ=ŽŠ¿8Ýöæ{½Ø.«B }ÌdRG=ãÜñ½tÓο|øÑGíÛ3[‚2K)³¡£â(4¦¸(seZ„c ÈmìºÆ¨!×Â3+.¾|ÈÿñŸþsŒhQË©eQשHÐ"Èè® ýì´˜ÊÿúœK¥¤_Ø­PÇõСC¬~)H~ùçÙç¿ìù‡ÞäÏø§ÿç¿«Ä7ðØŸö˄Ƥcù¤ßœˆÃT¨s… @€@z 0XœÞØt¼fGœòÜò¦Žƒf} ð»;÷;âä=q˜ú€¯B `И pš l@cBcÊV¥¶í$Ð]iîܹ!×b¿¯àßgÿû~íSŸÞ=ÇjAú›&×eï}¾_Ï¿¿ ©‡a'¶?ZÁ§¨I Ù˜t€Œ\µÏÂWÆÆDuƒ @€Ú@€Áâ6@ÌÀ&výuW|-}“ ‡)-d}“ ‡©]€FC  hLM@b@ )hLhLIõ=ö›<4¦vH<½Uò·~ ]4&4&ôš@ 5&—ŠÉ%dr&S Ï;Éÿ¨S@€ @ ÓИ:M8Ûï?¥ÿð¥ÃVÄL&¦† X¡Cö¿wÿ-»¶ÄoÜL&¦…€ÍB ИòEÚÜ@cŠ -W¦¹íø4¬D ©R¨]cRH4šS6ï|wçŸÞ‹_‡OóD`Sÿo¤ê·ÑOÅä'dR%ÿò~ºªš*nT€ @è ‹;7›^óúÙ!c_«Ú,ܲÐþUr&—ŸI+XEeÌ~eû3µ§…! n¹×-{Y÷Ó¿êú×ïnyÙ–l^ØPx* 9 T@c¢G@)&€Æ®LSÜu©Z$­1éNt¼' ÑbëïæÉ%È\[¤»4¬ó‡}Ô†ÞØÖM]cj+L6d„R1ù ™’©{… @€ À`qÞûÀàùƒe‡ š5H •Ϥ¢äL~~&}ª”®Ii5ç<å íKõIõ=u×é¦ýèÑ*ÖMW’ä¤e-ôÛOÅÿ(]Í 6€@âИ€ê@cŠë\™rìä›@ÒS¾éÒº  1%Ÿ]C  ¢©˜B ™Ú°6@€ @ ·,î-±¬­ïüÙ!&‚襗öÆÞÔ¿–ŸIÖˆ ’¬µ’úfž€Ì$“íä3IT²ö˜c§—ô&}j†“½#ñÎÖç@ ŠH14¦¸àpešâ®KÕÚ@© ÙD  1¥1*Ô Í¨™Š‰„LÍdM@€ @ #,îÖmÔÙ!Z b5óíË̤w,Ž•5€ªƒ€D:›ôÐ9vÎÀÓ›ê“r˜¤7éS뢖<¬lh% ÐhL½¡Åº€@—  1ÅçÊ´ËÝ‘Ýu™S—³»n@cêiöøàÃ÷6¿3ÝÊÚ7‘½4}ÃÏÝ;o½·ºûd“€ @€š À`q2½Šùj‚ÓDBvˆ&éM’™¬™c_k‰šxA ›œZ眧jèM˦þiµrN^7+ɾ @cÊ@¨"ŠK).ö\™÷È(FËјŠç¶©€A§Éù$ðÎ_7HcÒÿVóÙí’/C¹$€Æ”˰Ò(ä…S\$¹2ÍK?§µ  1Ñ3rJ)§¥YÅ#€ÆT¼˜Ób@€ ¤˜ƒÅ)N[ª&9ÉæÞ2™É^˜ô¦™LöŽ26Yò¦¶`g#½% ®¨²ë¯»,y˜½\ŸtUÝØŸ±·{a}@ ÿИòcZ @cŠ W¦îÚT½ hLM@b•,@cÊbÔ¨3j@c¢[@€ @)"À`qŠ‚AU @è4¦¾ñãÛ€@G  1ÅáåÊ´£'N)ñPÎ@cê W¶ ®@cê:rv@€ Ô'À`1½€ Ü@cÊM(iòH).ª\™æ±ÏÓ¦hLô†œ@cÊi`iVñ 1/æ´€ @)&À`qŠƒCÕ @è4¦Þñbm@ «ИâpseÚÕÎÈκN©ëÈÙaw 1u‡3{@Ç  1u1;€ @€š'À`qó¬r·æ“k|aÛU¹k Êç6ž=mý1¹j:J©£xÙ8 Ð7hLqü¸2í[ïâÛi'€Æ”öQ¿  1µޝA mИÒê@€ B`°¸Àá¿cán3^9±ÀhzH¶{xùg3PQª¤„SJA5 ZИâúW¦5ù&€Æ”ïø¸uhL>MÏ4¦|Å“Ö@€ @ ã,ÎxûR}4¦¾Ðã»Ý!€ÆÔÎìù!€Æ”ŸXÒäS\P¹2Ía—§I4&ºCN  1å4°4«xИŠsZ @€ `°8ÅÁétÕИ:M˜í÷Sß²‹S±âMk!1hLqãÊ4cÝ™êö’S/±zV 1e%RÔ l~gºFŠWî )@€ @É`°8ù$V4¦Äг㦠 15Š!4&: bhLqÁáÊ4Å]—ªµS ²‰4@cJcT¨Z `Ó‹¯ß×Âwù  @€ 6`°¸Í@³´94¦,E«¨uEc*jäi7Z%€ÆÔ*9¾tSd®L»ÐÙE‚И„Ï®;I©“tÙ6ºHàýÞ’Éôîß¶vqŸì € @€@ ¸k 18ø™i:SfBEE!hL) Õ€j@cŠë\™rÔä›S¾ã[àÖ¡18ø4€ @€ Ð! wl6‹Æ”…(½ŽhLEï´½%€ÆÔ[b¬t‘Sl®L»ØÙUИ€Î.»A©”ÙÚK`ÿ{÷ß²kK{·ÉÖ @€ ´“ƒÅí¤™±m¡1e,`…¬.S!ÃN£!ÐhL}€ÇW!N@cŠ#Ì•i§ûÛO–S²üÙ{Ç 1u -†@g,ܲp¯[öZóúm^ÿÊgÒ¿ö§½Ü²´2ÂSgâÀV!@€ X ¸ƒ 18ø™i:SfBEE!hL) Õ€j@cŠë\™rÔä›S¾ã[àÖ¡18ø4=›úOé¯lLƒçž¾aúÑ­2hÖ —ŸIÞ’–Õ²~cû©øe³¹Ô€ @È&‹³·¶Ô©-ÙHG  1u/‡@  1å0¨4 ù!€ÆK®LóÓÓiI-hLô‹œ@cÊi`iV~ ÈLRQûä3IT²†*?“-HoÒ§f8Ù;×·õyA€ @è‹»Ç:u{BcJ]H¨P„è4¦Þñbm@ «ИâpseÚÕÎÈκN©ëÈÙaw 1u‡3{@Û(Ù’R.isZ°ùã\&-Ë^’Ã$½IŸZ®&- 1µ>‚ @€š$À`q“ ò¸S£š‡6-Ùz¥ì%+ÖüÝ=‹?áþœ¶þ˜<´6@í%0羯?°\.þìÇ¿Þí㫾ÒóÎÛ[Û»7¶@ ehLqè¸2m¹cñÅL@cÊD˜¨dï  1õž߀@¢\â%·àò3©^zsË®-²—ƾ8Öª©üL‰Ö—C€ @…$À`q!ÃnFc*pðSÝô×ß]¢ÎY³,Ûvcª«Nå DHT:ýëî`´ 9*‘±S@5  1Åu ®L9lòM)ßñ-pëИ |šžM•”~Iy˜”fÉZ IÌéM-Ø›šHÎ’6¹w²ÙVj @€ d–ƒÅ™ ]ß+ŽÆÔw†l¡C&¿|TTc¾ô“|ø^‡öÈf!lxììÚÓkK²Ý.jä‹S\<¹2ÍWo§5ahLô‰œ@cÊi`iV~ (»’Ê®¿îÒäq®•–Iy˜\î%™Lz‡TLùí´ € @é&À`qºãÓÑÚ¡1u/ï š ™HÅÔ¤|9'P3!©˜rušì@cŠ‹W¦ÙëÑÔ¸7ИzC‹u3D)CÁ¢ª€ @€ Œ`°8#êD5ј:A•m¶‹@(!©˜Ú–í@ ·¢ ™HÅ”Û`Ó0d•S\ä¸2Íj¿¦ÞÍ@cjŽkeŽSæBF…!@€ @©'À`qêCÔ¹ ¢1uŽ-[î;PB&R1õ)[€@Î „2‘Š)çñ¦yÈ$4¦¸°qešÉNM¥›&€ÆÔ4*VÌ4¦lÅ‹ÚB€ @€²@€Áâ,D©CuDcêX6Û..!©˜Ú…”í@ çü„L¤bÊy°i2I).l\™f²SSé¦  15гE)[ñ¢¶¨K`ó;Ó5Rüâë÷Á€ @€@ò,N>‰Õ)1ôì¸9.!©˜šÆZ(<—‰TL…ï €@:  1ÅÅ…+ÓtöZjÕ.hLí"ÉvRF)e¡:h•S«äø @€ Ð wjV6‰Æ”•H¹žJÈD*¦"wÚ^°„L¤bê58¾tƒSe®L»ÑÙGrИ’cÏž;J XÓ† .} 8ð¼ó΋_‡OsFଳΊoÑ7ÞØÑƒ°]—ÆtÅ8²1µ 'Û @€úF€Áâ¾ñËô·Ñ˜2¾‚T~óóžYvYAK3ÛH`ëÖ­mܛʷ·n½î¨,U˜ºBE"€Æm®L‹t,±­hLEŒz!Ú\,éÄO<èÃÏ»` +ç^0°§œ?ðß>üŸÿeïsÏ¿ØÊ9ÑÒÿâsú_|vrVÿgW£œyÞ€r9wÀ™^9ãÜ^¹èŒsÊå7ç\T³œ~öEÑrÚÙ–ËYžæ•SϺ0\μðÔ3/<¥§\pÊ™=å×g\P³œ|ÆAù_Î?ù7çŸ*§ŸÒéçÿªNéwÚù¥Ò?T~yZÿ œ.¿8µU9¥ÿ/N9OåÄZåç¿>¯fùÙ¯Ï ÊÉç†ÊOO>ו£ýÕÿ÷û?=é\•ÂåœN:ç„_ó÷ÿð™éÓ§§ÿ|0æÉ‡?»ç^ý/î—þªRC@€ @ ÿ,Ό붩ÀÁÏFÓß{ï½£Ž:ê_÷ù’žxÌF©e:èIH ¾-Y²$Õ¡]%@ô»Š›A½$€ÆŒ+Ó^v'VÏ4¦ŒŒê6K pÓ·Þ±ùõ¿egP6å]Wn¸õŽsÂÆïºòÚŽwƒ²]åÏ*¯zå•möˆ­»\Y¿uWP¶e]¹¼³nó;/{eí¦w\yiÓÛAÙ”5®¼öö‹åò§_ûÓêW{ʪWÿ´ê+o­teÃ[+¼²|ý[Ë׿ie™ÊºrYºîÍ ¼¬òÆ ^Y²ö +‹ƒòúâ—‚²È•5¯/ì);¼ØS濸sþêr™·zGPVåy¯Ì]¹£T¶«<§²¢\æ¬Ø”åA™½|›•g—õ”Y˶ÍZª²Ue¦+/lá•éK¶¸òÌ’-Ï,.—§oyzñæ§eš+ 7Oí)›†›û÷ÿ°û”›&»2Ó¤rÙ8iþƉó6îý…ýÒ¯1Mœ8ñ[ß=dÞŠ-rÑtQÝì €õ @€ tˆƒÅ›…Í¢1e!JÅ­£9L·ÝûøøK¾¸ï×0™ŠÛzÙr ¸é‰ÐY‹Öi߯a2õ^æW'ú™! €@Þ  1ÅE˜+Ó¼÷ÿ¢·©è= ·í/œÆ$Qɤ¥*ž®dË7ÜhL1êR 1…ì¥mî­À$™És˜z¦ZS 0µßa 4¦ÚSIc*;L=Óš×yÓÂÃTјæ­Þé4¦^8L%É9L5¦¶Îô5¦%[«4¦ŠÃ$™©¦Æä9L›§,ŒhLó7Mö¦Ió²¡1•¦Cç­Ü„ï¥×•: “)·çl@€ ¬`°8+‘ê@=ј:•M¶‡€9LCî¡Gû4ŠòäôÅ_ü2&S{Øæ{+%‹åBë63®S·ÁdÊwÄýÖýâÄš–B »ИИ²Û{©y_  1õ• ßO)ÂiL×ßrGÙR²4KåLKådK×ß|»4&?åRÔ[² L¾º¤åZé—”‡)’©J`zÇe`êE¦J&? ÓÊ^åajà0LU*¦Ã´¦q*¦ZSŠ)ÈÃTIÅTÎÃÔG‡é…j‡)œŠiK|*&%a gcªÖ˜”Š)ýÙ˜‡é{‡Î_µÕFR;åÍÒ”˜L)=éR-@€ „SA]«™hL~ª›nÓÐûF(I¹FQ”\iÈÇ=ƒÉ”ꨥ¡rd;õÌ •ÞÞßÔm¦/ÀdJCdºQ‡ úgýn f€@_ 1¡1õ¥ÿðÝl@cÊvü¨}]…Ó˜®»ùö°¥äæ‰Ûög}úßœš-.–"ÞRH]ªš<.b/U§_*ÙK•)䚘4£\+ÉUæ’+O$˜ìÚÛ›N®y˜4¯\ãéäÊsÉ5;ÜìvN'q˜ùÓÉ©˜œÆTžQ®V*¦”kLæ0-XµÕI‘Ƥèœt:&§~@€ @ 9hLɱO|ÏhL‰‡€ D 8‡iYi|Ìž+eß9öéÅ_ '¦³XªºMð áÎg濬nCN¦|w/úo–&1$6 ½*údäÊwèi2G )s– ·SÛP²¡t(¢Æµ”Ê –¶ýùÚ@c:>”i©ÇXRÖ¥-=eÝå[²d]R‘®äoæ¸`¹&í¥SÈU20­zå-? Ó / Óò o-_¯ò¦Ê2+ëÊ¥žÃT-0E’0•‡r‚ ³R‰$ajv.¹fó0ùӳ˶ÍRYª²Ue¦•ðtr[jN'WšK®)‡©Jc 9Lóƒ¸ÒÄp×ÜhL¾«dËž±T’–jå[ R.Uϧ.m|{Íko¿X.’ºk/ý©Sȵ 0­m”„©áDr«wÌ[µ£Ö\rÛËsÉ­Øþ\©´8—\Éašá•*):—ÜâÍ¡éä¦.ìIÅdy˜¬<0nîßÿÃîA6¦ù›&•ËÆIžÃdÙ˜1Þ—ÒÔ…?!T¦mõFRæ­"Òï´þ-˜LG}ô^{íÕ|uŨ¯hýzßÚÿýCWÝÑwÜh—>êß¿¿6hÛä@€ d’ƒÅ™ [{*ÆÔŽl¥MœÃ<û¤bê™QÎZëI0kš²è ÿ㫽2™Ü0ˆ†2ôš>}º«²½ãþTzõ½AÚ¦vêß¶íÈßÅØ±ckšÍTFmѰLTF‰o‚ ­¦ >¼æwUÿ~¥—Z}Ø«-˜ÅRî6ÞŒr=ÝfõŽ©óÖªÛôÖdR-pöRóU±zñНsÃ<n…@+Û¾ì¥xí¶ÛnÚ¯{§áÖšh›õw¤î¤wj91}#Z™nö–E߈ZŸ÷O Z%ÿHÑiȈªjì€O}EËÍæÑutÆpS V™f6ÕLLj_Çê]§Þ™Su³1äƾׄ-@ £ИâÇ•iF»5Õn’S“ X-k §1]sãíÕNR•¢¤Oð“ã¨T3Ç’Ë·•–ÖÚlqÞ„qUsÆ5R—Ê3ÇÕɽ´Ò˽¤–§•[È'Ì9€ @H‹S†d*Æ” wö!`Ó÷, ©õ¤bÒ™FÃüœ:%)H">bò‚æM&7H¢*¡{í÷ÐЊÙð3â¸1KªdÚ˜‰ ƒX~7¨â7KoZ{Sb‡­¬e{ß½¸¬*ZpY%U™Ð¸M4‹’ÖÑ·¢AhÇš©mÊSÑún;n5UÏÆ‘lDÈjr5¬-Ú‚Ó³ïËÅrvà0…R1i(µÜmzì· ýüäçzg2EžšñrÃhÁšè\'@äÍ1´¾g©˜ÜíSS^ô©“ÉÜ ‹ ¹eú3´}û®þ…”,÷‘{BÒ*o«…ý:‡z—*:4\£:Ú[b¢_<ætîco£oÌëÒ²?ò)Ô~ú%}d«Y«C[ÇßÎZÁ dúbÍsŽmÊÎö ¹ƒ–Íq¶êÙ¦¬Úþ€°>r'+;ÒݩƣܦBY‡7Î8Xý•̵ËÎ]Ö |¶/÷2›3ñ“€@âИâBÀ•iâ” t”SGñ²ñäOcºa¨?;Xhùê†~ÿÇÇW)J‘ìJJ°α¤4KU™–l¶¸Š´ôÚŸä*ùe•ò-YyÅÊ[=sÆÕR—*öÒ›ºr¶¢§Çô ˆ•žÜKAZìªÜK5ì¥hú%iL=öRp%Ö9I>ÍìåÛÊÅËÀÔ”ÀT„I ™žYÜSž^¼åéÈDrÓª¦ž‰ä4—œ9LšH®¢1•¦y%-EKª&•s“{LAžª?'à"ü‹Sš5™t­hãhî¡]Ú@’7é:Ù].Úµ·{ÐÇ.ueëòQÛ;ZͶàžãqíîj9$-ÙøHrçFö @€ ôƒÅ}ã—éo£1e:|¹©| ‡ÉϪRÒüœ:Jh-I£(#&-øü—šš]ÎÝ;ÞD·q»%oC%zYl#¬q»7ïŒKGäËCQWÃ6ë†n´`6ƒ¶£•m<ÇÒ˜y`÷øM°›šÚJ3’™aõ·aÛ»Û íÚÏcëë[p5Qóý=úGÇÕ\¡GQªÊ«Tž.<1\EWªi,Õ”–ÊSÅyù–Nš3®¬.Õ™6®ñÌqmµ—bÒ/ÕžB®Õ LO/Ú<­Rz%0˜æo6&“s˜–¯[ß(£Ô~ˆp‡ùdþHÊŒ’ö³X“É¿¶Ëf{¢Å`Òµ«]HÛÕ¦?dæ.­môÊ¥>Övì+~êi» ¶Çí9E7D‚ÔÓ_š@€ P$ )Ú¡¶¢18øÉ7ݦۇ Æß4„RÊÃq˜^/O'WÿI0 ¡<üÔ¼Ï}q¿uë××kUHcòWóµ †(]Æ@l ÅnÕkœÄ†D|WÃÌ$}×ÒóÔ›TÎFlÌEð-³o¹)·,㎭l;µ ÖÔ˜šЉãh_6ó”¹NVð¨˜ÆdµgÛ¬’N]Rµý æ’êCÅrÖ…®Û”2ñx“?¡X¹Û”ß*©˜d¿éBu›q3_üÜ—ö‹ÏÉ$\¾fÑqñÒ§¡PšÌd£gÎA1P½Õ˜|¼¾vfѱ­¹Îé"Õ˜b3ÔFBÉn³Ö™ýNXsPÑú†ë]nƒ55¦õ–f£_'WOôg5ˆ~HcòÃáL;„}—+Ç?~R9ÿðwYú'sÈÜËfy³ƒ44'¦ß[L³s'+7®ë¶ìöå¶ýÈl­ÐX±ÚåF•CzVè¬b[Žê€I@Ø/'€Æ®Lï T £И:Š—'G ×“Ë(›\[ßó‰'ž8èº!«^1÷¨FѧGÿð¸ÊGoÕ“ä'¹RÊ«T/»’.z=])7ñË“O/d”Š´ôôÜÕi©<Â2í¹UyfìÔùrV¢ÞRìK£&Ï[Ì5¦²SÅŸ6.”xIóÇ)ëÒˆ‰sg,Úàr/M_¸A¥ôt‘+•ÜK½O¿t×£Sf-Ý6yîË*Á“mV¼ôKÃÇα ~W†™ýÌ’-Ï,.—§o ʢ;½$),0-ìIÂ䦫d` ’0©X²¥LhLžÃô5dô³F=»Á¢¿¨4ŒbÁUg½°Õ쉙ë]*&QI¡ûÙÉçÖœ]Ξtñ0Kamï¸kE´¬—=J¨ut]m_´uì)1½lÂ>µËW½ì"Üå[²+swjû"Së§9¾ @€ ”`°8%H¢hLIPgŸç0é1°Àa*=&‡IC@å„:¥Q”© 7)¹ÆÁlÈkÔ¬ 5ŸÓÔƒO>c2¹¡’hFÐȆ³vܘ‰qßµD#j…콩ђaà˜¸7&cÙtLnpã3ö|šîôÛG6Èãç³±zº4ìFþ0Ž ÙWlâ³he¬ ²lÉróزÛWçòë4lŽ[!d±Œž½Áw˜FÎ\?{ùvJµ¤õê6ÊLoÝæ©ç^µ ^6ª©Á·±3V«ÛĘL_÷ Å+J5nf¡ùí²ïúý-:¸gý*Ê9wÛ‹m\Ñ´=šSRsûÖ ýràüÍêS»›`[ˆ*º¾áïÔÜWƒè-¡èë¤1iÞ¦ž,\Î`{qçäýèŸûj)Û¶æ£ïHF?]Óü@Ô‹ˆñÑËé_¡cÙmÍEÊu wB¨ S4¡ÍEÖV EÁ‚ng½œÓÚ—ë«¡j¸tSwýéêot{·úX9×d·Yǧùƒ5!WhLq‘åÊ4¯ýžv4&zBf „¼£ÐŸ 4&ýGÐ)ív™}æ#CdJÓmÎ=Š. ºö¶£~x\½Jf&…Je28 Ž„]% —œÙÿ’=>ûÿ³ræy—hôäŠëoÿü—¾b%IY÷æ·¾w˜ýyôN0WÉ•£~t‚[ù[ß;´’o©Îlq/½®”K~֥ᣦ}ó»‡ÖP—ê'^úÜö=åì‹5ˆc唳.V)9Lá™ãâ&+Íï™4º¢ûÌ{êªþ¤3.R LºÎ¿óáÉÿúù/;IöÒíMú×}¾lSI` ì¥Ó‚)°—œÀÔiÎ}»´£‡€9L WouI˜Žºd¢•®˜vàÙcî|jµs˜.¹gÞÀ{æ#)+¶ß6zåg9|À„ÃŒ|úzKÅ$Œf}ýô¤Ú&SGÛÂÆ!@€ `°¸@Á7©ÀÁO²éæ0 ½od9åy%•µžÓ(J0)XIGx`ÊKGœ`2ŠF‡Ž¸xÂá¥rí£/„Ÿ[¤pÜÜøœLI¶™}ÇШJ/Y,§žu¡ßm4àæ,–SnœuäÀ‰nðíøË§>úÌË)ÕàÛÙ·Î.¼ƒoe‡©2ø6zz“©‰z•WÑh¾Pü,VÍo¡ˆkö&úÊÂåG_êŒá‹} nã¬1öø¨¢Ü§Zôû];£sÑ/bìh3 Ð4¦8l\™¶Ô©øRf 1e&TT´Š€M¿îÞ2Þ—ïëjL2ÜÍ»7ÉRȺ|¶)™°¼·Ñ–Ætùµ·ÕV‘‚DÓo]~ÍmGþð¸’T[Kò3*•Ó)YR¥êÉà¤+Ùó^Gÿø„›ïxÈt%{ükÏîùܲ×t%ü›ó.QtýPùIæ-ÉX3e¾®‘¬hY++ÝÎâÒëb=]¤k3+z̨\–—Ó&ë©#WjÚKR—zr/IcúÍE*ººsÅÔ¥;žd“K¿$é_öùrmiaU¦)^ú¥) 6E20Õ˜úª1ébXÿõéðoƒ&ur˜*]HýDÒzLÐz‚& ½Y¦“¯Ÿ©kéwϳ0iîîñ/êû–Q˹lŠKÅTÒ˜ÙëL¦ÞžAX€ @hžƒÅͳÊÝšhL¹ iTq˜F¸ÇÀ\6¢HC1‡é·÷Î×àI 1•ÄNº~ÆÅwÏÓ¼`zjî€3Ç”sêT? ¦!”ÆÍÝ;vv¹ *`õä¡îôc+3™Ãê6Ò˜Ìb‘Ãôëf™Å2nΫ’ÞÔyúe ¾Mxþ5=@8máfu›3oyö÷úÁ7=@¨±Ê'žY¥n?»\“aqO“{¦IbÁs§­F_g _|´èß>nÕƒèÛã£×=¾ôØ?N-¥bÚzØ€ñM_ß¹è7ÛdÖƒŠM).þ\™ûèÈë;|«:ÿialfa§1¹ŒÂª‹›^¹®Æ¤/ÛôÆÑ †õü‡¥ ÍÜKÓ¯Öœ‡´þM}zäŽ3 )¦ôhIÎO*[J¨dÅ™I7Ýñt¥»§w4=œ\%³”ݳ¬?g/}mŸ/}eÊs+u…leÊœ•Ò˜î>Ö¤¥g_xÕ’-ý´ßéû|ñ+*Gþð]G)åÒ‘?<~÷ÜSÿîóÅ}-÷ÒÐÆøÝC9íÀï*ÁåWùÜ÷=ð;‡¨h˜æþS¥+iYÿ1ÕŸ3Î4¦À[*©Kr˜iÅö½¿°ï7¾}ˆŠvôÈSsä-ðíCTôþÞŸßW×lZ¾åžQÁÅÛ²mzç¡qs.¹bðÞŸÿò׿u°’0 ¼b°’ëjAêÒ¯~s‘Šô‘ŠÔ%³—nxÒgöø/J¿¤²ÿ7–½4ô¡‰Æ´hóE¼E zSÿ6ž?NÓü L JI`*ÍW³´0©Üö§†þû{WÂV†Ø¡!p˜”LkÕÖ’÷¦›UPÒš*ÎFßî|jÕñƒ¦)Äcç¼rÈer˜‚Ñ·RFëÙ¥XèZZÃ(¿¼fºä0—ŠÉL/‘9þWçÔœ]®C-b³€ @€@0X\ `‡›ŠÆTàà'Ótç0U#ìEÑóE)eÓy]#f—Ü;ÿþÉ/IF±Ñ0{L£(N]«„:Êîæ³tà ¡lÒÒÞ_ØoÝúõÉ´½¶@ÀD+ud¦Àa:óÂÊäƒ=ÝFSÈaÒàÛíãV›´Fçá§×z³nS·Q>ž«^RJ'ßÓm489rÚJu›¶˜L-(ôWúý'<ñÑO?fö+Ò˜ÜIæ“ÓùAÓ˜Ùˆ~¡û‡@  1Å+ÓtQªÐA¼UÝÁj³ébÐ|ÁÊ©ägc2Ê©$=Éf—k0©\Hc²Mze¬4¦Ë®\WBZ÷¦>•Æä†<äŽ8-É™I¡yߢºtJZ‡ô³_ýæ7ç^"{éòë†J]’«d –õ´T$3–.¿v¨Ö”ŸJ³tÃеÎÿ¸§æ†»ìÚ¡ºpºìÚ!ò“ÌU’·tÁo¯zà‰iR‹f,~E—ÓÒ˜FN|^ Güàø¡÷¾äTÙKãg.× Ón&‰;ûâko{@®Òa£5XóäŒà£ž ãVn×Gæ-YÊ%Ó˜ôPšV»ç±)Ö9öÄÓN>sÀ­÷ŒÒ‚å^’´t÷£Sn¾gÔß:DÒÌè§_½¤ øC>nÔ´d/Ùlqò5¦ïù“Ÿj¹—ä-)ñ’Š4&˽tðQÇžyá !Óã“—|zÿò䬗4rtÑe·|í›Û#MºJt%’~©±ÀÔB6& Ló¦NjLæ0Í_¹Õu0ëWê-zS9aÐ4 LºxÖè›kÙè[YcZ ÀÙó@Êä§ {f]p-]€ ¸iÎ`2eôlFµ!@€ v §=B¬Sá²és˜†Ü;Âݹ¡9Ke=²¤1©¬KÙ¬{æe™(¾Ãô«ëfhðäêG_Í e“= ¦!L¦Œõ>_d©%3Éa:åÌ Ý£ƒ6‹œ ¾Ic:å†Yž5æÊ[·qƒo¦1¹GÌX/‹EEƒœ=.ìé6˜LÉt›>DßÎ&>†¢¯‘XÿñÑk}A§Ž3n~–è'eö xИâºW¦,ù&€Æ”ïøæºu!Iy”ôŽ2ÑZ£{§1Ùw4£\FØÓÕƒc<$}zÄŽ ­àkI —KŠRy8—WI £§Ì“¨ô`I]2W©¼\J°¤¢K#eWºàwWk¡<7\)c­ÊÄgW\vÍ)J§3PEF‘–U´ dKJ¹¤e›$îüß^uü/NS¾%}$¯E™–,ß’þ}~e ¹XѧzÇÊn»íöèSϹ ã”]ɼ%]ËXRÑÂgþqOe÷‘#cIïhA¹—N:s€Ô%ÉIw=2YÆŒd/óóSÏp…ì% ýœ5àŠŸüüT—oI–’.ê,“¬šîÙïô‹”cI–ÒЇ&)÷’ì%Sm®¿s¤Þ7iÈð‰ZA V>½û黽ä235™é¹›Ï©!0ÙÈùŸüøúÛ[9á¿ó»‡Ì[¹¥gÜ­4†b=GÒ#f®³ éG,«LÊL¨TLß5Ï9L…;ž\uÀ™£COƒÙ&S®Oþ4€ @‰`°8QüÉî)Yþ…Ú»9L·Ýû¸sP Å¢”Ü4Š¢Yä4ŠŒž­ÚñhIcr)Ul¼ëÉç^)=V53ÔÔÒCtîI°“ià~íbk! Ÿ!—É_(ef*9LÔë6˜~}ÃLu »=>}MA¨o+·.iÚZë6åY_ØúûûüäSüƒ<ñ•‘·²Étî¾if»‡%sRÉ>DD 1Mˆ:LŠ~ 1yÚЫ²à_zß?ÑÏI/*ÚÁ%ùW–  1ÅE+Ó,÷mêÞ˜ScF¬‘RÑlLª¨æ…“Œ¤…^hLn"9M3—Ñ„LÒ˜þpõàIŸñýc+*REHZûº’'ùNRÍåžDJÝDïS•,¥É³W*©Ò¨Éó¤1•D¥×‡zZ9–FM~þŽƘ®d–’-«üáš!§ž3ОùP1]éÔ³ÿËÓ•fÉʈ sm†8]K[Ñòï¯"™I—Ö÷=|dÿÊq±©â$-Icº÷ñ)®Xâ%S—œ·:n†©KV¼Q”`„M£(K±Q iEc)–ReðèÓn6E u&:3”ÿ$˜|”}ÿy¯%ç~éÃë¿É}ú´¨'²œþ‰;ûÄã¢qàò p¤ÛÈV ,–Õ;¯xpqÏ„+ƒTiLM[kƒoW?RÎà¥Éæ½h¼›…Ðeð²Á·±Ï¾¼ß7þíž_øþußI;´Üx}ˆ¾1ÜЫ3Ø}u {|TY¸îzjµ ½^pûÜ nŽèÓ·³Màì¿ &ßä•ehLhLYî¿Ô½oИúÆo'HÀiLšnúôéVÍ7§—z¡1iC˜ô9Pz%ؤ–w-é÷WÝZÓ7²7õéáß?6fs’übfI­²sÒìR—†šfÀðËÓµ IÓÀÙ;ʱ4ô1zGSÂÍXôŠþpõ“–TÆÏZ!ßHN’ÆYÆÏZ®yâN=ûâ¡ÃFËI²âôNÿK®²dK.ÓÒá?8^ßzlüsòZ$*é#Ù-úWËZ8ìûÇ;ðÊo|ûß]y›¤¥{›¤Y*KV”cIÆ’þÕõØ•·Ü¯å‡žœ£y¾µ ‹s%^:錋T$-iˆGӯ飛î~B—mO”–¿þ­ƒuýfÒÒ„9k5gÜvª¦Ó0ÍWÒ˜.TùñOOўͧôK–ué±IK”²[3Ç]vý·•&=÷¦?0AC§_pù×<(x¢¥\6j,É=ÛÔ¤ºä¯Ö¤Æôàˆñk7½ÓåIåüÎ!s—ovö’ÍÅôœ”„é±é/+ ú á‹ƒIÙKÃ( ¨&Å+H‹uÙ”«^¢@\ù𤈪=Dè?d“ÊÉaRëT0™Z>·ðE@€ @ L©À}©ÀÁO éf2=h¾¬Ù:>Dß4&7”¹ME§ýÎcÛ]ãWK|´Ai»^ñÐb¢ßz°øfHaDcJC úP4¦8x\™ö¡kñÕ @cÊ@¨bmNc’ä$J»J/-Xr¥“t%ÙO¶á±cÇj.9}3£“]^zå­õÅ£×õ©4¦êvº)Þz* “\æ¤z × ~àw•Ÿ$‡É䤑Ÿ×Lpîy«wJNúÜ÷UÑ‚ sEÃ+C†–Ëb³¿röÅ6àréUC¾Qzó”³.Öà‹Œ¥ÃpœeZÒ5ÕàûFþýãl’8%^’·¤kl9LR—TŽ=ñ4Ó•øö!š?Nÿ>üäK³äŠì¥½?¿¯„$å[ºòæavY.9IÿjXçÁ±s4UœŒ%½£rèÑÇ)åÒY 2u风½ñ®‘ºz·¬KÊ®¤¢ÄKúW“šÿ.Ú|Æ…ƒTd/٧ʺôËÓ.<ã‚A÷zV _ûæA•~qÚ…nî}bÖAG+{I“Þ”ÌôoGxKV*™™[°—z;©œiLV$3ýû{ôd¥vb‡Î='NTôŸ[¶Éõ.KÍ¥Ñ=fEÃ(£fm°a…õ²û]6l‘"%«L‰Ðe2vÑx%µ~xÚËÁµ´9LÕÓÉ9‡ “©Cqd³€ @((‹ ø ÙhL~2M/›Lc¦÷ØK•ìæz8pììW4–b“†Ë4ò«ëf¸IÁ¤1IGÐÊMO,ïq˜*ÓÉùó‚9‡É†PÔTL¦dâÝä^}‘¥Z`r¨Œ—í%—ÿøË§º‰äf,ÙrܧÊ~3õMG™xlðíæ'–ÿä²)²Xä0•’ñ„ 9L˜LM†® «õ!úcç¼â†^ƒÑ×ëfXò6EÿØ?Nµ¡rEÿÂ;æêÔ¡èWR1ý6ÄM$F)1ômÛ1SJ®LÛÖÑØP*  1¥2,TªRÜjÊÀ$ I/KŤW©™dh»4qôéaGSs…à:6T*i“\þ$A~R©ì¨*ž¥dõK0°*Û5Ôâ&†3KÉ•ò¬pöTPez8óZB%d,XYfsÉÙ´P× ²Ê£(¡2 åçar£C˜LiïŒ&²Ô˜\å5\ü»+oõ»˜Ì{«ÑmJƒo64|ó ¬é0a2u©Û´;úN|´¡W¢ß¥8²›®@cêêŽí)-W¦ëxl8:|«:m¤…$P8éwW”¯KkºGúTSi°Ã•j)¤%•´’P©+'9i©†¥<æŠK­Ô²®dˆÄJKµ¼¥’´Ôo)¬.U{K–e7F]ªØKåÄK}É·Ô)ÉÎ’™tU\ýzeæØÉýžyY‰k¾æ L¦oüì’ÞÐ[Àd²ZÏè[èBzqÈaêÉhíÏ%çÀa2ò‡€FC€ @ ,îÔ¬l)+‘ÊY=Íd>ú÷è ˜z+¢Øã|u¦p6ëzSÍœL‹ï¤A¡—Æ9ðý׿…ÓõQ΀§½9¯ô§‹©­L¦ß^qK¸ÛD¦Òƒ =Ý&þ‡iÉÂÃÏÿõøþ?ŠVID]%í`3Q¿´F¿¦ÇVï¼!Ò- &g">T2uИR’^W)W¦½îP|!SИ2.*Û<ÂiL¿tKŒf¤O=ú˜ÆR4‹Rm3©ü¼W E©2\HT*?âãò*y©•jfWª§+U§YŠË´Ôš´ ÕHýçO¯®!P]&ÐLôCâcL üøè»§Iýè×;oÈikm0¹ËÙ] 1e?ŠhLq1äÊ4û=œÄ@c¢ä”@á4¦ÊitÖ¶à}zèQÇÔ›ÐÍ·‘™“LK*=¦S³¿UÏWWTª“Z©œƒ§gV¸]©æÜp5Œ¥Êìc5fˆ«ž$®-Þ’•Kç'Œkè0i…¶kLzzæÑ£÷²ìôìÜ(•–í}{OÅ liý©4NõÎ3£Æ<)“iú¢×\"kKÂT~¬z¥êBº¤ŽMRFëy H3Ó–7þòáGá‘”œži @€ Ð w†k&¶ŠÆ”‰0åµ’o¼ùæ~_;àþ‘O—GáJy¬«+¥²ž±¤4—œ=¤WžK®‡IRÂ;ïþM0ÿöî.¹J² êqi™ì™·è`‘††lŒy%ñù“ã~:ðò›ktKÂäw›ª)]·)'A·X$0Ývìwd2mÚü†‹¾ËÀ¤þ#Ñ÷ÝXbâ”òZ¦¢_cÊÞEß9LÛÞ|ÏH†Îõ“Cï»3LÌ`r^#E»:E©Sd»·]4¦8Ö\™v¯'²§$ 1%A}v@á4&]ŽÆhFúTS¼ŠT#a’Ÿ<)b&INŠó“4’k)Å»J½Ð•‚š`Êöhy&b,5#-M‹ÌÍ·ÔÐ[êNÊ¥Ÿ©í“®*mdJCWÊú«[Ùs3.K“-è}-ØûZÖ;ZˆI-“éëß:ø™…¯–‡ÞJc(îI ˜Ñ·Ò }8L]8² @€ @À#À`q»SƒŸŠ¦›Ét߈iö XÍÇÀœÃ4mÑæ©¥1®ò09‡Éš­ IHrC=zǬ&ÓS4jdƒEúWE¶ŠÖ”ˆ bcD¼’% —åâËoîñÞ*“KÂT_}+?@Ø0Ï‚gçIcZ=¾‹¾úƒº‡º ÚP¡õ ½¯Õ¬{øcŒÉRÊëÞ»}Ó˜œÃ:oÔL7šLÎk¤hWG 1ukW7ŠÆ‡›+Ó®vFvÖuhL]GλC ˆ“yE5‹4¦CŽ<&ôQpíÚZ) ”4,ABªŒJUI•¢R)ïŽ+ÁÓcÑRzž¬÷ÆRðð™+Ä©*½•–”u©V¾¥Ä½¥ÒÔvÉ¥\²gì4ab“±Ò;ƒ°ge´Ž]ˆÚÑ®7-]S½—™LÓ¼Zî•Ð[¬M>³¨y£oäaêι”½@€ @Õ,.p@c*pðÓÒt3™î}|Ú¬¥åT:å$å–„ÉFQ*C(Áƒy½ŸK.ä0©å.å’ ÙCn–iɆ†ì‘6K¼¤5"äÒ5iMû¯d .ËoŽë6‹Ë#o¾úfž &õiLž|˜Ú¨4<–¦Ýì%³”Ô ôŽËée]ÅŸiÝ­£Ý£ýj}­üìhyè5ýf ¶šSô¼L7z5˜ÜQ\l¸ÆºR­‰áJ‰|4‚“Gi)ªIµ]c2WIn|ÊÄ&˺ä†ì<ÿÁ;-ëI¬†§™Lûó Éó6ØÐ[)âe­»Êè›Ë}uü¯Î9ãÜñ£o[ÞøË‡}Ôpï¬@€ @ ) 7…)Ÿ+¡1å3®l•™Lw?:­Îc`ÁDrír˜Ül6#˜hiÇ ™âr[öýkùx´¦û(ƒ˜sXåÀeùÃMUݦÎà› 66é0Ébq®’ú† jÌÐÍ%g“%a²¹äBFÆçqÏa$’hRç¢m‹o½Áäèy£…Áä$(²Ï¬@cÊZÄ¢õEcŠ‹!W¦Ùïá´ Žý#§ §1ÓD UÞѧҘzVˆ¸Gþ„n¶\{Z·zï/iEÉÍd·®c)…E¥F©•‚LK5²+Y²¥º’¥Ñî)¥¹áj¤YR¾¥tgZj&·S‡4&h0Kɼӈ•eZ’ÆdZÙ¨–†*´‚%mj~ÄÊL¦IÏo°ÄZ6‹œ{Ì‚Pp˜rzö¦Y€ @H7‹ÓŸŽÖ©£xÙx¯˜Étç#SŸ®Ì"g£(öüž†¿,§¸ "µœ‡IUr°iÈF~lPH¹LKúÓžj3=Åì_7»\¯ZÇÊ# —å‚ßßtO`ª9øÖ¼ÃdÁÜ5-Xg°ä:zÇz‹ëê?ö¤j™”] whËŠ~´þî¼3˜:o´6˜Ü5tì(«И²¹žz£1ÅÅ+Óì÷pZG‰þ‘SEÔ˜bÄ#iLñ“+”ô£øyÜœTo¡l&Õ—“*™utyìÊæÐp5ç€3Q©«É®TOWÊ«±TÓjj»ÆdÏKé¥ÙK¶àþµô¾ŠYè¥ý龨ä©F&Ó×:L©Ì:.ǶüØû×ràmøÈ# ™i¥\–óc¥ÛTåîrÏvöÊaŠvØ04¨èº•vÙ¯h'¢¥âŸ7&»¯·6˜œý˜Ð‚N@cê$Ýîl)Ž3W¦Ýé…ì%)hLI‘g¿&P8éÂ?ÜãéSiLá”H–©‘~dR´xNRœœT×O*åÚ‰µ”‚4<õò*9»¥8 –šIÂäÖi»ÆÔá¶jóf2=5g]ÙHó´’‡©›á`_€ @€@‹ Ü!И ü”6ÝL¦Ûž\ï1°¾äaJi›©V;.Ë¥7Ôë6½u˜ÚQ#¶Ñ=¥èßHô»Gœ=%H)AømÚ5SH®LÛÔÍØLJ  1¥40T«¯ §1U²ûz–õé¿ñ“ZâQ@¸§, fòŠ/{ÔL‰Ë¢d3…U¦~«•NÉ®£Ây•”»2\íÔJ¹˜®WºR½•3­1éè—ÉôÕzrö:å?Íñ‡ÃÔ׳#߇ @€úB€Áâ¾ÐËøwј2À|VßL¦!Mög‘ëû\rù„E«<rYλô†h·Áa*B7±è—ØËSOÚIƒè!úÅj#SöãÆ„Æ”ý^L Z%€ÆÔ*9¾—r…Ó˜,p½¢Oÿíð7¥yI’êÏææ<¤èB%’ä¤^ùIR”ª-¥º¢®Réª2¾d]c*›Lßø7]<û-ÅaJù™—êA€ @ ÿИòãº-Dc*pðSÝt3™n>ÉB!Sªc–ŽÊÉe9÷·7øÝ‹%‘éF-ˆ~7(³Ä  1%‚>W)!W¦}î`l ÕИR*×:âiL—ÞXIqTÃ1RžØïþãú+îQyú6ÓIH.[’¿P5¿›iI®xY”ü裮ՊA€ @%€ÆTÐÀÍFc*pð³Ñt™Lû|ùÿùç/}vÜäÙñ£(ï¼û·l4‰Zv…À?ú®Æï~à±øn³íÍ÷ºRvÒUGþè ¢ßUâ쬛ИºI»3ûBcŠãÊ•igz[M 4¦´D‚z´™@±4¦­[·N¯~IOñË}¾í®Coòg¾ Ü8äÞ† M¤ScÒ¹aài«^ýSÌH S›Ï l€ @¨G€Áâ÷ 4¦?3Mdþ×Þÿ¯8L™ X:*ª›ÄýïùOK7¼Ósp˜Ò«öׂ跟)[L4¦ôÄ¢Õš 1Å‘ãÊ´Õ~Å÷²A)q¢–½&P,)Š'~´‚O!P“@:5¦—7ïúÞ…Óyú•zQÃaêõ ’/@€ @-`°¸etÙÿ"Söc˜ÿ<¹æÀ‡–ï¹iç_ꢇ)ÿ ÷-´›Ä붯­×mp˜z53ß ú™ mS ÐRö4¦¸€peš²îJuÚL©Í@Ù\Z 1õ̆²& ¤ScúýË¥1ýäò9¯¿ý>sÉ¥åK= @€ PX 6ôL*WàÐg¨éÒ˜^þÙ?ú¨¦É„Ô¡Pv³ªî&±t¥èàS7cÑý}ýî3gÝ#€ÆÔ=ÖÚS§úÛM?4¦ôLj¶D ½&BÉR1YõìF ·ùƒ)äajéôÈ— @€ >@c꼬•lLY`¡ê5™p˜ ÕZnlÈdÂaj™d¿Hô³5êG)ûý )û½˜´J©Ur|/åИz­°4™°‡ÕrL …“¥b²¢„Lý÷ɄÔò³0Õƒ @€@>  1å3®Mµ ©)L¬Ô-c_»æõ51{óM&¦n…%íû4kPÃ*:—‡©!«Ì­ÒPsˆ~æbJ…ã 1e¿ 1ÅÅ+Óì÷pZG‰þ‘SEטä£ÄÛ6ó_ܹbýŸrläдeëßZ´æõx,¯íx7U'?“KȤjèmóÎw5—ªÚR@€ @ ,.D˜k7©ÀÁOcÓ÷ºe¯†ÕÒà‰F{p˜‚*È ·,ÜÿÞý›i¬\¦f@ek£=zú†é ëLô"b…Ì@cÊL¨êV).†\™f¿‡Ó‚8hLôœ(ºÆ”Ó°Ò¬bðS1ù ™ŠEÖB€ @©"À`qªÂÑÝÊ 1u—7{‹# AS¿±ý”[¥ÿ”þZ°b©V¶ìÚ¢e-èO­©¢uZpê r˜Ôm†/>xþ`u -ë_#£ü^zÓ¬ÛèÓ‚CËSó\EßNZ–ϤÔ\ú׉M}½w}äþÌÚR8hLÙ9S\ ¹2Í~§qИè9%€Æ”ÓÀҬˆ¦bò2 … @€RF€Á┤›ÕAcê&möO@žÓä¦HDØõ×].?“þ4I)ô'J JÝ@Š’8˜¥$ÝÍÜ&#£¥N¢Î£wÔT´ uà––‹Kÿ*¦&Aª3è_§1Ù Ä´H­¦›™‚0phEn  1e?´hLq1äÊ4û=œÄ@c¢ä”SNK³ C šŠ‰„L… > … @€@Š 0XœâàtºjhL&Ìö›'à´$—2Gj‚ï£XºÓT,½JóÛgÍ\pZ’„󓜧e}jé»Ôs¬ÛXÿÉ%Š6Jº’eÞòSp¹.a’“‘Çæ2uMÎ 4¦ì).†\™f¿‡Ó‚8hLôœ@cÊi`iV1¼ùÎ_Ï¿c‰•SoZðoNïwÝ<÷΂ß(Z @€ ¤ƒÅé‹I×j„ÆÔ5Ôì¨!3N´šS—¤&X&{Ó¤%V‘½¤¢—s¥áÆY!¯,ÝŽ¯ªøiºìSýk}ƺ\–¼Ò(Z»,¦jµ¥Ý²æ»nö©M¶ž44¦¤#Àþ;D©C`Ù,ºM©ÛÄÙ @€ C€Áâw4¦Ÿ¦C€ 5hLY‹X´¾hLq1äÊ4û=œÄ@c¢ä”SNK³ŠG©x1§Å€ @H1‹SœNW ©Ó„Ù> @h4¦¶¡LlChLqè¹2M¬c²ã®@cê fvÒ}hLÝgÎ!ÐhLÁÊF!@€ Ö0XÜ·\| )aÌy#^wÉö?ÏÍy#i^» ¼óþ†ÍïLÿàÃ÷Ú½a¶—D?A¢Š-@cj]j¾ˆÆ ®LSÓQ©HG 1u+MžSò1 h 4¦¶`d#€ @€@{0XÜŽ™Ü S&ÃV°J?¹æÀ‡—¶`¦¹}%ÀMâ¾Ìò÷‰~–£GÝ@cjD(ýŸsŽŠ‹W¦éïÁÔ°/ИúB輦SŠƒCÕ ÐhL½¡Åº€ @€@‡ 0XÜaÀiÞ<Sš£CÝŒ=¡Ü$nZn¾BôsJRƒSö»稸rešýN â 1Ñ?rJ)§¥YÅ#€ÆT¼˜Ób@€ ¤˜ƒÅ)N§«†ÆÔiÂl¿ïИúΰ€[à&qƒîšLô‹ýü·)û1æC®L³ßÃiA4&úGN  1å4°4«xИŠsZ @€ `°8ÅÁétÕИ:M˜í÷Sßp Ü$.`Ð]“‰~‘£Ÿÿ¶£1e?Æœ£âbÈ•iö{8-ˆ#€ÆDÿÈ)4¦œ–fSñbN‹!@€ b §88®S§ ³ý¾@cê;Ãn›Ä ºk2Ñ/rôóßv4¦ìǘsT\ ¹2Í~§qИè9%€Æ”ÓÀÒ¬â@c*^Ìi1 @€RL€Áâ§ÓUCcê4a¶ßwhL}gXÀ-p“¸€AwM&úEŽ~þÛŽÆ”ýsŽŠ‹á]Ç|üøÙÙ2-€@hLtœ@cÊi`iVñ 1/æ´€ @)&€Æ”âàtºjhL&ÌöûN©ï ¸n0è®ÉD¿ÈÑÏÛј²cÎQÙ!-€@«ИZ%Ç÷RN)å¢zh–S³¤X€ @è4¦.@Në.ИÒêÕC‰ÞÐn·-7_!ú¹ % ©A)ûÝ‚sÔÜ›úí·ÿäþG‡‚ùîÎ-z?û¦¨O‰Þ‘ShL9 ,Í*9+v~ïÂéú·xM§Å€ @€@ú 1¥/&]«S×P³£–  1µŒ®È_ä&1Ñ篊 ¶ç–SöCË/”\¥¿½»+É—ÆŸyY¿ìG˜@ >4&zGN  1å4°4«x&/Ü*I9™Š×tZ @€ ¤SúbÒµ¡1u 5;j™SËèŠüEn}4¦"÷<·)ûÑ-ø/”’0ÝñÅÝ,Óâ{iAå•™cõ§²4­xlpôý?½ºÆVÓ Ù?-(64¦bÇ?Ç­GcÊqpiZ± 1+Þ´€ @)'€Æ”òu²zhL¤Ë¶ÛC©= ¶•‚ß$.X´ÃÍ%úï9o>Sö\ðs”Œ%ç0Yî%efzôè½´ ,M;W-”´dSËiÙ_ïh}elÊ~ &€ÆTààç»éhLùŽ/­+4¦›¦B€ @ ýИÒ£ŽÕ©chÙpÛ 1µ e‘6Tð›ÄE u¹­o½·zó;Ó­Lßðsýº­}ó÷Î_?x«€Lhr>  1e?®ÿ…R&…Qö’D%iIúÓt%û÷Ý[´ ÄKZПÊÏ${Ikº•³ßhA  18øùn:S¾ãKë D©@Á¦©€ @H?4¦ôǨc5DcêZ6Ü6hLmCY¤ ü&q‘B]n놷Fë­f¾ô“|ø^™Ðä|@cÊ~\ þ e)—F-ÈUÚ¼pºL&-»$Las›”ºÉV3ùÉÖÏ~ &€ÆTààç»éhLùŽ/­+4¦›¦B€ @ ýИÒ£ŽÕ©chÙpÛ 1µ e‘6Tð›ÄE uO[G®Ú§¦Æ´lÛÅB«óI)ûq-ø/”¥\’Éd3Çé¥dKR”$3ÉRÒŸZA‰š´`ö’ý«?õ¦¾bñ‚@V  1e5rÔ»4&ºrB)'¤€ @È4¦|ı¥V 1µ„/u•SWqçeg¿Iœ—0ö®52‘Š©wY;ýИÒ£F5,ò/”æ‰sö’&÷?ZÅ4&ý+“Iðä-ÙG–¢É¾bÚ ¼ ahLU#€ÆDÿ€@N 1å$4€ @ù €Æ”8¶Ô 4¦–°ñ¥®@cê*î¼ì¬È7‰óÃVÚMÈD*¦V8ò4@cJstš«¿PÍqb-ä‘S£J›D‰nœ@cÊI i @€òA)ql©hL-aãK]%€ÆÔUÜyÙ7‰óÉÞµ#”‰TL½ÃÇÚ™ €Æ”‰0ÅV’_¨ìÇ@ UhL­’ã{)'€Æ”òQ=4K©YR¬@€ tS §uhLi õê!€ÆDoh7‰[€–¯ø ™HÅ”˜ÒŠ*hLÙïüBe?†´­@cj•ßK94¦”ˆêA YhLÍ’b=@€ @  Иº9­»@cJkd¨W4&zC ¸IÜ´||Å%d"S>J+ÂИ²ß'ø…Š‹á´›>~nXöƒL P‡]#§ИrXšU<hLÅ‹9-† @€@Š  1¥88®S§ ³ý¾@cê;Ãn›Ä ºk²%d"S‘û@žÛŽÆ”ýèò C®L³ßÃiA4&úGN  1å4°4«xИŠsZ @€ `°8ÅÁétÕИ:M˜í÷Sßp Ü$.`Ð]“•‰TLEî9o;SöÌ/T\ ¹2Í~§qИè9%€Æ”ÓÀÒ¬â@c*^Ìi1 @€RL€Áâ§ÓUCcê4a¶ßwhL}gXÀ-p“¸€AwMÞ°aÃiçü¸Èh{ž  1e?ºüBÅÄpâq»O½«!Fcê*nvÖ=hLÝcÍž ÐQhLÅËÆ!@€ Þ@cê¯\­Æ”«pæ´1hL9 lg›ÅMâÎòMëÖKÓþf,Y²öß_u+&SZE½ú@©ðRòU~¡jBêÒ·¾{輕[æ­Øràw0™Âô·ûîÿ¸iç»~Ù¸ã]+¯•Ê~_ýºì¥W·ÿùÕm~¥T6¨lÝ¥²^eKPÖå—7—ËÚM屮´éí—6¾½ÆÊko¿”?­~µ\V½ú§U¯üiå+o©¬ØP.Ë׿µ|ý›ËTÖe©ÊËo¾ðò*ú ¶²xíë‹_z}‘•5¯/ ÊÎ/e¾Êê Ì[½cުϗÊÜ•V¶?·"(sT–oŸ”m*Ï. Ê,•¥[gZyaëŒR™¾d‹•gåi•E›|òùO~j÷i 7O-•) 7MY°i²•ù›&eãÞ_Ø)%'Fª‘uhLY õ‡@™]€ @H4¦£ÛUAcê6qö×{hL½gÆ7>æ&q;nñþ¯ì?qæ vU7M/½“©€!ïMFcÊ~„ù…ŠÆÐ¦ù+·–Ü—7æ.ߌÉ¢¤ß¸ÏìþÎ[òí¥×¶ÿYEöÒW¤1šhSà0•&ç0•¦]ëœÀ´9˜œÃTÖ˜*“Ó˜|‡ieµÃhLÎa 4¦Àar“â(‡©¬1•¦×–&§1Í«¡1mhL=S¼ÆôL-ɦ©%‡©¬1Í7i#SöϦ´ EИR ª¾@cê =¾ @€ ´™S›fishLYŠVQëŠÆTÔÈ÷©ÝÜ$î¾ ~Ù¦I3_PB§1)ñ&SƒI•c  1e¿ƒð Šaà0}ïЫ¶Êƒ 4¦Ræžç–mú9™x̸ñM‘õVr§G;7ÿ²“ª‘š9£ê§!ôÑü¾zµ¦iL~¦%7g\Ù[ÚºKÓÃ#'¬·Éã‚òŽ›Bî劽žEΘBÉ­zåO+_y+(ѹ䪦ª¹äJÓF¦f¦“Û™Nnûìå¡TL[g-Ý:S¥’Šiú’-VB©˜LcúûOíQÎ¥b2éÁãmr=+¯íx·WqéõÊ'ïöñ°{ý-¾Ô@cJ}ˆ¨ š#€ÆÔ'Ö‚ @€ºB©+˜Ó¹4¦tÆ…ZùИè-à&q вøç0³ÛÔ¹ >oÕŽçWí8èæÞšLº3m:ÎÑGÝ¿ÿ^¸Þßk¯½|{¦_¿~z§!C[G+K{Ò‚þÔ¦´¬wâ¿ë*ãVÓMz}]ÓGúúþûï¯T¥¾;=joÆį`ÍŒVF•\¸paÍïÖû(Æ;v¬¾e&“5¿/4¦ì‡™_(‹¡9L‹^ÜVSB5Ig{m2I-²³«^:¡5<Áº>¥³–Ö׿vFªwFÕûv*ÓXײþm~/­uá’Æ´Çú­»zÊ–]2–¬˜·´o 1÷Õ¥°½´éí—6e•×Þ~1(rÓêWÿT"¹`.9K¿¶^¦f¦Š¦¹Å ë¼ ì°_ç 41ܳË4—\d:¹*ÓÉùÓ¢Ír˜iœiL›4—\y:¹›&ÓÉ3ÊÉaª©1É k-@Í~ ©YR¬—1hL Õ…@=hLô @€ @ EИRŒnW©ÛÄÙ_ï  1õžßø˜›ÄE躧ûeÍ%÷ìÒåëߪw\7Ju‹tîÊÏ­Ø>ðòÞ™Lv \îgû©˜ÄÖ7‡ µÖñ5&ÝÕö})GúÓÄ#­l“ÞÑŸ¶š½c ¶¦‹ m*ª1éÝAw«©ú®Ò‡Xž'· ·eÛc´Vþ ¶5·N´2~UýeÛ²Û”5ÓUƶi$£Sè#cåVy5Ó%¾ò?’4àܲA*oÇSö#Ê/”b覲„ZÉ¥·(˜4˜QÎré•NàÛg,zíëßêEN&‚ü³¨ÎîOÿâΓvÂÑyFg;áØ)Å?‰ÙùÐzŸÖ±_úlÆdíKç5)H°ä—ÍUù–öÝïë¿ÖK¼äç^ªm/½ö'©Ke{IS$ÓŠ ²—)ê0)ý¡e`²¢TˆA6D+ANÄòì®1“~ Ke»~¦UæXY^•‡©ÊaŠOÅTq˜œÆ4Åט*Ó¤’ÄÆÔ—Éw!"€ÆD—€@N 1å$4€ @ù €Æ”8¶Ô 4¦–°ñ¥®@cê*î¼ìŒ›Äy‰dÝv˜Ã4åÙ¥¥;¬õS1Uî‚붨榹ø½0™ÌRÖ KzäO!g¹[ã’i´‚S”ô¾yNv‡[ŸZ^ýiëØ rK餵lÉ„,Ÿ‡mÙî—[Û¸Þ÷qØfu+Ý¿[ïl'}¤ïÚ.”µÈvjwèm_ú¢ÕS«…$-«¤5Á*c[°—ÞtëÛ²¿/·«³­` «BSè#K°ä[bú¢j¨Æše…²ž(4!k!Ïý)ûÑåÊs˜"ªÓ˜”°Ç$Ô•×òÌÂW›4™ìäí&þ9ÄNÎZÍΓv"ÒyFÚ Ç¥í$柜uÒ³}þ‚}¥£}Ó4&eWòKÈX’Ƥ)Ò^RÊ¥JÖ¥u)”{©b/¹ôK½˜–F&ßa* LÕÓêy˜Úì0-ÞütEcÒ\r–©'“s˜*©˜Ð˜:ÚcÙxÑ 1-â´7oÞzë­ûî»ï˜cŽùæ!Ç|÷ÌßüîaZ~ä‘GÞ{ï½¼5•ö@€ @"€Æ”¡`µ»ªhLí&ÊöÚO©ýL °Enç;Èe‡i¶ç0U2yy *é‚™k¼»àÒ˜”ÑaÀe759»œS‚¢™~ì#ÝÆ¶ÜlR!swt{ÛI?v;ܽc¶Ý;7›Çþ4I·Ø]2³y즻…Ò<¡PXmãú–“œ|Én±«†&c9õGËVËDâjå6î*i­óó‘èOW+Û»>uÓØù{ךö§>uY£B$£©á¡”Næ{X_Ÿr:”å¸ ™XyîÿhLÙnÁ¡œÃ'¡ö¤b ré¹y–m›¶@&ÓAcÆï¦%E׉žœ£éNk¡Ó¾ý韜uÞ³‰,}#S'®¨£Ùö~ª¾Oヌ²+•,™«Tm,í»ßþÃ_ž0®ä-ùÓÆù3ÇÕ°—^yk冷+õ209É%aZ\; Óë «'’+Í%çM$WúuV¦¶åaªv˜JÓÜ¿ÿ‡@cš\šK®4ÜF7Ù˜ÚÞEÙ`Á  1¼ÐülÐÎ>ùÉOîVëõ_ÿë;wn¶›Gí!@€ ì@cÊnìú\s4¦>#d'€ÆÔqÄyÜAÁoç1¤=mª‘‡É9Lkß虨tÇÔ&$rwÁg-Û6séÖ‹š3™B÷³åÜèž·^&Ù½m»Yn‰=Ìþñç²Õ|wÇ¥‰jLzG#Çæ$ÙËeiÒfÍæñëàGÙHå ‰Dî‹î}÷-G¡ð¾\¥eÕ94ñœ%ari™´_­£7Mågcòwº÷ýÈ6ë¶æê¯Û¾{9©Kë;*ß=¿Ü:4¦ì‡¹È¿P5¦úªÀ-—^iZ±­Sç½²ÿ7˜LÑlL–²®™“sMÉ?[ï Ê¢ªk':i 1}fEI–’_JÆÒ—÷ÛÿÇÆ¿øÚÛ2–¬¬ö².ù3Çõä^jd/-[÷æR+• Lf‘k<‘Üón"9.¹`"¹Vç’‹8LSn^Ò˜b&²1u¢£²ÍÂ@c*lèix¶ ( Ó‰'žXS`ò߼袋HË”íHS{@€ d”SF׎j£1µƒ"Ûè,4¦ÎòÍéÖ‹|“8§!-7K÷qÿÇWöŸìæ’[Ü[u·Tå0Y*¦ù/–&¯‰¤bÒ]ð™/l±dë…¸±aN¦Ðýl¥ÒÍl½´àdv‘êç’¹,&úøw¸M{ª™)t§ÜöårŠ˜¢ä×!4œU©É2ùwôC½9É ›;å÷+¹ìMÛ”Y¡½‡ª¤,m•Û”¯1ÙGj”s’\5ÌXÒîdkÙwýXr©|wûªÖ¡1e?Ø…ý…jà0¹é䢩˜*ÓŒ¶Nž·!Þd² mþiÁ,OÿT=9›cÚPcÒO§Ð¨‘Ù…^i“ó“¢ 2–4×êý=%]É•U¯þ)(¯Xyk¥+^⥚¹—ØKõ20­Ù¹ ©$LeÃX’qà[­åÛ¬HY ¬µ’¸üjÛw¥L_²ÅÊ3‹ƒòtPªæ’S&9LJÂTÖ˜êäa"S:-»(4¦B…›Ææ‡€fŽkè0Ù §œrJ~šMK @€ ¬@cÊJ¤:PO4¦@e“m&€ÆÔf ÅØ\aoç;¼a‡É˱¤tKµj:¹:©˜t+Ôn^ðû&Sè~¶ÏÖ}$‡ÆI<¦Ý˜ô#ÏFwÍí›!NïØÊz§¦Ædïk­©[ì6›{G·Ø]þ!«‰œË~d[¶ Iõ4&}dÓ'ÙäGúSÛ7s(j)Y%­¶‚›ÎAÐ:ö¦iLZÍ2BÙ›~6¦Ð®})ú‘iLZG»¶zšËeê€qsM°Ê 1åû¨ÏeëŠù å&ÍV¶lý›fɘ„ªYÉ,‘^c µtŸôü†¯—“Ée“S”ªR+Ur,)[á°GŸ\¹á-s•ü"¬TÞ´RC]Z÷æ€ß_ãÔ¥±SçÿæÜKÆL™oª™Ô¥;‡ýãµC-^içÂJú¥Ë®rê9ÿpõ ˆ%{IE¿ÅA©)0•’0ýöÊÁ'Ÿ9à–{F©T’0Õp˜â“0M+ L›§”ò0©h.¹ÆÓ¤ùUœ·ZØû û=8büÚM︲ak‡Óû¼ÛÇÃNléÌÁ— 03ìý—N‰î§1™Jþ)-4”í3áö±{ŒÀÖ­[?ùÉOöJcúìg?ËÔrë&4€ @I@cJ: î)AøìºIhLM‚b5Ÿ@oç»”¦Y/¸º>êÙ G]2ÑËÃôzp üÅ÷O^ó³ÆÓʲä;£‡˜pÑsý»àÒ˜4ïLÿKoh8»\¾ÙÒºŒ@cÊXÀjT·h¿Pr˜¾8L[Ý |Ò¼:{Ÿrã¬ßÝ·à¼!s»§ÉÁ7ÝþÐç¿ô•ÓϽdŸ/~寡J]úæw=ê‡'œ~Î@½3jò<¥Îré—FNz~÷Üó„_ž~êÙøÁñŸû¾e{©ä×ÈÀT™Eî‘§æ|æ÷”ÆtÎÅWªÌZ˜ÎpÅO®‘„©ÎDrÎaR¦ûé3êlõ&²1eñ¡ÎI¯éÏG¬jØ žÎ㬫1It’qï§¿Ó—-©SRád¿o¼±W“­|ë»>üè#B€ @è4¦.NãnИÒêTM‰Ñ¢Ý$nQ†¾bÓ$9L•Én,WĨY޼dbe.¹²ÃtÎm³¸xBIcÚÜ_¤b:ëÖÙ‡ÑsýTLº n Îû&S†ºC᫊Ɣý.P¨_(s˜¬ÚZ>¿LUöÓ+¦]ýð å‰ÉÖ¼~çS«Ž8A)|&/ب¸ÊÅwϳDzr˜ž|îÕÃŒ—Ædó*SIB NàOÎ^÷ÕoüÛ˜qã³ß)Ê-°¾¡•™ôSø©Ïìár)Õ\Ðoå= t1ÏXªš*®Ú[ò猛úÜ*yKÒ˜,ñ’\¥ÑSæÉ^š>y7 RMàÔÿ)5‡)i…@~¡V¯^­ø¼[zNàcF'áÏã T;ë¤ýÈÓÒ˜ýEÓ€»ž/M'÷Ц“Ó üþÉk¤1Ý7i›NΗPÍdÚóŸþùwý/Q(7ï ™úߥ19ž5¤1ÝõสÍjcÉý†Ú/©¼%•I³ƒiã†zZ)—d/)Ù’IKnÎ8-+L÷œö¹/î{àw¹î¶ôo9ýÒÊOβ19{ÉÍ÷orõ-è·XŦ» þµlÛ¬¥Û”{éÎG&«Hc’¦&‡I厇'éÏ obe9iLCšØ3‹\MÉœ6KÂäý¦£1µrzâ;¨OÀiLn:9-è¥9âô¥f³1Y&½†®´LR¢`$Bà“Ÿüd &“ËÆ$iÝæ]ÿþÁG‰TžB€ @E!€ÆT”H×h'SƒŸ™¦£1e&Tiªhn§‰w§ê¢dßÔ½Òå›{î¼–¦³Y䟱N“Ý/%a*%Pâ‡Û8kŒnë^©&›Nî˜Ë¦üäSn·ªç.xé–§s˜n>iß/eÑ}W¿1rÐÇã.¥@ ¥NÿÄǧü¿;uȱݮ(È/Ô¥—^úë3.pù~Lš±Yätê¾ãÉUÎ@6iÍO°>ÊÜ#‡IE¦‹R.Y"=•¯Ÿ9ú‚ÛŸs xl>P_BíwÆÏÇ-¹nΆ? ovË“/~£¦w5ã•W¼ôì§>½GEÉJ%—’¿ éÎácî’g,Ùh¥ì4™læâWN;g  I§ž3P¡Ñ´qf­áÕ;d/)Ùáa£M]ÒÂá?8Þ~sÍ^Òäqƒï$^*EPI˜4sÜÉgP±ÜK¿½bð¡ß?Né—ö.å^²ôKw>-hLø—I ›w¾›ÊÆQ)@€ @ /ИòÉÚÆÔ4¾ÒehL]žÝä&q>‚ß ™LÊú0wÙfwÛU÷\-EÄãÓ×)Ç%÷̨r÷¼Ë‡/2‡I‰8sL)ßÃÖ™/lUš¥v¸àö¹º^/“Gà0í÷õE«6Ú¨ìo¿_¶´1“Îþ;4¦LΫtq~¡d2ü› |oÆNàîì­‰än±LgòÛÆ¬4F'p9LÝù¼L½g, Nà’Z¤1Õ“P•HïŒs¸{jï¾ÿAv{ˆõ ¿H`zç¯Ô¢`R¹OïQ΢TILhé”\ùâ—©ÚU ¼1+?Tôc*iÉ•òlq«wœzöÅGüàxM§O9ûbÙKr•®üÀ}O ¤¥a£-ë’ýìÊaÒ{åmʺ$ué3ÿ¸ç˜§—>üd0CÜ•·Üó=£´pó=OXî%û]Vî%9L.ýR¿ß\¤ÄK ô¿îóå3/4ôÁ‰ÿ²Ï—/»á¾_ž~áÁG;nÖKá)äb&ó™Ð˜²{ Pótp“«^/&•«™u‰TLéŒ4µ*ý/­é²+oô5&-“© †fB€ @ hLÉpOÅ^јR*K‰ÒâÜ$nNæ¾b&Óœ¥›Ü7–ÃcÖ [M`R¹øîy|`‘ÝW⇋‚L=“îŒ*ÓÐq«jN'r˜0™2×CŠUa4¦ìÇ»P¿PºGvÒoÎwú©é2:Ož¿Q'ðã.ŸªøÄç_s“Nàwñ®ñ«}‡IsŠo©˜J xüDz!‡ÉNàÙ5™|É LÖåKÓîÎIªZ¨ÈIÒ˜n`L]]©ÚX*¢4%«Êª ÈU2cÉÊ¥W QÖ¥ó.¹Ê².=9c™Ò,©ø‰—ìgWeì3K%0ðíCôï”ç×ÙÌq›£ÉãTä0É^šøÜËg ¸Â"{ã]#'ÌY«"iI¿Ñ7Ü9RåéÅ›k©K*r˜ñÇ&-ùåi^{Lj&30ù ™Ð˜²²¤é" ôI¡ )“¥bÒ«A6¦t5…Ú@¼uëÖO|â½2™þóþûç–¬ iLï¼û7pB€ @è4¦N‘ÍÀvј2¤ÂW©ð] …ºIÜ  ¬}G&Ó7¾}Èì6¹®•Yäv”ç!ª¤ñæ’[Z•‡I÷GŸ^¼ÅÒxL]Xš‰FsÐTf#ªé0ŘL;W-üÓ«k¢üj¾™5ÌÔ7 И²¥ø:í*0™N?ßM!gŠŒ? ¨eÑ›]š},0P«ó0Im©—H¯¦Ã”i“ÉúFH`²î$é>½»¯(‰”ª‹4¦¡÷ñ³+U¼±Š®T1–LZª*Á$q®”g‹s)—,ë’ÙfN]2ɦ³bö’‚hq J)÷R¹”rkYy¦”dË~ ƒ¢iã\ñç+ýj—§›7…\hF9²1eÿLI 2F)c£º¡C‡öJcºñ¶{CyŒéH€ @€@g  1u–oª·ŽÆ”êðP¹4&:B Šv“¸D™ûJÉd:xÖ’õ¦ð-ðÒ\rµ¦ùÁt3*1SM“irÿ£UæÞÔ?JïÑ£÷ÊR*œIhL™ [U¥ ø %“éW§Ÿ˜ÊfL%‹^y&Ð’ÃT6]Á%ä0õH¨1S=“éèGNy÷ÙüÎt›B.ú2©ìòZ ¥Hù‚4¦a£-µ’K°Ö•d/EŒ%%[2'¸¾·TκԤºäÛKN]ªi/ùSÉ6Êß^*ÉÇ”ÎBŽzK¡wÈÆ”òÞNõrF)g¥9E!pà6i2vä£SQ: í„ @€@RИ’"Ÿ‚ý¢1¥ T¡4&ºH  x“¸J™ûʸ'Çðíƒg.~ÍIˆ,„ \ÖôÝaÒ¨ì«Ûþüï|ä@Õs•”Šil¿ý3Ç“ g’S&ÃVUébþB]pÑ%ýNëè2¡x9 SU½Ê ¼â0•¤–Àb©$Òkè0é¾qÇ»>÷…[¦_cŠéݦ1Õp’¼¤JÒ˜† -K©ZT*ç¾²¹ájK¡dK¡|K5R.ÕʺT/ñ’E3”{©¦½d[N¿„Æ”ý³#-È04¦ ª™€þ{ñ•¯|¥¡ÉtÀßY´jcMéOfR¹"÷ Ú@€ @cê0à4o)ÍÑ¡nF‰žÐbÞ$nTæ¾2f\`2M_ôš»ÉZžÈÆ›¼&šÆ£g.¹¦ó0ivÓο¼ÿ·"åa’ƤõŽ¥e’ºd™™^?|æeýj¾¯ulÍÌ¡¦Â)%€Æ”ÒÀô¢Z…ý…’ÉôËÓú÷(2=ÓU&’³,z–H¯4ŘKÌSJÆSN¤×ŒÃ¤ø‡õH¨k^_³ÿ½û« _:|ЬAý§ô×òàùƒ÷º¥œHOËz_Q´Tú Îêéy™ÆäT¤š _ø_{G©w¼X»D °7‰‹™L_ÿÖÁÏ,xÕ L³J7S5Q9 Sõ-ð¶8Lë\¥Å÷ Ò²¡¶üL’™V<6x窅¦+ýíÝ]R—ÞݹÅÙKúŠV(BthcÇ  1uqÇwPä_¨Àd:µùì˜1Àd'pÏ@õ¦Rnž>:LQ‰¨JȤ)Jr•‚ÿ*lY¨eûTÒÒô Ó%99{IëK~êxohz¦1…æ}ëImUÊPøyiL÷ŽŠJ5]¥èôp=qñ¤¥rŒ*‘Šñ–ü9ã*êRJ_]šV™6Ο9.±•vØKNfbR¹¦;+B  ИڑM@ AúÆ€K.Ûw¿¯ÿ‡ÿøL²—´<ð÷W=·dmŒÃ´nË._O°þì€ @È'4¦|Ƶ©V¡15…‰•%€Æ”(þ¬î¼È7‰³³ÞÔÛL¦ió_q÷¿ëÞ/ÍPãß¿mø$ ÉÖKŠoƒ´¡’Ætã]#k®XJQÉIK=ºR­4KžgVwª¸ZÞ’æÜh¥µtJ}üS>z>­È 4¦¬DŠzB )ï¾ÿÁ†­»¢2“’0½ùÎ_›Ú+A€ @è;4¦¾3ÌìИ2ºU©@Án_S¹IÜ>–Ø’L¦¯xÐSsÖYâ‡ÐÓ>æaÊ@û©b¡ 1e?ÜüBù1”Éôӓέi â0ù Lc %L ý)é†;GÖOªTš}µ"*)–K…e¢’+%±,Tª&‰ë‘–*ù–J?¾ {K!í )û'KZ%hLYŠu…@“$3½ñöûJδå¿háwÿ¦\MM~—Õ @€ ´S fuhLY\‘êÆT¤h·­­Ü$nÊŒl(0™¾qиÙ/û9<ÈÔ‘èQÍÞ@cê ­t®Ë/T(.2™N8éÜhΞãuÎ爟ÕdÓο䆚iLe©ZE2!Iås_ÜOS=9©ÊUª!*™·TÒ•J© ýRž!®Ž´”T¾¥øtMhLé<R«¼@cÊkdi @€ @ 9hLɱO|ÏhL‰‡€ 4$€ÆÔ+D p“¸€½B&Ó~ßø·±Ï¾ìîk’‡©€Ý ÿMFcÊ~Œù…ŠÆP&“¤%ßJÁa Q2)”6)øsaO‘ÆtÝ#kåRr©•6Õ•LZêÑ•ÂÆRO¦¥tJKQ¥ )û'KZ%hLYŠu… @€ dƒS6âÔ‘Z¢1u+m+4¦¶â,ÊÆ¸I\”HW·Ó7™p˜ŠÙòßj4¦ìǘ_¨š1ôM&¦("iLÿ©Ý{$$—6ÉËŸ$éÚÛG„)ÕÍ«ä‰Jš®2+\•®JpŸý(mŸ¢1eÿdI ²D)KÑ¢®€ @€ l@cÊFœ:RK4¦Ž`e£m%€ÆÔVœEÙ7‰‹éH;Ídºñž±ûî÷õE«6ÆÌF¤©ˆÞÿÛ…EóJ)«‘ë©7¿Põbh&SM>Æô»WeK %OZ°ioiLCG˜“*“æËOre£2*õ”yÓf µ¥>hLÙ?YÒ‚,@cÊR´¨+ @€ @ И²§ŽÔ©#XÙh[  1µgQ6ÆMâ¢DºV;o}ð¬=þÛ'æ­XÃTänÛ¶£1e?´üBÅÄð×§žö›s.ˆ9{ë#I¨~ôQö;BïZðÖ[oýÝßýÝn¼ÚJà?ü‡OLž±Ðïo¶îê]`z»öÉ»}<ìÄÞ~‰õ!~hLé5„ @€ dSÖ"ÖÆú¢1µ&›ê4¦Í÷f¹IœïøÆ·NÑ¿íùÿué†ëÝ'S‘»GæÛŽÆ”ù~Ì/TL —m»qÎË·ÆK¨t˜j{çÝ¿Åû^|Ú4¦ìŸbiA2И’áÎ^!@€ @y&€Æ”çè6hSƒŸ™¦£1e&Tiª(7‰Ón×Å¢¿ýõ5ï_â0u;쯽ИÚË3‰­ñ Uú¾7|é'Uv¼õv½8“£‡ÆÔ‚¥Ôð+hLIœÙg 1å!Š´€ @€ .hLéŠGWkƒÆÔUÜì¬%hL-a+ú—¸I\ä°åé ·üþ¯¼õîû„nXâ0¹cä¤íhLÙ$¿Põb¨TLº6QÑÂo¿=ã0ùèИ:I-¬€Æ”ýS,-H†S2ÜÙ+ @€ @ ÏИòÝmCc*pð3Ót4¦Ì„*Må&qš¢‘d]|“ ‡)ÉH°ïv@cjÉä¶Ã/TMö–ŠÉ4&-èOßdÒ ‡)Ä ©K©áWИ’;5²çl@cÊvü¨= @€ @ ИÒ•.Õ ©K ÙM 1õ^q¿ÊMâ‚Ä~øÒá*ñ5“ ‡© ]"ÿÍDcÊ~Œù…ªC—ŠÉ%dÒjf2á0Õ$†ÆÔÐIja4¦ìŸbiA2И’áÎ^!@€ @y&€Æ”çè6hSƒŸ™¦£1e&Tiª(7‰ÓÖeÿ{÷_¸eaÃÈdzÿo4\ hLRƒ*ò ä§bò2iÍ?ýù¯äaªÙ¥þúïJðŠ)¯íxwõkoǯS¨O7lûóÚÍ»â›üúÛïwösòn;±³»`ëH‚SÔÙ' @€ @ ßИòߨ֡18ø™i:SfB•¦Šr“8MÑèT]úí·Ûïw;úÑ£µùLZпƒf <°ír¯[öÒ¿òœÜ§k^_Ó©Ú°]t‡Sw8wr/üBEé†R1ù ™: ¶ ®@cê:rvØhLÝáÌ^ @€ @E"€ÆT¤h‡ÚŠÆTààg¦éhL™ Uš*ÊMâ4E£Su‘“$?I[—¨$cÉÒ2¹üL[vm±OÝ;Ó7L7ç‰2L)ÃÁ+W_¨P £©˜B ™²sZ 4&úBN  1å4°4 € @€ 4¦á'½k4¦¤#Àþ@cj̈5"¸I\„N¡¬Ký§ôWK•Éô² Lz _:\隤.é­`ÅÄ&^È04¦ ¯\u~¡B1¬™Š‰„LÙïé´ 4&úEN  1å4°4 € @€ 4¦á'½k4¦¤#Àþ@cj̈5"¸I\„N!KI®’ZªK–ŠÉågÒ²>•ç$uI úTeì‹cm5^È04¦ ¯\u~¡B1\¹c¨˜X¶äï^öY÷§>Ê~Ài<hLt‡œ@cÊi`i @€ @ AhL ÂOz×hLIG€ý7&€ÆÔ˜kDp“¸ÂÍçr,ÉR²eKÂ$«ÉĦ]ÝesÌ¡1¡cä¼hLÙ0¿P11|xùgõ¿ì™@ 4&ºFN  1å4°4 € @€ 4¦á'½k4¦¤#Àþ@cj̈5"¸I\„N¡‰ä”‡I-U¾%×^½£¢»ç^6l(2Úž[hLÙ-¿P11DcÊ~§±Иè 9%€Æ”ÓÀÒ,@€ @€@‚И„Ÿô®Ñ˜’ŽûoL©1#Öˆà&qa;…¦#~pìøK¾´ï×0™ Û òÜp4¦ìG—_¨˜¢1e¿ƒÓ‚XhLtœ@cÊi`i @€ @ AhL ÂOz×hLIG€ý7&€ÆÔ˜kDp“¸˜BÓ‘?8î…—ßX²ö§¦/þâ—1™ŠÙrÝj4¦ì‡—_¨˜¢1e¿ƒÓ‚XhLtœ@cÊi`i @€ @ AhL ÂOz×hLIG€ý7&€ÆÔ˜kDp“¸€"p˜~xÜÒuošÆ´è¥×Ç=ƒÉTÀŽ÷&£1e?ÂüBÅÄ)ûœÄ@c¢ƒä”SNK³ @€ @ @cJ~Ò»FcJ:ì¿14¦ÆŒX#B€›ÄEëæ0-[÷æÒ—ߔô¸¤1-\óú¸§1™ŠÖòÞ^4¦ìG˜_¨˜¢1e¿ƒÓ‚XhLtœ@cÊi`i @€ @ AhL ÂOz×hLIG€ý7&€ÆÔ˜kDp“¸PBÓQ?¨ôÒ:öÝéÓ§kaÿý÷×.\ÿÝÐî´²¾¢ïê}½úõëçªÚpS}éÚ×àÁƒ}½ÚÕYíÕ¿j~_jRôï¢1e¿ð C4¦ìwpZK‰’ShL9 ,Í‚ @€ $H)AøIï)é°ÿÆИ3bn¤S˜Ã´bÃ[JÅTšQî F¹@cZ½sÞªsWîxbÊÂÏ7m29s(ªÉÂÑË›LHŠî4&SÜŸkÖ¬i©šu;v¬}Q“™LÍl*~_²‹¶lÙRo³¦Ü jr¯4&g/é[Ñ5„À =И²ßø…Љ!Sö;8-ˆ%€ÆDÉ)4¦œ–fA€ @€$€Æ” ü¤wÆ”tØchL±F„7‰‹Ð)ÂS%“?£œR1=_Ò˜ž[±}ääfM&ól”:h·Ýv eZ’Ž# ɽ)ŸI‘Ó˜´lÉ™L÷‘dê}ËÆ¤e}Å” û®éGÒ’lM'Hõïßß¾•~ôŽSˆvíÚeJ“mJ “´Kzä6eÖ«Þ¾¬·¸Úú’–ëH–É5ÜiLnãúº*ã²CùMÓ}ç ©O‡'SŸð¥âËüBÅ„)}”JtŽSçØ²åD  1%ŠŸC€ @€rI)—am®QhLÍqb­$  1%I?³ûæ&qfC×lÅ=‡é­eë{¦“[¼öE/½^žQ®”Š©¤1mŸ³bûìåÛFLZðù/5ž].>“ŸOHZ,"Ó˜œ„$kÇÞ1ßHrÉOöŽþuÙ˜L’¤­fѵ‚ù@æ<… Ø›¶M—„É6¥wlS®’nS6­[t_¡kƒ&fY…ÝË©]6µœÛÕÓv'yKïë_½ô§L,k‘Ÿ)JëÛû¼Z$€ÆÔ"¸}_¨˜` 1¥¨§R•N@cêU¶™hL)U€ @€ äŒSÎÚ›æ 1õ†ë&C)îß+7‰3ÀÕw“7Ü›/ØŒr/½¾h4¦ó_Üé§bš³<Иž]¶íñ‰ó÷id2…4&Y8Òt,Ÿé;rq,e‘Óƒ´ìûF¶šËÒ¤•c4&Khdn“e`ò§l³XüœF’ä9[ÈyEN?²/†f‹î+ÊÚ4,—WÉV°Ö™Ÿdº’5Ð)JªŒ 'ý«¯ë¥W· 7^¾ûgg[‡ÆÔY¾ÝØ:¿P1”јºÑÙG‚И„Ï®;I©“tÙ6 @€ @ ˜ИŠ÷R«Ñ˜ üÌ4)3¡JSE¹Iœ¦h´¹.5&:¹ú©˜ä0ÍZºmæÒ­Nh`2…4&óŠLÙqù“,÷’M—f)ˆœ´¤‡4&Ë“¤÷kfcòÕ"-KòÝ#›ÇÍæ‰Ó¿Ê´dùì¥?m›Qɾ£1پܦÔsô¯MŠç¿›ZÎ5Эi–™‰e¬”YÊס˜N® S &¼ ~¡b€Æ”pïd÷&€ÆÔiÂl?!hL g·€ @€ @cÊqp5 ©!>OžSò1È` ¸IœÁ 5Ue.¹åëß\¶Î›NNy˜œÃJÅTšQ®¤1mñÂÖéK¶<<~Þçêçdj8©œêjb“ülL–-ÉOYd­’£1É…r®V³?M0r–’OGÕS*&{Çí½žÆÚTt_nËfeÕ ƒo ITÚm·Ý´k-8Êef² ï¬ÕZÁUµ©³RChL ¥~~¡bB„Æ”úþKûF©oüøvj  1¥64T € @€ YhL™ ]ß+ŽÆÔw†l¡ÓИ:M8—Ûç&q.Ãê9Lo.3‡éåÊ\rkß0‡É¦“›¿zç¼U;æ®TÙ>§Ça R1™ÆôÌâ-=ùü羸ßË/¯²ŠÑ˜l9}Å-˜Í£ù:–0Iÿšd³³Yv¢š“Ûš%|ÒŸ¶)½ÜŸ~’'ûH)ŽL¢²—ÕÇ6e)‘lµÐ¦\­¢ûj¦·ø“yZÚå ²& ˆmGÛw@Bé—ÈÆÔ êë 1µb›à*&hL ÷NvßihL&Ìö"Ð@cÒÝÔÈ–wÔ^~^ЄjÎn!@€ @H+4¦´F¦ õBcêdvÑGhL}X̯s“8q7‡I˜\¦ÑÏnøéÓ–¬}cqÉaZTr˜”¦ã/Ÿú| 1mnÅö_]7ãð‹'>@eücÓ×Ó’-O/Þ2mÑæÇÕ5™20:õ[&ªM%ûD©OøRñe~¡b€ƔŠ>J%:G©slÙr‡ 8?^ûq.»dœq“&Kãi5ÔŸ²—ô§^Ê;Úáj³y@€ @€2K)³¡ë{ÅјúÎ-tšS§ çrûÜ$ÎYXå0ùÃã,“›HnÔ³ŽºdââÒ\rÎaš²`“¦oœ5F©˜ä0)“¦[G¯>å¥&¿äR1=½hóÔ…›§,ÜôÀ¸¹{×ÉÉ”3†4''И²H~¡bbˆÆ”ýN b  1ÑA2H@Þ¼&?§¦ì%%5ÉTWc’±¤L¡.}¨V5õÉ}3ƒ@¨2 @€ @]!€ÆÔÌéÜ S:ãB­|hLô‡p“¸h©ýJà0ýà8³—T^xù %a5kÑ'º¹ä,ÓÉ×ϼaÄ2iLÏU¦“S¦'Ÿ{õ)‡©’Š)Иlš<Óýcçîý…ڳ˥– +.4¦ìÇž_¨˜¢1e¿ƒÓ‚XhLt Pî%M”Ò˜ä6ù&RƒIå|I² ‰ý73ˆ…*C€ @€ ÐahLœæÍ£1¥9:ÔÍ 1ÑZ ÀMâ ¥ó+æ0SÉ^2)˜Hî¥×GÎ\/i¡7—ܼÕ;JsÉíÆ¤{ù¶g—m1cý̶j:¹3n~ö77?ûôâÍÓlF¹R*¦IóÉ™Lc枣ÎC) —ßx$…‡@*¡1e#Nqµä*†Sö;8-ˆ%€ÆDÉ,?“&…³vô/½´Ð i×®]‚¿ÑÌ’¡â€ @€ t†Sg¸fb«hL™SÁ+‰ÆTðÐZó¹IÜ·´}ë ƒºížÇuɳ—$0- 20IcZwäÀ e‡iU9“æ’{nE 1™Ã4kéVéJr˜”‡é¦‘˽h|ÃTIÅd“Ê7¾{ÄqÿÃÐùÿ“~)E# y"mý¿v}И²§¸Zò C)ûœÄ@c¢ƒd–€o9É%TjVc’å20 J! ªÔ9Yú¡Acê\?èÖ–ù…Š!ÆÔ­nÈ~"€Æ”xvÛwNc’}Ô¯_?Û ô§hLÒ•Ü\rJßš‘®ï•c € @€ äSƒÚl“Иš%ÅzÉÈÒÝåä(±çnç¦K˜ÉtËÝ-\³SÅ&ËÀôØô—•uÉ•ãþ8Õ&åa:àÌ1ÊÃ4si0—Ü1—M9lÀøÃ./©j:¹ùå$L!‡ “)7§ù†d釩ù¸¦uM~¡b"ƒÆ”ÖnK½ÚD©M ÙL÷ øÙ˜d%™‰ä|¦S´º[¶lé~Ø# @€ @Y"€Æ”¥hµ¹®hLmÊæ:@ Kw—;Ð|6Ùn·Æ-ß*›Lw=fö’ŠËÀôüªsWî°‰ää0I`š½¬<—œ9L3–ÓÉ=³xËÓ‹6×›NÎÏÃd&S:{Bçj•¥4¦Îõƒnm™_¨ÒhLÝê†ì'!hL g·&Ðk©Óbû€ @€ džSæCØzИZgÇ7»E Kw—»Å„ý4$ÀMↈ²µ‚™L7Ýù¨æ³)äL`š[˜, “&’+Í%WÎÃdsɵæ0Õ3™nY˜-tÔ¶Yú¡Acj&¢é^‡_¨˜ø 1¥»óR»>@cê3B6NhLéŒ µ‚ @€ d™S–£×Ǻ£1õ _ï,Ý]îvÑn7Ç)KkÉd:òÈÀd*ÛKÕ“9L³ÌaR¦‚$Lu¦M“æ•§“«—‡©^N¦5¯¯ÙÿÞý³Dº6G K?4hLÍÅ4Íkñ 4¦4w]êÖhLm€È&ÒH)Q¡N€ @€ l@cÊvüúT{4¦>áãË]!¥»Ë]ÂNš!ÀMâf(enwÿò—ƒ9ü†Û±)ä,S( “s˜ž åaZ¸iò‚M“æ÷ÎaÚòÆ_>üè#µë¯»úOé/iú†éƒçVZ¦A³éMýk+HrÒGZпzÓ½Ÿ9άp–~hИ²ßAù…Љ!Sö;8-ˆ%€ÆDÉ)4¦œ–fA€ @€$€Æ” ü¤wÆ”tØcYº»Ü¸5¬Ñ%Ü$îè®ïÆL¦ë‡>˜\¦K‚8LÖÐ~cûI`’º$™éèGûâØ-»¶¸üLò–ô©ÞÔ;’œ´¬uºNˆ¶B K?4hL­D8]ßá*&hLéê¬Ô¦íИڎ” ¦ƒS:â@- @€ @y"€Æ”§hö²-hL½Æê ÈÒÝåð°ËÚ¸Iœãža&ÓuC¶)äz&"¹Å[$0ùS_ò09˜ò“”rIêÒ^·ì%™Iï+ñ’Ü&[Áì%[ǽ“ã@ä©iYú¡AcÊ~Ïã*&†hLÙïà´ –$§ИrXš@€ @HS‚ð“Þ5SÒ`ÿ déîrãÖ°F—p“¸K Ú™L×yئSQ¦h¦© 7Y¦¶8Lj«ì%ýë«KšfNY— ƒ>•À¤•„É•„±ÛÞÈÒ Sïb›Æµù…Љ S»,uj#4¦6ÂdSi"€Æ”¦hP@€ @€@> 1å#Ž-µ©%l|©«²tw¹«`ØYn羘ÉtÍm—¦òDrA¦r&s˜4‘Üü“æmœX*ß=ìGWß0tí¦wbÊ–7þòáGEZ¦%½o“ÇÙ –I ×ײ?Çœl'­™û@ä£Yú¡AcÊ~Ÿã*&†hLÙïà´ –$§ИrXš@€ @HS‚ð“Þ5SÒ`ÿ déîrãÖ°F—p“¸K Ý™LW ~è™Å[žV©LSn–Àä&˜úè0©¡Ò•”iIr’?mœ².)!“+ZMïhš9½ã¯–('vÞ˜@–~hИÇ3íkð !4¦´w_ê×GhL}È×ÓJ)­‘¡^€ @€ ì@cÊnìú\s4¦>#d'¥»Ë‡Áš%ÀMâfIe|½²Ét냖)˜ü‰äæ—¦¾;LÆI&Ó®¿îÒÌq>6½©wô¾Š[ÍR4ñÊ ,ýР1e¥WÕ¯'¿P11DcÊ~§±Иè 9%€Æ”ÓÀÒ,@€ @€@‚И„Ÿô®Ñ˜’ŽûoL Kw—·†5ºD€›Ä]‚ݘÉtÅ-:É&’sI˜Úå0¥ ­T¡S²ôCƒÆÔ©^нíò é{‘=%B)ìì´óИ:Ϙ=@€ @€ŠF©h÷Ú‹ÆTààg¦éYº»œ¨ù¯(7‰óc¯…f2 ºåA˜&Uf‘kË\r…"YØÆfé‡)ûÝ”_¨˜¢1e¿ƒÓ‚XhLtœ@cÊi`i @€ @ AhL ÂOz×hLIG€ý7&¥»Ë[Ã]"ÀMâ.NÍnÌdºü¦á~&ò0¥&>i¯H–~hИÒÞ›×_¨FhL;kdšS¦ÃGåë@c¢w@€ @€ ÐnhLí&š¡í¡1e(X…­j–î.6Hék87‰Ó“Ž×ÈL¦?z&ÓwûÑÕ7 ]»é˜²å¿|øÑG¯;H7,ýР1¥»/5S;~¡b(¡15Ó…X'ÃИ2<ªG‰þ@€ @€@»  1µ›h†¶‡Æ”¡`¶ªYº»\Ø ¥¯áÜ$N_LºQ#ßdÂaêñ¼ì#K?4hLÙïuüBÅÄ)ûœÄ@c¢ƒä”SNK³ @€ @ @cJ~Ò»FcJ:ì¿1,Ý]nÜÖènw túv˜LßùÖ—ö;#d€ @€ „ 1¸K 18ø™iz–î.gjþ+ÊMâÜÇxñ=ƒ&÷?ú¥ñã-yY?÷¦o2á0å¾W´ÜÀ,ýР1µæÔ|‘_¨˜P 1¥¦ŸR‘Î@cê W¶š84¦ÄC@ @€ @¹#€Æ”»6ß 4¦æY±fR²tw9)Fì7B€›Ä¹ïcûíÿîÎ-Ñfn^8]z“ÿ¾™L8L¹ï}i`–~hИúét|—_¨˜8 1¥£“R‹Ž@cêZ6œ,4¦dù³w@ÿöþÚ®ªÎ÷ÅwüÇ{õÆxï¾úûƨÆÒ²¼—ûêë^ %jÔÒRA!TÙ ¨h”^ÚУ ,A1ôBГ„.}K’œä¤O šä¤%A"RRHþßµ{ϳöÚÍÙ{Ÿ½ÚùÙcŽÃ:{¯µæœŸßÜk-2?ç7!@€ "@c*bT[ìS‹ Ø-Eyš]NUW`’¸À#â­7.þŨGF¾öÑ1ê¦2)3“më¥m•Èû2™T´>zeÞäákÈÓ©³gé(îPM¢Æ”¥¡J[b €ÆTN™hLYˆm€ @€ ‹S±âÙVoИÚÂÅΩÈÓìr*€¨´&‰‹=.´lœL¦×~Ó§ŸÚÞ»¾GŠ’%aR–&ý*·ÉÞ×O[cNïk½£ el*6z×.<ÝhИÚnööçÕ$&hLÙ°´¨«ИºŠ““e‡SvbAK @€ @E!€ÆT”HvÐ4¦ qHÂò4»œ0ªkL€Iâbs•ÔGû)ŸIÞ’ÞÔ¶²4é§Œ%ýª÷ݧ&3é¥lL–®‰<ÝhИò?p¹C5‰!Sþ8=hJ‰RPhL ,Ý‚ @€ ¤H)EøiWÆ”v¨pyš]¼7ì‘&‰R5æ*é%WII˜¤%ÙÏ7öö›Ì¤—‰M–¢I?mÛŠ[.¥æSmæäéFƒÆ”¹áÓvƒìõÆ[;Û>ÒƒИ<²ß]Dcò;þî=SƒK× @€ @)@cJ |ªEcÊBhCsyš]&–™!€Æ”™Pt¿!ÎU’·¤Eå¬ÉIZ*NEY—”„Éå^²¼MúUV“í©í·Þ8ØýfqÆ<ÈÓ)Ï#ÍÚnw¨ü÷#– 1Å‚•“f‡SvbAKºJ€»ZWqr2@€ @€DÉãa€ÆäqðsÓõ<Í.çjñŠÆTà›«¤jy8YJ’™ô«ò3IW’Õd™–ô«¶õ‘vö¤CôŽ%mr†Sѵv äéFƒÆÔnt³·?S“˜ 1eoÀÒ¢®@cê*NN–hLÙ‰- @€ …SQ"ÙA?И:€Æ! ÈÓìrÂh¨®14¦åRré””xIö’:« ÷Óú®÷í#{IfÒ¯¶/DäéFƒÆ”ÿá‹ÆÔ$†hLùàô )4&HA  14°t € @€ "4¦á§]5SÚ þÁ äivyðÞ°GBИM5(<ÝhИò?äИšÄ)ÿœ4%€ÆÄ)(4¦‚–nA€ @€R$€Æ”"ü´«FcJ;Ô?8<Í.ÞöHˆSB ©… § Sþ‡S“¢1å€Óƒ¦И %€ÆTÐÀÒ-@€ @€@ŠИR„ŸvÕhLiG€ú'§ÙåÁ{à @cJt6«Ù·õPßœCo½™ÍÖѪ ÈÓ)ƒ¨Í&¡15†ÆÔæhb÷¼@cÊ[Äho‹ИZÅn€ @€ ´L©eTÅÛ©x1-^ò4»\<ú¹íSnC׆?}õ!MJfâÖäéFƒÆÔZL³¼S“è 1eyèÒ¶.@cêDN‘EhLYŒ m‚ @€ ä›S¾ã7¤Ö£1 'B O³Ë‰¡’V 1µB©°û 16´qu,O74¦¸FArçEcjÂ)¹HM©@cJ;•ÆO)~ÆÔ@€ @ð“oõÉãàç¦ëyš]Î Ôâ7©ø1nÒC4&¯ÃßIçót£Acê$ÂÙ:©I<И²5XiM×  1u)'Ì4¦lÄV@€ @€ŠD©HÑl³/hLmc÷äiv9O74¦N"œ­cИšÄ)[ƒ•ÖtSבrÂl@cÊFh @€ @ HИŠÍ6û‚ÆÔ&0vO@žf—SÀC•õ  1y=2И¼'ÏÓ©“gë4¦&ñ@cÊÖ`¥5]'€ÆÔu¤œ0И²Z@€ @(4¦"E³Í¾ 1µ ŒÝS §ÙåðPe}hL^ 4&¯ÃßIçót£Acê$Â@ И²ZÑuhL]GÊ !@€ @Þ@còx 1yüÜt=O³Ë¹Zü†¢1?ÆMzˆÆäuø;é|žn4hLD8Ícæl“fõ®»ÿ`ÿÁ?Ìpib €ÆTN™hLYˆm€ @€ ‹S±âÙVoИÚÂÅΩÈÓìr*€¨´4&¯Ç“×áï¤óyºÑ 1uáÔŽ³t̨é£R«>Û~ëáÙn ­ƒ@ Иb€Ê)³@) Q  € @€ b@c*V<Ûê S[¸Ø9yš]N•Ö#€Æäõ¸@cò:üt>O74¦N"œÎ1ÊÃ4â‘#'TÎ!ùL=ý=£ç¶mkÐä“-‘öÔG*é44ZÕYiLB!â0~ÕxmÛ¯Ö½czS;kŸ4šIè64¦nå|!€Æ”‘@Ð @€ @€@ 1(˜ív©]bìŸ<<Í.'O‡@còzh 1yþN:Ÿ§ S'Nç9Ãîfþ6¤4™¯ãò3é;}}zS’œäëhŸtÚšx­ê¬/u_@Ô}‰Jr¹´a  C¡wÌÓËó%%*ŒS P9e 1e! ´€ @€ P,hLÅŠg[½Acj ;§B O³Ë©¢ÒzИ¼hL^‡¿“ÎgýF3ÿžC³n)—sþCgü§_õþ:é3Ç$BÀÖMë?د Ë3$‡Éå²OMf²æ8'‘Ö¥Y‰8XV*ÉL. •ë¾å¦(}j­”ìåU¶ª4cCݱ@cŠ/'OSzì©€ @€ PThLEl ýBcj»¤L ë³Ë)ã¡úúИ¼hL^‡¿“ÎgýFó“ÒÌwÝ"«‰WV X!µNi„œŽã¤%ûT“d&er%«½ér»,•Nª i^FÉ%£²Oõ«e±²âãërS8’$€Æ”$mêJS‚°© € @€ à 4&O]¯›hL?7]Ïúìrn@úÕP4&¿âé-“×áï¤óY¿Ñl_ÕPczê²N:Ì1‰°”BªJ?‚c˜ô’ؤŒD2x\ "y<þ$r܆ÃeÉ« ‘Ë\¥mKgÅ ù&€Æ”ïøÑú†И€ @€ t›S·‰æè|hL9 –·MÍúì²·ÉvÇј²Ÿ˜[‡Æ3àâ>7šº ™HÅ”í±(/G9„$ß„—“ £÷%0é#yKê6Li ï–ížu¡uâ µËR.Ùéô«¶MfrY¬ —!êB­œ©@cJ=4 hLñp嬀 @€ Ÿ  1y}4&ƒŸ›®ç`v97,=j(“GÁ®í*“×áï¤ó9¸ÑÔMÈD*¦N¢è1¶nšVŽsµ*ÕÞÔÏð›zÇöôç¥îpŽ%ÇÁÁ1\aVþ ¢§Å$€ÆT̸ҫChL @€ @€ºM©ÛDst>4¦ËÛ¦æ`vÙÛØd¸ãhLNüMCcŠŸqÁjÈÇ&’‰TL…tð“Qö²hL^†NC€ @€b%€Æ+ÞlŸ)Ûñ¡u|Ì.«Œ@cÊX@’mS²¼ P[>n4‘„L¤b*ÀÈ£ €€oИ|‹¸7ýEcò&Ôt€ @€ 4¦ÄPg¯"4¦ìÅ„E äcv™¸eŒSÆ’lsИ’å]€Úrs£q ™HÅ”ça÷ú¿oÝñúœ<÷ ƶïþýâ}oôÆX§†@ºИÒåOí±@cŠ -'† @€ xKÉÛÐ:„ÆäqðsÓõÜÌ.熨 Ecò"Ì:‰Æäuø;é|nn4.!©˜:‰sVޱ;TVZ“±vLXó^}3Ö(šî@cêKΔ)ÜÕ2@€ @(4¦B„±³N 1uÆ£’$›Ùå$¡P×`И#TèÏј Þ8:—§2‘Š)ŽAà9јšÀFcJp$RUИҠN @cJ2U@€ @€<#€ÆäYÀÃÝEcò8ø¹ézžf—sµø Ec*~Œ›ôÉëðwÒùÝhz§=6ö‚;é$Çd†ÀÓ/ž÷Õ ™ð­Ëï|÷/'™™XÑt›S·‰r¾Œà®–‘@Ð @€ @€@ 1(˜ív©]bìŸ<Í.'‡@còzl 1yþN:Ÿ—Mooï‘GóåO;vl'ýä˜ غu«‚xò©g\}õÕhN¶š0eÊ”O}ö‹â£¡ž­–Ñt‹S·HržŒ@cÊX@h @€ @ И ÄN»€ÆÔ)9ŽKŽ@^f—“#BM-@cjRqwAc*nlcêY.n4%‡iØ +¶ônzõK˜L1 …˜O[r˜†=?·WA<ý—`2…yËaúôg]²®þò-ÂdŠy(rúÔ 1¥†žŠã%€Æ/_Î@€ @ð‘“Q/÷Éãàç¦ë¹˜]Î MoŠÆäM¨ëuÉëðwÒùìßhä0}ø¨a z·®Üüª ˜å/íÃdê$Ò©#‡éÃG›2o¥ âiç`2•CbÓÒu;5¼WlzunÏËú9™R¯T4¦˜ÀrÚ´  1¥ê‡ @€ SñbÚrИZFÅŽ©Èþìrjh¨¸14&¯G“×áï¤ó¿ÑÓÑÃön]µy¿IÒ˜zúö7âë¬.×I¼Ó8Ʀ©óV*ˆÒ˜\¿ÎÅäd ¦Ï»lýÎU%KoÅKû–÷훳l3&SC•:c&€Æ3`NŸ4¦´ÈS/ @€ @ ¸ИŠÛA{†Æ4("vH@Æg—SçCê@còz` 1yþN:Ÿå9L‹Vn]õr ¿8É£§oïÒ{1™:‰wâǘÃ4mþÊÕ/ï›:ÄïíµÉ$‡é3r˜6쌌ðe÷ÎZºùƒädJ|¸Ra¼ИâåËÙS#€Æ”z*† @€ –SaC;xÇИgÄiÈòìrÚl¨¿!4&¯“×áï¤ó™½ÑT¦WVoÙï$KÅ$Éc醽K6ì9vÄ×ïºçÞv»=f̘ѥWOéå·7ÝK»é#ý9ínsæÌiå̓êTýýý¶³6Úmyîö/;L/¬ ÑAÜQ&ÓåWü°Ý®¹ ~8ˆ:O__ŸÖFø´ãÇ×›V½Ü\ìt*½o»ég»Mjws˜z6ì ¯Š¨á3—lúà‡Y²ly»gv= põ×:h/më•:„v»Æþù&€Æ”ïøÑú†И€ @€ t›S·‰æè|hL9 –·MÍìì²·ÉEÇјr¦¸‰ÆÙž7›7s˜¯zeÍ–ýY|*+Ê•5¦õ{¯Ûsì m›LÆ 1b„©ÚÖË¢{øá‡5*¢1éÍHìkws“ûÈìýÖ›¤1I]Ò›RdôÒFij)Ø sS%ˆU+ʹ ¾¸~ÏȳFµk2…ƒ¨hº *‚ÚvÁ9r¤QÕ›ÚÖûÚAä‹‘ýjû+ŽúU»ÉþÑOwlq1‡iùÆ]‚S•Š)õö‘™ñ¢L¦µk2…‡¨uÜ„<ërºâË93M)Óá¡q@cêœGB€ @€ PŸ“Ç#Éãàç¦ëÙœ]Î >_ŠÆäkäKýFcò:üt>ƒ7šÃt 6‹-F¦,>’<¤1-Z»û‹Ç·g2E|³[ÄNòG$¯½ÁZw7Û'ü‘9R‘c-Ó½iI'1ËÃ1r˜>¢µä^XµfKý ÊÔ ñ»g¶g2E‚¨_;yHæúUÌõQø}¹J.'“> ‡XF”£[ún;LáTL‘Цɇ’ç¬#u5&ëQ*º“óä‰Sž¢E[Û €ÆÔ,v… @€ @ %hL-a*æNhLÅŒk±z•ÁÙåb.foИŠ×{…ÆÔ"(v«ÈÚF“ô—W½²vëf©˜ÊÓî…kw/X³ë Ç­õÕå">‡s_ИÂãNÆL+—¥2ÒÍašþªPƒTL½‘|ZÕAüN;&S]Éi®×"lf’¥\ªM1xܵFT·H†¦Á+¼f¢Yzë‚>uQ_[&Ó5¦ t &çÉ4¦œŒæ¶J©URì@€ @€@«ИZ%UÀýИ ÔÂu)k³Ë…\Ì¡13®-ö ©EPìV!©M‡éå²þb‰jjS1™ÆôÂê6L¦ˆãRõHþ¿\ЦÈ`©»›íÉÆtØa‡…wŸÇ-õU¼‘Xv˜„¦š †—T>-ÄïœqQ‹«Ë  ØÚš€ne@mLž<9ŒÔW«ÈIr²p„W‹««1é$Mrn %dÎaª+xÕákv/X½ëù…}GÙêêr2Ê>¥6·žÉ:„¡äØ|@cÊwüh}ChL @€ @€ºM©ÛDst>4¦ËÛ¦fjvÙÛ(ä®ãhL¹ Y7ŒÆÔMš^œ+;7šA¦p¢šê,>r˜æ¯Ú5oÕÎϹ¥œL©gcRŠ °IS¤qV'“s˜¤b 4¦’©3uÄS[3™DÙ9’ôr9–êfcŠ,3g>“ã_Wc²%꺗:STðÚç/[QÎ ^óWí|î…VM&iL¶”ž^ê¯uDY©Â‹†×4LBשrÂ<@cÊS´hkИڀŮ€ @€ ´D©%LÅÜ ©˜q-V¯²3»\,®ï SÁܼ{hL^‡¿“ÎgäF#‡éÃG[^K®®þ²qô'œÅG’ÇÜ•;çôö·b2E4&ç¾$¶¨œ,Ó«“heû9L â4·–Ü–ý«*A´åäÂÙ†–„M³|Z ⼕;çöîüöéƒçdŠÑÀÈ݉HK¶rߘ1c"˜Ünu ž°îÓ-äƒ8LÎÒ‹Œp ^8áÏÌߨJN¦º#Y²´Löa±íÄ t &çÉ+4¦¼FŽvB‰!@€ @€@·  1u›hŽÎ‡Æ”£`yÛÔŒÌ.{Ë?§GcÊiàºÓl4¦îpôè,Y¸Ñ8‡iÍ–k¶ì_ýr•þâ–“kœ¨&ÈâcÓìýÿü¥¯ÞuϽMB(…Å2Óè%™Ã-’?äyØû.WÞ¬}§v7«.²¨\äX§.RcŠ:L¥ ®ÚüêÊͯÊajÄH*&ÄovaóÕåêjL ªàŠ°ÔœHpõ«Þ4ÕÉ­=—ŒÁã¦Ú¾¢’¤ÊL\ºaoCÁ«4Ÿž·ñ?ôÑ%Ë–7áu5&¥e²©.kkÛ%jJ‚GWUºÚˆc£ ј”3ðàÁƒ®ïúU×b—H° Lè @€ @C#€Æ44~¹>)×áó¤ñY˜]öu‘º‰ÆT¤h¶Ý4¦¶‘ù~@L7š}o¬j‘lÈaÚÿðìÍ?·lɆ½æ¾¨<÷âotßÒž¾Êb[öŒ›Ú·x])ÓšÝÏ-þ͵÷/¿ç¹ –Ågvoÿ¬ý3—ïø\S“IIhœ™$©Åµ3¬+9)ò¦v®»›D¹™J™4‘=ó§1ýng‹AtS`¡•D´kÆ-›ÛÛoA”ÃôÓ‡z¬Ù]Ñ6ì¹ãéuå ® ² ýì‘•7=²Ò‚(SÇ‚øÍ¦&“‚Ø(£•b*MGÒR8¸êˆådÒGá¯ÚÜK-ecjNÈa*ÃQOozxåÕc—=8s³KRep&/xEŸj99áOÎßrù=/>>wKYð*Á™4wCs“)<Ô·¤Ìás“vèB‹ãƒÝ `И ¹%àäWëî#º§¸ i3I;…W*uWá°Q›[,4€ @€ Ø 1ņ6û'FcÊ~ŒhaL³Ë€-64¦bÇwÞ¡1yþN:Óf\ïŸ_õW/¿úHó6™Ã´håVç¾ ?² §¿œqóüáçM Òb[§ý|Þ•¿^²hÝî…kwßûüÆ/]þüew¿8ògspë –ŠiÖò2`fôlÿÜqƒädê–oÇŒ;õÐχê›Ó¼ße‡iþJ b) ÓþáçOúæõ3]¦ã¯œòØÜ—-ˆ£Ç¯øòÏ[/ñÜ[œ{ë Ç]þ\$ˆßüþ 9™Ò ˆþ/R|ömmÞ9LŸþܱ=v:8c&®œQw,úÑØegÜ2_d”‡É¦i˶‰Ìó6Û‚‰˜NúÉŒËî^,2¿|rƒ3£gÇSsÖ¿°œLi¡nÔ%€ÆÄÀÈ'IKÊ`çÚ.Ô–£uiíjL²Ÿ¤+…Sä¹)SD¶Í'Z @€ @€@<Иâáš‹³¢1å"Lž72¦ÙeÏ©¾ûhL…q³¢1yþN:ÓF“´TšÈLæ0-”ÃTq_®·ìÌ[æŸpÕ[ikyß>IŸ:gËO'ô–^Γ³Ö¿ÿƒƒ¬.—*†@]hL ŒP?3‘¬íRš¤1Ù¶$%Kï×Pc²•ã\6&-áiI˜ä@á0åp0Ðd@€ @€@‚И„µªÐ˜²ÚSK ¦ÙeP›S±ã;HïИ¼'éFã4¦F2Sà05lAïVKÞcî‹–ÙR‘º4kÅãg¼tám %vH™¿rçÔ¥Ûä0]!iMYò?ý¥ËîZ|͸žHiLS—nŸ²d&S'cÂã4¦2Sà05lʼ•á Z&-É:Ͼø[eÒ’“¤TCÒ˜³yÉú=ÌÞüð¬Mòu,ˆrÑ´& ‚(mÒ‚­á|Z.ˆ'/“&“Ó˜ÈLÃôÙc—®ßY‚ o•[ŸZXz%‡Iv—ò0)s˜ðI ^ÑB{"hLkv?4s“àüê©5‚sã„•¶Öž’W‚WÏöiÁßöÄÌu˜LCáœ04¦„S]7˜¨ä4&[.ÖV§uK”6[TN‡5¦Ã;LGšÏÔÒ ¦Ýèç€ @€ @ Иò³®µ©k(9Qlbš]Ž­½œ8И2†´Æ”ùÜÖÓ&¢1Ed&9LGuÌ‚[Ìí0ñEåGc—ª(?Í õÊðP–šÇæ¼Hë÷¼¸~Ïâu»å0©Hyau«FËÉ=0í¥ïÞ4çk?ž.ói ‹ÏÒ@òÆ„É4¤јªe&9LGÊašÛkAtq”££"IšÎ ­8yôL%Óú²4¦Ù›-ˆÒt¾tÅóD™:Z1íîg7\3vÙ'ÎX•Š)Ä,šL©Zf*9L_\²®¿v„kx[†*·–œFx‰L'ИfnœglúûoMä.D—ܹ8:ÂKÓiH#œƒ&€Æ”0pªë°Æ¤m¥RRN%m ’ÉÉÆdošÉÔ½r&@€ @€ŠE©Xñl«7hLmábçTÄ4»œJ_¨41hL‰¡ÎbEhLYŒJ¦Û4qãÑæ%Vn›ó®÷¾ïðùË·8{IKÈY~9L?¼o鳋£ä=Jásòu3•¥¦"yìÖ2dr˜´™ô—ù«I+‘y˜zû?~îIJÃTITc“•#?:|Òÿ¬¼˜é&”¡xóÆO(ˆÏÍí­ ¢­•¦-WŽ=ñ›·|<Aì½ñäÿuÄ‘KÖö×Âùå“k”l¬,0mÜ«µä´Z¢F¸9L‚#2ÊÃ$8ã§o’½d#|Ü´>Á ¯µç,=3™Þ÷ßÿ¡oÓæL_hhD‰a[aIËÌY?,3“6ZÍÆ¤5æÜ‰Ð˜r;h8 @€ @ hL‰`Îf%hLÙŒ ­ @cb!ýå'¿ÿÙáÃ×ÞÿÓ7&þä¾ ”Ö üäˆú¾—²4íÛ:vìØ/ŸxRmGEPQS&§éèW­%gA´åÒÄù«v~ýÚé7>¬˜¦ ÊÔ¹Ï4& b%Ÿ–LÛÆO=êÃYþ럼þÔuY‰ày^Îù4ï§žzê5?ýU-œ™Ëƒ%ä´œÈHÑSš±+ï]òýŸÏ+ð5ƤÒrr#GŽ´µ­1é˜#Fèr˜l#]£ € @€ d’S&Ã’L£Ð˜’áL-C!€Æ4zÞ‹Æäm胎£1yþN:¿qßX=íx}N'7>¦vQ9˜Ü2™N;ç’ÊêZå¶ä0]ußR˜d{HdQ–múËšÝZiKÓeÒ˜V휷rç¥w-Örrã¦öóËùß¹iN]ý%p˜>ÜÚ—÷HòPyãßñ<Ú‰sí¢r%ÉB&Ó—N<)D9L˜‚¥KšŽD´ëƯÐúhJÂ$‡É–K 4¦R•ŠI9‡Ä&¬0S'p˜–Õ8LýøòõÛ,ˆ¯¿ñV;}ˆmßÈ¢rÉÕ˜L7üªÎ-O¬–¥wóã«•žJ“@MYò[‘±.2ÊÃ$KOy˜äxi­=ÁÑš‰?ºoYÝî&ƒƒÉ[¼9q7 1uƒ"çH…€Ó˜T»Ö‚ÓŠrZNNʯ¤wÉÆ$]éàÁƒ®ÝúU“Ö¥K¥'T @€ @€@> 1å#N±´)¬œ´«ИºŠÓ—“¡1ùéºýDcò:üt>)"0¹VÊdúþ9ÛÒc–¹çþi/Ý?­O/–¢F əᡕ¶îynã=ÏmЧ¶ØÖ z« jý%â0a2µ=>ÂSµÀäN%“é¸_Ñò ]uï Ln­´Ÿ<°|öò~ ¢tœkÇõ¸ ÞùôzYhçübþ“ó¶N/¯ 8°œ\‡)ä0eÈdrSÀäàÈdºú†_Õ¹jŸ¦o\7ãºñË-C•á׎[.‘KÃ{no0¯»L#üú‡VÔ¼"&SÛ#œ&€Æ”0pªë[<Î^ýýýZWN9™d2Ù;ƒhLÝkg‚ @€ @ÀhLÞ„º¶£hL?7]GcÊM¨²ÔP4¦,E#ñ¶ 1%Ž<ïƪ15˜´Àd:ûâò[•ä=%÷eÏ¢ÊBrr_LÑJ[–¥Æ&-C6kEÿÌåZik‡ô[lË-'W×aÂdjo¸šÆÔ@`r§2“)İÃÖtDËÃÔ(ˆá5ë:LY1™ô‘&G&Ó®ÿU½¾»j„¯¶¾³<ÂKSi„ï(ðš$Uu&L¦öF8{'L)aàT—4¦¤HS @€ @ÀhLþ妧hL?7]GcÊM¨²ÔP4¦,E#ñ¶ 1%Ž<ïƤ1Í}edx ¹&”d2}ïì‹e½TÄ—É¥¨i`xT9Lþ²tÛ”%Aiâ0ÕšL¯Ì›üȈÃ'VÛȺoæ=âm´éÃá%äšh&S“ .ˆh:5"ÚŒ’ˆb‡©ÖdjÄy׎ÜÑ3§^·¸ëÜ;½q •}e2ýpô­!8Ó`#¼â0ÕXzM&L¦V‚Â>é@cJ‡;µÆN)vÄT@€ @ðŽ“w!è0“ÇÁÏM×јrª,5)KÑH¼-hL‰#Ï{…1iLma¹üŠŽ<ëb[B.¼ÆV9 “e©©äï‰d©©Õ_u˜äyüvÏzçk¤4I0µ ~co¿ïS;Q¼ëž{=áëA+i´ÌÑ© ¢%ÓH5TÑ:p˜Ä­;Dõ@AT(ÛéJ÷÷=éäo^5úÖ:#¼lw5á–i,,x ê0 Îö½è~78#†Hiˆ9<«И²Ú@€ @È/4¦üÆnÈ-Gc2BN;4¦Ø±4¦"Fµå>¡1µŒŠ@4&5ã’Ë®úîY£Üêc–¼Ç%aê®Ã$Ãã?Þp˜,Ók¿é“Ì4mÔ•÷ŽV“”ÂGÛÚˆ¼¯wd>ÙžŒ¢0;îúõOøú@KKvÄAó0™¦óïo½mµ+‚¨OõQÝ *ÊĽë{ˆã×¾ñÍ+¯ûed„Ï/$gªl-¹åUy˜:p˜œà•@ר­@cj•ûåŒSÎFs!@€ @9 €Æ”ƒ ÅÕD4¦¸ÈrÞî@cêK΄ÆäQ°k»ŠÆäuø;é|F4&5=0™ÎU^}¬¢w˜ÀTÎßÓÛ?«©áÑJ¦°Ã¤Jßzã i.rY$3éWmkC¿Js1ŸI;è}³$¾¼ôÜx½¿öÑ1h:^Üc“éø¯…-4—IË1¬ét–‡)ì05¢…µ6ˆŠ¬ÅÎí@Ld2]qÝ/ËjWÝ®áÔ@$¨"-hLi‘§Þ˜  1Å ˜ÓC€ @€<$€ÆäaÐ+]Fcò8ø¹é:SnB•¥†¢1e)‰·)qäy¯0;“HÊdúΣñ¥²Šœ&¥¨©,$×,KM“j [,ÚV& .ò–¤+™Ì¤}´!åEiÛ½¯THÈT;þe2}áø¯)ˆSËAl7“ÕÞ$ˆÎE Q‡(Ä ¨1É¥e2]~í/«Fxi‰=7ÂgºNŠÆ”8ùÝJ4&¿ãßaïј:WŒÃИŠÇ{‘)Iý–Ét꘸/3zvL¯1<:s˜TÓ\$*©(Í’¼ËÏd?í¥÷%»,þÅ([‰ÌŽRQB¦c•›ª“éË_« ¢­•¶"X+M¥n;s˜š1¼fœ ¢…ØÑrn%ö’ÉtÙµ¿p9Æj½r†ªeÛ§.Ý>uɶ)¥ráo>ñ«'k5½&EIªp˜‹#uB©j“hL9M„ @€ äŒSÎÖÍæ¢1u“&犇S<\ ~V4¦‚¸y÷И¼'ϚƤ>Èdúöé™Þq_ê;LªËi.NZ’™$cé½ý–¤G;¼2o²6,mRø¸ LÒžì#^µd2}þË_ qVE`ª âÒ²¦Ó±ÃÔ$ˆú¨nõ¾-¨ …[vZ”Étéo˜ÂvWÏöÀÒ“À´tSÂq¡ºØ  1ÅŽ˜ Ò!€Æ”wj… @€ ™S‘£;HßИ<~nºŽÆ”›Pe©¡hLYŠFâmAcJyÞ+Ì Æ$¤2™¾uúEJÞr_‚$LÎð°5*Cq˜T‘[PLN’¶¥(IjÑOeîÑ;ÚA¢’”½£Oõ¦Þ±mKΔ÷èÇÚ~3™Z âP¦&At.Zm; bZËÊdºäš[Â驜Ýe“áäaŠu”ròD  1%Š›Ê’#€Æ”kj‚ @€ øBÉ—H×é'“ÇÁÏM×јrª,5)KÑH¼-hL‰#Ï{…ÙÔ˜D50™N»P«Ùd¶\°ÌVÈð¢Ã”÷Øe¿ý2™þùK_-Ñò ÕqˆSö!4j¡L¦‹¯¹¥j„W'ab-¹ü—–×'€ÆÄÈ((4¦‚–nA€ @€R$€Æ”"ü´«FcJ;Ô?84¦Á±G 4&¯“×áï¤ó™Õ˜Ô™Lßüþ…æ¾DRÔ =S'°8¦}2™>÷¥¯6 ¢·“”É4êê›ëÚ]8Lí5ŽÈ<4¦Ì‡ˆvF©3n@€ @€@chL4&ƒŸ›®£1å&TYj(S–¢‘x[ИGž÷ ³¬1‰­L¦S¾¡20M­¬"וµäòµ|µ?0™Žûjm=w˜,ˆ2™.úÑÍác6ÂYK._ƒœÖ¶D©%Lì”?hLù‹-† @€ dSÖ#cûИb„Ë©»D©K ý: “_ñŽôÉëðwÒùŒkLê’L¦“¿w¹8LÄ8ÇÈdúìq_ ‡É…E&“¤¥0¦ ŒYš4¦ rÊ,@cÊBh @€ @ XИŠ϶zƒÆÔ.vN…S*Øó^)SÞ#8¤ö£1 Ÿg_cRTÂ&ÓO~1þ³Ÿ?níË{6m½QÙ¾÷ÿñö;>†3Ã}›L8L‘@…M&¦ bš64hLCãÇÑ™%€Æ”ÙÐÐ0@€ @€@n  1å6tCo8ÓÐr†¸  1ÅM¸çGc*dX[íS«¤Ø¯L “Új&S®®™L8Luƒh&S®G8„C¤ И Xº@€ @H‘SŠðÓ®)íPÿàИgÄ5И¼hL^‡¿“ÎçEcRß¾~æþÇQÿy˜: sfŽ‘Éôÿû‡÷/_¿­y2­ëíÌ49¹†|íƒï:ñÃÿ­ }¤Lcz‡LcÉ…šºI©›49W† 1e(4€ @€ PhL d'Ý@cê„Ç$K)YÞ© © ì¬hLqóø¨iLº'Þ»äÖ’Ëûh}ý·p˜êñò÷îºé„æpp˜ò>þ½n?“×á/rçјŠ]ú@€ @H‡S:Ü3Q+S&Â@#š@cb€t@©hÅ9©8±L¨'ùÒ˜&¬yï«¿û÷ºž‡²ÔüÇÛd©IhØ ±šF&“‚èg¦2ÏÒÿ™îÚÿf£ŽÃ4ÄÇá)@cJ9T4¦¸Èr^@€ @€€¿Иüý!4&ƒŸ›®£1å&TYj(S–¢‘x[ИGž÷ s§1 x­É„Ô»qXk2ùî0)„3qhÑ8ý·Ödb-¹Üp\‡â И Xº@€ @H‘SŠðÓ®)íPÿàИgÄ5И¼hL^‡¿“ÎçQcR?Ã&S'ÏÀ1a“É+‡iïúž×~ÓW½ïÞ ›L8L­4¡ИºA‘sdSƒB“ @€ @9'€Æ”ó¥ùhLC¡Ç±É@cJ†sÁjAc*X@ÛëS{¼ØûPŽ4¦}oôîþýb33™p˜r=ˆÍdòÊaš6j„Êâ_ŒŠNbÓä‘ÃÂošÉ„ÔëNã« 11 J© ¥[€ @€   1¥?íªÑ˜ÒŽõNipFìQCÉëAÆäuø;é|f5¦ƒ<8h^ûý[ÿñö;ƒîÆY& “éßßz;Ë-ìnÛqxÝ®}tL­Û$WïOï0»Ζ4¦ôØSs¬ИbÅËÉ!@€ @^@cò2ìÖi4&ƒŸ›®£1å&TYj(S–¢‘x[ИGž÷ ³©1MÞ8yää‘ygKû!! “ÞTцR4姯´5И%€ÆTÐÀÒ-@€ @€@ŠИR„ŸvÕhLiG€ú'€Æ48#ö¨!€Æäõ @cò:üt>ƒ“¼%Ó’´!WÉze˜´aI˜´®œd&}jÅiO à$EÀR.…WŽ“¨d«ÅY¦%í`&“å^Òû¶‰MI5“z 4¦x¸rÖÔ  1¥@€ @(4¦Â…´õ¡1µÎŠ=Ó"€Æ”ù\׋Ɣëð µñhLC%èÝñÔ˜”uɉS& ‰•l9“™ì#)M“7‰mxA Ë”„Éœ$½lµ8ýj®’~•¨¤÷-9“}d{ÚÂs*Jã”åÞÑ6 NipFì‘KhL¹ † @€ dšS¦ÃoãИâåËÙ»A©½;“w!wÉëðwÒù jL•LcRš%ËÀ¤—­.7~Õx½©ŸzG“„'­+§ 4¦NbÏ1€’$€Æ”$mêJS‚°© € @€ à 4&O]¯›hL?7]GcÊM¨²ÔP4¦,E#ñ¶ 1%Ž<ïfPcR¦%™LÿxÐt%{ITÒ›ú©¢ôŽ’0Yº&™Lyí‡ P|hLű§=Dcò4ðt€ @€ #4¦áfýÔhLYí;t‰QÐ4¦ ç4¦âÄ2¡ždPcJ¨çT@I@cJ’6u%H)AØT@€ @ð„“'®×M4&ƒŸ›®£1å&TYj(S–¢‘x[ИGž÷ јòAÚ_3qhѸât‡ž@ B‰!QPhL ,Ý‚ @€ ¤H)EøiWÆ”v¨phLƒ3bhL^ 4&¯ÃßIçј:¡Æ1ˆƒÿgUΙhLÙ‰-é*4¦®âäd€ @€ ˆÿXìñ0@cò8ø¹é:SnB•¥†¢1e)‰·)qäy¯0G÷ļ6Ú?þÏ”!RlhLÅŽ¯Ç½Ccò8øt€ @€ þ±8&°y8-S¢ä{™²õ}tÔ4¦Ž°å 4¦¢D2±~ 1%†šŠ 0þÏ”!RlhLÅŽ¯Ç½Ccò8øt€ @€ þ±8&°y8-S¢ä{ј|õ©#lE9©(‘L¬hL‰¡¦" B€ÿ3eˆ›S±ãëqïИ<>]‡ @€ ÄD€,Ž lN‹Æ”‡(ùÞF4&ßG@GýGcê[QBc*J$ëSb¨©ƒàÿL"Å&€ÆTìøzÜ;4&ƒO×!@€ @1à‹c›‡Ó¢1å!J¾·É÷ÐQÿј:ÂV”ƒÐ˜ŠÉÄúÆ”j*‚À ø?S†H±  1;¾÷ÉãàÓu@€ @€@LøÇâ˜Àæá´hLyˆ’ïmDcò}tÔ4¦Ž°å 4¦¢D2±~ 1%†šŠ 0þÏ”!RlhLÅŽ¯Ç½Ccò8øt€ @€ þ±8&°y8-S¢ä{ј|õ©#lE9©(‘L¬hL‰8l–ÿôIDAT¡¦" B€ÿ3eˆ›S±ãëqïИ<>]‡ @€ ÄD€,Ž lN‹Æ”‡(ùÞF4&ßG@GýGcê[QBc*J$ëSb¨©ƒàÿL"Å&€ÆTìøzÜ;4&ƒO×!@€ @1à‹c›‡Ó¢1å!J¾·É÷ÐQÿј:ÂV”ƒÐ˜ŠÉÄúÆ”j*‚À ø?S†H±  1;¾÷ÉãàÓu@€ @€@LøÇâ˜Àæá´hLyˆ’ïmDcò}tÔ4¦Ž°å 4¦¢D2±~ 1%†šŠ 0þÏ”!RlhLÅŽ¯Ç½Ccò8øt€ @€ þ±8&°y8-S¢ä{ј|õ©#ly>hí”C²—¬üÛ'išðÑóÞùÝÎ<÷¶ÇN _Ó¯WüÙo1¤cTþÏ4îÔš4¦¤HSOÂИNu€ @€ ðŹQј<~nºŽÆ”›Pe©¡hLYŠF"mùmo .Õ-?9"‘PIŽ äHcêÝyƒÞv¼>'Ǹi:šÐeüž¯C…%€ÆTØÐúÞ14&ßGý‡ @€ tŸS÷™ææŒhL¹ •Ç Ecò8øw©svù=òöêkL½óÛ'Zž iL9jj2±£–¢@ò(ZDéO5F8#¢ И Xº@€ @H‘SŠðÓ®)íPÿàИgÄ5И|u2‘ŠÉÇ¡ÐvŸsä娩m‡ H ƒb`„;¾÷ÉãàÓu@€ @€@LИb›‡Ó¢1å!J¾·É÷ÐQÿј:–ÿƒj2‘Š)ÿQM 9rƒrÔÔG$€äQÀ Ò¥F8á И Xº@€ @H‘SŠðÓ®)íPÿàИgÄ5И<‘„L¤bòt´Ýí¹A9jjÛaàˆ’àØáÅŽ¯Ç½Ccò8øt€ @€ 4¦˜Àæá´hLyˆ’ïmDcò}tÔ4¦Ž°â pB&R1"¤ t"GnPŽšš@ਢ€< Tº"Àg8”SAK· @€ @)@cJ~ÚU£1¥êœÓàŒØ£†“¿ƒÂ%d"“¿ƒ ížçÈ ÊQSÛ@@<Å&À/v|=î“ÇÁ§ë€ @€ ˜ 1Å6§EcÊC”|o#“ï# £þ£1u„­(YB&R1%ž ô#GnPŽšš@ਢ€< Tº"Àg8”SAK· @€ @)@cJ~ÚU£1¥êœÓàŒØ£†“׃B ™HÅäõh»ó9rƒrÔÔ¶ÃÀ$†A± 0‹_{‡Æäqðé: @€ @ &hL1ÍÃiјò%ßÛˆÆäûè¨ÿhLa+ÈAS¦L9úÈ8p  ý¡ñÈ‘”£¦Æ7j("$"F•> `„3 J© ¥[€ @€   1¥?íªÑ˜ÒŽõNipFìQCÉÛA!‡éSŸýâO>|8&“·Ã ÝŽçÈ ÊQSÛûC €äÁ8(6Fx±ãëqïИ<>]‡ @€ ÄD)&°y8-S¢ä{ј|õ©#l¹?HÓ§?{ì’uý½›^}xò\L¦ÜG4©äÈ ÊQS“Šõ‹’G±âIo¢ጉ‚@c*h`é @€ @ EhL)ÂO»j4¦´#@ýƒ@cœ{Ô@còpPÓçŽ]º~çÊͯJcZþÒ¾ “0™<t9GnPŽšÚI$8HŒb`„;¾÷ÉãàÓu@€ @€@LИb›‡Ó¢1å!J¾·É÷ÐQÿј:–ãƒÌaZ¶~çªÍû¥1­(iL=}ûš8‡œL9ŽkRMÏ‘”£¦&=ê)$bÅ“ÞD 0Â%€ÆTÐÀÒ-@€ @€@ŠИR„ŸvÕhLiG€ú'€Æ48#ö¨!€ÆäÕ Ãô™ÏÛ³açê—‡I©˜V¼´oyŸ4¦½K7î?qö'‡uÿ~¯˜ÐÙ¶äÈ ÊQSÛ ;C LɃ¡PlŒðbÇ×ãÞ¡1y|º@€ @ˆ‰SL`ópZ4¦:ê?SGØryPÅaÚµzËþU!I©˜–m 4¦%ö<ðÔìó‰M¦žžž#F´ËbòäÉ‘CF}øá‡Ï™3ǽ?f̽ÓüÌ®vµAÛÚyذa:JgÓ«ù±îVïv¶vŽ9Ò•‘–«…j˜^ÚèëëSóÚê`ÂøñãER/¤¿¿?òiŽÜ 5µ•qÈ>ˆ@ò`L›#¼Øñõ¸whLŸ®C€ @€b"€ÆØ<œ)Qò½hL¾€ŽúÆÔ¶üdÓò»ÖlÙ¯TL«,SeE¹@cÚ°wÉú=‹×í¹ÿÉY-šL’‡$»´Ë¢Ö|’ ¤ó„õ ’šŸÙÕnâŽûõ`éÕüXßÌ'{É ªõuܧnçÈQÚ!õ–« â6jÔ(k­HÚ0&¼ÄAä  d²Ú`åÈ ÊQS;ˆ‡@à’ƒ ØáÅŽ¯Ç½Ccò8øt€ @€ 4¦˜Àæá´hLyˆ’ïmDcò}tÔ4¦Ž°åì ¨ÃToE9¥bz±¤1-Z»{Üã-™Lu5&™=r_ôrn<{Gn<K&¨C´³ó–dÒXz!ÛÇn¦‘}jç7eG;èÌf>i[ò^z_oFZb^Ž^µ“½¯æÕ†ÖvÖ™u~m‡ ¡˜Z®„U‘ö4j¹Z«=­¿ö²mc¢—Zh]8ÜÉ--V-%×AÙ]µšZŽÜ 55gš›H ͈‰#<&°œ6mhLiG€ú!@€ @Å#€ÆT¼˜¶Ü#4¦–Q±cjИRCŸçŠÑ˜ò½–Ú[h9¹†©˜ÊÓî…kw/X³ë¾Çfš“©Vc’øâ%³dÕ˜@£,ßRÝlL&?Ùºr:Äl'ÛÙÔ"—gȽ£³™dc¹Æ¸EåtK¹¤èeRŽò éM÷Q˜ ô;gdMºæÙ˜ºÞr×Në¾d£æ-7…K/ë£õÈ1±žª×¶áN¥w´å^ Sr@ì´µ+æÈ ÊQS[ú&³"<Å&À/v|=î“ÇÁ§ë€ @€ ˜ 1Å6§EcÊC”|o#“ï# £þ£1u„-7…¦ÊrrûWÚŠr/í[Þ·¯§oïÒ{é˜Lczaõ®{3™êfc2OH*’ù1ò`´!ÃÆ-âf“íf†‰G•œçdÚv /-g™ÂI›šhLæ*Ù™-Õ“Ó›tZU^TÎ…Ód©ðòvú(¢1© Ör}GËÍ‹²3kC©my¸ ÖxµÇV¸«ËD;X§²£"” §nnª¹A9jjn.(44S<2ÓuŒð®#å„Ù €Æ”8Ð @€ @€@‘ 1)šmö©M`ìž4¦ ç¿J4¦üǰaê8Láåä^’ôoÙÆ½K78©œŠIÓüU»æ­ÚùëG›ådª›É¤%óÌõ±¥Íœac“<'{Gέ1QÉ,"G¹‚‹šÙ Ãb“ªn6¦° cç<ÚkLªÈ–¨ÓO[º.üŠhL–±ÉšGËÓ¶Ã|Ô*ky¤ µ­0q6јÂ©ŠÚ¤YVKŽÜ 5µÀW!º#$árê `„g 4!hLqP圀 @€ ¿  1y4&ƒŸ›®£1å&TYj(S–¢ÑͶ4s˜6½ºÜ9L R1Í_µsîÊszûï~dF£Õåj5&K}dݰlLzÇ-LæÖ‰S²¥pW@#;Ç--ç²1™odËŸiÃIE:m“lLaÊÖ³sÙžÂ'±f裺™‡ìÓˆÆwËÃík›Kåãš!bRìW·T\#)|*CíD1·ê_óQ˜#7(GMíæ7ŸsùCÉßXûÙSF¸Ÿq÷ ×hL™.B€ @€&€Æ”0ð,U‡Æ”¥hЖúИ@cêZöqS°œÊËûW¹z šQŠ01,aÚÙÔ¨ZJ™lLÙÿšÓBß yø>ŠÞFxÑ#ìmÿјÜJÌzÂs²öüê-2:@€ @€À И<"hL?7]GcÊM¨²ÔP4¦,E£;m1‡©gîÀa* L_ØúÍëgönzuEÃtòu3JÓžëXþ¥+žÊå*ÏüÙܹ½;g÷öÏZÑ?sùŽ;˜LÝiqœg‰d~гª”Ï6ÃÚmJë”r”â(GMm7^ì€’ã ØáÅŽo¡{çŒ#·†²ùHf7Ó˜ä0vØaε7Oß~—{³Ðèè @€ @@cê[1Bc*F‹Ý 4¦bÇ7¦Þ¡1Å6­ÓÊaútà0ítI˜Vm~õ©¶žpÕ”ˆÃ4}Ùv9LŸ'ûß4¦ìLj‰’Çðqpæ 0Â3"؈@DcRŠ&­çvnOc’Ã$“ Ö€ @€ @ 4&Ç“ÇÁÏM×_øÍ¨´Kà×+þìoÈÍ@§¡õ}ôÑ<>Í¥_’½dÓò Ó¾Çç½|ü•Ï/­ÎÃ$‡Iy˜¤1Y¦ù«vÍ[µóçNš´`kt9¹ SÙa2“éØ¿ù/þïìùOí6ö/onÈþ)û1¢…C"€ä1$|œyŒð̇ˆ6"јôkxQ¸ö4¦Úêà@€ @€¢И<hLŸ®€¾Â¬ýoEè }€@=>|ø„Ésu©b/¹Uä›hLZHnÉúòZr‹J“ò0}â¼IÎaztέ(^NnFi9¹iK·O-ÙKVNþÞ?¸ðòMÛ_ß¾÷zçl@cÊf\hU× yt %'Ê$Fx&ÃB£Z!VúúúÂ+ÊéðA4&¥_êééqÕ 1µBœ} @€ @¾@còx 1y|º^hLEˆ"}hJ l2Mšëì¥` ¹R¦GçlVÖ%W¾ñ“ K“ò0)ý’åaš»rçÓ^úúµÓg¯èŸµ¼þrra‡I&C2ËИ²ÚÖH]€È)2L€žáàдæÂê‘”$‰Iáýј€ @€ @€Ú&€ÆÔ6²â€ÆTœXÒ/  1yvï:m&ÓCçöRe 9ËÀ¤²xJ) ÓÚ@` ¯%'‡inïÎr¦!‡©z99—‡É&L&ïFX®:ŒÆ”«pÑØö y´ÏŒ#òD€ž§hÑÖ6 1µ‹]!@€ @h‰SK˜Š¹S1ãJ¯¼!€ÆäM¨}神Lã'ÎvKÈE&K´`õ®ÒZr;-Sc‡i{íZra‡ “É÷—áþ£1e884­<ºA‘sd—#<»±¡eC"€Æ4$| @€ @€@hL 4&ƒO׋@©Q¤­ÉôÉáÃxjv)ýÒ@¦ª$Læ0I`Z$aŠæaêÙ>-Èô}ê’m¦1ÕÍÃÔ$'SÿÁþa÷ k­½ìX 1Å‚•“f‡’GvbAKâ Àƒ*çÌ4¦ &@€ @€ F©`m§;hLíÐb_dŽSæBBƒâ$ðêþý=æ÷?9Ë– L. S‡iú²íÓÚq˜ä3mßû‡?½óŽëÓøUãG<2âàöíëÓ›=ý=î§í£lCÙ§¼ Ð]hLÝåÉÙ2GÉ#s!¡A]%Àï*NN–hLÙ‰- @€ …SQ"ÙA?И:€Æ!È4¦ìÄ‚–$CÀL¦qÏ –[,!W˜’0Y¦Ù½ý³VôÏZ¾cæò3zvLïÙ^v˜–¶š‡©Öa’¢$‡iää‘s¶ÎQN&Ûçg=´Š '}ª }:jú¨d°P‹?Иü‰µ§=Eòð4ðÞt›îM¨}ë(“o§¿€ @€ ø  1ÅÏ8³5 1e644 ­@cj…ûŒ€™L÷=6s@`ª³\ÈaR&ËÃ4‡ÉÊO²K‡ßz¸KÅ$ŸÉ>Õ†ÞÔOyNnÿ‚Á§;©@cJ=4 ^Hñòåìi`„§ê‰SL`9- @€ @ÀchLÉãàÓõ"@c*BéCûÌdº÷±™óVíTú%ËÀdI˜f+ ÓŠr¦ SÉaš:´µä\e/iÛ\%{Ó20Ù¶>Ur&ýÔ§Vl^è"4¦.ÂäTY$€ä‘ŨЦî`„w%gÊ4¦L…ƒÆ@€ @€ A©aì¬hLqã(d„SFA3’'`&Ó¯Y-0 $aša ÉuÏa²ÕâÔÓ°ºäò3)“¤%·v“Ò4yãääÉPc±  1;¾ôî’ƒ ØáÅŽ¯Ç½Ccò8øt€ @€ 4¦˜Àæá´hLyˆm„@ChL Ÿ ˜Ét÷#3J˜ÂS„)p˜B ÉMY²íäï]ðƒ /ß´ýõ&eûÞ?üéwêRU&IKÿxг}ôÎøUãå0œ¥V’®¤ã$*ÉI²bY—,'“6¤7i[ïKuÒþúÔí‰ÆÔ>rŽÈ 4¦¬D‚vÄDÉ#&°œ6#á Íè64¦nå|€ @€  1y<И<>]/4¦"D‘>´O@KÅÉLÒq.å’Ô%ËÏd2“e`² ½ïVšÓ;Ò›$6µ_'G@ И2$øØræ,`„g! ´!hL1@唀 @€ Ï  1y<И<>]/4¦"D‘>´O@f’©H’–¤%YN&[TÎd&åjRѯ˜ô‘$'ÛSò“K×Ô~µô  1¥Z+$XñròÔ 0ÂS ˆ‡S<\9+ @€ @ÀghLGÉãàÓõ"@c*BéCûVÜ;Ú’̤m¹JÚÐÏ=sTì#ýjÙ¯z_¿ªØ’s¼ ShL9 Ín•’G«¤Ø/ŸáùŒ­”Ó ˆØ€ @€ 6  1µ ¬H»£1)šôÅChL.C>@cò9ú^ôÉË0{ÜIF¸ÇÁ/v×јŠ_z@€ @HƒSÔ3R'SFA3 Ð4¦Î¸q œ@cÊiàhv«FÝ‹>£1yf: @€ @H”S¢¸³US¶âAk Ð&4¦6±»Иüˆ³Ÿ½Dcò3îõÉã`{ÙUF¸—a÷¡ÓhL>D™>B€ @€’%€Æ”,ïLՆƔ©pдK©]bìï4&/Âìi'ј< ¼?ÝFòð'Ö~ö”îgÜ=è5“A¦‹€ @€ „  1% ÷Éçè{Ñw$/Âìq'á¿Ø]Gc*v|é @€ @ hLiPÏHhL Í€@gИ:ãÆQ'€ÆTð{Ý=4&¯ÃïCç‘<|ˆ²Ï}d„ûýB÷©Ðá¥s€ @€ T 1¥‚=•¢1e#´@cꇛS±ãëwïИüŽ¿½Gòð È^w‘îuø‹Üy4¦"G—¾A€ @€Ò!€Æ”÷LÔŠÆ”‰0ÐtJ©SrWhhL…¯çCcò|¿ûHűß=d„ûÿ÷©ÀÁ¥k€ @€ ” 1¥> Õ¢1e! ´@cê™S‘£ë{ßИ|…ï?’GáCìyកâv©¸±¥g€ @€ ´ 1¥E>zßþÓ›ãWý¥Ô‡ºeѶóÓhuB­øã¸{ùjô~rÃZ=ûA `fÞrHSƒuËÙvèw; Ö]ºã-4&oC_ØŽ¿õæ¡QÙðþ(ÿoRØÈ{Ú14&O_ün£1?Æô€ @€ 44¦¤‰§\ßê]·Ôu ~½âÏÞx‹‰Þ”£Cõ”À´M'4Ò˜ö½±jÐÃÙÅ$Ðd"œYðb†ÜÓ^¡1yøbw»‘‡Š„Zì¸ûÙ;4&?ãîA¯Ñ˜<2]„ @€ $L)aàiW×(!©˜ÒŽ õC %2‘Š©%|ìT`u'™/pĽì“—a/z§y¨H¨E¼ýCcò1ê^ôÉ‹0ÓI@€ @€@¢ИʼnÊj2‘Š)¡h@Ý„L¤bj {—@݉pfÁ‹p?{†ÆägÜ‹ßëZ µøQ÷²‡hL^†Ý‡N£1ùeú@€ @H–S²¼³P[mB&R1e!.´-¨MÈD*¦ѱ[Á D&™/x¼}ì“Q÷¡Ïµ*ªq÷°hLÝ.£1ùgz @€ @H’S’´3SW8!©˜2V D2‘Š©UpìWl‘‰pfÁ‹n/{‡ÆäeØýètïÄC2<¬ ¡ús{‰ÆäcÔ½è3“a¦“€ @€ D  1%Š;+•…2‘Š)+Q¡h™@8!©˜ZÆÆŽp ™˜÷ ÚvÉà{ÔåŸQÖ˜P=Šºg]Ecò,àþtÉŸXÓS@€ @€@RИ’"µz,!©˜²Ú ¸„L¤bj‘»yAÀ%dbÜ‹x{×I4&ïBîU‡-!ªWA÷­³hL¾EÜ›þ¢1yj: @€ @HŒSb¨3V‘%d"SÆÂBs Ð*KÈD*¦Vy±Ÿ?”‰YpÂíYOј< ¸ÝUB&$TÿÂîQј< ¶_]Ecò+Þô€ @€ 4¦”ß|óÍn¸áꦯoûÛÍwÈø§7Þw쯿(ãlÒ¼K/½ôôÓOoÞþ‰'&ñ=¢¤Aà®g?ÿrÿ‚4j¦N èrÚüz{^é•ú=å'?ºrÆEŸI½j@+ [·nõq0ÑçN ø 1éK1è÷÷k_ûÚ ûø³ƒ.¼ƒ>;¶ÓA—èqsÆÞxà·}‰VIeH’S’´©+AhL ¦*@€ @€€'ИzΜ9ï~Ïß^tÉ•V.tåâ+/ Ê*ÿùÿþ¿Gžvö_1PF]q~½rÞE—Gʹ]^.^~n¥üàÂË+å²\”sjÊÙç_VS.=ëüR9o œyÞ¥åÜKÏ<÷Ò3Ê%gœ[.§ÿà’H9í—åW.þþ9¡röÅß?ûâïÕ”‘g]\*£Âå»g Ê™å;gŽ(gŒúÎZ[N¿èÛ5å[§_ô­Ó. —ožvádžÿóýïÿ o~?(§T• Nùþ#¾þ½÷¾÷½ž|•é¦oz{{<ê˜áÇ8pÀ·¾ÓßTèrúý3Ω¹!wC» ý±«\Ps¬û‹ÞøêÜò"7»È.|«ÜàêßÚÞÔêßËndá[Xó›Wø¶ܰNnXÿçÿõŸO<é{ÁMÊJôVuÁû?øQ™©D“JsJÀI_Šó‰&—={ë ¼Î¥fÔá«Mä1»ùvøjÓäRzœ®sµ©~„nöðylnø´\óyB¶ÇãcJÏÃÚht©qR>ž‡§L™rÌ'>ÃMN¯N4»%hL-ab§ü@cÊ_Ìh1 @€ @ ëИDHÓGùÄŽ½°²=(o¸²mÏ*óî¿]¼|ýo÷¼”Ý*¿ÿM¥¼²ë÷®lÝyÐÊ+ý_.—×_ÞñúæJÙ´ýu+/mÿÝKÛ‚ÒçÊo·1(¯©løM¹¬ÿÍkë_ ʺWe뵕²fë5[ö[Y­òrPVYÙüêÊJéÝôª•*/íSYn¥/(=å²wÙÆrYºqïÒ AY²aOPÖïy±R¯ÛS*»©¬-—…kw/\”kvYyau¹Ì_½kþª*ó¬¬Ü9·Ræôö»2{E¿•Y*Ëw¨Ì¬”=;.¾ú–Ï}é«Ó{¶O_”iV–nŸ”m*ã&-FcÊú%ˆöuD ä0 {aÅ–‡ŸžË„_G9¨mºœ¾¸bCén8pC´»¡Šîƒ² Tì>XÿXsï«{׋Üïìf¹Ó­ÙR¾Í…op‘»[Õ­­öŽºUßËndv ß¿J7¯àþUuçêÝi·­ÖŠà†õ—ýîŸyQw+•ª[Uå>uò÷.@cj{ ú}€'“þ` z©Ù;p©Y´|½žÀËÜ•çí­»~?ð°íž´Ý3öŽªgìòvåéÚ­#ÏÕÕ¡ÇéȳôÀƒ´{ŠvÏÏÕÏKìá¹ê±ywðØ\zf®½ÔèÙ•#ÏÉåKMøj³|ÇÅ×ÜòÏ_úª]jf„ŸŠ+—šû'çàyXÓ§?{ì’uý<Øø}‘+zïјŠaoû‡Æämèé8 @€ @ 6hLÍ4¦oÓ¬IeâÄMÖÚ|­Š&Qõ¬ ÛK¿ ÙKšÄ­˜Â“˜´1T‡é•‡Ió.ó»Q‡i¿›åÕFHc ¦°ÆÔÔa*ÏÄ4ט‚)™ÐpØa æfJÓÀn&¸®Æ4»fJØ9L3KS5e©ä0¡1ÅvàÄ™# ‡éÃG [°bkà ¾´oÂdL¦ÌŨ ’Æ´xÅúÈ=1,òZ2Bw¬² Þ†ònH,pv[ Êžn­¡[ç¾VÏÊ­õq«Ä‚ZiàæenD½5ïV7,4¦B~Òí”'“²»…ŸºÝƒ·ýÍÀžuÆÔèÚu˜*!ÐĘŒüI@Ƥ{T®oL–žƒKMɘ\cʼÖoÓÒuý<ؤ{…¡öØ  1ÅŽ˜ Ò!€Æ”wj… @€ ™SS©X¦¡:LÑTLÎaê©ü)¹2u;S?1æƒ[NÅј\*¦lLKÈÆTäK—·} ¦£‡-ìÝj&b`öí›0i9™¼‰u\“’ „½¥ˆÅkSp §E ç ¬I@É>Ø(ï`ÝTLC JÉ#™#9ëçGq©˜ByëæG)kLO[6¦n»Ô²)ÉÆ”Øè-LEþhLM.5 –Sä‘ÛÒV¶[Ñ%ƒ§ë -8L.³i©˜ú5&ÃSÝÄoÏN8LŸ;vÙú<ØæJEG@cbp”SAK· @€ @)@cj¬1ý±»Eâ6Bü­IM¥„§l#‹Ç…&T´\ÕrÑ L­-$Zó¢´\kÉ5ÊÃÔ5‡)¼¢\“TLnEž!¦b*iL76JÅ4)Å UÇC ì0­ÜªÉT7Û'ïP¢áƒ1™âÎY+¤1™¹YËÉ­wÞE—«„×uðw]AµfíÔÆy˜‚åä­—Zg¥Ôš5R«¬Ü8R1•ò£„5¦ºbÁÔ%hL|»Ú&à‰Æäuk|©y!ИÞÓh½æÅš«’s‹5—tÉ’ÃT½LsÕ+K™M:L›j³™†–cv‹WFbn¶xeýTL•ÄoUÉJK—iLZd¹‰1™eIÓgä0mØÉƒMÛ—È#4¦i[GéÍpíWÍ{…Ï£=¤I5}äfÅt†Ã;¬¶%Vï¨Q£T«±S–×!iL2wîƒvC,Ý í>xîE—«´—z°¡ÀT¹ß5° \r”fÓ`y˜–T¥bªŸ¥±Ày·ñ×ï~ðé¥bj¤1ýÇÛhLQóDc „ÈðSwõ¥fÞ’@cjr© ?i÷é»ú»y&÷\Ý<å[°¨kó$«ÛæºZט4§¥kf»“±ünv°î" ÈÖ7D“ì&æ®ÖGsK¤Õñ š' g ßï*é#wºÚ•RëeFÙ×SJ+d ßÔ*Sw¦ð*¨nýÓÒʧҘƗ4¦ºbSZ#9×õú¢1U„ÈÈǹõìí– nz©©o/ $7máRãþ$À¦AuI—Ç4òülºdÕZrͦæËÉU/µ\Ö˜JÏÆ&÷—ŸŠ³ªõ‡¦î?ؘg£Spô¤!Çå†t ޽cb´%†´¬Eæ?éW=ŸØy&OžìTÌ®Öûa»Ú.).‘¤êuж=äØi%WYKLZ²ýÍ1ŠœSGé}× KHiz–Içö‘9èÚÕd‡hÃÞ´Ú;nÃ:>›5/r6{ÇNâºï.›µÏõ5…Æ£1¥*“ €Æ”eê€ @€ øE©A¼McªU”Ü;š8Ñ$ÊœÅkÂi–”i©*ÙRU¾¥o©‰ºÔhå¸ Es{©:ý’û“ñʤKu¦&«È Ìõ–ÿˆÜ­…ÑúBr Vï’½dÅ9Ló4%Sš•Q)§²XY^#C+eÌÏk±ŒÆkəär‘ecr³5¡O4¦j!2ú·zöÖø/5å¿ ( LåGëR²ÃV]É©tµ©½Ô è’åõ—«“0E˜Ût˜ìÙ¸¼Èr泓â0 ö`£«q+6Nñ±{>qO#î©fÐlLvÍp:TXf²Â“~ kLNZÒŒ-!çòPª=&ˆ‡5&w}²sÚ£Žt+»¹‡4Û¡‰Æä29¹*"SØ·¤˜µgs]Sk];ՆȳbQ.«Éö)YÞÔ–4¦ÄPS @€ @ÀhL BhLG««%¹75‰2sájûµì*U’L˜®TµB\½•,LZФ\Šd]ЍK«šÛK¥?ø{ñªÅãªþjca 15¼ÔÔ·$ƒ›iý´¦›µZk§®äÀBÌ{ÂÓ@¾·JÊ·Ê¥¦j!9—µ´=]²’¦Ôùý¶ÈrƳ“:‡©Ñƒe·Ò:¹C|°qRŽ=̘ m’žsLâÑ£EDcÒ¯zrêe‹4ý(,B¹g•°ßcW§©Fm»³Ù†=eÙu&m;=¨öœúH;kÓŒt;¹=­ÙsZm6&ílKÝYúÕÉ[ö‘ÄZîr>©åµg³§/ÛÙe`BcêÎå©;9Kæ ¢1éÂgKuÚËþÆý©JæzCƒ @€ @È4¦Q0ÉÙHu74‰2}ÁªÜNT åXzvö2ç*ÕJK³_Ü Rë-=õBiñÓª•O¥1ÝhL S¢1µ9Ùý?S“Kž½õ^{© ?o·°"sQòº»CeúÂuîO~ò³;TÂKÈ]{Óí*fÛDþ à±çŸqÞ*åççµ»g-Ýrá•78]òágžvîåÓ_|¹’„©áBrÎõf*­·Îò@vÒ¥Áj•µ%u­?ä0 <Øüjâš«Ç.»õ©5µrö¸©}ö`£ÿãxrÞ–Ëïyññ¹[Z|°q¶fÌÝƒŠ“~ô޶%ú؆~µ‰uKJä1ëHï¸çð¤ø¸3»«’;•ÞÑÃŒö×n–¾È¤%«ÚÞ ·Íš>§•\íj°-Âkga£(ì Ûû¦%ÙI´³m˜3`ÕÙÜ>uÏfMr¹¬¬hLݹ¡1u‡#gI€.áZuñ ÿŸZ3ÉìN÷1&oêþË:D•€ @€ dœ€çÓ£çzúêCo¨’þ­öÃG³ß"ÅM“heÚ «j-¥r‚¥­®øñÏ>xäÑö÷ßV>óÏÇ=òôì@MÐöçŽûÀ‘G[X*îåýOš}Øa‡¹ÞóÞ÷M˜80•Y3.¢.•ü+{­^dÇfyßý·ïÓÏ3Φ^4×{òwÎÒäÁ}Mÿäg¾¨)„r¾ŠHú¥ÒÂU®hÞwþª`2æ}à#árÞå×Soÿ@‹Þþ‘g_¦rçCSÿç‰L3+Ó3¶ŠÜwκTeÚ²íA LšÖ$Í…Cјöm=4îÔC Çfü Jó|#`Ó¢•[À´ª´Ì}ñ¿rÊî[jËÉé÷Éó&™Ÿ¡/é÷þmî—®xþK—??ògs]*¦@c*¥m¸c´AM&ßPÓßZ;^Ÿ3mó ûÞè­ GÓôV5º!êÆwÖy—ª„…Ý[ïžð·ïý¯ºªH]Ò¨¾þæ;ëÜø6ï¿üš›ô~d9'Ýþ¾õ½sœOpćŽ~ð©YáÛœ¾*S^XûcY¡%äÎ<ÿ ÝF¯¹ñvgå꾦;ÝÀ-äãºÙ=LÿŽÒìãŸþ‚4\9Lóž÷iû{ç\¦X•UP;5IE_1ÝÎnÿü€t[ºa™ÆÔ$e _Ãv x¢1éJ¾ÔDž´õì­'ðê¿ ('[ªM¹TÓ´~Ž7»Ãœ‘gŸ}ᕺÔL[¸N—m|säÙ*G|è(»Úhã”ïž­¢ K¿ätI]dþñƒGéAúôó®ÐÆ—Nü†ì%=K¿ÿƒG-X³KåÞG§ë’òÃëǸgæ–’0…V[.¹’Q]²²ÈòW­°<È"Ë¿í=tû ±>ËaúôçŽíÙ°Ó=ØL]²ý„«¦œqËü]vÑí ‡Ÿ7éñy/—LnØsÚÏç]ùë%öc&®ÕƒÍew/>îòçn|xeÙÏŽÿÁÆòuëνԭsrž¼@cÊkä|o·þq,|a´”½z¹Är 5&K(g –Ew¢p.8ßÓ@€ @€j x®1IdÑ?&žÿçµ2“iLk¶(— D¤ìÿkiLóW†-%·­©fÖ²÷¼÷¿j^V3(*ÏÌ\¦m½£4K’–®ÿù#¾zŠ%[úö÷ÎÑ ®Mߪ(ÿ„¦R\ ŠË®&w5¿bS¹Í׌‹¨KVŽ ç¨0©´þÅnËTQk/…Ó/5[?®¤1)wEm¦ðp)CLÿNѼ¯› L;Ü2r˜N5©´Š\Ó"”Ö¢3iïËIqWAc⪘%æ0-”ÃTJNc É•&-$÷Ò>iL?¼o©¾×w>½þËW>/)p˜Öí~jþV9LúnjrTS}L{©’Š©ß Ù·?ˆÉ”¥`g²-Ò˜îê9L¥®Ì$iÚüU5·Â{àÌó.U kºyÝ;áiç[ïzèÓŸ;NCZ7ÁÅk¶éÞ÷ƒ‹®:碫l„Ož±Tw=íI1¨7Uî?Y>)㟚Ukè>ðÄÌ3Ï¿2P *K£ÊÊþO_üä?}ÑnmúŽÈ*ÐÎr¢Ô&4«@yu ĂҚŒº—é׿I˜*VAIcz ИÂ7¬¿ø«¿Q4¦Lö¼6Ê©t%‰>u»gl={ë ¼®±dÜP½`\$¡iðh½©ü\}éÕ7JW²´@g]p¥Ê]ã' ÿì±f/ÿ¯'Ë•¼ãþIÃÿéX»Ô|ù_N6QÒ\ÉÛÆMÔE&œìMöÒn¸Mê’iL¿.Y’úiÒT`*%P,_mÖ¬Œê’ÁÝ<œò­ì÷oël‘å}k—SÌÏÃæ0-“Ãdq)™Ùß¼~æV–ÿ£oßÝÏ®?þÊ祢N[¶íËW<¯rů—èr-nr˜ÆÏØ$\z°Ñãå˜LàÁ&’0rˆ× %grK³ ñTž{hL¹¡0]ÉÙGa5ÓeYj¨1Y.ßp6&[­ÓÎIñä#]ú @€ @€@#hLöÏ÷52“iL–6©ª”&H¬he꼕îת‰“—÷kÊö—w=dZ*M¢hû×=­_e)é_ð­þ­ŠÍà*Û„\%ç-)÷’&nÝÌÊCOͲ'|彿ž¢)–O}öX½íÏnלîOÎÔß…kºE?Ÿœú¢–º°¿WÑD‹¦[”šB&®i]ͲèMº<;o¶5Ëk“»šzÑŸ«èÏÇõëq'~ã¾GƒlLöç㚃ùÄg¾¨ ˜[ï}J‰+´¡_?ñé/êÏʵøNx2ÆiLn>fü¤ÿëˆ ûÔôó 'œ$iäÙ—ªÜ^јnøLÇ|ê .›…ì%m[9õÌKk&›nWczeíÚßÝ~r9Ü1OÛpÉ@»‡é¨a {·ºy>7áê¦ú4Ï'IS}WÝ»dÒ‚WJSy99iL ¸lû'Îôèì-úZ›õ”Z!ð¶ñSÉÉÔn\¼ÚßiLue&iLSç¯,ßC·Bw<óÜKUÂÉËÛ›_•ª;â+§èöçR.éNç¼%MrßrçCº£E<Ý÷üíûî?Yï[ŠAÝÑt³“R ›ÝïÌ^Ò­M·­°R „(áôK<»H75í³`ÍîÈMÓ/ï}êýøˆ².Y*A LA6¦’Ãô7ïù»/žp’eÔêòë~¥»’ngæàêËõ…ãO²[Õ»Þýwcx¾Jº]² É«¯O2õEc:÷ÒðÓud[ÏÞz¯{©ii!抺To‘ÊàR#iIËÆ™Ìd‹ÇéRS*W¨Ø_¸ ¦ö7_ú—oè:œ¾ô‡7ŒÑ£rpÁ)ÙKz`¾ça9L;ËSÉ•´˜Ìõä{+'aªv˜Üãq»ÏÿíYðû›Kày8p˜>{ìÒõ;Ã6êïðó'|»¶ëª®ç™É _‘BªÇ{¥b 4¦5Ƥåä”cRÓÈ›æþà—/ˆLÙaâÁ&™+µtSבrÂø Øj˜‘lLôÒ›¶Øe³EåôqXc’äÃ" –Çß j€ @€ @ oИœÆT-3ékŽóûç\f‰+¬„W”öé/h2F³¿×Ý2.˜’Y±ã]ïù;MÌ|÷ìKULc²µxþí®ÇeZ<2e…f‚õSïØdð?ù¤Sϼ$œ)œÖ¢õi›:SÞ®UÅn¯&]p¬Øâ²²•ÓÒ”æù*«hí•ÆtÕ½KõÕ¶ šö &MKS}çýj&Mø¹UW\Æ‚ ŸYIþÃd*ö@bï"SDf’Æ4eÞÊèm1ðtUWåŒs/QqcØmÈRÒMmÒô¥auI÷>ó–´ŠÓu?»Cª®~ ö`z[w=Ýæl '[ÎI‰—t/»ø‡?µ„(Òp{~ñ¸ÇgèWY?.P œ•û£ŸÞ¦”ß8õ¬ŸÞzÿßÓÀMKÈ•îh¥$‚º£­Ü©UPMcÒÏ»&LU‘}kw1•ǦõêöÌ /ékuÙµ·J½ÕÏÏ’-$g“³ ìV…Æ4ÄÉáµ<јΨ"+×]jžŸÛ«'ðÚKM$ÙR$»Û ÙLKÕ*˜t©‘½dê’]jL` ԥʥF®¤ŠK¿$ÝÿÆ_=Pºwäpú%]gô -WòÊëǸdoQ)¼`eUäê&a ìävµþ:SlÏÃe‡i]äÁæÉy[”ZÒ=ØØZrJ0ùÈìÍ–?OÓ÷,Cý¯Çøé/éÁFy˜T~ñij»,Ç$6\!sI)—a£Ñ°Æ¤ s¦!¹Üu­jLJÎäN$ ª»¹ï @€ @…" )âñðk)3ÓÖ[¿ý©UwŽÄ½ù×ïzÏss{]%·qσOkÖV¿º)ÛÒºÁªp𦕥䤥›ïxÐ2-s·%YAÅŒ%û+p[ÕBÿÄoù–lŠÅÒ,Y‘¤ ]ýtë阺äòRh~W½6ÝR^3(õAoJ` VØY»[³/šz9íÜËU4m ?×êT¶þŤY«ôÓÜÑt¯¦a4Ý«)Íøª(_…2I“1½å¿&×ìï×ýê·¦Z)ÙKý—ÿäV¥_R Íkú!ИκԒ0Íè f]î¥Ã;L3ÁúÕ&ƒoºã1iLVäiEcúäßÿU4##Ðû/‡yÔ1/¬Ø¾˜¸,¥\ûlÈ’Æ´ÄéÒ˜ÌaúÕĵ'];Có£ú2~÷¦97LèÈXPZåÊMvšÉô÷ü/7ÏùO&©P Ð -3wÔð¿–=ÐD8ý—¨ÔÞuû»ûÁÉ2™,¹ mó–´`œ2 Ú¯”uioxÍ8ÝÚ‚T(¥»ž$ÝüÐQ÷?1C?Ÿ›·ÆL>Kˆ2ö±î§»›³rÇÜ71¸ÙMmM à†îhAN˜ô¾3q•‡I Þ·[˜4¦pAÝÂÜÝJÛJ¨bÒí¿žrƯ©l 1êQ9KñFcª#Dºk‹ž½õ^÷RãR™ÖJKöŒm·Ôȥƞ®]*SY5N]¸Ô”®6îRc®d9ýÒšÝÊ÷fÐ&ߨüðú1z~V&]atyðé…Ú?ya‹“[j¹j¹ð"Ë%W²uIÏÃÑ Lq> Í9î°c>ñ™%kû]˜ìÿƒtñ×_5 ?o’]ê-Ù•hëyæáYÒ˜‚ ¸&%aCý¯‡&eiÒeY=ýø¹¦š›ÿ÷ƒ΃M+wó¶ö™°æ½oÿéÍ,]óß4¦üÇÐÛ8ûHÙ”ÜB™ZoN¿ŠI«SxE:åq’ å-P:@€ @€À æÞqèçÃý-ÿe}‹ë'G¬ÿ‰UV©H¡¢I”gç®'R²íË®¾QÓ±¶è[° ÜWN)[J%)–JS)×þìýúÔ´%á9•ž’±¤¹[›Sq3+JAüuø†àŸûµ!KI³¹Ay|ÆÜž Á’M´¨È[Òb:]õSû›æÛÆMÔÊqnºEÓJ¶dê’–3BÛúi“¦ 4㫟ÊTL«vZ¾ [9N“»NfblÆ4¦ðršôÕÔoyEŒÒ”k!9å^R ÍûêO¨å0©Ü6>Е\ ÙKV4üG|Ø&ƒo¼ã±oMczßß¾{ï“?}û‚¿¨èý½¿ƒßç/~Æú~àºaÃ?ô?~z®»˜„sÒè",$WIW0zü ûjßåó&ÙŒéew¿xÙÝ‹mmšŸNèýÎMsl99i‚úŠI Œ¤1þ¥÷_ö/OoüÔ3}Ã)pžXDÝ Î±½Þ³ãê¿ÿ‡*s·ú†ÜûLc ßu7t·?Ý u¿«¬xKºK^ò£ŸºQu#S®A7±­›]ÉÐ f¸ï¸¢Ô[s•©ô-ØSºÙÝ %×|§œ~î¦èîví÷ŸtêYúš¸l‚n!TÝÑdw´Š‰+I÷/»‘ÝñÐT[<®œA°¤ÞJÀÕÍë¶‚rêY—ªAéô_Ýÿ|Dº%á]'à‰Æ\Ijžº¢ôìœz_jÜu&üW•§ëŠ·z®vO×ö\mE¤2]¤2Õã´e6u—š«z›ŠV^¶Kr¼ýè†Ûì)ZEKÈé™Ù&Sÿ?ñé/\uý LºÎXÖR=0k»þr¡ LN`²;xvÈJéR$(­Ö%[_dy÷³w¼uÉ{ê?ßvü¡§¯îb9ðð¥ÃüŸîÁÆÅÅ‚"'û®gÖ›À$Úã¦ö}ùŠçíÁFHå0©ˆ¡®ÕÒ˜Œ˜ŒÒc/{îÉy[=ØüÓñGM[wã²í×ènEé =è‘àõ?níúuÌë¢1yþ|wÞiL£K/ëÌøñãMijUcÒ®R—¤>ÉgÒ‘îDùfCë!@€ @€@× Œ;5ú¯ù?9âPïDÕ£Eå>tÔ1ÑyË™T)šDyfΊð”‰ùIî¾+é%þø[óµãŸš)WéÎ&i‚V?%-©Ì[ñJØX RPT¦Ul×RPØäŠ[!nNÏV›Ð•¨tõOo×\‹&tµ}ã˜ôþ¬¥[LZÒ¼KyÁ¸Òô€å¥Ð¯þvÜ–½Ð$®æ]LcÒì‹fb¦-Þ¬eã‚©—’ºtåè1š€ý‹q¶àÎß¼çïlRAkîhVF“¾®h–÷އ¦Ø¢Vôε7•Q¡ŸÒ˜ôgå–ÁBsÀ¶xÜ1Ã?ÉoÕÜŒ&efÒÒWÿð¾µ4üÏ_Ö²uCÊÆô®w¿gÓö×7¿²§¾Ì´pl×Ç'„@80|øð “ç†sE¸k‚&üî|zÝü•;å-M|á[Å&ø.Ÿ7ÉfLo}jÖ[™¶d»¾•A6¦‡VT­ºšòT³¿z²¾*Û÷þáOï¼ÓAk9¤¨j•3éoP—µ¨ÜÀ-¯únh÷ÁÓ~pÉiç\¾ JT’°«Ië’¶{”Òo Ã=9Sc[Æ’o*KKòwCª®K.6te,)]Ÿ/iC‹¢ê[ðÌœÕÚA?¥1év^ÎÉY¹˜tG{è™…¦äÖÞÑô•‘º¤$‚³{ûϽl´¥_ ndN±•O©¤ÞÚ¨ºsÉ*8û’ëtçúÙÿÙ8w£Š»m…M&4¦¢~SRì—'“.&MžÀŸ™hLÕÙ•Ü“výLKîRö–ÂyL%-ézbËÆ)å’þ@Õz–¾iÌZ-NfI‹ÇÝú€Šý€Ë½¤{±®BzÀþå½OêùùØß0{Iº¿=9Ûc³®6_ûÖ™î™9HYº<0þËÏÌ|\Z1­e©õlLö<¬R_fŠáy¸ü`3©ÎƒÍcs_ÖóŒ²K>:{óͯÖöm“× bKZ˜&ÉÙ–`räMsõT#Ïéêû–}íÇÓ–“ãÁ&þËîþhLÝÇŒÆÔ}¦œ1!Nc²uá´"œeVÒ¿›©ƒhLò–üI÷=9_À*÷>9ÿó_>©ô—åÛ?6üóÊÀ¤Ÿ¿~|ž¦dä0i[嬋¯SÊ¢rnÚÆÉLº0”™)†i›Ü} hpFT&üæ„Ó°Y®Íó)QÊ•¿^âòÍè»|ÒOfXºÍ•^z×b™LÇ]öÜ%w.j´êJØaÂdÊHÜ3ÕŒ°Æ˜¬‘Ò˜J·¼è­ÐÝO;çbyºn ë~7_ôDcÒ•¤ÑuFW˜É³Vè <Ÿ—šêôKã?X(­Í L‘µb;xÞµÿÍà1øò÷Æú<ÜèÁÆþï¦êÁÆœ°&6¥Åõx°Iì’…Æ j4¦X°rÒô  1¥Z@€ @€@¡Hg)-!Wû2©VHªäL 2'ieÒÌåUZ’S”B~R#EÉM܆D¥´uu¥r"–jcÉ–`¨*-zK¥$.UÞ’ì¥ÞòÊÎ^ªQ—¢s0ÁÔoåïÈKöÒÀdÌ€½40û;T{ÉÍÜt¦1Ó6z½õf 3­R¨ñLgb&ðÆÞþÉ#‡©¼ö›¾HU/=7~ñ/F ½~›ðÿÔì°ÈèæùÊ_öòT_`¦Úaê/ça*͆NSª³ŠiÑÈajd2õí뛼qòлÃòE`ß½n ¹Ú–Kcš…Æ”¯ñŸ‹Öú¢1}qõÚÊå|¥vyѳ·žÀ»x©¸Ú´{©)=H7%뺒µé—:s%;ÎÆ¤»ùyXã^2Sƒçá®<ö´ò`SÎkUÊœ×TÎîüÁÆ}ÁyÂiñZ‡ÆÔ"¨övCcj{ç†SnBEC!@€ @È;iLüÈ1áÕmj·5‰2qÆòæûÔ(JU¢Ò€«T])ª+É[*ͬÔ1–*kèDçtKÐÍ·T×[ZYã-ÕɺTO]ø#òª…04SÏ^*Íþ.­Zp§õÄKu÷’Æ”÷JûÓ ÐÄUšwíH}Ú•FiÂïcÇ|â'g—¯¦-VlE·~M–—ª©ÎÃTv˜*_·æ“™Lý¯þ!Üøa÷ ëéïéJw8IaHcj~Ë3©êžXå*Õxº¡œ‚õ¤¥*C7|«Ÿu)âTßÚœ[^uyý ·t «£´ÿBc*ÌàÏNG<ј¢W’êå&u!ÒxÓKM° ¥•HúRËcZNíV~®îê¥&"J6X<.z©ÈTÚÉ£r|ÏÃÝzì l†Ul\ìÁ¦’„)È;èƒMkr¶=Ø xZÕ_`žpZ¼ ¡1µª½ÝИÚãÅÞ¹!€Æ”›PÑP@€ @€òN И>|L Éæb÷hå©é=n¦$²Q^ú­ÆOj¸\ÈUª«+Õ® WþÛå²±ÔPZŠæ[ªñ–ê­¬N¥Õâ" ÆUg]*嫈Lú–fb¬Lm?wE[bS|Ó6y½´?šÌ{dÄáJŤ ecš6j„Šì%«ËR4Õ¾¿âÞѶçÞõmXA{÷íÿè1Ÿ÷ĬˆÀTZo%ÈU0øT_;Óö½ø·ßqÐFNyø­‡xd„ÞÑöèù£µ=fé˜ñ«Êž–}¤|ÚP5½ i¨âçì.iLOM_ÞÄÍyÖ(•*{ Á0² jé–M+ØÄ[Ь…: %¢.…”ܺ« º„(ÝU Ü ©»#³‰€'Óȳ.n”©TW={ë <ÆKMéV[»ìrË—š†iÞê^j:ÈôyZŽéy¸³ÇžWæM¶ÇžˆÛýêþš˜=Ø(Õkéï%ì4Œ’Ë>uâWO6W©Qу͟Þx°i÷ Çžì!ÇÛ+S,¡GcŠ+'MŸSú1 € @€ xB ¤1},¬ÕnkåÉi=îýyY÷wÞáJ:¥FI•ܪp‘¹[÷kðýMŒ¥J¦¥ZiinoxI@Zª›o©â- ®.U’UD².% .…gnbš¶ñd„ÓÍÈU2Émh!9‰JzG†“~jÞNxÚÞ´öÑ1úÈ<'¥CÚªÑL¦±ÏtþbyJÕÖ¯)-þ¨/r g yª/ì0©‘ýû•«@•ä3I`:øÇƒšÉsù™ìS—Ï@S}Îpj«ìœ/Ҙ·¼Ú{¢iLun…¡Û_­®¤{_í]/t¿«– jR.EB ßÝʉ—ª³¡Ø¼¸•ºn\4¦|ð\´ÖiT“'p]ˆôžÀ¥&òD]wyÊÊšqeû?Xg¹Rš‹’ágæ¶$þÚã{n÷±gGÏòÖU´¡5éÂ_+3™ÜƒMD`*?ØÙ%»ð`S×ajý GÏ<ö`£G =ääââÐõF¢1uipB4¦X°rÒô  1¥Z@€ @€€'¤1}àÃsK¹ÕÝø«¿~÷ãÓ–9ýhðÒŸ7/u]¥Ì•D,šY±þÓpÛŽKµÒRdÆ%*-iö¥2Å[™€©J¹ToÁ¸à/¤ƒRYëaˆó1-ß´'ƒœn¶KÀ\%½¤%©X¦%éJÎR’Õdéšl7í¯)=Û¹])¨¥d2ÝûØÌ*©j!¹.LõE&Õ«©;›´ ÏÞ™º¤×œ­s,9“ö‘ؤ¢ý•±©]˜ìŸ;Ò˜ž˜ÖS{7,™IA.¥ïž9J¥Ñ­°C·l,UÝòêÝ隈¹ƒªKA6”¦+ÇuñF†Æ”»Ažý{¢1éJZLÙ®09Ûôì­'ðü]jªWŽëâ:Ëñ=·ûØãŠôØ#»6¥™Lö`ãRKV¯ÛoX`šŠX÷ò0Ù·»•'9Ü&j[ñ6!S,w4¦X°rÒô  1¥Z@€ @€€'Lcj®ý¥4¦©Ë5“–~«J§4°bEtéŠW©®®T›cÉfv#™–j¥¥Zo)ô÷â–£¢·TY0®”¬"u‰lLž|3ØM§"ÉR’“äì%½o‰—¬Íò–4g 4ÿ§÷]é Se“éÑ™aI±ü¥®Ìó¹©>ûV¶µäJ­Ã¤Fj‘8YJÚ¨$iI.?“}*iI3|¶¡¢ ÛW± Hcj~ËûΙ£T¦VªÉ&ØÈÐè¹ÍÝܰ·¹»U¥Bi°þi¬÷24¦b#Ré'SÝ+‰»¶èB¤'ð„/5•Çé: .‡Ÿ¢-µë¥&&©ÝÇ}#Â=»•“©ökR6™Z°©ü„ºÙñZr®­<áØZºö„£bOD¾Ð˜b :S,X9iúИÒ-€ @€ @ÀÆtäÇæ¯’lÔ°hå±)K„Ôh#økãÚRI§Ô(©Ry·´tTÝR«+…Œ¥òÚu2-ÕI¶Ô¦·Tñ$ZÌ™ßn1MÛx2Âéf»œ«äÖX1QIçQÊÙKÒ•4ig§µ÷õÓæðt¬û¨ÝzÍdºç‘¤¸"(³*‹d•¥ÃRº‚p:´§úê:Ljž[-N˜ô޲X6&­.§eæô«9LöŽ>ÒÏvûÅþ¹# é±)Ë܃DJß9ã"•ð­°ù½¯6›`d…¸ºnno©:•`MÖ¥*·”A0æÛSîyöì‹ÆtƨšKÍ@¶6={ë ¼þ߸çíÐcöP/55 SF²–6U—ÊÒ|Ã:sLÏÃ<öèICú5OBi&SäÁf SÉ:íìÁ¦ÑZrî«ÝÊŽe´CäsOÞ,ìá )– £1Å‚•“¦O)ýÐ@€ @€9S^ÆvŽÚ鉯dW’FEÏÞz¯ÿhØ¥¦6Á[(™Ø¥&¦çá{^™7YÏE.'e“o–™Lw•lœÀ¤ƒƒ͠S‹O8¶›o,ñdŽ®Ým*Swy–φÆ VNš>4¦ôc@ @€ @ð„€iLÍæHzé‘ç–JEÔFj˜N©’^Å’¬„Keî¶”y¥2}[w7ô¯ÿQc©vy¸*iii @D¥%%¨¨,ߨLgÅ4mãɧ›ù"`&Ó]¦›•h&b)WÁÀBr]q˜ò……Ö&I@Ó#Ï/Þ7(ºÍ}ûô‹TeH­ÔàÆWk, *-Eîqeo)ñ¬KnahLIŽOOêòGcrIIí NÕöðsKôÞÅK=H‡KäZ¿Ô¤òÓçá²ÉälL`êôÁ¦‡É“«D·º‰ÆÔ-’UçAcŠ+'MŸSú1 € @€ xBÀ4¦ÈI)T4‰2á¹%µR“wBr’ü¤:ŠRQ)˜_‰¦V2oi{]]©nš¥üJKµóÄ9¶ñäD7»NÀL¦;&L+µ«&¦®ç„Ò˜‚[^õ}pà×e©µ;ààznm*ÁÚ;]o)™ rŸBcâKÔužhL"£—šë?áÙ@cjt©©~ÒŽïR“¡”¥ù}6“鎇†ú`ƒÃÔõKNˆÆÕChL±`å¤é@cJ?´€ @€ OHcúÇ#?Vc™{T.šDyèÙk³%™Š)µê]çú–RÙUª] .ºtNh:ºR~Ò,µ˜œ)¿Ó6ž|‰èf× ˜ÉtûƒÓ¦Ö|‡¾–\×[Ë F@ÓCÏ.ip[ \o~¡J{·¿nnÝû]=i©bdò‡ÆT°¯@ºã‰Æô­Ó/ªc#YvÒ;ôì­'p.5îi9×ÏÃf2 åÁ‡)¦KS,`јbÁÊIÓ'€Æ”~ h @€ @ž4¦}´¹{¤I”Ÿy±®Ô mRdÑ·ê\JZ%ª´PTÝ20}[í*ù +5²šr=mãÉ÷ˆnv€™L·Ÿþ^à0u3'¬% ©þ-¯²Ó·N»PŶp,ÝòêÝõªîwy^ü‰ïQ× ø¢1Ù•¤AÑ…HOà-^gÊYÜ }©Éûó°™L=Øà0uý"ãNˆÆ [4¦X°rÒô  1¥Z@€ @€€'LcªYÔ¦ÊCú iLO/¶5ݦIl^¶±±”¢~R¥T_T*ežÈ¢9-fNŠc·¼OÛxòU¢›]'1™p˜ºN˜Ö%hLO¿X}[,ßþì&øÍÓ.T)ß» Öu• &æ¢1ñUê:O4&]I*—šª‹Œ]jÆ?½XOà­Øà0uý >!S,xјbÁÊIÓ'€Æ”~ h @€ @ž0©61RxFä/þêÝ<½¸¾‡d6’J%“DíÆÔ¥Z Çʶ:Å{KiPó©Ó6ž|›èf× 8“©Å©¾ÿxû®·úF@“ìú‹™–îw§|ÿB•F~’» 6¼÷-Ù6èe?_; 1ùöI ¿¾hL‘+‰{¨.mèÙ[Oà‘U&?f׿ï¿ý÷ì?Ëd:úcÃZy°ÁaJàò…Æ d4¦X°rÒô  1¥Z@€ @€€?d2)'“{=õô´.\n»çÁÈ;üš$±&Þ=î±æ5N›Û“ýi¾Sô´»¶mï—¥ÔDcÂaê.pÏ϶uëÖð=qêôY‘˯.Ⱥ,'yÈx]­<$¬}y“ç߬¶ºïƒÆôæ›o†/5Ú~|ÒÔÚ«MÆ¿þ 7oÐçá¹‹×æâyxÚÚ³Öþvyó¦¶.ïŒÆÔ1ºf¢1Å‚•“¦O)ýÐ@€ @€¼% ,>ͳžði.ÉÛ¯p!;®Ä-L&¦BF<;úÿ¿‹k~îI6¦ì ò ¶Ä©{sa7wßñŒ48ƒÏÃo¼µó×+þlê¦Mlp˜».¡1Å‚)¬œ4}hLéÇ€@€ @€ à-4¦ŒÌ» ±œ¶ñö;EÇ»B ®É„ÃÔ¶œ¤ 4¦!ÞŒŽÆÄ÷® 4¦˜¾wž6ƒÏ˶WÏa*{~ß[k2é¦$/hL±ÐFcŠ+'MŸSú1 € @€ xK©s<œ¶ñö;EÇ»E b2á0u ,çAcJþƇÆÄ÷)B€lLq\ˆ²öÔ!€ÆÄ°€ @€ @€ @€€wИ¼ ¹gFcJ7àûÞèUê–'Ö‘nÛ R;SAI7¢И€ @€ @€ @ðŽ“w!÷¬ÃhL©|ÚæêjL[LL½mEhS¢Hê@cbX@€ @€ @€ @À;hLޅܳ£1¥𺠙HÅÔµ¸ 1u %'Ê4¦lŃÖ@€ @€ @€ @ hL @¦Š  1¥ßU]›‰TL]‹ S×Pr¢l@cÊVmiP¦e›ÊgûÊØ±ccÌõO‹Æ”(n*KŽSr¬© € @€ @€ @!€Æ”‘@ÐŒ˜äKcz|ÒT'-ÙÆ6•’·¤ró­Æ4ˆÀ´ë÷USlÓ+“d¦*éåÆTÏa 4¦’ÃÔ\cZºÑ9Le©ÖajQcš¿ZS 1SDcêÝ9 1•¦æÓôŠÆ8Li SLßcNë#4&£NŸ!@€ @€ @€<'€Æäù(|÷ó¥1=6qª“–².•/½ñó_Þ)©nú%åaröR9 SiG9 Sçy˜Zu˜ö»_Ó#OM [J‘í’Ætr8ëR9ñRT]:ørÿë/ïx}s¨(ñ’+/mÿÔ¥{iÛïúBÓÆß¾&uÉJT`zåÀº­kɹ…äÖlÙ¿Z¥ÁZr-æaj×ajq9¹*ËÉ•W”[Ùj*¦™Ëw”KÏ L¥²ÝiLnE¹p*&Ó˜îºçÞ?üûÛ®üû[oÇû5;í°CãN· Î4 1¥A:!@€ @€ @€ *4¦TñSyìò¥1=üäóK)üëM¿4¦-i)šu©V] å^ ¯N¿˜œ½4¨ÀÔ, ÓËûWm~Õ­%ç’ÓÆŠMûV¼”åVúöõ”ËÞ„¦ËÉÍé퟽¢\f­¨¿œœ4&-'g“s˜¦-Ý^Ö˜J©˜Lcºñæ;ÂÒ˜¶ãåhLñòåì©@cJ =C€ @€ @€ @ -hLi‘§ÞdäKcšðÄó&'Õ–—ûÞtËÿòµ“µ$[ª‘–,÷RD  /Ur/5²—Âé—:˜”‡i••ÀÔ, SµÃ´,¼–܆½KK%XH®ÁZræa²Ã$i@cZº}ÀaZZv˜Ð˜’ùRS‹'И< 4Ý„ @€ @€ @€À4&FC± äMczN‹Á…Kxa¸o¹ã_¾zr£¥âL`ªï-iÙ¸•ã~'oÉJgé—ÂKȵ.0µ“„©ä0­Ê‹•²xÝžRÙ½Hem¹,\»;(kv/X³ËŠ–seþª]ZH®¼–\7&Ó˜‚TL &4¦b_Lè]ÂИNu€ @€ @€ @HŸSú1 qÈ—ÆôàÏmRF%+%-)\´ZÙ‰_=Ù½S6–BÉ–ò-µà-•/ýæµõ¯eÝ+Êeë­çÊš­ÖlQÙ_¶—¶ì—º4`/µ©žÀ¤åäöº$LK7–30u„©®Ã4µ¦Ã´r缕;çVŠ–s¥Åµä$0Y 4¦ÆSœ_eÎí4&ïBN‡!@€ @€ @€ €ÆÄ(6|iLãn@Nª^NŠÒOo¾ýįœ¬¨®TÊ´¤²q ”ó-ER.…׌«R—ä0uÉ^êÝôê •—öYYn¥OÞ’+­ LJÅÔI¦ÀaªJÂ4à0õî˜zûÍašeeù•™•2£g‡•é=eI“ò0™Æ45(ÛTä-EÊgûŠl³ˆïWì´Ã;5Þ*8;Ò €Æ”uê„ @€ @€ @€@ªИRÅOå±È™ÆôØsÁêoµ¥d)Ýðó@c ¹JËÃÕ.g Æ­·RÊ·õ–šªKíæ^jd/…¦½=»/0…’ë0 ÓŠ*ifE`š!©â0 ɕ֒“ÆTv˜j&ó™Ð˜bÿJS7И¼ 5… @€ @€ @€@…c¡Øò¥1=ðè³&$Õ9I×ÿÛí#¾ò ó“jKÄX*yK•uâlck4å’VŽs Æ5[6®ñÊqe{iSuî¥Æé—´œ[BnɆ½K6ì Êú=J¼äJ‹˜š L«ªV‘›Û~¦Àaª,$ç& L%iÛÔS±/&ô.ahL §:@€ @€ @€ ¤O)ýЂ8 äKcºÿÑgÃ~RÙLª$U-é_¿áR+U6ª]¥ÆÆR -5õ–VKWreóþU›_]Y]$-¹Rgå¸Ö쥥!{),0Uì%-$·{‘ÊÚrY¸vwPÖì–·äÊ «w¹2UãUäV¬"§åäl¹ÊBr’0 ,$ç&·œ4¦Ú…äÂï)Îo3çö‹À Óøñãûúú ÉÁƒG5räÈ9sæø‰ÞB€ @€ @€ @ XИŠOz%/iÜ#Ïi“”ÑÿvÛ ÿúò§õR+ITrEÆÒì7žúýsNüê)·ÞýK¶¤w>ó¹ãn½ë!IK*OÏ\6â«§¨h#ì-Mž±ôG}ÙÕ79oiÆ¢õGyôÄéKV¼T{©oߥ?ºñ’ÝØÓ·oê‚u=}ÁÊqÃ?{¬~†s/•쥽_þ—“~q£ôKN`ºèÊÞÿÁ£T.¼ò˜Ž;ñ?»°y¦ú óVîœ[)ò–\i&0-ß1£²œ[EN©˜ÂI˜‚ L¥$LhL\b ÐERÜÙ¤$ICÒ;ýýýöf3iòäɇ~xOOí:lذ1cÆèWmè£.6‘SA€ @€ @€ @I@cJ’6u%O _ÓØ‡Ÿ «H‘íë~hLöf%¯RtU¸ðÚpò®¸æ¦G&ÏÖÆ½ž–´ôéÏwù57=lï<ô´¼%mü⮇T´¡ÜKNZš0qö{Þû>½é².]võ’x|jÖòRÖ%yKVκàJ•°½tæWÊ[²âVŽ“½ôÓû_øÈy—_÷„iÁÆe£e/ýÍ{þN?¿ú­3¿xÂIw>4U?Gž}™¦w½ç﮽yìÏï~âñ™L—]{ëŽ?éöñS~pÉuÇ ÿ|‹“ÉLhLÉ…©±ÌDj¤1ÉpÒ§Í•ÓÇNc²m©OsæÌ‘…ÆTÈC§ @€ @€ @€Þ–À„Æäí5„ŽÇG ²¨ÜøÒK&’^ª´ I{['•‹/Zœ€ @€ @€ @ @cJ2U¤H _Ó=>]×F²7,éÄ“";”— ƒ ü¤ÚâR+Y‚¥å}ûTlÛò*•Ô¥òÂp2–¬HW2I?ŸŸ¿vø?+iIÛ÷?!©,-¹¬Kgœ…Šì%K¹¤RÒ˜vëW·fœt%˜L] — ®¸Á¼%•“N=ëûç^>Õ.­g‹Ç]yý§.Ùâqóž÷)ýÒ×¾u¦-!gê’~*ë’ì¥àgiå8+Ò˜ô޼%+Ÿ?þ$ÙKç\r¶ßõî¿û×SΘ¶tûÔ l J)åR“B6¦¿ËT]<áÄI}}}ÒÆŒ#“iEå D8“ —v«Ó=‚ @€ @€ @€@á  1>Äžw0_ÓÝã'×U‘ìÍk~ú+iLn·\t£$*M[°N¢’eWºùŽmû=û>K*J­tÊwϾóIÃ?{¬yKÇÿëÉw<0iéÆ Ç’ÊOÓ’ {/þáO¿ü/'«HZR.%­ç¤%—uéŒó®P){KëvK]’ƤŸr•ÆŒhkÆé¥\Ò;÷>:]+ÇýôÖûÍ[’Ã4ýÅ—µlœ©K¿¼÷I¥V’½”•;•uIÒ’Ô¥R¦©æ-IZºkÂÔÿuÄG¤.©Ü\Z-nÖŠÒ•ä-éç3/¼¤G§ö*ý’r/)Óôží²—”I嚟ßwï“óe/MšÛ'“©E‰lLž_Iè~œÆ¤5æ$0YZQN«Ãi£lLJß${I2“ܦþþþ8ÚÊ9!@€ @€ @€  1%™*R$;ɲ%Õ-Wßð«/x’[÷­f#ð“Ê¥d&IQ’œ¤|KRˆ~~ûx½#uIïœyÁ•–cÉ,éM• ¤¥=å²~ÏýÏ´$QéÙyktøíã&j[ïŒ}lÆmã&êyKJ¶èJëvŸ~Þ*ò–>ù™/wâ7f.Ý¢÷¥.YÊ%-'oÉ–ŠÓšq¿~dú„gjCY—¾þí³Þÿ¸ÄK¦.}ýÛgJZúÞ9—}íÛgÊaºâº_I]Ò;R—¹—†}ê Z-näÙ—Êaºöæ±&0éçe×Þªw¾{Vðþ¥×Þ*{I_9åŒSKïÜûÄüŸÝñø?ñ‘Sϼä_O9ýcÃ?ß<ýRäS²1¥ø]¦êâgc’€$ I2’6¬§ƒhLJß&"õÉì'^€ @€ @€ @€@~  1å7v´¼ùÒ˜îz`’[Ö­vCÓq#¾Þdû(Ȩd¥”TéÇ7ÞnÆ’Š²+=>åÅkn¼ý¹ùkci}Pî7Ñ,¥Hyô¹Å¶BœÔ%eZRyä¹E’–¤+=òì"­÷ÌœÕÚP²%yK*ò–T”lIY—ì§\¥[ï}ʼ%˽ôÐ3 -ëÒÄY+•xé™º¤b ÆYyrF¯ì¥[îy≽ºÔÛÿÀÄ–{IËÆÝñÐT-§rûƒST›Ö+{iFÏŽÛÇOÑO•ûžšÛÏß÷ä|9LÓJeÌÏË^*-¬7áùå·Þÿ¼J[“vFcjåKÇ>h‘@OOOxO­~g©Å:Ø € @€ @€ @È4¦‹¦v@ _SxY7ÂåG×SíûNQ’¥4QÉR+•D%+µ¢’½c®R¨Æ’J`,•¤%W‚åá\)IKr•ªJÉUrEÓ=L7o©*åR=uiniÁ8W¤.™·dêR©ê’Ф%WÌ[²b+ÇY1{)(eu)°—TÚõ–ÈÆÔÁ—ŽC ÐhL]ÁÈI @€ @€ @€ 'hLyŠmmŸ@Î4¦û'6ñ~8úViL­˜IµÆR#W©®®$o©ÖXTZ2{i¾JÅ[ºàòë§.Þä[ªë-­Üö–,ëR»êÒ ©KµöÒRg/êÒÐí%'3‘©ý¯ G@ ChL‚ã0@€ @€ @€ ä—S~cGË[!/©îânÎI’Æt숯×I Ó)U%UªÎ«d –ª\%ýZJ°TGW*¥\ §YrÛaiið|K5ÞR .UR.µžu©¾ºTJ¼TɽT²—– 5÷Rmê&4¦V¾tì®@cê FN@€ @€ @€ <@cÊS´hkûò¥1Ý6nbÔ=r‹»­Û}åè_{Â×k×z ¯ûV¸ê•àš¸Jt¥Pš¥z+Ä5H¶4··Y¾¥æÞ’– /תº4äe㚯:‡ÆÔþW# Ð!4¦Áq @€ @€ @€òK)¿±£å­È—Æ4fìÄh†¤PΤ+¯ûåOøzÝåÞ\"¥F¹”ä' ”ÒêoJ%ÁÒ€®¤4Kå…áBËÃÍ[¹sn¤ÔHK‘uâõ–föt¨.Å‘x©®Ï„ÆÔÊ—Ž} ÐhL]ÁÈI @€ @€ @€ 'hLyŠmmŸ@¾4¦_Ý÷T•ovÖìºBÓñ_«³CS-)¢+–’Ê*+;Ã¥ÊUª$Xª£+É^ªg,5––úg­Ø1kyP”c©ª4õ–¦k8W" ÆÅœu©QN&4¦ö¿‚  1uŽÃ @€ @€ @€ _hLù-o…@¾4¦[ï}ªIž¤+~òË/ÿ5·CYH2-iÀLªã'™«µ”B¢R}W©±®Tk,ÕfZª#-E׉Sî¥íÓU– ”zÞÒö©K·eɶæ+¾%ð)S+_:ö@W 1u#' @€ @€ @€@ž 1å)Z´µ}ùÒ˜~yï“‘ IîWIH—]û iLul¤°¢´r§œ¤p‰.ýV³ÜÜÞ~iIÊìÞ~)Já2k…²+Y)çXj-ÓRi©A¾¥ yK5 ©ý¯ G@ ChL‚ã0@€ @€ @€ ä—S~cGË[!/é¿~²‰u$éó_þÚ Z’YJ½*Íä$'-–R¨dÒR«º’Ö‰‹® 'c©%iiÚRKi)ù–š§tBcjåKÇ>è 4¦®`ä$€ @€ @€ @È4¦‚¯4?¿‚ïPGcŠ—/gOSjè©€ @€ @€ @i@cJ‹<õ&C ×S2ˆ¨%ßИò?Z߃€ @€ @€ @Þ@cò.äžuɳ€û×]4&ÿbîIј< 4Ý„ @€ @€ @€À4&FC±  1;¾ô И Xº@€ @€ @€ ÆИÅ&€ÆTìøÒ;4&Æ@Q  15²ô € @€ @€ @  118ŠM©Øñ¥whLŒ¢@c*jdé @€ @€ @€@cbp›S±ãKïИE%€ÆTÔÈÒ/@€ @€ @€ 4$€ÆÄà(64¦bÇ—Þ¡11ŠJ©¨‘¥_€ @€ @€ @hH‰ÁQlhLÅŽ/½Ccb •SQ#K¿ @€ @€ @€ Ѓ£ØИŠ_z‡ÆÄ(*4¦¢F–~A€ @€ @€ @ !4&G±  1;¾ô‰1PThLE,ý‚ @€ @€ @€@ChL Žbx¦oøÊ]?-vé×N;ìиS½&@ç J© ¥[€ @€ @€ @hL‰Ñ@ ÇИr<šÞŒã€ @€ @€ @Þ@cò.äÅíðä“ûöõ·ô õ 11. J© ¥[€ @€ @€ @hL‰ÑQ‡ßzxaúBG Ð*4¦VI±_Π1å,`4€ @€ @€ @C'€Æ4t†œ! F<2BÓÈÉ#•iÔôQÚ°bù™úök[úU{ªhŸ,4›6@`¨И†Jã3J)£¡Y€ @€ @€ @ˆS|l9s’ƯofÒ˜¥c†Ý7lÎÖ9ÿxÐågÒ¯¦1飞þmèW’d © ±@cŠ+'MŸSú1 € @€ @€ @H˜SÂÀ©.&NKR¦%ó“”IÒ’U'ÃIz“Šv“Ƥ¢}FÏSc8-’#€Æ”kjJ”S¢¸© € @€ @€ @Y €Æ”…(І¡±dëÇ9uI¢’e`²7¥.é§|&ÙK*ÚPЦ¡×Ë 24¦”@õq@cŠ‹,ç… @€ @€ @€@f  1e644¬-ný8§1™®¤“HW²OÍaÒ†Ö›ÓnúÙVì ,@cÊbThS 1u"§€ @€ @€ @€@¾ 1å+^´¶‰J¶`œËÀ4yãd¹JZcNkÉé§´eæ´­Ÿ¶ð/äžSîCHê@cbd@€ @€ @€ @À;hLÞ…œCE"€ÆT¤hÒ—4&† @€ @€ @€¼ pàÍ =;®¶2móñwõ6gë·Ý;úÔ t€@ 1 ˆt¡4&Æ @€ @€ @€¼ ðöŸÞ¿ê/e/Õ½¯O½ @'!€S‚Hê@cb\@€ @€ @€ @À«wÝRWcÒû¾  Ÿ~èé¿æ•×&ùÑWzé%4&/ÃîC§Ñ˜|ˆ2}„ @€ @€ @€@@ nB&R118ŠG@ºÞÜWN-^¿èÊИ %€ÆTÐÀÒ-@€ @€ @€ Ô#P›‰TLŒ”â@c*^LéQ4&DA  14°t € @€ @€ @õD2‘ЉaRHhL… + €ÆÄh((4¦‚–nA€ @€ @€ @ pB&R11L I©a¥SИ %€ÆTÐÀÒ-@€ @€ @€ 4 à2‘Љ1RThLE,ý*@cb(”SAK· @€ @€ @€ И€%d"c¤¨ИŠYúU&€ÆÄP((4¦‚–nA€ @€ @€ @ 1%dzbýú $’S!ÃJ§ 11 J© ¥[€ @€ @€ @hL ··÷¯ßõýŠGàÍ7ß<æŸùÎùG¯kôehL …‚@c*h`é @€ @€ @€½täQÇ<77ø‰ÉÄ0)9LŸþì±·Ý÷Øé?¸äꫯ.XïèÊИ %€ÆTÐÀÒ-@€ @€ @€ Ô# oéÃG {aÅ–ÞM¯ÎëyùCÁdb ‡€9L·ß÷¸†÷ŠM¯ž†ÉTœØÒ“jhLŒˆ‚@c*h`é @€ @€ @€jÓÑÃôn]¹ùÕÀóxißœe˜L ”‚¦Ï{ÇØÇWU†÷ò¾}§s19™ `º&€ÆÄx((4¦‚–nA€ @€ @€ @ š€9L Wn]õò~Ó˜–¿´¯§oß쥛ÉÉÄ`É;9LŸ1‡©2¼eéIcZ¶qï÷1™ò]Ú_K‰QQPhL ,Ý‚ @€ @€ @€@ˆ€9L‹Vn]ýòþr®šŠÆ$ÏcÖÒÍüÈ1K{–à y$Pq˜ž†wµ¥§á½tÃÞï}ñ•Wý(]£Í¨O‰‘QPhL ,Ý‚ @€ @€ @€@…€9L‹W½²zË€äa¹jzúö.ݸwɆ=3–lúà‡?¶dY&Óˆ#/½´1lذɓ'×EÞÓÓ£ê~Ô××wðàÁÕ¨máªG—^zgüøñêŽ^jvÍ£Š¡0‡éÎqO¬Ù²ÀÒÓð.%3iÉú=#Ϻø’Ë®j½" Þ6ÂõÒpmýðøötuÐ*Ôf}ûšï¦Þ zžXwp×Ú9sæÔ­‘/f4¦XÇ%'OSzì©€ @€ @€ @ñpSEò¨ZQÎI/®ß3ãÅ—>ÐŽÉ$ÑǼ½ä ɇ¨ëH¤Ðžu;ªÃÕ,ºB¨‘G>¹Ù!ò–Ô“«ÆŒÓÊ]i!'éŒ@Èa:ÐÄÒÓð^¼N&Ó¨ÖM& †ð¸ÍÎ`ÐàlQþSûý~¥®1¹‹€Ybj°»ª„‡_Ì詳KGežSæCD!@€ @€ @€ Ð)ÃT_ò0É$EkwO[Ô†ÉÖ˜Ô@çyHG°ì5£FÒûaiäÈ‘ö‘Þ×nR(tmD w·ö#D¢ƒ;vv¿ZzI«²´¡$.–PÇ* ·MïH½²wì´¶D5°: Çu“€9Lw{bíÖU©˜B &Z*¦Òß½píîïžÙªÉј4ŒñÆáÁfãG_ 97ü¬Ãnˆšê§3Ø>Î4r#6¬ÚI´g˜šÎ¯—$òE{í`'wûë§åé›bcÞuÊȨ̂Úö¸6X÷urk˜ë¯{'ÜÚÈi#_ô‘}=Õ$ƒãΣm™[|1«¾ê€b“Š:8‡ ‘Àê]·¼ý§7=‰s˜lx›¢wÓÃ+O¸jÊðó'å”]ÚÓ·/Þ‹¢Ã{Áš]'ýd††÷ׯî,½YËwh„³±ÉmÒïvZ;ÅÞl2„œf4hØ¡9ÈŠràª"€ÆÄ€È!S'íeÍ8Çz§¾Æ¾Hš6eRž£]‹¹ìæp0Ðd@€ @€ @€ ‚¨8L[á!½CåÖ§Ö¬¨,¶5ü<ÙÏ/ݸWÓͯ^¼n¦/]ñ¼$9Lã§oÒz[#6÷§z•ŠiÖŠ@ò˜Ñ³ý©Ùëßß8'SÁ±Ò½ø ÜÕsØøUÙ\f’ÃôéÏ{ÇØÇÝð^µyÿÕã–i„K¹“¢'OŠÞ…·-, ï™ÞZNîáY›¾|ÅóÊ4ö½›{íý˵`â5ãz¾{ÓKÅTÞ;¦/Û~Ê÷æd*÷^Ó£ç:ûÏ;uP̧Ѝ•”xEŠ‚ËñÖÊ!~íƒÆäW¼‹ÐÛð—ú‚+›­°i}“˜¤Å^µÑ0“ËÌf“[°VÇ„·‹€Š>@€ @€ @€ @ çÌaZØ»ÕRÔØ2[2<®»LnÇò—ö-ïÛ÷‹'WŸ~ó @€ @€ @€he˜žþµ­ßËÓK‘ðH»Èzâ%Ÿÿê÷^}ÚUч)B±ÓÖóß=¶ò Ó)Ÿ¼!v”‹Gl'˜RÈãÜ Û>þËù~[—vBy’é¼ ¯ßr÷I²zbLÅ0ÓÏúñs8è̶˜ÏË*ü;DmÇ&‰)¢—2LÑf,Êû3W~7õaJå}õÍ÷\ÕŠ1EyoÚ–Uø3"Æ”¶“Û²#:¥ Sí$ÓÀSŠ1ò„ß\|’A z1¦Fü|';ÂE)2H{cJ¹¥|§ÉâŽtñ[±ÍÜ jš2 @€ @€ @€º uÔQ§žþÏ©ýRJ/e{lµZÔDŒés_½ã“—}'ú0þ¹›OûÜÍ‘ðˆœGêÃ]j^vÊå‘aºê¦{â=cŠ„GŒsZ1¦!ÈyÿŽ3ÿœwÖµÿóÀè‰ ”(ðÑ­ÿË™çÿÅþÏüÓ妈1Eg¦Û² S´‹-ä¢JóòŽ S«Âc#¹,ÆåÛÉEŒ©+¥×É0Åç~qóÿûÿýçïvl–X2Ô\àÂãëöß#÷C`´@ôQŠ$R¾_dì+»Ë¥C¢3S|O†n*œâ‘XŠG:Ež‡Z½zujÑäA€ @€ @€ @€@µ±åÖa‡ö¡^E—:l¥5±ÁÖg7Ý ØH.5aúôÆ,Æ!7|èê´ÙV4ªI›mEÎcõwEÈãï?üõ·üú,ÆtýެS!äqÊÖpà!·Þqßí;ü寮vâ®ÞþäS˜¾~×úÕ®˜ã9çœó¢¿,/ï´…\êÀôÆ3¯yÕi_M¦(ïW¾ÿ«¯|ÿ¦¼¼ó Sì–xÔÉ—}ð ·DyǾŠGþãeíòînŦ}÷{ƦͷFyÿè¶~sÖa’Lç¾¼1ì&B€I ÌÏÏG)~MI¤Ý»wïܹ3’Hñ$ñ$¾ŒûcJMœòGä–â­fŠ&Lñb†šä|\‹ @€ @€ @€)ÉtÆG/Èãi­´‹\$<Ž›»ú˜w\;m¿ñö£O¹ü+›øÌ×1rKùˆÍ¶N=Û!Ç9ú0µ[1E†©;äQÌ0EÎC’I5–%PŒ1Lùù#Éô¿¬XÞ©Â#ÀtÜ™WG¦çÅH¦¯|£¯¼oÜuÁ•wD¿±TÞŸºâ»íäväÛÉ3L©¼ôÓ_þæ‡ÛzÃLbLe­ºó 0c‘5*&‘Rï¥<ž”wSÚiƸL— @€ @€ @€À ´“Lÿ|AÊv´÷Øjµ¨‰¦´‘Ü51n¹÷ê[ÒN[Y¦hT“o¶µqëÝ^uçÀF5ý&I¦).—šÝzŠ1 0åwI¦CV••w¾…\k¹TÞ}íΞòN{É-”÷¶·îLå}ù–=Æú3L I¦¸ƒb˜IŒ©fÅãvh˜€SÃÔt @€ @€ @€fT %™>ð‘ÏDû¥ï`ZØi«µ—\ôašß¶36ÛŠÇ7DÂãîhT! …íä†e˜F$™vÿ÷Ý3º ¦½ç£LùùR’©¯¼ïûz'¢ù¼vDoP†iã w·+<í–xÝ]©Ó° SW’)n"…™Ä˜ö|}A€¥ ˆ1-ÝÊ;  @€ @€ @€ÔZ ’L‡¶’L­öKíLƒ»ÔŒÌ0C£3L“Lk.[³î¦uµ–rsuxèW»–x;‘d:xÕQ ù¼îcň^O¦ñ2L½I¦¸Ë‡~¼Ä[õ6C@Œi 4‡ @€ @€ @€¨©@$™^pð Oû§O·ÓK·f[ÈeãæöFrŶ:}˜Ú]j6Ûê4ªYJ†iÇý?ÿõÃäÛؾòã+×{}¼²eç–ôk4gÊû3ÅÒ›wîÞ¿•YSP·U3³ÿé£vT^Þi“Ävy§&L}½® SÖilI}˜R†)ƃýªfn‡cjìÒš @€ @€ @€Àl ¤$ÓûÏþt¾ÇÖײxG!áqck#¹ö^r¶Z{Éíi¦ž S€Ï]7·âŒk¯ZÏ#Ï#š3û3ÅïÆoE»¦ø­x[žyšÍÅ2ë1"ÉtСGuåó:¦¼ SÏV‰Ùn‰QÞ2Lcp;„cš ¶K @€ @€ @€˜ˆ@J2½ïìó‹¦þ„ÇB—š’2L1¹h°ɤx2ç|zx’º.¥^Mé•ÔŸ)z2­ú̪‰¨¸Hs"Éô‚CÌÊ»;À´iÛ€ˆ^»Í˜ SsÖßLh¬€Sc—ÖÄ @€ @€ @€fY %™Þ{Öù±ÇV 0õ'<®¸áîÔ¥¦”>LI;,¥VLñktfJ/¦LñˆWRg¦x%ÒKù˜å•2÷ñR’i¡¼[=Æò&L#"zç~qó¾û=cÓæ[ómã>±—Üxëâ(ì€ÓÞè9– @€ @€ @€@}R’é=gžŸLý B—š®»ë’k³qÊÖpà!·Þq߈Gÿ^r¹B$“¢S|ý–¢3S<Éû3ÅóøÝÈ0¥0S:dý·×§FMöT ’L¾èÈÞòÞší“8,¢'ô§ÈÞO€I ˆ1MRÛµ @€ @€ @€LT %™N=óSWnݹ1F+ÞÑNx6’ÛÐ 0í}†)æé¥*Å“¼SŠ1ů‘^Šc¹ñ$LñÎø­ør¢(.Ö ”dj—w!À40¢'ÃÔ •7š) ÆÔÌu5+ @€ @€ @€I dúÐyy€)Ox\zÝB¦R2Lq¹'¥MåR˜)="À/¦$Sz%:6¥íçd˜ê^ D’éù/:¢PÞ]û$æ=¦½tv8& Æ4d— @€ @€ @€ P¥@J2½óŒóR€)F 0å ²2LUNÒµgX ’LÏ{á—o阮òîŠèÉ0Ípu˜:Ó$ Æ4M«å^  @€ @€ @€Œ'’LkÏ8¯`êJxÈ0Gê¨Z dI¦Cޏ´ÑK›$¦!ÃT«•r3! Ƥ< @€ @€ @€Ì„@J2½ãƒëŠ ¦™XûÙ˜d$™8äðb1¦ÙXy³$@ 9bLÍYK3!@€ @€ @€ 0Z %™NùÀB’)žpà!·Þqßí;6vÜÿó_?ü[õHI&}˜ê¿RîĘ @€ @€ @€(&™d˜fhágfªy’É^r3³æ&J€@sĘš³–fB€ @€ @€ @`)Y’éÀóŠãxÞAú0-EÌ{¦K ’LÏ:àEû>鉛6ß:¢ÍXüÖƒýjº¦æn  Ðl1¦f¯¯Ù @€ @€ @€ ð‹«?¹æ)ÿû­›.µ—œúh¤ÀÇŸÿ[›Ö¾R†©‘‹kR4X@Œ©Á‹kj @€ @€ @€†\sÎo^µÏ=7ÌËyì¸ÿç¿~ø|¦UàUû<ø±Wˆ1éÃ4­+ë¾ h´€S£—×ä @€ @€ @€ hŘ~³}þžýEÔC†IÕL½@”÷¹/¬ÒÀ$“ ÓÔ¯¯  ÐP1¦†.¬i @€ @€ @€Xš@O’I†iilÞUoíó¿Ùu[Üb’I†©Þ+çî˜i1¦™^~“'@€ @€ @€h¶ÀWO^½~õÊŸü`{Ï4·~líÝ[æóó$“ S³ë¡a³{èþQÉ·^0×?¯â‹Å$“ SÃjÀth˜€SÃÔt @€ @€ @€´"¨1¦ˆzô‹ôg›"Ét×}ýúáGð˜(ãˆ+}ÿ«ë{nøþom‰ß*¾˜’L2LÓ²²î“™cšÙ¥7q @€ @€ @€& D†éÒ5«bēԴ¦Øé3«V¤ÉG $^ÿΗ×ýG‰ S¼9½³É4æÖÈ*Eǯi6ñ$^¬áüõÑ‹ÎdñÊÀl_#TL‚Ó- Æ4Ýëçî  @€ @€ @€ øÕC»£!Mä“"±O¢cMŠ}¤GêU½š"Æ”¾ŒwÆ{âI|/Fþ ,: lþÀš¨çH,EIGÝÆ“x%vJïÅ“ôzÔyªçx#^‰×%™ê¼¸î™cšÙ¥7q @€ @€ @€† ¤–K‘gJ‰WJ)¥|Ä+‘íH»ÎÅ{Rì)! ¥gO®†K™Þ äeñ»¼nSͧ”RÊíEaÇ+©Y΋О–cS¸æn™æ ˆ15Í @€ @€ @`R‹š˜x$6âIjB“Bñ<õª‰Gz1RMñþx’ö¡KcÑLyŠ¢Œ£¶S…§Š:O5Ÿ‡ðRyÇ;SÙÇëù;ئh­Ý*³# Æ4;km¦ @€ @€ @€3$ÙŽÔr)oHÑ¥<ä½j¢™MŒxC´«‰÷¤½çP¼SÈc†je:§šZ.¥ø]j¹5Y¥h”Bxy § _¼}›Ò\Så{ @€@ÝĘê¶"î‡ @€ @€ @€@ ‘aJ½j"íÏSŒ#•RO¦È*Å“x=~7½žö˜K_æ»t•p+NA`R§SD—"¢uõœFªüˆ+ÅoEUǓԖ,¾Œßµgâ2,ˆS @ 1¦‚ @€ @€ @€@ÝŠ9¤ˆn¤/‹¿Æ—ÑÌ&~+F~ó=_ÖmRî‡@ˆöKyG¥0E2)RJ‘Ì‹O¢°Sy§HSÊóÅ#žÄ—Z1©"ÔV@Œ©¶KãÆ @€ @€ @€ @€ÌŠ€Ó¬¬´y @€ @€ @€ @€¨­€Sm—Æ @€ @€ @€ @€˜1¦YYió$@€ @€ @€ ° pÍ9¿yÕ>¿Ù>Ï„@3¢¼Ï}y3§fVh®€Ss×ÖÌ @€ @€ @€ cRÍcjöúš cjèš @€ @€ @€Ÿú«¬Ó®Û h ÀOweå}Á85S"@€@£Ę½¼&G€ @€ @€ @` @ì·9xàά¼/>©‘“3)4XÀ& ^\S#@€ @€ @€ 0D@ŒIi4X@Œ©Á‹kj4Z@Œ©ÑËkr @€ @€ @€ ˆ1)Œ ˆ15xqMF ˆ15zyMŽ @€ @€ @€À@1&…Ñ`1¦/®© Ðh1¦F/¯É @€ @€ @€( Ƥ0, ÆÔàÅ55- ÆÔèå59 @€ @€ @€ĘFƒĘ¼¸¦F€@£Ę½¼&G€ @€ @€ @` €“Âh°€Sƒ×Ôh´€S£—×ä @€ @€ @€ cR cjðâšcjôòš @€ @€ @€\àÖK~sñIíqÊ~óª}¾Œ×õ T¦X 8/ï ^Ÿ•÷ûžµðJ¿Ô^@Œ©öKä  @€ @€ @€”"ðÃmY¶cà8ë°R®à$ªˆ2VáQü P{1¦Ú/‘$@€ @€ @€ P–À°œ‡GYÂÎS¡À° ž”^…‹âÒØ1¦=Ñò^ @€ @€ @€S-00ç!ä1Õkêæ‹ƒzRzŠ„S" Æ4% å6  @€ @€ @€”"Пóò(ÖIê Ðԓҫú¸,M@ŒiiNÞE€ @€ @€ @ =9!f,«Yä=A=)=µA€écšžµr§ @€ @€ @€J(æ<„¼ÎSý÷V{¼’|WÍGñ.ûüõÅê¿øÑÈ> Ýõ_þ‡ß~ÔïÿÁŠüõâ'"=ÿÃ?úãôÃT±ÝuÛ*ݬnÛ¥ÛªÞþî­áV畼=«ä®b.ÔóO²znTÒYUg…UuVØÝµ}S§¶óòî­ðV‘wê¼»Ô¿•z»Ú|_Í·Ê>¯ü¼ø;õ¿«]ÿÅÀí@ßag|b\ÑñYxÞ xÓI§u}" Šø\¼ûìÏ>ûÙÏ^ê’{¦D@ŒiJÊm @€ @€ @€Lƒ@„?¢KôR 0eãÞŸEŒé}­S 0eAV dh†©c*f˜òäGÊ0å±ÞÀG+ÆÔõøn;Æ”2L­G'ÃÔcº®ìèÊ0µ"]¦þS'ÆÑ‰1¥èFWŒ©Úè1e&1¦å¬ö,ÆtÔ±]¹¥B­¦ôRTrJ/ 0õ–n'ÀÔÂ+%Ô'óºÂy½¦…ˆÞèS+«7,ÃÔíõåöǘRz¯˜aÊbL­ ßèÓ•}y¾b†i!ÆÔJõµƒ}bLËù¡pnj" ÆT“…p @€ @€ @€MH=lÚ¡¥vt©«“ÍáGf1¦¦¼MjÂ4¬Óè Ó^·bz`¡S+Ætmw7¦E[1å1ެS¡M;ÃTLoä1¦‹S7¦®VL­nLw鯴ŸŠˆ1Eœ.Å•ºÊ5Ë-µ£KQÉyû¥LKÊ0E§±¥µbÊ3L[:-Ç¢à»{‹µbjw +4!ëkÅÔiEÖÝŠiS'É—‡ùÚmÉúZ1¥ÓšèÆÔaÊ[”m¸V7¦åød8'Õ ˆ1U¿î€ @€ @€ @ 1ÅðÇÀM¸^zä±ïýà‡{:0 ØH®» Sÿ\û0 È0µ:Ö¤íäòœÇB+¦ÞíäZÔ lÅôl;¹îVLKÛQn@+¦ÖŽrínL­ÓÀå"®aS¹Ò?)Æ´PŸÅ ã:{F%ÓKùæqÅÎa…-äú:0 0 ÜH.ßqô^r£ú0-9ôØvr½û'ÆFŠ­‚·Ó…M ;ÊhÅtEkwÅa1¦´ÍbŒKĘJÿT8!õcªÇ:¸  @€ @€ @€Fô„?ÚÝk ;ǽôÈcÞóo×îžÈB¦b€iÇO&?ŠÉ}ëû?I{ÉîÃ4*ÃÔ·\ÖŸæ¶ÔŠé¾æH£ôVL…SÿæYí¸FĘæÎúçýô—ùøÉÏ~Õˆb©lcŠ8]O¥žÐRTr¶kw]êm¡÷Roz©ØBìö¦‡u``êjÂtg¶=b]›$f¦¥î%·L¦«o¾':¥qU¶£Ü"ÛÉ-¥S1Æ”ï±XlÅ”bLO_ùÌâç"žÿG©¬ª\˜eˆ1•¡è @€ @€ @€Z=á…üGD@Z),Ætú‡ïØ9*ÿÑþµ÷VW€)ïXÓõøÑ­-·ôaZ,Ãtmw†ió7ïMµÚûjÝrol§•ƀǻ6µÆˆVLcúßý½ó.þưVL׈Ó»O;;21ù½_?,®1þG®c:¦˜Rêj֪ը䔴ëÎÛ ¨ÛžèR1½T á ÜBn`¦b€iŒ&LQä[o`kÞil¡Â³fcCö’³Ó3LC·“ëô$‹BŒÔ‡)u&{Þ!íMå²ÓuÙ(¶bJ1¦}÷{FñsÏ|HÂoüÏ…# ¨ƒ€SVÁ= @€ @€ @€4D`xø£•ÿØùàKŽ8æÝ§ŸÝß{©þèé^³h€i`¦ÖFrí½ä ½j–!ÃÔŽ12LY7š¯Æèd˜6mkǘº6Òj…6Rn£cÚ|ÙõY7¦Bb£ÝŠi`Œ)27bL{óI1¦bJ©»ÁRÔjcJ{ÇÝæå:°nS’&ÏÞõô^*¦—Ší—Æ 0õïØ›Ï‹ S+Àã†4¶Gz)û£ÍX>R¿±¼åX×+n$—…öй½ÂŠYzoi}˜ö4Ãtù–ì³bLy+¦ž “ÓÞÔ¿c ¨³€SWǽ @€ @€ @€L™@„?ú3ÅW^1¦Bo¡,ü1rã­Û~ø“´…\!öÑêÀT0µ:Ö Üo«¯ S'ä1,Þ10Ø‘ö’ëëô„ S§ÓÀ Ó­Æ3cZ×cJ‰j¤ÑßIŒi/?cŠ8ÝèB-VrOËŸ…È]§t÷,ºôƒŸÄNˆ ›!vWr±ýRq ¹½ 0nÂ40ԘڽǺ3LùFrÙ^r7 ÝKn¼ SŠ1ý]Š1õõaJŸ ݘöòSàpê) ÆTÏuqW @€ @€ @€S)áþÌGþJ$–"ÆtêigEì#íùh7^úit¬ÉšÖ H/ýdPzi‘ÓbÉ=Ç;®ûv¡9Mg#¹NgšeÈ0u¶ÐÊcL]‰N†IŒi9>cŠ:Q¨ñ[©’Û1»BØ®·n£€˜o:‡õt]*6^•^ê¤ñÚé¥bS±;þõ¦­ó±Ð]lT¦®&Ly‘lÂTìÃÔ߄难-³ÓÈ S¾b<¹rk{lܺsã½äR¦4Ú1¦!&1¦åø\8'ucªÃ*¸ @€ @€ @€†Dø#(õ>ú©‹c¤Ž5Ñr)Æñ'½'k¹”í±õÀß¼ñÄY·>F–öØþ@JuDÚcËö,äã’¯Ýú„'ïû•Ö¯yš÷ùÉÈvÄxŒlÇ_Þü¬çãÕ¯?!¥:yñÑÏúÓƒžù§ECšñåq'¼+¾Œñ©‹¯‰ñèÇ<ö¿<ñ©ç­¿fÓ»^uô3þë bdŽm;OûÈçW>ç1^pØËVÿÍ›¯hŘ:M˜î¾¬Ø‡©ÐxFŒiòÅ1¦ˆÓõjO­F%w3Ì+6OÚuÕm§t{ö:Ì÷=Œ¬Rp$ðRË¥Èá}ê¢+Ÿó¼ƒ£€SË¥H)wáÆ(æ7¿ýݶúo².b­ôRÔs*é(ã“ßsVD‘¾ºõû]úë7œ# ûs—|#•tJ,åã³_ÙÜÊ-uzŒ}óÞ“N=3Š‘ŽÈsį¿øès¼ëƒçFn#6ÒzåkOyŽHr¼þøµ`zÇÎGd8þãcþàìO]ò/_ûÎ~ÂSÿ2bLí]äºL…ͳR\CŒiò¥žÅ˜^rôèBí­äVÀnDݦÄR±tóç­ìÝòMâ"º¡¥(ãvt©ÕB,ž¯»pã…—^q¥È-Ee7ŒK1¦O~þŠˆ.Å>q×Þ1¦bD×¥´[\”w¼I¦Î¶q÷ýÕëOˆßÊwŽË{/½úu'DµG‘ì‚Ëýû]¿ñ¦h¼u~Ù7îˆ&L‘^ŠöKÑo,ÒKÑr,~ÜRTû®¸1ê?ýzÐa/‹²âçQöÑ{ìßÚг…bO†oLbL“ÿD¸"È»1¥$ÒĘ" •Z1å1¦ /žË @€ @€ @€L‘@„?ò4Ÿ¼è%/‹ÓÀ´G¼˜š-åH/E¼#Û-.¢KÇeÑ¥Ô¢¦Ý{©Ðu)Õä»kEÈ#¥—¢÷R$<"ÞãßÌ‚1ò}µ"Àô¸'í˜Z;jŸ'RéH#òm¼éqO|jt`J[È¥G¾…V4¡YýÚãÓþq)À饔Þ8þ”3þò5onõaÚqÙõÙÈv‘+˜6\—˜Ä˜ª*ìˆ1EŽ.ÔþJV´ÃâJ©ŒÛ{Ãuž¤ S$–Ò>q­'Y¿¥,¥ô…+bĔƋS÷nq÷G=âó—g…ý¤}£—Ø_½á„‘Ì‹>Lyt©¸m\´\ŠwfåFgÛ¸¨ùOÿË5Wß|O¤ô^öò×D³±¨öW¾î-ió¸(ø¨öDŒéµÇ§šSÔ|Œ(øÞñ¡xåÃçoˆôRŒh<é¥h®K€Àr Dû¥|ƒ¸t­¥Æ˜â°ž S,Æ´Ü æü @€ @€ @€Ó+áÑi½øeÿðî¹bV)-u>¶?{lÅÖZ'¿÷ìbt)µ¨I1¦ÈyDò#¢ÿøî³òmã¢?MŒÔx)‹z´¢Kñžè½ÁŽ|ó¸v|ü‚,Æ”6‹©Žˆ.¥HÇ+ÿ6Æñ67Z.E˜#ºÑĈGl¡•bL±…\cje˜"Æã¬óÚ1¦ˆnœµî’ˆ1¥S;½QØE®'±¡Óä«=‹1½øe£ µXÉívJÝ»¼nû³Ji£Ã4:{ÃeON~ïYWZ÷…+R§èÒÂóÏgÅüìç#®ù¤-¥z.v]J»ÅEã¥(ì“N=ë…/9:k¹ãÖ{ãõ¼ëR;¥×I/E…GhéŒ]—¾¸ñ¦¨ö«n¾'ÕyYV怜ÇX|ô‹:O5äûëcŠÛ&Fã±Nï¥VŒé†»£ñXÿ€öK ßÀ߆NŒ¯?À¤Óä?®H€ÀÄ"tÔ“aŠK/)ÆÔŸ~J7-Æ4±Ås! @€ @€ @€©ˆøE1ÞÑQzaĘNýP;±Ô‰zô¤=¢9͆«o Sòˆ¨Ç6|#b©EMä<>É7¾|Õ-‘ÛÈZÔ´r±¯V{|ó¾g=÷ HxD㥬÷Ò­÷¾ðÅGG€)¶‹í´Rï¥gþéAúø…cŠŒ'›nø~4[ÊBKÜRöB=· ;byç|öòVã¥{S2/Jú3ÿòõ<º”vEŒò.6^zÛ»æR…§ ã"À•Ü[Þ—bDyŸwñ5Ñx)FÊêEŒ)~ýÈù"½ÕûÇÅæq©÷R<ÿÄEWgeßé½e饈1|Ú9­ÊÏÆ¢í— 0‰1MþáŠLF G±)\ÿµ1ÍÏÏÇ–âøô(&¡Ä˜&³x®B€ @€ @€ 0ñ¯lÅö3ýÏ#ÆtÒ»>4,ê‘g>}é1‘ÏÈÇ_¿áÄH{󗯉´GŒØ$.rKñkñ=­ ã²GŒ”íH#/ÍsQj¼1¦x#žD¶ãmèÒ3ÿëA±—V¤:b/­v¤‘ÒKñ$‚1âIJ/½îøµ±…Ü[N9#ÂéHãø“ÏˆGüÏŸþì<4ß¼yÑ“M媪ðˆ1EŽ.Ô!•ÜÊ' J)KéyWŠÒ¦b¹¦ø]´\Š|RŒx÷YÅÜRk{¸(æ4²’Žd^4XÊ«:j8bLQÛ¯~Ý ñ<ÂIíÝâ:­Å¢¼ÏÿÒ5ÙëOÜ7Fd˜ÞõÁs£È/Üxcªêøõ¨?ÿë(òÔiiÓ¶]‘[Š×ã×è:¡½È-EÁGû¥ˆ+Eañg¡½xž÷^zús^eÿ·Ÿ}"Þ|ò]íÇ|í ßÓKyÂϦrU}:\—eX»vmÄ•ò$ÒÜÜ\~¡ÅcL»wïÞRxlß¾=?¸ø|™nÝi  @€ @€ @€L©@„?úóÅWYuTĘòWz¢)ð±°C\¡?MOsšžGÚT«]Š„Gj¼TÜ6.u¦I;j]uSŒ¬'MÚN+ß<î’¯7E:bDÔ#¶ÐJÝh6fãîHr¤ý³bD†ã⫾Sì@“µ_j86ŒìÀ¤Sµå1¦¨ÃÑ…:¢’ÛEÛê¨4p\{ÛýíÖJ…îjVhö¥M·ôsÖB¬»žó­âRUçý–Öv¡¼ÛÑ¥¼Èó:Oí—Rç#•zOÁk>•ýô^ºî®aÛÆ~]Œ©Úψ« Pº@ÄŠI¤&å—ˆ×óçû”~a'$@€ @€ @€ 0³þ–íH¯G|äíïüP+¨48ê10í±hÎ#‹w Jxä¹¥aÑ¥bª£+ϱ- sD+š³?µ! 0ÝP0-Ä8vä[h`Ò©ªIŠ1.ÔžJn•k_Ñv§”†•R¯Pà =–Ú‰¥!¼!%¢KÅÂn×v!™W çõä–òˆÞBt©Uê…èRwµB{ôÒBÙ·wNìï½4nzI7¦ª>®K€@MĘj²nƒ @€ @€ @  þˆ0ǰaŽƒWõ¶µgô´VÊ¿ìŽzd{i-’óhw¦Yh¹Ô“ðȺ.eñŽB×¥Bã¥þ†4=yŽO\øµžöK)ÉÑŸ^ZèÀtížµŸùG=úÜ/nÑ™&ÚÒ¼û´³oßñ`>îܵû×?Ò„r©h)Æ4¢Pã·¢’‡UéÀ×ûRJƒ²J#z,uBxý–úCKýý–ÚÍ–ZµFªíöètÞu©]Ñxéò-“H/‰1Uô™pYê" ÆT—•p @€ @€ @€ ÈÂß¼/ýÙŽƒ;ê­kÏè¼Þ* ‹+uí¥µÐl©+´4$·´'Ñ¥Þn4];ÇwÑÊÓKí&4×íÙþq³JbL“/ûˆ1EœnH“¤vÛ¤¨ä!ɤxິ\Úå°Ý*,ÒÊÞ Œ+ L,õ‡–š- Í-umé¥+ E^Ü!±'·Ô³gÜàèRï¥=Œî-e›9›ÊMþsáŠÔA@Œ©«à @€ @€ @€"ᯧQ´ ¿uó=ýÜ•UWÖf)K,í*òÒóžfK~Kƒ·ŠÝr©˜Õ‹­vKl…ö–ÒH©”÷ˆ1MþsáŠÔA@Œ©«à @€ @€ @€"áÑ!zä §|pDÂc¡ÁR;çÑ×fx£'Þ1h#­ÑÑ¥Á—ŠIŽR"Å“ˆ1M¾ô³Ó¡GŽ.Ôv%ß|ÏÕ#I+9먔F__¥®ýà •=–ºxéËA‰¥Q¡¥N³¥=Ú*n!·ÔÕr©œfcc^Ę&ÿ¹pEê ÆT‡Up @€ @€ @€ ˆðGoË™<ÒÑz1¦·œüÁñŽÞ„G„<öXžð‘[ê vº.-]ZÖ&4bL“/ýˆ1EËÒ¥RTr_ip,iÀÖo©t ªzRJí2TêÍ*uº+ Ž+Mg¥%f˜âmbL“ÿ\¸"ucªÃ*¸ @€ @€ @€†Døãò‘yŽçEŒé¤Ó;ïÉz)-;†d;†µ¢éo³ûg-='Q“wŠ1M¾ô#Æu8ºP«ä¾ÒÒE)ª7—F2©gt† ,æ´\ŒšÔê$oCŒiòŸ W$@ bLuX÷@€ @€ @€ ÐsýÏŸwÈkN:-½> ÕQè@Ó½\aÛ¬Èv4¨ÓäK?‹1rÄèBQɃë6¯çB2©¯†ûʸA•\nÈIŒiòŸ W$@ bLuX÷@€ @€ @€ ÐûÊ7ŽøG¼ß³ž_xÃqǾrÐxÅqÇÌÆø·ÿî·;rõˆÉ>öþøÝ§}ûŽóqç®Ý¿~ø‘†TLÓˆSÔáèB]´’×m^̯8îØÙ(àeúœFÙï÷Ìç8yäœöÝïÅÏE<ð¡_UQP®I€ÒĘJ£t" @€ @€ @€§Ÿ~úI…ljo}ûß¾ñ-ÅñâÃùóW¼¦çÅYþòùúš×½i´À¦Í·Š1•øáºóÎ;‹UÏßø¦{–à¹Ï?x–˲ò¹/åÅY=_Œ©ÄÏ…S P1¦:¬‚{ @€ @€ @€h¦ÀÏùpOÎÀ—{/ S韖÷ÿ|ï×Å*Щô† 0a1¦ ƒ» @€ @€ @€À ˆ1-G°CŒ©ôÓrêäÏ)ÆTúGà ˜°€Ó„Á]Ž @€ @€ @`†Ę–#É!ÆTúGHŒi9 uòçc*ý£á„LX@ŒiÂà.G€ @€ @€ 0CbLË‘äc*ý#$Æ´…:ùsŠ1•þÑpB&, Æ4ap—#@€ @€ @€˜!_ü÷‡'ehüï¸{÷¯~d†Êhù§z÷ý5¾lfa‚bLËÿYq–W@Œiy} @€ @€ @`Æ"É=™FŒŸýâ×£ß0k¿»(È/õðŒUéÓXØ¢e¶èº,zoØ¥ø—^NH€ ˆ1MÜå @€ @€ @€ @€ècR @€ @€ @€ @€T, ÆTñ¸< @€ @€ @€ @€bLj€ @€ @€ @€ @€ŠĘ*^—'@€ @€ @€ @€ @@ŒI  @€ @€ @€ @€ P±€SÅ àò @€ @€ @€ @€ˆ1© @€ @€ @€ @€*cªx\ž @€ @€ @€ @€1&5@€ @€ @€ @€ @€@ÅbL/€Ë @€ @€ @€ @€ Ƥ @€ @€ @€ @€¨X@Œ©âpy @€ @€ @€ @€ĘÔ @€ @€ @€ @€ ˆ1U¼.O€ @€ @€ @€ @€€“ @€ @€ @€ @€ @ b1¦ŠÀå  @€ @€ @€ @€cR @€ @€ @€ @€T, ÆTñ¸< @€ @€ @€ @€bLj€ @€ @€ @€ @€ŠĘ*^—'@€ @€ @€ @€ @@ŒI  @€ @€ @€ @€ P±€SÅ àò @€ @€ @€ @€ˆ1© @€ @€ @€ @€*cªx\ž @€ @€ @€ @€1&5@€ @€ @€ @€ @€@ÅbL/€Ë @€ @€ @€ @€ Ƥ @€ @€ @€ @€¨X@Œ©âpy @€ @€ @€ @€ĘÔ @€ @€ @€ @€ ˆ1U¼.O€ @€ @€ @€ @€€“ @€ @€ @€ @€ @ b1¦ŠÀå  @€ @€ @€ @€cR @€ @€ @€ @€T, ÆTñ¸< @€ @€ @€ @€bLj€ @€ @€ @€ @€ŠĘ*^—'@€ @€ @€ @€ @@ŒI  @€ @€ @€ @€ P±€SÅ àò @€ @€ @€ @€ˆ1© @€ @€ @€ @€*cªx\ž @€ @€ @€ @€1&5@€ @€ @€ @€ @€@ÅbL/€Ë @€ @€ @€ @€ Ƥ @€ @€ @€ @€¨X`‘ÓöíÛ{n°ÿ•Šgàò @€ @€ @€ @€Ô[`gëQ¼ÇžW†Æ˜Ö¬Y³²óHÑ¥þWê=wwG€ @€ @€ @€ @€@õ«V­Ê“Hénú_cЬS™ŽY¿~}ÖÿJõós @€ @€ @€ @€Ô[`ݺu«W¯N÷}”æææú_‰ßÚ)ß<.Řâ­ý¯Ô[ÀÝ @€ @€ @€ @€ P±ÀîÖ#ÝDŠ1õ¿¿54Æ”ß~´ešŸŸ/Φÿ•Šçêò @€ @€ @€ @€Ô[`Ë–-+V¬(Þcñ•Q1¦h¿‰¥hâ”ÜÿJ½çîî @€ @€ @€ @€¨^ v„‹$Rä–ò[éyehŒ)މ#ãÝù‘ý¯T??w@€ @€ @€ @€ @€@½¢R$‘¢ƒR~›ý¯ 1E§Øˆ.¢KñH§è¥ÞÓww @€ @€ @€ @€T,0??¹£ø5%‘vïÞÝÿJÜâàSjÙ”?V¯^ÝÿJÅósy @€ @€ @€ @€j/°fÍšb):+õ¿“Ú©ötƒ @€ @€ @€ @€4D@Œ©! i @€ @€ @€ @€¦W@Œiz×Î @€ @€ @€ @€hˆ€SCÒ4 @€ @€ @€ @€L¯€Óô®;'@€ @€ @€¡÷ð5K¾IDAT @€ Ð1¦†,¤i @€ @€ @€ @€˜^1¦é];wN€ @€ @€ @€ @ !bL YHÓ @€ @€ @€ @€ 0½bLÓ»vîœ @€ @€ @€ @€@CƲ¦A€ @€ @€ @€ @`zʦwíÜ9 @€ @€ @€ @€†ˆ15d!Mƒ @€ @€ @€ @€Àô ˆ1MïÚ¹s @€ @€ @€ @€ cjÈBš @€ @€ @€ @€écšÞµsç @€ @€ @€ @€" ÆÔ…4  @€ @€ @€ @€Ó+ Æ4½kçÎ  @€ @€ @€ @€4D@Œ©! i @€ @€ @€ @€¦W@Œiz×Î @€ @€ @€ @€hˆ€SCÒ4 @€ @€ @€ @€L¯€Óô®;'@€ @€ @€ @€ Ð1¦†,¤i @€ @€ @€ @€˜^1¦é];wN€ @€ @€ @€ @ !bL YHÓ @€ @€ @€ @€ 0½bLÓ»vîœ @€ @€ @€ @€@CƲ¦A€ @€ @€ @€ @`zʦwíÜ9 @€ @€ @€ @€†ˆ15d!Mƒ @€ @€ @€ @€Àô ˆ1MïÚ¹s @€ @€ @€ @€ cjÈBš @€ @€ @€ @€écšÞµsç @€ @€ @€ @€" ÆÔ…4  @€ @€ @€ @€Ó+ Æ4½kçÎ  @€ @€ @€ @€4D@Œ©! i @€ @€ @€ @€¦W@Œiz×Î @€ @€ @€ @€hˆ€SCÒ4 @€ @€ @€ @€L¯€Óô®;'@€ @€ @€ @€ Ð1¦†,¤i @€ @€ @€ @€˜^1¦é];wN€ @€ @€ @€ @ !bL YHÓ @€ @€ @€ @€ 0½bLÓ»vîœ @€ @€ @€ @€@CƲ¦A€ @€ @€ @€ @`zʦwíÜ9 @€ @€ @€ @€†ˆ15d!Mƒ @€ @€ @€ @€Àô ˆ1MïÚ¹s @€ @€ @€ @€ cjÈBš @€ @€ @€ @€écšÞµsç @€ @€ @€ @€" ÆÔ…4  @€ @€ @€ @€Ó+ Æ4½kçÎ  @€ @€ @€ @€4D@Œ©! i @€ @€ @€ @€¦W@Œiz×Î @€ @€ @€ @€hˆ€SCÒ4 @€ @€ @€ @€L¯€Óô®;'@€ @€ @€ @€ Ð1¦†,¤i @€ @€ @€ @€˜^1¦é];wN€ @€ @€ @€ @ !bL YHÓ @€ @€ @€ @€ 0½bLÓ»vîœ @€ @€ @€ @€@CƲ¦A€ @€ @€ @€ @`zʦwíÜ9 @€ @€ @€ @€†ˆ15d!Mƒ @€ @€ @€ @€Àô ˆ1MïÚ¹s @€ @€ @€ @€ cjÈBš @€ @€ @€ @€écšÞµsç @€ @€ @€ @€" ÆÔ…4  @€ @€ @€ @€Ó+ Æ4½kçÎ  @€ @€ @€ @€4D@Œ©! i @€ @€ @€ @€¦W@Œiz×Î @€ @€ @€ @€hˆÀ¨ÓüüüÜÜÜöíÛó¹Æ+ëÖ­Û¹sgCfo @€ @€ @€ @€,¿@„ŽzrGñe„‘ò+1­ZµjõêÕk×®]¹råúõëã€â+’LË¿v®@€ @€ @€ @€ @  +V¬X³fMJ"¥ÜQz%ñJšáàSt`Êß±eË–t|ĘÒ1qÆx4AÈ @€ @€ @€ @€XNØ.âJé )w=•òW"˜ñ¤ø­Q›Ê¥ƒãDÑ–)¿ÕÈ3ÅÁņNË9 ç&@€ @€ @€ @€ @ !CнäòÉDi‘nLù[#ëœò-äR—¦xÄ“†Ø˜ @€ @€ @€ @€Ë/¦<´WK_æÄêÆo SêÚT|D[§â— ®@€ @€ @€ @€ @€À Ä.rGñzl3cJq§¼S<É·–‹`“Ó…['@€ @€ @€ @€ 0AÈåÑ£¸l4Qš››K× Ó¨S„–¢SÊ:Å#Ñ¥x’2Lé` @€ @€ @€ @€ŒH;Â¥R<æççS6)ÂLñˆ'ñJ>¸Sü^~dcŠããy£âÔè  @€ @€ @€ @€ °¨@dŠI¤ZŠ_£ÅR<Ò—ñº©Ü¢ð @€ @€ @€ @€”" ÆT £“ @€ @€ @€ @€ 0¾€ÓøvŽ$@€ @€ @€ @€ @ 1¦R„ @€ @€ @€ @€ñĘƷs$ @€ @€ @€ @€¥ˆ1•Âè$ @€ @€ @€ @€Œ/ Æ4¾#  @€ @€ @€ @€(E@Œ©F'!@€ @€ @€ @€ @`|1¦ñíI€ @€ @€ @€ @€@)bL¥0:  @€ @€ @€ @€ã ˆ1oçH @€ @€ @€ @€Jc*…ÑI @€ @€ @€ @€_@Œi|;G @€ @€ @€ @€ PŠ€S)ŒNB€ @€ @€ @€ @€ÀøbLãÛ9’ @€ @€ @€ @€RĘJat @€ @€ @€ @€ÆcßΑ @€ @€ @€ @€”" ÆT £“ @€ @€ @€ @€ 0¾€ÓøvŽ$@€ @€ @€ @€ @ 1¦R„ @€ @€ @€ @€ñĘƷs$ @€ @€ @€ @€¥ˆ1•Âè$ @€ @€ @€ @€Œ/ Æ4¾#  @€ @€ @€ @€(E@Œ©F'!@€ @€ @€ @€ @`|1¦ñíI€ @€ @€ @€ @€@)bL¥0:  @€ @€ @€ @€ã ˆ1oçH @€ @€ @€ @€Jc*…ÑI @€ @€ @€ @€_@Œi|;G @€ @€ @€ @€ PŠ€S)ŒNB€ @€ @€ @€ @€ÀøbLãÛ9’ @€ @€ @€ @€RĘJat @€ @€ @€ @€ÆcßΑ @€ @€ @€ @€”" ÆT £“ @€ @€ @€ @€ 0¾€ÓøvŽ$@€ @€ @€ @€ @ 1¦R„ @€ @€ @€ @€ñĘƷs$ @€ @€ @€ @€¥ˆ1•Âè$ @€ @€ @€ @€Œ/ Æ4¾#  @€ @€ @€ @€(E@Œ©F'!@€ @€ @€ @€ @`|1¦ñíI€ @€ @€ @€ @€@)bL¥0:  @€ @€ @€ @€ã ˆ1oçH @€ @€ @€ @€Jc*…ÑI @€ @€ @€ @€_@Œi|;G @€ @€ @€ @€ PŠ€S)ŒNB€ @€ @€ @€ @€ÀøbLãÛ9’ @€ @€ @€ @€RĘJat @€ @€ @€ @€ÆcßΑ @€ @€ @€ @€”" ÆT £“ @€ @€ @€ @€ 0¾€ÓøvŽ$@€ @€ @€ @€ @ 1¦R„ @€ @€ @€ @€ñĘƷs$ @€ @€ @€ @€¥ˆ1•Âè$ @€ @€ @€ @€Œ/ Æ4¾#  @€ @€ @€ @€(E@Œ©F'!@€ @€ @€ @€ @`|1¦ñíI€ @€ @€ @€ @€@)bL¥0:  @€ @€ @€ @€ã ˆ1oçH @€ @€ @€ @€Jc*…ÑI @€ @€ @€ @€_@Œi|;G @€ @€ @€ @€ PŠ€S)ŒNB€ @€ @€ @€ @€ÀøbLãÛ9’ @€ @€ @€ @€RĘJat @€ @€ @€ @€ÆcßΑ @€ @€ @€ @€”" ÆT £“ @€ @€ @€ @€ 0¾€ÓøvŽ$@€ @€ @€ @€ @ ¡1¦õëׯ\¹rÅŠ«V­*^i~~¾ç•RîÃI @€ @€ @€ @€h¤ÀÚµk#‰5kÖ'¯Ç#½24Ʀ-[¶Ä;æææV¯^Þ½{÷îx=ÎØH/“"@€ @€ @€ @€ @ \èšq£ÈÅi#†´nݺtþx=’H‹Ä˜â°H/¥"Ì”ç–âDñºS¹Kål @€ @€ @€ @€š*q¥x¤ÙÛ/¥æL‹wcÊ]b ¹”ŠSYL55Õμ @€ @€ @€ @€(W m·sçÎ8mtSZ¿~ý’6•K7¤åâøÈ3Å1¦r—ÇÙ @€ @€ @€ @€4^ ÒGÑ~)uSŠStSŠ'K1¥ÆMÉ(މ/#É¿F**e›< @€ @€ @€ @€ 0Z 'Eâ(e˜â‘2Hñk¼˜¿¾Ï°SÄ[c¹þßÕIÙ @€ @€ @€ @€ °DèÃY¥õ¿ñnL}JY§ôHÛÉ¥Gœ±øåïÆÛ @€ @€ @€ @€˜AØö­˜DŠèRްxŒi½L™ @€ @€ @€ @€ª†n*WÕ ¹. @€ @€ @€ @€³& Æ4k+n¾ @€ @€ @€ @€j' ÆT»%qC @€ @€ @€ @€fM@ŒiÖVÜ|  @€ @€ @€ @€ÔN@Œ©vK↠@€ @€ @€ @€Ìš€Ó¬­¸ù @€ @€ @€ @€¨€Sí–Ä  @€ @€ @€ @€˜51¦Y[qó%@€ @€ @€ @€ P;1¦Ú-‰"@€ @€ @€ @€ 0kbL³¶âæK€ @€ @€ @€ @ vbLµ[7D€ @€ @€ @€ @`ÖĘfmÅÍ— @€ @€ @€ @€@íĘj·$nˆ @€ @€ @€ @€À¬ ˆ1ÍÚŠ›/ @€ @€ @€ @€Ú ˆ1ÕnIÜ @€ @€ @€ @€Ycšµ7_ @€ @€ @€ @€µcªÝ’¸! @€ @€ @€ @€³& Æ4k+n¾ @€ @€ @€ @€j' ÆT»%qC @€ @€ @€ @€fM@ŒiÖVÜ|  @€ @€ @€ @€ÔN@Œ©vK↠@€ @€ @€ @€Ìš€Ó¬­¸ù @€ @€ @€ @€¨€Sí–Ä  @€ @€ @€ @€˜51¦Y[qó%@€ @€ @€ @€ P;1¦Ú-‰"@€ @€ @€ @€ 0kbL³¶âæK€ @€ @€ @€ @ vbLµ[7D€ @€ @€ @€ @`ÖĘfmÅÍ— @€ @€ @€ @€@íĘj·$nˆ @€ @€ @€ @€À¬ ˆ1ÍÚŠ›/ @€ @€ @€ @€Ú ˆ1ÕnIÜ @€ @€ @€ @€Ycšµ7_ @€ @€ @€ @€µcªÝ’¸! @€ @€ @€ @€³& Æ4k+n¾ @€ @€ @€ @€j' ÆT»%qC @€ @€ @€ @€fM@ŒiÖVÜ|  @€ @€ @€ @€ÔN@Œ©vK↠@€ @€ @€ @€Ìš€Ó¬­¸ù @€ @€ @€ @€¨€Sí–Ä  @€ @€ @€ @€˜51¦Y[qó%@€ @€ @€ @€ P;1¦Ú-‰"@€ @€ @€ @€ 0kbL³¶âæK€ @€ @€ @€ @ vbLµ[7D€ @€ @€ @€ @`ÖĘfmÅÍ— @€ @€ @€ @€@íĘj·$nˆ @€ @€ @€ @€À¬ ˆ1ÍÚŠ›/ @€ @€ @€ @€Ú ˆ1ÕnIÜ @€ @€ @€ @€Ycšµ7_ @€ @€ @€ @€µcªÝ’¸! @€ @€ @€ @€³& Æ4k+n¾ @€ @€ @€ @€j' ÆT»%qC @€ @€ @€ @€fM@ŒiÖVÜ|  @€ @€ @€ @€ÔN@Œ©vK↠@€ @€ @€ @€Ìš€Ó¬­¸ù @€ @€ @€ @€¨€Sí–Ä  @€ @€ @€ @€˜51¦Y[qó%@€ @€ @€ @€ P;1¦Ú-‰"@€ @€ @€ @€ 0kbL³¶âæK€ @€ @€ @€ @ vbLµ[7D€ @€ @€ @€ @`ÖĘfmÅÍ— @€ @€ @€ @€@íĘj·$nˆ @€ @€ @€ @€À¬ ˆ1ÍÚŠ›/ @€ @€ @€ @€Ú ˆ1ÕnIÜ @€ @€ @€ @€Ycšµ7_ @€ @€ @€ @€µcªÝ’¸! @€ @€ @€ @€³& Æ4k+n¾ @€ @€ @€ @€j'0*Æ4???77·}ûöt×»wïÞÒyÄóÚMÅ  @€ @€ @€ @€ PKu­ÇÎ;ÓÝE$)O"¥W†Æ˜V­Zµzõêµk×®\¹rýúõñÖx¾bÅŠø2oªå|Ý @€ @€ @€ @€õˆÐÑš5kR)%™R)=R—¥Á1¦ø½xGšMäžÒó6ÅózMÑÝ @€ @€ @€ @€ Pcè—¦tƒ‘dŠG<‰`SÏ-ÚT.½5Nm™âI„™âŒñk:— @€ @€ @€ @€–.1¤´µ\dây¾M\œa‘S´_ŠèSjåݘbw¹x%N‘'¤–~ÞI€ @€ @€ @€ @€ÀÌ D€)m ;Å¥}áÒ6qIŠGŘâÈÈ0õo$©¦þ¶N3ëkâ @€ @€ @€ @€ŒH»Àõ¿'JiŠ×‡Æ˜Rú)õaŠÇîÝ»ó½ä"%Ƥò @€ @€ @€ @€XŠ@lþüóóó‘MJ_ÎÍÍ¥ßcJý–"Ñ¥xÄ»ã­ñJ¼‡ @€ @€ @€ @€ÙH;Â¥R<"Ãx%ö’‹G$‘¢§RÈ Ž1Å[ó#óSd›ây¤ŸÒvt @€ @€ @€ @€-1¦b)‚Iñþø5Z,Å#e˜â1tS9¾ @€ @€ @€ @€˜Œ€Ódœ]… @€ @€ @€ @€¡bLŠƒ @€ @€ @€ @€ŠĘ*^—'@€ @€ @€ @€ @@ŒI  @€ @€ @€ @€ P±€SÅ àò @€ @€ @€ @€ˆ1© @€ @€ @€ @€*cªx\ž @€ @€ @€ @€1&5@€ @€ @€ @€ @€@ÅbL/€Ë @€ @€ @€ @€ Ƥ @€ @€ @€ @€¨X@Œ©âpy @€ @€ @€ @€ĘÔ @€ @€ @€ @€ ˆ1U¼.O€ @€ @€ @€ @€€“ @€ @€ @€ @€ @ b1¦ŠÀå  @€ @€ @€ @€cR @€ @€ @€ @€T, ÆTñ¸< @€ @€ @€ @€bLj€ @€ @€ @€ @€ŠĘ*^—'@€ @€ @€ @€ @@ŒI  @€ @€ @€ @€ P±€SÅ àò @€ @€ @€ @€ˆ1© @€ @€ @€ @€*cªx\ž @€ @€ @€ @€1&5@€ @€ @€ @€ @€@ÅbL/€Ë @€ @€ @€ @€ Ƥ @€ @€ @€ @€¨X@Œ©âpy @€ @€ @€ @€ĘÔ @€ @€ @€ @€ ˆ1U¼.O€ @€ @€ @€ @€€“ @€ @€ @€ @€ @ b1¦ŠÀå  @€ @€ @€ @€cR @€ @€ @€ @€T, ÆTñ¸< @€ @€ @€ @€bLj€ @€ @€ @€ @€ŠĘ*^—'@€ @€ @€ @€ @@ŒI  @€ @€ @€ @€ P±€SÅ àò @€ @€ @€ @€ˆ1© @€ @€ @€ @€*cªx\ž @€ @€ @€ @€1&5@€ @€ @€ @€ @€@ÅbL/€Ë @€ @€ @€ @€ Ƥ @€ @€ @€ @€¨X@Œ©âpy @€ @€ @€ @€ĘÔ @€ @€ @€ @€ ˆ1U¼.O€ @€ @€ @€ @€€“ @€ @€ @€ @€ @ b1¦ŠÀå  @€ @€ @€ @€cR @€ @€ @€ @€T, ÆTñ¸< @€ @€ @€ @€bLj€ @€ @€ @€ @€ŠĘ*^—'@€ @€ @€ @€ @@ŒI  @€ @€ @€ @€ P±€SÅ àò @€ @€ @€ @€ˆ1© @€ @€ @€ @€*cªx\ž @€ @€ @€ @€1&5@€ @€ @€ @€ @€@ÅbL/€Ë @€ @€ @€ @€ Ƥ @€ @€ @€ @€¨X@Œ©âpy @€ @€ @€ @€ĘÔ @€ @€ @€ @€ ˆ1U¼.O€ @€ @€ @€ @€€“ @€ @€ @€ @€ @ b1¦ŠÀå  @€ @€ @€ @€cR @€ @€ @€ @€T, ÆTñ¸< @€ @€ @€ @€bLj€ @€ @€ @€ @€Š†Æ˜vîܹfÍšU«VÍÍÍå÷Ï{^©øö]ž @€ @€ @€ @€z ÌÏϯn=Ö¯_Ÿît÷îÝ)›”¿24Æ´råÊ-mÙ²%Ž_»vmOâàâ+õž¾»#@€ @€ @€ @€ @ b覴bÅŠˆ+Eî("IiŠŠ'ëÖ­+¾28Æ´}ûö-¥¤wÇéâ×|Nñ†Šççò @€ @€ @€ @€Ô^ âJùvpÑM)ñJžMŠTRtfŠI íÆ”O0:0ÅÁ)Ì”Z9åg©=‚$@€ @€ @€ @€ @ .©S„‘"€1¤x¤mââ±HŒ)¢O© SĘ¢¹Sêé”vª«ËäÜ @€ @€ @€ @€µÈCG]J»ÃE¦´»\Üû¨S™o$—º1¥ÉŸ×~ún @€ @€ @€ @€Š"z”7NJ[˥ʟ1õ´\ŠôStcJGO¦<ÒTñü\ž @€ @€ @€ @€z ä-—ÒmFû¥ØN.=_³fMŠ4 Ž1EPiŸ}ö‰ãÓ#%¡â˜x’z:¥Ýå< @€ @€ @€ @€ 0B âFÑ>)O"ÍÍÍÅ›ãË#Å#žÄÖrñÊàSü^ì—?¶oßž®OâDÑ™ = @€ @€ @€ @€ˆÄQ1‰”BKñˆ>JÑ–)?|è¦r‹^À @€ @€ @€ @€ PŠ€S)ŒNB€ @€ @€ @€ @€ÀøbLãÛ9’ @€ @€ @€ @€RĘJat @€ @€ @€ @€ÆcßΑ @€ @€ @€ @€”" ÆT £“ @€ @€ @€ @€ 0¾€ÓøvŽ$@€ @€ @€ @€ @ 1¦R„ @€ @€ @€ @€ñĘƷs$ @€ @€ @€ @€¥ˆ1•Âè$ @€ @€ @€ @€Œ/ Æ4¾#  @€ @€ @€ @€(E@Œ©F'!@€ @€ @€ @€ @`|1¦ñíI€ @€ @€ @€ @€@)bL¥0:  @€ @€ @€ @€ã ˆ1oçH @€ @€ @€ @€Jc*…ÑI @€ @€ @€ @€_@Œi|;G @€ @€ @€ @€ PŠ€S)ŒNB€ @€ @€ @€ @€ÀøbLãÛ9’ @€ @€ @€ @€RĘJat @€ @€ @€ @€ÆcßΑ @€ @€ @€ @€”" ÆT £“ @€ @€ @€ @€ 0¾€ÓøvŽ$@€ @€ @€ @€ @ 1¦R„ @€ @€ @€ @€ñĘƷs$ @€ @€ @€ @€¥ˆ1•Âè$ @€ @€ @€ @€Œ/ Æ4¾#  @€ @€ @€ @€(E@Œ©F'!@€ @€ @€ @€ @`|1¦ñíI€ @€ @€ @€ @€@)bL¥0:  @€ @€ @€ @€ã ˆ1oçH @€ @€ @€ @€Jc*…ÑI @€ @€ @€ @€_@Œi|;G @€ @€ @€ @€ PŠ€S)ŒNB€ @€ @€ @€ @€ÀøbLãÛ9’ @€ @€ @€ @€RĘJat @€ @€ @€ @€ÆcßΑ @€ @€ @€ @€”" ÆT £“ @€ @€ @€ @€ 0¾€ÓøvŽ$@€ @€ @€ @€ @ 1¦R„ @€ @€ @€ @€ñĘƷs$ @€ @€ @€ @€¥ˆ1•Âè$ @€ @€ @€ @€Œ/ Æ4¾#  @€ @€ @€ @€(E@Œ©F'!@€ @€ @€ @€ @`|1¦ñíI€ @€ @€ @€ @€@)bL¥0:  @€ @€ @€ @€ã ˆ1oçH @€ @€ @€ @€Jc*…ÑI @€ @€ @€ @€_@Œi|;G @€ @€ @€ @€ PŠ€S)ŒNB€ @€ @€ @€ @€ÀøbLãÛ9’ @€ @€ @€ @€RĘJat @€ @€ @€ @€ÆcßΑ @€ @€ @€ @€”" ÆT £“ @€ @€ @€ @€ 0¾€ÓøvŽ$@€ @€ @€ @€ @ 1¦R„ @€ @€ @€ @€ñĘƷs$ @€ @€ @€ @€¥ˆ1•Â8ÎIV­Zµ}ûöqŽt n¨¥•­ÇÚµk×­[‡‡$°sçÎ5kÖÄG#>#ëׯÇB`ùÒ÷áø5¾ÏÍÍ-ß…œ™@.ÿ×?ý °zõj8FÄ·¦T* FLF þƒ˜ÿ e2Wt•:ÄŒŠ?Ås?Õa]ÜÃ0¨X/7 'dâ§MÅ“ ô|C‹¿jðã÷¬•‡OĬ­øŒÌ7¾•õÔ¶ïoÓ¸ô±ˆóóóùû §¸ˆñ#M€¤¿7+*MãB»g=©¶ãߺã/aüÑF…4O@Œ©š5¬‰pª†¾‰W]±bÅ–Ö#~‹º’djâ"›Ó D†)>ñWùGC’i°d(¶øÞ›Š-ýùaɇz#1òªK?ø“꘎3sXüuFü¥Fª33Ë^ÍDwïÞß ¢äR±ùÏb5ËPÑUÓÿZ“_<ž¿¬è¦\–ÀP¨Øø6h @ÈÄ7s8¿¡õÿ«?¨Yð‰˜…UžÁ9Æ £¶‹ÙŽøÒ_jM]%ô¬šŸpòŒÈÿö,>uëë† H¦ôw/ñGï¨öøG1\š$ ÆTÍjÆ7—”8©æò®Ú,â¤ýMq³ÖÖlƈ¿X,þ«I|ËéÆ?# ŒHqÒü-¥êe=U7+ºÄT øqª—oºn>~âêù¡+~*‹lÓtÍÂÝŽ' Æ4ž›£ªð|#äŘzpò¥â?jú0Uõ™­öºbLÕú»ú2 ¤Ï¿­Å_Ÿ¦ÆÏËt9§]&ø‹˜ÿ)ÌO8Å¿¡-¦ôâÿôÍ|™ŠÐi+èù¸Ï~%«à¢Ë* Æ´¬¼ƒOÿ±L? ÆÏçT°»dO7&½1·Â&4Ž€àGÍ1ã ôÔ›¸À¸ŽÛžnL"{`7“oíéÆ4“&=!q6!èZ^&V?í±›éy-ïÔMÈ|¿QbL=8éÛšƒ³ü½Ã¿|Ïòê7xîé¶ÏË;ýs•ÓÔ­x¬`ü¥PZM?áäË70´äÇ¿©+o7õçêf-¯ÙŒ)Ðÿg ¿1)¶žSÏž†K8·ØcaÍ=&›ít‰›íõŸèìóÿ 8ýÅqú»c-y&ºÕ]¬g­}ç©n)\yIþk“SNú_ãÅÔ¶$þòmIEæM ð×­ ZLSYHÿ)Œ¿2oqñý-þ߃Éd5È¿A¥ ¾ý„“¯Wÿ·níjj^ÌnoüeËqyó4 ˆ1MzÕâ‡ÂH/åWÍÿ<éûp½ +¶mÐM…À ô|w?‡¿÷îñé@`¤@1P’:¸ú{m%³ÜbLË-ܰó 4lAë<´Eq§K³Vçõ*÷ÞĘÊõt¶åð|ýÂñçô¿qûgìœâRA䯖ûãYÃó‹1ÕpQÜÒÞ äÿ)L=5ãï²|ÿß{ÕÉŸ¡ø *ug‰uœümÔðŠ=›\û‚®‘[ÚÙ²7zŽ 1¦I/Sü‡³ØDïœI/@¯WÜ"$žk9ÓÄE6§qRÓ»”gŠél 3¢c–&г½—ïÃKcó®½è©:ÿ”²Wš3p°Ó ,r¦ÿ¾›vÞIOÒ¿ˆÔèþÜʲ ˆ1-­/‹€S?kú[ÊÔÈA#½¢OÏR|–å3Yï“ÿüå_õ^+w·ù Ó߯‘bL{ÀW›·öü_îûì³S¾8)¢çjS­n¤L?‘–©é\µcšô²ôÿáGŠI¯Aã®—6kHÆM΄ì•@D—R?ä½:‹ƒ ,&àûðbB~¿|bÕù |߯1Zã»ã4n~&T;ø‡ðh¹^9òÚ­ÍrÞP,wñ[ï<ˉíÜ%ø51¾Ç¢áôàô|C‹/ý=C ©:EÏŸ¿¦êÞÝ,¡ùwûø¶–ÿþ0uÓóŸ$+س‚á㦮ªÝðRzþ¾”C¼‡Àt ˆ1M×z¹[ @€ @€ @€ @€ cj࢚ @€ @€ @€ @€écš®õr· @€ @€ @€ @€(ðÿ×Q’úšê÷IEND®B`‚rabbitmq-server-3.2.4/plugins-src/webmachine-wrapper/webmachine-git/www/images/easy-ops.gif0000644000000000000000000002535712305126066030571 0ustar rootrootGIF89aç„÷ $$$+++444<<>í::ó56“ZZ¢NN±JK„dd‰`aŸy{´ac¨prÝABÞMOÏZZâDDîHHñKKÖaaÛtwÞxzênqÿÿ ÿ /ÿ/>ÿ>{•zLÿLYÿYfÿfsÿsÿjtny†t|…y~ƒt~Š}‚…}ƒŠ{„“u‡š‹™„„„†‹„ŠŽŒŒŒ†Œ’‰“ƒŽšŒ’•‡‘œŠ““””‘–›”šžžžž§Šª‹Ž¡šš£»œŽ—£Ž˜¤– ”›£™Ÿ¢“¨¡ž¡œ¢¦—¡­¤­“§·¦²Ÿ¨´“§¹œ­½£££­¦¦¢¦ª¤ª­«««·¢¢½¢¢¦½¦ §°¤«´©®´¦®¹¨¯¸«²µ«²»µµ¶±¶»³¹½½½½Ç’Ûšžæ„î®É®®Ø¤¤Þ©­Æº¾Ò½½à¬¬û¥¥ôµµÿ²²÷¸¸ŠÿŠ•ÿ•ŸÿŸ§Á¡«Æ§©Á©±Ë¬±Ä·³Â½©ÿ©²ÿ²»ÿ»š®Â¡³Ä®¶Á®ºÄ¨·È¬¼Ë²ºÄº¾Ãµ¾È¹¿É½Á¯À͵ÀÀ¼ÂƵÁ̺Â̾ÈÌ¿ÇÑÃÃÄÄÆÉÆÉËÍÍÎÜÇÇÑÇÌÃËÕÏÏÐÆÎØ×ÏÓÇÐ×ÉÒÖÅÒÝÌÕÛÔÔÔ×רÑÚßÚÚÚùÃÃÿËËãßßõÒÒùÖÖÃÿÃËÿËÒÿÒÜÿÜÔÝâßáâäääêææëëëðîîäÿäìÿìôôôýóóôÿôÿÿÿ!ù!ÿ ICCRGBG1012ÿ applmntrRGB XYZ Ù )2acspAPPLöÖÓ-applrXYZ,gXYZ@bXYZTwtpthchad|,rTRC¨gTRC¸bTRCÈvcgtØndinì>desÿc,ddscmBmmodÔ(cprtü$XYZ `5Ä*XYZ o‘³còXYZ 'Dó³ XYZ óRÏsf32 BÞÿÿó&’ý‘ÿÿû¢ÿÿý£ÜÀlcurvÍcurvÍcurvÍvcgt) ºvPEa”ÿÝ A º 9 ÁWèvþyæJ›ä6Zy ˜!¸"Ù#ÿ%"&F'j()»*å,-C.r/¥0Û23I4…5Ä78E9ƒ:¿;ë=>:?Z@{A BÅCæE F.GQHqI’J¶KØLûNO:PYQ}RœS»TÚUúWXDYoZ¢[Ô]^4_d`‘aÁbòd"eUfgÄhýj;kl¾noOpqîsCt•uðw@xbylzr{y|ƒ}†~‹Š€Œ‡‚}ƒx„h…U†B‡)ˆ ˆì‰ÇŠ¡‹uŒJ玳€V‘-’’Û“²”ˆ•^–2——ÿݘ³™‰ša›8œœçÁžœŸx U¡4¢¢õ£Õ¤¸¥Œ¦V§#§ò¨À©ª\«+«ø¬Ç­˜®h¯:° °Ú±¬²}³N´ ´òµÅ¶”·c¸3¹¹Ðº»M¼¼Ä½‚¾@¾ÿ¿¾À|Á=ÂÂÂÃ…ÄLÅÅÛÆ¥ÇqÈ=É ÉÛÊ­Ë€ÌSÍ%ÍôξψÐQÑÑâÒ®ÓwÔ?Õ ÕÕÖ ×lØ9ÙÙÕÚ¤ÛtÜDÝÝéÞºßàcá6â âêãÂä•åeæ1æûçÉè”écê6ë ëèìÑíÆîÆïØðÿòBó™õ ö¤ø\úFüeþ’ÿÿAäqÓ·°Çÿ÷= •  u ô}‚þnÏ*x·æ(H d!"¡#Å$ä&'((F)o*“+¸,ã./70d1Ž2¾3ð5$6S7Š8¼9ë;<=5>H?X@nAƒB–CªD½EÏFáGòIJK)L:MINWOjPwQ„R’S¡T±UÆVâXY#ZC[a\]Ÿ^¾_ß`ÿb!cJdoe—fÃgôi"jUklÆnoCp~qÄrütuvw#x'y(z({'|&}"~€ €üî‚ރ̈́¸…Ÿ†Š‡mˆS‰6ŠŠ÷‹ÓŒ«…Ž[3 æ‘À’š“ÿr”P•-– –ì—̘®™šu›[œC+žŸŸî Ú¡Æ¢¢£m¤=¥¥ã¦µ§Œ¨`©5ª ªå«¾¬š­r®K¯%¯ÿ°Ù±°²Š³c´8µ µà¶´·ˆ¸^¹3ººØ»¬¼½S¾%¾÷¿ÊÀÁnÂ@ÃÃçĹůaÇ5È ÈßɵÊËdÌ?Í$ÎÏÏòÐÝÑÈҴӜԃÕjÖR×9ØÙÙïÚØÛÂܯݛދß}àoáeâ[ãRäKåFæDçAè?éCêJëRì\íjîzïð¨ñÀòÚó÷õö<÷_øƒù«úÒû÷ýþ?ÿAÿÿ^Ã6®>äÿšc>*  " $ , +$ûÚ®v8ùµr0ï¯n.ð³v;Ì–a / û!Ì"Ÿ#r$E%%ó&Á'„(>(ú)´*n+++è,¦-f.&.ç/¨0j111õ2º3€4F5 5Ô6›7a8(8ð9¸:;F<<Ú=¤>n?7@@ÌA—BcC0DDÎEFoGDHHèI½J”KkLDMMôNÉO•P\Q#QìR¶S‚TQUUðVÂW–XoYFZ!Zÿ[ß\À]¡^ƒ_i`La5bccèdÊe¨f†gah@iiÿjàkÿÁl¡m†nkoOp7qrrîs×tÂu¬v˜w„xqy_zI{1||Ä}ƒ~EÀ€8ò‚¬ƒg„"„Ý…˜†S‡‡ÍˆŒ‰JŠ ŠÎ‹ŒRÜŽ¡ZË‘„’A““Á”„•I––ß—®˜™Yš3››ðœÔºž£Ÿ }¡o¢a£N¤2¥¥ê¦Å§¡¨~©_ª?« ¬¬é­Î®³¯ž°‡±p²[³E´0µ¶¶ð·Ü¸Å¹®ºž»À¼ä¾¿À3ÁSÂyèÄâÆ*ÇÈìÊpÌͿϤѴÓ÷ÖyÙZÜžà“åNë¤õJÿÿndin6ÿ™VÈU‘°'‘`P T9 =úá&f,E_x‘«Åßù0Lj‡¦Æç .T|§Ó5j¥ä$g¬ó;…Ïjº ]°[°  a º  q Í * ‡ æ G ¦ l ÕDµ&œ‹ýzú{ÿ… ‘¥2ÂSâv ¢:Ólœ1Ç`ú —!4!Ô"t##¶$Z$ý%ÿ&B&ç'‹(.(Ï)u**»+^,,¢-D-æ.‹/,/Î0z1D22ù3×4³5˜6{7g8Q9C:=;3<6=?>J?`@{A¢BÌDE9F~GÈIJQKLÔNObP­QþSOT¡U÷WJX£Yý[U\­^__`·bcldÃf7gÁiBjÈlSmÚoipør…tu¥w455é6Ñ7¾8«9 :˜;<‘=“>›?¥@µAÎBäDE$FLGwH¦IãKLbM£NæP+QqR½TUJV‘WÚY"Zn[´\ü^D_Œ`Óbced¬fg™ijlmŒopŽr sŒu vxy›{#|´~@Ópƒ„²†U‡÷‰ ‹OŒüŽ­`’“Ñ•Œ—N™ šÌœ“žV ¡ä£¬¥t§:©ªÂ¬c®¯§±R³´¯¶i¸%¹á»Ÿ½d¿$ÀèªÄnÆ+ÇïɨËcÍÎÒЋÒ@Ó÷ÿÕ¦×WÙ Ú¹Ü`Þß­áOâíäŠæ ç²éJêßìpíûïˆñò¥ô0õ¸÷GøÖúdûýýŽÿÿDj‘¸ß2^‹¼î$^žâ,Ü>¦ójã_Þ`á g î y  ¯ C á’Eþ¸t3ô·~C بzL%ÿÛºŸ‚h Q!>"-#$%%ø&ñ'é(ß)Ý*×+Ô,Ñ-Ï.Ò/Ó0ä23'4H5k6‹7¯8Î9ò;i?…@¢AÂBÝCþEF=G`Hÿ…I¸JíL)MaNšOÕQRQSŒTÉV WDX…YÆ[\I]Œ^Ð`aZb cîeBfÑhrjk¼mfopÙr”tRvwÙyœ{\}"~Þ€¡‚d„$…æ‡Ç‰°‹›{X‘0“”Ζ•˜Vš›ºgŸ ²¢R£ï¥ˆ§¨´ªY¬­Þ¯¨±t³=µ¶É¸ºP¼½Ø¿”ÁWÃÄÚÆžÈeÊ(ËôͻϋÑ^Ó"Ô”Ö ×‰ÙÚžÜ$Ý£ßà‹áñãLäåãçè@ébê{ëƒì…írî]ï7ðð×ñŸòWóó»ôXôöõ‹öö£÷(÷œøøƒøñùRù´úÿúxúÊûû\û¥ûîü7üvü¦üÕýý4ýdý“ýÃýóþ"þOþzþ¥þÐþûÿ'ÿRÿ}ÿ¨ÿÔÿÿdesc Color LCDmluc nbNOèptPTúsvSEfiFI daDK0zhCN LfrFRÿXjaJPnenUS|plPLŽptBR esES¸zhTWÊruRU$ØkoKR üdeDEnlNLitIT.Farge-LCDLCD a CoresFärg-LCDVäri-LCDLCD-farveskærm_i‚r LCDLCD ÿcouleur0«0é0ü LCDColor LCDKolor LCDLCD ColoridoLCD color_i‚rm²fv˜oy:Vh&25B=>9 -48A?;59Îì·ì LCDFarb-LCDKleuren-LCDLCD colorimmodœgÁ´Å1textCopyright Apple, Inc., 2009,ç„þÓ H° Áƒ*\Ȱ¡Ã‡#JœH±¢Å‹3jÜȱ£Ç CŠI²¤É“(Sª\ɲ¥Ë—0cÊœI³¦Í›8sêÜɳ§ÏŸ@ƒ J´¨Ñ£H“*]Ê´©ÍsÅÚD(0@@ lƒÈœÓ¯9-@¶¬Ù³ Þ€Ëö¥´ÎÊKöÀ¤¶xORÛ@·/]pò þ(ÎÄU¹"´NœWpÃÚt(@WÀ˜Á˜1¶‰{V@c ¥10w¢Ì¨!J; ×!¯£E8löèÔ¸š¡Mv@`‹à Ÿ °A\îãéÄ)nf£¸¼±žFŽzØ´k;J[~¶qê‚Íþt&$Òe³ȃgk.ÂÙÙGŽ‘»öz¦àH›52šþ² sßRÆ\W–w©´›Y\6àQˆðV5-Es^Y |÷ P♥€},™ÓÁY¸!P|™5AâH3Ì$ˆX†$MÂYYmœØ“9Ü•õF:ÔÀ±Á…)`Æm"ÚY€¨cMà)"m,éz&H3Òg å“5Ec`o³]éWÓ„È&˜0M›Ut@À 8€Ñ™U@‚IóYü œ'µ1Ü\Œa‰“IÓFl–u€% µ‡éD€‰ˆŠ4¢_ŒßBæb¥‡~Ôoþ*9”i¨‰“€_€QMŠ 6÷‘u ª7*…âÊ‘4Dvf&D€ (!H.MrPÌGù5"gª,FröeÀ˜t eCìJV·bt,YÑÙz.F\ÖiæYd›!• kGpô¹ß¾…ûïÃdÇ8îûQ1øE âplè¤cˆé“}(eó>AéÏ*Pýö§c>ý9y+ê>yz¾”¶A@X1ß8̱À2Ð1â Æ(pˆ£ã‡˜Áqxðƒ¡/È@Dï‚'hÞ 8È@s\p„ŽÁ` GøAÎ0†5ä ׇ¿¢Tþ¨ÛA4e âþ„ôP‡5¤ è‚@€‹õ…h ˆˆÌ‚6…¸P%8àÊ5ƒ €ÀC2ôÐ?@B¹p/-Œ^,B˜ÄüÃú >x Ç,ƒ3Î/Ps›*À&ó¾±ÍmÊÔ 4•)9§‘΢®³ïœÅ#‘‹[Ìb’€>eÉÏ:¤! (%.ˆ˜%hªÁ[FWõ…c¨€À€€@"ÐÂæÊ…ºžá®KTƒØà78ñ x(Ãò‡ÁÂyàÃøÀØÆ2¶|èƒt*?D²ŽÍla§@Ø7Àá ^ÀÃüz‡½¶Á•x-úÀ….T ˆþ­* xà O̱ªADWgA`YÍ\L€ lÁº†:è¡€`D# ñÔyæ"À†0„áÎd°#˜F1̉Îi˜·šÓè©7xú ž!z;X¯|yš^ôzüE%jQIP ¤¾Sº¸.-œzÏF4"zÀƒ¬º… d0„7>yq°‹{ ¹Œh~ÃPC2°Ü)àá¹€D#îùTEæBÛån2–±Œf@ƒÐ@…9Óyßóª·š<­f ¢×‚Ù¼ú=§:EŠ`,ãÉ0ìT¥>¢ƒ¥ìpÕ.0€ ØB¨Aá£xª,8ØþC^å2©EШ܅:8ºÄ=%a]ìjWÆ4~Æ3p\Ts"Ù¾Fö'tªMõÖ×¾H&ª~Á vvw»SnªS%qeªêaÁiÐÂ0‚ ð̺ý‰ÌÊ7ˆdÏ,  úÞœ¬r¹apî> ü>Ïó/Žqwkì ×bdžFoÕûi´@§.€F¢ih ÓÅæEwÝ©]`\÷´°ò©j‡WŠZ  àƒ4ÊŒE•¥¹z~'Žo# Ø*Ð18W–*ÞsŸ³»]wÒØÆ#€0Òéú>º§ß ´]`ƒù6ûâ÷í±¤ÏyNcÆ—–²·þ Õ+çsŸ ùŠT÷ð(\ä~»ªühVàˆÆ8à…3`€p%A J°…º:s ^ ʰô».“™hèœÌu5´¦4mÃh„è AÑÂÕ±Þ­g=œh§ú˜Y†e¶éJw¦3‹Î…-”€$0`/€á ŸÆ™bŽAaØ!DÀŠÌê ‚s˜ Ÿ‡9ìAò{€*?ùÊC^ó ýäEOÍ—^ó|Xó^ ù6Oô Ïƒæ3û̓~¸‡ÃòùÜï~Ÿ7½æ ˆI #àeSÀq#´J"?À‡\˜¢D“Àþ$¶þÏýî{ÿûàŸ+ÂÏ}#DOÛODôt@þö»ÿý“¨Dö‡QŒh\ƒÝK±Dm*!?‰IʀƀΠ ÆÀ ˜€h Ñ0€ ¨€è€¨€Ÿ=H €×<œ0Ø Ø€˜€È  ÔÐ^‘jC<`5‚Ña à×0ƒß`ƒ3˜ƒ:7¸ƒ9x‚à„>8ƒÈ<5؃ÑðlÌs?8„C„B˜ƒ=¸ƒSèƒdJLÑ#ð&á0ta-´>DC94†.ä.”†ës†lȆhˆ†„†-´AbH‡ô†j¸>ôB!$C9´†)˜æ0&ÎWæÀ-þ}ñû“?è£>õcPá?ù£>”8‰Œ¨? b^±ˆ–X‰è“‰˜H)¨‚KQ ´aA9‚…—óîF-è6~‹­8ˆHdåÆ8eñ9µHâ4 Daaÿr¿X¦h)±6£2ÉÁ3s  cÐ,íBŠÑX»Rd£q%+²Ac2¬¸Ô`ªØ&jFŽ=¡ràÐÎè2ð¡„#op[è°#;´c;¸sº“ñiæo œ@ÿ#ŠJÈ<Ï=ÓÓa‰ÚˆÔp#­Ö=곆êp0 & ˆ³²’,9Šæ`þ>æã>Í æƒ ï“/ ˆæó’%iP€ÈC&ù“0I‰0qMÐ ð‰æ ÒôR0%M‡ð›…ViÛOÏ ”@r–O}PUkМ_ P ø·è`˜N (Q ûWÊWVâ  ¥_žýTú„€0 û4 ¹ ™äÉ ¬ µðb¿ð •°F† ’ ŽÀHäH9¥SÕä gqp‡°n ‡Ð ¿ymÁii˜æŒ iVÖiûÔOb€¡Z€†/á ª CÖq5ĵ q– Fjp5W[ M\@xuÇ„\þ}•IOÄ€µX„•YŽ”ÅX!ÐX» Y}€Y‘Ũ-…X„e¢UZ}Åá´ uåZ[Yp ¥ß0x.† +Ñmb"Nã[ãp »0mPbw¦+ö-v]ÙU Ûh G ghé5 ͶMïÕ<;d%Ð «°MËöh׊dä¥N$€ ÁР;ú b:¡ú„Iý¤ °xwjš z +!7BÔÐ# ‰ ä –xà˵w6žÈi]¿@p€¶ Ï@ièÄp‡f^Ë6dÍÓܺl:®ÔZh#ÀNÍðd1fHíjr Oý´þZð Рnâðr) j³&±jørN"×0 $æd°Ç*]ÊZ]À±Üh7–_Ô¥Þ€ ŒVMZà±=Em Çq׆cþcÞÖTÕer€P¡)ׯ@³ƒÙR`˜Oà¡#oÂ@Ô€ +ºo]k(ÉZ]ÌúgGcÐÐ0Óz^ =Îð ÝÊ ‹µ§qÎ0i" NödQ&eTF`d[¡-»r €ëÖ¶¢¥àüJPâÆp@û¶kðD}à~ Ž$ .–]Ú5léDh;vhW„Ø4Þ`ô•^íe­Ò iæu¹Òþ _^ë]—6rŠdOö®wÐOh+P[` ¨ÖÜ¢åP!­ƒÛ™s» Xmàð!0#`¿ø{¿#`øÛ¿þû¿Lÿ+Àÿ‹w"ðÑà Ü<=À# SWý‹w!w$ÀL üÁý;÷k û`¿àÃJ Ê[¨«Uð¦,‘0Wb..t Êð"“ ˆðÃŽðÃB<ÄD\ÄF|Īç/pˆ€ÑC|@lÄA\Ä‹pÄV|ÅS\|Æg Ô1¬ z+14ÿ²4zH ˆ R¹ÆlÜÆnüÆm¬ѳ Q© ëÇnì Qi xÜÇ€ ÇþØÅ÷jÝ¢Ý0Æ!ð/4³± Ò@ , ’ É‘,É–|É•|Éh¼É” ÉÇ=IðÈÔ@ ÊÛ £<É–<ʧ¼Ê|Ê©œÊ”ŒÊ± Ëh ¢Ül*:+W@Ã,a íhÏ×’t…Æ|ÌÈœÌʬAá AG=Í,Íì ÑsË,ÍÆÍѼÌÛ|Íɬ†$Q˜«{ J0Á7sÁ«Û¹“AÙÎîüÎîÜ“í,Ïð\Ïö|Ï0¹>ß3”#¡ j«Q º 1Zx{_Üä@ êQ ¾ˆÀ.h–Ž ™TðÐ Ê ñ†5!F\˜Ñ Aþ«íbLm˜¯pTs†Òñ¡Nà … ·q 9›c@`Ó¡ õóÐ=äÐq«ÒpßHÔ 1Æ)¢÷¢¦Ðƒ,P-ÛPÎᦆ¹¾‰ M:S!4[M=* ÑuÏ%I”ø,”öÜ“æc rÏô<×|íΕm-Ö Š=3ʆ€HN)•M©—T9•`ÙYY—’•Á`ÙÍÀ•—í¬Å°Ù••­P SIÙ`éØyé”zŒÚ¾@zì e­`íúêφIý3n [Э”œ„Q–ù™¤™\P_Ÿª` óùY…umÀX~К‹þe«ù¿dË ´9_@6 ¬É«Én H ŠmÎРºE);nû„þ$ P^ x8í"ý¶‡9DÜ©ßÙ\g ž~0]wè™ hБŸÊ=šƒ`ŸŒåO'w̤eÔ„µÉØ­^ ShàMä´ ÖvÞ—öÚb³@Ÿì]UiМè†×¯ m˜÷mý#ŰJà‰\0ŠIzV£· ­©£¾À ¿` ×Å ¼P ‘Ð E HXzhH‹ ÌÆSP:m‹``YŽ¥ZZÞÖrº]ëÝTÕO1®èæ´Ë˜åÜÑ1q§þyúV"À§]ðJWxåJ JZN„ XˆÕè•Y–Å–5éŒåzÝ»¹›ŒšYh€X‡õðw êuðÛ¢ŠWdÀ^`ªZ[±…­ €[²z; ·ûÝaãð ÁêÄj¬Ï…¬,ök¹`ÏJ¸$à Òš_‡F¹?ö Sà­à:m=fæçº¹îD•&¦J5Œ€`0¾_V"`¯ë±ÒæœçÔP°y0[] °(†´Ik£Á&cƒ €m‰«¸ÛSZ ®ÚpÈfm$ ½P`TöT..K,ëO/ ‡€êæÅà±Ñ­ ·M ”@bFì~ËbôTì0þ±Ë S° ‘V¹ d%àì?&½äZh$`cœÛ¹†¤ $'U/ngiÐ`Y@§ ´=Ñ( –àpk{{¬)Ök|F kï„» %p¸ûÞòµé %à ¼°^RËM͆_…æ #0Áðµ/¶%—œ æOt¦¡¦;ȨñÐ]ŒàP e€§z ï»òŽä°û¬O[hËòÌ®%ÐõÑ›µ7ié”p–ö_(Krœ6nfË`Ë%W–pº5~¦pXpÝ397 yPvcP¿ö°û¯/Â"|¿(Ì¿øKÀÿ‹ûlû½À#`ÌÁÃÂ",°ÿû!µÿÁÉþ/û±Ÿ¿öûõëcðÜ“€|õ+¤Ã<<Ä„`Äá…@|†Å†0Äç?ÄÄÅäňþ?,ÿ?<þEÌÄGŒÿ?L|LìþLþQ‘!D Fš„«˜4pæÒ=„QâDŠ-^ĘQãÆŠæÌ…£ÍØ0_­|yjåÉÒJ•¸,©\9Le«•–zÕluç.K4‡Õìù².”8-í‰òçÊ”­R&…IsgÐ¥5]¶DéÉ—¥aÊE“nœCŽeÍžE›¶£9qà®IƒMn´iÒæÞÅ÷.3°yñÞµûWïß¼vöK¸ïâ»u©]‹NídÊ•-§ó(Ns8Îà:ƒ¡Î3è¶£EŸæ,ÚtçÏ¡C·==ÚóçÖ³]³¾½´kÛ»S·7N8ÙËŧèÐãræÑ5g ]útêÕ­_Çî¼:fäݽ{—üð¹Dâå'šˆž{ÄðdÕ«Ožûøôá‹Hüû~þýýÿ0@$°@D0Ad°A„0B '¤°B /Ä0C 7ä°C?1DG$±DOÌ0 ;././@LongLink0000000000000000000000000000015300000000000011564 Lustar rootrootrabbitmq-server-3.2.4/plugins-src/webmachine-wrapper/webmachine-git/www/images/basic-trace-request-tab.pngrabbitmq-server-3.2.4/plugins-src/webmachine-wrapper/webmachine-git/www/images/basic-trace-request-t0000644000000000000000000006771112305126066032371 0ustar rootroot‰PNG  IHDR JwÅsRGB®Îé pHYs  šœtIMEÙ6 šq{$tEXtCommentCreated with GIMPW IDATxÚìwXTÇ׀߭HG@EQ{o±—ØkbW,±÷KŠ]cb‰-–Ø[b½÷Þ{ V@@vÙz¿?)² &Íï›÷yÖGvöΙsfæÌ™&“$I" ظqcšïªW¯Ž@ ‚ÿ¿ÈE@ x_ÈRz4þüóO²ÈÁ‘„ðj@ðÿeÊ?$I†@ ‚,CL@ xo(ßö½.Ö„La‡‹«*™L”š@ ‚L‘®GCy›_‡—§ IôìC™’Å(à÷9ëŽßŘÅë8@ ü?24žÝÜFá Øðj gƒ¹º}+áaAXÕ‚ëÑbün4Ydl˜ :4-ZƒÉ§Q§û×™W11€ ‹I3ubÑÞc\§¯Áµëæö"¯]âT‰LMñZ½ÙûkM†ôgq•c kRèo¿Ø¦ES9wWªï» ÌËïqâÚ2ä7~§F»ïÓĵg.ŒæÒôº Yú8Ã÷}µà0#Z±fÖܦxÉFœ¸†Ÿ£P @ ²Š4'7²3ÆH§íÈg—v=F±O;RÇIÁ¬Ñûxñ7=/ƒÒª|-F®ÌÆÚƒ—xNxx8w®&WÈZPº ”Aþª]¹}l1GüÎÝ‚‚‚ â¯k‡éîH´ÖDÂ3#ß-ÙÍ­À‡Ü¿¶Ÿn*<«ýÄõ‡!üuý,Szåæ…!ý´FÞ9N¾æ Éí B ‚÷jh˜ ‰Îw{ÛØ»’ÓNÚÄhßý…m?´èÉuE}öœœI­b¹P$†9yá«y;i¡AŸhÈóÈ‹£R‰Z­F­VãâY„+Fái'¡ôFׯ¥qs¶ÃÎÙ… w_gÕ \<òÒ¶ß4r¥·†U2paÓJÚw*O6±ÐU ‚÷kh¼Æ^¥L§_ŽãŽÆ€òoôËN®egŒ‘fÃRÚ3íëe*_¦\@ž·xîîšÁM»äuq¥ýðθf`$dË]‡¯ÚµmøèBØ´=’F¥s m ‹IcM˜±º)tF“Ídj'Š:+¹nÓ;Ïœ˜yú(€<žNiž?y‚ …)"½›w’·ãáísœÍõ ÉíSÿ•.;zöÿ¨žß=ÅÍ2S)à&¼@ d5i\ .ž>„?ÇlãCt8¢ x–*OŽw]Ó é¾z€‚y]S™âøëì^úÔ¨B… eiÎïÚ9Ëœ(V«:ìÜÆÃ°X¨ì¤t¥v›¾x;=ãÓ^ ™1mE=íx¥±†7iÙž/Z&ïr©äÍ_ ÿ,óý#Ö®{°>B@ ø7<2¥ßl\º4øt_ê]®íü…€‰Çi<âwªzÿ­:g·®…8sã‘Ís+^/F5šô©‚7¦rJuœNÛR.h5þ®oãå½3s™DO¥Ð@ þ CÀ½Pî]ÞÏðÊ«¨]ª ÇŒ¡K1š9É´•ûùmH¿=ÕP¤V<ÔÜZÖ‹C¯Ò„+Ôé$ôÅ©rµ= ] mkNá¹1¥Á¢ÈdJÌ\Ý÷ÝGUÃAL›@ðï9K0tÑ výÖ+Vp,ÎL§qã ¨_âÝw"wðã»õsèÓ°›ÏM(”Ûµò‡l^µˆÓצú>G¥v ï×VJóìÜrj´—aI4G¥v,÷3òdKó\ìý?)Ñ1’ÀKƒÞ}­‰@ ‚¬34ŒÚgܾv•K¯qúø9bäÅ=gŒÍNü]0âÐhô˜QÍÁ'{õ¿’q‹!–(­ /7q¨@ ÜÐ@ xWä¢@ CC 04@ „¡!@@ „¡!@ @ ÂÐ@ @ ah@ ††@ ah@ CC 04@ CC @@ „¡!@@ ÂÐ@ðq¡E à5wïÞÅh4âææFBB&“ ™L†*• ¥R‰J¥Jú¿B¡Àl6£×ëqss††@ ‚ôQ(äΛ{Âs)éïÍ3žD¾z/ïz_qK&1™”Óÿ™¾Æ¨‹&4,òƒÕýÔºeæÅ“0^jMÿ³º•õゥ¤ÉÀ«˜4qúLë°F£A£É|ÞM†8b3¯QC¼!e¸™ø˜ ÿb=yçrÀÌ«˜b5Ú,­G …¹\ždT88:àé鉛›J¥¥R‰\.G¡T P(P*¬^ …Ba3¾ohH±Ì¯]–=÷â„‘µÒܦxÉ’ü:ªùüŠ2~wÐ{ëŒÎ®›ˆO^?*Öú’Hý¿›ÏˆkÛèRÔ—å+s6,>1M:v~Û„ÊUºŸÅ•ÿ=ÆýäâBj÷߇Q’2h`žñÇøþÿÓ2MÎk¿ ¯@ÿ2´~½$}pݲèÃÕ°mÆe,§ÿ¢neYý{_§Ðót-éO“o†S¬hAú-KþÊN¿*e8úïT”w-‡§GP²ý'Î`P¥bø–žÌ­ÇY#«×†„L&Ȭÿ —Ë“¦Mììì°SÛ¡V«Qª’§R>JCãUȦ‡Å3Í鬯àÿ€—Áç¸ÿÞŸIwd«àì¥Gi¾¼sœ|ÍÒç›AÔqR#›òãÈ25U;~Ç–éŸC¶(eÿnù{—ýœéÎ@­LNS‰Ž#øvÜ×äpÈbgqÜ)°‹ÛÖ1ðË*¨dé¢LéE»Áÿ§ešœWoúMÞÅw5ÜpÌ®þ×![º%S8ÓdÈP¾ (›¡œ2;ʼ~`Zé£Ð­,«ïià4°a{òŒÝÎéåK ½wù¼žŒ[wÝæïõQW(U³+Õgõ“Øyëw §ó¤Ý6;e‹>œŸ:´aÏ|+×§Œ·Š»'–R­ßêTƉEªKh\*ñ¡ÇhÕn!1rª”kH.u4[&tdþ¡¦$S8Ó;ö¢ôü¬9‰?ï° ÍNúN:šeý¨”â?‹…8M‹Å‚ÅbA’$,‹UÅÉXÿ>°¡aæÂ¦ñÜZ½€›‘&>ôQ7ø²IÂäïõ™ô%Ç–±-YsO—¦a¹°i%í;•ÇÉÙg¥ƒRùnq¼cÇäìäòÁäàè¤~Ó¡GñZù²{œÿaÚV^Ywª†NÂâm¹©]*×[«rvú°2• \Þ¿ž#7Ÿ¿wÙÊÕnäòµÿhtK¦t§e߯hTÎçÇrv%ÍmĨà£Ñ­¬©YÏõ] 9¦/K÷&¥­záàGß ÍY3îWî¾´¤ù}ÐÙM ª@Òù’~ßsú n-ëÏž¹Úú=ÚqeõDZ|µš±j°ô†Ñ+â’ÂËÿôö!bêv#Ÿ³ Uöütm¦bf¿úL9¹—f5”³Õ »4å`ˆyƉ$ Éì)Tª2ñ/ã0f…‘!Ih° ž>}ÊÓÈHâââÐéthµZâãã1˜L&ëï?VCÃôò2Ý×¶fÇ–`¼ÌÒ½×m6~—vÎÃÇdžÍäúk÷PFa@ÈÅ­4óˇÇýNÈK#]4—Nìdbß6,ܾ—ÙýJãããCõ>3¹¥Gu…Ö•›s,ÎÌ€Oýé1u7 ’ÿàSnõ’M+;í3º¨ÛLík¿\ëQ¹‘辞Nï>ß0jX_¦¬9ƉKöM†/å™^âÐ/º&‚m£¾ÅÇ¿''$5,›¶GÒ¨trââÐÚ‰Ö2ðïÉùÄú›qœ¹Æ¥;ù¾ÿO\øëbRºÆ®8E¬&‚Ó$•ãW™WUÍ“ëLí×–ö½zãããôM×0Jq‘Ù¿y1]J÷dõŸ+éRÔF/:Š&ᶈ áÔ¡õt©0*Ù¤—6[òzf3n—÷-IŠ»zŸ™\ z@\ä]voZL÷v£9uá0ÃÊøáããÜÍ×RÍ•FÞ=ÌãrÝÈïlz«Ü?¼LÍÜXõ+nD¦úVûä<_¶í͈1ÃønêF]âÇáÃèÑökN?ŠÇ yößÖ-ÉÀ“ר²b#¶¢•þ¾n=¹¸ŒíÆîÕ æeÉ¡tô6 uË>’e#û1l؆ ÃÞÓX6²½{·fÊÚK˜%!çX2¥?SÖ`_¢nUï3“Q¯¸qx©5>cÏgéw>¦æu,IË©G’FÍm8k§öOz~â¬Ù|7mwrfØ›é¸sò4ž•š“Û-Ùó+Ót¸“Ž_߃”&—_)nÞjð¶ÇÛ·þ…’wBx)‚·{²(iW‰l2J»ìø.‚»"¹{,T(?îʦÔn^”sS1®sU¶] ':ô#†o£[÷Š8d1+—ËA&Ã`0Âùóç9vô(Û¶mcùòå¬ZµŠ-[¶pêÔ)¢¢¢ÐëõV/ÒÇgh\ß1—6£ZR¾Rú{Û³cÚoÌaš9³ª'½·ãÊÃ0Bní!vëlLÚO‚dÊ L"ìâjô bÑ­G^ØŽ´y,5®ä…Q˽³»Y¼çÑퟑ~¤Ÿ¶´òªM¬¸O,nÌgÂ9~3˜°+ôUþÎçµJ³ï^,’9[æqèìJ:ö8LëÕ1'Ó‡ãÞëˆdàêŽÕ|Ñ»Ùdê·Êýc©›»Ô‡ÜŸ0áçÖ¬[±kZOrzÚsvËŸôš6žê¾Ž¼Š¼÷ŸÖ-ÉÇýëX6i!)±Qü{ºåU¦Nï ö Ùuæ&]jyÛÔÛ,Õ-•7=&!û‰õlØ£¡p©b¨ÎŸÄ±ñDFTDnŽã¯[™0oó¾íÉm·fIò¨S¶8£/zpðÀŸtÏ~‹¾fÛLYËÉÀí[ñD[J¦~ª]—õ´çAX¡wæ#_;ŸAzäÀýÃKißû† –æ3´Ooï½ÀåÓ1¸ûzb—Ò6Hô4\¿ŸÖè1ÝîFh’ýœ kÝ I°9uò}«6lHhÌžUã™·ã…ïO iÃ~„&æÓ¢ gÓöHê•Îc5" yû^”¾)}³uÿwlÀ¨ý¡M9È”>|µf!eÔr·¬B™jiºøÚÊo™Å‚Ùd"00={°y×1¶½ÊÙÛ‘<жð8JÏí{¡ì?pˆÍ›7sçÎ,™¡aÑ?bé5_5)2wºÍ šMl=‘Ü%D^¢ýècLÒ/;J×¢ŒžÜ›–µòayv9Ý0¥ù9ëϦp=/B¯åfH;cŒ1Pm.Zuj À‚Ý«i\¹MzüĪ‘µ b—ÃŒxzzà’ÝggÙÓnÆ®œ›ƒŸ£Ì†ÐÕiž¹¾k!ÇÌõ0½¼ÃÙ w0Ù[Ÿ[wì  jçQô÷¶glûÊT¸ÄÁÉ£G.ò9(põpÃÕÙ9Ñò6syÇ:õþ„l‰«Ö,ÑrÒN¦÷¬KñÒõèÒӇЋOˆ7§#— Ænš ª ¼°”Ú¥‹Ó´÷Pê8)è:û_4(O¹š™ÝÙ›óçd¸)•‘e¯ óˆz8ËdLÖ…@F“‰ìªÐ¹wgpnËŽß{S±\UFÌÞF5{7^A™ÿ“ ÃÓŽ<øWjDǶ2¥ª Ò–V^NiâÖ>>IÀ¤‡ŒZ0€‚ÙUÈ”^tþyeÔr¦-9I6ïÒ4ù´6Ø7äÈÙ©^¾ýÆ‚ñ2ž[A‹!œµëžÐ Bž¤û†øç´Kš_®Úi,UWÁÛÓ ³hƒŠ7R¶;`ÂdraãÆ-€ O¥£ÎZj•"©¨Ø´ L;Ñd¢J2á“•ÅÞ ¯ ¦”-¤xFÒtíEZöÃI&“ ¿FóØÒØ„c®<‰›7_®›ÃÂ:}ñ¨ÐœBn²T£w€xCjÃlíº' ˜z9·‡}R|K7%WˆÕCveÚ8dJGPzàøºcS(qVʱ—¥~o‚Æ€%“óýGž¦J˜Õ„n™IxuÆ:âï¿„¦ —,S£ãwÇÀ‹¢1§c9F_篰X”67›L&œ¼ Ëמ{‡£^—ò«¨hëZ 7Û‚*Z¯7!AI0«pB[£G*ýD¥oé)T³…lL­lÝø”¾|lxªÝiñEÀGYú臌ÜñŒ¥GàîâDŸßŽã‘«!CÖì'BÓg—fhF®Þ""ZG|¹ðôÈŽ«‹®®Ž¸¹¸àì考ƒ=*•w÷ì\>ÿŠˆˆ"##ñññù8¦NbœdºáK:4®FùJ•¨T©ËU¢u· LÿeIœhù¯Ûy6yËŽô‚%ƒÆð@cH7,XkÁA!cúô?ynL®YÁ'fòÓöd/E Á?¹wÞ:‚Éål3É€Îðö]1Ög¨„îêÏ™àäÃsƒî›ÐJm_µÁÒÍkéࡦOç¥©Ò à˜´¯ÌÌÕ}¿Ñ}Tµ4–cʽgª´-e¸ü C,魌 :t ³æF­¡ÿ‚“ÔðsDž¸ÅI¥´³iø!ÅqkÿuJ6/žjÅ÷Û•2E: vú˜©´©ÒÙáñúÜ™ÛaQ©›™|5+â¡~ÛÔ`8›W=¡Á»ÞMîï_¦*/J•*E©RÅ(V´4E*¹PºX)Šú£T©R”,æ—8Ugfߔި^ÍÜ!5Ùýc;ÝÍ’tX>2ݲücÝr"ôâ“tM…÷¥[‘WW°´ ›VŽƒ¿1qíå,i¯S–‘É #Á$Ìß²Å!v5£ô6…ÿäüRhß¾}šO@@+.ÄR¢îg9…ðèä:û4œÛ¦j‹Mo¸ä•j{œìeû} +Ÿé™8¼qª¶Q¯ËÜ!1A'Ùé0"žï6æþÐåð2̪s‰ëS¹Òð ë"äáË\¯×s7ô)ùóæ m³º4ª[™¢…}quvÄÍÙ 77ÜÜœÉáéNN¯ð+„V«%&&æík4d2§OŸÎÒOZoF[Æ¡Í÷õq}£Ót-X…ïj¸u掾Ä%9ú{Û³ozWzŽ[ÎÉ3‡]¡Au;S¦xùtà f/ÀgƒªuögtšÉé«78´v"5û…Ò«yÁdñ¹@ÌX·:ζŒ–?|IA9’ÉÚÈÞ}ÀÃë9ÿ(šká_¢//m¯šOõÌ‘-d«9€ÎõøóÐy.ŸÙÅgå›Óü»ú8`dßôÎäýq??©ÅW GÁóYLû#uÃpêÒeîß?ÇÖ}§Ù¼ê Ÿ}â›,+¹U™/†&V(3nìM£ç¯ãØvø!/ž†€îQ/•ÙlBc²Øh•IrûšŒ©ƒ,úGŒ¨Tÿ½¸¡#»ZÆÑㇹ˜4WzëÊ9n?@³‰»AÖCÎmbâÉ—Œøâ“D/OÆá¯•3F§·åÍP?òÛY2L[§<ÿDŽy«2»³7;Æ|Îñ kXBÄFîxÆà¾5¬s±¦WÖ'…¨”vÄg§ýÍ™ÚXÍHîJ¦)GÄF$ÌÆ´uÄÕUôÝÑ™oÛV§å€Ñ´pSѽýRž&I8‚ŦJׇÕ-Oé’ÒóOtËd^äVàöo9žzçÁ{Ò-‹öÃ:M`Ãæ®T©×…_{çaǘÏSƒVy$©X„ŠÔÃë2²èñm¥*Ö‹›Q Un @놹x?ˆ«'×3tMDÒ@©v³ J÷3£C ŠÔjO 7ó7Ç XôA,½ž®“zSÐÅš‚øÐƒä÷ócæÞ©ú‘£+‡ÐmÒq~ZsŠúþ®)²{(èïO³q»ÞºëãÆÁE6pz¾œr¥Ž“‚ÍÇo&T÷¯œ÷ð²ûdž†$I<O“O«Q®ta æÏG¿ü8:8`ï˜ GG\]\quu#»[v ùF«Õb2™Ò0KذaCšOxxxšÏÒ!¾ ¡ª ý²ñlrXX´zlgkXâgÃé»ÒÃkû¥AÕ\’¾?“©÷´]Rxx¸´ë·¡I¿i?f“"mœü¹õ;ç¶ÒæÍS%r~'¦ÈÛ”ÞÕ“žùvþfiã‚oSååÍ8þø}¦TÇI!’o“ï¥m{þL.;UiÑŽãÒŸÓû&Å1ðÇõÒúWm2PÚùúð´ÔÁC-Ò’g¥¯Ó¡ª -Ù°6© –¸!ü­ÒóeÔr æn9—Tf…_Ü»()½¨*Hs·œ‘6ÏI.'ÏOHû/?H_Âng˜¶Ôòš'­¶wèËҔ^¹%@êÔ£‡HãV¶¦o×¼¤4çkö“têô6©~›M IDAT…›*éù1rJmfzC¿3ûK¤É½>ŒL“Óx_šÕ2§Ô}þ±Tº}vëÏÖgr|-] “‚/oO–Mޝ¥][æ¾S:LX$í”3éïž“¬2ûPºõ럻¥ ÕR¤g½ö·uëêÁyIÏLÙpÔ¦Þf¥n=¼¶ÇZnö ¥—‚¥ð°«ÒWy’Þ9sÅÒ—MÝ­Û7”–ï9!mžÓ/)¼ûèåÒ®s“ÞéÛx ´~Ýü7êßÅTòYzä¶”J®EÚµ—©p§¹ÒƒÄ¶*3Ÿ{¶[ó§ª •QË¥ö£“Ûbk{½H¤>³IA·NI¿N’¨kßH;OÞH_Rù«*HGþ M÷½¡OKuœÒŸ—‚3Ö×Ï}èr—®ý=é÷ *ÙK¸v“¶Ÿ¹ûNyIï³wï^©à'­¥-»KWoÝ•.߸#»|SZµa´óÀiéÄù[ÒÕÛAÒýÐgRpÄ é¯‡¥!C†H»ví²ŸLJqÒÆÆ³tФzõêY“½Î€E¡Â>Í1u…Yï± ÀÙÍ9Ɇ¼‡â5û²êÄmêú¨Ñš8Ù«ßðPèˆ7¦ø^2 3Êm¾#Ýg£NC¼ÞL6'פ…]™Í³6N“2C,QZ^nï\n¯ãPd¥`¥8V ¬‰ÏˆSÔósD¯Ó¡´·Guƒj¥ŒÀ?Ðà;8sa"^’I턽:¹ Þžú‘^ÚÒ“—-âc¢‰Ó›Èæì«Cæ\¬ñ1јÜqQgõñ›ïI¦ ÿ#º¥×i°(ÞþÎK·2#ŸXԠД‹|ê›-)¯³gGÛ¾«Á´Øï8ò[«¤Ýq™-gF‹Biƒ}Úrx]ÖfÍ3‚"ðÎ W‡ôëmBäy 5>Å+ßàž^:$QÏ_ášÃãÝOVýÀå HÙh4QãäœumÂíÛ·éóÃBMw.OÌf &“…{áæêŠ›› NNθº:£VÙ¯aþÌÉ4iÒ„Ò¥K§~ûo´> ììíÿF¸Ø¸²6yá§ru6œl<'SÚ㔲tdjÞÒ¥}PÙ;ãfÿ÷òìà”hX¨]ñRÿÃ8²°£;6· gÊ,`^ââ«”å/Sª“ÓQ¨À…B© ›sÚÔ½%<+ô#½´¥'/[8ºyàøŽ)rtóxou!ëeú±ð¿£[vöΙ֓G·ÞÖ¹8<·9×® —o¶TyµK 7!ýírvvN¿Ì^—µÂÙ‹¢o)ZÉÁMX²æbúFFb›îéåùŸ,‡Tí³Ûû·ôúxq9Hfd‰.d2$I†Lf=x\¡R¢V«­÷¢¤ƒœÿgX ±\=}€9÷ôä%‚w£Lç,ê_5ÃQ@Ì“[ìZ¾4›8{î/ߨßý¶pÐ-¡[2å:î`AŠiGÎ’ðW8»/šÐ]C8|íñ¼‘Û¯üE“âîÿÏËáŸa4 ‹d¶‰Ë¶%, ³€LÂ"IH !“ɬ'ŠÚ Õxn÷Âq¬>z'ͪ4jK­šµ¨àŸó?_WŒš(Ì^-Ùºµ F£ŽˆÈWøæÎþ¿é†~O#êìo· _<ÓPé«l.Cûê91Ùíì2.º%tëã“»WvÛ£_³ŽðÐ8Ú.Ý@GL$$¼@/åÉ’ã°ßÙPÚãá&ÊáŸõ8 ƒÑˆÑhÆl6a2YÐéP«ÕdË– u‚•Ê…ˆѱ9•ÊÐhÖýç0nñ¾üy5 8û"œƒ+'2mô&ÚŽœC» ¹þÓUÅΣ µëmÆ{ƯlUüþA¸@ të?äìPºR¥^}QÿCå SÈ1').Ã:•b6KÈe2,æ^B˜_O³¤cP¥ñsØÛ[-5µÚdJ\=òÓ¼k?Î\Ê’›á@ |¼È•Jd¯™ ™L2°H2™õrWI².•^瑎¡‘©Å Æx­(u@ þßXÖÛ[__/I`1‘,ŒF#f“ “ÁˆI®Çd0 T*Ó]£‘îbP­V‡QCȳÌ»€6J¡zù1tÿÙ3IHÖË©´:]Ò ¢’ÉzÊ!€ÅGtÌÿšÁfæUL411šÄ[ uħszª^CTtÑ1šä“ßé=1Äj´éèÉÛÂSûì ¯ RÙ½¾@ìÄn2`0½ŸÅ†’)Ž ÷ {™tpSzèubbbÞú»¬MŸW11hâôïí&C±ZÓ¿ªÕZML’N ÿ/m ¹Wçl< Çb1a4[0[L˜% “ƒÑ€N¯C§O@gÐù,{{{›Ç¬ghhü6f]º÷ãÛq³‰®Ö—¹KVQÃÏ9ës$Å2¿vYöÜ‹ûq\Ü·Ÿ¼~+VŒÎJáï—Ÿ€o~f`Ùâ¸Äãû“ϯ(ãwý§²–yqí[ããã“ô»âFIÂs—ŸÛ—¢xÉ2”,Y _ÿžt-Y”#!©¯jÖFÞæ×áå)è_’=ûP¦d1 äÍËÚC·3ep< <Ê€’…è?qƒ*÷ôdn=ŽÏt8ÀÍ-“Rå¡DÝy¼¾(ñeðQºógÐÔit,S”Æc·™ÎZÒxv]Kú³ïÞ«÷ Wϙߥ £çO£jå |:x·Í[OÍšVŒë@ÁÒ_ñËÄÞÊŸ—u'¾wÝxzž®%ýiòÍpŠ-H¿…GÓ½•Õ¢bX¿T2xý9t?.CsטO»'ø_2œžñǸÊ.ý_÷(oéÉ<|iL7m‡ °™§‰›ïˆžJðŸF&“áŸ/O\äV`O#£yŒQoFŸ GŸ` A«'>.žØ—1„…ãææF¶lÙlÆ—îÔÉÈÙKqùk9£ŸAi§ÄÕ%Ûûi°B.0=,ž’kNÓx|Ãw?8å=ñ2ø¥(›/ý]î}8¿}ÕŒŸwE3rÁ.z5-ƒ£R†E÷Œ}«ÇÓw£‘ÏìfÉÛÖ À¤XV}ß‘ù÷{qéá7䲓yÿÃZæAès(l=™äÙÍm”o2ߦã9øyUÖÛO®¦a@#V÷Zȟ㛥{Ó d gzÇ^”ž‚µóÂŒØ1±.}'•áøoÍPšg®’ɰhï±`ÂeÆM£Ì€^¯Á»d3òØÉÐG]¡TÍ®ŒZsеócù¡ck4 ³LŶñÍÒ=hG2=cýüœ9¾Žcqfºüc±š¹~à ^5áí`}ç½ý³™2šàux°#>6ꆙ“+º2ûÎ îÝ뀃LFßv ¨ð ®o¥°ËûÙ½nÖÜf`Ãöä»?ÊbÑ1¨r=ƹlej@Ù4¿pl-LùuAMÔ2@Ið¡o™¼»&r:جWSº}EÙQsð­\Ÿ2¹TÜ=±”kÔìœßå{h#$;'·ä»]ݸzo9”FöM¯Kíú®\=7ˆª7.Æ‹ºÎÓN0aö|ò8Ùa”@“~CçP0¯»è©ÿi •Jbûñü¹ó(y¼sÝÕ7W'ì *T‰ÇÒMFärOŸ„áë“ ''§wóh˜Ívø×ëIçâö„îŸÇÜ‘õNY36àÖêÜŒ4}…¬ºÁ—M:–AC-80§?ïŠæë%ÇÒ²,މ  ÜÞ‹¦}g3«eNâM rvÂY)Ç üÀ††Ç–±-YsO÷¦­=Å*´°þ71ùC47ÎÄâéï‚câ)E9ýk0ã÷o9ûÀz©ŽE{q¾×n¬›ÛËjdÈÔ¯Õ›½¿vãÖ²þ,Þ—þèÛóŒ;SòAH2{ •ªLüË8Œ™¸½o.;•õ©W¿èÑ£+Y/£ :» T¨Q:ŸUn~ôœ>ˆ[Ëús!4ýé™Ò‹N_çç³²D,!gWÒlÐFŒŠdݺqôùÊZs–¿R+z¶,ksÏ~Ô㳫“*²{Ž<`¼LT\¬”×w-䘾,Ý›”N*·¾š³fܯÜ}iIÓ‡¾,ÊÕk“iݲ 7¦qãúT¯XÂÍ“Ï9­Ñ W»Q¿G;®¬žH‹¯V3¶C –Ò0ºsÅÔ¦e!ña§¸$œ 3?³25u¾˜‘SØy1"ÍïÃï?bý‰»ôjû7¦E“ÆÔ«ZìRµDÑS þÓÈårªRš’…r¯!>>½>½Þˆ.A.A‹N«E£‰#èþ]œìUøøø¼»¡a½ÎÜ™æÃÆPJ-çâš ì¹þ3¹¥Gu…Ö•›s,ÎÌ€Oýé1Õ¶Ë:!â"½}îèü©í²25¾_NÁGOꣃ8´v¢5½þ=S\äeæîÉ 4óËGïÞ­ñ)ðÇî¿ .:Œs‡ÖÓ½ÝhöÜB—¢¾ôžs”M¿hGûÞßУ•?_NÝŸ”N[ù8ôK#†®‰`Û¨oññïÉ…Ç D\Ûˆ{þz‘y%T»‘ÏAEÔ™ |>|YRü^å:3£e~ë(öäFvÆé4¢ùìÒv&Å>íH'³FïãE:.wµ›åÜTŒë\•mW‰=ňáÛèÖ½"2Ù[Ã-úG,» "§P«B)|}|Xuèî>=T':zù•àæý§o÷eʈøV­{Ñ®ß|¢,¡‰·j7ƒp­Ä“‹Ë¨ÑÎzëbµ‚yY¼÷?w(ËÐ5„îBûÖ­:ç¤íi&™¯‚… Ý5„#VÁÖÅ“ð¨þ ¥r[Ïx|–Kz,*øJ U«V”kõ5³g`ZfÝý’Ž;'OãY©9¹Ý’åêW¦ èp',&¡Z¿cÛTÉÁÆi{èÚ®¼m¦ÌoßBøJ> Á£H|¼Ýoæìºïñ)6”¿¢ŒImÁå}Ö¶ wïÖ ›Éôá}Ùw/6SÙ ½~ÞjÔ¥ðF¨Ý|èà¡æ­WÒ´ù«¶¢†_joçõƒ“)üy{ò:ˆŽJðß74r{{Ñ¢~òæÊΫ8š8-qñZ´ZqºâtD<~„#ÅŠ%Ož<88ØVþ4ClÎzRæër§‚ žØ—~ß-dõOƒÉ3ce}²¦&]ß1—6£ÆR¾’ý½íY8톷¯€Ÿ£,©>³ª'÷ÔæÊÃ0Üu7ù¬|sÄççÈo-¹’nX+ž_ú}uœ»õט+ŒlØ–{¸v¸1÷ÎîfñžópÐÄÒ «XRe=}ÆÌ¤þ5gnù‚ù&S£Õ÷ÌÜrŠ&żlºÐõZkV¸QÜÒ9Ü%oÊ=8(d¬Û&þÎ=Uø©}¾þi?G~k…,ú:õ: cÚŽë”÷àüª®´ ØÌí =ˆ¼w‰yƒ¿åXœ™C·âè[Ó…3/ <<6“ß5_prisB[R}x( ìâ›ù¾}¡7ŸtžI™ßÚQ|Ì÷Œn[';BîÜàéË„wðr¸ÓfÁ$¦·ø†»ÆScÃx~\º›ŽJ“7·µ¬Ì‰jWwÛÇ7Ëí]Éi§íb´àîhËsàÃWkrµY/·¬À÷+O1¨~þL…ËÕÞLœï[µAÛ{V&({-,;ºÒtt.ÎÜÙF>µÇ×&‚ˆW“)î©âÂú^´þ1/Çÿ ¥ ‹Ä™U_Ñ~Ô–öN|Øi¾ûzj_W›ï‹“$ ª%Á$h o5*%S; ¥ëÂòÍô¯@ðO ¥RI™…ñÎéÉ…«<~Å«W±˜z Žj,Njr{¹S°@~rçγ³3J¥ƒÁ±Gc÷ÂqŒ[|€ß÷fù¾¿0nê2¡o=~ÖƒÝןþãŒXôX:GÍWM Ìn3‡‚f[S,dKˆ¼DûÑǘ:¥+^v2”®E=¹7-kåÃòìrºaJósÖžMáz^„^;ËÍvÆ!b¡Ú\´êÔÖšÇÝ«i\¹MzüĪ‘µ b—ÃŒxzZïpÉ³m£êuÚ™F@k–h9i'Ó{Ö¥xéztééCèÅ'Ä›A¡´£Ž“‚ü93µÄœ%Z« pÕVŒÝìräüLÆ.¹ÆŽ1 Q©½=¼…k¡¯pÌW“_D2¥Ÿï‡‘&=r‘ÏA«‡®ÎΨd2ü?Áµ+×èZÍûäçS®=v3¨š £{7£éˆ?Ò,¤´W)Ó™yŠãŽÆjÌf4垣heêäH^´yßIž¥8R:Ãp™š¹óR²RM¾œ¸‘S[`þò³h% ßr5;îB^êIЄ']ù]µ¸wÖÔX™š"5ê§Ê§2qI)¥Ú 7'd¯CÁ¼nØ«í°³w#»« w'\ím_®”T|iذ\ÒßÑWp%8yqjîŠ]9wò £?/R»¦K¾æ¿Ò¬œõà=§Ü~tðP£“@¦PãšÃ›9rØüä-î…J ö  Û^(]&æWO§ðçímN›Èí|˜{ú [†Ö&üÔ26Zh=î$W.ýaõŽÉìi=þ .ß´^¼užÖ#Ž2qÉàÄ+µ”©ûYŠºªÄ»xîtóåÃ9:pn‹ž´õ=›³ì­w5h®²òeIªõ½”à™\Ž|óÒ¶E=voMïŽhß¼ÍëW¥q½šT«ò þþþxxx-[6dòLœ£Ñ¬ÿšõ·ýÒ¢õú²¡^ß,ËDø•Ýì|¶Ÿ<«á)ƒg—0ë‡ít«ÿ 9T2 Ú§`ßÿœvIvÕNc© ¼ Þžn˜EDP¼‘²…Ü&“ 7nLx*-uV‹K­R$ +6íÓN`4™°¼ÞÃ+YG47°ýtvvvHúWä¨Ð†ZÙ3ß%5úöIïó-Ý–\!Vn%ø#ð>g·Ò¥ÞHŽÅ™Áµ[RÇd6J tI¼ýUŽZ n¹ ƒn!ŸU+NƒÁ3™úu;ìÁæûõ-Þº#ü[ ιËðý†k4=°Šf½&poý÷ôÈ‘‡Í#ëbƺUTg4¥Óÿ:QÔYÉu˜$çw®çê vjHx¥§ZÛî”É­gí ºì­5•c*²yd &¬ÿžÏ5jö/l3¯2cd™¿RW¶L?Oë‰'xªm…_¦Z5žú_Œ§F©ŸSýÖ5›Ò¦Ü[$®ïÈZâððsÊpëxzi¹x& ‡Ç°çÒM,—Ñ|Àl:ÖëÆÞ‹›(å©™ŸÖ5(í3NžxIÓŸŠ§u›Ñš%ÔXמŒœð–¡ûs.¶'ÛFÂë:P2Ÿ{¦Fþ]æ•Î`ä¯ »‡ÕØ/üéHº8¹Z§‰<Ô)ú!#wýO®˜´-øÄL~Þ’¡å­ïS¥hxžÜ;oõär†èÔáù«vecÕ®o´.ùX:Ä—Þ¿nbÆÚ,è_5M㬾˵'®T*œØ™¨S·ÊGý!§Ö1ót,;¯õ"‡JÆ ƒ6UÇ`‹k»ÖáÕ¨#Þæèªé:ú7®?j–a¾G7—§M ×°³Ïü=ô*bè÷ý~ίk•Ô°f÷-L5Ì `¼•šÒß{ ç­à^·êËžÚïsa×zQ™=¾œJ£7õä¾u£Jñú|[W~1–ö%Fc §6ãpllÉ6êc)ܨ)Ç(Õö8aæÈ¢1¬|¦gåðÆ8Èd¶åžÊØMß8µtèɆ½Z–˜M|Nf•½"I¾N„^|’ªã~[i‘L<¾¯#oóät¬Ö˜?ò8È›(_J{{d‰mÁùÃW‰í[W™ ™\‘"ÍÏø¥GW«G-¸M‰ºŸÁš)„GÄÝÓš¿Ø§Ö©‡\Éë;LJµ:ÍÈ?_#Û#ÿ×éÌÜÆ3Z{5’ÉÚNœ¹N}ÿ¢©uÐ=¿N‡€AéGe߃{‹¸ôŒz~ ”§lˆ60µD®enÀ¢T§Jc’ñT*—è•ÿÃY’a!—Ë­×ÄgÒ°þ÷¯‰—âØ2n m¾¯ŸÊÈp-X…ïj¸u掾Ä%9ú{Û³ozWzŽ[ÎÉ3‡]¡Au;S¦xùtà f/ÀgƒªuögtšÉé«78´v"5û…Ò«yò‘“ç1cÝÎ:kØ2Zþð%]äI WàÝÜ8¼>ÅîT¾ XNw/;vÿØŽ ¥M>ôþÅ­,S§’:©1¿šèT0óèÆÞ$cBo´]àaà&X¦Wܾt‘Ç1‰.`Ó+R.Pn²áxÈœ¨Ý©'eÔrœ\ü2•ïS—.sÿþ9¶~H虥ô÷cþ¡tä¥ãö©í©†Ž*ÇDŸ˜•§Ð&®Æzp Ñ*÷ú”v2dJo®[º4øt_&n• \Ûù S~ð2ª¦¿Â)WQê8)Ø|üf’3æþ•Sà>€^vo ¿x&>þ=Ù5€§»i9âS†ÖIí¶—â8ºrÝ&ç§5§¨ïïš)U~ñ44Ñ M=Š·è1¢R üKôâÆÓë¢SÍ&N^ºOHàêõ_šMì9y£$YÃ_äVàöo9Ž0hÞî~’)½(ßÜ“5Ó÷®µÊAñˆ ÑêV´Wÿ  ¿?ÍÆí"ÁއϺå&ê̆NÝÆÃÐl_0…1Fìe ·ócå­û¥ûiVÜ•"µÚÓÂMÅüMç1c=kéèõtÔ;qć$¿Ÿ3÷>H3òïÚ©Lš‘ìƒ=IéÔ¾í 7ÉÀ¾iµ(ìïDzãa8ç)E 7‹¿ªÏªC×ytÿ“?œÜ®ø7Ï0OA‹)æ[™¥C|™1b Oõ`æØªo çw4¯”+1ýጩ\ŒšýV£I‘ÆÀëÈ×è 1m"|,†Æ¾ésâ›G|Ëú3a©#K¦2å”u{ÜÀ†¥9óØ…{·1¨š G—£Sû/p¾†‰mŠ Sz§ jöœÅϹˆ:7‹-šÒ}rûM!OŠ­–KG~ޝË6ÅØg9¿t/›ØÁ•¤»—Sú4côEgЧ³_Má\„‰çβ`Lg6þØ“²…óãããCÞüþ´›ľówiYÜÄšÉ#ÙcäÊÜn,Ø~ž3;X·Æj61qá1òUlB 7¿mK·YAôž5tè3èç·Î¢Á€Õ ;@­Ê£¸ñÔºB©r`F÷š|÷óUhD‘‘«¨ZÀ9Ã|Ëí|é:¢·–£nËõ.ã¤ÞBBäuF¶-ÇÐ5Ösz×-ÊØ§PåÌG 7–ƒ(œ7/ÍüòQ®AÚ_Ä’AU’F{î…pïò~FÖ[CíR©Þ³7>yýh>ä$Ó×fó· 3t5+œ‹0{çJ¤ð-ð=ZùÓb,lß5”*Ù[Ãí\Aw€^-ªàããC›™wÙé.•ódKr©oY1 Ÿ¼E}º ;OÞ [íü™0– œZ7jíÆ°è§X¾ãrÚ-¨º<~¡É² IDAT§`õ6´pS1¼Ã§Ô¸ÉŠ%ãÀ¹-v±QÄ›!W±Ê`¼L@Ã<ËáÀºo¿`äŽg„îB×~³¸™ÞGüɤë©R8/½{·¦HÕŒ[y˜…];Gkšnm½ÎKƒŠ†ƒ×2¼™;ç}Iíju¸aI}p›R©F­Nÿ£ä…™q`òyøøŒÅê XƘ6%’ý ‰ÛŽ4ñ¦#ÿ ¬|¦§Néj´fNoLH&ñÆ´ß§Ûðébˆ~©E¦ø¿öÎ;<ªjëÃïôLȤZ ª‚4¥‰"éEéED±PUÚ,E°pi6úQ‘""%¡wDP $HLH€d’™L=ß“LRȸw½>óàdÏì³Ëš³gí²4| 4nÓÓcÇ’¾™×ËÏ휯ûØlÁ­5âwÓ΄üêíýNš ƒŸ¯÷ï·;u‚b'-CŸQ‹ÍjÆb±£ÒûZg‹ù»ÐP<à6·º°˜Í8ÐãgòÍǵ^pºÓnÅjs¢Òòô¥ÝœÈ…„ J—)E€¯þîþ²”4¾Ñ”°±{hQÌO%͉¯É .\hr•Óf5ãÖøåšj¹lV3V› ¿€ÌEÃ9ã^*µ=ÊéC/gš»QüðQÿɘºO¢Ÿ´‰÷»U»íߥÙlA£ÍgÌÍS!ŠÓŽÕáÂ×h,@Øî§Rë=œ82ŠâE°“ëúó~ê[¬XÍû›M³:ñ5™°Çn£r£,ÙqšÖUn³-=±—ò+§ÓnÅqÓ”˜ÍjEíã#ÛZ…ÿ.]º„^¯Ç`0`41  ôz=:g!¨F£ñNŸ¸\.œN'N§“ÔÔ¼!´Fµ5 ¸9žþyWÙe/ü4 Öûà—¯[Úˆßm´ŽÎH)càß|z|sTãÖ"ÃSw_“©Èõö~Ç/·‡æ¶DFfYýŒYß5a0Þú+¾¦@|ÿFÿûšï(]«7b* zzS(ÕLÿ {u±ó“6D՚ϧùzÛÌä-ˆ&X2ÿ^A êÅy™wÚôã«UsLUfÛâðLÑÓkï¨_L&S!e2Þô›Ò{áæ-g<ï´éÃâå‹$2â~C›wåоª¹~³YűÛ<Óº;8·°û‰VoÌsÓ,ìó‚ Ü‹5÷·=…£{·0oÍf.\¹.V Üuj=¿…ÃÞO¹Á¼±ãWZV)žïoáÈö ¬N¶³ù‡Ä]·ÝÃròÆŽ_ióHÑâ„UjÃÙƒž8;7“’ÆoÞ`÷¾“¤ÿƒmAàAõhÜ=æ$\¡‰ŒìŠÃa%>!•ð2AhÄ„»†† àÀû¢$*­‘‚Šâ0'‘¦«Idd$ŠÃÊÕ¤TÊ•¸ïÊ™>¦àR\$ÇÇþì§D¶Wa·Z¹–æ¤X NÌRnPEQp»ÝÞ³þ?kÕ…¢(xÿ+`!÷ÿœÐ0W¤Y‹ŠbEÂÿ<ÿ¿ µ›!Ý+wAl(ÙB"KX àVܨÏW·â&+⪠AAЍ2rx,Üo†ËåB£ÑxÞ«²Ou»Ý¸]îûìdPAAî[Ün§Â•9]’õr¹\¨ÔžÝ&Y ·Û[qèѸ/ƒ:íÖ»u:¶¤%'p=ÇáaÆ]!ãY÷Ÿ(¯ÛžBb²å¶¾“aNæJBV»‚ÛžÆ ³M K„ÿ \.WöÚŒLát9½ÛX]N—÷}–øp:œ8œŽûTh()|Ö¬6›Î¥=P½Œ°°°‚_Õß&ÖòÏîñ'7òBµpªÕªËîÏö¾¸ƒ_òxÃ켘þ@´ëÝ,¯âLäË)=)Qé[.ù{¿mÿŒJuÆ2®Y]*G”£|D5>ßsEî>‚ üO (J.‘55âr¹²ÏÌp8q8Øív‡gA4ï¹ÐH9Àì¸t>[¾7ïÉŠ÷ë÷q,¶àÁ®BþœÞ¹€Öc—q6&Æ{¤ñ¯Ç¶3À÷ Ééδ̥k¶cöªÙd‹ј·^F¥ Ãaàw³¼*m(}FNà)? %|Š6KhKÚOËþï³!z KïcîØ>Ô®Z4ï‰-žèC—äN%ÂKÖ´H–¨p8Þ¹²D…Ãév‡ [Ö ëýêÑpq`í¿8µt>'œ÷E#Û’N0²MOâ2 ož¬¨‘*G1­Ö{¤±HU^úr!>ÿ|Ù‹ç>‡À·d-^7ˆJ!Æö¾»]^}`qJ4X‹¨a“/žS7J¨PJÓíÕQtÔápÁ6•4ÖOîÈòsV¹S ‚ðÀ¢Ñh<"Ân÷z4œYÓ&.v‡»ÍNFFV«‹ÅÊõk×Ñét÷ŸÐp^?Ì€]ø~ý‡à8Ì’ÍÇó¹yÛ9´áSï”DŸÑs8þgú­Ó€˜ƒ‘´‹(OXX#¦,#溷5™C»60mXW|·™¹/>JXX‡Îá·$¶¤#tiОi.^zº2gn$ã6=-gø“†ê”3éHK8ËÆµ‹Ð}"{lgt­˜·îXöº”Bëhåð–ÅÞ´ÆCçpèµ\í³Ý„=Ô‰]:Óí©AÙO×ö~;¸›Ùc†±í÷ÜÖDömßÀ´‡òì™ÙËs½1ËH´e×1é=¼Tã!:?W‰ÇºL`Íæ_Ø»+Џܶ˼S¿2Cæý\°J±s|Kv}FLžÏލ(ví>ÙigÇ¢ñô<„á£F3dÈFÍ‹c—‘d¹qSy ï«‚¸zæ'^¨NÁCh_¥«“íËq:h~vðÇ®%4è<Ìkyý¥ÑŒ=šÑ£'±áF¶JWœ×Ø´p<=7˜ª…ÓbôâÌžôm<ËëËãùvÂxÂ*âÀŸ ¤°uÑxO[<Ô‰¯ÛÛö$‚ðO¢ÕjÉÈÈÀb±dOd ›Í†ÃîÀjµ’‘‘9Õ̵ädT*&?Óý'4Žÿ ]'t¤Nýg^ÚÈ÷³¾áBº’Ëãõõ †,3pä|1§6‘9——¦ÿH†â,$M!îà|š »ÀÂS—8sà;”u“iÒê+®9,œ‹ÞÈ¢MûyçõTü5‹§?Ï¥ÍshÙf)Ö€|¶Úsªàœõ{øxDó[K:zÑ¢ˆŠŠb϶õLó1(ž QŠ+ƒS[?e[ôWô¸._®fB¯’Ì3…s×Ý·¬ã®E­é4ú"¿œ¼H\̆i—ñÜ“²å\ V ¦ëT{ODò庯èÛ­¤·\sûv,gÞªMžÈ¯¸öÇfmÜÌð.m±<:’¥ó^cת·XôãyO‹›OÓ¿UªÌÝAdä1ÆWÚʨ¡Ï3nÙQÒm.ÀÎof;£ \À{åÐÚ ™Á¦c±ÄûžÔ53é×£‡ã®áR’Ù·3€÷f~̧³¦Ò±Ü)V¯^M•§b²&ç*¯Ói-´¯Rò°S/nâ±gÒ}ÍAÖ|¾„y_Möˆ®L­P]¤( =ÏÊw:±¦þ‹éS§3yü+<å—}œ[LÔW ›ñë–/aÙ©½4üù}f}€ÇŸŸC-½šÞ“ßâô‘y–s¿ŸåìÙ³üvê8;Ó²‡`S™Z´yº[±#úשOŸ'ƒã0—®š ­£ãÊúL?Ï„ù/Q1H‡JÊóïM-½šY‹wcM:L—±?3sÉPÂMjPÐjàïµ Áé™YWµ>”Ö}_ç)? Ãæmc@›Æ4ïè ùn÷L d\¿Êq»›‡ÃK€Ê6C'0}â`ª•ôAmˆ`ÁÞ#ì^Ú-¦Ø9½JO!àž£qùÈF6$þHÙ¥ QAâá|ôöwôk9Š:vË_`lEå’™ UzöžLC õâw¦¹-¸î v¥â€§ÓŸ5kÖNB´nV·A¯ËzRÕP¯í 0k§wÖ4“â ñ'·òÝÞ  [*%êv¥Cý0o]ÚtìAÿŽ•¼ïëOæ×‘½uÅJ‚6ÉUS¥ÍžÇ*¬Žé±?P¥\vjÂy®Uq¦þxœ¸žüJ…ËN÷ñÌ(™K ®›ÂÀk´¹NÅÛ/á´y<%IWÍPÙ½Á“wÎ~ÁÁw¬J_@¸M¼y0þ*J”­?: ò£r%?P®²°×ËÌÜS¦h¹¹¼Yï ê«\âÕšÈ/›’hû^%oŒ‘œõSìi…ÚEA˜Ùiå&vo<[¿É°éËÖ-ÛžY…ÄKÑì¯p¢ lDddcTº2$Ò§ ÷)jµçÔχ"·X1.œ?ÙlÆœj&##£ÑH`` U«V¥JÕ*}Œ¸\®ûLh(׈5É‹WS/D P=þåJ`Ò±õh_žoŠ_°nåb‚ˆŸ›\1§e.©[§>äÞ-àt:±˜s ÈÑ5/¶´võë×§ÞcõéÒo*³?Ø‚YQp¹<ë+7Dg/üðCæ.Yǰ֕r7¢.·^Sëh¬gèÖtF®ëçGauŒµ{ÞŸŽKÊõ»ÙEù¦õÖ{ªíQòt¨æ¦Q6»®ù‡3fŽy*m(uÖ¤Æ ÝÐ¥]¥LÛ•ì^ØÓëqÏköBÔ ªPƒá¥ômÎÕx;£¶Ÿâå–Ùm–‘°Ÿñ¯}CH£)¼ÒÅæûò±Ý\ÎqîÈÍá½ ï+«Ðà«Qq`éaïú •Úó·¬0èE±‹›Õ‰I«F¥Õ€beËœñ”oÿ1ou­¸¸—‘çY×*S­&X·²ð»‹œ+«Æ÷àÀ_r˜ ÷'*• 2ïùZ­–à‚ƒƒÑd,žôÛðüóÞŒ4ÖO™D×·Zæz¨øo6 $)êm~>sÿ 1¼´‘-³û2hÊìŽÚÎĺõ¹Ðüyj=R§À´ŠAÑéå†$E¿Ï3½ç°÷è ¶­˜FÓcÜ>;ˆÔî}gpáÙÎúÑèÏéøöH*ú«Q2÷Ÿ9û'¶¯bçid=dï9t’ë6ÏŠ\‹ÅLüÅcÌØŸ­)¡SyÙ™ê=í2+ÖPhkTiÄÜçKóý¤çøå‚§ ñG÷}"¯ kBHyÏwWNìÀÒ_Îb6dzñë©à8ÌÒÛH°(Þ¾ô—gJÄž|‘ 7ÞÁ0Kxdy8Òc¢Ó„ŸiS«&“?zç5Μ¹@j¦èqÛ.1¾~uZ¿Uðnœ_#§³ÀÒŠ%ð÷%íÊyÎÇf.URXý¯á·»™7£ÅU*g"‘³"±*ä)ï­ú ÅÎöŸ¢Jå¾Ü§¦Ç¨¶0ƒÑ³6‘`6óë®Xlçç_¶r6©x‘ìóZ,™}eO¾Ì†.Ä¥’55»ývûƒ?ÎgÒ®kúq{O\ Ë'²çÐa~ÿ};Î1 ÔÀòq홸`#'Oä³—ž`yñ‘<^ÖGîf‚ Ü¿b#Çÿ¨ÕjŠùÃÏÏ/GºÊ»øS¡ðj•’ãpò5kÖÜÕ‚6nÜ8Ïß¶ÌjÌ/®.,ÿ”^ÊeŽÚvv,žD¿i˽Ÿ]½÷,õŠÅ0gDw>‹Jà•YkÝûqt*¶¤Ó¦)ÎD¾y»-o­ø+SÅôãÇ“©^Ò‡Ô‹›x¤é°\åj=v¿ú¾*.óy¦4kÅW‰6ê¼²åãÛæz¢ˆ‰þœ&ݧZÿ™ëð´>Š!]^å¸ÝMùvï±âíG˜Ù®;n8yü%–ÏM%Íùëá¶Å³â½N¼ùùzÈÊ/¿dÊWÛÚÒã °$fR«î¬NöxxZ?ëÏ–]O0õýÞÔ-gáƒþ¯z§êêòñŠiÄÌíܽ)`lÅ⯆s}ÏÆ}²€9ëÒõá«ô¯ß!ׂVJ¼Á¡£uÇ2¶As޶ú˜M³Úå» 46ê#õø0Ïß;Nÿ–w›%RóIOÛ—¨[Ÿ j8xð ôãÛ¯1·ïËÞò~²z-J-´¯Pìl™Ýœ!_"¸ñD¯lÅL`äÇ<ר£çê;ÃÆÌ C§ŽÔ.—Q ]ÄF/£Q÷·o3Š9#²óÓùdÓ5ÐÕeáúÅT5ÏS}þåé§™_PþòŒûd½§ËŒµÙ¿ôuzLøLÝØº{&a–CŒhÕÇÛž­Ç|ÎG¯µÊcO‚ ÷ qqq”(Q‚ÒeJ£Õj½¢Âáp’’’gêD­Vãr¹°Z­¤¦¦Þ{¡qg¸°Yí¸5:Œzím¤Aê¸Ñ` 4y' ²„Æ×»NÓèõ*À…Ý® ÷æïÂ’fÃàçëÍWqZII³¡5øþƒö$‚pgÄÆÆBÙ²e=BC¥ò¾vìØA:u¼bC§Ó¡Ö¨q9]dddä+4ÔFµ5ŒÆ|àÂÓÀ?0À›“ìÅ„Ôzc¾7•Öø …×£X`0%K–ÌGdx¾ëk2eîj¹s‘¡8ãùfì|üK—¢˜ÁH``0!Á!øhÒ9u ŸÌ­'Z½1_‘`ŽÛǘñ” Â`4LHp®´¿¨Ñ&ì¶w[¥¯â~Ã3“Ùճ†÷o£ÉûYm>mšŸ]­Þ˜)2ÏÉl6³qãÆ|§XnF+­)‚ B^±áù§mÛ¶´k×—ËÅõë×ÑëõhµZt:]¡‹@³¸/<N»—t© `1ßàÆ óýÜÖd⮤J# ‚p_qï…†’ÂgÍj³é\ÚÕp1ÑË ó¾ýŒ¿l‘S¸ÃŸ3‘o¦4 Ê£ýyc`Â}—ó×…‹’?wæ²Áò•k±?É!)Â}Å=Ÿ:I9Àì¸tj,ßKëµòFݼ×\¿¸KššÔ._,ßô ûrzg0ÕŸFùö³ýßó›.·TV6¼Û‘7èÇÑs/SBë`Ëìæ4kÀÑ}/SB—])v¶-Y@·Ñ3h\RÍnÃmªBۚť=AF6.¬ý§–Îçd‚ó¾h[Ò F¶éI\FáÍ£ÊÜgÙú™GDdwLzÜF,¾ÌÔ9<¢B¥ç©þ³ aÆçûŒÄƒŒX¼‡V-ž¢m·Þ¼0` ýº6¾­SWAþq¡Ñ£G;~Ý Î뇰¢ ߯ÿ‡Y²ùx¾On‡6|êu÷=‡ã¦ß: ˆ9I»ˆò„……1bÊ2b®;p[“9´kÓ†ueÁw›™û⣙Ssø-Ɇ-é]´ggš‹—ž®ÌÀ™+*æ+Ç™ùb7z BXX³Öá(¤%œeãÚE è>‘=¶3ºVaaaÌ[w,{Ž^±s|KvGLžÏލ(ví>Á©ÝKéÜe0Ý_üŒ$·Blô2:wLçîz#¡tí[åmv* ¤°uÑxOúCø÷ºýÞ¶pÛ.óNýÊ ™÷sv~7aM:ÍÌažö}¬Ëvœˆ\ÄžŒfé¼qô³„›{ò¯<ˆÝ¿§؆1™u+¬®ÙÊ ÕŸcø¨¡tîÜ™E[þ(8¿|m#‘}Û70íÅ¡üpàkföòØÕ˜e$Ú²âÅói¯tœ¹#W;ÎlÇ!CºÐgôfÆ–s)E²Øãû=^²rÙÞ}`=ƒõ|y$¯ý)vv,À°¶OP5¢#gF’씩;Aþ>ÉÉÉ\Ž‹ãôé_9xà {÷îe×®]ìÞ½›èèh¢¢¢ˆŽŽæÐ¡Cœ8q‚sçÎÏ7òÍïžNÿþºN˜LúÁ /mdÁ¬oÓ£.ÅT^GÔ׃±©GÎÇQÜz’NuÚóRzvü»#G LëÌÕCÿ¦É0+ûN]"àÆƵêF“MÛÞšsÑY´i?üädÉê¯YüÄ*†NšCËc&NEõç³ÕïÒ¤ó[ÌY¿‡6‡þ=o…bççÅ/òÉîœ92 ×ok©ñL{êÖ9KŸ Nmý”mÑר6ÐÍêe«©´b8B«§#y8HÍ•CKh7d›ŽÅòÇФ3ý¾p1zÖ7 ìÞ‹þ•?å•ïM¤Z!¢a_¦½p†6â°+…_»ED±Bó~ô‰ ¾Ÿö,[ÊÏåbÜ Îï˜OËþ]‰U¶ð~·€ßÌvNF%àzt7ûªÌ§Ú¤-ý×%n>¬~ûYúµýš5ûÿ TÆ_¬ž·Šãv7i! Ù´ásfõÆø·³£€)¨ Oô¤åO ©k ‘C^ã™e{è_'˜“ëGòïxk¾]wp~¾¶qrO'®ý±™E7ÃÆÍ¼³x5KçÕ¥ßko±èɆLìX Åeçô©t’-¸ðÔûÀªÁty§¿üKE…¨¯_£Ç„M,6›ô¸½¼ùÆ—èÃò-Kšª"}ºóõöd˜íäIUéiòÊ:võIäôÞ­¼4ñc"?Éï_6ÜGÓ‚ <˜BÙ²erUËo׉Á`ð¦TížM¸m—X2OÏkm*ª8ýæ¼æµDî:ïýLFÂ!zLÜÉÌ} 5¨ÐTcâ»Cèødy܉‡ LÓº®²ê•¹TiJì±hNÆÄ³á†â§k)EçÞݘ¿q)­}^œ ŽÃ\ºjÅΙè•Pz áÁ*´!u6ª ”xƒ¾½š¨ÓSµIKbÌ[´™#~Öû‚®}«¼}®îgÄâËTðËàÀîhâÓ=ƒö²YG°( jC öa÷Ònù ƒã?,`§«Îë¿}à7œFÏgVîüƒˆz­éöD åÛ̪ñmyô±–ôè]ºðFT^W·ÝÌŸV;+¿ÝF²M¡F‡1t¯”W÷9 ´‹×ƒhÝ÷užòÓ0lÞ6´iLóŽ=è¨#Ýî™ÖS™±c/ßÎx• [Ò~ºŒý™i‹_ñ„`d.êIDAT­GC­æ²‹­ÑRú‘2”(Q"ßWéþ¨±‚©•Ëæµ5“*ß©p"*צÀqœ?ö#B œú|0¯Øä.)Â}E.ÆÝŽÞZ—ldCâ”]º$^ÀGoG¿–£(¡Sa·üÆVT.ið6 {O¦!zñ»ÓÜ– \HwP»RqÀ‰ÓéÏš5ë'!Z7«'¤º^—u˜µ†zm_€Y»p8¸³ÏÏSeüÉ­|·÷ƒÅ–J‰º]éP?¬hUéi=n/OÄy¦0>Ù¸/×`©+V´I™Ñ@¥Õåú®_@¸M¼y0þ*J”­?:Õß¼ö-òN¼ä|þz'šÀFDF6F¥+ã Œæ\ÀÑߊ• ÇöQµã‹ø©Àétñ짬oí¤X©²˜Ê %Kéj¨\çiÒ—sÇí­6”¦ù€ÇùjÖhj}1šÉ‹72¸M­|Li…Ú-&möЮ¸ón4 -“-†o$^*Ûcáreïüð-ó8oO{¼Ð²ŸÙð˜—ñûŸïR>"÷âãŒÔ|<7a©ÎØÕsøªùˤ¦Û¹³ ‚p  å‘£æ1yñjê…èqªÇ¿ \éLúâ#¶íËó BQã Ö­\L°ás“+¦à´¬`uëÔ§QƒÐ\IN§‹9·€œQBóbKK`ÇÁC” À•Ã#Ú©š©ÉÉ‹ptÕ$ºŒ]ƪ]gyeBU ${:ÝRhUžÖ¾ óó_¯Î‚·VòÖÜŸ(’{ÜÅ• ¼vay_IŠc+Zµl–c*+³ ] hn}}kz)žhØð&W¾ {>ŸNû›í­¡ÅÈÏYWö3º¾6—iCÛ±eÌJþïõ¦¹c£ÜÂ6²ÇX‹¸Ü!kA°âÊÿ ö1<‹J›ßO͉Kˆ!ßïz2®ýD•"-ð4•}˜§ü4ÈæVAî7îÉÔIÊ»™mIÏÖ¨S¿>õë×§ÞcõéÒo*³?Ø‚YQ¼O†+7DçXxwÅ/Oâ³½À´‹7¾³gÿWÙ7ñ‹»æðÞw1Þ÷º7ÿ+çö{<$¥LyÒ+4ì˚ϗðá‡2wÉ:†µÎÅC­Ë;ˆ¸-¿Ò«Å®Þ8ËÔ Ë>7M"Š¡ÎÉu›»ÝŽÅ|ƒË1w`w|¶'Tå"H¯âç_¶súÂÖ}þ6§ŽìãôÅ«žp¦æ¸²ÄÀ¯‘ÓY`éNÅøû’vå<çc¼ŽÓ˜×²ûÐïÄœÙJ‹á À¼–M»Ïáp~íÂò6•¯Í€PËǵgₜ{‘´B< …ÖÕ¥°gî N&90W¥sžàS“Þ“ÿöŸ¢Jå¾Ü§)Ô6ìÉÙpÃA1½6—g!ËÑUïJæd’SÙštԱ赖|½í8—~ßǻϽ’mÓ•ÛsáÂ…‚_gñpx–¼·c×gúæbç×£ ä›´¯_*Ó..3©ÁÃ4}q) îç…já|´bf§‚Ûr‰zŒaø¼™Tñ—ðE‚ Ü%2ï{›6mbРA 2„W_}•#F0|øpÖ®][¤X'¹îJuÚ¿ÈŒ×< îúŽûˆU«W±ô«ÅLì]‹ý f2rhVþrž¿³‰nËìg™´ëëÆŽgUT\Ž ÙÙ±x&3öx¶ÇŒhõ(Qú3vó·¼ÜÈŸŸ¿˜Bïýñ³œi]«¢Ò–.0 44ôï÷)EÒ¾èÙ¡-ÞÍàÇ3(kÈ7KÆ=GxXk·Å1ô >P¿R5j`ÆÐvLYØÓ{Ø•#Ãã;ùx~4uæoe41ÿ—X0ú=6ï=Àª¹ãÙpÃÁ²×[²æ@Ž3-¬[ùóšµoÓþoµôj& hGã¶‹¨øJßÜÞ½¾à—VëYK3vŸôZG½Šåعoîo˶‡zŸârau)ÄJEmôL~8®W(Gùê¯ò𼟘رšÜA¸K"#û>üôÓO’+Ùd2Ñ®]»"Å:Q)9äÈš5k¸µ”qó62nî×Ô-cíƒû‘ÓF±êŒ•>oJ§Z%n™yãÆïR]جvÜF½ö6Ò õÆ Üh0š¼dêÅM<Òt_ï:Mó0=—?£>w;­¤;òþýN±Y­hF4x\àtèµ…wâ¼Æê·ŸÅÒéÿx¾N0‹ ÖÄý4ìŸÌ¹ý}=ó÷Šsš_“/\¸Ðäù][Çõ"å­8­¤¤ÙÐ|ó´…ÓnÅ­ö)´«™t› ¿ï‚׿gü…×UqÚI³Ú0ýò”ë̆W™ž4”khE+C ‹ú4¡ÒŒƒ<îãµ—4«_“ {ì6*7À’§i]%à¶íÄøy=:v+|0êUÞzøšn³ü‚ …pùòeŠS¶L´:ÏöÖ°páB222P«Õ 4ˆ¦M›¢×ëQ«Õw¶½Õåºiö\]œ¶#=‡­øl?ÿld £1_!QxøxÓ@’½ðÓ€ZoÌWL¨´Æ»&2 ™½'oý-E€9ncVÄS>4ƒÑDPp0!ÁA¸Òþ¢F›0ïîTzL&ßÌü5yü®]Ô¼UZ#ù¶…Vo¼e=tFwGd¡®*­“É”§\ñG¿á™ÉáÌêY£PÛ(ŠÐÙþI{޵ú’fá>¹ìÅ”9àÛmž©6V{Gv’ŸÈÈjo£^•«ž&‚ ÜeÜn7Š;·xüñÇ©Zµ*=ôõêÕóz3”[ÌsÜÖ„®Þ¿ÍŠi #sÆÚ€öŽîÝÀ¼5›¹påú}[Öb!átÔ1 yuÂÂÂèü\%¾Á哚ÿ­æ?™÷ýHP¥6œ=8Š0ß¿)xTëõ=óÖË·RbØðÍ»ìÞw’t9­S„ü¦Dz÷î @·nÝÐh4ÞϨ(ü¾zgÛ[Õ>èБÈaNÂÚ‘ÈÈ®8VâR /t_¬Suæ;Éè3h¶ 7Q¾\¡†û:ïûSðÝêЇæ"9>Žðg?%²½ »Õʵ4'Åur×áÁD,ÎСC©P¡*•ÊãùP”B…Þ™ÐpgàÊ:ùÃ\‘f-*>8ªRëG¥šµ©ô€åý¿‰†ˆÚM‰†á¿Æµ‘Cs( Õ«WGQ”l‘¡( P¨Ø¸­©KâE~Iw\ëQŠËჂ ‚ð_ÇÍ"" §Ó™Gd(d¾w{þÍ=Mn ¢8X7õSô¬‡8ƒAá¿›= Š[Áb±x†ËåÂåv¡vªAã'·!4<[æ.Å^¥Né0lé)\þã«>ø7'ín^õ Â|¥'Aá¿—Ë凇ÃÅbñnmU©2£¹:]¨UjWÃåÆåÊÿìâ\çh¼Ù·3¿‰Îû)]z¾Ð˜õë\ô9“¢œ£á´[±Ú4Z:t*6«Ã]ÜZúOaNäšÅ‡2%ýÿ9Õé´’|-ƒ Ð û~—ˆÃšL|’“²åJ¢¹Gí%‚ Üš³gÏâp8 $##§Ó‰J¥Â`0 Óé¼!â³þ_£Ñàr¹°Ùl.4îvôÖ»w`— ‚ "AA‚ ‚ ˆÐAA¡!‚ ‚ AADh‚ ‚ ˆÐAA„† ‚ "4AADh‚ ‚ BCA‚ ‚ "4AA¡!‚ ‚ AA„ÛB+M ‚ B—.]B¯×c00  z½N‡V«E£Ñ R©P©T¸\.œN'N§“ÔÔÔ<ù‰GCA„ÿ"4AA¡!‚ ‚ AA‚ ‚ ˆÐAA„† ‚ ‚ AADh‚ ‚ BCAA„† ‚ "4AA¡!‚ ‚ BCA‚ ‚ ˆÐAA¡!‚ ‚ AAþËÑæ|Ó£G;ÎhÍš5Òš‚ ‚ äB<‚ ‚ ˆÐAA„† ‚ ‚ AAþóü?!ED¿tÒ­óIEND®B`‚rabbitmq-server-3.2.4/plugins-src/webmachine-wrapper/webmachine-git/www/images/basho-landscape.gif0000644000000000000000000000517712305126066032053 0ustar rootrootGIF89aÜNçÿÿÿ¶³´¬©ª£ ¡À½¾¢ ¡™—˜àÞßÕÓÔÔÒÓÉÇÈÈÆÇ¿½¾µ³´¬ª««©ª™–˜¶³µµ²´¬©«£ ¢¢Ÿ¡š—™ywyxvx™—™Žˆ†ˆ‡…‡€~€€€xvy‡…ˆxwyqpr‘އ†ˆ€~€qpsiilhhkqqsppriikbcfhikbcebdfaceííìø—ù˜ø—ø˜ê’&é’&ê“'ߎ.ߎ/Þ.ÞŽ/ûµcýÈŠÞ/Õ‹5ÔŠ5ˇ;ʆ;ʇ;ˇ<„Aû´cüµdûµdì®hýljþÈŠýÇŠí½†î¾‡í½‡ë¼†ê»†èº†æ¹…áµƒáµ„à´„Ú°‚×®‚Ö­Ö®‚Ï©€Âƒ@¹€F¹F¹G°}K¯}K¦zOӫѪ˥~̦Ë¥˦Ä¡~Ÿ} }¾|ihgîíì¦yN§zO¦yOwS”tV”tW‹qZ¸™{³•y®’x®“y‚n\¥w¤ŒvŒqZƒn\ƒn]‚m\¥Œv¥Œwœ†t›†t“r’rŠ|p{k_’€rzk_Š{p‰{pyqkjfcumvn€umsibyqlzqlqlirmjjfdjecrljiggàÞÞÕÓÓÉÇÇÀ¾¾¿½½îíííììàßßßÞÞÔÓÓÈÇÇÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ!ùÿ,ÜNþÿ H° Áƒ*\Ȱ¡Ã‡#JœH±¢Å‹3jÜȱ£Ç CŠI²¤É“(Sª\ɲ¥Ë—0cÊœ‰ 0`ÐÜÉ“&Œ›8qÒø)CFÏ£HOæ¼i³èP›:“JÊñfNL‹ÅJµ«×‰W‰.Ízó«Ù³ Ÿ†ejs¨Q´pãZu V¡ £ÆÝ+s¨]œ9a`"$Š]ƒK†ú“¯c•?çÊÀ! áÊ4- ¸-[ÏCäì9GËP,äŒÕmàÖDÛ¶M»£[­4Lã°,DàëÄAí¾ö¬¶qíã¡>„£yŽÞÿ–½Kׯò§Åõ"ßþkl<6LþçðM¸uál½sþ›™»{†nýÊ/ðîϱ­I{F9½ö÷tÛP¦ ŸS‹­‡ Vcà ƒE(¡€Œµ—Ÿ_‰AEl@Ѱ€ƒ jØ^^ñÙ Z³¡¥qMµV!v­(£zoÁ'Ÿqïõ™ŠamX—U‘I×¢Œ2.æ]M• ‹Pñ[|‘ Un€@¤ƒ)õ_M)ùžr;šu’BiU‘AµµØ•v¸¥AÖ= w²¥\šc Åf²!YÁž ùfA± w"vC™Eæ…wú Ž:UcB¸]uâ]m™EkŒÉ€‚£ bj H.X‡b:(R›a þ£Æ â_“”'ŽîÍ€›‰^ù×ç}²ÊZ[ ]‡ÓœˆŽHU’-"HC°Á®—ÖX¸þã^iyFAædcµÞ—iE‚…‘¤÷½ +´±Ò•q5©¦”qz-¯Ö’‰ïAú!ÙdMט!q«Ô§«ÞU¦¸ë±+[ õ—iS÷Á¦fÁ1¨ïSœè]˜ÿ*徚]œ™–è¶Úеt¶héDuF¨ƒºÙ»âÆ,/‹$#ÄSæ¹h-Á5Iìb™‰f<¯ÅPΛtB CIíR¡çZºëÖ h‡ïžêZ~G'»P”Rbª_…âÚŠŸbj­4ŠVGp­U'îÏŸõlêþ[ •€Ö{Êh ١‹ «ÅqÄ3i²ãzûˆé½Ê([Ø.¿¨wtyö¹©¿†v:6ÎæM|…s‰;s|ª™ƒf.ßǧ :&œðBŽ-¡m#žfV>tÎ<ÇÙ™·͵.cY›î ®·:ÁÂmÝ]ü–Ý"¿W‘–bÉòþ´€àjgº T±¾o)Võ>"Ç·ŠÓƒæRš¬—ü!…®áœÒt4İ¥Zõ¡”–”ƒF|w›ÅvW¬¥Èè6õ T$…0é> ɇgÌ`l@‹’AèBˆXåZP›Ý¾`ã/øøË*GúËŒ,X?ù´‰+þ[üp·eµíe¦Z̸êö¾¦ˆŽc›³œ¿&…¾¡PbCTZóàš¡Î~‚Kòô—§#!ŽGÌ"ÓG(%š/„‹¢åÈD%z‘Y‘h+ˆˆH9yPè(%9ò®R%³ÝC^ø=õ].ITlè–±©On‹<WC"•îJ&ˆ’ºn²‚=9@=´Ž ™¥,»Q²`‚ß Ÿ”¨MR…:V}t´-]'yÒÙ#›"€´Mé)pÄ*!²˜Îq{y|Q 1T¢ÍQK€¸{¡Àî„M¨Ýp“ šö4%ÚmO¤(Cì3¾oÕ2œ¾[$ñÞ•¬B†ŒšIþ¤c}dHð±ÑF] Ö„#œ0²)H+34)íaÌŸrÚ[‹te¤6¶moìÑ 5AG ½’KOa—:({®“Eò”Žvb Î9Ò‹DÄ‹è@^ôQ¡o¥£ !ZeMñIâ:Ç Mj?ÝôÙuˆ:SµSy‘ÔÌtö…žzózL]MÃ~0˜’ª©T—H!­l}ºÌ$Rɧ¸ >ÉŸÒY™”þR/ ýE.l»v Í3•E¬+µüúO[)Έ±|h9êÂB:O,:µÑgz²áD6_s1ä7—¨´¢°nfÃX #«×¨ÖgrV}Èp Ê®Ì5«6Eþ ï‰ÒJìl…$Sîù¿KÎëmÁX†ªE½AB”béÖ'eUŠ2=0"@3ænÿ±@£¶S«¤¹›Nz'"+‚¯†– í W¸4a3eÇÂ-ê¥”Žº^#!¢ª£]hûQ§ÏvEÐ8Ql¸×õ6ÕK2–¢ðjÓ‘³f©8ÓViŠ“\ÙÄšµŠ–×ê`…í\¤N–´glÛŠ|8±²0r¾ 1„Ö‘Íëg2£Zrœü œ+~ñŠ7TQÍLÑ ÷ªT}0w!~ãG¦x°)Âvš/ÄìÅVìàC^ sÛÅeg:·ÿ^Ö7b«°«¦ÅË{Éx$0z_cGUªèH*+§ªÙÔ3ÆË€¿C,/ʸW+lå£ðq —­Ú]º™M*dtäÝ 9úÑŽ´¤'MéJ[úҘδ¦7ÍéN{úÓ µ¨GMêR›úÔ¨NµªWÍêV»úÕ ;rabbitmq-server-3.2.4/plugins-src/webmachine-wrapper/webmachine-git/www/images/chash.gif0000644000000000000000000002453512305126066030114 0ustar rootrootGIF89aääö  %" $) 1###""-,,,%%2,,7/.:33333;<<< H D S<desÿc,ddscmBmmodÔ(cprtü$XYZ `5Ä*XYZ o‘³còXYZ 'Dó³ XYZ óRÏsf32 BÞÿÿó&’ý‘ÿÿû¢ÿÿý£ÜÀlcurvÍcurvÍcurvÍvcgt) ºvPEa”ÿÝ A º 9 ÁWèvþyæJ›ä6Zy ˜!¸"Ù#ÿ%"&F'j()»*å,-C.r/¥0Û23I4…5Ä78E9ƒ:¿;ë=>:?Z@{A BÅCæE F.GQHqI’J¶KØLûNO:PYQ}RœS»TÚUúWXDYoZ¢[Ô]^4_d`‘aÁbòd"eUfgÄhýj;kl¾noOpqîsCt•uðw@xbylzr{y|ƒ}†~‹Š€Œ‡‚}ƒx„h…U†B‡)ˆ ˆì‰ÇŠ¡‹uŒJ玳€V‘-’’Û“²”ˆ•^–2——ÿݘ³™‰ša›8œœçÁžœŸx U¡4¢¢õ£Õ¤¸¥Œ¦V§#§ò¨À©ª\«+«ø¬Ç­˜®h¯:° °Ú±¬²}³N´ ´òµÅ¶”·c¸3¹¹Ðº»M¼¼Ä½‚¾@¾ÿ¿¾À|Á=ÂÂÂÃ…ÄLÅÅÛÆ¥ÇqÈ=É ÉÛÊ­Ë€ÌSÍ%ÍôξψÐQÑÑâÒ®ÓwÔ?Õ ÕÕÖ ×lØ9ÙÙÕÚ¤ÛtÜDÝÝéÞºßàcá6â âêãÂä•åeæ1æûçÉè”écê6ë ëèìÑíÆîÆïØðÿòBó™õ ö¤ø\úFüeþ’ÿÿAäqÓ·°Çÿ÷= •  u ô}‚þnÏ*x·æ(H d!"¡#Å$ä&'((F)o*“+¸,ã./70d1Ž2¾3ð5$6S7Š8¼9ë;<=5>H?X@nAƒB–CªD½EÏFáGòIJK)L:MINWOjPwQ„R’S¡T±UÆVâXY#ZC[a\]Ÿ^¾_ß`ÿb!cJdoe—fÃgôi"jUklÆnoCp~qÄrütuvw#x'y(z({'|&}"~€ €üî‚ރ̈́¸…Ÿ†Š‡mˆS‰6ŠŠ÷‹ÓŒ«…Ž[3 æ‘À’š“ÿr”P•-– –ì—̘®™šu›[œC+žŸŸî Ú¡Æ¢¢£m¤=¥¥ã¦µ§Œ¨`©5ª ªå«¾¬š­r®K¯%¯ÿ°Ù±°²Š³c´8µ µà¶´·ˆ¸^¹3ººØ»¬¼½S¾%¾÷¿ÊÀÁnÂ@ÃÃçĹůaÇ5È ÈßɵÊËdÌ?Í$ÎÏÏòÐÝÑÈҴӜԃÕjÖR×9ØÙÙïÚØÛÂܯݛދß}àoáeâ[ãRäKåFæDçAè?éCêJëRì\íjîzïð¨ñÀòÚó÷õö<÷_øƒù«úÒû÷ýþ?ÿAÿÿ^Ã6®>äÿšc>*  " $ , +$ûÚ®v8ùµr0ï¯n.ð³v;Ì–a / û!Ì"Ÿ#r$E%%ó&Á'„(>(ú)´*n+++è,¦-f.&.ç/¨0j111õ2º3€4F5 5Ô6›7a8(8ð9¸:;F<<Ú=¤>n?7@@ÌA—BcC0DDÎEFoGDHHèI½J”KkLDMMôNÉO•P\Q#QìR¶S‚TQUUðVÂW–XoYFZ!Zÿ[ß\À]¡^ƒ_i`La5bccèdÊe¨f†gah@iiÿjàkÿÁl¡m†nkoOp7qrrîs×tÂu¬v˜w„xqy_zI{1||Ä}ƒ~EÀ€8ò‚¬ƒg„"„Ý…˜†S‡‡ÍˆŒ‰JŠ ŠÎ‹ŒRÜŽ¡ZË‘„’A““Á”„•I––ß—®˜™Yš3››ðœÔºž£Ÿ }¡o¢a£N¤2¥¥ê¦Å§¡¨~©_ª?« ¬¬é­Î®³¯ž°‡±p²[³E´0µ¶¶ð·Ü¸Å¹®ºž»À¼ä¾¿À3ÁSÂyèÄâÆ*ÇÈìÊpÌͿϤѴÓ÷ÖyÙZÜžà“åNë¤õJÿÿndin6ÿ™VÈU‘°'‘`P T9 =úá&f,E_x‘«Åßù0Lj‡¦Æç .T|§Ó5j¥ä$g¬ó;…Ïjº ]°[°  a º  q Í * ‡ æ G ¦ l ÕDµ&œ‹ýzú{ÿ… ‘¥2ÂSâv ¢:Ólœ1Ç`ú —!4!Ô"t##¶$Z$ý%ÿ&B&ç'‹(.(Ï)u**»+^,,¢-D-æ.‹/,/Î0z1D22ù3×4³5˜6{7g8Q9C:=;3<6=?>J?`@{A¢BÌDE9F~GÈIJQKLÔNObP­QþSOT¡U÷WJX£Yý[U\­^__`·bcldÃf7gÁiBjÈlSmÚoipør…tu¥w455é6Ñ7¾8«9 :˜;<‘=“>›?¥@µAÎBäDE$FLGwH¦IãKLbM£NæP+QqR½TUJV‘WÚY"Zn[´\ü^D_Œ`Óbced¬fg™ijlmŒopŽr sŒu vxy›{#|´~@Ópƒ„²†U‡÷‰ ‹OŒüŽ­`’“Ñ•Œ—N™ šÌœ“žV ¡ä£¬¥t§:©ªÂ¬c®¯§±R³´¯¶i¸%¹á»Ÿ½d¿$ÀèªÄnÆ+ÇïɨËcÍÎÒЋÒ@Ó÷ÿÕ¦×WÙ Ú¹Ü`Þß­áOâíäŠæ ç²éJêßìpíûïˆñò¥ô0õ¸÷GøÖúdûýýŽÿÿDj‘¸ß2^‹¼î$^žâ,Ü>¦ójã_Þ`á g î y  ¯ C á’Eþ¸t3ô·~C بzL%ÿÛºŸ‚h Q!>"-#$%%ø&ñ'é(ß)Ý*×+Ô,Ñ-Ï.Ò/Ó0ä23'4H5k6‹7¯8Î9ò;i?…@¢AÂBÝCþEF=G`Hÿ…I¸JíL)MaNšOÕQRQSŒTÉV WDX…YÆ[\I]Œ^Ð`aZb cîeBfÑhrjk¼mfopÙr”tRvwÙyœ{\}"~Þ€¡‚d„$…æ‡Ç‰°‹›{X‘0“”Ζ•˜Vš›ºgŸ ²¢R£ï¥ˆ§¨´ªY¬­Þ¯¨±t³=µ¶É¸ºP¼½Ø¿”ÁWÃÄÚÆžÈeÊ(ËôͻϋÑ^Ó"Ô”Ö ×‰ÙÚžÜ$Ý£ßà‹áñãLäåãçè@ébê{ëƒì…írî]ï7ðð×ñŸòWóó»ôXôöõ‹öö£÷(÷œøøƒøñùRù´úÿúxúÊûû\û¥ûîü7üvü¦üÕýý4ýdý“ýÃýóþ"þOþzþ¥þÐþûÿ'ÿRÿ}ÿ¨ÿÔÿÿdesc Color LCDmluc nbNOèptPTúsvSEfiFI daDK0zhCN LfrFRÿXjaJPnenUS|plPLŽptBR esES¸zhTWÊruRU$ØkoKR üdeDEnlNLitIT.Farge-LCDLCD a CoresFärg-LCDVäri-LCDLCD-farveskærm_i‚r LCDLCD ÿcouleur0«0é0ü LCDColor LCDKolor LCDLCD ColoridoLCD color_i‚rm²fv˜oy:Vh&25B=>9 -48A?;59Îì·ì LCDFarb-LCDKleuren-LCDLCD colorimmodœgÁ´Å1textCopyright Apple, Inc., 2009,ääþ€}‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊÊ)|ËÏËÎÐÔÆÒÕØÃ×ÙܾÛÝà¹ßáä´ãåè¯zéíêÓîñ©çòõ¢ôŽ|ú}ûöþˆøé¨oÏÀ Ø“_A96X°¨!‡ ¼„ò>¨Ç‰D YÀѳï"Æv q„²eË‘$MžD—²>=yj¸tY#OÌ™ñj rÆ';[²Àãó Pn%`G”ŸUBEóใ4© wòäé÷TQ‹ ‹öìM=þxðÔ¡áU:L–æÖâž=z Ö#ÏàÃoÚ™“¦n¼M÷ s{8Ïœ/)H|ð`A@A‚H¤3‡©Ö:uΘ1’É™:všÊ”lË"ÉÀs¸À„(¾Œ13²4>¯ç˜ãÅ`±zº .$º²·áݼc¹ý‹óL ðrÏ"¡}ðœñB" ªq! `Œq¹é•ž,D‘]| %ˆ‘$ø’‡$`g \(ÇœLUµ +Ó8ÃN_€ c°3I†ˆè1†„¤Àd ž¨ÊM€å1†ÿ}!c%4*þ¢Ç¼øEnyt•¥¨XNZ$`f’$#ypaAZö—‰T†RP`w €@stò¥#s|€À væTš›Å^%@ŸÌùˆ$ PBE¥ cpSfdrV`uŒ ]Šž&y  €yÆôi$0v3g`Â{x¤€ §zY«¥n¦àS”€ B8“V: A8„’b(%w\7†nd¡ B9« »?AÖBÖ*{+'c$¢鈯éLÚj>å!k3¨,k Z  k¹0m;«®+ŸzÔöÍó­'yX€A©{&ÂÈ,#Wþnh/+òf"«…¦.‚n=#ò&°Ú ƒrF&ˆ­M!üêO¿*½5‡¹JÆšèás@kˆ¯)wòP°ð¼ <ÛèU‹P48ÕrS^ gÓW‡²ªB÷B@e]q½vÈâ4'v  Å®ú|œvÔÐåaÇò6'x@`‚az|`uØåœ5"H 3صè!Á €ð8F7™!ÀiˆßÓ¹(|‚n']ŠÇtëöçj¢^á/Ës©V"$@³9¬ƒB´$ä»; Še‚Îܾ:-U%ÁàzHið¹›À‘GCΠÝ}èA™Q::”CþSV³u] з Æ¿3‹á†à@f2ÔZá/³õ´mˆº± ¬ö„ˆ›w&À˜¡(@ÌÐ0³lMq_;Dú0–;M¤FýË`NP€)XÁ S(@:f¿¬ØALàÉ\ñ·y®V\‰\3\! 8ÌÂ#£Ap)AÄ1Aƒ½‚}ð@ îp‡¸P` 9Ìá(P¶c\ ø»"ŠxŠ €JB€pS‡X!Š8´Â|WAXÀŠ‹‰€£·ZÆE(Ž9s0#³`…@éwÁ( ì€HBŽž[Eò$‘ ˜Á €"§0È8/[à 0þ@ D‚‹ù’Ù$0P‚1¤ 7ÌỀ›îµERÜù"Á?Tø/D«Dà1„aFp‘¤[»ƒ i OÊé•ù@¢%ù…/  (€R` V6š©È ¼€L8s d„4/‘€xáïü‚ºÉÆÉÜD.ˆ”9W8Ç*Õ‘á‚g5 ´#Ø#+w88qNL¤3ëÌ„D0Ðyš¡˜L18MqÅ9 Y›h¨%ª’Zè‚,z†æ4‘tÀ¸ç@€‚Oˆ”·T“I/ŒÁ@-ÅÍKMµQ5‰SsEE??€QT-{À.Úþœ:°¡,x â ÑúáâAˆª©Ø–úLQDÔ'UéЄ®„d$ñ*ò^¥v 7ÅPRù±SP @ -UC]FÒÀZÜÓ% A)òê’öᬠ  ˜C¯ôdj¸(H]ÒQ0–ådAÒå¸u'KqefÁz‚!šâ³ŠÈé&úꉔò´.‹™r¡ºÚ.°8E+ÊSLJ 2¨ HÓ¹âÄ^°À*‚k/>u@AS‡&ò š• R¨ êB¶.,n*¸€/µ¶ñæ^/AW<صæD Gk Âp¡ >hÁ Và‚!”'A€lEoå¢þNº"¿MumI .X¸ ^g7ÃrLÃBG.ø,Ìû6þ¢â Àp†5<¢¼Èyp±ÃÖ ê¢7Ä•…WÌÒ9ó’êy\ê׎˜¬z­Äue‘ ÕÉX–h¹ˆªxÉhWgÁ¹|·`¬†õÂ[@€ ;‚Ò7ç«ä=¼Æ%ÀE^o¼ˆ5ç¢%h)sBhJ tC.nÊh‡€Í¸Šé2s1H±AÀ]m!Ò$åX»$õœ{c”:|¡œ»hèžó1aX$à ­œµ‡ó@eþ€Zçì´M¸Ì ˜ »Ýã-™Aà_8SÙZc6/Zäãæ:W.7ó/<)”Wû 8s+=¯×¬l–¹Fó °íh`¸ï6%b÷°jm-ÿBŽ)©w0R×Ê»¡tðž…Ç]‚¼#¾Ðí'u˜C‘‰ÁEFCüØÁø@ *Î[fs X‡QÄ܈V÷yzóáØ|@ÄŘà9ÌMŒ/|ÀÇfÒw$ \™ãKõ7_A> Qßæßœ«¡årG"Ãxßx92ÐmhY=Ï­ƒ€–ŒÛ9\àǘƒºÎaƒÿÈÐwê  šùOëɨ˜·‡þ“®‹1CàsV='âËÀ·Z3sç!ðª~ƪ°m'#”ª¸Ð7¢•¸Á±øÀ‡¨ÁÎÁ»úêWÏúÖ»þõ°½ìgOûÚÛþö¸Ï½îs_¥!KôŠDâÄ >` @ÿ®‚³’q¥­ú‡¼CY~iyäsó8ìÂEx¾\ÐÓ—…â­ï²‹£ÜXtG†Ö·~XØ!ôT>Š˜?‡1ÝŠˆïÃ7Úÿ` ¿åcàæeª3Ú¦tüÇ cg}ç}Cf^vtrJ× ¨ ˜|Øh¨&€s|‘ó&xbÐbò§H‚´Cb%‚#(AòþÖ ÆÆ€láxgFö hw^q4ƒ»ð&0"‘ƒÒ¡ S–çƒ?H|¾°=]— ½w±ñ¸ xwWH%8 0UtÐvÎõxb'æÃƒ0hØf^coX§wƒµ@…g à„™•†jØ]ø cXÐfq§ænc€ ¨ =ˆ[h}Ø ^`tø–‚ c Y¼…±õ¸ ’EOQBs˜%X¨‡Š˜2«A¹@&ÿ·[´–g_°¼EŠŠ ›x ˜7UòµˆT‹_–‡L·‹Ø„¹ _ÆwÑv µV‡"0ŒàE‹‰PŒÆx $€Øv¼Èþ„˜¸†<Ò8”A·Ü¤Œz±5cÛ‹f†"J„Ss‹‘@"f]¥Ž*ñ\ÒVFgᘉ•@`÷xU±Uåw½GlÒÁ! ¥)•@ŽLFQ²§Å\å=óWsÛÇ4ö ˜( kHD@x þ¥ápŤPsõ‡b‡¨Hñx Ôèé (–ac\–å†"ü‹%à`ð˜h˜“tÒ†®ð!½4¸¥E’bвh“Ðh’›°“ª°K\ÐKb0• ñÆ$ˆóç{cÀ$ä… ¡Ó•^ù•) b"ó”Iqejªpr÷% ?rþ“šÀ”pŠ« %a+5Üå;`GleØ5¨“ 'i‹uÙ «‚—c°RHP’æmkIum;:¤ä ˆ `I ]P ?šAà+ÀÖM òŽácb÷PÓYj’™‘𚜉‡ŸprÃb´RÕô`ðføfš*英іȩd­ÉT¡›‘å*µ+µRËÑ’9fZ°• :JÉT󥘢°KZ OT5g Óažs tv•f è‚óù  œ“ žœ°I*uQ°‘qþùŸp6i…E”CÖŽ¢’T%Ù ú Né „‘ÊTvpv`þZ¡ª5#œ]+×'† #J¢—© (°%oÖ̃ÄDÌ% Y ÍH)ðQœ@Ÿ¥°£<Ú w (šy¡A®¡Ab6 `õ^Hé* ê…§ÀÊžt‡AT H†uøY"–V¦fz ç ᲟžHT±~yjµ6“]й¥§°™!U¢J&²#t3%ý £ãpAu5CÌt§õi ŒJ—= )€B)jIa©Ùç{`p0\Ж\`ò‰cx¥Ó娑°Kª "€qLS[€ ZÀÃ’«ºº Ú8" “þ 5”J8´C(ÊHx£Ù­Ñ*­¼Ú( ZÐK¤&‰™=O´GS_à\pÀœG®QªŽÓŠ3†F¡AHü`z„F}TM] ‰œZïåÊ ÿZz€ rªÚhO™š°QÔGbP¯\C1;±{®‡à°®Aê]_ç âT IQ4¯¡ öšÛ#'‹²);ª„Àæ8°×)%ÂÚ&T]ܪCÀM¡)²¶*´Šú Rê ÿêQ&`­²†­ßæ¢g0ÀôAS0!ðSú ›(é‡? ª³¡v (.K„rȱrjJ °M,õþHmÙ°!p†û©XK ±é>"p·l:”1ÕŒ:,öŸþ9õÚ¬Ó3q»¨IÛ;© àZ"K:Ÿ»W”qÛ—ž`f¡˜;² úйž[ äÈPH]pª×¶´&œª¶pFF¯H«¥:0ˆÛ?·0| )€—(¹$N‹q¹– 34H¯ˆ \ *ßH Y; gÐ;–ÀÚ—©kiÍ£.ú¢P&×½\PÏ›ºã{œþјAÊ#À›Y˜ªqÑ¢Dº+8T6b-û£Ž#¾&'€¢#×Éë«do!¿ò ù wp™ÛHƒ7 ùë Šþ—#ëÚ¤¬” 1kEÄ‚hw "к^ )àù# ) 7°Lw 54% óC?H“0ƒ²ÌZd ´©ÄšàQ"ç²r`Ç”Á>bLzp$ bÛ–;+ °`ŘŸÜ1–SõtBÂ*` —¤T_b»©)P£ ±yê yà P)°‘ŠQ>a*‹PšIiì½)ð£Ù ¯ 8Ù½ü‰QåR±ÝpµØvIœZ€…+®·Ë n(°®Ü]°C Œ ¢<ÊÂ)´ÊÃ%Ð}¢Ç½j’ZлëéM=RËJL®“Àí¸Ã•Ü$þ𲨫Ф€Æì“;»r̬ z€ ú<ín²á½;pƒ ÖŒ JC!ÚŒ¾TÕ¢B9¨álEK,î{¹!Û°•¼-`œ˜l x€@SÛÜÉ@e†ÏÅ`ËûpBæ¾Ç+²•lM‚‚Œ“U"*äœÛLP.ÅF·ÑÂ@2ÃZ1è¬Æ\°•L°)Ï· Â|z#“£Í¥•Aƒö( ÈB¶¬š^°0Æ6Óƒž pš29& Í'€—epä2ýl.[/å°1 ²1š;Ñ¡Ú]>Ú'ðåˆöåi.né¯=ÚBéRMêyQAe¡ÿI°SPR°0½ú- €©ËL/DÀRÚ»è-™>ðN®àº^Ƀ-Ûž~á"½ì¡ìñädþ¤> ¸Ñ¢ªË>7P&°Å0ë}v­;ÕI¡-Zîu ^!` O!Þ^paãÝìZ .ì¢b>OæÙRUµ½ ÍS«áÜ^°PnÑã¢nàéùHBJ¤.êݨu›Ó ¡)à” +F¹!«žÄk¹Ue[*bÎ*ÕYåþ+WÚm½±ñH¯¢L1Àuñ¹Uå-uóWîò·ÉCoç²aåMògR1dx¹Oîê[ð6±5-Êè¿]YI!Å ¿: þ9ÀïZ¯õ/Ú¢LÜ(‚ªYGo奾±Lßô,öd=ÜÛë;\½½qÁþD,Zî. ïKí{?ô1ßÁ÷LM÷¾U5T€Î'`=Hï"O†fàè.ò¬Œ@¤¼ù»R@†OÑãC¤,÷Úöah¢ïÁí˽Û7á¡1 6Þ€ú¦ü¦qö”ê0kòúåâíÈ”ƒQôÝÇí.êä^ømAS1ýnñ=+ÍÍó«ßöXÑù8³º<ÕiQû)Uã)‚ý–býÈoEßSú!SÇK¼%uŒpÓXA5óïýI€PW7wVx6'ˆ—§Çר÷ù Yiy‰ùÈ'¹™éù *:JZjÊɧ—‡g'èZg§ÈØùIyz‹›«»ËÛËÙÇ·§ŠGlgw§¸8jëëü -ÙØ¨§š—-»çHëÙ<.>NZ-|>ëÈ\îþ¾YM_] Ÿ¯¿_Ú9l ¿ Ô„K Á… ~s1¢Ä> 'Z¼èŽ Æ;zü2¤È‘$Kš<‰2¥Ê•,[º| 3¦Ì™4kÚ¼‰ÓR ;rabbitmq-server-3.2.4/plugins-src/webmachine-wrapper/webmachine-git/www/images/halfblankbox.gif0000644000000000000000000000202512305126066031447 0ustar rootrootGIF87aódç·  !!!"""###$$$%%%&&&'''((()))+++,,,---...///111222333444666888999:::;;;<<<===???CCCDDDGGGHHHIIIJJJKKKMMMOOOPPPRRRSSSTTTUUUYYYZZZ\\\]]]^^^___```aaabbbcccdddeeefffhhhlllmmmpppqqquuuvvvxxxyyyzzz}}}‚‚‚ƒƒƒ„„„………‡‡‡ˆˆˆ‰‰‰‹‹‹ŒŒŒŽŽŽ“““”””•••–––———™™™ššš›››œœœžžžŸŸŸ   ¡¡¡¢¢¢£££¤¤¤¥¥¥§§§¨¨¨©©©ªªª«««¬¬¬­­­®®®¯¯¯°°°±±±²²²³³³´´´µµµ¶¶¶···¹¹¹ººº»»»¼¼¼½½½¿¿¿ÀÀÀÁÁÁÂÂÂÃÃÃÄÄÄÆÆÆÇÇÇÈÈÈÉÉÉÊÊÊËËËÌÌÌÍÍÍÎÎÎÏÏÏÐÐÐÑÑÑÒÒÒÓÓÓÔÔÔÕÕÕÖÖÖ×××ÙÙÙÚÚÚÛÛÛÜÜÜßßßáááãããäääåååæææçççéééëëëìììíííïïïóóóôôôõõõöööùùùúúúûûûÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ,ódúo H° Áƒ*\Ȱ¡Ã‡#JœH±¢Å‹3jÜȱ£Ç CŠI²¤É“(Sª\ɲ¥Ë—0cÊœI³¦Í›8sêÜɳ§ÏŸ@ƒ J´¨Ñ£H“*]Ê´©Ó§P£JJµªÕ«X³jÝʵ«×¯`ÊK¶¬Ù³hÓª]˶­Û·pãÊK·®Ý»xóêÝË·¯ß¿€ L¸°áÈ+^̸±ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹Mº´éÓ¨S«^ͺµë×°cËžM»¶íÛ¸sëÞÍ»·ïßÀƒ N¼¸ñãÈ“+_μ¹óçУKŸN½ºõëØ³kß.= ;rabbitmq-server-3.2.4/plugins-src/webmachine-wrapper/webmachine-git/www/images/more.gif0000644000000000000000000011354112305126066027764 0ustar rootrootGIF89a@Î÷     %76+# "* ('"& 3 ; 6 : , 1#####,+++-##8''%%2-,5*)844433;;;;9000/9GV PdvsI66S++l&&x((t99k11 K G H R \WA'L<desÿc,ddscmBmmodÔ(cprtü$XYZ `5Ä*XYZ o‘³còXYZ 'Dó³ XYZ óRÏsf32 BÞÿÿó&’ý‘ÿÿû¢ÿÿý£ÜÀlcurvÍcurvÍcurvÍvcgt) ºvPEa”ÿÝ A º 9 ÁWèvþyæJ›ä6Zy ˜!¸"Ù#ÿ%"&F'j()»*å,-C.r/¥0Û23I4…5Ä78E9ƒ:¿;ë=>:?Z@{A BÅCæE F.GQHqI’J¶KØLûNO:PYQ}RœS»TÚUúWXDYoZ¢[Ô]^4_d`‘aÁbòd"eUfgÄhýj;kl¾noOpqîsCt•uðw@xbylzr{y|ƒ}†~‹Š€Œ‡‚}ƒx„h…U†B‡)ˆ ˆì‰ÇŠ¡‹uŒJ玳€V‘-’’Û“²”ˆ•^–2——ÿݘ³™‰ša›8œœçÁžœŸx U¡4¢¢õ£Õ¤¸¥Œ¦V§#§ò¨À©ª\«+«ø¬Ç­˜®h¯:° °Ú±¬²}³N´ ´òµÅ¶”·c¸3¹¹Ðº»M¼¼Ä½‚¾@¾ÿ¿¾À|Á=ÂÂÂÃ…ÄLÅÅÛÆ¥ÇqÈ=É ÉÛÊ­Ë€ÌSÍ%ÍôξψÐQÑÑâÒ®ÓwÔ?Õ ÕÕÖ ×lØ9ÙÙÕÚ¤ÛtÜDÝÝéÞºßàcá6â âêãÂä•åeæ1æûçÉè”écê6ë ëèìÑíÆîÆïØðÿòBó™õ ö¤ø\úFüeþ’ÿÿAäqÓ·°Çÿ÷= •  u ô}‚þnÏ*x·æ(H d!"¡#Å$ä&'((F)o*“+¸,ã./70d1Ž2¾3ð5$6S7Š8¼9ë;<=5>H?X@nAƒB–CªD½EÏFáGòIJK)L:MINWOjPwQ„R’S¡T±UÆVâXY#ZC[a\]Ÿ^¾_ß`ÿb!cJdoe—fÃgôi"jUklÆnoCp~qÄrütuvw#x'y(z({'|&}"~€ €üî‚ރ̈́¸…Ÿ†Š‡mˆS‰6ŠŠ÷‹ÓŒ«…Ž[3 æ‘À’š“ÿr”P•-– –ì—̘®™šu›[œC+žŸŸî Ú¡Æ¢¢£m¤=¥¥ã¦µ§Œ¨`©5ª ªå«¾¬š­r®K¯%¯ÿ°Ù±°²Š³c´8µ µà¶´·ˆ¸^¹3ººØ»¬¼½S¾%¾÷¿ÊÀÁnÂ@ÃÃçĹůaÇ5È ÈßɵÊËdÌ?Í$ÎÏÏòÐÝÑÈҴӜԃÕjÖR×9ØÙÙïÚØÛÂܯݛދß}àoáeâ[ãRäKåFæDçAè?éCêJëRì\íjîzïð¨ñÀòÚó÷õö<÷_øƒù«úÒû÷ýþ?ÿAÿÿ^Ã6®>äÿšc>*  " $ , +$ûÚ®v8ùµr0ï¯n.ð³v;Ì–a / û!Ì"Ÿ#r$E%%ó&Á'„(>(ú)´*n+++è,¦-f.&.ç/¨0j111õ2º3€4F5 5Ô6›7a8(8ð9¸:;F<<Ú=¤>n?7@@ÌA—BcC0DDÎEFoGDHHèI½J”KkLDMMôNÉO•P\Q#QìR¶S‚TQUUðVÂW–XoYFZ!Zÿ[ß\À]¡^ƒ_i`La5bccèdÊe¨f†gah@iiÿjàkÿÁl¡m†nkoOp7qrrîs×tÂu¬v˜w„xqy_zI{1||Ä}ƒ~EÀ€8ò‚¬ƒg„"„Ý…˜†S‡‡ÍˆŒ‰JŠ ŠÎ‹ŒRÜŽ¡ZË‘„’A““Á”„•I––ß—®˜™Yš3››ðœÔºž£Ÿ }¡o¢a£N¤2¥¥ê¦Å§¡¨~©_ª?« ¬¬é­Î®³¯ž°‡±p²[³E´0µ¶¶ð·Ü¸Å¹®ºž»À¼ä¾¿À3ÁSÂyèÄâÆ*ÇÈìÊpÌͿϤѴÓ÷ÖyÙZÜžà“åNë¤õJÿÿndin6ÿ™VÈU‘°'‘`P T9 =úá&f,E_x‘«Åßù0Lj‡¦Æç .T|§Ó5j¥ä$g¬ó;…Ïjº ]°[°  a º  q Í * ‡ æ G ¦ l ÕDµ&œ‹ýzú{ÿ… ‘¥2ÂSâv ¢:Ólœ1Ç`ú —!4!Ô"t##¶$Z$ý%ÿ&B&ç'‹(.(Ï)u**»+^,,¢-D-æ.‹/,/Î0z1D22ù3×4³5˜6{7g8Q9C:=;3<6=?>J?`@{A¢BÌDE9F~GÈIJQKLÔNObP­QþSOT¡U÷WJX£Yý[U\­^__`·bcldÃf7gÁiBjÈlSmÚoipør…tu¥w455é6Ñ7¾8«9 :˜;<‘=“>›?¥@µAÎBäDE$FLGwH¦IãKLbM£NæP+QqR½TUJV‘WÚY"Zn[´\ü^D_Œ`Óbced¬fg™ijlmŒopŽr sŒu vxy›{#|´~@Ópƒ„²†U‡÷‰ ‹OŒüŽ­`’“Ñ•Œ—N™ šÌœ“žV ¡ä£¬¥t§:©ªÂ¬c®¯§±R³´¯¶i¸%¹á»Ÿ½d¿$ÀèªÄnÆ+ÇïɨËcÍÎÒЋÒ@Ó÷ÿÕ¦×WÙ Ú¹Ü`Þß­áOâíäŠæ ç²éJêßìpíûïˆñò¥ô0õ¸÷GøÖúdûýýŽÿÿDj‘¸ß2^‹¼î$^žâ,Ü>¦ójã_Þ`á g î y  ¯ C á’Eþ¸t3ô·~C بzL%ÿÛºŸ‚h Q!>"-#$%%ø&ñ'é(ß)Ý*×+Ô,Ñ-Ï.Ò/Ó0ä23'4H5k6‹7¯8Î9ò;i?…@¢AÂBÝCþEF=G`Hÿ…I¸JíL)MaNšOÕQRQSŒTÉV WDX…YÆ[\I]Œ^Ð`aZb cîeBfÑhrjk¼mfopÙr”tRvwÙyœ{\}"~Þ€¡‚d„$…æ‡Ç‰°‹›{X‘0“”Ζ•˜Vš›ºgŸ ²¢R£ï¥ˆ§¨´ªY¬­Þ¯¨±t³=µ¶É¸ºP¼½Ø¿”ÁWÃÄÚÆžÈeÊ(ËôͻϋÑ^Ó"Ô”Ö ×‰ÙÚžÜ$Ý£ßà‹áñãLäåãçè@ébê{ëƒì…írî]ï7ðð×ñŸòWóó»ôXôöõ‹öö£÷(÷œøøƒøñùRù´úÿúxúÊûû\û¥ûîü7üvü¦üÕýý4ýdý“ýÃýóþ"þOþzþ¥þÐþûÿ'ÿRÿ}ÿ¨ÿÔÿÿdesc Color LCDmluc nbNOèptPTúsvSEfiFI daDK0zhCN LfrFRÿXjaJPnenUS|plPLŽptBR esES¸zhTWÊruRU$ØkoKR üdeDEnlNLitIT.Farge-LCDLCD a CoresFärg-LCDVäri-LCDLCD-farveskærm_i‚r LCDLCD ÿcouleur0«0é0ü LCDColor LCDKolor LCDLCD ColoridoLCD color_i‚rm²fv˜oy:Vh&25B=>9 -48A?;59Îì·ì LCDFarb-LCDKleuren-LCDLCD colorimmodœgÁ´Å1textCopyright Apple, Inc., 2009,@Îþÿ H° Áƒ*\Ȱ¡Ã‡#JœH±¢Å‹3jÜȱ£Ç CŠI²¤É“(Sª\ɲ¥Ë—0cÊœI³¦Í›8sêÜɳ§ÏŸ@ƒ J´¨Ñ£H“*]Ê´©Ó§P£JJµ*F}V³jÕ9ÀßÖ¯`av K¶ìɱfÓªí8`ßÚ·p+¢K·®Â¹vóêÅ«·o\¾~§,¸0X†[m«¸ñVÄŽ#7…,¹2RÊ–3Ŭ¹³On=‹æéÕ çѨKz--°´¿×°Û†ݚuêÛ Wÿ› »Ÿ?ßýÐÛ÷šø¾ã¼_ã^^ÑõlãÇõ½ã† š´d_hÙò%Ù3hÙ¸þ½Ów¹?â³ ÚfΜwù}ð°%«ÂB*œ@±²Å €dÉx¡…P8¡‚}8QE2ØŒg^z­±wÛjÏí£7_81@‚[<à =AF7Ïlá„8ñ7ä%'áhžwÞ>ÙxÁÂ$l‘Mh &Ð>ÜlAÂ,x‘ y¾)§Ü‹¹¶[q@VÑ€ ^p³^C>¤*4 7Ç%¹ä•LêUa7[< B2 ÊE&Dôð"Â[tcÞneV!=Éðd”åBðx ¼ ‡Þ›y¦Uá<^4Å; ÚÐ;T4°Å<2ÚèV£ÅZ´Y©§Ñ£EU¼Óé§þeõ¶O7T àl¡jÑ>^ @…èÁª•s3Î#¥2ºZd©Dþ(Ã*§‹&+ìQZè츂´ìDþ¬ªL‹KNë”srC 󘀴ͣ ,.Ч¸IU»Ï<™bƒÒ¶aÐêF/R°YˆM^°«¿ù)6ä7ïÀC¬*”ªÄðEï@ EÄáRüSÁÒ©E¶g)ÜÑ>P઼"÷ôZ?>Ó€2.mœ‘³Ï ©rÌ)Ÿ=TˆhÎ?{^€œ4Ъ7 V<}jLþX®>´A=Éñä(Óº3 ¸{ÝRqútó@23éÜ/tƒ¶Úk³ÍMþÐÐ$wGÐ4p$Ìx£DràÜÔôwG{láª=Y.ÝØ´xGïà`È‹Ä66šßtyGÙ4ñãTí… $~Ù8uÓ:¸V§®ÛÝ@ /N£{t°ƒn‘é¤í‘¼´4\Õ^Ò3FÓ®[zJÏÐÌúÌC‚;Á®“$ÌC»äòñ‚˜Ò'4›>ô°°O½ƒTE©å›ÂI ñ \w]>A3mcOí •èA}‡E1XŒX„ Ú_m†v0¬°Oy'ч鈾) D‚î&A¶ÁãÙðIA’¼c0Ô€/@¸@_lÀ€¨#Éèñ„õ}ƒþ(1Ñ;àñÐ( Ä€˜§ó ï $`bIV˜›ëu£˜! {±yP[Mtö–®ŸP$ô4¸1ÑY€‡¥È$'Z¯AÑÞO°!‚lîƒ 4¸!ÇImôø „rư  Ðx†,àXØè<¼˜ÃÂYì (#P ’y à¨ôÂû¾€ nhÒ{Ó¡…æÁŸÍÐ%ZpB$Ÿ h`£•šœã-'äDz”e=Ñ#PöÑ€/Dã;¾ Ï&…F¶Y¯o¶, 4Dhf£Cô"SWÌ>eGÉ6ÂÎ!Ò‚\qèm(Êþ J=[éÊpŽÃ¯G´ÔfÍd,òœÃL‰úút0BÕƒ#øƘ͈óëˆBÊ‘pC£àŒÇFJR=䳨™w”| E_¸")ô@Ò’ž"ž"›'%VØä}ÕêÙw° …L¯I²Á‚çU\ƒG7Ü{àŸ¤±rd.w-DÏn  “yŠ?@H ‹ŒËñi€þSd<Óõ«ìM† ük哨@õÕr÷:wl¡ k†J¶àä:çE§¦óÅICš±Ý(ïšMl ¡âÌpÑÜ ú)Ln­¦_´X«À±I¦ôHº/¼¦MÃÕ“2• ,#6©\žÎD)]U‹$£â¹5”Ù»7 ¦ú) öËÄçé0&ÆP ޲Ÿ,XûÚØÎ¶¶·Íín{ûÛà·¸ÇMîr›ûÜåžÐ,»Á w#Ï®òSöAf펚=ÇÁè;²SõÙ‚Ã4g§µW"fC¼V ¼K’Ñläùß˱æ½9<é§´÷›g£¶†þé9 úàNaµÅ³ŒqÜd•ÝaU´S¸Ö<#s½grOQÞl°À•ˆõµZ²:(€Å?†‚Åé=ìêM§ Vø´S¬ð¥B }èEÆÐœc|õ`E…ƵÓIÄß$Cå”Ón¹ËsM‰‹„ÍAáw+…œã¦›øáö°SÚ;÷Öá%†7tÎu§øäJ¤§³…/@Û)_Pz0õÌìf×hë<_ •/ò-çün×V×92ægÌû¨£w±·™w¤¸»)Sž»°ëën`CE´nJ†ZùŽ9žÒØØæÿšz¨Oš°sñÉRêyÜ[eO ÜͨŒov8ä[>¨šþÍ Ög)ïxxV<ŽW¼b´Ñþ°ˆ}ûÙ¿¶ºü&:щ¶˜ÔœÆÆÔ¬÷¥ <Û@VŽO÷× woLÕzEñzJ~ß‘ 3UW§`HêGD×}PàWÒW‘KϰN~@VwT€.aÔñÑg øWδNSEV¾+‹ µJñQÊðØ‚deVW•'×g~4T }KAT Ñ4WTew5ƒ‚‚òz1}:1fÖM؃5ÕZ”w‚g{Ñ =¶€J!gÊàMÙP •QvY›†ÇXÓ ‘ÂÑ‚EW[ ë4xÙðKœ° ›Ð þ¬õf6K‚‡ Ï@ÏÐRz踆üÄ ƒ÷KÐP Éõf“:uoÏ MÅ‚IñZàK˜xEì†]¿ÄNÓ´l2„Ó ÊÐG,ø‰ ÁGLôE_솉«èN¨Çph6xÐP"`ŠéTÈ[›4DôíÓD8‹ˆQìf‹ pry¤‹ ‘;kèJÓD@%0$N²HjvÔˆÑP€†FñÄ{†>èCõÀAé¥v'ˆ>D Ê@gXX}2Ž­1b!8„S´7vޏ `lYú`+ÏxÑ‚ŽSa1]Ö}ËÀG(|TÀ ÉrÉÁ¯6þ…üÃiÔñ ¼0Þ˜L I Ä ª(GÅ8ÃU¢x¸É€ŒÉ@$€’D!TÐ àáNt˜Sç1ó“Ið#P×!8s‘B! kbz+¶ŽS-  Iʰ €:q0°ͰNõ…cƒ7Pb?pDH0ÐÐ ¼@’)¹þð/kˆx çI•EGä où ÊÀ &ó©T`†Ïhs1é5vdDGD PÏ€â÷C? ¤5ŽÚU•zUbó`™4„™š¨ É0*‡Ÿy¦¤‘9‡;©zŒenDCðØÕM¾ "ð‰ÃYþ PþàöˆaÉ+ž%x H t`^½ùùÁ×I’ ÒˆA(Oíh{ >З4~˜8ˆù"uuù‰EóÇ©ˆ¶cMR6ˆ_ ZðªèJ­èˆÊàà~¯Ãê;ˆ| æjå\v˜‰Ý¾ø‹÷† Ñ 7“í ÊHùŒ˜&…²‚'ˆØOÖHD)Úš«²s4a—' yÉä8Ÿ ÚŽÔ(Œ<šŽ—¢Í0€d5ñ¢-‘ ÚŸàL VB‹U=ÒÈŠCTŽC z˜¼ –CŠZª\ rœtsKZb爎÷9~¤ ªFWzþS:~6g‚õ$3b@æÈAñ%xº¦Í4¤Ë·™Áf£Ĩ4CÄî!¦µ¨™_°3XŠK2j Ñà‹Ë¥¨òT2-é÷hæ§ÿ™&P064tr¨À”¶yH/iº:¢Õ±™^ ,`‘,Ѫ$¡[À4ÉÀ©T,ß©'ó²E9¢ ]²QÓ^F%ÙŠ¨xu¬Ÿ:=LJÖ ™âCçú½BÝ¡­B†ïº;DDÈØš *$`p(A­A$ Ê Êˆ}é¯ÝŠ¥ƒH°6R¥+¡°¤C$^«]Z›Hõ¯±CÒ˜‰šÉ ^þ)T ­$A¤¡VÐT²ÊˆÙ5«k€\6¦òꛩªP#᱑  ܱ®Åʳ=;!­Q“ÚŠ‘„ª4'9 HkÜ" [Ýñ€äX§Kd²¹!FC#p$º™©  à0ë];úð’Ò´kX ÙUHh‰¶!+Œ%eòª±Â——s{…Äe­KÛc«Šæ4€k(+°þ)´ª4$õ¿f8²ûM¼µ\7¹!±C$·pÉ _ DëtyuËï !* ¶¼àãNI«¦KzP‚£~êGͰ _ªZÀ @Ù E³‹þ $Ð, ^þr]£«DØø»$!4ùÕgV+ËÀº^`"(BV‚ÏË?ÜP+"à[À_° Lˆšd¬wâ½,¼ä£*{X»Z󤲵ѾÿÐ £ò丹˄»NÜû—ü«Ïá¨ÒH®øL˜;¿U `³Ðœ Q·K•)p»ý²¡ÜOrÁ/á¿“:È—ØÑºó«5Ó;Pð &| ϰ¼&ÙÂÇ›­½„¿,L JÃi¼b Àþ9YÉÀº<ÜW>Ü÷^ vCÄ Ñ6Ѐ¾ ÄïÃÄûºƒ¢Ë»{J±TL$ã¨Öؤþ ›à “P þ­ëç Âò.œÄj’PVÈ$ð 0BùAÛ1¿‚ÜÄʳ¢Ë£@ù¡¥YÇ.¾ù8ñФ×PYt•{°Åæ+ȃÜWfJèNÀ ,À¶¼VÐÆóÛÂ. ;ˆ\;Z¦Š«¢œöâKVyà ›ì›r¼ ˘¼ŒÜÜœÉ! _À ¹›­¨ÔMæÕOÈ ©µÌĮ̀ÅDOHTzp%úL¨DÍË€ú|¼`Íþ ɰ ›Ü ÐäM«È»åHª¾ËÎ_#©óð"èØ5ÑšXÐ`Ïš©™mZÌÇu\%úŠá!¡ôü?SÌÐ0aþ1òà…5eÞà¤N:уøK¿tž4MÓ2-ŒdN0ÄN³Ð(|"®„e:DàtEŒƒ¤Ó¬ØN#mPjŽ é"A]1Ýe ,}z0 ŽéØ£yLDšCDhÝ£zŠQæ8ªbÁY WœQTå f_Žú¨gŠ@=Ý×:ª i×ÔÒ]Ý  | –¥rÃï1€>ÙnØ2=¡LØAa)Ú †¸Z;[ÁÉA3º ‘ú’0©Ùã²¶„kÑOL§w#¼±.0 FQ«Ú·cØ$ʉ¼×[ºÂ‡pÛ XLâëŠPœiÉ¢ÀÂmó”ºNÊ»R|ÂËþÍ|ErÔÖ’+ÝÓˆ”§$-à ¡ÜÛ­ÕšmmÒ{8ÞÔ]¢ú@-Þê WP2#™Þñ+é—Ù ß÷½ÙNb5üÝß`à¾ñXàžà ¾à Þàþàá>á^á~ážá¾áÞáþá â">â$^â&~â(žâ*¾â,Þâ.¾Fûâ]e§2ÎH·]ãa…8¾:¾ã‚rã;žo>ÎQ@Žã=>äÊ’4àŠä+Á/1ÂäMNãñÉ åS¤03Óì ðpÜjå#‘%C,Ít,梯PÒ"Øû«æá#lÓ"Ø #ç1fþR>AèÓÕU¥¤z^<µ! Á¨bÄ è^ K¥;èÊš«ÉÁoùã"kŒ ‚ŒàÛ>åî\0ô Ùü6•ýìݧßèßÀén«²ÒúÙð›´|Ë Il°¼¼H™ gSÊMú òü ÈYä(=éÑaÄ[Ð2I\½–X¶_[¿©¼@N §á1ˆš0Vv°›€|+ãî‘ìÊ`" )Éàëž‚þ ë¶!ÙÎ ¦ÅÉ;;™HŽìô Ši³Ñ \=¢2ó ™B½ZÐK²ú¥L~éÙPDRÂÁ0Kõº`W§Ænº“~!«Bßrr£i³Ø©còþâý34 Së&1 –ÑÍâ'ðs¹âÜ0¤%Ú§vD‘Pð ÓVð·›Rßa¥“Û^±¯>£R*!qFªB*Ô QB ¸²Óô A!¡z-‰Ëãðe­7óÓaN@Ã]ßJs* ô!³±Sð‚ö¡öuÜöN%´Ä7)ƒLdqUà=_|ÿõÁ› šbeJæ™ ÎójŸøv±øæ#9÷Ò2C,g=PtÉRP€ùy¡ùSÞ¨-´Žæv’Žc‚—ŸÕª/”PB‘¢ô)a…¥Ó4…Ï?µ×·/9±¾Ëcå/¡º¼9þuø¸Í÷Í\:Ž÷tÏû/œsø¨o²ƒj8Üû£';Ð ÃYsúÓýý¹ï,^¿/©JÊð¡VðÝß{Ó %öðùS|1ïÁzûöUqâïßB† >„QâDŠ-^ĘQãFŽýqkÀžú:ž¤8@!J–õ‰ÐRŠ“}þV¶Ä™SçNž=ÚÜ—m 7}rTye?$X´©TêTªU9ÕG €nV3&õŠq«zúj ›VíZ–þöeÕ2ä;¶ÁÖ}èá>Z ö‹ŠWð`Á6Ýfõ"Ba·t /¼ûáÂ}"Èê3Œv¡æÇ=oþ\év=eL.dì˜0Îu­8i¨ï²²57ÿSÕðgÞ½- ­Á<‡©GLå Úy ¢<«;sfܾ­_MO¨ê†Æ#¯K gx ²A7l°Û †t;[ýúüÇéõ1îÑ;^Ö„Å·þ¿Ú Ú‡—lùå[xÇ À胰.¬æaá Šöc <µ¬¢/T˜‡ž²ôÉaŠA±˜`à&:#„±§ÜÞ¢g ,ÂP- ÃzíE†XØžçIá–S¼e³â‹±I©°¢›N«(ǰv´J<Œôix¾DàÄ#‹FÚt2Í£ç¸ÉÈJ«úcþ«ÇŒ¸yónfÌb„A DÌ|T³Ð‹ì£Ç‰-6’“*,§úo#¹áf„\üÌåA™4´Ó«hü‚„Ž•êQ¥¨€í*´È拈9r”çLOoÍ(=zº€ž“H=ÊTŸ"툞žÁ†z!†˜^x¢!¡"×[u /X¶':½"ö$/œ€š-@€ ¼ÈFÚyÌBÓZybSÊj/lÌ+awâðÞ‰üiÀ‹gž‘æ™h Á†im·áŸúÉj°É©[öÍIËœ°y šgÊE¸ÝwÕÍá†'üâF,Æ ã–Âʼn+@Î&…§…×_“#„’1âvþb™¥o•ò§_žæ9›šYÄœw–wB*í)è“\> f¶pÂfnÐygÚ3ã…ºP6¹`Ÿ£¬FŠ*£}Úgh˜þòHþøvöLç²yŠžyª zí|º'­yÚ‚ …¥uE;&¿C½ûöûïÁfÌŠW* çn'¬5ÒX*cE6‡rÕïhÇÁÜ4‡1»y¶°¢*¶1J<'÷ÉŠ*fduÊÉ9sØ%ô'«w†³êv‹F¿¨ (¼jÎfÉ…¯|ìãéŽxÆ ËyŠr¹C¯œ`Õì+‘Óí­³)+xDÈÏ+ñí2^¢¢Í·ÿl‚Ç#6E¶÷u&póx†¨þÔr?ˆ/kü ¼Ð õ ïB‚WáG#x@Ala C°“Ò©%CxÆ!V§‡Ot#ïrŸ ø–y,ÏW <œÐò÷ÞYEPÆ34±õù¡ÛXTdø]ÁC*L!³C†-!‚é‹2šÑŒ…laO[â õ1x8!ƒ‘¢3RºDCë¢ÒºÑ´ †±>n¯Ô†Ær壢N⦌ƒa#aÜ[ûvcÇÍ%Ï{_Ha½†ôp-è ™Í’è:F†Mï`Å:s?5RdwÓó 6T ´›ÕJ{,Ìaj8¥Ïˆ’ÿ°$[â–0i¹²x°Ä‹a"þôf.)eDNé›Ù Ò•®# 0½Â&xl¡ ¾a <42°Ñ3ZÐ7¦Mif45 ¥uØ6:(@ð3ÐxÏ3£YÎiâ6¼ŽÕ’éo~†!‘g éÙG Oиy‘~ò^‚¡@ŠYV³v m€6+²OÜä²3VðÂ;ÊÒ·‰²5„Â!tÌ”T«¡½yšÃ’V%pðè† à¡lŽÏ"õ 7TÐ EÖT-7ínÈÓŒNÄTílÒ?¿8O£ÊˆšÜ€“XÚÀ½ô:,ªU«jÓäÕ0ÅÔjS!‚¥vJT-"€ÆÈÄ:Ö'ôT“œþþ¨ªÉ _+MéÊ“›¾C …s’•À³ÌBmA aSâ`§RÐn¤ÔP Ñ(CrÔë@à ¬dugïuƒÙèf‚¯F(,X˜AD+šv§—Íá^Ò×Ô5°n-½hn ~¸uÌ]Z £w@œµ ®Odùnˆ ³ê)ÚŠ«ù!2¢À«Tka¶?¼½=òÑè–†Ô¥¥µÚå6‰KÞk{[2]´—0Ü Pµdc¦þ•&¼`7ØÁ†p„%dG™Ž¢ð hOŠ¿É“ü*HäÒA5}DŒU«¸Õô*+q¡qkúäÙ!¥ÌõWçVVÿº"ñó7¤ôâùÐ:%Ivoþ‰ wÙÙúî’Ë3c?dŸÙ®% ¸V_þ»Šò[2 T:ŸY×z£Ùê|¢qÚ©ZùÊ']²´¡r¯õ^è~Œ¬@e%ú[²Xéq2Ð ?k_„ØAø`Àk¢ÊÙÝÏæ/4@mÏTÜâ:Ëx]~8·zûã®´Wé›YúyIùZT¹nö¾Ü"µÅÞ“ã.s9O‹¨0‘ºÜç?¡l«bÍÄ¢ã®#H÷Šexþ—v»ÛÌÙö;CkãÝëT‰Û3lÜ>h¾îé?y/7ªA‚;{²ê¹8¾Õú˜l6ƒ‡Ýð‰{ÄÇáU» ÝæqDή(ÌÌf©¸åö¶È·o¦¶ÙPÆ-×twÈ·þdò2âßÁ±¾Ö‘´ó¸9L¡¡‚C †ì:4ýÞë‚ <£Ù ðˆç ×Ã>îØ¨‚ÊêBzdæäô:a•Ì¯ð•§æ’C/ö´Ô<'yǹîÓ·eL¿‚ÂÓC•_SÍcɳÆZê­“Èc[ü^yƦà¯N€ {½ŠâhÐ(R æëðãˆçC ¨‚1¤N¨>ʹ ë{»ŠZ²f¸¿')¸“¨?‹`@Ž@eÈ$løái! j¶§C*°C@ŸxÁô‰$(ø˜š©lØ@°=0¢µ#ì;)â†Ð[ª'q‚‹â‰Ô»ë2X†¿ónÈlþ™jÀo€¬ Ä>ˆ)­lx†!º©ˆAT ´-@!VêBËAC:¤-\A¬3hH†´á@{ó d 4œˆJ†¿kÃw DB£¯I¤ãÄ Ul^è=¦ §É QÆ#>[„:x;^è•ÑSÂ_´ aüciE‘·0ˆÇ%±õ¬!”¶gp‚Ç£³S”D¯Æ™@ïÑpÃsF`û<; ‰œ`ÇvtÇJþd”ˆBnü¥é(™{¬"ñ:³"¬Åh _¬ŠI< ô‡x@¦ëÆ’ Û@H¨ûFI“¶hHXŠª¼´FžÁ‘$AG³´ ÇŠõp XµƒiØ‚‘ëˆùCɵx¾ò‚f°™ßŠÉKdQlx†eåÓ'ÐðÈ>HŠp'hÉ-t½Žü°ä°`8’áhPXK†HB¶HÉÜʈ`KATÁ£DJ ‚c…&,Ù¡®†.RTèƒ<„Cø½NÓ1]=ìá„)±ë©vcªÆÛ/€[®j?–i%ögƒ9R$M¤!ÓB;ö@€`•9’ÓþFd†Æ©š6 Óy¨2j„õá84$„äÙ"ÃVøcÛ†£.hJ1kY<ƲØÓÆ}d/§Ÿ¦ë5IÕ"5RM|`\F®œü<Ä€Všâ6fCªBêæDBü1EFhÝZ´6RÔNèä6)Ò6D¯ñk§‰îõуvDBÄSC¤”üoÎïÇÑ“³ïG^ Xóömwaeõ¶©¹e\<µoœÙZ2ê?ÕQ„¤ᅱ۱ïw€ op_·0H.ý’ï–]Vð'IÑÑ`ÜF=Õôžoxh íàVÆ=ýëy€ÿëGFfÜUÁ‚X„qZDî×þÅ5Õe$oÆí†#^Op¦þÆGMFnrh i•¼8ŒR î‚Tr“ pz´Ó%ë?œí5Oz$€Ö<'ñ݈OÃXY5ïò$?ó%O/VxóìvîG;Wƒd—Ž0Ï•BßUtôX‚t¿§oæî©åB¥AןF§ÑVpLWØBêêïNìFÀ°ˆ>U7õKWT;Å©6›qRñ…õž´už)òX¼ð¹—_ö²)ò&Gò®Cöd7™g%UpLßjyvhvJ¯ ÉdlŸ(R7HŽŒuo/GI/=rG¼–¸vt/©ug÷r÷w/§¶þ”÷z·÷{Ç÷|×÷}ç÷~÷÷ø€ø'ø‚7øƒGø„Wø…gø†wø‡‡øˆ—ø‰§øŠ·ø‹ÇøŒ×øçøŽ·]àE×@,‘‡N5ù‘/ù”w’gyWž ”yR ]ù™Ï:šý¾›ÇùªP†1ô ™§ ðìy†ø!‡sy`¿.©õw§‚ÚÛCžÿùàs‰èà¢Ç4 z©÷UÏwp‡|8Hzi€#Äz°à%äz1w‹SЃ?PáVÀœ‡€†«ÄúøÝ`Yû„Ê)êSà›E”Ü»7ú°²¤7%ã{$~…ô š'|Ý%µ?”?ŸpÊa„ $—Èoˆþ×",=ÛB鶃‘ŠŠâ|‡(û«Ž:×êg-õ4Ÿ‡?XŸ?x—AùäMý†¨ßßàÕm'Õiר,×~ÈóÑ}„õy„ŠýÅzÔW\•ÍÕ¬(Õw¸P¼%Tpò‚–|¡e4պ݆õñx¨xéÏÝwˆ®©"ãcrÁÔÖ+&èÊ˸ÝMMgP¼`ëö®·lÓîØ¹sGjÝàÍÓ·Ï߃wÿ6rìèñ#È"G’,iò$Ê”*W²léÒ%6'ýÑÜ·O½œÝ¶°€@Ä@eØÞÑÓgÑæ¾/[5Jo^·g^œ@ð€”/Ï–yBþ„(T4lÜÞÍ£·‹—jײmëö-ܸ,ý ˜ç¯ßMZT4ÀâK¶¢6i†Tæe¤¿›8¹=³Ò·Ä/—”=Ö­[Y}, Éíìù3èТKÒ¤¹e‹ÓnV €¢¬[QÂ& £¬©ï2 ð-7ŠÜômü8òäÊ?–¾Ù­A·*¬¡@3ë%í¹ûèqÛÒ“‚𨀼ü<úôêM^¯™—^²œ@›wñev—wéeƒòsËï%Ûzx h‰ùãÔ<[@ÐNÜ·V~j%62 @QF]D`H„µ‡ ‰%šø{úÔ3Þ$T·Oú´U![0bEkþD™õáuõøO?ý”ö£HÝœx$’˜¹E^8uãÄNp£OZ$3ãaoÅ”Ø;8ÑM=ÖØ^bä@âˆ#¥Ü3$‘Ua’q–èO$XÈd^ðX1@ÝL¸<"` — Üp´Ï;Tä(xBò‡Cý±Î‡ i!ª_b8Á“L…î FR˜e[ï|ÚÑ>,z‘Ù`H‘)®Ø#$ˆUð̦Á¨O‹s…úT6$4Œ"EçªoQ,Húp#‚ØäT”Qø‚+®­PI`D#,ºêkgJ¶ÑÏxAO›õ3À©jÑø’> ÔÛ=_DIÖþ¶éèn¤ÖžP›.ÄËuÊ.i4á44 8ñN¾%U¡L´myÁªHþÀãDÉÄ<èŒð,ì¯G|3rë’Ôœ¨U  LÇ&½C±Kû¶DW³;Ÿ¥17Ýxó2¦ÀcV?>ÛŒ3Ö£ébMOuCÂÝüK’áGòKÑPÑî<,<M6¢À|‡9óÔ£¯ g½·q¾Ú‘»óZ=-)£…¾h»$‚ª)éãÅZ<³¸z¨2=TÐÌØ|{±£xìÙ  Â%”ôa‡‹t² fš+ÓùçÁ·5ñLî-<À›dÅÕ¬+Îþ}/Á£`\‚ &Î@Ó´Éü)<ø ·È3T"°PøZݨpöZô4°–>Þm‘Œ4ÏlïÉŒ>ÿpMœ²…¤­y.IÆóT²…/Ôè ØB3ž‘ ü}ALÊëÙCO½+cKyK2g¸¢ä^«ƒ2°…g°³²Hi2(ãÅÊSÑ€÷@ç¯ê Zmñ4Z€-¬R3<âIJã$àwr¡_ò€L½ÅøƒÂXÊò=$r$J|× P…Îp#-Ø!¡I²aÆ·xAØp!æŒØÅ9nAïÂ5#¸@`g| ²—6ÒDvÉ("ˆèÈÅ®ÁþCv_h öø–/ Q$t <—-¨ _@4¦f/¢H‘á³Ø»†£…Žù#’qqß[ò16ª€Hþp`p¨fË]Д³É»\ÔµR’mq6VÒº’Àè„-áäêü¡ÄQA¥¡Bè%"_îÍ&ú˜Ç;TÐI/ºò-ÙÂJ.É’º…“cÛRE«‹ì# øÀ"Ç£Rrb¶§@ErÓB @J–‰˜ƒŠlœ"ч ¬@–»> F1ŠAŒdaŸýL—çh@ˆ)§È*ù…ŠäFmqgIà1^¼ƒ"ôðÂ2ªÓbpÀ{[ü¨¦P n4àþ‘¤AiûÞ—–¢ÊPk©I2Vš‚ ;Íh.N0  ‹‘_c3™ƒTµ2%êLI7D÷ÌZ¦¤ $¸ 7pÕŒC3㪜BúŽ€"”=c… –ªÒPá\j*Jôñ*ˆÅ¿˜ë/4P‘qõ¯ç¹ÎMDD§¶ë¯s‰QBÛ‘~UV$ˆEë¾€ Ìb®K­JkYå0r8U-GŠÉ–†V%#;,[ ×e$·Øé-œŠÈq¶ ”!81Õná¾<®ov#¨tg ’f’D¿‡ó®„;3ßgºÁ•N±~dCQUH´³ß2†õ)•^íg´}’*4ƒ$X z.Ã#VøM*`V‡@@@‹7hôA*$#²~ì+’¡u[¥jT`¸?ó T†à"à  n4â`2H Ÿ¾æ[ã!Ù°%UZV”\.0ÒB4r‡8Ì (ƒô€òÓåþÉ|! ‚ÈÑ<Û6ÿ;EÂÒL¦¤çù”‘”`qˆÔ˜‹b§[ÈÍݸþ!<öA*'´ØêsI§:ÇÒY¼Ã9€ ð‚2TîEn9ÛÕß ’àGJÁ34=å” Ø’Ø ·-òÐQ7èÂÜÊA¦'þ‡þxW7°Ts$ÍkîõÕ9¢c­£Q)}—üJàá,ø –`ˆCô‡k`NL¥÷°¨¸Á î†äqªû’b¿‘)†äß¹î®7Ÿíh¨àú›I¬ ™Ix%å=âÿàÌV[2AL4XÍ™GK?[(Ìå=²bÍãþ${@ˆ€|A2(ƒ2@ƒ64 úõßñÁ7`C˜TI@[QÍÚ\ıüË2IZö9àHìÃ3,ÙÃþD€ ýØO eF"©ßƒ|AŽlÑ€TÀÍXìAA2a]qÜ®eÚg¨Ÿ@ßGª ™©] º`T`ƒ <Kìƒ2<ÀÎyØÕ}ÜJ%O€àGÈݲ=rĈÀ$ ‰•Yú1!{¸7@ɽ„­^úÕý‘Da]þm„û×¹7(ŠÜ`I¼CjIC‚Œ™¹á\@]6¤PÕåžÏlÑÚHPÒ‚Äo™–öñË@ÀfôØIƒXšQš#ÖÆ‚DW»åÙð„¢”Xˆ ÜÝ?À’GüèÚ?ìþCv„Vöä'ÆT@a‘hx$ààÂU¬K>% fC4<@†F=xþ‡ cˆx p–vY™GhÁFÖF4,Ù÷Æp `ÔUÙÂìÈ.£Å€S$¾#mUáî PäFìŸ6²Jæq„`âV74LDæLj}ÌU1ôÂ,ÌS2µaC ÕCz¨‘÷•axqæ.r%¶)ÃuÄhn›2³Ýag /À0Ì-LAl9älA 4x<4Œ\bɌեýÃYœpæH¨F¼›z,/¬À\Õ0€2^d:"uRZ¡‡ÜAÀ,v§$qxfÉ9u„O’„Ä!r† °ÀÈCFýÂ<Á‰Içtn‡|=ƒ@”žåØ´Eª€‘þ(lÄçH@› éåyh*Å \@\hxÀflÎÄ7É—4ˆgH<΋Õ"Gp#¥ýC&õÈ€VK(Žb‰,Ã,P2ð‚R€ÙöL(…âÕ¢U›2\’8ÀŠLäLàK‘ò‰~Ä=wjèÅ 2DИ­4]KÐnió̉3ºˆ-‰i/*Ã2¬Ù\G’rÄ<Ü2]©[ÀÃ!4Œ™§!£¢rU? 6xÙjJ7@AQ%Ínþƒ«,ÃØ'PÕ<–±ÌG7(Ø]ݨŠ4 " †yè?ðè½ÑÙê^k|¤œ‹$¹¹jþM¡ã¤~u’ŠŠ" Za2ífqBÁ g?@C÷&ºtʱÛDØT¬Êª›e4LªjÊA@2ÐC$ @–ѧþævjº‹¸ÐUN<¬:n$nPù㬌§?ÌÞ%MQäÞ"^Fk‰ÌŸtÁÀL*LñŦÚbƒT<±’È¡zäG 'O)/Ü_?øéLT¡mÊsTÁü^æÞ(xƒMµaâ½ÚdVÛ3€ë=P^Û$çWþCWâ"¯z7 L!É|iÁx%x‚!ðÁ!t‚6tÃ9nÕ*òûá.Øõèzèžák`z#`ªO†©ÿÎ[äP-‚È!û‚ˆ1ƒ3XÃ"j‘àB™œ…2ðB(þ¥žTôÙø÷yßPš¨êhc¥i!ã—í'‰l)ûº©ýX™1 VïÌÃ0<6`ƒ4| ܧr¼ƒÏœæHœiÖý'G`_ê2G6±ÍH<ã€Ù +«|Ò'=À,Ã0Œ±<4 ±¤’àžé?ì! sD'΄ñ†D<8Ò lf†…‰Éé ¥m¨h0&]ŸyÏ4¬[DŸ®F‰=rD‘úáVÒ±ÿ>ä×Þ*r ðBe¸*<ŒrNìÏà&ÆMl€U]U.l>ëÆE’@“Uyf¦veæ “†’ñéy‹×&` QDf´Wþ³Ñ?-æ\}A@ÍŸh m!®„`~„«äâå¹”Ô1IL®P*Q-° ·sÚæÅnŽ02@#j¦¶DFo„íå"Ú\Wˆ€´Iœ¯»â´Jô™fX?±tKKt=Cp€ü@¤€V ØTAð„¡Å?ªEO£öQrâWfrI(ðvzþF§x­‘Åþ@õ“H!„TdAle<q)²š±EGBÁî²DYÿƒgr´þ]ØG³53ÍÝa«…ZÉöˆ’]Ó‘»DWB<ê£bã>Ã;›Ï„uï7·…8Açx P3ó 5d›Ä†6[[X&Ãe;µíþ:CYB±e14<ÃðâHKdgÃEÖvÎë€D%æönsl›„žl“d¦ˆHÁÃ;D‚#Dy7À³ÿíIŸtFjÏV_]þþkÃöõr=+Óy.56B±[+¤cwË»<…Hµø('qóĉ.[ ÊEb›a†;1HDCpÚ÷t£§‚{„`±4_¤¤Ûº]°Ë‘I¨àĶ”‚Ç¡ý)Ê­rÞh$·E¨öÎà›sgø kf§D®ôIt l/xÌèÁ+˜GŠgPsx“‡HùPá®"CÀk4/Œt-ƒFŽs„2øÐ˜‹ß‘Ä>Ü÷„­I“„;ZÁüÄ.Ì0B#vî|^C4ð‚`G´›EÆ—÷’ÄÃH<·5 “úΚqúw2¯…[_4£BkÌÍä„Mܨ¢×|®n¸ÐEF…ŸD8úÛŽ‹o<çÖ²¯…ÜYáGzhÁ,C!ÌáÙ(¶·6=”<€ˆ¹©ƒ9Ã⪗{ÞÕFº³Z„]{” ó‚3غCˆçbû‚(_ į—{\,7F;ÚÀ“Da¥D£Ÿ¹ZÀC%ºã»‡ë3p‚’ ñ5`®Ó‘°Ázµ£"£ÀŒ‡Æ©o›‘{7ï˜Á“¼ZXíøÅ‘4Dƒ(Â!ˆÂù-ؽ£÷}YQД‰¶M7@žÆE¸£DH×Qެpêd³E×£6 Ó•iü?x ¾K¼Ã¼úwò—_,C6´¾x¿½G9¢#O8T¦’¯SÁH{Ææ£„ZOèÿƒ|½Ð¯§R›‹kwðûxÆ|ÿÀ PcÉd)Ÿ§öì·,Á7I\svý~ é«„L9A´ dMQ<`hhAS›sþ®£ÕÇáðR4žr¼JX4xýï¿ñ·3@¨Øò`Aƒ&,¥•-_žeëo=‹¹Q`þ¥›>†9’dI“'Q¦TùÏß>}óºaSæE Ce+CVqâo¥¾ýN&ûbò‹œ,Uø®“*^”aãF‘ž>«­Îû6žJÁ†;6ìG}ôÞq{–L  ôÕùU¥—A‡–¤×@©¿¤cý‘x@EËhÙÞUÜ·¯åâÅýüõÃÆâ7²—1gÖÜ’¼˜3«0Ô"vîÑôP =é[ß¿a•5€ò4êĪqçù4Í¿7ùÑ%ÌlÏxm¡¢bÀ;°¥qBƒ’RµÉlCÀú½«t/ *#Rô¸›'ÈòÂѧWÏ’ó»gÊ”-óº ¥Ðq’èF=oþI§ÁÚç5œ‚B ¨¤Rl7‚èZÏÁ1ÃMŸ,ø€Xø¢-ðm%üVꆕª3É‹þŽÐ(œ²©Ï¡d²!¬ÑÆìˆ bŠéq‡"æƒâ­yTq%(#JlËg£Í7½ò\ꌅX®mb Cq IpB¤]Uzt%i'É2v$†X U‰àqVߥmµ³l¸¥L]âÈÃ;ò¨ãŠ(Th  …N)û ^I…;==Ö ØTX6©:flA‘nÚθ‘ h‘E:î¨Úê:¤pâVP ª9%ÖŽJ—S*"ü4¡l aÞ-x‰F"-SMZîàZçn²‰†Š\Ãê¿ïh ­xÆ ¯Q‚‡âœUvÌT<ˆ›þDp‚Ô+§‚ß¹9DZ8ϲæ½eòÜê=¬4Þ\ÿA%-Ø ;â’´¸©ìíàù6ã§* e”U:¯óá#ôç,˜¸Ášf”±ÃôªíhKÒo»qý¤}x\vœÞa³¤æÑ}¶.úðC=þ„} cø÷û2ž»ñ]™ÒŸïc é9@…Í55¥ˆÍ$$pNfä®@ \pà£~4”È— l<ÃÏ»Ã$¾°?*,C(û{âU²`;`!þ`I°§½ËÌã-ØÈSöàÁNˆeInŽºÐ1ãw8ß<ÁŒg¼ç "   < 5bÙYX®X+î2݈— X<$‡€Óƒ<œu43N2ˆôLò á LhBœp4 Q h„!e °tO,_haIDt™lèÎrTÀ–Æç¢"=¤ä/ ²´y¨Qyш4°ldƒ”° !TØ… „´â+K"‚‡•k,°¡]né =<ÏÁ‹0)Ì»q™íä7T/(O(ü‹Â…} À‡sÂæœeP„ñB2š‘ (ú¡‘Uóþ<êq/tN”=ýæ:³Ánl4žÉHKè.!‰Hdo!Á6SR”±‹üäŽ ‚‚(ÇÜ JP–éÁ¸FæôÁIRԌ¼h7Þw°@ÍPjZBá‡=ì¡lˆ H0¨%ÿAXXZ*$I%Ü0iA¢ dfT-8å„(6Ñ kpLsC%*‰cÑyìu‰Œ†E†ÉˆqZÍ}”ÓÏtj¥ÿ$ <£´…o!’ U`›Z3ºQ"FŠÕðlfͩػ/¯W9‹³XÄϳÇը…$AmÃâJ±¨0%ðУjXY¶]I"IUêFþ¡Ee¾óTÂíh‘V!ºD¨…uõQGx°Ðt‚lE -*$–d kI’sDã-(`Á¼h‘?Q„¯Ç­H Ñ¤ 7Цnöá„xQ/¬éìP«)<«ñ"A‚¤Ëœ—$ûô!7(ó¼× 0Ê(Uªrx(8iEPe4ÿÕO€Ws¼?x0vÑBhX [8a…Ù f(L(@X!ôpËš¼)Ü/`6s).ðüöÊ üZd1v]qy°N˜8ðß !špë»*x‹¾ÀƒdjÂŽ-ÉÍBâ:6¸µ,/ˆ›¥@MQ¡G7LþÌ>ò\˜ÝØr%ûpxÌó»Õ`Ê}ÁWýÝ\ÄØÁ·6ŒG+&ÏJs¹¤›~8fKðÀÿØChtVué³gTq‡ê!›8&4¢¡Œ&¦‰* èLise&È$Q©­•!˜´!Òr–]òa&ÒKóT’8y¥ÇŽŸ+kÎÕƒÓœ¡_6¨ŠEÂÓX«-”.D‚ 9¨A±ÓðŒ,ºKœþA/|zÚ$0¸S†‹mñ±Ü±ÎÍWÅ=Ú¥]Õ˜Æ4¢‘Ìw¾ÞšPÙÊì†!à»ø¥7Â’f“dʨB¼@¨`èÀ.°þ/`Î6¾<£û"Nh‘]r™É\îFïFÄk6Y ˆ¯ÄßG¡‡2Ì @1ÔßÀ×Ë„ dÛçgw|œ-z\ÍN„¾Ã4Ç—ÿæ-hxpN06 ÞB9pc¼&YyAÜSRd‹Àà{t—s„kcØPÙ/qaºÝ¸{½È<ÄDÀB ¨· àôü-t®œ2:b^dzÜà…¦ôçËÜ›‰¬¬´ “]«ɸ}îÑÒþÞ÷~Þ«9„ÿ·þIx¾(ûC¾j0sæk?¦¬‡‚ª€"!¦ÏPÐB&´ÀÌn%êXûœàõ¨À à ¶àDX fÏlO¢Ò¯Y‚=bì,¬b¯bÐó¬F`ç˜(„¶€[¤ tàÞôô⥜oJ6Ì@¼`¤ ZÐ.¶ @ÏµÔ ‘r …Ë „$ P VÈÄ ¨ÌÊ<ðì¦Ë1¼pµ”êL¸àÁŠ)>Š¢ tmeÎà»r¬màpp`²nñrt0 •ðaO * x!”a`”† ¨°àì¥Êpo )J7ìxÒ"×쀧ôà°þá¾`ãàítíoì@ à¡`ÜpæXÑà\ÑŽÖ¤]Qæ¸/Ǽ ¿¯¿`Ÿ”°Á)Š\@~ z¶©z©ô$1÷Î+jæçn²Á6( ! 鈨ˆBÁµÜ  ¬À ¨àOñÝÐsì–f«ÀJOñ«u {ñèºATÖNy¾@'´ "”1’š±„.$ä%(Ny’éf¶À톉ˆø€»¼@÷çÆŽïÑñ]LžÀ F”àjÁöî±Oä JmÙêzO‘ã ™”‰ñªì yѲ+ƒ4¨è®¯öJ©þ<¨j 0xaú\ #3üª¿ª€©|¬rbÁäDQzñ0b21PÌ"®~ŠH™rr¿$*{R÷c~”jãÞ‰Q ß!îL'Œ ”zñ‚ >’Ò•ŠBr!Vvà Q­òªò¬Â é¡9Ìrã ÕØ²-ÑÎ’d©°¢ãa»ž§”‰­2Jƒ’ ”øò=îÈ ^åZhÁ2N*ÚÄ"‰ƒ ¾.;“ò–Q 5ÓY¢Ïê ¾À ¨Œºàr<¨é’N³8®è ¾Àf/F@*6 ĪbKÈHºüÁ¬«(ÛO<…s8±1¤ÑþÏ ijÀ&ré‹e¦¡¸F ÊË힊ˆJéb“Qbá ˜«.uÓ®>"¿JÐÏ|)3Ùó®¦k±ôaFbl"³¡Bá!ª´B»FÊF hmd¯L„A’¡Ét$>bª€DçsÛ"ô ÉSˆœ04C‰N”pR£¨Â1ºí ²@-`ï0À@1óMb2=â1C.G›ñ+pCqTLˆ,Ñ&5® Î}rÃ%@ ˆHV xà0@ °¤HŸ‹'¨@(G¹T3¿¢0¨”AŒ‡!Ó‚“*Æ_Z¶à£Öb]††Hù+DF$˜úôR³þ¨Ü"#&ï1µm=ƒQ‰NyÖêO>'æRUµ Îâ‚ôÊ?UÅâ,G"£–éPáæœN"oVµWgµÏËA!1XüQ;#é4ê1C B}µYµ´LK=ûKF‹Õ úS&e2V§ÕY¹GÜÓ sC½ä©‰ruµ[ÑLöT´>¾àÉBSZÓu^qÂK§õOÂ]K \û‹Yéu^íX¿€'h=ÿõ`ƒCžžõ^¶a!Ä]Â_vbMb$–b16c5vc9¶c=öcA6dEvdI¶dMödQ6eUveY¶e]öea6fevfi¶fmöfq6guvgy¶g}ög6hþ…vh‰¶höh‘6i•vi™¶iöi¡ö±˜1$ ¡.6j)I Èj$”¦öç°º”ÁgB¢kóIF!6lïªp¦$ºökB†jMm' {NÂlQ.nçnEâöN$Þ%ª`ø–sX`nM øMpàlE¸wnjH%úŽk½%vr“f ×f¦Ãm3×$’…ÈNÃ8×Aæa2 èÁ{DrBo÷®Ÿ(%uäVTÂ¥HbpMB PuK âFwÓ£j—$Tà€0WvÂà*êÖá´4!v y×CXB÷$2vOB´ 2ÜáÎ}îa[ ÂþÐzL{Ñx¡7!¢! ×o B†ž¡Úáyì¡` ÂÌÜw=ÞalÇ$ÞAD×~Do»­« ·w?7X¶`XÖÝh†µu28P¯Vi¡lCå QBÚ—ÓB¡õŒÌŒX„õ€"“8``ùô„“v#p{Èæ$¨ 5Òô ÷á `X_…h¨€Ä‡Å¡ìdØò!øázC"^øp ·P €‚p#„°‹ýøÊ KÊu,GЦ@øÎÁ\eÃJá|K!}Ã!’Aa´W#p¢ €-Õ=ÏX`˜F¬3‹h½þ ‘ `Ô #³°U©à!Þ JH¡¹ô¡àLGøáL "Yâ—n ˆU"¦Ê9}³E\îV찲Π˜½(˜{íð @´Ìèž¡Hñæ«—H ðòo¡•%É/Lw myݶ9òZ»Ô¤„JhM¬à LåSϘA^âBçÐÍù´à’A&Á´{"«v ÎÜV… °E‚[!jÇ è¡¸ÿÏ+ë´3€ôò!¾¬\ÙuMègmé§O¢¶UKí˜É· x‹$ºCb´E"{ZŠõ¡¸}ú0’ʽ]âyôàFXÄ7Øgmišº x“Št_ží]ø¢Æèu‰‚ÁõaRD *¸aàæ¡ªØµ"x7ê!˜cùf¼«\¢Ödì¦ÛÇ¢œ$ àÍ ±"hy$ ŒÛ­ ¡aÄLáÛaXçAŠ»°ñ~?¾|^ tc8|Þ;lZ°`¨N" V ÷iDDÔA¤ÌLAð˜Fáyu“Yý04Ï"X’Ç[y\ÃM6Êdó,èã’|*®È"OÝ<°EFùu“ÍtQ€6ÁMÏ0§ "¤UEV¸WQ6ÿÕÄ‚e7•AÝ @å•„È4_(°@àK[µHf™fþãO"¼#?úÐóN6ÏÜ%TE:ÖôEfž5paE[8I¤F"Ì$ %sÝ“ßidþ\xñÅ% €‹x` ïˆyf§žªÈÍaös7Ñ<€T4ÝI HjTE3AÃCÖYEðHG“DuÖdÖ˜m1@[@z ² -Ń‹걄æ§Ö^ë×>TDu4P(u«º6ð+DÝ <è2´ BïàQ€B䫚vT h±ÅVÁ<ûìØÐ%,¶ /LSKÒ,K†K–MÉè)h„ÂÝjkÂÏ8ÈÐgQ"”§¢#KH¥VÐ,Á/±…>(¦ÈpÍ6T=Ù€j8‰  ÐXUkЄïÐ}2D‘¼Ñ¢9A£¡G<¸LþpÊÌEíÍ^לsœÑ4&O@#äëfí"t¤­j× ÿÐBh"4¼Ú»ô 7Žã†0$¡?Àrñ, |Á}•/p 'ePÁ#Pp£^ò×᳉†!ý A úÉЊŒ!^@ΰÊ}8AáíÉ*Õ \@Ãp¶ÐÄøzþX…ùeÄ 0}<ƒ$¨_è4B$ ïXà6p…nF#A’Q´<íÆ`|éûâ¾@X+ÆàžÑúvÉ`;Œˆ¼Œq Ží0MºøÅU©Õ™Óoâé!Ägÿ#ÎìÆbDP Ay¢d<@^EC8€µŒܸ]îøÅœ!å ŠÑ2=´Ð+ä³&þ€¤‰ÂåðB›£Ã˜@¾@ìÒCÌQ‹O·]Mä¥ÄîË ëÈÕà ØA.|‘‹ œ ¬¾Š` E75îqÆ®•ñêgãQôåFIÍraFÒÍ6¶¼Ÿ§=µþžTÀ§_èÁX@##SZt@ƒ0×T,ÝÇQt«NØ@ólš$<@†YÁóÉåË]!Ï0kˆDü S üõ?º—$Çî9ŽõBx5Ä'@ Và/šËwRãñófí×Wêõg ŸÖµ5".*€ÖýÇ‚jhfX—=Ì4âì)‚]Ûd^h@j³i¢!@ |Tbž¹s¦÷ÎÏ º‘NöÁ°çDÇ*è+SDŠoco® êdF‹`$ÚˆãÆxòÞ&l°_ˆºšý#tc¹òâðíšÞg`B®Ú8ñ6T °êdlÒ°“Z³!‚ŒDÃÆþÙu:–Äp _¦¼(ÕdsœÀc ˆtNð'} ¼x†Ý1ŽùÓ“©É¦2Ë¢sò+4À žGÈ^S lµZÁ¦r»Íã2=赉¦YñN5ý¢ñÄÜyÀ”‹'Gdq~„;U‘}Ú·"þÀwÄc=¡mWb9‘_i¥1¨áFò‚?ë¢SW!ÞBluÂÒk€=ÑT e:Ñ n×Ck±A²„w X&Ü0¶”z§`lW Tf\ñ=#lÉ‘{ñÓä¹² !$ BAÕ{'%^´gý0e"@r}áàÆ @z` ö d4¸"¸&þ$ Ð ÓdÝð _@ PZ¸aŽ€Ñ+x'Æ‚`n4(ÿ0=àçbWóÂ]q³öÁ‚Æa'È$ T°˜ðzðõ€0 ˆ†8±ÑIºD6"`Ïð¡nr²$ EïAÌWj÷ΑhËÔeqc‚‘Ñ6E2@ÿ@•9¬EH"PÆj"@ÏÐ'¹gTÀâÀ5ý Ü ÷ÔƒŸ¸ó ¥ádT °” Ë@,Ìûoòö@%øk)7/²œAÉð9Ó ÿ!t³ˆ(”e?S‡Z@‹zÑ(‘`v– C,àþØÞˆó€ ^ÀwѕŌÇÁ"Ù ‘ÉY–ç[Q„¡µrŠa„È‹31Qmb/½—:ÎáN4¡_0j 'ûà…iPva 0[ð^¦‡‘gâð b õ%Ö å×ð€kZðiödp þ°‹ˆøÁÇ1G"7uR2S(#m·‚Àö-T×"1ð bv€4`ƒ3•Ri"BGÀ úP#Tð&T‘U·€GqséLj±L–ö"U‘vA.3(U‹0t”CõÁØà‰CáØ‘ Pqàv@Ñ`nPþy˜ò£q¢Ž®X9ûÐ Û(þá”™¯{ Cxt“ –¶ŒfF·Ò±@h‚iÜåŒ5oÓÖs\©Ù¸ ÷Ô7¤Õ ýÐ þуÐ^gïó›eB*HÁ UE¼öÙáŠ*pC©øáXhÅ`€R„Pј°^  ·ÒÜ€#[p:t4ó@P5óÀ|N0ž|¡‘^ðWn7™ú¤Pxpƒ` €gôš÷¹ûðKs9›Ï öóÊ@ {¡`Ð|’¸W'Òdñ¦ C +óÒ•Z¡RÜUø ›÷¸árø:P‰ÉÐ {PT¢þ€ ‚ ¦»` · å6-4*?6Ê ì6bi¶S‰ ‹iŠÉÀ %‡¥@Ø9  4EèUÀ ÿ¡.·RñxsCõAÁ^)€˜©:“'‘É˹s‡¤P²S ·_pqK'§¼1& Šù-wØ#úW0l¹y¸¥Aàó)ÓI(|S/T€¨MxÔMûð °— dÚ0ï@+ùTð[Ù¢C0à?p ÒàG†¹ª\Ú&E*q’ [ðW!Úš ©‘AØz±9#ž¿ ú1ŸCjKH;Óku4A·Eï9‘jÚxO7Rþ›¢$*ÀOf¥u Q®¾y®{QKDÑ !rNÝP ûÙ‘ÉÇÙ˜ ©œÉkÍo®)\—ŒÓ¹X„–&®óetÔXTZîH‰[xJY¢T83 Q GÓçJ¬–dû±=ÁQþÀ #`ðà§8šÌ™Æ© + nˆ8Ì&‰&[`‚)ÇŒ"s2OÀ tt°C@!ÝP‡U ²A¶Zп!¦Ðª¼p#_È/_  ÖW®+Qµ~ÁQûð€aÏ⠞󰆫"þð< ¤¤Ñ`ùùÇev!$^{ªË`‡iÉ " Ñ7òþÊ©žê)ïÉØ/LN­Vz¹ûWú·€5Ãp^°)`Ø2•´â£c× §QðõDáN/É‹ 0Å0töÓdû°$Páh¾#¸Žei¤ï.T`Ž$3‹þ õ«¹xlŸ#N°¶*Ÿ&?ºÐ¤\fêtÇ펻AícÏßño²J0ÅIðÀ]ì^P 7ø¡˜¢ÏZ6úî+3F@0ÄÐ ´`Qå‘÷#ï‚’øC>oCg/×)NÈ1SD}R|;@þà¶”ÿ¨Å3α‰*!a`uþp«·£gPßñZÝ  >P—²Ê@TÀÉÉzc« E[rªyù¡ä @†(“ÿP=VÀ9+çö<“0²=Ù¢Ê@ç ™@b0/ð:Ðë+¡;¸/‚¾Âã` ¿0; Mᬥ âUÞý#XРA_`;øO ß5Ø÷›“‚ûñßFn* RùR0[ƒy«ˆ€×Ð <+¶ÐsYÓæÍ‚DŒ±sÇç8df0@…l4q.eÚÔéS¨QB@ÂJ2lÝÞ…ÄV’+¾l¡âDÅRkîK&‚ijŠMá©€×àCþþDp#¨‚/Anÿ¥%H¢%„”õ5hIðdb“ ¼àÔ§J7µM»5ñÓ³ÏB^œ4ЭŠ-3¯fÝÚõ<þöé£7·l_  ˜²%Y²-U ¨x0 ñjnTh9ÞT!Æx —(Â`²Éƒ Vö¸ÁlÖ#«þ·o8ù†þ ‘ Í£kƒ`tþü=}³¹%£€HøpÀ›d« žn¸ÁfAh Q&™/´€‚P&3z¾€@÷ šG'ôqI:‚ºyÀ#+ž1È èûG™-þY콨ÈÎ1”‚¦ —ê ÉDP„L¨ï§@æÑGýiŽ@(£þd-¶Ùæ™'AܰÉ£‚Bƒ*›ÑR“*™º¢Œ ÀLÆú1H„Ä:*Q0( #hŸ¯!}X`A)œèñ¢*ülm Ž#í üö‰MJL3²ÚlÛŠP³Éìªp‚„¢ž2´ôô…k"‘ +n ¡8Ê(×lX8ˆh|Ì%eÒlÊŸfDPÁUµ²àÖè©>oàQÒRM³ÕöX*;…çp»I›g"‚ÐK$#4ªb£±iV‹HÈ«wßñUׂð%(Çcàƒ>¬Ë©À àÅ®¨bR–6>³ƒoÞ'?·Õxc‚þ¨œžÚ¬´r+l¼TA®iž-€"›ÕèTÈ5iäó8h 8Æœ ‚â¯/nìEqT÷…`vj-–;§8c!‡#§áæyè±4cŽ»Ö46Ù–yìyÞɦÜ*X €\RO¾ Y­gx¼‰Þœ(© ÞÜNMí ú"‚èi !`3Ö%xD°‚á¥Ø‚€¥›šçYj8ò=¶é&k&¹özô(Á{IÚè¹ ^$$Ý¢áišŠ¿V tлÙ4K$¡!Ãz. ¢¼¡*TþÓ%¼p3ª^EPFÎ¥¶Ð ¦ý,U,ÖúRÒ×2"°÷1ßüþÚºÁÆáŠ«âŸ~¢!A„dæÎlÇçÕ½ ÃUƒð޵íxÏ<Äó2¥çyYœKL´Ñá& ˜ NÀ¤A{ŸE7(µ5ñ…°tÿ0ùôàx,*JP¿±FfyAðö¨ˆ ÈØ;z¸‚ à^ï*щÒÀô¬¤hN©LœCð ÀQ,Ö‘ô  td ["äâ€È'›}Ìã @P+´ ÐäV³#Âáä†ÉØ×töfhhÁ .ê‹¢¼pÇ»èñˆs 7H¨¬‡ÑÈ æ¢lÐ3×À~"ØELJ¥|ð€,ŠñÉbü@þkD‹à£( †6Ü_AæÑ€¹ù–Ñ ÿ±yä•ÌÛ‹KØó¨23Ý ‚»ötAe=¡ n8Ò'®v1fRš™›>¬‹O# àÀBØO*Ø8$Snè0K¦lˆ ŠfËgÒxµ3H7 ºl ';ZFÌ•¨e`ŽTЂ á;"ܰƦùP¨€SóÀ0p±ƒáÅèÔ†.¡EETæR´àÑ} yÀ“H(Ä=ć»+^C¨ãKBºDCÀ5Ÿ!‚5~ Uð‚x¡‰IœВ¯>ˆF'T¢G7Ø‚ þü…NU˜Jå$ˆ´I† ºw@r!aÜïbŠ+\‰“„½Äé*_Ô€\fÆY¤d¾  e<ãш4°ñLK^Rª‹¥’4€ €^€”¹ð*…Lǧìà $ˆGSL%:½T® ÇÓ‘<ù5'Õø¦&iu£Ñ–BºÈµ)ÅA… (<£A ÒR6œšXÅ.¢óPNUžñ„$Hö“;PÁ—Dð¶A…ðBp·ƒÒšÜÔ ó€@vówÚ‚äé%lˆØYW¦$M¬R$Á@µ°6°¸•VæQ}ôƒ|Âå/AÇ6/Ü×l¸(‰A2´¡ :@‘À›ìC‰N¹þ!`Œx-`ö ,X¢-½ƒH¿Ô$´6ùeMàa•ÖÞ¤BnqB¾ jT¡ÆÕŠ÷0fÝþb’Cè†lÃg8ÀG@‚Іçz“)Ó­.…±ë’~<`‰å@ŠíôVðÔ” ÑX©‰)B✊ØyP¼‰!¥Ö›d@÷ïHV£¾5­m Ç9áû²ÛœÍ P8ƒ$í`CØmZx™o’¶KZAyI†i Bò‚W1ÝÅUŠ‘¦åAÚµˆZÀ1P@‚[‚ªØ:¬u'°M ß›316ÕáÑÀÄæìP Ê5y`«òd—`Ã^. 3A°q^ád×wù.þð˜Å@}2ÅZÁ”%EeAavÐC·Mç±m-C€«sÜ-ÛtcKÐð„$}b<À4‹&!¡ »K.Æ¥Sy5,i‚]ƒ:|F§Û’,  ŠÀÒæÎ¤ÇToŒ*¶ƒÐeœzŠ€ÓPAôMœðï‚„¸&, ³‡oÙìÀÚŒÆt¦²’î[܌ؑIJ}èló`/8Þߨè#ÝÙ¨%Ü};à€òþOǶzzØ.áÝj n/ÄæÐxßÎÚn“öà¤Ä7!ç¿/'Ыß!•‚êÓÏMUxäÙy¯ þL^ߪ|ã²{CúW“Ù„p‰ÍO Ì8Ý䕲]^SfØÓœ{SYNØç6¿Ÿ›„QO·‚6±A;ÐPÁüf,Ű7¥ÂQV_öˆpmHäo’Œ~×dî7‘^ÿ ~z ¥ÿƒ’šzÕSõÇ£ÒÄ»ñ0ˆ]#U!Ò…oÒVºù6 ÚMWùšï ÝpëM8´”åÛäCC`²]B°¢T¸¯Ã>Wƒµo•r‘]8Éʘ1¶€gÉωÍ1± 'Ƚá[Aû–ÀÀ ¼‰|J¸9a·*Ø‚.8?0J <@è’‰þ§P®bð…5j®K§h9œH'›à2¨‘+›{‘"ˆïÀ eH>å+6›H†¢`›æ*(^À„<˜–žÐâ»´AÚ@Q‚%P®#€€“›±³‘Æs ÝP±{›´šXÂnB8±®ÞcŠü“©¢ð?t/H†Àb†M…Oè„à ÃCþ*Õ—*ð®JPæR› +zCž9lˆ‰°4úà n8¿%\ŒšøŸ×*AŒ¶›XŒF'p£P†ÂÚ-ÃZ(HÜ"I„º}™­È^X€a †$€øbˆ`ˆy+ ,+E·¡«V Aƒø²¸~þ‘+¶Z i¨#¹£ÂÑŠ¾öjÁ/h—d•-Ñnø­Ðñµ`Ÿ¨«Ä-y‚ HH.b ;艞 ta"º.Ó.—0œàz™<´‰Ÿ© u4À¹š §§ù‚è€-à…gÈ D”¼Љ¦|.í» âY##¸…$ƒ#¡¨‰@qºÀ¥à† Ë®p<­%ü‡C¬‰[yÅ…œBuᆢà P#ª’¼šÀh‹±­Qº–œÄ}„l𾂰ҋÓÐ †áIœØ¢)ƒ³ >±‰¢<¶š`E¦xtLGòè´B`A/P†ùÊÊy@“-°83Ÿþ¾ëJ©¢*ëi€4{/¨„¼»ƒ ( £`Ȧ¨(D¶š ºÔ¿8Ì› t‰ŒtŠ‚‡¿|¨pƒLˆ•ÄbT›n¨9sL¯<1 ‚q‘†eà…D(=x‹¶Ñ¶”»a»‰–Z ìMºŒ ^iŠÇkŠü‡»Ã¶ nã¶oh(‹[4IÆ\=Þä/FinˆµQ‘†d°ÌÒ´¨)ŠÐF@a ¹ÛËš ‚ÓüÀƒp'›€Å›(;Õ»ÛãŒ0:üÈÆÜ‡¹|LOñé-ÈÕ!R±„Ë<ƒ­KK8œ¦x¹¥ -œ¥Ç‚Ðo4Ê&ä@˜»‰g %Î0þ+’}à‡¤C=@“k¤Ð‡ò¸²¡ºgH†7(½1¨=ÿ ¥.Û§21JkKjˆ¢ü‡x’<eŠÅH8Ã%̹«ûƒqpPÓ!¡€‡&ÒÇ\½É3Rù‚>Øœ(8•l]K¿ƒ¸ÎCÓȆèþÄ2úÓÑ-'eŠËѵ5Ú ÚVà» UÓWÓ¾q/à‚8E¨+H›5Úº“3 KKM)]<‚àé±)=ˆ‹x (Ê‚pJ¶B´ 5¸:;8ºH„Tsû¢2T·"õ-hƒ$„HÐ*X#'P›Ã+Š`Q?>lˆFó¬ÿGœx€ýÎËÏ}36´`G˜±þ ÕsÐ"`ÄÕ\õ‡‰"™fàÚ-`W/¨‚5âá`â0¿|’ \ Y,ÂlUÑ‚ B=ˆ-`Õ`«¿ÑL¾¡‚.¨=…J¢Ar}:IÝø š?ŠÛúuWp°mõ½œûOƒ¨†fMSU;œVý‹Ò¦°·).v Éäù Ò ƒ´P¨˜dɉ57ô1ÃY{D´¬fH†.ƒ¤ƒ¸Â€‚ˆØ³¦¹¥˜©›¨R:¿˜ûQ—¸™‚08„UØ‚ºÁª+ DjX¨J2ŸŸõ;tCÙ­/X£jhpw ¨…rÕx‡Òlˆ+ÍZþÊ ¼MS@6e]‹·É,ð‚eЭ-Y›*XQqª[[lÓwÀe`ßlȃ͙{]£Pt ã3§¼šH Ú8€k…Ý-p¤ BHƒ5ˆ„¿R³”\-•gzªÆ]¨ƒ5Û€‡†Ýn †¼£HË;­‡Bá!§P~õ×ѺCŠQ$¥ ‚€€ƒ‚ü‰ið-t—nPØ­Ïqe^:+±Á¶ÁšÀ‹‡nHã¤Æm%¥/¸¤¢z à£Ý›Ø> ÛÂ=TB‹WuMöÕÏÐp°˜SúýkqTý•[*á¶QI7T0N€® ‚þÚBc½‰Ëà ­ý‡\€MÞœtµ”­¡ ˜1åS!lȘ*‡QÁŽcö 9þàh *å xÚ¢ðRˆàšh`G.+’•ƒÅe FTlSš…WÐà#a2-S}ßh&Cz0›õQ!.¸,À-‚CGv¥‚>óÎØ“Í$%+ع†0 ¦Èaïxц¨¶ç+ô€ ø8p‚ú£TÛ6‰Û†>O·ùgI<õ‘uÝveW™,ʼ:10Q¢ÑúÁ »,ã%;YƒØ‚ ±ä+ô$PâØdhh€à¬ã= û.™æMI@Q×¢ò‚È­ÝŠ†J(½ŸFß6Q›Bçd›Å,eœC±`ÍÌÉ#àA€ièÅ¥‚iþQØ„¼í9¾¾¯vLs-CYk¢…«ì­Q)„ÒÓ Q{=d´p‚f "3j¦H»—H†„\#m€„€­R®ZHâxU†YzìÙå]ì1Ô¾bähðÈ©¬GÜðƒ,.€gÉÞú<äÞµ‚l¨ˆeãe¦è@z‡wb·ÞÖ„­­àÁbø¨G­—.ÞäýÅÜÖí¬âÖÃð‚zÄJu[|®2ö˜Ÿ·Í¾B/á/ȆUÊaµ‘ÀÛÒÌ6ÞTPþkmɲ…¸ßo°*¨/Ï=OhFï¨ÒÀ{‡´ÉÊÀ£[QÈ»(à)µÁo˜þè¢ þA´8ë- ÉÃz­<£[nˆ†-p º ÔFmÍ€QŠ@×t€ÿ@i*pZàÁ Ð:µo±žl}öY ŸéØè‡¡rª¤¡[hÀêú€ƒHƒ*øf(8VèÎØ‹=ÖUnRòÞmݧŒšÖ­s"Ïk´ð`_ð g°‚v…W[,#€äÍ+91a'ÞrÆ®â€Ô›oá†jXÕý ˜.Àiœ®+ šú`]6žè‰¶î!ÇëbU=€E—,H*€®?ú ëù€$0 @¬sÛ¤‡xH™eÌ ·tÆZ=-¨fVoVþV†Êœo:½á…ßš<:(®ÓsÈ=#GpήõÏs«Q×|® àAb¨_å¨Á,el*JwÐ%)Ýwpög‡vþš®Šø¢ü±õ©T,ˆ7`€ÁÑ­QM Õ8 ¸[è…\ÐD=GN[gFˆ…ÐìüÎoÌYðÀ&ô*x†ùÐÝ¢GïÑÍ…<6øôlâ‚È‹a4Ã^ÅévýeèEQÁO(=6p_ ØAÉR hyÎoØï`z6¹'€É–yåê-À†bÍŠPÁy_ÌrÓùê¡Û°Òõ¢ŠþàÃïA…ùþŒH€W ŠaàÁXp€›ªx€àA\€!€‚o*Ђ“ºz€gP ‚o—”¼ßÓÛ/3Í‹¼×ûäGry€j¹?}põú°„˜¸Åàn%³ò0Ùµ—, ‚ÎÇiGp€ZP.%g:‹H—_ ý'ž[uc/€x|ôt…ú°Dàس~˜v- ß*p\àî D¬›dxÈN†®€ö‹GŠlÝàÍ“6@½yó"œGOŸ¾~þüý˨q#ÇŽ?‚ )r$É’&O¢L©r%È‹ûÂ{×[6þ¸DØðáÌBw~Þ±sè4žy9Pl)Ób ž€áõŨ±š2ðå6lÙT|¡‰ ¯!  ‚Û;‡ô¨ Ho.]Šû.bd©w/ß¾~ÿÖ‹W.¼ÂÙ$‹Hwç;šB-òÔ šW"°=Û` «-Êž†âYKbXk9 Œ³›-2¹q m¶×nïàMÔÞ>о÷ݽø/oàâÆ#Ooï¹ó  pë[ŸóÆÙºRöš›*4•!HbºX­^(gËF¶h+.Œ/v˳ÁÂôž9yؘæu¯lRôÎ[ôÓpÁáEœr 2Ø ƒÊ1Ü[^ès þ?Â4SþqÍ_høÌœ…ÂkÙöNÐðððRß<¾óuó¼–l¶IT¡?$4 ‘"™¤’K¢”à™ p;Â3lWvóÅÙìw]3Ò4Ív¶!¤<°a“ŒVœ·][ví3ÀD½#“mIDOpÐ4ÍF *Ȥ ƒÚ ? @‘pÃ]D=…Ù™â;ë¦!v]Õ‡=[ìf]WŸâ¤Ó*póL…)¦'‚ ¡Q …«¬ͣūŠJx*ª‰ ÂCUòçc7Ýä¹)^Ók?¶%p=cë”ÓUK<tÛ¯¿ÿžäÒ½¿ ø ¸¿Þ¦X…û°KeL·ÅãÐÂx½C‚”"ø*ÀsÜ1£b¼O?¾3å\õ„›§… î\-êÏ©èpãœs·ŠÖ|§÷FÐváÅîB¿<±‚¾fijÍ:Cõ¬Äñü "\rÆÿ< to'¨‘ZR“]v¿OP…«Râu3F]³àÍÍe¶ÝwkÛM¶ ×7qO6Msàx^ø¿oxK†3ÞxÇþà¸ä“çüå—cž¹æ›s޹矃ºè£“^ºé§£žºê«³€Þºë¯Ã»ì³Ó^»í·ãž»î»ó޻ðÃ_¼ñÇ#Ÿ¼òË3ß¼óÏC½ôÓS_½õ×cŸ½öÛsß½÷߃¾øã“_¾ù磟¾úë³ß¾ûïÿüóÓ_¿ý÷㟿þûóß¿ÿÿ0€  hÀ"0 \ èÀÎ;rabbitmq-server-3.2.4/plugins-src/webmachine-wrapper/webmachine-git/www/images/blankbox.gif0000644000000000000000000000223512305126066030617 0ustar rootrootGIF87aóáç·  !!!"""###$$$%%%&&&'''((()))+++,,,---...///111222333444666888999:::;;;<<<===???CCCDDDGGGHHHIIIJJJKKKMMMOOOPPPRRRSSSTTTUUUYYYZZZ\\\]]]^^^___```aaabbbcccdddeeefffhhhlllmmmpppqqquuuvvvxxxyyyzzz}}}‚‚‚ƒƒƒ„„„………‡‡‡ˆˆˆ‰‰‰‹‹‹ŒŒŒŽŽŽ“““”””•••–––———™™™ššš›››œœœžžžŸŸŸ   ¡¡¡¢¢¢£££¤¤¤¥¥¥§§§¨¨¨©©©ªªª«««¬¬¬­­­®®®¯¯¯°°°±±±²²²³³³´´´µµµ¶¶¶···¹¹¹ººº»»»¼¼¼½½½¿¿¿ÀÀÀÁÁÁÂÂÂÃÃÃÄÄÄÆÆÆÇÇÇÈÈÈÉÉÉÊÊÊËËËÌÌÌÍÍÍÎÎÎÏÏÏÐÐÐÑÑÑÒÒÒÓÓÓÔÔÔÕÕÕÖÖÖ×××ÙÙÙÚÚÚÛÛÛÜÜÜßßßáááãããäääåååæææçççéééëëëìììíííïïïóóóôôôõõõöööùùùúúúûûûÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ,óáþo H° Áƒ*\Ȱ¡Ã‡#JœH±¢Å‹3jÜȱ£Ç CŠI²¤É“(Sª\ɲ¥Ë—0cÊœI³¦Í›8sêÜɳ§ÏŸ@ƒ J´¨Ñ£H“*]Ê´©Ó§P£JJµªÕ«X³jÝʵ«×¯`ÊK¶¬Ù³hÓª]˶­Û·pãÊK·®Ý»xóêÝË·¯ß¿€ L¸°áÈ+^̸±ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹Mº´éÓ¨S«^ͺµë×°cËžM»¶íÛ¸sëÞÍ»·ïßÀƒ N¼¸ñãÈ“+_μ¹óçУKŸN½ºõëØ³kßν»÷ïàËO¾¼ùóèÓ«_Ͼ½û÷ðãËŸO¿¾ýûøóëßÏ¿¿ÿÿ(à€hà&¨à‚ 6èàƒF(á„Vhá…f¨á†vèᇠ†(âˆ$–hâ‰(¦¨âŠ,¶èâ‹0Æ(ãŒ4Öhã8æ¨ãŽ<öèã@)äDiä‘H&©$O;rabbitmq-server-3.2.4/plugins-src/webmachine-wrapper/webmachine-git/www/images/WM200-crop.png0000644000000000000000000003445512305126066030555 0ustar rootroot‰PNG  IHDRÍnãsRGB®ÎébKGDÿÿÿ ½§“ pHYs  šœtIMEÙ /d]~. IDATxÚí½ÙËž˜÷Eäž•µw7›½l6ÉCžåî÷ÎÍÌhd€`²``<º°½È/Ö ðŸz±l6,È’e c Ìh4ËÝeÎÆ}ï}­®½r‹ðCv›;ϹÝ\šñdWWVWeEF|ù‹ÈÈ_­µæ9!ûý/5 ïqºÍNÿL”¾‡ëÔßÈ>Hs ƒÁ`0â1 #ƒÁ`Äc0 F<ƒÁˆÇ`0Œx~I´Öãyž›1ŒxŽŸÃ“*-Ë2“* #ž×ñB&ÎDXm¼æý%…M¤c0‘xž”ÏÒ©F.¾gÓ—¿ý^ØáËæF:Ã×ã…­&Ë2~ñ?àÞJ Û¶©F.÷þÞ y8B2Ò1Ž8âQZ±7ÚåÒ‡0LÛô‡®Å{-ƒÁpÌ≳Ÿ/ÿÛ²q-­Þ‹—¹~lJÍ`0xépqê2ŽåÒ»L”§h„¦Ä Ãñ‰Ç¶fëgÐ:Á³¶©–L¤c0ކ—ŽŽf*¦¯˜’2 ¯O¸ò1¹R C:í=‚µ•šS“|üïâ‡Ñ¡“žDé!;ƒÿ›Áú¿!òÎ0HV^Òd¼ Ìá}ÖJÓÙ“´vÏÒœZdg¥E”R‹<¤,ºy¶²½»Êõ?ü—\š´q,AUX s­îã! â³øTIé4Fö^åÕ#žáhÄ[÷ª?(¡•"SÅK²\Ñë¶mX\˜§ì)Ô¨C©6I:à•Êãñ—w¦÷.mñ^ñ ¸so™‘ò÷#žeNŸžÃ²mÚí=”ÊÉs”¢ˆÜ~¿‡e—ª¥A‰v{Ʋl„°‰ã!Žã†e„%éw»ìííŽ#ßpn!Ç÷2&Ê?|á@oœ¥1%¯„h…”Aœ$,-o°¹—D ²<i–ûH5bñܵÈÅÊúh¥pü•§¸AÐHûå™)´R¨î&ÙÖmÜÅ_{õ1žÀ÷¹ri/®ßf8Д¢2äŠ\)z¡£Y8¿€´Ãö:¥ëlªËvбÛfúòw * Sc 'gŒGi²\!3M®4™RHÕZóQt¡ZkJQe<ŒÖäJј˜_åÒ@™Êþ1…VOŸðl+¢}@¼¸ë’«”Íî&77®Rñkd*-r¨Ï|›ZXÇ÷ÎÌÍ ô ­ªµ r¥ÈsEjÀùs ¸¾‹Ö){«èï®í_¹²–…_®3}ù;XŽû’¹(fD[ÎS'õ—.{žÇG—/òù—7Ùkå„Q™ÖΡ«YXXÀ±õ²Kn×УY’a¯T&éwއí¦¦Ny®Q¹&Ï÷kP*ýÄ\­Ñ¨qGD«q'ä±êq7I€(B!Šß‹±&ç%³^BRñ«\œ¼ŒÒšaÚDZ\|Ç?Ô¦]ÎÍÏ¢Ô2k;[D•:½^™÷ éxåÀÆ·-˜<å¸Å>‰V)nXAZG—‹ë¹ïä{.ßøèñÅ V–v˜¨E,,,`Û‚zäâØN¹Ž_®›i8ñí^Ï pÏÔDÃ{…m[œžžfjjšþ(#Ïfà1Ð],ÐZañ9^£e÷èèÿ‘Àù[Ô¢¿Šç¾þYþÏO}šŽ¸»uß P¹bg°É‡§¿EµtÙÔDÃ{‰%¡¾Û9Ç•1L6QJÞÆuðú{0Ï-ÅÀ øæÜ÷q,›A2ࢼBÙ3³ †w[ž!“•â9MªáÞÌ°É SŸ6£ ”‘ç÷¨Gß6GÍ`8h´Îy“SÖ^:Ó/WÃtË+ƒÁðúÄ£QŠ{; ƒáX»ZE´3àáÖ?c¹õÿ§ë¿uÂ"N#Sƒá­‹x¤p¨†â:.Õðƒ“÷í…Y‚Ø`xëÄ#„Cä~B%ÿÏÜSZƒáøÅ3¹zý!íÎW¯ß.®ýïsøña²,ÛOçøh{žç$iòØß‡·+­HÓ¥Tñï] ƒ÷z¬Ç¤5išîçëá©mq?÷û½ˆƒýÊó¼˜ÿŒËŸW/ìé½`ß †“Œý|錸vë.n©I%ÙÝÝæËk·øèÊEò<çáÇÌḬ̀±¹Vš<ω¢ˆÛ·oãº.Y–13;C§Ýass“ápÈ… p‡Á`@½^GJ‰ïûì¶ZÜ»{—?üápHÇxž7Î/âíç¶ÝÛÛcgg‡,Ë8sæ žçÑét˜˜˜`mmápÈää$ŽãàyEb±"ka‡ó 4›ÍǤsAMÐ+D@„ïûã ŠW¯^¥ßïS«ÕØÜÜdrr’(ŠÆÙ¥”8ŽÃ_|A¸Ÿ• À¶múý>.^`mu ×u h­±ö§£Z–Åææ&Ÿ|ò ¥RÉÔFÃû-žápÈÕ›wpÃ&~’¦9~P¦ÕióÅÕ[\¾´@»Ý¦ßïsýúu¢r™™Ó3dYÆÖö6R :I’`Ù–eñÙgŸ1Ž˜ŸŸ£Ñh2 öShÇaww—n¯Ç`P¤1í÷ûضC·×ű„ä¹Âó~ò“Ÿày>SS“h!°m›N·Ë`0 \.3Žô{xžÇ‡}D¹\¿Á`0nèÒ9xÇBLªøãC™œGï=O% ܸý€ i ¶”Å’R’)EädTýœ…Ù&iãxºž¥A–¦!‘–@ Q$½V ­žàØHH“­4ŽëÐÞÛÃq\\ÏÝÏQ¢I³lŠ7X¶…%$Y®ŠTJ„!Ãá<Ï‹”§–E<Ë–¸¶…Ú¾MºüÉÂoÐ8}þ)é<Ö"2â1â9±$Y‹öàFqáÈ>â»´"ïl’íÜÅ;ÿ—^-âÉóœ­í]ºCMTXkíú6– â ×±J>¼E¥{‹™fð(ç¨ÙõŽžL$ *)­‰9¸Ù®Hqšh$ãlüïm?#¯ëáOµÆ[<ÊäïŒÿFª”léSâŸþSþ yý…Òy´-25Ô`x]Oš¦Üºó€Ý¾¦Zo’g9™Ò FÅR§ýöͪϙ3g‰|Mº»J©9M:êáEµ"ú±läÛ´®•ÎÉZ«äíU¬¹qÜŠ‰xLÄc"ž·%âp‡‹‹ç¸vë.­*µEàÙìlnШxÌÏÏ#…B {lßýœë?Ãòi­‹e;†ÑSòÑD„a‰á oj¨ÁpLùðßøÐâì™3Ø–¤Vöpì“s¦O’7oÊô7ÿCV6”b¨6±á‰‘ŽÖŠíþ&··nPšäýãÿA¶†ï›nÁðFºZÍ(²ÑY¥3jÓ{ô’6ߘýõ¨v"¾x®Ýa‡µö Û½ºq ´f¢ú[8û ± †×( ò+|ÿܯ!…d”õ±¥Gàœœõ²,i1S›gª<ÒÙxñ2“ÞÕ`xƒ]-[Ú”¼×dÙ-Ê~ûEg{„®‡V›X²MÙ7Ò1ÞXÄs¥sÒ¼wb @JÇèÜTƒáG¤}F”J¥¯uO–RŠl?ß’”)å81œÒŠ4IÑZãºî¸¼²,ÿ Ãpüü3Ï+‡ŽƒÖš4KI“Ôd|4âysÒy¸¼Âö^ÌÔÌ I’qou ÌÏÍ’¤ Ÿ}úÝn—z½Îúú:͉ ¢R‰8ŽÇ•¹R©ðÅ_àyõFƒ<Ë‚€$)rL_¸p$IèõŠlˆ›››A0εœe¶mãû>IšðÍo|óÕ"Ö·ï­1yj´vwùòúm>º|,ËY^^æúõëÌÍÍ•+‚  \)³µ¹E†ø¾Ïµkטššbgg‡R©DEE²6­‘R„!ëkkãï\«ÕÆéh;Q‘e|ðQôt£ƒr:|#n©T§†mµZüâ¿ ÃqÞm)%“““ôz=677ÉóœÓ§OcYBòK’„N·K¥\Ævl<×#ÏslÛ¦^¯³¼¼q’R)— |ôÑÇD‡Ò³¾,Ò¹yw•úÄ I®PJãø»Ý=nÞyÀâÙylÛÆqó"£Fõ¶þÅ?ÃYüËô*¹³¼ƒ šÜ_ï2Y Ä)‚"y| GL•aaºB'X–Dkè÷{´Z»œ9{¶¸%Dt?–´‹ÏÑš,M‘ÒBZ•k,ÛB öWÚPäyŽ¢øîŽ!A ÑÃ6ñ½?!üþ‚”öSÒyü[ìdkú]¾·…·2ØI'Ks6·v +Óhý(ÏóœøÎ¯3*GxY‡Ak“RcŠdØ#¨4hœ |mgl%8§?Á>u‘J×oߥÛï°8× I ­¥iN–e :Ûœ¹x…žÈ‘ž (¨,Å-U‘R`{þ±í·Îbœ¹o#üò¡¨Æ¤—5ñ€”J!_^àÓ/ï…8®‹”‚~¯GÜoqéâ"žãàÊŒak;Ÿ³}Gãeâ^7ˆ8󽿌¼ž+#ÂvqN_À‘pùÂ_^¿ËîÎ6åJ­¹Êhï®saaž’ï2X½ÁNo•°•%µ)æ>ùU,Ç=¦ýô°gÆ‘Z¹\¦×{vzÙ(Šè÷z¦ñ¼OîD¥ßüh‘_|~›Äk µz$Ï£Ú”|ïÔ”ß|99YVŒçضÍÎnk¼ÝuŠQ#/,ã…eÓ"ßÞó¹ë‚(òùáwçøæ'§)•ÐKçmÇql¾ùñY¾ÿ &“ŽE9tߺ³m’$¢´b­½ÂÏü9ÛÃm[l o`;oÿêZkö»üäÞ󰵎å5Ø\Ãrâ·î®‰Q6äîÖMNÿúüW¬î-³¼»ŒÖÊ´>ÓÕzÿÐZ“ä1©JÙênж°-‹³gðÞþ½'ÍS”ÎÙîmÒuHó˜éêðvuWr•Ó‹» ÒA±¯q‡‰ÒÓµils³¨Ïû†%-æjg™©Î‘©)@×zûW˜BÒŒ&©†u@‘ç1Rúo徇NÈ•™o uNš ±­ ¸uAšû“MWë=–-qò$]{'¤3>pBâX6Jué¾Ä³½·òJŠ×r‘$ÄÙ=,‘àZžiy'¿Ka"žwZ2”¶ßÑ㛣Þ̉Ådi…6ÓOhCR¤qLžÅ8^ *³F<†7-œ$k3H6p펽“ss Ï'KbZË·è¬/ay>BZȇ÷q£* W°]ßtµ ¯¥Zý_pcí°ÚúÿLœ@„´ð¢ ~¹ZämòBò ñŽ­ét{ܽ¿N.Ÿþ9Ýn—F£Áúú:®ë233C¿ßggg‡<Ïñ<¯¨°¶]Üä[.óàþ}*• ®çá:B²,ãÔ©SlllP®T¨U«lmmÑn·Å1RR›™™aii‰4MljÝÄþ¶r¹ÌùóçÍñûªÒÙÚfe£Ecê4JA·«¹vóW.- µfuu•n·‹çyF<†c³nÛ÷WnÇ „´Á-sãîZCT ©Õ'£)mJå*–%iµ;¤iJT­a[6½^ÝV‡j½Bµ\EJ›0*“dšRÙ£?’ç)iš11yŠ$ÍiwºDå ›ÛŒâQ1§Èu°\¤E¦`0JÅ)Ò’8®ÃÂÌÕŠ¹YõëHçÁÊ.nÔ$I…í„tz_\¿Ëå‹gð½€V«C¿¿gÄc8Ž@GÓév¹sáV¤Ù`ÄVk@® ËÓõ:×n-siÚãâ„ *Ò2žš-º=*GŠ"¬e[ ›(­h4a ÎFØŽ½ÿ™>J+„H1âÔ¹*–ÕcâÔR°ŸçYi…e ˜XlÍbfÑþ{ÐÙì)ûjdYÆæÖÖZ·ÆN{D’åä¹.®h!Òã‹ë7¹°±pÑGÊЈÇp±Ž&Í2â$# Fý˜ÁHzý8ÃF¢ cÅÚÒ*Ó>ÖÁ¬kK9y„@B©ý²ïýè3¤¨C‹¿LMT³³3¸–—Šn·E{å6»÷¾Ä B’~hò43ÿÇ L¾Íòq]ÎÌO£ô*«ÛÛTëMr­†Ä½çæOS©–ñ"c»»fÄc8fùL4øÁ—·W°½*£a÷‘tlIµäbK3 DÍÓÅ8” u‘bÖHçÀs]Ι½Êƒ ¼ LÜ?Ne?3¦‹ÆæüäE#ÃñËgr¢Î•ò‹/¯211Ëìì,®-¨Fî8¡ãF2'@> ggÈÕW68¿pŽJµ<–N1Ø, Ý’áø.X¾¡IDAT¦¦jüZy‘,k`I‡rIbI3qþ¤á¸só9"¼M5ú„Àµ÷s€?þ:#ñ2LÜÙ¾IœŽhDSŒ’‡¸–C%º` ç§»,íüK6{?áT훔Þ™Ž×ˆÇp¬èý <–´Xo/3LúLU¦‹%}Í媇%}êÑ·pí:ž[}np#ñ¸!W¦¿Ò)iÞDZJac=#U‚átµ¬2è»xv’7÷Ü×™N¶áX)f®J”2ˆo¡ÔÐHçDG¸ ­Ó—fÅ4â1¼6!„0Ò1ñ^ÇYP§ “öz_ÐÝ1kjŒx ÇÒ9½Ñ=înÿ¶»?1ƒÊ3¸l8~®t,Ný§*¿0ç;ñ˜"0WK3êì,“Ξ™l0áØ¥£híu¸·´‰L²´ÞAk˜9]Ìå‡ôz=<Ï+²z.¶mã{>ý~Ÿ~¿‚É©I´ÒÄIŒ@°ÛÚ%ð‹lŽãŒ3j­Çs„Fãш0 q=)$I’ÐÚkQ KDQdá¤JçþÒ:a¥‰ãx —«» ajj‚ÍÍM®^½Êää$÷ïßÇ÷}|ßÇó_¦ÑhP¯M¢µæ£aks‹À/!°)W"Î[ 0ÉÜx 'O:­½w¬â„Mº#Eªb¶ZCâ,G"˜ª×¸ùp“³3ŠÓg| ¦qÊFc+B\󊧕Ù&j¤ ‹+d:aZ{ }Ð=´î"lÐ æÎ æÎ5PJ#¥F£Ô=z ¼b¦A!q¬ ¡7cÆx o3÷èäJ‘åŠ$É(—\ìQJ¦Š¥dÒ4§ÝË©5Ž%±/š\k´z†T‘žÍãYJ÷§ Šç¥(äsð\ñX Ͻ‡èY¤y‡þè!žÝÀ¶Bspx o§tµj…ųšwWˆ‚:®’gŠ’g3ŠSºm¦'›LOŸÆ‚TuYÞ{Àd42•rª2ƒg;oüû$Y ¥sL.f#û ŸZ•KçáÚí%Ò¬ŽëyÄqB·³ÃôD©SS8–"ô%›Ý.ý¸M’ ÙéoâÛ!õ°†gWß–¤9¨F<†wE>õZ•+4_ÜX¦? È“ÁX:ž-¨E.RJ¦«³œªÌ ).‡K!q,Çâ ÅŒ”^ƒ|j|táN÷§j!S§Náí§>•ûYmiãX®åâÙž‘މx †¯JS’QŸz¥Ì>9Ïțۢڇ®XŒx †#B«œîÎ;÷®byZåHkéºx³ç k¦LWË`8†3›çãE5´R¸A„V)ä)Â2yyÞ`!,¤xsÍßD<†ã«ÞÒ¢TŸ¢TŸBç)jØFU„¿ykd"ÃÉîvÅ=²Í›èQÏÆÛñ“t!ÄK¥f"Ãkªë¢8Ï 3 ü¦ÈUÎ é¡uNè_²<Å>¢4ËSºqÏ©„’å)BÈgæØ6â1^*î!½7{7|œ¸³}“ö`Ð-ÑíQõ|sþ»¿´|4šÎ¨ÍgË?Ãs|¤°é wYœ¼ÌùÉ‹F<à øä›×r,—Ó•9N•g¥CêaƒÐŽdÕ pB.L]Æ6½¤K³Ô¤Qš0]-ƒá‰ÇñÞñ8œªœ&Ë ã”rxîH¸!sîY²¼Gi4¢RZ|îkx †÷ˆ$MðÝÒø÷,ÏdzÇùÄžÒÚˆÇ`x-ÑÍ~ãWð4¥R‰~¿?nüë´Ûm\×%Ë2šM,i±¼¼Œã8ôz=\×¥V«099ùKgL,¤syõ€Û²Æò‡,--àº.I’ e‘.v4Q1;;ûLY=’Nïÿ0áßýY)ÄX>n‡÷àÁpœÒ9x<D!Þ’•}zOÉç¨ùwæŽß_ A¦rú½>7oÞ¤R©ñ ¯f‰O7­SFi ßi"¥ý”tËGó6äxî=ã÷èHß{vN±²,—›´èüè×Dà›ˆÇ`x)Z+ât½?Ķ_ž'Í{luÿˆ “ÿås¥sX>¼Qùô^ð|t$ï}z6geÙzæûÿþïÿ>¿ýÛ¿ ˜1ƒáºO[–q¬ ®]{l›÷(yçür!)¢çʧØvR‰ö#ž³ >þæ÷ȕ’҈Ç`x9Ç*S.<%ÐÔKŸ „…Öšr¹L¯÷´|4QÑïõÞ9<[ Gñþk+½g¾÷ÕÛ+„åi¦±\ñ ¯ÖÝB£2Ç?ÑâQ×¢Ûí Š|4•J…v» @«y‚þö ­¥[¤£NP&´ñ«“L_ù.®ù7(îF/äóƒ_Íùó?µÆbXÝú6•Ñzx‹îÖ Z+,Û!KF”š§™¾üíñ8Ö“äyŽcÛOÈí‘tê:•ÐÁw-ÓÕ2ŽERZã8YV4<Û¶ÙÙm·WK.R j§ÏR95_,"vp)Z¤<Ž”!¥ÕX>þ§½§¤Sl„p˜¼ð1ç¯PÜC®@HŠ@ž?ßDz,Ò,;$ž’NàÙ‡bHƒÁpä$Iƒ‡÷øñÌpc[šÚ8ó¢HËFÚNñÓ²I:‡å£‹F—ÎþT!‘–ƒ´¬â§´^i’¡eYã‡þ5§¤c"ƒá¸š¸ÌÏMóÿÑß§?ÚÁ„¾@¾§z¥5Jiú£¼—:$¯å)’AÿéQßzJ:&â1ŽLelvÖ¹ºv½Å0KiÅIÕè­ÙG)åЦRr~iéäIL{õÞSÏ·nÿŒ,~ú{›ˆÇ`8òˆB1Hû´‡mzq—ΰƒçxÔ‚:ž}2×l—–MPúNt¿Ò@:ŽÁpÜ8–Ã\í 3ÕY2K:¸¶wb¿³´Ê3O=ß<{éÙ¯7ÕÄ`8ZÛr"'I€îàÙ>“}шÇðš[£@Ø.È÷)ÈÖ(£unŽ¿áµ7¿tDºò£Oÿñ?B+õÅ>¥3S Œx ¯¿–Yè<%[úSTñž¬ *„@‰xžÄ .Ž¿Zöé±þÒßÃ[ø¼Wcf\ÇD<†7B–e¬wŸÇ³ÜߟsÏ“ÁD<ÃJgsk‡Õ6SóìuÚܺ󀋋gQJÓív‘–Ķmò,'Ë2”RÄqL·ÛŶm¦¦¦È²Œ••”RÔj5êõ:I’Ç1µzqÇø ?`mmz½N§Ó! C\×%Š"Z­Öø&Ís çÐJÓë÷ƒååe|ß§Ùlâ8Å„:­5ý~Ÿö^›éÙÚ‘L²3ñ^›t¶YÙìИœFkðKv»{ܺó€³ó3t:z½ëëëlmmá>““ÄIÂúÚÒ’4ê †Ã!q“eÅ@íp4b¢ÙäüùóÄqÌÎεZ{÷îÑívY[[߬éº.IšÐïõQJñóŸÿœ hÔLNNÒéthíµB†!RJvwwi4›œ=s¶ø2ÚO#ž#FótvüweôàYé8ߦHçÁÚ^©Á Îh÷F¤™¦?¤YJž/3=Õd8ˆ™›;Ë™³ XÒ¢T*á8ý @“eRÊ}‘ب\1Šc\×¥R.E%Î[`4J¨UxžÇââ%Ò4C«â~$زXÉ4IlÛ²lÊå2v›4ËÃÛ²èt{,œÓ”¢ˆjµ²OghÚ‰ÏQ7^,v»?c?<ò›&'ÏúXVé±¼-GóÞŠ<ñœÚ[U¦J+Z{mî/oRmαÕàÙÃ8G A๸ËòöƒìgÏ>J'ªµFkM¢Á­ ÐOôþ±ÒûwW<+ͨ_Œ !À 4ˆÜ€§ºHúÐû¡5C nuÿý´&×M£”¦5ÔdÙTÃËÆF@¶¸òAùÄÙ^ëânm¥ÕxÝ¥ÃCi…oO¤4Žx°´J¹6I<²¹µËÙ…sd3Uûi-Š:Âø±¶'Ч§ÐJ¡F ­Õþöƒú¢Q9 Msvw·¨Ö›¨Ñ•rÄÄÄĉ’ÎáÆ[$†ãç¿æÉm¯²ýeÂ9ü9¯*“—½îßüíÏøÃßý€,Û•i¤ý´dífsr, ö塵G6‡+z_PÏ–yT¹„³¿(<ûâé´Û4šŒF#ýmÚý”Jx²§ËçyÎÒò*[»CfΜc¯Õâ‹«·øøÃ‹Hiío_bg{‡~¿çyäyŽïûH)©V«Üð€J¹L£Ñ`4Ñív ‚¥3§g˜œœ|#ÆJÔM†Ã!I–ÑlLŽODúP)êA‘7¨(“ý:vð¥ÇòQZë_–¥ã¼<õÆ{;9»„r5ÇsN~7íÉþ¤\^¶ý¥cn‡^søýžG”ö+ÉImÃoý«EþàwïðoÿóÏùÑï}B’Å,-/Óëvq™eY®Ðò\£´ $WE2$}è,–T@åŠ<Ïɲ¼ø]éC‘PQ™r•£”"W ­r2¥Éµ8ÑÉ÷óÄ¿øë 䉓ÎÒò›»CªÍ)î­ ƳL!¥Mji>ûâ_¹È… ÙÚÞfvfË–Ôëuò<çÂ…K¸®ËúÆ:Y–Ѩ]ÓÍÍM¦¦¦ˆ¢"‰ùë$Nwè o"ó3hi¦ÈrM𦬬®±ºô×(•"Tž”"¶·6©Õx¾G<ŠÅ1½^Çqh4§HÓ„õõUòLQ®T¨Ô$ñˆáp„ãzãîú~Í9ñλÒ-|‡¥sX>ð»wøéß½Å÷þáEæçÏ»Ûí¢4ܺyƒ½½]”Rœž™c8Ñëu¨”kÄɈ$N–…Ðøa‰³gÏ3Žè9=>ÿôçh£ÁiYLNN±øÁGaé°Z±–þ õÙ?§/@õþ ÞÉ”@R fúYÐjîåg™[¼ÂÎ^Ÿv/Áu$½aŠëXÔO•YÛX¥÷éÿ΢K8a!´@¡édûƒ™B§§"q…`°Ÿ‰¯:m1P_Òï¾î3¦¦?zÈòÞÿ‰£ÑÉLYÍ’åEªP•+vvwQDdAÈü™³Ò²¨5š( KS¤°Hó ÇvÈ•&KS,ÇÆ±‹U!ÞŽê*ÑqÊðEãGy?õÜaéŒõäž#M-ü ¤TØ®¢Qøa‰ ,+Ú£BET©¯zdÔ˵F+°l­5sçÎóx'\+Eš<¾cÚö‘g¿KXúÕw2|ViÌÎû¤£þxÀ]X¥ú$Ó—¿‹ëx,.œáæ­{ìö÷¨Ö'ÈóœJ(éõ{ û->¸¸ˆï{Ha³Ý[áÆú—ÔKMò<#Îb¾sæW(yoWšÔ(X hwº(u‡ýÁ€8ŽaA¶w)mj³ç©ÍžáëÇæƒ è[w¹»tŸÀµ“N)(º˜å)&ÊSïNħq<"étÉ’n—N·7®/‡§a|­º$yVÔø~HÇ'füãUúW½|þU%ö¬ùBGÑíúõÿéþèÇŸ…ó,é”Ü»·»v̦UÔ+>£Î 8ujŠü=Y:Ûql®\Z¤TZE:ž÷¸tÞEßcnºÁÚÖé0%ô$ÝÕ#?;»2E£Î&eß#,…'J>Ïkôϒ˳¤ò²íÏ+Wx|ÒàWº^9ýèÄß,±º´Âì¾õ”t°ø+ß{-¬tÑõRJcÉ÷gÕÛ¶X8;Oœs]Jþ»}w¶ïû\¹|‰‹5A½ªƒ }´•f\_Š¡ŸG3»ßu^µ¡¿ìu_WÄ/û»V7{i·ëyäºÿgêϨN\¦äן’€Ý¬¸ŽY¼€ïž¬·¶%h”?rÓœø1æ·Žzù럳|È`´Z7¹c7Ÿ]L1ÞviŸ¾Núˆw."v'Y˜úz£ûTßû:³ ŸÁ`8†8õÅÝ9ñ ÇÌþi‰JpÑ„‰x ƒÁ`0â1 #ƒÁ`Äc0 F<ƒÁˆÇ`0Œx ƒÁ`0â1 #ƒÁ`Äc0 F<ƒÁˆÇ`0Œx ƒÁ`0ñ †cDk4/^Jæÿ¿7B4µÄIEND®B`‚rabbitmq-server-3.2.4/plugins-src/webmachine-wrapper/webmachine-git/www/reftrans.html0000644000000000000000000000620612305126066027577 0ustar rootroot Webmachine's approach to resource functions and referential transparency

    webmachine

    Webmachine's approach to resource functions and referential transparency

    Webmachine goes to great lengths to help your resource functions to be as referentially transparent as possible. By "referentially transparent" we mean that given the same input {ReqData, Context} the function will return the same output {Result, ReqData, Context} and that side effects will be insignificant from the point of view of Webmachine's execution.

    We don't try to force you into pure referential transparency; we give you as big a hole as you want via Context. As that term is application-specific, you can put database handles, server process identifiers, or anything else you like in there and we won't try to stop you.

    However, all Webmachine really cares about is the rest of the terms. Since resource functions are generally referentially transparent at least with regard to those terms, many things are easier -- testing, debugging, and even static analysis and reasoning about your Web application.

    Note that there is one important exception to this. The streamed body feature exists to allow resources to consume or produce request/response bodies a hunk at a time without ever having the whole thing in memory. While the continuation-passing style used in the streaming API is friendly to general functional analysis, due to the necessary side-effect of reading or writing to sockets the stream bodies cannot be treated in quite the same way as other uses of the ReqData interface. Luckily, it is easy to inspect a ReqData to see if this is the case in any individual resource or request instance.

    rabbitmq-server-3.2.4/plugins-src/webmachine-wrapper/webmachine-git/www/example_resources.html0000644000000000000000000001617112305126066031502 0ustar rootroot Webmachine examples

    webmachine

    Webmachine examples

    The simplest possible example is the one produced via the quickstart.

    For an example of a read/write filesystem server showing several interesting features and supporting GET, PUT, DELETE, and POST, see demo_fs_resource.

    For a very simple resource demonstrating content negotiation, basic auth, and some caching headers, see webmachine_demo_resource.

    Some example code based on webmachine_demo_resource follows.

    The simplest working resource could export only one function in addition to init/1:

    -module(webmachine_demo_resource).
    -export([init/1, to_html/2]).
    -include_lib("webmachine/include/webmachine.hrl").
    
    init([]) -> {ok, undefined}.
    
    to_html(ReqData, Context) -> {"Hello, new world", ReqData, Context}.
    

    That's really it -- a working webmachine resource. That resource will respond to all valid GET requests with the exact same response.

    Many interesting bits of HTTP are handled automatically by Webmachine. For instance, if a client sends a request to that trivial resource with an Accept header that does not allow for a text/html response, they will receive a 406 Not Acceptable.

    Suppose I wanted to serve a plaintext client as well. I could note that I provide more than just HTML:

    content_types_provided(ReqData, Context) ->
       {[{"text/html", to_html},{"text/plain",to_text}], ReqData, Context}.
    

    I already have my HTML representation produced, so I add a text one: (and while I'm at it, I'll show that it's trivial to produce dynamic content as well)

    to_text(ReqData, Context) ->
        Path = wrq:disp_path(ReqData),
        Body = io_lib:format("Hello ~s from webmachine.~n", [Path]),
        {Body, ReqData, Context}.
    

    Now that this resource provides multiple media types, it automatically performs conneg:

    $ telnet localhost 8000
    Trying 127.0.0.1...
    Connected to localhost.
    Escape character is '^]'.
    GET /demo/a/resource/path HTTP/1.1
    Accept: text/plain
    
    HTTP/1.1 200 OK
    Vary: Accept
    Server: MochiWeb/1.1 WebMachine/0.97
    Date: Sun, 15 Mar 2009 02:54:02 GMT
    Content-Type: text/plain
    Content-Length: 39
    
    Hello a/resource/path from webmachine.
    

    What about authorization? Webmachine resources default to assuming the client is authorized, but that can easily be overridden. Here's an overly simplistic but illustrative example:

    is_authorized(ReqData, Context) ->
        case wrq:disp_path(ReqData) of
            "authdemo" -> 
                case wrq:get_req_header("authorization", ReqData) of
                    "Basic "++Base64 ->
                        Str = base64:mime_decode_to_string(Base64),
                        case string:tokens(Str, ":") of
                            ["authdemo", "demo1"] ->
                                {true, ReqData, Context};
                            _ ->
                                {"Basic realm=webmachine", ReqData, Context}
                        end;
                    _ ->
                        {"Basic realm=webmachine", ReqData, Context}
                end;
            _ -> {true, ReqData, Context}
        end.
    

    With that function in the resource, all paths except /authdemo from this resource's root are authorized. For that one path, the UA will be asked to do basic authorization with the user/pass of authdemo/demo1. It should go without saying that this isn't quite the same function that we use in our real apps, but it is nice and simple.

    If you've generated the application from the quickstart, make sure you've added this line to your dispatch.conf file:

    {["demo", '*'], mywebdemo_resource, []}.
    

    Now you can point your browser at http://localhost:8000/demo/authdemo with the demo app running:

    $ curl -v http://localhost:8000/demo/authdemo
    > GET /demo/authdemo HTTP/1.1
    > Host: localhost:8000
    > Accept: */*
    > 
    < HTTP/1.1 401 Unauthorized
    < WWW-Authenticate: Basic realm=webmachine
    < Server: MochiWeb/1.1 WebMachine/0.97
    < Date: Sun, 15 Mar 2009 02:57:43 GMT
    < Content-Length: 0
    
    < 
    

    $ curl -v -u authdemo:demo1 http://localhost:8000/demo/authdemo 
    * Server auth using Basic with user 'authdemo'
    > GET /demo/authdemo HTTP/1.1
    > Authorization: Basic YXV0aGRlbW86ZGVtbzE=
    > Host: localhost:8000
    > Accept: */*
    > 
    < HTTP/1.1 200 OK
    < Vary: Accept
    < Server: MochiWeb/1.1 WebMachine/0.97
    
    < Date: Sun, 15 Mar 2009 02:59:02 GMT
    < Content-Type: text/html
    < Content-Length: 59
    < 
    <html><body>Hello authdemo from webmachine.
    </body></html>
    

    HTTP caching support is also quite easy, with functions allowing resources to define (e.g.) last_modified, expires, and generate_etag. For instance, since representations of this resource vary only by URI Path, I could use an extremely simple entity tag unfit for most real applications but sufficient for this example:

    generate_etag(ReqData, Context) -> {wrq:raw_path(ReqData), ReqData, Context}.
    

    Similarly, here's a trivial expires rule:

    expires(ReqData, Context) -> {{{2021,1,1},{0,0,0}}, ReqData, Context}.
    

    And now the response from our earlier request is appropriately tagged:

    HTTP/1.1 200 OK
    Vary: Accept
    Server: MochiWeb/1.1 WebMachine/0.97
    Expires: Fri, 01 Jan 2021 00:00:00 GMT
    ETag: /demo/authdemo
    Date: Sun, 15 Mar 2009 02:59:02 GMT
    Content-Type: text/html
    Content-Length: 59
    
    <html><body>Hello authdemo from webmachine.
    </body></html>
    

    For more details, read the source of the resources linked at the top of this page.

    rabbitmq-server-3.2.4/plugins-src/webmachine-wrapper/webmachine-git/www/blogs.html0000644000000000000000000000464212305126066027063 0ustar rootroot other writing about Webmachine

    webmachine

    What else can I read?

    In addition to the documentation on this site and the source code on bitbucket, some useful Webmachine writing can be found on blogs and elsewhere. A small sampling of these is here:

    The restful way blog is almost entirely dedicated to Webmachine.

    The BeerRiot blog contains multiple topics, including a wealth of examples and discussion of Webmachine.

    The blog of Andy Gross has some useful hints and tutorials.

    Paul Mineiro posted about dynamically loading webmachine resources.

    Kevin Smith teaches an excellent Erlang training class which often culminates with development of applications in Webmachine.

    There is a fairly low traffic mailing list for technical discussion of Webmachine.

    rabbitmq-server-3.2.4/plugins-src/webmachine-wrapper/webmachine-git/www/diagram.html0000644000000000000000000000352212305126066027355 0ustar rootroot Webmachine decision flow

    webmachine

    Webmachine decision flow

    This diagram is illustrative of the flow of processing that a webmachine resource goes through from inception to response.

    Version 1 of this diagram, from Alan Dean, was the inspiration for webmachine_decision_core. Versions 2 and 3 were created in collaboration between Alan Dean and Justin Sheehy.

    A copy of v3 is found in the webmachine source tree for convenience.

    http diagram v3

    rabbitmq-server-3.2.4/plugins-src/webmachine-wrapper/webmachine-git/www/quickstart.html0000644000000000000000000000453612305126066030151 0ustar rootroot getting started quickly with Webmachine

    webmachine

    getting started quickly with Webmachine

    Make sure that you have a working Erlang/OTP release, R12B5 or later.

    Get the webmachine code:

    hg clone http://bitbucket.org/justin/webmachine/ webmachine-read-only
    

    Build webmachine:

    cd webmachine-read-only
    make
    

    Create, build, and start the skeleton resource:

    ./scripts/new_webmachine.sh mywebdemo /tmp
    cd /tmp/mywebdemo
    make
    ./start.sh
    

    Take a look! Point a web browser at http://localhost:8000/

    To make this resource handle URI paths other than /, add more dispatch terms in /tmp/mywebdemo/priv/dispatch.conf; to make that resource to more interesting things, modify the resource itself at /tmp/mywebdemo/src/mywebdemo_resource.erl.

    To learn how to do more interesting things, check out some examples or read more documentation.

    rabbitmq-server-3.2.4/plugins-src/webmachine-wrapper/webmachine-git/www/favicon.ico0000644000000000000000000000217612305126066027210 0ustar rootroot h(  ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ~|{ÿtrqÿvtsÿ…„ƒÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿgedÿœ›šÿÑÐÐÿååäÿàààÿÃÂÂÿƒ€€ÿljiÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿjhgÿÜÛÛÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ³±±ÿjhgÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿkhgÿèèèÿüüüÿÿÿÿÿúúúÿÕÔÔÿ•“’ÿÿðððÿÿÿÿÿ²±±ÿqnmÿÿÿÿÿÿÿÿÿÿ‹‹ÿ¶µµÿäääÿº¹¸ÿÿÿÿÿàààÿŒ‹ÿwutÿ][Zÿ³²²ÿþþþÿæææÿ|{zÿÿÿÿÿÿÿÿÿÿkhgÿïïîÿ”“’ÿ®¬¬ÿÿÿÿÿÿÿÿÿÿÿÿÿýýýÿííìÿååäÿååäÿ}|ÿ«©¨ÿ–””ÿÿÿÿÿÿÿa_^ÿ—–•ÿ`^]ÿ²°¯ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿúúúÿ¹¸·ÿžœÿ‰‡†ÿÿÿÿÿÿÿ`^\ÿ^\[ÿ[YXÿ¢  ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÃÃÂÿ‚€ÿÿÿÿÿÿÿgedÿdbaÿ_]\ÿ…ƒƒÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ½¼¼ÿŽÿÿÿÿÿÿÿŽÿ][Zÿecbÿa^]ÿÇÆÆÿÿÿÿÿÿÿÿÿ½¼¼ÿ“‘‘ÿëëëÿÿÿÿÿÿÿÿÿ€~}ÿÿÿÿÿÿÿÿÿÿÿÿÿb]Zÿdbaÿb`_ÿljiÿœ›šÿ‰‡†ÿ][ZÿXUTÿÛÛÚÿÿÿÿÿ¹¸·ÿmjiÿÿÿÿÿÿÿ‘Šÿˆ¢·ÿ˜¡ÿ_YUÿdbaÿca`ÿ][Zÿ_]\ÿdbaÿa_^ÿÊÉÉÿº¸¸ÿca`ÿÿÿÿÿÿÿ˜––ÿXOHÿ)ÂÿwÉÿÿ£¥§ÿb_]ÿ[YXÿb`_ÿcaaÿca`ÿ`^]ÿ][Zÿhedÿÿÿÿÿÿÿÿÿÿ—–•ÿ^XSÿZ}™ÿv²Üÿ™°Äÿÿÿÿÿÿÿqnmÿgecÿhfeÿ|yxÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ—–•ÿTRQÿd^Zÿ\XUÿxusÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿŒŠŠÿyvuÿtqpÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþøðàÀÀÀÀÀÀà€ÿÿrabbitmq-server-3.2.4/plugins-src/webmachine-wrapper/webmachine-git/www/mechanics.html0000644000000000000000000001072012305126066027701 0ustar rootroot Webmachine mechanics

    webmachine

    How does this Webmachine thing work, anyway?

    This page describes the basic mechanics of Webmachine from the point of view of a single incoming HTTP Request, documenting the behavior of Webmachine through to the HTTP Response.

    (This is a bit different from what you might get with a "Web Framework" as we're not going to talk about MVC, ORMs, or anything else about the rest of the shape of your application. We believe that you know better than we do how to structure your own app -- Webmachine's job is to help you make sure that your app's presence on the Web is well-behaved and well-structured.)

    When a request is initially received by Webmachine it is handled by the dispatcher. If the dispatcher does not find a matching resource then it will immediately respond with a 404 Not Found. If a match is found then a request data record is created and the matching resource is kicked off via its init/1 function.

    The resource then flows through the decision core, which is effectively just running the request through the HTTP flowchart. At each decision point (diamond) in the diagram, Webmachine will determine which path to follow. In some cases it can determine the path purely from the request data -- for instance, the path from decision C3 depends purely on whether the client sent an Accept header. In many cases, however, the decision is application-specific -- the path from B10 depends on the value the resource module returns from allowed_methods. Eventually the chosen path will terminate at one of the rectangles on the diagram. At that point Webmachine will send an appropriate HTTP response, with the headers and body dependent on the path through the diagram and the values returned by the resource's functions.

    Most of the time you don't need to worry about this big diagram, though -- just define the resource functions relevant to your app and Webmachine will do the rest. A good understanding of this central mechanism in Webmachine is most useful when debugging your resources.

    From the way that webmachine's decision core works, it follows that Webmachine's HTTP behavior is transactional. Each HTTP Request is fully received, and the resulting HTTP Response is then fully constructed before being returned. This means that while Webmachine is suitable for a great many Web applications it is not a good fit for an application that will gradually or continuously stream responses back to clients inside the context of a single HTTP Request.

    A useful way to build Webmachine applications is often just to write a single function such as to_html to provide the most basic of stubs; when that function exists (or any other returned by content_types_provided) you can produce 200 OK responses. After that, you can easily extend your application's Web behavior simply by filling in the other resource functions as desired.

    rabbitmq-server-3.2.4/plugins-src/webmachine-wrapper/webmachine-git/www/docs.html0000644000000000000000000000436012305126066026702 0ustar rootroot Webmachine documentation rabbitmq-server-3.2.4/plugins-src/webmachine-wrapper/webmachine-git/www/contact.html0000644000000000000000000000316412305126066027406 0ustar rootroot Webmachine contact information

    webmachine

    Webmachine contact information

    Have questions about Webmachine that aren't answered here? We'd love to hear from you.

    Subscribers to the Webmachine mailing list include both users and the core development team.

    rabbitmq-server-3.2.4/plugins-src/webmachine-wrapper/webmachine-git/www/resources.html0000644000000000000000000003627612305126066027777 0ustar rootroot Webmachine resource functions

    webmachine

    Webmachine resource functions

    All webmachine resources should include the webmachine resource library:

    -include_lib("webmachine/include/webmachine.hrl").

    All webmachine resources should define and export init/1, which will receive a configuration property list from the dispatcher as its argument. This function should, if successful, return {ok, Context}. Context is any term, and will be threaded through all of the other webmachine resource functions. Alternately, the resource can go into debugging mode by returning {{trace, Dir}, Context} instead -- see the tracing documentation for more information.

    All webmachine resource functions are of the signature:

    f(ReqData, Context) -> {Result, ReqData, Context}

    Context is an arbitrary term() that is specific to your application. Webmachine will never do anything with this term other than threading it through the various functions of your resource. This is the means by which transient application-specific request state is passed along between functions.

    ReqData is a #wm_reqdata{} term, and is manipulated via the wrq interface. A resource function may access request data (such as header values) from the input value. If a resource function wishes to affect the response data in some way other than that implied by its return value (e.g. adding an X-Header) then it should modify the returned ReqData term accordingly.

    The rest of this document is about the effects produced by different values in the Result term.

    There are over 30 resource functions you can define, but any of them can be omitted as they have reasonable defaults.

    Each function is described below, showing the default and allowed values that may be in the Result term. The default will be used if a resource does not export the function. If a function has an "X" in the "Halt" column, it also has the option of returning either of the two following special values for Result:

    ResultEffect
    {error, Err::term()}Immediately end processing of this request, returning a 500 response code. The response body will contain the Err term.
    {halt, Code::integer()}Immediately end processing of this request, returning response code Code. It is the responsibility of the resource to ensure that all necessary response header and body elements are filled in ReqData in order to make that reponse code valid.
    {halt, {Code::integer(), ReasonPhrase::iolist()}}Same as {halt, Code::integer()} but supply a custom reason phrase for the HTTP status code as well.

    Any function which has no description is optional and the effect of its return value should be evident from examining the diagram.

    FunctionDefaultHaltAllowedDescription
    resource_existstrueXtrue | falseReturning non-true values will result in 404 Not Found.
    service_availabletrueXtrue | false
    is_authorizedtrueXtrue | AuthHeadIf this returns anything other than true, the response will be 401 Unauthorized. The AuthHead return value will be used as the value in the WWW-Authenticate header.
    forbiddenfalseXtrue | false
    allow_missing_postfalseXtrue | falseIf the resource accepts POST requests to nonexistent resources, then this should return true.
    malformed_requestfalseXtrue | false
    uri_too_longfalseXtrue | false
    known_content_typetrueXtrue | false
    valid_content_headerstrueXtrue | false
    valid_entity_lengthtrueXtrue | false
    options[][Header]If the OPTIONS method is supported and is used, the return value of this function is expected to be a list of pairs representing header names and values that should appear in the response.
    allowed_methods['GET', 'HEAD'][Method]If a Method not in this list is requested, then a 405 Method Not Allowed will be sent. Note that these are all-caps and are atoms. (single-quoted)
    delete_resourcefalseXtrue | falseThis is called when a DELETE request should be enacted, and should return true if the deletion succeeded.
    delete_completedtrueXtrue | falseThis is only called after a successful delete_resource call, and should return false if the deletion was accepted but cannot yet be guaranteed to have finished.
    post_is_createfalsetrue | falseIf POST requests should be treated as a request to put content into a (potentially new) resource as opposed to being a generic submission for processing, then this function should return true. If it does return true, then create_path will be called and the rest of the request will be treated much like a PUT to the Path entry returned by that call.
    create_pathundefinedPathThis will be called on a POST request if post_is_create returns true. It is an error for this function to not produce a Path if post_is_create returns true. The Path returned should be a valid URI part following the dispatcher prefix. That Path will replace the previous one in the return value of wrq:disp_path(ReqData) for all subsequent resource function calls in the course of this request.
    process_postfalseXtrue | falseIf post_is_create returns false, then this will be called to process any POST requests. If it succeeds, it should return true.
    content_types_provided [{"text/html", to_html}] [{Mediatype, Handler}] This should return a list of pairs where each pair is of the form {Mediatype, Handler} where Mediatype is a string of content-type format and the Handler is an atom naming the function which can provide a resource representation in that media type. Content negotiation is driven by this return value. For example, if a client request includes an Accept header with a value that does not appear as a first element in any of the return tuples, then a 406 Not Acceptable will be sent.
    content_types_accepted [] [{Mediatype, Handler}] This is used similarly to content_types_provided, except that it is for incoming resource representations -- for example, PUT requests. Handler functions usually want to use wrq:req_body(ReqData) to access the incoming request body.
    charsets_providedno_charsetno_charset | [{Charset, CharsetConverter}] If this is anything other than the atom no_charset, it must be a list of pairs where each pair is of the form Charset, Converter where Charset is a string naming a charset and Converter is a callable function in the resource which will be called on the produced body in a GET and ensure that it is in Charset.
    encodings_provided [{"identity", fun(X) -> X end}] [{Encoding, Encoder}] This must be a list of pairs where in each pair Encoding is a string naming a valid content encoding and Encoder is a callable function in the resource which will be called on the produced body in a GET and ensure that it is so encoded. One useful setting is to have the function check on method, and on GET requests return [{"identity", fun(X) -> X end}, {"gzip", fun(X) -> zlib:gzip(X) end}] as this is all that is needed to support gzip content encoding.
    variances [] [HeaderName] If this function is implemented, it should return a list of strings with header names that should be included in a given response's Vary header. The standard conneg headers (Accept, Accept-Encoding, Accept-Charset, Accept-Language) do not need to be specified here as Webmachine will add the correct elements of those automatically depending on resource behavior.
    is_conflictfalsetrue | falseIf this returns true, the client will receive a 409 Conflict.
    multiple_choicesfalseXtrue | falseIf this returns true, then it is assumed that multiple representations of the response are possible and a single one cannot be automatically chosen, so a 300 Multiple Choices will be sent instead of a 200.
    previously_existedfalseXtrue | false
    moved_permanentlyfalseX {true, MovedURI} | false
    moved_temporarilyfalseX {true, MovedURI} | false
    last_modifiedundefinedundefined | {{YYYY,MM,DD}, {Hour,Min,Sec}}
    expiresundefinedundefined | {{YYYY,MM,DD}, {Hour,Min,Sec}}
    generate_etagundefinedundefined | ETagIf this returns a value, it will be used as the value of the ETag header and for comparison in conditional requests.
    finish_requesttruetrue | falseThis function, if exported, is called just before the final response is constructed and sent. The Result is ignored, so any effect of this function must be by returning a modified ReqData .
    body-producing function named as a Handler by content_types_providedX Body The Body should be either an iolist() or {stream,streambody()}
    POST-processing function named as a Handler by content_types_acceptedX true

    The above are all of the supported predefined resource functions. In addition to whichever of these a resource wishes to use, it also must export all of the functions named in the return values of the content_types_provided and content_types_accepted functions with behavior as described in the bottom two rows of the table.

    rabbitmq-server-3.2.4/plugins-src/webmachine-wrapper/webmachine-git/www/intros.html0000644000000000000000000000536612305126066027277 0ustar rootroot introductions to Webmachine

    webmachine

    How do I get started?

    If you want to jump in and start coding right away, the quickstart is the way to go.

    If you would prefer to watch a narrated slideshow introduction, this is roughly similar to the presentation that was given at Bay Area Erlang Factory 2009:

    Some blogs also have posts that can serve as useful introductions to Webmachine, if you prefer to start that way.

    No matter how you get started, you'll probably want to come back and read more documentation once you get up and running.

    rabbitmq-server-3.2.4/plugins-src/webmachine-wrapper/webmachine-git/www/streambody.html0000644000000000000000000001231612305126066030123 0ustar rootroot Webmachine streamed bodies

    webmachine

    Webmachine streamed bodies

    Webmachine allows the resource developer to handle request and response bodies as either whole units (binary or iolist) to be handed around at once, or else to choose to "stream" the body.

    The body-handling functions are:

    • wrq:req_body/1
    • wrq:stream_req_body/2
    • wrq:set_resp_body/2

    The last of these, wrq:set_resp_body/2, is also called implicitly with the return value of any content-producing function such as to_html/2.

    The first of these (req_body) is the simplest. It will provide the whole incoming request body as a binary. (Unless the body is too large, as set by wrq:set_max_recv_body/2 or defaulting to 50M) For the majority of resources, this is the easiest way to handle the incoming request body.

    If a resource wants to handle the incoming request body a hunk at a time, it may call wrq:stream_req_body/2 instead. Instead of a binary, this produces a StreamBody structure.

    (It is an error to call both wrq:req_body/1 and wrq:stream_req_body/2 in the execution of a single resource.)

    A StreamBody is a pair of the form {Data,Next} where Data is a binary and Next is either the atom done signifying the end of the body or else a 0-arity function that, when called, will produce the "next" StreamBody structure.

    The integer parameter to wrq:stream_req_body/2 indicates the maximum size in bytes of any Hunk from the resulting StreamBody.

    When a resource provides a body to be sent in the response, it should use wrq:set_resp_body/2. The parameter to this function may be either an iolist, representing the entire body, or else a pair of the form {stream, StreamBody}.

    An example may make the usage of this API clearer. A complete and working resource module using this API in both directions:

    -module(mywebdemo_resource).
    -export([init/1, allowed_methods/2, process_post/2]).
    
    -include_lib("webmachine/include/webmachine.hrl").
    
    init([]) -> {ok, undefined}.
    
    allowed_methods(ReqData, State) -> {['POST'], ReqData, State}.
    
    process_post(ReqData, State) ->
        Body = get_streamed_body(wrq:stream_req_body(ReqData, 3), []),
        {true, wrq:set_resp_body({stream, send_streamed_body(Body,4)},ReqData), State}.
    
    send_streamed_body(Body, Max) ->
        HunkLen=8*Max,
        case Body of        
            <> ->
                io:format("SENT ~p~n",[<>]),
                {<>, fun() -> send_streamed_body(Rest,Max) end};
            _ ->
                io:format("SENT ~p~n",[Body]),
                {Body, done}
        end.
    
    get_streamed_body({Hunk,done},Acc) ->
        io:format("RECEIVED ~p~n",[Hunk]),
        iolist_to_binary(lists:reverse([Hunk|Acc]));
    get_streamed_body({Hunk,Next},Acc) ->
        io:format("RECEIVED ~p~n",[Hunk]),
        get_streamed_body(Next(),[Hunk|Acc]).
    

    If you use this resource in place of the file /tmp/mywebdemo/src/mywebdemo_resource.erl in the quickstart setup, you should then be able to issue curl -d '1234567890' http://127.0.0.1:8000/ on the command line and the io:format calls will show you what is going on.

    Obviously, a realistic resource wouldn't use this API just to collect the whole binary into memory or break one up that is already present -- you'd use req_body and put a simple iolist into set_resp_body instead. Also, the choices of 3 and 4 bytes as hunk size are far from optimal for most reasonable uses. This resource is intended only as a demonstration of the API, not as a real-world use of streaming request/response bodies.

    rabbitmq-server-3.2.4/plugins-src/webmachine-wrapper/webmachine-git/www/reqdata.html0000644000000000000000000002100112305126066027362 0ustar rootroot Webmachine request/response data

    webmachine

    Webmachine request/response data

    This is documentation of the Webmachine Request Data API as embodied by the "wrq" module. This module is the means by which resources access and manipulate the state of the request they are handling.

    Given that all webmachine resource functions have this signature:

    f(ReqData, Context) -> {Result, ReqData, Context}

    we should explain in detail the ReqData input and output parameter. This is a data structure used to represent the request sent by the client as well as the response being built by the resource. The wrq module is used to access the values in the input parameter. Most functions in most resources have no need to modify the output ReqData and can simply pass along the one received as input. However, in some cases a resource will need to make some update to the response other than that implied by Result and in those cases it should use the wrq module to build a modified ReqData from the original one for the return value.

    A couple of nonstandard types are assumed here:

    TypeDescription
    string()a list() with all elements in the ASCII range
    rd()opaque record, used as the input/output ReqData
    streambody()A webmachine streamed body format
    mochiheaders()a structure used in mochiweb for HTTP header storage

    The accessors are:

    FunctionDescription
    method(rd()) -> 'DELETE' | 'GET' | 'HEAD' | 'OPTIONS' | 'POST' | 'PUT' | 'TRACE' The HTTP method used by the client. (note that it is an atom() )
    version(rd()) -> {integer(),integer()} The HTTP version used by the client. Most often {1,1} .
    peer(rd()) -> string() The IP address of the client.
    disp_path(rd()) -> string() The "local" path of the resource URI; the part after any prefix used in dispatch configuration. Of the three path accessors, this is the one you usually want. This is also the one that will change after create_path is called in your resource.
    path(rd()) -> string() The path part of the URI -- after the host and port, but not including any query string.
    raw_path(rd()) -> string() The entire path part of the URI, including any query string present.
    path_info(atom(),rd()) -> 'undefined' | string() Looks up a binding as described in dispatch configuration.
    path_info(rd()) -> any() The dictionary of bindings as described in dispatch configuration.
    path_tokens(rd()) -> list() This is a list of string() terms, the disp_path components split by "/".
    get_req_header(string(),rd()) -> 'undefined' | string() Look up the value of an incoming request header.
    req_headers(rd()) -> mochiheaders() The incoming HTTP headers. Generally, get_req_header is more useful.
    req_body(rd()) -> 'undefined' | binary() The incoming request body, if any.
    stream_req_body(rd(),integer()) -> streambody() The incoming request body in streamed form, with hunks no bigger than the integer argument.
    get_cookie_value(string(),rd()) -> string() Look up the named value in the incoming request cookie header.
    req_cookie(rd()) -> string() The raw value of the cookie header. Note that get_cookie_value is often more useful.
    get_qs_value(string(),rd()) -> 'undefined' | string() Given the name of a key, look up the corresponding value in the query string.
    get_qs_value(string(),string(),rd()) -> string() Given the name of a key and a default value if not present, look up the corresponding value in the query string.
    req_qs(rd()) -> [{string(), string()}] The parsed query string, if any. Note that get_qs_value is often more useful.
    get_resp_header(string(),rd()) -> string() Look up the current value of an outgoing request header.
    resp_redirect(rd()) -> bool() the last value passed to do_redirect, false otherwise -- if true, then some responses will be 303 instead of 2xx where applicable
    resp_headers(rd()) -> mochiheaders() The outgoing HTTP headers. Generally, get_resp_header is more useful.
    resp_body(rd()) -> 'undefined' | binary() The outgoing response body, if one has been set. Usually, append_to_response_body is the best way to set this.
    app_root(rd()) -> string() Indicates the "height" above the requested URI that this resource is dispatched from. Typical values are "." , ".." , "../.." and so on.

    The functions for (nondestructive) modification of rd() terms are:

    FunctionDescription
    set_resp_header(string(),string(),rd()) -> rd() Given a header name and value, set an outgoing request header to that value.
    append_to_response_body(binary(),rd()) -> rd() Append the given value to the body of the outgoing response.
    do_redirect(bool(),rd()) -> rd() see resp_redirect; this sets that value.
    set_disp_path(string(),rd()) -> rd() The disp_path is the only path that can be changed during a request. This function will do so.
    set_req_body(binary(),rd()) -> rd() Replace the incoming request body with this for the rest of the processing.
    set_resp_body(binary(),rd()) -> rd() Set the outgoing response body to this value.
    set_resp_body(streambody(),rd()) -> rd() Use this streamed body to produce the outgoing response body on demand.
    set_resp_headers([{string(),string()}],rd()) -> rd() Given a list of two-tuples of {headername,value}, set those outgoing response headers.
    remove_resp_header(string(),rd()) -> rd() Remove the named outgoing response header.
    rabbitmq-server-3.2.4/plugins-src/webmachine-wrapper/webmachine-git/www/css/0000755000000000000000000000000012305126066025651 5ustar rootrootrabbitmq-server-3.2.4/plugins-src/webmachine-wrapper/webmachine-git/www/css/style-1c.css0000644000000000000000000000516712305126066030035 0ustar rootroot/* global reset */ *{ margin: 0; padding: 0; }* :focus, :active { outline: 0; } body { font: .9em Georgia, "Times New Roman", Sans-Serif; background: #fff url(../images/bg.gif) repeat-x; color: #333; } a { color: #3333FF; text-decoration: none; } img { border: 0; } h1 { float: left; margin: 20px 0 50px; font-size: 4em; color: #fff; } h2 { font-size: 2.4em; font-weight: normal; margin: 0 0 20px; } h2 a:hover { background: #3333FF; color: #fff; } .hr { color: #ccc; } p { margin: 5px 0 15px; line-height: 1.6em; } #content { margin: 0 auto; width: 900px; } #top { float: right; margin: 38px 0 30px 0;} #top li { list-style: none; display: inline; } #top li a { float: left; padding: 6px 20px; margin: 3px 2px 0 0; color: #3333FF; } #top li a.current { color: #fff; background: #3333FF; } #top li a:hover { background: #808080; color: #fff; } #intro { clear: both; padding: 15px 0 1px 20px; border: 1px solid #dedede; font-size: 1.3em; background: #eee; margin: 0 0 30px; } #left { float: left; width: 830px; margin: 0 0 15px; } #right { float: right; width: 0px; } #right h3 { border-bottom: 1px solid #ccc; margin: 0 0 10px; } #right img { margin: 0 3px 3px 0; border: 2px solid #eee; padding: 2px; } #right li { list-style: none; } #right li a { display: block; border-bottom: 1px solid #ccc; padding: 5px 5px; } #footer { clear: both; padding: 15px 0; border-top: 1px solid #ccc; } #r { float: right; } dt { font-weight:bold; } dd { margin: 0.5em 0 0.5em 1em; } /* table */ .fwf { font: 12px "Courier"; color: #111; } .lhcol { width: 200px; } .x_check { padding-left:3px; font: 12px "Courier"; } table { width: 100%; padding: 0; border-spacing: 0px; border-collapse: collapse; margin: 5px; margin-bottom: 15px; } th { font: bold 12px "Georgia", Verdana, Arial, Helvetica, sans-serif; /* color: #4f6b72; */ border: 1px solid #999; letter-spacing: 2px; text-transform: uppercase; text-align: left; padding: 6px 6px 6px 12px; background: #ddd; } th.nobg { border-top: 0; border-left: 0; border-right: 1px solid #999; background: none; } td { border: 1px solid #999; background: #fff; padding: 6px 6px 6px 12px; vertical-align: top; font: inherit; color: #222; } td.alt { background: #F5FAFA; color: #797268; } th.spec { border-left: 1px solid #999; border-top: 0; background: #fff url(images/bullet1.gif) no-repeat; font: bold 10px "Trebuchet MS", Verdana, Arial, Helvetica, sans-serif; } th.specalt { border-left: 1px solid #999; border-top: 0; background: #f5fafa url(images/bullet2.gif) no-repeat; font: bold 10px "Trebuchet MS", Verdana, Arial, Helvetica, sans-serif; color: #797268; } rabbitmq-server-3.2.4/plugins-src/webmachine-wrapper/webmachine-git/www/css/style.css0000755000000000000000000000516712305126066027537 0ustar rootroot/* global reset */ *{ margin: 0; padding: 0; }* :focus, :active { outline: 0; } body { font: .9em Georgia, "Times New Roman", Sans-Serif; background: #fff url(../images/bg.gif) repeat-x; color: #333; } a { color: #3333FF; text-decoration: none; } img { border: 0; } h1 { float: left; margin: 20px 0 50px; font-size: 4em; color: #fff; } h2 { font-size: 2.4em; font-weight: normal; margin: 0 0 20px; } h2 a:hover { background: #3333FF; color: #fff; } .hr { color: #ccc; } p { margin: 5px 0 15px; line-height: 1.6em; } #content { margin: 0 auto; width: 900px; } #top { float: right; margin: 38px 0 30px 0;} #top li { list-style: none; display: inline; } #top li a { float: left; padding: 6px 20px; margin: 3px 2px 0 0; color: #3333FF; } #top li a.current { color: #fff; background: #3333FF; } #top li a:hover { background: #808080; color: #fff; } #intro { clear: both; padding: 15px 0 1px 20px; border: 1px solid #dedede; font-size: 1.3em; background: #eee; margin: 0 0 30px; } #left { float: left; width: 550px; margin: 0 0 15px; } #right { float: right; width: 280px; } #right h3 { border-bottom: 1px solid #ccc; margin: 0 0 10px; } #right img { margin: 0 3px 3px 0; border: 0 solid #eee; padding: 2px; } #right li { list-style: none; } #right li a { display: block; border-bottom: 1px solid #ccc; padding: 5px 5px; } #footer { clear: both; padding: 15px 0; border-top: 1px solid #ccc; } #r { float: right; } dt { font-weight:bold; } dd { margin: 0.5em 0 0.5em 1em; } /* table */ .fwf { font: 12px "Courier"; color: #111; } .lhcol { width: 200px; } .x_check { padding-left:3px; font: 12px "Courier"; } table { width: 100%; padding: 0; border-spacing: 0px; border-collapse: collapse; margin: 5px; margin-bottom: 15px; } th { font: bold 12px "Georgia", Verdana, Arial, Helvetica, sans-serif; /* color: #4f6b72; */ border: 1px solid #999; letter-spacing: 2px; text-transform: uppercase; text-align: left; padding: 6px 6px 6px 12px; background: #ddd; } th.nobg { border-top: 0; border-left: 0; border-right: 1px solid #999; background: none; } td { border: 1px solid #999; background: #fff; padding: 6px 6px 6px 12px; vertical-align: top; font: inherit; color: #222; } td.alt { background: #F5FAFA; color: #797268; } th.spec { border-left: 1px solid #999; border-top: 0; background: #fff url(images/bullet1.gif) no-repeat; font: bold 10px "Trebuchet MS", Verdana, Arial, Helvetica, sans-serif; } th.specalt { border-left: 1px solid #999; border-top: 0; background: #f5fafa url(images/bullet2.gif) no-repeat; font: bold 10px "Trebuchet MS", Verdana, Arial, Helvetica, sans-serif; color: #797268; } rabbitmq-server-3.2.4/plugins-src/webmachine-wrapper/webmachine-git/www/debugging.html0000644000000000000000000002234012305126066027703 0ustar rootroot Webmachine debugging

    webmachine

    Webmachine debugging

    Having trouble with your webmachine resource? Try debugging it with the webmachine trace utility!

    Basic Use

    To get started, first change your resource's init/1 function to return {trace, Path} instead of ok. For example:

    init(Config) ->
       {{trace, "/tmp"}, Config}.  %% debugging code
       %%{ok, Config}.             %% regular code
    

    Rebuild and reload the module, then in your webmachine application's shell, type:

    wmtrace_resource:add_dispatch_rule("wmtrace", "/tmp").
    

    Now issue the HTTP request that you're trying to debug. Once it has finished, point your browser at http://YOUR_HOST/wmtrace/. You'll see one or more trace files available for inspection. Click on one of them to navigate to the trace inspection utility, which will look something like this:

    Basic Trace

    The example above is a trace of a resource that responded to a GET of the root path (as you can see in the Detail Panel), and ran all the way to a 200 response code (as you can see in the Decision Graph).

    The graph starts small, so you can get a quick view of the path your resource took through it. You can zoom in and out of the Decision Graph by using the Zoom Controls.

    The path your resource took through the graph is highlighted with a dark grey line. Hovering your mouse over the outlined decision points along that line will pop up a tool tip with the name of the decision, and the names of the functions in your resource that were called at that point. Clicking on a decision will flip the Detail Panel to the Decision Tab, where information about that decision will be displayed.

    If your resource traversed the graph all the way to one of the standard, non-error return codes, the box for that return code will be outlined. If your resource instead returned a non-standard or error code, a red circle will be drawn next to the last decision point your resource reached. Clicking on either of these types of endpoints will flip the Detail Panel to the Response Tab, where information about the response will be displayed.

    The Detail Panel has three tabs: Request (labeled Q), Response (labeled R), and Decision (labeled D). Clicking each of these will show information about the request, response, or current decision, respectively.

    Detail Panel Request Tab

    The Request Tab shows details about what the client requested. The method and path are displayed at the top, headers below that, and body (if available) at the bottom.

    Detail Panel Response Tab

    The Response Tab shows details about how your resource responded. The response code is displayed at the top, headers below that, and body (if available) at the bottom.

    Detail Panel Decision Tab

    The Decision Tab shows details about the currently selected decision. The decision's name is displayed in a dropdown at the top (changing this dropdown or clicking on a decision in the graph will change which decision is displayed). The list of the functions called in the resource's module is displayed in a dropdown below the decision. The arguments with which the function was called are displayed just below the function's name, and the return value of the function is displayed at the bottom of the panel.

    The Detail Panel can be resized by clicking and dragging the tabs or the dark grey border to the left or right. Clicking the border will toggle the panel's visibility.

    Configuration Details

    The Webmachine trace tool is divided into two parts: one produces the trace logs, while the other produces the visualization.

    Trace Log Production Configuration

    You may configure the path under which trace files are stored by specifying that path as the Path part of your resource module's init/1 return value. Every time a request is made to that resource, a new trace file will be created in the specified directory.

    Warning: Trace files can be large. It is advised that you do not leave tracing enabled on a large-content-producing or high-hit-rate resource.

    The path may be either absolute:

    init(Config) ->
       {{trace, "/tmp/traces"}, Config}. %% absolute path /tmp/traces
    

    or relative to your application's root:

    init(Config) ->
       {{trace, "traces"}, Config}. %% "traces" directory in application's root
    

    Trace Viewer Configuration

    The viewer is configured by its entry in the dispatch list. Two functions make modifying that entry easy: wmtrace_resource:add_dispatch_rule/2 and wmtrace_resource:remove_dispatch_rules/0.

    Call add_dispatch_rule/2 with the HTTP-exported path, and the path to the trace files. For example, to expose the viewer at http://YOUR_HOST/dev/wmtrace/ and point it at the trace files in /tmp/traces, type in your application's erlang shell:

    wmtrace_resource:add_dispatch_rule("dev/wmtrace", "/tmp/traces").
    

    If you know that you always want the viewer enabled and configured in a specific way, you can also add a line like the following to your application's dispatch list:

    {["dev", "wmtrace", '*'], wmtrace_resource, [{trace_dir, "/tmp/traces"}]}
    

    To disable all trace viewer resources at any point, just execute wmtrace_resource:remove_dispatch_rules/0 in your application's erlang shell.

    Trace Log Format

    The trace file is fairly straightforward, if you want to read it with less:

    • {decision, X}. indicates that a decision point was reached
    • {attempt, Module, Function, Args}. indicates that a call to Module:Function(Args) was made.
    • {result, Module, Function, Result}. indicates that the call to Module:Function(Args) returned Result .
    • {not_expored, Module, Function, Args}. indicates that Module:Function(Args) would have been called, but it was not exported (or not defined) by the module

    The format should be such that a file:consult/1 will give you a list of the lines as erlang terms.

    Special Handling for Funs and Pids

    Funs and Pids don't roundtrip through file serialization very well (file:consult/1 will blow up on a fun or pid written to a file with io:format("~p", [FunOrPid])). To deal with this, the trace logger prints a recognizable tuple translation instead of the fun or pid.

    Fun Translation

    Funs you might see in Erlang source as fun io:format/2 will appear in a trace log as:

    {'WMTRACE_ESCAPED_FUN',[{module,io},
                            {name,format},
                            {arity,2},
                            {type,external}]}
    

    Those that would be in Erlang source as fun() -> ok end will appear in a trace log as:

    {'WMTRACE_ESCAPED_FUN',[{module,sampletrace_resource},
                            {name,'-to_html/2-fun-0-'},
                            {arity,0},
                            {type,local}]}
    

    Pid Translation

    Pids are simply logged in a marked tuple, after being run through erlang:pid_to_list/1:

    {'WMTRACE_ESCAPED_PID',"<0.74.0>"}
    
    rabbitmq-server-3.2.4/plugins-src/webmachine-wrapper/webmachine-git/www/dispatcher.html0000644000000000000000000001141312305126066030075 0ustar rootroot Webmachine request dispatching

    webmachine

    Webmachine request dispatching

    This page describes the configuration of URI dispatch to resources in a webmachine application. The dispatch map data structure is a list of 3-tuples, where each entry is of the form {pathspec, resource, args}. The first pathspec in the list that matches the URI for a request will cause the corresponding resource to be used in handling that request.

    A pathspec is a list of pathterms. A pathterm is any of [string,atom,star] where star is just the atom of "*". The pathspec-matching is done by breaking up the request URI into tokens via the "/" separator and matching those tokens against the pathterms. A string pathterm will match a token if the token is equal to that string. A non-star atom will match any single token. The star atom (* in single quotes) will match any number of tokens, but may only be present as the last pathterm in a pathspec. If all tokens are matched and all pathterms are used, then the pathspec matches. The tokens used are available in wrq:path_tokens(ReqData) in the resource functions.

    Any atom pathterms that were used in a match will cause a binding in the path_info element of the request's ReqData. If there was a foo atom that matched the token "bar", then wrq:path_info(foo, ReqData) will return "bar" inside the resource calls, and in any case wrq:path_info(ReqData) will return a Dict term with all the bindings, accessible via the dict standard library module. If there was a star pathterm in the pathspec, then wrq:disp_path(ReqData) in a resource function will return the URI portion that was matched by the star.

    The resource is an atom identifying a resource that should handle a matching request. It will have the args (which must be a list) passed to its init function before request handling begins.

    In the default directory structure for a new webmachine application, the dispatch terms will be in file:consult form in "priv/dispatch.conf" under the application root.

    Examples

    The examples below are taken from Justin Sheehy's slide at Erlang Factory 2009

    Dispatch RuleURLwrq:disp_pathwrq:pathwrq:path_infowrq:path_tokens
    {["a"], some_resource, []}/a"""/a"[][]
    {["a", '*'], some_resource, []}/a"""/a"[][]
    {["a", '*'], some_resource, []}/a/b/c"b/c""/a/b/c"[]["b", "c"]
    {["a", foo], some_resource, []}/a/b"""/a/b"[{foo, "b"}][]
    {["a", foo, '*'], some_resource, []}/a/b"""/a/b"[{foo, "b"}][]
    {["a", foo, '*'], some_resource, []}/a/b/c/d"c/d""/a/b/c/d"[{foo, "b"}]["c", "d"]

    Query strings are easy too:

    • Given rule: {["a", foo, '*'], some_resource, []}
    • And URL: /a/b/c/d?fee=ah&fie=ha
    • Then wrq:get_qs_value("fie",ReqData) -> "ha"
    rabbitmq-server-3.2.4/plugins-src/webmachine-wrapper/webmachine-git/ebin/0000755000000000000000000000000012305126066025152 5ustar rootrootrabbitmq-server-3.2.4/plugins-src/webmachine-wrapper/webmachine-git/include/0000755000000000000000000000000012305126066025660 5ustar rootrootrabbitmq-server-3.2.4/plugins-src/webmachine-wrapper/webmachine-git/include/wm_resource.hrl0000644000000000000000000000007512305126066030723 0ustar rootroot-record(wm_resource, {module, modstate, modexports, trace}). rabbitmq-server-3.2.4/plugins-src/webmachine-wrapper/webmachine-git/include/webmachine_logger.hrl0000644000000000000000000000063212305126066032031 0ustar rootroot-record(wm_log_data, {resource_module :: atom(), start_time :: tuple(), method :: atom(), headers, peer, path :: string(), version, response_code, response_length, end_time :: tuple(), finish_time :: tuple(), notes}). -type wm_log_data() :: #wm_log_data{}. -define(EVENT_LOGGER, webmachine_log_event). rabbitmq-server-3.2.4/plugins-src/webmachine-wrapper/webmachine-git/include/webmachine.hrl0000644000000000000000000000017612305126066030475 0ustar rootroot-export([ping/2]). -include_lib("webmachine/include/wm_reqdata.hrl"). ping(ReqData, State) -> {pong, ReqData, State}. rabbitmq-server-3.2.4/plugins-src/webmachine-wrapper/webmachine-git/include/wm_reqdata.hrl0000644000000000000000000000064012305126066030513 0ustar rootroot-record(wm_reqdata, {method, scheme, version, peer, wm_state, disp_path, path, raw_path, path_info, path_tokens, app_root,response_code,max_recv_body, max_recv_hunk, req_cookie, req_qs, req_headers, req_body, resp_redirect, resp_headers, resp_body, resp_range, host_tokens, port, notes }). rabbitmq-server-3.2.4/plugins-src/webmachine-wrapper/webmachine-git/include/wm_reqstate.hrl0000644000000000000000000000051312305126066030721 0ustar rootroot-record(wm_reqstate, {socket=undefined, metadata=orddict:new(), range=undefined, peer=undefined, reqdata=undefined, bodyfetch=undefined, reqbody=undefined, log_data=undefined }). rabbitmq-server-3.2.4/plugins-src/webmachine-wrapper/webmachine-git/.done0000644000000000000000000000000012305126066025151 0ustar rootrootrabbitmq-server-3.2.4/plugins-src/webmachine-wrapper/webmachine-git/Emakefile0000644000000000000000000000013312305126066026037 0ustar rootroot% -*- mode: erlang -*- {["src/*"], [{i, "include"}, {outdir, "ebin"}, debug_info] }. rabbitmq-server-3.2.4/plugins-src/webmachine-wrapper/webmachine-git/LICENSE0000644000000000000000000002367712305126066025261 0ustar rootroot 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 rabbitmq-server-3.2.4/plugins-src/webmachine-wrapper/webmachine-git/rebar.config.script0000644000000000000000000000060312305126066030021 0ustar rootrootcase erlang:system_info(otp_release) =< "R15B01" of true -> HashDefine = [{d,old_hash}], case lists:keysearch(erl_opts, 1, CONFIG) of {value, {erl_opts, Opts}} -> lists:keyreplace(erl_opts,1,CONFIG,{erl_opts,Opts++HashDefine}); false -> CONFIG ++ [{erl_opts, HashDefine}] end; false -> CONFIG end. rabbitmq-server-3.2.4/plugins-src/webmachine-wrapper/webmachine-git/rebar.config0000644000000000000000000000037612305126066026525 0ustar rootroot%%-*- mode: erlang -*- {erl_opts, [warnings_as_errors]}. {cover_enabled, true}. {edoc_opts, [{preprocess, true}]}. {deps, [ {mochiweb, "1.5.1*", {git, "git://github.com/basho/mochiweb", {tag, "1.5.1p6"}}} ]}. rabbitmq-server-3.2.4/plugins-src/webmachine-wrapper/webmachine-git/start.sh0000755000000000000000000000014112305126066025725 0ustar rootroot#!/bin/sh cd `dirname $0` exec erl -pa $PWD/ebin $PWD/deps/*/ebin -boot start_sasl -s webmachine rabbitmq-server-3.2.4/plugins-src/webmachine-wrapper/webmachine-git/docs/0000755000000000000000000000000012305126066025165 5ustar rootrootrabbitmq-server-3.2.4/plugins-src/webmachine-wrapper/webmachine-git/docs/http-headers-status-v3.png0000644000000000000000000144573212305126066032152 0ustar rootroot‰PNG  IHDR Bˆå°vÍsRGB®ÎégAMA± üa cHRMz&€„ú€èu0ê`:˜pœºQ<ÿŽIDATx^ìÝ œdey/~LâÕÄ«ÉÿÞĘ\·˜`î½IÔh”qÉ¢‰&¨j£(*Š‚ƒˆÄ]@EqAed†e€a‡a؆Fd“YØ5^ù?UO÷Û§OUWï]Këó~šÓ§Îò¾ßsªºéúÍó>áñÇßȃ @€ @€ @€ @€]ˆ“ @€ @€ @€ @€º(°QÏíÔ @€ @€ @€ @€1&· @€ @€ @€ @€]cêòpz @€ @€ @€ @€æQŒé¶Ûnk½Þk×®ÔM0Ùí'up @€ @€ @€ @€˜Ÿ3cЍÐöÛo¿xñâVÍêS{î¹glÖáGè¼Af’ÆÚ¦µ×_}l\ëUv©m¼©íÝpÀìºë®óóF1j @€ @€ @€ @€³'0ó1¦Í6Ûl¬SyêôÓOmòqØa‡Åú6•5±©£ê·Wª®yì±Ç¥u}lI£8`¶ªßÖH™aŠ-'cŠ Sl,Æ4{÷¢# @€ @€ @€ @€Ì[îĘªÜ‘"+ùT6‹¼QÛüÐXëcãxꡇª¡®ŠUF &cŠãDÊ*¶œ~Œ)椋„Vô*bàåQ»ÿªOårƶâÑ6tÕº}N~W;Kn–OµË¸¯„L˜`m~½±úܺ¾:œÖÓÅaË`óÙêš2eãZÇâhÕ½ªwE‡ÁÖNT¶Œ£µ?×ÔN4ÖÅ­ÝünƒØrùòå¡_[»É8`ÞQåöhK}‹Ç½¸6 @€ @€ @€ @€tK`0cL‘í¨æ“"ð‰¥’>ÉLR|üǸ1¦Ø+O%‰tÔ4«1Åî£É U°Ô”Ê› s]ùTyd%+HµÞ+åPeû¨›å,x幜OµK‡1ÏGˆÒV9-`ªsŸcËëeHeÊwRt£LuW ëD¾$zXzÕ6«”+ÆÔy­Ù 8Nç]Z‡»TãGa‡ÍlÍX«d‚gìcK&OT¢fÕÄO-x1²Lbu¸Ž­Ã‰{ IbL倭۴=W‡³dð®:мCJ©Ü-yäè[mD­Ú9ð)ß½v$@€ @€ @€ @€̪À¬Ä˜"TIŽÚ#£EµB;1¶Ìµ®¯; Ï´B´]ŸéjÞ%úSêU2‘SuûiƘb÷Rª5¬S‚2"A]Œ1e©¡Ú%ˆTM™¢®sÀ(vœƒS\èˆþDW«5ZCEYʨÃëªÕ¹dVcLåàåf¨v2‹`åšZŒ©\ˆ²}[í¸‚ó­ Ó%—\òOÿôOo}Û[·Ür‹-ãË[·|kõñ¶·ÆSok¶üOs¡ÙF=;Æc‹-·j[lñ–-ÞÒã-úüú׿þ‹_üâÃ?<«?Eœ @€ @€ @€̈À¬Ä˜2EÔú˜S™Z«:kXœ¨Z7¨VئÀÍeŒ)'§+§n1•lMfhâkõ‘;vˆ1ÅîÕí³|T‡Ó¥I‡]j·Wk‡«tèsÙlâ1¦Z .vÌ”[ç³d£<],”ÄXkð¨6É`ë ©Õ¹$áf5ÆTÎÒV»Ú«ˆ4Åcû¸ÏËH«i«o›ç›‘·’Þ<ÈvÛm·ù–o>ë‚3NYvÒ©g.]vÎégžæ9ËÏ>Åù+.½ð²•—®¼æÊ«¯]uõuW_s}£ÅªÕ+/¿ê²‹.[qþEçŸ{á9gæç.;í¬SOYvòI§-9aéâãO>Ž=æ„ï½xQ´EÇuÔqG6Ú±mG{DlÿÝŽŽãTÛ1K¾Gk<;áCuØòÄÓ–ìðÑžö´§}àèÍ«£W @€ @€ @€ @ *0+1¦¶¥•ƪº4ÍjL‘Xªå¥"Û‘³³å£sq£q'•«bM§S­šQkN¥ô3AJ*+:=jÍrUS\1„¶“ÊÕNQÛ¥ö:©!:SöÍXL‡>—ãÌHŒi,™8KµXQµþVÛ)Þ:w&‡S½¯J%ª™1u–qcL1Þ¸ 1äØ2¯~mŠÀ¶ÌI÷æÕ;à—¿òåsWœ}úÙ§yÞôÒEç­¸tù¥W^rõu«®¾~ÕE—\xÖ9gž¶ìÔÓÎ8íô3-Î8{ÙòD¼iõ«›y¦ /¸øüsW4òLËÎ9íÔ3O9yÙI'ž¾dñ©Çgžé¸9æÄïF)bIjKŽŽ£}ç¨oïÐ~{}ï¯î÷•½÷ÿê~ ÷=äðCŽ=ñ˜Å§?‰£}Ò8ÈÒ3OÙúý[o»í¶óê¢, @€ @€ @€ô©@ßǘÆedÔ£íå™ËjLµøKkN%RDYL¨7'•‹‡daÌ2NŶCŸË.1ÕbpŪóY2u”ùª\ÎS·²2VÔdëE[+ûTÝrfcLÕ²[Õ³´1Å|pÕ‚^ÕÎG˜¬v“·ÕŽqûzéÓ7²±ºý•½¿rá¥dŒé¼ ÏY~ñòKW^ºêš•—\vÑ·¾shÌ÷ìç<{£'lT}üÏßÿŸ¯}Ýk¿¼÷—/¸¨fºòê+¢nSäŸÎ>ÿ¬eç,kĘN?qÉ©'J#Ãtì’c¢,S¤—²,ÓDZlõ–>¿çç_ýšW?éIOzâŸø”§<%~ã7~ã…/zá.»íñ¦H Mü€N1¦÷m÷¾±n›»Ö†C€ @€ @€ @€ý.0ø1¦Zþ¦zÁz*ÆT õfŒ)缫ÍUW2=]1eħ:G^|}ŽË=‘àQíeÜa8eKkN®mý§ÖwŠg©ÕîÊ}ËÒZT©õPmcL¡4cL+.[ÉE†é‹/¸|Õe«®½êØãyã›Þø›¿ù›™^ú­ßú­§>õ©OúÓï÷~ï¿ý·ÿV"M/}ÙKúæW¬¼|åê•9æVœÖg~öéKÏ8å¤ÓOÌÙå¢xRVN*ÌuN2EòéÛG~k‹·mñ¤'?9Nú‚¼ ¦½ûò—¿¼óÎ;ÿÝßýÝÿøÿã Ox¦¯Þtÿ÷#O$Õy›SÎ8ù½Û¾WŒ©ßNë? @€ @€ @€æ‰À€Ç˜¢ÂM‡"@scªMjs´E5R¨ë1¦(VT‹+å‹¡:½]|›™˜ÈÖÄòÔbLµyÐÊY¦P©:‹\§¤‹ª¡¢¸"!S¹•ic¤9a_õÑa8yG• ø2>•y©òh1Mö,©öå£z‡Ä·qÒÚ³y!Ê£ím«mVøà}ûÕ½¿zÉ•;”aºüº›®Ýï€ýžýìggVéþÏÿùÿðŸøÄ'ân‰[⤓NúÌg>ó–·¼%6ˆlSlð»¿û»øàöË/¾àªÕ+W\ºâ¼‹Î;óü3¢¶SăNãÜe§uêÉËNjL-7º SçÚH'œºxÇ?üã?ú£cŽ9&Ïû­o}+Öl½õÖùíºuëÞµÕ»bÍæ[l1©idcê—U?  @€ @€ @€ @ <ÆAågÚÆ˜"êÕzÆ*49¹¢3µ,QoÞ‚Ó)Õ†Úö0Bš~ç#ÔZ iú‡Ô"¯6µE!0ñÎOù,1–¶·bcçg«™ëšÎl1¦•«¯¼øò‹¢Ó7=83LOyÊS¢êÒÏ~ö³ÎŒÚHÿëý¯Ø>fÛå»\wãµ—\yñÖùgŽd:åøãN<¶Qfé„Eç•‹éä¾ñÍ^ü’?íiOÛwŸ}~òãçÙ—.]úÿïÿýÜç>W:sÙe—=ç9Ïy泞¹ÇW÷ˆ½¦“dc€{Ø @€ @€ @€ 0f8ÆqHêÄL[­‚c=Õa—r8fÛ`ÍXëËŽ‘P©–Þ©õ*O]+¼Ô¡S<Õ9ßÓù¾‰M'5g7eky¡Ù8uhÌ͉:w>.èÄÓHSv˜›³tîÞ¸/–)®—wüÚ>_[uÝÕW_·êÌsÎxíë^™¤'=éIŸÿüç'Øç“O>ùÿøc¯?ÿ߾軋®½ñÚ—^xÞ…çžqÞ²SÏ\zÒé'F¥FA¦%Ç|wñÑcL'ž¾äc >‡zÛÛÞö_ÿõ_ÙŸÿüçwß}÷š5kn¿ýö˜`®ôj¯½öŠ-cú¹ØKŒi‚Ëf @€ @€ @€ Ðï3cêwŽÙîLéÕ!V5Ûgwüy+¡±(6‡ÿµ}¿u˜®¿åº/~ñ  úßøw¼ã?üðÄ)?üðßþíßnÄÞþ¶ëo¾î’+/.Ètú)ËNnÌ+wÊqÇžxLdúî $ÓX©£(Œôž÷½û OxÂ>ûìSÎoo¼ñûoÿíéOúATÖŸ}öÙO~òo¿âU¯ˆ½Ä˜&~±lI€ @€ @€ @€}- ÆÔ×—Oç è$°Ï¾_[sÇ­K—ú÷ÿ÷¢Jþççw^îÕÖ­[µ¸6lØðË_þ²¶ò¾ûîûÕ¯~+ï½÷Þw¿ûݱïŸþÙŸvÄw®¹nÕ…—,?wùÙËÎ9}é§œxÚ’ÅÍyå¾»äèqcLïÚz«ß}ÚïVg–<ôÐCãÈùØzë­ËHV­ZõüŸÿò¿ÛDŒÉýM€ @€ @€ @€óG@Œiþ\k#%0ïöÙwŸ»ÖÝuÐ!ýþü~”bÚn»í’à®»îŠÿê¯þêyÏ{Þ&›lrà>ðÀ1¿Û'>ñ‰¿üË¿ü“?ù“W½êUGydÖm:öØcë·~ëIO~òÇvþØM·ÞxÑ¥+FÍ+·tñq'{Ì ãWcŠÓSÿûS9æ˜r¢ÔS‰1•¾Å³+W®ü“çþÉߊ1ͻր  @€ @€ @€ 0¯Ęæõå7xƒ-°ï¾û¬»oí—öüb¤…~ÿ÷?bC1ÞH,Eé£X³Å=ëYÏzò“Ÿüßÿûßyçßÿþ÷Çʧ<å)Ï|æ3c¢·ßû½ß‹$SlAF¶)žÚâ­[¬¹ýÖ‹/¿èüçyþ§uÚÉËN:áÔÅÇ|ìD&•{ïû'ýâ¿XÌ£êR„¨båsžóœj•¦SO=õ7~ã7_õšWªÆ4Ø÷§Ñ @€ @€ @€ @€@U@ŒÉý@€ÀÀ ì»ß¾Xÿù/~>¢BñqÑEÅPO9唨®ô›¿ù›ýèGcò¸ÈmµÕVÿùŸÿù;¿ó;±r·ÝvûÁ~ðÉO~òMozÓÕW_ÛÇÜsïxÇ;âo|Ó¿wÇ÷.¹ââ .:ÿ¬óÏ<í¬S#Æ´äÔŽ?ù¸qcLKN;a×ÝwtÔk_ûÚÿøÇEüÛßþvy›m¶)kþë¿þ+2UQ;ê?Þó®ØkÑñGM¹E ê½Û¾wûí·Ø l` @€ @€ @€ 0@bLt1 …ÑÓƒë¿ð¥FŒé5¯yMä“âùÃ;,¾éä–-[V6?ꨣbåŸþéŸVWæ³<òÈŽ;îϾéÍo¼íΈ1]2…Säœ=âWÿëã8Ÿÿüç{ì±<ø¡‡kÞýîw—žœp O{ÚÓžÿçÏßÿÀýc¯)g˜bG1&/ @€ @€ @€è#1¦>ºXºJ€Àäª1¦W¾ò•·ß~{ìÄGDr(¦“;ñÄãÛŸþô§ëׯ?è ƒb峟ýì¨Õ”+×®]û³Ÿý,–£xÒ;ì0ÍS„Š¢´ÒîŸýTL`eŸ¾úÕ¯F:*óÇýßÿû?÷¹ÏÅò/~ñ‹ÓO?ýÏŸÿçQjëm¶žf)&1¦ÉÝ+¶&@€ @€ @€ @€n ˆ1uû 8?³&04©Ü>!¤ç?ÿùçœsNœêì³Ï~êSŸkb.¹[n¹åÃþð_þå_Æ´nÏxÆ3båvÛm+?ô¡EÎiñâűýÝwßý–·¼%žÚìM›MyR¹½xÑñ'÷Áà)Où'?éÉQáé†nˆëxà˜Û."V‘mzú<ý‰O|âë^ÿχ}ØwO8z:¥˜Ä˜fí¶r` @€ @€ @€˜1¦YauPzA`ß}÷Y{ï={}u¯¨oô»¿û»Qr)zõÐCí²Ë.ñm$“žÐ|üŸÿó>øàÏ~ö³OyÊSÊʘ`îøãí¯ºêª¿ø‹¿ˆõoÇÛoýþ-_~Ñù+Î;óü3N;ë´“—t©‹;ùؘý-RGTê<ŠmŽ=ñ˜wÙé™Ïz擞ô¤'?ùÉ/|á ·ÜbËø‡ˆdU˜~ÿ~ÿmïxë·úö4§“Ën˜T®nB} @€ @€ @€ @€ lôðÃßÙî1ÁýmF€ DÙ¡Ö7›{î¹g‚»Oa³}öÝçöÜ~äÑGn¼ñÆ‘CzÏ{Þ·Åq~ô£zè¡Qcé oxûÞõ®³Î:+VF÷¾ò•¯ÄšýוQ´é×ÍÇ‘GûþÎS~g·Ýw»áæëW\ºâ¼çžqÞ²SÏ\zÒé'ž°tñq'{Ì Š1eM¦ØþÀoøŽ­ÞñÜ?yîDý¥?|z´?þ_üú}ýÞûï9§qãP¬Ò$Æ4…{Æ.´ˆy0ýºèÞ @€ @€ @€˜mâC© Û=fûÄŽO€À|¸õÖ[[ßl®¸âŠÙsØg߯Ý|ÛMË/^þ¶·¿-¢HÏ{Þó–.]:©ÓÝqǯýëcß¿ü«¿<áÄÅ«V¯\~Éò³—Ÿ½ììÓO9ã”O[²ø”ã#x4ÁjL?Š”R–n:ê¸#<öˆl±OM¤¤Ó3Lª1MêBÛ˜Î6lð뢛„ @€ @€ @`¶Ęf[Øñ ˜ûÓ¾ûí{Óm7G’é€oìÿ;¿ó;‘FŠbK÷Ýwß/ÉÏþó/~ñ‹±×oþÖon·ýv·~ÿæ+®¾âÒ•—,¿ä‚s/<÷ÌóÎ8íìSO9óä¨Éy¦%§ž•™"Õ4ÁÇ.Õ6©Ý'r–3/8cÛn»ýöÛOp¼6#@€ÀXbLî  @€ @€ @€93ÆÔvê+  0eU«VÍq5¦=÷ÜsÙÙg\~ÕeW^uùû¶yïžð„È$½ï}ï{ðÁÇ}{ýÙÏ~¶ï¾û>éIOŠ]^ö²—ž~ÆiW_¿jé²¥G}Ä·ŽøÖ7¿}ð‡.<àà¯ïà~û}cß}¾þµ¯}}ïh{ïÿÕÞi}ëÀ-Þ¶Å;ßùÎ)_2; @ n¸áÕ˜ÆýÁa @€ @€ @€i Œcjûa••˜YYTnë­·~îsŸ»×Þ{]óu§œvòËÿîå‘IŠÇ[ßúÖk¯½ö¿øÅXo ëׯÿüç?ÿä'?96þ£?ú£}öûÚ-·Ý|Ô±G½bÓWDjšìC>2Y• µåižeè€OØèo|ãÌ^2G#@€@˜æ¯¡v'@€ @€ @€ P0©œû9˜ûIå"Æ ¡?þã?þŸ¿é{7->qñ‹_ò⌠ýÙŸýÙþûï%F¢2Ó£>úë_ÿ:¦{衇֮]»xñâW¼â¹Ùÿøÿã3Ÿýô÷ï¾í»‹Þäo7©&¦¼ü”§<åùÏþ ^ð‚§?ýéqßÿýßæÑžúÔ§>ç9Ï™ò‘ÛîhR¹9º¿†À@ ˜Tn /¯Á @€ @€ @€zE@Œ©W®„~xnŘ"Üóìç<û«û~õÆïÝtÒÒ“^ý÷¯~òo7Ê,Å#2C[n±åî»ï~Ì1Çì½÷Þ[mµÕ _øÂRiã7Þ{ß½¿wÇšS–òºyÝL¥‹¶Ûn»‡~øšk®Y¸páŸüÉŸl»í¶K–,yÆ3žñ¦˜ïÀœ©åqĘþ•e€æ@@Œi‚ @€ @€ @@ŒÉ=@€À t1Æ”I¦¯|í+×Þ¸úò«.Ûy—Ÿù¬gþöoÿvÛÀПøÄ§ÿáÓß²Å[N=ýÔ›Öܸdé’×½~Æ2LqÆ \|ñÅ/}éK?÷¹Ïí»ï¾¿ñ¿ñ|à ƒÚqÇ¿ùÍoþæoþ¦ÓÝ‘NC€À„Ę&LeC @€ @€ @€© l4õ]íI€ÞÈIåÊãþø>ý¹ÿ¼èÒ7ÝzÃ]°ë§>ùŠM_ñìç>;"Mdzžù¬g=ëEý¢í?¸ý)§|Ó­7^¹êŠC¾sèLÍ%Wºå‘¢ÓÊ•+£SÌm—ëwÛm·¥K—F¤if3Lª1õöªw @€ @€ @€ 0" Æän @``j1¦Èô<ñ‰¿µÙÿíèc>oŹW\}Åu7^wÃÍÑ®¿ñ–¢ÝpËõ×ßtݪÕW­¸dùIKOüðŽþý?øƒÏ}ò“Ÿ¼âŠ+¢Ó—¾ô¥o|ãyü˜Øî¬³Îšñs‰1 ìÍm` @€ @€ @€81¦»¤D€À°@kŒ)sBO}êS_ûº×~qÏ/~÷øïžxÊ’%'Ÿ°ä”F‹åã—·ßû½õío}Æ3ž1¡¢8æ[ßúÖ˜_鍊nŠS™Bn»í¶‹yåfãŒï}ï{Ý @€ @€ @€ @ ÷Ęzÿé!SØa‡:ƒžÐî1Y¢Ú1cò¸'>ñ‰qò²>;2ã§þíßþíOúÓSä³ @€ @€ @€˜C1¦9Äv*æV ænÛx~<ž÷¼ç=ó™ÏüÓ?ýÓÚp#Ãôë_ÿº­úÂ… 7m>baj—eýúõSÛ±ìµùæõ”CNðØÛl3t„\Ƚb@SÓ¨þÄ1׬™æ§ÞŸª@fµ7Ñ·¶ë'ÞãVÿ‰ïkK @€ @€ @€̸€ÓŒ“: æZ`Æ ^xáÃ?<ÁGziÁ‚«šm¶Ù&–'¸cu³Í§‚ÙxãúiË!'xìÚöùí{4Úô›núøªU£‡­­™ÈY¦ÖŸª@[èIôp:Vÿé; @€ @€ @€˜¦€Ó4íN€î L*Æ´hÑ¢Z)¿õ‘jÚ£™ŠJK±5Ãõˆ–/_žk–.]D §¨ü”•œjÇ–±WîËñ (b4ñdœ0‹'År¬Éoc!¾>òHce,ÄÊr˜QZ´hhÇ\({Å‘ËʽJ9¥ L*Æ¡¥Ì*ÕQ¢)ŸŠXRD”"® ¤Xi¤xÄB„œbM<߯r>ÇBl|*Žk2Æ9§“ÖEŒ&¦E‹8NăJr(¾Í€N$b!óL™pÊàQ)MûæÌk¹PöŠÁÅÆÖ‰ðM&ub9K+Å¡²‚Q5oTÛ&RGm4t´Ü+ÖäIc!ŽXkªOåªkb›X§ÎlVõQžÛäs÷8Nf¤R Œ.–³3I‘89–laÌ5 [Ž_ÎÏãĵçS)Ü:–oì5ÁBYóéõg¬ @€ @€ @€ÌŒ€ÓÌ8: º(0©SfŒZ{›A¥XÏÆLsÕ)çy䑈+ÅS%ÏËYÃ)K4åÑ¢žSìX]ÓÙ¤Z (絫MW7-B6µ¹ïÊ”je¡uR¹|ª:=\qâP­1¦Ší£cyê2…\ ?åšÖ§Ê–%'Tz••ª2ðìI9W,T³D¹K'j;ef«ä™ N¦âÙRö©vüê©«=ÏÍJ‚*1©ÚXªã³Ls&»Î·„g  @€ @€ @€˜ÏbLóùê;"0©Ó‚ j1¦ˆD5Æu•âÛ|D2)2LZÊåx*ÓNcН9Í\<²DÓbL%‘Óc*Ñ¥j¤)ÎÙ|ª,4;ÓXS(ej§Äzʳ­1¦ê6¹Wkâ'#GåD9êÜ,žÊM“*»³Œcʳ‡±W¶E~-£‹üP¬‰g³ŠRìR@òŒñl´ÌK•±äñ³·‰ºG­Õ˜2TbLYµ(ùT|›bCóÁM¤SÆŒ²ÀR>"®”ÓÌåXÊ0c³’èÊ(R ZµÕbLC‡nþ§ ³ô¼º&§ö«%¶l ?Ui™ @€ @€ @€3" Æ4#ŒB€n L*ưQ–MŠ…È0Õª1Åñl’b!&’‹ rû¨Æ ‘sŠmbÇØ&æ›ËóPQ·©cŠ-sã¶jÚ&³8YÍ(“4‘ÚÉ2E±&–cƒÌ U‹•oóø¹Wk5¦ˆe-¢,\²&Ž–ÝÈ,Qìžkrö´2½Z‰1e€) ÅK¤Ü7×äÆq®hÕmâÛœ®5fT6Žã4kc ¥”>ÊÉæÊ5cLÑÏZö<·ïcÊaæqªÏ#$NëXĘºùòvn @€ @€ @€óF`†cLW^yåâÅ‹gOʃ_ýõQ d¬~úé±Á”»ûÆÆ=Ë”?g;Ƶxì±ÇfötE¾ó%˜ÈI£o³z·L¤¶!0“1Ũ#oá¤x#…Dˆ¸RU#ª4UßfãÙXGn)y„œ].±P–˱¾ºÜJ]BBͳ=Ÿ+£S¥àPÒ¥Z^¨o*je^³œ¹¬Túi <åle¹c­@QíDÕøN9QìGhÛ‡RL(7.ñ r–ìX~›sÏÅfÙáêñ3UÍNµ]m›¶Y«ê]UMU#GÕüSn_ªCå·U̬¨”jÔ)ëBeZ«æ©¦Çªò­Óùå|‚µGµÃÕ^ÅrõZ”³”ÉûÊqjQ­ªŒeŠ€“› @€ @€ @€ú]`bL¥|QZä´k9›X†‡r}©WT%«Vú)¹–Zž&B6qÌêüqµèO5áT1mÃIÕþ”n”’N¹&ž}γä³"T<Ê wÕþä69äj«íèªÁ jE¢¶Õªª£¨v¾Š\RÝ`,Ì(”£‹þW§É‹oÛ²Wm‹I^Ù0*çªæ¨b˜­ ¤ê)ª÷C9KUµÚÉ~™é?Ù˜lŒiýúõ .Üc=-Z4Û}ëpü=ö˜îÉK÷«ãˆLiKѽ©œháÂÇyd*;Öö™~Ú^¥è[ôp:iú¯_ßpž¦Ò4q¦0@û @€ @€ @€ 0³Ó1e(§Vtg¬zH­³¹•yÇr6±Ro©3bCY+(žŠàK&oªQ¡,UŽ\ ÄÄS%~”“Á•I⪈9„œ7-NWž ùlNuÙl³Í2“޽òŒ¹q-ôÓvtÕmª‰ÚVŠÊˆXŽ¢Ì—uªE•r8Å*ûVŠEŸDÈ£•#d"ª”’ÊKYU›º®Š“+±Wémö°5ÆTN-â–Ã)“ÊUû0³w¼£HIŘ"ôñÆ/X° bLÛl³Í¦›nÚ-“7®Ÿyó͇֔…Î}+}Ï…Ü+Ò9Ó èäI㘫V:Dvjk&B7µþTÚ^¢èÉ4/]«ÿD†S¶‰qE©UiRqj8¥ÓG¨ ¹Ã7Á{rR†6&@€ @€ @€ @ *0ÝS­|N:")‹‰òBÕØP,Gº¥¦Ÿ•2¢!›͉xPfƒÊšLùÄ6qØj‚'–«ßÆ™ž‰ÍªYŸ¬ÔÚìO™ý-²ÏÕ³ä©óìq®øš{e'³>S°ÊÙsƒ¶£‹mJÀ¨º}mß:Ÿ¦èU³J72ÅUb!7®­•=ŽS2jÅ$ K9Qœ«ô°(U¯xu8ÕÎT{[[³¯vÛø–šÀ¤bL‘^Š S9BĘ֬Y“ß®j>ÊSe}.<Ò¬MT6ˆ8T,ÇײýX»u½"F‡Œæùc931™M)+c¡*Ë‘¡É¸R.”½2SÛ«Ùó‘ãĹJ¥¥rÀJ,Ç×ÄÁ«kâ©ÒóZu¨ÚÀc÷Ø2wÏTPK]Œ=;S(J!¢X+ cUa«7OAÎaÖpš—®ÍXÊxó\ùHÉšR9~Y¨ö'6Ž ]}t¾Xcõ'¡òk^∗•‹•Q³]v;£Nyõ+ù½Æ6¹2S½[µk÷d!/V‡ãªo @€ @€ @€O`ðcL0Ê FãQLîùÈEe£\˜Üζ&@€ÀŒ L*ÆgŽ$SdŒ"ÌÈÅš… –MY®©mŒ©l;f *¾F¤)Ž_sL™yšÈø²SnÊ W¬)å»r\e›Ì*å£R*gÌQ”ê\ÙùVíX™OUïɼŽ_•·L€ @€ @€ @€À¸ƒcŠ9Ñ"l4ÖtrãuØ i€éľ˜¾ÀdcLåŒñ©£Ì!EQ¥\Ÿ¦¶1¦Ì<Å#bLÕnÇöŠªF£ÆW9F‰†´Æ˜JÆ¥‰#Gh&³)e!–[+-eФÚÙÌú´Æ˜ªÛä^ùux¼ÿ–SµÎT)É+³8PÙ}سMŒ©úTœe£,­Œ¥:º,õÏ”U‰ÐOYŸ×§ k"©“½Ê…2¨RN©zêØ>~¬UÇlÝ+ð³8V«RkŒ©$º²oÕþT/Dq·?Õ‹•§«î’>µm²8SÜãÕ³§a¯Ê„Sé|M»<ÕcʧÊñǽím@€ @€ @€ @€ÀXƒcrí  0ð“Š1U+'…L$“Ê#¡"ÕÃM<Æ•œ"ÆT2,Å'šHŒ©ÄJ"}R,²;Y³§,ÄòX1¦jÔ&ò7Yü©THÊnÔâ8cL±q©ëSjÿd¨µìX²;¥ÖT¹k1£ZB+cF9–2º~))T­Æ”•œ2QT­Æ”çÊZAQj(cO±Pfö0¾–8nž:XK ';V®ËDbLe¼Y̩ڟ¶1¦qûSXJ@UCKe‰P®Td˜²DSÑ(‰®Ì6•qµj—§ZcLµã—«l @€ @€ @€É ˆ1MVÌöè9IŘ"o”sÉEÞ(H11Üš5kbedÊgãk¬Ì5‘jŠ…Ø8ÓN9ø˜].£Nñ5–c³,à 9ßÜ#<ï,ÕcÊŠAñˆ§"t’5u"Ê““‘e^¤L?—ÙÈÓäBÙ«5SªÅ¡ò¤±ù›ˆFåšœž,Ni¡X“›ÖjLñl†â¼¹{¦‹J‡s÷xäXb›Ø2ûßæ$zµSuãØ=ÓZyÀ2º ÖÄÑrñ5ó4cŠå$*IŒ1U9ÌX¬<ÖdÊ'0ÛŽ¥ZÃ)NZËTÿ2–êB0•µ›¢õb•vèO²§ÆÊšH*ÈY­*X­ {¥vjäˆòªµj—+R|òBäëø£è}C€ @€ @€ @€ÀxbLã yž=/0©SŒ&bFHвLñ5–s|‘dÊ R©«™¤ø6ÒH±&bIñµ:f¬Ïgs÷Ø8òL倉1•„M„{ò0‘ÅÉêAYÁ(“:ñTÎt–Ü«ÄhÊB¬Ì½b˲qIE„%3%ó”‡õYÕ©œ=ó@ñ(û–“ƾyüØ ÏUB9Ùó<~W®ÉŒQõ€ÕWÇ‘šÒ™<~utÙá uE+h¥'‘.Êþ´=þÐ ›­ñ-'r´ê6Ñ]wÝu¬nÌÞy'ÛÏ®lÿÐCu>ï¸t¥ÛNJ`€&cêŠÚlk³Úí •(U­fOëy«…šfµWƒqðêŒoƒ1"£ @€ @€ @€ @`6z1Ætúé§G„¨ÃhãÙ Ê\ýõpÀŒ»¬]»vûí·¿òÊ+ãøÕƒWÏÛ¹‡3Þ¥Þ9`\ÎæãnÐ;cÑ#0¨1¦êäesp±"ɳƒEËÙë:qäHÅ#V–ÅcMl•“ÊÁ3`ÈBÅrìOeu¥ÖkSíUž4ÖTO‘»´ž·Œ±Úɶ/'ãGgòø±¥žZûœa©ìpHìU’Âùhí|¢e9«µŒòÔf+aRÂ'6.õ“ª§(y¦’Œ‰sU£6Õ Oѯ–kÊ•cu ª!—«É8Q-ʨc¡š¬Ê«}¨n™ËeyüR䩊ƒdÈi¬Î…Vº]Û¡Õ[6+H•™ìâÚU§ºËaÆ6±ë«TÇ[íXlV;l¿Ht@Ï ˆ1õì¥Ñ1 @€ @€ @€˜¬À ĘªóµÕ2@Á‰tNLLVI¹A)ATº›ÅâÛR§šì)uŒªÇ/ɘê–e.¶8o)æ‡-á§rÆZ¨t Êí«ç­&uÊYÚ¼v1ª}¨–\Š,Tú$WîUê•…XYŠ0Õù*EégÛöí@µÃÑ¥œQ.I³‡e¯ZY¦2Õ]õ°e¼y„ZÛÃNö®µ=) ÆäN @€ @€ @€ @€˜S)ð“(XÉ9Ñ"=S&›++3îqœLäd´%·ŒÉÚr÷ئzœ¬á”ÇÌÂ?¯)ç¼N–>Šc–2Hµ°QkŒi¬Ôêå jç-a£rê±^n”Z¬ª0ûœ!¡œú-GWfÊ‹5iëKÑ£zåŒ%QÔö°m;P½­‹d†Ò?'΋…œ.°tu³Í6+W-7È©÷òBG -—óªåŪv`^NB`ŽĘæÜé @€ @€ @€ @`öf ÆTfË^f¡ œ‰,“+ñÈO®Ì˜Kmef˜"ÚRŽ–A™,/T›•Lõ¼™Ô)y 8Tdeʉ"&U¦B«RV{•ˆG¶,—kç-㪞¥íÀË¢¥$U®,}ާÊfee™“.“CµÑµÕ‹NVMªþ­‡«¥'%~TUÍã¤O,çÍ TV޵A¹ía«Å2xä‘G®m÷øÅ/~1ñƒØ’ @€ @€ @€ô‚À ĘzaƒÚ‡Ú\uƒ:Lã"@€ @€ @€ @€˜çbL=}D§Z±«žî®Î @€ @€ @€ @€˜’€Ó”Øæj§˜e/su6ç!@€ @€ @€ @€ Ð1¦î¸;+ @€ @€ @€ @€E@ŒÉÍ@€ @€ @€ @€ @€@—Ęº|œž @€ @€ @€ @€.ǘ/^üØcÍÈe¸þúë—/_>#‡šþAfp\¥3§Ÿ~zŒqú}Ë#{tr¦Žæ8 @€ @€ @€ @€¦#ÐåÓöÛo?ÞW÷PN}fêhÓ9N$„öÜsÏé¡í¾»îºëm·Ý6S‡DTp¦Žæ8 @€ @€ @€ @€¦#0“1¦‡z¨µ+k×®m]™[F(§–¤i{„¶Ã›ø–ÑiÛÉÎ;Nj—‰÷¶ÃaKä«õhc¿íú\©¯Ã;l\œj­¬I yÜ#Û€ @€ @€ @€ @€@˜™S’âQ›މ LYY¦{»òÊ+seylذÁÅ#@€ @€ @€ @€ @`0FbLwÞyç7¾ñ‹ûáqÔQG-_¾|0.€Q @€ @€ @€ @€ 0*ÆtÈ!‡¬é‡Ç’%KĘܻ @€ @€ @€ @€F@Œi`.¥ @€ @€ @€ @€èW1¦~½rúM€ @€ @€ @€ @``ĘæRN} ëׯßxãÍÓ7uÁnï—/›o¾ù6ÛlÓíî8?^Xºt馛nš¯Ž ôJ·ôcªïÃñV3ôâ(©·Ê]W~è­þéM ì±ÇÕ{&Þ©z¬ƒº3Pñ¿–q•w'?êêvL\÷x·)›ÄrõÛùã`¤ý"wìªU«ú¥·sÜω·ñ9>i/Ÿ®ö†jðG†^¾^³Ñ7¯ˆÙPuÌ® ä/íÕnÄÿ·Øõë2ÙÄE\¸paÙËo8UÀÉâ«ÿ7™ì­eû(x‰Û;‹-êñëÉ ˆ1MVl·Þ~=íëëZýŸˆ1Ugíëqé<éÄçgñÒ(›ÅKÃÿ¨LÇÓ¾âf+Ä›°¿oºaæ@ z×ÍÁ霢ß„ úý öQÿã·¯ê?’‰¿£ù±ØG—oš]­}6àgšžvŸm¸cŘÆBcªÉTßÐ|:Û¯ÍÞ<¾ßgzóºèÕ4Z?ùδÇ4k÷9È@Õ ò¼~Ã)þñã;4Ræ‘G‰A¥çøætºY¨þRZû8lVÏëàæL@ŒiΨ{÷Dùƒ¼ü8ïÝŽêÙÕÿ‘ö—b· ˆÿ-©ÆÏã].Š3Á!0Kµ@IÜ~¥³Dí°E@ŒÉÍ0)¿"NŠËÆÓhýgþEàt<ûk_1¦þº^zëC¾÷€S §ü*å_ºÏÛ·1¦y{é{àùË[)¿¿·Ç/óbL}wѳS¹Ž~éþ鬤»be$™¼™÷Ýí­Ãjÿîµïn<1¦Á»¦“Qü}"†¬TÉäìzfëøÝ+ÿžQ­g.‹ŽtYÀü]¾óìôµûM\`ž]ÿî 7îºüå-fîÎe蟳æß¦Ë ¼ëŸ¾ëiŸ ø¬Ï.ØŒv·Ì×ÿ²?ÿGuFÏà`fRÀú;hŠ1ÕpÊßÜ|º?“/¾:–O¾ûêréìDòGa¹½ãÿã_z£›(_Ïl—W°ü£J¿áä•iûË œž¹mudâ~Ž?Ç­x÷®Ve›£;˜ÓÓg>ó™×¾öµ/yÉKâëÞ{ïÕæ§öX²d‰jfêæÉ‰–â=Nµÿ™"ûãäGyÆœ{gìM¡õæuÔ^‰1 ê•íåq‰1õòÕéÁ¾‰1õàEÔ.U&æì²,ƒz­[ÇUý+jüÿ©+5.}ŸŽÔçX.œS '~•Šgùg7Í>}ÉO³ÛbLÓ´{o äÂø„(ë§Æ[\|+ÆÔ›«C¯ò *ÊeˆÁo8i%ÆÔww²OV úïˆ2‡:Ù#Øž@ ÌQŒé¤“NzÎsž³ÑèGä™bý’LbL3xW•B>åÈgðà57µÿ‘öÿÕsÃî,=.¿ÃU¯ñ¿pñÿä=ÞgÝë_ZŒÉ¤rý{)û¨çš}t±z¡«ªÄõÂU˜'}¨M죮Õ9Ÿ'ós˜&•›Ÿ×½GíC¾Ökõ³d£S '«1ÅÊüØ?¯íßþ”{îÏ­S¦³c/ 䜯#’Lñcêåë5VßÊTN-ç7œ2µZÔÊÕôã®Ïc øc‹{càæ"ÆtÉ%—” S,TóL‘dcêâM¿ÖT?×ÏTÔÅþ8õÔªÿ#×Ô?˜˜£½L k —ÿQ‰÷:1¦»Ä=5œj $þúãï›=uuµ3bLƒzegi\bL³ë°­ùs°|¾›÷*\1On1¦yr¡f˜>äk½”ñ‡Áüg“ Õpª¿J…’¿¼ ÌûÀÄâó'neË>(? sFàè¹S]¾ÒÕêT|ÀÕ$â:öã@f¼ÏA®~"à‚vÀî ˆ1u×ßÙç@`.bL;í´S–aŠÐRDš"·3Ê•ÂLS˜]N5¦™º3jÕJâ°ÂÈ3e;—Ç)“5Ä‚?ÃÍ¥¼sõ¸@ü1ÿ'<2L=~±ú½{Õ÷áø{AüªÓï#ÒÿÞ¨Þu¹Üû}ÖÃ. ˆ1už:?ü· Ó¼ºjs-yç™WW¿›SçôcÏgµÏåÝÛ´UçÚšÏAgõ&ì̓×þÿ«7;©W&+P~FÚ#ÿ}{üdôÝ'ËØõí«ÊFâ7œrQâÞÎOÍ|@ÐõUf\ÀdÇ3Nꀽ&01¦-·Ü2‹0UKiÊ$S„œ&[IŒ©×n#ý!@€@Ï ”ôì¥Ñ1 @`°âoèƒ=@£#@€À@ øŸè¼¬E€æ­€ßmæí¥7púZ`ê1¦L&Å£5‡ôÚ×¾6ŸŠS‰(e¦ò(SË}æ3Ÿcêë{Hç  @€ @€ @€ @€LS`ê1¦(Ÿ›å”"TÍ!E\©D”b²ð¶¥±ö`žI5¦i^u» @€ @€ @€ @€è)©Ç˜ÆŠ+Eq¦Œ7Å´q­±¤x¶„œbᤓNš`t©º™SOÝC:C€ @€ @€ @€ @`šS1E®(&ËÄRuò¸Î³ÅE¶)w‰Gì~öÙg‹1MóÚ @€ @€ @€ @€@¿ L+Æ´÷Þ{׿•‹YäÚÎ4W²J1\dŠØSÙìàƒžl’I5¦~¿íôŸ @€ @€ @€ @€@U`Z1¦ˆ•ÚKiŠoK>©ZŸ©mJ©Ì=GcrS @€ @€ @€ @€˜ÏÓ1•4RÌWM5EY¦Îá¤K.¹¤D N:é¤I%™TcšÏ·¬± @€ @€ @€ @€ žÀtcL%™¤˜.§Š{ÉK^R%Å6TÊrMÕ‡ÓàÝOFD€ @€ @€ @€ @` Ó1E,)ê0•ôR.|æ3ŸiWª&™¢\Sn³Ï>[5¦)\<» @€ @€ @€ @€ ˆ1UI‘IŠKµLRÉ9ÅS9\ÔgŠŠMmK7M$ÏdR¹Á¸ùŒ‚ @€ @€ @€ @€@ Ì@Œ)‚Gez¸H&m¹å–µ(R[*ÄB>J)¦˜Šn"Ñ¥ê6bLn_ @€ @€ @€ @€ƒ$031¦vÚ©Ä’¢8Sk,)²JÕèRnkªÓÌM<Ì$Æ4H· ± @€ @€ @€ @€˜™ÓêÕ«#É”i¤Ï|æ31—\>b9¦–›xtI5&7+ @€ @€ @€ @€A˜™ÓÔÒHSÞK5¦A½‹ @€ @€ @€ @`~ ˆ1ÍÏënÔ @€ @€ @€ @€zH@Œ©‡.†® @€ @€ @€ @€˜ŸbLóóº5 @€ @€ @€ @€cê¡‹¡+ @€ @€ @€ @€æ§€Óü¼îFM€ @€ @€ @€ @ ‡Ęzèbè  @€ @€ @€ @€ù) Æ4?¯»Q @€ @€ @€ @€è!1¦ººB€ @€ @€ @€ @`~ ˆ1ÍÏënÔ @€ @€ @€ @€zH@Œ©‡.†® @€ @€ @€ @€˜Ÿ#1¦ 6ìµ×^‡ôÃãk_ûÚå—_>?/˜Q @€ @€ @€ @€<‘SŒ-’LwöÉc𮄠@€ @€ @€ @€˜·£bLóVÁÀ  @€ @€ @€ @€袀Sñš @€ @€ @€ @€†€“û€ @€ @€ @€ @€. ˆ1uù8= @€ @€ @€ @€bLî @€ @€ @€ @€º, ÆÔå àô @€ @€ @€ @€ˆ1¹ @€ @€ @€ @€è²€S—/€Ó @€ @€ @€ @€ Æä @€ @€ @€ @€ @ ËbL]¾NO€ @€ @€ @€ @€€“{€ @€ @€ @€ @€. ˆ1uù8= @€ @€ @€ @€bLî @€ @€ @€ @€º, ÆÔå àô @€ @€ @€ @€ˆ1¹ @€ @€ @€ @€è²€S—/€Ó @€ @€ @€ @€ Æä @€ @€ @€ @€ @ ËbL]¾NO€ @€ @€ @€ @€€“{€ @€ @€ @€ @€. ˆ1uù8= @€ @€ @€ @€bLî @€ @€ @€ @€º, ÆÔå àô @€ @€ @€ @€ˆ1¹ @€ @€ @€ @€è²€S—/€Ó @€ @€ @€ @€ Æä @€ @€ @€ @€ @ ËbL]¾NO€ @€ @€ @€ @€€“{€ @€ @€ @€ @€. ˆ1uù8= @€ @€ @€ @€bLî @€ @€ @€ @€º, ÆÔå àô @€ @€ @€ @€ˆ1¹ @€ @€ @€ @€è²€S—/€Ó @€ @€ @€ @€ Æä @€ @€ @€ @€ @ ËbL]¾NO€ @€ @€ @€ @€€“{€ @€ @€ @€ @€. ˆ1uù8= @€ @€ @€ @€bLî @€ @€ @€ @€º, ÆÔå àô @€ @€ @€ @€ˆ1¹ @€ @€ @€ @€è²€S—/€Ó @€ @€ @€ @€ Æä @€ @€ @€ @€ @ ËbL]¾NO€ @€ @€ @€ @€€“{€ @€ @€ @€ @€. ˆ1uù8= @€ @€ @€ @€bLî @€ @€ @€ @€º, ÆÔå àô @€ @€ @€ @€ˆ1¹ @€ @€ @€ @€è²€S—/€Ó @€ @€ @€ @€ Æä @€ @€ @€ @€ @ ËbL]¾NO€ @€ @€ @€ @€€“{€ @€ @€ @€ @€. ˆ1uù8= @€ @€ @€ @€bLî @€ @€ @€ @€º, ÆÔå àô @€ @€ @€ @€ˆ1¹ @€ @€ @€ @€è²€S—/€Ó @€ @€ @€ @€ Æä @€ @€ @€ @€ @ ËbL]¾NO€ @€ @€ @€ @€€“{€ @€ @€ @€ @€. ˆ1uù8= @€ @€ @€ @€bLî @€ @€ @€ @€º, ÆÔå àô @€ @€ @€ @€ˆ1¹ @€ @€ @€ @€è²€S—/€Ó @€ @€ @€ @€ Æä @€ @€ @€ @€ @ ËbL]¾NO€ @€ @€ @€ @€€“{€ @€ @€ @€ @€. ˆ1uù8= @€ @€ @€ @€bLî @€ @€ @€ @€º,0ÑÓ‚ V­ZÕåÎ:= @€ @€ @€ @€}.°ùæ›·Ž`B1¦È0m´ÑFbL}~è> @€ @€ @€ @€n ¬_¿>2Lo¼qk'Æ1-\¸p=öØtÓMŘºy › @€ @€ @€ @€@Ÿ l³Í6‹-šbŒ)Ç.ÆÔç÷€î @€ @€ @€ @€è 1¦ž¸ :A€ @€ @€ @€ @`> ˆ1Íç«oì @€ @€ @€ @€zB@Œ©'.ƒN @€ @€ @€ @€˜ÏÓŠ1m¾ùæ«V­šÏ|ÆN€ @€ @€ @€ @€Àô¦cšþé @€ @€ @€ @€m6âB€ @€ @€ @€ @€î ˆ1u×ßÙ  @€ @€ @€ @€x\ŒÉM@€ @€ @€ @€ @€@—Ęº|œž @€ @€ @€ @€1&÷ @€ @€ @€ @€]cêòpz @€ @€ @€ @€ĘÜ @€ @€ @€ @€tY@Œ©ËÀé  @€ @€ @€ @€cr @€ @€ @€ @€ Ðe1¦._§'@€ @€ @€ @€ @@ŒÉ=@€ @€ @€ @€ @€@—Ęº|œž @€ @€ @€ @€1&÷ @€ @€ @€ @€]cêòpz @€ @€ @€ @€ĘÜ @€ @€ @€ @€tY@Œ©ËÀé  @€ @€ @€ @€cr @€ @€ @€ @€ Ðe1¦._§'@€ @€ @€ @€ @@ŒÉ=@€ @€ @€ @€ @€@—Ęº|œž @€ @€ @€ @€1&÷ @€ @€ @€ @€]cêòpz @€ @€ @€ @€ĘÜ @€ @€ @€ @€tY@Œ©ËÀé  @€ @€ @€ @€cr @€ @€ @€ @€ Ðe1¦._§'@€ @€ @€ @€ @@ŒÉ=@€ @€ @€ @€ @€@—Ęº|œž @€ @€ @€ @€1&÷ @€ @€ @€ @€]cêòpz @€ @€ @€ @€ĘÜ @€ @€ @€ @€tY@Œ©ËÀé  @€ @€ @€ @€cr @€ @€ @€ @€ Ðe1¦._§'@€ @€ @€ @€ @@ŒÉ=@€ @€ @€ @€ @€@—Ęº|œž @€ @€ @€ @€1&÷ @€ @€ @€ @€]cêòpz @€ @€ @€ @€ĘÜ @€ @€ @€ @€tY@Œ©ËÀé  @€ @€ @€ @€cr @€ @€ @€ @€ Ðe1¦._§'@€ @€ @€ @€ @@ŒÉ=@€ @€ @€ @€ @€@—Ęº|œž @€ @€ @€ @€1&÷ @€ @€ @€ @€]cêòpz @€ @€ @€ @€ĘÜ @€ @€ @€ @€tY@Œ©ËÀé  @€ @€ @€ @€cr @€ @€ @€ @€ Ðe1¦._§'@€ @€ @€ @€ @@ŒÉ=@€ @€ @€ @€ @€@—Ęº|œž @€ @€ @€ @€1&÷ @€ @€ @€ 0ß?üð×t|üMóÑy›yõì_þå_nºé¦‡|æ™gÎ÷Ëø'# Æ4-Û @€ @€ @€ @€ƒ(qœÏé«K–žUÚ §œ•mñÉöÖ·¿kË·¿ëø“Ïj'y\³{âюɶ$۲﷣OXmQ´ÅÃíøeG5ÚéG·#Ž?ýˆã¢íðc‡ÚaÇœí;ÕöÝS¿Ýlß:z¨ºhii‡,ZÚhGòÍf;8Ú‘ÙN>øˆ“j¶›ma´Ã‡Ûa'ã°“¢ð¡öõïœôõmÿoµý¾µ$Ú¾Ñiúçñ¡þk‡,i¶öþæp;ø„¯6Úâ·¿g‡­·Þzocš-1¦Ù’u\ @€ @€ @€ @ _"Ɖ¥µülí–vÏýfûÁýî´àSÑî¾ï§Ñîºw¨Ý¹á‘lwD[ÿÈíö“Û×ýäûÍvÛÚFûÞÚïžF[Ól·þ Ú¢Ýrw£Ýí®hßí·ol¶îˆöP´ëoo´ëšíÚïÿ0ÛêÛíšhß{0ÚÕÑÖ<¸ªÑ¸êÖ¡¶ò–¢]yËývóýW4Ûå7E»ï²h76Ú¥Ñn¸ï’îvñõvQ´ë¢mXíÚ f[½aùêõÑ.¸¦ÑÎo´uç_½î…/yù>‡.9wÕºhç¬Z{ÎUvv´•kÏj´{>þé}Řúåþï‘~Š1õÈ…Ð  @€ @€ @€ @ kcŠ’K%·TÒK`úA3ºô±ŸŠvw 0ÝûÓ‘S%Ô¦Q¦fŒ)3Lk¦FŒit†éG Ó]C¦fŒ©™aªÆ˜Fg˜1¦’aj‰1­¼µ‘aŠ1 g˜®hd˜š1¦Q¦ÖÓ†ZŒ)3LµÓyˆ1í,ÆÔµÛ¹_O,ÆÔ¯WN¿  @€ @€ @€ @€™ˆÓñ'ŸÕ -5rK]i÷Ř¢Ó¨ L#¦GJ¦IÖaÊ0ÕJ1Ê0M¶S3Æ4ÙRLÃÕ˜š¥˜*Õ˜†2LÕjLW¯ËSL'׬Æ4ªS³Ó=ÑĘfêæœ?Çcš?×ÚH  @€ @€ @€ @€öÍÓ™C¹¥á’Keò¸XøèÇw‹64\3½Ô:‹\ 0•¹äjE˜&P‡©QŠiò¦‘åÚ–bjÖa]ŠéƨÃ4ÅRL1£\5ÆÔvF¹³®còZ›´€Ó¤Éì@€ @€ @€ @€ ˜@ĘŽ;éÌÌ-ÝY)¹TfŽËS%½ôÈíë‡æ«Î"WLe"¹æ,r#ÉÅtr7G»+Zc"¹R„©9—ܬd˜®¸y8ÃTŸQîÞKn¸7Š0e»èºh-ÅT‰1UJ1]µ¶”b:³czËÛ¶ jû¯_ýzÀîÙA1¦Ät( @€ @€ @€ @ /"Æt̉gÜe–ª­Yr)«.íøñÝ¢Et©:y\kù¥’^Š:L#¦ü(ÒK•Sû‰äêu˜¾ÿеßÿa¶Õ·5Ú5Ѿ÷`´«£­‰ LÙ¸êÖFk[‡©s†©Ä˜.jĘÚg˜bR¹ ®i´óm]–b*1¦±J1cúÙÏÕ—÷‡Nω€Óœ0;  @€ @€ @€ ÐÃÓ’3"®4Ü~ÒH,UBK;î¼[´Zá¥ÖÚKYä†Ë/•)ä:˜Æ*ÂtÝèÓd˜†bL×n¸0Ûê `+Ãtîªu/|ÉË¿vÈ ç\Õ¨Ætv³Sµ“Sßì½Û51¦Þ½6zF€ @€ @€ @€Ì@ƾ»dY¦”ªí¶uCs¢}dçÝ¢ å–Öþ8ª.ekä–²UÓKÃå—êSȵ›E®aºîö‡­¥S3Ã4\„©Z‡©Y„iFê0™aª–b®ÃtÞªucÚû›S#Ã44ÜÚ³VÞ¦lm'•Sinîç>=‹SŸ^8Ý&@€ @€ @€ @€fL bLGŸ°,RJ¥}/²J¥ÝóãìôÉhµÜR5ºT­½Ô¹üR³ÓCÙ®¿}¨e†©6‹\k¦á¹ä†L%Ãtå-\yËýWÞ|Ì"×h7Ýy£ÝwY´íÒh7ܳÈe»øúF˹ä¦aªÇ˜VF€©‘a:k8Ã$Æ4c·æ|:Ó|ºÚÆJ€ @€ @€ @€´ˆÓ¢ÅËFJ+UË,5—?¼Ó'£ÝZ)¹ÔÈ-Uª.U£K7GÕ¥lw>¡¥Òn¸c(Àtýp€©c¦^ó½Ö"L¬j[„©’aj˜š¦`ªd˜2À4Í Ó9«Öf5¦j¦j†IŒÉël bLS@³  @€ @€ @€ 0Pc:êøeÃ)¥GD©Ö"ôÃÇ>Y¥j»ùî5Ú]Ù†£KH/E¦áÓÇ©ÀÔn¹F¦[­^„éæ±Š0 ÕaÉ0]רô"Ûµ.̶zÃòÕë£]0ö\rQ‡)2L1—ÜPŒ©]&“Ê Ôkc#Æ4‡ØNE€ @€ @€ @€ô¤@ĘŽ<þôZJ©|Y¥È0EN,5rKCõ–ÚU]jNW™9®eò¸ë¾ß&½ÔœB®Q~)ÚÕÙÖ<¸ªÑF*0•Y䚦Ê,ræR„©ãDrækG2L`jd˜®i´ómÝùW¯;/Ûªu`*¦ˆ1½ ª1|Bë\r™aR©'oó^ïÔ„bLË—/_¸páš5kz}4úG€ @€ @€ @€˜¼@ĘŽ8îôjJ©V`éCÛ5ZÎW›*.çŒkæ–:E—¾~Èw/¿þY{é¼Ënþäg¿ú­£OèR3½ôÃs.½é“ŸýÊIç\YI/5L‘[ŠöÍ£NùàN»ïòé/ŸqÑcT`jÎ"WHî†û–^pýv;îöé½îô©½&=‘\%Ô¦s›E˜¢5&’kƘ¾Úˆ1 …–JzIŒiòwß¼ÛcQó±~ýúÚÈÇ1m¾ùæÛl³Í{ì±é¦›.]ºtÞÉ0 @€ @€ @€ 0èÓ±§eD©mJéCÝ5ZÛÄÒ w<íúJÉ¥‘9ãbò¸fnié¹+ŸýÜçsÊZ:÷²›ÿúoþöÃ;ÿç›ßú®wo³CÔ^:tÑÒxv‡vó–ïzÓ–ïÊ L`Šö¢—lòÆ-¶úàÇvßê};<ë9Ï;áŒË¯¸ùþl—ßÔ~¹KohÌ"÷ª|Ã;¶þÐß9éßÞò΋®oT`šH®Y„iÑÒKßÿáOŽaj;‘ÜÕõ"L ÓÊFkƘ·¦—Ęýµ2Ýñm¼ñÆ ,È$R-É4NŒ)*0Å>yþU«V•åéöÈþ @€ @€ @€ @€žˆÓaÇœ6\QiT]¥L)}ð£»FŠ+N, - ç–²êR¶ˆ.ýÃëþµc:ù‚(¼Ñ¥(¼”3ǽè%{ö%7ýýkÿõ {œé¥-xÖeò¸H/E†©1\s ¹Ï}å ø6LÇ/»ìðÅ眶üú˜?.Úq§_é¥ïα§_¦cN»ô½É§÷\¦ïžzi˜N:ÿÚC9ûÄó®½ðÚ »iáÛßýÁ3.½í‚1&’.´îœj¦•ks"¹ˆ1}EŒ©gnà~éHL¦ìm$™âQíùøÕ˜ÊÖq (ËÔ/ÃÖO @€ @€ @€ @€À"ÆôcN@ÒXíƒ;îúw½.RJÕöý¡bKÕÐRæ–ªíÝQõè³_‰ÄÒwO:?£KGÇB#´ÔX^tÒy]:êÄóJí¥ƒçyQ~)f‘{泟·×GÆDr±ðïïùзŽ=û¯þúe‘aÚ}…±}‰¯{ìDd˜^ù¯ß÷Ð%\³þüF[wþÕëÎnm'’‹"L™a:ëÊ{^ðb1¦ Þ\6k/1¤˜Z®úÜDcLQŠ)j:µNJGš @€ @€ @€ Ðïcj(Å”p9+ÜvüD´Z\©5±饨·tÍmF±¥l1a\LWÒKÃÑ¥ósÚ¸ 0}h§Ý߸åV‘[ŠSÄ’>ø±Oeí¥H/Å·GDŒixò¸Ëoºï²›…—^øâM.½ñ¾h ;ù/Þ$Ê/EŒéœ+n¿øú{#À´íŽ»]tݽ/øë—zìÙÑ"·å—"Õu˜b¹%ç®þÔ—¾ñÍïže¡†2Lc˜Î‰YäšÉ ˜VÞ“ÓÆ‰1õû=ßÝþG€©uR¸ ŘbÏÈ0E’©»pv @€ @€ @€ @€ÀlDŒéÛß=µCQ¥í?ò‰hµ2KµÄRæ–"±4ÔÖ<%—¢ÞÒ!‹–.:éüH,}á«•èRN׈1-9/L[½ïC¯ù§7lõÞEkä–š¦˜9.bL1s\¦—rò¸S—_¿óî{½së]rÃ}‘^ÊS¤—"¥_c ¹(¿´íG>å—"½SÈEkĘVGŒéO"Ã-¢KÑ2ƘJ¦±f‘kf˜î‰–&1¦Ù¸çÕ1c^¹Ö SŒcÊô“:Lóêv1X @€ @€ @€ 0¯"Ætèѧ6cIÕ6RT)cL¥ÆÒ¨¸Rä–š‰¥œ'n¸=õ–¢ÒR¶$½ë};\xÍ]oÜb«Ïå æœq¼ð%›,»è†e+nX¾êÎŒ.E™¥Ó.¼!L]Š“ÇÅÌq‘^ÊÚK_9ਨ½ôãÏÉ L‘[:åüë^ð×›Dz)bL]·!ÒKQ~iÛ2Ê/UcL‘^ŠS˜b ¹?¹ÇÁGŸù¾vÍYä:˜†f‘«f˜TcšW¯Ž™lÌ%¶Ç'Æ饨è=š… ÎlÏ @€ @€ @€ ÐuFŒiÑÒ‘BJÕ¢JÍ”ÒvþD´–¬R†–‰¥U·6BKµõ–í–F‹ÂKG.9/f‹;øÈ“#«tä ç.øÏ/G¦ˆ.}î+m¶ÅV‡/>÷ãÿ¹×«ÿé ¥ðR¤—Î[yG䟶ßñS]úô^ £ðÒ—82ÒK]ŠÉã¾uÜ9¯ú‡7Dí¥0EŒ)2L+®Ýå—Þ?c:䘳¢Ež)ÒKo{÷_ÿæwüÝ3ãëÛþã}æ_¾èe‡Ÿtqf˜ÎYµ6æšB®Ý,rbL]¿K 9#\Æâ±|ùòê Æ‰1ÅÖeO1¦¸  @€ @€ @€hˆSLýV©¥4NʈҚ¶ûð.ÑZƒJeM5±”¹¥(¶¡¥¡vóý»üç—KÉ¥ƒŽ89j2}ࣟ*U—>ûå7{Ë;?¾û^¥ðÒ¥7Ü-§ÛùS{½êß°ÝŽ»sÚ¥9sÜÙ—ßé¥h»ï¹0ÓK]ŠvÆ¥·í÷­%Q~食ÜcÙ%·E‹ÚKQéükÖí¸ëQé#»î‘˜>ò‰=>ò‰/ 0­\ÛœB®}&“ÊyíLS bLÕ$ÒäbLÓ<·Ý  @€ @€ @€ @€½/1¦ouJÛ”Ræ“¶ýð.ÑJi¥ *•6WŠÜÒÍC-'‰+­™XÊÖ˜-®Zr©mt)LZ*-ÒK]­1sÜPkæ–²En©´ V7&Ëùã"½t~sæ¸Úüqç—_ªÀ4áS†™^ðâ—åàŵMÕowþô¾oyÛV·­ýIµýìç¿êý›A»%0N5¦nuËy  @€ @€ @€ @€s&1¦ƒ @€ @€ @€ @€³)1¦¯礋®‹(R¶‘@R.¿÷6fJixJ¸¨®T/°4\l)RJµV -Ô['·´n"Ñ¥³VÞÓ!„4ý§Ä˜fó~œ§Çcš§Þ°  @€ @€ @€ @€"Ј1}ûÄ !µm[àãÑFMW›®]u¥’[jM,u-5ª.­Š¸Ri£f‹;'ê-e]ui¶£KÕð““—ÏŒ ˆ1Í8© @€ @€ @€ @€}&1¦ý¿}bÌòVmÕâIïÙþãÑZ+*u*åôpÃsÃLW›!®%´T¯·TË-U'Œ›Ëè’SŸÝÖýÖ]1¦~»búK€ @€ @€ @€Ì´@ĘöýÖ’¡šI«×7š ¤Ò2ÆT[Y¾Tž.²JmâJõ2KYo©^l©sKµyèTcšé{Ðñcr @€ @€ @€ @€ó] c:tÉpiÝùEÝÞ½ÝÎÑ2™TZ£ŠÒXmÔ”p¦‡‹ÄÒ¡¥µQi)[-BÔ ßŠ1Í÷×Ì,Œ_ŒiP’ @€ @€ @€è+ˆ1ísè’±¤Œ17f8iTPi¨ºRÔXjF”ªíì«Öµ•kcn¸lg µÞ -µ§Ä˜úêïΊ1õÇuÒK @€ @€ @€ @`ö"ÆôµC–Düh¬öÛííœvɤ1ƒJ™X;®Ô¨´te/VZšHµ'1¦Ù»çí‘Řæí¥7p @€ @€ @€ @`H bL{ó„‘RI¥fÒð»¶Ý9Zk!¥v)¥‘ÉàʬpýW+Ò$ÆäÅ3ãbL3Nê€ @€ @€ @€ @€@Ÿ üË¿üË‹^ô¢3åãÕ¯~Í&/eµ=ç¹Ï{Ö³Ÿ[[Ù•oÿèÊyk'ý½ßûÿþê/îГçýÙó·~ÿ‡n[û“jûÙÏÕgw†îΡ€Ób; @€ @€ @€ Г6lX^yœwþGŸ°¬Ö?æäÖ•s½fÉÉß¾ø%s}ÒŠèÀD4n¼ý~1¦ž¼ß{´SbL=zat‹ @€ @€ @€è–Àýê×µüM|{Áš/²j£Ë¾Lôg²ÝP©[·t_œWŒ©/.“N @€ @€ @€ @€s'Л1¦5÷ÜÄ51¦ï^÷‚Éæ‡zd{1¦¹»‰ûðLbL}xÑt™ @€ @€ @€˜MÞŒ1e)¦l}ZIŒi6oÛ¾?¶Sß_B @€ @€ @€ @€fV cL¥SƘú´ “ÓÌÞ¨v41¦» †C€ @€ @€ @€LWàÿýú×ëxtí?ëÐnºóGwß;Î60©g/¾ý«¥S.¬ºûøIaV7þÁý^ÇÃãž"òaÓ½6ö\1¦Á½¶FF€ @€ @€ @€ „À¯þßc‹®{F-Æ´äæ Äà ‚À€“[ @€ @€ @€ ÐÓ×ß»_-ÔßÞùðÉ=Ýo#01¦ÉhÙ– @€ @€ @€ 0·mK1eŒIA¦¹½Î6»bL³ëëè @€ @€ @€ @€é<üØ-«Ö}6ÛÙßS¤—–ßùž²æÑ_n˜ÎÁíK wĘzçZè  @€ @€ @€ @ “À­1¦u?YމÀà ˆ1 Þ55" @€ @€ @€ @`0ĘóºUS@ŒÉ@€ @€ @€ @€è1¦þ¸Nz9%1¦)±Ù‰ @€ @€ @€ 0çbLsNî„s' Æ4wÖÎD€ @€ @€ @€˜Ž€ÓtôìÛãbL=~t @€ @€ @€ 0$ ÆäV`1¦¾¸†F€ @€ @€ @€ ”€Ó@]Nƒ- ÆäŽ @€ @€ @€ @€ô‡€S\'½œ’€Ó”ØìD€ @€ @€ @€˜s1¦9'w¹cš;kg"@€ @€ @€ @€LGà?:óU­Þ°×tb_½) ÆÔ›×E¯ @€ @€ @€ @€uŸüâΈ1­Z÷Y4O@Œi𮩠@€ @€ @€ @€ƒ)ð‹_=¼jýçÖÿdù`Ϩ淀Óü¾þFO€ @€ @€ @€ @ Ęzà"è @€ @€ @€ @ E`óã6§B`þˆ1ÍŸkm¤ @€ @€ @€ @€@߬Z¿JŒ©o®–ŽÎ„€ÓL(: @€ @€ @€ @`æÖ<¸fÓÃ6¶èºEfÚfé6±+7>`ã<É• ÷¸hXˆg£å–3w~G"Ð1¦. ;% @€ @€ @€ @ ³@„“¢ SlÑ¥Œ(Å·Wʽ"Ø´üÎåñ5òLñí#¿x¤<–@Ÿ ˆ1õé…Óm @€ @€ @€ @`²ðR5ºT*0Åú-­d}l5™²‰1 òÝ0?Æ&Æ4?®³Q @€ @€ @€ @€ý#¥Œ%U£KQŸ)*0ÅÊ 0eÂ)¾F‹õKo]Ú?ãÓSmĘÜ @€ @€ @€ @€Þ(E˜rò¸ì\†–baÁ9 "Ò fŠ…Ø, 2õÖô†À$Ę& fs @€ @€ @€ @€À, d5¦E×-Š|R9U|é¥hQx)ª4ÅúXÈ52L³|A~.ĘæBÙ9 @€ @€ @€ @€è Æäö @€ @€ @€ @€ @ ËbL]¾NO€ @€ @€ @€ @€€“{€ @€ @€ @€ Ðþ׆ÓÖ¼f̓‡÷Gwõ’ÀdĘ&£e[ @€ @€ @€ @€@÷~ò‹;YµÑªuŸí^œ™Àl ˆ1Í–¬ã @€ @€ @€ @€fV@Œif=­§æWŒécûØF&/°zõêžzݶíÌÃ?ü‚ýÍ™gžÙû]ÕCs&pçwþùÿù«¾x Ï™‰ @€ @€ @€ôµÀ}ÞõW/ú›ƒÙ¾¯G¡óÚ Ì¯ÓÖ[o½ß7Y÷àÏFµ~¶v¨=ºï7yÛ¿¿kíÞsÿHûÁý6Ú}Ñ~íîÒîýé]•vç½?½sÃ#Ùîȶ¾Ñnj?¹}ÝO¾_i·­ûÉmk‡Ú÷Öþ¸Ñîi´5¥ýàÇ·µÝúƒÝr÷H»ùî5Ú]vÓ]µ;¾±Òn¸ãáîx(ÛõÑnj×ÝþÐPûþ¯­´Õ·ý°´kn{ðšï µ«¿÷`£­i´UCí«ni+o}`å-CíÊ[¸ò–ûíæû¯¨´Ëoº¿Ùî‹vY´‡Ú¥7Þ×h74Ú%7Ü;Ô®¿÷âJ»èº{/ºnC´¥]»áÂJ[¾z}i¬^Á5CíükÖ7ÚÕë¢WÚªu玴µ‹N½üÿèYç\µ6ÚÙÙV®=k¨ÝsÖÊ{μòž¼øåË—/ïñwÈ0ýÍ&›uÂÙÿÚ7H2õøÅÒ½9ˆ ÓßlòŠãN½0¾J2Í» @€ @€ @€ÌžÀÈGÃÿä£áÙcvä® Ì»S•"¥Tk÷ ç–ö=à·þû»2Ã4fz)bLõÓPzi$ÃÔ 0uÊ0 ˜"É4¦áÓÄ2L?ìœaZµ¦CŒ©C†©cjd˜†cLC¦fŒi$ÃtÃè Óõ‘acºvÊjŒiõ†Ž1¦F†©cªd˜Ö³j$ÆT2LÃ1¦F†©_bLñƒê¥›lºø´ #ˆvÅ ë^ãÇU×ÞQ¸‡"ï‹3.\¯‹«nÉË$™zèêè  @€ @€ @€À|4<4»ô—Àü‹1pHµÒÒH\©™[ÚçëS½êR–_]Š:LwÞÛ’^®À4Á"L·UŠ0µ«ÃÔ(ÂÔ¦S³ÓÍ¥S,t®Ã4Í S³Óp¦X?Ã4“¥˜1¦Ù*Å4~ŒéÊ>¨ÆÔøAõ·‘aZµµ"®´Ë¯—dê¯÷a½yF†éo7=sŵåu±ü*I¦™wvD @€ @€ @€9ðÑðœQ;Qæ]ŒiŸ¯³}J©™UúÚ׿1¦¶¡¥œ?®L7jò¸úüq1‘\} ¹˜N®L!W«À4͉äÆÉ0Mn.¹–:Lsœašt)¦‘éä¢&S™N.š3ÊSŠ)&’ËIå:”bêñIå†~P¾"êl•¸FdÎ.½ní«ÿQ Á.¾µ:u72ÃtÖE×–×EÌŒ¯‹ V~_M¦n^ç&@€ @€ @€˜ª@ëGÃù˜†§*j¿˜w1¦*e ©m‹g·|û»š•–êÅ–Úæ–*U—ÚG—¦–^jSéî¬Àô£›J¦;§[„)S/¥]sÛƒÓŸKnZu˜&ašÖtr‘aj1µrm³ M'¦Œ1ºìœþøç¥ýìç¿ê…tþ :áô×ßþÐuߊ1åϪ«n}à’k#ÉôúÓ—Ñ ]Õs&¦³/º¶ùºh–(»í‡åuqþÊï¿øe¯Xuõ5sÖ'"@€ @€ @€ 0M OÐî}$0ïbL{ïÿÍZE¥ê·ñì–oßꎨ®TÚúG"«TÚíë#®”í'Yr)Zd•ªí¶Ñ…—†fŽ‹ùãîjkîùñPûÁojmæ»%¢KÃé¥Z€éÆIÏ"×ø8?rK¥0_„iÕ­#sÉ­¼õF»¥Ñ®l´ûíæF»¢´›î¿|¨ÝwùM÷]íÆ¡vé÷5Ú vÉ ÷–vñõ÷–vQc.¹ÑÓÉ]»aŵ.,mõä2Lç­ZwîHk˜ê1¦•kÏ®d˜Îj˜JŒéè–U‹iÅ=Óõyþ Z²ì¢š“–RL͸FãbÅE¹hõ=¯úÇןrê²Iõvýúõ›o¾ùÆÍG,¬Y³&v_µjU®É•ñˆ•e³òÔÃ<ãòåË7ÝtÓ|v›m¶É•±I¬,]Š#çѪ,çÍ•±}ŽO—ª O|DñYU~œŸÅAâcßÖÝ—.]š+ãS¶üÌ7¶ŒÏ£'~"[ÎCycúê~߬ƒjËñìoߪ’UWjM,ez©pÉåïEh©’[ªM·¦cz©]#½TŸ?î·o¸#ÚCÙâcûˆ³d‹7¯¡öýñLÃE˜"þ2ÔÖ<ØüÈ?Û™‰)­˜š¦v¦›[Læ¡S3Ã4V€)’LÈ0žK®2\Û¹äÆÊ0E’騜Tnì SVcêµS-ÃTûY+ã‘*[qÍ&›dŠŸ4 .ÌwÃø¹߯’Œ1•·ÈøT²Gµ§JÀ"2L±K|ͽ,Xé¥ü‘ßæúØ=×Ç1ËÊü1–+3®9Ø+3UÚ ” SfûZK”å»V¼.νâ{=¥$SføÊ dF.DÜám«ëpðx9´M>u(¯£¹RB€ @€ @€˜{ ç,=Óüh¸$â#°òð¸ÃŒsó®üy¬qó€ñqsl–oMê,ãvÃ)0cLg ¥j+µ”¾²ßÁ[¼m«Zu¥òmk\©¹¦™X+´”…—ZsK?øQ[ª¶Ñ饇;Mך^j`U~©e ¹ö˜&`É0T`ŠRL3^„éºÑE˜®³Ó׬o›aªaZwΪ‘:Lg_µ6Z‰1•¹äªu˜z³Sü zÙßnzⲋ¢(Wf×ZgÎjÄ5šy²¨ƒµüê¼ò&Z“)~l”²Iù–Ñ¢xÔ²J%{ŒcŠŸI‘Fª¾oƳH5EÒ"#M™p*‡ª¥C2)RýW~ä{±AMS 2Lñº8ûâë"ÜY/Å4\¢läuqã}g_>é$Sü‚7a~-½_ì2Û”¿áeb=¥ZR,äšüM.^_ùËY–‹GüÒ¬ýn—IÁüÅ®Z±,ÖÇ·q„|”Íj‡*'-½*ö:šæfw @€ @€ @€Àœ Ô>UÞ¢ñX3Æ4s —hóƒªR„"ÿÍ|ùô*‹0å'\cŠ5ùiWõ³³œç$?ð*Ÿ…å|>sèDý(0ïbLTj™ôm¤œÒWö=ø-oÛª]\i8«4:®4ªÌÒpb©ZŠ9ã†g‹'·ô£›ïê]ŠÀJ³ðÒèÚKSK/ —_º¦”_Š…‘òKÍ L•òK™ßÌ)äj³ÈM.À4E˜:O$·þü«×E;¯Ò:g˜¢ÓQKÕ˜J†©L$W]è©jLC?¨Îhd˜†JÎTg”«ÌœW§cj²_pÕÝL2ÅÏŒZ¥™ŒeV)¾æ#~•´ÓX1¦ÖâIeʹX(?ŸJŒ)~te!ÁøqXj8•wÕÚTtýøn«Ï³'¦s.¾näuñý¡™›Ó,ŽÊ¡7¦¹l¾.μtÍ_ÿÍ$f—‹;3_%„—·qÖFÊ„S¾LòwµøÍ,îÛ|¥T#P¹&~‡+õÉjÕ˜J¤¯l“¿–£årt&wŒnä1³S¾”âÛèU-2ïu4{7¡# @€ @€ @€fV ÍGÃÃ5>량†Ë¿Ì¯ö¼ü«ø2N|–,Ê µjLùmëggµÏªòc¬Rÿif¹m`æ]ŒéËû4T<©]¥xö-oÝ*ÂIÕÖ(§ÔÚ~P­±q¥‘ÄRD—j•–òÛÚlq£rK‘aº³Ñâ3øj›ht©Y'ê-UÛêÛ~XÚ5·ýðš1ÒKµS}þ¸Q¦ærÑ¢êR¥EVf¸Ý×È O!× ”6z¹K®¿7&+müYä&_„©>‘\K¦œHîÈFŒé™g­¼§µSI2õNŒ©þƒêŽÆÔYg+CiÕ¼m3ÆÔ¸1_PŸ·ò®Wþý¿œrê²Îo^ñc£VB©Ä˜6Úh£ŒeÒ¨§CŒ©6­i5Æ»—:OÕ¼m-“Õ•e޹yç5h“ajÉöÕrèåuqÆ%k^4á$SþRUñ•)s8Õ*e¹&v) ¤üõ.Ö”°y&ŸZg‚‹-Ë‹%guŒCÅB™Ø1ŸÍ9³XZž.•iª8o-èu4ƒwC @€ @€ @€fU`œò3ôÑpkŒ)>`ªfòó©ò)UνkÚÆ˜jŸÅfµSë‡Ñ³jèà}*0ïbL{í{PûXRsê·½öiĘbatE¥zJ)k,Ý2F\©]bit±¥1BK:"£'Œk”ÛÉvûP‹ØÊHë]jD[¦”^êP~iú¦jz)–'`Z¾z}LWZÛYäF˜ÚL$טNnåÚf¦¡SÛ"L½cj›aÊé䢵+93TŠ)cL]·áœ+ïÚt¼$Süh©F”â}-¾Íy¬Ê§Ú›ÝX1¦Ö mþXªþôŠ5QQ¦Ô¤©¹üäËoµr5}ú†«Û3.¦—Öê0• Sç×EóýgÅuN¿xBI¦ ×ÒE‰1Å+¨ìUûµ/#McLñlÎÜcŠ•¹{‰ý•CE’)§®+)(¯£¿÷ @€ @€ 0KÕ¹ä230RÞb6?ÎùFÊ´<ùUù Y“"¦cŠ}k©¦YÒsØ~˜1¦}*½µ.ì¹ÏA›¿õmk)ÕV•VÊKwU[en¸œ'®Yf©µÒRV]ªÕ[jÍ-E€©’[§êR&Zª…—:Í·æjí¥O/ÅœM )m ¦ W¯ÜRiT2LÍÓ$f‘;'¢KÙšE˜Ê,rGžÒ¨ÆÔû1¦øAY%ˆç’kþ Ê\C¥˜š5KÉ™Z)¦‹®kÄ5.¼vÃÙWÞÙ9É”u\J—Œ(ÅÊ)Ęr>¬R©T‚©&?âD9mj¼“–‰´b¹LÑÕïï°ú?«™a:»:—Üp†)³}YKs¬RL‘í[qmãuqÚE·¾p¼šLqV •e¥ê¯q±Au*ßLÆfe–Æœ¸dÌóµ>YW© U~í+³ÂµT®ºcõPÑF¬ÆgõZ88 @€ @€ @€ÀŒLû£á¡À&øÑp)'Qæ)å-bMÊšÎ1¦ÖÏÎb÷üû&.0ïbL{|í Q ¤2×[s!žSK2©cJ)³JcXŠ+µK,ZjäTÚä–2¹ÒaθZt©6mܪ[G¥—VÆ´q£fŽ{ ÌW«½tEëäq™?®Y ¨íüq A¶k‡ÞI#O­š^jWiL1‘\¤—Žè‡SùAÕ ½5êrÕ3LÕš·4¦ü‹iþ“ú5“dYŠ)U# væw¾â5f—ˉ±Ê#Sˆ1Å^ñƒ*SJñˆQ9—V­€Mä-ò‡_< ¹q™]5ßËTcšø{úüÙ²d˜ª¯‹òöXæÊ0 ½.î+¯‹,Å4ôº¸fýÒ·¼ð%/¿òª«Ç¬U#+‰¥åM›±ôüõ.ïä½'ç¾ÛãǘÊ[›jjîû:ý3n½õÖ{|íÀ¡ÔQ‰UâÙ7oùΑ † )u(§”)¥ÎY¥‘¸Rez¸œ'nô$qíCKcä–~ŸÓ—Ö¨;RÚš߼廞ýœç½è%û…½Žb$]zÍkÿõYÏy^|Í L]zÍ?5×üÓ¿®¼e8ºtËý]:舓_øâMâÙh›m±Udb¢}ࣟŠvYD—šé¥Øà[èÒÈÊd]{)Ó3c˜†ÒK­¦Õ£LÕòK1‘\û)ä®^wvΪµQx©´¶˜2À”mš1¦_üêáu?Y>ý;³Ã*?¨†¦Ì‚ÑþcÏó^ó±S¢½i÷3·Úã¼S/»;"hqù¶ÝgÅ«?zÊ;¿xîwÏ»­™a×8ÿêuË.»ãï:&™²?¥Ò48Ùãä1ù(ð௙Рj(ÃtÑuCï®Í÷ÒòVù™ÃWÆ‹â5—Æûpý¯‹¡ôd%Ï»zÝÉËÇI2ÍÈ™xy$Éôw @€ @€ @€@—}øñÕ'O¤c}4%Nª 7>[2öG`•É?Á†'ûyîDÆb¢jCæçªSâä.ãǘ"=—eÄrľ¶ŽÓ—ö>°<ª-dzcª­¼a¤RÎ÷PÛRŽ´fD©´QY¥áR:9#Xk«UZž'nì©âš'UK.}h§Ýß´åV‘UZqÍ]/zÉ&g^|c|»Ë§¿Ñ¥øúÆ-¶ŠÜR|åøt?×T /E†)ÒKqr¦—¶zï‡"±Ñ¥í?ú©hZ&7Þ÷‚oË3–^j-¿4Æüqñ>iƒ¡VI/E’©`J/µL!W 0M3ƦUë>{øêß»ð®­gïE‘?¨N8}EãÖºsF²ÔX²âŽ Ûîyô5[}鼏޻çÊm÷¹0.Ó1çݶÙngÔJ1E,ô‚ëôKoÿ»WwªÉ4{ƒrdc D†i»ßç5ÃLæk+¯‹¡ ã 32LïÚã¼Kn¸/^ñ¶ðÆÝÏ8â¬5»»ñºˆ·¬ÈöÅë¢VŠéükï*ñº8é‚›_б&Óô¯ÝÄcLÓ?—# @€ @€ @€t_ þ%|öÅu3ûÑp| – yÎ÷¢ªÅÒKî*åGã>[ݨâ£áî_}=h'SßDY‡xÄB-H7~Œ©TF‰jL1aM_#7bL_]8V)ÖdzoÚò¹Á¨XR~;:œ4NP©1%ܳµ+µÖXª$–&ZŠ·ªF½¥5#SÅ}âÓ_ŽS–\ŠÓQK΋XR³äR£êR,}m^Škr!sK¯þ§7|öË^žU—† /-<üäŒ1e†é3{õ–FZká¥f ˜Ëld渉LWI/M°üÒ¹Q~©RiÌÓpù¥R‡iÊ1¦[î¹ç¼5»E€éUE›½Sþ Z|ÚŠj€)o›k¢}ïÁˆ1°âŽ¼Ð‹—ßþÆOñä‹ïÌi³"òõªOiøÏÓ× m†ÀB, N½äû/õ?Ÿrê²¾~Qëü@ dŒ)Ûa¦Ì0µâÚÖ`_ΧE˜â&Ï×E¼×yÖšS.¹«ýë¢Yþ­üUÜâu±äü›^ðâN³ËM\±±iÚ @€ @€ ÐgcÊ6F˜©óGÃñX|4üéÃVæG`ª%Ÿ:㸠¾?îGÃY ÄGÃ}vÃ̃îFz©D—Ê´ƒeÜãǘbÓ8DÎYØï\cúâW¶M#eÁ¤/DŒi‹w¶)žTýíû#ù¤¥]j[]i¬Kù1|m†¸j¥¥ZŠyârz¸ÒoXÍ÷¬Ò>ò”¾d“ZÊ’KZŠ.5sK±Ü 0Ý—Ñ¥øö¸Ó/‹(L^ŠÖ0íØhïØúC‘aŠ–¦ÓÆÍFzé¼±Ë/eþ ÑV6ÚYvO¶Zni:1¦0sënß¹úw3À4«1¦øAõ7›42L×5ï·¼†n›¼CÖ4~Ví|à¥ÿyØÊÿüÎÊøAuð©7ÅuÌ«öÅ#¯Ž¼íW»6æï»°Yìª *9Óàj-½X’©ßßÕ«ÿÕS»0Sd˜âuqæŠkÇz]D°/bL%Ôozw¶Úë¢%Û×ø._WÞ³ä¼ÙM2 Ö53 @€ @€ @€ŽÕS»0ÓÄ>>#>^|áíQÞâ›§Þ՘μò“øhøJ »K{N j2m¾ùæFªõlB1¦Ø'æ•‹£ SÏl2ŠÓ¾²p¬ÚH±>ž}ãïè°ÁDÂI%·Ô(™ÓhF8©µµ+µO,U*-uÎ-e½¥lqrLwÄ çVë-]1ZjF—FrKZÊOºüúœ0.ZÄ•¶Ûq·lÏ|Îó>½çÂWýãb93LQ˜®Ñ&PxéÂfá“j»`bµ—&™^0Q~iŠ1¦·˜2ÆtâÍ/ŠÙåf¶-¿e׿ÙäÇŸva5½Ô(Â4`Ê4[NzzüòïG½™íöYI¦üA—,&›‹ Ó¿í¶lé¥w¥ùHÉ™fÞ¶¼†’L{/xüÔÏjº,pø{F¢è%“>\™©™azÅ®•êýº8aÅíñK[³øÜýµ Sëë"Þ‚j¥˜Êëb(Étð.]ñªìG ~ü—MæwÛ @€ Ð ¬ö| @€˜#ã?Úþ#°fe¦f†iB ǧ`oÜýŒøPx«/{ÐÒ›&ôÑp³Hý£aÓõtãC³U *åìrK—.­>;~Œ©Ì€I¦~/È1¦Ïea‡òHñìßòŽñê' ‡“ÆÈ'eb©žRj–Ï)­C©¶Æ¬pÕ‰áÚÄ•FWZúœ~8´ØçgöÙ>÷•ƒ2ÔóÄUë-År–\ªæ–²êRF—¢ØÒ—8²:gÜ þz“H/Et)ª1Etéäó¯{泟÷õïœÔvθœÂ¬´ D—U‚b²³œïl¤M®öÒDË/M!ÆôÒM_úí‹^^­ÀT]>ôê‘ÊLcm3Ùõÿ¶ÝF[¾ã½#%»Ê5tÏ •àŠSd˜†³÷ÇO¬cοmÙåw_2”-Û1¦£ÎþÞP)¦¦mµäL¡8ôøåÿç÷ŸôÃ÷?¥ýÏjšÄ2n ,xÆÖoù—òžó*Ö‚}Y„)~‹ ÓðD™÷xÊMŸúö•ñºÈØeÔ'«½.âEј›²ñ ÜÚêûÃ'¿tà¿müÔŸoÿ$¯ “ˆºb @€ô¸Àgþ÷¤ÕïÖÿ;/ @€,ð±ßûì¶[lÿ‘Otþh8>‹†ÿó;WÖþù,>¸o÷Ñpã#°œ¤| ¶ßw–¾èÅ/}ôç¿êñÿiÓ½ˆ SŽqæc1¦˜Ž®D—.\ú+bLŸûò7ÚÖFÊ•ñlĘj´ $µ›÷mìˆRÆ•†‚J­“ÁÕg…kW©±”%Fj¡¥’^ÊÐÒW¦ ®º£Ô[zõ?½á+ß8*rK ?ùÕÿø†ˆ+Å×X¡¥…‡5ÖTCK‘aŠÜÒ)ç_—õ–"À߯ÇÿÛ~d·h]Ú}Ï…õ×/‹@@„–j¹¥F€itÕ¥FŒ¦Má¥õ]ª¥—š‘‚ÒÖÆTñÞZZËÌq“«½Ô:Áܧ\þ‡ôÌÎϽàÅ/?ú„e+ïX¶øúW¶’θí_ÖýdùŒ·Ï~ö³ñãjäÞ`šñt÷ÆŒ§9!`˜"½?¨Þÿµ ¿päÕIý®ÝðªO9þ‚ÛëÓÉUò¶1ðØä导ðœóo»lù£7^øx|ú®è–Àùûµù#ò‚g<~Þ~QÞ&o~ó›~ûø¡×E3šï®ù.šáÎ^ÅÉòu±üšõ›}ꌽ¿¶ý뢖í«ÌAùÅý½ö_þíÆË/‹×ÅÏoò¢ 0a“>Ù¸‡Å˜úú—E'@€˜'»=÷ñøwÏÝúÿ_ç%@€ @`^ \ul›À>ö{ZP>ÿ–1†q?Þý;WæG`¥Óø G†©ò؋Ί†¯¾ùžÛÖþD’ižüïoosÑ¢Ee.¹Xˆ0Ò$bL±iL$I¦|”ÊL½9Ôq{ÕxýïõjU¤Úr<»Ù[ÞÑR*©V9©|;œLʈRósôέ‘>ÉvK½U烚nì¸Rä–2±4ÜÓÃ5Þ°š-2LQl©´ÃŸsÜé—E¥l±¡¥cO¿´¬‰åL,•Ñ¥¨·é¥h¯ú‡×÷ÔK#³íG>­D—þuówF«êÒ¤¢Kµiã²2J=ºÔ Š6²¢CížxíæF;G‘Æzvâ1¦x+Öfºð®­Ç½ñ¦¶A$™¶ûð'Jn(¨1œÕˆ([T ŒèR¶ÌjD¦Ó/»{³Ý–EØ6ÚG¾~q3ô~¨ÓèéäF2L—ߘ£óãjjWÊ^3&¿°VÓôærüL2ðíãG¥—†ßQK¦m›s,F‹—Ænߺ"ÞÙNkóº¨Ô'íÊ0Ý~y]üü—é3v‘ü@—.Æ4à—Øð @€F bLû¼f`Fc  @€ô´ÀƒwŽú¬`*ÝŽ$Ãg÷úFç†wÿvĘF2Lc|6üÑðèéäâ£áj†ÉGÃ=}ÃÌÎE¥Œ!µVSR¹$вL`•/þI£xöß6ÿ÷qÓHíg|#Ÿ”‰¥fJitQ¥Žu•j–jq¥’X*ÃåÂÈÜpÃ3ÄE½¥Riié×år‰+•’K9ÝÒE×ekÔ[ŠvÒù×6BKc–\ÚÐy¸ Ð4Z»ªKm¢Kã§—šÑ¥™H/•TÓdcLù†~õ]gœ¶æ5Y™iöbLñŠ‹$Ó¶Þ%§Ê¾‘†f¬&mó*_ÄF¦¥—Þ•I²’aÊpXµfàP¦J†É«x—ëï!”SK€©Œk(Éô­ãK$´ä>‡óCo†']tgû×E›lßÈtr­¦|]H2õ÷­5g½cš3j'"@€ 0M1¦iÚ @€‰ ”S»S9L 3äGÃc}6æGã?‹†õA†§“kÍ0ùhxâЖs,0ÑÓwk–N¯üÏìùÖJHeM<1¦”§ÚÇ’"™”m¸ÒX³¿•”RK]¥F¸Ò²ºR£5SJ¥µ+UKÕIâj•–òÛÖÐÒPbi8´Ônª¸zniÌ’K× ÍW›0®G¢KÕÊLS‹1ݹ¡1McL$a¦Y1ÅY"ÉôþvÉ›*o›Ì´å]wB‰¦e-/\É0Å%hNÒ7œa®8V†©õÇÕ÷–-ºæ;{üòÑ¡™)ËkóÑÖßµbé,½Tvž DŒiìS1É$Óþ‡×òºz·¬½.2‹9ôºhù®ší+ÃTM2­[µ<^ñµv¼"æéM[¶“û€ @€@¿ˆ1õË•ÒO @€ 1¦Ž¦2ÄÈ3|zÏ&øXëGÃ9EOëGÃce˜$™àæÈ!Ì»ÓÐ˾äFGŽ>½Çcª…Ê·ÕìÑ„–GÍûVŸ®: \kP©Mi¥È¬Ü0Ôª)¥‘åÑÕôR#±4Tii¨ÌRã­´kð· -5£0mê-EŸkFÚP½¥‰æ–Ö3ºäR£>Pi³0gܸ3ÍM'Æ”ïþrCÛ·†MÛtý#3SÃ,“L#•f†LCÁµÌ¥5/hÎñ×È0 ×ÁšN.ë0M,ÃTýqõÀÍ«–n³i$™ZÇIŽhù¶hP]ˆÙùØDÎ^’LÕ LCo›ÃÅÉF½.V¼.Æú®s†©$™ŽÛ|ãxEüèî5µ~zELä þ6bLƒ @`PĘåJ @€>ˆÏ¿âS°‰=I¦=ë£á¡’%>®—·èœa’dšØe±Õœ Ì¿Só5?V‹w„Ýü߯¸éþhÃó¸»0R<©M¥vµ”ÚOW™n¬ºJµ)áje–*q¥‘‰áF%–:TZjZj-¶42OÜ„sK°gÇÙâšñšFÂfÆ'Œ7ÃL?ÆÔöõºjýªØx̓ C|/y¦òЍ­÷Š˜½{ ,ÆÔ‹WEŸ @€´cr_ @€ ЫïØê?vßãëí?«–·hóÏø×5ʈTÊ[L$Ô ÷*†~ÍGycúÏxÁ—™ÚZâíà_ßüïõ FOèV›ß­Ó\o™L*m¸–Rç”R‰§´ nh>¸¡êJS‰+5 ö´”YʪKŒ®´4~héêu-óÄ5‹Ô•[j¾iç–º]š©Iå:¼a,8gATcZ¸ráò;—o~ÜæÑö¸hRŸ)rK±»o³t›hÕ§:3’Lïûà‚¡â[£Le¬öY)e˜¢'1mVž‰S,¬øÂ6Ñ¢ÞLd5r.¹x*¾Æš\߯féˆ reì8ßSy2É´ÏÁǶ}]”âdï‹uÓÌ0=ò£½`óh7¿0 2Õnõ|EÄ« ×ç×X Œ…9´qª. ˆ1u Þi  @€LZ@ŒiÒdv @€ @`îI¦/}}b þ¬òѰ ÓÜ]0gšQycŠWû¨hÑè¤Q<û†7ÿ{û *!¤2¹[.´Ÿâ-Šå´¶1æ}«&–†Š*µ *ÕK+u¬®ÔŒ+µ™n¬ÄÒTCKç‰ë½ÜR­DÓ,UcŠdR´x©Fž)‚JùšúL¹ñ¦x6N¹fÑu‹rûÎH2½÷ƒ †¢l9-`s¹¼Ð™B;?²ecLz:ñ:L¥™ÌˆjL‘ÛÈ•9sVÔ›ÉLF|ͧ"½-ñ5·Úïzz~2ÉôµƒéðºhÌ}9üºÈe5„>‘¹ä¢ÓÏÙ¡—;¼¼"râÅòŠÈ _lkb›êLs±^•²¸ä=~1¦¿@ºG€ @ ˆ1¹ @€èmH2}ê‹_ŸòGÃ2L½}yõ®“À¼‹1}ª„ÛÅŒâÙ7¼éíãÄ’®šÌk¬jIãTQÉ'ª¥¥6)¥JPi(°’±•j[=fu¥¶–*q¥õçWæ†ËùGµUQZ©Þ!€ÑÅ–™€ÒšÅ–zªÞRç©åf)ÆÅ–¢äR¼òb!ç+˜b9ÒK‘aŠxS<›µšba"1¦Ø·‘dúÀÇGLó]Ö±³SÈ0•dFœ7‹ÐD˪KYŸ)ÖGù¥X™%šbûx¶º¥w_s I¦½:¦ì+ÅÉF2LWM+ÃcÉÄR,Du¥¼Õ³ØRyEÄSñÒˆB–bŠ…Ø l)Æ4÷C—O!ÆÔå àô @€&, Æ4a* @€ Ð-H2íö…ýÇÿ¬åŸñË0uë’9ïŒÌ¿S3±8V‹<ãëßôöÖgG*$E©´ë"‡TmRkk¼­´m×6Jé”V'Õ³JI߯j­“ÁE¨eq¥ösõ™.K}Zj4ÍRŒ©^* ¥>S¼ncåúGÖG hé­ÙÙâõ™&þzŽ$ÓÖøx)µU 0e¦¡ËT™ôt ¦èOIfä,ZÙÃŒqDD#Ödž)·Œ¸FÎ(—›Å69÷œ9È$ÓW<¦íë"ã˜Cï]•׍ê0•û?âæÏ_¸HºH€ @ ) ÆäF @€ @ O"É´ëç÷ç£ááÀd˜úäªêf'ycjd[çe^ÏþËß>Na¤±vï8¹[§BJcG”FWTªÏ×f¸œ®ÝdpÃÓõ™nT¥J\©MbiåH`"!¡Þßf–bLQ])Ú#¿x$&+¯¿,Èu˜Jí¥H2ÅšI•b*G‹$Ó»·ß9“j¥ØLãR6L%«1µ:Ly–H)•B2iŠ–u˜â©üšÛ”§âÛÜ ZViò 0—™dúò7Ž®¼.† ÈU‚}SË0Å@Jù±XŽSÞçY„©¼"bMí%[Æ+e.)œ«kbL]£wb @€“cš$˜Í  @€è¢@$™>ñ¹ýÆúh¸|(/ÃÔÅkäÔ3(0ïbLTì0;[<1¦´>5T*) &u $Uk)UJ(e-¥u6n-¥L)M$¨Ô¬>ÒÚÎŽ˜Ki+‘—lÍâ=ÍøKiÃÍÞ"M§‡³cšÁ—h‡CE’é?¶Ûyd¹«†.b™N†in†à,fV “L{ptV& ö­*Â4å ÓÌöÓÑV@Œi`/­ @€ œ€ÓÀ]R"@€ 0Ø‘dÚå³ûuøhX†i°o€y5ºycŠ”âX³³Åúx6bL6h)T&t«ÌìÖH*ù¤6³¼•dÒp>©c-¥¬»Ó¬¨4‘ RûÒJó1®4VÔ©¯cLñVÕH2m»s#š6ºØLΗ·ÉË_yáå7Þ¶ö'Ú£?ÿÕ¼zË3ØÈ$Ó¯‹êìŠSžKnàÅ p&ĘfRÓ± @€̦€Ólê:6 @€³!I¦ŸÝ·íGÃ2L³î˜Ý˜1¦ZÑ£ê·cúçÍÞ6‰ÔQ-„4•LÒÐŒ`ãæ“†*‹TË)år›¢J£ƒJ7ÜtÊ/Õöí÷S¼qD’é]ÛîTf‘ËÊ0uë-Õy{A “L_úú¢Úëý‹û/zí¿üÛ·ßß!Ø·öŸýü—²}½pû³bLýyÝôš @`> ˆ1ÍÇ«nÌ @€ú^ ’Lÿ̾µÀd˜úþºÀhycÊJkcµxöu›½­ÃxjmTK)˜4Fͤq¦{k7ï[eê·–”’ ÒT§À€S&™¶zÿNæ’óöN d’)rKåu!Ãäö˜ 1¦¹Pv @€3! Æ4ŠŽA€ @€ÀÜ D’içO$™d˜æþ8ãl Ì»S”Yk•5ñìëþím6èðT£0RçV)›TJ(5ç<ª¶{ΊLR­M5£3ƒU‹õPƒcŠ·‰’dR‡i¶ß4¿_ªI&¦~¹j}ßO1¦¾¿„@€ 0oĘæÍ¥6P @€ƒ'P’L2Lƒwq(æ]Œéí[ï°÷7Oh´ƒÛ´·¿{‡¿yùkÚ>U[ùÕƒO£-þêÁã·¯¼XëO~éÀÿïþAçž<ïùqô ˪³Pݹá‘|ûˆ$Ó›ÿýý›¼ü•^~c‡9³â©Gnά¼€º4ó‘dú—7ükÔ*ûÇþsÉͼ¯#¶ ˆ1¹+ @€ô‹€S¿\)ý$@€ @ @$™â#°M^ú²«o¾ÇGÃ_1¦c=ö5£‘ù¨¶¼è%¶ñÿ®­ôí ¼t“W<ëÙÏí<ÀW½æŸ.[}[ïǘâ½i¶—a°÷hÙ¦À÷ŸýÏ[ÿ÷3®9¢Ã/pkøÙÏ)Û7Mi»7ĘÜ @€úE@Œ©_®”~ @€ ÐVàÁ;?ñ7¿}õ·¿(Ãä<ùcj½~_Õž%ÐV 7«1=þËÇ_ðŒ^vJ‡«¦ÓཉQgu?Y~Ȫ.»}ÑX¯ &·ÐL ˆ1ͤ¦c @€˜M1¦ÙÔul @€f]àÁ;ßn£.ÙÃGóNís. ÆôI“èÑÓyûÅϪǿø¢þøçmG$Ã4ço°NØ}Œ1Ýúàá÷>ôXëëB†©ûWhÀz Æ4`Ôp @€X@Œi€/®¡ @€˜ÍÓã§~ÖGÃóájÏ·1Š1‰1˜´@/Ƙš¥˜?«¢­>¹õÇ• Ó|{s7Þøù¯Ž$Ó£¿Ü˵$“ “›dæĘfÞÔ  @€ÌŽ€Óì¸:* @€s$Ÿ¯Yþx„™ÜGÃsdî4s% Æ4éËd+÷Ø~ðz1Æ”¥˜²}ñEµW2LsõŽê<]xätîAI2É0uùR êéŘõÊ @€Àà ˆ1 Þ55" @€ƒ(ð½e‹®ùο|´þØ£¬¿kÅÒ2âj’ÉGÃx#̯1‰1‰1˜´@ÏŘª¥˜† 2Å;Yþ¸òƒj~½©ÏãÑ.½ué6K· ’L?¸ÿÑŸÿòWãni“cš4™ @€tI@Œ©KðNK€ @€ÀĸyÕÒm6$Së.‘mŠV]ï£á‰ÃÚ²Çæ{Œé§ýW¼ž;´{ø³~ôXçm<;Hq¹ï{hœ+·Mo½°«¥˜*™¢“²½u¥ôfÖ¢Ó‚sìqQã×µ5®‰¯«Ö¯*˱°þ‘õyòÿ÷ë__qϪ|ÖƒÀ ˆ1Í0¨Ã @€˜51¦Y£u` @€fD *0]¾ÿ‚hYŠéGw¯‰TSaʃG¼)¾­­Ï†c}>åA Oæ{Œ©O/›nh-ÅT)ÈŠÀ<X~çòØ8’L‘gÚô°M7?nó¨Ì+K}¦XÑ¥H8ÅB¤b}lîë˧óÄ˜Ü EÀϪA¹’Æ1ƒbL3ˆéPã ˆ1od  @€½! ÆÔ×A/ @€˜¢€†§g·>cꃋ¤‹&$àgÕ„˜l4¿Ęæ×õîúhŘº~ t€ @€ÀĘ&e3 @€zSÀGýy]ôj&ĘfBÑ1ô‚À/{|ÍòÇã'–ÃbLî…9cšSn'#@€ 0 oýûã‹?6ýíJ€ @€® ˆ1u•ßÉgU@ŒiVyœÀÌ \ó=Î^°ù÷–-ªzݪåñÔÌŸÏ ô³€S?_½>ì»S^4]&@€ @€ @€ý' ÆÔ×L'* Æ4Q)Ûè¥Ûlúèë[;sùþ n<~atR7ôˆ€S\ˆùÒ 1¦ùr¥“ @ ?îZ±ô¸Í7Ž?¤´v·íÊþ•^ @€ @ Ę܃+ Æ4¸×ÖÈNà—>Y¥ø\Æ•âk”_*e™âpܼ*ÖÇšX_"M‘yŠo£ýèî5Gb@Æcr‹Ì©€Óœr; @€qV|a›H2µn*cr÷ @€ ÐßbLý}ýô¾“€“ûƒ@? Äà"ɤøs[•"·k2±ñ¦ø¦X“ë£åæâovÑü…®Ÿ®´¾Î€Ó A:ÌÄĘ&æd+ @€s ÉRLñW”ø«ÈÙ 6ÿÊ+N½nÕòXŽ…ÚúX{å–sÐC§ @€ @€ÀÔʦngÏ^cêõ+¤ª¥äR^Н‘jÊJK™RŠHSþ….–ãküõ­”kŠ-s/óG@Œiþ\ëž©SO\ @€ ЈšÖù/¾â!ñ§’ø6–óï*Yµ:¾ b}´ü[J¤—ò¯(ñוø‹ G @€ô®€Sï^=›®€ÓtíO`.ª€ËDkâpñW¶H)eOb9þú–ÿp0žÍD­Ä›æ²ÃÎE`î|tõ!«6«ÝùðÉsß%gdÕ'?¾ÝFc¶Ïä± @€ÈôRv0–£Sþ%ÿ%XþC¯Xˆ¸R<Ëe}<MA¦¾¶ºF€ @€ÀãÿxC㳉ã?Æ‚Àà ˆ1 Þ55¢Èâò¯lQö<Ê¿,Œ S¤—²üRŽ?ÿ$_c¯ÜÒ¿#Ø;ÃÀZÎþþ›ÛƘ–Üü"Zf^à‹/jcŠõ @€tI ”\Š¿‡d±êø;Iþó°üšüÇ`Yë:ÿÁX¶(ÈÔ¥Ž;- @€&&1¦#¶žØ¦¶"ÐObLýtµôuž Ä¿Ì(Rüq-âojñ5ÿôV*-Å·ù§· 0åB~-³ËÍsFßcdRŠi>\ý.Œq¬‚L±Þƒ @€. D&)K.•ÐR$“ò¯%ùÄbƒüGbùÏÀâ¯.¥Sü½%Ÿò @€ @€@ï ˆ1õîµÑ³i ˆ1M‹ÏÎæR **EË3f…ó\(_kOå·Q¢)¶ÉšLæ@kA&¥˜æÏÕïÂH[ 2)ÅÔ…Ëà” @€FÊŒr‘IŠåˆ(Å¿ûНñ¯¼ò‰EP)N±¦üÓ¯\ÎâL(  @€ ÐëbL½~…ôoŠbLS„³ô²@kA&¥˜zùzõ}ßZ 2)ÅÔ÷Õ @€ @€ @€@ ˆ1õðÅѵéˆ1MGϾ лÕ‚LJ1õîu˜žU 2)Å40—Õ@ @€ @€ @€@o ˆ1õæuÑ«i ˆ1M›Ð @ 'ª™”bêÉK4XªdRŠi°®­Ñ @€ @€ @€žcê¹K¢C3# Æ43ŽŽB ûÞùxü¬:õ³Ýï‰è,ȤSÏ\AïHdRŠiЯ³ñ @€ ‚Àyû?~Ùƒ0c @€ @`Þ ˆ1ÍÛK?ècô+l|óG@Œiþ\k#°@dRŠiÂ`6œž@dRŠizŠö&@€ 0»=÷ñ}^3'r @€Ì’€Ó,Á:l·æWŒiõêÕŸíøØ}÷ÝwØa‡ÎÛxvÀ¶ß~ûÎ#Úk¯½{ì±n¿T'pþï¼üÍ=¶d÷ ljóHà˜s¶ŸG£5Ôn ¬þ»Ýç'@€ @`|;?ô̇¿´éøÛÙbÂþîÚ/2¿…>üðÃãÜóŽ{L_ >ûˆO@:çÎ;ïœðëÞ†æ…À~ûí×ùUãý­æ3.H΋[Ç Ì€ÓÜ8;Ëœ ̯ÓÖ[oý/oØìãŸØ½´?±ûHÛe÷~ýfñ—/Øy—OEÛ©m[ð©|êcc´.Øí£oÓvüønCmçÝv¬´ì¼[¥}ò#; µïôɶm‡}²µ}èc»µîú¡JûàGw­·wýàŽ»~`¤}â;Ž´í?ò‰¶m»|¢Ñ>\m»l÷á]¶­µvÙv‡]Þ?FÛæC»4Û‚Z{߇4Úëí½\0ª}`Á{?ðñh[·kïÙþãmÛ»·ÿx£m·s­ýÇv;—¶ù;Þÿߟú´ÿØvçh覆޵íNïzÿNøGÏ\¾|ùœ¿6'}Â3Ï<óo6yÅ›ÿñåýºšôøì@`*‡~øŸÿŸ¿ŠÿšÊÎö!0I¸Óâ~‹»n’ûÙœ @€9ˆéãO(Ñ"{1§'è“UÿîZû‹ëλìkýç×ÿ[üÝuÔ_\ÇþCkëŸXÛþ}µõ/«ü›jë_S;þµÓ_PÛþítÔNÇø«iÛ¿—¶þ±´õo¤üióO££þ.šÝh£ Í?‡¶üE´ñ·Ðç=ÿ/&û?¶±}\Ü6ro\úÆÕÿv;<íw·þ÷ö±þÆÞáìíÿ´Þéêüsú¨`Ô_ÑÇùûyË 0úÏæcÿͼõ¯å¹úmÿBÞú·ñÖ«!ëþ‡ü¬×ýÛ[ǼúÛîôòWÿs¼–ú½ÊàLN ~gˆ·¯|«|˜Øø ±|Œl³í­V–Õ>"¬ýüªýðýÆÕüpø³¿‘7«vïTµÏø*íUÞšÚ½/Uß‘jïE#?†šŸÓUÕÞ|òç-ÍÝò=g¨ÕÜìô”§>Mbrr7¢­ tcr{ ¨À¼‹1í÷CÖ=ð³lk‡Ú£kjû~ã·þû»î¹ÿÑÒ~pÿ£v_´ŸF»»´{zW¥ÝyïOïÜðHiwlxäŽõCíöõ4ÛOn_÷“ïWÚmkRÚ÷Öþ¸Ñîi´5¥ýàÇ·µÝúƒÝr÷H»ùîÝ|W¶‡oÊvg£ÝXi7Üñÿ³÷'Psgž/ÌÌ9÷Nß™3sû;÷»§Ým Ý=—¹ýMO»ñбeÛm›Õ Œ1›mÚòÂb±ãÆľ#‹Ù$!B }G í•’Ú­ ±·ÀÆØúþ™ÿ¬§¢r«¬zkÉÌú׉óž|³r‰üGTdÄ¿xž·Vn|“iÒ† =¿áM/­Gzã¹JZ¾î KËÖ½±lÝ®e/yi©¥µ»úªiç’5Õ´xÍÎÅ/iÑ‹¯{iµ—:iÁ ¯ûé5¤g‘Vé™U¯yi¥—æ¯ÜÁôôŠjš·bǼ瑶#͵ôÜö9Nš½|›¥YË·ÍZ¤™Ë¶Í\¶uæR/ͰԷuz5m1qÁ_ýõ>Ó–l™jiñ–)AÚzÔQG‰d*i‹­ÇjLÑŽüîñhÜ0~ÉÔ˜v:ºqPÇ£¾}çèã5ø6~7!¤€R@ H) ¤@“ ø Ó€Is–?2qÎgD25©bÌi@Ìî5ºÂÖzã­ÝÕl­‰†ÖŠ•ÕL¬±öÕËj¼YµÆ¦jÕÀšêTÍšj¦T³£FÔ oš5T×|šd8XMÍdjöÒ°±4ÁRê›Ii’uÔ5ÖÚEiÆ4­o Ì¡U‹èâ-Sͺhó7ÿ^££Zìñ?غ+ÞäŽÒ_°tõÞûü-6\c{l¨1°WlìQëzš]=΢î•~`Q¯šÓSJ¶ôŠ=Æ„îÙÏãK&ô³¹ÙÌûWú^,äÏmŸk Î6n†q³Š³ôÿù3^w×–~PjKÿì_ß(Œ©uí¢®TÐmØgß¿­Ì'3‰›wÖÌ!¢}{¦ï¶i6oÈÖ¬öEV"d#V3-Xi»^¬Ì²Õ²@6Y|[Õ¼ªÖï)ç åÌ i²é“1LAŸ)‚19 ÓVôŸÂ“;l[¼yÊ¢b`Ld˜¿°Í+¾—vÝö»Ñ"™ZÝTêzÅSÀg˜N`û†ß\ʉd*^)'Ç>Ãt¾Õ·#D2§ì”S) ¤€R@ HžRsfŸ;`Àä9Ï¡÷aÔ„9Ÿù¼|2µ¦ }H±»ÂÜzí®é+E]€©añÖˆÆ.M^a˜ÚI±¸¶S[ÿéÌûVÓ˜eŸ5k>mÁgüjÏÐRÏ8ŒÉVxú‹7ì.﬇1yK:amcòÖ'XÝQúÏúSÆÒLü‡W·‰a “ÞJà4†É5žWÇ2LAé» ±Å,÷ ¯õmÄæbLFø[Pú˜ZÓ ê*%R=ÂŒL)V¦=t‰S`jŽa²ÙÀò²݆ˆÛmIŒ©†³´y½Ê¤_LÁ\^å­TõAPƒ1Õ8HÁ˜j^=Œ©2…&½ÖFS‰~"z”( Œ)… ,´CžÃ˜0`ºU7KUgK7Ür'F\Õ… ô½ƒ.E|/…©êL LpÅ0Uü0Å.rqìŒ~˜f˜B J²2Lž+&oiQÅS00ë'ÃäàÞÃÔ +&0àQŒ)äŠ)ÿÞ˜<†é[‡-^½Ý¦Ïa7¹U$S;ÚK]³8 x Ó1'` g¿ ˜“àÑ]$SqʰH9E½‚?g«opdˆúvøÀã]½Z¤gV^¥€R@ H) ¤@ð¦/ ˜2÷9  \ñʨñ³E2µ¤01ÕØ]=ßö5îí¯7»kÔÖZÏÉ}"ÀqoëÛ¾Q?L=ñd¤Xü ã°÷ú¦\1ÅxÂðüa4âŒ'ðÆ”äŒÇ÷Lß4ÆTµº;¥Ïø˜àÇ4?-í!c{8ÄA_sC¬s¬ë­%Ø22Lîà ŽA½ ¸bª5•[È‚p¼‚ÚU¾Ñ0QWLæÅÃ˜î ¼1…œ£0.0¦–´‡ºH™ Æäø>ð^m5sˆ;<ŒiþcŠú“ 9“³F,ÖS:Ãä»bª‰¾Â¸+t˜Å([FV‰wÅäNÞŸbª¼ƒª®àoLt.`-½1ÅbLþì›ÇË c*ÓoDÏÒ}„1u¿ ”ƒ¶(ÐsÌaJ©Â*a…oùþIn´8n‡\.µƒ.…|/…ãÇÕÐK¾£ÈÊ»(rÑ@rµ®ÍŸdµ+S‰%g>Ý$!€©~˜ZÄ0ÁeeáäÂëàA× 'GW–Ęj—žTWŸ`ä–sŒ‰ Ó’·‡¦ÏѽånùdjK£©‹æ_2L´9²¡#V‚ßÅOOÉ”ÿ,XÉ0yõÍ·`Á“Õ7‘L+KeW H) ¤€R Ô  Ó¼çÜ/¾#Ÿýiùdêwécб»:ÌŠkwÝäÌõV ­ÛÞƒ‰5Íý‚'ˆÂ˜ÖÆ…{±J¬—çåj 9ךjzÚÂ0ÕºbJd˜ZI±Ä»br1¦Xg<ýÁ˜¢kƒXÂ?¦ù£®JBA—²”~8 ÓæwÖ"¹¥_‰Ç[ú±‘»Â0‹~Í÷IBé{±œqÄeq¢Ž¸‚ r>Æc÷-á˜úÝêeS€Sˆ[ Í!î½Ï¾O/~!ô:KІióƒ^Ûå4_¡Xr«1ý~šÈ0Ùd_œ+¦°—¸ì®˜,vJöˆr˜†s1¦š¦•ˆrhj„1•íw¢ç鮘º«¿îÞ6zcŠRJ>¨ä±J×Ý ŒéDw Hu(U -9cªÀ«m]Â"!so`§ÐK1!äâ<0¹#®€Éx×xÁ8a âyWWù+Ò*îpk¢z{Èv…Ú®úŸŒwŒÌˆr­ðÃÔJ†É 'ÇøßUŒ)NÎ_}bÓ˜ñS¶ì|ßÒëoý¾m?É. †éß:¬ïÅí±Óç(š›ï~äÃŽØýþû \Ô?´¯òiôÄοvíÚ¶Þ´…ׇ¨-¼Z[ŸºÐÃtÔ1'xæ'ßõw°¾ÖؼšüäôsϿ𒦟åØô¹ž­0í»;ïÕ¾ë7úìÑãÓsÕ*ýçÖªß#¦ÓÎ<ŸõÍu‰‡ú†%êÛa:ìžæÿ½÷Þë@£»àÓ\»{VÕz6qVwSw—R@ H) ¤€h‰d˜¦Î{>vÅ L(#ÆÍÉ´s×›-¹]o^„SÌêЊ§%×†ÖŠßx%db]ë©_K‹¢‰/¦ÖR,ž£zßF:Å£è^{íE»¨²¸ÑŠ-Þ˜е…n{£ŽuÖ˜„µÁoLðcš?ꧤ\ ‹)ýt|-3ÀK°Å®vœ`åÒ.ÏÓ½p¹–ó?Lé¥??[8¹G\né/‹ &è¯ïÝbޘ¥_1†c:ö¸¸¥í?~ôçÞlÖôÔR crßn!-Ú·y‹_‘¸æG0êF.0¹s‚tc©Ä’K÷ÔÊ0íê« 'rÅTÅjãJú„3‡psÝIºåñ®˜ˆ1ýUà©&¢\àŠÉom€1-Xö¢ÛÔìz'“nªóR  c*d±)Óõè9Œ æGµ•‘óµ>ÆÄÞ†%š¶ô.±ƒXŠBKQni½.%8^ª¬ ‚Ç¥ÐKv¯ãCÈU<050…`>Àätçô4¬»; îîLîìY¬)±TqJÉXïæ#×íÍC¯ÈRËü0U& ׇÓS2ÃDoL#Ç<åBi¨Bõ[m>‚ ÓÒ5;°V,ºŽÓç W¿~Ó]|hc$¦xaÎà¸ß~û <¸}O³mÛ¶#F4zý &pv9äœtÝL2¤Ñ»àʡѳ¢Ç#«¸rˆÜâÓÿ ê I T¦·¢¿ Z‘ø»tÚàó.h†d:t(~¨´-,«ÌÑk¢Ú„ ܽ…·¶KYU¯{ý”ܶ#cnùÛIÊaT«è^­…¿Ç Ãô–;k&]Y};ì¨ã†ÞÑ ÉĸµÂF›J´M4­ÍUsWK'éu0hÐ HŠoqâìÙ³›»©Î’R@ H) ¤€(¢Ãôôóq+^üÞ;¢«¬~}øc³>ý¹/Šdjºˆ1¹v×*¨TÁ•®½©jwÚZݰq)ðJÇöÞpÜ¢PšRCÕŒN˜|7öÁ*P %æšOÓ §°E0eôÔ‘b±hba†)™b9”Sl@1.éÆtÍÃB tÓ+†1U×GKÞ"cŠ–|K{J黾—²”~]|-» ®Ú Mµ¥_³¸ŽÙöÄPé¿ÿûšnt¢(º>ÆäQ˜Ñ–ÍÚ40wÑ œ:LŒ‚ºùj#ç>°òæò09~˜Vn¬‰%—•Xrýa˜z>*n cª 'gá‚©ºÊ<_@³ÜÆgéV0LÆ41À˜èM Ôà°©Æ4gÁª¼Mº½®*ÿ½«€0¦Þ-û’?yÏaL0×bI.¢ôÞµ7 ûî÷O4P)–Uª2Ô?Æö®  ¥XnÉw™Ž.£¬„àqqî—‚î‹ëö¶J/ùˆR¢Èycï Àä."É 0ùtS0Å3L+_{¦!†©6Ú7"¾× ÑC+‚wiÍr“ÚXr5 úO†1 Î(ànÊ!Æd SÅŽœEÂÌ7޼vÃ7D2hpç†á¥£åóèn³ŠÛ51ƒŽSBxG]<¨îÑÆ¾Unm¨VZQòWMG צT]19¾h˜ÆØìÙ^ûqS$q´ºÌ\C­Ìvzç1¦º9OÉmÝs[r@ÿ1¦Vý=†é¬ó3Ö·C'™@Ë‘%m-pm ‹‹1%Õ¨ØÖžøO×Dµ%UZ‘R@ H) º¨zÛÑéŠ}(Þ.Ëóâ°þx夯M¬ÁÀ'Ëíbégš¾oÒ‰ýq f˜©’/ypìÌO‰dj¶ü€1¥Ú]ßõì®Çž˜dnm™Wû—=?î¢Ð½T3 Bl¹X„¥7<¾átµ—e˜jV{fˆ&žHNe˜ˆ1¥P,McL¾Q½ÆÒîÂjs­Â4K¿})X sº%cתŽLjã1Õ˜<ûª¥'L¾¦¸Ò¯‰``á ,`S¥Ÿ‘`«ñÔ™aBéW1¦`YïfÃaÆÔlû§óʬ1¦HûVãïÌY¸ŠS‡îëÌ|î—B0+-X½MwÂäø tZª¸6*ÕSV†É‹kYq7PË0A(‰1ņ“³ÖFS™3z¶Î+ Œ©óšëŽQ ç0¦knZÞáþ‹o1œN•Rˆ%Ô5+B’¸%Ç·-GYî ¡ÇK‘V(x\"½Të÷8?Î]< !×O€©ÒïiÒ S¼¦ÃTñTb½oÉQ†És–kÉ[qBŸÉÆ€ŸàycJa˜rèÉa˜".gÌ ˆá¾û«†ÊN2ÅbLt?CgB0òʱYvîÄw:œ´I `n“¸‡3Ít7rȺ.KWF8‘¶Tœ‚mlÐvbþâc—2GM¸ vâÞÛ–%>.NïS!›²aL<€Y¥5™Çó©íjø–ÏʿۘÛ:ÒÂ÷ÐM SªaÚó ·òµŸÚ˜O&Ð$Q‡@VyÈ6Yí2"Tð/]ÂðwäVf;×~¬cîoÄ ž¤:º>oļEŒx"«½¬Ì¼>ûÅY5rsËãy°ý -Ãü*)“Ñë»p·í\Þ™wÅ^!ª•µ9íø=†¦ õíÐ#¿ßO&6§VëB%Ȇ(©úYéXcËÓšJ·iˆbLѪhõÊ*§U'ÖO«<î‹ ÚròÊ–«Pƒj°B-3Îe9#“Äêê>£½¡ø[s/n—ê¡&R*¤€R@ Ä)À¾ zèQtÀ_cöu2Àš¦vl¥PZ=ºJÁöXw:u§¹åOÌ9¦?ÿ…Óž~&5:Ý ‚GV¼p%L(÷™!’©¹rÆT×îõòB[kÝ¥¡nظæ\Ú›7 × D,3À°¤’‹8½ð î‚Oc˜,ˆOtþ8¼È3[41³‹SÅÒ<ÆäÕ£æwLðcš?«e,ýÐÂàk­ë ÑKñæt‡^ Ò£Qä]pù~ÝbK?Í WBé›û“ØÒoša‚Iü“ôÆ”\úòÆÔ\¨³J¬1¦¤YE¶cÆäûJ Ïâ¿ÈÞö^a1á/Øj°Ëܶ \’aŠz „Ÿx7¾ŠCX:dmF?L3L˜ 0¦pôRš4÷˜Jü“Ñ£uAaL]]·ì„½‡1E<âºÃ'øËÅpº:r® GP)Ì*W KÕ8q¡qu·T³<.—B^—¼þŠç\¤ÖñR4rœgˆñl1ȸ+ÎýR \¯c±ré Ùz9þ0,ÞS“»²$À”ì„©Â0yN˜è¸ÒK!†©0¹~,+SxÝIn½1Ã三¸bªDÎò¼ÎøÖ¨}ÝYI&7¨ç›É@`þÛÜ&‘ÅÁ.î4ò)Š1átºÁŒ²MuÛÚPlDÍ‘Ñ᲌Ì5TÔ´Êém›òç¶Ûˆòw?20[½dOÄieÆM I±4bÉNá’© e٠Љ¦½Çîá0Lµl_È0]qQÃ4cYþë)çd.g« 4va|Ë:Àê:€¹he@â¯Æ~V™y«xذƒí'ÆQJ³SpYþìWý1Ú̲äbLÌ<+QÈû‘ûÓãO›²¸ø#)™Œ^ eÁ¥°+›Ë+f2D®D¯ÕŠ'¶ã÷è0LuXR›a};¤’ ùg}@pÃJú¤T?ûÊZ*Ûc­™5Ñù­”ªh~Œ¬òu« /m9Ýæ·àÚO&„…žŽÕ™gÅ&0Êûâ_VWÈÂ:Ég$ÿÊߚ뇀î{ƒk_õ¸R@ H) J«@*B‡ÁúÀض'z5ècð[ëT`§õêÙùaïÂ=ØŽ$ÒÍýî-Ø“áuØñ#ƺNÇ–ÉSBÎ;¹ˆd7Û²Çþ¶e˜6cÈ”»‡½¬P_1”m{F\Öô±g±oyüå0ʺmì³ñ°ô§³‡j´:º Sàµ7à ôÞï{tÆþŸUt¹FõÞãaLÉvW˜[¯¾ñŽÀîZ1±¦Z+ÜR̤odQèÛAüz+BãâÇÕXSÍ­Eü*PobØRm±æZíVîÒ oäÈd “ñ™[ñá2LÍÇµŽši´fm§³°ÓØo©®ê¬uKß4ƔĨÑö>{ÁJLó‡&øã+@k E_µ±»^—ܰq5Ž—’}/¥„2Èî)`rçõ0½ðLµžµ–)#ÁV»Ê7c$AÇ0^]Ù /\Æ4ÌØ<'Lµ~˜T®áVO'ô†èN ùŠR˜.€ûñ½÷E+ |F0ã¼Ç…âÇÅ:KŠ"翪_q±o¨8¼2Þ”-_Fµo¢Æü0ñ½3r¢ç; )œœ‚ÊõÆïFOÙY„1uVoÝ­c ôÆ„³ÑHî:^…áô÷N¬:x$¢ä€JNÏ£f(`ÔNG¤ÆŸm5NœçÖ¸:´®q›äâ8hÅ¢KÇKñ¾—¢Áã|z©Žû¥ÊÜ]GâúÂu–’4à©>À•Îȃsw‰‰ë'9À$çºM~ÐóÆ´w4\>1¦†)b€óÏNä,Ã5°vçºÛ3‘LÄŒpaRMøàrœKƇÖX×ÄiÛv¬$®« Z0£“o7r/kóÓ¼µåÁææ95NëªÛ’òZ¿ôádŽ:B†lû—b:2áeí03´e&šfƒWèXãÞ;72†ÉY\°}žÃ9õ pÌJ˜EŸí«`Lø]œœ™dB¡ãç€r¤wŸP…gevë«DôWÙ ~‹_.h¿#Ô[ó@ÃB·º¬·ý"²ü]DÉõuÄ_ Ÿ4 c²Ÿ™À³mºÆIÊdôúð‹šàN~0QŒ)z…¨V”¢å¿ÇÃÄÅÜ|óf©o'“O&<>[|¢ÍŽ5)n+ǦÛÕœUÈê‹’ÍÌT…¦¦x|´*Z-ÅBœh’7¦PËIFÍ* (šg{:û Ì6™<»ïK, Ø”6çax@ûa¿¡]¦Œ6¤€R@ HžUö"\Ä;±‡}ZãõÑqãÒ²7E&ûéåa÷†›ªtl]SvÒÜ[°s…芰lWÃ5ynðÏ˺ùg§‹Ý¼þÅïÑftLæ9z…¨Víø=Æ1L!fn—±¤Ñ‰Ö·,$'X^6Éä–[Nk<­ú…ŠØ*¤GY0¦Øªh xˆx³ŠdÙcÆ¢-§ÛÀrªÅÊ3ë ®€ÆÙ¾bãɉ={(W\¢1o®Ç)\×±#‰Ò¶¼!Ò¥€R@ Hâ*À¾+ûä¬büu?l ;çè±Ø콸#ÊâvEB] Þ‚øµ‹YÜž:<ìDµy;vÙ¡²î"¯cR»ˆÛ½·n˜ O¬›m·Ðíq¤õc٥繮±C•ô§³‡Ê^Ó0ãø¹/ ˜êÇ’ ûar½ö&¯xA×ýžG¦Ë'SvÍq$0¦ v×\sk’­5€–+kÝE¡¾'ûºèRØ“}]÷KuðÔ "Ö„Å[ä™HÎõOo “M'Ã(êcL5Á}B¶Ðoþ½¨c­ôÊûŒoTÛmÏÌgW`š¿¹Ò_Í•À–6½U\‹ePÇ ¡ÒÐT5ž¯vB5y*™|P j3¯ç‚+`˜Rœ0U*ÀÌeÛf. (H$Øü@rðÆtí°GSÖô*¨\Cížîˆ1ŵoUôÌxvEüŒa0]˜ØˆÙË+Îe`µÕ²&+ì’Qä,ÊJM¹³’3?LQw€ž£'X _@ÖþÐ`¥åÙ‚i¸*ÆTñü€ÆÔ ¿=cçÆÔ9­u§Ž*ÐsÓ•×ßêL¸ÿâÛß;!z@uð*Õ.rT±¸GY¡¡uZJt¹T'`\(nÍ’‘°ã¥„Èq5¾—ªÁãšs¿TãÙqDrŒœ´²$ƒ¦: ot˜,¹cõêz£Å›_ ŒÉ&vj¹z,ðÿQ1À™Ë™Nî…—3\¸3ÇÕCëLfÐdSÄic.åäì/&2F0ÐjÉÅv6,ü–]–_|E~È¥Ìl½‘™_Í Ù#3‰bƒžð9w œÄ#ù-­¨\ñÉÕ¢<×rËœ˜ ÛlÇt¹¯Ü {æFg˜h] åŸWÃÔò—›Ã0½Éa^<Ôl˜ö~Ë·Ãûë‘L4ÁÛ#°òÐ(ÏpüQX…$†­ 8€UÈs¼c¥b=¤C&VïÐÁ¶|9¶Ž¹¿ˆèÜ@ôÇh{HþYÅÆ6áE[nn¹Å²J”…?pþ´qY†HÉdôú†6â DXìçÌ)ôFµbY´ð÷è1LgžÌ‚4Uߨ£¾}»žO&Ða±B·¼°RýP QjèII­¹sËԆȮE«bc2ïG¶ªÞšV|Åù°hËÉ Ãß‹Ur^ÙòÌŒÙÓ±¦á[¶ÞøkÏB•XßX]ÍOßY|䧦¸åM±.(¤€R   °o™go„ÝZöUðáëÕËFw†¥îÁDšì`»rhñ@ôÖ“±‘,»²îÕÜá[ä|6óéöp’0&ìg‹£ZYX76°‰yàNöôBʸåîbL¦6B^œM7à’åž}ºF1¦†Éõ¢Zwzïw?<ýŸ?sàÎ]o´žw8ÛÀ˜²Û]kl­5+B#nìãÜíÄ»\Š'WÒÐ¥¤àquØþ-ªæS¬c±T¬'»&µUÕ OV„%Ñ “k­µ‹nö0¦H 9w޹YŒ)ƨnföÏxS8|Ax=p“¥Ÿ3®^ƒe¾gåï%§ô=+º9ßrÝ/5„¯¹QäÒcº¦rr!#y8Œ`ЦŠm嬋H/áxŒÀŸ˜³âÒ«oç,9Ž#±Ã>ᓟ> ƒáO~ê¤_]t•C/¥ööW–lß{ß¿‹™»>*èÝzH†‹öœúƒ1}ô§Vì¸iÑ– ZQ7¯A†©ïÅí³‡Õ8ò’ÉG^쥓†Ìøê™ãåè³^8¹#.šôÐŒu4À™+&(IцܚF25ñD!ß!M\¡U§ÐÏG«®V÷:0ÓM4üVÝsu@Ó €a:ò˜\«4¹OZ¥ñ‹ð“~vÃ\c˜b~þ0 †iþ.~ðÓD’©é¬†Nt×4·êšÝºŽëð)vÝy·2Öòû‚a:õÌó£õ Ó?üpÛaÖ·GgoHªoæŠÉêÛ·O$™Zõík™1Å>¥ù@ª›gLåFó¬{¢R@ H) ¤@›0fšnl… az. utas»X\¥`kfb{Ť½IŠs¬Šë»·À÷:ü7„1ÙEx.Ž1軎cé6‰Ô¸ÑB¼ ÝçâºXn{Ü‘ 9šm+Ó„´ýbòamNça\AA¸§îÓÙCÕ­ Ã4ï9ócmË]ŒaŠtݹ&”ï\4iÔÌuI+^0Z6j*ü—È'ô÷›žX{ÐÖwgÇ–EŠÝ•ÆÕ+’í®ßøöá°©"}ì¸"ôècOªì9Ɉ¥{GM„55´"†V˜"¯¼a˜Tô“_ìû‰¿wç€ã½.Å9°w]ïÀ"jü –HzÖEØóÏŸ>À'‰cÝ/Å;à©õXï#,Û}Õ§L~1HýÁ)@X~|ÚùH°l¤#,tÂÔ&Œ FõX{;KA1ÍŸbfwêÀI´®‡êÀ7|+º¥ sm®­÷Œíx¨!Nøamp½.¥ KQßK^pVÿô/‡¢ô±ÓjÂ觤ÇËŠ¯¹Ð@(~S\ AÐK¾v*ÀÇ÷ý»Ä(rà †ÉÃ×Xú˜ê¾Jt@*0ú¬=/ݳû­èãcжonƒ†Ê6-K…¼¬qjà8^¢qû¨ïô‹³/ñ_[p9ÿ¹WðF[Zyaíÿ™/øé€Ë®½ƒ/,{O]ûpLöÙêÄ=-Ú:=pÛÞtžE‘«LáUÞGæ ®^ 9(k˜.Þò ‡1í¼RÞ˜zôW¦ÇnŸ˜ڧ­®Ü)h$ Ý-Æ£}Gw*«íº†Ó0¯DL77¡Ó½@oW\{»?5^¤ÎQSlÂP '8U"_rFNâXzà±'a…ÑÔ‚•›q=7ÐÇÒ/ιCnZß|×Cø74´®‰«…–²pKîxÛ§þêb,ላ -Ù±è’3ö~ý«ÿrh°~Èw€|ߣÓ~~æE^G‡ie°R-ä ÷wLÛ{ß¿O¤—¢‹ŠœÎ1¦$÷K5“³Ä$fˆîCß•q–›øCµÅÞP-”šÃ˜6lÛ €iÄó»«o¯9/ŸÜ®úºg¦¯ë°%`˜*ëÉÌ•(j&Î኉l0Lß¹xRÀ0½ðÚO®Ÿó•3Çœ¾=Øù`úÜwÅD\\ü[ZI2µo²¼!yaýDN¢®˜ºHCÓ&K{t'ïÛP&Kv0¦(ØG«ô)7Í;çŽgÌ?Ù‰WL¿qÌ ²}ÎïÂ[SRý]¼½0”'µ™dBU Em(héÐyežn¨ ú,éÙ&Ã[ßà‡é ³ÆÛ2͛Ƭ¨¶Ã¡úV1AzTn¥¾á=…®I>™Z"fûZfó½d~Y2ÌÙ,¶™YŽ×1R@ H) ¤€h·Сcãb@¸#:·`µ1ŸWÝп ÖfùŒuÁ‹Ø·¡[ð¦6R°ÃÜ«Ñi“»‡§X>Ý<à07jž{ßhNBKqö„nÄ‹G³mûíîÈS¹{¨§K;1ç?ŽŒÕÖ­!d˜¦Ì{Ηª Å-ráߣs6âH#­ÿôIDATc2/ª?½a†š±ŽÞ¬C®˜Ì„rÇH‘LžØÀ˜` CŠ…™hw­ÁõÌ­–*v×°¡õªïÂBV 6Ò'f,A2\ K@A/Á²jëBCìah…õ ÉŒ«8“¾ñäJ=tɆu1=lþ-Žøî‰§œ‰% ~ŒžJð¸¦ð¸˜l‘§ëýÂ]äé®ðüÒס Ó¿žv>ÌL¡(r†°Ð.Ú>Œ)2…_-ý©óžÿ›½÷M2³_iu`C¸ è­0‚5·»$8Zög¨ãsËóº”6ŽVô¨ 5!;½„æ¥Æÿ–=°!ÿ[¾fNP*SPô‘Ò÷ ãŽI\S»»º~Qxàä=àÎúË(ÌDŒÉ}9ÛÁ íÛTŸ¢vÆGbñã $ù ¼àÒkÑv~öÅœ¼qØH@KûþíßÓýÒyÿvõI?>啕Ë^Édó}h¦à~ 핹ˆC…fêö¯ñJà9#H˜ž2ên+31»d“tUÿµïø~#Æ”îöOÞ˜ŠúKQ¾ó©€0¦|–‹r•Y.kc¢ èr`L—_;4XÁc·/ÄøöÈïžàzNŠns,ýè§¿À¨Ø<Öb,}ïCÞ’ ÐXl]h #jÀÔ.·tóÆ„¡õ×C§äkß< 9ÊB…xõ~ú¯.†Áź,§ýêb$ ´ðý*ỷèÁL~z¶ò.rÀo¯¹ã¼Õ!Ÿ9`Ìä6êv;4¶lÐ†ßø‹oáu _ýÆ¡èè`ܶ±ñoWÝKpÓKz Ûî0 Û÷ø×!ÝýðÔúÔç¿üõCð÷–ß=n‘ãlÏM÷ŒuûCÀ˜œØº^¯+Šþ×þŸÇâ Éð=åâ_&ô“ð÷KŒ¿ßçïn>ièðI¶ç¶á“ÌYnJ¸÷F1¦µ›_Ÿµöê–ÿ­6mŘ<†é›‡-Y½Ý¢™löb1™»ŽÐïœøp ŽŸ¯ôù³n›Ä…“|ŒÉwÅTër†Z b/¿yDJt¹ÌÍ‹”SÀc˜¾{‚­· [¥_ÚuЙÀJ*1_|õßc˜üßÅ™þïbÄôuU†ÉqÅäý.<'Û›Oüɯ’¢Ëuî9u§|(à1LgœŸTß’†êæ?ž¹¾¡úÖn’)B*R@ H) ¤€R`Oû {ˆë1L ˜2÷¹Jï=ð×8aª0L0¡cÂòzQ½ö“oÖ˜¨ó§èÊí#¦`ú¿Ç}2Æ 3cб»:Î'’ì® kAa#¹àEXY½Õ¡•å €T0üÇßßù¦×P8Zéz‡Ž+Ÿ¶®,è»b丙fk½kÄâÁ¿\‹rçðñ0Ÿ¢Jà¯ÙQaa›4o쨞ÓÏxNw\×õ¼âÙß°Ú †S˜L‘`#ý·«oDzϟŸqÑñ'Ÿ¶÷ßþý¯¯ _õ_ùÆ¡HtZ XM¯ºåØ%ŽûÑ©4bψ ÏÀ^zØÀhAE"ÀtìOý'ß zÈQÇ£B90“šiô#‡Éôà#Ätþe·b›k;O?÷Š“O=/„°´c –œ…Lî• €Ÿ'¦ù“,íá:ðlPhöAѳ0¡Lvµ»$øt«¾E½^8€k€­  u! P40¨¾ã¥Hظׯ0v Vt”>ë}/a#¦Üo}𞇧¡”?é1ÊšìÚ÷ýš€tèQÇ£Üï50’ãï…W܆ @Ãø…—ßêÆï1™¾‚E Uâ‘Éˈ¯aÛ"" „1é},â ÆÄT 3¡á5_nãæ¼ÚØ¬á€j'¤&È©ç× …[r¢íÂä æ9ˆ·fÇM]ˆ9A¶Zh¦Ìa¶ÍUš©Á—\Ìõ8sñF2L'œ|ƒ¨ š (¸!À_LHôÈWÚ(Î%…£È¹eÅÅ@È MëHY&Ý„1é—(Z©€0¦Vª©kuZ,X‰äú“¶Ô÷Æ„¥óQ7Ú~‚ÝÃéË®Z+ÝíRlxßzäžÛ¤ÀsÌ¡®ÆŒgWsÍFMn˜mKî ŠÃfðIŽw¥7ÐÁΊûGoiÈMÃFN}æl<ýÜ+c_~Ý0ôW¦Î¡2´Þuä1'Z². 1&¸ŽÄHÛó¹f'º)çþúêSϺC/,ˆ ÿ]‚ÇcÄêvƒµ‡ ŸsÉU{cô… tk®¹m8¶É-ÑëŽGÿæÞÑÓ~vÆ…ØÀP –~}åPôxÇKÞ’5oÕÚ=OÅðÛè¢ëƒq8é%ìG{0ã¨Ìã–÷KwÓÁ9ºÓ;.’ùFÆ1wŒ˜„†å¿8ï ŒÓž¼ ¦ë†½4jÒRìI÷ZÉ!\–Fw#Ç<L˪S[1&2L‹_ØŠ0¸ãò{±Œatâ30aîüþ)kQŽ“¾zÂåÓQL®1í%7œœ¹ p _‘L-j]t™N(0L•±_5Ú¦öat‡èø-í«ÆX|áµIÑß…?£kóè†Öƒ-ƒH¦Ngîï†é0Lõê]7³¾1EPßV8íp¤¾‘%e}É”ûº  J) ¤€R@ ´@èÚÊ\Ô¿æ?{À€Ésž‹šPhE1ªè½ž½ývôÞ'/òì'0|c –%x³æ´ºî"™BSfªow½†v×[+ÊÁ`E<8ÃV8ê¥Äð:H£÷L¯ž›%ßÖ­…­6XTQÜXð ÷\ Ëêˆq3±1bÜ ˜79üØ”…ØøÎ1'>ÖT˜Rý1çw«@=ûê%W£†À§…!,œ¼‚=¤—°=ôþÇaõ¼×ûNë.=üä3°šÒ^Š[(&Œáè SŘ$†áôÊ[€itʳëA±À^Šô“_\€D3)§A®ÜùÐ ,°‹Òõè¥_ž?qÄ,‚¬ Y` Å OúÀ0|ÚùiÂ"ÊûûnÔSKca´ÉSuÕY­½¦xüB1Ío¥××§ÜÝ:b ÉJ?¦¬Ö(qÌý»u€¶ôaŽÇ2àƒþå0®þeéã/€«†˜Û-”¸‡1ùñ &Î^ËÎX´ÆX€k °ÁrGðÊýäÓ`3»z Ë}=³ùsÞ¢S°g^xåÅC†æÓKHà–θ`Š5á©ùë`$G¹?:u9*Š%Îr(w²ð{Pô(qü=æ¤S¼ °xËy¿½õÛß9>).‚ʵ꽣ë”Pcª…™ˆ1ÅÏ*V¦qÀ¤9ËC¸’­¿M rꆹĜ p[ó_`AW,©‡1Áö ­ù^Zø‚Y…Ñ4=ò䳈¬‚„ x% ½„„ µŒ¦BÞäÝÃSѯ¤åÛÑyÁ ™òÀD/•„¼CÎÿ̧@ÆI7aL%ü鑺¨€0¦.Н[÷[0L yß°7&8‚fàx{.‡7¦Ë®Û™àN|ûï²zDýa°û=ŒÉß`zèñYðXË¥?–¦ù|Hjo–ÝOô±„õ@TcŒí§gbÛBÛb{Äc3Ð/±Õ!è¾`;è² TÜY3ÑÙWa©Ð˜I H)a…ГsWbÄ… th*#.oÔMKìÊ ‘ËÆ)ØfÀ8`ZùÇ]ÞÐËǘп!½4~æóƒaÜrï8s¼Dt‰¸é™Çf<‡ž7&÷c˜ð×Ð%ËýÎç{ÉØ*‘ÝI/ž²—aƒsŽÍ¸ÊÄ<$cî—ð†è^úçÏa@þ»1sÓWfìQ}úóÜ?õgD&kî^¸e2ÿLýß8kèÿþµoºè…mnݳ­YßÀ0=:{çÎoxtè ®¿|úC3Ö¡t€1 Ÿö’Nn›ùBw§ÏE2õ»Õ:¤&´Ï5? ƨ,«èùij¯à‡b˜Ð¦9¿‹§†OuÕ0‹f˜6’鈟üûÿsÖ ªÀá?Ûë”3ÎK¯oXÆÔ7%7^¯Ä˜²Ö7Ç©»G2ü7ÕU_¶üKR ]ÁÛóêòµÂºR@ H) r©€Ï0} s‡!Š;Z¤mCÅѳ<Œ ó|è·£÷^Y–൷âŠÉìK$™nœù¿t¤Ó¾l#ÌÜœÅî5´†V„"¤°UñGýž_ ?¼ÒC¾w%3±Ò ¯°šÂÙ&€a4óÿzTz¬·i`:±ÀšO¬ÿ´`a´©Â(Š„S¯pb˜vT?pX5fÑ%Ø0= ó)]\0Á"Šb˜OiA½š*†½”^êi5½D¿;Ę`&¥—úA§_0ì¡)ƒN?æP:^Â&’+œ?·Ïô0c‚¡ïäSÏGÂ,ò·¿sÜy¿½åÞ1s¿xÐÁIvÑ6aL®Q=j~ÇÓüé¥ÏoA¤¡ø¸RPîVPâ0³c1pPÖz‰³þ•:°u€Vt«\L€u­Æa°­ø¥uå~ÿ£ÏûÀëRmÐ@Ôs¼„u¿°œ{À÷k‚'¾æ©Æôy¬øõ æ~¼úÜ"¾†mp¨]qñ5Éi*G)[ä&àk VÀ¢÷9¶-°£ô cBxxÒ2ü z å~í°GSLâòÆ”ËWY2µkÓž ?!ÃTŒgýå[ÃÏü‡Oì4«È†ëo>¾ïSµ]ǯAÍtaõæ7_ŒGÇKçýúj´]lÐb#œ¢E2‡nK…WÕßõ˜Zâ•À•¼W’ß4aÎHÖb‚Í%4MÞ\ÞsÛú‹ Ðá„V‹Þ˜ðJÂë¦ÆÔ[laLCSÂÒg'LÖòdñ Œ)?{e¡D c*QaöÚ£]BD9uÉCÏ2ÖÖ3bÅÇ`©imºeüg¿0àÍ]º±&‚{¥GXßÖìÆëçÎQ¾ÞôùŒuÇ_>ÝK—MÿÊã¿ð©Ñ³6@yPbÃäcòær†ýë>öÄmo¼ÿ§?ÿ¹Ð?pe¾Ü ÀEð¾…«¶ñwa+ûh•V2uñfþ.àßûòáK# ò»˜f¿ ˜‡ª¿‹J˜E·ÑVò“KŒ^~xkݺZQ8ëªúÉõ )êC °¾áßI ^©o>­›Ä’Nxzý_ýö½?ùæ×¾ç†ƒ”¤@V.ßß³¯=s¹=R@ H) Òxë­·:è ‡'Ω1¡8Ë]l"ËÀö.c×ãÄ#`?™½‘QTèµ×ï½{&oÅ‹³>­¿ðµÿuý“?›ðâ7Š2ºia>ǯùB5çå“~Æ1Q»kÅÊêùOªØ]öVXVï1Áu«sþ¥×À©’-=ÿß®¡‰«@Íu=­H6ã ;ê wŒ¡b A½å /z¶$àJp¶D¿¹æNQ¸M³*È•YK6ùÕw˜01ìÂ+´ záÃ>ufˆa5ešºpÃOyáOyÃôëŸó=^TÜÕc{ìôå0‚_1~þ _\n‰ ×y`‚÷Ÿ~>øl€^BºÜÓæ€‡î—à™6RcZLŒÉ !„ ËwOüù¹¿¹¥ÓÓÑ5kÏ‚HItµî'1}|ß$c»Õ.FªÖŸTCà2àhpgý­Zbéó/¼myEÏ:P)wÖ,ÆJŸiôSÏr­/Ëݼ.1d05ÒYˆ°ôïAzxŠžø*ËÝð5bL´“£ôÁ0!n <0_»ñî± :Ž—BËzY>ñ€Ê Žœ£|’3”ò†Ðèyx ’ï± ’õHð•-˜ £k/0Ü‹ÁŠl`QÙbpÅ·¾‹ã‹0ÊÂ¥è+]Œ²ÐkÁh clô]Žøî‰ç\r5 % ½µÌ\²£ƒ1ö9{Ñâèi ûáLò¾ÑÓÀ-11h76È-`⬲rh0m ´èréâ+‡¢¯X›èR5UBŹè| c$vÅMp4Ž!Ö…WÜ “Ðå7Þo£2ÒKô‹ËtûˆI¶¬„K‹à×ñìϱÀƒ´ó~s V^ÂhCtlc×BŒ AåÖmy÷Ùõ£¢0Ì4ýýÆ¿|ùr˜áæômpz·AÖÁîvã˜0Àaùà×búåè-öz~Ê ¼ÎÔමJ$#c˜ðtH"™ÚQ”ºf É„¦oÁŠ­)¿‹!#–᧺Fï¾Ékñ»¸wÒÿwáµ]ø]<8u-Ù>†“‹5LƒaºæÆaü]¼ñÎï[øºT€0¯KP³4ªÒûFpD£@{dÖú‡g®C;ü“ë瀙«´ÃÕúVÃÌEXÒ€a9Nõ­@u#/Y];[S^ÊBùR@ H*3½·ïÃÕ„Yn]w8a„–d ψ Xp#®Q´~Þ¾ßß{ï=÷"¸£ë ÞFI|°NãŠÃ%”öUC#É4j§÷6¡ØòôÞ1f„q,èº{Þ¬“½ö:Á éÍú›¾jÃëè½?³jç?ê¹Å`±Aå`Ã~–6fw­ØWÁ0M™·ü$l\vݰ)ó_pö0eþ*˜XÌu°D[ë©¿º c4˜XñíØÉ ]gK ”Pú×ß>TNÃÊ Ó(Ö‚rñ' ª°£ÎZ²ÀÁì¨G}‚gRxt3x%˜&¼â›O™0O|ØÑ'À7uÁz,ø|hâ3`˜¸à8 ­¦tQsÕc¶Ø|/\Ë2ì!S!B€ ôÒ wÅž‰ó^‚íâà#ÿÅyWÐRÊå°‹dáÚÎÇç¬Ãô£SÏ£- K:ËÒ&oLiFõ—v=1{¦ùCnHÌÆž\^ž·üe+M놬™™n–²ÀêÀ˜É ÍÙI5”ûu‘:0ú)¯Üî[×aHÇÚ$=¬è¬(ú T˜c×Xð½›xôÒ¯.¼ˆ@€¯Uʽ‚¯yåÎЀØ`(@¹ÃZŽ„2}rþK(zì¹àò[ƒøqþ*_˜Êý °å{¾C&w}/1&TcòÊVq”»Uƒ$ø0¦†Þ/=t01&Øzö *÷TþÊ1/¨œÛ|ÕN)²YÃOÌZfmšùXªlxЭ5\¡Ìp[rKt^À~ ½ !Ä ¼.¡±Bë‚,A/Ñ÷b›¢uºõÞqhšðzºê–ñn M(Ä3§€x%Ñà÷ŒÅ+ÉbYžqþLn¹Å>äM'Lê-Œ©g=zðî+ Œ©ûe ôWf¼1Ù=a˜(º+&§/½ê¶H¢ê¹ßbÄåö-¸¬§&Õ"ÒŒ§Î„m Kö/‚¬c”Déú;FX_„”̶]LÌ{ðqKô[‹o§Jc‚=„–ãöÒ«ïÀˆt‹s.¹ Ãlô]ð/vÒi$Z ¯‘®¹m8F\ÓŽ ¸%ŸÅœ-îŽ}o·„–ÐÅõ„×Å·\ Ão ¹ÑÅ9ñÀ¦,𢶛ç[ŒÃáý˜1ËÜ„UD¾î¹d3m9Æ`Lt¼„Þ¶çqOÊ/}í`úÈEbdwŒÒ±„ÀÞ{½·€U²ðÞ˜á_þe' °áo–ˆrÙ½1cbÌ4ÊñÌÔ&Œ Õ•$Óì%ëkúµdðýþëOo˜ ÓÒMÂôùcó6Ärtí¸brú S­Ž~˜ìÑD2õ·•ÕùíW€$Ó³+¶˜[2¶®ö»Àˆî†GŸÇ²Zð%øi¸ ~?¾vvÌïÂtÙ@Ëe˜D–´¿Hs}Ÿd:Î ¤H­¾Ÿÿ2a¶Ã×~Îe˜âê[e1w¥¾…&Õ·\׆fNS EY’R@ Hâ(ÐÕzf†ƒI-]˜¨Á®Uˆ¨ <)îÎ<Ø¿¶ÑÏ#§å^$Ä!¹“¹mÛ6ðLÈ’•É*\P¿j4cÉ4~v’ Å\¨Ž›· &c˜@ ºn\1ËÀ–9‘Ç“&vÝ{d aL0±¼2Û]öVâ)0¢"1’ü*qÏe×ÞAT ˆmªî¤/ ­H0 Œ™´Ͱ¿OÎ]‰ $ØNɬ[á4°—à—ëäÓ<[kÅŽê¦?ù4ü K)’‘+°¹Á¡ö^¡g Ô¤ã~t*XM¯¼ù Kg^x%é%ì¤Õ~w`2¼Gõ؆½î£Ž§ôÂËoÅ6l¤øK§¿håúœ©Ã´¼Èœ÷W``ôý-áÍeÜ›"a*ï,4Yh¾øÂ¢Ï4Vh²à¤Àæûøª"YËè–ø{É•C¹¬÷,Ÿ°D´„v‰ÍcYÂÞJx%ÁZ!Ï¢Lž1“ɃhëLlTN­Šè´˜:­¸î×z ŽÑåÜOVoL­ÏN7®Èát”z¶=øöðÇÅ÷0*æØ‡;~®Ìq.éø1H~wÄí”R]ݨvPª=¬ B ØN4nsklž–ÜEB6Ò6jG\ÕQ·3ðfϦš*¡âB.—nºg¬ÃÙã1n‰¾dÏÙ‰Œ3‚ÛbÆUƒéVPîj(Ü+ Âëºp7Æä×ø¡¾ÇÍY“Ñ÷Rt—¥G…E*.ÆCÕ¦íïmzëñ±«÷‡'íöaLø‰dš¹x}µS[‰^ÄFt²eýTúaò Ë¡'ࢠ“|2u£YÒ=V$oóŸÛ÷»¨:{·õ‘lÖŒ¹Lgû¢ “È’†K¨\'€dBÇ J/U@RÚO‡¤„iËN¯o3Ë0©¾•«ú´ùi„1µY`]^ H) Ê­z/7ïAðÄ=!Oæ‚®Îq ¿‚} <˜ž“¢{Hð¸ËÍ_:µ={6¯`÷ãÊ@yH2át3xðàP‰àâI_!3üЏó€!Ùö‡®yYÞÎnA 'ò©í²¼ KeÁ˜p)†LƺBÊXI2||vh­ ¦PïËÀ¼Þ»T¦J$èŠU3C¹~˜ÜÅ`½F2ƘXF Ù]Lªkh5T%£qµ2ï[5«z¥_–,þŽë·žäJÈŽj¾vlÃE—Òl§µ >CVS†‹ÚKÝužµ'˜6ŽN'8À°Ež4™v8¨\Ô¨îÚØ'Î\ö×ß§º&-›¥Ý/ýZ{=Ózmð ¥&Jßu¸תöó8Ëyhů[†=4…>·èv+âï¤â5Ü1•ÓùV :Pú(ti’7¦Œï( Œ‰S-ÀDq€1Yó•4·ˆ&Ì\–ôF«iÇ’1‡[BÃÅ~‹Ø4vâÏ}UÙKÊ}CÙ¼žÛ4Ù\ž½’⚣X€i³»8©É2éöW½÷œ«Ü>&Ýô{”R I„15)œNË»=‡1ýÛ•·E‘#Ûƒo1⊠¹(R–TN2'1”’gL±Ë*²ö–ƒ8áÜ€Üa\©_Ç·ëAKá8qSão °6üßÓ®íñTÇá¡ÁX¿Ð%ÇKŠÛ1‚¿%:^Âß”pïé P²ô¨b1¦  ûÖã+vÜû+ßöÞ¶÷þЂŽI¦‹ÖtãPÜ&Y‚áteî<†a꣦-f€Kb˜D2å½ÍVþ|<’é‡<½|³ó»–Q²mtWÖšU:&ÆbíâÚ$†)…,Y»«áUÂ*ÃÂ)@’ÉES µ Se1nu$½¾¥0L¡ú¶ìÞ!S|驚ÀÔpîeƒ '¦2ÜJ„1µRM]K H) zN€2@pðî'*ÂC¤œD]Àôu¢!là_Ì=ø»‡ÎŠp$¯ÉÅ…Àž¸ÇÍ€ˆóÖæ6 ‘K2 ÃíAì-QoLÌŸž‚ò‰è—Û8‘¹ÂGhÈeÄ”1ê‹26]I27Ë5¡¤/?ˆ2LÕÈã{TÄ®û#‹g÷É´ûÃí±‹ SŠÝæÖ_vWgÁgÈâê¬ÿtãéDWFX¥À¸Z ¨O,E¡%3¯ÅN ÓéNÿÐ¥`µ§ ¯ÔÚK·ÄÐK¾ß‹jìžTz &PxâÁRÏtWL8¬MÞ˜l Pìrßñ3<Œ©f¹o³¥oR§¦õ:Ä’o2Š-ý¬Ü’Ï>†çQpÍYñ¬õõÙµa#'ÃßI,½ÔOv …Ž¢Ï@Aåš~Å”üDaL“¯b¹è‡S쬢ñI8`üŒ¥YÝÔL:ÍW”[ Ý5 mÒ{*xIÕ¶QÉôRí[ÉdI?pÖFÄK˜§kÎw€0¦’7)z¼+ Œ©Ã‚ëvR ç0¦_¹5ÆR…1·‡ <.倸¯âɤšE?@më?"•âý*UWñã«d\)˜O­%–b=-Õ…–ØÑIô·TY?T[ÚêÆê{]ÊÜ%J§”ê~ÛOŒ)åwºß­žI®%’LÓ® Ö‘fsÐÿGeaغ¿‚Ç3yT–a¥3LœAýíZ’y]D ´II“&}å‡Ì]¶ÙÖ¦„µ+k˜’êï"aâïâÝݺ3ð‘³7ÍnÓê²¹Rà¾ûî;ì¨ãl wœ&Ï^u%·o²ä›&€PLϺ ëÛ¿ðGˆ0aЀÝ;·EÕØÚ7xS®TRf:­€0¦N+®ûI) ¤@©@c&úC¢g&n×± œ‚¯ c2‡ç€rp|ÝãbL8‘çE\‚‡§×Œ5|DÉe•ð/om@T¸nj(¿â-¸§À1I¡%-rsEhÉ2ŒLº¡è¨^`1{!Œ‰·èg=Éô¥_þجŠ¿ Ì÷U¸ìu–~˜b˜†LûÝ/»]÷W_ßÝÏl—ãt`L-±»Æ!JK­°}Õ™ñ±¬&KQfʼnD y܉ZPSœîTÕÇy©÷‰–BöÒx×;­6“¶ cJ7ª?>})¦ùëZÝ[^ú kIKt¹”¦À-}¨zÞª²kž×/%;ÖªkúŽ Œ©ímëŸBS²¦Ä˜Ò›/€V®æ˜¸ +Õ·Xíû«ê¿ @-¹¥PTÓXt‰ÝKQßKî\^ô}û&j¨µÉ2é&Œ©õ¿b]±—ÆÔË¥_êgï9Œé’!·&‡^Ç·•yÊšá±ë-)ÞsRœkb×ëc§bשReD*Å®ªqhŒ²"Ãl['ä·bˆ¥ˆ§¥zÐRBœ8ÌÔ:#ðŒÑâjÖµzH–±_•¥G•â)©q2o0¦¡‹‡Â!Ó„5FÃT1yda˜¶ì|ÿOþs©›>=\?ñ)L³—¾ö1À"£Ä3%1LÛÞ¨ù]àÇ‹Ÿùài^¨þÀñ[Žý™£ÀWö«/ƒô=ù wÝs/zY! ’ÖÖ7†U­e˜‚ú–‘aÚñæî~oÁ̓¸ßªÑÞ+™à™‰Ûø`)º{p ¾zyn7KOc¹ZS¹ÊSO#¤€VJ¤…\ŒÉe’1ºÂ_¸)2Œ g1ÏÀ˜ÀáÛèž$ŒÉÝ+r èC¾Êö»î…IP¹tskWã²`L<+„1™ÿ$>]ŒÉ¸Ë-á©› 'ªA2zä÷«¡<+˸³×·ì sˆ°q ™Þ~e-þb{çê> JtÂ/Møl÷ã/cÌa?ŽÁlÀcSsOª³Š¡€0¦b”“r)¤€9U€Žˆ˜9 B j\fð þµ¬¾ã•3À×Y»v-N‰îqÁ »¼(×aŒ6Þ"„þ`Àa¸¬eù1'F8W¶s!oLîƒð¦I“›PJtÝd¹¢,&2‹1írËØÍ'ö‘îr3I‹®úï~)¶†‘dºÌ Ç„Rõc»Ü¥!† ˜žß´ã«w;|ñ“¿ÿð#Œ á¬—ËØ¸Öì„];9r„ýÇäô÷ТlcjÎîšhn­µ¯¦-M Ub•hx¸Ø•ŸQ#jÈW}·6œ&˜LŒ×*‹hû0¦£úcSû0Í= í¥Ÿ!X-çnj´ô›×¢èRGVù cjQƒWºËcJ.RbL)í¾Âhåb´šYÂ0®”Ï4Ö9\LDËZ¯KÑp–Kk饸ÈqÁ,^#L뾌²Lº c*]#¢êª˜º*¿nÞ>zc 1Fî¿lzäqÙñ£4>)yüœ¼&•J)TŠw­-U‘a»v™ýI†FÝáq—ïO"‹³¥,ÜRk½àÖí0Õ= Kª Œ F+.¿sÁØ­€;`'éضð-Û°jeáH2MzfmP1*ìGcQÖúÿðѱÍÔA~˜Ú×’êÊ]T€$ӌůÔü.|ß¹¦eS'¶W¿ü0ñaÒß²£C?sü䱇ÇcnémÖ]¬»5H¦CŽü>_ÖEÎ@Rÿ•šXße˜¼·ƒÏ*aƒÁ3[ÂNlÃKþ‚X¿ØoßfÂÞ˜è®IŸÒ* Œ©´E«“R@ HN(@oL`hÜgÜZȆzcâ~¢<ÜÃq¢Ø=Ęx5";ü‘¢#%° ycbNHGñþkÒb–’Nç·Ä˜˜swdÌ?‘ÝšÏèzKâÒÎE¾°c'Î¥¿(^*ÄZa?¯æJÝ*oL¼#I¦{¬sü§1ÇS—]~óˆo|øª ¯3âslúŸ7ÃÄ•-t¼sFˆÁ#W°f ô¬ ;QÅ»qbLYì®u|ÖPÏÄê¸VJ5«¶ÌW}ýPqþ‚Ït)ˆÑSC®TÖy¶4dX][(hÆäÕ£Õ`,0¦¿Ù'=ALŨWú©‰T6ª§”¾ïÆ;&D`Œ³%oÈÓkŒñ<¦ _àš[+„1u£u,Â=…1%—’‡1ùÍW4ùŽ”<8 Œ™º$éí–äÅ ‹kÀtÈÒÆ…ÂYz3z•äIJŒ¼˜ZJ/YS“eÒMSÚå±8 c*NY)§ )ÐsÓE—ßþœ= |‹éÉtßHu¿ :UïÄ„“ÂéDÉq§”Îq½ëZ)˜¹OÕª#®ÌÄRxì b©ZŠ„û.—² ž»xL–UWÚy&¿ ºäÙì|>ô% Ëõ˜2œ"ÉôÔÓk][A'µ0Ųb˜jup±ðI¦ƒ§/zÙ<“E­ÒÁÊÚ%¾•°b"lΓûC޵SÛÏœçìgnäb±äUnC d `âJ°ùH;¼%í=ØÄû’U¬œ0KâßÝ;·f‡`]4á/·™, ±œ c*g¹ê©¤€R  ¸Û‚‚Ê-åà (‡OØŽ\µ$<\?µ H¦Ñ3jL(Œ9î/?°0ОËY–…ašºzÉ—ïýrH÷ÛÌ*=0aƒ ذí K¿²í®I¦×&ì®U+kFãj…VIZÿ™è¨>bJ­»ìÓ™Îä¥~Š_Ç‚Ôqtɵ¾¶ cú~J陲äc³O]»zL€‚„M¬þM³¥ûk}-5Zú!j-ºÖ×/ý®k˜úù6é‰Ó…1%30¦ºÍ@+—ôYÔ2Ý3\ŠSÀ4t)â ®åÓsY&Ý„1õDâ‡ì˜˜:&µnÔYzcºðò["`ÃŒv\x™‡1U¨£Düˆ ¹BÉóÊ”œ!t>©B)͉¬ÉâWÉq­DKÁ‘Fp¥xb)#´”7gKu{`YzTM`LF,Ù XfÕ¢‘Ë–èa›ëö²|H2=1o Aõ-–ÕÔEXSh@2 øÚÁSmªL®U:`±éXr¦’K+ºvj÷gî:]cpÉB‹¬Ì› ™þÎ÷k<á¥Ö·æ&c•À-!¨ï8 ¡âàu N˜Ì÷ý6á_PM<ÛîÎúfQáRaL…,6eZ H) J¢@ÓSIž¿8A’éžG¦;þz«~¬JÕ•u†iËÎ÷/Ÿ}ýj㯭L3+ì<ðÌä:èÅx0‹îâH“S`LÝ5@ŽªWÚZ»kŒeÕ5´Æ›Xkí«Ñ@`¶§Ù•ŸivÔ´ÅVª¶Óh¨¸Ž «kµÚ„1yFõ˜e½A5xt²‡1Å.ôÍdcÏn]O6ª‡ÂÖ†)Hö´èQkrKù±™ËS¡›Ù6f^S²¸Ä˜¼ö-þíæ½ÑpÀ£“×iÍÒAÛÊRÉð<`2aéº\ª¦ç0äx©²Lº cjãÏY—îA„1õ`¡÷Æ#÷ÆtÁe7§ðFøöïx.²¤”ÑrüWË·§ÃIÖAñÆTqî”"ƒ«P)žUJ —ˆ+ÅKþ¢4gÕuuåPöÁyÊ‘YzTÍaL°a]²•v\‹ÌXä™`ÀâÓ¨’Lç®!©ÆåƒtÂZA¨Xr½Ñ’ë)=H2M^¸É]VkViwemÿ&Ü?düœ±avêèÏœßâ0üÆ dTi•C’L$†mwl}kŽa‚Jd•°ðp¨A€™ð/ü3WÕDOKøÛø {Â)ØC§MF8•Cp=EŒ˜T-¤€R@ tO¸/ y0Šîé^îtçH2Ýýðt¯÷ž`B1WF† ±ähÏÁš4óÀÄ -?øŠëXhó¡-Ȣ˕µ„€1ÅØ]+kºÝ5«¡5uågŠ—zgñgWʼò3#,ên§b;Í…¿¥t«iû0¦«{¥Œž´ÓüI&÷–~½u¿1Ð’_úþ9K¡(*}aLemûû\˜’$ÆnßjçqZ¹$G€Õ&.ŽU ÖI6ê°6–e|ÕAtÉ}ïd™tÆÔß߬Η®˜TJª@/bL)ã" §1+éö*æøìQFü(i­Ou 'Å#JŽ;¥øÀÛã6;àZª«CjÇZIQá\Éqt\ b)vŸ¥GÕÆËS®%ìa¤9þÅËò°Ýœ‹$Óø9/Íx³ª+Å0•´ÝÖc%*’éK”n]„1¦¨”Q) ¤€R û d6jªkBq—»4Ê0uÿ‘ò—`LQ»«ke Û]@9)ÆUÇ‹Ršq5–Sñv&ÚTc\ì$¹¨úÚ)´‹úöaL!«»[ú£žZ„iþº Z´&D¬ëÕi~ZÔÓÄǃK³¥WÝ,•Y‹ÚÉ…1å¯íÌGŽ„1ÕØª’M:³‡hßF=¹(óDa§€ñaLS}ÂÑ&¤nQÉ2é&Œ)¿|å¢, c*KIê9B ôÆtÞonŠC‹‚a0¾ýv#&=JÀlÈ”eì X[Oªƒ(¥ƒJ‰®• µB¨!,©Ñƒ³ô¨r‹1áÇL’é±™«£1þÎþõG{âº-捻-;ßÿÓŸÿ¬fQ ”LL_<èà‰ó7àwjZ⇩dréqú©€G2~l`BÅÃÔOauz}„1Õ×HGH) ¤€R ªI¦;FNå$Ÿ;ZÃÔ’ŠŒ)³ÝÕ·²f°µ&ÂIÙüÓ{¿#áÀR\Ô;¦ÔÊdp¨m˜âŒêUûCOz#³·¬ôë,ýM,ýXK=Rú˜ZÒÜ•ð"˜êaL)³ŠhÓо=ôäÂèDagOÙÖCl«qârÄ-…,ðY&Ý„1•°Ñ#uQaL]_·n§=‡1û››RÀø–bê¤>o)SœûÙº;·TGÑq±Þâ#mû!üTñ É ê4âT©ŒcìF¥,ÇgéQåc2’iìŒÜçÃÔÎfS×.€ ™üê·Á‘¸¿ 1L(¹bf$j—[ÙÄ0³$‹–kaLE+1åW H) ¤€èº$™n1E S;ÊS¿ì®ZëWkÜê$TËŒ+%™FÛ…1¥ÕG>±Óü)N³1³×/ýÇZ=‚+%•¾0¦v´~e¸¦0¦zSúŒ!Ú7´rÁ1õ' FlÉ–ÄÙÀšqù…–¢­M–I7aLeh7ô ùQ@S~ÊB9i©½‡1]zS xtî¥7!:Ll`l€G5ìQÂR·Ï»Bœ”Æ'9}”Üx†Ì åÿ˜,=ªœcLQ’I SKI]¬¨ „H&1LE-È‚äÛ%™Ä0¤ÐŠŸMaLÅ/C=R@ H)ÐyB$“ü0µ°<Œ)«ÝÕ³²6mk7®Ö.ûLBU  ®U†Ö6aL Fõ`¹ïȉ ÿêoö©XÝ»Qúþ¢_UaL-lôJu)aL©“Ó|…\­9qAàÿ¯QÏI¸RÄyd«Þí¾N–I7aL¥j@ô0]W@S׋@h=‡1 ¾ôÆÒß"4LiäRGÑíÈ€Ù<'9>“â<'œ$/J Ü›¥G•ŒÉ%™Ä0µ§©ÔU ©€‘Lb˜ Y~EË4I&1LE+·"çWS‘KOy—R@ H) º¨€‘Lb˜Z[ À˜’ì®´µž“ÝîšÉÄê8R¢eÕ‡TĩԟnÆtø±IVw”þð‰ þê¯÷Éduo®ôE)e3ª cjm»Wž« cJǘþzŸhûæ6hhßÐÊÕ4qqMYbd•ÚX·u›ñœeÒMSyZ=IÆ”‡RPÚ @ÏaLû|âÿùägLJûþÝ~ÿŸÿëÿN9 ÓWŸ>ã¥B(ð?ÿé³ÿûÿþŸÒ³ú_þë9æ©u[Þµ´iû{mø1ö÷’}K—í¿ÿþG{¢›Õèö–ïÿéÏîïÍt¾(ˆãGÄ èšß\šþ»Øö†~)Ñ|góÆÛ‹ú6ôþaéõmÇ›äû9”»‚( Œ© ¥lJ) ¤€9T€$Ó7>|Õ†×Szï0¡üþÃr˜ÿ|f S+í®2®¶Mÿðÿcº-æñ›n¿/ôÓH¯u÷ߺQý~Ò·Á&›åÃ_µíñ a²n_&ÿëûË¿ßïS®_ññ?*ý÷¯–0Ÿínër%Œ)cªÛ|ý§¿ø?þáŸ>ßÄõ^köÿëÓ$½ƒ¤s¬Êÿ¤[ë~cº’h§˜ک®®ÝEz cÚ¾}ûìÚð”Pºýž‘ÑÚSb²”xhä–OŒ íÈúa§ïyg{ºN S\ݺ ¬½ñÿyݤ‡R~b˜ºP.%½åš]÷_õÔ~ö¥Ù)õM SI ¿%Œ©ªëžR@ H) ¤@iX¾iäÓ«ÇŠajaö‚ÝuÄè ¿¹ëÄ¢›I›°…â—’^U>øàƒÕ}Ìø)峺£ôQ ]²”þÒÕ›…1µ°m,Æ¥„1¥–Ó‚ Ü&nâSÓòپͽý¤<´Qu›š1geÒ­?aå²ÇÆÔã ¼ß[S´Óý%è[)«@N1¦w¶ï9ý/þøÈÙ¨ç±Ù–¦ò¶äz²düiþÝsLjÍÄ0©ö´P`Lwõíµ~ל¤ú&†©…jëR{„1©H) ¤€R  Œ]½ÿ˜>SI’ E~˜ú¡npjù슓WÜyÍôÿÑ·¾¯|V÷‰­I?®º7Êí(w”>ê@nsؾŒÉS£õ¿xÇ cj¤ÌÞxç÷íû¹õçÊ¿ÿ·O"õç ]<7§“nT +º¦€0¦®I¯·WaLÕHa]|CëÖÅR §=ªÑg×ðH¦7·GI&1LímJuõÜ*°yùžëÚ³jòîßmgÄ0å¶Ü š±Wß™üÄÚƒví^[ßÄ0´Xó›maLù-åL H) ¤€È»›Þz+6¼ùx¶P,¹V•_±Ì}us»öÕ]·Ì> ˈ…?«{pùh´V”cB¹£ôQPÊW¾éO$Œ©Ñú_¼ã…15RfùʶÍåMýl/l±Êé¤[#CÇJ®) Œ©kÒëÆíU@“0&)аyìQù®˜ØOÝ3ú¬?~ôg—dÃÔÞvTW/ˆ!²D SAÊ­¨Ù Õ71LE-È<ç[SžKGy“R@ H) ò­\1cÂÆŸþüg—·ÃÔ¢+â4jJžéЉ©25Z1J†1ÑS:dÆÔhý/Þñ˜)³|bLðÃÄé¡‚:dÊã¤[#µBÇJn* Œ©›êëÞmT@SÃKÉFàzœ&ÈcŠ®˜˜À3½³ÝH&1LmlAué|(°{ç¶ ƒ ½ýÊÚPŽæ^6hkßlÛid‰¦|]±s1dÞô°ú&†©Ø%ÛÜ cÊmÑ(cR@ H) ¤@¾0WL$™Ö¿ñ°‘Lb˜Z[tMØÜr{йb"ÈÒƒ™­%Ø芉©2 cj´þïxaL”Y1&sÅT\‡Lyœtk¤VèX)ÐM„1uS}Ý» ô:Æ„WcúðxéÚ]«6¾Û!´2ÖrPÜ(ôôËbÞÆe—v]1U2á2 ™Ä05!§N)œ/=5bÁ̓c³ ¶ “ûÈ1L…+âf S]Œ Ùþ÷þ(†)‡ÅW’, c*IAê1¤€R@ HN+`®˜ˆ1xþcýé’L¿ÿð£Nç¦Ô÷+“ÝÕuÅT2‡L«_y{ñ‹o¤ÛB›˜]ÆX8ýšYl°-7ü6wA×SÉ2­Ýü΂Õ;ÓeÙ°õ½?üñO¥n«ôp{öcj¤¼»ûÃô_M–_VsÍQÒYæŠ)Ÿ™ž_ÿ&RÁ&Ý©:V tYaL].ݾ] ô:ÆÔ.]u])ÐI\WLŽC¦NfA÷’ÝR Ó#÷®„—çN˜:x Ò²{79ø ƒ—&î‡s&æpÏÎÕ}Ýʹî[\FR@ ôˆ˜z¤ {ï1…1õ^™ë‰K¦@Ô“2•¬ˆõ8õ Ë%|€%mí› J {à tË„st×ÄÃð-3ò©Þåõ½+D  öº|@¥Ù›fóP°M œpLß¶>&9dR5j½˜Z¯©®(¤€R@ ”\XWLrÈTòRï÷ãźbbµ‘C¦~«[€ D]1 ,@±)‹* Œ©QÅòs|¬+&ÎÉ!S~ŠI9‘mU@S[åÕÅ»§€0¦îi¯;Kþ+ðá{n9xÏ yéê/ìùù^{.úDð/ö`ø¡(»æQ –À*aÁ&7f¸%üK/Mø–„“qNeIÏ×b€+KrÑ%z`ÂN|‹mFšÃ_&O-΄.'„1©H) ¤€R AžÝ|Ökbz`ù_Þ»ì/ìßkðb:¼WxõíÉVOF­ø–ñ/~Áöìþp{¯ѓωòµ²¦/·Ñ«þÁö nô¤*zè2* Œ©¸¥ŠUîœB:ë/½dÿâ+}¤€è„1õB)÷ä3 cêÉb×C—R]›<Ä~⥥|8=”HR€Aâð­ùd†Šã_| oL<Çà/cÏáHûJ Kì LÂñ†.a˜xÒK†:ah§ k¼°†úHV* Œ©•jêZR@ H) ¤@Ï)aÔÊOôÜcëû§@ßÖK²¼û‡Mý»ŒÎ.¤[ßÒ_³ëþBæ^™–é c*G !À¤½¦€0¦^+ñžy^aL=SÔzÐÒ+ Œ©ôE¬ŒS˜ài ß`Ü\.LÂßÝ;·câ]1ZbŒ9R  àZ ÃÆÙéØÀ„4xÚ`D‘Ã~lc'ö4q"ê( ŒIUD H) ¤€ýP@S?ÄëÝS…1õnÙïÙ#Œ©—K¿üÏ.Œ©e,Œ©娧* Œ©QÅt|AÆT‚R6¥@]„1Õ•HH) ¤€(˜JS”z) ¤€R  cê†ê…¿§0¦Âa?@S?ÄÓ©¹W@Sî‹(S…1e’IIÒ) Œ©tEª¢˜T¤@YÆT–’ÔsH) ¤€¨¯€0¦úé) ¤€R@ $* ŒI•£ „15!ZiNÆTš¢ÔƒÄ( Œ©ÕBS9ÊQO!U@S£Šéø‚( Œ© ¥lJº cª+‘R@ H)P„1•¦(õ R@ H) ¤@7ÆÔ Õ OaL…/Â~<€0¦~ˆ§Ss¯€0¦ÜQ¦ cÊ$“’¥S@SéŠTD„1©&H²( Œ©,%©çh¥»ßÚƒ™þ···òšº–HP`÷‡ÛaÖüýGoI!)Ð „1uBeÝC H) ¤€(­˜J[´í|0aLíT7ïׯ”÷Rþú£€0¦þ¨—Ÿs…1å§,”)ÐI„1uRmÝ«ƒ cê Øº•h«˜Ú*¯.^P4Í_Ђ+f¶×ìºÿ®¾½`Ù,fö•ë¢) ö­h%¦üJ) ¤€¹R@S®Š£(™ÆT”’jG>…1µCU]3/ cÊKIô/˜ú§ŸÎ–EU@SQKNù®£€0&U)P„1•¥$õ­T@Óü­TSת£€0&U‘Ž* ö­£rëfR@ H) ¤@ÙÆT¶íÈócêˆÌ9½‰0¦œŒ²Õ„1µDÆ®_DS׋@]Q@SWd×MÛ¯€0¦ök¬;HÎ( Œ©3:ë.ÅR@ÓüÅ*¯‚çVSÁ °hÙWûV´S~¥€R@ H\) Œ)WÅQ”Ìc*JIµ#Ÿëßx˜1ðoÇÅuM)Ðe„1u¹ZtûË÷ß’I) zMaL½Vâ=ó¼Â˜z¦¨õ ¥W@Sé‹XØ„šæoB4Ò¬˜šUNç5¥€Ú·¦dÓIR@ H) ¤€ ˜TšP@S¢•æ”Ñ«þ`¦Ò<‘D TÆT‚ÚðÎö=@n9¸¢GR 1„15¦—Ž.Œ˜ STʨ¨£€0&U)U@ÓüªT@SÅÖ­öìQû¦Z ¤€R@ H~(0uýQ£V~¢Щ½¨€0¦^,õÊ3£ÅÿâzY={™ÆT‚ÒåôŠR) zMaL½Vâ=ó¼Â˜z¦¨õ ¥W¸ýõ©ŸZúrÖ6¦€¦ùÓKG÷KaLý’O'7ª€Ú·FÓñR@ H) ¤€p˜óòɘT#U`í®ûáÇk÷·7z¢Ž/+_»yí®Jð z)£ÀªÉÞÌÂæå§À pzE©½¦€0¦^+ñžy^aL=SÔzP) ¤@* iþ,ôî=²0¦îiß“wVûÖ“Å®‡–R@ H) Z¥€0¦V)©ëH) ¤€R@ H)Ð5„1uMzݸ½ cj¯¾ººh­»wn›0hÒÛ¯¬ ]ù¥§F,¸ypko§«IÂ+ iþÂa‘@S‘J«yUûV‚BÔ#H) ¤€ÝS@S÷´/Æ×îZ;aÍ„bäU¹lµØêKêzR  L<3 «F 冓¹È¢2QOÌ¡°P”*ÄzRé{)Ð3 cꙢîµÆÔk%®ç-¶)¬ÒÜËáÛb?žr/Z®€¦ù[.©.˜¬€0&ÕŽŽ* ö­£rëfR@ H) ¤@ÙÆT¶mõó ¸o@ß¶¾V_U×+€(waL('e±qRX%L+`r¡ñKêŒ.(†éÃÝïEo¬BìBaè–R ' cÊIA(­V@S«Õõ¤@Û@Oô‘û¡ŸŠ xcqd ºhŠîyî)È©m%£ çXMóç¸pÊ—5aLå+Ó\?‘Ú·\2'¤€R@ ä]aLy/¡®æoЄAûݺYl™7ÛCñ|°€Ð0|‹mQ/]-®VÞ^¸@°!¡¬Q Æ6ŠEŒ¯p'üeqó+$ÔVæ@×’íQ³˜>Àägð—SŒù?tÑÚ¯™…ö”FóWE‘Ýõ™½èŠ)©—Ý;„…‹âÃa6a¤PÍë®3¥@ÎÆ”óRöšU@S³Êé<)Ð 0ØØ¹Ú[ fè}¢cŠ=„à¯uOÑ‹ÅØckßlâùHØÀ’‹näZ÷”ÝS@ÓüÝÓ¾ï,Œ© ½›¬ö­›êëÞR@ H) ¤@áÆTø"lçl{oðÜÌ x&P,ïýá=À+柉ßbÁ&ÐË2dÈý*ŸþgíZ$(ßOŠO±žË ¥ V‰™G5àJ;ñ×JܧŒiE?ÀÿNŸŒéý@ìë“K³ì‚µýHc•lÁ30Æ’ã\fHº`Çhf¡íEÒø –ἤB$¯†P œ0²‰$Eóh\o! ¢€0¦‚”²Ù¨˜ULÇKn*À®'»¡H$ë1®À6»§ lŽ—ì[€~*(}¤@) iþ*ìî<êî·o}w6ÓÂ-çßշ׊7Ù|Ûlé®eU`÷[{Ь1ͼiƨãίîÙµ©¬Ï­ç’R@ H) ¤@ËÆÔrIËtAƒT\>‰è>³7Í&¹ÂÀsL 9d¹~Å:t(€2 hÏRDŒÉˆ%Û`Yó¡@/¡zÐ Ü5ÑSWCñ1ܳmÛ6ü[Vˆ •\S®~׆³`©³AKdb8éDtË„frU|Ì æƒ¸¦=©±…ˆI".hGirV sF+»¶Hè¼ÆFM.Ìó+£R  „15!šNiD€J¿[ö —¢ û…15¢¥ŽÍ À‡ìü1^ŠM¯.Ïp "¤€R@ H)à) ŒIõ E¸ÛÀ„€ªZ†ùgÂ6¾5~…H<>ã'„1õËÂs DÿLüGòß ¼Ø@îžÙ³½ŒáxB0ø‹m Î º¾eûy¯Áƒ#?ØÀìʼ¾rïèn‡.‹¼ñ^6£,y8ÌuÄeè ×uËD]F°Y¨ÁŒùw1&œQ^ذÂ1ÂsññMC^Ùö° ¬Ä­ °Ç ÑêkEôú–[Üwä½Pô¸¸•u´¾¹¼·CÙÆby¬B˜2ÖŠÎFV‰Þz0YÀeÏØ0ÿ=øì vâHÒ0šYèLÑd¿ Y´ôBÄÕPp(>zÛb4Naæ(û½t¤…Q@SaŠJmLaL饣¥@0VÉVN˜kPŒ.Ðeg”94—¡ì›ÕÅüëÖR  cê‚è=wËg7Ÿ‹1aÏi¡î€3|'LÑtÇQ¸¹n!¤€R@ HÒ( Œ©4EÙŽ¡›%\àZ° µ ºúdâÝA;MX`FYòàrôTD¤‰¬È#ZHÑiÓ{ï½Gd‡‘J!ùPÉHìáÁø‹cð/X"lã\|H5…®ïfW#=ÃÓ±a>¢ìØÆ‡Ã;F/KR‡÷-ÆdÍàq”ˆ¤š§Éâ¡tÑ„¢'¸†¿ 9âÂ)2²è±A‚Í ‹z’ "»†Ã¬hH± ¬ÄYjø—µg¹erÄñÑë[é³¢°p¢}DEë.ÅÌà‚±—µ13˜²49ÆX%w³ X29wú€ûñW3 )ìwá¤OR!â+À¥ì¤—øÿb' T«Ü³K­#¥@‘ÆT¤ÒR^P@SbéP)Ð]È*!ôÆ—K膮„HÜOÊGÒ,÷(¢\w‹Owº£{oÝ5Ö!“\1õV%èäÓ&9d’+¦N–‚î%¤€R@ _aLÅ/Ã6>À²)æ0øìÚbØ 6p’ñ.ód)ó´ä²M¤”ð—°¯l’°séu‰¤ˆ‹1qO4 [ôú–as… òv¼ ý*…ãÁ¸;Ý….ëâ5@^Š…1Ñ&ðItÄ…Ü/±J`5wÿmècä5méE‰EF/VÐ–Žšè+Z±“+´eÞ¢×·<[=‰^0Zß,È$¶£—ukqº†ÄÑÁíS€¬®Ož ó˜kà”6ð-¾â$þ2ÒœfÚWÍ]™³?é…ˆR¶"”µ;aÄRÖG H* Œ©„…ªGòƤz ¤€åU@SyË6WOuÈ$WL¹* ²e&êI®˜ÊVÆz) ¤€R í c‚SÕ¶ßF7q Ðÿ ¿èã¢'æ¢ p’‰^‘Ì÷öðDóäÔÆÄë[î\ŒÉ½ ë{ ó0sÃÃ̸.ëÒ0Ø.ÆÔ ëú(²ˆr.„m:å'DÐ-䋚71ÙõÝŠ„íXŒ)Tßp={±ÒF³íbL¬ T·R@ H)ÐÓ cêéâ/óÃk¸^æÒÕ³I) z]aL½^:ôü!‡LrÅÔ!Ý{ö6Q‡LrÅÔ³•A.¤€R@ 4«€0¦f•Óy-PÀŘp9PJtkd®•EŽ ïǯ,|÷0ê9eq $^-t}÷I’0&ܾÂé=ˆ.yŒ¾ ]ÖÉèi-¬D—p1&(I@Í-,F‘+F„ˆtQ´ \êˆ×ŒrH,,œ½¾)šâ)ZßpÑ%ÖÌèeC1…1•¨æêQ¤€R ¯ cÊkÉ(_ýT@S?ÔéR@ H)c„1å¸pJ–5×!“\1•¬póø8®C&¹bÊc )OR@ H) ¤@ÞÆ”÷*uþ‚Ø#2xœa(€NÈàÒBøËãIq'90L8—aÈx þ;‚¼6ð1÷ú–c•ìtRS8€ÐoÊgøXc/K¦Š¹ÆªË.Æ„¯PŽÔ™…ee’5ÙIªE ÂJ“á۬ȬPXj¬¡ë[®\ŒÉª%«A´¾±½â¢—u÷c*uK¦‡“R@ H|( Œ)å \´\aL-—T”]Ràý·ö<ñ›=€6ô‘RÀƤÊÐ)Ì!“\1uJòÞ¾ëI®˜z».è饀R@ HæÆÔœn=~Ö¶wg÷mûÍ>z«­:¸±ÞÚq£6]¿M—m‡Í]sÆÆã´f©9étV€a3 »6 «Êb’œ’H5D ô ˜z°Ð{ã‘…1õF9ë){A 3ð®šxi/<«žQ dU@SV¥t\  C&™5[ ¥.‘E:d’+¦,Zé) ¤€R@ DƤJÑ„}[/Å ïÝ?ljâ\RtF­üÄk*úS(ÿR ^gî÷, Z ]èúÁé!¥>R@ ôš˜z­Ä{æy…1õLQëAK¯€0¦Ò±° „15!šNiV8dºù_âo³ÐyR èIËìÑLÇJ) ¤€RÀƤÊЄ˜š­4§c*MQêAbÆT‚j!Œ©…¨GÍ) Œ©9ÝtVîè-Œé¦›nÚK)Рÿå¿þ·M›6åþ·¼gÏ;ÛÏú§½–ß~F²ª,JŽ) Œ©cRëF{ö¼õÖ[ÇŸôü•R  |ðÁÇÿ¯Åè¢t@ÝB H) ¤€ * Œ©AÁt¸§ÀS‹ÏûÊw÷zý5’£8þ¬ÿûò{?Ûƒ®GîÞšyïÉÿc¯·–<Ñ [Ögüൗ=3ÑØëÊú€z.) ƤÊQRz c:ùä“oºí®­»Þ§ïoñÒîo»ëØãNÂÆf¤×«éÕ×w{é5¤ÅI/ïøw7mÚþž¥ÛßÛ¸-H¶½ç§w7l}w½“Ömy·’ÞyiË;/mÒÚÍïxéÕwÖéí5¯¾ý"Ò+AZýÊÛ^zÙK/¼üV6½µÊI+7¾µrã›L+6éù oiýÏ9iùº7,-[·kÙKAZúÒ./­õR_vö­Ù¹¤’¯Ù¹øÅ -zqç¢_÷Òê×:iÁ ¯ûé5¤g‘Vé™U¯yi¥—æ¯Ü¤;žvÒ¼;æ=´i.ÓsÛç8iöòm–f-ß6kYf.Ûæ¥¥[‘fXêÛ:½š¶Œ˜¸à¯þzŸiK¶ MeZì¥)^ÚŒ4yÑæO~úÀÙ³gç¿@õ|ñÏð¥åË—ç?·Ê¡è˜:$´nã1Lh{ÍЃ:H$“*D»Ãôõozñe×£Ö‰dj·Úº¾R@ H)PJ„1•²XÛúPèx£ûNøQG…y[ïÕ­‹¿çbï¾víÚ¾¾¾ne¬ë÷½ôÒK|ÊY_ûæ¡“'Oîzfú™%®Ršøª—ËºŸòñôªEë«_‘E«ˆ%ˆ<ûf¢Ãd&*hñ)ÛR ¿ cꯂ:?§ ôÆP ”Rlºtã­w}︓ `r饀©–^ɘ* S"À´Õ&l´aÚ†)À˜<†©‚1ec˜Þ3L>ÆTa˜°Qe˜3ÕbLÃTƒ1 “‡1y Sc &cª2L+ë3L`LÃäbLôuZ_cŠe˜ „1aºìš¡ÑæömøÌçE2å´ÁU¶º €0¦.ˆÞ‹·ô->F?1íðÃæˆdêÅJÐÁg¦qêŽûE}{rö2¼÷E2uP~ÝJ H) ¤€(‰˜JRz Ÿa0iÎrt‡þntÉH¦mÛ¶1Zñ?QQ 4pàÀÁƒï·ß~…XíÙÚz†é”3ÎÇzà…«¶ô/ý%™bnm†S®> E‰P”±‡ 0Å6’˜¶ŽåV7ꀰh}N­ÝÎ[ÈLÔNuum)P„1¡””Ç&è=ŒéÖ»\7K!béc¢×¥ã%Ï S*½’)‹&xcrœ0½ã„)ꇩ℠ޘ2ùaê'ÃTqÅøaê'ôš~˜ZéŠÉŘsÅ´´ÆS}ŒiQ1¼1aºüÚ¡KÃ’mΑLM4†:¥¤ c*iÁæê±<‹Ï<úÄ\k‡GÉ”«"*Uf<ãÔ·»ãþ1Vßž˜%’©TE¬‡‘R@ H) :£€0¦Îè\Ž»€a oòÜçØ ‡ÉôÖr‘L@[ÈÖÄbLpÞ¢…E9aÂÛ.GáÖ} 0L§žqþó»ë‚•[ûI2‘"êú'c:t(&æ ÔZw‰«®KÔ E«¥,3Q Q ú«€0¦þ*¨ósª@ÏaL7Ür'%7Yœ¸ëo¹SðoZbü8×ñR€.ÅÆ‹†«ë)5\À0ùäV[ 9l¤Ç’kÔSó S+ÂÉ5êŠiùöTŒ©Ž+&’cP¹WLù*G† ~¶l:~³f-^/ŸL9mt•­+ Œ©Ã‚÷Þí‹Ï“s­†EíðCÏ–O¦Þ«mb§¾ñ­Ã†Ý?&Tß&ÎÉÔvñu) ¤€R d c*Y¶ïqÈ0M™ûÜóë=ãÛ2c ïÖ{š÷É:Œx |°Ì$Â6üeoA'ôbcÕî ã9í®óŸÛòÕo2iÒ¤&Í´…˜ŒÚF8,¥ Ý¯Há«BÜãV*ì!œD<äáB{¬"1vAîQMM<©Nɳµ­7eÑÊsa%å-j&¢¿@6S2±L•g)Ф˜šN§å]žÃ˜®»ùÎ;%÷_|{Ì÷Oä/Bœ¥mïm¬¤ Û€+1½Kn ¸’›Ü°qièR„^ Ln¹4LÀ´î—*˜ª“?½š0Uœ0a0Ä’[» ‹KÐãñÓNÎ--^³sñ‹AZôâë^Zí¥…Nj,–\£~˜žK÷ômæRÏÓ K!†©Ïc˜j0¦Å[¦.Þ2ÅK›½Ta˜ˆ1ó”[¦`àòðËö¦ën÷JܦÏKŠ×OEM_´îÓŸûÒ¢%KÊ-Œ¡eUI«¬0BîÌ¢ ¼9xFNh¬Éø±åDYŽ…{Ç£ÙB%n¸ƒù,´cg®{³¥l ®ƒû¥€0¦~ɧ“Ó ÅgìSóB6Mÿí¹/J¼‡›uà—¾ÒÉd†ãÎC´©¯»Ä­b¡í×Ì?>IÍ{Cšpy´‹[^j4NÝùÀX¼÷CKÙIC}{|úR¼÷ׯo’dBþ;S ´ÑãÅj3.ëQ¤”KR}NéK´»Ð[^‹tA) ¤€RÀU@“êC]* Óó)ƒ>LzD£$ˆ³aýaP&f†Úk¯½6…¸dØx&‹þ†‘#¶éN‰“Ñ'ØÏíƒcÈ»ØÄQO4¨ôð`ÊP˜ºÒ•à0L§y~Åî†<`w}zùæ¯|ãqãŸhôaMs·Ð©­•]¨ ‰£ñFt§äzÌ≡€€(;s×äÖlÂ~#ÕpM‚tø`C S£ÅZ¬ãÛgÑ2çp¡ IÛ ìVÓ ÍæÜoæB6yšnh]W C«i®™ÓC©ƒfÉ~š‰lf$ÿ‚§˜õB¿J{(Ò½î4“}åÎvY¥µæ±î„Qh‚©¡f!£•5ãa ݺ­kj¬­òV/.Œ©CBë6V ç0¦ko¾3N"¥tíMÆ„ ‡UªC,‘^ qK £Kµî—2ÒK«¢ôRƒ“OÙï ;aª˜‚NOÀ”î„éõ/¼†ô,Òª =L¾&¤ù+wiÅŽ§4oÅŽyÏ#mGšËôœ—æXꧦ ÃŒi8ƒÊ%3L±(·NÿR#÷«0Lo¥XR@•M_øÒ§?÷ņH&w}o+ûC£‘6iÂUhè#"cEg'™êÎÁ[žÍ^c{Ðé´El0-a»¹É]æOA»@öÌ·IÏž»¬0¦ž+ò=°Y|̦r‰›&°´ÃÛÙÉDûNkñGZ±c5Š6õI¿nVõ‰ÞêÛàͦ>É>›]¼nhé E£Õ9Ý2NE]0›C}7­ïSŸûb$ƒ4 ìÆ>rl}cô ¾aqåjy"¥ª'•ëCôÛ¤¾D» ½åµH”R@ H) B <»ù¬»úzË.ª:ÐÃôôóî Ïõ¿ë úüõœ7Þõp£$“‹1‘G1‰]ed5 ÆÄn0¶’‰6×X`ّ͋Ù&[#ÃØL™´Ù4Y¸š;²¡5¸œ»­™½ ¸º7:7«ºÀñô}ÖTÚûÂmYà¡,Ù^ŸÇ„žÑjЉÃÇwÛ^Ûæ¹ö aL¡+à")š„²áŠSÿj´vÓ8u×cclèWáÕúöÂkc§6C2qòõ\×­o¡Š‘^ßøÔ ÃDà‚KH+¼•Ž•µí±ë³|Y”ö[pK$TÕí^¼>k)».Vñ¬'ªc4ª²|C7mk¡7ZIt¼R@ H)Є}[/ÆÔ„n=rŠÃ0Ń,tt†‰ƒ¾†5F2¡3ɱ{Èø‹¹ˆÅìrY0&v¤í:貤‚ø–CB.W@?×dP9ëÍRÃcì+f,4{ÝÜ¿ÂÕa:Ëc˜ê.[ÂòÝÙK_ýò×óÉd%k›HÁ˜XO &ŽÄ ÌÑ=+[¬8˜_Yl¸Œ‰0œ;ÀÁ¹ýñ)R¸ï© ›E+“…¡q‹–kH‡°¬x48˜ÎhI¸ßZ0~åú·ÆWöspçÜŸIOœû°!3QR¤ŽÀ,Ù¸™Ê»+±íEbu´Ã&}\ 2Ï9³Ã`‡!ÛN’¡‰Wà·Ì›µx¬®!ÈÌY¡¹·RÙè/Ü•õ Õ4ìq5 ÕsžîN0Ùƒ„ÚR›£®,$­k ÉnfÕÐT®2½ÚC™Ô|‰G‹ʸE“dótí«Vš|R÷t÷ú®yÖ}Iõì·.Œ©âêÒÝT ç0¦kn¥”ÖNòù¤knvô±'F]+qÏK[Þ©¦Íï€U²T-Õ„Š{ÄSˆ[zñ•·k½.…Ñ¥Ré%]Š÷½”?ŽAŽÃî—‰¬rý˜úå„)[ 9—ašîÄ’›æ8aÀÄ4|‚ç)…aÊ¡7&aºÞa˜".Cµ§%šOyvmv’) cb?iÐ ‚®ú@<‘]:l`ù²=6f6ÀˆŽdqeןÅmc;…ÿX‡’¡»³¯Él®çb³ŠÎ™M퇚d7†:™Ëe|KZŸËž¢÷²«ñ”Pï¹›ÍÜ[St“ŸÇžš—fÓ¬Z´=g„h‡ï{tFC>™Ð¬Ñm‹_­y¡±2Ô ¢mÁñlޏÁØ´r Í5‡Át$ã~e­™™/Ùbóv\¨ä2.¼>ö[°´A„ÞvdñhI7#)oÍ’=¾â1Ñg´’g;ÏÖ†ÌØÛ„M7vR®¸²ü›a"t¤IJ6h}na} ŒSz SȆîv"Ú êÛ˜)KòÉÄBD¶-0AÝú­)õÍ>¡ZįP¨¿•NlyÙ«–u½‹ØŠaUÝnmÝ›b-uP¬¬',JÎôà_[Ýn7uªµ…ÞÂú£KI) ¤€) cRõHR }Óž~>´€fÕ¥îB‚còÏÃßüõÃFe÷ÉD´ÝH")Ì ¶Ù©æD£ŽqÝ YÏýU|È?áÃE€ØãÌÙaæ•y/žË›áÄ‹¸_á›FÅ‘=⩆aJˆèí.[BéÏê{¥!’‰CfÚ'Yè,…”‚渕emCiŽYl[v8†_Ù ½Õ»‹;Š1FŠµÂ½”Š2)МEëþF,Z®!æzƒ–\%m Mà Ù÷€qb_…<—©t2>KŒ™(ÃôPCf"Ú=ðâp'2’¬Ž´ïY»²Xš†íÂ.f<4CP’¡‰76pYN$рÛš!ˆÖ›2aC•ŠùqUiküØêÚ›Ô- Ø+›`²‰ÁÌtF_eœk3ÑøP4Ør#d¤BøÛÉbz =8N¡õ×gÑD¯oMy©)ß)QãÏÕÔXÆxó‡ cj^;™kzcºúÆ;jh$—LÚò¾=ú{'º|R"¨DK5n–ªÄR,´å–V».—°á–Baã¼é«DzéßK½”!~\ß/nnÝrô™l ¸ŒŸBÈE£È­¬EÎ$W"‡mǼ1ÍBªøaÊà„ik Ãä’{ÐØöž²x3}/EÓ'?}`~¼1Õ0L¡±t²%1û&Í_»ÿg3ùdâ#Ô-s»)ìŽpû[<غŒØfÒí²K„l;Ñí¥Y‡¦n§Ð½—Í,ZNxw\„'æ{ØÿCW,šUæ6¶µv{¥6ø7×ͦ³½—]GºÖŸ\¿Ê”9aLe*ÍŽ„JlÏ‘=ükÔ©e ¤)½B’&IÙH²²5]së§j]1ùS0ƒ‚úöèäÅxïgŒ.g¢ÓS·¾™aÂ*FJ}3’$ŠÖ™¤òbM ½R£%‚ Z². «±Õy^ÇìõÌ?íGn=g_"zS>TË ½éÚ¢¥€R@ HFÆÔ¨b=r| Ù!®ôÁìYô]wGV’ÉíçSXýùÌ[ûrå0L.ØÛiW¯l‘eKóW옱$ÓÁãÆ?Ѧ¼¹€–ßÂ]Ôò‹ë‚ùQ ŽE+ÎÙs-޲ùA‚xlíu DIȦ¤[H[æGÒÎç$l&J™ò'ïš6Ñ¡Š åBkdŠÕÑ,oÆÄ°|] Lh¾‰æ›ŽáœQº¡É®Àzåšzl®Š† ‰+‡À8ÞK+­~vãºY²Ë²pùD¬Ìf§â-\£¦µnõ&¥gUžâ,÷›W`%·{ET†1™z6¿2½º¿&Ì£[4Ñë»%E˪íq1&^Ü5 ™é8TôöŒško‹!Œ©½úêê]S ç0¦«n¼#ì9É ‡o1Ÿ¡”*Õ°JI¸R•X‚Ë¥—-9qâ|h)™[ŠÄŒËæxé9då&×÷’·jß’·|ßÒξµz©?ޱSãǵ`ªa˜–o¯‰"˜¶…£È-ݚ䄉ä¼ä3LpÂ`L SÞ‚Ê9 SÍXš«Áâ]2T,)Ò÷äÓ™H¦hÀöTÜž¥áAè©ØZ.wLÂéCûÊ:I˜Èò³·gýEëù¹#–P·Ïºè`Ùt¾uͼb“—–Oö5ùq!}>»VìÌYGÖZåP¯ÿº¦œÐÒ%\$t/^'”á®5ù=xcaL=Xèm{ä˜UkfÎŽ·i.ñ`Óœ·bÇÜç·ÿnt&ŸL&¸t’&ƒP#lªû¬nãÃѵÛ@Ù(—-Ûp×m÷زv?îÂ)^“ËÙº²ÁŒ¾/BcàÐ1ö€n–Œ¦²á.³äfƵ ðA(ÛsüåRþkžÿðúp öòŠ^Á^+¦OLÊ_­ª€iÆ©ôúæcsxï?2)+Édõ¦ÃïØú­Iõ óÝŠlM›©k‘¹ûæNÖ«¤òâ18˵rFK$Š1¹ÇXVùî}ùÊæïŽ= ;8tS«™-,ôVU]G H) ¤€È¢€0¦,*õÚ1Œ%Wã‡Ée˜âÒÿ® ú®½=É”sŒ‰¾1zmÆ1Ä0ùqšÞ¤±Ý\á&-[Âøkú¢—|­]$“YP[þ“ä@Þ\·üº`[´\ü¥ž…¡!‹VÈnç¬u¡ŠG÷3<2ºd(d&ʃªÎC¬™ˆ¨e³ÀÚ˜§ŒŽÒ™Èt8UDCeÈ"Gë E€å„vH.°ŒZ`\à±ÎwbÔÐäÞ®`; Ê¡aÇ Aô9Ç«¹u,Z©p–­ë³Ò$WŠ­ÉvLl=w'˜ìÈÐëÞ2ïîw­”Ì­R| ‡ŒTfà5Œ‰‹š^£yˆ-÷ú¡_ïeWŽÅ˜ÜÚ{}>‚;—×áN¯ÜNS¯”tÏ=gïaL7ÜaQÞ¢WÝpÇÀïpR(QájX%BKµÄR2´Tñ·”[ò†Oa¯KñèRÔñR8r¦1¾—¢ô¦ZßKŒZRã~é/h ý ù=¤jZ‘ÉSSR¹éN¹(ÀDLĘ’ü0å cò¦ë*±ä|¬þ·bÇÒ!Ö~ÞóÞô9¼[=1oMŸLèš®NÞˆÁP߈{ˆÛ£cŘð­uPlÛ¦ Ñ›D‹½±P¯×m‰q¢»Ì‚]F÷^œéŒÞèP?‰¾ ¢[/3úõJéź­Ö³öȼ/¨ ò]{» cêšôe»1,>0gucÉUÌÙ.KšbÓä îžG¦×.çnØ”¡©t‡|„A ¿]A†Òp 6×8ÀZ!kÉ9¼´ƒí:¡ÖÌÀ¸»-KB\bÃFÎÖî%¥í"ô‹1Åf‰·³7QôYÏÜVÝ |=áÃ76ìA\AÈê#í Iš¤d£Uõ>0N=P‰%ç[yï^-~jQ]ŸLæh™çk·n}‹VŒ”úæÊz«âß5eïôØòÂ¥`U±¯Ì¤ªü!ŒÉ5Ä >Ð0Š¿ôÉy)\™F.ÖUëKDoju¯U…®ëH) ¤€V@S‡ÏÿíÈ0MucÉE®ÀšºØ!vü¡dñ}Ë·_sûCÙ£Ëå_–É¡Ç0y> õ^0„Ô`Ãxê¢Mí#™z¤ ô˜íP lѪXˆ¿d¡ô²[´bñ[oƧ3"ãq›nÀ~‹~@Ó„Y½L“^æíúm&ÚÁBÌb&rÍ;´–cŠZ a¡×"Y¬&c ™c Mv‹Œ2i0\QŠ­T49†¬Ø²•qa›UÅtŒÉµ@í²ëbL–yºK©²›^í¦6¯-šèõ]5¨¹)µ—ºEF”Í~¶f|Ã45ÖŽ†=|MaLPY÷è‚=‡1]yýQ‰{À$ ¹Þتp’¿Óq§Tõ«*UX¥XKÅKÑ8qÞ0ÉMëƒY++nŠñº”]ªu¼äM¸:èRÕ÷R½Ô¼û%ûö<xN¼á=Ós† <0¹ÓŒ>× Ó–¤(rðÀD€‰Qä_ Œ ÓÞ˴±tˆµw\1Adã›0wÍ?æÀEK–¦´7\t…~ Wä4J˜øU¬‹#z-"÷chvà, {ÌÞ° ï‡òfÞ5Øæˆ;9Ôa.câSðúìfñôXŒ »^F’z¥ìµ»dGbÖ¿݈g±ïB«ßk·ÆÔk%Þžç5‹ šÞ‹ÛMó¥cñy1ðÛ¬Ê]¸b‚±Àk‡—m»ëáié$“5˜|‹e-*[QÖ²ñ06Ȥ? ñ`ë ˆ•µTtiÃAi¨5ã~A‰¢†LHlºÝûb½…°W^„ (ŸŽfæÍ "6Ô¶‡WæYöâ=#%ââ0f’¯ îw·M.^ŸYBþùFˆ½B’&Q©ív-©€4NÝi »…n}‹±¡W\UÖØõmù¶‡ž\„÷~Jt9CŠ]1íÕiåªoÑŠ‘Rß\YðÊæÛ™U—¯i·Î°\’Ê‹—r_µöq+¿û^æ)nþQ‚fƒ#®dõ¿«K¬E8׺4!³—kÆjIéë"R@ H) ¤@ÇÆÔ1© q#c˜Bƒ¾¤i~. ¹b²AßÕ·ÉTˆrg&†éÍ4†)Õî ‚ CþÉ 7}é vùd*¤Êj~ˆµhEVIí VåE,Z˜Íáêèì-×;‹é€6N®yŸËϸß,?<%JœÐÅN~„ídN:l&¢ÝÆLŽ”=Öêè–5ír±ìŒÅ˜lЦ•XCSCmžî´‘‹ÅbL|´¨Šæ 3BrRÉ = câ“Ù< ír|"×fvQ.û´_ ¶£F*Ͳ˜^í¦îÁ!ãXôúT‰Ù ÉŽzÒâÊ"¶Ò´"3[tèúÌåwò'Ó‹÷ÆÔ‹¥ÞÏ\c²Òl4 ­ cr½u•TÙƒo:æ„øüpÑHpßøöáD”˜žœµäª›îòG¼oÝ7jâƒ/a¶7 bÚðæ7¾uø3–`ƒS¡=iâŒ%þU&h‰1¹—9ÜR(`œ_¬&lz¢nòÐ¥ÇK‰‘ã0,?ç’«‘\÷K_ýÆ¡G}‚ë{ {ξè*×ýú¸n½tØÀšø 6’&tˆÏ¼`È?}êóAÚÿóÿ´ÿç=êxÌûÎdZºµ†^ª !WÏSÀ0™û¥þcL»v/o÷‚ S@¼9s™§Ü4ïÈ‹'#sÇ3W\ÆÕ`puñï]ä§ ïYèû ­l@½ñs^¬K2a>æ–É…¦ÍQêì~YgÎØ9Il*á+»¦ïöc×U`'ú:¡Q¯½šÝ_Ù)Øp[°hV±'öÖÑ¡—Ûíæ|¼› ´hÁÂШEË’GÍûVG÷»ƒt»B¬é>‹9<¦%f¢\9cäôuK+KÝ~vãÜ Ï¼Œé¼+F,³7ÿG§‡ÒÍDfA¹„fm\ÃK¨8Bÿº˜Xã Ùšù%dh Ù3™±èD’kGrmžföቱ•Š_ñ¾î\˜Ý ;£ÓâI¶ ›`ŠZ–B™wm§f˜µc\[nèR|ØŒ¦W{ðuÔŒc|ö¨…-jLf&M^ûMÅÚÐÜë‡r›ÃcI²$Œ©$Ù£a ãñ^pÛ+ÈQc""Í—J 0&º´IJøSÊ+}ײ•ôæÉ?ýÅß~â¿sœƒôäÌ%Ÿúì-W:ãœKŽ>ö$üEºwÔD×ÇÒ¾ŸøïŸeâpÖ¨ñ³Rœ-eá–jÑ¥_ÕE—N=ë¢ÇNOç--:åÌ‹~~æEÏ:‘ãöùÛ¿Gò‚Ç­ôÒÃO>³×^{ýìŒ g7D/™ï¥O~êów?¹­íŠÇ0];4X ä84F•ÀHã–ÇVŽ™»ñÑ9ÐIýÙ sYŽ_=s¼×O½Ç0¦ÊH£bI™Þ·uܬ՟¬ç“©­ÏUЋÓ?ª-,ÀSDWôÑJ›maL¥-Ú=->cžœm‡ÇÍÛtÐYãÇÎ݈v °’_Ý>í0¨_¶Ã´ø€â­aJ–m…Eí𰇦Ö.×χä~^¤%§³3‰Ìp5OÆkâHZ²B oÆÓsuØÖwgßÕ·ú é0¦¯ë°a÷Izï\æ{iôìõ¨o˜A‘ï}`L5õÍyïýŸLý—+?õ­ÿÏ¢+H) ¤€½ €0¦^(å,Ï0Lóžs:áÏ»~¸¥ƒÎ0Ls6`¬wã˜ô¡þ“ëçpÐwÏSkB üAß–!"™²@›Ž¹ð{.ßÏòÇÓ/†éTŸa²ÅÆ®ße˜^1þ2† ËHÀ0ýô†¹Ý;iM°ŒÄ&hÆûO>³á‹òÉÔ¦’Õe¡À3÷ï9ý/öŒ>+fJ±hafá±¹Ѹ¡’“aBõ¾rIJøá¨‡g®Ã¤Ú:aò1&—Òë˜E«ôåÜ3Ì’(AÑ`™=k=¦‡`&:ë¶ùœB‹ÐÖí|¤{›7uñ¤P9`âvsÓü w`Â|$§$ÛWQc/ÃT 2hiÆ0âXš# o5ØE“PˆÏ\ÂåÓQRDÊ‚Õ`΂ ZR ר™/|òÓu¢ËµïÑ ze œ!˜.ÒTЇ*y¶…1•¼€Ûûx´ø<úÄÜ ^ï’[÷&3g£F{ +"–ÂâãµÃ+kÛáŠMo4 ÐO]²åö‘SÚJ2¡½ ÑëíÕ+õêÀ@Ñ`6êC˜$>c›úCû”õba¦*Ãx^¬©o|ïÃï—…&»ŒuÀW _®oÎ{ß«o}^}{p¼÷ÛG2媾º¶(óR@ H) ¤@g Æô‡ÞêÌít—|*@†iÊÜçb}¾%6XŒûò\­ €µ÷,)ãµyì ‘LýhPtj!ÆTˆbÊe&añùìÃä·ÃÁ[žïqr%Æd«ÖhñÔÖûo´cB;¼hóí#ÚK2åRÚ^Ì”kŸŠ…™<†é›‡Ýqÿ˜¤úÆ÷>ŒS|ïcúdüü—ñÞ3‡„÷þN1m]¬ë¯à½ïÓÛm%™z±hõÌR@ H) ¤@a Æ”1òoaŸROS }“ç>—Ô § óÁè„ãï_ÀBÌÃjŠ1ÍãÛñ—M E\²„X] ƒäå7‹dêF=4Œ)fÃtÊç§Ø]Qú NH°Áî:áéõ"™ºQö=pOØ`¦º-X°:5F†+G.ƒE 5ö„+¦c‚§gXо!]óðsA8¹Šsq³0È¢ÕŸªÖ ™(~zfIÌÍ¡œúRÅ,¹¨%Z*o†èŒñgÜ:_f¢þ“Ε…Q@SaŠJ +€X™`àS úº>Ædœ°Æºè$“Ç…\3”î‘,¹N’ðíw¾{¼»'i{à÷NúÝCÉ*¹|)!q6à` dô—^ûµo†YOK8 Ð,!c«„„ Ɔ;ò˜“FŒ›ùµo†qSZ„8EŒgÓþŸ9£)¤ß^sÇI?>ýÁ±3-yý‹¯ÿæš;'rÖEHk!aÏß=ñþG§Qââ!¸_ºïÑi‡+½ÿql#a?ùéˆ.}ÑU Ç„¾È$ûûÐÏ6ðø[bÂ6"Ç!aã¸JKX“„\ Ð1¦áãç]3mù±?d:ä°ÝÏOU¼s þXஆœG-Ìä3Lç™Ù?X°TY³Ä!?ŠÞØfo0† ös„“›µtÌã—=¸´.Á†¢H¦îê܃÷ì§§ü±ócªwÅ3S‹7 z¨ážy™®±ì†GŸûòÐŒu¿{jÍmãVÁB诜ñø#³6X$2Y´Zehj‰™È3K®Ù †‰…H³$¦¢yδVìtÝœß<Ðvè{웉ÖolË»V•R 3 cêŒÎºK@8‹à1hРP4ú“›¥·NmÈyë/ Œé·× 9FrÿÅ·ß9úø”øÕøi‹Á!~ö%HþÆÅÆ'aÛý×@%l¯õ¦?áT ”’£x ôþ1n˜¤¾ ¥¿J/LÂNpE¿½ötJ°Ah‰Aâ;ýÄŸFhéÁ1œOK@—-a{¾ú/‡^;t¸-½gKØD 1êF‚›%ü‹á7® nÉÒ½£=Œ‰ÜÒ½LcÀ8KÀ˜0P¨tÉ•CÁ*ÁëR€1ýâ|J‰ cbW `˜îÆ´ÿçÑ:ô¨ã±7KHˆgôR<®ÏǘFLŽã§-øwÂܵ¤—†Ÿt ý-t¦± ÷K'Ÿz¼1ýãþŸûÇöH¦bL¿›ÿO±³Øy÷Ò FLÒMì?üg{¹õ>B­þp ͱôèÙë9wÎõ@ž;kYÅ£õ·>}þ] Œa ¹qY®ï³ïï?ü¨õ?9]Q t]aL]/‚bf Ôa0Š”ÖLÚ²¹×&:m†½ ˆéé¯ËüeL;ì…õäª\KgÿúÆÏü_îìûM¼2tJ 8ûÂýü—çYÿÓ}ï³£hïýKî]dï}NŸð½ÏuÀ‡_øÔð©/Õ¾÷½úæ¹`têÛ5Ã=àãÿù?ÿßbìž®‰_Û%Và¡SŠÙ6+×R@ H) Z©€0¦VªYÀktÐA÷ŒœXí„W–ºƒ>†éÁ@ÏÓó:\•œuÛüh@1Ló3œœqÉfˆ9î;ñ'¿:ç³ÿõO?ûê„w]Ù—‚-vü*}†¤Ý ŠÞÓdËH¼µ£!G5‚+Hÿê¯÷Þü¯ÿµë® ô„gýåÉßûŽ;±h z¨átá3yÑ«p3†Œiäôuæi «£yËÓçݹ€kÎ1A#‹VglPÍDf–hKÖ–fI›ºõ±•°e2øå?~ôç¾Ì•e) |„1©"”B &À-“û(u0&¸r2LÑ“ § f%sõm®W¤Ð6¾>’r€aItž„>  19ýW#aÌ3nê"øRâä‚ÄTâÄ'ÓAß<ì²kïà¤ÔÜe/!šüô*pKžk%Œ×x”Òð±3ŽÐÒõ· %ÉS°J§žuA%BKt¼äxZò÷œyâÄ´tÂɧž–üÙ¯ŸŸqÑ}£§1NÜôEÈ-ZõÄ3GnéW¾7&¿ÿêM’!Uz –€+Áy2q%DŽûþN¥'€›î‹tæC¾ÿÃSá…#:àJw>4 (Ò0ÿ/Ñ¥cpÊO?ßè¥ ·äaL·˜„Î1Ó÷N:èÒ—:ôÐ%œŽi`àx Óéç^ñÝL˜ŸCj!Æ4rÌS÷ÆÄºêÒK6‘D;¾Ø‹vLwÖ³—mC·þ~rýœÛ_…2B¡ “z׫Ãci‡µçXú€¿NÌÓ½w ÃøëÝyðžrJÔ³[ÏS]‹j8VGûæà‡iéO¯Ÿ[, ^´úéëàÂø §x¿à©;'®®iÜdÑjEhŽ–˜‰h–äôJÿ™Öu<œÂêJ€héÓC™hÁ*L‰dêñ®‘¿À c*páõzÖGŒ¸pTAåBqåê{c÷'N¸6úúú -'1&†ƒ‰M¿¹ê¶#Ž>>ô•ùLŠÝ€_%ƒ“°ÁXoœã“tä1'â_lе’Í}޲@Òw¾{"œ-q}GpKˆ<-áïAÿr(þâ†Ã¿ØŸ„ ðI€–p:âÄax¦YK62$ÜGŸ\ {f.Þˆ¿Jø _MœµÜ’yZŸ„íÛî÷ë+‡‚[¿‡}†d‡}‚-î¯|ý8[·¤ç|ŒÉ‡ rKæu T¸%ü‹á{aãàr aã|ziò°‘“±ñèÔå ”@/aÞÄ€qæxišöû‚ÇÑU)Ò½ÍÞ놽„Èq؆Ë% Kð½4nÎŒ ±têyØøÝ˜¹­Å˜ÐCŠÂLs^n×<ªë¥WÝV©uÕÊcfÆ”aÂܹ7ØX± f1/¸kÆ?¾vvM£`,]uâ2L|@‘L…nâ”ù„1©Z4«I¦Qãç…l/q¶ÃX”ù?å¶Ã0àín‡Cë2k™2LKWof#¼eçûú³?5[f9>ThÅúïþa“eqå@2Ýú»Ñéï}/¨\å½Wÿcs7žyÛü#.| ï}Ì\=j¹oœÚVµ0Æ2L¾qŠI&ªך¶eíÂOcj›¸º°R@ IaLE*­öä•$ÓÄY˃>M)C‰!¡ŠÅs†ºò5‡Ù LtÂayƒtôز¶ÆOm'Üc˜>|Õ†×Ùßö†}í)ÎÐUÑéu½«V&; $ÓÏ~q^Êø‹šjÆ_ó6ò@¹_p·WîN]ëzᢣ×.#ÊÝ;rœ¿ÞÝýaG^7)»ÏÜ_S½+áäì±k-ZOqÑÃ"y z ”i€&,ZÆ4í%0Lhèоará_¯daE«?õ¬%f"£lñ†ÂêJX)š¾îÉg_Añ!L¦€²•™¨?E¥s¥@!ÆTˆbR&ãضmbÁ` ¹bÂáõ1&z 0.Tt…+\HàÉÅÊ ÔÈá3Þ(ˆñIô¢4¾–½ÌE$“~{Í“æ­â¿‹‚äÅ€Cöàãð·4fÒt"äÑI 8BžÝ·‰ØóÀ£ÓG?µ€Qá ]Ì™>´Vé‘'ŸÅý-ÑÓ÷ÐÕ-½Ý"H-!ÁÙ’EˆûÝ#Ó¦-ÜgK=ñÌU·<øÐÄgèr ÐÒÝOEÂÆ”gד[bº{ÔTocù¶ãç3`ܤgÖ!Ñëü-Ýx÷XN¤ùi+Ð¥Ç=ýÄÓ/ÑåÒãžÆßÑS–#fÜýãžÆà‰.Y¢Ë%†óF€~º÷KŒr냓È*aÃÅ•ðoF?L< °9üú¦OŸüôðÆdNlÌßp稕Ÿà|dû0&üÜXcmŒaëÆãO¿ 7¡^š±î©¯˜³Ð‰Ï¼|ÍÃÏa,M†Éuúꎥ£ “H¦¢7qÊŒ˜T-ú¡í>=>;¶Æùa6Â~;ìÆ’«¶Ã.SaIC‘Lý(«¼ŸêÚ§B“e= ™îTßz“Õ70sæéýÑÙñÞ=kCˆ]¦³w 'ç.°s{5"™ò^{Zž?aL-—T”R@ Hb* Œ©˜åÖâ\$ÓÌe5ü¾#|ó¼‹N¸MlÄ´uÓ—l™±½ôì “H¦—_Êå cŠLvH¦ŸþâÜ èÿ[ï&¯« Á0þ@?L罄ñ×øù›jã4m ¦Š£š(ÃÄÒÉÔ¹:Pâ;Ƙì¡ëZ´0»clܸ*ÓCcæläjøU£–ß?emÀ0É¢ÕêêÔ3Ì’n¼Kx d@@âÝO¾è…épÜÅEQK™‰Z]ªºžèž˜º§½îÜfûŸè¥2aL-ÉA.(äß®º¼Ql·À˜ˆeL!2‰|R|8ɇ@ñ©‚(«„~¤%oÅ¿è'”Ðˬ†‡óq%$°JæiÉ %#–ÜJ¸ N¹%ó·„¾ŽË-“O,¹‰Ü’› ]bÀ¸ T\eÃq¹äù^Š¢Kt¼ä¢K·´xóy¿½¾—ài‰È1¦,þ–ÒicÚ´ý=Ôç5»îÌÔVŒ wñ*í•·Y²´”©e¯tRéñµ–a ¥“&‘Lyh©”‡V* Œ©•jöâµh÷ñø,FtuaÏ«¼·w•Ç  “z•oÏJl¯À/NÔXË0‰d*k%£}* `²§&ÉtËÝ£Ý÷>;‡Vßê¾÷ý¾VepņždœŠúdÚ¹ºïÃÝ^?'ôÁþ²–NÏ=—0¦ž+r=°R@ Ä+ ŒI5ƒ d?cidÐØcCƒ>ØNi& úhät„ü0¹k à“é½×·Æö±Ñí«¼SÞd€É.å‘L§Ÿ›ÅîJ†‰¥OÛx8’ ã…+‰aÊB2¡V¼ýÊZÈ+î^;S2ÀdbТ5òñÙÍX´bñ—Š…A­þ׸™‰úÿ°º‚mW@SÛ%Ö º£@ÏaL¿¾òÖÒÈ¥Ž^|ßcJâ²2I!V)Qò¢ÕÆ€J ¬’Å[ªàJœ4¾hÃÙ]e¸üñÀ¯Ò¯.º*Ä-yÄ’7ÖªK™ ¥Ê¨¬!n)Œ.UCÅ1fÜ–tt©âxÉC—èx‰|,vîÆ$!ŠœûoÓ·”är);~Ôª#Û„1 Ä óÖýà6£o[þ¸oþb'ý3á/¶±1âùø Ûø[÷÷’éâ+n±j;6wÖIs™Yü0‰aª[: H c*Riå:¯´û<0ff€×LfЬkÎÎÂ0-X½L‰+Þx­àeÁ7ß,xÅðm‚6ð/7øZÁ)¹T™KU€&ªî|8ã{¿fúÄa—³3Lô·DoLä™°_zÊ«H؉ ¬ç~FMØiGªH £€0¦Â•2*¤€íU@S{õ-àÕI2Ú;è3?%u}u¦™£¹ûûûÉ×ÐÆjö¨‘ »ÜØ@ÛzÚôØÄc¬‹^@seL?>mpdüU ?'m ÉÆè'ÃÄ¡k‚7דpDݯY®kUn2X´ÆÎ¬‰íPYÝ‹¬[¶|èâ¡\¶'‹VJ•iÖLÔäR71L¹ùù*#R ›˜²é¤£ §@ÏaLõ~TÙƒo=긔¢ÁÝè6©Žó¤«äÏ}¦§Z¿Jɬ’ã])W Âu»á’ˆ%o)I¶‚ƒaÂÄXMÊ-1„Yo´Tá–ª.—ZÅ!õó:m˜¬ó.8æ’ßûÃ{h¬kŽ©e„œÛöÞ6£—pN©Û|€dºèò[ `òœ0ùQäj‚²/³¥`ÍÄ’ÃT·t@ÁÆT°Ëuvi÷¹ïÑ®'¼ ¦AÓG $õâ¨âmè8mnŽa¢(öÁ%×?_(À›ø6Á{' ›k¹{>s4Q]?lTúV}ï‡ë[v†‰b›eœ$ö˜&L–€sZvïÚзöÍÆ16Å‚=ø ëƒ{¾Ð "€0¦‚”²)¤€íV@S».âõI2™²$¥îÙN}c)ü0M‹ úê2L°¼mÙù>&t§Ñ¯6§§èr£û=¤Xð/W § TÝoö·?ÜýžÂ=·©jy$Ó©ƒ+v×°ó{[;J;¹Wú¾õÛ‹0Ð † Å‚¶BçcÒ?Gd6@C5@=ш¬M5¡”—Í›E +ñÌl[ÖìM³eѪ[ñ¢f¢êôo–Œ§l_ê&†©nYè);„1å®H”¡Ö(ÐsÓEWܦÍ'ðí¡G~?倘¯êI!\)à“<ÚÝÒvt8Ü4xŠ›*aàâA%‚,•žJƒ¸¸¥*±” Z †èª¹)[Úl¡âúɵéô6aLX:€Î7~£èŽs+ Ü®9I&ÆIhlg ’éÂËnöªG À™;W,¹Ö´“ºJ‘ÆTäÒËaÞi÷¹÷ÑuÛá¨9»? “½D\Cy`2.„_+„hs( ²Ô4Q]wǨ&ê[£ “YƱùL–p©7Íè4ÓcöcrÿbÆÛ8’xþ6ôt:¸k cêšôº±R@ äKaLù*Üä†$Ó£“W;á5ÓÃÃä›FÝ…+¦ßø‘Åc_šnx@¥Øò-t•JWLØfÇISû* H¦=å x>¼pÔ_ý[Fз»¶Šaâ‹°× ôY1lD† ×#—Fdí« ¥¼r®,Z¶RÃ~»–,ZYj]ÌDb˜²„Ž‘¹S@SîŠDj½‡1UœÙÄ:C‚«›CŽü~VWIŒìVßdRKâž0œÄ=¢”F)¥‚JˆH<8Ç»R=\)>6\Lx8¢Ku-q—ÿÔ&Œ‰oüF]ç¨`•ø«ÅNNHf„46è±)Ë$Ó—Ý\õÀDçþ@:i)˜bÉeVÇ”SaLå,×n>í>¿=Ãâàm[i„mQf«ü0áiñšÀº4l¸†×É‘&FšCA;a·rWŸ¢+@Õµ·r=/†ßû‘é“&&Eû8£WÐÍè¶äÆtìä„ ‘&lã[$l`ApÑÕî•ü cê•’ÖsJ) ¤@„1©Š$)@’é‘I‹ëúh¢ºzèȘ÷¾_ß (oŽaB6±Ì—ñ ðÁz_F‹ƒMôæTEŽ‘æød˜$:jÒ§ c*F9)—R@ H)ÐvVì¸é®¾½Þýæ¶ßI7(¦$™zb¡3è‹Y=Ø(Ã1ÐÁ6G§ìNù)ãÇ‘Jq{Úô½D¯“jÝ&Kª'ùŽ”’})ÑõÎoüÌñ«”Â*ù˜K°jÄ[»oiQǽ 4RÓÙ.4Æ„¶$ÓàKo¤÷,׃¦|7¼Ê]ÆÔA±{ðV´û {hªµÃîûH SV‰¶>2MTCn[ßÄ0µUüR]\S©ŠS#¤€Í+ Œ©yízéL’L#&.¹ááЯ¡Xr½$[IžÕ#™~zv¬ÝU SIʸ‡C­~KÌDb˜JPôR`0&U‚’*Ћ“‹…¶1}ûˆcSHó”ê6©–äFKã“,p˜7‚rS%œ*ù\‹X¥TB«èI¦sþíF‹&C3ŠbÉ•´ÅÖc5®€0¦Æ5Ó )@»Ïí#§„Úa1L ɨƒ3*@Õ·ŒÕ71LÔaž˜T¤€R@ ø cREȨI¦',­¢ÔQÀB’餟þ v·ôÅ0ºL•yS@­T†~š‰Ä0• è¤€§€0&Õƒ’*Ðs‚pÑ×Q(ù.޶âÛoq,·[‘ŸI n“B¾”ÂpRmÜ·ZD)B)XêU§J=ë‰íH¦³}£‰ †©¤Íµ«)„15%›NjHÀî3bеÃb˜P7¤MT˜2±ú&†©!u°0&Õ) ¤€T@“jBvH2¡ãmp1LÙÕ+ú‘ ™Nüɯ¬èÅ0½@•WY´JPš6‰a*Aéë¤@ €0&U…’*Ðs"p±Øâ"²áÛo~ll˜¶†vÆÓHæ<Éñœ2‰©ë-.â›Ï' QjšUJ9±Þ˜Ø4É$†©¤mµ«Y„15«œÎkH×î#†©!étp ¸&*1LMØë§ÈS¯×=¿R@  cRUhH—dÃÔt%8ØH&1L%(M=BHY´JP%š0‰a*A¹ë¤@UaLª %U ç0¦s.½1…1·À˜ªÄñF¹µ’Ë$Õ†u« ñ&2©dRC×, Æ„ $ÓÏué~yâÔùë¶¼›’ÔI-i{®ÇŠS@“êE§ðì>_ßx|áKKWoNi„¬Þ¹û÷u*_ºO9 ‰êç_ùùœ³`Uú{_õ­œ• é§ÆÔ´t:Q H) Ê¥€0¦r•g'ž†$:áß<øðU^Oé„oÙùþï?Ô ¯…Ò±{€d:öG§øÕoß;r\úøkÇ›t,Wº‘h‰$™<‹Ö_–E«%’vþ" ™‰4=ÔùÒ¥@{ÆÔ^}uõ®)Ð[Ó¥—^º—>R AþÓú‹©súÜê¦íïuí'›zãŸýð1Lù,åªk cêšô½xã7fÞ{ì?ü—¥ÓžÃÔ‹ÅßñgÞ´sÎü/#§Ý,†©ãÚü†Â˜ ^€Ê¾R@ ´JaL­R²§®’験ŽÃÔS…nûëß\.†©7‹¾ž$Ó±Çý@ S¡Ëzç;›²˜‰Ä0º”•y)¯€0&ÕŒ’*Ð[S´Ó'~ô­ˆU ·ÓžË÷ß1‚ü0•´¹Öc5¥€0¦¦dÓIM*ðÌýúùܲdNR;,?LM «ÓâØúîì;—ü‡ùF¤¼÷å‡Iu'FaLªR@ H) |ˆ1¡O%=¤@vví^þàò½_yí­¤N¸ü0e³ˆG¾ñÎïSÆ_òÃTÄ2UžM?ýùÏhÁdÑ*n•x÷›êš‰Ä0·|•s)¦€0&Õ’* Œ)-ö– )P$Œiùã{ð®Éôæ±ÙV'µ¤Í¸+UaLª Tàíí{ÖÎþÓ¿¿k÷ÃÔÉ¢è…{aÊ o«wÞ¿íx;£¦^¨Í<£0¦fTÓ9R@ H)PB„1•°PÛÿHS×…Nøòm·ÄúÄ0µ¿º‡$’I S÷ËF9è·I$“,Zý–¶Æ”n&ÒôP'ŠA÷]Q@SWd×MÛ¯€0&aLR arêéòý=Œ iùãQ’IÔö7§ºC.Æ”Ëb)z¦VºìÞ!ѧØÚ7ûíWÖbÔî#‹OÑ =‡ù‡}ªoÛov½¿õ-J2‰aÊa‘å%K˜òRʇR@ tYaL].€Þ®˜0CŒ4âùýþÃ÷C$“¦i“YŽ’Lb˜š”R§åOY´òW&Ysô‡ÞJ1iz(«Ž:N QaLE,5å9ƒ˜FXä H äc¢+&&ðL{ö¸$“:©CRR„1•´`»øX˜æ^6襧FDó0aЀ«û¸ßµûˆaêby•æÖïýá½”g ‘Lb˜JSîmyaLm‘U•R@ Hâ) Œ©xeÖíÓÓŠ7ýñ£j&1LÝ.œNßß%™Ä0uZ}Ý¯Í È¢Õf;qù™HÓC]÷]T@SÅ×­Û©€0&aLR aòˆ1™+¦ŠC&´$™ÔImgªkç^aL¹/¢beΖÀ*Ãhɸ%<È#÷ããp?í>Ï®zLIèÈb=µrÛu&¬™0h ôl˜‰J S×Ë+ïÆ”÷Rþ¤€R C cêÐe¹¹b2‡Lýé’Lb˜ÊRÈ=I&1L©¦£ ¢€kÑ*H–{.›î°í½m)mf"Mõ\åÐ÷ ˜z°Ð{ã‘{cÂ+CŽ”´uçîo~Œ¾-“¯½ùÁö7v§?Qîz~®+&Ç!ºªšËì–\O™¬€0&ÕŽ–*€pr`•àéÃÝïgZpó`lcc÷Îm$œp·©ƒb?ŽD;¼c=”ôá„-ÍŽ.Ö ÀÓàiƒ‡Ìóâ®ÝåE-ìÛæ9ýâ6>f·B}{öå>~«HT@“*‡R@ H_aLª )àºb2‡L¸H¦ßøQC—ÒÁ¥Qàß?øcižE"B ÀÂðþïÕ¸å´^Àò³ß­ûÑ.„¿° ᯙ‰Ìd„B|~Ûœ<åô!•-) ²+ Œ)»V:²P ô:ÆT¨ÂRf¥@‚!WLŽC&I&z]aL½^ZüüÆ*aãå¹xuÆ’ƒ‹&€Jøô]4yíªikßl;²ÅÒåz@Ù›fÃ8’ <Û |d <3a§ùgÂNؤ`®Âh'ìÇÁ= Œ±Y„15«œÎ“R@ H’) Œ©dÚÖÇ ¹br2µõ¾º¸R@ H¨0ûÀ4tñPX‡`&B‚9Èü3ÁF„mœ’û•Ä”R œ c*g¹ê©öcR%W êŠÉqÈTðgSö¥@¿ÆÔo uWc•*Obb,9xZb°9àM›°¨¼4áÛБ’T 4ª0&ž‚ :[‚ æ*Û‰ TDX¯¸‡æ*}¤@¼˜T3¤€R@ ø cREÈ®@Ô“ë)ûut¤R@ Hþ+£vƒg²Enf;‚½ß’pâ½F8Ò8IN)][E‡ ³@Ñ.B'LpsWày`]{Ê~ÙC cê¡ÂÖ£J) ¤@š˜T?2*ëŠI™2ª§Ã¤€R å ˜QŒ%g¶#lsð&ºôF¢÷î–gC”R / cÊKI(-V@Þ˜Z,¨.':ªÀ‡ì¥Á´äá=xWÝÿ£êží/v43º™È¡˜rX(EÎÉ$<@0IôÉDP‰>™W û1á+ìÁ·ØF\9lc*ráw-ïXEÇ q¶ØÛ*1Ša&fHÓ„5AÄîeZ7γ˜ò\:Ê›R@ tPaL»Ø·z÷›¶¾;›iö¦`Z÷æÃ¶ç½UìÇSR h ¸N»™÷ɦ!ÐKf2ÞE{PåW Hl cʦ“Ž*œ˜ WdʰHP`×&cšx©’R ª€0&Õ†–*°ìÞ`é`&lƒO2LØæ­°Á¯ø/œ0á_$L-Í‹.Ö+ ÀEŒ (z`‡Ñåà;ñ{€1Á,…õvØÆÔ+•£¹çÆÔœn:K H) J§€0¦Òi'¨oë¥À˜6uâfº‡R@ H8hr—´Ñv„Øà:7‹è´ÉöHK) J«€0¦Òm¯?˜0¦^¯zþò( Œ©‹F¹’mW@SÛ%Ö º£€0¦îè®»JÖ+ Œ©õšêŠÅW@Sñ˰HO Œ©H¥Uø¼n}wö]}{aú­ðO¢è°˜:,¸n'¤€yU`Ó[£7…>U^3¨|åQaLy,åI H) öìy÷›d&RE=ª€0¦-øò?¶0¦ò—±ž°WÆÔ+%­çlDaL¨¥cû«€0¦þ*¨óP@SbéPWaLªR@ H) |Ø›ƤêИ’KK) ¤@ÇÆÔ1©u#);„1å®H”¡Ö( Œ©5:ê*R û cê~(ùS@SþʤÌ9ÆTæÒÍݳ cÊ]‘%C˜ŠRRʧR@ ´YaLm¸œ—ÆTÎrÕSI) Н€0¦â—¡ž@ 4«€0¦f•Óy9W@SÎ HÙ“™Æ”Y*ØC cê¡ÂÎÁ£ cÊA!ôN„1õNY·øI…1µXP]N H) Šª€0¦¢–\Wó-Œ©«òëæR@ H)¨€0&U)л cêݲ/ù“ c*yëñzHaL=TØzÔÌ cÊ,•l˜Z ¢.‘UaLY•Òq!„1©JH) ¤€ðƤŠÐ„˜šM§H) ¤@ÆÔ‘u )S„1å´`”­þ* Œ©¿ ê|)>ü`ˆ ÀLúH)` cRe褘:©vÏßKSÏWfÆÔ¬r:O H) J¦€0¦’hgGSgtÖ]¤€R Q„15ª˜Ž—åQ@SyÊROR£€0&U)P0^zjIJ{‡|¸û½P¾wïÜöòÜ {eW ´[aLíVX×wƤúÐA„1uPìrÝJS¹ÊSO#¤€M+ÀÞÔ«oOnú :±ÆÔƒ…®G–R@ BaL…(&eR ´EaLm‘Uí¾˜º_ÊÈ®ÀÎÕ} É=lRöKéH)Ð cê‰bÎÍC cÊMQôBF„1õB)·å…1µEV]T H) Ч€zSÅ+³äXS AYR@ H„1©ZHÞU@Sï–}ÉŸ\SÉ XW&àiÁ̓‘èŠéíWÖ‚j‚&>#ð&üÝ=ØÏ¯ô‘=§€0¦ž+ò®>°0¦®Êßk7×Ä[¯•xËžWSˤԅ¤€R Ø ¨7UìòëRî…1uIxÝV H) ê( ŒIUD ô®˜z·ìKþä˜J^Àz¼2)°µoö#÷Æ„¹— B‚û%ÐKŒ%‡¯ð{¸ÿâ0ìÁ„Ÿ°Q&5ô,R “˜2ɤƒZ¤€0¦ ©ËdQ@oYTÒ11 cRµR@ H)à+ Þ”*B cjB4"¤€P@SDÖ-¤@NƔӂQ¶ú«€0¦þ*¨ó¥@' «oL«Få}K>™H)á/¿ÄäFšÞ$ŸL,,Ý+ cÊE1ôL&„1õLQçáA5ñ–‡R(d„1²Ø”i) ¤€h½êMµ^Ó¸¢0¦(d=¢R  c*d±)ÓR % cj‰ŒºHþÆ”¿2Qޤ@‚Æ*áû©ƒ2Ñëý3a?"Ía§ë¢ Û<Ò¢ÎI`)ÐC cê¡ÂÎÁ£ cÊA!”; »?ÜþÄÚƒ˜Æ®Þÿ®¾½F¯úÛóêÛ“Ëýøzºæ¸ç¸=7¤ÓÿbϹ«þ;ú¬æ/«3¥€R@ YaLE.½®å]Sפץ€R UaLª R wÆÔ»e_ò'ÆTòÖã•Ic•À$™7&ÀIÀ›àu {È3á‘~ø ×MÁN)“&z)PGaLª"T@S'ÕîÕ{M]è¥hñüÇ>úÓ½ªŠž»ž3nÚ‹FlZþx½“õ½R@ Hr* Œ©œåÚæ§ÆÔfuy) ¤€hRaLM §Ó¤@ ÆT‚BÔ#Ä) ŒIõB F²JÈ.1&Dˆ[pó`âJô´ôÒS#¸ñòÜ ÜMŒ%‡¿8¸0ªŒJV) Œ©UJê:YÆ”E%Ó?ví^‹1­ØqSÿ.¬³K­À‡ìü±ŒéòýKýØz8) ¤€i cRýhBaLMˆ¦S¤€R  cê€Èº…È©˜rZ0ÊVÆÔ_u¾è˜ ”̵&$úaBøc_q€'ìÁþŽåS7’9R@SŽ £²"Œ© 9uÈ$WLy(—¼ç!Ö!“\1彨”?) ¤€h£˜Ú(ny/-Œ©¼e«'“R@ [aLÅ.?å^ ôGaLýQOçæXaL9.eM H) ú©€0¦~ ¨ÓR@SCréàfˆ:d’+¦fµì¥ó¢™äŠ©—Ê_Ï*¤€Q„1©V4¡€0¦&DÓ)R@ H)Є1u@dÝB äTaL9-e«¿ cꯂ:_ H) ò«€0¦ü–Ms&Œ©Œ¥šÏgr2ÉS>Ë(¹ 9d’+¦<’ò$¤€S@Sç´.Ñ„1•¨0õ(R@ HR) Œ©TÅ©‡‘ ) Œ©!¹tpqÆTœ²RN¥€R Q„15ª˜Žï˜ú£žÎmD×!“\15¢\oë:d’+¦Þ® zz) ¤€€˜T šP@S¢é) ¤€è€˜: ²n!rª€0¦œŒ²Õ_„1õWA/ò¢À®M{ð®šxi^ò£|H<( Œ)¥Ð;yÆÔ;eƒ'¥C&¹bÊAQ* æI®˜ UnʬR@ ´CaLíPµôׯTú"ÖJ)  ª€0¦‚œ²-Z €0¦ˆ¨KäQaLy,åI 4£€0¦fTÓ9eW@SÙK8_Ï'Œ)_åQòÜÐ!“\1•¼˜[þxtÈ$WL-V”R@ H* Œ©€…Öý, cê~(R@ H)§€0&Õ )л cêݲ/ù“÷ÆôÖ[oÍ®÷yâ‰'ê¢ïK¥@–ÿàƒ ÐìÚ´ý$yc*@A)‹U@SGåîù› cêù*Ða&ôýð£?¡‹Òa]t»TÞå‹•HR@ tWûï¿ÿÒÔÏ™gž™~€¾m«_|ñ9眓~‹Ç¼»µHw￘ú¯a^ASºY H)P„1¢˜”I)Є1µEV]´û ôÆtÊ)§ü?ûý¿_üÒWÜtà—¾bi¿ÿ÷ÿ÷Wûë¿ôåÄôÅ/øÅ/¡ÁtÀ¿¤¿|@bpÀAúüâÓ|>.}î 2¥|­¦/}ö€úé3|ÉKŸÏš>ýù/ŤÏ}éÓAúâ§?WMŸúÜ3¥Ï~ñS~Ú¿‘ôÏŸý¢ŸüçϤ¥ÿôÿÇ?~ò³8擱éÓþÕ_ï}ÕUWuÿÇZ/Ë—,ú»ÿ¾ß¥?ÿ~½õ½è%„1õRiwÿY…1u¿ z(“'Oþ›ï‹‰ðzf=j¿À¢ôÿ:ê¨b0úý~^]@ äSM›6ý·ÿóÿ<缋™ÎvÓ¹Ÿ}îEH8`ÐÏNÿÕ¹UÓà‹~5ø¢³"éÌÁžyNM:㜠ƒtö…gTÒ/Ͼ°’.øå¯¼ô‹¸túYÔ¦óO;ËOgVÓ©gž_MgœêçŸRMçrF~þËóBég¿<ÏK¿°tîOá¤ÓÏýééçþ$. :í\? ¶ôãÓ{éÔjú×SWÓ)ƒÿõ”sNަŸŸó£HúáÏÏùáÏÏþáϪé?;û‹}û¿ÿÄÆ~꥓ÂéW'ýäW{íÕ[ö´|þšú™+aLý°7OÆÔ›å®§–R@ ä_aLù/#åP ´KaLíRV×í²½ev9ùä“oºí®­»ÞÒÎ÷·î|‹—v3ÝxÛ]ÇwÒæ×w»éÕ×w{é5¤ÅM;þýe'mÚþž¥ÛßóÒ6/mÒ»¶¾»ÞIë¶¼ké¥-ïxi³—ÖZzõ5Az{Í«o¿øJ5­~åm/½ì¥^~+H›ÞZ夕ßZ¹ñM¦H‚ôü†7½´é眴|Ý––­{cÙK»˜–2­ÝÕWM;—¬©¦ÅkvzéE/-òÒë^ZýúB'-xáu?½†ô,Òª =³ê5/­ôÒü•;‚´bÇÓ•4oÅŽyÏ#mGšké¹ísœ4{ù6K³–o›µ,H3—móÒÒ­H3,õm^M[¦õmù«¿ÞgÄÄÓ–l™Ê´ØKS¼´ÙK‹6Ÿø“_af—©õn¿|ùrjó–n„¥8ÿ¹­÷4ú^ ´NaL­ÓRWª¯€0¦úéˆÖ(†éëßð8ùdêÕ‘é¹=†é Ä• Ö]¼U$S&ñth½À˜@)ÕØ%<ßÏžûgã–pÀ3}/Dm›BôRªè°ñÁ]:õê;®ÙÁ|?§{}6—Ïa†©ÖÈuÅd Se}Ôξƒç¶¹bª.‚JrÅ´¬fá7“ïŠ)ðÆäºm^ä­wÆÔúßFǯ¸ãßÜշך]÷wüκaÆTàÂSÖ¥€¥V@S©‹W'RƤ RRzcºþ–;c(¥J¨8|û½ïŸä®q´í·L®Ûv]B¹°ï¥½´Î !—â©™@r›H.ˆ%ç[K®_~˜úÁ0erÅä"W.Q®ÖS ôÕüÃcNŒ)N¦ÉœcLd˜žyn–Àr:b„ÿCÔ¿Ÿž.’©¤Í¶«!„15$—ú) N¯§¦%/n¾÷E2Õ¯w¿¦'çZµ!õŽîâ-÷È'SïV =y Æ»zÊPá€ùK^ 9ÂE—B†ˆ¬!ìã}?ǯw#×',—ê7Äkl89ß»sBxz‹(uÅdáä<‚늩֑s4}’+&cºÑ *—QކaL]üµêÖšík•’=uaL=UÜzX) ¤@PǦ@…¥¬J+ Œ©Å‚êryQ 1¦XJ‰;1óýÝ q¶@K•ÅŽà–ê¢KÙé¥Ê:Èw€.…è%,‹´‘pÂô‚9a ™€ie,ÀT× Óº]˜Ò`Ь•ô쌮©Ó‹‘ÒcÉå€aJ'G£dÆDÓ$1¦³Ï½xËÎ÷-íxóƒ?ýùÏ]ÿ“azö¹M+¼Âõ0&xì7Œ ¥ó“ÓϽð¢_w=ŸÊ€è¦˜º©~ïÝ[Sï•y'Ÿ Ó7¾uXß‹Ûý÷¾ïS§ö½ØÀã†Ýõ»¦³Ô×××ô¹ž¸víÚÐ)MÜ=z‘F³Ñòãßó?¸lRÞ}pÈÒÏÇ$Ã4æÉ¹^µ‰Pïè.Þ|÷#‡ñÝï¿ßœÈ¹­èà~ú© ³Ê*×’KEŸ½‰ËòÛ*£.žˆ1EíÞÒ©Š³¥½÷Ù÷éÅ/Б}UßÏk<ßÏõ¦Z—϶VÊ55TbÉÅG«Æ’sÖGµ’aš¿¢•ÞI¿i.S\89oùÓ² ySm zºbB ŒépcŠqÛ\1cr­Ø~w÷‡ù©fÊI4Û—E%îµn½N¼Py¤ŒR@ H\) ŽM®ŠC™‘U@SGåÖÍ:§@ÏaL×Ý|g,¥Dãàµ7{SÈJ!–K¶¾ P)”\»¡¿ýÎKɾ—êÓK`˜ê†ëÀÄ9°T€©f­d0U¦E/ú+&ýE“5ë&ƒ@rÍÄ’k•¦, ScJpÅDŒé—g_*Ù?~ÔeŒ‰ Ó‚ç_ÆZØÐÚzg€ÌP( W¿>è´sÏ»à’ε(º“È›˜òV"åÎ0¦r—oWŸŽ ÓÒ5;Òßû‡Õ$Éêb¿ýö1bD Ÿr„ I0Ç€BÄîÞЭq:.ÒÐ)éoÛ¶­ÿ?Äÿ¤ä-ûƒC:ÅSF†iN#áäÀ0Áss ÆTk+°õNÀ˜BV¬wj®Jè¬n) Ù¾n)_èûÊS¡‹O™—R@ ”XulJ\¸z4)PGaLª"%U ç0¦koº“XRœô¾ýî÷Oô³¿¤­1â ]Š@K©ÜÒæwÀ-…Ð¥xßKè¥UQz)B.ÕS<Àäǘ¨ÃSkœ0­z확¯Í_¹ÃRøøÈ2Ê9XR™!–\F† k+=oL ¢Ü/möRey¥ycÊÆd S0)·¶žÓ‚^ûñiƒE2•´×ceP@S‘tHËÆÔ2)u¡ŒaªÀ(áH²€QH“ã½hS$ø 3­ƒôÄ–evš'©*´c‘á–Ô¼–`Là` «ŠÊ•%Ÿa†©Ò]dD9—zGµ¹ñ·› ™CÔœF´ôÌÇnÑrبµÙÎR"IulèСfágتz˜%K:¦[ cªÄƒƒñ!šÞÅs®Š_:UË-Á(á.Z ³ƒ¥]J£—V›¿ç—ß‚‘ÁRš¦Z; –2:a"FÉdË¢ðc2€ ­Sç¦é}žÏfbLæŠÉlÆ01¨œ0¦nýˆZu_ÍöµJÉžºŽ0¦ž*n=¬R @ ¨cS ÂRV¥@‹ÆÔbAu¹¼(ÐsÓ57 ‹ºP²=øö»Çžv°±VlUaOK/m~)d7ŒrK  Kµ¾ÜiR Ûãé%o~ËMaÛbrÙ&ß “YƒcÛœ0=·Nà-Í 9„‡Oøe[k¦¥Oxz†ÇªJ’c¢Q’SÔCoL`˜>ïûaBM»dpÖÖ£h`ÿ…Ù÷™U¯ýøT‘Lyis•N+ Œ©ÓŠ÷öý„1õvù·éé†)òÞ÷aó©ã½÷}XüÐ#¿ßht9Løkþ“H5Ñ!¾°‚m×3·±“´ ¶bغwâí\søÄ+ã`ÛcLIè²®ªîW Bp ogô•À=ÀAyÞ‚“žÿ?ªP¶é‰ù™={6.Å=Ì1”7¦V=82Öh20Lè.>öÔ<Œè@%6!{òì.Þ0lT£$žR@[€8T¦n=±zEÅPŽtAD%Y‘¢ŽÁb1&«rv<2–³*A6þì׳ªN–1œB‹BµGòIæ)TëìÑà¨,”O«ç8ÝÄlS“¢ËæAbL)v |…æ,\·nªZ › ê­›rÖ¿•°~càÉk=*Ö† „\€É R_Ï “Ï0ÕúuŽ:aò^mLÎj¨š¥PÏ'Æ’kÔ¦ŒÉYïä2L˜òðSê8Û·|ûUý¿”®Ð; cê²Ö“J) Š¥€0¦b•—r+Z©€0¦Vª©kåHÞØnk äÎknvô±'ÚÁ¢ÆÚ¨p4†q¥Š§¥,ÐÒ‹p¶ÄŒÃ†cCLD—jݹ'ÐK˜¢H¢—RÜ/¥x`Bx2/EÖJö`Z¹£íN˜j¦-.Ãd«*á„ ÓƒÆäùa Ù%sè‰ ÓÂç_ö6NJE\2T"ÊÙt&œíÿkf’‰ó‚n+•´Zsu9jϺLJÕÍ‚D«+Q‹ÆÔbAu¹T„1©‚´Zc˜êÀ(Œ˜ë…·Kt±i„d¢OäݼÂ`EÅÂW€?Ð`¬+¼Èð¾3n{ÙË ~Áƒy$=èð Ø07Ev°õ:xJô²¦¨}…l0˜K>á_ò4<×§çsrcùG&q…袞rb³M8_áv”‚w´GvƒÊµäÁ ë4T³\†)ä¹3ÎS@¿¡æ\×ÉD$3À+¥ž°ÔBõ eá–# ž$oLDøaM³ RA܃rÁ+ƒ‹l²=v_V7Üc? ^ÖíñF+žŽ(³aõÉ áŒ‹_4U±€iCÈ!ÕÚaˆlÔ ÓŒª-²ÆiN˜`‘¤Qò¯þzocª $çòL'þäW9 *Ã0…ãƒì¢K×§3¡íɧœ“%ºœ0¦¦[n›ñM¹‚0¦¦åmòDaLM §ÓšR@SS²é¤$\†)Ä.Œ’òÞ?ä;Y}2”1ßEÈOèm’æ2%`5€•`Y%|ˆŒ¸Aåp€¹áᡃ‰E/kâ.±Ý,áFäZˆÑç ‘£Oû é;*z£Xz&”mþ‹Ó ÂÕ쎦››·~>¸Kbeü¥Ôa˜j=w2!|œXwñºÛ³údBÞÈ÷àA ~l=qKGR|:Ó·ia›{Xj¼2· ‘7‡D[%Ø ‘÷n5ã¥ÜSŒ|â5ù/ïË\`ú9ÄÖR`I/E8É®ªuöhx>¾ëx ·³Ö2>¤¡KQgϼ¥2.½”´PÊ‹Wññ¼Ñ*™ªêwö%Ú^§¦8¿Î‘(r)N˜üAn¼ ayÕ€`.œ=€)™a ­z:çß<Œ)6–œÙ T®¸¿A˹0¦bçASç5×¥€R ‹˜²¨¤c¤@9ÆTÎrÕSíé9Œéªî ù/”¸~ßüÞ‰•µŒaD‰ R «TÅ•j<-Å8[zÁJþòÇ*·äÍW9^Ü«–Ä`5d×¥xt †Å—v1¹†Åï¥z)ê~)bg\ø‚³ÌO¯!!X2¯ïî¢INXr—Nö`ª $˜œ%•®&³Hcz`ü‚X?L¹òƆés~,¹ª&c˜Ö½ò…Ç~o.3êŠÉ—ph°ý¼>É”„1a¢…kè1ÅÂ)@›Ôá‚uNX2$‡¹CÀtãn˜ó¶»<8€§ÛÅÝé.;˜á”'Æõ]fˆËëÝ+Gs‹cx=…ùç1œ3‹îáSóNnñFÔ„3R<‘ǘŒ>û۔ª^AP@S'TÖ=* cR]h1 “Ë.»0ŠãŠÉëwaZ·òÞ?8ÉDŸ:ˆð•ír8 „§ÐûN+ ‘I8‹8$!ìâÂ"䜨O4Œ)J«ØaÖCÀ¹!î×çë/\{¢}‚ý<†ÐUèFQŒ)šmæ–!êØ!Á‡TM¬7¦þ?¸õ—2Ö,0Lè.2–\ØS†î":äè.^sûCY¢ËáéЋc±²c[OÜRC‰àH«l,Gë±Ch˜¢ýÃtŒ‰™qƒ$²Üí:é“)Ûnç-ZyP:¤ôX1\ÜZªc¨«ì6³p‘=…“ËXÏKp1¦¸õQ4Ax Ì|v…™ Z¸bjerœz'rœ‰²)÷Káðô¶8jÛÀª`Š"‡·[¬%!º*Ñ S(½c70†É,À˜¾éaL‰>›å©¿D<‚0¦r”c‡ŸBS‡×í¤€R £˜2 ¥Ã¤@ ÆTÂBÕ#y ôÆtåõw˜‡¤è¾ø½RÖ5ÆxWаJŒ·ÉKQb)êl© -ÅF‹ó½¸‡,‰uÑ¥tzÉu¼Dü%&xœodlØý’¿b²`rlŽžg ï÷=0®à}+d“ëN˜ 1¥0Lð¶UYöêyÒJrÅDïú0éÖ%™’0&.aÇDÀé% ºÁý6™‡ .+Ç)øp®‹S•œ­äL&o8ÊI,Î0¹Í3 5e¡:èõÁæ¥BÓEœ Šæ×áyæÙa²é[柹â1¡=ä´xG|Å9Z›³‰(; Ïhn¨ g4õþ霘:§µî´g0&Õ‚)` w²ììøÁûE<»\ëSÇ{ïû¾(¾]d²WóÎwwè Î75_‘ Ëe/D¾Úx_yá Ç˰ÐZ3+z°a@|ÏÚeMÑÐ+8Š1‘ÁñìfÐ3“½sÙÁ·ÄS¢ùwyÞ4šm>>ö³¾ 9cêÿƒ»½º•‹ ÓØ8†É«9—”jw1âŠ) ÞQm®Z‡dŠºb¿(©ž°ãdõÊ*’u¨Øû"e`“=rÈ«bc²N#Š˜49/Å*Án›Û‘³‹„ª“ubÉðá\·ó­‚1Rn­³G³N)q>&;ÌuKY”CbL)f|…f<³"ìÝ9}¹T\xzÏòÌ-Õ¬•Šêûx^›Ñý’0Õ*k¢¼eQîš([…EPAJ˜|GÎEnÎòmÆ0etÂä’3† Kž|Œé{)>›…1•ãÇ(Œ©åØá§ÆÔaÁu;) ¤€Ȩ€0¦ŒBé0)PB„1•°PõHžY1¦èú×"êwòÉ'¹þŽ0Šä˜ñíÀcNXý2˜$7½µšLRlòA¥$VÉ1Ö¸YŠzZªñÜø[Šá–Ð¥ÀåR£Ž—zéE}a ÖGF}/y!'Ý/¦Æ(½Të~)`ŠÄs°Bšý±B/Á|ãÓ/„\`¢³¥ücLÆ0ÕÆ™ËŒ™” ¹d¨D”#Ãäk¸õ‡?;;%º\ Æä΢ Ácñ;Ü .µw²Óö¢›à‰ˆr'®l›¥¡ˆ!ø6Ê$…f.q ïhüS,Æd3I\cB{¢ËúÝñ`›îâ|*‘&c³}¦ˆígQó,Œ©¨%WÌ| c*f¹å-×Ãä;欼÷'-ÜüؼMcçnD3wãs6]ŒòøÓ›<ßµ®˜‚÷þÒ­ß>âØawý.é1É»ßb]ÈÐ ab¾]Gƒ|±A2‰Çð‚dV,ì/Åw%Y(÷`{á†.ëf̸̮^éÆyæéø;ͽ¹‡4D&t#$<×˜¡þ1W‹äZ%ÞÑò½B£žÝ“1Lè.†Ð·qó6=T›Aµñ»‹?ýrPmBÝÅå^Ü¥«n™â“É5“ Y%Á­'ÜÃá¤yßdwˆ}$À=Ñ‚ÀN|‹ÃìcµÈª®/åV'þKàŒB4O¡Â¡êdCy$»µ¡ªèV~ÆSèÓ®ªuöhæ¶ÓNĹòÆ”·¦¸­ù!Æ1;ÔX!pÀôùϧ[!žœµ$ÆÇ³-=9sIÔòðÈ„YO˜5qÆÏ÷Rè’ÏD&s- t¿ôàØéxUÍîÛ„Ä(r4,Œ~êY`rM IÓCŸ¹çá©Hwûiʳë€)ˆ"7é™uO=³ÃÞáÏ ‰kŸ¶Ü7n‚ÎGãÎà 1¦ŸÍ˜ÚúéØÅ…1uLê2ÝHS™JSÏ"¤€(“˜ÊTšz)И˜ÓKGçQØÕ¼õ1&Î@ðÓЂàjàcL·'š_~kÈu·uÌ Ä’RȤäxpaV)ÖÇÒ7¾uø§>û¤¯ëpºmÿÑO±ï'þ{FŸežÛg<»úëß:,´{ŽúÞIXˆObéô³/FŠ wã°‘ˆ2†€q3î o6ü±qèRÕ»{ÈñÒNÿê¿j‘ãâJÆÑK®Ë÷XzéÊ[ÀºÉš¥“>g㦽÷ý;X™0›â§VLýǘÐ5\´å‚¶Vu2LÏ>·Éf¤`k&Íöƒ+gtÖøƒÎäÅ“O2câÿŸ½?º¢:÷}aîýƽgŸ{î9ãܱ¿s’½wº}ÌÞ÷ËÞÆ£QQ‰‰‰½ ‰ ˜Ä„hì[T@ FÁ^x;}餕¾WîDD@Pà[DQùþUOÕ³æªnÕê«ù¯1ǵjÕªšó?çš5k>¿ù³÷ô3zO¿ÌË–øîU5gÎiÛõ›‹£H&'d:ŠqHŒvhÿߊí/ùVÌ6b1bCò¯§—_ɲ~UX+c2M‰9JÏ,§îJ®%†Iÿ)«ê¥øú2e11&9À¼¶‰1Õõ/ã=91¦†Êû‹cÊ}¨^a˜Ú6îV€IïûgÝ:÷}ÜôϺe:R·¾sq߇©7ý€û¾íŠ c§¹«vá¾ÿ‹Ó£H¦ê³í¹•×ä„< xiǵû¬))…0Lãž!yw›Ór&/ÙÜlìˆræp±ßÀ(’©d®â`Ž‘âß°c0F5ñý´?7L7^(¦‚1æ%Üùs"Ìzqm _gÙÙû/÷~ÄǪô?ûåéc¦Ì—Àô]|¥Ì9 9Ä’=óðì¤ù:tЯ0 )ˆÒ^—¼è’7rœxvWFûæ·¿‹GÔK¯í}é5½1±Ðí÷—cVᩱ³OøÙ©’>0}`0úCxäéš^wY“}¿ÓÔýŠžHŽœùï‡)³¸j Q¢È=òÌtc2LwN˜®¿SÌæœîÈ1¥»þš”{bLMž—¥T€ P cb¡ùU€S~ë> %Ÿ)òò”§4Æ$øñ3Læª?¥ªcê{ÿ#Søö¬_uµ§=ÉZÖ˜d–ÐI[­ófJ©(myOp%IàQú=8¤Ë¯/Ä>â+™C|bÄ™[´ˆ%Z·tØ~‚©F J‚.]qÝ-H6®¤Éá–-™aã0î°õÌø¹þ¹Eº¤ë#1É8lìì~”éã½0ÏX¦ï% ¦1‚Çwâ)¾ßM÷K‚1ÓK¶MÎH;1)+)=‹)=0™«*+óÆôþ'o,Ü~ÑcmF­ûNýþÂ0-yy[ÁY×–w5¦ ™ðÇ€ªGEß5bu·¾sPwƒ'¿ÚµïÌcÆöø«'M}éMÈnºbs&Tº0œdÀHÊ¥QÞün‡tðI~Œ ¿ÕÅñâ~'D—"=‘¬†0„í0ŒIŽ—ðDöx47/-Çûs‹ HW&ûbR’[ÿdXý:H©=Â:{½¯N楾ê×lxæ"ˆ1±A4RbLT;‹×Ã`}%&wô(t»8_Ä}ÿÏO­<] $™¶O5K‰I|;ù1&ìÔÜJ08n%“ré=?hÉÌ­I¦M˼}.òéQOöˆ'*zcjèM„SCåÎýň1å¾ T#€Å0Aß°[¢ü(ÀdÞ÷o{j…É0á¾Â5“0v5w3¢†É}_`Ó“ pßG|œˆèrÕdž¿­“‚1I „™,†é¨Žc§. .âñ“É0*@³Y Íæ§Ùˆ‡TÓ“ï|¸5"º\ ÎÓRl+Œ ”R輄M&မ‹^ö¬’RÈ~Á'¹¬Ò{Ø:ÒZ¥Þ'ÏY!÷‘‡µ0&å–FM´0&](5rÂ<™sÀ»$t˜‹@Âö÷vV¦°, ó xöÄœ¶‘0« aãdzSHèdž_´˜UÀ;æ%0±€é¤3ÎIoLxb:fö¡‡%“ ‡NÀ Û§Ýó ˜1ù+ÙŽœcRßK­“c'fþã°#Oí|V@u¿âf¤Á#ŒI6Žýé)x¤u:nˆ÷?:ÎÚÓéd¼[“2LÅÓƲýÔÒcÊIE×¶˜Ä˜j«'ÏF¨ µR€S­”äy¨@ú Æ”¾:cŽÄÈ.®Rü¢”Ƙ`ׇé§À†‡JÆÀ˜î¸¯%ÀC’»äßžuNW¿ÿ$“€%I „“ü;=ŽÙõã•×ߊyCàJHVx8{Ƴ‡ØÙÃæ º„ |,ö´„Žj0èÒY¿ê†ùDÁ˜°ayZzÎò´„ DÌ*b£ÓÏO³Ö[KÚ`%Ì!7 S‡x_°r6n¸õØÀÎ8§ë ·ÞÉDìÁ;¸%Ì*þùžG°YE01ØFÌ3ZBÂfo»«óŒ˜pÄD$J^×ënÌ6úœ½Ï\º³€“îzx8VLâ`¼Ïxi‹½1ÓŽø ïýŸiÇi‹7ÇÉǾý‡Ã<&8èuç@`L (m'L•»_òÀLñ1&ÀTWŒ ÓGu\¼z›69iB2ãŒæ†€2×?²äÖ¡+nº Ó)¯Â??6þøÀBD”;£×ô«¾è1J©+&kºÖž¨ #™ðﲓx1~7åkRe xfŠuY/ˆ1ÕKYž7HbLl•* ÓŠWw{ïûöMFe¹ïƒ>Áû™H½§_üà"Ü÷±§ësz=±,ü¾oßð3!ã’L•VQs~gbL~˜ †‹Ãä>¡ø‡‹@ÌfsI`³ ñÜi[÷­fC’©9ÕÏ«fWÁ˜"æ%ð˜±ðåÀYˆßýñJxt_Î:¿¿…1MôFˆÃ´Ãã#&KHz$Ì<`:BbÓ#aÂA¼;c¡Të„yè10Ï 3 H˜Àr)ì¹ìº[0ðpÕvL2`”ÐK˜aÀF[ï‘qêŒ9‡acçÈô‚,‹²0¦õÆß&½„YL&`Mfð޹øÄdÂu½îÂdÂÐc®À CoF”Ã|æ0{€9 @/‹ þpÅÍHB/aÞï<6\æè«ÿé›ÿŒ"ö´<3ýÛ7öýþaGʪ'ÿz'bLÙýÿ•ŒSN*º¶Å$ÆT[=y6*@¨¨•Ęj¥$ÏCÒ§1¦ôÕsì( <€À“ˆSubaLr´ø2Iµ®ÆtoK‡„oÏ<ç‚À°$ÿ~' œ N' ±ñâËoÎZòª€J˜4|¼u²ƒ.Ù*lÛ³‡Ö6p%ÀI¦Ïö®dsK<ÒzÙµ· yz’ -a¢SŠX ©ŽÜeC¦‘°»’¬ŒÔYEY‰¹E¤–§&N’Å‘xÿÆ·¿ ßKH`˜0½ˆyFk’‹þmŒ èVÿ?þì,L,Âñ¦/¾²ç¯´6àx öËŠÉó~{Ùc6ÆÔÑv½„ÉG$ñÀ„YÅ!#f½$~àK³ýÀ¹‚šˆ¬ÆÓõ¾ÜôÀ¤Ëâ±ñäê¿›º©SmÓ€IGqÔ±/®~CâÈ8){ÞYm™h 0dö÷ ü0 Ÿ¹ F)X4Q•˜`Ë´ý1ìAP¹1 Þû˜Ø-0L¶K$‚dJõÿ½ÜÌ×c*7<¾. cª‹¬r0 Í$a—qßâe—Ý0²æ(øòYÝÿ}ü+§T9\áÏ @Æ4~ÃaÓ^x¨S§NÓ®‰.â!“<&`¸h5›õn³±£Z“}Øì…2\TÏÒxiyÔ!ÿôÚ§IŒ‰ ÄWàÏÿvSiŒñU¬€…1ýÓ·Âæ%dþÉ3WˆéBAO:tÚM·Ýc:iÇG+ Ük{®ÞnqK.±\  ál·í˜C|ÚC¼ôÚÞ˜mÄ;&±!3‰}D+ÈÈÏO·ò q¶$I1&kA¤mú²0&{nQfÅëf‘àŠéºÞwËôâDY%¹v7/ÁÁ&1]BÒyFÁ˜né;èÔÎÈl#0&Y.‰ G˜FÄëû‘3AÕ`VÓŽˆ‡iGñ½Œ©çO9ë‚«nê‡ùÇ)/lÂD$f5aQ¸“|¾—* —Ôž?¨Ü ›‡øa&û¨Gc‡c D[·«¸9†L44 pKXU/ &ñÇWLWZŒšÂ´¯åiþVÃ(µË1J¯­ô~ë;›w~ôգ,<'h¦Ęš©~þ®MŒ)u^«ƒdr† …¥3tœ]îû×µ,†&Üô­4w3†pˆ${ÇðU˜ xnðå’0 ¦«®ï…›>ÒG>¯Uþyž:)à*€iÛûår !@2M]°Z½uš¼»4<>`ˆ(ÃEa˜œfóô* šÍfµ0LÃE‹a:ú¸Uv Ù´¿ûÉ—_}U§òò´YS€·ÅŒ)zÚ8ÿî õQxH„gO zYeM>ØXæ-!!0œrK‚1霃ÝQX}…åÑÙî1°JJ–H-°&L5`ÂáŒsº¡×%v_Ë3ØoM5Øâúh$z{†‹£0«€¹Ì'ˆ×%ñå,âËyÖÒ-O<; ¾—]º¥_ fú=l…Ã3,ÞųD¢½$3 H–çæ‘30 Ì¥øo¾ã¡aè¸ðncL;ùÍHˆ2LR:“dÂ_Æ¿¤·2_UºDŠYŠf•·ÁòæîrĘrWåM-0íµM•?í’IoúâyQIÜ÷/¶È"á¦/iü¢7àÊ¢ûý .ŸÇì’ì²É0‘dJEƒ11&`ÒÌ É4eþê€áâFk¸ˆÔµï,lÇŒÿe¸èm6áÃE“a’fC’)'™äm1¤cŠœv؇ä¯íMöâ($ÀIgýª›9B,=0¸ÕŒ ,Iq%8uÆ3¦Î9Ès¥ørVïÎð·$s –$}×ß_ŽÉk>aìlL5\ËÝòÐ:–gŸ_"ÐÒõ½ï5u ú£Ç´öŸvvWܪ®ëuf°& “𺄠L&<7÷e|”Ô:i±L&`C¸%lKä8õ½4|‹0 vùÀcã홄“.|ÖO=÷•7õ½â¦¾wò™È츥ïöc¼?9n‘Ì`éw—ÝôË3Ï'Æ”ˆ¾¢y™ ÆÔ<íS|ebL)®QlEɆ–< – +­Ý#k"%Tœ“lKHB,Íxi‹l,´GšÉ\%)sŽöl£3á¨Ë%9G;fœ‘ŠbÆÐ¥…‹FÊŘÄ~³á§Ä°T?Œ Í$¦¯Ýé6§B›1WÕŒRvLTÐä%Û j”rÂÊìT5$–œøa2H&‰ )/ Œ­­­1ûô5ñ‘#ÿÁø-vÂëÛ‚ ôŠÕ‡³DJæ˜&xM\›W/ùCtˆ1%½†²•?Úk³UŸ/ H& Dul)ffÊðO¼é80Š{ß/ ‡Qü I¦ÆWq¹W”Ñf À¤§’iò¼Õq‡‹v,9Þ»ÃÅvÇ“}Xú&’LåVb®çm1¤úñ·ý‡úfô´˜2oµyLaÂõß2ÿ`L>Øsž™sÚÁ†>p¶Á?Ïà™džaXku5þ¹g>!hVÁœRLŸFöÜ\é§ëo{è¤Ó=“СCÏ£ôž÷>Íõ_>……'Æ”ÂJk~–‰15¿˜*@¨R€ÛȯĘò[÷/yî0¦?ß5È?Ù§{ð­e=òM º4R“¤|’1E1QX˜4´cÀùç £Y%1_’Í*àJB/EBK2«hN,>þ¬N¡¥ˆFËæ!Éuð^‚[ÂrÉ$¡KætdeÓß¾°¢i¼¶oØÔMÂ:‰Mû6UßX$ÓÏNyqÍÓ©aAœª·+ZªÒ†Ì‚RÖjTw7Œa’yX¸àR¿mð²^Ý┤dL×G8›ÿ`ðCÀ‰ÀNµ´´èå€1ŸÂEåŠB}Æ),I‡ĘÒQOYÉ%íµY©É&–CH¦â›~!˜‚Ë!÷}×ÿ¢Ë.ë}?Œa $™j2€i¢†Yºô¬-5„\D¹„dš4gUŒá¢…¼2LÆä‰>Æ0’L‹îè>¹{ÇÞôŽ~wµ-X=´(¨y–*ˆe)¡o‹! Æ1/¯pÀ¤¹«ÖD…Ì?xÖD…³J%ÖG•„–„£5“.‹òÏ0˜k¢dz!b5TÄ:(ï"(èyOÜùJé%( Æ”“þSN*º¶Å$ÆT[=y6*@¨¨•Ęj¥$ÏCÒ§1¦ôÕsKÜaL·õ¨ëýø¦£ˆÀÒ_ÀIÂ*9¾”Š(¥ §J^PÉ¡Éë])W’€âfÉN^hIlž‰ÅÖÉK-9Ü’-ù¹¥R.—à~©™^—ÂVRVƒ1EüɺŒî²`Û‚XÿÂR É´hõgu¬Ë±œ13LŽ-Óo”Šf˜FO^pÂÉç~ðñçš/u°Ex©c7pHp_${€á0OØ–èlدl¶x<÷NæÁz! SâÉã ?‘S)`„c䣻ԼÉ1MS~¥Þ˜ôñ/%ù÷¸›ÂW8¬Tðûô(@Œ)=u•…œÒ^›…Zl~@2Öù|Çí¢ëI™ug€g(~ÿ‹€QF'&Ã$HÊÇŸþMJ^ÃLó¥ÌS@EÛñø ³W9ì4|wE#ïå2LÒlÔïX%`LöPïKî±~LOÏS°¬ò¶Ò cŠž[Àç¬*9ÿà[å|p|9ûfŠp%cÎ!®;çÀIßô‚®± säÛ…sÑL‚ãxÉï¼¹jz‰SÞz.bLy«ñš”—SMdäI¨ T æ cª¹¤k¾ߺv#¿«$ÝS$yc½…D|ÓÐo”RP)ĵ’,‚ Ä•Šü·KgK¾q‘ΖBâÄø[*Í-Yþ¬´ÃIµ›vŒvÿ^+oLaÿ¶–-‡ <¤Çìûÿºòk“[×¶b¨&›ðQ~‹~/ôÃ1ÑÜIS¦ÿ³S®zËšnvc:µ/µ­6aV!ËT¯;>þ¤ÎânÊ|R'IÂ*ŠH<6aC,áA‘€ÉWêcIÝÅtÝ ÊäðÑ$$W¸€$É­€Sš[ý9öhXMœÐÌ¿g–¯ÊëGyt’ Æ”äÚÉ^Þh¯Í^6©DC{#RgÐç¾aØ*+\ïlŸCh?L£ìÜûÉ—_Y÷}ÀÈ6Æ-¥`0¶ÁW:ži’N¼l‘›6oùá}nV[Ðp±(œ'–\e šÍgŸ€ašÕ£ 6ðÐÜ/½>Í I M{7XD»g¿xi¢£¦Œ7bÞC*X0¦ˆy |…\0Ñ»&Ê»2*dqTÙ룂|9»ìlaYTD z7}”Ë¥Âj¨U»°ʳ*Vèyã¥;â?ûÇ?’Þ˜2Þ;¹Å#Æ”“Š®m1‰1ÕVOž P*@j¥1¦Z)ÉóPô)@Œ)}uÆÇR wÓ-}˜D‘gߊÑ(~ò®b ŠøV—’xTŠ•"X¥2p%+ÜX»Ç‹»|ô„‡3<- %¯³¥ª¸¥&£KõƘÚÚÛ:>Õï0òaCL€ˆ´¡ 'üAñìrpI×MÉtâ)óÛÞT7þâdKƒj=JMÚ2£ý0‰-óÞ‡Ÿ8îø€HyÀƒ4´x }IO#Œ”L·LòêСƒDmÓxsæÁ äT¦&³÷2ƒÊá0@Kx×ó‹£&/çoOò½œøgÒüˆ&9‚MrEùm¬¾“¥EbLi©©lä“öÚlÔc2J’éÔ³Î3LJN,`\vÈ®Á8­=â¾_Ärë¦};Æ*º€´ö`jc'Æ;9ÉŒ¹°’iܬ•Þá¢ÄvÃ9E#ïѱä}† ¯Ïì«nI6€+[‚s&qÂ4º‹5è•Ø/Gn_4Yð&ìÿÄÊˬ¼-†T­`LÑs8T¢ÿ˜ÐùÃ…shÐy{ÚÁN?úcÃN5…žŠçŸ^ˆr¹d?·©¤×%w&¡Î+ ˆ1e¶_*.1¦œTtm‹IŒ©¶zòlT€ P*P+ˆ1ÕJIž‡ ¤ObLé«3æ8–yĘŠ&þŠ'û€1zÖùf7ÿvpX7E‘ü¯ìY²®Ñœ@t& }1à“•xÜÑäzkW„Å;™+Z*Ž Wnµ³&²2h AL<Þ]K â–56f*æ–l?‚¶+AI¡ãà¹Îè’9Q@Œ)›’¯T>ßýX[P)9)/‹Yˆ1ÕDFž„ P*@j®1¦šKÊRÔ(@Œ)5UÅŒ–§@î0¦Þ}DÌâ[ká» I [ªgL*ÀIEÎØƒ%#æ CA¥p×Ja–Â|,Kñ<-M2Ú–3Iž8qœmŒï%^¬Æ&I°$µüa[<0á%ßÂì‡oñ.)fX›d:yÎòíE“¦I 9Ǔϖ“a’Xr yè®$TÈ!Ù)qâðnb@Š1Ià9|3„ éˆ1i”ºˆ~ËãIü6álà$«TIP9É›xf’ÜjÌxÏã‰áäÊ»¤âhbL©¨¦Ìd’öÚÌTeb "$S4Àdù_´ïûÖÌ5ñVÀ0éźéÏî’Idð `$ðœ`”ÉNŒf̈C2™¾¢äpÑj9úV䬒8[±€ `>Âñx&©Ù‰8‡Në,³ ð¶Rµ‚1‰¿½°É‡¯ÿã7ÇÍ\gÚÁëN)deT˜çÐ9‡xŽœ]OKQ^œ£¹¥Â¬BÐ|Bø5ù 1¦ÌöK¾‚cÊO]ת¤Ä˜j¥$ÏC¨ µU€SmõäÙ¨@š Æ”¦Úb^ËP wS¯;ÑE˜ã3¾uV½ËN+h—?Y â#R‘Û¤p/JQ|’„ ‰*¹VªW‚S÷HæšHïÊÈ0h©±K$k2AYŒI"Ê™–?ñÀ$M !³Ÿ± 1ÿ¸ ™:þôäYË·¢Èe¬ŠóÙ2Ëb˜$à{$ €$%TÅ9Ž?¤’0C À„ÃäçÂá…„üG”Ýt’¤WÄ%äüÂ!!‡’1œYÏa§äÖD²°G²äÏ?ާ7¦˜-0e‡cJY…¥<»´×¦¼“™}L'Ÿyž ©›äŒû~ÁMEe “ QdƒMû¬Û·cº“”°¹ÉÔ-ç¹’èrÏN[2\4Ð7×}We tVV ¢Åaü-‰&@Kø‘ã$Àœì‡O&õÀ´«mð¦œWV–‹ÏÛbHíc¥0/aL>à€±3Ä­ZÀR(s:"xþÁðß¹2*À»RŒeQá.œ½A⬹ÏÄBˆÿæð&h¥º\Š˜O Ɣ宩¸lĘòS×µ*)1¦Z)ÉóP*@¨@m ÆT[=y6*&ˆ1¥©¶˜×2ÈÆÔóއ#0#|k-y÷°G>÷H²`Ñ“¼aÝE ÜYÚ(3†…yCPJq@%#\°k¥`ïJ¡¸R¤›%#<\b&«á™ê„1Á,i¶@¸.€µû…g‚ÙOöà˜r=É4sÙ¶bC¦e‘ò¬ª‡20Let!<” $\bL ¯ ŒeöÚŒUhbŠ#$“x^Ô(râ„É߯˜aBq1DÁ@êÉ?€‘oqF/Šh'F*f¤ €L£ž_®ÃEÇggy/à3L¸ž°J²ÈqÀ’ð.“«„ØÌsòQ£Ë±ò2¨o‹!•*SÔò§µ»q|ªÎ<”ðÙlÎ?¬Ù½0ræ!ÖlÃ*Zòó>¶aJÁ“"WC…øo®æq¾N¿%Æ”Á)¤HÀ˜–ï왟ò²¤Õ+@Œ©z y*@¨¨‡Ęê¡*ÏIÒ¡1¦tÔsY¶yĘ"x#`L°•’Ö´GOš(’Ûš(Ô´ÚŠæO†cvÛ^%É= •BY¥²q%70\Öˆ¥À)Îz`LíûÛÅ™éc †@Ù)ïxÉaâí ÜH¦c;<}é2q,+\­…­Fd2LåªÊã3¨1¦ Vj‚‹D{m‚+'íYÉôË3Î żïK$_áTÃ0éÈæàÄ?€TñßKÿôIDAT‘ÁŒŽgÒ®m†ó/$Óˆ©ËÜ–<\¬†a‚z&‡„@rHØi¾ã#<0éW"¸çc†k!×Eãm1¤úcŠžvÀ£%4¤…"• ‘§ œi‡Òs±f|¸’ëfÉ~5Sˆ³%cn!þ–¢ù'bLù黀1-Ü~Q~ÊË’V¯1¦ê5䨠T  cª‡ª<'H‡ĘÒQOÌeÙ äcºù/ý#0#|«a;‚#Å€bI€“‚ù¤(Dɦ”‚Ö;ŠAË ç›FŒˆ†+%Ä‘{VzN[Œ©ì?bE?’éù—¶š“YwôÃT‘®üQ¶ Æ”­úLzih¯Mz ¥; ™~qƹaà2†7U2LéV‡¹Q@H¦Ö)KMß]æp±J†‰ÂS(x[ QG0¦èåO8q!K®€*µ&Êv0ÖD•¿,Êv°4ÏP –Ü ó6\[´ª1õ5¿ 1¦ütnĘòS×µ*)1¦Z)ÉóP*@¨@m ÆT[=y6*&ˆ1¥©¶˜×2ÈÆtÓíý#fúðí/Ï<¯Ø’ GžäzHòùI2}&•`’€%iŠâ“bQJÞ0pî4"@¥`VÉŽ—+\)lf3½þè ™ŽétòÔÅ[á‰ÁtÆ@?Leô‚<4Û cÊvý&­t´×&­F2—‹d:ý\ñ¼èÅ‘aÊ\m׬@B2=3y©¸H†©f*óD ð¶‰1EO;c)A!ÃW@•=ùNCÂ…²J¹Š8¯“ĘòÓ«cÊO]ת¤Ä˜j¥$ÏC¨ µU€SmõäÙ¨@š Æ”¦Úb^ËP wÓ·÷/ÀC&Hdoã[ ØQI²Q¤H‡I:EX˜+,éE)À—’;L¥(PÉgâªù"Å œ0Õ“C2ðËÉ/n1ë‚~˜Êèyh¶ Æ”íúMZéh¯MZd1? ™N:ýמ¦,Vu-Ë$$ÓðIKÍ–C†©–ó\ĘÊiâ)zÎHDÈÐTz)TÑ´ƒãQ)Žóæ’k¢Ò®Ê™ bLå´ètKŒ)Ýõ׌Ücj†ê¼& T€ ”V€SixȪƲZ³¹/Wþ0¦>ýílÁéÆ>ý­#â÷++‚›¦Â„`ˆ¯uA‘ü©È»ÀIÅ3†ÅˆR‘ovYNMJUÎNâçiǘ„d:Ú ™È0å¾c§†ĘØ©1¦FªãkyH&2L9n eÝC2‘a*C;Z±¼-†HŒékÿøÍèi0bÊ2ãgþ¡‚ɇ€icA”á¼¹xÂ!ßΛ‰1Uü¿O݉1¥®ÊšžabLM¯f€ P*@ ÆÄ†Aò«1¦üÖ}ÆKž;Œ©GŸ‡Â "ìÇ·Õq@@ì6ÅüÅ“ƒ>ÏI˜% "“È'5vqg0&“d"Ôñ>›Å+WbLå*Æã«Q€öÚjÔãoËQ@I&2LåÈ–÷c•d"Ô÷¦Ð°òó¶1ýÃ7£§¾ößl²4îüCÐ̃=Û É^åI}î®~R#Ï@Œ©aýDÓ/DŒ©éUº cJ]•1ÃT€ Pœ(@Œ)'ÍbRˆ1±YdTÜaLÇœpò…_–àÒæ_¾÷ýˆܯ®»ðâØé×]h'Ø™˜¨Àù¯ÿ­óyÝ#2vèáG_u}¯Í;?2Óß¾ø*i}|2!«'|úú­ïxrk~ܹ÷“f>ib2?ÙQ€Svê2 %¡½6 µ”™<üèw¿÷ý«.¹$⦯pßÿò«Ä Z2S ©+H¦;ì_ýñ÷VmØ=\üìó/RW:f8q ð¶Ž1ýŸÿç:ôGGG$ðoÿqxô1Þo?σL5Qà›ßþ_ÿÏßÿèSuèÐÁÓ‘îyïÓÄý ™¡R c*¥¿÷*@Œ‰m‚ P*@’©1¦dÖ sE¡1¦F¨Ìk4A|aLkÖ¬éSüžb¦K®¸îüßüÁ³“³­ÀÙ¿îV²€ —®O>Æ„þcÁW®ß´‹ SºR^2± cJlÕd2c´×f²Z[¨M ÿê¿lž>2ú¾O†)±جŒ=4ýŸL½™ S³ôÏ×uy[ ¯ï¥K—.0^S¦Í1nš™ú~ʳ']‡Íºä™ÉƒÒ•g3·ÃFM|ä‰ÑùŸ2k11¦ ôiĘ2P‰ .1¦ ÎËQ*@¨@Lˆ1ÅЇQ *@Œ)ƒ•Ê"Y ä cò×yôúu~KÂH¢C£w¼âïÌ–gúab¯ŸGˆ1å±Ö›WfÚk›§}¯¼cÍÁ:}´jFÄ}Ÿ SF©2Z÷9[º/Y¿7°å`¸H?L¥$ä÷±àm1¶Tï~øY–½7íxgøê¯MXz– §,ôÆ»É'è@bL ªŒ”d…SJ*ŠÙ¤T€ äNbL¹«r˜ ¨ĘØ2ª1¦¢Haqf¦x €IĘÆ\{÷ª_?°ÿc‘aÊhÎb•R€S)…ø}- ½¶–jò\qøèÀç÷}2LqÌÙqÀ˜n¿¬’Ÿd"Ô³¶Pÿâò¶[ãŒaLó7Ý4iÍ6¯¿¢lO&cŠÝät 1¦UFJ²BŒ)%ÅlR*@r§1¦ÜU9 Lˆ1± d]bLʨ@% $c²]1YÒÜþ>ûœ &Ôõžœå W€[G# ½¶‘jçãZö¶OîÞéƒ77yJ¼èŽî»ÚÈNÉ„û>¦|4ªJé!™È0U¥&¨o‹±F–0&qÅ$SÞ2cŠÝät 1¦U³B¨ T€ T¡1¦*ÄãO©@Ê 7¦”W ³¦1¦J–l¯ déâ(8ŒI\1IêñõƒŸª$&Þr­1¦\Wà O{mÃ%Ïü_ŸÖºôáÅÛÈI¿R’‰ Sæ[Eü¶µ·E¬$¦øªòÈ2àm1¶XY˜ÔS2cŠÝät 1¦UF"³²iŸw-A"³ÉLQ*@¨8HŒ‰€ äWbLù­ûŒ—<ïÓÖöý˜µH¯lý`óÎÇDŸß¦K7÷X¹éÝèNVV3Þ£²xÉS€Sòê$Ë9¢½6˵ۄ²aÝåàJØ€7¦Y=º Á “d_áÝÜ’é­w¬ÚOŽÜ»¡ÂÒ„"ñ’ TV·ŽOu,yALÛvïÇ{É#y([ÞcKöÁÇáAÍÕ5¯½õáKë߉³Þ¦¹Ç˜®˜2æiù†}¯nÇìPÔB8àh±ëœ&EbLI©‰Dæ£Ëè. ¶-HdÖ˜)*@¨ ^ˆ1±MPü*@Œ)¿uŸñ’çcáñÉg_D¤?ý[ôü6{ ”¬ôÄYzLWL†C¦Œ÷^,ˆ£1¦8*ñ˜Z)@{m­”äy\À0 ¤pδzh?ìÄì®´}ÑdloZ?¦_ ç¤PË|*°ÿ¯û{ÌîŒ ¶7$¸ejYÑ‚~/ôA9‰Y®};v"ÑÙ@>›J}KÍÛb}õMâÙ_ÙÓ_è%3í;°&‰yež¨€­1&6„00v:dà!PáGÉÈJ~‚²Ñº¶C)ýHI© T€ 4EbLM‘¥‰P€S"ª™¨½yǘj¯(ÏH¬€ß“á©Áyáå¨@â Æ”¸*Ét†h¯Ítõ6¥pâr /`IH ”À- ®„„ý šÄ]“†ãwµ-ƒ…sâ+· tŸÜæ4ðLØ€/ØLÿLblÃÔiòk“‘â¸nÊ­˜,x… ð¶X¡piýÙ_~Úºöë~ŒiÖ–Îi-óˆ1å ’+,"(pŒŽðŽñx& ¨0^»bL؉SƒsÂN†wåÅ+¼$F¨ T  ˆ1U!JR®1¦”W ³¦1&¶ *rü®˜è)åUÊì×RbLµT“ç*¥íµ¥â÷e) ((%0I —dÞ͘qà–ðQöcÂI9§²®Èƒ³¤ oâ` 66±·á6)£˜åðx“ì{²¤ËÒ|x[l~44®˜„j¢C¦†Ö/VŽĘÊQ+_ÇbàeÆ`I6dª 9 ._×Ãò¥KK¨ ÉP€S2ê¹ ÍP€S3Tç5 1¦ˆÌKPº)ðù§œ|ðÁNVºç'ÿÔá`ïï8±gýŒº]˜'¦)Q€SJ**#Ù¤½6#™”bˆ×%äF#Ê ¨${ðŽoáI²+ûñþùýØÀoõ«¤”‡ùh¬â!/µ®TÒp'ò-Þao“¤ØSc³É«eZÞ3]½þÂÍ}ãü©›:IºúùïúqÍî»s&‹›ˆ1¥¦ªžQ‰º‹Ëb¥Ø·Ž¯ä[ <§£)åÅžY^ P*@¨ÀAbLlT ¿ cÊoÝg¼äĘ2^Á,^ŽØ·í îUSúä¨È,*(©1¦’ñ€*@{m Åä©\tGwxZ‚â .—@&T:°·]0&ÙWL-IŒ9ÙI ó¬€x€Ø0ýˆ¿%˜âä[õ( ±çò¬Ë^x[¬‹¬é8é¨ußÃ”Ž¼2—ùV€S¾ë?ªôâºRÆKâáRÇW²îš0¦Ò¨&7GU© T€ 4^bLלW¤IQ€SRj‚ù¨±Ęj,(OGš¦1¦¦IÏ 'XbL ®œ föÚ V*‹DR©ÌlKNüHÀ3Á€&ìÁ·0ÂÉ»ºHe™éd*ÀÛb2ë¥!¹"ÆÔ™y‘(@Œ©"fôaԄ©&ÀLØÆÀ ûÕÛ%öà#`&Ý“Q=X,*@¨HºĘ’^C̨ŸĘê§-ÏÜTˆ15U~^œ ÔPbL5“§ÊŒĘ2S•©(íµ©¨&f’ äCLð±„d;a3÷ã#v¶ïoχ*,ecàm±±z'êjĘUÌL„ĘØ<ÂÀèH¼1‰+&yÉÀ ò./l›)) T€ P¦(@Œ©)²ó¢T  cJD50µW€Sí5å©@s ÆÔÝyÕd+@Œ)Ùõ“µÜÑ^›µey¨ T  x[¬B¼´ÿ”SÚk0?ùrõß-Ü~Q~ÊË’R*@¨ YU€SVk–墥 ÆTZ#‘Jˆ1¥²Ú˜i* €`Lv:øù§Ô‡ PGbLl T€öÚFªÍká¾?õöƒo­¡T€ P„*ÀÛbB+¦Ù"ÆÔ•yZ(€¶JŒ©BòT€ P*@¨@“ ÆÔä àå©@ ÆÔDñyéz*@Œ©žêòÜT ‘ €^úó¿Y$ìš|Q* cbKh¤´×6Rm^‹ýÛ@E ¼ýñÒ÷?ÝXÑOù#*P¦¼-–)X–'Æ”¥ÚÌvYÐV§o>9Ûedéj«ÀGŸmÛõÑ‚/¾äÂÚêʳQ*@¨@µ cªVAþž ¤WbLé­;æã%'Æ”ñ fñò¥1¦|Õ7KCšùcˆÄCj¦íµ5“’'Š¡û·"ñ¿T† 4BÞ¡rB¯A4$¡Ãlù`[e£(WbLå*Æã© T 1 cjŒÎ¼ H¢Ę’X+ÌS àv Dä)¨@R Æ””š`>£Íü‰©Š\d„öÚ\Tsb Éþ-1U‘®Œ,Ü~1¦tUYŠsËÛbŠ+¯Ú¬ ©VAþ¾Q °­6Jéì\‡Svê’%¡T€ dKbLÙªO–† ”£1¦rÔâ±)R€SŠ*‹Y¥¥ ÆTJ!~Ÿ;hæÏ]•7µÀ´×6UþÜ]œý[6&ÆTy–8 ð¶G¥ŒC4$£›Áb±­f°Rë\$bLu˜§§T€ P  ÆT¡püÈ€Ę2P‰,BĘØ.¨@†€©àN?Ü¡"±(T :hæ¯N?þº<h¯-O/]ìߪÓ/·¿&Ɣ۪oBÁy[l‚èI¹äÜ7ÎiǵIÉ óAÂ`[eë(WbLå*Æã©@SX°`A?ûÕÞÞÞ” Ä¿èþýû[ZZâäP(][[›ù“M›6ÉWØ0÷·¶¶b§ž_Ï Ë©â\:Î18[ ‹sªÆƒ&”–¶DŒ©1M‚W¡IT€Sk…yªĘj "OA¨  U€fþ„VLF³E{mF+6¡Åbÿ–ЊIz¶ˆ1%½†²”?Þ³T›,  T€ Ø cbC ÉW G]ºtôäC™™ð•)‘žÇà‡òÑS=FÔÓÌ›ê…Iç9•ªóxÄ—#¥RÌz׋ªtšëiµîô`ˆ,µæ©M³.—¦½6—ÕÞ´B³kšôé¾01¦t×_ºrÏÛbºê«üܽ ÐCÒº¶µeE R—Ñ]°Ý}rw|…óµïoÇ66à_É·å_‡¿ Õ*€vˆ†Šˆa.İ« R¾’o¥­V{Iþ>» cÊnݲd™R@(Ð*@O„ãш`Àt„¤Á»øæ›"!lð+lãxuVGX"=XeÒH>â*Âɵôø­„´3}#éaBÕèWÂåÈy«òXR"ez$cz ͘ž'ƒŸà¥‘æôþú–̘…Õ‚èÁz9Âd¿ê)ù·OâúH&9L+B¤Võäç8›†ÿócLòάgÃÏE@óü‚%ÉåÔO•Ö¦‰1IÕ›d’Ô¾çüfÁM ýê%a1¦$Ôó@š£1¦æèΫÖ]bLu—˜ 5Tàóû…UÚ»¡ 0>bø({ð`?’ÐN —^ŸfM¯Óž©†™á©¨@  ™?•”¡,Ò^›¡ÊLAQØ¿¥ ’’˜EbLI¬•¬æ‰·Å¬Ö¬Q.0¨KÈpKØ/"‡,ضà´Óþ¿îG†Ãh¤huâ6 €Ú'&´F´XõÏ$ß*i‡„Àã‹ ø¨Æc¹²b;OµÚ@*6ðã‡~o1©Vƒ™O”Â3Yã“â—é‘H0áH‰kÖ¡Cópù¹§\8³8ûÁKøÿ%Äð`Læ¯<¾ #¸’¸Ò—8 Âñf´@oL7NÂ3éŸ4,¨œ`L& „Kk$úQ‘ G$’â˜P!)Ž HêIKg:sò\ÅQSdù¡y~%Òä‡&_¥ÕdÖ¦§tžJTN î©*îâ<ͦ®‰1ÕU^žœ $ZbL‰®f®rˆ1U®I¯€²J¸4¶wµ-€+&pKÀ•°!n™@/WÂWØÆ~…œp<25¾ÊxÅ&(ðán+–œ¤yýb 7áæÂž}Ûš%^2' Ð^›“ŠNH1‰1%¤"Ò}Öìúh¤é›O~¬­ƒ~ÄÆ_~š†B0)Q-†a†acºƒ4¾²¥€bI@C„OR^Û=f÷Mx/‚4„½²ÕÒQq†¼š|’ÆCi‡V*ÞŤ¡"Ñ!S:ª¶¹¬Æ$h…àx™„A3ŠUí5áפb˃T›þ>÷ x(èáaY°G}©Zâ•Gý!™ÿ`ù• â‡NO(¿ªc¿I\1‰S(Ol5Ø„Ã$œYíRÓ±Y‹Æ˜T19§ ]zþ8“,°¦BŠ`˜ÌŠ0)(‘Ýì üLNÈ^žó›ÅT:-Г–NF†ýç—ÃP¹Š¬%ùFŒ)ɵüQú*@Œ©¾úòìMS€SӤ煩@ («P n–'‰& JØ–sb?襥÷ÀñuN2UpQþ„ ¤LXÈ®ø;Ël˜ÞZ“²â0»)R€SŠ*+Y%Æ”JlT^ÙÓèR`¿á°Få‚×ɇh…Á°ŸÃ°Ìµq¼d¢KÊ‹`¿@!81¼$l‚œÌÉÀ%]!êKqæi´øVÚ'Ð%m«r<_TÀ¯@m1&=¿I€?0ñØÎÅÞ¯$îÑxX²¡,΀ î€_y~î9¿æûÁà`lÈNÙ#|’^T¾2Y l›“çüz¤rž »€_iqQúg⿯€ÅW„A ^†wl£± ^ƒ=&u$’6~‰Œ&ˆ¡ü<ÐÃ$ò_¢,ŒI.*ð N+DŽ!òcLÖÝ­{w)¯dXq%‰%'ÿ/u†„ã#0&¿³€•8 %RDR#%1&QLtƶÀaøh†ç“>ÄãI*CÎÍN@/*âàHþókÝáºr Ù#1ædÖ¦\T[…ÿüRjbLÕüù[*@¡1¦F¨Ìk4AbLM—¤+ ¬’ KxL’Xrò޶/²´Šß&ødRLÀžä+¾¨@ösm° mpçì—%l¢Ęš(~/MŒ)‡•^i‘áo©uí×1¦mïO¬ô¬üQí@’‰Ã°Ì5 JâÏF‚ÇIù„‘9áGôøÌ)Á%]!ê¤5ŠÛ0màêÐPñQ|2II4ZbÒ Æü5CÚbL~oLŠAȆØÔ…»»Çèn5l_Ô*ìû=~Ž_á' xÎoJ¨ÄƒÚþeÌÿzQÅ5„™ÀÏ£ 䄞_ýKyü øK¤ À"R¢fÔ-¯™)ÐV¥5*™„âIÄ1õæA‚üq°þÜωç&è¹>z(Ck°ä†Š8F)@!üðQQ? aqë)°¼RdáŠÌâ8”Pr¤¸&ò{YÓ™dœMÏéù­ ÊbÊaæÏUd)¸ðFf1õ¢ÒçˆòZ"Ïù¥txéiå'xaC~e_ðMÝã?¿'·IþŸÐS’k‡y£õU€S}õåÙ›¦1¦¦IÏ S V /0IØ¢—Kx?°·]¾¨ {ð>™°G¶Å9SWäO¨@*sÈD©¬ÎôdšSzê* 9%Æ”…Zl\2ÑSã* WW sÈÄaXæš‚pÿ€û%pKx—òM~m2H $'Pöà0l+J’9%X ¤+€æ'­QÉf’f WLJ/I+EÂΤ‰ùkž5ĘÀ÷ÀT6Ô‚Žmq©"îR$ª”Éa(´ ÑĘü˜Äµ‰çü¦Êù#1©wÁ•Äý ®®yPŒÉôX#Žd<SX‰ôHœÜãý¥yµÍ+S(Lö…JU¯€@“8cªþä991¦œT4‹I ÆÄf‘Qˆ1e´bY,*@¨@Îð;d¢€œ7‰ŸSDæ%TbLl å(艮˜Ê‘Ç–£€ß!‡aåèÇc© T ± ÔcRw#JЬl“N€~à)ßb¿crBBQDcLŸ+þó«Ô&<$WÑkIfô%¨ä_ÞcBnM*’1Æ„ƒ=%Òü‹‡'¨æo&±­‚˧ø#øåSŠZ•Z:C¼V²2I‰1U¦E² 1¦,Ô"Ë 1&6 *@¨È¢~‡LôÅzNV™ˆ1%«>²žbLY¯áš—Ï㉮˜j®0OXPÀï‰Ã0¶*@¨È„õÀ˜ Œ¸;  A…—„@ô#÷Á»îîG1 ua¢{$¾•ü\b0yÎoÖ‰òFz݃ éE5º“DªŸL¦7&Í¿‡…’ð[%ßQÂ0™ T&š A¨hĘ$4/C¨1¦V ³T ˆ1ÕBEžƒ P*@¨€é‰>XAÙË1¦ìÕi’KDŒ)ɵ“ȼy2ÑS"k)C™22q–¡ŠeQ¨ 9W N“F¬&Aâ€ûèB¾GŽ”d|…wÀFê!IÀ ý9Î _ùϯ*ŸälâI1&q³„¯ô<ø;;tè G*ÆdfF*œS€'9¹¿D ]É•»ÊyKcñ© å*@Œ©\Åx<ÈŽƲS—,I‘Ä˜Ø ¨@†€Esêí?y?CEbQ¨@ ˜™è  !ùÓ¸ cŠ««…Ęj¡bÞΡ™èŠ)oUß„òš™8 kB4ù’o¼tß5MÎ/Ob(À¶C$R¤@­0&¸,òDMÂGñc$þŠÌo )–„@;yöèGù•çÌžƒýç— G…ƒñ.{<±dîñ Å Ì¿:j2³d)‘騿¨ T ˆ1U B2¢1¦ŒT$‹áU€ÛÈSúÄíjß¶ ‰E¡Õ) ™è :ùë¸ cŠ««…Ęj¡bÞΡ™èŠ)oUßœòŠC&Ú£~“¯:jÝw¦nêÔäLðòT †l«1Dâ!E Ô cJ ¬ê{©)y#%›šru^” P*ˆ1e Y*P¡Ę*Ž?KºĘ’^CÌ(CbLeˆÅCó¡€8d¢€|ÔvóKIŒ©ùu§cÊSm×°¬pÈDWL5Ô“§ŠR@2q–ËVB4$—ÕžÊB³­¦²Úššé cLñ­Y/¸€jnšUp^— P*P+ˆ1ÕJIž‡ ¤ObLé«3æ8–ù˜ž}öÙN‘¯Ÿüä'ÿþïÿ} ¿Í’Çü÷¾÷½è|òÉ»wïŽõjöAïï3¤#½15»Ru},w‹nÿÇsLÉÿHÂû„›N;4á9ŒÎôG-Dƒ»[ªÚ]v3KŒ)»u›Ä’cJb­¤ O[¶¾vû=W¤ £ÌbúøôÓOû_}AúËÁT¢À¥}ÿ¿&QÉ/ù*ÐXz=úÍÛŸ<´±×äÕÒ­À ›útëÕ¦âtƒ¹/_aÆ͘1£üßñT  `èÞ§O¼§#»ÌeĘØ.¨@~ ƔߺÏxÉó…1]tÑEW^Ócüä™iÒÌq“f^qõ N< Hc'Ò˜‰3Ý4cÌD#M˜1ÚHÏ>7]Ó¨ç¦[i¼™¦?m¤‘FŒ›¦©uÜ´Ö±ÅiÌ´gœôü3cžÚHÃÇq°‘>QSËð‰-ÊÓS[žš8è© N:a ‘ `§ç éÉç6Rÿ'Ækzè‰ñ=||¼“ÿ@!ëÝoðÿó÷ÿãþGÇÒq÷wŸ•ÆJúî÷¾Ô#ù=Áûï¿ÄQÇþê‚ßã‘#ù¹e¢ZËyüÆÛ%Ú} ¤ÛûÞ÷ý?TûCO¨}à³fu€Å½Ÿv}#Æ;ýžÕéyú½ Ïß×iG÷Ô³á½\Pçسi·Ô§y{³Ð~¬¸Ó,¢ï*ê¸|½–Ù_ýË÷¾Ù ·ßÿ˜ÑM¡Ë2º©swîn iQyÏ1¦¼·€Æ–ŸScõÎÆÕ¶mÛ†áb·‹.åp1šäRÀÒ¹sg46ŽR’\MuÊ ½gžsz›5kÖÔé<-¨‰ ~zÒ©HDj¢gN™·<Ôr`åÖÆî"· óÇÐýÄ“NýÓU7aO’)½ÕMŒ)½uÇœSj ÆT­‚ü}BÈÆôРÇvîýÄNüé¡ýúü w¼s@Ò[’ÞFúéM3íùx»‘¶íÞ¯éÝû­Ôn¥­NúhkûG[w}´ÅH›w~ä¦_ßùáë;œ´iLJNzëÃ׬ô¤oÒ†7?ذ]Òû¯JÚöþz#­Ûöþº7ÞCzEÒV+­Õ´åÝ—´fó»šVo~wõëû$­Ò´i_[!í]ùZ!­xmïŠNZ¾ñ+m°Ò2M¯¾³ÔIo/}õí—Ö;iÉú·­´îíÅëöhzñ•=š^xeÏ k‘v#-’ô²•iÁšvMó×´Ï_í¤y«Ûç­Þ5o••æjjÛ5ÇM³Ûv¶NYúµøæì•;giZ±s¦•vHš±|Ç¡‡|ŒÉžIé8fêBÔ#9hšJh›¼l¡©\ã-þÎpÇ^§Àtô±Ç™¡ö„}`@hö{»´ßûHû=ÔÝôuE½\xçïÜœž-¬O³;´åVòöfÚ•i?æïÄŠz0³û*î»ü½–vYÚ_IgõƒýÀcãÐMI²:«VÒžêúÛ¢0)ÿ-bLI©‰|äƒS>깆¥´¦ŽÓ®Áñk¨,OåS@¦Gž‹Ævû=ƒ8PÉU¡÷¬sºb¶aѪ7~D’)WuŸ¶Â]:ñ¤Ó–¿Ú¾|}{§Ÿ“dJ[ý5#¿ žykkkëÒ¥K`AKÎRêo±Ñ±cGœï%Õ QÓqM½µ-cw‘Žc.ËSÀf˜N“¡{Ë“cH2•'_’Ž&Æ”¤Ú`^¨@c ÆÔX½yµ†)?ŒiàcJ)y6`§ÐƘb¢K0áoC*0dŠ˜lC¾Ë0ù&‡aÚh0LÀä2LÀ›a*`L[Þ[Á0m®˜a²­þ¶á¿À0m(Í0U…1 °€b†©ÝË0­*0L€0¦b8`æòt`L˜IùñO:Žº“ÅxÞ¢qÉ•$™Ö‹¦ûBÀ˜®»±·¿Wt¸¥wÀýÒÑÇâ &8ƒØÍ€~Ï 6+a˜<¤fPÿ¦€¦2L«‚0&å2ý½™Ÿa‘1)…€`šð¥I^c—Š1ÁSaò`LËwcJПS‚*#Y!Æ”ƒJ®aÁ0a¸8cÑË.ÖPUž*Pa˜' kcúÜM’)/E ½k·¼'U¿°m뎤O¦¼Ô~ºÊ) ÓŠWw[muó»K×í"É”®l|n›2ó¶iÓ&IA&õë×/Z¡—pŒÒKØsÈ!‡4^· \±èÖÆî"5Ê"+`1L¿8ͺ"É”ÚFBŒ)µUÇŒSª ÆTµ„7“Ãn=aQ7hD޳z?¿ç¹¢ß+t}Žû%7næ›h ¹˜N˜LR³ÏV²Ÿ·5¡[“T~,9ÇSÕ ÓžàIÒˆ+&ÇÜ|7æ¼ÕíóVï2]1®ãvaLÅ=•xŒÆtö¹ÝÌ> Û$™šóß'ÆÔÝózUbLy­ù²Êí2LkÙ.ÞÔóÖ²N«c„Ö°áÆ–žkù÷TVŠø¿ÒAoÉ`.ñÏ=Æ#ŠéÏFDÆ`×Ä·bݬÇK¦G‡x6¹­ßÀsÏ¿ð˯¾*+ò /Øn#ì”uÂì>*yÑT?×¢™Á0i0wùæÃ|ìò•«Jêà9@Ÿ+aà÷4`QÌ|êDÛ(÷¿³¦äŸXVæ+è ¤Œx‰;¾ê¡€0Lmwk[Å3£x(Ä|Úê‹kvÿ³S&M™VîÕÍnJýß ›S%ÒÞ°Ó3ß"ÇÔ»—.·D<^¨ßÌ0# EÒLïJØ–;†C‡€=8RÛ’bLدm Ûr¤d[Ð(­Dü\)¾â+࿵դ»ÐQ þò¨J³Ã—»^ž¡Žt: 6ÇEr¼|•êDüzᑵR@¦è¡ûÃ>ùÔ3|òI­.ÊóÔ[bLõV˜ç§ÉU€Srë†9«JÜaL÷=ühÁ¯~•\Ûü}ý-ŒI‰%ÃN_ –¶ìZòsK›w~Š.‚(9V|ï%XôÕ–¿a{‘û¥W‹&ÛýÒ{’0e,î—"<0ÉÊH¿¿0Ùþ´1‰ã&ÀH®ˆazõõ\²ôÕ·5ÓK@—$­³Òâu{4© l¼€´Ö"‚!;0Sd,¹X~˜À0!=#Aå¦@Œ „GU»ZüXgRÌÉbϵTJ÷Ë{”K2áAÚœ )9,Íf±0?âyêÆŠéËû÷„ # Ëäܳž¬ZæúÆtC¯¢^Ñ@6ÑŽ?ý¨cŽó@Kþn0]Bè£—Ìøqf¿gõx.²ÈkvtÀd»"óL& ‰‰i+ÝZ[—éÇ´ÿ8š*òÃTÃ4·à:Îò'“ºb2ÃÉE`LðÌ”ë–ݬÂcj–òù¼.1¦|Ö{9¥v¦׺ÃEð5íµ.âN‡ábe$f5P¢QŒµþ¶j¼bˆy-Sa˜V½¶'°­¢§’njÑêJH&Ôš¨´(ÁSdÒÃì¯8ÀÖž »Þ½tL‰x˜GºÎ¼¡yh›A“þMú1cÂNuÔ$¬R Æ„3€ž4û@óŽSóÑZæ›Jô­­šîÂÕ˜Õ-q=}ˆt#r’N @1&ívpKõ@"óÍ)T†©äнÿcÏ’dJ` †e‰SŠ*‹Y¥5V€Såé’¢@þ0¦þz})‰G%;Ý×È9çv •‰¥üÐR‘Ë%›[rí÷‘èRˆï%/½ä`2é¥`L>€Ékéw¦:aZüÊžò&× `&ug2ßrgb§UENM `—Æ’† X€bLJÌ´½›˜Éï©éfRŽ´ý0훀Cav)Ðc¸¬<’)ÌX‚™s©¦H°G׌â+6&Y3mBK{ô·²ÎU®%=¥¹ì,>ü””^6ÙùÆtõ ½´,l¸ñ1GŽŸvÔÑÇiïÖ VLmFÓKa®æbLïÍ s/Wä[n£eW3û4À„ÿQÇT3ÄT ³b?L† =UcZ±3°§ ôÆDŒ©9ÿÊËs†Àæöç5ôF­®±ÑŒ¨g-}ý‡e’LÒ!HoãéjÐ0Ðÿ˜t£ Vzþn°þêÏÍ>GþÔžz÷Ô8> DåwÈd¶.ó/o¶.O#D6ôTfï$Î6¤=Ä«bÞ x˜*  S¨ÉÖŘÐV®zë¸ËóÉ„~Éì½¥› Ę´ "q’ðöYï™7ô` bÊR@ôþ rB¹‰VÒ%â%{tȤñæt†™K¸ÈÉÌž÷Öæ‡³îbA™Ý…gT#(jÙëË]ÏB+l»f·Ã‰Ód¶¥dæJ¦øC÷%ɔ̚ È1¦ÔT3Jj®1¦šKÊ&CÜaL÷öâ·Çë|ëÍS©Çõ±d8) –bIR!j’Á-½Uˆ$A”L$Eaã?.8r\±ï¥ôR€û¥!ä¬dÞreL®É†ÿõNªÐ “Œ ¾— iM{‘¦Õí —$iT&30“—a²é%e˜,Œi²å)‚aJ 7&™IynÚ 6áQðÛ_äŠÉx¢F-€·ø}9$“ç9YçÖež“ñ€-Çèê1Y¤óÈ:u"È#™Ôóì‘)i™ƒ–‹òHožM{KY[Fû5¼}XÓõ½(%70"*cò,s %¿¿%·÷‹¦6Kú^²Ú¶Ý¼ ~æÜ¾®l€©'LÑäLrážäŠÜÈ}WÁ‡\D,9?ÄþêPñÆÂ0…•#ÆTÿI§"ÆT†X<´jˆ1U-a†O† ÃÅÙ/®5†‹A®˜\¶cu.–E2 À$c9Óש ²¾ÈxO{22ÄÐ;Ù“™âB‚¡˜KÏ^ÁÏu1ºYý§Õʸ"Î&¾Udä©™D¡äÒj~FõºÂˆíÙ?j5ëñ| ƒ[üDx3Ú ~…¯Äâh’‚2h1=g0ÕÓ²ÈEýlÄo'«òà0LO[ “çÙÄÊ%NSáÙÄÂ˜à—·÷eLƒ xBe©Úø(„Šh+ÇCaSù‰I‡(d 58Þl-øè?¿jåùJRp9¹¢Fèµ¥NÅ“4oiuÒ¼=fËt=ï†^.é'Ø^µ3Ï|iSY$“ô¨tyÞ4A"©M©;H*–~©VÏŸE üòsóOŠ?<ޚϞ¸œÇiÎŒ#=W|Œ•çYù§ë?×Ó,qÁ¤ahïgþµIWù÷äÏUƒaŠÛVç·½YÉT%ÆT¿^šÍ 20ó&÷üße"éÐdX¢Ý‘ƒwéÐÿȈHçåð­ÜeŒ[êJ0W¦j*~UÁ­­¬îÂ3ª‘q‹ÜL}„i“Á¾ $ªÍnG›®D*šDÆ2é0LeÝ2Š>™Rш1¥¢š˜I*Pˆ1ÕEVž´ù äczhˆaÿ°àEÉŽwÏCƒ1Yz7’gÃA””UòºY*KV¼$´äã–Œ€q6·€.Åt¼TVIâ+Åt¿Th©ÙSh ¹r0­‚ï¥BB`&ÀdEhZ±óicÚ1s…× “:dJ”7&g&eºÁ0¹«‚ÄN šåZF–;ۓŰKÁåÕï/½!ft9L|tèÐÏÃò’fa—éxu’)xéÏô+™nöì÷ï1§hå·æÙLóºÙo~Ç™¡cºêú^è d’Ä´7ZÇcêhö„Þn0ÈÕ\Ü@™>^Ó<.’^ ‘é„‹0m|'` tÂdÄTOr¡0•a „/•¼œ»j—$£Ë²bÉ)piaLCÆEЖôÆ” $1¦UF²BŒ)•\Y¦ á¢„Îï8æp1>ɤã48[s\‡~bÔÇ Ûbu“ê${„KP¼FMt¿I†ˆæàSL>²'ð´r•è+"KþLŠíG²¤lŠƒåºøJ1&ëʳ8ŒIWÏ›pƒDA‘‘U”WmTz~†ðŸA/gêé©QOe´xUÖÒð«†ÉllÅ ‹øãÑÆÖ뎇cF—ƒ泉È%jˆ†ÑÁ‘T¤¶"GÔL("C9Æl-8‰ Gžó«Pþ¯¤ ð’ a#†ImR5x&OlÕZ;ØN×óŽzÅ —×Þ…(D®ôlpÆ<}ɦΈ]N°Ù’ERQÿAùkˆE_ªÕÿg‘¿’4Q^H5Ï“lüÿ‚ÿ1Vš“¢úO÷4Kyà•ƒ%Ÿê»K®.'‰ŸYRe˜L´Wž%£ÛêÜ• ™Nž4eZÉKHÓ’N@^rwÀ†‰&H£•³is5OŽž¤¶½tœœó¿™y«•ò~Gqµ:sÏSñ­-~wNÀì.䮤£Õ\o"‚YËô¬çîàï.Ò5Èakz‘¦ØC÷û“djz–Î1¦Òñ*Uˆ1eµfs_®ÜaLw?48Er±$|{ö¯»°ÍóÅñà*±Ja¸RX*ĉûÀïoÉÏ-¹A”bx]²' e®P“]zwµß÷’mÝ7è%¯û%Y2+–ìXKHïXiƒeí0,vzÛ±÷Wàé•=/¬E*raâqÂT \‘&øa²¢È•å„ “¸6±1¦oD0L‰òÆäIyã=x¦‘Ù·Õ¥&à€Y ÊÕEñH&ÓJ$¤‰É cR LÌ)¤“t2qlNÛ©UFžÆå¥3þr]sõ×Mçɹï½k#0¦+¯ëÑ+c:òèŽA=áèý4‰{93Åw5g;^*Ã÷R½+„œÛ³vkn‡EÎöÓ S¡3øKoÌâ^«ˆa*vŒé> c ¥-‰1ÕæÏP“³cª‰Œäão„/×s§9\,I2aȧ»¬ü†¼¦ýU!‘{F˜2ðSÐÄÃ"˜žœä´æÏ…°—=§Õ±¥iò\Q‡¦:ŽH&ûâ9¿ønÑlûG­ú[ÕD[¾’A¯™a¡XÄàIÕòdbRz¼ÿ ~õ´"<lɆiM¯òïà0LÃÝXr³ÄÂ÷lâqÅä4¶—wßü—þ%}2)Æ„<‹ã%)YÃaAÄΧfB))öHõÅÁ˜Ä9–ÿüfmê¶´+yÒG%l´ýËÙµA)„rö¦VÌ´<ï˜w†©.éÄ@ZV×ÀkéÔ^‹ã“Ƀ1A:é 4rd4ÿG¢³ÿψ1yº©²ÿc¬Ô¯ß“§YJÏ#]4a³d[ÖŒGjšNæJÑK^ßrÅ[€W9¯K¹õo{pLõÀ0 &¨iM»2LÊ_ÚQäÚ=®ã"œ0‰Ç8ôT‚1EЖĘù—)q-bL ªŒd…S*¹¬"*Ã$Ïò@¡O þèÊ•X \WL¸—9ÃÅK® ™üŒŽ 8:®«¼gà'e< S®Xv1ü I!9FÌ6Ø/ŽLÄÅ…l/2@‡£þÓªtW”o&ðgוK#cx†Á’m¼ûG­ø‰üV|ð˜5ˆÂrIdùJ\òÑ" ÈuÍQ±‰1yÎàWOÎì`Ëåje †éÑCˆNÎ _hû¶T8@ÛM·— ™<?e>Tm݃š’¦"Ð’ì×VäiEE–ÊUšD+ÐÐ~­PÏWP°$%lp9T«<éˆÝQ.!­-Y*W·¤ÂúhzíõWFW#¾QÛ6Ù¥&bT‚ µ?yÑk?øÑÑËW®Šèë<“y¤þ¡›þcòüYp0ZªFëNz!¿7&Ç•Eàc¬8RŠÎì Ìf)ûÑT$øhZ©‰1•uã‹>X&gÎÍl«®7kA{-äe5¤­Î\¶íØN%|2bLr»”ö`vør"ÆTÃê®É©<óV“<ó$5Q êÖVÜ]H¤‚jº‹@ŒIî².T†1Š+¡£Ð!±ŒO´ÈĘjRûy8‰0L…¡»¬–wcß숅ÈãAC÷{ZFdJl³!Ɣتaƨ@Ý ÆTw‰yæ(PcÂèÙ|5'›5ºêE]ÔïÁ®Ï¤÷Á!ic|¿éü«®†y%–lD)TŠÀ•‰%´äŒ#ÍPqbèûÀ5ç?1bJÏ>÷Í~éUE—o|çýCf-yUó(ºtùu·˜iÑêí˜Uô8^²#ÇYþ…«¶Ýxë=&½´ mÛ ·ÞcZú[†OD‚¥_Ò’õo· ›ˆäñ½à~)Fü¸…†ùßãÉJ„ ˜” €I˜€ê1¦¿~ñ~šgèit&Å?ûÖgØÊ?[4nÑsÚvÊdñèù[ž·eÔ¼ÍH#çn;02ÂûËo.‰"™§nÍéxäÕ<Ù˜‡•)`™…×)xÙ/f-ñ¥äß#Fý­9u‹ _Õ%Óúõn 5?¿1Ýìé Í>pøè©@èbú–sz¿â q½ÿrŸv}CGMé}û}ó–nTsS殼ê†[§ÌYá Žyåõ·Îyiƒôx@—zö¹wñËoJw縗‹ŒŒ9ýÅõ—]{‹Ó¡—B¼Ê½Ùj+™“Ç™\„&ûÏõÇ+{: “‹`bOt¹¹m»\†i§b—³Vî´RÁiœ\Â!ܽÕ`L›æÕ¼Ùð„¡ cbãh¤Ę©vâ¯e0L^°`äÜ-Öpñ©·Ù鮫124‡‹Ï½ðFa¸hßÈt¸F2a8ç1ó Î0®3±"jÈ$qM¡cŒ[ûbè5Yɵ[,\òÞQ/˜»E&p!ÏÌ~ýéY¯cìmw5Öc騹›GÎÙ¬®˜„`CtøI 7F“Lª‰_ÙÓþYäÿ%j›pó_,—ˆ‰1á<ž™ùÿÒN ‡é_[›%.$ÖßÕ˜ù‰ù—Ì×aû¶Å,¯0Lm÷HOeÛk´O—÷ŒZƒù+´Õ± ·Ž]°uÌü-ÒV%ʪ,_WLÚV§/}#šd’J÷gO€,ÓŽ‡É‹çøˆ^:fÁy˜WØý[ÄÌ&%pk31Í[‡.Ÿ´x»yw.®Ì™7VV}ˆ]õE·¶âî·6Ô¬éü^» ¹µÉÂѲº ÿ¨FuÀmBX[s.TnB¾šcì÷w;MHÔ·.yö0tÿâËOãH£ “è³Â½£Ö˜‡ÏÜ3šðhýºšdè~×@’Lq´oÂ1Ęš :/I¢1¦„T³Q¾êu[`$›•3•À˜Ä·¿¼0ŬKÊÏF"~Œ©ïýxb™ñ-få"(6ÒøUˆ00*\@l8{¾~OKΖ:ÿúÂÃŽøÉêÍ–ÿ·Ý¯ÀÇ+®¿å°ýD¸¥ŸžtZç_]\ {f.~UfÛl\é›ßþ®bL—]wËÂUÛÅ´o£K½„F1ð7燅 áî‘ÆL[zÆ9]ÍÈqº¦7è%'­{û’«{!©Ï3x\\÷KÅñãdªHS °8  €ÌÀ<˜L§&Õ`Lû¬™µ¥óÂíÕµqËLʸçéRW}ÃLJ§k'‰àúG–œpͤ§gmš¼xû™½§#Ñ{úñ×L:£×tÿd±±úÍÅ%|2Õµ\^¦!ÃÆ‰Ç/Ó¯ƒ—œuË il—<´è¬[¦c$VÔÞ®žtõ Å…Ææ2sx6éÑç¡’Ñåb–…‡•­@¯ï~ÑÁR€ ½gY S•T| õnÙøíñ9Æä·]!6~ï“©aã3ª~Âü p>í“©ìñYUmupçƒo­‰.&ÿÒÖcJùdʪð).×”>ï<ìàš‰ÑEˆžyü&ßÔÕÚÌ%.šø¢ÕÅaæÍš|»Úš|+J­–¡gÞš×vª¾µ¡Þe%€ÜÚdp·¾sÌ[Ûó/½é‡³­îb »‹æU}>®ŒA{ëÚ¯¿²§4Ì$ †îaf³sƒ=wÃ[†.Ÿøâ6§ëeõo§÷šæ<'C÷~$™ÙÒˆ1%²Z˜)*Ј15Df^¤ `Õ$‘̰ì¸\\ë&`(ÓÛy=2Ú€sZÓ}øcº {„Ô÷¾™˜ LN$™¶s'ïdöÖLêe¤°a³J¸R ±¤HZBê?d¬øHâ†~1çßqÿ³~u!¸%Øû-niÓ^!–L£>lùÊ-©×¥i/¬{zÜœqÓ—Š]¬½†iØX cº4lìlÇÆÿêÛ£ŸIü”<5v6’…1]Ý[|/ 3I0&¡—FM]òäèÙ“æ­•àq#§,ÁÝãÏÎ1e é½Áãüô’0…º_²ç4™ñã SÁI!„œ?*SeÓ+o-ÀôX[¤ºbL2“2 “¸{µ#ƒèì›5“rMa&E&‹%>*kþªvL¦ž¨µõN„ºðâ뢣Ë5à_ÉK4W`L—]ssX§‡ýOš‚F¨x»ÁÈÞ^—À'¡¿’v«ýöHw7iö x›3Ãb ÆtsŸ{¥¯Cï×:až K­ÏÍ}æ¹¹ÒËÝqß`KJg*š‰~ŽåÎ<§›I/¡3í%¥—г¡CSsÊüWЛ=ûü‹a²»2thèÍFNE'¶gÖÒ-‡þðHteÒ=>jRëä%Æ´¦ÐÒø9k5sÜœ5B/aLcg­>Jׇmø–9ÑêÊÀh±\ßû‡h'ÜÒ·¾ýÝ ³–ã}æâõèëг]znæ2l€Ô<óWÝ:ýü44{0Lذ¼.¹]æ•ÐÅ À„NÌõ*÷ú7 ˜gœmunx Gß…"ýÛäùko»»èÇЭÝvW z³Cx¶/¾ªçñ'žrþï.0ô9tbèÊðoúyÞï.CØ8°JèÖà¸O<¥ûÖž;ûÀôOÀ˜VíêyçÀ?ìÈ?\qsÇŸžÒóŽÂ0™äe€Ó87äee¦/®ý€‰SƒÿƒÄ˜,xÎ/GŒ)ç @¦£:ÎXô²=\´ aÿpQ 0ÞKܯ*Vä=0—¸bÂp>Mq?Âp±®$k2 ¨-$ f†ið°qaÏ&æn¼D½cºí‰BއG€,㾲ȳÉõ·‘djFsP[oÌd1LçtužÌ~S6Œ µïÄçZ°åº–Å– Ì6ôÂÆ¯O¦ö€BäJ]]ƒ0Êãç¾J’©uŸ¶kzÚªf²¦“N[±a·Þ «í¶* c,ŒiÁVa˜ðÀxñƒ ï|f•N.€G±M¶h«“_Ür4I¦5ŘB`¦83oh6ðP‚µšh90ó†RöÝÍê↷qæ-q¢ê[êÝE»È£â¹ŒY‹z ÊlÞÚØ]$®Ud(Cž¡»f²¦“N‹º  ‰0Ðp¡jq½ÞÄ!\ï'—«oÂî÷/üËð63άÏT³Â“dJV«"Æ”¬ú`n¨@# ÆÔHµy­ú(†ÉQ׉…1!|{ÚÃɉ¤À˜î¸·E©#ÿ¾=ëœ <Š¿†(é~‡Ur½+âJ²,Ì5É ×:a.’K°å+º$Û-Ÿaø‘ÆÍXjrK0äkêôóSÅ´?å6<}Í_ù†mæþ{=#þ–°-îI`ì‡ÿ©1Æ%x—@K ™`쇫˜ù%fÜù]t Ž—`æ·\•¬Ý}×€á°ôcê{f¼´ãÝkzÝ«¿]’ùÁã¬èKz©8x\P®û%Ìß“`’)þé›OÞõÑ‚š§o¯=â¨cÇN]èÁà¤åèìfRºõ›+>± §Öb'˜¶ôM{­³±ˆÐ³¶Þž€5H2Õ§ËMÇY1]zõM½¢´½'GNAS,ÙúûÀ+¯¿µgŸûÐõcB£ió—Ò€N‚ÄuèÐáŠën‘€“ì9e; æ&+&º»›n»§ÓI§aC0&K<Ò*1Ñ›^‚W¹Ë®í­.—dㄟŸúÈð‰èÙ@dÞpëÝøS€ÂìsÏ#Ò³f‚&œ_:´AOM4tz*q¿4{ÙVlã¿óîÃ¥C³z¶—wƒÈDW†íšžý¤CŸÖýÊžâ{iÚâÍ —îì? Üz0`Lx¶Çû° /â Ê ¯c;`òz`2{ª˜Þ˜‚&™«}Sƒèÿ3Gðyý2Qz+ðìV{›p³å–‰)— l[ý"îÑÓ®1é%Ü‘•w—»* 0%jzvÞf.Þ?æe`"‘Û  ÃEL5ñò„ÉQ`ÙΛͥ˜Éa˜žñlã®s²˜Îx²ô`[yïýr÷ª•ã( œ †ãÙÄ!™Ú7°gkœ=¾î…à ÏL6ÃT˜$ñ@!v 9Ë· :3>j_&÷ÉÔrhê\©f0Œ~’iáìÆ<—÷ŽtËØV]˜Éf˜N]þj{Ô[|[”E€h«cl†iÆò·¬pr¶»ñ”à²Z0Ù¢­:hÂø±é3'íØïú7×3¦83oh3VØÁ[¦cò -–Å%tá½(œ\É™7„D̉òM/fÕ·6Ô»‘yè EÍ•áät%€ÀÙÚ]ŒŸ469C>æ$ Ýf²¦S‰ºã9QM¼ƒaÂs_×¾sÀ0!É ~45œ\ÄÐ]H¦û–eCØ´—bó{Ïâ9®d ðt-˜K*@ÊR€SYrñàä)ÐÚÚèØ>Æ„@tžXtÉ+`¬ Æä™è7­ï¹·å̳/(É$ù|)ÁR°G%…N ŽF VI¦üŠ“e¿o³'V4dÒY¿êû=b'Á?~æ²gÆÐ%lÿàGG9Ð’½ÀúGž‡dõÕ‰Ä@L%€•‘VZoL‚.Ip%¼ƒ^Ò€q@—e $Ð’DYÆô„½Î~àx >Kn Pìýš0M‰mD\Â`á–c’ K’""ÇÅ¢—l¯BEî—|¾Lý0ÉÎ8ÓáG5tÑñþi}Ùóøª‚g¦°c*Øÿ‡ñ̸YEœø?·ÛÚŒ4ëIÃ]X?xò«Öì›m'¸fÐâ«-FÕè‚WKjÇUam½*sÚÙ¿¹÷Á±þE<([ cúÓU7EtzOŒ°0¦ˆìÞÏÛζ}ÈOBÆ$VXL›Ô—r¦c9“Δ¶mEôÍ`@—n¼íttOŸcù–³]Ê¡‹ƒ'9$„—rnz{êÂWp¸%$q2‡?:1™Ò³I4Lì‘M’Ùqa½ % ‚ (!ä°Gè¥Þ}aû?;ô<0¡tIøK˜@/a»¾ùÏ<3]Ý/Åïµâ`L›ÿ÷“³TŽT€ P*9Þ¿¨Ãßÿÿ9qÖ²€á¢‹‹_#î°ë‡ÉuóĴׂ±×ç„9Š>éô_wíýW0¬åOR¡À£†»YO†fî—§Ÿ}Oÿ'<ÍæÐØ®d‰˜ú0TëŒéÉå]ïœ_®VÞ'¦mT'òlâ·öI“ûýå=¯üáÿýå%ÿ‡7MW`A¿ßyž SFW(Ä4ôŠ LÆÞÖ“éÀ‹½p›K ÉôµøÆžßÿ§¦œHï?ÿ_ÿßÿX¾¾½ÐS¹kÀÜ™7ë1Sž1Á£Œž¿E¦È®´©À0™Þ¬ChKA¾û½ï¯9ï?§N(f¸ À‡ÅœyC›Áä›Ä’ôۃcת«̼¡‹+cæíøÿÆ*hº1omÁ£h3Hn9ÝÅŸÇüçT ™É´(1tÌtÞ…§ÁÈÓ¬@søÌM}[W?5cÆo½žX†¡;ð&tnVÿfûÑô Ýá²W@=IX„ðãSþ¯GWþoiQ/óù|å퇳e¾`i¨ˆ¡1¦"ñ$+oJ*çÏa,Œ)ÐS’K–7`L·ß;ÈŠà˜^ßwû=ƒ€1™®’¶‹°$åK\Ê$Щ’éhÄÃ*)´$ÖÄŠ=·‚4äéI—]{ R·?\Û<ÌùÓ^Xg¡K¶-Èð‰ˆôü¢uA F}˜íM£>~¥Ð¸%$ì¯$bÝŸ2ÿÁ•Ôº/sÍ×õ¾Ž—`’w a±bûÖ»Z-]²ü-ÁUÉË»oéׂXK0óc6nÍnpKkI ÿŽš {¿—^² ÿñ#ÇEù^Š F2ÅÁ˜À´N1}ãåO¬ú;ÿ0÷¹ ‡µíêSó4dÔŸ~ ×Yëv9æ—^R€IZfRd!fßf,{ ÕN`…lXðê."4äz¤uæQG·jÃŽ=ï}šÆÿ5ó\‚1Ƶ”Þá,aºð÷„¡}  *½¸æMxW’„ÀpxGl8€˜Âh>úÌ$Йˆ'.—ÔÉ\`4Ìi‹Ö‰?9éÜð.}ÝçtësÏàacç\z 0&‡ËDÿgK‹)]Ü:«‹ƒ¿%íâ¤gS.}ÜÈÁë’z’CŸ†® ÿôf­“—ØÓ‘N?&Ó3£[7{ è%ôiݯ¸Y}/Á7|‹@š`B8ËÓJ Dj†©»Œ€,Ë *·ÿ¡3þéžìõíƒL SàÖCÞÜÁN`¢P`À/>wóAË`Ê¥ï¿!d¸è,‡ë­pŠ3t¹ ÕyÞ㯞äGÞ=aôf„U¶'þâçã—ß³àõ~5÷ò„IP`æ–³'ô§nê„EÉkÖ¬Á€pQÛVÿ³ låöéY¯ƒ qš46B,ŒÉFÆÑÞŠžMV Ãðl‚´£Ž:zá#··»çË\þµ›Ð¥_ó߯ǃh¹¶OkÌ“-Ð*f% AW#O¦˜|°0¦'œ¥ügôš6váŽ&ÓO‰ƒKZ‘+5—¼·× ›G=ðÙ¤¿4A¶·ä+ØVásenÿƒŸê<Û*½T˜E)ܵ‰òì¼-²´ÝÔs/¼aûa ñfmDYÕ¶ ŸÖWuÿÚê‰w²­&Z<—²ì¶/xðŠ3ó†fƒÙ6JÁÌmø™3¿ÕÅ-p»¸¡2óväOV=yçžqw'Z±ä÷1sXÅ­ÍØØät­aRϽcøªž[êÖ†î¢ûU¿›²æ%ÛîLÂyȆaC÷Y[:ï;°fÛ¶m:uz~Áꈡ»šÀ0!¸ª,Ä$¾ áŠiÌ‚7†)rè~äÑÇŸÙoöÆ{V쬽‰$õÕ°RŒzå;x¦ÛùÑÜjŒü- ©T€S*«™.(pÈ!‡Ê c ûqê– ¸ ßžqö !ù7|Γ‚|)Ù‘·›ü…ƒa¦Ä¶?fŒ P*@ªS@†‹/E%¶—<hМÖ9›ax ÅJЇ‹`˜N:ùôõ[ß‘{Í»~V]®ùë$*€ÐŒI&Í+H&Œ ®Üñl‚P;0ôm]5jÞfx79þšIbiýºÆ¤w¼áäÄW.ÖW,\º^[û»Ÿ|ùÕWIÔ+cy±dšù]€IKiM¤Ü=(´ê7ZPˆà’2ó†ÉµYO¦Â0ù—ò›‘+QûÃôЩz¤Ï>ÿ"c2³85PÀÓV]€IÏl=Þ^y“¹†Ð™E±¹^‰ %uÐMɺôT†©d[µ¦ë{i[=ðÛj ê¶^§òâÁ˜Ü(„rÅ83oVäz crppôop1(f~íâì»›Aèræ­^5û¼eÞÚË–)zé.pkÓ0[¸µ þêµÿÌì×cÞÚØ]Ä®0Xžþ¡»Lz!™¦Î_mV@]¢cU0&tnxNDÿæ2Lº—W;Mü- ú—Ì\ºô’W½\ –þ‡Ÿ|N¼.á#,ýýŸ/S“ݯìyîo/ëÕwÐKŠ.=ÿâë°úcºڬ¸F*B— Ž—üa㪦—”g* c’Y*ÀL3_»âÉÕŽg¦úaL:Ÿ²díNu~.ÏÒÂyXOÔ6À$«]åqÚö˜µû/ÃÛœ¯¦À·àÕÃ0‘djvÕ„ëÛó¼7FôŠ=3 &«²;@{ÞGœÉ¹Ó@{Á*Áub_*  D ö×Ûïlv}èèlKާ1xs“_ÏÀÿW’eOJÞ`ë ˜4“˜Nùó]ƒJV½„T.Äç‡Éf˜Šý”2LU’Lh ý*IRZ]eù@C ˜ô”ÖCî7–ÛV ¼]¸O@(muå‹ËwoyReµZß_ Æ0饛5ó†{Y=F†õ•4-g¯ç­-Ï-¾µ…uÓÒ‚žOº‡Lšy!™&Ï]]òž¨K£=f Ýí)Ъ†î 3KÙ#Æ”¥ÚdY¨@y c*O/r‡1Ýv×À"7H¦K¤ïà[`L¡I%±¤"Ë}œä¥”ŠX%Ãr+•M,•-ɃY\n)0Zœ3Ø-×ë’‹.Uä¼$>1P1Æ$qÀLo}0#ìïÞï…~5é ìù”S^X³Ã];h-tÀ{U½9S\Ä‚É6"&’L5©µ´œ3¼ÔÞâþPzÂ!OO<üÈcõq×Ãeªc°0PÉh´á€fq§WDg†¡™®³%¥—?ýøŸ²hõ[‹TÑL±Ç ºm”*8B7<—d˜ð\½dÝ;Ÿ}þEûž.y ˜Ó»]ßàáÆäÿ*¼tú½hOr–⣙gK¥=ÉE☊.•t çéÊ|˜6Nç­âtAqŽ©cJ^«cލ ùT`ý˜?x!RÀâ^½&“¦Ls†‹.UàÜX€©Èg§,ð¯¯-É0a¸øæžÿöÅWšóÚŽ~«„g¨Ÿ«V¯>üÇÇÎYözégÃéWÃdx,(É0yb6…ý_"þbõ“"‡g¾ Ûoní7 PõF”%›• êjô±Ôµ¤æ’ jÏ{±°­ P¡a@I®ZìM=oí~y[u—•h«žÐ9ŽU¹àçÒMíx瀩0Û[êÚ[ƒgÞ@¿½4gAàÌ[MF†©Ó¿‰»µÅì.lƒ… ¹Ý…bLíï~ÒÄòVpiŽó+-9?ÙúÆ?9æ¸ ³ÛJÝ5°gùAECw6›Æ·bLלW¤IQ€SRj‚ù¨±¹Ã˜0ã¦t‘ßžÖù|ÿ~k˜‚<'™ˆ’NŸ$ÛÅH4¥¤^vãÁãJAQá"cÃiï œ-yãÄaRÒ*®4·äñYRsÃ8ÇÔ cj]ÛzÈÀC:>ÕQ–´¬hé2º‹¹¡Çìøˆ3ôø ©­= ˆùwÓÔ‚Uo)êa®ª×…Îžà ŽQÊx؈Ã0-Ý°×³Ž°ÆO—€1an7¢W|Óñâ˜Ú†÷½_©N/ª¯+3üåÂRnä"Ð%3`œõ²½Sh å/ÝEº1;Ÿø‡cJÌß…¡T€ T®ÀëÓZa‘‚e€™°!epF8g‹;‡È~¼‹Ç&9F~çÚ&M-. Àä:aò Þ½2†içÞOLÛ9úÅÈ`Œ„1¾Å¶ä\‡»2ôÅ·øIœBñ˜d*°|åªþø˜YK_÷=›sÅë+Ê7„|tàsÑÿü•ä¿£áÐBþ)žýØ©ÿ¬dŠ™º\×õ7·ôà­zÓß›àk>\N$Aw؇a‚¡÷˯ ¸dI­ÄÿxcžÉìE¥‘H¯+mI<6I·Œè¥äEy@bÉô‡Ë{VËß%Ô¸´U+ĪÁÛy¢^F@ Q€1á}ݲ•“þxœ¿½±SJlóÌXÃfÞÆÜ~ã½?ýÞÔÏG¯U¿‘aºÄonn=·6`*ÿÖ“a*ëÖÖ\epuŽó›^Õg`Ë–7Ž>öøñ³ÚÊ4+xcÇ\~€¡;›MõµVÁˆ1U B2¢1¦ŒT$‹áU w¦Û<žÌøS({¤’gÃ`’J“I&ÉÉoÂ7<Ž@¥ïJ‘–Â|,éd ækÌä±îÇ–ü–~¿¿%/·Tçhq1:aLøŸÁ6³ÿ¯û±ž ж3©&|Û¾¿%ôl<ØS²Â|Êq'ž2å› 0YNhì©7'.»Ì¾­5J‘a*)rÞŒ)Â?\˰‰°QEõŠÅ Ó¿iGçÙˆì÷<áÊð$烖üý›Ó³­ÚàrÉû2(`\ ë¸º¡KfFŒ)oÿJ–— P¬* pÒ®¶ê“ {`eÇa2ðQ ꫇öƒ¡Öt8rÀÇÏì* $†‹óìá¢`ÒábQl¯òcÉa¹‡a’*àW7Q2àÊXWø~l`lgô›ÕÆr É4sÉ&÷ÙĈZh“ÁN¿ª`˜ ›ü5ôo"JŠ× üM` VO<øãàŸ¥˜ üDþS|U¯Ì½½ûðT½iÏ—å€Yºõ`˜¤\ ´ É„=Ú*¤‘ %H?ŒîWVz mT¯Ï,’é²N[ åz‹C^Ú~ÚV£¡„ycFƒGÁmqá loì”’Óbæ¤13oëÖ¿1îâŸKGTבaÌRó0(Pý­-“ “´ Žó3ð’iÜÌ•f…ú ÝÙlßlˆ15^s^‘ $EbLI© æ£Æ äcÂ\[„•ßžzÖy%Ìð™ç=ˆ’Ã'9N××ëb³×´HÜ)izÙV$É¢±€dËwÌù6àR’XŠ-E:[ ‰§s@1£ÆV'Œ ˆ’fàrI‡ì0Û,ضÀ|üÃW؆)&Æ„ßÊ|ÊÜÛ SÑ“FÔ B2L5î>3q:`L˜Õèô=5ªÒ½b .3̇\¸’Kì•øÒß³År¹TÔ›Ùãê3®d_GŒ)5‚ P*Pˆ'tqÆBÑ ñØkº¸bÂ6¾’cÂ…dÂpÑzŽp ¦$j¸'–\ ÄA¯Œ~Ía­z`Ò±1F¿Â6!cÊÀ¿BH¦é‹7•|6ñ;ýŠ¿˜Û ÿA‘FÁÿEþJò—‘#Mo(ò_“ÿ¶ñžÙR˜{{Ýñ°Ü9ji®ã/Ü©Ãq„UÂÀPÔ¸´•¤‘ˆÇ&ì= Çã[i$Ø)$ _YR$Óï/íÝVçÚ+[d=^YÁ¡&Üç‚gž€c•°öÆN)m©Þ3o ·,[(;^õ¦± š•çjnmf˜8ÎoVƒ¬ùu…d;cEÉ¡»x¦7¡Þr‡îl65¯¾8'$ÆG%C²©1¦lÖ+Ku0ÓÎ’ÁÀèE½ïpÊYç…6*ÜÍYñ,LR0™ìHÉð¥T‚R²LøÖªÖ°$®°Ãq%ËOx" À•‚bÃÙ–~oL% ®äDVrÍü®³%kÉZ³Œý%iÿu˜'I ¬D‡+&éiÄ6ð­DÙ0 9ꨩd·dͧüôäÙË·«Ÿ-Ǻí„Igß<d˜J ›Ï€1ýÞ]œØÅ jaL½bʬ-—i‡cLþŽ®|r!¡â¼šÓ›UзÔð'Ęòùßd©©Ș°‹«Ë%@•à*F]Èà[|DSö‹ó¼‹»&ñÒÿe‘L2\tï§¶ÃÎÀ¤ÆZsnºb†I½âdÔô?ª4?¾¤IÆÀHO~­¼BÅ/>l¤ ™;â˜ç_ÜõlRµ!DK$„ þA ÿAO„öÿ|ÄMb2Ê_ ò/ã«V ÀÜÛóŽ‡Í€õ¾®Æ™:0¹º2L(št­¦SÚƒÐoÚHrrÛÒåj#©•8ûB)v¹[Õ{d¿à<²²[[œî¢Ü0©É© Žó“SÕçDH¦ÑÓW”eV(—aâãaõ5UÙˆ1U¦E² 1¦,Ô"Ë @î0&Y/–ð-0¦ˆœõ[?Iþ†ç¤Ò.”Ô¯R¸Ù^mù–ý¾V)WòFP²–Å"–R-5 cÒ`˜$¦^jÈG %ì‘Às°÷(í§£Â|JÇŸžkyk¸Ó¸ NÏÛ㉩՛p¥Ð^.!/µË"Æ”ÞÿsN¨hºɤÃE70´8 ÔMõ SÓ‹É $AL?øÑÑl4ŸM<Kņ$yˆPæÞoﯓ²’º´¦~˜XAT ŽÉtÉõÑm5”†é˯¾ŠsE“vj5óf2Li×$'ùsk‹Ó]¤aÊIuç°˜B2˜²ŒC÷,Õ>1¦,Õ&ËBÊS€SyzñèÔ(;Œé¦¿ôW;º‹1EPò«b ɉààÇ’N ‹øæØïÛvÍ ¶ÜÇ€+v: *¹K!1œO\)ÌJª1&t3˜O9¦ÓÉÏ/ÙªK]Í™b2L©é‰›—QÁ˜"z¶‡·0¦v}Á”’pK¡=žÎ××ù},wqIŒW[&bLÍûðÊT€ P,(’É3\4oFd˜²Plj)ƒLæo|6!Ô˜ŠªKF`îíÑç!`*b%É0ÕEqž´R@2ýæâë ÁU ®m5”@†©RíÓú»êgÞÈ0¥´î£omqº 2L)­úœd[H¦Ö)K9tÏLcÊLU² T lˆ1•-ò‡1ÁÛ¹¸;2“ cúåç*cTr#ÊâP¤™ Qr‚Aœd&›R 6äïRÖ]+UÀ¤crH¦Nž²x‹ 01–\::àäV£FôuÀ˜`ŽòP^ïW‚ȬÄ{œAdº¸RF»8bL ø£0 T€ Pt+`‘LAÃE2Lé®×Dæ$Ó¡?:zü¼WM_x6!ÔÈêªq¦`î½áÏyªž SUæéj¡H¦ /¾ÞßVã@ d˜jQé;‡E2U:óF†)}õmä8ìÖ§» ÔêªÏIæ…dzzòRYC÷”6bL)­8f› Ô@bL5‘§H¢¹Ã˜àê<ÂúŽo1‰SO²NWœvÎW"AEÔR”#%°J¢êQɶâ{ÆÀ=ùùI0&!™Ž>á—“_Ü¢G?LIìn™'Á˜B{Ŷ]>faL±ùKO'·ë‹Adæ(Ø¥§&Ɣȿ3E¨H™ ™<ÃE2L)«Âôd×"™?züÜWuHCCHzj¯ÚœÂÜ{ým™£Ù“Nÿõ½ ?"ÑÐ[­îü}ù €d…`¶Õ8P¦ò•ÎÎ/*›y#Ô࿵Åé.xkË@Õç¤B2a¸Î¡{jœS*‘E *@Œ©Báø³¤+?Œ©ÏC ŠÌT ‹Úv ú/Î8×Ü<ò£H%˜¤â(o&¢4s¬õ’ #º½|G~£”4“‡d"Ôô~7IùÆô›K®èô\ìòþÇÆcª¬'ôÂI>“Dfœ^ŽS’þ1Ì  T Å ˜$¦Wd²n’Ld˜ÒPcµÌ£iî%ÃTKey®Z+`’Lq 2Lµ®ôÏ$™â̼‘aJ_‡äؼµÅé.È0e¦êsR“dâÐ=Õ•NŒ)ÕÕÇÌSª ÆT•|üqrÈÆtCŸ‡,ën\6|û‹ÓÏ8@B—LŠÉ$¹Þè?)Ž-¿ÇdcR’©ÿÐÉG}ܪ ;"V».ݰ÷Àg_$·[bΨ0&¸Óèôît"ƒ„¯ôw†¾Þ/Çd§¿C#ÆÔÀ?/E¨ȸB2ýù¾'O:ùôõ[߉.ÂXûÙç.f¼=ÔµxB2‰•wáÒõÑÎx>:ðy]3Ó7X1÷’aj°ì¼\ ÉJ ÃT¼™ü‰LqfÞÈ0e¬È­-NwA†)cUŸ“âÉtﱺ§ºÆ‰1¥ºú˜y*P•Ęª’?N®ù˜®½öÚ|Qò˜2k±9ó¾m÷þdþ§1ŸòƒÃ'ÔÌÚIf®† Vþ‚¿HœW]ßËcü„¨b2ÿrÌ T Ù €d"ÃÔìJÈËõg¼ðô?þË7ïi2Ly©r£œ0÷2–\ë=EÉä˜òôZd˜ÒX³õË3fÞ;üÇÑ3od˜ê§Ï|Þÿáª_Æ0©M¬^º® l™ùôÑÿøŸNÏ¡{]u®ëɉ1ÕU^žœ $ZbL‰®f®rò…1ùuŠ–ñ[*¨@b1¦ŸïûJ'úaª¼Gä/Dóæ? câ¿™ P*@€çúabóh€»>Z0xùšûêȈöF?L ¨ˆf]bÏ{ŸFT=U4«^x]¿ï~øYômñ˯¾¢nTÀTΣ' è=› ¦×wöÜ×™·¶lV.K– ûÛŸþ+rèžÞæ@Œ)½uÇœSj ÆT­‚ü}B ÆôQÌÕ,BƒH,ÆôÒŽkkë°ñíI‚0–\B»á„e‹Sƒû“:]ŽSÂþXÌ T Y „‘LŒ%—¬zJyn€1áÙdÝžáa£2L)¯áÒÙ#™È0•ÖŽG4V0’‰~˜[iºZÉD†)MYV^{}çàƒxk+K3œ&– ;xI‡¿m\ˆ{_àèC÷ä×&1¦ä×sHê¥1¦z)Ëó6YbLʨ@Ù $c‚+¦'WÿLã7æŸO!ÃÔä¾6=—'ÆT'®¨Á§%Æ”žÿsJ¨hŽ~’‰ Ssj"»Wýè¯ÛÚÚoß÷ÉšÏ>ðZACHvk¾¨d~s/¦œT}êŠé'™È0¥®œá@’‰ Sƒk¡¡—³1&\‘·¶†Ê΋5L·ÖœzûÁ}ÛþöÅW~’‰C÷†ÕC5"ÆTzü-H·ĘÒ]Ì}¨ĘÊFXlŠæå¨@21&qÅ$iÛûÍù2L¼ ÄW€Sûœ ²DŒ)~›ç‘T€ PÜ*`’Ld˜rÛ SpÉDCHcdOÈULs/¦„T ³¨€I2‘ab#‰£€‡d"ÃG´ãbL’‰·¶×i^³¾wCÛçöûKý²ÓC2qèž––BŒ)-5Å|RÚ+@Œ©öšòŒ‰P€1&*P¶ ĘÔ“`LpÈ„FæSÈ0%¢¯MO&ˆ1UÀ %ð'ĘÒóŸcN© ÍT@H&2Lͬƒ¬\»Çì›ömŠ(’L4„d¥ÎË(‡L4ô–!m’B2‘aj’ü©¼¬’Ld˜RYeeÚÀ˜ð;ÞÚÊ'GÑ]YtG÷í‹&{²ôÁ››&wï¨;•dâÐ=9uW2'ĘJJĨ@f Ɣ٪Í{ÁòŽ1á‘ÓiÓ[mÛóqô1ü6K  ºQéÑ%Ú÷ágIë9LWLê ™Ä4 gR’VY ÏÏ{ý5ºýoÙµÿÝû³ô¯OWYÞzçÀÆ·>ŒÎó®½0Ýð–ÆìQ*@¨@BÀÄ4ø’„d†ÙH¯‡ <¤dæÑÒh)©RVøàãÏ¿üŠÔ¬Vo¦ÊõÁÇe[ÍTÖ¿0œy«¿ÆÉ¸B1Æ„<ñÖ–ŒŠa.ÊPþ–LVÉüåú1-KîaîÁÔ"‡îeˆ›€C‰1% ˜*Ð$ˆ15Ix^¶Þ äcª·¾Œ)}E`Žó­€ø[oLÂ3ÍêÑï¯Ok…0؉{Ûe?M`›° ä[¿”žS *‰Y¤uR€S„åi›­1¦fׯOªVÀïŠÉtÈTõéy*@¨ T€ P*@¨@¨À•-ák¼QÚÿ×ýØÆ¨&l´ïoǶ¼Ë)L‰²R*@¨ T  cJA%1‹%V  É„ õÏP œÓê¡ýÄ'Ó®¶r°ÒK`›p%N²Ę’\;̨¯Ęê«/ÏÞ4ˆ15Mz^˜ ÔD@WLtÈTmy*@¨ T€ P*@J*€õÚ ¶-Àa•d/ 3'LpÎÔc¶µ¬¶{â‹ P*@¨ éP€S:ꉹŒR@X%OK –Ä“€Jp¿„wñØ„ýÀ˜ðQ¾Å‘r°O|%VbL‰­fŒ Ô]bLu—˜hŽĘš£;¯Jj¥Àž—¶íê#I†ª/½uîäT« ñxs“¿ØŸâR1ëT ZbLéo!ĘÒ_‡,¨TbL•*Çß%\bL ¯ f ”¡1¦2Äâ¡T€ P*@¨ T€ ÔSQë¾Ã rõ˜ç¦T€ P*@j¬À¬]–>ÜÃs^€M“»w¬ñÅx:*ˆ1%§.*Í 1¦J•ãï¨@ú Æ”þ:d  ÆÄ†A²£1¦ìÔ%KB¨ T€ P*@R®1¦”W ³O¨ T w ŒîrH`™×iñ³M¹S‡ΰĘÒ_¹Ä˜Ò_‡,¨TbL•*Çß%\bL ¯ f ”¡@ûG ÚÚoÿëï—ñJ¨ T€ P*@¨¨ƒÀ˜fmé\‡ó”T€ P*@¨¨½ðÃŒ ïˆßKØÀûëÓZq¥Ewt— qׄýB5a§Yû ñŒT a cj˜Ôu»1¦ºIËSÄ+@Œ)ñUÄ V¦1¦Êt㯨 T€ P*@¨ T€ PP€1MÝÔ‰Q*@¨ T  €I®„¬â$6„gÂÞWN?~~`?`¦{Û5ÒÜê¡ýà±)Åd&©@€ĘÒß,ˆ1¥¿Y*P©Ę*UŽ¿K¸Ę^AÌV‹ƒ(  T€ P*@¨ T ± cJlÕ0cT€ P*@¨€_8Xiû¢ÉÀ’Äë’€MlÎtÑ„ãñG"aïT• ¤UbLi­¹B¾‰1¥¿Y*P©Ę*UŽ¿K¸Ę^AÌP ­½[ T€ P*@¨ IV€S’k‡y£T€ P*@< ˆË%0LØoL6©&Ù¹«mÀ~ 9‡HØ€‹&JJÒª1¦´Ö\!ßĘÒ_‡,¨TbL•*Çß%\bL ¯ f xØ´oSǧ:"µ®mí÷B¿³{`»eEË!‘C±ýدºO¶– ñE¨ T€ P*@¨h˜ã7Æ r S›¢T€ P*@ªT@\.‰k%lN¼ƒXOKòâ{ ûÅW“€MU^?§ÍT€S3կ͵‰1ÕFGž… ¤QbLi¬5æ9†ĘbˆÄC¨@€+&8dB¦€(UÂ>b[² hiÁ¶€œ”^Âñ€ŸVf‡ P*@¨ T€ P,+†‰S–+˜e£T€ P*!ìm& /„Š“hqØÿL€–*a?5ÉWz$6dË,Jþ Æ”þ:'Æ”þ:d ¨@¥ cªT9þ.á cJx1{T @u¼ä÷À„£Á3µïo'LpË„¤ØÕ¤T€ P*@¨ T€ ÔOWßÒ¶«¤Q¯|I?â«ú]—g¦T€ P*@¨ T  ÖÏ8ø`''ýùßþ©ÃÁ;+ìÁ·|¥JbL©ª.f– ÔTbL5•“'KŽĘ’SÌ ˆ¥€ J8T¢ËÉo*Á6ð­°Mx‡‹&IðÌëÔ<ˆ P*@¨ T€ P*P…¯ìéÿX[‡À„¯ª81J¨ T€ P*@¨@íøüÓƒ=¾~ÆoÂ~|ËWª Æ”ªêbf©@M ÆTS9y²ä(@Œ)9uÁœPX hü8ÀIQ/ðLf{€4aï-+Z°wÙàT€ P*@¨ T ® |ñå§­k¿îǘ°_ÕõÒ<9 T€ P*@¨ e(0·0Æ„ý|¥MbLi«1æ— ÔNbLµÓ’gJ”ĘUÌ (­€xcÃ>I<0á…`•&¿6Yè%øj’=-Wú¤<‚ P*@¨ T€ P*P <Î1ÑS-¤å9¨ T€ P&)ðÄùÇ^Û¤kó²T n :d¢+¦ºé]×cª«¼<9H´Ę]=Ì\å cª\;þ’ P*@¨ T€ P*@¨ð(0~Ãa&ÉDWLl!T€ P*@¨@ºèõƒvJw˜{*¨€ß!]1¥³©cJg½1×T  cª…Š¿øåϰš(ó%e© T€ PŒ+@Œ)ã\¯âuîÜùûÿq¨X£ ;TÁüô¯ÿöÿûÚ×ÿ¡¤É)ĺbN2LH¡f£"S‘e$úé1G™Ö¢h«P‘ ¨Øîjî)eÙSÎßÿ¯}ç_þÕcÐ1 7ßüÎÿºôÒKëUai>/1¦4×óNªS€Suúñ׉U _ÓE]ÔÐc»ö}RH{?Ùµ÷“V:€ôРÇÎ=ÿÂ{ìx§Þz瀕ÞFúéMM{>Þn¤m{öoÛí¤7vï·R»•¶:飭»>Úb¤Í»>Ú¼ÓI¯ïüÐJ;¬´IÓ[¾æ¤^{ëƒoÒ†7?°Òv¤÷_Õ´íýõFZ÷ÆûëÞxOÒ+H[´vë{VÚ‚ôîËFZ³ù]M«7ï[ýº“V½¾ÏJ›¬Ô椽+_+¤¯í]±ÑIË7î]¾ñ嬴ÌHK_}ÇNo#½„´ÞIKÖ¿m¥uVZ¼n“^Ùó¢›^xeÏ k‘v#-Òôòî…FZ°¦]Óü5íóW;iÞêv+­Ú…4WSÛ®9…´³uÊÒ¯ýÃ7g¯Ü‰4KÒŠ3´cæŠ3–ï8ôð£±J ±ÿaÍØŒ3~zÒ©g-ÃóƶmÛ’Ÿaæ P*@¨ T€ P¬*†éÒ«ozdèXoH2eµ–Y.*@¨ yQ€S^jºÆåìÔ©ÓøÉ3Å¥F(Ø¡ÔüôàÀÇ~}þ…ŽÉÉ56mÛó±XšÄÆä˜\ӒڕĢ䘓\C’X‘\ãÑ–ñ¨ÈfT°¹v"ÇH$¶¡ÕH¶aHLBŽ=È5‰%Hm@b»}ÄÜ#†ž‚•Ç6ñXöŸYG :óV[vœ_žqî·÷w-8–ÕÆ1ܸ&›n{f¾×S&NGŒ)ÕÈBPŠ ÆT‘lüQòÈÆPIˆ%M&´ô=jÄ ÒA—bÐK ™”^rF–.ÀÅ0¹H¦*&{*)šar1&gljaL “3TuF«>†©mS0ÆäŒ_mŒ)ˆar‡³.Æä0LƸÖ3ºÅ07cz¹h°»pÍîHŒÉûš“Á0íšÝVÀ˜”ar1&‹aJƆéÄ“N[þj;6ž_°Þ³H2%¿ÿe© T€ P*@¨@&°¦›±l'ƒžC’)“µÌBQ*@¨È‘ĘrTÙµ,*0¦q“fŠ)Ê´C¹+ç?~`À£‚1é‚ù¢¥òå2LîbxÁ˜<–#Y÷®+ÞÅT¤ ÝMŒIW¶Û“± Ý^Í.ëØÕTcROÆäšudQº½"Ý‹1Á|CŒ)~s$Æ_+I²¦1¦¬Õ(Ëã(?ŒiàcŠºX%×ßÒƒ,Œ©Èå’ø^*v¼$cJ“^òLLí>'L!“œ‡+&Ë S€&Ë S9~˜ªd˜Lî¾xØ ŸLÅ®˜Þ pÅäøaJ¢+¦ÒÓòtxc²¦_œ¶bÃn±à1cÊ|’Lìå© T€ P*@¨h‚`˜.»úf8Æã Ösãñd I¦&Ô/I¨ T€ ÔNbLµÓ2WgÆ4vâÌ";”ôC#~cúÕyzìMëÃ63 L%ü0Å`˜c tÅdyc*åŠÉƒ1i‰¿áºb*òÆdcLn¨ ×S!¼†bLv< ËSÇ“`LÅ14v\OoL!!bL¹ê[XX*P¤1&6ˆŒ*;Œ ãÂBT83Bœ½íÀïAÐ’Å-aã ^=}/ùé%#„\LLáäB0!¨\‰XrUùa*Bïc1LŽOÑJ¦x®˜ áä0ðÕpr&¿አƒ` *áŠ)ùAå„aZ¹a·i'À:‰)óH2e´Ûf±¨ T€ P*@¨@R°¦knFLs8C0&¬áø}2%µÎ˜/*@¨ T ¤ĘJJÄ‚Æ4fâ ¯AÊ0? ÆäñÀäFù(Z!£’iWòÆ’« ô٠'WXÙ^­+&ËÊ+¢\»Øq Œ)À¢gc û«cb'Dò«1¦üÖ}ÆKžGŒIýsú7œQ£ÏÓR´À-ÙP¼]ÚRŒ.y襂û%0vB;˜6ºƒNO$ã‚#P_¹€©'LvØckZÀícÇ’s|Û•hQ8¹rý0Á’ã1LÅáällßãƒ4šaòcL3ÝËNNÒ¡‡=eÚìw?üLÓÇŸþ-!¦Ÿýâ´¶»a'WL–ÀvšGY“æ®:üÈc·ly#!¹e6¨ T€ P*@¨Ȱ`˜.Ãô†ŸÂóxòðã£Ï<ó¬Ÿ|’aX4*@¨ T › cÊf½Ö½TÀ˜FO˜á±Cm3ÌO÷? Œ©›å~©ÝJå¦%M09Ö%Ø’$9¥¢h±äJûaŠf˜—à 'WQNÂÉ!»bÚ³x•`âq­z)ÂýÒpKš¶½hÉL^L¥&á]4ÁÏ¿`*HζF®ÅáÙõ&Ú(?L†+&£l2LsÛvÍ)$äÆôŒzcr¦˜L†I0¦㦙Պ6ÓÜÿ­\Ýe˜öxìpÅ$¾²ãoâœU‡ÿø˜ÊH¦ÖÖÖC9$º¤ ,ÀýìWLMÚÚÚºtéó`=Ls‚ßv´_ñ¯Xîµx< T€ P*@¨ å* “e +&w•…íŠÉ~<ÍcÃ; ™N>õŒ²H&óAÛxHÑŒáÑÀóÀ‚=aÏ›6mÚ¿?à9®¬g&a¿ »~ÎÇ™rÛ§T€ P*ˆ1%¢Ò— `LÏ>7Ý´@9ã\ÛÓ}ý=ç¼nžàq3Óë;-»RÁ´0©IGj9Â]FéVÚò.,D¦‘H–¸cèn%ktQ\B&ËúS`˜Ö#–œ?œœQÎ '·p³:}¾mÓQk&¤_8AåŠ\1Ͳl7ŽÕÓÙçvóØà>:ðyúG­sLŒ©ÖŠò|T = cJO]1§e);Œ ãBa’Ʋ1¦`€éåâ@r^'LVå"'L«L'L»Ô©‚c Œ%g•KÆäe˜‚"ÊÁ“Ø Pãg•M2µ··Ã ïÒGgR¤I–8Ëêg˜ 0õyYX¬VÙƒN‚ƒñ?Ç`°-?—vÊ™qÙ£“þ=zôÀG/F “[¯mMíQyq*@¨ T€ P*;,†éZ‹a uÅd{еO¬ÇÇ”A2Ƀ :tèàñ´$.Zu'žDðà Ï/xpÐg <5à£NØÐ¯tI†ÿYF«Pj°Ä’>Ýà·ò|äy™™¢½1ÉÓ„ä´°!}ú§}QoL8^–CàéC–dxže´¼ê›VO‹G$ìÄ™å*âÉ Ï2òQ8'Ù/—ÀµÄ]®e2L|œáߊ P*@¨@Ê Æ”² KJv1yH›Ö(@K÷<4©€åñNä8ÇÆ´1€^òº_’@rûQQ¹÷œ09F"'\!–œ’3íAb rÍ@޵랰/¬ucÉÙ¡6$ÎF ä‹ÒÁ0™“é‡É4Üc kÜĘ’ò·g>¨@ã ÆÔxÍyņ(;Œ ãBú7¬Q㯃F‚(izëÃM…qdibÉïo©(ZœÍ-x]*F—"é¥w5žqˆï¥xî—loÿšt¨Zˆ|\€Ér.ŠdkC£ÈÅsÂdúa’Q¯›œPÊŠßvFŠô´…1}Ãb˜ŠÉ)ÄC?:9Þ˜”a*¬uÞb=„X¶Z{Qq¦+&Á˜ óØ+‹M2a"“õ˜|Ç„»ÐEf´?Æ$Ë‹ñNfÄYô¬Î“<“bRÂ9ÉUÄÉ“éoÉ„–ÔÑN’¡T€ P*@¨ T Xƒa²–XXklìg¤Ãäy<±#ŒãðþÁ±H&Æ„' Y!òÀ"+(Ä««>8àHðFXž¡È‘M…ç1Gže´¨¸´<žÈŠz™ÕðÖò•<þ NÉ95‡È²gž–3ü;Q*@¨HŸĘÒWg‰È10¦Ö±Ó RblºÛ6HYÛÅÜ’µ0Þƒ.ÁýÒv+9ÁãŠÇ…ú÷ €É2%(Àä.q0 É‚öâ¥ì…°;ØN˜¬á½ ü±äÊb˜æ´íüÅé–7&a˜lWLÞÅçĘÂZ61¦Düç™ *Ј15Ev^´þ äc¸ÐC#a€¨éîwùu7Û‘’'}€£™ÌA¤ºñ,8ótÇ”2²ôBK!Ü’ ¦\.ù¹¥²/Ù‘ãœñh‘ï%ð8?½äw¿T<`õ ÷•…«`r'¯¶¢È’óLve?Àd’Û!“ -ù·“ƒ10Lf89s­³²A&€bˆÓ7zz,’I–{¦ìãcL~PIöÈT¾ù-vj:lÃÆ •}¥ÛާXëIÐ^–}ß#¥I&Æ$aãÌ•xpT/}ÖÐPnoLžGAŽÌ%fÜjcÂ1êWɃ1á$ ”ÄQ“ÐNŠ1á+ u‡ýX%""òq†'*@¨ éS€Súê,9¶0¦1ÓL ”Çðd¤ºŠá)Â̈.yÌI?®`BÚòn L;ÑÞ6wq{i'Lvh$—a²&e˜t½:,í—Ë0ÁˆŒé`L! l7ĘÂZ61¦Düç™ *Ј15Ev^´þ äczp°—F2ˆw=`=ãÅàác!ö°CÁGàJ~OK®‡Ïr¸%{a«=ýcPYój¡Kþ°qöÔ9NǦâ~É¡ÑKUij1| ‡ìñ=ôRLL/ÙŒš 0E‘+PüÈÿô¤Ô`Lf,9 qC{P†)b­³ëŠ :‹ãÖQÓ–ÿ ”O&1hÿ£N’€É½zc’=þ©Ô û1&œV~./|”0v²ÅÓºÓ½Sý;F^ P*@¨ T€ P(,†éš›±Ž&ƒa XbñŽeí°×j Æ$'÷´ŒŒŽ.W2¨r)`6”RÒ_™@" `-ÃSŒ®£=æ: ó£F‹ÃÙüAåÄç“yœ×Ò_á+¹› T€ P*Vˆ1¥µæšœo`LOyÞZÄꤩ ^{Óû‘è’7xœA/¸_²ÍF–û%¿&ÓHäF‘³ C>'LÖRv˜Ü}‘&{ï˜{Ü@rKnþšö‚eÇX—aaL¶0&¿&YNŒ)¬Mcjò¿—§MT€SÅç¥ë©@î0¦~ vF„2.,Nø¶Ë¯ºº.”L>Éò¨àT ~•\×Ja¬’5±ë¸Y*ò´TÂÙ’ ©Äá–¢½.yÑ¥bÇK½d9. uå{ ñßvÜ/ÙÃV½wüz)ØýR1˜ï “lÑKî·¶“D‘žŒÉ`˜Þs‚5ø¦6»rCÖ:[®˜ä™2Žœºì?:zË–7Âú3$Ž‘H’eÍ2õÒH¢'˜“¬-–ŸÈ‘fˆ1-È1z6|”¸uúÓ `^Q2ÌåËõ¼)ðÜT€ P*@¨ T „q&;œL K_}ç¥W½®˜ôñäžA#"H¦ŒIŸ ðø Þ[åYCäá_ɰdBBW ؤ5þg-¼@Qò’ÀpòX„pZÒËÉÕõZÒN¾Õ¸r|œáŒ P*@¨@ú Æ”¾:KDŽ1 ó|‘Ê ßáØžÄ U –Bâxñ0/ù I²âÝ´!ⳕ6íksR`¹S˜&{•‚íoU’Ë0Á!ÉÃ0Í]µK’0L³Ýxˆ%'SÃDŒ)¢YcJÄž™ MQ€SSdçEë¯@iŒIfî0ßgúM©Æêr…‹.º¨ß …Cr¾í,£ÆmEIœ'E§0V©€+ÙKTÍdJš¶XÐÒK¯¼õ­ï|W-ø‹Óðï:ôÄFÿGG^qý-‚Ï+DÃFL˜§^—~zÒi­æmºÅLq/ >‘ã.½¶÷¥×ôƤ³JÓKßøöwÅ÷Òb7²ÙÈx|—^úÆ·¾+è’•Üq­gtëÆkŸW"„\,L0IªcÚ·íàŠgëÒX“ ÃÔ¶q·:a’˜Öh ®d¥k&]ØoîŸZd1Lß=Ë™½§Ÿpͤk-ÖµÎÖÃÚÝx`˜·ºO#¦” ™ê](žŸ P*@¨ T€ P4* “óœk,¿ÁãɈ9›ñ`‚ǤnýæNYò¦,ã¾®e1OÎè=}äœÍv¤‰Â <âáñä®Q$SsU’Xr|Q*@¨ ¹V€S®«?²ðî>8·ÿÁÏ? <ȘFOõ¤ ÛSßû-ƒ”ÇðdCKEKâ—­ßñ­ïü‹ÆŒ;ñ§ã#ÞÍeðKÖZv%½„=7÷¹·Øf4WMEf¹yÆãé›ßþ®™ž;Û^ÁnyWï„IƒlÀ*ÑýŠ›‘L€ÉÃ0Á ÓI.ƤϽ1…5GbL쥨@~ ƔߺÏBÉeµ¡zE1‹TcR·êfȧ”ªŒ ãÂÉ3j4È$ïÀ“¶f²ähŠ`•ÜIÞ@7K‚. ·$ÃÍο¾°gŸû'®gŸ{±-Ķq0&%è¢ÿÖ·¿ksKض‚ö££žy®xH/ff™‡#ôÞ‘°pÖJ1|/ =[¸¥bzÉð&ZÌã]²0¦5–— 3‰ã%ÃýR»7~œ‹êœŽºÌ>"(Ûw’DÙñAjLÕbL˜†_t°þ÷0Lh+7îÖ§i'ÖZŠ×÷a²kßÂÔ.ypÑ]#V£úÀ0š·Ñ©ÿøÀÂ;ž^%Ë t­3”´:ìl²ôÐHŸL)ý›3ÛT€ P*@¨ T€ ÔI0L—]s³:ˆÕ8×x<™¶ì-<ž´ÎÙ,'ýǽt 'Ž}åââñdäÜÍÇ_=Éz<±±ˆI'b½è—`’©Nbò´T€ P*@¨@j Æ”šªjxFa&€ Ç×a&`LÞhV©ï}œõ«®–&ÃÆ„!·pK¾£Ë¯/ìuû}0àÛºú]ìJ…Èq¶ï%ØŒf.~U†èb3RzIE‹ÿÔN??Cw$]І©‹#ÀTÒ Ó®¸I0ÁBSNÁšc’Æôën{(Œa¢7¦ˆöMŒ©á~^ $Fú›ªSTf$k ˆãs, Ä >•Ê,aiŒ ¿‘Õ‡â2=ÕòXÓ}-I?b*öÎûZ0j,b’N*&“B=*ù\+©S%ÿ†é]I·-ýöWêpS6WÂ6Þáo©ó¯.üM÷+.¿îõÿ)܆•&·$CÒñ3–]ví-gžÓ­ÓÏOëö‡ËeTzÙµ½1*EêöûË10;})—KgœÓmÌ´—Nøù©8[Ÿ{ùÓ5½Ï8»ë ?;õÐÃúó=`êéOW÷>þg§" zj¸ûë{ß}Û]-‡þð¨»>˜¬oOD:åÐy]¯»ÀÐÜ5`øq'ž‚tK¿q¼tÞï.ÃÇS;_ðoý³ß¹heî—Ì!¯>YÒ+˜ÌApÞ˜¶¯_¿H7ëáD`¦º½,†é¤ÓVnØíxír&a˜Ð°ÊYcÉÝ:tù-C—£a-€€¨šk-îùIJÃäºb²ì ½Vì|zòÒCŠ.W·’ñÄT€ P*@¨ T€ ¤L‹aºúf<Ë㉮¯Ç“Kû¿p÷È5…P×ßyhÜ+x<éûÌ*q;·m0¦¢%¶+&}<éûpkDt¹”‰ÅìR*@¨ YR€S–j³¶eŒI’fÆôÔ¨)¦ʳÞ2HÓUíMEá;,hÉâ–€+ýζÉð[×ÀcnÙ6;KßÛý 1!©ï%Yú~Óm÷t‚‰ÁŽ×aÙŒÆÏ½ßKb!êqë=ÖºèsºÁÛ‘Ã^ÐŽ=–=¨`:ýì®bš8o-Ö'ÀÄ#Qä®éuÖ«ÃâóÇ+{v<ñ”Ž?=E¬<=>ÛH§t¾à—ßì$;…mͱì8À˜ào‰S”S¢ñ'T # ÔÙT•XŒD*n “dM=+iNKcLêÊ f mÛ°q_Ë3°)`e»FäÕìø-L?’®ë}·,_¿õ®€ð‹&+Ô†½j$ òaîéÕw =€–B¾Wÿé[ÿ0ÉcɇœÒ§æiÆ¿ÿéI§.µ]âÇy&ÛÐàxiì‚­clÁBç®}ç\ײ•#Áýc^1gs÷ûö|li!^CñZg±dÊõÍ…§T€ P*@¨ 1°¦›<ËuÔs°K¬g“…[…a¶¤ÞO.`ÌÚ îœƒÇ“AÖÞkš?ÚµxŠUºÉÔ©ãñ·Öü!‹'l´o­‰Ñ¸x T€ P4(ŒéÚÿ~ðÁNLTÀ«À=?)xcR·L®g¦N'ÿäÈ)% Ra&'ؘ~ú‹Óf/yUˆ%~›.—„[²íJë%^‡šÄxdaL÷N{a6¦-Z'6#؉à„I¢s<2|¢0­9ðnº_úF1Ƥ‹ØÅOëä%Æd/Që =Öªu× BÈ`½$˜zÞ1ð÷—ß\$gÓP« 1¦Š;DbLKÇRÔ+@Œ)õU˜ßˆ7¦ €D’ S‹“üF~ ÑéR-$¼1ýåÞ– ßžyö‘þ“lJÅ^”NÒ$1à¼iS‘3Oׯ’£X!á6ím0CI¸÷DêСƒøùX^’Œ8%!N’C,Ù¡‹‘d *Ä’õ±ài CÒ·/½¦7襖áqª®]Ž˜qê{ ˆ’ŒP±1tÌl$¡—„µhI\.áÝöºÐè%M‚.)}Q¬?ÎÂ*ÆÔýÊžW÷ìtéёƄ¸ð& $_ãj’¡­›vÎv!}O¼ä˜ÁãÂÜÆÄ˜¶Þþóà§óɤ¦Û¿ûÿyhp«—^²W9K›±V9Ûª^CVã㨹›1¡¾PAS^Ú;ž"àï*p­³ÊÒùü?Þrû=ûâ«TÿÁ™y*@¨ T€ P*@j®Àûï¿Øa‡M[¸Æ gÇ+˜¬õHÝúÎÅâ }<Ábn<˜ô~b9ÞÁ0áñŒXhqϨ5ö“ NÎuÅ$'“_ܱSÎþÚ—úßüÆËÕXzF`¯y;ç © T€ D)ðÄù5¾KÖt&™yK¨wÖéÈÞ1% u»m ´7ÁÀ4bÂ<@K ”`3»¹^¸%è(²+ýü41!‰ñ_ÉøÜbtHtŽ3Îé Ûø^’%î° c²ãÇY Ú‘`_€­Ç²2X†ËÖ0aÞË–¦—­Q=V&`û±Q3-‰õ¡û=‘`ƒ€ï%1ô`²0¦Vc‚}ç‘g¦cše¯aÐ(rà 1¦Š»bbLKÇRÔ+@Œ)õU˜ßÀƒ’:Q‚[%øT2µ(1ÒXr“'Oö{sJ—®À˜n¿g‡:2?â[kÔÈ!EÂIf¼ábDÉ¡”„UÂÈÒ ®ˆŽbÉeä±oŸ<ÒŠáæ§­HpÖÐÓ&–.»¶÷¥×öVbI6º½@ôÀ•0BºdzZB„8‰†Iý‚>eCK —dx ÄÑâ€+ÁÓ©‚1YCUczâÙYÇŸxÊu½îRâ1ã.¶A{ñ*ô=ü-÷ÛË0~•'¢Ø#¾—0–ÅG8Ì„áìó/¾Žqm^*B—À09þE‹Ð¥Â0× ‹V–ï%?Ìc1nZpD¹ºÝ>ýôÓÎ;zrŒÃÃ9ôR`ÒUάáÎgVÁBðÜ oرäö Ž<·îü;fK¼¨m3a–¤æZghÒí×]u}¯Í;?B"É”®>¹¥T€ P*@¨  P`Û¶mˆˆ1uÁêâÇçñVcŸžµ Ë*†ÏÜdÅ’[ÿöôeoác¯'–ÁbÉáñŒXe1zþÖ‹¶0cH´ke˜Ž>á—CGLÀ³ÉνŸ|ùZ4 zës‰º=,×'»<+ T€ P*@*RÀTN8¬™ˆÓaýxëäˆeð0Hqö:Æ3“»’YÖ3;&8^[À?8¸Cž™„m]ú¾Ü¶+© IlFسÌ6!ÁëX(Xˆn¸åî3Îî*¢ÓÏîz}ï»%‡ÐK’Ô÷’µÁ¿ëÏã£faT?~Θð>mñfO91÷`B¹13WÓØw~uá¥]v³».}‡zc5­6Ę*j…Öˆ1U,HR¯Ÿ¾S_…ù-@KK‹¢K=zôÀGS‹ÒAåð‰H‡¨¦T iaLw  Z#Â>w[£F‡¤ãÅ¢£C&EÂI”’=ÃëIb\+¹ŒÂ`$ô¸%$‰„^‚mÛê{ &!Xˆ$‡¬`GêÿÄxµ a±:ìçþö2ØwÎýÍ¥ð½„A>V­‹¡gp«å{ öˆ›ïˆŽítòÉg^ŒÉZ—î®aðÛeˆ1Uܦ‰1U,HR¯Ÿ¾S_…¹.œ( †ä÷¦TcåÒ0I)€1a\æ ûñíé]Î8ÀüJý9>8ÉáMJÉÙ¶ý* Œœ\L~êÂu~bI†žfV iôó/I„8Ó ¨º]ìõJÖ®A-ï ’ÄÞ§ª§P°bC-é|‡ŠË%IÖô´,À0N3ÇŒ t¼d 8ÑøQœoËŘd2}ÇÆW‚^ß¿uØÐb’é‰1B/™“:a’ÕêëUê4fþ–CWÃT¯ÁôÃ$E#É”ë{ O¨ T€ P*@ÂpH¦y«K>žL[ú¦3)¦Aª`o XoEˆ3íJÏ/ZWdTrmIºâ=ÀrdÅŒ+ gú^’Èq¦ï¥‚1hMÁ¤6 5ý…Ú(Ùð„‹˜ä¡€SÅÿbLKÇRÔ+À§ïÔW! p°½½Ý¯B\Œ)úcúó]ƒüÎt¾Æq€í6I’1p4·]8©¢$èRapé8öT×J#ï’ò¸’Ã-Ù¸R0±dx -¹Ü’I,ÉvIn©€.­ B—¼ãv5 ]2ñ¦Ê0¦m»÷[ÿ<¢€a ˜^ŸÖºzh¿Ï؇¯]m >x³<—fB2=üøhõÀ$“ÕB\³Ÿ=_¯.ÄÐ~Ž‘`µá‡©8^CÃD’)ÝKA¨ T€ P*@j®€L“æ®Ò9ºäÆóxb¯ävVo˳dÄ ¿¦rI&©(\¥äó«äÌÿºÞ•âàJ>–7KÖ`T’ÏÓR8´´Ðžhö$¿¥Ü’Ïå’5À ÉΆx]*ÉæÇñ·}LU“ü§>ÿÔóßÚ»¡mr÷Ž ™üÿ9ìÇ·åöF ™Î:Ë"™-Â0 ”aj³¬g×_k4ÃD’©Ü:âñT€ P*@¨ T ' €d:þ„&ÎYå,®(^_á:aªÃ3ºÜè.‡àÌ¿hlRNª&YÅäDj²êƒ¹¡T€ P*@š €…1 Ÿf‚í ©Óºœ¬£d¤ Óá.w/pKºþÙYíÚBÑ¥âÕìž—¬ØÐAôRÑzuÃýRy½1UÙ@‰1U) NR¬Ÿ¾S\yÌz”yÄ˜Ä ’&]çVŒ;Ÿoî‰Ü~ÛtžTp×).”‚))_Yš¬R¤_%fúU*rûéÕŠ£ááá,¾¾,hÉgŽYôÞërÉË-`ŠF—ª'“Ê:C 0¦âÿ<0-}¸’¸bÂ4:¸%¬–£0·.žý؃Ã"§Ÿ|rò©g<ôè³æg& S°ÐÙFǬ¥å0LŒÝÀ[ T€ P*@¨  lÙòÆÑÇÿܬ6ÿ㉳¾ÂŽs-'0~X!'ìåÚX¨-„ºÄ"Ú“údÚóžwõˆ™1LX1" ¾ð`¥<“®$ñì/ùƪ¯VN¤V« O¨ T€ ¤^`Lƒ‡O ÊáDç0 R^c“e`ZïMEv%'FG´äá–ÜõÏ^—ÄšàÄa.e·#Ç…ÒKÖªuwÉzÅî—<Özcª¸ÑcªX:þ ¤^>}§¾ Y€`r‡1ÝÒo@12y#{ßcòKî Æ’Qrù¤°Ðo‚(EƒJ×JÕàJ!Ä’L.û’™œAª;Nõ°ö·ä‹ç÷·T’[j€Ë¥°©æ¢€UÆ„EwtGÂÚ_L#fÒ±?"öÈ~)aæ°_vâ‡a}•LyÖl'âdËyä@r>#Ã0¹Ž[ãøa"ÃÄ; T€ P*@¨  É4~V[ñ㉓BÌ!…8×õe˜°€dV.HëÇ´Ïd>[ÉJ}§¾ Y€`ò‡1õaÔxjçó=N8eŒèO&{kû+øWt2F™Eaà¼~• ×JžÑg`èâ’±á áá OK~gK:T56Êö·Ô\nÉ3z®9Æ„ÿ™L”c2Óèò·“@˜R¨$3æò&Ó‘0áŽw92z]H¦†Œ²˜6˜ŒUÎÃä.ð.t&ÃÄ[ T€ P*@¨ 5U@H¦q3WЦÀdúˆµã\×Ï“H©ôL"}Ó¹’GbŽ1#Íá­‚Àß52£'ãDjF+–Å¢T€ P*@â+`aLÃ&FØ›,ƒÔYçÛ«ß½N•<&'¿]©Ø–T -¹ö£‚µÈ]fPà–Š—µÛô’….† £—,«+vX©:z‰SüFv$1¦ê5ä¨@ZàÓwZkŽù.¡@î0¦Þ}D GøöԳΠ8 ~ N*€ðÎ$¯Lõ:¾6’R”^¶–±J*nší®aÉï`ÉÀ• £Ò7KÁž–ÀÚ—†–\îÞ¿Ön[¿ý«šcL:Q.“é’ÄëVú‚dÂ~¸_ÂNqÑ„ãñ­ydô_VH¦ûÒVáD‘s&ÇBàÖ臉7*@¨ T€ P*@j¨€Lcf¬ð>ž¯¯xv,9ÇÂQ“XrZ!–ðÏ\òl%ΖÄE®† }§µæ˜ï äcêyÇÃ?0·5Fà|UÌ!©Ï¤ž“C @”Ì®ÈÁ’+KªÖåoÆJI×õiB¤9Þu0þˆ²,X¾ÂG9I¼4Å|9$Ó xðZž]ˆÔPXèL†)¦ž<Œ P*@¨ T€ PŠ’iäÔe…ÇY_a’Û©’5÷Ä «¿[l`’+qÂ$!ääÏ3—)Q¿ùª‹œH­‹¬<) T€ P*&€1=üäs± R–¥iwXPŽèEïq9Š %¿¿¥Ü’»ŽÝö¥ÚÈDŒ©âöMŒ©béøC*zøôú*d‚ÈÆtó_úGŒñ-0¦¸ƒE@H’l·ù1“1¦Ô¸oÖrUOòŒ2ÃIù P©x *îyrŽ+… µkî©‘=Lw ¡“¹ÊYŠÜí×]u}¯Í;?ŠH;÷~òåW_52ç¼ T€ P*@¨ S@H¦S–…=žÔƒaʘ†™*'R3U,  T€ P*P‰À˜ú?1¾¤AÊ13•µèݵ(’ŠV¶»±8¹%3Zœ†n$ºd^‹S%íÌþ 1¦Š¥ã©@êàÓwê«V wÓM·÷àð-0&ÿAì‘BH®«$Ÿ·$“LŠÂ’‚=yzø$ùh»S ¡”¼ R°k¥¢xpÙó®Tîð:ÕþÓB2õ8B&O…’abÇO¨ T€ P*@¨@Ã’é™)Ký'd˜V I¹'R“RÌ T€ P*Ð4€1=ôøx½É46Á õË3Ïs÷Ø9|q9BMK^\É0!¹+Û½ëÛWH¸gI;$•kR©ëñĘ*n¬Ä˜*–Ž?¤©W€Oß©¯B€ÓÁƒ]tÆ…JùÇ7bÔxƹ±#3Ž›»m×ÜàAd œdñI%¥J)¨äC[ê:ÊLÝÉÓŽ1)ÉÔ÷áVød˜ØëS*@¨ T€ P*Ð`„dzzÒRóñ„ Sƒk!—ãDj"ª™ T€ P*@š©0¦aoŠ2HE˜\sR1®TdB²‰%?´”ð•íĘ*n¯Ä˜*–Ž?¤©W€Oß©¯B€“1ÝØ§¿íÖ(8áÛ_œqnÄ!_Y£Æ‡TÊg’Fy ˆõ2I’;Ê,kaòÊË'|è™d¶)“’Lw$&vùT€ P*@¨ T€ 4E!™ð¨%O‚d˜šR Í¿('R›_Ì T€ P*Ðd€1=ðØøØ)Ÿ™ÉG)X” C’ÇÍ’?zC’-5’7bL7YbLKÇRÔ+À§ïÔW! @ŒÉƘzôyÈC™ñí/N?7â€X’¢H!LR™TëÍõçI>©Þël`L’‰ û{*@¨ T€ P*@š¨€’Ld˜šX M¾4'R›\¼< T€ P*Ð|€1Ýÿ踘)g}{¤uÉ•|æ$›Ê@"ÆTq«%ÆT±tü!H½|úN}²Ä˜lŒé˜N¾ðâëÃÒÑ'üò_¾÷ýˆB¾ºî‹c¤?^wá¯b”:Ÿ×ý¿ü×ÿŸ¯ýÃ7FŒ›¶yçGš¶íÞŸÀåÀ'Ÿœ|ê'œtæU×÷2sëßÞ¹÷“/¿ú*E`–¨ T€ P*@¨Ȇ ™Ž8úð#Žî4tÄ„èÇ“=ï}š"³E p"• ‚ P*@¨ȽÀ˜°l¾ƒT¨™)9&•ºæä»ßûþÑÇÿ"â0á}n7ÏóÅG>Ï}[;HŒ‰m€ äW>}ç·î3^ò/_qñ,XЧøàÃL¿ûãågÿº›g'?fX˯¾ñ—§U²€«6ìH>ƄƒiHï+È0åª[ca© T€ P*@¨@2ùÂy—?ü?É0%³vêž+N¤Ö]b^€ P*@¨Hº% R—\q R¦uj@“h{gÍ97ˆ1áŸ@Œ)éÝóGê§Ÿ¾ë§-ÏÜTò…1ù¥ŽžQå·T Pdzc²š÷š‰_^ñŸÛß|3¬â臩©ý-/N¨ T€ P*@r¤ÀÂí Yñà$ìñ„~˜²Ü8‘šåÚeÙ¨ T€ P  Á¥ cBs$ÆTá’?£P€OߨD!HbL…Haõ?ñœ™T ¹Ó‡¼¤Ã—c®m7ÀT@†‰w*@¨ T€ P*@¦0¦ÇÚ:ü틯I&2L «ˆæ\ˆ©ÍÑW¥T€ P*@­@&Í%M/1&bL‰þÛ3sT Þ ðé»Þ óüMR€1&*P¶ ŘÖLÃd¥+þîËÚ=$¦&õ±¼, T€ P*@¨È©ïºq×G Px?ÉD†)ûm‚©Ù¯c– P*@¨([¦?™Ì1&bLeÿù*%øô¥ÚdY ˆ1•°drœÇB•¥@B1&Û““Æ\ûåW_)ÉD†‰Ý> T€ P*@¨ õS }ûþ¿î8¿I2‘aª_E$èÌœHMPe0+T€ P*@¨@R(Ë Áƒc*@Œ‰SRþáÌhŠ|únŠì¼hý ÆDŒ‰ ”­@1&uÅä:d:øán!™È0Õ¿#娠T€ P*@¨@®8dà!%Ë’iÇ;È0•*#p"5#ÉbP*@¨ µT &—ÃÃÊR€1¦ZþKy.*:øôº*c†ã)wŒé¯ûò“ϾˆHø[ôü6c |üéߢ …fïÿÕÀ£LWLB2¹—É„ÔÀ|ðRT€ P*@¨ T€ äK~/ôÆÔ²¢™&¿6¹um+¶l[€$Bà£l \öÆ1ù(Ÿ¥åDj>륦T€ P*@"(i*i›È˜9¦dqâÂF¦¾vÂcmvü"Õ T w ðé;wUž—çcÊK=³œÙVÀãŠÉpÈ”ír³tT€ P*@¨ T€ 4]PJÝ'wß´o¦ŽOu¨€ {c_Mø G¶µ·aC¿jzæ™z)À‰Ôz)ËóR*@¨ T€ P¯ĘØ&¨@~àÓw~ë>ã%'Æ”ñ fñr¡€ß“á) °T€ P*@¨ T€ 4I³{ˆ¿% K`˜$`•Ú÷·cC¸%NøV¾‚7&=¬IYæeë¯'Rë¯1¯@¨ T€ P*@DbLl T ¿ ðé;¿uŸñ’cÊx³xÙW Ð2e¿âYB*@¨ T€ P*@)UBV]¶x` ÄR—Ñ]ð-Þ%i˜¹D€™¨‡œH­‡ª<' T€ P*@¨R€Ûȯ|úÎoÝg¼äĘ2^Á,^¾˜Òç nWû¶å«Ô,- T€ P*@¨ ÍS@‰%ÝL’# !WLpÈ${°½ÿ¯û›—_^¹! p"µ!2ó"T€ P*@¨ T cb3 ùU€Oßù­ûŒ—œSÆ+˜ÅË—ĘòUß,- T€ P*@¨h¾ —à] èÜ,In6íÛ„p„xsÂ3d’=8F£Ë5?ëÌAýàDjý´å™© T€ P*@¨@±ĘØ"¨@~àÓw~ë>ã%'Æ”ñ fñò¥1¦|Õ7KK¨ T€ P*@š¯ %$äÃô±„=iNÞñjßߎm9’¯ì+À‰Ôì×1KH¨ T€ P*ˆ1%¥&˜*ÐxøôÝxÍyņ(@Œ©!2ó"T 1 cjŒÎ¼  T€ P*@¨ T€ D(À‰T6*@¨ T€ P*Ð(ˆ15Ji^‡ $O>}'¯N˜£š(@Œ©&2ò$T  cJF=0T€ P*@¨ T€ P\+À‰Ô\W? O¨ T€ P*ÐPˆ15Tn^Œ $J>}'ª:˜™Ú)@Œ©vZòLT é cjz0T€ P*@¨ T€ P*À‰T¶*@¨ T€ P*Ð(ˆ15Ji^‡ $O>}'¯N˜£š(@Œ©&2ò$T  cJF=0T€ P*@¨ T€ ,Ü~ÑcmœsÈkCàDj^kžå¦T€ P*@¨h¼Ę¯9¯H’¢Ÿ¾“RÌGà”båé¨@3 ÆÔLõym*@¨ T€ P*@ cÊukàDj®«Ÿ…§T€ P*@¨h¨Ę*7/F¥Ÿ¾UÌLí ÆT;-y&*Ðtˆ15½ ˜*@¨ T€ P*@lˆ1åº!p"5×ÕÏÂS*@¨ T€ 4TbL •›£‰R€O߉ªf¦v cª–<h®ŸzðÏÿv·«}Ûš›^ P*@¨ T€ P*@Œ)×m€©¹®~ž P*@¨ T ¡ cj¨Ü¼H”|úNTu03µS€Sí´ä™¨@s½„{Õ€“›› ^ P*@¨ T€ P*ˆ1åºp"5×ÕÏÂS*@¨ T€ 4TbL •›£‰R€O߉ªf¦v cª–<h®‚1!®_T€ P*@¨ T€ Pf+@Œ©Ù5ÐÔës"µ©òóâT€ P*@¨ ¹R€S®ª›…¥E ðé› "£ cÊhŲXT€ P*@¨ T€ P*@š§1¦æiŸ€+s"5•À,P*@¨ T€ äDbL9©h“ (ðÿgïO å¨ÎtM˜î¿‡ªÕ]·ïß÷ïUU]¶Ëö-nßÕUEácd—'fmflcËÌ3¶0 FƒBLˆQbš%40‰£Yh@H$el¶þ7â‹Ü¹3"r:'2OfÆsÖ^gʼnŒŒáÙ‘ybïýìï£õÍmÑ¡И:´b¹¬%°{{÷ÄýT>xs]ì_›“"-É^2WÉÐØzm©õZp TÁqÍ€ @€@SìþÓ¶{—üUªÆ´âíáM9ÒèHmzà, @€ò@)µÌ5B ­oîŒ%€ÆÔ¡Ëeu"s•teI!—$-9]i÷ön[¯ßæ3½1o¢6°5d”ëÄ›‚k‚ @€@kH ÈD(¦Öª¤&œ ©M€Ì! @€ @câF€@~ ÐúÎoÝwø•£1uxsy€ @€ ¦H ÈD(¦¦ño•Ñ‘Ú*5Áy@€ t>4¦Î¯c®åÐúæÞèPhLZ±\ @€ @ /Ä2Š©/*¡¯IGj_×LJ @È4¦üÔ5W 8ZßÜJ©C+–Ë‚ @€ ôX@&B1õE%ôõ1éHíëàø€ @ù!€Æ”ŸºæJ!'@ë›{¢C  1uhÅrY9$ð§÷¬›³gǦ^:— @€ ´‰PL-U/Í;:R›Çš#A€ äSÞï®?Ïh}ç¹ö;úÚј:ºz¹¸\À¤ÿU“†æê¢¹X@€ @  ¸€L„bjÁÚiÆ)Ñ‘Ú Ê€ @4&îä—­ïüÖ}‡_9S‡W0——#hL9ªl.€ @­N@™ÅÔê•Ô¸ó£#µqlÙ3 @€J  1qG@ ¿h}ç·î;üÊó¥1Í™3ghÅŸK/½ôg?ûYåmxµœxâ‰C† ©|!›6mj³OÿŽMSÞëã'†´Ùisº€ @€@'è~wݘ§/èÄ+ãšj @Gj Ø€ @™@cÊ#;@[ õÝ–ÕÆIW'/éä“O>èÃ/ºdˆ• ýrñ /òƒƒûçÙç‹/S¹ Y^vÁÀËÎ/SÎxÙy N–s/• Ÿë•s.ì•Aç\•³/”,g?(µœyþ¥Q9ïÒ3½rÆy—–”s/=ãÜKO/–KN?·XN;ç’Ôrê9—ål¿\|Ê٥嬋O Ë/Ë”g^–~ùÅ™£rÆÀ_xåçg ,)§üù驜œV~vÚE©å§§]ôÓÓ.üé©ñò“S/tåÿ›ÿÔÿ¸_þä” OŠ— N:å‚“~yÁ>_Ü_’SõP+m1zôè¾ù£~ðí?þ¸•΋s @€rG`çÎ_Þó;S§NÍÝÅsÁ"@G*· @€šE©Y¤9Z­ïÖ«Î(¹Ó˜†ß>jëößo‰Êî-ÛKÊÍ·:ú¸“6¿»ÛÊ[®¼ó»·ÞùÝ›®¼ý»7J˦m»\Ù¸mWPºƒ²!*mØúÑë^Y¿å#W^Ûòák›£²nó‡QyëõAù@eÊ›QYýæAy#(¯¾±3*›v®òÊÊ;Wn|ßÊ • QY¾áý ¼®òÞ²BYºþ=W–¬oÉúK^ ÊbWÖíè*–í¯¬-–Ek·/Z•…kÞ Êêw_öÊ‚Wß Ë;*/©¬ŠÊ‹«Þ ÊÊ ¼°òí¨¬xûy¯Ì_þöüåÛTæYY”¹^™³´Û•ç–t»2{I÷ì%[g/Þ:Ë+3»¶Ê–][þöï?=vÒ‚¯l™neQP¦e³ÊÔ…›Oüåí¥1Éa:òG'¨*GÜûøQG…É”É÷#; @€z@ t˜ú=þÌÜ…«ºüî!˜L=`Øöo¡#µí« € @hhLmSUœ(2'@ë;s¤ì°5äNc’¨ä,¥äÂM·S`/½£Rª.ÉaJÚKoÿ..0…öRSÁaJL‡© 0ÉdÊÀa 4¦¢Ã$™)®1…SQcªÓa*§1¥8L¡ÆTt˜V–:L+ä0UÒ˜J¦¥1‡©[S‰ÆTt˜$35¦T‡©5&s˜T³ªMÕÝí˜L­ñõÊY@€ @ ‡ä0}åkýÆ=3ÏÚ› VnÅdÊám@4¦ö¤x¸ÒK ¿¥+dŽ«{I‰äÖ«ÄRÈ¥E`ª"0Õ”H.Ê%$’+ä’‹É…ScrÉõÐaª#\˜Q®l:¹x(¦ S¥PL¯l1éAÓ˜JÓÉM ¦6J*g“ªÛiL$P@åþ»õnL¦†|i²S@€ @ •€9LãŸ§Ìæþ,‹®uÛ_X¾å[ß9˜ìr9ºsèHÍQes©€ @}L©+€ÃC  ÐúîCøº‘ò¨1ù–Ò&)Jž¥tã-Ò˜NŒç‰sÞRR»ÉdÝåê=wZ’þÔ)G69X=ø‰,‘œ~4KXÚ€…JÒJ­‘d{Ó^ÕJ[ÐÐoÛ¾0u,Û³ÖÛqmcûm“ûqbSû|Ór¦€ @èLr˜¾úµ~ONžη)›ðÚͲPóä¹®7¿QÉdµÔXжBãEñ“¬A¡v‡ ïjo·iö’š$Ú‰Z%®ybRlâ„iLjªÄÐZÇ '½Ë5U´¥­±ý¸HNÚ^'f (ý¶íÝ™ø·ˆ­l㛆ŽÔ6®Ý™tèw2—@€ ö ‡Éw˜^ šœQ¤ØBÂk›e¡É-ŠÈ;sÑý¾]“ÉÓ˜,–’~L9²æF²ñ¢ JÖ/ÚÆiL±6Ej›¥–:°´îÇeÁ¶Pµ®Md‡¶ÓpiéÜÆ–ÂÛ¢4Ù[,n-'ÐÒÛБÚÒÕÃÉA€ t4¦ŽªN.u õ].6n¹Ó˜®½éε%éÞ$$Y ¢(éÕþGŸ`Ë~Y“È秇‹,Y¤¥ 7œ•¯ÆJš´Tˆ·”ð–ÊG]Š©K–PÌ/å2ÇÅb/¥ØKa22+Šù•Õïjâ¬+šA[(ï,xõ—TVE% ¿”H!×ËLJ'—šE®$S,‹\™ L˜,‹œ4¦1øá—bË'þò‚s. ÜõŸü¥?Ú~¦(YCíƒ+ÞVª¾¹Ë¶]ÇÃU³Ë¹N|›OìkLþlãÔhLþ€u¾×®19¶æK¹pM±N|›âÌ @€ Їä0}åkýžp¹ä¼l×jœé˃¸¿Ûâ·N®ŠÉfY(“øŒ…5™LÉhLj2X°Ø 5d,’k\¤jLÚ¦7“Ó•Ôl±ltnâ‡ÉEx²H·ÚÌÚY.“µ³ÕÝ™÷a÷öÐt¤ö– ï‡ @€@­Иj%Åvè<´¾;¯N¹¢@î4¦k~{§o Å–õª4¦²ŠR‰¥TÆU2u©Œ±”*-Eñ–ÊzKïWõ–,§˜²Å¹ô[)Iô#WÈWÁ^²a‰ÛK5†_ ºªÃI·ê°ú¬­TL!×I“Œ¥¶Ó˜<‡)J,¸<Õaª8H0wé6!½nD“Éuâ«K]=éJ*§o ’LcÒ‚VÚK±hL¶¥¨_>– ¡B4&õþÛž]·¾[˧€ÆÄ?/@€ ô-¸Ã´á}×< §‡) ÅΊ æÀ¸PL…YjžL{yÓV‰ÉT5©œh$/¦1©‰¡…/rŒ¬¥c™²]§ÜÔ‹ZÚ6ãB{³=kÁ2kë|th•LNRcG§ášT¶^Û«I¥Í´ÞO¥ÆÔ··7G‡ @€@Û@cj»*ã„!4¦ÌP²£Ö"P“Ƥž8SÚýçä“OöÛ;½€I~ð¤`yØoïèÿãR)¥ÅUJæƒKË Wf)i,)I\Iž¸ ï¾âç-Mœ¹èì‹.×oriÂŒEg_x¹~Þ’§.uá+=5{ú ¯V¼¤Þä¹KÞ¸øW×/dÏ8ÿ2+W\ç˜ñ3á— öR-á—ªæ«&0=—]¦éA¦(“ ¹Ô^SÌaÒÁò׃\r×?²ì×£_ùõèEcg®vÁ›n@ªÖÕc?5S”¯Á$óñm½öö‡*Ädò;Í]ß½zám2±´R_úZp?¶Þ6Ðof°/ o¶}l¥¿gõìûÓŽíX±ïŸZ†Úý›Šó‡ @€@Ëp“K€î;LÍ\ÿëûýêþEÎxÍæÉ¨i©†ØÕ-—ðZZl–…Ò…OY°±²ÉäÚnÁÁ©Ðx‘cd ½ËotX‹CÚ³£RÛ,5¶;$EiK5d¬¥£F °dõ›TZví›bo±3±`N±æRËÞÕOŒŽÔêŒØ€ @Ù@cʆ#{@; õÝŽµÆ9{Ì:H"©®1ij &ªOͦ-¶5Õ@cºñ •äŠï]}ãGýøM¹å•å'¹ò¾:pý²B¡•¬„–’+€â—׃HK~°¥a7üÌg?oÒÒ-w=ü…/MÒ’~kYÒÒð»Þ÷K_“«¤ßÃG>ä‡\úÌ?~þÌ †¨üdÀYZ5vB,g\à¸x9ã|bÖ¿}i?—6náêw?ýŸ?ñçgž~þe*‡ÿèDýY%öR2y\©½f (~éÿ~°rœei·:¯]ñ&õh‡ekIþ¸Å[gÕ‘B..0™ÉÔcé“?¼âíáÖ|­i9LGþø„ÀnÝ!G™zÑ/Ú Á‘C¦\~ß"Uè˜ië¾uÞ„Ëî]øËßÎUqùÜ Á¬Å[gvmv[%“©iWÇ @€ 6"`Óøgç¹<×6ŲœŸ4l–Šš'ÖB9õ¦yr˜F—¶PÔH´„×|×Úz“_Úðõj1™Úˆ§ #•û€ @Í"€ÆÔ,Ò­G€ÖwëÕ gT; HšKÍdo¯¢1Y`vÛT³-(zûþHcºú†;J $ßFÚyõ #L©\ÊYJÉÐJ‘´”ЕÔÏëŠuøªÌ|iµŒ%iL–$nß/íé Æ‹¯Ê[’´¤ßOÍX¨Å[Òr——0Nê’Kg>“%{bÚË2–T —Þ?uÁOÌ9æéûâ~.ä’ä-7Ó©Kzuèuw(ì¿Êýãf¨¼(o)T—Tî{|ƣϾ8sáͦÕï/o.£rïc3œ½tÏ£ÓU¢äqË·=4ñÅ»™þä¬eê°Ö¿~á«c'¼j/…ƒÂ²8.0É¿ñÊ–][f¼•é¯l Ê¢ ¸ðK–B.Yz 1­Ûüî²î›Ç.ÿ»Q]{=²ò³Íù˜Ãd>œ Âdw‹n iLãçm´z7gÃC¦¨O¸zæMã–«¦T5‡ž2~îÆ’A‚%Á ÁÌÛÕ·b25§9  @€:€9Lãžç" [«Ö°×?²ôô›ç«•jSh4ÅâˆË¦(êRÔBYYl¡˜Ãd¡˜l–…š'ϼ°áëßúÁ„I“;× t¤r@€ @ YИšEšã@ õÐún½:áŒj$ ˜åЦdÇR6iM©««K”½Ù_®ñØ­¶™4¦«n‹äÿ©WüÑ ©Ä)¥Uòã*ù¢’ëÛuÆ’¿àÒÃÉLzø©ÙÒ˜d¨ÈUÒBoiÝŽÐRŠ~›½¬ E%+’lAýÅGüèÄß\§¼¥“~q––•'îÀï¢HK ¹¤eùIŠ·¤ß¦1…Þ’Ê;¡Æ4ã¥0gÜìEõçˆÑOˆÙç‹ûpò™*ßúÎ!2cT´æø“Ï<ì‡'ìó…ýä-zî`•ùaì¥O}æóó—o{xÒ‹²”N9gСýOPQÏõ/Ï–õ[ë‡Ý2æ¼AÃ>õ™Ïé·MÀu¥œ½T~i«o/©¿».©ј$0=·îº1KþV“•æhLÃô£ &\ä½ÙÝ!¡Æ´ÁrÉ]óÐÍuVUj¨à‘Ù냚ZhL÷L^Mt.$49^WÝ2¶Bv¹Vûür>€ @€@_¦ýú{fž›_á‚0¹æ‰²];‡IÍϰ½ùNÐB™´P4ãåðÁ“ïy¶ÐB)„b²Yš‹2ñù×÷Çdê« Îü¸t¤fŽ”B€ @  4&n ä—­ïüÖ}Û_¹ÒÁéÇ.C 2™üKªžTNј,Þé"3µ)iLWÞ0"EH ¢%ùÝ®¼^Óñ–è-–î-©%ÅÖ¤*Jneä*­ß¡ÞX1WI©â.zýâÐOÒïTiɹJÎ[ òÄ…‹^:𻇪(Uœ–rI“_/¾ü:ë;3~¦IKzé¹W6Iv¹aăZ£>åÀ[ Õ%½äŠD¥ÓλLQ—.¼ìZéJf/I]’®tÁe×jÁb/Icºç±§œ3XÆ’ì%Eý‘ƤßJ7dØË'oÉb/™´4åÅõ*Zè÷íƒãöR˜<.–?®žðKQþ¸iiá—b™jŒÆ”˜š¦1ES!jWñF ï»C”¦AåÄ«g)“ÉÝ4n…*ÔÒÉ©¾î¼ö›çN4jA,_ƒ$0&˜LmúmÆiC€ @ iä0}9p˜æÆ‚ [ÛV-5O9˰䖥™´dÞ’~/ Ê»*úSÆ’IK7Þ(JZ¸sÌÓŠÃd—LZÒf‘º´êEW²œq–-N/Ýÿø ©K¿ºöŽOýãç'>·\*Œ¼%™I®|ó;‡hÍ)н´\±—¶É^RÚ8ýV ’Ç- 4&S— oùœ¢.)Ó¨G¦…+?'{éÁ§_À¤?öRÝöR2\ ö’“™jј†Ž<ÈÀäB1 ‹£°L%+ ±šz¿ò—×ìuÐa?Œ‡ìò&K$'‡I¹äTûªk]šL¦©/¿¥<ïöŽ¿jæ¹·=¯òàô×,äÕì(\¯!Ì»W̵'“éÛßùÞŸÿò—¶ÿ¶ã @€ ¬ |üñÇûìûåÇ&Í-i¡&kÕúÍ5KÍaR E“Ú•®…rÎmÏ?0}¥“S0H'ׄ×õ›'2™¾¼ÿçßùW½oXuÞ_õß³®Þ†íŽÔ†¡eÇ€ @ˆ@câ–€@~ ÐúÎoÝw•;ÖL$-¸ÈLvaÕ5& Ť-¸ìtmJEј®¸~„g…ù¹¼¢W¥1•³‘ÊRªj)™«ä•íÒPü”pó–¼qæC¬H':ã‚!Ò•öýÒ~Sæ¯2iIË2–iiòü•æ-IK2iÉŠÞe Š´ôÌÜ•¡®¬¼cÌÓò–î7CÛ[È%S—&ÍY¡KÀ´2(êY–ºtßã3,ð’\%Kš/«‹½¤œqOÏ^þôìeEiiù6å‰S¤¥SÎ$QÉb/ÓÒnKÃïyB}Ó*˜4Ñö®‡§Yì¥s û—}¿*¥&Иoå—® Û+[üäqQ渤½äé8±Kþ¬Ecºà²s§¬9óžÅ)½çc–ýç®­CW&½|Þ׿ñÅgç,q“›]&˜,‘œ‚0=þÜëVé ©¥A%k˜¼àMåà³àX‡ ž<á…M%ƒ¢ô½Ã޾þæ‘Ýïý“©M¿Ù8m@€ 4”ÀСCO;ç×"öš'jçFÉÍ/¿o‘ò\—­ÎÃ/›2øž—Ÿ}éMµò‚ʲB ¥˜N®0Ë›”rÇØi_øê>οêÅMW5®ÍÕŽ{~bõ¾³ZÑYÔ,i²/@€ T"€ÆÄýü õߺï„+W@%» å…“Éä_Rõ.0 PŠÃd1™œÒÔ¦TéºÛS¬£B´$½zø/Ù 6É‚'¹øI 3©’¥dÞI¬¸|p&*¹ÄU E¥3οìˆøÀø™ú­euŸ®Q†8ýÖr¡ƒ8°Xô®Óϻ̊Œ¥N>Ó¤¥ëoP“ÃiYÒ’ÖkYQ—$'Ic2i)(+Þ–tïc3,[œ%Œ»`ðµR—öùÂW¯½uÌ݉᮹uÌS³– ·Œv˽E“òÇit¥cz†â-I]ÒKZ#uéêáÚæsãg,=ø¨ãùé#šzî¥Ã´,{é>ó¹+ohL¥ö’¯.qƒ¬,ŠÊ´0Œ•Ú¥¥ä–µhLç\8xý–V½µ>)3=²ò³þlÚ´éÀ|æ¹%Þ-W˜Â@\ïqÙ” F¼ YΖ¦AƒªÊ[6àÆ¹ÎxíŠ1]Ç]9# Åêb–N.Åä ˜Ã¤+UÁdjtµ²@€ ´)™L§ž}IJó$œb´aW-”®žyÓ¸åÊ%§Ê7Ï› T×7X ezÔB‰GŠ- Å$‡i¿ý¿±xõfk¡ìþÃ'mŠ«§=÷“ј–}B€ @ Ý  1µ{ rþè94¦ž³ã}L@¹ä$ IC’ŒË(§3«®1éý²ŸôÓî“®VÓÐko¯` éÕÃx\*É/kK"'¥:Iµ[J¦+¹dpf,Y>8+æ'Y¹âú;e, ¼ü:‰JV†^wçá?:ñ¢Ë¯UŒ¥(=Ü«Á<×Óλ̕£Ÿ¶ù‹>˜»ÿ´mé¶k+B‡Í–ÕÐ/ÿôIDATGØL¦ 3Û LÎar#æ0F ƒ–K.ŒÃ8LʼnÎå&L¦¬*Žý@€ @ # ÈdúåY{ÍoŠ…Mªñ¦XTq˜ ¹Â+8L©&Óĵ×íXבx+\SÞjœë… @€@ИjÅfè@hLX©\R@ wÓ¯†Ý–ŒäÖèÕCûWaƒØKiZR”ýÍ÷“Šá”ÊXJ.¬NZh¥”èJUt¥(ÌR¥HKµHK Sê-ã-Õê-É¡iuÉ÷™zÉ4¦ª?]Ý]ýîïWu³Ú7É´ÿß|jÆb‹ÀÝ-%#i“4²R‡É™a•&'xïÃ?Ô~†l @€ ä‡ÀàË~5àÌ‹£v®Åˆ-Dv‰äâab“q˜jv˜Ô<™·üí?ÿ¥ØÛû¶½óCÛ])S+K† @€@-Иj¡Ä6èLhLY¯\Uþ4¦Ë‡ÝVÆ= ¢"]>ìÖC:.f •’ÊOª”ú­ÐÉk àÂÞÞ2¢RakjJ¸BïpIb¸ÔÜp)ÆRt,ž!.UZÊÒ[R@ EQQX i‹6GeáæÌƒ-UÝaã4&Í –ä^õ±ËÇŽX4B¥ÿcýµ¬ßö}£yÃZi Zi¯Vý*zýõ2™ž˜ÞU!°)Î~"9ËÔšg–ÑÏâ0©À œkq˜ºßû½?HPõôØ€ @ÈK]þ‹3Æ&—ç:&¶Ûš'Å\rõ8L Voßý‡O^µ¡Ôà0q€_g Ô‚‹ÏÔ½«[ËZПÖàÒ6Q5hLQ\ @€2'€Æ”9Rv¶!€ÆÔ6UʼnÖG wј†\}kjÖ6[©W¥1U—LEŠ•‚–T]N’Ÿd%4Q*”@RI„VŠ»Ja*±ô¬p^Š1 .±’Œ´T]ZJÉW>ÞR+yK1±©q“>ê4—¢¤ë4W7º¹MöÑTº¼¥9›æhÍ®?îRÑ‚¶©úÁ5“iüôWì†qSr„Àw˜,—œŒ1#€ÃT•3@€ @µL¦3ºV­ª.Ïõ\ŠÅ’hŠE&“NLí)3“4?D)µ­Ôªrñ™ô§iLzIr­VËÔ‘Z.¹o·Acê[þ€ @-K©e«†ƒ@à  151èyÔ˜\$Ï7²Hï\võ­‡ylä9Ù¨®…jf’“–J¥b8ëü­à*¥GW*`) Ï“È —4–Ì}‰—`¾l¬Ä“Ä)Ø\™¨¤Æ[*84Uƒ$5mƒ†jLNKROºùI®ŸÝ:ÓmZ°úÜÕ«®¢^uë^¯úc&Ó¸©¯D·G¨©Í]êa Gz“KŽ8LUk @€ # “éçg L LA;T1bý0±Ê6NtqS,î;m¿ý¿±xõfËjZbq˜ì NKr¡mÕìòçXX\kg©¨96lþ°¨24¦¨D.€ @ €ÆÔªìíA©=ꉳ¬›@î4¦Ë®ºµBô#½zð‘ÇVŽT)Å[Ið¤xº·²~’Â)y•ÊZJC+Õ +©y«\%+)ÆRä¿ÇÒR牫Kj¨Ædó€ýžtú¯½ªßêI·¢™Äš=\ãg×L¦Ç§,rSr„ šåL.¹™² @€ ÐS2™N>ý¢ yF`*æ¹.b‘•äӴ™!¶`g-QÉ"0ÙJ©Kú­v–kp)DSO¯¯…Þ‡ÆÔB•Á©@€ @ • 1µRmp.h.4¦æòæhM#;ið•·Î_n‚Q¬_y‹4&çU^ܣʥë­rÒ7ëðõ»}“ àÜšÔLpšçêEWª®+ÍJ‰±TÈ ΑõK™HKž´ÔzÁ–ª*MÓ˜¬Ç\`—ËÀõ¤kAÝèöªå>Ђ۾öϼ™LN^X˜ü‚Ä,grÉÕΖ-!@€ z ÈdúÙiyS·Ës]2Å¢Ðrìq&;1—?ÎiL¦+Y+Ì^5‡I –Å»öy#õ^{3·Gcj&mŽ@€ 6"€ÆÔF•Å©B chLew­B wÓ +oqRQrA¯|ıå6ð}£:–à ©µ”@QJËþf–R9Q©\h¥ ÞR])èJNèJ%¹áÂhÿV¦Ee³‚ÿeáæª’PëoÐ8IÓ‚Õoni ôÛ>èêCW×¹%’³Îô‰k'j3­±¹Âõ~˜Éôð³ aËe‘s#~¦¦zÙ²= @€ P/3™ü,rÊNnÓc¬yâ’½t˜tbjIYÂ8IÍ+×àR#KÛXp\kp¹vY½ÕjÛ£1µZp>€ @hhL-Rœú€S@çÍ G)n -íž[(ƒ~3ü #Ž­E9ªe›HKªh&%ü$ÅR* §T!\yQÉÃ…®RͺRÁX*èJ$-%µªÆiLÍøÔ†Ç0“é¡g^Žê:m„‡©iÕÁ @€ s2™~zê…aód«µCÙ7œSœ Ó{‡)Ïјò\û\; @€*@câö€@~  1å·î;üÊs§1]ò›áE»È¢yå’+ÉE?êñB¨"ÅÊV’bÅBé”-éá”ÌR D¥rq•â¡•¼èJ)–:%ÆRíQ :@cr&ÓØI RGp˜:ü˛˃ @€@‹Éô“S/ŒZ£¥A˜Ô<Áaêeu¡1õ o‡ @€@§@cêÔšåº PSuFlÑ–ò§1]1<Í1Šb IcúÁÇ(QW±¤¹Gõ©HIK©«\º7ç'yŠRZ8¥(88½µX iàhLõñbë¶!/éôÓOÿôgÿiŸ/í_®|ö¿þ?ÿåÿúÛ ¤¿ôÅý÷¡´¿þëÿíÿý×/W¨5yNC®¸ný–üòŸü¥•?Ù2™þë?ýÓõ7ŒvìÏî÷~ÿç¿´ô…´2dÎ € @¨‘À%?þÖ¾ÿ÷ß,^½¹B eÁêí»ÿðI;ÌùfhL9¿¸|@€ ”#€ÆÄ½ü@cÊoÝwø•çKcÚ¹sçœÒŸ‡ÆOŽ•Ñ<\Éš#PK-'»Ú[\cÒwÕÄ•G­zkq…A¦ÿFçò @€ Ð:ÆœÜ}Êÿ‰Ã”U… 1eE’ý@€ @ Ã 1uX…r9¨ƒS°Ø´äKcJÖLå¸5¼ 6ŠÆ´c÷ÒQ]{M}íG[¶ÿ>µâp˜Úé»™s… @€@»sòžS÷zïÃ?¤6OˆÃToõ¢1ÕKŒí!@€ hL9©h.)И¸-:”SIÖ0¬T Ðâј¦¿~”4&•·?Zš4™p˜:ô;œË‚ @€@«˜vݞߨ“KšL8L=¨34¦@ã-€ @È4¦<Ô2×thLÜJ µheÉB1Y‘ϤSõM&¦ýç² @€ ÐÇ>xsÝöÕ]É“Ðz¥o2á0õ¬ÎИzÆwA€ @ ã  1u|s(K‰›£C  1Õª°¦­¬1¹PLf2Éjr&S‡~{sY€ @èc«1q@¿yWHžÇcý÷Ž­4“ ‡©Çu†ÆÔct¼€ @M©³ë—«ƒ@%hLÜJ ï“ ­©PÖ¼õá†î]•·áÕv'ðÖ»»WlÜYù*¶nßýç¿ü¥5¿üPL. “NU&Ó»;ÿв§Ýš09+@€ @ FÓößÚ5'¹±B1IoJ®ÿ£?îþÃ'5îœÍbИ¸% @€ ThLÜÈ/4¦üÖ}‡_yÞ5¦¯^./b¡˜\@¦|\=W @€ ôaõ¥½d2IZÒo©K n¨SymòX Ѥ?µRE¯êO¥Ÿ³eýŽeëƒ h·C¢1µ[q¾€ @h4¦&æ0hAhL-X)œRИ² È> Ðw’¡˜ü€L}w^€ @èd»·w[È¥%÷ “·d—j¹äd/)ßœýù§Ý»´ «ÉB4ÉdÒŸŠádb?µ@cª[B€ @ WИrUÝ\,J 1qCt(4¦­X.+7RC1)7õÏ…B€ @ o8I~’L&‰J2“LcrÁ–,“^ÕJm¯Wµl%5ë\ß\I›©M*ŠÓ„ @€@³  15›8ǃ@ë@cjºàL2%€Æ”)NvæøäÏwmj奷Γ½¤§U·æ­¦6÷t8 @€ R‘rI1™$'½1o¢.[¿-Æ’ÉL–6N˜ádª“¢1©hK ËÄOíИjgÅ–€ @È4¦\U7 hLÜJ©C+–ËÊþ¸I“¦ü]:W @€ 4›€eˆS±¸JJg—,yœÖH]²Ôr’–,>“~k3ËF‡ÆTo…¡1ÕKŒí!@€ hL9©h.)И¸-:”S‡V,—•?hLù«s®€ @}FÀ/éG™ã´¬HKŸIÒ’e‘“·¤õV,2“ÖÛŸ½‰Ÿº 1Õ…‹!@€ hLù©k®qhLÜJ©C+–ËÊ4¦üÕ9W @€ ä…S^jšë„ @€@ИêÆæè hLT™\ŠO‰ûB©C*’Ë€ @€ €ÆÄM@€ ¤@câÆ€@~  1å·î;üÊј:¼‚¹¼ü@cÊO]s¥€ @€@Þ 1å­Æ¹^@€ ÔH©FPl$€ÆÔ•Ê%И¸ Ð!И:¤"¹ @€ teöV$€ @€Z—S¦uƒÆ”)Nv@€ Î!€ÆÔ9uÉ•@ ^hLõcû6!€ÆÔ&ÅiBÀ#Ðïþ~]Ý]  @€ кИ2­4¦Lq²3@€ t4¦Î©K®õ@cª—Û· 4¦6©(N&Øëнú?Ö_&“–¥4é÷°ùÃF,a›ì}ÛÞú­pMzI›é7ð @€ 4›S¦Äј2ÅÉÎ @€ Ð9И:§.¹ÔK©^blß&Иڤ¢8M¬Û±ÎÌ$©KZØõÇ]Zvñ™ºwukÙ~Û;|à Š€ @€šD)SÐhL™âdg€ @èhLS—\ ê%€ÆT/1¶ohLmRQœ& uiàŒúK¢ÒœMslµE`Ò‚0)8“6P& L*ZÖoøA€ @h*{ŽÛ£Þ4~2"ÐÓÔk÷LUýUûÿ\ôhFØ  @€ '€ÆÄ=ü@cÊoÝwø•Ó¥ØáÌåuYJr•t]N]rñ™´R¯Ês’á¤m”uNE ±‰@€ @Í#0ø³{~ýß›w¸N?RhLŸˆk©eéÓ^?\ @€úŒSŸ¡çÀèshL}^œ@c 15†+{…@ÃXþ8?mœþ´r Î$·IV“L&ùL¶Æe—kرc@€ @ Ò˜n:.YhéÃm{Îú«Ia™ø @€F©ahÙ1ZžSËW'Ø3hL=ãÆ» Ðg,aœ\%?UœÖ¨8{I''ÉVjË>;W @€ ä–S¦Uß“®75 ¡˜2½Ø @€bИ¸% _hLù­û¿r4¦¯`.€ @€ ÐИ2…ÞS2 ¡˜2½ Ø @€’И¸+ _hLù­û¿r4¦¯`.€ @€ ÐИ2…Þ“.9‰PL™Þì € @IhLÜÈ/4¦üÖ}‡_9S‡W0—@€ @èhL™BoÉÈD(¦Lïv@€ ThLÜÈ/4¦üÖ}‡_9S‡W0——»ÿcÛ3ë\·ct~.™+… @€Z—S¦uÓ6“®Úd"S¦÷;ƒ @€@*4&n ä—S~ë¾Ã¯©Ã+˜ËËþ¸iT×^][‡æç’¹R@€ @ u  1eZ7í¤1Y@&B1ez°3@€ ”#€ÆÄ½ü@cÊoÝwø•£1uxsyù!€Æ”ŸºæJ!@€ ÐИ2­¤vÒ˜tá ÈD(¦Lov@€ rИ¸7 _hLù­û¿ò|iLC‡Ý‹ÔIàù_þ×5kÖ´þ7Á;;ÞØgß/|ä´Ö?U΀ @è|hL™Öq{iL'ŸtÂèÑ£3ÀÎ @€ thLÜÈ/4¦üÖ}‡_y¾4¦“O>yøí£¶îø}IÙþû-QÙ}óí£Ž9î¤-Ûwo~·XÞzwwPÞQùÊ›®¼ý»7¼²éíßmÚ¶ËÊF+ÝAÙ•6lýèu¯¬ßúÑú-QymˇAÙ”u®¼õáÚ¨|°ö­Ö¼Y,«ßü (oåÕ7vFeÓÎU^Y¹qçÊï[Y¡²!*Ë7¼•×ß[æ•¥ëßseÉúK^‹Êâ×ve]Pº¢²ý•µÅ²híöEk¢²pÍö…kÞ Êêw_öÊ‚Wß Ë;*/©¬ŠÊ‹«Þ ÊÊ ¼°òí¨¬xûy¯Ì_ñöüåÛTæ¹²lÛ\¯ÌYÚíÊsK»Ÿ[•ÙKºƒ²x«Ê,Wº¶Î,–-c'-øÛ¿ÿôŒW¶¨L·²((Ó‚²YeêÂÍû|qÿ9sæ´ø7ÁÎ;¿¼_¿ÇOÿö÷™:uj‹Ÿ-§@€ t>4¦Lë¸4&õ½\yýˆ#~x<&S¦·;ƒ @€@:4&î ä—S~ë¾Ã¯ö¤0ÒR<ØRª·äE]JW—zf/¥D`zÓ"0}𪠴©·A˜ÌzqEñÞ{ŸK®Wq˜êv˜êK'7«k«Ë(§8Lr˜’Ó´E[²ÙÒÉYÙç‹ûOš<ã½ÿàÊïÿðI+|1˜Ã4þÙy+6¼¿üõHcZüZ:K=Å/,“Étð¤g&·Â©r€ @€@î 1eZå-®1Éaºú†;‚ÆiAcrÓEk“é¾ûîÏ”;ƒ @€"hLÜ È/4¦üÖ}‡_yî4¦o¹+QÉÿS¯þøØ7*º’+Ý»ä*¹²¡[º’•,ä’Š\%¿¬/ ¼eŽSþ¸ÍQY·ùè¼õáÚ¨¤ä[#u©`/ŦUug‘“æòž¼%WªL‰ L]k‹¹ä­Ý”5AY”wƒ²:(/»òê» ¢ò΂WßyIeUT^\õNPVå…•o»òüŠ·]™¿B‰ä‚\rÅtr˶Í[¶m®+K{î0Í,8L%Ó¢-Ó=‡iZÁa2é¡ñ“ý`Zºgúü‹Á¦'&Ï_& t¡˜Â €Ae©Ræ/ÝüÍï5mÑf•T‡©¥’Ê¥8L~7qi(&7ÛUÝIJÄf-zãß>h¤ɵ|WX¥ueZ?oì]®CÓúUõªõçZ±›„j›9ÉY2fähÏþ,Xmæzrõ.ëfõ«>VS…R5&¿Õú¸M2wÇâ0Ù!Ü,FQ…ƒV>ØôãkL®ÛÚÎÁQ#OwJæŠé¬Ûzí“§”ª1¹s‹u=k}lÿFØj¹7Ø€ @µ@cª•TMÛµšÆTâ0ùéäÖ¿W'8Lwô¬ ’ËS˜–×d2¹–Žßäq¤ÊiL®]c-Jÿ½z‹YDÖ@³¬íÐ#ßêÔö§köº $î]î¸H)Y£¦i?. ¯Ó˜\£Lkü¶9?6-Ç®%Ö¾K¾¤f£VÆ®Ô<-ÛÉ5Òmc¥Ø³9LÉ~€šnS6‚ @è hL}AcB 5 1µF=p™ÈÆtíÍw¦kIaê·ko 4&-”FTŠ[JciM])ÍX* ¶TFZ âë”&Œ ÂíXÙ• ƒ˜+ÕÕ¥÷z`/U¿Ô{©îLõg‘+˜¶¦a’ÀF`*hLiA˜œÕÔ"јü\rvcèN°\KünâµA¾¿°›ø] ÅTè)Þ6cáýj3™\ߨÅRgÌqñ5&ëÜLjLNJÕ˜,,ë0µ·ûF‘uຯ<; '¹®g{£‹½dÛ[Ÿ²¥rs¯J²xûNcÒ²u1»^æØA+Ÿ¡ËUg-§1Ùz;D-<-î”ýXG³MÀ5¥,yJõjLÉýëº:©3ÿÿÊ!@€@Þ  1ez´”Æ”t˜lnUÐ> Ök–T<SQc rÇtD•ìrIÉkVÕ˜¬qÓ˜¬B¬µå+A¶Æ×˜Re#¿ÙkÍdýXcÊ5™]ÐNU»M¦h÷Û¡î4ìþ®ìlµ;–ü½¥¾ä·ß]SÔšÆÖ¨´ íÜR–;¹ÊVºÀ™Þ¿ì € @ И—]C Å  1µxqz=%?é¦;]¢·äÂ57ÝÙÿèRc)ÅVF¡•,ÆÒ~ñrÃYž¸0ÌR2Ò’E]ŠÅ[JzK˜ÖSï0Z6ºäþ{ú¿ƒ÷A€ @ 4¦j„êz½u4¦Àaº±K.½qº#Ö8æØ„¡˜¬qªÆ~e“)©1ù¸\67­´E¾×éDU5&méhÚ›ZL¾¾ãÅ6#Åþ´ý[KÓNFµÐ¹nM2“Äu'ov]³1¦1ù»Òé™n¥ ´·ûû±³Š½d F×î³£h?&?(-XcV+¿ó®êºKÙ€ @ O 1õ v – €ÆÔÕÀIdO wÓ°ßÞYb ¹\oá‚^•Æ”0“*ZJæ*•°éJiÆRi)ðTR¼%›àXš0®’ºK×µ¶ræ¸ –eŽ‹Å^z9™<. _%\4Þ•ùa¯åüåÛ¬¨û2(Ë‚¢~LW|{IËÏ-)–¬&Ë"7¦4&ç0…Ò[—+Ía*t— ÅdÝÄRÁ¦¾¼é€«d—³žMs’Ô¿©ß&è¸×Óê¢ø¨?×zB-¨¾ýX€Û‰ÛÀú^­ûU½«¶¥S‚lþŒÅ²©±¶ÞwƒÜnMÓ±W]'ó~t ê!ìŠÊ4y†4& ÈËRgWa徭§Ã嘫[Ù]—u1'¡9à.o‚»XëgwÐ’û7DcÊþ¿+{„ @@cÊôhIÓÕÎaJ6N]®óXœàÒPLs—íSµîpø1#Gݛʩ²ÆäÚ_¹ÖæÃÔ¥1Yê4µÔ¬…¥·›Bdk*hLÖ(³¦Ÿk~º5j[Åd#×Ôzkšùâ˜ÆÛ¹NÉšØvVnÚ‹½dL\*: ¬k,kÁµ‹uÚ•¶´†§]ˆ«½„É”ég—A€ †@cj8b–%€ÆÔ²UÉõŽ@IÝ.Óõ¹Ô½;nß¼ÛžGÖ‘Ó¼½zÔO(nP¤T!œ’YJ•]¥ïüà°(7ÜÆ÷/»â†ï|ÿ0ý¶ç¢Ë­ ¾â‹¯cåß¿hÿ£O²e“–´fÐÐ,‰XP¼KÓ_|ÕB.}û{‡Ê[ª¬.¹ÀKGüèÄ'¦¾Äï Õ¥ñSøÝCætmR,+úS¹É åøyÉJ{éÔsöÃ,“Ô%-?òÌ‹*Zð¦È^J LaW¦+~ø%™L¡À´µß·îe&˜¬ôVcÚ½sϺ9 ½›ÍaÿìüHzÛðþO®™}àùTŽº|êIÃf=ûò[ ²eu:ý•Í'^=3H'†b:ïö¾yî„ÃO~pÆk‘Ɔ°šüÒÆ¯W3™zyQnJh/÷ÃÛ!@€ v%€Æ”iÍ5NcšûF·êùšÃä§gÜ2ÿ†G—¹\r×=²ôÚ‡—ZãT= 7_ñôóoXœà'çoüåoç¸qýÆ©"+¿¼ÉädšrV †äÎÜ-»6©[ãz·LôÑ[,€“[ïÖh½ _d[ºmü½iž‰…ε·«Ôæ°^Õ©&ÏÁ?º{£íÊíÜÂ&¥Bð_ÒÛÝ[´`—YîJý¾>ÿt!8LU?l@€ZS«Õçæ@cjkŽ”1?ñ‘‹“â‚•TÒ˜ä0íµ×^®;ÃÅVÑÄ,÷þŒO¶Á»s³}÷È_Vœ4¦Ø«+‹”,Üû©Å‰JÁB¨(Y9ù”³?óÙÿj‰áä*õ?æ¤G'>'?IËêì{dÂs_øò×ξèriL~¤¥Ï|öó*&0IZzzÆBUÇY1{©˜*NËë{ÉÆ}æ?¯lqé ãÂŒc®¨Wñß¾´ßOÌt—ÆŒŸ©CÈmr—>ýŸWŸcd/yêÒiç]vÿ¸ꋌeŽÛç‹û}ê3ŸŸ0{¹…_Úç ûÝóØŒ{±Ï¾ZŒ½TKø%/“~I Î?|æsQ ¹®­åRÈM/“BΘz«1I`š4tÏùÿyϘ“wÛ¦yvS…A˜Þ—½ôÔüMÁ]ñÚuËd²n⦯;â²)*ÖMüÛÇ—«›XöØØ¯6x²…bLÑ·g_ÜðõoU‰ÉÔ¸ëbÏ€ @€@ç@cÊ´Ž§1êÚëžÅÿSU™)èQ¹aD¬q:tô+Ö8Uůî_¤¢Æ©ºîšôê·Î›ðèìõ–Nîð˦ÜþôªÛŸZ©Æ© ÅdS¥€ÿþaec2eŠA€ @ 3  1uf½rU¨…S-”ئÅhò•& ÚâXÛ\,-Ø­²“f‰YXiÓ˜,¶¶] ¦»Å.¹ÊéX§[9Iëõê‘?>Á6(Ñ’ìOONŠ-›¥/¯¿wßÓBI6’U’±4ë¥Õ¶lŠÒÙ^n–\‰"-­ß¡ Ž:ú¤«oi‚?p–\%iLlé’__æCnùÔ¥Qc'È^ÒŸÒY$Ýõà-_ò«ë¬÷pÊüUgœ?DeüÔ—]Ô¥3οìâ˯û·/î'uÉÅ^=n¦Ö¨Ü0âAS—´7 ¼4ôº;¤.]8äZù1³nüÖw9þä3g.Ü`—^¥¥Ûî{ê›ß9D™N9w°Å^’½tÏ£Óï~tú¿~á«–<îüÁ×üòìAÃn£ù—úýäÌ¥Òkž˜¹ô¼AÃ̳9wÐ0^?c逳©<ðôóR—T®¼yô/κtÐU·Icòí¥™][f¨¼•²S!ü’‹ÃÔciÃë›w>28˜ô¡‘ÿÌa÷Ì<'0Ù#éÉù›mÝŽñó69dŠU´â0i¶«4&ë&>þª™÷N^Øc˶©§X’SÑʺ‰»¶Ô¤^ßÿ[?˜0ir{}Š9[@€ @ = 1eZO Õ˜d2U–™Ôr•¦Âì×8ýõèW¬ËB]r˜.—Æ´fû5c—¨}ªÆé#³×«áÆÇ—slÂÆé9·=ÅèW¬qjLA[~Ú¢-ß;ìèrÙå2¥ÈÎ @€ ÐИ:°R¹$ÔH ‘CÕ5ž›A ^5ÉiL“_Év"CI?Z¨’TÎiL¾ºÔÖ“õ»%‹HWJcúÑ éN’³”^WDœ÷\q9à’ /­xKÞÒ‹ËßrA•Ü‚¤%-ËXúö÷•œ¤å}¿ôµ‡Ÿší‡YÒJYJ–$N‚Ú@&“ü$EZÚ÷KûÉRzðÉY~ïÐ+o¸sÞ’7´FJg‘x¤pJ>1ëÀïzñ¯®›<¥B.ýöŽUôÒ¸) ž·R 7ÞñàÀ˯Sì%©K.gÜèq3ä0=öìKÚ`ö¢²a´ >ÇN>SYáî|†~[Î89L¿ºv„…\rEÓ­÷=õôìe.ö’ì%9Lw?hLò–ôû¼ÁרŸò–TŽýé²—ŽùéŸúÌçÌ^ú×}¿:nÆR¹JWÝ<ú滟ø—}¿:æ©çe/iáαS>òx§1ùö’ú=#iÑ–é‹‚>P^²ó–z£1I`zïáÁ>÷ÿˆ¦FjLr˜¾¼_à0)ü’K5h®Û‘C¦^tç‹¿ç¹Êaºë™Õ&ÔTWõ«ÊTG‡ž2vÆzÙc"/iÌ´uJÉçf»†”6O|“©ÞïU¶‡ @€j#€ÆT§·j‚ÆTNf’äޒ0Q“Št%“–T~sÃZÖdGIKú½pM 1YÈ¥‘cž>ñçgž~þe*oéŠëï”átúy—©„êÒ;ßúî!Ê §¨KrIËÒ˜$Á(ð’t%EôÑÞÔçø©ð·å‰SÎ8…\º÷±˜‚¨Kaà%M¬T:¹ äÒò@WºõÞ'ÕqhLD“ÙK’–,ü’–Çë÷¾_•½¤ßý¾}ðȇ§ ¾ú¶g]ªrðQÇßùÐT-ó“ÓÍa² LÒ˜\ì¥4{© 0• ¿Ô3iÜ#ãR&Ó˜®Ú7È.—iÙùè¥_Þï€ÇŸ™ëwaºÂI®ê)¾åÉ•ãçmxpÆk§Þ4ïˆ!SÌaRªX±úUMªiLÚ@ÝÄ.iô´uE‡)˜í ^˜LmÿÏ@€ @ 5  1eZ/¦1i|"óböR¬¸4sÃTèH)†‘.4N¥1™Ã¤8L'^-i¡5NÕàÆéóÖ+xó @cZ Æ©ÒÉÓ] ü8Áš†äÚéÉô«s³m_³7T"°nN¦Sv@€ú†Sßpç¨hhL­P œC 1±©÷í7ר` éÕ#~x|… ßÞ“œ”PNJ-’“$*)œŠ-HQ2QÉ\¥ÐOrÒÒv‹±$3I‰á¬H!ÒoÙKr•NúÅYOL{ÙrÃ)Ò’^ÒÆ ³¤ràw‘´ü]½dÒ’²ÅÉI’¨fˆ º-Ø’%ó–´ uIÞ’-ï#ieËG Š·$éÑg_”ºäB.iùžÇf(mÜ=κ„…‹²ÅIcúÆ¿¬"EI¿-üÒ¨G¦©Xø%Å^RÚ8yK*~I~ÒO¿ ‡éÜK‡É^Ò‚b/)yœ\%½dE˜ôûޱSÌ^:àÀƒŠöR8q³®ðK=ИøÊWÞº|ÿ’L&05¬Œì·×ÿ¹Ý‡f/EaºÂF˜ÆÍÝ`‰äTõšáúØs¯IW½c“ée‡žüàô×ÔMhLƒ&žºÖEìˆyš×ðû&îûůìþÃ'=ú†áM€ @€Ò 1ez_,Ü2(Õ7jèÊkü7ͱñí%C:lœN•À¤Ž kœÊarßBs˜ÔÃhL3׫}*‡iШ@cRãTÓ%w½‹ìÚéOÌzõþÓÿ²ùçÓ¸æ6{†@ }Mñ@€ÚŸSû×!Wž@cê)9Þ×ç²Ñ˜tÚÑ®]»´ PNJP×çÖƒÆtÅu·Wpôª4¦ØŠS¥„f’+NNûÔl+2–Æ>5ËD¥§¦½¬>¾©Ï¯Ò²”N)á´ ß27%ìT þ\³ý‰©/+Ò’t%õ žqþe*ã§,dÒ’2Ä)7œ¤1Ù”G½Ë—–x鄟Ÿiñ–$-)=ÜEC®Õoó–¾õC”*μ%•û4&‹åóÈ3/JKRѲ~OyCr)X–ºtÊ9ƒ”-.˜–ÅŒ¥±_ ¦W3,KÉB.9鮇§Yì%˧ù—xIÞÒ¸éKMZR¼¥s.vôONc/m¹qÔøï/ué77ÝoöÒ?|úsžºTkò¸r©åÆLXð·ÿ©Ê‰çöùâþŸ¼åÅÉ¿¿æ)ý}·´G³÷üòá¶Üœ±· :ôÔs.‰n¼‚ú¦[(0Û¤1ÍÙ`1·$0}ë¼ S¾eÝÄšêª LÆ´|ÛoÆtsÛóê&žúòæCMN Ť ¿cì´ýöÿÆâÕ›×où“©÷Ç @€ ˆSÖ·ÂÔו´´âíáÙ–Tê±Uÿ´íwÏë F­~’b¯H4+jœ*“9Lê‘Ã4äÞ…Ö8µDçÍ\¯Æé=Ï®9îÊjœª7àç7Ì9iµÚûÖÀ÷ÁËaRãtÒ„Éë_šóÑŠÒVv¬ÑÍŸÈ„€¢k£1eý5Åþ @èhL}‚ƒB % 1µD5p=!à4¦uëÖõë×ÏvÑ¿ý©…½*ïRÛuuuÙ6cÇŽÕûí§''Òï 4¦ko÷•£Ø²^=ü‡Ç{A’Š)ÞÒV!”Š¥EÉ…SŠÅUÒŸ¿½s¬ì¥3.¢ß¿½c¬:ûf)Xsþ‰JJúfnŠ• =ÜêwU´ ôpêtâ”îð0=œ|¦¡×ÝiéáÿÑ ³_Ù¨ý q³m”™$oIE/Mzn…¤%­9þä3U´ uɼ%å‰s—Îç”s;iiŸ/|Uê’b,÷³3ä-rö )J·Üû¤yK˜ä-YÂ8+‡(ÜOÏ·${ɦÙKºlIÒ’Ô%éJWÞéôŸŸlyß“óU´pò—tÄñÒ˜s^}A©-s\K©vI–JŠÌ4æäÝÚÉtö%áè2ÅMú¥.YQ(¦›Æ-wÝÄê#>þª™Aˆ¬°^ÔS¬8Lr˜®yxIj7±ï0Ùb25¨6Ù- @€rG)ë*·¼rYïuOLcr“;L¦BWIÐb}jŸjŽ"0¹,çr˜.»w¡9LÊ%'iìŒ×¬qªDçgßú¼ŠÚ§Aã´+ˆµì§“‹¦é/XËTå£ÝÊüJÙ!JÜt · @A©3ê‘«€@O 1õ„ïi NcÒÙ 8Ð4¤ØÉÕÝÿÕÝÝÝ—Õ£“Æ4ôÚÛ“š‘[£Wë\… ’/Eñ“,ŠR!’…SrEiàÓƒŠ“ç¯”®4~ê‚ÀU -%EWÒšqSX28W”Î,=>yXzî•*’–T”îú>3g…IK*–ÎO÷س/Y¤%¹J¦+Y1cIñ–f¼¼Áe‹“·¤`KOzÑRÅY¶8r顉/ÞýÈôb¼¥eÛôç”×›´¤…±^p ã4Ãrò ë|ú%Œ“½¤¨K<õ¼~Ë[ºó¡©*н4+¶s˜xéþ§æ[Ú8+#œ¢8Lši±—™²äö§<2eñ}OÌë½½äĦz5&ëNݶ`ÊõvYR¹†iLºÇe2röÅîÖŠ·ð& o‰ ÞƒÀZa-[.9ç0ÙT×§žßÅa*t;zI‡ “©Gß+¼ € @H#€Æ”õ}Ñh))0¹+Éd½%®ßCíÓ‰/¼!KÉú+zŽ¢//îv¥ÆÏÝhSÐ8]Ú}פÕ*%¹Îm¶¶yÒaÂdÊúÞaiИ¸/ @èhLR“\ê'Ðà¡êúOˆw@ ukLÙ¶ö"é××ÜsŒü?õª:æ*là^rZ’?©¸úI®Äü¤ØŸÖåç•ÀR²$ƒ³Rp•lÁRÂËÊ@dq¹áœ®ä¤%ç*Ť¥0O\QZ ’ÄòÄYocIYt>ÆŠ¯.I𠤥 l•´dE}”ÅRP—L`’ºdS0] ¤%+¡ºTŒº”Eà¥Ô˜L=Ó˜6m ²+‰äÔç•Иvoï^rß°U§$^L]YùÓ “é—g]lÒ›Ý9‘ÀTp˜\-[múÝĪ s˜Ô!U±¿œÃ„ÉÔG_N€ @G)ë*mœÆTA`ra&S¢qLU&Ø, ; ÂÎ(N°×8-ç0%M¦lÛÚYWûkChLmXiœ2 @©И¸1 _hLù­û¿òÜiL¿ºæ¶¸xäùF¿v[Ð+W*!Õh#¥¸Jq?)Pœ¥TATJq• ;t%ÅlOêJQ„ž0Ò’3–,ÒRi)œ1™"-…1~\©Ó[ŠBÇWS—2ËW!œ½Ô+ɾ>Üû’˜8 Ÿt¥7æMŒ­ß¾ºK/õàÅL¦‚èim~¦ –à 5íÌâ0yÝÄõ9L˜L=¨#Þ@€ Ä  1e}O4HcÚö»çk“ú[„É¢.9QÉÉi¥â6ÙW‘f—Öò$“éäÓ/²LIIq˜¢:"S-4Ù€ @h4¦¬Á¶”Ƥ‹“ÉtÐÇú)ÎÃŽˆh~”5NcA‚Ÿ˜õê~ûcÒô\NóÔ…÷>üC ^ÚÚYWûkyhL-_Eœ  @5@cª›A   1u`¥rIÜiLƒ¯¼ÅwŒb²Ñ +o‰fšiTK sº%Kz–·dê·òyß\2¸ \˜/,µÌz ­”„V²äbµXŠU6– éáÚ(ÒRå8Löjæ“å3Iê’%u¶JW²¢—ô§t%½$I ’œ´FêU®©ê—“L¦ŸvQÁTóúˆ-S0ÏuË´ðUÈ%W•'@€ @Ù@cÊši«iLº>3™ 3©‚N‰’,祉Î{ì0é@Íikg]c쯵  1µvýpv€ ÔN©vVl N#€ÆÔi5ÊõDr§1ITª éU›JØ“²t[…änÎIŠ-TV”J#*Õ&*• ­´µ^])ÅXZ´ÙÉ1µHB­¿M¶ÓŸvïr•$0ÉL’¥´µkŽŠ¥I;ý6¥ÉrÏéG ú³ÆPLî«K&ÓOO½Ð4µ¨fó\q˜ø¦‡ @€úŒSÖè[PcÒ%ÊdúÁÇxSI&ׇЇ©™mí¬+ýµ04¦®N € º 1Õ…‹!ÐQИ:ª:¹˜"ÜiL—þfx9£Hëõª4¦ $_Š<$ ˜T>fR,’B©H©–XJ.ºR—™+©%Ì—Z©$œ])ºR9¡*[©É_-2™~rê…Aî?˜,Ó¢(S“«ƒÃA€ @%И²¾!ZScÒUÊdúþáÇYäüÁ^ã´7SÖÙ И¸ @èhLR“\ê'€ÆT?3ÞÑr§1]rÅðrÙÙ´^¯ºpè5$qsÙÜü…­Éänš•h%%Ë[le×ÖY•%/¢R-¢Rº«˜.ÅRH=Öú‘“q†m­1é+&0™N¹0)0á0µÅ÷/' @€ N&€Æ”uí¶¬Æ¤ L¦ÃŽQã4œ(Uȇ)ëýeD)#ì€ >'€ÆÔçUÀ @ Ï 1õzÜXyÔ˜œT”\ÆôƒÃƒXèµZG•ͤšœ$?¢R¥@J.âNÐ-è—EA/¡•0O’W©í©Ý5&}=Èd:é” b{ÇØiûíÿÅ«7¯ßòQ…²ûŸ4ö †½C€ @¹%€Æ”uÕ·²Æ¤k•Éô½ÃŽŽe¢ÇaÊú.`Ù@cÊŽ%{‚ @ o  1õ-޾$€ÆÔ—ô9v äNcºxèðò騶êU „Þ‹²EI¾‚<_®„ ¿ª–¸œd¢’§(U²”Jg:Ö¢ï°èI_2™NüeÑdÂajàW&»† @€j$€ÆT#¨š7kqI×a&“ëpÀaª¹nÙ°/ 1õuŽ @€@# 15‚*û„@{@cjzâ,ë&;iàЛ+EzUQЫ*G©¤{HeÂ&¥ÅOJ‹¢dÙßò÷­¡ÆUghLúÜ;“ ‡©îoAÞ@€ 4‚SÖT[_cÒ;“ ‡)ëúgY@cÊš(ûƒ @ ¯ 1õyŽ ¾'€ÆÔ÷uÀ4„@î4¦cO>ëÆ»ÆedJ9ö§g}yÿS_Š­¼aäø2eÜ #«—ëGŽ£´AWßñÿý/ÿWå3ùüûç‡ÆOöS³mÚ¶«!ÇÞíT&Ó¡?ü ¹äzG‘wC€ @@cʤÛM[hL:[3™¾´ß—&M¡r¢ó÷>üCÖØj&€ÆT3*6„ @ Å  1µxqzh 4¦Âe×}I _Ó£>z`霿ì³ï—þiïÿ[ÉŸLà+ûðéÏ|¶ò~óÀï¾´t}ëkLú"ùí…¿\¼bCånâÝø¤/¿r86 @€ hLYWt»hLºîŸþêo®ø'8LYßì/ShL™âdg€ ô!4¦>„Ï¡!ÐÇИú¸8|£äKcJR¬Ü§Æ«H%Кјöüéã=ÿî½É·W¨5¦F}•²_@€ @ F)ë[¢4¦Q]{M[{Z…Æ)q˜²¾;Ø_ýИêgÆ; @hMhL­Y/œšA©”9F@cúSõhQiÖð=ú_%“é½S¯‡©¾b9$ @€rK)ëªo/IgûÑî?¥6Nq˜²¾5Ø_ 1õo‚ @   1µ`¥pJh4¦&æ0Í&€Æ„ƺ ´¢Æ†b 4&•YÃÕ)ë,Æajö—+ǃ @€@Î  1e}´‘Æ´õ£9;?^#I“ ‡)ëû‚ýõ”SOÉñ>@€ZS«Õçæ@cjkŽÔThLu+,õFîaûÎ#Њ“…b²"ŸéOû&SS¿V9 @€ hLYßm¤1ù—î›L8LYßì¯Иz·B€ ÐRИZª:84•SSqs°æ@cBc‚@ÝZNcòC12é[ÄL&¦æ}¡r$@€ @À@cÊúfhA©{Ww¿ûûU½P3™p˜ª‚bƒ¦@cj*n@€@  15.»†@‹@cjñ âôzJ ïÓï>þõ£U(o¿÷ûím(9! ê~çý*5®Û¦§Ÿ¸Æ¼ÏÅädÒÁþã“¿4æì€ @€@EhLYß -¨1]>¶ÿcýwýq—•u;ÖéwWw—»týiË ÞzÅ_Ÿ5öú  1ÕÏŒw@€ КИZ³^8+4ƒS3(sŒ> w©sHdK ŠÉ È”í¡Ø @€ Z  1ÕJªÖíZMc’¢$‡iÀÄs6Í8c -O\;ÑÅg6˜Š.Ok´J-¡›jÅÁvè%4¦^äí€ ´ 4¦–© NM'€ÆÔtä°9ИšÃ™£@ a’¡˜J25ìÀì€ @€@yhLYß­¦1éú¤%YŒ%-ŒX4B úS>“]ºô§“™´Fž1™²¾/Ø_O  1õ”ïƒ @ Õ 1µZp>h4¦æ±æHM%€ÆÔTÜ (Љ€Lƒfw€ @€@ИêVuóÔ˜ö¾mo;m·àKK¶R¿%9IiRqÚSÕ‹e4œSÃs@€šD©I 9 ZS V §”4¦,(²´›öèÕ¤¡­p.œ @€ whLYß­¦1­Û±Î’Ä)À’ËçD%ešs“ÒÏ ‹ØÄZ‚SKT'@€@И2€È. ЦИڴâ8íjИªâu´ 4¦v©)΀ @y €Æ”u-·šÆdö’%ÉI Âd—«5c—•äüq*Zc ÚX¿Î˜5öž@cê)9Þ@€@«@cjµá| Ð<hLÍcÍ‘šJ©©¸9H©pÙ5 @€ P'4¦:UݼÕ4&°ì%K*Ý»ºíü¢I+%6iAëm¥yNÒ›ª^#@ yИšÇš#A€ ÐXhLåËÞ!ÐÊИZ¹v8·^@cê<Þ –"€ÆÔRÕÁÉ@€ @ çИ²¾ZPcÊúÙšH©‰°9 @ %€ÆÔP¼ì-M©¥«‡“ë94¦ž³ãh-hL­Uœ  @€òM)ëúGcÊš(ûË74¦|×?W@è$hLT›\ ê#€ÆT/¶nhLmSUœ(ª@câ @€Z‡SÖuÆ”5Qö—ohLù®®€ ÐIИ:©6¹ÔG©>^lÝ6Иڦª8QT!€ÆÄ-@€ ´4¦¬ë¢4¦Q]{él³Àþ )4¦Lq²3@€úSÂçÐèchL}\¾QИE–ýB ÙИšMœãA€ @å  1e}w 1eM”ýå›S¾ëŸ«‡ t4¦NªM®õ@cª[· 4¦¶©*NU 1q‹@€ @­C)ëº@cÊš(ûË74¦|×?W@è$hLT›\ ê#€ÆT/¶nhLmSUœ(ª@câ @€Z‡SÖuÆ”5Qö—ohLù®®€ ÐIИ:©6¹ÔG©>^lÝ6Иڦª8QT!€ÆÄ-@€ ´4¦¬ë)k¢ì/ßИò]ÿ\= @ “ 1uRmr-¨S}¼Øºm 1µMUq¢¨B‰[€ @hhLY×SÖDÙ_¾  1å»þ¹z@€@'@cê¤ÚäZ P4¦úx±uÛ@cj›ªâD!@€ @mC)ëªBcÊš(ûË74¦|×?W@è$hLT›\ ê#€ÆT/¶nhLmSUœ(ŒÀ¼+LÐïƒ7×Å€líš³ä¾aP‚ @€ ÐИ²®4¦¬‰²¿|@cÊwýsõ€ N"€ÆÔIµÉµ@ >hLõñbë¶!€ÆÔ6UʼnB@ä*IcÚ½½;IcÁ-W=>J€ @€Z‚SÖՀƔ5Qö—ohLù®®€ ÐIИ:©6¹ÔG©>^lÝ6Иڦª8QÈaš>°¿ŠDCÒ’Â/½6y¬‘Qˆ¦í«»’ë哤%½ªtr–`έזŠÌdk™©m/‡ @€ÚÀÒ§Ëv¥é%~zG •5&]ÙŠ·‡—GÙ±{iï.wC И•]B€ ÐL÷.ùëÔ'ð±Ëÿ¾™§Á± f˜5<½ï嬿Úóá¶fŸ ǃ@c 15†+{…@˜«¤kAN’¢.é·iLiik×ý©õÚÀrÌiY öÛe—kÀ©±K@€ @!Ô€LZÉO¯ ´¸ÆT. Óô×êõ¥³4€S ²K@€šI \@&B15³8ú€@¹€L„bêƒÊà"€ÆÔ(²ì™ðSÂ)‘œŠáÿÖŸŠ½ä^²л´Æb2ñ@€ @ ±R2Š) è-®1éS2Š)‹Êg €ÆÔ¨ì€ &Hd"S“«€ÃA o$2Š©oj‚£6ŠS£È²_@€ @€@ Ä2Š)£› õ5¦d@&B1eTùì¦И•]B€ ÐdÉ€L„bjrp8ô d@&B1õMMpÔF@cjYö @€ @È#X@&B1et´¾Æ¤ d"SF•Ïn@©PÙ% @Í'àd"SóùsDô? ¡˜ú¬8p£ 15Š,û… @€ 䔀 ÈD(¦ìИü€L„bÊ®òÙS 15*»„ @ ùü€L„bj>Ž>#àd"SŸUn4¦F‘e¿h6›öœº×žIC›}\Ž@€ @ FÀd"Sv÷F[hLº\‰PLÙU>{j4¦@e—€ ô  ÈD(¦>ÏA!З, ¡˜ú²8v£ 15Š,û…@³  15›8ǃ @€ÊP&B1ezƒ´‹Æd™Å”iå³³@cjTv @€@Ÿ°€L„bêø}IÀ2Š©/ë€c7Š@¾4¦¥K—­øs饗žvÚi•·áÕ#ð³Ÿý¬ò]{íµüq£>‚îwǦGíõñC2Ü%»‚ @€ Ð3›&Ú9ÿ¡ž½—w¥hI'?ñ…Á[ß[H=B ¥  1µtõpr€:Àœ9sªk8IÃs¤«ü óuÂÍÑ€k¸æÁkÀ^Ù% ÐêÜyÉÇï¼ÑêgÉùA ~ùÒ˜N>ùäƒ9ü¢K†X¹0V.òƒƒÿçÙç‹/S¹ Y^vAXÎ/Sλhpj9÷¢ÁQ¹pð¹^9çÂÁ^tÎQ9û‚AÉrÖƒÎ:?¥œyþ¥Q9ïÒ3½rÆy—ÆË¹—žqË%§Ÿ[,§sIj9õœK‚r¶_.>õì‹O‰•³.>嬋Y¦ 8óâ° Œ•_œ90(gÄËÏÏXRNøóÓ/R99­üì´‹RËOO»((§^+?9õBWúÿËÿýoþÓON¹På¤x¹à¤S.8é—üíßJíú?\Í~ÇÔ©S¿¼ßG}·_{HWÍÆÃñ @€ æØ´i“š'xàÎ;›wÔN?R»hL[Úgß/uÔQ4N;ý–lóëCcjó äô!´>= {üOJ†¢.â?}ÿàÃ4 •rŠ 3ÅF— ƒJ)ÃI±Q¤ØÈQqÀ¨8TÅÆ†J‡„¼Á ÄPlÜÇî)â‰îÄÆtl(ç¿þ·>àÀGpâ7|ý[?Ð0_ëW}óÏPXÔþ=ztóÍ!>$ ÓúîÃ:àÐ #;iøí£¶nÿ½Ê–¨ìÞ²½Xn¾}ÔÑÇ´ùÝÝ®¼õîî ¼£ò;•7]yûwoxeÓÛ¿Û´m—+·íÚØ• Ý»Âòц­½î•õ[>råµ-¾¶9*ë6•·>\”¬¬y³XV¿ùÁê7¬ì|Õʦ ¬òÊÊ;Wn|ßÊ • QY¾áý ¼þþ²×ßseéú÷\Y²þ½%ëw,y-(‹]Y·£«X¶¿²¶X­Ý¾hMT®y7(«ƒò²+¯¾» *ï,xõ—TVEåÅUïeeP^Xù¶•çWËüoÏ_®²Mež•eA™ë•9K»]yni÷sK¢2{I÷ì%[g/Ê,Wº¶Î,”][ÆNZð·ÿé¯l™îÊ¢-Ó¢²yÚ¢ÍSnÞç‹û·¾Æ¤Tÿþ½C®êqïãt7ì “C€ @Õ „S¿)s—>6i.&Su^5oÑ“&ÕþóK6ޏoÓšë– û‚S_P瘀rE@OÂOL˜E¡ü±§›n ¤¢Q§ÂxSl˜)6ºT²±$7d£H…ñ£häȆ܀‘Ɖ¢A" ƆÜÀPa<È ÙH² pè§8ècÃ=±â±Áhdgé6Ó±7”óƒÃ¹øŠá…œ-¸‰Æn C6ýêf4¦ä‡HL®¼~„jðˆÉ”«/.6çŠCô¾s~+tèåçNc’¨´y{ÑRò%-ß|[ðÔXV]’ÃTj/ÉdŠÛKµL[K¦¤Ã L t˜–{“d¦R)r˜ŠÓº‹=‡©+æ04¦…‰GXïA6x–­Åaª[cò¦à©·à0ùϾ¾Æä&-¤hL‹¶L÷¦i ÛCc²T‹^íZ¯í¸“©C¿¯¹,@€ ´>9L_Ù¯ßÔ¹ËÔÒÔ@È#1™2«´Öטä0©ö_X²‰ÆifµÎŽG©qlÙ3 „¤1›0-6å?ýöֻɟ0ΖæÉ‡#Mµ8Lë óáÝLxÓ˜l¼›ún“›ñîÏu÷¦¸{“Û£!¡hB»›ÍnóØ£Iì…éë6qÝÍZ÷5&7SÝטŠóÒÃTIÃ7IéB4¦Ä‡+p˜naÃ| Lp8&ß?Ȇ†óQϹ¾ÊÜiL7Ý6*zLŒb,#-)ØRôÔX>ê’E`J‰½”j/UÀT)Sä0Ń0â0EA˜Â8L%A˜<­¾\¦¾p˜ J~!SôDë¹ùMÅ43|¶hLB1µ~4¦àÕ÷]´z›=§òÙº·ÝCL¦\³sñ€ @èÃôµ~Óæ-S«Ó5O™0‡˜L™TG‹kLÃôµ~/.ÝTÒ8ešM&uÏNA©TÙ' xô üøÓÓ é>R2~h@êÇÇžä9• LA–—âÃâ0¹Ì±œ©“<*†b ³vX(¦X²ŽÔPLnN{!S© 1Y(¦`úºÓ˜i7B©˜jâ1ù¡˜")̧DcEc*:LʤL>²g 1Å>ar˜®ºa„Õ¦iLJ«rXÿãˆÉÄW:›@úÐ0­ïήõü]]î4&=ÃyâLxwO~¸XÈ% ¿äž&-y\!s\Jò8=e®÷Â/EšÉO!W°æë˜ª$’+ä’‹„¹äЉäA˜Š¹ä²ŽÃ”‘Ãäõvc¼y¿»B:¹ÀaJjLi¡˜Z\c²T¯¬Ù{NU ×[ïÆdÊß7:W @€ ¾#9L󗹿‰Í²èZ·ý¡§1™2¨˜VÖ˜"‡iÙ&¿ö5ˆBã4ƒŠg "€ÆÔ °ì€ BiªË—Ìõqã-Ò˜N,9• 6Ŧ¸ÃT´ö­ ‘œŸN.š_˜Ÿê0¹¡¢b(¦D:9=Æ[F¹*¡˜B©öPLs]F¹ÒPL¥SJ(&4¦¤Ãtõ #/íõ÷-' iLª2L&¾‡ ÐÁîàÊåÒ|yÔ˜bŠR¤º¿ÈIþScIâÊÞR"ê’ ò.Kq¸ð¡Óä_ ÓûS˜º¸`/yQã´Lõ LÕ¦ð!µ(0EÝÍÁCOX¢ÖØck˜ 9ž¹4—\k8L‹·ÆÒÉ™Ë_ŒÆTÆa2é¡ñ“ýÚ|wçZá{Dÿ¨¾óýC»Öl ŸS£ÜÕî9UUsËÝ|è»ÿûz϶««Ë‹ý¹k×.-ØÿªÖë§ÞC$·í¶Þ®[·®—{¨÷ˆl@€ 8æ0MŸ¿Ü¦wû³ƒ‘5ÛÇ>õÜý¾ùÞûï× Í5Cl¡7­µ*Ýß@Çòÿ´Qìíõ¶AʵžbÇ*w’-«1™ÃôÒ²M6ˆ’¬}5N9¬WÓîîîmÕŽ3dÕ2uð]CØÅn¿ªw‘öº5Zu!îµìªö;¶ÞO–moç¤WgO»Æû¼gÒ“w¡1õ„ï :Hczì©©©)>løé†Pc**ÿцpt)6ÆT6Sa8ÉÉ­É%sɉ;¼8L•¦âÀPqHHóáH—NnµÆ} C?‰PLϯxÛJ]¡˜|Éf¡Gi4‚PLA4& Ö(Ó9±tèí£?þǟ먕NÙTq˜®¾ñe LÎ!‘v¦Ê:´ÿq#GÝ[ï妎UÞIò±¹ÞƒÚö-÷¬Ø³Ëà]h0Ò¡á õí+Œ…¡áÃëntûºÁTŠ»g°¸i¨›p ÜiL•б”œœTXðŸíÙ±4ÒRl©Œ´”ð–Âðžå쥷>ŒÇ^*o/¹GÏà´4…œÒÉ9•>J!—©'S8e6˜\àÐ4‡é]{x-¦CІ°…€¢…˜¢E%¿Þ\r½ŒÃTÆaÒsðƒ–T.æ0…Ä®$5&ÝBMøpV>„ý£Z¼öí Ï©ªˆá£;èúþ]éaqï½÷ön6L ýŸþýûkyâĉ¶^?þö±?kd;hï²Í  S8p v2gΜºÞËÆ€ @€@/ DÓóËm€¤˜Q®08öXýîƒO>·ÿõ™Ljžìµ×^Ö ±Ÿ#Fèlõð_ï9kWj5T~—öo½ðjbhÙoÚhYg2vìX·k€¤îPm¥TÕ#ÙzÒf:v¥s«zz­©1™Ã´`ù©Su#¨Ó gS±5ÂR´㓬 ž5EËÝ®!l»µÛOíͪդ[H[ÆvëßÃv÷ÖrCV½Éu2õºtÉÓRÛõåxºIòôÊ}0ëºÏ«^uf 1e†’A€@:iL<9%Êì‘6Uþ†áwýèØ“CNNÓñ˜bYä\¦@` ¦X¦pðèýhب|.9Ëí'èˆMk/:L=J'e” Ók¸trʰ¡¬…Ä[•XC“Ê÷£¤r願ÊiLíþSÞnAs˜¢ÆWÚ{?ô¨úL&¿ñec@µ4»b͵ׅò­yբϊµ_ [B Y74l-VwÉb³.±WÇa°¸WøZï͹Әô\è%€ó“ÁŠÒ ÃGº§Fßywò{Ñ‚[*¤%.d‹SÈ¥òQ—¢ÀK~´ÏbÌÏBì¥Úí%ÿIÔ%6É•¦KÉ"—©D`Ê.“VôE/Aò +#1ßÓóƒdÉ~¾äy…gÜØ“nð°[xÞ-›K®¼Ã$—ßiL¦ó[ñ¦ÔhL}®1¹T…A‚”Ù®öœª¼Ô7Ýõh]&SÉÿ¦~yû3ùϬj¯nê7a5&{Ƶ}º³j½/[΀ @I î0ºÑ]F9› lÍ“ž˜]—É”lžÄž5:ªV€ó3’¢†>1ÓHÛ”kÅhãT¹$µõäÔ¨ vˆy jLÎaŠ ¢¨ö-Ÿ…_û7×Ù8Õ%árbPÌ3k„Æäî™Ú[¬É³•{§îTW=hTõ®wƒrw]…në 7j¹¦Ö×~Ÿ×{ =ß©çìx' ÔD Иž˜R: Í“·á§ë5 ủÉäUì%?SY©Äa F‹ Q35N䆊ãè0­³|Ð%©9êq˜ÞÑXî ã0=óü9ê.œ¯1&åÓ5¦›-“†Š©8j“)o“¦a7Þ!M->‹ t‰ hTîzL¦XãKá9ky®e›ÔŒÉôÖ¸kÅgÅš>ålæhèаiL®MÝŽƒÅÍ»›u¤ÜiLz.L:InM¹§ÆXŒÊ(C\i¤¥¸´¤´qQª¸b¸¤·KS—*Ç^*o/U ¿d)ríÙ4–B®—ÓËQ¦ ‚0•u˜ ¹˜Ò¦@Ûwæ~àïwù¹ä¶X$Rÿ!øÁ‰A4¦ S jLÞ?ªÄsj¡así9UI©oùHí&S/5&=nºi²ZÖ¿==ƒê·EÎO®‰u [‡¯½Åâ*iÙüYíÖžem'¶Y¬“T/5h<£YßÉ€ @íD@ÓW¿ÖoÆóË­½\Âk ßûÒ«AódôøYµ›L©“j˜bâ RŠõÁiKüÆ5%´“˜Mb~†í_Ëþ«êÅóÃ/é%ÛÌoæX›E/¹·û ­×N\{Ç÷Z¬Ê“ç»ZMcò¦QÂÚ¯«qꘘ1#æ÷±jKëfµêóo ^²ÀWÚ›5Qõ§Ý*¶s­täO+×[‹ËBY“Ó¯YSÖÔ€uïÕ‚_wÖ†uéä쾪pCº†s¹c¹Û)Ù|»jÿ¦•>å&ÐkAº=»öµÝó®“ÚnÑäÇGGtŸ,½×.9öéó?˜1°>ª÷yó¾јšÇš#AÈ)iL?19u@ʆœ®¿y¤K‘æÒÆ•Œ4EcLhhÉ]*¤KÀTs¦õÞ ‘Ëα6Ê%'=c‡iٶذÎì%ÝÅÑœp(GÓ@_còÒÉÙäs4¦Àaúmà0•âîÍ! †‡V¾sð‘ÇÖ˜].Uc²‡X÷àgc4å›]cJO†ÉæXãÈôqß-ô¬˜Óï-.»E TÆà«»7CÃ6&ë>€®…èêZ Ú¨5X~û×õœh³ä—€û&q U·ÆIÖØtíe#¶&¼kfºÇ®!›HÆ`q‹ÞÇužVþ4¦›G&œ¤ày±ðÔx§ž‹ÉàJC+Y€¥])n,yÁ–JSÅ¥…\*AÉOŸû`ú]Æ©s-÷yåOA–¯¢1eI“}A€@ iLŸ*?mþðº›ïüáÑ'–OëªKÞSÜ^ G”ô0feåÆtÉeíÐ ‚•’ L¯¥aò¦pB‚MœV€UMNЃ}”#x¼¯!Se‡©RÃiLA(¦‚ÃäÜä\c*q˜6¶,°–÷EÁPÝ÷pÅǪÑdJ6¾¬µ¥':÷dhC0å›í)ÚeS˜ýÆ‘=…úŸœÖzVä[ -CÀ.(ŒQ\½´¡a¯õ]óа5 cyxüÆ©µò\šu7;Hïò»2üNØ—€k[S×¾[¬nßNÉ[ÖÇš™ÖzMm)3XÜ2wnoO$w“ž ”t’® Ÿ£Ã’“\y+­T]©è*E"|š±”¶¤Å¡®äJš·ä?q³‡[­D!@£@ ÁW•_ÜÃhì‘4~) … 5UÓçÚÇŒ{›D[úØ=¼úϯÅr…~j (”½Ê"ç²&Çr'ׄIOÀöü@éSÉDr­©1¥ý£òžS“¡˜¼çT¸ºñŽšL¦ “û7æ&nÚ?›ä³¦Öû½œúÓÞâÿ3‹õÚ›Kë÷öºYgÑêÿ¢vâ*üÿyv·eo¿y? @€ P‘@‡©´Ý2ʹnt%˜¸ïñšL&kž˜Œb?vR.«:­Ô±4ë>sG¬©â[#¶“d¿yLcR‡šíDñ¶à÷ÙYÄveaoôvkÑ8)ÖêñOÉ:éìí~O_ê­£1Y¦‡©ü J¢ökmœ:Â®î  µ@cšš­uŒÚ=ãš™®:lc'¥ÙÍ`Õçî1W•v¸˜ÆäOò‘ig!¸\ÝY÷®»gÜz‹È¥-õj¹2ÖεCÛ¹éÇŽåvh'ì‚"».àØ™¸û6y¯Ú’ôìüÝ~ü[W·ºQŠ}úÜÓ®ÑNX îÓZã}^á#ñKhLew€ ' iì¸ÉeçÆoþðÚ›‚©µÅ´ñ¨K±&\©‚½TB*ŒU˜vtÕ„)ÕaŠÆ}äÊæ«o‹ç’«ÍaR2ïDc*q˜A˜\ɳÆä9LQ$T jV³•<†•o+ÁŸRûtDõ˜L~ãKrþŒ÷8ª§;³öS›cÏÞ±‡ØXã(Ök¹gE¾Ò ÐR††ýÖwFCÃîCmÚ¢k!ú­Qû[KÙ¾"lÄÖ%…´Î ×L¶d­…¨·X¿þtA‹íî4Ü—‰[ãïÙj¦\K™ÁâÖ¸s38‹ÜiLz.ô -Ý[±èÕþGŸ`ZR¬øÎ»UòK`Á»ò†\%+¥ÆR™`K´ä™ò©ÞROÔ¥BDÐò™ã‚©±)öRA´¢ÏYì¥dø¥È»÷òÇü¢À´2šhë&{uÅeG.›BnÙ¶¹aò8Wž+¤L–ÃD ƒŽ–Lmßâ0%³ÈÙ°ùMcòŸƒ“Ëû|qÿØœ‰MÛ—¼É?UþQùƒklbD8B3!”…:|N»lÛõw<\Kv¹¤`dÿ{\ç¯=ÎÚ—ä71ÚuVÚ¿¿çÔÖø íO¥ç»·zÕW}õ§í·Ø €&W ‡ƒ @€@> Èa’Å2=Ì%ÃT¡½0Xm@5OîylfÕìrÖôHB¶¶†…7W»ÀfDhcËœeÛÇ‚-e¢1i·:f(ZŸ¾ëÅ3Æ·m¬[ß?y'‹Øéù]ÿjËÔV¶E4&—K®¾Ú§éƒ[õ7N}°®kŠZuû'±Jñ«ÃÞëß-Ö\-7ãÞëßEVãö«ë˜ÆäÛuÚ2æ ¹›Äîÿ¬©›jò%ï"]‚%Ôó?/¶Ò€.0†¥ÇSòÓ§ãÚÑ­ƒãîíïóæ}©¢155G‚ SÒ˜||rb@ª8ödRéƒM…a¦Tu)6Þ’;'í% ÕS1SI‚›Ü¾Ð†A˜lÄÁ²¡ŸÒŸm‰Šw¬,­˜K®0 cC9Ò˜.’Æäâ0•:LyN*8L7rÉryC1•z ÉYVUM¦XãË>Ör±üPö£95jL˜í%§;è(-÷¬˜Óï-.»µÔ?4\ ÅT×аûP뮨ÉLÖ8}m:µ1õÛÒ¸˜Æ{¯µpÕi£CØø¯k-Zó¼FI]@vž©ûg°¸µnâ^œMî4¦k~{gRBrkôjÙ§ÆK©Œ«T>=\Û3!-%SÅ%½%ùÓ^J‰ºä©KUì%/ð’Ez÷Ã/Õ`/ySøä ¿d™R¦À^ :.ëH!D`ê…Àäg‘󟀄iÌ„öИbIOíöˆRË ”†b žSÃÃu#ª›Lêy´Nyý'pÝ ¾Æ¤—´ë ôŸ5]w¼´þ\ml±ëcküï.7`Þ® ]è?Ûm Âž•ýµôû÷âÛ’·B€ @ S”Ñ J7z4ËBÍ“»­b2YOºß3eýjX„$×r±‰6ÕAM{£ßTqvHÌñ+Õµ>üfH¬3΢.Ùi¸É–7Á^²ž;³©, ¬,Ѷߣç¢Æ¶L+hLÎa²¬%ÉÆ©% úÒòY³˜ÂA”§F8föX¨®­Ò­ýhÝ þ–U5&kuZÝYMé-Öãé†p\•ÅÎÄÕ¬ÛÒ¯ëXO®3~´gë«­ÉnokJ[Œýä±ÜMk[jaÒï˜Æd{s÷¼b÷ª¯1Åí|ì“¥÷ºQ«ä§Ï}0ÝÆîì„k¼Ïýdc—јË—½C€ÀiL<þl…©aနKŸŸHåáÒÆE#J±ô¯CÉñ£%…a#Åì Š—£#™#M`ª3‘œç0'¨/é.¦×X¼u–•p.º?=И~}³Òhhì&5‡F>£1ÉaºÚs˜‚l-aE§¤“‹¦¸Óy»Y–çäG3rÔ½å>œ1Éž±­ÙeÉö(hFS›ý§ñÊÌzUû¶AË=+ò¾&à —›?¦Ö·Æ÷í«[y?•ôÓ ƒ]GëÛï Ðg_a€­=èÖ[ËTk,°uth!Öõ;=b_Öt5¨öMbcÇúÓ†õ[X_Šë]q'k“êíåZÊ|™ôõ›Ùñs§1é¹°*ÉÅL*.O?>AQ”R)¥%ƒó›¢4gáÚb0ÏPWzîåµ`É•Ù/¯ ìx/IÜ3³^ytâs*“f½>‚DO!•³ÅE9ŒS£.…£Þóhx©¼ºôà³"Å>ü¦?e¥3~¦•0çq1yÜc“_2uÉì¥ûÇÍÊãA¹/,1 ß (Zj/…O´*c'¾¹ù…ø¢ÉÜB¦ üR˜*Lu©-4&ïUpÛÈÄzúùMO=¿Én€BÃ#ê&ž¾hs,Ó3/½i¡˜ì9uö’­×ÞþPÕ˜L¦ÐêÇ=Gê?GÌ`µ ¦Z \o“þOØ|Vý¸7&׸/3ûïeÿ¥ìÇþÓø¾íÇþ9Ù?3ׯJ4¦Ìþ-°#@€ ”'à&7v¢6¬Âè>5“J0&‰,–5調t¥²«m8ó•-QódiawÔ#3*Äd2çÃÿ±FM·pÍ›)h 39´Æ¥¾²«qM×qf³ýku­äT`×ð±öˆ½Ëthk¡¨#ÏÖXÿšõ빎–ýÖS¬¥SKG[ŸkLžÃ5NÕ“àfù[-¦Xœà•o?ûÒ›ŠÉ¦*ÕÒ85žåš{æ!©»S¿Íãñ·mýé¯qç*ºbõãš–6c' `ÜinËä™hŽëš®®®Ý Žk™É”zªÉÒºwõãy$e;·»Èµ‘ý“qG÷û‘“÷ªíÁ]¦;t²¥o··±Ò[R?}n”m¬KnéöhLü³ƒ Æ4æ±gÓ¤¢<Ã~{ÇQ?>!Š·”–¢Yñ¡;þÜËkb“ᣱ¤‚Ñ2ë¥Õ6œ” ¿4ýÅWzjöSÓŒJ†ŠÜüvwA˜ÜxÅõ˜÷س/i (œ¾Í`wA˜îyl†žñÊ%’³Q pÇ&˜|‡I™4 Óæi^"¹œ'•3‡ÉM!ã¥:rSè+¼c¡ TƒáØPY!¨…Å[¿xY“Éo騇ø5¥@xöÔm/%›cÏíå˜íXR”íÁ²mð‡’ÝC mƆ5Mèé‚¡a}©6bh8ÖâB[ Ñ,¶–¯¥ëÑ»Üw‚‘5$c_®Ak€»ïëÒŸnHÚ?1×&uiì’_2 ·Í-ž¨Ë*èNÛ_SEcRõÛ 0÷“\ÓF8,î¢Ü£Ô¢‡B= è©ÑyH• ™àWÉ)J_üòןôœ{ ¼ï‘I_øò×,ž§+Z#c)Е¬¼þžÖ|泟×oWì¡3o)é-U ¹”¢.ÙÓÌçÑ÷ ¼ôéüüãgº'Ôûâ~½4n¦tK-«|뻇h›~~¦Xõ´ª5z<²¢ç×}¾¸ŸÊ§þñó*Zøæw)—<.5ÜÝLÿ×/|µzþ¸% ©ð¤›L!WU`ê½ÆôÇOvvmúÒæóúÐ?ªÿþ¡]k¶™÷¦æ¨Ë§Z9éšYž?áîg׸n⦯;â²)Ñ A˜¯áÞÉk<Ù…bÒ µ†ÝVÝdjèuõxç Ê=(ÇFz¼[Þ@€ T%9L󗹉€š„sÆðùÖB9rHPÆÏÛèºÑ‡Ü·pȽ ý逃î~yÐÝ Š³,Â1Œ‘L¯š]®ê¹ÙêAsÝa6¹¢Æ7¶Åf}«1™ÃôÒ²M~ãtè˜W¢žŠ×vüúþE¿º‘3ØN¼z棳_·¹Ojœj¶ý7ÏàB1Ù J[7NÛâžá$+@câþ€ 4¦GŸñG£bCN±©p¤©8ØdÃL'Ÿr¶6²¥knºË­1uI#¶æ¨£OÒð¶†ÜÈ‘Öìû¥¯Yùö÷M ¿”šB®É Ù0Ðñ'Ÿi£?§ž;ØÒn|ê3ŸïY"¹™a"9(ç{a4&ß[Š-WˆÆ´õ£9Ϭ;ð£?njp­6u÷Ãtƒ¦(,‚rq˜ôø­e\ýnø¾>šCæE9îÊNÍÍ"°á!ébb25õ 9òFàì¿ÞóÔ ª¾bÌ+:^ }/5 »´¾«Bgƒ¦°Ì€þackÊjL滹 PÚErMÓ/§·,üË·gÁ”¢‚#|B,xRêŸQ8¥Ò J?<æ¤Ï|ö¿>6ñ9ÓMιèrý©gG§+ÉXê´¶ùü#žó#-i›³/¼ÜIK?ýåÙ*U¤¥”xK¡·o÷K,aœÔ¥¿{H”6® ×KQ’·d˜$ÁÈR=næèq3´Þ\{•Ù‹6êO‹½¤§Uy÷±Ìqû|a?=¹–&BŽb/¥ÚK.5ò¨G¦Ic²ðK~ò¸‚¡tnÆÂ/¹p£¡À´Å'—<ò¾²EQ‹JRÈ¥ùû=‹Æ´¾{‹¦ÑKÿ󨮽ÔÜÛû²üûíÕ+r˜"ã-ˆ «ÿRÑ,ç×vÈa:rÈë&¾ü¾…ß:o‚4&7H0øž—ÕM|ØàÉ~(&{N««omW“ÉÄrŸ=C€ @>s˜¦Í_fSt,ÏõÅ#_:}ø|,Ñôî[ž\©ŠM>õ¦yj¡Hc &ÀhÒöŠ·üv®Z(—ŽZPèFfY¨yrçC™™L0Fíɦcê±5&s˜^”ÃT˜‘eÓ¡£_q3AÝ ÊÄßPËTµÿÈìõæ0xzÕყ¨ö½Æi±ö‡µmã´cn­œ^SN+žË† Ð<Ò˜îä™ÄPT1qÇÕ7ŒpR± öÐ5{Á1-X¹Y“~ö˳_qƒžÁ4ÀôÒŠ·4~¤A%•«;òÛß?Ô2ÇÉUzjÆBKà ¢LŸùÇÏ»1£#|â%¿º®$üRɆll(,ï¸Q!=Ëi0è××Þaù7T4‰Ý¦oþû!6îhLaÖ`+±<šY­œÅñ´ Lnç{‡-Q©^iýö™˜4X£ÒI“4¯ºa„k|Y"9›@òëÑ‹TË ‚«'ðË¥1­Ù>ñï <Œ˜õļšâ®'ðHc*Ì"Ðhš_ 5&Só¾ 8S÷Ú£RQfJÖ "}ö#EuÝŽÓnž(Œõ Óúæfl.º¶;Ÿäš²“6µ(è.SrM‹\gí§ý×7÷È/…PIz&8òG'Ä‚'ùC(¹XJ…)ðzޔ䥳/ºüÞ‡ƒhLÎXvÓHùIÁ6O?çGZÚ÷Ë_;ëÂË]ŠâŸ8+°æ_ÛqÕ#Í‘×o{î<ó‚!&ÎÿdÀYZûÔ,gÐø½C|r–Œ–“~qÖ¾_ÚO刨¯°)óWýÛ—ö“º¤ßW\§Šl$ýéžM_~5ˆÆ$oÉžPU¤1Yž¸@c*D]šjL“ž[¡œqzru­Î[2É|=¿÷³3öùÂWå'ÚÿËwìÏÎП¶fîÒâã¬iL¾À¤GÛ~ß>Xå_öýꀳ.•yó‹³.=æ'§Ûšƒ<ÞÂ/iù€ÒïøôçîxpŠž½‚R´—¢ Êåö ©ÜšÍ›g¬|ßâÿÞ‰ª1ÿ¨¾wè¢ÕÛ,Ï  «TOÎÛh©w?»úÄa³,ª–&:žDcrƒҘF“µ\(&›ß ÜÒWÝ2¶jv¹Ú?_l @€ t*ÀaگߴyËbÍM|nÉÖBªë —ܤ—ÞTóDÝè7_!‡é2iL…nô[6hÔ‚Hc*t£k^Š5Oî;-«˜LZ }¥1Ó~ý^\º)Ù8µ”0AÉvDQíß5éUkœSXûjœŽŸ»1И®ŠÉQhœvêÛê×…ÆÔê5ÄùAh{Ò˜”¯£Âx“ H¥Œ:½þž9+~ј‘Œ% -i€ÉæÀ?üÔl ¹ÀKÏ/{SN{áU „eûÔçWiLç®'X´Ô¹‹ß°¡„q¦eáÐR0Nôê»'þ;oåÀ˯ӂ¦‚VyKz–•´d§*NcRR9‹êâ…ê(И¾°_2mœVžrÎ ð‡\3ÂÙKZ8oð5C†k,sÜ!GÞ aQø¥%Ýw=_cJÈL±¡aç/곯Djw[d•ptx}ök6…‘Ö7·dëˆ%•Ó‰ùkò§1]?¢‚“äžýgÄZ–å0=üôszŒÐ£¤¯(¹gJ}ÅÈCÒc¥zxõd,„Ñ•¬Xt¥±O;ä××ëYó©é/K¥”¢¤‡K‹«dšEiiÍö‘L8ãü!ò–ôÒÂРW°¥ž˜)iI[šJoϦã¦,°5§ŸwÙ3sWª+Y¤Q\ÐBÂ8Ó˜¿>,’–î|†t¥OýãçõÛÂ/¹œÇ÷>hLÁ3k!ð’©KЍ$É/ÉX’·dO±w?2]/I]ºìêÛM]ºKá—BoÉÊȇ§ÉU²Ìq¦ÚèÏqÓ—Zú3 L®Ø3®"0é·¶qá—´|ûƒSaßJZþ¸T¥©–¤r_é÷•Ñ3Oð#0ùvÿÝ‹£°LþÊ^.ÿlè^ßþÞ! Wu»{/ÊÑNrÕsêøylþÄðñ+ô¿ªîõMuÕsª?H`“)b.\£µèxa2µÎ÷5g@€ V#:LL™»ÔoÛ„ÍèU?šFMÔ¹^4¦"v)Ìz.,šËæ/{åŠð©1x@´â=&VXÖ¤­XP¥ ýpè'ùÏ”ÅmB9É\¥®°¿O*´’õý)9±X2iI¢’_ä*ÙsçÈž–±ôÀø™zô´ôpZ3~¦C{Iâ¬<>yå‰=nÆ ??Ó’ÄéÁÔ¥Šó½%—'NO«½ôØ =ú9㮽íõ>ßó¨4¦¯šº•P]’«ô˳™º¤üq.ÞÒð{žÐí±?=ãÜAÃÌ[ºùî'"?LŠ<ò¡à)Öb/%Ì7ú©ç-sÜÑ?9]Q—~~æ¥*– M“~k›ûž˜oáFÿy߯SÍö’ûš®EcÚç‹û?ðÌu垌Ǯø;å]ζÜ:áËê)~vîR»ë‚ýQ”þ T Æ4ÅÙ¢¿jò„f¸>:ûuKV­©®zNõ dãê9µÂ PœøË ιpp÷{¿ÿó_þÒ'_R€ @hY;wîÔÌ£“æúƒ(®…¢æÉƒ3^ "‡-µL5ÑBs­É)‡I%öÚ‰êF4¦»TèF—ÈòµoÿËý/5ií·³mguÆÞnÔÌ[E›jß5N£öi”¦DÓõ¢ºÚ—ä4‚f°Ù Š^8ƒMµ/Éæå‡ý’8ÁÖH¿ðW7ÿð€}ºoìÿg…É¡@ ÑÎøŸöœþ?5óű @ oôuÏC“¢8:%CQÑðÓ×Ý H•êJÑp@aPàªGZ’¸PZúšÆ•\Ê !ø½CŸœöòÈ'èi\ESßUlÉ/iÀÈÆäškÀȦ»k¨HÓÚ­<öìK§{Ù 'ŸiÚUyæE~éáIA ¹h0(Òôõ@`ZhL6k]“?_}ÀY—ó“ÓIö’Šzî;%ИÂÁ c:¡À”ȧQ‹ÆtìOž±vp¹içÖ~­Ýû/¾a?ÿ®(7<¤JQËëÔ›æé Ü¿5Àwø`{¦P2;lÐäÑÓÖ–›âþĬW÷ûÒ—&]xÄG7ÜÉßgýÕ=øÿŸ)è{å¦d\õ…M ¦ú­ïØg_Mï [ahØ9L5 ûYz¬õ­¡á£Oí÷PWÿIk3ãn÷/á k¾&jíŽÑy{hé“ëEc*јô\Xòè‘pA¯þÃãS6ð"'¹J…Ö‡2*zŽÔÓdà'…el¨"ùaÁ!S„I™4ÅyØØ%zTU][¦jÅ Õsªë&VEÓ É ÌaÒÕ©`25¢*Ù' @€Ú€™LLœkÍa¿yr×3«Õ$¹yü 5WÕ:Sºþ|jþ&ëF—Ã4H“×.‡é’»^*v£'¦~ï ÃVmxWÍ“-Û™hÑ7Ž™LÏÌIoœj¨ ’©›Bµ¯ø[Á JØÛ ÆéØpÅ 6µO)Êu¾5Ç*8LÇœHã´%j=''¡¡,4¦œÔ5— @ è!êî±+ H]HŸ±K›lŒÉÒtX¤%7À¤$ ýæú;•¸CIsošÛµIcCR—Ì[Ry66RÎ8‰æÏÌ]qøOÐhшÑOk»F‹ô̤»ìÚÛïJkf¼¼A£BZ£"›‡`ö’2o¨<9k™ên¹÷IIKš¸®G; )ü’&­1UÝznºû ý¶råÑõ; 4¦ÊS½IåÖlÞœ*3}ôÇM}TÛYvôèщ# €ªÛ`È—ÅûΉ¯*®žÀ­ñõŠð |ÆkÎaÒðÜ¡ƒ&ß?u­¥óSøêXà0íÿIÓ_°'ðvÿ)Ëkh©} þl iñV Ô˜®úž-ËíÔ¢ÖwÚа‚0éãïZßAÉ2CÃj}§ {æ(CÃîýAcjÚg¥WÓ€Ö­[çŸkrMÓ®¤÷R4¦¡×ÞžªÙJ½ª‡'!¥,„“*=GJ~wŠÒÓ^>âÇ':?ÉôpùÄÔ—-œ­Q¨OuüY‘œ$iiN×&KZУ§6p¾¼RÂi~Ëš×Ó§b/iYE çÕcd2þÎ!zîÔ ¶¤GO­‘¨tÝm˜´¤W}6rêͬV~a?‰JÚLнžPõû›ÿ~°r鸟qÊÙƒÆN|Q­‘½öEZQÚ8‹À¤g#=¼*ö’t% "jO±ç^­ùÅY—ºÀKz~’·d!F­˜ÀtôI§KWR¹â¦ûÕ¹yÖÅW«˜¤oö’žkvÆ%_?ð û݇Io©Kc²‡9ÉLãW~ÃE¥kÆdÿ®¾ôÕ&=·$ ÑÎoV‘_¯LVN¹i®X7±’"¸q®å<¶nâÇfoøù sʹöþ?*:‹{ÿ à @€ Щ"“iÂ×v1x˜¶îÄ«gºÊ”—߲扚™W>°øÊ1]Ånô%ÝCG¿òëû_ ºÑéرæÎa²æ &S‹ÜNÖ—ê§QGØ8½fì7 ôê_õàbWûjœŽŸ»Ñ¯ýc3£œÁæ;L4N[¤Þ;ÿ4И:¿Ž¹B@}L@OP£ÆNL HEsà5ü Hõ?ÎRv¤=rÿöα~÷PM}× ‘ ŒŸŒI]ÒØÙäšñ®1#ËføU rt¨HZÒØ½ ­ †~uí iH£B6<ô«kÂ5_Øï”sqf°kúº¤%éJŠÀ$‡Éb/iÜG£9<ý¼Æ€l¸gÌSÏ|äñzÔtåm|û ½ª zæ¿ïÉùq|¹LþÈN-јœø®‡F“™î_òŸÝxMghLºqC“é¸dãKOà^(&“:ÿöôn“êQOàãæl´8L–ÍYÃCÏzÝ"¡úéäbS‡›LhL}ü]Èá=¾Æä Ln‹XëÛ:^T®yh‰>þ~¦:††Kû^®|G¢15óÛ¿ÿØáü5{5óTúüX¦1UôêaýKŸ ¼˜I.xRLKJþé+JÎUr–’=Y–+…§L{Ö,>nÙ­¬ Šž8Ub¹áì;ËŠ‹´ä\z8¡l)’ë“©âb!—ì(VÌ[r%–‚$Œ³RL挳lq…²Å%EÖƒT1²høPåÇ ¢Œziã~tâi×§gܧæ®UĦ¦iLzžÛ´m—’b*,žŽ§19“iâ¬%QœÀÂ$W»7ìfp¢}”ðØs˜T#ª…rÝÄÉTt÷ùw'@€ –%`&ÓCOϱ&°›˜Úf©®ý8Laó¤;jžй&žrÉÅ&L¦–º¬/5Ù8µÚ/iœ†[1—œ ¢øÓh"ø׊O:L4N[ªö;ödИ:¶j¹0@­B@Ow=8¡‚¢ôëp@*x*$ëpãM%ÃL…9ðñq¥h©8ä†J‚£â˜QÚQ{)˜Öîgáðæ±»a hÈúIî±ðKRÈ%ÇtêÕ˜ì¡ñ½]ïvm:zi 3uŒÆd&Sp{ÔØø hùq˜,¸@ê÷T‡©“M&4¦VùRä<öì1)M`Š™L ÷Õí‚ÆÔWä“ÇÍÆôëknYGá³`T~uMðÔX Ñ’ÒןTANr/%,¥4Q©à*™±dÅâ*¹¢tÅ*©º’3¯cÞR`,E]ÉuHKÔ§²·dýѾºTâ--ŽyKú³u)ÊŽì«Kþsí½ãçýó¿}Eq˜ôûâ+nm²ÆdŸ%ÉL¯¾;2õó”:4l£ù©3ˆÜ8{††ú×;”z7S£ÈÖ¿ßÜiL¿v[ÙH¯ê=Ô¢%½\òìèB(¥ÄR*†SJ³”Râ*U ­ÅX ;ˆ“¥Š±JÙV¢ÜpÞBRZryâ*„\ŠyKUC.Õu©g~RïêAR9‹ÆTõ³¶÷m{WÝ¦Æ “é+<5c± ¤”ˆöÉT¢„l-´*ÿ£²GÕw?ø¸ÆÓc3@€ @ ?d2Ðï›>ù\r~EÔ‡î;L ‹¥^‡É™L>aÍéw¿ü0o+Uãôëý¾5Ncúš x³ÀS{Q£dƒ­²ÃdµÿöûAãTc$«¡q”$ÇúgÖúnÔœI3 15ƒ2Ç€ kÒ˜îót}R)ãMQz8?ÌR|ê{” £$GGÊ,÷0Zj,#‡?Bä UнT2q=ȰQ̳Qgø¥Ø8No4¦>¹Õ4¹¢Ñ “ûî»ÿÐ£Ž³Ì-nÑ L)Hzç0Ùøþô‰ñ¬à*i.^íìu©nd¼¡ï ­ï ­ïž û3ˆz04,‡ ©ïo…ŸAî4¦Ë‡Ý–)²Žôª{ pɃË-D)ÞJs½ùñ“*ÄRŠ‚*À• ªT©S]¥¨‹0`©ä1´¢±”i©i)ž'.%UÜÖXª¸2ÞR!äRi¸%¤ÞoÖ ©¿ºQoÛ{ÀÄê^8c ¬X|¦î]ÝZÖ‚þÔ–*Ú¦ò·Ðºõ¯ñ+_bz—‹ÀMqNÎr6ÙÖ Mä<®åÕ–í¿ÿó_þ’ã/F.€ @(Kà½÷ßßÿ€o>ðÄìbó$TX\ºËe›bÑc‡Éu£ëœvýq—P-˜³iŽŠFF,¡×¹¦v–þ´–—uºe(—¼þúFÕþ“~ã´¶Ú·.‚0«ÈfkË×â0©qúŸüE“Ù2™uI&Ó’û†©lí jyûê.Í×Bl½ÖhXE›é½ÔÒ  1qg@€@ƒ HcºcÌÓt\>ìÖp@Ê•ªÎ/ *ùIâ|©Å%æºÞRqÌ(1¹=U]*æßð3ÇU°—¢Ç¼*6ªè´—Æd“+44vùX5IT4Ö£eý¶;K);´Òl$H¯öà¦9ê^Ý'i¯âüvo AÏã0EIú>üƒ¤§õ®‡m-¸Ø¨²—¢« C4%׿1o¢EQm!É ©·oiÖú®04ìç‘L.´¾{04¬ï+}¿é[NßuÔ¶¯8[66꙱έ±¯¸`–Á))ˆí"wÓ«o-gi½^ÕÓ@걜neÿôÌ$ÉI•ý¤Ê•›z")&ƒ‹[ó•u%[JË —j,%3ÄÕ"-%óÄ%½%? ²:.]ßeՇׯmÐ I_îf&ékݺ×ÕÕîâ3éOû–×K– AV}~•Éô…¯|}üôWbSRË›åì u÷àUF_5ì€ @èf2?Ëš'±DQzé‹L&#h=hjdYg™S~|&yKzU“\0Piô éΩ×Ú®ÄúR]ãÔôµ`lÌÂ<[ã46 ¼“NJ®’FPôÛ²ZhhÄÖhÔÄ”&mcëU´^›ÉyÒ‹6ÓoÛ€Ä  1qO@€@ƒ Hc1úéªR)ƒM%àKb,¥K¥3ÞK½%÷V&#‡‹ºòóo$3ÇGz~©Ý£1©=¢æ†î#ÂWÄo˜hHM©=¢Æ‹Š´Mî;™L‡y¬…¿-6¾¼,ÞþÕªÌêÈ ÃUÍ%s˜ì$õŒ­'jAÙötm!Q¥+é \ zêÖüÍ4Ð[4÷@E ©±T{pù½} So òþ>#k}Gñc­oŶH oÑ ‡É.ؾ»´ n}¡iY-n ™}¡9AS/9éÏxeq`4¦,(f³µú®77_›IcRѳl-qùÌd7õ•hòD¡áaÕmµiuç=¤ŸSq˜²ùÖd/€ @€Àž=f2Ý7nV‰Â²,PX\ó$%Ll¡íª[Æ~ï ÃVmx׺ËS‹"ñøq˜u›h]ixÉͱŽ65²ü¹"j‚Ù~²"`}©ã¦Ó¢ÀTsíׇÉNØ…\²hLnÖkàÄÂ2iÅ/Ém2ÛÉÞ«·h›¬.œýt4¦ŽªN.€@+4¦ûŸö‡¢ÂJV‚ѥ˂©ÀMI-5ä舌¥Xž¸äàQlÀ¨.u)6ƒ= Blö6öRrúz{Ec²¦‡iIj˜Ø‚›ân¯ZF ÙH õìf•Étð‘ÇZ°ƒy‰)~ –hI¯&{Æväzö–À¤Gk=u»çsYM®É6s¯ÚtS úþ©ïë€3è9¨õ]Ïа¹ÇCÃn\[ßc.N‡¾Ä¬ƾ÷LÜ´ï7•ÎÈ„ÆÔó›5ëwæNcºìª[Ë=üi½^Õs@… ª¾ê”–T4“R¢(Åó¾;ô|銟“8¾ö —+þ3¨ž]¬&fTŠºRб”–.zN­UZê㫤yM±ˆ¦ÇØ‹X˜ØÞ8LÖYfcsE\WšmcS¢U\­C¸·ÆeX_j²qö?D³kÜ›žå’sª‘ èO h˜Ä,Ù˜ŠÓ•¤.i½VjKBgÉ,T\æ‹Ö ÇY´ 4¦–© N€@§ÆtÛ}Oõ`@ª8Ì8+%9:Å•ÂpRlü(9r3 ‡ŠRæ´»¨KÑ<öÂ$v§.•L\/ =Ô5"Syã¶Ó˜¬aâOb÷gSØ«úmÃ@6d¡Mzö˜LGUw!K4üçæ·' ö,“ÎйJöîì%­×²‹xªIzä¶Çr=„[´TK ݳ+Íø]hLewÍ&P®õíaÊ|hXÃÖ¦%ÅìLS6-Μ¾Ö´ûг4šíþƒÆÔ:5˜;ið•·†}éE¯tæt÷È&ÆJɃ£ÿ™&'™¥TQQR öJ–R¹LpYèJ5„YŠGZj'i)ùˆÜ )Ù«n_âöÍn¯šÃ¤ %Zûë™LN^XœâöGA˜¼‡T¦ÖùªåL @€ БÌdºç±™®¡Z¶-‹8LbhsBlÁMõs »Õ¿f¯º‰Ñ–{®#á÷ùEY_jÔ8-Dv!¸R{QëÃd×(É…\²±KW¡û­ „I JiaÓÁº¤{/?ˆ@c➀ Ætë}O¥FEcLƒ¯¼%J ª”p•ÒÇ• .‹¯.¥IKQÊ¡øÌö®`H¨¶œqÑHP†ÒR»Gcr “dhXÝYýq ›Äî¶ïÍ}'“é #Ž-ÓøŠÉùSzì0é$«äRËYfg÷|n®’]Ž›c`ÏÞNêÍÅfö^4¦ÌP²£>#PÒúŽÂ—$††ÃlY »qmËiWÍ^rª“^rI6ûŒQFFcÊd»ÉÆ4èÊ[Ruu³‹ôª\f?$Rêr% ©œ¢´´ºœEÖQß_ØýW®”‹«”Z)=º’=˜¦d…+¦4óæêqÇJ Ô3–¼ïÁ†>¶6zçÓ˜,:¨ë.W‚d=³ZøPëj7Cßf»5~¦ÍdzøÙ…6ÉÕ&×Gì?¤‡©F¤l@€ ôŒ€™Lw?:³T`J ¤æI/ã0é Õβ\rê2sSýÔ°RÏš+Ú̆ ìw½ ®žqÈ绬/õ‘°qê Léµß3‡I`5pb¹ä´ ‘Kf¡e›ù­õZ£?õ[ö’ ¥hE úÓ…kÊgqÕ• 1q@€@ƒ „Ó“–ÿ+µØ€Tõñ¦4W©8œT:–TLÊ‘o©0”àÔ¥’A¢DÔ¥f¨KþP{Ec²DKjk¨ÑáZj’¸‘ ›Ç®±!‹ë¦^ôò¾3“É5¾Jæ·CPkFµ7“NÒÍ%°hLzðÖ¶Ó•ô|n©œíÉÜÂ5©À¢¢:ó©—›ÍÛј²áÈ^ú˜€µ¾mh86}(;“¡aõ·¸Ì˜I?öýf=0–"Ó¾Ü,QÊèðhLÌ`7yÔ˜*<ê©QÿþçÊ‘•*$ws/ZR59©4ï›%€+Éþ¦¯¤úE¥‚«”ÈWNWê`c)ÕˆjÆ”ÁG³Ú.d2ýÛ—öè™—mª„Ÿ¦Á=¤fòªÚ‰ð: @€ wf2zdFÔ<±±¥}è™8LZeб‹h«•Hð×ëO­tÝmy¯¤†]¿õ¥§ej¿Ç“N\“¹ÝékÙ/é·"3¹DúÓ½dëOÿ ÀŽÛ–SÛV'@ ]HcºåÞ'K¤ŠcOÛ4~téo†[d ¥ÂÐRUc)!-Å'·GÞRaB{ÉTö䌫:k½½4¦>¼e2ýàðc*Ïoï¥ÃÔ‡W—ý¡Ñ˜²gÊû†@¼õ¦þLö½œøË ιpðú-U([¶ÿþÏùKß\Fk©uê'w“ž S좂ftIøÔX´Ž*FEª0)‘ßÍ´¤ÐLJ““ÊúIa Y¥=ý ŸÅ Ji¢RÜUò¢+åMW*÷|ܾ“¾DÌd;iATÑžeo×Ë?ªÖùªåL @€ ÐÙÌdùÈt¿yâ‚™gè0u6Æ6½:ëK­Ð8íÃÔ¦L8í6 €ÆÔ•Ä)BhoÒ˜n¾ç‰’ñ¦Òï—\H•IÍáååHZ², ~IŽ%3r¤yK…,}á-ÅnИj¿ãe2}ÿðcJæ·{5ˆÃTB©ö‹-[ž@ÕÖ7Cý¬C4¦^Ìðí¹Ó˜ô\Xúðç£`A¯þÀ‚1:åÈÄ£2î‘EHòKòÙ1}MWU9)J=h–±”j•J“ÁuJ>¸ªæ~-´µÆd&Ó>_ÚÿÁ‰ üt§8L~E²+@€ @ Ff2ÝùÐôdó¤÷¹äj<6ë+Ö—šÚ8Åaê«Já¸U 1q‹@€@ƒ ÓÝO¤ HE£Ná€Ô1õ 3¥OzsÃ%F‘*IK-9N„ÆT×-˜L‡ãg‘Ë$—\]çУ1µG=q–µ¨ÐúÆaªbùíИzÏ0«=äNcºøŠáL#½j‘Ë–P?²’pÛk\Sx ,o&™@¢(•†Sò"*!*E¹~kQ—ümÚ]cÒA`2}q]ˆ]ü£Êê+’ý@€ @µ0“鎱Óüæ SíÛzKëK5Nq˜ÚºN;üäј:¼‚¹<@}O@ÓMw?QÓ€Tõ!§-f¼u%o)´[¼‘£¶Tuø©Þ»V&“ ù`‰Ã”©ދí[ž@j뛡áLê )Œ™ì$ÓÐáô£‹‡WFËÔ+‘ÌnJ{ ’S‘ü…’§É0]eTm‘“ä—Â#f郦y+íðÄYõ‘´6è)i2ñ*“/Gv@€ ô€@ÌdÂaêÃö}K¬/‡©}«2gŽÆ”‹jæ"!ô%iL¿õ„7 uºxèÍA^°Ú†œR]%o®{að¨ÇИzp¿ú&S:@4¦ÜX¼¥å ÄZß gUchLY‘ìý~r§1 zsL0òþ.ÒSãaÇ”•|ñ¨¢„TŸ“äÉIøIMv›:CcòM&þQõþk‘=@€ @½!àL&¦Þ`lÓ÷º¾T¦6­Á6SŽ*›K… Ð7¤1Ýx×ø²™7^Ù’2 •˜ñž«¤hL=»SÍdÂa*K©g7ïjy®õÍÐp†u…Æ”!Ì^î*_Óé§ŸþéÏþÓ>_Ú¿\ùÌçöþ/ÿ×ßVØ ÊK_Ü_é½(mDàÿý×/ÿ¯õוOøû›ÿ4~Òìõ[>reÓ¶]½üà5âíÊ.÷ùÿöÏç\8Ø?Õäò–í¿ÿó_þÒˆ`Ÿ€ @€Œ@`2ý?ŸúÞ—þßUÞ­ÐBQóäúhF@}©ÿô¯ÿç÷ŽÜ¿jãô?>¡qÚa•ßV—ƒÆÔVÕÅÉBhGtÐýoÿÜé\Ž4ý—ÿßßj®ÂxøŽÿÉ€ØCæG»ÿÔŽ·G¶ç,“é>õ™IÓ_¨üþÞ‡Èö¸í±74¦ö¨'β'Ôúþç¿ýßÎ9úભo††k䋯T#¨&l–/içÎsJ?9Vî3.¹’5L jÇ&ý'hMIßOt3gùúʃü£jÂ+‡€ @€Þ»ð³®9 ‡)ŸwÂõSÿç§–ŸW¹öq˜òyo´ÐU£1µPep*€:“À¶mÛªkh©ê`ö¶xõf4¦äæ“?¸êñö~Ú€¦] úRå3IZÒ²d&ŸI¯vïêÖŸ&6ÉaÒšv¿dοs 1uN]r%€ œH†bò2åJò²Ñ˜¸Ú™€æ‰©kE“Ô‘¢¢þõ±Ø,2¿[Fëõ§6Ózm`òS2Tv;Ãhƹ£15ƒrmÇ@cª[A U $C1©UëŠó‚ @€@ç°¨æºYJZ–Ÿd]fÖ_fsþ´ .6ëD“Ædë­©n)J¦%)ä’4&»"Ks65®[©ßZ#‡ ©*½£.©£ª“‹ äŽ@j(&2¥ÜhL¹ûptÚ[O‹ú^4%Ì®ÍrÉ)&“uËè·½¤î?ÓœúdˆÉT× ÆT®†nŒÆÔP¼ì%°ûOÛžYw • k¾¦'ÔGV|Ö­Y»ctcÏÞ!@€ ¼pýb6ÉO=e2™¬ͺØìÇVjK“.ÑÒÏiA¿ºÉ.š)dõV>S½Ä·=SãØ²g4•SSqs0@€ 䛀³—Ü$?Ó˜~ɦJTRß™MþÓJ­±e ΔoxrõÒ’oIåd,Y&ýhþT‘±¤PLZ£­´õrå\Fg@cêŒzä* @؃ÆTñ&@câ3ÒÎ\4kÓ˜4OL=*¦+Y¤%‹­ë„ÑzõÉX.9ý¦û¥ÞÊGcª—Xã¶Gcj[ö ¦@cj*n@€ @€@û@cjߺãÌ!@(%@4¦JwŸ—v& KÉ…V’Òd1°õ[×d¿õ£mÜK¶F“M3kçKï›sGcêîiGEcjºàL Ð+hL½ÂÇ›!@€ @È4¦üÔ5W @èthL•j©Óï®@cÊf/w…ÆÔK€¼­B©Uj‚ó€ @€ @ Å  1µxqz€ ÔL©*4¦šo$6„ИZç@cjºàL Ð+hL½ÂÇ›!@€ l ̺eÏKc²Ý%{k[?š³óã5ír¶œgN  1å´â¹l@€@@cªT©hLxËsIh4¦F‘­¿hLõ3ãhIhL-Y-œ @€òJ€Îâ¼Ö¼®{T×^sß89Ǹôv €ÆÔµÄ9B€ P 4¦J”h™Ör±Mû8u¯=ch}gVhL™¡ìõŽÐ˜z@ 5 1µF=p€ @€@H€ÎâßhL9®üö¹t4¦ö©+΀ ÊИ*ñ¡eÊç§³  1eZ¿hL™âìÕÎИz…7C u 1µN]p&€ @€Sžï4¦<×~Û\;SÛT' @€@hL•¡1ñêlhL™Ö/S¦8{µ34¦^áãÍhhL­Sœ  @€ €Æ”ç{)ϵß6׎ÆÔ6UʼnB€ P…S%@hL|€:›S¦õ‹Æ”)Î^í ©Wøx3Z‡SëÔg@€  1åù@cÊsí·Íµ£1µMUq¢€ T!€ÆT  Î&€Æ”iý¢1eгW;Ccê>Þ Ö!°û?¶=³îÀu;F·Î)q&€ @€@~ ÐYœßºßƒÆ”ãÊoŸKGcjŸºâL!@¨L©Z¦|~:›S¦õ‹Æ”)Î^í ©Wøx3 @€ @)è,ÎñmÆ”ãÊoŸKGcjŸºâL!@¨L©Z¦|~:›S¦õ‹Æ”)Î^í ©Wøx3ú„ÀØåcUúäЀ @€@Mè,® Sgn„ÆÔ™õÚaW…ÆÔaÊå@€rL©RåÓ2ÍñG#—ŽÆ”i5£1eгW;Ccê>Þ >!Ðïþ~]Ý]}rh @€ @ &tׄ©37BcêÌzí°«Bcê° år @9&€ÆT©òi™æø£‘‹KGcÊ´šÑ˜2ÅÙ«¡1õ o†@ó ˜8`¯+öêÿX™LZ–Ò¤ßÃæ±h„ÌÞ·í­ß פ—´™~7ÿ$9" @€ wtçø@cÊqå·Ï¥£1µO]q¦€ T&€ÆT‰-S>?M)ÓúEcÊg¯v†ÆÔ+|¼Í'°nÇ:3“¤.ia×wiÙÅgêÞÕ­eûmçæNÍ?[Ž@€ ä”Å9­øà²Ñ˜r\ùíséhLíSWœ) @•  1UâCË”ÏOg@cÊ´~ј2ÅÙ«¡1õ o†@ó (êÒÀu\‰Js6ͱ°LúQ&gÒŠÃ$IEËúÝüó䈀 @€@® ÐYœ³êßúÑW¤1MYûsÇî¥9ƒÁå¶*Eí™=<*gÿõžÓÿÇâŸZÏ @hOhL•ê–i{ÞÕœu­Иj%Uv;©KúµòÒ[ç©CcúëGº5o}0µ×G`=!€ÆÔj¼}H@–’\%€S—\|&­Ô«òœd8ieSÑ‚El†@€@óÐYÜ<Ö-q¤é¯¥Î¾Ô²âíá-qŠœî|/~ P'£Ž:ª'Ÿ­¦¿çÃß½ýÕü›unÓÌ!@€ $ÐYœã›bèUNž21Ǹô6 0uÂמrœ(§@€ª@cªDˆ–iµû‡×Û›@s5¦9sæÔ9ÌÞ~›ÿ—ÿ»ýιÞ3>ÿüó[ÿ¶Ï—ÆtòÉ'¿}ÔÖ¿—í¿ß”Ý7ß>ê˜ãNÒÂf•w‹å­wwå•ß½éÊÛ¿{Ã+›Þþݦm»\Ù¸mׯî l(–^ßZ,ë·~´~KT^ÛòaP6e+o}¸6*¬}ëƒ5oËê7?ÊAyõQÙ´s•WVnܹrãûVV¨lˆÊò ïåu•÷–yeéú÷¬, ÊŽ%¯e±+ëvtËöWÖË¢µÛ­‰ÊÂ5Û®ywáê ¼ìÊ«ï.ˆÊ; ^}ç%•UQyqÕ;AYùÎ +ßvåùo»2ÅÛó—«lS™geYPæzeÎÒnWž[ÚýÜ’¨Ì^Ò={ÉÖÙ‹ƒ2«PfvmueF×–Ÿœr¡ÊŒW¶L·²((Ó‚²9( 7™°à³Ÿýlë’?þøcéV× ¿çËû°téÒÖ?a΀ @èptwx—½¼¡C‡þâôó¿ý½C¦NšW\w«ÐÍ©[ô积۵ÕÏ•óƒ @Õ 1U"DË´ÚýÃëíM ¹ÓèÑ£9þ'%¢EÁ²_¡²`ÉêO}úͲ(øérŦ·Ëk¾PQÁ¦Hó(’…Ó'VnJq' âDÑš(Q&|_bÝŽÅi²„3%G"Ô$œ#á gG85·#J½ˆ)Â%:DèB„"DwR„øþáÇ\<ôfYò|Âù×wà¶þmŸ;I¢’}Šbż¥›ouôq'•|´’ö’4¦RI2SªÀä9Lmð>o’™êv˜<©f‡)ú(¦8LÆ”î0ESø™,jL¥Ë.Ïa’ÏTª1Å?Ÿú Vq˜z©1Ur˜"É9LZð4¦-£1™ÃtçýãT}óº6|高L­ÿÝËB€ @ Ó ÐYÜé5œz}’BN?÷R5N_^Õ}àw1™ry´üEËaú÷ïºðÕnݨ§žs &SË×'@€@hLhL|HòK ùSÆ/~t˜‹©zt˜Bh˜ .LIh˜§ÂE„ÑB<"LmÓ«i!`œ;á‚¿”üRêKb¾”| £½¤†z© 1¥‡wIÄvIjL.¤‹‹çR!Â`.‘Æ:LhLmóÍ hL•ü0KnÙ|À›BÉ¢.•^ Õ¥êöRácV£Àä䲎Ãä9L…PLÑG±W“b2UÅ9L ÅFcêq(¦Y^(¦™¡„X9ÓÔvˆÆdÓÈÑãõ Xh¯í˜û &SÛ|)q¢€ @èXhL[µe/L:Èç^ªySÖ8]°b+&Sþî‚V¿bs˜­Þf½( C~êÙ˜L­^kœ @•  1¡1ñÉ/¦kL."L̲ýŠÝ/u½*©–ÜV iW<(Œ‡)LiU´)Ê9LQ2«”LV.Uà0Å܉rÙ«²ŤtUÉDUÉU)ù©ü¨.‰´T±œTÒ˜*S©ÃTÌFµp3јZñëBÓM·ÞeŠ’+ÅÒ;¿ûí­w鳬I“–‚¨K¥—„ÉÿŒU°—‚L…[d/²ÈU˜ÊaZí%’ó-BEE«’K®SZ:¹ª¡˜V–f”óÒÉéCf” "§•Í(W9Si:¹d(&§1•Ë(×ú“s˜ä¨9I*ès‹^'&S+~qN€ @È4¦üÔux¥ÃtÞ¥~ãTáÖ_Z±å[ÄdÊÙÐÊ—8Lß?ô•ÕÛœl'IöN9ûbb2µrÅqn€  1õü eÚsv¼³ô…Æ”FrEX^ 5&9~‰gµ* ¿´kCw"«UõDr®}ë•5oF%™K®r¦R&¬Tt˜üÔUÉPL^:¹H“péäütUÉŒr…b 2ÊÅB1Y4¦¤Æä2ÊI~@cjŶ4&‰JÉ JW|ìIîOÿCå–ËxKág,ñ1‹ÙK1iÝæ‹%ÒãŸ:}üü,rEI&“-E`J ˜.©QÑjÈ%×8L~ÞG}bo˜Ã´dkÉG·$ÜV—RјN:åÂ@cZ÷ž¶p³>Ʀ1ýã?~ö÷øÄ/þË_Záþv“}Õºy„úU²¿Ù‹^ÿâWX¼dI+œ*ç@€ äŽÅyªrs˜4£1Ù8}aÙ–o}çà)S¦ä‰×ÚŠä0}GÓšm1ÙN“zŸyÖÅ¿:´Ï›s‚ @Õ©!Z¦Õî^ooMט|•"¦+éÏ^ 4¦˜bQcP˜ra"›¢²JñÆ~‰®”ÄaÚð~Q`ÊÚaòÓUÕ’Nî/¼‹‹íâB1“S• ÅTÏE“§1¥„q åiLßüæ·bòC ~ öjÁsjÜ)Icºñ–»Rå$[©W|쉶}¢¼™ºn*6† ô€S%h´L{pKñ–6"ÐS¤R¤óIcúL¥ 0[?’Já—*öRÒ¦ð#0EYä>pEY©|"9_œpÖ„ó%gº–8L5:L¾‘y:¹PcÚòýâhLÉ0.ÃEÓ~û#&?|´ûO­v×çNcºaø]f#¥½*iC·%¿„a–Ò"-Ùgl}i¸bÈ¥Ô´q‰›ñÌBŸÕ~©ÆL=˜ü¤&¥©ÛÑ•R©¶DrÒ˜V%J÷¨…•ï¸hi)A˜z™K®¶8Lr˜ôéuS1“ç0•Ó˜Þûð}ûIö¦þl×@D³nâµAÕH,›ùòk_üÊ×k7™ÔµäzÙ’]c}xÕÖI×ÕÕ¥ŽÑÚOcï½÷¶ÎDëŠUï³Öø]õïŠ-!@€ úÐY\¯vݺà0¥4N-È5Nç-©ÃdR»O­¿ºˆhû¤õ¢ µ íG~Ì^{íUUޱ£KŠ2áIŽ;VV}c²ÅZ¡ùé6¶…Øõê´ý5=Rž;´.ÐÜ/;œ»ä ïõ; l3khë·ö pýÙãID¶7íD y :uÝå66‡iñÚ·Óf‚E²:5oÀ™ë2™Ü «2»s´ÒéhIt=»4Û­W–ë*ÑAS?J½9™r•[áXôÉô¬®y @ vhL•XÑ2­ýNbËv$ÐS9ÑB~ż…ÆŠ‘\±!é-•š¯I¨Hu*ª‡_ª-S\`*É^U)ì‹'0u¥É -ÚËê ÓÕ q˜êw˜¶Í)„bzni·‚¹¤Çs)Äa’Ã$ÿÁ4&ŠÉO'‡ÆÔºqEcºaøÈècóÿgï?Àæ¨Î}O”û²oéZYïè#­ ÕlF‡eí#­£‘5-˜;¥/½cCcú–Æììë¶ ggµÛ²ÞÑÊV7½ì8¶­ùÏݪJö­ôž¡¨ @€òD€Áâk;îú7tµî>Rs¢—íÑzgÛ¬k²Gè¬íVÛoHÖ1t¦‹93É);¡1ÇÙª§-›‘c‘ Miš”­µãÉs˜ª†Ež“l§'ÁÔK•5üM›L6Èàú•tCFÌ1 õ=ëZþÈItT$´YpÃÈÌèa"ª~­×™~dG‡{Ìí"½£— ¿øš5Ðz……ÒíË?6Ý–“i­ó-@€@3Иâ(qeÚLbìè¾ÆTÊS/ùËŒ¹+>½û5äŠoË©°²Æ/UZEÅ©¨L×3UÙ^z«¡½T–(B…g/µ&0ù¾D©‰$L=Uy“›HN ³–†s»ô$v©$a ŒˆR¦Æy˜*"„²1S‡‰IåRz¬Kcºê†!U6’9I•¢O¿ÿ£ãÝQTûpr‡V鸪i,Õ”–¢ÞÒ*eZreC¬KÍ&^ZW%FÂ{)&ýR“Sã Li¶§Gi­µI˜¦…¦ŠÀä;L:€KÓ9õ¦´ec ;Lëß\ê¿8¡n˜Øžvµ8Až0{Í>_j<»œdÙ«{‚ÓdІÆü1e23iÉÏÚ:nœW ö0ŸjpF‘¶5ó¨lU öXgtR9½zÖªá×Í—–l¼LÛLéé‰jA€ @ g,ÎY@«›ã9L±vH%“=c£‹Óióe24fÜøõ5&[ÙÆôr©›ÌÜÒWtµîl*·em'd5µp<9‡)š0¬V*¦ò“`6Šrâ)ç53»œ£}hÊ0*M‘=sU¯ï¹ŽêSŠŽŠ¸æÛf]–/n­=L¬·û}Ì2jGÇyü¾ˆöbÚ“ ®Z¤w\ª3{ß*:6mˌɴÐù  @ yhLq¬¸2m¾'±f t]cRF˜°ká)JÓç.ÿôgö¨¡+™_QKZj4‡U]u©†G¶—ÂEür530U LåYäü‰äšMÂäMQV#^Øê{n"¹°ÃTÏejõ\r.“K 1ýy˜ÈÆ”ÞC\Ó•7 ©Rüª?}*É¡ˆ¢¤¼J=©•zr,Uû€föK^r³*i©4U\t¶¸ÊñÖDÖ¥@]j`/‰—T^ªNƒVJš²—bÒ/Yx“ ëLîX ¹Ø L}˜|ë°·I˜œ(‡IÅå^Š.¤'SM‡I¹ïì„»¨ä0UçB/ ÀU4&ÍÓ÷Ô³M&SˆÜ“‡Æsý!6÷© L¦Ùx«]º¼è˜rhŒÕFÜløXiÁ^VŸ¨ÆdµÒûN·²¯ûcµî¡[Û‚[3½')j@€ Ü`°87¡Œ4$ä0)¢_OÔU•ŠÉ{ÆF§Sç½²ÿ7ãL¦¨Æ¤«?½ij‹)5¦%Ù5 åî5½F—“ör¤öì.WJ"çÆŸͬ gç„Ìëã®UmÁ%-6HþE¨þ´Ô5vaëŒ+[3ª1…jî;OV_F±Jú“aÑËVö­[ÍÇêjšÓ˜üKr“ºÜÆm§f,Ùµ(”ZêOÿð9[mý}Y(-¸n-F5¦¦ŸÓC±DnÆd iL>‡×ROYÛ£}ÏuTë.X®§ it³îq2—TL_&¡Îì`ún5#bSÚätî»–êLï;wÍ:mèØt‡c2-wf¾@hH)W¦ ;+dš@÷5&©¡ŒJž¢ôÌsÆTr*\)çX*Ï^Uˬf‹ëq*f°8§ p˜ÎºÐ†m²û*‡ÉÏ\ŠI‰™õÄ¡]œNž·!ÆdŠjLN¡°ÉÇ¥S¸9Úlž¸è“3Âo—„ºÔu¢]®Úå­ïåØýëÐølLþ%§¾e¹vLïˆÊ7¶åš!ª1ù«¹kj½i»Õ+I»]¶GëYScò[¡ªþþ;ÑlL¡©ßŽÉç잃2z¡—ðÍ:L/OPªR1I¶S/ÕHÔÏÝ 'SHcòƒèwcQ2[.Ú÷\Gu#'5GEÜ–Ýfµ ~âwŒÐabHM5sZ˜z…ŽvTc EÄ=rf™ÙwµM×Ál ¶¯è±i5ïc@sz6¥Y€ ¶@cŠCÉ•iÛ:J%®kL¦RÔ+Óæ,“Æu*šÍSÓ[*?H¢° D”Æ"¬wÌ­TÏ™<.’ù¥JœØéç|ñ•‰ø)ä|S¢¦#Q%0óSmUÑÀHPšL´xs|.›œ 1yÁ¦ ÌÊwËÙ˜j;LL*—ÊÃøã¥1]qݘ#gÐuÆT6þª¼¿@NòJµXí*Õ̱dž`é«%-y[Ô[Š?êÌô³.Å«K&»´Ç^ò¦ò‘?.$zóÇÕ;Jm¨È•g¼Iëf`ê½À4i^pôÊaJ¿ÆdÓíÎaòÎÅe‡©Æ0qí8Á;óÅÏ}q¿y Õ ec qöéÙ.Œ›¥óiÈ°Þ Îa*p—FQÊUg³¶'Á‡©*aXY¶³þ?;ùܘÙåšÔ˜ÌE3tѾW’?*âë¢ædü¾:LÜâÇÔ¥%³m†4&×O\D쳚ûŽš?tc—­:6m/ŒÉ´ÜŸù" @ hLq”¸2m¦±Nv $¡1…\ ߬˜ZÒ˜ªµŠ:)`jK5…Š·Ô;uimyÒª}¢¾½T#ýRiº*=úâJüru30U‰š“ŸØE¡VžJ 0ùSÝ$L%‡ÉÒ¸|÷°÷Ûb¦¢ÊI6&]»ºÿ˜°L'õž$Kÿ.iÐu·­tÖQdAŸõÃãj¬PšÎ•Pî²Z©Ìº’sŸ_±ñÌó.±rñï¯1=pÀï¯ùÖ÷Ó¿þfö!G[}¬Ö8\§µ*0ÙÑÛWéí­«tòå&7úvêM³Žºd¢Jÿ¡Ï]ýð›NÎN¬BÏ<Û À]ûØ Çþqê™·Ì~|Æz“³ޢͣ§¯®g2idÍ=u§fiÙž¥soú'Øu­×:.I¾[-´‚Ê}äÛEþm˜Ì^ö|¡Ü ~­B5±•Mir[Àaêd?eÛ€ @ˆ`°8w¦òãëÞÔÅé5¼à’_õð’+Zbs˹aIJ1³_у‰zêéž /þêºý®›q˨åþÅ鄹ëkšL6Iœ{HwÝç®%íÿ:4tݽêŒ^Hús½i}m!tý½¼ÕWLœò¯7CW¬Íßm¹ÞåªöbÉ¢¶VÉšWë1—íÖ]YG›æ¿#»+Ǿ븊é#›ÝÌÞq«9&º„·¼>!a&k¦7ƒTë˜Ã´põ¶‡©4ãáO¯˜¦'ƒ„奲so›ã²Yß7iÍI×ÍP¼’ŠIO‚iàXãN?­o2ù½1TÃPÓ¡ uÝz”üQ‘š} æ Œmͯ˜í×ßiÍžãïÂH¨ÆŒÆhÑ}Ùf“i²³ @ 5hLqܸ2m­Wñ­¬èºÆT[¥¨HSf/•ÆTv-*rEŒYÑL ˜ž|K¥”K~þ©r'~ö«ßŒ™2ß2¿ÜxûCßÔ;ýN—>á ŠQSæýñÚ¡q¢äN”r¾L|vÅ ¿<}Ÿ/î{àw½î¶áÁEbPv¥¶½ÌUåOTÕL¦‡ÆÍ9ôèã L•Ä.%©î,rSÖNÂ䦢’ÆtnF4&7á’Ž6]ÿÚ³4.ïoܤrZÉæ¹·ãTÔØD(_tVŽbÕSÓå×Þs¨èS{õV¨H5’*U%1«NeJhöÈØg>ÿ¥¯œqÞ%*ò–4’ò›ó.9úG'<<æý«eÔÁ¦Õ~sî%=É–Js‡íñÙ=÷ùâWÜQ§åG=­!˜Ò(Œ_v~ó»‡ú)—xbšÂê9ãj«K¦šºtÊY«Ô9®Qî¥Ú“Ç-ÝzçÓOúÍE»tÅO¿dóÇÝþФÝçËÙ°,0ið¨§xóÇùG¬æ«7…œe`òKë“ì¥ÇÎþøôO|ÜôPZ GŠ9LCïQNÔ_ÊÕ/I#¿£fmxbæúSnœõëf™Ã¤™ãN¾~æOâµbûu-=üâ N]{ë¨å‡ oTmNªæ¨gVí]?'S Uå+€ @€ª0Xœ¯!‡éÔ’ÃäF9tqzé°.Iðoï¯bsß>nå7ÎóÈÓkuq:aîkœ5æÖÑ+†OyI§w>¹Z×§îâô©9ë¾Z''S¾øÑš¾¸þÀ`žÊ9÷ÅoE“†°®Þꢔ<ðì1ÎaRGUÿ´éä4F¤åÛÆ¬|hÚÚÃL¸küê a˜÷$˜†P”¨ÿ„“âr2õ­m|€ ô•SA®LûÚ¿ø~º $¡1Ÿ“Ÿ 4&·Âòž¹ªª¦« ›•â"“VÕ˜*Îå¹üº¡²)ýŒÔ¥}¾èwkîÄ…—^-S ŠQ“çéÍÓΚ±j³+vÿÇ=ÏÿíUŒœ6ôþ1Ÿûâ¾×Ýö@ïì¥Û}æÅ÷<6eöòmVª¦[ZžBîÎG&ÿë翚B®*S›&S ²¢1)¡¯ËL¬Gt´,7I&’Ë\Wc’±d¹ ÝsZ.Ÿ³}?݇líÚÓ5ƒÝÔ‰Ñ}zäóß/§)só,VÏþæ¦] T=³0†­@‰Jf/¹4K:À¦>·Êt%YJúwô”ù:Ø”iéôsš*è¼%­ ÷Úïtó–tÔ õ´&Í^¡ÃOEY—4hxÁo¯²Ïe]Ò(I áÐûG˜8÷üK®:õì‹5^símœröÅúWË· ýØø¹¦.=9c™\Â_Ÿu±Š†Ÿœ¾Ì–}ê9e]š6oý­÷Žú핃O>sÀ#OÍQÑÂ9_iç-÷Œ:éÌ'1Àæw¼ùž'7çìWH]zpì ýäç§~ý[ßt÷:Do¼kä¯~s‘Šy6ò–μhP¿Ó/pù­ÿ²Ï—£ÙÒBé—B“?õ£Kž¦üiQ©ålLë׬}oøÀ¤•ŽiL=Sy¹àñA?1kCÐ%Ö¼>bæú#N°(K`R*&ý«x)FzŽpäÌõÁÌ}/lÕHñý“×X*¦À`‚Ì‘O¯Üû ug—ËâN!@€ `°8EÁèkUÌaêú¨\œ^z߯и„iLº8½âÁÅÇ_>U§?½V&*Oðe÷/Òƒ7zôðÂ;æªø§z iÜìuû}ã߯Œß×ZòýÆdƒ0õe&s˜¬ÚZî¨^vsõÒ@c*åa:~Ð4=&uÉá»þñ¥|`‘ 7_t×óÝ9·ì0y²]ð°ÜüM'üꜘÙårÌž¦A€ ~hLq1âÊ4ý=˜ö…@×5¦JÒ-&ÏzáSŸÙ#ìWx–R(ÿKO¦¥—kKþ¤UfSÔœ´Ê쥣~x‚˺¤wFM~^E‚„f¬’Daù_œ;qÄŽ—,a‰—T† }ü/NÓuâï¯rÍàÎ+MW%wÂÉÁý÷ÛwÕmÁ;g^,;bê¼u|ûcOoÒ’\ê³ûGLýÜöÕ±'iI ò–4[œVÖA¨CQ ò–d/飫?péU·évdŽ›¾L^}ËR—öþ¾:,å~æ÷Ôqxå-÷f=u|Þý蔽?¿ï%W ¾òæa{þËw=2yàÁ1©aJÙKZtÓ°³\¡•u”¼üÖŸüìÔ sÖêM}tûÓ$-Yî%M$wðQÇ}h¢&•¾¦_ª/0µ 1I`zëžÓ>:­"0uRc2‡iÈ}#‚ÞèIoêBGœxóË¥(Éaúõ 3/) ›úÈÓ/k¤XçP€³aâ±s^9àLuµ £•I`6§“ÚÈi˜LIØ/ @€òN€Áâ¼DXÓ)g^Xº8-?]c£º8=aдߕì%Ù!—Ü3_#€z–Fƒ}¦1•/N—§ Ð36·?¹Ê¥b²Ñ7]œŽ}öeL¦¼ô—δÃiLud¦Àaúî¡óWmµÁ:7Ò­a7g;ð¬1öè­†JÔK¥1•ÒÃÐzÌ:êáÆßõÔêK¶Ú•ž³TLÖK5ޤ”Þ˜L 0[… @ OИâðqeÚ§ÎÅ—SO ûÓŽ«éZ˜_1qf 1Õv-š0+|§"$-9›Â©–pWeÒì•2(Jù_ö>jšMg…yK§ž=PÅ&­*Ï·z‡ä‡a#¦Ú,Uþ\UzÿðwÞ%W^}ë'î}|ŠÔ% ºx<÷â+ûþqÒ$”êE¦„®"åHÈ^ÒÂ1'ž¦™ã$HóóSm 9ý«¢)ªäBSéJÓ³—*Óf]~Z.+º­”ž)äüÙ¨ÜrÑL.™Ð˜ÌDr“˜5ÎÆdkG5&ÉPMŤæHcºìêÁõd#½¯OøÁ±1+ÄøI5«Š šX¹èÒ«GO™§…‡F=-iI˜ýkGšcV,»Ri¹îRv•ÝÒR?ÑHñyCæhŒøÜÛæhÜMÿZ 5§1bM$¤­“ÃhL[ÅDÃÄW=¼Ä&Ñ À‰&SêÿB!@€ M g3n¡Z—¦ ¢§Ö0É&=`süåÒ˜æÙÅ©ÆtqªYºtqZzÆ&ÈÜïš¿¼fº³C‚äʲɮÓË&Óýw†/±CWÜüYLܧœÉ†bªe&9Lßüî!óVnñ;ª˜ìÉ@ŸØŒ‡6—\IcÚnÙ¬Íaêwí •žéäBO‚•ziÙd:÷z) PP¯-ÉÅo;€rH )‡Ýš&5I ëS¼J1aÆiLÍd~‰šÁEÜÚ²Pš®Ê©.óKE¨Ø9kÉ+ò%.»fHH]2‰¢t (éâ ñR)ë’“–Lc*=ßb%P&T,Õ‹ŠÔ¥s^yïcST´¬l/Jõb×Jï"AB šŸê®G¦hÐCj~*Í'A²ºØ¿*ÃÇÌ6AÂÍL˜ü¬.5&6ª)[“ÊÕÔ˜”¢ÉMW7SMI_Ë®ÃdÓ®\Ï7Òûúôˆï³‚—©L’•ðáTû¸ªˆJ~v%›ÎS—vjÙš©˜Æäþ Rœ•4&SOøåé*š¦ñþ‘Se,Ùd*NWÒ›ÁqX9öî{<Иt*åR0OÜÊíò–ôŽ%@Ó±g“ŽCÁ1{ÉiJ¶dE&Ó]¥ÜK–MÉ( ².Ic*%^òËY rsÆéàÜÿ[Ë^’´¤iãtˆZÊ%Wθp4¦ò±ºpó×¾y°;VÛk/9™IÒ©„Ü&ÿÏacæ~ïŸ?ùá™ÿ{ñ2쬭Ë7î·Ûñ'žÒ#™z³ ꤬‘âÇg¬s£oz3û•`˜xÅö²ÆT&~`òKœ9F“—±¿’Š©2§ÆÞ6|Òûç½ßÿÛMþ ² @€ ÆИ3JûÓ§OÿÒ¾_«z²’@Zƒº8•Àd6J ‘Ã4ðžyæ0iœÁ4&ç0雲ÃÉì®Áõ˜ÍßÿÃg¶üâÿÓÍ pö• ¿öì¥ê˜·.ßÿSŸÞcÖ¢õ=Cvn¥ü `0ȦÁç0©—êOßaR¦‡)4\%“ë¨{a¿qGüÇlpkëhM†ooMû7õƒ I ©ŸF—t_cŠU)ÆKcúôu¥ºfEÙRr•4K.ù‹“–,É®+Ê·$wâ× ±©âL]²¹ªL¢0}BsU©„².I“PÎS—Ì[ÒtUÍÐ-k¯ô ¿h–ª[î%ABÉ)÷’ Kò"uIš„þô‰ácç|fÿâr/‚Dlú¥¸ùãJ“,ùÉ\bÄ}”‰lLvô†²1ICr“>í…ÆäÛO=1HcúýU·ú9ÇBËúTS½jB‘ÃÉŸ.rhy•¾ùÝCg-~EG×ÌůXj%QOLz^ 67œéJ:Òªó›•Sœé+nŽF]æ êÀ³É%-ÉRÒr0"óC$-9sÐIK.å’Þ  -/‡Ê´$iI™–,—B‰„¦1é°ÔÑXÊî³M"¡ŠR¢Ù„qvXê©J¹„¦+}ý[kª8;,å0iæ8½ÙO¹—Jçþß ŽÒ¡Æt¡’éÏ?ÞpŸyKr˜ž|ö%iLãf½${é¾R6¦ÙK½Ò˜>½û½ËÆÔŽ'#OüÙOÕ{ºœ7ôväÀ Ò˜lôMä5ô6úÙ ¦£iŒøðl˜øñéë5L|ÿä5áéäªàäií»ß×gÌ]±vÓ;˜L=³Qm@€ ¤‘S£Òë:)ӯϸ 'g{%´Æ7tqZžå|u0,(‡iàÝóìâTC Ò˜œºÖò0Y’`=ÔNÎ]ž[6¦{† ]ûÜôwWÌ(hžvŒ'ä]ÃlLz–oùæÈºåÑm ¡hðÄ¥²Ö µþôæ’›põ£/X&—Í:”0Ìec:ã7g©—¾±¤:37±ƒrO`؉ÁmÂ×7ôú§”/@è<4¦8Æ\™v¾²‡$ $¡1ŸOM_,©öp½Ð*vúsUùÞ’=Ie9_FN|^fÅý·´ÃЉó/¹Êt%›¥ÊŠô K¹Tv'Vl—2qø÷+bh¸W~ãÛ‡H“Ðlq,±|›t¥+o¹ß&§’,1åùuÒ'®¼ù~?Ï‹2¼(ý’å^šøÜËv])5BÿJc?g­nÓ?0z¶æ§ ®4‡'óí¥à Ô›“Êe`j˜~)d5eTc’äIáüC©YIOàí¶Ûnú¾½|*É#³—û4¦+ouù¢ úôðïë'Lª¥"•'}ó>*KV<0tPÙŸJ¡¤#êÔsêß?\=DÇØu· Þ9;xGËîHsùÍüIå-¹?o6ZAQš¥glС¨#SE+<9c™9-wâiîØsÒ’æ‰Sѱ'oI“‡NZÒ1&“Iù–tdÊ[:録u4îýù/k*G›3îÁ±slÂ8Ë„VN‰V:&U,1š~ü³SuLêàTâ%•ÒÁhL²—†>8Qº’¼%›9î—§]ø£Ÿž¢ÙK]v‹~qÚ…_;ð @cZ$™¤JSÚùAñR Å‹‡õ>m&“4&)>*µe&]¢wæ¥îzé•·–g¬¸¥:5k¤ø•‹Ëå¤ëgX”LJ¦“ sÙ”Î}ØEã-•‡¦½¬sŸHºŒýbâ;LÖFL¦Î“­B€ @ x,ÎKÌe2ü› ܳ6¸a§ÊÀäÔ9Lß=Ï.NUtq:|ÊKzöéÂ;æ§Ê§¿»g³CÜE}Ùazp”]™ª¼û> ƒóÒÚÒŽë¬J£ÓËœûü k^9e%nÙfEq½ÔžS‘·Tžñ°4„¢?m.€‹î|^y¬Õ?­\zß [éY;PãQóƒ(ÿY¸3Îàzéo¿ß–Ʊ@ Æ]ŠÆ”HQK’S\ع2-äAQ Fw]còUЍkñä3ÆëW4«U¸Ì/&-Y±LKVt (BŽ„•Ç'Ì}jær-ÈX:üÇ[Úó–,É‹¥\rîDpaøíCT”ÒEj„¬‰`θeÛl¶8•‡Ÿœ#ƒBÓÆóóÓdJèþû¡G§"_BY]´šR.ɈqÓ]O\|ù­&HrÔ±*$è}¾,GBv„œ»Òt¥æäqµ¤ˆ^YÔ˜ ¤ÌLÎD¦¦~ÔðÍò±ä9€þAåZ;GLœûû«‡è_—WiüÌåzGG—o,M_¸AÅY\Qr3;ÞL|tüs¤<õX*ã¦/³âìñ2›¯qê¼u*îðs ´t¦¤%Íà8Y%Pa–n4÷e91*R—nºû S—‚yÇαÇÔîxx’-È(4©pÄ”%7Ü9R3Ç™ºôÔì—žzö%;8å-Ùñ©å[Ò!úؤ%×Ý1rÈð N0¼÷‰Y·=0AÂÍ=O̲$i~ž´¶ØK½ÍÆä†¨LfzoøŸþ‰òZÇ4&\Öc}±T}fììW}æåGžVY;qÞköœ«¾©Œ˜±Þ’c)Ó°Ékî›´æÞ‰/Þ;áE&HVܯ¨Ã„É”­µ… @€@ª 0Xœêðô®r2™NúÍùÑ‹S]~–Õ•Û§—r0[‚çòÅéÒàâô±gÖéúT§÷éâtâ‹O=÷Zȉ:L˜L½ OÖvSD`r­7“iÎÒMn°Û†¶m¨M£(ÁHš{ ¬<ãá¶Çg¬`òK*Á(ʤ5æ¾Öã0Ug³Öƒp¾Ãd½“©½6B L‰®¤˜S\p¸2Mq×¥jm Ð}éècL®¨éNŒ{zñ?|z÷†ZEyx¡ŽVá»JΦ°g¨ü¢«T”ðÅŠ“–47œ” gPhaÚüõ*vK݉NŸP¦%MQe÷ÙUîztŠæ§²”K£Ÿ~A³TÓÆ•d ó%,ý’oJhr*™ʺtùÃôoi¢¤ ÷Òý£žUn_蜽ää‡ iL’ìzä›H“ôf© Oš6!)äwWÞZåÙáQ)úTST?Šy§t õxNôªèq:Ì|Q©²Üã*ù“2F=Á²·T:êBž~6€*Á q¥Iâì ´"yP%˜*®r(:iÉÜ ŽnA9áÝTŽ•c²'%ZÈ+¬NŒ¦'Ûªr£õ†‘)Û«.ù™™z•©êy;̓þØÙÌT_czw疫ʇŸüíÝ]*Mê´¿½â–r¿*­‡Ø<¾ÃT h;‹”¥ë¯5{oáC d‡SvbEM!P@hLqAçÊ´€‡D¡šÜu)P)œ\áåI2›bì´@cªgVÔÕ*VWpVB…û³Ú¦¨ö(*i–Bɖ̈ê ­‰@–¨øU²DéâÑ/54‰EÁÌq~â¥ffŽ«JéÒ·Ù¨2¤1Å©…Ó˜zŒJÂ1_<Ò§:öB’;lü…z‡PôýZŠR9ƒ™ŸWɬ”hqÙ•ëJ•|<µ¥¥ÀXª’–ÊG '-)Ù’ŸoiFõqhÇdï¼¥RîêÒŒºÔ¶9ãÎ4׺Æd–d&•Z/ N=zô^3/ë'™)ôùäþG÷jŒ50™ÝÒ3ôV{ôm›Ok9LáDèñ&S¡þ{Cc!@€ Ð) wŠlbÛ•Éô«ÓÏ÷’FW«!¥A yð/N[v˜B&“.¥UæÞÔ?Ô~]}í·bPØqw4 »d2¦êÓ•;ž÷æt«ã$…µ$7é[9‘REÉŸ|±GWªˆµS+ÕO°Tˆ‰äX²ÇË¢ÒR(ÓR]i©Wù–d6ò–Bgç&Œkè0i…¾jLõû›Æ§¢£«¶º†´z{üü丟^2èæ‡´2Q`Ïè[ø B—‡)ü¨k3“ãÞy÷o½­$ëC€ @è!À`q{Ãù ìwZÿPz`7ËyOz›I‚{—‡É9";Þz?þR:æê; M Œ7þ€o=øÈŸÄ¬Ð“ŽÌ²%¹²ÔÒ&ÕÐ’êÊIì«V”â,¥:GZYa±L<‘ìJÞ×3+\m]©Nš¥&3-…“-%:O\3°[§C“ŸÒh©¤l ˳ô¯>Õ“y*zSUrµÇFõ¯Šȳ,Mõ^2™.ºì&Ën“KÂäžs †‰½'q˜2y¢Ò€ @È4‹3¾&*/“éÄSÎë¹8õ2—/N#Ø´æ0¹ j=ä¦âÒ…³iö ùº ÖŸ2Hlºv»Ê¶ì8M4ˆUrH@&Óþß×?£cA¦Ü™·dR=̦÷-͘þµtM¼ ô@cJol¨ ð1S\'àÊ”C$ß’Иb\‹Ç'ΗÆÔدˆ8á©ßBBEå¹'B¥/©^J·×«JÝdKiõ–BþS&xiLJc#éÓƒŽøIƒã¤¦‡ä¿¹dKÍe5«˜yß"ó/ÚDŒ›ƒRšˆ±®¨T;µRYs©™`©JWòÂì¦Yj2'S‡4& ›Úv6&¥"IÿêÉQ³—ô²ø*–{É$µ¤÷Í]2™.øýžÀŒ»Ñ·I•ù5q˜šÉ:€ @€@û 0XÜ~¦iÜ¢L¦Ÿýú¼ª‹ÓZØôÅaò/¥m¶8{þGæ‡þ”¨ä_SG/ºíòœW‘ ÈdúÚ7š8w½ž =æ§²î‹ÃdМ¤ÐXÞqŠ’MçÔ9íO×o‹&Ú´@cJ{„¨ M).ü\™úà(@ã»®1Å«N4¦f]‹%µç}kRTªž–ªñÌTQc©lMÔœ!.&ÃKå.|“6B—WCcÊäa/I9lêéDz_ŸêØ‹Y!æ£ò´nõçwsZR%‰ŽiI®TùI ,¥’¨ÉiæTÁMõ\¥FºRNr,5:èÆÔÃC&Óù—Þ<äZkŒXp˜ºö@€ Ô À`qaº…L¦Ÿž|®qRCúâ0†" í,Àd:ð ñÏ­·<ÖÑÇÀúè0u¶ölH4¦4D:@u 1¡1qp—@SŒ/ñÈøyÒ˜šq-ÊfEdÒ7_¨ˆW)ì1•%’`©<£QkÓR¥[ZŠJhL™<HcR›Näÿ©O¥1ŬP'CRHHªäLòÒ&¹üIq)”Ü‘VûèòšÅ‰J1®R%»Rát¥zbS¦5&„2™ú_zC0ñŸ—¨ß‹Ã”É“•† @€@n 1å&”M4$0™N:×]œº Áº8Åaj‚«tƒ€L¦¯xÐSsÖ¹Ôãþ`QËsÉu£êìH4¦4D:@hL-ô®L[€ÆW2D )F¥xø©@cŠ®P-$5ÈóÒØ¦¨«RÔ5(‚ñ Wæ7ÖójM 1eèðí©ªiL¾QZÖ§ÿvøk®PWè«'úùïÇeN M¸X9ºjù€ö¸XØRªž®ö!7£ÆýaÄæóå{ͬkLêÜ2™ÎûÝ ¡àâ0eò E¥!@€ ' ç)šM´E&Ó '3i~ð\+8LMc•îL¦o4nöË¡Á.¦îÅ€=A »И²;j S\¹2-À!Pè&v]cª§R˜_ñГÏKcjì!õ.‘RUª—`’¢:E•«3+\IœÈ«Æ”É‚4&MÂeÓ±ùÅM…¨O¿wøkÍŒ’šù3’z¦TŒÕ’êúIu¥êtJ:Ø•Z:Ýä@c2“éÜßÞàζ8L™<=Qi@€ 䌃Å9 h͑ɤ«l¦&P±Jbd2í÷“`ç:*SbÁ`ÇÈ4¦lÅ‹ÚB `ИИ Öåi®G )F¥xpÜóÿ©Ý{éZôB¨¨'*yy^ÂsRåØXªib¡1eò!I3p•½Z^‘>ýÞa?vRQË áC¨Vš2KVæÊ¤`R0+%')TÈ¥Ô’¥ÔУ̇Æä›L8L™<7Qi@€ äSþbÚD‹œÉD¦&h±J2|“ ‡)™°Wd‘S£F!PhLhL…éì44B ë“2ÂÄÃÇÍýûؽyÅ¢®SQíQÔµ”Èó1(И2yšÆô“O¿ööõÊO~~ú—ö;ðÚ¡#z[®:"R¿fhãrõÐÇ) øÎ¡?R‰©ÀE—ßöéÝ÷X»é¿¼ñöû)<”“é§]´ï~_Ÿ1wE¨Â¡?ßy÷o)¬?U‚ @€rE)WáìEcd2ýøç§+áÍ=ŽŠ¿8Ýöæ{½Ø.«B }ÌdRG=ãÜñ½tÓο|øÑGíÛ3[‚2K)³¡£â(4¦¸(seZ„c ÈmìºÆ¨!×Â3+.¾|ÈÿñŸþsŒhQË©eQשHÐ"Èè® ýì´˜ÊÿúœK¥¤_Ø­PÇõСC¬~)H~ùçÙç¿ìù‡ÞäÏø§ÿç¿«Ä7ðØŸö˄Ƥcù¤ßœˆÃT¨s… @€@z 0XœÞØt¼fGœòÜò¦Žƒf} ð»;÷;âä=q˜ú€¯B `И pš l@cBcÊV¥¶í$Ð]iîܹ!×b¿¯àßgÿû~íSŸÞ=ÇjAú›&×eï}¾_Ï¿¿ ©‡a'¶?ZÁ§¨I Ù˜t€Œ\µÏÂWÆÆDuƒ @€Ú@€Áâ6@ÌÀ&výuW|-}“ ‡)-d}“ ‡©]€FC  hLM@b@ )hLhLIõ=ö›<4¦vH<½Uò·~ ]4&4&ôš@ 5&—ŠÉ%dr&S Ï;Éÿ¨S@€ @ ÓИ:M8Ûï?¥ÿð¥ÃVÄL&¦† X¡Cö¿wÿ-»¶ÄoÜL&¦…€ÍB ИòEÚÜ@cŠ -W¦¹íø4¬D ©R¨]cRH4šS6ï|wçŸÞ‹_‡OóD`Sÿo¤ê·ÑOÅä'dR%ÿò~ºªš*nT€ @è ‹;7›^óúÙ!c_«Ú,ܲÐþUr&—ŸI+XEeÌ~eû3µ§…! n¹×-{Y÷Ó¿êú×ïnyÙ–l^ØPx* 9 T@c¢G@)&€Æ®LSÜu©Z$­1éNt¼' ÑbëïæÉ%È\[¤»4¬ó‡}Ô†ÞØÖM]cj+L6d„R1ù ™’©{… @€ À`qÞûÀàùƒe‡ š5H •Ϥ¢äL~~&}ª”®Ii5ç<å íKõIõ=u×é¦ýèÑ*ÖMW’ä¤e-ôÛOÅÿ(]Í 6€@âИ€ê@cŠë\™rìä›@ÒS¾éÒº  1%Ÿ]C  ¢©˜B ™Ú°6@€ @ ·,î-±¬­ïüÙ!&‚襗öÆÞÔ¿–ŸIÖˆ ’¬µ’úfž€Ì$“íä3IT²ö˜c§—ô&}j†“½#ñÎÖç@ ŠH14¦¸àpešâ®KÕÚ@© ÙD  1¥1*Ô Í¨™Š‰„LÍdM@€ @ #,îÖmÔÙ!Z b5óíË̤w,Ž•5€ªƒ€D:›ôÐ9vÎÀÓ›ê“r˜¤7éS뢖<¬lh% ÐhL½¡Åº€@—  1ÅçÊ´ËÝ‘Ýu™S—³»n@cêiöøàÃ÷6¿3ÝÊÚ7‘½4}ÃÏÝ;o½·ºûd“€ @€š À`q2½Šùj‚ÓDBvˆ&éM’™¬™c_k‰šxA ›œZ眧jèM˦þiµrN^7+ɾ @cÊ@¨"ŠK).ö\™÷È(FËјŠç¶©€A§Éù$ðÎ_7HcÒÿVóÙí’/C¹$€Æ”˰Ò(ä…S\$¹2ÍK?§µ  1Ñ3rJ)§¥YÅ#€ÆT¼˜Ób@€ ¤˜ƒÅ)N[ª&9ÉæÞ2™É^˜ô¦™LöŽ26Yò¦¶`g#½% ®¨²ë¯»,y˜½\ŸtUÝØŸ±·{a}@ ÿИòcZ @cŠ W¦îÚT½ hLM@b•,@cÊbÔ¨3j@c¢[@€ @)"À`qŠ‚AU @è4¦¾ñãÛ€@G  1ÅáåÊ´£'N)ñPÎ@cê W¶ ®@cê:rv@€ Ô'À`1½€ Ü@cÊM(iòH).ª\™æ±ÏÓ¦hLô†œ@cÊi`iVñ 1/æ´€ @)&À`qŠƒCÕ @è4¦Þñbm@ «ИâpseÚÕÎÈκN©ëÈÙaw 1u‡3{@Ç  1u1;€ @€š'À`qó¬r·æ“k|aÛU¹k Êç6ž=mý1¹j:J©£xÙ8 Ð7hLqü¸2í[ïâÛi'€Æ”öQ¿  1µޝA mИÒê@€ B`°¸Àá¿cán3^9±ÀhzH¶{xùg3PQª¤„SJA5 ZИâúW¦5ù&€Æ”ïø¸uhL>MÏ4¦|Å“Ö@€ @ ã,ÎxûR}4¦¾Ðã»Ý!€ÆÔÎìù!€Æ”ŸXÒäS\P¹2Ía—§I4&ºCN  1å4°4«xИŠsZ @€ `°8ÅÁétÕИ:M˜í÷Sß²‹S±âMk!1hLqãÊ4cÝ™êö’S/±zV 1e%RÔ l~gºFŠWî )@€ @É`°8ù$V4¦Äг㦠 15Š!4&: bhLqÁáÊ4Å]—ªµS ²‰4@cJcT¨Z `Ó‹¯ß×Âwù  @€ 6`°¸Í@³´94¦,E«¨uEc*jäi7Z%€ÆÔ*9¾tSd®L»ÐÙE‚И„Ï®;I©“tÙ6ºHàýÞ’Éôîß¶vqŸì € @€@ ¸k 18ø™i:SfBEE!hL) Õ€j@cŠë\™rÔä›S¾ã[àÖ¡18ø4€ @€ Ð! wl6‹Æ”…(½ŽhLEï´½%€ÆÔ[b¬t‘Sl®L»ØÙUИ€Î.»A©”ÙÚK`ÿ{÷ß²kK{·ÉÖ @€ ´“ƒÅí¤™±m¡1e,`…¬.S!ÃN£!ÐhL}€ÇW!N@cŠ#Ì•i§ûÛO–S²üÙ{Ç 1u -†@g,ܲp¯[öZóúm^ÿÊgÒ¿ö§½Ü²´2ÂSgâÀV!@€ X ¸ƒ 18ø™i:SfBEE!hL) Õ€j@cŠë\™rÔä›S¾ã[àÖ¡18ø4=›úOé¯lLƒçž¾aúÑ­2hÖ —ŸIÞ’–Õ²~cû©øe³¹Ô€ @È&‹³·¶Ô©-ÙHG  1u/‡@  1å0¨4 ù!€ÆK®LóÓÓiI-hLô‹œ@cÊi`iV~ ÈLRQûä3IT²†*?“-HoÒ§f8Ù;×·õyA€ @è‹»Ç:u{BcJ]H¨P„è4¦Þñbm@ «ИâpseÚÕÎÈκN©ëÈÙaw 1u‡3{@Û(Ù’R.isZ°ùã\&-Ë^’Ã$½IŸZ®&- 1µ>‚ @€š$À`q“ ò¸S£š‡6-Ùz¥ì%+ÖüÝ=‹?áþœ¶þ˜<´6@í%0羯?°\.þìÇ¿Þí㫾ÒóÎÛ[Û»7¶@ ehLqè¸2m¹cñÅL@cÊD˜¨dï  1õž߀@¢\â%·àò3©^zsË®-²—ƾ8Öª©üL‰Ö—C€ @…$À`q!ÃnFc*pðSÝô×ß]¢ÎY³,Ûvcª«Nå DHT:ýëî`´ 9*‘±S@5  1Åu ®L9lòM)ßñ-pëИ |šžM•”~Iy˜”fÉZ IÌéM-Ø›šHÎ’6¹w²ÙVj @€ d–ƒÅ™ ]ß+ŽÆÔw†l¡C&¿|TTc¾ô“|ø^‡öÈf!lxììÚÓkK²Ý.jä‹S\<¹2ÍWo§5ahLô‰œ@cÊi`iV~ (»’Ê®¿îÒäq®•–Iy˜\î%™Lz‡TLùí´ € @é&À`qºãÓÑÚ¡1u/ï š ™HÅÔ¤|9'P3!©˜rušì@cŠ‹W¦ÙëÑÔ¸7ИzC‹u3D)CÁ¢ª€ @€ Œ`°8#êD5ј:A•m¶‹@(!©˜Ú–í@ ·¢ ™HÅ”Û`Ó0d•S\ä¸2Íj¿¦ÞÍ@cjŽkeŽSæBF…!@€ @©'À`qêCÔ¹ ¢1uŽ-[î;PB&R1õ)[€@Î „2‘Š)çñ¦yÈ$4¦¸°qešÉNM¥›&€ÆÔ4*VÌ4¦lÅ‹ÚB€ @€²@€Áâ,D©CuDcêX6Û..!©˜Ú…”í@ çü„L¤bÊy°i2I).l\™f²SSé¦  15гE)[ñ¢¶¨K`ó;Ó5Rüâë÷Á€ @€@ò,N>‰Õ)1ôì¸9.!©˜šÆZ(<—‰TL…ï €@:  1ÅÅ…+ÓtöZjÕ.hLí"ÉvRF)e¡:h•S«äø @€ Ð wjV6‰Æ”•H¹žJÈD*¦"wÚ^°„L¤bê58¾tƒSe®L»ÑÙGrИ’cÏž;J XÓ† .} 8ð¼ó΋_‡OsFଳΊoÑ7ÞØÑƒ°]—ÆtÅ8²1µ 'Û @€úF€Áâ¾ñËô·Ñ˜2¾‚T~óóžYvYAK3ÛH`ëÖ­mܛʷ·n½î¨,U˜ºBE"€Æm®L‹t,±­hLEŒz!Ú\,éÄO<èÃÏ»` +ç^0°§œ?ðß>üŸÿeïsÏ¿ØÊ9ÑÒÿâsú_|vrVÿgW£œyÞ€r9wÀ™^9ãÜ^¹èŒsÊå7ç\T³œ~öEÑrÚÙ–ËYžæ•SϺ0\μðÔ3/<¥§\pÊ™=å×g\P³œ|ÆAù_Î?ù7çŸ*§ŸÒéçÿªNéwÚù¥Ò?T~yZÿ œ.¿8µU9¥ÿ/N9OåÄZåç¿>¯fùÙ¯Ï ÊÉç†ÊOO>ו£ýÕÿ÷û?=é\•ÂåœN:ç„_ó÷ÿð™éÓ§§ÿ|0æÉ‡?»ç^ý/î—þªRC@€ @ ÿ,Ό붩ÀÁÏFÓß{ï½£Ž:ê_÷ù’žxÌF©e:èIH ¾-Y²$Õ¡]%@ô»Š›A½$€ÆŒ+Ó^v'VÏ4¦ŒŒê6K pÓ·Þ±ùõ¿egP6å]Wn¸õŽsÂÆïºòÚŽwƒ²]åÏ*¯zå•möˆ­»\Y¿uWP¶e]¹¼³nó;/{eí¦w\yiÓÛAÙ”5®¼öö‹åò§_ûÓêW{ʪWÿ´ê+o­teÃ[+¼²|ý[Ë׿ie™ÊºrYºîÍ ¼¬òÆ ^Y²ö +‹ƒòúâ—‚²È•5¯/ì);¼ØS濸sþêr™·zGPVåy¯Ì]¹£T¶«<§²¢\æ¬Ø”åA™½|›•g—õ”Y˶ÍZª²Ue¦+/lá•éK¶¸òÌ’-Ï,.—§oyzñæ§eš+ 7Oí)›†›û÷ÿ°û”›&»2Ó¤rÙ8iþƉó6îý…ýÒ¯1Mœ8ñ[ß=dÞŠ-rÑtQÝì €õ @€ tˆƒÅ›…Í¢1e!JÅ­£9L·ÝûøøK¾¸ï×0™ŠÛzÙr ¸é‰ÐY‹Öi߯a2õ^æW'ú™! €@Þ  1ÅE˜+Ó¼÷ÿ¢·©è= ·í/œÆ$Qɤ¥*ž®dË7ÜhL1êR 1…ì¥mî­À$™És˜z¦ZS 0µßa 4¦ÚSIc*;L=Óš×yÓÂÃTјæ­Þé4¦^8L%É9L5¦¶Îô5¦%[«4¦ŠÃ$™©¦Æä9L›§,ŒhLó7Mö¦Ió²¡1•¦Cç­Ü„ï¥×•: “)·çl@€ ¬`°8+‘ê@=ј:•M¶‡€9LCî¡Gû4ŠòäôÅ_ü2&S{Øæ{+%‹åBë63®S·ÁdÊwÄýÖýâÄš–B »ИИ²Û{©y_  1õ• ßO)ÂiL×ßrGÙR²4KåLKådK×ß|»4&?åRÔ[² L¾º¤åZé—”‡)’©J`zÇe`êE¦J&? ÓÊ^åajà0LU*¦Ã´¦q*¦ZSŠ)ÈÃTIÅTÎÃÔG‡é…j‡)œŠiK|*&%a gcªÖ˜”Š)ýÙ˜‡é{‡Î_µÕFR;åÍÒ”˜L)=éR-@€ „SA]«™hL~ª›nÓÐûF(I¹FQ”\iÈÇ=ƒÉ”ꨥ¡rd;õÌ •ÞÞßÔm¦/ÀdJCdºQ‡ úgýn f€@_ 1¡1õ¥ÿðÝl@cÊvü¨}]…Ó˜®»ùö°¥äæ‰Ûög}úßœš-.–"ÞRH]ªš<.b/U§_*ÙK•)䚘4£\+ÉUæ’+O$˜ìÚÛ›N®y˜4¯\ãéäÊsÉ5;ÜìvN'q˜ùÓÉ©˜œÆTžQ®V*¦”kLæ0-XµÕI‘Ƥèœt:&§~@€ @ 9hLɱO|ÏhL‰‡€ D 8‡iYi|Ìž+eß9öéÅ_ '¦³XªºMð áÎg濬nCN¦|w/úo–&1$6 ½*údäÊwèi2G )s– ·SÛP²¡t(¢Æµ”Ê –¶ýùÚ@c:>”i©ÇXRÖ¥-=eÝå[²d]R‘®äoæ¸`¹&í¥SÈU20­zå-? Ó / Óò o-_¯ò¦Ê2+ëÊ¥žÃT-0E’0•‡r‚ ³R‰$ajv.¹fó0ùӳ˶ÍRYª²Ue¦•ðtr[jN'WšK®)‡©Jc 9Lóƒ¸ÒÄp×ÜhL¾«dËž±T’–jå[ R.Uϧ.m|{Íko¿X.’ºk/ý©Sȵ 0­m”„©áDr«wÌ[µ£Ö\rÛËsÉ­Øþ\©´8—\Éašá•*):—ÜâÍ¡éä¦.ìIÅdy˜¬<0nîßÿÃîA6¦ù›&•ËÆIžÃdÙ˜1Þ—ÒÔ…?!T¦mõFRæ­"Òï´þ-˜LG}ô^{íÕ|uŨ¯hýzßÚÿýCWÝÑwÜh—>êß¿¿6hÛä@€ d’ƒÅ™ [{*ÆÔŽl¥MœÃ<û¤bê™QÎZëI0kš²è ÿ㫽2™Ü0ˆ†2ôš>}º«²½ãþTzõ½AÚ¦vêß¶íÈßÅØ±ckšÍTFmѰLTF‰o‚ ­¦ >¼æwUÿ~¥—Z}Ø«-˜ÅRî6ÞŒr=ÝfõŽ©óÖªÛôÖdR-pöRóU±zñНsÃ<n…@+Û¾ì¥xí¶ÛnÚ¯{§áÖšh›õw¤î¤wj91}#Z™nö–E߈ZŸ÷O Z%ÿHÑiȈªjì€O}EËÍæÑutÆpS V™f6ÕLLj_Çê]§Þ™Su³1äƾׄ-@ £ИâÇ•iF»5Õn’S“ X-k §1]sãíÕNR•¢¤Oð“ã¨T3Ç’Ë·•–ÖÚlqÞ„qUsÆ5R—Ê3ÇÕɽ´Ò˽¤–§•[È'Ì9€ @H‹S†d*Æ” wö!`Ó÷, ©õ¤bÒ™FÃüœ:%)H">bò‚æM&7H¢*¡{í÷ÐЊÙð3â¸1KªdÚ˜‰ ƒX~7¨â7KoZ{Sb‡­¬e{ß½¸¬*ZpY%U™Ð¸M4‹’ÖÑ·¢AhÇš©mÊSÑún;n5UÏÆ‘lDÈjr5¬-Ú‚Ó³ïËÅrvà0…R1i(µÜmzì· ýüäçzg2EžšñrÃhÁšè\'@äÍ1´¾g©˜ÜíSS^ô©“ÉÜ ‹ ¹eú3´}û®þ…”,÷‘{BÒ*o«…ý:‡z—*:4\£:Ú[b¢_<ætîco£oÌëÒ²?ò)Ô~ú%}d«Y«C[ÇßÎZÁ dúbÍsŽmÊÎö ¹ƒ–Íq¶êÙ¦¬Úþ€°>r'+;ÒݩƣܦBY‡7Î8Xý•̵ËÎ]Ö |¶/÷2›3ñ“€@âИâBÀ•iâ” t”SGñ²ñäOcºa¨?;Xhùê†~ÿÇÇW)J‘ìJJ°α¤4KU™–l¶¸Š´ôÚŸä*ùe•ò-YyÅÊ[=sÆÕR—*öÒ›ºr¶¢§Çô ˆ•žÜKAZìªÜK5ì¥hú%iL=öRp%Ö9I>ÍìåÛÊÅËÀÔ”ÀT„I ™žYÜSž^¼åéÈDrÓª¦ž‰ä4—œ9LšH®¢1•¦y%-EKª&•s“{LAžª?'à"ü‹Sš5™t­hãhî¡]Ú@’7é:Ù].Úµ·{ÐÇ.ueëòQÛ;ZͶàžãqíîj9$-ÙøHrçFö @€ ôƒÅ}ã—éo£1e:|¹©| ‡ÉϪRÒüœ:Jh-I£(#&-øü—šš]ÎÝ;ÞD·q»%oC%zYl#¬q»7ïŒKGäËCQWÃ6ë†n´`6ƒ¶£•m<ÇÒ˜y`÷øM°›šÚJ3’™aõ·aÛ»Û íÚÏcëë[p5Qóý=úGÇÕ\¡GQªÊ«Tž.<1\EWªi,Õ”–ÊSÅyù–Nš3®¬.Õ™6®ñÌqmµ—bÒ/ÕžB®Õ LO/Ú<­Rz%0˜æo6&“s˜–¯[ß(£Ô~ˆp‡ùdþHÊŒ’ö³X“É¿¶Ëf{¢Å`Òµ«]HÛÕ¦?dæ.­môÊ¥>Övì+~êi» ¶Çí9E7D‚ÔÓ_š@€ P$ )Ú¡¶¢18øÉ7ݦۇ Æß4„RÊÃq˜^/O'WÿI0 ¡<üÔ¼Ï}q¿uë××kUHcòWóµ †(]Æ@l ÅnÕkœÄ†D|WÃÌ$}×ÒóÔ›TÎFlÌEð-³o¹)·,㎭l;µ ÖÔ˜šЉãh_6ó”¹NVð¨˜ÆdµgÛ¬’N]Rµý æ’êCÅrÖ…®Û”2ñx“?¡X¹Û”ß*©˜d¿éBu›q3_üÜ—ö‹ÏÉ$\¾fÑqñÒ§¡PšÌd£gÎA1P½Õ˜|¼¾vfѱ­¹Îé"Õ˜b3ÔFBÉn³Ö™ýNXsPÑú†ë]nƒ55¦õ–f£_'WOôg5ˆ~HcòÃáL;„}—+Ç?~R9ÿðwYú'sÈÜËfy³ƒ44'¦ß[L³s'+7®ë¶ìöå¶ýÈl­ÐX±ÚåF•CzVè¬b[Žê€I@Ø/'€Æ®Lï T £И:Š—'G ×“Ë(›\[ßó‰'ž8èº!«^1÷¨FѧGÿð¸ÊGoÕ“ä'¹RÊ«T/»’.z=])7ñË“O/d”Š´ôôÜÕi©<Â2í¹UyfìÔùrV¢ÞRìK£&Ï[Ì5¦²SÅŸ6.”xIóÇ)ëÒˆ‰sg,Úàr/M_¸A¥ôt‘+•ÜK½O¿t×£Sf-Ý6yîË*Á“mV¼ôKÃÇα ~W†™ýÌ’-Ï,.—§o ʢ;½$),0-ìIÂ䦫d` ’0©X²¥LhLžÃô5dô³F=»Á¢¿¨4ŒbÁUg½°Õ쉙ë]*&QI¡ûÙÉçÖœ]Ξtñ0Kamï¸kE´¬—=J¨ut]m_´uì)1½lÂ>µËW½ì"Üå[²+swjû"Së§9¾ @€ ”`°8%H¢hLIPgŸç0é1°Àa*=&‡IC@å„:¥Q”© 7)¹ÆÁlÈkÔ¬ 5ŸÓÔƒO>c2¹¡’hFÐȆ³vܘ‰qßµD#j…콩ђaà˜¸7&cÙtLnpã3ö|šîôÛG6Èãç³±zº4ìFþ0Ž ÙWlâ³he¬ ²lÉróزÛWçòë4lŽ[!d±Œž½Áw˜FÎ\?{ùvJµ¤õê6ÊLoÝæ©ç^µ ^6ª©Á·±3V«ÛĘL_÷ Å+J5nf¡ùí²ïúý-:¸gý*Ê9wÛ‹m\Ñ´=šSRsûÖ ýràüÍêS»›`[ˆ*º¾áïÔÜWƒè-¡èë¤1iÞ¦ž,\Î`{qçäýèŸûj)Û¶æ£ïHF?]Óü@Ô‹ˆñÑËé_¡cÙmÍEÊu wB¨ S4¡ÍEÖV EÁ‚ng½œÓÚ—ë«¡j¸tSwýéêot{·úX9×d·Yǧùƒ5!WhLq‘åÊ4¯ýžv4&zBf „¼£ÐŸ 4&ýGÐ)ív™}æ#CdJÓmÎ=Š. ºö¶£~x\½Jf&…Je28 Ž„]% —œÙÿ’=>ûÿ³ræy—hôäŠëoÿü—¾b%IY÷æ·¾w˜ýyôN0WÉ•£~t‚[ù[ß;´’o©Îlq/½®”K~֥ᣦ}ó»‡ÖP—ê'^úÜö=åì‹5ˆc唳.V)9Lá™ãâ&+Íï™4º¢ûÌ{êªþ¤3.R LºÎ¿óáÉÿúù/;IöÒíMú×}¾lSI` ì¥Ó‚)°—œÀÔiÎ}»´£‡€9L WouI˜Žºd¢•®˜vàÙcî|jµs˜.¹gÞÀ{æ#)+¶ß6zåg9|À„ÃŒ|úzKÅ$Œf}ýô¤Ú&SGÛÂÆ!@€ `°¸@Á7©ÀÁO²éæ0 ½od9åy%•µžÓ(J0)XIGx`ÊKGœ`2ŠF‡Ž¸xÂá¥rí£/„Ÿ[¤pÜÜøœLI¶™}ÇШJ/Y,§žu¡ßm4àæ,–SnœuäÀ‰nðíøË§>úÌË)ÕàÛÙ·Î.¼ƒoe‡©2ø6zz“©‰z•WÑh¾Pü,VÍo¡ˆkö&úÊÂåG_êŒá‹} nã¬1öø¨¢Ü§Zôû];£sÑ/bìh3 Ð4¦8l\™¶Ô©øRf 1e&TT´Š€M¿îÞ2Þ—ïëjL2ÜÍ»7ÉRȺ|¶)™°¼·Ñ–Ætùµ·ÕV‘‚DÓo]~ÍmGþð¸’T[Kò3*•Ó)YR¥êÉà¤+Ùó^Gÿø„›ïxÈt%{ükÏîùܲ×t%ü›ó.QtýPùIæ-ÉX3e¾®‘¬hY++ÝÎâÒëb=]¤k3+z̨\–—Ó&ë©#WjÚKR—zr/IcúÍE*ººsÅÔ¥;žd“K¿$é_öùrmiaU¦)^ú¥) 6E20Õ˜úª1ébXÿõéðoƒ&ur˜*]HýDÒzLÐz‚& ½Y¦“¯Ÿ©kéwϳ0iîîñ/êû–Q˹lŠKÅTÒ˜ÙëL¦ÞžAX€ @hžƒÅͳÊÝšhL¹ iTq˜F¸ÇÀ\6¢HC1‡é·÷Î×àI 1•ÄNº~ÆÅwÏÓ¼`zjî€3Ç”sêT? ¦!”ÆÍÝ;vv¹ *`õä¡îôc+3™Ãê6Ò˜Ìb‘Ãôëf™Å2nΫ’ÞÔyúe ¾Mxþ5=@8máfu›3oyö÷úÁ7=@¨±Ê'žY¥n?»\“aqO“{¦IbÁs§­F_g _|´èß>nÕƒèÛã£×=¾ôØ?N-¥bÚzØ€ñM_ß¹è7ÛdÖƒŠM).þ\™ûèÈë;|«:ÿialfa§1¹ŒÂª‹›^¹®Æ¤/ÛôÆÑ †õü‡¥ ÍÜKÓ¯Öœ‡´þM}zäŽ3 )¦ôhIÎO*[J¨dÅ™I7Ýñt¥»§w4=œ\%³”ݳ¬?g/}mŸ/}eÊs+u…leÊœ•Ò˜î>Ö¤¥g_xÕ’-ý´ßéû|ñ+*Gþð]G)åÒ‘?<~÷ÜSÿîóÅ}-÷ÒÐÆøÝC9íÀï*ÁåWùÜ÷=ð;‡¨h˜æþS¥+iYÿ1ÕŸ3Î4¦À[*©Kr˜iÅö½¿°ï7¾}ˆŠvôÈSsä-ðíCTôþÞŸßW×lZ¾åžQÁÅÛ²mzç¡qs.¹bðÞŸÿò׿u°’0 ¼b°’ëjAêÒ¯~s‘Šô‘ŠÔ%³—nxÒgöø/J¿¤²ÿ7–½4ô¡‰Æ´hóE¼E zSÿ6ž?NÓü L JI`*ÍW³´0©Üö§†þû{WÂV†Ø¡!p˜”LkÕÖ’÷¦›UPÒš*ÎFßî|jÕñƒ¦)Äcç¼rÈer˜‚Ñ·RFëÙ¥XèZZÃ(¿¼fºä0—ŠÉL/‘9þWçÔœ]®C-b³€ @€@0X\ `‡›ŠÆTàà'Ótç0U#ìEÑóE)eÓy]#f—Ü;ÿþÉ/IF±Ñ0{L£(N]«„:Êîæ³tà ¡lÒÒÞ_ØoÝúõÉ´½¶@ÀD+ud¦Àa:óÂÊäƒ=ÝFSÈaÒàÛíãV›´Fçá§×z³nS·Q>ž«^RJ'ßÓm489rÚJu›¶˜L-(ôWúý'<ñÑO?fö+Ò˜ÜIæ“ÓùAÓ˜Ùˆ~¡û‡@  1Å+ÓtQªÐA¼UÝÁj³ébÐ|ÁÊ©ägc2Ê©$=Éf—k0©\Hc²Mze¬4¦Ë®\WBZ÷¦>•Æä†<äŽ8-É™I¡yߢºtJZ‡ô³_ýæ7ç^"{éòë†J]’«d –õ´T$3–.¿v¨Ö”ŸJ³tÃеÎÿ¸§æ†»ìÚ¡ºpºìÚ!ò“ÌU’·tÁo¯zà‰iR‹f,~E—ÓÒ˜FN|^ Güàø¡÷¾äTÙKãg.× Ón&‰;ûâko{@®Òa£5XóäŒà£ž ãVn×Gæ-YÊ%Ó˜ôPšV»ç±)Ö9öÄÓN>sÀ­÷ŒÒ‚å^’´t÷£Sn¾gÔß:DÒÌè§_½¤ øC>nÔ´d/Ùlqò5¦ïù“Ÿj¹—ä-)ñ’Š4&˽tðQÇžyá !Óã“—|zÿò䬗4rtÑe·|í›Û#MºJt%’~©±ÀÔB6& Ló¦NjLæ0Í_¹Õu0ëWê-zS9aÐ4 LºxÖè›kÙè[YcZ ÀÙó@Êä§ {f]p-]€ ¸iÎ`2eôlFµ!@€ v §=B¬Sá²és˜†Ü;Âݹ¡9Ke=²¤1©¬KÙ¬{æe™(¾Ãô«ëfhðäêG_Í e“= ¦!L¦Œõ>_d©%3Éa:åÌ Ý£ƒ6‹œ ¾Ic:å†Yž5æÊ[·qƒo¦1¹GÌX/‹EEƒœ=.ìé6˜LÉt›>DßÎ&>†¢¯‘XÿñÑk}A§Ž3n~–è'eö xИâºW¦,ù&€Æ”ïøæºu!Iy”ôŽ2ÑZ£{§1Ùw4£\FØÓÕƒc<$}zÄŽ ­àkI —KŠRy8—WI £§Ì“¨ô`I]2W©¼\J°¤¢K#eWºàwWk¡<7\)c­ÊÄgW\vÍ)J§3PEF‘–U´ dKJ¹¤e›$îüß^uü/NS¾%}$¯E™–,ß’þ}~e ¹XѧzÇÊn»íöèSϹ ã”]ɼ%]ËXRÑÂgþqOe÷‘#cIïhA¹—N:s€Ô%ÉIw=2YÆŒd/óóSÏp…ì% ýœ5àŠŸüüT—oI–’.ê,“¬šîÙïô‹”cI–ÒЇ&)÷’ì%Sm®¿s¤Þ7iÈð‰ZA V>½û黽ä235™é¹›Ï©!0ÙÈùŸüøúÛ[9á¿ó»‡Ì[¹¥gÜ­4†b=GÒ#f®³ éG,«LÊL¨TLß5Ï9L…;ž\uÀ™£COƒÙ&S®Oþ4€ @‰`°8QüÉî)Yþ…Ú»9L·Ýû¸sP Å¢”Ü4Š¢Yä4ŠŒž­ÚñhIcr)Ul¼ëÉç^)=V53ÔÔÒCtîI°“ià~íbk! Ÿ!—É_(ef*9LÔë6˜~}ÃLu »=>}MA¨o+·.iÚZë6åY_ØúûûüäSüƒ<ñ•‘·²Étî¾if»‡%sRÉ>DD 1Mˆ:LŠ~ 1yÚЫ²à_zß?ÑÏI/*ÚÁ%ùW–  1ÅE+Ó,÷mêÞ˜ScF¬‘RÑlLª¨æ…“Œ¤…^hLn"9M3—Ñ„LÒ˜þpõàIŸñýc+*REHZûº’'ùNRÍåžDJÝDïS•,¥É³W*©Ò¨Éó¤1•D¥×‡zZ9–FM~þŽƘ®d–’-«üáš!§ž3ОùP1]éÔ³ÿËÓ•fÉʈ sm†8]K[Ñòï¯"™I—Ö÷=|dÿÊq±©â$-Icº÷ñ)®Xâ%S—œ·:n†©KV¼Q”`„M£(K±Q iEc)–ReðèÓn6E u&:3”ÿ$˜|”}ÿy¯%ç~éÃë¿É}ú´¨'²œþ‰;ûÄã¢qàò p¤ÛÈV ,–Õ;¯xpqÏ„+ƒTiLM[kƒoW?RÎà¥Éæ½h¼›…Ðeð²Á·±Ï¾¼ß7þíž_øþußI;´Üx}ˆ¾1ÜЫ3Ø}u {|TY¸îzjµ ½^pûÜ nŽèÓ·³Màì¿ &ßä•ehLhLYî¿Ô½oИúÆo'HÀiLšnúôéVÍ7§—z¡1iC˜ô9Pz%ؤ–w-é÷WÝZÓ7²7õéáß?6fs’übfI­²sÒìR—†šfÀðËÓµ IÓÀÙ;ʱ4ô1zGSÂÍXôŠþpõ“–TÆÏZ!ßHN’ÆYÆÏZ®yâN=ûâ¡ÃFËI²âôNÿK®²dK.ÓÒá?8^ßzlüsòZ$*é#Ù-úWËZ8ìûÇ;ðÊo|ûß]y›¤¥{›¤Y*KV”cIÆ’þÕõØ•·Ü¯å‡žœ£y¾µ ‹s%^:錋T$-iˆGӯ飛î~B—mO”–¿þ­ƒuýfÒÒ„9k5gÜvª¦Ó0ÍWÒ˜.TùñOOўͧôK–ué±IK”²[3Ç]vý·•&=÷¦?0AC§_pù×<(x¢¥\6j,É=ÛÔ¤ºä¯Ö¤Æôàˆñk7½ÓåIåüÎ!s—ovö’ÍÅôœ”„é±é/+ ú á‹ƒIÙKÃ( ¨&Å+H‹uÙ”«^¢@\ù𤈪=Dè?d“ÊÉaRëT0™Z>·ðE@€ @ L©À}©ÀÁO éf2=h¾¬Ù:>Dß4&7”¹ME§ýÎcÛ]ãWK|´Ai»^ñÐb¢ßz°øfHaDcJC úP4¦8x\™ö¡kñÕ @cÊ@¨bmNc’ä$J»J/-Xr¥“t%ÙO¶á±cÇj.9}3£“]^zå­õÅ£×õ©4¦êvº)Þz* “\æ¤z × ~àw•Ÿ$‡É䤑Ÿ×Lpîy«wJNúÜ÷UÑ‚ sEÃ+C†–Ëb³¿röÅ6àréUC¾Qzó”³.Öà‹Œ¥ÃpœeZÒ5ÕàûFþýãl’8%^’·¤kl9LR—TŽ=ñ4Ó•øö!š?Nÿ>üäK³äŠì¥½?¿¯„$å[ºòæavY.9IÿjXçÁ±s4UœŒ%½£rèÑÇ)åÒY 2u风½ñ®‘ºz·¬KÊ®¤¢ÄKúW“šÿ.Ú|Æ…ƒTd/٧ʺôËÓ.<ã‚A÷zV _ûæA•~qÚ…nî}bÖAG+{I“Þ”ÌôoGxKV*™™[°—z;©œiLV$3ýû{ôd¥vb‡Î='NTôŸ[¶Éõ.KÍ¥Ñ=fEÃ(£fm°a…õ²û]6l‘"%«L‰Ðe2vÑx%µ~xÚËÁµ´9LÕÓÉ9‡ “©Cqd³€ @((‹ ø ÙhL~2M/›Lc¦÷ØK•ìæz8pììW4–b“†Ë4ò«ëf¸IÁ¤1IGÐÊMO,ïq˜*ÓÉùó‚9‡É†PÔTL¦dâÝä^}‘¥Z`r¨Œ—í%—ÿøË§º‰äf,ÙrܧÊ~3õMG™xlðíæ'–ÿä²)²Xä0•’ñ„ 9L˜LM†® «õ!úcç¼â†^ƒÑ×ëfXò6EÿØ?Nµ¡rEÿÂ;æêÔ¡èWR1ý6ÄM$F)1ômÛ1SJ®LÛÖÑØP*  1¥2,TªRÜjÊÀ$ I/KŤW©™dh»4qôéaGSs…à:6T*i“\þ$A~R©ì¨*ž¥dõK0°*Û5Ôâ&†3KÉ•ò¬pöTPez8óZB%d,XYfsÉÙ´P× ²Ê£(¡2 åçar£C˜LiïŒ&²Ô˜\å5\ü»+oõ»˜Ì{«ÑmJƒo64|ó ¬é0a2u©Û´;úN|´¡W¢ß¥8²›®@cêêŽí)-W¦ëxl8:|«:m¤…$P8éwW”¯KkºGúTSi°Ã•j)¤%•´’P©+'9i©†¥<æŠK­Ô²®dˆÄJKµ¼¥’´Ôo)¬.U{K–e7F]ªØKåÄK}É·Ô)ÉÎ’™tU\ýzeæØÉýžyY‰k¾æ L¦oüì’ÞÐ[Àd²ZÏè[èBzqÈaêÉhíÏ%çÀa2ò‡€FC€ @ ,îÔ¬l)+‘ÊY=Íd>ú÷è ˜z+¢Øã|u¦p6ëzSÍœL‹ï¤A¡—Æ9ðý׿…ÓõQ΀§½9¯ô§‹©­L¦ß^qK¸ÛD¦Òƒ =Ý&þ‡iÉÂÃÏÿõøþ?ŠVID]%í`3Q¿´F¿¦ÇVï¼!Ò- &g">T2uИR’^W)W¦½îP|!SИ2.*Û<ÂiL¿tKŒf¤O=ú˜ÆR4‹Rm3©ü¼W E©2\HT*?âãò*y©•jfWª§+U§YŠË´Ôš´ ÕHýçO¯®!P]&ÐLôCâcL üøè»§Iýè×;oÈikm0¹ËÙ] 1e?ŠhLq1äÊ4û=œÄ@c¢ä”@á4¦ÊitÖ¶à}zèQÇÔ›ÐÍ·‘™“LK*=¦S³¿UÏWWTª“Z©œƒ§gV¸]©æÜp5Œ¥Êìc5fˆ«ž$®-Þ’•Kç'Œkè0i…¶kLzzæÑ£÷²ìôìÜ(•–í}{OÅ liý©4NõÎ3£Æ<)“iú¢×\"kKÂT~¬z¥êBº¤ŽMRFëy H3Ó–7þòáGá‘”œži @€ Ð w†k&¶ŠÆ”‰0åµ’o¼ùæ~_;àþ‘O—GáJy¬«+¥²ž±¤4—œ=¤WžK®‡IRÂ;ïþM0ÿöî.¹J² êqi™ì™·è`‘††lŒy%ñù“ã~:ðò›ktKÂäw›ª)]·)'A·X$0Ývìwd2mÚü†‹¾ËÀ¤þ#Ñ÷ÝXbâ”òZ¦¢_cÊÞEß9LÛÞ|ÏH†Îõ“Cï»3LÌ`r^#E»:E©Sd»·]4¦8Ö\™v¯'²§$ 1%A}v@á4&]ŽÆhFúTS¼ŠT#a’Ÿ<)b&INŠó“4’k)Å»J½Ð•‚š`Êöhy&b,5#-M‹ÌÍ·ÔÐ[êNÊ¥Ÿ©í“®*mdJCWÊú«[Ùs3.K“-è}-ØûZÖ;ZˆI-“éëß:ø™…¯–‡ÞJc(îI ˜Ñ·Ò }8L]8² @€ @À#À`q»SƒŸŠ¦›Ét߈iö XÍÇÀœÃ4mÑæ©¥1®ò09‡Éš­ IHrC=zǬ&ÓS4jdƒEúWE¶ŠÖ”ˆ bcD¼’% —åâËoîñÞ*“KÂT_}+?@Ø0Ï‚gçIcZ=¾‹¾úƒº‡º ÚP¡õ ½¯Õ¬{øcŒÉRÊëÞ»}Ó˜œÃ:oÔL7šLÎk¤hWG 1ukW7ŠÆ‡›+Ó®vFvÖuhL]GλC ˆ“yE5‹4¦CŽ<&ôQpíÚZ) ”4,ABªŒJUI•¢R)ïŽ+ÁÓcÑRzž¬÷ÆRðð™+Ä©*½•–”u©V¾¥Ä½¥ÒÔvÉ¥\²gì4ab“±Ò;ƒ°ge´Ž]ˆÚÑ®7-]S½—™LÓ¼Zî•Ð[¬M>³¨y£oäaêι”½@€ @Õ,.p@c*pðÓÒt3™î}|Ú¬¥åT:å$å–„ÉFQ*C(Áƒy½ŸK.ä0©å.å’ ÙCn–iɆ†ì‘6K¼¤5"äÒ5iMû¯d .ËoŽë6‹Ë#o¾úfž &õiLž|˜Ú¨4<–¦Ýì%³”Ô ôŽËée]ÅŸiÝ­£Ý£ýj}­üìhyè5ýf ¶šSô¼L7z5˜ÜQ\l¸ÆºR­‰áJ‰|4‚“Gi)ªIµ]c2WIn|ÊÄ&˺ä†ì<ÿÁ;-ëI¬†§™Lûó Éó6ØÐ[)âe­»Êè›Ë}uü¯Î9ãÜñ£o[ÞøË‡}Ôpï¬@€ @ ) 7…)Ÿ+¡1å3®l•™Lw?:­Îc`ÁDrír˜Ül6#˜hiÇ ™âr[öýkùx´¦û(ƒ˜sXåÀeùÃMUݦÎà› 66é0Ébq®’ú† jÌÐÍ%g“%a²¹äBFÆçqÏa$’hRç¢m‹o½Áäèy£…Áä$(²Ï¬@cÊZÄ¢õEcŠ‹!W¦Ùïá´ Žý#§ §1ÓD UÞѧҘzVˆ¸Gþ„n¶\{Z·zï/iEÉÍd·®c)…E¥F©•‚LK5²+Y²¥º’¥Ñî)¥¹áj¤YR¾¥tgZj&·S‡4&h0Kɼӈ•eZ’ÆdZÙ¨–†*´‚%mj~ÄÊL¦IÏo°ÄZ6‹œ{Ì‚Pp˜rzö¦Y€ @H7‹ÓŸŽÖ©£xÙx¯˜Étç#SŸ®Ì"g£(öüž†¿,§¸ "µœ‡IUr°iÈF~lPH¹LKúÓžj3=Åì_7»\¯ZÇÊ# —å‚ßßtO`ª9øÖ¼ÃdÁÜ5-Xg°ä:zÇz‹ëê?ö¤j™”] whËŠ~´þî¼3˜:o´6˜Ü5tì(«И²¹žz£1ÅÅ+Óì÷pZG‰þ‘SEÔ˜bÄ#iLñ“+”ô£øyÜœTo¡l&Õ—“*™utyìÊæÐp5ç€3Q©«É®TOWÊ«±TÓjj»ÆdÏKé¥ÙK¶àþµô¾ŠYè¥ý龨ä©F&Ó×:L©Ì:.ǶüØû×ràmøÈ# ™i¥\–óc¥ÛTåîrÏvöÊaŠvØ04¨èº•vÙ¯h'¢¥âŸ7&»¯·6˜œý˜Ð‚N@cê$Ýîl)Ž3W¦Ýé…ì%)hLI‘g¿&P8éÂ?ÜãéSiLá”H–©‘~dR´xNRœœT×O*åÚ‰µ”‚4<õò*9»¥8 –šIÂäÖi»ÆÔá¶jóf2=5g]ÙHó´’‡©›á`_€ @€@‹ Ü!И ü”6ÝL¦Ûž\ï1°¾äaJi›©V;.Ë¥7Ôë6½u˜ÚQ#¶Ñ=¥èßHô»Gœ=%H)AømÚ5SH®LÛÔÍØLJ  1¥40T«¯ §1U²ûz–õé¿ñ“ZâQ@¸§, fòŠ/{ÔL‰Ë¢d3…U¦~«•NÉ®£Ây•”»2\íÔJ¹˜®WºR½•3­1éè—ÉôÕzrö:å?Íñ‡ÃÔ׳#߇ @€úB€Áâ¾ÐËøwј2À|VßL¦!Mög‘ëû\rù„E«<rYλô†h·Áa*B7±è—ØËSOÚIƒè!úÅj#SöãÆ„Æ”ý^L Z%€ÆÔ*9¾—r…Ó˜,p½¢Oÿíð7¥yI’êÏææ<¤èB%’ä¤^ùIR”ª-¥º¢®Réª2¾d]c*›Lßø7]<û-ÅaJù™—êA€ @ ÿИòãº-Dc*pðSÝt3™n>ÉB!Sªc–ŽÊÉe9÷·7øÝ‹%‘éF-ˆ~7(³Ä  1%‚>W)!W¦}î`l ÕИR*×:âiL—ÞXIqTÃ1RžØïþãú+îQyú6ÓIH.[’¿P5¿›iI®xY”ü裮ՊA€ @%€ÆTÐÀÍFc*pð³Ñt™Lû|ùÿùç/}vÜäÙñ£(ï¼û·l4‰Zv…À?ú®Æï~à±øn³íÍ÷ºRvÒUGþè ¢ßUâ쬛ИºI»3ûBcŠãÊ•igz[M 4¦´D‚z´™@±4¦­[·N¯~IOñË}¾í®Coòg¾ Ü8äÞ† M¤ScÒ¹aài«^ýSÌH S›Ï l€ @¨G€Áâ÷ 4¦?3Mdþ×Þÿ¯8L™ X:*ª›ÄýïùOK7¼Ósp˜Ò«öׂ跟)[L4¦ôÄ¢Õš 1Å‘ãÊ´Õ~Å÷²A)q¢–½&P,)Š'~´‚O!P“@:5¦—7ïúÞ…Óyú•zQÃaêõ ’/@€ @-`°¸etÙÿ"Söc˜ÿ<¹æÀ‡–ï¹iç_ꢇ)ÿ ÷-´›Ä붯­×mp˜z53ß ú™ mS ÐRö4¦¸€peš²îJuÚL©Í@Ù\Z 1õ̆²& ¤ScúýË¥1ýäò9¯¿ý>sÉ¥åK= @€ PX 6ôL*WàÐg¨éÒ˜^þÙ?ú¨¦É„Ô¡Pv³ªî&±t¥èàS7cÑý}ýî3gÝ#€ÆÔ=ÖÚS§úÛM?4¦ôLj¶D ½&BÉR1YõìF ·ùƒ)äajéôÈ— @€ >@c꼬•lLY`¡ê5™p˜ ÕZnlÈdÂaj™d¿Hô³5êG)ûý )û½˜´J©Ur|/åИz­°4™°‡ÕrL …“¥b²¢„Lý÷ɄÔò³0Õƒ @€@>  1å3®Mµ ©)L¬Ô-c_»æõ51{óM&¦n…%íû4kPÃ*:—‡©!«Ì­ÒPsˆ~æbJ…ã 1e¿ 1ÅÅ+Óì÷pZG‰þ‘SEטä£ÄÛ6ó_ܹbýŸrläдeëßZ´æõx,¯íx7U'?“KȤjèmóÎw5—ªÚR@€ @ ,.D˜k7©ÀÁOcÓ÷ºe¯†ÕÒà‰F{p˜‚*È ·,ÜÿÞý›i¬\¦f@ek£=zú†é ëLô"b…Ì@cÊL¨êV).†\™f¿‡Ó‚8hLôœ(ºÆ”Ó°Ò¬bðS1ù ™ŠEÖB€ @©"À`qªÂÑÝÊ 1u—7{‹# AS¿±ý”[¥ÿ”þZ°b©V¶ìÚ¢e-èO­©¢uZpê r˜Ôm†/>xþ`u -ë_#£ü^zÓ¬ÛèÓ‚CËSó\EßNZ–ϤÔ\ú׉M}½w}äþÌÚR8hLÙ9S\ ¹2Í~§qИè9%€Æ”ÓÀҬˆ¦bò2 … @€RF€Á┤›ÕAcê&möO@žÓä¦HDØõ×].?“þ4I)ô'J JÝ@Š’8˜¥$ÝÍÜ&#£¥N¢Î£wÔT´ uà––‹Kÿ*¦&Aª3è_§1Ù Ä´H­¦›™‚0phEn  1e?´hLq1äÊ4û=œÄ@c¢ä”SNK³ C šŠ‰„L… > … @€@Š 0XœâàtºjhL&Ìö›'à´$—2Gj‚ï£XºÓT,½JóÛgÍ\pZ’„󓜧e}jé»Ôs¬ÛXÿÉ%Š6Jº’eÞòSp¹.a’“‘Çæ2uMÎ 4¦ì).†\™f¿‡Ó‚8hLôœ@cÊi`iV1¼ùÎ_Ï¿c‰•SoZðoNïwÝ<÷΂ß(Z @€ ¤ƒÅé‹I×j„ÆÔ5Ôì¨!3N´šS—¤&X&{Ó¤%V‘½¤¢—s¥áÆY!¯,ÝŽ¯ªøiºìSýk}ƺ\–¼Ò(Z»,¦jµ¥Ý²æ»nö©M¶ž44¦¤#Àþ;D©C`Ù,ºM©ÛÄÙ @€ C€Áâw4¦Ÿ¦C€ 5hLY‹X´¾hLq1äÊ4û=œÄ@c¢ä”SNK³ŠG©x1§Å€ @H1‹SœNW ©Ó„Ù> @h4¦¶¡LlChLqè¹2M¬c²ã®@cê fvÒ}hLÝgÎ!ÐhLÁÊF!@€ Ö0XÜ·\| )aÌy#^wÉö?ÏÍy#i^» ¼óþ†ÍïLÿàÃ÷Ú½a¶—D?A¢Š-@cj]j¾ˆÆ ®LSÓQ©HG 1u+MžSò1 h 4¦¶`d#€ @€@{0XÜŽ™Ü S&ÃV°J?¹æÀ‡—¶`¦¹}%ÀMâ¾Ìò÷‰~–£GÝ@cjD(ýŸsŽŠ‹W¦éïÁÔ°/ИúB輦SŠƒCÕ ÐhL½¡Åº€ @€@‡ 0XÜaÀiÞ<Sš£CÝŒ=¡Ü$nZn¾BôsJRƒSö»稸rešýN â 1Ñ?rJ)§¥YÅ#€ÆT¼˜Ób@€ ¤˜ƒÅ)N§«†ÆÔiÂl¿ïИúΰ€[à&qƒîšLô‹ýü·)û1æC®L³ßÃiA4&úGN  1å4°4«xИŠsZ @€ `°8ÅÁétÕИ:M˜í÷Sßp Ü$.`Ð]“‰~‘£Ÿÿ¶£1e?Æœ£âbÈ•iö{8-ˆ#€ÆDÿÈ)4¦œ–fSñbN‹!@€ b §88®S§ ³ý¾@cê;Ãn›Ä ºk2Ñ/rôóßv4¦ìǘsT\ ¹2Í~§qИè9%€Æ”ÓÀÒ¬â@c*^Ìi1 @€RL€Áâ§ÓUCcê4a¶ßwhL}gXÀ-p“¸€AwM&úEŽ~þÛŽÆ”ýsŽŠ‹á]Ç|üøÙÙ2-€@hLtœ@cÊi`iVñ 1/æ´€ @)&€Æ”âàtºjhL&ÌöûN©ï ¸n0è®ÉD¿ÈÑÏÛј²cÎQÙ!-€@«ИZ%Ç÷RN)å¢zh–S³¤X€ @è4¦.@Në.ИÒêÕC‰ÞÐn·-7_!ú¹ % ©A)ûÝ‚sÔÜ›úí·ÿäþG‡‚ùîÎ-z?û¦¨O‰Þ‘ShL9 ,Í*9+v~ïÂéú·xM§Å€ @€@ú 1¥/&]«S×P³£–  1µŒ®È_ä&1Ñ篊 ¶ç–SöCË/”\¥¿½»+É—ÆŸyY¿ìG˜@ >4&zGN  1å4°4«x&/Ü*I9™Š×tZ @€ ¤SúbÒµ¡1u 5;j™SËèŠüEn}4¦"÷<·)ûÑ-ø/”’0ÝñÅÝ,Óâ{iAå•™cõ§²4­xlpôý?½ºÆVÓ Ù?-(64¦bÇ?Ç­GcÊqpiZ± 1+Þ´€ @)'€Æ”òu²zhL¤Ë¶ÛC©= ¶•‚ß$.X´ÃÍ%úï9o>Sö\ðs”Œ%ç0Yî%efzôè½´ ,M;W-”´dSËiÙ_ïh}elÊ~ &€ÆTààç»éhLùŽ/­+4¦›¦B€ @ ýИÒ£ŽÕ©chÙpÛ 1µ e‘6Tð›ÄE u¹­o½·zó;Ó­Lßðsýº­}ó÷Î_?x«€Lhr>  1e?®ÿ…R&…Qö’D%iIúÓt%û÷Ý[´ ÄKZПÊÏ${Ikº•³ßhA  18øùn:S¾ãKë D©@Á¦©€ @H?4¦ôǨc5DcêZ6Ü6hLmCY¤ ü&q‘B]n놷Fë­f¾ô“|ø^™Ðä|@cÊ~\ þ e)—F-ÈUÚ¼pºL&-»$Las›”ºÉV3ùÉÖÏ~ &€ÆTààç»éhLùŽ/­+4¦›¦B€ @ ýИÒ£ŽÕ©chÙpÛ 1µ e‘6Tð›ÄE uO[G®Ú§¦Æ´lÛÅB«óI)ûq-ø/”¥\’Éd3Çé¥dKR”$3ÉRÒŸZA‰š´`ö’ý«?õ¦¾bñ‚@V  1e5rÔ»4&ºrB)'¤€ @È4¦|ı¥V 1µ„/u•SWqçeg¿Iœ—0ö®52‘Š©wY;ýИÒ£F5,ò/”æ‰sö’&÷?ZÅ4&ý+“Iðä-ÙG–¢É¾bÚ ¼ ahLU#€ÆDÿ€@N 1å$4€ @ù €Æ”8¶Ô 4¦–°ñ¥®@cê*î¼ì¬È7‰óÃVÚMÈD*¦V8ò4@cJstš«¿PÍqb-ä‘S£J›D‰nœ@cÊI i @€òA)ql©hL-aãK]%€ÆÔUÜyÙ7‰óÉÞµ#”‰TL½ÃÇÚ™ €Æ”‰0ÅV’_¨ìÇ@ UhL­’ã{)'€Æ”òQ=4K©YR¬@€ tS §uhLi õê!€ÆDoh7‰[€–¯ø ™HÅ”˜ÒŠ*hLÙïüBe?†´­@cj•ßK94¦”ˆêA YhLÍ’b=@€ @  Иº9­»@cJkd¨W4&zC ¸IÜ´||Å%d"S>J+ÂИ²ß'ø…Š‹á´›>~nXöƒL P‡]#§ИrXšU<hLÅ‹9-† @€@Š  1¥88®S§ ³ý¾@cê;Ãn›Ä ºk²%d"S‘û@žÛŽÆ”ýèò C®L³ßÃiA4&úGN  1å4°4«xИŠsZ @€ `°8ÅÁétÕИ:M˜í÷Sßp Ü$.`Ð]“•‰TLEî9o;SöÌ/T\ ¹2Í~§qИè9%€Æ”ÓÀÒ¬â@c*^Ìi1 @€RL€Áâ§ÓUCcê4a¶ßwhL}gXÀ-p“¸€AwMÞ°aÃiçü¸Èh{ž  1e?ºüBÅÄpâq»O½«!Fcê*nvÖ=hLÝcÍž ÐQhLÅËÆ!@€ Þ@cê¯\­Æ”«pæ´1hL9 lg›ÅMâÎòMëÖKÓþf,Y²öß_u+&SZE½ú@©ðRòU~¡jBêÒ·¾{輕[æ­Øràw0™Âô·ûîÿ¸iç»~Ù¸ã]+¯•Ê~_ýºì¥W·ÿùÕm~¥T6¨lÝ¥²^eKPÖå—7—ËÚM屮´éí—6¾½ÆÊko¿”?­~µ\V½ú§U¯üiå+o©¬ØP.Ë׿µ|ý›ËTÖe©ÊËo¾ðò*ú ¶²xíë‹_z}‘•5¯/ ÊÎ/e¾Êê Ì[½cުϗÊÜ•V¶?·"(sT–oŸ”m*Ï. Ê,•¥[gZyaëŒR™¾d‹•gåi•E›|òùO~j÷i 7O-•) 7MY°i²•ù›&eãÞ_Ø)%'Fª‘uhLY õ‡@™]€ @H4¦£ÛUAcê6qö×{hL½gÆ7>æ&q;nñþ¯ì?qæ vU7M/½“©€!ïMFcÊ~„ù…ŠÆÐ¦ù+·–Ü—7æ.ߌÉ¢¤ß¸ÏìþÎ[òí¥×¶ÿYEöÒW¤1šhSà0•&ç0•¦]ëœÀ´9˜œÃTÖ˜*“Ó˜|‡ieµÃhLÎa 4¦Àar“â(‡©¬1•¦×–&§1Í«¡1mhL=S¼ÆôL-ɦ©%‡©¬1Í7i#SöϦ´ EИR ª¾@cê =¾ @€ ´™S›fishLYŠVQëŠÆTÔÈ÷©ÝÜ$î¾ ~Ù¦I3_PB§1)ñ&SƒI•c  1e¿ƒð Šaà0}ïЫ¶Êƒ 4¦Ræžç–mú9™x̸ñM‘õVr§G;7ÿ²“ª‘š9£ê§!ôÑü¾zµ¦iL~¦%7g\Ù[ÚºKÓÃ#'¬·Éã‚òŽ›Bî劽žEΘBÉ­zåO+_y+(ѹ䪦ª¹äJÓF¦f¦“Û™Nnûìå¡TL[g-Ý:S¥’Šiú’-VB©˜LcúûOíQÎ¥b2éÁãmr=+¯íx·WqéõÊ'ïöñ°{ý-¾Ô@cJ}ˆ¨ š#€ÆÔ'Ö‚ @€ºB©+˜Ó¹4¦tÆ…ZùИè-à&q вøç0³ÛÔ¹ >oÕŽçWí8èæÞšLº3m:ÎÑGÝ¿ÿ^¸Þßk¯½|{¦_¿~z§!C[G+K{Ò‚þÔ¦´¬wâ¿ë*ãVÓMz}]ÓGúúþûï¯T¥¾;=joÆį`ÍŒVF•\¸paÍïÖû(Æ;v¬¾e&“5¿/4¦ì‡™_(‹¡9L‹^ÜVSB5Ig{m2I-²³«^:¡5<Áº>¥³–Ö׿vFªwFÕûv*ÓXײþm~/­uá’Æ´Çú­»zÊ–]2–¬˜·´o 1÷Õ¥°½´éí—6e•×Þ~1(rÓêWÿT"¹`.9K¿¶^¦f¦Š¦¹Å ë¼ ì°_ç 41ܳË4—\d:¹*ÓÉùÓ¢Ír˜iœiL›4—\y:¹›&ÓÉ3ÊÉaª©1É k-@Í~ ©YR¬—1hL Õ…@=hLô @€ @ EИRŒnW©ÛÄÙ_ï  1õžßø˜›ÄE躧ûeÍ%÷ìÒåëߪw\7Ju‹tîÊÏ­Ø>ðòÞ™Lv \îgû©˜ÄÖ7‡ µÖñ5&ÝÕö})GúÓÄ#­l“ÞÑŸ¶š½c ¶¦‹ m*ª1éÝAw«©ú®Ò‡Xž'· ·eÛc´Vþ ¶5·N´2~UýeÛ²Û”5ÓUƶi$£Sè#cåVy5Ó%¾ò?’4àܲA*oÇSö#Ê/”b覲„ZÉ¥·(˜4˜QÎré•NàÛg,zíëßêEN&‚ü³¨ÎîOÿâΓvÂÑyFg;áØ)Å?‰ÙùÐzŸÖ±_úlÆdíKç5)H°ä—ÍUù–öÝïë¿ÖK¼äç^ªm/½ö'©Ke{IS$ÓŠ ²—)ê0)ý¡e`²¢TˆA6D+ANÄòì®1“~ Ke»~¦UæXY^•‡©ÊaŠOÅTq˜œÆ4Åט*Ó¤’ÄÆÔ—Éw!"€ÆD—€@N 1å$4€ @ù €Æ”8¶Ô 4¦–°ñ¥®@cê*î¼ìŒ›Äy‰dÝv˜Ã4åÙ¥¥;¬õS1Uî‚붨榹ø½0™ÌRÖ KzäO!g¹[ã’i´‚S”ô¾yNv‡[ŸZ^ýiëØ rK餵lÉ„,Ÿ‡mÙî—[Û¸Þ÷qØfu+Ý¿[ïl'}¤ïÚ.”µÈvjwèm_ú¢ÕS«…$-«¤5Á*c[°—ÞtëÛ²¿/·«³­` «BSè#K°ä[bú¢j¨Æše…²ž(4!k!Ïý)ûÑåÊs˜"ªÓ˜”°Ç$Ô•×òÌÂW›4™ìäí&þ9ÄNÎZÍΓv"ÒyFÚ Ç¥í$柜uÒ³}þ‚}¥£}Ó4&eWòKÈX’Ƥ)Ò^RÊ¥JÖ¥u)”{©b/¹ôK½˜–F&ßa* LÕÓêy˜Úì0-ÞütEcÒ\r–©'“s˜*©˜Ð˜:ÚcÙxÑ 1-â´7oÞzë­ûî»ï˜cŽùæ!Ç|÷ÌßüîaZ~ä‘GÞ{ï½¼5•ö@€ @"€Æ”¡`µ»ªhLí&ÊöÚO©ýL °Enç;Èe‡i¶ç0U2yy *é‚™k¼»àÒ˜”ÑaÀe759»œS‚¢™~ì#ÝÆ¶ÜlR!swt{ÛI?v;ܽc¶Ý;7›Çþ4I·Ø]2³y즻…Ò<¡PXmãú–“œ|Én±«†&c9õGËVËDâjå6î*i­óó‘èOW+Û»>uÓØù{ךö§>uY£B$£©á¡”Næ{X_Ÿr:”å¸ ™XyîÿhLÙnÁ¡œÃ'¡ö¤b ré¹y–m›¶@&ÓAcÆï¦%E׉žœ£éNk¡Ó¾ý韜uÞ³‰,}#S'®¨£Ùö~ª¾Oヌ²+•,™«Tm,í»ßþÃ_ž0®ä-ùÓÆù3ÇÕ°—^yk冷+õ209É%aZ\; Óë «'’+Í%çM$WúuV¦¶åaªv˜JÓÜ¿ÿ‡@cš\šK®4ÜF7Ù˜ÚÞEÙ`Á  1¼ÐülÐÎ>ùÉOîVëõ_ÿë;wn¶›Gí!@€ ì@cÊnìú\s4¦>#d'€ÆÔqÄyÜAÁoç1¤=mª‘‡É9Lkß虨tÇÔ&$rwÁg-Û6séÖ‹š3™B÷³åÜèž·^&Ù½m»Yn‰=Ìþñç²Õ|wÇ¥‰jLzG#Çæ$ÙËeiÒfÍæñëàGÙHå ‰Dî‹î}÷-G¡ð¾\¥eÕ94ñœ%ari™´_­£7Mågcòwº÷ýÈ6ë¶æê¯Û¾{9©Kë;*ß=¿Ü:4¦ì‡¹È¿P5¦úªÀ-—^iZ±­Sç½²ÿ7˜LÑlL–²®™“sMÉ?[ï Ê¢ªk':i 1}fEI–’_JÆÒ—÷ÛÿÇÆ¿øÚÛ2–¬¬ö².ù3Çõä^jd/-[÷æR+• Lf‘k<‘Üón"9.¹`"¹Vç’‹8LSn^Ò˜b&²1u¢£²ÍÂ@c*lèix¶ ( Ó‰'žXS`ò߼袋HË”íHS{@€ d”SF׎j£1µƒ"Ûè,4¦ÎòÍéÖ‹|“8§!-7K÷qÿÇWöŸìæ’[Ü[u·Tå0Y*¦ù/–&¯‰¤bÒ]ð™/l±dë…¸±aN¦Ðýl¥ÒÍl½´àdv‘êç’¹,&úøw¸M{ª™)t§ÜöårŠ˜¢ä×!4œU©É2ùwôC½9É ›;å÷+¹ìMÛ”Y¡½‡ª¤,m•Û”¯1ÙGj”s’\5ÌXÒîdkÙwýXr©|wûªÖ¡1e?Ø…ý…jà0¹é䢩˜*ÓŒ¶Nž·!Þd² mþiÁ,OÿT=9›cÚPcÒO§Ð¨‘Ù…^i“ó“¢ 2–4×êý=%]É•U¯þ)(¯Xyk¥+^⥚¹—ØKõ20­Ù¹ ©$LeÃX’qà[­åÛ¬HY ¬µ’¸üjÛw¥L_²ÅÊ3‹ƒòtPªæ’S&9LJÂTÖ˜êäa"S:-»(4¦B…›Ææ‡€fŽkè0Ù §œrJ~šMK @€ ¬@cÊJ¤:PO4¦@e“m&€ÆÔf ÅØ\aoç;¼a‡É˱¤tKµj:¹:©˜t+Ôn^ðû&Sè~¶ÏÖ}$‡ÆI<¦Ý˜ô#ÏFwÍí›!NïØÊz§¦Ædïk­©[ì6›{G·Ø]þ!«‰œË~d[¶ Iõ4&}dÓ'ÙäGúSÛ7s(j)Y%­¶‚›ÎAÐ:ö¦iLZÍ2BÙ›~6¦Ð®})ú‘iLZG»¶zšËeê€qsM°Ê 1åû¨ÏeëŠù å&ÍV¶lý›fɘ„ªYÉ,‘^c µtŸôü†¯—“Ée“S”ªR+Ur,)[á°GŸ\¹á-s•ü"¬TÞ´RC]Z÷æ€ß_ãÔ¥±SçÿæÜKÆL™oª™Ô¥;‡ýãµC-^içÂJú¥Ë®rê9ÿpõ ˆ%{IE¿ÅA©)0•’0ýöÊÁ'Ÿ9à–{F©T’0Õp˜â“0M+ L›§”ò0©h.¹ÆÓ¤ùUœ·ZØû û=8büÚM︲ak‡Óû¼ÛÇÃNléÌÁ— 03ìý—N‰î§1™Jþ)-4”í3áö±{ŒÀÖ­[?ùÉOöJcúìg?ËÔrë&4€ @I@cJ: î)AøìºIhLM‚b5Ÿ@oç»”¦Y/¸º>êÙ G]2ÑËÃôzp üÅ÷O^ó³ÆÓʲä;£‡˜pÑsý»àÒ˜4ïLÿKoh8»\¾ÙÒºŒ@cÊXÀjT·h¿Pr˜¾8L[Ý |Ò¼:{Ÿrã¬ßÝ·à¼!s»§ÉÁ7ÝþÐç¿ô•ÓϽdŸ/~寡J]úæw=ê‡'œ~Î@½3jò<¥Îré—FNz~÷Üó„_ž~êÙøÁñŸû¾e{©ä×ÈÀT™Eî‘§æ|æ÷”ÆtÎÅWªÌZ˜ÎpÅO®‘„©ÎDrÎaR¦ûé3êlõ&²1eñ¡ÎI¯éÏG¬jØ žÎ㬫1It’qï§¿Ó—-©SRád¿o¼±W“­|ë»>üè#B€ @è4¦.NãnИÒêTM‰Ñ¢Ý$nQ†¾bÓ$9L•Én,WĨY޼dbe.¹²ÃtÎm³¸xBIcÚÜ_¤b:ëÖÙ‡ÑsýTLº n Îû&S†ºC᫊Ɣý.P¨_(s˜¬ÚZ>¿LUöÓ+¦]ýð å‰ÉÖ¼~çS«Ž8A)|&/ب¸ÊÅwϳDzr˜ž|îÕÃŒ—Ædó*SIB NàOÎ^÷ÕoüÛ˜qã³ß)Ê-°¾¡•™ôSø©Ïìár)Õ\Ðoå= t1ÏXªš*®Ú[ò猛úÜ*yKÒ˜,ñ’\¥ÑSæÉ^š>y7 RMàÔÿ)5‡)i…@~¡V¯^­ø¼[zNàcF'áÏã T;ë¤ýÈÓÒ˜ýEÓ€»ž/M'÷Ц“Ó üþÉk¤1Ý7i›NΗPÍdÚóŸþùwý/Q(7ï ™úߥ19ž5¤1ÝõสÍjcÉý†Ú/©¼%•I³ƒiã†zZ)—d/)Ù’IKnÎ8-+L÷œö¹/î{àw¹î¶ôo9ýÒÊOβ19{ÉÍ÷orõ-è·XŦ» þµlÛ¬¥Û”{éÎG&«Hc’¦&‡I厇'éÏ obe9iLCšØ3‹\MÉœ6KÂäý¦£1µrzâ;¨OÀiLn:9-è¥9âô¥f³1Y&½†®´LR¢`$Bà“Ÿüd &“ËÆ$iÝæ]ÿþÁG‰TžB€ @E!€ÆT”H×h'SƒŸ™¦£1e&Tiªhn§‰w§ê¢dßÔ½Òå›{î¼–¦³Y䟱N“Ý/%a*%Pâ‡Û8kŒnë^©&›Nî˜Ë¦üäSn·ªç.xé–§s˜n>iß/eÑ}W¿1rÐÇã.¥@ ¥NÿÄǧü¿;uȱݮ(È/Ô¥—^úë3.pù~Lš±Yätê¾ãÉUÎ@6iÍO°>ÊÜ#‡IE¦‹R.Y"=•¯Ÿ9ú‚ÛŸs xl>P_BíwÆÏÇ-¹nΆ? ovË“/~£¦w5ã•W¼ôì§>½GEÉJ%—’¿ éÎácî’g,Ùh¥ì4™læâWN;g  I§ž3P¡Ñ´qf­áÕ;d/)Ùáa£M]ÒÂá?8Þ~sÍ^Òäqƒï$^*EPI˜4sÜÉgP±ÜK¿½bð¡ß?Né—ö.å^²ôKw>-hLø—I ›w¾›ÊÆQ)@€ @ /ИòÉÚÆÔ4¾ÒehL]žÝä&q>‚ß ™LÊú0wÙfwÛU÷\-EÄãÓ×)Ç%÷̨r÷¼Ë‡/2‡I‰8sL)ßÃÖ™/lUš¥v¸àö¹º^/“Gà0í÷õE«6Ú¨ìo¿_¶´1“Îþ;4¦LΫtq~¡d2ü› |oÆNàîì­‰än±LgòÛÆ¬4F'p9LÝù¼L½g, Nà’Z¤1Õ“P•HïŒs¸{jï¾ÿAv{ˆõ ¿H`zç¯Ô¢`R¹OïQ΢TILhé”\ùâ—©ÚU ¼1+?Tôc*iÉ•òlq«wœzöÅGüàxM§O9ûbÙKr•®üÀ}O ¤¥a£-ë’ýìÊaÒ{åmʺ$ué3ÿ¸ç˜§—>üd0CÜ•·Üó=£´pó=OXî%û]Vî%9L.ýR¿ß\¤ÄK ô¿îóå3/4ôÁ‰ÿ²Ï—/»á¾_ž~áÁG;nÖKá)äb&ó™Ð˜²{ Pótp“«^/&•«™u‰TLéŒ4µ*ý/­é²+oô5&-“© †fB€ @ hLÉpOÅ^јR*K‰ÒâÜ$nNæ¾b&Óœ¥›Ü7–ÃcÖ [M`R¹øîy|`‘ÝW⇋‚L=“îŒ*ÓÐq«jN'r˜0™2×CŠUa4¦ìÇ»P¿PºGvÒoÎwú©é2:Ož¿Q'ðã.ŸªøÄç_s“Nàwñ®ñ«}‡IsŠo©˜J xüDz!‡ÉNàÙ5™|É LÖåKÓîÎIªZ¨ÈIÒ˜n`L]]©ÚX*¢4%«Êª ÈU2cÉÊ¥W QÖ¥ó.¹Ê².=9c™Ò,©ø‰—ìgWeì3K%0ðíCôï”ç×ÙÌq›£ÉãTä0É^šøÜËg ¸Â"{ã]#'ÌY«"iI¿Ñ7Ü9RåéÅ›k©K*r˜ñÇ&-ùåi^{Lj&30ù ™Ð˜²²¤é" ôI¡ )“¥bÒ«A6¦t5…Ú@¼uëÖO|â½2™þóþûç–¬ iLï¼û7pB€ @è4¦N‘ÍÀvј2¤ÂW©ð] …ºIÜ  ¬}G&Ó7¾}Èì6¹®•Yäv”ç!ª¤ñæ’[Z•‡I÷GŸ^¼ÅÒxL]Xš‰FsÐTf#ªé0ŘL;W-üÓ«k¢üj¾™5ÌÔ7 И²¥ø:í*0™N?ßM!gŠŒ? ¨eÑ›]š},0P«ó0Im©—H¯¦Ã”i“ÉúFH`²î$é>½»¯(‰”ª‹4¦¡÷ñ³+U¼±Š®T1–LZª*Á$q®”g‹s)—,ë’ÙfN]2ɦ³bö’‚hq J)÷R¹”rkYy¦”dË~ ƒ¢iã\ñç+ýj—§›7…\hF9²1eÿLI 2F)c£º¡C‡öJcºñ¶{CyŒéH€ @€@g  1u–oª·ŽÆ”êðP¹4&:B Šv“¸D™ûJÉd:xÖ’õ¦ð-ðÒ\rµ¦ùÁt3*1SM“irÿ£UæÞÔ?JïÑ£÷ÊR*œIhL™ [U¥ ø %“éW§Ÿ˜ÊfL%‹^y&Ð’ÃT6]Á%ä0õH¨1S=“éèGNy÷ÙüÎt›B.ú2©ìòZ ¥Hù‚4¦a£-µ’K°Ö•d/EŒ%%[2'¸¾·TκԤºäÛKN]ªi/ùSÉ6Êß^*ÉÇ”ÎBŽzK¡wÈÆ”òÞNõrF)g¥9E!pà6i2vä£SQ: í„ @€@RИ’"Ÿ‚ý¢1¥ T¡4&ºH  x“¸J™ûʸ'Çðíƒg.~ÍIˆ,„ \ÖôÝaÒ¨ì«Ûþüï|ä@Õs•”Šil¿ý3Ç“ g’S&ÃVUébþB]pÑ%ýNëè2¡x9 SU½Ê ¼â0•¤–Àb©$Òkè0é¾qÇ»>÷…[¦_cŠéݦ1Õp’¼¤JÒ˜† -K©ZT*ç¾²¹ájK¡dK¡|K5R.ÕʺT/ñ’E3”{©¦½d[N¿„Æ”ý³#-È04¦ ª™€þ{ñ•¯|¥¡ÉtÀßY´jcMéOfR¹"÷ Ú@€ @cê0à4o)ÍÑ¡nF‰žÐbÞ$nTæ¾2f\`2M_ôš»ÉZžÈÆ›¼&šÆ£g.¹¦ó0ivÓο¼ÿ·"åa’ƤõŽ¥e’ºd™™^?|æeýj¾¯ulÍÌ¡¦Â)%€Æ”ÒÀô¢Z…ý…’ÉôËÓú÷(2=ÓU&’³,z–H¯4ŘKÌSJÆSN¤×ŒÃ¤ø‡õH¨k^_³ÿ½û« _:|ЬAý§ô×òàùƒ÷º¥œHOËz_Q´Tú Îêéy™ÆäT¤š _ø_{G©w¼X»D °7‰‹™L_ÿÖÁÏ,xÕ L³J7S5Q9 Sõ-ð¶8Lë\¥Å÷ Ò²¡¶üL’™V<6x窅¦+ýíÝ]R—ÞݹÅÙKúŠV(BthcÇ  1uqÇwPä_¨Àd:µùì˜1Àd'pÏ@õ¦Rnž>:LQ‰¨JȤ)Jr•‚ÿ*lY¨eûTÒÒô Ó%99{IëK~êxohz¦1…æ}ëImUÊPøyiL÷ŽŠJ5]¥èôp=qñ¤¥rŒ*‘Šñ–ü9ã*êRJ_]šV™6Ο9.±•vØKNfbR¹¦;+B  ИڑM@ AúÆ€K.Ûw¿¯ÿ‡ÿøL²—´<ð÷W=·dmŒÃ´nË._O°þì€ @È'4¦|Ƶ©V¡15…‰•%€Æ”(þ¬î¼È7‰³³ÞÔÛL¦ió_q÷¿ëÞ/ÍPãß¿mø$ ÉÖKŠoƒ´¡’Ætã]#k®XJQÉIK=ºR­4KžgVwª¸ZÞ’æÜh¥µtJ}üS>z>­È 4¦¬DŠzB )ï¾ÿÁ†­»¢2“’0½ùÎ_›Ú+A€ @è;4¦¾3ÌìИ2ºU©@Án_S¹IÜ>–Ø’L¦¯xÐSsÖYâ‡ÐÓ>æaÊ@û©b¡ 1e?ÜüBù1”Éôӓέi â0ù Lc %L ý)é†;GÖOªTš}µ"*)–K…e¢’+%±,Tª&‰ë‘–*ù–J?¾ {K!í )û'KZ%hLYŠu…@“$3½ñöûJδå¿háwÿ¦\MM~—Õ @€ ´S fuhLY\‘êÆT¤h·­­Ü$nÊŒl(0™¾qиÙ/û9<ÈÔ‘èQÍÞ@cê ­t®Ë/T(.2™N8éÜhΞãuÎ爟ÕdÓο䆚iLe©ZE2!Iås_ÜOS=9©ÊUª!*™·TÒ•J© ýRž!®Ž´”T¾¥øtMhLé<R«¼@cÊkdi @€ @ 9hLɱO|ÏhL‰‡€ 4$€ÆÔ+D p“¸€½B&Ó~ßø·±Ï¾ìîk’‡©€Ý ÿMFcÊ~Œù…ŠÆP&“¤%ßJÁa Q2)”6)øsaO‘ÆtÝ#kåRr©•6Õ•LZêÑ•ÂÆRO¦¥tJKQ¥ )û'KZ%hLYŠu… @€ dƒS6âÔ‘Z¢1u+m+4¦¶â,ÊÆ¸I\”HW·Ó7™p˜ŠÙòßj4¦ìǘ_¨š1ôM&¦("iLÿ©Ý{$$—6ÉËŸ$éÚÛG„)ÕÍ«ä‰Jš®2+\•®JpŸý(mŸ¢1eÿdI ²D)KÑ¢®€ @€ l@cÊFœ:RK4¦Ž`e£m%€ÆÔVœEÙ7‰‹éH;Ídºñž±ûî÷õE«6ÆÌF¤©ˆÞÿÛ…EóJ)«‘ë©7¿Põbh&SM>Æô»WeK %OZ°ioiLCG˜“*“æËOre£2*õ”yÓf µ¥>hLÙ?YÒ‚,@cÊR´¨+ @€ @ И²§ŽÔ©#XÙh[  1µgQ6ÆMâ¢DºV;o}ð¬=þÛ'æ­XÃTänÛ¶£1e?´üBÅÄð×§žö›s.ˆ9{ë#I¨~ôQö;BïZðÖ[oýÝßýÝn¼ÚJà?ü‡OLž±Ðïo¶îê]`z»öÉ»}<ìÄÞ~‰õ!~hLé5„ @€ dSÖ"ÖÆú¢1µ&›ê4¦Í÷f¹IœïøÆ·NÑ¿íùÿué†ëÝ'S‘»GæÛŽÆ”ù~Ì/TL —m»qÎË·ÆK¨t˜j{çÝ¿Åû^|Ú4¦ìŸbiA2И’áÎ^!@€ @y&€Æ”çè6hSƒŸ™¦£1e&Tiª(7‰Ón×Å¢¿ýõ5ï_â0u;쯽ИÚË3‰­ñ Uú¾7|é'Uv¼õv½8“£‡ÆÔ‚¥Ôð+hLIœÙg 1å!Š´€ @€ .hLéŠGWkƒÆÔUÜì¬%hL-a+ú—¸I\ä°åé ·üþ¯¼õîû„nXâ0¹cä¤íhLÙ$¿Põb¨TLº6QÑÂo¿=ã0ùèИ:I-¬€Æ”ýS,-H†S2ÜÙ+ @€ @ ÏИòÝmCc*pð3Ót4¦Ì„*Må&qš¢‘d]|“ ‡)ÉH°ïv@cjÉä¶Ã/TMö–ŠÉ4&-èOßdÒ ‡)Ä ©K©áWИ’;5²çl@cÊvü¨= @€ @ ИÒ•.Õ ©K ÙM 1õ^q¿ÊMâ‚Ä~øÒá*ñ5“ ‡© ]"ÿÍDcÊ~Œù…ªC—ŠÉ%dÒjf2á0Õ$†ÆÔÐIja4¦ìŸbiA2И’áÎ^!@€ @y&€Æ”çè6hSƒŸ™¦£1e&Tiª(7‰ÓÖeÿ{÷_¸eaÃÈdzÿo4\ hLRƒ*ò ä§bò2iÍ?ýù¯äaªÙ¥þúïJðŠ)¯íxwõkoǯS¨O7lûóÚÍ»â›üúÛïwösòn;±³»`ëH‚SÔÙ' @€ @ ßИòߨ֡18ø™i:SfB•¦Šr“8MÑèT]úí·Ûïw;úÑ£µùLZпƒf <°ír¯[öÒ¿òœÜ§k^_Ó©Ú°]t‡Sw8wr/üBEé†R1ù ™: ¶ ®@cê:rvØhLÝáÌ^ @€ @E"€ÆT¤h‡ÚŠÆTààg¦éhL™ Uš*ÊMâ4E£Su‘“$?I[—¨$cÉÒ2¹üL[vm±OÝ;Ó7L7ç‰2L)ÃÁ+W_¨P £©˜B ™²sZ 4&úBN  1å4°4 € @€ 4¦á'½k4¦¤#Àþ@cj̈5"¸I\„N¡¬Ký§ôWK•Éô² Lz _:\隤.é­`ÅÄ&^È04¦ ¯\u~¡B1¬™Š‰„LÙïé´ 4&úEN  1å4°4 € @€ 4¦á'½k4¦¤#Àþ@cj̈5"¸I\„N!KI®’ZªK–ŠÉågÒ²>•ç$uI úTeì‹cm5^È04¦ ¯\u~¡B1\¹c¨˜X¶äï^öY÷§>Ê~Ài<hLt‡œ@cÊi`i @€ @ AhL ÂOz×hLIG€ý7&€ÆÔ˜kDp“¸ÂÍçr,ÉR²eKÂ$«ÉĦ]ÝesÌ¡1¡cä¼hLÙ0¿P11|xùgõ¿ì™@ 4&ºFN  1å4°4 € @€ 4¦á'½k4¦¤#Àþ@cj̈5"¸I\„N¡‰ä”‡I-U¾%×^½£¢»ç^6l(2Úž[hLÙ-¿P11DcÊ~§±Иè 9%€Æ”ÓÀÒ,@€ @€@‚И„Ÿô®Ñ˜’ŽûoL©1#Öˆà&qa;…¦#~pìøK¾´ï×0™ Û òÜp4¦ìG—_¨˜¢1e¿ƒÓ‚XhLtœ@cÊi`i @€ @ AhL ÂOz×hLIG€ý7&€ÆÔ˜kDp“¸˜BÓ‘?8î…—ßX²ö§¦/þâ—1™ŠÙrÝj4¦ì‡—_¨˜¢1e¿ƒÓ‚XhLtœ@cÊi`i @€ @ AhL ÂOz×hLIG€ý7&€ÆÔ˜kDp“¸€"p˜~xÜÒuošÆ´è¥×Ç=ƒÉTÀŽ÷&£1e?ÂüBÅÄ)ûœÄ@c¢ƒä”SNK³ @€ @ @cJ~Ò»FcJ:ì¿14¦ÆŒX#B€›ÄEëæ0-[÷æÒ—ߔô¸¤1-\óú¸§1™ŠÖòÞ^4¦ìG˜_¨˜¢1e¿ƒÓ‚XhLtœ@cÊi`i @€ @ AhL ÂOz×hLIG€ý7&€ÆÔ˜kDp“¸PBÓQ?¨ôÒ:öÝéÓ§kaÿý÷×.\ÿÝÐî´²¾¢ïê}½úõëçªÚpS}éÚ×àÁƒ}½ÚÕYíÕ¿j~_jRôï¢1e¿ð C4¦ìwpZK‰’ShL9 ,Í‚ @€ $H)AøIï)é°ÿÆИ3bn¤S˜Ã´bÃ[JÅTšQî F¹@cZ½sÞªsWîxbÊÂÏ7m29s(ªÉÂÑË›LHŠî4&SÜŸkÖ¬i©šu;v¬}Q“™LÍl*~_²‹¶lÙRo³¦Ü jr¯4&g/é[Ñ5„À =И²ßø…Љ!Sö;8-ˆ%€ÆDÉ)4¦œ–fA€ @€$€Æ” ü¤wÆ”tØchL±F„7‰‹Ð)ÂS%“?£œR1=_Ò˜ž[±}ääfM&ól”:h·Ýv eZ’Ž# ɽ)ŸI‘Ó˜´lÉ™L÷‘dê}ËÆ¤e}Å” û®éGÒ’lM'Hõïßß¾•~ôŽSˆvíÚeJ“mJ “´Kzä6eÖ«Þ¾¬·¸Úú’–ëH–É5ÜiLnãúº*ã²CùMÓ}ç ©O‡'SŸð¥âËüBÅ„)}”JtŽSçØ²åD  1%ŠŸC€ @€rI)—am®QhLÍqb­$  1%I?³ûæ&qfC×lÅ=‡é­eë{¦“[¼öE/½^žQ®”Š©¤1mŸ³bûìåÛFLZðù/5ž].>“ŸOHZ,"Ó˜œ„$kÇÞ1ßHrÉOöŽþuÙ˜L’¤­fѵ‚ù@æ<… Ø›¶M—„É6¥wlS®’nS6­[t_¡kƒ&fY…ÝË©]6µœÛÕÓv'yKïë_½ô§L,k‘Ÿ)JëÛû¼Z$€ÆÔ"¸}_¨˜` 1¥¨§R•N@cêU¶™hL)U€ @€ äŒSÎÚ›æ 1õ†ë&C)îß+7‰3ÀÕw“7Ü›/ØŒr/½¾h4¦ó_Üé§bš³<Иž]¶íñ‰ó÷id2…4&Y8Òt,Ÿé;rq,e‘Óƒ´ìûF¶šËÒ¤•c4&Khdn“e`ò§l³XüœF’ä9[ÈyEN?²/†f‹î+ÊÚ4,—WÉV°Ö™Ÿdº’5Ð)JªŒ 'ý«¯ë¥W· 7^¾ûgg[‡ÆÔY¾ÝØ:¿P1”јºÑÙG‚И„Ï®;I©“tÙ6 @€ @ ˜ИŠ÷R«Ñ˜ üÌ4)3¡JSE¹Iœ¦h´¹.5&:¹ú©˜ä0ÍZºmæÒ­Nh`2…4&óŠLÙqù“,÷’M—f)ˆœ´¤‡4&Ë“¤÷kfcòÕ"-KòÝ#›ÇÍæ‰Ó¿Ê´dùì¥?m›Qɾ£1پܦÔsô¯MŠç¿›ZÎ5Эi–™‰e¬”YÊס˜N® S &¼ ~¡b€Æ”pïd÷&€ÆÔiÂl?!hL g·€ @€ @cÊqp5 ©!>OžSò1È` ¸IœÁ 5Ue.¹åëß\¶Î›NNy˜œÃJÅTšQ®¤1mñÂÖéK¶<<~Þçêçdj8©œêjb“ülL–-ÉOYd­’£1É…r®V³?M0r–’OGÕS*&{Çí½žÆÚTt_nËfeÕ ƒo ITÚm·Ý´k-8Êef² ï¬ÕZÁUµ©³RChL ¥~~¡bB„Æ”úþKûF©oüøvj  1¥64T € @€ YhL™ ]ß+ŽÆÔw†l¡ÓИ:M8—Ûç&q.Ãê9Lo.3‡éåÊ\rkß0‡É¦“›¿zç¼U;æ®TÙ>§Ça R1™ÆôÌâ-=ùü羸ßË/¯²ŠÑ˜l9}Å-˜Í£ù:–0Iÿšd³³Yv¢š“Ûš%|ÒŸ¶)½ÜŸ~’'ûH)ŽL¢²—ÕÇ6e)‘lµÐ¦\­¢ûj¦·ø“yZÚå ²& ˆmGÛw@Bé—ÈÆÔ êë 1µb›à*&hL ÷NvßihL&Ìö"Ð@cÒÝÔÈ–wÔ^~^ЄjÎn!@€ @H+4¦´F¦ õBcêdvÑGhL}X̯s“8q7‡I˜\¦ÑÏnøéÓ–¬}cqÉaZTr˜”¦ã/Ÿú| 1mnÅö_]7ãð‹'>@eücÓ×Ó’-O/Þ2mÑæÇÕ5™20:õ[&ªM%ûD©OøRñe~¡b€ƔŠ>J%:G©slÙr‡ 8?^ûq.»dœq“&Kãi5ÔŸ²—ô§^Ê;Úáj³y@€ @€2K)³¡ë{ÅјúÎ-tšS§ çrûÜ$ÎYXå0ùÃã,“›HnÔ³ŽºdââÒ\rÎaš²`“¦oœ5F©˜ä0)“¦[G¯>å¥&¿äR1=½hóÔ…›§,ÜôÀ¸¹{×ÉÉ”3†4''И²H~¡bbˆÆ”ýN b  1ÑA2H@Þ¼&?§¦ì%%5ÉTWc’±¤L¡.}¨V5õÉ}3ƒ@¨2 @€ @]!€ÆÔÌéÜ S:ãB­|hLô‡p“¸h©ýJà0ýà8³—T^xù %a5kÑ'º¹ä,ÓÉ×ϼaÄ2iLÏU¦“S¦'Ÿ{õ)‡©’Š)Иlš<Óýcçîý…ڳ˥– +.4¦ìÇž_¨˜¢1e¿ƒÓ‚XhLt Pî%M”Ò˜ä6ù&RƒIå|I² ‰ý73ˆ…*C€ @€ ÐahLœæÍ£1¥9:ÔÍ 1ÑZ ÀMâ ¥ó+æ0SÉ^2)˜Hî¥×GÎ\/i¡7—ܼÕ;JsÉíÆ¤{ù¶g—m1cý̶j:¹3n~ö77?ûôâÍÓlF¹R*¦IóÉ™Lc枣ÎC) —ßx$…‡@*¡1e#Nqµä*†Sö;8-ˆ%€ÆDÉ,?“&…³vô/½´Ð i×®]‚¿ÑÌ’¡â€ @€ t†Sg¸fb«hL™SÁ+‰ÆTðÐZó¹IÜ·´}ë ƒºížÇuɳ—$0- 20IcZwäÀ e‡iU9“æ’{nE 1™Ã4kéVéJr˜”‡é¦‘˽h|ÃTIÅd“Ê7¾{ÄqÿÃÐùÿ“~)E# y"mý¿v}И²§¸Zò C)ûœÄ@c¢ƒd–€o9É%TjVc’å20 J! ªÔ9Yú¡Acê\?èÖ–ù…Š!ÆÔ­nÈ~"€Æ”xvÛwNc’}Ô¯_?Û ô§hLÒ•Ü\rJßš‘®ï•c € @€ äSƒÚl“Иš%ÅzÉÈÒÝåä(±çnç¦K˜ÉtËÝ-\³SÅ&ËÀôØô—•uÉ•ãþ8Õ&åa:àÌ1ÊÃ4si0—Ü1—M9lÀøÃ./©j:¹ùå$L!‡ “)7§ù†d釩ù¸¦uM~¡b"ƒÆ”ÖnK½ÚD©M ÙL÷ øÙ˜d%™‰ä|¦S´º[¶lé~Ø# @€ @Y"€Æ”¥hµ¹®hLmÊæ:@ Kw—;Ð|6Ùn·Æ-ß*›Lw=fö’ŠËÀôüªsWî°‰ää0I`š½¬<—œ9L3–ÓÉ=³xËÓ‹6×›NÎÏÃd&S:{Bçj•¥4¦Îõƒnm™_¨ÒhLÝê†ì'!hL g·&Ðk©Óbû€ @€ džSæCØzИZgÇ7»E Kw—»Å„ý4$ÀMↈ²µ‚™L7Ýù¨æ³)äL`š[˜, “&’+Í%WÎÃdsɵæ0Õ3™nY˜-tÔ¶Yú¡Acj&¢é^‡_¨˜ø 1¥»óR»>@cê3B6NhLéŒ µ‚ @€ d™S–£×Ǻ£1õ _ï,Ý]îvÑn7Ç)KkÉd:òÈÀd*ÛKÕ“9L³ÌaR¦‚$Lu¦M“æ•§“«—‡©^N¦5¯¯ÙÿÞý³Dº6G K?4hLÍÅ4Íkñ 4¦4w]êÖhLm€È&ÒH)Q¡N€ @€ l@cÊvüúT{4¦>áãË]!¥»Ë]ÂNš!ÀMâf(enwÿò—ƒ9ü†Û±)ä,S( “s˜ž åaZ¸iò‚M“æ÷ÎaÚòÆ_>üè#µë¯»úOé/iú†éƒçVZ¦A³éMýk+HrÒGZпzÓ½Ÿ9άp–~hИ²ßAù…Љ!Sö;8-ˆ%€ÆDÉ)4¦œ–fA€ @€$€Æ” ü¤wÆ”tØcYº»Ü¸5¬Ñ%Ü$îè®ïÆL¦ë‡>˜\¦K‚8LÖÐ~cûI`’º$™éèGûâØ-»¶¸üLò–ô©ÞÔ;’œ´¬uºNˆ¶B K?4hL­D8]ßá*&hLéê¬Ô¦íИڎ” ¦ƒS:â@- @€ @y"€Æ”§hö²-hL½Æê ÈÒÝåð°ËÚ¸Iœãža&ÓuC¶)äz&"¹Å[$0ùS_ò09˜ò“”rIêÒ^·ì%™Iï+ñ’Ü&[Áì%[ǽ“ã@ä©iYú¡AcÊ~Ïã*&†hLÙïà´ –$§ИrXš@€ @HS‚ð“Þ5SÒ`ÿ déîrãÖ°F—p“¸K Ú™L×yئSQ¦h¦© 7Y¦¶8Lj«ì%ýë«KšfNY— ƒ>•À¤•„É•„±ÛÞÈÒ Sïb›Æµù…Љ S»,uj#4¦6ÂdSi"€Æ”¦hP@€ @€@> 1å#Ž-µ©%l|©«²tw¹«`ØYn羘ÉtÍm—¦òDrA¦r&s˜4‘Üü“æmœX*ß=ìGWß0tí¦wbÊ–7þòáGEZ¦%½o“ÇÙ –I ×ײ?Çœl'­™û@ä£Yú¡AcÊ~Ÿã*&†hLÙïà´ –$§ИrXš@€ @HS‚ð“Þ5SÒ`ÿ déîrãÖ°F—p“¸K Ý™LW ~è™Å[žV©LSn–Àä&˜úè0©¡Ò•”iIr’?mœ².)!“+ZMïhš9½ã¯–('vÞ˜@–~hИÇ3íkð !4¦´w_ê×GhL}È×ÓJ)­‘¡^€ @€ ì@cÊnìú\s4¦>#d'¥»Ë‡Áš%ÀMâfIe|½²Ét냖)˜ü‰äæ—¦¾;LÆI&Ó®¿îÒÌq>6½©wô¾Š[ÍR4ñÊ ,ýР1e¥WÕ¯'¿P11DcÊ~§±Иè 9%€Æ”ÓÀÒ,@€ @€@‚И„Ÿô®Ñ˜’ŽûoL Kw—·†5ºD€›Ä]‚ݘÉtÅ-:É&’sI˜Úå0¥ ­T¡S²ôCƒÆÔ©^нíò é{‘=%B)ìì´óИ:Ϙ=@€ @€ŠF©h÷Ú‹ÆTààg¦éYº»œ¨ù¯(7‰óc¯…f2 ºåA˜&Uf‘kË\r…"YØÆfé‡)ûÝ”_¨˜¢1e¿ƒÓ‚XhLtœ@cÊi`i @€ @ AhL ÂOz×hLIG€ý7&¥»Ë[Ã]"ÀMâ.NÍnÌdºü¦á~&ò0¥&>i¯H–~hИÒÞ›×_¨FhL;kdšS¦ÃGåë@c¢w@€ @€ ÐnhLí&š¡í¡1e(X…­j–î.6Hék87‰Ó“Ž×ÈL¦?z&ÓwûÑÕ7 ]»é˜²å¿|øÑG¯;H7,ýР1¥»/5S;~¡b(¡15Ó…X'ÃИ2<ªG‰þ@€ @€@»  1µ›h†¶‡Æ”¡`¶ªYº»\Ø ¥¯áÜ$N_LºQ#ßdÂaêñ¼ì#K?4hLÙïuüBÅÄ)ûœÄ@c¢ƒä”SNK³ @€ @ @cJ~Ò»FcJ:ì¿1,Ý]nÜÖènw túv˜LßùÖ—ö;#d€ @€ „ 1¸K 18ø™iz–î.gjþ+ÊMâÜÇxñ=ƒ&÷?ú¥ñã-yY?÷¦o2á0å¾W´ÜÀ,ýР1µæÔ|‘_¨˜P 1¥¦ŸR‘Î@cê W¶š84¦ÄC@ @€ @¹#€Æ”»6ß 4¦æY±fR²tw9)Fì7B€›Ä¹ïcûíÿîÎ-Ñfn^8]z“ÿ¾™L8L¹ï}i`–~hИúét|—_¨˜8 1¥£“R‹Ž@cêZ6œ,4¦dù³w@ÿöþÚ®ªÎ÷ÅwüÇ{õÆxï¾úûƨÆÒ²¼—ûêë^ %jÔÒRA!TÙ ¨h”^ÚУ ,A1ôBГ„.}K’œä¤O šä¤%A"RRHþßµ{ϳöÚÍÙ{Ÿ½ÚùÙcŽÃ:{¯µæœŸßÜk-2?ç7!@€ "@c*bT[ìS‹ Ø-Eyš]NUW`’¸À#â­7.þŨGF¾öÑ1ê¦2)3“më¥m•Èû2™T´>zeÞäákÈÓ©³gé(îPM¢Æ”¥¡J[b €ÆTN™hLYˆm€ @€ ‹S±âÙVoИÚÂÅΩÈÓìr*€¨´&‰‹=.´lœL¦×~Ó§ŸÚÞ»¾GŠ’%aR–&ý*·ÉÞ×O[cNïk½£ el*6z×.<ÝhИÚnööçÕ$&hLÙ°´¨«ИºŠ““e‡SvbAK @€ @E!€ÆT”HvÐ4¦ qHÂò4»œ0ªkL€Iâbs•ÔGû)ŸIÞ’ÞÔ¶²4é§Œ%ýª÷ݧ&3é¥lL–®‰<ÝhИò?p¹C5‰!Sþ8=hJ‰RPhL ,Ý‚ @€ ¤H)EøiWÆ”v¨pyš]¼7ì‘&‰R5æ*é%WII˜¤%ÙÏ7öö›Ì¤—‰M–¢I?mÛŠ[.¥æSmæäéFƒÆ”¹áÓvƒìõÆ[;Û>ÒƒИ<²ß]Dcò;þî=SƒK× @€ @)@cJ |ªEcÊBhCsyš]&–™!€Æ”™Pt¿!ÎU’·¤Eå¬ÉIZ*NEY—”„Éå^²¼MúUV“í©í·Þ8ØýfqÆ<ÈÓ)Ï#ÍÚnw¨ü÷#– 1Å‚•“f‡SvbAKºJ€»ZWqr2@€ @€DÉãa€ÆäqðsÓõ<Í.çjñŠÆTà›«¤jy8YJ’™ô«ò3IW’Õd™–ô«¶õ‘vö¤CôŽ%mr†Sѵv äéFƒÆÔnt³·?S“˜ 1eoÀÒ¢®@cê*NN–hLÙ‰- @€ …SQ"ÙA?И:€Æ! ÈÓìrÂh¨®14¦åRré””xIö’:« ÷Óú®÷í#{IfÒ¯¶/DäéFƒÆ”ÿá‹ÆÔ$†hLùàô )4&HA  14°t € @€ "4¦á§]5SÚ þÁ äivyðÞ°GBИM5(<ÝhИò?äИšÄ)ÿœ4%€ÆÄ)(4¦‚–nA€ @€R$€Æ”"ü´«FcJ;Ô?8<Í.ÞöHˆSB ©… § Sþ‡S“¢1å€Óƒ¦И %€ÆTÐÀÒ-@€ @€@ŠИR„ŸvÕhLiG€ú'§ÙåÁ{à @cJt6«Ù·õPßœCo½™ÍÖѪ ÈÓ)ƒ¨Í&¡15†ÆÔæhb÷¼@cÊ[Äho‹ИZÅn€ @€ ´L©eTÅÛ©x1-^ò4»\<ú¹íSnC׆?}õ!MJfâÖäéFƒÆÔZL³¼S“è 1eyèÒ¶.@cêDN‘EhLYŒ m‚ @€ ä›S¾ã7¤Ö£1 'B O³Ë‰¡’V 1µB©°û 16´qu,O74¦¸FArçEcjÂ)¹HM©@cJ;•ÆO)~ÆÔ@€ @ð“oõÉãàç¦ëyš]Î Ôâ7©ø1nÒC4&¯ÃßIçót£Acê$ÂÙ:©I<И²5XiM×  1u)'Ì4¦lÄV@€ @€ŠD©HÑl³/hLmc÷äiv9O74¦N"œ­cИšÄ)[ƒ•ÖtSבrÂl@cÊFh @€ @ HИŠÍ6û‚ÆÔ&0vO@žf—SÀC•õ  1y=2И¼'ÏÓ©“gë4¦&ñ@cÊÖ`¥5]'€ÆÔu¤œ0И²Z@€ @(4¦"E³Í¾ 1µ ŒÝS §ÙåðPe}hL^ 4&¯ÃßIçót£Acê$Â@ И²ZÑuhL]GÊ !@€ @Þ@còx 1yüÜt=O³Ë¹Zü†¢1?ÆMzˆÆäuø;é|žn4hLD8Ícæl“fõ®»ÿ`ÿÁ?Ìpib €ÆTN™hLYˆm€ @€ ‹S±âÙVoИÚÂÅΩÈÓìr*€¨´4&¯Ç“×áï¤óyºÑ 1uáÔŽ³t̨é£R«>Û~ëáÙn ­ƒ@ Иb€Ê)³@) Q  € @€ b@c*V<Ûê S[¸Ø9yš]N•Ö#€Æäõ¸@cò:üt>O74¦N"œÎ1ÊÃ4â‘#'TÎ!ùL=ý=£ç¶mkÐä“-‘öÔG*é44ZÕYiLB!â0~ÕxmÛ¯Ö½czS;kŸ4šIè64¦nå|!€Æ”‘@Ð @€ @€@ 1(˜ív©]bìŸ<<Í.'O‡@còzh 1yþN:Ÿ§ S'Nç9Ãîfþ6¤4™¯ãò3é;}}zS’œäëhŸtÚšx­ê¬/u_@Ô}‰Jr¹´a  C¡wÌÓËó%%*ŒS P9e 1e! ´€ @€ P,hLÅŠg[½Acj ;§B O³Ë©¢ÒzИ¼hL^‡¿“ÎgýF3ÿžC³n)—sþCgü§_õþ:é3Ç$BÀÖMë?د Ë3$‡Éå²OMf²æ8'‘Ö¥Y‰8XV*ÉL. •ë¾å¦(}j­”ìåU¶ª4cCݱ@cŠ/'OSzì©€ @€ PThLEl ýBcj»¤L ë³Ë)ã¡úúИ¼hL^‡¿“ÎgýFó“ÒÌwÝ"«‰WV X!µNi„œŽã¤%ûT“d&er%«½ér»,•Nª i^FÉ%£²Oõ«e±²âãërS8’$€Æ”$mêJS‚°© € @€ à 4&O]¯›hL?7]Ïúìrn@úÕP4&¿âé-“×áï¤óY¿Ñl_ÕPczê²N:Ì1‰°”BªJ?‚c˜ô’ؤŒD2x\ "y<þ$r܆ÃeÉ« ‘Ë\¥mKgÅ ù&€Æ”ïøÑú†И€ @€ t›S·‰æè|hL9 –·MÍúì²·ÉvÇј²Ÿ˜[‡Æ3àâ>7šº ™HÅ”í±(/G9„$ß„—“ £÷%0é#yKê6Li ï–ížu¡uâ µËR.Ùéô«¶MfrY¬ —!êB­œ©@cJ=4 hLñp嬀 @€ Ÿ  1y}4&ƒŸ›®ç`v97,=j(“GÁ®í*“×áï¤ó9¸ÑÔMÈD*¦N¢è1¶nšVŽsµ*ÕÞÔÏð›zÇöôç¥îpŽ%ÇÁÁ1\aVþ ¢§Å$€ÆT̸ҫChL @€ @€ºM©ÛDst>4¦ËÛ¦æ`vÙÛØd¸ãhLNüMCcŠŸqÁjÈÇ&’‰TL…tð“Qö²hL^†NC€ @€b%€Æ+ÞlŸ)Ûñ¡u|Ì.«Œ@cÊX@’mS²¼ P[>n4‘„L¤b*ÀÈ£ €€oИ|‹¸7ýEcò&Ôt€ @€ 4¦ÄPg¯"4¦ìÅ„E äcv™¸eŒSÆ’lsИ’å]€Úrs£q ™HÅ”ça÷ú¿oÝñúœ<÷ ƶïþýâ}oôÆX§†@ºИÒåOí±@cŠ -'† @€ xKÉÛÐ:„ÆäqðsÓõÜÌ.熨 Ecò"Ì:‰Æäuø;é|nn4.!©˜:‰sVޱ;TVZ“±vLXó^}3Ö(šî@cêKΔ)ÜÕ2@€ @(4¦B„±³N 1uÆ£’$›Ùå$¡P×`И#TèÏј Þ8:—§2‘Š)ŽAà9јšÀFcJp$RUИҠN @cJ2U@€ @€<#€ÆäYÀÃÝEcò8ø¹ézžf—sµø Ec*~Œ›ôÉëðwÒùÝhz§=6ö‚;é$Çd†ÀÓ/ž÷Õ ™ð­Ëï|÷/'™™XÑt›S·‰r¾Œà®–‘@Ð @€ @€@ 1(˜ív©]bìŸ<Í.'‡@còzl 1yþN:Ÿ—Mooï‘GóåO;vl'ýä˜ غu«‚xò©g\}õÕhN¶š0eÊ”O}ö‹â£¡ž­–Ñt‹S·HržŒ@cÊX@h @€ @ И ÄN»€ÆÔ)9ŽKŽ@^f—“#BM-@cjRqwAc*nlcêY.n4%‡iØ +¶ônzõK˜L1 …˜O[r˜†=?·WA<ý—`2…yËaúôg]²®þò-ÂdŠy(rúÔ 1¥†žŠã%€Æ/_Î@€ @ð‘“Q/÷Éãàç¦ë¹˜]Î MoŠÆäM¨ëuÉëðwÒùìßhä0}ø¨a z·®Üüª ˜å/íÃdê$Ò©#‡éÃG›2o¥ âiç`2•CbÓÒu;5¼WlzunÏËú9™R¯T4¦˜ÀrÚ´  1¥ê‡ @€ SñbÚrИZFÅŽ©Èþìrjh¨¸14&¯G“×áï¤ó¿ÑÓÑÃön]µy¿IÒ˜zúö7âë¬.×I¼Ó8Ʀ©óV*ˆÒ˜\¿ÎÅäd ¦Ï»lýÎU%KoÅKû–÷훳l3&SC•:c&€Æ3`NŸ4¦´ÈS/ @€ @ ¸ИŠÛA{†Æ4("vH@Æg—SçCê@còz` 1yþN:Ÿå9L‹Vn]õr ¿8É£§oïÒ{1™:‰wâǘÃ4mþÊÕ/ï›:ÄïíµÉ$‡é3r˜6쌌ðe÷ÎZºùƒädJ|¸Ra¼ИâåËÙS#€Æ”z*† @€ –SaC;xÇИgÄiÈòìrÚl¨¿!4&¯“×áï¤ó™½ÑT¦WVoÙï$KÅ$Éc醽K6ì9vÄ×ïºçÞv»=f̘ѥWOéå·7ÝK»é#ý9ínsæÌiå̓êTýýý¶³6Úmyîö/;L/¬ ÑAÜQ&ÓåWü°Ý®¹ ~8ˆ:O__ŸÖFø´ãÇ×›V½Ü\ìt*½o»ég»Mjws˜z6ì ¯Š¨á3—lúà‡Y²ly»gv= põ×:h/më•:„v»Æþù&€Æ”ïøÑú†И€ @€ t›S·‰æè|hL9 –·MÍìì²·ÉEÇјr¦¸‰ÆÙž7›7s˜¯zeÍ–ýY|*+Ê•5¦õ{¯Ûsì m›LÆ 1b„©ÚÖË¢{øá‡5*¢1éÍHìkws“ûÈìýÖ›¤1I]Ò›RdôÒFij)Ø sS%ˆU+ʹ ¾¸~ÏȳFµk2…ƒ¨hº *‚ÚvÁ9r¤QÕ›ÚÖûÚAä‹‘ýjû+ŽúU»ÉþÑOwlq1‡iùÆ]‚S•Š)õö‘™ñ¢L¦µk2…‡¨uÜ„<ërºâË93M)Óá¡q@cêœGB€ @€ PŸ“Ç#Éãàç¦ëÙœ]Î >_ŠÆäkäKýFcò:üt>ƒ7šÃt 6‹-F¦,>’<¤1-Z»û‹Ç·g2E|³[ÄNòG$¯½ÁZw7Û'ü‘9R‘c-Ó½iI'1ËÃ1r˜>¢µä^XµfKý ÊÔ ñ»g¶g2E‚¨_;yHæúUÌõQø}¹J.'“> ‡XF”£[ún;LáTL‘Цɇ’ç¬#u5&ëQ*º“óä‰Sž¢E[Û €ÆÔ,v… @€ @ %hL-a*æNhLÅŒk±z•ÁÙåb.foИŠ×{…ÆÔ"(v«ÈÚF“ô—W½²vëf©˜ÊÓî…kw/X³ë Ç­õÕå">‡s_ИÂãNÆL+—¥2ÒÍašþªPƒTL½‘|ZÕAüN;&S]Éi®×"lf’¥\ªM1xܵFT·H†¦Á+¼f¢Yzë‚>uQ_[&Ó5¦ t &çÉ4¦œŒæ¶J©URì@€ @€@«ИZ%UÀýИ ÔÂu)k³Ë…\Ì¡13®-ö ©EPìV!©M‡éå²þb‰jjS1™ÆôÂê6L¦ˆãRõHþ¿\ЦÈ`©»›íÉÆtØa‡…wŸÇ-õU¼‘Xv˜„¦š †—T>-ÄïœqQ‹«Ë  ØÚš€ne@mLž<9ŒÔW«ÈIr²p„W‹««1é$Mrn %dÎaª+xÕákv/X½ëù…}GÙêêr2Ê>¥6·žÉ:„¡äØ|@cÊwüh}ChL @€ @€ºM©ÛDst>4¦ËÛ¦fjvÙÛ(ä®ãhL¹ Y7ŒÆÔMš^œ+;7šA¦p¢šê,>r˜æ¯Ú5oÕÎϹ¥œL©gcRŠ °IS¤qV'“s˜¤b 4¦’©3uÄS[3™DÙ9’ôr9–êfcŠ,3g>“ã_Wc²%꺗:STðÚç/[QÎ ^óWí|î…VM&iL¶”ž^ê¯uDY©Â‹†×4LBשrÂ<@cÊS´hkИڀŮ€ @€ ´D©%LÅÜ ©˜q-V¯²3»\,®ï SÁܼ{hL^‡¿“ÎgäF#‡éÃG[^K®®þ²qô'œÅG’ÇÜ•;çôö·b2E4&ç¾$¶¨œ,Ó«“heû9L â4·–Ü–ý«*A´åäÂÙ†–„M³|Z ⼕;çöîüöéƒçdŠÑÀÈ݉HK¶rߘ1c"˜Ünu ž°îÓ-äƒ8LÎÒ‹Œp ^8áÏÌߨJN¦º#Y²´Löa±íÄ t &çÉ+4¦¼FŽvB‰!@€ @€@·  1u›hŽÎ‡Æ”£`yÛÔŒÌ.{Ë?§GcÊiàºÓl4¦îpôè,Y¸Ñ8‡iÍ–k¶ì_ýr•þâ–“kœ¨&ÈâcÓìýÿü¥¯ÞuϽMB(…Å2Óè%™Ã-’?äyØû.WÞ¬}§v7«.²¨\äX§.RcŠ:L¥ ®ÚüêÊͯÊajÄH*&ÄovaóÕåêjL ªàŠ°ÔœHpõ«Þ4ÕÉ­=—ŒÁã¦Ú¾¢’¤ÊL\ºaoCÁ«4Ÿž·ñ?ôÑ%Ë–7áu5&¥e²©.kkÛ%jJ‚GWUºÚˆc£ ј”3ðàÁƒ®ïúU×b—H° Lè @€ @C#€Æ44~¹>)×áó¤ñY˜]öu‘º‰ÆT¤h¶Ý4¦¶‘ù~@L7š}o¬j‘lÈaÚÿðìÍ?·lɆ½æ¾¨<÷âotßÒž¾Êb[öŒ›Ú·x])ÓšÝÏ-þ͵÷/¿ç¹ –Ågvoÿ¬ý3—ïø\S“IIhœ™$©Åµ3¬+9)ò¦v®»›D¹™J™4‘=ó§1ýng‹AtS`¡•D´kÆ-›ÛÛoA”ÃôÓ‡z¬Ù]Ñ6ì¹ãéuå ® ² ýì‘•7=²Ò‚(SÇ‚øÍ¦&“‚Ø(£•b*MGÒR8¸êˆådÒGá¯ÚÜK-ecjNÈa*ÃQOozxåÕc—=8s³KRep&/xEŸj99áOÎßrù=/>>wKYð*Á™4wCs“)<Ô·¤Ìás“vèB‹ãƒÝ `И ¹%àäWëî#º§¸ i3I;…W*uWá°Q›[,4€ @€ Ø 1ņ6û'FcÊ~ŒhaL³Ë€-64¦bÇwÞ¡1yþN:Óf\ïŸ_õW/¿úHó6™Ã´håVç¾ ?² §¿œqóüáçM Òb[§ý|Þ•¿^²hÝî…kwßûüÆ/]þüew¿8ògspë –ŠiÖò2`fôlÿÜqƒädê–oÇŒ;õÐχê›Ó¼ße‡iþJ b) ÓþáçOúæõ3]¦ã¯œòØÜ—-ˆ£Ç¯øòÏ[/ñÜ[œ{ë Ç]þ\$ˆßüþ 9™Ò ˆþ/R|ömmÞ9LŸþܱ=v:8c&®œQw,úÑØegÜ2_d”‡É¦i˶‰Ìó6Û‚‰˜NúÉŒËî^,2¿|rƒ3£gÇSsÖ¿°œLi¡nÔ%€ÆÄÀÈ'IKÊ`çÚ.Ô–£uiíjL²Ÿ¤+…Sä¹)SD¶Í'Z @€ @€@<Иâáš‹³¢1å"Lž72¦ÙeÏ©¾ûhL…q³¢1yþN:ÓF“´TšÈLæ0-”ÃTq_®·ìÌ[æŸpÕ[ikyß>IŸ:gËO'ô–^Γ³Ö¿ÿƒƒ¬.—*†@]hL ŒP?3‘¬íRš¤1Ù¶$%Kï×Pc²•ã\6&-áiI˜ä@á0åp0Ðd@€ @€@‚И„µªÐ˜²ÚSK ¦ÙeP›S±ã;HïИ¼'éFã4¦F2Sà05lAïVKÞcî‹–ÙR‘º4kÅãg¼tám %vH™¿rçÔ¥Ûä0]!iMYò?ý¥ËîZ|͸žHiLS—nŸ²d&S'cÂã4¦2Sà05lʼ•á Z&-É:Ͼø[eÒ’“¤TCÒ˜³yÉú=ÌÞüð¬Mòu,ˆrÑ´& ‚(mÒ‚­á|Z.ˆ'/“&“Ó˜ÈLÃôÙc—®ßY‚ o•[ŸZXz%‡Iv—ò0)s˜ðI ^ÑB{"hLkv?4s“àüê©5‚sã„•¶Öž’W‚WÏöiÁßöÄÌu˜LCáœ04¦„S]7˜¨ä4&[.ÖV§uK”6[TN‡5¦Ã;LGšÏÔÒ ¦Ýèç€ @€ @ Иò³®µ©k(9Qlbš]Ž­½œ8И2†´Æ”ùÜÖÓ&¢1Ed&9LGuÌ‚[Ìí0ñEåGc—ª(?Í õÊðP–šÇæ¼Hë÷¼¸~Ïâu»å0©Hyau«FËÉ=0í¥ïÞ4çk?ž.ói ‹ÏÒ@òÆ„É4¤јªe&9LGÊašÛkAtq”££"IšÎ ­8yôL%Óú²4¦Ù›-ˆÒt¾tÅóD™:Z1íîg7\3vÙ'ÎX•Š)Ä,šL©Zf*9L_\²®¿v„kx[†*·–œFx‰L'ИfnœglúûoMä.D—ܹ8:ÂKÓiH#œƒ&€Æ”0pªë°Æ¤m¥RRN%m ’ÉÉÆdošÉÔ½r&@€ @€ŠE©Xñl«7hLmábçTÄ4»œJ_¨41hL‰¡ÎbEhLYŒJ¦Û4qãÑæ%Vn›ó®÷¾ïðùË·8{IKÈY~9L?¼o鳋£ä=Jásòu3•¥¦"yìÖ2dr˜´™ô—ù«I+‘y˜zû?~îIJÃTITc“•#?:|Òÿ¬¼˜é&”¡xóÆO(ˆÏÍí­ ¢­•¦-WŽ=ñ›·|<Aì½ñäÿuÄ‘KÖö×Âùå“k”l¬,0mÜ«µä´Z¢F¸9L‚#2ÊÃ$8ã§o’½d#|Ü´>Á ¯µç,=3™Þ÷ßÿ¡oÓæL_hhD‰a[aIËÌY?,3“6ZÍÆ¤5æÜ‰Ð˜r;h8 @€ @ hL‰`Îf%hLÙŒ ­ @cb!ýå'¿ÿÙáÃ×ÞÿÓ7&þä¾ ”Ö üäˆú¾—²4íÛ:vìØ/ŸxRmGEPQS&§éèW­%gA´åÒÄù«v~ýÚé7>¬˜¦ ÊÔ¹Ï4& b%Ÿ–LÛÆO=êÃYþ럼þÔuY‰ày^Îù4ï§žzê5?ýU-œ™Ëƒ%ä´œÈHÑSš±+ï]òýŸÏ+ð5ƤÒrr#GŽ´µ­1é˜#Fèr˜l#]£ € @€ d’S&Ã’L£Ð˜’áL-C!€Æ4zÞ‹Æäm胎£1yþN:¿qßX=íx}N'7>¦vQ9˜Ü2™N;ç’ÊêZå¶ä0]ußR˜d{HdQ–múËšÝZiKÓeÒ˜V휷rç¥w-Örrã¦öóËùß¹iN]ý%p˜>ÜÚ—÷HòPyãßñ<Ú‰sí¢r%ÉB&Ó—N<)D9L˜‚¥KšŽD´ëƯÐúhJÂ$‡É–K 4¦R•ŠI9‡Ä&¬0S'p˜–Õ8LýøòõÛ,ˆ¯¿ñV;}ˆmßÈ¢rÉÕ˜L7üªÎ-O¬–¥wóã«•žJ“@MYò[‘±.2ÊÃ$KOy˜äxi­=ÁÑš‰?ºoYÝî&ƒƒÉ[¼9q7 1uƒ"çH…€Ó˜T»Ö‚ÓŠrZNNʯ¤wÉÆ$]éàÁƒ®ÝúU“Ö¥K¥'T @€ @€@> 1å#N±´)¬œ´«ИºŠÓ—“¡1ùéºýDcò:üt>)"0¹VÊdúþ9ÛÒc–¹çþi/Ý?­O/–¢F əᡕ¶îynã=ÏmЧ¶ØÖ z« jý%â0a2µ=>ÂSµÀäN%“é¸_Ñò ]uï Ln­´Ÿ<°|öò~ ¢tœkÇõ¸ ÞùôzYhçübþ“ó¶N/¯ 8°œ\‡)ä0eÈdrSÀäàÈdºú†_Õ¹jŸ¦o\7ãºñË-C•á׎[.‘KÃ{no0¯»L#üú‡VÔ¼"&SÛ#œ&€Æ”0pªë[<Î^ýýýZWN9™d2Ù;ƒhLÝkg‚ @€ @ÀhLÞ„º¶£hL?7]GcÊM¨²ÔP4¦,E#ñ¶ 1%Ž<ïƪ15˜´Àd:ûâò[•ä=%÷eÏ¢ÊBrr_LÑJ[–¥Æ&-C6kEÿÌåZik‡ô[lË-'W×aÂdjo¸šÆÔ@`r§2“)İÃÖtDËÃÔ(ˆá5ë:LY1™ô‘&G&Ó®ÿU½¾»j„¯¶¾³<ÂKSi„ï(ðš$Uu&L¦öF8{'L)aàT—4¦¤HS @€ @ÀhLþ妧hL?7]GcÊM¨²ÔP4¦,E#ñ¶ 1%Ž<ïƤ1Í}edx ¹&”d2}ïì‹e½TÄ—É¥¨i`xT9Lþ²tÛ”%Aiâ0ÕšL¯Ì›üȈÃ'VÛȺoæ=âm´éÃá%äšh&S“ .ˆh:5"ÚŒ’ˆb‡©ÖdjÄy׎ÜÑ3§^·¸ëÜ;½q •}e2ýpô­!8Ó`#¼â0ÕXzM&L¦V‚Â>é@cJ‡;µÆN)vÄT@€ @ðŽ“w!è0“ÇÁÏM×јrª,5)KÑH¼-hL‰#Ï{…1iLma¹üŠŽ<ëb[B.¼ÆV9 “e©©äï‰d©©Õ_u˜äyüvÏzçk¤4I0µ ~co¿ïS;Q¼ëž{=áëA+i´ÌÑ© ¢%ÓH5TÑ:p˜Ä­;Dõ@AT(ÛéJ÷÷=éäo^5úÖ:#¼lw5á–i,,x ê0 Îö½è~78#†Hiˆ9<«И²Ú@€ @È/4¦üÆnÈ-Gc2BN;4¦Ø±4¦"Fµå>¡1µŒŠ@4&5ã’Ë®úîY£Üêc–¼Ç%aê®Ã$Ãã?Þp˜,Ók¿é“Ì4mÔ•÷ŽV“”ÂGÛÚˆ¼¯wd>ÙžŒ¢0;îúõOøú@KKvÄAó0™¦óïo½mµ+‚¨OõQÝ *ÊĽë{ˆã×¾ñÍ+¯ûed„Ï/$gªl-¹åUy˜:p˜œà•@ר­@cj•ûåŒSÎFs!@€ @9 €Æ”ƒ ÅÕD4¦¸ÈrÞî@cêK΄ÆäQ°k»ŠÆäuø;é|F4&5=0™ÎU^}¬¢w˜ÀTÎßÓÛ?«©áÑJ¦°Ã¤Jßzã i.rY$3éWmkC¿Js1ŸI;è}³$¾¼ôÜx½¿öÑ1h:^Üc“éø¯…-4—IË1¬ét–‡)ì05¢…µ6ˆŠ¬ÅÎí@Ld2]qÝ/ËjWÝ®áÔ@$¨"-hLi‘§Þ˜  1Å ˜ÓC€ @€<$€ÆäaÐ+]Fcò8ø¹é:SnB•¥†¢1e)‰·)qäy¯0;“HÊdúΣñ¥²Šœ&¥¨©,$×,KM“j [,ÚV& .ò–¤+™Ì¤}´!åEiÛ½¯THÈT;þe2}áø¯)ˆSËAl7“ÕÞ$ˆÎE Q‡(Ä ¨1É¥e2]~í/«Fxi‰=7ÂgºNŠÆ”8ùÝJ4&¿ãßaïј:WŒÃИŠÇ{‘)Iý–Ét꘸/3zvL¯1<:s˜TÓ\$*©(Í’¼ËÏd?í¥÷%»,þÅ([‰ÌŽRQB¦c•›ª“éË_« ¢­•¶"X+M¥n;s˜š1¼fœ ¢…ØÑrn%ö’ÉtÙµ¿p9Æj½r†ªeÛ§.Ý>uɶ)¥ráo>ñ«'k5½&EIªp˜‹#uB©j“hL9M„ @€ äŒSÎÖÍæ¢1u“&犇S<\ ~V4¦‚¸y÷И¼'ϚƤ>Èdúöé™Þq_ê;LªËi.NZ’™$cé½ý–¤G;¼2o²6,mRø¸ LÒžì#^µd2}þË_ qVE`ª âÒ²¦Ó±ÃÔ$ˆú¨nõ¾-¨ …[vZ”Étéo˜ÂvWÏöÀÒ“À´tSÂq¡ºØ  1ÅŽ˜ Ò!€Æ”wj… @€ ™S‘£;HßИ<~nºŽÆ”›Pe©¡hLYŠFâmAcJyÞ+Ì Æ$¤2™¾uúEJÞr_‚$LÎð°5*Cq˜T‘[PLN’¶¥(IjÑOeîÑ;ÚA¢’”½£Oõ¦Þ±mKΔ÷èÇÚ~3™Z âP¦&At.Zm; bZËÊdºäš[Â驜Ýe“áäaŠu”ròD  1%Š›Ê’#€Æ”kj‚ @€ øBÉ—H×é'“ÇÁÏM×јrª,5)KÑH¼-hL‰#Ï{…ÙÔ˜D50™N»P«Ùd¶\°ÌVÈð¢Ã”÷Øe¿ý2™þùK_-Ñò ÕqˆSö!4j¡L¦‹¯¹¥j„W'ab-¹ü—–×'€ÆÄÈ((4¦‚–nA€ @€R$€Æ”"ü´«FcJ;Ô?84¦Á±G 4&¯“×áï¤ó™Õ˜Ô™Lßüþ…æ¾DRÔ =S'°8¦}2™>÷¥¯6 ¢·“”É4êê›ëÚ]8Lí5ŽÈ<4¦Ì‡ˆvF©3n@€ @€@chL4&ƒŸ›®£1å&TYj(S–¢‘x[ИGž÷ ³¬1‰­L¦S¾¡20M­¬"וµäòµ|µ?0™Žûjm=w˜,ˆ2™.úÑÍác6ÂYK._ƒœÖ¶D©%Lì”?hLù‹-† @€ dSÖ#cûИb„Ë©»D©K ý: “_ñŽôÉëðwÒùŒkLê’L¦“¿w¹8LÄ8ÇÈdúìq_ ‡É…E&“¤¥0¦ ŒYš4¦ rÊ,@cÊBh @€ @ XИŠ϶zƒÆÔ.vN…S*Øó^)SÞ#8¤ö£1 Ÿg_cRTÂ&ÓO~1þ³Ÿ?níË{6m½QÙ¾÷ÿñö;>†3Ã}›L8L‘@…M&¦ bš64hLCãÇÑ™%€Æ”ÙÐÐ0@€ @€@n  1å6tCo8ÓÐr†¸  1ÅM¸çGc*dX[íS«¤Ø¯L “Új&S®®™L8Luƒh&S®G8„C¤ И Xº@€ @H‘SŠðÓ®)íPÿàИgÄ5И¼hL^‡¿“ÎçEcRß¾~æþÇQÿy˜: sfŽ‘Éôÿû‡÷/_¿­y2­ëíÌ49¹†|íƒï:ñÃÿ­ }¤Lcz‡LcÉ…šºI©›49W† 1e(4€ @€ PhL d'Ý@cê„Ç$K)YÞ© © ì¬hLqóø¨iLº'Þ»äÖ’Ëûh}ý·p˜êñò÷îºé„æpp˜ò>þ½n?“×á/rçјŠ]ú@€ @H‡S:Ü3Q+S&Â@#š@cb€t@©hÅ9©8±L¨'ùÒ˜&¬yï«¿û÷ºž‡²ÔüÇÛd©IhØ ±šF&“‚èg¦2ÏÒÿ™îÚÿf£ŽÃ4ÄÇá)@cJ9T4¦¸Èr^@€ @€€¿Иüý!4&ƒŸ›®£1å&TYj(S–¢‘x[ИGž÷ s§1 x­É„Ô»qXk2ùî0)„3qhÑ8ý·Ödb-¹Üp\‡â И Xº@€ @H‘SŠðÓ®)íPÿàИgÄ5И¼hL^‡¿“ÎçQcR?Ã&S'ÏÀ1a“É+‡iïúž×~ÓW½ïÞ ›L8L­4¡ИºA‘sdSƒB“ @€ @9'€Æ”ó¥ùhLC¡Ç±É@cJ†sÁjAc*X@ÛëS{¼ØûPŽ4¦}oôîþýb33™p˜r=ˆÍdòÊaš6j„Êâ_ŒŠNbÓä‘ÃÂošÉ„ÔëNã« 11 J© ¥[€ @€   1¥?íªÑ˜ÒŽõNipFìQCÉëAÆäuø;é|f5¦ƒ<8h^ûý[ÿñö;ƒîÆY& “éßßz;Ë-ìnÛqxÝ®}tL­Û$WïOï0»Ζ4¦ôØSs¬ИbÅËÉ!@€ @^@cò2ìÖi4&ƒŸ›®£1å&TYj(S–¢‘x[ИGž÷ ³©1MÞ8yää‘ygKû!! “ÞTцR4姯´5И%€ÆTÐÀÒ-@€ @€@ŠИR„ŸvÕhLiG€ú'€Æ48#ö¨!€Æäõ @cò:üt>ƒ“¼%Ó’´!WÉze˜´aI˜´®œd&}jÅiO à$EÀR.…WŽ“¨d«ÅY¦%í`&“å^Òû¶‰MI5“z 4¦x¸rÖÔ  1¥@€ @(4¦Â…´õ¡1µÎŠ=Ó"€Æ”ù\׋Ɣëð µñhLC%èÝñÔ˜”uɉS& ‰•l9“™ì#)M“7‰mxA Ë”„Éœ$½lµ8ýj®’~•¨¤÷-9“}d{ÚÂs*Jã”åÞÑ6 NipFì‘KhL¹ † @€ dšS¦ÃoãИâåËÙ»A©½;“w!wÉëðwÒù jL•LcRš%ËÀ¤—­.7~Õx½©ŸzG“„'­+§ 4¦NbÏ1€’$€Æ”$mêJS‚°© € @€ à 4&O]¯›hL?7]GcÊM¨²ÔP4¦,E#ñ¶ 1%Ž<ïfPcR¦%™LÿxÐt%{ITÒ›ú©¢ôŽ’0Yº&™Lyí‡ P|hLű§=Dcò4ðt€ @€ #4¦áfýÔhLYí;t‰QÐ4¦ ç4¦âÄ2¡ždPcJ¨çT@I@cJ’6u%H)AØT@€ @ð„“'®×M4&ƒŸ›®£1å&TYj(S–¢‘x[ИGž÷ јòAÚ_3qhѸât‡ž@ B‰!QPhL ,Ý‚ @€ ¤H)EøiWÆ”v¨phLƒ3bhL^ 4&¯ÃßIçј:¡Æ1ˆƒÿgUΙhLÙ‰-é*4¦®âäd€ @€ ˆÿXìñ0@cò8ø¹é:SnB•¥†¢1e)‰·)qäy¯0G÷ļ6Ú?þÏ”!RlhLÅŽ¯Ç½Ccò8øt€ @€ þ±8&°y8-S¢ä{™²õ}tÔ4¦Ž°å 4¦¢D2±~ 1%†šŠ 0þÏ”!RlhLÅŽ¯Ç½Ccò8øt€ @€ þ±8&°y8-S¢ä{ј|õ©#lE9©(‘L¬hL‰¡¦" B€ÿ3eˆ›S±ãëqïИ<>]‡ @€ ÄD€,Ž lN‹Æ”‡(ùÞF4&ßG@GýGcê[QBc*J$ëSb¨©ƒàÿL"Å&€ÆTìøzÜ;4&ƒO×!@€ @1à‹c›‡Ó¢1å!J¾·É÷ÐQÿј:ÂV”ƒÐ˜ŠÉÄúÆ”j*‚À ø?S†H±  1;¾÷ÉãàÓu@€ @€@LøÇâ˜Àæá´hLyˆ’ïmDcò}tÔ4¦Ž°å 4¦¢D2±~ 1%†šŠ 0þÏ”!RlhLÅŽ¯Ç½Ccò8øt€ @€ þ±8&°y8-S¢ä{ј|õ©#lE9©(‘L¬hL‰8l–ÿôIDAT¡¦" B€ÿ3eˆ›S±ãëqïИ<>]‡ @€ ÄD€,Ž lN‹Æ”‡(ùÞF4&ßG@GýGcê[QBc*J$ëSb¨©ƒàÿL"Å&€ÆTìøzÜ;4&ƒO×!@€ @1à‹c›‡Ó¢1å!J¾·É÷ÐQÿј:ÂV”ƒÐ˜ŠÉÄúÆ”j*‚À ø?S†H±  1;¾÷ÉãàÓu@€ @€@LøÇâ˜Àæá´hLyˆ’ïmDcò}tÔ4¦Ž°å 4¦¢D2±~ 1%†šŠ 0þÏ”!RlhLÅŽ¯Ç½Ccò8øt€ @€ þ±8&°y8-S¢ä{ј|õ©#ly>hí”C²—¬üÛ'išðÑóÞùÝÎ<÷¶ÇN _Ó¯WüÙo1¤cTþÏ4îÔš4¦¤HSOÂИNu€ @€ ðŹQј<~nºŽÆ”›Pe©¡hLYŠF"mùmo .Õ-?9"‘PIŽ äHcêÝyƒÞv¼>'Ǹi:šÐeüž¯C…%€ÆTØÐúÞ14&ßGý‡ @€ tŸS÷™ææŒhL¹ •Ç Ecò8øw©svù=òöêkL½óÛ'Zž iL9jj2±£–¢@ò(ZDéO5F8#¢ И Xº@€ @H‘SŠðÓ®)íPÿàИgÄ5И|u2‘ŠÉÇ¡ÐvŸsä娩m‡ H ƒb`„;¾÷ÉãàÓu@€ @€@LИb›‡Ó¢1å!J¾·É÷ÐQÿј:–ÿƒj2‘Š)ÿQM 9rƒrÔÔG$€äQÀ Ò¥F8á И Xº@€ @H‘SŠðÓ®)íPÿàИgÄ5И<‘„L¤bòt´Ýí¹A9jjÛaàˆ’àØáÅŽ¯Ç½Ccò8øt€ @€ 4¦˜Àæá´hLyˆ’ïmDcò}tÔ4¦Ž°â pB&R1"¤ t"GnPŽšš@ਢ€< Tº"Àg8”SAK· @€ @)@cJ~ÚU£1¥êœÓàŒØ£†“¿ƒÂ%d"“¿ƒ ížçÈ ÊQSÛ@@<Å&À/v|=î“ÇÁ§ë€ @€ ˜ 1Å6§EcÊC”|o#“ï# £þ£1u„­(YB&R1%ž ô#GnPŽšš@ਢ€< Tº"Àg8”SAK· @€ @)@cJ~ÚU£1¥êœÓàŒØ£†“׃B ™HÅäõh»ó9rƒrÔÔ¶ÃÀ$†A± 0‹_{‡Æäqðé: @€ @ &hL1ÍÃiјò%ßÛˆÆäûè¨ÿhLa+ÈAS¦L9úÈ8p  ý¡ñÈ‘”£¦Æ7j("$"F•> `„3 J© ¥[€ @€   1¥?íªÑ˜ÒŽõNipFìQCÉÛA!‡éSŸýâO>|8&“·Ã ÝŽçÈ ÊQSÛûC €äÁ8(6Fx±ãëqïИ<>]‡ @€ ÄD)&°y8-S¢ä{ј|õ©#l¹?HÓ§?{ì’uý½›^}xò\L¦ÜG4©äÈ ÊQS“Šõ‹’G±âIo¢ጉ‚@c*h`é @€ @ EhL)ÂO»j4¦´#@ýƒ@cœ{Ô@còpPÓçŽ]º~çÊͯJcZþÒ¾ “0™<t9GnPŽšÚI$8HŒb`„;¾÷ÉãàÓu@€ @€@LИb›‡Ó¢1å!J¾·É÷ÐQÿј:–ãƒÌaZ¶~çªÍû¥1­(iL=}ûš8‡œL9ŽkRMÏ‘”£¦&=ê)$bÅ“ÞD 0Â%€ÆTÐÀÒ-@€ @€@ŠИR„ŸvÕhLiG€ú'€Æ48#ö¨!€ÆäÕ Ãô™ÏÛ³açê—‡I©˜V¼´oyŸ4¦½K7î?qö'‡uÿ~¯˜ÐÙ¶äÈ ÊQSÛ ;C LɃ¡PlŒðbÇ×ãÞ¡1y|º@€ @ˆ‰SL`ópZ4¦:ê?SGØryPÅaÚµzËþU!I©˜–m 4¦%ö<ðÔìó‰M¦žžž#F´ËbòäÉ‘CF}øá‡Ï™3ǽ?f̽ÓüÌ®vµAÛÚyذa:JgÓ«ù±îVïv¶vŽ9Ò•‘–«…j˜^ÚèëëSóÚê`ÂøñãER/¤¿¿?òiŽÜ 5µ•qÈ>ˆ@ò`L›#¼Øñõ¸whLŸ®C€ @€b"€ÆØ<œ)Qò½hL¾€ŽúÆÔ¶üdÓò»ÖlÙ¯TL«,SeE¹@cÚ°wÉú=‹×í¹ÿÉY-šL’‡$»´Ë¢Ö|’ ¤ó„õ ’šŸÙÕnâŽûõ`éÕüXßÌ'{É ªõuܧnçÈQÚ!õ–« â6jÔ(k­HÚ0&¼ÄAä  d²Ú`åÈ ÊQS;ˆ‡@à’ƒ ØáÅŽ¯Ç½Ccò8øt€ @€ 4¦˜Àæá´hLyˆ’ïmDcò}tÔ4¦Ž°åì ¨ÃToE9¥bz±¤1-Z»{Üã-™Lu5&™=r_ôrn<{Gn<K&¨C´³ó–dÒXz!ÛÇn¦‘}jç7eG;èÌf>i[ò^z_oFZb^Ž^µ“½¯æÕ†ÖvÖ™u~m‡ ¡˜Z®„U‘ö4j¹Z«=­¿ö²mc¢—Zh]8ÜÉ--V-%×AÙ]µšZŽÜ 55gš›H ͈‰#<&°œ6mhLiG€ú!@€ @Å#€ÆT¼˜¶Ü#4¦–Q±cjИRCŸçŠÑ˜ò½–Ú[h9¹†©˜ÊÓî…kw/X³ë¾Çfš“©Vc’øâ%³dÕ˜@£,ßRÝlL&?Ùºr:Äl'ÛÙÔ"—gȽ£³™dc¹Æ¸EåtK¹¤èeRŽò éM÷Q˜ ô;gdMºæÙ˜ºÞr×Në¾d£æ-7…K/ë£õÈ1±žª×¶áN¥w´å^ Sr@ì´µ+æÈ ÊQS[ú&³"<Å&À/v|=î“ÇÁ§ë€ @€ ˜ 1Å6§EcÊC”|o#“ï# £þ£1u„-7…¦ÊrrûWÚŠr/í[Þ·¯§oïÒ{é˜Lczaõ®{3™êfc2OH*’ù1ò`´!ÃÆ-âf“íf†‰G•œçdÚv /-g™ÂI›šhLæ*Ù™-Õ“Ó›tZU^TÎ…Ód©ðòvú(¢1© Ör}GËÍ‹²3kC©my¸ ÖxµÇV¸«ËD;X§²£"” §nnª¹A9jjn.(44S<2ÓuŒð®#å„Ù €Æ”8Ð @€ @€@‘ 1)šmö©M`ìž4¦ ç¿J4¦üǰaê8Láåä^’ôoÙÆ½K78©œŠIÓüU»æ­ÚùëG›ådª›É¤%óÌõ±¥Íœac“<'{Gέ1QÉ,"G¹‚‹šÙ Ãb“ªn6¦° cç<ÚkLªÈ–¨ÓO[º.üŠhL–±ÉšGËÓ¶Ã|Ô*ky¤ µ­0q6јÂ©ŠÚ¤YVKŽÜ 5µÀW!º#$árê `„g 4!hLqP圀 @€ ¿  1y4&ƒŸ›®£1å&TYj(S–¢ÑͶ4s˜6½ºÜ9L R1Í_µsîÊszûï~dF£Õåj5&K}dݰlLzÇ-LæÖ‰S²¥pW@#;Ç--ç²1™odËŸiÃIE:m“lLaÊÖ³sÙžÂ'±f裺™‡ìÓˆÆwËÃík›Kåãš!bRìW·T\#)|*CíD1·ê_óQ˜#7(GMíæ7ŸsùCÉßXûÙSF¸Ÿq÷ ×hL™.B€ @€&€Æ”0ð,U‡Æ”¥hЖúИ@cêZöqS°œÊËûW¹z šQŠ01,aÚÙÔ¨ZJ™lLÙÿšÓBß yø>ŠÞFxÑ#ìmÿјÜJÌzÂs²öüê-2:@€ @€À И<"hL?7]GcÊM¨²ÔP4¦,E£;m1‡©gîÀa* L_ØúÍëgönzuEÃtòu3JÓžëXþ¥+žÊå*ÏüÙܹ½;g÷öÏZÑ?sùŽ;˜LÝiqœg‰d~гª”Ï6ÃÚmJë”r”â(GMm7^ì€’ã ØáÅŽo¡{çŒ#·†²ùHf7Ó˜ä0vØaε7Oß~—{³Ðèè @€ @@cê[1Bc*F‹Ý 4¦bÇ7¦Þ¡1Å6­ÓÊaútà0ítI˜Vm~õ©¶žpÕ”ˆÃ4}Ùv9LŸ'ûß4¦ìLj‰’Çðqpæ 0Â3"؈@DcRŠ&­çvnOc’Ã$“ Ö€ @€ @ 4&Ç“ÇÁÏM×_øÍ¨´Kà×+þìoÈÍ@§¡õ}ôÑ<>Í¥_’½dÓò Ó¾Çç½|ü•Ï/­ÎÃ$‡Iy˜¤1Y¦ù«vÍ[µóçNš´`kt9¹ SÙa2“éØ¿ù/þïìùOí6ö/onÈþ)û1¢…C"€ä1$|œyŒð̇ˆ6"јôkxQ¸ö4¦Úêà@€ @€¢И<hLŸ®€¾Â¬ýoEè }€@=>|ø„Ésu©b/¹Uä›hLZHnÉúòZr‹J“ò0}â¼IÎaztέ(^NnFi9¹iK·O-ÙKVNþÞ?¸ðòMÛ_ß¾÷zçl@cÊf\hU× yt %'Ê$Fx&ÃB£Z!VúúúÂ+ÊéðA4&¥_êééqÕ 1µBœ} @€ @¾@còx 1y|º^hLEˆ"}hJ l2Mšëì¥` ¹R¦GçlVÖ%W¾ñ“ K“ò0)ý’åaš»rçÓ^úúµÓg¯èŸµ¼þrra‡I&C2ËИ²ÚÖH]€È)2L€žáàдæÂê‘”$‰Iáýј€ @€ @€Ú&€ÆÔ6²â€ÆTœXÒ/  1yvï:m&ÓCçöRe 9ËÀ¤²xJ) ÓÚ@` ¯%'‡inïÎr¦!‡©z99—‡É&L&ïFX®:ŒÆ”«pÑØö y´ÏŒ#òD€ž§hÑÖ6 1µ‹]!@€ @h‰SK˜Š¹S1ãJ¯¼!€ÆäM¨}神Lã'ÎvKÈE&K´`õ®ÒZr;-Sc‡i{íZra‡ “É÷—áþ£1e884­<ºA‘sd—#<»±¡eC"€Æ4$| @€ @€@hL 4&ƒO׋@©Q¤­ÉôÉáÃxjv)ýÒ@¦ª$Læ0I`Z$aŠæaêÙ>-Èô}ê’m¦1ÕÍÃÔ$'SÿÁþa÷ k­½ìX 1Å‚•“f‡’GvbAKâ Àƒ*çÌ4¦ &@€ @€ F©`m§;hLíÐb_dŽSæBBƒâ$ðêþý=æ÷?9Ë– L. S‡iú²íÓÚq˜ä3mßû‡?½óŽëÓøUãG<2âàöíëÓ›=ý=î§í£lCÙ§¼ Ð]hLÝåÉÙ2GÉ#s!¡A]%Àï*NN–hLÙ‰- @€ …SQ"ÙA?И:€Æ!È4¦ìÄ‚–$CÀL¦qÏ –[,!W˜’0Y¦Ù½ý³VôÏZ¾cæò3zvLïÙ^v˜–¶š‡©Öa’¢$‡iää‘s¶ÎQN&Ûçg=´Š '}ª }:jú¨d°P‹?Иü‰µ§=Eòð4ðÞt›îM¨}ë(“o§¿€ @€ ø  1ÅÏ8³5 1e644 ­@cj…ûŒ€™L÷=6s@`ª³\ÈaR&ËÃ4‡ÉÊO²K‡ßz¸KÅ$ŸÉ>Õ†ÞÔOyNnÿ‚Á§;©@cJ=4 ^Hñòåìi`„§ê‰SL`9- @€ @ÀchLÉãàÓõ"@c*BéCûÌdº÷±™óVíTú%ËÀdI˜f+ ÓŠr¦ SÉaš:´µä\e/iÛ\%{Ó20Ù¶>Ur&ýÔ§Vl^è"4¦.ÂäTY$€ä‘ŨЦî`„w%gÊ4¦L…ƒÆ@€ @€ A©aì¬hLqã(d„SFA3’'`&Ó¯Y-0 $aša ÉuÏa²ÕâÔÓ°ºäò3)“¤%·v“Ò4yãääÉPc±  1;¾ôî’ƒ ØáÅŽ¯Ç½Ccò8øt€ @€ 4¦˜Àæá´hLyˆm„@ChL Ÿ ˜Ét÷#3J˜ÂS„)p˜B ÉMY²íäï]ðƒ /ß´ýõ&eûÞ?üéwêRU&IKÿxг}ôÎøUãå0œ¥V’®¤ã$*ÉI²bY—,'“6¤7i[ïKuÒþúÔí‰ÆÔ>rŽÈ 4¦¬D‚vÄDÉ#&°œ6#á Íè64¦nå|€ @€  1y<И<>]/4¦"D‘>´O@KÅÉLÒq.å’Ô%ËÏd2“e`² ½ïVšÓ;Ò›$6µ_'G@ И2$øØræ,`„g! ´!hL1@唀 @€ Ï  1y<И<>]/4¦"D‘>´O@f’©H’–¤%YN&[TÎd&åjRѯ˜ô‘$'ÛSò“K×Ô~µô  1¥Z+$XñròÔ 0ÂS ˆ‡S<\9+ @€ @ÀghLGÉãàÓõ"@c*BéCûVÜ;Ú’̤m¹JÚÐÏ=sTì#ýjÙ¯z_¿ªØ’s¼ ShL9 Ín•’G«¤Ø/ŸáùŒ­”Ó ˆØ€ @€ 6  1µ ¬H»£1)šôÅChL.C>@cò9ú^ôÉË0{ÜIF¸ÇÁ/v×јŠ_z@€ @HƒSÔ3R'SFA3 Ð4¦Î¸q œ@cÊiàhv«FÝ‹>£1yf: @€ @H”S¢¸³US¶âAk Ð&4¦6±»Иüˆ³Ÿ½Dcò3îõÉã`{ÙUF¸—a÷¡ÓhL>D™>B€ @€’%€Æ”,ïLՆƔ©pдK©]bìï4&/Âìi'ј< ¼?ÝFòð'Ö~ö”îgÜ=è5“A¦‹€ @€ „  1% ÷Éçè{Ñw$/Âìq'á¿Ø]Gc*v|é @€ @ hLiPÏHhL Í€@gИ:ãÆQ'€ÆTð{Ý=4&¯ÃïCç‘<|ˆ²Ï}d„ûýB÷©Ðá¥s€ @€ T 1¥‚=•¢1e#´@cꇛS±ãëwïИüŽ¿½Gòð È^w‘îuø‹Üy4¦"G—¾A€ @€Ò!€Æ”÷LÔŠÆ”‰0ÐtJ©SrWhhL…¯çCcò|¿ûHűß=d„ûÿ÷©ÀÁ¥k€ @€ ” 1¥> Õ¢1e! ´@cê™S‘£ë{ßИ|…ï?’GáCìyកâv©¸±¥g€ @€ ´ 1¥E>zßþÓ›ãWý¥Ô‡ºeѶóÓhuB­øã¸{ùjô~rÃZ=ûA `fÞrHSƒuËÙvèw; Ö]ºã-4&oC_ØŽ¿õæ¡QÙðþ(ÿoRØÈ{Ú14&O_ün£1?Æô€ @€ 44¦¤‰§\ßê]·Ôu ~½âÏÞx‹‰Þ”£Cõ”À´M'4Ò˜ö½±jÐÃÙÅ$Ðd"œYðb†ÜÓ^¡1yøbw»‘‡Š„Zì¸ûÙ;4&?ãîA¯Ñ˜<2]„ @€ $L)aàiW×(!©˜ÒŽ õC %2‘Š©%|ìT`u'™/pĽì“—a/z§y¨H¨E¼ýCcò1ê^ôÉ‹0ÓI@€ @€@¢ИʼnÊj2‘Š)¡h@Ý„L¤bj {—@݉pfÁ‹p?{†ÆägÜ‹ßëZ µøQ÷²‡hL^†Ý‡N£1ùeú@€ @H–S²¼³P[mB&R1e!.´-¨MÈD*¦ѱ[Á D&™/x¼}ì“Q÷¡Ïµ*ªq÷°hLÝ.£1ùgz @€ @H’S’´3SW8!©˜2V D2‘Š©UpìWl‘‰pfÁ‹n/{‡ÆäeØýètïÄC2<¬ ¡ús{‰ÆäcÔ½è3“a¦“€ @€ D  1%Š;+•…2‘Š)+Q¡h™@8!©˜ZÆÆŽp ™˜÷ ÚvÉà{ÔåŸQÖ˜P=Šºg]Ecò,àþtÉŸXÓS@€ @€@RИ’"µz,!©˜²Ú ¸„L¤bj‘»yAÀ%dbÜ‹x{×I4&ïBîU‡-!ªWA÷­³hL¾EÜ›þ¢1yj: @€ @HŒSb¨3V‘%d"SÆÂBs Ð*KÈD*¦Vy±Ÿ?”‰YpÂíYOј< ¸ÝUB&$TÿÂîQј< ¶_]Ecò+Þô€ @€ 4¦”ß|óÍn¸áꦯoûÛÍwÈø§7Þw쯿(ãlÒ¼K/½ôôÓOoÞþ‰'&ñ=¢¤Aà®g?ÿrÿ‚4j¦N èrÚüz{^é•ú=å'?ºrÆEŸI½j@+ [·nõq0ÑçN ø 1éK1è÷÷k_ûÚ ûø³ƒ.¼ƒ>;¶ÓA—èqsÆÞxà·}‰VIeH’S’´©+AhL ¦*@€ @€€'ИzΜ9ï~Ïß^tÉ•V.tåâ+/ Ê*ÿùÿþ¿Gžvö_1PF]q~½rÞE—Gʹ]^.^~n¥üàÂË+å²\”sjÊÙç_VS.=ëüR9o œyÞ¥åÜKÏ<÷Ò3Ê%gœ[.§ÿà’H9í—åW.þþ9¡röÅß?ûâïÕ”‘g]\*£Âå»g Ê™å;gŽ(gŒúÎZ[N¿èÛ5å[§_ô­Ó. —ožvádžÿóýïÿ o~?(§T• Nùþ#¾þ½÷¾÷½ž|•é¦oz{{<ê˜áÇ8pÀ·¾ÓßTèrúý3Ω¹!wC» ý±«\Ps¬û‹ÞøêÜò"7»È.|«ÜàêßÚÞÔêßËndá[Xó›Wø¶ܰNnXÿçÿõŸO<é{ÁMÊJôVuÁû?øQ™©D“JsJÀI_Šó‰&—={ë ¼Î¥fÔá«Mä1»ùvøjÓäRzœ®sµ©~„nöðylnø´\óyB¶ÇãcJÏÃÚht©qR>ž‡§L™rÌ'>ÃMN¯N4»%hL-ab§ü@cÊ_Ìh1 @€ @ ëИDHÓGùÄŽ½°²=(o¸²mÏ*óî¿]¼|ýo÷¼”Ý*¿ÿM¥¼²ë÷®lÝyÐÊ+ý_.—×_ÞñúæJÙ´ýu+/mÿÝKÛ‚ÒçÊo·1(¯©løM¹¬ÿÍkë_ ʺWe뵕²fë5[ö[Y­òrPVYÙüêÊJéÝôª•*/íSYn¥/(=å²wÙÆrYºqïÒ AY²aOPÖïy±R¯ÛS*»©¬-—…kw/\”kvYyau¹Ì_½kþª*ó¬¬Ü9·Ræôö»2{E¿•Y*Ëw¨Ì¬”=;.¾ú–Ï}é«Ó{¶O_”iV–nŸ”m*ã&-FcÊú%ˆöuD ä0 {aÅ–‡ŸžË„_G9¨mºœ¾¸bCén8pC´»¡Šîƒ² Tì>XÿXsï«{׋Üïìf¹Ó­ÙR¾Í…op‘»[Õ­­öŽºUßËndv ß¿J7¯àþUuçêÝi·­ÖŠà†õ—ýîŸyQw+•ª[Uå>uò÷.@cj{ ú}€'“þ` z©Ù;p©Y´|½žÀËÜ•çí­»~?ð°íž´Ý3öŽªgìòvåéÚ­#ÏÕÕ¡ÇéȳôÀƒ´{ŠvÏÏÕÏKìá¹ê±ywðØ\zf®½ÔèÙ•#ÏÉåKMøj³|ÇÅ×ÜòÏ_úª]jf„ŸŠ+—šû'çàyXÓ§?{ì’uý<Øø}‘+zïјŠaoû‡Æämèé8 @€ @ 6hLÍ4¦oÓ¬IeâÄMÖÚ|­Š&Qõ¬ ÛK¿ ÙKšÄ­˜Â“˜´1T‡é•‡Ió.ó»Q‡i¿›åÕFHc ¦°ÆÔÔa*ÏÄ4ט‚)™ÐpØa æfJÓÀn&¸®Æ4»fJØ9L3KS5e©ä0¡1ÅvàÄ™# ‡éÃG [°bkà ¾´oÂdL¦ÌŨ ’Æ´xÅúÈ=1,òZ2Bw¬² Þ†ònH,pv[ Êžn­¡[ç¾VÏÊ­õq«Ä‚ZiàæenD½5ïV7,4¦B~Òí”'“²»…ŸºÝƒ·ýÍÀžuÆÔèÚu˜*!ÐĘŒüI@Ƥ{T®oL–žƒKMɘ\cʼÖoÓÒuý<ؤ{…¡öØ  1ÅŽ˜ Ò!€Æ”wj… @€ ™SS©X¦¡:LÑTLÎaê©ü)¹2u;S?1æƒ[NÅј\*¦lLKÈÆTäK—·} ¦£‡-ìÝj&b`öí›0i9™¼‰u\“’ „½¥ˆÅkSp §E ç ¬I@É>Ø(ï`ÝTLC JÉ#™#9ëçGq©˜ByëæG)kLO[6¦n»Ô²)ÉÆ”Øè-LEþhLM.5 –Sä‘ÛÒV¶[Ñ%ƒ§ë -8L.³i©˜ú5&ÃSÝÄoÏN8LŸ;vÙú<ØæJEG@cbp”SAK· @€ @)@cj¬1ý±»Eâ6Bü­IM¥„§l#‹Ç…&T´\ÕrÑ L­-$Zó¢´\kÉ5ÊÃÔ5‡)¼¢\“TLnEž!¦b*iL76JÅ4)Å UÇC ì0­ÜªÉT7Û'ïP¢áƒ1™âÎY+¤1™¹YËÉ­wÞE—«„×uðw]AµfíÔÆy˜‚åä­—Zg¥Ôš5R«¬Ü8R1•ò£„5¦ºbÁÔ%hL|»Ú&à‰Æäuk|©y!ИÞÓh½æÅš«’s‹5—tÉ’ÃT½LsÕ+K™M:L›j³™†–cv‹WFbn¶xeýTL•ÄoUÉJK—iLZd¹‰1™eIÓgä0mØÉƒMÛ—È#4¦i[GéÍpíWÍ{…Ï£=¤I5}äfÅt†Ã;¬¶%Vï¨Q£T«±S–×!iL2wîƒvC,Ý í>xîE—«´—z°¡ÀT¹ß5° \r”fÓ`y˜–T¥bªŸ¥±Ày·ñ×ï~ðé¥bj¤1ýÇÛhLQóDc „ÈðSwõ¥fÞ’@cjr© ?i÷é»ú»y&÷\Ý<å[°¨kó$«ÛæºZט4§¥kf»“±ünv°î" ÈÖ7D“ì&æ®ÖGsK¤Õñ š' g ßï*é#wºÚ•RëeFÙ×SJ+d ßÔ*Sw¦ð*¨nýÓÒʧҘƗ4¦ºbSZ#9×õú¢1U„ÈÈǹõìí– nz©©o/ $7máRãþ$À¦AuI—Ç4òülºdÕZrͦæËÉU/µ\Ö˜JÏÆ&÷—ŸŠ³ªõ‡¦î?ؘg£Spô¤!Çå†t ޽cb´%†´¬Eæ?éW=ŸØy&OžìTÌ®Öûa»Ú.).‘¤êuж=äØi%WYKLZ²ýÍ1ŠœSGé}× KHiz–Içö‘9èÚÕd‡hÃÞ´Ú;nÃ:>›5/r6{ÇNâºï.›µÏõ5…Æ£1¥*“ €Æ”eê€ @€ øE©A¼McªU”Ü;š8Ñ$ÊœÅkÂi–”i©*ÙRU¾¥o©‰ºÔhå¸ Es{©:ý’û“ñʤKu¦&«È Ìõ–ÿˆÜ­…ÑúBr Vï’½dÅ9Ló4%Sš•Q)§²XY^#C+eÌÏk±ŒÆkəär‘ecr³5¡O4¦j!2ú·zöÖø/5å¿ ( LåGëR²ÃV]É©tµ©½Ô è’åõ—«“0E˜Ût˜ìÙ¸¼Èr泓â0 ö`£«q+6Nñ±{>qO#î©fÐlLvÍp:TXf²Â“~ kLNZÒŒ-!çòPª=&ˆ‡5&w}²sÚ£Žt+»¹‡4Û¡‰Æä29¹*"SØ·¤˜µgs]Sk];ՆȳbQ.«Éö)YÞÔ–4¦ÄPS @€ @ÀhL BhLG««%¹75‰2sájûµì*U’L˜®TµB\½•,LZФ\Šd]ЍK«šÛK¥?ø{ñªÅãªþjca 15¼ÔÔ·$ƒ›iý´¦›µZk§®äÀBÌ{ÂÓ@¾·JÊ·Ê¥¦j!9—µ´=]²’¦Ôùý¶ÈrƳ“:‡©Ñƒe·Ò:¹C|°qRŽ=̘ m’žsLâÑ£EDcÒ¯zrêe‹4ý(,B¹g•°ßcW§©Fm»³Ù†=eÙu&m;=¨öœúH;kÓŒt;¹=­ÙsZm6&ílKÝYúÕÉ[ö‘ÄZîr>©åµg³§/ÛÙe`BcêÎå©;9Kæ ¢1éÂgKuÚËþÆý©JæzCƒ @€ @È4¦Q0ÉÙHu74‰2}ÁªÜNT åXzvö2ç*ÕJK³_Ü Rë-=õBiñÓª•O¥1ÝhL S¢1µ9Ùý?S“Kž½õ^{© ?o·°"sQòº»CeúÂuîO~ò³;TÂKÈ]{Óí*fÛDþ à±çŸqÞ*åççµ»g-Ýrá•78]òágžvîåÓ_|¹’„©áBrÎõf*­·Îò@vÒ¥Áj•µ%u­?ä0 <Øüjâš«Ç.»õ©5µrö¸©}ö`£ÿãxrÞ–Ëïyññ¹[Z|°q¶fÌÝƒŠ“~ô޶%ú؆~µ‰uKJä1ëHï¸çð¤ø¸3»«’;•ÞÑÃŒö×n–¾È¤%«ÚÞ ·Íš>§•\íj°-Âkga£(ì Ûû¦%ÙI´³m˜3`ÕÙÜ>uÏfMr¹¬¬hLݹ¡1u‡#gI€.áZuñ ÿŸZ3ÉìN÷1&oêþË:D•€ @€ dœ€çÓ£çzúêCo¨’þ­öÃG³ß"ÅM“heÚ «j-¥r‚¥­®øñÏ>xäÑö÷ßV>óÏÇ=òôì@MÐöçŽûÀ‘G[X*îåýOš}Øa‡¹ÞóÞ÷M˜80•Y3.¢.•ü+{­^dÇfyßý·ïÓÏ3Φ^4×{òwÎÒäÁ}Mÿäg¾¨)„r¾ŠHú¥ÒÂU®hÞwþª`2æ}à#árÞå×Soÿ@‹Þþ‘g_¦rçCSÿç‰L3+Ó3¶ŠÜwκTeÚ²íA LšÖ$Í…Cјöm=4îÔC Çfü Jó|#`Ó¢•[À´ª´Ì}ñ¿rÊî[jËÉé÷Éó&™Ÿ¡/é÷þmî—®xþK—??ògs]*¦@c*¥m¸c´AM&ßPÓßZ;^Ÿ3mó ûÞè­ GÓôV5º!êÆwÖy—ª„…Ý[ïžð·ïý¯ºªH]Ò¨¾þæ;ëÜø6ï¿üš›ô~d9'Ýþ¾õ½sœOpćŽ~ð©YáÛœ¾*S^XûcY¡%äÎ<ÿ ÝF¯¹ñvgå꾦;ÝÀ-äãºÙ=LÿŽÒìãŸþ‚4\9Lóž÷iû{ç\¦X•UP;5IE_1ÝÎnÿü€t[ºa™ÆÔ$e _Ãv x¢1éJ¾ÔDž´õì­'ðê¿ ('[ªM¹TÓ´~Ž7»Ãœ‘gŸ}ᕺÔL[¸N—m|säÙ*G|è(»Úhã”ïž­¢ K¿ätI]dþñƒGéAúôó®ÐÆ—Nü†ì%=K¿ÿƒG-X³KåÞG§ë’òÃëǸgæ–’0…V[.¹’Q]²²ÈòW­°<È"Ë¿í=tû ±>ËaúôçŽíÙ°Ó=ØL]²ý„«¦œqËü]vÑí ‡Ÿ7éñy/—LnØsÚÏç]ùë%öc&®ÕƒÍew/>îòçn|xeÙÏŽÿÁÆòuëνԭsrž¼@cÊkä|o·þq,|a´”½z¹Är 5&K(g –Ew¢p.8ßÓ@€ @€j x®1IdÑ?&žÿçµ2“iLk¶(— D¤ìÿkiLóW†-%·­©fÖ²÷¼÷¿j^V3(*ÏÌ\¦m½£4K’–®ÿù#¾zŠ%[úö÷ÎÑ ®Mߪ(ÿ„¦R\ ŠË®&w5¿bS¹Í׌‹¨KVŽ ç¨0©´þÅnËTQk/…Ó/5[?®¤1)wEm¦ðp)CLÿNѼ¯› L;Ü2r˜N5©´Š\Ó"”Ö¢3iïËIqWAc⪘%æ0-”ÃTJNc É•&-$÷Ò>iL?¼o©¾×w>½þËW>/)p˜Öí~jþV9LúnjrTS}L{©’Š©ß Ù·?ˆÉ”¥`g²-Ò˜îê9L¥®Ì$iÚüU5·Â{àÌó.U kºyÝ;áiç[ïzèÓŸ;NCZ7ÁÅk¶éÞ÷ƒ‹®:碫l„Ož±Tw=íI1¨7Uî?Y>)㟚Ukè>ðÄÌ3Ï¿2P *K£ÊÊþO_üä?}ÑnmúŽÈ*ÐÎr¢Ô&4«@yu ĂҚŒº—é׿I˜*VAIcz ИÂ7¬¿ø«¿Q4¦Lö¼6Ê©t%‰>u»gl={ë ¼®±dÜP½`\$¡iðh½©ü\}éÕ7JW²´@g]p¥Ê]ã' ÿì±f/ÿ¯'Ë•¼ãþIÃÿéX»Ô|ù_N6QÒ\ÉÛÆMÔE&œìMöÒn¸Mê’iL¿.Y’úiÒT`*%P,_mÖ¬Œê’ÁÝ<œò­ì÷oël‘å}k—SÌÏÃæ0-“Ãdq)™Ùß¼~æV–ÿ£oßÝÏ®?þÊ祢N[¶íËW<¯rů—èr-nr˜ÆÏØ$\z°Ñãå˜LàÁ&’0rˆ× %grK³ ñTž{hL¹¡0]ÉÙGa5ÓeYj¨1Y.ßp6&[­ÓÎIñä#]ú @€ @€@#hLöÏ÷52“iL–6©ª”&H¬he꼕îת‰“—÷kÊö—w=dZ*M¢hû×=­_e)é_ð­þ­ŠÍà*Û„\%ç-)÷’&nÝÌÊCOͲ'|彿ž¢)–O}öX½íÏnלîOÎÔß…kºE?Ÿœú¢–º°¿WÑD‹¦[”šB&®i]ͲèMº<;o¶5Ëk“»šzÑŸ«èÏÇõëq'~ã¾GƒlLöç㚃ùÄg¾¨ ˜[ï}J‰+´¡_?ñé/êÏʵøNx2ÆiLn>fü¤ÿëˆ ûÔôó 'œ$iäÙ—ªÜ^јnøLÇ|ê .›…ì%m[9õÌKk&›nWczeíÚßÝ~r9Ü1OÛpÉ@»‡é¨a {·ºy>7áê¦ú4Ï'IS}WÝ»dÒ‚WJSy99iL ¸lû'Îôèì-úZ›õ”Z!ð¶ñSÉÉÔn\¼ÚßiLue&iLSç¯,ßC·Bw<óÜKUÂÉËÛ›_•ª;â+§èöçR.éNç¼%MrßrçCº£E<Ý÷üíûî?Yï[ŠAÝÑt³“R ›ÝïÌ^Ò­M·­°R „(áôK<»H75í³`ÍîÈMÓ/ï}êýøˆ².Y*A LA6¦’Ãô7ïù»/žp’eÔêòë~¥»’ngæàêËõ…ãO²[Õ»Þýwcx¾Jº]² É«¯O2õEc:÷ÒðÓud[ÏÞz¯{©ii!抺To‘ÊàR#iIËÆ™Ìd‹ÇéRS*W¨Ø_¸ ¦ö7_ú—oè:œ¾ô‡7ŒÑ£rpÁ)ÙKz`¾ça9L;ËSÉ•´˜Ìõä{+'aªv˜Üãq»ÏÿíYðû›Kày8p˜>{ìÒõ;Ã6êïðó'|»¶ëª®ç™É _‘BªÇ{¥b 4¦5Ƥåä”cRÓÈ›æþà—/ˆLÙaâÁ&™+µtSבrÂø Øj˜‘lLôÒ›¶Øe³EåôqXc’äÃ" –Çß j€ @€ @ oИœÆT-3ékŽóûç\f‰+¬„W”öé/h2F³¿×Ý2.˜’Y±ã]ïù;MÌ|÷ìKULc²µxþí®ÇeZ<2e…f‚õSïØdð?ù¤Sϼ$œ)œÖ¢õi›:SÞ®UÅn¯&]p¬Øâ²²•ÓÒ”æù*«hí•ÆtÕ½KõÕ¶ šö &MKS}çýj&Mø¹UW\Æ‚ ŸYIþÃd*ö@bï"SDf’Æ4eÞÊèm1ðtUWåŒs/QqcØmÈRÒMmÒô¥auI÷>ó–´ŠÓu?»Cª®~ ö`z[w=Ýæl '[ÎI‰—t/»ø‡?µ„(Òp{~ñ¸ÇgèWY?.P œ•û£ŸÞ¦”ß8õ¬ŸÞzÿßÓÀMKÈ•îh¥$‚º£­Ü©UPMcÒÏ»&LU‘}kw1•ǦõêöÌ /ékuÙµ·J½ÕÏÏ’-$g“³ ìV…Æ4ÄÉáµ<јΨ"+×]jžŸÛ«'ðÚKM$ÙR$»Û ÙLKÕ*˜t©‘½dê’]jL` ԥʥF®¤ŠK¿$ÝÿÆ_=Pºwäpú%]gô -WòÊëǸdoQ)¼`eUäê&a ìävµþ:SlÏÃe‡i]äÁæÉy[”ZÒ=ØØZrJ0ùÈìÍ–?OÓ÷,Cý¯Çøé/éÁFy˜T~ñij»,Ç$6\!sI)—a£Ñ°Æ¤ s¦!¹Üu­jLJÎäN$ ª»¹ï @€ @…" )âñðk)3ÓÖ[¿ý©UwŽÄ½ù×ïzÏss{]%·qσOkÖV¿º)ÛÒºÁªp𦕥䤥›ïxÐ2-s·%YAÅŒ%û+p[ÕBÿÄoù–lŠÅÒ,Y‘¤ ]ýtë阺äòRh~W½6ÝR^3(õAoJ` VØY»[³/šz9íÜËU4m ?×êT¶þŤY«ôÓÜÑt¯¦a4Ý«)Íøª(_…2I“1½å¿&×ìï×ýê·¦Z)ÙKý—ÿäV¥_R Íkú!ИκԒ0Íè f]î¥Ã;L3ÁúÕ&ƒoºã1iLVäiEcúäßÿU4##Ðû/‡yÔ1/¬Ø¾˜¸,¥\ûlÈ’Æ´ÄéÒ˜ÌaúÕĵ'];Có£ú2~÷¦97LèÈXPZåÊMvšÉô÷ü/7ÏùO&©P Ð -3wÔð¿–=ÐD8ý—¨ÔÞuû»ûÁÉ2™,¹ mó–´`œ2 Ú¯”uioxÍ8ÝÚ‚T(¥»ž$ÝüÐQ÷?1C?Ÿ›·ÆL>Kˆ2ö±î§»›³rÇÜ71¸ÙMmM à†îhAN˜ô¾3q•‡I Þ·[˜4¦pAÝÂÜÝJÛJ¨bÒí¿žrƯ©l 1êQ9KñFcª#Dºk‹ž½õ^÷RãR™ÖJKöŒm·Ôȥƞ®]*SY5N]¸Ô”®6îRc®d9ýÒšÝÊ÷fÐ&ߨüðú1z~V&]atyðé…Ú?ya‹“[j¹j¹ð"Ë%W²uIÏÃÑ Lq> Í9î°c>ñ™%kû]˜ìÿƒtñ×_5 ?o’]ê-Ù•hëyæáYÒ˜‚ ¸&%aCý¯‡&eiÒeY=ýø¹¦š›ÿ÷ƒ΃M+wó¶ö™°æ½oÿéÍ,]óß4¦üÇÐÛ8ûHÙ”ÜB™ZoN¿ŠI«SxE:åq’ å-P:@€ @€À æÞqèçÃý-ÿe}‹ë'G¬ÿ‰UV©H¡¢I”gç®'R²íË®¾QÓ±¶è[° ÜWN)[J%)–JS)×þìýúÔ´%á9•ž’±¤¹[›Sq3+JAüuø†àŸûµ!KI³¹Ay|ÆÜž Á’M´¨È[Òb:]õSû›æÛÆMÔÊqnºEÓJ¶dê’–3BÛúi“¦ 4㫟ÊTL«vZ¾ [9N“»NfblÆ4¦ðršôÕÔoyEŒÒ”k!9å^R ÍûêO¨å0©Ü6>Е\ ÙKV4üG|Ø&ƒo¼ã±oMczßß¾{ï“?}û‚¿¨èý½¿ƒßç/~Æú~àºaÃ?ô?~z®»˜„sÒè",$WIW0zü ûjßåó&ÙŒéew¿xÙÝ‹mmšŸNèýÎMsl99i‚úŠI Œ¤1þ¥÷_ö/OoüÔ3}Ã)pžXDÝ Î±½Þ³ãê¿ÿ‡*s·ú†ÜûLc ßu7t·?Ý u¿«¬xKºK^ò£ŸºQu#S®A7±­›]ÉÐ f¸ï¸¢Ô[s•©ô-ØSºÙÝ %×|§œ~î¦èîví÷ŸtêYúš¸l‚n!TÝÑdw´Š‰+I÷/»‘ÝñÐT[<®œA°¤ÞJÀÕÍë¶‚rêY—ªAéô_Ýÿ|Dº%á]'à‰Æ\Ijžº¢ôìœz_jÜu&üW•§ëŠ·z®vO×ö\mE¤2]¤2Õã´e6u—š«z›ŠV^¶Kr¼ýè†Ûì)ZEKÈé™Ù&Sÿ?ñé/\uý LºÎXÖR=0k»þr¡ LN`²;xvÈJéR$(­Ö%[_dy÷³w¼uÉ{ê?ßvü¡§¯îb9ðð¥ÃüŸîÁÆÅÅ‚"'û®gÖ›À$Úã¦ö}ùŠçíÁFHå0©ˆ¡®ÕÒ˜Œ˜ŒÒc/{îÉy[=ØüÓñGM[wã²í×ènEé =è‘àõ?níúuÌë¢1yþ|wÞiL£K/ëÌøñãMijUcÒ®R—¤>ÉgÒ‘îDùfCë!@€ @€@× Œ;5ú¯ù?9âPïDÕ£Eå>tÔ1ÑyË™T)šDyfΊð”‰ùIî¾+é%þø[óµãŸš)WéÎ&i‚V?%-©Ì[ñJØX RPT¦Ul×RPØäŠ[!nNÏV›Ð•¨tõOo×\‹&tµ}ã˜ôþ¬¥[LZÒ¼KyÁ¸Òô€å¥Ð¯þvÜ–½Ð$®æ]LcÒì‹fb¦-Þ¬eã‚©—’ºtåè1š€ý‹q¶àÎß¼çïlRAkîhVF“¾®h–÷އ¦Ø¢Vôε7•Q¡ŸÒ˜ôgå–ÁBsÀ¶xÜ1Ã?ÉoÕÜŒ&efÒÒWÿð¾µ4üÏ_Ö²uCÊÆô®w¿gÓö×7¿²§¾Ì´pl×Ç'„@80|øð “ç†sE¸k‚&üî|zÝü•;å-M|á[Å&ø.Ÿ7ÉfLo}jÖ[™¶d»¾•A6¦‡VT­ºšòT³¿z²¾*Û÷þáOï¼ÓAk9¤¨j•3éoP—µ¨ÜÀ-¯únh÷ÁÓ~pÉiç\¾ JT’°«Ië’¶{”Òo Ã=9Sc[Æ’o*KKòwCª®K.6te,)]Ÿ/iC‹¢ê[ðÌœÕÚA?¥1év^ÎÉY¹˜tG{è™…¦äÖÞÑô•‘º¤$‚³{ûϽl´¥_ ndN±•O©¤ÞÚ¨ºsÉ*8û’ëtçúÙÿÙ8w£Š»m…M&4¦¢~SRì—'“.&MžÀŸ™hLÕÙ•Ü“výLKîRö–ÂyL%-ézbËÆ)å’þ@Õz–¾iÌZ-NfI‹ÇÝú€Šý€Ë½¤{±®BzÀþå½OêùùØß0{Iº¿=9Ûc³®6_ûÖ™î™9HYº<0þËÏÌ|\Z1­e©õlLö<¬R_fŠáy¸ü`3©ÎƒÍcs_ÖóŒ²K>:{óͯÖöm“× bKZ˜&ÉÙ–`räMsõT#Ïéêû–}íÇÓ–“ãÁ&þËîþhLÝÇŒÆÔ}¦œ1!Nc²uá´"œeVÒ¿›©ƒhLò–üI÷=9_À*÷>9ÿó_>©ô—åÛ?6üóÊÀ¤Ÿ¿~|ž¦dä0i[嬋¯SÊ¢rnÚÆÉLº0”™)†i›Ü} hpFT&üæ„Ó°Y®Íó)QÊ•¿^âòÍè»|ÒOfXºÍ•^z×b™LÇ]öÜ%w.j´êJØaÂdÊHÜ3ÕŒ°Æ˜¬‘Ò˜J·¼è­ÐÝO;çbyºn ë~7_ôDcÒ•¤ÑuFW˜É³Vè <Ÿ—šêôKã?X(­Í L‘µb;xÞµÿÍà1øò÷Æú<ÜèÁÆþï¦êÁÆœ°&6¥Åõx°Iì’…Æ j4¦X°rÒô  1¥Z@€ @€@¡Hg)-!Wû2©VHªäL 2'ieÒÌåUZ’S”B~R#EÉM܆D¥´uu¥r"–jcÉ–`¨*-zK¥$.UÞ’ì¥ÞòÊÎ^ªQ—¢s0ÁÔoåïÈKöÒÀdÌ€½40û;T{ÉÍÜt¦1Ó6z½õf 3­R¨ñLgb&ðÆÞþÉ#‡©¼ö›¾HU/=7~ñ/F ½~›ðÿÔì°ÈèæùÊ_öòT_`¦Úaê/ça*͆NSª³ŠiÑÈajd2õí뛼qòлÃòE`ß½n ¹Ú–Kcš…Æ”¯ñŸ‹Öú¢1}qõÚÊå|¥vyѳ·žÀ»x©¸Ú´{©)=H7%뺒µé—:s%;ÎÆ¤»ùyXã^2Sƒçá®<ö´ò`SÎkUÊœ×TÎîüÁÆ}ÁyÂiñZ‡ÆÔ"¨övCcj{ç†SnBEC!@€ @È;iLüÈ1áÕmj·5‰2qÆòæûÔ(JU¢Ò€«T])ª+É[*ͬÔ1–*kèDçtKÐÍ·T×[ZYã-ÕɺTO]ø#òª…04SÏ^*Íþ.­Zp§õÄKu÷’Æ”÷JûÓ ÐÄUšwíH}Ú•FiÂïcÇ|â'g—¯¦-VlE·~M–—ª©ÎÃTv˜*_·æ“™Lý¯þ!Üøa÷ ëéïéJw8IaHcj~Ë3©êžXå*Õxº¡œ‚õ¤¥*C7|«Ÿu)âTßÚœ[^uyý ·t «£´ÿBc*ÌàÏNG<ј¢W’êå&u!ÒxÓKM° ¥•HúRËcZNíV~®îê¥&"J6X<.z©ÈTÚÉ£r|ÏÃÝzì l†Ul\ìÁ¦’„)È;èƒMkr¶=Ø xZÕ_`žpZ¼ ¡1µª½ÝИÚãÅÞ¹!€Æ”›PÑP@€ @€òN И>|L Éæb÷hå©é=n¦$²Q^ú­ÆOj¸\ÈUª«+Õ® WþÛå²±ÔPZŠæ[ªñ–ê­¬N¥Õâ" ÆUg]*嫈Lú–fb¬Lm?wE[bS|Ó6y½´?šÌ{dÄáJŤ ecš6j„Šì%«ËR4Õ¾¿âÞѶçÞõmXA{÷íÿè1Ÿ÷ĬˆÀTZo%ÈU0øT_;Óö½ø·ßqÐFNyø­‡xd„ÞÑöèù£µ=fé˜ñ«Êž–}¤|ÚP5½ i¨âçì.iLOM_ÞÄÍyÖ(•*{ Á0² jé–M+ØÄ[Ь…: %¢.…”ܺ« º„(ÝU Ü ©»#³‰€'Óȳ.n”©TW={ë <ÆKMéV[»ìrË—š†iÞê^j:ÈôyZŽéy¸³ÇžWæM¶ÇžˆÛýêþš˜=Ø(Õkéï%ì4Œ’Ë>uâWO6W©Qу͟Þx°i÷ Çžì!ÇÛ+S,¡GcŠ+'MŸSú1 € @€ xB ¤1},¬ÕnkåÉi=îýyY÷wÞáJ:¥FI•ܪp‘¹[÷kðýMŒ¥J¦¥ZiinoxI@Zª›o©â- ®.U’UD².% .…gnbš¶ñd„ÓÍÈU2Émh!9‰JzG†“~jÞNxÚÞ´öÑ1úÈ<'¥CÚªÑL¦±ÏtþbyJÕÖ¯)-þ¨/r g yª/ì0©‘ýû•«@•ä3I`:øÇƒšÉsù™ìS—Ï@S}Îpj«ìœ/Ҙ·¼Ú{¢iLun…¡Û_­®¤{_í]/t¿«– jR.EB ßÝʉ—ª³¡Ø¼¸•ºn\4¦|ð\´ÖiT“'p]ˆôžÀ¥&òD]wyÊÊšqeû?Xg¹Rš‹’ágæ¶$þÚã{n÷±gGÏòÖU´¡5éÂ_+3™ÜƒMD`*?ØÙ%»ð`S×ajý GÏ<ö`£G =ääââÐõF¢1uipB4¦X°rÒô  1¥Z@€ @€€'¤1}àÃsK¹ÕÝø«¿~÷ãÓ–9ýhðÒŸ7/u]¥Ì•D,šY±þÓpÛŽKµÒRdÆ%*-iö¥2Å[™€©J¹ToÁ¸à/¤ƒRYëaˆó1-ß´'ƒœn¶KÀ\%½¤%©X¦%éJÎR’Õdéšl7í¯)=Û¹])¨¥d2ÝûØÌ*©j!¹.LõE&Õ«©;›´ ÏÞ™º¤×œ­s,9“ö‘ؤ¢ý•±©]˜ìŸ;Ò˜ž˜ÖS{7,™IA.¥ïž9J¥Ñ­°C·l,UÝòêÝ隈¹ƒªKA6”¦+ÇuñF†Æ”»Ažý{¢1éJZLÙ®09Ûôì­'ðü]jªWŽëâ:Ëñ=·ûØãŠôØ#»6¥™Lö`ãRKV¯ÛoX`šŠX÷ò0Ù·»•'9Ü&j[ñ6!S,w4¦X°rÒô  1¥Z@€ @€€'Lcj®ý¥4¦©Ë5“–~«J§4°bEtéŠW©®®T›cÉfv#™–j¥¥Zo)ô÷â–£¢·TY0®”¬"u‰lLž|3ØM§"ÉR’“äì%½o‰—¬Íò–4g 4ÿ§÷]é Se“éÑ™aI±ü¥®Ìó¹©>ûV¶µäJ­Ã¤Fj‘8YJÚ¨$iI.?“}*iI3|¶¡¢ ÛW± Hcj~ËûΙ£T¦VªÉ&ØÈÐè¹ÍÝܰ·¹»U¥Bi°þi¬÷24¦b#Ré'SÝ+‰»¶èB¤'ð„/5•Çé: .‡Ÿ¢-µë¥&&©ÝÇ}#Â=»•“©ökR6™Z°©ü„ºÙñZr®­<áØZºö„£bOD¾Ð˜b :S,X9iúИÒ-€ @€ @ÀÆtäÇæ¯’lÔ°hå±)K„Ôh#økãÚRI§Ô(©Ry·´tTÝR«+…Œ¥òÚu2-ÕI¶Ô¦·Tñ$ZÌ™ßn1MÛx2Âéf»œ«äÖX1QIçQÊÙKÒ•4ig§µ÷õÓæðt¬û¨ÝzÍdºç‘¤¸"(³*‹d•¥ÃRº‚p:´§úê:Ljž[-N˜ô޲X6&­.§eæô«9LöŽ>ÒÏvûÅþ¹# é±)Ë܃DJß9ã"•ð­°ù½¯6›`d…¸ºnno©:•`MÖ¥*·”A0æÛSîyöì‹ÆtƨšKÍ@¶6={ë ¼þ߸çíÐcöP/55 SF²–6U—ÊÒ|Ã:sLÏÃ<öèICú5OBi&SäÁf SÉ:íìÁ¦ÑZrî«ÝÊŽe´CäsOÞ,ìá )– £1Å‚•“¦O)ýÐ@€ @€9S^ÆvŽÚ鉯dW’FEÏÞz¯ÿhØ¥¦6Á[(™Ø¥&¦çá{^™7YÏE.'e“o–™Lw•lœÀ¤ƒƒ͠S‹O8¶›o,ñdŽ®Ým*Swy–φÆ VNš>4¦ôc@ @€ @ð„€iLÍæHzé‘ç–JEÔFj˜N©’^Å’¬„Keî¶”y¥2}[w7ô¯ÿQc©vy¸*iii @D¥%%¨¨,ߨLgÅ4mãɧ›ù"`&Ó]¦›•h&b)WÁÀBr]q˜ò……Ö&I@Ó#Ï/Þ7(ºÍ}ûô‹TeH­ÔàÆWk, *-Eîqeo)ñ¬KnahLIŽOOêòGcrIIí NÕöðsKôÞÅK=H‡KäZ¿Ô¤òÓçá²ÉälL`êôÁ¦‡É“«D·º‰ÆÔ-’UçAcŠ+'MŸSú1 € @€ xBÀ4¦ÈI)T4‰2á¹%µR“wBr’ü¤:ŠRQ)˜_‰¦V2oi{]]©nš¥üJKµóÄ9¶ñäD7»NÀL¦;&L+µ«&¦®ç„Ò˜‚[^õ}pà×e©µ;ààznm*ÁÚ;]o)™ rŸBcâKÔužhL"£—šë?áÙ@cjt©©~ÒŽïR“¡”¥ù}6“鎇†ú`ƒÃÔõKNˆÆÕChL±`å¤é@cJ?´€ @€ OHcúÇ#?Vc™{T.šDyèÙk³%™Š)µê]çú–RÙUª] .ºtNh:ºR~Ò,µ˜œ)¿Ó6ž|‰èf× ˜ÉtûƒÓ¦Ö|‡¾–\×[Ë F@ÓCÏ.ip[ \o~¡J{·¿nnÝû]=i©bdò‡ÆT°¯@ºã‰Æô­Ó/ªc#YvÒ;ôì­'p.5îi9×ÏÃf2 åÁ‡)¦KS,`јbÁÊIÓ'€Æ”~ h @€ @ž4¦}´¹{¤I”Ÿy±®Ô mRdÑ·ê\JZ%ª´PTÝ20}[í*ù +5²šr=mãÉ÷ˆnv€™L·Ÿþ^à0u3'¬% ©þ-¯²Ó·N»PŶp,ÝòêÝõªîwy^ü‰ïQ× ø¢1Ù•¤AÑ…HOà-^gÊYÜ }©Éûó°™L=Øà0uý"ãNˆÆ [4¦X°rÒô  1¥Z@€ @€€'LcªYÔ¦ÊCú iLO/¶5ݦIl^¶±±”¢~R¥T_T*ežÈ¢9-fNŠc·¼OÛxòU¢›]'1™p˜ºN˜Ö%hLO¿X}[,ßþì&øÍÓ.T)ß» Öu• &æ¢1ñUê:O4&]I*—šª‹Œ]jÆ?½XOà­Øà0uý >!S,xјbÁÊIÓ'€Æ”~ h @€ @ž0©61RxFä/þêÝ<½¸¾‡d6’J%“DíÆÔ¥Z Çʶ:Å{KiPó©Ó6ž|›èf× 8“©Å©¾ÿxû®·úF@“ìú‹™–îw§|ÿB•F~’» 6¼÷-Ù6èe?_; 1ùöI ¿¾hL‘+‰{¨.mèÙ[Oà‘U&?f׿ï¿ý÷ì?Ëd:úcÃZy°ÁaJàò…Æ d4¦X°rÒô  1¥Z@€ @€€?d2)'“{=õô´.\n»çÁÈ;üš$±&Þ=î±æ5N›Û“ýi¾Sô´»¶mï—¥ÔDcÂaê.pÏ϶uëÖð=qêôY‘˯.Ⱥ,'yÈx]­<$¬}y“ç߬¶ºïƒÆôæ›o†/5Ú~|ÒÔÚ«MÆ¿þ 7oÐçá¹‹×æâyxÚÚ³Öþvyó¦¶.ïŒÆÔ1ºf¢1Å‚•“¦O)ýÐ@€ @€¼% ,>ͳžði.ÉÛ¯p!;®Ä-L&¦BF<;úÿ¿‹k~îI6¦ì ò ¶Ä©{sa7wßñŒ48ƒÏÃo¼µó×+þlê¦Mlp˜».¡1Å‚)¬œ4}hLéÇ€@€ @€ à-4¦ŒÌ» ±œ¶ñö;EÇ»B ®É„ÃÔ¶œ¤ 4¦!ÞŒŽÆÄ÷® 4¦˜¾wž6ƒÏ˶WÏa*{~ß[k2é¦$/hL±ÐFcŠ+'MŸSú1 € @€ xK©s<œ¶ñö;EÇ»E b2á0u ,çAcJþƇÆÄ÷)B€lLq\ˆ²öÔ!€ÆÄ°€ @€ @€ @€€wИ¼ ¹gFcJ7àûÞèUê–'Ö‘nÛ R;SAI7¢И€ @€ @€ @ðŽ“w!÷¬ÃhL©|ÚæêjL[LL½mEhS¢Hê@cbX@€ @€ @€ @À;hLޅܳ£1¥𺠙HÅÔµ¸ 1u %'Ê4¦lŃÖ@€ @€ @€ @ hL @¦Š  1¥ßU]›‰TL]‹ S×Pr¢l@cÊVmiP¦e›ÊgûÊØ±ccÌõO‹Æ”(n*KŽSr¬© € @€ @€ @!€Æ”‘@ÐŒ˜äKcz|ÒT'-ÙÆ6•’·¤ró­Æ4ˆÀ´ë÷USlÓ+“d¦*éåÆTÏa 4¦’ÃÔ\cZºÑ9Le©ÖajQcš¿ZS 1SDcêÝ9 1•¦æÓôŠÆ8Li SLßcNë#4&£NŸ!@€ @€ @€<'€Æäù(|÷ó¥1=6qª“–².•/½ñó_Þ)©nú%åaröR9 SiG9 Sçy˜Zu˜ö»_Ó#OM [J‘í’Ætr8ëR9ñRT]:ørÿë/ïx}s¨(ñ’+/mÿÔ¥{iÛïúBÓÆß¾&uÉJT`zåÀº­kɹ…äÖlÙ¿Z¥ÁZr-æaj×ajq9¹*ËÉ•W”[Ùj*¦™Ëw”KÏ L¥²ÝiLnE¹p*&Ó˜îºçÞ?üûÛ®üû[oÇû5;í°CãN· Î4 1¥A:!@€ @€ @€ *4¦TñSyìò¥1=üäóK)üëM¿4¦-i)šu©V] å^ ¯N¿˜œ½4¨ÀÔ, ÓËûWm~Õ­%ç’ÓÆŠMûV¼”åVúöõ”ËÞ„¦ËÉÍé퟽¢\f­¨¿œœ4&-'g“s˜¦-Ý^Ö˜J©˜Lcºñæ;ÂÒ˜¶ãåhLñòåì©@cJ =C€ @€ @€ @ -hLi‘§ÞdäKcšðÄó&'Õ–—ûÞtËÿòµ“µ$[ª‘–,÷RD  /Ur/5²—Âé—:˜”‡i••ÀÔ, SµÃ´,¼–܆½KK%XH®ÁZræa²Ã$i@cZº}ÀaZZv˜Ð˜’ùRS‹'И< 4Ý„ @€ @€ @€À4&FC± äMczN‹Á…Kxa¸o¹ã_¾zr£¥âL`ªï-iÙ¸•ã~'oÉJgé—ÂKȵ.0µ“„©ä0­Ê‹•²xÝžRÙ½Hem¹,\»;(kv/X³ËŠ–seþª]ZH®¼–\7&Ó˜‚TL &4¦b_Lè]ÂИNu€ @€ @€ @HŸSú1 qÈ—ÆôàÏmRF%+%-)\´ZÙ‰_=Ù½S6–BÉ–ò-µà-•/ýæµõ¯eÝ+Êeë­çÊš­ÖlQÙ_¶—¶ì—º4`/µ©žÀ¤åäöº$LK7–30u„©®Ã4µ¦Ã´r缕;çVŠ–s¥Åµä$0Y 4¦ÆSœ_eÎí4&ïBN‡!@€ @€ @€ €ÆÄ(6|iLãn@Nª^NŠÒOo¾ýįœ¬¨®TÊ´¤²q ”ó-ER.…׌«R—ä0uÉ^êÝôê •—öYYn¥OÞ’+­ LJÅÔI¦ÀaªJÂ4à0õî˜zûÍašeeù•™•2£g‡•é=eI“ò0™Æ45(ÛTä-EÊgûŠl³ˆïWì´Ã;5Þ*8;Ò €Æ”uê„ @€ @€ @€@ªИRÅOå±È™ÆôØsÁêoµ¥d)Ýðó@c ¹JËÃÕ.g Æ­·RÊ·õ–šªKíæ^jd/…¦½=»/0…’ë0 ÓŠ*ifE`š!©â0 ɕ֒“ÆTv˜j&ó™Ð˜bÿJS7И¼ 5… @€ @€ @€@…c¡Øò¥1=ðè³&$Õ9I×ÿÛí#¾ò ó“jKÄX*yK•uâlck4å’VŽs Æ5[6®ñÊqe{iSuî¥Æé—´œ[BnɆ½K6ì Êú=J¼äJ‹˜š L«ªV‘›Û~¦Àaª,$ç& L%iÛÔS±/&ô.ahL §:@€ @€ @€ ¤O)ýЂ8 äKcºÿÑgÃ~RÙLª$U-é_¿áR+U6ª]¥ÆÆR -5õ–VKWreóþU›_]Y]$-¹Rgå¸Ö쥥!{),0Uì%-$·{‘ÊÚrY¸vwPÖì–·äÊ «w¹2UãUäV¬"§åäl¹ÊBr’0 ,$ç&·œ4¦Ú…äÂï)Îo3çö‹À Óøñãûúú ÉÁƒG5räÈ9sæø‰ÞB€ @€ @€ @ XИŠOz%/iÜ#Ïi“”ÑÿvÛ ÿúò§õR+ITrEÆÒì7žúýsNüê)·ÞýK¶¤w>ó¹ãn½ë!IK*OÏ\6â«§¨h#ì-Mž±ôG}ÙÕ79oiÆ¢õGyôÄéKV¼T{©oߥ?ºñ’ÝØÓ·oê‚u=}ÁÊqÃ?{¬~†s/•쥽_þ—“~q£ôKN`ºèÊÞÿÁ£T.¼ò˜Ž;ñ?»°y¦ú óVîœ[)ò–\i&0-ß1£²œ[EN©˜ÂI˜‚ L¥$LhL\b ÐERÜÙ¤$ICÒ;ýýýöf3iòäɇ~xOOí:lذ1cÆèWmè£.6‘SA€ @€ @€ @I@cJ’6u%O _ÓØ‡Ÿ «H‘íë~hLöf%¯RtU¸ðÚpò®¸æ¦G&ÏÖÆ½ž–´ôéÏwù57=lï<ô´¼%mü⮇T´¡ÜKNZš0qö{Þû>½é².]võ’x|jÖòRÖ%yKVκàJ•°½tæWÊ[²âVŽ“½ôÓû_øÈy—_÷„iÁÆe£e/ýÍ{þN?¿ú­3¿xÂIw>4U?Gž}™¦w½ç﮽yìÏï~âñ™L—]{ëŽ?éöñS~pÉuÇ ÿ|‹“ÉLhLÉ…©±ÌDj¤1ÉpÒ§Í•ÓÇNc²m©OsæÌ‘…ÆTÈC§ @€ @€ @€Þ–À„Æäí5„ŽÇG ²¨ÜøÒK&’^ª´ I{['•‹/Zœ€ @€ @€ @ @cJ2U¤H _Ó=>]×F²7,éÄ“";”— ƒ ü¤ÚâR+Y‚¥å}ûTlÛò*•Ô¥òÂp2–¬HW2I?ŸŸ¿vø?+iIÛ÷?!©,-¹¬Kgœ…Šì%K¹¤RÒ˜vëW·fœt%˜L] — ®¸Á¼%•“N=ëûç^>Õ.­g‹Ç]yý§.Ùâqóž÷)ýÒ×¾u¦-!gê’~*ë’ì¥àgiå8+Ò˜ô޼%+Ÿ?þ$ÙKç\r¶ßõî¿û×SΘ¶tûÔ l J)åR“B6¦¿ËT]<áÄI}}}ÒÆŒ#“iEå D8“ —v«Ó=‚ @€ @€ @€@á  1>Äžw0_ÓÝã'×U‘ìÍk~ú+iLn·\t£$*M[°N¢’eWºùŽmû=û>K*J­tÊwϾóIÃ?{¬yKÇÿëÉw<0iéÆ Ç’ÊOÓ’ {/þáO¿ü/'«HZR.%­ç¤%—uéŒó®P){KëvK]’ƤŸr•ÆŒhkÆé¥\Ò;÷>:]+ÇýôÖûÍ[’Ã4ýÅ—µlœ©K¿¼÷I¥V’½”•;•uIÒ’Ô¥R¦©æ-IZºkÂÔÿuÄG¤.©Ü\Z-nÖŠÒ•ä-éç3/¼¤G§ö*ý’r/)Óôží²—”I嚟ßwï“óe/MšÛ'“©E‰lLž_Iè~œÆ¤5æ$0YZQN«Ãi£lLJß${I2“ܦþþþ8ÚÊ9!@€ @€ @€  1%™*R$;ɲ%Õ-Wßð«/x’[÷­f#ð“Ê¥d&IQ’œ¤|KRˆ~~ûx½#uIïœyÁ•–cÉ,éM• ¤¥=å²~ÏýÏ´$QéÙyktøíã&j[ïŒ}lÆmã&êyKJ¶èJëvŸ~Þ*ò–>ù™/wâ7f.Ý¢÷¥.YÊ%-'oÉ–ŠÓšq¿~dú„gjCY—¾þí³Þÿ¸ÄK¦.}ýÛgJZúÞ9—}íÛgÊaºâº_I]Ò;R—¹—†}ê Z-näÙ—Êaºöæ±&0éçe×Þªw¾{Vðþ¥×Þ*{I_9åŒSKïÜûÄüŸÝñø?ñ‘Sϼä_O9ýcÃ?ß<ýRäS²1¥ø]¦êâgc’€$ I2’6¬§ƒhLJß&"õÉì'^€ @€ @€ @€@~  1å7v´¼ùÒ˜îz`’[Ö­vCÓq#¾Þdû(Ȩd¥”TéÇ7ÞnÆ’Š²+=>åÅkn¼ý¹ùkci}Pî7Ñ,¥Hyô¹Å¶BœÔ%eZRyä¹E’–¤+=òì"­÷ÌœÕÚP²%yK*ò–T”lIY—ì§\¥[ï}ʼ%˽ôÐ3 -ëÒÄY+•xé™º¤b ÆYyrF¯ì¥[îy≽ºÔÛÿÀÄ–{IËÆÝñÐT-§rûƒST›Ö+{iFÏŽÛÇOÑO•ûžšÛÏß÷ä|9LÓJeÌÏË^*-¬7áùå·Þÿ¼J[“vFcjåKÇ>h‘@OOOxO­~g©Å:Ø € @€ @€ @È4¦‹¦v@ _SxY7ÂåG×SíûNQ’¥4QÉR+•D%+µ¢’½c®R¨Æ’J`,•¤%W‚åá\)IKr•ªJÉUrEÓ=L7o©*åR=uiniÁ8W¤.™·dêR©ê’Ф%WÌ[²b+ÇY1{)(eu)°—TÚõ–ÈÆÔÁ—ŽC ÐhL]ÁÈI @€ @€ @€ 'hLyŠmmŸ@Î4¦û'6ñ~8úViL­˜IµÆR#W©®®$o©ÖXTZ2{i¾JÅ[ºàòë§.Þä[ªë-­Üö–,ëR»êÒ ©KµöÒRg/êÒÐí%'3‘©ý¯ G@ ChL‚ã0@€ @€ @€ ä—S~cGË[!/©îânÎI’Æt숯×I Ó)U%UªÎ«d –ª\%ýZJ°TGW*¥\ §YrÛaiið|K5ÞR .UR.µžu©¾ºTJ¼TɽT²—– 5÷Rmê&4¦V¾tì®@cê FN@€ @€ @€ <@cÊS´hkûò¥1Ý6nbÔ=r‹»­Û}åè_{Â×k×z ¯ûV¸ê•àš¸Jt¥Pš¥z+Ä5H¶4··Y¾¥æÞ’– /תº4äe㚯:‡ÆÔþW# Ð!4¦Áq @€ @€ @€òK)¿±£å­È—Æ4fìÄh†¤PΤ+¯ûåOøzÝåÞ\"¥F¹”ä' ”ÒêoJ%ÁÒ€®¤4Kå…áBËÃÍ[¹sn¤ÔHK‘uâõ–föt¨.Å‘x©®Ï„ÆÔÊ—Ž} ÐhL]ÁÈI @€ @€ @€ 'hLyŠmmŸ@¾4¦_Ý÷T•ovÖìºBÓñ_«³CS-)¢+–’Ê*+;Ã¥ÊUª$Xª£+É^ªg,5––úg­Ø1kyP”c©ª4õ–¦k8W" ÆÅœu©QN&4¦ö¿‚  1uŽÃ @€ @€ @€ _hLù-o…@¾4¦[ï}ªIž¤+~òË/ÿ5·CYH2-iÀLªã'™«µ”B¢R}W©±®Tk,ÕfZª#-E׉Sî¥íÓU– ”zÞÒö©K·eɶæ+¾%ð)S+_:ö@W 1u#' @€ @€ @€@ž 1å)Z´µ}ùÒ˜~yï“‘ IîWIH—]û iLul¤°¢´r§œ¤p‰.ýV³ÜÜÞ~iIÊìÞ~)Já2k…²+Y)çXj-ÓRi©A¾¥ yK5 ©ý¯ G@ ChL‚ã0@€ @€ @€ ä—S~cGË[!/é¿~²‰u$éó_þÚ Z’YJ½*Íä$'-–R¨dÒR«º’Ö‰‹® 'c©%iiÚRKi)ù–š§tBcjåKÇ>è 4¦®`ä$€ @€ @€ @È4¦‚¯4?¿‚ïPGcŠ—/gOSjè©€ @€ @€ @i@cJ‹<õ&C ×S2ˆ¨%ßИò?Z߃€ @€ @€ @Þ@cò.äžuɳ€û×]4&ÿbîIј< 4Ý„ @€ @€ @€À4&FC±  1;¾ô И Xº@€ @€ @€ ÆИÅ&€ÆTìøÒ;4&Æ@Q  15²ô € @€ @€ @  118ŠM©Øñ¥whLŒ¢@c*jdé @€ @€ @€@cbp›S±ãKïИE%€ÆTÔÈÒ/@€ @€ @€ 4$€ÆÄà(64¦bÇ—Þ¡11ŠJ©¨‘¥_€ @€ @€ @hH‰ÁQlhLÅŽ/½Ccb •SQ#K¿ @€ @€ @€ Ѓ£ØИŠ_z‡ÆÄ(*4¦¢F–~A€ @€ @€ @ !4&G±  1;¾ô‰1PThLE,ý‚ @€ @€ @€@ChL Žbx¦oøÊ]?-vé×N;ìиS½&@ç J© ¥[€ @€ @€ @hL‰Ñ@ ÇИr<šÞŒã€ @€ @€ @Þ@cò.äÅíðä“ûöõ·ô õ 11. J© ¥[€ @€ @€ @hL‰ÑQ‡ßzxaúBG Ð*4¦VI±_Π1å,`4€ @€ @€ @C'€Æ4t†œ! F<2BÓÈÉ#•iÔôQÚ°bù™úök[úU{ªhŸ,4›6@`¨И†Jã3J)£¡Y€ @€ @€ @ˆS|l9s’ƯofÒ˜¥c†Ý7lÎÖ9ÿxÐågÒ¯¦1飞þmèW’d © ±@cŠ+'MŸSú1 € @€ @€ @H˜SÂÀ©.&NKR¦%ó“”IÒ’U'ÃIz“Šv“Ƥ¢}FÏSc8-’#€Æ”kjJ”S¢¸© € @€ @€ @Y €Æ”…(І¡±dëÇ9uI¢’e`²7¥.é§|&ÙK*ÚPЦ¡×Ë 24¦”@õq@cŠ‹,ç… @€ @€ @€@f  1e644¬-ný8§1™®¤“HW²OÍaÒ†Ö›ÓnúÙVì ,@cÊbThS 1u"§€ @€ @€ @€@¾ 1å+^´¶‰J¶`œËÀ4yãd¹JZcNkÉé§´eæ´­Ÿ¶ð/äžSîCHê@cbd@€ @€ @€ @À;hLÞ…œCE"€ÆT¤hÒ—4&† @€ @€ @€¼ pàÍ =;®¶2móñwõ6gë·Ý;úÔ t€@ 1 ˆt¡4&Æ @€ @€ @€¼ ðöŸÞ¿ê/e/Õ½¯O½ @'!€S‚Hê@cb\@€ @€ @€ @À«wÝRWcÒû¾  Ÿ~èé¿æ•×&ùÑWzé%4&/ÃîC§Ñ˜|ˆ2}„ @€ @€ @€@@ nB&R118ŠG@ºÞÜWN-^¿èÊИ %€ÆTÐÀÒ-@€ @€ @€ Ô#P›‰TLŒ”â@c*^LéQ4&DA  14°t € @€ @€ @õD2‘ЉaRHhL… + €ÆÄh((4¦‚–nA€ @€ @€ @ pB&R11L I©a¥SИ %€ÆTÐÀÒ-@€ @€ @€ 4 à2‘Љ1RThLE,ý*@cb(”SAK· @€ @€ @€ И€%d"c¤¨ИŠYúU&€ÆÄP((4¦‚–nA€ @€ @€ @ 1%dzbýú $’S!ÃJ§ 11 J© ¥[€ @€ @€ @hL ··÷¯ßõýŠGàÍ7ß<æŸùÎùG¯kôehL …‚@c*h`é @€ @€ @€½täQÇ<77ø‰ÉÄ0)9LŸþì±·Ý÷Øé?¸äꫯ.XïèÊИ %€ÆTÐÀÒ-@€ @€ @€ Ô# oéÃG {aÅ–ÞM¯ÎëyùCÁdb ‡€9L·ß÷¸†÷ŠM¯ž†ÉTœØÒ“jhLŒˆ‚@c*h`é @€ @€ @€jÓÑÃôn]¹ùÕÀóxißœe˜L ”‚¦Ï{ÇØÇWU†÷ò¾}§s19™ `º&€ÆÄx((4¦‚–nA€ @€ @€ @ š€9L Wn]õò~Ó˜–¿´¯§oß쥛ÉÉÄ`É;9LŸ1‡©2¼eéIcZ¶qï÷1™ò]Ú_K‰QQPhL ,Ý‚ @€ @€ @€@ˆ€9L‹Vn]ýòþr®šŠÆ$ÏcÖÒÍüÈ1K{–à y$Pq˜ž†wµ¥§á½tÃÞï}ñ•Wý(]£Í¨O‰‘QPhL ,Ý‚ @€ @€ @€@…€9L‹W½²zË€äa¹jzúö.ݸwɆ=3–lúà‡?¶dY&Óˆ#/½´1lذɓ'×EÞÓÓ£ê~Ô××wðàÁÕ¨máªG—^zgüøñêŽ^jvÍ£Š¡0‡éÎqO¬Ù²ÀÒÓð.%3iÉú=#Ϻø’Ë®j½" Þ6ÂõÒpmýðøötuÐ*Ôf}ûšï¦Þ zžXwp×Ú9sæÔ­‘/f4¦XÇ%'OSzì©€ @€ @€ @ñpSEò¨ZQÎI/®ß3ãÅ—>ÐŽÉ$ÑǼ½ä ɇ¨ëH¤Ðžu;ªÃÕ,ºB¨‘G>¹Ù!ò–Ô“«ÆŒÓÊ]i!'éŒ@Èa:ÐÄÒÓð^¼N&Ó¨ÖM& †ð¸ÍÎ`ÐàlQþSûý~¥®1¹‹€Ybj°»ª„‡_Ì詳KGežSæCD!@€ @€ @€ Ð)ÃT_ò0É$EkwO[Ô†ÉÖ˜Ô@çyHG°ì5£FÒûaiäÈ‘ö‘Þ×nR(tmD w·ö#D¢ƒ;vv¿ZzI«²´¡$.–PÇ* ·MïH½²wì´¶D5°: Çu“€9Lw{bíÖU©˜B &Z*¦Òß½píîïžÙªÉј4ŒñÆáÁfãG_ 97ü¬Ãnˆšê§3Ø>Î4r#6¬ÚI´g˜šÎ¯—$òE{í`'wûë§åé›bcÞuÊȨ̂Úö¸6X÷urk˜ë¯{'ÜÚÈi#_ô‘}=Õ$ƒãΣm™[|1«¾ê€b“Š:8‡ ‘Àê]·¼ý§7=‰s˜lx›¢wÓÃ+O¸jÊðó'å”]ÚÓ·/Þ‹¢Ã{Áš]'ýd††÷ׯî,½YËwh„³±ÉmÒïvZ;ÅÞl2„œf4hØ¡9ÈŠràª"€ÆÄ€È!S'íeÍ8Çz§¾Æ¾Hš6eRž£]‹¹ìæp0Ðd@€ @€ @€ ‚¨8L[á!½CåÖ§Ö¬¨,¶5ü<ÙÏ/ݸWÓͯ^¼n¦/]ñ¼$9Lã§oÒz[#6÷§z•ŠiÖŠ@ò˜Ñ³ý©Ùëßß8'SÁ±Ò½ø ÜÕsØøUÙ\f’ÃôéÏ{ÇØÇÝð^µyÿÕã–i„K¹“¢'OŠÞ…·-, ï™ÞZNîáY›¾|ÅóÊ4ö½›{íý˵`â5ãz¾{ÓKÅTÞ;¦/Û~Ê÷æd*÷^Ó£ç:ûÏ;uP̧Ѝ•”xEŠ‚ËñÖÊ!~íƒÆäW¼‹ÐÛð—ú‚+›­°i}“˜¤Å^µÑ0“ËÌf“[°VÇ„·‹€Š>@€ @€ @€ @ çÌaZØ»ÕRÔØ2[2<®»LnÇò—ö-ïÛ÷‹'WŸ~ó @€ @€ @€he˜žþµ­ßËÓK‘ðH»Èzâ%Ÿÿê÷^}ÚUч)B±ÓÖóß=¶ò Ó)Ÿ¼!v”‹Gl'˜RÈãÜ Û>þËù~[—vBy’é¼ ¯ßr÷I²zbLÅ0ÓÏúñs8è̶˜ÏË*ü;DmÇ&‰)¢—2LÑf,Êû3W~7õaJå}õÍ÷\ÕŠ1EyoÚ–Uø3"Æ”¶“Û²#:¥ Sí$ÓÀSŠ1ò„ß\|’A z1¦Fü|';ÂE)2H{cJ¹¥|§ÉâŽtñ[±ÍÜ jš2 @€ @€ @€º uÔQ§žþÏ©ýRJ/e{lµZÔDŒés_½ã“—}'ú0þ¹›OûÜÍ‘ðˆœGêÃ]j^vÊå‘aºê¦{â=cŠ„GŒsZ1¦!ÈyÿŽ3ÿœwÖµÿóÀè‰ ”(ðÑ­ÿË™çÿÅþÏüÓ妈1Eg¦Û² S´‹-ä¢JóòŽ S«Âc#¹,ÆåÛÉEŒ©+¥×É0Åç~qóÿûÿýçïvl–X2Ô\àÂãëöß#÷C`´@ôQŠ$R¾_dì+»Ë¥C¢3S|O†n*œâ‘XŠG:Ež‡Z½zujÑäA€ @€ @€ @€@µ±åÖa‡ö¡^E—:l¥5±ÁÖg7Ý ØH.5aúôÆ,Æ!7|èê´ÙV4ªI›mEÎcõwEÈãï?üõ·üú,ÆtýެS!äqÊÖpà!·Þqßí;ü寮vâ®ÞþäS˜¾~×úÕ®˜ã9çœó¢¿,/ï´…\êÀôÆ3¯yÕi_M¦(ïW¾ÿ«¯|ÿ¦¼¼ó Sì–xÔÉ—}ð ·DyǾŠGþãeíòînŦ}÷{ƦͷFyÿè¶~sÖa’Lç¾¼1ì&B€I ÌÏÏG)~MI¤Ý»wïܹ3’Hñ$ñ$¾ŒûcJMœòGä–â­fŠ&Lñb†šä|\‹ @€ @€ @€)ÉtÆG/Èãi­´‹\$<Ž›»ú˜w\;m¿ñö£O¹ü+›øÌ×1rKùˆÍ¶N=Û!Ç9ú0µ[1E†©;äQÌ0EÎC’I5–%PŒ1Lùù#Éô¿¬XÞ©Â#ÀtÜ™WG¦çÅH¦¯|£¯¼oÜuÁ•wD¿±TÞŸºâ»íäväÛÉ3L©¼ôÓ_þæ‡ÛzÃLbLe­ºó 0c‘5*&‘Rï¥<ž”wSÚiƸL— @€ @€ @€À ´“Lÿ|AÊv´÷Øjµ¨‰¦´‘Ü51n¹÷ê[ÒN[Y¦hT“o¶µqëÝ^uçÀF5ý&I¦).—šÝzŠ1 0åwI¦CV••w¾…\k¹TÞ}íΞòN{É-”÷¶·îLå}ù–=Æú3L I¦¸ƒb˜IŒ©fÅãvh˜€SÃÔt @€ @€ @€fT %™>ð‘ÏDû¥ï`ZØi«µ—\ôašß¶36ÛŠÇ7DÂãîhT! …íä†e˜F$™vÿ÷Ý3º ¦½ç£LùùR’©¯¼ïûz'¢ù¼vDoP†iã w·+<í–xÝ]©Ó° SW’)n"…™Ä˜ö|}A€¥ ˆ1-ÝÊ;  @€ @€ @€ÔZ ’L‡¶’L­öKíLƒ»ÔŒÌ0C£3L“Lk.[³î¦uµ–rsuxèW»–x;‘d:xÕQ ù¼îcň^O¦ñ2L½I¦¸Ë‡~¼Ä[õ6C@Œi 4‡ @€ @€ @€¨©@$™^pð Oû§O·ÓK·f[ÈeãæöFrŶ:}˜Ú]j6Ûê4ªYJ†iÇý?ÿõÃäÛؾòã+×{}¼²eç–ôk4gÊû3ÅÒ›wîÞ¿•YSP·U3³ÿé£vT^Þi“Ävy§&L}½® SÖilI}˜R†)ƃýªfn‡cjìÒš @€ @€ @€Àl ¤$ÓûÏþt¾ÇÖײxG!áqck#¹ö^r¶Z{Éíi¦ž S€Ï]7·âŒk¯ZÏ#Ï#š3û3ÅïÆoE»¦ø­x[žyšÍÅ2ë1"ÉtСGuåó:¦¼ SÏV‰Ùn‰QÞ2Lcp;„cš ¶K @€ @€ @€˜ˆ@J2½ïìó‹¦þ„ÇB—š’2L1¹h°ɤx2ç|zx’º.¥^Mé•ÔŸ)z2­ú̪‰¨¸Hs"Éô‚CÌÊ»;À´iÛ€ˆ^»Í˜ SsÖßLh¬€Sc—ÖÄ @€ @€ @€fY %™Þ{Öù±ÇV 0õ'<®¸áîÔ¥¦”>LI;,¥VLñktfJ/¦LñˆWRg¦x%ÒKù˜å•2÷ñR’i¡¼[=Æò&L#"zç~qó¾û=cÓæ[ómã>±—Üxëâ(ì€ÓÞè9– @€ @€ @€@}R’é=gžŸLý B—š®»ë’k³qÊÖpà!·Þq߈Gÿ^r¹B$“¢S|ý–¢3S<Éû3ÅóøÝÈ0¥0S:dý·×§FMöT ’L¾èÈÞòÞší“8,¢'ô§ÈÞO€I ˆ1MRÛµ @€ @€ @€LT %™N=óSWnݹ1F+ÞÑNx6’ÛÐ 0í}†)æé¥*Å“¼SŠ1ů‘^Šc¹ñ$LñÎø­ør¢(.Ö ”dj—w!À40¢'ÃÔ •7š) ÆÔÌu5+ @€ @€ @€I dúÐyy€)Ox\zÝB¦R2Lq¹'¥MåR˜)="À/¦$Sz%:6¥íçd˜ê^ D’éù/:¢PÞ]û$æ=¦½tv8& Æ4d— @€ @€ @€ P¥@J2½óŒóR€)F 0å ²2LUNÒµgX ’LÏ{á—o阮òîŠèÉ0Ípu˜:Ó$ Æ4M«å^  @€ @€ @€Œ'’LkÏ8¯`êJxÈ0Gê¨Z dI¦Cޏ´ÑK›$¦!ÃT«•r3! Ƥ< @€ @€ @€Ì„@J2½ãƒëŠ ¦™XûÙ˜d$™8äðb1¦ÙXy³$@ 9bLÍYK3!@€ @€ @€ 0Z %™NùÀB’)žpà!·Þqßí;6vÜÿó_?ü[õHI&}˜ê¿RîĘ @€ @€ @€(&™d˜fhágfªy’É^r3³æ&J€@sĘš³–fB€ @€ @€ @`)Y’éÀóŠãxÞAú0-EÌ{¦K ’LÏ:àEû>鉛6ß:¢ÍXüÖƒýjº¦æn  Ðl1¦f¯¯Ù @€ @€ @€ ð‹«?¹æ)ÿû­›.µ—œúh¤ÀÇŸÿ[›Ö¾R†©‘‹kR4X@Œ©Á‹kj @€ @€ @€†\sÎo^µÏ=7ÌËyì¸ÿç¿~ø|¦UàUû<ø±Wˆ1éÃ4­+ë¾ h´€S£—×ä @€ @€ @€ hŘ~³}þžýEÔC†IÕL½@”÷¹/¬ÒÀ$“ ÓÔ¯¯  ÐP1¦†.¬i @€ @€ @€Xš@O’I†iilÞUoíó¿Ùu[Üb’I†©Þ+çî˜i1¦™^~“'@€ @€ @€h¶ÀWO^½~õÊŸü`{Ï4·~líÝ[æóó$“ S³ë¡a³{èþQÉ·^0×?¯â‹Å$“ SÃjÀth˜€SÃÔt @€ @€ @€´"¨1¦ˆzô‹ôg›"Ét×}ýúáGð˜(ãˆ+}ÿ«ë{nøþom‰ß*¾˜’L2LÓ²²î“™cšÙ¥7q @€ @€ @€& D†éÒ5«bēԴ¦Øé3«V¤ÉG $^ÿΗ×ýG‰ S¼9½³É4æÖÈ*Eǯi6ñ$^¬áüõÑ‹ÎdñÊÀl_#TL‚Ó- Æ4Ýëçî  @€ @€ @€ øÕC»£!Mä“"±O¢cMŠ}¤GêU½š"Æ”¾ŒwÆ{âI|/Fþ ,: lþÀš¨çH,EIGÝÆ“x%vJïÅ“ôzÔyªçx#^‰×%™ê¼¸î™cšÙ¥7q @€ @€ @€† ¤–K‘gJ‰WJ)¥|Ä+‘íH»ÎÅ{Rì)! ¥gO®†K™Þ äeñ»¼nSͧ”RÊíEaÇ+©Y΋О–cS¸æn™æ ˆ15Í @€ @€ @`R‹š˜x$6âIjB“Bñ<õª‰Gz1RMñþx’ö¡KcÑLyŠ¢Œ£¶S…§Š:O5Ÿ‡ðRyÇ;SÙÇëù;ئh­Ý*³# Æ4;km¦ @€ @€ @€3$ÙŽÔr)oHÑ¥<ä½j¢™MŒxC´«‰÷¤½çP¼SÈc†je:§šZ.¥ø]j¹5Y¥h”Bxy § _¼}›Ò\Så{ @€@ÝĘê¶"î‡ @€ @€ @€@ ‘aJ½j"íÏSŒ#•RO¦È*Å“x=~7½žö˜K_æ»t•p+NA`R§SD—"¢uõœFªüˆ+ÅoEUǓԖ,¾Œßµgâ2,ˆS @ 1¦‚ @€ @€ @€@ÝŠ9¤ˆn¤/‹¿Æ—ÑÌ&~+F~ó=_ÖmRî‡@ˆöKyG¥0E2)RJ‘Ì‹O¢°Sy§HSÊóÅ#žÄ—Z1©"ÔV@Œ©¶KãÆ @€ @€ @€ @€ÌŠ€Ó¬¬´y @€ @€ @€ @€¨­€Sm—Æ @€ @€ @€ @€˜1¦YYió$@€ @€ @€ ° pÍ9¿yÕ>¿Ù>Ï„@3¢¼Ï}y3§fVh®€Ss×ÖÌ @€ @€ @€ cRÍcjöúš cjèš @€ @€ @€Ÿú«¬Ó®Û h ÀOweå}Á85S"@€@£Ę½¼&G€ @€ @€ @` @ì·9xàά¼/>©‘“3)4XÀ& ^\S#@€ @€ @€ 0D@ŒIi4X@Œ©Á‹kj4Z@Œ©ÑËkr @€ @€ @€ ˆ1)Œ ˆ15xqMF ˆ15zyMŽ @€ @€ @€À@1&…Ñ`1¦/®© Ðh1¦F/¯É @€ @€ @€( Ƥ0, ÆÔàÅ55- ÆÔèå59 @€ @€ @€ĘFƒĘ¼¸¦F€@£Ę½¼&G€ @€ @€ @` €“Âh°€Sƒ×Ôh´€S£—×ä @€ @€ @€ cR cjðâšcjôòš @€ @€ @€\àÖK~sñIíqÊ~óª}¾Œ×õ T¦X 8/ï ^Ÿ•÷ûžµðJ¿Ô^@Œ©öKä  @€ @€ @€”"ðÃmY¶cà8ë°R®à$ªˆ2VáQü P{1¦Ú/‘$@€ @€ @€ P–À°œ‡GYÂÎS¡À° ž”^…‹âÒØ1¦=Ñò^ @€ @€ @€S-00ç!ä1Õkêæ‹ƒzRzŠ„S" Æ4% å6  @€ @€ @€”"Пóò(ÖIê Ðԓҫú¸,M@ŒiiNÞE€ @€ @€ @ =9!f,«Yä=A=)=µA€écšžµr§ @€ @€ @€J(æ<„¼ÎSý÷V{¼’|WÍGñ.ûüõÅê¿øÑÈ> Ýõ_þ‡ß~ÔïÿÁŠüõâ'"=ÿÃ?úãôÃT±ÝuÛ*ݬnÛ¥ÛªÞþî­áV畼=«ä®b.ÔóO²znTÒYUg…UuVØÝµ}S§¶óòî­ðV‘wê¼»Ô¿•z»Ú|_Í·Ê>¯ü¼ø;õ¿«]ÿÅÀí@ßag|b\ÑñYxÞ xÓI§u}" Šø\¼ûìÏ>ûÙÏ^ê’{¦D@ŒiJÊm @€ @€ @€Lƒ@„?¢KôR 0eãÞŸEŒé}­S 0eAV dh†©c*f˜òäGÊ0å±ÞÀG+ÆÔõøn;Æ”2L­G'ÃÔcº®ìèÊ0µ"]¦þS'ÆÑ‰1¥èFWŒ©Úè1e&1¦å¬ö,ÆtÔ±]¹¥B­¦ôRTrJ/ 0õ–n'ÀÔÂ+%Ô'óºÂy½¦…ˆÞèS+«7,ÃÔíõåöǘRz¯˜aÊbL­ ßèÓ•}y¾b†i!ÆÔJõµƒ}bLËù¡pnj" ÆT“…p @€ @€ @€MH=lÚ¡¥vt©«“ÍáGf1¦¦¼MjÂ4¬Óè Ó^·bz`¡S+Ætmw7¦E[1å1ެS¡M;ÃTLoä1¦‹S7¦®VL­nLw鯴ŸŠˆ1Eœ.Å•ºÊ5Ë-µ£KQÉyû¥LKÊ0E§±¥µbÊ3L[:-Ç¢à»{‹µbjw +4!ëkÅÔiEÖÝŠiS'É—‡ùÚmÉúZ1¥ÓšèÆÔaÊ[”m¸V7¦åød8'Õ ˆ1U¿î€ @€ @€ @ 1ÅðÇÀM¸^zä±ïýà‡{:0 ØH®» Sÿ\û0 È0µ:Ö¤íäòœÇB+¦ÞíäZÔ lÅôl;¹îVLKÛQn@+¦ÖŽrínL­ÓÀå"®aS¹Ò?)Æ´PŸÅ ã:{F%ÓKùæqÅÎa…-äú:0 0 ÜH.ßqô^r£ú0-9ôØvr½û'ÆFŠ­‚·Ó…M ;ÊhÅtEkwÅa1¦´ÍbŒKĘJÿT8!õcªÇ:¸  @€ @€ @€Fô„?ÚÝk ;ǽôÈcÞóo×îžÈB¦b€iÇO&?ŠÉ}ëû?I{ÉîÃ4*ÃÔ·\ÖŸæ¶ÔŠé¾æH£ôVL…SÿæYí¸FĘæÎúçýô—ùøÉÏ~Õˆb©lcŠ8]O¥žÐRTr¶kw]êm¡÷Roz©ØBìö¦‡u``êjÂtg¶=b]›$f¦¥î%·L¦«o¾':¥qU¶£Ü"ÛÉ-¥S1Æ”ï±XlÅ”bLO_ùÌâç"žÿG©¬ª\˜eˆ1•¡è @€ @€ @€Z=á…üGD@Z),Ætú‡ïØ9*ÿÑþµ÷VW€)ïXÓõøÑ­-·ôaZ,Ãtmw†ió7ïMµÚûjÝrol§•ƀǻ6µÆˆVLcúßý½ó.þưVL׈Ó»O;;21ù½_?,®1þG®c:¦˜Rêj֪ը䔴ëÎÛ ¨ÛžèR1½T á ÜBn`¦b€iŒ&LQä[o`kÞil¡Â³fcCö’³Ó3LC·“ëô$‹BŒÔ‡)u&{Þ!íMå²ÓuÙ(¶bJ1¦}÷{FñsÏ|HÂoüÏ…# ¨ƒ€SVÁ= @€ @€ @€4D`xø£•ÿØùàKŽ8æÝ§ŸÝß{©þèé^³h€i`¦ÖFrí½ä ½j–!ÃÔŽ12LY7š¯Æèd˜6mkǘº6Òj…6Rn£cÚ|ÙõY7¦Bb£ÝŠi`Œ)27bL{óI1¦bJ©»ÁRÔjcJ{ÇÝæå:°nS’&ÏÞõô^*¦—Ší—Æ 0õïØ›Ï‹ S+Àã†4¶Gz)û£ÍX>R¿±¼åX×+n$—…öй½ÂŠYzoi}˜ö4Ãtù–ì³bLy+¦ž “ÓÞÔ¿c ¨³€SWǽ @€ @€ @€L™@„?ú3ÅW^1¦Bo¡,ü1rã­Û~ø“´…\!öÑêÀT0µ:Ö Üo«¯ S'ä1,Þ10Ø‘ö’ëëô„ S§ÓÀ Ó­Æ3cZ×cJ‰j¤ÑßIŒi/?cŠ8ÝèB-VrOËŸ…È]§t÷,ºôƒŸÄNˆ ›!vWr±ýRq ¹½ 0nÂ40ԘڽǺ3LùFrÙ^r7 ÝKn¼ SŠ1ý]Š1õõaJŸ ݘöòSàpê) ÆTÏuqW @€ @€ @€S)áþÌGþJ$–"ÆtêigEì#íùh7^úit¬ÉšÖ H/ýdPzi‘ÓbÉ=Ç;®ûv¡9Mg#¹NgšeÈ0u¶ÐÊcL]‰N†IŒi9>cŠ:Q¨ñ[©’Û1»BØ®·n£€˜o:‡õt]*6^•^ê¤ñÚé¥bS±;þõ¦­ó±Ð]lT¦®&Ly‘lÂTìÃÔ߄难-³ÓÈ S¾b<¹rk{lܺsã½äR¦4Ú1¦!&1¦åø\8'ucªÃ*¸ @€ @€ @€†Dø#(õ>ú©‹c¤Ž5Ñr)Æñ'½'k¹”í±õÀß¼ñÄY·>F–öØþ@JuDÚcËö,äã’¯Ýú„'ïû•Ö¯yš÷ùÉÈvÄxŒlÇ_Þü¬çãÕ¯?!¥:yñÑÏúÓƒžù§ECšñåq'¼+¾Œñ©‹¯‰ñèÇ<ö¿<ñ©ç­¿fÓ»^uô3þë bdŽm;OûÈçW>ç1^pØËVÿÍ›¯hŘ:M˜î¾¬Ø‡©ÐxFŒiòÅ1¦ˆÓõjO­F%w3Ì+6OÚuÕm§t{ö:Ì÷=Œ¬Rp$ðRË¥Èá}ê¢+Ÿó¼ƒ£€SË¥H)wáÆ(æ7¿ýݶúo².b­ôRÔs*é(ã“ßsVD‘¾ºõû]úë7œ# ûs—|#•tJ,åã³_ÙÜÊ-uzŒ}óÞ“N=3Š‘ŽÈsį¿øès¼ëƒçFn#6ÒzåkOyŽHr¼þøµ`zÇÎGd8þãcþàìO]ò/_ûÎ~ÂSÿ2bLí]äºL…ͳR\CŒiò¥žÅ˜^rôèBí­äVÀnDݦÄR±tóç­ìÝòMâ"º¡¥(ãvt©ÕB,ž¯»pã…—^q¥È-Ee7ŒK1¦O~þŠˆ.Å>q×Þ1¦bD×¥´[\”w¼I¦Î¶q÷ýÕëOˆßÊwŽË{/½úu'DµG‘ì‚Ëýû]¿ñ¦h¼u~Ù7îˆ&L‘^ŠöKÑo,ÒKÑr,~ÜRTû®¸1ê?ýzÐa/‹²âçQöÑ{ìßÚг…bO†oLbL“ÿD¸"È»1¥$ÒĘ" •Z1å1¦ /žË @€ @€ @€L‘@„?ò4Ÿ¼è%/‹ÓÀ´G¼˜š-åH/E¼#Û-.¢KÇeÑ¥Ô¢¦Ý{©Ðu)Õä»kEÈ#¥—¢÷R$<"ÞãßÌ‚1ò}µ"Àô¸'í˜Z;jŸ'RéH#òm¼éqO|jt`J[È¥G¾…V4¡YýÚãÓþq)À饔Þ8þ”3þò5onõaÚqÙõÙÈv‘+˜6\—˜Ä˜ª*ìˆ1EŽ.ÔþJV´ÃâJ©ŒÛ{Ãuž¤ S$–Ò>q­'Y¿¥,¥ô…+bĔƋS÷nq÷G=âó—g…ý¤}£—Ø_½á„‘Ì‹>Lyt©¸m\´\ŠwfåFgÛ¸¨ùOÿË5Wß|O¤ô^öò×D³±¨öW¾î-ió¸(ø¨öDŒéµÇ§šSÔ|Œ(øÞñ¡xåÃçoˆôRŒh<é¥h®K€Àr Dû¥|ƒ¸t­¥Æ˜â°ž S,Æ´Ü æü @€ @€ @€Ó+áÑi½øeÿðî¹bV)-u>¶?{lÅÖZ'¿÷ìbt)µ¨I1¦ÈyDò#¢ÿøî³òmã¢?MŒÔx)‹z´¢Kñžè½ÁŽ|ó¸v|ü‚,Æ”6‹©Žˆ.¥HÇ+ÿ6Æñ67Z.E˜#ºÑĈGl¡•bL±…\cje˜"Æã¬óÚ1¦ˆnœµî’ˆ1¥S;½QØE®'±¡Óä«=‹1½øe£ µXÉívJÝ»¼nû³Ji£Ã4:{ÃeON~ïYWZ÷…+R§èÒÂóÏgÅüìç#®ù¤-¥z.v]J»ÅEã¥(ì“N=ë…/9:k¹ãÖ{ãõ¼ëR;¥×I/E…GhéŒ]—¾¸ñ¦¨ö«n¾'ÕyYV怜ÇX|ô‹:O5äûëcŠÛ&Fã±Nï¥VŒé†»£ñXÿ€öK ßÀ߆NŒ¯?À¤Óä?®H€ÀÄ"tÔ“aŠK/)ÆÔŸ~J7-Æ4±Ås! @€ @€ @€©ˆøE1ÞÑQzaĘNýP;±Ô‰zô¤=¢9͆«o Sòˆ¨Ç6|#b©EMä<>É7¾|Õ-‘ÛÈZÔ´r±¯V{|ó¾g=÷ HxD㥬÷Ò­÷¾ðÅGG€)¶‹í´Rï¥gþéAúø…cŠŒ'›nø~4[ÊBKÜRöB=· ;byç|öòVã¥{S2/Jú3ÿòõ<º”vEŒò.6^zÛ»æR…§ ã"À•Ü[Þ—bDyŸwñ5Ñx)FÊêEŒ)~ýÈù"½ÕûÇÅæq©÷R<ÿÄEWgeßé½e饈1|Ú9­ÊÏÆ¢í— 0‰1MþáŠLF G±)\ÿµ1ÍÏÏÇ–âøô(&¡Ä˜&³x®B€ @€ @€ 0ñ¯lÅö3ýÏ#ÆtÒ»>4,ê‘g>}é1‘ÏÈÇ_¿áÄH{󗯉´GŒØ$.rKñkñ=­ ã²GŒ”íH#/ÍsQj¼1¦x#žD¶ãmèÒ3ÿëA±—V¤:b/­v¤‘ÒKñ$‚1âIJ/½îøµ±…Ü[N9#ÂéHãø“ÏˆGüÏŸþì<4ß¼yÑ“M媪ðˆ1EŽ.Ô!•ÜÊ' J)KéyWŠÒ¦b¹¦ø]´\Š|RŒx÷YÅÜRk{¸(æ4²’Žd^4XÊ«:j8bLQÛ¯~Ý ñ<ÂIíÝâ:­Å¢¼ÏÿÒ5ÙëOÜ7Fd˜ÞõÁs£È/Üxcªêøõ¨?ÿë(òÔiiÓ¶]‘[Š×ã×è:¡½È-EÁGû¥ˆ+Eañg¡½xž÷^zús^eÿ·Ÿ}"Þ|ò]íÇ|í ßÓKyÂϦrU}:\—eX»vmÄ•ò$ÒÜÜ\~¡ÅcL»wïÞRxlß¾=?¸ø|™nÝi  @€ @€ @€L©@„?úóÅWYuTĘòWz¢)ð±°C\¡?MOsšžGÚT«]Š„Gj¼TÜ6.u¦I;j]uSŒ¬'MÚN+ß<î’¯7E:bDÔ#¶ÐJÝh6fãîHr¤ý³bD†ã⫾Sì@“µ_j86ŒìÀ¤Sµå1¦¨ÃÑ…:¢’ÛEÛê¨4p\{ÛýíÖJ…îjVhö¥M·ôsÖB¬»žó­âRUçý–Öv¡¼ÛÑ¥¼Èó:Oí—Rç#•zOÁk>•ýô^ºî®aÛÆ~]Œ©Úψ« Pº@ÄŠI¤&å—ˆ×óçû”~a'$@€ @€ @€ 0³þ–íH¯G|äíïüP+¨48ê10í±hÎ#‹w Jxä¹¥aÑ¥bª£+ϱ- sD+š³?µ! 0ÝP0-Ä8vä[h`Ò©ªIŠ1.ÔžJn•k_Ñv§”†•R¯Pà =–Ú‰¥!¼!%¢KÅÂn×v!™W çõä–òˆÞBt©Uê…èRwµB{ôÒBÙ·wNìï½4nzI7¦ª>®K€@MĘj²nƒ @€ @€ @  þˆ0ǰaŽƒWõ¶µgô´VÊ¿ìŽzd{i-’óhw¦Yh¹Ô“ðȺ.eñŽB×¥Bã¥þ†4=yŽO\øµžöK)ÉÑŸ^ZèÀtížµŸùG=úÜ/nÑ™&ÚÒ¼û´³oßñ`>îܵû×?Ò„r©h)Æ4¢Pã·¢’‡UéÀ×ûRJƒ²J#z,uBxý–úCKýý–ÚÍ–ZµFªíöètÞu©]Ñxéò-“H/‰1Uô™pYê" ÆT—•p @€ @€ @€ ÈÂß¼/ýÙŽƒ;ê­kÏè¼Þ* ‹+uí¥µÐl©+´4$·´'Ñ¥Þn4];ÇwÑÊÓKí&4×íÙþq³JbL“/ûˆ1EœnH“¤vÛ¤¨ä!ɤxິ\Úå°Ý*,ÒÊÞ Œ+ L,õ‡–š- Í-umé¥+ E^Ü!±'·Ô³gÜàèRï¥=Œî-e›9›ÊMþsáŠÔA@Œ©«à @€ @€ @€"ᯧQ´ ¿uó=ýÜ•UWÖf)K,í*òÒóžfK~Kƒ·ŠÝr©˜Õ‹­vKl…ö–ÒH©”÷ˆ1MþsáŠÔA@Œ©«à @€ @€ @€"áÑ!zä §|pDÂc¡ÁR;çÑ×fx£'Þ1h#­ÑÑ¥Á—ŠIŽR"Å“ˆ1M¾ô³Ó¡GŽ.Ôv%ß|ÏÕ#I+9먔F__¥®ýà •=–ºxéËA‰¥Q¡¥N³¥=Ú*n!·ÔÕr©œfcc^Ę&ÿ¹pEê ÆT‡Up @€ @€ @€ ˆðGoË™<ÒÑz1¦·œüÁñŽÞ„G„<öXžð‘[ê vº.-]ZÖ&4bL“/ýˆ1EËÒ¥RTr_ip,iÀÖo©t ªzRJí2TêÍ*uº+ Ž+Mg¥%f˜âmbL“ÿ\¸"ucªÃ*¸ @€ @€ @€†Døãò‘yŽçEŒé¤Ó;ïÉz)-;†d;†µ¢éo³ûg-='Q“wŠ1M¾ô#Æu8ºP«ä¾ÒÒE)ª7—F2©gt† ,æ´\ŒšÔê$oCŒiòŸ W$@ bLuX÷@€ @€ @€ ÐsýÏŸwÈkN:-½> ÕQè@Ó½\aÛ¬Èv4¨ÓäK?‹1rÄèBQɃë6¯çB2©¯†ûʸA•\nÈIŒiòŸ W$@ bLuX÷@€ @€ @€ ÐûÊ7ŽøG¼ß³ž_xÃqǾrÐxÅqÇÌÆø·ÿî·;rõˆÉ>öþøÝ§}ûŽóqç®Ý¿~ø‘†TLÓˆSÔáèB]´’×m^̯8îØÙ(àeúœFÙï÷Ìç8yäœöÝïÅÏE<ð¡_UQP®I€ÒĘJ£t" @€ @€ @€§Ÿ~úI…ljo}ûß¾ñ-ÅñâÃùóW¼¦çÅYþòùúš×½i´À¦Í·Š1•øáºóÎ;‹UÏßø¦{–à¹Ï?x–˲ò¹/åÅY=_Œ©ÄÏ…S P1¦:¬‚{ @€ @€ @€h¦ÀÏùpOÎÀ—{/ S韖÷ÿ|ï×Å*Щô† 0a1¦ ƒ» @€ @€ @€À ˆ1-G°CŒ©ôÓrêäÏ)ÆTúGà ˜°€Ó„Á]Ž @€ @€ @`†Ę–#É!ÆTúGHŒi9 uòçc*ý£á„LX@ŒiÂà.G€ @€ @€ 0CbLË‘äc*ý#$Æ´…:ùsŠ1•þÑpB&, Æ4ap—#@€ @€ @€˜!_ü÷‡'ehüï¸{÷¯~d†Êhù§z÷ý5¾lfa‚bLËÿYq–W@Œiy} @€ @€ @`Æ"É=™FŒŸýâ×£ß0k¿»(È/õðŒUéÓXØ¢e¶èº,zoØ¥ø—^NH€ ˆ1MÜå @€ @€ @€ @€ècR @€ @€ @€ @€T, ÆTñ¸< @€ @€ @€ @€bLj€ @€ @€ @€ @€ŠĘ*^—'@€ @€ @€ @€ @@ŒI  @€ @€ @€ @€ P±€SÅ àò @€ @€ @€ @€ˆ1© @€ @€ @€ @€*cªx\ž @€ @€ @€ @€1&5@€ @€ @€ @€ @€@ÅbL/€Ë @€ @€ @€ @€ Ƥ @€ @€ @€ @€¨X@Œ©âpy @€ @€ @€ @€ĘÔ @€ @€ @€ @€ ˆ1U¼.O€ @€ @€ @€ @€€“ @€ @€ @€ @€ @ b1¦ŠÀå  @€ @€ @€ @€cR @€ @€ @€ @€T, ÆTñ¸< @€ @€ @€ @€bLj€ @€ @€ @€ @€ŠĘ*^—'@€ @€ @€ @€ @@ŒI  @€ @€ @€ @€ P±€SÅ àò @€ @€ @€ @€ˆ1© @€ @€ @€ @€*cªx\ž @€ @€ @€ @€1&5@€ @€ @€ @€ @€@ÅbL/€Ë @€ @€ @€ @€ Ƥ @€ @€ @€ @€¨X@Œ©âpy @€ @€ @€ @€ĘÔ @€ @€ @€ @€ ˆ1U¼.O€ @€ @€ @€ @€€“ @€ @€ @€ @€ @ b1¦ŠÀå  @€ @€ @€ @€cR @€ @€ @€ @€T, ÆTñ¸< @€ @€ @€ @€bLj€ @€ @€ @€ @€ŠĘ*^—'@€ @€ @€ @€ @@ŒI  @€ @€ @€ @€ P±€SÅ àò @€ @€ @€ @€ˆ1© @€ @€ @€ @€*cªx\ž @€ @€ @€ @€1&5@€ @€ @€ @€ @€@ÅbL/€Ë @€ @€ @€ @€ Ƥ @€ @€ @€ @€¨X`‘ÓöíÛ{n°ÿ•Šgàò @€ @€ @€ @€Ô[`gëQ¼ÇžW†Æ˜Ö¬Y³²óHÑ¥þWê=wwG€ @€ @€ @€ @€@õ«V­Ê“Hénú_cЬS™ŽY¿~}ÖÿJõós @€ @€ @€ @€Ô[`ݺu«W¯N÷}”æææú_‰ßÚ)ß<.Řâ­ý¯Ô[ÀÝ @€ @€ @€ @€ P±ÀîÖ#ÝDŠ1õ¿¿54Æ”ß~´ešŸŸ/Φÿ•Šçêò @€ @€ @€ @€Ô[`Ë–-+V¬(Þcñ•Q1¦h¿‰¥hâ”ÜÿJ½çîî @€ @€ @€ @€¨^ v„‹$Rä–ò[éyehŒ)މ#ãÝù‘ý¯T??w@€ @€ @€ @€ @€@½¢R$‘¢ƒR~›ý¯ 1E§Øˆ.¢KñH§è¥ÞÓww @€ @€ @€ @€T,0??¹£ø5%‘vïÞÝÿJÜâàSjÙ”?V¯^ÝÿJÅósy @€ @€ @€ @€j/°fÍšb):+õ¿“Ú©ötƒ @€ @€ @€ @€4D@Œ©! i @€ @€ @€ @€¦W@Œiz×Î @€ @€ @€ @€hˆ€SCÒ4 @€ @€ @€ @€L¯€Óô®;'@€ @€ @€¡÷ð5K¾IDAT @€ Ð1¦†,¤i @€ @€ @€ @€˜^1¦é];wN€ @€ @€ @€ @ !bL YHÓ @€ @€ @€ @€ 0½bLÓ»vîœ @€ @€ @€ @€@CƲ¦A€ @€ @€ @€ @`zʦwíÜ9 @€ @€ @€ @€†ˆ15d!Mƒ @€ @€ @€ @€Àô ˆ1MïÚ¹s @€ @€ @€ @€ cjÈBš @€ @€ @€ @€écšÞµsç @€ @€ @€ @€" ÆÔ…4  @€ @€ @€ @€Ó+ Æ4½kçÎ  @€ @€ @€ @€4D@Œ©! i @€ @€ @€ @€¦W@Œiz×Î @€ @€ @€ @€hˆ€SCÒ4 @€ @€ @€ @€L¯€Óô®;'@€ @€ @€ @€ Ð1¦†,¤i @€ @€ @€ @€˜^1¦é];wN€ @€ @€ @€ @ !bL YHÓ @€ @€ @€ @€ 0½bLÓ»vîœ @€ @€ @€ @€@CƲ¦A€ @€ @€ @€ @`zʦwíÜ9 @€ @€ @€ @€†ˆ15d!Mƒ @€ @€ @€ @€Àô ˆ1MïÚ¹s @€ @€ @€ @€ cjÈBš @€ @€ @€ @€écšÞµsç @€ @€ @€ @€" ÆÔ…4  @€ @€ @€ @€Ó+ Æ4½kçÎ  @€ @€ @€ @€4D@Œ©! i @€ @€ @€ @€¦W@Œiz×Î @€ @€ @€ @€hˆ€SCÒ4 @€ @€ @€ @€L¯€Óô®;'@€ @€ @€ @€ Ð1¦†,¤i @€ @€ @€ @€˜^1¦é];wN€ @€ @€ @€ @ !bL YHÓ @€ @€ @€ @€ 0½bLÓ»vîœ @€ @€ @€ @€@CƲ¦A€ @€ @€ @€ @`zʦwíÜ9 @€ @€ @€ @€†ˆ15d!Mƒ @€ @€ @€ @€Àô ˆ1MïÚ¹s @€ @€ @€ @€ cjÈBš @€ @€ @€ @€écšÞµsç @€ @€ @€ @€" ÆÔ…4  @€ @€ @€ @€Ó+ Æ4½kçÎ  @€ @€ @€ @€4D@Œ©! i @€ @€ @€ @€¦W@Œiz×Î @€ @€ @€ @€hˆ€SCÒ4 @€ @€ @€ @€L¯€Óô®;'@€ @€ @€ @€ Ð1¦†,¤i @€ @€ @€ @€˜^1¦é];wN€ @€ @€ @€ @ !bL YHÓ @€ @€ @€ @€ 0½bLÓ»vîœ @€ @€ @€ @€@CƲ¦A€ @€ @€ @€ @`zʦwíÜ9 @€ @€ @€ @€†ˆ15d!Mƒ @€ @€ @€ @€Àô ˆ1MïÚ¹s @€ @€ @€ @€ cjÈBš @€ @€ @€ @€écšÞµsç @€ @€ @€ @€" ÆÔ…4  @€ @€ @€ @€Ó+ Æ4½kçÎ  @€ @€ @€ @€4D@Œ©! i @€ @€ @€ @€¦W@Œiz×Î @€ @€ @€ @€hˆÀ¨ÓüüüÜÜÜöíÛó¹Æ+ëÖ­Û¹sgCfo @€ @€ @€ @€,¿@„ŽzrGñe„‘ò+1­ZµjõêÕk×®]¹råúõëã€â+’LË¿v®@€ @€ @€ @€ @  +V¬X³fMJ"¥ÜQz%ñJšáàSt`Êß±eË–t|ĘÒ1qÆx4AÈ @€ @€ @€ @€XNØ.âJé )w=•òW"˜ñ¤ø­Q›Ê¥ƒãDÑ–)¿ÕÈ3ÅÁņNË9 ç&@€ @€ @€ @€ @ !CнäòÉDi‘nLù[#ëœò-äR—¦xÄ“†Ø˜ @€ @€ @€ @€Ë/¦<´WK_æÄêÆo SêÚT|D[§â— ®@€ @€ @€ @€ @€À Ä.rGñzl3cJq§¼S<É·–‹`“Ó…['@€ @€ @€ @€ 0AÈåÑ£¸l4Qš››K× Ó¨S„–¢SÊ:Å#Ñ¥x’2Lé` @€ @€ @€ @€ŒH;Â¥R<æççS6)ÂLñˆ'ñJ>¸Sü^~dcŠããy£âÔè  @€ @€ @€ @€ °¨@dŠI¤ZŠ_£ÅR<Ò—ñº©Ü¢ð @€ @€ @€ @€”" ÆT £“ @€ @€ @€ @€ 0¾€ÓøvŽ$@€ @€ @€ @€ @ 1¦R„ @€ @€ @€ @€ñĘƷs$ @€ @€ @€ @€¥ˆ1•Âè$ @€ @€ @€ @€Œ/ Æ4¾#  @€ @€ @€ @€(E@Œ©F'!@€ @€ @€ @€ @`|1¦ñíI€ @€ @€ @€ @€@)bL¥0:  @€ @€ @€ @€ã ˆ1oçH @€ @€ @€ @€Jc*…ÑI @€ @€ @€ @€_@Œi|;G @€ @€ @€ @€ PŠ€S)ŒNB€ @€ @€ @€ @€ÀøbLãÛ9’ @€ @€ @€ @€RĘJat @€ @€ @€ @€ÆcßΑ @€ @€ @€ @€”" ÆT £“ @€ @€ @€ @€ 0¾€ÓøvŽ$@€ @€ @€ @€ @ 1¦R„ @€ @€ @€ @€ñĘƷs$ @€ @€ @€ @€¥ˆ1•Âè$ @€ @€ @€ @€Œ/ Æ4¾#  @€ @€ @€ @€(E@Œ©F'!@€ @€ @€ @€ @`|1¦ñíI€ @€ @€ @€ @€@)bL¥0:  @€ @€ @€ @€ã ˆ1oçH @€ @€ @€ @€Jc*…ÑI @€ @€ @€ @€_@Œi|;G @€ @€ @€ @€ PŠ€S)ŒNB€ @€ @€ @€ @€ÀøbLãÛ9’ @€ @€ @€ @€RĘJat @€ @€ @€ @€ÆcßΑ @€ @€ @€ @€”" ÆT £“ @€ @€ @€ @€ 0¾€ÓøvŽ$@€ @€ @€ @€ @ 1¦R„ @€ @€ @€ @€ñĘƷs$ @€ @€ @€ @€¥ˆ1•Âè$ @€ @€ @€ @€Œ/ Æ4¾#  @€ @€ @€ @€(E@Œ©F'!@€ @€ @€ @€ @`|1¦ñíI€ @€ @€ @€ @€@)bL¥0:  @€ @€ @€ @€ã ˆ1oçH @€ @€ @€ @€Jc*…ÑI @€ @€ @€ @€_@Œi|;G @€ @€ @€ @€ PŠ€S)ŒNB€ @€ @€ @€ @€ÀøbLãÛ9’ @€ @€ @€ @€RĘJat @€ @€ @€ @€ÆcßΑ @€ @€ @€ @€”" ÆT £“ @€ @€ @€ @€ 0¾€ÓøvŽ$@€ @€ @€ @€ @ 1¦R„ @€ @€ @€ @€ñĘƷs$ @€ @€ @€ @€¥ˆ1•Âè$ @€ @€ @€ @€Œ/ Æ4¾#  @€ @€ @€ @€(E@Œ©F'!@€ @€ @€ @€ @`|1¦ñíI€ @€ @€ @€ @€@)bL¥0:  @€ @€ @€ @€ã ˆ1oçH @€ @€ @€ @€Jc*…ÑI @€ @€ @€ @€_@Œi|;G @€ @€ @€ @€ PŠ€S)ŒNB€ @€ @€ @€ @€ÀøbLãÛ9’ @€ @€ @€ @€RĘJat @€ @€ @€ @€ÆcßΑ @€ @€ @€ @€”" ÆT £“ @€ @€ @€ @€ 0¾€ÓøvŽ$@€ @€ @€ @€ @ ¡1¦õëׯ\¹rÅŠ«V­*^i~~¾ç•RîÃI @€ @€ @€ @€h¤ÀÚµk#‰5kÖ'¯Ç#½24Ʀ-[¶Ä;æææV¯^Þ½{÷îx=ÎØH/“"@€ @€ @€ @€ @ \èšq£ÈÅi#†´nݺtþx=’H‹Ä˜â°H/¥"Ì”ç–âDñºS¹Kål @€ @€ @€ @€š*q¥x¤ÙÛ/¥æL‹wcÊ]b ¹”ŠSYL55Õμ @€ @€ @€ @€(W m·sçÎ8mtSZ¿~ý’6•K7¤åâøÈ3Å1¦r—ÇÙ @€ @€ @€ @€4^ ÒGÑ~)uSŠStSŠ'K1¥ÆMÉ(މ/#É¿F**e›< @€ @€ @€ @€ 0Z 'Eâ(e˜â‘2Hñk¼˜¿¾Ï°SÄ[c¹þßÕIÙ @€ @€ @€ @€ °DèÃY¥õ¿ñnL}JY§ôHÛÉ¥Gœ±øåïÆÛ @€ @€ @€ @€˜AØö­˜DŠèRްxŒi½L™ @€ @€ @€ @€ª†n*WÕ ¹. @€ @€ @€ @€³& Æ4k+n¾ @€ @€ @€ @€j' ÆT»%qC @€ @€ @€ @€fM@ŒiÖVÜ|  @€ @€ @€ @€ÔN@Œ©vK↠@€ @€ @€ @€Ìš€Ó¬­¸ù @€ @€ @€ @€¨€Sí–Ä  @€ @€ @€ @€˜51¦Y[qó%@€ @€ @€ @€ P;1¦Ú-‰"@€ @€ @€ @€ 0kbL³¶âæK€ @€ @€ @€ @ vbLµ[7D€ @€ @€ @€ @`ÖĘfmÅÍ— @€ @€ @€ @€@íĘj·$nˆ @€ @€ @€ @€À¬ ˆ1ÍÚŠ›/ @€ @€ @€ @€Ú ˆ1ÕnIÜ @€ @€ @€ @€Ycšµ7_ @€ @€ @€ @€µcªÝ’¸! @€ @€ @€ @€³& Æ4k+n¾ @€ @€ @€ @€j' ÆT»%qC @€ @€ @€ @€fM@ŒiÖVÜ|  @€ @€ @€ @€ÔN@Œ©vK↠@€ @€ @€ @€Ìš€Ó¬­¸ù @€ @€ @€ @€¨€Sí–Ä  @€ @€ @€ @€˜51¦Y[qó%@€ @€ @€ @€ P;1¦Ú-‰"@€ @€ @€ @€ 0kbL³¶âæK€ @€ @€ @€ @ vbLµ[7D€ @€ @€ @€ @`ÖĘfmÅÍ— @€ @€ @€ @€@íĘj·$nˆ @€ @€ @€ @€À¬ ˆ1ÍÚŠ›/ @€ @€ @€ @€Ú ˆ1ÕnIÜ @€ @€ @€ @€Ycšµ7_ @€ @€ @€ @€µcªÝ’¸! @€ @€ @€ @€³& Æ4k+n¾ @€ @€ @€ @€j' ÆT»%qC @€ @€ @€ @€fM@ŒiÖVÜ|  @€ @€ @€ @€ÔN@Œ©vK↠@€ @€ @€ @€Ìš€Ó¬­¸ù @€ @€ @€ @€¨€Sí–Ä  @€ @€ @€ @€˜51¦Y[qó%@€ @€ @€ @€ P;1¦Ú-‰"@€ @€ @€ @€ 0kbL³¶âæK€ @€ @€ @€ @ vbLµ[7D€ @€ @€ @€ @`ÖĘfmÅÍ— @€ @€ @€ @€@íĘj·$nˆ @€ @€ @€ @€À¬ ˆ1ÍÚŠ›/ @€ @€ @€ @€Ú ˆ1ÕnIÜ @€ @€ @€ @€Ycšµ7_ @€ @€ @€ @€µcªÝ’¸! @€ @€ @€ @€³& Æ4k+n¾ @€ @€ @€ @€j' ÆT»%qC @€ @€ @€ @€fM@ŒiÖVÜ|  @€ @€ @€ @€ÔN@Œ©vK↠@€ @€ @€ @€Ìš€Ó¬­¸ù @€ @€ @€ @€¨€Sí–Ä  @€ @€ @€ @€˜51¦Y[qó%@€ @€ @€ @€ P;1¦Ú-‰"@€ @€ @€ @€ 0kbL³¶âæK€ @€ @€ @€ @ vbLµ[7D€ @€ @€ @€ @`ÖĘfmÅÍ— @€ @€ @€ @€@íĘj·$nˆ @€ @€ @€ @€À¬ ˆ1ÍÚŠ›/ @€ @€ @€ @€Ú ˆ1ÕnIÜ @€ @€ @€ @€Ycšµ7_ @€ @€ @€ @€µcªÝ’¸! @€ @€ @€ @€³& Æ4k+n¾ @€ @€ @€ @€j'0*Æ4???77·}ûöt×»wïÞÒyÄóÚMÅ  @€ @€ @€ @€ PKu­ÇÎ;ÓÝE$)O"¥W†Æ˜V­Zµzõêµk×®\¹rýúõñÖx¾bÅŠø2oªå|Ý @€ @€ @€ @€õˆÐÑš5kR)%™R)=R—¥Á1¦ø½xGšMäžÒó6ÅózMÑÝ @€ @€ @€ @€ Pcè—¦tƒ‘dŠG<‰`SÏ-ÚT.½5Nm™âI„™âŒñk:— @€ @€ @€ @€–.1¤´µ\dây¾M\œa‘S´_ŠèSjåݘbw¹x%N‘'¤–~ÞI€ @€ @€ @€ @€ÀÌ D€)m ;Å¥}áÒ6qIŠGŘâÈÈ0õo$©¦þ¶N3ëkâ @€ @€ @€ @€ŒH»Àõ¿'JiŠ×‡Æ˜Rú)õaŠÇîÝ»ó½ä"%Ƥò @€ @€ @€ @€XŠ@lþüóóó‘MJ_ÎÍÍ¥ßcJý–"Ñ¥xÄ»ã­ñJ¼‡ @€ @€ @€ @€ÙH;Â¥R<"Ãx%ö’‹G$‘¢§RÈ Ž1Å[ó#óSd›ây¤ŸÒvt @€ @€ @€ @€-1¦b)‚Iñþø5Z,Å#e˜â1tS9¾ @€ @€ @€ @€˜Œ€Ódœ]… @€ @€ @€ @€¡bLŠƒ @€ @€ @€ @€ŠĘ*^—'@€ @€ @€ @€ @@ŒI  @€ @€ @€ @€ P±€SÅ àò @€ @€ @€ @€ˆ1© @€ @€ @€ @€*cªx\ž @€ @€ @€ @€1&5@€ @€ @€ @€ @€@ÅbL/€Ë @€ @€ @€ @€ Ƥ @€ @€ @€ @€¨X@Œ©âpy @€ @€ @€ @€ĘÔ @€ @€ @€ @€ ˆ1U¼.O€ @€ @€ @€ @€€“ @€ @€ @€ @€ @ b1¦ŠÀå  @€ @€ @€ @€cR @€ @€ @€ @€T, ÆTñ¸< @€ @€ @€ @€bLj€ @€ @€ @€ @€ŠĘ*^—'@€ @€ @€ @€ @@ŒI  @€ @€ @€ @€ P±€SÅ àò @€ @€ @€ @€ˆ1© @€ @€ @€ @€*cªx\ž @€ @€ @€ @€1&5@€ @€ @€ @€ @€@ÅbL/€Ë @€ @€ @€ @€ Ƥ @€ @€ @€ @€¨X@Œ©âpy @€ @€ @€ @€ĘÔ @€ @€ @€ @€ ˆ1U¼.O€ @€ @€ @€ @€€“ @€ @€ @€ @€ @ b1¦ŠÀå  @€ @€ @€ @€cR @€ @€ @€ @€T, ÆTñ¸< @€ @€ @€ @€bLj€ @€ @€ @€ @€ŠĘ*^—'@€ @€ @€ @€ @@ŒI  @€ @€ @€ @€ P±€SÅ àò @€ @€ @€ @€ˆ1© @€ @€ @€ @€*cªx\ž @€ @€ @€ @€1&5@€ @€ @€ @€ @€@ÅbL/€Ë @€ @€ @€ @€ Ƥ @€ @€ @€ @€¨X@Œ©âpy @€ @€ @€ @€ĘÔ @€ @€ @€ @€ ˆ1U¼.O€ @€ @€ @€ @€€“ @€ @€ @€ @€ @ b1¦ŠÀå  @€ @€ @€ @€cR @€ @€ @€ @€T, ÆTñ¸< @€ @€ @€ @€bLj€ @€ @€ @€ @€ŠĘ*^—'@€ @€ @€ @€ @@ŒI  @€ @€ @€ @€ P±€SÅ àò @€ @€ @€ @€ˆ1© @€ @€ @€ @€*cªx\ž @€ @€ @€ @€1&5@€ @€ @€ @€ @€@ÅbL/€Ë @€ @€ @€ @€ Ƥ @€ @€ @€ @€¨X@Œ©âpy @€ @€ @€ @€ĘÔ @€ @€ @€ @€ ˆ1U¼.O€ @€ @€ @€ @€€“ @€ @€ @€ @€ @ b1¦ŠÀå  @€ @€ @€ @€cR @€ @€ @€ @€T, ÆTñ¸< @€ @€ @€ @€bLj€ @€ @€ @€ @€Š†Æ˜vîܹfÍšU«VÍÍÍå÷Ï{^©øö]ž @€ @€ @€ @€z ÌÏϯn=Ö¯_Ÿît÷îÝ)›”¿24Æ´råÊ-mÙ²%Ž_»vmOâàâ+õž¾»#@€ @€ @€ @€ @ b覴bÅŠˆ+Eî("IiŠŠ'ëÖ­+¾28Æ´}ûö-¥¤wÇéâ×|Nñ†Šççò @€ @€ @€ @€Ô^ âJùvpÑM)ñJžMŠTRtfŠI íÆ”O0:0ÅÁ)Ì”Z9åg©=‚$@€ @€ @€ @€ @ .©S„‘"€1¤x¤mââ±HŒ)¢O© SĘ¢¹Sêé”vª«ËäÜ @€ @€ @€ @€µÈCG]J»ÃE¦´»\Üû¨S™o$—º1¥ÉŸ×~ún @€ @€ @€ @€Š"z”7NJ[˥ʟ1õ´\ŠôStcJGO¦<ÒTñü\ž @€ @€ @€ @€z ä-—ÒmFû¥ØN.=_³fMŠ4 Ž1EPiŸ}ö‰ãÓ#%¡â˜x’z:¥Ýå< @€ @€ @€ @€ 0B âFÑ>)O"ÍÍÍÅ›ãË#Å#žÄÖrñÊàSü^ì—?¶oßž®OâDÑ™ = @€ @€ @€ @€ˆÄQ1‰”BKñˆ>JÑ–)?|è¦r‹^À @€ @€ @€ @€ PŠ€S)ŒNB€ @€ @€ @€ @€ÀøbLãÛ9’ @€ @€ @€ @€RĘJat @€ @€ @€ @€ÆcßΑ @€ @€ @€ @€”" ÆT £“ @€ @€ @€ @€ 0¾€ÓøvŽ$@€ @€ @€ @€ @ 1¦R„ @€ @€ @€ @€ñĘƷs$ @€ @€ @€ @€¥ˆ1•Âè$ @€ @€ @€ @€Œ/ Æ4¾#  @€ @€ @€ @€(E@Œ©F'!@€ @€ @€ @€ @`|1¦ñíI€ @€ @€ @€ @€@)bL¥0:  @€ @€ @€ @€ã ˆ1oçH @€ @€ @€ @€Jc*…ÑI @€ @€ @€ @€_@Œi|;G @€ @€ @€ @€ PŠ€S)ŒNB€ @€ @€ @€ @€ÀøbLãÛ9’ @€ @€ @€ @€RĘJat @€ @€ @€ @€ÆcßΑ @€ @€ @€ @€”" ÆT £“ @€ @€ @€ @€ 0¾€ÓøvŽ$@€ @€ @€ @€ @ 1¦R„ @€ @€ @€ @€ñĘƷs$ @€ @€ @€ @€¥ˆ1•Âè$ @€ @€ @€ @€Œ/ Æ4¾#  @€ @€ @€ @€(E@Œ©F'!@€ @€ @€ @€ @`|1¦ñíI€ @€ @€ @€ @€@)bL¥0:  @€ @€ @€ @€ã ˆ1oçH @€ @€ @€ @€Jc*…ÑI @€ @€ @€ @€_@Œi|;G @€ @€ @€ @€ PŠ€S)ŒNB€ @€ @€ @€ @€ÀøbLãÛ9’ @€ @€ @€ @€RĘJat @€ @€ @€ @€ÆcßΑ @€ @€ @€ @€”" ÆT £“ @€ @€ @€ @€ 0¾€ÓøvŽ$@€ @€ @€ @€ @ 1¦R„ @€ @€ @€ @€ñĘƷs$ @€ @€ @€ @€¥ˆ1•Âè$ @€ @€ @€ @€Œ/ Æ4¾#  @€ @€ @€ @€(E@Œ©F'!@€ @€ @€ @€ @`|1¦ñíI€ @€ @€ @€ @€@)bL¥0:  @€ @€ @€ @€ã ˆ1oçH @€ @€ @€ @€Jc*…ÑI @€ @€ @€ @€_@Œi|;G @€ @€ @€ @€ PŠ€S)ŒNB€ @€ @€ @€ @€ÀøbLãÛ9’ @€ @€ @€ @€RĘJat @€ @€ @€ @€ÆcßΑ @€ @€ @€ @€”" ÆT £“ @€ @€ @€ @€ 0¾€ÓøvŽ$@€ @€ @€ @€ @ 1¦R„ @€ @€ @€ @€ñĘƷs$ @€ @€ @€ @€¥ˆ1•Â8ÎIV­Zµ}ûöqŽt n¨¥•­ÇÚµk×­[‡‡$°sçÎ5kÖÄG#>#ëׯÇB`ùÒ÷áø5¾ÏÍÍ-ß…œ™@.ÿ×?ý °zõj8FÄ·¦T* FLF þƒ˜ÿ e2Wt•:ÄŒŠ?Ås?Õa]ÜÃ0¨X/7 'dâ§MÅ“ ô|C‹¿jðã÷¬•‡OĬ­øŒÌ7¾•õÔ¶ïoÓ¸ô±ˆóóóùû §¸ˆñ#M€¤¿7+*MãB»g=©¶ãߺã/aüÑF…4O@Œ©š5¬‰pª†¾‰W]±bÅ–Ö#~‹º’djâ"›Ó D†)>ñWùGC’i°d(¶øÞ›Š-ýùaɇz#1òªK?ø“꘎3sXüuFü¥Fª33Ë^ÍDwïÞß ¢äR±ùÏb5ËPÑUÓÿZ“_<ž¿¬è¦\–ÀP¨Øø6h @ÈÄ7s8¿¡õÿ«?¨Yð‰˜…UžÁ9Æ £¶‹ÙŽøÒ_jM]%ô¬šŸpòŒÈÿö,>uëë† H¦ôw/ñGï¨öøG1\š$ ÆTÍjÆ7—”8©æò®Ú,â¤ýMq³ÖÖlƈ¿X,þ«I|ËéÆ?# ŒHqÒü-¥êe=U7+ºÄT øqª—oºn>~âêù¡+~*‹lÓtÍÂÝŽ' Æ4ž›£ªð|#äŘzpò¥â?jú0Uõ™­öºbLÕú»ú2 ¤Ï¿­Å_Ÿ¦ÆÏËt9§]&ø‹˜ÿ)ÌO8Å¿¡-¦ôâÿôÍ|™ŠÐi+èù¸Ï~%«à¢Ë* Æ´¬¼ƒOÿ±L? ÆÏçT°»dO7&½1·Â&4Ž€àGÍ1ã ôÔ›¸À¸ŽÛžnL"{`7“oíéÆ4“&=!q6!èZ^&V?í±›éy-ïÔMÈ|¿QbL=8éÛšƒ³ü½Ã¿|Ïòê7xîé¶ÏË;ýs•ÓÔ­x¬`ü¥PZM?áäË70´äÇ¿©+o7õçêf-¯ÙŒ)Ðÿg ¿1)¶žSÏž†K8·ØcaÍ=&›ít‰›íõŸèìóÿ 8ýÅqú»c-y&ºÕ]¬g­}ç©n)\yIþk“SNú_ãÅÔ¶$þòmIEæM ð×­ ZLSYHÿ)Œ¿2oqñý-þ߃Éd5È¿A¥ ¾ý„“¯Wÿ·níjj^ÌnoüeËqyó4 ˆ1MzÕâ‡ÂH/åWÍÿ<éûp½ +¶mÐM…À ô|w?‡¿÷îñé@`¤@1P’:¸ú{m%³ÜbLË-ܰó 4lAë<´Eq§K³Vçõ*÷ÞĘÊõt¶åð|ýÂñçô¿qûgìœâRA䯖ûãYÃó‹1ÕpQÜÒÞ äÿ)L=5ãï²|ÿß{ÕÉŸ¡ø *ug‰uœümÔðŠ=›\û‚®‘[ÚÙ²7zŽ 1¦I/Sü‡³ØDïœI/@¯WÜ"$žk9ÓÄE6§qRÓ»”gŠél 3¢c–&г½—ïÃKcó®½è©:ÿ”²Wš3p°Ó ,r¦ÿ¾›vÞIOÒ¿ˆÔèþÜʲ ˆ1-­/‹€S?kú[ÊÔÈA#½¢OÏR|–å3Yï“ÿüå_õ^+w·ù Ó߯‘bL{ÀW›·öü_îûì³S¾8)¢çjS­n¤L?‘–©é\µcšô²ôÿáGŠI¯Aã®—6kHÆM΄ì•@D—R?ä½:‹ƒ ,&àûðbB~¿|bÕù |߯1Zã»ã4n~&T;ø‡ðh¹^9òÚ­ÍrÞP,wñ[ï<ˉíÜ%ø51¾Ç¢áôàô|C‹/ý=C ©:EÏŸ¿¦êÞÝ,¡ùwûø¶–ÿþ0uÓóŸ$+س‚á㦮ªÝðRzþ¾”C¼‡Àt ˆ1M×z¹[ @€ @€ @€ @€ cj࢚ @€ @€ @€ @€écš®õr· @€ @€ @€ @€(ðÿ×Q’úšê÷IEND®B`‚rabbitmq-server-3.2.4/plugins-src/webmachine-wrapper/.srcdist_done0000644000000000000000000000000012305126066024021 0ustar rootrootrabbitmq-server-3.2.4/plugins-src/webmachine-wrapper/license_info0000644000000000000000000000021712305126066023732 0ustar rootrootWebmachine is Copyright (c) Basho Technologies and is covered by the Apache License 2.0. It was downloaded from http://webmachine.basho.com/ rabbitmq-server-3.2.4/plugins-src/webmachine-wrapper/LICENSE-Apache-Basho0000644000000000000000000002367712305126066024607 0ustar rootroot 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 rabbitmq-server-3.2.4/plugins-src/webmachine-wrapper/hash.mk0000644000000000000000000000003512305126066022624 0ustar rootrootUPSTREAM_SHORT_HASH:=e9359c7 rabbitmq-server-3.2.4/plugins-src/webmachine-wrapper/Makefile0000644000000000000000000000002712305126066023011 0ustar rootrootinclude ../umbrella.mk rabbitmq-server-3.2.4/plugins-src/webmachine-wrapper/package.mk0000644000000000000000000000102112305126066023270 0ustar rootrootAPP_NAME:=webmachine DEPS:=mochiweb-wrapper UPSTREAM_GIT:=https://github.com/rabbitmq/webmachine.git UPSTREAM_REVISION:=e9359c7092b228f671417abe68319913f1aebe46 RETAIN_ORIGINAL_VERSION:=true WRAPPER_PATCHES:=10-remove-crypto-dependency.patch ORIGINAL_APP_FILE=$(CLONE_DIR)/src/$(APP_NAME).app.src DO_NOT_GENERATE_APP_FILE=true define package_rules # This rule is run *before* the one in do_package.mk $(PLUGINS_SRC_DIST_DIR)/$(PACKAGE_DIR)/.srcdist_done:: cp $(CLONE_DIR)/LICENSE $(PACKAGE_DIR)/LICENSE-Apache-Basho endef rabbitmq-server-3.2.4/plugins-src/webmachine-wrapper/10-remove-crypto-dependency.patch0000644000000000000000000000412312305126066027540 0ustar rootrootdiff --git a/src/webmachine.app.src b/src/webmachine.app.src index eb949a2..2c46c3f 100644 --- a/src/webmachine.app.src +++ b/src/webmachine.app.src @@ -7,7 +7,6 @@ {registered, []}, {applications, [kernel, stdlib, - crypto, mochiweb]}, {mod, {webmachine_app, []}}, {env, []} diff --git a/src/webmachine.erl b/src/webmachine.erl index 47f1ce2..2e5be1b 100644 --- a/src/webmachine.erl +++ b/src/webmachine.erl @@ -28,7 +28,6 @@ %% @doc Start the webmachine server. start() -> webmachine_deps:ensure(), - application:start(crypto), application:start(webmachine). %% @spec stop() -> ok diff --git a/src/webmachine_decision_core.erl b/src/webmachine_decision_core.erl index 194c48d..3379388 100644 --- a/src/webmachine_decision_core.erl +++ b/src/webmachine_decision_core.erl @@ -722,32 +722,17 @@ variances() -> end, Accept ++ AcceptEncoding ++ AcceptCharset ++ resource_call(variances). --ifndef(old_hash). md5(Bin) -> - crypto:hash(md5, Bin). + erlang:md5(Bin). md5_init() -> - crypto:hash_init(md5). + erlang:md5_init(). md5_update(Ctx, Bin) -> - crypto:hash_update(Ctx, Bin). + erlang:md5_update(Ctx, Bin). md5_final(Ctx) -> - crypto:hash_final(Ctx). --else. -md5(Bin) -> - crypto:md5(Bin). - -md5_init() -> - crypto:md5_init(). - -md5_update(Ctx, Bin) -> - crypto:md5_update(Ctx, Bin). - -md5_final(Ctx) -> - crypto:md5_final(Ctx). --endif. - + erlang:md5_final(Ctx). compute_body_md5() -> case wrcall({req_body, 52428800}) of diff --git a/src/webmachine_request.erl b/src/webmachine_request.erl index 2a5ff7a..ee459a3 100644 --- a/src/webmachine_request.erl +++ b/src/webmachine_request.erl @@ -624,7 +624,7 @@ parts_to_body(BodyList, Size, Req) when is_list(BodyList) -> {CT, _} -> CT end, - Boundary = mochihex:to_hex(crypto:rand_bytes(8)), + Boundary = mochihex:to_hex(mochiweb_util:rand_bytes(8)), HeaderList = [{"Content-Type", ["multipart/byteranges; ", "boundary=", Boundary]}], rabbitmq-server-3.2.4/plugins-src/README0000644000000000000000000000023012305126066016445 0ustar rootrootThis is the released version of rabbitmq-public-umbrella. You can clone the full version with: hg clone http://hg.rabbitmq.com/rabbitmq-public-umbrella rabbitmq-server-3.2.4/plugins-src/erlang-rfc4627-wrapper/0000755000000000000000000000000012305126066021613 5ustar rootrootrabbitmq-server-3.2.4/plugins-src/erlang-rfc4627-wrapper/10-no-cowboy-dependency.patch0000644000000000000000000001242112305126066027102 0ustar rootrootdiff --git a/ebin/rfc4627_jsonrpc.app b/ebin/rfc4627_jsonrpc.app index ef9fe44..e06b46c 100644 --- a/ebin/rfc4627_jsonrpc.app +++ b/ebin/rfc4627_jsonrpc.app @@ -9,7 +9,6 @@ rfc4627_jsonrpc_http, rfc4627_jsonrpc_inets, rfc4627_jsonrpc_mochiweb, - rfc4627_jsonrpc_cowboy, rfc4627_jsonrpc_registry ]}, {registered, []}, diff --git a/src/rfc4627_jsonrpc_cowboy.erl b/src/rfc4627_jsonrpc_cowboy.erl deleted file mode 100644 index 2af0fd8..0000000 --- a/src/rfc4627_jsonrpc_cowboy.erl +++ /dev/null @@ -1,113 +0,0 @@ -%% JSON-RPC for Cowboy -%%--------------------------------------------------------------------------- -%% @author Erik Timan -%% @author Tony Garnock-Jones -%% @author LShift Ltd. -%% @copyright 2007-2010, 2011, 2012 Tony Garnock-Jones and 2007-2010 LShift Ltd. -%% @license -%% -%% Permission is hereby granted, free of charge, to any person -%% obtaining a copy of this software and associated documentation -%% files (the "Software"), to deal in the Software without -%% restriction, including without limitation the rights to use, copy, -%% modify, merge, publish, distribute, sublicense, and/or sell copies -%% of the Software, and to permit persons to whom the Software is -%% furnished to do so, subject to the following conditions: -%% -%% The above copyright notice and this permission notice shall be -%% included in all copies or substantial portions of the Software. -%% -%% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -%% EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -%% MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -%% NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS -%% BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN -%% ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -%% CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -%% SOFTWARE. -%%--------------------------------------------------------------------------- -%% -%% @reference the Cowboy github page -%% -%% @doc Support for serving JSON-RPC via Cowboy. -%% -%% Familiarity with writing Cowboy applications is assumed. -%% -%% == Basic Usage == -%% -%%
      -%%
    • Register your JSON-RPC services as usual.
    • -%%
    • Decide on your `AliasPrefix' (see {@link rfc4627_jsonrpc_http:invoke_service_method/4}).
    • -%%
    • When a Cowboy request arrives at your application, call {@link handle/2} with your `AliasPrefix' and the request.
    • -%%
    -%% -%% It's as simple as that - if the request's URI path matches the -%% `AliasPrefix', it will be decoded and the JSON-RPC service it names -%% will be invoked. - --module(rfc4627_jsonrpc_cowboy). - --export([handle/2]). - -normalize(X) when is_atom(X) -> - string:to_lower(atom_to_list(X)); -normalize(X) when is_binary(X) -> - string:to_lower(binary_to_list(X)); -normalize(X) when is_list(X) -> - string:to_lower(X). - -%% @spec (string(), #http_req{}) -> no_match | {ok, #http_req{}} -%% -%% @doc If the request matches `AliasPrefix', the corresponding -%% JSON-RPC service is invoked, and an `{ok, #http_req{}}' is returned; -%% otherwise, `no_match' is returned. -%% -%% Call this function from your Cowboy HTTP handler's `handle' -%% function, as follows: -%% -%% ``` -%% Req2 = case rfc4627_jsonrpc_cowboy:handle("/rpc", Req) of -%% no_match -> -%% handle_non_jsonrpc_request(Req); -%% {ok, Reponse} -> -%% Response -%% end -%% ''' -%% -%% where `handle_non_jsonrpc_request' does the obvious thing for -%% non-JSON-RPC requests. -handle(AliasPrefix, Req) -> - {BinaryPath, _} = cowboy_req:path(Req), - Path = binary_to_list(BinaryPath), - {QSVals, _} = cowboy_req:qs_vals(Req), - QueryObj = {obj, [{binary_to_list(K), V} || {K,V} <- QSVals]}, - {Hdrs, _} = cowboy_req:headers(Req), - HeaderObj = {obj, [{normalize(K), V} || {K,V} <- Hdrs]}, - {PeerAddr, _} = cowboy_req:peer_addr(Req), - Peer = list_to_binary(inet_parse:ntoa(PeerAddr)), - {Method, _} = cowboy_req:method(Req), - RequestInfo = {obj, [{"http_method", Method}, - {"http_query_parameters", QueryObj}, - {"http_headers", HeaderObj}, - {"remote_peername", Peer}, - {"scheme", <<"http">>}]}, - {ok, Body, _} = cowboy_req:body(Req), - - case rfc4627_jsonrpc_http:invoke_service_method(AliasPrefix, - Path, - RequestInfo, - Body) of - no_match -> - no_match; - {ok, ResultEnc, ResponseInfo} -> - {obj, ResponseHeaderFields} = - rfc4627:get_field(ResponseInfo, "http_headers", {obj, []}), - StatusCode = - rfc4627:get_field(ResponseInfo, "http_status_code", 200), - Headers = [{list_to_binary(K), V} || {K,V} <- ResponseHeaderFields], - RespType = [{<<"Content-Type">>, rfc4627:mime_type()}], - cowboy_req:reply(StatusCode, - Headers ++ RespType, - ResultEnc, - Req) - end. rabbitmq-server-3.2.4/plugins-src/erlang-rfc4627-wrapper/erlang-rfc4627-git/0000755000000000000000000000000012305126066024737 5ustar rootrootrabbitmq-server-3.2.4/plugins-src/erlang-rfc4627-wrapper/erlang-rfc4627-git/README.md0000644000000000000000000001124612305126066026222 0ustar rootroot# RFC4627 (JSON) and JSON-RPC for Erlang An implementation of JSON and JSON-RPC for Erlang. See [rfc4627.erl](http://tonyg.github.com/erlang-rfc4627/doc/rfc4627.html), the JSON/RFC4627 codec itself, to learn how to encode and decode JSON objects from Erlang code. ## Providing and calling JSON-RPC services See [rfc4627\_jsonrpc.erl](http://tonyg.github.com/erlang-rfc4627/doc/rfc4627_jsonrpc.html), a JSON-RPC service registry and transport-neutral service method invocation mechanism, to learn how to expose Erlang processes as remotely-callable JSON-RPC services, and to learn how to invoke local JSON-RPC services from Erlang without the overhead of HTTP. ## Exposing JSON-RPC services over HTTP ### Using Inets See [rfc4627\_jsonrpc\_inets.erl](http://tonyg.github.com/erlang-rfc4627/doc/rfc4627_jsonrpc_inets.html), an Inets HTTP transport binding for JSON-RPC, to learn how to configure the Inets HTTP server to respond to JSON-RPC requests. ### Using Mochiweb See [rfc4627\_jsonrpc\_mochiweb.erl](http://tonyg.github.com/erlang-rfc4627/doc/rfc4627_jsonrpc_mochiweb.html) to learn how to delegate incoming Mochiweb HTTP requests to the JSON-RPC service dispatcher. ### Using Cowboy See [rfc4627\_jsonrpc\_cowboy.erl](http://tonyg.github.com/erlang-rfc4627/doc/rfc4627_jsonrpc_cowboy.html) to learn how to delegate incoming Cowboy HTTP requests to the JSON-RPC service dispatcher. ## Running the example test service that comes with the source code Included with the Erlang RFC4627 source code is a small Inets-based example that defines a "hello world"-style JSON-RPC service, and calls it from a Javascript program embedded in a web page. At your Erlang shell, - after compiling the code with `make all test-compile`, - when your current working directory contains the `test` directory from the distribution, such that `./test/server_root/conf/httpd.conf` exists, type `test_jsonrpc_inets:start_httpd().` (Don't forget the trailing "."!) This will - start the inets httpd on port 5671 (from `./test/server_root/conf/httpd.conf`) - allow HTTP access to JSON-RPC services via a url prefix of `/rpc` (again from `httpd.conf`) - start the `rfc4627_jsonrpc` service registry - register the test service Visiting in your browser should load a page that uses javascript to invoke the Erlang-implemented JSON-RPC test service. ## Invoking JSON-RPC procedures from Javascript See the [relevant section](http://tonyg.github.com/erlang-rfc4627/doc/overview-summary.html#Invoking_JSON-RPC_procedures_from_Javascript) of the `edoc` documentation included with the source code. ## References - the [JSON RFC](http://www.ietf.org/rfc/rfc4627.txt). - the [JSON-RPC specification](http://json-rpc.org/wd/JSON-RPC-1-1-WD-20060807.html) 1.1 working draft ([mirrored locally](http://tonyg.github.com/erlang-rfc4627/doc/JSON-RPC-1-1-WD-20060807.html)). - Joe Armstrong's [message](http://erlang.org/pipermail/erlang-questions/2005-November/017805.html) describing the basis of the JSON data type mapping that the `rfc4627.erl` module uses. ## Contributors The codebase and documentation was originally written between 2007 and 2010 by Tony Garnock-Jones while at LShift in London. Since then, it has been maintained by Tony and enhanced with a few generous contributions from others: - András Veres-Szentkirályi - Eugene Volchek - Simon MacMullen - Andrey Khozov - Erik Timan ## Copyright and Licence Copyrights: - Copyright © 2007-2010, 2011, 2012 Tony Garnock-Jones. - Portions copyright 2007-2010 LShift Ltd. - Portions copyright contributors to the project, listed above. License (MIT): Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. rabbitmq-server-3.2.4/plugins-src/erlang-rfc4627-wrapper/erlang-rfc4627-git/src/0000755000000000000000000000000012305126066025526 5ustar rootrootrabbitmq-server-3.2.4/plugins-src/erlang-rfc4627-wrapper/erlang-rfc4627-git/src/rfc4627.erl0000644000000000000000000005315012305126066027333 0ustar rootroot%% JSON - RFC 4627 - for Erlang %%--------------------------------------------------------------------------- %% @author Tony Garnock-Jones %% @author LShift Ltd. %% @copyright 2007-2010, 2011, 2012 Tony Garnock-Jones and 2007-2010 LShift Ltd. %% @license %% %% Permission is hereby granted, free of charge, to any person %% obtaining a copy of this software and associated documentation %% files (the "Software"), to deal in the Software without %% restriction, including without limitation the rights to use, copy, %% modify, merge, publish, distribute, sublicense, and/or sell copies %% of the Software, and to permit persons to whom the Software is %% furnished to do so, subject to the following conditions: %% %% The above copyright notice and this permission notice shall be %% included in all copies or substantial portions of the Software. %% %% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, %% EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF %% MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND %% NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS %% BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN %% ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN %% CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE %% SOFTWARE. %%--------------------------------------------------------------------------- %% %% @reference RFC %% 4627, the JSON RFC %% %% @reference JSON in general %% %% @reference Joe Armstrong's %% message describing the basis of the JSON data type mapping that %% this module uses %% %% @doc An implementation of RFC 4627 (JSON, the JavaScript Object Notation) for Erlang. %% %% The basic API is comprised of the {@link encode/1} and {@link decode/1} functions. %% %% == Data Type Mapping == %% %% The data type mapping I've implemented is as per Joe Armstrong's %% message [http://www.erlang.org/ml-archive/erlang-questions/200511/msg00193.html] - see {@link json()}. %% %% == Unicode == %% %% When serializing a string, if characters are found with codepoint %% >127, we rely on the unicode encoder to build the proper byte %% sequence for transmission. We still use the \uXXXX escape for %% control characters (other than the RFC-specified specially %% recognised ones). %% %% {@link decode/1} will autodetect the unicode encoding used, and any %% strings returned in the result as binaries will contain UTF-8 %% encoded byte sequences for codepoints >127. Object keys containing %% codepoints >127 will be returned as lists of codepoints, rather %% than being UTF-8 encoded. If you have already transformed the text %% to parse into a list of unicode codepoints, perhaps by your own use %% of {@link unicode_decode/1}, then use {@link decode_noauto/1} to %% avoid redundant and erroneous double-unicode-decoding. %% %% Similarly, {@link encode/1} produces text that is already UTF-8 %% encoded. To get raw codepoints, use {@link encode_noauto/1} and %% {@link encode_noauto/2}. You can use {@link unicode_encode/1} to %% UTF-encode the results, if that's appropriate for your application. %% %% == Differences to the specification == %% %% I'm lenient in the following ways during parsing: %% %%
      %%
    • repeated commas in arrays and objects collapse to a single comma
    • %%
    • any character =<32 is considered whitespace
    • %%
    • leading zeros for numbers are accepted
    • %%
    • we don't restrict the toplevel token to only object or array - %% any JSON value can be used at toplevel
    • %%
    %% @type json() = jsonobj() | jsonarray() | jsonnum() | jsonstr() | true | false | null. An Erlang representation of a general JSON value. %% @type jsonobj() = {obj, [{jsonkey(), json()}]}. A JSON "object" or "struct". %% @type jsonkey() = string(). A field-name within a JSON "object". %% @type jsonarray() = [json()]. A JSON array value. %% @type jsonnum() = integer() | float(). A JSON numeric value. %% @type jsonstr() = binary(). A JSON string value. %% @type byte() = integer(). An integer >=0 and =<255. -module(rfc4627). -export([mime_type/0, encode/1, decode/1]). -export([encode_noauto/1, encode_noauto/2, decode_noauto/1]). -export([unicode_decode/1, unicode_encode/1]). -export([from_record/3, to_record/3]). -export([hex_digit/1, digit_hex/1]). -export([get_field/2, get_field/3, set_field/3, exclude_field/2]). -export([equiv/2]). %% @spec () -> string() %% @doc Returns the IANA-registered MIME type for JSON data. mime_type() -> "application/json". %% @spec (json()) -> [byte()] %% %% @doc Encodes the JSON value supplied, first into Unicode %% codepoints, and then into UTF-8. %% %% The resulting string is a list of byte values that should be %% interpreted as UTF-8 encoded text. %% %% During encoding, atoms and binaries are accepted as keys of JSON %% objects (type {@link jsonkey()}) as well as the usual strings %% (lists of character codepoints). encode(X) -> unicode_encode({'utf-8', encode_noauto(X)}). %% @spec (json()) -> string() %% %% @doc Encodes the JSON value supplied into raw Unicode codepoints. %% %% The resulting string may contain codepoints with value >=128. You %% can use {@link unicode_encode/1} to UTF-encode the results, if %% that's appropriate for your application. %% %% During encoding, atoms and binaries are accepted as keys of JSON %% objects (type {@link jsonkey()}) as well as the usual strings %% (lists of character codepoints). encode_noauto(X) -> lists:reverse(encode_noauto(X, [])). %% @spec (json(), string()) -> string() %% %% @doc As {@link encode_noauto/1}, but prepends reversed text %% to the supplied accumulator string. encode_noauto(true, Acc) -> "eurt" ++ Acc; encode_noauto(false, Acc) -> "eslaf" ++ Acc; encode_noauto(null, Acc) -> "llun" ++ Acc; encode_noauto(Str, Acc) when is_binary(Str) -> Codepoints = xmerl_ucs:from_utf8(Str), quote_and_encode_string(Codepoints, Acc); encode_noauto(Str, Acc) when is_atom(Str) -> quote_and_encode_string(atom_to_list(Str), Acc); encode_noauto(Num, Acc) when is_number(Num) -> encode_number(Num, Acc); encode_noauto({obj, Fields}, Acc) -> "}" ++ encode_object(Fields, "{" ++ Acc); encode_noauto(Dict, Acc) when element(1, Dict) =:= dict -> "}" ++ encode_object(dict:to_list(Dict), "{" ++ Acc); encode_noauto(Arr, Acc) when is_list(Arr) -> "]" ++ encode_array(Arr, "[" ++ Acc). encode_object([], Acc) -> Acc; encode_object([{Key, Value}], Acc) -> encode_field(Key, Value, Acc); encode_object([{Key, Value} | Rest], Acc) -> encode_object(Rest, "," ++ encode_field(Key, Value, Acc)). encode_field(Key, Value, Acc) when is_binary(Key) -> Codepoints = xmerl_ucs:from_utf8(Key), encode_noauto(Value, ":" ++ quote_and_encode_string(Codepoints, Acc)); encode_field(Key, Value, Acc) when is_atom(Key) -> encode_noauto(Value, ":" ++ quote_and_encode_string(atom_to_list(Key), Acc)); encode_field(Key, Value, Acc) when is_list(Key) -> encode_noauto(Value, ":" ++ quote_and_encode_string(Key, Acc)). encode_array([], Acc) -> Acc; encode_array([X], Acc) -> encode_noauto(X, Acc); encode_array([X | Rest], Acc) -> encode_array(Rest, "," ++ encode_noauto(X, Acc)). quote_and_encode_string(Str, Acc) -> "\"" ++ encode_string(Str, "\"" ++ Acc). encode_string([], Acc) -> Acc; encode_string([$" | Rest], Acc) -> encode_string(Rest, [$", $\\ | Acc]); encode_string([$\\ | Rest], Acc) -> encode_string(Rest, [$\\, $\\ | Acc]); encode_string([X | Rest], Acc) when X < 32 orelse X > 127 -> encode_string(Rest, encode_general_char(X, Acc)); encode_string([X | Rest], Acc) -> encode_string(Rest, [X | Acc]). encode_general_char(8, Acc) -> [$b, $\\ | Acc]; encode_general_char(9, Acc) -> [$t, $\\ | Acc]; encode_general_char(10, Acc) -> [$n, $\\ | Acc]; encode_general_char(12, Acc) -> [$f, $\\ | Acc]; encode_general_char(13, Acc) -> [$r, $\\ | Acc]; encode_general_char(X, Acc) when X > 127 -> [X | Acc]; encode_general_char(X, Acc) -> %% FIXME currently this branch never runs. %% We could make it configurable, maybe? Utf16Bytes = xmerl_ucs:to_utf16be(X), encode_utf16be_chars(Utf16Bytes, Acc). encode_utf16be_chars([], Acc) -> Acc; encode_utf16be_chars([B1, B2 | Rest], Acc) -> encode_utf16be_chars(Rest, [hex_digit((B2) band 16#F), hex_digit((B2 bsr 4) band 16#F), hex_digit((B1) band 16#F), hex_digit((B1 bsr 4) band 16#F), $u, $\\ | Acc]). %% @spec (Nibble::integer()) -> char() %% @doc Returns the character code corresponding to Nibble. %% %% Nibble must be >=0 and =<15. hex_digit(N) when is_integer(N), N >= 0, N =< 9 -> $0 + N; hex_digit(N) when is_integer(N), N >= 10, N =< 15 -> $A + N - 10. encode_number(Num, Acc) when is_integer(Num) -> lists:reverse(integer_to_list(Num), Acc); encode_number(Num, Acc) when is_float(Num) -> lists:reverse(float_to_list(Num), Acc). %% @spec (Input::(binary() | [byte()])) -> ({ok, json(), Remainder} | {error, Reason}) %% where Remainder = string() %% Reason = any() %% %% @doc Decodes a JSON value from an input binary or string of %% Unicode-encoded text. %% %% Given a binary, converts it to a list of bytes. Given a %% list/string, interprets it as a list of bytes. %% %% Uses {@link unicode_decode/1} on its input, which results in a list %% of codepoints, and then decodes a JSON value from that list of %% codepoints. %% %% Returns either `{ok, Result, Remainder}', where Remainder is the %% remaining portion of the input that was not consumed in the process %% of decoding Result, or `{error, Reason}'. decode(Bin) when is_binary(Bin) -> decode(binary_to_list(Bin)); decode(Bytes) -> {_Charset, Codepoints} = unicode_decode(Bytes), decode_noauto(Codepoints). %% @spec (Input::string()) -> ({ok, json(), string()} | {error, any()}) %% %% @doc As {@link decode/1}, but does not perform Unicode decoding on its input. %% %% Expects a list of codepoints - an ordinary Erlang string - rather %% than a list of Unicode-encoded bytes. decode_noauto(Bin) when is_binary(Bin) -> decode_noauto(binary_to_list(Bin)); decode_noauto(Chars) -> case catch parse(skipws(Chars)) of {'EXIT', Reason} -> %% Reason is usually far too much information, but helps %% if needing to debug this module. {error, Reason}; {Value, Remaining} -> {ok, Value, skipws(Remaining)} end. %% @spec ([byte()]) -> [char()] %% %% @doc Autodetects and decodes using the Unicode encoding of its input. %% %% From RFC4627, section 3, "Encoding": %% %%
    %% JSON text SHALL be encoded in Unicode. The default encoding is %% UTF-8. %% %% Since the first two characters of a JSON text will always be ASCII %% characters [RFC0020], it is possible to determine whether an octet %% stream is UTF-8, UTF-16 (BE or LE), or UTF-32 (BE or LE) by looking %% at the pattern of nulls in the first four octets. %% %% 00 00 00 xx UTF-32BE %% 00 xx 00 xx UTF-16BE %% xx 00 00 00 UTF-32LE %% xx 00 xx 00 UTF-16LE %% xx xx xx xx UTF-8 %%
    %% %% Interestingly, the BOM (byte-order mark) is not mentioned. We %% support it here by using it to detect our encoding, discarding it %% if present, even though RFC4627 explicitly notes that the first two %% characters of a JSON text will be ASCII. %% %% If a BOM ([http://unicode.org/faq/utf_bom.html]) is present, we use %% that; if not, we use RFC4627's rules (as above). Note that UTF-32 %% is the same as UCS-4 for our purposes (but see also %% [http://unicode.org/reports/tr19/tr19-9.html]). Note that UTF-16 is %% not the same as UCS-2! %% %% Note that I'm using xmerl's UCS/UTF support here. There's another %% UTF-8 codec in asn1rt, which works on binaries instead of lists. %% unicode_decode([0,0,254,255|C]) -> {'utf-32', xmerl_ucs:from_ucs4be(C)}; unicode_decode([255,254,0,0|C]) -> {'utf-32', xmerl_ucs:from_ucs4le(C)}; unicode_decode([254,255|C]) -> {'utf-16', xmerl_ucs:from_utf16be(C)}; unicode_decode([239,187,191|C]) -> {'utf-8', xmerl_ucs:from_utf8(C)}; unicode_decode(C=[0,0,_,_|_]) -> {'utf-32be', xmerl_ucs:from_ucs4be(C)}; unicode_decode(C=[_,_,0,0|_]) -> {'utf-32le', xmerl_ucs:from_ucs4le(C)}; unicode_decode(C=[0,_|_]) -> {'utf-16be', xmerl_ucs:from_utf16be(C)}; unicode_decode(C=[_,0|_]) -> {'utf-16le', xmerl_ucs:from_utf16le(C)}; unicode_decode(C=_) -> {'utf-8', xmerl_ucs:from_utf8(C)}. %% @spec (EncodingAndCharacters::{Encoding, [char()]}) -> [byte()] %% where Encoding = 'utf-32' | 'utf-32be' | 'utf-32le' | 'utf-16' | %% 'utf-16be' | 'utf-16le' | 'utf-8' %% %% @doc Encodes the given characters to bytes, using the given Unicode encoding. %% %% For convenience, we supply a partial inverse of unicode_decode; If %% a BOM is requested, we more-or-less arbitrarily pick the big-endian %% variant of the encoding, since big-endian is network-order. We %% don't support UTF-8 with BOM here. unicode_encode({'utf-32', C}) -> [0,0,254,255|xmerl_ucs:to_ucs4be(C)]; unicode_encode({'utf-32be', C}) -> xmerl_ucs:to_ucs4be(C); unicode_encode({'utf-32le', C}) -> xmerl_ucs:to_ucs4le(C); unicode_encode({'utf-16', C}) -> [254,255|xmerl_ucs:to_utf16be(C)]; unicode_encode({'utf-16be', C}) -> xmerl_ucs:to_utf16be(C); unicode_encode({'utf-16le', C}) -> xmerl_ucs:to_utf16le(C); unicode_encode({'utf-8', C}) -> xmerl_ucs:to_utf8(C). parse([$" | Rest]) -> %% " emacs balancing {Codepoints, Rest1} = parse_string(Rest, []), {list_to_binary(xmerl_ucs:to_utf8(Codepoints)), Rest1}; parse("true" ++ Rest) -> {true, Rest}; parse("false" ++ Rest) -> {false, Rest}; parse("null" ++ Rest) -> {null, Rest}; parse([${ | Rest]) -> parse_object(skipws(Rest), []); parse([$[ | Rest]) -> parse_array(skipws(Rest), []); parse([]) -> exit(unexpected_end_of_input); parse(Chars) -> parse_number(Chars, []). skipws([X | Rest]) when X =< 32 -> skipws(Rest); skipws(Chars) -> Chars. parse_string(Chars, Acc) -> case parse_codepoint(Chars) of {done, Rest} -> {lists:reverse(Acc), Rest}; {ok, Codepoint, Rest} -> parse_string(Rest, [Codepoint | Acc]) end. parse_codepoint([$" | Rest]) -> %% " emacs balancing {done, Rest}; parse_codepoint([$\\, Key | Rest]) -> parse_general_char(Key, Rest); parse_codepoint([X | Rest]) -> {ok, X, Rest}. parse_general_char($b, Rest) -> {ok, 8, Rest}; parse_general_char($t, Rest) -> {ok, 9, Rest}; parse_general_char($n, Rest) -> {ok, 10, Rest}; parse_general_char($f, Rest) -> {ok, 12, Rest}; parse_general_char($r, Rest) -> {ok, 13, Rest}; parse_general_char($/, Rest) -> {ok, $/, Rest}; parse_general_char($\\, Rest) -> {ok, $\\, Rest}; parse_general_char($", Rest) -> {ok, $", Rest}; parse_general_char($u, [D0, D1, D2, D3 | Rest]) -> Codepoint = (digit_hex(D0) bsl 12) + (digit_hex(D1) bsl 8) + (digit_hex(D2) bsl 4) + (digit_hex(D3)), if Codepoint >= 16#D800 andalso Codepoint < 16#DC00 -> % High half of surrogate pair case parse_codepoint(Rest) of {low_surrogate_pair, Codepoint2, Rest1} -> [FinalCodepoint] = xmerl_ucs:from_utf16be(<>), {ok, FinalCodepoint, Rest1}; _ -> exit(incorrect_usage_of_surrogate_pair) end; Codepoint >= 16#DC00 andalso Codepoint < 16#E000 -> {low_surrogate_pair, Codepoint, Rest}; true -> {ok, Codepoint, Rest} end. %% @spec (Hexchar::char()) -> integer() %% @doc Returns the number corresponding to Hexchar. %% %% Hexchar must be one of the characters `$0' through `$9', `$A' %% through `$F' or `$a' through `$f'. digit_hex(C) when is_integer(C), C >= $0, C =< $9 -> C - $0; digit_hex(C) when is_integer(C), C >= $A, C =< $F -> C - $A + 10; digit_hex(C) when is_integer(C), C >= $a, C =< $f -> C - $a + 10. finish_number(Acc, Rest) -> Str = lists:reverse(Acc), {case catch list_to_integer(Str) of {'EXIT', _} -> list_to_float(Str); Value -> Value end, Rest}. parse_number([$- | Rest], Acc) -> parse_number1(Rest, [$- | Acc]); parse_number(Rest = [C | _], Acc) -> case is_digit(C) of true -> parse_number1(Rest, Acc); false -> exit(syntax_error) end. parse_number1(Rest, Acc) -> {Acc1, Rest1} = parse_int_part(Rest, Acc), case Rest1 of [] -> finish_number(Acc1, []); [$. | More] -> {Acc2, Rest2} = parse_int_part(More, [$. | Acc1]), parse_exp(Rest2, Acc2, false); _ -> parse_exp(Rest1, Acc1, true) end. parse_int_part(Chars = [_Ch | _Rest], Acc) -> parse_int_part0(Chars, Acc). parse_int_part0([], Acc) -> {Acc, []}; parse_int_part0([Ch | Rest], Acc) -> case is_digit(Ch) of true -> parse_int_part0(Rest, [Ch | Acc]); false -> {Acc, [Ch | Rest]} end. parse_exp([$e | Rest], Acc, NeedFrac) -> parse_exp1(Rest, Acc, NeedFrac); parse_exp([$E | Rest], Acc, NeedFrac) -> parse_exp1(Rest, Acc, NeedFrac); parse_exp(Rest, Acc, _NeedFrac) -> finish_number(Acc, Rest). parse_exp1(Rest, Acc, NeedFrac) -> {Acc1, Rest1} = parse_signed_int_part(Rest, if NeedFrac -> [$e, $0, $. | Acc]; true -> [$e | Acc] end), finish_number(Acc1, Rest1). parse_signed_int_part([$+ | Rest], Acc) -> parse_int_part(Rest, [$+ | Acc]); parse_signed_int_part([$- | Rest], Acc) -> parse_int_part(Rest, [$- | Acc]); parse_signed_int_part(Rest, Acc) -> parse_int_part(Rest, Acc). is_digit(N) when is_integer(N) -> N >= $0 andalso N =< $9; is_digit(_) -> false. parse_object([$} | Rest], Acc) -> {{obj, lists:reverse(Acc)}, Rest}; parse_object([$, | Rest], Acc) -> parse_object(skipws(Rest), Acc); parse_object([$" | Rest], Acc) -> %% " emacs balancing {KeyCodepoints, Rest1} = parse_string(Rest, []), [$: | Rest2] = skipws(Rest1), {Value, Rest3} = parse(skipws(Rest2)), parse_object(skipws(Rest3), [{KeyCodepoints, Value} | Acc]). parse_array([$] | Rest], Acc) -> {lists:reverse(Acc), Rest}; parse_array([$, | Rest], Acc) -> parse_array(skipws(Rest), Acc); parse_array(Chars, Acc) -> {Value, Rest} = parse(Chars), parse_array(skipws(Rest), [Value | Acc]). %% @spec (Record, atom(), [any()]) -> jsonobj() %% where Record = tuple() %% %% @doc Used by the `?RFC4627_FROM_RECORD' macro in `rfc4627.hrl'. %% %% Given a record type definiton of ``-record(myrecord, {field1, %% field})'', and a value ``V = #myrecord{}'', the code %% ``?RFC4627_FROM_RECORD(myrecord, V)'' will return a JSON "object" %% with fields corresponding to the fields of the record. The macro %% expands to a call to the `from_record' function. from_record(R, _RecordName, Fields) -> {obj, encode_record_fields(R, 2, Fields)}. encode_record_fields(_R, _Index, []) -> []; encode_record_fields(R, Index, [Field | Rest]) -> case element(Index, R) of undefined -> encode_record_fields(R, Index + 1, Rest); Value -> [{atom_to_list(Field), Value} | encode_record_fields(R, Index + 1, Rest)] end. %% @spec (JsonObject::jsonobj(), DefaultValue::Record, [atom()]) -> Record %% where Record = tuple() %% %% @doc Used by the `?RFC4627_TO_RECORD' macro in `rfc4627.hrl'. %% %% Given a record type definiton of ``-record(myrecord, {field1, %% field})'', and a JSON "object" ``J = {obj, [{"field1", 123}, %% {"field2", 234}]}'', the code ``?RFC4627_TO_RECORD(myrecord, J)'' %% will return a record ``#myrecord{field1 = 123, field2 = 234}''. %% The macro expands to a call to the `to_record' function. to_record({obj, Values}, Fallback, Fields) -> list_to_tuple([element(1, Fallback) | decode_record_fields(Values, Fallback, 2, Fields)]). decode_record_fields(_Values, _Fallback, _Index, []) -> []; decode_record_fields(Values, Fallback, Index, [Field | Rest]) -> [case lists:keysearch(atom_to_list(Field), 1, Values) of {value, {_, Value}} -> Value; false -> element(Index, Fallback) end | decode_record_fields(Values, Fallback, Index + 1, Rest)]. %% @spec (JsonObject::jsonobj(), atom()) -> jsonobj() %% @doc Exclude a named field from a JSON "object". exclude_field({obj, Props}, Key) -> {obj, lists:keydelete(Key, 1, Props)}. %% @spec (JsonObject::jsonobj(), atom()) -> {ok, json()} | not_found %% @doc Retrieves the value of a named field of a JSON "object". get_field({obj, Props}, Key) -> case lists:keysearch(Key, 1, Props) of {value, {_K, Val}} -> {ok, Val}; false -> not_found end. %% @spec (jsonobj(), atom(), json()) -> json() %% @doc Retrieves the value of a named field of a JSON "object", or a %% default value if no such field is present. get_field(Obj, Key, DefaultValue) -> case get_field(Obj, Key) of {ok, Val} -> Val; not_found -> DefaultValue end. %% @spec (JsonObject::jsonobj(), atom(), json()) -> jsonobj() %% @doc Adds or replaces a named field with the given value. %% %% Returns a JSON "object" that contains the new field value as well %% as all the unmodified fields from the first argument. set_field({obj, Props}, Key, NewValue) -> {obj, [{Key, NewValue} | lists:keydelete(Key, 1, Props)]}. %% @spec (A::json(), B::json()) -> bool() %% @doc Tests equivalence of JSON terms. %% %% After Bob Ippolito's `equiv' predicate in mochijson. equiv({obj, Props1}, {obj, Props2}) -> L1 = lists:keysort(1, Props1), L2 = lists:keysort(1, Props2), equiv_sorted_plists(L1, L2); equiv(A, B) when is_list(A) andalso is_list(B) -> equiv_arrays(A, B); equiv(A, B) -> A == B. equiv_sorted_plists([], []) -> true; equiv_sorted_plists([], _) -> false; equiv_sorted_plists(_, []) -> false; equiv_sorted_plists([{K1, V1} | R1], [{K2, V2} | R2]) -> K1 == K2 andalso equiv(V1, V2) andalso equiv_sorted_plists(R1, R2). equiv_arrays([], []) -> true; equiv_arrays([], _) -> false; equiv_arrays(_, []) -> false; equiv_arrays([V1 | R1], [V2 | R2]) -> equiv(V1, V2) andalso equiv_arrays(R1, R2). ././@LongLink0000000000000000000000000000015200000000000011563 Lustar rootrootrabbitmq-server-3.2.4/plugins-src/erlang-rfc4627-wrapper/erlang-rfc4627-git/src/rfc4627_jsonrpc_inets.erlrabbitmq-server-3.2.4/plugins-src/erlang-rfc4627-wrapper/erlang-rfc4627-git/src/rfc4627_jsonrpc_inet0000644000000000000000000001503612305126066031330 0ustar rootroot%% JSON-RPC for Erlang's inets httpd %%--------------------------------------------------------------------------- %% @author Tony Garnock-Jones %% @author LShift Ltd. %% @copyright 2007-2010, 2011, 2012 Tony Garnock-Jones and 2007-2010 LShift Ltd. %% @license %% %% Permission is hereby granted, free of charge, to any person %% obtaining a copy of this software and associated documentation %% files (the "Software"), to deal in the Software without %% restriction, including without limitation the rights to use, copy, %% modify, merge, publish, distribute, sublicense, and/or sell copies %% of the Software, and to permit persons to whom the Software is %% furnished to do so, subject to the following conditions: %% %% The above copyright notice and this permission notice shall be %% included in all copies or substantial portions of the Software. %% %% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, %% EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF %% MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND %% NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS %% BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN %% ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN %% CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE %% SOFTWARE. %%--------------------------------------------------------------------------- %% @since 1.2.0 %% %% @doc An extension module for the Inets HTTP server, providing HTTP access to JSON-RPC services. %% %% == Configuring HTTP access to registered JSON-RPC services == %% %% The inets httpd uses an `httpd.conf' file to configure itself. To %% enable HTTP access to registered JSON-RPC services, two things need %% to be added to the httpd configuration file: %% %%
      %%
    • an entry for `rfc4627_jsonrpc_inets' in the `Modules' configuration directive (just after `mod_alias' and `mod_auth' will do)
    • %%
    • a `JsonRpcAlias' directive, specifying a subspace of the URLs served by the httpd that will be mapped to JSON-RPC service requests (the value used as `AliasPrefix' in calls to {@link rfc4627_jsonrpc_http:invoke_service_method/4})
    • %%
    %% %% Here's a complete `httpd.conf': %% %% ``` %% ServerName localhost %% ServerRoot test/server_root %% DocumentRoot test/server_root/htdocs %% Port 5671 %% Modules mod_alias mod_auth rfc4627_jsonrpc_inets mod_actions mod_cgi mod_responsecontrol mod_trace mod_range mod_head mod_include mod_dir mod_get mod_log mod_disk_log %% DirectoryIndex index.html %% JsonRpcAlias /rpc %% ErrorLog logs/error_log %% TransferLog logs/access_log %% SecurityLog logs/security_log %% ''' %% %% If an httpd server is started from this configuration, it will %% %%
      %%
    • listen on port 5671
    • %%
    • permit JSON-RPC access via URLs starting with `/rpc'
    • %%
    %% %% The URL structure for JSON-RPC requests will be %% %%
    http://localhost:5671/rpc/ServiceName
    %% %% where ServiceName is the {@link %% rfc4627_jsonrpc:register_service/2}'d name of the service. For %% instance, the example "hello world" service defined in %% `test_jsonrpc_inets.erl' would be accessible at %% %% ``http://localhost:5671/rpc/test'' %% %% The built-in service description method, `system.describe', is %% accessible via a POST to that URL, or a GET to %% %% ``http://localhost:5671/rpc/test/system.describe'' %% %% Similarly, any idempotent methods provided by a service may be %% accessed via POST to the base URL for the service, or via GET to a %% URL of the form %% %%
    http://localhost:5671/rpc/ServiceName/MethodName?arg=value&...
    %% -module(rfc4627_jsonrpc_inets). -include("rfc4627_jsonrpc.hrl"). %% The path to httpd.hrl has changed with various OTP releases. Our %% Makefile detects the changes for us, and supplies compile-time %% macro definitions to allow us to adapt. -ifdef(inets_pre_r14a). -include_lib("inets/src/httpd.hrl"). -else. -ifdef(inets_pre_r14b01). -include_lib("inets/src/http_server/httpd.hrl"). -else. -include_lib("inets/include/httpd.hrl"). -endif. -endif. -export([do/1, load/2]). %% @spec (#mod{}) -> {proceed, term()} %% @doc Implements the inets httpd main callback interface. %% %% Calls out to {@link rfc4627_jsonrpc_http:invoke_service_method/4}. do(ModData = #mod{data = OldData}) -> case {proplists:get_value(status, OldData), proplists:get_value(response, OldData)} of {undefined, undefined} -> do_rpc(ModData); _ -> {proceed, OldData} end. %% @spec (Line::string(), AccIn::term()) -> {ok, AccOut::term(), {atom(), term()}} %% @doc Parses the `"JsonRpcAlias"' configuration entry from the inets `httpd.conf' file. load("JsonRpcAlias " ++ Alias, []) -> {ok, [], {json_rpc_alias, Alias}}. do_rpc(#mod{init_data = #init_data{peername = {PeerPort, PeerName}}, config_db = ConfigDb, socket_type = SocketType, method = HttpMethod, request_uri = PathAndQuery, parsed_header = InetsHeaders, entity_body = Body, data = OldData}) -> AliasPrefix = httpd_util:lookup(ConfigDb, json_rpc_alias, default), {Path, QueryObj} = case string:tokens(PathAndQuery, "?") of [] -> {"", {obj, []}}; [P] -> {P, {obj, []}}; [P, Q] -> {P, {obj, case httpd:parse_query(Q) of [{"",""}] -> []; %% is this a bug in httpd? KV -> [{K, list_to_binary(V)} || {K,V} <- KV] end}} end, HeaderObj = {obj, [{K, list_to_binary(V)} || {K,V} <- InetsHeaders]}, SchemeFields = case SocketType of ip_comm -> [{"scheme", <<"http">>}]; ssl -> [{"scheme", <<"https">>}]; _ -> [] end, RequestInfo = {obj, ([{"http_method", list_to_binary(HttpMethod)}, {"http_query_parameters", QueryObj}, {"http_headers", HeaderObj}, {"remote_port", PeerPort}, {"remote_peername", list_to_binary(PeerName)}] ++ SchemeFields)}, case rfc4627_jsonrpc_http:invoke_service_method(AliasPrefix, Path, RequestInfo, Body) of no_match -> {proceed, OldData}; {ok, ResultEnc, ResponseInfo} -> {obj, ResponseHeaderFields} = rfc4627:get_field(ResponseInfo, "http_headers", {obj, []}), StatusCode = rfc4627:get_field(ResponseInfo, "http_status_code", 200), Headers = [{K, binary_to_list(V)} || {K,V} <- ResponseHeaderFields], {proceed, [{response, {response, [{code, StatusCode}, {content_length, integer_to_list(length(ResultEnc))}, {content_type, rfc4627:mime_type()} | Headers], ResultEnc}} | OldData]} end. rabbitmq-server-3.2.4/plugins-src/erlang-rfc4627-wrapper/erlang-rfc4627-git/src/doc/0000755000000000000000000000000012305126066026273 5ustar rootroot././@LongLink0000000000000000000000000000014500000000000011565 Lustar rootrootrabbitmq-server-3.2.4/plugins-src/erlang-rfc4627-wrapper/erlang-rfc4627-git/src/doc/overview.edoc.inrabbitmq-server-3.2.4/plugins-src/erlang-rfc4627-wrapper/erlang-rfc4627-git/src/doc/overview.edoc.in0000644000000000000000000001234712305126066031411 0ustar rootroot@title RFC4627 (JSON) and JSON-RPC for Erlang @author Tony Garnock-Jones @author LShift Ltd. @copyright 2007-2010, 2011, 2012 Tony Garnock-Jones and 2007-2010 LShift Ltd. @version %%VERSION%% @reference RFC 4627, the JSON RFC @reference The JSON-RPC specification 1.1 working draft (mirrored locally). @doc

    An implementation of JSON and JSON-RPC for Erlang.

    See {@link rfc4627}, the JSON/RFC4627 codec itself, to learn how to encode and decode JSON objects from Erlang code. == Providing and calling JSON-RPC services == See {@link rfc4627_jsonrpc}, a JSON-RPC service registry and transport-neutral service method invocation mechanism, to learn how to expose Erlang processes as remotely-callable JSON-RPC services, and to learn how to invoke local JSON-RPC services from Erlang without the overhead of HTTP. == Exposing JSON-RPC services over HTTP == === Using Inets === See {@link rfc4627_jsonrpc_inets}, an Inets HTTP transport binding for JSON-RPC, to learn how to configure the Inets HTTP server to respond to JSON-RPC requests. === Using Mochiweb === See {@link rfc4627_jsonrpc_mochiweb} to learn how to delegate incoming Mochiweb HTTP requests to the JSON-RPC service dispatcher. === Using Cowboy === See {@link rfc4627_jsonrpc_cowboy} to learn how to delegate incoming Cowboy HTTP requests to the JSON-RPC service dispatcher. == Running the example test service that comes with the source code == Included with the Erlang RFC4627 source code is a small Inets-based example that defines a "hello world"-style JSON-RPC service, and calls it from a Javascript program embedded in a web page. At your Erlang shell,
    • after compiling the code with "`make all test-compile'",
    • when your current working directory contains the "test" directory from the distribution, such that "test/server_root/conf/httpd.conf" exists,
    type `test_jsonrpc_inets:start_httpd()'. This will
    • start the inets httpd on port 5671 (from test/server_root/conf/httpd.conf)
    • allow HTTP access to JSON-RPC services via a url prefix of "/rpc" (again from httpd.conf)
    • start the `rfc4627_jsonrpc' service registry
    • register the test service
    Visiting [http://localhost:5671/] in your browser should load a page that uses javascript to invoke the Erlang-implemented JSON-RPC test service. == Invoking JSON-RPC procedures from Javascript == Once {@link rfc4627_jsonrpc_inets} is configured as part of a running inets httpd, services can be accessed via HTTP POST and (conditionally) HTTP GET. This distribution includes Javascript code for invoking JSON-RPC services from within a web browser:
    • json.js: a slightly modified version of the original json.org Javascript JSON codec
    • jsonrpc.js: classes for XmlHttpRequest-based JSON-RPC service access
    • prototype-1.4.0.js: provides cross-browser XmlHttpRequest implementation, as well as many very useful utilities and a framework for class-based programming in Javascript
    • test-client.js: running-example javascript client code
    • index.html: loads and runs the running-example client
    The main class for JSON-RPC service access is jsonrpc.js's `JsonRpcService' class. ``` var serviceName = "test"; // or whatever your service is registered as var locationBase = document.location; // e.g. "http://localhost:5671/" var jsonRpcPrefix = "rpc/"; // or as configured in your httpd.conf var testService = new JsonRpcService(locationBase + jsonRpcPrefix + serviceName, onReady); function onReady() { // callback invoked when the service is opened and ready for requests testService.test_proc("Hello, world!").addCallback(process_reply); function process_reply(reply) { // ... } } ''' When an instance of `JsonRpcService' is constructed, it immediately calls the `system.describe' method of the service. When the result arrives, it uses the service description to add methods for each available service procedure to itself (see `installGenericProxy' in jsonrpc.js), and then calls the `onReady' callback supplied to the constructor to indicate that it is ready to process requests. Javascript's network primitives force you to work in continuation-passing-style. Every service procedure available on a `JsonRpcService' instance is asynchronous: calling one returns an instance of `JsonRpcTransaction'. The `addCallback' method of `JsonRpcTransaction' can be used to add a handler for processing the result of a JSON-RPC service request. The `addErrorCallback' is used to catch notifications of error responses to a JSON-RPC service request. ``` myService.myServiceProcedure(arg).addCallback(myReplyHandler).addErrorCallback(myErrorHandler); ''' (note that `addCallback' and `addErrorCallback' return the `JsonRpcTransaction' object for convenience, to allow chaining as seen above.) ././@LongLink0000000000000000000000000000016200000000000011564 Lustar rootrootrabbitmq-server-3.2.4/plugins-src/erlang-rfc4627-wrapper/erlang-rfc4627-git/src/doc/JSON-RPC-1-1-WD-20060807.htmlrabbitmq-server-3.2.4/plugins-src/erlang-rfc4627-wrapper/erlang-rfc4627-git/src/doc/JSON-RPC-1-1-WD-0000644000000000000000000017276212305126066030311 0ustar rootroot JSON-RPC 1.1 Working Draft 7 August 2006

    JSON-RPC 1.1 Specification

    Working Draft 7 August 2006

    Previous Versions:
    JSON-RPC 1.0
    Editors:
    Atif Aziz, www.raboof.com
    Jan-Klaas Kollhof, jan.kollhof.net

    This document is currently a working draft published with the intent of soliciting community feedback. Please send your comments and concerns to the public mailing-list JSON-RPC Yahoo! Group. Make sure you prefix the subject line with “1.1WD:â€, as in “1.1WD: Comment on errorsâ€.

    This specification is designed to provide the developer with the information needed to implement the protocol on the client or server end of a communication bus.

    Table of Contents

    1. Overview

    JSON-RPC is a stateless and light-weight remote procedure call (RPC) protocol for inter-networking applications over HTTP. It uses JSON as the data format for of all facets of a remote procedure call, including all application data carried in parameters.

    By leveraging HTTP, JSON-RPC allows implementations to immediately benefit from the widely deployed World Wide Web infrastructure that is well-documented and understood today. It introduces no new HTTP verbs or message header extensions. JSON-RPC relies on JSON for the format of the HTTP message bodies, which allows implementations to benefit from a simple and standard text format that has suitable representations for the most commonly used scalar and structured data types inapplications. It is being quickly and widely adopted for web applications, and for which libraries are readily available in several languages.

    The general mechanism for a remote procedure call using JSON-RPC consists of a client establishing a connection with a service and then invoking one or more procedures provided by that service. A single remote procedure call begins life as a request sent from the client to the server. The call ends when the client subsequently receives a response from the server over the same connection. Another call on the same connection is only made once the previous call has ended.

    1.1. Goals

    The primary goals of this specification are to define the JSON-RPC 1.1 protocol in terms of:

    • Expressing a remote procedure call and its result in JSON.
    • Using HTTP to transfer the request and response messages that make up a remote procedure call.
    • Expressing error conditions in JSON and in HTTP.
    • Publishing and discovering a simple and machine-readable specification of a JSON-RPC service.

    1.2. Non-Goals

    JSON-RPC does not address security, correlation, reliability, sessions management, state management and many other features that may be found in other RPC protocols or distributed systems. Developers are instead encouraged to employ features of HTTP and related Internet technologies that can offer some of these features in an equally compelling, robust and satisfying manner. Some features may be defined as extensions by other specifications.

    2. Differences From Version 1

    The following list (non-comprehensive) summarizes the general changes that have been applied to version 1.0:

    • JSON-RPC 1.1 is bound to HTTP only. Use over other protocols are not considered normative according to verson 1.1.
    • Renamed request to Procedure Call (capitalization significant).
    • Renamed response to Procedure Return (capitalization significant).
    • Removed notifications.
    • Removed the requirement to specify id for regular calls.
    • Formalize Content-Type for JSON-RPC.
    • Add version member to Procedure Call and Procedure Return objects.
    • Formalization of the JSON type system, i.e. Boolean, String, Number, Array, Object and the Null value (capitalization significant).
    • Added call encoding for HTTP GET.
    • Added named and positional arguments.
    • Added Error object and formalization of error codes.
    • Added introspection (service description) and required system procedures.

    3. Requirements

    The key words MUST, MUST NOT, REQUIRED, SHALL, SHALL NOT, SHOULD, SHOULD NOT, RECOMMENDED, MAY and OPTIONAL in this document are to be interpreted as described in RFC 2119.

    An implementation is not compliant if it fails to satisfy one or more of the MUST requirements for the protocols it implements. An implementation that satisfies all of the MUST and all of the SHOULD requirements for its features is said to be unconditionally compliant; one that satisfies all of the 'must' requirements but not all of the SHOULD requirements for its features is said to be conditionally compliant.

    4. Terminology

    Below is a summary of some terminology used in this documentation that can help in disambiguation of commonly applied and therefore often overloaded terms:

    Client
    The agent that is the initiator of the remote procedure call.
    Server
    Software that implements JSON-RPC, which may hosts one or more JSON-RPC services and which also acts as the gateway to lower-level protocols and transports.
    Service
    Provider of one or more procedures that may be the target of remote procedure calls by clients.
    Procedure
    A named operation on a service that may be the target of a remote procedure call. In this document, the terms method and procedure are used to mean the same thing.
    Method
    Same as Procedure.
    Call
    An invocation of a procedure on a service that results in a sequential request-response transaction between the client and the server.
    Request
    The message that frames a call and its parameters.
    Response
    The message that frames the result of a successful call or the error in the case of a failed call.
    Result
    The answer for a successful call.
    Error
    The answer for a failed call.
    Notification
    A one-way (fire and forget) call that produces no results, including any indication of error.

    5. Type System

    JSON-RPC shares the same type system as JSON to specify all value components of a call. In its abstract form (grammatic and syntatic details aside), JSON can represent four primitive types—String, Number, Booleans, and Null—and two structured types—Object and Array—that are briefly defined here:

    String
    A sequence of zero or more Unicode characters.
    Number
    An integer component optionally prefixed with a minus sign and which may be followed by a fraction part and/or an exponent part.
    Boolean
    Literally true or false.
    Null
    Literally null.
    Array
    An ordered sequence of zero or more elements, where each element hola value is a String, Number, Boolean, Null, Object or another Array. The index of the first element is zero and increments by one for each subequent element.
    Object
    An unordered collection of zero or more members. Each member is a name/value pair, where a name is a String, and a value is a String, Number, Boolean, Null, Array or another Object.

    For the remainder of this document, it is expected that the reader has some familiarity with the basic syntax of JSON text. Otherwise, consult the JSON specification (RFC 4627) for further details.

    Atif Aziz: It may be worth mentioning here how this specification makes a distinction between JSON, the abstract type system, and JSON text, the syntax for serializing the values. In XML parlance, JSON is the InfoSet and JSON text is the equivalent of XML 1.0.

    This document also uses a specific convention to refer to any JSON type. Wherever a JSON type is mentioned, the first letter is always capitalized and the whole word appears in its root form (never in its plural form).

    6. Procedure Call (Request)

    A remote procedure call is made by sending a request to a remote service using either HTTP POST or HTTP GET. How and where the call is encoded within the HTTP message depends on the HTTP method that is employed. In the case of HTTP POST, the procedure call is carried in the body of the HTTP message whereas in the case of HTTP GET, it is expressed along the path and query components of the HTTP Request-URI.

    Suppose that a service exposes a procedure named sum that takes two Number parameters, as in sum(a, b), and returns their sum. The HTTP POST to call this procedure call would be as follows:

    Procedure Call Example Using HTTP POST
    POST /myservice HTTP/1.1 
    User-Agent: Wget/1.6
    Host: www.example.com
    Content-Type: application/json
    Content-Length: 181
    Accept: application/json
    
    {
        "version" : "1.1",
        "method"  : "sum",
        "params"  : [ 17, 25 ]
    }

    In this example, the method being targeted is provided by a service located at http://www.example.com/myservice. The call is expressed as a JSON Object in the body of the HTTP POST message. The version member of this object tells the receiver the version of the JSON-RPC protocol being used by the client. The method member indicates the procedure being invoked, which is sum in this example. Finally, the params member contains a JSON Array that lists the parameters (in order) to be supplied to the procedure.

    The same invocation is shown here using HTTP GET:

    Procedure Call Example Using HTTP GET
    GET /myservice/sum?a=17&b=25 HTTP/1.1 
    User-Agent: Wget/1.6
    Host: www.example.com
    Accept: application/json
    
    

    There are two distinctions from the HTTP POST version that are improtant to note. First, an HTTP GET targeting a procedure on a JSON-RPC service is largely indistinguishable from a regular HTTP GET transaction. For this reason, there is no mention of of the JSON-RPC protocol version being used. Second, the entire call is encoded in the HTTP Request-URI. The procedure to invoke is appended to the location of the service, such that it appears as the last component of the URI path component. The call parameters appear as the query component and are named after the formal arguments of the target procedure.

    6.1. HTTP Header Requirements

    Regardless of whether a remote procedure call is made using HTTP GET or POST, the HTTP request message MUST specify the following headers:

    6.2. Call Encoding Using HTTP POST

    When using HTTP POST, the call is expressed in the HTTP request body as a JSON Object that carries the following members:

    id
    OPTIOINAL. A request identifier that can be of any JSON type. This member is essentially maintained for backward compatibility with version 1.0 of the specification where it was used to correlate a response with its request. If this member is present then the server MUST repeat it verbatim on the response.
    version
    REQUIRED. A String specifying the version of the JSON-RPC protocol to which the client conforms. An implementation conforming to this specification MUST use the exact String value of "1.1" for this member.
    method
    REQUIRED. A String containing the name of the procedure to be invoked. Procedure names that begin with the word system followed by a period character (U+002E or ASCII 46) are reserved. In other words, a procedure named system.foobar is considered to have reserved semantics.
    Atif Aziz: Ideally, this member would have been named proc to reflect the procedure in RPC, but is being left as method for sake of compatibility. One could permit both, but that could unnecessarily increase complexity. In the text of this document, however, I have tried to stick to the term procedure. If anyone spots any use of the word method, except references to the membermethod, then please let me know.
    params
    OPTIONAL. An Array or Object that holds the actual parameter values for the invocation of the procedure.

    Unless a call is for notification purposes only, bearing one-way semantics, it MUST be replied to with a response.

    6.2.1. Named and Positional Parameters

    Parameters for a procedure call can be identified by their name, position, or both. The name and position of a parameter is defined by the formal argument list of the target procedure. The first position is zero and increments by one for each subsequent formal argument.

    A client can specify parameters by-name, by-position or both using a JSON Object as the value for the params member. Each member of this object becomes a candidate parameter for the call. If the name of the object member consists entirely of decimal digits (0-9) then it identifies the parameter by its position in the formal argument list. In all other instances, the member name identifies the parameter by its name and MUST match exactly (including in case) the name defined by the formal argument.

    Suppose a remote procedure called sum that defines three formal arguments called a, b and c. Suppose further that a comes first in the argument list, b second and c third. The following example shows how this procedure would be called using named parameters in an HTTP POST transaction (the headers have been omitted from all examples in this section for sake of brevity):

    Procedure Call With Named Parameters (1)
    {
        "version" : "1.1",
        "method"  : "sum",
        "params"  : { "a" : 12, "b" : 34, "c" : 56 }
    }

    Since parameters are identified by their name, the order is insignificant. The same MAY be expressed with parameters appearing in a different order than which is defined by the formal argument list:

    Procedure Call With Named Parameters (2)
    {
        "version" : "1.1",
        "method"  : "sum",
        "params"  : { "b" : 34, "c" : 56, "a" : 12 }
    }

    A client MAY choose to send all or some of the paramters by-position, in or out of sequence. The example below shows the same call being expressed with parameters a and b named after their positions in the formal argument list:

    Procedure Call With Named and Positional Parameters
    {
        "version" : "1.1",
        "method"  : "sum",
        "params"  : { "1" : 34, "c" : 56, "0" : 12 }
    }

    If a client chooses to send parameters exclusively by their position, then it MAY use a JSON Array for the params member of the Procedure Call object as a terser method:

    Procedure Call With Positional Parameters Only (Using JSON Array)
    {
        "version" : "1.1",
        "method"  : "sum",
        "params"  : [ 12, 34, 56 ]
    }

    A server MUST accept all forms of parameter expressions described in this section. The last case, where parameters are sent in an array, was the only one supported in JSON-RPC 1.0. Servers conforming to JSON-RPC 1.1 can therefore continue to support calls from existing JSON-RPC 1.0 clients.

    If the value of the params member is any other type except JSON Object or Array, then the server MUST reject the call with an error.

    Atif Aziz: Need to add a comment about which error should be specifically returned if the params member is neither JSON Object or Array.

    6.2.2. Choosing Between Named and Positional Parameters

    Calls that identify all parameters exclusively by-name are RECOMMENDED over any positional parameters for the following reasons:

    1. The call appears more readable and self-contained on the wire, which can aid in logging and diagnosis without having to constantly consult the procudure definitions.
    2. The client gains independence from any change in the order of the formal argument list.
    3. If the formal argument list is large and mostly optional, the client can send only those parameters by-name that it needs to fulfill the purpose of a particular call.

    6.2.3. Null Parameters

    The Null value MAY be used as the value of any parameter and MUST be taken to mean that the parameter is not being supplied for the call.

    6.2.4. Member Sequence

    Client implementations SHOULD strive to order the members of the Procedure Call object such that the server is able to employ a streaming strategy to process the contents. At the very least, a client SHOULD ensure that the version member appears first and the params member last. An example how this can be an advantage is where a client tries to invoke a procedure that does not exist on the target service. The server can then skip to the end and issue an error as soon as it reads the value of the method member and finds it to be in error.

    Atif Aziz: Allow a server to refuse a request if it does not wish to process a request where the params member appears before method.

    6.3. Call Encoding Using HTTP GET

    When using HTTP GET, the target procedure and parameters for the call are entirely expressed within the Request-URI of the HTTP message. The target procedure MUST appear as the last component of the Request-URI path component. The procedure's name MUST therefore be preceded by a forward-slash (U+002F or ASCII 47) but MUST NOT end in one.

    The parameters are placed in the query component (as defined in RFC 3986) of the Request-URI, which is then formatted using the same scheme as defined for HTML Forms with the get method. Each parameters consists of a name/position and value pair that is separated by the equal sign (U+003D or ASCII 61) and parameters themselves are separated by an ampersand (U+0026 or ASCII 38):

    name1=value1&name2=value2&name3=value3…

    A client MAY send the parameters in a different order than in which the formal argument list of the target procedure defines them.

    6.3.1. Encoding of Call Parameter Values

    The client MUST NOT use the JSON syntax for the parameter values. All values MUST be plain text and observe the escaping rules defined for the query component of the URL. After decoding, the server MUST treat all values as if they were sent as JSON String values. The server MAY then perform conversions at its discretion (on a best-attempt basis) if the formal arguments of the target procedure expects other non-String values. This specification does not define any conversion rules or methods.

    Parameters named identically on the query string MUST be collapsed into an Array of String values using the same order in which they appear in the query string and identified by the repeating parameter name. For instance, the following query string specifies two parameters only, namely scale and city:

    city=london&scale=farenheit&city=zurich&city=new+york

    The parameter scale has the single String value of "farenheit" whereas city is an Array of String values equivalent to the JSON text [ "london", "zurich", "new york" ].

    It is specifically not possible to send parameters of type Object using HTTP GET.

    6.3.2. Safe and Idempotent Procedures Only

    Due to semantics and therefore requirements of HTTP GET, only procedures that are considered safe and idempotent MAY be invoked using HTTP GET. An explanation of what is considered safe and idempotent is provided in Section 9.1 (Safe and Idempotent Methods) of HTTP 1.1 specificiation. A server SHOULD provide a means (through a configuration file, for example) for a service to indicate which of its procedures are safe and idempotent in order to be callable using HTTP GET. In the absence of such means on the other hand, the server MUST allow invocations using HTTP POST only.

    A server MUST respond with an error if a client attempts to invoke a procedure that has not been designated by the service as safe for call using HTTP GET.

    A procedure callable using HTTP GET SHOULD also be callable using HTTP POST.

    6.4. Choosing Between HTTP POST and GET

    The choice of the HTTP method for a remote procedure call depends on the consequences of calling the procedure as well as the benefits afforded by each of the two HTTP methods. In general, any remote procedure call can be made using HTTP POST, but some benefits

    HTTP GET can be particularly useful when:

    • The procedure is safe, idempotent and compatible with HTTP GET semantics. Therefore it produces information without causing side-effects.
    • The procedure has only arguments that are compatible with scalar JSON types Boolean, Number and String.
    • Performance benefits can be leveraged through client-side caching as well as caching on HTTP proxy infrastructure that is widely available and deployed over intranets and on the Internet.

    6.5. Case-Sensitivity of Procedure and Parameter Names

    Conforming implementations MUST treat procedure and parameter names as being case-sensitive such the names bar and BAR would be seen as two distinct entities.

    6.6. Procedure Call Parity

    The parity of a procedure call is defined by how closely it matches the target procedure's formal definition and argument list. A call is on full parity with the target procedure when it meets all of the following conditions:

    1. All parameters were supplied and none had the Null value.
    2. No extra parameters were supplied.
    3. The values for each parameter matched exactly the expected type.

    Note that when parameters are named by-position or by-name, their sequence does not change or contribute to the parity of the call. A call can have full parity with its procedure even if the parameters were not sent in the sequence of the formal argument list.

    6.6.1. Call Approximation

    A server SHOULD try to adapt a call such that it has the greatest chance of succeeding by making the following adjustments for the actual invocation:

    • If the call supplies fewer parameters than expected then the missing parameters SHOULD assume the Null value.
    • If the call supplies more parameters than expected then they MAY be dropped prior to invocation. A server MAY however, provide a means for a procedure to receive the excess parameters if necessary (for example by allowing a variable-length argument list).
    • Make reasonable conversions between the actual and expected type of a parameter. The eventual conversion methods and policies applied to approximate a call are left at the discretion of the server and service, but both SHOULD strive to avoid conversions that cause any loss or precision of data.

    7. Procedure Return (Response)

    When a remote procedure call is made, the service MUST reply with a response whether the invocation was successful or not.

    7.1. HTTP Status Code Requirements

    When the call is made using HTTP POST, the HTTP status code for a successful result MUST be 200.

    When the call is made using HTTP GET, the HTTP status code for a successful result SHOULD be 200. If the HTTP GET call requested cache validation as well, the response MAY be 304 (Not Modified). The use of status codes generally related to redirection (e.g., 302 “Found†or 301 “Moved Permanentlyâ€) of HTTP GET transactions is not strictly prohibited, but service providers are RECOMMENDED instead to use public documentation and communication methods to advertise the relocation of a service.

    Clients SHOULD be prepared to handle a status code of 401 (Unauthorized) resulting from an authentication challenge when a call is sent anonymously.

    Unless noted otherwise, a status code of 500 (Internal Server Error) MUST be used under the following conditions:

    • There was an error parsing the JSON text comprising the Procedure Call.
    • The target procedure does not exist on the server. For HTTP GET, a server SHOULD use 404 (Not Found) instead of 500.
    • The procedure could not be invoked due to an error resulting from call approximation.
    • The invocation took place but resulted in an error from inside the procedure.

    7.2. HTTP Header Requirements

    Regardless of the HTTP method used to make the remote procedure call, the HTTP response message MUST specify the following headers:

    7.3. Procedure Return Object

    Regardless of the HTTP method used to make the remote procedure call, the response body MUST be a JSON Object that carries the following properties or members:

    id
    OPTIONAL. This MUST be the same value as that of the id member of Procedure Call object to which the response corresponds. This member is maintained for backward compatibility with version 1.0 of the specification where it was used to correlate a response with its request. If the id member was present on the request, then the server MUST repeat it verbatim on the response.
    version
    REQUIRED. A String specifying the version of the JSON-RPC protocol to which the client conforms. An implementation conforming to this specification MUST use the exact String value of "1.1" for this member. The absence of this member can effectively be taken to mean that the remote server implement version 1.0 of the JSON-RPC protocol.
    result
    REQUIRED on success. The value that was returned by the procedure upon a successful invocation. This member MUST be entirely omitted in case there was an error invoking the procedure.
    error
    REQUIRED on error. An Object containing error information about the fault that occured before, during or after the call. This member MUST be entirely omitted if there was no error.

    Only one of result or error members MUST be specified, but never both. If both are missing, then the Procedure Return should be treated as if it had the value Null.

    Procedure Return Example
    HTTP/1.1 200 OK
    Connection: close
    Content-Length: 23
    Content-Type: application/json
    Date: Sat, 08 Jul 2006 12:04:08 GMT
    Server: Microsoft-IIS/6.0
    
    {
        "version" : "1.1",
        "result"  : 42
    }

    7.4. Error Object

    When a remote procedure call fails, the Procedure Return object MUST contain the error member whose value is a JSON Object with the following properties members:

    name
    REQUIRED. A String value that MUST read "JSONRPCError".
    code
    REQUIRED. A Number value that indicates the actual error that occurred. This MUST be an integer between 100 and 999.
    message
    REQUIRED. A String value that provides a short description of the error. The message SHOULD be limited to a single sentence.
    error
    OPTIONAL. A JSON Null, Number, String or Object value that carries custom and application-specific error information. Error objects MAY be nested using this property.
    Error Procedure Return Example
    {
        "version" : "1.1",
        "error" : {
            "name" : "JSONRPCError",
            "code" : 123,
            "message" : "An error occurred parsing the request object.",
            "error" : {
                "name" : "JSONError",
                "message" : "Bad array",
                "at" : 42,
                "text" : "{\"id\":1,\"method\":\"sum\",\"params\":[1,2,3,4,5}"} 
            }
    }

    The following table lists the errors codes defined by this specification:

    code Example Message Meaning
    000 Server error A general error occurred on the server prior to procedure invocation on the service.
    000 Parse error An error occurred on the server while parsing the JSON text comprising the procedure call.
    000 Bad call The procedure call is not valid.
    000 Call member out of sequence The server refuses to process the call because a member is not in the required sequence. For example, the params member of the Procedure Call object appeared before version or method members.
    000 Service error The call is valid, but a general error occurred during the procedure invocation.
    000 Procedure not found The call is valid but the procedure identified by the call could not be located on the service.
    Atif Aziz: Assign error codes and add a passage on how they should be interpreted. Particularly, which error codes indicate that a call must not be repeated verbatim without some change.

    8. Processing Model

    The processing model for the treatment of a remote procedure call is outlined as follows:

    • Determine the HTTP method of the Procedure Call.
    • Decode the call using the rules laid out for HTTP PSO
    • Rearrange the parameter order according to the formal argument list of the procedure.

    9. Services

    A JSON-RPC service MUST, at a mimum, support a procedure called system.describe. The result of calling this procedure without any parameters MUST be a Service Description object as described in the next section.

    10. Service Description

    A service description is a JSON Object with the following members or properties:

    sdversion
    REQUIRED. A String value that represents the version number of this object and MUST read "1.0" for conforming implementations.
    name
    REQUIRED. A String value that provides a simple name for the method.
    id
    REQUIRED. A String value that uniquely and globally identifies the service. The string MUST use the URI Generic Syntax (RFC 3986).
    version
    OPTIONAL. A String value that indicates version number of the service and MAY be used by the applications for checking compatibility. The version number, when present, MUST include a major and minor component separated by a period (U+002E or ASCII 46). The major and minor components MUST use decimal digits (0 to 9) only. For example, use "2.5" to mean a major version of 2 and a minor version of 5. The use and interpretation of the version number is left at the discretion of the applications treating the Service Description.
    summary
    OPTIONAL. A String value that summarizes the purpose of the service. This SHOULD be kept to a maximum of 5 sentences and often limited a single phrase like, “The News Search service allows you to search the Internet for news stories.â€
    Atif Aziz: Not sure if summary has any useful purpose in a service description. There is the help member to serve a similar purpose anyhow. Also, without this member being typed as Object, it is difficult to imagine how to communicate the language of the text unless one includes a language member (which starts to make things messy).
    help
    OPTIONAL. A String value that is a URL from where human-readable documentation about the service may be obtained.
    address
    OPTIONAL. A String value that is the URL of the service end-point to which the remote procedure calls can be targeted. The protocol scheme of this URL SHOULD be http or https. Although this value is optional, it is highly RECOMMENDED that a service always publish its address so that a service description obtained indirectly can be used nonetheless to locate the service.
    procs
    OPTIONAL. An Array value whose element contain Service Procedure Description objects, each of uniquely describes a single procedure. If the only description of each procedure that a service has is its name, then it MAY instead supply an Array of String elements for this member and where each element uniquely names a procedure.

    A service SHOULD NOT include the system.describe procedure in its description as it is assumed that all conforming services MUST support it.

    10.1. Service Procedure Description

    A procedure description is a JSON Object with the following members and properties:

    name
    REQUIRED. A String value that provides a simple name for the method.
    summary
    OPTIONAL. A String value that summarizes the purpose of the service. This SHOULD be kept to a maximum of 3 sentences and often limited to a single phrase like, “Lets you search for hyperlinks that have been tagged by particular tags.â€
    Atif Aziz: Not sure if summary has any useful purpose in a service procedure description. There is the help member to serve a similar purpose anyhow. Also, without this member being typed as Object, it is difficult to imagine how to communicate the language of the text unless one includes a language member (which starts to make things messy).
    help
    OPTIONAL. A String value that is a URL from where human-readable documentation about the procedure may be obtained.
    idempotent
    OPTIONAL. A Boolean value that indicates whether the procedure is idempotent and therefore essentially safe to invoke over an HTTP GET transaction. This member MUST be present and true for the procedure to be considered idempotent.
    params
    OPTIONAL. An Array value whose elements are either Procedure Parameter Description objects or String values. If an element each of uniquely describes a single parameter of the procedure. If the only description that is available of each parameter is its name, then a service MAY instead supply an Array of String elements for this member and where each element uniquely names a parameter and the parameter is assumed to be typed as "any". In either case, the elements of the array MUST be ordered after the formal argument list of the procedure being described. If this member is missing or the Null value then the procedure does not expect any parameters.
    return
    OPTIONAL. An Object value that is structured after the Procedure Parameter Description and which describes the output from the procedure. Otherwise, if it is a String value, then it defines the type of the return value. If this member is missing or is the Null value then the return type of the procedure is defined to be "any".

    10.2. Procedure Parameter Description

    A procedure description is a JSON Object with the following members and properties:

    name
    REQUIRED. A String value that provides a simple name for parameter.
    type
    OPTIONAL. A String value that denotes the expected value type for the parameter. If this member is not supplied or is the Null value then the type is defined "any".

    10.2.1. Parameter and Return Type Strings

    The type member of the Procedure Parameter Description MAY be one of the following String values:

    "bit"
    Boolean
    "num"
    Number
    "str"
    String
    "arr"
    Array
    "obj"
    Object
    "any"
    Boolean, Number, String, Array or Object
    "nil"
    None (valid only for procedure return type)

    If another String value is found then it must be treated the same as "any".

    The "nil" string MUST NOT be used to describe the type of a procedure's formal argument. Rather, it is strictly reserved to denote the return type of a procedure that is not expected to produce a result. In other words, the result member of the Procedure Return object resulting from a call to such procedure is not interesting because it will always be the Null value.

    It is valid for a call to supply the Null value for any parameter no matter how it is typed in its description.

    10.3. Service Description Example

    Below is an example of Service Description object that describes a fictious DemoService service that resides at the address http://www.example.com/service and which publishes a single procedure called sum with two Number parameters, namely a and b, and which returns a Number result.

    Service Description Example
    {
        "name"    : "DemoService",
        "id"      : "urn:uuid:41544946-415a-495a-5645-454441534646",
        "summary" : "A simple demonstration service.",
        "help"    : "http://www.example.com/service/index.html",
        "address" : "http://www.example.com/service",
        "procs" : [ 
            {
                "name"    : "sum",
                "summary" : "Sums two numbers.",
                "help"    : "http://www.example.com/service/sum.html",
                "params"  : [ 
                    { "name" : "a", "type" : "num" }, 
                    { "name" : "b", "type" : "num" } ],
                "return" : {
                    "type" : "num" 
            }, 
            {
                "name"    : "time",
                "summary" : "Returns the current date and time in ISO 8601 format.",
                "help"    : "http://www.example.com/service/time.html",
                "return" : {
                    "type" : "string" 
            } 
        ]
    }

    10.4. Language of the Description Objects

    The summary members of the Service Description and Procedure Description objects contain human-readable text. A service MAY use the Accept-Language header from the HTTP request message to deliver a localized text for its String value. Likewise, the URL for the help members MAY also point a page that contains the localized documentation. However, the documentation at the URL SHOULD also provide hyperlinks to the documentation in other languages if the translations are available.

    11. Service, Procedure and Parameter Names

    In JSON-RPC, service, procedure, parameters identifiable by name. The names of all these artifacts SHOULD only include:

    • Uppercase alphabets A to Z (U+0041 to U+005A, ASCII 65 to 90)
    • Lowercase alphabets A to Z (U+0061 to U+007A, ASCII 97 to 122)
    • Decimal digits 0 to 9 (U+0030 to U+0039, ASCII 48 to 57)
    • Hyphen (U+002D, ASCII 45)

    All other characters in a name, although not technically excluded here, could severely limit the reach of the service and its procedures given certain environments, scenarios and especially programming languages.

    12. Object Extensions

    Objects defined in this specification (Procedure Call, Procedure Return, Error) MAY contain additional members not specifically mentioned. Such member names SHOULD be prefixed with the Dollar sign (U+0024 or ASCII 36), as in $extension.

    Atif Aziz: The reason for choosing the Dollar sign is related to the JavaScript heritage. According to the ECMAScript Language Specification (ECMA-262), “The Dollar sign is intended for use only in mechanically generated code.†Although the general convention in Internet protocols is to use the letter X followed by a dash (U+002D or ASCII 45), as in x-extension, the Dollar sign seems like a more natural and appropriate fit for JSON-RPC. Should we really be caring about the JavaScript/JSON heritage in a communication protocol? One downside of using Dollar sign is that it reserved in the Query component of the URI Generic Syntax (RFC 2396).
    Atif Aziz: Add comment about CGI binding for extensions on the Procedure Call object?

    13. Limitations

    It is worth noting that JSON-RPC is limited by the inability to represent cyclic object graphs in JSON text. Therefore implementations SHOULD take care that parent-child, sibling and cross-reference relationships result in error at the client end when making the remote procedure call or server end when responding with the result of the call. There are two possible ways to control this:

    • Configure a maximum allowed size of the request and response messages produced for a remote procedure call.
    • Configure a maximum depth of nesting of Array and Object values.

    As soon as either configured limit is breached, the client or server fail the call with an error.

    ././@LongLink0000000000000000000000000000015500000000000011566 Lustar rootrootrabbitmq-server-3.2.4/plugins-src/erlang-rfc4627-wrapper/erlang-rfc4627-git/src/rfc4627_jsonrpc_mochiweb.erlrabbitmq-server-3.2.4/plugins-src/erlang-rfc4627-wrapper/erlang-rfc4627-git/src/rfc4627_jsonrpc_moch0000644000000000000000000001116612305126066031317 0ustar rootroot%% JSON-RPC for Mochiweb %%--------------------------------------------------------------------------- %% @author Tony Garnock-Jones %% @author LShift Ltd. %% @copyright 2007-2010, 2011, 2012 Tony Garnock-Jones and 2007-2010 LShift Ltd. %% @license %% %% Permission is hereby granted, free of charge, to any person %% obtaining a copy of this software and associated documentation %% files (the "Software"), to deal in the Software without %% restriction, including without limitation the rights to use, copy, %% modify, merge, publish, distribute, sublicense, and/or sell copies %% of the Software, and to permit persons to whom the Software is %% furnished to do so, subject to the following conditions: %% %% The above copyright notice and this permission notice shall be %% included in all copies or substantial portions of the Software. %% %% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, %% EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF %% MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND %% NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS %% BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN %% ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN %% CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE %% SOFTWARE. %%--------------------------------------------------------------------------- %% @since 1.2.0 %% %% @reference the Mochiweb home page %% %% @doc Support for serving JSON-RPC via Mochiweb. %% %% Familiarity with writing Mochiweb applications is assumed. %% %% == Basic Usage == %% %%
      %%
    • Register your JSON-RPC services as usual.
    • %%
    • Decide on your `AliasPrefix' (see {@link rfc4627_jsonrpc_http:invoke_service_method/4}).
    • %%
    • When a Mochiweb request arrives at your application, call {@link handle/2} with your `AliasPrefix' and the request.
    • %%
    %% %% It's as simple as that - if the request's URI path matches the %% `AliasPrefix', it will be decoded and the JSON-RPC service it names %% will be invoked. -module(rfc4627_jsonrpc_mochiweb). -export([handle/2]). normalize(X) when is_atom(X) -> string:to_lower(atom_to_list(X)); normalize(X) when is_binary(X) -> string:to_lower(binary_to_list(X)); normalize(X) when is_list(X) -> string:to_lower(X). %% @spec (string(), #mochiweb_request{}) -> no_match | {ok, Response} %% where Response = {Code, ReplyHeaders, ReplyBody} %% Code = integer() %% ReplyHeaders = [{string(), string()}] %% ReplyBody = string() %% %% @doc If the request matches `AliasPrefix', the corresponding %% JSON-RPC service is invoked, and an `{ok, Response}' is returned; %% otherwise, `no_match' is returned. %% %% Call this function from your Mochiweb application's `loop' %% function, as follows: %% %% ``` %% case rfc4627_jsonrpc_mochiweb:handle("/rpc", Req) of %% no_match -> %% handle_non_jsonrpc_request(Req); %% {ok, Response} -> %% Req:respond(Response) %% end %% ''' %% %% where `handle_non_jsonrpc_request' does the obvious thing for %% non-JSON-RPC requests. handle(AliasPrefix, Req) -> Path = Req:get(path), QueryObj = {obj, [{K, list_to_binary(V)} || {K,V} <- Req:parse_qs()]}, HeaderObj = {obj, [{normalize(K), list_to_binary(V)} || {K,V} <- mochiweb_headers:to_list(Req:get(headers))]}, RequestInfo = {obj, [{"http_method", list_to_binary(atom_to_list(Req:get(method)))}, {"http_query_parameters", QueryObj}, {"http_headers", HeaderObj}, {"remote_peername", list_to_binary(Req:get(peer))}, {"scheme", <<"http">>}]}, Body = Req:recv_body(), case rfc4627_jsonrpc_http:invoke_service_method(AliasPrefix, Path, RequestInfo, Body) of no_match -> no_match; {ok, ResultEnc, ResponseInfo} -> DefaultType = rfc4627:mime_type(), RespType = case Req:accepts_content_type(DefaultType) of true -> DefaultType; false -> case Req:accepts_content_type("text/plain") of true -> "text/plain"; false -> DefaultType end end, {obj, ResponseHeaderFields} = rfc4627:get_field(ResponseInfo, "http_headers", {obj, []}), StatusCode = rfc4627:get_field(ResponseInfo, "http_status_code", 200), Headers = [{K, binary_to_list(V)} || {K,V} <- ResponseHeaderFields], {ok, {StatusCode, Headers ++ [{"Content-type", RespType}], ResultEnc}} end. ././@LongLink0000000000000000000000000000015000000000000011561 Lustar rootrootrabbitmq-server-3.2.4/plugins-src/erlang-rfc4627-wrapper/erlang-rfc4627-git/src/rfc4627_jsonrpc_sup.erlrabbitmq-server-3.2.4/plugins-src/erlang-rfc4627-wrapper/erlang-rfc4627-git/src/rfc4627_jsonrpc_sup.0000644000000000000000000000321112305126066031246 0ustar rootroot%% @author Tony Garnock-Jones %% @author LShift Ltd. %% @copyright 2007-2010, 2011, 2012 Tony Garnock-Jones and 2007-2010 LShift Ltd. %% @license %% %% Permission is hereby granted, free of charge, to any person %% obtaining a copy of this software and associated documentation %% files (the "Software"), to deal in the Software without %% restriction, including without limitation the rights to use, copy, %% modify, merge, publish, distribute, sublicense, and/or sell copies %% of the Software, and to permit persons to whom the Software is %% furnished to do so, subject to the following conditions: %% %% The above copyright notice and this permission notice shall be %% included in all copies or substantial portions of the Software. %% %% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, %% EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF %% MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND %% NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS %% BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN %% ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN %% CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE %% SOFTWARE. -module(rfc4627_jsonrpc_sup). -behaviour(supervisor). -export([start_link/0, init/1]). start_link() -> supervisor:start_link({local, ?MODULE}, ?MODULE, _Arg = []). init([]) -> {ok, {{one_for_one, 3, 10}, [{rfc4627_jsonrpc, {rfc4627_jsonrpc, start_link, []}, permanent, 10000, worker, [rfc4627_jsonrpc]} ]}}. ././@LongLink0000000000000000000000000000015100000000000011562 Lustar rootrootrabbitmq-server-3.2.4/plugins-src/erlang-rfc4627-wrapper/erlang-rfc4627-git/src/rfc4627_jsonrpc_http.erlrabbitmq-server-3.2.4/plugins-src/erlang-rfc4627-wrapper/erlang-rfc4627-git/src/rfc4627_jsonrpc_http0000644000000000000000000001557212305126066031355 0ustar rootroot%% JSON-RPC for HTTP transports (inets, mochiweb, yaws, ...) %%--------------------------------------------------------------------------- %% @author Tony Garnock-Jones %% @author LShift Ltd. %% @copyright 2007-2010, 2011, 2012 Tony Garnock-Jones and 2007-2010 LShift Ltd. %% @license %% %% Permission is hereby granted, free of charge, to any person %% obtaining a copy of this software and associated documentation %% files (the "Software"), to deal in the Software without %% restriction, including without limitation the rights to use, copy, %% modify, merge, publish, distribute, sublicense, and/or sell copies %% of the Software, and to permit persons to whom the Software is %% furnished to do so, subject to the following conditions: %% %% The above copyright notice and this permission notice shall be %% included in all copies or substantial portions of the Software. %% %% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, %% EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF %% MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND %% NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS %% BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN %% ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN %% CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE %% SOFTWARE. %%--------------------------------------------------------------------------- %% @since 1.2.0 %% %% @doc General JSON-RPC HTTP transport support. %% %% Used by the Inets HTTP transport library, {@link %% rfc4627_jsonrpc_inets}. -module(rfc4627_jsonrpc_http). -include("rfc4627_jsonrpc.hrl"). -export([invoke_service_method/4]). %% @spec (AliasPrefix, Path, RequestInfo, Body) -> Result %% where AliasPrefix = default | string() %% Path = string() %% RequestInfo = rfc4627:jsonobj() %% Body = string() | binary() %% Result = no_match | {ok, string(), jsonobj()} %% %% @doc Uses `AliasPrefix', `RequestInfo', `Path' and `Body' to locate %% and invoke a service procedure. %% %% If `AliasPrefix' is `default', the default prefix `"/jsonrpc"' is used. %% %% `Path' is expected to be the "path" part of the request URI: a string of the form "/.../prefix/objectname[/methodname]". %% %% `RequestInfo' is a JSON "object" containing HTTP-specific request information: %% %%
      %%
    • `http_method' should be either `<<"GET">>' (the default) or `<<"POST">>'
    • %%
    • `http_query_parameters' should be the query parameters (the part of the URL after "?") %% decoded into a JSON "object", with one field per parameter
    • %%
    • `http_headers' should be a JSON "object" containing the HTTP request headers
    • %%
    • `scheme' should be either `<<"http">>' or `<<"https">>'
    • %%
    • `remote_port' should be the TCP port number of the remote peer
    • %%
    • `remote_peername' should be a {@type binary()} containing the IP address of the %% remote peer, in a form acceptable to {@link inet:gethostbyaddr/1}
    • %%
    %% %% All the fields in `RequestInfo' are optional. %% %% `Body' must be either a {@type binary()} or a {@type string()} %% containing the HTTP request body. %% %% Operation proceeds as follows. `Path' is first matched against %% `AliasPrefix'. If it does not match, `no_match' is %% returned. Otherwise, the matching prefix is stripped from the path, %% and extraction of the service name, method name, and parameters from %% the HTTP request proceeds as per the JSON-RPC specification, %% [JSON-RPC-1-1-WD-20060807.html#ProcedureCall]. %% %% Once the service name, method name and parameters are known, The %% service is looked up with {@link rfc4627_jsonrpc:lookup_service/1}, %% and the named method is invoked with {@link %% rfc4627_jsonrpc:invoke_service_method/8}. %% %% The final result is encoded into a list of bytes using {@link %% rfc4627:encode/1}, and returned along with the `ResponseInfo' to %% our caller. invoke_service_method(default, Path, RequestInfo, Body) -> invoke_service_method("/jsonrpc", Path, RequestInfo, Body); invoke_service_method(AliasPrefix, Path, RequestInfo, Body) -> case parse_jsonrpc(AliasPrefix, Path, rfc4627:get_field(RequestInfo, "http_method", <<"GET">>), rfc4627:get_field(RequestInfo, "http_query_parameters", {obj, []}), Body) of no_match -> no_match; {PostOrGet, Id, Service, Method, Args} -> {_ResultOrError, Result, ResponseInfo} = case rfc4627_jsonrpc:lookup_service(Service) of not_found -> Err = rfc4627_jsonrpc:error_response(404, "Service not found", Service), rfc4627_jsonrpc:expand_jsonrpc_reply(Id, Err); ServiceRec -> HttpHeaders = rfc4627:get_field(RequestInfo, "http_headers", {obj, []}), Timeout = extract_timeout_header(HttpHeaders), EndpointAddress = service_address(AliasPrefix, RequestInfo, Service), rfc4627_jsonrpc:invoke_service_method( ServiceRec, Id, PostOrGet, RequestInfo, EndpointAddress, Method, Args, Timeout) end, ResultEnc = lists:flatten(rfc4627:encode(Result)), {ok, ResultEnc, ResponseInfo} end. extract_timeout_header(HeadersJsonObj) -> case rfc4627:get_field(HeadersJsonObj, "x-json-rpc-timeout", <<"default">>) of <<"default">> -> default; <<"infinity">> -> infinity; Other -> list_to_integer(binary_to_list(Other)) end. extract_object_and_method(AliasPrefix, Path) -> AliasPrefixRe = "^" ++ AliasPrefix ++ "/", case re:run(Path, AliasPrefixRe) of {match, [{0, Length}]} -> ObjectMethod = string:substr(Path, Length + 1), case lists:reverse(string:tokens(ObjectMethod, "/")) of [] -> {<<>>, <<>>}; [Object] -> {list_to_binary(Object), <<>>}; [Method1, Object | _] -> {list_to_binary(Object), list_to_binary(Method1)} end; nomatch -> no_match end. parse_jsonrpc(AliasPrefix, Path, HttpMethod, QueryParametersObj, Body) -> case extract_object_and_method(AliasPrefix, Path) of no_match -> no_match; {Object, PathMethod} -> case HttpMethod of <<"POST">> -> {ok, RequestObject, _} = rfc4627:decode(Body), {post, rfc4627:get_field(RequestObject, "id", null), Object, rfc4627:get_field(RequestObject, "method", undefined), rfc4627:get_field(RequestObject, "params", [])}; _ -> %% GET, presumably. We don't really care, here. {get, null, Object, PathMethod, QueryParametersObj} end end. service_address(AliasPrefix, RequestInfo, ServiceName) -> HttpHeaders = rfc4627:get_field(RequestInfo, "http_headers", {obj, []}), Host = case rfc4627:get_field(HttpHeaders, "host", undefined) of undefined -> ""; Name -> "//" ++ binary_to_list(Name) end, Scheme = case rfc4627:get_field(RequestInfo, "scheme", undefined) of undefined -> ""; S -> binary_to_list(S) ++ ":" end, list_to_binary(Scheme ++ Host ++ AliasPrefix ++ "/" ++ binary_to_list(ServiceName)). ././@LongLink0000000000000000000000000000015000000000000011561 Lustar rootrootrabbitmq-server-3.2.4/plugins-src/erlang-rfc4627-wrapper/erlang-rfc4627-git/src/rfc4627_jsonrpc_app.erlrabbitmq-server-3.2.4/plugins-src/erlang-rfc4627-wrapper/erlang-rfc4627-git/src/rfc4627_jsonrpc_app.0000644000000000000000000000264612305126066031232 0ustar rootroot%% @author Tony Garnock-Jones %% @author LShift Ltd. %% @copyright 2007-2010, 2011, 2012 Tony Garnock-Jones and 2007-2010 LShift Ltd. %% @license %% %% Permission is hereby granted, free of charge, to any person %% obtaining a copy of this software and associated documentation %% files (the "Software"), to deal in the Software without %% restriction, including without limitation the rights to use, copy, %% modify, merge, publish, distribute, sublicense, and/or sell copies %% of the Software, and to permit persons to whom the Software is %% furnished to do so, subject to the following conditions: %% %% The above copyright notice and this permission notice shall be %% included in all copies or substantial portions of the Software. %% %% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, %% EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF %% MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND %% NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS %% BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN %% ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN %% CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE %% SOFTWARE. -module(rfc4627_jsonrpc_app). -export([start/2, stop/1]). -behaviour(application). start(normal, []) -> rfc4627_jsonrpc_sup:start_link(). stop(_State) -> ok. rabbitmq-server-3.2.4/plugins-src/erlang-rfc4627-wrapper/erlang-rfc4627-git/src/rfc4627_jsonrpc.erl0000644000000000000000000005543312305126066031077 0ustar rootroot%% JSON-RPC, transport-neutral. %%--------------------------------------------------------------------------- %% @author Tony Garnock-Jones %% @author LShift Ltd. %% @copyright 2007-2010, 2011, 2012 Tony Garnock-Jones and 2007-2010 LShift Ltd. %% @license %% %% Permission is hereby granted, free of charge, to any person %% obtaining a copy of this software and associated documentation %% files (the "Software"), to deal in the Software without %% restriction, including without limitation the rights to use, copy, %% modify, merge, publish, distribute, sublicense, and/or sell copies %% of the Software, and to permit persons to whom the Software is %% furnished to do so, subject to the following conditions: %% %% The above copyright notice and this permission notice shall be %% included in all copies or substantial portions of the Software. %% %% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, %% EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF %% MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND %% NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS %% BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN %% ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN %% CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE %% SOFTWARE. %%--------------------------------------------------------------------------- %% @since 1.2.0 %% %% @reference the JSON-RPC specification (draft; mirrored locally) %% %% @doc Provides a registry of running JSON-RPC objects, and a %% transport-neutral means of invoking methods defined on such %% objects. %% %% Other modules provide interfaces to specific transports and %% transport implementations. See {@link rfc4627_jsonrpc_http} and %% {@link rfc4627_jsonrpc_inets}, for example. %% %% == JSON-RPC Objects are Erlang Processes == %% %% In the normal case, each JSON-RPC object in a running system %% corresponds to one Erlang process. This makes object lifecycle %% control very natural. %% %% == Basic usage == %% %% Ensure the registry process is running, using {@link start/0} or %% {@link start_link/0}. Once it's up and running, use {@link %% register_service/2} to expose a process as a JSON-RPC service. %% %% To register a service, you will need to describe the methods %% available on it. Use {@link service/4} to do so. %% %% == Implementing a service == %% %% Your service should be implemented by a `gen_server' %% process. JSON-RPC requests will be sent to it as %% `gen_server:call/2' messages: %% %% ``{jsonrpc, ProcedureNameBin, RequestInfo, Args}'' %% %% Your module's `handle_call' function should respond to these %% messages with a reply of type {@type jsonrpc_response()}. %% %% Here's the implementation of the "test_proc" example: %% %% ``` %% handle_call({jsonrpc, <<"test_proc">>, _RequestInfo, [Value]}, _From, State) -> %% {reply, {result, <<"ErlangServer: ", Value/binary>>}, State}. %% ''' %% %% See also the complete example Erlang module included with the %% source code, `test_jsonrpc_inets.erl'. %% %% == Registering a service with the Service Registry == %% %% You will need to ``-include("rfc4627_jsonrpc.hrl").'' (Or, if %% you've installed the compiled `rfc4627_jsonrpc' code in your Erlang %% lib directory, %% ``-include_lib("rfc4627/include/rfc4627_jsonrpc.hrl").'') %% %% The service registry must be started before any registrations can %% be performed: simply call {@link start/0} or {@link %% start_link/0}. This will start the registry if it wasn't running, %% or if it was, it will inform you of the existing registry's Pid. %% %% Registering a service is as simple as starting a process to receive %% service requests, and passing its pid to `rfc4627_jsonrpc' along %% with a service %% descriptor object built from Erlang records defined in %% `mod_jsonrpc.hrl': %% %% ``` %% {ok, Pid} = gen_server:start(?MODULE, [], []), %% rfc4627_jsonrpc:register_service %% (Pid, %% rfc4627_jsonrpc:service(<<"test">>, %% <<"urn:uuid:afe1b4b5-23b0-4964-a74a-9168535c96b2">>, %% <<"1.0">>, %% [#service_proc{name = <<"test_proc">>, %% idempotent = true, %% params = [#service_proc_param{name = <<"value">>, %% type = <<"str">>}]}])). %% ''' %% %% This code registers a service called "test": %% %%
      %%
    • its name is "test"
    • %%
    • its identifier (JSON-RPC's service description "id" field) is "urn:uuid:afe1b4b5-23b0-4964-a74a-9168535c96b2"
    • %%
    • its version string is "1.0"
    • %%
    • %% it defines just one method/procedure, which %%
        %%
      • is named "test_proc"
      • %%
      • is marked "idempotent", which means it is permitted to be accessed via HTTP GET instead of only HTTP POST
      • %%
      • has a single parameter named "value" of type "str"
      • %%
      %%
    • %%
    %% %% Note that almost all of the string values are expressed as %% binaries: this is because {@link rfc4627} uses binaries to %% represent JSON strings. %% %% To register a service with multiple procedures, add additional %% `#service_proc' records to the procedure list in the call to {@link %% service/4}. Similarly, additional parameters for each procedure can %% be defined by the addition of extra `#service_proc_param' records %% in the appropriate place. %% %% The available types for parameters are the strings defined in this %% part of the JSON-RPC specification, namely "bit", "num", "str", %% "arr", "obj", "any" or "nil". See also %% `rfc4627_jsonrpc:proc_param_type/1'. %% %% == Invoking methods on local services == %% %% Usually, JSON-RPC services are invoked via HTTP using {@link %% rfc4627_jsonrpc_inets} or similar. However, the interface used by %% specific network transports to call methods on services is also %% available to ordinary programs. (And, of course, programs that %% implement new kinds of network transport for JSON-RPC.) %% %% To invoke a local service method, first retrieve its service %% descriptor using {@link lookup_service/1}. Then use {@link %% jsonrpc_post/3} or {@link invoke_service_method/8} to call a method %% on the service. %% %% The service record as retrieved from the registry contains the pid %% of the process responsible for handling service requests. %% %% == Experimental extension: 'Stateless' services == %% %% Instead of registering a pid with the `rfc4627_jsonrpc' %% registry, an alternative is to use a service record with a %% function object instead of a pid. This allows more control over %% how a service is implemented: if using a `gen_server' %% service is too heavy, a function object that sends a simple %% message could be used; or if the service didn't need an %% implementing process at all, the function object could process %% the request without sending any messages at all. %% %% To build a service descriptor object with a function handler %% instead of a pid, call `rfc4627_jsonrpc:service/5' %% instead of `rfc4627_jsonrpc:service/4': %% %% ``` %% rfc4627_jsonrpc:service({function, fun my_handler/3}, Name, Id, Version, Procs) %% -> service descriptor object %% %% my_handler(ProcedureNameBin, RequestInfo, Args) -> jsonrpc_response() %% ''' %% %% The resulting service descriptor can be registered with {@link %% register_service/1} as well as used directly with {@link %% invoke_service_method/8}. %% %% @type service() = #service{}. A service description record, as %% defined in `rfc4627_jsonrpc.hrl'. Can be constructed using {@link %% service/4}, or retrieved from the registry using {@link %% lookup_service/1}. %% %% @type json() = rfc4627:json(). A JSON value. %% @type jsonobj() = rfc4627:jsonobj(). A JSON "object" or "struct". %% @type jsonarray() = rfc4627:jsonarray(). A JSON array. %% %% @type jsonrpc_response() = {(result | error), json()} | {(result | error), json(), jsonobj()}. %% %% The type that JSON-RPC service implementations are required to %% return. %% %% The first value should be `result' for a normal return value, or %% `error' for an error response. Use {@link error_response/2} or %% {@link error_response/3} to construct approprate error response %% values. %% %% The second value is the main response body: for normal returns, %% this is the ordinary return value of the procedure, and for error %% responses, it is the response structure defined in the JSON-RPC %% specification. %% %% The third, optional, value is called `ResponseInfo'. It can be used %% by the service implementation to supply transport-specific %% information back to its caller. For instance, if invoked via HTTP, %% extra headers to send back to the HTTP client can be passed in the %% `ResponseInfo' object. If `ResponseInfo' is omitted, `{obj, []}' is %% assumed. -module(rfc4627_jsonrpc). -include("rfc4627.hrl"). -include("rfc4627_jsonrpc.hrl"). -export([start/0, start_link/0]). -export([lookup_service/1, register_service/1, register_service/2]). -export([gen_object_name/0, system_describe/2]). -export([jsonrpc_post/3, jsonrpc_post/4, invoke_service_method/8, expand_jsonrpc_reply/2]). -export([error_response/2, error_response/3, service/4, service/5, proc/2]). -define(SERVICE, ?MODULE). %% @spec () -> {ok, pid()} | {error, {already_started, pid()}} %% @doc Starts the registry process. start() -> gen_server:start({local, ?SERVICE}, rfc4627_jsonrpc_registry, [], []). %% @spec () -> {ok, pid()} | {error, {already_started, pid()}} %% @doc Starts the registry process, linking it to the calling process. start_link() -> gen_server:start_link({local, ?SERVICE}, rfc4627_jsonrpc_registry, [], []). %% @spec (binary()) -> not_found | service() %% @doc Calls the registry to look up a service by name. lookup_service(Service) -> gen_server:call(?SERVICE, {lookup_service, Service}). %% @spec (service()) -> ok %% @doc Registers a JSON-RPC service. %% %% The name of the service is contained within its service record. register_service(ServiceDescription) -> gen_server:call(?SERVICE, {register_service, ServiceDescription}). %% @spec (pid(), service()) -> ok %% @doc Registers a JSON-RPC service. %% %% The name of the service is contained within its service record. register_service(Pid, ServiceDescription) -> gen_server:call(?SERVICE, {register_service, Pid, ServiceDescription}). %% @spec () -> string() %% @doc Generates a unique name that can be used for otherwise unnamed JSON-RPC services. gen_object_name() -> Hash = erlang:md5(term_to_binary({node(), erlang:now()})), binary_to_hex(Hash). %% @spec (binary(), Service::service()) -> jsonobj() %% @doc Builds a JSON-RPC service description JSON object. %% %% This is used in the implementation of the `system.describe' %% JSON-RPC method that all JSON-RPC services are required by the %% specification to support. %% %% If `EndpointAddress' is `undefined', no `address' field is returned %% in the resulting description. Otherwise, it is included %% verbatim. The other fields in the description are constructed using %% the information in the `Service' record. system_describe(EndpointAddress, #service{name = Name, id = Id, version = Version, summary = Summary, help = Help, procs = Procs}) -> remove_undefined({obj, [{"sdversion", <<"1.0">>}, {"name", Name}, {"id", Id}, {"version", Version}, {"summary", Summary}, {"help", Help}, {"address", EndpointAddress}, {"procs", [system_describe_proc(P) || P <- Procs]}]}). %% @spec (service(), jsonobj(), jsonobj()) -> jsonrpc_response() %% @doc Calls {@link jsonrpc_post/4} with a `Timeout' of `default'. jsonrpc_post(ServiceRec, RequestInfo, RequestObj) -> jsonrpc_post(ServiceRec, RequestInfo, RequestObj, default). %% @spec (service(), jsonobj(), jsonobj(), Timeout) -> jsonrpc_response() %% where Timeout = default | infinity | integer() %% %% @doc Performs a POST-style invocation of a JSON-RPC service method. %% %% `RequestObj' is to be a JSON "object" containing at minimum fields %% named "id", "method" and "params", with meanings as defined by the %% JSON-RPC specification. %% %% See {@link invoke_service_method/8} for descriptions of the other %% parameters. jsonrpc_post(ServiceRec, RequestInfo, RequestObj, Timeout) -> Id = rfc4627:get_field(RequestObj, "id", undefined), Method = rfc4627:get_field(RequestObj, "method", undefined), Args = rfc4627:get_field(RequestObj, "params", undefined), invoke_service_method(ServiceRec, Id, post, RequestInfo, undefined, Method, Args, Timeout). %% @spec (ServiceRec, RequestId, PostOrGet, RequestInfo, EndpointAddress, Method, Args, Timeout) %% -> jsonrpc_response() %% where ServiceRec = service() %% RequestId = integer() | null %% PostOrGet = post | get %% RequestInfo = jsonobj() %% EndpointAddress = binary() | undefined %% Method = binary() %% Args = jsonobj() | jsonarray() %% Timeout = default | infinity | integer() %% %% @doc Calls a method defined on a JSON-RPC service. %% %% Use {@link lookup_service/1} or {@link service/5} to get a usable %% #service record for use with this function. %% %% The request ID should be the ID from the JSON-RPC request, as it %% was encoded for the transport the request arrived on. It will be %% used by this function in constructing the JSON-RPC reply %% object. Since the request ID is optional, it is acceptable to %% supply `null' instead of an integer. %% %% The `PostOrGet' parameter is used to check the idempotency setting %% for the chosen service procedure. If the parameter is passed as %% `post', no check is performed, as it is assumed that a stateful %% method call is permitted; if it is passed as `get', then the %% idempotency flag is checked, and an error object may be returned in %% the case that the invoked method is non-idempotent. %% %% The `RequestInfo' structure contains transport-specific details %% about the request. For HTTP, for example, this will include the %% HTTP headers and HTTP method. For AMQP, it will include the %% exchange and routing-key. %% %% The `EndpointAddress' is only used in the case that the method %% being invoked is `system.describe', in which case it is %% incorporated into the returned description as detailed in the %% documentation for {@link system_describe/2}. %% %% `Method' is the name of the service method to invoke, and `Args' is %% either a JSON "object" or a JSON array, to serve as the parameters %% for the call. %% %% The `Timeout' parameter is used to control how long the system will %% wait for a reply from the backing gen_server. If `default' is %% specified, the default `gen_server:call' timeout is used; %% otherwise, `infinity' or a number of milliseconds is passed in to %% the `gen_server:call'. invoke_service_method(ServiceRec = #service{}, RequestId, PostOrGet, RequestInfo, EndpointAddress, Method, Args, Timeout) -> expand_jsonrpc_reply( RequestId, case Method of <<"system.describe">> -> {result, system_describe(EndpointAddress, ServiceRec)}; <<"system.", _Rest/binary>> -> error_response(403, "System methods forbidden", Method); _ -> case lookup_service_proc(ServiceRec, Method) of {ok, ServiceProc} -> invoke_service(PostOrGet, ServiceRec#service.handler, RequestInfo, ServiceProc, Args, Timeout); not_found -> error_response(404, "Procedure not found", [EndpointAddress, Method]) end end). %% @spec (CodeOrMessage::(integer() | string() | binary()), json()) -> {error, jsonobj()} %% @doc Constructs an error response as per the JSON-RPC specification. %% %% Either a code or a message can be supplied as the first argument. %% %% @see error_response/3 error_response(Code, ErrorValue) when is_integer(Code) -> error_response(Code, "Error "++integer_to_list(Code), ErrorValue); error_response(Message, ErrorValue) when is_list(Message) -> error_response(500, list_to_binary(Message), ErrorValue); error_response(Message, ErrorValue) when is_binary(Message) -> error_response(500, Message, ErrorValue). %% @spec (integer(), (string() | binary()), json()) -> {error, jsonobj()} %% @doc Constructs an error response as per the JSON-RPC specification. %% %% The first argument should hold the error code. Error codes are %% defined in the JSON-RPC specification. %% %% The second argument can be either a `string()' or a `binary()' %% describing the error as text. %% %% The third argument is a general JSON value providing arbitrary %% further detail on the error. error_response(Code, Message, ErrorValue) when is_list(Message) -> error_response(Code, list_to_binary(Message), ErrorValue); error_response(Code, Message, ErrorValue) -> {error, {obj, [{"name", <<"JSONRPCError">>}, {"code", Code}, {"message", Message}, {"error", ErrorValue}]}}. %% @spec (Name, Id, Version, Procs) -> service() %% where Name = binary() | string() %% Id = binary() | string() %% Version = binary() | string() %% Procs = [ProcedureDescription] %% ProcedureDescription = {Name, [Parameter]} | #service_proc{} %% Parameter = {Name, ParameterType} | #service_proc_param{} %% ParameterType = bit | num | str | arr | obj | any | nil | string() | binary() %% %% @doc Constructs a service description record. %% %% The `Procs' parameter should be a list of procedure-descriptions, %% which can be either constructed manually or using {@link proc/2}. service(Name, Id, Version, Procs) when is_list(Name) -> service(list_to_binary(Name), Id, Version, Procs); service(Name, Id, Version, Procs) when is_list(Id) -> service(Name, list_to_binary(Id), Version, Procs); service(Name, Id, Version, Procs) when is_list(Version) -> service(Name, Id, list_to_binary(Version), Procs); service(Name, Id, Version, Procs) -> #service{name = Name, id = Id, version = Version, procs = [case P of {ProcName, Params} -> proc(ProcName, Params); #service_proc{} -> P end || P <- Procs]}. %% @spec (Handler, Name, Id, Version, Procs) -> service() %% where Handler = {pid, pid()} | {function, function()} %% %% @doc As for {@link service/4}, but supplying a handler for use with %% an experimental "stateless" service implementation. service(Handler, Name, Id, Version, Procs) -> (service(Name, Id, Version, Procs))#service{handler = Handler}. %% @spec (Name, [Parameter]) -> #service_proc{} %% where Name = binary() | string() %% Parameter = {Name, ParameterType} | #service_proc_param{} %% ParameterType = bit | num | str | arr | obj | any | nil | string() | binary() %% %% @doc Constructs a service procedure description record. proc(Name, Params) when is_list(Name) -> proc(list_to_binary(Name), Params); proc(Name, Params) -> #service_proc{name = Name, params = [proc_param(P) || P <- Params]}. %--------------------------------------------------------------------------- build_jsonrpc_response(Id, ResultField) -> {obj, [{version, <<"1.1">>}, {id, Id}, ResultField]}. expand_jsonrpc_reply(RequestId, {ResultOrError, Value}) -> {ResultOrError, build_jsonrpc_response(RequestId, {ResultOrError, Value}), {obj, []}}; expand_jsonrpc_reply(RequestId, {ResultOrError, Value, ResponseInfo}) -> {ResultOrError, build_jsonrpc_response(RequestId, {ResultOrError, Value}), ResponseInfo}. proc_param({N, T}) when is_list(N) -> proc_param({list_to_binary(N), T}); proc_param({N, T}) -> #service_proc_param{name = N, type = proc_param_type(T)}. proc_param_type(bit) -> <<"bit">>; proc_param_type(num) -> <<"num">>; proc_param_type(str) -> <<"str">>; proc_param_type(arr) -> <<"arr">>; proc_param_type(obj) -> <<"obj">>; proc_param_type(any) -> <<"any">>; proc_param_type(nil) -> <<"nil">>; proc_param_type(T) when is_list(T) -> list_to_binary(T); proc_param_type(T) when is_binary(T) -> T. binary_to_hex(<<>>) -> []; binary_to_hex(<>) -> [rfc4627:hex_digit((B bsr 4) band 15), rfc4627:hex_digit(B band 15) | binary_to_hex(Rest)]. lookup_service_proc(#service{procs = Procs}, Method) -> case lists:keysearch(Method, #service_proc.name, Procs) of {value, ServiceProc} -> {ok, ServiceProc}; false -> not_found end. invoke_service(get, Handler, RequestInfo, ServiceProc, Args, Timeout) -> if ServiceProc#service_proc.idempotent -> invoke_service1(Handler, RequestInfo, ServiceProc, Args, Timeout); true -> error_response(403, "Non-idempotent method", ServiceProc#service_proc.name) end; invoke_service(post, Handler, RequestInfo, ServiceProc, Args, Timeout) -> invoke_service1(Handler, RequestInfo, ServiceProc, Args, Timeout). invoke_service1(Handler, RequestInfo, #service_proc{name = Name, params = Params}, Args, Timeout) -> case catch run_handler(Handler, Name, RequestInfo, coerce_args(Params, Args), Timeout) of {'EXIT', {{function_clause, _}, _}} -> error_response(404, "Undefined procedure", Name); {'EXIT', Reason} -> error_response(500, "Internal error", list_to_binary(io_lib:format("~p", [Reason]))); Response -> Response end. run_handler({pid, Pid}, Name, RequestInfo, CoercedArgs, default) -> gen_server:call(Pid, {jsonrpc, Name, RequestInfo, CoercedArgs}); run_handler({pid, Pid}, Name, RequestInfo, CoercedArgs, Timeout) -> gen_server:call(Pid, {jsonrpc, Name, RequestInfo, CoercedArgs}, Timeout); run_handler({function, F}, Name, RequestInfo, CoercedArgs, _Timeout) -> F(Name, RequestInfo, CoercedArgs). coerce_args(_Params, Args) when is_list(Args) -> Args; coerce_args(Params, {obj, Fields}) -> [case lists:keysearch(binary_to_list(Name), 1, Fields) of {value, {_, Value}} -> coerce_value(Value, Type); false -> null end || #service_proc_param{name = Name, type = Type} <- Params]. coerce_value(Value, _Type) when not(is_binary(Value)) -> Value; coerce_value(<<"true">>, <<"bit">>) -> true; coerce_value(_, <<"bit">>) -> false; coerce_value(V, <<"num">>) -> list_to_integer(binary_to_list(V)); coerce_value(V, <<"str">>) -> V; coerce_value(V, <<"arr">>) -> rfc4627:decode(V); coerce_value(V, <<"obj">>) -> rfc4627:decode(V); coerce_value(V, <<"any">>) -> V; coerce_value(_, <<"nil">>) -> null; coerce_value(V, _) -> V. remove_undefined({obj, Fields}) -> {obj, remove_undefined1(Fields)}. remove_undefined1([]) -> []; remove_undefined1([{_, undefined} | Rest]) -> remove_undefined1(Rest); remove_undefined1([X | Rest]) -> [X | remove_undefined1(Rest)]. system_describe_proc(P = #service_proc{params = Params}) -> remove_undefined(?RFC4627_FROM_RECORD(service_proc, P#service_proc{params = [system_describe_proc_param(A) || A <- Params]})). system_describe_proc_param(P = #service_proc_param{}) -> remove_undefined(?RFC4627_FROM_RECORD(service_proc_param, P)). ././@LongLink0000000000000000000000000000015500000000000011566 Lustar rootrootrabbitmq-server-3.2.4/plugins-src/erlang-rfc4627-wrapper/erlang-rfc4627-git/src/rfc4627_jsonrpc_registry.erlrabbitmq-server-3.2.4/plugins-src/erlang-rfc4627-wrapper/erlang-rfc4627-git/src/rfc4627_jsonrpc_regi0000644000000000000000000000675512305126066031327 0ustar rootroot%% JSON-RPC service registry %%--------------------------------------------------------------------------- %% @author Tony Garnock-Jones %% @author LShift Ltd. %% @copyright 2007-2010, 2011, 2012 Tony Garnock-Jones and 2007-2010 LShift Ltd. %% @license %% %% Permission is hereby granted, free of charge, to any person %% obtaining a copy of this software and associated documentation %% files (the "Software"), to deal in the Software without %% restriction, including without limitation the rights to use, copy, %% modify, merge, publish, distribute, sublicense, and/or sell copies %% of the Software, and to permit persons to whom the Software is %% furnished to do so, subject to the following conditions: %% %% The above copyright notice and this permission notice shall be %% included in all copies or substantial portions of the Software. %% %% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, %% EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF %% MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND %% NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS %% BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN %% ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN %% CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE %% SOFTWARE. %%--------------------------------------------------------------------------- %% @since 1.2.0 %% @private %% @doc JSON-RPC service registry implementation. %% %% Started and managed by functions defined in module {@link rfc4627_jsonrpc}. -module(rfc4627_jsonrpc_registry). -include("rfc4627_jsonrpc.hrl"). -behaviour(gen_server). -export([init/1, terminate/2, code_change/3, handle_call/3, handle_cast/2, handle_info/2]). -define(TABLE_NAME, ?MODULE). %% @doc gen_server behaviour callback. init(_Args) -> ?TABLE_NAME = ets:new(?TABLE_NAME, [named_table]), {ok, no_jsonrpc_state}. %% @doc gen_server behaviour callback. terminate(_Reason, _State) -> %% FIXME: should we notify services here? ok. %% @doc gen_server behaviour callback. code_change(_OldVsn, State, _Extra) -> {ok, State}. %% @doc gen_server behaviour callback. handle_call({lookup_service, Service}, _From, State) -> case ets:lookup(?TABLE_NAME, {service, Service}) of [] -> {reply, not_found, State}; [{_, ServiceRec}] -> {reply, ServiceRec, State} end; handle_call({register_service, ServiceDescription = #service{name = Name}}, _From, State) -> ets:insert(?TABLE_NAME, {{service, Name}, ServiceDescription}), {reply, ok, State}; handle_call({register_service, Pid, ServiceDescription = #service{name = Name}}, _From, State) -> SD = ServiceDescription#service{handler = {pid, Pid}}, erlang:monitor(process, Pid), ets:insert(?TABLE_NAME, {{service, Name}, SD}), ets:insert(?TABLE_NAME, {{service_pid, Pid}, Name}), {reply, ok, State}. %% @doc gen_server behaviour callback. handle_cast(Request, State) -> error_logger:error_msg("Unhandled cast in ~p: ~p", [?MODULE, Request]), {noreply, State}. %% @doc gen_server behaviour callback. handle_info({'DOWN', _MonitorRef, process, DownPid, _Reason}, State) -> case ets:lookup(?TABLE_NAME, {service_pid, DownPid}) of [] -> {noreply, State}; [{_, ServiceName}] -> ets:delete(?TABLE_NAME, {service_pid, DownPid}), ets:delete(?TABLE_NAME, {service, ServiceName}), {noreply, State} end. rabbitmq-server-3.2.4/plugins-src/erlang-rfc4627-wrapper/erlang-rfc4627-git/test/0000755000000000000000000000000012305126066025716 5ustar rootrootrabbitmq-server-3.2.4/plugins-src/erlang-rfc4627-wrapper/erlang-rfc4627-git/test/server_root/0000755000000000000000000000000012305126066030267 5ustar rootroot././@LongLink0000000000000000000000000000014500000000000011565 Lustar rootrootrabbitmq-server-3.2.4/plugins-src/erlang-rfc4627-wrapper/erlang-rfc4627-git/test/server_root/htdocs/rabbitmq-server-3.2.4/plugins-src/erlang-rfc4627-wrapper/erlang-rfc4627-git/test/server_root/htdocs/0000755000000000000000000000000012305126066031553 5ustar rootroot././@LongLink0000000000000000000000000000015700000000000011570 Lustar rootrootrabbitmq-server-3.2.4/plugins-src/erlang-rfc4627-wrapper/erlang-rfc4627-git/test/server_root/htdocs/index.htmlrabbitmq-server-3.2.4/plugins-src/erlang-rfc4627-wrapper/erlang-rfc4627-git/test/server_root/htdocs/0000644000000000000000000000130212305126066031551 0ustar rootroot RFC4627 JSON-RPC test

    RFC4627 JSON-RPC test

    Expect to see: "Starting" and "ErlangServer: Hello, world!", followed by false.

    
        

    Click the following button to crash the server process:

    ././@LongLink0000000000000000000000000000016300000000000011565 Lustar rootrootrabbitmq-server-3.2.4/plugins-src/erlang-rfc4627-wrapper/erlang-rfc4627-git/test/server_root/htdocs/test-client.jsrabbitmq-server-3.2.4/plugins-src/erlang-rfc4627-wrapper/erlang-rfc4627-git/test/server_root/htdocs/0000644000000000000000000000072712305126066031563 0ustar rootrootfunction log() { $A(arguments).each(function (arg) { $("testOutput").appendChild (document.createTextNode(JSON.stringify(arg) + "\n")); }); } function testMain() { log("Starting."); var testService = new JsonRpcService(document.location + "rpc/test", onReady); function onReady() { testService.test_proc("Hello, world!").addCallback(log); } Event.observe($("crashButton"), "click", function () { testService.crash() }); } ././@LongLink0000000000000000000000000000016700000000000011571 Lustar rootrootrabbitmq-server-3.2.4/plugins-src/erlang-rfc4627-wrapper/erlang-rfc4627-git/test/server_root/htdocs/prototype-1.4.0.jsrabbitmq-server-3.2.4/plugins-src/erlang-rfc4627-wrapper/erlang-rfc4627-git/test/server_root/htdocs/0000644000000000000000000013452512305126066031567 0ustar rootroot/* Prototype JavaScript framework, version 1.4.0 * (c) 2005 Sam Stephenson * * Prototype is freely distributable under the terms of an MIT-style license. * For details, see the Prototype web site: http://prototype.conio.net/ * /*--------------------------------------------------------------------------*/ var Prototype = { Version: '1.4.0', ScriptFragment: '(?:)((\n|\r|.)*?)(?:<\/script>)', emptyFunction: function() {}, K: function(x) {return x} } var Class = { create: function() { return function() { this.initialize.apply(this, arguments); } } } var Abstract = new Object(); Object.extend = function(destination, source) { for (property in source) { destination[property] = source[property]; } return destination; } Object.inspect = function(object) { try { if (object == undefined) return 'undefined'; if (object == null) return 'null'; return object.inspect ? object.inspect() : object.toString(); } catch (e) { if (e instanceof RangeError) return '...'; throw e; } } Function.prototype.bind = function() { var __method = this, args = $A(arguments), object = args.shift(); return function() { return __method.apply(object, args.concat($A(arguments))); } } Function.prototype.bindAsEventListener = function(object) { var __method = this; return function(event) { return __method.call(object, event || window.event); } } Object.extend(Number.prototype, { toColorPart: function() { var digits = this.toString(16); if (this < 16) return '0' + digits; return digits; }, succ: function() { return this + 1; }, times: function(iterator) { $R(0, this, true).each(iterator); return this; } }); var Try = { these: function() { var returnValue; for (var i = 0; i < arguments.length; i++) { var lambda = arguments[i]; try { returnValue = lambda(); break; } catch (e) {} } return returnValue; } } /*--------------------------------------------------------------------------*/ var PeriodicalExecuter = Class.create(); PeriodicalExecuter.prototype = { initialize: function(callback, frequency) { this.callback = callback; this.frequency = frequency; this.currentlyExecuting = false; this.registerCallback(); }, registerCallback: function() { setInterval(this.onTimerEvent.bind(this), this.frequency * 1000); }, onTimerEvent: function() { if (!this.currentlyExecuting) { try { this.currentlyExecuting = true; this.callback(); } finally { this.currentlyExecuting = false; } } } } /*--------------------------------------------------------------------------*/ function $() { var elements = new Array(); for (var i = 0; i < arguments.length; i++) { var element = arguments[i]; if (typeof element == 'string') element = document.getElementById(element); if (arguments.length == 1) return element; elements.push(element); } return elements; } Object.extend(String.prototype, { stripTags: function() { return this.replace(/<\/?[^>]+>/gi, ''); }, stripScripts: function() { return this.replace(new RegExp(Prototype.ScriptFragment, 'img'), ''); }, extractScripts: function() { var matchAll = new RegExp(Prototype.ScriptFragment, 'img'); var matchOne = new RegExp(Prototype.ScriptFragment, 'im'); return (this.match(matchAll) || []).map(function(scriptTag) { return (scriptTag.match(matchOne) || ['', ''])[1]; }); }, evalScripts: function() { return this.extractScripts().map(eval); }, escapeHTML: function() { var div = document.createElement('div'); var text = document.createTextNode(this); div.appendChild(text); return div.innerHTML; }, unescapeHTML: function() { var div = document.createElement('div'); div.innerHTML = this.stripTags(); return div.childNodes[0] ? div.childNodes[0].nodeValue : ''; }, toQueryParams: function() { var pairs = this.match(/^\??(.*)$/)[1].split('&'); return pairs.inject({}, function(params, pairString) { var pair = pairString.split('='); params[pair[0]] = pair[1]; return params; }); }, toArray: function() { return this.split(''); }, camelize: function() { var oStringList = this.split('-'); if (oStringList.length == 1) return oStringList[0]; var camelizedString = this.indexOf('-') == 0 ? oStringList[0].charAt(0).toUpperCase() + oStringList[0].substring(1) : oStringList[0]; for (var i = 1, len = oStringList.length; i < len; i++) { var s = oStringList[i]; camelizedString += s.charAt(0).toUpperCase() + s.substring(1); } return camelizedString; }, inspect: function() { return "'" + this.replace('\\', '\\\\').replace("'", '\\\'') + "'"; } }); String.prototype.parseQuery = String.prototype.toQueryParams; var $break = new Object(); var $continue = new Object(); var Enumerable = { each: function(iterator) { var index = 0; try { this._each(function(value) { try { iterator(value, index++); } catch (e) { if (e != $continue) throw e; } }); } catch (e) { if (e != $break) throw e; } }, all: function(iterator) { var result = true; this.each(function(value, index) { result = result && !!(iterator || Prototype.K)(value, index); if (!result) throw $break; }); return result; }, any: function(iterator) { var result = true; this.each(function(value, index) { if (result = !!(iterator || Prototype.K)(value, index)) throw $break; }); return result; }, collect: function(iterator) { var results = []; this.each(function(value, index) { results.push(iterator(value, index)); }); return results; }, detect: function (iterator) { var result; this.each(function(value, index) { if (iterator(value, index)) { result = value; throw $break; } }); return result; }, findAll: function(iterator) { var results = []; this.each(function(value, index) { if (iterator(value, index)) results.push(value); }); return results; }, grep: function(pattern, iterator) { var results = []; this.each(function(value, index) { var stringValue = value.toString(); if (stringValue.match(pattern)) results.push((iterator || Prototype.K)(value, index)); }) return results; }, include: function(object) { var found = false; this.each(function(value) { if (value == object) { found = true; throw $break; } }); return found; }, inject: function(memo, iterator) { this.each(function(value, index) { memo = iterator(memo, value, index); }); return memo; }, invoke: function(method) { var args = $A(arguments).slice(1); return this.collect(function(value) { return value[method].apply(value, args); }); }, max: function(iterator) { var result; this.each(function(value, index) { value = (iterator || Prototype.K)(value, index); if (value >= (result || value)) result = value; }); return result; }, min: function(iterator) { var result; this.each(function(value, index) { value = (iterator || Prototype.K)(value, index); if (value <= (result || value)) result = value; }); return result; }, partition: function(iterator) { var trues = [], falses = []; this.each(function(value, index) { ((iterator || Prototype.K)(value, index) ? trues : falses).push(value); }); return [trues, falses]; }, pluck: function(property) { var results = []; this.each(function(value, index) { results.push(value[property]); }); return results; }, reject: function(iterator) { var results = []; this.each(function(value, index) { if (!iterator(value, index)) results.push(value); }); return results; }, sortBy: function(iterator) { return this.collect(function(value, index) { return {value: value, criteria: iterator(value, index)}; }).sort(function(left, right) { var a = left.criteria, b = right.criteria; return a < b ? -1 : a > b ? 1 : 0; }).pluck('value'); }, toArray: function() { return this.collect(Prototype.K); }, zip: function() { var iterator = Prototype.K, args = $A(arguments); if (typeof args.last() == 'function') iterator = args.pop(); var collections = [this].concat(args).map($A); return this.map(function(value, index) { iterator(value = collections.pluck(index)); return value; }); }, inspect: function() { return '#'; } } Object.extend(Enumerable, { map: Enumerable.collect, find: Enumerable.detect, select: Enumerable.findAll, member: Enumerable.include, entries: Enumerable.toArray }); var $A = Array.from = function(iterable) { if (!iterable) return []; if (iterable.toArray) { return iterable.toArray(); } else { var results = []; for (var i = 0; i < iterable.length; i++) results.push(iterable[i]); return results; } } Object.extend(Array.prototype, Enumerable); Array.prototype._reverse = Array.prototype.reverse; Object.extend(Array.prototype, { _each: function(iterator) { for (var i = 0; i < this.length; i++) iterator(this[i]); }, clear: function() { this.length = 0; return this; }, first: function() { return this[0]; }, last: function() { return this[this.length - 1]; }, compact: function() { return this.select(function(value) { return value != undefined || value != null; }); }, flatten: function() { return this.inject([], function(array, value) { return array.concat(value.constructor == Array ? value.flatten() : [value]); }); }, without: function() { var values = $A(arguments); return this.select(function(value) { return !values.include(value); }); }, indexOf: function(object) { for (var i = 0; i < this.length; i++) if (this[i] == object) return i; return -1; }, reverse: function(inline) { return (inline !== false ? this : this.toArray())._reverse(); }, shift: function() { var result = this[0]; for (var i = 0; i < this.length - 1; i++) this[i] = this[i + 1]; this.length--; return result; }, inspect: function() { return '[' + this.map(Object.inspect).join(', ') + ']'; } }); var Hash = { _each: function(iterator) { for (key in this) { var value = this[key]; if (typeof value == 'function') continue; var pair = [key, value]; pair.key = key; pair.value = value; iterator(pair); } }, keys: function() { return this.pluck('key'); }, values: function() { return this.pluck('value'); }, merge: function(hash) { return $H(hash).inject($H(this), function(mergedHash, pair) { mergedHash[pair.key] = pair.value; return mergedHash; }); }, toQueryString: function() { return this.map(function(pair) { return pair.map(encodeURIComponent).join('='); }).join('&'); }, inspect: function() { return '#'; } } function $H(object) { var hash = Object.extend({}, object || {}); Object.extend(hash, Enumerable); Object.extend(hash, Hash); return hash; } ObjectRange = Class.create(); Object.extend(ObjectRange.prototype, Enumerable); Object.extend(ObjectRange.prototype, { initialize: function(start, end, exclusive) { this.start = start; this.end = end; this.exclusive = exclusive; }, _each: function(iterator) { var value = this.start; do { iterator(value); value = value.succ(); } while (this.include(value)); }, include: function(value) { if (value < this.start) return false; if (this.exclusive) return value < this.end; return value <= this.end; } }); var $R = function(start, end, exclusive) { return new ObjectRange(start, end, exclusive); } var Ajax = { getTransport: function() { return Try.these( function() {return new ActiveXObject('Msxml2.XMLHTTP')}, function() {return new ActiveXObject('Microsoft.XMLHTTP')}, function() {return new XMLHttpRequest()} ) || false; }, activeRequestCount: 0 } Ajax.Responders = { responders: [], _each: function(iterator) { this.responders._each(iterator); }, register: function(responderToAdd) { if (!this.include(responderToAdd)) this.responders.push(responderToAdd); }, unregister: function(responderToRemove) { this.responders = this.responders.without(responderToRemove); }, dispatch: function(callback, request, transport, json) { this.each(function(responder) { if (responder[callback] && typeof responder[callback] == 'function') { try { responder[callback].apply(responder, [request, transport, json]); } catch (e) {} } }); } }; Object.extend(Ajax.Responders, Enumerable); Ajax.Responders.register({ onCreate: function() { Ajax.activeRequestCount++; }, onComplete: function() { Ajax.activeRequestCount--; } }); Ajax.Base = function() {}; Ajax.Base.prototype = { setOptions: function(options) { this.options = { method: 'post', asynchronous: true, parameters: '' } Object.extend(this.options, options || {}); }, responseIsSuccess: function() { return this.transport.status == undefined || this.transport.status == 0 || (this.transport.status >= 200 && this.transport.status < 300); }, responseIsFailure: function() { return !this.responseIsSuccess(); } } Ajax.Request = Class.create(); Ajax.Request.Events = ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete']; Ajax.Request.prototype = Object.extend(new Ajax.Base(), { initialize: function(url, options) { this.transport = Ajax.getTransport(); this.setOptions(options); this.request(url); }, request: function(url) { var parameters = this.options.parameters || ''; if (parameters.length > 0) parameters += '&_='; try { this.url = url; if (this.options.method == 'get' && parameters.length > 0) this.url += (this.url.match(/\?/) ? '&' : '?') + parameters; Ajax.Responders.dispatch('onCreate', this, this.transport); this.transport.open(this.options.method, this.url, this.options.asynchronous); if (this.options.asynchronous) { this.transport.onreadystatechange = this.onStateChange.bind(this); setTimeout((function() {this.respondToReadyState(1)}).bind(this), 10); } this.setRequestHeaders(); var body = this.options.postBody ? this.options.postBody : parameters; this.transport.send(this.options.method == 'post' ? body : null); } catch (e) { this.dispatchException(e); } }, setRequestHeaders: function() { var requestHeaders = ['X-Requested-With', 'XMLHttpRequest', 'X-Prototype-Version', Prototype.Version]; if (this.options.method == 'post') { requestHeaders.push('Content-type', 'application/x-www-form-urlencoded'); /* Force "Connection: close" for Mozilla browsers to work around * a bug where XMLHttpReqeuest sends an incorrect Content-length * header. See Mozilla Bugzilla #246651. */ if (this.transport.overrideMimeType) requestHeaders.push('Connection', 'close'); } if (this.options.requestHeaders) requestHeaders.push.apply(requestHeaders, this.options.requestHeaders); for (var i = 0; i < requestHeaders.length; i += 2) this.transport.setRequestHeader(requestHeaders[i], requestHeaders[i+1]); }, onStateChange: function() { var readyState = this.transport.readyState; if (readyState != 1) this.respondToReadyState(this.transport.readyState); }, header: function(name) { try { return this.transport.getResponseHeader(name); } catch (e) {} }, evalJSON: function() { try { return eval(this.header('X-JSON')); } catch (e) {} }, evalResponse: function() { try { return eval(this.transport.responseText); } catch (e) { this.dispatchException(e); } }, respondToReadyState: function(readyState) { var event = Ajax.Request.Events[readyState]; var transport = this.transport, json = this.evalJSON(); if (event == 'Complete') { try { (this.options['on' + this.transport.status] || this.options['on' + (this.responseIsSuccess() ? 'Success' : 'Failure')] || Prototype.emptyFunction)(transport, json); } catch (e) { this.dispatchException(e); } if ((this.header('Content-type') || '').match(/^text\/javascript/i)) this.evalResponse(); } try { (this.options['on' + event] || Prototype.emptyFunction)(transport, json); Ajax.Responders.dispatch('on' + event, this, transport, json); } catch (e) { this.dispatchException(e); } /* Avoid memory leak in MSIE: clean up the oncomplete event handler */ if (event == 'Complete') this.transport.onreadystatechange = Prototype.emptyFunction; }, dispatchException: function(exception) { (this.options.onException || Prototype.emptyFunction)(this, exception); Ajax.Responders.dispatch('onException', this, exception); } }); Ajax.Updater = Class.create(); Object.extend(Object.extend(Ajax.Updater.prototype, Ajax.Request.prototype), { initialize: function(container, url, options) { this.containers = { success: container.success ? $(container.success) : $(container), failure: container.failure ? $(container.failure) : (container.success ? null : $(container)) } this.transport = Ajax.getTransport(); this.setOptions(options); var onComplete = this.options.onComplete || Prototype.emptyFunction; this.options.onComplete = (function(transport, object) { this.updateContent(); onComplete(transport, object); }).bind(this); this.request(url); }, updateContent: function() { var receiver = this.responseIsSuccess() ? this.containers.success : this.containers.failure; var response = this.transport.responseText; if (!this.options.evalScripts) response = response.stripScripts(); if (receiver) { if (this.options.insertion) { new this.options.insertion(receiver, response); } else { Element.update(receiver, response); } } if (this.responseIsSuccess()) { if (this.onComplete) setTimeout(this.onComplete.bind(this), 10); } } }); Ajax.PeriodicalUpdater = Class.create(); Ajax.PeriodicalUpdater.prototype = Object.extend(new Ajax.Base(), { initialize: function(container, url, options) { this.setOptions(options); this.onComplete = this.options.onComplete; this.frequency = (this.options.frequency || 2); this.decay = (this.options.decay || 1); this.updater = {}; this.container = container; this.url = url; this.start(); }, start: function() { this.options.onComplete = this.updateComplete.bind(this); this.onTimerEvent(); }, stop: function() { this.updater.onComplete = undefined; clearTimeout(this.timer); (this.onComplete || Prototype.emptyFunction).apply(this, arguments); }, updateComplete: function(request) { if (this.options.decay) { this.decay = (request.responseText == this.lastText ? this.decay * this.options.decay : 1); this.lastText = request.responseText; } this.timer = setTimeout(this.onTimerEvent.bind(this), this.decay * this.frequency * 1000); }, onTimerEvent: function() { this.updater = new Ajax.Updater(this.container, this.url, this.options); } }); document.getElementsByClassName = function(className, parentElement) { var children = ($(parentElement) || document.body).getElementsByTagName('*'); return $A(children).inject([], function(elements, child) { if (child.className.match(new RegExp("(^|\\s)" + className + "(\\s|$)"))) elements.push(child); return elements; }); } /*--------------------------------------------------------------------------*/ if (!window.Element) { var Element = new Object(); } Object.extend(Element, { visible: function(element) { return $(element).style.display != 'none'; }, toggle: function() { for (var i = 0; i < arguments.length; i++) { var element = $(arguments[i]); Element[Element.visible(element) ? 'hide' : 'show'](element); } }, hide: function() { for (var i = 0; i < arguments.length; i++) { var element = $(arguments[i]); element.style.display = 'none'; } }, show: function() { for (var i = 0; i < arguments.length; i++) { var element = $(arguments[i]); element.style.display = ''; } }, remove: function(element) { element = $(element); element.parentNode.removeChild(element); }, update: function(element, html) { $(element).innerHTML = html.stripScripts(); setTimeout(function() {html.evalScripts()}, 10); }, getHeight: function(element) { element = $(element); return element.offsetHeight; }, classNames: function(element) { return new Element.ClassNames(element); }, hasClassName: function(element, className) { if (!(element = $(element))) return; return Element.classNames(element).include(className); }, addClassName: function(element, className) { if (!(element = $(element))) return; return Element.classNames(element).add(className); }, removeClassName: function(element, className) { if (!(element = $(element))) return; return Element.classNames(element).remove(className); }, // removes whitespace-only text node children cleanWhitespace: function(element) { element = $(element); for (var i = 0; i < element.childNodes.length; i++) { var node = element.childNodes[i]; if (node.nodeType == 3 && !/\S/.test(node.nodeValue)) Element.remove(node); } }, empty: function(element) { return $(element).innerHTML.match(/^\s*$/); }, scrollTo: function(element) { element = $(element); var x = element.x ? element.x : element.offsetLeft, y = element.y ? element.y : element.offsetTop; window.scrollTo(x, y); }, getStyle: function(element, style) { element = $(element); var value = element.style[style.camelize()]; if (!value) { if (document.defaultView && document.defaultView.getComputedStyle) { var css = document.defaultView.getComputedStyle(element, null); value = css ? css.getPropertyValue(style) : null; } else if (element.currentStyle) { value = element.currentStyle[style.camelize()]; } } if (window.opera && ['left', 'top', 'right', 'bottom'].include(style)) if (Element.getStyle(element, 'position') == 'static') value = 'auto'; return value == 'auto' ? null : value; }, setStyle: function(element, style) { element = $(element); for (name in style) element.style[name.camelize()] = style[name]; }, getDimensions: function(element) { element = $(element); if (Element.getStyle(element, 'display') != 'none') return {width: element.offsetWidth, height: element.offsetHeight}; // All *Width and *Height properties give 0 on elements with display none, // so enable the element temporarily var els = element.style; var originalVisibility = els.visibility; var originalPosition = els.position; els.visibility = 'hidden'; els.position = 'absolute'; els.display = ''; var originalWidth = element.clientWidth; var originalHeight = element.clientHeight; els.display = 'none'; els.position = originalPosition; els.visibility = originalVisibility; return {width: originalWidth, height: originalHeight}; }, makePositioned: function(element) { element = $(element); var pos = Element.getStyle(element, 'position'); if (pos == 'static' || !pos) { element._madePositioned = true; element.style.position = 'relative'; // Opera returns the offset relative to the positioning context, when an // element is position relative but top and left have not been defined if (window.opera) { element.style.top = 0; element.style.left = 0; } } }, undoPositioned: function(element) { element = $(element); if (element._madePositioned) { element._madePositioned = undefined; element.style.position = element.style.top = element.style.left = element.style.bottom = element.style.right = ''; } }, makeClipping: function(element) { element = $(element); if (element._overflow) return; element._overflow = element.style.overflow; if ((Element.getStyle(element, 'overflow') || 'visible') != 'hidden') element.style.overflow = 'hidden'; }, undoClipping: function(element) { element = $(element); if (element._overflow) return; element.style.overflow = element._overflow; element._overflow = undefined; } }); var Toggle = new Object(); Toggle.display = Element.toggle; /*--------------------------------------------------------------------------*/ Abstract.Insertion = function(adjacency) { this.adjacency = adjacency; } Abstract.Insertion.prototype = { initialize: function(element, content) { this.element = $(element); this.content = content.stripScripts(); if (this.adjacency && this.element.insertAdjacentHTML) { try { this.element.insertAdjacentHTML(this.adjacency, this.content); } catch (e) { if (this.element.tagName.toLowerCase() == 'tbody') { this.insertContent(this.contentFromAnonymousTable()); } else { throw e; } } } else { this.range = this.element.ownerDocument.createRange(); if (this.initializeRange) this.initializeRange(); this.insertContent([this.range.createContextualFragment(this.content)]); } setTimeout(function() {content.evalScripts()}, 10); }, contentFromAnonymousTable: function() { var div = document.createElement('div'); div.innerHTML = '' + this.content + '
    '; return $A(div.childNodes[0].childNodes[0].childNodes); } } var Insertion = new Object(); Insertion.Before = Class.create(); Insertion.Before.prototype = Object.extend(new Abstract.Insertion('beforeBegin'), { initializeRange: function() { this.range.setStartBefore(this.element); }, insertContent: function(fragments) { fragments.each((function(fragment) { this.element.parentNode.insertBefore(fragment, this.element); }).bind(this)); } }); Insertion.Top = Class.create(); Insertion.Top.prototype = Object.extend(new Abstract.Insertion('afterBegin'), { initializeRange: function() { this.range.selectNodeContents(this.element); this.range.collapse(true); }, insertContent: function(fragments) { fragments.reverse(false).each((function(fragment) { this.element.insertBefore(fragment, this.element.firstChild); }).bind(this)); } }); Insertion.Bottom = Class.create(); Insertion.Bottom.prototype = Object.extend(new Abstract.Insertion('beforeEnd'), { initializeRange: function() { this.range.selectNodeContents(this.element); this.range.collapse(this.element); }, insertContent: function(fragments) { fragments.each((function(fragment) { this.element.appendChild(fragment); }).bind(this)); } }); Insertion.After = Class.create(); Insertion.After.prototype = Object.extend(new Abstract.Insertion('afterEnd'), { initializeRange: function() { this.range.setStartAfter(this.element); }, insertContent: function(fragments) { fragments.each((function(fragment) { this.element.parentNode.insertBefore(fragment, this.element.nextSibling); }).bind(this)); } }); /*--------------------------------------------------------------------------*/ Element.ClassNames = Class.create(); Element.ClassNames.prototype = { initialize: function(element) { this.element = $(element); }, _each: function(iterator) { this.element.className.split(/\s+/).select(function(name) { return name.length > 0; })._each(iterator); }, set: function(className) { this.element.className = className; }, add: function(classNameToAdd) { if (this.include(classNameToAdd)) return; this.set(this.toArray().concat(classNameToAdd).join(' ')); }, remove: function(classNameToRemove) { if (!this.include(classNameToRemove)) return; this.set(this.select(function(className) { return className != classNameToRemove; }).join(' ')); }, toString: function() { return this.toArray().join(' '); } } Object.extend(Element.ClassNames.prototype, Enumerable); var Field = { clear: function() { for (var i = 0; i < arguments.length; i++) $(arguments[i]).value = ''; }, focus: function(element) { $(element).focus(); }, present: function() { for (var i = 0; i < arguments.length; i++) if ($(arguments[i]).value == '') return false; return true; }, select: function(element) { $(element).select(); }, activate: function(element) { element = $(element); element.focus(); if (element.select) element.select(); } } /*--------------------------------------------------------------------------*/ var Form = { serialize: function(form) { var elements = Form.getElements($(form)); var queryComponents = new Array(); for (var i = 0; i < elements.length; i++) { var queryComponent = Form.Element.serialize(elements[i]); if (queryComponent) queryComponents.push(queryComponent); } return queryComponents.join('&'); }, getElements: function(form) { form = $(form); var elements = new Array(); for (tagName in Form.Element.Serializers) { var tagElements = form.getElementsByTagName(tagName); for (var j = 0; j < tagElements.length; j++) elements.push(tagElements[j]); } return elements; }, getInputs: function(form, typeName, name) { form = $(form); var inputs = form.getElementsByTagName('input'); if (!typeName && !name) return inputs; var matchingInputs = new Array(); for (var i = 0; i < inputs.length; i++) { var input = inputs[i]; if ((typeName && input.type != typeName) || (name && input.name != name)) continue; matchingInputs.push(input); } return matchingInputs; }, disable: function(form) { var elements = Form.getElements(form); for (var i = 0; i < elements.length; i++) { var element = elements[i]; element.blur(); element.disabled = 'true'; } }, enable: function(form) { var elements = Form.getElements(form); for (var i = 0; i < elements.length; i++) { var element = elements[i]; element.disabled = ''; } }, findFirstElement: function(form) { return Form.getElements(form).find(function(element) { return element.type != 'hidden' && !element.disabled && ['input', 'select', 'textarea'].include(element.tagName.toLowerCase()); }); }, focusFirstElement: function(form) { Field.activate(Form.findFirstElement(form)); }, reset: function(form) { $(form).reset(); } } Form.Element = { serialize: function(element) { element = $(element); var method = element.tagName.toLowerCase(); var parameter = Form.Element.Serializers[method](element); if (parameter) { var key = encodeURIComponent(parameter[0]); if (key.length == 0) return; if (parameter[1].constructor != Array) parameter[1] = [parameter[1]]; return parameter[1].map(function(value) { return key + '=' + encodeURIComponent(value); }).join('&'); } }, getValue: function(element) { element = $(element); var method = element.tagName.toLowerCase(); var parameter = Form.Element.Serializers[method](element); if (parameter) return parameter[1]; } } Form.Element.Serializers = { input: function(element) { switch (element.type.toLowerCase()) { case 'submit': case 'hidden': case 'password': case 'text': return Form.Element.Serializers.textarea(element); case 'checkbox': case 'radio': return Form.Element.Serializers.inputSelector(element); } return false; }, inputSelector: function(element) { if (element.checked) return [element.name, element.value]; }, textarea: function(element) { return [element.name, element.value]; }, select: function(element) { return Form.Element.Serializers[element.type == 'select-one' ? 'selectOne' : 'selectMany'](element); }, selectOne: function(element) { var value = '', opt, index = element.selectedIndex; if (index >= 0) { opt = element.options[index]; value = opt.value; if (!value && !('value' in opt)) value = opt.text; } return [element.name, value]; }, selectMany: function(element) { var value = new Array(); for (var i = 0; i < element.length; i++) { var opt = element.options[i]; if (opt.selected) { var optValue = opt.value; if (!optValue && !('value' in opt)) optValue = opt.text; value.push(optValue); } } return [element.name, value]; } } /*--------------------------------------------------------------------------*/ var $F = Form.Element.getValue; /*--------------------------------------------------------------------------*/ Abstract.TimedObserver = function() {} Abstract.TimedObserver.prototype = { initialize: function(element, frequency, callback) { this.frequency = frequency; this.element = $(element); this.callback = callback; this.lastValue = this.getValue(); this.registerCallback(); }, registerCallback: function() { setInterval(this.onTimerEvent.bind(this), this.frequency * 1000); }, onTimerEvent: function() { var value = this.getValue(); if (this.lastValue != value) { this.callback(this.element, value); this.lastValue = value; } } } Form.Element.Observer = Class.create(); Form.Element.Observer.prototype = Object.extend(new Abstract.TimedObserver(), { getValue: function() { return Form.Element.getValue(this.element); } }); Form.Observer = Class.create(); Form.Observer.prototype = Object.extend(new Abstract.TimedObserver(), { getValue: function() { return Form.serialize(this.element); } }); /*--------------------------------------------------------------------------*/ Abstract.EventObserver = function() {} Abstract.EventObserver.prototype = { initialize: function(element, callback) { this.element = $(element); this.callback = callback; this.lastValue = this.getValue(); if (this.element.tagName.toLowerCase() == 'form') this.registerFormCallbacks(); else this.registerCallback(this.element); }, onElementEvent: function() { var value = this.getValue(); if (this.lastValue != value) { this.callback(this.element, value); this.lastValue = value; } }, registerFormCallbacks: function() { var elements = Form.getElements(this.element); for (var i = 0; i < elements.length; i++) this.registerCallback(elements[i]); }, registerCallback: function(element) { if (element.type) { switch (element.type.toLowerCase()) { case 'checkbox': case 'radio': Event.observe(element, 'click', this.onElementEvent.bind(this)); break; case 'password': case 'text': case 'textarea': case 'select-one': case 'select-multiple': Event.observe(element, 'change', this.onElementEvent.bind(this)); break; } } } } Form.Element.EventObserver = Class.create(); Form.Element.EventObserver.prototype = Object.extend(new Abstract.EventObserver(), { getValue: function() { return Form.Element.getValue(this.element); } }); Form.EventObserver = Class.create(); Form.EventObserver.prototype = Object.extend(new Abstract.EventObserver(), { getValue: function() { return Form.serialize(this.element); } }); if (!window.Event) { var Event = new Object(); } Object.extend(Event, { KEY_BACKSPACE: 8, KEY_TAB: 9, KEY_RETURN: 13, KEY_ESC: 27, KEY_LEFT: 37, KEY_UP: 38, KEY_RIGHT: 39, KEY_DOWN: 40, KEY_DELETE: 46, element: function(event) { return event.target || event.srcElement; }, isLeftClick: function(event) { return (((event.which) && (event.which == 1)) || ((event.button) && (event.button == 1))); }, pointerX: function(event) { return event.pageX || (event.clientX + (document.documentElement.scrollLeft || document.body.scrollLeft)); }, pointerY: function(event) { return event.pageY || (event.clientY + (document.documentElement.scrollTop || document.body.scrollTop)); }, stop: function(event) { if (event.preventDefault) { event.preventDefault(); event.stopPropagation(); } else { event.returnValue = false; event.cancelBubble = true; } }, // find the first node with the given tagName, starting from the // node the event was triggered on; traverses the DOM upwards findElement: function(event, tagName) { var element = Event.element(event); while (element.parentNode && (!element.tagName || (element.tagName.toUpperCase() != tagName.toUpperCase()))) element = element.parentNode; return element; }, observers: false, _observeAndCache: function(element, name, observer, useCapture) { if (!this.observers) this.observers = []; if (element.addEventListener) { this.observers.push([element, name, observer, useCapture]); element.addEventListener(name, observer, useCapture); } else if (element.attachEvent) { this.observers.push([element, name, observer, useCapture]); element.attachEvent('on' + name, observer); } }, unloadCache: function() { if (!Event.observers) return; for (var i = 0; i < Event.observers.length; i++) { Event.stopObserving.apply(this, Event.observers[i]); Event.observers[i][0] = null; } Event.observers = false; }, observe: function(element, name, observer, useCapture) { var element = $(element); useCapture = useCapture || false; if (name == 'keypress' && (navigator.appVersion.match(/Konqueror|Safari|KHTML/) || element.attachEvent)) name = 'keydown'; this._observeAndCache(element, name, observer, useCapture); }, stopObserving: function(element, name, observer, useCapture) { var element = $(element); useCapture = useCapture || false; if (name == 'keypress' && (navigator.appVersion.match(/Konqueror|Safari|KHTML/) || element.detachEvent)) name = 'keydown'; if (element.removeEventListener) { element.removeEventListener(name, observer, useCapture); } else if (element.detachEvent) { element.detachEvent('on' + name, observer); } } }); /* prevent memory leaks in IE */ Event.observe(window, 'unload', Event.unloadCache, false); var Position = { // set to true if needed, warning: firefox performance problems // NOT neeeded for page scrolling, only if draggable contained in // scrollable elements includeScrollOffsets: false, // must be called before calling withinIncludingScrolloffset, every time the // page is scrolled prepare: function() { this.deltaX = window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft || 0; this.deltaY = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop || 0; }, realOffset: function(element) { var valueT = 0, valueL = 0; do { valueT += element.scrollTop || 0; valueL += element.scrollLeft || 0; element = element.parentNode; } while (element); return [valueL, valueT]; }, cumulativeOffset: function(element) { var valueT = 0, valueL = 0; do { valueT += element.offsetTop || 0; valueL += element.offsetLeft || 0; element = element.offsetParent; } while (element); return [valueL, valueT]; }, positionedOffset: function(element) { var valueT = 0, valueL = 0; do { valueT += element.offsetTop || 0; valueL += element.offsetLeft || 0; element = element.offsetParent; if (element) { p = Element.getStyle(element, 'position'); if (p == 'relative' || p == 'absolute') break; } } while (element); return [valueL, valueT]; }, offsetParent: function(element) { if (element.offsetParent) return element.offsetParent; if (element == document.body) return element; while ((element = element.parentNode) && element != document.body) if (Element.getStyle(element, 'position') != 'static') return element; return document.body; }, // caches x/y coordinate pair to use with overlap within: function(element, x, y) { if (this.includeScrollOffsets) return this.withinIncludingScrolloffsets(element, x, y); this.xcomp = x; this.ycomp = y; this.offset = this.cumulativeOffset(element); return (y >= this.offset[1] && y < this.offset[1] + element.offsetHeight && x >= this.offset[0] && x < this.offset[0] + element.offsetWidth); }, withinIncludingScrolloffsets: function(element, x, y) { var offsetcache = this.realOffset(element); this.xcomp = x + offsetcache[0] - this.deltaX; this.ycomp = y + offsetcache[1] - this.deltaY; this.offset = this.cumulativeOffset(element); return (this.ycomp >= this.offset[1] && this.ycomp < this.offset[1] + element.offsetHeight && this.xcomp >= this.offset[0] && this.xcomp < this.offset[0] + element.offsetWidth); }, // within must be called directly before overlap: function(mode, element) { if (!mode) return 0; if (mode == 'vertical') return ((this.offset[1] + element.offsetHeight) - this.ycomp) / element.offsetHeight; if (mode == 'horizontal') return ((this.offset[0] + element.offsetWidth) - this.xcomp) / element.offsetWidth; }, clone: function(source, target) { source = $(source); target = $(target); target.style.position = 'absolute'; var offsets = this.cumulativeOffset(source); target.style.top = offsets[1] + 'px'; target.style.left = offsets[0] + 'px'; target.style.width = source.offsetWidth + 'px'; target.style.height = source.offsetHeight + 'px'; }, page: function(forElement) { var valueT = 0, valueL = 0; var element = forElement; do { valueT += element.offsetTop || 0; valueL += element.offsetLeft || 0; // Safari fix if (element.offsetParent==document.body) if (Element.getStyle(element,'position')=='absolute') break; } while (element = element.offsetParent); element = forElement; do { valueT -= element.scrollTop || 0; valueL -= element.scrollLeft || 0; } while (element = element.parentNode); return [valueL, valueT]; }, clone: function(source, target) { var options = Object.extend({ setLeft: true, setTop: true, setWidth: true, setHeight: true, offsetTop: 0, offsetLeft: 0 }, arguments[2] || {}) // find page position of source source = $(source); var p = Position.page(source); // find coordinate system to use target = $(target); var delta = [0, 0]; var parent = null; // delta [0,0] will do fine with position: fixed elements, // position:absolute needs offsetParent deltas if (Element.getStyle(target,'position') == 'absolute') { parent = Position.offsetParent(target); delta = Position.page(parent); } // correct by body offsets (fixes Safari) if (parent == document.body) { delta[0] -= document.body.offsetLeft; delta[1] -= document.body.offsetTop; } // set position if(options.setLeft) target.style.left = (p[0] - delta[0] + options.offsetLeft) + 'px'; if(options.setTop) target.style.top = (p[1] - delta[1] + options.offsetTop) + 'px'; if(options.setWidth) target.style.width = source.offsetWidth + 'px'; if(options.setHeight) target.style.height = source.offsetHeight + 'px'; }, absolutize: function(element) { element = $(element); if (element.style.position == 'absolute') return; Position.prepare(); var offsets = Position.positionedOffset(element); var top = offsets[1]; var left = offsets[0]; var width = element.clientWidth; var height = element.clientHeight; element._originalLeft = left - parseFloat(element.style.left || 0); element._originalTop = top - parseFloat(element.style.top || 0); element._originalWidth = element.style.width; element._originalHeight = element.style.height; element.style.position = 'absolute'; element.style.top = top + 'px';; element.style.left = left + 'px';; element.style.width = width + 'px';; element.style.height = height + 'px';; }, relativize: function(element) { element = $(element); if (element.style.position == 'relative') return; Position.prepare(); element.style.position = 'relative'; var top = parseFloat(element.style.top || 0) - (element._originalTop || 0); var left = parseFloat(element.style.left || 0) - (element._originalLeft || 0); element.style.top = top + 'px'; element.style.left = left + 'px'; element.style.height = element._originalHeight; element.style.width = element._originalWidth; } } // Safari returns margins on body which is incorrect if the child is absolutely // positioned. For performance reasons, redefine Position.cumulativeOffset for // KHTML/WebKit only. if (/Konqueror|Safari|KHTML/.test(navigator.userAgent)) { Position.cumulativeOffset = function(element) { var valueT = 0, valueL = 0; do { valueT += element.offsetTop || 0; valueL += element.offsetLeft || 0; if (element.offsetParent == document.body) if (Element.getStyle(element, 'position') == 'absolute') break; element = element.offsetParent; } while (element); return [valueL, valueT]; } }././@LongLink0000000000000000000000000000015700000000000011570 Lustar rootrootrabbitmq-server-3.2.4/plugins-src/erlang-rfc4627-wrapper/erlang-rfc4627-git/test/server_root/htdocs/jsonrpc.jsrabbitmq-server-3.2.4/plugins-src/erlang-rfc4627-wrapper/erlang-rfc4627-git/test/server_root/htdocs/0000644000000000000000000000655012305126066031563 0ustar rootrootJsonRpcRequestId = 1; JsonRpcTransaction = Class.create(); Object.extend(JsonRpcTransaction.prototype, { initialize: function(serviceUrl, methodName, params, options) { this.options = { debug: false, timeout: 0 /* milliseconds; zero means "do not specify" */ }; Object.extend(this.options, options || {}); this.serviceUrl = serviceUrl; this.methodName = methodName; this.params = params; this.error = null; this.reply = null; this.replyReady = 0; this.callbacks = []; this.errorCallbacks = []; this.sendRequest(); }, buildRequest: function() { return { version: "1.1", id: JsonRpcRequestId++, method: this.methodName, params: this.params }; }, sendRequest: function() { var headers = ['Content-type', 'application/json', 'Accept', 'application/json']; if (this.options.timeout) { headers.push('X-JSON-RPC-Timeout', this.options.timeout); } this.request = new Ajax.Request(this.serviceUrl, { method: 'post', requestHeaders: headers, postBody: JSON.stringify(this.buildRequest()), onComplete: this.receiveReply.bind(this) }); }, receiveReply: function(ajaxRequest) { var response = JSON.parse(ajaxRequest.responseText); if (response.error) { if (this.options.debug) { alert("JsonRPC error:\n" + "Service: " + JSON.stringify(this.serviceUrl) + "\n" + "Method: " + JSON.stringify(this.methodName) + "\n" + "Params: " + JSON.stringify(this.params) + "\n" + "Response: " + JSON.stringify(response) + "\n"); } this.error = response.error; this.errorCallbacks.each(function (cb) { try { cb(response.error, true); } catch (err) {} }); } else { var reply = response.result; this.reply = reply; this.replyReady = 1; this.callbacks.each(function (cb) { try { cb(reply, false); } catch (err) {} }); } }, addCallback: function(cb) { this.callbacks.push(cb); if (this.replyReady) { setTimeout(function () { try { cb(this.reply, false); } catch (err) {} }, 0); } return this; }, addErrorCallback: function(cb) { this.errorCallbacks.push(cb); if (this.error) { setTimeout(function () { try { cb(this.error, true); } catch (err) {} }, 0); } return this; } }); JsonRpcService = Class.create(); Object.extend(JsonRpcService.prototype, { initialize: function(serviceUrl, onReady, options) { this.options = { transactionClass: JsonRpcTransaction, timeout: 0, /* milliseconds; zero means "do not specify" */ debug: false }; Object.extend(this.options, options || {}); this.serviceUrl = serviceUrl; var svc = this; var txn = new (this.options.transactionClass)(serviceUrl, "system.describe", [], {debug: this.options.debug}); txn.addCallback(receiveServiceDescription); function receiveServiceDescription(sd) { svc.serviceDescription = sd; svc.serviceDescription.procs.each(svc.installGenericProxy.bind(svc)); onReady(); } }, installGenericProxy: function(desc) { this[desc.name] = function () { var actuals = $A(arguments); return new (this.options.transactionClass)(this.serviceUrl, desc.name, actuals, { debug: this.options.debug, timeout: this.options.timeout }); }; } }); ././@LongLink0000000000000000000000000000015400000000000011565 Lustar rootrootrabbitmq-server-3.2.4/plugins-src/erlang-rfc4627-wrapper/erlang-rfc4627-git/test/server_root/htdocs/json.jsrabbitmq-server-3.2.4/plugins-src/erlang-rfc4627-wrapper/erlang-rfc4627-git/test/server_root/htdocs/0000644000000000000000000004174612305126066031571 0ustar rootroot/* http://www.JSON.org/json2.js 2010-08-25 Public Domain. NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK. See http://www.JSON.org/js.html This code should be minified before deployment. See http://javascript.crockford.com/jsmin.html USE YOUR OWN COPY. IT IS EXTREMELY UNWISE TO LOAD CODE FROM SERVERS YOU DO NOT CONTROL. This file creates a global JSON object containing two methods: stringify and parse. JSON.stringify(value, replacer, space) value any JavaScript value, usually an object or array. replacer an optional parameter that determines how object values are stringified for objects. It can be a function or an array of strings. space an optional parameter that specifies the indentation of nested structures. If it is omitted, the text will be packed without extra whitespace. If it is a number, it will specify the number of spaces to indent at each level. If it is a string (such as '\t' or ' '), it contains the characters used to indent at each level. This method produces a JSON text from a JavaScript value. When an object value is found, if the object contains a toJSON method, its toJSON method will be called and the result will be stringified. A toJSON method does not serialize: it returns the value represented by the name/value pair that should be serialized, or undefined if nothing should be serialized. The toJSON method will be passed the key associated with the value, and this will be bound to the value For example, this would serialize Dates as ISO strings. Date.prototype.toJSON = function (key) { function f(n) { // Format integers to have at least two digits. return n < 10 ? '0' + n : n; } return this.getUTCFullYear() + '-' + f(this.getUTCMonth() + 1) + '-' + f(this.getUTCDate()) + 'T' + f(this.getUTCHours()) + ':' + f(this.getUTCMinutes()) + ':' + f(this.getUTCSeconds()) + 'Z'; }; You can provide an optional replacer method. It will be passed the key and value of each member, with this bound to the containing object. The value that is returned from your method will be serialized. If your method returns undefined, then the member will be excluded from the serialization. If the replacer parameter is an array of strings, then it will be used to select the members to be serialized. It filters the results such that only members with keys listed in the replacer array are stringified. Values that do not have JSON representations, such as undefined or functions, will not be serialized. Such values in objects will be dropped; in arrays they will be replaced with null. You can use a replacer function to replace those with JSON values. JSON.stringify(undefined) returns undefined. The optional space parameter produces a stringification of the value that is filled with line breaks and indentation to make it easier to read. If the space parameter is a non-empty string, then that string will be used for indentation. If the space parameter is a number, then the indentation will be that many spaces. Example: text = JSON.stringify(['e', {pluribus: 'unum'}]); // text is '["e",{"pluribus":"unum"}]' text = JSON.stringify(['e', {pluribus: 'unum'}], null, '\t'); // text is '[\n\t"e",\n\t{\n\t\t"pluribus": "unum"\n\t}\n]' text = JSON.stringify([new Date()], function (key, value) { return this[key] instanceof Date ? 'Date(' + this[key] + ')' : value; }); // text is '["Date(---current time---)"]' JSON.parse(text, reviver) This method parses a JSON text to produce an object or array. It can throw a SyntaxError exception. The optional reviver parameter is a function that can filter and transform the results. It receives each of the keys and values, and its return value is used instead of the original value. If it returns what it received, then the structure is not modified. If it returns undefined then the member is deleted. Example: // Parse the text. Values that look like ISO date strings will // be converted to Date objects. myData = JSON.parse(text, function (key, value) { var a; if (typeof value === 'string') { a = /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)Z$/.exec(value); if (a) { return new Date(Date.UTC(+a[1], +a[2] - 1, +a[3], +a[4], +a[5], +a[6])); } } return value; }); myData = JSON.parse('["Date(09/09/2001)"]', function (key, value) { var d; if (typeof value === 'string' && value.slice(0, 5) === 'Date(' && value.slice(-1) === ')') { d = new Date(value.slice(5, -1)); if (d) { return d; } } return value; }); This is a reference implementation. You are free to copy, modify, or redistribute. */ /*jslint evil: true, strict: false */ /*members "", "\b", "\t", "\n", "\f", "\r", "\"", JSON, "\\", apply, call, charCodeAt, getUTCDate, getUTCFullYear, getUTCHours, getUTCMinutes, getUTCMonth, getUTCSeconds, hasOwnProperty, join, lastIndex, length, parse, prototype, push, replace, slice, stringify, test, toJSON, toString, valueOf */ // Create a JSON object only if one does not already exist. We create the // methods in a closure to avoid creating global variables. if (!this.JSON) { this.JSON = {}; } (function () { function f(n) { // Format integers to have at least two digits. return n < 10 ? '0' + n : n; } if (typeof Date.prototype.toJSON !== 'function') { Date.prototype.toJSON = function (key) { return isFinite(this.valueOf()) ? this.getUTCFullYear() + '-' + f(this.getUTCMonth() + 1) + '-' + f(this.getUTCDate()) + 'T' + f(this.getUTCHours()) + ':' + f(this.getUTCMinutes()) + ':' + f(this.getUTCSeconds()) + 'Z' : null; }; String.prototype.toJSON = Number.prototype.toJSON = Boolean.prototype.toJSON = function (key) { return this.valueOf(); }; } var cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g, escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g, gap, indent, meta = { // table of character substitutions '\b': '\\b', '\t': '\\t', '\n': '\\n', '\f': '\\f', '\r': '\\r', '"' : '\\"', '\\': '\\\\' }, rep; function quote(string) { // If the string contains no control characters, no quote characters, and no // backslash characters, then we can safely slap some quotes around it. // Otherwise we must also replace the offending characters with safe escape // sequences. escapable.lastIndex = 0; return escapable.test(string) ? '"' + string.replace(escapable, function (a) { var c = meta[a]; return typeof c === 'string' ? c : '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4); }) + '"' : '"' + string + '"'; } function str(key, holder) { // Produce a string from holder[key]. var i, // The loop counter. k, // The member key. v, // The member value. length, mind = gap, partial, value = holder[key]; // If the value has a toJSON method, call it to obtain a replacement value. if (value && typeof value === 'object' && typeof value.toJSON === 'function') { value = value.toJSON(key); } // If we were called with a replacer function, then call the replacer to // obtain a replacement value. if (typeof rep === 'function') { value = rep.call(holder, key, value); } // What happens next depends on the value's type. switch (typeof value) { case 'string': return quote(value); case 'number': // JSON numbers must be finite. Encode non-finite numbers as null. return isFinite(value) ? String(value) : 'null'; case 'boolean': case 'null': // If the value is a boolean or null, convert it to a string. Note: // typeof null does not produce 'null'. The case is included here in // the remote chance that this gets fixed someday. return String(value); // If the type is 'object', we might be dealing with an object or an array or // null. case 'object': // Due to a specification blunder in ECMAScript, typeof null is 'object', // so watch out for that case. if (!value) { return 'null'; } // Make an array to hold the partial results of stringifying this object value. gap += indent; partial = []; // Is the value an array? if (Object.prototype.toString.apply(value) === '[object Array]') { // The value is an array. Stringify every element. Use null as a placeholder // for non-JSON values. length = value.length; for (i = 0; i < length; i += 1) { partial[i] = str(i, value) || 'null'; } // Join all of the elements together, separated with commas, and wrap them in // brackets. v = partial.length === 0 ? '[]' : gap ? '[\n' + gap + partial.join(',\n' + gap) + '\n' + mind + ']' : '[' + partial.join(',') + ']'; gap = mind; return v; } // If the replacer is an array, use it to select the members to be stringified. if (rep && typeof rep === 'object') { length = rep.length; for (i = 0; i < length; i += 1) { k = rep[i]; if (typeof k === 'string') { v = str(k, value); if (v) { partial.push(quote(k) + (gap ? ': ' : ':') + v); } } } } else { // Otherwise, iterate through all of the keys in the object. for (k in value) { if (Object.hasOwnProperty.call(value, k)) { v = str(k, value); if (v) { partial.push(quote(k) + (gap ? ': ' : ':') + v); } } } } // Join all of the member texts together, separated with commas, // and wrap them in braces. v = partial.length === 0 ? '{}' : gap ? '{\n' + gap + partial.join(',\n' + gap) + '\n' + mind + '}' : '{' + partial.join(',') + '}'; gap = mind; return v; } } // If the JSON object does not yet have a stringify method, give it one. if (typeof JSON.stringify !== 'function') { JSON.stringify = function (value, replacer, space) { // The stringify method takes a value and an optional replacer, and an optional // space parameter, and returns a JSON text. The replacer can be a function // that can replace values, or an array of strings that will select the keys. // A default replacer method can be provided. Use of the space parameter can // produce text that is more easily readable. var i; gap = ''; indent = ''; // If the space parameter is a number, make an indent string containing that // many spaces. if (typeof space === 'number') { for (i = 0; i < space; i += 1) { indent += ' '; } // If the space parameter is a string, it will be used as the indent string. } else if (typeof space === 'string') { indent = space; } // If there is a replacer, it must be a function or an array. // Otherwise, throw an error. rep = replacer; if (replacer && typeof replacer !== 'function' && (typeof replacer !== 'object' || typeof replacer.length !== 'number')) { throw new Error('JSON.stringify'); } // Make a fake root object containing our value under the key of ''. // Return the result of stringifying the value. return str('', {'': value}); }; } // If the JSON object does not yet have a parse method, give it one. if (typeof JSON.parse !== 'function') { JSON.parse = function (text, reviver) { // The parse method takes a text and an optional reviver function, and returns // a JavaScript value if the text is a valid JSON text. var j; function walk(holder, key) { // The walk method is used to recursively walk the resulting structure so // that modifications can be made. var k, v, value = holder[key]; if (value && typeof value === 'object') { for (k in value) { if (Object.hasOwnProperty.call(value, k)) { v = walk(value, k); if (v !== undefined) { value[k] = v; } else { delete value[k]; } } } } return reviver.call(holder, key, value); } // Parsing happens in four stages. In the first stage, we replace certain // Unicode characters with escape sequences. JavaScript handles many characters // incorrectly, either silently deleting them, or treating them as line endings. text = String(text); cx.lastIndex = 0; if (cx.test(text)) { text = text.replace(cx, function (a) { return '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4); }); } // In the second stage, we run the text against regular expressions that look // for non-JSON patterns. We are especially concerned with '()' and 'new' // because they can cause invocation, and '=' because it can cause mutation. // But just to be safe, we want to reject all unexpected forms. // We split the second stage into 4 regexp operations in order to work around // crippling inefficiencies in IE's and Safari's regexp engines. First we // replace the JSON backslash pairs with '@' (a non-JSON character). Second, we // replace all simple value tokens with ']' characters. Third, we delete all // open brackets that follow a colon or comma or that begin the text. Finally, // we look to see that the remaining characters are only whitespace or ']' or // ',' or ':' or '{' or '}'. If that is so, then the text is safe for eval. if (/^[\],:{}\s]*$/ .test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@') .replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']') .replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) { // In the third stage we use the eval function to compile the text into a // JavaScript structure. The '{' operator is subject to a syntactic ambiguity // in JavaScript: it can begin a block or an object literal. We wrap the text // in parens to eliminate the ambiguity. j = eval('(' + text + ')'); // In the optional fourth stage, we recursively walk the new structure, passing // each name/value pair to a reviver function for possible transformation. return typeof reviver === 'function' ? walk({'': j}, '') : j; } // If the text is not JSON parseable, then a SyntaxError is thrown. throw new SyntaxError('JSON.parse'); }; } }()); rabbitmq-server-3.2.4/plugins-src/erlang-rfc4627-wrapper/erlang-rfc4627-git/test/server_root/conf/0000755000000000000000000000000012305126066031214 5ustar rootroot././@LongLink0000000000000000000000000000015500000000000011566 Lustar rootrootrabbitmq-server-3.2.4/plugins-src/erlang-rfc4627-wrapper/erlang-rfc4627-git/test/server_root/conf/httpd.confrabbitmq-server-3.2.4/plugins-src/erlang-rfc4627-wrapper/erlang-rfc4627-git/test/server_root/conf/ht0000644000000000000000000000061212305126066031551 0ustar rootrootServerName localhost ServerRoot test/server_root DocumentRoot test/server_root/htdocs Port 5671 Modules mod_alias mod_auth rfc4627_jsonrpc_inets mod_actions mod_cgi mod_responsecontrol mod_trace mod_range mod_head mod_include mod_dir mod_get mod_log mod_disk_log DirectoryIndex index.html JsonRpcAlias /rpc ErrorLog logs/error_log TransferLog logs/access_log SecurityLog logs/security_log ././@LongLink0000000000000000000000000000015500000000000011566 Lustar rootrootrabbitmq-server-3.2.4/plugins-src/erlang-rfc4627-wrapper/erlang-rfc4627-git/test/server_root/conf/mime.typesrabbitmq-server-3.2.4/plugins-src/erlang-rfc4627-wrapper/erlang-rfc4627-git/test/server_root/conf/mi0000644000000000000000000002711012305126066031545 0ustar rootroot# This is a comment. I love comments. # MIME type Extension application/EDI-Consent application/EDI-X12 application/EDIFACT application/activemessage application/andrew-inset ez application/applefile application/atomicmail application/batch-SMTP application/beep+xml application/cals-1840 application/commonground application/cybercash application/dca-rft application/dec-dx application/dvcs application/eshop application/http application/hyperstudio application/iges application/index application/index.cmd application/index.obj application/index.response application/index.vnd application/iotp application/ipp application/isup application/font-tdpfr application/mac-binhex40 hqx application/mac-compactpro cpt application/macwriteii application/marc application/mathematica application/mathematica-old application/msword doc application/news-message-id application/news-transmission application/ocsp-request application/ocsp-response application/octet-stream bin dms lha lzh exe class so dll application/oda oda application/parityfec application/pdf pdf application/pgp-encrypted application/pgp-keys application/pgp-signature application/pkcs10 application/pkcs7-mime application/pkcs7-signature application/pkix-cert application/pkix-crl application/pkixcmp application/postscript ai eps ps application/prs.alvestrand.titrax-sheet application/prs.cww application/prs.nprend application/qsig application/remote-printing application/riscos application/rtf application/sdp application/set-payment application/set-payment-initiation application/set-registration application/set-registration-initiation application/sgml application/sgml-open-catalog application/sieve application/slate application/smil smi smil application/timestamp-query application/timestamp-reply application/vemmi application/vnd.3M.Post-it-Notes application/vnd.FloGraphIt application/vnd.accpac.simply.aso application/vnd.accpac.simply.imp application/vnd.acucobol application/vnd.aether.imp application/vnd.anser-web-certificate-issue-initiation application/vnd.anser-web-funds-transfer-initiation application/vnd.audiograph application/vnd.businessobjects application/vnd.bmi application/vnd.canon-cpdl application/vnd.canon-lips application/vnd.claymore application/vnd.commerce-battelle application/vnd.commonspace application/vnd.comsocaller application/vnd.contact.cmsg application/vnd.cosmocaller application/vnd.cups-postscript application/vnd.cups-raster application/vnd.cups-raw application/vnd.ctc-posml application/vnd.cybank application/vnd.dna application/vnd.dpgraph application/vnd.dxr application/vnd.ecdis-update application/vnd.ecowin.chart application/vnd.ecowin.filerequest application/vnd.ecowin.fileupdate application/vnd.ecowin.series application/vnd.ecowin.seriesrequest application/vnd.ecowin.seriesupdate application/vnd.enliven application/vnd.epson.esf application/vnd.epson.msf application/vnd.epson.quickanime application/vnd.epson.salt application/vnd.epson.ssf application/vnd.ericsson.quickcall application/vnd.eudora.data application/vnd.fdf application/vnd.ffsns application/vnd.framemaker application/vnd.fsc.weblaunch application/vnd.fujitsu.oasys application/vnd.fujitsu.oasys2 application/vnd.fujitsu.oasys3 application/vnd.fujitsu.oasysgp application/vnd.fujitsu.oasysprs application/vnd.fujixerox.ddd application/vnd.fujixerox.docuworks application/vnd.fujixerox.docuworks.binder application/vnd.fut-misnet application/vnd.grafeq application/vnd.groove-account application/vnd.groove-identity-message application/vnd.groove-injector application/vnd.groove-tool-message application/vnd.groove-tool-template application/vnd.groove-vcard application/vnd.hhe.lesson-player application/vnd.hp-HPGL application/vnd.hp-PCL application/vnd.hp-PCLXL application/vnd.hp-hpid application/vnd.hp-hps application/vnd.httphone application/vnd.hzn-3d-crossword application/vnd.ibm.afplinedata application/vnd.ibm.MiniPay application/vnd.ibm.modcap application/vnd.informix-visionary application/vnd.intercon.formnet application/vnd.intertrust.digibox application/vnd.intertrust.nncp application/vnd.intu.qbo application/vnd.intu.qfx application/vnd.irepository.package+xml application/vnd.is-xpr application/vnd.japannet-directory-service application/vnd.japannet-jpnstore-wakeup application/vnd.japannet-payment-wakeup application/vnd.japannet-registration application/vnd.japannet-registration-wakeup application/vnd.japannet-setstore-wakeup application/vnd.japannet-verification application/vnd.japannet-verification-wakeup application/vnd.koan application/vnd.lotus-1-2-3 application/vnd.lotus-approach application/vnd.lotus-freelance application/vnd.lotus-notes application/vnd.lotus-organizer application/vnd.lotus-screencam application/vnd.lotus-wordpro application/vnd.mcd application/vnd.mediastation.cdkey application/vnd.meridian-slingshot application/vnd.mif mif application/vnd.minisoft-hp3000-save application/vnd.mitsubishi.misty-guard.trustweb application/vnd.mobius.daf application/vnd.mobius.dis application/vnd.mobius.msl application/vnd.mobius.plc application/vnd.mobius.txf application/vnd.motorola.flexsuite application/vnd.motorola.flexsuite.adsi application/vnd.motorola.flexsuite.fis application/vnd.motorola.flexsuite.gotap application/vnd.motorola.flexsuite.kmr application/vnd.motorola.flexsuite.ttc application/vnd.motorola.flexsuite.wem application/vnd.mozilla.xul+xml application/vnd.ms-artgalry application/vnd.ms-asf application/vnd.ms-excel xls application/vnd.ms-lrm application/vnd.ms-powerpoint ppt application/vnd.ms-project application/vnd.ms-tnef application/vnd.ms-works application/vnd.mseq application/vnd.msign application/vnd.music-niff application/vnd.musician application/vnd.netfpx application/vnd.noblenet-directory application/vnd.noblenet-sealer application/vnd.noblenet-web application/vnd.novadigm.EDM application/vnd.novadigm.EDX application/vnd.novadigm.EXT application/vnd.osa.netdeploy application/vnd.palm application/vnd.pg.format application/vnd.pg.osasli application/vnd.powerbuilder6 application/vnd.powerbuilder6-s application/vnd.powerbuilder7 application/vnd.powerbuilder7-s application/vnd.powerbuilder75 application/vnd.powerbuilder75-s application/vnd.previewsystems.box application/vnd.publishare-delta-tree application/vnd.pvi.ptid1 application/vnd.pwg-xhtml-print+xml application/vnd.rapid application/vnd.s3sms application/vnd.seemail application/vnd.shana.informed.formdata application/vnd.shana.informed.formtemplate application/vnd.shana.informed.interchange application/vnd.shana.informed.package application/vnd.sss-cod application/vnd.sss-dtf application/vnd.sss-ntf application/vnd.street-stream application/vnd.svd application/vnd.swiftview-ics application/vnd.triscape.mxs application/vnd.trueapp application/vnd.truedoc application/vnd.tve-trigger application/vnd.ufdl application/vnd.uplanet.alert application/vnd.uplanet.alert-wbxml application/vnd.uplanet.bearer-choice-wbxml application/vnd.uplanet.bearer-choice application/vnd.uplanet.cacheop application/vnd.uplanet.cacheop-wbxml application/vnd.uplanet.channel application/vnd.uplanet.channel-wbxml application/vnd.uplanet.list application/vnd.uplanet.list-wbxml application/vnd.uplanet.listcmd application/vnd.uplanet.listcmd-wbxml application/vnd.uplanet.signal application/vnd.vcx application/vnd.vectorworks application/vnd.vidsoft.vidconference application/vnd.visio application/vnd.vividence.scriptfile application/vnd.wap.sic application/vnd.wap.slc application/vnd.wap.wbxml wbxml application/vnd.wap.wmlc wmlc application/vnd.wap.wmlscriptc wmlsc application/vnd.webturbo application/vnd.wrq-hp3000-labelled application/vnd.wt.stf application/vnd.xara application/vnd.xfdl application/vnd.yellowriver-custom-menu application/whoispp-query application/whoispp-response application/wita application/wordperfect5.1 application/x-bcpio bcpio application/x-cdlink vcd application/x-chess-pgn pgn application/x-compress application/x-cpio cpio application/x-csh csh application/x-director dcr dir dxr application/x-dvi dvi application/x-futuresplash spl application/x-gtar gtar application/x-gzip application/x-hdf hdf application/x-javascript js application/x-koan skp skd skt skm application/x-latex latex application/x-netcdf nc cdf application/x-sh sh application/x-shar shar application/x-shockwave-flash swf application/x-stuffit sit application/x-sv4cpio sv4cpio application/x-sv4crc sv4crc application/x-tar tar application/x-tcl tcl application/x-tex tex application/x-texinfo texinfo texi application/x-troff t tr roff application/x-troff-man man application/x-troff-me me application/x-troff-ms ms application/x-ustar ustar application/x-wais-source src application/x400-bp application/xml application/xml-dtd application/xml-external-parsed-entity application/zip zip audio/32kadpcm audio/basic au snd audio/g.722.1 audio/l16 audio/midi mid midi kar audio/mp4a-latm audio/mpa-robust audio/mpeg mpga mp2 mp3 audio/parityfec audio/prs.sid audio/telephone-event audio/tone audio/vnd.cisco.nse audio/vnd.cns.anp1 audio/vnd.cns.inf1 audio/vnd.digital-winds audio/vnd.everad.plj audio/vnd.lucent.voice audio/vnd.nortel.vbk audio/vnd.nuera.ecelp4800 audio/vnd.nuera.ecelp7470 audio/vnd.nuera.ecelp9600 audio/vnd.octel.sbc audio/vnd.qcelp audio/vnd.rhetorex.32kadpcm audio/vnd.vmx.cvsd audio/x-aiff aif aiff aifc audio/x-mpegurl m3u audio/x-pn-realaudio ram rm audio/x-pn-realaudio-plugin rpm audio/x-realaudio ra audio/x-wav wav chemical/x-pdb pdb chemical/x-xyz xyz image/bmp bmp image/cgm image/g3fax image/gif gif image/ief ief image/jpeg jpeg jpg jpe image/naplps image/png png image/prs.btif image/prs.pti image/tiff tiff tif image/vnd.cns.inf2 image/vnd.dwg image/vnd.dxf image/vnd.fastbidsheet image/vnd.fpx image/vnd.fst image/vnd.fujixerox.edmics-mmr image/vnd.fujixerox.edmics-rlc image/vnd.mix image/vnd.net-fpx image/vnd.svf image/vnd.wap.wbmp wbmp image/vnd.xiff image/x-cmu-raster ras image/x-portable-anymap pnm image/x-portable-bitmap pbm image/x-portable-graymap pgm image/x-portable-pixmap ppm image/x-rgb rgb image/x-xbitmap xbm image/x-xpixmap xpm image/x-xwindowdump xwd message/delivery-status message/disposition-notification message/external-body message/http message/news message/partial message/rfc822 message/s-http model/iges igs iges model/mesh msh mesh silo model/vnd.dwf model/vnd.flatland.3dml model/vnd.gdl model/vnd.gs-gdl model/vnd.gtw model/vnd.mts model/vnd.vtu model/vrml wrl vrml multipart/alternative multipart/appledouble multipart/byteranges multipart/digest multipart/encrypted multipart/form-data multipart/header-set multipart/mixed multipart/parallel multipart/related multipart/report multipart/signed multipart/voice-message text/calendar text/css css text/directory text/enriched text/html html htm text/parityfec text/plain asc txt text/prs.lines.tag text/rfc822-headers text/richtext rtx text/rtf rtf text/sgml sgml sgm text/tab-separated-values tsv text/t140 text/uri-list text/vnd.DMClientScript text/vnd.IPTC.NITF text/vnd.IPTC.NewsML text/vnd.abc text/vnd.curl text/vnd.flatland.3dml text/vnd.fly text/vnd.fmi.flexstor text/vnd.in3d.3dml text/vnd.in3d.spot text/vnd.latex-z text/vnd.motorola.reflex text/vnd.ms-mediapackage text/vnd.wap.si text/vnd.wap.sl text/vnd.wap.wml wml text/vnd.wap.wmlscript wmls text/x-setext etx text/x-server-parsed-html shtml text/xml xml xsl text/xml-external-parsed-entity video/mp4v-es video/mpeg mpeg mpg mpe video/parityfec video/pointer video/quicktime qt mov video/vnd.fvt video/vnd.motorola.video video/vnd.motorola.videop video/vnd.mpegurl mxu video/vnd.mts video/vnd.nokia.interleaved-multimedia video/vnd.vivo video/x-msvideo avi video/x-sgi-movie movie x-conference/x-cooltalk ice rabbitmq-server-3.2.4/plugins-src/erlang-rfc4627-wrapper/erlang-rfc4627-git/test/server_root/logs/0000755000000000000000000000000012305126066031233 5ustar rootroot././@LongLink0000000000000000000000000000015100000000000011562 Lustar rootrootrabbitmq-server-3.2.4/plugins-src/erlang-rfc4627-wrapper/erlang-rfc4627-git/test/server_root/logs/READMErabbitmq-server-3.2.4/plugins-src/erlang-rfc4627-wrapper/erlang-rfc4627-git/test/server_root/logs/RE0000644000000000000000000000013112305126066031457 0ustar rootrootDirectory in which the test_jsonrpc_inets inets httpd instance will place its log files. ././@LongLink0000000000000000000000000000015000000000000011561 Lustar rootrootrabbitmq-server-3.2.4/plugins-src/erlang-rfc4627-wrapper/erlang-rfc4627-git/test/test_jsonrpc_inets.erlrabbitmq-server-3.2.4/plugins-src/erlang-rfc4627-wrapper/erlang-rfc4627-git/test/test_jsonrpc_inets.0000644000000000000000000000612412305126066031641 0ustar rootroot%% An example JSON-RPC service %%--------------------------------------------------------------------------- %% Copyright (c) 2007-2010 Tony Garnock-Jones %% Copyright (c) 2007-2010 LShift Ltd. %% %% Permission is hereby granted, free of charge, to any person %% obtaining a copy of this software and associated documentation %% files (the "Software"), to deal in the Software without %% restriction, including without limitation the rights to use, copy, %% modify, merge, publish, distribute, sublicense, and/or sell copies %% of the Software, and to permit persons to whom the Software is %% furnished to do so, subject to the following conditions: %% %% The above copyright notice and this permission notice shall be %% included in all copies or substantial portions of the Software. %% %% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, %% EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF %% MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND %% NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS %% BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN %% ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN %% CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE %% SOFTWARE. %%--------------------------------------------------------------------------- -module(test_jsonrpc_inets). -include("rfc4627_jsonrpc.hrl"). -behaviour(gen_server). -export([start/0, start_httpd/0]). -export([init/1, terminate/2, code_change/3, handle_call/3, handle_cast/2, handle_info/2]). start() -> {ok, Pid} = gen_server:start(?MODULE, [], []), rfc4627_jsonrpc:register_service (Pid, rfc4627_jsonrpc:service(<<"test">>, <<"urn:uuid:afe1b4b5-23b0-4964-a74a-9168535c96b2">>, <<"1.0">>, [#service_proc{name = <<"test_proc">>, idempotent = true, params = [#service_proc_param{name = <<"value">>, type = <<"str">>}]}, #service_proc{name = <<"crash">>, idempotent = false, params = []}])). start_httpd() -> ok = case rfc4627_jsonrpc:start() of {ok, _JsonrpcPid} -> ok; {error, {already_started, _JsonrpcPid}} -> ok end, ok = inets:start(), {ok, _HttpdPid} = inets:start(httpd, [{file, "test/server_root/conf/httpd.conf"}]), start(). %--------------------------------------------------------------------------- init(_Args) -> {ok, no_state}. terminate(_Reason, _State) -> ok. code_change(_OldVsn, State, _Extra) -> {ok, State}. handle_call({jsonrpc, <<"test_proc">>, _ModData, [Value]}, _From, State) -> {reply, {result, <<"ErlangServer: ", Value/binary>>}, State}; handle_call({jsonrpc, <<"crash">>, _ModData, []}, _From, _State) -> exit(deliberate_crash). handle_cast(Request, State) -> error_logger:error_msg("Unhandled cast in test_jsonrpc: ~p", [Request]), {noreply, State}. handle_info(Info, State) -> error_logger:error_msg("Unhandled info in test_jsonrpc: ~p", [Info]), {noreply, State}. rabbitmq-server-3.2.4/plugins-src/erlang-rfc4627-wrapper/erlang-rfc4627-git/test/test_rfc4627.erl0000644000000000000000000002050512305126066030560 0ustar rootroot%% Basic JSON (RFC-4627) codec tests %%--------------------------------------------------------------------------- %% Copyright (c) 2007-2010 Tony Garnock-Jones %% Copyright (c) 2007-2010 LShift Ltd. %% %% Permission is hereby granted, free of charge, to any person %% obtaining a copy of this software and associated documentation %% files (the "Software"), to deal in the Software without %% restriction, including without limitation the rights to use, copy, %% modify, merge, publish, distribute, sublicense, and/or sell copies %% of the Software, and to permit persons to whom the Software is %% furnished to do so, subject to the following conditions: %% %% The above copyright notice and this permission notice shall be %% included in all copies or substantial portions of the Software. %% %% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, %% EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF %% MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND %% NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS %% BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN %% ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN %% CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE %% SOFTWARE. %%--------------------------------------------------------------------------- -module(test_rfc4627). -include("rfc4627.hrl"). -export([test_all/0]). -record(address, {number, street, town, country = <<"England">>}). test_all() -> passed = test_codec(), passed = test_records(), passed = test_dict(), passed = test_unicode(), passed = test_equiv(), passed = test_eof_detection(), passed = test_exclude(), passed. test_codec() -> Cases = [ {1, "1"}, {1, "1,", false}, {1.0, "1.0"}, {12.3, "1.23e1"}, {<<"hi">>, "\"hi\""}, {<<>>, "\"\""}, {<<"\n">>, "\"\\n\""}, {<<"\t">>, "\"\\t\""}, {<<"\\">>, "\"\\\\\""}, {<<195,133>>, [34,0,16#c5,0,34,0]}, {<<127>>, [34,0,16#7f,0,34,0]}, {<<194,128>>, [34,0,16#80,0,34,0]}, {<<30>>, "\"\\u001e\""}, {[1, 2], "[1, 2]"}, {[], "[]"}, {{obj, [{"a", 1}, {"b", 2}]}, "{\"a\": 1, \"b\": 2}"}, {{obj, []}, "{}"}, {{obj, []}, "{ \n\n }"}, {true, "true"}, {null, "null"}, {false, "false"} ], lists:foreach(fun test_codec/1, Cases), passed. test_codec({Erl, Json}) -> test_codec({Erl, Json, true}); test_codec({Erl, Json, EofExpected}) -> %% We can test Erl -> Json -> Erl, but not Json -> Erl -> %% Json. However, we can test Json -> Erl. {ok, Erl, []} = rfc4627:decode(rfc4627:encode(Erl)), {ok, Erl, Rest} = rfc4627:decode(Json), {at_eof, EofExpected} = {at_eof, (Rest == [])}, passed. %% UTF tests. test_unicode() -> passed = test_unicode_encodings(), passed = test_unicode_json(), passed. test_unicode_encodings() -> ZWaterBass = [16#0000007A, 16#00006C34, 16#0001D11E], U32B = [0, 0, 16#00, 16#7A, 0, 0, 16#6C, 16#34, 0, 1, 16#D1, 16#1E] = rfc4627:unicode_encode({'utf-32be', ZWaterBass}), U32L = [16#7A, 0, 0, 0, 16#34, 16#6C, 0, 0, 16#1E, 16#D1, 1, 0] = rfc4627:unicode_encode({'utf-32le', ZWaterBass}), U32B_BOM = [0, 0, 16#FE, 16#FF, 0, 0, 16#00, 16#7A, 0, 0, 16#6C, 16#34, 0, 1, 16#D1, 16#1E] = rfc4627:unicode_encode({'utf-32', ZWaterBass}), U16L = [16#7A, 16#00, 16#34, 16#6C, 16#34, 16#D8, 16#1E, 16#DD] = rfc4627:unicode_encode({'utf-16le', ZWaterBass}), U16B = [16#00, 16#7A, 16#6C, 16#34, 16#D8, 16#34, 16#DD, 16#1E] = rfc4627:unicode_encode({'utf-16be', ZWaterBass}), U16B_BOM = [16#FE, 16#FF, 16#00, 16#7A, 16#6C, 16#34, 16#D8, 16#34, 16#DD, 16#1E] = rfc4627:unicode_encode({'utf-16', ZWaterBass}), U8 = [16#7A, 16#E6,16#B0,16#B4, 16#F0,16#9D,16#84,16#9E] = rfc4627:unicode_encode({'utf-8', ZWaterBass}), {'utf-32be', ZWaterBass} = rfc4627:unicode_decode(U32B), {'utf-32le', ZWaterBass} = rfc4627:unicode_decode(U32L), {'utf-32', ZWaterBass} = rfc4627:unicode_decode(U32B_BOM), {'utf-16be', ZWaterBass} = rfc4627:unicode_decode(U16B), {'utf-16le', ZWaterBass} = rfc4627:unicode_decode(U16L), {'utf-16', ZWaterBass} = rfc4627:unicode_decode(U16B_BOM), {'utf-8', ZWaterBass} = rfc4627:unicode_decode(U8), {'utf-8', ZWaterBass} = rfc4627:unicode_decode([16#EF,16#BB,16#BF]++U8), passed. test_unicode_json() -> U16B = [16#00, 16#7A, 16#6C, 16#34, 16#D8, 16#34, 16#DD, 16#1E], U16BQuote = [0, 16#22], U32L = [16#7A, 0, 0, 0, 16#34, 16#6C, 0, 0, 16#1E, 16#D1, 1, 0], U32LQuote = [16#22, 0, 0, 0], U8 = [16#7A, 16#E6,16#B0,16#B4, 16#F0,16#9D,16#84,16#9E], U8Bin = list_to_binary(U8), {utf8_decode, {ok, U8Bin, ""}} = {utf8_decode, rfc4627:decode("\"" ++ U8 ++ "\"")}, {utf16_decode, {ok, U8Bin, ""}} = {utf16_decode, rfc4627:decode(U16BQuote ++ U16B ++ U16BQuote)}, {utf32_decode, {ok, U8Bin, ""}} = {utf32_decode, rfc4627:decode(U32LQuote ++ U32L ++ U32LQuote)}, {u_escape_decode, {ok, U8Bin, ""}} = {u_escape_decode, rfc4627:decode("\"\\u007a\\u6c34\\ud834\\udd1e\"")}, {u_escape_decode, {ok, U8Bin, ""}} = {u_escape_decode, rfc4627:decode("\"z\\u6C34\\uD834\\uDD1E\"")}, UnicodeKeyed = {obj, [{[16#C5], list_to_binary(xmerl_ucs:to_utf8([16#C5]))}]}, {utf8_roundtrip, {ok, UnicodeKeyed, ""}} = {utf8_roundtrip, rfc4627:decode(rfc4627:encode(UnicodeKeyed))}, {utf16_roundtrip, {ok, UnicodeKeyed, ""}} = {utf16_roundtrip, rfc4627:decode(rfc4627:unicode_encode({'utf-16le', rfc4627:encode_noauto(UnicodeKeyed)}))}, {utf32_roundtrip, {ok, UnicodeKeyed, ""}} = {utf32_roundtrip, rfc4627:decode(rfc4627:unicode_encode({'utf-32be', rfc4627:encode_noauto(UnicodeKeyed)}))}, passed. test_records() -> A = #address{number = 6, street = <<"Rufus Street">>, town = <<"London">>}, AEnc = {obj, [{"number", 6}, {"street", <<"Rufus Street">>}, {"town", <<"London">>}, {"country", <<"England">>}]} = ?RFC4627_FROM_RECORD(address, A), A = ?RFC4627_TO_RECORD(address, {obj, [{"number", 6}, {"street", <<"Rufus Street">>}, {"town", <<"London">>}]}), {ok, AEnc, []} = rfc4627:decode(rfc4627:encode(AEnc)), passed. test_dict() -> Dict = dict:append("c", 2, dict:append("c", 1, dict:store("b", <<"hello">>, dict:store("a", 123, dict:new())))), {ok, Obj, ""} = rfc4627:decode(rfc4627:encode(Dict)), {ok, 123} = rfc4627:get_field(Obj, "a"), {ok, <<"hello">>} = rfc4627:get_field(Obj, "b"), {ok, [1, 2]} = rfc4627:get_field(Obj, "c"), passed. test_exclude() -> Dict = dict:store("c", 2, dict:store("b", <<"hello">>, dict:store("a", 123, dict:new()))), {ok, Obj, ""} = rfc4627:decode(rfc4627:encode(Dict)), Obj2 = rfc4627:exclude_field(Obj, "a"), true = rfc4627:equiv({obj, [{"c", 2}, {"b", <<"hello">>}]}, Obj2), Obj3 = rfc4627:exclude_field(Obj2, "b"), true = rfc4627:equiv({obj, [{"c", 2}]}, Obj3), Obj4 = rfc4627:exclude_field(Obj3, "x"), true = rfc4627:equiv({obj, [{"c", 2}]}, Obj4), Obj5 = rfc4627:exclude_field(Obj3, "c"), true = rfc4627:equiv({obj, []}, Obj5), passed. test_equiv() -> true = rfc4627:equiv([1, 2], [1, 2]), false = rfc4627:equiv([1, 2], [2, 1]), false = rfc4627:equiv([1, 2], [1]), false = rfc4627:equiv([1], [1, 2]), true = rfc4627:equiv([], []), false = rfc4627:equiv([], [1]), false = rfc4627:equiv([1], []), true = rfc4627:equiv({obj, [{"a", true}, {"b", 123}]}, {obj, [{"a", true}, {"b", 123}]}), true = rfc4627:equiv({obj, [{"a", true}, {"b", 123}]}, {obj, [{"b", 123}, {"a", true}]}), false = rfc4627:equiv({obj, [{"a", true}, {"b", 124}]}, {obj, [{"a", true}, {"b", 123}]}), false = rfc4627:equiv({obj, [{"b", 123}]}, {obj, [{"a", true}, {"b", 123}]}), false = rfc4627:equiv({obj, [{"a", true}, {"b", 123}]}, {obj, [{"b", 123}]}), true = rfc4627:equiv({obj, []}, {obj, []}), false = rfc4627:equiv({obj, []}, {obj, [{"a", true}, {"b", 123}]}), true = rfc4627:equiv(<<"ab">>, <<"ab">>), false = rfc4627:equiv(<<"ab">>, <<"a">>), true = rfc4627:equiv(<<>>, <<>>), passed. test_eof_detection() -> {error, unexpected_end_of_input} = rfc4627:decode(""), {error, syntax_error} = rfc4627:decode("()"), passed. rabbitmq-server-3.2.4/plugins-src/erlang-rfc4627-wrapper/erlang-rfc4627-git/Makefile0000644000000000000000000000462012305126066026401 0ustar rootrootSOURCE_DIR=src EBIN_DIR=ebin DOC_DIR=doc INCLUDE_DIR=include INCLUDES=$(wildcard $(INCLUDE_DIR)/*.hrl) SOURCES=$(wildcard $(SOURCE_DIR)/*.erl) TARGETS=$(patsubst $(SOURCE_DIR)/%.erl, $(EBIN_DIR)/%.beam,$(SOURCES)) ERLC_OPTS=-I $(INCLUDE_DIR) -o $(EBIN_DIR) $(INETS_DEF) -Wall +debug_info # +native -v DIST_DIR=dist SIGNING_KEY_ID=F8D7D525 VERSION=HEAD PACKAGE_NAME=rfc4627_jsonrpc ## The path to httpd.hrl changed at R14A, and then changed again ## between OTP R14B and R14B01. Detect the changes, and supply ## compile-time macro definitions to allow rfc4627_jsonrpc_inets.erl ## to adapt to the new paths. ERLANG_OTP_RELEASE:=$(shell erl -noshell -eval 'io:format(erlang:system_info(otp_release)), halt().') $(info Building for OTP release $(ERLANG_OTP_RELEASE).) ifeq ($(shell test R14A \> $(ERLANG_OTP_RELEASE) && echo yes),yes) $(info Using path to INETS httpd.hrl that existed before R14A.) INETS_DEF=-Dinets_pre_r14a else ifeq ($(shell test R14B01 \> $(ERLANG_OTP_RELEASE) && echo yes),yes) $(info Using path to INETS httpd.hrl that existed before R14B01.) INETS_DEF=-Dinets_pre_r14b01 else $(info Using path to INETS httpd.hrl that exists in releases at and after R14B01.) INETS_DEF= endif endif all: $(TARGETS) $(EBIN_DIR)/%.beam: $(SOURCE_DIR)/%.erl $(INCLUDES) erlc $(ERLC_OPTS) $< clean: rm -f ebin/*.beam rm -f $(TARGETS) rm -rf $(DIST_DIR) rm -rf $(DOC_DIR) dist: all doc/index.html mkdir -p $(DIST_DIR) cp -r doc ebin include src test Makefile $(DIST_DIR) distclean: clean rm -rf $(DIST_DIR) find . -name '*~' -exec rm {} \; debian-package: clean @(cat debian/changelog | head -1 | fgrep -q 'rfc4627-erlang ($(VERSION))') || \ (echo "No changelog entry for version $(VERSION) exists. Aborting."; false) tar -cf debian-package.tar `ls | grep -v _darcs` mkdir build cd build; tar -xf ../debian-package.tar cd build; dpkg-buildpackage -rfakeroot -k$(SIGNING_KEY_ID) rm -rf build debian-package.tar $(DOC_DIR)/index.html: $(DOC_DIR)/overview.edoc erl -noshell \ -eval 'edoc:application(rfc4627, ".", [{overview, "$(DOC_DIR)/overview.edoc"}, {dir, "$(DOC_DIR)"}])' \ -run init stop cp src/doc/JSON-RPC-1-1-WD-20060807.html $(DOC_DIR) $(DOC_DIR)/overview.edoc: src/doc/overview.edoc.in mkdir -p $(DOC_DIR) sed -e 's:%%VERSION%%:$(VERSION):g' < $< > $@ test-compile: erlc $(ERLC_OPTS) $(wildcard test/*.erl) test: all test-compile erl -pa ebin -noshell -eval 'passed = test_rfc4627:test_all(), c:q().' rabbitmq-server-3.2.4/plugins-src/erlang-rfc4627-wrapper/erlang-rfc4627-git/ebin/0000755000000000000000000000000012305126066025654 5ustar rootroot././@LongLink0000000000000000000000000000014500000000000011565 Lustar rootrootrabbitmq-server-3.2.4/plugins-src/erlang-rfc4627-wrapper/erlang-rfc4627-git/ebin/rfc4627_jsonrpc.apprabbitmq-server-3.2.4/plugins-src/erlang-rfc4627-wrapper/erlang-rfc4627-git/ebin/rfc4627_jsonrpc.app0000644000000000000000000000062212305126066031211 0ustar rootroot{application, rfc4627_jsonrpc, [{description, "JSON RPC Service"}, {vsn, "0.01"}, {modules, [ rfc4627, rfc4627_jsonrpc, rfc4627_jsonrpc_app, rfc4627_jsonrpc_sup, rfc4627_jsonrpc_http, rfc4627_jsonrpc_inets, rfc4627_jsonrpc_mochiweb, rfc4627_jsonrpc_registry ]}, {registered, []}, {mod, {rfc4627_jsonrpc_app, []}}, {env, []}, {applications, [kernel, stdlib]}]}. rabbitmq-server-3.2.4/plugins-src/erlang-rfc4627-wrapper/erlang-rfc4627-git/include/0000755000000000000000000000000012305126066026362 5ustar rootrootrabbitmq-server-3.2.4/plugins-src/erlang-rfc4627-wrapper/erlang-rfc4627-git/include/rfc4627.hrl0000644000000000000000000000343112305126066030167 0ustar rootroot%% JSON - RFC 4627 - for Erlang %%--------------------------------------------------------------------------- %% Copyright (c) 2007-2010, 2011, 2012 Tony Garnock-Jones %% Copyright (c) 2007-2010 LShift Ltd. %% %% Permission is hereby granted, free of charge, to any person %% obtaining a copy of this software and associated documentation %% files (the "Software"), to deal in the Software without %% restriction, including without limitation the rights to use, copy, %% modify, merge, publish, distribute, sublicense, and/or sell copies %% of the Software, and to permit persons to whom the Software is %% furnished to do so, subject to the following conditions: %% %% The above copyright notice and this permission notice shall be %% included in all copies or substantial portions of the Software. %% %% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, %% EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF %% MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND %% NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS %% BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN %% ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN %% CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE %% SOFTWARE. %%--------------------------------------------------------------------------- %% %% Convenience macros for encoding and decoding record structures. %% %% Erlang's compile-time-only notion of record definitions means we %% have to supply a constant record name in the source text. -define(RFC4627_FROM_RECORD(RName, R), rfc4627:from_record(R, RName, record_info(fields, RName))). -define(RFC4627_TO_RECORD(RName, R), rfc4627:to_record(R, #RName{}, record_info(fields, RName))). ././@LongLink0000000000000000000000000000015000000000000011561 Lustar rootrootrabbitmq-server-3.2.4/plugins-src/erlang-rfc4627-wrapper/erlang-rfc4627-git/include/rfc4627_jsonrpc.hrlrabbitmq-server-3.2.4/plugins-src/erlang-rfc4627-wrapper/erlang-rfc4627-git/include/rfc4627_jsonrpc.0000644000000000000000000000320712305126066031220 0ustar rootroot%% JSON-RPC for Erlang %%--------------------------------------------------------------------------- %% Copyright (c) 2007-2010, 2011, 2012 Tony Garnock-Jones %% Copyright (c) 2007-2010 LShift Ltd. %% %% Permission is hereby granted, free of charge, to any person %% obtaining a copy of this software and associated documentation %% files (the "Software"), to deal in the Software without %% restriction, including without limitation the rights to use, copy, %% modify, merge, publish, distribute, sublicense, and/or sell copies %% of the Software, and to permit persons to whom the Software is %% furnished to do so, subject to the following conditions: %% %% The above copyright notice and this permission notice shall be %% included in all copies or substantial portions of the Software. %% %% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, %% EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF %% MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND %% NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS %% BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN %% ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN %% CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE %% SOFTWARE. %%--------------------------------------------------------------------------- %% %% Records for JSON-RPC services using the rfc4627_jsonrpc module. -record(service, {handler, name, id, version, summary, help, procs}). -record(service_proc, {name, summary, help, idempotent = false, params, return}). -record(service_proc_param, {name, type}). rabbitmq-server-3.2.4/plugins-src/erlang-rfc4627-wrapper/erlang-rfc4627-git/.done0000644000000000000000000000000012305126066025653 0ustar rootrootrabbitmq-server-3.2.4/plugins-src/erlang-rfc4627-wrapper/erlang-rfc4627-git/debian/0000755000000000000000000000000012305126066026161 5ustar rootrootrabbitmq-server-3.2.4/plugins-src/erlang-rfc4627-wrapper/erlang-rfc4627-git/debian/copyright0000644000000000000000000000265112305126066030120 0ustar rootrootThis package was debianized by Tony Garnock-Jones on Fri, 19 Jan 2007 20:08:56 +0000. Upstream Author: Tony Garnock-Jones Copyright: 2007 Tony Garnock-Jones, 2007 LShift Ltd. License: Copyright (c) 2007 Tony Garnock-Jones and LShift Ltd. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. The Debian packaging is (C) 2007, Tony Garnock-Jones and is licensed under the GPL, see `/usr/share/common-licenses/GPL'. rabbitmq-server-3.2.4/plugins-src/erlang-rfc4627-wrapper/erlang-rfc4627-git/debian/postinst.ex0000644000000000000000000000170012305126066030400 0ustar rootroot#!/bin/sh # postinst script for rabbitmq # # see: dh_installdeb(1) set -e # summary of how this script can be called: # * `configure' # * `abort-upgrade' # * `abort-remove' `in-favour' # # * `abort-remove' # * `abort-deconfigure' `in-favour' # `removing' # # for details, see http://www.debian.org/doc/debian-policy/ or # the debian-policy package case "$1" in configure) ;; abort-upgrade|abort-remove|abort-deconfigure) ;; *) echo "postinst called with unknown argument \`$1'" >&2 exit 1 ;; esac # dh_installdeb will replace this with shell code automatically # generated by other debhelper scripts. #DEBHELPER# exit 0 rabbitmq-server-3.2.4/plugins-src/erlang-rfc4627-wrapper/erlang-rfc4627-git/debian/compat0000644000000000000000000000000212305126066027357 0ustar rootroot5 rabbitmq-server-3.2.4/plugins-src/erlang-rfc4627-wrapper/erlang-rfc4627-git/debian/rules0000755000000000000000000000033112305126066027236 0ustar rootroot#!/usr/bin/make -f include /usr/share/cdbs/1/rules/debhelper.mk include /usr/share/cdbs/1/class/makefile.mk DEB_MAKE_INSTALL_TARGET := dist DIST_DIR=$(DEB_DESTDIR)usr/lib/erlang/lib/rfc4627-$(DEB_UPSTREAM_VERSION)/ rabbitmq-server-3.2.4/plugins-src/erlang-rfc4627-wrapper/erlang-rfc4627-git/debian/control0000644000000000000000000000057212305126066027570 0ustar rootrootSource: rfc4627-erlang Section: libs Priority: extra Maintainer: Tony Garnock-Jones Build-Depends: cdbs, debhelper (>= 5), erlang-base | erlang-base-hipe, erlang-nox, erlang-dev, make Standards-Version: 3.7.2 Package: rfc4627-erlang Architecture: all Depends: erlang-base | erlang-base-hipe Description: A JSON (RFC4627) codec and JSON-RPC server for Erlang rabbitmq-server-3.2.4/plugins-src/erlang-rfc4627-wrapper/erlang-rfc4627-git/debian/prerm.ex0000644000000000000000000000156012305126066027646 0ustar rootroot#!/bin/sh # prerm script for rabbitmq # # see: dh_installdeb(1) set -e # summary of how this script can be called: # * `remove' # * `upgrade' # * `failed-upgrade' # * `remove' `in-favour' # * `deconfigure' `in-favour' # `removing' # # for details, see http://www.debian.org/doc/debian-policy/ or # the debian-policy package case "$1" in remove|upgrade|deconfigure) ;; failed-upgrade) ;; *) echo "prerm called with unknown argument \`$1'" >&2 exit 1 ;; esac # dh_installdeb will replace this with shell code automatically # generated by other debhelper scripts. #DEBHELPER# exit 0 rabbitmq-server-3.2.4/plugins-src/erlang-rfc4627-wrapper/erlang-rfc4627-git/debian/postrm.ex0000644000000000000000000000164512305126066030051 0ustar rootroot#!/bin/sh # postrm script for rabbitmq # # see: dh_installdeb(1) set -e # summary of how this script can be called: # * `remove' # * `purge' # * `upgrade' # * `failed-upgrade' # * `abort-install' # * `abort-install' # * `abort-upgrade' # * `disappear' # # for details, see http://www.debian.org/doc/debian-policy/ or # the debian-policy package case "$1" in purge|remove|upgrade|failed-upgrade|abort-install|abort-upgrade|disappear) ;; *) echo "postrm called with unknown argument \`$1'" >&2 exit 1 ;; esac # dh_installdeb will replace this with shell code automatically # generated by other debhelper scripts. #DEBHELPER# exit 0 rabbitmq-server-3.2.4/plugins-src/erlang-rfc4627-wrapper/erlang-rfc4627-git/debian/dirs0000644000000000000000000000002312305126066027040 0ustar rootrootusr/lib/erlang/lib rabbitmq-server-3.2.4/plugins-src/erlang-rfc4627-wrapper/erlang-rfc4627-git/debian/preinst.ex0000644000000000000000000000126512305126066030207 0ustar rootroot#!/bin/sh # preinst script for rabbitmq # # see: dh_installdeb(1) set -e # summary of how this script can be called: # * `install' # * `install' # * `upgrade' # * `abort-upgrade' # for details, see http://www.debian.org/doc/debian-policy/ or # the debian-policy package case "$1" in install|upgrade) ;; abort-upgrade) ;; *) echo "preinst called with unknown argument \`$1'" >&2 exit 1 ;; esac # dh_installdeb will replace this with shell code automatically # generated by other debhelper scripts. #DEBHELPER# exit 0 rabbitmq-server-3.2.4/plugins-src/erlang-rfc4627-wrapper/erlang-rfc4627-git/debian/changelog0000644000000000000000000000250612305126066030036 0ustar rootrootrfc4627-erlang (1.1.1) unstable; urgency=low * Fix \u escaping for surrogate pairs. -- Tony Garnock-Jones Thu, 01 May 2008 12:10:41 +0100 rfc4627-erlang (1.1.0-1) unstable; urgency=low * Unicode support per RFC. -- Tony Garnock-Jones Wed, 03 Oct 2007 15:58:39 +0100 rfc4627-erlang (1.0.4-1) unstable; urgency=low * Support X-JSON-RPC-Timeout header (value in milliseconds). -- Tony Garnock-Jones Thu, 21 Jun 2007 15:00:46 +0100 rfc4627-erlang (1.0.3-1) unstable; urgency=low * Add start_link for use in supervision hierarchies. -- Tony Garnock-Jones Wed, 20 Jun 2007 14:04:42 +0100 rfc4627-erlang (1.0.2-1) unstable; urgency=low * Documentation for release * Minor API improvements * MIT licensing -- Tony Garnock-Jones Sat, 17 Feb 2007 14:44:57 +0000 rfc4627-erlang (1.0.1-1) unstable; urgency=low * JSON-RPC transport is factored out on the client * Header file path correction * No longer take any action synchronously in the JS client -- Tony Garnock-Jones Mon, 29 Jan 2007 15:28:06 +0000 rfc4627-erlang (1.0-1) unstable; urgency=low * Initial release -- Tony Garnock-Jones Fri, 26 Jan 2007 14:17:16 +0000 rabbitmq-server-3.2.4/plugins-src/erlang-rfc4627-wrapper/erlang-rfc4627-git/rebar.config0000644000000000000000000000002612305126066027217 0ustar rootroot%-*-mode: erlang -*- rabbitmq-server-3.2.4/plugins-src/erlang-rfc4627-wrapper/.srcdist_done0000644000000000000000000000000012305126066024262 0ustar rootrootrabbitmq-server-3.2.4/plugins-src/erlang-rfc4627-wrapper/hash.mk0000644000000000000000000000003512305126066023065 0ustar rootrootUPSTREAM_SHORT_HASH:=5e67120 rabbitmq-server-3.2.4/plugins-src/erlang-rfc4627-wrapper/Makefile0000644000000000000000000000002712305126066023252 0ustar rootrootinclude ../umbrella.mk rabbitmq-server-3.2.4/plugins-src/erlang-rfc4627-wrapper/package.mk0000644000000000000000000000155712305126066023547 0ustar rootrootAPP_NAME:=rfc4627_jsonrpc DEPS:=mochiweb-wrapper UPSTREAM_GIT:=https://github.com/rabbitmq/erlang-rfc4627.git UPSTREAM_REVISION:=5e67120216b11a2ff5d74e00a789b219d0a3bc36 WRAPPER_PATCHES:=10-no-cowboy-dependency.patch ORIGINAL_APP_FILE=$(CLONE_DIR)/ebin/$(APP_NAME).app DO_NOT_GENERATE_APP_FILE=true ## The path to httpd.hrl has changed in OTP R14A and newer. Detect the ## change, and supply a compile-time macro definition to allow ## rfc4627_jsonrpc_inets.erl to adapt to the new path. ifeq ($(shell erl -noshell -eval 'io:format([list_to_integer(X) || X <- string:tokens(erlang:system_info(version), ".")] < [5,8]), halt().'),true) PACKAGE_ERLC_OPTS+=-Dinets_pre_r14a else ifeq ($(shell erl -noshell -eval 'io:format([list_to_integer(X) || X <- string:tokens(erlang:system_info(version), ".")] < [5,8,2]), halt().'),true) PACKAGE_ERLC_OPTS+=-Dinets_pre_r14b01 endif endif rabbitmq-server-3.2.4/plugins-src/rabbitmq-tracing/0000755000000000000000000000000012305126066021020 5ustar rootrootrabbitmq-server-3.2.4/plugins-src/rabbitmq-tracing/priv/0000755000000000000000000000000012305126066022000 5ustar rootrootrabbitmq-server-3.2.4/plugins-src/rabbitmq-tracing/priv/www/0000755000000000000000000000000012305126066022624 5ustar rootrootrabbitmq-server-3.2.4/plugins-src/rabbitmq-tracing/priv/www/js/0000755000000000000000000000000012305126066023240 5ustar rootrootrabbitmq-server-3.2.4/plugins-src/rabbitmq-tracing/priv/www/js/tracing.js0000644000000000000000000000242612305126066025231 0ustar rootrootdispatcher_add(function(sammy) { sammy.get('#/traces', function() { render({'traces': '/traces', 'vhosts': '/vhosts', 'files': '/trace-files'}, 'traces', '#/traces'); }); sammy.get('#/traces/:vhost/:name', function() { var path = '/traces/' + esc(this.params['vhost']) + '/' + esc(this.params['name']); render({'trace': path}, 'trace', '#/traces'); }); sammy.put('#/traces', function() { if (sync_put(this, '/traces/:vhost/:name')) update(); return false; }); sammy.del('#/traces', function() { if (sync_delete(this, '/traces/:vhost/:name')) partial_update(); return false; }); sammy.del('#/trace-files', function() { if (sync_delete(this, '/trace-files/:name')) partial_update(); return false; }); }); NAVIGATION['Admin'][0]['Tracing'] = ['#/traces', 'administrator']; function link_trace(name) { return _link_to(fmt_escape_html(name), 'api/trace-files/' + esc(name)); } function link_trace_queue(trace) { return _link_to('(queue)', '#/queues/' + esc(trace.vhost) + '/' + esc(trace.queue.name)); } rabbitmq-server-3.2.4/plugins-src/rabbitmq-tracing/priv/www/js/tmpl/0000755000000000000000000000000012305126066024214 5ustar rootrootrabbitmq-server-3.2.4/plugins-src/rabbitmq-tracing/priv/www/js/tmpl/traces.ejs0000644000000000000000000001130612305126066026201 0ustar rootroot

    Traces

    All traces

    Currently running traces

    <% if (traces.length > 0) { %> <% if (vhosts_interesting) { %> <% } %> <% for (var i = 0; i < traces.length; i++) { var trace = traces[i]; %> > <% if (vhosts_interesting) { %> <% } %> <% if (trace.queue) { %> <% } else { %> <% } %> <% } %>
    Virtual hostName Pattern Format Rate Queued
    <%= fmt_string(trace.vhost) %><%= fmt_string(trace.name) %> <%= fmt_string(trace.pattern) %> <%= fmt_string(trace.format) %> <%= fmt_rate(trace.queue.message_stats, 'ack', false) %> <%= trace.queue.messages %> <%= link_trace_queue(trace) %>
    FAILED
    <% } else { %>

    ... no traces running ...

    <% } %>

    Trace log files

    <% if (files.length > 0) { %> <% for (var i = 0; i < files.length; i++) { var file = files[i]; %> > <% } %>
    Name Size
    <%= link_trace(file.name) %> <%= fmt_bytes(file.size) %>
    <% } else { %>

    ... no files ...

    <% } %>

    Add a new trace

    <% if (vhosts_interesting) { %> <% } else { %> <% } %>
    *
    Examples: #, publish.#, deliver.# #.amq.direct, #.myqueue
    rabbitmq-server-3.2.4/plugins-src/rabbitmq-tracing/src/0000755000000000000000000000000012305126066021607 5ustar rootrootrabbitmq-server-3.2.4/plugins-src/rabbitmq-tracing/src/rabbit_tracing_wm_file.erl0000644000000000000000000000344712305126066026777 0ustar rootroot%% The contents of this file are subject to the Mozilla Public License %% Version 1.1 (the "License"); you may not use this file except in %% compliance with the License. You may obtain a copy of the License at %% http://www.mozilla.org/MPL/ %% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the %% License for the specific language governing rights and limitations %% under the License. %% %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is GoPivotal, Inc. %% Copyright (c) 2007-2013 GoPivotal, Inc. All rights reserved. -module(rabbit_tracing_wm_file). -export([init/1, resource_exists/2, serve/2, content_types_provided/2, is_authorized/2, allowed_methods/2, delete_resource/2]). -include_lib("rabbitmq_management/include/rabbit_mgmt.hrl"). -include_lib("webmachine/include/webmachine.hrl"). %%-------------------------------------------------------------------- init(_Config) -> {ok, #context{}}. content_types_provided(ReqData, Context) -> {[{"text/plain", serve}], ReqData, Context}. allowed_methods(ReqData, Context) -> {['HEAD', 'GET', 'DELETE'], ReqData, Context}. resource_exists(ReqData, Context) -> Name = rabbit_mgmt_util:id(name, ReqData), {rabbit_tracing_files:exists(Name), ReqData, Context}. serve(ReqData, Context) -> Name = rabbit_mgmt_util:id(name, ReqData), {ok, Content} = file:read_file(rabbit_tracing_files:full_path(Name)), {Content, ReqData, Context}. delete_resource(ReqData, Context) -> Name = rabbit_mgmt_util:id(name, ReqData), ok = rabbit_tracing_files:delete(Name), {true, ReqData, Context}. is_authorized(ReqData, Context) -> rabbit_mgmt_util:is_authorized_admin(ReqData, Context). rabbitmq-server-3.2.4/plugins-src/rabbitmq-tracing/src/rabbit_tracing_app.erl0000644000000000000000000000147712305126066026136 0ustar rootroot%% The contents of this file are subject to the Mozilla Public License %% Version 1.1 (the "License"); you may not use this file except in %% compliance with the License. You may obtain a copy of the License %% at http://www.mozilla.org/MPL/ %% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See %% the License for the specific language governing rights and %% limitations under the License. %% %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is GoPivotal, Inc. %% Copyright (c) 2007-2013 GoPivotal, Inc. All rights reserved. %% -module(rabbit_tracing_app). -behaviour(application). -export([start/2, stop/1]). start(_Type, _StartArgs) -> rabbit_tracing_sup:start_link(). stop(_State) -> ok. rabbitmq-server-3.2.4/plugins-src/rabbitmq-tracing/src/rabbit_tracing_wm_files.erl0000644000000000000000000000253312305126066027155 0ustar rootroot%% The contents of this file are subject to the Mozilla Public License %% Version 1.1 (the "License"); you may not use this file except in %% compliance with the License. You may obtain a copy of the License %% at http://www.mozilla.org/MPL/ %% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See %% the License for the specific language governing rights and %% limitations under the License. %% %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is GoPivotal, Inc. %% Copyright (c) 2007-2013 GoPivotal, Inc. All rights reserved. %% -module(rabbit_tracing_wm_files). -export([init/1, to_json/2, content_types_provided/2, is_authorized/2]). -include_lib("rabbitmq_management/include/rabbit_mgmt.hrl"). -include_lib("webmachine/include/webmachine.hrl"). %%-------------------------------------------------------------------- init(_Config) -> {ok, #context{}}. content_types_provided(ReqData, Context) -> {[{"application/json", to_json}], ReqData, Context}. to_json(ReqData, Context) -> rabbit_mgmt_util:reply(rabbit_tracing_files:list(), ReqData, Context). is_authorized(ReqData, Context) -> rabbit_mgmt_util:is_authorized_admin(ReqData, Context). %%-------------------------------------------------------------------- rabbitmq-server-3.2.4/plugins-src/rabbitmq-tracing/src/rabbit_tracing_consumer_sup.erl0000644000000000000000000000222012305126066030063 0ustar rootroot%% The contents of this file are subject to the Mozilla Public License %% Version 1.1 (the "License"); you may not use this file except in %% compliance with the License. You may obtain a copy of the License %% at http://www.mozilla.org/MPL/ %% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See %% the License for the specific language governing rights and %% limitations under the License. %% %% The Original Code is RabbitMQ Federation. %% %% The Initial Developer of the Original Code is GoPivotal, Inc. %% Copyright (c) 2007-2013 GoPivotal, Inc. All rights reserved. %% -module(rabbit_tracing_consumer_sup). -behaviour(supervisor). -include_lib("rabbit_common/include/rabbit.hrl"). -export([start_link/1]). -export([init/1]). start_link(Args) -> supervisor2:start_link(?MODULE, Args). %%---------------------------------------------------------------------------- init(Args) -> {ok, {{one_for_one, 3, 10}, [{consumer, {rabbit_tracing_consumer, start_link, [Args]}, transient, ?MAX_WAIT, worker, [rabbit_tracing_consumer]}]}}. rabbitmq-server-3.2.4/plugins-src/rabbitmq-tracing/src/rabbitmq_tracing.app.src0000644000000000000000000000051612305126066026411 0ustar rootroot{application, rabbitmq_tracing, [{description, "RabbitMQ message logging / tracing"}, {vsn, "%%VSN%%"}, {modules, []}, {registered, []}, {mod, {rabbit_tracing_app, []}}, {env, [{username, <<"guest">>}, {directory, "/var/tmp/rabbitmq-tracing"}]}, {applications, [kernel, stdlib, rabbit, rabbitmq_management]}]}. rabbitmq-server-3.2.4/plugins-src/rabbitmq-tracing/src/rabbit_tracing_files.erl0000644000000000000000000000324312305126066026451 0ustar rootroot%% The contents of this file are subject to the Mozilla Public License %% Version 1.1 (the "License"); you may not use this file except in %% compliance with the License. You may obtain a copy of the License %% at http://www.mozilla.org/MPL/ %% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See %% the License for the specific language governing rights and %% limitations under the License. %% %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is GoPivotal, Inc. %% Copyright (c) 2007-2013 GoPivotal, Inc. All rights reserved. %% -module(rabbit_tracing_files). -include_lib("kernel/include/file.hrl"). -export([list/0, exists/1, delete/1, full_path/1]). %%-------------------------------------------------------------------- list() -> {ok, Dir} = application:get_env(rabbitmq_tracing, directory), ok = filelib:ensure_dir(Dir ++ "/a"), {ok, Names} = file:list_dir(Dir), [file_info(Name) || Name <- Names]. exists(Name) -> filelib:is_regular(full_path(Name)). delete(Name) -> ok = file:delete(full_path(Name)). full_path(Name0) when is_binary(Name0) -> full_path(binary_to_list(Name0)); full_path(Name0) -> {ok, Dir} = application:get_env(rabbitmq_tracing, directory), case mochiweb_util:safe_relative_path(Name0) of undefined -> exit(how_rude); Name -> Dir ++ "/" ++ Name end. %%-------------------------------------------------------------------- file_info(Name) -> {ok, Info} = file:read_file_info(full_path(Name)), [{name, list_to_binary(Name)}, {size, Info#file_info.size}]. rabbitmq-server-3.2.4/plugins-src/rabbitmq-tracing/src/rabbit_tracing_sup.erl0000644000000000000000000000316512305126066026161 0ustar rootroot%% The contents of this file are subject to the Mozilla Public License %% Version 1.1 (the "License"); you may not use this file except in %% compliance with the License. You may obtain a copy of the License %% at http://www.mozilla.org/MPL/ %% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See %% the License for the specific language governing rights and %% limitations under the License. %% %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is GoPivotal, Inc. %% Copyright (c) 2007-2013 GoPivotal, Inc. All rights reserved. %% -module(rabbit_tracing_sup). -behaviour(supervisor). -include_lib("rabbit_common/include/rabbit.hrl"). -define(SUPERVISOR, ?MODULE). -export([start_link/0, start_child/2, stop_child/1]). -export([init/1]). %%---------------------------------------------------------------------------- start_link() -> supervisor:start_link({local, ?SUPERVISOR}, ?MODULE, []). start_child(Id, Args) -> supervisor:start_child( ?SUPERVISOR, {Id, {rabbit_tracing_consumer_sup, start_link, [Args]}, temporary, ?MAX_WAIT, supervisor, [rabbit_tracing_consumer_sup]}). stop_child(Id) -> supervisor:terminate_child(?SUPERVISOR, Id), supervisor:delete_child(?SUPERVISOR, Id), ok. %%---------------------------------------------------------------------------- init([]) -> {ok, {{one_for_one, 3, 10}, [{traces, {rabbit_tracing_traces, start_link, []}, transient, ?MAX_WAIT, worker, [rabbit_tracing_traces]}]}}. rabbitmq-server-3.2.4/plugins-src/rabbitmq-tracing/src/rabbit_tracing_consumer.erl0000644000000000000000000001555012305126066027206 0ustar rootroot%% The contents of this file are subject to the Mozilla Public License %% Version 1.1 (the "License"); you may not use this file except in %% compliance with the License. You may obtain a copy of the License %% at http://www.mozilla.org/MPL/ %% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See %% the License for the specific language governing rights and %% limitations under the License. %% %% The Original Code is RabbitMQ Federation. %% %% The Initial Developer of the Original Code is GoPivotal, Inc. %% Copyright (c) 2007-2013 GoPivotal, Inc. All rights reserved. %% -module(rabbit_tracing_consumer). -behaviour(gen_server). -include_lib("amqp_client/include/amqp_client.hrl"). -import(rabbit_misc, [pget/2, pget/3, table_lookup/2]). -record(state, {conn, ch, vhost, queue, file, filename, format}). -record(log_record, {timestamp, type, exchange, queue, node, routing_keys, properties, payload}). -define(X, <<"amq.rabbitmq.trace">>). -export([start_link/1, info_all/1]). -export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]). start_link(Args) -> gen_server:start_link(?MODULE, Args, []). info_all(Pid) -> gen_server:call(Pid, info_all, infinity). %%---------------------------------------------------------------------------- init(Args) -> process_flag(trap_exit, true), Name = pget(name, Args), VHost = pget(vhost, Args), {ok, Username0} = application:get_env(rabbitmq_tracing, username), Username = case is_binary(Username0) of true -> Username0; false -> list_to_binary(Username0) end, {ok, Conn} = amqp_connection:start( #amqp_params_direct{username = Username, virtual_host = VHost}), link(Conn), {ok, Ch} = amqp_connection:open_channel(Conn), link(Ch), #'queue.declare_ok'{queue = Q} = amqp_channel:call(Ch, #'queue.declare'{durable = false, exclusive = true}), #'queue.bind_ok'{} = amqp_channel:call( Ch, #'queue.bind'{exchange = ?X, queue = Q, routing_key = pget(pattern, Args)}), #'basic.qos_ok'{} = amqp_channel:call(Ch, #'basic.qos'{prefetch_count = 10}), #'basic.consume_ok'{} = amqp_channel:subscribe(Ch, #'basic.consume'{queue = Q, no_ack = false}, self()), {ok, Dir} = application:get_env(directory), Filename = Dir ++ "/" ++ binary_to_list(Name) ++ ".log", case filelib:ensure_dir(Filename) of ok -> case file:open(Filename, [append]) of {ok, F} -> rabbit_tracing_traces:announce(VHost, Name, self()), Format = list_to_atom(binary_to_list(pget(format, Args))), rabbit_log:info("Tracer opened log file ~p with " "format ~p~n", [Filename, Format]), {ok, #state{conn = Conn, ch = Ch, vhost = VHost, queue = Q, file = F, filename = Filename, format = Format}}; {error, E} -> {stop, {could_not_open, Filename, E}} end; {error, E} -> {stop, {could_not_create_dir, Dir, E}} end. handle_call(info_all, _From, State = #state{vhost = V, queue = Q}) -> [QInfo] = rabbit_mgmt_db:augment_queues( [rabbit_mgmt_wm_queue:queue(V, Q)], rabbit_mgmt_util:no_range(), basic), {reply, [{queue, rabbit_mgmt_format:strip_pids(QInfo)}], State}; handle_call(_Req, _From, State) -> {reply, unknown_request, State}. handle_cast(_C, State) -> {noreply, State}. handle_info(Delivery = {#'basic.deliver'{delivery_tag = Seq}, #amqp_msg{}}, State = #state{ch = Ch, file = F, format = Format}) -> Print = fun(Fmt, Args) -> io:format(F, Fmt, Args) end, log(Format, Print, delivery_to_log_record(Delivery)), amqp_channel:cast(Ch, #'basic.ack'{delivery_tag = Seq}), {noreply, State}; handle_info(_I, State) -> {noreply, State}. terminate(shutdown, #state{conn = Conn, ch = Ch, file = F, filename = Filename}) -> catch amqp_channel:close(Ch), catch amqp_connection:close(Conn), catch file:close(F), rabbit_log:info("Tracer closed log file ~p~n", [Filename]), ok; terminate(_Reason, _State) -> ok. code_change(_, State, _) -> {ok, State}. %%---------------------------------------------------------------------------- delivery_to_log_record({#'basic.deliver'{routing_key = Key}, #amqp_msg{props = #'P_basic'{headers = H}, payload = Payload}}) -> {Type, Q} = case Key of <<"publish.", _Rest/binary>> -> {published, none}; <<"deliver.", Rest/binary>> -> {received, Rest} end, {longstr, Node} = table_lookup(H, <<"node">>), {longstr, X} = table_lookup(H, <<"exchange_name">>), {array, Keys} = table_lookup(H, <<"routing_keys">>), {table, Props} = table_lookup(H, <<"properties">>), #log_record{timestamp = rabbit_mgmt_format:timestamp(os:timestamp()), type = Type, exchange = X, queue = Q, node = Node, routing_keys = [K || {_, K} <- Keys], properties = Props, payload = Payload}. log(text, P, Record) -> P("~n~s~n", [string:copies("=", 80)]), P("~s: ", [Record#log_record.timestamp]), case Record#log_record.type of published -> P("Message published~n~n", []); received -> P("Message received~n~n", []) end, P("Node: ~s~n", [Record#log_record.node]), P("Exchange: ~s~n", [Record#log_record.exchange]), case Record#log_record.queue of none -> ok; Q -> P("Queue: ~s~n", [Q]) end, P("Routing keys: ~p~n", [Record#log_record.routing_keys]), P("Properties: ~p~n", [Record#log_record.properties]), P("Payload: ~n~s~n", [Record#log_record.payload]); log(json, P, Record) -> P("~s~n", [mochijson2:encode( [{timestamp, Record#log_record.timestamp}, {type, Record#log_record.type}, {node, Record#log_record.node}, {exchange, Record#log_record.exchange}, {queue, Record#log_record.queue}, {routing_keys, Record#log_record.routing_keys}, {properties, rabbit_mgmt_format:amqp_table( Record#log_record.properties)}, {payload, base64:encode(Record#log_record.payload)}])]). rabbitmq-server-3.2.4/plugins-src/rabbitmq-tracing/src/rabbit_tracing_traces.erl0000644000000000000000000000733012305126066026631 0ustar rootroot%% The contents of this file are subject to the Mozilla Public License %% Version 1.1 (the "License"); you may not use this file except in %% compliance with the License. You may obtain a copy of the License %% at http://www.mozilla.org/MPL/ %% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See %% the License for the specific language governing rights and %% limitations under the License. %% %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is GoPivotal, Inc. %% Copyright (c) 2007-2013 GoPivotal, Inc. All rights reserved. %% -module(rabbit_tracing_traces). -behaviour(gen_server). -import(rabbit_misc, [pget/2]). -export([list/0, lookup/2, create/3, stop/2, announce/3]). -export([start_link/0]). -export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]). -define(SERVER, ?MODULE). -record(state, { table }). %%-------------------------------------------------------------------- start_link() -> gen_server:start_link({local, ?MODULE}, ?MODULE, [], []). list() -> gen_server:call(?MODULE, list, infinity). lookup(VHost, Name) -> gen_server:call(?MODULE, {lookup, VHost, Name}, infinity). create(VHost, Name, Trace) -> gen_server:call(?MODULE, {create, VHost, Name, Trace}, infinity). stop(VHost, Name) -> gen_server:call(?MODULE, {stop, VHost, Name}, infinity). announce(VHost, Name, Pid) -> gen_server:cast(?MODULE, {announce, {VHost, Name}, Pid}). %%-------------------------------------------------------------------- init([]) -> {ok, #state{table = ets:new(anon, [private])}}. handle_call(list, _From, State = #state{table = Table}) -> {reply, [augment(Trace) || {_K, Trace} <- ets:tab2list(Table)], State}; handle_call({lookup, VHost, Name}, _From, State = #state{table = Table}) -> {reply, case ets:lookup(Table, {VHost, Name}) of [] -> not_found; [{_K, Trace}] -> augment(Trace) end, State}; handle_call({create, VHost, Name, Trace0}, _From, State = #state{table = Table}) -> Already = vhost_tracing(VHost, Table), Trace = pset(vhost, VHost, pset(name, Name, Trace0)), true = ets:insert(Table, {{VHost, Name}, Trace}), case Already of true -> ok; false -> rabbit_trace:start(VHost) end, {reply, rabbit_tracing_sup:start_child({VHost, Name}, Trace), State}; handle_call({stop, VHost, Name}, _From, State = #state{table = Table}) -> true = ets:delete(Table, {VHost, Name}), case vhost_tracing(VHost, Table) of true -> ok; false -> rabbit_trace:stop(VHost) end, rabbit_tracing_sup:stop_child({VHost, Name}), {reply, ok, State}; handle_call(_Req, _From, State) -> {reply, unknown_request, State}. handle_cast({announce, Key, Pid}, State = #state{table = Table}) -> case ets:lookup(Table, Key) of [] -> ok; [{_, Trace}] -> ets:insert(Table, {Key, pset(pid, Pid, Trace)}) end, {noreply, State}; handle_cast(_C, State) -> {noreply, State}. handle_info(_I, State) -> {noreply, State}. terminate(_, _) -> ok. code_change(_, State, _) -> {ok, State}. %%-------------------------------------------------------------------- pset(Key, Value, List) -> [{Key, Value} | proplists:delete(Key, List)]. vhost_tracing(VHost, Table) -> case [true || {{V, _}, _} <- ets:tab2list(Table), V =:= VHost] of [] -> false; _ -> true end. augment(Trace) -> Pid = pget(pid, Trace), Trace1 = lists:keydelete(pid, 1, Trace), case Pid of undefined -> Trace1; _ -> rabbit_tracing_consumer:info_all(Pid) ++ Trace1 end. rabbitmq-server-3.2.4/plugins-src/rabbitmq-tracing/src/rabbit_tracing_wm_traces.erl0000644000000000000000000000253512305126066027336 0ustar rootroot%% The contents of this file are subject to the Mozilla Public License %% Version 1.1 (the "License"); you may not use this file except in %% compliance with the License. You may obtain a copy of the License %% at http://www.mozilla.org/MPL/ %% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See %% the License for the specific language governing rights and %% limitations under the License. %% %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is GoPivotal, Inc. %% Copyright (c) 2007-2013 GoPivotal, Inc. All rights reserved. %% -module(rabbit_tracing_wm_traces). -export([init/1, to_json/2, content_types_provided/2, is_authorized/2]). -include_lib("rabbitmq_management/include/rabbit_mgmt.hrl"). -include_lib("webmachine/include/webmachine.hrl"). %%-------------------------------------------------------------------- init(_Config) -> {ok, #context{}}. content_types_provided(ReqData, Context) -> {[{"application/json", to_json}], ReqData, Context}. to_json(ReqData, Context) -> rabbit_mgmt_util:reply(rabbit_tracing_traces:list(), ReqData, Context). is_authorized(ReqData, Context) -> rabbit_mgmt_util:is_authorized_admin(ReqData, Context). %%-------------------------------------------------------------------- rabbitmq-server-3.2.4/plugins-src/rabbitmq-tracing/src/rabbit_tracing_mgmt.erl0000644000000000000000000000225112305126066026311 0ustar rootroot%% The contents of this file are subject to the Mozilla Public License %% Version 1.1 (the "License"); you may not use this file except in %% compliance with the License. You may obtain a copy of the License %% at http://www.mozilla.org/MPL/ %% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See %% the License for the specific language governing rights and %% limitations under the License. %% %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is GoPivotal, Inc. %% Copyright (c) 2007-2013 GoPivotal, Inc. All rights reserved. %% -module(rabbit_tracing_mgmt). -behaviour(rabbit_mgmt_extension). -export([dispatcher/0, web_ui/0]). dispatcher() -> [{["traces"], rabbit_tracing_wm_traces, []}, {["traces", vhost], rabbit_tracing_wm_traces, []}, {["traces", vhost, name], rabbit_tracing_wm_trace, []}, {["trace-files"], rabbit_tracing_wm_files, []}, {["trace-files", name], rabbit_tracing_wm_file, []}]. web_ui() -> [{javascript, <<"tracing.js">>}]. rabbitmq-server-3.2.4/plugins-src/rabbitmq-tracing/src/rabbit_tracing_wm_trace.erl0000644000000000000000000000606412305126066027154 0ustar rootroot%% The contents of this file are subject to the Mozilla Public License %% Version 1.1 (the "License"); you may not use this file except in %% compliance with the License. You may obtain a copy of the License at %% http://www.mozilla.org/MPL/ %% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the %% License for the specific language governing rights and limitations %% under the License. %% %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is GoPivotal, Inc. %% Copyright (c) 2007-2013 GoPivotal, Inc. All rights reserved. -module(rabbit_tracing_wm_trace). -export([init/1, resource_exists/2, to_json/2, content_types_provided/2, content_types_accepted/2, is_authorized/2, allowed_methods/2, accept_content/2, delete_resource/2]). -define(ERR, <<"Something went wrong trying to start the trace - check the " "logs.">>). -include_lib("rabbitmq_management/include/rabbit_mgmt.hrl"). -include_lib("webmachine/include/webmachine.hrl"). %%-------------------------------------------------------------------- init(_Config) -> {ok, #context{}}. content_types_provided(ReqData, Context) -> {[{"application/json", to_json}], ReqData, Context}. content_types_accepted(ReqData, Context) -> {[{"application/json", accept_content}], ReqData, Context}. allowed_methods(ReqData, Context) -> {['HEAD', 'GET', 'PUT', 'DELETE'], ReqData, Context}. resource_exists(ReqData, Context) -> {case trace(ReqData) of not_found -> false; _ -> true end, ReqData, Context}. to_json(ReqData, Context) -> rabbit_mgmt_util:reply(trace(ReqData), ReqData, Context). accept_content(ReqData, Context) -> case rabbit_mgmt_util:vhost(ReqData) of not_found -> not_found; VHost -> Name = rabbit_mgmt_util:id(name, ReqData), rabbit_mgmt_util:with_decode( [format], ReqData, Context, fun([_], Trace) -> case rabbit_tracing_traces:create( VHost, Name, Trace) of {ok, _} -> {true, ReqData, Context}; _ -> rabbit_mgmt_util:bad_request( ?ERR, ReqData, Context) end end) end. delete_resource(ReqData, Context) -> VHost = rabbit_mgmt_util:vhost(ReqData), Name = rabbit_mgmt_util:id(name, ReqData), ok = rabbit_tracing_traces:stop(VHost, Name), {true, ReqData, Context}. is_authorized(ReqData, Context) -> rabbit_mgmt_util:is_authorized_admin(ReqData, Context). %%-------------------------------------------------------------------- trace(ReqData) -> case rabbit_mgmt_util:vhost(ReqData) of not_found -> not_found; VHost -> rabbit_tracing_traces:lookup( VHost, rabbit_mgmt_util:id(name, ReqData)) end. rabbitmq-server-3.2.4/plugins-src/rabbitmq-tracing/README0000644000000000000000000000267412305126066021711 0ustar rootrootAn opinionated tracing plugin for RabbitMQ management. Build it like any other plugin. After installation you should see a "Tracing" tab in the management UI. Hopefully use is obvious. Configuration ============= There is two configuration options: directory: This controls where the log files go. It defaults to "/var/tmp/rabbitmq-tracing". username: name of the user as which to create queues and bind to the tracing exchange. Obviously this user will need to exist and have permission to do those things. Performance =========== On my workstation, rabbitmq-tracing can write about 2000 msg/s to a log file. You should be careful using rabbitmq-tracing if you think you're going to capture more messages than this. Of course, any messages that can't be logged are queued. The code to serve up the log files over HTTP is pretty dumb, it loads the whole log into memory. If you have large log files you may wish to transfer them off the server in some other way. HTTP API ======== GET /api/traces GET /api/traces/ GET PUT DELETE /api/traces// GET /api/trace-files GET DELETE /api/trace-files/ (GET returns the file as text/plain, not JSON describing it.) Example for how to create a trace: $ curl -i -u guest:guest -H "content-type:application/json" -XPUT \ http://localhost:55672/api/traces/%2f/my-trace \ -d'{"format":"text","pattern":"#"}' rabbitmq-server-3.2.4/plugins-src/rabbitmq-tracing/test/0000755000000000000000000000000012305126066021777 5ustar rootrootrabbitmq-server-3.2.4/plugins-src/rabbitmq-tracing/test/src/0000755000000000000000000000000012305126066022566 5ustar rootrootrabbitmq-server-3.2.4/plugins-src/rabbitmq-tracing/test/src/rabbit_tracing_test.erl0000644000000000000000000001450012305126066027303 0ustar rootroot%% The contents of this file are subject to the Mozilla Public License %% Version 1.1 (the "License"); you may not use this file except in %% compliance with the License. You may obtain a copy of the License %% at http://www.mozilla.org/MPL/ %% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See %% the License for the specific language governing rights and %% limitations under the License. %% %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is GoPivotal, Inc. %% Copyright (c) 2007-2013 GoPivotal, Inc. All rights reserved. %% -module(rabbit_tracing_test). -define(LOG_DIR, "/var/tmp/rabbitmq-tracing/"). -include_lib("eunit/include/eunit.hrl"). -include_lib("amqp_client/include/amqp_client.hrl"). -include_lib("rabbitmq_management/include/rabbit_mgmt_test.hrl"). -import(rabbit_misc, [pget/2]). tracing_test() -> case filelib:is_dir(?LOG_DIR) of true -> {ok, Files} = file:list_dir(?LOG_DIR), [ok = file:delete(?LOG_DIR ++ F) || F <- Files]; _ -> ok end, [] = http_get("/traces/%2f/"), [] = http_get("/trace-files/"), Args = [{format, <<"json">>}, {pattern, <<"#">>}], http_put("/traces/%2f/test", Args, ?NO_CONTENT), assert_list([[{name, <<"test">>}, {format, <<"json">>}, {pattern, <<"#">>}]], http_get("/traces/%2f/")), assert_item([{name, <<"test">>}, {format, <<"json">>}, {pattern, <<"#">>}], http_get("/traces/%2f/test")), {ok, Conn} = amqp_connection:start(#amqp_params_network{}), {ok, Ch} = amqp_connection:open_channel(Conn), amqp_channel:cast(Ch, #'basic.publish'{ exchange = <<"amq.topic">>, routing_key = <<"key">> }, #amqp_msg{props = #'P_basic'{}, payload = <<"Hello world">>}), amqp_channel:close(Ch), amqp_connection:close(Conn), timer:sleep(100), http_delete("/traces/%2f/test", ?NO_CONTENT), [] = http_get("/traces/%2f/"), assert_list([[{name, <<"test.log">>}]], http_get("/trace-files/")), %% This is a bit cheeky as the log is actually one JSON doc per %% line and we assume here it's only one line assert_item([{type, <<"published">>}, {exchange, <<"amq.topic">>}, {routing_keys, [<<"key">>]}, {payload, base64:encode(<<"Hello world">>)}], http_get("/trace-files/test.log")), http_delete("/trace-files/test.log", ?NO_CONTENT), ok. %%--------------------------------------------------------------------------- %% Below is copypasta from rabbit_mgmt_test_http, it's not obvious how %% to share that given the build system. http_get(Path) -> http_get(Path, ?OK). http_get(Path, CodeExp) -> http_get(Path, "guest", "guest", CodeExp). http_get(Path, User, Pass, CodeExp) -> {ok, {{_HTTP, CodeAct, _}, Headers, ResBody}} = req(get, Path, [auth_header(User, Pass)]), assert_code(CodeExp, CodeAct, "GET", Path, ResBody), decode(CodeExp, Headers, ResBody). http_put(Path, List, CodeExp) -> http_put_raw(Path, format_for_upload(List), CodeExp). http_put(Path, List, User, Pass, CodeExp) -> http_put_raw(Path, format_for_upload(List), User, Pass, CodeExp). http_post(Path, List, CodeExp) -> http_post_raw(Path, format_for_upload(List), CodeExp). http_post(Path, List, User, Pass, CodeExp) -> http_post_raw(Path, format_for_upload(List), User, Pass, CodeExp). format_for_upload(List) -> iolist_to_binary(mochijson2:encode({struct, List})). http_put_raw(Path, Body, CodeExp) -> http_upload_raw(put, Path, Body, "guest", "guest", CodeExp). http_put_raw(Path, Body, User, Pass, CodeExp) -> http_upload_raw(put, Path, Body, User, Pass, CodeExp). http_post_raw(Path, Body, CodeExp) -> http_upload_raw(post, Path, Body, "guest", "guest", CodeExp). http_post_raw(Path, Body, User, Pass, CodeExp) -> http_upload_raw(post, Path, Body, User, Pass, CodeExp). http_upload_raw(Type, Path, Body, User, Pass, CodeExp) -> {ok, {{_HTTP, CodeAct, _}, Headers, ResBody}} = req(Type, Path, [auth_header(User, Pass)], Body), assert_code(CodeExp, CodeAct, Type, Path, ResBody), decode(CodeExp, Headers, ResBody). http_delete(Path, CodeExp) -> http_delete(Path, "guest", "guest", CodeExp). http_delete(Path, User, Pass, CodeExp) -> {ok, {{_HTTP, CodeAct, _}, Headers, ResBody}} = req(delete, Path, [auth_header(User, Pass)]), assert_code(CodeExp, CodeAct, "DELETE", Path, ResBody), decode(CodeExp, Headers, ResBody). assert_code(CodeExp, CodeAct, Type, Path, Body) -> case CodeExp of CodeAct -> ok; _ -> throw({expected, CodeExp, got, CodeAct, type, Type, path, Path, body, Body}) end. req(Type, Path, Headers) -> httpc:request(Type, {?PREFIX ++ Path, Headers}, ?HTTPC_OPTS, []). req(Type, Path, Headers, Body) -> httpc:request(Type, {?PREFIX ++ Path, Headers, "application/json", Body}, ?HTTPC_OPTS, []). decode(?OK, _Headers, ResBody) -> cleanup(mochijson2:decode(ResBody)); decode(_, Headers, _ResBody) -> Headers. cleanup(L) when is_list(L) -> [cleanup(I) || I <- L]; cleanup({struct, I}) -> cleanup(I); cleanup({K, V}) when is_binary(K) -> {list_to_atom(binary_to_list(K)), cleanup(V)}; cleanup(I) -> I. auth_header(Username, Password) -> {"Authorization", "Basic " ++ binary_to_list(base64:encode(Username ++ ":" ++ Password))}. %%--------------------------------------------------------------------------- assert_list(Exp, Act) -> case length(Exp) == length(Act) of true -> ok; false -> throw({expected, Exp, actual, Act}) end, [case length(lists:filter(fun(ActI) -> test_item(ExpI, ActI) end, Act)) of 1 -> ok; N -> throw({found, N, ExpI, in, Act}) end || ExpI <- Exp]. assert_item(Exp, Act) -> case test_item0(Exp, Act) of [] -> ok; Or -> throw(Or) end. test_item(Exp, Act) -> case test_item0(Exp, Act) of [] -> true; _ -> false end. test_item0(Exp, Act) -> [{did_not_find, ExpI, in, Act} || ExpI <- Exp, not lists:member(ExpI, Act)]. rabbitmq-server-3.2.4/plugins-src/rabbitmq-tracing/.srcdist_done0000644000000000000000000000000012305126066023467 0ustar rootrootrabbitmq-server-3.2.4/plugins-src/rabbitmq-tracing/Makefile0000644000000000000000000000002712305126066022457 0ustar rootrootinclude ../umbrella.mk rabbitmq-server-3.2.4/plugins-src/rabbitmq-tracing/ebin/0000755000000000000000000000000012305126066021735 5ustar rootrootrabbitmq-server-3.2.4/plugins-src/rabbitmq-tracing/package.mk0000644000000000000000000000037412305126066022750 0ustar rootrootRELEASABLE:=true DEPS:=rabbitmq-management WITH_BROKER_TEST_COMMANDS:=eunit:test(rabbit_tracing_test,[verbose]) CONSTRUCT_APP_PREREQS:=$(shell find $(PACKAGE_DIR)/priv -type f) define construct_app_commands cp -r $(PACKAGE_DIR)/priv $(APP_DIR) endef rabbitmq-server-3.2.4/plugins-src/rabbitmq-management-visualiser/0000755000000000000000000000000012305126066023671 5ustar rootrootrabbitmq-server-3.2.4/plugins-src/rabbitmq-management-visualiser/priv/0000755000000000000000000000000012305126066024651 5ustar rootrootrabbitmq-server-3.2.4/plugins-src/rabbitmq-management-visualiser/priv/www/0000755000000000000000000000000012305126066025475 5ustar rootrootrabbitmq-server-3.2.4/plugins-src/rabbitmq-management-visualiser/priv/www/js/0000755000000000000000000000000012305126066026111 5ustar rootrootrabbitmq-server-3.2.4/plugins-src/rabbitmq-management-visualiser/priv/www/js/visualiser.js0000644000000000000000000000013712305126066030636 0ustar rootrootdispatcher_add(function(sammy) {}); NAVIGATION['Visualiser'] = ['visualiser/', "management"]; rabbitmq-server-3.2.4/plugins-src/rabbitmq-management-visualiser/priv/www/visualiser/0000755000000000000000000000000012305126066027663 5ustar rootrootrabbitmq-server-3.2.4/plugins-src/rabbitmq-management-visualiser/priv/www/visualiser/index.html0000644000000000000000000001322412305126066031662 0ustar rootroot RabbitMQ Visualiser
    Vhost:
    Help

    RabbitMQ Visualiser

    Click to hide.

    The left of the canvas displays exchanges, the right displays queues, and the top displays channels. All of these items can be dragged around the canvas. They repel one another, and snap back into their predefined areas should they be released within the boundaries of those areas.

    Shift-clicking on an item hides it - it will be added to the relevant select box on the left.

    Hovering over an item shows at the top of the screen various details about the item. Double-clicking on the item will take you to the specific page in the Management Plugin concerning that item.

    When hovering over an item, incoming links and/or traffic are shown in green, whilst outgoing links and/or traffic are shown in blue. Bindings are always displayed, but the consumers of a queue, and likewise the publishers to an exchange, are only drawn in when hovering over the exchange, queue or channel in question.

    By default, up to 10 exchanges, 10 queues and 10 channels are displayed. Additional resources are available from the left hand-side select boxes, and can be brought into the display by selecting them and clicking on the relevant 'Show' button.

    The 'Display' check-boxes turn off and on entire resource classes, and resets positioning.

    Click to hide.

    rabbitmq-server-3.2.4/plugins-src/rabbitmq-management-visualiser/priv/www/visualiser/js/0000755000000000000000000000000012305126066030277 5ustar rootrootrabbitmq-server-3.2.4/plugins-src/rabbitmq-management-visualiser/priv/www/visualiser/js/model.js0000644000000000000000000010666512305126066031753 0ustar rootroot/*global octtree, vec3, Spring */ function searchX(elem, tree, xIncr, xMax) { var found = tree.findInRadius(elem.pos, xIncr / 2, 1); while (found.length > 0 && elem.pos[octtree.x] + xIncr < xMax) { elem.pos[octtree.x] += xIncr; found = tree.findInRadius(elem.pos, xIncr / 2, 1); } return (found.length === 0); } function searchY(elem, tree, yIncr) { var found = tree.findInRadius(elem.pos, yIncr / 2, 1); while (found.length > 0) { elem.pos[octtree.y] += yIncr; found = tree.findInRadius(elem.pos, yIncr / 2, 1); } } function bezierMid(startX, startY, ctl1X, ctl1Y, ctl2X, ctl2Y, endX, endY) { var start_ctl1X, start_ctl1Y, end_ctl2X, end_ctl2Y, ctl1_ctl2X, ctl1_ctl2Y, mid1X, mid1Y, mid2X, mid2Y; start_ctl1X = (startX + ctl1X) / 2; start_ctl1Y = (startY + ctl1Y) / 2; end_ctl2X = (endX + ctl2X) / 2; end_ctl2Y = (endY + ctl2Y) / 2; ctl1_ctl2X = (ctl1X + ctl2X) / 2; ctl1_ctl2Y = (ctl1Y + ctl2Y) / 2; mid1X = (start_ctl1X + ctl1_ctl2X) / 2; mid1Y = (start_ctl1Y + ctl1_ctl2Y) / 2; mid2X = (end_ctl2X + ctl1_ctl2X) / 2; mid2Y = (end_ctl2Y + ctl1_ctl2Y) / 2; return [(mid1X + mid2X) / 2, (mid1Y + mid2Y) / 2]; } function stringifyObject(a) { var b, e; b = {}; for (e in a) { if (a.hasOwnProperty(e)) { if ("object" === typeof a[e]) { b[e] = stringifyObject(a[e]); } else { b[e] = "" + a[e]; } } } return b; } String.prototype.toTitleCase = function () { return this.replace(/(^|_)([a-z])/g, function (str, g1, g2, offset, totalStr) { return g1.replace("_", " ") + g2.toUpperCase(); }); }; var Consumer = {}; Consumer.render = function (channel, queue, ctx, consumerTag) { var yMid, xCtl, dim, mid; ctx.beginPath(); yMid = (channel.yMax + queue.pos[octtree.y]) / 2; xCtl = queue.pos[octtree.x]; ctx.moveTo(channel.pos[octtree.x], channel.yMax); ctx.bezierCurveTo(channel.pos[octtree.x], yMid, xCtl, queue.pos[octtree.y] - channel.yInit, xCtl, queue.pos[octtree.y] - queue.fontSize); ctx.moveTo(channel.pos[octtree.x], channel.yMax); ctx.closePath(); ctx.stroke(); dim = ctx.measureText(consumerTag); mid = bezierMid(channel.pos[octtree.x], channel.yMax, channel.pos[octtree.x], yMid, xCtl, queue.pos[octtree.y] - channel.yInit, xCtl, queue.pos[octtree.y] - queue.fontSize); ctx.textBaseline = "middle"; ctx.textAlign = "center"; ctx.fillStyle = "rgba(255, 255, 255, 0.67)"; ctx.fillRect(mid[0] - (dim.width / 2), mid[1] - (channel.fontSize / 2), dim.width, channel.fontSize); ctx.fillStyle = ctx.strokeStyle; ctx.fillText(consumerTag, mid[0], mid[1]); ctx.beginPath(); ctx.moveTo(channel.pos[octtree.x], channel.yMax); ctx.lineTo(channel.pos[octtree.x] - (channel.fontSize / 2), channel.yMax + channel.fontSize); ctx.lineTo(channel.pos[octtree.x] + (channel.fontSize / 2), channel.yMax + channel.fontSize); ctx.closePath(); ctx.fillStyle = ctx.strokeStyle; ctx.fill(); }; var Publisher = {}; Publisher.render = function (channel, exchange, ctx) { var yMid, xCtl; ctx.beginPath(); yMid = (channel.yMax + exchange.pos[octtree.y]) / 2; xCtl = exchange.pos[octtree.x]; ctx.moveTo(channel.pos[octtree.x], channel.yMax); ctx.bezierCurveTo(channel.pos[octtree.x], yMid, xCtl, exchange.pos[octtree.y] - channel.yInit, xCtl, exchange.pos[octtree.y] - exchange.fontSize); ctx.moveTo(channel.pos[octtree.x], channel.yMax); ctx.closePath(); ctx.stroke(); ctx.beginPath(); ctx.moveTo(exchange.pos[octtree.x], exchange.pos[octtree.y] - exchange.fontSize); ctx.lineTo(exchange.pos[octtree.x] - exchange.fontSize / 2, exchange.pos[octtree.y] - 2 * exchange.fontSize); ctx.lineTo(exchange.pos[octtree.x] + exchange.fontSize / 2, exchange.pos[octtree.y] - 2 * exchange.fontSize); ctx.closePath(); ctx.fillStyle = ctx.strokeStyle; ctx.fill(); }; function Channel(tree, elem, model) { this.name = elem.name; this.pos = vec3.create(); this.findNewPosition(model, tree); this.next_pos = vec3.create(this.pos); this.mass = 0.1; this.velocity = vec3.create(); this.ideal = { pos : vec3.create() }; this.disabled = false; this.update(elem); tree.add(this); } Channel.prototype = { yInit : 100, yIncr : 50, xInit : 100, xIncr : 50, xMax : 200, yBoundary : 200, attributes : [ 'acks_uncommitted', 'client_flow_blocked', 'confirm', 'connection_details', 'consumer_count', 'message_stats', 'messages_unacknowledged', 'messages_unconfirmed', 'node', 'number', 'prefetch_count', 'transactional', 'user', 'vhost' ], pos : vec3.create(), fontSize : 12, spring : new Spring(), details : undefined, object_type : 'channel', detail_attributes : [ 'name', 'user', 'transactional', 'confirm', 'node', 'vhost', 'prefetch_count', 'messages_unacknowledged', 'messages_unconfirmed', 'consumer_count', 'client_flow_blocked' ] }; Channel.prototype.spring.octtreeLimit = 10; Channel.prototype.spring.octtreeRadius = 500; Channel.prototype.spring.equilibriumLength = 0; Channel.prototype.spring.dampingFactor = 0.1; Channel.prototype.spring.pull = true; Channel.prototype.spring.push = false; Channel.prototype.findNewPosition = function (model, tree) { this.pos[octtree.x] = this.xInit; this.pos[octtree.y] = this.yInit; this.pos[octtree.z] = 0; while (! searchX(this, tree, this.xIncr, this.xMax)) { this.pos[octtree.y] += this.yIncr; this.pos[octtree.x] = this.xInit + (this.pos[octtree.y] / 10); } this.yMin = this.pos[octtree.y]; this.yMax = this.pos[octtree.y]; }; Channel.prototype.canvasResized = function (canvas) { Channel.prototype.xMax = canvas.width; }; Channel.prototype.update = function (elem) { var attr, i; for (i = 0; i < this.attributes.length; i += 1) { attr = this.attributes[i]; this[attr] = elem[attr]; } }; Channel.prototype.remove = function (tree, model) { tree.del(this); }; Channel.prototype.render = function (model, ctx) { var i, dim, consumer, queue, publisher, exchange; if (this.disabled) { return; } dim = ctx.measureText(this.name); if (model.cull(this.pos[octtree.x] - this.fontSize, this.pos[octtree.y] - (dim.width / 2) - this.fontSize, this.fontSize * 2, dim.width + (this.fontSize * 2))) { return; } this.yMax = this.pos[octtree.y] + (dim.width / 2) + this.fontSize; this.yMin = this.pos[octtree.y] - (dim.width / 2) - this.fontSize; ctx.beginPath(); ctx.textAlign = "center"; ctx.textBaseline = "middle"; ctx.lineWidth = 2.0; ctx.strokeStyle = "black"; ctx.moveTo(this.pos[octtree.x] - this.fontSize, this.yMin); ctx.lineTo(this.pos[octtree.x] + this.fontSize, this.yMin); ctx.lineTo(this.pos[octtree.x] + this.fontSize, this.yMax); ctx.lineTo(this.pos[octtree.x] - this.fontSize, this.yMax); ctx.closePath(); this.preStroke(model, ctx); ctx.save(); ctx.translate(this.pos[octtree.x], this.pos[octtree.y]); ctx.rotate(3 * Math.PI / 2); ctx.fillStyle = ctx.strokeStyle; ctx.fillText(this.name, 0, 0); ctx.restore(); if (undefined !== this.details) { model.resetHighlighted(); ctx.lineWidth = 2.0; if (undefined !== this.details.consumer_details) { ctx.strokeStyle = "#00a000"; for (i = 0; i < this.details.consumer_details.length; i += 1) { consumer = this.details.consumer_details[i]; queue = consumer.queue_details.name; if (undefined !== model.queue[queue] && ! model.queue[queue].disabled) { model.setHighlighted(model.queue[queue]); Consumer.render(this, model.queue[queue], ctx, consumer.consumer_tag); } } } if (undefined !== this.details.publishes) { ctx.strokeStyle = "#0000a0"; for (i = 0; i < this.details.publishes.length; i += 1) { publisher = this.details.publishes[i]; exchange = publisher.exchange.name; if (undefined !== model.exchange[exchange] && ! model.exchange[exchange].disabled) { model.setHighlighted(model.exchange[exchange]); Publisher.render(this, model.exchange[exchange], ctx); } } } } }; Channel.prototype.preStroke = function (model, ctx) { }; Channel.prototype.animate = function (elapsed) { if (this.yBoundary > this.pos[octtree.y]) { this.ideal.pos[octtree.x] = this.pos[octtree.x]; this.ideal.pos[octtree.y] = this.yInit; this.spring.apply(elapsed, this, this.ideal); } }; Channel.prototype.disable = function (model) { model.channels_visible -= 1; }; Channel.prototype.enable = function (model, tree) { model.channels_visible += 1; this.findNewPosition(model, tree); }; Channel.prototype.getDetails = function () { }; Channel.prototype.stringAttributes = function () { var obj, i, attName, attNameTitle; obj = { Channel : '', attributeOrder : ['Channel'] }; for (i in this.detail_attributes) { attName = this.detail_attributes[i]; attNameTitle = attName.toTitleCase(); obj.attributeOrder.push(attNameTitle); if ("object" === typeof this[attName]) { obj[attNameTitle] = stringifyObject(this[attName]); } else { obj[attNameTitle] = "" + this[attName]; } } if (undefined !== this.message_stats) { if (undefined !== this.message_stats.publish_details) { obj.attributeOrder.push('Publish Rate (msgs/sec)'); obj['Publish Rate (msgs/sec)'] = "" + Math.round(this.message_stats.publish_details.rate); } if (undefined !== this.message_stats.deliver_get_details) { obj.attributeOrder.push('Delivery and Get Rate (msgs/sec)'); obj['Delivery and Get Rate (msgs/sec)'] = "" + Math.round(this.message_stats.deliver_get_details.rate); } if (undefined !== this.message_stats.ack_details) { obj.attributeOrder.push('Delivery Acknowledgement Rate (acks/sec)'); obj['Delivery Acknowledgement Rate (acks/sec)'] = "" + Math.round(this.message_stats.ack_details.rate); } } return obj; }; Channel.prototype.url = function () { return "/channels/" + encodeURIComponent(this.name); }; Channel.prototype.navigateTo = function () { document.location = "../#" + this.url(); }; function Exchange(tree, elem, model) { this.name = elem.name; this.pos = vec3.create(); this.findNewPosition(model, tree); this.next_pos = vec3.create(this.pos); this.mass = 0.1; this.velocity = vec3.create(); this.ideal = { pos : vec3.create() }; this.disabled = false; this.bindings_outbound = { exchange : {}, queue : {} }; this.bindings_inbound = {}; this.update(elem); tree.add(this); } Exchange.prototype = { yInit : 250, yIncr : 50, xInit : 100, xBoundary : 200, attributes : [ 'arguments', 'auto_delete', 'durable', 'internal', 'type', 'message_stats_out', 'message_stats_in', 'vhost' ], pos : vec3.create(), fontSize : 12, spring : new Spring(), details : undefined, object_type : 'exchange', detail_attributes : [ 'name', 'type', 'durable', 'auto_delete', 'internal', 'arguments', 'vhost' ] }; Exchange.prototype.spring.octtreeLimit = 10; Exchange.prototype.spring.octtreeRadius = 500; Exchange.prototype.spring.equilibriumLength = 0; Exchange.prototype.spring.dampingFactor = 0.1; Exchange.prototype.spring.pull = true; Exchange.prototype.spring.push = false; Exchange.prototype.findNewPosition = function (model, tree) { this.pos[octtree.x] = this.xInit; this.pos[octtree.y] = this.yInit; this.pos[octtree.z] = 0; searchY(this, tree, this.yIncr); this.xMin = this.pos[octtree.x]; this.xMax = this.pos[octtree.x]; }; Exchange.prototype.canvasResized = function (canvas) { Exchange.prototype.xInit = canvas.width / 6; Exchange.prototype.xBoundary = 2 * canvas.width / 6; }; Exchange.prototype.update = function (elem) { var attr, i; for (i = 0; i < this.attributes.length; i += 1) { attr = this.attributes[i]; this[attr] = elem[attr]; } }; Exchange.prototype.remove = function (tree, model) { tree.del(this); }; Exchange.prototype.render = function (model, ctx) { var i, dim, channel; if (this.disabled) { return; } for (i in this.bindings_outbound.exchange) { this.bindings_outbound.exchange[i].render(model, ctx); } if (model.rendering.queue.enabled) { for (i in this.bindings_outbound.queue) { this.bindings_outbound.queue[i].render(model, ctx); } } dim = ctx.measureText(this.name); if (model.cull(this.pos[octtree.x] - (dim.width / 2) - this.fontSize, this.pos[octtree.y] - this.fontSize, dim.width + (2 * this.fontSize), 2 * this.fontSize)) { return; } ctx.beginPath(); ctx.textAlign = "center"; ctx.textBaseline = "middle"; ctx.lineWidth = 2.0; ctx.strokeStyle = "black"; ctx.arc(this.pos[octtree.x] - (dim.width / 2), this.pos[octtree.y], this.fontSize, Math.PI / 2, 3 * Math.PI / 2, false); ctx.lineTo(this.pos[octtree.x] + (dim.width / 2), this.pos[octtree.y] - this.fontSize); ctx.arc(this.pos[octtree.x] + (dim.width / 2), this.pos[octtree.y], this.fontSize, 3 * Math.PI / 2, Math.PI / 2, false); ctx.closePath(); this.preStroke(model, ctx); ctx.fillStyle = ctx.strokeStyle; ctx.fillText(this.name, this.pos[octtree.x], this.pos[octtree.y]); this.xMin = this.pos[octtree.x] - (dim.width / 2) - this.fontSize; this.xMax = this.pos[octtree.x] + (dim.width / 2) + this.fontSize; if (undefined !== this.details) { model.resetHighlighted(); ctx.lineWidth = 2.0; ctx.strokeStyle = "#00a000"; if (undefined !== this.details.incoming) { for (i = 0; i < this.details.incoming.length; i += 1) { channel = this.details.incoming[i].channel_details.name; if (undefined !== model.channel[channel] && ! model.channel[channel].disabled) { model.setHighlighted(model.channel[channel]); Publisher.render(model.channel[channel], this, ctx); } } } for (i in this.bindings_outbound.queue) { model.setHighlighted(model.queue[this.bindings_outbound.queue[i].destination]); } for (i in this.bindings_outbound.exchange) { model.setHighlighted(model.exchange[this.bindings_outbound.exchange[i].destination]); } for (i in this.bindings_inbound) { model.setHighlighted(model.exchange[this.bindings_inbound[i].source]); } } }; Exchange.prototype.preStroke = function (model, ctx) { }; Exchange.prototype.animate = function (elapsed) { if (this.xBoundary > this.pos[octtree.x]) { this.ideal.pos[octtree.x] = this.xInit; this.ideal.pos[octtree.y] = this.pos[octtree.y]; this.spring.apply(elapsed, this, this.ideal); } }; Exchange.prototype.disable = function (model) { model.exchanges_visible -= 1; }; Exchange.prototype.enable = function (model, tree) { model.exchanges_visible += 1; this.findNewPosition(model, tree); }; Exchange.prototype.getDetails = function () { }; Exchange.prototype.stringAttributes = function () { var obj, i, attName, attNameTitle; obj = { Exchange : '', attributeOrder : ['Exchange'] }; for (i in this.detail_attributes) { attName = this.detail_attributes[i]; attNameTitle = attName.toTitleCase(); obj.attributeOrder.push(attNameTitle); if ("object" === typeof this[attName]) { obj[attNameTitle] = stringifyObject(this[attName]); } else { obj[attNameTitle] = "" + this[attName]; } } obj.attributeOrder.push('Outgoing Queue Bindings'); obj['Outgoing Queue Bindings'] = "" + Object.keys(this.bindings_outbound.queue).length; obj.attributeOrder.push('Outgoing Exchange Bindings'); obj['Outgoing Exchange Bindings'] = "" + Object.keys(this.bindings_outbound.exchange).length; obj.attributeOrder.push('Incoming Exchange Bindings'); obj['Incoming Exchange Bindings'] = "" + Object.keys(this.bindings_inbound).length; if (undefined !== this.message_stats_in && undefined !== this.message_stats_in.publish_details) { obj.attributeOrder.push('Message Incoming Rate (msgs/sec)'); obj['Message Incoming Rate (msgs/sec)'] = "" + Math.round(this.message_stats_in.publish_details.rate); } if (undefined !== this.message_stats_out && undefined !== this.message_stats_out.publish_details) { obj.attributeOrder.push('Message Outgoing Rate (msgs/sec)'); obj['Message Outgoing Rate (msgs/sec)'] = "" + Math.round(this.message_stats_out.publish_details.rate); } return obj; }; Exchange.prototype.url = function () { var name; if (this.name === "") { name = "amq.default"; } else { name = this.name; } return "/exchanges/" + encodeURIComponent(this.vhost) + "/" + encodeURIComponent(name); }; Exchange.prototype.navigateTo = function () { document.location = "../#" + this.url(); }; function Queue(tree, elem, model) { this.name = elem.name; this.pos = vec3.create(); this.findNewPosition(model, tree); this.next_pos = vec3.create(this.pos); this.mass = 0.1; this.velocity = vec3.create(); this.ideal = { pos : vec3.create() }; this.disabled = false; this.bindings_inbound = {}; this.update(elem); tree.add(this); } Queue.prototype = { yInit : 250, yIncr : 50, xInit : 400, xBoundary : 300, attributes : [ 'arguments', 'auto_delete', 'durable', 'messages', 'messages_ready', 'messages_unacknowledged', 'message_stats', 'node', 'owner_pid_details', 'vhost', 'memory', 'consumers' ], pos : vec3.create(), fontSize : 12, spring : new Spring(), details : undefined, object_type : 'queue', detail_attributes : [ 'name', 'durable', 'auto_delete', 'arguments', 'node', 'vhost', 'messages_ready', 'messages_unacknowledged', 'consumers', 'memory' ] }; Queue.prototype.spring.octtreeLimit = 10; Queue.prototype.spring.octtreeRadius = 500; Queue.prototype.spring.equilibriumLength = 0; Queue.prototype.spring.dampingFactor = 0.1; Queue.prototype.spring.pull = true; Queue.prototype.spring.push = false; Queue.prototype.findNewPosition = function (model, tree) { this.pos[octtree.x] = this.xInit; this.pos[octtree.y] = this.yInit; this.pos[octtree.z] = 0; searchY(this, tree, this.yIncr); this.xMin = this.pos[octtree.x]; this.xMax = this.pos[octtree.x]; }; Queue.prototype.canvasResized = function (canvas) { Queue.prototype.xInit = 5 * canvas.width / 6; Queue.prototype.xBoundary = 4 * canvas.width / 6; }; Queue.prototype.update = function (elem) { var attr, i; for (i = 0; i < this.attributes.length; i += 1) { attr = this.attributes[i]; this[attr] = elem[attr]; } }; Queue.prototype.remove = function (tree, model) { tree.del(this); }; Queue.prototype.render = function (model, ctx) { var text, dim, i, channel; if (this.disabled) { return; } text = this.name + " (" + this.messages_ready + ", " + this.messages_unacknowledged + ")"; dim = ctx.measureText(text); if (model.cull(this.pos[octtree.x] - (dim.width / 2) - this.fontSize, this.pos[octtree.y] - this.fontSize, dim.width + (2 * this.fontSize), 2 * this.fontSize)) { return; } ctx.beginPath(); ctx.textAlign = "center"; ctx.textBaseline = "middle"; ctx.lineWidth = 2.0; ctx.strokeStyle = "black"; ctx.moveTo(this.pos[octtree.x] - (dim.width / 2) - this.fontSize, this.pos[octtree.y] - this.fontSize); ctx.lineTo(this.pos[octtree.x] + (dim.width / 2) + this.fontSize, this.pos[octtree.y] - this.fontSize); ctx.lineTo(this.pos[octtree.x] + (dim.width / 2) + this.fontSize, this.pos[octtree.y] + this.fontSize); ctx.lineTo(this.pos[octtree.x] - (dim.width / 2) - this.fontSize, this.pos[octtree.y] + this.fontSize); ctx.closePath(); this.preStroke(model, ctx); ctx.fillStyle = ctx.strokeStyle; ctx.fillText(text, this.pos[octtree.x], this.pos[octtree.y]); this.xMin = this.pos[octtree.x] - (dim.width / 2) - this.fontSize; this.xMax = this.pos[octtree.x] + (dim.width / 2) + this.fontSize; if (undefined !== this.details && undefined !== this.details.consumer_details) { model.resetHighlighted(); ctx.lineWidth = 2.0; ctx.strokeStyle = "#0000a0"; for (i = 0; i < this.details.consumer_details.length; i += 1) { channel = this.details.consumer_details[i].channel_details.name; if (undefined !== model.channel[channel] && ! model.channel[channel].disabled) { model.setHighlighted(model.channel[channel]); Consumer.render(model.channel[channel], this, ctx, this.details.consumer_details[i].consumer_tag); } } for (i in this.bindings_inbound) { model.setHighlighted(model.exchange[this.bindings_inbound[i].source]); } } }; Queue.prototype.preStroke = function (model, ctx) { }; Queue.prototype.animate = function (elapsed) { if (this.xBoundary < this.pos[octtree.x]) { this.ideal.pos[octtree.x] = this.xInit; this.ideal.pos[octtree.y] = this.pos[octtree.y]; this.spring.apply(elapsed, this, this.ideal); } }; Queue.prototype.disable = function (model) { model.queues_visible -= 1; }; Queue.prototype.enable = function (model, tree) { model.queues_visible += 1; this.findNewPosition(model, tree); }; Queue.prototype.getDetails = function () { }; Queue.prototype.stringAttributes = function () { var obj, i, attName, attNameTitle; obj = { Queue : '', attributeOrder : ['Queue'] }; for (i in this.detail_attributes) { attName = this.detail_attributes[i]; attNameTitle = attName.toTitleCase(); obj.attributeOrder.push(attNameTitle); if ("object" === typeof this[attName]) { obj[attNameTitle] = stringifyObject(this[attName]); } else { obj[attNameTitle] = "" + this[attName]; } } obj.attributeOrder.push('Incoming Exchange Bindings'); obj['Incoming Exchange Bindings'] = "" + Object.keys(this.bindings_inbound).length; if (undefined !== this.message_stats) { if (undefined !== this.message_stats.publish_details) { obj.attributeOrder.push('Message Incoming Rate (msgs/sec)'); obj['Message Incoming Rate (msgs/sec)'] = "" + Math.round(this.message_stats.publish_details.rate); } if (undefined !== this.message_stats.deliver_get_details) { obj.attributeOrder.push('Delivery and Get Rate (msgs/sec)'); obj['Delivery and Get Rate (msgs/sec)'] = "" + Math.round(this.message_stats.deliver_get_details.rate); } if (undefined !== this.message_stats.ack_details) { obj.attributeOrder.push('Delivery Acknowledgement Rate (acks/sec)'); obj['Delivery Acknowledgement Rate (acks/sec)'] = "" + Math.round(this.message_stats.ack_details.rate); } } return obj; }; Queue.prototype.url = function () { return "/queues/" + encodeURIComponent(this.vhost) + "/" + encodeURIComponent(this.name); }; Queue.prototype.navigateTo = function () { document.location = "../#" + this.url(); }; function Binding(elems) { this.keys = {}; this.set(elems); var elem = elems.shift(); this.source = elem.source; this.destination_type = elem.destination_type; this.destination = elem.destination; } Binding.prototype = { attributes : [ 'arguments' ], offset : 150, fontSize : 12, loopOffset : 50, object_type : 'binding' }; Binding.prototype.set = function (elems) { var i, elem, attr, j; this.keys = {}; for (i = 0; i < elems.length; i += 1) { elem = elems[i]; this.keys[elem.routing_key] = {}; for (j = 0; j < this.attributes.length; j += 1) { attr = this.attributes[j]; this.keys[elem.routing_key][attr] = elem[attr]; } } }; Binding.prototype.render = function (model, ctx) { var source, destination, xMid, xCtl1, xCtl2, yCtl1, yCtl2, xMin, yMin, xMax, yMax; source = model.exchange[this.source]; if (this.destination_type === "exchange") { destination = model.exchange[this.destination]; } else { destination = model.queue[this.destination]; } if (undefined === source || undefined === destination) { return; } if (source.disabled || destination.disabled) { return; } xMid = (source.xMax + destination.xMin) / 2; xCtl1 = xMid > (source.xMax + this.offset) ? xMid : source.xMax + this.offset; xCtl2 = xMid < (destination.xMin - this.offset) ? xMid : destination.xMin - this.offset; yCtl1 = destination === source ? source.pos[octtree.y] - this.loopOffset : source.pos[octtree.y]; yCtl2 = destination === source ? destination.pos[octtree.y] - this.loopOffset : destination.pos[octtree.y]; xMin = Math.min(source.xMax, xCtl2); yMin = Math.min(yCtl1, yCtl2); xMax = Math.max(destination.xMin, xCtl1); yMax = Math.max(source.pos[octtree.y], destination.pos[octtree.y]); if (model.cull(xMin, yMin, xMax - xMin, yMax - yMin)) { return; } ctx.beginPath(); ctx.lineWidth = 1.0; ctx.strokeStyle = "black"; ctx.moveTo(source.xMax, source.pos[octtree.y]); ctx.bezierCurveTo(xCtl1, yCtl1, xCtl2, yCtl2, destination.xMin, destination.pos[octtree.y]); ctx.moveTo(destination.xMin, destination.pos[octtree.y] + 1); ctx.bezierCurveTo(xCtl2, yCtl2 + 1, xCtl1, yCtl1 + 1, source.xMax, source.pos[octtree.y] + 1); ctx.moveTo(source.xMax, source.pos[octtree.y]); this.preStroke(source, destination, model, ctx); // draw an arrow head ctx.beginPath(); ctx.moveTo(destination.xMin, destination.pos[octtree.y]); ctx.lineTo(destination.xMin - this.fontSize, destination.pos[octtree.y] + (this.fontSize / 2)); ctx.lineTo(destination.xMin - this.fontSize, destination.pos[octtree.y] - (this.fontSize / 2)); ctx.closePath(); ctx.fillStyle = ctx.strokeStyle; ctx.fill(); }; Binding.prototype.preStroke = function (source, destination, model, ctx) { }; function Model() { this.exchange = {}; this.exchanges_visible = 0; this.queue = {}; this.queues_visible = 0; this.channel = {}; this.channels_visible = 0; this.connection = {}; this.vhost = {}; this.rendering = { exchange : { enabled : true, on_enable : {} }, queue : { enabled : true, on_enable : {} }, channel : { enabled : true, on_enable : {} }, connection : { enabled : true, on_enable : {} } }; this.highlighted = { exchange : {}, queue : {}, channel : {}, connection : {} }; } Model.prototype.permitted_exchanges_visible = 10; Model.prototype.permitted_queues_visible = 10; Model.prototype.permitted_channels_visible = 10; Model.prototype.rebuild = function (tree, configuration) { var elem, matched, i, binding, bindings, source, src, destination_type, j, src1, destination, dest, dest_type; // Channels matched = {}; for (i = 0; i < configuration.channels.length; i += 1) { elem = configuration.channels[i]; if (undefined === this.channel[elem.name]) { this.channel[elem.name] = new Channel(tree, elem, this); this.channels_visible += 1; if ((this.channels_visible > this.permitted_channels_visible) || ! this.rendering.channel.enabled) { this.disable(this.channel[elem.name], tree); } } else { this.channel[elem.name].update(elem); } matched[elem.name] = true; } for (i in this.channel) { if (undefined === matched[i]) { elem = this.channel[i]; delete this.channel[i]; elem.remove(tree, this); if (! elem.disabled) { this.channels_visible -= 1; } } } // Exchanges matched = {}; for (i = 0; i < configuration.exchanges.length; i += 1) { elem = configuration.exchanges[i]; if (undefined === this.exchange[elem.name]) { this.exchange[elem.name] = new Exchange(tree, elem, this); this.exchanges_visible += 1; if (elem.name.slice(0, 4) === "amq." || (this.exchanges_visible > this.permitted_exchanges_visible) || ! this.rendering.exchange.enabled) { this.disable(this.exchange[elem.name], tree); } } else { this.exchange[elem.name].update(elem); } matched[elem.name] = true; } for (i in this.exchange) { if (undefined === matched[i]) { elem = this.exchange[i]; delete this.exchange[i]; elem.remove(tree, this); if (! elem.disabled) { this.exchanges_visible -= 1; } } } // Queues matched = {}; for (i = 0; i < configuration.queues.length; i += 1) { elem = configuration.queues[i]; if (undefined === this.queue[elem.name]) { this.queue[elem.name] = new Queue(tree, elem, this); this.queues_visible += 1; if ((this.queues_visible > this.permitted_queues_visible) || ! this.rendering.queue.enabled) { this.disable(this.queue[elem.name], tree); delete this.rendering.queue.on_enable[elem.name]; } } else { this.queue[elem.name].update(elem); } matched[elem.name] = true; } for (i in this.queue) { if (undefined === matched[i]) { elem = this.queue[i]; delete this.queue[i]; elem.remove(tree, this); if (! elem.disabled) { this.queues_visible -= 1; } } } // Bindings bindings = {}; for (i = 0; i < configuration.bindings.length; i += 1) { elem = configuration.bindings[i]; if (undefined === this.exchange[elem.source] || undefined === this[elem.destination_type][elem.destination]) { continue; } if (undefined === bindings[elem.source]) { bindings[elem.source] = { exchange : {}, queue : {} }; } source = bindings[elem.source]; if (undefined === source[elem.destination_type][elem.destination]) { source[elem.destination_type][elem.destination] = new Array(elem); } else { source[elem.destination_type][elem.destination].push(elem); } } for (source in bindings) { src = this.exchange[source].bindings_outbound; i = bindings[source]; for (destination_type in i) { j = i[destination_type]; src1 = src[destination_type]; for (destination in j) { dest = this[destination_type][destination].bindings_inbound; if (undefined === src1[destination]) { src1[destination] = new Binding(j[destination]); } else { src1[destination].set(j[destination]); } binding = src1[destination]; if (undefined === dest[source]) { dest[source] = binding; } } } } for (src in this.exchange) { for (dest_type in this.exchange[src].bindings_outbound) { for (dest in this.exchange[src].bindings_outbound[dest_type]) { binding = this.exchange[src].bindings_outbound[dest_type][dest]; if (undefined === bindings[binding.source] || undefined === bindings[binding.source][binding.destination_type] || undefined === bindings[binding.source][binding.destination_type][binding.destination]) { delete this.exchange[src].bindings_outbound[dest_type][dest]; if (undefined !== this[binding.destination_type][binding.destination]) { delete this[binding.destination_type][binding.destination].bindings_inbound[binding.source]; } } } } } bindings = undefined; // vhosts matched = {}; for (i = 0; i < configuration.vhosts.length; i += 1) { elem = configuration.vhosts[i]; if (undefined === this.vhost[elem.name]) { this.vhost[elem.name] = elem; this.vhost_add(elem); } matched[elem.name] = true; } for (i in this.vhost) { if (undefined === matched[i]) { this.vhost_remove(this.vhost[i]); delete this.vhost[i]; } } matched = undefined; }; Model.prototype.disable = function (elem, tree) { elem.disable(this); tree.del(elem); elem.disabled = true; elem.details = undefined; }; Model.prototype.enable = function (elem, tree) { elem.enable(this, tree); tree.add(elem); elem.disabled = false; elem.details = undefined; }; Model.prototype.render = function (ctx) { var i; if (this.rendering.exchange.enabled) { for (i in this.exchange) { this.exchange[i].render(this, ctx); } } if (this.rendering.queue.enabled) { for (i in this.queue) { this.queue[i].render(this, ctx); } } if (this.rendering.channel.enabled) { for (i in this.channel) { this.channel[i].render(this, ctx); } } }; Model.prototype.cull = function (xMin, yMin, width, height) { return false; }; Model.prototype.vhost_add = function (elem) { }; Model.prototype.vhost_del = function (elem) { }; Model.prototype.resetHighlighted = function () { this.highlighted = { exchange : {}, queue : {}, channel : {}, connection : {} }; }; Model.prototype.setHighlighted = function (elem) { if (undefined !== elem) { this.highlighted[elem.object_type][elem.name] = elem; } }; Model.prototype.isHighlighted = function (elem) { return ((undefined !== elem) && (undefined !== this.highlighted[elem.object_type][elem.name])); }; rabbitmq-server-3.2.4/plugins-src/rabbitmq-management-visualiser/priv/www/visualiser/js/octtree.js0000644000000000000000000003276012305126066032312 0ustar rootroot/*global vec3 */ var octtree = {}; octtree.top_nw = 0; octtree.top_ne = 1; octtree.top_se = 2; octtree.top_sw = 3; octtree.bot_nw = 4; octtree.bot_ne = 5; octtree.bot_se = 6; octtree.bot_sw = 7; octtree.children = [ octtree.top_nw, octtree.top_ne, octtree.top_se, octtree.top_sw, octtree.bot_nw, octtree.bot_ne, octtree.bot_se, octtree.bot_sw ]; octtree.firstChildId = 0; octtree.lastChildId = 7; octtree.x = 0; octtree.y = 1; octtree.z = 2; octtree.randoms = []; octtree.randomIndex = 0; octtree.i = 0; for (octtree.i = 0; octtree.i < 100; octtree.i += 1) { octtree.randoms.push(Math.random()); } function Octtree(xMin, xMax, yMin, yMax, zMin, zMax, parent, childId) { this.xMin = xMin; this.xMax = xMax; this.yMin = yMin; this.yMax = yMax; this.zMin = zMin; this.zMax = zMax; this.parent = parent; this.childId = childId; if (undefined !== childId && childId !== octtree.lastChildId && undefined !== parent) { this.nextSiblingId = childId + 1; } this.xMid = xMin + (xMax - xMin) / 2; this.yMid = yMin + (yMax - yMin) / 2; this.zMid = zMin + (zMax - zMin) / 2; } Octtree.prototype.isEmpty = function () { return (undefined === this[octtree.firstChildId]) && (undefined === this.value); }; Octtree.prototype.hasChildren = function () { return undefined !== this[octtree.firstChildId]; }; Octtree.prototype.hasValue = function () { return undefined !== this.value; }; Octtree.prototype.add = function (value) { return octtree.add(this, value); }; Octtree.prototype.del = function (value) { return octtree.del(this, value); }; Octtree.prototype.update = function () { return octtree.update(this); }; Octtree.prototype.findInRadius = function (pos, radius, limit) { return octtree.findInRadius(this, pos, radius, limit); }; Octtree.prototype.size = function () { return octtree.size(this); }; octtree.findNode = function (tree, pos) { while (true) { if (pos[octtree.x] < tree.xMin || tree.xMax <= pos[octtree.x] || pos[octtree.y] < tree.yMin || tree.yMax <= pos[octtree.y] || pos[octtree.z] < tree.zMin || tree.zMax <= pos[octtree.z]) { if (undefined === tree.parent) { return undefined; } else { tree = tree.parent; continue; } } if (tree.hasChildren()) { if (pos[octtree.x] < tree.xMid) { if (pos[octtree.y] < tree.yMid) { if (pos[octtree.z] < tree.zMid) { tree = tree[octtree.bot_sw]; } else { tree = tree[octtree.bot_nw]; } } else { if (pos[octtree.z] < tree.zMid) { tree = tree[octtree.top_sw]; } else { tree = tree[octtree.top_nw]; } } } else { if (pos[octtree.y] < tree.yMid) { if (pos[octtree.z] < tree.zMid) { tree = tree[octtree.bot_se]; } else { tree = tree[octtree.bot_ne]; } } else { if (pos[octtree.z] < tree.zMid) { tree = tree[octtree.top_se]; } else { tree = tree[octtree.top_ne]; } } } } else { return tree; } } }; octtree.add = function (tree, value) { tree = octtree.findNode(tree, value.pos); if (undefined === tree) { return undefined; } else { var displaced; while (undefined !== value) { if (tree.hasValue()) { if (tree.value.pos[octtree.x] === value.pos[octtree.x] && tree.value.pos[octtree.y] === value.pos[octtree.y] && tree.value.pos[octtree.z] === value.pos[octtree.z]) { tree.value = value; value = undefined; } else { displaced = value; // make sure we add our new value last value = tree.value; tree.value = undefined; tree[octtree.top_nw] = new Octtree(tree.xMin, tree.xMid, tree.yMid, tree.yMax, tree.zMid, tree.zMax, tree, octtree.top_nw); tree[octtree.top_ne] = new Octtree(tree.xMid, tree.xMax, tree.yMid, tree.yMax, tree.zMid, tree.zMax, tree, octtree.top_ne); tree[octtree.top_se] = new Octtree(tree.xMid, tree.xMax, tree.yMid, tree.yMax, tree.zMin, tree.zMid, tree, octtree.top_se); tree[octtree.top_sw] = new Octtree(tree.xMin, tree.xMid, tree.yMid, tree.yMax, tree.zMin, tree.zMid, tree, octtree.top_sw); tree[octtree.bot_nw] = new Octtree(tree.xMin, tree.xMid, tree.yMin, tree.yMid, tree.zMid, tree.zMax, tree, octtree.bot_nw); tree[octtree.bot_ne] = new Octtree(tree.xMid, tree.xMax, tree.yMin, tree.yMid, tree.zMid, tree.zMax, tree, octtree.bot_ne); tree[octtree.bot_se] = new Octtree(tree.xMid, tree.xMax, tree.yMin, tree.yMid, tree.zMin, tree.zMid, tree, octtree.bot_se); tree[octtree.bot_sw] = new Octtree(tree.xMin, tree.xMid, tree.yMin, tree.yMid, tree.zMin, tree.zMid, tree, octtree.bot_sw); tree = octtree.findNode(tree, value.pos); } } else { tree.value = value; value = displaced; displaced = undefined; if (undefined !== value) { tree = octtree.findNode(tree, value.pos); } } } return tree; } }; octtree.del = function (tree, value) { tree = octtree.findNode(tree, value.pos); if (undefined === tree || (!tree.hasValue())) { return tree; } if (tree.value.pos[octtree.x] === value.pos[octtree.x] && tree.value.pos[octtree.y] === value.pos[octtree.y] && tree.value.pos[octtree.z] === value.pos[octtree.z]) { tree.value = undefined; tree = tree.parent; var valCount, nonEmptyChild, child, i; while (undefined !== tree) { valCount = 0; for (i = 0; i < octtree.children.length; i += 1) { child = octtree.children[i]; if (!tree[child].isEmpty()) { valCount += 1; nonEmptyChild = tree[child]; } } if (0 === valCount) { for (i = 0; i < octtree.children.length; i += 1) { child = octtree.children[i]; tree[child] = undefined; } tree = tree.parent; } else if (1 === valCount) { if (nonEmptyChild.hasValue()) { for (i = 0; i < octtree.children.length; i += 1) { child = octtree.children[i]; tree[child] = undefined; } tree.value = nonEmptyChild.value; tree = tree.parent; } else { break; } } else { break; } } } return tree; }; octtree.next = function (tree) { while (undefined !== tree) { if (undefined !== tree.nextSiblingId) { return tree.parent[tree.nextSiblingId]; } else { tree = tree.parent; } } return undefined; }; octtree.defined = function (a, b) { if (undefined === a) { return b; } else { return a; } }; octtree.update = function (tree) { var root, parent, v, movedValues, i; root = tree; parent = root.parent; root.parent = undefined; // do this to stop next going up past tree movedValues = []; while (undefined !== tree) { if (tree.hasValue()) { v = tree.value; if (v.next_pos[octtree.x] < tree.xMin || tree.xMax <= v.next_pos[octtree.x] || v.next_pos[octtree.y] < tree.yMin || tree.yMax <= v.next_pos[octtree.y] || v.next_pos[octtree.z] < tree.zMin || tree.zMax <= v.next_pos[octtree.z]) { movedValues.push(tree.value); } else { vec3.set(v.next_pos, v.pos); } tree = octtree.next(tree); } else if (tree.hasChildren()) { tree = tree[octtree.firstChildId]; } else { tree = octtree.next(tree); } } root.parent = parent; tree = root; for (i = 0; i < movedValues.length; i += 1) { v = movedValues[i]; tree = octtree.defined(tree.del(v), tree); vec3.set(v.next_pos, v.pos); tree = octtree.defined(tree.add(v), tree); } return root; }; octtree.findInRadius = function (tree, pos, radius, limit) { var acc, radiusSq, worklist, x_p_r, x_m_r, y_p_r, y_m_r, z_p_r, z_m_r, xd, yd, zd; acc = []; radiusSq = radius * radius; worklist = [tree]; tree = undefined; x_p_r = 0; x_m_r = 0; y_p_r = 0; y_m_r = 0; z_p_r = 0; z_m_r = 0; while (0 < worklist.length && (undefined === limit || limit > acc.length)) { tree = worklist.shift(); if (tree.isEmpty()) { continue; } if (tree.hasValue()) { xd = Math.abs(tree.value.pos[octtree.x] - pos[octtree.x]); yd = Math.abs(tree.value.pos[octtree.y] - pos[octtree.y]); zd = Math.abs(tree.value.pos[octtree.z] - pos[octtree.z]); xd *= xd; yd *= yd; zd *= zd; if ((xd + yd + zd) <= radiusSq) { acc.push(tree); } continue; } x_p_r = pos[octtree.x] + radius; x_m_r = pos[octtree.x] - radius; y_p_r = pos[octtree.y] + radius; y_m_r = pos[octtree.y] - radius; z_p_r = pos[octtree.z] + radius; z_m_r = pos[octtree.z] - radius; if (x_p_r < tree.xMin || tree.xMax <= x_m_r || y_p_r < tree.yMin || tree.yMax <= y_m_r || z_p_r < tree.zMin || tree.zMax <= z_m_r) { continue; } if (x_m_r < tree.xMid) { if (y_m_r < tree.yMid) { if (z_m_r < tree.zMid) { octtree.randomPush(worklist, tree[octtree.bot_sw]); } if (tree.zMid <= z_p_r) { octtree.randomPush(worklist, tree[octtree.bot_nw]); } } if (tree.yMid <= y_p_r) { if (z_m_r < tree.zMid) { octtree.randomPush(worklist, tree[octtree.top_sw]); } if (tree.zMid <= z_p_r) { octtree.randomPush(worklist, tree[octtree.top_nw]); } } } if (tree.xMid <= x_p_r) { if (y_m_r < tree.yMid) { if (z_m_r < tree.zMid) { octtree.randomPush(worklist, tree[octtree.bot_se]); } if (tree.zMid <= z_p_r) { octtree.randomPush(worklist, tree[octtree.bot_ne]); } } if (tree.yMid <= y_p_r) { if (z_m_r < tree.zMid) { octtree.randomPush(worklist, tree[octtree.top_se]); } if (tree.zMid <= z_p_r) { octtree.randomPush(worklist, tree[octtree.top_ne]); } } } } return acc; }; octtree.size = function (tree) { var count, root, parent; root = 0; root = tree; parent = root.parent; root.parent = undefined; // stop the traversal going above us. while (undefined !== tree) { if (tree.hasValue()) { count += 1; tree = octtree.next(tree); } else if (tree.hasChildren()) { tree = tree[octtree.firstChildId]; } else { tree = octtree.next(tree); } } root.parent = parent; return count; }; octtree.create = function (xMin, xMax, yMin, yMax, zMin, zMax) { return new Octtree(xMin, xMax, yMin, yMax, zMin, zMax, undefined, undefined); }; octtree.randomPush = function (ary, e) { if (octtree.nextRandom() > 0.5) { ary.push(e); } else { ary.unshift(e); } return ary; }; octtree.nextRandom = function () { var r = octtree.randoms[octtree.randomIndex]; octtree.randomIndex += 1; if (octtree.randomIndex === octtree.randoms.length) { octtree.randomIndex = 0; } return r; }; rabbitmq-server-3.2.4/plugins-src/rabbitmq-management-visualiser/priv/www/visualiser/js/physics.js0000644000000000000000000000667112305126066032331 0ustar rootroot/*global octtree, vec3 */ function Newton() { } Newton.prototype.friction = 100; Newton.prototype.update = function (elapsed, obj) { var incr; vec3.scale(obj.velocity, 1 - (this.friction * elapsed)); incr = vec3.create(obj.velocity); vec3.scale(incr, elapsed); vec3.add(obj.pos, incr, obj.next_pos); }; function Spring() { } Spring.prototype.k = 1; Spring.prototype.equilibriumLength = 2; Spring.prototype.push = true; Spring.prototype.pull = true; Spring.prototype.dampingFactor = 0.5; Spring.prototype.octtreeRadius = 4; Spring.prototype.octtreeLimit = 40; Spring.prototype.apply = function (elapsed, obj1, obj2) { var damper, vecOP, distanceOP, x; damper = this.dampingFactor * elapsed * 100000; vecOP = vec3.create(); distanceOP = 0; x = 0; vec3.subtract(obj2.pos, obj1.pos, vecOP); distanceOP = vec3.length(vecOP); if (!isNaN(distanceOP) && 0 !== distanceOP) { x = distanceOP - this.equilibriumLength; if (distanceOP > this.equilibriumLength && !this.pull) { return; } if (distanceOP < this.equilibriumLength && !this.push) { return; } vec3.scale(vecOP, (damper * (((1 / distanceOP) * x) / obj1.mass))); vec3.add(obj1.velocity, vecOP); } }; Spring.prototype.update = function (elapsed, tree, obj) { var damper, vecOP, distanceOP, x, found, i, obj1; damper = this.dampingFactor * elapsed * 100000; vecOP = vec3.create(); distanceOP = 0; x = 0; found = tree.findInRadius(obj.pos, this.octtreeRadius, this.octtreeLimit); for (i = 0; i < found.length; i += 1) { obj1 = found[i].value; if (obj1 !== obj) { // F = -k x where x is difference from equilibriumLength // a = F / m vec3.subtract(obj1.pos, obj.pos, vecOP); distanceOP = vec3.length(vecOP); if (!isNaN(distanceOP) && 0 !== distanceOP) { x = distanceOP - this.equilibriumLength; if (distanceOP > this.equilibriumLength && !this.pull) { continue; } if (distanceOP < this.equilibriumLength && !this.push) { continue; } vec3.scale(vecOP, (damper * (((1 / distanceOP) * x) / obj.mass))); vec3.add(obj.velocity, vecOP); } } } }; function Gravity() { } Gravity.prototype.bigG = 1 / 20; Gravity.prototype.octtreeRadius = 5; Gravity.prototype.octtreeLimit = 20; Gravity.prototype.repel = false; Gravity.prototype.update = function (elapsed, tree, obj) { var vecOP, distanceOP, found, i, obj1; vecOP = vec3.create(); distanceOP = 0; found = tree.findInRadius(obj.pos, this.octtreeRadius, this.octtreeLimit); for (i = 0; i < found.length; i += 1) { obj1 = found[i].value; if (obj1 !== obj) { // F = G.m1.m2 / (d.d) // a = F / m1 // thus a = G.m2/(d.d) vec3.subtract(obj1.pos, obj.pos, vecOP); distanceOP = vec3.length(vecOP); if ((!(isNaN(distanceOP))) && 0 !== distanceOP) { vec3.scale(vecOP, (this.bigG * obj1.mass) / (distanceOP * distanceOP)); if (this.repel) { vec3.subtract(obj.velocity, vecOP); } else { vec3.add(obj.velocity, vecOP); } } } } }; rabbitmq-server-3.2.4/plugins-src/rabbitmq-management-visualiser/priv/www/visualiser/js/main.js0000644000000000000000000005224512305126066031571 0ustar rootroot/*global octtree, vec3, Model, Channel, Exchange, Queue, Binding, Newton, Spring, window */ /*jslint browser: true, devel: true */ var tree = octtree.create(0, 10000, 0, 1000000, -0.5, 2); var updatePeriod = 1000; // 1 second var configuration, detailsInFlight, mouseDragOffsetVec, hoveringOver, dragging, selectedVhost, ctx, canvas, tick, mouseMove, setCanvasMousemove, requestAnimFrame; var client = new XMLHttpRequest(); var detailsClient = new XMLHttpRequest(); var model = new Model(); var mousePos = vec3.create(); var mouseDown = false; var highlight = "#ffffc0"; var faded = "#c0c0c0"; var eta = 0.1; var max_v = 100000; var newton = new Newton(); var spring = new Spring(); spring.octtreeRadius = 500; spring.equilibriumLength = 50; spring.dampingFactor = 0.01; spring.pull = false; spring.push = true; var rendering = true; var lastTime = 0; var fontSize = 12; Exchange.prototype.fontSize = fontSize; Queue.prototype.fontSize = fontSize; Binding.prototype.fontSize = fontSize; var canvasLeft = 0; var canvasTop = 0; var scrollLeft = 0; var scrollTop = 0; var clientWidth = 0; var clientHeight = 0; /****************************************************************************** * Fetching details from the broker * ******************************************************************************/ function update() { if (undefined === selectedVhost) { client.open("GET", "../api/all"); } else { client.open("GET", "../api/all/" + encodeURIComponent(selectedVhost)); } client.send(); } function updateReady() { if (client.readyState === 4 && client.status === 200) { setTimeout(update, updatePeriod); configuration = JSON.parse(client.responseText); model.rebuild(tree, configuration); if (!rendering) { lastTime = 0; requestAnimFrame(tick); } } } client.onreadystatechange = updateReady; function getDetails() { detailsInFlight = this; detailsClient.abort(); detailsClient.open("GET", "../api" + this.url()); detailsClient.send(); } Channel.prototype.getDetails = getDetails; Exchange.prototype.getDetails = getDetails; Queue.prototype.getDetails = getDetails; function repeatGetDetails() { if (undefined !== hoveringOver) { hoveringOver.getDetails(); } } function flattenAtts(a) { if ("string" === typeof a) { return a; } else { var str, e; str = "{"; for (e in a) { if (a.hasOwnProperty(e)) { str += "" + e + ": " + flattenAtts(a[e]) + ", "; } } return str.replace(/(, )?$/, "}"); } } function setDetails(elem) { var details, strAtts, visibleRows, columns, column, str, attName, i; details = document.getElementById("details"); if (undefined === elem) { details.innerHTML = ""; detailsInFlight = undefined; } else { strAtts = elem.stringAttributes(); visibleRows = Math.floor(details.clientHeight / 16); // line-height + padding; columns = Math.ceil(strAtts.attributeOrder.length / visibleRows); column = 0; str = ""; for (i in strAtts.attributeOrder) { column += 1; attName = strAtts.attributeOrder[i]; if (undefined !== strAtts[attName]) { str += ""; } else { str += ""; } if (column === columns) { column = 0; str += ""; } } str += "
    " + attName + "" + flattenAtts(strAtts[attName]) + "" + attName + "
    "; document.getElementById("details").innerHTML = str; } } function detailsUpdateReady() { if (detailsClient.readyState === 4 && detailsClient.status === 200 && undefined !== hoveringOver && undefined !== detailsInFlight && hoveringOver.object_type === detailsInFlight.object_type && hoveringOver.name === detailsInFlight.name) { try { var details = JSON.parse(detailsClient.responseText); if (undefined !== details.name && details.name === detailsInFlight.name) { model[detailsInFlight.object_type][detailsInFlight.name].details = details; setDetails(model[detailsInFlight.object_type][detailsInFlight.name]); setTimeout(repeatGetDetails, updatePeriod); } } catch (err) { // We probably cancelled it as we were receiving data. model[detailsInFlight.object_type][detailsInFlight.name].details = undefined; window.console.info("" + err); } } } detailsClient.onreadystatechange = detailsUpdateReady; /****************************************************************************** * Rendering / animation * ******************************************************************************/ requestAnimFrame = (function () { return (this.requestAnimationFrame || this.webkitRequestAnimationFrame || this.mozRequestAnimationFrame || this.oRequestAnimationFrame || this.msRequestAnimationFrame || function (/* function FrameRequestCallback */ callback, /* DOMElement Element */ element) { setTimeout(callback, 1000 / 60); }); })(); function recordMousePos(e) { var x, y; x = e.pageX; y = e.pageY; x = (x - canvasLeft) + scrollLeft; y = (y - canvasTop) + scrollTop; mousePos[octtree.x] = x; mousePos[octtree.y] = y; } mouseMove = function (e) { recordMousePos(e); canvas.onmousemove = undefined; setTimeout(setCanvasMousemove, 10); }; setCanvasMousemove = function () { if (rendering) { canvas.onmousemove = mouseMove; } }; function resizeCanvas() { var e; if (undefined !== canvas) { canvas.width = canvas.parentNode.offsetWidth; canvas.height = canvas.parentNode.offsetHeight; Channel.prototype.canvasResized(canvas); Exchange.prototype.canvasResized(canvas); Queue.prototype.canvasResized(canvas); clientWidth = canvas.width; clientHeight = canvas.height; e = canvas.parentNode; while (undefined !== e && null !== e) { if (undefined !== e.clientHeight && undefined !== e.clientWidth && e.clientHeight > 0 && e.clientWidth > 0) { clientHeight = Math.min(clientHeight, e.clientHeight); clientWidth = Math.min(clientWidth, e.clientWidth); } e = e.parentNode; } canvasLeft = 0; canvasTop = 0; e = canvas.parentNode; while (undefined !== e && null !== e) { if (undefined !== e.offsetLeft && undefined !== e.offsetTop) { canvasLeft += e.offsetLeft; canvasTop += e.offsetTop; } e = e.parentNode; } if (undefined !== hoveringOver && undefined !== hoveringOver.details) { setDetails(hoveringOver); } } } function canvasScroll() { scrollLeft = 0; scrollTop = 0; var e = canvas.parentNode; while (undefined !== e && null !== e) { if (undefined !== e.scrollLeft && undefined !== e.scrollTop) { scrollLeft += e.scrollLeft; scrollTop += e.scrollTop; } e = e.parentNode; } } function clamp(elem) { var x_vel_abs, y_vel_abs; x_vel_abs = Math.abs(elem.velocity[octtree.x]); y_vel_abs = Math.abs(elem.velocity[octtree.y]); if (0 !== x_vel_abs && eta > x_vel_abs) { elem.velocity[octtree.x] = 0; } else if (max_v < x_vel_abs) { elem.velocity[octtree.x] = max_v * (x_vel_abs / elem.velocity[octtree.x]); } if (0 !== y_vel_abs && eta > y_vel_abs) { elem.velocity[octtree.y] = 0; } else if (max_v < y_vel_abs) { elem.velocity[octtree.y] = max_v * (y_vel_abs / elem.velocity[octtree.y]); } if (elem.next_pos[octtree.x] < 1) { elem.next_pos[octtree.x] = 1; elem.velocity[octtree.x] = 0; } if (elem.next_pos[octtree.y] < 1) { elem.next_pos[octtree.y] = 1; elem.velocity[octtree.y] = 0; } if (elem.next_pos[octtree.x] >= canvas.width) { elem.next_pos[octtree.x] = canvas.width - 1; } if (elem.next_pos[octtree.y] >= (canvas.height - 100)) { canvas.height += 100; } } function initCanvas() { resizeCanvas(); setCanvasMousemove(); canvas.onmousedown = function (e) { recordMousePos(e); if (e.shiftKey && undefined !== hoveringOver) { model.disable(hoveringOver, tree); mouseDown = false; hoveringOver = undefined; dragging = undefined; } else { mouseDown = true; mouseDragOffsetVec = undefined; } }; canvas.ondblclick = function (e) { recordMousePos(e); if (undefined !== hoveringOver) { hoveringOver.navigateTo(); } }; canvas.onmouseup = function (e) { recordMousePos(e); mouseDown = false; mouseDragOffsetVec = undefined; dragging = undefined; }; try { ctx = canvas.getContext("2d"); } catch (e) { } if (!ctx) { alert("Could not initialise 2D canvas. Change browser?"); } } function drawScene() { ctx.font = "" + fontSize + "px sans-serif"; ctx.clearRect(scrollLeft, scrollTop, clientWidth, clientHeight); ctx.lineWidth = 1.0; ctx.lineCap = "round"; ctx.lineJoin = "round"; ctx.strokeStyle = "black"; model.render(ctx); } function animate() { var timeNow, elapsed, e, i; timeNow = new Date().getTime(); if (lastTime !== 0) { elapsed = (timeNow - lastTime) / 10000; for (i in model.exchange) { e = model.exchange[i]; if ((undefined === dragging || dragging !== e) && ! e.disabled) { e.animate(elapsed); newton.update(elapsed, e); spring.update(elapsed, tree, e); clamp(e); } } for (i in model.channel) { e = model.channel[i]; if ((undefined === dragging || dragging !== e) && ! e.disabled) { e.animate(elapsed); newton.update(elapsed, e); spring.update(elapsed, tree, e); clamp(e); } } for (i in model.queue) { e = model.queue[i]; if ((undefined === dragging || dragging !== e) && ! e.disabled) { e.animate(elapsed); newton.update(elapsed, e); spring.update(elapsed, tree, e); clamp(e); } } tree.update(); } lastTime = timeNow; } tick = function () { drawScene(); animate(); if (rendering) { requestAnimFrame(tick); } }; function visualisationStart() { canvas = document.getElementById("topology_canvas"); initCanvas(); update(); requestAnimFrame(tick); } // Used to start/stop doing work when we gain/lose focus function enableRendering() { lastTime = 0; rendering = true; setCanvasMousemove(); requestAnimFrame(tick); } function disableRendering() { canvas.onmousemove = undefined; rendering = false; } /****************************************************************************** * Model callbacks for rendering * ******************************************************************************/ function draggable(model, ctx) { var inPath = ctx.isPointInPath(mousePos[octtree.x], mousePos[octtree.y]); if ((inPath && undefined === hoveringOver) || dragging === this || hoveringOver === this) { ctx.fillStyle = highlight; ctx.fill(); if (hoveringOver !== this) { this.getDetails(); } hoveringOver = this; if (mouseDown) { dragging = this; if (undefined === mouseDragOffsetVec) { mouseDragOffsetVec = vec3.create(this.pos); vec3.subtract(mouseDragOffsetVec, mousePos); } vec3.set(mousePos, this.next_pos); vec3.add(this.next_pos, mouseDragOffsetVec); this.velocity = vec3.create(); clamp(this); } else if (!inPath) { if (undefined !== hoveringOver) { hoveringOver.details = undefined; } if (detailsInFlight === this) { setDetails(undefined); } dragging = undefined; hoveringOver = undefined; mouseDragOffsetVec = undefined; } } else { ctx.fillStyle = "white"; ctx.fill(); } if (undefined !== hoveringOver && hoveringOver !== this && ! model.isHighlighted(this)) { ctx.strokeStyle = faded; } ctx.stroke(); } Channel.prototype.preStroke = draggable; Exchange.prototype.preStroke = draggable; Queue.prototype.preStroke = draggable; Binding.prototype.preStroke = function (source, destination, model, ctx) { var drawBindingKeys, xMid, yMid, bindingKey, k, dim; drawBindingKeys = false; if (undefined === hoveringOver) { drawBindingKeys = ctx.isPointInPath(mousePos[octtree.x], mousePos[octtree.y]); } else { if (hoveringOver === source) { ctx.strokeStyle = "#0000a0"; drawBindingKeys = true; } else if (hoveringOver === destination) { ctx.strokeStyle = "#00a000"; drawBindingKeys = true; } else { ctx.strokeStyle = faded; } } ctx.stroke(); if (drawBindingKeys) { xMid = (source.xMax + destination.xMin) / 2; yMid = source === destination ? source.pos[octtree.y] - this.loopOffset + fontSize : (source.pos[octtree.y] + destination.pos[octtree.y]) / 2; bindingKey = ""; for (k in this.keys) { bindingKey += ", " + k; } bindingKey = bindingKey.slice(2); dim = ctx.measureText(bindingKey); ctx.textBaseline = "middle"; ctx.textAlign = "center"; ctx.fillStyle = "rgba(255, 255, 255, 0.67)"; ctx.fillRect(xMid - (dim.width / 2), yMid - (this.fontSize / 2), dim.width, this.fontSize); ctx.fillStyle = ctx.strokeStyle; ctx.fillText(bindingKey, xMid, yMid); } }; function frustumCull(xMin, yMin, width, height) { return ((yMin > (scrollTop + clientHeight)) || ((yMin + height) < scrollTop) || (xMin > (scrollLeft + clientWidth)) || ((xMin + width) < scrollLeft)); } Model.prototype.cull = frustumCull; /****************************************************************************** * Showing / hiding / removing resources * ******************************************************************************/ function selectInsertAlphabetical(selectElem, optionElem) { var preceding, i; for (i = 0; i < selectElem.options.length; i += 1) { if (optionElem.text < selectElem.options[i].text) { preceding = selectElem.options[i]; break; } } selectElem.add(optionElem, preceding); return selectElem.options; } function show(hiddenElemId, model, type) { var i, e, hidden; if (model.rendering[type].enabled) { hidden = document.getElementById(hiddenElemId); for (i = 0; i < hidden.options.length; i += 1) { e = hidden.options[i]; if (e.selected) { model.enable(model[type][e.value], tree); hidden.remove(i); i -= 1; } } } } function showChannels() { show("hidden_channels", model, 'channel'); } function showExchanges() { show("hidden_exchanges", model, 'exchange'); } function showQueues() { show("hidden_queues", model, 'queue'); } // Called when the resource is enabled from being hidden function enable_fun(type, postFun) { return function (model, tree) { if (model.rendering[type].enabled) { delete model.rendering[type].on_enable[this.name]; } this.remove = Object.getPrototypeOf(this).remove; this.postFun = postFun; this.postFun(model, tree); }; } Channel.prototype.enable = enable_fun('channel', Channel.prototype.enable); Exchange.prototype.enable = enable_fun('exchange', Exchange.prototype.enable); Queue.prototype.enable = enable_fun('queue', Queue.prototype.enable); // Called when the item is removed and the item is disabled function remove_disabled_fun(hiddenElemId, postFun) { return function (tree, model) { var hidden, i; hidden = document.getElementById(hiddenElemId); for (i = 0; i < hidden.options.length; i += 1) { if (hidden.options[i].value === this.name) { hidden.remove(i); break; } } model.enable(this, tree); this.postFun = postFun; this.postFun(tree, model); }; } function disable_fun(hiddenElemId, type, postFun) { return function (model) { if (detailsInFlight === this) { setDetails(undefined); } var optionElem = document.createElement('option'); optionElem.text = '"' + this.name + '"'; if (undefined !== model.rendering[type].on_enable[this.name]) { optionElem.text += ' *'; } optionElem.value = this.name; selectInsertAlphabetical(document.getElementById(hiddenElemId), optionElem); this.remove = remove_disabled_fun(hiddenElemId, this.remove); this.postFun = postFun; this.postFun(model); }; } Channel.prototype.disable = disable_fun("hidden_channels", 'channel', Channel.prototype.disable); Exchange.prototype.disable = disable_fun("hidden_exchanges", 'exchange', Exchange.prototype.disable); Queue.prototype.disable = disable_fun("hidden_queues", 'queue', Queue.prototype.disable); // Called when the resource is deleted / vanishes on the broker function remove_fun(postFun, type) { return function (tree, model) { if (undefined !== hoveringOver && this === hoveringOver) { hoveringOver = undefined; dragging = undefined; } delete model.rendering[type].on_enable[this.name]; if (this === detailsInFlight) { setDetails(undefined); } this.postFun = postFun; this.postFun(tree, model); }; } Channel.prototype.remove = remove_fun(Channel.prototype.remove, 'channel'); Queue.prototype.remove = remove_fun(Queue.prototype.remove, 'queue'); Exchange.prototype.remove = remove_fun(Exchange.prototype.remove, 'exchange'); function toggleRendering(hiddenElemId, showButtonElemId, type) { var hidden, i, e; model.rendering[type].enabled = !model.rendering[type].enabled; if (model.rendering[type].enabled) { hidden = document.getElementById(hiddenElemId); for (i = 0; i < hidden.options.length; i += 1) { e = hidden.options[i].value; if (undefined !== model.rendering[type].on_enable[e]) { model.enable(model[type][e], tree); hidden.remove(i); i -= 1; } } document.getElementById(showButtonElemId).disabled = false; } else { for (i in model[type]) { if (! model[type][i].disabled) { model.rendering[type].on_enable[model[type][i].name] = true; model.disable(model[type][i], tree); } } document.getElementById(showButtonElemId).disabled = true; } return true; } function displayHelp() { document.getElementById('help').style.display = 'block'; } function hideHelp() { document.getElementById('help').style.display = 'none'; } /****************************************************************************** * VHost * ******************************************************************************/ Model.prototype.vhost_add = function (vhost) { var optionElem, options; optionElem = document.createElement('option'); optionElem.text = vhost.name; optionElem.value = vhost.name; options = selectInsertAlphabetical(document.getElementById('vhosts'), optionElem); if (options.length === 1) { selectedVhost = options[0].value; options[0].selected = true; } }; Model.prototype.vhost_remove = function (vhost) { var elem, i; elem = document.getElementById('vhosts'); for (i = 0; i < elem.options.length; i += 1) { if (elem.options[i].value === vhost.name) { elem.remove(i); break; } } }; function vhostChanged() { var elem, i, e, j; elem = document.getElementById('vhosts'); for (i = 0; i < elem.options.length; i += 1) { if (elem.options[i].selected && selectedVhost !== elem.options[i].value) { selectedVhost = elem.options[i].value; for (e in ['channel', 'exchange', 'queue']) { for (j in model[e]) { model[e][j].remove(tree, model); } } break; } } } ././@LongLink0000000000000000000000000000015000000000000011561 Lustar rootrootrabbitmq-server-3.2.4/plugins-src/rabbitmq-management-visualiser/priv/www/visualiser/js/glMatrix-min.jsrabbitmq-server-3.2.4/plugins-src/rabbitmq-management-visualiser/priv/www/visualiser/js/glMatrix-min0000644000000000000000000003027412305126066032600 0ustar rootroot// glMatrix v0.9.5 glMatrixArrayType=typeof Float32Array!="undefined"?Float32Array:typeof WebGLFloatArray!="undefined"?WebGLFloatArray:Array;var vec3={};vec3.create=function(a){var b=new glMatrixArrayType(3);if(a){b[0]=a[0];b[1]=a[1];b[2]=a[2]}return b};vec3.set=function(a,b){b[0]=a[0];b[1]=a[1];b[2]=a[2];return b};vec3.add=function(a,b,c){if(!c||a==c){a[0]+=b[0];a[1]+=b[1];a[2]+=b[2];return a}c[0]=a[0]+b[0];c[1]=a[1]+b[1];c[2]=a[2]+b[2];return c}; vec3.subtract=function(a,b,c){if(!c||a==c){a[0]-=b[0];a[1]-=b[1];a[2]-=b[2];return a}c[0]=a[0]-b[0];c[1]=a[1]-b[1];c[2]=a[2]-b[2];return c};vec3.negate=function(a,b){b||(b=a);b[0]=-a[0];b[1]=-a[1];b[2]=-a[2];return b};vec3.scale=function(a,b,c){if(!c||a==c){a[0]*=b;a[1]*=b;a[2]*=b;return a}c[0]=a[0]*b;c[1]=a[1]*b;c[2]=a[2]*b;return c}; vec3.normalize=function(a,b){b||(b=a);var c=a[0],d=a[1],e=a[2],g=Math.sqrt(c*c+d*d+e*e);if(g){if(g==1){b[0]=c;b[1]=d;b[2]=e;return b}}else{b[0]=0;b[1]=0;b[2]=0;return b}g=1/g;b[0]=c*g;b[1]=d*g;b[2]=e*g;return b};vec3.cross=function(a,b,c){c||(c=a);var d=a[0],e=a[1];a=a[2];var g=b[0],f=b[1];b=b[2];c[0]=e*b-a*f;c[1]=a*g-d*b;c[2]=d*f-e*g;return c};vec3.length=function(a){var b=a[0],c=a[1];a=a[2];return Math.sqrt(b*b+c*c+a*a)};vec3.dot=function(a,b){return a[0]*b[0]+a[1]*b[1]+a[2]*b[2]}; vec3.direction=function(a,b,c){c||(c=a);var d=a[0]-b[0],e=a[1]-b[1];a=a[2]-b[2];b=Math.sqrt(d*d+e*e+a*a);if(!b){c[0]=0;c[1]=0;c[2]=0;return c}b=1/b;c[0]=d*b;c[1]=e*b;c[2]=a*b;return c};vec3.lerp=function(a,b,c,d){d||(d=a);d[0]=a[0]+c*(b[0]-a[0]);d[1]=a[1]+c*(b[1]-a[1]);d[2]=a[2]+c*(b[2]-a[2]);return d};vec3.str=function(a){return"["+a[0]+", "+a[1]+", "+a[2]+"]"};var mat3={}; mat3.create=function(a){var b=new glMatrixArrayType(9);if(a){b[0]=a[0];b[1]=a[1];b[2]=a[2];b[3]=a[3];b[4]=a[4];b[5]=a[5];b[6]=a[6];b[7]=a[7];b[8]=a[8];b[9]=a[9]}return b};mat3.set=function(a,b){b[0]=a[0];b[1]=a[1];b[2]=a[2];b[3]=a[3];b[4]=a[4];b[5]=a[5];b[6]=a[6];b[7]=a[7];b[8]=a[8];return b};mat3.identity=function(a){a[0]=1;a[1]=0;a[2]=0;a[3]=0;a[4]=1;a[5]=0;a[6]=0;a[7]=0;a[8]=1;return a}; mat3.transpose=function(a,b){if(!b||a==b){var c=a[1],d=a[2],e=a[5];a[1]=a[3];a[2]=a[6];a[3]=c;a[5]=a[7];a[6]=d;a[7]=e;return a}b[0]=a[0];b[1]=a[3];b[2]=a[6];b[3]=a[1];b[4]=a[4];b[5]=a[7];b[6]=a[2];b[7]=a[5];b[8]=a[8];return b};mat3.toMat4=function(a,b){b||(b=mat4.create());b[0]=a[0];b[1]=a[1];b[2]=a[2];b[3]=0;b[4]=a[3];b[5]=a[4];b[6]=a[5];b[7]=0;b[8]=a[6];b[9]=a[7];b[10]=a[8];b[11]=0;b[12]=0;b[13]=0;b[14]=0;b[15]=1;return b}; mat3.str=function(a){return"["+a[0]+", "+a[1]+", "+a[2]+", "+a[3]+", "+a[4]+", "+a[5]+", "+a[6]+", "+a[7]+", "+a[8]+"]"};var mat4={};mat4.create=function(a){var b=new glMatrixArrayType(16);if(a){b[0]=a[0];b[1]=a[1];b[2]=a[2];b[3]=a[3];b[4]=a[4];b[5]=a[5];b[6]=a[6];b[7]=a[7];b[8]=a[8];b[9]=a[9];b[10]=a[10];b[11]=a[11];b[12]=a[12];b[13]=a[13];b[14]=a[14];b[15]=a[15]}return b}; mat4.set=function(a,b){b[0]=a[0];b[1]=a[1];b[2]=a[2];b[3]=a[3];b[4]=a[4];b[5]=a[5];b[6]=a[6];b[7]=a[7];b[8]=a[8];b[9]=a[9];b[10]=a[10];b[11]=a[11];b[12]=a[12];b[13]=a[13];b[14]=a[14];b[15]=a[15];return b};mat4.identity=function(a){a[0]=1;a[1]=0;a[2]=0;a[3]=0;a[4]=0;a[5]=1;a[6]=0;a[7]=0;a[8]=0;a[9]=0;a[10]=1;a[11]=0;a[12]=0;a[13]=0;a[14]=0;a[15]=1;return a}; mat4.transpose=function(a,b){if(!b||a==b){var c=a[1],d=a[2],e=a[3],g=a[6],f=a[7],h=a[11];a[1]=a[4];a[2]=a[8];a[3]=a[12];a[4]=c;a[6]=a[9];a[7]=a[13];a[8]=d;a[9]=g;a[11]=a[14];a[12]=e;a[13]=f;a[14]=h;return a}b[0]=a[0];b[1]=a[4];b[2]=a[8];b[3]=a[12];b[4]=a[1];b[5]=a[5];b[6]=a[9];b[7]=a[13];b[8]=a[2];b[9]=a[6];b[10]=a[10];b[11]=a[14];b[12]=a[3];b[13]=a[7];b[14]=a[11];b[15]=a[15];return b}; mat4.determinant=function(a){var b=a[0],c=a[1],d=a[2],e=a[3],g=a[4],f=a[5],h=a[6],i=a[7],j=a[8],k=a[9],l=a[10],o=a[11],m=a[12],n=a[13],p=a[14];a=a[15];return m*k*h*e-j*n*h*e-m*f*l*e+g*n*l*e+j*f*p*e-g*k*p*e-m*k*d*i+j*n*d*i+m*c*l*i-b*n*l*i-j*c*p*i+b*k*p*i+m*f*d*o-g*n*d*o-m*c*h*o+b*n*h*o+g*c*p*o-b*f*p*o-j*f*d*a+g*k*d*a+j*c*h*a-b*k*h*a-g*c*l*a+b*f*l*a}; mat4.inverse=function(a,b){b||(b=a);var c=a[0],d=a[1],e=a[2],g=a[3],f=a[4],h=a[5],i=a[6],j=a[7],k=a[8],l=a[9],o=a[10],m=a[11],n=a[12],p=a[13],r=a[14],s=a[15],A=c*h-d*f,B=c*i-e*f,t=c*j-g*f,u=d*i-e*h,v=d*j-g*h,w=e*j-g*i,x=k*p-l*n,y=k*r-o*n,z=k*s-m*n,C=l*r-o*p,D=l*s-m*p,E=o*s-m*r,q=1/(A*E-B*D+t*C+u*z-v*y+w*x);b[0]=(h*E-i*D+j*C)*q;b[1]=(-d*E+e*D-g*C)*q;b[2]=(p*w-r*v+s*u)*q;b[3]=(-l*w+o*v-m*u)*q;b[4]=(-f*E+i*z-j*y)*q;b[5]=(c*E-e*z+g*y)*q;b[6]=(-n*w+r*t-s*B)*q;b[7]=(k*w-o*t+m*B)*q;b[8]=(f*D-h*z+j*x)*q; b[9]=(-c*D+d*z-g*x)*q;b[10]=(n*v-p*t+s*A)*q;b[11]=(-k*v+l*t-m*A)*q;b[12]=(-f*C+h*y-i*x)*q;b[13]=(c*C-d*y+e*x)*q;b[14]=(-n*u+p*B-r*A)*q;b[15]=(k*u-l*B+o*A)*q;return b};mat4.toRotationMat=function(a,b){b||(b=mat4.create());b[0]=a[0];b[1]=a[1];b[2]=a[2];b[3]=a[3];b[4]=a[4];b[5]=a[5];b[6]=a[6];b[7]=a[7];b[8]=a[8];b[9]=a[9];b[10]=a[10];b[11]=a[11];b[12]=0;b[13]=0;b[14]=0;b[15]=1;return b}; mat4.toMat3=function(a,b){b||(b=mat3.create());b[0]=a[0];b[1]=a[1];b[2]=a[2];b[3]=a[4];b[4]=a[5];b[5]=a[6];b[6]=a[8];b[7]=a[9];b[8]=a[10];return b};mat4.toInverseMat3=function(a,b){var c=a[0],d=a[1],e=a[2],g=a[4],f=a[5],h=a[6],i=a[8],j=a[9],k=a[10],l=k*f-h*j,o=-k*g+h*i,m=j*g-f*i,n=c*l+d*o+e*m;if(!n)return null;n=1/n;b||(b=mat3.create());b[0]=l*n;b[1]=(-k*d+e*j)*n;b[2]=(h*d-e*f)*n;b[3]=o*n;b[4]=(k*c-e*i)*n;b[5]=(-h*c+e*g)*n;b[6]=m*n;b[7]=(-j*c+d*i)*n;b[8]=(f*c-d*g)*n;return b}; mat4.multiply=function(a,b,c){c||(c=a);var d=a[0],e=a[1],g=a[2],f=a[3],h=a[4],i=a[5],j=a[6],k=a[7],l=a[8],o=a[9],m=a[10],n=a[11],p=a[12],r=a[13],s=a[14];a=a[15];var A=b[0],B=b[1],t=b[2],u=b[3],v=b[4],w=b[5],x=b[6],y=b[7],z=b[8],C=b[9],D=b[10],E=b[11],q=b[12],F=b[13],G=b[14];b=b[15];c[0]=A*d+B*h+t*l+u*p;c[1]=A*e+B*i+t*o+u*r;c[2]=A*g+B*j+t*m+u*s;c[3]=A*f+B*k+t*n+u*a;c[4]=v*d+w*h+x*l+y*p;c[5]=v*e+w*i+x*o+y*r;c[6]=v*g+w*j+x*m+y*s;c[7]=v*f+w*k+x*n+y*a;c[8]=z*d+C*h+D*l+E*p;c[9]=z*e+C*i+D*o+E*r;c[10]=z* g+C*j+D*m+E*s;c[11]=z*f+C*k+D*n+E*a;c[12]=q*d+F*h+G*l+b*p;c[13]=q*e+F*i+G*o+b*r;c[14]=q*g+F*j+G*m+b*s;c[15]=q*f+F*k+G*n+b*a;return c};mat4.multiplyVec3=function(a,b,c){c||(c=b);var d=b[0],e=b[1];b=b[2];c[0]=a[0]*d+a[4]*e+a[8]*b+a[12];c[1]=a[1]*d+a[5]*e+a[9]*b+a[13];c[2]=a[2]*d+a[6]*e+a[10]*b+a[14];return c}; mat4.multiplyVec4=function(a,b,c){c||(c=b);var d=b[0],e=b[1],g=b[2];b=b[3];c[0]=a[0]*d+a[4]*e+a[8]*g+a[12]*b;c[1]=a[1]*d+a[5]*e+a[9]*g+a[13]*b;c[2]=a[2]*d+a[6]*e+a[10]*g+a[14]*b;c[3]=a[3]*d+a[7]*e+a[11]*g+a[15]*b;return c}; mat4.translate=function(a,b,c){var d=b[0],e=b[1];b=b[2];if(!c||a==c){a[12]=a[0]*d+a[4]*e+a[8]*b+a[12];a[13]=a[1]*d+a[5]*e+a[9]*b+a[13];a[14]=a[2]*d+a[6]*e+a[10]*b+a[14];a[15]=a[3]*d+a[7]*e+a[11]*b+a[15];return a}var g=a[0],f=a[1],h=a[2],i=a[3],j=a[4],k=a[5],l=a[6],o=a[7],m=a[8],n=a[9],p=a[10],r=a[11];c[0]=g;c[1]=f;c[2]=h;c[3]=i;c[4]=j;c[5]=k;c[6]=l;c[7]=o;c[8]=m;c[9]=n;c[10]=p;c[11]=r;c[12]=g*d+j*e+m*b+a[12];c[13]=f*d+k*e+n*b+a[13];c[14]=h*d+l*e+p*b+a[14];c[15]=i*d+o*e+r*b+a[15];return c}; mat4.scale=function(a,b,c){var d=b[0],e=b[1];b=b[2];if(!c||a==c){a[0]*=d;a[1]*=d;a[2]*=d;a[3]*=d;a[4]*=e;a[5]*=e;a[6]*=e;a[7]*=e;a[8]*=b;a[9]*=b;a[10]*=b;a[11]*=b;return a}c[0]=a[0]*d;c[1]=a[1]*d;c[2]=a[2]*d;c[3]=a[3]*d;c[4]=a[4]*e;c[5]=a[5]*e;c[6]=a[6]*e;c[7]=a[7]*e;c[8]=a[8]*b;c[9]=a[9]*b;c[10]=a[10]*b;c[11]=a[11]*b;c[12]=a[12];c[13]=a[13];c[14]=a[14];c[15]=a[15];return c}; mat4.rotate=function(a,b,c,d){var e=c[0],g=c[1];c=c[2];var f=Math.sqrt(e*e+g*g+c*c);if(!f)return null;if(f!=1){f=1/f;e*=f;g*=f;c*=f}var h=Math.sin(b),i=Math.cos(b),j=1-i;b=a[0];f=a[1];var k=a[2],l=a[3],o=a[4],m=a[5],n=a[6],p=a[7],r=a[8],s=a[9],A=a[10],B=a[11],t=e*e*j+i,u=g*e*j+c*h,v=c*e*j-g*h,w=e*g*j-c*h,x=g*g*j+i,y=c*g*j+e*h,z=e*c*j+g*h;e=g*c*j-e*h;g=c*c*j+i;if(d){if(a!=d){d[12]=a[12];d[13]=a[13];d[14]=a[14];d[15]=a[15]}}else d=a;d[0]=b*t+o*u+r*v;d[1]=f*t+m*u+s*v;d[2]=k*t+n*u+A*v;d[3]=l*t+p*u+B* v;d[4]=b*w+o*x+r*y;d[5]=f*w+m*x+s*y;d[6]=k*w+n*x+A*y;d[7]=l*w+p*x+B*y;d[8]=b*z+o*e+r*g;d[9]=f*z+m*e+s*g;d[10]=k*z+n*e+A*g;d[11]=l*z+p*e+B*g;return d};mat4.rotateX=function(a,b,c){var d=Math.sin(b);b=Math.cos(b);var e=a[4],g=a[5],f=a[6],h=a[7],i=a[8],j=a[9],k=a[10],l=a[11];if(c){if(a!=c){c[0]=a[0];c[1]=a[1];c[2]=a[2];c[3]=a[3];c[12]=a[12];c[13]=a[13];c[14]=a[14];c[15]=a[15]}}else c=a;c[4]=e*b+i*d;c[5]=g*b+j*d;c[6]=f*b+k*d;c[7]=h*b+l*d;c[8]=e*-d+i*b;c[9]=g*-d+j*b;c[10]=f*-d+k*b;c[11]=h*-d+l*b;return c}; mat4.rotateY=function(a,b,c){var d=Math.sin(b);b=Math.cos(b);var e=a[0],g=a[1],f=a[2],h=a[3],i=a[8],j=a[9],k=a[10],l=a[11];if(c){if(a!=c){c[4]=a[4];c[5]=a[5];c[6]=a[6];c[7]=a[7];c[12]=a[12];c[13]=a[13];c[14]=a[14];c[15]=a[15]}}else c=a;c[0]=e*b+i*-d;c[1]=g*b+j*-d;c[2]=f*b+k*-d;c[3]=h*b+l*-d;c[8]=e*d+i*b;c[9]=g*d+j*b;c[10]=f*d+k*b;c[11]=h*d+l*b;return c}; mat4.rotateZ=function(a,b,c){var d=Math.sin(b);b=Math.cos(b);var e=a[0],g=a[1],f=a[2],h=a[3],i=a[4],j=a[5],k=a[6],l=a[7];if(c){if(a!=c){c[8]=a[8];c[9]=a[9];c[10]=a[10];c[11]=a[11];c[12]=a[12];c[13]=a[13];c[14]=a[14];c[15]=a[15]}}else c=a;c[0]=e*b+i*d;c[1]=g*b+j*d;c[2]=f*b+k*d;c[3]=h*b+l*d;c[4]=e*-d+i*b;c[5]=g*-d+j*b;c[6]=f*-d+k*b;c[7]=h*-d+l*b;return c}; mat4.frustum=function(a,b,c,d,e,g,f){f||(f=mat4.create());var h=b-a,i=d-c,j=g-e;f[0]=e*2/h;f[1]=0;f[2]=0;f[3]=0;f[4]=0;f[5]=e*2/i;f[6]=0;f[7]=0;f[8]=(b+a)/h;f[9]=(d+c)/i;f[10]=-(g+e)/j;f[11]=-1;f[12]=0;f[13]=0;f[14]=-(g*e*2)/j;f[15]=0;return f};mat4.perspective=function(a,b,c,d,e){a=c*Math.tan(a*Math.PI/360);b=a*b;return mat4.frustum(-b,b,-a,a,c,d,e)}; mat4.ortho=function(a,b,c,d,e,g,f){f||(f=mat4.create());var h=b-a,i=d-c,j=g-e;f[0]=2/h;f[1]=0;f[2]=0;f[3]=0;f[4]=0;f[5]=2/i;f[6]=0;f[7]=0;f[8]=0;f[9]=0;f[10]=-2/j;f[11]=0;f[12]=-(a+b)/h;f[13]=-(d+c)/i;f[14]=-(g+e)/j;f[15]=1;return f}; mat4.lookAt=function(a,b,c,d){d||(d=mat4.create());var e=a[0],g=a[1];a=a[2];var f=c[0],h=c[1],i=c[2];c=b[1];var j=b[2];if(e==b[0]&&g==c&&a==j)return mat4.identity(d);var k,l,o,m;c=e-b[0];j=g-b[1];b=a-b[2];m=1/Math.sqrt(c*c+j*j+b*b);c*=m;j*=m;b*=m;k=h*b-i*j;i=i*c-f*b;f=f*j-h*c;if(m=Math.sqrt(k*k+i*i+f*f)){m=1/m;k*=m;i*=m;f*=m}else f=i=k=0;h=j*f-b*i;l=b*k-c*f;o=c*i-j*k;if(m=Math.sqrt(h*h+l*l+o*o)){m=1/m;h*=m;l*=m;o*=m}else o=l=h=0;d[0]=k;d[1]=h;d[2]=c;d[3]=0;d[4]=i;d[5]=l;d[6]=j;d[7]=0;d[8]=f;d[9]= o;d[10]=b;d[11]=0;d[12]=-(k*e+i*g+f*a);d[13]=-(h*e+l*g+o*a);d[14]=-(c*e+j*g+b*a);d[15]=1;return d};mat4.str=function(a){return"["+a[0]+", "+a[1]+", "+a[2]+", "+a[3]+", "+a[4]+", "+a[5]+", "+a[6]+", "+a[7]+", "+a[8]+", "+a[9]+", "+a[10]+", "+a[11]+", "+a[12]+", "+a[13]+", "+a[14]+", "+a[15]+"]"};quat4={};quat4.create=function(a){var b=new glMatrixArrayType(4);if(a){b[0]=a[0];b[1]=a[1];b[2]=a[2];b[3]=a[3]}return b};quat4.set=function(a,b){b[0]=a[0];b[1]=a[1];b[2]=a[2];b[3]=a[3];return b}; quat4.calculateW=function(a,b){var c=a[0],d=a[1],e=a[2];if(!b||a==b){a[3]=-Math.sqrt(Math.abs(1-c*c-d*d-e*e));return a}b[0]=c;b[1]=d;b[2]=e;b[3]=-Math.sqrt(Math.abs(1-c*c-d*d-e*e));return b};quat4.inverse=function(a,b){if(!b||a==b){a[0]*=1;a[1]*=1;a[2]*=1;return a}b[0]=-a[0];b[1]=-a[1];b[2]=-a[2];b[3]=a[3];return b};quat4.length=function(a){var b=a[0],c=a[1],d=a[2];a=a[3];return Math.sqrt(b*b+c*c+d*d+a*a)}; quat4.normalize=function(a,b){b||(b=a);var c=a[0],d=a[1],e=a[2],g=a[3],f=Math.sqrt(c*c+d*d+e*e+g*g);if(f==0){b[0]=0;b[1]=0;b[2]=0;b[3]=0;return b}f=1/f;b[0]=c*f;b[1]=d*f;b[2]=e*f;b[3]=g*f;return b};quat4.multiply=function(a,b,c){c||(c=a);var d=a[0],e=a[1],g=a[2];a=a[3];var f=b[0],h=b[1],i=b[2];b=b[3];c[0]=d*b+a*f+e*i-g*h;c[1]=e*b+a*h+g*f-d*i;c[2]=g*b+a*i+d*h-e*f;c[3]=a*b-d*f-e*h-g*i;return c}; quat4.multiplyVec3=function(a,b,c){c||(c=b);var d=b[0],e=b[1],g=b[2];b=a[0];var f=a[1],h=a[2];a=a[3];var i=a*d+f*g-h*e,j=a*e+h*d-b*g,k=a*g+b*e-f*d;d=-b*d-f*e-h*g;c[0]=i*a+d*-b+j*-h-k*-f;c[1]=j*a+d*-f+k*-b-i*-h;c[2]=k*a+d*-h+i*-f-j*-b;return c};quat4.toMat3=function(a,b){b||(b=mat3.create());var c=a[0],d=a[1],e=a[2],g=a[3],f=c+c,h=d+d,i=e+e,j=c*f,k=c*h;c=c*i;var l=d*h;d=d*i;e=e*i;f=g*f;h=g*h;g=g*i;b[0]=1-(l+e);b[1]=k-g;b[2]=c+h;b[3]=k+g;b[4]=1-(j+e);b[5]=d-f;b[6]=c-h;b[7]=d+f;b[8]=1-(j+l);return b}; quat4.toMat4=function(a,b){b||(b=mat4.create());var c=a[0],d=a[1],e=a[2],g=a[3],f=c+c,h=d+d,i=e+e,j=c*f,k=c*h;c=c*i;var l=d*h;d=d*i;e=e*i;f=g*f;h=g*h;g=g*i;b[0]=1-(l+e);b[1]=k-g;b[2]=c+h;b[3]=0;b[4]=k+g;b[5]=1-(j+e);b[6]=d-f;b[7]=0;b[8]=c-h;b[9]=d+f;b[10]=1-(j+l);b[11]=0;b[12]=0;b[13]=0;b[14]=0;b[15]=1;return b};quat4.slerp=function(a,b,c,d){d||(d=a);var e=c;if(a[0]*b[0]+a[1]*b[1]+a[2]*b[2]+a[3]*b[3]<0)e=-1*c;d[0]=1-c*a[0]+e*b[0];d[1]=1-c*a[1]+e*b[1];d[2]=1-c*a[2]+e*b[2];d[3]=1-c*a[3]+e*b[3];return d}; quat4.str=function(a){return"["+a[0]+", "+a[1]+", "+a[2]+", "+a[3]+"]"}; rabbitmq-server-3.2.4/plugins-src/rabbitmq-management-visualiser/src/0000755000000000000000000000000012305126066024460 5ustar rootroot././@LongLink0000000000000000000000000000015400000000000011565 Lustar rootrootrabbitmq-server-3.2.4/plugins-src/rabbitmq-management-visualiser/src/rabbitmq_management_visualiser.app.srcrabbitmq-server-3.2.4/plugins-src/rabbitmq-management-visualiser/src/rabbitmq_management_visualiser.0000644000000000000000000000032212305126066032721 0ustar rootroot{application, rabbitmq_management_visualiser, [{description, "RabbitMQ Visualiser"}, {vsn, "%%VSN%%"}, {modules, []}, {registered, []}, {applications, [kernel, stdlib, rabbit, rabbitmq_management]}]}. rabbitmq-server-3.2.4/plugins-src/rabbitmq-management-visualiser/src/rabbit_visualiser_mgmt.erl0000644000000000000000000000170712305126066031726 0ustar rootroot%% The contents of this file are subject to the Mozilla Public License %% Version 1.1 (the "License"); you may not use this file except in %% compliance with the License. You may obtain a copy of the License at %% http://www.mozilla.org/MPL/ %% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the %% License for the specific language governing rights and limitations %% under the License. %% %% The Original Code is RabbitMQ Visualiser. %% %% The Initial Developer of the Original Code is GoPivotal, Inc. %% Copyright (c) 2011-2013 GoPivotal, Inc. All rights reserved. %% -module(rabbit_visualiser_mgmt). -behaviour(rabbit_mgmt_extension). -export([dispatcher/0, web_ui/0]). dispatcher() -> [{["all"], rabbit_mgmt_wm_all, []}, {["all", vhost], rabbit_mgmt_wm_all, []}]. web_ui() -> [{javascript, <<"visualiser.js">>}]. rabbitmq-server-3.2.4/plugins-src/rabbitmq-management-visualiser/src/rabbit_mgmt_wm_all.erl0000644000000000000000000000372412305126066031014 0ustar rootroot%% The contents of this file are subject to the Mozilla Public License %% Version 1.1 (the "License"); you may not use this file except in %% compliance with the License. You may obtain a copy of the License at %% http://www.mozilla.org/MPL/ %% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the %% License for the specific language governing rights and limitations %% under the License. %% %% The Original Code is RabbitMQ Visualiser. %% %% The Initial Developer of the Original Code is GoPivotal, Inc. %% Copyright (c) 2011-2013 GoPivotal, Inc. All rights reserved. -module(rabbit_mgmt_wm_all). -export([init/1, to_json/2, content_types_provided/2, is_authorized/2, resource_exists/2]). -import(rabbit_misc, [pget/2]). -include_lib("rabbitmq_management/include/rabbit_mgmt.hrl"). -include_lib("webmachine/include/webmachine.hrl"). -include_lib("amqp_client/include/amqp_client.hrl"). %%-------------------------------------------------------------------- init(_Config) -> {ok, #context{}}. content_types_provided(ReqData, Context) -> {[{"application/json", to_json}], ReqData, Context}. resource_exists(ReqData, Context) -> {case rabbit_mgmt_util:vhost(ReqData) of not_found -> false; _ -> true end, ReqData, Context}. to_json(ReqData, Context) -> rabbit_mgmt_util:reply( [{Key, Mod:augmented(ReqData, Context)} || {Key, Mod} <- [{queues, rabbit_mgmt_wm_queues}, {exchanges, rabbit_mgmt_wm_exchanges}, {bindings, rabbit_mgmt_wm_bindings}, {channels, rabbit_mgmt_wm_channels}, {connections, rabbit_mgmt_wm_connections}, {vhosts, rabbit_mgmt_wm_vhosts}] ], ReqData, Context). is_authorized(ReqData, Context) -> rabbit_mgmt_util:is_authorized(ReqData, Context). rabbitmq-server-3.2.4/plugins-src/rabbitmq-management-visualiser/README0000644000000000000000000000402112305126066024546 0ustar rootrootRabbitMQ Visualiser =================== Usage ----- This is a plugin for the RabbitMQ Management Plugin that provides an HTML Canvas for rendering configured broker topology. The current main purpose of this is for diagnostics and comprehension of the current routing topology of the broker. The left of the canvas displays exchanges, the right displays queues, and the top displays channels. All of these items can be dragged around the canvas. They repel one another, and snap back into their predefined areas should they be released within the boundaries of those areas. Shift-clicking on an item hides it - it will be added to the relevant select box on the left. Hovering over an item shows at the top of the screen various details about the item. Double-clicking on the item will take you to the specific page in the Management Plugin concerning that item. When hovering over an item, incoming links and/or traffic are shown in green, whilst outgoing links and/or traffic are shown in blue. Bindings are always displayed, but the consumers of a queue, and likewise the publishers to an exchange, are only drawn in when hovering over the exchange, queue or channel in question. By default, up to 10 exchanges, 10 queues and 10 channels are displayed. Additional resources are available from the left hand-side select boxes, and can be brought into the display by selecting them and clicking on the relevant 'Show' button. The 'Display' check-boxes turn off and on entire resource classes, and resets positioning. Compatibility and Performance Notes ----------------------------------- Does work in recent versions of Safari both on OS X and Windows. Does work in Firefox (at least version 4.0). Does work in Chrome. Does not work in Internet Explorer. No error is given, but it doesn't work. Best performance is with Chrome. Note though that in some cases it has been seen that hardware rendering (use of GPU) can actually slow down performance. Some experimentation with browser flags and settings may be necessary to ensure smooth operation. rabbitmq-server-3.2.4/plugins-src/rabbitmq-management-visualiser/LICENSE-BSD-glMatrix0000644000000000000000000000243012305126066027070 0ustar rootrootCopyright (c) 2011, Brandon Jones All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. rabbitmq-server-3.2.4/plugins-src/rabbitmq-management-visualiser/.srcdist_done0000644000000000000000000000000012305126066026340 0ustar rootrootrabbitmq-server-3.2.4/plugins-src/rabbitmq-management-visualiser/license_info0000644000000000000000000000023012305126066026244 0ustar rootrootglMatrix is "Copyright (c) 2011, Brandon Jones" and is covered by the BSD 2-Clause license. It was downloaded from http://code.google.com/p/glmatrix/ rabbitmq-server-3.2.4/plugins-src/rabbitmq-management-visualiser/LICENSE-MPL-RabbitMQ0000644000000000000000000006051412305126066026771 0ustar rootroot MOZILLA PUBLIC LICENSE Version 1.1 --------------- 1. Definitions. 1.0.1. "Commercial Use" means distribution or otherwise making the Covered Code available to a third party. 1.1. "Contributor" means each entity that creates or contributes to the creation of Modifications. 1.2. "Contributor Version" means the combination of the Original Code, prior Modifications used by a Contributor, and the Modifications made by that particular Contributor. 1.3. "Covered Code" means the Original Code or Modifications or the combination of the Original Code and Modifications, in each case including portions thereof. 1.4. "Electronic Distribution Mechanism" means a mechanism generally accepted in the software development community for the electronic transfer of data. 1.5. "Executable" means Covered Code in any form other than Source Code. 1.6. "Initial Developer" means the individual or entity identified as the Initial Developer in the Source Code notice required by Exhibit A. 1.7. "Larger Work" means a work which combines Covered Code or portions thereof with code not governed by the terms of this License. 1.8. "License" means this document. 1.8.1. "Licensable" means having the right to grant, to the maximum extent possible, whether at the time of the initial grant or subsequently acquired, any and all of the rights conveyed herein. 1.9. "Modifications" means any addition to or deletion from the substance or structure of either the Original Code or any previous Modifications. When Covered Code is released as a series of files, a Modification is: A. Any addition to or deletion from the contents of a file containing Original Code or previous Modifications. B. Any new file that contains any part of the Original Code or previous Modifications. 1.10. "Original Code" means Source Code of computer software code which is described in the Source Code notice required by Exhibit A as Original Code, and which, at the time of its release under this License is not already Covered Code governed by this License. 1.10.1. "Patent Claims" means any patent claim(s), now owned or hereafter acquired, including without limitation, method, process, and apparatus claims, in any patent Licensable by grantor. 1.11. "Source Code" means the preferred form of the Covered Code for making modifications to it, including all modules it contains, plus any associated interface definition files, scripts used to control compilation and installation of an Executable, or source code differential comparisons against either the Original Code or another well known, available Covered Code of the Contributor's choice. The Source Code can be in a compressed or archival form, provided the appropriate decompression or de-archiving software is widely available for no charge. 1.12. "You" (or "Your") means an individual or a legal entity exercising rights under, and complying with all of the terms of, this License or a future version of this License issued under Section 6.1. For legal entities, "You" includes any entity which controls, is controlled by, or is under common control with You. For purposes of this definition, "control" means (a) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (b) ownership of more than fifty percent (50%) of the outstanding shares or beneficial ownership of such entity. 2. Source Code License. 2.1. The Initial Developer Grant. The Initial Developer hereby grants You a world-wide, royalty-free, non-exclusive license, subject to third party intellectual property claims: (a) under intellectual property rights (other than patent or trademark) Licensable by Initial Developer to use, reproduce, modify, display, perform, sublicense and distribute the Original Code (or portions thereof) with or without Modifications, and/or as part of a Larger Work; and (b) under Patents Claims infringed by the making, using or selling of Original Code, to make, have made, use, practice, sell, and offer for sale, and/or otherwise dispose of the Original Code (or portions thereof). (c) the licenses granted in this Section 2.1(a) and (b) are effective on the date Initial Developer first distributes Original Code under the terms of this License. (d) Notwithstanding Section 2.1(b) above, no patent license is granted: 1) for code that You delete from the Original Code; 2) separate from the Original Code; or 3) for infringements caused by: i) the modification of the Original Code or ii) the combination of the Original Code with other software or devices. 2.2. Contributor Grant. Subject to third party intellectual property claims, each Contributor hereby grants You a world-wide, royalty-free, non-exclusive license (a) under intellectual property rights (other than patent or trademark) Licensable by Contributor, to use, reproduce, modify, display, perform, sublicense and distribute the Modifications created by such Contributor (or portions thereof) either on an unmodified basis, with other Modifications, as Covered Code and/or as part of a Larger Work; and (b) under Patent Claims infringed by the making, using, or selling of Modifications made by that Contributor either alone and/or in combination with its Contributor Version (or portions of such combination), to make, use, sell, offer for sale, have made, and/or otherwise dispose of: 1) Modifications made by that Contributor (or portions thereof); and 2) the combination of Modifications made by that Contributor with its Contributor Version (or portions of such combination). (c) the licenses granted in Sections 2.2(a) and 2.2(b) are effective on the date Contributor first makes Commercial Use of the Covered Code. (d) Notwithstanding Section 2.2(b) above, no patent license is granted: 1) for any code that Contributor has deleted from the Contributor Version; 2) separate from the Contributor Version; 3) for infringements caused by: i) third party modifications of Contributor Version or ii) the combination of Modifications made by that Contributor with other software (except as part of the Contributor Version) or other devices; or 4) under Patent Claims infringed by Covered Code in the absence of Modifications made by that Contributor. 3. Distribution Obligations. 3.1. Application of License. The Modifications which You create or to which You contribute are governed by the terms of this License, including without limitation Section 2.2. The Source Code version of Covered Code may be distributed only under the terms of this License or a future version of this License released under Section 6.1, and You must include a copy of this License with every copy of the Source Code You distribute. You may not offer or impose any terms on any Source Code version that alters or restricts the applicable version of this License or the recipients' rights hereunder. However, You may include an additional document offering the additional rights described in Section 3.5. 3.2. Availability of Source Code. Any Modification which You create or to which You contribute must be made available in Source Code form under the terms of this License either on the same media as an Executable version or via an accepted Electronic Distribution Mechanism to anyone to whom you made an Executable version available; and if made available via Electronic Distribution Mechanism, must remain available for at least twelve (12) months after the date it initially became available, or at least six (6) months after a subsequent version of that particular Modification has been made available to such recipients. You are responsible for ensuring that the Source Code version remains available even if the Electronic Distribution Mechanism is maintained by a third party. 3.3. Description of Modifications. You must cause all Covered Code to which You contribute to contain a file documenting the changes You made to create that Covered Code and the date of any change. You must include a prominent statement that the Modification is derived, directly or indirectly, from Original Code provided by the Initial Developer and including the name of the Initial Developer in (a) the Source Code, and (b) in any notice in an Executable version or related documentation in which You describe the origin or ownership of the Covered Code. 3.4. Intellectual Property Matters (a) Third Party Claims. If Contributor has knowledge that a license under a third party's intellectual property rights is required to exercise the rights granted by such Contributor under Sections 2.1 or 2.2, Contributor must include a text file with the Source Code distribution titled "LEGAL" which describes the claim and the party making the claim in sufficient detail that a recipient will know whom to contact. If Contributor obtains such knowledge after the Modification is made available as described in Section 3.2, Contributor shall promptly modify the LEGAL file in all copies Contributor makes available thereafter and shall take other steps (such as notifying appropriate mailing lists or newsgroups) reasonably calculated to inform those who received the Covered Code that new knowledge has been obtained. (b) Contributor APIs. If Contributor's Modifications include an application programming interface and Contributor has knowledge of patent licenses which are reasonably necessary to implement that API, Contributor must also include this information in the LEGAL file. (c) Representations. Contributor represents that, except as disclosed pursuant to Section 3.4(a) above, Contributor believes that Contributor's Modifications are Contributor's original creation(s) and/or Contributor has sufficient rights to grant the rights conveyed by this License. 3.5. Required Notices. You must duplicate the notice in Exhibit A in each file of the Source Code. If it is not possible to put such notice in a particular Source Code file due to its structure, then You must include such notice in a location (such as a relevant directory) where a user would be likely to look for such a notice. If You created one or more Modification(s) You may add your name as a Contributor to the notice described in Exhibit A. You must also duplicate this License in any documentation for the Source Code where You describe recipients' rights or ownership rights relating to Covered Code. You may choose to offer, and to charge a fee for, warranty, support, indemnity or liability obligations to one or more recipients of Covered Code. However, You may do so only on Your own behalf, and not on behalf of the Initial Developer or any Contributor. You must make it absolutely clear than any such warranty, support, indemnity or liability obligation is offered by You alone, and You hereby agree to indemnify the Initial Developer and every Contributor for any liability incurred by the Initial Developer or such Contributor as a result of warranty, support, indemnity or liability terms You offer. 3.6. Distribution of Executable Versions. You may distribute Covered Code in Executable form only if the requirements of Section 3.1-3.5 have been met for that Covered Code, and if You include a notice stating that the Source Code version of the Covered Code is available under the terms of this License, including a description of how and where You have fulfilled the obligations of Section 3.2. The notice must be conspicuously included in any notice in an Executable version, related documentation or collateral in which You describe recipients' rights relating to the Covered Code. You may distribute the Executable version of Covered Code or ownership rights under a license of Your choice, which may contain terms different from this License, provided that You are in compliance with the terms of this License and that the license for the Executable version does not attempt to limit or alter the recipient's rights in the Source Code version from the rights set forth in this License. If You distribute the Executable version under a different license You must make it absolutely clear that any terms which differ from this License are offered by You alone, not by the Initial Developer or any Contributor. You hereby agree to indemnify the Initial Developer and every Contributor for any liability incurred by the Initial Developer or such Contributor as a result of any such terms You offer. 3.7. Larger Works. You may create a Larger Work by combining Covered Code with other code not governed by the terms of this License and distribute the Larger Work as a single product. In such a case, You must make sure the requirements of this License are fulfilled for the Covered Code. 4. Inability to Comply Due to Statute or Regulation. If it is impossible for You to comply with any of the terms of this License with respect to some or all of the Covered Code due to statute, judicial order, or regulation then You must: (a) comply with the terms of this License to the maximum extent possible; and (b) describe the limitations and the code they affect. Such description must be included in the LEGAL file described in Section 3.4 and must be included with all distributions of the Source Code. Except to the extent prohibited by statute or regulation, such description must be sufficiently detailed for a recipient of ordinary skill to be able to understand it. 5. Application of this License. This License applies to code to which the Initial Developer has attached the notice in Exhibit A and to related Covered Code. 6. Versions of the License. 6.1. New Versions. Netscape Communications Corporation ("Netscape") may publish revised and/or new versions of the License from time to time. Each version will be given a distinguishing version number. 6.2. Effect of New Versions. Once Covered Code has been published under a particular version of the License, You may always continue to use it under the terms of that version. You may also choose to use such Covered Code under the terms of any subsequent version of the License published by Netscape. No one other than Netscape has the right to modify the terms applicable to Covered Code created under this License. 6.3. Derivative Works. If You create or use a modified version of this License (which you may only do in order to apply it to code which is not already Covered Code governed by this License), You must (a) rename Your license so that the phrases "Mozilla", "MOZILLAPL", "MOZPL", "Netscape", "MPL", "NPL" or any confusingly similar phrase do not appear in your license (except to note that your license differs from this License) and (b) otherwise make it clear that Your version of the license contains terms which differ from the Mozilla Public License and Netscape Public License. (Filling in the name of the Initial Developer, Original Code or Contributor in the notice described in Exhibit A shall not of themselves be deemed to be modifications of this License.) 7. DISCLAIMER OF WARRANTY. COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER THIS DISCLAIMER. 8. TERMINATION. 8.1. This License and the rights granted hereunder will terminate automatically if You fail to comply with terms herein and fail to cure such breach within 30 days of becoming aware of the breach. All sublicenses to the Covered Code which are properly granted shall survive any termination of this License. Provisions which, by their nature, must remain in effect beyond the termination of this License shall survive. 8.2. If You initiate litigation by asserting a patent infringement claim (excluding declatory judgment actions) against Initial Developer or a Contributor (the Initial Developer or Contributor against whom You file such action is referred to as "Participant") alleging that: (a) such Participant's Contributor Version directly or indirectly infringes any patent, then any and all rights granted by such Participant to You under Sections 2.1 and/or 2.2 of this License shall, upon 60 days notice from Participant terminate prospectively, unless if within 60 days after receipt of notice You either: (i) agree in writing to pay Participant a mutually agreeable reasonable royalty for Your past and future use of Modifications made by such Participant, or (ii) withdraw Your litigation claim with respect to the Contributor Version against such Participant. If within 60 days of notice, a reasonable royalty and payment arrangement are not mutually agreed upon in writing by the parties or the litigation claim is not withdrawn, the rights granted by Participant to You under Sections 2.1 and/or 2.2 automatically terminate at the expiration of the 60 day notice period specified above. (b) any software, hardware, or device, other than such Participant's Contributor Version, directly or indirectly infringes any patent, then any rights granted to You by such Participant under Sections 2.1(b) and 2.2(b) are revoked effective as of the date You first made, used, sold, distributed, or had made, Modifications made by that Participant. 8.3. If You assert a patent infringement claim against Participant alleging that such Participant's Contributor Version directly or indirectly infringes any patent where such claim is resolved (such as by license or settlement) prior to the initiation of patent infringement litigation, then the reasonable value of the licenses granted by such Participant under Sections 2.1 or 2.2 shall be taken into account in determining the amount or value of any payment or license. 8.4. In the event of termination under Sections 8.1 or 8.2 above, all end user license agreements (excluding distributors and resellers) which have been validly granted by You or any distributor hereunder prior to termination shall survive termination. 9. LIMITATION OF LIABILITY. UNDER NO CIRCUMSTANCES AND UNDER NO LEGAL THEORY, WHETHER TORT (INCLUDING NEGLIGENCE), CONTRACT, OR OTHERWISE, SHALL YOU, THE INITIAL DEVELOPER, ANY OTHER CONTRIBUTOR, OR ANY DISTRIBUTOR OF COVERED CODE, OR ANY SUPPLIER OF ANY OF SUCH PARTIES, BE LIABLE TO ANY PERSON FOR ANY INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES OF ANY CHARACTER INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF GOODWILL, WORK STOPPAGE, COMPUTER FAILURE OR MALFUNCTION, OR ANY AND ALL OTHER COMMERCIAL DAMAGES OR LOSSES, EVEN IF SUCH PARTY SHALL HAVE BEEN INFORMED OF THE POSSIBILITY OF SUCH DAMAGES. THIS LIMITATION OF LIABILITY SHALL NOT APPLY TO LIABILITY FOR DEATH OR PERSONAL INJURY RESULTING FROM SUCH PARTY'S NEGLIGENCE TO THE EXTENT APPLICABLE LAW PROHIBITS SUCH LIMITATION. SOME JURISDICTIONS DO NOT ALLOW THE EXCLUSION OR LIMITATION OF INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO THIS EXCLUSION AND LIMITATION MAY NOT APPLY TO YOU. 10. U.S. GOVERNMENT END USERS. The Covered Code is a "commercial item," as that term is defined in 48 C.F.R. 2.101 (Oct. 1995), consisting of "commercial computer software" and "commercial computer software documentation," as such terms are used in 48 C.F.R. 12.212 (Sept. 1995). Consistent with 48 C.F.R. 12.212 and 48 C.F.R. 227.7202-1 through 227.7202-4 (June 1995), all U.S. Government End Users acquire Covered Code with only those rights set forth herein. 11. MISCELLANEOUS. This License represents the complete agreement concerning subject matter hereof. If any provision of this License is held to be unenforceable, such provision shall be reformed only to the extent necessary to make it enforceable. This License shall be governed by California law provisions (except to the extent applicable law, if any, provides otherwise), excluding its conflict-of-law provisions. With respect to disputes in which at least one party is a citizen of, or an entity chartered or registered to do business in the United States of America, any litigation relating to this License shall be subject to the jurisdiction of the Federal Courts of the Northern District of California, with venue lying in Santa Clara County, California, with the losing party responsible for costs, including without limitation, court costs and reasonable attorneys' fees and expenses. The application of the United Nations Convention on Contracts for the International Sale of Goods is expressly excluded. Any law or regulation which provides that the language of a contract shall be construed against the drafter shall not apply to this License. 12. RESPONSIBILITY FOR CLAIMS. As between Initial Developer and the Contributors, each party is responsible for claims and damages arising, directly or indirectly, out of its utilization of rights under this License and You agree to work with Initial Developer and Contributors to distribute such responsibility on an equitable basis. Nothing herein is intended or shall be deemed to constitute any admission of liability. 13. MULTIPLE-LICENSED CODE. Initial Developer may designate portions of the Covered Code as "Multiple-Licensed". "Multiple-Licensed" means that the Initial Developer permits you to utilize portions of the Covered Code under Your choice of the NPL or the alternative licenses, if any, specified by the Initial Developer in the file described in Exhibit A. EXHIBIT A -Mozilla Public License. ``The contents of this file are subject to the Mozilla Public License Version 1.1 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.mozilla.org/MPL/ Software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for the specific language governing rights and limitations under the License. The Original Code is RabbitMQ Visualiser. The Initial Developer of the Original Code is GoPivotal, Inc. Copyright (c) 2011-2013 GoPivotal, Inc. All rights reserved.'' [NOTE: The text of this Exhibit A may differ slightly from the text of the notices in the Source Code files of the Original Code. You should use the text of this Exhibit A rather than the text found in the Original Code Source Code for Your Modifications.] rabbitmq-server-3.2.4/plugins-src/rabbitmq-management-visualiser/Makefile0000644000000000000000000000002712305126066025330 0ustar rootrootinclude ../umbrella.mk rabbitmq-server-3.2.4/plugins-src/rabbitmq-management-visualiser/ebin/0000755000000000000000000000000012305126066024606 5ustar rootrootrabbitmq-server-3.2.4/plugins-src/rabbitmq-management-visualiser/package.mk0000644000000000000000000000026712305126066025622 0ustar rootrootRELEASABLE:=true DEPS:=rabbitmq-management CONSTRUCT_APP_PREREQS:=$(shell find $(PACKAGE_DIR)/priv -type f) define construct_app_commands cp -r $(PACKAGE_DIR)/priv $(APP_DIR) endef rabbitmq-server-3.2.4/plugins-src/rabbitmq-management-visualiser/LICENSE0000644000000000000000000000054612305126066024703 0ustar rootrootThis package, the RabbitMQ Visualiser is licensed under the MPL. For the MPL, please see LICENSE-MPL-RabbitMQ. This package makes use of the following third party libraries: glMatrix - http://code.google.com/p/glmatrix/ - BSD 2-clause license, see LICENSE-BSD-glMatrix If you have any questions regarding licensing, please contact us at info@rabbitmq.com. rabbitmq-server-3.2.4/plugins-src/rabbitmq-jsonrpc/0000755000000000000000000000000012305126066021047 5ustar rootrootrabbitmq-server-3.2.4/plugins-src/rabbitmq-jsonrpc/src/0000755000000000000000000000000012305126066021636 5ustar rootrootrabbitmq-server-3.2.4/plugins-src/rabbitmq-jsonrpc/src/rabbitmq_jsonrpc.app.src0000644000000000000000000000047712305126066026475 0ustar rootroot{application, rabbitmq_jsonrpc, [{description, "Rabbit JSON-RPC"}, {vsn, "%%VSN%%"}, {modules, []}, {registered, []}, {mod, {rabbit_jsonrpc, []}}, {env, [{listener, [{port, 15670}]}, {redirect_old_port, true}]}, {applications, [kernel, stdlib, rabbitmq_web_dispatch, rfc4627_jsonrpc]}]}. rabbitmq-server-3.2.4/plugins-src/rabbitmq-jsonrpc/src/rabbit_jsonrpc.erl0000644000000000000000000000453412305126066025351 0ustar rootroot%% The contents of this file are subject to the Mozilla Public License %% Version 1.1 (the "License"); you may not use this file except in %% compliance with the License. You may obtain a copy of the License %% at http://www.mozilla.org/MPL/ %% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See %% the License for the specific language governing rights and %% limitations under the License. %% %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is GoPivotal, Inc. %% Copyright (c) 2007-2013 GoPivotal, Inc. All rights reserved. %% -module(rabbit_jsonrpc). -behaviour(application). -export([start/2, stop/1, listener/0]). %% Dummy supervisor - see Ulf Wiger's comment at %% http://erlang.2086793.n4.nabble.com/initializing-library-applications-without-processes-td2094473.html -behaviour(supervisor). -export([init/1]). start(_Type, _StartArgs) -> RpcContext = case application:get_env(?MODULE, context) of undefined -> "rpc"; {ok, V} -> V end, Listener = listener(), if_redirect( fun () -> rabbit_web_dispatch:register_port_redirect( jsonrpc_redirect, [{port, 55670}, {ignore_in_use, true}], "", port(Listener)) end), rabbit_web_dispatch:register_context_handler( jsonrpc, Listener, RpcContext, fun(Req) -> case rfc4627_jsonrpc_mochiweb:handle("/" ++ RpcContext, Req) of no_match -> Req:not_found(); {ok, Response} -> Req:respond(Response) end end, "JSON-RPC: RPC endpoint"), supervisor:start_link({local, ?MODULE}, ?MODULE, []). stop(_State) -> if_redirect( fun () -> rabbit_web_dispatch:unregister_context(jsonrpc_redirect) end), rabbit_web_dispatch:unregister_context(jsonrpc), ok. init([]) -> {ok, {{one_for_one, 3, 10}, []}}. listener() -> {ok, Listener} = application:get_env(rabbitmq_jsonrpc, listener), Listener. if_redirect(Thunk) -> {ok, Redir} = application:get_env(rabbitmq_jsonrpc, redirect_old_port), case Redir of true -> Thunk(); false -> ok end. port(Listener) -> proplists:get_value(port, Listener). rabbitmq-server-3.2.4/plugins-src/rabbitmq-jsonrpc/README0000644000000000000000000001424112305126066021731 0ustar rootrootYou will need: - GNU make - Erlang - RabbitMQ broker source distribution, compiled, runnable and on your erlang library path - erlang-rfc4627 module, compiled and on your erlang library path To run the server with the additional HTTP support, $ make run The Makefile defaults to searching for the RabbitMQ broker in ../rabbitmq-server, and this can be overridden by setting RABBIT_SERVER_SOURCE_ROOT, like so: $ make RABBIT_SERVER_SOURCE_ROOT=path/to/rabbitmq-server run (If just the "../" part is wrong, you can try setting a different variable, RABBIT_SOURCE_ROOT, to the correct value instead. See the Makefile for the details of how RABBIT_SERVER_SOURCE_ROOT is constructed from RABBIT_SOURCE_ROOT.) The broker should start, and output a series of "starting ..." messages. A successful start looks like: starting database ...done starting core processes ...done starting recovery ...done starting persister ...done starting builtin applications ...done starting TCP listeners ...done starting HTTP-JSON-listeners ...done broker running If erlang-rfc4627 is not compiled, or not on the erlang search path, you will see: starting database ...done starting core processes ...done starting recovery ...done starting persister ...done starting builtin applications ...done starting TCP listeners ...done starting HTTP-JSON-listeners ...{"init terminating in do_boot",{{nocatch,{error,{cannot_start_application,rabbit,{bad_return,{{rabbit,start,[normal,[]]},{'EXIT',{undef,[{mod_jsonrpc,start,[]},{rabbit_http,kickstart,0},{rabbit,'-start/2-fun-0-',1},{lists,foreach,2},{rabbit,start,2},{application_master,start_it_old,4}]}}}}}}},[{init,start_it,1},{init,start_em,1}]}} Crash dump was written to: erl_crash.dump init terminating in do_boot () And finally, if the RABBIT_SERVER_SOURCE_ROOT is wrong, or it is right but the code is not compiled or not on your erlang search path, you will see: erlc -I ../rabbitmq-server/include -I include -o ebin -Wall +debug_info src/rabbit_http_channel.erl src/rabbit_http_channel.erl:28: can't find include file "rabbit.hrl" src/rabbit_http_channel.erl:29: can't find include file "rabbit_framing.hrl" src/rabbit_http_channel.erl:133: record content undefined src/rabbit_http_channel.erl:136: variable 'Props' is unbound src/rabbit_http_channel.erl:139: variable 'BodyFragmentsRev' is unbound src/rabbit_http_channel.erl:146: record 'P_basic' undefined src/rabbit_http_channel.erl:198: record content undefined src/rabbit_http_channel.erl:220: record 'P_basic' undefined src/rabbit_http_channel.erl:240: record 'channel.open' undefined src/rabbit_http_channel.erl:263: record 'P_basic' undefined src/rabbit_http_channel.erl:276: record 'channel.open_ok' undefined src/rabbit_http_channel.erl:146: Warning: function build_props/1 is unused src/rabbit_http_channel.erl:197: Warning: variable 'Bin' is unused src/rabbit_http_channel.erl:197: Warning: variable 'Props' is unused make: *** [ebin/rabbit_http_channel.beam] Error 1 All that aside, once the server starts successfully, including a "...done" for the "starting HTTP-JSON-listeners" line, you should be able to visit http://localhost:15670/ and get a webpage. Clicking on "Simple JSONRPC test" will run a small test application. Successful output of http://localhost:15670/test/index.html at the time of writing is: test_main {"installGenericProxy":{"name":"open","idempotent":false,"params":[{"name":"username","type":"str"},{"name":"password","type":"str"},{"name":"sessionTimeout","type":"num"},{"name":"virtualHost","type":"str"}]}} open {"installGenericProxy":{"name":"poll","idempotent":false,"params":[]}} {"installGenericProxy":{"name":"close","idempotent":false,"params":[]}} {"installGenericProxy":{"name":"call","idempotent":false,"params":[{"name":"method","type":"str"},{"name":"args","type":"arr"}]}} {"installGenericProxy":{"name":"cast","idempotent":false,"params":[{"name":"method","type":"str"},{"name":"args","type":"arr"},{"name":"content","type":"str"},{"name":"props","type":"arr"}]}} handle_channel_ready {"q1":"test-queue-1a"} {"q2":"test-queue-1b"} {"consumeOk":"aa-cons-tag1"} {"delivery":{"content":"hello, world","delivery_tag":1,"redelivered":false,"exchange":"","routing_key":"test-queue-1a","props":{"content_type":null,"content_encoding":null,"headers":null,"delivery_mode":null,"priority":null,"correlation_id":null,"reply_to":null,"expiration":null,"message_id":null,"timestamp":null,"type":null,"user_id":null,"app_id":null,"cluster_id":null}}} {"cancelOk":"aa-cons-tag1"} {"delivery2":{"content":"hello, world, again! pub 2","delivery_tag":2,"redelivered":false,"exchange":"","routing_key":"test-queue-1b","props":{"content_type":null,"content_encoding":null,"headers":null,"delivery_mode":null,"priority":null,"correlation_id":null,"reply_to":"something22","expiration":null,"message_id":null,"timestamp":null,"type":null,"user_id":null,"app_id":null,"cluster_id":null}}} {"installGenericProxy":{"name":"poll","idempotent":false,"params":[]}} {"installGenericProxy":{"name":"close","idempotent":false,"params":[]}} {"installGenericProxy":{"name":"call","idempotent":false,"params":[{"name":"method","type":"str"},{"name":"args","type":"arr"}]}} {"installGenericProxy":{"name":"cast","idempotent":false,"params":[{"name":"method","type":"str"},{"name":"args","type":"arr"},{"name":"content","type":"str"},{"name":"props","type":"arr"}]}} test basic.cancel compliance queue declare OK {"delivery4":{"content":"One","delivery_tag":1,"redelivered":false,"exchange":"","routing_key":"test-queue-4","props":{"content_type":null,"content_encoding":null,"headers":null,"delivery_mode":null,"priority":null,"correlation_id":null,"reply_to":null,"expiration":null,"message_id":null,"timestamp":null,"type":null,"user_id":null,"app_id":null,"cluster_id":null}}} {"never existed":"this-never-existed"} {"cancelled":"my-consumer"} The source to the test program is in server_root/htdocs/test/test.js and server_root/htdocs/test/index.html Tony Garnock-Jones 1 May 2008 http://lists.rabbitmq.com/cgi-bin/mailman/listinfo/ rabbitmq-server-3.2.4/plugins-src/rabbitmq-jsonrpc/.srcdist_done0000644000000000000000000000000012305126066023516 0ustar rootrootrabbitmq-server-3.2.4/plugins-src/rabbitmq-jsonrpc/Makefile0000644000000000000000000000002712305126066022506 0ustar rootrootinclude ../umbrella.mk rabbitmq-server-3.2.4/plugins-src/rabbitmq-jsonrpc/ebin/0000755000000000000000000000000012305126066021764 5ustar rootrootrabbitmq-server-3.2.4/plugins-src/rabbitmq-jsonrpc/package.mk0000644000000000000000000000012412305126066022770 0ustar rootrootDEPS:=rabbitmq-server rabbitmq-web-dispatch mochiweb-wrapper erlang-rfc4627-wrapper rabbitmq-server-3.2.4/plugins-src/all-packages.mk0000644000000000000000000000070012305126066020444 0ustar rootrootUMBRELLA_BASE_DIR:=. include common.mk CHAIN_TESTS:=true # Pull in all the packages $(foreach PACKAGE_MK,$(wildcard */package.mk),$(eval $(call do_package,$(call canonical_path,$(patsubst %/,%,$(dir $(PACKAGE_MK))))))) # ...and the non-integrated ones $(foreach V,$(.VARIABLES),$(if $(filter NON_INTEGRATED_%,$(filter-out NON_INTEGRATED_DEPS_%,$V)),$(eval $(call do_package,$(subst NON_INTEGRATED_,,$V))))) test-all-packages: $(CHAINED_TESTS) rabbitmq-server-3.2.4/plugins-src/rabbitmq-jsonrpc-channel-examples/0000755000000000000000000000000012305126066024271 5ustar rootrootrabbitmq-server-3.2.4/plugins-src/rabbitmq-jsonrpc-channel-examples/priv/0000755000000000000000000000000012305126066025251 5ustar rootrootrabbitmq-server-3.2.4/plugins-src/rabbitmq-jsonrpc-channel-examples/priv/www-examples/0000755000000000000000000000000012305126066027711 5ustar rootrootrabbitmq-server-3.2.4/plugins-src/rabbitmq-jsonrpc-channel-examples/priv/www-examples/index.html0000644000000000000000000000105412305126066031706 0ustar rootroot RabbitMQ Example Site ././@LongLink0000000000000000000000000000015000000000000011561 Lustar rootrootrabbitmq-server-3.2.4/plugins-src/rabbitmq-jsonrpc-channel-examples/priv/www-examples/WhiteRabbitBoard/rabbitmq-server-3.2.4/plugins-src/rabbitmq-jsonrpc-channel-examples/priv/www-examples/WhiteRabbitBoa0000755000000000000000000000000012305126066032460 5ustar rootroot././@LongLink0000000000000000000000000000016200000000000011564 Lustar rootrootrabbitmq-server-3.2.4/plugins-src/rabbitmq-jsonrpc-channel-examples/priv/www-examples/WhiteRabbitBoard/index.htmlrabbitmq-server-3.2.4/plugins-src/rabbitmq-jsonrpc-channel-examples/priv/www-examples/WhiteRabbitBoa0000644000000000000000000002052512305126066032466 0ustar rootroot WhiteRabbitBoard
    brush
    brush 2
    line
    rectangle
    circle
    clear

    WhiteRabbitBoard

    © Rafael Robayna, © Tony Garnock-Jones
    (based on Canvas Painter, © Rafael Robayna)
    
    
    
    
    ././@LongLink0000000000000000000000000000016000000000000011562 Lustar  rootrootrabbitmq-server-3.2.4/plugins-src/rabbitmq-jsonrpc-channel-examples/priv/www-examples/WhiteRabbitBoard/painter/rabbitmq-server-3.2.4/plugins-src/rabbitmq-jsonrpc-channel-examples/priv/www-examples/WhiteRabbitBoa0000755000000000000000000000000012305126066032460 5ustar  rootroot././@LongLink0000000000000000000000000000017400000000000011567 Lustar  rootrootrabbitmq-server-3.2.4/plugins-src/rabbitmq-jsonrpc-channel-examples/priv/www-examples/WhiteRabbitBoard/painter/CPWidgets.jsrabbitmq-server-3.2.4/plugins-src/rabbitmq-jsonrpc-channel-examples/priv/www-examples/WhiteRabbitBoa0000644000000000000000000003511412305126066032466 0ustar  rootroot/*
    	Copyright (c) 2005, 2006 Rafael Robayna
    
    	Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
    
    	The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
    
    	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
    
    	Additional Contributions by: Morris Johns
    */
    
    	/*
    		todo:
    		need to fix the error with drawing the function
    		need to write tutorial for using CanvasWidget
    
    		bugs: 
    		needs to be positioned absolutly and referenced absolutly - this is an issue with how mouse events are interpreted in all browsers
    
    		CanvasWidget is a base class that handles all event listening and triggering.  A person who wishes to write
    		a widget for Canvas can easily extend CanvasWidget and the few simple methods deling with drawing the widget.
    
    		Handles checking for the canvas element and the initalization of mouse event listeners.
    		to use, the drawWidget and widgetActionPerformed functions need to be extended.
    	*/
    
    	var ColorWidget = CanvasWidget.extend({
    		color_red: 0,
    		color_green: 0,
    		color_blue: 0,
    		color_alpha: 1,
    		colorString: "",
    		constructor: function(canvasName, position) {
    			this.inherit(canvasName, position);
    		},
    
    		drawWidget: function() {
    			this.context.clearRect(0,0,255,120);
    			var linGradRed = this.context.createLinearGradient(0,0,255,0);
    			linGradRed.addColorStop(0, 'rgba(0,'+this.color_green+','+this.color_blue+',1)');
    			linGradRed.addColorStop(1, 'rgba(255,'+this.color_green+','+this.color_blue+',1)');
    
    			var linGradGreen = this.context.createLinearGradient(0,0,255,0);
    			linGradGreen.addColorStop(0, 'rgba('+this.color_red+',0,'+this.color_blue+',1)');
    			linGradGreen.addColorStop(1, 'rgba('+this.color_red+',255,'+this.color_blue+',1)');
    
    			var linGradBlue= this.context.createLinearGradient(0,0,255,0);
    			linGradBlue.addColorStop(0, 'rgba('+this.color_red+','+this.color_green+',0,1)');
    			linGradBlue.addColorStop(1, 'rgba('+this.color_red+','+this.color_green+',255,1)');
    
    			var linGradAlpha= this.context.createLinearGradient(0,0,255,0);
    			linGradAlpha.addColorStop(0, 'rgba('+this.color_red+','+this.color_green+','+this.color_blue+',1)');
    			linGradAlpha.addColorStop(1, 'rgba('+this.color_red+','+this.color_green+','+this.color_blue+',0)');
    
    			this.context.fillStyle = linGradRed;
    			this.context.fillRect(0,0,255,20);
    			this.drawColorWidgetPointer(this.color_red, 20, this.context);
    
    			this.context.fillStyle = linGradGreen;
    			this.context.fillRect(0,20,255,20);
    			this.drawColorWidgetPointer(this.color_green, 40, this.context);
    
    			this.context.fillStyle = linGradBlue;
    			this.context.fillRect(0,40,255,20);
    			this.drawColorWidgetPointer(this.color_blue, 60, this.context);
    
    			this.context.fillStyle = linGradAlpha;
    			this.context.fillRect(0,60,255,20);
    			var alphaPosition = Math.floor((1-this.color_alpha)*255);
    			this.drawColorWidgetPointer(alphaPosition, 80, this.context);
    
    			this.context.fillStyle = "black";
    			this.context.fillRect(255, 0, 275, 40);
    
    			this.context.fillStyle = "white";
    			this.context.fillRect(255, 40, 275, 40);
    		},	
    			
    		drawColorWidgetPointer: function(xPos, yPos) {
    			this.context.fillStyle = "white";
    			this.context.beginPath();
    			this.context.moveTo(xPos - 6, yPos);
    			this.context.lineTo(xPos, yPos - 5);
    			this.context.lineTo(xPos + 6, yPos);
    			this.context.fill();
    			
    			this.context.strokeWidth = 1;
    			this.context.fillStyle = "black";
    
    			this.context.beginPath();
    			this.context.arc(xPos, yPos-7.5, 2.5,0,Math.PI*2 ,true);
    			this.context.fill();
    			this.context.closePath();
    		},
    		
    		checkWidgetEvent: function(e) {
    			var mousePos = this.getCanvasMousePos(e);
    
    			if(mousePos.x > 255) {
    				if(mousePos.y > 0 && mousePos.y <= 40) {
    					this.color_red = 0;
    					this.color_green = 0;
    					this.color_blue = 0;
    				} else {
    					this.color_red = 255;
    					this.color_green = 255;
    					this.color_blue = 255;
    				}
    			} else {
    				if(mousePos.y > 0 && mousePos.y <= 20) {
    					this.color_red = mousePos.x;
    				} else if(mousePos.y > 20 && mousePos.y <= 40) {
    					this.color_green = mousePos.x;
    				} else if(mousePos.y > 40 && mousePos.y <= 60) {
    					this.color_blue = mousePos.x;
    				} else {
    					this.color_alpha = 1 - mousePos.x/255;
    				}
    			}
    			
    			this.colorString = 'rgba('+this.color_red+','+this.color_green+','+this.color_blue+','+this.color_alpha+')';
    			this.drawWidget();
    			this.callWidgetListeners();
    		}
    	});
    
    	var LineWidthWidget = CanvasWidget.extend({
    		lineWidth: null,
    		
    		constructor: function(canvasName, lineWidth, position) {
    			this.lineWidth = lineWidth;
    			this.inherit(canvasName, position);
    		},
    
    		drawWidget: function() {
    			this.context.clearRect(0,0,275,120);
    
    			this.context.fillStyle = 'rgba(0,0,0,0.2)';
    			this.context.fillRect(0, 0, 275, 76);
    
    			this.context.strokeStyle = 'rgba(255,255,255,1)';
    			this.context.moveTo(1, 38);
    			this.context.lineTo(274, 38);
    			this.context.stroke();
    
    			this.context.strokeStyle = 'rgba(255,255,255,0.5)';
    			this.context.moveTo(1, 19);
    			this.context.lineTo(274, 19);
    			this.context.moveTo(1, 57);
    			this.context.lineTo(274, 57);
    			this.context.stroke();
    			
    			this.context.beginPath();
    			var linePosition = Math.floor((this.lineWidth*255)/76);
    			this.context.fillStyle = 'rgba(0,0,0,1)';
    			this.context.arc(linePosition, 38, this.lineWidth/2, 0, Math.PI*2, true);
    			this.context.fill();
    			this.context.closePath();
    		},
    	
    		checkWidgetEvent: function(e) {
    			var mousePos = this.getCanvasMousePos(e);
    
    			if(mousePos.x >= 0 && mousePos.x <= 255) {
    				this.lineWidth = Math.floor(((mousePos.x)*76)/255) + 1;
    				this.drawWidget();
    				this.callWidgetListeners();
    			}
    		}
    	});
    
    	var TransportWidget = CanvasWidget.extend({
    		timeline_shift: 5,
    		timeline_position: 5,
    		buttons: null,
    		lastTransportButton: null,
    		btnSize: {x: 30, y: 24},
    		btnShift: 32,
    		btnSpace: 4,
    		btnY: 20,
    		animator: null,
    
    		constructor: function(canvasName, position, animator) {
    			this.animator = animator;
    			this.inherit(canvasName, position);
    			this.animator.addAnimationEventListener(this.animationEventOcccured.bindAsEventListener(this));
    			this.animator.addTimeChangeEventListener(this.setTransportPosition.bindAsEventListener(this));
    		},
    
    		drawWidget: function(lineWidth) {
    			this.context.clearRect(0,0,255,120);
    			this.context.lineWidth = 1;
    			this.context.fillStyle = "#EEEEEE";
    			this.context.fillRect(0, 0, 274, 50);
    			
    			this.timeline_position = 5;
    			this.drawTransportPosition();
    
    			this.buttons = new Array();
    			
    			this.context.strokeStyle = "black";
    			this.context.fillStyle = "#DDDDDD";
    			this.context.lineWidth = 1;
    
    			for(i = 1; i <= 6; i++) {
    				this.drawButtonBorder(i);
    			}
    			this.context.fill();
    
    			this.drawRecordButton(true);
    			this.drawPlayButton(false);
    			this.drawStopButton(false);
    			this.drawRewindButton(false);
    			this.drawForwardStepButton(false);
    			this.drawForwardEndButton(false);
    			
    			this.lastTransportButton = 1;
    			
    			return transportWidget;
    		},
    
    		setButtonColor: function(action) {
    			if(action) this.context.fillStyle = "red";
    			else this.context.fillStyle = "black";
    		},
    
    		drawRecordButton: function(action) {
    			this.context.beginPath();
    			this.setButtonColor(action);
    			this.context.arc(this.buttons[1] + this.btnSize.x/2, this.btnY + this.btnSize.y/2, 8, 0, Math.PI*2, true)
    			this.context.fill();
    			this.context.closePath();
    		},
    		
    		drawPlayButton: function(action) {
    			this.context.beginPath();
    			this.setButtonColor(action);
    			this.context.moveTo(this.buttons[2] + 6, this.btnY + 4);
    			this.context.lineTo(this.buttons[2] + 6, this.btnY + this.btnSize.y - 4 );
    			this.context.lineTo(this.btnSize.x + this.buttons[2] - 6, this.btnSize.y/2 + this.btnY);
    			this.context.lineTo(this.buttons[2] + 6, this.btnY + 4);
    			this.context.fill();
    			this.context.closePath();
    		},
    
    		drawStopButton: function(action) {
    			this.context.beginPath();
    			this.setButtonColor(action);
    			this.context.fillRect(this.buttons[3] + this.btnSize.x/2 - 8, this.btnY + this.btnSize.y/2 - 8, 16, 16);
    			this.context.closePath();
    		},
    
    		drawRewindButton: function(action) {
    			this.context.beginPath();
    			this.setButtonColor(action);
    			this.context.fillRect(this.buttons[4] + this.btnSize.x/2 - 7, this.btnY + 4, 3, this.btnSize.y - 8);
    			this.context.moveTo(this.btnSize.x/2 + this.buttons[4] - 4, this.btnSize.y/2 + this.btnY);
    			this.context.lineTo(this.buttons[4] + this.btnSize.x - 8, this.btnY + 4 );
    			this.context.lineTo(this.buttons[4] + this.btnSize.x - 8, this.btnSize.y + this.btnY - 4);
    			this.context.lineTo(this.btnSize.x/2 + this.buttons[4] - 4, this.btnSize.y/2 + this.btnY);
    			this.context.fill();
    			this.context.closePath();
    		},
    
    		drawForwardStepButton: function(action) {
    			this.context.beginPath();
    			this.setButtonColor(action);
    			this.context.moveTo(this.buttons[5] + 4, this.btnY + 4);
    			this.context.lineTo(this.buttons[5] + 4, this.btnY + this.btnSize.y - 4 );
    			this.context.lineTo(this.btnSize.x/2 + this.buttons[5], this.btnSize.y/2 + this.btnY);
    			this.context.lineTo(this.buttons[5] + 4, this.btnY + 4);
    			this.context.moveTo(this.btnSize.x/2 + this.buttons[5], this.btnY + 4);
    			this.context.lineTo(this.buttons[5] + this.btnSize.x/2, this.btnY + this.btnSize.y - 4 );
    			this.context.lineTo(this.btnSize.x + this.buttons[5] - 4, this.btnSize.y/2 + this.btnY);
    			this.context.lineTo(this.btnSize.x/2 + this.buttons[5], this.btnY + 4);
    			this.context.fill();
    			this.context.closePath();
    		},
    
    		drawForwardEndButton: function(action) {
    			this.context.beginPath();
    			this.setButtonColor(action);
    			this.context.fillRect(this.buttons[6] + this.btnSize.x/2 + 4, this.btnY + 4, 3, this.btnSize.y - 8);
    			this.context.moveTo(this.buttons[6] + 8, this.btnY + 4);
    			this.context.lineTo(this.buttons[6] + 8, this.btnY + this.btnSize.y - 4 );
    			this.context.lineTo(this.btnSize.x/2 + this.buttons[6] + 4, this.btnSize.y/2 + this.btnY);
    			this.context.lineTo(this.buttons[6] + 8, this.btnY + 4);
    			this.context.fill();
    			this.context.closePath();
    		},
    
    		drawButtonBorder: function(buttonNum) {
    			var space = (buttonNum>1)?this.btnShift+(this.btnSpace*buttonNum):this.btnShift;
    			this.buttons[buttonNum] = space + (this.btnSize.x*(buttonNum - 1));
    			buttonNum--;
    			this.context.fillStyle = "#DDDDDD";
    			this.context.fillRect(space + (this.btnSize.x*buttonNum), this.btnY, this.btnSize.x, this.btnSize.y);
    			this.context.strokeRect(space + (this.btnSize.x*buttonNum), this.btnY, this.btnSize.x, this.btnSize.y);
    			this.context.fillStyle = "black";
    			this.context.fillRect(space + (this.btnSize.x*buttonNum), this.btnY - 1, this.btnSize.x, 1);
    			this.context.fillRect(space + (this.btnSize.x*buttonNum) - 1, this.btnY, 1, this.btnSize.y);
    		},
    
    		//can remove and replace this with something array
    		setButtonLook: function(index, action) {
    			switch (index){
    				case 1:
    					this.drawRecordButton(action);
    					break;
    				case 2:
    					this.drawPlayButton(action);
    					break;
    				case 3:
    					this.drawStopButton(action);
    					break;
    				case 4:
    					this.drawRewindButton(action);
    					break;
    				case 5:
    					this.drawForwardStepButton(action);
    					break;
    				case 6:
    					this.drawForwardEndButton(action);
    					break;
    			}
    		},
    
    		drawTransportPosition: function() {
    			this.context.fillStyle =  "#EEEEEE";
    			this.context.fillRect(this.timeline_shift, 7, 265, 5);
    			this.context.strokeStyle = "#666666";
    			this.context.strokeRect(this.timeline_shift, 8, 265, 3);
    			this.context.fillStyle =  "white";
    			this.context.fillRect(this.timeline_shift, 9, 265, 1);
    			this.context.fillStyle = "#AAAAAA";
    			this.context.fillRect(this.timeline_position, 7, 6, 4);
    			this.context.fillStyle = "#000000";
    		},
    	
    		checkWidgetEvent: function(e) {
    			if(this.animator.animation == null) return;
    
    			var mousePos = this.getCanvasMousePos(e);
    
    			if(mousePos.y < 20 && !this.animator.isEmpty()) {
    				this.timeline_position = mousePos.x;
    				this.animator.goToAnimationNode(Math.floor((this.animator.animation.last.t*this.timeline_position)/255));
    				this.drawTransportPosition();
    			} else if(e.type != "mousemove") {
    				if(mousePos.x > this.buttons[1] && mousePos.x < this.buttons[2]) {
    					this.animator.startRecordAnimation();
    					this.setActiveTransportButton(1);
    				} else if (mousePos.x > this.buttons[2] && mousePos.x < this.buttons[3]) {
    					this.animator.stopAnimation();
    					if(this.animator.playAnimation()) {
    						this.setActiveTransportButton(2);
    					}
    				} else if (mousePos.x > this.buttons[3] && mousePos.x < this.buttons[4]) {
    					this.animator.stopAnimation();
    					this.setActiveTransportButton(3); //not sure about removing this
    				} else if (mousePos.x > this.buttons[4] && mousePos.x < this.buttons[5]) {
    					this.animator.stopAnimation();
    					if(!this.animator.isEmpty()) {	
    						this.animator.goToAnimationNode(0);
    						this.setTransportPosition();
    					}
    				} else if (mousePos.x > this.buttons[5] && mousePos.x < this.buttons[6]) {
    					this.animator.stopAnimation();
    					if(!this.animator.isEmpty()) {
    						this.animator.goToAnimationNode(this.animator.curAnimationNode.n.t);
    						this.setTransportPosition();
    					}
    					this.setActiveTransportButton(3);
    				} else if (mousePos.x > this.buttons[6] && mousePos.x < (this.buttons[6] + 30)) {
    					this.animator.stopAnimation();
    					if(!this.animator.isEmpty()) {
    						this.setActiveTransportButton(6);
    						this.animator.goToAnimationNode(this.animator.animation.last.t);
    						this.setTransportPosition();
    						this.setActiveTransportButton(3);
    					}
    				}
    			}
    		},
    
    		setActiveTransportButton: function(button) {
    			this.drawButtonBorder(button);
    			this.setButtonLook(this.lastTransportButton, false);
    			this.setButtonLook(button, true);
    			this.lastTransportButton = button;
    		},
    		
    		animationEventOcccured: function(action) {
    			this.setActiveTransportButton(action);
    		},
    
    		setTransportPosition: function(e) {
    			var animationLength = this.animator.animation.last.t;
    			var time = this.animator.curAnimationNode.t;
    			this.timeline_position = Math.floor((time*260)/animationLength) + 5;
    			this.drawTransportPosition();
    		}
    	});
    ././@LongLink0000000000000000000000000000017400000000000011567 Lustar  rootrootrabbitmq-server-3.2.4/plugins-src/rabbitmq-jsonrpc-channel-examples/priv/www-examples/WhiteRabbitBoard/painter/CPDrawing.jsrabbitmq-server-3.2.4/plugins-src/rabbitmq-jsonrpc-channel-examples/priv/www-examples/WhiteRabbitBoa0000644000000000000000000001250612305126066032466 0ustar  rootroot/*
    	Copyright (c) 2005, 2006 Rafael Robayna
    
    	Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
    
    	The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
    
    	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
    
    	Additional Contributions by: Morris Johns
    */
    var CPDrawing = Base.extend({
    	canvasPainter: null,  // a reference to the instance of the canvasPainter it is going to manipulate
    	drawing: null, // the drawing data
    	undoNodes: null, // undone drawing data nodes
    	lastClear: null,
    	
    	constructor: function(canvasPainter) {
    		this.canvasPainter = canvasPainter;
    		this.drawing = new Array();
    		this.undoNodes = new Array();
    		this.canvasPainter.addWidgetListener(this.recordAction.bindAsEventListener(this)); 
    	},
    
    	recordAction: function() {
    		if(this.drawing.length != 0 && this.canvasPainter.cpMouseDownState == true && (this.canvasPainter.curDrawAction == 0 || this.canvasPainter.curDrawAction == 1)) {
    			var currentNode = this.drawing[this.drawing.length - 1];
    			currentNode.p[currentNode.p.length] = this.canvasPainter.curPos;
    		} else {
    			if(this.canvasPainter.curDrawAction == 5) this.lastClear = this.drawing.length;
    			this.drawing.push(this.addNode());
    			this.undoNodes = new Array();
    		}
    	},
    
    	addNode: function() {
    		var drawingNode = new Object()
    		drawingNode.p = new Array(2);  //points array
    		drawingNode.p[0] = this.canvasPainter.startPos;
    		drawingNode.p[1] = this.canvasPainter.curPos;
    		drawingNode.a = this.canvasPainter.curDrawAction; //action
    		//color and line width should stored and recalled independantly for both this and animator
    		drawingNode.c = this.canvasPainter.drawColor; //color
    		drawingNode.w = this.canvasPainter.context.lineWidth; //width
    		return drawingNode;
    	},
    	
    	removeLastNode: function() {
    		if(this.drawing.length == 0) return;
    		this.undoNodes.push(this.drawing.pop());
    		this.paintDrawing();
    	},
    	
    	addLastRemovedNode: function() {
    		if(this.undoNodes.length == 0) return;
    		this.drawing.push(this.undoNodes.pop());
    		this.paintDrawing();
    	},
    
    	paintDrawing: function() {	
    		this.canvasPainter.clearCanvas(canvasPainter);
    		for(var i = 0; i < this.drawing.length; i++) {
    			var drawingNode = this.drawing[i];
    			this.canvasPainter.context.fillStyle = drawingNode.c;
    			this.canvasPainter.context.strokeStyle = drawingNode.c;
    			this.canvasPainter.context.lineWidth = drawingNode.w;
    
    			if(drawingNode.p.length == 2) {
    				this.canvasPainter.drawActions[drawingNode.a](drawingNode.p[0], drawingNode.p[1], this.canvasPainter.context, false);
    			} else {
    				for(var n = 0; n < (drawingNode.p.length - 1); n++) {
    					this.canvasPainter.drawActions[drawingNode.a](drawingNode.p[n], drawingNode.p[n+1], this.canvasPainter.context, false);
    				}
    			}
    		}
    	},
    
    	saveDrawing: function() {
    		if(this.lastClear != null) {
    			this.drawing = this.drawing.slice(this.lastClear);
    			this.lastClear = null;
    		}
    		this.optimizeForSave();
    		return this.drawing.toSource();
    	},
    
    	optimizeForSave: function() {
    		//need to implement this
    		for(var i = (this.drawing.length - 1); i >= 0; i--) {
    			printError("i : "+i);
    			if(this.drawing[i].a != 3) continue;
    			for(var n = 0; n < i; n++) {
    				printError("n : "+n);
    				if(this.drawing[n].a != 3) continue;
    				if(this.shapeContains(i, this.drawing[i], n, this.drawing[n])) {
    					this.drawing.splice(n, 1);
    					i--;
    				}	
    			}
    		}
    	},
    
    	shapeContains: function(i1, nodeAbove, i2, nodeBellow) {
    		//only checks for two non oblique rectanges right now
    		
    		var naA = nodeAbove.p[0];
    		var naB = {x: nodeAbove.p[1].x, y:nodeAbove.p[0].y};
    		var naC = nodeAbove.p[1];
    		
    		document.getElementById("errorArea").innerHTML += "point a at index " + i1 + " " + i2 + " " + naA.x + " " + naA.y + "
    "; document.getElementById("errorArea").innerHTML += "point a at index " + i1 + " " + i2 + " " + naB.x + " " + naB.y + "
    "; document.getElementById("errorArea").innerHTML += "point a at index " + i1 + " " + i2 + " " + naC.x + " " + naC.y + "

    "; var checkPoints = new Array(4); checkPoints[0] = nodeBellow.p[0]; checkPoints[1] = {x: nodeBellow.p[1].x, y:nodeBellow.p[0].y}; checkPoints[2] = nodeBellow.p[1]; checkPoints[3] = {x: nodeBellow.p[0].x, y:nodeBellow.p[1].y}; var validPoints = 0; for(var i = 0; i < 4; i++) { if(checkPoints[i].x >= naA.x && checkPoints[i].x <= naB.x && checkPoints[i].y >= naA.y && checkPoints[i].y <= naC.y) { validPoints++; } } if(validPoints == 4) return true; return false; } }); ././@LongLink0000000000000000000000000000017700000000000011572 Lustar rootrootrabbitmq-server-3.2.4/plugins-src/rabbitmq-jsonrpc-channel-examples/priv/www-examples/WhiteRabbitBoard/painter/CanvasWidget.jsrabbitmq-server-3.2.4/plugins-src/rabbitmq-jsonrpc-channel-examples/priv/www-examples/WhiteRabbitBoa0000644000000000000000000001430412305126066032464 0ustar rootroot/** * Copyright (c) 2005, 2006 Rafael Robayna * * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * * * CanvasWidget is a base class that handles all mouse event listening for a canvas element, * implements a widget event listener than you can use to trigger events remotely on widget * state changes and encapsulates a few useful helper functions. * * To create widget using CanvasWidget all you need to do is the following: * * var YourWidget = CanvasWidget.extend({ * widget_value_1: null, * constructor: function(canvasName, position) { * this.inherit(canvasName, position); * }, * checkWidgetMouseEvent: function(e) { * var mousePos = this.getCanvasMousePos(e); * //interpret the mouse position * this.drawWidget(); * }, * drawWidget: function() { * //your canvas drawing code * } * }); * * //initialize an instance of your widget * var yourWidget = new YourWidget("canvas_name", {x: canvasPosX, y: canvasPosY}); * * //initialize an instance of your widget * yourWidget.addWidgetListener(function () { * //assign your widget value to something else * something = this.widget_value_1; * }); * * **/ var CanvasWidget = Base.extend({ canvas: null, context: null, position: null, widgetListeners: null, /** * constuctor * * @param {String} canvasName - the id of the corresponding canvas html element * @param {Array} position - the absolute position of the canvas html elemnt, {x:#,y:#} */ constructor: function(canvasElementID, position) { this.canvas = document.getElementById(canvasElementID); this.context = this.canvas.getContext('2d'); this.drawWidget(); this.initMouseListeners(); //this.position = position; this.position = Position.cumulativeOffset(this.canvas); this.position = {x: this.position[0], y: this.position[1]}; this.widgetListeners = new Array(); }, /** * Initializes all the mouse listeners for the widget. */ initMouseListeners: function() { this.mouseMoveTrigger = new Function(); if (document.all) { this.canvas.attachEvent("onmousedown", this.mouseDownActionPerformed.bindAsEventListener(this)); this.canvas.attachEvent("onmousemove", this.mouseMoveActionPerformed.bindAsEventListener(this)); this.canvas.attachEvent("onmouseup", this.mouseUpActionPerformed.bindAsEventListener(this)); this.canvas.attachEvent("onmouseout", this.mouseUpActionPerformed.bindAsEventListener(this)); } else { this.canvas.addEventListener("mousedown", this.mouseDownActionPerformed.bindAsEventListener(this), false); this.canvas.addEventListener("mousemove", this.mouseMoveActionPerformed.bindAsEventListener(this), false); this.canvas.addEventListener("mouseup", this.mouseUpActionPerformed.bindAsEventListener(this), false); this.canvas.addEventListener("mouseout", this.mouseUpActionPerformed.bindAsEventListener(this), false); } }, /** * Triggered by any mousedown event on the widget. This function calls * checkWidgetMouseEvent() and links the mousemove listener to checkWidgetEvent(). * * Override this function if you want direct access to mousedown events. * * @param {Event} e */ mouseDownActionPerformed: function(e) { this.mouseMoveTrigger = function(e) { this.checkWidgetEvent(e); } this.checkWidgetEvent(e); }, /** * Triggered by any mousemove event on the widget. * * Override this function if you want direct access to mousemove events. * * @param {Event} e */ mouseMoveActionPerformed: function(e) { this.mouseMoveTrigger(e); }, /** * Triggered by any mouseup or mouseout event on the widget. * * Override this function if you want direct access to mouseup events. * * @param {Event} e */ mouseUpActionPerformed: function(e) { this.mouseMoveTrigger = new Function(); }, /** * Called by the mousedown and mousemove event listeners by default. * * This function must be implemented by any class extending CPWidget. * * @param {Event} e */ checkWidgetMouseEvent: function(e) {}, /** * Draws the widget. * * This function must be implemented by any class extending CPWidget. * */ drawWidget: function() {}, /** * Used to add event listeners directly to the widget. Listeners registered * with this function are triggered every time the widget's state changes. * * @param {Function} eventListener */ addWidgetListener: function(eventListener) { this.widgetListeners[this.widgetListeners.length] = eventListener; }, /** * Executs all functions registered as widgetListeners. Should be called every time * the widget's state changes. */ callWidgetListeners: function() { if(this.widgetListeners.length != 0) { for(var i=0; i < this.widgetListeners.length; i++) this.widgetListeners[i](); } }, /** * Helper function to get the mouse position relative to the canvas position. * * @param {Event} e */ getCanvasMousePos: function(e) { return {x: e.clientX - this.position.x, y: e.clientY - this.position.y}; } }); var CanvasHelper = { canvasExists: function(canvasName) { var canvas = document.getElementById(canvasName); return canvas.getContext('2d'); } } ././@LongLink0000000000000000000000000000017500000000000011570 Lustar rootrootrabbitmq-server-3.2.4/plugins-src/rabbitmq-jsonrpc-channel-examples/priv/www-examples/WhiteRabbitBoard/painter/CPAnimator.jsrabbitmq-server-3.2.4/plugins-src/rabbitmq-jsonrpc-channel-examples/priv/www-examples/WhiteRabbitBoa0000644000000000000000000001634012305126066032466 0ustar rootroot/* Copyright (c) 2005, 2006 Rafael Robayna Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. Additional Contributions by: Morris Johns */ var CPAnimator = Base.extend({ RECORD: 0, PLAY: 1, STOP: 2, animationControlState: null, animationClockStart: 0, animation: null, curAnimationNode: null, animationEventListeners: new Array(), timeChangeEventListeners: new Array(), canvasPainter: null, constructor: function(canvasPainter) { this.canvasPainter = canvasPainter; this.newAnimation(); this.canvasPainter.addWidgetListener(this.recordAction.bindAsEventListener(this)); }, newAnimation: function() { this.stopAnimation(); this.animation = null; this.startRecordAnimation(); var curDrawAction = canvasPainter.curDrawAction; this.canvasPainter.curDrawAction = 5; var firstNode = this.getAction(); this.canvasPainter.curDrawAction = curDrawAction; this.animation.first = firstNode; this.animation.last = firstNode; this.curAnimationNode = firstNode; this.triggerAnimationEvent(1); }, startRecordAnimation: function() { this.animationControlState = this.RECORD; if(this.animation == null || this.curAnimationNode == null) { this.canvasPainter.clearCanvas(canvasPainter.context); this.animation = new Object(); this.curAnimationNode = null; this.animationClockStart = new Date().getTime(); } else { this.animationClockStart = new Date().getTime() + this.curAnimationNode.time; this.playAnimation(); } }, recordAction: function() { if(this.animationControlState != this.RECORD) return; var animationNode = this.getAction(); this.addNode(animationNode); }, getAction: function() { var animationNode = new Object() animationNode.p = new Array(2); //points array animationNode.p[0] = this.canvasPainter.startPos; animationNode.p[1] = this.canvasPainter.curPos; animationNode.a = this.canvasPainter.curDrawAction; //action animationNode.t = this.getAnimationTime(); //time animationNode.c = this.canvasPainter.drawColor; //color animationNode.w = this.canvasPainter.context.lineWidth; //width animationNode.n = null; //next return animationNode; }, //TODO: not sure need to check this bit addNode: function(animationNode) { if(this.animation.last == this.animation.first || animationNode.t >= this.animation.last.t) { this.animation.last.n = animationNode; this.animation.last = animationNode; } else { if(this.curAnimationNode.n == null) return; while(this.curAnimationNode.n.t <= animationNode.t) { this.curAnimationNode = this.curAnimationNode.n; this.paintAnimationNode(); } animationNode.n = this.curAnimationNode.n; this.curAnimationNode.n = animationNode; } if(this.animation.first.n == animationNode) { this.animationClockStart = new Date().getTime(); this.animation.first.t = 1; animationNode.t = 1; } this.curAnimationNode = animationNode; }, getAnimationTime: function() { return new Date().getTime() - this.animationClockStart; }, stopAnimation: function() { if(this.animationControlState != this.STOP) { this.animationControlState = this.STOP; this.triggerAnimationEvent(3); } }, playAnimation: function() { if(this.animation.first == this.animation.last) return false; if(this.animationControlState != this.RECORD) this.animationControlState = this.PLAY; if(this.curAnimationNode != null) { if(this.curAnimationNode == this.animation.last && this.animationControlState != this.RECORD) { this.curAnimationNode = this.animation.first; this.canvasPainter.clearCanvas(canvasPainter.context); } this.animationClockStart = new Date().getTime() - this.curAnimationNode.t; this.getAnimationNode(); } else { this.animationClockStart = new Date().getTime(); this.curAnimationNode = this.animation.first; this.getAnimationNode(); } return true; }, getAnimationNode: function() { if(this.animationControlState == this.STOP) return; if(this.curAnimationNode != this.animation.last) { while(this.curAnimationNode != this.animation.last && this.curAnimationNode.n.t < this.getAnimationTime()) { this.curAnimationNode = this.curAnimationNode.n; this.paintAnimationNode(); } this.triggerTimeChangeEvent(); window.setTimeout(this.getAnimationNode.bindAsEventListener(this), 5); } else if(this.animationControlState != this.RECORD) { this.stopAnimation(); } }, paintAnimationNode:function() { this.canvasPainter.context.save(); this.canvasPainter.context.fillStyle = this.curAnimationNode.c; this.canvasPainter.context.strokeStyle = this.curAnimationNode.c; this.canvasPainter.context.lineWidth = this.curAnimationNode.w; this.canvasPainter.drawActions[this.curAnimationNode.a](this.curAnimationNode.p[0], this.curAnimationNode.p[1], canvasPainter.context, false); this.canvasPainter.context.restore(); }, goToAnimationNode: function(time) { this.stopAnimation(); if(this.curAnimationNode.t > time) { this.canvasPainter.clearCanvas(canvasPainter.context); this.curAnimationNode = this.animation.first; } while(this.curAnimationNode != null) { this.paintAnimationNode(); if(this.curAnimationNode.n == null || this.curAnimationNode.n.t > time) { break; } else { this.curAnimationNode = this.curAnimationNode.n; } } }, isEmpty: function() { return this.animation.first == this.animation.last; }, // Event Handlers triggerAnimationEvent: function(action) { if(this.animationEventListeners.length != 0) { for(var i=0; i < this.animationEventListeners.length; i++) { this.animationEventListeners[i](action); } } }, addAnimationEventListener: function(eventListener) { this.animationEventListeners[this.animationEventListeners.length] = eventListener; }, triggerTimeChangeEvent: function() { if(this.timeChangeEventListeners.length != 0) { for(var i=0; i < this.timeChangeEventListeners.length; i++) this.timeChangeEventListeners[i](); } }, addTimeChangeEventListener: function(eventListener) { this.timeChangeEventListeners[this.timeChangeEventListeners.length] = eventListener; }, saveAnimation: function() { return this.animation.toSource(); } }); ././@LongLink0000000000000000000000000000017500000000000011570 Lustar rootrootrabbitmq-server-3.2.4/plugins-src/rabbitmq-jsonrpc-channel-examples/priv/www-examples/WhiteRabbitBoard/painter/cp_depends.jsrabbitmq-server-3.2.4/plugins-src/rabbitmq-jsonrpc-channel-examples/priv/www-examples/WhiteRabbitBoa0000644000000000000000000000622212305126066032464 0ustar rootroot/* Base, version 1.0.1 Copyright 2006, Dean Edwards License: http://creativecommons.org/licenses/LGPL/2.1/ */ function Base() { }; Base.version = "1.0.1"; Base.prototype = { extend: function(source, value) { var extend = Base.prototype.extend; if (arguments.length == 2) { var ancestor = this[source]; // overriding? if ((ancestor instanceof Function) && (value instanceof Function) && ancestor.valueOf() != value.valueOf() && /\binherit\b/.test(value)) { var method = value; value = function() { var previous = this.inherit; this.inherit = ancestor; var returnValue = method.apply(this, arguments); this.inherit = previous; return returnValue; }; // point to the underlying method value.valueOf = function() { return method; }; value.toString = function() { return String(method); }; } return this[source] = value; } else if (source) { var _prototype = {toSource: null}; // do the "toString" and other methods manually var _protected = ["toString", "valueOf"]; // if we are prototyping then include the constructor if (Base._prototyping) _protected[2] = "constructor"; for (var i = 0; (name = _protected[i]); i++) { if (source[name] != _prototype[name]) { extend.call(this, name, source[name]); } } // copy each of the source object's properties to this object for (var name in source) { if (!_prototype[name]) { extend.call(this, name, source[name]); } } } return this; }, inherit: function() { // call this method from any other method to invoke that method's ancestor } }; Base.extend = function(_instance, _static) { var extend = Base.prototype.extend; if (!_instance) _instance = {}; // create the constructor if (_instance.constructor == Object) { _instance.constructor = new Function; } // build the prototype Base._prototyping = true; var _prototype = new this; extend.call(_prototype, _instance); var constructor = _prototype.constructor; _prototype.constructor = this; delete Base._prototyping; // create the wrapper for the constructor function var klass = function() { if (!Base._prototyping) constructor.apply(this, arguments); this.constructor = klass; }; klass.prototype = _prototype; // build the class interface klass.extend = this.extend; klass.toString = function() { return String(constructor); }; extend.call(klass, _static); // support singletons var object = constructor ? klass : _prototype; // class initialisation if (object.init instanceof Function) object.init(); return object; }; /* Prototype JavaScript framework, version 1.4.0 * (c) 2005 Sam Stephenson * * Prototype is freely distributable under the terms of an MIT-style license. * For details, see the Prototype web site: http://prototype.conio.net/ * /*--------------------------------------------------------------------------*/ Function.prototype.bindAsEventListener = function(object) { var __method = this; return function(event) { return __method.call(object, event || window.event); } } ././@LongLink0000000000000000000000000000020000000000000011555 Lustar rootrootrabbitmq-server-3.2.4/plugins-src/rabbitmq-jsonrpc-channel-examples/priv/www-examples/WhiteRabbitBoard/painter/CanvasPainter.jsrabbitmq-server-3.2.4/plugins-src/rabbitmq-jsonrpc-channel-examples/priv/www-examples/WhiteRabbitBoa0000644000000000000000000002227712305126066032474 0ustar rootroot/**************************************************************************************************** Copyright (c) 2005, 2006 Rafael Robayna Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. Additional Contributions by: Morris Johns ****************************************************************************************************/ var CanvasPainter = CanvasWidget.extend({ canvasInterface: "", contextI: "", canvasWidth: 0, canvasHeight: 0, startPos: {x:-1,y:-1}, curPos: {x:-1,y:-1}, drawColor: "rgb(0,0,0)", //need to change to drawColor... currentLineWidth: 1, drawActions: null, curDrawAction: 0, cpMouseDownState: false, /*** init(String canvasName, String canvasInterfaceName, Array position) initializes the canvas elements, adds event handlers and pulls height and width information from the canvas element Parameters: canvasName - the name of the bottom canvas element canvasInterfaceName - the name of the top canvas element canvasPos - the absolution position of both canvas elements, used for mouse tracking. ex. {x: 10, y: 10} ***/ constructor: function(canvasName, canvasInterfaceName, position) { this.canvasInterface = document.getElementById(canvasInterfaceName); this.contextI = this.canvasInterface.getContext("2d"); this.inherit(canvasName, position); this.canvasHeight = this.canvas.getAttribute('height'); this.canvasWidth = this.canvas.getAttribute('width'); this.drawActions = [this.drawBrush, this.drawPencil, this.drawLine, this.drawRectangle, this.drawCircle, this.clearCanvas]; }, initMouseListeners: function() { this.mouseMoveTrigger = new Function(); if(document.all) { this.canvasInterface.attachEvent("onmousedown", this.mouseDownActionPerformed.bindAsEventListener(this)); this.canvasInterface.attachEvent("onmousemove", this.mouseMoveActionPerformed.bindAsEventListener(this)); this.canvasInterface.attachEvent("onmouseup", this.mouseUpActionPerformed.bindAsEventListener(this)); attachEvent("mouseup", this.mouseUpActionPerformed.bindAsEventListener(this)); } else { this.canvasInterface.addEventListener("mousedown", this.mouseDownActionPerformed.bindAsEventListener(this), false); this.canvasInterface.addEventListener("mousemove", this.mouseMoveActionPerformed.bindAsEventListener(this), false); this.canvasInterface.addEventListener("mouseup", this.mouseUpActionPerformed.bindAsEventListener(this), false); addEventListener("mouseup", this.mouseUpActionPerformed.bindAsEventListener(this), false); } }, mouseDownActionPerformed: function(e) { this.startPos = this.getCanvasMousePos(e, this.position); this.context.lineJoin = "round"; //Link mousemove event to the cpMouseMove Function through the wrapper this.mouseMoveTrigger = function(e) { this.cpMouseMove(e); }; }, sendAction: function(eventName, eventArgs) { sendCanvasPainterEvent({event: eventName, args: eventArgs}); }, handleActionEvent: function(event) { var eventName = event.event; var eventArgs = event.args; if (eventName == "clearCanvas") { this.clearCanvas(this.context); return; } this.setColorInternal(eventArgs.drawColor); this.setLineWidthInternal(eventArgs.lineWidth); if (eventName == "drawBrush") { this.drawBrush(eventArgs.startPos, eventArgs.curPos, this.context); } else if (eventName == "drawPencil") { this.drawPencil(eventArgs.startPos, eventArgs.curPos, this.context); } else if (eventName == "drawAction") { this.drawActions[eventArgs.actionNumber](eventArgs.startPos, eventArgs.curPos, this.context, false); } this.callWidgetListeners(); }, computeActionBase: function() { return { startPos: this.startPos, curPos: this.curPos, drawColor: this.drawColor, lineWidth: this.currentLineWidth }; }, cpMouseMove: function(e) { this.setColorInternal(this.drawColor); this.setLineWidthInternal(this.currentLineWidth); this.curPos = this.getCanvasMousePos(e, this.position); var actionArgs = this.computeActionBase(); if(this.curDrawAction == 0) { this.sendAction("drawBrush", actionArgs); this.startPos = this.curPos; } else if(this.curDrawAction == 1) { this.sendAction("drawPencil", actionArgs); this.startPos = this.curPos; } else if(this.curDrawAction == 2) { this.contextI.lineWidth = this.context.lineWidth; this.contextI.clearRect(0,0,this.canvasWidth,this.canvasHeight); this.drawLine(this.startPos, this.curPos, this.contextI); } else if(this.curDrawAction == 3) { this.contextI.clearRect(0,0,this.canvasWidth,this.canvasHeight); this.drawRectangle(this.startPos, this.curPos, this.contextI); } else if(this.curDrawAction == 4) { this.contextI.clearRect(0,0,this.canvasWidth,this.canvasHeight); this.drawCircle(this.startPos, this.curPos, this.contextI); } this.cpMouseDownState = true; }, mouseUpActionPerformed: function(e) { if(!this.cpMouseDownState) return; this.curPos = this.getCanvasMousePos(e, this.position); if(this.curDrawAction > 1) { var actionArgs = this.computeActionBase(); actionArgs.actionNumber = this.curDrawAction; this.sendAction("drawAction", actionArgs); this.clearInterface(); } this.mouseMoveTrigger = new Function(); this.cpMouseDownState = false; }, //Draw Functions drawRectangle: function(pntFrom, pntTo, context) { context.beginPath(); context.fillRect(pntFrom.x, pntFrom.y, pntTo.x - pntFrom.x, pntTo.y - pntFrom.y); context.closePath(); }, drawCircle: function (pntFrom, pntTo, context) { var centerX = Math.max(pntFrom.x,pntTo.x) - Math.abs(pntFrom.x - pntTo.x)/2; var centerY = Math.max(pntFrom.y,pntTo.y) - Math.abs(pntFrom.y - pntTo.y)/2; context.beginPath(); var distance = Math.sqrt(Math.pow(pntFrom.x - pntTo.x,2) + Math.pow(pntFrom.y - pntTo.y,2)); context.arc(centerX, centerY, distance/2,0,Math.PI*2 ,true); context.fill(); context.closePath(); }, drawLine: function(pntFrom, pntTo, context) { context.beginPath(); context.moveTo(pntFrom.x,pntFrom.y); context.lineTo(pntTo.x,pntTo.y); context.stroke(); context.closePath(); }, drawPencil: function(pntFrom, pntTo, context) { context.save(); context.beginPath(); context.lineCap = "round"; context.moveTo(pntFrom.x,pntFrom.y); context.lineTo(pntTo.x,pntTo.y); context.stroke(); context.closePath(); context.restore(); }, drawBrush: function(pntFrom, pntTo, context) { context.beginPath(); context.moveTo(pntFrom.x, pntFrom.y); context.lineTo(pntTo.x, pntTo.y); context.stroke(); context.closePath(); }, clearCanvas: function(context) { canvasPainter.context.beginPath(); canvasPainter.context.clearRect(0,0,canvasPainter.canvasWidth,canvasPainter.canvasHeight); canvasPainter.context.closePath(); }, clearInterface: function() { this.contextI.beginPath(); this.contextI.clearRect(0,0,this.canvasWidth,this.canvasHeight); this.contextI.closePath(); }, //Setter Methods setColorInternal: function(color) { this.context.fillStyle = color; this.context.strokeStyle = color; this.contextI.fillStyle = color; this.contextI.strokeStyle = color; }, setColor: function(color) { this.setColorInternal(color); this.drawColor = color; }, setLineWidthInternal: function(lineWidth) { this.context.lineWidth = lineWidth; this.contextI.lineWidth = lineWidth; }, setLineWidth: function(lineWidth) { this.setLineWidthInternal(lineWidth); this.currentLineWidth = lineWidth; }, //TODO: look into the event responce/calling for this function setDrawAction: function(action) { if(action == 5) { var lastAction = this.curDrawAction; this.curDrawAction = action; this.callWidgetListeners(); this.curDrawAction = lastAction; this.sendAction("clearCanvas", {}); } else { this.curDrawAction = action; this.context.fillStyle = this.drawColor; this.context.strokeStyle = this.drawColor; } }, getDistance: function(pntFrom, pntTo) { return Math.sqrt(Math.pow(pntFrom.x - pntTo.x,2) + Math.pow(pntFrom.y - pntTo.y,2)); } }); ././@LongLink0000000000000000000000000000017300000000000011566 Lustar rootrootrabbitmq-server-3.2.4/plugins-src/rabbitmq-jsonrpc-channel-examples/priv/www-examples/WhiteRabbitBoard/painter/excanvas.jsrabbitmq-server-3.2.4/plugins-src/rabbitmq-jsonrpc-channel-examples/priv/www-examples/WhiteRabbitBoa0000644000000000000000000005123612305126066032471 0ustar rootroot// Copyright 2006 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // TODO: Patterns // TODO: Radial gradient // TODO: Clipping paths // TODO: Coordsize // TODO: Painting mode // TODO: Optimize // TODO: canvas width/height sets content size in moz, border size in ie // TODO: Painting outside the canvas should not be allowed // only add this code if we do not already have a canvas implementation if (!window.CanvasRenderingContext2D) { (function () { var G_vmlCanvasManager_ = { init: function (opt_doc) { var doc = opt_doc || document; if (/MSIE/.test(navigator.userAgent) && !window.opera) { var self = this; doc.attachEvent("onreadystatechange", function () { self.init_(doc); }); } }, init_: function (doc, e) { if (doc.readyState == "complete") { // create xmlns if (!doc.namespaces["g_vml_"]) { doc.namespaces.add("g_vml_", "urn:schemas-microsoft-com:vml"); } // setup default css var ss = doc.createStyleSheet(); ss.cssText = "canvas{display:inline-block;overflow:hidden;" + "text-align:left;}" + "canvas *{behavior:url(#default#VML)}"; // find all canvas elements var els = doc.getElementsByTagName("canvas"); for (var i = 0; i < els.length; i++) { if (!els[i].getContext) { this.initElement(els[i]); } } } }, fixElement_: function (el) { // in IE before version 5.5 we would need to add HTML: to the tag name // but we do not care about IE before version 6 var outerHTML = el.outerHTML; var newEl = document.createElement(outerHTML); // if the tag is still open IE has created the children as siblings and // it has also created a tag with the name "/FOO" if (outerHTML.slice(-2) != "/>") { var tagName = "/" + el.tagName; var ns; // remove content while ((ns = el.nextSibling) && ns.tagName != tagName) { ns.removeNode(); } // remove the incorrect closing tag if (ns) { ns.removeNode(); } } el.parentNode.replaceChild(newEl, el); return newEl; }, /** * Public initializes a canvas element so that it can be used as canvas * element from now on. This is called automatically before the page is * loaded but if you are creating elements using createElement yuo need to * make sure this is called on the element. * @param el {HTMLElement} The canvas element to initialize. */ initElement: function (el) { el = this.fixElement_(el); el.getContext = function () { if (this.context_) { return this.context_; } return this.context_ = new CanvasRenderingContext2D_(this); }; var self = this; //bind el.attachEvent("onpropertychange", function (e) { // we need to watch changes to width and height switch (e.propertyName) { case "width": case "height": // coord size changed? break; } }); // if style.height is set var attrs = el.attributes; if (attrs.width && attrs.width.specified) { // TODO: use runtimeStyle and coordsize // el.getContext().setWidth_(attrs.width.nodeValue); el.style.width = attrs.width.nodeValue + "px"; } if (attrs.height && attrs.height.specified) { // TODO: use runtimeStyle and coordsize // el.getContext().setHeight_(attrs.height.nodeValue); el.style.height = attrs.height.nodeValue + "px"; } //el.getContext().setCoordsize_() } }; G_vmlCanvasManager_.init(); // precompute "00" to "FF" var dec2hex = []; for (var i = 0; i < 16; i++) { for (var j = 0; j < 16; j++) { dec2hex[i * 16 + j] = i.toString(16) + j.toString(16); } } function createMatrixIdentity() { return [ [1, 0, 0], [0, 1, 0], [0, 0, 1] ]; } function matrixMultiply(m1, m2) { var result = createMatrixIdentity(); for (var x = 0; x < 3; x++) { for (var y = 0; y < 3; y++) { var sum = 0; for (var z = 0; z < 3; z++) { sum += m1[x][z] * m2[z][y]; } result[x][y] = sum; } } return result; } function copyState(o1, o2) { o2.fillStyle = o1.fillStyle; o2.lineCap = o1.lineCap; o2.lineJoin = o1.lineJoin; o2.lineWidth = o1.lineWidth; o2.miterLimit = o1.miterLimit; o2.shadowBlur = o1.shadowBlur; o2.shadowColor = o1.shadowColor; o2.shadowOffsetX = o1.shadowOffsetX; o2.shadowOffsetY = o1.shadowOffsetY; o2.strokeStyle = o1.strokeStyle; } function processStyle(styleString) { var str, alpha = 1; styleString = String(styleString); if (styleString.substring(0, 3) == "rgb") { var start = styleString.indexOf("(", 3); var end = styleString.indexOf(")", start + 1); var guts = styleString.substring(start + 1, end).split(","); str = "#"; for (var i = 0; i < 3; i++) { str += dec2hex[parseInt(guts[i])]; } if ((guts.length == 4) && (styleString.substr(3, 1) == "a")) { alpha = guts[3]; } } else { str = styleString; } return [str, alpha]; } function processLineCap(lineCap) { switch (lineCap) { case "butt": return "flat"; case "round": return "round"; case "square": default: return "square"; } } /** * This class implements CanvasRenderingContext2D interface as described by * the WHATWG. * @param surfaceElement {HTMLElement} The element that the 2D context should * be associated with */ function CanvasRenderingContext2D_(surfaceElement) { this.m_ = createMatrixIdentity(); this.element_ = surfaceElement; this.mStack_ = []; this.aStack_ = []; this.currentPath_ = []; // Canvas context properties this.strokeStyle = "#000"; this.fillStyle = "#ccc"; this.lineWidth = 1; this.lineJoin = "miter"; this.lineCap = "butt"; this.miterLimit = 10; this.globalAlpha = 1; }; var contextPrototype = CanvasRenderingContext2D_.prototype; contextPrototype.clearRect = function() { this.element_.innerHTML = ""; this.currentPath_ = []; }; contextPrototype.beginPath = function() { // TODO: Branch current matrix so that save/restore has no effect // as per safari docs. this.currentPath_ = []; }; contextPrototype.moveTo = function(aX, aY) { this.currentPath_.push({type: "moveTo", x: aX, y: aY}); }; contextPrototype.lineTo = function(aX, aY) { this.currentPath_.push({type: "lineTo", x: aX, y: aY}); }; contextPrototype.bezierCurveTo = function(aCP1x, aCP1y, aCP2x, aCP2y, aX, aY) { this.currentPath_.push({type: "bezierCurveTo", cp1x: aCP1x, cp1y: aCP1y, cp2x: aCP2x, cp2y: aCP2y, x: aX, y: aY}); }; contextPrototype.quadraticCurveTo = function(aCPx, aCPy, aX, aY) { // VML's qb produces different output to Firefox's // FF's behaviour seems to have changed in 1.5.0.1, check this this.bezierCurveTo(aCPx, aCPy, aCPx, aCPy, aX, aY); }; contextPrototype.arc = function(aX, aY, aRadius, aStartAngle, aEndAngle, aClockwise) { if (!aClockwise) { var t = aStartAngle; aStartAngle = aEndAngle; aEndAngle = t; } var xStart = aX + (Math.cos(aStartAngle) * aRadius); var yStart = aY + Math.round(Math.sin(aStartAngle) * aRadius); var xEnd = aX + (Math.cos(aEndAngle) * aRadius); var yEnd = aY + Math.round(Math.sin(aEndAngle) * aRadius); this.currentPath_.push({type: "arc", x: aX, y: aY, radius: aRadius, xStart: xStart, yStart: yStart, xEnd: xEnd, yEnd: yEnd}); }; contextPrototype.rect = function(aX, aY, aWidth, aHeight) { this.moveTo(aX, aY); this.lineTo(aX + aWidth, aY); this.lineTo(aX + aWidth, aY + aHeight); this.lineTo(aX, aY + aHeight); this.closePath(); }; contextPrototype.strokeRect = function(aX, aY, aWidth, aHeight) { // Will destroy any existing path (same as FF behaviour) this.beginPath(); this.moveTo(aX, aY); this.lineTo(aX + aWidth, aY); this.lineTo(aX + aWidth, aY + aHeight); this.lineTo(aX, aY + aHeight); this.closePath(); this.stroke(); }; contextPrototype.fillRect = function(aX, aY, aWidth, aHeight) { // Will destroy any existing path (same as FF behaviour) this.beginPath(); this.moveTo(aX, aY); this.lineTo(aX + aWidth, aY); this.lineTo(aX + aWidth, aY + aHeight); this.lineTo(aX, aY + aHeight); this.closePath(); this.fill(); }; contextPrototype.createLinearGradient = function(aX0, aY0, aX1, aY1) { var gradient = new CanvasGradient_("gradient"); return gradient; }; contextPrototype.createRadialGradient = function(aX0, aY0, aR0, aX1, aY1, aR1) { var gradient = new CanvasGradient_("gradientradial"); gradient.radius1_ = aR0; gradient.radius2_ = aR1; gradient.focus_.x = aX0; gradient.focus_.y = aY0; return gradient; }; contextPrototype.drawImage = function (image, var_args) { var dx, dy, dw, dh, sx, sy, sw, sh; var w = image.width; var h = image.height; if (arguments.length == 3) { dx = arguments[1]; dy = arguments[2]; sx = sy = 0; sw = dw = w; sh = dh = h; } else if (arguments.length == 5) { dx = arguments[1]; dy = arguments[2]; dw = arguments[3]; dh = arguments[4]; sx = sy = 0; sw = w; sh = h; } else if (arguments.length == 9) { sx = arguments[1]; sy = arguments[2]; sw = arguments[3]; sh = arguments[4]; dx = arguments[5]; dy = arguments[6]; dw = arguments[7]; dh = arguments[8]; } else { throw "Invalid number of arguments"; } var d = this.getCoords_(dx, dy); var w2 = (sw / 2); var h2 = (sh / 2); var vmlStr = []; // For some reason that I've now forgotten, using divs didn't work vmlStr.push(' ' , '', ''); this.element_.insertAdjacentHTML("BeforeEnd", vmlStr.join("")); }; contextPrototype.stroke = function(aFill) { var lineStr = []; var lineOpen = false; var a = processStyle(aFill ? this.fillStyle : this.strokeStyle); var color = a[0]; var opacity = a[1] * this.globalAlpha; lineStr.push(' max.x) { max.x = c.x; } if (min.y == null || c.y < min.y) { min.y = c.y; } if (max.y == null || c.y > max.y) { max.y = c.y; } } } lineStr.push(' ">'); if (typeof this.fillStyle == "object") { var focus = {x: "50%", y: "50%"}; var width = (max.x - min.x); var height = (max.y - min.y); var dimension = (width > height) ? width : height; focus.x = Math.floor((this.fillStyle.focus_.x / width) * 100 + 50) + "%"; focus.y = Math.floor((this.fillStyle.focus_.y / height) * 100 + 50) + "%"; var colors = []; // inside radius (%) if (this.fillStyle.type_ == "gradientradial") { var inside = (this.fillStyle.radius1_ / dimension * 100); // percentage that outside radius exceeds inside radius var expansion = (this.fillStyle.radius2_ / dimension * 100) - inside; } else { var inside = 0; var expansion = 100; } var insidecolor = {offset: null, color: null}; var outsidecolor = {offset: null, color: null}; // We need to sort 'colors' by percentage, from 0 > 100 otherwise ie // won't interpret it correctly this.fillStyle.colors_.sort(function (cs1, cs2) { return cs1.offset - cs2.offset; }); for (var i = 0; i < this.fillStyle.colors_.length; i++) { var fs = this.fillStyle.colors_[i]; colors.push( (fs.offset * expansion) + inside, "% ", fs.color, ","); if (fs.offset > insidecolor.offset || insidecolor.offset == null) { insidecolor.offset = fs.offset; insidecolor.color = fs.color; } if (fs.offset < outsidecolor.offset || outsidecolor.offset == null) { outsidecolor.offset = fs.offset; outsidecolor.color = fs.color; } } colors.pop(); lineStr.push(''); } else if (aFill) { lineStr.push(''); } else { lineStr.push( '' ); } lineStr.push(""); this.element_.insertAdjacentHTML("beforeEnd", lineStr.join("")); this.currentPath_ = []; }; contextPrototype.fill = function() { this.stroke(true); } contextPrototype.closePath = function() { this.currentPath_.push({type: "close"}); }; /** * @private */ contextPrototype.getCoords_ = function(aX, aY) { return { x: (aX * this.m_[0][0] + aY * this.m_[1][0] + this.m_[2][0]), y: (aX * this.m_[0][1] + aY * this.m_[1][1] + this.m_[2][1]) } }; contextPrototype.save = function() { var o = {}; copyState(this, o); this.aStack_.push(o); this.mStack_.push(this.m_); this.m_ = matrixMultiply(createMatrixIdentity(), this.m_); }; contextPrototype.restore = function() { copyState(this.aStack_.pop(), this); this.m_ = this.mStack_.pop(); }; contextPrototype.translate = function(aX, aY) { var m1 = [ [1, 0, 0], [0, 1, 0], [aX, aY, 1] ]; this.m_ = matrixMultiply(m1, this.m_); }; contextPrototype.rotate = function(aRot) { var c = Math.cos(aRot); var s = Math.sin(aRot); var m1 = [ [c, s, 0], [-s, c, 0], [0, 0, 1] ]; this.m_ = matrixMultiply(m1, this.m_); }; contextPrototype.scale = function(aX, aY) { var m1 = [ [aX, 0, 0], [0, aY, 0], [0, 0, 1] ]; this.m_ = matrixMultiply(m1, this.m_); }; /******** STUBS ********/ contextPrototype.clip = function() { // TODO: Implement }; contextPrototype.arcTo = function() { // TODO: Implement }; contextPrototype.createPattern = function() { return new CanvasPattern_; }; // Gradient / Pattern Stubs function CanvasGradient_(aType) { this.type_ = aType; this.radius1_ = 0; this.radius2_ = 0; this.colors_ = []; this.focus_ = {x: 0, y: 0}; } CanvasGradient_.prototype.addColorStop = function(aOffset, aColor) { aColor = processStyle(aColor); this.colors_.push({offset: 1-aOffset, color: aColor}); }; function CanvasPattern_() {} // set up externs G_vmlCanvasManager = G_vmlCanvasManager_; CanvasRenderingContext2D = CanvasRenderingContext2D_; CanvasGradient = CanvasGradient_; CanvasPattern = CanvasPattern_; })(); } // if ././@LongLink0000000000000000000000000000017300000000000011566 Lustar rootrootrabbitmq-server-3.2.4/plugins-src/rabbitmq-jsonrpc-channel-examples/priv/www-examples/WhiteRabbitBoard/whiterabbitboard.jsrabbitmq-server-3.2.4/plugins-src/rabbitmq-jsonrpc-channel-examples/priv/www-examples/WhiteRabbitBoa0000644000000000000000000000340112305126066032460 0ustar rootrootfunction genguid() { return "g" + Math.floor(Math.random() * 1e10); } var sendCanvasPainterEvent; var listenToCanvasPainterEvents; var rabbitReadyCallback = null; function setupWhiteRabbitBoard() { log("Starting."); var channel; var queueName; var exchangeName = "canvasPainter"; RabbitMQ.openChannel(on_open, { debug: true, debugLogger: log }); function on_open(c) { channel = c; log("on_open"); channel.exchangeDeclare(exchangeName, "fanout") .addCallback(on_exchange_declared); } function on_exchange_declared() { log("on_exchange_declared"); channel.queueDeclare().addCallback(on_queue_declared); } function on_queue_declared(newQueueName) { log("on_queue_declared"); queueName = newQueueName; channel.queueBind(queueName, exchangeName).addCallback(on_queue_bound); } function on_queue_bound() { log("on_queue_bound"); sendCanvasPainterEvent = function (event) { channel.basicPublish(exchangeName, "", JSON.stringify(event)); }; listenToCanvasPainterEvents = function (callback) { channel.basicConsume(queueName, { consumeOk: function(tag) { log({consumeOk: tag}); }, deliver: function(delivery) { //log({delivery: delivery}); var parsedMessage = JSON.parse(delivery.content); //log({parsedMessage: parsedMessage}); callback(parsedMessage); } }, { no_ack: true }); }; rabbitReadyCallback(); } } function log() { $A(arguments).each(function (arg) { if (typeof(arg) == 'string') { $("testOutput").appendChild(document.createTextNode(arg + "\n")); } else { $("testOutput").appendChild(document .createTextNode(JSON.stringify(arg) + "\n")); } }); } rabbitmq-server-3.2.4/plugins-src/rabbitmq-jsonrpc-channel-examples/priv/www-examples/test/0000755000000000000000000000000012305126066030670 5ustar rootroot././@LongLink0000000000000000000000000000014600000000000011566 Lustar rootrootrabbitmq-server-3.2.4/plugins-src/rabbitmq-jsonrpc-channel-examples/priv/www-examples/test/index.htmlrabbitmq-server-3.2.4/plugins-src/rabbitmq-jsonrpc-channel-examples/priv/www-examples/test/index.htm0000644000000000000000000000146212305126066032514 0ustar rootroot RabbitMQ JSON-RPC test


    RabbitMQ JSON-RPC simple tests

    
        
    rabbitmq-server-3.2.4/plugins-src/rabbitmq-jsonrpc-channel-examples/priv/www-examples/test/test.js0000644000000000000000000000652412305126066032214 0ustar rootrootfunction testMain() { log("test_main"); var channelFactory = new JsonRpc.Service("/rpc/rabbitmq", handle_service_ready, {debug: true, debugLogger: log, timeout: 30000}); var channel; // service gateway ready function handle_service_ready() { log("open"); channel = new RabbitMQ.Channel(channelFactory, handle_channel_ready, { debug: true, debugLogger: log, channelTimeout: 5 }); } function handle_channel_ready() { log("handle_channel_ready"); var queue1 = "test-queue-1a"; var queue2 = "test-queue-1b"; var tag1 = "aa-cons-tag1"; var msg1 = "hello, world"; var msg2 = "hello, world, again! pub 2"; channel.queueDeclare(queue1) .addCallback(function(reply) { log({q1: reply}); channel.basicConsume(queue1, { consumeOk: function(tag) { log({consumeOk: tag}); this.tag = tag; }, deliver: function(delivery) { log({delivery: delivery}); channel.basicAck(delivery.delivery_tag); channel.basicCancel(this.tag); }, cancelOk: function(tag) { log({cancelOk: tag}); } }, { consumer_tag: tag1 }) .addCallback(function () { channel.basicPublish("", queue1, msg1); }); }); channel.queueDeclare(queue2) .addCallback(function(reply) { log({q2: reply}); channel.basicConsume(queue2, { consumeOk: function(tag) { this.tag = tag; }, deliver: function(delivery) { log({delivery2: delivery}); channel.basicAck(delivery.delivery_tag); channel.basicCancel(this.tag) .addCallback(reopen); } }) .addCallback(function () { channel.basicPublish("", queue2, msg2, {reply_to: "something22"}); }); }); } function reopen() { channel.close(); channel = new RabbitMQ.Channel(channelFactory, test_cancel, { debug: true, debugLogger: log, channelTimeout: 6 }); } function test_cancel(channel) { log("test basic.cancel compliance"); var queue = "test-queue-4"; var ctag = "my-consumer"; channel.queueDeclare(queue, false, false, true) .addCallback(function () { log("queue declare OK"); channel.basicConsume(queue, { deliver: function(delivery) { log({delivery4: delivery}); channel.basicCancel("this-never-existed") .addCallback(function (x) { log({"never existed": x}); }); channel.basicCancel(ctag) .addCallback(function (x) { log({cancelled: x}); channel.basicPublish("", queue, "Two"); log({finished: "tests passed"}); }); } }, { consumer_tag: ctag, no_ack: true }) .addCallback(function () { channel.basicPublish("", queue, "One"); }); }); } } function log() { $.each(arguments, function (i, arg) { if (typeof(arg) == 'string') { $("#testOutput")[0].appendChild(document.createTextNode(arg + "\n")); } else { $("#testOutput")[0].appendChild(document .createTextNode(JSON.stringify(arg) + "\n")); } }); } $(document).ready(testMain); rabbitmq-server-3.2.4/plugins-src/rabbitmq-jsonrpc-channel-examples/priv/www-examples/img/0000755000000000000000000000000012305126066030465 5ustar rootroot././@LongLink0000000000000000000000000000015300000000000011564 Lustar rootrootrabbitmq-server-3.2.4/plugins-src/rabbitmq-jsonrpc-channel-examples/priv/www-examples/img/RabbitMQLogo.pngrabbitmq-server-3.2.4/plugins-src/rabbitmq-jsonrpc-channel-examples/priv/www-examples/img/RabbitMQLo0000644000000000000000000003365412305126066032357 0ustar rootroot‰PNG  IHDRHWfãÜÉsBIT|dˆ pHYsÉÉœcˆtEXtSoftwarewww.inkscape.org›î< IDATxœíwxé}ç¿è$’ @°ˆ¤H‘¢(ª—•´ÒÙ[ÜvíKÊÆŽKâÄŽc_.—xïœ\ìxãØÙÄç;ql§¸Å½­·y»´ê%öÞ½÷2÷Ç 1Ä ¢´ø< /3/3¿y]DQ…,ó’Fªä*î¸â ㎋D€J[Ú>«T©òº$‰  #‹"#M¥¡”+ T( R¨P[SSÑãIcÏßÿcÀ|+‰8ðð[ÿ ÈÕÂö ÿùAàêT‚›ö}À¯=ôÝUüÌ+Á_Ã?¶­HD¾»¢Ph€úVÀØOþšçF✞úÜÚëÎCÀ‰÷oî,£Àó_Z{½ãpø=›;‡gŸlSÌ1…øµ¿ÝÜyäaviŸ÷=‘Ø»s7$ɦÎÉðcza.ïû}]=XŸËV3,öUøƒu·U)•05Ñj0Á¨o.ûØD@~ï€e$ÿV©8pá[Àž·ß)lÏW~\úîúÛ,_~ð?O^8Ý ³p xå+eîD´ìö¼z+Ð}”\±· ~óD|›/ ÝKÌ9ˆÅ›/ ‡L¿ÌSë¶Œ€\uØa¶Yó¾ßÒl„©Ù¸‰3͢[^Èû~‡©µ,épcrlÝïÍ&bvi³K hÐê0Ô?€æF}És"â[_82Žî¾çˆWØv‹—ˆZ+ `#Oý5жxøq`ðþ›=±*¯#Ì«–M+«– Û÷èôƦ'ÀcðŒÛçÁ‹çÏ`[k;î-i…-æµ9æãV•a›ÉÊ5àK_¼ |HT©R&fÛ*ÒÅÜËeâõû ‡*¾ßd*‰³W.`T€p”J¤ XX-š—ñÂùWE‹ž´èOÜîx'¿C*Bn äZû7ÂoŒ= üÍ àŸ:6n¾U^—ÈerÄqúu<‡Óí,K,¶Ú+•J‘J&ËZñ¥) g.Ÿ‡Íéà}¿±^‡S; Mz¨”*ȤRP…h<†`(„•U3–,+ˆÅãœÏº½¼tá,î¹ãNȤ2Ásª H6ïú" ¨ªx-ÀìàÚËßã:£¬£ÀßÞ üŸk€²¶òs­²µI%‘˜ØT+L{‹ ó+KH§ÓôØÊªeÓ$[½n5´`ÅjF*g>Årmì:¯p¬Ñhph÷>èš8ï‰D"¨J¨Jè±§ã³S›™ÅZQû~œ»z '…H I¯ò¿Üë‰zpà×€÷x|‘¬>Ù8ç€ÿþøæÏ­Jqìypçï2ÿ޽¯ôý™o}ˆ‡+7ǤR MLah^µr„ÂFá 0ýmFSYû\´¬`fqž3Þj4á¾÷ð G>Äb1võöãÞc§ Ë9ï[6LÎÏžWuY)´-À‡¾ /¦—¿VSSÑÕc–ÞÎ휱p4oýdŽª€Ü(jšH‘\ü«7g.UnkØBÊ  Vü8›•.‰`j.]@ZìÜû¡Üp¡|ÔÕÔ¢®†‹\(Ï»* 7 * ¤SÌ1¶À¬R¥´ò•XE²@ú†&ÞXC¡ð H¾ïR)ø„¯ÕaãÙrÂ2÷‘QLèB¾g¯|V€b ÈJ¦¦Óüµ;7“­pü›=‡-€F¥†N[ÏcÇ*–K<‘€•åRÎj/™JrœI‰õuW#–XœòT*ų5!¿·8ÅüEà”ÀÙ,^¸ámŠ{‰;Vª€´Œ’Ú• åkDU…H$e)<ÜÜ ôœ Áè½w–7w>BnàÅ"ÇwÌöR¹Îè·Co!¥ð62ïÜo#s0ß spÌ’q­0ìö¾d6±C¬„²< $"äÿ"Ðu$ÿ¶¶i’Ï&ÆRm/²Ŧ5@ë`qseÑf41ìinŸáHjU‰…®YXíÜb­eØÝ^/'ë§A«T|¢TtZD"ã¸EÁð£¡^Çû™üRÄú·JqLüŠ;Ö¸MøçÓ)àÜ¿|°OñoCQ¤¬\Ä ¸‰ç€ŸÿÐy˜”\«DæNÄ<÷ðÜßQžrw^3ù›~øñcÀ½Þô)@YÁÊÎ!7ðôß/|‰?uÏ»Bþ&Ÿ~ø§À}Üÿ§€¬p¦ƒygι_Y'¯øÇŸ®|¿ð>Ÿðt»$hŠùh3špƒül¶Yx¥ÀVÙu ‚2Qòáöº9cÚÚº’÷'©D‚úZ-<~¦cÆã÷æùUìªæR:œýsL,¶öyÛ4ðé½À¿¿/¿p\… Àß¿xéËÅ6— xü0ðóÿË/Ù¤âÀ3Ÿ>¢r{Ï ð™}ÀÓŸ–לˆù>q¬¯j55S);d2•ĪÃÎ+×™ÂçDÒ¨v+(ƒ ·ú ”¿l[ád.B ë»m<|k·-`síǤHE.½'u=ÿö¹ÌœþáÍü‡E@×FÔØúV"‚NbΈ³~d* |ëä2ÑÞ‡ŠÿÑ ðÿl“Ìqeж‡êðÛˆÊÍžëÊ0ðù;?»hÊÈ ¹/ÞÇ5W¨u@ëùn>+°tˆ±JñϽüí]ÀŸœ­ìjv Óf41ŠH8Ý.Dc1(вö»ê°#År8–+ ùjIÖ¨7^hT\!\Çã_\.Ïâ%¢öþu@œ'÷2Î~½8ùÜÀmHY¨MǹüOË‚{?Vø³î%àŸæ upêÃÀÝá/Å–JW~@ª±C‰¾ýQ ÿtñBâë¿EìgYj À#Ÿö?¬—g¾F tä:ñ³ÀWß|ô—¥ÿ®ÿüvR©=‹®xä DàKs¼§Ñ ðÒ??ú$Ó1f¾üÇïúïÒŽ¿ÇÞ l?Îî fBÀÛ?W8z¡®ôL”\ÚŒ&ŒNOЯ)МîŽÎ²öË^‰êêêyM1ð Èr÷)5Ï1B‘üšIñÉŽ_øÑŸñBÄV¬zõÓOÕlß;ÖoMSi5£A`×¾»‹ÿl¹¸—z+f檢ëqbâ[¿YõðjôÀŸšºòN"½|ø0mcÞàê€;~[ø÷XºBVÁY:ð3 Ž§b‹\Üý@sðå·3Õà±gÈò”7ÏÓ/­½î»øÝ[‘²†ØõÛ¯þ:SP_þéÄ—ÙT»ßìæ¿ðM¦€<õû›¶‚ÕÖÖ¡F£A0Ge\±YÊ©tVV8N9Ι,ì ; Ù„d Ÿà™K–Ò²Á³†ùJ ¯}cí5Ÿ](¿ú;ௗÚÍ) ˜z ø—wV\•\ ¼÷ß ÷ÜqÌ7ždމ¥À‡´¾pÌE¥~ûkD½Ìý}.¯8ùô߬ý¿eð±§ ›vÝ|ìà §˜«¸?|WñB"wY]È ³ÿÀïÿøÒƒÌñïÿ10ôfæªó6¥Í`ÂÄÜ4ýÚît žH@.+-Ðît ‘L2Q¦zMQ'´F,U¤8E!øVÉT’gK‚±Ê÷•¸é$cÀõŸoüq(ŠÆ/ÞOì]lá(‘¿÷CÀØWx_×~Žg¬ÿ^ ‡G[e-ð«ßÔKüÛò±:\ή@EÀ£_f;È\½—9°‘z˜Å0´¬ÈCâ·¿&ÜF=ø°µZtÍ¿SÜnQØÂ+MQœ`1°ƒÃóe¤C2ÉHâMjY+ãyPðÍ'‹’-Z3·Üð¢dáRFErs爇úïþÄDcöfÎEk>öYY Á½È;ø®Òæ¹÷!@šc˜‰ú/„•kk+Àï'ml‹á-HYá/|©¸€î¥œÚÓL»Š›ÃCEZ¹<ÿÅâöq‹ÒP¯ƒZÉŒ},Õ›¦(XX©x­†òÕëÏŠM’ϧQa¤<ÇIS£uc{Æ”K9*n¹ÜÌcöÓE¥‰€‰…„eI•À‰oùsbGJ×Qà>VPヌ…>™hßÌŸ[³M yìÆ|¨´ÀÃ]ü±umäû¿økcŽY`þ|ñ¶Î¼ùÏ‹Ÿƒ±ŸØd/|smlé °:)l5‹Ój4aza–~½ê°#™JAZä*Íévr`µµ”Ÿ È·b“l’ƒ6_aßd* ¹˜k‚æ³™1‘"ÜÜàtïJñŸI€Ž}$‹ãè£Â›~årø=ä¯Rl;ÀÅëÝÿPÓXx;>ö=Ìpõ‡Å È#¿Qzø×¾‡™2;‡þ¬´ýÝB´±d*ªÃV´í]ÚL£RCW'Ðܲü*öæH±XÌɦ€d*9™V˜~]ͦYŸïŽþÐ}lë„*±ãÙq’…8ôîÒÝs‚¤Ïå¦ÝͼZü~•ñÀØyšØ/Ó97c)s¸iÒ5@)W0Ú˜W-E HŠ¢8ùÜ«´Ãã°¤Ò›· “ˆÅHrœDü÷í¹›oq^ùýçýİ ((X†ôxDøgk å…IIåÜϯ\'6„¢ï!«àRQi¹+Öåk¥ïïB$qBq,v[^;nŸ‘X”1V©J;|êôz#* _kZiúõÐÜD~ýŸù½¶Tš8i‚NÀ1Gr­},ã·}šG_ý! í‘W¦P@IpTÓ"„öàýù„Òu¸þ³µ×ñ±EV‹zsyÇÏÎ!wÕè³Çæ†Ý$ÚŒ&FµîD2»Ë£^XP:[½V*”hÌ“¯\,|™rúiEQ¼­qóÙg«’ÍÞ‡„ÛçÏ?ø_Ì€f€ÄFƒÀG~~óTî<*ƒ :ö—|c?wlåšp¹as&ê÷m޾¡ r™Œ½²j)B@2ãœÛŒÜŠ¥ÂjÃNeÜ(øVªÒu"y¶–Š-–’<ãÆÎµ¿RKWm]G€?~xÛ_qßý%I;»ißWþ>ø„“­ˆÂ·0b±&VHŽÙfå]=±ñú}…™éw­†Ê²•Ëd·F:æØ7¾•êz¹ê[c)‘‘ÛäWKý6’Þxöë›?7!<øI’^øì˜ã¿|8ù{Ÿjæ·ï{,Dþâ!²º-•ö½åÏIÏSfKhu©hÙysçpÐf4aae­ÐG,‡Óã*Øó…7)—É o¬\Ÿ‘H¹\Î ! …C^ò,žà†ê­WEhkÈîùÃüï×€Gÿ p-“/lÚ´ŠâmŸ!6·Üê7a7pá[ÀÉUæ‰(©ö3ù<`'ƒ³Ü"­å ×”–ÏF¦$™D¹±£ìõ|ÔèË·ÄQÃFèn zH¥RFXÍʪ¥hÙjh©x![µRÍÁMì•1hTùCɶ†Š}ä7 o#‘*B[™xÛ§¹ã—¿WÞ~=fà©Ï÷àtÀߟ~ùYàÚˆ=­’Âà*%ï‹u± N•šƒ\Íͨy­ % L,›£yuýB2Pþ ³tÜF4Òâ«Ë\§.c¥Exªmù¤®MØvõ·»Yì}ˆ„ÈäædϼBV~ÅV·v/‘êØ—¿ÇŒåÛh*) ÙYZQ¼’s)˜†Š½Åi3š°d]s¸„£¸½ž¼´Ù«G©TŠæ&ž*NeÂWû1®|'F6|+ÈõrË·†€‰¾ý**‚DF„ä+_YKÆHñ…'…ïçì7€ïü!·lµŽ8ˆtíÄüPgj›™Õjnüxõ«Å‡Jžã(kþB_¥æNq«WRøÞ› ˆÅ çÄŠÍ"X@šô† IÔñ4çb7ñÚBNú°‘«#¿ Üù!SHˆ˜‹(Xœ‹¶BH§¹RhuñJÍ!ÂÓ&B]F…ó[©D £ÞÀèÿ¼²jÁP·H8f4þ6®Ou£Ž›Æêöz‹ÇËj%[7«B._·PïÖ°AÞNì¸ œñôËÂ>{æküÂq÷›OO¿ù’]"d…%ÔÞ'f=#+Uþ.â'8]'Ðx£æÀwø îÞæ°…\0b´fÈ—ˆÅ06W¦Ú9•RÉL€U§ÿ  sTìB«­! ó©’lØ+’­H­he•šž?_8Íι|÷¸ã<|äg¤L1uF°Uΰ§2=Íùšå[A²çÀ®«Yò¦¹c¯³$˜š/4_ 4ö˜QoX7ˆº\Œz®msÕ^¡ßž«ƒ+|› „/m )´ˆÀ­Rl€Ýn5êç6¿bóâ?r'><ô™ÒæÀnÝvZe: 8çK;f.–1îX¾Rcì9D|$%°ì9Œ ŸÃmŒL&ã8ZØÞìh,§‡Ùç»R¹×ùh3¶rÆV6AÁ쥰hæöª7p@m ùß'+¨õ{†4fºØ~Œ;¶p!ÿö\ú.sL¦"±•¥2¿ÎñrQë¸*.ßÊ«X¬<©›ç¼ÄÁĦs` H±èâìzÒj0âò æd^µ ¯›äƳÕkC£¾ä>6B‹DènïÄø,Ó363Y‘Êå¹°+þ»5$@ÔKvÓ[•†vÒr!·ÚÏz+HvU €?X(O®¸í[™rø'À›þwéÇ7 ö\ õÖiÙÅÃ?%mnKeæUn‹rî-ŽB®€¾± v—“[ÉÈx"»‹ù@Ýhõ:KOg7&çg¥Ø<>/-+ØfªLܳ?À¢…¹‰DØÖZ¸ÂþÖP±oGºŽ0_¯\yú䄽ܱz®}Fóç‹ÏÞé<Ì|½x ð”PY= ߃®ÿÞõ?ÓÅšÃÔ‹üçE(çyæp3ªø[É}a«Ù.¯‘hû*Ãî'BezÏA¥P¢³µƒ3~ed‘h5LóL¥ðÚÕ‹»æ6S› >ÜU¹Q°‹µ¦â¤Ü|õ' 9uøðÛ€/¿ƒÔ®,¾Þ7g¿QüñR/“ ®¬#-Y׫a*Á/ä„à^&9ð¹h[€]÷—¶¿b`gUº=rðUä1Û¬œðž¦†Æu+ÜTšÝ}u>‘Là•‹ç‹—Þ|/•NãüðeÞ¦þí;í£* 7Š|vH>øV‹Bc'³]À??\Ú ©ß´±*ø<õ8àâé´Xˆïþ’¹ÿ¶¿mHy»\~úH¥¢bùæïq#Nþ6¥ƒ';”‰¯[åMB¥T¢±ž9¿ù•%ØÌК χB.ÇP?7pÝðá…s¯–”£OÄñÊÅ×8m# ¯«GpëÚª€Ü(¶àJÈg‡¬3p…ÃÜkÀ3_àÝœÃÌ«À§÷’Ï”Êþóu< |ç£ÅíãÆ/¸êµ²x€'øÓŸ`¾{€ïÿqqs8÷_Àṟ̑Úfî¾7 -K¸”’î¹°…ŸÇçåÔH¬díG¡t·w¢³«jûƒ<ýʯ01;%¨^d:ÆÌâž|ñYŽ]ëuØÝ7 x^U¹Q(4Ü€ñ…‹ù·ßÍÓbà‡ üè“ùSï¦_þõ=ÀîbvcTÕ“S1ù `ÛAæØõŸÿúnaE&^øGàËpÇú¬ð§> XqŠçÿøÏ’‚ëAQ¤êÑ¿¿ûÞ;ÿnãkrfÙ~óõØ3[*~·Í¸¾m±A«ƒZusZ…ÜË[ñ<•Nãúä~úÜ/q~ø2Í˰»ððú}XuØ1¿¼ˆs×.á'Ï=‰+£×•Ô³›šqlÿaˆ×É-O¥ÓˆÆÖÔú­ãžé>Ê´;Ú¦ˆãÏæø†O/™Y¹‡JU÷ì׉ӧ¹‡4ßr/«€c†»‰øðÈûÅ ¿ñeà '™ùÒwI˜Õ£ÿÆï‰vÌßûñ|³Ùû0p÷ŸƒDJæðÅ72³y^ý*y¸<úoü¼V'€o˜xŽûÞ±÷mn™¼7rë`>q/ð–¿îûnKŠ"anM]›2=Z]]=<~~X!º‘ˆÅbß—G®aÁ¼Ìy?™JbѼŒEž÷ ÑÒl€±É€¹åE$ Ä ÄqúßìX*‚D,Æ;î+€ª€ÜXºŽ¡GC1Ÿ7µ©‹¨¢¿øKî{þU~ÄF"Þ÷ï@ß]Å H€Ÿ|‡Ø2©uÆ6 |þ±UšM#ñÎ:fó;žzOïÿ¯âçÐwðè×€¯? FÔÞÊ0ðÙƒd…Ù2@ÜÃPnÉS˜c÷›ˆÀÝL´-D(ç,IÅIŽý“Erú¢aÀòUbƒ~ìÒ¦M±ÕØ’W@nVxO>$ ï9€F]®T¬WÕnƒµ„4F)TZ(\‰Ì…­ÄVȘ`{²â¨ÉnòæO‘›ýê‹?VË."Êm—°ç-À‡¾KÔZv±Ç,ù+ÄÁw¿õ¯¥eýM" ¿ýnA`Û¤0ÿ‰ïþf ¸Íâ‘/‹I°{.ñôìÑRCºJ¤ÍhÂÈÔ8g\[[W0³d³ØÞÑ…VC &f§1»4¿i]Ùˆ!?Nj ÞH•ÄþVNOåJaè#öÀ\Ö K€ßý>ðÖO“TC!Ô4‘•çc—*ÓK !9Ÿº‘ɦ)¢6£q'ð¡ïüvù6¿;~øÔu ïžÂÛæÒ¶øè“D@Ë6/T…²øø¯€£Þœã ®¦–׋»ÙÞëB(JìØ7Ý}íG‡©mCK¡ñ!¢²”é4IwÛ MïËAÓÀ-õŸ×"·0Ãöc•]u,^fV!RÔóoŸÅc^ùâ(1ßX³M*jHçGc?±­ ½…¾^ ³ƒŸ±¯´‘ÎySxýgä|ìkq–Ñ>vÜE„éàSÔØ6Eb"Gž$ö×€´ú-‘“sÑw0ôVR³Tæ/¬Ù_E"`Ç©rgNæ~öÀì²rÌ —ÈHÿ§€|+ï.Àð3bÕ*5oUn¡øƒDcLÇ—¶V[–r¸Œ€ìú:-ä²Ê ´d*…X<†X<žé·SY™%‰è2hk²J•*Uª0¨†ùT©R¥Jª²J•*UòPUªT©’‡ª€¬R¥J•›“¿ªÙf¹%¿W%°:l˜_^¿-@“®±l … T*!•H o|“I¥S˜˜#Õ­d2ÙMS ³™¨U*lï褯×ܹ$’ ìèÜ‘HŒe«ÉT’^ŒÏL!¢wÛvÔhÖê.úƒÌ,ÎÁð#¦ Q©Ðajg˜Ò…¹¥¸<.„"ÔÕÔb[k{F[)“ÁˆÉ¹i¸¼n„"aN³{·Ï‹`(•RµîuOÄ1³8Ï‹x"V‹ÞmÝаjJ:ÜNÌ--"A,¡F­AOg7tuÄÌ’J¥°h^†Ù¾ŠX, ¹LŽºÚ:ìÞ±’œkßê°aae áH‰º:-úº{9vCŠ¢0·¼‹m‰d-ÍìèÜŽ±™I$SIôoßUÆ´Å0>; ‰XÂhëõû0¿²µR¾î¬:ì˜]šG,Gc½½ýI™²"Ncj~6—EŠwµuÐ÷òPß.H$" ³ö …\ž×ð©+ T(Eö_Àé…9èš0·¼ˆ@0©T‚hÌ ‹}áp;{Öšt;Ü.œ¹|ñD ¹EÁæ´cae ÷; uæð‡˜^˜C“®b±—G†ûð¸ó OK†úwáì• H¥RxáÜ+èïîÅΞyl<ÇÙ+`ÏxUJœ7ÌËX4¯àø#ôyJ¥Ó˜^˜@ì›È¹HÜ>/¦æÐÙÚÎK3<~/ëpáúxý>è´kv¾¹¥\F𢠔+H%as:0·´ˆ7Þy7](utz‚V_Õ*5Ü^7–­fX6?pDй)†d*E׎–6¼|ñ,G‚Ëã†ÙfŃw½‘nŸÝ–þ^Ë ôÿ{¶uC©PÀávâÌåóÜëÁ¼„{‚:ó@ð×®3±XD_]í¤U¨ÝåÀÌâ<âñ. #Nƒ¢(¸2çäø# õlnyÑXF½WF†Š„ÑÒ¼&äÌK„‚h5˜hét»ðÒ…3H¥ÓP*”‹DpyÝJe´€L$“xõÒ98ÜNˆÅb(J8=.Ì//àÀî}ènßVÔ9—Š¥0Z°dYÁ’e;Y ï—,˙ߣùª¿ûƒ¼rñ5„"aȤRHÄ8ÜNÌ//âÔáãh¨× NÚ¬B£V#™LÁáv¡¡¾ººz¤) g.ŸÇªÓ±X J 0€U§=;h™{]*ä $’ Ø],YWpÿÉÓ auyäæ2NBµR…“cpº]py݈'ènï¤d"‘Àô¤R)C@BAL/ÌA§­‡\.ÇÅëk­.œ<~î:²ÖpŽ¢(¼zùVvú¸WF‡áòºé†`ƒ½;×d¶Eb¡0µ’Èx"Îy<½›ðÖÓ@*‘àÚø LÍÏbtz]íÛ T(@Q.\C<‘À¡ÝûÐÕ¾ iŠÂµ±ë˜YœÇØÌîf¶ ˆÅc¸6>£¾­pû<˜šŸ…Õ¾J‡!¢ÍhÂѽqiä’É$Æg§°`^Æžƒ™ ‹ÉÈÔ8ì.'jÔœ:r•áH/^8—דc84´¯àq 163 0£¾™^¹G¢Q\»Ž4EáÀà^lïèD<dz¯¾ˆP$Œ‘©qÝ{^¿£ÓPʸûŽ;Q«©A4Å‹çÏÀl³Âæ´ÃÐÔ,x.nŸÏy‰3.‘Hp÷Ñœñ+£×!—˱§( žH`ÙjÆöŽNˆD"<ô†‘J¥ñ³çŸ‚H4S³±  vr~©t=}ܱ¹>ƒá5»ßÌÂn'ŒzŽí? ©D»Ë‰—.œÁõ‰Qt´´B*-ÎÔÓajãEaÙb¦·ÉmWÊøŽ#EÂèéÃ@o?Ä"&ç¦1<1Šë“c´ð›!½~N8Sæa ‡èp#σU§j¥ §Ÿ‚R¡EQp¸dº5&S)z?{wîFog7É$ž;ó"‚á–-+èÎDŒ¸½Z8ÛmFBá^8÷*oÛÖBÄq\»ŽæŒå ø01K4Ú@0Hk7æU VvˆD"Ü}ôN4éàõûðÂ9n{^1ùRd )àaeÁY5k5OHS>’É$Ü>ï¡H÷ÜqÝØÞÑ…¶ÌƒÆ\k/!—É!“­ ™T¹L¹L‘HD.ÜPõuZ¨U*r=x\hÔå¿B‘0ôM¸ïÄ=8¸{/½ÂÌ"•H°wç D"Äb1Ý$> ó~—`8„“‡áÄÁ£èâi\ŸK8säöUVÈh̬À`f‰´ðèlë€ÛëÎ4¯§P«©A</ÉÛllj†\&ƒ/àgœ_‡Û‰H,ŠZM CaÌ9†ÕnƒB.Gscœn'ì.êë´p¸H§ÓH§ÓtKQÎ÷«Qkè¯H”´hHSiZVˆD"47êé×Éd;·ïÀ®Þ~tg”r™ í™ë#ñu cëë´t?Zƒ¡SS1„Âahkëpêð1l3µa¨o}ÿúCkçmyÕhi6Ò÷K}–¡éf‘kÎ‹ÜøG>Ò™^$|O@µRmíZ/©D mmÜ>/ý£Cääø~¼xþ gáHiŠ‚˜õ”ê`<ù• ¢±(-Ø…¢T(qhhº;:qetŸ6§Ï} ÷Üq’V²Ôš˜±gúÆÆÌy à ø T_¡ñÑܨ§K–ì¹bÛ“öôb¨/W­ çrzqÓ‹LU v½bhÒ5àŽý‡9ã¢Þë! ƒ¢(ΪoïÎÁ¼s}Cãú¬¯ÓB"‘ •JÁÐã,íÆVŽ}2-z<>/F¦ÆE±«w'ÃNšJ¥è‡í¹«y÷Œ„Єâl‘b±mÆVÌ-/`ɲB¯^³Ž›õœ3Ùs‹ÇyÏ1„#Ôh404éaµÛpæòyìÞ±=ÛºçYßЉD‚h,†gϼˆ»öp´¥BIÏÜëÕIPhÒ1χ±IØïÁÇà–¬P*Š„é˜Rtbû365ã:FcRôœ}Bä#ûã+26¦\ØÆ^Pdìt±QÉcqòoK³{úùŸìÛQ!WÐ6’JÑX¯Ãéc§pcr sÓˆD£¸6>‚ãûÓßQ,sR‰r™ ñDBP8E¡N C,»Ja …ÜU úi¿o`ž ªX5N,–0^!LÍåÇÂf¯S³‘aSÊ…}Ô*õºAë¼×¡LŽp*Âhz•Ũþèéƒ/à‡ÙfÅÌâ<Í+Ø;0Hk%±ÓÓ}wÞÃë(+5­ÃÔÆét+™•PGK~™=ÇÚÚ:ܱ¿²JEVᇇöãÅógà ø1<1Š™¥yÚ½ŸRWÈå8¾ÿ0Î^¹€`(„—.œ…ÉЂƒ{8׎?À²Õ Ï‹H,ŠP˜{¿d¶ßC.“C*‘ Yàþa#“J9¢ÙãÊ™ÇU«¸D¥P_«Å²ÕŒx"ž7 5‹Ñje}w9Ïë4Í80ÅÏ¥RIöÇgfhÔ%öV.€H$ÂPÿ.8=.8=nØvâq-àýÍ^ôùVV¹äªC|ð9IJ?Z!¬R(á…i*}SÒ+ñ»d¯³xBøõP({b½_E,æ®:‹Xb±ÇÁ‚yÃã#ˆÅc¸xý*"Ñ(zú7œD,ax¿ËEßЕB‰`8·×“ñ$ ««§mk|(ip´à9VÈ8}ü.LÎMc|f¡p/]8ƒãûÐ&£Þ€ûOÞ‹+£×a±¯Âb³ÂðáÞ;NÒǺ19†‰Ù)P ‚¹A«ƒ€ÛÇô]dï%vßÀ4E•Ô[­R ŠÞÈnÁîVÈ'ÅД#u­™ j6VÇ*ýÿ¦n8ßê3+©³O—¬=Àíó"‰p¶çc£#æ³*W:Bš¢ Îñt:ËPœL%é'2Ÿ€Èý¡“ÏózHÄÜï–]¹Ù¨k€B®@š¢02U™l‡ËÁ0mxü>z5§ù”ŠL&Ãá= —ÉA„!@[æw™šŸÉ{Ý•JV•^²¬Àb#¿yû:ê5@ÔÆìý—[£µG÷þíP×\ÔjhAÿö^kÂÅž¹g²±Ÿ15ñ-¼²Î-›ËtŽ@̆ÚlZrÜl˜}Ü•%ζ´ÈÝ»s7D 6°_}æU Á Ì«üêìËGÂŒ`f6—F†‘H&2OQ¤ÓiÈer3†\‰DB'Ñ/¬,áüµK 5´XÇ‚P^ºp/_8‹ù•E8=.„"a8Ü.¼võ"‡µ#ÉerÚ{|uìíu …C¸6Nž¤ÛÛ;é]±XL¯æ®ŽÝÀÜÒÎ_ÆÄì4Çø,„&]#møŸÂ¥Wé'jö745Ó¶Ù³—ÏcfqŽ6¤R)Dм9#ÑæWyÿÊÉó•ˆ%ôCd‘• "͹æWq~ø2}=PUÒõO$pm|étÉTÙ߬±^W¶Ê»²jaØ1»£¶†8(ûº{!‰Åð«³/Ãæ´ÓÂ…8‹³«åÒP¯CZƒh,†T:…&]#¯ÝŒÍ@OÀîrâ勯ÁãóÒ×SÖ‰“L¥°²j¡ŸEÁ’Ñk4H$xý>¸½ú³$¾‘,²ZYÆ?‹Ç‹Ç‘H&pñÆUÚ¶žKV€†#a\†×ïÃôÂf–æ+¢¡ä£3­àòº125N‡ÌYܨ Ú’oÔ7ãàÐ~\»0€3W.07”J±o`(o¦Mc}‚¡ ~ü쓈Åô…°×ÃÖÛÕƒX<މ¹i,Zˆª@bâHh˽ÇN•XP…U§«èXÂ¥»£“Ì?',*¹LŽ;Þ³Í ·×oÀ‘HµR‰ýš÷X¥Táî#'°²j×ïƒ/³F¥Fs“°]­ÍÆ‚Þë¬gP*•Ы¶m¸¹Q‘H„[ÓÝûP¯­‡ÓãF2™€R¾v<±H„=;ÑjhÃí‚×ïE"™„R¡dx˜ëë2×—:—µCÇ05?‹p$Œ=Ûº9×J_WÉ'Ž2K϶nÄâ1†­ypÇN8=.„£P më0qÄ Mz¼ñÄ=°Ø­ðú}†CIe¨«©åxNó±sû¤R)ÈY÷\WN&N;+D¬F£Á@OmÛË¥·³ú†FØœx>DcQF §L*ÅÞ»áõ“÷Äb1j4tµm£W‡Íz ôô! žL IÖˆ­]í´FU£Öà ÇïÆÔÂ,BáÔ*5z;»Å ÓÖs¬úºz`hÔÃáv `ÔP«©¡Sþr‘Ëåèéã„xÕÕÔb §“4ÍÐШg„ Dcn3¶ÂíuC,–ÀÔldF~dnqUŠ54‡Ù¥y\†¡©§+gWUª”Ì•ÑaÌ,ÎcGWϺf *[ŸD2‰=ósÀÛN?¸î¬’ø~<ýÊóJ$xøo&+ìM9r•*Uª$¯T(7M8æ·®¶ŽÖ«õ¿ªT©rSX²¬`ÙjF«Ñ„:M ’©$nÆg§½Ûøë_–Ëäü ¼~Zš¨QkHÄauØ05?Ë9nU@V©R妦(˜mV˜mÌX^±XŒÞmÝtQÅ›JÓÁ\¤)ú·÷2*o•mƒôø½XuØ¡Qkx+ãT©²¬:ì™r:Á¹ÕUn.©T ^¿þP‰L =i¢W¿¡ ɼ~¡ É$¤)Ô*ëuœÿ×”ÍUIEND®B`‚././@LongLink0000000000000000000000000000014500000000000011565 Lustar rootrootrabbitmq-server-3.2.4/plugins-src/rabbitmq-jsonrpc-channel-examples/priv/www-examples/img/listBg.gifrabbitmq-server-3.2.4/plugins-src/rabbitmq-jsonrpc-channel-examples/priv/www-examples/img/listBg.gif0000644000000000000000000000244712305126066032407 0ustar rootrootGIF89al2³ñññþþþðððýýýÿÿÿôôôòòòõõõóóóûûûöööùùùúúúøøøüüü÷÷÷!ù,l2@ÿŒc„½8ëÍ»ÿ`(Ždižhª®lë¾p,Ït=Ç@ì|ïÿ† pH,ȤrÉl:ŸÐ¨tJ­Z¯Ø¬vËíz¿à0ñG&Îè´zÍn»ßð¸|N¯Ûïø¼~Ïïûÿ€‚ƒ„…†‡jeŠ<Ž‘’“”•–—˜™š›œžŸ ¡¢£¤¥¦§¨©ª«¬­‹‹ ²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒµ°ŠרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷ÚÕúûüýþÿ H° Áƒ*\Ȱ¡Ã‡#J䠢ŋ3jÜȱ£Ç ÿCŠI²¤É“(Sª\ɲ¥Ë—0cÊœI³&Æ€rêÜɳ§ÏŸ@ƒ J´¨Ñ£H“*]Ê´©Ó§P£JJµªÕ«X³ò ¨ «×¯`ÊK¶¬Ù³hÓª]˶­Û·pãÊK·®Ý»xóêÝË·/Ø€  L¸°áÈ+^̸±ãÇ#KžL¹²å˘3kÞ̹³çÏ C˜ ´éÓ¨S«^ͺµë×°cËžM»¶íÛ¸sëÞÍ»·ïßÀƒ N¼8ꀒ+_μ¹óçУKŸN½ºõëØ³kßν»÷ïàËO¾¼ùóèÓ3XÀ†û÷ðãËŸO¿¾ýûøóëŸQ  Íÿ(àÿ€hà&¨à‚&$ƃF(á„Vhá…f¨á†R°‡È‡ †(âˆ$–hâ‰(¦¨âŠwtÀ‹0Æ(ãŒ4Öhã8æ¨ãŽ<öèã@)äDiä‘H&©ä’L6éä“2rå×”TViå•Xf©å–\véå—mÔÀ˜d–iæ™h¦©æšl¶éæ›pÆ)çœtÖiçxæ©çž|öé矀*è f&Ú¡ˆ&ªè¢Œ6êè£F*餑‘fÜ¥˜fªé¦œvêé§ †*ꨵäÀ©¨¦ªêª¬¶êê«°Æ*무Öjë­¸æªë®¼öêë¯À+ì°Äk챪„ϲÌ6ëìÿ³ÐF+í´ÔVkíµè §Þ¶Üvëí·à†+î¸ä–kî¹Ù) À~ì¶ëî»ðÆ+ï¼ôÖ:dï¾üöëï¿,p þ1hðÁ'¬ð 7ìðÃ7ñÄWlñÅg¬ñJrèñÇ ‡,òÈ$—lòÉc¤ÕÊ,·ìòË0Ç,óÌ4×lóÍJá„óÎ<÷ìóÏ@-ôÐDo‹H'­ôÒL7íôÓPG½†‹PVmõÕXg­õÖ\wíõ×`‡ý#Õb—möÙh§­öÚl·ívŒR‚)÷Üt×m÷Ýxç­÷Þ_äÊ߀.øà„nøáˆ'®øâžˆIèãG.ùä”Wnùå˜g®ùÔæs:Îùç ‡.ú褗nú騗i(¥¬·îúë°Ç.ûì´×>X@Óä®ûî¼÷îûïÀ/üðÄ? îÆ'¯üòÌ7ïüóÐG/=5‘jýõØg¯ýöÜwïý÷©™Šìøä—oþù觯þúì·ïþû·Šÿüô×oÿýøç¯ÿþü§ª,¶  HÀð€L`>‚®:ðŒ 'HÁ Z°9Úº 7ÈÁzðƒ aw&Bšð„(L¡ WȺð…0Œ¡ gHÃÚð†8Ì¡w¸ˆ;rabbitmq-server-3.2.4/plugins-src/rabbitmq-jsonrpc-channel-examples/priv/www-examples/img/li.gif0000644000000000000000000000006112305126066031555 0ustar rootrootGIF89a€fffÿÿÿ!ù,@†hº}B;rabbitmq-server-3.2.4/plugins-src/rabbitmq-jsonrpc-channel-examples/priv/www-examples/chat/0000755000000000000000000000000012305126066030630 5ustar rootroot././@LongLink0000000000000000000000000000014600000000000011566 Lustar rootrootrabbitmq-server-3.2.4/plugins-src/rabbitmq-jsonrpc-channel-examples/priv/www-examples/chat/index.htmlrabbitmq-server-3.2.4/plugins-src/rabbitmq-jsonrpc-channel-examples/priv/www-examples/chat/index.htm0000644000000000000000000000453612305126066032461 0ustar rootroot Rabbit Chat

    Rabbit Chat

    Channel:
    Name:
    
      
    
    rabbitmq-server-3.2.4/plugins-src/rabbitmq-jsonrpc-channel-examples/priv/www-examples/chat/chat.css0000644000000000000000000000027612305126066032266 0ustar  rootrootbody {
    	background: white;
    }
    
    .nick {
    	color: red;
    }
    
    span.nick {
    	padding-right: 0.5em;
    }
    
    .utterance .message {
    	color: blue;
    }
    
    #chatOutput {
    	border: solid black 2px;
    	padding: 0.5em;
    }
    rabbitmq-server-3.2.4/plugins-src/rabbitmq-jsonrpc-channel-examples/priv/www-examples/chat/chat.js0000644000000000000000000000611412305126066032107 0ustar  rootrootvar channel;
    var queueName = null;
    
    function mkElement(name, cls) {
        var e = document.createElement(name);
        e.className = cls;
        return e;
    }
    
    function mkSpan(cls, content) {
        var node = mkElement("span", cls);
        node.appendChild(document.createTextNode(content));
        return node;
    }
    
    var mimeTypeHandlers = {
        "text/plain": function(delivery) {
    	var utterance = mkElement("div", "utterance");
    	utterance.appendChild(mkSpan("nick", delivery.routing_key));
    	utterance.appendChild(mkSpan("message", delivery.content));
    	$("chatOutput").appendChild(utterance);
        },
    
        "application/json": function(delivery) {
    	var parsedMessage = JSON.parse(delivery.content);
        }
    };
    
    function initUsername() {
        var username = document.location.search.match(/username=([^&]+)/);
        if (username) {
    	username = username[1].replace(/\+/g, " ");
    	username = unescape(username);
        }
    
        if (username) {
    	return username;
        } else {
    	return "user" + Math.floor(Math.random() * 1e10);
        }
    }
    
    function chatMain() {
        log("Starting.");
    
        $("userName").value = initUsername();
        $("chatMessage").focus();
    
        RabbitMQ.openChannel(function (c) {
    			     channel = c;
    			     change_channel();
    			 },
    			 { debug: true,
    			   debugLogger: log });
    }
    
    function change_channel() {
        log("change_channel: " + $("channelName").value);
        channel.exchangeDeclare($("channelName").value, "fanout")
        .addCallback(on_exchange_declared);
    
        function on_exchange_declared() {
    	log("on_exchange_declared");
    	if (queueName != null) {
    	    channel.queueDelete(queueName)
    	    .addCallback(function (messageCount) {
    			     log("queue deleted");
    			     declare_fresh_queue();
    			 });
    
    	    queueName = null;
    	} else {
    	    declare_fresh_queue();
    	}
        }
    
        function declare_fresh_queue() {
    	log("declare_fresh_queue");
    	channel.queueDeclare().addCallback(on_queue_declared);
        }
    
        function on_queue_declared(newQueueName) {
    	log("on_queue_declared");
    	queueName = newQueueName;
    	channel.queueBind(queueName, $("channelName").value).addCallback(on_queue_bound);
        }
    
        function on_queue_bound() {
    	log("on_queue_bound");
    	$("chatOutput").innerHTML = "";
    	channel.basicConsume(queueName,
    			     {
    				 deliver: function(delivery) {
    				     var mimeType = delivery.props.content_type;
    				     if (mimeType == null) {
    					 mimeType = "text/plain";
    				     }
    				     var handler = mimeTypeHandlers[mimeType];
    				     if (handler != null) {
    					 handler(delivery);
    				     } else {
    					 log({props: delivery.props, unhandled: delivery.content});
    				     }
    				 }
    			     },
    			     { no_ack: true });
        }
    }
    
    function send_chat() {
        channel.basicPublish($("channelName").value, $("userName").value,
    			 $("chatMessage").value,
    			 { content_type: "text/plain" });
        $("chatMessage").value = "";
    }
    
    function log() {
        $A(arguments).each(function (arg) {
    			   if (typeof(arg) == 'string') {
    			       $("testOutput").appendChild(document.createTextNode(arg + "\n"));
    			   } else {
    			       $("testOutput").appendChild(document
    							   .createTextNode(JSON.stringify(arg) +
    									   "\n"));
    			   }
    		       });
    }
    rabbitmq-server-3.2.4/plugins-src/rabbitmq-jsonrpc-channel-examples/priv/www-examples/rabbit.css0000644000000000000000000000574312305126066031677 0ustar  rootrootbody, table {
    	font: 12px/15px Verdana, sans-serif;
    	color: #333 !important;
    	background-color: #fff;
    }
    
    body {
    	margin: 40px 0;
    }
    
    div#outerContainer {
    	text-align: left;
    	clear: both;
    	margin: 0 auto;
    	width: 770px;
    	padding: 16px 0 0 0;
    }
    	
    :link {
    	color: #f60;
    	text-decoration: underline;
    	}
    
    :visited {
    	color: #c40;        
    }
    
    :link img, :visited img {
    	border: 0;
    	}
    	
    
    a:hover {
    	text-decoration: none;
    	}
    	
    h1, h2, h3 {
    	color: #f60;
    	font-family: Helvetica, Arial, sans-serif;
    	margin: 0;
    	padding: 0 ;
    	}
    
    h1 {
    	margin: 0;
    	float: left;
    	}
    
    h2 a {
    	color: #f60;
    	}
    
    h2 {
    	font-size: 18px;
    	line-height: 18px;
    	}
    
    h3 {
    	font-size: 14px;
    	line-height: 14px;
    	}
    	
    .col {
    	float: left;
    	width: 49.5%;
    	background: url(img/listBg.gif) Repeat-X top right;
    	margin: 0.5ex 0 4ex 0;
    	padding: 0;
    	}
    
    .columnLeft {
    	float: left;
    }
    .columnRight {
    	float: right;
    }
    	
    .col h3 {
    	background: url(img/listBg.gif) Repeat-X top left;
    	margin: 0 25px 0 0;
    	padding: 10px;
    }
    
    ul {
    	margin: 0;
    	padding: 0 2em 0 0 ;
    	}
    	
    li {
    	list-style-type: none; 
    	background: url(img/li.gif) no-repeat 1px 12px;
    	margin: 0;
    	padding: 1ex 1em;
    	border-bottom: #e4e4e4 1px solid;
    	}
    	
    p {
    	clear:left;
    	}
    	
    .logos {
    	text-align: center;
    	margin-top: 3ex;
    	}
    .logos img {
    	padding: 0 20px;}
    .intro {
         font-weight: bold;
    }
    
    .clear {
    	clear:left;
    }
    
    .document h2, h3 {
      margin-top: 1em;
    }
    .document li {
      border: none;
    }
    
    ul.mainNav {
    	text-align: right;
    	margin: 1em 0 0 0;
    	padding: 4px 0 0 0;
    	height: 20px;
    	float: right:
    	clear: both;
    }
    .mainNav li {
    	display: inline;
    	border: none;
    	background: white;
    	padding: 0;
    	margin: 1px;
    	text-decoration: none;
    }
    .mainNav :link, .mainNav :visited {
    	color: #a9b5af;
    	text-decoration: none;
    }
    .mainNav :hover, .mainNav :active {
    	color: #a9b5af;
    	text-decoration: underline;
    }
    
    hr {
    	clear: both;
    	visibility: hidden;
    }
    
    .compact li {
    	padding-bottom: 0em;
    }
    .compact {
    	padding-bottom: 1ex;
    }
    
    .docToc {
    	border: #e4e4e4 1px solid;
    	padding: 1em;
    }
    
    .docToc h1, .docToc h2, .docToc h3 {
    	margin: 0em;
    }
    
    .faqHeading {
    	border-top: #e4e4e4 1px solid;
    	margin-top: 1em;
    	padding-top: 1em;
    	color: #f60;
    	font-weight: bold;
    }
    
    .faqQuestion {
    	font-style: italic;
    }
    
    .faqAnswer {
    	margin-left: 0em;
    }
    
    .sourcecode {
    	padding: 1em;
    	border: #e4e4e4 1px solid;
    	background: #efd2bf;
    }
    .sourcecode i {
    	color: darkred;
    }
    .sourcecode b {
    	color: darkcyan;
    }
    
    table {
    	width: 100%;
    	border: #e4e4e4 1px solid;
    }
    th {
    	border-bottom: #e4e4e4 1px solid;
    }
    th, td {
    	text-align: left;
    	padding-left: 0.5em;
    	padding-right: 0.5em;
    }
    
    .amqpRules th, .amqpRules td {
    	vertical-align: top;
    }
    .amqpRules .notes {
    	font-style: italic;
    }
    .amqpRules .notes .leader {
    	font-weight: bold;
    }
    .amqpRules .statusCell {
    	background: #ccc;
    }
    .amqpRules .status_ok			{background: #0c0;}
    .amqpRules .status_planned		{background: #cf0;}
    .amqpRules .status_partial		{background: #cf0;}
    .amqpRules .status_unsupported		{background: #fc0;}
    .amqpRules .status_failing		{background: #c00; color: white;}
    
    .platformHighlight {
    	background: #ff0;
    }
    rabbitmq-server-3.2.4/plugins-src/rabbitmq-jsonrpc-channel-examples/src/0000755000000000000000000000000012305126066025060 5ustar  rootroot././@LongLink0000000000000000000000000000016200000000000011564 Lustar  rootrootrabbitmq-server-3.2.4/plugins-src/rabbitmq-jsonrpc-channel-examples/src/rabbitmq_jsonrpc_channel_examples.app.srcrabbitmq-server-3.2.4/plugins-src/rabbitmq-jsonrpc-channel-examples/src/rabbitmq_jsonrpc_channel_exa0000644000000000000000000000043012305126066032664 0ustar  rootroot{application, rabbitmq_jsonrpc_channel_examples,
     [{description, "rabbit_jsonrpc_channel_examples"},
      {vsn, "0.01"},
      {modules, []},
      {registered, []},
      {mod, {rabbit_jsonrpc_channel_test_app, []}},
      {env, []},
      {applications, [kernel, stdlib, rabbitmq_jsonrpc_channel]}]}.
    ././@LongLink0000000000000000000000000000015400000000000011565 Lustar  rootrootrabbitmq-server-3.2.4/plugins-src/rabbitmq-jsonrpc-channel-examples/src/rabbit_jsonrpc_channel_test_app.erlrabbitmq-server-3.2.4/plugins-src/rabbitmq-jsonrpc-channel-examples/src/rabbit_jsonrpc_channel_test_0000644000000000000000000000303012305126066032666 0ustar  rootroot%% The contents of this file are subject to the Mozilla Public License
    %% Version 1.1 (the "License"); you may not use this file except in
    %% compliance with the License. You may obtain a copy of the License
    %% at http://www.mozilla.org/MPL/
    %%
    %% Software distributed under the License is distributed on an "AS IS"
    %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
    %% the License for the specific language governing rights and
    %% limitations under the License.
    %%
    %% The Original Code is RabbitMQ.
    %%
    %% The Initial Developer of the Original Code is GoPivotal, Inc.
    %% Copyright (c) 2007-2013 GoPivotal, Inc.  All rights reserved.
    %%
    
    -module(rabbit_jsonrpc_channel_test_app).
    
    -behaviour(application).
    -export([start/2,stop/1]).
    
    %% Dummy supervisor - see Ulf Wiger's comment at
    %% http://erlang.2086793.n4.nabble.com/initializing-library-applications-without-processes-td2094473.html
    -behaviour(supervisor).
    -export([init/1]).
    
    start(_Type, _StartArgs) ->
        {ok, _} = rabbit_web_dispatch:register_static_context(jsonrpc_examples,
                                                          rabbit_jsonrpc:listener(),
                                                          "rpc-examples", ?MODULE,
                                                          "priv/www-examples",
                                                          "JSON-RPC: examples"),
        supervisor:start_link({local, ?MODULE}, ?MODULE, []).
    
    stop(_State) ->
        rabbit_web_dispatch:unregister_context(jsonrpc_examples),
        ok.
    
    init([]) -> {ok, {{one_for_one, 3, 10}, []}}.
    rabbitmq-server-3.2.4/plugins-src/rabbitmq-jsonrpc-channel-examples/.srcdist_done0000644000000000000000000000000012305126066026740 0ustar  rootrootrabbitmq-server-3.2.4/plugins-src/rabbitmq-jsonrpc-channel-examples/Makefile0000644000000000000000000000002712305126066025730 0ustar  rootrootinclude ../umbrella.mk
    rabbitmq-server-3.2.4/plugins-src/rabbitmq-jsonrpc-channel-examples/ebin/0000755000000000000000000000000012305126066025206 5ustar  rootrootrabbitmq-server-3.2.4/plugins-src/rabbitmq-jsonrpc-channel-examples/package.mk0000644000000000000000000000021312305126066026211 0ustar  rootrootRELEASABLE:=true
    DEPS:=rabbitmq-server rabbitmq-jsonrpc-channel
    
    define construct_app_commands
    	cp -r $(PACKAGE_DIR)/priv $(APP_DIR)
    endef
    rabbitmq-server-3.2.4/plugins-src/rabbitmq-auth-backend-ldap/0000755000000000000000000000000012305126066022635 5ustar  rootrootrabbitmq-server-3.2.4/plugins-src/rabbitmq-auth-backend-ldap/src/0000755000000000000000000000000012305126066023424 5ustar  rootrootrabbitmq-server-3.2.4/plugins-src/rabbitmq-auth-backend-ldap/src/rabbitmq_auth_backend_ldap.app.src0000644000000000000000000000144112305126066032205 0ustar  rootroot%% -*- erlang -*-
    {application, rabbitmq_auth_backend_ldap,
     [{description, "RabbitMQ LDAP Authentication Backend"},
      {vsn, "%%VSN%%"},
      {modules, []},
      {registered, []},
      {mod, {rabbit_auth_backend_ldap_app, []}},
      {env, [ {servers,               undefined},
              {user_dn_pattern,       "${username}"},
              {dn_lookup_attribute,   none},
              {dn_lookup_base,        none},
              {other_bind,            as_user},
              {vhost_access_query,    {constant, true}},
              {resource_access_query, {constant, true}},
              {tag_queries,           [{administrator, {constant, false}}]},
              {use_ssl,               false},
              {port,                  389},
              {log,                   false} ] },
      {applications, [kernel, stdlib, eldap, rabbit]}]}.
    rabbitmq-server-3.2.4/plugins-src/rabbitmq-auth-backend-ldap/src/rabbit_auth_backend_ldap.erl0000644000000000000000000003153212305126066031067 0ustar  rootroot%% The contents of this file are subject to the Mozilla Public License
    %% Version 1.1 (the "License"); you may not use this file except in
    %% compliance with the License. You may obtain a copy of the License
    %% at http://www.mozilla.org/MPL/
    %%
    %% Software distributed under the License is distributed on an "AS IS"
    %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
    %% the License for the specific language governing rights and
    %% limitations under the License.
    %%
    %% The Original Code is RabbitMQ.
    %%
    %% The Initial Developer of the Original Code is GoPivotal, Inc.
    %% Copyright (c) 2007-2013 GoPivotal, Inc.  All rights reserved.
    %%
    
    -module(rabbit_auth_backend_ldap).
    
    %% Connect to an LDAP server for authentication and authorisation
    
    -include_lib("eldap/include/eldap.hrl").
    -include_lib("rabbit_common/include/rabbit.hrl").
    
    -behaviour(rabbit_auth_backend).
    
    -export([description/0]).
    -export([check_user_login/2, check_vhost_access/2, check_resource_access/3]).
    
    -define(L(F, A),  log("LDAP "         ++ F, A)).
    -define(L1(F, A), log("    LDAP "     ++ F, A)).
    -define(L2(F, A), log("        LDAP " ++ F, A)).
    
    -import(rabbit_misc, [pget/2]).
    
    -record(impl, { user_dn, password }).
    
    %%--------------------------------------------------------------------
    
    description() ->
        [{name, <<"LDAP">>},
         {description, <<"LDAP authentication / authorisation">>}].
    
    %%--------------------------------------------------------------------
    
    check_user_login(Username, []) ->
        %% Without password, e.g. EXTERNAL
        ?L("CHECK: passwordless login for ~s", [Username]),
        R = with_ldap(creds(none),
                      fun(LDAP) -> do_login(Username, none, LDAP) end),
        ?L("DECISION: passwordless login for ~s: ~p",
           [Username, log_result(R)]),
        R;
    
    check_user_login(Username, [{password, Password}]) ->
        ?L("CHECK: login for ~s", [Username]),
        R = with_ldap({fill_user_dn_pattern(Username), Password},
                      fun(LDAP) -> do_login(Username, Password, LDAP) end),
        ?L("DECISION: login for ~s: ~p", [Username, log_result(R)]),
        R;
    
    check_user_login(Username, AuthProps) ->
        exit({unknown_auth_props, Username, AuthProps}).
    
    check_vhost_access(User = #user{username = Username,
                                    impl     = #impl{user_dn = UserDN}}, VHost) ->
        Args = [{username, Username},
                {user_dn,  UserDN},
                {vhost,    VHost}],
        ?L("CHECK: ~s for ~s", [log_vhost(Args), log_user(User)]),
        R = evaluate_ldap(env(vhost_access_query), Args, User),
        ?L("DECISION: ~s for ~s: ~p",
           [log_vhost(Args), log_user(User), log_result(R)]),
        R.
    
    check_resource_access(User = #user{username = Username,
                                       impl     = #impl{user_dn = UserDN}},
                          #resource{virtual_host = VHost, kind = Type, name = Name},
                          Permission) ->
        Args = [{username,   Username},
                {user_dn,    UserDN},
                {vhost,      VHost},
                {resource,   Type},
                {name,       Name},
                {permission, Permission}],
        ?L("CHECK: ~s for ~s", [log_resource(Args), log_user(User)]),
        R = evaluate_ldap(env(resource_access_query), Args, User),
        ?L("DECISION: ~s for ~s: ~p",
           [log_resource(Args), log_user(User), log_result(R)]),
        R.
    
    %%--------------------------------------------------------------------
    
    evaluate(Query, Args, User, LDAP) ->
        ?L1("evaluating query: ~p", [Query]),
        evaluate0(Query, Args, User, LDAP).
    
    evaluate0({constant, Bool}, _Args, _User, _LDAP) ->
        ?L1("evaluated constant: ~p", [Bool]),
        Bool;
    
    evaluate0({for, [{Type, Value, SubQuery}|Rest]}, Args, User, LDAP) ->
        case pget(Type, Args) of
            undefined -> {error, {args_do_not_contain, Type, Args}};
            Value     -> ?L1("selecting subquery ~s = ~s", [Type, Value]),
                         evaluate(SubQuery, Args, User, LDAP);
            _         -> evaluate0({for, Rest}, Args, User, LDAP)
        end;
    
    evaluate0({for, []}, _Args, _User, _LDAP) ->
        {error, {for_query_incomplete}};
    
    evaluate0({exists, DNPattern}, Args, _User, LDAP) ->
        %% eldap forces us to have a filter. objectClass should always be there.
        Filter = eldap:present("objectClass"),
        DN = fill(DNPattern, Args),
        R = object_exists(DN, Filter, LDAP),
        ?L1("evaluated exists for \"~s\": ~p", [DN, R]),
        R;
    
    evaluate0({in_group, DNPattern}, Args, User, LDAP) ->
        evaluate({in_group, DNPattern, "member"}, Args, User, LDAP);
    
    evaluate0({in_group, DNPattern, Desc}, Args,
              #user{impl = #impl{user_dn = UserDN}}, LDAP) ->
        Filter = eldap:equalityMatch(Desc, UserDN),
        DN = fill(DNPattern, Args),
        R = object_exists(DN, Filter, LDAP),
        ?L1("evaluated in_group for \"~s\": ~p", [DN, R]),
        R;
    
    evaluate0({'not', SubQuery}, Args, User, LDAP) ->
        R = evaluate(SubQuery, Args, User, LDAP),
        ?L1("negated result to ~s", [R]),
        not R;
    
    evaluate0({'and', Queries}, Args, User, LDAP) when is_list(Queries) ->
        R = lists:foldl(fun (Q,  true)  -> evaluate(Q, Args, User, LDAP);
                            (_Q, false) -> false
                        end, true, Queries),
        ?L1("'and' result: ~s", [R]),
        R;
    
    evaluate0({'or', Queries}, Args, User, LDAP) when is_list(Queries) ->
        R = lists:foldl(fun (_Q, true)  -> true;
                            (Q,  false) -> evaluate(Q, Args, User, LDAP)
                        end, false, Queries),
        ?L1("'or' result: ~s", [R]),
        R;
    
    evaluate0({equals, StringQuery1, StringQuery2}, Args, User, LDAP) ->
        safe_eval(fun (String1, String2) ->
                          R = String1 =:= String2,
                          ?L1("evaluated equals \"~s\", \"~s\": ~s",
                              [String1, String2, R]),
                          R
                  end,
                  evaluate(StringQuery1, Args, User, LDAP),
                  evaluate(StringQuery2, Args, User, LDAP));
    
    evaluate0({match, StringQuery, REQuery}, Args, User, LDAP) ->
        safe_eval(fun (String, RE) ->
                          R = case re:run(String, RE) of
                                  {match, _} -> true;
                                  nomatch    -> false
                              end,
                          ?L1("evaluated match \"~s\" against RE \"~s\": ~s",
                              [String, RE, R]),
                          R
                  end,
                  evaluate(StringQuery, Args, User, LDAP),
                  evaluate(REQuery, Args, User, LDAP));
    
    evaluate0(StringPattern, Args, User, LDAP) when is_list(StringPattern) ->
        evaluate0({string, StringPattern}, Args, User, LDAP);
    
    evaluate0({string, StringPattern}, Args, _User, _LDAP) ->
        R = fill(StringPattern, Args),
        ?L1("evaluated string for \"~s\"", [R]),
        R;
    
    evaluate0({attribute, DNPattern, AttributeName}, Args, _User, LDAP) ->
        DN = fill(DNPattern, Args),
        R = attribute(DN, AttributeName, LDAP),
        ?L1("evaluated attribute \"~s\" for \"~s\": ~p",
            [AttributeName, DN, R]),
        R;
    
    evaluate0(Q, Args, _User, _LDAP) ->
        {error, {unrecognised_query, Q, Args}}.
    
    safe_eval(_F, {error, _}, _)          -> false;
    safe_eval(_F, _,          {error, _}) -> false;
    safe_eval(F,  V1,         V2)         -> F(V1, V2).
    
    object_exists(DN, Filter, LDAP) ->
        case eldap:search(LDAP,
                          [{base, DN},
                           {filter, Filter},
                           {attributes, ["objectClass"]}, %% Reduce verbiage
                           {scope, eldap:baseObject()}]) of
            {ok, #eldap_search_result{entries = Entries}} ->
                length(Entries) > 0;
            {error, _} = E ->
                E
        end.
    
    attribute(DN, AttributeName, LDAP) ->
        case eldap:search(LDAP,
                          [{base, DN},
                           {filter, eldap:present("objectClass")},
                           {attributes, [AttributeName]}]) of
            {ok, #eldap_search_result{entries = [#eldap_entry{attributes = A}]}} ->
                case pget(AttributeName, A) of
                    [Attr] -> Attr;
                    _      -> {error, not_found}
                end;
            {ok, #eldap_search_result{entries = _}} ->
                {error, not_found};
            {error, _} = E ->
                E
        end.
    
    evaluate_ldap(Q, Args, User) ->
        with_ldap(creds(User), fun(LDAP) -> evaluate(Q, Args, User, LDAP) end).
    
    %%--------------------------------------------------------------------
    
    with_ldap(Creds, Fun) -> with_ldap(Creds, Fun, env(servers)).
    
    with_ldap(_Creds, _Fun, undefined) ->
        {error, no_ldap_servers_defined};
    
    %% TODO - ATM we create and destroy a new LDAP connection on every
    %% call. This could almost certainly be more efficient.
    with_ldap(Creds, Fun, Servers) ->
        Opts0 = [{ssl, env(use_ssl)}, {port, env(port)}],
        Opts = case env(log) of
                   network ->
                       Pre = "    LDAP network traffic: ",
                       rabbit_log:info(
                         "    LDAP connecting to servers: ~p~n", [Servers]),
                       [{log, fun(1, S, A) -> rabbit_log:warning(Pre ++ S, A);
                                 (2, S, A) -> rabbit_log:info   (Pre ++ S, A)
                              end} | Opts0];
                   _ ->
                       Opts0
               end,
        case eldap:open(Servers, Opts) of
            {ok, LDAP} ->
                try Creds of
                    anon ->
                        ?L1("anonymous bind", []),
                        Fun(LDAP);
                    {UserDN, Password} ->
                        case eldap:simple_bind(LDAP, UserDN, Password) of
                            ok ->
                                ?L1("bind succeeded: ~s", [UserDN]),
                                Fun(LDAP);
                            {error, invalidCredentials} ->
                                ?L1("bind returned \"invalid credentials\": ~s",
                                    [UserDN]),
                                {refused, UserDN, []};
                            {error, E} ->
                                ?L1("bind error: ~s ~p", [UserDN, E]),
                                {error, E}
                        end
                after
                    eldap:close(LDAP)
                end;
            Error ->
                ?L1("connect error: ~p", [Error]),
                Error
        end.
    
    env(F) ->
        {ok, V} = application:get_env(rabbitmq_auth_backend_ldap, F),
        V.
    
    do_login(Username, Password, LDAP) ->
        UserDN = username_to_dn(Username, LDAP),
        User = #user{username     = Username,
                     auth_backend = ?MODULE,
                     impl         = #impl{user_dn  = UserDN,
                                          password = Password}},
    
        TagRes = [begin
                      ?L1("CHECK: does ~s have tag ~s?", [Username, Tag]),
                      R = evaluate(Q, [{username, Username},
                                       {user_dn,  UserDN}], User, LDAP),
                      ?L1("DECISION: does ~s have tag ~s? ~p",
                          [Username, Tag, R]),
                      {Tag, R}
                  end || {Tag, Q} <- env(tag_queries)],
        case [E || {_, E = {error, _}} <- TagRes] of
            []      -> {ok, User#user{tags = [Tag || {Tag, true} <- TagRes]}};
            [E | _] -> E
        end.
    
    username_to_dn(Username, LDAP) ->
        username_to_dn(Username, LDAP, env(dn_lookup_attribute)).
    
    username_to_dn(Username, _LDAP, none) ->
        fill_user_dn_pattern(Username);
    
    username_to_dn(Username, LDAP, Attr) ->
        Filled = fill_user_dn_pattern(Username),
        case eldap:search(LDAP,
                          [{base, env(dn_lookup_base)},
                           {filter, eldap:equalityMatch(Attr, Filled)},
                           {attributes, ["distinguishedName"]}]) of
            {ok, #eldap_search_result{entries = [#eldap_entry{object_name = DN}]}}->
                DN;
            {ok, #eldap_search_result{entries = Entries}} ->
                rabbit_log:warning("Searching for DN for ~s, got back ~p~n",
                                   [Filled, Entries]),
                Filled;
            {error, _} = E ->
                exit(E)
        end.
    
    fill_user_dn_pattern(Username) ->
        fill(env(user_dn_pattern), [{username, Username}]).
    
    creds(User) -> creds(User, env(other_bind)).
    
    creds(none, as_user) ->
        exit(as_user_no_password);
    creds(#user{impl = #impl{user_dn = UserDN, password = Password}}, as_user) ->
        {UserDN, Password};
    creds(_, Creds) ->
        Creds.
    
    log(Fmt,  Args) -> case env(log) of
                           false -> ok;
                           _     -> rabbit_log:info(Fmt ++ "~n", Args)
                       end.
    
    fill(Fmt, Args) ->
        ?L2("filling template \"~s\" with~n            ~p", [Fmt, Args]),
        R = rabbit_auth_backend_ldap_util:fill(Fmt, Args),
        ?L2("template result: \"~s\"", [R]),
        R.
    
    log_result({ok, #user{}})   -> ok;
    log_result(true)            -> ok;
    log_result(false)           -> denied;
    log_result({refused, _, _}) -> denied;
    log_result(E)               -> E.
    
    log_user(#user{username = U}) -> rabbit_misc:format("\"~s\"", [U]).
    
    log_vhost(Args) ->
        rabbit_misc:format("access to vhost \"~s\"", [pget(vhost, Args)]).
    
    log_resource(Args) ->
        rabbit_misc:format("~s permission for ~s \"~s\" in \"~s\"",
                           [pget(permission, Args), pget(resource, Args),
                            pget(name, Args), pget(vhost, Args)]).
    rabbitmq-server-3.2.4/plugins-src/rabbitmq-auth-backend-ldap/src/rabbit_auth_backend_ldap_util.erl0000644000000000000000000000174012305126066032122 0ustar  rootroot%% The contents of this file are subject to the Mozilla Public License
    %% Version 1.1 (the "License"); you may not use this file except in
    %% compliance with the License. You may obtain a copy of the License
    %% at http://www.mozilla.org/MPL/
    %%
    %% Software distributed under the License is distributed on an "AS IS"
    %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
    %% the License for the specific language governing rights and
    %% limitations under the License.
    %%
    %% The Original Code is RabbitMQ.
    %%
    %% The Initial Developer of the Original Code is GoPivotal, Inc.
    %% Copyright (c) 2007-2013 GoPivotal, Inc.  All rights reserved.
    %%
    
    -module(rabbit_auth_backend_ldap_util).
    
    -export([fill/2]).
    
    fill(Fmt, []) ->
        binary_to_list(iolist_to_binary(Fmt));
    
    fill(Fmt, [{K, V} | T]) ->
        Var = [[$\\, $$, ${] ++ atom_to_list(K) ++ [$}]],
        fill(re:replace(Fmt, Var, [to_repl(V)], [global]), T).
    
    to_repl(V) when is_atom(V) ->
        atom_to_list(V);
    to_repl(V) ->
        V.
    rabbitmq-server-3.2.4/plugins-src/rabbitmq-auth-backend-ldap/src/rabbit_auth_backend_ldap_app.erl0000644000000000000000000000264512305126066031732 0ustar  rootroot%% The contents of this file are subject to the Mozilla Public License
    %% Version 1.1 (the "License"); you may not use this file except in
    %% compliance with the License. You may obtain a copy of the License
    %% at http://www.mozilla.org/MPL/
    %%
    %% Software distributed under the License is distributed on an "AS IS"
    %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
    %% the License for the specific language governing rights and
    %% limitations under the License.
    %%
    %% The Original Code is RabbitMQ.
    %%
    %% The Initial Developer of the Original Code is GoPivotal, Inc.
    %% Copyright (c) 2007-2013 GoPivotal, Inc.  All rights reserved.
    %%
    
    -module(rabbit_auth_backend_ldap_app).
    
    -behaviour(application).
    -export([start/2, stop/1]).
    
    %% Dummy supervisor to get this application behaviour working
    -behaviour(supervisor).
    -export([init/1]).
    
    start(_Type, _StartArgs) ->
        {ok, Backends} = application:get_env(rabbit, auth_backends),
        case lists:member(rabbit_auth_backend_ldap, Backends) of
            true  -> ok;
            false -> rabbit_log:warning(
                       "LDAP plugin loaded, but rabbit_auth_backend_ldap is not "
                       "in the list of auth_backends. LDAP auth will not work.~n")
        end,
        supervisor:start_link({local, ?MODULE}, ?MODULE, []).
    
    stop(_State) ->
        ok.
    
    %%----------------------------------------------------------------------------
    
    init([]) -> {ok, {{one_for_one, 3, 10}, []}}.
    rabbitmq-server-3.2.4/plugins-src/rabbitmq-auth-backend-ldap/README0000644000000000000000000000104512305126066023515 0ustar  rootrootRequirements
    ============
    
    You can build and install it like any other plugin (see
    http://www.rabbitmq.com/plugin-development.html).
    
    Documentation
    =============
    
    See http://www.rabbitmq.com/ldap.html
    
    Limitations
    ===========
    
    Currently this plugin is rather chatty with LDAP connections when
    doing authorisation over LDAP - every time RabbitMQ needs to do an
    authorisation query it starts a new LDAP connection. However, RabbitMQ
    does have a per-channel authorisation cache, so this is not too awful.
    
    There might need to be more types of queries.
    rabbitmq-server-3.2.4/plugins-src/rabbitmq-auth-backend-ldap/test/0000755000000000000000000000000012305126066023614 5ustar  rootrootrabbitmq-server-3.2.4/plugins-src/rabbitmq-auth-backend-ldap/test/src/0000755000000000000000000000000012305126066024403 5ustar  rootroot././@LongLink0000000000000000000000000000015000000000000011561 Lustar  rootrootrabbitmq-server-3.2.4/plugins-src/rabbitmq-auth-backend-ldap/test/src/rabbit_auth_backend_ldap_test.erlrabbitmq-server-3.2.4/plugins-src/rabbitmq-auth-backend-ldap/test/src/rabbit_auth_backend_ldap_test.0000644000000000000000000000662012305126066032402 0ustar  rootroot%% The contents of this file are subject to the Mozilla Public License
    %% Version 1.1 (the "License"); you may not use this file except in
    %% compliance with the License. You may obtain a copy of the License
    %% at http://www.mozilla.org/MPL/
    %%
    %% Software distributed under the License is distributed on an "AS IS"
    %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
    %% the License for the specific language governing rights and
    %% limitations under the License.
    %%
    %% The Original Code is RabbitMQ
    %%
    %% The Initial Developer of the Original Code is GoPivotal, Inc.
    %% Copyright (c) 2007-2013 GoPivotal, Inc.  All rights reserved.
    %%
    
    -module(rabbit_auth_backend_ldap_test).
    
    -include_lib("eunit/include/eunit.hrl").
    -include_lib("amqp_client/include/amqp_client.hrl").
    
    -define(SIMON, #amqp_params_network{username     = <<"Simon MacMullen">>,
                                        password     = <<"password">>,
                                        virtual_host = <<"test">>}).
    
    -define(MIKEB, #amqp_params_network{username     = <<"Mike Bridgen">>,
                                        password     = <<"password">>,
                                        virtual_host = <<"test">>}).
    
    login_test_() ->
        [?_test(fail(#amqp_params_network{})),
         ?_test(fail(#amqp_params_network{username     = <<"Simon MacMullen">>})),
         ?_test(fail(#amqp_params_network{username     = <<"Simon MacMullen">>,
                                          password     = <<"password">>})),
         ?_test(succ(?SIMON)),
         ?_test(succ(?MIKEB))].
    
    succ(Params) -> ?assertMatch({ok, _}, amqp_connection:start(Params)).
    fail(Params) -> ?assertMatch({error, _}, amqp_connection:start(Params)).
    
    in_group_test_() ->
        X = [#'exchange.declare'{exchange = <<"test">>}],
        [test_resource_fun(PTR) || PTR <- [{?SIMON, X, ok},
                                           {?MIKEB, X, fail}]].
    
    const_test_() ->
        Q = [#'queue.declare'{queue = <<"test">>}],
        [test_resource_fun(PTR) || PTR <- [{?SIMON, Q, ok},
                                           {?MIKEB, Q, fail}]].
    
    string_match_test_() ->
        B = fun(N) ->
                    [#'exchange.declare'{exchange = N},
                     #'queue.declare'{queue = <<"test">>},
                     #'queue.bind'{exchange = N, queue = <<"test">>}]
            end,
        [test_resource_fun(PTR) ||
            PTR <- [{?SIMON, B(<<"xch-Simon MacMullen-abc123">>), ok},
                    {?SIMON, B(<<"abc123">>),                     fail},
                    {?SIMON, B(<<"xch-Someone Else-abc123">>),    fail}]].
    
    boolean_logic_test_() ->
        Q1 = [#'queue.declare'{queue = <<"test1">>},
              #'basic.consume'{queue = <<"test1">>}],
        Q2 = [#'queue.declare'{queue = <<"test2">>},
              #'basic.consume'{queue = <<"test2">>}],
        [test_resource_fun(PTR) || PTR <- [{?SIMON, Q1, ok},
                                           {?SIMON, Q2, ok},
                                           {?MIKEB, Q1, fail},
                                           {?MIKEB, Q2, fail}]].
    
    test_resource_fun({Person, Things, Result}) ->
        fun() ->
                {ok, Conn} = amqp_connection:start(Person),
                {ok, Ch} = amqp_connection:open_channel(Conn),
                ?assertEqual(Result,
                             try
                                 [amqp_channel:call(Ch, T) || T <- Things],
                                 amqp_connection:close(Conn),
                                 ok
                             catch exit:_ -> fail
                             end)
        end.
    rabbitmq-server-3.2.4/plugins-src/rabbitmq-auth-backend-ldap/README-authorisation0000644000000000000000000000004612305126066026404 0ustar  rootrootSee http://www.rabbitmq.com/ldap.html
    rabbitmq-server-3.2.4/plugins-src/rabbitmq-auth-backend-ldap/.srcdist_done0000644000000000000000000000000012305126066025304 0ustar  rootrootrabbitmq-server-3.2.4/plugins-src/rabbitmq-auth-backend-ldap/Makefile0000644000000000000000000000002712305126066024274 0ustar  rootrootinclude ../umbrella.mk
    rabbitmq-server-3.2.4/plugins-src/rabbitmq-auth-backend-ldap/example/0000755000000000000000000000000012305126066024270 5ustar  rootrootrabbitmq-server-3.2.4/plugins-src/rabbitmq-auth-backend-ldap/example/groups.ldif0000644000000000000000000000031712305126066026450 0ustar  rootrootdn: ou=groups,dc=example,dc=com
    objectclass:organizationalunit
    ou: groups
    
    dn: cn=wheel,ou=groups,dc=example,dc=com
    objectclass: groupOfNames
    cn: wheel
    member: cn=Simon MacMullen,ou=people,dc=example,dc=com
    rabbitmq-server-3.2.4/plugins-src/rabbitmq-auth-backend-ldap/example/README0000644000000000000000000000060612305126066025152 0ustar  rootrootThis is a very simple example, designed to be set up with the modern
    Debian / Ubuntu packaging of OpenLDAP. Running setup.sh after "apt-get
    install slapd" will wipe out any existing LDAP database and get you:
    
    * A domain
    * An admin user
    * A couple of normal users
    * A group containing the users
    * An OU representing a vhost
    
    These correspond to the examples mentioned in the documentation.
    rabbitmq-server-3.2.4/plugins-src/rabbitmq-auth-backend-ldap/example/setup.sh0000755000000000000000000000106412305126066025770 0ustar  rootroot#!/bin/sh -e
    
    # Based on instructions found at
    # http://ubuntuforums.org/showthread.php?p=8161118#post8161118
    # - yes that does seem to be the most authoritative place.
    
    sudo apt-get --yes purge slapd
    sudo rm -rf /var/lib/ldap
    sudo apt-get --yes install slapd
    sleep 1
    
    DIR=$(dirname $0)
    
    sudo ldapadd -Y EXTERNAL -H ldapi:/// -f ${DIR}/global.ldif
    ldapadd -x -D cn=admin,dc=example,dc=com -w admin -f ${DIR}/people.ldif
    ldapadd -x -D cn=admin,dc=example,dc=com -w admin -f ${DIR}/groups.ldif
    ldapadd -x -D cn=admin,dc=example,dc=com -w admin -f ${DIR}/rabbit.ldif
    rabbitmq-server-3.2.4/plugins-src/rabbitmq-auth-backend-ldap/example/people.ldif0000644000000000000000000000075512305126066026423 0ustar  rootrootdn: dc=example,dc=com
    objectClass: top
    objectClass: dcObject
    objectclass: organization
    o: example.com
    dc: example
    description: Example
    
    dn: ou=people,dc=example,dc=com
    objectClass: organizationalUnit
    ou: people
    
    dn: cn=Simon MacMullen,ou=people,dc=example,dc=com
    objectClass: person
    cn: Simon MacMullen
    sn: MacMullen
    userPassword: password
    description: can-declare-queues
    
    dn: cn=Mike Bridgen,ou=people,dc=example,dc=com
    objectClass: person
    cn: Mike Bridgen
    sn: Bridgen
    userPassword: password
    rabbitmq-server-3.2.4/plugins-src/rabbitmq-auth-backend-ldap/example/global.ldif0000644000000000000000000000126712305126066026376 0ustar  rootroot# Load modules for database type
    dn: cn=module,cn=config
    objectclass: olcModuleList
    cn: module
    olcModuleLoad: back_bdb.la
    
    # Create directory database
    dn: olcDatabase=bdb,cn=config
    objectClass: olcDatabaseConfig
    objectClass: olcBdbConfig
    olcDatabase: bdb
    # Domain name (e.g. example.com)
    olcSuffix: dc=example,dc=com
    # Location on system where database is stored
    olcDbDirectory: /var/lib/ldap
    # Manager of the database
    olcRootDN: cn=admin,dc=example,dc=com
    olcRootPW: admin
    olcAccess: to attrs=userPassword
      by self write
      by anonymous auth
      by dn.base="cn=admin,dc=example,dc=com" write
      by * none
    olcAccess: to *
      by self write
      by dn.base="cn=admin,dc=example,dc=com" write
      by * read
    rabbitmq-server-3.2.4/plugins-src/rabbitmq-auth-backend-ldap/example/rabbit.ldif0000644000000000000000000000025612305126066026376 0ustar  rootrootdn: ou=vhosts,dc=example,dc=com
    objectClass: organizationalUnit
    ou: vhosts
    
    dn: ou=test,ou=vhosts,dc=example,dc=com
    objectClass: top
    objectClass: organizationalUnit
    ou: test
    rabbitmq-server-3.2.4/plugins-src/rabbitmq-auth-backend-ldap/ebin/0000755000000000000000000000000012305126066023552 5ustar  rootrootrabbitmq-server-3.2.4/plugins-src/rabbitmq-auth-backend-ldap/etc/0000755000000000000000000000000012305126066023410 5ustar  rootrootrabbitmq-server-3.2.4/plugins-src/rabbitmq-auth-backend-ldap/etc/rabbit-test.config0000644000000000000000000000330512305126066027020 0ustar  rootroot%% -*- erlang -*-
    [{rabbit, [{auth_backends, [rabbit_auth_backend_ldap]},
               {default_vhost, <<"test">>}]},
     {rabbitmq_auth_backend_ldap,
      [ {servers,            ["localhost"]},
        {user_dn_pattern,    "cn=${username},ou=People,dc=example,dc=com"},
        {other_bind,         anon},
        {use_ssl,            false},
        {port,               389},
        {log,                true},
        {tag_queries,        [{administrator, {constant, false}}]},
        {vhost_access_query, {exists, "ou=${vhost},ou=vhosts,dc=example,dc=com"}},
        {resource_access_query,
         {for, [{resource, exchange,
                 {for, [{permission, configure,
                         {in_group, "cn=wheel,ou=groups,dc=example,dc=com"}
                        },
                        {permission, write, {constant, true}},
                        {permission, read,
                         {match, {string, "${name}"},
                                 {string, "^xch-${username}-.*"}}
                        }
                       ]}},
                {resource, queue,
                 {for, [{permission, configure,
                         {match, {attribute, "${user_dn}", "description"},
                                 {string, "can-declare-queues"}}
                        },
                        {permission, write, {constant, true}},
                        {permission, read,
                         {'or',
                          [{'and',
                            [{equals, "${name}", "test1"},
                             {equals, "${username}", "Simon MacMullen"}]},
                           {'and',
                            [{equals, "${name}", "test2"},
                             {'not', {equals, "${username}", "Mike Bridgen"}}]}
                          ]}}
                       ]}}
                ]}}
      ]}
    ].
    rabbitmq-server-3.2.4/plugins-src/rabbitmq-auth-backend-ldap/README-tests0000644000000000000000000000060012305126066024651 0ustar  rootrootThe tests *require* a locally installed LDAP server with some
    predefined objects inside. If there's no LDAP server running on port
    389, they will be skipped.
    
    On Debian / Ubuntu you can just:
    
    $ ./example/setup.sh
    $ make test
    
     - but be aware that this will wipe out your local OpenLDAP installation.
    
    Poke around in example/ if using any other distro, you can probably
    make it work.
    rabbitmq-server-3.2.4/plugins-src/rabbitmq-auth-backend-ldap/package.mk0000644000000000000000000000042012305126066024555 0ustar  rootrootRELEASABLE:=true
    DEPS:=rabbitmq-server rabbitmq-erlang-client eldap-wrapper
    
    ifeq ($(shell nc -z localhost 389 && echo true),true)
    WITH_BROKER_TEST_COMMANDS:=eunit:test(rabbit_auth_backend_ldap_test,[verbose])
    WITH_BROKER_TEST_CONFIG:=$(PACKAGE_DIR)/etc/rabbit-test
    endif
    rabbitmq-server-3.2.4/plugins-src/cowboy-wrapper/0000755000000000000000000000000012305126066020552 5ustar  rootroot././@LongLink0000000000000000000000000000014600000000000011566 Lustar  rootrootrabbitmq-server-3.2.4/plugins-src/cowboy-wrapper/0003-R12-drop-all-references-to-reference-type.patchrabbitmq-server-3.2.4/plugins-src/cowboy-wrapper/0003-R12-drop-all-references-to-reference-type.patc0000644000000000000000000000317312305126066031535 0ustar  rootrootFrom 4db80ab7bacf04502ad2d29d4760e04a6d787a83 Mon Sep 17 00:00:00 2001
    From: Marek Majkowski 
    Date: Thu, 26 Jan 2012 12:52:23 +0000
    Subject: [PATCH 3/7] R12: drop all references to reference() type
    
    ---
     src/cowboy_http_protocol.erl  |    2 +-
     src/cowboy_http_websocket.erl |    2 +-
     src/cowboy_listener.erl       |    2 +-
     3 files changed, 3 insertions(+), 3 deletions(-)
    
    diff --git a/src/cowboy_http_protocol.erl b/src/cowboy_http_protocol.erl
    index b80745f..0183785 100644
    --- a/src/cowboy_http_protocol.erl
    +++ b/src/cowboy_http_protocol.erl
    @@ -57,7 +57,7 @@
     	buffer = <<>> :: binary(),
     	hibernate = false,
     	loop_timeout = infinity :: timeout(),
    -	loop_timeout_ref :: undefined | reference()
    +	loop_timeout_ref
     }).
     
     %% API.
    diff --git a/src/cowboy_http_websocket.erl b/src/cowboy_http_websocket.erl
    index 5f59891..5100213 100644
    --- a/src/cowboy_http_websocket.erl
    +++ b/src/cowboy_http_websocket.erl
    @@ -52,7 +52,7 @@
     	opts :: any(),
     	challenge = undefined :: undefined | binary() | {binary(), binary()},
     	timeout = infinity :: timeout(),
    -	timeout_ref = undefined :: undefined | reference(),
    +	timeout_ref = undefined,
     	messages = undefined :: undefined | {atom(), atom(), atom()},
     	hibernate = false,
     	eop :: undefined | tuple(), %% hixie-76 specific.
    diff --git a/src/cowboy_listener.erl b/src/cowboy_listener.erl
    index c19d079..86e87f1 100644
    --- a/src/cowboy_listener.erl
    +++ b/src/cowboy_listener.erl
    @@ -23,8 +23,8 @@
     
     -record(state, {
     	req_pools = [] :: [{atom(), non_neg_integer()}],
    -	reqs_table :: ets:tid(),
    -	queue = [] :: [{pid(), reference()}]
    +	reqs_table,
    +	queue = []
     }).
     
     %% API.
    -- 
    1.7.0.4
    
    rabbitmq-server-3.2.4/plugins-src/cowboy-wrapper/0002-R12-drop-all-references-to-boolean-type.patch0000644000000000000000000001426312305126066031367 0ustar  rootrootFrom 257e64326ad786d19328d343da0ff7d29adbae4e Mon Sep 17 00:00:00 2001
    From: Marek Majkowski 
    Date: Thu, 26 Jan 2012 12:51:30 +0000
    Subject: [PATCH 2/7] R12 - drop all references to boolean() type
    
    ---
     src/cowboy_cookies.erl        |    8 --------
     src/cowboy_http.erl           |    1 -
     src/cowboy_http_protocol.erl  |    3 +--
     src/cowboy_http_req.erl       |    2 --
     src/cowboy_http_static.erl    |    5 -----
     src/cowboy_http_websocket.erl |    2 +-
     6 files changed, 2 insertions(+), 19 deletions(-)
    
    diff --git a/src/cowboy_cookies.erl b/src/cowboy_cookies.erl
    index 6818a86..7f5ab60 100644
    --- a/src/cowboy_cookies.erl
    +++ b/src/cowboy_cookies.erl
    @@ -112,7 +112,6 @@ cookie(Key, Value, Options) when is_binary(Key)
     %% Internal.
     
     %% @doc Check if a character is a white space character.
    --spec is_whitespace(char()) -> boolean().
     is_whitespace($\s) -> true;
     is_whitespace($\t) -> true;
     is_whitespace($\r) -> true;
    @@ -120,7 +119,6 @@ is_whitespace($\n) -> true;
     is_whitespace(_) -> false.
     
     %% @doc Check if a character is a seperator.
    --spec is_separator(char()) -> boolean().
     is_separator(C) when C < 32 -> true;
     is_separator($\s) -> true;
     is_separator($\t) -> true;
    @@ -144,7 +142,6 @@ is_separator($}) -> true;
     is_separator(_) -> false.
     
     %% @doc Check if a binary has an ASCII seperator character.
    --spec has_seperator(binary()) -> boolean().
     has_seperator(<<>>) ->
     	false;
     has_seperator(<<$/, Rest/binary>>) ->
    @@ -228,7 +225,6 @@ read_quoted(<>, Acc) ->
     	read_quoted(Rest, <>).
     
     %% @doc Drop characters while a function returns true.
    --spec binary_dropwhile(fun((char()) -> boolean()), binary()) -> binary().
     binary_dropwhile(_F, <<"">>) ->
     	<<"">>;
     binary_dropwhile(F, String) ->
    @@ -246,8 +242,6 @@ skip_whitespace(String) ->
     	binary_dropwhile(fun is_whitespace/1, String).
     
     %% @doc Split a binary when the current character causes F to return true.
    --spec binary_splitwith(fun((char()) -> boolean()), binary(), binary())
    -	-> {binary(), binary()}.
     binary_splitwith(_F, Head, <<>>) ->
     	{Head, <<>>};
     binary_splitwith(F, Head, Tail) ->
    @@ -260,8 +254,6 @@ binary_splitwith(F, Head, Tail) ->
     	end.
     
     %% @doc Split a binary with a function returning true or false on each char.
    --spec binary_splitwith(fun((char()) -> boolean()), binary())
    -	-> {binary(), binary()}.
     binary_splitwith(F, String) ->
     	binary_splitwith(F, <<>>, String).
     
    diff --git a/src/cowboy_http.erl b/src/cowboy_http.erl
    index 95a7334..d7261c8 100644
    --- a/src/cowboy_http.erl
    +++ b/src/cowboy_http.erl
    @@ -755,7 +755,6 @@ urlencode(Bin, Opts) ->
     	Upper = proplists:get_value(upper, Opts, false),
     	urlencode(Bin, <<>>, Plus, Upper).
     
    --spec urlencode(binary(), binary(), boolean(), boolean()) -> binary().
     urlencode(<>, Acc, P=Plus, U=Upper) ->
     	if	C >= $0, C =< $9 -> urlencode(Rest, <>, P, U);
     		C >= $A, C =< $Z -> urlencode(Rest, <>, P, U);
    diff --git a/src/cowboy_http_protocol.erl b/src/cowboy_http_protocol.erl
    index baee081..b80745f 100644
    --- a/src/cowboy_http_protocol.erl
    +++ b/src/cowboy_http_protocol.erl
    @@ -55,7 +55,7 @@
     	max_line_length :: integer(),
     	timeout :: timeout(),
     	buffer = <<>> :: binary(),
    -	hibernate = false :: boolean(),
    +	hibernate = false,
     	loop_timeout = infinity :: timeout(),
     	loop_timeout_ref :: undefined | reference()
     }).
    @@ -440,7 +440,6 @@ format_header(Field) when byte_size(Field) =< 20; byte_size(Field) > 32 ->
     format_header(Field) ->
     	format_header(Field, true, <<>>).
     
    --spec format_header(binary(), boolean(), binary()) -> binary().
     format_header(<<>>, _Any, Acc) ->
     	Acc;
     %% Replicate a bug in OTP for compatibility reasons when there's a - right
    diff --git a/src/cowboy_http_req.erl b/src/cowboy_http_req.erl
    index 92d96ad..d729d6c 100644
    --- a/src/cowboy_http_req.erl
    +++ b/src/cowboy_http_req.erl
    @@ -515,13 +515,11 @@ set_resp_body_fun(StreamLen, StreamFun, Req) ->
     
     
     %% @doc Return whether the given header has been set for the response.
    --spec has_resp_header(cowboy_http:header(), #http_req{}) -> boolean().
     has_resp_header(Name, #http_req{resp_headers=RespHeaders}) ->
     	NameBin = header_to_binary(Name),
     	lists:keymember(NameBin, 1, RespHeaders).
     
     %% @doc Return whether a body has been set for the response.
    --spec has_resp_body(#http_req{}) -> boolean().
     has_resp_body(#http_req{resp_body={Length, _}}) ->
     	Length > 0;
     has_resp_body(#http_req{resp_body=RespBody}) ->
    diff --git a/src/cowboy_http_static.erl b/src/cowboy_http_static.erl
    index 0ee996a..d370046 100644
    --- a/src/cowboy_http_static.erl
    +++ b/src/cowboy_http_static.erl
    @@ -207,8 +207,6 @@ allowed_methods(Req, State) ->
     	{['GET', 'HEAD'], Req, State}.
     
     %% @private
    --spec malformed_request(#http_req{}, #state{}) ->
    -		{boolean(), #http_req{}, #state{}}.
     malformed_request(Req, #state{filepath=error}=State) ->
     	{true, Req, State};
     malformed_request(Req, State) ->
    @@ -216,8 +214,6 @@ malformed_request(Req, State) ->
     
     
     %% @private Check if the resource exists under the document root.
    --spec resource_exists(#http_req{}, #state{}) ->
    -		{boolean(), #http_req{}, #state{}}.
     resource_exists(Req, #state{fileinfo={error, _}}=State) ->
     	{false, Req, State};
     resource_exists(Req, #state{fileinfo={ok, Fileinfo}}=State) ->
    @@ -227,7 +223,6 @@ resource_exists(Req, #state{fileinfo={ok, Fileinfo}}=State) ->
     %% @private
     %% Access to a file resource is forbidden if it exists and the local node does
     %% not have permission to read it. Directory listings are always forbidden.
    --spec forbidden(#http_req{}, #state{}) -> {boolean(), #http_req{}, #state{}}.
     forbidden(Req, #state{fileinfo={_, #file_info{type=directory}}}=State) ->
     	{true, Req, State};
     forbidden(Req, #state{fileinfo={error, eacces}}=State) ->
    diff --git a/src/cowboy_http_websocket.erl b/src/cowboy_http_websocket.erl
    index 0f0204c..5f59891 100644
    --- a/src/cowboy_http_websocket.erl
    +++ b/src/cowboy_http_websocket.erl
    @@ -54,7 +54,7 @@
     	timeout = infinity :: timeout(),
     	timeout_ref = undefined :: undefined | reference(),
     	messages = undefined :: undefined | {atom(), atom(), atom()},
    -	hibernate = false :: boolean(),
    +	hibernate = false,
     	eop :: undefined | tuple(), %% hixie-76 specific.
     	origin = undefined :: undefined | binary() %% hixie-76 specific.
     }).
    -- 
    1.7.0.4
    
    rabbitmq-server-3.2.4/plugins-src/cowboy-wrapper/README.md0000644000000000000000000000002412305126066022025 0ustar  rootrootCowboy requires R14
    rabbitmq-server-3.2.4/plugins-src/cowboy-wrapper/0001-R12-fake-iodata-type.patch0000644000000000000000000000255112305126066025642 0ustar  rootrootFrom c2303fb756eeb8bd92dc04764970a43f59940208 Mon Sep 17 00:00:00 2001
    From: Marek Majkowski 
    Date: Thu, 26 Jan 2012 12:48:41 +0000
    Subject: [PATCH 1/7] R12 - Fake iodata() type
    
    ---
     include/http.hrl    |    2 +-
     src/cowboy_http.erl |    3 ++-
     2 files changed, 3 insertions(+), 2 deletions(-)
    
    diff --git a/include/http.hrl b/include/http.hrl
    index c66f2b0..c98f873 100644
    --- a/include/http.hrl
    +++ b/include/http.hrl
    @@ -47,7 +47,7 @@
     	%% Response.
     	resp_state = waiting   :: locked | waiting | chunks | done,
     	resp_headers = []      :: cowboy_http:headers(),
    -	resp_body  = <<>>      :: iodata() | {non_neg_integer(),
    +	resp_body  = <<>>      :: cowboy_http:fake_iodata() | {non_neg_integer(),
     								fun(() -> {sent, non_neg_integer()})},
     
     	%% Functions.
    diff --git a/src/cowboy_http.erl b/src/cowboy_http.erl
    index 32b0ca9..95a7334 100644
    --- a/src/cowboy_http.erl
    +++ b/src/cowboy_http.erl
    @@ -46,7 +46,8 @@
     	| 'Expires' | 'Last-Modified' | 'Accept-Ranges' | 'Set-Cookie'
     	| 'Set-Cookie2' | 'X-Forwarded-For' | 'Cookie' | 'Keep-Alive'
     	| 'Proxy-Connection' | binary().
    --type headers() :: [{header(), iodata()}].
    +-type fake_iodata() :: iolist() | binary().
    +-type headers() :: [{header(), fake_iodata()}].
     -type status() :: non_neg_integer() | binary().
     
     -export_type([method/0, uri/0, version/0, header/0, headers/0, status/0]).
    -- 
    1.7.0.4
    
    rabbitmq-server-3.2.4/plugins-src/cowboy-wrapper/cowboy-git/0000755000000000000000000000000012305126066022635 5ustar  rootrootrabbitmq-server-3.2.4/plugins-src/cowboy-wrapper/cowboy-git/CHANGELOG.md0000644000000000000000000001576512305126066024464 0ustar  rootrootCHANGELOG
    =========
    
    0.4.0
    -----
    
    *   Set the cowboy_listener process priority to high
    
        As it is the central process used by all incoming requests
        we need to set its priority to high to avoid timeouts that
        would happen otherwise when reaching a huge number of
        concurrent requests.
    
    *   Add cowboy:child_spec/6 for embedding in other applications
    
    *   Add cowboy_http_rest, an experimental REST protocol support
    
        Based on the Webmachine diagram and documentation. It is a
        new implementation, not a port, therefore a few changes have
        been made. However all the callback names are the same and
        should behave similarly to Webmachine.
    
        There is currently no documentation other than the Webmachine
        resource documentation and the comments found in cowboy_http_rest,
        which itself should be fairly easy to read and understand.
    
    *   Add cowboy_http_static, an experimental static file handler
    
        Makes use of the aforementioned REST protocol support to
        deliver files with proper content type and cache headers.
    
        Note that this uses the new file:sendfile support when
        appropriate, which currently requires the VM to be started
        with the +A option defined, else errors may randomly appear.
    
    *   Add cowboy_bstr module for binary strings related functions
    
    *   Add cowboy_http module for HTTP parsing functions
    
        This module so far contains various functions for HTTP header
        parsing along with URL encoding and decoding.
    
    *   Remove quoted from the default dependencies
    
        This should make Cowboy much easier to compile and use by default.
        It is of course still possible to use quoted as your URL decoding
        library in Cowboy thanks to the newly added urldecode option.
    
    *   Fix supervisor spec for non dynamic modules to allow upgrades to complete
    
    *   Add cowboy:accept_ack/1 for a cleaner handling of the shoot message
    
        Before, when the listener accepted a connection, the newly created
        process was waiting for a message containing the atom 'shoot' before
        proceeding. This has been replaced by the cowboy:accept_ack/1 function.
    
        This function should be used where 'shoot' was received because the
        contents of the message have changed (and could change again in the
        distant future).
    
    *   Update binary parsing expressions to avoid hype crashes
    
        More specifically, /bits was replaced by /binary.
    
    *   Rename the type cowboy_dispatcher:path_tokens/0 to tokens/0
    
    *   Remove the cowboy_clock:date/0, time/0 and datetime/0 types
    
        The calendar module exports those same types properly since R14B04.
    
    *   Add cacertfile configuration option to cowboy_ssl_transport
    
    *   Add cowboy_protocol behaviour
    
    *   Remove -Wbehaviours dialyzer option unavailable in R15B
    
    *   Many tests and specs improvements
    
    ### cowboy_http_req
    
    *   Fix a crash when reading the request body
    
    *   Add parse_header/2 and parse_header/3
    
        The following headers can now be semantically parsed: Connection, Accept,
        Accept-Charset, Accept-Encoding, Accept-Language, Content-Length,
        Content-Type, If-Match, If-None-Match, If-Modified-Since,
        If-Unmodified-Since, Upgrade
    
    *   Add set_resp_header/3, set_resp_cookie/4 and set_resp_body/2
    
        These functions allow handlers to set response headers and body
        without having to reply directly.
    
    *   Add set_resp_body_fun/3
    
        This function allows handlers to stream the body of the response
        using the given fun. The size of the response must be known beforehand.
    
    *   Add transport/1 to obtain the transport and socket for the request
    
        This allows handlers to have low-level socket access in those cases
        where they do need it, like when streaming a response body with
        set_resp_body_fun/3.
    
    *   Add peer_addr/1
    
        This function tries to guess the real peer IP based on the HTTP
        headers received.
    
    *   Add meta/2 and meta/3 to save useful protocol information
    
        Currently used to save the Websocket protocol version currently used,
        and to save request information in the REST protocol handler.
    
    *   Add reply/2 and reply/3 aliases to reply/4
    
    *   Add upgrade_reply/3 for protocol upgrades
    
    ### cowboy_http_protocol
    
    *   Add the {urldecode, fun urldecode/2} option
    
        Added when quoted was removed from the default build. Can be used to
        tell Cowboy to use quoted or any other URL decoding routine.
    
    *   Add the max_keepalive option
    
    *   Add the max_line_length option
    
    *   Allow HTTP handlers to stop during init/3
    
        To do so they can return {shutdown, Req, State}.
    
    *   Add loops support in HTTP handlers for proper long-polling support
    
        A loop can be entered by returning either of {loop, Req, State},
        {loop, Req, State, hibernate}, {loop, Req, State, Timeout} or
        {loop, Req, State, Timeout, hibernate} from init/3.
    
        Loops are useful when we cannot reply immediately and instead
        are waiting for an Erlang message to be able to complete the request,
        as would typically be done for long-polling.
    
        Loop support in the protocol means that timeouts and hibernating
        are well tested and handled so you can use those options without
        worrying. It is recommended to set the timeout option.
    
        When a loop is started, handle/2 will never be called so it does
        not need to be defined. When the request process receives an Erlang
        message, it will call the info/3 function with the message as the
        first argument.
    
        Like in OTP, you do need to set timeout and hibernate again when
        returning from info/3 to enable them until the next call.
    
    *   Fix the sending of 500 errors when handlers crash
    
        Now we send an error response when no response has been sent,
        and do nothing more than close the connection if anything
        did get sent.
    
    *   Fix a crash when the server is sent HTTP responses
    
    *   Fix HTTP timeouts handling when the Request-Line wasn't received
    
    *   Fix the handling of the max number of empty lines between requests
    
    *   Fix the handling of HEAD requests
    
    *   Fix HTTP/1.0 Host header handling
    
    *   Reply status 400 if we receive an unexpected value or error for headers
    
    *   Properly close when the application sends "Connection: close" header
    
    *   Close HTTP connections on all errors
    
    *   Improve the error message for HTTP handlers
    
    ### cowboy_http_websocket
    
    *   Add websocket support for all versions up to RFC 6455
    
        Support isn't perfect yet according to the specifications, but
        is working against all currently known client implementations.
    
    *   Allow websocket_init/3 to return with the hibernate option set
    
    *   Add {shutdown, Req} return value to websocket_init/3 to fail an upgrade
    
    *   Fix websocket timeout handling
    
    *   Fix error messages: wrong callback name was reported on error
    
    *   Fix byte-by-byte websocket handling
    
    *   Fix an issue when using hixie-76 with certain proxies
    
    *   Fix a crash in the hixie-76 handshake
    
    *   Fix the handshake when SSL is used on port 443
    
    *   Fix a crash in the handshake when cowboy_http_req:compact/1 is used
    
    *   Fix handshake when a query string is present
    
    *   Fix a crash when the Upgrade header contains more than one token
    
    0.2.0
    -----
    
    *   Initial release.
    rabbitmq-server-3.2.4/plugins-src/cowboy-wrapper/cowboy-git/README.md0000644000000000000000000002616712305126066024130 0ustar  rootrootCowboy
    ======
    
    Cowboy is a small, fast and modular HTTP server written in Erlang.
    
    Cowboy is also a socket acceptor pool, able to accept connections
    for any kind of TCP protocol.
    
    Goals
    -----
    
    Cowboy aims to provide the following advantages:
    
    * **Small** code base.
    * Damn **fast**.
    * **Modular**: transport and protocol handlers are replaceable.
    * **Binary HTTP** for greater speed and lower memory usage.
    * Easy to **embed** inside another application.
    * Selectively **dispatch** requests to handlers, allowing you to send some
      requests to your embedded code and others to a FastCGI application in
      PHP or Ruby.
    * No parameterized module. No process dictionary. **Clean** Erlang code.
    
    The server is currently in early development. Comments and suggestions are
    more than welcome. To contribute, either open bug reports, or fork the project
    and send us pull requests with new or improved functionality. You should
    discuss your plans with us before doing any serious work, though, to avoid
    duplicating efforts.
    
    Quick start
    -----------
    
    * Add Cowboy as a rebar or agner dependency to your application.
    * Start Cowboy and add one or more listeners.
    * Write handlers for your application.
    * Check out [examples](https://github.com/extend/cowboy_examples)!
    
    Getting Started
    ---------------
    
    At heart, Cowboy is nothing more than an TCP acceptor pool. All it does is
    accept connections received on a given port and using a given transport,
    like TCP or SSL, and forward them to a request handler for the given
    protocol. Acceptors and request handlers are of course supervised
    automatically.
    
    It just so happens that Cowboy also includes an HTTP protocol handler.
    But Cowboy does nothing by default. You need to explicitly ask Cowboy
    to listen on a port with your chosen transport and protocol handlers.
    To do so, you must start a listener.
    
    A listener is a special kind of supervisor that manages both the
    acceptor pool and the request processes. It is named and can thus be
    started and stopped at will.
    
    An acceptor pool is a pool of processes whose only role is to accept
    new connections. It's good practice to have many of these processes
    as they are very cheap and allow much quicker response when you get
    many connections. Of course, as with everything else, you should
    **benchmark** before you decide what's best for you.
    
    Cowboy includes a TCP transport handler for HTTP and an SSL transport
    handler for HTTPS. The transport handlers can of course be reused for
    other protocols like FTP or IRC.
    
    The HTTP protocol requires one last thing to continue: dispatching rules.
    Don't worry about it right now though and continue reading, it'll all
    be explained.
    
    You can start and stop listeners by calling `cowboy:start_listener/6` and
    `cowboy:stop_listener/1` respectively.
    
    The following example demonstrates the startup of a very simple listener.
    
    ``` erlang
    application:start(cowboy),
    Dispatch = [
        %% {Host, list({Path, Handler, Opts})}
        {'_', [{'_', my_handler, []}]}
    ],
    %% Name, NbAcceptors, Transport, TransOpts, Protocol, ProtoOpts
    cowboy:start_listener(my_http_listener, 100,
        cowboy_tcp_transport, [{port, 8080}],
        cowboy_http_protocol, [{dispatch, Dispatch}]
    ).
    ```
    
    This is not enough though, you must also write the my_handler module
    to process the incoming HTTP requests. Of course Cowboy comes with
    predefined handlers for specific tasks but most of the time you'll
    want to write your own handlers for your application.
    
    Following is an example of a "Hello World!" HTTP handler.
    
    ``` erlang
    -module(my_handler).
    -export([init/3, handle/2, terminate/2]).
    
    init({tcp, http}, Req, Opts) ->
        {ok, Req, undefined_state}.
    
    handle(Req, State) ->
        {ok, Req2} = cowboy_http_req:reply(200, [], <<"Hello World!">>, Req),
        {ok, Req2, State}.
    
    terminate(Req, State) ->
        ok.
    ```
    
    You can also write handlers that do not reply directly. Instead, such handlers
    will wait for an Erlang message from another process and only reply when
    receiving such message, or timeout if it didn't arrive in time.
    
    This is especially useful for long-polling functionality, as Cowboy will handle
    process hibernation and timeouts properly, preventing mistakes if you were to
    write the code yourself. An handler of that kind can be defined like this:
    
    ``` erlang
    -module(my_loop_handler).
    -export([init/3, info/3, terminate/2]).
    
    -define(TIMEOUT, 60000).
    
    init({tcp, http}, Req, Opts) ->
    	{loop, Req, undefined_state, ?TIMEOUT, hibernate}.
    
    info({reply, Body}, Req, State) ->
    	{ok, Req2} = cowboy_http_req:reply(200, [], Body, Req),
    	{ok, Req2, State};
    info(Message, Req, State) ->
    	{loop, Req, State, hibernate}.
    
    terminate(Req, State) ->
    	ok.
    ```
    
    It is of course possible to combine both type of handlers together as long as
    you return the proper tuple from init/3.
    
    **Note**: versions prior to `0.4.0` used the
    [quoted](https://github.com/klaar/quoted.erl) library instead of the built in
    `cowboy_http:urldecode/2` function. If you want to retain this you must add it
    as a dependency to your application and add the following cowboy_http_protocol
    option:
    
    ``` erlang
        {urldecode, {fun quoted:from_url/2, quoted:make([])}}
    ```
    
    Continue reading to learn how to dispatch rules and handle requests.
    
    Dispatch rules
    --------------
    
    Cowboy allows you to dispatch HTTP requests directly to a specific handler
    based on the hostname and path information from the request. It also lets
    you define static options for the handler directly in the rules.
    
    To match the hostname and path, Cowboy requires a list of tokens. For
    example, to match the "dev-extend.eu" domain name, you must specify
    `[<<"dev-extend">>, <<"eu">>]`. Or, to match the "/path/to/my/resource"
    you must use `[<<"path">>, <<"to">>, <<"my">>, <<"resource">>]`. All the
    tokens must be given as binary.
    
    You can use the special token `'_'` (the atom underscore) to indicate that
    you accept anything in that position. For example if you have both
    "dev-extend.eu" and "dev-extend.fr" domains, you can use the match spec
    `[<<"dev-extend">>, '_']` to match any top level extension.
    
    Finally, you can also match multiple leading segments of the domain name and
    multiple trailing segments of the request path using the atom `'...'` (the atom
    ellipsis) respectively as the first host token or the last path token. For
    example, host rule `['...', <<"dev-extend">>, <<"eu">>]` can match both
    "cowboy.bugs.dev-extend.eu" and "dev-extend.eu" and path rule
    `[<<"projects">>, '...']` can match both "/projects" and
    "/projects/cowboy/issues/42". The host leading segments and the path trailing
    segments can later be retrieved through `cowboy_http_req:host_info/1` and
    `cowboy_http_req:path_info/1`.
    
    Any other atom used as a token will bind the value to this atom when
    matching. To follow on our hostnames example, `[<<"dev-extend">>, ext]`
    would bind the values `<<"eu">>` and `<<"fr">>` to the ext atom, that you
    can later retrieve in your handler by calling `cowboy_http_req:binding/{2,3}`.
    
    You can also accept any match spec by using the atom `'_'` directly instead of
    a list of tokens. Our hello world example above uses this to forward all
    requests to a single handler.
    
    There is currently no way to match multiple tokens at once.
    
    Requests handling
    -----------------
    
    Requests are passed around in the Request variable. Although they are
    defined as a record, it is recommended to access them only through the
    cowboy_http_req module API.
    
    You can retrieve the HTTP method, HTTP version, peer address and port,
    host tokens, raw host, used port, path tokens, raw path, query string
    values, bound values from the dispatch step, header values from the
    request. You can also read the request body, if any, optionally parsing
    it as a query string. Finally, the request allows you to send a response
    to the client.
    
    See the cowboy_http_req module for more information.
    
    Websockets
    ----------
    
    The Websocket protocol is built upon the HTTP protocol. It first sends
    an HTTP request for an handshake, performs it and then switches
    to Websocket. Therefore you need to write a standard HTTP handler to
    confirm the handshake should be completed and then the Websocket-specific
    callbacks.
    
    A simple handler doing nothing but sending a repetitive message using
    Websocket would look like this:
    
    ``` erlang
    -module(my_ws_handler).
    -export([init/3]).
    -export([websocket_init/3, websocket_handle/3,
        websocket_info/3, websocket_terminate/3]).
    
    init({tcp, http}, Req, Opts) ->
        {upgrade, protocol, cowboy_http_websocket}.
    
    websocket_init(TransportName, Req, _Opts) ->
        erlang:start_timer(1000, self(), <<"Hello!">>),
        {ok, Req, undefined_state}.
    
    websocket_handle({text, Msg}, Req, State) ->
        {reply, {text, << "That's what she said! ", Msg/binary >>}, Req, State};
    websocket_handle(_Data, Req, State) ->
        {ok, Req, State}.
    
    websocket_info({timeout, _Ref, Msg}, Req, State) ->
        erlang:start_timer(1000, self(), <<"How' you doin'?">>),
        {reply, {text, Msg}, Req, State};
    websocket_info(_Info, Req, State) ->
        {ok, Req, State}.
    
    websocket_terminate(_Reason, _Req, _State) ->
        ok.
    ```
    
    Of course you can have an HTTP handler doing both HTTP and Websocket
    handling, but for the sake of this example we're ignoring the HTTP
    part entirely.
    
    As the Websocket protocol is still a draft the API is subject to change
    regularly when support to the most recent drafts gets added. Features may
    be added, changed or removed before the protocol gets finalized. Cowboy
    tries to implement all drafts transparently and give a single interface to
    handle them all, however.
    
    Using Cowboy with other protocols
    ---------------------------------
    
    One of the strengths of Cowboy is of course that you can use it with any
    protocol you want. The only downside is that if it's not HTTP, you'll
    probably have to write the protocol handler yourself.
    
    The only exported function a protocol handler needs is the start_link/4
    function, with arguments ListenerPid, Socket, Transport and Opts. ListenerPid
    is the pid to the listener's gen_server, managing the connections. Socket is of
    course the client socket; Transport is the module name of the chosen transport
    handler and Opts is protocol options defined when starting the listener.
    
    After initializing your protocol, it is recommended to call the
    function cowboy:accept_ack/1 with the ListenerPid as argument,
    as it will ensure Cowboy has been able to fully initialize the socket.
    Anything you do past this point is up to you!
    
    If you need to change some socket options, like enabling raw mode for example,
    you can call the Transport:setopts/2 function. It is the protocol's
    responsability to manage the socket usage, there should be no need for an user
    to specify that kind of options while starting a listener.
    
    You should definitely look at the cowboy_http_protocol module for a great
    example of fast request handling if you need to. Otherwise it's probably
    safe to use `{active, once}` mode and handle everything as it comes.
    
    Note that while you technically can run a protocol handler directly as a
    gen_server or a gen_fsm, it's probably not a good idea, as the only call
    you'll ever receive from Cowboy is the start_link/4 call. On the other
    hand, feel free to write a very basic protocol handler which then forwards
    requests to a gen_server or gen_fsm. By doing so however you must take
    care to supervise their processes as Cowboy only knows about the protocol
    handler itself.
    rabbitmq-server-3.2.4/plugins-src/cowboy-wrapper/cowboy-git/src/0000755000000000000000000000000012305126066023424 5ustar  rootrootrabbitmq-server-3.2.4/plugins-src/cowboy-wrapper/cowboy-git/src/cowboy_bstr.erl0000644000000000000000000000520612305126066026467 0ustar  rootroot%% Copyright (c) 2011, Loïc Hoguin 
    %%
    %% Permission to use, copy, modify, and/or distribute this software for any
    %% purpose with or without fee is hereby granted, provided that the above
    %% copyright notice and this permission notice appear in all copies.
    %%
    %% THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
    %% WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
    %% MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
    %% ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
    %% WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
    %% ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
    %% OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
    
    %% @doc Binary string manipulation.
    -module(cowboy_bstr).
    
    -export([to_lower/1]). %% Binary strings.
    -export([char_to_lower/1, char_to_upper/1]). %% Characters.
    
    %% @doc Convert a binary string to lowercase.
    -spec to_lower(binary()) -> binary().
    to_lower(L) ->
    	<< << (char_to_lower(C)) >> || << C >> <= L >>.
    
    %% @doc Convert [A-Z] characters to lowercase.
    %% @end
    %% We gain noticeable speed by matching each value directly.
    -spec char_to_lower(char()) -> char().
    char_to_lower($A) -> $a;
    char_to_lower($B) -> $b;
    char_to_lower($C) -> $c;
    char_to_lower($D) -> $d;
    char_to_lower($E) -> $e;
    char_to_lower($F) -> $f;
    char_to_lower($G) -> $g;
    char_to_lower($H) -> $h;
    char_to_lower($I) -> $i;
    char_to_lower($J) -> $j;
    char_to_lower($K) -> $k;
    char_to_lower($L) -> $l;
    char_to_lower($M) -> $m;
    char_to_lower($N) -> $n;
    char_to_lower($O) -> $o;
    char_to_lower($P) -> $p;
    char_to_lower($Q) -> $q;
    char_to_lower($R) -> $r;
    char_to_lower($S) -> $s;
    char_to_lower($T) -> $t;
    char_to_lower($U) -> $u;
    char_to_lower($V) -> $v;
    char_to_lower($W) -> $w;
    char_to_lower($X) -> $x;
    char_to_lower($Y) -> $y;
    char_to_lower($Z) -> $z;
    char_to_lower(Ch) -> Ch.
    
    %% @doc Convert [a-z] characters to uppercase.
    -spec char_to_upper(char()) -> char().
    char_to_upper($a) -> $A;
    char_to_upper($b) -> $B;
    char_to_upper($c) -> $C;
    char_to_upper($d) -> $D;
    char_to_upper($e) -> $E;
    char_to_upper($f) -> $F;
    char_to_upper($g) -> $G;
    char_to_upper($h) -> $H;
    char_to_upper($i) -> $I;
    char_to_upper($j) -> $J;
    char_to_upper($k) -> $K;
    char_to_upper($l) -> $L;
    char_to_upper($m) -> $M;
    char_to_upper($n) -> $N;
    char_to_upper($o) -> $O;
    char_to_upper($p) -> $P;
    char_to_upper($q) -> $Q;
    char_to_upper($r) -> $R;
    char_to_upper($s) -> $S;
    char_to_upper($t) -> $T;
    char_to_upper($u) -> $U;
    char_to_upper($v) -> $V;
    char_to_upper($w) -> $W;
    char_to_upper($x) -> $X;
    char_to_upper($y) -> $Y;
    char_to_upper($z) -> $Z;
    char_to_upper(Ch) -> Ch.
    rabbitmq-server-3.2.4/plugins-src/cowboy-wrapper/cowboy-git/src/cowboy_sup.erl0000644000000000000000000000244112305126066026322 0ustar  rootroot%% Copyright (c) 2011, Loïc Hoguin 
    %%
    %% Permission to use, copy, modify, and/or distribute this software for any
    %% purpose with or without fee is hereby granted, provided that the above
    %% copyright notice and this permission notice appear in all copies.
    %%
    %% THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
    %% WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
    %% MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
    %% ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
    %% WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
    %% ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
    %% OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
    
    %% @private
    -module(cowboy_sup).
    -behaviour(supervisor).
    
    -export([start_link/0]). %% API.
    -export([init/1]). %% supervisor.
    
    -define(SUPERVISOR, ?MODULE).
    
    %% API.
    
    -spec start_link() -> {ok, pid()}.
    start_link() ->
    	supervisor:start_link({local, ?SUPERVISOR}, ?MODULE, []).
    
    %% supervisor.
    
    -spec init([]) -> {ok, {{one_for_one, 10, 10}, [{_, _, _, _, _, _}, ...]}}.
    init([]) ->
    	Procs = [{cowboy_clock, {cowboy_clock, start_link, []},
    		permanent, 5000, worker, [cowboy_clock]}],
    	{ok, {{one_for_one, 10, 10}, Procs}}.
    rabbitmq-server-3.2.4/plugins-src/cowboy-wrapper/cowboy-git/src/cowboy_listener.erl0000644000000000000000000001443612305126066027347 0ustar  rootroot%% Copyright (c) 2011, Loïc Hoguin 
    %%
    %% Permission to use, copy, modify, and/or distribute this software for any
    %% purpose with or without fee is hereby granted, provided that the above
    %% copyright notice and this permission notice appear in all copies.
    %%
    %% THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
    %% WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
    %% MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
    %% ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
    %% WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
    %% ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
    %% OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
    
    %% @doc Public API for managing listeners.
    -module(cowboy_listener).
    -behaviour(gen_server).
    
    -export([start_link/0, stop/1,
    	add_connection/3, move_connection/3, remove_connection/2, wait/3]). %% API.
    -export([init/1, handle_call/3, handle_cast/2,
    	handle_info/2, terminate/2, code_change/3]). %% gen_server.
    
    -record(state, {
    	req_pools = [] :: [{atom(), non_neg_integer()}],
    	reqs_table,
    	queue = []
    }).
    
    %% API.
    
    %% @private
    %%
    %% We set the process priority to high because cowboy_listener is the central
    %% gen_server in Cowboy and is used to manage all the incoming connections.
    %% Setting the process priority to high ensures the connection-related code
    %% will always be executed when a connection needs it, allowing Cowboy to
    %% scale far beyond what it would with a normal priority.
    -spec start_link() -> {ok, pid()}.
    start_link() ->
    	gen_server:start_link(?MODULE, [], [{spawn_opt, [{priority, high}]}]).
    
    %% @private
    -spec stop(pid()) -> stopped.
    stop(ServerPid) ->
    	gen_server:call(ServerPid, stop).
    
    %% @doc Add a connection to the given pool in the listener.
    %%
    %% Pools of connections are used to restrict the maximum number of connections
    %% depending on their type. By default, Cowboy add all connections to the
    %% pool default. It also checks for the maximum number of connections
    %% in that pool before accepting again.
    %%
    %% When a process managing a connection dies, the process is removed from the
    %% pool. If the socket has been sent to another process, it is up to the
    %% protocol code to inform the listener of the new ConnPid by removing
    %% the previous and adding the new one.
    -spec add_connection(pid(), atom(), pid()) -> {ok, non_neg_integer()}.
    add_connection(ServerPid, Pool, ConnPid) ->
    	gen_server:call(ServerPid, {add_connection, Pool, ConnPid}).
    
    %% @doc Move a connection from one pool to another.
    -spec move_connection(pid(), atom(), pid()) -> ok.
    move_connection(ServerPid, DestPool, ConnPid) ->
    	gen_server:cast(ServerPid, {move_connection, DestPool, ConnPid}).
    
    %% @doc Remove the given connection from its pool.
    -spec remove_connection(pid(), pid()) -> ok.
    remove_connection(ServerPid, ConnPid) ->
    	gen_server:cast(ServerPid, {remove_connection, ConnPid}).
    
    %% @doc Wait until the number of connections in the given pool gets below
    %% the given threshold.
    %%
    %% This function will not return until the number of connections in the pool
    %% gets below MaxConns. It makes use of gen_server:reply/2
    %% to make the process wait for a reply indefinitely.
    -spec wait(pid(), atom(), non_neg_integer()) -> ok.
    wait(ServerPid, Pool, MaxConns) ->
    	gen_server:call(ServerPid, {wait, Pool, MaxConns}, infinity).
    
    %% gen_server.
    
    %% @private
    -spec init([]) -> {ok, #state{}}.
    init([]) ->
    	ReqsTablePid = ets:new(requests_table, [set, private]),
    	{ok, #state{reqs_table=ReqsTablePid}}.
    
    %% @private
    -spec handle_call(_, _, State)
    	-> {reply, ignored, State} | {stop, normal, stopped, State}.
    handle_call({add_connection, Pool, ConnPid}, _From, State=#state{
    		req_pools=Pools, reqs_table=ReqsTable}) ->
    	MonitorRef = erlang:monitor(process, ConnPid),
    	{NbConnsRet, Pools2} = case lists:keyfind(Pool, 1, Pools) of
    		false ->
    			{1, [{Pool, 1}|Pools]};
    		{Pool, NbConns} ->
    			NbConns2 = NbConns + 1,
    			{NbConns2, [{Pool, NbConns2}|lists:keydelete(Pool, 1, Pools)]}
    	end,
    	ets:insert(ReqsTable, {ConnPid, {MonitorRef, Pool}}),
    	{reply, {ok, NbConnsRet}, State#state{req_pools=Pools2}};
    handle_call({wait, Pool, MaxConns}, From, State=#state{
    		req_pools=Pools, queue=Queue}) ->
    	case lists:keyfind(Pool, 1, Pools) of
    		{Pool, NbConns} when NbConns > MaxConns ->
    			{noreply, State#state{queue=[From|Queue]}};
    		_Any ->
    			{reply, ok, State}
    	end;
    handle_call(stop, _From, State) ->
    	{stop, normal, stopped, State};
    handle_call(_Request, _From, State) ->
    	{reply, ignored, State}.
    
    %% @private
    -spec handle_cast(_, State) -> {noreply, State}.
    handle_cast({move_connection, DestPool, ConnPid}, State=#state{
    		req_pools=Pools, reqs_table=ReqsTable}) ->
    	{MonitorRef, SrcPool} = ets:lookup_element(ReqsTable, ConnPid, 2),
    	ets:insert(ReqsTable, {ConnPid, {MonitorRef, DestPool}}),
    	{SrcPool, SrcNbConns} = lists:keyfind(SrcPool, 1, Pools),
    	DestNbConns = case lists:keyfind(DestPool, 1, Pools) of
    		false -> 1;
    		{DestPool, NbConns} -> NbConns + 1
    	end,
    	Pools2 = lists:keydelete(SrcPool, 1, lists:keydelete(DestPool, 1, Pools)),
    	Pools3 = [{SrcPool, SrcNbConns - 1}, {DestPool, DestNbConns}|Pools2],
    	{noreply, State#state{req_pools=Pools3}};
    handle_cast({remove_connection, ConnPid}, State) ->
    	State2 = remove_pid(ConnPid, State),
    	{noreply, State2};
    handle_cast(_Msg, State) ->
    	{noreply, State}.
    
    %% @private
    -spec handle_info(_, State) -> {noreply, State}.
    handle_info({'DOWN', _Ref, process, Pid, _Info}, State) ->
    	State2 = remove_pid(Pid, State),
    	{noreply, State2};
    handle_info(_Info, State) ->
    	{noreply, State}.
    
    %% @private
    -spec terminate(_, _) -> ok.
    terminate(_Reason, _State) ->
    	ok.
    
    %% @private
    -spec code_change(_, State, _) -> {ok, State}.
    code_change(_OldVsn, State, _Extra) ->
    	{ok, State}.
    
    %% Internal.
    
    %% @private
    -spec remove_pid(pid(), State) -> State.
    remove_pid(Pid, State=#state{
    		req_pools=Pools, reqs_table=ReqsTable, queue=Queue}) ->
    	{MonitorRef, Pool} = ets:lookup_element(ReqsTable, Pid, 2),
    	erlang:demonitor(MonitorRef, [flush]),
    	{Pool, NbConns} = lists:keyfind(Pool, 1, Pools),
    	Pools2 = [{Pool, NbConns - 1}|lists:keydelete(Pool, 1, Pools)],
    	ets:delete(ReqsTable, Pid),
    	case Queue of
    		[] ->
    			State#state{req_pools=Pools2};
    		[Client|Queue2] ->
    			gen_server:reply(Client, ok),
    			State#state{req_pools=Pools2, queue=Queue2}
    	end.
    rabbitmq-server-3.2.4/plugins-src/cowboy-wrapper/cowboy-git/src/cowboy_protocol.erl0000644000000000000000000000541512305126066027360 0ustar  rootroot%% Copyright (c) 2011, Loïc Hoguin 
    %% Copyright (c) 2011, Michiel Hakvoort 
    %%
    %% Permission to use, copy, modify, and/or distribute this software for any
    %% purpose with or without fee is hereby granted, provided that the above
    %% copyright notice and this permission notice appear in all copies.
    %%
    %% THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
    %% WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
    %% MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
    %% ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
    %% WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
    %% ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
    %% OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
    
    %% @doc Cowboy protocol.
    %%
    %% A Cowboy protocol must implement one callback: start_link/4.
    %%
    %% start_link/4 is meant for the initialization of the
    %% protocol process.
    %% It receives the pid to the listener's gen_server, the client socket,
    %% the module name of the chosen transport and the options defined when
    %% starting the listener. The start_link/4 function must follow
    %% the supervisor start function specification.
    %%
    %% After initializing your protocol, it is recommended to call the
    %% function cowboy:accept_ack/1 with the ListenerPid as argument,
    %% as it will ensure Cowboy has been able to fully initialize the socket.
    %% Anything you do past this point is up to you!
    %%
    %% If you need to change some socket options, like enabling raw mode
    %% for example, you can call the Transport:setopts/2 function.
    %% It is the protocol's responsability to manage the socket usage,
    %% there should be no need for an user to specify that kind of options
    %% while starting a listener.
    %%
    %% You should definitely look at the cowboy_http_protocol module for
    %% a great example of fast request handling if you need to.
    %% Otherwise it's probably safe to use {active, once} mode
    %% and handle everything as it comes.
    %%
    %% Note that while you technically can run a protocol handler directly
    %% as a gen_server or a gen_fsm, it's probably not a good idea,
    %% as the only call you'll ever receive from Cowboy is the
    %% start_link/4 call. On the other hand, feel free to write
    %% a very basic protocol handler which then forwards requests to a
    %% gen_server or gen_fsm. By doing so however you must take care to
    %% supervise their processes as Cowboy only knows about the protocol
    %% handler itself.
    -module(cowboy_protocol).
    
    -export([behaviour_info/1]).
    
    %% @private
    -spec behaviour_info(_)
    	-> undefined | [{start_link, 4}, ...].
    behaviour_info(callbacks) ->
    	[{start_link, 4}];
    behaviour_info(_Other) ->
    	undefined.
    rabbitmq-server-3.2.4/plugins-src/cowboy-wrapper/cowboy-git/src/cowboy_cookies.erl0000644000000000000000000002556212305126066027160 0ustar  rootroot%% Copyright 2007 Mochi Media, Inc.
    %% Copyright 2011 Thomas Burdick 
    %%
    %% Permission to use, copy, modify, and/or distribute this software for any
    %% purpose with or without fee is hereby granted, provided that the above
    %% copyright notice and this permission notice appear in all copies.
    %%
    %% THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
    %% WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
    %% MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
    %% ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
    %% WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
    %% ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
    %% OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
    
    %% @doc HTTP Cookie parsing and generating (RFC 2965).
    
    -module(cowboy_cookies).
    
    -export([parse_cookie/1, cookie/3, cookie/2]). %% API.
    
    %% Types.
    -type kv() :: {Name::binary(), Value::binary()}.
    -type kvlist() :: [kv()].
    -type cookie_option() :: {max_age, integer()}
    				| {local_time, calendar:datetime()}
    				| {domain, binary()} | {path, binary()}
    				| {secure, true | false} | {http_only, true | false}.
    -export_type([kv/0, kvlist/0, cookie_option/0]).
    
    -define(QUOTE, $\").
    
    -include_lib("eunit/include/eunit.hrl").
    
    %% API.
    
    %% @doc Parse the contents of a Cookie header field, ignoring cookie
    %% attributes, and return a simple property list.
    -spec parse_cookie(binary()) -> kvlist().
    parse_cookie(<<>>) ->
    	[];
    parse_cookie(Cookie) when is_binary(Cookie) ->
    	parse_cookie(Cookie, []).
    
    %% @equiv cookie(Key, Value, [])
    -spec cookie(binary(), binary()) -> kv().
    cookie(Key, Value) when is_binary(Key) andalso is_binary(Value) ->
    	cookie(Key, Value, []).
    
    %% @doc Generate a Set-Cookie header field tuple.
    -spec cookie(binary(), binary(), [cookie_option()]) -> kv().
    cookie(Key, Value, Options) when is_binary(Key)
    		andalso is_binary(Value) andalso is_list(Options) ->
    	Cookie = <<(any_to_binary(Key))/binary, "=",
    		(quote(Value))/binary, "; Version=1">>,
    	%% Set-Cookie:
    	%%    Comment, Domain, Max-Age, Path, Secure, Version
    	ExpiresPart =
    		case proplists:get_value(max_age, Options) of
    			undefined ->
    				<<"">>;
    			RawAge ->
    				When = case proplists:get_value(local_time, Options) of
    						undefined ->
    							calendar:local_time();
    						LocalTime ->
    							LocalTime
    					end,
    				Age = case RawAge < 0 of
    						true ->
    							0;
    						false ->
    							RawAge
    					end,
    				AgeBinary = quote(Age),
    				CookieDate = age_to_cookie_date(Age, When),
    				<<"; Expires=", CookieDate/binary,
    				"; Max-Age=", AgeBinary/binary>>
    		end,
    	SecurePart =
    		case proplists:get_value(secure, Options) of
    			true ->
    				<<"; Secure">>;
    			_ ->
    				<<"">>
    		end,
    	DomainPart =
    		case proplists:get_value(domain, Options) of
    			undefined ->
    				<<"">>;
    			Domain ->
    				<<"; Domain=", (quote(Domain))/binary>>
    		end,
    	PathPart =
    		case proplists:get_value(path, Options) of
    			undefined ->
    				<<"">>;
    			Path ->
    				<<"; Path=", (quote(Path))/binary>>
    		end,
    	HttpOnlyPart =
    		case proplists:get_value(http_only, Options) of
    			true ->
    				<<"; HttpOnly">>;
    			_ ->
    				<<"">>
    		end,
    	CookieParts = <>,
    	{<<"Set-Cookie">>, CookieParts}.
    
    %% Internal.
    
    %% @doc Check if a character is a white space character.
    is_whitespace($\s) -> true;
    is_whitespace($\t) -> true;
    is_whitespace($\r) -> true;
    is_whitespace($\n) -> true;
    is_whitespace(_) -> false.
    
    %% @doc Check if a character is a seperator.
    is_separator(C) when C < 32 -> true;
    is_separator($\s) -> true;
    is_separator($\t) -> true;
    is_separator($() -> true;
    is_separator($)) -> true;
    is_separator($<) -> true;
    is_separator($>) -> true;
    is_separator($@) -> true;
    is_separator($,) -> true;
    is_separator($;) -> true;
    is_separator($:) -> true;
    is_separator($\\) -> true;
    is_separator(?QUOTE) -> true;
    is_separator($/) -> true;
    is_separator($[) -> true;
    is_separator($]) -> true;
    is_separator($?) -> true;
    is_separator($=) -> true;
    is_separator(${) -> true;
    is_separator($}) -> true;
    is_separator(_) -> false.
    
    %% @doc Check if a binary has an ASCII seperator character.
    has_seperator(<<>>) ->
    	false;
    has_seperator(<<$/, Rest/binary>>) ->
    	has_seperator(Rest);
    has_seperator(<>) ->
    	case is_separator(C) of
    		true ->
    			true;
    		false ->
    			has_seperator(Rest)
    	end.
    
    %% @doc Convert to a binary and raise an error if quoting is required. Quoting
    %% is broken in different ways for different browsers. Its better to simply
    %% avoiding doing it at all.
    %% @end
    -spec quote(term()) -> binary().
    quote(V0) ->
    	V = any_to_binary(V0),
    	case has_seperator(V) of
    		true ->
    			erlang:error({cookie_quoting_required, V});
    		false ->
    			V
    	end.
    
    -spec add_seconds(integer(), calendar:datetime()) -> calendar:datetime().
    add_seconds(Secs, LocalTime) ->
    	Greg = calendar:datetime_to_gregorian_seconds(LocalTime),
    	calendar:gregorian_seconds_to_datetime(Greg + Secs).
    
    -spec age_to_cookie_date(integer(), calendar:datetime()) -> binary().
    age_to_cookie_date(Age, LocalTime) ->
    	cowboy_clock:rfc2109(add_seconds(Age, LocalTime)).
    
    -spec parse_cookie(binary(), kvlist()) -> kvlist().
    parse_cookie(<<>>, Acc) ->
    	lists:reverse(Acc);
    parse_cookie(String, Acc) ->
    	{{Token, Value}, Rest} = read_pair(String),
    	Acc1 = case Token of
    			<<"">> ->
    				Acc;
    			<<"$", _R/binary>> ->
    				Acc;
    			_ ->
    				[{Token, Value} | Acc]
    		end,
    	parse_cookie(Rest, Acc1).
    
    -spec read_pair(binary()) -> {{binary(), binary()}, binary()}.
    read_pair(String) ->
    	{Token, Rest} = read_token(skip_whitespace(String)),
    	{Value, Rest1} = read_value(skip_whitespace(Rest)),
    	{{Token, Value}, skip_past_separator(Rest1)}.
    
    -spec read_value(binary()) -> {binary(), binary()}.
    read_value(<<"=",  Value/binary>>) ->
    	Value1 = skip_whitespace(Value),
    	case Value1 of
    		<> ->
    			read_quoted(Value1);
    		_ ->
    			read_token(Value1)
    	end;
    read_value(String) ->
    	{<<"">>, String}.
    
    -spec read_quoted(binary()) -> {binary(), binary()}.
    read_quoted(<>) ->
    	read_quoted(String, <<"">>).
    
    -spec read_quoted(binary(), binary()) -> {binary(), binary()}.
    read_quoted(<<"">>, Acc) ->
    	{Acc, <<"">>};
    read_quoted(<>, Acc) ->
    	{Acc, Rest};
    read_quoted(<<$\\, Any, Rest/binary>>, Acc) ->
    	read_quoted(Rest, <>);
    read_quoted(<>, Acc) ->
    	read_quoted(Rest, <>).
    
    %% @doc Drop characters while a function returns true.
    binary_dropwhile(_F, <<"">>) ->
    	<<"">>;
    binary_dropwhile(F, String) ->
    	<> = String,
    	case F(C) of
    		true ->
    			binary_dropwhile(F, Rest);
    		false ->
    			String
    	end.
    
    %% @doc Remove leading whitespace.
    -spec skip_whitespace(binary()) -> binary().
    skip_whitespace(String) ->
    	binary_dropwhile(fun is_whitespace/1, String).
    
    %% @doc Split a binary when the current character causes F to return true.
    binary_splitwith(_F, Head, <<>>) ->
    	{Head, <<>>};
    binary_splitwith(F, Head, Tail) ->
    	<> = Tail,
    	case F(C) of
    		true ->
    			{Head, Tail};
    		false ->
    			binary_splitwith(F, <>, NTail)
    	end.
    
    %% @doc Split a binary with a function returning true or false on each char.
    binary_splitwith(F, String) ->
    	binary_splitwith(F, <<>>, String).
    
    %% @doc Split the binary when the next seperator is found.
    -spec read_token(binary()) -> {binary(), binary()}.
    read_token(String) ->
    	binary_splitwith(fun is_separator/1, String).
    
    %% @doc Return string after ; or , characters.
    -spec skip_past_separator(binary()) -> binary().
    skip_past_separator(<<"">>) ->
    	<<"">>;
    skip_past_separator(<<";", Rest/binary>>) ->
    	Rest;
    skip_past_separator(<<",", Rest/binary>>) ->
    	Rest;
    skip_past_separator(<<_C, Rest/binary>>) ->
    	skip_past_separator(Rest).
    
    -spec any_to_binary(binary() | string() | atom() | integer()) -> binary().
    any_to_binary(V) when is_binary(V) ->
    	V;
    any_to_binary(V) when is_list(V) ->
    	erlang:list_to_binary(V);
    any_to_binary(V) when is_atom(V) ->
    	erlang:atom_to_binary(V, latin1);
    any_to_binary(V) when is_integer(V) ->
    	list_to_binary(integer_to_list(V)).
    
    %% Tests.
    
    -ifdef(TEST).
    
    quote_test() ->
    	%% ?assertError eunit macro is not compatible with coverage module
    	_ = try quote(<<":wq">>)
    	catch error:{cookie_quoting_required, <<":wq">>} -> ok
    	end,
    	?assertEqual(<<"foo">>,quote(foo)),
    	ok.
    
    parse_cookie_test() ->
    	%% RFC example
    	C1 = <<"$Version=\"1\"; Customer=\"WILE_E_COYOTE\"; $Path=\"/acme\";
    	Part_Number=\"Rocket_Launcher_0001\"; $Path=\"/acme\";
    	Shipping=\"FedEx\"; $Path=\"/acme\"">>,
    	?assertEqual(
    	[{<<"Customer">>,<<"WILE_E_COYOTE">>},
    		{<<"Part_Number">>,<<"Rocket_Launcher_0001">>},
    		{<<"Shipping">>,<<"FedEx">>}],
    	parse_cookie(C1)),
    	%% Potential edge cases
    	?assertEqual(
    	[{<<"foo">>, <<"x">>}],
    	parse_cookie(<<"foo=\"\\x\"">>)),
    	?assertEqual(
    	[],
    	parse_cookie(<<"=">>)),
    	?assertEqual(
    	[{<<"foo">>, <<"">>}, {<<"bar">>, <<"">>}],
    	parse_cookie(<<"  foo ; bar  ">>)),
    	?assertEqual(
    	[{<<"foo">>, <<"">>}, {<<"bar">>, <<"">>}],
    	parse_cookie(<<"foo=;bar=">>)),
    	?assertEqual(
    	[{<<"foo">>, <<"\";">>}, {<<"bar">>, <<"">>}],
    	parse_cookie(<<"foo = \"\\\";\";bar ">>)),
    	?assertEqual(
    	[{<<"foo">>, <<"\";bar">>}],
    	parse_cookie(<<"foo=\"\\\";bar">>)),
    	?assertEqual(
    	[],
    	parse_cookie(<<"">>)),
    	?assertEqual(
    	[{<<"foo">>, <<"bar">>}, {<<"baz">>, <<"wibble">>}],
    	parse_cookie(<<"foo=bar , baz=wibble ">>)),
    	ok.
    
    domain_test() ->
    	?assertEqual(
    	{<<"Set-Cookie">>,
    		<<"Customer=WILE_E_COYOTE; "
    		"Version=1; "
    		"Domain=acme.com; "
    		"HttpOnly">>},
    	cookie(<<"Customer">>, <<"WILE_E_COYOTE">>,
    			[{http_only, true}, {domain, <<"acme.com">>}])),
    	ok.
    
    local_time_test() ->
    	{<<"Set-Cookie">>, B} = cookie(<<"Customer">>, <<"WILE_E_COYOTE">>,
    							[{max_age, 111}, {secure, true}]),
    
    	?assertMatch(
    	[<<"Customer=WILE_E_COYOTE">>,
    		<<" Version=1">>,
    		<<" Expires=", _R/binary>>,
    		<<" Max-Age=111">>,
    		<<" Secure">>],
    	binary:split(B, <<";">>, [global])),
    	ok.
    
    -spec cookie_test() -> no_return(). %% Not actually true, just a bad option.
    cookie_test() ->
    	C1 = {<<"Set-Cookie">>,
    		<<"Customer=WILE_E_COYOTE; "
    		"Version=1; "
    		"Path=/acme">>},
    	C1 = cookie(<<"Customer">>, <<"WILE_E_COYOTE">>, [{path, <<"/acme">>}]),
    
    	C1 = cookie(<<"Customer">>, <<"WILE_E_COYOTE">>,
    				[{path, <<"/acme">>}, {badoption, <<"negatory">>}]),
    
    	{<<"Set-Cookie">>,<<"=NoKey; Version=1">>}
    		= cookie(<<"">>, <<"NoKey">>, []),
    	{<<"Set-Cookie">>,<<"=NoKey; Version=1">>}
    		= cookie(<<"">>, <<"NoKey">>),
    	LocalTime = calendar:universal_time_to_local_time(
    		{{2007, 5, 15}, {13, 45, 33}}),
    	C2 = {<<"Set-Cookie">>,
    		<<"Customer=WILE_E_COYOTE; "
    		"Version=1; "
    		"Expires=Tue, 15 May 2007 13:45:33 GMT; "
    		"Max-Age=0">>},
    	C2 = cookie(<<"Customer">>, <<"WILE_E_COYOTE">>,
    				[{max_age, -111}, {local_time, LocalTime}]),
    	C3 = {<<"Set-Cookie">>,
    		<<"Customer=WILE_E_COYOTE; "
    		"Version=1; "
    		"Expires=Wed, 16 May 2007 13:45:50 GMT; "
    		"Max-Age=86417">>},
    	C3 = cookie(<<"Customer">>, <<"WILE_E_COYOTE">>,
    				[{max_age, 86417}, {local_time, LocalTime}]),
    	ok.
    
    -endif.
    rabbitmq-server-3.2.4/plugins-src/cowboy-wrapper/cowboy-git/src/cowboy_http_handler.erl0000644000000000000000000000410612305126066030167 0ustar  rootroot%% Copyright (c) 2011, Loïc Hoguin 
    %%
    %% Permission to use, copy, modify, and/or distribute this software for any
    %% purpose with or without fee is hereby granted, provided that the above
    %% copyright notice and this permission notice appear in all copies.
    %%
    %% THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
    %% WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
    %% MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
    %% ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
    %% WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
    %% ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
    %% OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
    
    %% @doc Handler for HTTP requests.
    %%
    %% HTTP handlers must implement three callbacks: init/3,
    %% handle/2 and terminate/2, called one after another in
    %% that order.
    %%
    %% init/3 is meant for initialization. It receives information about
    %% the transport and protocol used, along with the handler options from the
    %% dispatch list, and allows you to upgrade the protocol if needed. You can
    %% define a request-wide state here.
    %%
    %% handle/2 is meant for handling the request. It receives the
    %% request and the state previously defined.
    %%
    %% terminate/2 is meant for cleaning up. It also receives the
    %% request and the state previously defined.
    %%
    %% You do not have to read the request body or even send a reply if you do
    %% not need to. Cowboy will properly handle these cases and clean-up afterwards.
    %% In doubt it'll simply close the connection.
    %%
    %% Note that when upgrading the connection to WebSocket you do not need to
    %% define the handle/2 and terminate/2 callbacks.
    -module(cowboy_http_handler).
    
    -export([behaviour_info/1]).
    
    %% @private
    -spec behaviour_info(_)
    	-> undefined | [{handle, 2} | {init, 3} | {terminate, 2}, ...].
    behaviour_info(callbacks) ->
    	[{init, 3}, {handle, 2}, {terminate, 2}];
    behaviour_info(_Other) ->
    	undefined.
    rabbitmq-server-3.2.4/plugins-src/cowboy-wrapper/cowboy-git/src/cowboy_http_protocol.erl0000644000000000000000000004516612305126066030426 0ustar  rootroot%% Copyright (c) 2011, Loïc Hoguin 
    %% Copyright (c) 2011, Anthony Ramine 
    %%
    %% Permission to use, copy, modify, and/or distribute this software for any
    %% purpose with or without fee is hereby granted, provided that the above
    %% copyright notice and this permission notice appear in all copies.
    %%
    %% THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
    %% WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
    %% MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
    %% ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
    %% WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
    %% ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
    %% OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
    
    %% @doc HTTP protocol handler.
    %%
    %% The available options are:
    %% 
    %%
    dispatch
    The dispatch list for this protocol.
    %%
    max_empty_lines
    Max number of empty lines before a request. %% Defaults to 5.
    %%
    timeout
    Time in milliseconds before an idle %% connection is closed. Defaults to 5000 milliseconds.
    %%
    urldecode
    Function and options argument to use when decoding %% URL encoded strings. Defaults to `{fun cowboy_http:urldecode/2, crash}'. %%
    %%
    %% %% Note that there is no need to monitor these processes when using Cowboy as %% an application as it already supervises them under the listener supervisor. %% %% @see cowboy_dispatcher %% @see cowboy_http_handler -module(cowboy_http_protocol). -behaviour(cowboy_protocol). -export([start_link/4]). %% API. -export([init/4, parse_request/1, handler_loop/3]). %% FSM. -include("include/http.hrl"). -include_lib("eunit/include/eunit.hrl"). -record(state, { listener :: pid(), socket :: inet:socket(), transport :: module(), dispatch :: cowboy_dispatcher:dispatch_rules(), handler :: {module(), any()}, urldecode :: {fun((binary(), T) -> binary()), T}, req_empty_lines = 0 :: integer(), max_empty_lines :: integer(), req_keepalive = 1 :: integer(), max_keepalive :: integer(), max_line_length :: integer(), timeout :: timeout(), buffer = <<>> :: binary(), hibernate = false, loop_timeout = infinity :: timeout(), loop_timeout_ref }). %% API. %% @doc Start an HTTP protocol process. -spec start_link(pid(), inet:socket(), module(), any()) -> {ok, pid()}. start_link(ListenerPid, Socket, Transport, Opts) -> Pid = spawn_link(?MODULE, init, [ListenerPid, Socket, Transport, Opts]), {ok, Pid}. %% FSM. %% @private -spec init(pid(), inet:socket(), module(), any()) -> ok | none(). init(ListenerPid, Socket, Transport, Opts) -> Dispatch = proplists:get_value(dispatch, Opts, []), MaxEmptyLines = proplists:get_value(max_empty_lines, Opts, 5), MaxKeepalive = proplists:get_value(max_keepalive, Opts, infinity), MaxLineLength = proplists:get_value(max_line_length, Opts, 4096), Timeout = proplists:get_value(timeout, Opts, 5000), URLDecDefault = {fun cowboy_http:urldecode/2, crash}, URLDec = proplists:get_value(urldecode, Opts, URLDecDefault), ok = cowboy:accept_ack(ListenerPid), wait_request(#state{listener=ListenerPid, socket=Socket, transport=Transport, dispatch=Dispatch, max_empty_lines=MaxEmptyLines, max_keepalive=MaxKeepalive, max_line_length=MaxLineLength, timeout=Timeout, urldecode=URLDec}). %% @private -spec parse_request(#state{}) -> ok | none(). %% We limit the length of the Request-line to MaxLength to avoid endlessly %% reading from the socket and eventually crashing. parse_request(State=#state{buffer=Buffer, max_line_length=MaxLength}) -> case erlang:decode_packet(http_bin, Buffer, []) of {ok, Request, Rest} -> request(Request, State#state{buffer=Rest}); {more, _Length} when byte_size(Buffer) > MaxLength -> error_terminate(413, State); {more, _Length} -> wait_request(State); {error, _Reason} -> error_terminate(400, State) end. -spec wait_request(#state{}) -> ok | none(). wait_request(State=#state{socket=Socket, transport=Transport, timeout=T, buffer=Buffer}) -> case Transport:recv(Socket, 0, T) of {ok, Data} -> parse_request(State#state{ buffer= << Buffer/binary, Data/binary >>}); {error, _Reason} -> terminate(State) end. -spec request({http_request, cowboy_http:method(), cowboy_http:uri(), cowboy_http:version()}, #state{}) -> ok | none(). request({http_request, _Method, _URI, Version}, State) when Version =/= {1, 0}, Version =/= {1, 1} -> error_terminate(505, State); request({http_request, Method, {abs_path, AbsPath}, Version}, State=#state{socket=Socket, transport=Transport, urldecode={URLDecFun, URLDecArg}=URLDec}) -> URLDecode = fun(Bin) -> URLDecFun(Bin, URLDecArg) end, {Path, RawPath, Qs} = cowboy_dispatcher:split_path(AbsPath, URLDecode), ConnAtom = version_to_connection(Version), parse_header(#http_req{socket=Socket, transport=Transport, connection=ConnAtom, pid=self(), method=Method, version=Version, path=Path, raw_path=RawPath, raw_qs=Qs, urldecode=URLDec}, State); request({http_request, Method, '*', Version}, State=#state{socket=Socket, transport=Transport, urldecode=URLDec}) -> ConnAtom = version_to_connection(Version), parse_header(#http_req{socket=Socket, transport=Transport, connection=ConnAtom, pid=self(), method=Method, version=Version, path='*', raw_path= <<"*">>, raw_qs= <<>>, urldecode=URLDec}, State); request({http_request, _Method, _URI, _Version}, State) -> error_terminate(501, State); request({http_error, <<"\r\n">>}, State=#state{req_empty_lines=N, max_empty_lines=N}) -> error_terminate(400, State); request({http_error, <<"\r\n">>}, State=#state{req_empty_lines=N}) -> parse_request(State#state{req_empty_lines=N + 1}); request(_Any, State) -> error_terminate(400, State). -spec parse_header(#http_req{}, #state{}) -> ok | none(). parse_header(Req, State=#state{buffer=Buffer, max_line_length=MaxLength}) -> case erlang:decode_packet(httph_bin, Buffer, []) of {ok, Header, Rest} -> header(Header, Req, State#state{buffer=Rest}); {more, _Length} when byte_size(Buffer) > MaxLength -> error_terminate(413, State); {more, _Length} -> wait_header(Req, State); {error, _Reason} -> error_terminate(400, State) end. -spec wait_header(#http_req{}, #state{}) -> ok | none(). wait_header(Req, State=#state{socket=Socket, transport=Transport, timeout=T, buffer=Buffer}) -> case Transport:recv(Socket, 0, T) of {ok, Data} -> parse_header(Req, State#state{ buffer= << Buffer/binary, Data/binary >>}); {error, timeout} -> error_terminate(408, State); {error, closed} -> terminate(State) end. -spec header({http_header, integer(), cowboy_http:header(), any(), binary()} | http_eoh, #http_req{}, #state{}) -> ok | none(). header({http_header, _I, 'Host', _R, RawHost}, Req=#http_req{ transport=Transport, host=undefined}, State) -> RawHost2 = cowboy_bstr:to_lower(RawHost), case catch cowboy_dispatcher:split_host(RawHost2) of {Host, RawHost3, undefined} -> Port = default_port(Transport:name()), dispatch(fun parse_header/2, Req#http_req{ host=Host, raw_host=RawHost3, port=Port, headers=[{'Host', RawHost3}|Req#http_req.headers]}, State); {Host, RawHost3, Port} -> dispatch(fun parse_header/2, Req#http_req{ host=Host, raw_host=RawHost3, port=Port, headers=[{'Host', RawHost3}|Req#http_req.headers]}, State); {'EXIT', _Reason} -> error_terminate(400, State) end; %% Ignore Host headers if we already have it. header({http_header, _I, 'Host', _R, _V}, Req, State) -> parse_header(Req, State); header({http_header, _I, 'Connection', _R, Connection}, Req=#http_req{headers=Headers}, State) -> Req2 = Req#http_req{headers=[{'Connection', Connection}|Headers]}, {ConnTokens, Req3} = cowboy_http_req:parse_header('Connection', Req2), ConnAtom = cowboy_http:connection_to_atom(ConnTokens), parse_header(Req3#http_req{connection=ConnAtom}, State); header({http_header, _I, Field, _R, Value}, Req, State) -> Field2 = format_header(Field), parse_header(Req#http_req{headers=[{Field2, Value}|Req#http_req.headers]}, State); %% The Host header is required in HTTP/1.1. header(http_eoh, #http_req{version={1, 1}, host=undefined}, State) -> error_terminate(400, State); %% It is however optional in HTTP/1.0. header(http_eoh, Req=#http_req{version={1, 0}, transport=Transport, host=undefined}, State=#state{buffer=Buffer}) -> Port = default_port(Transport:name()), dispatch(fun handler_init/2, Req#http_req{host=[], raw_host= <<>>, port=Port, buffer=Buffer}, State#state{buffer= <<>>}); header(http_eoh, Req, State=#state{buffer=Buffer}) -> handler_init(Req#http_req{buffer=Buffer}, State#state{buffer= <<>>}); header(_Any, _Req, State) -> error_terminate(400, State). -spec dispatch(fun((#http_req{}, #state{}) -> ok), #http_req{}, #state{}) -> ok | none(). dispatch(Next, Req=#http_req{host=Host, path=Path}, State=#state{dispatch=Dispatch}) -> %% @todo We should allow a configurable chain of handlers here to %% allow things like url rewriting, site-wide authentication, %% optional dispatching, and more. It would default to what %% we are doing so far. case cowboy_dispatcher:match(Host, Path, Dispatch) of {ok, Handler, Opts, Binds, HostInfo, PathInfo} -> Next(Req#http_req{host_info=HostInfo, path_info=PathInfo, bindings=Binds}, State#state{handler={Handler, Opts}}); {error, notfound, host} -> error_terminate(400, State); {error, notfound, path} -> error_terminate(404, State) end. -spec handler_init(#http_req{}, #state{}) -> ok | none(). handler_init(Req, State=#state{transport=Transport, handler={Handler, Opts}}) -> try Handler:init({Transport:name(), http}, Req, Opts) of {ok, Req2, HandlerState} -> handler_handle(HandlerState, Req2, State); {loop, Req2, HandlerState} -> handler_before_loop(HandlerState, Req2, State); {loop, Req2, HandlerState, hibernate} -> handler_before_loop(HandlerState, Req2, State#state{hibernate=true}); {loop, Req2, HandlerState, Timeout} -> handler_before_loop(HandlerState, Req2, State#state{loop_timeout=Timeout}); {loop, Req2, HandlerState, Timeout, hibernate} -> handler_before_loop(HandlerState, Req2, State#state{hibernate=true, loop_timeout=Timeout}); {shutdown, Req2, HandlerState} -> handler_terminate(HandlerState, Req2, State); %% @todo {upgrade, transport, Module} {upgrade, protocol, Module} -> upgrade_protocol(Req, State, Module) catch Class:Reason -> error_terminate(500, State), error_logger:error_msg( "** Handler ~p terminating in init/3~n" " for the reason ~p:~p~n" "** Options were ~p~n" "** Request was ~p~n** Stacktrace: ~p~n~n", [Handler, Class, Reason, Opts, Req, erlang:get_stacktrace()]) end. -spec upgrade_protocol(#http_req{}, #state{}, atom()) -> ok | none(). upgrade_protocol(Req, State=#state{listener=ListenerPid, handler={Handler, Opts}}, Module) -> case Module:upgrade(ListenerPid, Handler, Opts, Req) of {UpgradeRes, Req2} -> next_request(Req2, State, UpgradeRes); _Any -> terminate(State) end. -spec handler_handle(any(), #http_req{}, #state{}) -> ok | none(). handler_handle(HandlerState, Req, State=#state{handler={Handler, Opts}}) -> try Handler:handle(Req, HandlerState) of {ok, Req2, HandlerState2} -> terminate_request(HandlerState2, Req2, State) catch Class:Reason -> error_logger:error_msg( "** Handler ~p terminating in handle/2~n" " for the reason ~p:~p~n" "** Options were ~p~n** Handler state was ~p~n" "** Request was ~p~n** Stacktrace: ~p~n~n", [Handler, Class, Reason, Opts, HandlerState, Req, erlang:get_stacktrace()]), handler_terminate(HandlerState, Req, State), error_terminate(500, State) end. %% We don't listen for Transport closes because that would force us %% to receive data and buffer it indefinitely. -spec handler_before_loop(any(), #http_req{}, #state{}) -> ok | none(). handler_before_loop(HandlerState, Req, State=#state{hibernate=true}) -> State2 = handler_loop_timeout(State), erlang:hibernate(?MODULE, handler_loop, [HandlerState, Req, State2#state{hibernate=false}]); handler_before_loop(HandlerState, Req, State) -> State2 = handler_loop_timeout(State), handler_loop(HandlerState, Req, State2). %% Almost the same code can be found in cowboy_http_websocket. -spec handler_loop_timeout(#state{}) -> #state{}. handler_loop_timeout(State=#state{loop_timeout=infinity}) -> State#state{loop_timeout_ref=undefined}; handler_loop_timeout(State=#state{loop_timeout=Timeout, loop_timeout_ref=PrevRef}) -> _ = case PrevRef of undefined -> ignore; PrevRef -> erlang:cancel_timer(PrevRef) end, TRef = make_ref(), erlang:send_after(Timeout, self(), {?MODULE, timeout, TRef}), State#state{loop_timeout_ref=TRef}. -spec handler_loop(any(), #http_req{}, #state{}) -> ok | none(). handler_loop(HandlerState, Req, State=#state{loop_timeout_ref=TRef}) -> receive {?MODULE, timeout, TRef} -> terminate_request(HandlerState, Req, State); {?MODULE, timeout, OlderTRef} when is_reference(OlderTRef) -> handler_loop(HandlerState, Req, State); Message -> handler_call(HandlerState, Req, State, Message) end. -spec handler_call(any(), #http_req{}, #state{}, any()) -> ok | none(). handler_call(HandlerState, Req, State=#state{handler={Handler, Opts}}, Message) -> try Handler:info(Message, Req, HandlerState) of {ok, Req2, HandlerState2} -> terminate_request(HandlerState2, Req2, State); {loop, Req2, HandlerState2} -> handler_before_loop(HandlerState2, Req2, State); {loop, Req2, HandlerState2, hibernate} -> handler_before_loop(HandlerState2, Req2, State#state{hibernate=true}) catch Class:Reason -> error_logger:error_msg( "** Handler ~p terminating in info/3~n" " for the reason ~p:~p~n" "** Options were ~p~n** Handler state was ~p~n" "** Request was ~p~n** Stacktrace: ~p~n~n", [Handler, Class, Reason, Opts, HandlerState, Req, erlang:get_stacktrace()]), handler_terminate(HandlerState, Req, State), error_terminate(500, State) end. -spec handler_terminate(any(), #http_req{}, #state{}) -> ok. handler_terminate(HandlerState, Req, #state{handler={Handler, Opts}}) -> try Handler:terminate(Req#http_req{resp_state=locked}, HandlerState) catch Class:Reason -> error_logger:error_msg( "** Handler ~p terminating in terminate/2~n" " for the reason ~p:~p~n" "** Options were ~p~n** Handler state was ~p~n" "** Request was ~p~n** Stacktrace: ~p~n~n", [Handler, Class, Reason, Opts, HandlerState, Req, erlang:get_stacktrace()]) end. -spec terminate_request(any(), #http_req{}, #state{}) -> ok | none(). terminate_request(HandlerState, Req, State) -> HandlerRes = handler_terminate(HandlerState, Req, State), next_request(Req, State, HandlerRes). -spec next_request(#http_req{}, #state{}, any()) -> ok | none(). next_request(Req=#http_req{connection=Conn}, State=#state{req_keepalive=Keepalive, max_keepalive=MaxKeepalive}, HandlerRes) -> RespRes = ensure_response(Req), {BodyRes, Buffer} = ensure_body_processed(Req), %% Flush the resp_sent message before moving on. receive {cowboy_http_req, resp_sent} -> ok after 0 -> ok end, case {HandlerRes, BodyRes, RespRes, Conn} of {ok, ok, ok, keepalive} when Keepalive < MaxKeepalive -> ?MODULE:parse_request(State#state{ buffer=Buffer, req_empty_lines=0, req_keepalive=Keepalive + 1}); _Closed -> terminate(State) end. -spec ensure_body_processed(#http_req{}) -> {ok | close, binary()}. ensure_body_processed(#http_req{body_state=done, buffer=Buffer}) -> {ok, Buffer}; ensure_body_processed(Req=#http_req{body_state=waiting}) -> case cowboy_http_req:body(Req) of {error, badarg} -> {ok, Req#http_req.buffer}; %% No body. {error, _Reason} -> {close, <<>>}; {ok, _, Req2} -> {ok, Req2#http_req.buffer} end; ensure_body_processed(Req=#http_req{body_state={multipart, _, _}}) -> {ok, Req2} = cowboy_http_req:multipart_skip(Req), ensure_body_processed(Req2). -spec ensure_response(#http_req{}) -> ok. %% The handler has already fully replied to the client. ensure_response(#http_req{resp_state=done}) -> ok; %% No response has been sent but everything apparently went fine. %% Reply with 204 No Content to indicate this. ensure_response(Req=#http_req{resp_state=waiting}) -> _ = cowboy_http_req:reply(204, [], [], Req), ok; %% Close the chunked reply. ensure_response(#http_req{method='HEAD', resp_state=chunks}) -> close; ensure_response(#http_req{socket=Socket, transport=Transport, resp_state=chunks}) -> Transport:send(Socket, <<"0\r\n\r\n">>), close. %% Only send an error reply if there is no resp_sent message. -spec error_terminate(cowboy_http:status(), #state{}) -> ok. error_terminate(Code, State=#state{socket=Socket, transport=Transport}) -> receive {cowboy_http_req, resp_sent} -> ok after 0 -> _ = cowboy_http_req:reply(Code, #http_req{ socket=Socket, transport=Transport, connection=close, pid=self(), resp_state=waiting}), ok end, terminate(State). -spec terminate(#state{}) -> ok. terminate(#state{socket=Socket, transport=Transport}) -> Transport:close(Socket), ok. %% Internal. -spec version_to_connection(cowboy_http:version()) -> keepalive | close. version_to_connection({1, 1}) -> keepalive; version_to_connection(_Any) -> close. -spec default_port(atom()) -> 80 | 443. default_port(ssl) -> 443; default_port(_) -> 80. %% @todo While 32 should be enough for everybody, we should probably make %% this configurable or something. -spec format_header(atom()) -> atom(); (binary()) -> binary(). format_header(Field) when is_atom(Field) -> Field; format_header(Field) when byte_size(Field) =< 20; byte_size(Field) > 32 -> Field; format_header(Field) -> format_header(Field, true, <<>>). format_header(<<>>, _Any, Acc) -> Acc; %% Replicate a bug in OTP for compatibility reasons when there's a - right %% after another. Proper use should always be 'true' instead of 'not Bool'. format_header(<< $-, Rest/bits >>, Bool, Acc) -> format_header(Rest, not Bool, << Acc/binary, $- >>); format_header(<< C, Rest/bits >>, true, Acc) -> format_header(Rest, false, << Acc/binary, (cowboy_bstr:char_to_upper(C)) >>); format_header(<< C, Rest/bits >>, false, Acc) -> format_header(Rest, false, << Acc/binary, (cowboy_bstr:char_to_lower(C)) >>). %% Tests. -ifdef(TEST). format_header_test_() -> %% {Header, Result} Tests = [ {<<"Sec-Websocket-Version">>, <<"Sec-Websocket-Version">>}, {<<"Sec-WebSocket-Version">>, <<"Sec-Websocket-Version">>}, {<<"sec-websocket-version">>, <<"Sec-Websocket-Version">>}, {<<"SEC-WEBSOCKET-VERSION">>, <<"Sec-Websocket-Version">>}, %% These last tests ensures we're formatting headers exactly like OTP. %% Even though it's dumb, it's better for compatibility reasons. {<<"Sec-WebSocket--Version">>, <<"Sec-Websocket--version">>}, {<<"Sec-WebSocket---Version">>, <<"Sec-Websocket---Version">>} ], [{H, fun() -> R = format_header(H) end} || {H, R} <- Tests]. -endif. rabbitmq-server-3.2.4/plugins-src/cowboy-wrapper/cowboy-git/src/cowboy.app.src0000644000000000000000000000200312305126066026211 0ustar rootroot%% Copyright (c) 2011, Loïc Hoguin %% %% Permission to use, copy, modify, and/or distribute this software for any %% purpose with or without fee is hereby granted, provided that the above %% copyright notice and this permission notice appear in all copies. %% %% THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES %% WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF %% MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR %% ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES %% WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN %% ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF %% OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. {application, cowboy, [ {description, "Small, fast, modular HTTP server."}, {vsn, "0.5.0"}, {modules, []}, {registered, [cowboy_clock, cowboy_sup]}, {applications, [ kernel, stdlib ]}, {mod, {cowboy_app, []}}, {env, []} ]}. rabbitmq-server-3.2.4/plugins-src/cowboy-wrapper/cowboy-git/src/cowboy_dispatcher.erl0000644000000000000000000002746412305126066027655 0ustar rootroot%% Copyright (c) 2011, Loïc Hoguin %% Copyright (c) 2011, Anthony Ramine %% %% Permission to use, copy, modify, and/or distribute this software for any %% purpose with or without fee is hereby granted, provided that the above %% copyright notice and this permission notice appear in all copies. %% %% THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES %% WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF %% MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR %% ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES %% WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN %% ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF %% OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. %% @doc Dispatch requests according to a hostname and path. -module(cowboy_dispatcher). -export([split_host/1, split_path/2, match/3]). %% API. -type bindings() :: list({atom(), binary()}). -type tokens() :: list(binary()). -type match_rule() :: '_' | '*' | list(binary() | '_' | '...' | atom()). -type dispatch_path() :: list({match_rule(), module(), any()}). -type dispatch_rule() :: {Host::match_rule(), Path::dispatch_path()}. -type dispatch_rules() :: list(dispatch_rule()). -export_type([bindings/0, tokens/0, dispatch_rules/0]). -include_lib("eunit/include/eunit.hrl"). %% API. %% @doc Split a hostname into a list of tokens. -spec split_host(binary()) -> {tokens(), binary(), undefined | inet:ip_port()}. split_host(<<>>) -> {[], <<>>, undefined}; split_host(Host) -> case binary:split(Host, <<":">>) of [Host] -> {binary:split(Host, <<".">>, [global, trim]), Host, undefined}; [Host2, Port] -> {binary:split(Host2, <<".">>, [global, trim]), Host2, list_to_integer(binary_to_list(Port))} end. %% @doc Split a path into a list of path segments. %% %% Following RFC2396, this function may return path segments containing any %% character, including / if, and only if, a / was escaped %% and part of a path segment. -spec split_path(binary(), fun((binary()) -> binary())) -> {tokens(), binary(), binary()}. split_path(Path, URLDec) -> case binary:split(Path, <<"?">>) of [Path] -> {do_split_path(Path, <<"/">>, URLDec), Path, <<>>}; [<<>>, Qs] -> {[], <<>>, Qs}; [Path2, Qs] -> {do_split_path(Path2, <<"/">>, URLDec), Path2, Qs} end. -spec do_split_path(binary(), <<_:8>>, fun((binary()) -> binary())) -> tokens(). do_split_path(RawPath, Separator, URLDec) -> EncodedPath = case binary:split(RawPath, Separator, [global, trim]) of [<<>>|Path] -> Path; Path -> Path end, [URLDec(Token) || Token <- EncodedPath]. %% @doc Match hostname tokens and path tokens against dispatch rules. %% %% It is typically used for matching tokens for the hostname and path of %% the request against a global dispatch rule for your listener. %% %% Dispatch rules are a list of {Hostname, PathRules} tuples, with %% PathRules being a list of {Path, HandlerMod, HandlerOpts}. %% %% Hostname and Path are match rules and can be either the %% atom '_', which matches everything for a single token, the atom %% '*', which matches everything for the rest of the tokens, or a %% list of tokens. Each token can be either a binary, the atom '_', %% the atom '...' or a named atom. A binary token must match exactly, %% '_' matches everything for a single token, '...' matches %% everything for the rest of the tokens and a named atom will bind the %% corresponding token value and return it. %% %% The list of hostname tokens is reversed before matching. For example, if %% we were to match "www.dev-extend.eu", we would first match "eu", then %% "dev-extend", then "www". This means that in the context of hostnames, %% the '...' atom matches properly the lower levels of the domain %% as would be expected. %% %% When a result is found, this function will return the handler module and %% options found in the dispatch list, a key-value list of bindings and %% the tokens that were matched by the '...' atom for both the %% hostname and path. -spec match(Host::tokens(), Path::tokens(), dispatch_rules()) -> {ok, module(), any(), bindings(), HostInfo::undefined | tokens(), PathInfo::undefined | tokens()} | {error, notfound, host} | {error, notfound, path}. match(_Host, _Path, []) -> {error, notfound, host}; match(_Host, Path, [{'_', PathMatchs}|_Tail]) -> match_path(Path, PathMatchs, [], undefined); match(Host, Path, [{HostMatch, PathMatchs}|Tail]) -> case try_match(host, Host, HostMatch) of false -> match(Host, Path, Tail); {true, HostBinds, undefined} -> match_path(Path, PathMatchs, HostBinds, undefined); {true, HostBinds, HostInfo} -> match_path(Path, PathMatchs, HostBinds, lists:reverse(HostInfo)) end. -spec match_path(tokens(), dispatch_path(), bindings(), HostInfo::undefined | tokens()) -> {ok, module(), any(), bindings(), HostInfo::undefined | tokens(), PathInfo::undefined | tokens()} | {error, notfound, path}. match_path(_Path, [], _HostBinds, _HostInfo) -> {error, notfound, path}; match_path(_Path, [{'_', Handler, Opts}|_Tail], HostBinds, HostInfo) -> {ok, Handler, Opts, HostBinds, HostInfo, undefined}; match_path('*', [{'*', Handler, Opts}|_Tail], HostBinds, HostInfo) -> {ok, Handler, Opts, HostBinds, HostInfo, undefined}; match_path(Path, [{PathMatch, Handler, Opts}|Tail], HostBinds, HostInfo) -> case try_match(path, Path, PathMatch) of false -> match_path(Path, Tail, HostBinds, HostInfo); {true, PathBinds, PathInfo} -> {ok, Handler, Opts, HostBinds ++ PathBinds, HostInfo, PathInfo} end. %% Internal. -spec try_match(host | path, tokens(), match_rule()) -> {true, bindings(), undefined | tokens()} | false. try_match(host, List, Match) -> list_match(lists:reverse(List), lists:reverse(Match), []); try_match(path, List, Match) -> list_match(List, Match, []). -spec list_match(tokens(), match_rule(), bindings()) -> {true, bindings(), undefined | tokens()} | false. %% Atom '...' matches any trailing path, stop right now. list_match(List, ['...'], Binds) -> {true, Binds, List}; %% Atom '_' matches anything, continue. list_match([_E|Tail], ['_'|TailMatch], Binds) -> list_match(Tail, TailMatch, Binds); %% Both values match, continue. list_match([E|Tail], [E|TailMatch], Binds) -> list_match(Tail, TailMatch, Binds); %% Bind E to the variable name V and continue. list_match([E|Tail], [V|TailMatch], Binds) when is_atom(V) -> list_match(Tail, TailMatch, [{V, E}|Binds]); %% Match complete. list_match([], [], Binds) -> {true, Binds, undefined}; %% Values don't match, stop. list_match(_List, _Match, _Binds) -> false. %% Tests. -ifdef(TEST). split_host_test_() -> %% {Host, Result} Tests = [ {<<"">>, {[], <<"">>, undefined}}, {<<".........">>, {[], <<".........">>, undefined}}, {<<"*">>, {[<<"*">>], <<"*">>, undefined}}, {<<"cowboy.dev-extend.eu">>, {[<<"cowboy">>, <<"dev-extend">>, <<"eu">>], <<"cowboy.dev-extend.eu">>, undefined}}, {<<"dev-extend..eu">>, {[<<"dev-extend">>, <<>>, <<"eu">>], <<"dev-extend..eu">>, undefined}}, {<<"dev-extend.eu">>, {[<<"dev-extend">>, <<"eu">>], <<"dev-extend.eu">>, undefined}}, {<<"dev-extend.eu:8080">>, {[<<"dev-extend">>, <<"eu">>], <<"dev-extend.eu">>, 8080}}, {<<"a.b.c.d.e.f.g.h.i.j.k.l.m.n.o.p.q.r.s.t.u.v.w.x.y.z">>, {[<<"a">>, <<"b">>, <<"c">>, <<"d">>, <<"e">>, <<"f">>, <<"g">>, <<"h">>, <<"i">>, <<"j">>, <<"k">>, <<"l">>, <<"m">>, <<"n">>, <<"o">>, <<"p">>, <<"q">>, <<"r">>, <<"s">>, <<"t">>, <<"u">>, <<"v">>, <<"w">>, <<"x">>, <<"y">>, <<"z">>], <<"a.b.c.d.e.f.g.h.i.j.k.l.m.n.o.p.q.r.s.t.u.v.w.x.y.z">>, undefined}} ], [{H, fun() -> R = split_host(H) end} || {H, R} <- Tests]. split_host_fail_test_() -> Tests = [ <<"dev-extend.eu:owns">>, <<"dev-extend.eu: owns">>, <<"dev-extend.eu:42fun">>, <<"dev-extend.eu: 42fun">>, <<"dev-extend.eu:42 fun">>, <<"dev-extend.eu:fun 42">>, <<"dev-extend.eu: 42">>, <<":owns">>, <<":42 fun">> ], [{H, fun() -> case catch split_host(H) of {'EXIT', _Reason} -> ok end end} || H <- Tests]. split_path_test_() -> %% {Path, Result, QueryString} Tests = [ {<<"?">>, [], <<"">>, <<"">>}, {<<"???">>, [], <<"">>, <<"??">>}, {<<"/">>, [], <<"/">>, <<"">>}, {<<"/users">>, [<<"users">>], <<"/users">>, <<"">>}, {<<"/users?">>, [<<"users">>], <<"/users">>, <<"">>}, {<<"/users?a">>, [<<"users">>], <<"/users">>, <<"a">>}, {<<"/users/42/friends?a=b&c=d&e=notsure?whatever">>, [<<"users">>, <<"42">>, <<"friends">>], <<"/users/42/friends">>, <<"a=b&c=d&e=notsure?whatever">>}, {<<"/users/a+b/c%21d?e+f=g+h">>, [<<"users">>, <<"a b">>, <<"c!d">>], <<"/users/a+b/c%21d">>, <<"e+f=g+h">>} ], URLDecode = fun(Bin) -> cowboy_http:urldecode(Bin, crash) end, [{P, fun() -> {R, RawP, Qs} = split_path(P, URLDecode) end} || {P, R, RawP, Qs} <- Tests]. match_test_() -> Dispatch = [ {[<<"www">>, '_', <<"dev-extend">>, <<"eu">>], [ {[<<"users">>, '_', <<"mails">>], match_any_subdomain_users, []} ]}, {[<<"dev-extend">>, <<"eu">>], [ {[<<"users">>, id, <<"friends">>], match_extend_users_friends, []}, {'_', match_extend, []} ]}, {[<<"dev-extend">>, var], [ {[<<"threads">>, var], match_duplicate_vars, [we, {expect, two}, var, here]} ]}, {[<<"erlang">>, ext], [ {'_', match_erlang_ext, []} ]}, {'_', [ {[<<"users">>, id, <<"friends">>], match_users_friends, []}, {'_', match_any, []} ]} ], %% {Host, Path, Result} Tests = [ {[<<"any">>], [], {ok, match_any, [], []}}, {[<<"www">>, <<"any">>, <<"dev-extend">>, <<"eu">>], [<<"users">>, <<"42">>, <<"mails">>], {ok, match_any_subdomain_users, [], []}}, {[<<"www">>, <<"dev-extend">>, <<"eu">>], [<<"users">>, <<"42">>, <<"mails">>], {ok, match_any, [], []}}, {[<<"www">>, <<"dev-extend">>, <<"eu">>], [], {ok, match_any, [], []}}, {[<<"www">>, <<"any">>, <<"dev-extend">>, <<"eu">>], [<<"not_users">>, <<"42">>, <<"mails">>], {error, notfound, path}}, {[<<"dev-extend">>, <<"eu">>], [], {ok, match_extend, [], []}}, {[<<"dev-extend">>, <<"eu">>], [<<"users">>, <<"42">>, <<"friends">>], {ok, match_extend_users_friends, [], [{id, <<"42">>}]}}, {[<<"erlang">>, <<"fr">>], '_', {ok, match_erlang_ext, [], [{ext, <<"fr">>}]}}, {[<<"any">>], [<<"users">>, <<"444">>, <<"friends">>], {ok, match_users_friends, [], [{id, <<"444">>}]}}, {[<<"dev-extend">>, <<"fr">>], [<<"threads">>, <<"987">>], {ok, match_duplicate_vars, [we, {expect, two}, var, here], [{var, <<"fr">>}, {var, <<"987">>}]}} ], [{lists:flatten(io_lib:format("~p, ~p", [H, P])), fun() -> {ok, Handler, Opts, Binds, undefined, undefined} = match(H, P, Dispatch) end} || {H, P, {ok, Handler, Opts, Binds}} <- Tests]. match_info_test_() -> Dispatch = [ {[<<"www">>, <<"dev-extend">>, <<"eu">>], [ {[<<"pathinfo">>, <<"is">>, <<"next">>, '...'], match_path, []} ]}, {['...', <<"dev-extend">>, <<"eu">>], [ {'_', match_any, []} ]} ], Tests = [ {[<<"dev-extend">>, <<"eu">>], [], {ok, match_any, [], [], [], undefined}}, {[<<"bugs">>, <<"dev-extend">>, <<"eu">>], [], {ok, match_any, [], [], [<<"bugs">>], undefined}}, {[<<"cowboy">>, <<"bugs">>, <<"dev-extend">>, <<"eu">>], [], {ok, match_any, [], [], [<<"cowboy">>, <<"bugs">>], undefined}}, {[<<"www">>, <<"dev-extend">>, <<"eu">>], [<<"pathinfo">>, <<"is">>, <<"next">>], {ok, match_path, [], [], undefined, []}}, {[<<"www">>, <<"dev-extend">>, <<"eu">>], [<<"pathinfo">>, <<"is">>, <<"next">>, <<"path_info">>], {ok, match_path, [], [], undefined, [<<"path_info">>]}}, {[<<"www">>, <<"dev-extend">>, <<"eu">>], [<<"pathinfo">>, <<"is">>, <<"next">>, <<"foo">>, <<"bar">>], {ok, match_path, [], [], undefined, [<<"foo">>, <<"bar">>]}} ], [{lists:flatten(io_lib:format("~p, ~p", [H, P])), fun() -> R = match(H, P, Dispatch) end} || {H, P, R} <- Tests]. -endif. rabbitmq-server-3.2.4/plugins-src/cowboy-wrapper/cowboy-git/src/cowboy_http_websocket.erl0000644000000000000000000005335512305126066030552 0ustar rootroot%% Copyright (c) 2011, Loïc Hoguin %% %% Permission to use, copy, modify, and/or distribute this software for any %% purpose with or without fee is hereby granted, provided that the above %% copyright notice and this permission notice appear in all copies. %% %% THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES %% WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF %% MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR %% ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES %% WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN %% ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF %% OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. %% @doc WebSocket protocol implementation. %% %% Supports the protocol version 0 (hixie-76), version 7 (hybi-7) %% and version 8 (hybi-8, hybi-9 and hybi-10). %% %% Version 0 is supported by the following browsers: %%
      %%
    • Firefox 4-5 (disabled by default)
    • %%
    • Chrome 6-13
    • %%
    • Safari 5.0.1+
    • %%
    • Opera 11.00+ (disabled by default)
    • %%
    %% %% Version 7 is supported by the following browser: %%
      %%
    • Firefox 6
    • %%
    %% %% Version 8+ is supported by the following browsers: %%
      %%
    • Firefox 7+
    • %%
    • Chrome 14+
    • %%
    -module(cowboy_http_websocket). -export([upgrade/4]). %% API. -export([handler_loop/4]). %% Internal. -include("include/http.hrl"). -include_lib("eunit/include/eunit.hrl"). -type opcode() :: 0 | 1 | 2 | 8 | 9 | 10. -type mask_key() :: 0..16#ffffffff. -record(state, { version :: 0 | 7 | 8 | 13, handler :: module(), opts :: any(), challenge = undefined :: undefined | binary() | {binary(), binary()}, timeout = infinity :: timeout(), timeout_ref = undefined, messages = undefined :: undefined | {atom(), atom(), atom()}, hibernate = false, eop :: undefined | tuple(), %% hixie-76 specific. origin = undefined :: undefined | binary() %% hixie-76 specific. }). %% @doc Upgrade a HTTP request to the WebSocket protocol. %% %% You do not need to call this function manually. To upgrade to the WebSocket %% protocol, you simply need to return {upgrade, protocol, {@module}} %% in your cowboy_http_handler:init/3 handler function. -spec upgrade(pid(), module(), any(), #http_req{}) -> closed | none(). upgrade(ListenerPid, Handler, Opts, Req) -> cowboy_listener:move_connection(ListenerPid, websocket, self()), case catch websocket_upgrade(#state{handler=Handler, opts=Opts}, Req) of {ok, State, Req2} -> handler_init(State, Req2); {'EXIT', _Reason} -> upgrade_error(Req) end. -spec websocket_upgrade(#state{}, #http_req{}) -> {ok, #state{}, #http_req{}}. websocket_upgrade(State, Req) -> {ConnTokens, Req2} = cowboy_http_req:parse_header('Connection', Req), true = lists:member(<<"upgrade">>, ConnTokens), %% @todo Should probably send a 426 if the Upgrade header is missing. {[<<"websocket">>], Req3} = cowboy_http_req:parse_header('Upgrade', Req2), {Version, Req4} = cowboy_http_req:header(<<"Sec-Websocket-Version">>, Req3), websocket_upgrade(Version, State, Req4). %% @todo Handle the Sec-Websocket-Protocol header. %% @todo Reply a proper error, don't die, if a required header is undefined. -spec websocket_upgrade(undefined | <<_:8>>, #state{}, #http_req{}) -> {ok, #state{}, #http_req{}}. %% No version given. Assuming hixie-76 draft. %% %% We need to wait to send a reply back before trying to read the %% third part of the challenge key, because proxies will wait for %% a reply before sending it. Therefore we calculate the challenge %% key only in websocket_handshake/3. websocket_upgrade(undefined, State, Req=#http_req{meta=Meta}) -> {Origin, Req2} = cowboy_http_req:header(<<"Origin">>, Req), {Key1, Req3} = cowboy_http_req:header(<<"Sec-Websocket-Key1">>, Req2), {Key2, Req4} = cowboy_http_req:header(<<"Sec-Websocket-Key2">>, Req3), false = lists:member(undefined, [Origin, Key1, Key2]), EOP = binary:compile_pattern(<< 255 >>), {ok, State#state{version=0, origin=Origin, challenge={Key1, Key2}, eop=EOP}, Req4#http_req{meta=[{websocket_version, 0}|Meta]}}; %% Versions 7 and 8. Implementation follows the hybi 7 through 17 drafts. websocket_upgrade(Version, State, Req=#http_req{meta=Meta}) when Version =:= <<"7">>; Version =:= <<"8">>; Version =:= <<"13">> -> {Key, Req2} = cowboy_http_req:header(<<"Sec-Websocket-Key">>, Req), false = Key =:= undefined, Challenge = hybi_challenge(Key), IntVersion = list_to_integer(binary_to_list(Version)), {ok, State#state{version=IntVersion, challenge=Challenge}, Req2#http_req{meta=[{websocket_version, IntVersion}|Meta]}}. -spec handler_init(#state{}, #http_req{}) -> closed | none(). handler_init(State=#state{handler=Handler, opts=Opts}, Req=#http_req{transport=Transport}) -> try Handler:websocket_init(Transport:name(), Req, Opts) of {ok, Req2, HandlerState} -> websocket_handshake(State, Req2, HandlerState); {ok, Req2, HandlerState, hibernate} -> websocket_handshake(State#state{hibernate=true}, Req2, HandlerState); {ok, Req2, HandlerState, Timeout} -> websocket_handshake(State#state{timeout=Timeout}, Req2, HandlerState); {ok, Req2, HandlerState, Timeout, hibernate} -> websocket_handshake(State#state{timeout=Timeout, hibernate=true}, Req2, HandlerState); {shutdown, Req2} -> upgrade_denied(Req2) catch Class:Reason -> upgrade_error(Req), error_logger:error_msg( "** Handler ~p terminating in websocket_init/3~n" " for the reason ~p:~p~n** Options were ~p~n" "** Request was ~p~n** Stacktrace: ~p~n~n", [Handler, Class, Reason, Opts, Req, erlang:get_stacktrace()]) end. -spec upgrade_error(#http_req{}) -> closed. upgrade_error(Req) -> {ok, _Req2} = cowboy_http_req:reply(400, [], [], Req#http_req{resp_state=waiting}), closed. %% @see cowboy_http_protocol:ensure_response/1 -spec upgrade_denied(#http_req{}) -> closed. upgrade_denied(#http_req{resp_state=done}) -> closed; upgrade_denied(Req=#http_req{resp_state=waiting}) -> {ok, _Req2} = cowboy_http_req:reply(400, [], [], Req), closed; upgrade_denied(#http_req{method='HEAD', resp_state=chunks}) -> closed; upgrade_denied(#http_req{socket=Socket, transport=Transport, resp_state=chunks}) -> Transport:send(Socket, <<"0\r\n\r\n">>), closed. -spec websocket_handshake(#state{}, #http_req{}, any()) -> closed | none(). websocket_handshake(State=#state{version=0, origin=Origin, challenge={Key1, Key2}}, Req=#http_req{socket=Socket, transport=Transport, raw_host=Host, port=Port, raw_path=Path, raw_qs=QS}, HandlerState) -> Location = hixie76_location(Transport:name(), Host, Port, Path, QS), {ok, Req2} = cowboy_http_req:upgrade_reply( <<"101 WebSocket Protocol Handshake">>, [{<<"Upgrade">>, <<"WebSocket">>}, {<<"Sec-Websocket-Location">>, Location}, {<<"Sec-Websocket-Origin">>, Origin}], Req#http_req{resp_state=waiting}), %% Flush the resp_sent message before moving on. receive {cowboy_http_req, resp_sent} -> ok after 0 -> ok end, %% We replied with a proper response. Proxies should be happy enough, %% we can now read the 8 last bytes of the challenge keys and send %% the challenge response directly to the socket. case cowboy_http_req:body(8, Req2) of {ok, Key3, Req3} -> Challenge = hixie76_challenge(Key1, Key2, Key3), Transport:send(Socket, Challenge), handler_before_loop(State#state{messages=Transport:messages()}, Req3, HandlerState, <<>>); _Any -> closed %% If an error happened reading the body, stop there. end; websocket_handshake(State=#state{challenge=Challenge}, Req=#http_req{transport=Transport}, HandlerState) -> {ok, Req2} = cowboy_http_req:upgrade_reply( 101, [{<<"Upgrade">>, <<"websocket">>}, {<<"Sec-Websocket-Accept">>, Challenge}], Req#http_req{resp_state=waiting}), %% Flush the resp_sent message before moving on. receive {cowboy_http_req, resp_sent} -> ok after 0 -> ok end, handler_before_loop(State#state{messages=Transport:messages()}, Req2, HandlerState, <<>>). -spec handler_before_loop(#state{}, #http_req{}, any(), binary()) -> closed | none(). handler_before_loop(State=#state{hibernate=true}, Req=#http_req{socket=Socket, transport=Transport}, HandlerState, SoFar) -> Transport:setopts(Socket, [{active, once}]), State2 = handler_loop_timeout(State), erlang:hibernate(?MODULE, handler_loop, [State2#state{hibernate=false}, Req, HandlerState, SoFar]); handler_before_loop(State, Req=#http_req{socket=Socket, transport=Transport}, HandlerState, SoFar) -> Transport:setopts(Socket, [{active, once}]), State2 = handler_loop_timeout(State), handler_loop(State2, Req, HandlerState, SoFar). -spec handler_loop_timeout(#state{}) -> #state{}. handler_loop_timeout(State=#state{timeout=infinity}) -> State#state{timeout_ref=undefined}; handler_loop_timeout(State=#state{timeout=Timeout, timeout_ref=PrevRef}) -> _ = case PrevRef of undefined -> ignore; PrevRef -> erlang:cancel_timer(PrevRef) end, TRef = make_ref(), erlang:send_after(Timeout, self(), {?MODULE, timeout, TRef}), State#state{timeout_ref=TRef}. %% @private -spec handler_loop(#state{}, #http_req{}, any(), binary()) -> closed | none(). handler_loop(State=#state{messages={OK, Closed, Error}, timeout_ref=TRef}, Req=#http_req{socket=Socket}, HandlerState, SoFar) -> receive {OK, Socket, Data} -> websocket_data(State, Req, HandlerState, << SoFar/binary, Data/binary >>); {Closed, Socket} -> handler_terminate(State, Req, HandlerState, {error, closed}); {Error, Socket, Reason} -> handler_terminate(State, Req, HandlerState, {error, Reason}); {?MODULE, timeout, TRef} -> websocket_close(State, Req, HandlerState, {normal, timeout}); {?MODULE, timeout, OlderTRef} when is_reference(OlderTRef) -> handler_loop(State, Req, HandlerState, SoFar); Message -> handler_call(State, Req, HandlerState, SoFar, websocket_info, Message, fun handler_before_loop/4) end. -spec websocket_data(#state{}, #http_req{}, any(), binary()) -> closed | none(). %% No more data. websocket_data(State, Req, HandlerState, <<>>) -> handler_before_loop(State, Req, HandlerState, <<>>); %% hixie-76 close frame. websocket_data(State=#state{version=0}, Req, HandlerState, << 255, 0, _Rest/binary >>) -> websocket_close(State, Req, HandlerState, {normal, closed}); %% hixie-76 data frame. We only support the frame type 0, same as the specs. websocket_data(State=#state{version=0, eop=EOP}, Req, HandlerState, Data = << 0, _/binary >>) -> case binary:match(Data, EOP) of {Pos, 1} -> Pos2 = Pos - 1, << 0, Payload:Pos2/binary, 255, Rest/bits >> = Data, handler_call(State, Req, HandlerState, Rest, websocket_handle, {text, Payload}, fun websocket_data/4); nomatch -> %% @todo We probably should allow limiting frame length. handler_before_loop(State, Req, HandlerState, Data) end; %% incomplete hybi data frame. websocket_data(State=#state{version=Version}, Req, HandlerState, Data) when Version =/= 0, byte_size(Data) =:= 1 -> handler_before_loop(State, Req, HandlerState, Data); %% hybi data frame. %% @todo Handle Fin. websocket_data(State=#state{version=Version}, Req, HandlerState, Data) when Version =/= 0 -> << 1:1, 0:3, Opcode:4, Mask:1, PayloadLen:7, Rest/bits >> = Data, case {PayloadLen, Rest} of {126, _} when Opcode >= 8 -> websocket_close( State, Req, HandlerState, {error, protocol}); {127, _} when Opcode >= 8 -> websocket_close( State, Req, HandlerState, {error, protocol}); {126, << L:16, R/bits >>} -> websocket_before_unmask( State, Req, HandlerState, Data, R, Opcode, Mask, L); {126, Rest} -> websocket_before_unmask( State, Req, HandlerState, Data, Rest, Opcode, Mask, undefined); {127, << 0:1, L:63, R/bits >>} -> websocket_before_unmask( State, Req, HandlerState, Data, R, Opcode, Mask, L); {127, Rest} -> websocket_before_unmask( State, Req, HandlerState, Data, Rest, Opcode, Mask, undefined); {PayloadLen, Rest} -> websocket_before_unmask( State, Req, HandlerState, Data, Rest, Opcode, Mask, PayloadLen) end; %% Something was wrong with the frame. Close the connection. websocket_data(State, Req, HandlerState, _Bad) -> websocket_close(State, Req, HandlerState, {error, badframe}). %% hybi routing depending on whether unmasking is needed. -spec websocket_before_unmask(#state{}, #http_req{}, any(), binary(), binary(), opcode(), 0 | 1, non_neg_integer() | undefined) -> closed | none(). websocket_before_unmask(State, Req, HandlerState, Data, Rest, Opcode, Mask, PayloadLen) -> case {Mask, PayloadLen} of {0, 0} -> websocket_dispatch(State, Req, HandlerState, Rest, Opcode, <<>>); {1, N} when N + 4 > byte_size(Rest); N =:= undefined -> %% @todo We probably should allow limiting frame length. handler_before_loop(State, Req, HandlerState, Data); {1, _N} -> << MaskKey:32, Payload:PayloadLen/binary, Rest2/bits >> = Rest, websocket_unmask(State, Req, HandlerState, Rest2, Opcode, Payload, MaskKey) end. %% hybi unmasking. -spec websocket_unmask(#state{}, #http_req{}, any(), binary(), opcode(), binary(), mask_key()) -> closed | none(). websocket_unmask(State, Req, HandlerState, RemainingData, Opcode, Payload, MaskKey) -> websocket_unmask(State, Req, HandlerState, RemainingData, Opcode, Payload, MaskKey, <<>>). -spec websocket_unmask(#state{}, #http_req{}, any(), binary(), opcode(), binary(), mask_key(), binary()) -> closed | none(). websocket_unmask(State, Req, HandlerState, RemainingData, Opcode, << O:32, Rest/bits >>, MaskKey, Acc) -> T = O bxor MaskKey, websocket_unmask(State, Req, HandlerState, RemainingData, Opcode, Rest, MaskKey, << Acc/binary, T:32 >>); websocket_unmask(State, Req, HandlerState, RemainingData, Opcode, << O:24 >>, MaskKey, Acc) -> << MaskKey2:24, _:8 >> = << MaskKey:32 >>, T = O bxor MaskKey2, websocket_dispatch(State, Req, HandlerState, RemainingData, Opcode, << Acc/binary, T:24 >>); websocket_unmask(State, Req, HandlerState, RemainingData, Opcode, << O:16 >>, MaskKey, Acc) -> << MaskKey2:16, _:16 >> = << MaskKey:32 >>, T = O bxor MaskKey2, websocket_dispatch(State, Req, HandlerState, RemainingData, Opcode, << Acc/binary, T:16 >>); websocket_unmask(State, Req, HandlerState, RemainingData, Opcode, << O:8 >>, MaskKey, Acc) -> << MaskKey2:8, _:24 >> = << MaskKey:32 >>, T = O bxor MaskKey2, websocket_dispatch(State, Req, HandlerState, RemainingData, Opcode, << Acc/binary, T:8 >>); websocket_unmask(State, Req, HandlerState, RemainingData, Opcode, <<>>, _MaskKey, Acc) -> websocket_dispatch(State, Req, HandlerState, RemainingData, Opcode, Acc). %% hybi dispatching. -spec websocket_dispatch(#state{}, #http_req{}, any(), binary(), opcode(), binary()) -> closed | none(). %% @todo Fragmentation. %~ websocket_dispatch(State, Req, HandlerState, RemainingData, 0, Payload) -> %% Text frame. websocket_dispatch(State, Req, HandlerState, RemainingData, 1, Payload) -> handler_call(State, Req, HandlerState, RemainingData, websocket_handle, {text, Payload}, fun websocket_data/4); %% Binary frame. websocket_dispatch(State, Req, HandlerState, RemainingData, 2, Payload) -> handler_call(State, Req, HandlerState, RemainingData, websocket_handle, {binary, Payload}, fun websocket_data/4); %% Close control frame. %% @todo Handle the optional Payload. websocket_dispatch(State, Req, HandlerState, _RemainingData, 8, _Payload) -> websocket_close(State, Req, HandlerState, {normal, closed}); %% Ping control frame. Send a pong back and forward the ping to the handler. websocket_dispatch(State, Req=#http_req{socket=Socket, transport=Transport}, HandlerState, RemainingData, 9, Payload) -> Len = hybi_payload_length(byte_size(Payload)), Transport:send(Socket, << 1:1, 0:3, 10:4, 0:1, Len/bits, Payload/binary >>), handler_call(State, Req, HandlerState, RemainingData, websocket_handle, {ping, Payload}, fun websocket_data/4); %% Pong control frame. websocket_dispatch(State, Req, HandlerState, RemainingData, 10, Payload) -> handler_call(State, Req, HandlerState, RemainingData, websocket_handle, {pong, Payload}, fun websocket_data/4). -spec handler_call(#state{}, #http_req{}, any(), binary(), atom(), any(), fun()) -> closed | none(). handler_call(State=#state{handler=Handler, opts=Opts}, Req, HandlerState, RemainingData, Callback, Message, NextState) -> try Handler:Callback(Message, Req, HandlerState) of {ok, Req2, HandlerState2} -> NextState(State, Req2, HandlerState2, RemainingData); {ok, Req2, HandlerState2, hibernate} -> NextState(State#state{hibernate=true}, Req2, HandlerState2, RemainingData); {reply, Payload, Req2, HandlerState2} -> websocket_send(Payload, State, Req2), NextState(State, Req2, HandlerState2, RemainingData); {reply, Payload, Req2, HandlerState2, hibernate} -> websocket_send(Payload, State, Req2), NextState(State#state{hibernate=true}, Req2, HandlerState2, RemainingData); {shutdown, Req2, HandlerState2} -> websocket_close(State, Req2, HandlerState2, {normal, shutdown}) catch Class:Reason -> error_logger:error_msg( "** Handler ~p terminating in ~p/3~n" " for the reason ~p:~p~n** Message was ~p~n" "** Options were ~p~n** Handler state was ~p~n" "** Request was ~p~n** Stacktrace: ~p~n~n", [Handler, Callback, Class, Reason, Message, Opts, HandlerState, Req, erlang:get_stacktrace()]), websocket_close(State, Req, HandlerState, {error, handler}) end. -spec websocket_send(binary(), #state{}, #http_req{}) -> closed | ignore. %% hixie-76 text frame. websocket_send({text, Payload}, #state{version=0}, #http_req{socket=Socket, transport=Transport}) -> Transport:send(Socket, [0, Payload, 255]); %% Ignore all unknown frame types for compatibility with hixie 76. websocket_send(_Any, #state{version=0}, _Req) -> ignore; websocket_send({Type, Payload}, _State, #http_req{socket=Socket, transport=Transport}) -> Opcode = case Type of text -> 1; binary -> 2; ping -> 9; pong -> 10 end, Len = hybi_payload_length(iolist_size(Payload)), Transport:send(Socket, [<< 1:1, 0:3, Opcode:4, 0:1, Len/bits >>, Payload]). -spec websocket_close(#state{}, #http_req{}, any(), {atom(), atom()}) -> closed. websocket_close(State=#state{version=0}, Req=#http_req{socket=Socket, transport=Transport}, HandlerState, Reason) -> Transport:send(Socket, << 255, 0 >>), handler_terminate(State, Req, HandlerState, Reason); %% @todo Send a Payload? Using Reason is usually good but we're quite careless. websocket_close(State, Req=#http_req{socket=Socket, transport=Transport}, HandlerState, Reason) -> Transport:send(Socket, << 1:1, 0:3, 8:4, 0:8 >>), handler_terminate(State, Req, HandlerState, Reason). -spec handler_terminate(#state{}, #http_req{}, any(), atom() | {atom(), atom()}) -> closed. handler_terminate(#state{handler=Handler, opts=Opts}, Req, HandlerState, TerminateReason) -> try Handler:websocket_terminate(TerminateReason, Req, HandlerState) catch Class:Reason -> error_logger:error_msg( "** Handler ~p terminating in websocket_terminate/3~n" " for the reason ~p:~p~n** Initial reason was ~p~n" "** Options were ~p~n** Handler state was ~p~n" "** Request was ~p~n** Stacktrace: ~p~n~n", [Handler, Class, Reason, TerminateReason, Opts, HandlerState, Req, erlang:get_stacktrace()]) end, closed. %% hixie-76 specific. -spec hixie76_challenge(binary(), binary(), binary()) -> binary(). hixie76_challenge(Key1, Key2, Key3) -> IntKey1 = hixie76_key_to_integer(Key1), IntKey2 = hixie76_key_to_integer(Key2), erlang:md5(<< IntKey1:32, IntKey2:32, Key3/binary >>). -spec hixie76_key_to_integer(binary()) -> integer(). hixie76_key_to_integer(Key) -> Number = list_to_integer([C || << C >> <= Key, C >= $0, C =< $9]), Spaces = length([C || << C >> <= Key, C =:= 32]), Number div Spaces. -spec hixie76_location(atom(), binary(), inet:ip_port(), binary(), binary()) -> binary(). hixie76_location(Protocol, Host, Port, Path, <<>>) -> << (hixie76_location_protocol(Protocol))/binary, "://", Host/binary, (hixie76_location_port(Protocol, Port))/binary, Path/binary>>; hixie76_location(Protocol, Host, Port, Path, QS) -> << (hixie76_location_protocol(Protocol))/binary, "://", Host/binary, (hixie76_location_port(Protocol, Port))/binary, Path/binary, "?", QS/binary >>. -spec hixie76_location_protocol(atom()) -> binary(). hixie76_location_protocol(ssl) -> <<"wss">>; hixie76_location_protocol(_) -> <<"ws">>. %% @todo We should add a secure/0 function to transports %% instead of relying on their name. -spec hixie76_location_port(atom(), inet:ip_port()) -> binary(). hixie76_location_port(ssl, 443) -> <<>>; hixie76_location_port(tcp, 80) -> <<>>; hixie76_location_port(_, Port) -> <<":", (list_to_binary(integer_to_list(Port)))/binary>>. %% hybi specific. -spec hybi_challenge(binary()) -> binary(). hybi_challenge(Key) -> Bin = << Key/binary, "258EAFA5-E914-47DA-95CA-C5AB0DC85B11" >>, base64:encode(crypto:sha(Bin)). -spec hybi_payload_length(0..16#7fffffffffffffff) -> << _:7 >> | << _:23 >> | << _:71 >>. hybi_payload_length(N) -> case N of N when N =< 125 -> << N:7 >>; N when N =< 16#ffff -> << 126:7, N:16 >>; N when N =< 16#7fffffffffffffff -> << 127:7, N:64 >> end. %% Tests. -ifdef(TEST). hixie76_location_test() -> ?assertEqual(<<"ws://localhost/path">>, hixie76_location(tcp, <<"localhost">>, 80, <<"/path">>, <<>>)), ?assertEqual(<<"ws://localhost:443/path">>, hixie76_location(tcp, <<"localhost">>, 443, <<"/path">>, <<>>)), ?assertEqual(<<"ws://localhost:8080/path">>, hixie76_location(tcp, <<"localhost">>, 8080, <<"/path">>, <<>>)), ?assertEqual(<<"ws://localhost:8080/path?dummy=2785">>, hixie76_location(tcp, <<"localhost">>, 8080, <<"/path">>, <<"dummy=2785">>)), ?assertEqual(<<"wss://localhost/path">>, hixie76_location(ssl, <<"localhost">>, 443, <<"/path">>, <<>>)), ?assertEqual(<<"wss://localhost:8443/path">>, hixie76_location(ssl, <<"localhost">>, 8443, <<"/path">>, <<>>)), ?assertEqual(<<"wss://localhost:8443/path?dummy=2785">>, hixie76_location(ssl, <<"localhost">>, 8443, <<"/path">>, <<"dummy=2785">>)), ok. -endif. rabbitmq-server-3.2.4/plugins-src/cowboy-wrapper/cowboy-git/src/cowboy_http_req.erl0000644000000000000000000007551412305126066027354 0ustar rootroot%% Copyright (c) 2011, Loïc Hoguin %% Copyright (c) 2011, Anthony Ramine %% %% Permission to use, copy, modify, and/or distribute this software for any %% purpose with or without fee is hereby granted, provided that the above %% copyright notice and this permission notice appear in all copies. %% %% THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES %% WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF %% MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR %% ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES %% WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN %% ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF %% OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. %% @doc HTTP request manipulation API. %% %% Almost all functions in this module return a new Req variable. %% It should always be used instead of the one used in your function call %% because it keeps the state of the request. It also allows Cowboy to do %% some lazy evaluation and cache results where possible. -module(cowboy_http_req). -export([ method/1, version/1, peer/1, peer_addr/1, host/1, host_info/1, raw_host/1, port/1, path/1, path_info/1, raw_path/1, qs_val/2, qs_val/3, qs_vals/1, raw_qs/1, binding/2, binding/3, bindings/1, header/2, header/3, headers/1, parse_header/2, parse_header/3, cookie/2, cookie/3, cookies/1, meta/2, meta/3 ]). %% Request API. -export([ body/1, body/2, body_qs/1, multipart_data/1, multipart_skip/1 ]). %% Request Body API. -export([ set_resp_cookie/4, set_resp_header/3, set_resp_body/2, set_resp_body_fun/3, has_resp_header/2, has_resp_body/1, reply/2, reply/3, reply/4, chunked_reply/2, chunked_reply/3, chunk/2, upgrade_reply/3 ]). %% Response API. -export([ compact/1, transport/1 ]). %% Misc API. -include("include/http.hrl"). -include_lib("eunit/include/eunit.hrl"). %% Request API. %% @doc Return the HTTP method of the request. -spec method(#http_req{}) -> {cowboy_http:method(), #http_req{}}. method(Req) -> {Req#http_req.method, Req}. %% @doc Return the HTTP version used for the request. -spec version(#http_req{}) -> {cowboy_http:version(), #http_req{}}. version(Req) -> {Req#http_req.version, Req}. %% @doc Return the peer address and port number of the remote host. -spec peer(#http_req{}) -> {{inet:ip_address(), inet:ip_port()}, #http_req{}}. peer(Req=#http_req{socket=Socket, transport=Transport, peer=undefined}) -> {ok, Peer} = Transport:peername(Socket), {Peer, Req#http_req{peer=Peer}}; peer(Req) -> {Req#http_req.peer, Req}. %% @doc Returns the peer address calculated from headers. -spec peer_addr(#http_req{}) -> {inet:ip_address(), #http_req{}}. peer_addr(Req = #http_req{}) -> {RealIp, Req1} = header(<<"X-Real-Ip">>, Req), {ForwardedForRaw, Req2} = header(<<"X-Forwarded-For">>, Req1), {{PeerIp, _PeerPort}, Req3} = peer(Req2), ForwardedFor = case ForwardedForRaw of undefined -> undefined; ForwardedForRaw -> case re:run(ForwardedForRaw, "^(?[^\\,]+)", [{capture, [first_ip], binary}]) of {match, [FirstIp]} -> FirstIp; _Any -> undefined end end, {ok, PeerAddr} = if is_binary(RealIp) -> inet_parse:address(binary_to_list(RealIp)); is_binary(ForwardedFor) -> inet_parse:address(binary_to_list(ForwardedFor)); true -> {ok, PeerIp} end, {PeerAddr, Req3}. %% @doc Return the tokens for the hostname requested. -spec host(#http_req{}) -> {cowboy_dispatcher:tokens(), #http_req{}}. host(Req) -> {Req#http_req.host, Req}. %% @doc Return the extra host information obtained from partially matching %% the hostname using '...'. -spec host_info(#http_req{}) -> {cowboy_dispatcher:tokens() | undefined, #http_req{}}. host_info(Req) -> {Req#http_req.host_info, Req}. %% @doc Return the raw host directly taken from the request. -spec raw_host(#http_req{}) -> {binary(), #http_req{}}. raw_host(Req) -> {Req#http_req.raw_host, Req}. %% @doc Return the port used for this request. -spec port(#http_req{}) -> {inet:ip_port(), #http_req{}}. port(Req) -> {Req#http_req.port, Req}. %% @doc Return the path segments for the path requested. %% %% Following RFC2396, this function may return path segments containing any %% character, including / if, and only if, a / was escaped %% and part of a path segment in the path requested. -spec path(#http_req{}) -> {cowboy_dispatcher:tokens(), #http_req{}}. path(Req) -> {Req#http_req.path, Req}. %% @doc Return the extra path information obtained from partially matching %% the patch using '...'. -spec path_info(#http_req{}) -> {cowboy_dispatcher:tokens() | undefined, #http_req{}}. path_info(Req) -> {Req#http_req.path_info, Req}. %% @doc Return the raw path directly taken from the request. -spec raw_path(#http_req{}) -> {binary(), #http_req{}}. raw_path(Req) -> {Req#http_req.raw_path, Req}. %% @equiv qs_val(Name, Req, undefined) -spec qs_val(binary(), #http_req{}) -> {binary() | true | undefined, #http_req{}}. qs_val(Name, Req) when is_binary(Name) -> qs_val(Name, Req, undefined). %% @doc Return the query string value for the given key, or a default if %% missing. qs_val(Name, Req=#http_req{raw_qs=RawQs, qs_vals=undefined, urldecode={URLDecFun, URLDecArg}}, Default) when is_binary(Name) -> QsVals = parse_qs(RawQs, fun(Bin) -> URLDecFun(Bin, URLDecArg) end), qs_val(Name, Req#http_req{qs_vals=QsVals}, Default); qs_val(Name, Req, Default) -> case lists:keyfind(Name, 1, Req#http_req.qs_vals) of {Name, Value} -> {Value, Req}; false -> {Default, Req} end. %% @doc Return the full list of query string values. -spec qs_vals(#http_req{}) -> {list({binary(), binary() | true}), #http_req{}}. qs_vals(Req=#http_req{raw_qs=RawQs, qs_vals=undefined, urldecode={URLDecFun, URLDecArg}}) -> QsVals = parse_qs(RawQs, fun(Bin) -> URLDecFun(Bin, URLDecArg) end), qs_vals(Req#http_req{qs_vals=QsVals}); qs_vals(Req=#http_req{qs_vals=QsVals}) -> {QsVals, Req}. %% @doc Return the raw query string directly taken from the request. -spec raw_qs(#http_req{}) -> {binary(), #http_req{}}. raw_qs(Req) -> {Req#http_req.raw_qs, Req}. %% @equiv binding(Name, Req, undefined) -spec binding(atom(), #http_req{}) -> {binary() | undefined, #http_req{}}. binding(Name, Req) when is_atom(Name) -> binding(Name, Req, undefined). %% @doc Return the binding value for the given key obtained when matching %% the host and path against the dispatch list, or a default if missing. binding(Name, Req, Default) when is_atom(Name) -> case lists:keyfind(Name, 1, Req#http_req.bindings) of {Name, Value} -> {Value, Req}; false -> {Default, Req} end. %% @doc Return the full list of binding values. -spec bindings(#http_req{}) -> {list({atom(), binary()}), #http_req{}}. bindings(Req) -> {Req#http_req.bindings, Req}. %% @equiv header(Name, Req, undefined) -spec header(atom() | binary(), #http_req{}) -> {binary() | undefined, #http_req{}}. header(Name, Req) when is_atom(Name) orelse is_binary(Name) -> header(Name, Req, undefined). %% @doc Return the header value for the given key, or a default if missing. header(Name, Req, Default) when is_atom(Name) orelse is_binary(Name) -> case lists:keyfind(Name, 1, Req#http_req.headers) of {Name, Value} -> {Value, Req}; false -> {Default, Req} end. %% @doc Return the full list of headers. -spec headers(#http_req{}) -> {cowboy_http:headers(), #http_req{}}. headers(Req) -> {Req#http_req.headers, Req}. %% @doc Semantically parse headers. %% %% When the value isn't found, a proper default value for the type %% returned is used as a return value. %% @see parse_header/3 -spec parse_header(cowboy_http:header(), #http_req{}) -> {any(), #http_req{}} | {error, badarg}. parse_header(Name, Req=#http_req{p_headers=PHeaders}) -> case lists:keyfind(Name, 1, PHeaders) of false -> parse_header(Name, Req, parse_header_default(Name)); {Name, Value} -> {Value, Req} end. %% @doc Default values for semantic header parsing. -spec parse_header_default(cowboy_http:header()) -> any(). parse_header_default('Connection') -> []; parse_header_default(_Name) -> undefined. %% @doc Semantically parse headers. %% %% When the header is unknown, the value is returned directly without parsing. -spec parse_header(cowboy_http:header(), #http_req{}, any()) -> {any(), #http_req{}} | {error, badarg}. parse_header(Name, Req, Default) when Name =:= 'Accept' -> parse_header(Name, Req, Default, fun (Value) -> cowboy_http:list(Value, fun cowboy_http:media_range/2) end); parse_header(Name, Req, Default) when Name =:= 'Accept-Charset' -> parse_header(Name, Req, Default, fun (Value) -> cowboy_http:nonempty_list(Value, fun cowboy_http:conneg/2) end); parse_header(Name, Req, Default) when Name =:= 'Accept-Encoding' -> parse_header(Name, Req, Default, fun (Value) -> cowboy_http:list(Value, fun cowboy_http:conneg/2) end); parse_header(Name, Req, Default) when Name =:= 'Accept-Language' -> parse_header(Name, Req, Default, fun (Value) -> cowboy_http:nonempty_list(Value, fun cowboy_http:language_range/2) end); parse_header(Name, Req, Default) when Name =:= 'Connection' -> parse_header(Name, Req, Default, fun (Value) -> cowboy_http:nonempty_list(Value, fun cowboy_http:token_ci/2) end); parse_header(Name, Req, Default) when Name =:= 'Content-Length' -> parse_header(Name, Req, Default, fun (Value) -> cowboy_http:digits(Value) end); parse_header(Name, Req, Default) when Name =:= 'Content-Type' -> parse_header(Name, Req, Default, fun (Value) -> cowboy_http:content_type(Value) end); parse_header(Name, Req, Default) when Name =:= 'If-Match'; Name =:= 'If-None-Match' -> parse_header(Name, Req, Default, fun (Value) -> cowboy_http:entity_tag_match(Value) end); parse_header(Name, Req, Default) when Name =:= 'If-Modified-Since'; Name =:= 'If-Unmodified-Since' -> parse_header(Name, Req, Default, fun (Value) -> cowboy_http:http_date(Value) end); parse_header(Name, Req, Default) when Name =:= 'Upgrade' -> parse_header(Name, Req, Default, fun (Value) -> cowboy_http:nonempty_list(Value, fun cowboy_http:token_ci/2) end); parse_header(Name, Req, Default) -> {Value, Req2} = header(Name, Req, Default), {undefined, Value, Req2}. parse_header(Name, Req=#http_req{p_headers=PHeaders}, Default, Fun) -> case header(Name, Req) of {undefined, Req2} -> {Default, Req2#http_req{p_headers=[{Name, Default}|PHeaders]}}; {Value, Req2} -> case Fun(Value) of {error, badarg} -> {error, badarg}; P -> {P, Req2#http_req{p_headers=[{Name, P}|PHeaders]}} end end. %% @equiv cookie(Name, Req, undefined) -spec cookie(binary(), #http_req{}) -> {binary() | true | undefined, #http_req{}}. cookie(Name, Req) when is_binary(Name) -> cookie(Name, Req, undefined). %% @doc Return the cookie value for the given key, or a default if %% missing. cookie(Name, Req=#http_req{cookies=undefined}, Default) when is_binary(Name) -> case header('Cookie', Req) of {undefined, Req2} -> {Default, Req2#http_req{cookies=[]}}; {RawCookie, Req2} -> Cookies = cowboy_cookies:parse_cookie(RawCookie), cookie(Name, Req2#http_req{cookies=Cookies}, Default) end; cookie(Name, Req, Default) -> case lists:keyfind(Name, 1, Req#http_req.cookies) of {Name, Value} -> {Value, Req}; false -> {Default, Req} end. %% @doc Return the full list of cookie values. -spec cookies(#http_req{}) -> {list({binary(), binary() | true}), #http_req{}}. cookies(Req=#http_req{cookies=undefined}) -> case header('Cookie', Req) of {undefined, Req2} -> {[], Req2#http_req{cookies=[]}}; {RawCookie, Req2} -> Cookies = cowboy_cookies:parse_cookie(RawCookie), cookies(Req2#http_req{cookies=Cookies}) end; cookies(Req=#http_req{cookies=Cookies}) -> {Cookies, Req}. %% @equiv meta(Name, Req, undefined) -spec meta(atom(), #http_req{}) -> {any() | undefined, #http_req{}}. meta(Name, Req) -> meta(Name, Req, undefined). %% @doc Return metadata information about the request. %% %% Metadata information varies from one protocol to another. Websockets %% would define the protocol version here, while REST would use it to %% indicate which media type, language and charset were retained. -spec meta(atom(), #http_req{}, any()) -> {any(), #http_req{}}. meta(Name, Req, Default) -> case lists:keyfind(Name, 1, Req#http_req.meta) of {Name, Value} -> {Value, Req}; false -> {Default, Req} end. %% Request Body API. %% @doc Return the full body sent with the request, or {error, badarg} %% if no Content-Length is available. %% @todo We probably want to allow a max length. %% @todo Add multipart support to this function. -spec body(#http_req{}) -> {ok, binary(), #http_req{}} | {error, atom()}. body(Req) -> {Length, Req2} = cowboy_http_req:parse_header('Content-Length', Req), case Length of undefined -> {error, badarg}; {error, badarg} -> {error, badarg}; _Any -> body(Length, Req2) end. %% @doc Return Length bytes of the request body. %% %% You probably shouldn't be calling this function directly, as it expects the %% Length argument to be the full size of the body, and will consider %% the body to be fully read from the socket. %% @todo We probably want to configure the timeout. -spec body(non_neg_integer(), #http_req{}) -> {ok, binary(), #http_req{}} | {error, atom()}. body(Length, Req=#http_req{body_state=waiting, buffer=Buffer}) when is_integer(Length) andalso Length =< byte_size(Buffer) -> << Body:Length/binary, Rest/bits >> = Buffer, {ok, Body, Req#http_req{body_state=done, buffer=Rest}}; body(Length, Req=#http_req{socket=Socket, transport=Transport, body_state=waiting, buffer=Buffer}) -> case Transport:recv(Socket, Length - byte_size(Buffer), 5000) of {ok, Body} -> {ok, << Buffer/binary, Body/binary >>, Req#http_req{body_state=done, buffer= <<>>}}; {error, Reason} -> {error, Reason} end. %% @doc Return the full body sent with the reqest, parsed as an %% application/x-www-form-urlencoded string. Essentially a POST query string. -spec body_qs(#http_req{}) -> {list({binary(), binary() | true}), #http_req{}}. body_qs(Req=#http_req{urldecode={URLDecFun, URLDecArg}}) -> {ok, Body, Req2} = body(Req), {parse_qs(Body, fun(Bin) -> URLDecFun(Bin, URLDecArg) end), Req2}. %% Multipart Request API. %% @doc Return data from the multipart parser. %% %% Use this function for multipart streaming. For each part in the request, %% this function returns {headers, Headers} followed by a sequence of %% {data, Data} tuples and finally end_of_part. When there %% is no part to parse anymore, eof is returned. %% %% If the request Content-Type is not a multipart one, {error, badarg} %% is returned. -spec multipart_data(#http_req{}) -> {{headers, cowboy_http:headers()} | {data, binary()} | end_of_part | eof, #http_req{}}. multipart_data(Req=#http_req{body_state=waiting}) -> {{<<"multipart">>, _SubType, Params}, Req2} = parse_header('Content-Type', Req), {_, Boundary} = lists:keyfind(<<"boundary">>, 1, Params), {Length, Req3=#http_req{buffer=Buffer}} = parse_header('Content-Length', Req2), multipart_data(Req3, Length, cowboy_multipart:parser(Boundary), Buffer); multipart_data(Req=#http_req{body_state={multipart, Length, Cont}}) -> multipart_data(Req, Length, Cont()); multipart_data(Req=#http_req{body_state=done}) -> {eof, Req}. multipart_data(Req, Length, Parser, Buffer) when byte_size(Buffer) >= Length -> << Data:Length/binary, Rest/binary >> = Buffer, multipart_data(Req#http_req{buffer=Rest}, 0, Parser(Data)); multipart_data(Req, Length, Parser, Buffer) -> NewLength = Length - byte_size(Buffer), multipart_data(Req#http_req{buffer= <<>>}, NewLength, Parser(Buffer)). multipart_data(Req, Length, {headers, Headers, Cont}) -> {{headers, Headers}, Req#http_req{body_state={multipart, Length, Cont}}}; multipart_data(Req, Length, {body, Data, Cont}) -> {{body, Data}, Req#http_req{body_state={multipart, Length, Cont}}}; multipart_data(Req, Length, {end_of_part, Cont}) -> {end_of_part, Req#http_req{body_state={multipart, Length, Cont}}}; multipart_data(Req, 0, eof) -> {eof, Req#http_req{body_state=done}}; multipart_data(Req=#http_req{socket=Socket, transport=Transport}, Length, eof) -> {ok, _Data} = Transport:recv(Socket, Length, 5000), {eof, Req#http_req{body_state=done}}; multipart_data(Req=#http_req{socket=Socket, transport=Transport}, Length, {more, Parser}) when Length > 0 -> case Transport:recv(Socket, 0, 5000) of {ok, << Data:Length/binary, Buffer/binary >>} -> multipart_data(Req#http_req{buffer=Buffer}, 0, Parser(Data)); {ok, Data} -> multipart_data(Req, Length - byte_size(Data), Parser(Data)) end. %% @doc Skip a part returned by the multipart parser. %% %% This function repeatedly calls multipart_data/1 until %% end_of_part or eof is parsed. multipart_skip(Req) -> case multipart_data(Req) of {end_of_part, Req2} -> {ok, Req2}; {eof, Req2} -> {ok, Req2}; {_Other, Req2} -> multipart_skip(Req2) end. %% Response API. %% @doc Add a cookie header to the response. -spec set_resp_cookie(binary(), binary(), [cowboy_cookies:cookie_option()], #http_req{}) -> {ok, #http_req{}}. set_resp_cookie(Name, Value, Options, Req) -> {HeaderName, HeaderValue} = cowboy_cookies:cookie(Name, Value, Options), set_resp_header(HeaderName, HeaderValue, Req). %% @doc Add a header to the response. set_resp_header(Name, Value, Req=#http_req{resp_headers=RespHeaders}) -> NameBin = header_to_binary(Name), {ok, Req#http_req{resp_headers=[{NameBin, Value}|RespHeaders]}}. %% @doc Add a body to the response. %% %% The body set here is ignored if the response is later sent using %% anything other than reply/2 or reply/3. The response body is expected %% to be a binary or an iolist. set_resp_body(Body, Req) -> {ok, Req#http_req{resp_body=Body}}. %% @doc Add a body function to the response. %% %% The response body may also be set to a content-length - stream-function pair. %% If the response body is of this type normal response headers will be sent. %% After the response headers has been sent the body function is applied. %% The body function is expected to write the response body directly to the %% socket using the transport module. %% %% If the body function crashes while writing the response body or writes fewer %% bytes than declared the behaviour is undefined. The body set here is ignored %% if the response is later sent using anything other than `reply/2' or %% `reply/3'. %% %% @see cowboy_http_req:transport/1. -spec set_resp_body_fun(non_neg_integer(), fun(() -> {sent, non_neg_integer()}), #http_req{}) -> {ok, #http_req{}}. set_resp_body_fun(StreamLen, StreamFun, Req) -> {ok, Req#http_req{resp_body={StreamLen, StreamFun}}}. %% @doc Return whether the given header has been set for the response. has_resp_header(Name, #http_req{resp_headers=RespHeaders}) -> NameBin = header_to_binary(Name), lists:keymember(NameBin, 1, RespHeaders). %% @doc Return whether a body has been set for the response. has_resp_body(#http_req{resp_body={Length, _}}) -> Length > 0; has_resp_body(#http_req{resp_body=RespBody}) -> iolist_size(RespBody) > 0. %% @equiv reply(Status, [], [], Req) -spec reply(cowboy_http:status(), #http_req{}) -> {ok, #http_req{}}. reply(Status, Req=#http_req{resp_body=Body}) -> reply(Status, [], Body, Req). %% @equiv reply(Status, Headers, [], Req) -spec reply(cowboy_http:status(), cowboy_http:headers(), #http_req{}) -> {ok, #http_req{}}. reply(Status, Headers, Req=#http_req{resp_body=Body}) -> reply(Status, Headers, Body, Req). %% @doc Send a reply to the client. reply(Status, Headers, Body, Req=#http_req{socket=Socket, transport=Transport, connection=Connection, pid=ReqPid, method=Method, resp_state=waiting, resp_headers=RespHeaders}) -> RespConn = response_connection(Headers, Connection), ContentLen = case Body of {CL, _} -> CL; _ -> iolist_size(Body) end, Head = response_head(Status, Headers, RespHeaders, [ {<<"Connection">>, atom_to_connection(Connection)}, {<<"Content-Length">>, integer_to_list(ContentLen)}, {<<"Date">>, cowboy_clock:rfc1123()}, {<<"Server">>, <<"Cowboy">>} ]), case {Method, Body} of {'HEAD', _} -> Transport:send(Socket, Head); {_, {_, StreamFun}} -> Transport:send(Socket, Head), StreamFun(); {_, _} -> Transport:send(Socket, [Head, Body]) end, ReqPid ! {?MODULE, resp_sent}, {ok, Req#http_req{connection=RespConn, resp_state=done, resp_headers=[], resp_body= <<>>}}. %% @equiv chunked_reply(Status, [], Req) -spec chunked_reply(cowboy_http:status(), #http_req{}) -> {ok, #http_req{}}. chunked_reply(Status, Req) -> chunked_reply(Status, [], Req). %% @doc Initiate the sending of a chunked reply to the client. %% @see cowboy_http_req:chunk/2 -spec chunked_reply(cowboy_http:status(), cowboy_http:headers(), #http_req{}) -> {ok, #http_req{}}. chunked_reply(Status, Headers, Req=#http_req{socket=Socket, transport=Transport, connection=Connection, pid=ReqPid, resp_state=waiting, resp_headers=RespHeaders}) -> RespConn = response_connection(Headers, Connection), Head = response_head(Status, Headers, RespHeaders, [ {<<"Connection">>, atom_to_connection(Connection)}, {<<"Transfer-Encoding">>, <<"chunked">>}, {<<"Date">>, cowboy_clock:rfc1123()}, {<<"Server">>, <<"Cowboy">>} ]), Transport:send(Socket, Head), ReqPid ! {?MODULE, resp_sent}, {ok, Req#http_req{connection=RespConn, resp_state=chunks, resp_headers=[], resp_body= <<>>}}. %% @doc Send a chunk of data. %% %% A chunked reply must have been initiated before calling this function. chunk(_Data, #http_req{socket=_Socket, transport=_Transport, method='HEAD'}) -> ok; chunk(Data, #http_req{socket=Socket, transport=Transport, resp_state=chunks}) -> Transport:send(Socket, [erlang:integer_to_list(iolist_size(Data), 16), <<"\r\n">>, Data, <<"\r\n">>]). %% @doc Send an upgrade reply. %% @private -spec upgrade_reply(cowboy_http:status(), cowboy_http:headers(), #http_req{}) -> {ok, #http_req{}}. upgrade_reply(Status, Headers, Req=#http_req{socket=Socket, transport=Transport, pid=ReqPid, resp_state=waiting, resp_headers=RespHeaders}) -> Head = response_head(Status, Headers, RespHeaders, [ {<<"Connection">>, <<"Upgrade">>} ]), Transport:send(Socket, Head), ReqPid ! {?MODULE, resp_sent}, {ok, Req#http_req{resp_state=done, resp_headers=[], resp_body= <<>>}}. %% Misc API. %% @doc Compact the request data by removing all non-system information. %% %% This essentially removes the host, path, query string, bindings and headers. %% Use it when you really need to save up memory, for example when having %% many concurrent long-running connections. -spec compact(#http_req{}) -> #http_req{}. compact(Req) -> Req#http_req{host=undefined, host_info=undefined, path=undefined, path_info=undefined, qs_vals=undefined, bindings=undefined, headers=[], p_headers=[], cookies=[]}. %% @doc Return the transport module and socket associated with a request. %% %% This exposes the same socket interface used internally by the HTTP protocol %% implementation to developers that needs low level access to the socket. %% %% It is preferred to use this in conjuction with the stream function support %% in `set_resp_body_fun/3' if this is used to write a response body directly %% to the socket. This ensures that the response headers are set correctly. -spec transport(#http_req{}) -> {ok, module(), inet:socket()}. transport(#http_req{transport=Transport, socket=Socket}) -> {ok, Transport, Socket}. %% Internal. -spec parse_qs(binary(), fun((binary()) -> binary())) -> list({binary(), binary() | true}). parse_qs(<<>>, _URLDecode) -> []; parse_qs(Qs, URLDecode) -> Tokens = binary:split(Qs, <<"&">>, [global, trim]), [case binary:split(Token, <<"=">>) of [Token] -> {URLDecode(Token), true}; [Name, Value] -> {URLDecode(Name), URLDecode(Value)} end || Token <- Tokens]. -spec response_connection(cowboy_http:headers(), keepalive | close) -> keepalive | close. response_connection([], Connection) -> Connection; response_connection([{Name, Value}|Tail], Connection) -> case Name of 'Connection' -> response_connection_parse(Value); Name when is_atom(Name) -> response_connection(Tail, Connection); Name -> Name2 = cowboy_bstr:to_lower(Name), case Name2 of <<"connection">> -> response_connection_parse(Value); _Any -> response_connection(Tail, Connection) end end. -spec response_connection_parse(binary()) -> keepalive | close. response_connection_parse(ReplyConn) -> Tokens = cowboy_http:nonempty_list(ReplyConn, fun cowboy_http:token/2), cowboy_http:connection_to_atom(Tokens). -spec response_head(cowboy_http:status(), cowboy_http:headers(), cowboy_http:headers(), cowboy_http:headers()) -> iolist(). response_head(Status, Headers, RespHeaders, DefaultHeaders) -> StatusLine = <<"HTTP/1.1 ", (status(Status))/binary, "\r\n">>, Headers2 = [{header_to_binary(Key), Value} || {Key, Value} <- Headers], Headers3 = merge_headers( merge_headers(Headers2, RespHeaders), DefaultHeaders), Headers4 = [[Key, <<": ">>, Value, <<"\r\n">>] || {Key, Value} <- Headers3], [StatusLine, Headers4, <<"\r\n">>]. -spec merge_headers(cowboy_http:headers(), cowboy_http:headers()) -> cowboy_http:headers(). merge_headers(Headers, []) -> Headers; merge_headers(Headers, [{Name, Value}|Tail]) -> Headers2 = case lists:keymember(Name, 1, Headers) of true -> Headers; false -> Headers ++ [{Name, Value}] end, merge_headers(Headers2, Tail). -spec atom_to_connection(keepalive) -> <<_:80>>; (close) -> <<_:40>>. atom_to_connection(keepalive) -> <<"keep-alive">>; atom_to_connection(close) -> <<"close">>. -spec status(cowboy_http:status()) -> binary(). status(100) -> <<"100 Continue">>; status(101) -> <<"101 Switching Protocols">>; status(102) -> <<"102 Processing">>; status(200) -> <<"200 OK">>; status(201) -> <<"201 Created">>; status(202) -> <<"202 Accepted">>; status(203) -> <<"203 Non-Authoritative Information">>; status(204) -> <<"204 No Content">>; status(205) -> <<"205 Reset Content">>; status(206) -> <<"206 Partial Content">>; status(207) -> <<"207 Multi-Status">>; status(226) -> <<"226 IM Used">>; status(300) -> <<"300 Multiple Choices">>; status(301) -> <<"301 Moved Permanently">>; status(302) -> <<"302 Found">>; status(303) -> <<"303 See Other">>; status(304) -> <<"304 Not Modified">>; status(305) -> <<"305 Use Proxy">>; status(306) -> <<"306 Switch Proxy">>; status(307) -> <<"307 Temporary Redirect">>; status(400) -> <<"400 Bad Request">>; status(401) -> <<"401 Unauthorized">>; status(402) -> <<"402 Payment Required">>; status(403) -> <<"403 Forbidden">>; status(404) -> <<"404 Not Found">>; status(405) -> <<"405 Method Not Allowed">>; status(406) -> <<"406 Not Acceptable">>; status(407) -> <<"407 Proxy Authentication Required">>; status(408) -> <<"408 Request Timeout">>; status(409) -> <<"409 Conflict">>; status(410) -> <<"410 Gone">>; status(411) -> <<"411 Length Required">>; status(412) -> <<"412 Precondition Failed">>; status(413) -> <<"413 Request Entity Too Large">>; status(414) -> <<"414 Request-URI Too Long">>; status(415) -> <<"415 Unsupported Media Type">>; status(416) -> <<"416 Requested Range Not Satisfiable">>; status(417) -> <<"417 Expectation Failed">>; status(418) -> <<"418 I'm a teapot">>; status(422) -> <<"422 Unprocessable Entity">>; status(423) -> <<"423 Locked">>; status(424) -> <<"424 Failed Dependency">>; status(425) -> <<"425 Unordered Collection">>; status(426) -> <<"426 Upgrade Required">>; status(500) -> <<"500 Internal Server Error">>; status(501) -> <<"501 Not Implemented">>; status(502) -> <<"502 Bad Gateway">>; status(503) -> <<"503 Service Unavailable">>; status(504) -> <<"504 Gateway Timeout">>; status(505) -> <<"505 HTTP Version Not Supported">>; status(506) -> <<"506 Variant Also Negotiates">>; status(507) -> <<"507 Insufficient Storage">>; status(510) -> <<"510 Not Extended">>; status(B) when is_binary(B) -> B. -spec header_to_binary(cowboy_http:header()) -> binary(). header_to_binary('Cache-Control') -> <<"Cache-Control">>; header_to_binary('Connection') -> <<"Connection">>; header_to_binary('Date') -> <<"Date">>; header_to_binary('Pragma') -> <<"Pragma">>; header_to_binary('Transfer-Encoding') -> <<"Transfer-Encoding">>; header_to_binary('Upgrade') -> <<"Upgrade">>; header_to_binary('Via') -> <<"Via">>; header_to_binary('Accept') -> <<"Accept">>; header_to_binary('Accept-Charset') -> <<"Accept-Charset">>; header_to_binary('Accept-Encoding') -> <<"Accept-Encoding">>; header_to_binary('Accept-Language') -> <<"Accept-Language">>; header_to_binary('Authorization') -> <<"Authorization">>; header_to_binary('From') -> <<"From">>; header_to_binary('Host') -> <<"Host">>; header_to_binary('If-Modified-Since') -> <<"If-Modified-Since">>; header_to_binary('If-Match') -> <<"If-Match">>; header_to_binary('If-None-Match') -> <<"If-None-Match">>; header_to_binary('If-Range') -> <<"If-Range">>; header_to_binary('If-Unmodified-Since') -> <<"If-Unmodified-Since">>; header_to_binary('Max-Forwards') -> <<"Max-Forwards">>; header_to_binary('Proxy-Authorization') -> <<"Proxy-Authorization">>; header_to_binary('Range') -> <<"Range">>; header_to_binary('Referer') -> <<"Referer">>; header_to_binary('User-Agent') -> <<"User-Agent">>; header_to_binary('Age') -> <<"Age">>; header_to_binary('Location') -> <<"Location">>; header_to_binary('Proxy-Authenticate') -> <<"Proxy-Authenticate">>; header_to_binary('Public') -> <<"Public">>; header_to_binary('Retry-After') -> <<"Retry-After">>; header_to_binary('Server') -> <<"Server">>; header_to_binary('Vary') -> <<"Vary">>; header_to_binary('Warning') -> <<"Warning">>; header_to_binary('Www-Authenticate') -> <<"Www-Authenticate">>; header_to_binary('Allow') -> <<"Allow">>; header_to_binary('Content-Base') -> <<"Content-Base">>; header_to_binary('Content-Encoding') -> <<"Content-Encoding">>; header_to_binary('Content-Language') -> <<"Content-Language">>; header_to_binary('Content-Length') -> <<"Content-Length">>; header_to_binary('Content-Location') -> <<"Content-Location">>; header_to_binary('Content-Md5') -> <<"Content-Md5">>; header_to_binary('Content-Range') -> <<"Content-Range">>; header_to_binary('Content-Type') -> <<"Content-Type">>; header_to_binary('Etag') -> <<"Etag">>; header_to_binary('Expires') -> <<"Expires">>; header_to_binary('Last-Modified') -> <<"Last-Modified">>; header_to_binary('Accept-Ranges') -> <<"Accept-Ranges">>; header_to_binary('Set-Cookie') -> <<"Set-Cookie">>; header_to_binary('Set-Cookie2') -> <<"Set-Cookie2">>; header_to_binary('X-Forwarded-For') -> <<"X-Forwarded-For">>; header_to_binary('Cookie') -> <<"Cookie">>; header_to_binary('Keep-Alive') -> <<"Keep-Alive">>; header_to_binary('Proxy-Connection') -> <<"Proxy-Connection">>; header_to_binary(B) when is_binary(B) -> B. %% Tests. -ifdef(TEST). parse_qs_test_() -> %% {Qs, Result} Tests = [ {<<"">>, []}, {<<"a=b">>, [{<<"a">>, <<"b">>}]}, {<<"aaa=bbb">>, [{<<"aaa">>, <<"bbb">>}]}, {<<"a&b">>, [{<<"a">>, true}, {<<"b">>, true}]}, {<<"a=b&c&d=e">>, [{<<"a">>, <<"b">>}, {<<"c">>, true}, {<<"d">>, <<"e">>}]}, {<<"a=b=c=d=e&f=g">>, [{<<"a">>, <<"b=c=d=e">>}, {<<"f">>, <<"g">>}]}, {<<"a+b=c+d">>, [{<<"a b">>, <<"c d">>}]} ], URLDecode = fun cowboy_http:urldecode/1, [{Qs, fun() -> R = parse_qs(Qs, URLDecode) end} || {Qs, R} <- Tests]. -endif. rabbitmq-server-3.2.4/plugins-src/cowboy-wrapper/cowboy-git/src/cowboy_ssl_transport.erl0000644000000000000000000001325412305126066030434 0ustar rootroot%% Copyright (c) 2011, Loïc Hoguin %% %% Permission to use, copy, modify, and/or distribute this software for any %% purpose with or without fee is hereby granted, provided that the above %% copyright notice and this permission notice appear in all copies. %% %% THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES %% WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF %% MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR %% ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES %% WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN %% ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF %% OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. %% @doc SSL transport API. %% %% Wrapper around ssl implementing the Cowboy transport API. %% %% This transport requires the crypto, public_key %% and ssl applications to be started. If they aren't started, %% it will try to start them itself before opening a port to listen. %% Applications aren't stopped when the listening socket is closed, though. %% %% @see ssl -module(cowboy_ssl_transport). -export([name/0, messages/0, listen/1, accept/2, recv/3, send/2, setopts/2, controlling_process/2, peername/1, close/1]). %% @doc Name of this transport API, ssl. -spec name() -> ssl. name() -> ssl. %% @doc Atoms used in the process messages sent by this API. %% %% They identify incoming data, closed connection and errors when receiving %% data in active mode. -spec messages() -> {ssl, ssl_closed, ssl_error}. messages() -> {ssl, ssl_closed, ssl_error}. %% @doc Setup a socket to listen on the given port on the local host. %% %% The available options are: %%
    %%
    port
    Mandatory. TCP port number to open.
    %%
    backlog
    Maximum length of the pending connections queue. %% Defaults to 1024.
    %%
    ip
    Interface to listen on. Listen on all interfaces %% by default.
    %%
    certfile
    Mandatory. Path to a file containing the user's %% certificate.
    %%
    keyfile
    Mandatory. Path to the file containing the user's %% private PEM encoded key.
    %%
    cacertfile
    Optional. Path to file containing PEM encoded %% CA certificates (trusted certificates used for verifying a peer %% certificate).
    %%
    password
    Mandatory. String containing the user's password. %% All private keyfiles must be password protected currently.
    %%
    %% %% @see ssl:listen/2 %% @todo The password option shouldn't be mandatory. -spec listen([{port, inet:ip_port()} | {certfile, string()} | {keyfile, string()} | {password, string()} | {cacertfile, string()} | {ip, inet:ip_address()}]) -> {ok, ssl:sslsocket()} | {error, atom()}. listen(Opts) -> require([crypto, public_key, ssl]), {port, Port} = lists:keyfind(port, 1, Opts), Backlog = proplists:get_value(backlog, Opts, 1024), {certfile, CertFile} = lists:keyfind(certfile, 1, Opts), {keyfile, KeyFile} = lists:keyfind(keyfile, 1, Opts), {password, Password} = lists:keyfind(password, 1, Opts), ListenOpts0 = [binary, {active, false}, {backlog, Backlog}, {packet, raw}, {reuseaddr, true}, {certfile, CertFile}, {keyfile, KeyFile}, {password, Password}], ListenOpts1 = case lists:keyfind(ip, 1, Opts) of false -> ListenOpts0; Ip -> [Ip|ListenOpts0] end, ListenOpts = case lists:keyfind(cacertfile, 1, Opts) of false -> ListenOpts1; CACertFile -> [CACertFile|ListenOpts1] end, ssl:listen(Port, ListenOpts). %% @doc Accept an incoming connection on a listen socket. %% %% Note that this function does both the transport accept and %% the SSL handshake. %% %% @see ssl:transport_accept/2 %% @see ssl:ssl_accept/2 -spec accept(ssl:sslsocket(), timeout()) -> {ok, ssl:sslsocket()} | {error, closed | timeout | atom()}. accept(LSocket, Timeout) -> case ssl:transport_accept(LSocket, Timeout) of {ok, CSocket} -> ssl_accept(CSocket, Timeout); {error, Reason} -> {error, Reason} end. %% @doc Receive a packet from a socket in passive mode. %% @see ssl:recv/3 -spec recv(ssl:sslsocket(), non_neg_integer(), timeout()) -> {ok, any()} | {error, closed | atom()}. recv(Socket, Length, Timeout) -> ssl:recv(Socket, Length, Timeout). %% @doc Send a packet on a socket. %% @see ssl:send/2 -spec send(ssl:sslsocket(), iolist()) -> ok | {error, atom()}. send(Socket, Packet) -> ssl:send(Socket, Packet). %% @doc Set one or more options for a socket. %% @see ssl:setopts/2 -spec setopts(ssl:sslsocket(), list()) -> ok | {error, atom()}. setopts(Socket, Opts) -> ssl:setopts(Socket, Opts). %% @doc Assign a new controlling process Pid to Socket. %% @see ssl:controlling_process/2 -spec controlling_process(ssl:sslsocket(), pid()) -> ok | {error, closed | not_owner | atom()}. controlling_process(Socket, Pid) -> ssl:controlling_process(Socket, Pid). %% @doc Return the address and port for the other end of a connection. %% @see ssl:peername/1 -spec peername(ssl:sslsocket()) -> {ok, {inet:ip_address(), inet:ip_port()}} | {error, atom()}. peername(Socket) -> ssl:peername(Socket). %% @doc Close a TCP socket. %% @see ssl:close/1 -spec close(ssl:sslsocket()) -> ok. close(Socket) -> ssl:close(Socket). %% Internal. -spec require(list(module())) -> ok. require([]) -> ok; require([App|Tail]) -> case application:start(App) of ok -> ok; {error, {already_started, App}} -> ok end, require(Tail). -spec ssl_accept(ssl:sslsocket(), timeout()) -> {ok, ssl:sslsocket()} | {error, closed | timeout | atom()}. ssl_accept(Socket, Timeout) -> case ssl:ssl_accept(Socket, Timeout) of ok -> {ok, Socket}; {error, Reason} -> {error, Reason} end. rabbitmq-server-3.2.4/plugins-src/cowboy-wrapper/cowboy-git/src/cowboy_http_rest.erl0000644000000000000000000010030512305126066027525 0ustar rootroot%% Copyright (c) 2011, Loïc Hoguin %% %% Permission to use, copy, modify, and/or distribute this software for any %% purpose with or without fee is hereby granted, provided that the above %% copyright notice and this permission notice appear in all copies. %% %% THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES %% WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF %% MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR %% ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES %% WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN %% ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF %% OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. %% @doc Experimental REST protocol implementation. %% %% Based on the Webmachine Diagram from Alan Dean and Justin Sheehy, which %% can be found in the Webmachine source tree, and on the Webmachine %% documentation available at http://wiki.basho.com/Webmachine.html %% at the time of writing. -module(cowboy_http_rest). -export([upgrade/4]). -record(state, { %% Handler. handler :: atom(), handler_state :: any(), %% Media type. content_types_p = [] :: [{{binary(), binary(), [{binary(), binary()}]}, atom()}], content_type_a :: undefined | {{binary(), binary(), [{binary(), binary()}]}, atom()}, %% Language. languages_p = [] :: [binary()], language_a :: undefined | binary(), %% Charset. charsets_p = [] :: [binary()], charset_a :: undefined | binary(), %% Cached resource calls. etag :: undefined | no_call | binary(), last_modified :: undefined | no_call | calendar:datetime(), expires :: undefined | no_call | calendar:datetime() }). -include("include/http.hrl"). %% @doc Upgrade a HTTP request to the REST protocol. %% %% You do not need to call this function manually. To upgrade to the REST %% protocol, you simply need to return {upgrade, protocol, {@module}} %% in your cowboy_http_handler:init/3 handler function. -spec upgrade(pid(), module(), any(), #http_req{}) -> {ok, #http_req{}} | close. upgrade(_ListenerPid, Handler, Opts, Req) -> try case erlang:function_exported(Handler, rest_init, 2) of true -> case Handler:rest_init(Req, Opts) of {ok, Req2, HandlerState} -> service_available(Req2, #state{handler=Handler, handler_state=HandlerState}) end; false -> service_available(Req, #state{handler=Handler}) end catch Class:Reason -> error_logger:error_msg( "** Handler ~p terminating in rest_init/3~n" " for the reason ~p:~p~n** Options were ~p~n" "** Request was ~p~n** Stacktrace: ~p~n~n", [Handler, Class, Reason, Opts, Req, erlang:get_stacktrace()]), {ok, _Req2} = cowboy_http_req:reply(500, Req), close end. service_available(Req, State) -> expect(Req, State, service_available, true, fun known_methods/2, 503). %% known_methods/2 should return a list of atoms or binary methods. known_methods(Req=#http_req{method=Method}, State) -> case call(Req, State, known_methods) of no_call when Method =:= 'HEAD'; Method =:= 'GET'; Method =:= 'POST'; Method =:= 'PUT'; Method =:= 'DELETE'; Method =:= 'TRACE'; Method =:= 'CONNECT'; Method =:= 'OPTIONS' -> next(Req, State, fun uri_too_long/2); no_call -> next(Req, State, 501); {halt, Req2, HandlerState} -> terminate(Req2, State#state{handler_state=HandlerState}); {List, Req2, HandlerState} -> State2 = State#state{handler_state=HandlerState}, case lists:member(Method, List) of true -> next(Req2, State2, fun uri_too_long/2); false -> next(Req2, State2, 501) end end. uri_too_long(Req, State) -> expect(Req, State, uri_too_long, false, fun allowed_methods/2, 414). %% allowed_methods/2 should return a list of atoms or binary methods. allowed_methods(Req=#http_req{method=Method}, State) -> case call(Req, State, allowed_methods) of no_call when Method =:= 'HEAD'; Method =:= 'GET' -> next(Req, State, fun malformed_request/2); no_call -> method_not_allowed(Req, State, ['GET', 'HEAD']); {halt, Req2, HandlerState} -> terminate(Req2, State#state{handler_state=HandlerState}); {List, Req2, HandlerState} -> State2 = State#state{handler_state=HandlerState}, case lists:member(Method, List) of true -> next(Req2, State2, fun malformed_request/2); false -> method_not_allowed(Req2, State2, List) end end. method_not_allowed(Req, State, Methods) -> {ok, Req2} = cowboy_http_req:set_resp_header( <<"Allow">>, method_not_allowed_build(Methods, []), Req), respond(Req2, State, 405). method_not_allowed_build([], []) -> <<>>; method_not_allowed_build([], [_Ignore|Acc]) -> lists:reverse(Acc); method_not_allowed_build([Method|Tail], Acc) when is_atom(Method) -> Method2 = list_to_binary(atom_to_list(Method)), method_not_allowed_build(Tail, [<<", ">>, Method2|Acc]); method_not_allowed_build([Method|Tail], Acc) -> method_not_allowed_build(Tail, [<<", ">>, Method|Acc]). malformed_request(Req, State) -> expect(Req, State, malformed_request, false, fun is_authorized/2, 400). %% is_authorized/2 should return true or {false, WwwAuthenticateHeader}. is_authorized(Req, State) -> case call(Req, State, is_authorized) of no_call -> forbidden(Req, State); {halt, Req2, HandlerState} -> terminate(Req2, State#state{handler_state=HandlerState}); {true, Req2, HandlerState} -> forbidden(Req2, State#state{handler_state=HandlerState}); {{false, AuthHead}, Req2, HandlerState} -> {ok, Req3} = cowboy_http_req:set_resp_header( <<"Www-Authenticate">>, AuthHead, Req2), respond(Req3, State#state{handler_state=HandlerState}, 401) end. forbidden(Req, State) -> expect(Req, State, forbidden, false, fun valid_content_headers/2, 403). valid_content_headers(Req, State) -> expect(Req, State, valid_content_headers, true, fun known_content_type/2, 501). known_content_type(Req, State) -> expect(Req, State, known_content_type, true, fun valid_entity_length/2, 413). valid_entity_length(Req, State) -> expect(Req, State, valid_entity_length, true, fun options/2, 413). %% If you need to add additional headers to the response at this point, %% you should do it directly in the options/2 call using set_resp_headers. options(Req=#http_req{method='OPTIONS'}, State) -> case call(Req, State, options) of {halt, Req2, HandlerState} -> terminate(Req2, State#state{handler_state=HandlerState}); {ok, Req2, HandlerState} -> respond(Req2, State#state{handler_state=HandlerState}, 200) end; options(Req, State) -> content_types_provided(Req, State). %% content_types_provided/2 should return a list of content types and their %% associated callback function as a tuple: {{Type, SubType, Params}, Fun}. %% Type and SubType are the media type as binary. Params is a list of %% Key/Value tuple, with Key and Value a binary. Fun is the name of the %% callback that will be used to return the content of the response. It is %% given as an atom. %% %% An example of such return value would be: %% {{<<"text">>, <<"html">>, []}, to_html} %% %% Note that it is also possible to return a binary content type that will %% then be parsed by Cowboy. However note that while this may make your %% resources a little more readable, this is a lot less efficient. An example %% of such a return value would be: %% {<<"text/html">>, to_html} content_types_provided(Req=#http_req{meta=Meta}, State) -> case call(Req, State, content_types_provided) of no_call -> not_acceptable(Req, State); {halt, Req2, HandlerState} -> terminate(Req2, State#state{handler_state=HandlerState}); {[], Req2, HandlerState} -> not_acceptable(Req2, State#state{handler_state=HandlerState}); {CTP, Req2, HandlerState} -> CTP2 = [normalize_content_types_provided(P) || P <- CTP], State2 = State#state{ handler_state=HandlerState, content_types_p=CTP2}, {Accept, Req3} = cowboy_http_req:parse_header('Accept', Req2), case Accept of undefined -> {PMT, _Fun} = HeadCTP = hd(CTP2), languages_provided( Req3#http_req{meta=[{media_type, PMT}|Meta]}, State2#state{content_type_a=HeadCTP}); Accept -> Accept2 = prioritize_accept(Accept), choose_media_type(Req3, State2, Accept2) end end. normalize_content_types_provided({ContentType, Handler}) when is_binary(ContentType) -> {cowboy_http:content_type(ContentType), Handler}; normalize_content_types_provided(Provided) -> Provided. prioritize_accept(Accept) -> lists:sort( fun ({MediaTypeA, Quality, _AcceptParamsA}, {MediaTypeB, Quality, _AcceptParamsB}) -> %% Same quality, check precedence in more details. prioritize_mediatype(MediaTypeA, MediaTypeB); ({_MediaTypeA, QualityA, _AcceptParamsA}, {_MediaTypeB, QualityB, _AcceptParamsB}) -> %% Just compare the quality. QualityA > QualityB end, Accept). %% Media ranges can be overridden by more specific media ranges or %% specific media types. If more than one media range applies to a given %% type, the most specific reference has precedence. %% %% We always choose B over A when we can't decide between the two. prioritize_mediatype({TypeA, SubTypeA, ParamsA}, {TypeB, SubTypeB, ParamsB}) -> case TypeB of TypeA -> case SubTypeB of SubTypeA -> length(ParamsA) > length(ParamsB); <<"*">> -> true; _Any -> false end; <<"*">> -> true; _Any -> false end. %% Ignoring the rare AcceptParams. Not sure what should be done about them. choose_media_type(Req, State, []) -> not_acceptable(Req, State); choose_media_type(Req, State=#state{content_types_p=CTP}, [MediaType|Tail]) -> match_media_type(Req, State, Tail, CTP, MediaType). match_media_type(Req, State, Accept, [], _MediaType) -> choose_media_type(Req, State, Accept); match_media_type(Req, State, Accept, CTP, MediaType = {{<<"*">>, <<"*">>, _Params_A}, _QA, _APA}) -> match_media_type_params(Req, State, Accept, CTP, MediaType); match_media_type(Req, State, Accept, CTP = [{{Type, SubType_P, _PP}, _Fun}|_Tail], MediaType = {{Type, SubType_A, _PA}, _QA, _APA}) when SubType_P =:= SubType_A; SubType_A =:= <<"*">> -> match_media_type_params(Req, State, Accept, CTP, MediaType); match_media_type(Req, State, Accept, [_Any|Tail], MediaType) -> match_media_type(Req, State, Accept, Tail, MediaType). match_media_type_params(Req=#http_req{meta=Meta}, State, Accept, [Provided = {PMT = {_TP, _STP, Params_P}, _Fun}|Tail], MediaType = {{_TA, _STA, Params_A}, _QA, _APA}) -> case lists:sort(Params_P) =:= lists:sort(Params_A) of true -> languages_provided(Req#http_req{meta=[{media_type, PMT}|Meta]}, State#state{content_type_a=Provided}); false -> match_media_type(Req, State, Accept, Tail, MediaType) end. %% languages_provided should return a list of binary values indicating %% which languages are accepted by the resource. %% %% @todo I suppose we should also ask the resource if it wants to %% set a language itself or if it wants it to be automatically chosen. languages_provided(Req, State) -> case call(Req, State, languages_provided) of no_call -> charsets_provided(Req, State); {halt, Req2, HandlerState} -> terminate(Req2, State#state{handler_state=HandlerState}); {[], Req2, HandlerState} -> not_acceptable(Req2, State#state{handler_state=HandlerState}); {LP, Req2, HandlerState} -> State2 = State#state{handler_state=HandlerState, languages_p=LP}, {AcceptLanguage, Req3} = cowboy_http_req:parse_header('Accept-Language', Req2), case AcceptLanguage of undefined -> set_language(Req3, State2#state{language_a=hd(LP)}); AcceptLanguage -> AcceptLanguage2 = prioritize_languages(AcceptLanguage), choose_language(Req3, State2, AcceptLanguage2) end end. %% A language-range matches a language-tag if it exactly equals the tag, %% or if it exactly equals a prefix of the tag such that the first tag %% character following the prefix is "-". The special range "*", if %% present in the Accept-Language field, matches every tag not matched %% by any other range present in the Accept-Language field. %% %% @todo The last sentence probably means we should always put '*' %% at the end of the list. prioritize_languages(AcceptLanguages) -> lists:sort( fun ({_TagA, QualityA}, {_TagB, QualityB}) -> QualityA > QualityB end, AcceptLanguages). choose_language(Req, State, []) -> not_acceptable(Req, State); choose_language(Req, State=#state{languages_p=LP}, [Language|Tail]) -> match_language(Req, State, Tail, LP, Language). match_language(Req, State, Accept, [], _Language) -> choose_language(Req, State, Accept); match_language(Req, State, _Accept, [Provided|_Tail], {'*', _Quality}) -> set_language(Req, State#state{language_a=Provided}); match_language(Req, State, _Accept, [Provided|_Tail], {Provided, _Quality}) -> set_language(Req, State#state{language_a=Provided}); match_language(Req, State, Accept, [Provided|Tail], Language = {Tag, _Quality}) -> Length = byte_size(Tag), case Provided of << Tag:Length/binary, $-, _Any/bits >> -> set_language(Req, State#state{language_a=Provided}); _Any -> match_language(Req, State, Accept, Tail, Language) end. set_language(Req=#http_req{meta=Meta}, State=#state{language_a=Language}) -> {ok, Req2} = cowboy_http_req:set_resp_header( <<"Content-Language">>, Language, Req), charsets_provided(Req2#http_req{meta=[{language, Language}|Meta]}, State). %% charsets_provided should return a list of binary values indicating %% which charsets are accepted by the resource. charsets_provided(Req, State) -> case call(Req, State, charsets_provided) of no_call -> set_content_type(Req, State); {halt, Req2, HandlerState} -> terminate(Req2, State#state{handler_state=HandlerState}); {[], Req2, HandlerState} -> not_acceptable(Req2, State#state{handler_state=HandlerState}); {CP, Req2, HandlerState} -> State2 = State#state{handler_state=HandlerState, charsets_p=CP}, {AcceptCharset, Req3} = cowboy_http_req:parse_header('Accept-Charset', Req2), case AcceptCharset of undefined -> set_content_type(Req3, State2#state{charset_a=hd(CP)}); AcceptCharset -> AcceptCharset2 = prioritize_charsets(AcceptCharset), choose_charset(Req3, State2, AcceptCharset2) end end. %% The special value "*", if present in the Accept-Charset field, %% matches every character set (including ISO-8859-1) which is not %% mentioned elsewhere in the Accept-Charset field. If no "*" is present %% in an Accept-Charset field, then all character sets not explicitly %% mentioned get a quality value of 0, except for ISO-8859-1, which gets %% a quality value of 1 if not explicitly mentioned. prioritize_charsets(AcceptCharsets) -> AcceptCharsets2 = lists:sort( fun ({_CharsetA, QualityA}, {_CharsetB, QualityB}) -> QualityA > QualityB end, AcceptCharsets), case lists:keymember(<<"*">>, 1, AcceptCharsets2) of true -> AcceptCharsets2; false -> [{<<"iso-8859-1">>, 1000}|AcceptCharsets2] end. choose_charset(Req, State, []) -> not_acceptable(Req, State); choose_charset(Req, State=#state{charsets_p=CP}, [Charset|Tail]) -> match_charset(Req, State, Tail, CP, Charset). match_charset(Req, State, Accept, [], _Charset) -> choose_charset(Req, State, Accept); match_charset(Req, State, _Accept, [Provided|_Tail], {Provided, _Quality}) -> set_content_type(Req, State#state{charset_a=Provided}); match_charset(Req, State, Accept, [_Provided|Tail], Charset) -> match_charset(Req, State, Accept, Tail, Charset). set_content_type(Req=#http_req{meta=Meta}, State=#state{ content_type_a={{Type, SubType, Params}, _Fun}, charset_a=Charset}) -> ParamsBin = set_content_type_build_params(Params, []), ContentType = [Type, <<"/">>, SubType, ParamsBin], ContentType2 = case Charset of undefined -> ContentType; Charset -> [ContentType, <<"; charset=">>, Charset] end, {ok, Req2} = cowboy_http_req:set_resp_header( <<"Content-Type">>, ContentType2, Req), encodings_provided(Req2#http_req{meta=[{charset, Charset}|Meta]}, State). set_content_type_build_params([], []) -> <<>>; set_content_type_build_params([], Acc) -> lists:reverse(Acc); set_content_type_build_params([{Attr, Value}|Tail], Acc) -> set_content_type_build_params(Tail, [[Attr, <<"=">>, Value], <<";">>|Acc]). %% @todo Match for identity as we provide nothing else for now. %% @todo Don't forget to set the Content-Encoding header when we reply a body %% and the found encoding is something other than identity. encodings_provided(Req, State) -> variances(Req, State). not_acceptable(Req, State) -> respond(Req, State, 406). %% variances/2 should return a list of headers that will be added %% to the Vary response header. The Accept, Accept-Language, %% Accept-Charset and Accept-Encoding headers do not need to be %% specified. %% %% @todo Do Accept-Encoding too when we handle it. %% @todo Does the order matter? variances(Req, State=#state{content_types_p=CTP, languages_p=LP, charsets_p=CP}) -> Variances = case CTP of [] -> []; [_] -> []; [_|_] -> [<<"Accept">>] end, Variances2 = case LP of [] -> Variances; [_] -> Variances; [_|_] -> [<<"Accept-Language">>|Variances] end, Variances3 = case CP of [] -> Variances2; [_] -> Variances2; [_|_] -> [<<"Accept-Charset">>|Variances2] end, {Variances4, Req3, State2} = case call(Req, State, variances) of no_call -> {Variances3, Req, State}; {HandlerVariances, Req2, HandlerState} -> {Variances3 ++ HandlerVariances, Req2, State#state{handler_state=HandlerState}} end, case [[<<", ">>, V] || V <- Variances4] of [] -> resource_exists(Req3, State2); [[<<", ">>, H]|Variances5] -> {ok, Req4} = cowboy_http_req:set_resp_header( <<"Variances">>, [H|Variances5], Req3), resource_exists(Req4, State2) end. resource_exists(Req, State) -> expect(Req, State, resource_exists, true, fun if_match_exists/2, fun if_match_musnt_exist/2). if_match_exists(Req, State) -> case cowboy_http_req:parse_header('If-Match', Req) of {undefined, Req2} -> if_unmodified_since_exists(Req2, State); {'*', Req2} -> if_unmodified_since_exists(Req2, State); {ETagsList, Req2} -> if_match(Req2, State, ETagsList) end. if_match(Req, State, EtagsList) -> {Etag, Req2, State2} = generate_etag(Req, State), case Etag of no_call -> precondition_failed(Req2, State2); Etag -> case lists:member(Etag, EtagsList) of true -> if_unmodified_since_exists(Req2, State2); false -> precondition_failed(Req2, State2) end end. if_match_musnt_exist(Req, State) -> case cowboy_http_req:header('If-Match', Req) of {undefined, Req2} -> is_put_to_missing_resource(Req2, State); {_Any, Req2} -> precondition_failed(Req2, State) end. if_unmodified_since_exists(Req, State) -> case cowboy_http_req:parse_header('If-Unmodified-Since', Req) of {undefined, Req2} -> if_none_match_exists(Req2, State); {{error, badarg}, Req2} -> if_none_match_exists(Req2, State); {IfUnmodifiedSince, Req2} -> if_unmodified_since(Req2, State, IfUnmodifiedSince) end. %% If LastModified is the atom 'no_call', we continue. if_unmodified_since(Req, State, IfUnmodifiedSince) -> {LastModified, Req2, State2} = last_modified(Req, State), case LastModified > IfUnmodifiedSince of true -> precondition_failed(Req2, State2); false -> if_none_match_exists(Req2, State2) end. if_none_match_exists(Req, State) -> case cowboy_http_req:parse_header('If-None-Match', Req) of {undefined, Req2} -> if_modified_since_exists(Req2, State); {'*', Req2} -> precondition_is_head_get(Req2, State); {EtagsList, Req2} -> if_none_match(Req2, State, EtagsList) end. if_none_match(Req, State, EtagsList) -> {Etag, Req2, State2} = generate_etag(Req, State), case Etag of no_call -> precondition_failed(Req2, State2); Etag -> case lists:member(Etag, EtagsList) of true -> precondition_is_head_get(Req2, State2); false -> if_modified_since_exists(Req2, State2) end end. precondition_is_head_get(Req=#http_req{method=Method}, State) when Method =:= 'HEAD'; Method =:= 'GET' -> not_modified(Req, State); precondition_is_head_get(Req, State) -> precondition_failed(Req, State). if_modified_since_exists(Req, State) -> case cowboy_http_req:parse_header('If-Modified-Since', Req) of {undefined, Req2} -> method(Req2, State); {{error, badarg}, Req2} -> method(Req2, State); {IfModifiedSince, Req2} -> if_modified_since_now(Req2, State, IfModifiedSince) end. if_modified_since_now(Req, State, IfModifiedSince) -> case IfModifiedSince > erlang:universaltime() of true -> method(Req, State); false -> if_modified_since(Req, State, IfModifiedSince) end. if_modified_since(Req, State, IfModifiedSince) -> {LastModified, Req2, State2} = last_modified(Req, State), case LastModified of no_call -> method(Req2, State2); LastModified -> case LastModified > IfModifiedSince of true -> method(Req2, State2); false -> not_modified(Req2, State2) end end. not_modified(Req=#http_req{resp_headers=RespHeaders}, State) -> RespHeaders2 = lists:keydelete(<<"Content-Type">>, 1, RespHeaders), Req2 = Req#http_req{resp_headers=RespHeaders2}, {Req3, State2} = set_resp_etag(Req2, State), {Req4, State3} = set_resp_expires(Req3, State2), respond(Req4, State3, 304). precondition_failed(Req, State) -> respond(Req, State, 412). is_put_to_missing_resource(Req=#http_req{method='PUT'}, State) -> moved_permanently(Req, State, fun is_conflict/2); is_put_to_missing_resource(Req, State) -> previously_existed(Req, State). %% moved_permanently/2 should return either false or {true, Location} %% with Location the full new URI of the resource. moved_permanently(Req, State, OnFalse) -> case call(Req, State, moved_permanently) of {{true, Location}, Req2, HandlerState} -> {ok, Req3} = cowboy_http_req:set_resp_header( <<"Location">>, Location, Req2), respond(Req3, State#state{handler_state=HandlerState}, 301); {false, Req2, HandlerState} -> OnFalse(Req2, State#state{handler_state=HandlerState}); {halt, Req2, HandlerState} -> terminate(Req2, State#state{handler_state=HandlerState}); no_call -> OnFalse(Req, State) end. previously_existed(Req, State) -> expect(Req, State, previously_existed, false, fun (R, S) -> is_post_to_missing_resource(R, S, 404) end, fun (R, S) -> moved_permanently(R, S, fun moved_temporarily/2) end). %% moved_temporarily/2 should return either false or {true, Location} %% with Location the full new URI of the resource. moved_temporarily(Req, State) -> case call(Req, State, moved_temporarily) of {{true, Location}, Req2, HandlerState} -> {ok, Req3} = cowboy_http_req:set_resp_header( <<"Location">>, Location, Req2), respond(Req3, State#state{handler_state=HandlerState}, 307); {false, Req2, HandlerState} -> is_post_to_missing_resource(Req2, State#state{handler_state=HandlerState}, 410); {halt, Req2, HandlerState} -> terminate(Req2, State#state{handler_state=HandlerState}); no_call -> is_post_to_missing_resource(Req, State, 410) end. is_post_to_missing_resource(Req=#http_req{method='POST'}, State, OnFalse) -> allow_missing_post(Req, State, OnFalse); is_post_to_missing_resource(Req, State, OnFalse) -> respond(Req, State, OnFalse). allow_missing_post(Req, State, OnFalse) -> expect(Req, State, allow_missing_post, true, fun post_is_create/2, OnFalse). method(Req=#http_req{method='DELETE'}, State) -> delete_resource(Req, State); method(Req=#http_req{method='POST'}, State) -> post_is_create(Req, State); method(Req=#http_req{method='PUT'}, State) -> is_conflict(Req, State); method(Req, State) -> set_resp_body(Req, State). %% delete_resource/2 should start deleting the resource and return. delete_resource(Req, State) -> expect(Req, State, delete_resource, true, fun delete_completed/2, 500). %% delete_completed/2 indicates whether the resource has been deleted yet. delete_completed(Req, State) -> expect(Req, State, delete_completed, true, fun has_resp_body/2, 202). %% post_is_create/2 indicates whether the POST method can create new resources. post_is_create(Req, State) -> expect(Req, State, post_is_create, false, fun process_post/2, fun create_path/2). %% When the POST method can create new resources, create_path/2 will be called %% and is expected to return the full path to the new resource %% (including the leading /). create_path(Req=#http_req{meta=Meta}, State) -> case call(Req, State, create_path) of {halt, Req2, HandlerState} -> terminate(Req2, State#state{handler_state=HandlerState}); {Path, Req2, HandlerState} -> Location = create_path_location(Req2, Path), State2 = State#state{handler_state=HandlerState}, {ok, Req3} = cowboy_http_req:set_resp_header( <<"Location">>, Location, Req2), put_resource(Req3#http_req{meta=[{put_path, Path}|Meta]}, State2, 303) end. create_path_location(#http_req{transport=Transport, raw_host=Host, port=Port}, Path) -> TransportName = Transport:name(), << (create_path_location_protocol(TransportName))/binary, "://", Host/binary, (create_path_location_port(TransportName, Port))/binary, Path/binary >>. create_path_location_protocol(ssl) -> <<"https">>; create_path_location_protocol(_) -> <<"http">>. create_path_location_port(ssl, 443) -> <<>>; create_path_location_port(tcp, 80) -> <<>>; create_path_location_port(_, Port) -> <<":", (list_to_binary(integer_to_list(Port)))/binary>>. %% process_post should return true when the POST body could be processed %% and false when it hasn't, in which case a 500 error is sent. process_post(Req, State) -> case call(Req, State, process_post) of {halt, Req2, HandlerState} -> terminate(Req2, State#state{handler_state=HandlerState}); {true, Req2, HandlerState} -> State2 = State#state{handler_state=HandlerState}, next(Req2, State2, 201); {false, Req2, HandlerState} -> State2 = State#state{handler_state=HandlerState}, respond(Req2, State2, 500) end. is_conflict(Req, State) -> expect(Req, State, is_conflict, false, fun put_resource/2, 409). put_resource(Req=#http_req{raw_path=RawPath, meta=Meta}, State) -> Req2 = Req#http_req{meta=[{put_path, RawPath}|Meta]}, put_resource(Req2, State, fun is_new_resource/2). %% content_types_accepted should return a list of media types and their %% associated callback functions in the same format as content_types_provided. %% %% The callback will then be called and is expected to process the content %% pushed to the resource in the request body. The path to the new resource %% may be different from the request path, and is stored as request metadata. %% It is always defined past this point. It can be retrieved as demonstrated: %% {PutPath, Req2} = cowboy_http_req:meta(put_path, Req) put_resource(Req, State, OnTrue) -> case call(Req, State, content_types_accepted) of no_call -> respond(Req, State, 415); {halt, Req2, HandlerState} -> terminate(Req2, State#state{handler_state=HandlerState}); {CTA, Req2, HandlerState} -> State2 = State#state{handler_state=HandlerState}, {ContentType, Req3} = cowboy_http_req:parse_header('Content-Type', Req2), choose_content_type(Req3, State2, OnTrue, ContentType, CTA) end. choose_content_type(Req, State, _OnTrue, _ContentType, []) -> respond(Req, State, 415); choose_content_type(Req, State, OnTrue, ContentType, [{Accepted, Fun}|_Tail]) when ContentType =:= Accepted -> case call(Req, State, Fun) of {halt, Req2, HandlerState} -> terminate(Req2, State#state{handler_state=HandlerState}); {true, Req2, HandlerState} -> State2 = State#state{handler_state=HandlerState}, next(Req2, State2, OnTrue); {false, Req2, HandlerState} -> State2 = State#state{handler_state=HandlerState}, respond(Req2, State2, 500) end; choose_content_type(Req, State, OnTrue, ContentType, [_Any|Tail]) -> choose_content_type(Req, State, OnTrue, ContentType, Tail). %% Whether we created a new resource, either through PUT or POST. %% This is easily testable because we would have set the Location %% header by this point if we did so. is_new_resource(Req, State) -> case cowboy_http_req:has_resp_header(<<"Location">>, Req) of true -> respond(Req, State, 201); false -> has_resp_body(Req, State) end. has_resp_body(Req, State) -> case cowboy_http_req:has_resp_body(Req) of true -> multiple_choices(Req, State); false -> respond(Req, State, 204) end. %% Set the response headers and call the callback found using %% content_types_provided/2 to obtain the request body and add %% it to the response. set_resp_body(Req=#http_req{method=Method}, State=#state{content_type_a={_Type, Fun}}) when Method =:= 'GET'; Method =:= 'HEAD' -> {Req2, State2} = set_resp_etag(Req, State), {LastModified, Req3, State3} = last_modified(Req2, State2), case LastModified of LastModified when is_atom(LastModified) -> Req4 = Req3; LastModified -> LastModifiedStr = httpd_util:rfc1123_date(LastModified), {ok, Req4} = cowboy_http_req:set_resp_header( <<"Last-Modified">>, LastModifiedStr, Req3) end, {Req5, State4} = set_resp_expires(Req4, State3), case call(Req5, State4, Fun) of {halt, Req6, HandlerState} -> terminate(Req6, State4#state{handler_state=HandlerState}); {Body, Req6, HandlerState} -> State5 = State4#state{handler_state=HandlerState}, {ok, Req7} = case Body of {stream, Len, Fun1} -> cowboy_http_req:set_resp_body_fun(Len, Fun1, Req6); _Contents -> cowboy_http_req:set_resp_body(Body, Req6) end, multiple_choices(Req7, State5) end; set_resp_body(Req, State) -> multiple_choices(Req, State). multiple_choices(Req, State) -> expect(Req, State, multiple_choices, false, 200, 300). %% Response utility functions. set_resp_etag(Req, State) -> {Etag, Req2, State2} = generate_etag(Req, State), case Etag of undefined -> {Req2, State2}; Etag -> {ok, Req3} = cowboy_http_req:set_resp_header( <<"Etag">>, Etag, Req2), {Req3, State2} end. set_resp_expires(Req, State) -> {Expires, Req2, State2} = expires(Req, State), case Expires of Expires when is_atom(Expires) -> {Req2, State2}; Expires -> ExpiresStr = httpd_util:rfc1123_date(Expires), {ok, Req3} = cowboy_http_req:set_resp_header( <<"Expires">>, ExpiresStr, Req2), {Req3, State2} end. %% Info retrieval. No logic. generate_etag(Req, State=#state{etag=no_call}) -> {undefined, Req, State}; generate_etag(Req, State=#state{etag=undefined}) -> case call(Req, State, generate_etag) of no_call -> {undefined, Req, State#state{etag=no_call}}; {Etag, Req2, HandlerState} -> {Etag, Req2, State#state{handler_state=HandlerState, etag=Etag}} end; generate_etag(Req, State=#state{etag=Etag}) -> {Etag, Req, State}. last_modified(Req, State=#state{last_modified=no_call}) -> {undefined, Req, State}; last_modified(Req, State=#state{last_modified=undefined}) -> case call(Req, State, last_modified) of no_call -> {undefined, Req, State#state{last_modified=no_call}}; {LastModified, Req2, HandlerState} -> {LastModified, Req2, State#state{handler_state=HandlerState, last_modified=LastModified}} end; last_modified(Req, State=#state{last_modified=LastModified}) -> {LastModified, Req, State}. expires(Req, State=#state{expires=no_call}) -> {undefined, Req, State}; expires(Req, State=#state{expires=undefined}) -> case call(Req, State, expires) of no_call -> {undefined, Req, State#state{expires=no_call}}; {Expires, Req2, HandlerState} -> {Expires, Req2, State#state{handler_state=HandlerState, expires=Expires}} end; expires(Req, State=#state{expires=Expires}) -> {Expires, Req, State}. %% REST primitives. expect(Req, State, Callback, Expected, OnTrue, OnFalse) -> case call(Req, State, Callback) of no_call -> next(Req, State, OnTrue); {halt, Req2, HandlerState} -> terminate(Req2, State#state{handler_state=HandlerState}); {Expected, Req2, HandlerState} -> next(Req2, State#state{handler_state=HandlerState}, OnTrue); {_Unexpected, Req2, HandlerState} -> next(Req2, State#state{handler_state=HandlerState}, OnFalse) end. call(Req, #state{handler=Handler, handler_state=HandlerState}, Fun) -> case erlang:function_exported(Handler, Fun, 2) of true -> Handler:Fun(Req, HandlerState); false -> no_call end. next(Req, State, Next) when is_function(Next) -> Next(Req, State); next(Req, State, StatusCode) when is_integer(StatusCode) -> respond(Req, State, StatusCode). %% @todo Allow some sort of callback for custom error pages. respond(Req, State, StatusCode) -> {ok, Req2} = cowboy_http_req:reply(StatusCode, Req), terminate(Req2, State). terminate(Req, #state{handler=Handler, handler_state=HandlerState}) -> case erlang:function_exported(Handler, rest_terminate, 2) of true -> ok = Handler:rest_terminate( Req#http_req{resp_state=locked}, HandlerState); false -> ok end, {ok, Req}. rabbitmq-server-3.2.4/plugins-src/cowboy-wrapper/cowboy-git/src/cowboy_clock.erl0000644000000000000000000002076212305126066026614 0ustar rootroot%% Copyright (c) 2011, Loïc Hoguin %% %% Permission to use, copy, modify, and/or distribute this software for any %% purpose with or without fee is hereby granted, provided that the above %% copyright notice and this permission notice appear in all copies. %% %% THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES %% WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF %% MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR %% ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES %% WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN %% ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF %% OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. %% @doc Date and time related functions. %% %% While a gen_server process runs in the background to update %% the cache of formatted dates every second, all API calls are %% local and directly read from the ETS cache table, providing %% fast time and date computations. -module(cowboy_clock). -behaviour(gen_server). -export([start_link/0, stop/0, rfc1123/0, rfc2109/1]). %% API. -export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]). %% gen_server. -record(state, { universaltime = undefined :: undefined | calendar:datetime(), rfc1123 = <<>> :: binary(), tref = undefined :: undefined | timer:tref() }). -define(SERVER, ?MODULE). -define(TABLE, ?MODULE). -include_lib("eunit/include/eunit.hrl"). %% API. %% @private -spec start_link() -> {ok, pid()}. start_link() -> gen_server:start_link({local, ?SERVER}, ?MODULE, [], []). %% @private -spec stop() -> stopped. stop() -> gen_server:call(?SERVER, stop). %% @doc Return the current date and time formatted according to RFC-1123. %% %% This format is used in the 'Date' header sent with HTTP responses. -spec rfc1123() -> binary(). rfc1123() -> ets:lookup_element(?TABLE, rfc1123, 2). %% @doc Return the current date and time formatted according to RFC-2109. %% %% This format is used in the 'Set-Cookie' header sent with %% HTTP responses. -spec rfc2109(calendar:datetime()) -> binary(). rfc2109(LocalTime) -> {{YYYY,MM,DD},{Hour,Min,Sec}} = case calendar:local_time_to_universal_time_dst(LocalTime) of [Gmt] -> Gmt; [_,Gmt] -> Gmt end, Wday = calendar:day_of_the_week({YYYY,MM,DD}), DayBin = pad_int(DD), YearBin = list_to_binary(integer_to_list(YYYY)), HourBin = pad_int(Hour), MinBin = pad_int(Min), SecBin = pad_int(Sec), WeekDay = weekday(Wday), Month = month(MM), <>. %% gen_server. %% @private -spec init([]) -> {ok, #state{}}. init([]) -> ?TABLE = ets:new(?TABLE, [set, protected, named_table, {read_concurrency, true}]), T = erlang:universaltime(), B = update_rfc1123(<<>>, undefined, T), {ok, TRef} = timer:send_interval(1000, update), ets:insert(?TABLE, {rfc1123, B}), {ok, #state{universaltime=T, rfc1123=B, tref=TRef}}. %% @private -spec handle_call(_, _, State) -> {reply, ignored, State} | {stop, normal, stopped, State}. handle_call(stop, _From, State=#state{tref=TRef}) -> {ok, cancel} = timer:cancel(TRef), {stop, normal, stopped, State}; handle_call(_Request, _From, State) -> {reply, ignored, State}. %% @private -spec handle_cast(_, State) -> {noreply, State}. handle_cast(_Msg, State) -> {noreply, State}. %% @private -spec handle_info(_, State) -> {noreply, State}. handle_info(update, #state{universaltime=Prev, rfc1123=B1, tref=TRef}) -> T = erlang:universaltime(), B2 = update_rfc1123(B1, Prev, T), ets:insert(?TABLE, {rfc1123, B2}), {noreply, #state{universaltime=T, rfc1123=B2, tref=TRef}}; handle_info(_Info, State) -> {noreply, State}. %% @private -spec terminate(_, _) -> ok. terminate(_Reason, _State) -> ok. %% @private -spec code_change(_, State, _) -> {ok, State}. code_change(_OldVsn, State, _Extra) -> {ok, State}. %% Internal. -spec update_rfc1123(binary(), undefined | calendar:datetime(), calendar:datetime()) -> binary(). update_rfc1123(Bin, Now, Now) -> Bin; update_rfc1123(<< Keep:23/binary, _/bits >>, {Date, {H, M, _}}, {Date, {H, M, S}}) -> << Keep/binary, (pad_int(S))/binary, " GMT" >>; update_rfc1123(<< Keep:20/binary, _/bits >>, {Date, {H, _, _}}, {Date, {H, M, S}}) -> << Keep/binary, (pad_int(M))/binary, $:, (pad_int(S))/binary, " GMT" >>; update_rfc1123(<< Keep:17/binary, _/bits >>, {Date, _}, {Date, {H, M, S}}) -> << Keep/binary, (pad_int(H))/binary, $:, (pad_int(M))/binary, $:, (pad_int(S))/binary, " GMT" >>; update_rfc1123(<< _:7/binary, Keep:10/binary, _/bits >>, {{Y, Mo, _}, _}, {Date = {Y, Mo, D}, {H, M, S}}) -> Wday = calendar:day_of_the_week(Date), << (weekday(Wday))/binary, ", ", (pad_int(D))/binary, Keep/binary, (pad_int(H))/binary, $:, (pad_int(M))/binary, $:, (pad_int(S))/binary, " GMT" >>; update_rfc1123(<< _:11/binary, Keep:6/binary, _/bits >>, {{Y, _, _}, _}, {Date = {Y, Mo, D}, {H, M, S}}) -> Wday = calendar:day_of_the_week(Date), << (weekday(Wday))/binary, ", ", (pad_int(D))/binary, " ", (month(Mo))/binary, Keep/binary, (pad_int(H))/binary, $:, (pad_int(M))/binary, $:, (pad_int(S))/binary, " GMT" >>; update_rfc1123(_, _, {Date = {Y, Mo, D}, {H, M, S}}) -> Wday = calendar:day_of_the_week(Date), << (weekday(Wday))/binary, ", ", (pad_int(D))/binary, " ", (month(Mo))/binary, " ", (list_to_binary(integer_to_list(Y)))/binary, " ", (pad_int(H))/binary, $:, (pad_int(M))/binary, $:, (pad_int(S))/binary, " GMT" >>. %% Following suggestion by MononcQc on #erlounge. -spec pad_int(0..59) -> binary(). pad_int(X) when X < 10 -> << $0, ($0 + X) >>; pad_int(X) -> list_to_binary(integer_to_list(X)). -spec weekday(1..7) -> <<_:24>>. weekday(1) -> <<"Mon">>; weekday(2) -> <<"Tue">>; weekday(3) -> <<"Wed">>; weekday(4) -> <<"Thu">>; weekday(5) -> <<"Fri">>; weekday(6) -> <<"Sat">>; weekday(7) -> <<"Sun">>. -spec month(1..12) -> <<_:24>>. month( 1) -> <<"Jan">>; month( 2) -> <<"Feb">>; month( 3) -> <<"Mar">>; month( 4) -> <<"Apr">>; month( 5) -> <<"May">>; month( 6) -> <<"Jun">>; month( 7) -> <<"Jul">>; month( 8) -> <<"Aug">>; month( 9) -> <<"Sep">>; month(10) -> <<"Oct">>; month(11) -> <<"Nov">>; month(12) -> <<"Dec">>. %% Tests. -ifdef(TEST). update_rfc1123_test_() -> Tests = [ {<<"Sat, 14 May 2011 14:25:33 GMT">>, undefined, {{2011, 5, 14}, {14, 25, 33}}, <<>>}, {<<"Sat, 14 May 2011 14:25:33 GMT">>, {{2011, 5, 14}, {14, 25, 33}}, {{2011, 5, 14}, {14, 25, 33}}, <<"Sat, 14 May 2011 14:25:33 GMT">>}, {<<"Sat, 14 May 2011 14:25:34 GMT">>, {{2011, 5, 14}, {14, 25, 33}}, {{2011, 5, 14}, {14, 25, 34}}, <<"Sat, 14 May 2011 14:25:33 GMT">>}, {<<"Sat, 14 May 2011 14:26:00 GMT">>, {{2011, 5, 14}, {14, 25, 59}}, {{2011, 5, 14}, {14, 26, 0}}, <<"Sat, 14 May 2011 14:25:59 GMT">>}, {<<"Sat, 14 May 2011 15:00:00 GMT">>, {{2011, 5, 14}, {14, 59, 59}}, {{2011, 5, 14}, {15, 0, 0}}, <<"Sat, 14 May 2011 14:59:59 GMT">>}, {<<"Sun, 15 May 2011 00:00:00 GMT">>, {{2011, 5, 14}, {23, 59, 59}}, {{2011, 5, 15}, { 0, 0, 0}}, <<"Sat, 14 May 2011 23:59:59 GMT">>}, {<<"Wed, 01 Jun 2011 00:00:00 GMT">>, {{2011, 5, 31}, {23, 59, 59}}, {{2011, 6, 1}, { 0, 0, 0}}, <<"Tue, 31 May 2011 23:59:59 GMT">>}, {<<"Sun, 01 Jan 2012 00:00:00 GMT">>, {{2011, 5, 31}, {23, 59, 59}}, {{2012, 1, 1}, { 0, 0, 0}}, <<"Sat, 31 Dec 2011 23:59:59 GMT">>} ], [{R, fun() -> R = update_rfc1123(B, P, N) end} || {R, P, N, B} <- Tests]. pad_int_test_() -> Tests = [ { 0, <<"00">>}, { 1, <<"01">>}, { 2, <<"02">>}, { 3, <<"03">>}, { 4, <<"04">>}, { 5, <<"05">>}, { 6, <<"06">>}, { 7, <<"07">>}, { 8, <<"08">>}, { 9, <<"09">>}, {10, <<"10">>}, {11, <<"11">>}, {12, <<"12">>}, {13, <<"13">>}, {14, <<"14">>}, {15, <<"15">>}, {16, <<"16">>}, {17, <<"17">>}, {18, <<"18">>}, {19, <<"19">>}, {20, <<"20">>}, {21, <<"21">>}, {22, <<"22">>}, {23, <<"23">>}, {24, <<"24">>}, {25, <<"25">>}, {26, <<"26">>}, {27, <<"27">>}, {28, <<"28">>}, {29, <<"29">>}, {30, <<"30">>}, {31, <<"31">>}, {32, <<"32">>}, {33, <<"33">>}, {34, <<"34">>}, {35, <<"35">>}, {36, <<"36">>}, {37, <<"37">>}, {38, <<"38">>}, {39, <<"39">>}, {40, <<"40">>}, {41, <<"41">>}, {42, <<"42">>}, {43, <<"43">>}, {44, <<"44">>}, {45, <<"45">>}, {46, <<"46">>}, {47, <<"47">>}, {48, <<"48">>}, {49, <<"49">>}, {50, <<"50">>}, {51, <<"51">>}, {52, <<"52">>}, {53, <<"53">>}, {54, <<"54">>}, {55, <<"55">>}, {56, <<"56">>}, {57, <<"57">>}, {58, <<"58">>}, {59, <<"59">>} ], [{I, fun() -> O = pad_int(I) end} || {I, O} <- Tests]. -endif. rabbitmq-server-3.2.4/plugins-src/cowboy-wrapper/cowboy-git/src/cowboy_requests_sup.erl0000644000000000000000000000271712305126066030263 0ustar rootroot%% Copyright (c) 2011, Loïc Hoguin %% %% Permission to use, copy, modify, and/or distribute this software for any %% purpose with or without fee is hereby granted, provided that the above %% copyright notice and this permission notice appear in all copies. %% %% THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES %% WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF %% MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR %% ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES %% WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN %% ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF %% OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. %% @private -module(cowboy_requests_sup). -behaviour(supervisor). -export([start_link/0, start_request/5]). %% API. -export([init/1]). %% supervisor. %% API. -spec start_link() -> {ok, pid()}. start_link() -> supervisor:start_link(?MODULE, []). -spec start_request(pid(), inet:socket(), module(), module(), any()) -> {ok, pid()}. start_request(ListenerPid, Socket, Transport, Protocol, Opts) -> Protocol:start_link(ListenerPid, Socket, Transport, Opts). %% supervisor. -spec init([]) -> {ok, {{simple_one_for_one, 0, 1}, [{_, _, _, _, _, _}, ...]}}. init([]) -> {ok, {{simple_one_for_one, 0, 1}, [{?MODULE, {?MODULE, start_request, []}, temporary, brutal_kill, worker, [?MODULE]}]}}. rabbitmq-server-3.2.4/plugins-src/cowboy-wrapper/cowboy-git/src/cowboy_acceptors_sup.erl0000644000000000000000000000340412305126066030365 0ustar rootroot%% Copyright (c) 2011, Loïc Hoguin %% %% Permission to use, copy, modify, and/or distribute this software for any %% purpose with or without fee is hereby granted, provided that the above %% copyright notice and this permission notice appear in all copies. %% %% THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES %% WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF %% MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR %% ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES %% WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN %% ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF %% OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. %% @private -module(cowboy_acceptors_sup). -behaviour(supervisor). -export([start_link/7]). %% API. -export([init/1]). %% supervisor. %% API. -spec start_link(non_neg_integer(), module(), any(), module(), any(), pid(), pid()) -> {ok, pid()}. start_link(NbAcceptors, Transport, TransOpts, Protocol, ProtoOpts, ListenerPid, ReqsPid) -> supervisor:start_link(?MODULE, [NbAcceptors, Transport, TransOpts, Protocol, ProtoOpts, ListenerPid, ReqsPid]). %% supervisor. -spec init(list()) -> {ok, {{one_for_one, 10, 10}, list()}}. init([NbAcceptors, Transport, TransOpts, Protocol, ProtoOpts, ListenerPid, ReqsPid]) -> {ok, LSocket} = Transport:listen(TransOpts), MaxConns = proplists:get_value(max_connections, TransOpts, 1024), Procs = [{{acceptor, self(), N}, {cowboy_acceptor, start_link, [ LSocket, Transport, Protocol, ProtoOpts, MaxConns, ListenerPid, ReqsPid ]}, permanent, brutal_kill, worker, []} || N <- lists:seq(1, NbAcceptors)], {ok, {{one_for_one, 10, 10}, Procs}}. rabbitmq-server-3.2.4/plugins-src/cowboy-wrapper/cowboy-git/src/cowboy_acceptor.erl0000644000000000000000000000443512305126066027320 0ustar rootroot%% Copyright (c) 2011, Loïc Hoguin %% %% Permission to use, copy, modify, and/or distribute this software for any %% purpose with or without fee is hereby granted, provided that the above %% copyright notice and this permission notice appear in all copies. %% %% THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES %% WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF %% MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR %% ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES %% WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN %% ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF %% OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. %% @private -module(cowboy_acceptor). -export([start_link/7]). %% API. -export([acceptor/7]). %% Internal. %% API. -spec start_link(inet:socket(), module(), module(), any(), non_neg_integer(), pid(), pid()) -> {ok, pid()}. start_link(LSocket, Transport, Protocol, Opts, MaxConns, ListenerPid, ReqsSup) -> Pid = spawn_link(?MODULE, acceptor, [LSocket, Transport, Protocol, Opts, MaxConns, ListenerPid, ReqsSup]), {ok, Pid}. %% Internal. -spec acceptor(inet:socket(), module(), module(), any(), non_neg_integer(), pid(), pid()) -> no_return(). acceptor(LSocket, Transport, Protocol, Opts, MaxConns, ListenerPid, ReqsSup) -> case Transport:accept(LSocket, 2000) of {ok, CSocket} -> {ok, Pid} = supervisor:start_child(ReqsSup, [ListenerPid, CSocket, Transport, Protocol, Opts]), Transport:controlling_process(CSocket, Pid), {ok, NbConns} = cowboy_listener:add_connection(ListenerPid, default, Pid), Pid ! {shoot, ListenerPid}, limit_reqs(ListenerPid, NbConns, MaxConns); {error, timeout} -> ignore; {error, _Reason} -> %% @todo Probably do something here. If the socket was closed, %% we may want to try and listen again on the port? ignore end, ?MODULE:acceptor(LSocket, Transport, Protocol, Opts, MaxConns, ListenerPid, ReqsSup). -spec limit_reqs(pid(), non_neg_integer(), non_neg_integer()) -> ok. limit_reqs(_ListenerPid, NbConns, MaxConns) when NbConns =< MaxConns -> ok; limit_reqs(ListenerPid, _NbConns, MaxConns) -> cowboy_listener:wait(ListenerPid, default, MaxConns). rabbitmq-server-3.2.4/plugins-src/cowboy-wrapper/cowboy-git/src/cowboy_listener_sup.erl0000644000000000000000000000350012305126066030224 0ustar rootroot%% Copyright (c) 2011, Loïc Hoguin %% %% Permission to use, copy, modify, and/or distribute this software for any %% purpose with or without fee is hereby granted, provided that the above %% copyright notice and this permission notice appear in all copies. %% %% THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES %% WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF %% MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR %% ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES %% WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN %% ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF %% OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. %% @private -module(cowboy_listener_sup). -behaviour(supervisor). -export([start_link/5]). %% API. -export([init/1]). %% supervisor. %% API. -spec start_link(non_neg_integer(), module(), any(), module(), any()) -> {ok, pid()}. start_link(NbAcceptors, Transport, TransOpts, Protocol, ProtoOpts) -> {ok, SupPid} = supervisor:start_link(?MODULE, []), {ok, ListenerPid} = supervisor:start_child(SupPid, {cowboy_listener, {cowboy_listener, start_link, []}, permanent, 5000, worker, [cowboy_listener]}), {ok, ReqsPid} = supervisor:start_child(SupPid, {cowboy_requests_sup, {cowboy_requests_sup, start_link, []}, permanent, 5000, supervisor, [cowboy_requests_sup]}), {ok, _PoolPid} = supervisor:start_child(SupPid, {cowboy_acceptors_sup, {cowboy_acceptors_sup, start_link, [ NbAcceptors, Transport, TransOpts, Protocol, ProtoOpts, ListenerPid, ReqsPid ]}, permanent, 5000, supervisor, [cowboy_acceptors_sup]}), {ok, SupPid}. %% supervisor. -spec init([]) -> {ok, {{one_for_all, 10, 10}, []}}. init([]) -> {ok, {{one_for_all, 10, 10}, []}}. rabbitmq-server-3.2.4/plugins-src/cowboy-wrapper/cowboy-git/src/cowboy_http_static.erl0000644000000000000000000004231612305126066030046 0ustar rootroot%% Copyright (c) 2011, Magnus Klaar %% %% Permission to use, copy, modify, and/or distribute this software for any %% purpose with or without fee is hereby granted, provided that the above %% copyright notice and this permission notice appear in all copies. %% %% THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES %% WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF %% MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR %% ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES %% WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN %% ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF %% OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. %% @doc Static resource handler. %% %% This built in HTTP handler provides a simple file serving capability for %% cowboy applications. It should be considered an experimental feature because %% of it's dependency on the experimental REST handler. It's recommended to be %% used for small or temporary environments where it is not preferrable to set %% up a second server just to serve files. %% %% If this handler is used the Erlang node running the cowboy application must %% be configured to use an async thread pool. This is configured by adding the %% `+A $POOL_SIZE' argument to the `erl' command used to start the node. See %% %% this reply from the OTP team to erlang-bugs %% %% == Base configuration == %% %% The handler must be configured with a request path prefix to serve files %% under and the path to a directory to read files from. The request path prefix %% is defined in the path pattern of the cowboy dispatch rule for the handler. %% The request path pattern must end with a ``'...''' token. %% The directory path can be set to either an absolute or relative path in the %% form of a list or binary string representation of a file system path. A list %% of binary path segments, as is used throughout cowboy, is also a valid %% directory path. %% %% The directory path can also be set to a relative path within the `priv/' %% directory of an application. This is configured by setting the value of the %% directory option to a tuple of the form `{priv_dir, Application, Relpath}'. %% %% ==== Examples ==== %% ``` %% %% Serve files from /var/www/ under http://example.com/static/ %% {[<<"static">>, '...'], cowboy_http_static, %% [{directory, "/var/www"}]} %% %% %% Serve files from the current working directory under http://example.com/static/ %% {[<<"static">>, '...'], cowboy_http_static, %% [{directory, <<"./">>}]} %% %% %% Serve files from cowboy/priv/www under http://example.com/ %% {['...'], cowboy_http_static, %% [{directory, {priv_dir, cowboy, [<<"www">>]}}]} %% ''' %% %% == Content type configuration == %% %% By default the content type of all static resources will be set to %% `application/octet-stream'. This can be overriden by supplying a list %% of filename extension to mimetypes pairs in the `mimetypes' option. %% The filename extension should be a binary string including the leading dot. %% The mimetypes must be of a type that the `cowboy_http_rest' protocol can %% handle. %% %% The spawngrid/mimetypes %% application, or an arbitrary function accepting the path to the file being %% served, can also be used to generate the list of content types for a static %% file resource. The function used must accept an additional argument after %% the file path argument. %% %% ==== Example ==== %% ``` %% %% Use a static list of content types. %% {[<<"static">>, '...'], cowboy_http_static, %% [{directory, {priv_dir, cowboy, []}}, %% {mimetypes, [ %% {<<".css">>, [<<"text/css">>]}, %% {<<".js">>, [<<"application/javascript">>]}]}]} %% %% %% Use the default database in the mimetypes application. %% {[<<"static">>, '...', cowboy_http_static, %% [{directory, {priv_dir, cowboy, []}}, %% {mimetypes, {fun mimetypes:path_to_mimes/2, default}}]]} %% ''' %% %% == ETag Header Function == %% %% The default behaviour of the static file handler is to not generate ETag %% headers. This is because generating ETag headers based on file metadata %% causes different servers in a cluster to generate different ETag values for %% the same file unless the metadata is also synced. Generating strong ETags %% based on the contents of a file is currently out of scope for this module. %% %% The default behaviour can be overridden to generate an ETag header based on %% a combination of the file path, file size, inode and mtime values. If the %% option value is a list of attribute names tagged with `attributes' a hex %% encoded CRC32 checksum of the attribute values are used as the ETag header %% value. %% %% If a strong ETag is required a user defined function for generating the %% header value can be supplied. The function must accept a proplist of the %% file attributes as the first argument and a second argument containing any %% additional data that the function requires. The function must return a %% `binary()' or `undefined'. %% %% ==== Examples ==== %% ``` %% %% A value of default is equal to not specifying the option. %% {[<<"static">>, '...', cowboy_http_static, %% [{directory, {priv_dir, cowboy, []}}, %% {etag, default}]]} %% %% %% Use all avaliable ETag function arguments to generate a header value. %% {[<<"static">>, '...', cowboy_http_static, %% [{directory, {priv_dir, cowboy, []}}, %% {etag, {attributes, [filepath, filesize, inode, mtime]}}]]} %% %% %% Use a user defined function to generate a strong ETag header value. %% {[<<"static">>, '...', cowboy_http_static, %% [{directory, {priv_dir, cowboy, []}}, %% {etag, {fun generate_strong_etag/2, strong_etag_extra}}]]} %% %% generate_strong_etag(Arguments, strong_etag_extra) -> %% {_, Filepath} = lists:keyfind(filepath, 1, Arguments), %% {_, _Filesize} = lists:keyfind(filesize, 1, Arguments), %% {_, _INode} = lists:keyfind(inode, 1, Arguments), %% {_, _Modified} = lists:keyfind(mtime, 1, Arguments), %% ChecksumCommand = lists:flatten(io_lib:format("sha1sum ~s", [Filepath])), %% [Checksum|_] = string:tokens(os:cmd(ChecksumCommand), " "), %% iolist_to_binary(Checksum). %% ''' -module(cowboy_http_static). %% include files -include("http.hrl"). -include_lib("kernel/include/file.hrl"). %% cowboy_http_protocol callbacks -export([init/3]). %% cowboy_http_rest callbacks -export([rest_init/2, allowed_methods/2, malformed_request/2, resource_exists/2, forbidden/2, last_modified/2, generate_etag/2, content_types_provided/2, file_contents/2]). %% internal -export([path_to_mimetypes/2]). %% types -type dirpath() :: string() | binary() | [binary()]. -type dirspec() :: dirpath() | {priv, atom(), dirpath()}. -type mimedef() :: {binary(), binary(), [{binary(), binary()}]}. -type etagarg() :: {filepath, binary()} | {mtime, calendar:datetime()} | {inode, non_neg_integer()} | {filesize, non_neg_integer()}. %% handler state -record(state, { filepath :: binary() | error, fileinfo :: {ok, #file_info{}} | {error, _} | error, mimetypes :: {fun((binary(), T) -> [mimedef()]), T} | undefined, etag_fun :: {fun(([etagarg()], T) -> undefined | binary()), T}}). %% @private Upgrade from HTTP handler to REST handler. init({_Transport, http}, _Req, _Opts) -> {upgrade, protocol, cowboy_http_rest}. %% @private Set up initial state of REST handler. -spec rest_init(#http_req{}, list()) -> {ok, #http_req{}, #state{}}. rest_init(Req, Opts) -> Directory = proplists:get_value(directory, Opts), Directory1 = directory_path(Directory), Mimetypes = proplists:get_value(mimetypes, Opts, []), Mimetypes1 = case Mimetypes of {_, _} -> Mimetypes; [] -> {fun path_to_mimetypes/2, []}; [_|_] -> {fun path_to_mimetypes/2, Mimetypes} end, ETagFunction = case proplists:get_value(etag, Opts) of default -> {fun no_etag_function/2, undefined}; undefined -> {fun no_etag_function/2, undefined}; {attributes, Attrs} -> {fun attr_etag_function/2, Attrs}; {_, _}=EtagFunction1 -> EtagFunction1 end, {Filepath, Req1} = cowboy_http_req:path_info(Req), State = case check_path(Filepath) of error -> #state{filepath=error, fileinfo=error, mimetypes=undefined, etag_fun=ETagFunction}; ok -> Filepath1 = join_paths(Directory1, Filepath), Fileinfo = file:read_file_info(Filepath1), #state{filepath=Filepath1, fileinfo=Fileinfo, mimetypes=Mimetypes1, etag_fun=ETagFunction} end, {ok, Req1, State}. %% @private Only allow GET and HEAD requests on files. -spec allowed_methods(#http_req{}, #state{}) -> {[atom()], #http_req{}, #state{}}. allowed_methods(Req, State) -> {['GET', 'HEAD'], Req, State}. %% @private malformed_request(Req, #state{filepath=error}=State) -> {true, Req, State}; malformed_request(Req, State) -> {false, Req, State}. %% @private Check if the resource exists under the document root. resource_exists(Req, #state{fileinfo={error, _}}=State) -> {false, Req, State}; resource_exists(Req, #state{fileinfo={ok, Fileinfo}}=State) -> {Fileinfo#file_info.type =:= regular, Req, State}. %% @private %% Access to a file resource is forbidden if it exists and the local node does %% not have permission to read it. Directory listings are always forbidden. forbidden(Req, #state{fileinfo={_, #file_info{type=directory}}}=State) -> {true, Req, State}; forbidden(Req, #state{fileinfo={error, eacces}}=State) -> {true, Req, State}; forbidden(Req, #state{fileinfo={error, _}}=State) -> {false, Req, State}; forbidden(Req, #state{fileinfo={ok, #file_info{access=Access}}}=State) -> {not (Access =:= read orelse Access =:= read_write), Req, State}. %% @private Read the time a file system system object was last modified. -spec last_modified(#http_req{}, #state{}) -> {calendar:datetime(), #http_req{}, #state{}}. last_modified(Req, #state{fileinfo={ok, #file_info{mtime=Modified}}}=State) -> {Modified, Req, State}. %% @private Generate the ETag header value for this file. %% The ETag header value is only generated if the resource is a file that %% exists in document root. -spec generate_etag(#http_req{}, #state{}) -> {undefined | binary(), #http_req{}, #state{}}. generate_etag(Req, #state{fileinfo={_, #file_info{type=regular, inode=INode, mtime=Modified, size=Filesize}}, filepath=Filepath, etag_fun={ETagFun, ETagData}}=State) -> ETagArgs = [ {filepath, Filepath}, {filesize, Filesize}, {inode, INode}, {mtime, Modified}], {ETagFun(ETagArgs, ETagData), Req, State}; generate_etag(Req, State) -> {undefined, Req, State}. %% @private Return the content type of a file. -spec content_types_provided(#http_req{}, #state{}) -> tuple(). content_types_provided(Req, #state{filepath=Filepath, mimetypes={MimetypesFun, MimetypesData}}=State) -> Mimetypes = [{T, file_contents} || T <- MimetypesFun(Filepath, MimetypesData)], {Mimetypes, Req, State}. %% @private Return a function that writes a file directly to the socket. -spec file_contents(#http_req{}, #state{}) -> tuple(). file_contents(Req, #state{filepath=Filepath, fileinfo={ok, #file_info{size=Filesize}}}=State) -> {ok, Transport, Socket} = cowboy_http_req:transport(Req), Writefile = content_function(Transport, Socket, Filepath), {{stream, Filesize, Writefile}, Req, State}. %% @private Return a function writing the contents of a file to a socket. %% The function returns the number of bytes written to the socket to enable %% the calling function to determine if the expected number of bytes were %% written to the socket. -spec content_function(module(), inet:socket(), binary()) -> fun(() -> {sent, non_neg_integer()}). content_function(Transport, Socket, Filepath) -> %% `file:sendfile/2' will only work with the `cowboy_tcp_transport' %% transport module. SSL or future SPDY transports that require the %% content to be encrypted or framed as the content is sent. case erlang:function_exported(file, sendfile, 2) of false -> fun() -> sfallback(Transport, Socket, Filepath) end; _ when Transport =/= cowboy_tcp_transport -> fun() -> sfallback(Transport, Socket, Filepath) end; true -> fun() -> sendfile(Socket, Filepath) end end. %% @private Sendfile fallback function. -spec sfallback(module(), inet:socket(), binary()) -> {sent, non_neg_integer()}. sfallback(Transport, Socket, Filepath) -> {ok, File} = file:open(Filepath, [read,binary,raw]), sfallback(Transport, Socket, File, 0). -spec sfallback(module(), inet:socket(), file:io_device(), non_neg_integer()) -> {sent, non_neg_integer()}. sfallback(Transport, Socket, File, Sent) -> case file:read(File, 16#1FFF) of eof -> ok = file:close(File), {sent, Sent}; {ok, Bin} -> ok = Transport:send(Socket, Bin), sfallback(Transport, Socket, File, Sent + byte_size(Bin)) end. %% @private Wrapper for sendfile function. -spec sendfile(inet:socket(), binary()) -> {sent, non_neg_integer()}. sendfile(Socket, Filepath) -> {ok, Sent} = file:sendfile(Filepath, Socket), {sent, Sent}. -spec directory_path(dirspec()) -> dirpath(). directory_path({priv_dir, App, []}) -> priv_dir_path(App); directory_path({priv_dir, App, [H|_]=Path}) when is_integer(H) -> filename:join(priv_dir_path(App), Path); directory_path({priv_dir, App, [H|_]=Path}) when is_binary(H) -> filename:join(filename:split(priv_dir_path(App)) ++ Path); directory_path({priv_dir, App, Path}) when is_binary(Path) -> filename:join(priv_dir_path(App), Path); directory_path(Path) -> Path. %% @private Validate a request path for unsafe characters. %% There is no way to escape special characters in a filesystem path. -spec check_path(Path::[binary()]) -> ok | error. check_path([]) -> ok; check_path([<<"">>|_T]) -> error; check_path([<<".">>|_T]) -> error; check_path([<<"..">>|_T]) -> error; check_path([H|T]) -> case binary:match(H, <<"/">>) of {_, _} -> error; nomatch -> check_path(T) end. %% @private Join the the directory and request paths. -spec join_paths(dirpath(), [binary()]) -> binary(). join_paths([H|_]=Dirpath, Filepath) when is_integer(H) -> filename:join(filename:split(Dirpath) ++ Filepath); join_paths([H|_]=Dirpath, Filepath) when is_binary(H) -> filename:join(Dirpath ++ Filepath); join_paths(Dirpath, Filepath) when is_binary(Dirpath) -> filename:join([Dirpath] ++ Filepath); join_paths([], Filepath) -> filename:join(Filepath). %% @private Return the path to the priv/ directory of an application. -spec priv_dir_path(atom()) -> string(). priv_dir_path(App) -> case code:priv_dir(App) of {error, bad_name} -> priv_dir_mod(App); Dir -> Dir end. -spec priv_dir_mod(atom()) -> string(). priv_dir_mod(Mod) -> case code:which(Mod) of File when not is_list(File) -> "../priv"; File -> filename:join([filename:dirname(File),"../priv"]) end. %% @private Use application/octet-stream as the default mimetype. %% If a list of extension - mimetype pairs are provided as the mimetypes %% an attempt to find the mimetype using the file extension. If no match %% is found the default mimetype is returned. -spec path_to_mimetypes(binary(), [{binary(), [mimedef()]}]) -> [mimedef()]. path_to_mimetypes(Filepath, Extensions) when is_binary(Filepath) -> Ext = filename:extension(Filepath), case Ext of <<>> -> default_mimetype(); _Ext -> path_to_mimetypes_(Ext, Extensions) end. -spec path_to_mimetypes_(binary(), [{binary(), [mimedef()]}]) -> [mimedef()]. path_to_mimetypes_(Ext, Extensions) -> case lists:keyfind(Ext, 1, Extensions) of {_, MTs} -> MTs; _Unknown -> default_mimetype() end. -spec default_mimetype() -> [mimedef()]. default_mimetype() -> [{<<"application">>, <<"octet-stream">>, []}]. %% @private Do not send ETag headers in the default configuration. -spec no_etag_function([etagarg()], undefined) -> undefined. no_etag_function(_Args, undefined) -> undefined. %% @private A simple alternative is to send an ETag based on file attributes. -type fileattr() :: filepath | filesize | mtime | inode. -spec attr_etag_function([etagarg()], [fileattr()]) -> binary(). attr_etag_function(Args, Attrs) -> attr_etag_function(Args, Attrs, []). -spec attr_etag_function([etagarg()], [fileattr()], [binary()]) -> binary(). attr_etag_function(_Args, [], Acc) -> list_to_binary(erlang:integer_to_list(erlang:crc32(Acc), 16)); attr_etag_function(Args, [H|T], Acc) -> {_, Value} = lists:keyfind(H, 1, Args), attr_etag_function(Args, T, [term_to_binary(Value)|Acc]). -ifdef(TEST). -include_lib("eunit/include/eunit.hrl"). -define(_eq(E, I), ?_assertEqual(E, I)). check_path_test_() -> C = fun check_path/1, [?_eq(error, C([<<>>])), ?_eq(ok, C([<<"abc">>])), ?_eq(error, C([<<".">>])), ?_eq(error, C([<<"..">>])), ?_eq(error, C([<<"/">>])) ]. join_paths_test_() -> P = fun join_paths/2, [?_eq(<<"a">>, P([], [<<"a">>])), ?_eq(<<"a/b/c">>, P(<<"a/b">>, [<<"c">>])), ?_eq(<<"a/b/c">>, P("a/b", [<<"c">>])), ?_eq(<<"a/b/c">>, P([<<"a">>, <<"b">>], [<<"c">>])) ]. directory_path_test_() -> P = fun directory_path/1, PL = fun(I) -> length(filename:split(P(I))) end, Base = PL({priv_dir, cowboy, []}), [?_eq(Base + 1, PL({priv_dir, cowboy, "a"})), ?_eq(Base + 1, PL({priv_dir, cowboy, <<"a">>})), ?_eq(Base + 1, PL({priv_dir, cowboy, [<<"a">>]})), ?_eq(Base + 2, PL({priv_dir, cowboy, "a/b"})), ?_eq(Base + 2, PL({priv_dir, cowboy, <<"a/b">>})), ?_eq(Base + 2, PL({priv_dir, cowboy, [<<"a">>, <<"b">>]})), ?_eq("a/b", P("a/b")) ]. -endif. rabbitmq-server-3.2.4/plugins-src/cowboy-wrapper/cowboy-git/src/cowboy_tcp_transport.erl0000644000000000000000000000732212305126066030420 0ustar rootroot%% Copyright (c) 2011, Loïc Hoguin %% %% Permission to use, copy, modify, and/or distribute this software for any %% purpose with or without fee is hereby granted, provided that the above %% copyright notice and this permission notice appear in all copies. %% %% THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES %% WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF %% MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR %% ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES %% WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN %% ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF %% OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. %% @doc TCP transport API. %% %% Wrapper around gen_tcp implementing the Cowboy transport API. %% %% @see gen_tcp -module(cowboy_tcp_transport). -export([name/0, messages/0, listen/1, accept/2, recv/3, send/2, setopts/2, controlling_process/2, peername/1, close/1]). %% @doc Name of this transport API, tcp. -spec name() -> tcp. name() -> tcp. %% @doc Atoms used in the process messages sent by this API. %% %% They identify incoming data, closed connection and errors when receiving %% data in active mode. -spec messages() -> {tcp, tcp_closed, tcp_error}. messages() -> {tcp, tcp_closed, tcp_error}. %% @doc Setup a socket to listen on the given port on the local host. %% %% The available options are: %%
    %%
    port
    Mandatory. TCP port number to open.
    %%
    backlog
    Maximum length of the pending connections queue. %% Defaults to 1024.
    %%
    ip
    Interface to listen on. Listen on all interfaces %% by default.
    %%
    %% %% @see gen_tcp:listen/2 -spec listen([{port, inet:ip_port()} | {ip, inet:ip_address()}]) -> {ok, inet:socket()} | {error, atom()}. listen(Opts) -> {port, Port} = lists:keyfind(port, 1, Opts), Backlog = proplists:get_value(backlog, Opts, 1024), ListenOpts0 = [binary, {active, false}, {backlog, Backlog}, {packet, raw}, {reuseaddr, true}], ListenOpts = case lists:keyfind(ip, 1, Opts) of false -> ListenOpts0; Ip -> [Ip|ListenOpts0] end, gen_tcp:listen(Port, ListenOpts). %% @doc Accept an incoming connection on a listen socket. %% @see gen_tcp:accept/2 -spec accept(inet:socket(), timeout()) -> {ok, inet:socket()} | {error, closed | timeout | atom()}. accept(LSocket, Timeout) -> gen_tcp:accept(LSocket, Timeout). %% @doc Receive a packet from a socket in passive mode. %% @see gen_tcp:recv/3 -spec recv(inet:socket(), non_neg_integer(), timeout()) -> {ok, any()} | {error, closed | atom()}. recv(Socket, Length, Timeout) -> gen_tcp:recv(Socket, Length, Timeout). %% @doc Send a packet on a socket. %% @see gen_tcp:send/2 -spec send(inet:socket(), iolist()) -> ok | {error, atom()}. send(Socket, Packet) -> gen_tcp:send(Socket, Packet). %% @doc Set one or more options for a socket. %% @see inet:setopts/2 -spec setopts(inet:socket(), list()) -> ok | {error, atom()}. setopts(Socket, Opts) -> inet:setopts(Socket, Opts). %% @doc Assign a new controlling process Pid to Socket. %% @see gen_tcp:controlling_process/2 -spec controlling_process(inet:socket(), pid()) -> ok | {error, closed | not_owner | atom()}. controlling_process(Socket, Pid) -> gen_tcp:controlling_process(Socket, Pid). %% @doc Return the address and port for the other end of a connection. %% @see inet:peername/1 -spec peername(inet:socket()) -> {ok, {inet:ip_address(), inet:ip_port()}} | {error, atom()}. peername(Socket) -> inet:peername(Socket). %% @doc Close a TCP socket. %% @see gen_tcp:close/1 -spec close(inet:socket()) -> ok. close(Socket) -> gen_tcp:close(Socket). rabbitmq-server-3.2.4/plugins-src/cowboy-wrapper/cowboy-git/src/cowboy_http_websocket_handler.erl0000644000000000000000000000557412305126066032247 0ustar rootroot%% Copyright (c) 2011, Loïc Hoguin %% %% Permission to use, copy, modify, and/or distribute this software for any %% purpose with or without fee is hereby granted, provided that the above %% copyright notice and this permission notice appear in all copies. %% %% THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES %% WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF %% MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR %% ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES %% WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN %% ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF %% OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. %% @doc Handler for HTTP WebSocket requests. %% %% WebSocket handlers must implement four callbacks: websocket_init/3, %% websocket_handle/3, websocket_info/3 and %% websocket_terminate/3. These callbacks will only be called if the %% connection is upgraded to WebSocket in the HTTP handler's init/3 %% callback. They are then called in that order, although %% websocket_handle/3 will be called for each packet received, %% and websocket_info for each message received. %% %% websocket_init/3 is meant for initialization. It receives %% information about the transport and protocol used, along with the handler %% options from the dispatch list. You can define a request-wide state here. %% If you are going to want to compact the request, you should probably do it %% here. %% %% websocket_handle/3 receives the data from the socket. It can reply %% something, do nothing or close the connection. %% %% websocket_info/3 receives messages sent to the process. It has %% the same reply format as websocket_handle/3 described above. Note %% that unlike in a gen_server, when websocket_info/3 %% replies something, it is always to the socket, not to the process that %% originated the message. %% %% websocket_terminate/3 is meant for cleaning up. It also receives %% the request and the state previously defined, along with a reason for %% termination. %% %% All of websocket_init/3, websocket_handle/3 and %% websocket_info/3 can decide to hibernate the process by adding %% an extra element to the returned tuple, containing the atom %% hibernate. Doing so helps save memory and improve CPU usage. -module(cowboy_http_websocket_handler). -export([behaviour_info/1]). %% @private -spec behaviour_info(_) -> undefined | [{websocket_handle, 3} | {websocket_info, 3} | {websocket_init, 3} | {websocket_terminate, 3}, ...]. behaviour_info(callbacks) -> [{websocket_init, 3}, {websocket_handle, 3}, {websocket_info, 3}, {websocket_terminate, 3}]; behaviour_info(_Other) -> undefined. rabbitmq-server-3.2.4/plugins-src/cowboy-wrapper/cowboy-git/src/cowboy_multipart.erl0000644000000000000000000002151212305126066027534 0ustar rootroot%% Copyright (c) 2011, Anthony Ramine %% %% Permission to use, copy, modify, and/or distribute this software for any %% purpose with or without fee is hereby granted, provided that the above %% copyright notice and this permission notice appear in all copies. %% %% THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES %% WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF %% MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR %% ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES %% WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN %% ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF %% OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. %% @doc Multipart parser. -module(cowboy_multipart). -type part_parser() :: any(). -type parser(T) :: fun((binary()) -> T). -type more(T) :: T | {more, parser(T)}. -type part_result() :: any(). -type headers() :: any(). -type http_headers() :: [{atom() | binary(), binary()}]. -type body_cont() :: any(). -type cont(T) :: fun(() -> T). -type body_result() :: any(). -type end_of_part() :: {end_of_part, cont(more(part_result()))}. -type disposition() :: {binary(), [{binary(), binary()}]}. -export([parser/1, content_disposition/1]). -include_lib("eunit/include/eunit.hrl"). %% API. %% @doc Return a multipart parser for the given boundary. -spec parser(binary()) -> part_parser(). parser(Boundary) when is_binary(Boundary) -> fun (Bin) when is_binary(Bin) -> parse(Bin, Boundary) end. %% @doc Parse a content disposition. %% @todo Parse the MIME header instead of the HTTP one. -spec content_disposition(binary()) -> disposition(). content_disposition(Data) -> cowboy_http:token_ci(Data, fun (_Rest, <<>>) -> {error, badarg}; (Rest, Disposition) -> cowboy_http:content_type_params(Rest, fun (Params) -> {Disposition, Params} end, []) end). %% Internal. %% @doc Entry point of the multipart parser, skips over the preamble if any. -spec parse(binary(), binary()) -> more(part_result()). parse(Bin, Boundary) when byte_size(Bin) >= byte_size(Boundary) + 2 -> BoundarySize = byte_size(Boundary), Pattern = pattern(Boundary), case Bin of <<"--", Boundary:BoundarySize/binary, Rest/binary>> -> % Data starts with initial boundary, skip preamble parsing. parse_boundary_tail(Rest, Pattern); _ -> % Parse preamble. skip(Bin, Pattern) end; parse(Bin, Boundary) -> % Not enough data to know if the data begins with a boundary. more(Bin, fun (NewBin) -> parse(NewBin, Boundary) end). -type pattern() :: {binary:cp(), non_neg_integer()}. %% @doc Return a compiled binary pattern with its size in bytes. %% The pattern is the boundary prepended with "\r\n--". -spec pattern(binary()) -> pattern(). pattern(Boundary) -> MatchPattern = <<"\r\n--", Boundary/binary>>, {binary:compile_pattern(MatchPattern), byte_size(MatchPattern)}. %% @doc Parse remaining characters of a line beginning with the boundary. %% If followed by "--", eof is returned and parsing is finished. -spec parse_boundary_tail(binary(), pattern()) -> more(part_result()). parse_boundary_tail(Bin, Pattern) when byte_size(Bin) >= 2 -> case Bin of <<"--", _Rest/binary>> -> % Boundary is followed by "--", end parsing. eof; _ -> % No dash after boundary, proceed with unknown chars and lwsp % removal. parse_boundary_eol(Bin, Pattern) end; parse_boundary_tail(Bin, Pattern) -> % Boundary may be followed by "--", need more data. more(Bin, fun (NewBin) -> parse_boundary_tail(NewBin, Pattern) end). %% @doc Skip whitespace and unknown chars until CRLF. -spec parse_boundary_eol(binary(), pattern()) -> more(part_result()). parse_boundary_eol(Bin, Pattern) -> case binary:match(Bin, <<"\r\n">>) of {CrlfStart, _Length} -> % End of line found, remove optional whitespace. <<_:CrlfStart/binary, Rest/binary>> = Bin, Fun = fun (Rest2) -> parse_boundary_crlf(Rest2, Pattern) end, cowboy_http:whitespace(Rest, Fun); nomatch -> % CRLF not found in the given binary. RestStart = lists:max([byte_size(Bin) - 1, 0]), <<_:RestStart/binary, Rest/binary>> = Bin, more(Rest, fun (NewBin) -> parse_boundary_eol(NewBin, Pattern) end) end. -spec parse_boundary_crlf(binary(), pattern()) -> more(part_result()). parse_boundary_crlf(<<"\r\n", Rest/binary>>, Pattern) -> % The binary is at least 2 bytes long as this function is only called by % parse_boundary_eol/3 when CRLF has been found so a more tuple will never % be returned from here. parse_headers(Rest, Pattern); parse_boundary_crlf(Bin, Pattern) -> % Unspecified behaviour here: RFC 2046 doesn't say what to do when LWSP is % not followed directly by a new line. In this implementation it is % considered part of the boundary so EOL needs to be searched again. parse_boundary_eol(Bin, Pattern). -spec parse_headers(binary(), pattern()) -> more(part_result()). parse_headers(Bin, Pattern) -> parse_headers(Bin, Pattern, []). -spec parse_headers(binary(), pattern(), http_headers()) -> more(part_result()). parse_headers(Bin, Pattern, Acc) -> case erlang:decode_packet(httph_bin, Bin, []) of {ok, {http_header, _, Name, _, Value}, Rest} -> parse_headers(Rest, Pattern, [{Name, Value} | Acc]); {ok, http_eoh, Rest} -> Headers = lists:reverse(Acc), {headers, Headers, fun () -> parse_body(Rest, Pattern) end}; {ok, {http_error, _}, _} -> % Skip malformed parts. skip(Bin, Pattern); {more, _} -> more(Bin, fun (NewBin) -> parse_headers(NewBin, Pattern, Acc) end) end. -spec parse_body(binary(), pattern()) -> more(body_result()). parse_body(Bin, Pattern = {P, PSize}) when byte_size(Bin) >= PSize -> case binary:match(Bin, P) of {0, _Length} -> <<_:PSize/binary, Rest/binary>> = Bin, end_of_part(Rest, Pattern); {BoundaryStart, _Length} -> % Boundary found, this is the latest partial body that will be % returned for this part. <> = Bin, FResult = end_of_part(Rest, Pattern), {body, PBody, fun () -> FResult end}; nomatch -> PartialLength = byte_size(Bin) - PSize + 1, <> = Bin, {body, PBody, fun () -> parse_body(Rest, Pattern) end} end; parse_body(Bin, Pattern) -> more(Bin, fun (NewBin) -> parse_body(NewBin, Pattern) end). -spec end_of_part(binary(), pattern()) -> end_of_part(). end_of_part(Bin, Pattern) -> {end_of_part, fun () -> parse_boundary_tail(Bin, Pattern) end}. -spec skip(binary(), pattern()) -> more(part_result()). skip(Bin, Pattern = {P, PSize}) -> case binary:match(Bin, P) of {BoundaryStart, _Length} -> % Boundary found, proceed with parsing of the next part. RestStart = BoundaryStart + PSize, <<_:RestStart/binary, Rest/binary>> = Bin, parse_boundary_tail(Rest, Pattern); nomatch -> % Boundary not found, need more data. RestStart = lists:max([byte_size(Bin) - PSize + 1, 0]), <<_:RestStart/binary, Rest/binary>> = Bin, more(Rest, fun (NewBin) -> skip(NewBin, Pattern) end) end. -spec more(binary(), parser(T)) -> {more, parser(T)}. more(<<>>, F) -> {more, F}; more(Bin, InnerF) -> F = fun (NewData) when is_binary(NewData) -> InnerF(<>) end, {more, F}. %% Tests. -ifdef(TEST). multipart_test_() -> %% {Body, Result} Tests = [ {<<"--boundary--">>, []}, {<<"preamble\r\n--boundary--">>, []}, {<<"--boundary--\r\nepilogue">>, []}, {<<"\r\n--boundary\r\nA:b\r\nC:d\r\n\r\n\r\n--boundary--">>, [{[{<<"A">>, <<"b">>}, {<<"C">>, <<"d">>}], <<>>}]}, { << "--boundary\r\nX-Name:answer\r\n\r\n42" "\r\n--boundary\r\nServer:Cowboy\r\n\r\nIt rocks!\r\n" "\r\n--boundary--" >>, [ {[{<<"X-Name">>, <<"answer">>}], <<"42">>}, {[{'Server', <<"Cowboy">>}], <<"It rocks!\r\n">>} ] } ], [{title(V), fun () -> R = acc_multipart(V) end} || {V, R} <- Tests]. acc_multipart(V) -> acc_multipart((parser(<<"boundary">>))(V), []). acc_multipart({headers, Headers, Cont}, Acc) -> acc_multipart(Cont(), [{Headers, []}|Acc]); acc_multipart({body, Body, Cont}, [{Headers, BodyAcc}|Acc]) -> acc_multipart(Cont(), [{Headers, [Body|BodyAcc]}|Acc]); acc_multipart({end_of_part, Cont}, [{Headers, BodyAcc}|Acc]) -> Body = list_to_binary(lists:reverse(BodyAcc)), acc_multipart(Cont(), [{Headers, Body}|Acc]); acc_multipart(eof, Acc) -> lists:reverse(Acc). content_disposition_test_() -> %% {Disposition, Result} Tests = [ {<<"form-data; name=id">>, {<<"form-data">>, [{<<"name">>, <<"id">>}]}}, {<<"inline">>, {<<"inline">>, []}}, {<<"attachment; \tfilename=brackets-slides.pdf">>, {<<"attachment">>, [{<<"filename">>, <<"brackets-slides.pdf">>}]}} ], [{title(V), fun () -> R = content_disposition(V) end} || {V, R} <- Tests]. title(Bin) -> Title = lists:foldl( fun ({T, R}, V) -> re:replace(V, T, R, [global]) end, Bin, [{"\t", "\\\\t"}, {"\r", "\\\\r"}, {"\n", "\\\\n"}] ), iolist_to_binary(Title). -endif. rabbitmq-server-3.2.4/plugins-src/cowboy-wrapper/cowboy-git/src/cowboy_app.erl0000644000000000000000000000310712305126066026273 0ustar rootroot%% Copyright (c) 2011, Loïc Hoguin %% %% Permission to use, copy, modify, and/or distribute this software for any %% purpose with or without fee is hereby granted, provided that the above %% copyright notice and this permission notice appear in all copies. %% %% THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES %% WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF %% MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR %% ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES %% WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN %% ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF %% OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. %% @private -module(cowboy_app). -behaviour(application). -export([start/2, stop/1, profile_output/0]). %% API. -type application_start_type() :: normal | {takeover, node()} | {failover, node()}. %% API. -spec start(application_start_type(), any()) -> {ok, pid()}. start(_Type, _Args) -> consider_profiling(), cowboy_sup:start_link(). -spec stop(any()) -> ok. stop(_State) -> ok. -spec profile_output() -> ok. profile_output() -> eprof:stop_profiling(), eprof:log("procs.profile"), eprof:analyze(procs), eprof:log("total.profile"), eprof:analyze(total). %% Internal. -spec consider_profiling() -> profiling | not_profiling. consider_profiling() -> case application:get_env(profile) of {ok, true} -> {ok, _Pid} = eprof:start(), eprof:start_profiling([self()]); _ -> not_profiling end. rabbitmq-server-3.2.4/plugins-src/cowboy-wrapper/cowboy-git/src/cowboy_http.erl0000644000000000000000000007315512305126066026504 0ustar rootroot%% Copyright (c) 2011, Loïc Hoguin %% Copyright (c) 2011, Anthony Ramine %% %% Permission to use, copy, modify, and/or distribute this software for any %% purpose with or without fee is hereby granted, provided that the above %% copyright notice and this permission notice appear in all copies. %% %% THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES %% WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF %% MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR %% ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES %% WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN %% ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF %% OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. %% @doc Core HTTP parsing API. -module(cowboy_http). %% Parsing. -export([list/2, nonempty_list/2, content_type/1, content_type_params/3, media_range/2, conneg/2, language_range/2, entity_tag_match/1, http_date/1, rfc1123_date/1, rfc850_date/1, asctime_date/1, whitespace/2, digits/1, token/2, token_ci/2, quoted_string/2]). %% Interpretation. -export([connection_to_atom/1, urldecode/1, urldecode/2, urlencode/1, urlencode/2]). -type method() :: 'OPTIONS' | 'GET' | 'HEAD' | 'POST' | 'PUT' | 'DELETE' | 'TRACE' | binary(). -type uri() :: '*' | {absoluteURI, http | https, Host::binary(), Port::integer() | undefined, Path::binary()} | {scheme, Scheme::binary(), binary()} | {abs_path, binary()} | binary(). -type version() :: {Major::non_neg_integer(), Minor::non_neg_integer()}. -type header() :: 'Cache-Control' | 'Connection' | 'Date' | 'Pragma' | 'Transfer-Encoding' | 'Upgrade' | 'Via' | 'Accept' | 'Accept-Charset' | 'Accept-Encoding' | 'Accept-Language' | 'Authorization' | 'From' | 'Host' | 'If-Modified-Since' | 'If-Match' | 'If-None-Match' | 'If-Range' | 'If-Unmodified-Since' | 'Max-Forwards' | 'Proxy-Authorization' | 'Range' | 'Referer' | 'User-Agent' | 'Age' | 'Location' | 'Proxy-Authenticate' | 'Public' | 'Retry-After' | 'Server' | 'Vary' | 'Warning' | 'Www-Authenticate' | 'Allow' | 'Content-Base' | 'Content-Encoding' | 'Content-Language' | 'Content-Length' | 'Content-Location' | 'Content-Md5' | 'Content-Range' | 'Content-Type' | 'Etag' | 'Expires' | 'Last-Modified' | 'Accept-Ranges' | 'Set-Cookie' | 'Set-Cookie2' | 'X-Forwarded-For' | 'Cookie' | 'Keep-Alive' | 'Proxy-Connection' | binary(). -type fake_iodata() :: iolist() | binary(). -type headers() :: [{header(), fake_iodata()}]. -type status() :: non_neg_integer() | binary(). -export_type([method/0, uri/0, version/0, header/0, headers/0, status/0]). -include("include/http.hrl"). -include_lib("eunit/include/eunit.hrl"). %% Parsing. %% @doc Parse a non-empty list of the given type. -spec nonempty_list(binary(), fun()) -> [any(), ...] | {error, badarg}. nonempty_list(Data, Fun) -> case list(Data, Fun, []) of {error, badarg} -> {error, badarg}; [] -> {error, badarg}; L -> lists:reverse(L) end. %% @doc Parse a list of the given type. -spec list(binary(), fun()) -> list() | {error, badarg}. list(Data, Fun) -> case list(Data, Fun, []) of {error, badarg} -> {error, badarg}; L -> lists:reverse(L) end. -spec list(binary(), fun(), [binary()]) -> [any()] | {error, badarg}. %% From the RFC: %%
    Wherever this construct is used, null elements are allowed, %% but do not contribute to the count of elements present. %% That is, "(element), , (element) " is permitted, but counts %% as only two elements. Therefore, where at least one element is required, %% at least one non-null element MUST be present.
    list(Data, Fun, Acc) -> whitespace(Data, fun (<<>>) -> Acc; (<< $,, Rest/binary >>) -> list(Rest, Fun, Acc); (Rest) -> Fun(Rest, fun (D, I) -> whitespace(D, fun (<<>>) -> [I|Acc]; (<< $,, R/binary >>) -> list(R, Fun, [I|Acc]); (_Any) -> {error, badarg} end) end) end). %% @doc Parse a content type. -spec content_type(binary()) -> any(). content_type(Data) -> media_type(Data, fun (Rest, Type, SubType) -> content_type_params(Rest, fun (Params) -> {Type, SubType, Params} end, []) end). -spec content_type_params(binary(), fun(), list({binary(), binary()})) -> any(). content_type_params(Data, Fun, Acc) -> whitespace(Data, fun (<< $;, Rest/binary >>) -> content_type_param(Rest, Fun, Acc); (<<>>) -> Fun(lists:reverse(Acc)); (_Rest) -> {error, badarg} end). -spec content_type_param(binary(), fun(), list({binary(), binary()})) -> any(). content_type_param(Data, Fun, Acc) -> whitespace(Data, fun (Rest) -> token_ci(Rest, fun (_Rest2, <<>>) -> {error, badarg}; (<< $=, Rest2/binary >>, Attr) -> word(Rest2, fun (Rest3, Value) -> content_type_params(Rest3, Fun, [{Attr, Value}|Acc]) end); (_Rest2, _Attr) -> {error, badarg} end) end). %% @doc Parse a media range. -spec media_range(binary(), fun()) -> any(). media_range(Data, Fun) -> media_type(Data, fun (Rest, Type, SubType) -> media_range_params(Rest, Fun, Type, SubType, []) end). -spec media_range_params(binary(), fun(), binary(), binary(), [{binary(), binary()}]) -> any(). media_range_params(Data, Fun, Type, SubType, Acc) -> whitespace(Data, fun (<< $;, Rest/binary >>) -> whitespace(Rest, fun (Rest2) -> media_range_param_attr(Rest2, Fun, Type, SubType, Acc) end); (Rest) -> Fun(Rest, {{Type, SubType, lists:reverse(Acc)}, 1000, []}) end). -spec media_range_param_attr(binary(), fun(), binary(), binary(), [{binary(), binary()}]) -> any(). media_range_param_attr(Data, Fun, Type, SubType, Acc) -> token_ci(Data, fun (_Rest, <<>>) -> {error, badarg}; (<< $=, Rest/binary >>, Attr) -> media_range_param_value(Rest, Fun, Type, SubType, Acc, Attr) end). -spec media_range_param_value(binary(), fun(), binary(), binary(), [{binary(), binary()}], binary()) -> any(). media_range_param_value(Data, Fun, Type, SubType, Acc, <<"q">>) -> qvalue(Data, fun (Rest, Quality) -> accept_ext(Rest, Fun, Type, SubType, Acc, Quality, []) end); media_range_param_value(Data, Fun, Type, SubType, Acc, Attr) -> word(Data, fun (Rest, Value) -> media_range_params(Rest, Fun, Type, SubType, [{Attr, Value}|Acc]) end). %% @doc Parse a media type. -spec media_type(binary(), fun()) -> any(). media_type(Data, Fun) -> token_ci(Data, fun (_Rest, <<>>) -> {error, badarg}; (<< $/, Rest/binary >>, Type) -> token_ci(Rest, fun (_Rest2, <<>>) -> {error, badarg}; (Rest2, SubType) -> Fun(Rest2, Type, SubType) end); (_Rest, _Type) -> {error, badarg} end). -spec accept_ext(binary(), fun(), binary(), binary(), [{binary(), binary()}], 0..1000, [{binary(), binary()} | binary()]) -> any(). accept_ext(Data, Fun, Type, SubType, Params, Quality, Acc) -> whitespace(Data, fun (<< $;, Rest/binary >>) -> whitespace(Rest, fun (Rest2) -> accept_ext_attr(Rest2, Fun, Type, SubType, Params, Quality, Acc) end); (Rest) -> Fun(Rest, {{Type, SubType, lists:reverse(Params)}, Quality, lists:reverse(Acc)}) end). -spec accept_ext_attr(binary(), fun(), binary(), binary(), [{binary(), binary()}], 0..1000, [{binary(), binary()} | binary()]) -> any(). accept_ext_attr(Data, Fun, Type, SubType, Params, Quality, Acc) -> token_ci(Data, fun (_Rest, <<>>) -> {error, badarg}; (<< $=, Rest/binary >>, Attr) -> accept_ext_value(Rest, Fun, Type, SubType, Params, Quality, Acc, Attr); (Rest, Attr) -> accept_ext(Rest, Fun, Type, SubType, Params, Quality, [Attr|Acc]) end). -spec accept_ext_value(binary(), fun(), binary(), binary(), [{binary(), binary()}], 0..1000, [{binary(), binary()} | binary()], binary()) -> any(). accept_ext_value(Data, Fun, Type, SubType, Params, Quality, Acc, Attr) -> word(Data, fun (Rest, Value) -> accept_ext(Rest, Fun, Type, SubType, Params, Quality, [{Attr, Value}|Acc]) end). %% @doc Parse a conneg header (Accept-Charset, Accept-Encoding), %% followed by an optional quality value. -spec conneg(binary(), fun()) -> any(). conneg(Data, Fun) -> token_ci(Data, fun (_Rest, <<>>) -> {error, badarg}; (Rest, Conneg) -> maybe_qparam(Rest, fun (Rest2, Quality) -> Fun(Rest2, {Conneg, Quality}) end) end). %% @doc Parse a language range, followed by an optional quality value. -spec language_range(binary(), fun()) -> any(). language_range(<< $*, Rest/binary >>, Fun) -> language_range_ret(Rest, Fun, '*'); language_range(Data, Fun) -> language_tag(Data, fun (Rest, LanguageTag) -> language_range_ret(Rest, Fun, LanguageTag) end). -spec language_range_ret(binary(), fun(), '*' | {binary(), [binary()]}) -> any(). language_range_ret(Data, Fun, LanguageTag) -> maybe_qparam(Data, fun (Rest, Quality) -> Fun(Rest, {LanguageTag, Quality}) end). -spec language_tag(binary(), fun()) -> any(). language_tag(Data, Fun) -> alpha(Data, fun (_Rest, Tag) when byte_size(Tag) =:= 0; byte_size(Tag) > 8 -> {error, badarg}; (<< $-, Rest/binary >>, Tag) -> language_subtag(Rest, Fun, Tag, []); (Rest, Tag) -> Fun(Rest, Tag) end). -spec language_subtag(binary(), fun(), binary(), [binary()]) -> any(). language_subtag(Data, Fun, Tag, Acc) -> alpha(Data, fun (_Rest, SubTag) when byte_size(SubTag) =:= 0; byte_size(SubTag) > 8 -> {error, badarg}; (<< $-, Rest/binary >>, SubTag) -> language_subtag(Rest, Fun, Tag, [SubTag|Acc]); (Rest, SubTag) -> %% Rebuild the full tag now that we know it's correct Sub = << << $-, S/binary >> || S <- lists:reverse([SubTag|Acc]) >>, Fun(Rest, << Tag/binary, Sub/binary >>) end). -spec maybe_qparam(binary(), fun()) -> any(). maybe_qparam(Data, Fun) -> whitespace(Data, fun (<< $;, Rest/binary >>) -> whitespace(Rest, fun (Rest2) -> qparam(Rest2, Fun) end); (Rest) -> Fun(Rest, 1000) end). %% @doc Parse a quality parameter string (for example q=0.500). -spec qparam(binary(), fun()) -> any(). qparam(<< Q, $=, Data/binary >>, Fun) when Q =:= $q; Q =:= $Q -> qvalue(Data, Fun). %% @doc Parse either a list of entity tags or a "*". -spec entity_tag_match(binary()) -> any(). entity_tag_match(<< $*, Rest/binary >>) -> whitespace(Rest, fun (<<>>) -> '*'; (_Any) -> {error, badarg} end); entity_tag_match(Data) -> nonempty_list(Data, fun entity_tag/2). %% @doc Parse an entity-tag. -spec entity_tag(binary(), fun()) -> any(). entity_tag(<< "W/", Rest/binary >>, Fun) -> opaque_tag(Rest, Fun, weak); entity_tag(Data, Fun) -> opaque_tag(Data, Fun, strong). -spec opaque_tag(binary(), fun(), weak | strong) -> any(). opaque_tag(Data, Fun, Strength) -> quoted_string(Data, fun (_Rest, <<>>) -> {error, badarg}; (Rest, OpaqueTag) -> Fun(Rest, {Strength, OpaqueTag}) end). %% @doc Parse an HTTP date (RFC1123, RFC850 or asctime date). %% @end %% %% While this may not be the most efficient date parsing we can do, %% it should work fine for our purposes because all HTTP dates should %% be sent as RFC1123 dates in HTTP/1.1. -spec http_date(binary()) -> any(). http_date(Data) -> case rfc1123_date(Data) of {error, badarg} -> case rfc850_date(Data) of {error, badarg} -> case asctime_date(Data) of {error, badarg} -> {error, badarg}; HTTPDate -> HTTPDate end; HTTPDate -> HTTPDate end; HTTPDate -> HTTPDate end. %% @doc Parse an RFC1123 date. -spec rfc1123_date(binary()) -> any(). rfc1123_date(Data) -> wkday(Data, fun (<< ", ", Rest/binary >>, _WkDay) -> date1(Rest, fun (<< " ", Rest2/binary >>, Date) -> time(Rest2, fun (<< " GMT", Rest3/binary >>, Time) -> http_date_ret(Rest3, {Date, Time}); (_Any, _Time) -> {error, badarg} end); (_Any, _Date) -> {error, badarg} end); (_Any, _WkDay) -> {error, badarg} end). %% @doc Parse an RFC850 date. -spec rfc850_date(binary()) -> any(). %% From the RFC: %% HTTP/1.1 clients and caches SHOULD assume that an RFC-850 date %% which appears to be more than 50 years in the future is in fact %% in the past (this helps solve the "year 2000" problem). rfc850_date(Data) -> weekday(Data, fun (<< ", ", Rest/binary >>, _WeekDay) -> date2(Rest, fun (<< " ", Rest2/binary >>, Date) -> time(Rest2, fun (<< " GMT", Rest3/binary >>, Time) -> http_date_ret(Rest3, {Date, Time}); (_Any, _Time) -> {error, badarg} end); (_Any, _Date) -> {error, badarg} end); (_Any, _WeekDay) -> {error, badarg} end). %% @doc Parse an asctime date. -spec asctime_date(binary()) -> any(). asctime_date(Data) -> wkday(Data, fun (<< " ", Rest/binary >>, _WkDay) -> date3(Rest, fun (<< " ", Rest2/binary >>, PartialDate) -> time(Rest2, fun (<< " ", Rest3/binary >>, Time) -> asctime_year(Rest3, PartialDate, Time); (_Any, _Time) -> {error, badarg} end); (_Any, _PartialDate) -> {error, badarg} end); (_Any, _WkDay) -> {error, badarg1} end). -spec asctime_year(binary(), tuple(), tuple()) -> any(). asctime_year(<< Y1, Y2, Y3, Y4, Rest/binary >>, {Month, Day}, Time) when Y1 >= $0, Y1 =< $9, Y2 >= $0, Y2 =< $9, Y3 >= $0, Y3 =< $9, Y4 >= $0, Y4 =< $9 -> Year = (Y1 - $0) * 1000 + (Y2 - $0) * 100 + (Y3 - $0) * 10 + (Y4 - $0), http_date_ret(Rest, {{Year, Month, Day}, Time}). -spec http_date_ret(binary(), tuple()) -> any(). http_date_ret(Data, DateTime = {Date, _Time}) -> whitespace(Data, fun (<<>>) -> case calendar:valid_date(Date) of true -> DateTime; false -> {error, badarg} end; (_Any) -> {error, badarg} end). %% We never use it, pretty much just checks the wkday is right. -spec wkday(binary(), fun()) -> any(). wkday(<< WkDay:3/binary, Rest/binary >>, Fun) when WkDay =:= <<"Mon">>; WkDay =:= <<"Tue">>; WkDay =:= <<"Wed">>; WkDay =:= <<"Thu">>; WkDay =:= <<"Fri">>; WkDay =:= <<"Sat">>; WkDay =:= <<"Sun">> -> Fun(Rest, WkDay); wkday(_Any, _Fun) -> {error, badarg}. %% We never use it, pretty much just checks the weekday is right. -spec weekday(binary(), fun()) -> any(). weekday(<< "Monday", Rest/binary >>, Fun) -> Fun(Rest, <<"Monday">>); weekday(<< "Tuesday", Rest/binary >>, Fun) -> Fun(Rest, <<"Tuesday">>); weekday(<< "Wednesday", Rest/binary >>, Fun) -> Fun(Rest, <<"Wednesday">>); weekday(<< "Thursday", Rest/binary >>, Fun) -> Fun(Rest, <<"Thursday">>); weekday(<< "Friday", Rest/binary >>, Fun) -> Fun(Rest, <<"Friday">>); weekday(<< "Saturday", Rest/binary >>, Fun) -> Fun(Rest, <<"Saturday">>); weekday(<< "Sunday", Rest/binary >>, Fun) -> Fun(Rest, <<"Sunday">>); weekday(_Any, _Fun) -> {error, badarg}. -spec date1(binary(), fun()) -> any(). date1(<< D1, D2, " ", M:3/binary, " ", Y1, Y2, Y3, Y4, Rest/binary >>, Fun) when D1 >= $0, D1 =< $9, D2 >= $0, D2 =< $9, Y1 >= $0, Y1 =< $9, Y2 >= $0, Y2 =< $9, Y3 >= $0, Y3 =< $9, Y4 >= $0, Y4 =< $9 -> case month(M) of {error, badarg} -> {error, badarg}; Month -> Fun(Rest, { (Y1 - $0) * 1000 + (Y2 - $0) * 100 + (Y3 - $0) * 10 + (Y4 - $0), Month, (D1 - $0) * 10 + (D2 - $0) }) end; date1(_Data, _Fun) -> {error, badarg}. -spec date2(binary(), fun()) -> any(). date2(<< D1, D2, "-", M:3/binary, "-", Y1, Y2, Rest/binary >>, Fun) when D1 >= $0, D1 =< $9, D2 >= $0, D2 =< $9, Y1 >= $0, Y1 =< $9, Y2 >= $0, Y2 =< $9 -> case month(M) of {error, badarg} -> {error, badarg}; Month -> Year = (Y1 - $0) * 10 + (Y2 - $0), Year2 = case Year > 50 of true -> Year + 1900; false -> Year + 2000 end, Fun(Rest, { Year2, Month, (D1 - $0) * 10 + (D2 - $0) }) end; date2(_Data, _Fun) -> {error, badarg}. -spec date3(binary(), fun()) -> any(). date3(<< M:3/binary, " ", D1, D2, Rest/binary >>, Fun) when (D1 >= $0 andalso D1 =< $3) orelse D1 =:= $\s, D2 >= $0, D2 =< $9 -> case month(M) of {error, badarg} -> {error, badarg}; Month -> Day = case D1 of $\s -> D2 - $0; D1 -> (D1 - $0) * 10 + (D2 - $0) end, Fun(Rest, {Month, Day}) end; date3(_Data, _Fun) -> {error, badarg}. -spec month(<< _:24 >>) -> 1..12 | {error, badarg}. month(<<"Jan">>) -> 1; month(<<"Feb">>) -> 2; month(<<"Mar">>) -> 3; month(<<"Apr">>) -> 4; month(<<"May">>) -> 5; month(<<"Jun">>) -> 6; month(<<"Jul">>) -> 7; month(<<"Aug">>) -> 8; month(<<"Sep">>) -> 9; month(<<"Oct">>) -> 10; month(<<"Nov">>) -> 11; month(<<"Dec">>) -> 12; month(_Any) -> {error, badarg}. -spec time(binary(), fun()) -> any(). time(<< H1, H2, ":", M1, M2, ":", S1, S2, Rest/binary >>, Fun) when H1 >= $0, H1 =< $2, H2 >= $0, H2 =< $9, M1 >= $0, M1 =< $5, M2 >= $0, M2 =< $9, S1 >= $0, S1 =< $5, S2 >= $0, S2 =< $9 -> Hour = (H1 - $0) * 10 + (H2 - $0), case Hour < 24 of true -> Time = { Hour, (M1 - $0) * 10 + (M2 - $0), (S1 - $0) * 10 + (S2 - $0) }, Fun(Rest, Time); false -> {error, badarg} end. %% @doc Skip whitespace. -spec whitespace(binary(), fun()) -> any(). whitespace(<< C, Rest/binary >>, Fun) when C =:= $\s; C =:= $\t -> whitespace(Rest, Fun); whitespace(Data, Fun) -> Fun(Data). %% @doc Parse a list of digits as a non negative integer. -spec digits(binary()) -> non_neg_integer() | {error, badarg}. digits(Data) -> digits(Data, fun (Rest, I) -> whitespace(Rest, fun (<<>>) -> I; (_Rest2) -> {error, badarg} end) end). -spec digits(binary(), fun()) -> any(). digits(<< C, Rest/binary >>, Fun) when C >= $0, C =< $9 -> digits(Rest, Fun, C - $0); digits(_Data, _Fun) -> {error, badarg}. -spec digits(binary(), fun(), non_neg_integer()) -> any(). digits(<< C, Rest/binary >>, Fun, Acc) when C >= $0, C =< $9 -> digits(Rest, Fun, Acc * 10 + (C - $0)); digits(Data, Fun, Acc) -> Fun(Data, Acc). %% @doc Parse a list of case-insensitive alpha characters. %% %% Changes all characters to lowercase. -spec alpha(binary(), fun()) -> any(). alpha(Data, Fun) -> alpha(Data, Fun, <<>>). -spec alpha(binary(), fun(), binary()) -> any(). alpha(<<>>, Fun, Acc) -> Fun(<<>>, Acc); alpha(<< C, Rest/binary >>, Fun, Acc) when C >= $a andalso C =< $z; C >= $A andalso C =< $Z -> C2 = cowboy_bstr:char_to_lower(C), alpha(Rest, Fun, << Acc/binary, C2 >>); alpha(Data, Fun, Acc) -> Fun(Data, Acc). %% @doc Parse either a token or a quoted string. -spec word(binary(), fun()) -> any(). word(Data = << $", _/binary >>, Fun) -> quoted_string(Data, Fun); word(Data, Fun) -> token(Data, fun (_Rest, <<>>) -> {error, badarg}; (Rest, Token) -> Fun(Rest, Token) end). %% @doc Parse a case-insensitive token. %% %% Changes all characters to lowercase. -spec token_ci(binary(), fun()) -> any(). token_ci(Data, Fun) -> token(Data, Fun, ci, <<>>). %% @doc Parse a token. -spec token(binary(), fun()) -> any(). token(Data, Fun) -> token(Data, Fun, cs, <<>>). -spec token(binary(), fun(), ci | cs, binary()) -> any(). token(<<>>, Fun, _Case, Acc) -> Fun(<<>>, Acc); token(Data = << C, _Rest/binary >>, Fun, _Case, Acc) when C =:= $(; C =:= $); C =:= $<; C =:= $>; C =:= $@; C =:= $,; C =:= $;; C =:= $:; C =:= $\\; C =:= $"; C =:= $/; C =:= $[; C =:= $]; C =:= $?; C =:= $=; C =:= ${; C =:= $}; C =:= $\s; C =:= $\t; C < 32; C =:= 127 -> Fun(Data, Acc); token(<< C, Rest/binary >>, Fun, Case = ci, Acc) -> C2 = cowboy_bstr:char_to_lower(C), token(Rest, Fun, Case, << Acc/binary, C2 >>); token(<< C, Rest/binary >>, Fun, Case, Acc) -> token(Rest, Fun, Case, << Acc/binary, C >>). %% @doc Parse a quoted string. -spec quoted_string(binary(), fun()) -> any(). quoted_string(<< $", Rest/binary >>, Fun) -> quoted_string(Rest, Fun, <<>>). -spec quoted_string(binary(), fun(), binary()) -> any(). quoted_string(<<>>, _Fun, _Acc) -> {error, badarg}; quoted_string(<< $", Rest/binary >>, Fun, Acc) -> Fun(Rest, Acc); quoted_string(<< $\\, C, Rest/binary >>, Fun, Acc) -> quoted_string(Rest, Fun, << Acc/binary, C >>); quoted_string(<< C, Rest/binary >>, Fun, Acc) -> quoted_string(Rest, Fun, << Acc/binary, C >>). %% @doc Parse a quality value. -spec qvalue(binary(), fun()) -> any(). qvalue(<< $0, $., Rest/binary >>, Fun) -> qvalue(Rest, Fun, 0, 100); qvalue(<< $0, Rest/binary >>, Fun) -> Fun(Rest, 0); qvalue(<< $1, $., $0, $0, $0, Rest/binary >>, Fun) -> Fun(Rest, 1000); qvalue(<< $1, $., $0, $0, Rest/binary >>, Fun) -> Fun(Rest, 1000); qvalue(<< $1, $., $0, Rest/binary >>, Fun) -> Fun(Rest, 1000); qvalue(<< $1, Rest/binary >>, Fun) -> Fun(Rest, 1000); qvalue(_Data, _Fun) -> {error, badarg}. -spec qvalue(binary(), fun(), integer(), 1 | 10 | 100) -> any(). qvalue(Data, Fun, Q, 0) -> Fun(Data, Q); qvalue(<< C, Rest/binary >>, Fun, Q, M) when C >= $0, C =< $9 -> qvalue(Rest, Fun, Q + (C - $0) * M, M div 10); qvalue(Data, Fun, Q, _M) -> Fun(Data, Q). %% Interpretation. %% @doc Walk through a tokens list and return whether %% the connection is keepalive or closed. %% %% The connection token is expected to be lower-case. -spec connection_to_atom([binary()]) -> keepalive | close. connection_to_atom([]) -> keepalive; connection_to_atom([<<"keep-alive">>|_Tail]) -> keepalive; connection_to_atom([<<"close">>|_Tail]) -> close; connection_to_atom([_Any|Tail]) -> connection_to_atom(Tail). %% @doc Decode a URL encoded binary. %% @equiv urldecode(Bin, crash) -spec urldecode(binary()) -> binary(). urldecode(Bin) when is_binary(Bin) -> urldecode(Bin, <<>>, crash). %% @doc Decode a URL encoded binary. %% The second argument specifies how to handle percent characters that are not %% followed by two valid hex characters. Use `skip' to ignore such errors, %% if `crash' is used the function will fail with the reason `badarg'. -spec urldecode(binary(), crash | skip) -> binary(). urldecode(Bin, OnError) when is_binary(Bin) -> urldecode(Bin, <<>>, OnError). -spec urldecode(binary(), binary(), crash | skip) -> binary(). urldecode(<<$%, H, L, Rest/binary>>, Acc, OnError) -> G = unhex(H), M = unhex(L), if G =:= error; M =:= error -> case OnError of skip -> ok; crash -> erlang:error(badarg) end, urldecode(<>, <>, OnError); true -> urldecode(Rest, <>, OnError) end; urldecode(<<$%, Rest/binary>>, Acc, OnError) -> case OnError of skip -> ok; crash -> erlang:error(badarg) end, urldecode(Rest, <>, OnError); urldecode(<<$+, Rest/binary>>, Acc, OnError) -> urldecode(Rest, <>, OnError); urldecode(<>, Acc, OnError) -> urldecode(Rest, <>, OnError); urldecode(<<>>, Acc, _OnError) -> Acc. -spec unhex(byte()) -> byte() | error. unhex(C) when C >= $0, C =< $9 -> C - $0; unhex(C) when C >= $A, C =< $F -> C - $A + 10; unhex(C) when C >= $a, C =< $f -> C - $a + 10; unhex(_) -> error. %% @doc URL encode a string binary. %% @equiv urlencode(Bin, []) -spec urlencode(binary()) -> binary(). urlencode(Bin) -> urlencode(Bin, []). %% @doc URL encode a string binary. %% The `noplus' option disables the default behaviour of quoting space %% characters, `\s', as `+'. The `upper' option overrides the default behaviour %% of writing hex numbers using lowecase letters to using uppercase letters %% instead. -spec urlencode(binary(), [noplus|upper]) -> binary(). urlencode(Bin, Opts) -> Plus = not proplists:get_value(noplus, Opts, false), Upper = proplists:get_value(upper, Opts, false), urlencode(Bin, <<>>, Plus, Upper). urlencode(<>, Acc, P=Plus, U=Upper) -> if C >= $0, C =< $9 -> urlencode(Rest, <>, P, U); C >= $A, C =< $Z -> urlencode(Rest, <>, P, U); C >= $a, C =< $z -> urlencode(Rest, <>, P, U); C =:= $.; C =:= $-; C =:= $~; C =:= $_ -> urlencode(Rest, <>, P, U); C =:= $ , Plus -> urlencode(Rest, <>, P, U); true -> H = C band 16#F0 bsr 4, L = C band 16#0F, H1 = if Upper -> tohexu(H); true -> tohexl(H) end, L1 = if Upper -> tohexu(L); true -> tohexl(L) end, urlencode(Rest, <>, P, U) end; urlencode(<<>>, Acc, _Plus, _Upper) -> Acc. -spec tohexu(byte()) -> byte(). tohexu(C) when C < 10 -> $0 + C; tohexu(C) when C < 17 -> $A + C - 10. -spec tohexl(byte()) -> byte(). tohexl(C) when C < 10 -> $0 + C; tohexl(C) when C < 17 -> $a + C - 10. %% Tests. -ifdef(TEST). nonempty_charset_list_test_() -> %% {Value, Result} Tests = [ {<<>>, {error, badarg}}, {<<"iso-8859-5, unicode-1-1;q=0.8">>, [ {<<"iso-8859-5">>, 1000}, {<<"unicode-1-1">>, 800} ]} ], [{V, fun() -> R = nonempty_list(V, fun conneg/2) end} || {V, R} <- Tests]. nonempty_language_range_list_test_() -> %% {Value, Result} Tests = [ {<<"da, en-gb;q=0.8, en;q=0.7">>, [ {<<"da">>, 1000}, {<<"en-gb">>, 800}, {<<"en">>, 700} ]}, {<<"en, en-US, en-cockney, i-cherokee, x-pig-latin">>, [ {<<"en">>, 1000}, {<<"en-us">>, 1000}, {<<"en-cockney">>, 1000}, {<<"i-cherokee">>, 1000}, {<<"x-pig-latin">>, 1000} ]} ], [{V, fun() -> R = nonempty_list(V, fun language_range/2) end} || {V, R} <- Tests]. nonempty_token_list_test_() -> %% {Value, Result} Tests = [ {<<>>, {error, badarg}}, {<<" ">>, {error, badarg}}, {<<" , ">>, {error, badarg}}, {<<",,,">>, {error, badarg}}, {<<"a b">>, {error, badarg}}, {<<"a , , , ">>, [<<"a">>]}, {<<" , , , a">>, [<<"a">>]}, {<<"a, , b">>, [<<"a">>, <<"b">>]}, {<<"close">>, [<<"close">>]}, {<<"keep-alive, upgrade">>, [<<"keep-alive">>, <<"upgrade">>]} ], [{V, fun() -> R = nonempty_list(V, fun token/2) end} || {V, R} <- Tests]. media_range_list_test_() -> %% {Tokens, Result} Tests = [ {<<"audio/*; q=0.2, audio/basic">>, [ {{<<"audio">>, <<"*">>, []}, 200, []}, {{<<"audio">>, <<"basic">>, []}, 1000, []} ]}, {<<"text/plain; q=0.5, text/html, " "text/x-dvi; q=0.8, text/x-c">>, [ {{<<"text">>, <<"plain">>, []}, 500, []}, {{<<"text">>, <<"html">>, []}, 1000, []}, {{<<"text">>, <<"x-dvi">>, []}, 800, []}, {{<<"text">>, <<"x-c">>, []}, 1000, []} ]}, {<<"text/*, text/html, text/html;level=1, */*">>, [ {{<<"text">>, <<"*">>, []}, 1000, []}, {{<<"text">>, <<"html">>, []}, 1000, []}, {{<<"text">>, <<"html">>, [{<<"level">>, <<"1">>}]}, 1000, []}, {{<<"*">>, <<"*">>, []}, 1000, []} ]}, {<<"text/*;q=0.3, text/html;q=0.7, text/html;level=1, " "text/html;level=2;q=0.4, */*;q=0.5">>, [ {{<<"text">>, <<"*">>, []}, 300, []}, {{<<"text">>, <<"html">>, []}, 700, []}, {{<<"text">>, <<"html">>, [{<<"level">>, <<"1">>}]}, 1000, []}, {{<<"text">>, <<"html">>, [{<<"level">>, <<"2">>}]}, 400, []}, {{<<"*">>, <<"*">>, []}, 500, []} ]}, {<<"text/html;level=1;quoted=\"hi hi hi\";" "q=0.123;standalone;complex=gits, text/plain">>, [ {{<<"text">>, <<"html">>, [{<<"level">>, <<"1">>}, {<<"quoted">>, <<"hi hi hi">>}]}, 123, [<<"standalone">>, {<<"complex">>, <<"gits">>}]}, {{<<"text">>, <<"plain">>, []}, 1000, []} ]} ], [{V, fun() -> R = list(V, fun media_range/2) end} || {V, R} <- Tests]. entity_tag_match_test_() -> %% {Tokens, Result} Tests = [ {<<"\"xyzzy\"">>, [{strong, <<"xyzzy">>}]}, {<<"\"xyzzy\", W/\"r2d2xxxx\", \"c3piozzzz\"">>, [{strong, <<"xyzzy">>}, {weak, <<"r2d2xxxx">>}, {strong, <<"c3piozzzz">>}]}, {<<"*">>, '*'} ], [{V, fun() -> R = entity_tag_match(V) end} || {V, R} <- Tests]. http_date_test_() -> %% {Tokens, Result} Tests = [ {<<"Sun, 06 Nov 1994 08:49:37 GMT">>, {{1994, 11, 6}, {8, 49, 37}}}, {<<"Sunday, 06-Nov-94 08:49:37 GMT">>, {{1994, 11, 6}, {8, 49, 37}}}, {<<"Sun Nov 6 08:49:37 1994">>, {{1994, 11, 6}, {8, 49, 37}}} ], [{V, fun() -> R = http_date(V) end} || {V, R} <- Tests]. rfc1123_date_test_() -> %% {Tokens, Result} Tests = [ {<<"Sun, 06 Nov 1994 08:49:37 GMT">>, {{1994, 11, 6}, {8, 49, 37}}} ], [{V, fun() -> R = rfc1123_date(V) end} || {V, R} <- Tests]. rfc850_date_test_() -> %% {Tokens, Result} Tests = [ {<<"Sunday, 06-Nov-94 08:49:37 GMT">>, {{1994, 11, 6}, {8, 49, 37}}} ], [{V, fun() -> R = rfc850_date(V) end} || {V, R} <- Tests]. asctime_date_test_() -> %% {Tokens, Result} Tests = [ {<<"Sun Nov 6 08:49:37 1994">>, {{1994, 11, 6}, {8, 49, 37}}} ], [{V, fun() -> R = asctime_date(V) end} || {V, R} <- Tests]. connection_to_atom_test_() -> %% {Tokens, Result} Tests = [ {[<<"close">>], close}, {[<<"keep-alive">>], keepalive}, {[<<"keep-alive">>, <<"upgrade">>], keepalive} ], [{lists:flatten(io_lib:format("~p", [T])), fun() -> R = connection_to_atom(T) end} || {T, R} <- Tests]. content_type_test_() -> %% {ContentType, Result} Tests = [ {<<"text/plain; charset=iso-8859-4">>, {<<"text">>, <<"plain">>, [{<<"charset">>, <<"iso-8859-4">>}]}}, {<<"multipart/form-data \t;Boundary=\"MultipartIsUgly\"">>, {<<"multipart">>, <<"form-data">>, [ {<<"boundary">>, <<"MultipartIsUgly">>} ]}}, {<<"foo/bar; one=FirstParam; two=SecondParam">>, {<<"foo">>, <<"bar">>, [ {<<"one">>, <<"FirstParam">>}, {<<"two">>, <<"SecondParam">>} ]}} ], [{V, fun () -> R = content_type(V) end} || {V, R} <- Tests]. digits_test_() -> %% {Digits, Result} Tests = [ {<<"42 ">>, 42}, {<<"69\t">>, 69}, {<<"1337">>, 1337} ], [{V, fun() -> R = digits(V) end} || {V, R} <- Tests]. urldecode_test_() -> U = fun urldecode/2, [?_assertEqual(<<" ">>, U(<<"%20">>, crash)), ?_assertEqual(<<" ">>, U(<<"+">>, crash)), ?_assertEqual(<<0>>, U(<<"%00">>, crash)), ?_assertEqual(<<255>>, U(<<"%fF">>, crash)), ?_assertEqual(<<"123">>, U(<<"123">>, crash)), ?_assertEqual(<<"%i5">>, U(<<"%i5">>, skip)), ?_assertEqual(<<"%5">>, U(<<"%5">>, skip)), ?_assertError(badarg, U(<<"%i5">>, crash)), ?_assertError(badarg, U(<<"%5">>, crash)) ]. urlencode_test_() -> U = fun urlencode/2, [?_assertEqual(<<"%ff%00">>, U(<<255,0>>, [])), ?_assertEqual(<<"%FF%00">>, U(<<255,0>>, [upper])), ?_assertEqual(<<"+">>, U(<<" ">>, [])), ?_assertEqual(<<"%20">>, U(<<" ">>, [noplus])), ?_assertEqual(<<"aBc">>, U(<<"aBc">>, [])), ?_assertEqual(<<".-~_">>, U(<<".-~_">>, [])), ?_assertEqual(<<"%ff+">>, urlencode(<<255, " ">>)) ]. -endif. rabbitmq-server-3.2.4/plugins-src/cowboy-wrapper/cowboy-git/src/cowboy.erl0000644000000000000000000000777712305126066025454 0ustar rootroot%% Copyright (c) 2011, Loïc Hoguin %% %% Permission to use, copy, modify, and/or distribute this software for any %% purpose with or without fee is hereby granted, provided that the above %% copyright notice and this permission notice appear in all copies. %% %% THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES %% WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF %% MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR %% ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES %% WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN %% ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF %% OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. %% @doc Cowboy API to start and stop listeners. -module(cowboy). -export([start_listener/6, stop_listener/1, child_spec/6, accept_ack/1]). %% @doc Start a listener for the given transport and protocol. %% %% A listener is effectively a pool of NbAcceptors acceptors. %% Acceptors accept connections on the given Transport and forward %% requests to the given Protocol handler. Both transport and protocol %% modules can be given options through the TransOpts and the %% ProtoOpts arguments. Available options are documented in the %% listen transport function and in the protocol module of your choice. %% %% All acceptor and request processes are supervised by the listener. %% %% It is recommended to set a large enough number of acceptors to improve %% performance. The exact number depends of course on your hardware, on the %% protocol used and on the number of expected simultaneous connections. %% %% The Transport option max_connections allows you to define %% the maximum number of simultaneous connections for this listener. It defaults %% to 1024. See cowboy_listener for more details on limiting the number %% of connections. %% %% Although Cowboy includes a cowboy_http_protocol handler, other %% handlers can be created for different protocols like IRC, FTP and more. %% %% Ref can be used to stop the listener later on. -spec start_listener(any(), non_neg_integer(), module(), any(), module(), any()) -> {ok, pid()}. start_listener(Ref, NbAcceptors, Transport, TransOpts, Protocol, ProtoOpts) when is_integer(NbAcceptors) andalso is_atom(Transport) andalso is_atom(Protocol) -> supervisor:start_child(cowboy_sup, child_spec(Ref, NbAcceptors, Transport, TransOpts, Protocol, ProtoOpts)). %% @doc Stop a listener identified by Ref. %% @todo Currently request processes aren't terminated with the listener. -spec stop_listener(any()) -> ok | {error, not_found}. stop_listener(Ref) -> case supervisor:terminate_child(cowboy_sup, {cowboy_listener_sup, Ref}) of ok -> supervisor:delete_child(cowboy_sup, {cowboy_listener_sup, Ref}); {error, Reason} -> {error, Reason} end. %% @doc Return a child spec suitable for embedding. %% %% When you want to embed cowboy in another application, you can use this %% function to create a ChildSpec suitable for use in a supervisor. %% The parameters are the same as in start_listener/6 but rather %% than hooking the listener to the cowboy internal supervisor, it just returns %% the spec. -spec child_spec(any(), non_neg_integer(), module(), any(), module(), any()) -> supervisor:child_spec(). child_spec(Ref, NbAcceptors, Transport, TransOpts, Protocol, ProtoOpts) when is_integer(NbAcceptors) andalso is_atom(Transport) andalso is_atom(Protocol) -> {{cowboy_listener_sup, Ref}, {cowboy_listener_sup, start_link, [ NbAcceptors, Transport, TransOpts, Protocol, ProtoOpts ]}, permanent, 5000, supervisor, [cowboy_listener_sup]}. %% @doc Acknowledge the accepted connection. %% %% Effectively used to make sure the socket control has been given to %% the protocol process before starting to use it. -spec accept_ack(pid()) -> ok. accept_ack(ListenerPid) -> receive {shoot, ListenerPid} -> ok end. rabbitmq-server-3.2.4/plugins-src/cowboy-wrapper/cowboy-git/doc/0000755000000000000000000000000012305126066023402 5ustar rootrootrabbitmq-server-3.2.4/plugins-src/cowboy-wrapper/cowboy-git/doc/overview.edoc0000644000000000000000000000017512305126066026107 0ustar rootroot@author Loïc Hoguin @copyright 2011 Loïc Hoguin @version HEAD @title Small, fast, modular HTTP server. rabbitmq-server-3.2.4/plugins-src/cowboy-wrapper/cowboy-git/test/0000755000000000000000000000000012305126066023614 5ustar rootrootrabbitmq-server-3.2.4/plugins-src/cowboy-wrapper/cowboy-git/test/http_handler_long_polling.erl0000644000000000000000000000106612305126066031542 0ustar rootroot%% Feel free to use, reuse and abuse the code in this file. -module(http_handler_long_polling). -behaviour(cowboy_http_handler). -export([init/3, handle/2, info/3, terminate/2]). init({_Transport, http}, Req, _Opts) -> erlang:send_after(500, self(), timeout), {loop, Req, 9, 5000, hibernate}. handle(_Req, _State) -> exit(badarg). info(timeout, Req, 0) -> {ok, Req2} = cowboy_http_req:reply(102, Req), {ok, Req2, 0}; info(timeout, Req, State) -> erlang:send_after(500, self(), timeout), {loop, Req, State - 1, hibernate}. terminate(_Req, _State) -> ok. rabbitmq-server-3.2.4/plugins-src/cowboy-wrapper/cowboy-git/test/http_handler_set_resp.erl0000644000000000000000000000203412305126066030677 0ustar rootroot%% Feel free to use, reuse and abuse the code in this file. -module(http_handler_set_resp). -behaviour(cowboy_http_handler). -export([init/3, handle/2, terminate/2]). init({_Transport, http}, Req, Opts) -> Headers = proplists:get_value(headers, Opts, []), Body = proplists:get_value(body, Opts, <<"http_handler_set_resp">>), {ok, Req2} = lists:foldl(fun({Name, Value}, {ok, R}) -> cowboy_http_req:set_resp_header(Name, Value, R) end, {ok, Req}, Headers), {ok, Req3} = cowboy_http_req:set_resp_body(Body, Req2), {ok, Req4} = cowboy_http_req:set_resp_header( <<"X-Cowboy-Test">>, <<"ok">>, Req3), {ok, Req5} = cowboy_http_req:set_resp_cookie( <<"cake">>, <<"lie">>, [], Req4), {ok, Req5, undefined}. handle(Req, State) -> case cowboy_http_req:has_resp_header(<<"X-Cowboy-Test">>, Req) of false -> {ok, Req, State}; true -> case cowboy_http_req:has_resp_body(Req) of false -> {ok, Req, State}; true -> {ok, Req2} = cowboy_http_req:reply(200, Req), {ok, Req2, State} end end. terminate(_Req, _State) -> ok. rabbitmq-server-3.2.4/plugins-src/cowboy-wrapper/cowboy-git/test/proper_SUITE.erl0000644000000000000000000000243712305126066026606 0ustar rootroot%% Copyright (c) 2011, Loïc Hoguin %% %% Permission to use, copy, modify, and/or distribute this software for any %% purpose with or without fee is hereby granted, provided that the above %% copyright notice and this permission notice appear in all copies. %% %% THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES %% WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF %% MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR %% ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES %% WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN %% ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF %% OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -module(proper_SUITE). -include_lib("common_test/include/ct.hrl"). -export([all/0, groups/0]). %% ct. -export([dispatcher_split_host/1]). %% cowboy_dispatcher. %% ct. all() -> [{group, dispatcher}]. groups() -> [{dispatcher, [], [dispatcher_split_host]}]. %% cowboy_dispatcher. dispatcher_split_host(_Config) -> true = proper:quickcheck(dispatcher_prop:prop_split_host_symmetric(), [{on_output, fun(Format, Data) -> io:format(user, Format, Data), %% Console. io:format(Format, Data) %% Logs. end}]). rabbitmq-server-3.2.4/plugins-src/cowboy-wrapper/cowboy-git/test/ws_timeout_hibernate_handler.erl0000644000000000000000000000134712305126066032242 0ustar rootroot%% Feel free to use, reuse and abuse the code in this file. -module(ws_timeout_hibernate_handler). -behaviour(cowboy_http_handler). -behaviour(cowboy_http_websocket_handler). -export([init/3, handle/2, terminate/2]). -export([websocket_init/3, websocket_handle/3, websocket_info/3, websocket_terminate/3]). init(_Any, _Req, _Opts) -> {upgrade, protocol, cowboy_http_websocket}. handle(_Req, _State) -> exit(badarg). terminate(_Req, _State) -> exit(badarg). websocket_init(_TransportName, Req, _Opts) -> {ok, Req, undefined, 1000, hibernate}. websocket_handle(_Frame, Req, State) -> {ok, Req, State, hibernate}. websocket_info(_Info, Req, State) -> {ok, Req, State, hibernate}. websocket_terminate(_Reason, _Req, _State) -> ok. rabbitmq-server-3.2.4/plugins-src/cowboy-wrapper/cowboy-git/test/http_SUITE.erl0000644000000000000000000005342312305126066026257 0ustar rootroot%% Copyright (c) 2011, Loïc Hoguin %% Copyright (c) 2011, Anthony Ramine %% %% Permission to use, copy, modify, and/or distribute this software for any %% purpose with or without fee is hereby granted, provided that the above %% copyright notice and this permission notice appear in all copies. %% %% THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES %% WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF %% MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR %% ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES %% WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN %% ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF %% OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -module(http_SUITE). -include_lib("common_test/include/ct.hrl"). -export([all/0, groups/0, init_per_suite/1, end_per_suite/1, init_per_group/2, end_per_group/2]). %% ct. -export([chunked_response/1, headers_dupe/1, headers_huge/1, keepalive_nl/1, max_keepalive/1, nc_rand/1, nc_zero/1, pipeline/1, raw/1, set_resp_header/1, set_resp_overwrite/1, set_resp_body/1, stream_body_set_resp/1, response_as_req/1, static_mimetypes_function/1, static_attribute_etag/1, static_function_etag/1, multipart/1]). %% http. -export([http_200/1, http_404/1, handler_errors/1, file_200/1, file_403/1, dir_403/1, file_404/1, file_400/1]). %% http and https. -export([http_10_hostless/1]). %% misc. -export([rest_simple/1, rest_keepalive/1, rest_keepalive_post/1]). %% rest. %% ct. all() -> [{group, http}, {group, https}, {group, misc}, {group, rest}]. groups() -> BaseTests = [http_200, http_404, handler_errors, file_200, file_403, dir_403, file_404, file_400], [{http, [], [chunked_response, headers_dupe, headers_huge, keepalive_nl, max_keepalive, nc_rand, nc_zero, pipeline, raw, set_resp_header, set_resp_overwrite, set_resp_body, response_as_req, stream_body_set_resp, static_mimetypes_function, static_attribute_etag, static_function_etag, multipart] ++ BaseTests}, {https, [], BaseTests}, {misc, [], [http_10_hostless]}, {rest, [], [rest_simple, rest_keepalive, rest_keepalive_post]}]. init_per_suite(Config) -> application:start(inets), application:start(cowboy), Config. end_per_suite(_Config) -> application:stop(cowboy), application:stop(inets), ok. init_per_group(http, Config) -> Port = 33080, Config1 = init_static_dir(Config), cowboy:start_listener(http, 100, cowboy_tcp_transport, [{port, Port}], cowboy_http_protocol, [{max_keepalive, 50}, {dispatch, init_http_dispatch(Config1)}] ), [{scheme, "http"}, {port, Port}|Config1]; init_per_group(https, Config) -> Port = 33081, Config1 = init_static_dir(Config), application:start(crypto), application:start(public_key), application:start(ssl), DataDir = ?config(data_dir, Config), cowboy:start_listener(https, 100, cowboy_ssl_transport, [ {port, Port}, {certfile, DataDir ++ "cert.pem"}, {keyfile, DataDir ++ "key.pem"}, {password, "cowboy"}], cowboy_http_protocol, [{dispatch, init_https_dispatch(Config1)}] ), [{scheme, "https"}, {port, Port}|Config1]; init_per_group(misc, Config) -> Port = 33082, cowboy:start_listener(misc, 100, cowboy_tcp_transport, [{port, Port}], cowboy_http_protocol, [{dispatch, [{'_', [ {[], http_handler, []} ]}]}]), [{port, Port}|Config]; init_per_group(rest, Config) -> Port = 33083, cowboy:start_listener(reset, 100, cowboy_tcp_transport, [{port, Port}], cowboy_http_protocol, [{dispatch, [{'_', [ {[<<"simple">>], rest_simple_resource, []}, {[<<"forbidden_post">>], rest_forbidden_resource, [true]}, {[<<"simple_post">>], rest_forbidden_resource, [false]} ]}]}]), [{port, Port}|Config]. end_per_group(https, Config) -> cowboy:stop_listener(https), application:stop(ssl), application:stop(public_key), application:stop(crypto), end_static_dir(Config), ok; end_per_group(http, Config) -> cowboy:stop_listener(http), end_static_dir(Config); end_per_group(Listener, _Config) -> cowboy:stop_listener(Listener), ok. %% Dispatch configuration. init_http_dispatch(Config) -> [ {[<<"localhost">>], [ {[<<"chunked_response">>], chunked_handler, []}, {[<<"init_shutdown">>], http_handler_init_shutdown, []}, {[<<"long_polling">>], http_handler_long_polling, []}, {[<<"headers">>, <<"dupe">>], http_handler, [{headers, [{<<"Connection">>, <<"close">>}]}]}, {[<<"set_resp">>, <<"header">>], http_handler_set_resp, [{headers, [{<<"Vary">>, <<"Accept">>}]}]}, {[<<"set_resp">>, <<"overwrite">>], http_handler_set_resp, [{headers, [{<<"Server">>, <<"DesireDrive/1.0">>}]}]}, {[<<"set_resp">>, <<"body">>], http_handler_set_resp, [{body, <<"A flameless dance does not equal a cycle">>}]}, {[<<"stream_body">>, <<"set_resp">>], http_handler_stream_body, [{reply, set_resp}, {body, <<"stream_body_set_resp">>}]}, {[<<"static">>, '...'], cowboy_http_static, [{directory, ?config(static_dir, Config)}, {mimetypes, [{<<".css">>, [<<"text/css">>]}]}]}, {[<<"static_mimetypes_function">>, '...'], cowboy_http_static, [{directory, ?config(static_dir, Config)}, {mimetypes, {fun(Path, data) when is_binary(Path) -> [<<"text/html">>] end, data}}]}, {[<<"handler_errors">>], http_handler_errors, []}, {[<<"static_attribute_etag">>, '...'], cowboy_http_static, [{directory, ?config(static_dir, Config)}, {etag, {attributes, [filepath, filesize, inode, mtime]}}]}, {[<<"static_function_etag">>, '...'], cowboy_http_static, [{directory, ?config(static_dir, Config)}, {etag, {fun static_function_etag/2, etag_data}}]}, {[<<"multipart">>], http_handler_multipart, []}, {[], http_handler, []} ]} ]. init_https_dispatch(Config) -> init_http_dispatch(Config). init_static_dir(Config) -> Dir = filename:join(?config(priv_dir, Config), "static"), Level1 = fun(Name) -> filename:join(Dir, Name) end, ok = file:make_dir(Dir), ok = file:write_file(Level1("test_file"), "test_file\n"), ok = file:write_file(Level1("test_file.css"), "test_file.css\n"), ok = file:write_file(Level1("test_noread"), "test_noread\n"), ok = file:change_mode(Level1("test_noread"), 8#0333), ok = file:write_file(Level1("test.html"), "test.html\n"), ok = file:make_dir(Level1("test_dir")), [{static_dir, Dir}|Config]. end_static_dir(Config) -> Dir = ?config(static_dir, Config), Level1 = fun(Name) -> filename:join(Dir, Name) end, ok = file:delete(Level1("test_file")), ok = file:delete(Level1("test_file.css")), ok = file:delete(Level1("test_noread")), ok = file:delete(Level1("test.html")), ok = file:del_dir(Level1("test_dir")), ok = file:del_dir(Dir), Config. %% http. chunked_response(Config) -> {ok, {{"HTTP/1.1", 200, "OK"}, _Headers, "chunked_handler\r\nworks fine!"}} = httpc:request(build_url("/chunked_response", Config)). headers_dupe(Config) -> {port, Port} = lists:keyfind(port, 1, Config), {ok, Socket} = gen_tcp:connect("localhost", Port, [binary, {active, false}, {packet, raw}]), ok = gen_tcp:send(Socket, "GET /headers/dupe HTTP/1.1\r\n" "Host: localhost\r\nConnection: keep-alive\r\n\r\n"), {ok, Data} = gen_tcp:recv(Socket, 0, 6000), {_Start, _Length} = binary:match(Data, <<"Connection: close">>), nomatch = binary:match(Data, <<"Connection: keep-alive">>), {error, closed} = gen_tcp:recv(Socket, 0, 1000). headers_huge(Config) -> Cookie = lists:flatten(["whatever_man_biiiiiiiiiiiig_cookie_me_want_77=" "Wed Apr 06 2011 10:38:52 GMT-0500 (CDT)" || _N <- lists:seq(1, 40)]), {_Packet, 200} = raw_req(["GET / HTTP/1.0\r\nHost: localhost\r\n" "Set-Cookie: ", Cookie, "\r\n\r\n"], Config). keepalive_nl(Config) -> {port, Port} = lists:keyfind(port, 1, Config), {ok, Socket} = gen_tcp:connect("localhost", Port, [binary, {active, false}, {packet, raw}]), ok = keepalive_nl_loop(Socket, 10), ok = gen_tcp:close(Socket). keepalive_nl_loop(_Socket, 0) -> ok; keepalive_nl_loop(Socket, N) -> ok = gen_tcp:send(Socket, "GET / HTTP/1.1\r\n" "Host: localhost\r\nConnection: keep-alive\r\n\r\n"), {ok, Data} = gen_tcp:recv(Socket, 0, 6000), {0, 12} = binary:match(Data, <<"HTTP/1.1 200">>), nomatch = binary:match(Data, <<"Connection: close">>), ok = gen_tcp:send(Socket, "\r\n"), %% extra nl keepalive_nl_loop(Socket, N - 1). max_keepalive(Config) -> {port, Port} = lists:keyfind(port, 1, Config), {ok, Socket} = gen_tcp:connect("localhost", Port, [binary, {active, false}, {packet, raw}]), ok = max_keepalive_loop(Socket, 50), {error, closed} = gen_tcp:recv(Socket, 0, 1000). max_keepalive_loop(_Socket, 0) -> ok; max_keepalive_loop(Socket, N) -> ok = gen_tcp:send(Socket, "GET / HTTP/1.1\r\n" "Host: localhost\r\nConnection: keep-alive\r\n\r\n"), {ok, Data} = gen_tcp:recv(Socket, 0, 6000), {0, 12} = binary:match(Data, <<"HTTP/1.1 200">>), case N of 1 -> {_, _} = binary:match(Data, <<"Connection: close">>); N -> nomatch = binary:match(Data, <<"Connection: close">>) end, keepalive_nl_loop(Socket, N - 1). multipart(Config) -> Url = build_url("/multipart", Config), Body = << "This is a preamble." "\r\n--OHai\r\nX-Name:answer\r\n\r\n42" "\r\n--OHai\r\nServer:Cowboy\r\n\r\nIt rocks!\r\n" "\r\n--OHai--" "This is an epiloque." >>, Request = {Url, [], "multipart/x-makes-no-sense; boundary=OHai", Body}, {ok, {{"HTTP/1.1", 200, "OK"}, _Headers, Response}} = httpc:request(post, Request, [], [{body_format, binary}]), Parts = binary_to_term(Response), Parts = [ {[{<<"X-Name">>, <<"answer">>}], <<"42">>}, {[{'Server', <<"Cowboy">>}], <<"It rocks!\r\n">>} ]. nc_rand(Config) -> nc_reqs(Config, "/dev/urandom"). nc_zero(Config) -> nc_reqs(Config, "/dev/zero"). nc_reqs(Config, Input) -> Cat = os:find_executable("cat"), Nc = os:find_executable("nc"), case {Cat, Nc} of {false, _} -> {skip, {notfound, cat}}; {_, false} -> {skip, {notfound, nc}}; _Good -> %% Throw garbage at the server then check if it's still up. {port, Port} = lists:keyfind(port, 1, Config), [nc_run_req(Port, Input) || _N <- lists:seq(1, 100)], Packet = "GET / HTTP/1.0\r\nHost: localhost\r\n\r\n", {Packet, 200} = raw_req(Packet, Config) end. nc_run_req(Port, Input) -> os:cmd("cat " ++ Input ++ " | nc localhost " ++ integer_to_list(Port)). pipeline(Config) -> {port, Port} = lists:keyfind(port, 1, Config), {ok, Socket} = gen_tcp:connect("localhost", Port, [binary, {active, false}, {packet, raw}]), ok = gen_tcp:send(Socket, "GET / HTTP/1.1\r\nHost: localhost\r\nConnection: keep-alive\r\n\r\n" "GET / HTTP/1.1\r\nHost: localhost\r\nConnection: keep-alive\r\n\r\n" "GET / HTTP/1.1\r\nHost: localhost\r\nConnection: keep-alive\r\n\r\n" "GET / HTTP/1.1\r\nHost: localhost\r\nConnection: keep-alive\r\n\r\n" "GET / HTTP/1.1\r\nHost: localhost\r\nConnection: close\r\n\r\n"), Data = pipeline_recv(Socket, <<>>), Reqs = binary:split(Data, << "\r\n\r\nhttp_handler" >>, [global, trim]), 5 = length(Reqs), pipeline_check(Reqs). pipeline_check([]) -> ok; pipeline_check([Req|Tail]) -> << "HTTP/1.1 200", _Rest/bits >> = Req, pipeline_check(Tail). pipeline_recv(Socket, SoFar) -> case gen_tcp:recv(Socket, 0, 6000) of {ok, Data} -> pipeline_recv(Socket, << SoFar/binary, Data/binary >>); {error, closed} -> ok = gen_tcp:close(Socket), SoFar end. raw_req(Packet, Config) -> {port, Port} = lists:keyfind(port, 1, Config), {ok, Socket} = gen_tcp:connect("localhost", Port, [binary, {active, false}, {packet, raw}]), ok = gen_tcp:send(Socket, Packet), Res = case gen_tcp:recv(Socket, 0, 6000) of {ok, << "HTTP/1.1 ", Str:24/bits, _Rest/bits >>} -> list_to_integer(binary_to_list(Str)); {error, Reason} -> Reason end, gen_tcp:close(Socket), {Packet, Res}. %% Send a raw request. Return the response code and the full response. raw_resp(Request, Config) -> {port, Port} = lists:keyfind(port, 1, Config), Transport = case ?config(scheme, Config) of "http" -> gen_tcp; "https" -> ssl end, {ok, Socket} = Transport:connect("localhost", Port, [binary, {active, false}, {packet, raw}]), ok = Transport:send(Socket, Request), {StatusCode, Response} = case recv_loop(Transport, Socket, <<>>) of {ok, << "HTTP/1.1 ", Str:24/bits, _Rest/bits >> = Bin} -> {list_to_integer(binary_to_list(Str)), Bin}; {ok, Bin} -> {badresp, Bin}; {error, Reason} -> {Reason, <<>>} end, Transport:close(Socket), {Response, StatusCode}. recv_loop(Transport, Socket, Acc) -> case Transport:recv(Socket, 0, 6000) of {ok, Data} -> recv_loop(Transport, Socket, <>); {error, closed} -> ok = Transport:close(Socket), {ok, Acc}; {error, Reason} -> {error, Reason} end. raw(Config) -> Huge = [$0 || _N <- lists:seq(1, 5000)], Tests = [ {"\r\n\r\n\r\n\r\n\r\nGET / HTTP/1.1\r\nHost: localhost\r\n\r\n", 200}, {"\n", 400}, {"Garbage\r\n\r\n", 400}, {"\r\n\r\n\r\n\r\n\r\n\r\n", 400}, {"GET / HTTP/1.1\r\nHost: dev-extend.eu\r\n\r\n", 400}, {"", closed}, {"\r\n", closed}, {"\r\n\r\n", closed}, {"GET / HTTP/1.1", closed}, {"GET / HTTP/1.1\r\n", 408}, {"GET / HTTP/1.1\r\nHost: localhost", 408}, {"GET / HTTP/1.1\r\nHost: localhost\r\n", 408}, {"GET / HTTP/1.1\r\nHost: localhost\r\n\r", 408}, {"GET http://localhost/ HTTP/1.1\r\n\r\n", 501}, {"GET / HTTP/1.2\r\nHost: localhost\r\n\r\n", 505}, {"GET /init_shutdown HTTP/1.1\r\nHost: localhost\r\n\r\n", 666}, {"GET /long_polling HTTP/1.1\r\nHost: localhost\r\n\r\n", 102}, {Huge, 413}, {"GET / HTTP/1.1\r\n" ++ Huge, 413} ], [{Packet, StatusCode} = raw_req(Packet, Config) || {Packet, StatusCode} <- Tests]. set_resp_header(Config) -> {port, Port} = lists:keyfind(port, 1, Config), {ok, Socket} = gen_tcp:connect("localhost", Port, [binary, {active, false}, {packet, raw}]), ok = gen_tcp:send(Socket, "GET /set_resp/header HTTP/1.1\r\n" "Host: localhost\r\nConnection: close\r\n\r\n"), {ok, Data} = gen_tcp:recv(Socket, 0, 6000), {_, _} = binary:match(Data, <<"Vary: Accept">>), {_, _} = binary:match(Data, <<"Set-Cookie: ">>). set_resp_overwrite(Config) -> {port, Port} = lists:keyfind(port, 1, Config), {ok, Socket} = gen_tcp:connect("localhost", Port, [binary, {active, false}, {packet, raw}]), ok = gen_tcp:send(Socket, "GET /set_resp/overwrite HTTP/1.1\r\n" "Host: localhost\r\nConnection: close\r\n\r\n"), {ok, Data} = gen_tcp:recv(Socket, 0, 6000), {_Start, _Length} = binary:match(Data, <<"Server: DesireDrive/1.0">>). set_resp_body(Config) -> {port, Port} = lists:keyfind(port, 1, Config), {ok, Socket} = gen_tcp:connect("localhost", Port, [binary, {active, false}, {packet, raw}]), ok = gen_tcp:send(Socket, "GET /set_resp/body HTTP/1.1\r\n" "Host: localhost\r\nConnection: close\r\n\r\n"), {ok, Data} = gen_tcp:recv(Socket, 0, 6000), {_Start, _Length} = binary:match(Data, <<"\r\n\r\n" "A flameless dance does not equal a cycle">>). response_as_req(Config) -> Packet = "HTTP/1.0 302 Found Location: http://www.google.co.il/ Cache-Control: private Content-Type: text/html; charset=UTF-8 Set-Cookie: PREF=ID=568f67013d4a7afa:FF=0:TM=1323014101:LM=1323014101:S=XqctDWC65MzKT0zC; expires=Tue, 03-Dec-2013 15:55:01 GMT; path=/; domain=.google.com Date: Sun, 04 Dec 2011 15:55:01 GMT Server: gws Content-Length: 221 X-XSS-Protection: 1; mode=block X-Frame-Options: SAMEORIGIN 302 Moved

    302 Moved

    The document has moved here. ", {Packet, 400} = raw_req(Packet, Config). stream_body_set_resp(Config) -> {Packet, 200} = raw_resp( "GET /stream_body/set_resp HTTP/1.1\r\n" "Host: localhost\r\nConnection: close\r\n\r\n", Config), {_Start, _Length} = binary:match(Packet, <<"stream_body_set_resp">>). static_mimetypes_function(Config) -> TestURL = build_url("/static_mimetypes_function/test.html", Config), {ok, {{"HTTP/1.1", 200, "OK"}, Headers1, "test.html\n"}} = httpc:request(TestURL), "text/html" = ?config("content-type", Headers1). handler_errors(Config) -> Request = fun(Case) -> raw_resp(["GET /handler_errors?case=", Case, " HTTP/1.1\r\n", "Host: localhost\r\n\r\n"], Config) end, {_Packet1, 500} = Request("init_before_reply"), {Packet2, 200} = Request("init_after_reply"), nomatch = binary:match(Packet2, <<"HTTP/1.1 500">>), {Packet3, 200} = Request("init_reply_handle_error"), nomatch = binary:match(Packet3, <<"HTTP/1.1 500">>), {_Packet4, 500} = Request("handle_before_reply"), {Packet5, 200} = Request("handle_after_reply"), nomatch = binary:match(Packet5, <<"HTTP/1.1 500">>), {Packet6, 200} = raw_resp([ "GET / HTTP/1.1\r\n", "Host: localhost\r\n", "Connection: keep-alive\r\n\r\n", "GET /handler_errors?case=handle_after_reply\r\n", "Host: localhost\r\n\r\n"], Config), nomatch = binary:match(Packet6, <<"HTTP/1.1 500">>), {Packet7, 200} = raw_resp([ "GET / HTTP/1.1\r\n", "Host: localhost\r\n", "Connection: keep-alive\r\n\r\n", "GET /handler_errors?case=handle_before_reply HTTP/1.1\r\n", "Host: localhost\r\n\r\n"], Config), {{_, _}, _} = {binary:match(Packet7, <<"HTTP/1.1 500">>), Packet7}, done. static_attribute_etag(Config) -> TestURL = build_url("/static_attribute_etag/test.html", Config), {ok, {{"HTTP/1.1", 200, "OK"}, Headers1, "test.html\n"}} = httpc:request(TestURL), false = ?config("etag", Headers1) =:= undefined, {ok, {{"HTTP/1.1", 200, "OK"}, Headers2, "test.html\n"}} = httpc:request(TestURL), true = ?config("etag", Headers1) =:= ?config("etag", Headers2). static_function_etag(Config) -> TestURL = build_url("/static_function_etag/test.html", Config), {ok, {{"HTTP/1.1", 200, "OK"}, Headers1, "test.html\n"}} = httpc:request(TestURL), false = ?config("etag", Headers1) =:= undefined, {ok, {{"HTTP/1.1", 200, "OK"}, Headers2, "test.html\n"}} = httpc:request(TestURL), true = ?config("etag", Headers1) =:= ?config("etag", Headers2). static_function_etag(Arguments, etag_data) -> {_, Filepath} = lists:keyfind(filepath, 1, Arguments), {_, _Filesize} = lists:keyfind(filesize, 1, Arguments), {_, _INode} = lists:keyfind(inode, 1, Arguments), {_, _Modified} = lists:keyfind(mtime, 1, Arguments), ChecksumCommand = lists:flatten(io_lib:format("sha1sum ~s", [Filepath])), [Checksum|_] = string:tokens(os:cmd(ChecksumCommand), " "), iolist_to_binary(Checksum). %% http and https. build_url(Path, Config) -> {scheme, Scheme} = lists:keyfind(scheme, 1, Config), {port, Port} = lists:keyfind(port, 1, Config), Scheme ++ "://localhost:" ++ integer_to_list(Port) ++ Path. http_200(Config) -> {ok, {{"HTTP/1.1", 200, "OK"}, _Headers, "http_handler"}} = httpc:request(build_url("/", Config)). http_404(Config) -> {ok, {{"HTTP/1.1", 404, "Not Found"}, _Headers, _Body}} = httpc:request(build_url("/not/found", Config)). file_200(Config) -> {ok, {{"HTTP/1.1", 200, "OK"}, Headers, "test_file\n"}} = httpc:request(build_url("/static/test_file", Config)), "application/octet-stream" = ?config("content-type", Headers), {ok, {{"HTTP/1.1", 200, "OK"}, Headers1, "test_file.css\n"}} = httpc:request(build_url("/static/test_file.css", Config)), "text/css" = ?config("content-type", Headers1). file_403(Config) -> {ok, {{"HTTP/1.1", 403, "Forbidden"}, _Headers, _Body}} = httpc:request(build_url("/static/test_noread", Config)). dir_403(Config) -> {ok, {{"HTTP/1.1", 403, "Forbidden"}, _Headers, _Body}} = httpc:request(build_url("/static/test_dir", Config)), {ok, {{"HTTP/1.1", 403, "Forbidden"}, _Headers, _Body}} = httpc:request(build_url("/static/test_dir/", Config)). file_404(Config) -> {ok, {{"HTTP/1.1", 404, "Not Found"}, _Headers, _Body}} = httpc:request(build_url("/static/not_found", Config)). file_400(Config) -> {ok, {{"HTTP/1.1", 400, "Bad Request"}, _Headers, _Body}} = httpc:request(build_url("/static/%2f", Config)), {ok, {{"HTTP/1.1", 400, "Bad Request"}, _Headers1, _Body1}} = httpc:request(build_url("/static/%2e", Config)), {ok, {{"HTTP/1.1", 400, "Bad Request"}, _Headers2, _Body2}} = httpc:request(build_url("/static/%2e%2e", Config)). %% misc. http_10_hostless(Config) -> Packet = "GET / HTTP/1.0\r\n\r\n", {Packet, 200} = raw_req(Packet, Config). %% rest. rest_simple(Config) -> Packet = "GET /simple HTTP/1.1\r\nHost: localhost\r\n\r\n", {Packet, 200} = raw_req(Packet, Config). rest_keepalive(Config) -> {port, Port} = lists:keyfind(port, 1, Config), {ok, Socket} = gen_tcp:connect("localhost", Port, [binary, {active, false}, {packet, raw}]), ok = rest_keepalive_loop(Socket, 100), ok = gen_tcp:close(Socket). rest_keepalive_loop(_Socket, 0) -> ok; rest_keepalive_loop(Socket, N) -> ok = gen_tcp:send(Socket, "GET /simple HTTP/1.1\r\n" "Host: localhost\r\nConnection: keep-alive\r\n\r\n"), {ok, Data} = gen_tcp:recv(Socket, 0, 6000), {0, 12} = binary:match(Data, <<"HTTP/1.1 200">>), nomatch = binary:match(Data, <<"Connection: close">>), rest_keepalive_loop(Socket, N - 1). rest_keepalive_post(Config) -> {port, Port} = lists:keyfind(port, 1, Config), {ok, Socket} = gen_tcp:connect("localhost", Port, [binary, {active, false}, {packet, raw}]), ok = rest_keepalive_post_loop(Socket, 10, forbidden_post), ok = gen_tcp:close(Socket). rest_keepalive_post_loop(_Socket, 0, _) -> ok; rest_keepalive_post_loop(Socket, N, simple_post) -> ok = gen_tcp:send(Socket, "POST /simple_post HTTP/1.1\r\n" "Host: localhost\r\nConnection: keep-alive\r\n" "Content-Length: 5\r\nContent-Type: text/plain\r\n\r\n12345"), {ok, Data} = gen_tcp:recv(Socket, 0, 6000), {0, 12} = binary:match(Data, <<"HTTP/1.1 303">>), nomatch = binary:match(Data, <<"Connection: close">>), rest_keepalive_post_loop(Socket, N - 1, forbidden_post); rest_keepalive_post_loop(Socket, N, forbidden_post) -> ok = gen_tcp:send(Socket, "POST /forbidden_post HTTP/1.1\r\n" "Host: localhost\r\nConnection: keep-alive\r\n" "Content-Length: 5\r\nContent-Type: text/plain\r\n\r\n12345"), {ok, Data} = gen_tcp:recv(Socket, 0, 6000), {0, 12} = binary:match(Data, <<"HTTP/1.1 403">>), nomatch = binary:match(Data, <<"Connection: close">>), rest_keepalive_post_loop(Socket, N - 1, simple_post). rabbitmq-server-3.2.4/plugins-src/cowboy-wrapper/cowboy-git/test/dispatcher_prop.erl0000644000000000000000000000434012305126066027507 0ustar rootroot%% Copyright (c) 2011, Magnus Klaar %% Copyright (c) 2011, Loïc Hoguin %% %% Permission to use, copy, modify, and/or distribute this software for any %% purpose with or without fee is hereby granted, provided that the above %% copyright notice and this permission notice appear in all copies. %% %% THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES %% WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF %% MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR %% ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES %% WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN %% ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF %% OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -module(dispatcher_prop). -include_lib("proper/include/proper.hrl"). %% Generators. hostname_head_char() -> oneof([choose($a, $z), choose($A, $Z), choose($0, $9)]). hostname_char() -> oneof([choose($a, $z), choose($A, $Z), choose($0, $9), $-]). hostname_label() -> ?SUCHTHAT(Label, [hostname_head_char()|list(hostname_char())], length(Label) < 64). hostname() -> ?SUCHTHAT(Hostname, ?LET(Labels, list(hostname_label()), string:join(Labels, ".")), length(Hostname) > 0 andalso length(Hostname) =< 255). port_number() -> choose(1, 16#ffff). port_str() -> oneof(["", ?LET(Port, port_number(), ":" ++ integer_to_list(Port))]). server() -> ?LET({Hostname, PortStr}, {hostname(), port_str()}, list_to_binary(Hostname ++ PortStr)). %% Properties. prop_split_host_symmetric() -> ?FORALL(Server, server(), begin case cowboy_dispatcher:split_host(Server) of {Tokens, RawHost, undefined} -> (Server == RawHost) and (Server == binary_join(Tokens, ".")); {Tokens, RawHost, Port} -> PortBin = (list_to_binary(":" ++ integer_to_list(Port))), (Server == << RawHost/binary, PortBin/binary >>) and (Server == << (binary_join(Tokens, "."))/binary, PortBin/binary >>) end end). %% Internal. %% Contributed by MononcQc on #erlounge. binary_join(Flowers, Leaf) -> case Flowers of [] -> <<>>; [Petal|Pot] -> iolist_to_binary( [Petal | [[Leaf | Pollen] || Pollen <- Pot]]) end. rabbitmq-server-3.2.4/plugins-src/cowboy-wrapper/cowboy-git/test/websocket_handler.erl0000644000000000000000000000211712305126066030004 0ustar rootroot%% Feel free to use, reuse and abuse the code in this file. -module(websocket_handler). -behaviour(cowboy_http_handler). -behaviour(cowboy_http_websocket_handler). -export([init/3, handle/2, terminate/2]). -export([websocket_init/3, websocket_handle/3, websocket_info/3, websocket_terminate/3]). init(_Any, _Req, _Opts) -> {upgrade, protocol, cowboy_http_websocket}. handle(_Req, _State) -> exit(badarg). terminate(_Req, _State) -> exit(badarg). websocket_init(_TransportName, Req, _Opts) -> erlang:start_timer(1000, self(), <<"websocket_init">>), Req2 = cowboy_http_req:compact(Req), {ok, Req2, undefined}. websocket_handle({text, Data}, Req, State) -> {reply, {text, Data}, Req, State}; websocket_handle({binary, Data}, Req, State) -> {reply, {binary, Data}, Req, State}; websocket_handle(_Frame, Req, State) -> {ok, Req, State}. websocket_info({timeout, _Ref, Msg}, Req, State) -> erlang:start_timer(1000, self(), <<"websocket_handle">>), {reply, {text, Msg}, Req, State}; websocket_info(_Info, Req, State) -> {ok, Req, State}. websocket_terminate(_Reason, _Req, _State) -> ok. rabbitmq-server-3.2.4/plugins-src/cowboy-wrapper/cowboy-git/test/rest_simple_resource.erl0000644000000000000000000000052512305126066030557 0ustar rootroot-module(rest_simple_resource). -export([init/3, content_types_provided/2, get_text_plain/2]). init(_Transport, _Req, _Opts) -> {upgrade, protocol, cowboy_http_rest}. content_types_provided(Req, State) -> {[{{<<"text">>, <<"plain">>, []}, get_text_plain}], Req, State}. get_text_plain(Req, State) -> {<<"This is REST!">>, Req, State}. rabbitmq-server-3.2.4/plugins-src/cowboy-wrapper/cowboy-git/test/rest_forbidden_resource.erl0000644000000000000000000000171612305126066031225 0ustar rootroot-module(rest_forbidden_resource). -export([init/3, rest_init/2, allowed_methods/2, forbidden/2, content_types_provided/2, content_types_accepted/2, post_is_create/2, create_path/2, to_text/2, from_text/2]). init(_Transport, _Req, _Opts) -> {upgrade, protocol, cowboy_http_rest}. rest_init(Req, [Forbidden]) -> {ok, Req, Forbidden}. allowed_methods(Req, State) -> {['GET', 'HEAD', 'POST'], Req, State}. forbidden(Req, State=true) -> {true, Req, State}; forbidden(Req, State=false) -> {false, Req, State}. content_types_provided(Req, State) -> {[{{<<"text">>, <<"plain">>, []}, to_text}], Req, State}. content_types_accepted(Req, State) -> {[{{<<"text">>, <<"plain">>, []}, from_text}], Req, State}. post_is_create(Req, State) -> {true, Req, State}. create_path(Req, State) -> {Path, Req2} = cowboy_http_req:raw_path(Req), {Path, Req2, State}. to_text(Req, State) -> {<<"This is REST!">>, Req, State}. from_text(Req, State) -> {true, Req, State}. rabbitmq-server-3.2.4/plugins-src/cowboy-wrapper/cowboy-git/test/http_handler_errors.erl0000644000000000000000000000221712305126066030372 0ustar rootroot%% Feel free to use, reuse and abuse the code in this file. -module(http_handler_errors). -behaviour(cowboy_http_handler). -export([init/3, handle/2, terminate/2]). init({_Transport, http}, Req, _Opts) -> {Case, Req1} = cowboy_http_req:qs_val(<<"case">>, Req), case_init(Case, Req1). case_init(<<"init_before_reply">> = Case, _Req) -> erlang:error(Case); case_init(<<"init_after_reply">> = Case, Req) -> {ok, _Req1} = cowboy_http_req:reply(200, [], "http_handler_crashes", Req), erlang:error(Case); case_init(<<"init_reply_handle_error">> = Case, Req) -> {ok, Req1} = cowboy_http_req:reply(200, [], "http_handler_crashes", Req), {ok, Req1, Case}; case_init(<<"handle_before_reply">> = Case, Req) -> {ok, Req, Case}; case_init(<<"handle_after_reply">> = Case, Req) -> {ok, Req, Case}. handle(_Req, <<"init_reply_handle_error">> = Case) -> erlang:error(Case); handle(_Req, <<"handle_before_reply">> = Case) -> erlang:error(Case); handle(Req, <<"handle_after_reply">> = Case) -> {ok, _Req1} = cowboy_http_req:reply(200, [], "http_handler_crashes", Req), erlang:error(Case). terminate(_Req, _State) -> ok. rabbitmq-server-3.2.4/plugins-src/cowboy-wrapper/cowboy-git/test/http_handler.erl0000644000000000000000000000106212305126066026773 0ustar rootroot%% Feel free to use, reuse and abuse the code in this file. -module(http_handler). -behaviour(cowboy_http_handler). -export([init/3, handle/2, terminate/2]). -record(state, {headers, body}). init({_Transport, http}, Req, Opts) -> Headers = proplists:get_value(headers, Opts, []), Body = proplists:get_value(body, Opts, "http_handler"), {ok, Req, #state{headers=Headers, body=Body}}. handle(Req, State=#state{headers=Headers, body=Body}) -> {ok, Req2} = cowboy_http_req:reply(200, Headers, Body, Req), {ok, Req2, State}. terminate(_Req, _State) -> ok. rabbitmq-server-3.2.4/plugins-src/cowboy-wrapper/cowboy-git/test/http_handler_init_shutdown.erl0000644000000000000000000000075712305126066031763 0ustar rootroot%% Feel free to use, reuse and abuse the code in this file. -module(http_handler_init_shutdown). -behaviour(cowboy_http_handler). -export([init/3, handle/2, terminate/2]). init({_Transport, http}, Req, _Opts) -> {ok, Req2} = cowboy_http_req:reply(<<"666 Init Shutdown Testing">>, [{'Connection', <<"close">>}], Req), {shutdown, Req2, undefined}. handle(Req, State) -> {ok, Req2} = cowboy_http_req:reply(200, [], "Hello world!", Req), {ok, Req2, State}. terminate(_Req, _State) -> ok. rabbitmq-server-3.2.4/plugins-src/cowboy-wrapper/cowboy-git/test/chunked_handler.erl0000644000000000000000000000070712305126066027442 0ustar rootroot%% Feel free to use, reuse and abuse the code in this file. -module(chunked_handler). -behaviour(cowboy_http_handler). -export([init/3, handle/2, terminate/2]). init({_Transport, http}, Req, _Opts) -> {ok, Req, undefined}. handle(Req, State) -> {ok, Req2} = cowboy_http_req:chunked_reply(200, Req), cowboy_http_req:chunk("chunked_handler\r\n", Req2), cowboy_http_req:chunk("works fine!", Req2), {ok, Req2, State}. terminate(_Req, _State) -> ok. rabbitmq-server-3.2.4/plugins-src/cowboy-wrapper/cowboy-git/test/ws_SUITE.erl0000644000000000000000000003057412305126066025733 0ustar rootroot%% Copyright (c) 2011, Loïc Hoguin %% %% Permission to use, copy, modify, and/or distribute this software for any %% purpose with or without fee is hereby granted, provided that the above %% copyright notice and this permission notice appear in all copies. %% %% THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES %% WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF %% MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR %% ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES %% WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN %% ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF %% OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -module(ws_SUITE). -include_lib("common_test/include/ct.hrl"). -export([all/0, groups/0, init_per_suite/1, end_per_suite/1, init_per_group/2, end_per_group/2]). %% ct. -export([ws0/1, ws8/1, ws8_single_bytes/1, ws8_init_shutdown/1, ws13/1, ws_timeout_hibernate/1]). %% ws. %% ct. all() -> [{group, ws}]. groups() -> BaseTests = [ws0, ws8, ws8_single_bytes, ws8_init_shutdown, ws13, ws_timeout_hibernate], [{ws, [], BaseTests}]. init_per_suite(Config) -> application:start(inets), application:start(cowboy), Config. end_per_suite(_Config) -> application:stop(cowboy), application:stop(inets), ok. init_per_group(ws, Config) -> Port = 33080, cowboy:start_listener(ws, 100, cowboy_tcp_transport, [{port, Port}], cowboy_http_protocol, [{dispatch, init_dispatch()}] ), [{port, Port}|Config]. end_per_group(Listener, _Config) -> cowboy:stop_listener(Listener), ok. %% Dispatch configuration. init_dispatch() -> [ {[<<"localhost">>], [ {[<<"websocket">>], websocket_handler, []}, {[<<"ws_timeout_hibernate">>], ws_timeout_hibernate_handler, []}, {[<<"ws_init_shutdown">>], websocket_handler_init_shutdown, []} ]} ]. %% ws and wss. %% This test makes sure the code works even if we wait for a reply %% before sending the third challenge key in the GET body. %% %% This ensures that Cowboy will work fine with proxies on hixie. ws0(Config) -> {port, Port} = lists:keyfind(port, 1, Config), {ok, Socket} = gen_tcp:connect("localhost", Port, [binary, {active, false}, {packet, raw}]), ok = gen_tcp:send(Socket, "GET /websocket HTTP/1.1\r\n" "Host: localhost\r\n" "Connection: Upgrade\r\n" "Upgrade: WebSocket\r\n" "Origin: http://localhost\r\n" "Sec-Websocket-Key1: Y\" 4 1Lj!957b8@0H756!i\r\n" "Sec-Websocket-Key2: 1711 M;4\\74 80<6\r\n" "\r\n"), {ok, Handshake} = gen_tcp:recv(Socket, 0, 6000), {ok, {http_response, {1, 1}, 101, "WebSocket Protocol Handshake"}, Rest} = erlang:decode_packet(http, Handshake, []), [Headers, <<>>] = websocket_headers( erlang:decode_packet(httph, Rest, []), []), {'Connection', "Upgrade"} = lists:keyfind('Connection', 1, Headers), {'Upgrade', "WebSocket"} = lists:keyfind('Upgrade', 1, Headers), {"sec-websocket-location", "ws://localhost/websocket"} = lists:keyfind("sec-websocket-location", 1, Headers), {"sec-websocket-origin", "http://localhost"} = lists:keyfind("sec-websocket-origin", 1, Headers), ok = gen_tcp:send(Socket, <<15,245,8,18,2,204,133,33>>), {ok, Body} = gen_tcp:recv(Socket, 0, 6000), <<169,244,191,103,146,33,149,59,74,104,67,5,99,118,171,236>> = Body, ok = gen_tcp:send(Socket, << 0, "client_msg", 255 >>), {ok, << 0, "client_msg", 255 >>} = gen_tcp:recv(Socket, 0, 6000), {ok, << 0, "websocket_init", 255 >>} = gen_tcp:recv(Socket, 0, 6000), {ok, << 0, "websocket_handle", 255 >>} = gen_tcp:recv(Socket, 0, 6000), {ok, << 0, "websocket_handle", 255 >>} = gen_tcp:recv(Socket, 0, 6000), {ok, << 0, "websocket_handle", 255 >>} = gen_tcp:recv(Socket, 0, 6000), %% We try to send another HTTP request to make sure %% the server closed the request. ok = gen_tcp:send(Socket, [ << 255, 0 >>, %% Close websocket command. "GET / HTTP/1.1\r\nHost: localhost\r\n\r\n" %% Server should ignore it. ]), {ok, << 255, 0 >>} = gen_tcp:recv(Socket, 0, 6000), {error, closed} = gen_tcp:recv(Socket, 0, 6000), ok. ws8(Config) -> {port, Port} = lists:keyfind(port, 1, Config), {ok, Socket} = gen_tcp:connect("localhost", Port, [binary, {active, false}, {packet, raw}]), ok = gen_tcp:send(Socket, [ "GET /websocket HTTP/1.1\r\n" "Host: localhost\r\n" "Connection: Upgrade\r\n" "Upgrade: websocket\r\n" "Sec-WebSocket-Origin: http://localhost\r\n" "Sec-WebSocket-Version: 8\r\n" "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n" "\r\n"]), {ok, Handshake} = gen_tcp:recv(Socket, 0, 6000), {ok, {http_response, {1, 1}, 101, "Switching Protocols"}, Rest} = erlang:decode_packet(http, Handshake, []), [Headers, <<>>] = websocket_headers( erlang:decode_packet(httph, Rest, []), []), {'Connection', "Upgrade"} = lists:keyfind('Connection', 1, Headers), {'Upgrade', "websocket"} = lists:keyfind('Upgrade', 1, Headers), {"sec-websocket-accept", "s3pPLMBiTxaQ9kYGzzhZRbK+xOo="} = lists:keyfind("sec-websocket-accept", 1, Headers), ok = gen_tcp:send(Socket, << 16#81, 16#85, 16#37, 16#fa, 16#21, 16#3d, 16#7f, 16#9f, 16#4d, 16#51, 16#58 >>), {ok, << 1:1, 0:3, 1:4, 0:1, 5:7, "Hello" >>} = gen_tcp:recv(Socket, 0, 6000), {ok, << 1:1, 0:3, 1:4, 0:1, 14:7, "websocket_init" >>} = gen_tcp:recv(Socket, 0, 6000), {ok, << 1:1, 0:3, 1:4, 0:1, 16:7, "websocket_handle" >>} = gen_tcp:recv(Socket, 0, 6000), {ok, << 1:1, 0:3, 1:4, 0:1, 16:7, "websocket_handle" >>} = gen_tcp:recv(Socket, 0, 6000), {ok, << 1:1, 0:3, 1:4, 0:1, 16:7, "websocket_handle" >>} = gen_tcp:recv(Socket, 0, 6000), ok = gen_tcp:send(Socket, << 1:1, 0:3, 9:4, 0:8 >>), %% ping {ok, << 1:1, 0:3, 10:4, 0:8 >>} = gen_tcp:recv(Socket, 0, 6000), %% pong ok = gen_tcp:send(Socket, << 1:1, 0:3, 8:4, 0:8 >>), %% close {ok, << 1:1, 0:3, 8:4, 0:8 >>} = gen_tcp:recv(Socket, 0, 6000), {error, closed} = gen_tcp:recv(Socket, 0, 6000), ok. ws8_single_bytes(Config) -> {port, Port} = lists:keyfind(port, 1, Config), {ok, Socket} = gen_tcp:connect("localhost", Port, [binary, {active, false}, {packet, raw}]), ok = gen_tcp:send(Socket, [ "GET /websocket HTTP/1.1\r\n" "Host: localhost\r\n" "Connection: Upgrade\r\n" "Upgrade: websocket\r\n" "Sec-WebSocket-Origin: http://localhost\r\n" "Sec-WebSocket-Version: 8\r\n" "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n" "\r\n"]), {ok, Handshake} = gen_tcp:recv(Socket, 0, 6000), {ok, {http_response, {1, 1}, 101, "Switching Protocols"}, Rest} = erlang:decode_packet(http, Handshake, []), [Headers, <<>>] = websocket_headers( erlang:decode_packet(httph, Rest, []), []), {'Connection', "Upgrade"} = lists:keyfind('Connection', 1, Headers), {'Upgrade', "websocket"} = lists:keyfind('Upgrade', 1, Headers), {"sec-websocket-accept", "s3pPLMBiTxaQ9kYGzzhZRbK+xOo="} = lists:keyfind("sec-websocket-accept", 1, Headers), ok = gen_tcp:send(Socket, << 16#81 >>), %% send one byte ok = timer:sleep(100), %% sleep for a period ok = gen_tcp:send(Socket, << 16#85 >>), %% send another and so on ok = timer:sleep(100), ok = gen_tcp:send(Socket, << 16#37 >>), ok = timer:sleep(100), ok = gen_tcp:send(Socket, << 16#fa >>), ok = timer:sleep(100), ok = gen_tcp:send(Socket, << 16#21 >>), ok = timer:sleep(100), ok = gen_tcp:send(Socket, << 16#3d >>), ok = timer:sleep(100), ok = gen_tcp:send(Socket, << 16#7f >>), ok = timer:sleep(100), ok = gen_tcp:send(Socket, << 16#9f >>), ok = timer:sleep(100), ok = gen_tcp:send(Socket, << 16#4d >>), ok = timer:sleep(100), ok = gen_tcp:send(Socket, << 16#51 >>), ok = timer:sleep(100), ok = gen_tcp:send(Socket, << 16#58 >>), {ok, << 1:1, 0:3, 1:4, 0:1, 14:7, "websocket_init" >>} = gen_tcp:recv(Socket, 0, 6000), {ok, << 1:1, 0:3, 1:4, 0:1, 5:7, "Hello" >>} = gen_tcp:recv(Socket, 0, 6000), {ok, << 1:1, 0:3, 1:4, 0:1, 16:7, "websocket_handle" >>} = gen_tcp:recv(Socket, 0, 6000), {ok, << 1:1, 0:3, 1:4, 0:1, 16:7, "websocket_handle" >>} = gen_tcp:recv(Socket, 0, 6000), {ok, << 1:1, 0:3, 1:4, 0:1, 16:7, "websocket_handle" >>} = gen_tcp:recv(Socket, 0, 6000), ok = gen_tcp:send(Socket, << 1:1, 0:3, 9:4, 0:8 >>), %% ping {ok, << 1:1, 0:3, 10:4, 0:8 >>} = gen_tcp:recv(Socket, 0, 6000), %% pong ok = gen_tcp:send(Socket, << 1:1, 0:3, 8:4, 0:8 >>), %% close {ok, << 1:1, 0:3, 8:4, 0:8 >>} = gen_tcp:recv(Socket, 0, 6000), {error, closed} = gen_tcp:recv(Socket, 0, 6000), ok. ws_timeout_hibernate(Config) -> {port, Port} = lists:keyfind(port, 1, Config), {ok, Socket} = gen_tcp:connect("localhost", Port, [binary, {active, false}, {packet, raw}]), ok = gen_tcp:send(Socket, [ "GET /ws_timeout_hibernate HTTP/1.1\r\n" "Host: localhost\r\n" "Connection: Upgrade\r\n" "Upgrade: websocket\r\n" "Sec-WebSocket-Origin: http://localhost\r\n" "Sec-WebSocket-Version: 8\r\n" "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n" "\r\n"]), {ok, Handshake} = gen_tcp:recv(Socket, 0, 6000), {ok, {http_response, {1, 1}, 101, "Switching Protocols"}, Rest} = erlang:decode_packet(http, Handshake, []), [Headers, <<>>] = websocket_headers( erlang:decode_packet(httph, Rest, []), []), {'Connection', "Upgrade"} = lists:keyfind('Connection', 1, Headers), {'Upgrade', "websocket"} = lists:keyfind('Upgrade', 1, Headers), {"sec-websocket-accept", "s3pPLMBiTxaQ9kYGzzhZRbK+xOo="} = lists:keyfind("sec-websocket-accept", 1, Headers), {ok, << 1:1, 0:3, 8:4, 0:8 >>} = gen_tcp:recv(Socket, 0, 6000), {error, closed} = gen_tcp:recv(Socket, 0, 6000), ok. ws8_init_shutdown(Config) -> {port, Port} = lists:keyfind(port, 1, Config), {ok, Socket} = gen_tcp:connect("localhost", Port, [binary, {active, false}, {packet, raw}]), ok = gen_tcp:send(Socket, [ "GET /ws_init_shutdown HTTP/1.1\r\n" "Host: localhost\r\n" "Connection: Upgrade\r\n" "Upgrade: websocket\r\n" "Sec-WebSocket-Origin: http://localhost\r\n" "Sec-WebSocket-Version: 8\r\n" "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n" "\r\n"]), {ok, Handshake} = gen_tcp:recv(Socket, 0, 6000), {ok, {http_response, {1, 1}, 403, "Forbidden"}, _Rest} = erlang:decode_packet(http, Handshake, []), {error, closed} = gen_tcp:recv(Socket, 0, 6000), ok. ws13(Config) -> {port, Port} = lists:keyfind(port, 1, Config), {ok, Socket} = gen_tcp:connect("localhost", Port, [binary, {active, false}, {packet, raw}]), ok = gen_tcp:send(Socket, [ "GET /websocket HTTP/1.1\r\n" "Host: localhost\r\n" "Connection: Upgrade\r\n" "Origin: http://localhost\r\n" "Sec-WebSocket-Version: 13\r\n" "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n" "Upgrade: websocket\r\n" "\r\n"]), {ok, Handshake} = gen_tcp:recv(Socket, 0, 6000), {ok, {http_response, {1, 1}, 101, "Switching Protocols"}, Rest} = erlang:decode_packet(http, Handshake, []), [Headers, <<>>] = websocket_headers( erlang:decode_packet(httph, Rest, []), []), {'Connection', "Upgrade"} = lists:keyfind('Connection', 1, Headers), {'Upgrade', "websocket"} = lists:keyfind('Upgrade', 1, Headers), {"sec-websocket-accept", "s3pPLMBiTxaQ9kYGzzhZRbK+xOo="} = lists:keyfind("sec-websocket-accept", 1, Headers), %% text ok = gen_tcp:send(Socket, << 16#81, 16#85, 16#37, 16#fa, 16#21, 16#3d, 16#7f, 16#9f, 16#4d, 16#51, 16#58 >>), {ok, << 1:1, 0:3, 1:4, 0:1, 5:7, "Hello" >>} = gen_tcp:recv(Socket, 0, 6000), %% binary (empty) ok = gen_tcp:send(Socket, << 1:1, 0:3, 2:4, 0:8 >>), {ok, << 1:1, 0:3, 2:4, 0:8 >>} = gen_tcp:recv(Socket, 0, 6000), %% binary ok = gen_tcp:send(Socket, << 16#82, 16#85, 16#37, 16#fa, 16#21, 16#3d, 16#7f, 16#9f, 16#4d, 16#51, 16#58 >>), {ok, << 1:1, 0:3, 2:4, 0:1, 5:7, "Hello" >>} = gen_tcp:recv(Socket, 0, 6000), %% Receives. {ok, << 1:1, 0:3, 1:4, 0:1, 14:7, "websocket_init" >>} = gen_tcp:recv(Socket, 0, 6000), {ok, << 1:1, 0:3, 1:4, 0:1, 16:7, "websocket_handle" >>} = gen_tcp:recv(Socket, 0, 6000), {ok, << 1:1, 0:3, 1:4, 0:1, 16:7, "websocket_handle" >>} = gen_tcp:recv(Socket, 0, 6000), {ok, << 1:1, 0:3, 1:4, 0:1, 16:7, "websocket_handle" >>} = gen_tcp:recv(Socket, 0, 6000), ok = gen_tcp:send(Socket, << 1:1, 0:3, 9:4, 0:8 >>), %% ping {ok, << 1:1, 0:3, 10:4, 0:8 >>} = gen_tcp:recv(Socket, 0, 6000), %% pong ok = gen_tcp:send(Socket, << 1:1, 0:3, 8:4, 0:8 >>), %% close {ok, << 1:1, 0:3, 8:4, 0:8 >>} = gen_tcp:recv(Socket, 0, 6000), {error, closed} = gen_tcp:recv(Socket, 0, 6000), ok. websocket_headers({ok, http_eoh, Rest}, Acc) -> [Acc, Rest]; websocket_headers({ok, {http_header, _I, Key, _R, Value}, Rest}, Acc) -> F = fun(S) when is_atom(S) -> S; (S) -> string:to_lower(S) end, websocket_headers(erlang:decode_packet(httph, Rest, []), [{F(Key), Value}|Acc]). rabbitmq-server-3.2.4/plugins-src/cowboy-wrapper/cowboy-git/test/http_handler_stream_body.erl0000644000000000000000000000153512305126066031370 0ustar rootroot%% Feel free to use, reuse and abuse the code in this file. -module(http_handler_stream_body). -behaviour(cowboy_http_handler). -export([init/3, handle/2, terminate/2]). -record(state, {headers, body, reply}). init({_Transport, http}, Req, Opts) -> Headers = proplists:get_value(headers, Opts, []), Body = proplists:get_value(body, Opts, "http_handler_stream_body"), Reply = proplists:get_value(reply, Opts), {ok, Req, #state{headers=Headers, body=Body, reply=Reply}}. handle(Req, State=#state{headers=_Headers, body=Body, reply=set_resp}) -> {ok, Transport, Socket} = cowboy_http_req:transport(Req), SFun = fun() -> Transport:send(Socket, Body), sent end, SLen = iolist_size(Body), {ok, Req2} = cowboy_http_req:set_resp_body_fun(SLen, SFun, Req), {ok, Req3} = cowboy_http_req:reply(200, Req2), {ok, Req3, State}. terminate(_Req, _State) -> ok. rabbitmq-server-3.2.4/plugins-src/cowboy-wrapper/cowboy-git/test/http_handler_multipart.erl0000644000000000000000000000165412305126066031103 0ustar rootroot%% Feel free to use, reuse and abuse the code in this file. -module(http_handler_multipart). -behaviour(cowboy_http_handler). -export([init/3, handle/2, terminate/2]). init({_Transport, http}, Req, []) -> {ok, Req, {}}. handle(Req, State) -> {Result, Req2} = acc_multipart(Req, []), {ok, Req3} = cowboy_http_req:reply(200, [], term_to_binary(Result), Req2), {ok, Req3, State}. terminate(_Req, _State) -> ok. acc_multipart(Req, Acc) -> {Result, Req2} = cowboy_http_req:multipart_data(Req), acc_multipart(Req2, Acc, Result). acc_multipart(Req, Acc, {headers, Headers}) -> acc_multipart(Req, [{Headers, []}|Acc]); acc_multipart(Req, [{Headers, BodyAcc}|Acc], {body, Data}) -> acc_multipart(Req, [{Headers, [Data|BodyAcc]}|Acc]); acc_multipart(Req, [{Headers, BodyAcc}|Acc], end_of_part) -> acc_multipart(Req, [{Headers, list_to_binary(lists:reverse(BodyAcc))}|Acc]); acc_multipart(Req, Acc, eof) -> {lists:reverse(Acc), Req}. ././@LongLink0000000000000000000000000000014500000000000011565 Lustar rootrootrabbitmq-server-3.2.4/plugins-src/cowboy-wrapper/cowboy-git/test/websocket_handler_init_shutdown.erlrabbitmq-server-3.2.4/plugins-src/cowboy-wrapper/cowboy-git/test/websocket_handler_init_shutdown.erl0000644000000000000000000000136412305126066032765 0ustar rootroot%% Feel free to use, reuse and abuse the code in this file. -module(websocket_handler_init_shutdown). -behaviour(cowboy_http_handler). -behaviour(cowboy_http_websocket_handler). -export([init/3, handle/2, terminate/2]). -export([websocket_init/3, websocket_handle/3, websocket_info/3, websocket_terminate/3]). init(_Any, _Req, _Opts) -> {upgrade, protocol, cowboy_http_websocket}. handle(_Req, _State) -> exit(badarg). terminate(_Req, _State) -> exit(badarg). websocket_init(_TransportName, Req, _Opts) -> {ok, Req2} = cowboy_http_req:reply(403, Req), {shutdown, Req2}. websocket_handle(_Frame, _Req, _State) -> exit(badarg). websocket_info(_Info, _Req, _State) -> exit(badarg). websocket_terminate(_Reason, _Req, _State) -> exit(badarg). rabbitmq-server-3.2.4/plugins-src/cowboy-wrapper/cowboy-git/test/http_SUITE_data/0000755000000000000000000000000012305126066026535 5ustar rootrootrabbitmq-server-3.2.4/plugins-src/cowboy-wrapper/cowboy-git/test/http_SUITE_data/cert.pem0000644000000000000000000000145212305126066030177 0ustar rootroot-----BEGIN CERTIFICATE----- MIICKTCCAZICCQCl9gdHk5NqUjANBgkqhkiG9w0BAQUFADBZMQswCQYDVQQGEwJB VTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0 cyBQdHkgTHRkMRIwEAYDVQQDDAlsb2NhbGhvc3QwHhcNMTEwNDA4MTMxNTE3WhcN MTEwNTA4MTMxNTE3WjBZMQswCQYDVQQGEwJBVTETMBEGA1UECAwKU29tZS1TdGF0 ZTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMRIwEAYDVQQDDAls b2NhbGhvc3QwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAOjgFPS0dP4d8F1e bNJPB+kAjM2FyTZGmkFCLUYONTPrdGOUIHL/UOGtU22BQzlskE+a6/j2Kg72tm8x 4X7yf+6s7CdRe086idNx9+GymZ64ZTnly33rD3AJffbBeWHwT2e9fuBeFk9WGC8v kqECFZyqf7+znS0o48oBNcx3ePB5AgMBAAEwDQYJKoZIhvcNAQEFBQADgYEASTkv oHuZyO8DgT8bIE6W3yM2fvlNshkhh7Thgpf32qQoVOxRU9EF0KpuJCCAHQHQNQlI nf9Zc4UzOrLhxZBGocNhkkn4WLw2ysto/7+/+9xHah0M0l4auHLQagVLCoOsHUn2 JX+A2NrbvuX5wnUrZGOdgY70tvMBeU/xLtp3af8= -----END CERTIFICATE----- rabbitmq-server-3.2.4/plugins-src/cowboy-wrapper/cowboy-git/test/http_SUITE_data/key.pem0000644000000000000000000000170312305126066030031 0ustar rootroot-----BEGIN RSA PRIVATE KEY----- Proc-Type: 4,ENCRYPTED DEK-Info: DES-EDE3-CBC,F11262DB77BB804C jOJ+ft/dihIxz7CTuuK47fCTGdX7xMLANmA7mRg8y9OYhNZQiCz5GjcWLqe0NNl5 qXPW0uvT/9B5O9o21Y2i/CKU1BqRLuXHXDsjHg7RGaSH6wIavWt+lR+I1sjieFbX VByK1KHXjEU704DEILKJIA9gVzoYAgMzo+FTw2e/2jusXntxk8HXyF5zKTzjHBtI NQGweJqTmfZjX3SgPP4Co/ShrA6fUG0uTp1HwbByJnwtAeT3xWJrAD4QSn7+qrlv 3qmEIqVXsvLrfZRY1WZ4uIsbLK8wkvxboSIoIK55VV9R2zRbwQULon6QJwKYujAr J2WUYkHHQOMpaAzUmalaT+8GUt8/A1oSK4BdiSZywsMMm46/hDadXBzFg+dPL5g2 Td+7/L0S6tUVWq4+YBp5EalZH6VQ4cqPYDJZUZ9xt6+yY7V5748lSdA7cHCROnbG bKbSW9WbF7MPDHCjvCAfq+s1dafHJgyIOlMg2bm7V8eHWAA0xKQ/o7i5EyEyaKYR UXGeAf+KfXcclEZ77v2RCXZvd6ceWkifm59qWv/3TCYaHiS2Aa3lVToMKTwYzzXQ p5X5os6wv3IAi2nGyAIOoSDisdHmFteZNXNQsw0n3XCAYfsNMk+r5/r5YqDffURH c8SMOCP4BIPoZ/abi/gnEntGqsx1YALg0aosHwHGDJ/l+QJC6u6PZk310YzRw4GL K9+wscFgEub2OO+R83Vkfesj4tYzgOjab7+92a/soHdW0zhGejlvehODOgNZ6NUG MPQlT+qpF9Jh5IThYXupXXFzJzQe3O/qVXy89m69JGa+AWRvbu+M/A== -----END RSA PRIVATE KEY----- rabbitmq-server-3.2.4/plugins-src/cowboy-wrapper/cowboy-git/cover.spec0000644000000000000000000000003512305126066024625 0ustar rootroot{incl_app, cowboy, details}. rabbitmq-server-3.2.4/plugins-src/cowboy-wrapper/cowboy-git/Makefile0000644000000000000000000000114412305126066024275 0ustar rootroot# See LICENSE for licensing information. DIALYZER = dialyzer REBAR = rebar all: app app: deps @$(REBAR) compile deps: @$(REBAR) get-deps clean: @$(REBAR) clean rm -f test/*.beam rm -f erl_crash.dump tests: clean app eunit ct eunit: @$(REBAR) eunit skip_deps=true ct: @$(REBAR) ct skip_deps=true build-plt: @$(DIALYZER) --build_plt --output_plt .cowboy_dialyzer.plt \ --apps kernel stdlib sasl inets crypto public_key ssl dialyze: @$(DIALYZER) --src src --plt .cowboy_dialyzer.plt -Werror_handling \ -Wrace_conditions -Wunmatched_returns # -Wunderspecs docs: @$(REBAR) doc skip_deps=true rabbitmq-server-3.2.4/plugins-src/cowboy-wrapper/cowboy-git/.travis.yml0000644000000000000000000000013512305126066024745 0ustar rootrootlanguage: erlang otp_release: - R15B - R14B04 - R14B03 - R14B02 script: "make tests" rabbitmq-server-3.2.4/plugins-src/cowboy-wrapper/cowboy-git/include/0000755000000000000000000000000012305126066024260 5ustar rootrootrabbitmq-server-3.2.4/plugins-src/cowboy-wrapper/cowboy-git/include/http.hrl0000644000000000000000000000500512305126066025746 0ustar rootroot%% Copyright (c) 2011, Loïc Hoguin %% Copyright (c) 2011, Anthony Ramine %% %% Permission to use, copy, modify, and/or distribute this software for any %% purpose with or without fee is hereby granted, provided that the above %% copyright notice and this permission notice appear in all copies. %% %% THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES %% WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF %% MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR %% ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES %% WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN %% ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF %% OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -record(http_req, { %% Transport. socket = undefined :: undefined | inet:socket(), transport = undefined :: undefined | module(), connection = keepalive :: keepalive | close, %% Request. pid = undefined :: pid(), method = 'GET' :: cowboy_http:method(), version = {1, 1} :: cowboy_http:version(), peer = undefined :: undefined | {inet:ip_address(), inet:ip_port()}, host = undefined :: undefined | cowboy_dispatcher:tokens(), host_info = undefined :: undefined | cowboy_dispatcher:tokens(), raw_host = undefined :: undefined | binary(), port = undefined :: undefined | inet:ip_port(), path = undefined :: undefined | '*' | cowboy_dispatcher:tokens(), path_info = undefined :: undefined | cowboy_dispatcher:tokens(), raw_path = undefined :: undefined | binary(), qs_vals = undefined :: undefined | list({binary(), binary() | true}), raw_qs = undefined :: undefined | binary(), bindings = undefined :: undefined | cowboy_dispatcher:bindings(), headers = [] :: cowboy_http:headers(), p_headers = [] :: [any()], %% @todo Improve those specs. cookies = undefined :: undefined | [{binary(), binary()}], meta = [] :: [{atom(), any()}], %% Request body. body_state = waiting :: waiting | done | {multipart, non_neg_integer(), fun()}, buffer = <<>> :: binary(), %% Response. resp_state = waiting :: locked | waiting | chunks | done, resp_headers = [] :: cowboy_http:headers(), resp_body = <<>> :: cowboy_http:fake_iodata() | {non_neg_integer(), fun(() -> {sent, non_neg_integer()})}, %% Functions. urldecode :: {fun((binary(), T) -> binary()), T} }). rabbitmq-server-3.2.4/plugins-src/cowboy-wrapper/cowboy-git/.done0000644000000000000000000000000012305126066023551 0ustar rootrootrabbitmq-server-3.2.4/plugins-src/cowboy-wrapper/cowboy-git/AUTHORS0000644000000000000000000000043212305126066023704 0ustar rootrootCowboy is available thanks to the work of: Loïc Hoguin Anthony Ramine Magnus Klaar Paul Oliver Steven Gravell Tom Burdick Hunter Morris Yurii Rashkovskii Ali Sabil Hans Ulrich Niedermann Jesper Louis Andersen Mathieu Lecarme Max Lapshin Michiel Hakvoort Ori Bar Alisdair Sullivan rabbitmq-server-3.2.4/plugins-src/cowboy-wrapper/cowboy-git/LICENSE0000644000000000000000000000136112305126066023643 0ustar rootrootCopyright (c) 2011, Loïc Hoguin Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies. THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. rabbitmq-server-3.2.4/plugins-src/cowboy-wrapper/cowboy-git/rebar.config0000644000000000000000000000042712305126066025122 0ustar rootroot{cover_enabled, true}. {deps, [ {proper, "1.0", {git, "git://github.com/manopapad/proper.git", {tag, "v1.0"}}} ]}. {eunit_opts, [verbose, {report, {eunit_surefire, [{dir, "."}]}}]}. {erl_opts, [ %% bin_opt_info, %% warn_missing_spec, warnings_as_errors, warn_export_all ]}. rabbitmq-server-3.2.4/plugins-src/cowboy-wrapper/.srcdist_done0000644000000000000000000000000012305126066023221 0ustar rootrootrabbitmq-server-3.2.4/plugins-src/cowboy-wrapper/hash.mk0000644000000000000000000000003512305126066022024 0ustar rootrootUPSTREAM_SHORT_HASH:=4b93c2d rabbitmq-server-3.2.4/plugins-src/cowboy-wrapper/Makefile0000644000000000000000000000002712305126066022211 0ustar rootrootinclude ../umbrella.mk rabbitmq-server-3.2.4/plugins-src/cowboy-wrapper/0007-R12-type-definitions-must-be-ordered.patch0000644000000000000000000000240212305126066031005 0ustar rootrootFrom 547731d5490b36f1239a99e6c4acc1964e724a6e Mon Sep 17 00:00:00 2001 From: Marek Majkowski Date: Thu, 26 Jan 2012 12:54:49 +0000 Subject: [PATCH 7/7] R12 - type definitions must be ordered --- src/cowboy_multipart.erl | 10 +++++----- 1 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/cowboy_multipart.erl b/src/cowboy_multipart.erl index c9b5b6c..0bd123a 100644 --- a/src/cowboy_multipart.erl +++ b/src/cowboy_multipart.erl @@ -15,15 +15,15 @@ %% @doc Multipart parser. -module(cowboy_multipart). --type part_parser() :: parser(more(part_result())). +-type part_parser() :: any(). -type parser(T) :: fun((binary()) -> T). -type more(T) :: T | {more, parser(T)}. --type part_result() :: headers() | eof. --type headers() :: {headers, http_headers(), body_cont()}. +-type part_result() :: any(). +-type headers() :: any(). -type http_headers() :: [{atom() | binary(), binary()}]. --type body_cont() :: cont(more(body_result())). +-type body_cont() :: any(). -type cont(T) :: fun(() -> T). --type body_result() :: {body, binary(), body_cont()} | end_of_part(). +-type body_result() :: any(). -type end_of_part() :: {end_of_part, cont(more(part_result()))}. -type disposition() :: {binary(), [{binary(), binary()}]}. -- 1.7.0.4 ././@LongLink0000000000000000000000000000016100000000000011563 Lustar rootrootrabbitmq-server-3.2.4/plugins-src/cowboy-wrapper/0006-Use-erlang-integer_to_list-and-lists-max-instead-of-.patchrabbitmq-server-3.2.4/plugins-src/cowboy-wrapper/0006-Use-erlang-integer_to_list-and-lists-max-inste0000644000000000000000000000474612305126066032064 0ustar rootrootFrom 81106c53b80f5d0fa441b893048bbdc6c9e2c4f0 Mon Sep 17 00:00:00 2001 From: Marek Majkowski Date: Thu, 26 Jan 2012 12:54:31 +0000 Subject: [PATCH 6/7] Use erlang:integer_to_list and lists:max instead of bifs --- src/cowboy_http_req.erl | 2 +- src/cowboy_http_static.erl | 2 +- src/cowboy_multipart.erl | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/cowboy_http_req.erl b/src/cowboy_http_req.erl index c884f5a..bf4ac7a 100644 --- a/src/cowboy_http_req.erl +++ b/src/cowboy_http_req.erl @@ -576,7 +576,7 @@ chunked_reply(Status, Headers, Req=#http_req{socket=Socket, chunk(_Data, #http_req{socket=_Socket, transport=_Transport, method='HEAD'}) -> ok; chunk(Data, #http_req{socket=Socket, transport=Transport, resp_state=chunks}) -> - Transport:send(Socket, [integer_to_list(iolist_size(Data), 16), + Transport:send(Socket, [erlang:integer_to_list(iolist_size(Data), 16), <<"\r\n">>, Data, <<"\r\n">>]). %% @doc Send an upgrade reply. diff --git a/src/cowboy_http_static.erl b/src/cowboy_http_static.erl index d370046..da3bd33 100644 --- a/src/cowboy_http_static.erl +++ b/src/cowboy_http_static.erl @@ -412,7 +412,7 @@ attr_etag_function(Args, Attrs) -> -spec attr_etag_function([etagarg()], [fileattr()], [binary()]) -> binary(). attr_etag_function(_Args, [], Acc) -> - list_to_binary(integer_to_list(erlang:crc32(Acc), 16)); + list_to_binary(erlang:integer_to_list(erlang:crc32(Acc), 16)); attr_etag_function(Args, [H|T], Acc) -> {_, Value} = lists:keyfind(H, 1, Args), attr_etag_function(Args, T, [term_to_binary(Value)|Acc]). diff --git a/src/cowboy_multipart.erl b/src/cowboy_multipart.erl index b7aeb54..c9b5b6c 100644 --- a/src/cowboy_multipart.erl +++ b/src/cowboy_multipart.erl @@ -105,7 +105,7 @@ parse_boundary_eol(Bin, Pattern) -> cowboy_http:whitespace(Rest, Fun); nomatch -> % CRLF not found in the given binary. - RestStart = max(byte_size(Bin) - 1, 0), + RestStart = lists:max([byte_size(Bin) - 1, 0]), <<_:RestStart/binary, Rest/binary>> = Bin, more(Rest, fun (NewBin) -> parse_boundary_eol(NewBin, Pattern) end) end. @@ -175,7 +175,7 @@ skip(Bin, Pattern = {P, PSize}) -> parse_boundary_tail(Rest, Pattern); nomatch -> % Boundary not found, need more data. - RestStart = max(byte_size(Bin) - PSize + 1, 0), + RestStart = lists:max([byte_size(Bin) - PSize + 1, 0]), <<_:RestStart/binary, Rest/binary>> = Bin, more(Rest, fun (NewBin) -> skip(NewBin, Pattern) end) end. -- 1.7.0.4 rabbitmq-server-3.2.4/plugins-src/cowboy-wrapper/0005-R12-drop-references-to-Default-any-type.patch0000644000000000000000000000433512305126066031355 0ustar rootrootFrom c7aef1d044a1e83fcd6be7a83b2c763c0366d4f8 Mon Sep 17 00:00:00 2001 From: Marek Majkowski Date: Thu, 26 Jan 2012 12:53:36 +0000 Subject: [PATCH 5/7] R12: drop references to Default:any() type --- src/cowboy_http_req.erl | 8 -------- 1 files changed, 0 insertions(+), 8 deletions(-) diff --git a/src/cowboy_http_req.erl b/src/cowboy_http_req.erl index 64e757c..c884f5a 100644 --- a/src/cowboy_http_req.erl +++ b/src/cowboy_http_req.erl @@ -147,8 +147,6 @@ qs_val(Name, Req) when is_binary(Name) -> %% @doc Return the query string value for the given key, or a default if %% missing. --spec qs_val(binary(), #http_req{}, Default) - -> {binary() | true | Default, #http_req{}} when Default::any(). qs_val(Name, Req=#http_req{raw_qs=RawQs, qs_vals=undefined, urldecode={URLDecFun, URLDecArg}}, Default) when is_binary(Name) -> QsVals = parse_qs(RawQs, fun(Bin) -> URLDecFun(Bin, URLDecArg) end), @@ -180,8 +178,6 @@ binding(Name, Req) when is_atom(Name) -> %% @doc Return the binding value for the given key obtained when matching %% the host and path against the dispatch list, or a default if missing. --spec binding(atom(), #http_req{}, Default) - -> {binary() | Default, #http_req{}} when Default::any(). binding(Name, Req, Default) when is_atom(Name) -> case lists:keyfind(Name, 1, Req#http_req.bindings) of {Name, Value} -> {Value, Req}; @@ -200,8 +196,6 @@ header(Name, Req) when is_atom(Name) orelse is_binary(Name) -> header(Name, Req, undefined). %% @doc Return the header value for the given key, or a default if missing. --spec header(atom() | binary(), #http_req{}, Default) - -> {binary() | Default, #http_req{}} when Default::any(). header(Name, Req, Default) when is_atom(Name) orelse is_binary(Name) -> case lists:keyfind(Name, 1, Req#http_req.headers) of {Name, Value} -> {Value, Req}; @@ -313,8 +307,6 @@ cookie(Name, Req) when is_binary(Name) -> %% @doc Return the cookie value for the given key, or a default if %% missing. --spec cookie(binary(), #http_req{}, Default) - -> {binary() | true | Default, #http_req{}} when Default::any(). cookie(Name, Req=#http_req{cookies=undefined}, Default) when is_binary(Name) -> case header('Cookie', Req) of {undefined, Req2} -> -- 1.7.0.4 rabbitmq-server-3.2.4/plugins-src/cowboy-wrapper/package.mk0000644000000000000000000000141712305126066022501 0ustar rootrootAPP_NAME:=cowboy UPSTREAM_GIT:=https://github.com/rabbitmq/cowboy.git UPSTREAM_REVISION:=4b93c2d19a10e5d9cee RETAIN_ORIGINAL_VERSION:=true WRAPPER_PATCHES:=\ 0001-R12-fake-iodata-type.patch \ 0002-R12-drop-all-references-to-boolean-type.patch \ 0003-R12-drop-all-references-to-reference-type.patch \ 0004-R12-drop-references-to-iodata-type.patch \ 0005-R12-drop-references-to-Default-any-type.patch \ 0006-Use-erlang-integer_to_list-and-lists-max-instead-of-.patch \ 0007-R12-type-definitions-must-be-ordered.patch # Path include/http.hrl is needed during compilation INCLUDE_DIRS+=$(CLONE_DIR) ORIGINAL_APP_FILE:=$(CLONE_DIR)/src/$(APP_NAME).app.src DO_NOT_GENERATE_APP_FILE=true define construct_app_commands cp $(CLONE_DIR)/LICENSE $(APP_DIR)/LICENSE-ISC-Cowboy endef rabbitmq-server-3.2.4/plugins-src/cowboy-wrapper/0004-R12-drop-references-to-iodata-type.patch0000644000000000000000000000416412305126066030444 0ustar rootrootFrom dfb750f491208a8e30cab0fa701dd866d60734b8 Mon Sep 17 00:00:00 2001 From: Marek Majkowski Date: Thu, 26 Jan 2012 12:53:08 +0000 Subject: [PATCH 4/7] R12: drop references to iodata() type --- src/cowboy_http_req.erl | 6 ------ 1 files changed, 0 insertions(+), 6 deletions(-) diff --git a/src/cowboy_http_req.erl b/src/cowboy_http_req.erl index d729d6c..64e757c 100644 --- a/src/cowboy_http_req.erl +++ b/src/cowboy_http_req.erl @@ -478,8 +478,6 @@ set_resp_cookie(Name, Value, Options, Req) -> set_resp_header(HeaderName, HeaderValue, Req). %% @doc Add a header to the response. --spec set_resp_header(cowboy_http:header(), iodata(), #http_req{}) - -> {ok, #http_req{}}. set_resp_header(Name, Value, Req=#http_req{resp_headers=RespHeaders}) -> NameBin = header_to_binary(Name), {ok, Req#http_req{resp_headers=[{NameBin, Value}|RespHeaders]}}. @@ -489,7 +487,6 @@ set_resp_header(Name, Value, Req=#http_req{resp_headers=RespHeaders}) -> %% The body set here is ignored if the response is later sent using %% anything other than reply/2 or reply/3. The response body is expected %% to be a binary or an iolist. --spec set_resp_body(iodata(), #http_req{}) -> {ok, #http_req{}}. set_resp_body(Body, Req) -> {ok, Req#http_req{resp_body=Body}}. @@ -537,8 +534,6 @@ reply(Status, Headers, Req=#http_req{resp_body=Body}) -> reply(Status, Headers, Body, Req). %% @doc Send a reply to the client. --spec reply(cowboy_http:status(), cowboy_http:headers(), iodata(), #http_req{}) - -> {ok, #http_req{}}. reply(Status, Headers, Body, Req=#http_req{socket=Socket, transport=Transport, connection=Connection, pid=ReqPid, method=Method, resp_state=waiting, resp_headers=RespHeaders}) -> @@ -586,7 +581,6 @@ chunked_reply(Status, Headers, Req=#http_req{socket=Socket, %% @doc Send a chunk of data. %% %% A chunked reply must have been initiated before calling this function. --spec chunk(iodata(), #http_req{}) -> ok | {error, atom()}. chunk(_Data, #http_req{socket=_Socket, transport=_Transport, method='HEAD'}) -> ok; chunk(Data, #http_req{socket=Socket, transport=Transport, resp_state=chunks}) -> -- 1.7.0.4 rabbitmq-server-3.2.4/plugins-src/rabbitmq-erlang-client/0000755000000000000000000000000012305126066022115 5ustar rootrootrabbitmq-server-3.2.4/plugins-src/rabbitmq-erlang-client/README.in0000755000000000000000000000053112305126066023404 0ustar rootrootREADME.in: Please see http://www.rabbitmq.com/build-erlang-client.html for build instructions. For your convenience, a text copy of these instructions is available below. Please be aware that the instructions here may not be as up to date as those at the above URL. =========================================================================== rabbitmq-server-3.2.4/plugins-src/rabbitmq-erlang-client/src/0000755000000000000000000000000012305126066022704 5ustar rootrootrabbitmq-server-3.2.4/plugins-src/rabbitmq-erlang-client/src/amqp_rpc_server.erl0000644000000000000000000001165112305126066026604 0ustar rootroot%% The contents of this file are subject to the Mozilla Public License %% Version 1.1 (the "License"); you may not use this file except in %% compliance with the License. You may obtain a copy of the License at %% http://www.mozilla.org/MPL/ %% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the %% License for the specific language governing rights and limitations %% under the License. %% %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is GoPivotal, Inc. %% Copyright (c) 2007-2013 GoPivotal, Inc. All rights reserved. %% %% @doc This is a utility module that is used to expose an arbitrary function %% via an asynchronous RPC over AMQP mechanism. It frees the implementor of %% a simple function from having to plumb this into AMQP. Note that the %% RPC server does not handle any data encoding, so it is up to the callback %% function to marshall and unmarshall message payloads accordingly. -module(amqp_rpc_server). -behaviour(gen_server). -include("amqp_client.hrl"). -export([init/1, terminate/2, code_change/3, handle_call/3, handle_cast/2, handle_info/2]). -export([start/3, start_link/3]). -export([stop/1]). -record(state, {channel, handler}). %%-------------------------------------------------------------------------- %% API %%-------------------------------------------------------------------------- %% @spec (Connection, Queue, RpcHandler) -> RpcServer %% where %% Connection = pid() %% Queue = binary() %% RpcHandler = function() %% RpcServer = pid() %% @doc Starts a new RPC server instance that receives requests via a %% specified queue and dispatches them to a specified handler function. This %% function returns the pid of the RPC server that can be used to stop the %% server. start(Connection, Queue, Fun) -> {ok, Pid} = gen_server:start(?MODULE, [Connection, Queue, Fun], []), Pid. %% @spec (Connection, Queue, RpcHandler) -> RpcServer %% where %% Connection = pid() %% Queue = binary() %% RpcHandler = function() %% RpcServer = pid() %% @doc Starts, and links to, a new RPC server instance that receives %% requests via a specified queue and dispatches them to a specified %% handler function. This function returns the pid of the RPC server that %% can be used to stop the server. start_link(Connection, Queue, Fun) -> {ok, Pid} = gen_server:start_link(?MODULE, [Connection, Queue, Fun], []), Pid. %% @spec (RpcServer) -> ok %% where %% RpcServer = pid() %% @doc Stops an exisiting RPC server. stop(Pid) -> gen_server:call(Pid, stop, infinity). %%-------------------------------------------------------------------------- %% gen_server callbacks %%-------------------------------------------------------------------------- %% @private init([Connection, Q, Fun]) -> {ok, Channel} = amqp_connection:open_channel( Connection, {amqp_direct_consumer, [self()]}), amqp_channel:call(Channel, #'queue.declare'{queue = Q}), amqp_channel:call(Channel, #'basic.consume'{queue = Q}), {ok, #state{channel = Channel, handler = Fun} }. %% @private handle_info(shutdown, State) -> {stop, normal, State}; %% @private handle_info({#'basic.consume'{}, _}, State) -> {noreply, State}; %% @private handle_info(#'basic.consume_ok'{}, State) -> {noreply, State}; %% @private handle_info(#'basic.cancel'{}, State) -> {noreply, State}; %% @private handle_info(#'basic.cancel_ok'{}, State) -> {stop, normal, State}; %% @private handle_info({#'basic.deliver'{delivery_tag = DeliveryTag}, #amqp_msg{props = Props, payload = Payload}}, State = #state{handler = Fun, channel = Channel}) -> #'P_basic'{correlation_id = CorrelationId, reply_to = Q} = Props, Response = Fun(Payload), Properties = #'P_basic'{correlation_id = CorrelationId}, Publish = #'basic.publish'{exchange = <<>>, routing_key = Q, mandatory = true}, amqp_channel:call(Channel, Publish, #amqp_msg{props = Properties, payload = Response}), amqp_channel:call(Channel, #'basic.ack'{delivery_tag = DeliveryTag}), {noreply, State}; %% @private handle_info({'DOWN', _MRef, process, _Pid, _Info}, State) -> {noreply, State}. %% @private handle_call(stop, _From, State) -> {stop, normal, ok, State}. %%-------------------------------------------------------------------------- %% Rest of the gen_server callbacks %%-------------------------------------------------------------------------- %% @private handle_cast(_Message, State) -> {noreply, State}. %% Closes the channel this gen_server instance started %% @private terminate(_Reason, #state{channel = Channel}) -> amqp_channel:close(Channel), ok. %% @private code_change(_OldVsn, State, _Extra) -> {ok, State}. rabbitmq-server-3.2.4/plugins-src/rabbitmq-erlang-client/src/overview.edoc.in0000644000000000000000000000347012305126066026017 0ustar rootroot@title AMQP Client for Erlang @author GoPivotal Inc. @copyright 2007-2013 GoPivotal, Inc. @version %%VERSION%% @reference AMQP documentation on the RabbitMQ website. @doc == Overview == This application provides an Erlang library to interact with an AMQP 0-9-1 compliant message broker. The module documentation assumes that the programmer has some basic familiarity with the execution model defined in the AMQP specification. The main components are {@link amqp_connection} and {@link amqp_channel}. The {@link amqp_connection} module is used to open and close connections to an AMQP broker as well as creating channels. The {@link amqp_channel} module is used to send and receive commands and messages to and from a broker within the context of a channel. == AMQP Record Definitions == Many of the API functions take structured records as arguments. These records represent the commands defined in the AMQP execution model. The definitions for these records are automatically generated by the rabbitmq-codegen project. rabbitmq-codegen parses a machine readable view of the specification and generates a header file that includes the entire command set of AMQP. Each command in AMQP has an identically named record. The protocol documentation serves as a reference for the attributes of each command. == Programming Model == For more information, refer to the Erlang AMQP client developer's guide on the RabbitMQ website. == RPC Components == The {@link amqp_rpc_server} module provides a generic building block to expose Erlang functions via an RPC over AMQP mechanism. The {@link amqp_rpc_client} provides a simple client utility to submit RPC requests to a server via AMQP. rabbitmq-server-3.2.4/plugins-src/rabbitmq-erlang-client/src/amqp_rpc_client.erl0000644000000000000000000001477012305126066026561 0ustar rootroot%% The contents of this file are subject to the Mozilla Public License %% Version 1.1 (the "License"); you may not use this file except in %% compliance with the License. You may obtain a copy of the License at %% http://www.mozilla.org/MPL/ %% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the %% License for the specific language governing rights and limitations %% under the License. %% %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is GoPivotal, Inc. %% Copyright (c) 2007-2013 GoPivotal, Inc. All rights reserved. %% %% @doc This module allows the simple execution of an asynchronous RPC over %% AMQP. It frees a client programmer of the necessary having to AMQP %% plumbing. Note that the this module does not handle any data encoding, %% so it is up to the caller to marshall and unmarshall message payloads %% accordingly. -module(amqp_rpc_client). -include("amqp_client.hrl"). -behaviour(gen_server). -export([start/2, start_link/2, stop/1]). -export([call/2]). -export([init/1, terminate/2, code_change/3, handle_call/3, handle_cast/2, handle_info/2]). -record(state, {channel, reply_queue, exchange, routing_key, continuations = dict:new(), correlation_id = 0}). %%-------------------------------------------------------------------------- %% API %%-------------------------------------------------------------------------- %% @spec (Connection, Queue) -> RpcClient %% where %% Connection = pid() %% Queue = binary() %% RpcClient = pid() %% @doc Starts a new RPC client instance that sends requests to a %% specified queue. This function returns the pid of the RPC client process %% that can be used to invoke RPCs and stop the client. start(Connection, Queue) -> {ok, Pid} = gen_server:start(?MODULE, [Connection, Queue], []), Pid. %% @spec (Connection, Queue) -> RpcClient %% where %% Connection = pid() %% Queue = binary() %% RpcClient = pid() %% @doc Starts, and links to, a new RPC client instance that sends requests %% to a specified queue. This function returns the pid of the RPC client %% process that can be used to invoke RPCs and stop the client. start_link(Connection, Queue) -> {ok, Pid} = gen_server:start_link(?MODULE, [Connection, Queue], []), Pid. %% @spec (RpcClient) -> ok %% where %% RpcClient = pid() %% @doc Stops an exisiting RPC client. stop(Pid) -> gen_server:call(Pid, stop, infinity). %% @spec (RpcClient, Payload) -> ok %% where %% RpcClient = pid() %% Payload = binary() %% @doc Invokes an RPC. Note the caller of this function is responsible for %% encoding the request and decoding the response. call(RpcClient, Payload) -> gen_server:call(RpcClient, {call, Payload}, infinity). %%-------------------------------------------------------------------------- %% Plumbing %%-------------------------------------------------------------------------- %% Sets up a reply queue for this client to listen on setup_reply_queue(State = #state{channel = Channel}) -> #'queue.declare_ok'{queue = Q} = amqp_channel:call(Channel, #'queue.declare'{}), State#state{reply_queue = Q}. %% Registers this RPC client instance as a consumer to handle rpc responses setup_consumer(#state{channel = Channel, reply_queue = Q}) -> amqp_channel:call(Channel, #'basic.consume'{queue = Q}). %% Publishes to the broker, stores the From address against %% the correlation id and increments the correlationid for %% the next request publish(Payload, From, State = #state{channel = Channel, reply_queue = Q, exchange = X, routing_key = RoutingKey, correlation_id = CorrelationId, continuations = Continuations}) -> EncodedCorrelationId = base64:encode(<>), Props = #'P_basic'{correlation_id = EncodedCorrelationId, content_type = <<"application/octet-stream">>, reply_to = Q}, Publish = #'basic.publish'{exchange = X, routing_key = RoutingKey, mandatory = true}, amqp_channel:call(Channel, Publish, #amqp_msg{props = Props, payload = Payload}), State#state{correlation_id = CorrelationId + 1, continuations = dict:store(EncodedCorrelationId, From, Continuations)}. %%-------------------------------------------------------------------------- %% gen_server callbacks %%-------------------------------------------------------------------------- %% Sets up a reply queue and consumer within an existing channel %% @private init([Connection, RoutingKey]) -> {ok, Channel} = amqp_connection:open_channel( Connection, {amqp_direct_consumer, [self()]}), InitialState = #state{channel = Channel, exchange = <<>>, routing_key = RoutingKey}, State = setup_reply_queue(InitialState), setup_consumer(State), {ok, State}. %% Closes the channel this gen_server instance started %% @private terminate(_Reason, #state{channel = Channel}) -> amqp_channel:close(Channel), ok. %% Handle the application initiated stop by just stopping this gen server %% @private handle_call(stop, _From, State) -> {stop, normal, ok, State}; %% @private handle_call({call, Payload}, From, State) -> NewState = publish(Payload, From, State), {noreply, NewState}. %% @private handle_cast(_Msg, State) -> {noreply, State}. %% @private handle_info({#'basic.consume'{}, _Pid}, State) -> {noreply, State}; %% @private handle_info(#'basic.consume_ok'{}, State) -> {noreply, State}; %% @private handle_info(#'basic.cancel'{}, State) -> {noreply, State}; %% @private handle_info(#'basic.cancel_ok'{}, State) -> {stop, normal, State}; %% @private handle_info({#'basic.deliver'{delivery_tag = DeliveryTag}, #amqp_msg{props = #'P_basic'{correlation_id = Id}, payload = Payload}}, State = #state{continuations = Conts, channel = Channel}) -> From = dict:fetch(Id, Conts), gen_server:reply(From, Payload), amqp_channel:call(Channel, #'basic.ack'{delivery_tag = DeliveryTag}), {noreply, State#state{continuations = dict:erase(Id, Conts) }}. %% @private code_change(_OldVsn, State, _Extra) -> {ok, State}. rabbitmq-server-3.2.4/plugins-src/rabbitmq-erlang-client/src/uri_parser.erl0000644000000000000000000001162312305126066025566 0ustar rootroot%% This file is a copy of http_uri.erl from the R13B-1 Erlang/OTP %% distribution with several modifications. %% All modifications are Copyright (c) 2009-2013 GoPivotal, Ltd. %% ``The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in %% compliance with the License. You should have received a copy of the %% Erlang Public License along with this software. If not, it can be %% retrieved via the world wide web at http://www.erlang.org/. %% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See %% the License for the specific language governing rights and limitations %% under the License. %% %% The Initial Developer of the Original Code is Ericsson Utvecklings AB. %% Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings %% AB. All Rights Reserved.'' %% See http://tools.ietf.org/html/rfc3986 -module(uri_parser). -export([parse/2]). %%%========================================================================= %%% API %%%========================================================================= %% Returns a key list of elements extracted from the URI. Note that %% only 'scheme' is guaranteed to exist. Key-Value pairs from the %% Defaults list will be used absence of a non-empty value extracted %% from the URI. The values extracted are strings, except for 'port' %% which is an integer, 'userinfo' which is a list of strings (split %% on $:), and 'query' which is a list of strings where no $= char %% found, or a {key,value} pair where a $= char is found (initial %% split on $& and subsequent optional split on $=). Possible keys %% are: 'scheme', 'userinfo', 'host', 'port', 'path', 'query', %% 'fragment'. parse(AbsURI, Defaults) -> case parse_scheme(AbsURI) of {error, Reason} -> {error, Reason}; {Scheme, Rest} -> case (catch parse_uri_rest(Rest, true)) of [_|_] = List -> merge_keylists([{scheme, Scheme} | List], Defaults); E -> {error, {malformed_uri, AbsURI, E}} end end. %%%======================================================================== %%% Internal functions %%%======================================================================== parse_scheme(AbsURI) -> split_uri(AbsURI, ":", {error, no_scheme}). parse_uri_rest("//" ++ URIPart, true) -> %% we have an authority {Authority, PathQueryFrag} = split_uri(URIPart, "/|\\?|#", {URIPart, ""}, 1, 0), AuthorityParts = parse_authority(Authority), parse_uri_rest(PathQueryFrag, false) ++ AuthorityParts; parse_uri_rest(PathQueryFrag, _Bool) -> %% no authority, just a path and maybe query {PathQuery, Frag} = split_uri(PathQueryFrag, "#", {PathQueryFrag, ""}), {Path, QueryString} = split_uri(PathQuery, "\\?", {PathQuery, ""}), QueryPropList = split_query(QueryString), [{path, Path}, {'query', QueryPropList}, {fragment, Frag}]. parse_authority(Authority) -> {UserInfo, HostPort} = split_uri(Authority, "@", {"", Authority}), UserInfoSplit = case re:split(UserInfo, ":", [{return, list}]) of [""] -> []; UIS -> UIS end, [{userinfo, UserInfoSplit} | parse_host_port(HostPort)]. parse_host_port("[" ++ HostPort) -> %ipv6 {Host, ColonPort} = split_uri(HostPort, "\\]", {HostPort, ""}), [{host, Host} | case split_uri(ColonPort, ":", not_found, 0, 1) of not_found -> case ColonPort of [] -> []; _ -> throw({invalid_port, ColonPort}) end; {_, Port} -> [{port, list_to_integer(Port)}] end]; parse_host_port(HostPort) -> {Host, Port} = split_uri(HostPort, ":", {HostPort, not_found}), [{host, Host} | case Port of not_found -> []; _ -> [{port, list_to_integer(Port)}] end]. split_query(Query) -> case re:split(Query, "&", [{return, list}]) of [""] -> []; QParams -> [split_uri(Param, "=", Param) || Param <- QParams] end. split_uri(UriPart, SplitChar, NoMatchResult) -> split_uri(UriPart, SplitChar, NoMatchResult, 1, 1). split_uri(UriPart, SplitChar, NoMatchResult, SkipLeft, SkipRight) -> case re:run(UriPart, SplitChar) of {match, [{Match, _}]} -> {string:substr(UriPart, 1, Match + 1 - SkipLeft), string:substr(UriPart, Match + 1 + SkipRight, length(UriPart))}; nomatch -> NoMatchResult end. merge_keylists(A, B) -> {AEmpty, ANonEmpty} = lists:partition(fun ({_Key, V}) -> V =:= [] end, A), [AEmptyS, ANonEmptyS, BS] = [lists:ukeysort(1, X) || X <- [AEmpty, ANonEmpty, B]], lists:ukeymerge(1, lists:ukeymerge(1, ANonEmptyS, BS), AEmptyS). rabbitmq-server-3.2.4/plugins-src/rabbitmq-erlang-client/src/amqp_channel_sup.erl0000644000000000000000000000603412305126066026730 0ustar rootroot%% The contents of this file are subject to the Mozilla Public License %% Version 1.1 (the "License"); you may not use this file except in %% compliance with the License. You may obtain a copy of the License at %% http://www.mozilla.org/MPL/ %% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the %% License for the specific language governing rights and limitations %% under the License. %% %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is GoPivotal, Inc. %% Copyright (c) 2007-2013 GoPivotal, Inc. All rights reserved. %% %% @private -module(amqp_channel_sup). -include("amqp_client_internal.hrl"). -behaviour(supervisor2). -export([start_link/5]). -export([init/1]). %%--------------------------------------------------------------------------- %% Interface %%--------------------------------------------------------------------------- start_link(Type, Connection, InfraArgs, ChNumber, Consumer = {_, _}) -> {ok, Sup} = supervisor2:start_link(?MODULE, [Consumer]), [{gen_consumer, ConsumerPid, _, _}] = supervisor2:which_children(Sup), {ok, ChPid} = supervisor2:start_child( Sup, {channel, {amqp_channel, start_link, [Type, Connection, ChNumber, ConsumerPid]}, intrinsic, ?MAX_WAIT, worker, [amqp_channel]}), Writer = start_writer(Sup, Type, InfraArgs, ChNumber, ChPid), amqp_channel:set_writer(ChPid, Writer), {ok, AState} = init_command_assembler(Type), {ok, Sup, {ChPid, AState}}. %%--------------------------------------------------------------------------- %% Internal plumbing %%--------------------------------------------------------------------------- start_writer(_Sup, direct, [ConnPid, ConnName, Node, User, VHost, Collector], ChNumber, ChPid) -> {ok, RabbitCh} = rpc:call(Node, rabbit_direct, start_channel, [ChNumber, ChPid, ConnPid, ConnName, ?PROTOCOL, User, VHost, ?CLIENT_CAPABILITIES, Collector]), link(RabbitCh), RabbitCh; start_writer(Sup, network, [Sock, FrameMax], ChNumber, ChPid) -> {ok, Writer} = supervisor2:start_child( Sup, {writer, {rabbit_writer, start_link, [Sock, ChNumber, FrameMax, ?PROTOCOL, ChPid]}, intrinsic, ?MAX_WAIT, worker, [rabbit_writer]}), Writer. init_command_assembler(direct) -> {ok, none}; init_command_assembler(network) -> rabbit_command_assembler:init(?PROTOCOL). %%--------------------------------------------------------------------------- %% supervisor2 callbacks %%--------------------------------------------------------------------------- init([{ConsumerModule, ConsumerArgs}]) -> {ok, {{one_for_all, 0, 1}, [{gen_consumer, {amqp_gen_consumer, start_link, [ConsumerModule, ConsumerArgs]}, intrinsic, ?MAX_WAIT, worker, [amqp_gen_consumer]}]}}. rabbitmq-server-3.2.4/plugins-src/rabbitmq-erlang-client/src/amqp_channel_sup_sup.erl0000644000000000000000000000311712305126066027616 0ustar rootroot%% The contents of this file are subject to the Mozilla Public License %% Version 1.1 (the "License"); you may not use this file except in %% compliance with the License. You may obtain a copy of the License at %% http://www.mozilla.org/MPL/ %% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the %% License for the specific language governing rights and limitations %% under the License. %% %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is GoPivotal, Inc. %% Copyright (c) 2007-2013 GoPivotal, Inc. All rights reserved. %% %% @private -module(amqp_channel_sup_sup). -include("amqp_client.hrl"). -behaviour(supervisor2). -export([start_link/2, start_channel_sup/4]). -export([init/1]). %%--------------------------------------------------------------------------- %% Interface %%--------------------------------------------------------------------------- start_link(Type, Connection) -> supervisor2:start_link(?MODULE, [Type, Connection]). start_channel_sup(Sup, InfraArgs, ChannelNumber, Consumer) -> supervisor2:start_child(Sup, [InfraArgs, ChannelNumber, Consumer]). %%--------------------------------------------------------------------------- %% supervisor2 callbacks %%--------------------------------------------------------------------------- init([Type, Connection]) -> {ok, {{simple_one_for_one, 0, 1}, [{channel_sup, {amqp_channel_sup, start_link, [Type, Connection]}, temporary, brutal_kill, supervisor, [amqp_channel_sup]}]}}. rabbitmq-server-3.2.4/plugins-src/rabbitmq-erlang-client/src/amqp_gen_connection.erl0000644000000000000000000003566212305126066027432 0ustar rootroot%% The contents of this file are subject to the Mozilla Public License %% Version 1.1 (the "License"); you may not use this file except in %% compliance with the License. You may obtain a copy of the License at %% http://www.mozilla.org/MPL/ %% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the %% License for the specific language governing rights and limitations %% under the License. %% %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is GoPivotal, Inc. %% Copyright (c) 2007-2013 GoPivotal, Inc. All rights reserved. %% %% @private -module(amqp_gen_connection). -include("amqp_client_internal.hrl"). -behaviour(gen_server). -export([start_link/2, connect/1, open_channel/3, hard_error_in_channel/3, channel_internal_error/3, server_misbehaved/2, channels_terminated/1, close/3, server_close/2, info/2, info_keys/0, info_keys/1, register_blocked_handler/2]). -export([behaviour_info/1]). -export([init/1, terminate/2, code_change/3, handle_call/3, handle_cast/2, handle_info/2]). -define(INFO_KEYS, [server_properties, is_closing, amqp_params, num_channels, channel_max]). -record(state, {module, module_state, channels_manager, amqp_params, channel_max, server_properties, %% connection.block, connection.unblock handler block_handler, closing = false %% #closing{} | false }). -record(closing, {reason, close, from = none}). %%--------------------------------------------------------------------------- %% Interface %%--------------------------------------------------------------------------- start_link(TypeSup, AMQPParams) -> gen_server:start_link(?MODULE, {TypeSup, AMQPParams}, []). connect(Pid) -> gen_server:call(Pid, connect, infinity). open_channel(Pid, ProposedNumber, Consumer) -> case gen_server:call(Pid, {command, {open_channel, ProposedNumber, Consumer}}, infinity) of {ok, ChannelPid} -> ok = amqp_channel:open(ChannelPid), {ok, ChannelPid}; Error -> Error end. hard_error_in_channel(Pid, ChannelPid, Reason) -> gen_server:cast(Pid, {hard_error_in_channel, ChannelPid, Reason}). channel_internal_error(Pid, ChannelPid, Reason) -> gen_server:cast(Pid, {channel_internal_error, ChannelPid, Reason}). server_misbehaved(Pid, AmqpError) -> gen_server:cast(Pid, {server_misbehaved, AmqpError}). channels_terminated(Pid) -> gen_server:cast(Pid, channels_terminated). close(Pid, Close, Timeout) -> gen_server:call(Pid, {command, {close, Close, Timeout}}, infinity). server_close(Pid, Close) -> gen_server:cast(Pid, {server_close, Close}). info(Pid, Items) -> gen_server:call(Pid, {info, Items}, infinity). info_keys() -> ?INFO_KEYS. info_keys(Pid) -> gen_server:call(Pid, info_keys, infinity). %%--------------------------------------------------------------------------- %% Behaviour %%--------------------------------------------------------------------------- behaviour_info(callbacks) -> [ %% init() -> {ok, InitialState} {init, 0}, %% terminate(Reason, FinalState) -> Ignored {terminate, 2}, %% connect(AmqpParams, SIF, TypeSup, State) -> %% {ok, ConnectParams} | {closing, ConnectParams, AmqpError, Reply} | %% {error, Error} %% where %% ConnectParams = {ServerProperties, ChannelMax, NewState} {connect, 4}, %% do(Method, State) -> Ignored {do, 2}, %% open_channel_args(State) -> OpenChannelArgs {open_channel_args, 1}, %% i(InfoItem, State) -> Info {i, 2}, %% info_keys() -> [InfoItem] {info_keys, 0}, %% CallbackReply = {ok, NewState} | {stop, Reason, FinalState} %% handle_message(Message, State) -> CallbackReply {handle_message, 2}, %% closing(flush|abrupt, Reason, State) -> CallbackReply {closing, 3}, %% channels_terminated(State) -> CallbackReply {channels_terminated, 1} ]; behaviour_info(_Other) -> undefined. callback(Function, Params, State = #state{module = Mod, module_state = MState}) -> case erlang:apply(Mod, Function, Params ++ [MState]) of {ok, NewMState} -> {noreply, State#state{module_state = NewMState}}; {stop, Reason, NewMState} -> {stop, Reason, State#state{module_state = NewMState}} end. %%--------------------------------------------------------------------------- %% gen_server callbacks %%--------------------------------------------------------------------------- init({TypeSup, AMQPParams}) -> %% Trapping exits since we need to make sure that the `terminate/2' is %% called in the case of direct connection (it does not matter for a network %% connection). See bug25116. process_flag(trap_exit, true), %% connect() has to be called first, so we can use a special state here {ok, {TypeSup, AMQPParams}}. handle_call(connect, _From, {TypeSup, AMQPParams}) -> {Type, Mod} = amqp_connection_type_sup:type_module(AMQPParams), {ok, MState} = Mod:init(), {ok, SIF, ChMgr} = amqp_connection_type_sup:start_infrastructure( TypeSup, self(), Type), State = #state{module = Mod, module_state = MState, channels_manager = ChMgr, amqp_params = AMQPParams, block_handler = none}, case Mod:connect(AMQPParams, SIF, TypeSup, MState) of {ok, Params} -> {reply, {ok, self()}, after_connect(Params, State)}; {closing, #amqp_error{name = access_refused} = AmqpError, Error} -> {stop, {shutdown, AmqpError}, Error, State}; {closing, Params, #amqp_error{} = AmqpError, Error} -> server_misbehaved(self(), AmqpError), {reply, Error, after_connect(Params, State)}; {error, _} = Error -> {stop, {shutdown, Error}, Error, State} end; handle_call({command, Command}, From, State = #state{closing = false}) -> handle_command(Command, From, State); handle_call({command, _Command}, _From, State) -> {reply, closing, State}; handle_call({info, Items}, _From, State) -> {reply, [{Item, i(Item, State)} || Item <- Items], State}; handle_call(info_keys, _From, State = #state{module = Mod}) -> {reply, ?INFO_KEYS ++ Mod:info_keys(), State}. after_connect({ServerProperties, ChannelMax, NewMState}, State = #state{channels_manager = ChMgr}) -> case ChannelMax of 0 -> ok; _ -> amqp_channels_manager:set_channel_max(ChMgr, ChannelMax) end, State#state{server_properties = ServerProperties, channel_max = ChannelMax, module_state = NewMState}. handle_cast({method, Method, none, noflow}, State) -> handle_method(Method, State); handle_cast(channels_terminated, State) -> handle_channels_terminated(State); handle_cast({hard_error_in_channel, _Pid, Reason}, State) -> server_initiated_close(Reason, State); handle_cast({channel_internal_error, Pid, Reason}, State) -> ?LOG_WARN("Connection (~p) closing: internal error in channel (~p): ~p~n", [self(), Pid, Reason]), internal_error(State); handle_cast({server_misbehaved, AmqpError}, State) -> server_misbehaved_close(AmqpError, State); handle_cast({server_close, #'connection.close'{} = Close}, State) -> server_initiated_close(Close, State); handle_cast({register_blocked_handler, HandlerPid}, State) -> Ref = erlang:monitor(process, HandlerPid), {noreply, State#state{block_handler = {HandlerPid, Ref}}}. %% @private handle_info({'DOWN', _, process, BlockHandler, Reason}, State = #state{block_handler = {BlockHandler, _Ref}}) -> ?LOG_WARN("Connection (~p): Unregistering block handler ~p because it died. " "Reason: ~p~n", [self(), BlockHandler, Reason]), {noreply, State#state{block_handler = none}}; handle_info(Info, State) -> callback(handle_message, [Info], State). terminate(Reason, #state{module = Mod, module_state = MState}) -> Mod:terminate(Reason, MState). code_change(_OldVsn, State, _Extra) -> {ok, State}. %%--------------------------------------------------------------------------- %% Infos %%--------------------------------------------------------------------------- i(server_properties, State) -> State#state.server_properties; i(is_closing, State) -> State#state.closing =/= false; i(amqp_params, State) -> State#state.amqp_params; i(channel_max, State) -> State#state.channel_max; i(num_channels, State) -> amqp_channels_manager:num_channels( State#state.channels_manager); i(Item, #state{module = Mod, module_state = MState}) -> Mod:i(Item, MState). %%--------------------------------------------------------------------------- %% connection.blocked, connection.unblocked %%--------------------------------------------------------------------------- register_blocked_handler(Pid, HandlerPid) -> gen_server:cast(Pid, {register_blocked_handler, HandlerPid}). %%--------------------------------------------------------------------------- %% Command handling %%--------------------------------------------------------------------------- handle_command({open_channel, ProposedNumber, Consumer}, _From, State = #state{channels_manager = ChMgr, module = Mod, module_state = MState}) -> {reply, amqp_channels_manager:open_channel(ChMgr, ProposedNumber, Consumer, Mod:open_channel_args(MState)), State}; handle_command({close, #'connection.close'{} = Close, Timeout}, From, State) -> app_initiated_close(Close, From, Timeout, State). %%--------------------------------------------------------------------------- %% Handling methods from broker %%--------------------------------------------------------------------------- handle_method(#'connection.close'{} = Close, State) -> server_initiated_close(Close, State); handle_method(#'connection.close_ok'{}, State = #state{closing = Closing}) -> case Closing of #closing{from = none} -> ok; #closing{from = From} -> gen_server:reply(From, ok) end, {stop, {shutdown, closing_to_reason(Closing)}, State}; handle_method(#'connection.blocked'{} = Blocked, State = #state{block_handler = BlockHandler}) -> case BlockHandler of none -> ok; {Pid, _Ref} -> Pid ! Blocked end, {noreply, State}; handle_method(#'connection.unblocked'{} = Unblocked, State = #state{block_handler = BlockHandler}) -> case BlockHandler of none -> ok; {Pid, _Ref} -> Pid ! Unblocked end, {noreply, State}; handle_method(Other, State) -> server_misbehaved_close(#amqp_error{name = command_invalid, explanation = "unexpected method on " "channel 0", method = element(1, Other)}, State). %%--------------------------------------------------------------------------- %% Closing %%--------------------------------------------------------------------------- app_initiated_close(Close, From, Timeout, State) -> case Timeout of infinity -> ok; _ -> erlang:send_after(Timeout, self(), closing_timeout) end, set_closing_state(flush, #closing{reason = app_initiated_close, close = Close, from = From}, State). internal_error(State) -> Close = #'connection.close'{reply_text = <<>>, reply_code = ?INTERNAL_ERROR, class_id = 0, method_id = 0}, set_closing_state(abrupt, #closing{reason = internal_error, close = Close}, State). server_initiated_close(Close, State) -> ?LOG_WARN("Connection (~p) closing: received hard error ~p " "from server~n", [self(), Close]), set_closing_state(abrupt, #closing{reason = server_initiated_close, close = Close}, State). server_misbehaved_close(AmqpError, State) -> ?LOG_WARN("Connection (~p) closing: server misbehaved: ~p~n", [self(), AmqpError]), {0, Close} = rabbit_binary_generator:map_exception(0, AmqpError, ?PROTOCOL), set_closing_state(abrupt, #closing{reason = server_misbehaved, close = Close}, State). set_closing_state(ChannelCloseType, NewClosing, State = #state{channels_manager = ChMgr, closing = CurClosing}) -> ResClosing = case closing_priority(NewClosing) =< closing_priority(CurClosing) of true -> NewClosing; false -> CurClosing end, ClosingReason = closing_to_reason(ResClosing), amqp_channels_manager:signal_connection_closing(ChMgr, ChannelCloseType, ClosingReason), callback(closing, [ChannelCloseType, ClosingReason], State#state{closing = ResClosing}). closing_priority(false) -> 99; closing_priority(#closing{reason = app_initiated_close}) -> 4; closing_priority(#closing{reason = internal_error}) -> 3; closing_priority(#closing{reason = server_misbehaved}) -> 2; closing_priority(#closing{reason = server_initiated_close}) -> 1. closing_to_reason(#closing{close = #'connection.close'{reply_code = 200}}) -> normal; closing_to_reason(#closing{reason = Reason, close = #'connection.close'{reply_code = Code, reply_text = Text}}) -> {Reason, Code, Text}; closing_to_reason(#closing{reason = Reason, close = {Reason, _Code, _Text} = Close}) -> Close. handle_channels_terminated(State = #state{closing = Closing, module = Mod, module_state = MState}) -> #closing{reason = Reason, close = Close, from = From} = Closing, case Reason of server_initiated_close -> Mod:do(#'connection.close_ok'{}, MState); _ -> Mod:do(Close, MState) end, case callback(channels_terminated, [], State) of {stop, _, _} = Stop -> case From of none -> ok; _ -> gen_server:reply(From, ok) end, Stop; Other -> Other end. rabbitmq-server-3.2.4/plugins-src/rabbitmq-erlang-client/src/amqp_connection.erl0000644000000000000000000003466212305126066026600 0ustar rootroot%% The contents of this file are subject to the Mozilla Public License %% Version 1.1 (the "License"); you may not use this file except in %% compliance with the License. You may obtain a copy of the License at %% http://www.mozilla.org/MPL/ %% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the %% License for the specific language governing rights and limitations %% under the License. %% %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is GoPivotal, Inc. %% Copyright (c) 2007-2013 GoPivotal, Inc. All rights reserved. %% %% @type close_reason(Type) = {shutdown, amqp_reason(Type)}. %% @type amqp_reason(Type) = {Type, Code, Text} %% Code = non_neg_integer() %% Text = binary(). %% @doc This module is responsible for maintaining a connection to an AMQP %% broker and manages channels within the connection. This module is used to %% open and close connections to the broker as well as creating new channels %% within a connection.
    %% The connections and channels created by this module are supervised under %% amqp_client's supervision tree. Please note that connections and channels %% do not get restarted automatically by the supervision tree in the case of a %% failure. If you need robust connections and channels, we recommend you use %% Erlang monitors on the returned connection and channel PIDs.
    %%
    %% In case of a failure or an AMQP error, the connection process exits with a %% meaningful exit reason:
    %%
    %% %% %% %% %% %% %% %% %% %% %% %% %% %% %% %% %% %% %% %% %% %% %% %% %% %% %% %% %% %%
    CauseExit reason
    Any reason, where Code would have been 200 otherwise```normal'''
    User application calls amqp_connection:close/3```close_reason(app_initiated_close)'''
    Server closes connection (hard error)```close_reason(server_initiated_close)'''
    Server misbehaved (did not follow protocol)```close_reason(server_misbehaved)'''
    AMQP client internal error - usually caused by a channel exiting %% with an unusual reason. This is usually accompanied by a more %% detailed error log from the channel```close_reason(internal_error)'''
    Other error(various error reasons, causing more detailed logging)
    %%
    %% See type definitions below. -module(amqp_connection). -include("amqp_client_internal.hrl"). -export([open_channel/1, open_channel/2, open_channel/3, register_blocked_handler/2]). -export([start/1, close/1, close/2, close/3]). -export([error_atom/1]). -export([info/2, info_keys/1, info_keys/0]). -export([socket_adapter_info/2]). -define(DEFAULT_CONSUMER, {amqp_selective_consumer, []}). -define(PROTOCOL_SSL_PORT, (?PROTOCOL_PORT - 1)). %%--------------------------------------------------------------------------- %% Type Definitions %%--------------------------------------------------------------------------- %% @type amqp_adapter_info() = #amqp_adapter_info{}. %% @type amqp_params_direct() = #amqp_params_direct{}. %% As defined in amqp_client.hrl. It contains the following fields: %%
      %%
    • username :: binary() - The name of a user registered with the broker, %% defaults to <<guest">>
    • %%
    • password :: binary() - The password of user, defaults to 'none'
    • %%
    • virtual_host :: binary() - The name of a virtual host in the broker, %% defaults to <<"/">>
    • %%
    • node :: atom() - The node the broker runs on (direct only)
    • %%
    • adapter_info :: amqp_adapter_info() - Extra management information for if %% this connection represents a non-AMQP network connection.
    • %%
    • client_properties :: [{binary(), atom(), binary()}] - A list of extra %% client properties to be sent to the server, defaults to []
    • %%
    %% %% @type amqp_params_network() = #amqp_params_network{}. %% As defined in amqp_client.hrl. It contains the following fields: %%
      %%
    • username :: binary() - The name of a user registered with the broker, %% defaults to <<guest">>
    • %%
    • password :: binary() - The user's password, defaults to %% <<"guest">>
    • %%
    • virtual_host :: binary() - The name of a virtual host in the broker, %% defaults to <<"/">>
    • %%
    • host :: string() - The hostname of the broker, %% defaults to "localhost" (network only)
    • %%
    • port :: integer() - The port the broker is listening on, %% defaults to 5672 (network only)
    • %%
    • channel_max :: non_neg_integer() - The channel_max handshake parameter, %% defaults to 0
    • %%
    • frame_max :: non_neg_integer() - The frame_max handshake parameter, %% defaults to 0 (network only)
    • %%
    • heartbeat :: non_neg_integer() - The hearbeat interval in seconds, %% defaults to 0 (turned off) (network only)
    • %%
    • connection_timeout :: non_neg_integer() | 'infinity' %% - The connection timeout in milliseconds, %% defaults to 'infinity' (network only)
    • %%
    • ssl_options :: term() - The second parameter to be used with the %% ssl:connect/2 function, defaults to 'none' (network only)
    • %%
    • client_properties :: [{binary(), atom(), binary()}] - A list of extra %% client properties to be sent to the server, defaults to []
    • %%
    • socket_options :: [any()] - Extra socket options. These are %% appended to the default options. See %% inet:setopts/2 %% and %% gen_tcp:connect/4 for descriptions of the available options.
    • %%
    %%--------------------------------------------------------------------------- %% Starting a connection %%--------------------------------------------------------------------------- %% @spec (Params) -> {ok, Connection} | {error, Error} %% where %% Params = amqp_params_network() | amqp_params_direct() %% Connection = pid() %% @doc Starts a connection to an AMQP server. Use network params to %% connect to a remote AMQP server or direct params for a direct %% connection to a RabbitMQ server, assuming that the server is %% running in the same process space. If the port is set to 'undefined', %% the default ports will be selected depending on whether this is a %% normal or an SSL connection. start(AmqpParams) -> ensure_started(), AmqpParams1 = case AmqpParams of #amqp_params_network{port = undefined, ssl_options = none} -> AmqpParams#amqp_params_network{port = ?PROTOCOL_PORT}; #amqp_params_network{port = undefined, ssl_options = _} -> AmqpParams#amqp_params_network{port = ?PROTOCOL_SSL_PORT}; _ -> AmqpParams end, {ok, _Sup, Connection} = amqp_sup:start_connection_sup(AmqpParams1), amqp_gen_connection:connect(Connection). %% Usually the amqp_client application will already be running. We %% check whether that is the case by invoking an undocumented function %% which does not require a synchronous call to the application %% controller. That way we don't risk a dead-lock if, say, the %% application controller is in the process of shutting down the very %% application which is making this call. ensure_started() -> case application_controller:get_master(amqp_client) of undefined -> case amqp_client:start() of ok -> ok; {error, {already_started, amqp_client}} -> ok; {error, _} = E -> throw(E) end; _ -> ok end. %%--------------------------------------------------------------------------- %% Commands %%--------------------------------------------------------------------------- %% @doc Invokes open_channel(ConnectionPid, none, %% {amqp_selective_consumer, []}). Opens a channel without having to %% specify a channel number. This uses the default consumer %% implementation. open_channel(ConnectionPid) -> open_channel(ConnectionPid, none, ?DEFAULT_CONSUMER). %% @doc Invokes open_channel(ConnectionPid, none, Consumer). %% Opens a channel without having to specify a channel number. open_channel(ConnectionPid, {_, _} = Consumer) -> open_channel(ConnectionPid, none, Consumer); %% @doc Invokes open_channel(ConnectionPid, ChannelNumber, %% {amqp_selective_consumer, []}). Opens a channel, using the default %% consumer implementation. open_channel(ConnectionPid, ChannelNumber) when is_number(ChannelNumber) orelse ChannelNumber =:= none -> open_channel(ConnectionPid, ChannelNumber, ?DEFAULT_CONSUMER). %% @spec (ConnectionPid, ChannelNumber, Consumer) -> Result %% where %% ConnectionPid = pid() %% ChannelNumber = pos_integer() | 'none' %% Consumer = {ConsumerModule, ConsumerArgs} %% ConsumerModule = atom() %% ConsumerArgs = [any()] %% Result = {ok, ChannelPid} | {error, Error} %% ChannelPid = pid() %% @doc Opens an AMQP channel.
    %% Opens a channel, using a proposed channel number and a specific consumer %% implementation.
    %% ConsumerModule must implement the amqp_gen_consumer behaviour. ConsumerArgs %% is passed as parameter to ConsumerModule:init/1.
    %% This function assumes that an AMQP connection (networked or direct) %% has already been successfully established.
    %% ChannelNumber must be less than or equal to the negotiated %% max_channel value, or less than or equal to ?MAX_CHANNEL_NUMBER %% (65535) if the negotiated max_channel value is 0.
    %% In the direct connection, max_channel is always 0. open_channel(ConnectionPid, ChannelNumber, {_ConsumerModule, _ConsumerArgs} = Consumer) -> amqp_gen_connection:open_channel(ConnectionPid, ChannelNumber, Consumer). %% @spec (ConnectionPid) -> ok | Error %% where %% ConnectionPid = pid() %% @doc Closes the channel, invokes %% close(Channel, 200, <<"Goodbye">>). close(ConnectionPid) -> close(ConnectionPid, 200, <<"Goodbye">>). %% @spec (ConnectionPid, Timeout) -> ok | Error %% where %% ConnectionPid = pid() %% Timeout = integer() %% @doc Closes the channel, using the supplied Timeout value. close(ConnectionPid, Timeout) -> close(ConnectionPid, 200, <<"Goodbye">>, Timeout). %% @spec (ConnectionPid, Code, Text) -> ok | closing %% where %% ConnectionPid = pid() %% Code = integer() %% Text = binary() %% @doc Closes the AMQP connection, allowing the caller to set the reply %% code and text. close(ConnectionPid, Code, Text) -> close(ConnectionPid, Code, Text, infinity). %% @spec (ConnectionPid, Code, Text, Timeout) -> ok | closing %% where %% ConnectionPid = pid() %% Code = integer() %% Text = binary() %% Timeout = integer() %% @doc Closes the AMQP connection, allowing the caller to set the reply %% code and text, as well as a timeout for the operation, after which the %% connection will be abruptly terminated. close(ConnectionPid, Code, Text, Timeout) -> Close = #'connection.close'{reply_text = Text, reply_code = Code, class_id = 0, method_id = 0}, amqp_gen_connection:close(ConnectionPid, Close, Timeout). register_blocked_handler(ConnectionPid, BlockHandler) -> amqp_gen_connection:register_blocked_handler(ConnectionPid, BlockHandler). %%--------------------------------------------------------------------------- %% Other functions %%--------------------------------------------------------------------------- %% @spec (Code) -> atom() %% where %% Code = integer() %% @doc Returns a descriptive atom corresponding to the given AMQP %% error code. error_atom(Code) -> ?PROTOCOL:amqp_exception(Code). %% @spec (ConnectionPid, Items) -> ResultList %% where %% ConnectionPid = pid() %% Items = [Item] %% ResultList = [{Item, Result}] %% Item = atom() %% Result = term() %% @doc Returns information about the connection, as specified by the Items %% list. Item may be any atom returned by info_keys/1: %%
      %%
    • type - returns the type of the connection (network or direct)
    • %%
    • server_properties - returns the server_properties fields sent by the %% server while establishing the connection
    • %%
    • is_closing - returns true if the connection is in the process of closing %% and false otherwise
    • %%
    • amqp_params - returns the #amqp_params{} structure used to start the %% connection
    • %%
    • num_channels - returns the number of channels currently open under the %% connection (excluding channel 0)
    • %%
    • channel_max - returns the channel_max value negotiated with the %% server
    • %%
    • heartbeat - returns the heartbeat value negotiated with the server %% (only for the network connection)
    • %%
    • frame_max - returns the frame_max value negotiated with the %% server (only for the network connection)
    • %%
    • sock - returns the socket for the network connection (for use with %% e.g. inet:sockname/1) (only for the network connection)
    • %%
    • any other value - throws an exception
    • %%
    info(ConnectionPid, Items) -> amqp_gen_connection:info(ConnectionPid, Items). %% @spec (ConnectionPid) -> Items %% where %% ConnectionPid = pid() %% Items = [Item] %% Item = atom() %% @doc Returns a list of atoms that can be used in conjunction with info/2. %% Note that the list differs from a type of connection to another (network vs. %% direct). Use info_keys/0 to get a list of info keys that can be used for %% any connection. info_keys(ConnectionPid) -> amqp_gen_connection:info_keys(ConnectionPid). %% @spec () -> Items %% where %% Items = [Item] %% Item = atom() %% @doc Returns a list of atoms that can be used in conjunction with info/2. %% These are general info keys, which can be used in any type of connection. %% Other info keys may exist for a specific type. To get the full list of %% atoms that can be used for a certain connection, use info_keys/1. info_keys() -> amqp_gen_connection:info_keys(). %% @doc Takes a socket and a protocol, returns an #amqp_adapter_info{} %% based on the socket for the protocol given. socket_adapter_info(Sock, Protocol) -> amqp_direct_connection:socket_adapter_info(Sock, Protocol). rabbitmq-server-3.2.4/plugins-src/rabbitmq-erlang-client/src/amqp_direct_consumer.erl0000644000000000000000000000576112305126066027624 0ustar rootroot%% The contents of this file are subject to the Mozilla Public License %% Version 1.1 (the "License"); you may not use this file except in %% compliance with the License. You may obtain a copy of the License at %% http://www.mozilla.org/MPL/ %% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the %% License for the specific language governing rights and limitations %% under the License. %% %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is GoPivotal, Inc. %% Copyright (c) 2011-2013 GoPivotal, Inc. All rights reserved. %% %% @doc This module is an implementation of the amqp_gen_consumer %% behaviour and can be used as part of the Consumer parameter when %% opening AMQP channels. %%
    %%
    %% The Consumer parameter for this implementation is {{@module}, %% [ConsumerPid]@}, where ConsumerPid is a process that will receive %% queue subscription-related messages.
    %%
    %% This consumer implementation causes the channel to send to the %% ConsumerPid all basic.consume, basic.consume_ok, basic.cancel, %% basic.cancel_ok and basic.deliver messages received from the %% server. %%
    %%
    %% In addition, this consumer implementation monitors the ConsumerPid %% and exits with the same shutdown reason when it dies. 'DOWN' %% messages from other sources are passed to ConsumerPid. %%
    %% Warning! It is not recommended to rely on a consumer on killing off the %% channel (through the exit signal). That may cause messages to get lost. %% Always use amqp_channel:close/{1,3} for a clean shut down.
    %%
    %% This module has no public functions. -module(amqp_direct_consumer). -include("amqp_gen_consumer_spec.hrl"). -behaviour(amqp_gen_consumer). -export([init/1, handle_consume_ok/3, handle_consume/3, handle_cancel_ok/3, handle_cancel/2, handle_server_cancel/2, handle_deliver/3, handle_info/2, handle_call/3, terminate/2]). %%--------------------------------------------------------------------------- %% amqp_gen_consumer callbacks %%--------------------------------------------------------------------------- %% @private init([ConsumerPid]) -> erlang:monitor(process, ConsumerPid), {ok, ConsumerPid}. %% @private handle_consume(M, A, C) -> C ! {M, A}, {ok, C}. %% @private handle_consume_ok(M, _, C) -> C ! M, {ok, C}. %% @private handle_cancel(M, C) -> C ! M, {ok, C}. %% @private handle_cancel_ok(M, _, C) -> C ! M, {ok, C}. %% @private handle_server_cancel(M, C) -> C ! {server_cancel, M}, {ok, C}. %% @private handle_deliver(M, A, C) -> C ! {M, A}, {ok, C}. %% @private handle_info({'DOWN', _MRef, process, C, Info}, C) -> {error, {consumer_died, Info}, C}; handle_info({'DOWN', MRef, process, Pid, Info}, C) -> C ! {'DOWN', MRef, process, Pid, Info}, {ok, C}. %% @private handle_call(M, A, C) -> C ! {M, A}, {reply, ok, C}. %% @private terminate(_Reason, C) -> C. rabbitmq-server-3.2.4/plugins-src/rabbitmq-erlang-client/src/amqp_selective_consumer.erl0000644000000000000000000002361012305126066030326 0ustar rootroot%% The contents of this file are subject to the Mozilla Public Licensbe %% Version 1.1 (the "License"); you may not use this file except in %% compliance with the License. You may obtain a copy of the License at %% http://www.mozilla.org/MPL/ %% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the %% License for the specific language governing rights and limitations %% under the License. %% %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is GoPivotal, Inc. %% Copyright (c) 2011-2013 GoPivotal, Inc. All rights reserved. %% %% @doc This module is an implementation of the amqp_gen_consumer %% behaviour and can be used as part of the Consumer parameter when %% opening AMQP channels. This is the default implementation selected %% by channel.
    %%
    %% The Consumer parameter for this implementation is {{@module}, []@}
    %% This consumer implementation keeps track of consumer tags and sends %% the subscription-relevant messages to the registered consumers, according %% to an internal tag dictionary.
    %%
    %% Send a #basic.consume{} message to the channel to subscribe a %% consumer to a queue and send a #basic.cancel{} message to cancel a %% subscription.
    %%
    %% The channel will send to the relevant registered consumers the %% basic.consume_ok, basic.cancel_ok, basic.cancel and basic.deliver messages %% received from the server.
    %%
    %% If a consumer is not registered for a given consumer tag, the message %% is sent to the default consumer registered with %% {@module}:register_default_consumer. If there is no default consumer %% registered in this case, an exception occurs and the channel is abruptly %% terminated.
    -module(amqp_selective_consumer). -include("amqp_gen_consumer_spec.hrl"). -behaviour(amqp_gen_consumer). -export([register_default_consumer/2]). -export([init/1, handle_consume_ok/3, handle_consume/3, handle_cancel_ok/3, handle_cancel/2, handle_server_cancel/2, handle_deliver/3, handle_info/2, handle_call/3, terminate/2]). -record(state, {consumers = dict:new(), %% Tag -> ConsumerPid unassigned = undefined, %% Pid monitors = dict:new(), %% Pid -> {Count, MRef} default_consumer = none}). %%--------------------------------------------------------------------------- %% Interface %%--------------------------------------------------------------------------- %% @spec (ChannelPid, ConsumerPid) -> ok %% where %% ChannelPid = pid() %% ConsumerPid = pid() %% @doc This function registers a default consumer with the channel. A %% default consumer is used when a subscription is made via %% amqp_channel:call(ChannelPid, #'basic.consume'{}) (rather than %% {@module}:subscribe/3) and hence there is no consumer pid %% registered with the consumer tag. In this case, the relevant %% deliveries will be sent to the default consumer. register_default_consumer(ChannelPid, ConsumerPid) -> amqp_channel:call_consumer(ChannelPid, {register_default_consumer, ConsumerPid}). %%--------------------------------------------------------------------------- %% amqp_gen_consumer callbacks %%--------------------------------------------------------------------------- %% @private init([]) -> {ok, #state{}}. %% @private handle_consume(#'basic.consume'{consumer_tag = Tag, nowait = NoWait}, Pid, State = #state{consumers = Consumers, monitors = Monitors}) -> Result = case NoWait of true when Tag =:= undefined orelse size(Tag) == 0 -> no_consumer_tag_specified; _ when is_binary(Tag) andalso size(Tag) >= 0 -> case resolve_consumer(Tag, State) of {consumer, _} -> consumer_tag_in_use; _ -> ok end; _ -> ok end, case {Result, NoWait} of {ok, true} -> {ok, State#state {consumers = dict:store(Tag, Pid, Consumers), monitors = add_to_monitor_dict(Pid, Monitors)}}; {ok, false} -> {ok, State#state{unassigned = Pid}}; {Err, true} -> {error, Err, State}; {_Err, false} -> %% Don't do anything (don't override existing %% consumers), the server will close the channel with an error. {ok, State} end. %% @private handle_consume_ok(BasicConsumeOk, _BasicConsume, State = #state{unassigned = Pid, consumers = Consumers, monitors = Monitors}) when is_pid(Pid) -> State1 = State#state{ consumers = dict:store(tag(BasicConsumeOk), Pid, Consumers), monitors = add_to_monitor_dict(Pid, Monitors), unassigned = undefined}, deliver(BasicConsumeOk, State1), {ok, State1}. %% @private %% We sent a basic.cancel. handle_cancel(#'basic.cancel'{nowait = true}, #state{default_consumer = none}) -> exit(cancel_nowait_requires_default_consumer); handle_cancel(Cancel = #'basic.cancel'{nowait = NoWait}, State) -> State1 = case NoWait of true -> do_cancel(Cancel, State); false -> State end, {ok, State1}. %% @private %% We sent a basic.cancel and now receive the ok. handle_cancel_ok(CancelOk, _Cancel, State) -> State1 = do_cancel(CancelOk, State), %% Use old state deliver(CancelOk, State), {ok, State1}. %% @private %% The server sent a basic.cancel. handle_server_cancel(Cancel = #'basic.cancel'{nowait = true}, State) -> State1 = do_cancel(Cancel, State), %% Use old state deliver(Cancel, State), {ok, State1}. %% @private handle_deliver(Deliver, Message, State) -> deliver(Deliver, Message, State), {ok, State}. %% @private handle_info({'DOWN', _MRef, process, Pid, _Info}, State = #state{monitors = Monitors, consumers = Consumers, default_consumer = DConsumer }) -> case dict:find(Pid, Monitors) of {ok, _CountMRef} -> {ok, State#state{monitors = dict:erase(Pid, Monitors), consumers = dict:filter( fun (_, Pid1) when Pid1 =:= Pid -> false; (_, _) -> true end, Consumers)}}; error -> case Pid of DConsumer -> {ok, State#state{ monitors = dict:erase(Pid, Monitors), default_consumer = none}}; _ -> {ok, State} %% unnamed consumer went down %% before receiving consume_ok end end. %% @private handle_call({register_default_consumer, Pid}, _From, State = #state{default_consumer = PrevPid, monitors = Monitors}) -> Monitors1 = case PrevPid of none -> Monitors; _ -> remove_from_monitor_dict(PrevPid, Monitors) end, {reply, ok, State#state{default_consumer = Pid, monitors = add_to_monitor_dict(Pid, Monitors1)}}. %% @private terminate(_Reason, State) -> State. %%--------------------------------------------------------------------------- %% Internal plumbing %%--------------------------------------------------------------------------- deliver(Msg, State) -> deliver(Msg, undefined, State). deliver(Msg, Message, State) -> Combined = if Message =:= undefined -> Msg; true -> {Msg, Message} end, case resolve_consumer(tag(Msg), State) of {consumer, Pid} -> Pid ! Combined; {default, Pid} -> Pid ! Combined; error -> exit(unexpected_delivery_and_no_default_consumer) end. do_cancel(Cancel, State = #state{consumers = Consumers, monitors = Monitors}) -> Tag = tag(Cancel), case dict:find(Tag, Consumers) of {ok, Pid} -> State#state{ consumers = dict:erase(Tag, Consumers), monitors = remove_from_monitor_dict(Pid, Monitors)}; error -> %% Untracked consumer. Do nothing. State end. resolve_consumer(Tag, #state{consumers = Consumers, default_consumer = DefaultConsumer}) -> case dict:find(Tag, Consumers) of {ok, ConsumerPid} -> {consumer, ConsumerPid}; error -> case DefaultConsumer of none -> error; _ -> {default, DefaultConsumer} end end. tag(#'basic.consume'{consumer_tag = Tag}) -> Tag; tag(#'basic.consume_ok'{consumer_tag = Tag}) -> Tag; tag(#'basic.cancel'{consumer_tag = Tag}) -> Tag; tag(#'basic.cancel_ok'{consumer_tag = Tag}) -> Tag; tag(#'basic.deliver'{consumer_tag = Tag}) -> Tag. add_to_monitor_dict(Pid, Monitors) -> case dict:find(Pid, Monitors) of error -> dict:store(Pid, {1, erlang:monitor(process, Pid)}, Monitors); {ok, {Count, MRef}} -> dict:store(Pid, {Count + 1, MRef}, Monitors) end. remove_from_monitor_dict(Pid, Monitors) -> case dict:fetch(Pid, Monitors) of {1, MRef} -> erlang:demonitor(MRef), dict:erase(Pid, Monitors); {Count, MRef} -> dict:store(Pid, {Count - 1, MRef}, Monitors) end. rabbitmq-server-3.2.4/plugins-src/rabbitmq-erlang-client/src/amqp_connection_sup.erl0000644000000000000000000000360112305126066027454 0ustar rootroot%% The contents of this file are subject to the Mozilla Public License %% Version 1.1 (the "License"); you may not use this file except in %% compliance with the License. You may obtain a copy of the License at %% http://www.mozilla.org/MPL/ %% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the %% License for the specific language governing rights and limitations %% under the License. %% %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is GoPivotal, Inc. %% Copyright (c) 2007-2013 GoPivotal, Inc. All rights reserved. %% %% @private -module(amqp_connection_sup). -include("amqp_client.hrl"). -behaviour(supervisor2). -export([start_link/1]). -export([init/1]). %%--------------------------------------------------------------------------- %% Interface %%--------------------------------------------------------------------------- start_link(AMQPParams) -> {ok, Sup} = supervisor2:start_link(?MODULE, []), {ok, TypeSup} = supervisor2:start_child( Sup, {connection_type_sup, {amqp_connection_type_sup, start_link, []}, transient, infinity, supervisor, [amqp_connection_type_sup]}), {ok, Connection} = supervisor2:start_child( Sup, {connection, {amqp_gen_connection, start_link, [TypeSup, AMQPParams]}, intrinsic, brutal_kill, worker, [amqp_gen_connection]}), {ok, Sup, Connection}. %%--------------------------------------------------------------------------- %% supervisor2 callbacks %%--------------------------------------------------------------------------- init([]) -> {ok, {{one_for_all, 0, 1}, []}}. rabbitmq-server-3.2.4/plugins-src/rabbitmq-erlang-client/src/amqp_gen_consumer.erl0000644000000000000000000002240312305126066027113 0ustar rootroot%% The contents of this file are subject to the Mozilla Public License %% Version 1.1 (the "License"); you may not use this file except in %% compliance with the License. You may obtain a copy of the License at %% http://www.mozilla.org/MPL/ %% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the %% License for the specific language governing rights and limitations %% under the License. %% %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is GoPivotal, Inc. %% Copyright (c) 2011-2013 GoPivotal, Inc. All rights reserved. %% %% @doc A behaviour module for implementing consumers for %% amqp_channel. To specify a consumer implementation for a channel, %% use amqp_connection:open_channel/{2,3}. %%
    %% All callbacks are called within the gen_consumer process.
    %%
    %% See comments in amqp_gen_consumer.erl source file for documentation %% on the callback functions. %%
    %% Note that making calls to the channel from the callback module will %% result in deadlock. -module(amqp_gen_consumer). -include("amqp_client.hrl"). -behaviour(gen_server2). -export([start_link/2, call_consumer/2, call_consumer/3]). -export([behaviour_info/1]). -export([init/1, terminate/2, code_change/3, handle_call/3, handle_cast/2, handle_info/2, prioritise_info/3]). -record(state, {module, module_state}). %%--------------------------------------------------------------------------- %% Interface %%--------------------------------------------------------------------------- %% @type ok_error() = {ok, state()} | {error, reason(), state()}. %% Denotes a successful or an error return from a consumer module call. start_link(ConsumerModule, ExtraParams) -> gen_server2:start_link(?MODULE, [ConsumerModule, ExtraParams], []). %% @spec (Consumer, Msg) -> ok %% where %% Consumer = pid() %% Msg = any() %% %% @doc This function is used to perform arbitrary calls into the %% consumer module. call_consumer(Pid, Msg) -> gen_server2:call(Pid, {consumer_call, Msg}, infinity). %% @spec (Consumer, Method, Args) -> ok %% where %% Consumer = pid() %% Method = amqp_method() %% Args = any() %% %% @doc This function is used by amqp_channel to forward received %% methods and deliveries to the consumer module. call_consumer(Pid, Method, Args) -> gen_server2:call(Pid, {consumer_call, Method, Args}, infinity). %%--------------------------------------------------------------------------- %% Behaviour %%--------------------------------------------------------------------------- %% @private behaviour_info(callbacks) -> [ %% init(Args) -> {ok, InitialState} | {stop, Reason} | ignore %% where %% Args = [any()] %% InitialState = state() %% Reason = term() %% %% This callback is invoked by the channel, when it starts %% up. Use it to initialize the state of the consumer. In case of %% an error, return {stop, Reason} or ignore. {init, 1}, %% handle_consume(Consume, Sender, State) -> ok_error() %% where %% Consume = #'basic.consume'{} %% Sender = pid() %% State = state() %% %% This callback is invoked by the channel before a basic.consume %% is sent to the server. {handle_consume, 3}, %% handle_consume_ok(ConsumeOk, Consume, State) -> ok_error() %% where %% ConsumeOk = #'basic.consume_ok'{} %% Consume = #'basic.consume'{} %% State = state() %% %% This callback is invoked by the channel every time a %% basic.consume_ok is received from the server. Consume is the original %% method sent out to the server - it can be used to associate the %% call with the response. {handle_consume_ok, 3}, %% handle_cancel(Cancel, State) -> ok_error() %% where %% Cancel = #'basic.cancel'{} %% State = state() %% %% This callback is invoked by the channel every time a basic.cancel %% is sent to the server. {handle_cancel, 2}, %% handle_cancel_ok(CancelOk, Cancel, State) -> ok_error() %% where %% CancelOk = #'basic.cancel_ok'{} %% Cancel = #'basic.cancel'{} %% State = state() %% %% This callback is invoked by the channel every time a basic.cancel_ok %% is received from the server. {handle_cancel_ok, 3}, %% handle_server_cancel(Cancel, State) -> ok_error() %% where %% Cancel = #'basic.cancel'{} %% State = state() %% %% This callback is invoked by the channel every time a basic.cancel %% is received from the server. {handle_server_cancel, 2}, %% handle_deliver(Deliver, Message, State) -> ok_error() %% where %% Deliver = #'basic.deliver'{} %% Message = #amqp_msg{} %% State = state() %% %% This callback is invoked by the channel every time a basic.deliver %% is received from the server. {handle_deliver, 3}, %% handle_info(Info, State) -> ok_error() %% where %% Info = any() %% State = state() %% %% This callback is invoked the consumer process receives a %% message. {handle_info, 2}, %% handle_call(Msg, From, State) -> {reply, Reply, NewState} | %% {noreply, NewState} | %% {error, Reason, NewState} %% where %% Msg = any() %% From = any() %% Reply = any() %% State = state() %% NewState = state() %% %% This callback is invoked by the channel when calling %% amqp_channel:call_consumer/2. Reply is the term that %% amqp_channel:call_consumer/2 will return. If the callback %% returns {noreply, _}, then the caller to %% amqp_channel:call_consumer/2 and the channel remain blocked %% until gen_server2:reply/2 is used with the provided From as %% the first argument. {handle_call, 3}, %% terminate(Reason, State) -> any() %% where %% Reason = any() %% State = state() %% %% This callback is invoked by the channel after it has shut down and %% just before its process exits. {terminate, 2} ]; behaviour_info(_Other) -> undefined. %%--------------------------------------------------------------------------- %% gen_server2 callbacks %%--------------------------------------------------------------------------- init([ConsumerModule, ExtraParams]) -> case ConsumerModule:init(ExtraParams) of {ok, MState} -> {ok, #state{module = ConsumerModule, module_state = MState}}; {stop, Reason} -> {stop, Reason}; ignore -> ignore end. prioritise_info({'DOWN', _MRef, process, _Pid, _Info}, _Len, _State) -> 1; prioritise_info(_, _Len, _State) -> 0. handle_call({consumer_call, Msg}, From, State = #state{module = ConsumerModule, module_state = MState}) -> case ConsumerModule:handle_call(Msg, From, MState) of {noreply, NewMState} -> {noreply, State#state{module_state = NewMState}}; {reply, Reply, NewMState} -> {reply, Reply, State#state{module_state = NewMState}}; {error, Reason, NewMState} -> {stop, {error, Reason}, {error, Reason}, State#state{module_state = NewMState}} end; handle_call({consumer_call, Method, Args}, _From, State = #state{module = ConsumerModule, module_state = MState}) -> Return = case Method of #'basic.consume'{} -> ConsumerModule:handle_consume(Method, Args, MState); #'basic.consume_ok'{} -> ConsumerModule:handle_consume_ok(Method, Args, MState); #'basic.cancel'{} -> case Args of none -> %% server-sent ConsumerModule:handle_server_cancel(Method, MState); Pid when is_pid(Pid) -> %% client-sent ConsumerModule:handle_cancel(Method, MState) end; #'basic.cancel_ok'{} -> ConsumerModule:handle_cancel_ok(Method, Args, MState); #'basic.deliver'{} -> ConsumerModule:handle_deliver(Method, Args, MState) end, case Return of {ok, NewMState} -> {reply, ok, State#state{module_state = NewMState}}; {error, Reason, NewMState} -> {stop, {error, Reason}, {error, Reason}, State#state{module_state = NewMState}} end. handle_cast(_What, State) -> {noreply, State}. handle_info(Info, State = #state{module_state = MState, module = ConsumerModule}) -> case ConsumerModule:handle_info(Info, MState) of {ok, NewMState} -> {noreply, State#state{module_state = NewMState}}; {error, Reason, NewMState} -> {stop, {error, Reason}, State#state{module_state = NewMState}} end. terminate(Reason, #state{module = ConsumerModule, module_state = MState}) -> ConsumerModule:terminate(Reason, MState). code_change(_OldVsn, State, _Extra) -> {ok, State}. rabbitmq-server-3.2.4/plugins-src/rabbitmq-erlang-client/src/amqp_connection_type_sup.erl0000644000000000000000000000643512305126066030525 0ustar rootroot%% The contents of this file are subject to the Mozilla Public License %% Version 1.1 (the "License"); you may not use this file except in %% compliance with the License. You may obtain a copy of the License at %% http://www.mozilla.org/MPL/ %% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the %% License for the specific language governing rights and limitations %% under the License. %% %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is GoPivotal, Inc. %% Copyright (c) 2007-2013 GoPivotal, Inc. All rights reserved. %% %% @private -module(amqp_connection_type_sup). -include("amqp_client_internal.hrl"). -behaviour(supervisor2). -export([start_link/0, start_infrastructure/3, type_module/1]). -export([init/1]). %%--------------------------------------------------------------------------- %% Interface %%--------------------------------------------------------------------------- start_link() -> supervisor2:start_link(?MODULE, []). start_infrastructure(Sup, Conn, Type) -> {ok, ChMgr} = start_channels_manager(Sup, Conn, Type), {ok, start_infrastructure_fun(Sup, Conn, ChMgr, Type), ChMgr}. type_module(#amqp_params_direct{}) -> {direct, amqp_direct_connection}; type_module(#amqp_params_network{}) -> {network, amqp_network_connection}. %%--------------------------------------------------------------------------- start_channels_manager(Sup, Conn, Type) -> {ok, ChSupSup} = supervisor2:start_child( Sup, {channel_sup_sup, {amqp_channel_sup_sup, start_link, [Type, Conn]}, intrinsic, infinity, supervisor, [amqp_channel_sup_sup]}), {ok, _} = supervisor2:start_child( Sup, {channels_manager, {amqp_channels_manager, start_link, [Conn, ChSupSup]}, transient, ?MAX_WAIT, worker, [amqp_channels_manager]}). start_infrastructure_fun(Sup, Conn, ChMgr, network) -> fun (Sock) -> {ok, AState} = rabbit_command_assembler:init(?PROTOCOL), {ok, Writer} = supervisor2:start_child( Sup, {writer, {rabbit_writer, start_link, [Sock, 0, ?FRAME_MIN_SIZE, ?PROTOCOL, Conn]}, transient, ?MAX_WAIT, worker, [rabbit_writer]}), {ok, _Reader} = supervisor2:start_child( Sup, {main_reader, {amqp_main_reader, start_link, [Sock, Conn, ChMgr, AState]}, transient, ?MAX_WAIT, worker, [amqp_main_reader]}), {ok, Writer} end; start_infrastructure_fun(Sup, _Conn, _ChMgr, direct) -> fun () -> supervisor2:start_child( Sup, {collector, {rabbit_queue_collector, start_link, []}, transient, ?MAX_WAIT, worker, [rabbit_queue_collector]}) end. %%--------------------------------------------------------------------------- %% supervisor2 callbacks %%--------------------------------------------------------------------------- init([]) -> {ok, {{one_for_all, 0, 1}, []}}. rabbitmq-server-3.2.4/plugins-src/rabbitmq-erlang-client/src/amqp_direct_connection.erl0000644000000000000000000001711612305126066030125 0ustar rootroot%% The contents of this file are subject to the Mozilla Public License %% Version 1.1 (the "License"); you may not use this file except in %% compliance with the License. You may obtain a copy of the License at %% http://www.mozilla.org/MPL/ %% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the %% License for the specific language governing rights and limitations %% under the License. %% %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is GoPivotal, Inc. %% Copyright (c) 2007-2013 GoPivotal, Inc. All rights reserved. %% %% @private -module(amqp_direct_connection). -include("amqp_client_internal.hrl"). -behaviour(amqp_gen_connection). -export([server_close/3]). -export([init/0, terminate/2, connect/4, do/2, open_channel_args/1, i/2, info_keys/0, handle_message/2, closing/3, channels_terminated/1]). -export([socket_adapter_info/2]). -record(state, {node, user, vhost, params, adapter_info, collector, closing_reason %% undefined | Reason }). -define(INFO_KEYS, [type]). -define(CREATION_EVENT_KEYS, [pid, protocol, host, port, name, peer_host, peer_port, user, vhost, client_properties, type]). %%--------------------------------------------------------------------------- %% amqp_connection:close() logically closes from the client end. We may %% want to close from the server end. server_close(ConnectionPid, Code, Text) -> Close = #'connection.close'{reply_text = Text, reply_code = Code, class_id = 0, method_id = 0}, amqp_gen_connection:server_close(ConnectionPid, Close). init() -> {ok, #state{}}. open_channel_args(#state{node = Node, user = User, vhost = VHost, adapter_info = Info, collector = Collector}) -> [self(), Info#amqp_adapter_info.name, Node, User, VHost, Collector]. do(_Method, _State) -> ok. handle_message(force_event_refresh, State = #state{node = Node}) -> rpc:call(Node, rabbit_event, notify, [connection_created, connection_info(State)]), {ok, State}; handle_message(closing_timeout, State = #state{closing_reason = Reason}) -> {stop, {closing_timeout, Reason}, State}; handle_message(Msg, State) -> {stop, {unexpected_msg, Msg}, State}. closing(_ChannelCloseType, Reason, State) -> {ok, State#state{closing_reason = Reason}}. channels_terminated(State = #state{closing_reason = Reason, collector = Collector}) -> rabbit_queue_collector:delete_all(Collector), {stop, {shutdown, Reason}, State}. terminate(_Reason, #state{node = Node}) -> rpc:call(Node, rabbit_direct, disconnect, [self(), [{pid, self()}]]), ok. i(type, _State) -> direct; i(pid, _State) -> self(); %% AMQP Params i(user, #state{params=#amqp_params_direct{username=#user{username=U}}}) -> U; i(user, #state{params=#amqp_params_direct{username=U}}) -> U; i(vhost, #state{params = P}) -> P#amqp_params_direct.virtual_host; i(client_properties, #state{params = P}) -> P#amqp_params_direct.client_properties; %% Optional adapter info i(protocol, #state{adapter_info = I}) -> I#amqp_adapter_info.protocol; i(host, #state{adapter_info = I}) -> I#amqp_adapter_info.host; i(port, #state{adapter_info = I}) -> I#amqp_adapter_info.port; i(peer_host, #state{adapter_info = I}) -> I#amqp_adapter_info.peer_host; i(peer_port, #state{adapter_info = I}) -> I#amqp_adapter_info.peer_port; i(name, #state{adapter_info = I}) -> I#amqp_adapter_info.name; i(Item, _State) -> throw({bad_argument, Item}). info_keys() -> ?INFO_KEYS. infos(Items, State) -> [{Item, i(Item, State)} || Item <- Items]. connection_info(State = #state{adapter_info = I}) -> infos(?CREATION_EVENT_KEYS, State) ++ I#amqp_adapter_info.additional_info. connect(Params = #amqp_params_direct{username = Username, password = Password, node = Node, adapter_info = Info, virtual_host = VHost}, SIF, _TypeSup, State) -> State1 = State#state{node = Node, vhost = VHost, params = Params, adapter_info = ensure_adapter_info(Info)}, AuthToken = case Password of none -> Username; _ -> {Username, Password} end, case rpc:call(Node, rabbit_direct, connect, [AuthToken, VHost, ?PROTOCOL, self(), connection_info(State1)]) of {ok, {User, ServerProperties}} -> {ok, Collector} = SIF(), State2 = State1#state{user = User, collector = Collector}, {ok, {ServerProperties, 0, State2}}; {error, _} = E -> E; {badrpc, nodedown} -> {error, {nodedown, Node}} end. ensure_adapter_info(none) -> ensure_adapter_info(#amqp_adapter_info{}); ensure_adapter_info(A = #amqp_adapter_info{protocol = unknown}) -> ensure_adapter_info(A#amqp_adapter_info{ protocol = {'Direct', ?PROTOCOL:version()}}); ensure_adapter_info(A = #amqp_adapter_info{name = unknown}) -> Name = list_to_binary(rabbit_misc:pid_to_string(self())), ensure_adapter_info(A#amqp_adapter_info{name = Name}); ensure_adapter_info(Info) -> Info. socket_adapter_info(Sock, Protocol) -> {PeerHost, PeerPort, Host, Port} = case rabbit_net:socket_ends(Sock, inbound) of {ok, Res} -> Res; _ -> {unknown, unknown, unknown, unknown} end, Name = case rabbit_net:connection_string(Sock, inbound) of {ok, Res1} -> Res1; _Error -> "(unknown)" end, #amqp_adapter_info{protocol = Protocol, name = list_to_binary(Name), host = Host, port = Port, peer_host = PeerHost, peer_port = PeerPort, additional_info = maybe_ssl_info(Sock)}. maybe_ssl_info(Sock) -> case rabbit_net:is_ssl(Sock) of true -> [{ssl, true}] ++ ssl_info(Sock) ++ ssl_cert_info(Sock); false -> [{ssl, false}] end. ssl_info(Sock) -> {Protocol, KeyExchange, Cipher, Hash} = case rabbit_net:ssl_info(Sock) of {ok, {P, {K, C, H}}} -> {P, K, C, H}; {ok, {P, {K, C, H, _}}} -> {P, K, C, H}; _ -> {unknown, unknown, unknown, unknown} end, [{ssl_protocol, Protocol}, {ssl_key_exchange, KeyExchange}, {ssl_cipher, Cipher}, {ssl_hash, Hash}]. ssl_cert_info(Sock) -> case rabbit_net:peercert(Sock) of {ok, Cert} -> [{peer_cert_issuer, list_to_binary( rabbit_ssl:peer_cert_issuer(Cert))}, {peer_cert_subject, list_to_binary( rabbit_ssl:peer_cert_subject(Cert))}, {peer_cert_validity, list_to_binary( rabbit_ssl:peer_cert_validity(Cert))}]; _ -> [] end. rabbitmq-server-3.2.4/plugins-src/rabbitmq-erlang-client/src/amqp_uri.erl0000644000000000000000000002121112305126066025222 0ustar rootroot%% The contents of this file are subject to the Mozilla Public License %% Version 1.1 (the "License"); you may not use this file except in %% compliance with the License. You may obtain a copy of the License at %% http://www.mozilla.org/MPL/ %% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the %% License for the specific language governing rights and limitations %% under the License. %% %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is GoPivotal, Inc. %% Copyright (c) 2007-2013 GoPivotal, Inc. All rights reserved. %% -module(amqp_uri). -include("amqp_client.hrl"). -export([parse/1, parse/2]). %%--------------------------------------------------------------------------- %% AMQP URI Parsing %%--------------------------------------------------------------------------- %% @spec (Uri) -> {ok, #amqp_params_network{} | #amqp_params_direct{}} | %% {error, {Info, Uri}} %% where %% Uri = string() %% Info = any() %% %% @doc Parses an AMQP URI. If any of the URI parts are missing, the %% default values are used. If the hostname is zero-length, an %% #amqp_params_direct{} record is returned; otherwise, an %% #amqp_params_network{} record is returned. Extra parameters may be %% specified via the query string %% (e.g. "?heartbeat=5&auth_mechanism=external"). In case of failure, %% an {error, {Info, Uri}} tuple is returned. %% %% The extra parameters that may be specified are channel_max, %% frame_max, heartbeat and auth_mechanism (the latter can appear more %% than once). The extra parameters that may be specified for an SSL %% connection are cacertfile, certfile, keyfile, verify, and %% fail_if_no_peer_cert. parse(Uri) -> parse(Uri, <<"/">>). parse(Uri, DefaultVHost) -> try case parse1(Uri, DefaultVHost) of {ok, #amqp_params_network{host = undefined, username = User, virtual_host = Vhost}} -> return({ok, #amqp_params_direct{username = User, virtual_host = Vhost}}); {ok, Params} -> return({ok, Params}) end catch throw:Err -> {error, {Err, Uri}}; error:Err -> {error, {Err, Uri}} end. parse1(Uri, DefaultVHost) when is_list(Uri) -> case uri_parser:parse(Uri, [{host, undefined}, {path, undefined}, {port, undefined}, {'query', []}]) of {error, Err} -> throw({unable_to_parse_uri, Err}); Parsed -> Endpoint = case string:to_lower(proplists:get_value(scheme, Parsed)) of "amqp" -> build_broker(Parsed, DefaultVHost); "amqps" -> build_ssl_broker(Parsed, DefaultVHost); Scheme -> fail({unexpected_uri_scheme, Scheme}) end, return({ok, broker_add_query(Endpoint, Parsed)}) end; parse1(_, _DefaultVHost) -> fail(expected_string_uri). unescape_string(Atom) when is_atom(Atom) -> Atom; unescape_string([]) -> []; unescape_string([$%, N1, N2 | Rest]) -> try [erlang:list_to_integer([N1, N2], 16) | unescape_string(Rest)] catch error:badarg -> throw({invalid_entitiy, ['%', N1, N2]}) end; unescape_string([$% | Rest]) -> fail({unterminated_entity, ['%' | Rest]}); unescape_string([C | Rest]) -> [C | unescape_string(Rest)]. build_broker(ParsedUri, DefaultVHost) -> [Host, Port, Path] = [proplists:get_value(F, ParsedUri) || F <- [host, port, path]], case Port =:= undefined orelse (0 < Port andalso Port =< 65535) of true -> ok; false -> fail({port_out_of_range, Port}) end, VHost = case Path of undefined -> DefaultVHost; [$/|Rest] -> case string:chr(Rest, $/) of 0 -> list_to_binary(unescape_string(Rest)); _ -> fail({invalid_vhost, Rest}) end end, UserInfo = proplists:get_value(userinfo, ParsedUri), Ps = #amqp_params_network{host = unescape_string(Host), port = Port, virtual_host = VHost, auth_mechanisms = mechanisms(ParsedUri)}, case UserInfo of [U, P | _] -> Ps#amqp_params_network{ username = list_to_binary(unescape_string(U)), password = list_to_binary(unescape_string(P))}; [U | _] -> Ps#amqp_params_network{ username = list_to_binary(unescape_string(U))}; _ -> Ps end. build_ssl_broker(ParsedUri, DefaultVHost) -> Params = build_broker(ParsedUri, DefaultVHost), Query = proplists:get_value('query', ParsedUri), SSLOptions = run_state_monad( [fun (L) -> KeyString = atom_to_list(Key), case lists:keysearch(KeyString, 1, Query) of {value, {_, Value}} -> try return([{Key, unescape_string(Fun(Value))} | L]) catch throw:Reason -> fail({invalid_ssl_parameter, Key, Value, Query, Reason}) end; false -> L end end || {Fun, Key} <- [{fun find_path_parameter/1, cacertfile}, {fun find_path_parameter/1, certfile}, {fun find_path_parameter/1, keyfile}, {fun find_atom_parameter/1, verify}, {fun find_boolean_parameter/1, fail_if_no_peer_cert}]], []), Params#amqp_params_network{ssl_options = SSLOptions}. broker_add_query(Params = #amqp_params_network{}, Uri) -> broker_add_query(Params, Uri, record_info(fields, amqp_params_network)). broker_add_query(Params, ParsedUri, Fields) -> Query = proplists:get_value('query', ParsedUri), {Params1, _Pos} = run_state_monad( [fun ({ParamsN, Pos}) -> Pos1 = Pos + 1, KeyString = atom_to_list(Field), case proplists:get_value(KeyString, Query) of undefined -> return({ParamsN, Pos1}); true -> %% proplists short form, not permitted return({ParamsN, Pos1}); Value -> try ValueParsed = parse_amqp_param(Field, Value), return( {setelement(Pos, ParamsN, ValueParsed), Pos1}) catch throw:Reason -> fail({invalid_amqp_params_parameter, Field, Value, Query, Reason}) end end end || Field <- Fields], {Params, 2}), Params1. parse_amqp_param(Field, String) when Field =:= channel_max orelse Field =:= frame_max orelse Field =:= heartbeat orelse Field =:= connection_timeout -> try return(list_to_integer(String)) catch error:badarg -> fail({not_an_integer, String}) end; parse_amqp_param(Field, String) -> fail({parameter_unconfigurable_in_query, Field, String}). find_path_parameter(Value) -> return(Value). find_boolean_parameter(Value) -> Bool = list_to_atom(Value), case is_boolean(Bool) of true -> return(Bool); false -> fail({require_boolean, Bool}) end. find_atom_parameter(Value) -> return(list_to_atom(Value)). mechanisms(ParsedUri) -> Query = proplists:get_value('query', ParsedUri), Mechanisms = case proplists:get_all_values("auth_mechanism", Query) of [] -> ["plain", "amqplain"]; Mechs -> Mechs end, [case [list_to_atom(T) || T <- string:tokens(Mech, ":")] of [F] -> fun (R, P, S) -> amqp_auth_mechanisms:F(R, P, S) end; [M, F] -> fun (R, P, S) -> M:F(R, P, S) end; L -> throw({not_mechanism, L}) end || Mech <- Mechanisms]. %% --=: Plain state monad implementation start :=-- run_state_monad(FunList, State) -> lists:foldl(fun (Fun, StateN) -> Fun(StateN) end, State, FunList). return(V) -> V. fail(Reason) -> throw(Reason). %% --=: end :=-- rabbitmq-server-3.2.4/plugins-src/rabbitmq-erlang-client/src/rabbit_routing_util.erl0000644000000000000000000001731312305126066027464 0ustar rootroot%% The contents of this file are subject to the Mozilla Public License %% Version 1.1 (the "License"); you may not use this file except in %% compliance with the License. You may obtain a copy of the License at %% http://www.mozilla.org/MPL/ %% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the %% License for the specific language governing rights and limitations %% under the License. %% %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is GoPivotal, Inc. %% Copyright (c) 2013-2013 GoPivotal, Inc. All rights reserved. %% -module(rabbit_routing_util). -export([init_state/0, dest_prefixes/0, all_dest_prefixes/0]). -export([ensure_endpoint/4, ensure_endpoint/5, ensure_binding/3]). -export([parse_endpoint/1, parse_endpoint/2]). -export([parse_routing/1, dest_temp_queue/1]). -include("amqp_client.hrl"). -include("rabbit_routing_prefixes.hrl"). %%---------------------------------------------------------------------------- init_state() -> sets:new(). dest_prefixes() -> [?EXCHANGE_PREFIX, ?TOPIC_PREFIX, ?QUEUE_PREFIX, ?AMQQUEUE_PREFIX, ?REPLY_QUEUE_PREFIX]. all_dest_prefixes() -> [?TEMP_QUEUE_PREFIX | dest_prefixes()]. %% -------------------------------------------------------------------------- parse_endpoint(Destination) -> parse_endpoint(Destination, false). parse_endpoint(undefined, AllowAnonymousQueue) -> parse_endpoint("/queue", AllowAnonymousQueue); parse_endpoint(Destination, AllowAnonymousQueue) when is_binary(Destination) -> parse_endpoint(unicode:characters_to_list(Destination), AllowAnonymousQueue); parse_endpoint(Destination, AllowAnonymousQueue) when is_list(Destination) -> case re:split(Destination, "/", [{return, list}]) of [Name] -> {ok, {queue, unescape(Name)}}; ["", Type | Rest] when Type =:= "exchange" orelse Type =:= "queue" orelse Type =:= "topic" orelse Type =:= "temp-queue" -> parse_endpoint0(atomise(Type), Rest, AllowAnonymousQueue); ["", "amq", "queue" | Rest] -> parse_endpoint0(amqqueue, Rest, AllowAnonymousQueue); ["", "reply-queue" = Prefix | [_|_]] -> parse_endpoint0(reply_queue, [lists:nthtail(2 + length(Prefix), Destination)], AllowAnonymousQueue); _ -> {error, {unknown_destination, Destination}} end. parse_endpoint0(exchange, ["" | _] = Rest, _) -> {error, {invalid_destination, exchange, to_url(Rest)}}; parse_endpoint0(exchange, [Name], _) -> {ok, {exchange, {unescape(Name), undefined}}}; parse_endpoint0(exchange, [Name, Pattern], _) -> {ok, {exchange, {unescape(Name), unescape(Pattern)}}}; parse_endpoint0(queue, [], false) -> {error, {invalid_destination, queue, []}}; parse_endpoint0(queue, [], true) -> {ok, {queue, undefined}}; parse_endpoint0(Type, [[_|_]] = [Name], _) -> {ok, {Type, unescape(Name)}}; parse_endpoint0(Type, Rest, _) -> {error, {invalid_destination, Type, to_url(Rest)}}. %% -------------------------------------------------------------------------- ensure_endpoint(Dir, Channel, EndPoint, State) -> ensure_endpoint(Dir, Channel, EndPoint, [], State). ensure_endpoint(source, Channel, {exchange, {Name, _}}, Params, State) -> check_exchange(Name, Channel, proplists:get_value(check_exchange, Params, false)), Method = queue_declare_method(#'queue.declare'{}, exchange, Params), #'queue.declare_ok'{queue = Queue} = amqp_channel:call(Channel, Method), {ok, Queue, State}; ensure_endpoint(source, Channel, {topic, _}, Params, State) -> Method = queue_declare_method(#'queue.declare'{}, topic, Params), #'queue.declare_ok'{queue = Queue} = amqp_channel:call(Channel, Method), {ok, Queue, State}; ensure_endpoint(_Dir, _Channel, {queue, undefined}, _Params, State) -> {ok, undefined, State}; ensure_endpoint(_, Channel, {queue, Name}, Params, State) -> Params1 = rabbit_misc:pset(durable, true, Params), Queue = list_to_binary(Name), State1 = case sets:is_element(Queue, State) of true -> State; _ -> Method = queue_declare_method( #'queue.declare'{queue = Queue, nowait = true}, queue, Params1), amqp_channel:cast(Channel, Method), sets:add_element(Queue, State) end, {ok, Queue, State1}; ensure_endpoint(dest, Channel, {exchange, {Name, _}}, Params, State) -> check_exchange(Name, Channel, proplists:get_value(check_exchange, Params, false)), {ok, undefined, State}; ensure_endpoint(dest, _Ch, {topic, _}, _Params, State) -> {ok, undefined, State}; ensure_endpoint(_, _Ch, {Type, Name}, _Params, State) when Type =:= reply_queue orelse Type =:= amqqueue -> {ok, list_to_binary(Name), State}; ensure_endpoint(_Direction, _Ch, _Endpoint, _Params, _State) -> {error, invalid_endpoint}. %% -------------------------------------------------------------------------- ensure_binding(QueueBin, {"", Queue}, _Channel) -> %% i.e., we should only be asked to bind to the default exchange a %% queue with its own name QueueBin = list_to_binary(Queue), ok; ensure_binding(Queue, {Exchange, RoutingKey}, Channel) -> #'queue.bind_ok'{} = amqp_channel:call(Channel, #'queue.bind'{ queue = Queue, exchange = list_to_binary(Exchange), routing_key = list_to_binary(RoutingKey)}), ok. %% -------------------------------------------------------------------------- parse_routing({exchange, {Name, undefined}}) -> {Name, ""}; parse_routing({exchange, {Name, Pattern}}) -> {Name, Pattern}; parse_routing({topic, Name}) -> {"amq.topic", Name}; parse_routing({Type, Name}) when Type =:= queue orelse Type =:= reply_queue orelse Type =:= amqqueue -> {"", Name}. dest_temp_queue({temp_queue, Name}) -> Name; dest_temp_queue(_) -> none. %% -------------------------------------------------------------------------- check_exchange(_, _, false) -> ok; check_exchange(ExchangeName, Channel, true) -> XDecl = #'exchange.declare'{ exchange = list_to_binary(ExchangeName), passive = true }, #'exchange.declare_ok'{} = amqp_channel:call(Channel, XDecl), ok. queue_declare_method(#'queue.declare'{} = Method, Type, Params) -> Method1 = case proplists:get_value(durable, Params, false) of true -> Method#'queue.declare'{durable = true}; false -> Method#'queue.declare'{auto_delete = true, exclusive = true} end, case {Type, proplists:get_value(subscription_queue_name_gen, Params)} of {topic, SQNG} when is_function(SQNG) -> Method1#'queue.declare'{queue = SQNG()}; _ -> Method1 end. %% -------------------------------------------------------------------------- to_url([]) -> []; to_url(Lol) -> "/" ++ string:join(Lol, "/"). atomise(Name) when is_list(Name) -> list_to_atom(re:replace(Name, "-", "_", [{return,list}, global])). unescape(Str) -> unescape(Str, []). unescape("%2F" ++ Str, Acc) -> unescape(Str, [$/ | Acc]); unescape([C | Str], Acc) -> unescape(Str, [C | Acc]); unescape([], Acc) -> lists:reverse(Acc). rabbitmq-server-3.2.4/plugins-src/rabbitmq-erlang-client/src/amqp_auth_mechanisms.erl0000644000000000000000000000345612305126066027606 0ustar rootroot%% The contents of this file are subject to the Mozilla Public License %% Version 1.1 (the "License"); you may not use this file except in %% compliance with the License. You may obtain a copy of the License at %% http://www.mozilla.org/MPL/ %% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the %% License for the specific language governing rights and limitations %% under the License. %% %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is GoPivotal, Inc. %% Copyright (c) 2007-2013 GoPivotal, Inc. All rights reserved. %% %% @private -module(amqp_auth_mechanisms). -include("amqp_client.hrl"). -export([plain/3, amqplain/3, external/3, crdemo/3]). %%--------------------------------------------------------------------------- plain(none, _, init) -> {<<"PLAIN">>, []}; plain(none, #amqp_params_network{username = Username, password = Password}, _State) -> {<<0, Username/binary, 0, Password/binary>>, _State}. amqplain(none, _, init) -> {<<"AMQPLAIN">>, []}; amqplain(none, #amqp_params_network{username = Username, password = Password}, _State) -> LoginTable = [{<<"LOGIN">>, longstr, Username}, {<<"PASSWORD">>, longstr, Password}], {rabbit_binary_generator:generate_table(LoginTable), _State}. external(none, _, init) -> {<<"EXTERNAL">>, []}; external(none, _, _State) -> {<<"">>, _State}. crdemo(none, _, init) -> {<<"RABBIT-CR-DEMO">>, 0}; crdemo(none, #amqp_params_network{username = Username}, 0) -> {Username, 1}; crdemo(<<"Please tell me your password">>, #amqp_params_network{password = Password}, 1) -> {<<"My password is ", Password/binary>>, 2}. rabbitmq-server-3.2.4/plugins-src/rabbitmq-erlang-client/src/amqp_sup.erl0000644000000000000000000000276112305126066025243 0ustar rootroot%% The contents of this file are subject to the Mozilla Public License %% Version 1.1 (the "License"); you may not use this file except in %% compliance with the License. You may obtain a copy of the License at %% http://www.mozilla.org/MPL/ %% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the %% License for the specific language governing rights and limitations %% under the License. %% %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is GoPivotal, Inc. %% Copyright (c) 2007-2013 GoPivotal, Inc. All rights reserved. %% %% @private -module(amqp_sup). -include("amqp_client.hrl"). -behaviour(supervisor2). -export([start_link/0, start_connection_sup/1]). -export([init/1]). %%--------------------------------------------------------------------------- %% Interface %%--------------------------------------------------------------------------- start_link() -> supervisor2:start_link({local, amqp_sup}, ?MODULE, []). start_connection_sup(AmqpParams) -> supervisor2:start_child(amqp_sup, [AmqpParams]). %%--------------------------------------------------------------------------- %% supervisor2 callbacks %%--------------------------------------------------------------------------- init([]) -> {ok, {{simple_one_for_one, 0, 1}, [{connection_sup, {amqp_connection_sup, start_link, []}, temporary, infinity, supervisor, [amqp_connection_sup]}]}}. rabbitmq-server-3.2.4/plugins-src/rabbitmq-erlang-client/src/amqp_channels_manager.erl0000644000000000000000000002416012305126066027716 0ustar rootroot%% The contents of this file are subject to the Mozilla Public License %% Version 1.1 (the "License"); you may not use this file except in %% compliance with the License. You may obtain a copy of the License at %% http://www.mozilla.org/MPL/ %% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the %% License for the specific language governing rights and limitations %% under the License. %% %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is GoPivotal, Inc. %% Copyright (c) 2007-2013 GoPivotal, Inc. All rights reserved. %% %% @private -module(amqp_channels_manager). -include("amqp_client_internal.hrl"). -behaviour(gen_server). -export([start_link/2, open_channel/4, set_channel_max/2, is_empty/1, num_channels/1, pass_frame/3, signal_connection_closing/3, process_channel_frame/4]). -export([init/1, terminate/2, code_change/3, handle_call/3, handle_cast/2, handle_info/2]). -record(state, {connection, channel_sup_sup, map_num_pa = gb_trees:empty(), %% Number -> {Pid, AState} map_pid_num = dict:new(), %% Pid -> Number channel_max = ?MAX_CHANNEL_NUMBER, closing = false}). %%--------------------------------------------------------------------------- %% Interface %%--------------------------------------------------------------------------- start_link(Connection, ChSupSup) -> gen_server:start_link(?MODULE, [Connection, ChSupSup], []). open_channel(ChMgr, ProposedNumber, Consumer, InfraArgs) -> gen_server:call(ChMgr, {open_channel, ProposedNumber, Consumer, InfraArgs}, infinity). set_channel_max(ChMgr, ChannelMax) -> gen_server:cast(ChMgr, {set_channel_max, ChannelMax}). is_empty(ChMgr) -> gen_server:call(ChMgr, is_empty, infinity). num_channels(ChMgr) -> gen_server:call(ChMgr, num_channels, infinity). pass_frame(ChMgr, ChNumber, Frame) -> gen_server:cast(ChMgr, {pass_frame, ChNumber, Frame}). signal_connection_closing(ChMgr, ChannelCloseType, Reason) -> gen_server:cast(ChMgr, {connection_closing, ChannelCloseType, Reason}). process_channel_frame(Frame, Channel, ChPid, AState) -> case rabbit_command_assembler:process(Frame, AState) of {ok, NewAState} -> NewAState; {ok, Method, NewAState} -> rabbit_channel:do(ChPid, Method), NewAState; {ok, Method, Content, NewAState} -> rabbit_channel:do(ChPid, Method, Content), NewAState; {error, Reason} -> ChPid ! {channel_exit, Channel, Reason}, AState end. %%--------------------------------------------------------------------------- %% gen_server callbacks %%--------------------------------------------------------------------------- init([Connection, ChSupSup]) -> {ok, #state{connection = Connection, channel_sup_sup = ChSupSup}}. terminate(_Reason, _State) -> ok. code_change(_OldVsn, State, _Extra) -> {ok, State}. handle_call({open_channel, ProposedNumber, Consumer, InfraArgs}, _, State = #state{closing = false}) -> handle_open_channel(ProposedNumber, Consumer, InfraArgs, State); handle_call(is_empty, _, State) -> {reply, internal_is_empty(State), State}; handle_call(num_channels, _, State) -> {reply, internal_num_channels(State), State}. handle_cast({set_channel_max, ChannelMax}, State) -> {noreply, State#state{channel_max = ChannelMax}}; handle_cast({pass_frame, ChNumber, Frame}, State) -> {noreply, internal_pass_frame(ChNumber, Frame, State)}; handle_cast({connection_closing, ChannelCloseType, Reason}, State) -> handle_connection_closing(ChannelCloseType, Reason, State). handle_info({'DOWN', _, process, Pid, Reason}, State) -> handle_down(Pid, Reason, State). %%--------------------------------------------------------------------------- %% Internal plumbing %%--------------------------------------------------------------------------- handle_open_channel(ProposedNumber, Consumer, InfraArgs, State = #state{channel_sup_sup = ChSupSup}) -> case new_number(ProposedNumber, State) of {ok, Number} -> {ok, _ChSup, {Ch, AState}} = amqp_channel_sup_sup:start_channel_sup(ChSupSup, InfraArgs, Number, Consumer), NewState = internal_register(Number, Ch, AState, State), erlang:monitor(process, Ch), {reply, {ok, Ch}, NewState}; {error, _} = Error -> {reply, Error, State} end. new_number(none, #state{channel_max = ChannelMax, map_num_pa = MapNPA}) -> case gb_trees:is_empty(MapNPA) of true -> {ok, 1}; false -> {Smallest, _} = gb_trees:smallest(MapNPA), if Smallest > 1 -> {ok, Smallest - 1}; true -> {Largest, _} = gb_trees:largest(MapNPA), if Largest < ChannelMax -> {ok, Largest + 1}; true -> find_free(MapNPA) end end end; new_number(Proposed, State = #state{channel_max = ChannelMax, map_num_pa = MapNPA}) -> IsValid = Proposed > 0 andalso Proposed =< ChannelMax andalso not gb_trees:is_defined(Proposed, MapNPA), case IsValid of true -> {ok, Proposed}; false -> new_number(none, State) end. find_free(MapNPA) -> find_free(gb_trees:iterator(MapNPA), 1). find_free(It, Candidate) -> case gb_trees:next(It) of {Number, _, It1} -> if Number > Candidate -> {ok, Number - 1}; Number =:= Candidate -> find_free(It1, Candidate + 1) end; none -> {error, out_of_channel_numbers} end. handle_down(Pid, Reason, State) -> case internal_lookup_pn(Pid, State) of undefined -> {stop, {error, unexpected_down}, State}; Number -> handle_channel_down(Pid, Number, Reason, State) end. handle_channel_down(Pid, Number, Reason, State) -> maybe_report_down(Pid, case Reason of {shutdown, R} -> R; _ -> Reason end, State), NewState = internal_unregister(Number, Pid, State), check_all_channels_terminated(NewState), {noreply, NewState}. maybe_report_down(_Pid, normal, _State) -> ok; maybe_report_down(_Pid, shutdown, _State) -> ok; maybe_report_down(_Pid, {app_initiated_close, _, _}, _State) -> ok; maybe_report_down(_Pid, {server_initiated_close, _, _}, _State) -> ok; maybe_report_down(_Pid, {connection_closing, _}, _State) -> ok; maybe_report_down(_Pid, {server_misbehaved, AmqpError}, #state{connection = Connection}) -> amqp_gen_connection:server_misbehaved(Connection, AmqpError); maybe_report_down(Pid, Other, #state{connection = Connection}) -> amqp_gen_connection:channel_internal_error(Connection, Pid, Other). check_all_channels_terminated(#state{closing = false}) -> ok; check_all_channels_terminated(State = #state{closing = true, connection = Connection}) -> case internal_is_empty(State) of true -> amqp_gen_connection:channels_terminated(Connection); false -> ok end. handle_connection_closing(ChannelCloseType, Reason, State = #state{connection = Connection}) -> case internal_is_empty(State) of true -> amqp_gen_connection:channels_terminated(Connection); false -> signal_channels_connection_closing(ChannelCloseType, Reason, State) end, {noreply, State#state{closing = true}}. %%--------------------------------------------------------------------------- internal_pass_frame(Number, Frame, State) -> case internal_lookup_npa(Number, State) of undefined -> ?LOG_INFO("Dropping frame ~p for invalid or closed " "channel number ~p~n", [Frame, Number]), State; {ChPid, AState} -> NewAState = process_channel_frame(Frame, Number, ChPid, AState), internal_update_npa(Number, ChPid, NewAState, State) end. internal_register(Number, Pid, AState, State = #state{map_num_pa = MapNPA, map_pid_num = MapPN}) -> MapNPA1 = gb_trees:enter(Number, {Pid, AState}, MapNPA), MapPN1 = dict:store(Pid, Number, MapPN), State#state{map_num_pa = MapNPA1, map_pid_num = MapPN1}. internal_unregister(Number, Pid, State = #state{map_num_pa = MapNPA, map_pid_num = MapPN}) -> MapNPA1 = gb_trees:delete(Number, MapNPA), MapPN1 = dict:erase(Pid, MapPN), State#state{map_num_pa = MapNPA1, map_pid_num = MapPN1}. internal_is_empty(#state{map_num_pa = MapNPA}) -> gb_trees:is_empty(MapNPA). internal_num_channels(#state{map_num_pa = MapNPA}) -> gb_trees:size(MapNPA). internal_lookup_npa(Number, #state{map_num_pa = MapNPA}) -> case gb_trees:lookup(Number, MapNPA) of {value, PA} -> PA; none -> undefined end. internal_lookup_pn(Pid, #state{map_pid_num = MapPN}) -> case dict:find(Pid, MapPN) of {ok, Number} -> Number; error -> undefined end. internal_update_npa(Number, Pid, AState, State = #state{map_num_pa = MapNPA}) -> State#state{map_num_pa = gb_trees:update(Number, {Pid, AState}, MapNPA)}. signal_channels_connection_closing(ChannelCloseType, Reason, #state{map_pid_num = MapPN}) -> [amqp_channel:connection_closing(Pid, ChannelCloseType, Reason) || Pid <- dict:fetch_keys(MapPN)]. rabbitmq-server-3.2.4/plugins-src/rabbitmq-erlang-client/src/amqp_main_reader.erl0000644000000000000000000001425712305126066026705 0ustar rootroot%% The contents of this file are subject to the Mozilla Public License %% Version 1.1 (the "License"); you may not use this file except in %% compliance with the License. You may obtain a copy of the License at %% http://www.mozilla.org/MPL/ %% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the %% License for the specific language governing rights and limitations %% under the License. %% %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is GoPivotal, Inc. %% Copyright (c) 2007-2013 GoPivotal, Inc. All rights reserved. %% %% @private -module(amqp_main_reader). -include("amqp_client_internal.hrl"). -behaviour(gen_server). -export([start_link/4]). -export([init/1, terminate/2, code_change/3, handle_call/3, handle_cast/2, handle_info/2]). -record(state, {sock, connection, channels_manager, astate, message = none %% none | {Type, Channel, Length} }). %%--------------------------------------------------------------------------- %% Interface %%--------------------------------------------------------------------------- start_link(Sock, Connection, ChMgr, AState) -> gen_server:start_link(?MODULE, [Sock, Connection, ChMgr, AState], []). %%--------------------------------------------------------------------------- %% gen_server callbacks %%--------------------------------------------------------------------------- init([Sock, Connection, ChMgr, AState]) -> State = #state{sock = Sock, connection = Connection, channels_manager = ChMgr, astate = AState, message = none}, case rabbit_net:async_recv(Sock, 0, infinity) of {ok, _} -> {ok, State}; {error, Reason} -> {stop, Reason, _} = handle_error(Reason, State), {stop, Reason} end. terminate(_Reason, _State) -> ok. code_change(_OldVsn, State, _Extra) -> {ok, State}. handle_call(Call, From, State) -> {stop, {unexpected_call, Call, From}, State}. handle_cast(Cast, State) -> {stop, {unexpected_cast, Cast}, State}. handle_info({inet_async, Sock, _, {ok, Data}}, State = #state {sock = Sock}) -> %% Latency hiding: Request next packet first, then process data case rabbit_net:async_recv(Sock, 0, infinity) of {ok, _} -> handle_data(Data, State); {error, Reason} -> handle_error(Reason, State) end; handle_info({inet_async, Sock, _, {error, Reason}}, State = #state{sock = Sock}) -> handle_error(Reason, State). handle_data(<>, #state{message = none} = State) when Type =:= ?FRAME_METHOD; Type =:= ?FRAME_HEADER; Type =:= ?FRAME_BODY; Type =:= ?FRAME_HEARTBEAT -> %% Optimisation for the direct match handle_data( More, process_frame(Type, Channel, Payload, State#state{message = none})); handle_data(<>, #state{message = none} = State) when Type =:= ?FRAME_METHOD; Type =:= ?FRAME_HEADER; Type =:= ?FRAME_BODY; Type =:= ?FRAME_HEARTBEAT -> {noreply, State#state{message = {Type, Channel, Length, Data}}}; handle_data(<<"AMQP", A, B, C>>, #state{sock = Sock, message = none} = State) -> {ok, <>} = rabbit_net:sync_recv(Sock, 1), handle_error({refused, {A, B, C, D}}, State); handle_data(<>, #state{message = none} = State) -> handle_error({malformed_header, Malformed}, State); handle_data(<>, #state{message = none} = State) -> {noreply, State#state{message = {expecting_header, Data}}}; handle_data(Data, #state{message = {Type, Channel, L, OldData}} = State) -> case <> of <> -> handle_data(More, process_frame(Type, Channel, Payload, State#state{message = none})); NotEnough -> %% Read in more data from the socket {noreply, State#state{message = {Type, Channel, L, NotEnough}}} end; handle_data(Data, #state{message = {expecting_header, Old}} = State) -> handle_data(<>, State#state{message = none}); handle_data(<<>>, State) -> {noreply, State}. %%--------------------------------------------------------------------------- %% Internal plumbing %%--------------------------------------------------------------------------- process_frame(Type, ChNumber, Payload, State = #state{connection = Connection, channels_manager = ChMgr, astate = AState}) -> case rabbit_command_assembler:analyze_frame(Type, Payload, ?PROTOCOL) of heartbeat when ChNumber /= 0 -> amqp_gen_connection:server_misbehaved( Connection, #amqp_error{name = command_invalid, explanation = "heartbeat on non-zero channel"}), State; %% Match heartbeats but don't do anything with them heartbeat -> State; AnalyzedFrame when ChNumber /= 0 -> amqp_channels_manager:pass_frame(ChMgr, ChNumber, AnalyzedFrame), State; AnalyzedFrame -> State#state{astate = amqp_channels_manager:process_channel_frame( AnalyzedFrame, 0, Connection, AState)} end. handle_error(closed, State = #state{connection = Conn}) -> Conn ! socket_closed, {noreply, State}; handle_error({refused, Version}, State = #state{connection = Conn}) -> Conn ! {refused, Version}, {noreply, State}; handle_error({malformed_header, Version}, State = #state{connection = Conn}) -> Conn ! {malformed_header, Version}, {noreply, State}; handle_error(Reason, State = #state{connection = Conn}) -> Conn ! {socket_error, Reason}, {stop, {socket_error, Reason}, State}. rabbitmq-server-3.2.4/plugins-src/rabbitmq-erlang-client/src/amqp_network_connection.erl0000644000000000000000000003535612305126066030352 0ustar rootroot%% The contents of this file are subject to the Mozilla Public License %% Version 1.1 (the "License"); you may not use this file except in %% compliance with the License. You may obtain a copy of the License at %% http://www.mozilla.org/MPL/ %% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the %% License for the specific language governing rights and limitations %% under the License. %% %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is GoPivotal, Inc. %% Copyright (c) 2007-2013 GoPivotal, Inc. All rights reserved. %% %% @private -module(amqp_network_connection). -include("amqp_client_internal.hrl"). -behaviour(amqp_gen_connection). -export([init/0, terminate/2, connect/4, do/2, open_channel_args/1, i/2, info_keys/0, handle_message/2, closing/3, channels_terminated/1]). -define(RABBIT_TCP_OPTS, [binary, {packet, 0}, {active,false}, {nodelay, true}]). -define(SOCKET_CLOSING_TIMEOUT, 1000). -define(HANDSHAKE_RECEIVE_TIMEOUT, 60000). -define(TCP_MAX_PACKET_SIZE, (16#4000000 + ?EMPTY_FRAME_SIZE - 1)). -record(state, {sock, heartbeat, writer0, frame_max, type_sup, closing_reason, %% undefined | Reason waiting_socket_close = false}). -define(INFO_KEYS, [type, heartbeat, frame_max, sock]). %%--------------------------------------------------------------------------- init() -> {ok, #state{}}. open_channel_args(#state{sock = Sock, frame_max = FrameMax}) -> [Sock, FrameMax]. do(#'connection.close_ok'{} = CloseOk, State) -> erlang:send_after(?SOCKET_CLOSING_TIMEOUT, self(), socket_closing_timeout), do2(CloseOk, State); do(Method, State) -> do2(Method, State). do2(Method, #state{writer0 = Writer}) -> %% Catching because it expects the {channel_exit, _, _} message on error catch rabbit_writer:send_command_sync(Writer, Method). handle_message(socket_closing_timeout, State = #state{closing_reason = Reason}) -> {stop, {socket_closing_timeout, Reason}, State}; handle_message(socket_closed, State = #state{waiting_socket_close = true, closing_reason = Reason}) -> {stop, {shutdown, Reason}, State}; handle_message(socket_closed, State = #state{waiting_socket_close = false}) -> {stop, socket_closed_unexpectedly, State}; handle_message({socket_error, _} = SocketError, State) -> {stop, SocketError, State}; handle_message({channel_exit, 0, Reason}, State) -> {stop, {channel0_died, Reason}, State}; handle_message(heartbeat_timeout, State) -> {stop, heartbeat_timeout, State}; handle_message(closing_timeout, State = #state{closing_reason = Reason}) -> {stop, Reason, State}; %% see http://erlang.org/pipermail/erlang-bugs/2012-June/002933.html handle_message({Ref, {error, Reason}}, State = #state{waiting_socket_close = Waiting, closing_reason = CloseReason}) when is_reference(Ref) -> {stop, case {Reason, Waiting} of {closed, true} -> {shutdown, CloseReason}; {closed, false} -> socket_closed_unexpectedly; {_, _} -> {socket_error, Reason} end, State}. closing(_ChannelCloseType, Reason, State) -> {ok, State#state{closing_reason = Reason}}. channels_terminated(State = #state{closing_reason = {server_initiated_close, _, _}}) -> {ok, State#state{waiting_socket_close = true}}; channels_terminated(State) -> {ok, State}. terminate(_Reason, _State) -> ok. i(type, _State) -> network; i(heartbeat, State) -> State#state.heartbeat; i(frame_max, State) -> State#state.frame_max; i(sock, State) -> State#state.sock; i(Item, _State) -> throw({bad_argument, Item}). info_keys() -> ?INFO_KEYS. %%--------------------------------------------------------------------------- %% Handshake %%--------------------------------------------------------------------------- connect(AmqpParams = #amqp_params_network{host = Host}, SIF, TypeSup, State) -> case gethostaddr(Host) of [] -> {error, unknown_host}; [AF|_] -> do_connect( AF, AmqpParams, SIF, State#state{type_sup = TypeSup}) end. do_connect({Addr, Family}, AmqpParams = #amqp_params_network{ssl_options = none, port = Port, connection_timeout = Timeout, socket_options = ExtraOpts}, SIF, State) -> obtain(), case gen_tcp:connect(Addr, Port, [Family | ?RABBIT_TCP_OPTS] ++ ExtraOpts, Timeout) of {ok, Sock} -> try_handshake(AmqpParams, SIF, State#state{sock = Sock}); {error, _} = E -> E end; do_connect({Addr, Family}, AmqpParams = #amqp_params_network{ssl_options = SslOpts, port = Port, connection_timeout = Timeout, socket_options = ExtraOpts}, SIF, State) -> app_utils:start_applications([asn1, crypto, public_key, ssl]), obtain(), case gen_tcp:connect(Addr, Port, [Family | ?RABBIT_TCP_OPTS] ++ ExtraOpts, Timeout) of {ok, Sock} -> case ssl:connect(Sock, SslOpts) of {ok, SslSock} -> RabbitSslSock = #ssl_socket{ssl = SslSock, tcp = Sock}, try_handshake(AmqpParams, SIF, State#state{sock = RabbitSslSock}); {error, _} = E -> E end; {error, _} = E -> E end. inet_address_preference() -> case application:get_env(amqp_client, prefer_ipv6) of {ok, true} -> [inet6, inet]; {ok, false} -> [inet, inet6] end. gethostaddr(Host) -> Lookups = [{Family, inet:getaddr(Host, Family)} || Family <- inet_address_preference()], [{IP, Family} || {Family, {ok, IP}} <- Lookups]. try_handshake(AmqpParams, SIF, State) -> try handshake(AmqpParams, SIF, State) of Return -> Return catch exit:Reason -> {error, Reason} end. handshake(AmqpParams, SIF, State0 = #state{sock = Sock}) -> ok = rabbit_net:send(Sock, ?PROTOCOL_HEADER), network_handshake(AmqpParams, start_infrastructure(SIF, State0)). start_infrastructure(SIF, State = #state{sock = Sock}) -> {ok, Writer} = SIF(Sock), State#state{writer0 = Writer}. network_handshake(AmqpParams = #amqp_params_network{virtual_host = VHost}, State0) -> Start = #'connection.start'{server_properties = ServerProperties, mechanisms = Mechanisms} = handshake_recv('connection.start'), ok = check_version(Start), case login(AmqpParams, Mechanisms, State0) of {closing, #amqp_error{}, _Error} = Err -> do(#'connection.close_ok'{}, State0), Err; Tune -> {TuneOk, ChannelMax, State1} = tune(Tune, AmqpParams, State0), do2(TuneOk, State1), do2(#'connection.open'{virtual_host = VHost}, State1), Params = {ServerProperties, ChannelMax, State1}, case handshake_recv('connection.open_ok') of #'connection.open_ok'{} -> {ok, Params}; {closing, #amqp_error{} = AmqpError, Error} -> {closing, Params, AmqpError, Error} end end. check_version(#'connection.start'{version_major = ?PROTOCOL_VERSION_MAJOR, version_minor = ?PROTOCOL_VERSION_MINOR}) -> ok; check_version(#'connection.start'{version_major = 8, version_minor = 0}) -> exit({protocol_version_mismatch, 0, 8}); check_version(#'connection.start'{version_major = Major, version_minor = Minor}) -> exit({protocol_version_mismatch, Major, Minor}). tune(#'connection.tune'{channel_max = ServerChannelMax, frame_max = ServerFrameMax, heartbeat = ServerHeartbeat}, #amqp_params_network{channel_max = ClientChannelMax, frame_max = ClientFrameMax, heartbeat = ClientHeartbeat}, State) -> [ChannelMax, Heartbeat, FrameMax] = lists:zipwith(fun (Client, Server) when Client =:= 0; Server =:= 0 -> lists:max([Client, Server]); (Client, Server) -> lists:min([Client, Server]) end, [ClientChannelMax, ClientHeartbeat, ClientFrameMax], [ServerChannelMax, ServerHeartbeat, ServerFrameMax]), %% If we attempt to recv > 64Mb, inet_drv will return enomem, so %% we cap the max negotiated frame size accordingly. Note that %% since we receive the frame header separately, we can actually %% cope with frame sizes of 64M + ?EMPTY_FRAME_SIZE - 1. CappedFrameMax = case FrameMax of 0 -> ?TCP_MAX_PACKET_SIZE; _ -> lists:min([FrameMax, ?TCP_MAX_PACKET_SIZE]) end, NewState = State#state{heartbeat = Heartbeat, frame_max = CappedFrameMax}, start_heartbeat(NewState), {#'connection.tune_ok'{channel_max = ChannelMax, frame_max = CappedFrameMax, heartbeat = Heartbeat}, ChannelMax, NewState}. start_heartbeat(#state{sock = Sock, heartbeat = Heartbeat, type_sup = Sup}) -> Frame = rabbit_binary_generator:build_heartbeat_frame(), SendFun = fun () -> catch rabbit_net:send(Sock, Frame) end, Connection = self(), ReceiveFun = fun () -> Connection ! heartbeat_timeout end, rabbit_heartbeat:start( Sup, Sock, Heartbeat, SendFun, Heartbeat, ReceiveFun). login(Params = #amqp_params_network{auth_mechanisms = ClientMechanisms, client_properties = UserProps}, ServerMechanismsStr, State) -> ServerMechanisms = string:tokens(binary_to_list(ServerMechanismsStr), " "), case [{N, S, F} || F <- ClientMechanisms, {N, S} <- [F(none, Params, init)], lists:member(binary_to_list(N), ServerMechanisms)] of [{Name, MState0, Mech}|_] -> {Resp, MState1} = Mech(none, Params, MState0), StartOk = #'connection.start_ok'{ client_properties = client_properties(UserProps), mechanism = Name, response = Resp}, do2(StartOk, State), login_loop(Mech, MState1, Params, State); [] -> exit({no_suitable_auth_mechanism, ServerMechanisms}) end. login_loop(Mech, MState0, Params, State) -> case handshake_recv('connection.tune') of Tune = #'connection.tune'{} -> Tune; #'connection.secure'{challenge = Challenge} -> {Resp, MState1} = Mech(Challenge, Params, MState0), do2(#'connection.secure_ok'{response = Resp}, State), login_loop(Mech, MState1, Params, State); #'connection.close'{reply_code = ?ACCESS_REFUSED, reply_text = ExplanationBin} -> Explanation = binary_to_list(ExplanationBin), {closing, #amqp_error{name = access_refused, explanation = Explanation}, {error, {auth_failure, Explanation}}} end. client_properties(UserProperties) -> {ok, Vsn} = application:get_key(amqp_client, vsn), Default = [{<<"product">>, longstr, <<"RabbitMQ">>}, {<<"version">>, longstr, list_to_binary(Vsn)}, {<<"platform">>, longstr, <<"Erlang">>}, {<<"copyright">>, longstr, <<"Copyright (c) 2007-2013 GoPivotal, Inc.">>}, {<<"information">>, longstr, <<"Licensed under the MPL. " "See http://www.rabbitmq.com/">>}, {<<"capabilities">>, table, ?CLIENT_CAPABILITIES}], lists:foldl(fun({K, _, _} = Tuple, Acc) -> lists:keystore(K, 1, Acc, Tuple) end, Default, UserProperties). handshake_recv(Expecting) -> receive {'$gen_cast', {method, Method, none, noflow}} -> case {Expecting, element(1, Method)} of {E, M} when E =:= M -> Method; {'connection.tune', 'connection.secure'} -> Method; {'connection.tune', 'connection.close'} -> Method; {'connection.open_ok', _} -> {closing, #amqp_error{name = command_invalid, explanation = "was expecting " "connection.open_ok"}, {error, {unexpected_method, Method, {expecting, Expecting}}}}; _ -> throw({unexpected_method, Method, {expecting, Expecting}}) end; socket_closed -> case Expecting of 'connection.tune' -> exit({auth_failure, "Disconnected"}); 'connection.open_ok' -> exit(access_refused); _ -> exit({socket_closed_unexpectedly, Expecting}) end; {socket_error, _} = SocketError -> exit({SocketError, {expecting, Expecting}}); {refused, Version} -> exit({server_refused_connection, Version}); {malformed_header, All} -> exit({server_sent_malformed_header, All}); heartbeat_timeout -> exit(heartbeat_timeout); Other -> throw({handshake_recv_unexpected_message, Other}) after ?HANDSHAKE_RECEIVE_TIMEOUT -> case Expecting of 'connection.open_ok' -> {closing, #amqp_error{name = internal_error, explanation = "handshake timed out waiting " "connection.open_ok"}, {error, handshake_receive_timed_out}}; _ -> exit(handshake_receive_timed_out) end end. obtain() -> case code:is_loaded(file_handle_cache) of false -> ok; _ -> file_handle_cache:obtain() end. rabbitmq-server-3.2.4/plugins-src/rabbitmq-erlang-client/src/amqp_channel.erl0000644000000000000000000011261512305126066026044 0ustar rootroot%% The contents of this file are subject to the Mozilla Public License %% Version 1.1 (the "License"); you may not use this file except in %% compliance with the License. You may obtain a copy of the License at %% http://www.mozilla.org/MPL/ %% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the %% License for the specific language governing rights and limitations %% under the License. %% %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is GoPivotal, Inc. %% Copyright (c) 2007-2013 GoPivotal, Inc. All rights reserved. %% %% @type close_reason(Type) = {shutdown, amqp_reason(Type)}. %% @type amqp_reason(Type) = {Type, Code, Text} %% Code = non_neg_integer() %% Text = binary(). %% @doc This module encapsulates the client's view of an AMQP %% channel. Each server side channel is represented by an amqp_channel %% process on the client side. Channel processes are created using the %% {@link amqp_connection} module. Channel processes are supervised %% under amqp_client's supervision tree.
    %%
    %% In case of a failure or an AMQP error, the channel process exits with a %% meaningful exit reason:
    %%
    %% %% %% %% %% %% %% %% %% %% %% %% %% %% %% %% %% %% %% %% %% %% %% %% %% %% %% %% %% %%
    CauseExit reason
    Any reason, where Code would have been 200 otherwise```normal'''
    User application calls amqp_channel:close/3```close_reason(app_initiated_close)'''
    Server closes channel (soft error)```close_reason(server_initiated_close)'''
    Server misbehaved (did not follow protocol)```close_reason(server_misbehaved)'''
    Connection is closing (causing all channels to cleanup and %% close)```{shutdown, {connection_closing, amqp_reason(atom())}}'''
    Other error(various error reasons, causing more detailed logging)
    %%
    %% See type definitions below. -module(amqp_channel). -include("amqp_client_internal.hrl"). -behaviour(gen_server). -export([call/2, call/3, cast/2, cast/3, cast_flow/3]). -export([close/1, close/3]). -export([register_return_handler/2, unregister_return_handler/1, register_flow_handler/2, unregister_flow_handler/1, register_confirm_handler/2, unregister_confirm_handler/1]). -export([call_consumer/2, subscribe/3]). -export([next_publish_seqno/1, wait_for_confirms/1, wait_for_confirms/2, wait_for_confirms_or_die/1, wait_for_confirms_or_die/2]). -export([start_link/4, set_writer/2, connection_closing/3, open/1]). -export([init/1, terminate/2, code_change/3, handle_call/3, handle_cast/2, handle_info/2]). -define(TIMEOUT_FLUSH, 60000). -record(state, {number, connection, consumer, driver, rpc_requests = queue:new(), closing = false, %% false | %% {just_channel, Reason} | %% {connection, Reason} writer, return_handler = none, confirm_handler = none, next_pub_seqno = 0, flow_active = true, flow_handler = none, unconfirmed_set = gb_sets:new(), waiting_set = gb_trees:empty(), only_acks_received = true }). %%--------------------------------------------------------------------------- %% Type Definitions %%--------------------------------------------------------------------------- %% @type amqp_method(). %% This abstract datatype represents the set of methods that comprise %% the AMQP execution model. As indicated in the overview, the %% attributes of each method in the execution model are described in %% the protocol documentation. The Erlang record definitions are %% autogenerated from a parseable version of the specification. Most %% fields in the generated records have sensible default values that %% you need not worry in the case of a simple usage of the client %% library. %% @type amqp_msg() = #amqp_msg{}. %% This is the content encapsulated in content-bearing AMQP methods. It %% contains the following fields: %%
      %%
    • props :: class_property() - A class property record, defaults to %% #'P_basic'{}
    • %%
    • payload :: binary() - The arbitrary data payload
    • %%
    %%--------------------------------------------------------------------------- %% AMQP Channel API methods %%--------------------------------------------------------------------------- %% @spec (Channel, Method) -> Result %% @doc This is equivalent to amqp_channel:call(Channel, Method, none). call(Channel, Method) -> gen_server:call(Channel, {call, Method, none, self()}, infinity). %% @spec (Channel, Method, Content) -> Result %% where %% Channel = pid() %% Method = amqp_method() %% Content = amqp_msg() | none %% Result = amqp_method() | ok | blocked | closing %% @doc This sends an AMQP method on the channel. %% For content bearing methods, Content has to be an amqp_msg(), whereas %% for non-content bearing methods, it needs to be the atom 'none'.
    %% In the case of synchronous methods, this function blocks until the %% corresponding reply comes back from the server and returns it. %% In the case of asynchronous methods, the function blocks until the method %% gets sent on the wire and returns the atom 'ok' on success.
    %% This will return the atom 'blocked' if the server has %% throttled the client for flow control reasons. This will return the %% atom 'closing' if the channel is in the process of shutting down.
    %% Note that for asynchronous methods, the synchronicity implied by %% 'call' only means that the client has transmitted the method to %% the broker. It does not necessarily imply that the broker has %% accepted responsibility for the message. call(Channel, Method, Content) -> gen_server:call(Channel, {call, Method, Content, self()}, infinity). %% @spec (Channel, Method) -> ok %% @doc This is equivalent to amqp_channel:cast(Channel, Method, none). cast(Channel, Method) -> gen_server:cast(Channel, {cast, Method, none, self(), noflow}). %% @spec (Channel, Method, Content) -> ok %% where %% Channel = pid() %% Method = amqp_method() %% Content = amqp_msg() | none %% @doc This function is the same as {@link call/3}, except that it returns %% immediately with the atom 'ok', without blocking the caller process. %% This function is not recommended with synchronous methods, since there is no %% way to verify that the server has received the method. cast(Channel, Method, Content) -> gen_server:cast(Channel, {cast, Method, Content, self(), noflow}). %% @spec (Channel, Method, Content) -> ok %% where %% Channel = pid() %% Method = amqp_method() %% Content = amqp_msg() | none %% @doc Like cast/3, with flow control. cast_flow(Channel, Method, Content) -> credit_flow:send(Channel), gen_server:cast(Channel, {cast, Method, Content, self(), flow}). %% @spec (Channel) -> ok | closing %% where %% Channel = pid() %% @doc Closes the channel, invokes %% close(Channel, 200, <<"Goodbye">>). close(Channel) -> close(Channel, 200, <<"Goodbye">>). %% @spec (Channel, Code, Text) -> ok | closing %% where %% Channel = pid() %% Code = integer() %% Text = binary() %% @doc Closes the channel, allowing the caller to supply a reply code and %% text. If the channel is already closing, the atom 'closing' is returned. close(Channel, Code, Text) -> gen_server:call(Channel, {close, Code, Text}, infinity). %% @spec (Channel) -> integer() %% where %% Channel = pid() %% @doc When in confirm mode, returns the sequence number of the next %% message to be published. next_publish_seqno(Channel) -> gen_server:call(Channel, next_publish_seqno, infinity). %% @spec (Channel) -> boolean() | 'timeout' %% where %% Channel = pid() %% @doc Wait until all messages published since the last call have %% been either ack'd or nack'd by the broker. Note, when called on a %% non-Confirm channel, waitForConfirms returns an error. wait_for_confirms(Channel) -> wait_for_confirms(Channel, infinity). %% @spec (Channel, Timeout) -> boolean() | 'timeout' %% where %% Channel = pid() %% Timeout = non_neg_integer() | 'infinity' %% @doc Wait until all messages published since the last call have %% been either ack'd or nack'd by the broker or the timeout expires. %% Note, when called on a non-Confirm channel, waitForConfirms throws %% an exception. wait_for_confirms(Channel, Timeout) -> case gen_server:call(Channel, {wait_for_confirms, Timeout}, infinity) of {error, Reason} -> throw(Reason); Other -> Other end. %% @spec (Channel) -> true %% where %% Channel = pid() %% @doc Behaves the same as wait_for_confirms/1, but if a nack is %% received, the calling process is immediately sent an %% exit(nack_received). wait_for_confirms_or_die(Channel) -> wait_for_confirms_or_die(Channel, infinity). %% @spec (Channel, Timeout) -> true %% where %% Channel = pid() %% Timeout = non_neg_integer() | 'infinity' %% @doc Behaves the same as wait_for_confirms/1, but if a nack is %% received, the calling process is immediately sent an %% exit(nack_received). If the timeout expires, the calling process is %% sent an exit(timeout). wait_for_confirms_or_die(Channel, Timeout) -> case wait_for_confirms(Channel, Timeout) of timeout -> close(Channel, 200, <<"Confirm Timeout">>), exit(timeout); false -> close(Channel, 200, <<"Nacks Received">>), exit(nacks_received); true -> true end. %% @spec (Channel, ReturnHandler) -> ok %% where %% Channel = pid() %% ReturnHandler = pid() %% @doc This registers a handler to deal with returned messages. The %% registered process will receive #basic.return{} records. register_return_handler(Channel, ReturnHandler) -> gen_server:cast(Channel, {register_return_handler, ReturnHandler} ). %% @spec (Channel) -> ok %% where %% Channel = pid() %% @doc Removes the return handler, if it exists. Does nothing if there is no %% such handler. unregister_return_handler(Channel) -> gen_server:cast(Channel, unregister_return_handler). %% @spec (Channel, ConfirmHandler) -> ok %% where %% Channel = pid() %% ConfirmHandler = pid() %% @doc This registers a handler to deal with confirm-related %% messages. The registered process will receive #basic.ack{} and %% #basic.nack{} commands. register_confirm_handler(Channel, ConfirmHandler) -> gen_server:cast(Channel, {register_confirm_handler, ConfirmHandler} ). %% @spec (Channel) -> ok %% where %% Channel = pid() %% @doc Removes the confirm handler, if it exists. Does nothing if there is no %% such handler. unregister_confirm_handler(Channel) -> gen_server:cast(Channel, unregister_confirm_handler). %% @spec (Channel, FlowHandler) -> ok %% where %% Channel = pid() %% FlowHandler = pid() %% @doc This registers a handler to deal with channel flow notifications. %% The registered process will receive #channel.flow{} records. register_flow_handler(Channel, FlowHandler) -> gen_server:cast(Channel, {register_flow_handler, FlowHandler} ). %% @spec (Channel) -> ok %% where %% Channel = pid() %% @doc Removes the flow handler, if it exists. Does nothing if there is no %% such handler. unregister_flow_handler(Channel) -> gen_server:cast(Channel, unregister_flow_handler). %% @spec (Channel, Msg) -> ok %% where %% Channel = pid() %% Msg = any() %% @doc This causes the channel to invoke Consumer:handle_call/2, %% where Consumer is the amqp_gen_consumer implementation registered with %% the channel. call_consumer(Channel, Msg) -> gen_server:call(Channel, {call_consumer, Msg}, infinity). %% @spec (Channel, BasicConsume, Subscriber) -> ok %% where %% Channel = pid() %% BasicConsume = amqp_method() %% Subscriber = pid() %% @doc Subscribe the given pid to a queue using the specified %% basic.consume method. subscribe(Channel, BasicConsume = #'basic.consume'{}, Subscriber) -> gen_server:call(Channel, {subscribe, BasicConsume, Subscriber}, infinity). %%--------------------------------------------------------------------------- %% Internal interface %%--------------------------------------------------------------------------- %% @private start_link(Driver, Connection, ChannelNumber, Consumer) -> gen_server:start_link( ?MODULE, [Driver, Connection, ChannelNumber, Consumer], []). set_writer(Pid, Writer) -> gen_server:cast(Pid, {set_writer, Writer}). %% @private connection_closing(Pid, ChannelCloseType, Reason) -> gen_server:cast(Pid, {connection_closing, ChannelCloseType, Reason}). %% @private open(Pid) -> gen_server:call(Pid, open, infinity). %%--------------------------------------------------------------------------- %% gen_server callbacks %%--------------------------------------------------------------------------- %% @private init([Driver, Connection, ChannelNumber, Consumer]) -> {ok, #state{connection = Connection, driver = Driver, number = ChannelNumber, consumer = Consumer}}. %% @private handle_call(open, From, State) -> {noreply, rpc_top_half(#'channel.open'{}, none, From, none, noflow, State)}; %% @private handle_call({close, Code, Text}, From, State) -> handle_close(Code, Text, From, State); %% @private handle_call({call, Method, AmqpMsg, Sender}, From, State) -> handle_method_to_server(Method, AmqpMsg, From, Sender, noflow, State); %% Handles the delivery of messages from a direct channel %% @private handle_call({send_command_sync, Method, Content}, From, State) -> Ret = handle_method_from_server(Method, Content, State), gen_server:reply(From, ok), Ret; %% Handles the delivery of messages from a direct channel %% @private handle_call({send_command_sync, Method}, From, State) -> Ret = handle_method_from_server(Method, none, State), gen_server:reply(From, ok), Ret; %% @private handle_call(next_publish_seqno, _From, State = #state{next_pub_seqno = SeqNo}) -> {reply, SeqNo, State}; handle_call({wait_for_confirms, Timeout}, From, State) -> handle_wait_for_confirms(From, Timeout, State); %% @private handle_call({call_consumer, Msg}, _From, State = #state{consumer = Consumer}) -> {reply, amqp_gen_consumer:call_consumer(Consumer, Msg), State}; %% @private handle_call({subscribe, BasicConsume, Subscriber}, From, State) -> handle_method_to_server(BasicConsume, none, From, Subscriber, noflow, State). %% @private handle_cast({set_writer, Writer}, State) -> {noreply, State#state{writer = Writer}}; %% @private handle_cast({cast, Method, AmqpMsg, Sender, noflow}, State) -> handle_method_to_server(Method, AmqpMsg, none, Sender, noflow, State); handle_cast({cast, Method, AmqpMsg, Sender, flow}, State) -> credit_flow:ack(Sender), handle_method_to_server(Method, AmqpMsg, none, Sender, flow, State); %% @private handle_cast({register_return_handler, ReturnHandler}, State) -> Ref = erlang:monitor(process, ReturnHandler), {noreply, State#state{return_handler = {ReturnHandler, Ref}}}; %% @private handle_cast(unregister_return_handler, State = #state{return_handler = {_ReturnHandler, Ref}}) -> erlang:demonitor(Ref), {noreply, State#state{return_handler = none}}; %% @private handle_cast({register_confirm_handler, ConfirmHandler}, State) -> Ref = erlang:monitor(process, ConfirmHandler), {noreply, State#state{confirm_handler = {ConfirmHandler, Ref}}}; %% @private handle_cast(unregister_confirm_handler, State = #state{confirm_handler = {_ConfirmHandler, Ref}}) -> erlang:demonitor(Ref), {noreply, State#state{confirm_handler = none}}; %% @private handle_cast({register_flow_handler, FlowHandler}, State) -> Ref = erlang:monitor(process, FlowHandler), {noreply, State#state{flow_handler = {FlowHandler, Ref}}}; %% @private handle_cast(unregister_flow_handler, State = #state{flow_handler = {_FlowHandler, Ref}}) -> erlang:demonitor(Ref), {noreply, State#state{flow_handler = none}}; %% Received from channels manager %% @private handle_cast({method, Method, Content, noflow}, State) -> handle_method_from_server(Method, Content, State); %% Handles the situation when the connection closes without closing the channel %% beforehand. The channel must block all further RPCs, %% flush the RPC queue (optional), and terminate %% @private handle_cast({connection_closing, CloseType, Reason}, State) -> handle_connection_closing(CloseType, Reason, State); %% @private handle_cast({shutdown, Shutdown}, State) -> handle_shutdown(Shutdown, State). %% Received from rabbit_channel in the direct case %% @private handle_info({send_command, Method}, State) -> handle_method_from_server(Method, none, State); %% Received from rabbit_channel in the direct case %% @private handle_info({send_command, Method, Content}, State) -> handle_method_from_server(Method, Content, State); %% Received from rabbit_channel in the direct case %% @private handle_info({send_command_and_notify, Q, ChPid, Method, Content}, State) -> handle_method_from_server(Method, Content, State), rabbit_amqqueue:notify_sent(Q, ChPid), {noreply, State}; %% This comes from the writer or rabbit_channel %% @private handle_info({channel_exit, _ChNumber, Reason}, State) -> handle_channel_exit(Reason, State); %% This comes from rabbit_channel in the direct case handle_info({channel_closing, ChPid}, State) -> ok = rabbit_channel:ready_for_close(ChPid), {noreply, State}; %% @private handle_info({bump_credit, Msg}, State) -> credit_flow:handle_bump_msg(Msg), {noreply, State}; %% @private handle_info(timed_out_flushing_channel, State) -> ?LOG_WARN("Channel (~p) closing: timed out flushing while " "connection closing~n", [self()]), {stop, timed_out_flushing_channel, State}; %% @private handle_info({'DOWN', _, process, ReturnHandler, Reason}, State = #state{return_handler = {ReturnHandler, _Ref}}) -> ?LOG_WARN("Channel (~p): Unregistering return handler ~p because it died. " "Reason: ~p~n", [self(), ReturnHandler, Reason]), {noreply, State#state{return_handler = none}}; %% @private handle_info({'DOWN', _, process, ConfirmHandler, Reason}, State = #state{confirm_handler = {ConfirmHandler, _Ref}}) -> ?LOG_WARN("Channel (~p): Unregistering confirm handler ~p because it died. " "Reason: ~p~n", [self(), ConfirmHandler, Reason]), {noreply, State#state{confirm_handler = none}}; %% @private handle_info({'DOWN', _, process, FlowHandler, Reason}, State = #state{flow_handler = {FlowHandler, _Ref}}) -> ?LOG_WARN("Channel (~p): Unregistering flow handler ~p because it died. " "Reason: ~p~n", [self(), FlowHandler, Reason]), {noreply, State#state{flow_handler = none}}; handle_info({'DOWN', _, process, QPid, _Reason}, State) -> rabbit_amqqueue:notify_sent_queue_down(QPid), {noreply, State}; handle_info({confirm_timeout, From}, State = #state{waiting_set = WSet}) -> case gb_trees:lookup(From, WSet) of none -> {noreply, State}; {value, _} -> gen_server:reply(From, timeout), {noreply, State#state{waiting_set = gb_trees:delete(From, WSet)}} end. %% @private terminate(_Reason, State) -> flush_writer(State), State. %% @private code_change(_OldVsn, State, _Extra) -> {ok, State}. %%--------------------------------------------------------------------------- %% RPC mechanism %%--------------------------------------------------------------------------- handle_method_to_server(Method, AmqpMsg, From, Sender, Flow, State = #state{unconfirmed_set = USet}) -> case {check_invalid_method(Method), From, check_block(Method, AmqpMsg, State)} of {ok, _, ok} -> State1 = case {Method, State#state.next_pub_seqno} of {#'confirm.select'{}, _} -> State#state{next_pub_seqno = 1}; {#'basic.publish'{}, 0} -> State; {#'basic.publish'{}, SeqNo} -> State#state{unconfirmed_set = gb_sets:add(SeqNo, USet), next_pub_seqno = SeqNo + 1}; _ -> State end, {noreply, rpc_top_half(Method, build_content(AmqpMsg), From, Sender, Flow, State1)}; {ok, none, BlockReply} -> ?LOG_WARN("Channel (~p): discarding method ~p in cast.~n" "Reason: ~p~n", [self(), Method, BlockReply]), {noreply, State}; {ok, _, BlockReply} -> {reply, BlockReply, State}; {{_, InvalidMethodMessage}, none, _} -> ?LOG_WARN("Channel (~p): ignoring cast of ~p method. " ++ InvalidMethodMessage ++ "~n", [self(), Method]), {noreply, State}; {{InvalidMethodReply, _}, _, _} -> {reply, {error, InvalidMethodReply}, State} end. handle_close(Code, Text, From, State) -> Close = #'channel.close'{reply_code = Code, reply_text = Text, class_id = 0, method_id = 0}, case check_block(Close, none, State) of ok -> {noreply, rpc_top_half(Close, none, From, none, noflow, State)}; BlockReply -> {reply, BlockReply, State} end. rpc_top_half(Method, Content, From, Sender, Flow, State0 = #state{rpc_requests = RequestQueue}) -> State1 = State0#state{ rpc_requests = queue:in({From, Sender, Method, Content, Flow}, RequestQueue)}, IsFirstElement = queue:is_empty(RequestQueue), if IsFirstElement -> do_rpc(State1); true -> State1 end. rpc_bottom_half(Reply, State = #state{rpc_requests = RequestQueue}) -> {{value, {From, _Sender, _Method, _Content, _Flow}}, RequestQueue1} = queue:out(RequestQueue), case From of none -> ok; _ -> gen_server:reply(From, Reply) end, do_rpc(State#state{rpc_requests = RequestQueue1}). do_rpc(State = #state{rpc_requests = Q, closing = Closing}) -> case queue:out(Q) of {{value, {From, Sender, Method, Content, Flow}}, NewQ} -> State1 = pre_do(Method, Content, Sender, State), DoRet = do(Method, Content, Flow, State1), case ?PROTOCOL:is_method_synchronous(Method) of true -> State1; false -> case {From, DoRet} of {none, _} -> ok; {_, ok} -> gen_server:reply(From, ok); _ -> ok %% Do not reply if error in do. Expecting %% {channel_exit, _, _} end, do_rpc(State1#state{rpc_requests = NewQ}) end; {empty, NewQ} -> case Closing of {connection, Reason} -> gen_server:cast(self(), {shutdown, {connection_closing, Reason}}); _ -> ok end, State#state{rpc_requests = NewQ} end. pending_rpc_method(#state{rpc_requests = Q}) -> {value, {_From, _Sender, Method, _Content, _Flow}} = queue:peek(Q), Method. pre_do(#'channel.close'{reply_code = Code, reply_text = Text}, none, _Sender, State) -> State#state{closing = {just_channel, {app_initiated_close, Code, Text}}}; pre_do(#'basic.consume'{} = Method, none, Sender, State) -> ok = call_to_consumer(Method, Sender, State), State; pre_do(#'basic.cancel'{} = Method, none, Sender, State) -> ok = call_to_consumer(Method, Sender, State), State; pre_do(_, _, _, State) -> State. %%--------------------------------------------------------------------------- %% Handling of methods from the server %%--------------------------------------------------------------------------- handle_method_from_server(Method, Content, State = #state{closing = Closing}) -> case is_connection_method(Method) of true -> server_misbehaved( #amqp_error{name = command_invalid, explanation = "connection method on " "non-zero channel", method = element(1, Method)}, State); false -> Drop = case {Closing, Method} of {{just_channel, _}, #'channel.close'{}} -> false; {{just_channel, _}, #'channel.close_ok'{}} -> false; {{just_channel, _}, _} -> true; _ -> false end, if Drop -> ?LOG_INFO("Channel (~p): dropping method ~p from " "server because channel is closing~n", [self(), {Method, Content}]), {noreply, State}; true -> handle_method_from_server1(Method, amqp_msg(Content), State) end end. handle_method_from_server1(#'channel.open_ok'{}, none, State) -> {noreply, rpc_bottom_half(ok, State)}; handle_method_from_server1(#'channel.close'{reply_code = Code, reply_text = Text}, none, State = #state{closing = {just_channel, _}}) -> %% Both client and server sent close at the same time. Don't shutdown yet, %% wait for close_ok. do(#'channel.close_ok'{}, none, noflow, State), {noreply, State#state{ closing = {just_channel, {server_initiated_close, Code, Text}}}}; handle_method_from_server1(#'channel.close'{reply_code = Code, reply_text = Text}, none, State) -> do(#'channel.close_ok'{}, none, noflow, State), handle_shutdown({server_initiated_close, Code, Text}, State); handle_method_from_server1(#'channel.close_ok'{}, none, State = #state{closing = Closing}) -> case Closing of {just_channel, {app_initiated_close, _, _} = Reason} -> handle_shutdown(Reason, rpc_bottom_half(ok, State)); {just_channel, {server_initiated_close, _, _} = Reason} -> handle_shutdown(Reason, rpc_bottom_half(closing, State)); {connection, Reason} -> handle_shutdown({connection_closing, Reason}, State) end; handle_method_from_server1(#'basic.consume_ok'{} = ConsumeOk, none, State) -> Consume = #'basic.consume'{} = pending_rpc_method(State), ok = call_to_consumer(ConsumeOk, Consume, State), {noreply, rpc_bottom_half(ConsumeOk, State)}; handle_method_from_server1(#'basic.cancel_ok'{} = CancelOk, none, State) -> Cancel = #'basic.cancel'{} = pending_rpc_method(State), ok = call_to_consumer(CancelOk, Cancel, State), {noreply, rpc_bottom_half(CancelOk, State)}; handle_method_from_server1(#'basic.cancel'{} = Cancel, none, State) -> ok = call_to_consumer(Cancel, none, State), {noreply, State}; handle_method_from_server1(#'basic.deliver'{} = Deliver, AmqpMsg, State) -> ok = call_to_consumer(Deliver, AmqpMsg, State), {noreply, State}; handle_method_from_server1(#'channel.flow'{active = Active} = Flow, none, State = #state{flow_handler = FlowHandler}) -> case FlowHandler of none -> ok; {Pid, _Ref} -> Pid ! Flow end, %% Putting the flow_ok in the queue so that the RPC queue can be %% flushed beforehand. Methods that made it to the queue are not %% blocked in any circumstance. {noreply, rpc_top_half(#'channel.flow_ok'{active = Active}, none, none, none, noflow, State#state{flow_active = Active})}; handle_method_from_server1( #'basic.return'{} = BasicReturn, AmqpMsg, State = #state{return_handler = ReturnHandler}) -> case ReturnHandler of none -> ?LOG_WARN("Channel (~p): received {~p, ~p} but there is " "no return handler registered~n", [self(), BasicReturn, AmqpMsg]); {Pid, _Ref} -> Pid ! {BasicReturn, AmqpMsg} end, {noreply, State}; handle_method_from_server1(#'basic.ack'{} = BasicAck, none, #state{confirm_handler = none} = State) -> {noreply, update_confirm_set(BasicAck, State)}; handle_method_from_server1(#'basic.ack'{} = BasicAck, none, #state{confirm_handler = {CH, _Ref}} = State) -> CH ! BasicAck, {noreply, update_confirm_set(BasicAck, State)}; handle_method_from_server1(#'basic.nack'{} = BasicNack, none, #state{confirm_handler = none} = State) -> ?LOG_WARN("Channel (~p): received ~p but there is no " "confirm handler registered~n", [self(), BasicNack]), {noreply, update_confirm_set(BasicNack, State)}; handle_method_from_server1(#'basic.nack'{} = BasicNack, none, #state{confirm_handler = {CH, _Ref}} = State) -> CH ! BasicNack, {noreply, update_confirm_set(BasicNack, State)}; handle_method_from_server1(Method, none, State) -> {noreply, rpc_bottom_half(Method, State)}; handle_method_from_server1(Method, Content, State) -> {noreply, rpc_bottom_half({Method, Content}, State)}. %%--------------------------------------------------------------------------- %% Other handle_* functions %%--------------------------------------------------------------------------- handle_connection_closing(CloseType, Reason, State = #state{rpc_requests = RpcQueue, closing = Closing}) -> NewState = State#state{closing = {connection, Reason}}, case {CloseType, Closing, queue:is_empty(RpcQueue)} of {flush, false, false} -> erlang:send_after(?TIMEOUT_FLUSH, self(), timed_out_flushing_channel), {noreply, NewState}; {flush, {just_channel, _}, false} -> {noreply, NewState}; _ -> handle_shutdown({connection_closing, Reason}, NewState) end. handle_channel_exit(Reason = #amqp_error{name = ErrorName, explanation = Expl}, State = #state{connection = Connection, number = Number}) -> %% Sent by rabbit_channel for hard errors in the direct case ?LOG_ERR("connection ~p, channel ~p - error:~n~p~n", [Connection, Number, Reason]), {true, Code, _} = ?PROTOCOL:lookup_amqp_exception(ErrorName), ReportedReason = {server_initiated_close, Code, Expl}, amqp_gen_connection:hard_error_in_channel( Connection, self(), ReportedReason), handle_shutdown({connection_closing, ReportedReason}, State); handle_channel_exit(Reason, State) -> %% Unexpected death of a channel infrastructure process {stop, {infrastructure_died, Reason}, State}. handle_shutdown({_, 200, _}, State) -> {stop, normal, State}; handle_shutdown({connection_closing, {_, 200, _}}, State) -> {stop, normal, State}; handle_shutdown({connection_closing, normal}, State) -> {stop, normal, State}; handle_shutdown(Reason, State) -> {stop, {shutdown, Reason}, State}. %%--------------------------------------------------------------------------- %% Internal plumbing %%--------------------------------------------------------------------------- do(Method, Content, Flow, #state{driver = network, writer = W}) -> %% Catching because it expects the {channel_exit, _, _} message on error catch case {Content, Flow} of {none, _} -> rabbit_writer:send_command(W, Method); {_, flow} -> rabbit_writer:send_command_flow(W, Method, Content); {_, noflow} -> rabbit_writer:send_command(W, Method, Content) end; do(Method, Content, Flow, #state{driver = direct, writer = W}) -> %% ditto catching because... catch case {Content, Flow} of {none, _} -> rabbit_channel:do(W, Method); {_, flow} -> rabbit_channel:do_flow(W, Method, Content); {_, noflow} -> rabbit_channel:do(W, Method, Content) end. flush_writer(#state{driver = network, writer = Writer}) -> try rabbit_writer:flush(Writer) catch exit:noproc -> ok end; flush_writer(#state{driver = direct}) -> ok. amqp_msg(none) -> none; amqp_msg(Content) -> {Props, Payload} = rabbit_basic:from_content(Content), #amqp_msg{props = Props, payload = Payload}. build_content(none) -> none; build_content(#amqp_msg{props = Props, payload = Payload}) -> rabbit_basic:build_content(Props, Payload). check_block(_Method, _AmqpMsg, #state{closing = {just_channel, _}}) -> closing; check_block(_Method, _AmqpMsg, #state{closing = {connection, _}}) -> closing; check_block(_Method, none, #state{}) -> ok; check_block(_Method, #amqp_msg{}, #state{flow_active = false}) -> blocked; check_block(_Method, _AmqpMsg, #state{}) -> ok. check_invalid_method(#'channel.open'{}) -> {use_amqp_connection_module, "Use amqp_connection:open_channel/{1,2} instead"}; check_invalid_method(#'channel.close'{}) -> {use_close_function, "Use close/{1,3} instead"}; check_invalid_method(Method) -> case is_connection_method(Method) of true -> {connection_methods_not_allowed, "Sending connection methods is not allowed"}; false -> ok end. is_connection_method(Method) -> {ClassId, _} = ?PROTOCOL:method_id(element(1, Method)), ?PROTOCOL:lookup_class_name(ClassId) == connection. server_misbehaved(#amqp_error{} = AmqpError, State = #state{number = Number}) -> case rabbit_binary_generator:map_exception(Number, AmqpError, ?PROTOCOL) of {0, _} -> handle_shutdown({server_misbehaved, AmqpError}, State); {_, Close} -> ?LOG_WARN("Channel (~p) flushing and closing due to soft " "error caused by the server ~p~n", [self(), AmqpError]), Self = self(), spawn(fun () -> call(Self, Close) end), {noreply, State} end. update_confirm_set(#'basic.ack'{delivery_tag = SeqNo, multiple = Multiple}, State = #state{unconfirmed_set = USet}) -> maybe_notify_waiters( State#state{unconfirmed_set = update_unconfirmed(SeqNo, Multiple, USet)}); update_confirm_set(#'basic.nack'{delivery_tag = SeqNo, multiple = Multiple}, State = #state{unconfirmed_set = USet}) -> maybe_notify_waiters( State#state{unconfirmed_set = update_unconfirmed(SeqNo, Multiple, USet), only_acks_received = false}). update_unconfirmed(SeqNo, false, USet) -> gb_sets:del_element(SeqNo, USet); update_unconfirmed(SeqNo, true, USet) -> case gb_sets:is_empty(USet) of true -> USet; false -> {S, USet1} = gb_sets:take_smallest(USet), case S > SeqNo of true -> USet; false -> update_unconfirmed(SeqNo, true, USet1) end end. maybe_notify_waiters(State = #state{unconfirmed_set = USet}) -> case gb_sets:is_empty(USet) of false -> State; true -> notify_confirm_waiters(State) end. notify_confirm_waiters(State = #state{waiting_set = WSet, only_acks_received = OAR}) -> [begin safe_cancel_timer(TRef), gen_server:reply(From, OAR) end || {From, TRef} <- gb_trees:to_list(WSet)], State#state{waiting_set = gb_trees:empty(), only_acks_received = true}. handle_wait_for_confirms(_From, _Timeout, State = #state{next_pub_seqno = 0}) -> {reply, {error, not_in_confirm_mode}, State}; handle_wait_for_confirms(From, Timeout, State = #state{unconfirmed_set = USet, waiting_set = WSet}) -> case gb_sets:is_empty(USet) of true -> {reply, true, State}; false -> TRef = case Timeout of infinity -> undefined; _ -> erlang:send_after( Timeout * 1000, self(), {confirm_timeout, From}) end, {noreply, State#state{waiting_set = gb_trees:insert(From, TRef, WSet)}} end. call_to_consumer(Method, Args, #state{consumer = Consumer}) -> amqp_gen_consumer:call_consumer(Consumer, Method, Args). safe_cancel_timer(undefined) -> ok; safe_cancel_timer(TRef) -> erlang:cancel_timer(TRef). rabbitmq-server-3.2.4/plugins-src/rabbitmq-erlang-client/src/amqp_client.erl0000644000000000000000000000234412305126066025707 0ustar rootroot%% The contents of this file are subject to the Mozilla Public License %% Version 1.1 (the "License"); you may not use this file except in %% compliance with the License. You may obtain a copy of the License at %% http://www.mozilla.org/MPL/ %% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the %% License for the specific language governing rights and limitations %% under the License. %% %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is GoPivotal, Inc. %% Copyright (c) 2007-2013 GoPivotal, Inc. All rights reserved. %% %% @private -module(amqp_client). -behaviour(application). -export([start/0]). -export([start/2, stop/1]). %%--------------------------------------------------------------------------- %% Interface %%--------------------------------------------------------------------------- start() -> application:start(amqp_client). %%--------------------------------------------------------------------------- %% application callbacks %%--------------------------------------------------------------------------- start(_StartType, _StartArgs) -> amqp_sup:start_link(). stop(_State) -> ok. rabbitmq-server-3.2.4/plugins-src/rabbitmq-erlang-client/test/0000755000000000000000000000000012305126066023074 5ustar rootrootrabbitmq-server-3.2.4/plugins-src/rabbitmq-erlang-client/test/negative_test_util.erl0000644000000000000000000002060512305126066027501 0ustar rootroot%% The contents of this file are subject to the Mozilla Public License %% Version 1.1 (the "License"); you may not use this file except in %% compliance with the License. You may obtain a copy of the License at %% http://www.mozilla.org/MPL/ %% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the %% License for the specific language governing rights and limitations %% under the License. %% %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is GoPivotal, Inc. %% Copyright (c) 2007-2013 GoPivotal, Inc. All rights reserved. %% -module(negative_test_util). -include("amqp_client_internal.hrl"). -include_lib("eunit/include/eunit.hrl"). -compile(export_all). non_existent_exchange_test() -> {ok, Connection} = test_util:new_connection(), X = test_util:uuid(), RoutingKey = <<"a">>, Payload = <<"foobar">>, {ok, Channel} = amqp_connection:open_channel(Connection), {ok, OtherChannel} = amqp_connection:open_channel(Connection), amqp_channel:call(Channel, #'exchange.declare'{exchange = X}), %% Deliberately mix up the routingkey and exchange arguments Publish = #'basic.publish'{exchange = RoutingKey, routing_key = X}, amqp_channel:call(Channel, Publish, #amqp_msg{payload = Payload}), test_util:wait_for_death(Channel), %% Make sure Connection and OtherChannel still serve us and are not dead {ok, _} = amqp_connection:open_channel(Connection), #'exchange.declare_ok'{} = amqp_channel:call(OtherChannel, #'exchange.declare'{exchange = test_util:uuid()}), amqp_connection:close(Connection). bogus_rpc_test() -> {ok, Connection} = test_util:new_connection(), X = test_util:uuid(), Q = test_util:uuid(), R = test_util:uuid(), {ok, Channel} = amqp_connection:open_channel(Connection), amqp_channel:call(Channel, #'exchange.declare'{exchange = X}), %% Deliberately bind to a non-existent queue Bind = #'queue.bind'{exchange = X, queue = Q, routing_key = R}, try amqp_channel:call(Channel, Bind) of _ -> exit(expected_to_exit) catch exit:{{shutdown, {server_initiated_close, Code, _}},_} -> ?assertMatch(?NOT_FOUND, Code) end, test_util:wait_for_death(Channel), ?assertMatch(true, is_process_alive(Connection)), amqp_connection:close(Connection). hard_error_test() -> {ok, Connection} = test_util:new_connection(), {ok, Channel} = amqp_connection:open_channel(Connection), {ok, OtherChannel} = amqp_connection:open_channel(Connection), OtherChannelMonitor = erlang:monitor(process, OtherChannel), Qos = #'basic.qos'{global = true}, try amqp_channel:call(Channel, Qos) of _ -> exit(expected_to_exit) catch exit:{{shutdown, {connection_closing, {server_initiated_close, ?NOT_IMPLEMENTED, _}}}, _} -> ok end, receive {'DOWN', OtherChannelMonitor, process, OtherChannel, OtherExit} -> ?assertMatch({shutdown, {connection_closing, {server_initiated_close, ?NOT_IMPLEMENTED, _}}}, OtherExit) end, test_util:wait_for_death(Channel), test_util:wait_for_death(Connection). %% An error in a channel should result in the death of the entire connection. %% The death of the channel is caused by an error in generating the frames %% (writer dies) - only in the network case channel_writer_death_test() -> {ok, Connection} = test_util:new_connection(just_network), {ok, Channel} = amqp_connection:open_channel(Connection), Publish = #'basic.publish'{routing_key = <<>>, exchange = <<>>}, QoS = #'basic.qos'{prefetch_count = 0}, Message = #amqp_msg{props = <<>>, payload = <<>>}, amqp_channel:cast(Channel, Publish, Message), ?assertExit(_, amqp_channel:call(Channel, QoS)), test_util:wait_for_death(Channel), test_util:wait_for_death(Connection), ok. %% An error in the channel process should result in the death of the entire %% connection. The death of the channel is caused by making a call with an %% invalid message to the channel process channel_death_test() -> {ok, Connection} = test_util:new_connection(), {ok, Channel} = amqp_connection:open_channel(Connection), ?assertExit(_, amqp_channel:call(Channel, bogus_message)), test_util:wait_for_death(Channel), test_util:wait_for_death(Connection), ok. %% Attempting to send a shortstr longer than 255 bytes in a property field %% should fail - this only applies to the network case shortstr_overflow_property_test() -> {ok, Connection} = test_util:new_connection(just_network), {ok, Channel} = amqp_connection:open_channel(Connection), SentString = << <<"k">> || _ <- lists:seq(1, 340)>>, Q = test_util:uuid(), X = test_util:uuid(), Key = test_util:uuid(), Payload = <<"foobar">>, test_util:setup_exchange(Channel, Q, X, Key), Publish = #'basic.publish'{exchange = X, routing_key = Key}, PBasic = #'P_basic'{content_type = SentString}, AmqpMsg = #amqp_msg{payload = Payload, props = PBasic}, QoS = #'basic.qos'{prefetch_count = 0}, amqp_channel:cast(Channel, Publish, AmqpMsg), ?assertExit(_, amqp_channel:call(Channel, QoS)), test_util:wait_for_death(Channel), test_util:wait_for_death(Connection), ok. %% Attempting to send a shortstr longer than 255 bytes in a method's field %% should fail - this only applies to the network case shortstr_overflow_field_test() -> {ok, Connection} = test_util:new_connection(just_network), {ok, Channel} = amqp_connection:open_channel(Connection), SentString = << <<"k">> || _ <- lists:seq(1, 340)>>, Q = test_util:uuid(), X = test_util:uuid(), Key = test_util:uuid(), test_util:setup_exchange(Channel, Q, X, Key), ?assertExit(_, amqp_channel:call( Channel, #'basic.consume'{queue = Q, no_ack = true, consumer_tag = SentString})), test_util:wait_for_death(Channel), test_util:wait_for_death(Connection), ok. %% Simulates a #'connection.open'{} method received on non-zero channel. The %% connection is expected to send a '#connection.close{}' to the server with %% reply code command_invalid command_invalid_over_channel_test() -> {ok, Connection} = test_util:new_connection(), {ok, Channel} = amqp_connection:open_channel(Connection), MonitorRef = erlang:monitor(process, Connection), case amqp_connection:info(Connection, [type]) of [{type, direct}] -> Channel ! {send_command, #'connection.open'{}}; [{type, network}] -> gen_server:cast(Channel, {method, #'connection.open'{}, none, noflow}) end, assert_down_with_error(MonitorRef, command_invalid), ?assertNot(is_process_alive(Channel)), ok. %% Simulates a #'basic.ack'{} method received on channel zero. The connection %% is expected to send a '#connection.close{}' to the server with reply code %% command_invalid - this only applies to the network case command_invalid_over_channel0_test() -> {ok, Connection} = test_util:new_connection(just_network), gen_server:cast(Connection, {method, #'basic.ack'{}, none, noflow}), MonitorRef = erlang:monitor(process, Connection), assert_down_with_error(MonitorRef, command_invalid), ok. assert_down_with_error(MonitorRef, CodeAtom) -> receive {'DOWN', MonitorRef, process, _, Reason} -> {shutdown, {server_misbehaved, Code, _}} = Reason, ?assertMatch(CodeAtom, ?PROTOCOL:amqp_exception(Code)) after 2000 -> exit(did_not_die) end. non_existent_user_test() -> Params = [{username, test_util:uuid()}, {password, test_util:uuid()}], ?assertMatch({error, {auth_failure, _}}, test_util:new_connection(Params)). invalid_password_test() -> Params = [{username, <<"guest">>}, {password, test_util:uuid()}], ?assertMatch({error, {auth_failure, _}}, test_util:new_connection(Params)). non_existent_vhost_test() -> Params = [{virtual_host, test_util:uuid()}], ?assertMatch({error, access_refused}, test_util:new_connection(Params)). no_permission_test() -> Params = [{username, <<"test_user_no_perm">>}, {password, <<"test_user_no_perm">>}], ?assertMatch({error, access_refused}, test_util:new_connection(Params)). rabbitmq-server-3.2.4/plugins-src/rabbitmq-erlang-client/test/Makefile0000644000000000000000000000201712305126066024534 0ustar rootroot# The contents of this file are subject to the Mozilla Public License # Version 1.1 (the "License"); you may not use this file except in # compliance with the License. You may obtain a copy of the License at # http://www.mozilla.org/MPL/ # # Software distributed under the License is distributed on an "AS IS" # basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the # License for the specific language governing rights and limitations # under the License. # # The Original Code is RabbitMQ. # # The Initial Developer of the Original Code is GoPivotal, Inc. # Copyright (c) 2007-2013 GoPivotal, Inc. All rights reserved. # TEST_SOURCES=$(wildcard *.erl) TEST_TARGETS=$(patsubst %.erl, %.beam, $(TEST_SOURCES)) INCLUDES=$(wildcard ../$(INCLUDE_DIR)/*.hrl) DEPS_DIR=../deps ERLC_OPTS=-I ../$(INCLUDE_DIR) -o ./ -Wall -v +debug_info LIBS_PATH=ERL_LIBS=$(DEPS_DIR) all: compile compile: $(TEST_TARGETS) %.beam: %.erl $(DEPS_DIR)/$(COMMON_PACKAGE_DIR) $(INCLUDES) $(LIBS_PATH) erlc $(ERLC_OPTS) $< clean: rm -f *.beam rabbitmq-server-3.2.4/plugins-src/rabbitmq-erlang-client/test/test_util.erl0000644000000000000000000013553012305126066025623 0ustar rootroot%% The contents of this file are subject to the Mozilla Public License %% Version 1.1 (the "License"); you may not use this file except in %% compliance with the License. You may obtain a copy of the License at %% http://www.mozilla.org/MPL/ %% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the %% License for the specific language governing rights and limitations %% under the License. %% %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is GoPivotal, Inc. %% Copyright (c) 2011-2013 GoPivotal, Inc. All rights reserved. %% -module(test_util). -include_lib("eunit/include/eunit.hrl"). -include("amqp_client_internal.hrl"). -compile([export_all]). -define(TEST_REPEATS, 100). -record(publish, {q, x, routing_key, bind_key, payload, mandatory = false, immediate = false}). %% The latch constant defines how many processes are spawned in order %% to run certain functionality in parallel. It follows the standard %% countdown latch pattern. -define(Latch, 100). %% The wait constant defines how long a consumer waits before it %% unsubscribes -define(Wait, 200). %% AMQP URI parsing test amqp_uri_parse_test() -> %% From the spec (adapted) ?assertMatch({ok, #amqp_params_network{username = <<"user">>, password = <<"pass">>, host = "host", port = 10000, virtual_host = <<"vhost">>, heartbeat = 5}}, amqp_uri:parse( "amqp://user:pass@host:10000/vhost?heartbeat=5")), ?assertMatch({ok, #amqp_params_network{username = <<"usera">>, password = <<"apass">>, host = "hoast", port = 10000, virtual_host = <<"v/host">>}}, amqp_uri:parse( "aMQp://user%61:%61pass@ho%61st:10000/v%2fhost")), ?assertMatch({ok, #amqp_params_direct{}}, amqp_uri:parse("amqp://")), ?assertMatch({ok, #amqp_params_direct{username = <<"">>, virtual_host = <<"">>}}, amqp_uri:parse("amqp://:@/")), ?assertMatch({ok, #amqp_params_network{username = <<"">>, password = <<"">>, virtual_host = <<"">>, host = "host"}}, amqp_uri:parse("amqp://:@host/")), ?assertMatch({ok, #amqp_params_direct{username = <<"user">>}}, amqp_uri:parse("amqp://user@")), ?assertMatch({ok, #amqp_params_network{username = <<"user">>, password = <<"pass">>, host = "localhost"}}, amqp_uri:parse("amqp://user:pass@localhost")), ?assertMatch({ok, #amqp_params_network{host = "host", virtual_host = <<"/">>}}, amqp_uri:parse("amqp://host")), ?assertMatch({ok, #amqp_params_network{port = 10000, host = "localhost"}}, amqp_uri:parse("amqp://localhost:10000")), ?assertMatch({ok, #amqp_params_direct{virtual_host = <<"vhost">>}}, amqp_uri:parse("amqp:///vhost")), ?assertMatch({ok, #amqp_params_network{host = "host", virtual_host = <<"">>}}, amqp_uri:parse("amqp://host/")), ?assertMatch({ok, #amqp_params_network{host = "host", virtual_host = <<"/">>}}, amqp_uri:parse("amqp://host/%2f")), ?assertMatch({ok, #amqp_params_network{host = "::1"}}, amqp_uri:parse("amqp://[::1]")), %% Varous other cases ?assertMatch({ok, #amqp_params_network{host = "host", port = 100}}, amqp_uri:parse("amqp://host:100")), ?assertMatch({ok, #amqp_params_network{host = "::1", port = 100}}, amqp_uri:parse("amqp://[::1]:100")), ?assertMatch({ok, #amqp_params_network{host = "host", virtual_host = <<"blah">>}}, amqp_uri:parse("amqp://host/blah")), ?assertMatch({ok, #amqp_params_network{host = "host", port = 100, virtual_host = <<"blah">>}}, amqp_uri:parse("amqp://host:100/blah")), ?assertMatch({ok, #amqp_params_network{host = "::1", virtual_host = <<"blah">>}}, amqp_uri:parse("amqp://[::1]/blah")), ?assertMatch({ok, #amqp_params_network{host = "::1", port = 100, virtual_host = <<"blah">>}}, amqp_uri:parse("amqp://[::1]:100/blah")), ?assertMatch({ok, #amqp_params_network{username = <<"user">>, password = <<"pass">>, host = "host"}}, amqp_uri:parse("amqp://user:pass@host")), ?assertMatch({ok, #amqp_params_network{username = <<"user">>, password = <<"pass">>, port = 100}}, amqp_uri:parse("amqp://user:pass@host:100")), ?assertMatch({ok, #amqp_params_network{username = <<"user">>, password = <<"pass">>, host = "::1"}}, amqp_uri:parse("amqp://user:pass@[::1]")), ?assertMatch({ok, #amqp_params_network{username = <<"user">>, password = <<"pass">>, host = "::1", port = 100}}, amqp_uri:parse("amqp://user:pass@[::1]:100")), %% Various failure cases ?assertMatch({error, _}, amqp_uri:parse("http://www.rabbitmq.com")), ?assertMatch({error, _}, amqp_uri:parse("amqp://foo:bar:baz")), ?assertMatch({error, _}, amqp_uri:parse("amqp://foo[::1]")), ?assertMatch({error, _}, amqp_uri:parse("amqp://foo:[::1]")), ?assertMatch({error, _}, amqp_uri:parse("amqp://[::1]foo")), ?assertMatch({error, _}, amqp_uri:parse("amqp://foo:1000xyz")), ?assertMatch({error, _}, amqp_uri:parse("amqp://foo:1000000")), ?assertMatch({error, _}, amqp_uri:parse("amqp://foo/bar/baz")), ?assertMatch({error, _}, amqp_uri:parse("amqp://foo%1")), ?assertMatch({error, _}, amqp_uri:parse("amqp://foo%1x")), ?assertMatch({error, _}, amqp_uri:parse("amqp://foo%xy")), ok. %%-------------------------------------------------------------------- %% Destination Parsing Tests %%-------------------------------------------------------------------- route_destination_test() -> %% valid queue ?assertMatch({ok, {queue, "test"}}, parse_dest("/queue/test")), %% valid topic ?assertMatch({ok, {topic, "test"}}, parse_dest("/topic/test")), %% valid exchange ?assertMatch({ok, {exchange, {"test", undefined}}}, parse_dest("/exchange/test")), %% valid temp queue ?assertMatch({ok, {temp_queue, "test"}}, parse_dest("/temp-queue/test")), %% valid reply queue ?assertMatch({ok, {reply_queue, "test"}}, parse_dest("/reply-queue/test")), ?assertMatch({ok, {reply_queue, "test/2"}}, parse_dest("/reply-queue/test/2")), %% valid exchange with pattern ?assertMatch({ok, {exchange, {"test", "pattern"}}}, parse_dest("/exchange/test/pattern")), %% valid pre-declared queue ?assertMatch({ok, {amqqueue, "test"}}, parse_dest("/amq/queue/test")), %% queue without name ?assertMatch({error, {invalid_destination, queue, ""}}, parse_dest("/queue")), ?assertMatch({ok, {queue, undefined}}, parse_dest("/queue", true)), %% topic without name ?assertMatch({error, {invalid_destination, topic, ""}}, parse_dest("/topic")), %% exchange without name ?assertMatch({error, {invalid_destination, exchange, ""}}, parse_dest("/exchange")), %% exchange default name ?assertMatch({error, {invalid_destination, exchange, "//foo"}}, parse_dest("/exchange//foo")), %% amqqueue without name ?assertMatch({error, {invalid_destination, amqqueue, ""}}, parse_dest("/amq/queue")), %% queue without name with trailing slash ?assertMatch({error, {invalid_destination, queue, "/"}}, parse_dest("/queue/")), %% topic without name with trailing slash ?assertMatch({error, {invalid_destination, topic, "/"}}, parse_dest("/topic/")), %% exchange without name with trailing slash ?assertMatch({error, {invalid_destination, exchange, "/"}}, parse_dest("/exchange/")), %% queue with invalid name ?assertMatch({error, {invalid_destination, queue, "/foo/bar"}}, parse_dest("/queue/foo/bar")), %% topic with invalid name ?assertMatch({error, {invalid_destination, topic, "/foo/bar"}}, parse_dest("/topic/foo/bar")), %% exchange with invalid name ?assertMatch({error, {invalid_destination, exchange, "/foo/bar/baz"}}, parse_dest("/exchange/foo/bar/baz")), %% unknown destination ?assertMatch({error, {unknown_destination, "/blah/boo"}}, parse_dest("/blah/boo")), %% queue with escaped name ?assertMatch({ok, {queue, "te/st"}}, parse_dest("/queue/te%2Fst")), %% valid exchange with escaped name and pattern ?assertMatch({ok, {exchange, {"te/st", "pa/tt/ern"}}}, parse_dest("/exchange/te%2Fst/pa%2Ftt%2Fern")), ok. parse_dest(Destination, Params) -> rabbit_routing_util:parse_endpoint(Destination, Params). parse_dest(Destination) -> rabbit_routing_util:parse_endpoint(Destination). %%%% %% %% This is an example of how the client interaction should work %% %% {ok, Connection} = amqp_connection:start(network), %% {ok, Channel} = amqp_connection:open_channel(Connection), %% %%...do something useful %% amqp_channel:close(Channel), %% amqp_connection:close(Connection). %% lifecycle_test() -> {ok, Connection} = new_connection(), X = <<"x">>, {ok, Channel} = amqp_connection:open_channel(Connection), amqp_channel:call(Channel, #'exchange.declare'{exchange = X, type = <<"topic">>}), Parent = self(), [spawn(fun () -> queue_exchange_binding(Channel, X, Parent, Tag) end) || Tag <- lists:seq(1, ?Latch)], latch_loop(), amqp_channel:call(Channel, #'exchange.delete'{exchange = X}), teardown(Connection, Channel), ok. direct_no_password_test() -> {ok, Connection} = new_connection(just_direct, [{password, none}]), amqp_connection:close(Connection), wait_for_death(Connection). queue_exchange_binding(Channel, X, Parent, Tag) -> receive nothing -> ok after (?Latch - Tag rem 7) * 10 -> ok end, Q = <<"a.b.c", Tag:32>>, Binding = <<"a.b.c.*">>, #'queue.declare_ok'{queue = Q1} = amqp_channel:call(Channel, #'queue.declare'{queue = Q}), ?assertMatch(Q, Q1), Route = #'queue.bind'{queue = Q, exchange = X, routing_key = Binding}, amqp_channel:call(Channel, Route), amqp_channel:call(Channel, #'queue.delete'{queue = Q}), Parent ! finished. nowait_exchange_declare_test() -> {ok, Connection} = new_connection(), X = <<"x">>, {ok, Channel} = amqp_connection:open_channel(Connection), ?assertEqual( ok, amqp_channel:call(Channel, #'exchange.declare'{exchange = X, type = <<"topic">>, nowait = true})), teardown(Connection, Channel). channel_lifecycle_test() -> {ok, Connection} = new_connection(), {ok, Channel} = amqp_connection:open_channel(Connection), amqp_channel:close(Channel), {ok, Channel2} = amqp_connection:open_channel(Connection), teardown(Connection, Channel2), ok. abstract_method_serialization_test(BeforeFun, MultiOpFun, AfterFun) -> {ok, Connection} = new_connection(), {ok, Channel} = amqp_connection:open_channel(Connection), X = uuid(), Payload = list_to_binary(["x" || _ <- lists:seq(1, 1000)]), OpsPerProcess = 20, #'exchange.declare_ok'{} = amqp_channel:call(Channel, #'exchange.declare'{exchange = X, type = <<"topic">>}), BeforeRet = BeforeFun(Channel, X), Parent = self(), [spawn(fun () -> Ret = [MultiOpFun(Channel, X, Payload, BeforeRet) || _ <- lists:seq(1, OpsPerProcess)], Parent ! {finished, Ret} end) || _ <- lists:seq(1, ?Latch)], MultiOpRet = latch_loop(), AfterFun(Channel, X, Payload, BeforeRet, MultiOpRet), teardown(Connection, Channel). %% This is designed to exercize the internal queuing mechanism %% to ensure that sync methods are properly serialized sync_method_serialization_test() -> abstract_method_serialization_test( fun (_, _) -> ok end, fun (Channel, _, _, _) -> Q = uuid(), #'queue.declare_ok'{queue = Q1} = amqp_channel:call(Channel, #'queue.declare'{queue = Q}), ?assertMatch(Q, Q1) end, fun (_, _, _, _, _) -> ok end). %% This is designed to exercize the internal queuing mechanism %% to ensure that sending async methods and then a sync method is serialized %% properly async_sync_method_serialization_test() -> abstract_method_serialization_test( fun (Channel, _X) -> #'queue.declare_ok'{queue = Q} = amqp_channel:call(Channel, #'queue.declare'{}), Q end, fun (Channel, X, Payload, _) -> %% The async methods ok = amqp_channel:call(Channel, #'basic.publish'{exchange = X, routing_key = <<"a">>}, #amqp_msg{payload = Payload}) end, fun (Channel, X, _, Q, _) -> %% The sync method #'queue.bind_ok'{} = amqp_channel:call(Channel, #'queue.bind'{exchange = X, queue = Q, routing_key = <<"a">>}), %% No message should have been routed #'queue.declare_ok'{message_count = 0} = amqp_channel:call(Channel, #'queue.declare'{queue = Q, passive = true}) end). %% This is designed to exercize the internal queuing mechanism %% to ensure that sending sync methods and then an async method is serialized %% properly sync_async_method_serialization_test() -> abstract_method_serialization_test( fun (_, _) -> ok end, fun (Channel, X, _Payload, _) -> Q = uuid(), %% The sync methods (called with cast to resume immediately; %% the order should still be preserved) amqp_channel:cast(Channel, #'queue.declare'{queue = Q}), amqp_channel:cast(Channel, #'queue.bind'{exchange = X, queue = Q, routing_key= <<"a">>}), Q end, fun (Channel, X, Payload, _, MultiOpRet) -> #'confirm.select_ok'{} = amqp_channel:call( Channel, #'confirm.select'{}), ok = amqp_channel:call(Channel, #'basic.publish'{exchange = X, routing_key = <<"a">>}, #amqp_msg{payload = Payload}), %% All queues must have gotten this message true = amqp_channel:wait_for_confirms(Channel), lists:foreach( fun (Q) -> #'queue.purge_ok'{message_count = 1} = amqp_channel:call( Channel, #'queue.purge'{queue = Q}) end, lists:flatten(MultiOpRet)) end). queue_unbind_test() -> {ok, Connection} = new_connection(), X = <<"eggs">>, Q = <<"foobar">>, Key = <<"quay">>, Payload = <<"foobar">>, {ok, Channel} = amqp_connection:open_channel(Connection), amqp_channel:call(Channel, #'exchange.declare'{exchange = X}), amqp_channel:call(Channel, #'queue.declare'{queue = Q}), Bind = #'queue.bind'{queue = Q, exchange = X, routing_key = Key}, amqp_channel:call(Channel, Bind), Publish = #'basic.publish'{exchange = X, routing_key = Key}, amqp_channel:call(Channel, Publish, Msg = #amqp_msg{payload = Payload}), get_and_assert_equals(Channel, Q, Payload), Unbind = #'queue.unbind'{queue = Q, exchange = X, routing_key = Key}, amqp_channel:call(Channel, Unbind), amqp_channel:call(Channel, Publish, Msg), get_and_assert_empty(Channel, Q), teardown(Connection, Channel). get_and_assert_empty(Channel, Q) -> #'basic.get_empty'{} = amqp_channel:call(Channel, #'basic.get'{queue = Q, no_ack = true}). get_and_assert_equals(Channel, Q, Payload) -> get_and_assert_equals(Channel, Q, Payload, true). get_and_assert_equals(Channel, Q, Payload, NoAck) -> {GetOk = #'basic.get_ok'{}, Content} = amqp_channel:call(Channel, #'basic.get'{queue = Q, no_ack = NoAck}), #amqp_msg{payload = Payload2} = Content, ?assertMatch(Payload, Payload2), GetOk. basic_get_test() -> basic_get_test1(new_connection()). basic_get_ipv6_test() -> basic_get_test1(new_connection(just_network, [{host, "::1"}])). basic_get_test1({ok, Connection}) -> {ok, Channel} = amqp_connection:open_channel(Connection), {ok, Q} = setup_publish(Channel), get_and_assert_equals(Channel, Q, <<"foobar">>), get_and_assert_empty(Channel, Q), teardown(Connection, Channel). basic_return_test() -> {ok, Connection} = new_connection(), X = uuid(), Q = uuid(), Key = uuid(), Payload = <<"qwerty">>, {ok, Channel} = amqp_connection:open_channel(Connection), amqp_channel:register_return_handler(Channel, self()), amqp_channel:call(Channel, #'exchange.declare'{exchange = X}), amqp_channel:call(Channel, #'queue.declare'{queue = Q}), Publish = #'basic.publish'{exchange = X, routing_key = Key, mandatory = true}, amqp_channel:call(Channel, Publish, #amqp_msg{payload = Payload}), receive {BasicReturn = #'basic.return'{}, Content} -> #'basic.return'{reply_code = ReplyCode, exchange = X} = BasicReturn, ?assertMatch(?NO_ROUTE, ReplyCode), #amqp_msg{payload = Payload2} = Content, ?assertMatch(Payload, Payload2); WhatsThis1 -> exit({bad_message, WhatsThis1}) after 2000 -> exit(no_return_received) end, amqp_channel:unregister_return_handler(Channel), Publish = #'basic.publish'{exchange = X, routing_key = Key, mandatory = true}, amqp_channel:call(Channel, Publish, #amqp_msg{payload = Payload}), ok = receive {_BasicReturn = #'basic.return'{}, _Content} -> unexpected_return; WhatsThis2 -> exit({bad_message, WhatsThis2}) after 2000 -> ok end, teardown(Connection, Channel). channel_repeat_open_close_test() -> {ok, Connection} = new_connection(), lists:foreach( fun(_) -> {ok, Ch} = amqp_connection:open_channel(Connection), ok = amqp_channel:close(Ch) end, lists:seq(1, 50)), amqp_connection:close(Connection), wait_for_death(Connection). channel_multi_open_close_test() -> {ok, Connection} = new_connection(), [spawn_link( fun() -> try amqp_connection:open_channel(Connection) of {ok, Ch} -> try amqp_channel:close(Ch) of ok -> ok; closing -> ok catch exit:{noproc, _} -> ok; exit:{normal, _} -> ok end; closing -> ok catch exit:{noproc, _} -> ok; exit:{normal, _} -> ok end end) || _ <- lists:seq(1, 50)], erlang:yield(), amqp_connection:close(Connection), wait_for_death(Connection). basic_ack_test() -> {ok, Connection} = new_connection(), {ok, Channel} = amqp_connection:open_channel(Connection), {ok, Q} = setup_publish(Channel), {#'basic.get_ok'{delivery_tag = Tag}, _} = amqp_channel:call(Channel, #'basic.get'{queue = Q, no_ack = false}), amqp_channel:cast(Channel, #'basic.ack'{delivery_tag = Tag}), teardown(Connection, Channel). basic_ack_call_test() -> {ok, Connection} = new_connection(), {ok, Channel} = amqp_connection:open_channel(Connection), {ok, Q} = setup_publish(Channel), {#'basic.get_ok'{delivery_tag = Tag}, _} = amqp_channel:call(Channel, #'basic.get'{queue = Q, no_ack = false}), amqp_channel:call(Channel, #'basic.ack'{delivery_tag = Tag}), teardown(Connection, Channel). basic_consume_test() -> {ok, Connection} = new_connection(), {ok, Channel} = amqp_connection:open_channel(Connection), X = uuid(), amqp_channel:call(Channel, #'exchange.declare'{exchange = X}), RoutingKey = uuid(), Parent = self(), [spawn_link(fun () -> consume_loop(Channel, X, RoutingKey, Parent, <>) end) || Tag <- lists:seq(1, ?Latch)], timer:sleep(?Latch * 20), Publish = #'basic.publish'{exchange = X, routing_key = RoutingKey}, amqp_channel:call(Channel, Publish, #amqp_msg{payload = <<"foobar">>}), latch_loop(), teardown(Connection, Channel). consume_loop(Channel, X, RoutingKey, Parent, Tag) -> #'queue.declare_ok'{queue = Q} = amqp_channel:call(Channel, #'queue.declare'{}), #'queue.bind_ok'{} = amqp_channel:call(Channel, #'queue.bind'{queue = Q, exchange = X, routing_key = RoutingKey}), #'basic.consume_ok'{} = amqp_channel:call(Channel, #'basic.consume'{queue = Q, consumer_tag = Tag}), receive #'basic.consume_ok'{consumer_tag = Tag} -> ok end, receive {#'basic.deliver'{}, _} -> ok end, #'basic.cancel_ok'{} = amqp_channel:call(Channel, #'basic.cancel'{consumer_tag = Tag}), receive #'basic.cancel_ok'{consumer_tag = Tag} -> ok end, Parent ! finished. consume_notification_test() -> {ok, Connection} = new_connection(), {ok, Channel} = amqp_connection:open_channel(Connection), Q = uuid(), #'queue.declare_ok'{} = amqp_channel:call(Channel, #'queue.declare'{queue = Q}), #'basic.consume_ok'{consumer_tag = CTag} = ConsumeOk = amqp_channel:call(Channel, #'basic.consume'{queue = Q}), receive ConsumeOk -> ok end, #'queue.delete_ok'{} = amqp_channel:call(Channel, #'queue.delete'{queue = Q}), receive #'basic.cancel'{consumer_tag = CTag} -> ok end, amqp_channel:close(Channel), ok. basic_recover_test() -> {ok, Connection} = new_connection(), {ok, Channel} = amqp_connection:open_channel( Connection, {amqp_direct_consumer, [self()]}), #'queue.declare_ok'{queue = Q} = amqp_channel:call(Channel, #'queue.declare'{}), #'basic.consume_ok'{consumer_tag = Tag} = amqp_channel:call(Channel, #'basic.consume'{queue = Q}), receive #'basic.consume_ok'{consumer_tag = Tag} -> ok end, Publish = #'basic.publish'{exchange = <<>>, routing_key = Q}, amqp_channel:call(Channel, Publish, #amqp_msg{payload = <<"foobar">>}), receive {#'basic.deliver'{consumer_tag = Tag}, _} -> %% no_ack set to false, but don't send ack ok end, BasicRecover = #'basic.recover'{requeue = true}, amqp_channel:cast(Channel, BasicRecover), receive {#'basic.deliver'{consumer_tag = Tag, delivery_tag = DeliveryTag2}, _} -> amqp_channel:cast(Channel, #'basic.ack'{delivery_tag = DeliveryTag2}) end, teardown(Connection, Channel). simultaneous_close_test() -> {ok, Connection} = new_connection(), ChannelNumber = 5, {ok, Channel1} = amqp_connection:open_channel(Connection, ChannelNumber), %% Publish to non-existent exchange and immediately close channel amqp_channel:cast(Channel1, #'basic.publish'{exchange = uuid(), routing_key = <<"a">>}, #amqp_msg{payload = <<"foobar">>}), try amqp_channel:close(Channel1) of ok -> wait_for_death(Channel1); closing -> wait_for_death(Channel1) catch exit:{noproc, _} -> ok; exit:{{shutdown, {server_initiated_close, ?NOT_FOUND, _}}, _} -> ok end, %% Channel2 (opened with the exact same number as Channel1) %% should not receive a close_ok (which is intended for Channel1) {ok, Channel2} = amqp_connection:open_channel(Connection, ChannelNumber), %% Make sure Channel2 functions normally #'exchange.declare_ok'{} = amqp_channel:call(Channel2, #'exchange.declare'{exchange = uuid()}), teardown(Connection, Channel2). channel_tune_negotiation_test() -> {ok, Connection} = new_connection([{channel_max, 10}]), amqp_connection:close(Connection). basic_qos_test() -> [NoQos, Qos] = [basic_qos_test(Prefetch) || Prefetch <- [0,1]], ExpectedRatio = (1+1) / (1+50/5), FudgeFactor = 2, %% account for timing variations ?assertMatch(true, Qos / NoQos < ExpectedRatio * FudgeFactor). basic_qos_test(Prefetch) -> {ok, Connection} = new_connection(), Messages = 100, Workers = [5, 50], Parent = self(), {ok, Chan} = amqp_connection:open_channel(Connection), #'queue.declare_ok'{queue = Q} = amqp_channel:call(Chan, #'queue.declare'{}), Kids = [spawn( fun() -> {ok, Channel} = amqp_connection:open_channel(Connection), amqp_channel:call(Channel, #'basic.qos'{prefetch_count = Prefetch}), amqp_channel:call(Channel, #'basic.consume'{queue = Q}), Parent ! finished, sleeping_consumer(Channel, Sleep, Parent) end) || Sleep <- Workers], latch_loop(length(Kids)), spawn(fun() -> {ok, Channel} = amqp_connection:open_channel(Connection), producer_loop(Channel, Q, Messages) end), {Res, _} = timer:tc(erlang, apply, [fun latch_loop/1, [Messages]]), [Kid ! stop || Kid <- Kids], latch_loop(length(Kids)), teardown(Connection, Chan), Res. sleeping_consumer(Channel, Sleep, Parent) -> receive stop -> do_stop(Channel, Parent); #'basic.consume_ok'{} -> sleeping_consumer(Channel, Sleep, Parent); #'basic.cancel_ok'{} -> exit(unexpected_cancel_ok); {#'basic.deliver'{delivery_tag = DeliveryTag}, _Content} -> Parent ! finished, receive stop -> do_stop(Channel, Parent) after Sleep -> ok end, amqp_channel:cast(Channel, #'basic.ack'{delivery_tag = DeliveryTag}), sleeping_consumer(Channel, Sleep, Parent) end. do_stop(Channel, Parent) -> Parent ! finished, amqp_channel:close(Channel), wait_for_death(Channel), exit(normal). producer_loop(Channel, _RoutingKey, 0) -> amqp_channel:close(Channel), wait_for_death(Channel), ok; producer_loop(Channel, RoutingKey, N) -> Publish = #'basic.publish'{exchange = <<>>, routing_key = RoutingKey}, amqp_channel:call(Channel, Publish, #amqp_msg{payload = <<>>}), producer_loop(Channel, RoutingKey, N - 1). confirm_test() -> {ok, Connection} = new_connection(), {ok, Channel} = amqp_connection:open_channel(Connection), #'confirm.select_ok'{} = amqp_channel:call(Channel, #'confirm.select'{}), amqp_channel:register_confirm_handler(Channel, self()), {ok, Q} = setup_publish(Channel), {#'basic.get_ok'{}, _} = amqp_channel:call(Channel, #'basic.get'{queue = Q, no_ack = false}), ok = receive #'basic.ack'{} -> ok; #'basic.nack'{} -> fail after 2000 -> exit(did_not_receive_pub_ack) end, teardown(Connection, Channel). confirm_barrier_test() -> {ok, Connection} = new_connection(), {ok, Channel} = amqp_connection:open_channel(Connection), #'confirm.select_ok'{} = amqp_channel:call(Channel, #'confirm.select'{}), [amqp_channel:call(Channel, #'basic.publish'{routing_key = <<"whoosh">>}, #amqp_msg{payload = <<"foo">>}) || _ <- lists:seq(1, 1000)], %% Hopefully enough to get a multi-ack true = amqp_channel:wait_for_confirms(Channel), teardown(Connection, Channel). confirm_select_before_wait_test() -> {ok, Connection} = new_connection(), {ok, Channel} = amqp_connection:open_channel(Connection), try amqp_channel:wait_for_confirms(Channel) of _ -> exit(success_despite_lack_of_confirm_mode) catch not_in_confirm_mode -> ok end, teardown(Connection, Channel). confirm_barrier_timeout_test() -> {ok, Connection} = new_connection(), {ok, Channel} = amqp_connection:open_channel(Connection), #'confirm.select_ok'{} = amqp_channel:call(Channel, #'confirm.select'{}), [amqp_channel:call(Channel, #'basic.publish'{routing_key = <<"whoosh">>}, #amqp_msg{payload = <<"foo">>}) || _ <- lists:seq(1, 1000)], case amqp_channel:wait_for_confirms(Channel, 0) of true -> ok; timeout -> ok end, teardown(Connection, Channel). confirm_barrier_die_timeout_test() -> {ok, Connection} = new_connection(), {ok, Channel} = amqp_connection:open_channel(Connection), #'confirm.select_ok'{} = amqp_channel:call(Channel, #'confirm.select'{}), [amqp_channel:call(Channel, #'basic.publish'{routing_key = <<"whoosh">>}, #amqp_msg{payload = <<"foo">>}) || _ <- lists:seq(1, 1000)], try amqp_channel:wait_for_confirms_or_die(Channel, 0) of true -> ok catch exit:timeout -> ok end, amqp_connection:close(Connection), wait_for_death(Connection). default_consumer_test() -> {ok, Connection} = new_connection(), {ok, Channel} = amqp_connection:open_channel(Connection), amqp_selective_consumer:register_default_consumer(Channel, self()), #'queue.declare_ok'{queue = Q} = amqp_channel:call(Channel, #'queue.declare'{}), Pid = spawn(fun () -> receive after 10000 -> ok end end), #'basic.consume_ok'{} = amqp_channel:subscribe(Channel, #'basic.consume'{queue = Q}, Pid), erlang:monitor(process, Pid), exit(Pid, shutdown), receive {'DOWN', _, process, _, _} -> io:format("little consumer died out~n") end, Payload = <<"for the default consumer">>, amqp_channel:call(Channel, #'basic.publish'{exchange = <<>>, routing_key = Q}, #amqp_msg{payload = Payload}), receive {#'basic.deliver'{}, #'amqp_msg'{payload = Payload}} -> ok after 1000 -> exit('default_consumer_didnt_work') end, teardown(Connection, Channel). subscribe_nowait_test() -> {ok, Conn} = new_connection(), {ok, Ch} = amqp_connection:open_channel(Conn), {ok, Q} = setup_publish(Ch), CTag = uuid(), amqp_selective_consumer:register_default_consumer(Ch, self()), ok = amqp_channel:call(Ch, #'basic.consume'{queue = Q, consumer_tag = CTag, nowait = true}), ok = amqp_channel:call(Ch, #'basic.cancel' {consumer_tag = CTag, nowait = true}), ok = amqp_channel:call(Ch, #'basic.consume'{queue = Q, consumer_tag = CTag, nowait = true}), receive #'basic.consume_ok'{} -> exit(unexpected_consume_ok); {#'basic.deliver'{delivery_tag = DTag}, _Content} -> amqp_channel:cast(Ch, #'basic.ack'{delivery_tag = DTag}) end, teardown(Conn, Ch). basic_nack_test() -> {ok, Connection} = new_connection(), {ok, Channel} = amqp_connection:open_channel(Connection), #'queue.declare_ok'{queue = Q} = amqp_channel:call(Channel, #'queue.declare'{}), Payload = <<"m1">>, amqp_channel:call(Channel, #'basic.publish'{exchange = <<>>, routing_key = Q}, #amqp_msg{payload = Payload}), #'basic.get_ok'{delivery_tag = Tag} = get_and_assert_equals(Channel, Q, Payload, false), amqp_channel:call(Channel, #'basic.nack'{delivery_tag = Tag, multiple = false, requeue = false}), get_and_assert_empty(Channel, Q), teardown(Connection, Channel). large_content_test() -> {ok, Connection} = new_connection(), {ok, Channel} = amqp_connection:open_channel(Connection), #'queue.declare_ok'{queue = Q} = amqp_channel:call(Channel, #'queue.declare'{}), {A1,A2,A3} = now(), random:seed(A1, A2, A3), F = list_to_binary([random:uniform(256)-1 || _ <- lists:seq(1, 1000)]), Payload = list_to_binary([[F || _ <- lists:seq(1, 1000)]]), Publish = #'basic.publish'{exchange = <<>>, routing_key = Q}, amqp_channel:call(Channel, Publish, #amqp_msg{payload = Payload}), get_and_assert_equals(Channel, Q, Payload), teardown(Connection, Channel). %% ---------------------------------------------------------------------------- %% Test for the network client %% Sends a bunch of messages and immediatly closes the connection without %% closing the channel. Then gets the messages back from the queue and expects %% all of them to have been sent. pub_and_close_test() -> {ok, Connection1} = new_connection(just_network), X = uuid(), Q = uuid(), Key = uuid(), Payload = <<"eggs">>, NMessages = 50000, {ok, Channel1} = amqp_connection:open_channel(Connection1), amqp_channel:call(Channel1, #'exchange.declare'{exchange = X}), amqp_channel:call(Channel1, #'queue.declare'{queue = Q}), Route = #'queue.bind'{queue = Q, exchange = X, routing_key = Key}, amqp_channel:call(Channel1, Route), %% Send messages pc_producer_loop(Channel1, X, Key, Payload, NMessages), %% Close connection without closing channels amqp_connection:close(Connection1), %% Get sent messages back and count them {ok, Connection2} = new_connection(just_network), {ok, Channel2} = amqp_connection:open_channel( Connection2, {amqp_direct_consumer, [self()]}), amqp_channel:call(Channel2, #'basic.consume'{queue = Q, no_ack = true}), receive #'basic.consume_ok'{} -> ok end, ?assert(pc_consumer_loop(Channel2, Payload, 0) == NMessages), %% Make sure queue is empty #'queue.declare_ok'{queue = Q, message_count = NRemaining} = amqp_channel:call(Channel2, #'queue.declare'{queue = Q}), ?assert(NRemaining == 0), teardown(Connection2, Channel2), ok. pc_producer_loop(_, _, _, _, 0) -> ok; pc_producer_loop(Channel, X, Key, Payload, NRemaining) -> Publish = #'basic.publish'{exchange = X, routing_key = Key}, ok = amqp_channel:call(Channel, Publish, #amqp_msg{payload = Payload}), pc_producer_loop(Channel, X, Key, Payload, NRemaining - 1). pc_consumer_loop(Channel, Payload, NReceived) -> receive {#'basic.deliver'{}, #amqp_msg{payload = DeliveredPayload}} -> case DeliveredPayload of Payload -> pc_consumer_loop(Channel, Payload, NReceived + 1); _ -> exit(received_unexpected_content) end after 1000 -> NReceived end. %%--------------------------------------------------------------------------- %% This tests whether RPC over AMQP produces the same result as invoking the %% same argument against the same underlying gen_server instance. rpc_test() -> {ok, Connection} = new_connection(), Q = uuid(), Fun = fun(X) -> X + 1 end, RPCHandler = fun(X) -> term_to_binary(Fun(binary_to_term(X))) end, Server = amqp_rpc_server:start(Connection, Q, RPCHandler), Client = amqp_rpc_client:start(Connection, Q), Input = 1, Reply = amqp_rpc_client:call(Client, term_to_binary(Input)), Expected = Fun(Input), DecodedReply = binary_to_term(Reply), ?assertMatch(Expected, DecodedReply), amqp_rpc_client:stop(Client), amqp_rpc_server:stop(Server), amqp_connection:close(Connection), wait_for_death(Connection), ok. %% This tests if the RPC continues to generate valid correlation ids %% over a series of requests. rpc_client_test() -> {ok, Connection} = new_connection(), {ok, Channel} = amqp_connection:open_channel(Connection), Q = uuid(), Latch = 255, % enough requests to tickle bad correlation ids %% Start a server to return correlation ids to the client. Server = spawn_link(fun() -> rpc_correlation_server(Channel, Q) end), %% Generate a series of RPC requests on the same client. Client = amqp_rpc_client:start(Connection, Q), Parent = self(), [spawn(fun() -> Reply = amqp_rpc_client:call(Client, <<>>), Parent ! {finished, Reply} end) || _ <- lists:seq(1, Latch)], %% Verify that the correlation ids are valid UTF-8 strings. CorrelationIds = latch_loop(Latch), [?assertMatch(<<_/binary>>, DecodedId) || DecodedId <- [unicode:characters_to_binary(Id, utf8) || Id <- CorrelationIds]], %% Cleanup. Server ! stop, amqp_rpc_client:stop(Client), teardown(Connection, Channel), ok. %% Consumer of RPC requests that replies with the CorrelationId. rpc_correlation_server(Channel, Q) -> amqp_channel:register_return_handler(Channel, self()), amqp_channel:call(Channel, #'queue.declare'{queue = Q}), amqp_channel:call(Channel, #'basic.consume'{queue = Q}), rpc_client_consume_loop(Channel), amqp_channel:unregister_return_handler(Channel). rpc_client_consume_loop(Channel) -> receive stop -> ok; {#'basic.deliver'{delivery_tag = DeliveryTag}, #amqp_msg{props = Props}} -> #'P_basic'{correlation_id = CorrelationId, reply_to = Q} = Props, Properties = #'P_basic'{correlation_id = CorrelationId}, Publish = #'basic.publish'{exchange = <<>>, routing_key = Q, mandatory = true}, amqp_channel:call( Channel, Publish, #amqp_msg{props = Properties, payload = CorrelationId}), amqp_channel:call( Channel, #'basic.ack'{delivery_tag = DeliveryTag}), rpc_client_consume_loop(Channel); _ -> rpc_client_consume_loop(Channel) after 3000 -> exit(no_request_received) end. %%--------------------------------------------------------------------------- %% connection.blocked, connection.unblocked connection_blocked_network_test() -> {ok, Connection} = new_connection(just_network), X = <<"amq.direct">>, K = Payload = <<"x">>, clear_resource_alarm(memory), timer:sleep(1000), {ok, Channel} = amqp_connection:open_channel(Connection), Parent = self(), Child = spawn_link( fun() -> receive #'connection.blocked'{} -> ok end, clear_resource_alarm(memory), receive #'connection.unblocked'{} -> ok end, Parent ! ok end), amqp_connection:register_blocked_handler(Connection, Child), set_resource_alarm(memory), Publish = #'basic.publish'{exchange = X, routing_key = K}, amqp_channel:call(Channel, Publish, #amqp_msg{payload = Payload}), timer:sleep(1000), receive ok -> clear_resource_alarm(memory), clear_resource_alarm(disk), ok after 10000 -> clear_resource_alarm(memory), clear_resource_alarm(disk), exit(did_not_receive_connection_blocked) end. %%--------------------------------------------------------------------------- setup_publish(Channel) -> Publish = #publish{routing_key = <<"a.b.c.d">>, q = uuid(), x = uuid(), bind_key = <<"a.b.c.*">>, payload = <<"foobar">>}, setup_publish(Channel, Publish). setup_publish(Channel, #publish{routing_key = RoutingKey, q = Q, x = X, bind_key = BindKey, payload = Payload}) -> ok = setup_exchange(Channel, Q, X, BindKey), Publish = #'basic.publish'{exchange = X, routing_key = RoutingKey}, ok = amqp_channel:call(Channel, Publish, #amqp_msg{payload = Payload}), {ok, Q}. teardown(Connection, Channel) -> amqp_channel:close(Channel), wait_for_death(Channel), amqp_connection:close(Connection), wait_for_death(Connection). teardown_test() -> {ok, Connection} = new_connection(), {ok, Channel} = amqp_connection:open_channel(Connection), ?assertMatch(true, is_process_alive(Channel)), ?assertMatch(true, is_process_alive(Connection)), teardown(Connection, Channel), ?assertMatch(false, is_process_alive(Channel)), ?assertMatch(false, is_process_alive(Connection)). setup_exchange(Channel, Q, X, Binding) -> amqp_channel:call(Channel, #'exchange.declare'{exchange = X, type = <<"topic">>}), amqp_channel:call(Channel, #'queue.declare'{queue = Q}), Route = #'queue.bind'{queue = Q, exchange = X, routing_key = Binding}, amqp_channel:call(Channel, Route), ok. wait_for_death(Pid) -> Ref = erlang:monitor(process, Pid), receive {'DOWN', Ref, process, Pid, _Reason} -> ok after 1000 -> exit({timed_out_waiting_for_process_death, Pid}) end. latch_loop() -> latch_loop(?Latch, []). latch_loop(Latch) -> latch_loop(Latch, []). latch_loop(0, Acc) -> Acc; latch_loop(Latch, Acc) -> receive finished -> latch_loop(Latch - 1, Acc); {finished, Ret} -> latch_loop(Latch - 1, [Ret | Acc]) after ?Latch * ?Wait -> exit(waited_too_long) end. uuid() -> {A, B, C} = now(), <>. new_connection() -> new_connection(both, []). new_connection(AllowedConnectionTypes) when is_atom(AllowedConnectionTypes) -> new_connection(AllowedConnectionTypes, []); new_connection(Params) when is_list(Params) -> new_connection(both, Params). new_connection(AllowedConnectionTypes, Params) -> Params1 = case {AllowedConnectionTypes, os:getenv("AMQP_CLIENT_TEST_CONNECTION_TYPE")} of {just_direct, "network"} -> exit(normal); {just_direct, "network_ssl"} -> exit(normal); {just_network, "direct"} -> exit(normal); {_, "network"} -> make_network_params(Params); {_, "network_ssl"} -> {ok, [[CertsDir]]} = init:get_argument(erlang_client_ssl_dir), make_network_params( [{ssl_options, [{cacertfile, CertsDir ++ "/testca/cacert.pem"}, {certfile, CertsDir ++ "/client/cert.pem"}, {keyfile, CertsDir ++ "/client/key.pem"}, {verify, verify_peer}, {fail_if_no_peer_cert, true}]}] ++ Params); {_, "direct"} -> make_direct_params([{node, rabbit_nodes:make(rabbit)}] ++ Params) end, amqp_connection:start(Params1). %% Note: not all amqp_params_network fields supported. make_network_params(Props) -> Pgv = fun (Key, Default) -> proplists:get_value(Key, Props, Default) end, #amqp_params_network{username = Pgv(username, <<"guest">>), password = Pgv(password, <<"guest">>), virtual_host = Pgv(virtual_host, <<"/">>), channel_max = Pgv(channel_max, 0), ssl_options = Pgv(ssl_options, none), host = Pgv(host, "localhost")}. %% Note: not all amqp_params_direct fields supported. make_direct_params(Props) -> Pgv = fun (Key, Default) -> proplists:get_value(Key, Props, Default) end, #amqp_params_direct{username = Pgv(username, <<"guest">>), password = Pgv(password, <<"guest">>), virtual_host = Pgv(virtual_host, <<"/">>), node = Pgv(node, node())}. set_resource_alarm(memory) -> os:cmd("cd ../rabbitmq-test; make set-resource-alarm SOURCE=memory"); set_resource_alarm(disk) -> os:cmd("cd ../rabbitmq-test; make set-resource-alarm SOURCE=disk"). clear_resource_alarm(memory) -> os:cmd("cd ../rabbitmq-test; make clear-resource-alarm SOURCE=memory"); clear_resource_alarm(disk) -> os:cmd("cd ../rabbitmq-test; make clear-resource-alarm SOURCE=disk"). rabbitmq-server-3.2.4/plugins-src/rabbitmq-erlang-client/test/amqp_dbg.erl0000644000000000000000000000677312305126066025367 0ustar rootroot%% The contents of this file are subject to the Mozilla Public License %% Version 1.1 (the "License"); you may not use this file except in %% compliance with the License. You may obtain a copy of the License at %% http://www.mozilla.org/MPL/ %% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the %% License for the specific language governing rights and limitations %% under the License. %% %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is GoPivotal, Inc. %% Copyright (c) 2007-2013 GoPivotal, Inc. All rights reserved. %% -module(amqp_dbg). -include_lib("stdlib/include/ms_transform.hrl"). -export([tracer/0, all/0, c_all/0]). -export([supervision/0, c_supervision/0, connection_lifecycle/0, c_connection_lifecycle/0, channels_manager_lifecycle/0, c_channels_manager_lifecycle/0, channel_lifecycle/0, c_channel_lifecycle/0, methods/0, c_methods/0]). tracer() -> Ret = dbg:tracer(), {ok, _} = dbg:p(all, c), Ret. all() -> tpl_list(all_args()). c_all() -> ctpl_list(all_args()). supervision() -> tpl_list(sup_args()). c_supervision() -> ctpl_list(sup_args()). connection_lifecycle() -> tpl_list(cl_args()). c_connection_lifecycle() -> ctpl_list(cl_args()). channels_manager_lifecycle() -> tpl_list(cml_args()). c_channels_manager_lifecycle() -> ctpl_list(cml_args()). channel_lifecycle() -> tpl_list(cl_args()). c_channel_lifecycle() -> ctpl_list(cl_args()). methods() -> tpl_list(m_args()). c_methods() -> ctpl_list(m_args()). %%--------------------------------------------------------------------------- %% Internal plumbing %%--------------------------------------------------------------------------- all_args() -> sup_args() ++ ncl_args() ++ cml_args() ++ cl_args() ++ m_args(). sup_args() -> [{amqp_connection_sup, start_link, return_ms()}, {amqp_connection_type_sup, start_link, return_ms()}, {amqp_channel_sup_sup, start_link, return_ms()}, {amqp_channel_sup_sup, start_channel_sup, return_ms()}, {amqp_channel_sup, start_link, return_ms()}, {amqp_network_connection, start_infrastructure, return_ms()}, {amqp_network_connection, start_heartbeat, return_ms()}, {amqp_channel, start_writer, return_ms()}]. ncl_args() -> [{amqp_main_reader, start_link, return_ms()}, {amqp_gen_connection, set_closing_state, []}, {amqp_gen_connection, handle_channels_terminated, []}, {amqp_network_connection, connect, []}, {amqp_direct_connection, connect, []}, {amqp_gen_connection, terminate, []}]. cml_args() -> [{amqp_channels_manager, handle_open_channel, return_ms()}, {amqp_channels_manager, handle_channel_down, []}, {amqp_channels_manager, signal_channels_connection_closing, []}]. cl_args() -> [{amqp_channel, init, []}, {amqp_channel_util, open_channel, []}, {amqp_channel, terminate, []}]. m_args() -> [{amqp_channel, do, return_ms()}, {amqp_channel, handle_method, []}, {amqp_gen_connection, handle_method, []}, {amqp_network_connection, do, return_ms()}, {amqp_network_connection, handshake_recv, return_ms()}]. tpl_list(ArgsList) -> [{ok, _} = dbg:tpl(Module, Func, Ms) || {Module, Func, Ms} <- ArgsList], ok. ctpl_list(ArgsList) -> [{ok, _} = dbg:ctpl(Module, Func) || {Module, Func, _} <- ArgsList], ok. return_ms() -> dbg:fun2ms(fun(_) -> return_trace() end). rabbitmq-server-3.2.4/plugins-src/rabbitmq-erlang-client/test/amqp_client_SUITE.erl0000644000000000000000000001236112305126066027050 0ustar rootroot%% The contents of this file are subject to the Mozilla Public License %% Version 1.1 (the "License"); you may not use this file except in %% compliance with the License. You may obtain a copy of the License at %% http://www.mozilla.org/MPL/ %% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the %% License for the specific language governing rights and limitations %% under the License. %% %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is GoPivotal, Inc. %% Copyright (c) 2007-2013 GoPivotal, Inc. All rights reserved. %% -module(amqp_client_SUITE). -export([test_coverage/0]). -include_lib("eunit/include/eunit.hrl"). -define(FUNCTION, begin catch throw(x), Fun = case erlang:get_stacktrace() of [{_, F, _} | _] -> F; %% < R15 [{_, F, _, _} | _] -> F %% >= R15 end, list_to_atom(string:strip(atom_to_list(Fun), right, $_)) end). -define(RUN(Props), run(?FUNCTION, Props)). %%--------------------------------------------------------------------------- %% Tests %%--------------------------------------------------------------------------- amqp_uri_parse_test_() -> ?RUN([]). route_destination_test_() -> ?RUN([]). basic_get_test_() -> ?RUN([]). basic_get_ipv6_test_() -> ?RUN([]). basic_return_test_() -> ?RUN([]). simultaneous_close_test_() -> ?RUN([repeat]). basic_qos_test_() -> ?RUN([]). basic_recover_test_() -> ?RUN([]). basic_consume_test_() -> ?RUN([]). consume_notification_test_() -> ?RUN([]). basic_nack_test_() -> ?RUN([]). large_content_test_() -> ?RUN([]). lifecycle_test_() -> ?RUN([]). direct_no_password_test_() -> ?RUN([]). nowait_exchange_declare_test_() -> ?RUN([]). channel_repeat_open_close_test_() -> ?RUN([]). channel_multi_open_close_test_() -> ?RUN([]). basic_ack_test_() -> ?RUN([]). basic_ack_call_test_() -> ?RUN([]). channel_lifecycle_test_() -> ?RUN([]). queue_unbind_test_() -> ?RUN([]). sync_method_serialization_test_() -> ?RUN([]). async_sync_method_serialization_test_() -> ?RUN([]). sync_async_method_serialization_test_() -> ?RUN([]). teardown_test_() -> ?RUN([repeat]). rpc_test_() -> ?RUN([]). rpc_client_test_() -> ?RUN([]). pub_and_close_test_() -> ?RUN([]). channel_tune_negotiation_test_() -> ?RUN([]). confirm_test_() -> ?RUN([]). confirm_barrier_test_() -> ?RUN([]). confirm_select_before_wait_test_() -> ?RUN([]). confirm_barrier_timeout_test_() -> ?RUN([]). confirm_barrier_die_timeout_test_() -> ?RUN([]). default_consumer_test_() -> ?RUN([]). subscribe_nowait_test_() -> ?RUN([]). connection_blocked_network_test_() -> ?RUN([]). non_existent_exchange_test_() -> ?RUN([negative]). bogus_rpc_test_() -> ?RUN([negative, repeat]). hard_error_test_() -> ?RUN([negative, repeat]). non_existent_user_test_() -> ?RUN([negative]). invalid_password_test_() -> ?RUN([negative]). non_existent_vhost_test_() -> ?RUN([negative]). no_permission_test_() -> ?RUN([negative]). channel_writer_death_test_() -> ?RUN([negative]). channel_death_test_() -> ?RUN([negative]). shortstr_overflow_property_test_() -> ?RUN([negative]). shortstr_overflow_field_test_() -> ?RUN([negative]). command_invalid_over_channel_test_() -> ?RUN([negative]). command_invalid_over_channel0_test_() -> ?RUN([negative]). %%--------------------------------------------------------------------------- %% Internal %%--------------------------------------------------------------------------- run(TestName, Props) -> RepeatCount = case proplists:get_value(repeat, Props, false) of true -> 100; Number when is_number(Number) -> Number; false -> 1 end, Module = case proplists:get_bool(negative, Props) of true -> negative_test_util; false -> test_util end, {timeout, proplists:get_value(timeout, Props, 60), fun () -> lists:foreach( fun (_) -> try erlang:apply(Module, TestName, []) of Ret -> Ret catch exit:normal -> ok end end, lists:seq(1, RepeatCount)) end}. %%--------------------------------------------------------------------------- %% Coverage %%--------------------------------------------------------------------------- test_coverage() -> rabbit_misc:enable_cover(), test(), rabbit_misc:report_cover(). rabbitmq-server-3.2.4/plugins-src/rabbitmq-erlang-client/.srcdist_done0000644000000000000000000000000012305126066024564 0ustar rootrootrabbitmq-server-3.2.4/plugins-src/rabbitmq-erlang-client/Makefile0000644000000000000000000001154012305126066023556 0ustar rootroot# The contents of this file are subject to the Mozilla Public License # Version 1.1 (the "License"); you may not use this file except in # compliance with the License. You may obtain a copy of the License at # http://www.mozilla.org/MPL/ # # Software distributed under the License is distributed on an "AS IS" # basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the # License for the specific language governing rights and limitations # under the License. # # The Original Code is RabbitMQ. # # The Initial Developer of the Original Code is GoPivotal, Inc. # Copyright (c) 2007-2013 GoPivotal, Inc. All rights reserved. # VERSION=0.0.0 SOURCE_PACKAGE_DIR=$(PACKAGE)-$(VERSION)-src SOURCE_PACKAGE_TAR_GZ=$(SOURCE_PACKAGE_DIR).tar.gz BROKER_HEADERS=$(wildcard $(BROKER_DIR)/$(INCLUDE_DIR)/*.hrl) BROKER_SOURCES=$(wildcard $(BROKER_DIR)/$(SOURCE_DIR)/*.erl) BROKER_DEPS=$(BROKER_HEADERS) $(BROKER_SOURCES) INFILES=$(shell find . -name '*.app.in') INTARGETS=$(patsubst %.in, %, $(INFILES)) WEB_URL=http://www.rabbitmq.com/ include common.mk run_in_broker: compile $(BROKER_DEPS) $(EBIN_DIR)/$(PACKAGE).app $(MAKE) RABBITMQ_SERVER_START_ARGS='$(PA_LOAD_PATH)' -C $(BROKER_DIR) run clean: common_clean rm -f $(INTARGETS) rm -rf $(DIST_DIR) distribution: documentation source_tarball package %.app: %.app.in $(SOURCES) $(BROKER_DIR)/generate_app escript $(BROKER_DIR)/generate_app $< $@ $(SOURCE_DIR) sed 's/%%VSN%%/$(VERSION)/' $@ > $@.tmp && mv $@.tmp $@ ############################################################################### ## Dialyzer ############################################################################### RABBIT_PLT=$(BROKER_DIR)/rabbit.plt dialyze: $(RABBIT_PLT) $(TARGETS) dialyzer --plt $(RABBIT_PLT) --no_native -Wrace_conditions $(TARGETS) .PHONY: $(RABBIT_PLT) $(RABBIT_PLT): $(MAKE) -C $(BROKER_DIR) create-plt ############################################################################### ## Documentation ############################################################################### documentation: $(DOC_DIR)/index.html $(DOC_DIR)/overview.edoc: $(SOURCE_DIR)/overview.edoc.in mkdir -p $(DOC_DIR) sed -e 's:%%VERSION%%:$(VERSION):g' < $< > $@ $(DOC_DIR)/index.html: $(DEPS_DIR)/$(COMMON_PACKAGE_DIR) $(DOC_DIR)/overview.edoc $(SOURCES) $(LIBS_PATH) erl -noshell -eval 'edoc:application(amqp_client, ".", [{preprocess, true}, {macros, [{edoc, true}]}])' -run init stop ############################################################################### ## Testing ############################################################################### include test.mk compile_tests: $(TEST_TARGETS) $(EBIN_DIR)/$(PACKAGE).app $(TEST_TARGETS): $(TEST_DIR) .PHONY: $(TEST_DIR) $(TEST_DIR): $(DEPS_DIR)/$(COMMON_PACKAGE_DIR) $(MAKE) -C $(TEST_DIR) ############################################################################### ## Packaging ############################################################################### COPY=cp -pR $(DIST_DIR)/$(COMMON_PACKAGE_EZ): $(BROKER_DEPS) $(COMMON_PACKAGE).app | $(DIST_DIR) rm -f $@ $(MAKE) -C $(BROKER_DIR) rm -rf $(DIST_DIR)/$(COMMON_PACKAGE_DIR) mkdir -p $(DIST_DIR)/$(COMMON_PACKAGE_DIR)/$(INCLUDE_DIR) mkdir -p $(DIST_DIR)/$(COMMON_PACKAGE_DIR)/$(EBIN_DIR) cp $(COMMON_PACKAGE).app $(DIST_DIR)/$(COMMON_PACKAGE_DIR)/$(EBIN_DIR)/ $(foreach DEP, $(DEPS), \ ( cp $(BROKER_DIR)/ebin/$(DEP).beam $(DIST_DIR)/$(COMMON_PACKAGE_DIR)/$(EBIN_DIR)/ \ );) cp $(BROKER_DIR)/include/*.hrl $(DIST_DIR)/$(COMMON_PACKAGE_DIR)/$(INCLUDE_DIR)/ (cd $(DIST_DIR); zip -q -r $(COMMON_PACKAGE_EZ) $(COMMON_PACKAGE_DIR)) source_tarball: $(DIST_DIR)/$(COMMON_PACKAGE_EZ) $(EBIN_DIR)/$(PACKAGE).app | $(DIST_DIR) mkdir -p $(DIST_DIR)/$(SOURCE_PACKAGE_DIR)/$(DIST_DIR) $(COPY) $(DIST_DIR)/$(COMMON_PACKAGE_EZ) $(DIST_DIR)/$(SOURCE_PACKAGE_DIR)/$(DIST_DIR)/ $(COPY) README.in $(DIST_DIR)/$(SOURCE_PACKAGE_DIR)/README elinks -dump -no-references -no-numbering $(WEB_URL)build-erlang-client.html >> $(DIST_DIR)/$(SOURCE_PACKAGE_DIR)/README $(COPY) common.mk $(DIST_DIR)/$(SOURCE_PACKAGE_DIR)/ $(COPY) test.mk $(DIST_DIR)/$(SOURCE_PACKAGE_DIR)/ sed 's/%%VSN%%/$(VERSION)/' Makefile.in > $(DIST_DIR)/$(SOURCE_PACKAGE_DIR)/Makefile mkdir -p $(DIST_DIR)/$(SOURCE_PACKAGE_DIR)/$(SOURCE_DIR) $(COPY) $(SOURCE_DIR)/*.erl $(DIST_DIR)/$(SOURCE_PACKAGE_DIR)/$(SOURCE_DIR)/ mkdir -p $(DIST_DIR)/$(SOURCE_PACKAGE_DIR)/$(EBIN_DIR) $(COPY) $(EBIN_DIR)/*.app $(DIST_DIR)/$(SOURCE_PACKAGE_DIR)/$(EBIN_DIR)/ mkdir -p $(DIST_DIR)/$(SOURCE_PACKAGE_DIR)/$(INCLUDE_DIR) $(COPY) $(INCLUDE_DIR)/*.hrl $(DIST_DIR)/$(SOURCE_PACKAGE_DIR)/$(INCLUDE_DIR)/ mkdir -p $(DIST_DIR)/$(SOURCE_PACKAGE_DIR)/$(TEST_DIR) $(COPY) $(TEST_DIR)/*.erl $(DIST_DIR)/$(SOURCE_PACKAGE_DIR)/$(TEST_DIR)/ $(COPY) $(TEST_DIR)/Makefile $(DIST_DIR)/$(SOURCE_PACKAGE_DIR)/$(TEST_DIR)/ cd $(DIST_DIR) ; tar czf $(SOURCE_PACKAGE_TAR_GZ) $(SOURCE_PACKAGE_DIR) $(DIST_DIR): mkdir -p $@ rabbitmq-server-3.2.4/plugins-src/rabbitmq-erlang-client/common.mk0000644000000000000000000001615012305126066023741 0ustar rootroot# The contents of this file are subject to the Mozilla Public License # Version 1.1 (the "License"); you may not use this file except in # compliance with the License. You may obtain a copy of the License at # http://www.mozilla.org/MPL/ # # Software distributed under the License is distributed on an "AS IS" # basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the # License for the specific language governing rights and limitations # under the License. # # The Original Code is RabbitMQ. # # The Initial Developer of the Original Code is GoPivotal, Inc. # Copyright (c) 2007-2013 GoPivotal, Inc. All rights reserved. # # The client library can either be built from source control or by downloading # a source tarball from the RabbitMQ site. The intention behind the source tarball is # to be able to unpack this anywhere and just run a simple a test, under the # assumption that you have a running broker. This provides the simplest # possible way of building and running the client. # # The source control version, on the other hand, contains far more infrastructure # to start and stop brokers, package modules from the server, run embedded tests # and so forth. # # This means that the Makefile of the source control version contains a lot of # functionality that just wouldn't work with the source tarball version. # # The purpose of this common Makefile is to define as many commonalities # between the build requirements of the source control version and the source # tarball version. This avoids duplicating make definitions and rules and # helps keep the Makefile maintenence well factored. ifndef TMPDIR TMPDIR := /tmp endif EBIN_DIR=ebin BROKER_DIR=../rabbitmq-server export INCLUDE_DIR=include TEST_DIR=test SOURCE_DIR=src DIST_DIR=dist DEPS_DIR=deps DOC_DIR=doc DEPS_FILE=deps.mk ifeq ("$(ERL_LIBS)", "") ERL_LIBS := else ERL_LIBS := :$(ERL_LIBS) endif ERL_PATH ?= PACKAGE=amqp_client PACKAGE_DIR=$(PACKAGE)-$(VERSION) PACKAGE_NAME_EZ=$(PACKAGE_DIR).ez COMMON_PACKAGE=rabbit_common export COMMON_PACKAGE_DIR=$(COMMON_PACKAGE)-$(VERSION) COMMON_PACKAGE_EZ=$(COMMON_PACKAGE_DIR).ez NODE_NAME=amqp_client DEPS=$(shell erl -noshell -eval '{ok,[{_,_,[_,_,{modules, Mods},_,_,_]}]} = \ file:consult("$(COMMON_PACKAGE).app.in"), \ [io:format("~p ",[M]) || M <- Mods], halt().') INCLUDES=$(wildcard $(INCLUDE_DIR)/*.hrl) SOURCES=$(wildcard $(SOURCE_DIR)/*.erl) TARGETS=$(patsubst $(SOURCE_DIR)/%.erl, $(EBIN_DIR)/%.beam, $(SOURCES)) TEST_SOURCES=$(wildcard $(TEST_DIR)/*.erl) TEST_TARGETS=$(patsubst $(TEST_DIR)/%.erl, $(TEST_DIR)/%.beam, $(TEST_SOURCES)) LIBS_PATH_UNIX=$(DEPS_DIR):$(DIST_DIR)$(ERL_LIBS) IS_CYGWIN=$(shell if [ $(shell expr "$(shell uname -s)" : 'CYGWIN_NT') -gt 0 ]; then echo "true"; else echo "false"; fi) ifeq ($(IS_CYGWIN),true) LIBS_PATH=ERL_LIBS="$(shell cygpath -wp $(LIBS_PATH_UNIX))" else LIBS_PATH=ERL_LIBS=$(LIBS_PATH_UNIX) endif LOAD_PATH=$(EBIN_DIR) $(TEST_DIR) $(ERL_PATH) RUN:=$(LIBS_PATH) erl -pa $(LOAD_PATH) -sname $(NODE_NAME) MKTEMP=$$(mktemp $(TMPDIR)/tmp.XXXXXXXXXX) ifndef USE_SPECS # our type specs rely on features / bug fixes in dialyzer that are # only available in R13B01 upwards (R13B is eshell 5.7.2) # # NB: do not mark this variable for export, otherwise it will # override the test in rabbitmq-server's Makefile when it does the # make -C, which causes problems whenever the test here and the test # there compare system_info(version) against *different* eshell # version numbers. USE_SPECS:=$(shell erl -noshell -eval 'io:format([list_to_integer(X) || X <- string:tokens(erlang:system_info(version), ".")] >= [5,7,2]), halt().') endif ERLC_OPTS=-I $(INCLUDE_DIR) -pa $(EBIN_DIR) -o $(EBIN_DIR) -Wall -v +debug_info $(if $(filter true,$(USE_SPECS)),-Duse_specs) RABBITMQ_NODENAME=rabbit PA_LOAD_PATH=-pa $(realpath $(LOAD_PATH)) RABBITMQCTL=$(BROKER_DIR)/scripts/rabbitmqctl ifdef SSL_CERTS_DIR SSL := true ALL_SSL := { $(MAKE) test_ssl || OK=false; } ALL_SSL_COVERAGE := { $(MAKE) test_ssl_coverage || OK=false; } SSL_BROKER_ARGS := -rabbit ssl_listeners [{\\\"0.0.0.0\\\",5671},{\\\"::1\\\",5671}] \ -rabbit ssl_options [{cacertfile,\\\"$(SSL_CERTS_DIR)/testca/cacert.pem\\\"},{certfile,\\\"$(SSL_CERTS_DIR)/server/cert.pem\\\"},{keyfile,\\\"$(SSL_CERTS_DIR)/server/key.pem\\\"},{verify,verify_peer},{fail_if_no_peer_cert,true}] SSL_CLIENT_ARGS := -erlang_client_ssl_dir $(SSL_CERTS_DIR) else SSL := @echo No SSL_CERTS_DIR defined. && false ALL_SSL := true ALL_SSL_COVERAGE := true SSL_BROKER_ARGS := SSL_CLIENT_ARGS := endif # Versions prior to this are not supported NEED_MAKE := 3.80 ifneq "$(NEED_MAKE)" "$(firstword $(sort $(NEED_MAKE) $(MAKE_VERSION)))" $(error Versions of make prior to $(NEED_MAKE) are not supported) endif # .DEFAULT_GOAL introduced in 3.81 DEFAULT_GOAL_MAKE := 3.81 ifneq "$(DEFAULT_GOAL_MAKE)" "$(firstword $(sort $(DEFAULT_GOAL_MAKE) $(MAKE_VERSION)))" .DEFAULT_GOAL=all endif all: package common_clean: rm -f $(EBIN_DIR)/*.beam rm -f erl_crash.dump rm -rf $(DEPS_DIR) rm -rf $(DOC_DIR) rm -f $(DEPS_FILE) $(MAKE) -C $(TEST_DIR) clean compile: $(TARGETS) $(EBIN_DIR)/$(PACKAGE).app run: compile $(RUN) ############################################################################### ## Packaging ############################################################################### $(DIST_DIR)/$(PACKAGE_NAME_EZ): $(TARGETS) $(EBIN_DIR)/$(PACKAGE).app | $(DIST_DIR) rm -f $@ rm -rf $(DIST_DIR)/$(PACKAGE_DIR) mkdir -p $(DIST_DIR)/$(PACKAGE_DIR)/$(EBIN_DIR) mkdir -p $(DIST_DIR)/$(PACKAGE_DIR)/$(INCLUDE_DIR) cp -r $(EBIN_DIR)/*.beam $(DIST_DIR)/$(PACKAGE_DIR)/$(EBIN_DIR) cp -r $(EBIN_DIR)/*.app $(DIST_DIR)/$(PACKAGE_DIR)/$(EBIN_DIR) mkdir -p $(DIST_DIR)/$(PACKAGE_DIR)/$(INCLUDE_DIR) cp -r $(INCLUDE_DIR)/* $(DIST_DIR)/$(PACKAGE_DIR)/$(INCLUDE_DIR) (cd $(DIST_DIR); zip -q -r $(PACKAGE_NAME_EZ) $(PACKAGE_DIR)) package: $(DIST_DIR)/$(PACKAGE_NAME_EZ) ############################################################################### ## Internal targets ############################################################################### $(DEPS_DIR)/$(COMMON_PACKAGE_DIR): $(DIST_DIR)/$(COMMON_PACKAGE_EZ) | $(DEPS_DIR) rm -rf $(DEPS_DIR)/$(COMMON_PACKAGE_DIR) mkdir -p $(DEPS_DIR)/$(COMMON_PACKAGE_DIR) unzip -q -o $< -d $(DEPS_DIR) $(DEPS_FILE): $(SOURCES) $(INCLUDES) rm -f $@ echo $(subst : ,:,$(foreach FILE,$^,$(FILE):)) | escript $(BROKER_DIR)/generate_deps $@ $(EBIN_DIR) $(EBIN_DIR)/%.beam: $(SOURCE_DIR)/%.erl $(INCLUDES) $(DEPS_DIR)/$(COMMON_PACKAGE_DIR) | $(DEPS_FILE) $(LIBS_PATH) erlc $(ERLC_OPTS) $< $(DEPS_DIR): mkdir -p $@ # Note that all targets which depend on clean must have clean in their # name. Also any target that doesn't depend on clean should not have # clean in its name, unless you know that you don't need any of the # automatic dependency generation for that target. # We want to load the dep file if *any* target *doesn't* contain # "clean" - i.e. if removing all clean-like targets leaves something ifeq "$(MAKECMDGOALS)" "" TESTABLEGOALS:=$(.DEFAULT_GOAL) else TESTABLEGOALS:=$(MAKECMDGOALS) endif ifneq "$(strip $(patsubst clean%,,$(patsubst %clean,,$(TESTABLEGOALS))))" "" -include $(DEPS_FILE) endif rabbitmq-server-3.2.4/plugins-src/rabbitmq-erlang-client/test.mk0000644000000000000000000001141512305126066023427 0ustar rootroot# The contents of this file are subject to the Mozilla Public License # Version 1.1 (the "License"); you may not use this file except in # compliance with the License. You may obtain a copy of the License at # http://www.mozilla.org/MPL/ # # Software distributed under the License is distributed on an "AS IS" # basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the # License for the specific language governing rights and limitations # under the License. # # The Original Code is RabbitMQ. # # The Initial Developer of the Original Code is GoPivotal, Inc. # Copyright (c) 2007-2013 GoPivotal, Inc. All rights reserved. # IS_SUCCESS:=egrep "All .+ tests (successful|passed)." TESTING_MESSAGE:=-eval 'error_logger:tty(false), io:format("~nTesting in progress. Please wait...~n~n").' prepare_tests: compile compile_tests all_tests: prepare_tests OK=true && \ { $(MAKE) test_suites || OK=false; } && \ { $(MAKE) test_common_package || OK=false; } && \ { $(MAKE) test_direct || OK=false; } && \ $$OK test_suites: prepare_tests OK=true && \ { $(MAKE) test_network || OK=false; } && \ { $(MAKE) test_remote_direct || OK=false; } && \ $(ALL_SSL) && \ $$OK test_suites_coverage: prepare_tests OK=true && \ { $(MAKE) test_network_coverage || OK=false; } && \ { $(MAKE) test_direct_coverage || OK=false; } && \ $(ALL_SSL_COVERAGE) && \ $$OK ## Starts a broker, configures users and runs the tests on the same node run_test_in_broker: $(MAKE) start_test_broker_node $(MAKE) unboot_broker OK=true && \ TMPFILE=$(MKTEMP) && echo "Redirecting output to $$TMPFILE" && \ { $(MAKE) -C $(BROKER_DIR) run-node \ RABBITMQ_SERVER_START_ARGS="$(PA_LOAD_PATH) $(SSL_BROKER_ARGS) \ -noshell -s rabbit $(RUN_TEST_ARGS) -s init stop" 2>&1 | \ tee $$TMPFILE || OK=false; } && \ { $(IS_SUCCESS) $$TMPFILE || OK=false; } && \ rm $$TMPFILE && \ $(MAKE) boot_broker && \ $(MAKE) stop_test_broker_node && \ $$OK ## Starts a broker, configures users and runs the tests from a different node run_test_detached: start_test_broker_node OK=true && \ TMPFILE=$(MKTEMP) && echo "Redirecting output to $$TMPFILE" && \ { $(RUN) -noinput $(TESTING_MESSAGE) \ $(SSL_CLIENT_ARGS) $(RUN_TEST_ARGS) \ -s init stop 2>&1 | tee $$TMPFILE || OK=false; } && \ { $(IS_SUCCESS) $$TMPFILE || OK=false; } && \ rm $$TMPFILE && \ $(MAKE) stop_test_broker_node && \ $$OK ## Starts a broker, configures users and runs the tests from a different node run_test_foreground: start_test_broker_node OK=true && \ { $(RUN) -noinput $(TESTING_MESSAGE) \ $(SSL_CLIENT_ARGS) $(RUN_TEST_ARGS) \ -s init stop || OK=false; } && \ $(MAKE) stop_test_broker_node && \ $$OK start_test_broker_node: boot_broker sleep 1 - $(RABBITMQCTL) delete_user test_user_no_perm $(RABBITMQCTL) add_user test_user_no_perm test_user_no_perm sleep 1 stop_test_broker_node: sleep 1 $(RABBITMQCTL) delete_user test_user_no_perm $(MAKE) unboot_broker boot_broker: $(MAKE) -C $(BROKER_DIR) start-background-node RABBITMQ_SERVER_START_ARGS="$(RABBITMQ_SERVER_START_ARGS) $(SSL_BROKER_ARGS)" $(MAKE) -C $(BROKER_DIR) start-rabbit-on-node unboot_broker: $(MAKE) -C $(BROKER_DIR) stop-rabbit-on-node $(MAKE) -C $(BROKER_DIR) stop-node ssl: $(SSL) test_ssl: prepare_tests ssl $(MAKE) run_test_detached AMQP_CLIENT_TEST_CONNECTION_TYPE="network_ssl" RUN_TEST_ARGS="-s amqp_client_SUITE test" test_network: prepare_tests $(MAKE) run_test_detached AMQP_CLIENT_TEST_CONNECTION_TYPE="network" RUN_TEST_ARGS="-s amqp_client_SUITE test" test_direct: prepare_tests $(MAKE) run_test_in_broker AMQP_CLIENT_TEST_CONNECTION_TYPE="direct" RUN_TEST_ARGS="-s amqp_client_SUITE test" test_remote_direct: prepare_tests $(MAKE) run_test_detached AMQP_CLIENT_TEST_CONNECTION_TYPE="direct" RUN_TEST_ARGS="-s amqp_client_SUITE test" test_common_package: $(DIST_DIR)/$(COMMON_PACKAGE_EZ) package prepare_tests $(MAKE) run_test_detached RUN="$(LIBS_PATH) erl -pa $(TEST_DIR)" \ AMQP_CLIENT_TEST_CONNECTION_TYPE="network" RUN_TEST_ARGS="-s amqp_client_SUITE test" $(MAKE) run_test_detached RUN="$(LIBS_PATH) erl -pa $(TEST_DIR) -sname amqp_client" \ AMQP_CLIENT_TEST_CONNECTION_TYPE="direct" RUN_TEST_ARGS="-s amqp_client_SUITE test" test_ssl_coverage: prepare_tests ssl $(MAKE) run_test_detached AMQP_CLIENT_TEST_CONNECTION_TYPE="network_ssl" RUN_TEST_ARGS="-s amqp_client_SUITE test_coverage" test_network_coverage: prepare_tests $(MAKE) run_test_detached AMQP_CLIENT_TEST_CONNECTION_TYPE="network" RUN_TEST_ARGS="-s amqp_client_SUITE test_coverage" test_remote_direct_coverage: prepare_tests $(MAKE) run_test_detached AMQP_CLIENT_TEST_CONNECTION_TYPE="direct" RUN_TEST_ARGS="-s amqp_client_SUITE test_coverage" test_direct_coverage: prepare_tests $(MAKE) run_test_in_broker AMQP_CLIENT_TEST_CONNECTION_TYPE="direct" RUN_TEST_ARGS="-s amqp_client_SUITE test_coverage" rabbitmq-server-3.2.4/plugins-src/rabbitmq-erlang-client/rabbit_common.app.in0000644000000000000000000000226512305126066026044 0ustar rootroot{application, rabbit_common, [{description, "RabbitMQ Common Libraries"}, {vsn, "%%VSN%%"}, {modules, [ app_utils, credit_flow, pmon, gen_server2, mirrored_supervisor, priority_queue, rabbit_backing_queue, rabbit_basic, rabbit_binary_generator, rabbit_binary_parser, rabbit_channel, rabbit_runtime_parameter, rabbit_command_assembler, rabbit_exchange_type, rabbit_exchange_decorator, rabbit_auth_backend, rabbit_auth_mechanism, rabbit_framing_amqp_0_8, rabbit_framing_amqp_0_9_1, rabbit_heartbeat, rabbit_misc, rabbit_msg_store_index, rabbit_net, rabbit_nodes, rabbit_policy_validator, rabbit_reader, rabbit_writer, rabbit_event, rabbit_queue_collector, rabbit_queue_decorator, rabbit_amqqueue, supervisor2 ]}, {registered, []}, {env, []}, {applications, [kernel, stdlib]}]}. rabbitmq-server-3.2.4/plugins-src/rabbitmq-erlang-client/ebin/0000755000000000000000000000000012305126066023032 5ustar rootrootrabbitmq-server-3.2.4/plugins-src/rabbitmq-erlang-client/ebin/amqp_client.app.in0000644000000000000000000000035012305126066026433 0ustar rootroot{application, amqp_client, [{description, "RabbitMQ AMQP Client"}, {vsn, "%%VSN%%"}, {modules, []}, {registered, [amqp_sup]}, {env, [{prefer_ipv6, false}]}, {mod, {amqp_client, []}}, {applications, [kernel, stdlib]}]}. rabbitmq-server-3.2.4/plugins-src/rabbitmq-erlang-client/include/0000755000000000000000000000000012305126066023540 5ustar rootrootrabbitmq-server-3.2.4/plugins-src/rabbitmq-erlang-client/include/amqp_client_internal.hrl0000644000000000000000000000277512305126066030452 0ustar rootroot%% The contents of this file are subject to the Mozilla Public License %% Version 1.1 (the "License"); you may not use this file except in %% compliance with the License. You may obtain a copy of the License at %% http://www.mozilla.org/MPL/ %% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the %% License for the specific language governing rights and limitations %% under the License. %% %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is GoPivotal, Inc. %% Copyright (c) 2007-2013 GoPivotal, Inc. All rights reserved. %% -include("amqp_client.hrl"). -define(PROTOCOL_VERSION_MAJOR, 0). -define(PROTOCOL_VERSION_MINOR, 9). -define(PROTOCOL_HEADER, <<"AMQP", 0, 0, 9, 1>>). -define(PROTOCOL, rabbit_framing_amqp_0_9_1). -define(MAX_CHANNEL_NUMBER, 65535). -define(LOG_DEBUG(Format), error_logger:info_msg(Format)). -define(LOG_INFO(Format, Args), error_logger:info_msg(Format, Args)). -define(LOG_WARN(Format, Args), error_logger:warning_msg(Format, Args)). -define(LOG_ERR(Format, Args), error_logger:error_msg(Format, Args)). -define(CLIENT_CAPABILITIES, [{<<"publisher_confirms">>, bool, true}, {<<"exchange_exchange_bindings">>, bool, true}, {<<"basic.nack">>, bool, true}, {<<"consumer_cancel_notify">>, bool, true}, {<<"connection.blocked">>, bool, true}, {<<"authentication_failure_close">>, bool, true}]). rabbitmq-server-3.2.4/plugins-src/rabbitmq-erlang-client/include/amqp_gen_consumer_spec.hrl0000644000000000000000000000337712305126066030775 0ustar rootroot%% The contents of this file are subject to the Mozilla Public License %% Version 1.1 (the "License"); you may not use this file except in %% compliance with the License. You may obtain a copy of the License at %% http://www.mozilla.org/MPL/ %% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the %% License for the specific language governing rights and limitations %% under the License. %% %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is GoPivotal, Inc. %% Copyright (c) 2011-2013 GoPivotal, Inc. All rights reserved. %% -include("amqp_client.hrl"). -ifndef(edoc). -type(state() :: any()). -type(consume() :: #'basic.consume'{}). -type(consume_ok() :: #'basic.consume_ok'{}). -type(cancel() :: #'basic.cancel'{}). -type(cancel_ok() :: #'basic.cancel_ok'{}). -type(deliver() :: #'basic.deliver'{}). -type(from() :: any()). -type(reason() :: any()). -type(ok_error() :: {ok, state()} | {error, reason(), state()}). -spec(init/1 :: ([any()]) -> {ok, state()}). -spec(handle_consume/3 :: (consume(), pid(), state()) -> ok_error()). -spec(handle_consume_ok/3 :: (consume_ok(), consume(), state()) -> ok_error()). -spec(handle_cancel/2 :: (cancel(), state()) -> ok_error()). -spec(handle_cancel_ok/3 :: (cancel_ok(), cancel(), state()) -> ok_error()). -spec(handle_deliver/3 :: (deliver(), #amqp_msg{}, state()) -> ok_error()). -spec(handle_info/2 :: (any(), state()) -> ok_error()). -spec(handle_call/3 :: (any(), from(), state()) -> {reply, any(), state()} | {noreply, state()} | {error, reason(), state()}). -spec(terminate/2 :: (any(), state()) -> state()). -endif. rabbitmq-server-3.2.4/plugins-src/rabbitmq-erlang-client/include/amqp_client.hrl0000644000000000000000000000472712305126066026555 0ustar rootroot%% The contents of this file are subject to the Mozilla Public License %% Version 1.1 (the "License"); you may not use this file except in %% compliance with the License. You may obtain a copy of the License at %% http://www.mozilla.org/MPL/ %% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the %% License for the specific language governing rights and limitations %% under the License. %% %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is GoPivotal, Inc. %% Copyright (c) 2007-2013 GoPivotal, Inc. All rights reserved. %% -ifndef(AMQP_CLIENT_HRL). -define(AMQP_CLIENT_HRL, true). -include_lib("rabbit_common/include/rabbit.hrl"). -include_lib("rabbit_common/include/rabbit_framing.hrl"). -record(amqp_msg, {props = #'P_basic'{}, payload = <<>>}). -record(amqp_params_network, {username = <<"guest">>, password = <<"guest">>, virtual_host = <<"/">>, host = "localhost", port = undefined, channel_max = 0, frame_max = 0, heartbeat = 0, connection_timeout = infinity, ssl_options = none, auth_mechanisms = [fun amqp_auth_mechanisms:plain/3, fun amqp_auth_mechanisms:amqplain/3], client_properties = [], socket_options = []}). -record(amqp_params_direct, {username = <<"guest">>, password = none, virtual_host = <<"/">>, node = node(), adapter_info = none, client_properties = []}). -record(amqp_adapter_info, {host = unknown, port = unknown, peer_host = unknown, peer_port = unknown, name = unknown, protocol = unknown, additional_info = []}). -endif. rabbitmq-server-3.2.4/plugins-src/rabbitmq-erlang-client/include/rabbit_routing_prefixes.hrl0000644000000000000000000000172312305126066031171 0ustar rootroot%% The contents of this file are subject to the Mozilla Public License %% Version 1.1 (the "License"); you may not use this file except in %% compliance with the License. You may obtain a copy of the License %% at http://www.mozilla.org/MPL/ %% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See %% the License for the specific language governing rights and %% limitations under the License. %% %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is GoPivotal, Inc. %% Copyright (c) 2011-2013 GoPivotal, Inc. All rights reserved. %% -define(QUEUE_PREFIX, "/queue"). -define(TOPIC_PREFIX, "/topic"). -define(EXCHANGE_PREFIX, "/exchange"). -define(AMQQUEUE_PREFIX, "/amq/queue"). -define(TEMP_QUEUE_PREFIX, "/temp-queue"). %% reply queues names can have slashes in the content so no further %% parsing happens. -define(REPLY_QUEUE_PREFIX, "/reply-queue/"). rabbitmq-server-3.2.4/plugins-src/rabbitmq-erlang-client/Makefile.in0000644000000000000000000000137712305126066024172 0ustar rootroot# The contents of this file are subject to the Mozilla Public License # Version 1.1 (the "License"); you may not use this file except in # compliance with the License. You may obtain a copy of the License at # http://www.mozilla.org/MPL/ # # Software distributed under the License is distributed on an "AS IS" # basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the # License for the specific language governing rights and limitations # under the License. # # The Original Code is RabbitMQ. # # The Initial Developer of the Original Code is GoPivotal, Inc. # Copyright (c) 2007-2013 GoPivotal, Inc. All rights reserved. # VERSION=%%VSN%% include common.mk include test.mk clean: common_clean compile_tests: $(MAKE) -C test VERSION=$(VERSION) rabbitmq-server-3.2.4/plugins-src/Makefile0000644000000000000000000001073512305126066017240 0ustar rootroot.PHONY: default default: @echo No default target && false REPOS:= \ rabbitmq-server \ rabbitmq-codegen \ rabbitmq-java-client \ rabbitmq-dotnet-client \ rabbitmq-test \ cowboy-wrapper \ eldap-wrapper \ erlang-rfc4627-wrapper \ mochiweb-wrapper \ rabbitmq-amqp1.0 \ rabbitmq-auth-backend-ldap \ rabbitmq-auth-mechanism-ssl \ rabbitmq-consistent-hash-exchange \ rabbitmq-erlang-client \ rabbitmq-federation \ rabbitmq-federation-management \ rabbitmq-jsonrpc \ rabbitmq-jsonrpc-channel \ rabbitmq-jsonrpc-channel-examples \ rabbitmq-management \ rabbitmq-management-agent \ rabbitmq-management-visualiser \ rabbitmq-metronome \ rabbitmq-web-dispatch \ rabbitmq-mqtt \ rabbitmq-shovel \ rabbitmq-shovel-management \ rabbitmq-stomp \ rabbitmq-toke \ rabbitmq-tracing \ rabbitmq-web-stomp \ rabbitmq-web-stomp-examples \ sockjs-erlang-wrapper \ toke \ webmachine-wrapper BRANCH:=default HG_CORE_REPOBASE:=$(shell dirname `hg paths default 2>/dev/null` 2>/dev/null) ifndef HG_CORE_REPOBASE HG_CORE_REPOBASE:=http://hg.rabbitmq.com/ endif VERSION:=0.0.0 #---------------------------------- all: $(MAKE) -f all-packages.mk all-packages VERSION=$(VERSION) test: $(MAKE) -f all-packages.mk test-all-packages VERSION=$(VERSION) release: $(MAKE) -f all-packages.mk all-releasable VERSION=$(VERSION) clean: $(MAKE) -f all-packages.mk clean-all-packages check-xref: $(MAKE) -f all-packages.mk check-xref-packages plugins-dist: release rm -rf $(PLUGINS_DIST_DIR) mkdir -p $(PLUGINS_DIST_DIR) $(MAKE) -f all-packages.mk copy-releasable VERSION=$(VERSION) PLUGINS_DIST_DIR=$(PLUGINS_DIST_DIR) plugins-srcdist: rm -rf $(PLUGINS_SRC_DIST_DIR) mkdir -p $(PLUGINS_SRC_DIST_DIR)/licensing rsync -a --exclude '.hg*' rabbitmq-erlang-client $(PLUGINS_SRC_DIST_DIR)/ touch $(PLUGINS_SRC_DIST_DIR)/rabbitmq-erlang-client/.srcdist_done rsync -a --exclude '.hg*' rabbitmq-server $(PLUGINS_SRC_DIST_DIR)/ touch $(PLUGINS_SRC_DIST_DIR)/rabbitmq-server/.srcdist_done $(MAKE) -f all-packages.mk copy-srcdist VERSION=$(VERSION) PLUGINS_SRC_DIST_DIR=$(PLUGINS_SRC_DIST_DIR) cp Makefile *.mk generate* $(PLUGINS_SRC_DIST_DIR)/ echo "This is the released version of rabbitmq-public-umbrella. \ You can clone the full version with: hg clone http://hg.rabbitmq.com/rabbitmq-public-umbrella" > $(PLUGINS_SRC_DIST_DIR)/README PRESERVE_CLONE_DIR=1 make -C $(PLUGINS_SRC_DIST_DIR) clean rm -rf $(PLUGINS_SRC_DIST_DIR)/rabbitmq-server #---------------------------------- # Convenience aliases .PHONY: co co: checkout .PHONY: ci ci: checkin .PHONY: up up: update .PHONY: st st: status .PHONY: up_c up_c: named_update #---------------------------------- $(REPOS): hg clone $(HG_CORE_REPOBASE)/$@ .PHONY: checkout checkout: $(REPOS) #---------------------------------- # Subrepository management # $(1) is the target # $(2) is the target dependency. Can use % to get current REPO # $(3) is the target body. Can use % to get current REPO define repo_target .PHONY: $(1) $(1): $(2) $(3) endef # $(1) is the list of repos # $(2) is the suffix # $(3) is the target dependency. Can use % to get current REPO # $(4) is the target body. Can use % to get current REPO define repo_targets $(foreach REPO,$(1),$(call repo_target,$(REPO)+$(2),\ $(patsubst %,$(3),$(REPO)),$(patsubst %,$(4),$(REPO)))) endef # Do not allow status to fork with -j otherwise output will be garbled .PHONY: status status: checkout $(foreach DIR,. $(REPOS), \ (cd $(DIR); OUT=$$(hg st -mad); \ if \[ ! -z "$$OUT" \]; then echo "\n$(DIR):\n$$OUT"; fi) &&) true .PHONY: pull pull: $(foreach DIR,. $(REPOS),$(DIR)+pull) $(eval $(call repo_targets,. $(REPOS),pull,| %,(cd % && hg pull))) .PHONY: update update: $(foreach DIR,. $(REPOS),$(DIR)+update) $(eval $(call repo_targets,. $(REPOS),update,%+pull,(cd % && hg up))) .PHONY: named_update named_update: $(foreach DIR,. $(REPOS),$(DIR)+named_update) $(eval $(call repo_targets,. $(REPOS),named_update,%+pull,\ (cd % && hg up -C $(BRANCH)))) .PHONY: tag tag: $(foreach DIR,. $(REPOS),$(DIR)+tag) $(eval $(call repo_targets,. $(REPOS),tag,| %,(cd % && hg tag $(TAG)))) .PHONY: push push: $(foreach DIR,. $(REPOS),$(DIR)+push) # "|| true" sicne hg push fails if there are no changes $(eval $(call repo_targets,. $(REPOS),push,| %,(cd % && hg push -f || true))) .PHONY: checkin checkin: $(foreach DIR,. $(REPOS),$(DIR)+checkin) $(eval $(call repo_targets,. $(REPOS),checkin,| %,(cd % && hg ci))) rabbitmq-server-3.2.4/plugins-src/rabbitmq-management-agent/0000755000000000000000000000000012305126066022601 5ustar rootrootrabbitmq-server-3.2.4/plugins-src/rabbitmq-management-agent/src/0000755000000000000000000000000012305126066023370 5ustar rootrootrabbitmq-server-3.2.4/plugins-src/rabbitmq-management-agent/src/rabbit_mgmt_external_stats.erl0000644000000000000000000002301312305126066031502 0ustar rootroot%% The contents of this file are subject to the Mozilla Public License %% Version 1.1 (the "License"); you may not use this file except in %% compliance with the License. You may obtain a copy of the License at %% http://www.mozilla.org/MPL/ %% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the %% License for the specific language governing rights and limitations %% under the License. %% %% The Original Code is RabbitMQ Management Console. %% %% The Initial Developer of the Original Code is GoPivotal, Inc. %% Copyright (c) 2010-2013 GoPivotal, Inc. All rights reserved. %% -module(rabbit_mgmt_external_stats). -behaviour(gen_server). -export([start_link/0]). -export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]). -export([list_registry_plugins/1]). -include_lib("rabbit_common/include/rabbit.hrl"). -define(REFRESH_RATIO, 5000). -define(KEYS, [name, partitions, os_pid, fd_used, fd_total, sockets_used, sockets_total, mem_used, mem_limit, mem_alarm, disk_free_limit, disk_free, disk_free_alarm, proc_used, proc_total, statistics_level, uptime, run_queue, processors, exchange_types, auth_mechanisms, applications, contexts]). %%-------------------------------------------------------------------- -record(state, {fd_total}). %%-------------------------------------------------------------------- start_link() -> gen_server:start_link({local, ?MODULE}, ?MODULE, [], []). %%-------------------------------------------------------------------- get_used_fd() -> get_used_fd(os:type()). get_used_fd({unix, linux}) -> case file:list_dir("/proc/" ++ os:getpid() ++ "/fd") of {ok, Files} -> length(Files); {error, _} -> get_used_fd({unix, generic}) end; get_used_fd({unix, BSD}) when BSD == openbsd; BSD == freebsd; BSD == netbsd -> Digit = fun (D) -> lists:member(D, "0123456789*") end, length( lists:filter( fun (Line) -> lists:all(Digit, (lists:nth(4, string:tokens(Line, " ")))) end, string:tokens(os:cmd("fstat -p " ++ os:getpid()), "\n"))); get_used_fd({unix, _}) -> Cmd = rabbit_misc:format( "lsof -d \"0-9999999\" -lna -p ~s || echo failed", [os:getpid()]), Res = os:cmd(Cmd), case string:right(Res, 7) of "failed\n" -> unknown; _ -> string:words(Res, $\n) - 1 end; %% handle.exe can be obtained from %% http://technet.microsoft.com/en-us/sysinternals/bb896655.aspx %% Output looks like: %% Handle v3.42 %% Copyright (C) 1997-2008 Mark Russinovich %% Sysinternals - www.sysinternals.com %% %% Handle type summary: %% ALPC Port : 2 %% Desktop : 1 %% Directory : 1 %% Event : 108 %% File : 25 %% IoCompletion : 3 %% Key : 7 %% KeyedEvent : 1 %% Mutant : 1 %% Process : 3 %% Process : 38 %% Thread : 41 %% Timer : 3 %% TpWorkerFactory : 2 %% WindowStation : 2 %% Total handles: 238 %% Note that the "File" number appears to include network sockets too; I assume %% that's the number we care about. Note also that if you omit "-s" you will %% see a list of file handles *without* network sockets. If you then add "-a" %% you will see a list of handles of various types, including network sockets %% shown as file handles to \Device\Afd. get_used_fd({win32, _}) -> Handle = rabbit_misc:os_cmd( "handle.exe /accepteula -s -p " ++ os:getpid() ++ " 2> nul"), case Handle of [] -> install_handle_from_sysinternals; _ -> find_files_line(string:tokens(Handle, "\r\n")) end; get_used_fd(_) -> unknown. find_files_line([]) -> unknown; find_files_line([" File " ++ Rest | _T]) -> [Files] = string:tokens(Rest, ": "), list_to_integer(Files); find_files_line([_H | T]) -> find_files_line(T). -define(SAFE_CALL(Fun, NoProcFailResult), try Fun catch exit:{noproc, _} -> NoProcFailResult end). get_disk_free_limit() -> ?SAFE_CALL(rabbit_disk_monitor:get_disk_free_limit(), disk_free_monitoring_disabled). get_disk_free() -> ?SAFE_CALL(rabbit_disk_monitor:get_disk_free(), disk_free_monitoring_disabled). %%-------------------------------------------------------------------- infos(Items, State) -> [{Item, i(Item, State)} || Item <- Items]. i(name, _State) -> node(); i(partitions, _State) -> rabbit_node_monitor:partitions(); i(fd_used, _State) -> get_used_fd(); i(fd_total, #state{fd_total = FdTotal}) -> FdTotal; i(sockets_used, _State) -> proplists:get_value(sockets_used, file_handle_cache:info([sockets_used])); i(sockets_total, _State) -> proplists:get_value(sockets_limit, file_handle_cache:info([sockets_limit])); i(os_pid, _State) -> list_to_binary(os:getpid()); i(mem_used, _State) -> erlang:memory(total); i(mem_limit, _State) -> vm_memory_monitor:get_memory_limit(); i(mem_alarm, _State) -> resource_alarm_set(memory); i(proc_used, _State) -> erlang:system_info(process_count); i(proc_total, _State) -> erlang:system_info(process_limit); i(run_queue, _State) -> erlang:statistics(run_queue); i(processors, _State) -> erlang:system_info(logical_processors); i(disk_free_limit, _State) -> get_disk_free_limit(); i(disk_free, _State) -> get_disk_free(); i(disk_free_alarm, _State) -> resource_alarm_set(disk); i(contexts, _State) -> rabbit_web_dispatch_contexts(); i(uptime, _State) -> {Total, _} = erlang:statistics(wall_clock), Total; i(statistics_level, _State) -> {ok, StatsLevel} = application:get_env(rabbit, collect_statistics), StatsLevel; i(exchange_types, _State) -> list_registry_plugins(exchange); i(auth_mechanisms, _State) -> {ok, Mechanisms} = application:get_env(rabbit, auth_mechanisms), list_registry_plugins( auth_mechanism, fun (N) -> lists:member(list_to_atom(binary_to_list(N)), Mechanisms) end); i(applications, _State) -> [format_application(A) || A <- lists:keysort(1, rabbit_misc:which_applications())]. resource_alarm_set(Source) -> lists:member({{resource_limit, Source, node()},[]}, rabbit_alarm:get_alarms()). list_registry_plugins(Type) -> list_registry_plugins(Type, fun(_) -> true end). list_registry_plugins(Type, Fun) -> [registry_plugin_enabled(set_plugin_name(Name, Module), Fun) || {Name, Module} <- rabbit_registry:lookup_all(Type)]. registry_plugin_enabled(Desc, Fun) -> Desc ++ [{enabled, Fun(proplists:get_value(name, Desc))}]. format_application({Application, Description, Version}) -> [{name, Application}, {description, list_to_binary(Description)}, {version, list_to_binary(Version)}]. set_plugin_name(Name, Module) -> [{name, list_to_binary(atom_to_list(Name))} | proplists:delete(name, Module:description())]. %%-------------------------------------------------------------------- %% This is slightly icky in that we introduce knowledge of %% rabbit_web_dispatch, which is not a dependency. But the last thing I %% want to do is create a rabbitmq_mochiweb_management_agent plugin. rabbit_web_dispatch_contexts() -> [format_context(C) || C <- rabbit_web_dispatch_registry_list_all()]. %% For similar reasons we don't declare a dependency on %% rabbitmq_mochiweb - so at startup there's no guarantee it will be %% running. So we have to catch this noproc. rabbit_web_dispatch_registry_list_all() -> case code:is_loaded(rabbit_web_dispatch_registry) of false -> []; _ -> try M = rabbit_web_dispatch_registry, %% Fool xref M:list_all() catch exit:{noproc, _} -> [] end end. format_context({Path, Description, Rest}) -> [{description, list_to_binary(Description)}, {path, list_to_binary("/" ++ Path)} | format_mochiweb_option_list(Rest)]. format_mochiweb_option_list(C) -> [{K, format_mochiweb_option(K, V)} || {K, V} <- C]. format_mochiweb_option(ssl_opts, V) -> format_mochiweb_option_list(V); format_mochiweb_option(ciphers, V) -> list_to_binary(rabbit_misc:format("~w", [V])); format_mochiweb_option(_K, V) when is_list(V) -> list_to_binary(V); format_mochiweb_option(_K, V) -> V. %%-------------------------------------------------------------------- init([]) -> State = #state{fd_total = file_handle_cache:ulimit()}, %% If we emit an update straight away we will do so just before %% the mgmt db starts up - and then have to wait ?REFRESH_RATIO %% until we send another. So let's have a shorter wait in the hope %% that the db will have started by the time we emit an update, %% and thus shorten that little gap at startup where mgmt knows %% nothing about any nodes. erlang:send_after(1000, self(), emit_update), {ok, State}. handle_call(_Req, _From, State) -> {reply, unknown_request, State}. handle_cast(_C, State) -> {noreply, State}. handle_info(emit_update, State) -> {noreply, emit_update(State)}; handle_info(_I, State) -> {noreply, State}. terminate(_, _) -> ok. code_change(_, State, _) -> {ok, State}. %%-------------------------------------------------------------------- emit_update(State) -> rabbit_event:notify(node_stats, infos(?KEYS, State)), erlang:send_after(?REFRESH_RATIO, self(), emit_update), State. rabbitmq-server-3.2.4/plugins-src/rabbitmq-management-agent/src/rabbit_mgmt_db_handler.erl0000644000000000000000000000421412305126066030526 0ustar rootroot%% The contents of this file are subject to the Mozilla Public License %% Version 1.1 (the "License"); you may not use this file except in %% compliance with the License. You may obtain a copy of the License at %% http://www.mozilla.org/MPL/ %% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the %% License for the specific language governing rights and limitations %% under the License. %% %% The Original Code is RabbitMQ Management Console. %% %% The Initial Developer of the Original Code is GoPivotal, Inc. %% Copyright (c) 2010-2013 GoPivotal, Inc. All rights reserved. %% -module(rabbit_mgmt_db_handler). -behaviour(gen_event). -export([add_handler/0, gc/0]). -export([init/1, handle_call/2, handle_event/2, handle_info/2, terminate/2, code_change/3]). %%---------------------------------------------------------------------------- add_handler() -> ensure_statistics_enabled(), gen_event:add_sup_handler(rabbit_event, ?MODULE, []). gc() -> erlang:garbage_collect(whereis(rabbit_event)). %%---------------------------------------------------------------------------- ensure_statistics_enabled() -> {ok, ForceStats} = application:get_env(rabbitmq_management_agent, force_fine_statistics), {ok, StatsLevel} = application:get_env(rabbit, collect_statistics), case {ForceStats, StatsLevel} of {true, fine} -> ok; {true, _} -> application:set_env(rabbit, collect_statistics, fine); {false, none} -> application:set_env(rabbit, collect_statistics, coarse); {_, _} -> ok end. %%---------------------------------------------------------------------------- init([]) -> {ok, []}. handle_call(_Request, State) -> {ok, not_understood, State}. handle_event(Event, State) -> gen_server:cast({global, rabbit_mgmt_db}, {event, Event}), {ok, State}. handle_info(_Info, State) -> {ok, State}. terminate(_Arg, _State) -> ok. code_change(_OldVsn, State, _Extra) -> {ok, State}. rabbitmq-server-3.2.4/plugins-src/rabbitmq-management-agent/src/rabbit_mgmt_agent_app.erl0000644000000000000000000000250112305126066030377 0ustar rootroot%% The contents of this file are subject to the Mozilla Public License %% Version 1.1 (the "License"); you may not use this file except in %% compliance with the License. You may obtain a copy of the License at %% http://www.mozilla.org/MPL/ %% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the %% License for the specific language governing rights and limitations %% under the License. %% %% The Original Code is RabbitMQ Management Console. %% %% The Initial Developer of the Original Code is GoPivotal, Inc. %% Copyright (c) 2010-2013 GoPivotal, Inc. All rights reserved. %% -module(rabbit_mgmt_agent_app). -behaviour(application). -export([start/2, stop/1]). %% Make sure our database is hooked in *before* listening on the network or %% recovering queues (i.e. so there can't be any events fired before it starts). -rabbit_boot_step({rabbit_mgmt_db_handler, [{description, "management agent"}, {mfa, {rabbit_mgmt_db_handler, add_handler, []}}, {requires, rabbit_event}, {enables, recovery}]}). start(_Type, _StartArgs) -> rabbit_mgmt_agent_sup:start_link(). stop(_State) -> ok. rabbitmq-server-3.2.4/plugins-src/rabbitmq-management-agent/src/rabbit_mgmt_agent_sup.erl0000644000000000000000000000215512305126066030433 0ustar rootroot%% The contents of this file are subject to the Mozilla Public License %% Version 1.1 (the "License"); you may not use this file except in %% compliance with the License. You may obtain a copy of the License at %% http://www.mozilla.org/MPL/ %% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the %% License for the specific language governing rights and limitations %% under the License. %% %% The Original Code is RabbitMQ Management Console. %% %% The Initial Developer of the Original Code is GoPivotal, Inc. %% Copyright (c) 2010-2013 GoPivotal, Inc. All rights reserved. %% -module(rabbit_mgmt_agent_sup). -behaviour(supervisor). -export([init/1]). -export([start_link/0]). init([]) -> ExternalStats = {rabbit_mgmt_external_stats, {rabbit_mgmt_external_stats, start_link, []}, permanent, 5000, worker, [rabbit_mgmt_external_stats]}, {ok, {{one_for_one, 10, 10}, [ExternalStats]}}. start_link() -> supervisor:start_link({local, ?MODULE}, ?MODULE, []). rabbitmq-server-3.2.4/plugins-src/rabbitmq-management-agent/src/rabbitmq_management_agent.app.src0000644000000000000000000000041612305126066032034 0ustar rootroot{application, rabbitmq_management_agent, [{description, "RabbitMQ Management Agent"}, {vsn, "%%VSN%%"}, {modules, []}, {registered, []}, {mod, {rabbit_mgmt_agent_app, []}}, {env, [{force_fine_statistics, true}]}, {applications, [kernel, stdlib, rabbit]}]}. rabbitmq-server-3.2.4/plugins-src/rabbitmq-management-agent/.srcdist_done0000644000000000000000000000000012305126066025250 0ustar rootrootrabbitmq-server-3.2.4/plugins-src/rabbitmq-management-agent/Makefile0000644000000000000000000000002712305126066024240 0ustar rootrootinclude ../umbrella.mk rabbitmq-server-3.2.4/plugins-src/rabbitmq-management-agent/ebin/0000755000000000000000000000000012305126066023516 5ustar rootrootrabbitmq-server-3.2.4/plugins-src/rabbitmq-management-agent/package.mk0000644000000000000000000000003512305126066024523 0ustar rootrootDEPS:=rabbitmq-erlang-client rabbitmq-server-3.2.4/plugins-src/common.mk0000644000000000000000000001065012305126066017415 0ustar rootroot# Various global definitions # UMBRELLA_BASE_DIR should be set to the path of the # rabbitmq-public-umbrella directory before this file is included. # Make version check REQUIRED_MAKE_VERSION:=3.81 ifneq ($(shell ( echo "$(MAKE_VERSION)" ; echo "$(REQUIRED_MAKE_VERSION)" ) | sort -t. -n | head -1),$(REQUIRED_MAKE_VERSION)) $(error GNU make version $(REQUIRED_MAKE_VERSION) required) endif # This is the standard trick for making pattern substitution work # (amongst others) when the replacement needs to include a comma. COMMA:=, # Global settings that can be overridden on the command line # These ones are expected to be passed down to the sub-makes invoked # for non-integrated packages VERSION ?= 0.0.0 ERL ?= erl ERL_OPTS ?= ERLC ?= erlc ERLC_OPTS ?= -Wall +debug_info TMPDIR ?= /tmp NODENAME ?= rabbit-test ERL_CALL ?= erl_call ERL_CALL_OPTS ?= -sname $(NODENAME) -e # Where we put all the files produced when running tests. TEST_TMPDIR=$(TMPDIR)/rabbitmq-test # Callable functions # Convert a package name to the corresponding erlang app name define package_to_app_name $(subst -,_,$(1)) endef # If the variable named $(1) holds a non-empty value, return it. # Otherwise, set the variable to $(2) and return that value. define memoize $(if $($(1)),$($(1)),$(eval $(1):=$(2))$(2)) endef # Return a canonical form for the path in $(1) # # Absolute path names can be a bit verbose. This provides a way to # canonicalize path names with more concise results. define canonical_path $(call memoize,SHORT_$(realpath $(1)),$(1)) endef # Convert a package name to a path name define package_to_path $(call canonical_path,$(UMBRELLA_BASE_DIR)/$(1)) endef # Produce a cp command to copy from $(1) to $(2), unless $(1) is # empty, in which case do nothing. # # The optional $(3) gives a suffix to append to the command, if a # command is produced. define copy $(if $(1),cp -r $(1) $(2)$(if $(3), $(3))) endef # Produce the makefile fragment for the package with path in $(1), if # it hasn't already been visited. The path should have been # canonicalized via canonical_path. define do_package # Have we already visited this package? If so, skip it ifndef DONE_$(1) PACKAGE_DIR:=$(1) include $(UMBRELLA_BASE_DIR)/do-package.mk endif endef # This is used to chain test rules, so that test-all-packages works in # the presence of 'make -j' define chain_test $(if $(CHAIN_TESTS),$(CHAINED_TESTS)$(eval CHAINED_TESTS+=$(1))) endef # Mark the non-integrated repos NON_INTEGRATED_$(call package_to_path,rabbitmq-server):=true NON_INTEGRATED_$(call package_to_path,rabbitmq-erlang-client):=true NON_INTEGRATED_$(call package_to_path,rabbitmq-java-client):=true NON_INTEGRATED_$(call package_to_path,rabbitmq-dotnet-client):=true NON_INTEGRATED_$(call package_to_path,rabbitmq-test):=true NON_INTEGRATED_DEPS_$(call package_to_path,rabbitmq-erlang-client):=rabbitmq-server # Where the coverage package lives COVERAGE_PATH:=$(call package_to_path,coverage) # Where the rabbitmq-server package lives RABBITMQ_SERVER_PATH=$(call package_to_path,rabbitmq-server) # Cleaning support ifndef MAKECMDGOALS TESTABLEGOALS:=$(.DEFAULT_GOAL) else TESTABLEGOALS:=$(MAKECMDGOALS) endif # The CLEANING variable can be used to determine whether the top-level # goal is cleaning related. In particular, it can be used to prevent # including generated files when cleaning, which might otherwise # trigger undesirable activity. ifeq "$(strip $(patsubst clean%,,$(patsubst %clean,,$(TESTABLEGOALS))))" "" CLEANING:=true endif # Include a generated makefile fragment # # Note that this includes using "-include", and thus make will proceed # even if an error occurs while the fragment is being re-made (we # don't use "include" becuase it will produce a superfluous error # message when the fragment is re-made because it doesn't exist). # Thus you should also list the fragment as a dependency of any rules # that will refer to the contents of the fragment. define safe_include ifndef CLEANING -include $(1) # If we fail to make the fragment, make will just loop trying to # create it. So we have to explicitly catch that case. $$(if $$(MAKE_RESTARTS),$$(if $$(wildcard $(1)),,$$(error Failed to produce $(1)))) endif endef # This is not the make default, but it is a good idea .DELETE_ON_ERROR: # Declarations for global targets .PHONY: all-releasable copy-releasable copy-srcdist all-packages clean-all-packages all-releasable:: copy-releasable:: copy-srcdist:: all-packages:: clean-all-packages:: check-xref-packages:: rabbitmq-server-3.2.4/plugins-src/eldap-wrapper/0000755000000000000000000000000012305126066020335 5ustar rootrootrabbitmq-server-3.2.4/plugins-src/eldap-wrapper/eldap-git/0000755000000000000000000000000012305126066022203 5ustar rootrootrabbitmq-server-3.2.4/plugins-src/eldap-wrapper/eldap-git/src/0000755000000000000000000000000012305126066022772 5ustar rootrootrabbitmq-server-3.2.4/plugins-src/eldap-wrapper/eldap-git/src/Makefile0000644000000000000000000000100312305126066024424 0ustar rootroot ERLC = erlc EBIN_DIR = ../ebin ERLC_FLAGS += -I ./src -I ../include +debug_info ERL_OBJECTS := ${EBIN_DIR}/eldap.beam ${EBIN_DIR}/ELDAPv3.beam ${EBIN_DIR}/eldap_fsm.beam .SUFFIXES: .asn .erl .beam $(EBIN_DIR)/%.beam: %.erl $(ERLC) $(ERLC_FLAGS) -o $(EBIN_DIR) $< .PHONY: all all: asn $(ERL_OBJECTS) .PHONY: asn asn: ELDAPv3.erl ../ebin/ELDAPv3.beam ELDAPv3.erl: ELDAPv3.asn ${ERLC} ELDAPv3.asn mv ELDAPv3.beam ${EBIN_DIR} .PHONY: clean clean: -rm $(ERL_OBJECTS) ELDAPv3.erl ELDAPv3.asn1db ELDAPv3.hrl rabbitmq-server-3.2.4/plugins-src/eldap-wrapper/eldap-git/src/ELDAPv3.asn0000644000000000000000000002415512305126066024602 0ustar rootroot-- LDAPv3 ASN.1 specification, taken from RFC 2251 -- Lightweight-Directory-Access-Protocol-V3 DEFINITIONS ELDAPv3 DEFINITIONS IMPLICIT TAGS ::= BEGIN LDAPMessage ::= SEQUENCE { messageID MessageID, protocolOp CHOICE { bindRequest BindRequest, bindResponse BindResponse, unbindRequest UnbindRequest, searchRequest SearchRequest, searchResEntry SearchResultEntry, searchResDone SearchResultDone, searchResRef SearchResultReference, modifyRequest ModifyRequest, modifyResponse ModifyResponse, addRequest AddRequest, addResponse AddResponse, delRequest DelRequest, delResponse DelResponse, modDNRequest ModifyDNRequest, modDNResponse ModifyDNResponse, compareRequest CompareRequest, compareResponse CompareResponse, abandonRequest AbandonRequest, extendedReq ExtendedRequest, extendedResp ExtendedResponse }, controls [0] Controls OPTIONAL } MessageID ::= INTEGER (0 .. maxInt) maxInt INTEGER ::= 2147483647 -- (2^^31 - 1) -- LDAPString ::= OCTET STRING LDAPOID ::= OCTET STRING LDAPDN ::= LDAPString RelativeLDAPDN ::= LDAPString AttributeType ::= LDAPString AttributeDescription ::= LDAPString -- Wahl, et. al. Standards Track [Page 44] -- -- RFC 2251 LDAPv3 December 1997 AttributeDescriptionList ::= SEQUENCE OF AttributeDescription AttributeValue ::= OCTET STRING AttributeValueAssertion ::= SEQUENCE { attributeDesc AttributeDescription, assertionValue AssertionValue } AssertionValue ::= OCTET STRING Attribute ::= SEQUENCE { type AttributeDescription, vals SET OF AttributeValue } MatchingRuleId ::= LDAPString LDAPResult ::= SEQUENCE { resultCode ENUMERATED { success (0), operationsError (1), protocolError (2), timeLimitExceeded (3), sizeLimitExceeded (4), compareFalse (5), compareTrue (6), authMethodNotSupported (7), strongAuthRequired (8), -- 9 reserved -- referral (10), -- new adminLimitExceeded (11), -- new unavailableCriticalExtension (12), -- new confidentialityRequired (13), -- new saslBindInProgress (14), -- new noSuchAttribute (16), undefinedAttributeType (17), inappropriateMatching (18), constraintViolation (19), attributeOrValueExists (20), invalidAttributeSyntax (21), -- 22-31 unused -- noSuchObject (32), aliasProblem (33), invalidDNSyntax (34), -- 35 reserved for undefined isLeaf -- aliasDereferencingProblem (36), -- 37-47 unused -- inappropriateAuthentication (48), -- Wahl, et. al. Standards Track [Page 45] -- -- RFC 2251 LDAPv3 December 1997 invalidCredentials (49), insufficientAccessRights (50), busy (51), unavailable (52), unwillingToPerform (53), loopDetect (54), -- 55-63 unused -- namingViolation (64), objectClassViolation (65), notAllowedOnNonLeaf (66), notAllowedOnRDN (67), entryAlreadyExists (68), objectClassModsProhibited (69), -- 70 reserved for CLDAP -- affectsMultipleDSAs (71), -- new -- 72-79 unused -- other (80) }, -- 81-90 reserved for APIs -- matchedDN LDAPDN, errorMessage LDAPString, referral [3] Referral OPTIONAL } Referral ::= SEQUENCE OF LDAPURL LDAPURL ::= LDAPString -- limited to characters permitted in URLs Controls ::= SEQUENCE OF Control Control ::= SEQUENCE { controlType LDAPOID, criticality BOOLEAN DEFAULT FALSE, controlValue OCTET STRING OPTIONAL } BindRequest ::= [APPLICATION 0] SEQUENCE { version INTEGER (1 .. 127), name LDAPDN, authentication AuthenticationChoice } AuthenticationChoice ::= CHOICE { simple [0] OCTET STRING, -- 1 and 2 reserved sasl [3] SaslCredentials } SaslCredentials ::= SEQUENCE { mechanism LDAPString, credentials OCTET STRING OPTIONAL } BindResponse ::= [APPLICATION 1] SEQUENCE { -- Wahl, et. al. Standards Track [Page 46] -- -- RFC 2251 LDAPv3 December 1997 COMPONENTS OF LDAPResult, serverSaslCreds [7] OCTET STRING OPTIONAL } UnbindRequest ::= [APPLICATION 2] NULL SearchRequest ::= [APPLICATION 3] SEQUENCE { baseObject LDAPDN, scope ENUMERATED { baseObject (0), singleLevel (1), wholeSubtree (2) }, derefAliases ENUMERATED { neverDerefAliases (0), derefInSearching (1), derefFindingBaseObj (2), derefAlways (3) }, sizeLimit INTEGER (0 .. maxInt), timeLimit INTEGER (0 .. maxInt), typesOnly BOOLEAN, filter Filter, attributes AttributeDescriptionList } Filter ::= CHOICE { and [0] SET OF Filter, or [1] SET OF Filter, not [2] Filter, equalityMatch [3] AttributeValueAssertion, substrings [4] SubstringFilter, greaterOrEqual [5] AttributeValueAssertion, lessOrEqual [6] AttributeValueAssertion, present [7] AttributeDescription, approxMatch [8] AttributeValueAssertion, extensibleMatch [9] MatchingRuleAssertion } SubstringFilter ::= SEQUENCE { type AttributeDescription, -- at least one must be present substrings SEQUENCE OF CHOICE { initial [0] LDAPString, any [1] LDAPString, final [2] LDAPString } } MatchingRuleAssertion ::= SEQUENCE { matchingRule [1] MatchingRuleId OPTIONAL, type [2] AttributeDescription OPTIONAL, matchValue [3] AssertionValue, dnAttributes [4] BOOLEAN DEFAULT FALSE } -- Wahl, et. al. Standards Track [Page 47] -- -- RFC 2251 LDAPv3 December 1997 SearchResultEntry ::= [APPLICATION 4] SEQUENCE { objectName LDAPDN, attributes PartialAttributeList } PartialAttributeList ::= SEQUENCE OF SEQUENCE { type AttributeDescription, vals SET OF AttributeValue } SearchResultReference ::= [APPLICATION 19] SEQUENCE OF LDAPURL SearchResultDone ::= [APPLICATION 5] LDAPResult ModifyRequest ::= [APPLICATION 6] SEQUENCE { object LDAPDN, modification SEQUENCE OF SEQUENCE { operation ENUMERATED { add (0), delete (1), replace (2) }, modification AttributeTypeAndValues } } AttributeTypeAndValues ::= SEQUENCE { type AttributeDescription, vals SET OF AttributeValue } ModifyResponse ::= [APPLICATION 7] LDAPResult AddRequest ::= [APPLICATION 8] SEQUENCE { entry LDAPDN, attributes AttributeList } AttributeList ::= SEQUENCE OF SEQUENCE { type AttributeDescription, vals SET OF AttributeValue } AddResponse ::= [APPLICATION 9] LDAPResult DelRequest ::= [APPLICATION 10] LDAPDN DelResponse ::= [APPLICATION 11] LDAPResult ModifyDNRequest ::= [APPLICATION 12] SEQUENCE { entry LDAPDN, newrdn RelativeLDAPDN, deleteoldrdn BOOLEAN, newSuperior [0] LDAPDN OPTIONAL } ModifyDNResponse ::= [APPLICATION 13] LDAPResult -- Wahl, et. al. Standards Track [Page 48] -- -- RFC 2251 LDAPv3 December 1997 CompareRequest ::= [APPLICATION 14] SEQUENCE { entry LDAPDN, ava AttributeValueAssertion } CompareResponse ::= [APPLICATION 15] LDAPResult AbandonRequest ::= [APPLICATION 16] MessageID ExtendedRequest ::= [APPLICATION 23] SEQUENCE { requestName [0] LDAPOID, requestValue [1] OCTET STRING OPTIONAL } ExtendedResponse ::= [APPLICATION 24] SEQUENCE { COMPONENTS OF LDAPResult, responseName [10] LDAPOID OPTIONAL, response [11] OCTET STRING OPTIONAL } END rabbitmq-server-3.2.4/plugins-src/eldap-wrapper/eldap-git/src/eldap.erl0000644000000000000000000010672312305126066024574 0ustar rootroot-module(eldap). %%% -------------------------------------------------------------------- %%% Created: 12 Oct 2000 by Tobbe %%% Function: Erlang client LDAP implementation according RFC 2251,2253 %%% and 2255. The interface is based on RFC 1823, and %%% draft-ietf-asid-ldap-c-api-00.txt %%% %%% Copyright (c) 2010 Torbjorn Tornkvist %%% See MIT-LICENSE at the top dir for licensing information. %%% -------------------------------------------------------------------- -vc('$Id$ '). -export([open/1,open/2,simple_bind/3,controlling_process/2, baseObject/0,singleLevel/0,wholeSubtree/0,close/1, equalityMatch/2,greaterOrEqual/2,lessOrEqual/2, approxMatch/2,search/2,substrings/2,present/1, 'and'/1,'or'/1,'not'/1,modify/3, mod_add/2, mod_delete/2, mod_replace/2, add/3, delete/2, modify_dn/5,parse_dn/1, parse_ldap_url/1]). -import(lists,[concat/1]). -include("ELDAPv3.hrl"). -include("eldap.hrl"). -define(LDAP_VERSION, 3). -define(LDAP_PORT, 389). -define(LDAPS_PORT, 636). -record(eldap, {version = ?LDAP_VERSION, host, % Host running LDAP server port = ?LDAP_PORT, % The LDAP server port fd, % Socket filedescriptor. binddn = "", % Name of the entry to bind as passwd, % Password for (above) entry id = 0, % LDAP Request ID log, % User provided log function timeout = infinity, % Request timeout anon_auth = false, % Allow anonymous authentication use_tls = false % LDAP/LDAPS }). %%% For debug purposes %%-define(PRINT(S, A), io:fwrite("~w(~w): " ++ S, [?MODULE,?LINE|A])). -define(PRINT(S, A), true). -define(elog(S, A), error_logger:info_msg("~w(~w): "++S,[?MODULE,?LINE|A])). %%% ==================================================================== %%% Exported interface %%% ==================================================================== %%% -------------------------------------------------------------------- %%% open(Hosts [,Opts] ) %%% -------------------- %%% Setup a connection to on of the Hosts in the argument %%% list. Stop at the first successful connection attempt. %%% Valid Opts are: Where: %%% %%% {port, Port} - Port is the port number %%% {log, F} - F(LogLevel, FormatString, ListOfArgs) %%% {timeout, milliSec} - request timeout %%% %%% -------------------------------------------------------------------- open(Hosts) -> open(Hosts, []). open(Hosts, Opts) when list(Hosts), list(Opts) -> Self = self(), Pid = spawn_link(fun() -> init(Hosts, Opts, Self) end), recv(Pid). %%% -------------------------------------------------------------------- %%% Shutdown connection (and process) asynchronous. %%% -------------------------------------------------------------------- close(Handle) when pid(Handle) -> send(Handle, close). %%% -------------------------------------------------------------------- %%% Set who we should link ourselves to %%% -------------------------------------------------------------------- controlling_process(Handle, Pid) when pid(Handle),pid(Pid) -> link(Pid), send(Handle, {cnt_proc, Pid}), recv(Handle). %%% -------------------------------------------------------------------- %%% Authenticate ourselves to the Directory %%% using simple authentication. %%% %%% Dn - The name of the entry to bind as %%% Passwd - The password to be used %%% %%% Returns: ok | {error, Error} %%% -------------------------------------------------------------------- simple_bind(Handle, Dn, Passwd) when pid(Handle) -> send(Handle, {simple_bind, Dn, Passwd}), recv(Handle). %%% -------------------------------------------------------------------- %%% Add an entry. The entry field MUST NOT exist for the AddRequest %%% to succeed. The parent of the entry MUST exist. %%% Example: %%% %%% add(Handle, %%% "cn=Bill Valentine, ou=people, o=Bluetail AB, dc=bluetail, dc=com", %%% [{"objectclass", ["person"]}, %%% {"cn", ["Bill Valentine"]}, %%% {"sn", ["Valentine"]}, %%% {"telephoneNumber", ["545 555 00"]}] %%% ) %%% -------------------------------------------------------------------- add(Handle, Entry, Attributes) when pid(Handle),list(Entry),list(Attributes) -> send(Handle, {add, Entry, add_attrs(Attributes)}), recv(Handle). %%% Do sanity check ! add_attrs(Attrs) -> F = fun({Type,Vals}) when list(Type),list(Vals) -> %% Confused ? Me too... :-/ {'AddRequest_attributes',Type, Vals} end, case catch lists:map(F, Attrs) of {'EXIT', _} -> throw({error, attribute_values}); Else -> Else end. %%% -------------------------------------------------------------------- %%% Delete an entry. The entry consists of the DN of %%% the entry to be deleted. %%% Example: %%% %%% delete(Handle, %%% "cn=Bill Valentine, ou=people, o=Bluetail AB, dc=bluetail, dc=com" %%% ) %%% -------------------------------------------------------------------- delete(Handle, Entry) when pid(Handle), list(Entry) -> send(Handle, {delete, Entry}), recv(Handle). %%% -------------------------------------------------------------------- %%% Modify an entry. Given an entry a number of modification %%% operations can be performed as one atomic operation. %%% Example: %%% %%% modify(Handle, %%% "cn=Torbjorn Tornkvist, ou=people, o=Bluetail AB, dc=bluetail, dc=com", %%% [replace("telephoneNumber", ["555 555 00"]), %%% add("description", ["LDAP hacker"])] %%% ) %%% -------------------------------------------------------------------- modify(Handle, Object, Mods) when pid(Handle), list(Object), list(Mods) -> send(Handle, {modify, Object, Mods}), recv(Handle). %%% %%% Modification operations. %%% Example: %%% replace("telephoneNumber", ["555 555 00"]) %%% mod_add(Type, Values) when list(Type), list(Values) -> m(add, Type, Values). mod_delete(Type, Values) when list(Type), list(Values) -> m(delete, Type, Values). mod_replace(Type, Values) when list(Type), list(Values) -> m(replace, Type, Values). m(Operation, Type, Values) -> #'ModifyRequest_modification_SEQOF'{ operation = Operation, modification = #'AttributeTypeAndValues'{ type = Type, vals = Values}}. %%% -------------------------------------------------------------------- %%% Modify an entry. Given an entry a number of modification %%% operations can be performed as one atomic operation. %%% Example: %%% %%% modify_dn(Handle, %%% "cn=Bill Valentine, ou=people, o=Bluetail AB, dc=bluetail, dc=com", %%% "cn=Ben Emerson", %%% true, %%% "" %%% ) %%% -------------------------------------------------------------------- modify_dn(Handle, Entry, NewRDN, DelOldRDN, NewSup) when pid(Handle),list(Entry),list(NewRDN),atom(DelOldRDN),list(NewSup) -> send(Handle, {modify_dn, Entry, NewRDN, bool_p(DelOldRDN), optional(NewSup)}), recv(Handle). %%% Sanity checks ! bool_p(Bool) when Bool==true;Bool==false -> Bool. optional([]) -> asn1_NOVALUE; optional(Value) -> Value. %%% -------------------------------------------------------------------- %%% Synchronous search of the Directory returning a %%% requested set of attributes. %%% %%% Example: %%% %%% Filter = eldap:substrings("sn", [{any,"o"}]), %%% eldap:search(S, [{base, "dc=bluetail, dc=com"}, %%% {filter, Filter}, %%% {attributes,["cn"]}])), %%% %%% Returned result: {ok, #eldap_search_result{}} %%% %%% Example: %%% %%% {ok,{eldap_search_result, %%% [{eldap_entry, %%% "cn=Magnus Froberg, dc=bluetail, dc=com", %%% [{"cn",["Magnus Froberg"]}]}, %%% {eldap_entry, %%% "cn=Torbjorn Tornkvist, dc=bluetail, dc=com", %%% [{"cn",["Torbjorn Tornkvist"]}]}], %%% []}} %%% %%% -------------------------------------------------------------------- search(Handle, A) when pid(Handle), record(A, eldap_search) -> call_search(Handle, A); search(Handle, L) when pid(Handle), list(L) -> case catch parse_search_args(L) of {error, Emsg} -> {error, Emsg}; A when record(A, eldap_search) -> call_search(Handle, A) end. call_search(Handle, A) -> send(Handle, {search, A}), recv(Handle). parse_search_args(Args) -> parse_search_args(Args, #eldap_search{scope = wholeSubtree}). parse_search_args([{base, Base}|T],A) -> parse_search_args(T,A#eldap_search{base = Base}); parse_search_args([{filter, Filter}|T],A) -> parse_search_args(T,A#eldap_search{filter = Filter}); parse_search_args([{scope, Scope}|T],A) -> parse_search_args(T,A#eldap_search{scope = Scope}); parse_search_args([{attributes, Attrs}|T],A) -> parse_search_args(T,A#eldap_search{attributes = Attrs}); parse_search_args([{types_only, TypesOnly}|T],A) -> parse_search_args(T,A#eldap_search{types_only = TypesOnly}); parse_search_args([{timeout, Timeout}|T],A) when integer(Timeout) -> parse_search_args(T,A#eldap_search{timeout = Timeout}); parse_search_args([H|_],_) -> throw({error,{unknown_arg, H}}); parse_search_args([],A) -> A. %%% %%% The Scope parameter %%% baseObject() -> baseObject. singleLevel() -> singleLevel. wholeSubtree() -> wholeSubtree. %%% %%% Boolean filter operations %%% 'and'(ListOfFilters) when list(ListOfFilters) -> {'and',ListOfFilters}. 'or'(ListOfFilters) when list(ListOfFilters) -> {'or', ListOfFilters}. 'not'(Filter) when tuple(Filter) -> {'not',Filter}. %%% %%% The following Filter parameters consist of an attribute %%% and an attribute value. Example: F("uid","tobbe") %%% equalityMatch(Desc, Value) -> {equalityMatch, av_assert(Desc, Value)}. greaterOrEqual(Desc, Value) -> {greaterOrEqual, av_assert(Desc, Value)}. lessOrEqual(Desc, Value) -> {lessOrEqual, av_assert(Desc, Value)}. approxMatch(Desc, Value) -> {approxMatch, av_assert(Desc, Value)}. av_assert(Desc, Value) -> #'AttributeValueAssertion'{attributeDesc = Desc, assertionValue = Value}. %%% %%% Filter to check for the presence of an attribute %%% present(Attribute) when list(Attribute) -> {present, Attribute}. %%% %%% A substring filter seem to be based on a pattern: %%% %%% InitValue*AnyValue*FinalValue %%% %%% where all three parts seem to be optional (at least when %%% talking with an OpenLDAP server). Thus, the arguments %%% to substrings/2 looks like this: %%% %%% Type ::= string( ) %%% SubStr ::= listof( {initial,Value} | {any,Value}, {final,Value}) %%% %%% Example: substrings("sn",[{initial,"To"},{any,"kv"},{final,"st"}]) %%% will match entries containing: 'sn: Tornkvist' %%% substrings(Type, SubStr) when list(Type), list(SubStr) -> Ss = {'SubstringFilter_substrings',v_substr(SubStr)}, {substrings,#'SubstringFilter'{type = Type, substrings = Ss}}. %%% -------------------------------------------------------------------- %%% Worker process. We keep track of a controlling process to %%% be able to terminate together with it. %%% -------------------------------------------------------------------- init(Hosts, Opts, Cpid) -> Data = parse_args(Opts, Cpid, #eldap{}), case try_connect(Hosts, Data) of {ok,Data2} -> send(Cpid, {ok,self()}), put(req_timeout, Data#eldap.timeout), % kludge... loop(Cpid, Data2); Else -> send(Cpid, Else), unlink(Cpid), exit(Else) end. parse_args([{port, Port}|T], Cpid, Data) when integer(Port) -> parse_args(T, Cpid, Data#eldap{port = Port}); parse_args([{timeout, Timeout}|T], Cpid, Data) when integer(Timeout),Timeout>0 -> parse_args(T, Cpid, Data#eldap{timeout = Timeout}); parse_args([{anon_auth, true}|T], Cpid, Data) -> parse_args(T, Cpid, Data#eldap{anon_auth = false}); parse_args([{anon_auth, _}|T], Cpid, Data) -> parse_args(T, Cpid, Data); parse_args([{ssl, true}|T], Cpid, Data) -> parse_args(T, Cpid, Data#eldap{use_tls = true}); parse_args([{ssl, _}|T], Cpid, Data) -> parse_args(T, Cpid, Data); parse_args([{log, F}|T], Cpid, Data) when function(F) -> parse_args(T, Cpid, Data#eldap{log = F}); parse_args([{log, _}|T], Cpid, Data) -> parse_args(T, Cpid, Data); parse_args([H|_], Cpid, _) -> send(Cpid, {error,{wrong_option,H}}), exit(wrong_option); parse_args([], _, Data) -> Data. %%% Try to connect to the hosts in the listed order, %%% and stop with the first one to which a successful %%% connection is made. try_connect([Host|Hosts], Data) -> TcpOpts = [{packet, asn1}, {active,false}], case do_connect(Host, Data, TcpOpts) of {ok,Fd} -> {ok,Data#eldap{host = Host, fd = Fd}}; _ -> try_connect(Hosts, Data) end; try_connect([],_) -> {error,"connect failed"}. do_connect(Host, Data, Opts) when Data#eldap.use_tls == false -> gen_tcp:connect(Host, Data#eldap.port, Opts, Data#eldap.timeout); do_connect(Host, Data, Opts) when Data#eldap.use_tls == true -> ssl:connect(Host, Data#eldap.port, [{verify,0}|Opts]). loop(Cpid, Data) -> receive {From, {search, A}} -> {Res,NewData} = do_search(Data, A), send(From,Res), loop(Cpid, NewData); {From, {modify, Obj, Mod}} -> {Res,NewData} = do_modify(Data, Obj, Mod), send(From,Res), loop(Cpid, NewData); {From, {modify_dn, Obj, NewRDN, DelOldRDN, NewSup}} -> {Res,NewData} = do_modify_dn(Data, Obj, NewRDN, DelOldRDN, NewSup), send(From,Res), loop(Cpid, NewData); {From, {add, Entry, Attrs}} -> {Res,NewData} = do_add(Data, Entry, Attrs), send(From,Res), loop(Cpid, NewData); {From, {delete, Entry}} -> {Res,NewData} = do_delete(Data, Entry), send(From,Res), loop(Cpid, NewData); {From, {simple_bind, Dn, Passwd}} -> {Res,NewData} = do_simple_bind(Data, Dn, Passwd), send(From,Res), loop(Cpid, NewData); {From, {cnt_proc, NewCpid}} -> unlink(Cpid), send(From,ok), ?PRINT("New Cpid is: ~p~n",[NewCpid]), loop(NewCpid, Data); {From, close} -> unlink(Cpid), exit(closed); {Cpid, 'EXIT', Reason} -> ?PRINT("Got EXIT from Cpid, reason=~p~n",[Reason]), exit(Reason); _XX -> ?PRINT("loop got: ~p~n",[_XX]), loop(Cpid, Data) end. %%% -------------------------------------------------------------------- %%% bindRequest %%% -------------------------------------------------------------------- %%% Authenticate ourselves to the directory using %%% simple authentication. do_simple_bind(Data, anon, anon) -> %% For testing do_the_simple_bind(Data, "", ""); do_simple_bind(Data, Dn, _Passwd) when Dn=="",Data#eldap.anon_auth==false -> {{error,anonymous_auth},Data}; do_simple_bind(Data, _Dn, Passwd) when Passwd=="",Data#eldap.anon_auth==false -> {{error,anonymous_auth},Data}; do_simple_bind(Data, Dn, Passwd) -> do_the_simple_bind(Data, Dn, Passwd). do_the_simple_bind(Data, Dn, Passwd) -> case catch exec_simple_bind(Data#eldap{binddn = Dn, passwd = Passwd, id = bump_id(Data)}) of {ok,NewData} -> {ok,NewData}; {error,Emsg} -> {{error,Emsg},Data}; Else -> {{error,Else},Data} end. exec_simple_bind(Data) -> Req = #'BindRequest'{version = Data#eldap.version, name = Data#eldap.binddn, authentication = {simple, Data#eldap.passwd}}, log2(Data, "bind request = ~p~n", [Req]), Reply = request(Data#eldap.fd, Data, Data#eldap.id, {bindRequest, Req}), log2(Data, "bind reply = ~p~n", [Reply]), exec_simple_bind_reply(Data, Reply). exec_simple_bind_reply(Data, {ok,Msg}) when Msg#'LDAPMessage'.messageID == Data#eldap.id -> case Msg#'LDAPMessage'.protocolOp of {bindResponse, Result} -> case Result#'BindResponse'.resultCode of success -> {ok,Data}; Error -> {error, Error} end; Other -> {error, Other} end; exec_simple_bind_reply(_, Error) -> {error, Error}. %%% -------------------------------------------------------------------- %%% searchRequest %%% -------------------------------------------------------------------- do_search(Data, A) -> case catch do_search_0(Data, A) of {error,Emsg} -> {ldap_closed_p(Data, Emsg),Data}; {'EXIT',Error} -> {ldap_closed_p(Data, Error),Data}; {ok,Res,Ref,NewData} -> {{ok,polish(Res, Ref)},NewData}; Else -> {ldap_closed_p(Data, Else),Data} end. %%% %%% Polish the returned search result %%% polish(Res, Ref) -> R = polish_result(Res), %%% No special treatment of referrals at the moment. #eldap_search_result{entries = R, referrals = Ref}. polish_result([H|T]) when record(H, 'SearchResultEntry') -> ObjectName = H#'SearchResultEntry'.objectName, F = fun({_,A,V}) -> {A,V} end, Attrs = lists:map(F, H#'SearchResultEntry'.attributes), [#eldap_entry{object_name = ObjectName, attributes = Attrs}| polish_result(T)]; polish_result([]) -> []. do_search_0(Data, A) -> Req = #'SearchRequest'{baseObject = A#eldap_search.base, scope = v_scope(A#eldap_search.scope), derefAliases = neverDerefAliases, sizeLimit = 0, % no size limit timeLimit = v_timeout(A#eldap_search.timeout), typesOnly = v_bool(A#eldap_search.types_only), filter = v_filter(A#eldap_search.filter), attributes = v_attributes(A#eldap_search.attributes) }, Id = bump_id(Data), collect_search_responses(Data#eldap{id=Id}, Req, Id). %%% The returned answers cames in one packet per entry %%% mixed with possible referals collect_search_responses(Data, Req, ID) -> S = Data#eldap.fd, log2(Data, "search request = ~p~n", [Req]), send_request(S, Data, ID, {searchRequest, Req}), Resp = recv_response(S, Data), log2(Data, "search reply = ~p~n", [Resp]), collect_search_responses(Data, S, ID, Resp, [], []). collect_search_responses(Data, S, ID, {ok,Msg}, Acc, Ref) when record(Msg,'LDAPMessage') -> case Msg#'LDAPMessage'.protocolOp of {'searchResDone',R} when R#'LDAPResult'.resultCode == success -> log2(Data, "search reply = searchResDone ~n", []), {ok,Acc,Ref,Data}; {'searchResEntry',R} when record(R,'SearchResultEntry') -> Resp = recv_response(S, Data), log2(Data, "search reply = ~p~n", [Resp]), collect_search_responses(Data, S, ID, Resp, [R|Acc], Ref); {'searchResRef',R} -> %% At the moment we don't do anyting sensible here since %% I haven't been able to trigger the server to generate %% a response like this. Resp = recv_response(S, Data), log2(Data, "search reply = ~p~n", [Resp]), collect_search_responses(Data, S, ID, Resp, Acc, [R|Ref]); Else -> throw({error,Else}) end; collect_search_responses(_, _, _, Else, _, _) -> throw({error,Else}). %%% -------------------------------------------------------------------- %%% addRequest %%% -------------------------------------------------------------------- do_add(Data, Entry, Attrs) -> case catch do_add_0(Data, Entry, Attrs) of {error,Emsg} -> {ldap_closed_p(Data, Emsg),Data}; {'EXIT',Error} -> {ldap_closed_p(Data, Error),Data}; {ok,NewData} -> {ok,NewData}; Else -> {ldap_closed_p(Data, Else),Data} end. do_add_0(Data, Entry, Attrs) -> Req = #'AddRequest'{entry = Entry, attributes = Attrs}, S = Data#eldap.fd, Id = bump_id(Data), log2(Data, "add request = ~p~n", [Req]), Resp = request(S, Data, Id, {addRequest, Req}), log2(Data, "add reply = ~p~n", [Resp]), check_reply(Data#eldap{id = Id}, Resp, addResponse). %%% -------------------------------------------------------------------- %%% deleteRequest %%% -------------------------------------------------------------------- do_delete(Data, Entry) -> case catch do_delete_0(Data, Entry) of {error,Emsg} -> {ldap_closed_p(Data, Emsg),Data}; {'EXIT',Error} -> {ldap_closed_p(Data, Error),Data}; {ok,NewData} -> {ok,NewData}; Else -> {ldap_closed_p(Data, Else),Data} end. do_delete_0(Data, Entry) -> S = Data#eldap.fd, Id = bump_id(Data), log2(Data, "del request = ~p~n", [Entry]), Resp = request(S, Data, Id, {delRequest, Entry}), log2(Data, "del reply = ~p~n", [Resp]), check_reply(Data#eldap{id = Id}, Resp, delResponse). %%% -------------------------------------------------------------------- %%% modifyRequest %%% -------------------------------------------------------------------- do_modify(Data, Obj, Mod) -> case catch do_modify_0(Data, Obj, Mod) of {error,Emsg} -> {ldap_closed_p(Data, Emsg),Data}; {'EXIT',Error} -> {ldap_closed_p(Data, Error),Data}; {ok,NewData} -> {ok,NewData}; Else -> {ldap_closed_p(Data, Else),Data} end. do_modify_0(Data, Obj, Mod) -> v_modifications(Mod), Req = #'ModifyRequest'{object = Obj, modification = Mod}, S = Data#eldap.fd, Id = bump_id(Data), log2(Data, "modify request = ~p~n", [Req]), Resp = request(S, Data, Id, {modifyRequest, Req}), log2(Data, "modify reply = ~p~n", [Resp]), check_reply(Data#eldap{id = Id}, Resp, modifyResponse). %%% -------------------------------------------------------------------- %%% modifyDNRequest %%% -------------------------------------------------------------------- do_modify_dn(Data, Entry, NewRDN, DelOldRDN, NewSup) -> case catch do_modify_dn_0(Data, Entry, NewRDN, DelOldRDN, NewSup) of {error,Emsg} -> {ldap_closed_p(Data, Emsg),Data}; {'EXIT',Error} -> {ldap_closed_p(Data, Error),Data}; {ok,NewData} -> {ok,NewData}; Else -> {ldap_closed_p(Data, Else),Data} end. do_modify_dn_0(Data, Entry, NewRDN, DelOldRDN, NewSup) -> Req = #'ModifyDNRequest'{entry = Entry, newrdn = NewRDN, deleteoldrdn = DelOldRDN, newSuperior = NewSup}, S = Data#eldap.fd, Id = bump_id(Data), log2(Data, "modify DN request = ~p~n", [Req]), Resp = request(S, Data, Id, {modDNRequest, Req}), log2(Data, "modify DN reply = ~p~n", [Resp]), check_reply(Data#eldap{id = Id}, Resp, modDNResponse). %%% -------------------------------------------------------------------- %%% Send an LDAP request and receive the answer %%% -------------------------------------------------------------------- request(S, Data, ID, Request) -> send_request(S, Data, ID, Request), recv_response(S, Data). send_request(S, Data, ID, Request) -> Message = #'LDAPMessage'{messageID = ID, protocolOp = Request}, {ok,Bytes} = asn1rt:encode('ELDAPv3', 'LDAPMessage', Message), case do_send(S, Data, Bytes) of {error,Reason} -> throw({gen_tcp_error,Reason}); Else -> Else end. do_send(S, Data, Bytes) when Data#eldap.use_tls == false -> gen_tcp:send(S, Bytes); do_send(S, Data, Bytes) when Data#eldap.use_tls == true -> ssl:send(S, Bytes). do_recv(S, Data, Len, Timeout) when Data#eldap.use_tls == false -> gen_tcp:recv(S, Len, Timeout); do_recv(S, Data, Len, Timeout) when Data#eldap.use_tls == true -> ssl:recv(S, Len, Timeout). recv_response(S, Data) -> Timeout = get(req_timeout), % kludge... case do_recv(S, Data, 0, Timeout) of {ok, Packet} -> check_tag(Packet), case asn1rt:decode('ELDAPv3', 'LDAPMessage', Packet) of {ok,Resp} -> {ok,Resp}; Error -> throw(Error) end; {error,Reason} -> throw({gen_tcp_error, Reason}); Error -> throw(Error) end. %%% Sanity check of received packet check_tag(Data) -> case asn1rt_ber_bin:decode_tag(b2l(Data)) of {_Tag, Data1, _Rb} -> case asn1rt_ber_bin:decode_length(b2l(Data1)) of {{_Len, _Data2}, _Rb2} -> ok; _ -> throw({error,decoded_tag_length}) end; _ -> throw({error,decoded_tag}) end. %%% Check for expected kind of reply check_reply(Data, {ok,Msg}, Op) when Msg#'LDAPMessage'.messageID == Data#eldap.id -> case Msg#'LDAPMessage'.protocolOp of {Op, Result} -> case Result#'LDAPResult'.resultCode of success -> {ok,Data}; Error -> {error, Error} end; Other -> {error, Other} end; check_reply(_, Error, _) -> {error, Error}. %%% -------------------------------------------------------------------- %%% Verify the input data %%% -------------------------------------------------------------------- v_filter({'and',L}) -> {'and',L}; v_filter({'or', L}) -> {'or',L}; v_filter({'not',L}) -> {'not',L}; v_filter({equalityMatch,AV}) -> {equalityMatch,AV}; v_filter({greaterOrEqual,AV}) -> {greaterOrEqual,AV}; v_filter({lessOrEqual,AV}) -> {lessOrEqual,AV}; v_filter({approxMatch,AV}) -> {approxMatch,AV}; v_filter({present,A}) -> {present,A}; v_filter({substrings,S}) when record(S,'SubstringFilter') -> {substrings,S}; v_filter(_Filter) -> throw({error,concat(["unknown filter: ",_Filter])}). v_modifications(Mods) -> F = fun({_,Op,_}) -> case lists:member(Op,[add,delete,replace]) of true -> true; _ -> throw({error,{mod_operation,Op}}) end end, lists:foreach(F, Mods). v_substr([{Key,Str}|T]) when list(Str),Key==initial;Key==any;Key==final -> [{Key,Str}|v_substr(T)]; v_substr([H|_]) -> throw({error,{substring_arg,H}}); v_substr([]) -> []. v_scope(baseObject) -> baseObject; v_scope(singleLevel) -> singleLevel; v_scope(wholeSubtree) -> wholeSubtree; v_scope(_Scope) -> throw({error,concat(["unknown scope: ",_Scope])}). v_bool(true) -> true; v_bool(false) -> false; v_bool(_Bool) -> throw({error,concat(["not Boolean: ",_Bool])}). v_timeout(I) when integer(I), I>=0 -> I; v_timeout(_I) -> throw({error,concat(["timeout not positive integer: ",_I])}). v_attributes(Attrs) -> F = fun(A) when list(A) -> A; (A) -> throw({error,concat(["attribute not String: ",A])}) end, lists:map(F,Attrs). %%% -------------------------------------------------------------------- %%% Log routines. Call a user provided log routine F. %%% -------------------------------------------------------------------- log1(Data, Str, Args) -> log(Data, Str, Args, 1). log2(Data, Str, Args) -> log(Data, Str, Args, 2). log(Data, Str, Args, Level) when function(Data#eldap.log) -> catch (Data#eldap.log)(Level, Str, Args); log(_, _, _, _) -> ok. %%% -------------------------------------------------------------------- %%% Misc. routines %%% -------------------------------------------------------------------- send(To,Msg) -> To ! {self(),Msg}. recv(From) -> receive {From,Msg} -> Msg end. ldap_closed_p(Data, Emsg) when Data#eldap.use_tls == true -> %% Check if the SSL socket seems to be alive or not case catch ssl:sockname(Data#eldap.fd) of {error, _} -> ssl:close(Data#eldap.fd), {error, ldap_closed}; {ok, _} -> {error, Emsg}; _ -> %% sockname crashes if the socket pid is not alive {error, ldap_closed} end; ldap_closed_p(Data, Emsg) -> %% non-SSL socket case inet:port(Data#eldap.fd) of {error,_} -> {error, ldap_closed}; _ -> {error,Emsg} end. bump_id(Data) -> Data#eldap.id + 1. %%% -------------------------------------------------------------------- %%% parse_dn/1 - Implementation of RFC 2253: %%% %%% "UTF-8 String Representation of Distinguished Names" %%% %%% Test cases: %%% %%% The simplest case: %%% %%% 1> eldap:parse_dn("CN=Steve Kille,O=Isode Limited,C=GB"). %%% {ok,[[{attribute_type_and_value,"CN","Steve Kille"}], %%% [{attribute_type_and_value,"O","Isode Limited"}], %%% [{attribute_type_and_value,"C","GB"}]]} %%% %%% The first RDN is multi-valued: %%% %%% 2> eldap:parse_dn("OU=Sales+CN=J. Smith,O=Widget Inc.,C=US"). %%% {ok,[[{attribute_type_and_value,"OU","Sales"}, %%% {attribute_type_and_value,"CN","J. Smith"}], %%% [{attribute_type_and_value,"O","Widget Inc."}], %%% [{attribute_type_and_value,"C","US"}]]} %%% %%% Quoting a comma: %%% %%% 3> eldap:parse_dn("CN=L. Eagle,O=Sue\\, Grabbit and Runn,C=GB"). %%% {ok,[[{attribute_type_and_value,"CN","L. Eagle"}], %%% [{attribute_type_and_value,"O","Sue\\, Grabbit and Runn"}], %%% [{attribute_type_and_value,"C","GB"}]]} %%% %%% A value contains a carriage return: %%% %%% 4> eldap:parse_dn("CN=Before %%% 4> After,O=Test,C=GB"). %%% {ok,[[{attribute_type_and_value,"CN","Before\nAfter"}], %%% [{attribute_type_and_value,"O","Test"}], %%% [{attribute_type_and_value,"C","GB"}]]} %%% %%% 5> eldap:parse_dn("CN=Before\\0DAfter,O=Test,C=GB"). %%% {ok,[[{attribute_type_and_value,"CN","Before\\0DAfter"}], %%% [{attribute_type_and_value,"O","Test"}], %%% [{attribute_type_and_value,"C","GB"}]]} %%% %%% An RDN in OID form: %%% %%% 6> eldap:parse_dn("1.3.6.1.4.1.1466.0=#04024869,O=Test,C=GB"). %%% {ok,[[{attribute_type_and_value,"1.3.6.1.4.1.1466.0","#04024869"}], %%% [{attribute_type_and_value,"O","Test"}], %%% [{attribute_type_and_value,"C","GB"}]]} %%% %%% %%% -------------------------------------------------------------------- parse_dn("") -> % empty DN string {ok,[]}; parse_dn([H|_] = Str) when H=/=$, -> % 1:st name-component ! case catch parse_name(Str,[]) of {'EXIT',Reason} -> {parse_error,internal_error,Reason}; Else -> Else end. parse_name("",Acc) -> {ok,lists:reverse(Acc)}; parse_name([$,|T],Acc) -> % N:th name-component ! parse_name(T,Acc); parse_name(Str,Acc) -> {Rest,NameComponent} = parse_name_component(Str), parse_name(Rest,[NameComponent|Acc]). parse_name_component(Str) -> parse_name_component(Str,[]). parse_name_component(Str,Acc) -> case parse_attribute_type_and_value(Str) of {[$+|Rest], ATV} -> parse_name_component(Rest,[ATV|Acc]); {Rest,ATV} -> {Rest,lists:reverse([ATV|Acc])} end. parse_attribute_type_and_value(Str) -> case parse_attribute_type(Str) of {Rest,[]} -> error(expecting_attribute_type,Str); {Rest,Type} -> Rest2 = parse_equal_sign(Rest), {Rest3,Value} = parse_attribute_value(Rest2), {Rest3,{attribute_type_and_value,Type,Value}} end. -define(IS_ALPHA(X) , X>=$a,X=<$z;X>=$A,X=<$Z ). -define(IS_DIGIT(X) , X>=$0,X=<$9 ). -define(IS_SPECIAL(X) , X==$,;X==$=;X==$+;X==$<;X==$>;X==$#;X==$; ). -define(IS_QUOTECHAR(X) , X=/=$\\,X=/=$" ). -define(IS_STRINGCHAR(X) , X=/=$,,X=/=$=,X=/=$+,X=/=$<,X=/=$>,X=/=$#,X=/=$;,?IS_QUOTECHAR(X) ). -define(IS_HEXCHAR(X) , ?IS_DIGIT(X);X>=$a,X=<$f;X>=$A,X=<$F ). parse_attribute_type([H|T]) when ?IS_ALPHA(H) -> %% NB: It must be an error in the RFC in the definition %% of 'attributeType', should be: (ALPHA *keychar) {Rest,KeyChars} = parse_keychars(T), {Rest,[H|KeyChars]}; parse_attribute_type([H|_] = Str) when ?IS_DIGIT(H) -> parse_oid(Str); parse_attribute_type(Str) -> error(invalid_attribute_type,Str). %%% Is a hexstring ! parse_attribute_value([$#,X,Y|T]) when ?IS_HEXCHAR(X),?IS_HEXCHAR(Y) -> {Rest,HexString} = parse_hexstring(T), {Rest,[$#,X,Y|HexString]}; %%% Is a "quotation-sequence" ! parse_attribute_value([$"|T]) -> {Rest,Quotation} = parse_quotation(T), {Rest,[$"|Quotation]}; %%% Is a stringchar , pair or Empty ! parse_attribute_value(Str) -> parse_string(Str). parse_hexstring(Str) -> parse_hexstring(Str,[]). parse_hexstring([X,Y|T],Acc) when ?IS_HEXCHAR(X),?IS_HEXCHAR(Y) -> parse_hexstring(T,[Y,X|Acc]); parse_hexstring(T,Acc) -> {T,lists:reverse(Acc)}. parse_quotation([$"|T]) -> % an empty: "" is ok ! {T,[$"]}; parse_quotation(Str) -> parse_quotation(Str,[]). %%% Parse to end of quotation parse_quotation([$"|T],Acc) -> {T,lists:reverse([$"|Acc])}; parse_quotation([X|T],Acc) when ?IS_QUOTECHAR(X) -> parse_quotation(T,[X|Acc]); parse_quotation([$\\,X|T],Acc) when ?IS_SPECIAL(X) -> parse_quotation(T,[X,$\\|Acc]); parse_quotation([$\\,$\\|T],Acc) -> parse_quotation(T,[$\\,$\\|Acc]); parse_quotation([$\\,$"|T],Acc) -> parse_quotation(T,[$",$\\|Acc]); parse_quotation([$\\,X,Y|T],Acc) when ?IS_HEXCHAR(X),?IS_HEXCHAR(Y) -> parse_quotation(T,[Y,X,$\\|Acc]); parse_quotation(T,_) -> error(expecting_double_quote_mark,T). parse_string(Str) -> parse_string(Str,[]). parse_string("",Acc) -> {"",lists:reverse(Acc)}; parse_string([H|T],Acc) when ?IS_STRINGCHAR(H) -> parse_string(T,[H|Acc]); parse_string([$\\,X|T],Acc) when ?IS_SPECIAL(X) -> % is a pair ! parse_string(T,[X,$\\|Acc]); parse_string([$\\,$\\|T],Acc) -> % is a pair ! parse_string(T,[$\\,$\\|Acc]); parse_string([$\\,$" |T],Acc) -> % is a pair ! parse_string(T,[$" ,$\\|Acc]); parse_string([$\\,X,Y|T],Acc) when ?IS_HEXCHAR(X),?IS_HEXCHAR(Y) -> % is a pair! parse_string(T,[Y,X,$\\|Acc]); parse_string(T,Acc) -> {T,lists:reverse(Acc)}. parse_equal_sign([$=|T]) -> T; parse_equal_sign(T) -> error(expecting_equal_sign,T). parse_keychars(Str) -> parse_keychars(Str,[]). parse_keychars([H|T],Acc) when ?IS_ALPHA(H) -> parse_keychars(T,[H|Acc]); parse_keychars([H|T],Acc) when ?IS_DIGIT(H) -> parse_keychars(T,[H|Acc]); parse_keychars([$-|T],Acc) -> parse_keychars(T,[$-|Acc]); parse_keychars(T,Acc) -> {T,lists:reverse(Acc)}. parse_oid(Str) -> parse_oid(Str,[]). parse_oid([H,$.|T], Acc) when ?IS_DIGIT(H) -> parse_oid(T,[$.,H|Acc]); parse_oid([H|T], Acc) when ?IS_DIGIT(H) -> parse_oid(T,[H|Acc]); parse_oid(T, Acc) -> {T,lists:reverse(Acc)}. error(Emsg,Rest) -> throw({parse_error,Emsg,Rest}). %%% -------------------------------------------------------------------- %%% Parse LDAP url according to RFC 2255 %%% %%% Test case: %%% %%% 2> eldap:parse_ldap_url("ldap://10.42.126.33:389/cn=Administrative%20CA,o=Post%20Danmark,c=DK?certificateRevokationList;binary"). %%% {ok,{{10,42,126,33},389}, %%% [[{attribute_type_and_value,"cn","Administrative%20CA"}], %%% [{attribute_type_and_value,"o","Post%20Danmark"}], %%% [{attribute_type_and_value,"c","DK"}]], %%% {attributes,["certificateRevokationList;binary"]}} %%% %%% -------------------------------------------------------------------- parse_ldap_url("ldap://" ++ Rest1 = Str) -> {Rest2,HostPort} = parse_hostport(Rest1), %% Split the string into DN and Attributes+etc {Sdn,Rest3} = split_string(rm_leading_slash(Rest2),$?), case parse_dn(Sdn) of {parse_error,internal_error,_Reason} -> {parse_error,internal_error,{Str,[]}}; {parse_error,Emsg,Tail} -> Head = get_head(Str,Tail), {parse_error,Emsg,{Head,Tail}}; {ok,DN} -> %% We stop parsing here for now and leave %% 'scope', 'filter' and 'extensions' to %% be implemented later if needed. {_Rest4,Attributes} = parse_attributes(Rest3), {ok,HostPort,DN,Attributes} end. rm_leading_slash([$/|Tail]) -> Tail; rm_leading_slash(Tail) -> Tail. parse_attributes([$?|Tail]) -> case split_string(Tail,$?) of {[],Attributes} -> {[],{attributes,string:tokens(Attributes,",")}}; {Attributes,Rest} -> {Rest,{attributes,string:tokens(Attributes,",")}} end. parse_hostport(Str) -> {HostPort,Rest} = split_string(Str,$/), case split_string(HostPort,$:) of {Shost,[]} -> {Rest,{parse_host(Rest,Shost),?LDAP_PORT}}; {Shost,[$:|Sport]} -> {Rest,{parse_host(Rest,Shost), parse_port(Rest,Sport)}} end. parse_port(Rest,Sport) -> case list_to_integer(Sport) of Port when integer(Port) -> Port; _ -> error(parsing_port,Rest) end. parse_host(Rest,Shost) -> case catch validate_host(Shost) of {parse_error,Emsg,_} -> error(Emsg,Rest); Host -> Host end. validate_host(Shost) -> case inet_parse:address(Shost) of {ok,Host} -> Host; _ -> case inet_parse:domain(Shost) of true -> Shost; _ -> error(parsing_host,Shost) end end. split_string(Str,Key) -> Pred = fun(X) when X==Key -> false; (_) -> true end, lists:splitwith(Pred, Str). get_head(Str,Tail) -> get_head(Str,Tail,[]). %%% Should always succeed ! get_head([H|Tail],Tail,Rhead) -> lists:reverse([H|Rhead]); get_head([H|Rest],Tail,Rhead) -> get_head(Rest,Tail,[H|Rhead]). b2l(B) when binary(B) -> B; b2l(L) when list(L) -> list_to_binary(L). rabbitmq-server-3.2.4/plugins-src/eldap-wrapper/eldap-git/README0000644000000000000000000000227212305126066023066 0ustar rootrootHi, This is 'eldap', the Erlang LDAP library. It exports an API that can do all possible operations you may want to do against an LDAP server. The code has been tested to work at some point, but only the bind and search operations are running daily in our products, so there may be bugs lurking in some parts of the code. To just use eldap for doing authentication, do like in: {ok,X} = eldap:open(["ldap.mycorp.com"], []). eldap:simple_bind(X, "uid=tobbe,ou=People,dc=mycorp,dc=com", "passwd"). In the doc/README.example you'll find a trace from a Erlang shell session as an example on how to setup a connection, authenticate (bind) and perform a search. Note that by using the option {ssl, true}, you should be able to setup an SSL tunnel (LDAPS) if your Erlang system has been configured with SSL. In the test directory there are some hints and examples on how to test the code and how to setup and populate an OpenLDAP server. The 'eldap' code has been tested agains OpenLDAP, IPlanet and ActiveDirectory servers. If you plan to incorporate this code into your system I suggest that you build a server/supervisor harnesk that uses 'eldap' (as we have done in our products). Good luck ! /Tobbe rabbitmq-server-3.2.4/plugins-src/eldap-wrapper/eldap-git/doc/0000755000000000000000000000000012305126066022750 5ustar rootrootrabbitmq-server-3.2.4/plugins-src/eldap-wrapper/eldap-git/doc/short-desc0000644000000000000000000000005312305126066024744 0ustar rootrootThis is 'eldap', the Erlang LDAP library. rabbitmq-server-3.2.4/plugins-src/eldap-wrapper/eldap-git/doc/README.example0000644000000000000000000000455712305126066025275 0ustar rootroot1> {_,S} = eldap:open(["192.168.128.47"], []). {ok,<0.30.0>} 2> eldap:simple_bind(S,"cn=Torbjorn Tornkvist,cn=Users,dc=bluetail,dc=com","qwe123"). ok 3> Base = {base, "dc=bluetail,dc=com"}. {base,"dc=bluetail,dc=com"} 4> Scope = {scope, eldap:wholeSubtree()}. {scope,wholeSubtree} 5> Filter = {filter, eldap:equalityMatch("sAMAccountName", "tobbe")}. {filter,{equalityMatch,{'AttributeValueAssertion',"sAMAccountName","tobbe"}}} 6> Search = [Base, Scope, Filter]. [{base,"dc=bluetail,dc=com"}, {scope,wholeSubtree}, {filter,{equalityMatch,{'AttributeValueAssertion',"sAMAccountName","tobbe"}}}] 7> eldap:search(S, Search). {ok,{eldap_search_result,[{eldap_entry, "CN=Torbjorn Tornkvist,CN=Users,DC=bluetail,DC=com", [{"manager", ["CN=Tord Larsson,CN=Users,DC=bluetail,DC=com"]}, {"memberOf", ["CN=TestGroup2,CN=Users,DC=bluetail,DC=com", "CN=TestGroup,CN=Users,DC=bluetail,DC=com", "CN=Pre-Windows 2000 Compatible Access,CN=Builtin,DC=bluetail,DC=com", "CN=Server Operators,CN=Builtin,DC=bluetail,DC=com"]}, {"accountExpires",["0"]}, {"adminCount",["1"]}, {"badPasswordTime",["127119104851642448"]}, {"badPwdCount",["0"]}, {"codePage",["0"]}, {"cn",["Torbjorn Tornkvist"]}, {"company",["Alteon Web Systems"]}, {"countryCode",["0"]}, {"department",["Bluetail"]}, {"displayName",["Torbjorn Tornkvist"]}, {"mail",["tobbe@bluetail.com"]}, {"givenName",["Torbjorn"]}, {"instanceType",["4"]}, {"lastLogoff",["0"]}, {"lastLogon",["127119109376267104"]}, {"logonCount",[...]}, {"msNPAllowDialin"|...}, {...}|...]}], [["ldap://bluetail.com/CN=Configuration,DC=bluetail,DC=com"]]}} 8> rabbitmq-server-3.2.4/plugins-src/eldap-wrapper/eldap-git/test/0000755000000000000000000000000012305126066023162 5ustar rootrootrabbitmq-server-3.2.4/plugins-src/eldap-wrapper/eldap-git/test/bluetail.ldif0000644000000000000000000000050212305126066025620 0ustar rootrootdn: dc=bluetail, dc=com objectclass: dcObject dc: bluetail dn: o=Bluetail AB, dc=bluetail, dc=com objectclass: organization o: Bluetail AB street: St.Eriksgatan 44 postalCode: 112 34 dn: ou=people, o=Bluetail AB, dc=bluetail, dc=com objectclass: organizationalUnit ou: people description: People working at Bluetail rabbitmq-server-3.2.4/plugins-src/eldap-wrapper/eldap-git/test/README.test0000644000000000000000000000523212305126066025022 0ustar rootroot%%% $Id$ %%% -------------------------------------------------------------------- %%% Init setup %%% -------------------------------------------------------------------- I set up the OpenLDAP (2.0.6) server using the following /usr/local/etc/openldap/slapd.conf file: include /usr/local/etc/openldap/schema/core.schema pidfile /var/run/slapd.pid argsfile /var/run/slapd.args database ldbm suffix "dc=bluetail, dc=com" rootdn "dc=bluetail, dc=com" rootpw hejsan directory /usr/local/var/openldap-ldbm index objectClass eq %%% I started it on the console with some debug output: /usr/local/libexec/slapd -d 255 -f /usr/local/etc/openldap/slapd.conf %%% Then I defined the following data in: bluetail.ldif dn: dc=bluetail, dc=com objectclass: organization objectclass: dcObject dc: bluetail o: Bluetail AB %%% and in: tobbe.ldif dn: cn=Torbjorn Tornkvist, dc=bluetail, dc=com objectclass: person cn: Torbjorn Tornkvist sn: Tornkvist %%% I load the data with: ldapadd -D "dc=bluetail, dc=com" -w hejsan < bluetail.ldif ldapadd -D "dc=bluetail, dc=com" -w hejsan < people.ldif %%%% To search from a Unix shell: ldapsearch -L -b "dc=bluetail, dc=com" -w hejsan "(objectclass=*)" ldapsearch -L -b "dc=bluetail, dc=com" -w hejsan "cn=Torbjorn Tornkvist" ldapsearch -L -b "dc=bluetail, dc=com" -w hejsan "cn=Torb*kvist" %%% -------------------------------------------------------------------- %%% Example with certificateRevocationList %%% -------------------------------------------------------------------- %%% Using two ldif files: %%% post_danmark.ldif dn: o=Post Danmark, c=DK objectclass: country objectclass: organization c: DK o: Post Danmark %%% crl.ldif dn: cn=Administrative CA, o=Post Danmark, c=DK objectclass: cRLDistributionPoint cn: Administrative CA certificateRevocationList;binary:< file:/home/tobbe/erlang/eldap/server1.crl %%% Note the definition of the CRL file !! %%% To add the difinitions ldapadd -D "o=Post Danmark, c=DK" -w hejsan < post_danmark.ldif ldapadd -D "o=Post Danmark, c=DK" -w hejsan < crl.ldif %%% And to retreive the CRL ldapsearch -L -b "o=Post Danmark, c=DK" -w hejsan "(objectclass=*)" ldapsearch -L -b "o=Post Danmark, c=DK" -w hejsan "(cn=Administrative CA)" \ certificateRevocationList ### Put the retrieved binary in a file (tmp) with ### the following header and footer -----BEGIN X509 CRL----- <...binary....> -----END X509 CRL----- ### To verify it with openssl openssl crl -inform PEM -in tmp -text ldapsearch -L -D "cn=Torbjorn Tornkvist,o=Post Danmark,c=DK" -b "o=Post Danmark, c=DK" -w qwe123 "(cn=Torbjorn Tornkvist)" cn rabbitmq-server-3.2.4/plugins-src/eldap-wrapper/eldap-git/test/post_danmark.ldif0000644000000000000000000000013512305126066026503 0ustar rootrootdn: o=Post Danmark,c=DK objectclass: country objectclass: organization c: DK o: Post Danmark rabbitmq-server-3.2.4/plugins-src/eldap-wrapper/eldap-git/test/ldap.rc0000644000000000000000000000406212305126066024432 0ustar rootroot#!/bin/sh # # ldap This shell script takes care of starting and stopping # ldap servers (slapd and slurpd). # # chkconfig: - 39 61 # description: LDAP stands for Lightweight Directory Access Protocol, used \ # for implementing the industry standard directory services. # processname: slapd # config: /etc/openldap/slapd.conf # pidfile: /var/run/slapd.pid # Source function library. . /etc/init.d/functions # Source networking configuration and check that networking is up. if [ -r /etc/sysconfig/network ] ; then . /etc/sysconfig/network [ ${NETWORKING} = "no" ] && exit 0 fi slapd=/usr/sbin/slapd slurpd=/usr/sbin/slurpd [ -x ${slapd} ] || exit 0 [ -x ${slurpd} ] || exit 0 RETVAL=0 function start() { # Start daemons. echo -n "Starting slapd:" daemon ${slapd} RETVAL=$? echo if [ $RETVAL -eq 0 ]; then if grep -q "^replogfile" /etc/openldap/slapd.conf; then echo -n "Starting slurpd:" daemon ${slurpd} RETVAL=$? echo fi fi [ $RETVAL -eq 0 ] && touch /var/lock/subsys/ldap return $RETVAL } function stop() { # Stop daemons. echo -n "Shutting down ldap: " killproc ${slapd} RETVAL=$? if [ $RETVAL -eq 0 ]; then if grep -q "^replogfile" /etc/openldap/slapd.conf; then killproc ${slurpd} RETVAL=$? fi fi echo [ $RETVAL -eq 0 ] && rm -f /var/lock/subsys/ldap /var/run/slapd.args return $RETVAL } # See how we were called. case "$1" in start) start ;; stop) stop ;; status) status ${slapd} if grep -q "^replogfile" /etc/openldap/slapd.conf ; then status ${slurpd} fi ;; restart) stop start ;; reload) killall -HUP ${slapd} RETVAL=$? if [ $RETVAL -eq 0 ]; then if grep -q "^replogfile" /etc/openldap/slapd.conf; then killall -HUP ${slurpd} RETVAL=$? fi fi ;; condrestart) if [ -f /var/lock/subsys/ldap ] ; then stop start fi ;; *) echo "Usage: $0 start|stop|restart|status|condrestart}" RETVAL=1 esac exit $RETVAL rabbitmq-server-3.2.4/plugins-src/eldap-wrapper/eldap-git/test/tobbe.ldif0000644000000000000000000000017512305126066025120 0ustar rootrootdn: cn=Torbjorn Tornkvist,o=Post Danmark,c=DK objectclass: person cn: Torbjorn Tornkvist sn: Tornkvist userPassword: qwe123 rabbitmq-server-3.2.4/plugins-src/eldap-wrapper/eldap-git/test/slapd.conf0000644000000000000000000000257012305126066025140 0ustar rootroot# $OpenLDAP: pkg/ldap/servers/slapd/slapd.conf,v 1.8.8.4 2000/08/26 17:06:18 kurt Exp $ # # See slapd.conf(5) for details on configuration options. # This file should NOT be world readable. # include /usr/etc/openldap/schema/core.schema # Define global ACLs to disable default read access. # Do not enable referrals until AFTER you have a working directory # service AND an understanding of referrals. #referral ldap://root.openldap.org pidfile /var/run/slapd.pid argsfile /var/run/slapd.args # Load dynamic backend modules: # modulepath /usr/libexec/openldap # moduleload back_ldap.la # moduleload back_ldbm.la # moduleload back_passwd.la # moduleload back_shell.la ####################################################################### # ldbm database definitions ####################################################################### database ldbm suffix "dc=bluetail, dc=com" #suffix "o=My Organization Name, c=US" rootdn "dc=bluetail, dc=com" #rootdn "cn=Manager, o=My Organization Name, c=US" # Cleartext passwords, especially for the rootdn, should # be avoid. See slappasswd(8) and slapd.conf(5) for details. # Use of strong authentication encouraged. rootpw hejsan # The database directory MUST exist prior to running slapd AND # should only be accessable by the slapd/tools. Mode 700 recommended. directory /usr/var/openldap-ldbm # Indices to maintain index objectClass eq rabbitmq-server-3.2.4/plugins-src/eldap-wrapper/eldap-git/test/server1.crl0000644000000000000000000013374312305126066025266 0ustar rootroot0‚·ß0‚·H0  *†H†÷ 0Ã1 0 UUS10U  Entrust.net1;09U 2www.entrust.net/CPS incorp. by ref. (limits liab.)1%0#U (c) 1999 Entrust.net Limited1:08U1Entrust.net Secure Server Certification Authority 011114143859Z 011115143859Z0‚¶0#7JÒM 990525175538Z0 0 U 0#7JÒO 990525175716Z0 0 U 0#7JÒL 990525175812Z0 0 U 0#7JÓ« 990820202820Z0 0 U 0#7JÓª 990820202856Z0 0 U 0#7JÚ¡ 000131164211Z0 0 U 0#7JÚÙ 000131165325Z0 0 U 0#7JÚÜ 000131165447Z0 0 U 0#7JÝ 000203154145Z0 0 U 0#7JÚÍ 000210135059Z0 0 U 0#7JÚ› 000210135129Z0 0 U 0#7JÛQ 000302183659Z0 0 U 0#7Jݧ 000302183721Z0 0 U 0#7Jà! 000302183811Z0 0 U 0#7Jâ! 000309165548Z0 0 U 0#7Jä} 000403203708Z0 0 U 0#7Jຠ000413144803Z0 0 U 0#7Jå[ 000516175008Z0 0 U 0#7Jå^ 000516175034Z0 0 U 0#7JåX 000516175057Z0 0 U 0#7JäW 000516175130Z0 0 U 0#7Jä” 000516175201Z0 0 U 0#7JäT 000516175229Z0 0 U 0#7Jä€ 000516175300Z0 0 U 0#7JêE 000605185104Z0 0 U 0#7Jèa 000606152333Z0 0 U 0#7Jå‘ 000621195324Z0 0 U 0#7Jëi 000628184236Z0 0 U 0#7Jî™ 000714143308Z0 0 U 0#7Jî9 000804144912Z0 0 U 0#7Jêˆ 000817201522Z0 0 U 0#7Jï¸ 000821194130Z0 0 U 0#7Jñ¾ 000823200341Z0 0 U 0#7Jóu 000828204916Z0 0 U 0#7Jò² 000829142007Z0 0 U 0#7Jó· 000908175148Z0 0 U 0#7Jò© 000911194727Z0 0 U 0#7Jì 000913165543Z0 0 U 0#7Jî 000914204008Z0 0 U 0#7Jìk 000919140611Z0 0 U 0#7Jã‹ 000919140710Z0 0 U 0#7Jõ¸ 000919140825Z0 0 U 0#7Jõû 000919141005Z0 0 U 0#7JöJ 000922210539Z0 0 U 0#7Jó´ 000925163347Z0 0 U 0#7JõA 000926145959Z0 0 U 0#7JÓ¢ 001002175014Z0 0 U 0#7JÒ[ 001002175053Z0 0 U 0#7Jê‹ 001003134606Z0 0 U 0#7JÓ` 001003171558Z0 0 U 0#7JÒf 001003171650Z0 0 U 0#7JÒW 001003171742Z0 0 U 0#7JÒV 001003171819Z0 0 U 0#7Jïû 001003171931Z0 0 U 0#7Jïú 001003172018Z0 0 U 0#7Jùf 001011154910Z0 0 U 0#7Jùc 001011155023Z0 0 U 0#7Jú 001017125243Z0 0 U 0#7Jø 001017131240Z0 0 U 0#7JúG 001019165221Z0 0 U 0#7JûC 001019174947Z0 0 U 0#7Jû  001019204503Z0 0 U 0#7Jû 001019204529Z0 0 U 0#7Jû  001019204712Z0 0 U 0#7JûÖ 001020153727Z0 0 U 0#7Júî 001020234322Z0 0 U 0#7Júñ 001020234409Z0 0 U 0#7Júë 001020234505Z0 0 U 0#7Júè 001020234602Z0 0 U 0#7JëÊ 001023190656Z0 0 U 0#7JëR 001023191001Z0 0 U 0#7Jìn 001023191510Z0 0 U 0#7Jì6 001025123200Z0 0 U 0#7Jì  001025123251Z0 0 U 0#7Jìz 001025123343Z0 0 U 0#7Jì} 001025123429Z0 0 U 0#7JôÊ 001025123521Z0 0 U 0#7JôÍ 001025123610Z0 0 U 0#7Jü 001025182238Z0 0 U 0#7Jù¡ 001026180638Z0 0 U 0#7Jùž 001026180702Z0 0 U 0#7Jüª 001026204259Z0 0 U 0#7Jü§ 001026204339Z0 0 U 0#7Jüc 001027144520Z0 0 U 0#7Jüß 001030181704Z0 0 U 0#7Jý¬ 001102150821Z0 0 U 0#7Jþ 001103170909Z0 0 U 0#7Jþz 001107190213Z0 0 U 0#7Jþ4 001107190323Z0 0 U 0#7Jý[ 001108215744Z0 0 U 0#7JýX 001108215825Z0 0 U 0#7JýU 001108215908Z0 0 U 0#7JýR 001108215941Z0 0 U 0#7JýO 001108220024Z0 0 U 0#7JýL 001108220111Z0 0 U 0#7Jÿ  001109182918Z0 0 U 0#7Jýõ 001110182414Z0 0 U 0#7Jÿˆ 001113165037Z0 0 U 0#7Jÿ… 001113165052Z0 0 U 0#7Jÿ‚ 001113165201Z0 0 U 0#7Jþ˜ 001113185600Z0 0 U 0#7Jÿ 001114181854Z0 0 U 0#7Jÿk 001114181943Z0 0 U 0#7Jþƒ 001115151312Z0 0 U 0#7Jÿ 001115151353Z0 0 U 0#7Jþ¼ 001115151539Z0 0 U 0#7JþÖ 001116212153Z0 0 U 0#7JÿM 001117190830Z0 0 U 0#7JýÕ 001120145654Z0 0 U 0#7Jÿ, 001120145709Z0 0 U 0#7KÒ 001120173733Z0 0 U 0#7KØ 001120175358Z0 0 U 0#7Jÿ· 001120180522Z0 0 U 0#7Kj 001120184830Z0 0 U 0#7Jÿ´ 001120184928Z0 0 U 0#7K 001121212919Z0 0 U 0#7K 001121212958Z0 0 U 0#7K 001122142151Z0 0 U 0#7K 001122142228Z0 0 U 0#7K~ 001127204930Z0 0 U 0#7K* 001129143719Z0 0 U 0#7Jÿ£ 001129180550Z0 0 U 0#7Jÿ¦ 001129180614Z0 0 U 0#7K¿ 001130182111Z0 0 U 0#7Km 001204172750Z0 0 U 0#7K 001204200728Z0 0 U 0#7K„ 001205215948Z0 0 U 0#7K„ 001206212945Z0 0 U 0#7K 001207195836Z0 0 U 0#7K¿ 001211221342Z0 0 U 0#7K– 001212210045Z0 0 U 0#7JøS 001213155452Z0 0 U 0#7JøY 001213155532Z0 0 U 0#7JøV 001213155602Z0 0 U 0#7Ka 001213192537Z0 0 U 0#7K^ 001214175644Z0 0 U 0#7KS 001215200242Z0 0 U 0#7K} 001218174840Z0 0 U 0#7Ks 001218182420Z0 0 U 0#7Kš 001218221842Z0 0 U 0#7Kõ 001218222114Z0 0 U 0#7K— 001219143811Z0 0 U 0#7KY 001219154900Z0 0 U 0#7K6 001219185239Z0 0 U 0#7Kø 001219211710Z0 0 U 0#7K  001221174122Z0 0 U 0#7K¢ 001221191428Z0 0 U 0#7Kœ 001221195025Z0 0 U 0#7K™ 001221195038Z0 0 U 0#7K– 001221195049Z0 0 U 0#7K 001221211110Z0 0 U 0#7KŸ 001222145818Z0 0 U 0#7K_ 001222205456Z0 0 U 0#7K 010102142224Z0 0 U 0#7K‚ 010102175728Z0 0 U 0#7Kè 010102175906Z0 0 U 0#7KH 010103143850Z0 0 U 0#7K« 010103163513Z0 0 U 0#7KQ 010104191220Z0 0 U 0#7K¥ 010104222152Z0 0 U 0#7K‡ 010105185403Z0 0 U 0#7K€ 010105185646Z0 0 U 0#7Jÿ½ 010108134620Z0 0 U 0#7K» 010108163445Z0 0 U 0#7K< 010108194952Z0 0 U 0#7Ke 010108195407Z0 0 U 0#7K• 010108195633Z0 0 U 0#7K # 010108221600Z0 0 U 0#7Kw 010109144246Z0 0 U 0#7Kt 010109144420Z0 0 U 0#7K - 010109170529Z0 0 U 0#7K 0 010110184321Z0 0 U 0#7K ‚ 010110215800Z0 0 U 0#7KÇ 010110220200Z0 0 U 0#7Kß 010112164030Z0 0 U 0#7K  010112205539Z0 0 U 0#7K * 010113003258Z0 0 U 0#7K … 010115215616Z0 0 U 0#7K Ý 010115235140Z0 0 U 0#7K - 010116230321Z0 0 U 0#7K  010116230544Z0 0 U 0#7K 4 010116230604Z0 0 U 0#7K  010117150349Z0 0 U 0#7K ì 010117171904Z0 0 U 0#7K õ 010117203646Z0 0 U 0#7K  010118182156Z0 0 U 0#7K " 010118222646Z0 0 U 0#7Kd 010119154300Z0 0 U 0#7K ‰ 010119155929Z0 0 U 0#7K À 010119160606Z0 0 U 0#7K < 010119162936Z0 0 U 0#7K ½ 010119193506Z0 0 U 0#7K º 010119193629Z0 0 U 0#7K · 010119193800Z0 0 U 0#7K ´ 010119232357Z0 0 U 0#7K ¬ 010122194405Z0 0 U 0#7K ? 010122210816Z0 0 U 0#7K å 010123183746Z0 0 U 0#7Jõþ 010124000609Z0 0 U 0#7K ö 010124150400Z0 0 U 0#7K Ú 010124163613Z0 0 U 0#7K0 010124175955Z0 0 U 0#7K ` 010124221245Z0 0 U 0#7Kv 010125151717Z0 0 U 0#7Jþ 010125151806Z0 0 U 0#7K › 010125183826Z0 0 U 0#7K › 010125225116Z0 0 U 0#7K : 010126151123Z0 0 U 0#7K 4 010129204047Z0 0 U 0#7K E 010130204936Z0 0 U 0#7K H 010130205121Z0 0 U 0#7K\ 010131185121Z0 0 U 0#7K o 010131212700Z0 0 U 0#7K Œ 010201210454Z0 0 U 0#7K ˜ 010201220520Z0 0 U 0#7K ( 010202002205Z0 0 U 0#7K á 010202151733Z0 0 U 0#7K › 010202181547Z0 0 U 0#7K x 010202211248Z0 0 U 0#7K: 010202231940Z0 0 U 0#7K7 010202232131Z0 0 U 0#7K  010205165918Z0 0 U 0#7K 010205170243Z0 0 U 0#7K" 010205191001Z0 0 U 0#7K< 010205210210Z0 0 U 0#7Jþ 010207161029Z0 0 U 0#7JþÅ 010207161152Z0 0 U 0#7JþÈ 010207164707Z0 0 U 0#7JþÑ 010207181925Z0 0 U 0#7K l 010208125710Z0 0 U 0#7K ¦ 010208125812Z0 0 U 0#7K9 010208202144Z0 0 U 0#7Kû 010209005120Z0 0 U 0#7K 010209174816Z0 0 U 0#7K 010209192902Z0 0 U 0#7K] 010209233452Z0 0 U 0#7Kƒ 010210180910Z0 0 U 0#7K3 010212171542Z0 0 U 0#7K T 010212184042Z0 0 U 0#7K­ 010212184320Z0 0 U 0#7Jÿ  010212200425Z0 0 U 0#7Kÿ 010213174207Z0 0 U 0#7K ¼ 010213234039Z0 0 U 0#7K ¹ 010213234143Z0 0 U 0#7K ¶ 010213234227Z0 0 U 0#7K ³ 010213234331Z0 0 U 0#7KT 010214145003Z0 0 U 0#7K H 010214154218Z0 0 U 0#7K Ë 010214185710Z0 0 U 0#7K" 010214205834Z0 0 U 0#7K0 010214215921Z0 0 U 0#7Jÿ_ 010214220009Z0 0 U 0#7Jö· 010214220251Z0 0 U 0#7Kc 010215135255Z0 0 U 0#7K1 010215174952Z0 0 U 0#7KÈ 010216165139Z0 0 U 0#7KH 010216165228Z0 0 U 0#7K| 010216215115Z0 0 U 0#7KE 010216224324Z0 0 U 0#7KB 010216224446Z0 0 U 0#7KK 010216224603Z0 0 U 0#7KQ 010216224654Z0 0 U 0#7KN 010216224748Z0 0 U 0#7K \ 010219171329Z0 0 U 0#7K© 010221153039Z0 0 U 0#7K' 010221205736Z0 0 U 0#7K{ 010221210223Z0 0 U 0#7K 010221210310Z0 0 U 0#7Kw 010222180610Z0 0 U 0#7Kç 010223145845Z0 0 U 0#7Kœ 010223183226Z0 0 U 0#7K$ 010226172425Z0 0 U 0#7K ¯ 010226172822Z0 0 U 0#7K œ 010226172854Z0 0 U 0#7JùŒ 010226172959Z0 0 U 0#7K– 010227131412Z0 0 U 0#7K÷ 010228130544Z0 0 U 0#7Kv 010228181420Z0 0 U 0#7K0 010301150144Z0 0 U 0#7Kô 010302143812Z0 0 U 0#7Kñ 010302143928Z0 0 U 0#7Kî 010302144055Z0 0 U 0#7Kë 010302144145Z0 0 U 0#7Kè 010302144233Z0 0 U 0#7KÎ 010302150350Z0 0 U 0#7K× 010302150504Z0 0 U 0#7K + 010302153526Z0 0 U 0#7K ¡ 010302173905Z0 0 U 0#7K× 010302191808Z0 0 U 0#7K û 010302192240Z0 0 U 0#7K: 010302192354Z0 0 U 0#7K­ 010302200834Z0 0 U 0#7K † 010305183746Z0 0 U 0#7K ƒ 010305183831Z0 0 U 0#7Ko 010305184247Z0 0 U 0#7K 1 010305184419Z0 0 U 0#7K[ 010305202137Z0 0 U 0#7KX 010305202240Z0 0 U 0#7Kß 010305232715Z0 0 U 0#7KÌ 010306213746Z0 0 U 0#7Kå 010307185616Z0 0 U 0#7K 010308020003Z0 0 U 0#7Km 010308182243Z0 0 U 0#7Kj 010308182333Z0 0 U 0#7KÕ 010308214910Z0 0 U 0#7Ké 010309130635Z0 0 U 0#7Kõ 010309130652Z0 0 U 0#7KL 010309172620Z0 0 U 0#7K¶ 010309173204Z0 0 U 0#7KZ 010309203234Z0 0 U 0#7Kk 010310001657Z0 0 U 0#7K¨ 010312190022Z0 0 U 0#7Kï 010312234807Z0 0 U 0#7K ¾ 010313181851Z0 0 U 0#7K© 010314193613Z0 0 U 0#7KË 010314205700Z0 0 U 0#7K * 010315003948Z0 0 U 0#7Kf 010315161055Z0 0 U 0#7Kq 010315181200Z0 0 U 0#7K† 010315220244Z0 0 U 0#7Ke 010315231343Z0 0 U 0#7K£ 010316163521Z0 0 U 0#7Kt 010316195249Z0 0 U 0#7K› 010316195417Z0 0 U 0#7K 010316233543Z0 0 U 0#7K 010316233559Z0 0 U 0#7K  010316233742Z0 0 U 0#7K 010316233843Z0 0 U 0#7K 010316233954Z0 0 U 0#7K ý 010320135055Z0 0 U 0#7K  010320135200Z0 0 U 0#7K3 010320160955Z0 0 U 0#7Kß 010320211935Z0 0 U 0#7K© 010320215716Z0 0 U 0#7K­ 010321141538Z0 0 U 0#7K£ 010321154330Z0 0 U 0#7KÒ 010321181655Z0 0 U 0#7KÖ 010322002838Z0 0 U 0#7Kó 010322145246Z0 0 U 0#7K‰ 010322202519Z0 0 U 0#7KÜ 010323010657Z0 0 U 0#7Kß 010323010722Z0 0 U 0#7Ka 010323131943Z0 0 U 0#7Kï 010323182011Z0 0 U 0#7Kó 010323182100Z0 0 U 0#7K> 010323190045Z0 0 U 0#7K; 010323190157Z0 0 U 0#7Kä 010323220414Z0 0 U 0#7K† 010323220521Z0 0 U 0#7K 010326155439Z0 0 U 0#7Kç 010326175648Z0 0 U 0#7K˜ 010326192155Z0 0 U 0#7KK 010326212156Z0 0 U 0#7Kq 010326212355Z0 0 U 0#7Km 010327131619Z0 0 U 0#7K€ 010327201604Z0 0 U 0#7KÇ 010328203741Z0 0 U 0#7K“ 010328222245Z0 0 U 0#7KR 010329213247Z0 0 U 0#7K# 010330131120Z0 0 U 0#7Ké 010330182308Z0 0 U 0#7KÊ 010330205006Z0 0 U 0#7K² 010402121341Z0 0 U 0#7K  010402121746Z0 0 U 0#7K Á 010402142809Z0 0 U 0#7K Ä 010402142830Z0 0 U 0#7K a 010402160457Z0 0 U 0#7K ô 010402160758Z0 0 U 0#7K  010403200510Z0 0 U 0#7Jýä 010403204746Z0 0 U 0#7KB 010403221950Z0 0 U 0#7K!ž 010404122511Z0 0 U 0#7K” 010404151014Z0 0 U 0#7Kƒ 010404164735Z0 0 U 0#7K¸ 010404164956Z0 0 U 0#7K‘ 010404165245Z0 0 U 0#7K!â 010404184522Z0 0 U 0#7K!+ 010404234348Z0 0 U 0#7K!² 010405183558Z0 0 U 0#7K' 010405183721Z0 0 U 0#7K Ê 010405212209Z0 0 U 0#7K" 010406140528Z0 0 U 0#7KQ 010406150840Z0 0 U 0#7K"À 010406151005Z0 0 U 0#7K P 010406173336Z0 0 U 0#7K#I 010406194144Z0 0 U 0#7K"Æ 010406233938Z0 0 U 0#7K"É 010406234205Z0 0 U 0#7K#À 010409205446Z0 0 U 0#7K#Æ 010409205550Z0 0 U 0#7Kf 010409205710Z0 0 U 0#7Kc 010409205746Z0 0 U 0#7K"M 010409213919Z0 0 U 0#7K#õ 010410120938Z0 0 U 0#7K#ø 010410121014Z0 0 U 0#7K$l 010410175907Z0 0 U 0#7K$i 010410180025Z0 0 U 0#7KŠ 010410205937Z0 0 U 0#7Kê 010410210004Z0 0 U 0#7K$„ 010410221911Z0 0 U 0#7K j 010410222032Z0 0 U 0#7K$® 010410233423Z0 0 U 0#7K#+ 010411131754Z0 0 U 0#7K"_ 010411174525Z0 0 U 0#7K"\ 010411204043Z0 0 U 0#7K"Y 010411204213Z0 0 U 0#7K#| 010412120844Z0 0 U 0#7K ‚ 010412145750Z0 0 U 0#7K  010412174404Z0 0 U 0#7K$ó 010412180422Z0 0 U 0#7K#Û 010412180816Z0 0 U 0#7K#á 010412180834Z0 0 U 0#7K  010412202242Z0 0 U 0#7K$  010412202419Z0 0 U 0#7K$¢ 010416172608Z0 0 U 0#7Kœ 010416184300Z0 0 U 0#7K&" 010416234849Z0 0 U 0#7K!¡ 010417195237Z0 0 U 0#7K" 010417234149Z0 0 U 0#7Kí 010418144627Z0 0 U 0#7K# 010419121421Z0 0 U 0#7K¯ 010419151127Z0 0 U 0#7K!å 010419191117Z0 0 U 0#7K&6 010420121431Z0 0 U 0#7K( 010423123708Z0 0 U 0#7K'  010423173654Z0 0 U 0#7Kô 010423173912Z0 0 U 0#7K'‹ 010423185744Z0 0 U 0#7K d 010423190008Z0 0 U 0#7K$Æ 010423190111Z0 0 U 0#7K( 010423192054Z0 0 U 0#7K› 010423220548Z0 0 U 0#7K# 010423220709Z0 0 U 0#7K% 010423220756Z0 0 U 0#7K$$ 010424193722Z0 0 U 0#7K'é 010424194103Z0 0 U 0#7K} 010424194541Z0 0 U 0#7K€ 010424194616Z0 0 U 0#7K# 010424224443Z0 0 U 0#7K$¨ 010424224659Z0 0 U 0#7K" 010424224839Z0 0 U 0#7K( 010425195817Z0 0 U 0#7K(Ý 010425205049Z0 0 U 0#7K#= 010425224243Z0 0 U 0#7K$Ø 010426113348Z0 0 U 0#7K) 010426165610Z0 0 U 0#7K) 010426185924Z0 0 U 0#7K\ 010426213507Z0 0 U 0#7Ké 010427143635Z0 0 U 0#7K å 010427154208Z0 0 U 0#7K(X 010427173431Z0 0 U 0#7K%‚ 010427181921Z0 0 U 0#7K è 010427183240Z0 0 U 0#7K)Ð 010427200830Z0 0 U 0#7K) 010430142506Z0 0 U 0#7K 010430142705Z0 0 U 0#7K#1 010430170121Z0 0 U 0#7K Ž 010430194844Z0 0 U 0#7K O 010501225622Z0 0 U 0#7K*: 010502171144Z0 0 U 0#7K*Ý 010502171746Z0 0 U 0#7K+5 010502180002Z0 0 U 0#7K+ï 010503123518Z0 0 U 0#7K+Ä 010503200731Z0 0 U 0#7K+w 010503231253Z0 0 U 0#7K%% 010504124246Z0 0 U 0#7K] 010504152402Z0 0 U 0#7K+à 010504152640Z0 0 U 0#7K,I 010504160044Z0 0 U 0#7K* 010504193150Z0 0 U 0#7K,Û 010507173959Z0 0 U 0#7K+¾ 010507174119Z0 0 U 0#7K,f 010507230008Z0 0 U 0#7K,Ï 010509162653Z0 0 U 0#7K. 010509204622Z0 0 U 0#7K)… 010510205854Z0 0 U 0#7K.Ñ 010510235431Z0 0 U 0#7K)ö 010511121927Z0 0 U 0#7K.È 010511160910Z0 0 U 0#7K/9 010511161037Z0 0 U 0#7K/< 010511161052Z0 0 U 0#7K/? 010511165603Z0 0 U 0#7K˜ 010511182418Z0 0 U 0#7K(L 010511212123Z0 0 U 0#7K*@ 010514233946Z0 0 U 0#7K+  010515125127Z0 0 U 0#7K/i 010515144435Z0 0 U 0#7K.¿ 010515144713Z0 0 U 0#7K. 010515144732Z0 0 U 0#7Jêã 010515145000Z0 0 U 0#7K-g 010515190701Z0 0 U 0#7K0_ 010515204230Z0 0 U 0#7K0, 010515204426Z0 0 U 0#7K0A 010515234818Z0 0 U 0#7K Ú 010515234933Z0 0 U 0#7K ­ 010516144425Z0 0 U 0#7K. 010516201034Z0 0 U 0#7K+ø 010516225431Z0 0 U 0#7K. 010516233903Z0 0 U 0#7K#X 010516234006Z0 0 U 0#7JðG 010516235558Z0 0 U 0#7K0‰ 010517114944Z0 0 U 0#7K' 010517115245Z0 0 U 0#7K,ö 010517131045Z0 0 U 0#7K,ù 010517131134Z0 0 U 0#7K0P 010517152646Z0 0 U 0#7K+ 010517153136Z0 0 U 0#7K+ì 010517153259Z0 0 U 0#7K-d 010517153412Z0 0 U 0#7K! 010517184834Z0 0 U 0#7K1m 010517200849Z0 0 U 0#7K 010517201135Z0 0 U 0#7K( 010517234200Z0 0 U 0#7K% 010517234234Z0 0 U 0#7K  010517234308Z0 0 U 0#7K æ 010517234359Z0 0 U 0#7K ã 010517234429Z0 0 U 0#7K1; 010518134308Z0 0 U 0#7K.  010518134530Z0 0 U 0#7K1s 010518142046Z0 0 U 0#7K) 010518164414Z0 0 U 0#7K0Í 010518165017Z0 0 U 0#7K1û 010518225042Z0 0 U 0#7K1® 010522121913Z0 0 U 0#7K(I 010522122615Z0 0 U 0#7K+— 010522122943Z0 0 U 0#7K+Õ 010522123216Z0 0 U 0#7K1ê 010522151010Z0 0 U 0#7K-m 010522165110Z0 0 U 0#7K/0 010522165209Z0 0 U 0#7K/3 010522165317Z0 0 U 0#7K,½ 010522165531Z0 0 U 0#7K,À 010522165654Z0 0 U 0#7K,à 010522165838Z0 0 U 0#7K2ó 010522213313Z0 0 U 0#7K2 010523115147Z0 0 U 0#7K1¢ 010523115309Z0 0 U 0#7K2´ 010523140723Z0 0 U 0#7K1ˆ 010523140851Z0 0 U 0#7K$™ 010523152737Z0 0 U 0#7K0» 010523171822Z0 0 U 0#7K2Õ 010523171923Z0 0 U 0#7K$ 010523203647Z0 0 U 0#7K$ 010523203818Z0 0 U 0#7K2 010524153036Z0 0 U 0#7K-‡ 010524195909Z0 0 U 0#7K/Œ 010524215135Z0 0 U 0#7K0¬ 010525120534Z0 0 U 0#7K1) 010525153932Z0 0 U 0#7K*´ 010528115226Z0 0 U 0#7K3† 010528171347Z0 0 U 0#7K* 010528204329Z0 0 U 0#7K0  010528220237Z0 0 U 0#7K1F 010528220756Z0 0 U 0#7K2™ 010529160904Z0 0 U 0#7K4G 010529200228Z0 0 U 0#7K4‚ 010529200623Z0 0 U 0#7K4… 010529200652Z0 0 U 0#7K4õ 010529214529Z0 0 U 0#7K3î 010529214730Z0 0 U 0#7K4¡ 010530121027Z0 0 U 0#7K0# 010530130342Z0 0 U 0#7K5s 010530145703Z0 0 U 0#7K'” 010530145926Z0 0 U 0#7K&­ 010530145949Z0 0 U 0#7K&° 010530150025Z0 0 U 0#7K'‘ 010530150050Z0 0 U 0#7K @ 010530172628Z0 0 U 0#7K5W 010530185949Z0 0 U 0#7K5f 010530190710Z0 0 U 0#7K-r 010531113954Z0 0 U 0#7K4ª 010531125815Z0 0 U 0#7K6q 010531144535Z0 0 U 0#7K+õ 010531162013Z0 0 U 0#7K0Ä 010531194552Z0 0 U 0#7K6à 010601114309Z0 0 U 0#7K+t 010601121431Z0 0 U 0#7K75 010601184539Z0 0 U 0#7K-ø 010601184927Z0 0 U 0#7K6› 010604142919Z0 0 U 0#7K,Õ 010604143043Z0 0 U 0#7K3ô 010604143158Z0 0 U 0#7K0¡ 010604180916Z0 0 U 0#7K5 010604181306Z0 0 U 0#7K7b 010604201435Z0 0 U 0#7K6 010604201611Z0 0 U 0#7K6° 010604201806Z0 0 U 0#7K7’ 010604233026Z0 0 U 0#7K7¦ 010604233226Z0 0 U 0#7Kâ 010605184233Z0 0 U 0#7K8 010606185244Z0 0 U 0#7K5› 010607161118Z0 0 U 0#7K3ú 010607161436Z0 0 U 0#7K5x 010607183420Z0 0 U 0#7K+ò 010607183658Z0 0 U 0#7K3w 010607220701Z0 0 U 0#7K8Ï 010607235259Z0 0 U 0#7K8Ì 010607235328Z0 0 U 0#7K8É 010607235407Z0 0 U 0#7K8¥ 010608124000Z0 0 U 0#7K9 010608124127Z0 0 U 0#7K87 010608170528Z0 0 U 0#7K8: 010608170542Z0 0 U 0#7K81 010608170604Z0 0 U 0#7K8 010608170645Z0 0 U 0#7K84 010608170701Z0 0 U 0#7K"˜ 010608193419Z0 0 U 0#7K9 010608193659Z0 0 U 0#7KŒ 010608234151Z0 0 U 0#7K2i 010611171629Z0 0 U 0#7K6¹ 010611192107Z0 0 U 0#7K6¼ 010611192226Z0 0 U 0#7K4[ 010611210317Z0 0 U 0#7K/¶ 010611224119Z0 0 U 0#7K/­ 010611224141Z0 0 U 0#7K9= 010611224330Z0 0 U 0#7K:2 010612143058Z0 0 U 0#7K:5 010612143330Z0 0 U 0#7K:P 010612201543Z0 0 U 0#7K72 010612201714Z0 0 U 0#7K6Ý 010613152642Z0 0 U 0#7K ˆ 010613183150Z0 0 U 0#7K2ÿ 010613183551Z0 0 U 0#7K9É 010613184114Z0 0 U 0#7K7} 010613191308Z0 0 U 0#7K` 010613233450Z0 0 U 0#7K,  010613233514Z0 0 U 0#7K7ã 010614131952Z0 0 U 0#7K:Á 010614132551Z0 0 U 0#7K&` 010614161452Z0 0 U 0#7K&] 010614161553Z0 0 U 0#7K:ë 010614161747Z0 0 U 0#7K8g 010614211116Z0 0 U 0#7K6- 010614233939Z0 0 U 0#7K6* 010614234000Z0 0 U 0#7K± 010615132811Z0 0 U 0#7K;_ 010615133509Z0 0 U 0#7K:å 010615165755Z0 0 U 0#7K9“ 010615214108Z0 0 U 0#7K6å 010618132105Z0 0 U 0#7K;Í 010618132301Z0 0 U 0#7K<9 010618132538Z0 0 U 0#7K;Á 010618133152Z0 0 U 0#7K2Ÿ 010618173319Z0 0 U 0#7Kn 010625190415Z0 0 U 0#7K9¢ 010625195608Z0 0 U 0#7K7 010625210601Z0 0 U 0#7K0> 010626155726Z0 0 U 0#7K/• 010626155815Z0 0 U 0#7K.ã 010626155859Z0 0 U 0#7K>Ë 010626160040Z0 0 U 0#7K 010628153454Z0 0 U 0#7K:¡ 010628191256Z0 0 U 0#7K@ 010628221803Z0 0 U 0#7K9d 010628230741Z0 0 U 0#7K@ 010629154151Z0 0 U 0#7K@k 010629154916Z0 0 U 0#7K1 010629192841Z0 0 U 0#7K@t 010629203212Z0 0 U 0#7K8¨ 010629203347Z0 0 U 0#7K;¼ 010629203620Z0 0 U 0#7K@­ 010629224114Z0 0 U 0#7K@H 010703114950Z0 0 U 0#7K=ó 010703115249Z0 0 U 0#7K94 010703115350Z0 0 U 0#7K9, 010703115420Z0 0 U 0#7K=á 010703161227Z0 0 U 0#7K@  010703161346Z0 0 U 0#7K;› 010704125730Z0 0 U 0#7KA\ 010704130950Z0 0 U 0#7K>8 010704222411Z0 0 U 0#7KAd 010705172010Z0 0 U 0#7K?A 010705180831Z0 0 U 0#7KA_ 010705231349Z0 0 U 0#7KB 010705231854Z0 0 U 0#7K>­ 010705232032Z0 0 U 0#7K@W 010705232300Z0 0 U 0#7K@° 010706135718Z0 0 U 0#7K5¶ 010706194816Z0 0 U 0#7KB# 010709120525Z0 0 U 0#7KB 010709120626Z0 0 U 0#7KB 010709120708Z0 0 U 0#7KBv 010709150502Z0 0 U 0#7KBÖ 010709171534Z0 0 U 0#7K=Õ 010709171701Z0 0 U 0#7K8ð 010709221141Z0 0 U 0#7K:Í 010710142011Z0 0 U 0#7KBñ 010710142418Z0 0 U 0#7K?# 010710162942Z0 0 U 0#7K;z 010710202146Z0 0 U 0#7K;} 010710202216Z0 0 U 0#7K;w 010710202308Z0 0 U 0#7KB¬ 010710214305Z0 0 U 0#7KB© 010710214334Z0 0 U 0#7KB¦ 010710214356Z0 0 U 0#7KA 010711174336Z0 0 U 0#7K0Ö 010711174608Z0 0 U 0#7K0Ù 010711175950Z0 0 U 0#7KCœ 010711192513Z0 0 U 0#7KCŸ 010711192550Z0 0 U 0#7KC™ 010711192615Z0 0 U 0#7K?Ì 010712131202Z0 0 U 0#7KAº 010712160546Z0 0 U 0#7KA 010712160855Z0 0 U 0#7KBš 010712184813Z0 0 U 0#7K=2 010712184927Z0 0 U 0#7K ÿ 010712210059Z0 0 U 0#7K?r 010712210335Z0 0 U 0#7K$ 010713120812Z0 0 U 0#7KDÌ 010713180006Z0 0 U 0#7KDR 010713185937Z0 0 U 0#7KDs 010713190000Z0 0 U 0#7K:è 010716172147Z0 0 U 0#7KC9 010716172343Z0 0 U 0#7KC“ 010716221020Z0 0 U 0#7K(Î 010716233549Z0 0 U 0#7KP 010717185913Z0 0 U 0#7K8ä 010718131325Z0 0 U 0#7KF 010718171652Z0 0 U 0#7KF  010718174818Z0 0 U 0#7K0M 010718182355Z0 0 U 0#7KC  010718182637Z0 0 U 0#7KC/ 010718192621Z0 0 U 0#7KE[ 010719130442Z0 0 U 0#7KC 010719130853Z0 0 U 0#7K@ª 010719131145Z0 0 U 0#7KF¹ 010719170551Z0 0 U 0#7KF¼ 010719170653Z0 0 U 0#7K<¢ 010719171033Z0 0 U 0#7K:â 010719222043Z0 0 U 0#7K 010719231050Z0 0 U 0#7KC 010719231304Z0 0 U 0#7KG  010720143242Z0 0 U 0#7KGm 010720144259Z0 0 U 0#7KE% 010720221550Z0 0 U 0#7KF° 010723134211Z0 0 U 0#7KG" 010723160257Z0 0 U 0#7K=¾ 010723160446Z0 0 U 0#7K6­ 010723191330Z0 0 U 0#7K@â 010724122409Z0 0 U 0#7KEo 010724151803Z0 0 U 0#7KH– 010724153912Z0 0 U 0#7J⟠010724190519Z0 0 U 0#7KH² 010725181003Z0 0 U 0#7KH 010725181114Z0 0 U 0#7Kn 010725192352Z0 0 U 0#7KEƒ 010725192645Z0 0 U 0#7KI& 010725202817Z0 0 U 0#7KI  010726182034Z0 0 U 0#7KHð 010726182625Z0 0 U 0#7KI˜ 010727142911Z0 0 U 0#7KH 010727143604Z0 0 U 0#7KG 010727181014Z0 0 U 0#7KI› 010727181114Z0 0 U 0#7KHö 010730165817Z0 0 U 0#7K@• 010730170925Z0 0 U 0#7KIä 010730172750Z0 0 U 0#7KIð 010730172857Z0 0 U 0#7KJ 010730224935Z0 0 U 0#7KJ" 010730224959Z0 0 U 0#7KJ% 010730225020Z0 0 U 0#7KJ( 010730225038Z0 0 U 0#7KJ+ 010730225054Z0 0 U 0#7KIû 010730225335Z0 0 U 0#7KH¦ 010801115202Z0 0 U 0#7K+; 010801130604Z0 0 U 0#7KJñ 010801131004Z0 0 U 0#7KJî 010801131137Z0 0 U 0#7KJF 010801172548Z0 0 U 0#7K?d 010801184058Z0 0 U 0#7KIà 010801195011Z0 0 U 0#7KK² 010802152145Z0 0 U 0#7K?À 010802174929Z0 0 U 0#7KKH 010803114823Z0 0 U 0#7KL  010803152059Z0 0 U 0#7KI) 010803162446Z0 0 U 0#7KI‡ 010803180710Z0 0 U 0#7KJ” 010803180832Z0 0 U 0#7KI 010803181020Z0 0 U 0#7KKç 010803193540Z0 0 U 0#7KJä 010803193655Z0 0 U 0#7KJ7 010807120752Z0 0 U 0#7KH 010807122130Z0 0 U 0#7KLT 010807144953Z0 0 U 0#7KLQ 010807164749Z0 0 U 0#7KLf 010807170503Z0 0 U 0#7KL{ 010807192406Z0 0 U 0#7KKö 010807192515Z0 0 U 0#7KD™ 010807192621Z0 0 U 0#7KLõ 010807200441Z0 0 U 0#7KLè 010807234138Z0 0 U 0#7KJÉ 010807234259Z0 0 U 0#7K#U 010808121141Z0 0 U 0#7K3¯ 010808141323Z0 0 U 0#7KB— 010808141450Z0 0 U 0#7KBa 010808141621Z0 0 U 0#7KL 010808142003Z0 0 U 0#7KG 010808224144Z0 0 U 0#7KL] 010808224310Z0 0 U 0#7KL‡ 010808224409Z0 0 U 0#7KM 010808224458Z0 0 U 0#7KL¼ 010808224641Z0 0 U 0#7KK 010809141933Z0 0 U 0#7Kr 010809142206Z0 0 U 0#7K%= 010809155250Z0 0 U 0#7KM 010809184050Z0 0 U 0#7KMQ 010809184500Z0 0 U 0#7KBâ 010809203018Z0 0 U 0#7KN6 010809203334Z0 0 U 0#7KCÝ 010809221534Z0 0 U 0#7KD| 010810001710Z0 0 U 0#7KGÒ 010810002008Z0 0 U 0#7KGØ 010810002109Z0 0 U 0#7KGá 010810002249Z0 0 U 0#7K:G 010810002347Z0 0 U 0#7KL1 010810002447Z0 0 U 0#7KIµ 010810121405Z0 0 U 0#7KM‡ 010810160956Z0 0 U 0#7KL„ 010810161232Z0 0 U 0#7KN: 010810161527Z0 0 U 0#7KN² 010810212540Z0 0 U 0#7KN€ 010813133545Z0 0 U 0#7K 010813191529Z0 0 U 0#7KO} 010813223050Z0 0 U 0#7KOt 010813223141Z0 0 U 0#7KI@ 010814192844Z0 0 U 0#7KNC 010814211626Z0 0 U 0#7KN£ 010814235023Z0 0 U 0#7KOü 010815181247Z0 0 U 0#7KO¹ 010815183020Z0 0 U 0#7KPO 010815195102Z0 0 U 0#7KPL 010815195224Z0 0 U 0#7KPI 010815195322Z0 0 U 0#7KGÞ 010815195706Z0 0 U 0#7KGÕ 010815200135Z0 0 U 0#7K"€ 010815225735Z0 0 U 0#7KOª 010815225946Z0 0 U 0#7KPˆ 010816123616Z0 0 U 0#7KD 010816153838Z0 0 U 0#7KPa 010816154001Z0 0 U 0#7KP‚ 010816234048Z0 0 U 0#7KHó 010817124434Z0 0 U 0#7KQ 010820122620Z0 0 U 0#7KL¹ 010820185502Z0 0 U 0#7K!Á 010820185651Z0 0 U 0#7KPd 010820185917Z0 0 U 0#7KQ 010820190537Z0 0 U 0#7KQ— 010820190651Z0 0 U 0#7KDy 010820190934Z0 0 U 0#7KL% 010820230953Z0 0 U 0#7KP@ 010820231111Z0 0 U 0#7KOw 010820231159Z0 0 U 0#7KPí 010820231249Z0 0 U 0#7KM 010821155552Z0 0 U 0#7KLH 010821180919Z0 0 U 0#7KO* 010821181149Z0 0 U 0#7KP7 010821195124Z0 0 U 0#7KLZ 010821225046Z0 0 U 0#7K:X 010821232417Z0 0 U 0#7KNt 010822143254Z0 0 U 0#7KGç 010822173455Z0 0 U 0#7KR” 010822225734Z0 0 U 0#7KR^ 010822225821Z0 0 U 0#7KR1 010823161305Z0 0 U 0#7KFí 010823180054Z0 0 U 0#7KFl 010823180112Z0 0 U 0#7KRˆ 010823180216Z0 0 U 0#7KQÀ 010823232501Z0 0 U 0#7KL+ 010824133115Z0 0 U 0#7KÏ 010824160608Z0 0 U 0#7KQm 010827185131Z0 0 U 0#7K(‡ 010827205829Z0 0 U 0#7KRÞ 010828161701Z0 0 U 0#7KQ1 010828161831Z0 0 U 0#7Jãí 010828183938Z0 0 U 0#7Jáb 010828184021Z0 0 U 0#7Já_ 010828184104Z0 0 U 0#7Já\ 010828184320Z0 0 U 0#7JáY 010828184357Z0 0 U 0#7Já5 010828184458Z0 0 U 0#7Kö 010828185317Z0 0 U 0#7K.* 010828185355Z0 0 U 0#7KT˜ 010828233424Z0 0 U 0#7KT­ 010828233935Z0 0 U 0#7KKE 010829125810Z0 0 U 0#7KT+ 010829182257Z0 0 U 0#7K,Ò 010829182611Z0 0 U 0#7K7P 010829211033Z0 0 U 0#7KLª 010830161648Z0 0 U 0#7KU/ 010830174553Z0 0 U 0#7KU• 010830230357Z0 0 U 0#7KFÈ 010831130644Z0 0 U 0#7KP¦ 010831195329Z0 0 U 0#7KT3 010904120644Z0 0 U 0#7KTÎ 010904121120Z0 0 U 0#7KT¹ 010904121523Z0 0 U 0#7KT¶ 010904121709Z0 0 U 0#7KU× 010904121923Z0 0 U 0#7KS 010904171419Z0 0 U 0#7KT› 010904171639Z0 0 U 0#7KR 010904172006Z0 0 U 0#7KIž 010904211155Z0 0 U 0#7KPö 010904211239Z0 0 U 0#7KTä 010904211327Z0 0 U 0#7KV 010905121343Z0 0 U 0#7KUÔ 010905121803Z0 0 U 0#7KV¬ 010905132657Z0 0 U 0#7KCþ 010905150111Z0 0 U 0#7KFË 010905154453Z0 0 U 0#7KS3 010905180923Z0 0 U 0#7KV_ 010905194522Z0 0 U 0#7KVb 010905194552Z0 0 U 0#7KV¯ 010905194611Z0 0 U 0#7KVú 010905194640Z0 0 U 0#7KUÀ 010905211033Z0 0 U 0#7KV‰ 010905211402Z0 0 U 0#7KVÜ 010906154541Z0 0 U 0#7KVß 010906154703Z0 0 U 0#7KVè 010906154832Z0 0 U 0#7KVî 010906155014Z0 0 U 0#7KVë 010906155142Z0 0 U 0#7KW 010906221634Z0 0 U 0#7KOV 010906221741Z0 0 U 0#7KWq 010907121123Z0 0 U 0#7KUG 010907121239Z0 0 U 0#7KVe 010907142716Z0 0 U 0#7KNÖ 010907142842Z0 0 U 0#7KT 010907165257Z0 0 U 0#7Jý¡ 010907165415Z0 0 U 0#7K  010907165506Z0 0 U 0#7K  010907165551Z0 0 U 0#7KW× 010907165707Z0 0 U 0#7KFB 010907181822Z0 0 U 0#7KÑ 010907215205Z0 0 U 0#7KË 010907215243Z0 0 U 0#7KÈ 010907215319Z0 0 U 0#7KÅ 010907215359Z0 0 U 0#7K 010907215441Z0 0 U 0#7K! 010907215629Z0 0 U 0#7KWÚ 010910150242Z0 0 U 0#7Kë 010910172328Z0 0 U 0#7Kì 010910172422Z0 0 U 0#7KI 010910172512Z0 0 U 0#7JôE 010910172633Z0 0 U 0#7JôF 010910172709Z0 0 U 0#7JÛß 010910172748Z0 0 U 0#7JÛà 010910172821Z0 0 U 0#7KV§ 010910182536Z0 0 U 0#7KU› 010910220035Z0 0 U 0#7KWì 010910220338Z0 0 U 0#7KOò 010910220533Z0 0 U 0#7KT6 010911130930Z0 0 U 0#7KW 010912152238Z0 0 U 0#7KXÙ 010912193045Z0 0 U 0#7KDd 010913152727Z0 0 U 0#7KDa 010913152834Z0 0 U 0#7KYG 010913153020Z0 0 U 0#7K.c 010913153703Z0 0 U 0#7K@ 010913171810Z0 0 U 0#7KY 010913171930Z0 0 U 0#7KX’ 010913172100Z0 0 U 0#7KX. 010913192358Z0 0 U 0#7KY| 010913202229Z0 0 U 0#7KXÜ 010914122436Z0 0 U 0#7KJ÷ 010914195316Z0 0 U 0#7KQé 010914200558Z0 0 U 0#7KR‹ 010914200820Z0 0 U 0#7KZ> 010914201130Z0 0 U 0#7KXz 010917192846Z0 0 U 0#7K2x 010918150431Z0 0 U 0#7K2 010918150539Z0 0 U 0#7KR| 010918150704Z0 0 U 0#7KR 010918150812Z0 0 U 0#7KVÓ 010918172326Z0 0 U 0#7KZi 010918172631Z0 0 U 0#7KX˜ 010918172724Z0 0 U 0#7KZu 010918191452Z0 0 U 0#7KZl 010918191625Z0 0 U 0#7KF– 010918191734Z0 0 U 0#7KJÀ 010918191926Z0 0 U 0#7K[  010918205149Z0 0 U 0#7K5Q 010919123042Z0 0 U 0#7K5È 010919152619Z0 0 U 0#7K?ì 010919165902Z0 0 U 0#7K[³ 010920133555Z0 0 U 0#7K[ª 010920170308Z0 0 U 0#7K[¼ 010921135254Z0 0 U 0#7KZÆ 010921151559Z0 0 U 0#7KWû 010921184800Z0 0 U 0#7KYp 010921202753Z0 0 U 0#7K x 010921202941Z0 0 U 0#7K\³ 010921210630Z0 0 U 0#7KQï 010924200820Z0 0 U 0#7KX 010924214138Z0 0 U 0#7K3L 010925135206Z0 0 U 0#7K\Ë 010925141005Z0 0 U 0#7K« 010925141226Z0 0 U 0#7KYˆ 010925141349Z0 0 U 0#7K] 010925190123Z0 0 U 0#7K]“ 010925190318Z0 0 U 0#7K]R 010925192201Z0 0 U 0#7KLi 010925220530Z0 0 U 0#7KLc 010925220607Z0 0 U 0#7K]á 010925220732Z0 0 U 0#7KL4 010926121003Z0 0 U 0#7KVn 010926143926Z0 0 U 0#7KZP 010926193026Z0 0 U 0#7KZ 010926193137Z0 0 U 0#7K]¥ 010926193336Z0 0 U 0#7K\K 010926212242Z0 0 U 0#7KX¦ 010927121628Z0 0 U 0#7K^E 010927145511Z0 0 U 0#7K\ 010927145718Z0 0 U 0#7K\ 010927145905Z0 0 U 0#7K]¢ 010927174103Z0 0 U 0#7KTÅ 010927175903Z0 0 U 0#7K]= 010927213313Z0 0 U 0#7KYj 010927214149Z0 0 U 0#7K^Œ 010928150127Z0 0 U 0#7K^ 010928190415Z0 0 U 0#7K^Ñ 011001171557Z0 0 U 0#7K[Î 011001172300Z0 0 U 0#7KX› 011001172536Z0 0 U 0#7K_Ò 011001220127Z0 0 U 0#7K:S 011002120356Z0 0 U 0#7K/° 011002120425Z0 0 U 0#7K^" 011002120946Z0 0 U 0#7K.ú 011002180621Z0 0 U 0#7K?& 011002180746Z0 0 U 0#7K] 011002180937Z0 0 U 0#7K^† 011002213647Z0 0 U 0#7K^¹ 011003120702Z0 0 U 0#7K_` 011003121517Z0 0 U 0#7K]ü 011003121600Z0 0 U 0#7K_u 011003121853Z0 0 U 0#7KJ. 011003170912Z0 0 U 0#7K#Ÿ 011003190428Z0 0 U 0#7KX‰ 011004163807Z0 0 U 0#7K[Œ 011004195124Z0 0 U 0#7K^Q 011004221702Z0 0 U 0#7K`Ú 011005125959Z0 0 U 0#7K`× 011005130113Z0 0 U 0#7K_Q 011005130349Z0 0 U 0#7K[< 011005160358Z0 0 U 0#7K] 011005212305Z0 0 U 0#7K] 011005212401Z0 0 U 0#7KO“ 011009120400Z0 0 U 0#7Kbu 011009224319Z0 0 U 0#7K^ª 011009224416Z0 0 U 0#7K_Ú 011010161559Z0 0 U 0#7KTx 011010202051Z0 0 U 0#7KcŒ 011010220632Z0 0 U 0#7Ka  011011153032Z0 0 U 0#7Kd 011011183451Z0 0 U 0#7KcÊ 011011203403Z0 0 U 0#7K\¼ 011011215942Z0 0 U 0#7K:Ü 011011220020Z0 0 U 0#7KdA 011012190230Z0 0 U 0#7K^ 011015182752Z0 0 U 0#7Jæh 011015182936Z0 0 U 0#7Jæ( 011015183114Z0 0 U 0#7Jä— 011015183226Z0 0 U 0#7Kbï 011016192144Z0 0 U 0#7Kc 011016204430Z0 0 U 0#7Kc 011017140727Z0 0 U 0#7KdÁ 011017141008Z0 0 U 0#7Kc’ 011017174306Z0 0 U 0#7Kd  011017174703Z0 0 U 0#7Kbœ 011017194940Z0 0 U 0#7Keµ 011017195134Z0 0 U 0#7KcÓ 011017195242Z0 0 U 0#7K>Î 011017195403Z0 0 U 0#7KQ¦ 011017195510Z0 0 U 0#7K\{ 011018161238Z0 0 U 0#7K;’ 011018161719Z0 0 U 0#7Ke: 011019140524Z0 0 U 0#7K^¤ 011019140917Z0 0 U 0#7Kcg 011019174836Z0 0 U 0#7KfÈ 011019210853Z0 0 U 0#7Ka) 011022120103Z0 0 U 0#7K`T 011022190118Z0 0 U 0#7JÛÄ 011022190317Z0 0 U 0#7JÛÇ 011022190414Z0 0 U 0#7J݃ 011022190536Z0 0 U 0#7Kf{ 011023120250Z0 0 U 0#7Kfx 011023120356Z0 0 U 0#7Keþ 011023172433Z0 0 U 0#7Keû 011023172549Z0 0 U 0#7Ke‚ 011023172835Z0 0 U 0#7K^ô 011024120355Z0 0 U 0#7KbÈ 011025120015Z0 0 U 0#7K%( 011025120901Z0 0 U 0#7Kh: 011025180127Z0 0 U 0#7Kf– 011025195301Z0 0 U 0#7K2 011026120204Z0 0 U 0#7K= 011026120331Z0 0 U 0#7K= 011026120421Z0 0 U 0#7K=v 011026120527Z0 0 U 0#7K=G 011026120612Z0 0 U 0#7K=' 011026120658Z0 0 U 0#7KZ  011026165836Z0 0 U 0#7Kgq 011026165950Z0 0 U 0#7Keï 011026170123Z0 0 U 0#7Kg 011026170232Z0 0 U 0#7Kg 011026170306Z0 0 U 0#7KWà 011026170646Z0 0 U 0#7KhÇ 011026170754Z0 0 U 0#7Kb 011026203357Z0 0 U 0#7Kb 011026203415Z0 0 U 0#7Ke© 011029145636Z0 0 U 0#7Ki5 011029145859Z0 0 U 0#7KSg 011029150155Z0 0 U 0#7KbŠ 011029150340Z0 0 U 0#7Ke¦ 011029180247Z0 0 U 0#7Ki 011029180443Z0 0 U 0#7Kep 011029223549Z0 0 U 0#7KC¨ 011029225032Z0 0 U 0#7Kik 011030180954Z0 0 U 0#7Khu 011030181126Z0 0 U 0#7Kh= 011030181256Z0 0 U 0#7Ki© 011030181458Z0 0 U 0#7Kc© 011031175606Z0 0 U 0#7KfO 011031180041Z0 0 U 0#7Kc¦ 011031180120Z0 0 U 0#7KdÄ 011031180202Z0 0 U 0#7K`Z 011031201914Z0 0 U 0#7KiÍ 011031202243Z0 0 U 0#7Kõ 011031202428Z0 0 U 0#7K  011031202533Z0 0 U 0#7K É 011031202641Z0 0 U 0#7KGX 011031202725Z0 0 U 0#7K 011031202810Z0 0 U 0#7KG^ 011031202856Z0 0 U 0#7K 011031202940Z0 0 U 0#7KG[ 011031203024Z0 0 U 0#7K 011031203140Z0 0 U 0#7KGa 011031203237Z0 0 U 0#7K 011031203318Z0 0 U 0#7K_Ì 011031203911Z0 0 U 0#7Kav 011031204003Z0 0 U 0#7K_É 011031204210Z0 0 U 0#7Kh. 011101125941Z0 0 U 0#7Kj  011101130045Z0 0 U 0#7Kj) 011101130129Z0 0 U 0#7Kiß 011101184657Z0 0 U 0#7KTá 011101204219Z0 0 U 0#7K± 011101211340Z0 0 U 0#7JþË 011101211448Z0 0 U 0#7Kh 011102125854Z0 0 U 0#7Ki) 011102181832Z0 0 U 0#7K]™ 011102182015Z0 0 U 0#7Kk 011102210017Z0 0 U 0#7K¬ 011105125729Z0 0 U 0#7Ke7 011105150821Z0 0 U 0#7K© 011105150958Z0 0 U 0#7Kî 011105151153Z0 0 U 0#7KZ 011105151241Z0 0 U 0#7KÞ 011105151407Z0 0 U 0#7Kj 011105195953Z0 0 U 0#7Kjƒ 011105200116Z0 0 U 0#7K0Á 011105210130Z0 0 U 0#7Kj/ 011106125747Z0 0 U 0#7KkG 011106173500Z0 0 U 0#7Ki‰ 011106173632Z0 0 U 0#7Kfa 011106173744Z0 0 U 0#7KF 011106173916Z0 0 U 0#7KS\ 011106194220Z0 0 U 0#7Kg' 011106194338Z0 0 U 0#7Kj& 011106194731Z0 0 U 0#7Kjq 011106205745Z0 0 U 0#7Kap 011107125825Z0 0 U 0#7KgW 011107125914Z0 0 U 0#7Kcž 011107125956Z0 0 U 0#7Kb[ 011107130255Z0 0 U 0#7Kbº 011107130442Z0 0 U 0#7Kk 011107130603Z0 0 U 0#7Kk¬ 011107161935Z0 0 U 0#7K* 011107162028Z0 0 U 0#7Kkÿ 011107183044Z0 0 U 0#7Kú 011107183214Z0 0 U 0#7K# 011107183310Z0 0 U 0#7K  011107205149Z0 0 U 0#7Kl 011107205348Z0 0 U 0#7Kk‘ 011108130245Z0 0 U 0#7Kl¿ 011108205123Z0 0 U 0#7Km` 011108214519Z0 0 U 0#7Kj# 011108220042Z0 0 U 0#7KÆ 011108222136Z0 0 U 0#7KdU 011109163039Z0 0 U 0#7KdO 011109163237Z0 0 U 0#7KdR 011109163359Z0 0 U 0#7Klz 011109163508Z0 0 U 0#7K^• 011109163727Z0 0 U 0#7Kl, 011109164006Z0 0 U 0#7KÄ 011109210735Z0 0 U 0#7KmM 011109211253Z0 0 U 0#7K+‘ 011109211833Z0 0 U 0#7K\¿ 011109212112Z0 0 U 0#7K ” 011109212244Z0 0 U 0#7KNk 011109212428Z0 0 U 0#7K 011112150140Z0 0 U 0#7KiS 011112190815Z0 0 U 0#7Kk' 011112190927Z0 0 U 0#7KkÇ 011112191106Z0 0 U 0#7Kµ 011112191209Z0 0 U 0#7KkÒ 011112202048Z0 0 U 0#7Kb´ 011112202142Z0 0 U 0#7Km“ 011112215010Z0 0 U 0#7Kx 011113180723Z0 0 U 0#7KnÅ 011113180818Z0 0 U 0#7Ko 011113192702Z0 0 U 0#7Km® 011113220623Z0 0 U  00.0 U ¡0U#0€ðbU=³ÿ kûP„—óíbÐ0  *†H†÷ \8r>•]AªU >{ô8ûøÊ‰’œ¦’e‰HÜû— îû³GàØ,œ %%% See MIT-LICENSE at the top dir for licensing information. %%% %%% -------------------------------------------------------------------- -vc('$Id$ '). -export([topen_bind/1,topen_bind/2,all/0,t10/0,t20/0,t21/0,t22/0, t23/0,t24/0,t25/0,t26/0,t27/0,debug/1,t30/0,t31/0, t40/0,t41/0,t50/0,t51/0]). -export([crl1/0]). -export([switch/1]). -export([junk/0]). -include("ELDAPv3.hrl"). -include("eldap.hrl"). junk() -> DN = "cn=Torbjorn Tornkvist, ou=people, o=Bluetail AB, dc=bluetail, dc=com", Msg = #'LDAPMessage'{messageID = 1, protocolOp = {delRequest,DN}}, asn1rt:encode('ELDAPv3', 'LDAPMessage', Msg). %%% -------------------------------------------------------------------- %%% TEST STUFF %%% ---------- %%% When adding a new test case it can be useful to %%% switch on debugging, i.e debug(t) in the call to %%% topen_bind/2. %%% -------------------------------------------------------------------- all() -> Check = "=== Check the result of the previous test case !~n", t10(), t20(),t21(),t22(),t23(),t24(),t25(),t26(),t27(), t30(),t26(Check),t31(),t26(Check), t40(),t26(Check),t41(),t26(Check), t50(),t26(Check),t51(),t26(Check), ok. %%% %%% Setup a connection and bind using simple authentication %%% t10() -> F = fun() -> sleep(), line(), io:format("=== TEST 10 (connection setup + simple auth)~n"), line(), X = topen_bind("localhost", debug(f)), io:format("~p~n",[X]), X end, go(F). %%% %%% Do an equality match: sn = Tornkvist %%% t20() -> F = fun() -> sleep(), line(), io:format("=== TEST 20 (equality match)~n"), line(), {ok,S} = topen_bind("localhost", debug(f)), Filter = eldap:equalityMatch("sn","Tornkvist"), X=(catch eldap:search(S, [{base, "dc=bluetail, dc=com"}, {filter, Filter}])), io:format("~p~n",[X]), X end, go(F). %%% %%% Do a substring match: sn = To*kv*st %%% t21() -> F = fun() -> sleep(), line(), io:format("=== TEST 21 (substring match)~n"), line(), {ok,S} = topen_bind("localhost", debug(f)), Filter = eldap:substrings("sn", [{initial,"To"}, {any,"kv"}, {final,"st"}]), X=(catch eldap:search(S, [{base, "dc=bluetail, dc=com"}, {filter, Filter}])), io:format("~p~n",[X]), X end, go(F). %%% %%% Do a substring match: sn = *o* %%% and do only retrieve the cn attribute %%% t22() -> F = fun() -> sleep(), line(), io:format("=== TEST 22 (substring match + return 'cn' only)~n"), line(), {ok,S} = topen_bind("localhost", debug(f)), Filter = eldap:substrings("sn", [{any,"o"}]), X=(catch eldap:search(S, [{base, "dc=bluetail, dc=com"}, {filter, Filter}, {attributes,["cn"]}])), io:format("~p~n",[X]), X end, go(F). %%% %%% Do a present search for the attribute 'objectclass' %%% on the base level. %%% t23() -> F = fun() -> sleep(), line(), io:format("=== TEST 23 (objectclass=* , base level)~n"), line(), {ok,S} = topen_bind("localhost", debug(f)), X=(catch eldap:search(S, [{base, "dc=bluetail, dc=com"}, {filter, eldap:present("objectclass")}, {scope,eldap:baseObject()}])), io:format("~p~n",[X]), X end, go(F). %%% %%% Do a present search for the attribute 'objectclass' %%% on a single level. %%% t24() -> F = fun() -> sleep(), line(), io:format("=== TEST 24 (objectclass=* , single level)~n"), line(), {ok,S} = topen_bind("localhost", debug(f)), X=(catch eldap:search(S, [{base, "dc=bluetail, dc=com"}, {filter, eldap:present("objectclass")}, {scope,eldap:singleLevel()}])), io:format("~p~n",[X]), X end, go(F). %%% %%% Do a present search for the attribute 'objectclass' %%% on the whole subtree. %%% t25() -> F = fun() -> sleep(), line(), io:format("=== TEST 25 (objectclass=* , whole subtree)~n"), line(), {ok,S} = topen_bind("localhost", debug(f)), X=(catch eldap:search(S, [{base, "dc=bluetail, dc=com"}, {filter, eldap:present("objectclass")}, {scope,eldap:wholeSubtree()}])), io:format("~p~n",[X]), X end, go(F). %%% %%% Do a present search for the attributes %%% 'objectclass' and 'sn' on the whole subtree. %%% t26() -> t26([]). t26(Heading) -> F = fun() -> sleep(), line(), heading(Heading, "=== TEST 26 (objectclass=* and sn=*)~n"), line(), {ok,S} = topen_bind("localhost", debug(f)), Filter = eldap:'and'([eldap:present("objectclass"), eldap:present("sn")]), X=(catch eldap:search(S, [{base, "dc=bluetail, dc=com"}, {filter, Filter}, {scope,eldap:wholeSubtree()}])), io:format("~p~n",[X]), X end, go(F). %%% %%% Do a present search for the attributes %%% 'objectclass' and (not 'sn') on the whole subtree. %%% t27() -> F = fun() -> sleep(), line(), io:format("=== TEST 27 (objectclass=* and (not sn))~n"), line(), {ok,S} = topen_bind("localhost", debug(f)), Filter = eldap:'and'([eldap:present("objectclass"), eldap:'not'(eldap:present("sn"))]), X=(catch eldap:search(S, [{base, "dc=bluetail, dc=com"}, {filter, Filter}, {scope,eldap:wholeSubtree()}])), io:format("~p~n",[X]), X end, go(F). %%% %%% Replace the 'telephoneNumber' attribute and %%% add a new attribute 'description' %%% t30() -> t30([]). t30(Heading) -> F = fun() -> sleep(), {_,_,Tno} = erlang:now(), Stno = integer_to_list(Tno), Desc = "LDAP hacker " ++ Stno, line(), heading(Heading, "=== TEST 30 (replace telephoneNumber/" ++ Stno ++ " add description/" ++ Desc ++ ")~n"), line(), {ok,S} = topen_bind("localhost", debug(f)), Obj = "cn=Torbjorn Tornkvist, ou=people, o=Bluetail AB, dc=bluetail, dc=com", Mod = [eldap:mod_replace("telephoneNumber", [Stno]), eldap:mod_add("description", [Desc])], X=(catch eldap:modify(S, Obj, Mod)), io:format("~p~n",[X]), X end, go(F). %%% %%% Delete attribute 'description' %%% t31() -> t31([]). t31(Heading) -> F = fun() -> sleep(), {_,_,Tno} = erlang:now(), line(), heading(Heading, "=== TEST 31 (delete 'description' attribute)~n"), line(), {ok,S} = topen_bind("localhost", debug(f)), Obj = "cn=Torbjorn Tornkvist, ou=people, o=Bluetail AB, dc=bluetail, dc=com", Mod = [eldap:mod_delete("description", [])], X=(catch eldap:modify(S, Obj, Mod)), io:format("~p~n",[X]), X end, go(F). %%% %%% Add an entry %%% t40() -> t40([]). t40(Heading) -> F = fun() -> sleep(), {_,_,Tno} = erlang:now(), line(), heading(Heading, "=== TEST 40 (add entry 'Bill Valentine')~n"), line(), {ok,S} = topen_bind("localhost", debug(f)), Entry = "cn=Bill Valentine, ou=people, o=Bluetail AB, dc=bluetail, dc=com", X=(catch eldap:add(S, Entry, [{"objectclass", ["person"]}, {"cn", ["Bill Valentine"]}, {"sn", ["Valentine"]}, {"telephoneNumber", ["545 555 00"]}])), io:format("~p~n",[X]), X end, go(F). %%% %%% Delete an entry %%% t41() -> t41([]). t41(Heading) -> F = fun() -> sleep(), {_,_,Tno} = erlang:now(), line(), heading(Heading, "=== TEST 41 (delete entry 'Bill Valentine')~n"), line(), {ok,S} = topen_bind("localhost", debug(f)), Entry = "cn=Bill Valentine, ou=people, o=Bluetail AB, dc=bluetail, dc=com", X=(catch eldap:delete(S, Entry)), io:format("~p~n",[X]), X end, go(F). %%% %%% Modify the DN of an entry %%% t50() -> t50([]). t50(Heading) -> F = fun() -> sleep(), {_,_,Tno} = erlang:now(), line(), heading(Heading, "=== TEST 50 (modify DN to: 'Torbjorn M.Tornkvist')~n"), line(), {ok,S} = topen_bind("localhost", debug(f)), Entry = "cn=Torbjorn Tornkvist, ou=people, o=Bluetail AB, dc=bluetail, dc=com", X=(catch eldap:modify_dn(S, Entry, "cn=Torbjorn M.Tornkvist", false, [])), io:format("~p~n",[X]), X end, go(F). %%% %%% Modify the DN of an entry and remove the RDN attribute. %%% NB: Must be run after: 't50' ! %%% t51() -> t51([]). t51(Heading) -> F = fun() -> sleep(), {_,_,Tno} = erlang:now(), line(), heading(Heading, "=== TEST 51 (modify DN, remove the RDN attribute)~n"), line(), {ok,S} = topen_bind("localhost", debug(f)), Entry = "cn=Torbjorn M.Tornkvist, ou=people, o=Bluetail AB, dc=bluetail, dc=com", X=(catch eldap:modify_dn(S, Entry, "cn=Torbjorn Tornkvist", true, [])), io:format("~p~n",[X]), X end, go(F). %%% -------------------------------------------------------------------- %%% Test cases for certificate revocation lists %%% -------------------------------------------------------------------- crl1() -> F = fun() -> sleep(), line(), io:format("=== CRL-TEST 1 ~n"), line(), {ok,S} = crl_open_bind("localhost", debug(f)), Filter = eldap:equalityMatch("cn","Administrative CA"), X=(catch eldap:search(S, [{base, "o=Post Danmark, c=DK"}, {filter, Filter}, {attributes,["certificateRevocationList"]}])), dump_to_file("test-crl1.result",X), ok end, go(F). dump_to_file(Fname,{ok,Res}) -> case Res#eldap_search_result.entries of [Entry|_] -> case Entry#eldap_entry.attributes of [{Attribute,Value}|_] -> file:write_file(Fname,list_to_binary(Value)), io:format("Value of '~s' dumped to file: ~s~n", [Attribute,Fname]); Else -> io:format("ERROR(dump_to_file): no attributes found~n",[]) end; Else -> io:format("ERROR(dump_to_file): no entries found~n",[]) end. switch(1) -> %% %% SEARCH %% F = fun() -> sleep(), line(), io:format("=== SWITCH-TEST 1 (short-search)~n"), line(), {ok,S} = sw_open_bind("korp", debug(t)), Filter = eldap:equalityMatch("cn","Administrative CA"), X=(catch eldap:search(S, [{base, "o=Post Danmark, c=DK"}, {filter, Filter}, {attributes,["cn"]}])), io:format("RESULT: ~p~n", [X]), %%dump_to_file("test-switch-1.result",X), eldap:close(S), ok end, go(F); switch(2) -> %% %% ADD AN ENTRY %% F = fun() -> sleep(), line(), io:format("=== SWITCH-TEST 2 (add-entry)~n"), line(), {ok,S} = sw_open_bind("korp", debug(t)), Entry = "cn=Bill Valentine, o=Post Danmark, c=DK", X=(catch eldap:add(S, Entry, [{"objectclass", ["person"]}, {"cn", ["Bill Valentine"]}, {"sn", ["Valentine"]} ])), io:format("~p~n",[X]), eldap:close(S), X end, go(F); switch(3) -> %% %% SEARCH FOR THE NEWLEY ADDED ENTRY %% F = fun() -> sleep(), line(), io:format("=== SWITCH-TEST 3 (search-added)~n"), line(), {ok,S} = sw_open_bind("korp", debug(t)), Filter = eldap:equalityMatch("cn","Bill Valentine"), X=(catch eldap:search(S, [{base, "o=Post Danmark, c=DK"}, {filter, Filter}, {attributes,["cn"]}])), io:format("RESULT: ~p~n", [X]), %%dump_to_file("test-switch-1.result",X), eldap:close(S), ok end, go(F); switch(4) -> %% %% DELETE THE NEWLEY ADDED ENTRY %% F = fun() -> sleep(), line(), io:format("=== SWITCH-TEST 4 (delete-added)~n"), line(), {ok,S} = sw_open_bind("korp", debug(t)), Entry = "cn=Bill Valentine, o=Post Danmark, c=DK", X=(catch eldap:delete(S, Entry)), io:format("RESULT: ~p~n", [X]), %%dump_to_file("test-switch-1.result",X), eldap:close(S), ok end, go(F). %%% --------------- %%% Misc. functions %%% --------------- sw_open_bind(Host) -> sw_open_bind(Host, debug(t)). sw_open_bind(Host, Dbg) -> sw_open_bind(Host, Dbg, "cn=Torbjorn Tornkvist,o=Post Danmark,c=DK", "qwe123"). sw_open_bind(Host, LogFun, RootDN, Passwd) -> Opts = [{log,LogFun},{port,9779}], {ok,Handle} = eldap:open([Host], Opts), {eldap:simple_bind(Handle, RootDN, Passwd), Handle}. crl_open_bind(Host) -> crl_open_bind(Host, debug(t)). crl_open_bind(Host, Dbg) -> do_open_bind(Host, Dbg, "o=Post Danmark, c=DK", "hejsan"). topen_bind(Host) -> topen_bind(Host, debug(t)). topen_bind(Host, Dbg) -> do_open_bind(Host, Dbg, "dc=bluetail, dc=com", "hejsan"). do_open_bind(Host, LogFun, RootDN, Passwd) -> Opts = [{log,LogFun}], {ok,Handle} = eldap:open([Host], Opts), {eldap:simple_bind(Handle, RootDN, Passwd), Handle}. debug(t) -> fun(L,S,A) -> io:format("--- " ++ S, A) end; debug(1) -> fun(L,S,A) when L =< 1 -> io:format("--- " ++ S, A) end; debug(2) -> fun(L,S,A) when L =< 2 -> io:format("--- " ++ S, A) end; debug(f) -> false. sleep() -> msleep(400). %sleep(Sec) -> msleep(Sec*1000). msleep(T) -> receive after T -> true end. line() -> S = "==============================================================\n", io:format(S). heading([], Heading) -> io:format(Heading); heading(Heading, _ ) -> io:format(Heading). %%% %%% Process to run the test case %%% go(F) -> Self = self(), Pid = spawn(fun() -> run(F,Self) end), receive {Pid, X} -> ok end. run(F, Pid) -> Pid ! {self(),catch F()}. rabbitmq-server-3.2.4/plugins-src/eldap-wrapper/eldap-git/Makefile0000644000000000000000000000007112305126066023641 0ustar rootroot all: (cd src;$(MAKE)) clean: (cd src;$(MAKE) clean) rabbitmq-server-3.2.4/plugins-src/eldap-wrapper/eldap-git/ebin/0000755000000000000000000000000012305126066023120 5ustar rootrootrabbitmq-server-3.2.4/plugins-src/eldap-wrapper/eldap-git/ebin/eldap.app0000644000000000000000000000026712305126066024714 0ustar rootroot{application, eldap, [{description, "LDAP Client Library"}, {vsn, "0.01"}, {modules, [ eldap, 'ELDAPv3' ]}, {registered, []}, {applications, [kernel, stdlib]} ]}. rabbitmq-server-3.2.4/plugins-src/eldap-wrapper/eldap-git/include/0000755000000000000000000000000012305126066023626 5ustar rootrootrabbitmq-server-3.2.4/plugins-src/eldap-wrapper/eldap-git/include/eldap.hrl0000644000000000000000000000136212305126066025424 0ustar rootroot-ifndef( _ELDAP_HRL ). -define( _ELDAP_HRL , 1 ). %%% %%% Search input parameters %%% -record(eldap_search, { base = [], % Baseobject filter = [], % Search conditions scope, % Search scope attributes = [], % Attributes to be returned types_only = false, % Return types+values or types timeout = 0 % Timelimit for search }). %%% %%% Returned search result %%% -record(eldap_search_result, { entries = [], % List of #eldap_entry{} records referrals = [] % List of referrals }). %%% %%% LDAP entry %%% -record(eldap_entry, { object_name = "", % The DN for the entry attributes = [] % List of {Attribute, Value} pairs }). -endif. rabbitmq-server-3.2.4/plugins-src/eldap-wrapper/eldap-git/.done0000644000000000000000000000000012305126066023117 0ustar rootrootrabbitmq-server-3.2.4/plugins-src/eldap-wrapper/eldap-git/LICENSE0000644000000000000000000000205212305126066023207 0ustar rootroot Copyright (c) 2010, Torbjorn Tornkvist Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. rabbitmq-server-3.2.4/plugins-src/eldap-wrapper/remove-eldap-fsm.patch0000644000000000000000000010425212305126066024525 0ustar rootrootdiff --git a/src/eldap_fsm.erl b/src/eldap_fsm.erl deleted file mode 100644 index 381ce69..0000000 --- a/src/eldap_fsm.erl +++ /dev/null @@ -1,946 +0,0 @@ --module(eldap_fsm). -%%% -------------------------------------------------------------------- -%%% Created: 12 Oct 2000 by Tobbe -%%% Function: Erlang client LDAP implementation according RFC 2251. -%%% The interface is based on RFC 1823, and -%%% draft-ietf-asid-ldap-c-api-00.txt -%%% -%%% Copyright (C) 2000 Torbjörn Törnkvist -%%% Copyright (c) 2010 Torbjorn Tornkvist -%%% See MIT-LICENSE at the top dir for licensing information. -%%% -%%% Modified by Sean Hinde 7th Dec 2000 -%%% Turned into gen_fsm, made non-blocking, added timers etc to support this. -%%% Now has the concept of a name (string() or atom()) per instance which allows -%%% multiple users to call by name if so desired. -%%% -%%% Can be configured with start_link parameters or use a config file to get -%%% host to connect to, dn, password, log function etc. -%%% -------------------------------------------------------------------- - - -%%%---------------------------------------------------------------------- -%%% LDAP Client state machine. -%%% Possible states are: -%%% connecting - actually disconnected, but retrying periodically -%%% wait_bind_response - connected and sent bind request -%%% active - bound to LDAP Server and ready to handle commands -%%%---------------------------------------------------------------------- - -%%-compile(export_all). -%%-export([Function/Arity, ...]). - --behaviour(gen_fsm). - -%% External exports --export([start_link/1, start_link/5, start_link/6]). - --export([baseObject/0,singleLevel/0,wholeSubtree/0,close/1, - equalityMatch/2,greaterOrEqual/2,lessOrEqual/2, - approxMatch/2,search/2,substrings/2,present/1, - 'and'/1,'or'/1,'not'/1,modify/3, mod_add/2, mod_delete/2, - mod_replace/2, add/3, delete/2, modify_dn/5]). --export([debug_level/2, get_status/1]). - -%% gen_fsm callbacks --export([init/1, connecting/2, - connecting/3, wait_bind_response/3, active/3, handle_event/3, - handle_sync_event/4, handle_info/3, terminate/3, code_change/4]). - - --import(lists,[concat/1]). - --include("ELDAPv3.hrl"). --include("eldap.hrl"). - --define(LDAP_VERSION, 3). --define(RETRY_TIMEOUT, 5000). --define(BIND_TIMEOUT, 10000). --define(CMD_TIMEOUT, 5000). --define(MAX_TRANSACTION_ID, 65535). --define(MIN_TRANSACTION_ID, 0). - --record(eldap, {version = ?LDAP_VERSION, - hosts, % Possible hosts running LDAP servers - host = null, % Connected Host LDAP server - port = 389 , % The LDAP server port - fd = null, % Socket filedescriptor. - rootdn = "", % Name of the entry to bind as - passwd, % Password for (above) entry - id = 0, % LDAP Request ID - log, % User provided log function - bind_timer, % Ref to bind timeout - dict, % dict holding operation params and results - debug_level % Integer debug/logging level - }). - -%%%---------------------------------------------------------------------- -%%% API -%%%---------------------------------------------------------------------- -start_link(Name) -> - Reg_name = list_to_atom("eldap_" ++ Name), - gen_fsm:start_link({local, Reg_name}, ?MODULE, [], []). - -start_link(Name, Hosts, Port, Rootdn, Passwd) -> - Log = fun(N, Fmt, Args) -> io:format("---- " ++ Fmt, [Args]) end, - Reg_name = list_to_atom("eldap_" ++ Name), - gen_fsm:start_link({local, Reg_name}, ?MODULE, {Hosts, Port, Rootdn, Passwd, Log}, []). - -start_link(Name, Hosts, Port, Rootdn, Passwd, Log) -> - Reg_name = list_to_atom("eldap_" ++ Name), - gen_fsm:start_link({local, Reg_name}, ?MODULE, {Hosts, Port, Rootdn, Passwd, Log}, []). - -%%% -------------------------------------------------------------------- -%%% Set Debug Level. 0 - none, 1 - errors, 2 - ldap events -%%% -------------------------------------------------------------------- -debug_level(Handle, N) when integer(N) -> - Handle1 = get_handle(Handle), - gen_fsm:sync_send_all_state_event(Handle1, {debug_level,N}). - -%%% -------------------------------------------------------------------- -%%% Get status of connection. -%%% -------------------------------------------------------------------- -get_status(Handle) -> - Handle1 = get_handle(Handle), - gen_fsm:sync_send_all_state_event(Handle1, get_status). - -%%% -------------------------------------------------------------------- -%%% Shutdown connection (and process) asynchronous. -%%% -------------------------------------------------------------------- -close(Handle) -> - Handle1 = get_handle(Handle), - gen_fsm:send_all_state_event(Handle1, close). - -%%% -------------------------------------------------------------------- -%%% Add an entry. The entry field MUST NOT exist for the AddRequest -%%% to succeed. The parent of the entry MUST exist. -%%% Example: -%%% -%%% add(Handle, -%%% "cn=Bill Valentine, ou=people, o=Bluetail AB, dc=bluetail, dc=com", -%%% [{"objectclass", ["person"]}, -%%% {"cn", ["Bill Valentine"]}, -%%% {"sn", ["Valentine"]}, -%%% {"telephoneNumber", ["545 555 00"]}] -%%% ) -%%% -------------------------------------------------------------------- -add(Handle, Entry, Attributes) when list(Entry),list(Attributes) -> - Handle1 = get_handle(Handle), - gen_fsm:sync_send_event(Handle1, {add, Entry, add_attrs(Attributes)}). - -%%% Do sanity check ! -add_attrs(Attrs) -> - F = fun({Type,Vals}) when list(Type),list(Vals) -> - %% Confused ? Me too... :-/ - {'AddRequest_attributes',Type, Vals} - end, - case catch lists:map(F, Attrs) of - {'EXIT', _} -> throw({error, attribute_values}); - Else -> Else - end. - - -%%% -------------------------------------------------------------------- -%%% Delete an entry. The entry consists of the DN of -%%% the entry to be deleted. -%%% Example: -%%% -%%% delete(Handle, -%%% "cn=Bill Valentine, ou=people, o=Bluetail AB, dc=bluetail, dc=com" -%%% ) -%%% -------------------------------------------------------------------- -delete(Handle, Entry) when list(Entry) -> - Handle1 = get_handle(Handle), - gen_fsm:sync_send_event(Handle1, {delete, Entry}). - -%%% -------------------------------------------------------------------- -%%% Modify an entry. Given an entry a number of modification -%%% operations can be performed as one atomic operation. -%%% Example: -%%% -%%% modify(Handle, -%%% "cn=Torbjorn Tornkvist, ou=people, o=Bluetail AB, dc=bluetail, dc=com", -%%% [replace("telephoneNumber", ["555 555 00"]), -%%% add("description", ["LDAP hacker"])] -%%% ) -%%% -------------------------------------------------------------------- -modify(Handle, Object, Mods) when list(Object), list(Mods) -> - Handle1 = get_handle(Handle), - gen_fsm:sync_send_event(Handle1, {modify, Object, Mods}). - -%%% -%%% Modification operations. -%%% Example: -%%% replace("telephoneNumber", ["555 555 00"]) -%%% -mod_add(Type, Values) when list(Type), list(Values) -> m(add, Type, Values). -mod_delete(Type, Values) when list(Type), list(Values) -> m(delete, Type, Values). -mod_replace(Type, Values) when list(Type), list(Values) -> m(replace, Type, Values). - -m(Operation, Type, Values) -> - #'ModifyRequest_modification_SEQOF'{ - operation = Operation, - modification = #'AttributeTypeAndValues'{ - type = Type, - vals = Values}}. - -%%% -------------------------------------------------------------------- -%%% Modify an entry. Given an entry a number of modification -%%% operations can be performed as one atomic operation. -%%% Example: -%%% -%%% modify_dn(Handle, -%%% "cn=Bill Valentine, ou=people, o=Bluetail AB, dc=bluetail, dc=com", -%%% "cn=Ben Emerson", -%%% true, -%%% "" -%%% ) -%%% -------------------------------------------------------------------- -modify_dn(Handle, Entry, NewRDN, DelOldRDN, NewSup) - when list(Entry),list(NewRDN),atom(DelOldRDN),list(NewSup) -> - Handle1 = get_handle(Handle), - gen_fsm:sync_send_event(Handle1, {modify_dn, Entry, NewRDN, bool_p(DelOldRDN), optional(NewSup)}). - -%%% Sanity checks ! - -bool_p(Bool) when Bool==true;Bool==false -> Bool. - -optional([]) -> asn1_NOVALUE; -optional(Value) -> Value. - -%%% -------------------------------------------------------------------- -%%% Synchronous search of the Directory returning a -%%% requested set of attributes. -%%% -%%% Example: -%%% -%%% Filter = eldap:substrings("sn", [{any,"o"}]), -%%% eldap:search(S, [{base, "dc=bluetail, dc=com"}, -%%% {filter, Filter}, -%%% {attributes,["cn"]}])), -%%% -%%% Returned result: {ok, #eldap_search_result{}} -%%% -%%% Example: -%%% -%%% {ok,{eldap_search_result, -%%% [{eldap_entry, -%%% "cn=Magnus Froberg, dc=bluetail, dc=com", -%%% [{"cn",["Magnus Froberg"]}]}, -%%% {eldap_entry, -%%% "cn=Torbjorn Tornkvist, dc=bluetail, dc=com", -%%% [{"cn",["Torbjorn Tornkvist"]}]}], -%%% []}} -%%% -%%% -------------------------------------------------------------------- -search(Handle, A) when record(A, eldap_search) -> - call_search(Handle, A); -search(Handle, L) when list(Handle), list(L) -> - case catch parse_search_args(L) of - {error, Emsg} -> {error, Emsg}; - {'EXIT', Emsg} -> {error, Emsg}; - A when record(A, eldap_search) -> call_search(Handle, A) - end. - -call_search(Handle, A) -> - Handle1 = get_handle(Handle), - gen_fsm:sync_send_event(Handle1, {search, A}). - -parse_search_args(Args) -> - parse_search_args(Args, #eldap_search{scope = wholeSubtree}). - -parse_search_args([{base, Base}|T],A) -> - parse_search_args(T,A#eldap_search{base = Base}); -parse_search_args([{filter, Filter}|T],A) -> - parse_search_args(T,A#eldap_search{filter = Filter}); -parse_search_args([{scope, Scope}|T],A) -> - parse_search_args(T,A#eldap_search{scope = Scope}); -parse_search_args([{attributes, Attrs}|T],A) -> - parse_search_args(T,A#eldap_search{attributes = Attrs}); -parse_search_args([{types_only, TypesOnly}|T],A) -> - parse_search_args(T,A#eldap_search{types_only = TypesOnly}); -parse_search_args([{timeout, Timeout}|T],A) when integer(Timeout) -> - parse_search_args(T,A#eldap_search{timeout = Timeout}); -parse_search_args([H|T],A) -> - throw({error,{unknown_arg, H}}); -parse_search_args([],A) -> - A. - -%%% -%%% The Scope parameter -%%% -baseObject() -> baseObject. -singleLevel() -> singleLevel. -wholeSubtree() -> wholeSubtree. - -%%% -%%% Boolean filter operations -%%% -'and'(ListOfFilters) when list(ListOfFilters) -> {'and',ListOfFilters}. -'or'(ListOfFilters) when list(ListOfFilters) -> {'or', ListOfFilters}. -'not'(Filter) when tuple(Filter) -> {'not',Filter}. - -%%% -%%% The following Filter parameters consist of an attribute -%%% and an attribute value. Example: F("uid","tobbe") -%%% -equalityMatch(Desc, Value) -> {equalityMatch, av_assert(Desc, Value)}. -greaterOrEqual(Desc, Value) -> {greaterOrEqual, av_assert(Desc, Value)}. -lessOrEqual(Desc, Value) -> {lessOrEqual, av_assert(Desc, Value)}. -approxMatch(Desc, Value) -> {approxMatch, av_assert(Desc, Value)}. - -av_assert(Desc, Value) -> - #'AttributeValueAssertion'{attributeDesc = Desc, - assertionValue = Value}. - -%%% -%%% Filter to check for the presence of an attribute -%%% -present(Attribute) when list(Attribute) -> - {present, Attribute}. - - -%%% -%%% A substring filter seem to be based on a pattern: -%%% -%%% InitValue*AnyValue*FinalValue -%%% -%%% where all three parts seem to be optional (at least when -%%% talking with an OpenLDAP server). Thus, the arguments -%%% to substrings/2 looks like this: -%%% -%%% Type ::= string( ) -%%% SubStr ::= listof( {initial,Value} | {any,Value}, {final,Value}) -%%% -%%% Example: substrings("sn",[{initial,"To"},{any,"kv"},{final,"st"}]) -%%% will match entries containing: 'sn: Tornkvist' -%%% -substrings(Type, SubStr) when list(Type), list(SubStr) -> - Ss = {'SubstringFilter_substrings',v_substr(SubStr)}, - {substrings,#'SubstringFilter'{type = Type, - substrings = Ss}}. - - -get_handle(Pid) when pid(Pid) -> Pid; -get_handle(Atom) when atom(Atom) -> Atom; -get_handle(Name) when list(Name) -> list_to_atom("eldap_" ++ Name). -%%%---------------------------------------------------------------------- -%%% Callback functions from gen_fsm -%%%---------------------------------------------------------------------- - -%%---------------------------------------------------------------------- -%% Func: init/1 -%% Returns: {ok, StateName, StateData} | -%% {ok, StateName, StateData, Timeout} | -%% ignore | -%% {stop, StopReason} -%% I use the trick of setting a timeout of 0 to pass control into the -%% process. -%%---------------------------------------------------------------------- -init([]) -> - case get_config() of - {ok, Hosts, Rootdn, Passwd, Log} -> - init({Hosts, Rootdn, Passwd, Log}); - {error, Reason} -> - {stop, Reason} - end; -init({Hosts, Port, Rootdn, Passwd, Log}) -> - {ok, connecting, #eldap{hosts = Hosts, - port = Port, - rootdn = Rootdn, - passwd = Passwd, - id = 0, - log = Log, - dict = dict:new(), - debug_level = 0}, 0}. - -%%---------------------------------------------------------------------- -%% Func: StateName/2 -%% Called when gen_fsm:send_event/2,3 is invoked (async) -%% Returns: {next_state, NextStateName, NextStateData} | -%% {next_state, NextStateName, NextStateData, Timeout} | -%% {stop, Reason, NewStateData} -%%---------------------------------------------------------------------- -connecting(timeout, S) -> - {ok, NextState, NewS} = connect_bind(S), - {next_state, NextState, NewS}. - -%%---------------------------------------------------------------------- -%% Func: StateName/3 -%% Called when gen_fsm:sync_send_event/2,3 is invoked. -%% Returns: {next_state, NextStateName, NextStateData} | -%% {next_state, NextStateName, NextStateData, Timeout} | -%% {reply, Reply, NextStateName, NextStateData} | -%% {reply, Reply, NextStateName, NextStateData, Timeout} | -%% {stop, Reason, NewStateData} | -%% {stop, Reason, Reply, NewStateData} -%%---------------------------------------------------------------------- -connecting(Event, From, S) -> - Reply = {error, connecting}, - {reply, Reply, connecting, S}. - -wait_bind_response(Event, From, S) -> - Reply = {error, wait_bind_response}, - {reply, Reply, wait_bind_response, S}. - -active(Event, From, S) -> - case catch send_command(Event, From, S) of - {ok, NewS} -> - {next_state, active, NewS}; - {error, Reason} -> - {reply, {error, Reason}, active, S}; - {'EXIT', Reason} -> - {reply, {error, Reason}, active, S} - end. - -%%---------------------------------------------------------------------- -%% Func: handle_event/3 -%% Called when gen_fsm:send_all_state_event/2 is invoked. -%% Returns: {next_state, NextStateName, NextStateData} | -%% {next_state, NextStateName, NextStateData, Timeout} | -%% {stop, Reason, NewStateData} -%%---------------------------------------------------------------------- -handle_event(close, StateName, S) -> - gen_tcp:close(S#eldap.fd), - {stop, closed, S}; - -handle_event(Event, StateName, S) -> - {next_state, StateName, S}. - -%%---------------------------------------------------------------------- -%% Func: handle_sync_event/4 -%% Called when gen_fsm:sync_send_all_state_event/2,3 is invoked -%% Returns: {next_state, NextStateName, NextStateData} | -%% {next_state, NextStateName, NextStateData, Timeout} | -%% {reply, Reply, NextStateName, NextStateData} | -%% {reply, Reply, NextStateName, NextStateData, Timeout} | -%% {stop, Reason, NewStateData} | -%% {stop, Reason, Reply, NewStateData} -%%---------------------------------------------------------------------- -handle_sync_event({debug_level, N}, From, StateName, S) -> - {reply, ok, StateName, S#eldap{debug_level = N}}; - -handle_sync_event(Event, From, StateName, S) -> - {reply, {StateName, S}, StateName, S}; - -handle_sync_event(Event, From, StateName, S) -> - Reply = ok, - {reply, Reply, StateName, S}. - -%%---------------------------------------------------------------------- -%% Func: handle_info/3 -%% Returns: {next_state, NextStateName, NextStateData} | -%% {next_state, NextStateName, NextStateData, Timeout} | -%% {stop, Reason, NewStateData} -%%---------------------------------------------------------------------- - -%% -%% Packets arriving in various states -%% -handle_info({tcp, Socket, Data}, connecting, S) -> - log1("eldap. tcp packet received when disconnected!~n~p~n", [Data], S), - {next_state, connecting, S}; - -handle_info({tcp, Socket, Data}, wait_bind_response, S) -> - cancel_timer(S#eldap.bind_timer), - case catch recvd_wait_bind_response(Data, S) of - bound -> {next_state, active, S}; - {fail_bind, Reason} -> close_and_retry(S), - {next_state, connecting, S#eldap{fd = null}}; - {'EXIT', Reason} -> close_and_retry(S), - {next_state, connecting, S#eldap{fd = null}}; - {error, Reason} -> close_and_retry(S), - {next_state, connecting, S#eldap{fd = null}} - end; - -handle_info({tcp, Socket, Data}, active, S) -> - case catch recvd_packet(Data, S) of - {reply, Reply, To, NewS} -> gen_fsm:reply(To, Reply), - {next_state, active, NewS}; - {ok, NewS} -> {next_state, active, NewS}; - {'EXIT', Reason} -> {next_state, active, S}; - {error, Reason} -> {next_state, active, S} - end; - -handle_info({tcp_closed, Socket}, All_fsm_states, S) -> - F = fun(Id, [{Timer, From, Name}|Res]) -> - gen_fsm:reply(From, {error, tcp_closed}), - cancel_timer(Timer) - end, - dict:map(F, S#eldap.dict), - retry_connect(), - {next_state, connecting, S#eldap{fd = null, - dict = dict:new()}}; - -handle_info({tcp_error, Socket, Reason}, Fsm_state, S) -> - log1("eldap received tcp_error: ~p~nIn State: ~p~n", [Reason, Fsm_state], S), - {next_state, Fsm_state, S}; -%% -%% Timers -%% -handle_info({timeout, Timer, {cmd_timeout, Id}}, active, S) -> - case cmd_timeout(Timer, Id, S) of - {reply, To, Reason, NewS} -> gen_fsm:reply(To, Reason), - {next_state, active, NewS}; - {error, Reason} -> {next_state, active, S} - end; - -handle_info({timeout, retry_connect}, connecting, S) -> - {ok, NextState, NewS} = connect_bind(S), - {next_state, NextState, NewS}; - -handle_info({timeout, Timer, bind_timeout}, wait_bind_response, S) -> - close_and_retry(S), - {next_state, connecting, S#eldap{fd = null}}; - -%% -%% Make sure we don't fill the message queue with rubbish -%% -handle_info(Info, StateName, S) -> - log1("eldap. Unexpected Info: ~p~nIn state: ~p~n when StateData is: ~p~n", - [Info, StateName, S], S), - {next_state, StateName, S}. - -%%---------------------------------------------------------------------- -%% Func: terminate/3 -%% Purpose: Shutdown the fsm -%% Returns: any -%%---------------------------------------------------------------------- -terminate(Reason, StateName, StatData) -> - ok. - -%%---------------------------------------------------------------------- -%% Func: code_change/4 -%% Purpose: Convert process state when code is changed -%% Returns: {ok, NewState, NewStateData} -%%---------------------------------------------------------------------- -code_change(OldVsn, StateName, S, Extra) -> - {ok, StateName, S}. - -%%%---------------------------------------------------------------------- -%%% Internal functions -%%%---------------------------------------------------------------------- -send_command(Command, From, S) -> - Id = bump_id(S), - {Name, Request} = gen_req(Command), - Message = #'LDAPMessage'{messageID = Id, - protocolOp = {Name, Request}}, - log2("~p~n",[{Name, Request}], S), - {ok, Bytes} = asn1rt:encode('ELDAPv3', 'LDAPMessage', Message), - ok = gen_tcp:send(S#eldap.fd, Bytes), - Timer = erlang:start_timer(?CMD_TIMEOUT, self(), {cmd_timeout, Id}), - New_dict = dict:store(Id, [{Timer, From, Name}], S#eldap.dict), - {ok, S#eldap{id = Id, - dict = New_dict}}. - -gen_req({search, A}) -> - {searchRequest, - #'SearchRequest'{baseObject = A#eldap_search.base, - scope = v_scope(A#eldap_search.scope), - derefAliases = neverDerefAliases, - sizeLimit = 0, % no size limit - timeLimit = v_timeout(A#eldap_search.timeout), - typesOnly = v_bool(A#eldap_search.types_only), - filter = v_filter(A#eldap_search.filter), - attributes = v_attributes(A#eldap_search.attributes) - }}; -gen_req({add, Entry, Attrs}) -> - {addRequest, - #'AddRequest'{entry = Entry, - attributes = Attrs}}; -gen_req({delete, Entry}) -> - {delRequest, Entry}; -gen_req({modify, Obj, Mod}) -> - v_modifications(Mod), - {modifyRequest, - #'ModifyRequest'{object = Obj, - modification = Mod}}; -gen_req({modify_dn, Entry, NewRDN, DelOldRDN, NewSup}) -> - {modDNRequest, - #'ModifyDNRequest'{entry = Entry, - newrdn = NewRDN, - deleteoldrdn = DelOldRDN, - newSuperior = NewSup}}. - -%%----------------------------------------------------------------------- -%% recvd_packet -%% Deals with incoming packets in the active state -%% Will return one of: -%% {ok, NewS} - Don't reply to client yet as this is part of a search -%% result and we haven't got all the answers yet. -%% {reply, Result, From, NewS} - Reply with result to client From -%% {error, Reason} -%% {'EXIT', Reason} - Broke -%%----------------------------------------------------------------------- -recvd_packet(Pkt, S) -> - check_tag(Pkt), - case asn1rt:decode('ELDAPv3', 'LDAPMessage', Pkt) of - {ok,Msg} -> - Op = Msg#'LDAPMessage'.protocolOp, - log2("~p~n",[Op], S), - Dict = S#eldap.dict, - Id = Msg#'LDAPMessage'.messageID, - {Timer, From, Name, Result_so_far} = get_op_rec(Id, Dict), - case {Name, Op} of - {searchRequest, {searchResEntry, R}} when - record(R,'SearchResultEntry') -> - New_dict = dict:append(Id, R, Dict), - {ok, S#eldap{dict = New_dict}}; - {searchRequest, {searchResDone, Result}} -> - case Result#'LDAPResult'.resultCode of - success -> - {Res, Ref} = polish(Result_so_far), - New_dict = dict:erase(Id, Dict), - cancel_timer(Timer), - {reply, #eldap_search_result{entries = Res, - referrals = Ref}, From, - S#eldap{dict = New_dict}}; - Reason -> - New_dict = dict:erase(Id, Dict), - cancel_timer(Timer), - {reply, {error, Reason}, From, S#eldap{dict = New_dict}} - end; - {searchRequest, {searchResRef, R}} -> - New_dict = dict:append(Id, R, Dict), - {ok, S#eldap{dict = New_dict}}; - {addRequest, {addResponse, Result}} -> - New_dict = dict:erase(Id, Dict), - cancel_timer(Timer), - Reply = check_reply(Result, From), - {reply, Reply, From, S#eldap{dict = New_dict}}; - {delRequest, {delResponse, Result}} -> - New_dict = dict:erase(Id, Dict), - cancel_timer(Timer), - Reply = check_reply(Result, From), - {reply, Reply, From, S#eldap{dict = New_dict}}; - {modifyRequest, {modifyResponse, Result}} -> - New_dict = dict:erase(Id, Dict), - cancel_timer(Timer), - Reply = check_reply(Result, From), - {reply, Reply, From, S#eldap{dict = New_dict}}; - {modDNRequest, {modDNResponse, Result}} -> - New_dict = dict:erase(Id, Dict), - cancel_timer(Timer), - Reply = check_reply(Result, From), - {reply, Reply, From, S#eldap{dict = New_dict}}; - {OtherName, OtherResult} -> - New_dict = dict:erase(Id, Dict), - cancel_timer(Timer), - {reply, {error, {invalid_result, OtherName, OtherResult}}, - From, S#eldap{dict = New_dict}} - end; - Error -> Error - end. - -check_reply(#'LDAPResult'{resultCode = success}, From) -> - ok; -check_reply(#'LDAPResult'{resultCode = Reason}, From) -> - {error, Reason}; -check_reply(Other, From) -> - {error, Other}. - -get_op_rec(Id, Dict) -> - case dict:find(Id, Dict) of - {ok, [{Timer, From, Name}|Res]} -> - {Timer, From, Name, Res}; - error -> - throw({error, unkown_id}) - end. - -%%----------------------------------------------------------------------- -%% recvd_wait_bind_response packet -%% Deals with incoming packets in the wait_bind_response state -%% Will return one of: -%% bound - Success - move to active state -%% {fail_bind, Reason} - Failed -%% {error, Reason} -%% {'EXIT', Reason} - Broken packet -%%----------------------------------------------------------------------- -recvd_wait_bind_response(Pkt, S) -> - check_tag(Pkt), - case asn1rt:decode('ELDAPv3', 'LDAPMessage', Pkt) of - {ok,Msg} -> - log2("~p", [Msg], S), - check_id(S#eldap.id, Msg#'LDAPMessage'.messageID), - case Msg#'LDAPMessage'.protocolOp of - {bindResponse, Result} -> - case Result#'LDAPResult'.resultCode of - success -> bound; - Error -> {fail_bind, Error} - end - end; - Else -> - {fail_bind, Else} - end. - -check_id(Id, Id) -> ok; -check_id(_, _) -> throw({error, wrong_bind_id}). - -%%----------------------------------------------------------------------- -%% General Helpers -%%----------------------------------------------------------------------- - -cancel_timer(Timer) -> - erlang:cancel_timer(Timer), - receive - {timeout, Timer, _} -> - ok - after 0 -> - ok - end. - - -%%% Sanity check of received packet -check_tag(Data) -> - case asn1rt_ber:decode_tag(Data) of - {Tag, Data1, Rb} -> - case asn1rt_ber:decode_length(Data1) of - {{Len,Data2}, Rb2} -> ok; - _ -> throw({error,decoded_tag_length}) - end; - _ -> throw({error,decoded_tag}) - end. - -close_and_retry(S) -> - gen_tcp:close(S#eldap.fd), - retry_connect(). - -retry_connect() -> - erlang:send_after(?RETRY_TIMEOUT, self(), - {timeout, retry_connect}). - - -%%----------------------------------------------------------------------- -%% Sort out timed out commands -%%----------------------------------------------------------------------- -cmd_timeout(Timer, Id, S) -> - Dict = S#eldap.dict, - case dict:find(Id, Dict) of - {ok, [{Id, Timer, From, Name}|Res]} -> - case Name of - searchRequest -> - {Res1, Ref1} = polish(Res), - New_dict = dict:erase(Id, Dict), - {reply, From, {timeout, - #eldap_search_result{entries = Res1, - referrals = Ref1}}, - S#eldap{dict = New_dict}}; - Others -> - New_dict = dict:erase(Id, Dict), - {reply, From, {error, timeout}, S#eldap{dict = New_dict}} - end; - error -> - {error, timed_out_cmd_not_in_dict} - end. - -%%----------------------------------------------------------------------- -%% Common stuff for results -%%----------------------------------------------------------------------- -%%% -%%% Polish the returned search result -%%% - -polish(Entries) -> - polish(Entries, [], []). - -polish([H|T], Res, Ref) when record(H, 'SearchResultEntry') -> - ObjectName = H#'SearchResultEntry'.objectName, - F = fun({_,A,V}) -> {A,V} end, - Attrs = lists:map(F, H#'SearchResultEntry'.attributes), - polish(T, [#eldap_entry{object_name = ObjectName, - attributes = Attrs}|Res], Ref); -polish([H|T], Res, Ref) -> % No special treatment of referrals at the moment. - polish(T, Res, [H|Ref]); -polish([], Res, Ref) -> - {Res, Ref}. - -%%----------------------------------------------------------------------- -%% Connect to next server in list and attempt to bind to it. -%%----------------------------------------------------------------------- -connect_bind(S) -> - Host = next_host(S#eldap.host, S#eldap.hosts), - TcpOpts = [{packet, asn1}, {active, true}], - case gen_tcp:connect(Host, S#eldap.port, TcpOpts) of - {ok, Socket} -> - case bind_request(Socket, S) of - {ok, NewS} -> - Timer = erlang:start_timer(?BIND_TIMEOUT, self(), - {timeout, bind_timeout}), - {ok, wait_bind_response, NewS#eldap{fd = Socket, - host = Host, - bind_timer = Timer}}; - {error, Reason} -> - gen_tcp:close(Socket), - erlang:send_after(?RETRY_TIMEOUT, self(), - {timeout, retry_connect}), - {ok, connecting, S#eldap{host = Host}} - end; - {error, Reason} -> - erlang:send_after(?RETRY_TIMEOUT, self(), - {timeout, retry_connect}), - {ok, connecting, S#eldap{host = Host}} - end. - -bind_request(Socket, S) -> - Id = bump_id(S), - Req = #'BindRequest'{version = S#eldap.version, - name = S#eldap.rootdn, - authentication = {simple, S#eldap.passwd}}, - Message = #'LDAPMessage'{messageID = Id, - protocolOp = {bindRequest, Req}}, - log2("Message:~p~n",[Message], S), - {ok, Bytes} = asn1rt:encode('ELDAPv3', 'LDAPMessage', Message), - ok = gen_tcp:send(Socket, Bytes), - {ok, S#eldap{id = Id}}. - -%% Given last tried Server, find next one to try -next_host(null, [H|_]) -> H; % First time, take first -next_host(Host, Hosts) -> % Find next in turn - next_host(Host, Hosts, Hosts). - -next_host(Host, [Host], Hosts) -> hd(Hosts); % Wrap back to first -next_host(Host, [Host|Tail], Hosts) -> hd(Tail); % Take next -next_host(Host, [], Hosts) -> hd(Hosts); % Never connected before? (shouldn't happen) -next_host(Host, [H|T], Hosts) -> next_host(Host, T, Hosts). - - -%%% -------------------------------------------------------------------- -%%% Verify the input data -%%% -------------------------------------------------------------------- - -v_filter({'and',L}) -> {'and',L}; -v_filter({'or', L}) -> {'or',L}; -v_filter({'not',L}) -> {'not',L}; -v_filter({equalityMatch,AV}) -> {equalityMatch,AV}; -v_filter({greaterOrEqual,AV}) -> {greaterOrEqual,AV}; -v_filter({lessOrEqual,AV}) -> {lessOrEqual,AV}; -v_filter({approxMatch,AV}) -> {approxMatch,AV}; -v_filter({present,A}) -> {present,A}; -v_filter({substrings,S}) when record(S,'SubstringFilter') -> {substrings,S}; -v_filter(_Filter) -> throw({error,concat(["unknown filter: ",_Filter])}). - -v_modifications(Mods) -> - F = fun({_,Op,_}) -> - case lists:member(Op,[add,delete,replace]) of - true -> true; - _ -> throw({error,{mod_operation,Op}}) - end - end, - lists:foreach(F, Mods). - -v_substr([{Key,Str}|T]) when list(Str),Key==initial;Key==any;Key==final -> - [{Key,Str}|v_substr(T)]; -v_substr([H|T]) -> - throw({error,{substring_arg,H}}); -v_substr([]) -> - []. -v_scope(baseObject) -> baseObject; -v_scope(singleLevel) -> singleLevel; -v_scope(wholeSubtree) -> wholeSubtree; -v_scope(_Scope) -> throw({error,concat(["unknown scope: ",_Scope])}). - -v_bool(true) -> true; -v_bool(false) -> false; -v_bool(_Bool) -> throw({error,concat(["not Boolean: ",_Bool])}). - -v_timeout(I) when integer(I), I>=0 -> I; -v_timeout(_I) -> throw({error,concat(["timeout not positive integer: ",_I])}). - -v_attributes(Attrs) -> - F = fun(A) when list(A) -> A; - (A) -> throw({error,concat(["attribute not String: ",A])}) - end, - lists:map(F,Attrs). - - -%%% -------------------------------------------------------------------- -%%% Get and Validate the initial configuration -%%% -------------------------------------------------------------------- -get_config() -> - Priv_dir = code:priv_dir(eldap), - File = filename:join(Priv_dir, "eldap.conf"), - case file:consult(File) of - {ok, Entries} -> - case catch parse(Entries) of - {ok, Hosts, Port, Rootdn, Passwd, Log} -> - {ok, Hosts, Port, Rootdn, Passwd, Log}; - {error, Reason} -> - {error, Reason}; - {'EXIT', Reason} -> - {error, Reason} - end; - {error, Reason} -> - {error, Reason} - end. - -parse(Entries) -> - {ok, - get_hosts(host, Entries), - get_integer(port, Entries), - get_list(rootdn, Entries), - get_list(passwd, Entries), - get_log(log, Entries)}. - -get_integer(Key, List) -> - case lists:keysearch(Key, 1, List) of - {value, {Key, Value}} when integer(Value) -> - Value; - {value, {Key, Value}} -> - throw({error, "Bad Value in Config for " ++ atom_to_list(Key)}); - false -> - throw({error, "No Entry in Config for " ++ atom_to_list(Key)}) - end. - -get_list(Key, List) -> - case lists:keysearch(Key, 1, List) of - {value, {Key, Value}} when list(Value) -> - Value; - {value, {Key, Value}} -> - throw({error, "Bad Value in Config for " ++ atom_to_list(Key)}); - false -> - throw({error, "No Entry in Config for " ++ atom_to_list(Key)}) - end. - -get_log(Key, List) -> - case lists:keysearch(Key, 1, List) of - {value, {Key, Value}} when function(Value) -> - Value; - {value, {Key, Else}} -> - false; - false -> - fun(Level, Format, Args) -> io:format("--- " ++ Format, Args) end - end. - -get_hosts(Key, List) -> - lists:map(fun({Key1, {A,B,C,D}}) when integer(A), - integer(B), - integer(C), - integer(D), - Key == Key1-> - {A,B,C,D}; - ({Key1, Value}) when list(Value), - Key == Key1-> - Value; - ({Else, Value}) -> - throw({error, "Bad Hostname in config"}) - end, List). - -%%% -------------------------------------------------------------------- -%%% Other Stuff -%%% -------------------------------------------------------------------- -bump_id(#eldap{id = Id}) when Id > ?MAX_TRANSACTION_ID -> - ?MIN_TRANSACTION_ID; -bump_id(#eldap{id = Id}) -> - Id + 1. - -%%% -------------------------------------------------------------------- -%%% Log routines. Call a user provided log routine Fun. -%%% -------------------------------------------------------------------- - -log1(Str, Args, #eldap{log = Fun, debug_level = N}) -> log(Fun, Str, Args, 1, N). -log2(Str, Args, #eldap{log = Fun, debug_level = N}) -> log(Fun, Str, Args, 2, N). - -log(Fun, Str, Args, This_level, Status) when function(Fun), This_level =< Status -> - catch Fun(This_level, Str, Args); -log(_, _, _, _, _) -> - ok. rabbitmq-server-3.2.4/plugins-src/eldap-wrapper/remove-ietf-doc.patch0000644000000000000000000034266212305126066024360 0ustar rootrootdiff --git a/doc/draft-ietf-asid-ldap-c-api-00.txt b/doc/draft-ietf-asid-ldap-c-api-00.txt deleted file mode 100755 index 5f2e856..0000000 --- a/doc/draft-ietf-asid-ldap-c-api-00.txt +++ /dev/null @@ -1,3030 +0,0 @@ - - - - - - -Network Working Group T. Howes -INTERNET-DRAFT Netscape Communications Corp. -Intended Category: Standards Track M. Smith -Obsoletes: RFC 1823 Netscape Communications Corp. -Expires: January 1998 A. Herron - Microsoft Corp. - C. Weider - Microsoft Corp. - M. Wahl - Critical Angle, Inc. - - 29 July 1997 - - - The C LDAP Application Program Interface - - - - -1. Status of this Memo - -This draft document will be submitted to the RFC Editor as a Standards -Track document. Distribution of this memo is unlimited. Please send com- -ments to the authors. - -This document is an Internet-Draft. Internet-Drafts are working docu- -ments of the Internet Engineering Task Force (IETF), its areas, and its -working groups. Note that other groups may also distribute working -documents as Internet-Drafts. - -Internet-Drafts are draft documents valid for a maximum of six months -and may be updated, replaced, or obsoleted by other documents at any -time. It is inappropriate to use Internet-Drafts as reference material -or to cite them other than as ``work in progress.'' - -To learn the current status of any Internet-Draft, please check the -``1id-abstracts.txt'' listing contained in the Internet-Drafts Shadow -Directories on ds.internic.net (US East Coast), nic.nordu.net (Europe), -ftp.isi.edu (US West Coast), or munnari.oz.au (Pacific Rim). - -2. Introduction - -This document defines a C language application program interface to the -lightweight directory access protocol (LDAP). This document replaces the -previous definition of this API, defined in RFC 1823, updating it to -include support for features found in version 3 of the LDAP protocol. -New extended operation functions were added to support LDAPv3 features -such as controls. In addition, other LDAP API changes were made to - - - -Expires: January 1998 [Page 1] - -C LDAP API The C LDAP Application Program Interface 29 July 1997 - - -support information hiding and thread safety. - -The C LDAP API is designed to be powerful, yet simple to use. It defines -compatible synchronous and asynchronous interfaces to LDAP to suit a -wide variety of applications. This document gives a brief overview of -the LDAP model, then an overview of how the API is used by an applica- -tion program to obtain LDAP information. The API calls are described in -detail, followed by an appendix that provides some example code demon- -strating the use of the API. This document provides information to the -Internet community. It does not specify any standard. - -3. Overview of the LDAP Model - -LDAP is the lightweight directory access protocol, described in [2] and -[6]. It can provide a lightweight frontend to the X.500 directory [1], -or a stand-alone service. In either mode, LDAP is based on a client- -server model in which a client makes a TCP connection to an LDAP server, -over which it sends requests and receives responses. - -The LDAP information model is based on the entry, which contains infor- -mation about some object (e.g., a person). Entries are composed of -attributes, which have a type and one or more values. Each attribute has -a syntax that determines what kinds of values are allowed in the attri- -bute (e.g., ASCII characters, a jpeg photograph, etc.) and how those -values behave during directory operations (e.g., is case significant -during comparisons). - -Entries may be organized in a tree structure, usually based on politi- -cal, geographical, and organizational boundaries. Each entry is uniquely -named relative to its sibling entries by its relative distinguished name -(RDN) consisting of one or more distinguished attribute values from the -entry. At most one value from each attribute may be used in the RDN. -For example, the entry for the person Babs Jensen might be named with -the "Barbara Jensen" value from the commonName attribute. - -A globally unique name for an entry, called a distinguished name or DN, -is constructed by concatenating the sequence of RDNs from the entry up -to the root of the tree. For example, if Babs worked for the University -of Michigan, the DN of her U-M entry might be "cn=Barbara Jensen, -o=University of Michigan, c=US". The DN format used by LDAP is defined -in [4]. - -Operations are provided to authenticate, search for and retrieve infor- -mation, modify information, and add and delete entries from the tree. -The next sections give an overview of how the API is used and detailed -descriptions of the LDAP API calls that implement all of these func- -tions. - - - - -Expires: January 1998 [Page 2] - -C LDAP API The C LDAP Application Program Interface 29 July 1997 - - -4. Overview of LDAP API Use - -An application generally uses the C LDAP API in four simple steps. - -- Initialize an LDAP session with a default LDAP server. The - ldap_init() function returns a handle to the session, allowing mul- - tiple connections to be open at once. - -- Authenticate to the LDAP server. The ldap_bind() function and - friends support a variety of authentication methods. - -- Perform some LDAP operations and obtain some results. ldap_search() - and friends return results which can be parsed by - ldap_result2error(), ldap_first_entry(), ldap_next_entry(), etc. - -- Close the session. The ldap_unbind() function closes the connec- - tion. - -Operations can be performed either synchronously or asynchronously. The -names of the synchronous functions end in _s. For example, a synchronous -search can be completed by calling ldap_search_s(). An asynchronous -search can be initiated by calling ldap_search(). All synchronous rou- -tines return an indication of the outcome of the operation (e.g, the -constant LDAP_SUCCESS or some other error code). The asynchronous rou- -tines return the message id of the operation initiated. This id can be -used in subsequent calls to ldap_result() to obtain the result(s) of the -operation. An asynchronous operation can be abandoned by calling -ldap_abandon(). - -Results and errors are returned in an opaque structure called LDAPMes- -sage. Routines are provided to parse this structure, step through -entries and attributes returned, etc. Routines are also provided to -interpret errors. Later sections of this document describe these rou- -tines in more detail. - -LDAP version 3 servers may return referrals to other servers. By -default, implementations of this API will attempt to follow referrals -automatically for the application. This behavior can be disabled glo- -bally (using the ldap_set_option() call) or on a per-request basis -through the use of a client control. - -As in the LDAPv3 protocol itself, all DNs and string values that are -passed into or produced by the C LDAP API are represented as UTF-8[10] -characters. - -For compatibility with existing applications, implementations of this -API will by default use version 2 of the LDAP protocol. Applications -that intend to take advantage of LDAP version 3 features will need to - - - -Expires: January 1998 [Page 3] - -C LDAP API The C LDAP Application Program Interface 29 July 1997 - - -use the ldap_set_option() call with a LDAP_OPT_PROTOCOL_VERSION to -switch to version 3. - - -5. Common Data Structures - -Some data structures that are common to several LDAP API functions are -defined here: - - typedef struct ldap LDAP; - - typedef struct ldapmsg LDAPMessage; - - struct berval { - unsigned long bv_len; - char *bv_val; - }; - - struct timeval { - long tv_sec; - long tv_usec; - }; - -The LDAP structure is an opaque data type that represents an LDAP ses- -sion Typically this corresponds to a connection to a single server, but -it may encompass several server connections in the face of LDAPv3 refer- -rals. - -The LDAPMessage structure is an opaque data type that is used to return -results and error information. - -The berval structure is used to represent arbitrary binary data and its -fields have the following meanings: - -bv_len Length of data in bytes. - -bv_val A pointer to the data itself. - - -The timeval structure is used to represent an interval of time and its -fields have the following meanings: - -tv_sec Seconds component of time interval. - -tv_usec Microseconds component of time interval. - - - - - - -Expires: January 1998 [Page 4] - -C LDAP API The C LDAP Application Program Interface 29 July 1997 - - -6. LDAP Error Codes - -Many of the LDAP API routines return LDAP error codes, some of which -indicate local errors and some of which may be returned by servers. -Supported error codes are (hexadecimal values are given in parentheses -after the constant): - - LDAP_SUCCESS (0x00) - LDAP_OPERATIONS_ERROR( 0x01) - LDAP_PROTOCOL_ERROR (0x02) - LDAP_TIMELIMIT_EXCEEDED (0x03) - LDAP_SIZELIMIT_EXCEEDED (0x04) - LDAP_COMPARE_FALSE (0x05) - LDAP_COMPARE_TRUE (0x06) - LDAP_STRONG_AUTH_NOT_SUPPORTED (0x07) - LDAP_STRONG_AUTH_REQUIRED (0x08) - LDAP_REFERRAL (0x0a) -- new in LDAPv3 - LDAP_ADMINLIMIT_EXCEEDED (0x0b) -- new in LDAPv3 - LDAP_UNAVAILABLE_CRITICAL_EXTENSION (0x0c) -- new in LDAPv3 - LDAP_CONFIDENTIALITY_REQUIRED (0x0d) -- new in LDAPv3 - LDAP_NO_SUCH_ATTRIBUTE (0x10) - LDAP_UNDEFINED_TYPE (0x11) - LDAP_INAPPROPRIATE_MATCHING (0x12) - LDAP_CONSTRAINT_VIOLATION (0x13) - LDAP_TYPE_OR_VALUE_EXISTS (0x14) - LDAP_INVALID_SYNTAX (0x15) - LDAP_NO_SUCH_OBJECT (0x20) - LDAP_ALIAS_PROBLEM (0x21) - LDAP_INVALID_DN_SYNTAX (0x22) - LDAP_IS_LEAF (0x23) -- not used in LDAPv3 - LDAP_ALIAS_DEREF_PROBLEM (0x24) - LDAP_INAPPROPRIATE_AUTH (0x30) - LDAP_INVALID_CREDENTIALS (0x31) - LDAP_INSUFFICIENT_ACCESS (0x32) - LDAP_BUSY (0x33) - LDAP_UNAVAILABLE (0x34) - LDAP_UNWILLING_TO_PERFORM (0x35) - LDAP_LOOP_DETECT (0x36) - LDAP_NAMING_VIOLATION (0x40) - LDAP_OBJECT_CLASS_VIOLATION (0x41) - LDAP_NOT_ALLOWED_ON_NONLEAF (0x42) - LDAP_NOT_ALLOWED_ON_RDN (0x43) - LDAP_ALREADY_EXISTS (0x44) - LDAP_NO_OBJECT_CLASS_MODS (0x45) - LDAP_RESULTS_TOO_LARGE (0x46) - LDAP_AFFECTS_MULTIPLE_DSAS (0x47) -- new in LDAPv3 - LDAP_OTHER (0x50) - LDAP_SERVER_DOWN (0x51) - - - -Expires: January 1998 [Page 5] - -C LDAP API The C LDAP Application Program Interface 29 July 1997 - - - LDAP_LOCAL_ERROR (0x52) - LDAP_ENCODING_ERROR (0x53) - LDAP_DECODING_ERROR (0x54) - LDAP_TIMEOUT (0x55) - LDAP_AUTH_UNKNOWN (0x56) - LDAP_FILTER_ERROR (0x57) - LDAP_USER_CANCELLED (0x58) - LDAP_PARAM_ERROR (0x59) - LDAP_NO_MEMORY (0x5a) - LDAP_CONNECT_ERROR (0x5b) - LDAP_NOT_SUPPORTED (0x5c) - LDAP_CONTROL_NOT_FOUND (0x5d) - LDAP_NO_RESULTS_RETURNED (0x5e) - LDAP_MORE_RESULTS_TO_RETURN (0x5f) - LDAP_CLIENT_LOOP (0x60) - LDAP_REFERRAL_LIMIT_EXCEEDED (0x61) - - -7. Performing LDAP Operations - -This section describes each LDAP operation API call in detail. All func- -tions take a "session handle," a pointer to an LDAP structure containing -per-connection information. Many routines return results in an LDAPMes- -sage structure. These structures and others are described as needed -below. - - -7.1. Initializing an LDAP Session - -ldap_init() initializes a session with an LDAP server. The server is not -actually contacted until an operation is performed that requires it, -allowing various options to be set after initialization. - - LDAP *ldap_init( - char *hostname, - int portno - ); - -Use of the following routine is deprecated. - - LDAP *ldap_open( - char *hostname, - int portno - ); - -Parameters are: - -hostname Contains a space-separated list of hostnames or dotted strings - - - -Expires: January 1998 [Page 6] - -C LDAP API The C LDAP Application Program Interface 29 July 1997 - - - representing the IP address of hosts running an LDAP server to - connect to. Each hostname in the list can include an optional - port number which is separated from the host itself with a - colon (:) character. The hosts are tried in the order listed, - stopping with the first one to which a successful connection is - made. Note that only ldap_open() attempts to make the connec- - tion before returning to the caller. ldap_init() does not con- - nect to the LDAP server. - -portno Contains the TCP port number to connect to. The default LDAP - port of 389 can be obtained by supplying the constant - LDAP_PORT. If a host includes a port number then this parame- - ter is ignored. - -ldap_init() and ldap_open() both return a "session handle," a pointer to -an opaque structure that should be passed to subsequent calls pertaining -to the session. These routines return NULL if the session cannot be ini- -tialized in which case the operating system error reporting mechanism -can be checked to see why the call failed. - -Note that if you connect to an LDAPv2 server, one of the ldap_bind() -calls described below must be completed before other operations can be -performed on the session. LDAPv3 does not require that a bind operation -be completed before other operations can be performed. - -The calling program can set various attributes of the session by calling -the routines described in the next section. - - -7.2. LDAP Session Handle Options - -The LDAP session handle returned by ldap_init() is a pointer to an -opaque data type representing an LDAP session. Formerly, this data type -was a structure exposed to the caller, and various fields in the struc- -ture could be set to control aspects of the session, such as size and -time limits on searches. - -In the interest of insulating callers from inevitable changes to this -structure, these aspects of the session are now accessed through a pair -of accessor functions, described below. - -ldap_get_option() is used to access the current value of various -session-wide parameters. ldap_set_option() is used to set the value of -these parameters. - - int ldap_get_option( - LDAP *ld, - int option, - - - -Expires: January 1998 [Page 7] - -C LDAP API The C LDAP Application Program Interface 29 July 1997 - - - void *outvalue - ); - - int ldap_set_option( - LDAP *ld, - int option, - void *invalue - ); - -Parameters are: - -ld The session handle. - -option The name of the option being accessed or set. This parameter - should be one of the following constants, which have the indi- - cated meanings. After the constant the actual value of the con- - stant is listed in hexadecimal in parentheses followed by the - type of the corresponding outvalue or invalue parameter. - - LDAP_OPT_DESC (0x01) int * - The underlying socket descriptor corresponding to the default - LDAP connection. - - LDAP_OPT_DEREF (0x02) int * - Controls how aliases are handled during search. It can have - one of the following values: LDAP_DEREF_NEVER (0x00), - LDAP_DEREF_SEARCHING (0x01), LDAP_DEREF_FINDING (0x02), or - LDAP_DEREF_ALWAYS (0x03). The LDAP_DEREF_SEARCHING value - means aliases should be dereferenced during the search but not - when locating the base object of the search. The - LDAP_DEREF_FINDING value means aliases should be dereferenced - when locating the base object but not during the search. - - LDAP_OPT_SIZELIMIT (0x03) int * - A limit on the number of entries to return from a search. A - value of zero means no limit. - - LDAP_OPT_TIMELIMIT (0x04) int * - A limit on the number of seconds to spend on a search. A value - of zero means no limit - - LDAP_OPT_REBIND_FN (0x06) function pointer - See the discussion of ldap_bind() and friends below. - - LDAP_OPT_REBIND_ARG (0x07) void * - See the discussion of ldap_bind() and friends below. - - LDAP_OPT_REFERRALS (0x08) void * - - - -Expires: January 1998 [Page 8] - -C LDAP API The C LDAP Application Program Interface 29 July 1997 - - - This option controls whether the LDAP library automatically - follows referrals returned by LDAP servers or not. It can be - set to one of the constants LDAP_OPT_ON or LDAP_OPT_OFF. - - LDAP_OPT_RESTART (0x09) void * - This option controls whether LDAP I/O operations should - automatically be restarted if they abort prematurely. It - should be set to one of the constants LDAP_OPT_ON or - LDAP_OPT_OFF. This option is useful if an LDAP I/O operation - may be interrupted prematurely, for example by a timer going - off, or other interrrupt. - - LDAP_OPT_PROTOCOL_VERSION (0x11) int * - This option indicates the version of the default LDAP server. - It can be one of the constants LDAP_VERSION2 or LDAP_VERSION3. - If no version is set the default is LDAP_VERSION2. - - LDAP_OPT_SERVER_CONTROLS (0x12) LDAPControl ** - A default list of LDAP server controls to be sent with each - request. See the Using Controls section below. - - LDAP_OPT_CLIENT_CONTROLS (0x13) LDAPControl ** - A default list of client controls that affect the LDAP ses- - sion. See the Using Controls section below. - - LDAP_OPT_HOST_NAME (0x30) char ** - The host name of the default LDAP server. - - LDAP_OPT_ERROR_NUMBER (0x31) int * - The code of the most recent LDAP error that occurred for this - session. - - LDAP_OPT_ERROR_STRING (0x32) char ** - The message returned with the most recent LDAP error that - occurred for this session. - - -outvalue The address of a place to put the value of the option. The - actual type of this parameter depends on the setting of the - option parameter. - -invalue A pointer to the value the option is to be given. The actual - type of this parameter depends on the setting of the option - parameter. The constants LDAP_OPT_ON and LDAP_OPT_OFF can be - given for options that have on or off settings. - - - - - - -Expires: January 1998 [Page 9] - -C LDAP API The C LDAP Application Program Interface 29 July 1997 - - -7.3. Working with controls - -LDAPv3 operations can be extended through the use of controls. Controls -may be sent to a server or returned to the client with any LDAP message. -These controls are referred to as server controls. - -The LDAP API also supports a client-side extension mechanism through the -use of client controls. These controls affect the behavior of the LDAP -API only and are never sent to a server. A common data structure is -used to represent both types of controls: - - typedef struct ldapcontrol { - char *ldctl_oid; - struct berval ldctl_value; - char ldctl_iscritical; - } LDAPControl, *PLDAPControl; - -The fields in the ldapcontrol structure have the following meanings: - -ldctl_oid The control type, represented as a string. - -ldctl_value The data associated with the control (if any). - -ldctl_iscritical Indicates whether the control is critical of not. If - this field is non-zero, the operation will only be car- - ried out if the control is recognized by the server - and/or client. - -Some LDAP API calls allocate an ldapcontrol structure or a NULL- -terminated array of ldapcontrol structures. The following routines can -be used to dispose of a single control or an array of controls: - - void ldap_control_free( LDAPControl *ctrl ); - void ldap_controls_free( LDAPControl **ctrls ); - -A set of controls that affect the entire session can be set using the -ldap_set_option() function (see above). A list of controls can also be -passed directly to some LDAP API calls such as ldap_search_ext(), in -which case any controls set for the session through the use of -ldap_set_option() are ignored. Control lists are represented as a NULL- -terminated array of pointers to ldapcontrol structures. - -Server controls are defined by LDAPv3 protocol extension documents; for -example, a control has been proposed to support server-side sorting of -search results [7]. - -No client controls are defined by this document but they may be defined -in future revisions or in any document that extends this API. - - - -Expires: January 1998 [Page 10] - -C LDAP API The C LDAP Application Program Interface 29 July 1997 - - -7.4. Authenticating to the directory - -The following functions are used to authenticate an LDAP client to an -LDAP directory server. - -The ldap_sasl_bind() and ldap_sasl_bind_s() functions can be used to do -general and extensible authentication over LDAP through the use of the -Simple Authentication Security Layer [8]. The routines both take the dn -to bind as, the method to use, as a dotted-string representation of an -OID identifying the method, and a struct berval holding the credentials. -The special constant value LDAP_SASL_SIMPLE ("") can be passed to -request simple authentication, or the simplified routines -ldap_simple_bind() or ldap_simple_bind_s() can be used. - - int ldap_sasl_bind( - LDAP *ld, - char *dn, - char *mechanism, - struct berval *cred, - LDAPControl **serverctrls, - LDAPControl **clientctrls, - int *msgidp - ); - - int ldap_sasl_bind_s( - LDAP *ld, - char *dn, - char *mechanism, - struct berval *cred, - LDAPControl **serverctrls, - LDAPControl **clientctrls, - struct berval **servercredp - ); - - int ldap_simple_bind( - LDAP *ld, - char *dn, - char *passwd - ); - - int ldap_simple_bind_s( - LDAP *ld, - char *dn, - char *passwd - ); - - The use of the following routines is deprecated: - - - - -Expires: January 1998 [Page 11] - -C LDAP API The C LDAP Application Program Interface 29 July 1997 - - - int ldap_bind( LDAP *ld, char *dn, char *cred, int method ); - - int ldap_bind_s( LDAP *ld, char *dn, char *cred, int method ); - - int ldap_kerberos_bind( LDAP *ld, char *dn ); - - int ldap_kerberos_bind_s( LDAP *ld, char *dn ); - -Parameters are: - -ld The session handle. - -dn The name of the entry to bind as. - -mechanism Either LDAP_AUTH_SIMPLE_OID to get simple authentication, - or a dotted text string representing an OID identifying the - SASL method. - -cred The credentials with which to authenticate. Arbitrary - credentials can be passed using this parameter. The format - and content of the credentials depends on the setting of - the mechanism parameter. - -passwd For ldap_simple_bind(), the password to compare to the - entry's userPassword attribute. - -serverctrls List of LDAP server controls. - -clientctrls List of client controls. - -msgidp This result parameter will be set to the message id of the - request if the ldap_sasl_bind() call succeeds. - -servercredp This result parameter will be set to the credentials - returned by the server. This should be freed by calling - ldap_If no credentials are returned it will be set to NULL. - -Additional parameters for the deprecated routines are not described. -Interested readers are referred to RFC 1823. - -The ldap_sasl_bind() function initiates an asynchronous bind operation -and returns the constant LDAP_SUCCESS if the request was successfully -sent, or another LDAP error code if not. See the section below on error -handling for more information about possible errors and how to interpret -them. If successful, ldap_sasl_bind() places the message id of the -request in *msgidp. A subsequent call to ldap_result(), described below, -can be used to obtain the result of the bind. - - - - -Expires: January 1998 [Page 12] - -C LDAP API The C LDAP Application Program Interface 29 July 1997 - - -The ldap_simple_bind() function initiates a simple asynchronous bind -operation and returns the message id of the operation initiated. A sub- -sequent call to ldap_result(), described below, can be used to obtain -the result of the bind. In case of error, ldap_simple_bind() will return --1, setting the session error parameters in the LDAP structure appropri- -ately. - -The synchronous ldap_sasl_bind_s() and ldap_simple_bind_s() functions -both return the result of the operation, either the constant -LDAP_SUCCESS if the operation was successful, or another LDAP error code -if it was not. See the section below on error handling for more informa- -tion about possible errors and how to interpret them. - -Note that if an LDAPv2 server is contacted, no other operations over the -connection should be attempted before a bind call has successfully com- -pleted. - -Subsequent bind calls can be used to re-authenticate over the same con- -nection, and multistep SASL sequences can be accomplished through a -sequence of calls to ldap_sasl_bind() or ldap_sasl_bind_s(). - - -7.5. Closing the session - -The following functions are used to unbind from the directory, close the -connection, and dispose of the session handle. - - int ldap_unbind( LDAP *ld ); - - int ldap_unbind_s( LDAP *ld ); - -Parameters are: - -ld The session handle. - -ldap_unbind() and ldap_unbind_s() both work synchronously, unbinding -from the directory, closing the connection, and freeing up the ld struc- -ture before returning. There is no server response to an unbind opera- -tion. ldap_unbind() returns LDAP_SUCCESS (or another LDAP error code if -the request cannot be sent to the LDAP server). After a call to -ldap_unbind() or ldap_unbind_s(), the session handle ld is invalid. - - -7.6. Searching - -The following functions are used to search the LDAP directory, returning -a requested set of attributes for each entry matched. There are five -variations. - - - -Expires: January 1998 [Page 13] - -C LDAP API The C LDAP Application Program Interface 29 July 1997 - - - int ldap_search_ext( - LDAP *ld, - char *base, - int scope, - char *filter, - char **attrs, - int attrsonly, - LDAPControl **serverctrls, - LDAPControl **clientctrls, - struct timeval *timeoutp, - int sizelimit, - int *msgidp - ); - - int ldap_search_ext_s( - LDAP *ld, - char *base, - int scope, - char *filter, - char **attrs, - int attrsonly, - LDAPControl **serverctrls, - LDAPControl **clientctrls, - struct timeval *timeoutp, - int sizelimit, - LDAPMessage **res - ); - - int ldap_search( - LDAP *ld, - char *base, - int scope, - char *filter, - char **attrs, - int attrsonly - ); - - int ldap_search_s( - LDAP *ld, - char *base, - int scope, - char *filter, - char **attrs, - int attrsonly, - LDAPMessage **res - ); - - int ldap_search_st( - - - -Expires: January 1998 [Page 14] - -C LDAP API The C LDAP Application Program Interface 29 July 1997 - - - LDAP *ld, - char *base, - int scope, - char *filter, - char **attrs, - int attrsonly, - struct timeval *timeout, - LDAPMessage **res - ); - -Parameters are: - -ld The session handle. - -base The dn of the entry at which to start the search. - -scope One of LDAP_SCOPE_BASE (0x00), LDAP_SCOPE_ONELEVEL (0x01), - or LDAP_SCOPE_SUBTREE (0x02), indicating the scope of the - search. - -filter A character string as described in [3], representing the - search filter. - -attrs A NULL-terminated array of strings indicating which attri- - butes to return for each matching entry. Passing NULL for - this parameter causes all available attributes to be - retrieved. - -attrsonly A boolean value that should be zero if both attribute types - and values are to be returned, non-zero if only types are - wanted. - -timeout For the ldap_search_st() function, this specifies the local - search timeout value. For the ldap_search_ext() and - ldap_search_ext_s() functions, this specifies both the - local search timeout value and the operation time limit - that is sent to the server within the search request. - -res For the synchronous calls, this is a result parameter which - will contain the results of the search upon completion of - the call. - -serverctrls List of LDAP server controls. - -clientctrls List of client controls. - -msgidp This result parameter will be set to the message id of the - request if the ldap_search_ext() call succeeds. - - - -Expires: January 1998 [Page 15] - -C LDAP API The C LDAP Application Program Interface 29 July 1997 - - -There are three options in the session handle ld which potentially -affect how the search is performed. They are: - -LDAP_OPT_SIZELIMIT - A limit on the number of entries to return from the search. - A value of zero means no limit. Note that the value from - the session handle is ignored when using the - ldap_search_ext() or ldap_search_ext_s() functions. - -LDAP_OPT_TIMELIMIT - A limit on the number of seconds to spend on the search. A - value of zero means no limit. Note that the value from the - session handle is ignored when using the ldap_search_ext() - or ldap_search_ext_s() functions. - -LDAP_OPT_DEREF - One of LDAP_DEREF_NEVER (0x00), LDAP_DEREF_SEARCHING - (0x01), LDAP_DEREF_FINDING (0x02), or LDAP_DEREF_ALWAYS - (0x03), specifying how aliases should be handled during the - search. The LDAP_DEREF_SEARCHING value means aliases should - be dereferenced during the search but not when locating the - base object of the search. The LDAP_DEREF_FINDING value - means aliases should be dereferenced when locating the base - object but not during the search. - -The ldap_search_ext() function initiates an asynchronous search opera- -tion and returns the constant LDAP_SUCCESS if the request was success- -fully sent, or another LDAP error code if not. See the section below on -error handling for more information about possible errors and how to -interpret them. If successful, ldap_search_ext() places the message id -of the request in *msgidp. A subsequent call to ldap_result(), described -below, can be used to obtain the results from the search. These results -can be parsed using the result parsing routines described in detail -later. - -Similar to ldap_search_ext(), the ldap_search() function initiates an -asynchronous search operation and returns the message id of the opera- -tion initiated. As for ldap_search_ext(), a subsequent call to -ldap_result(), described below, can be used to obtain the result of the -bind. In case of error, ldap_search() will return -1, setting the ses- -sion error parameters in the LDAP structure appropriately. - -The synchronous ldap_search_ext_s(), ldap_search_s(), and -ldap_search_st() functions all return the result of the operation, -either the constant LDAP_SUCCESS if the operation was successful, or -another LDAP error code if it was not. See the section below on error -handling for more information about possible errors and how to interpret -them. Entries returned from the search (if any) are contained in the - - - -Expires: January 1998 [Page 16] - -C LDAP API The C LDAP Application Program Interface 29 July 1997 - - -res parameter. This parameter is opaque to the caller. Entries, attri- -butes, values, etc., should be extracted by calling the parsing routines -described below. The results contained in res should be freed when no -longer in use by calling ldap_msgfree(), described later. - -The ldap_search_ext() and ldap_search_ext_s() functions support LDAPv3 -server controls, client controls, and allow varying size and time limits -to be easily specified for each search operation. The ldap_search_st() -function is identical to ldap_search_s() except that it takes an addi- -tional parameter specifying a local timeout for the search. - -7.7. Reading an Entry - -LDAP does not support a read operation directly. Instead, this operation -is emulated by a search with base set to the DN of the entry to read, -scope set to LDAP_SCOPE_BASE, and filter set to "(objectclass=*)". attrs -contains the list of attributes to return. - - -7.8. Listing the Children of an Entry - -LDAP does not support a list operation directly. Instead, this operation -is emulated by a search with base set to the DN of the entry to list, -scope set to LDAP_SCOPE_ONELEVEL, and filter set to "(objectclass=*)". -attrs contains the list of attributes to return for each child entry. - -7.9. Comparing a Value Against an Entry - -The following routines are used to compare a given attribute value -assertion against an LDAP entry. There are four variations: - - int ldap_compare_ext( - LDAP *ld, - char *dn, - char *attr, - struct berval *bvalue - LDAPControl **serverctrls, - LDAPControl **clientctrls, - int *msgidp - ); - - int ldap_compare_ext_s( - LDAP *ld, - char *dn, - char *attr, - struct berval *bvalue, - LDAPControl **serverctrls, - LDAPControl **clientctrls - - - -Expires: January 1998 [Page 17] - -C LDAP API The C LDAP Application Program Interface 29 July 1997 - - - ); - - int ldap_compare( - LDAP *ld, - char *dn, - char *attr, - char *value - ); - - int ldap_compare_s( - LDAP *ld, - char *dn, - char *attr, - char *value - ); - -Parameters are: - -ld The session handle. - -dn The name of the entry to compare against. - -attr The attribute to compare against. - -bvalue The attribute value to compare against those found in the - given entry. This parameter is used in the extended rou- - tines and is a pointer to a struct berval so it is possible - to compare binary values. - -value A string attribute value to compare against, used by the - ldap_compare() and ldap_compare_s() functions. Use - ldap_compare_ext() or ldap_compare_ext_s() if you need to - compare binary values. - -serverctrls List of LDAP server controls. - -clientctrls List of client controls. - -msgidp This result parameter will be set to the message id of the - request if the ldap_compare_ext() call succeeds. - -The ldap_compare_ext() function initiates an asynchronous compare opera- -tion and returns the constant LDAP_SUCCESS if the request was success- -fully sent, or another LDAP error code if not. See the section below on -error handling for more information about possible errors and how to -interpret them. If successful, ldap_compare_ext() places the message id -of the request in *msgidp. A subsequent call to ldap_result(), described -below, can be used to obtain the result of the compare. - - - -Expires: January 1998 [Page 18] - -C LDAP API The C LDAP Application Program Interface 29 July 1997 - - -Similar to ldap_compare_ext(), the ldap_compare() function initiates an -asynchronous compare operation and returns the message id of the opera- -tion initiated. As for ldap_compare_ext(), a subsequent call to -ldap_result(), described below, can be used to obtain the result of the -bind. In case of error, ldap_compare() will return -1, setting the ses- -sion error parameters in the LDAP structure appropriately. - -The synchronous ldap_compare_ext_s() and ldap_compare_s() functions both -return the result of the operation, either the constant LDAP_SUCCESS if -the operation was successful, or another LDAP error code if it was not. -See the section below on error handling for more information about pos- -sible errors and how to interpret them. - -The ldap_compare_ext() and ldap_compare_ext_s() functions support LDAPv3 -server controls and client controls. - - -7.10. Modifying an entry - -The following routines are used to modify an existing LDAP entry. There -are four variations: - - typedef struct ldapmod { - int mod_op; - char *mod_type; - union { - char **modv_strvals; - struct berval **modv_bvals; - } mod_vals; - } LDAPMod; - #define mod_values mod_vals.modv_strvals - #define mod_bvalues mod_vals.modv_bvals - - int ldap_modify_ext( - LDAP *ld, - char *dn, - LDAPMod **mods, - LDAPControl **serverctrls, - LDAPControl **clientctrls, - int *msgidp - ); - - int ldap_modify_ext_s( - LDAP *ld, - char *dn, - LDAPMod **mods, - LDAPControl **serverctrls, - LDAPControl **clientctrls - - - -Expires: January 1998 [Page 19] - -C LDAP API The C LDAP Application Program Interface 29 July 1997 - - - ); - - int ldap_modify( - LDAP *ld, - char *dn, - LDAPMod **mods - ); - - int ldap_modify_s( - LDAP *ld, - char *dn, - LDAPMod **mods - ); - -Parameters are: - -ld The session handle. - -dn The name of the entry to modify. - -mods A NULL-terminated array of modifications to make to the - entry. - -serverctrls List of LDAP server controls. - -clientctrls List of client controls. - -msgidp This result parameter will be set to the message id of the - request if the ldap_modify_ext() call succeeds. - -The fields in the LDAPMod structure have the following meanings: - -mod_op The modification operation to perform. It should be one of - LDAP_MOD_ADD (0x00), LDAP_MOD_DELETE (0x01), or - LDAP_MOD_REPLACE (0x02). This field also indicates the - type of values included in the mod_vals union. It is logi- - cally ORed with LDAP_MOD_BVALUES (0x80) to select the - mod_bvalues form. Otherwise, the mod_values form is used. - -mod_type The type of the attribute to modify. - -mod_vals The values (if any) to add, delete, or replace. Only one of - the mod_values or mod_bvalues variants should be used, - selected by ORing the mod_op field with the constant - LDAP_MOD_BVALUES. mod_values is a NULL-terminated array of - zero-terminated strings and mod_bvalues is a NULL- - terminated array of berval structures that can be used to - pass binary values such as images. - - - -Expires: January 1998 [Page 20] - -C LDAP API The C LDAP Application Program Interface 29 July 1997 - - -For LDAP_MOD_ADD modifications, the given values are added to the -entry, creating the attribute if necessary. - -For LDAP_MOD_DELETE modifications, the given values are deleted from the -entry, removing the attribute if no values remain. If the entire attri- -bute is to be deleted, the mod_vals field should be set to NULL. - -For LDAP_MOD_REPLACE modifications, the attribute will have the listed -values after the modification, having been created if necessary, or -removed if the mod_vals field is NULL. All modifications are performed -in the order in which they are listed. - -The ldap_modify_ext() function initiates an asynchronous modify opera- -tion and returns the constant LDAP_SUCCESS if the request was success- -fully sent, or another LDAP error code if not. See the section below on -error handling for more information about possible errors and how to -interpret them. If successful, ldap_modify_ext() places the message id -of the request in *msgidp. A subsequent call to ldap_result(), described -below, can be used to obtain the result of the modify. - -Similar to ldap_modify_ext(), the ldap_modify() function initiates an -asynchronous modify operation and returns the message id of the opera- -tion initiated. As for ldap_modify_ext(), a subsequent call to -ldap_result(), described below, can be used to obtain the result of the -modify. In case of error, ldap_modify() will return -1, setting the ses- -sion error parameters in the LDAP structure appropriately. - -The synchronous ldap_modify_ext_s() and ldap_modify_s() functions both -return the result of the operation, either the constant LDAP_SUCCESS if -the operation was successful, or another LDAP error code if it was not. -See the section below on error handling for more information about pos- -sible errors and how to interpret them. - -The ldap_modify_ext() and ldap_modify_ext_s() functions support LDAPv3 -server controls and client controls. - - -7.11. Modifying the Name of an Entry - -In LDAPv2, the ldap_modrdn() and ldap_modrdn_s() routines were used to -change the name of an LDAP entry. They could only be used to change the -least significant component of a name (the RDN or relative distinguished -name). LDAPv3 provides the Modify DN protocol operation that allows more -general name change access. The ldap_rename() and ldap_rename_s() rou- -tines are used to change the name of an entry, and the use of the -ldap_modrdn() and ldap_modrdn_s() routines is deprecated. - - int ldap_rename( - - - -Expires: January 1998 [Page 21] - -C LDAP API The C LDAP Application Program Interface 29 July 1997 - - - LDAP *ld, - char *dn, - char *newrdn, - char *newparent, - int deleteoldrdn, - LDAPControl **serverctrls, - LDAPControl **clientctrls, - int *msgidp - - ); - int ldap_rename_s( - LDAP *ld, - char *dn, - char *newrdn, - char *newparent, - int deleteoldrdn, - LDAPControl **serverctrls, - LDAPControl **clientctrls - ); - - Use of the following routines is deprecated. - - int ldap_modrdn( - LDAP *ld, - char *dn, - char *newrdn, - int deleteoldrdn - ); - int ldap_modrdn_s( - LDAP *ld, - char *dn, - char *newrdn, - int deleteoldrdn - ); - -Parameters are: - -ld The session handle. - -dn The name of the entry whose DN is to be changed. - -newrdn The new RDN to give the entry. - -newparent The new parent, or superior entry. If this parameter is - NULL, only the RDN of the entry is changed. The root DN - may be specified by passing a zero length string, "". The - newparent parameter should always be NULL when using ver- - sion 2 of the LDAP protocol; otherwise the server's - - - -Expires: January 1998 [Page 22] - -C LDAP API The C LDAP Application Program Interface 29 July 1997 - - - behavior is undefined. - -deleteoldrdn This parameter only has meaning on the rename routines if - newrdn is different than the old RDN. It is a boolean - value, if non-zero indicating that the old RDN value(s) - should be removed, if zero indicating that the old RDN - value(s) should be retained as non-distinguished values of - the entry. - -serverctrls List of LDAP server controls. - -clientctrls List of client controls. - -msgidp This result parameter will be set to the message id of the - request if the ldap_rename() call succeeds. - -The ldap_rename() function initiates an asynchronous modify DN operation -and returns the constant LDAP_SUCCESS if the request was successfully -sent, or another LDAP error code if not. See the section below on error -handling for more information about possible errors and how to interpret -them. If successful, ldap_rename() places the DN message id of the -request in *msgidp. A subsequent call to ldap_result(), described below, -can be used to obtain the result of the rename. - -The synchronous ldap_rename_s() returns the result of the operation, -either the constant LDAP_SUCCESS if the operation was successful, or -another LDAP error code if it was not. See the section below on error -handling for more information about possible errors and how to interpret -them. - -The ldap_rename() and ldap_rename_s() functions both support LDAPv3 -server controls and client controls. - - -7.12. Adding an entry - -The following functions are used to add entries to the LDAP directory. -There are four variations: - - int ldap_add_ext( - LDAP *ld, - char *dn, - LDAPMod **attrs, - LDAPControl **serverctrls, - LDAPControl **clientctrls, - int *msgidp - ); - - - - -Expires: January 1998 [Page 23] - -C LDAP API The C LDAP Application Program Interface 29 July 1997 - - - int ldap_add_ext_s( - LDAP *ld, - char *dn, - LDAPMod **attrs, - LDAPControl **serverctrls, - LDAPControl **clientctrls - ); - - int ldap_add( - LDAP *ld, - char *dn, - LDAPMod **attrs - ); - - int ldap_add_s( - LDAP *ld, - char *dn, - LDAPMod **attrs - ); - -Parameters are: - -ld The session handle. - -dn The name of the entry to add. - -attrs The entry's attributes, specified using the LDAPMod struc- - ture defined for ldap_modify(). The mod_type and mod_vals - fields should be filled in. The mod_op field is ignored - unless ORed with the constant LDAP_MOD_BVALUES, used to - select the mod_bvalues case of the mod_vals union. - -serverctrls List of LDAP server controls. - -clientctrls List of client controls. - -msgidp This result parameter will be set to the message id of the - request if the ldap_add_ext() call succeeds. - -Note that the parent of the entry being added must already exist or the -parent must be empty (i.e., equal to the root DN) for an add to succeed. - -The ldap_add_ext() function initiates an asynchronous add operation and -returns the constant LDAP_SUCCESS if the request was successfully sent, -or another LDAP error code if not. See the section below on error han- -dling for more information about possible errors and how to interpret -them. If successful, ldap_add_ext() places the message id of the -request in *msgidp. A subsequent call to ldap_result(), described below, - - - -Expires: January 1998 [Page 24] - -C LDAP API The C LDAP Application Program Interface 29 July 1997 - - -can be used to obtain the result of the add. - -Similar to ldap_add_ext(), the ldap_add() function initiates an asyn- -chronous add operation and returns the message id of the operation ini- -tiated. As for ldap_add_ext(), a subsequent call to ldap_result(), -described below, can be used to obtain the result of the add. In case of -error, ldap_add() will return -1, setting the session error parameters -in the LDAP structure appropriately. - -The synchronous ldap_add_ext_s() and ldap_add_s() functions both return -the result of the operation, either the constant LDAP_SUCCESS if the -operation was successful, or another LDAP error code if it was not. See -the section below on error handling for more information about possible -errors and how to interpret them. - -The ldap_add_ext() and ldap_add_ext_s() functions support LDAPv3 server -controls and client controls. - - - -7.13. Deleting an entry - -The following functions are used to delete a leaf entry from the LDAP -directory. There are four variations: - - int ldap_delete_ext( - LDAP *ld, - char *dn, - LDAPControl **serverctrls, - LDAPControl **clientctrls, - int *msgidp - ); - - int ldap_delete_ext_s( - LDAP *ld, - char *dn, - LDAPControl **serverctrls, - LDAPControl **clientctrls - ); - - int ldap_delete( - LDAP *ld, - char *dn - ); - - int ldap_delete_s( - LDAP *ld, - char *dn - - - -Expires: January 1998 [Page 25] - -C LDAP API The C LDAP Application Program Interface 29 July 1997 - - - ); - -Parameters are: - -ld The session handle. - -dn The name of the entry to delete. - -serverctrls List of LDAP server controls. - -clientctrls List of client controls. - -msgidp This result parameter will be set to the message id of the - request if the ldap_delete_ext() call succeeds. - -Note that the entry to delete must be a leaf entry (i.e., it must have -no children). Deletion of entire subtrees in a single operation is not -supported by LDAP. - -The ldap_delete_ext() function initiates an asynchronous delete opera- -tion and returns the constant LDAP_SUCCESS if the request was success- -fully sent, or another LDAP error code if not. See the section below on -error handling for more information about possible errors and how to -interpret them. If successful, ldap_delete_ext() places the message id -of the request in *msgidp. A subsequent call to ldap_result(), described -below, can be used to obtain the result of the delete. - -Similar to ldap_delete_ext(), the ldap_delete() function initiates an -asynchronous delete operation and returns the message id of the opera- -tion initiated. As for ldap_delete_ext(), a subsequent call to -ldap_result(), described below, can be used to obtain the result of the -delete. In case of error, ldap_delete() will return -1, setting the ses- -sion error parameters in the LDAP structure appropriately. - -The synchronous ldap_delete_ext_s() and ldap_delete_s() functions both -return the result of the operation, either the constant LDAP_SUCCESS if -the operation was successful, or another LDAP error code if it was not. -See the section below on error handling for more information about pos- -sible errors and how to interpret them. - -The ldap_delete_ext() and ldap_delete_ext_s() functions support LDAPv3 -server controls and client controls. - - -7.14. Extended Operations - -The ldap_extended_operation() and ldap_extended_operation_s() routines -allow extended LDAP operations to be passed to the server, providing a - - - -Expires: January 1998 [Page 26] - -C LDAP API The C LDAP Application Program Interface 29 July 1997 - - -general protocol extensibility mechanism. - - int ldap_extended_operation( - LDAP *ld, - char *exoid, - struct berval *exdata, - LDAPControl **serverctrls, - LDAPControl **clientctrls, - int *msgidp - ); - - int ldap_extended_operation_s( - LDAP *ld, - char *exoid, - struct berval *exdata, - LDAPControl **serverctrls, - LDAPControl **clientctrls, - char **retoidp, - struct berval **retdatap - ); - -Parameters are: - -ld The session handle. - -requestoid The dotted-OID text string naming the request. - -requestdata The arbitrary data required by the operation (if NULL, no - data is sent to the server). - -serverctrls List of LDAP server controls. - -clientctrls List of client controls. - -msgidp This result parameter will be set to the message id of the - request if the ldap_extended_operation() call succeeds. - -retoidp Pointer to a character string that will be set to an allo- - cated, dotted-OID text string returned by the server. This - string should be disposed of using the ldap_memfree() func- - tion. If no OID was returned, *retoidp is set to NULL. - -retdatap Pointer to a berval structure pointer that will be set an - allocated copy of the data returned by the server. This - struct berval should be disposed of using ber_bvfree(). If - no data is returned, *retdatap is set to NULL. - -The ldap_extended_operation() function initiates an asynchronous - - - -Expires: January 1998 [Page 27] - -C LDAP API The C LDAP Application Program Interface 29 July 1997 - - -extended operation and returns the constant LDAP_SUCCESS if the request -was successfully sent, or another LDAP error code if not. See the sec- -tion below on error handling for more information about possible errors -and how to interpret them. If successful, ldap_extended_operation() -places the message id of the request in *msgidp. A subsequent call to -ldap_result(), described below, can be used to obtain the result of the -extended operation which can be passed to ldap_parse_extended_result() -to obtain the OID and data contained in the response. - -The synchronous ldap_extended_operation_s() function returns the result -of the operation, either the constant LDAP_SUCCESS if the operation was -successful, or another LDAP error code if it was not. See the section -below on error handling for more information about possible errors and -how to interpret them. The retoid and retdata parameters are filled in -with the OID and data from the response. If no OID or data was -returned, these parameters are set to NULL. - -The ldap_extended_operation() and ldap_extended_operation_s() functions -both support LDAPv3 server controls and client controls. - - -8. Abandoning An Operation - -The following calls are used to abandon an operation in progress: - - int ldap_abandon_ext( - LDAP *ld, - int msgid, - LDAPControl **serverctrls, - LDAPControl **clientctrls - ); - - int ldap_abandon( - LDAP *ld, - int msgid - ); - - -ld The session handle. - -msgid The message id of the request to be abandoned. - -serverctrls List of LDAP server controls. - -clientctrls List of client controls. - -ldap_abandon_ext() abandons the operation with message id msgid and -returns the constant LDAP_SUCCESS if the abandon was successful or - - - -Expires: January 1998 [Page 28] - -C LDAP API The C LDAP Application Program Interface 29 July 1997 - - -another LDAP error code if not. See the section below on error handling -for more information about possible errors and how to interpret them. - -ldap_abandon() is identical to ldap_abandon_ext() except that it returns -zero if the abandon was successful, -1 otherwise and does not support -LDAPv3 server controls or client controls. - -After a successful call to ldap_abandon() or ldap_abandon_ext(), results -with the given message id are never returned from a subsequent call to -ldap_result(). There is no server response to LDAP abandon operations. - - -9. Obtaining Results and Peeking Inside LDAP Messages - -ldap_result() is used to obtain the result of a previous asynchronously -initiated operation. Note that depending on how it is called, -ldap_result() may actually return a list or "chain" of messages. - -ldap_msgfree() frees the results obtained from a previous call to -ldap_result(), or a synchronous search routine. - -ldap_msgtype() returns the type of an LDAP message. ldap_msgid() -returns the message ID of an LDAP message. - - int ldap_result( - LDAP *ld, - int msgid, - int all, - struct timeval *timeout, - LDAPMessage **res - ); - - int ldap_msgfree( LDAPMessage *res ); - - int ldap_msgtype( LDAPMessage *res ); - - int ldap_msgid( LDAPMessage *res ); - -Parameters are: - -ld The session handle. - -msgid The message id of the operation whose results are to be - returned, or the constant LDAP_RES_ANY (-1) if any result is - desired. - -all Specifies how many messages will be retrieved in a single call - to ldap_result(). This parameter only has meaning for search - - - -Expires: January 1998 [Page 29] - -C LDAP API The C LDAP Application Program Interface 29 July 1997 - - - results. Pass the constant LDAP_MSG_ONE (0x00) to retrieve one - message at a time. Pass LDAP_MSG_ALL (0x01) to request that - all results of a search be received before returning all - results in a single chain. Pass LDAP_MSG_RECEIVED (0x02) to - indicate that all results retrieved so far should be returned - in the result chain. - -timeout A timeout specifying how long to wait for results to be - returned. A NULL value causes ldap_result() to block until - results are available. A timeout value of zero seconds speci- - fies a polling behavior. - -res For ldap_result(), a result parameter that will contain the - result(s) of the operation. For ldap_msgfree(), the result - chain to be freed, obtained from a previous call to - ldap_result(), ldap_search_s(), or ldap_search_st(). - -Upon successful completion, ldap_result() returns the type of the first -result returned in the res parameter. This will be one of the following -constants. - - LDAP_RES_BIND (0x61) - LDAP_RES_SEARCH_ENTRY (0x64) - LDAP_RES_SEARCH_REFERENCE (0x73) -- new in LDAPv3 - LDAP_RES_SEARCH_RESULT (0x65) - LDAP_RES_MODIFY (0x67) - LDAP_RES_ADD (0x69) - LDAP_RES_DELETE (0x6B) - LDAP_RES_MODDN (0x6D) - LDAP_RES_COMPARE (0x6F) - LDAP_RES_EXTENDED (0x78) -- new in LDAPv3 - -ldap_result() returns 0 if the timeout expired and -1 if an error -occurs, in which case the error parameters of the LDAP session handle -will be set accordingly. - -ldap_msgfree() frees the result structure pointed to by res and returns -the type of the message it freed. - -ldap_msgtype() returns the type of the LDAP message it is passed as a -parameter. The type will be one of the types listed above, or -1 on -error. - -ldap_msgid() returns the message ID associated with the LDAP message -passed as a parameter. - - - - - - -Expires: January 1998 [Page 30] - -C LDAP API The C LDAP Application Program Interface 29 July 1997 - - -10. Handling Errors and Parsing Results - -The following calls are used to extract information from results and -handle errors returned by other LDAP API routines. - - int ldap_parse_result( - LDAP *ld, - LDAPMessage *res, - int *errcodep, - char **matcheddnp, - char **errmsgp, - char ***referralsp, - LDAPControl ***serverctrlsp, - int freeit - ); - - int ldap_parse_sasl_bind_result( - LDAP *ld, - LDAPMessage *res, - struct berval **servercredp, - int freeit - ); - - int ldap_parse_extended_result( - LDAP *ld, - LDAPMessage *res, - char **resultoidp, - struct berval **resultdata, - int freeit - ); - - char *ldap_err2string( int err ); - - The use of the following routines is deprecated. - - int ldap_result2error( - LDAP *ld, - LDAPMessage *res, - int freeit - ); - - void ldap_perror( LDAP *ld, char *msg ); - -Parameters are: - -ld The session handle. - -res The result of an LDAP operation as returned by - - - -Expires: January 1998 [Page 31] - -C LDAP API The C LDAP Application Program Interface 29 July 1997 - - - ldap_result() or one of the synchronous API operation - calls. - -errcodep This result parameter will be filled in with the LDAP error - code field from the LDAPResult message. This is the indi- - cation from the server of the outcome of the operation. - NULL may be passed to ignore this field. - -matcheddnp In the case of a return of LDAP_NO_SUCH_OBJECT, this result - parameter will be filled in with a DN indicating how much - of the name in the request was recognized. NULL may be - passed to ignore this field. The matched DN string should - be freed by calling ldap_memfree() which is described later - in this document. - -errmsgp This result parameter will be filled in with the contents - of the error message field from the LDAPResult message. - The error message string should be freed by calling - ldap_memfree() which is described later in this document. - NULL may be passed to ignore this field. - -referralsp This result parameter will be filled in with the contents - of the referrals field from the LDAPResult message, indi- - cating zero or more alternate LDAP servers where the - request should be retried. The referrals array should be - freed by calling ldap_value_free() which is described later - in this document. NULL may be passed to ignore this field. - -serverctrlsp This result parameter will be filled in with an allocated - array of controls copied out of the LDAPResult message. - The control array should be freed by calling - ldap_controls_free() which was described earlier. - -freeit A boolean that determines whether the res parameter is - disposed of or not. Pass any non-zero value to have these - routines free res after extracting the requested informa- - tion. This is provided as a convenience; you can also use - ldap_msgfree() to free the result later. - -servercredp For SASL bind results, this result parameter will be filled - in with the credentials passed back by the server for - mutual authentication, if given. An allocated berval struc- - ture is returned that should be disposed of by calling - ldap_ber_free(). NULL may be passed to ignore this field. - -resultoidp For extended results, this result parameter will be filled - in with the dotted-OID text representation of the name of - the extended operation response. This string should be - - - -Expires: January 1998 [Page 32] - -C LDAP API The C LDAP Application Program Interface 29 July 1997 - - - disposed of by calling ldap_memfree(). NULL may be passed - to ignore this field. - -resultdatap For extended results, this result parameter will be filled - in with a pointer to a struct berval containing the data in - the extended operation response. It should be disposed of - by calling ldap_ber_free(). NULL may be passed to ignore - this field. - -err For ldap_err2string(), an LDAP error code, as returned by - ldap_result2error() or another LDAP API call. - -Additional parameters for the deprecated routines are not described. -Interested readers are referred to RFC 1823. - -All of the ldap_parse_*_result() routines skip over messages of type -LDAP_RES_SEARCH_ENTRY and LDAP_RES_SEARCH_REFERENCE when looking for a -result message to parse. They return the constant LDAP_SUCCESS if the -result was successfully parsed and another LDAP error code if not. Note -that the LDAP error code that indicates the outcome of the operation -performed by the server is placed in the errcodep ldap_parse_result() -parameter. - -ldap_err2string() is used to convert a numeric LDAP error code, as -returned by one of the ldap_parse_*_result() routines, or one of the -synchronous API operation calls, into an informative NULL-terminated -character string message describing the error. It returns a pointer to -static data. - - -11. Stepping Through a List of Results - -The ldap_first_message() and ldap_next_message() routines are used to -step through the list of messages in a result chain returned by -ldap_result(). For search operations, the result chain may actually -include referral messages, entry messages, and result messages. -ldap_count_messages() is used to count the number of messages returned. -The ldap_msgtype() function, described above, can be used to distinguish -between the different message types. - - LDAPMessage *ldap_first_message( LDAP *ld, LDAPMessage *res ); - - LDAPMessage *ldap_next_message( LDAP *ld, LDAPMessage *msg ); - - int ldap_count_messages( LDAP *ld, LDAPMessage *res ); - -Parameters are: - - - - -Expires: January 1998 [Page 33] - -C LDAP API The C LDAP Application Program Interface 29 July 1997 - - -ld The session handle. - -res The result chain, as obtained by a call to one of the synchronous - search routines or ldap_result(). - -msg The message returned by a previous call to ldap_first_message() - or ldap_next_message(). - -ldap_first_message() and ldap_next_message() will return NULL when no -more messages exist in the result set to be returned. NULL is also -returned if an error occurs while stepping through the entries, in which -case the error parameters in the session handle ld will be set to indi- -cate the error. - -ldap_count_messages() returns the number of messages contained in a -chain of results. It can also be used to count the number of messages -that remain in a chain if called with a message, entry, or reference -returned by ldap_first_message(), ldap_next_message(), -ldap_first_entry(), ldap_next_entry(), ldap_first_reference(), -ldap_next_reference(). - - -12. Parsing Search Results - -The following calls are used to parse the entries and references -returned by ldap_search() and friends. These results are returned in an -opaque structure that should only be accessed by calling the routines -described below. Routines are provided to step through the entries and -references returned, step through the attributes of an entry, retrieve -the name of an entry, and retrieve the values associated with a given -attribute in an entry. - - -12.1. Stepping Through a List of Entries - -The ldap_first_entry() and ldap_next_entry() routines are used to step -through and retrieve the list of entries from a search result chain. -The ldap_first_reference() and ldap_next_reference() routines are used -to step through and retrieve the list of continuation references from a -search result chain. ldap_count_entries() is used to count the number -of entries returned. ldap_count_references() is used to count the number -of references returned. - - LDAPMessage *ldap_first_entry( LDAP *ld, LDAPMessage *res ); - - LDAPMessage *ldap_next_entry( LDAP *ld, LDAPMessage *entry ); - - LDAPMessage *ldap_first_reference( LDAP *ld, LDAPMessage *res ); - - - -Expires: January 1998 [Page 34] - -C LDAP API The C LDAP Application Program Interface 29 July 1997 - - - LDAPMessage *ldap_next_reference( LDAP *ld, LDAPMessage *ref ); - - int ldap_count_entries( LDAP *ld, LDAPMessage *res ); - - int ldap_count_references( LDAP *ld, LDAPMessage *res ); - -Parameters are: - -ld The session handle. - -res The search result, as obtained by a call to one of the synchro- - nous search routines or ldap_result(). - -entry The entry returned by a previous call to ldap_first_entry() or - ldap_next_entry(). - -ldap_first_entry() and ldap_next_entry() will return NULL when no more -entries or references exist in the result set to be returned. NULL is -also returned if an error occurs while stepping through the entries, in -which case the error parameters in the session handle ld will be set to -indicate the error. - -ldap_count_entries() returns the number of entries contained in a chain -of entries. It can also be used to count the number of entries that -remain in a chain if called with a message, entry or reference returned -by ldap_first_message(), ldap_next_message(), ldap_first_entry(), -ldap_next_entry(), ldap_first_reference(), ldap_next_reference(). - -ldap_count_references() returns the number of references contained in a -chain of search results. It can also be used to count the number of -references that remain in a chain. - - -12.2. Stepping Through the Attributes of an Entry - -The ldap_first_attribute() and ldap_next_attribute() calls are used to -step through the list of attribute types returned with an entry. - - char *ldap_first_attribute( - LDAP *ld, - LDAPMessage *entry, - BerElement **ptr - ); - - char *ldap_next_attribute( - LDAP *ld, - LDAPMessage *entry, - BerElement *ptr - - - -Expires: January 1998 [Page 35] - -C LDAP API The C LDAP Application Program Interface 29 July 1997 - - - ); - - void ldap_memfree( char *mem ); - -Parameters are: - -ld The session handle. - -entry The entry whose attributes are to be stepped through, as returned - by ldap_first_entry() or ldap_next_entry(). - -ptr In ldap_first_attribute(), the address of a pointer used inter- - nally to keep track of the current position in the entry. In - ldap_next_attribute(), the pointer returned by a previous call to - ldap_first_attribute(). - -mem A pointer to memory allocated by the LDAP library, such as the - attribute names returned by ldap_first_attribute() and - ldap_next_attribute, or the DN returned by ldap_get_dn(). - -ldap_first_attribute() and ldap_next_attribute() will return NULL when -the end of the attributes is reached, or if there is an error, in which -case the error parameters in the session handle ld will be set to indi- -cate the error. - -Both routines return a pointer to an allocated buffer containing the -current attribute name. This should be freed when no longer in use by -calling ldap_memfree(). - -ldap_first_attribute() will allocate and return in ptr a pointer to a -BerElement used to keep track of the current position. This pointer -should be passed in subsequent calls to ldap_next_attribute() to step -through the entry's attributes. After a set of calls to -ldap_first_attribute() and ldap_next_attibute(), if ptr is non-NULL, it -should be freed by calling ldap_ber_free( ptr, 0 ). Note that it is very -important to pass the second parameter as 0 (zero) in this call. - -The attribute names returned are suitable for passing in a call to -ldap_get_values() and friends to retrieve the associated values. - - -12.3. Retrieving the Values of an Attribute - -ldap_get_values() and ldap_get_values_len() are used to retrieve the -values of a given attribute from an entry. ldap_count_values() and -ldap_count_values_len() are used to count the returned values. -ldap_value_free() and ldap_value_free_len() are used to free the values. - - - - -Expires: January 1998 [Page 36] - -C LDAP API The C LDAP Application Program Interface 29 July 1997 - - - char **ldap_get_values( - LDAP *ld, - LDAPMessage *entry, - char *attr - ); - - struct berval **ldap_get_values_len( - LDAP *ld, - LDAPMessage *entry, - char *attr - ); - - int ldap_count_values( char **vals ); - - int ldap_count_values_len( struct berval **vals ); - - int ldap_value_free( char **vals ); - - int ldap_value_free_len( struct berval **vals ); - -Parameters are: - -ld The session handle. - -entry The entry from which to retrieve values, as returned by - ldap_first_entry() or ldap_next_entry(). - -attr The attribute whose values are to be retrieved, as returned by - ldap_first_attribute() or ldap_next_attribute(), or a caller- - supplied string (e.g., "mail"). - -vals The values returned by a previous call to ldap_get_values() or - ldap_get_values_len(). - -Two forms of the various calls are provided. The first form is only -suitable for use with non-binary character string data. The second _len -form is used with any kind of data. - -Note that the values returned are dynamically allocated and should be -freed by calling either ldap_value_free() or ldap_value_free_len() when -no longer in use. - - -12.4. Retrieving the name of an entry - -ldap_get_dn() is used to retrieve the name of an entry. -ldap_explode_dn() and ldap_explode_rdn() are used to break up a name -into its component parts. ldap_dn2ufn() is used to convert the name into - - - -Expires: January 1998 [Page 37] - -C LDAP API The C LDAP Application Program Interface 29 July 1997 - - -a more "user friendly" format. - - char *ldap_get_dn( LDAP *ld, LDAPMessage *entry ); - - char **ldap_explode_dn( char *dn, int notypes ); - - char **ldap_explode_rdn( char *rdn, int notypes ); - - char *ldap_dn2ufn( char *dn ); - -Parameters are: - -ld The session handle. - -entry The entry whose name is to be retrieved, as returned by - ldap_first_entry() or ldap_next_entry(). - -dn The dn to explode, such as returned by ldap_get_dn(). - -rdn The rdn to explode, such as returned in the components of the - array returned by ldap_explode_dn(). - -notypes A boolean parameter, if non-zero indicating that the dn or rdn - components should have their type information stripped off - (i.e., "cn=Babs" would become "Babs"). - -ldap_get_dn() will return NULL if there is some error parsing the dn, -setting error parameters in the session handle ld to indicate the error. -It returns a pointer to malloc'ed space that the caller should free by -calling ldap_memfree() when it is no longer in use. Note the format of -the DNs returned is given by [4]. - -ldap_explode_dn() returns a NULL-terminated char * array containing the -RDN components of the DN supplied, with or without types as indicated by -the notypes parameter. The array returned should be freed when it is no -longer in use by calling ldap_value_free(). - -ldap_explode_rdn() returns a NULL-terminated char * array containing the -components of the RDN supplied, with or without types as indicated by -the notypes parameter. The array returned should be freed when it is no -longer in use by calling ldap_value_free(). - -ldap_dn2ufn() converts the DN into the user friendly format described in -[5]. The UFN returned is malloc'ed space that should be freed by a call -to ldap_memfree() when no longer in use. - - - - - - -Expires: January 1998 [Page 38] - -C LDAP API The C LDAP Application Program Interface 29 July 1997 - - -13. Encoded ASN.1 Value Manipulation - -This section describes routines which may be used to encode and decode -BER-encoded ASN.1 values, which are often used inside of control and -extension values. - -With the exceptions of two new functions ber_flatten() and ber_init(), -these functions are compatible with the University of Michigan LDAP 3.3 -implementation of BER. - - -13.1. General - - struct berval { - unsigned long bv_len; - char *bv_val; - }; - -A struct berval contains a sequence of bytes and an indication of its -length. The bv_val is not null terminated. bv_len must always be a -nonnegative number. Applications may allocate their own berval struc- -tures. - - typedef struct berelement { - /* opaque */ - } BerElement; - -The BerElement structure contains not only a copy of the encoded value, -but also state information used in encoding or decoding. Applications -cannot allocate their own BerElement structures. The internal state is -neither thread-specific nor locked, so two threads should not manipulate -the same BerElement value simultaneously. - -A single BerElement value cannot be used for both encoding and decoding. - - void ber_bvfree ( struct berval *bv); - -ber_bvfree() frees a berval returned from this API. Both the bv->bv_val -string and the berval itself are freed. Applications should not use -ber_bvfree() with bervals which the application has allocated. - - void ber_bvecfree ( struct berval **bv ); - -ber_bvecfree() frees an array of bervals returned from this API. Each -of the bervals in the array are freed using ber_bvfree(), then the array -itself is freed. - - struct berval *ber_bvdup (struct berval *bv ); - - - -Expires: January 1998 [Page 39] - -C LDAP API The C LDAP Application Program Interface 29 July 1997 - - -ber_bvdup() returns a copy of a berval. The bv_val field in the -returned berval points to a different area of memory as the bv_val field -in the argument berval. The null pointer is returned on error (e.g. out -of memory). - - void ber_free ( BerElement *ber, int fbuf ); - -ber_free() frees a BerElement which is returned from the API calls -ber_alloc_t() or ber_init(). Each BerElement must be freed by the -caller. The second argument fbuf should always be set to 1. - - -13.2. Encoding - - BerElement *ber_alloc_t(int options); - -ber_alloc_t() constructs and returns BerElement. The null pointer is -returned on error. The options field contains a bitwise-or of options -which are to be used when generating the encoding of this BerElement. -One option is defined and must always be supplied: - - #define LBER_USE_DER 0x01 - -When this option is present, lengths will always be encoded in the -minimum number of octets. Note that this option does not cause values -of sets and sequences to be rearranged in tag and byte order, so these -functions are not suitable for generating DER output as defined in X.509 -and X.680. - -Unrecognized option bits are ignored. - -The BerElement returned by ber_alloc_t() is initially empty. Calls to -ber_printf() will append bytes to the end of the ber_alloc_t(). - - int ber_printf(BerElement *ber, char *fmt, ... ) - -The ber_printf() routine is used to encode a BER element in much the -same way that sprintf() works. One important difference, though, is -that state information is kept in the ber argument so that multiple -calls can be made to ber_printf() to append to the end of the BER ele- -ment. ber must be a pointer to a BerElement returned by ber_alloc_t(). -ber_printf() interprets and formats its arguments according to the for- -mat string fmt. ber_printf() returns -1 if there is an error during -encoding. As with sprintf(), each character in fmt refers to an argu- -ment to ber_printf(). - -The format string can contain the following format characters: - - - - -Expires: January 1998 [Page 40] - -C LDAP API The C LDAP Application Program Interface 29 July 1997 - - -'t' Tag. The next argument is an int specifying the tag to override - the next element to be written to the ber. This works across - calls. The int value must contain the tag class, constructed - bit, and tag value. The tag value must fit in a single octet - (tag value is less than 32). For example, a tag of "[3]" for a - constructed type is 0xA3. - -'b' Boolean. The next argument is an int, containing either 0 for - FALSE or 0xff for TRUE. A boolean element is output. If this - format character is not preceded by the 't' format modifier, the - tag 0x01 is used for the element. - -'i' Integer. The next argument is an int, containing the integer in - the host's byte order. An integer element is output. If this - format character is not preceded by the 't' format modifier, the - tag 0x02 is used for the element. - -'X' Bitstring. The next two arguments are a char * pointer to the - start of the bitstring, followed by an int containing the number - of bits in the bitstring. A bitstring element is output, in - primitive form. If this format character is not preceded by the - 't' format modifier, the tag 0x03 is used for the element. - -'n' Null. No argument is required. An ASN.1 NULL element is out- - put. If this format character is not preceded by the 't' format - modifier, the tag 0x05 is used for the element. - -'o' Octet string. The next two arguments are a char *, followed by - an int with the length of the string. The string may contain - null bytes and need not by null-terminated. An octet string - element is output, in primitive form. If this format character - is not preceded by the 't' format modifier, the tag 0x04 is used - for the element. - -'s' Octet string. The next argument is a char * pointing to a - null-terminated string. An octet string element in primitive - form is output, which does not include the trailing ' ' byte. If - this format character is not preceded by the 't' format modif- - ier, the tag 0x04 is used for the element. - -'v' Several octet strings. The next argument is a char **, an array - of char * pointers to null-terminated strings. The last element - in the array must be a null pointer. The octet strings do not - include the trailing SEQUENCE OF octet strings. The 't' format - modifier cannot be used with this format character. - -'V' Several octet strings. A null-terminated array of berval *'s is - supplied. Note that a construct like '{V}' is required to get an - - - -Expires: January 1998 [Page 41] - -C LDAP API The C LDAP Application Program Interface 29 July 1997 - - - actual SEQUENCE OF octet strings. The 't' format modifier cannot - be used with this format character. - -'{' Begin sequence. No argument is required. If this format char- - acter is not preceded by the 't' format modifier, the tag 0x30 - is used. - -'}' End sequence. No argument is required. The 't' format modifier - cannot be used with this format character. - -'[' Begin set. No argument is required. If this format character - is not preceded by the 't' format modifier, the tag 0x31 is - used. - -']' End set. No argument is required. The 't' format modifier can- - not be used with this format character. - -Each use of a '{' format character must be matched by a '}' character, -either later in the format string, or in the format string of a subse- -quent call to ber_printf() for that BerElement. The same applies to the -'[' and - -Sequences and sets nest, and implementations of this API must maintain -internal state to be able to properly calculate the lengths. - - int ber_flatten (BerElement *ber, struct berval **bvPtr); - -The ber_flatten routine allocates a struct berval whose contents are a -BER encoding taken from the ber argument. The bvPtr pointer points to -the returned berval, which must be freed using ber_bvfree(). This rou- -tine returns 0 on success and -1 on error. - -The ber_flatten API call is not present in U-M LDAP 3.3. - -The use of ber_flatten on a BerElement in which all '{' and '}' format -modifiers have not been properly matched can result in a berval whose -contents are not a valid BER encoding. - - -13.3. Encoding Example - -The following is an example of encoding the following ASN.1 data type: - - Example1Request ::= SEQUENCE { - s OCTET STRING, -- must be printable - val1 INTEGER, - val2 [0] INTEGER DEFAULT 0 - } - - - -Expires: January 1998 [Page 42] - -C LDAP API The C LDAP Application Program Interface 29 July 1997 - - - int encode_example1(char *s,int val1,int val2,struct berval **bvPtr) - { - BerElement *ber; - int rc; - - ber = ber_alloc_t(LBER_USE_DER); - - if (ber == NULL) return -1; - - if (ber_printf(ber,"{si",s,val1) == -1) { - ber_free(ber,1); - return -1; - } - - if (val2 != 0) { - if (ber_printf(ber,"ti",0x80,val2) == -1) { - ber_free(ber,1); - return -1; - } - } - - if (ber_printf(ber,"}") == -1) { - ber_free(ber,1); - return -1; - } - - rc = ber_flatten(ber,bvPtr); - ber_free(ber,1); - return -1; - } - - -13.4. Decoding - -The following two symbols are available to applications. - - #define LBER_ERROR 0xffffffffL - #define LBER_DEFAULT 0xffffffffL - - BerElement *ber_init (struct berval *bv); - -The ber_init functions construct BerElement and returns a new BerElement -containing a copy of the data in the bv argument. ber_init returns the -null pointer on error. - - unsigned long ber_scanf (BerElement *ber, char *fmt, ... ); - -The ber_scanf() routine is used to decode a BER element in much the same - - - -Expires: January 1998 [Page 43] - -C LDAP API The C LDAP Application Program Interface 29 July 1997 - - -way that sscanf() works. One important difference, though, is that some -state information is kept with the ber argument so that multiple calls -can be made to ber_scanf() to sequentially read from the BER element. -The ber argument must be a pointer to a BerElement returned by -ber_init(). ber_scanf interprets the bytes according to the format -string fmt, and stores the results in its additional arguments. -ber_scanf() returns LBER_ERROR on error, and a nonnegative number on -success. - -The format string contains conversion specifications which are used to -direct the interpretation of the BER element. The format string can -contain the following characters: - -'a' Octet string. A char ** argument should be supplied. Memory is - allocated, filled with the contents of the octet string, null- - terminated, and the pointer to the string is stored in the argu- - ment. The returned value must be freed using ldap_memfree. The - tag of the element must indicate the primitive form (constructed - strings are not supported) but is otherwise ignored and dis- - carded during the decoding. This format cannot be used with - octet strings which could contain null bytes. - -'O' Octet string. A struct berval ** argument should be supplied, - which upon return points to a allocated struct berval containing - the octet string and its length. ber_bvfree() must be called to - free the allocated memory. The tag of the element must indicate - the primitive form (constructed strings are not supported) but - is otherwise ignored during the decoding. - -'b' Boolean. A pointer to an int should be supplied. The int value - stored will be 0 for FALSE or nonzero for TRUE. The tag of the - element must indicate the primitive form but is otherwise - ignored during the decoding. - -'i' Integer. A pointer to an int should be supplied. The int value - stored will be in host byte order. The tag of the element must - indicate the primitive form but is otherwise ignored during the - decoding. ber_scanf() will return an error if the integer can- - not be stored in an int. - -'B' Bitstring. A char ** argument should be supplied which will - point to the allocated bits, followed by an unsigned long * - argument, which will point to the length (in bits) of the bit- - string returned. ldap_memfree must be called to free the bit- - string. The tag of the element must indicate the primitive form - (constructed bitstrings are not supported) but is otherwise - ignored during the decoding. - - - - -Expires: January 1998 [Page 44] - -C LDAP API The C LDAP Application Program Interface 29 July 1997 - - -'n' Null. No argument is required. The element is simply skipped - if it is recognized as a zero-length element. The tag is - ignored. - -'v' Several octet strings. A char *** argument should be supplied, - which upon return points to a allocated null-terminated array of - char *'s containing the octet strings. NULL is stored if the - sequence is empty. ldap_memfree must be called to free each - element of the array and the array itself. The tag of the - sequence and of the octet strings are ignored. - -'V' Several octet strings (which could contain null bytes). A - struct berval *** should be supplied, which upon return points - to a allocated null-terminated array of struct berval *'s con- - taining the octet strings and their lengths. NULL is stored if - the sequence is empty. ber_bvecfree() can be called to free the - allocated memory. The tag of the sequence and of the octet - strings are ignored. - -'x' Skip element. The next element is skipped. No argument is - required. - -'{' Begin sequence. No argument is required. The initial sequence - tag and length are skipped. - -'}' End sequence. No argument is required. - -'[' Begin set. No argument is required. The initial set tag and - length are skipped. - -']' End set. No argument is required. - - unsigned long ber_peek_tag (BerElement *ber, unsigned long *lenPtr); - -ber_peek_tag() returns the tag of the next element to be parsed in the -BerElement argument. The length of this element is stored in the -*lenPtr argument. LBER_DEFAULT is returned if there is no further data -to be read. The ber argument is not modified. - - unsigned long ber_skip_tag (BerElement *ber, unsigned long *lenPtr); - -ber_skip_tag() is similar to ber_peek_tag(), except that the state -pointer in the BerElement argument is advanced past the first tag and -length, and is pointed to the value part of the next element. This rou- -tine should only be used with constructed types and situations when a -BER encoding is used as the value of an OCTET STRING. The length of the -value is stored in *lenPtr. - - - - -Expires: January 1998 [Page 45] - -C LDAP API The C LDAP Application Program Interface 29 July 1997 - - - unsigned long ber_first_element(BerElement *ber, - unsigned long *lenPtr, char **opaquePtr); - - unsigned long ber_next_element (BerElement *ber, - unsigned long *lenPtr, char *opaque); - -ber_first_element() and ber_next_element() are used to traverse a SET, -SET OF, SEQUENCE or SEQUENCE OF data value. ber_first_element() calls -ber_skip_tag(), stores internal information in *lenPtr and *opaquePtr, -and calls ber_peek_tag() for the first element inside the constructed -value. LBER_DEFAULT is returned if the constructed value is empty. -ber_next_element() positions the state at the start of the next element -in the constructed type. LBER_DEFAULT is returned if there are no -further values. - -The len and opaque values should not be used by applications other than -as arguments to ber_next_element(), as shown in the example below. - - -13.5. Decoding Example - -The following is an example of decoding an ASN.1 data type: - - Example2Request ::= SEQUENCE { - dn OCTET STRING, -- must be printable - scope ENUMERATED { b (0), s (1), w (2) }, - ali ENUMERATED { n (0), s (1), f (2), a (3) }, - size INTEGER, - time INTEGER, - tonly BOOLEAN, - attrs SEQUENCE OF OCTET STRING, -- must be printable - [0] SEQUENCE OF SEQUENCE { - type OCTET STRING -- must be printable, - crit BOOLEAN DEFAULT FALSE, - value OCTET STRING - } OPTIONAL } - - #define LDAP_TAG_CONTROL_LIST 0xA0L /* context specific cons 0 */ - - int decode_example2(struct berval *bv) - { - BerElement *ber; - unsigned long len; - int scope, ali, size, time, tonly; - char *dn = NULL, **attrs = NULL; - int res,i,rc = 0; - - ber = ber_init(bv); - - - -Expires: January 1998 [Page 46] - -C LDAP API The C LDAP Application Program Interface 29 July 1997 - - - if (ber == NULL) { - printf("ERROR ber_init failed0); - return -1; - } - - res = ber_scanf(ber,"{aiiiiib{v}",&dn,&scope,&ali, - &size,&time,&tonly,&attrs); - - if (res == -1) { - printf("ERROR ber_scanf failed0); - ber_free(ber,1); - return -1; - } - - /* *** use dn */ - ldap_memfree(dn); - - for (i = 0; attrs != NULL && attrs[i] != NULL; i++) { - /* *** use attrs[i] */ - ldap_memfree(attrs[i]); - } - ldap_memfree(attrs); - - if (ber_peek_tag(ber,&len) == LDAP_TAG_CONTROL_LIST) { - char *opaque; - unsigned long tag; - - for (tag = ber_first_element(ber,&len,&opaque); - tag != LBER_DEFAULT; - tag = ber_next_element (ber,&len,opaque)) { - - unsigned long ttag, tlen; - char *type; - int crit; - struct berval *value; - - if (ber_scanf(ber,"{a",&type) == LBER_ERROR) { - printf("ERROR cannot parse type0); - break; - } - /* *** use type */ - ldap_memfree(type); - - ttag = ber_peek_tag(ber,&tlen); - if (ttag == 0x01) { /* boolean */ - if (ber_scanf(ber,"b", - &crit) == LBER_ERROR) { - printf("ERROR cannot parse crit0); - - - -Expires: January 1998 [Page 47] - -C LDAP API The C LDAP Application Program Interface 29 July 1997 - - - rc = -1; - break; - } - } else if (ttag == 0x04) { /* octet string */ - crit = 0; - } else { - printf("ERROR extra field in controls0); - break; - } - - if (ber_scanf(ber,"O}",&value) == LBER_ERROR) { - printf("ERROR cannot parse value0); - rc = -1; - break; - } - /* *** use value */ - ldap_bvfree(value); - } - } - - ber_scanf(ber,"}"); - - ber_free(ber,1); - - return rc; - } - - - -14. Security Considerations - -LDAPv2 supports security through protocol-level authentication using -clear-text passwords. LDAPv3 adds support for SASL [8] (Simple Authen- -tication Security Layer) methods. LDAPv3 also supports operation over a -secure transport layer using Transport Layer Security TLS [8]. Readers -are referred to the protocol documents for discussion of related secu- -rity considerations. - -Implementations of this API should be cautious when handling authentica- -tion credentials. In particular, keeping long-lived copies of creden- -tials without the application's knowledge is discouraged. - - -15. Acknowledgements - -Many members of the IETF ASID working group as well as members of the -Internet at large have provided useful comments and suggestions that -have been incorporated into this revision. - - - -Expires: January 1998 [Page 48] - -C LDAP API The C LDAP Application Program Interface 29 July 1997 - - -This original material upon which this revision is based was based upon -work supported by the National Science Foundation under Grant No. NCR- -9416667. - - -16. Bibliography - -[1] The Directory: Selected Attribute Syntaxes. CCITT, Recommendation - X.520. - -[2] M. Wahl, A. Coulbeck, T. Howes, S. Kille, W. Yeong, C. Robbins, - "Lightweight Directory Access Protocol Attribute Syntax Defini- - tions", INTERNET-DRAFT , - 11 July 1997. - -[3] T. Howes, "A String Representation of LDAP Search Filters," - INTERNET-DRAFT , May 1997. - -[4] S. Kille, M. Wahl, "A UTF-8 String Representation of Distinguished - Names", INTERNET-DRAFT , 29 April - 1997. - -[5] S. Kille, "Using the OSI Directory to Achieve User Friendly Nam- - ing," RFC 1781, March 1995. - -[6] M. Wahl, T. Howes, S. Kille, "Lightweight Directory Access Protocol - (v3)", INTERNET-DRAFT , 11 - July 1997. - -[7] A. Herron, T. Howes, M. Wahl, "LDAP Control Extension for Server - Side Sorting of Search Result," INTERNET-DRAFT , 16 April 1997. - -[8] J. Meyers, "Simple Authentication and Security Layer", INTERNET- - DRAFT , April 1997. - -[9] "Lightweight Directory Access Protocol (v3) Extension for Transport - Layer Security", INTERNET-DRAFT , June 1997. - -[10] "UTF-8, a transformation format of Unicode and ISO 10646", RFC - 2044, October 1996. - -[11] "IP Version 6 Addressing Architecture,", RFC 1884, December 1995. - - - - - - - -Expires: January 1998 [Page 49] - -C LDAP API The C LDAP Application Program Interface 29 July 1997 - - -17. Author's Addresses - - Tim Howes - Netscape Communications Corp. - 501 E. Middlefield Rd., Mailstop MV068 - Mountain View, CA 94043 - USA - +1 415 937-3419 - howes@netscape.com - - - Mark Smith - Netscape Communications Corp. - 501 E. Middlefield Rd., Mailstop MV068 - Mountain View, CA 94043 - USA - +1 415 937-3477 - mcs@netscape.com - - Andy Herron - Microsoft Corp. - 1 Microsoft Way - Redmond, WA 98052 - USA - +1 425 882-8080 - andyhe@microsoft.com - - Chris Weider - Microsoft Corp. - 1 Microsoft Way - Redmond, WA 98052 - USA - +1 425 882-8080 - cweider@microsoft.com - - Mark Wahl - Critical Angle Inc. - 4815 W Braker Lane #502-385 - Austin, TX 78759 - USA - M.Wahl@critical-angle.com - - -18. Appendix A - Sample LDAP API Code - - #include - - main() - - - -Expires: January 1998 [Page 50] - -C LDAP API The C LDAP Application Program Interface 29 July 1997 - - - { - LDAP *ld; - LDAPMessage *res, *e; - int i; - char *a, *dn; - BerElement *ptr; - char **vals; - - /* open an LDAP session */ - if ( (ld = ldap_init( "dotted.host.name", LDAP_PORT )) == NULL ) - exit( 1 ); - - /* authenticate as nobody */ - if ( ldap_simple_bind_s( ld, NULL, NULL ) != LDAP_SUCCESS ) { - ldap_perror( ld, "ldap_simple_bind_s" ); - exit( 1 ); - } - - /* search for entries with cn of "Babs Jensen", return all attrs */ - if ( ldap_search_s( ld, "o=University of Michigan, c=US", - LDAP_SCOPE_SUBTREE, "(cn=Babs Jensen)", NULL, 0, &res ) - != LDAP_SUCCESS ) { - ldap_perror( ld, "ldap_search_s" ); - exit( 1 ); - } - - /* step through each entry returned */ - for ( e = ldap_first_entry( ld, res ); e != NULL; - e = ldap_next_entry( ld, e ) ) { - /* print its name */ - dn = ldap_get_dn( ld, e ); - printf( "dn: %s\n", dn ); - ldap_memfree( dn ); - - /* print each attribute */ - for ( a = ldap_first_attribute( ld, e, &ptr ); a != NULL; - a = ldap_next_attribute( ld, e, ptr ) ) { - printf( "attribute: %s\n", a ); - - /* print each value */ - vals = ldap_get_values( ld, e, a ); - for ( i = 0; vals[i] != NULL; i++ ) { - printf( "value: %s\n", vals[i] ); - } - ldap_value_free( vals ); - } - if ( ptr != NULL ) { - ldap_ber_free( ptr, 0 ); - - - -Expires: January 1998 [Page 51] - -C LDAP API The C LDAP Application Program Interface 29 July 1997 - - - } - } - /* free the search results */ - ldap_msgfree( res ); - - /* close and free connection resources */ - ldap_unbind( ld ); - } - - - -19. Appendix B - Outstanding Issues - - -19.1. Support for multithreaded applications - -In order to support multithreaded applications in a platform-independent -way, some additions to the LDAP API are needed. Different implementors -have taken different paths to solve this problem in the past. A common -set of thread-related API calls must be defined so that application -developers are not unduly burdened. These will be added to a future -revision of this specification. - - -19.2. Using Transport Layer Security (TLS) - -The API calls used to support TLS must be specified. They will be added -to a future revision of this specification. - - -19.3. Client control for chasing referrals - -A client control has been defined that can be used to specify on a per- -operation basis whether references and external referrals are automati- -cally chased by the client library. This will be added to a future -revision of this specification. - - -19.4. Potential confusion between hostname:port and IPv6 addresses - -String representations of IPv6 network addresses [11] can contain colon -characters. The ldap_init() call is specified to take strings of the -form "hostname:port" or "ipaddress:port". If IPv6 addresses are used, -the latter could be ambiguous. A future revision of this specification -will resolve this issue. - - - - - - -Expires: January 1998 [Page 52] - -C LDAP API The C LDAP Application Program Interface 29 July 1997 - - -19.5. Need to track SASL API standardization efforts - -If a standard Simple Authentication and Security Layer API is defined, -it may be necessary to modify the LDAP API to accommodate it. - - -19.6. Support for character sets other than UTF-8? - -Some application developers would prefer to pass string data using a -character set other than UTF-8. This could be accommodated by adding a -new option to ldap_set_option() that supports choosing a character set. -If this feature is added, the number of different character sets sup- -ported should definitely be minimized. - - -19.7. Use of UTF-8 with LDAPv2 servers - -Strings are always passed as UTF-8 in this API but LDAP version 2 -servers do not support the full range of UTF-8 characters. The expected -behavior of this API when using LDAP version 2 with unsupported charac- -ters should be specified. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Expires: January 1998 [Page 53] - - - -1. Status of this Memo............................................1 -2. Introduction...................................................1 -3. Overview of the LDAP Model.....................................2 -4. Overview of LDAP API Use.......................................3 -5. Common Data Structures.........................................4 -6. LDAP Error Codes...............................................5 -7. Performing LDAP Operations.....................................6 -7.1. Initializing an LDAP Session................................6 -7.2. LDAP Session Handle Options.................................7 -7.3. Working with controls.......................................10 -7.4. Authenticating to the directory.............................11 -7.5. Closing the session.........................................13 -7.6. Searching...................................................13 -7.7. Reading an Entry............................................17 -7.8. Listing the Children of an Entry............................17 -7.9. Comparing a Value Against an Entry..........................17 -7.10. Modifying an entry..........................................19 -7.11. Modifying the Name of an Entry..............................21 -7.12. Adding an entry.............................................23 -7.13. Deleting an entry...........................................25 -7.14. Extended Operations.........................................26 -8. Abandoning An Operation........................................28 -9. Obtaining Results and Peeking Inside LDAP Messages.............29 -10. Handling Errors and Parsing Results............................31 -11. Stepping Through a List of Results.............................33 -12. Parsing Search Results.........................................34 -12.1. Stepping Through a List of Entries..........................34 -12.2. Stepping Through the Attributes of an Entry.................35 -12.3. Retrieving the Values of an Attribute.......................36 -12.4. Retrieving the name of an entry.............................37 -13. Encoded ASN.1 Value Manipulation...............................39 -13.1. General.....................................................39 -13.2. Encoding....................................................40 -13.3. Encoding Example............................................42 -13.4. Decoding....................................................43 -13.5. Decoding Example............................................46 -14. Security Considerations........................................48 -15. Acknowledgements...............................................48 -16. Bibliography...................................................49 -17. Author's Addresses.............................................50 -18. Appendix A - Sample LDAP API Code..............................50 -19. Appendix B - Outstanding Issues................................52 -19.1. Support for multithreaded applications......................52 -19.2. Using Transport Layer Security (TLS)........................52 -19.3. Client control for chasing referrals........................52 -19.4. Potential confusion between hostname:port and IPv6 addresses52 -19.5. Need to track SASL API standardization efforts..............53 -19.6. Support for character sets other than UTF-8?................53 -19.7. Use of UTF-8 with LDAPv2 servers............................53 - - - - - - - - rabbitmq-server-3.2.4/plugins-src/eldap-wrapper/LICENSE-MIT-eldap0000644000000000000000000000205212305126066023053 0ustar rootroot Copyright (c) 2010, Torbjorn Tornkvist Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. rabbitmq-server-3.2.4/plugins-src/eldap-wrapper/.srcdist_done0000644000000000000000000000000012305126066023004 0ustar rootrootrabbitmq-server-3.2.4/plugins-src/eldap-wrapper/license_info0000644000000000000000000000021412305126066022712 0ustar rootrootEldap is "Copyright (c) 2010, Torbjorn Tornkvist" and is covered by the MIT license. It was downloaded from https://github.com/etnt/eldap rabbitmq-server-3.2.4/plugins-src/eldap-wrapper/hash.mk0000644000000000000000000000003512305126066021607 0ustar rootrootUPSTREAM_SHORT_HASH:=e309de4 rabbitmq-server-3.2.4/plugins-src/eldap-wrapper/Makefile0000644000000000000000000000002712305126066021774 0ustar rootrootinclude ../umbrella.mk rabbitmq-server-3.2.4/plugins-src/eldap-wrapper/eldap-appify.patch0000644000000000000000000000061312305126066023731 0ustar rootrootdiff -Naur eldap.orig/ebin/eldap.app eldap/ebin/eldap.app --- eldap.orig/ebin/eldap.app 1970-01-01 01:00:00.000000000 +0100 +++ eldap/ebin/eldap.app 2011-01-20 12:47:04.377399296 +0000 @@ -0,0 +1,10 @@ +{application, eldap, + [{description, "LDAP Client Library"}, + {vsn, "0.01"}, + {modules, [ + eldap, + 'ELDAPv3' + ]}, + {registered, []}, + {applications, [kernel, stdlib]} + ]}. rabbitmq-server-3.2.4/plugins-src/eldap-wrapper/package.mk0000644000000000000000000000165412305126066022267 0ustar rootrootAPP_NAME:=eldap UPSTREAM_GIT:=https://github.com/rabbitmq/eldap.git UPSTREAM_REVISION:=e309de4db4b78d67d623 WRAPPER_PATCHES:=eldap-appify.patch remove-eldap-fsm.patch eldap-no-ssl-seed.patch remove-ietf-doc.patch ORIGINAL_APP_FILE:=$(CLONE_DIR)/ebin/$(APP_NAME).app DO_NOT_GENERATE_APP_FILE=true GENERATED_DIR:=$(CLONE_DIR)/generated PACKAGE_ERLC_OPTS+=-I $(GENERATED_DIR) INCLUDE_HRLS+=$(GENERATED_DIR)/ELDAPv3.hrl EBIN_BEAMS+=$(GENERATED_DIR)/ELDAPv3.beam define package_rules $(CLONE_DIR)/src/ELDAPv3.asn: $(CLONE_DIR)/.done $(GENERATED_DIR)/ELDAPv3.hrl $(GENERATED_DIR)/ELDAPv3.beam: $(CLONE_DIR)/src/ELDAPv3.asn @mkdir -p $(GENERATED_DIR) $(ERLC) $(PACKAGE_ERLC_OPTS) -o $(GENERATED_DIR) $$< $(PACKAGE_DIR)+clean:: rm -rf $(GENERATED_DIR) $(EBIN_DIR) # This rule is run *before* the one in do_package.mk $(PLUGINS_SRC_DIST_DIR)/$(PACKAGE_DIR)/.srcdist_done:: cp $(CLONE_DIR)/LICENSE $(PACKAGE_DIR)/LICENSE-MIT-eldap endef rabbitmq-server-3.2.4/plugins-src/eldap-wrapper/eldap-no-ssl-seed.patch0000644000000000000000000000114112305126066024567 0ustar rootrootdiff --git a/src/eldap.erl b/src/eldap.erl index 9a78270..b0cdb2e 100644 --- a/src/eldap.erl +++ b/src/eldap.erl @@ -363,12 +363,5 @@ do_connect(Host, Data, Opts) when Data#eldap.use_tls == false -> gen_tcp:connect(Host, Data#eldap.port, Opts, Data#eldap.timeout); do_connect(Host, Data, Opts) when Data#eldap.use_tls == true -> - Vsn = erlang:system_info(version), - if Vsn >= "5.3" -> - %% In R9C, but not in R9B - {_,_,X} = erlang:now(), - ssl:seed("bkrlnateqqo" ++ integer_to_list(X)); - true -> true - end, ssl:connect(Host, Data#eldap.port, [{verify,0}|Opts]). rabbitmq-server-3.2.4/plugins-src/generate_app0000644000000000000000000000115612305126066020152 0ustar rootroot#!/usr/bin/env escript %% -*- erlang -*- main([InFile, OutFile | SrcDirs]) -> Modules = [list_to_atom(filename:basename(F, ".erl")) || SrcDir <- SrcDirs, F <- filelib:wildcard("*.erl", SrcDir)], {ok, [{application, Application, Properties}]} = file:consult(InFile), NewProperties = case proplists:get_value(modules, Properties) of [] -> lists:keyreplace(modules, 1, Properties, {modules, Modules}); _ -> Properties end, file:write_file( OutFile, io_lib:format("~p.~n", [{application, Application, NewProperties}])). rabbitmq-server-3.2.4/plugins-src/rabbitmq-federation-management/0000755000000000000000000000000012305126066023623 5ustar rootrootrabbitmq-server-3.2.4/plugins-src/rabbitmq-federation-management/priv/0000755000000000000000000000000012305126066024603 5ustar rootrootrabbitmq-server-3.2.4/plugins-src/rabbitmq-federation-management/priv/www/0000755000000000000000000000000012305126066025427 5ustar rootrootrabbitmq-server-3.2.4/plugins-src/rabbitmq-federation-management/priv/www/js/0000755000000000000000000000000012305126066026043 5ustar rootrootrabbitmq-server-3.2.4/plugins-src/rabbitmq-federation-management/priv/www/js/tmpl/0000755000000000000000000000000012305126066027017 5ustar rootrootrabbitmq-server-3.2.4/plugins-src/rabbitmq-federation-management/priv/www/js/tmpl/federation.ejs0000644000000000000000000000364112305126066031646 0ustar rootroot

    Federation Status

    Running Links

    <% if (links.length > 0) { %> <% if (vhosts_interesting) { %> <% } %> <% if (nodes_interesting) { %> <% } %> <% for (var i = 0; i < links.length; i++) { var link = links[i]; %> > <% if (vhosts_interesting) { %> <% } %> <% if (nodes_interesting) { %> <% } %> <% if (link.error) { %> <% } else { %> <% } %> <% } %>
    Connection URIVirtual HostExchange / QueueNodeState Inbound message rate Last changed
    <%= fmt_string(link.connection) %> <% if (link.name != link.upstream_name) { %> <%= fmt_string(link.upstream_name) %> <% } %> <%= fmt_string(link.uri) %><%= fmt_string(link.vhost) %> <% if (link.type == 'exchange') { %> <%= link_exchange(link.vhost, link.name) %> <% } else { %> <%= link_queue(link.vhost, link.name) %> <% } %> <%= fmt_string(link.type) %> <%= fmt_node(link.node) %>
    <%= link.status %>
    <%= link.timestamp %>
    <% if (link.status == 'starting') { %>
    <%= link.status %>
    <% } else { %>
    <%= link.status %>
    <% } %>
    <% if (link.local_channel) { %> <%= fmt_rate(link.local_channel.message_stats, 'confirm') %> <% } %> <%= link.timestamp %>
    <% } else { %>

    ... no links ...

    <% } %>
    ././@LongLink0000000000000000000000000000015200000000000011563 Lustar rootrootrabbitmq-server-3.2.4/plugins-src/rabbitmq-federation-management/priv/www/js/tmpl/federation-upstream.ejsrabbitmq-server-3.2.4/plugins-src/rabbitmq-federation-management/priv/www/js/tmpl/federation-upstrea0000644000000000000000000000325112305126066032544 0ustar rootroot

    Federation Upstream: <%= fmt_string(upstream.name) %>

    Overview

    Virtual Host <%= fmt_string(upstream.vhost) %>
    URI <%= fmt_string(upstream.value.uri) %>
    Expires <%= fmt_time(upstream.value.expires, 'ms') %>
    Message TTL <%= fmt_time(upstream.value['message-ttl'], 'ms') %>
    Max Hops <%= fmt_string(upstream.value['max-hops']) %>
    Prefetch Count <%= fmt_string(upstream.value['prefetch-count']) %>
    Reconnect Delay <%= fmt_time(upstream.value['reconnect-delay'], 's') %>
    Ack Mode <%= fmt_string(upstream.value['ack-mode']) %>
    Trust User-ID <%= fmt_boolean(upstream.value['trust-user-id']) %>

    Delete this upstream

    ././@LongLink0000000000000000000000000000015300000000000011564 Lustar rootrootrabbitmq-server-3.2.4/plugins-src/rabbitmq-federation-management/priv/www/js/tmpl/federation-upstreams.ejsrabbitmq-server-3.2.4/plugins-src/rabbitmq-federation-management/priv/www/js/tmpl/federation-upstrea0000644000000000000000000001724612305126066032555 0ustar rootroot

    Federation Upstreams

    Upstreams

    <% if (upstreams.length > 0) { %> <% if (vhosts_interesting) { %> <% } %> <% for (var i = 0; i < upstreams.length; i++) { var upstream = upstreams[i]; %> > <% if (vhosts_interesting) { %> <% } %> <% } %>
    Virtual HostName URI Expiry Message TTL Max Hops Prefetch Count Reconnect Delay Ack mode Trust User-ID
    <%= fmt_string(upstream.vhost) %><%= link_fed_conn(upstream.vhost, upstream.name) %> <%= fmt_shortened_uri(upstream.value.uri) %> <%= fmt_time(upstream.value.expires, 'ms') %> <%= fmt_time(upstream.value['message-ttl'], 'ms') %> <%= upstream.value['max-hops'] %> <%= upstream.value['prefetch-count'] %> <%= fmt_time(upstream.value['reconnect-delay'], 's') %> <%= fmt_string(upstream.value['ack-mode']) %> <%= fmt_boolean(upstream.value['trust-user-id']) %>
    <% } else { %>

    ... no upstreams ...

    <% } %>

    Add a new upstream

    <% if (vhosts_interesting) { %> <% } else { %> <% } %>
    *
    *
    ms
    ms
    s

    URI examples

    • amqp://server-name
      connect to server-name, without SSL and default credentials
    • amqp://user:password@server-name/my-vhost
      connect to server-name, with credentials and overridden virtual host
    • amqps://user:password@server-name?cacertfile=/path/to/cacert.pem&certfile=/path/to/cert.pem&keyfile=/path/to/key.pem&verify=verify_peer
      connect to server-name, with credentials and SSL
    • amqps://server-name?cacertfile=/path/to/cacert.pem&certfile=/path/to/cert.pem&keyfile=/path/to/key.pem&verify=verify_peer&fail_if_no_peer_cert=true&auth_mechanism=external
      connect to server-name, with SSL and EXTERNAL authentication

    Parameters

    <% if (vhosts_interesting) { %> <% } %> <% for (var i = 0; i < vhosts.length; i++) { var vhost = vhosts[i]; if (current_vhost != '' && current_vhost != vhost.name) continue; var username = null; var nodename = null; for (var j in globals) { if (globals[j].vhost == vhost.name) { if (globals[j].name == 'local-username') username = globals[j].value; if (globals[j].name == 'local-nodename') nodename = globals[j].value; } } %> > <% if (vhosts_interesting) { %> <% } %> <% } %>
    Virtual Host Local username Explicit identity for this cluster / node
    <%= fmt_string(vhost.name) %>
    rabbitmq-server-3.2.4/plugins-src/rabbitmq-federation-management/priv/www/js/federation.js0000644000000000000000000001075612305126066030532 0ustar rootrootdispatcher_add(function(sammy) { sammy.get('#/federation', function() { render({'links': {path: '/federation-links', options:{vhost:true}}, 'vhosts': '/vhosts'}, 'federation', '#/federation'); }); sammy.get('#/federation-upstreams', function() { render({'upstreams': {path: '/parameters/federation-upstream', options:{vhost:true}}, 'vhosts': '/vhosts', 'globals': '/parameters/federation'}, 'federation-upstreams', '#/federation-upstreams'); }); sammy.get('#/federation-upstreams/:vhost/:id', function() { render({'upstream': '/parameters/federation-upstream/' + esc(this.params['vhost']) + '/' + esc(this.params['id'])}, 'federation-upstream', '#/federation'); }); sammy.put('#/fed-globals', function() { if (this.params.value == '') this.params.value = null; if (sync_put(this, '/parameters/:component/:vhost/:name')) update(); return false; }); sammy.put('#/fed-parameters', function() { var num_keys = ['expires', 'message-ttl', 'max-hops', 'prefetch-count', 'reconnect-delay']; var bool_keys = ['trust-user-id']; var arrayable_keys = ['uri']; put_parameter(this, [], num_keys, bool_keys, arrayable_keys); return false; }); sammy.del('#/fed-parameters', function() { if (sync_delete(this, '/parameters/:component/:vhost/:name')) go_to('#/federation-upstreams'); return false; }); }); NAVIGATION['Admin'][0]['Federation Status'] = ['#/federation', "monitoring"]; NAVIGATION['Admin'][0]['Federation Upstreams'] = ['#/federation-upstreams', "policymaker"]; HELP['federation-explicit-identity'] = 'Each broker in a federated set of brokers needs a name. If you leave this blank RabbitMQ will generate one. If you set this, ensure that each broker has a unique name. Note that you must set this when using federation combined with clustering.'; HELP['federation-local-username'] = 'The name of a local user which can be used to publish messages received over federated links.'; HELP['federation-uri'] = 'URI to connect to. If upstream is a cluster and can have several URIs, you can enter them here separated by spaces.'; HELP['federation-expires'] = 'Time in milliseconds that the upstream should remember about this node for. After this time all upstream state will be removed. Leave this blank to mean "forever".'; HELP['federation-ttl'] = 'Time in milliseconds that undelivered messages should be held upstream when there is a network outage or backlog. Leave this blank to mean "forever".'; HELP['federation-max-hops'] = 'Maximum number of federation links that messages can traverse before being dropped. Defaults to 1 if not set.'; HELP['federation-prefetch'] = 'Maximum number of unacknowledged messages that may be in flight over a federation link at one time. Defaults to 1000 if not set.'; HELP['federation-reconnect'] = 'Time in seconds to wait after a network link goes down before attempting reconnection. Defaults to 1 if not set.'; HELP['federation-ack-mode'] = '
    \
    on-confirm
    \
    Messages are acknowledged to the upstream broker after they have been confirmed downstream. Handles network errors and broker failures without losing messages. The slowest option, and the default.
    \
    on-publish
    \
    Messages are acknowledged to the upstream broker after they have been published downstream. Handles network errors without losing messages, but may lose messages in the event of broker failures.
    \
    no-ack
    \
    Message acknowledgements are not used. The fastest option, but may lose messages in the event of network or broker failures.
    \
    '; HELP['federation-trust-user-id'] = 'Set "Yes" to preserve the "user-id" field across a federation link, even if the user-id does not match that used to republish the message. Set to "No" to clear the "user-id" field when messages are federated. Only set this to "Yes" if you trust the upstream broker not to forge user-ids.'; function link_fed_conn(vhost, name) { return _link_to(fmt_escape_html(name), '#/federation-upstreams/' + esc(vhost) + '/' + esc(name)); } rabbitmq-server-3.2.4/plugins-src/rabbitmq-federation-management/src/0000755000000000000000000000000012305126066024412 5ustar rootrootrabbitmq-server-3.2.4/plugins-src/rabbitmq-federation-management/src/rabbit_federation_mgmt.erl0000644000000000000000000000732512305126066031614 0ustar rootroot%% The contents of this file are subject to the Mozilla Public License %% Version 1.1 (the "License"); you may not use this file except in %% compliance with the License. You may obtain a copy of the License %% at http://www.mozilla.org/MPL/ %% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See %% the License for the specific language governing rights and %% limitations under the License. %% %% The Original Code is RabbitMQ. %% %% The Initial Developer of the Original Code is GoPivotal, Inc. %% Copyright (c) 2007-2013 GoPivotal, Inc. All rights reserved. %% -module(rabbit_federation_mgmt). -behaviour(rabbit_mgmt_extension). -export([dispatcher/0, web_ui/0]). -export([init/1, to_json/2, resource_exists/2, content_types_provided/2, is_authorized/2]). -import(rabbit_misc, [pget/2]). -include_lib("rabbitmq_management/include/rabbit_mgmt.hrl"). -include_lib("webmachine/include/webmachine.hrl"). dispatcher() -> [{["federation-links"], ?MODULE, []}, {["federation-links", vhost], ?MODULE, []}]. web_ui() -> [{javascript, <<"federation.js">>}]. %%-------------------------------------------------------------------- init(_Config) -> {ok, #context{}}. content_types_provided(ReqData, Context) -> {[{"application/json", to_json}], ReqData, Context}. resource_exists(ReqData, Context) -> {case rabbit_mgmt_util:vhost(ReqData) of not_found -> false; _ -> true end, ReqData, Context}. to_json(ReqData, Context) -> Chs = rabbit_mgmt_db:get_all_channels( rabbit_mgmt_util:range(ReqData)), rabbit_mgmt_util:reply_list( filter_vhost(status(Chs, ReqData, Context), ReqData), ReqData, Context). is_authorized(ReqData, Context) -> rabbit_mgmt_util:is_authorized_monitor(ReqData, Context). %%-------------------------------------------------------------------- filter_vhost(List, ReqData) -> rabbit_mgmt_util:all_or_one_vhost( ReqData, fun(V) -> lists:filter(fun(I) -> pget(vhost, I) =:= V end, List) end). status(Chs, ReqData, Context) -> rabbit_mgmt_util:filter_vhost( lists:append([status(Node, Chs) || Node <- [node() | nodes()]]), ReqData, Context). status(Node, Chs) -> case rpc:call(Node, rabbit_federation_status, status, [], infinity) of {badrpc, {'EXIT', {undef, _}}} -> []; {badrpc, {'EXIT', {noproc, _}}} -> []; Status -> [format(Node, I, Chs) || I <- Status] end. format(Node, Info0, Chs) -> Info1 = proplists:delete(status, Info0), Info = case pget(status, Info0) of {running, Name} -> [{status, running}, {local_connection, Name} | Info1]; {Status, E} -> Fmted = rabbit_mgmt_format:print("~p", [E]), [{status, Status}, {error, Fmted} | Info1]; S when is_atom(S) -> [{status, S} | Info1] end, LocalCh = case rabbit_mgmt_format:strip_pids( [Ch || Ch <- Chs, pget(name, pget(connection_details, Ch)) =:= pget(local_connection, Info)]) of [Ch] -> [{local_channel, Ch}]; [] -> [] end, [{node, Node} | format_info(Info)] ++ LocalCh. format_info(Items) -> [format_item(I) || I <- Items]. format_item({timestamp, {{Y, M, D}, {H, Min, S}}}) -> {timestamp, print("~w-~2.2.0w-~2.2.0w ~w:~2.2.0w:~2.2.0w", [Y, M, D, H, Min, S])}; format_item(I) -> I. print(Fmt, Val) -> list_to_binary(io_lib:format(Fmt, Val)). ././@LongLink0000000000000000000000000000015400000000000011565 Lustar rootrootrabbitmq-server-3.2.4/plugins-src/rabbitmq-federation-management/src/rabbitmq_federation_management.app.srcrabbitmq-server-3.2.4/plugins-src/rabbitmq-federation-management/src/rabbitmq_federation_management.0000644000000000000000000000034412305126066032611 0ustar rootroot{application, rabbitmq_federation_management, [{description, "RabbitMQ Federation Management"}, {vsn, "%%VSN%%"}, {modules, []}, {registered, []}, {env, []}, {applications, [kernel, stdlib, rabbitmq_management]} ]}. rabbitmq-server-3.2.4/plugins-src/rabbitmq-federation-management/README0000644000000000000000000000047312305126066024507 0ustar rootrootAdds information on federation link status to the management plugin. Build it like any other plugin. If you have a heterogenous cluster (where the nodes have different plugins installed), this should be installed on the same nodes as the management plugin. The HTTP API is very simple: GET /api/federation-links. rabbitmq-server-3.2.4/plugins-src/rabbitmq-federation-management/.srcdist_done0000644000000000000000000000000012305126066026272 0ustar rootrootrabbitmq-server-3.2.4/plugins-src/rabbitmq-federation-management/Makefile0000644000000000000000000000002712305126066025262 0ustar rootrootinclude ../umbrella.mk rabbitmq-server-3.2.4/plugins-src/rabbitmq-federation-management/ebin/0000755000000000000000000000000012305126066024540 5ustar rootrootrabbitmq-server-3.2.4/plugins-src/rabbitmq-federation-management/package.mk0000644000000000000000000000026712305126066025554 0ustar rootrootRELEASABLE:=true DEPS:=rabbitmq-management CONSTRUCT_APP_PREREQS:=$(shell find $(PACKAGE_DIR)/priv -type f) define construct_app_commands cp -r $(PACKAGE_DIR)/priv $(APP_DIR) endef rabbitmq-server-3.2.4/plugins-src/mochiweb-wrapper/0000755000000000000000000000000012305126066021045 5ustar rootrootrabbitmq-server-3.2.4/plugins-src/mochiweb-wrapper/20-MAX_RECV_BODY.patch0000644000000000000000000000064712305126066024375 0ustar rootrootdiff --git a/src/mochiweb_request.erl b/src/mochiweb_request.erl index 5d89662..6765ab0 100644 --- a/src/mochiweb_request.erl +++ b/src/mochiweb_request.erl @@ -42,7 +42,7 @@ -define(IDLE_TIMEOUT, 300000). % Maximum recv_body() length of 1MB --define(MAX_RECV_BODY, (1024*1024)). +-define(MAX_RECV_BODY, 104857600). %% @spec get_header_value(K) -> undefined | Value %% @doc Get the value of a given request header. rabbitmq-server-3.2.4/plugins-src/mochiweb-wrapper/LICENSE-MIT-Mochi0000644000000000000000000000207712305126066023544 0ustar rootrootThis is the MIT license. Copyright (c) 2007 Mochi Media, Inc. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ././@LongLink0000000000000000000000000000014600000000000011566 Lustar rootrootrabbitmq-server-3.2.4/plugins-src/mochiweb-wrapper/40-remove-compiler-syntax_tools-dependencies.patchrabbitmq-server-3.2.4/plugins-src/mochiweb-wrapper/40-remove-compiler-syntax_tools-dependencies.patc0000644000000000000000000000663612305126066032447 0ustar rootrootdiff --git a/src/mochiglobal.erl b/src/mochiglobal.erl deleted file mode 100644 index 6b20e41..0000000 --- a/src/mochiglobal.erl +++ /dev/null @@ -1,107 +0,0 @@ -%% @author Bob Ippolito -%% @copyright 2010 Mochi Media, Inc. -%% @doc Abuse module constant pools as a "read-only shared heap" (since erts 5.6) -%% [1]. --module(mochiglobal). --author("Bob Ippolito "). --export([get/1, get/2, put/2, delete/1]). - -%% -spec get(atom()) -> any() | undefined. -%% @equiv get(K, undefined) -get(K) -> - get(K, undefined). - -%% -spec get(atom(), T) -> any() | T. -%% @doc Get the term for K or return Default. -get(K, Default) -> - get(K, Default, key_to_module(K)). - -get(_K, Default, Mod) -> - try Mod:term() - catch error:undef -> - Default - end. - -%% -spec put(atom(), any()) -> ok. -%% @doc Store term V at K, replaces an existing term if present. -put(K, V) -> - put(K, V, key_to_module(K)). - -put(_K, V, Mod) -> - Bin = compile(Mod, V), - code:purge(Mod), - {module, Mod} = code:load_binary(Mod, atom_to_list(Mod) ++ ".erl", Bin), - ok. - -%% -spec delete(atom()) -> boolean(). -%% @doc Delete term stored at K, no-op if non-existent. -delete(K) -> - delete(K, key_to_module(K)). - -delete(_K, Mod) -> - code:purge(Mod), - code:delete(Mod). - -%% -spec key_to_module(atom()) -> atom(). -key_to_module(K) -> - list_to_atom("mochiglobal:" ++ atom_to_list(K)). - -%% -spec compile(atom(), any()) -> binary(). -compile(Module, T) -> - {ok, Module, Bin} = compile:forms(forms(Module, T), - [verbose, report_errors]), - Bin. - -%% -spec forms(atom(), any()) -> [erl_syntax:syntaxTree()]. -forms(Module, T) -> - [erl_syntax:revert(X) || X <- term_to_abstract(Module, term, T)]. - -%% -spec term_to_abstract(atom(), atom(), any()) -> [erl_syntax:syntaxTree()]. -term_to_abstract(Module, Getter, T) -> - [%% -module(Module). - erl_syntax:attribute( - erl_syntax:atom(module), - [erl_syntax:atom(Module)]), - %% -export([Getter/0]). - erl_syntax:attribute( - erl_syntax:atom(export), - [erl_syntax:list( - [erl_syntax:arity_qualifier( - erl_syntax:atom(Getter), - erl_syntax:integer(0))])]), - %% Getter() -> T. - erl_syntax:function( - erl_syntax:atom(Getter), - [erl_syntax:clause([], none, [erl_syntax:abstract(T)])])]. - -%% -%% Tests -%% --ifdef(TEST). --include_lib("eunit/include/eunit.hrl"). -get_put_delete_test() -> - K = '$$test$$mochiglobal', - delete(K), - ?assertEqual( - bar, - get(K, bar)), - try - ?MODULE:put(K, baz), - ?assertEqual( - baz, - get(K, bar)), - ?MODULE:put(K, wibble), - ?assertEqual( - wibble, - ?MODULE:get(K)) - after - delete(K) - end, - ?assertEqual( - bar, - get(K, bar)), - ?assertEqual( - undefined, - ?MODULE:get(K)), - ok. --endif. diff --git a/src/mochiweb.app.src b/src/mochiweb.app.src index c98d8a0..4a6808e 100644 --- a/src/mochiweb.app.src +++ b/src/mochiweb.app.src @@ -5,5 +5,4 @@ {modules, []}, {registered, []}, {env, []}, - {applications, [kernel, stdlib, inets, xmerl, - compiler, syntax_tools]}]}. + {applications, [kernel, stdlib, inets, xmerl]}]}. rabbitmq-server-3.2.4/plugins-src/mochiweb-wrapper/.srcdist_done0000644000000000000000000000000012305126066023514 0ustar rootrootrabbitmq-server-3.2.4/plugins-src/mochiweb-wrapper/license_info0000644000000000000000000000022112305126066023420 0ustar rootrootMochiweb is "Copyright (c) 2007 Mochi Media, Inc." and is covered by the MIT license. It was downloaded from http://github.com/mochi/mochiweb/ rabbitmq-server-3.2.4/plugins-src/mochiweb-wrapper/hash.mk0000644000000000000000000000003512305126066022317 0ustar rootrootUPSTREAM_SHORT_HASH:=680dba8 rabbitmq-server-3.2.4/plugins-src/mochiweb-wrapper/Makefile0000644000000000000000000000002712305126066022504 0ustar rootrootinclude ../umbrella.mk rabbitmq-server-3.2.4/plugins-src/mochiweb-wrapper/mochiweb-git/0000755000000000000000000000000012305126066023423 5ustar rootrootrabbitmq-server-3.2.4/plugins-src/mochiweb-wrapper/mochiweb-git/scripts/0000755000000000000000000000000012305126066025112 5ustar rootrootrabbitmq-server-3.2.4/plugins-src/mochiweb-wrapper/mochiweb-git/scripts/entities.erl0000755000000000000000000000262112305126066027446 0ustar rootroot#!/usr/bin/env escript %% -*- mode: erlang -*- -export([main/1]). %% @doc Script used to generate mochiweb_charref.erl table. main(_) -> application:start(inets), code:add_patha("ebin"), {ok, {_, _, HTML}} = httpc:request("http://www.w3.org/TR/html5/named-character-references.html"), print(lists:sort(search(mochiweb_html:parse(HTML)))). print([F | T]) -> io:put_chars([clause(F), ";\n"]), print(T); print([]) -> io:put_chars(["entity(_) -> undefined.\n"]), ok. clause({Title, [Codepoint]}) -> ["entity(\"", Title, "\") -> 16#", Codepoint]; clause({Title, [First | Rest]}) -> ["entity(\"", Title, "\") -> [16#", First, [[", 16#", Codepoint] || Codepoint <- Rest], "]"]. search(Elem) -> search(Elem, []). search({<<"tr">>, [{<<"id">>, <<"entity-", _/binary>>} | _], Children}, Acc) -> %% HTML5 charrefs can have more than one code point(!) [{<<"td">>, _, [{<<"code">>, _, [TitleSemi]}]}, {<<"td">>, [], [RawCPs]} | _] = Children, L = byte_size(TitleSemi) - 1, <> = TitleSemi, {match, Matches} = re:run(RawCPs, "(?:\\s*U\\+)([a-fA-F0-9]+)", [{capture, all, binary}, global]), [{Title, [CP || [_, CP] <- Matches]} | Acc]; search({Tag, Attrs, [H | T]}, Acc) -> search({Tag, Attrs, T}, search(H, Acc)); search({_Tag, _Attrs, []}, Acc) -> Acc; search(<<_/binary>>, Acc) -> Acc. rabbitmq-server-3.2.4/plugins-src/mochiweb-wrapper/mochiweb-git/scripts/new_mochiweb.erl0000755000000000000000000000101012305126066030257 0ustar rootroot#!/usr/bin/env escript %% -*- mode: erlang -*- -export([main/1]). %% External API main(_) -> usage(). %% Internal API usage() -> io:format( "new_mochiweb.erl has been replaced by a rebar template!\n" "\n" "To create a new mochiweb using project:\n" " make app PROJECT=project_name\n" "\n" "To create a new mochiweb using project in a specific directory:\n" " make app PROJECT=project_name PREFIX=$HOME/projects/\n" "\n" ), halt(1). rabbitmq-server-3.2.4/plugins-src/mochiweb-wrapper/mochiweb-git/CHANGES.md0000644000000000000000000000651212305126066025021 0ustar rootrootVersion 2.7.0 released XXXX-XX-XX * `mochiweb_socket_server:stop/1` is now a synchronous call instead of an asynchronous cast * `mochiweb_html:parse_tokens/1` (and `parse/1`) will now create a html element to wrap documents that have a HTML5 doctype (``) but no html element https://github.com/mochi/mochiweb/issues/110 Version 2.6.0 released 2013-04-15 * Enable R15B gen_tcp workaround only on R15B https://github.com/mochi/mochiweb/pull/107 Version 2.5.0 released 2013-03-04 * Replace now() with os:timestamp() in acceptor (optimization) https://github.com/mochi/mochiweb/pull/102 * New mochiweb_session module for managing session cookies. NOTE: this module is only supported on R15B02 and later! https://github.com/mochi/mochiweb/pull/94 * New mochiweb_base64url module for base64url encoding (URL and Filename safe alphabet, see RFC 4648). * Fix rebar.config in mochiwebapp_skel to use {branch, "master"} https://github.com/mochi/mochiweb/issues/105 Version 2.4.2 released 2013-02-05 * Fixed issue in mochiweb_response introduced in v2.4.0 https://github.com/mochi/mochiweb/pull/100 Version 2.4.1 released 2013-01-30 * Fixed issue in mochiweb_request introduced in v2.4.0 https://github.com/mochi/mochiweb/issues/97 * Fixed issue in mochifmt_records introduced in v2.4.0 https://github.com/mochi/mochiweb/issues/96 Version 2.4.0 released 2013-01-23 * Switch from parameterized modules to explicit tuple module calls for R16 compatibility (#95) * Fix for mochiweb_acceptor crash with extra-long HTTP headers under R15B02 (#91) * Fix case in handling range headers (#85) * Handle combined Content-Length header (#88) * Windows security fix for `safe_relative_path`, any path with a backslash on any platform is now considered unsafe (#92) Version 2.3.2 released 2012-07-27 * Case insensitive match for "Connection: close" (#81) Version 2.3.1 released 2012-03-31 * Fix edoc warnings (#63) * Fix mochiweb_html handling of invalid charref sequences (unescaped &) (#69). * Add a manual garbage collection between requests to avoid worst case behavior on keep-alive sockets. * Fix dst cookie bug (#73) * Removed unnecessary template_dir option, see https://github.com/basho/rebar/issues/203 Version 2.3.0 released 2011-10-14 * Handle ssl_closed message in mochiweb_http (#59) * Added support for new MIME types (otf, eot, m4v, svg, svgz, ttc, ttf, vcf, webm, webp, woff) (#61) * Updated mochiweb_charref to support all HTML5 entities. Note that if you are using this module directly, the spec has changed to return `[integer()]` for some entities. (#64) Version 2.2.1 released 2011-08-31 * Removed `mochiweb_skel` module from the pre-rebar era Version 2.2.0 released 2011-08-29 * Added new `mochiweb_http:start_link/1` and `mochiweb_socket_server:start_link/1` APIs to explicitly start linked servers. Also added `{link, false}` option to the `start/1` variants to explicitly start unlinked. This is in expectation that we will eventually change the default behavior of `start/1` to be unlinked as you would expect it to. See https://github.com/mochi/mochiweb/issues/58 for discussion. Version 2.1.0 released 2011-08-29 * Added new `mochijson2:decode/2` with `{format, struct | proplist | eep18}` options for easy decoding to various proplist formats. Also added encoding support for eep18 style objects. rabbitmq-server-3.2.4/plugins-src/mochiweb-wrapper/mochiweb-git/src/0000755000000000000000000000000012305126066024212 5ustar rootrootrabbitmq-server-3.2.4/plugins-src/mochiweb-wrapper/mochiweb-git/src/mochiweb_base64url.erl0000644000000000000000000000614712305126066030412 0ustar rootroot-module(mochiweb_base64url). -export([encode/1, decode/1]). %% @doc URL and filename safe base64 variant with no padding, %% also known as "base64url" per RFC 4648. %% %% This differs from base64 in the following ways: %% '-' is used in place of '+' (62), %% '_' is used in place of '/' (63), %% padding is implicit rather than explicit ('='). -spec encode(iolist()) -> binary(). encode(B) when is_binary(B) -> encode_binary(B); encode(L) when is_list(L) -> encode_binary(iolist_to_binary(L)). -spec decode(iolist()) -> binary(). decode(B) when is_binary(B) -> decode_binary(B); decode(L) when is_list(L) -> decode_binary(iolist_to_binary(L)). %% Implementation, derived from stdlib base64.erl %% One-based decode map. -define(DECODE_MAP, {bad,bad,bad,bad,bad,bad,bad,bad,ws,ws,bad,bad,ws,bad,bad, %1-15 bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad, %16-31 ws,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,62,bad,bad, %32-47 52,53,54,55,56,57,58,59,60,61,bad,bad,bad,bad,bad,bad, %48-63 bad,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14, %64-79 15,16,17,18,19,20,21,22,23,24,25,bad,bad,bad,bad,63, %80-95 bad,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40, %96-111 41,42,43,44,45,46,47,48,49,50,51,bad,bad,bad,bad,bad, %112-127 bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad, bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad, bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad, bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad, bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad, bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad, bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad, bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad}). encode_binary(Bin) -> Split = 3*(byte_size(Bin) div 3), <> = Bin, Main = << <<(b64e(C)):8>> || <> <= Main0 >>, case Rest of <> -> <
    >; <> -> <
    >; <<>> -> Main end. decode_binary(Bin) -> Main = << <<(b64d(C)):6>> || <> <= Bin, (C =/= $\t andalso C =/= $\s andalso C =/= $\r andalso C =/= $\n) >>, case bit_size(Main) rem 8 of 0 -> Main; N -> Split = byte_size(Main) - 1, <> = Main, Result end. %% accessors b64e(X) -> element(X+1, {$A, $B, $C, $D, $E, $F, $G, $H, $I, $J, $K, $L, $M, $N, $O, $P, $Q, $R, $S, $T, $U, $V, $W, $X, $Y, $Z, $a, $b, $c, $d, $e, $f, $g, $h, $i, $j, $k, $l, $m, $n, $o, $p, $q, $r, $s, $t, $u, $v, $w, $x, $y, $z, $0, $1, $2, $3, $4, $5, $6, $7, $8, $9, $-, $_}). b64d(X) -> b64d_ok(element(X, ?DECODE_MAP)). b64d_ok(I) when is_integer(I) -> I. rabbitmq-server-3.2.4/plugins-src/mochiweb-wrapper/mochiweb-git/src/mochiweb_acceptor.erl0000644000000000000000000000244012305126066030373 0ustar rootroot%% @author Bob Ippolito %% @copyright 2010 Mochi Media, Inc. %% @doc MochiWeb acceptor. -module(mochiweb_acceptor). -author('bob@mochimedia.com'). -include("internal.hrl"). -export([start_link/3, init/3]). start_link(Server, Listen, Loop) -> proc_lib:spawn_link(?MODULE, init, [Server, Listen, Loop]). init(Server, Listen, Loop) -> T1 = os:timestamp(), case catch mochiweb_socket:accept(Listen) of {ok, Socket} -> gen_server:cast(Server, {accepted, self(), timer:now_diff(os:timestamp(), T1)}), call_loop(Loop, Socket); {error, closed} -> exit(normal); {error, timeout} -> init(Server, Listen, Loop); {error, esslaccept} -> exit(normal); Other -> error_logger:error_report( [{application, mochiweb}, "Accept failed error", lists:flatten(io_lib:format("~p", [Other]))]), exit({error, accept_failed}) end. call_loop({M, F}, Socket) -> M:F(Socket); call_loop({M, F, [A1]}, Socket) -> M:F(Socket, A1); call_loop({M, F, A}, Socket) -> erlang:apply(M, F, [Socket | A]); call_loop(Loop, Socket) -> Loop(Socket). %% %% Tests %% -ifdef(TEST). -include_lib("eunit/include/eunit.hrl"). -endif. rabbitmq-server-3.2.4/plugins-src/mochiweb-wrapper/mochiweb-git/src/mochiweb_multipart.erl0000644000000000000000000010666312305126066030630 0ustar rootroot%% @author Bob Ippolito %% @copyright 2007 Mochi Media, Inc. %% @doc Utilities for parsing multipart/form-data. -module(mochiweb_multipart). -author('bob@mochimedia.com'). -export([parse_form/1, parse_form/2]). -export([parse_multipart_request/2]). -export([parts_to_body/3, parts_to_multipart_body/4]). -export([default_file_handler/2]). -define(CHUNKSIZE, 4096). -record(mp, {state, boundary, length, buffer, callback, req}). %% TODO: DOCUMENT THIS MODULE. %% @type key() = atom() | string() | binary(). %% @type value() = atom() | iolist() | integer(). %% @type header() = {key(), value()}. %% @type bodypart() = {Start::integer(), End::integer(), Body::iolist()}. %% @type formfile() = {Name::string(), ContentType::string(), Content::binary()}. %% @type request(). %% @type file_handler() = (Filename::string(), ContentType::string()) -> file_handler_callback(). %% @type file_handler_callback() = (binary() | eof) -> file_handler_callback() | term(). %% @spec parts_to_body([bodypart()], ContentType::string(), %% Size::integer()) -> {[header()], iolist()} %% @doc Return {[header()], iolist()} representing the body for the given %% parts, may be a single part or multipart. parts_to_body([{Start, End, Body}], ContentType, Size) -> HeaderList = [{"Content-Type", ContentType}, {"Content-Range", ["bytes ", mochiweb_util:make_io(Start), "-", mochiweb_util:make_io(End), "/", mochiweb_util:make_io(Size)]}], {HeaderList, Body}; parts_to_body(BodyList, ContentType, Size) when is_list(BodyList) -> parts_to_multipart_body(BodyList, ContentType, Size, mochihex:to_hex(mochiweb_util:rand_bytes(8))). %% @spec parts_to_multipart_body([bodypart()], ContentType::string(), %% Size::integer(), Boundary::string()) -> %% {[header()], iolist()} %% @doc Return {[header()], iolist()} representing the body for the given %% parts, always a multipart response. parts_to_multipart_body(BodyList, ContentType, Size, Boundary) -> HeaderList = [{"Content-Type", ["multipart/byteranges; ", "boundary=", Boundary]}], MultiPartBody = multipart_body(BodyList, ContentType, Boundary, Size), {HeaderList, MultiPartBody}. %% @spec multipart_body([bodypart()], ContentType::string(), %% Boundary::string(), Size::integer()) -> iolist() %% @doc Return the representation of a multipart body for the given [bodypart()]. multipart_body([], _ContentType, Boundary, _Size) -> ["--", Boundary, "--\r\n"]; multipart_body([{Start, End, Body} | BodyList], ContentType, Boundary, Size) -> ["--", Boundary, "\r\n", "Content-Type: ", ContentType, "\r\n", "Content-Range: ", "bytes ", mochiweb_util:make_io(Start), "-", mochiweb_util:make_io(End), "/", mochiweb_util:make_io(Size), "\r\n\r\n", Body, "\r\n" | multipart_body(BodyList, ContentType, Boundary, Size)]. %% @spec parse_form(request()) -> [{string(), string() | formfile()}] %% @doc Parse a multipart form from the given request using the in-memory %% default_file_handler/2. parse_form(Req) -> parse_form(Req, fun default_file_handler/2). %% @spec parse_form(request(), F::file_handler()) -> [{string(), string() | term()}] %% @doc Parse a multipart form from the given request using the given file_handler(). parse_form(Req, FileHandler) -> Callback = fun (Next) -> parse_form_outer(Next, FileHandler, []) end, {_, _, Res} = parse_multipart_request(Req, Callback), Res. parse_form_outer(eof, _, Acc) -> lists:reverse(Acc); parse_form_outer({headers, H}, FileHandler, State) -> {"form-data", H1} = proplists:get_value("content-disposition", H), Name = proplists:get_value("name", H1), Filename = proplists:get_value("filename", H1), case Filename of undefined -> fun (Next) -> parse_form_value(Next, {Name, []}, FileHandler, State) end; _ -> ContentType = proplists:get_value("content-type", H), Handler = FileHandler(Filename, ContentType), fun (Next) -> parse_form_file(Next, {Name, Handler}, FileHandler, State) end end. parse_form_value(body_end, {Name, Acc}, FileHandler, State) -> Value = binary_to_list(iolist_to_binary(lists:reverse(Acc))), State1 = [{Name, Value} | State], fun (Next) -> parse_form_outer(Next, FileHandler, State1) end; parse_form_value({body, Data}, {Name, Acc}, FileHandler, State) -> Acc1 = [Data | Acc], fun (Next) -> parse_form_value(Next, {Name, Acc1}, FileHandler, State) end. parse_form_file(body_end, {Name, Handler}, FileHandler, State) -> Value = Handler(eof), State1 = [{Name, Value} | State], fun (Next) -> parse_form_outer(Next, FileHandler, State1) end; parse_form_file({body, Data}, {Name, Handler}, FileHandler, State) -> H1 = Handler(Data), fun (Next) -> parse_form_file(Next, {Name, H1}, FileHandler, State) end. default_file_handler(Filename, ContentType) -> default_file_handler_1(Filename, ContentType, []). default_file_handler_1(Filename, ContentType, Acc) -> fun(eof) -> Value = iolist_to_binary(lists:reverse(Acc)), {Filename, ContentType, Value}; (Next) -> default_file_handler_1(Filename, ContentType, [Next | Acc]) end. parse_multipart_request(Req, Callback) -> %% TODO: Support chunked? Length = list_to_integer(Req:get_combined_header_value("content-length")), Boundary = iolist_to_binary( get_boundary(Req:get_header_value("content-type"))), Prefix = <<"\r\n--", Boundary/binary>>, BS = byte_size(Boundary), Chunk = read_chunk(Req, Length), Length1 = Length - byte_size(Chunk), <<"--", Boundary:BS/binary, "\r\n", Rest/binary>> = Chunk, feed_mp(headers, flash_multipart_hack(#mp{boundary=Prefix, length=Length1, buffer=Rest, callback=Callback, req=Req})). parse_headers(<<>>) -> []; parse_headers(Binary) -> parse_headers(Binary, []). parse_headers(Binary, Acc) -> case find_in_binary(<<"\r\n">>, Binary) of {exact, N} -> <> = Binary, parse_headers(Rest, [split_header(Line) | Acc]); not_found -> lists:reverse([split_header(Binary) | Acc]) end. split_header(Line) -> {Name, [$: | Value]} = lists:splitwith(fun (C) -> C =/= $: end, binary_to_list(Line)), {string:to_lower(string:strip(Name)), mochiweb_util:parse_header(Value)}. read_chunk(Req, Length) when Length > 0 -> case Length of Length when Length < ?CHUNKSIZE -> Req:recv(Length); _ -> Req:recv(?CHUNKSIZE) end. read_more(State=#mp{length=Length, buffer=Buffer, req=Req}) -> Data = read_chunk(Req, Length), Buffer1 = <>, flash_multipart_hack(State#mp{length=Length - byte_size(Data), buffer=Buffer1}). flash_multipart_hack(State=#mp{length=0, buffer=Buffer, boundary=Prefix}) -> %% http://code.google.com/p/mochiweb/issues/detail?id=22 %% Flash doesn't terminate multipart with \r\n properly so we fix it up here PrefixSize = size(Prefix), case size(Buffer) - (2 + PrefixSize) of Seek when Seek >= 0 -> case Buffer of <<_:Seek/binary, Prefix:PrefixSize/binary, "--">> -> Buffer1 = <>, State#mp{buffer=Buffer1}; _ -> State end; _ -> State end; flash_multipart_hack(State) -> State. feed_mp(headers, State=#mp{buffer=Buffer, callback=Callback}) -> {State1, P} = case find_in_binary(<<"\r\n\r\n">>, Buffer) of {exact, N} -> {State, N}; _ -> S1 = read_more(State), %% Assume headers must be less than ?CHUNKSIZE {exact, N} = find_in_binary(<<"\r\n\r\n">>, S1#mp.buffer), {S1, N} end, <> = State1#mp.buffer, NextCallback = Callback({headers, parse_headers(Headers)}), feed_mp(body, State1#mp{buffer=Rest, callback=NextCallback}); feed_mp(body, State=#mp{boundary=Prefix, buffer=Buffer, callback=Callback}) -> Boundary = find_boundary(Prefix, Buffer), case Boundary of {end_boundary, Start, Skip} -> <> = Buffer, C1 = Callback({body, Data}), C2 = C1(body_end), {State#mp.length, Rest, C2(eof)}; {next_boundary, Start, Skip} -> <> = Buffer, C1 = Callback({body, Data}), feed_mp(headers, State#mp{callback=C1(body_end), buffer=Rest}); {maybe, Start} -> <> = Buffer, feed_mp(body, read_more(State#mp{callback=Callback({body, Data}), buffer=Rest})); not_found -> {Data, Rest} = {Buffer, <<>>}, feed_mp(body, read_more(State#mp{callback=Callback({body, Data}), buffer=Rest})) end. get_boundary(ContentType) -> {"multipart/form-data", Opts} = mochiweb_util:parse_header(ContentType), case proplists:get_value("boundary", Opts) of S when is_list(S) -> S end. %% @spec find_in_binary(Pattern::binary(), Data::binary()) -> %% {exact, N} | {partial, N, K} | not_found %% @doc Searches for the given pattern in the given binary. find_in_binary(P, Data) when size(P) > 0 -> PS = size(P), DS = size(Data), case DS - PS of Last when Last < 0 -> partial_find(P, Data, 0, DS); Last -> case binary:match(Data, P) of {Pos, _} -> {exact, Pos}; nomatch -> partial_find(P, Data, Last+1, PS-1) end end. partial_find(_B, _D, _N, 0) -> not_found; partial_find(B, D, N, K) -> <> = B, case D of <<_Skip:N/binary, B1:K/binary>> -> {partial, N, K}; _ -> partial_find(B, D, 1 + N, K - 1) end. find_boundary(Prefix, Data) -> case find_in_binary(Prefix, Data) of {exact, Skip} -> PrefixSkip = Skip + size(Prefix), case Data of <<_:PrefixSkip/binary, "\r\n", _/binary>> -> {next_boundary, Skip, size(Prefix) + 2}; <<_:PrefixSkip/binary, "--\r\n", _/binary>> -> {end_boundary, Skip, size(Prefix) + 4}; _ when size(Data) < PrefixSkip + 4 -> %% Underflow {maybe, Skip}; _ -> %% False positive not_found end; {partial, Skip, Length} when (Skip + Length) =:= size(Data) -> %% Underflow {maybe, Skip}; _ -> not_found end. %% %% Tests %% -ifdef(TEST). -include_lib("eunit/include/eunit.hrl"). ssl_cert_opts() -> EbinDir = filename:dirname(code:which(?MODULE)), CertDir = filename:join([EbinDir, "..", "support", "test-materials"]), CertFile = filename:join(CertDir, "test_ssl_cert.pem"), KeyFile = filename:join(CertDir, "test_ssl_key.pem"), [{certfile, CertFile}, {keyfile, KeyFile}]. with_socket_server(Transport, ServerFun, ClientFun) -> ServerOpts0 = [{ip, "127.0.0.1"}, {port, 0}, {loop, ServerFun}], ServerOpts = case Transport of plain -> ServerOpts0; ssl -> ServerOpts0 ++ [{ssl, true}, {ssl_opts, ssl_cert_opts()}] end, {ok, Server} = mochiweb_socket_server:start_link(ServerOpts), Port = mochiweb_socket_server:get(Server, port), ClientOpts = [binary, {active, false}], {ok, Client} = case Transport of plain -> gen_tcp:connect("127.0.0.1", Port, ClientOpts); ssl -> ClientOpts1 = [{ssl_imp, new} | ClientOpts], {ok, SslSocket} = ssl:connect("127.0.0.1", Port, ClientOpts1), {ok, {ssl, SslSocket}} end, Res = (catch ClientFun(Client)), mochiweb_socket_server:stop(Server), Res. fake_request(Socket, ContentType, Length) -> mochiweb_request:new(Socket, 'POST', "/multipart", {1,1}, mochiweb_headers:make( [{"content-type", ContentType}, {"content-length", Length}])). test_callback({body, <<>>}, Rest=[body_end | _]) -> %% When expecting the body_end we might get an empty binary fun (Next) -> test_callback(Next, Rest) end; test_callback({body, Got}, [{body, Expect} | Rest]) when Got =/= Expect -> %% Partial response GotSize = size(Got), <> = Expect, fun (Next) -> test_callback(Next, [{body, Expect1} | Rest]) end; test_callback(Got, [Expect | Rest]) -> ?assertEqual(Got, Expect), case Rest of [] -> ok; _ -> fun (Next) -> test_callback(Next, Rest) end end. parse3_http_test() -> parse3(plain). parse3_https_test() -> parse3(ssl). parse3(Transport) -> ContentType = "multipart/form-data; boundary=---------------------------7386909285754635891697677882", BinContent = <<"-----------------------------7386909285754635891697677882\r\nContent-Disposition: form-data; name=\"hidden\"\r\n\r\nmultipart message\r\n-----------------------------7386909285754635891697677882\r\nContent-Disposition: form-data; name=\"file\"; filename=\"test_file.txt\"\r\nContent-Type: text/plain\r\n\r\nWoo multiline text file\n\nLa la la\r\n-----------------------------7386909285754635891697677882--\r\n">>, Expect = [{headers, [{"content-disposition", {"form-data", [{"name", "hidden"}]}}]}, {body, <<"multipart message">>}, body_end, {headers, [{"content-disposition", {"form-data", [{"name", "file"}, {"filename", "test_file.txt"}]}}, {"content-type", {"text/plain", []}}]}, {body, <<"Woo multiline text file\n\nLa la la">>}, body_end, eof], TestCallback = fun (Next) -> test_callback(Next, Expect) end, ServerFun = fun (Socket) -> ok = mochiweb_socket:send(Socket, BinContent), exit(normal) end, ClientFun = fun (Socket) -> Req = fake_request(Socket, ContentType, byte_size(BinContent)), Res = parse_multipart_request(Req, TestCallback), {0, <<>>, ok} = Res, ok end, ok = with_socket_server(Transport, ServerFun, ClientFun), ok. parse2_http_test() -> parse2(plain). parse2_https_test() -> parse2(ssl). parse2(Transport) -> ContentType = "multipart/form-data; boundary=---------------------------6072231407570234361599764024", BinContent = <<"-----------------------------6072231407570234361599764024\r\nContent-Disposition: form-data; name=\"hidden\"\r\n\r\nmultipart message\r\n-----------------------------6072231407570234361599764024\r\nContent-Disposition: form-data; name=\"file\"; filename=\"\"\r\nContent-Type: application/octet-stream\r\n\r\n\r\n-----------------------------6072231407570234361599764024--\r\n">>, Expect = [{headers, [{"content-disposition", {"form-data", [{"name", "hidden"}]}}]}, {body, <<"multipart message">>}, body_end, {headers, [{"content-disposition", {"form-data", [{"name", "file"}, {"filename", ""}]}}, {"content-type", {"application/octet-stream", []}}]}, {body, <<>>}, body_end, eof], TestCallback = fun (Next) -> test_callback(Next, Expect) end, ServerFun = fun (Socket) -> ok = mochiweb_socket:send(Socket, BinContent), exit(normal) end, ClientFun = fun (Socket) -> Req = fake_request(Socket, ContentType, byte_size(BinContent)), Res = parse_multipart_request(Req, TestCallback), {0, <<>>, ok} = Res, ok end, ok = with_socket_server(Transport, ServerFun, ClientFun), ok. parse_form_http_test() -> do_parse_form(plain). parse_form_https_test() -> do_parse_form(ssl). do_parse_form(Transport) -> ContentType = "multipart/form-data; boundary=AaB03x", "AaB03x" = get_boundary(ContentType), Content = mochiweb_util:join( ["--AaB03x", "Content-Disposition: form-data; name=\"submit-name\"", "", "Larry", "--AaB03x", "Content-Disposition: form-data; name=\"files\";" ++ "filename=\"file1.txt\"", "Content-Type: text/plain", "", "... contents of file1.txt ...", "--AaB03x--", ""], "\r\n"), BinContent = iolist_to_binary(Content), ServerFun = fun (Socket) -> ok = mochiweb_socket:send(Socket, BinContent), exit(normal) end, ClientFun = fun (Socket) -> Req = fake_request(Socket, ContentType, byte_size(BinContent)), Res = parse_form(Req), [{"submit-name", "Larry"}, {"files", {"file1.txt", {"text/plain",[]}, <<"... contents of file1.txt ...">>} }] = Res, ok end, ok = with_socket_server(Transport, ServerFun, ClientFun), ok. parse_http_test() -> do_parse(plain). parse_https_test() -> do_parse(ssl). do_parse(Transport) -> ContentType = "multipart/form-data; boundary=AaB03x", "AaB03x" = get_boundary(ContentType), Content = mochiweb_util:join( ["--AaB03x", "Content-Disposition: form-data; name=\"submit-name\"", "", "Larry", "--AaB03x", "Content-Disposition: form-data; name=\"files\";" ++ "filename=\"file1.txt\"", "Content-Type: text/plain", "", "... contents of file1.txt ...", "--AaB03x--", ""], "\r\n"), BinContent = iolist_to_binary(Content), Expect = [{headers, [{"content-disposition", {"form-data", [{"name", "submit-name"}]}}]}, {body, <<"Larry">>}, body_end, {headers, [{"content-disposition", {"form-data", [{"name", "files"}, {"filename", "file1.txt"}]}}, {"content-type", {"text/plain", []}}]}, {body, <<"... contents of file1.txt ...">>}, body_end, eof], TestCallback = fun (Next) -> test_callback(Next, Expect) end, ServerFun = fun (Socket) -> ok = mochiweb_socket:send(Socket, BinContent), exit(normal) end, ClientFun = fun (Socket) -> Req = fake_request(Socket, ContentType, byte_size(BinContent)), Res = parse_multipart_request(Req, TestCallback), {0, <<>>, ok} = Res, ok end, ok = with_socket_server(Transport, ServerFun, ClientFun), ok. parse_partial_body_boundary_http_test() -> parse_partial_body_boundary(plain). parse_partial_body_boundary_https_test() -> parse_partial_body_boundary(ssl). parse_partial_body_boundary(Transport) -> Boundary = string:copies("$", 2048), ContentType = "multipart/form-data; boundary=" ++ Boundary, ?assertEqual(Boundary, get_boundary(ContentType)), Content = mochiweb_util:join( ["--" ++ Boundary, "Content-Disposition: form-data; name=\"submit-name\"", "", "Larry", "--" ++ Boundary, "Content-Disposition: form-data; name=\"files\";" ++ "filename=\"file1.txt\"", "Content-Type: text/plain", "", "... contents of file1.txt ...", "--" ++ Boundary ++ "--", ""], "\r\n"), BinContent = iolist_to_binary(Content), Expect = [{headers, [{"content-disposition", {"form-data", [{"name", "submit-name"}]}}]}, {body, <<"Larry">>}, body_end, {headers, [{"content-disposition", {"form-data", [{"name", "files"}, {"filename", "file1.txt"}]}}, {"content-type", {"text/plain", []}} ]}, {body, <<"... contents of file1.txt ...">>}, body_end, eof], TestCallback = fun (Next) -> test_callback(Next, Expect) end, ServerFun = fun (Socket) -> ok = mochiweb_socket:send(Socket, BinContent), exit(normal) end, ClientFun = fun (Socket) -> Req = fake_request(Socket, ContentType, byte_size(BinContent)), Res = parse_multipart_request(Req, TestCallback), {0, <<>>, ok} = Res, ok end, ok = with_socket_server(Transport, ServerFun, ClientFun), ok. parse_large_header_http_test() -> parse_large_header(plain). parse_large_header_https_test() -> parse_large_header(ssl). parse_large_header(Transport) -> ContentType = "multipart/form-data; boundary=AaB03x", "AaB03x" = get_boundary(ContentType), Content = mochiweb_util:join( ["--AaB03x", "Content-Disposition: form-data; name=\"submit-name\"", "", "Larry", "--AaB03x", "Content-Disposition: form-data; name=\"files\";" ++ "filename=\"file1.txt\"", "Content-Type: text/plain", "x-large-header: " ++ string:copies("%", 4096), "", "... contents of file1.txt ...", "--AaB03x--", ""], "\r\n"), BinContent = iolist_to_binary(Content), Expect = [{headers, [{"content-disposition", {"form-data", [{"name", "submit-name"}]}}]}, {body, <<"Larry">>}, body_end, {headers, [{"content-disposition", {"form-data", [{"name", "files"}, {"filename", "file1.txt"}]}}, {"content-type", {"text/plain", []}}, {"x-large-header", {string:copies("%", 4096), []}} ]}, {body, <<"... contents of file1.txt ...">>}, body_end, eof], TestCallback = fun (Next) -> test_callback(Next, Expect) end, ServerFun = fun (Socket) -> ok = mochiweb_socket:send(Socket, BinContent), exit(normal) end, ClientFun = fun (Socket) -> Req = fake_request(Socket, ContentType, byte_size(BinContent)), Res = parse_multipart_request(Req, TestCallback), {0, <<>>, ok} = Res, ok end, ok = with_socket_server(Transport, ServerFun, ClientFun), ok. find_boundary_test() -> B = <<"\r\n--X">>, {next_boundary, 0, 7} = find_boundary(B, <<"\r\n--X\r\nRest">>), {next_boundary, 1, 7} = find_boundary(B, <<"!\r\n--X\r\nRest">>), {end_boundary, 0, 9} = find_boundary(B, <<"\r\n--X--\r\nRest">>), {end_boundary, 1, 9} = find_boundary(B, <<"!\r\n--X--\r\nRest">>), not_found = find_boundary(B, <<"--X\r\nRest">>), {maybe, 0} = find_boundary(B, <<"\r\n--X\r">>), {maybe, 1} = find_boundary(B, <<"!\r\n--X\r">>), P = <<"\r\n-----------------------------16037454351082272548568224146">>, B0 = <<55,212,131,77,206,23,216,198,35,87,252,118,252,8,25,211,132,229, 182,42,29,188,62,175,247,243,4,4,0,59, 13,10,45,45,45,45,45,45,45, 45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45, 49,54,48,51,55,52,53,52,51,53,49>>, {maybe, 30} = find_boundary(P, B0), not_found = find_boundary(B, <<"\r\n--XJOPKE">>), ok. find_in_binary_test() -> {exact, 0} = find_in_binary(<<"foo">>, <<"foobarbaz">>), {exact, 1} = find_in_binary(<<"oo">>, <<"foobarbaz">>), {exact, 8} = find_in_binary(<<"z">>, <<"foobarbaz">>), not_found = find_in_binary(<<"q">>, <<"foobarbaz">>), {partial, 7, 2} = find_in_binary(<<"azul">>, <<"foobarbaz">>), {exact, 0} = find_in_binary(<<"foobarbaz">>, <<"foobarbaz">>), {partial, 0, 3} = find_in_binary(<<"foobar">>, <<"foo">>), {partial, 1, 3} = find_in_binary(<<"foobar">>, <<"afoo">>), ok. flash_parse_http_test() -> flash_parse(plain). flash_parse_https_test() -> flash_parse(ssl). flash_parse(Transport) -> ContentType = "multipart/form-data; boundary=----------ei4GI3GI3Ij5Ef1ae0KM7Ij5ei4Ij5", "----------ei4GI3GI3Ij5Ef1ae0KM7Ij5ei4Ij5" = get_boundary(ContentType), BinContent = <<"------------ei4GI3GI3Ij5Ef1ae0KM7Ij5ei4Ij5\r\nContent-Disposition: form-data; name=\"Filename\"\r\n\r\nhello.txt\r\n------------ei4GI3GI3Ij5Ef1ae0KM7Ij5ei4Ij5\r\nContent-Disposition: form-data; name=\"success_action_status\"\r\n\r\n201\r\n------------ei4GI3GI3Ij5Ef1ae0KM7Ij5ei4Ij5\r\nContent-Disposition: form-data; name=\"file\"; filename=\"hello.txt\"\r\nContent-Type: application/octet-stream\r\n\r\nhello\n\r\n------------ei4GI3GI3Ij5Ef1ae0KM7Ij5ei4Ij5\r\nContent-Disposition: form-data; name=\"Upload\"\r\n\r\nSubmit Query\r\n------------ei4GI3GI3Ij5Ef1ae0KM7Ij5ei4Ij5--">>, Expect = [{headers, [{"content-disposition", {"form-data", [{"name", "Filename"}]}}]}, {body, <<"hello.txt">>}, body_end, {headers, [{"content-disposition", {"form-data", [{"name", "success_action_status"}]}}]}, {body, <<"201">>}, body_end, {headers, [{"content-disposition", {"form-data", [{"name", "file"}, {"filename", "hello.txt"}]}}, {"content-type", {"application/octet-stream", []}}]}, {body, <<"hello\n">>}, body_end, {headers, [{"content-disposition", {"form-data", [{"name", "Upload"}]}}]}, {body, <<"Submit Query">>}, body_end, eof], TestCallback = fun (Next) -> test_callback(Next, Expect) end, ServerFun = fun (Socket) -> ok = mochiweb_socket:send(Socket, BinContent), exit(normal) end, ClientFun = fun (Socket) -> Req = fake_request(Socket, ContentType, byte_size(BinContent)), Res = parse_multipart_request(Req, TestCallback), {0, <<>>, ok} = Res, ok end, ok = with_socket_server(Transport, ServerFun, ClientFun), ok. flash_parse2_http_test() -> flash_parse2(plain). flash_parse2_https_test() -> flash_parse2(ssl). flash_parse2(Transport) -> ContentType = "multipart/form-data; boundary=----------ei4GI3GI3Ij5Ef1ae0KM7Ij5ei4Ij5", "----------ei4GI3GI3Ij5Ef1ae0KM7Ij5ei4Ij5" = get_boundary(ContentType), Chunk = iolist_to_binary(string:copies("%", 4096)), BinContent = <<"------------ei4GI3GI3Ij5Ef1ae0KM7Ij5ei4Ij5\r\nContent-Disposition: form-data; name=\"Filename\"\r\n\r\nhello.txt\r\n------------ei4GI3GI3Ij5Ef1ae0KM7Ij5ei4Ij5\r\nContent-Disposition: form-data; name=\"success_action_status\"\r\n\r\n201\r\n------------ei4GI3GI3Ij5Ef1ae0KM7Ij5ei4Ij5\r\nContent-Disposition: form-data; name=\"file\"; filename=\"hello.txt\"\r\nContent-Type: application/octet-stream\r\n\r\n", Chunk/binary, "\r\n------------ei4GI3GI3Ij5Ef1ae0KM7Ij5ei4Ij5\r\nContent-Disposition: form-data; name=\"Upload\"\r\n\r\nSubmit Query\r\n------------ei4GI3GI3Ij5Ef1ae0KM7Ij5ei4Ij5--">>, Expect = [{headers, [{"content-disposition", {"form-data", [{"name", "Filename"}]}}]}, {body, <<"hello.txt">>}, body_end, {headers, [{"content-disposition", {"form-data", [{"name", "success_action_status"}]}}]}, {body, <<"201">>}, body_end, {headers, [{"content-disposition", {"form-data", [{"name", "file"}, {"filename", "hello.txt"}]}}, {"content-type", {"application/octet-stream", []}}]}, {body, Chunk}, body_end, {headers, [{"content-disposition", {"form-data", [{"name", "Upload"}]}}]}, {body, <<"Submit Query">>}, body_end, eof], TestCallback = fun (Next) -> test_callback(Next, Expect) end, ServerFun = fun (Socket) -> ok = mochiweb_socket:send(Socket, BinContent), exit(normal) end, ClientFun = fun (Socket) -> Req = fake_request(Socket, ContentType, byte_size(BinContent)), Res = parse_multipart_request(Req, TestCallback), {0, <<>>, ok} = Res, ok end, ok = with_socket_server(Transport, ServerFun, ClientFun), ok. parse_headers_test() -> ?assertEqual([], parse_headers(<<>>)). flash_multipart_hack_test() -> Buffer = <<"prefix-">>, Prefix = <<"prefix">>, State = #mp{length=0, buffer=Buffer, boundary=Prefix}, ?assertEqual(State, flash_multipart_hack(State)). parts_to_body_single_test() -> {HL, B} = parts_to_body([{0, 5, <<"01234">>}], "text/plain", 10), [{"Content-Range", Range}, {"Content-Type", Type}] = lists:sort(HL), ?assertEqual( <<"bytes 0-5/10">>, iolist_to_binary(Range)), ?assertEqual( <<"text/plain">>, iolist_to_binary(Type)), ?assertEqual( <<"01234">>, iolist_to_binary(B)), ok. parts_to_body_multi_test() -> {[{"Content-Type", Type}], _B} = parts_to_body([{0, 5, <<"01234">>}, {5, 10, <<"56789">>}], "text/plain", 10), ?assertMatch( <<"multipart/byteranges; boundary=", _/binary>>, iolist_to_binary(Type)), ok. parts_to_multipart_body_test() -> {[{"Content-Type", V}], B} = parts_to_multipart_body( [{0, 5, <<"01234">>}, {5, 10, <<"56789">>}], "text/plain", 10, "BOUNDARY"), MB = multipart_body( [{0, 5, <<"01234">>}, {5, 10, <<"56789">>}], "text/plain", "BOUNDARY", 10), ?assertEqual( <<"multipart/byteranges; boundary=BOUNDARY">>, iolist_to_binary(V)), ?assertEqual( iolist_to_binary(MB), iolist_to_binary(B)), ok. multipart_body_test() -> ?assertEqual( <<"--BOUNDARY--\r\n">>, iolist_to_binary(multipart_body([], "text/plain", "BOUNDARY", 0))), ?assertEqual( <<"--BOUNDARY\r\n" "Content-Type: text/plain\r\n" "Content-Range: bytes 0-5/10\r\n\r\n" "01234\r\n" "--BOUNDARY\r\n" "Content-Type: text/plain\r\n" "Content-Range: bytes 5-10/10\r\n\r\n" "56789\r\n" "--BOUNDARY--\r\n">>, iolist_to_binary(multipart_body([{0, 5, <<"01234">>}, {5, 10, <<"56789">>}], "text/plain", "BOUNDARY", 10))), ok. %% @todo Move somewhere more appropriate than in the test suite multipart_parsing_benchmark_test() -> run_multipart_parsing_benchmark(1). run_multipart_parsing_benchmark(0) -> ok; run_multipart_parsing_benchmark(N) -> multipart_parsing_benchmark(), run_multipart_parsing_benchmark(N-1). multipart_parsing_benchmark() -> ContentType = "multipart/form-data; boundary=----------ei4GI3GI3Ij5Ef1ae0KM7Ij5ei4Ij5", Chunk = binary:copy(<<"This Is_%Some=Quite0Long4String2Used9For7BenchmarKing.5">>, 102400), BinContent = <<"------------ei4GI3GI3Ij5Ef1ae0KM7Ij5ei4Ij5\r\nContent-Disposition: form-data; name=\"Filename\"\r\n\r\nhello.txt\r\n------------ei4GI3GI3Ij5Ef1ae0KM7Ij5ei4Ij5\r\nContent-Disposition: form-data; name=\"success_action_status\"\r\n\r\n201\r\n------------ei4GI3GI3Ij5Ef1ae0KM7Ij5ei4Ij5\r\nContent-Disposition: form-data; name=\"file\"; filename=\"hello.txt\"\r\nContent-Type: application/octet-stream\r\n\r\n", Chunk/binary, "\r\n------------ei4GI3GI3Ij5Ef1ae0KM7Ij5ei4Ij5\r\nContent-Disposition: form-data; name=\"Upload\"\r\n\r\nSubmit Query\r\n------------ei4GI3GI3Ij5Ef1ae0KM7Ij5ei4Ij5--">>, Expect = [{headers, [{"content-disposition", {"form-data", [{"name", "Filename"}]}}]}, {body, <<"hello.txt">>}, body_end, {headers, [{"content-disposition", {"form-data", [{"name", "success_action_status"}]}}]}, {body, <<"201">>}, body_end, {headers, [{"content-disposition", {"form-data", [{"name", "file"}, {"filename", "hello.txt"}]}}, {"content-type", {"application/octet-stream", []}}]}, {body, Chunk}, body_end, {headers, [{"content-disposition", {"form-data", [{"name", "Upload"}]}}]}, {body, <<"Submit Query">>}, body_end, eof], TestCallback = fun (Next) -> test_callback(Next, Expect) end, ServerFun = fun (Socket) -> ok = mochiweb_socket:send(Socket, BinContent), exit(normal) end, ClientFun = fun (Socket) -> Req = fake_request(Socket, ContentType, byte_size(BinContent)), Res = parse_multipart_request(Req, TestCallback), {0, <<>>, ok} = Res, ok end, ok = with_socket_server(plain, ServerFun, ClientFun), ok. -endif. rabbitmq-server-3.2.4/plugins-src/mochiweb-wrapper/mochiweb-git/src/mochiweb.app.src0000644000000000000000000000035112305126066027276 0ustar rootroot%% This is generated from src/mochiweb.app.src {application, mochiweb, [{description, "MochiMedia Web Server"}, {vsn, "2.7.0"}, {modules, []}, {registered, []}, {env, []}, {applications, [kernel, stdlib, inets, xmerl]}]}. rabbitmq-server-3.2.4/plugins-src/mochiweb-wrapper/mochiweb-git/src/mochiweb.erl0000644000000000000000000000473512305126066026524 0ustar rootroot%% @author Bob Ippolito %% @copyright 2007 Mochi Media, Inc. %% @doc Start and stop the MochiWeb server. -module(mochiweb). -author('bob@mochimedia.com'). -export([new_request/1, new_response/1]). -export([all_loaded/0, all_loaded/1, reload/0]). -export([ensure_started/1]). reload() -> [c:l(Module) || Module <- all_loaded()]. all_loaded() -> all_loaded(filename:dirname(code:which(?MODULE))). all_loaded(Base) when is_atom(Base) -> []; all_loaded(Base) -> FullBase = Base ++ "/", F = fun ({_Module, Loaded}, Acc) when is_atom(Loaded) -> Acc; ({Module, Loaded}, Acc) -> case lists:prefix(FullBase, Loaded) of true -> [Module | Acc]; false -> Acc end end, lists:foldl(F, [], code:all_loaded()). %% @spec new_request({Socket, Request, Headers}) -> MochiWebRequest %% @doc Return a mochiweb_request data structure. new_request({Socket, {Method, {abs_path, Uri}, Version}, Headers}) -> mochiweb_request:new(Socket, Method, Uri, Version, mochiweb_headers:make(Headers)); % this case probably doesn't "exist". new_request({Socket, {Method, {absoluteURI, _Protocol, _Host, _Port, Uri}, Version}, Headers}) -> mochiweb_request:new(Socket, Method, Uri, Version, mochiweb_headers:make(Headers)); %% Request-URI is "*" %% From http://www.w3.org/Protocols/rfc2616/rfc2616-sec5.html#sec5.1.2 new_request({Socket, {Method, '*'=Uri, Version}, Headers}) -> mochiweb_request:new(Socket, Method, Uri, Version, mochiweb_headers:make(Headers)). %% @spec new_response({Request, integer(), Headers}) -> MochiWebResponse %% @doc Return a mochiweb_response data structure. new_response({Request, Code, Headers}) -> mochiweb_response:new(Request, Code, mochiweb_headers:make(Headers)). %% @spec ensure_started(App::atom()) -> ok %% @doc Start the given App if it has not been started already. ensure_started(App) -> case application:start(App) of ok -> ok; {error, {already_started, App}} -> ok end. rabbitmq-server-3.2.4/plugins-src/mochiweb-wrapper/mochiweb-git/src/mochilogfile2.erl0000644000000000000000000000732712305126066027452 0ustar rootroot%% @author Bob Ippolito %% @copyright 2010 Mochi Media, Inc. %% @doc Write newline delimited log files, ensuring that if a truncated %% entry is found on log open then it is fixed before writing. Uses %% delayed writes and raw files for performance. -module(mochilogfile2). -author('bob@mochimedia.com'). -export([open/1, write/2, close/1, name/1]). %% @spec open(Name) -> Handle %% @doc Open the log file Name, creating or appending as necessary. All data %% at the end of the file will be truncated until a newline is found, to %% ensure that all records are complete. open(Name) -> {ok, FD} = file:open(Name, [raw, read, write, delayed_write, binary]), fix_log(FD), {?MODULE, Name, FD}. %% @spec name(Handle) -> string() %% @doc Return the path of the log file. name({?MODULE, Name, _FD}) -> Name. %% @spec write(Handle, IoData) -> ok %% @doc Write IoData to the log file referenced by Handle. write({?MODULE, _Name, FD}, IoData) -> ok = file:write(FD, [IoData, $\n]), ok. %% @spec close(Handle) -> ok %% @doc Close the log file referenced by Handle. close({?MODULE, _Name, FD}) -> ok = file:sync(FD), ok = file:close(FD), ok. fix_log(FD) -> {ok, Location} = file:position(FD, eof), Seek = find_last_newline(FD, Location), {ok, Seek} = file:position(FD, Seek), ok = file:truncate(FD), ok. %% Seek backwards to the last valid log entry find_last_newline(_FD, N) when N =< 1 -> 0; find_last_newline(FD, Location) -> case file:pread(FD, Location - 1, 1) of {ok, <<$\n>>} -> Location; {ok, _} -> find_last_newline(FD, Location - 1) end. %% %% Tests %% -ifdef(TEST). -include_lib("eunit/include/eunit.hrl"). name_test() -> D = mochitemp:mkdtemp(), FileName = filename:join(D, "open_close_test.log"), H = open(FileName), ?assertEqual( FileName, name(H)), close(H), file:delete(FileName), file:del_dir(D), ok. open_close_test() -> D = mochitemp:mkdtemp(), FileName = filename:join(D, "open_close_test.log"), OpenClose = fun () -> H = open(FileName), ?assertEqual( true, filelib:is_file(FileName)), ok = close(H), ?assertEqual( {ok, <<>>}, file:read_file(FileName)), ok end, OpenClose(), OpenClose(), file:delete(FileName), file:del_dir(D), ok. write_test() -> D = mochitemp:mkdtemp(), FileName = filename:join(D, "write_test.log"), F = fun () -> H = open(FileName), write(H, "test line"), close(H), ok end, F(), ?assertEqual( {ok, <<"test line\n">>}, file:read_file(FileName)), F(), ?assertEqual( {ok, <<"test line\ntest line\n">>}, file:read_file(FileName)), file:delete(FileName), file:del_dir(D), ok. fix_log_test() -> D = mochitemp:mkdtemp(), FileName = filename:join(D, "write_test.log"), file:write_file(FileName, <<"first line good\nsecond line bad">>), F = fun () -> H = open(FileName), write(H, "test line"), close(H), ok end, F(), ?assertEqual( {ok, <<"first line good\ntest line\n">>}, file:read_file(FileName)), file:write_file(FileName, <<"first line bad">>), F(), ?assertEqual( {ok, <<"test line\n">>}, file:read_file(FileName)), F(), ?assertEqual( {ok, <<"test line\ntest line\n">>}, file:read_file(FileName)), ok. -endif. rabbitmq-server-3.2.4/plugins-src/mochiweb-wrapper/mochiweb-git/src/mochiweb_request_tests.erl0000644000000000000000000001761512305126066031517 0ustar rootroot-module(mochiweb_request_tests). -ifdef(TEST). -include_lib("eunit/include/eunit.hrl"). accepts_content_type_test() -> Req1 = mochiweb_request:new(nil, 'GET', "/foo", {1, 1}, mochiweb_headers:make([{"Accept", "multipart/related"}])), ?assertEqual(true, Req1:accepts_content_type("multipart/related")), ?assertEqual(true, Req1:accepts_content_type(<<"multipart/related">>)), Req2 = mochiweb_request:new(nil, 'GET', "/foo", {1, 1}, mochiweb_headers:make([{"Accept", "text/html"}])), ?assertEqual(false, Req2:accepts_content_type("multipart/related")), Req3 = mochiweb_request:new(nil, 'GET', "/foo", {1, 1}, mochiweb_headers:make([{"Accept", "text/html, multipart/*"}])), ?assertEqual(true, Req3:accepts_content_type("multipart/related")), Req4 = mochiweb_request:new(nil, 'GET', "/foo", {1, 1}, mochiweb_headers:make([{"Accept", "text/html, multipart/*; q=0.0"}])), ?assertEqual(false, Req4:accepts_content_type("multipart/related")), Req5 = mochiweb_request:new(nil, 'GET', "/foo", {1, 1}, mochiweb_headers:make([{"Accept", "text/html, multipart/*; q=0"}])), ?assertEqual(false, Req5:accepts_content_type("multipart/related")), Req6 = mochiweb_request:new(nil, 'GET', "/foo", {1, 1}, mochiweb_headers:make([{"Accept", "text/html, */*; q=0.0"}])), ?assertEqual(false, Req6:accepts_content_type("multipart/related")), Req7 = mochiweb_request:new(nil, 'GET', "/foo", {1, 1}, mochiweb_headers:make([{"Accept", "multipart/*; q=0.0, */*"}])), ?assertEqual(false, Req7:accepts_content_type("multipart/related")), Req8 = mochiweb_request:new(nil, 'GET', "/foo", {1, 1}, mochiweb_headers:make([{"Accept", "*/*; q=0.0, multipart/*"}])), ?assertEqual(true, Req8:accepts_content_type("multipart/related")), Req9 = mochiweb_request:new(nil, 'GET', "/foo", {1, 1}, mochiweb_headers:make([{"Accept", "*/*; q=0.0, multipart/related"}])), ?assertEqual(true, Req9:accepts_content_type("multipart/related")), Req10 = mochiweb_request:new(nil, 'GET', "/foo", {1, 1}, mochiweb_headers:make([{"Accept", "text/html; level=1"}])), ?assertEqual(true, Req10:accepts_content_type("text/html;level=1")), Req11 = mochiweb_request:new(nil, 'GET', "/foo", {1, 1}, mochiweb_headers:make([{"Accept", "text/html; level=1, text/html"}])), ?assertEqual(true, Req11:accepts_content_type("text/html")), Req12 = mochiweb_request:new(nil, 'GET', "/foo", {1, 1}, mochiweb_headers:make([{"Accept", "text/html; level=1; q=0.0, text/html"}])), ?assertEqual(false, Req12:accepts_content_type("text/html;level=1")), Req13 = mochiweb_request:new(nil, 'GET', "/foo", {1, 1}, mochiweb_headers:make([{"Accept", "text/html; level=1; q=0.0, text/html"}])), ?assertEqual(false, Req13:accepts_content_type("text/html; level=1")), Req14 = mochiweb_request:new(nil, 'GET', "/foo", {1, 1}, mochiweb_headers:make([{"Accept", "text/html;level=1;q=0.1, text/html"}])), ?assertEqual(true, Req14:accepts_content_type("text/html; level=1")). accepted_encodings_test() -> Req1 = mochiweb_request:new(nil, 'GET', "/foo", {1, 1}, mochiweb_headers:make([])), ?assertEqual(["identity"], Req1:accepted_encodings(["gzip", "identity"])), Req2 = mochiweb_request:new(nil, 'GET', "/foo", {1, 1}, mochiweb_headers:make([{"Accept-Encoding", "gzip, deflate"}])), ?assertEqual(["gzip", "identity"], Req2:accepted_encodings(["gzip", "identity"])), Req3 = mochiweb_request:new(nil, 'GET', "/foo", {1, 1}, mochiweb_headers:make([{"Accept-Encoding", "gzip;q=0.5, deflate"}])), ?assertEqual(["deflate", "gzip", "identity"], Req3:accepted_encodings(["gzip", "deflate", "identity"])), Req4 = mochiweb_request:new(nil, 'GET', "/foo", {1, 1}, mochiweb_headers:make([{"Accept-Encoding", "identity, *;q=0"}])), ?assertEqual(["identity"], Req4:accepted_encodings(["gzip", "deflate", "identity"])), Req5 = mochiweb_request:new(nil, 'GET', "/foo", {1, 1}, mochiweb_headers:make([{"Accept-Encoding", "gzip; q=0.1, *;q=0"}])), ?assertEqual(["gzip"], Req5:accepted_encodings(["gzip", "deflate", "identity"])), Req6 = mochiweb_request:new(nil, 'GET', "/foo", {1, 1}, mochiweb_headers:make([{"Accept-Encoding", "gzip; q=, *;q=0"}])), ?assertEqual(bad_accept_encoding_value, Req6:accepted_encodings(["gzip", "deflate", "identity"])), Req7 = mochiweb_request:new(nil, 'GET', "/foo", {1, 1}, mochiweb_headers:make([{"Accept-Encoding", "gzip;q=2.0, *;q=0"}])), ?assertEqual(bad_accept_encoding_value, Req7:accepted_encodings(["gzip", "identity"])), Req8 = mochiweb_request:new(nil, 'GET', "/foo", {1, 1}, mochiweb_headers:make([{"Accept-Encoding", "deflate, *;q=0.0"}])), ?assertEqual([], Req8:accepted_encodings(["gzip", "identity"])). accepted_content_types_test() -> Req1 = mochiweb_request:new(nil, 'GET', "/foo", {1, 1}, mochiweb_headers:make([{"Accept", "text/html"}])), ?assertEqual(["text/html"], Req1:accepted_content_types(["text/html", "application/json"])), Req2 = mochiweb_request:new(nil, 'GET', "/foo", {1, 1}, mochiweb_headers:make([{"Accept", "text/html, */*;q=0"}])), ?assertEqual(["text/html"], Req2:accepted_content_types(["text/html", "application/json"])), Req3 = mochiweb_request:new(nil, 'GET', "/foo", {1, 1}, mochiweb_headers:make([{"Accept", "text/*, */*;q=0"}])), ?assertEqual(["text/html"], Req3:accepted_content_types(["text/html", "application/json"])), Req4 = mochiweb_request:new(nil, 'GET', "/foo", {1, 1}, mochiweb_headers:make([{"Accept", "text/*;q=0.8, */*;q=0.5"}])), ?assertEqual(["text/html", "application/json"], Req4:accepted_content_types(["application/json", "text/html"])), Req5 = mochiweb_request:new(nil, 'GET', "/foo", {1, 1}, mochiweb_headers:make([{"Accept", "text/*;q=0.8, */*;q=0.5"}])), ?assertEqual(["text/html", "application/json"], Req5:accepted_content_types(["text/html", "application/json"])), Req6 = mochiweb_request:new(nil, 'GET', "/foo", {1, 1}, mochiweb_headers:make([{"Accept", "text/*;q=0.5, */*;q=0.5"}])), ?assertEqual(["application/json", "text/html"], Req6:accepted_content_types(["application/json", "text/html"])), Req7 = mochiweb_request:new(nil, 'GET', "/foo", {1, 1}, mochiweb_headers:make( [{"Accept", "text/html;q=0.5, application/json;q=0.5"}])), ?assertEqual(["application/json", "text/html"], Req7:accepted_content_types(["application/json", "text/html"])), Req8 = mochiweb_request:new(nil, 'GET', "/foo", {1, 1}, mochiweb_headers:make([{"Accept", "text/html"}])), ?assertEqual([], Req8:accepted_content_types(["application/json"])), Req9 = mochiweb_request:new(nil, 'GET', "/foo", {1, 1}, mochiweb_headers:make([{"Accept", "text/*;q=0.9, text/html;q=0.5, */*;q=0.7"}])), ?assertEqual(["application/json", "text/html"], Req9:accepted_content_types(["text/html", "application/json"])). should_close_test() -> F = fun (V, H) -> (mochiweb_request:new( nil, 'GET', "/", V, mochiweb_headers:make(H) )):should_close() end, ?assertEqual( true, F({1, 1}, [{"Connection", "close"}])), ?assertEqual( true, F({1, 0}, [{"Connection", "close"}])), ?assertEqual( true, F({1, 1}, [{"Connection", "ClOSe"}])), ?assertEqual( false, F({1, 1}, [{"Connection", "closer"}])), ?assertEqual( false, F({1, 1}, [])), ?assertEqual( true, F({1, 0}, [])), ?assertEqual( false, F({1, 0}, [{"Connection", "Keep-Alive"}])), ok. -endif. rabbitmq-server-3.2.4/plugins-src/mochiweb-wrapper/mochiweb-git/src/mochiweb_request.erl.orig0000644000000000000000000010723212305126066031227 0ustar rootroot%% @author Bob Ippolito %% @copyright 2007 Mochi Media, Inc. %% @doc MochiWeb HTTP Request abstraction. -module(mochiweb_request). -author('bob@mochimedia.com'). -include_lib("kernel/include/file.hrl"). -include("internal.hrl"). -define(QUIP, "Any of you quaids got a smint?"). -export([new/5]). -export([get_header_value/2, get_primary_header_value/2, get_combined_header_value/2, get/2, dump/1]). -export([send/2, recv/2, recv/3, recv_body/1, recv_body/2, stream_body/4]). -export([start_response/2, start_response_length/2, start_raw_response/2]). -export([respond/2, ok/2]). -export([not_found/1, not_found/2]). -export([parse_post/1, parse_qs/1]). -export([should_close/1, cleanup/1]). -export([parse_cookie/1, get_cookie_value/2]). -export([serve_file/3, serve_file/4]). -export([accepted_encodings/2]). -export([accepts_content_type/2, accepted_content_types/2]). -define(SAVE_QS, mochiweb_request_qs). -define(SAVE_PATH, mochiweb_request_path). -define(SAVE_RECV, mochiweb_request_recv). -define(SAVE_BODY, mochiweb_request_body). -define(SAVE_BODY_LENGTH, mochiweb_request_body_length). -define(SAVE_POST, mochiweb_request_post). -define(SAVE_COOKIE, mochiweb_request_cookie). -define(SAVE_FORCE_CLOSE, mochiweb_request_force_close). %% @type key() = atom() | string() | binary() %% @type value() = atom() | string() | binary() | integer() %% @type headers(). A mochiweb_headers structure. %% @type request(). A mochiweb_request parameterized module instance. %% @type response(). A mochiweb_response parameterized module instance. %% @type ioheaders() = headers() | [{key(), value()}]. % 5 minute default idle timeout -define(IDLE_TIMEOUT, 300000). % Maximum recv_body() length of 1MB -define(MAX_RECV_BODY, (1024*1024)). %% @spec new(Socket, Method, RawPath, Version, headers()) -> request() %% @doc Create a new request instance. new(Socket, Method, RawPath, Version, Headers) -> {?MODULE, [Socket, Method, RawPath, Version, Headers]}. %% @spec get_header_value(K, request()) -> undefined | Value %% @doc Get the value of a given request header. get_header_value(K, {?MODULE, [_Socket, _Method, _RawPath, _Version, Headers]}) -> mochiweb_headers:get_value(K, Headers). get_primary_header_value(K, {?MODULE, [_Socket, _Method, _RawPath, _Version, Headers]}) -> mochiweb_headers:get_primary_value(K, Headers). get_combined_header_value(K, {?MODULE, [_Socket, _Method, _RawPath, _Version, Headers]}) -> mochiweb_headers:get_combined_value(K, Headers). %% @type field() = socket | scheme | method | raw_path | version | headers | peer | path | body_length | range %% @spec get(field(), request()) -> term() %% @doc Return the internal representation of the given field. If %% socket is requested on a HTTPS connection, then %% an ssl socket will be returned as {ssl, SslSocket}. %% You can use SslSocket with the ssl %% application, eg: ssl:peercert(SslSocket). get(socket, {?MODULE, [Socket, _Method, _RawPath, _Version, _Headers]}) -> Socket; get(scheme, {?MODULE, [Socket, _Method, _RawPath, _Version, _Headers]}) -> case mochiweb_socket:type(Socket) of plain -> http; ssl -> https end; get(method, {?MODULE, [_Socket, Method, _RawPath, _Version, _Headers]}) -> Method; get(raw_path, {?MODULE, [_Socket, _Method, RawPath, _Version, _Headers]}) -> RawPath; get(version, {?MODULE, [_Socket, _Method, _RawPath, Version, _Headers]}) -> Version; get(headers, {?MODULE, [_Socket, _Method, _RawPath, _Version, Headers]}) -> Headers; get(peer, {?MODULE, [Socket, _Method, _RawPath, _Version, _Headers]}=THIS) -> case mochiweb_socket:peername(Socket) of {ok, {Addr={10, _, _, _}, _Port}} -> case get_header_value("x-forwarded-for", THIS) of undefined -> inet_parse:ntoa(Addr); Hosts -> string:strip(lists:last(string:tokens(Hosts, ","))) end; {ok, {{127, 0, 0, 1}, _Port}} -> case get_header_value("x-forwarded-for", THIS) of undefined -> "127.0.0.1"; Hosts -> string:strip(lists:last(string:tokens(Hosts, ","))) end; {ok, {Addr, _Port}} -> inet_parse:ntoa(Addr); {error, enotconn} -> exit(normal) end; get(path, {?MODULE, [_Socket, _Method, RawPath, _Version, _Headers]}) -> case erlang:get(?SAVE_PATH) of undefined -> {Path0, _, _} = mochiweb_util:urlsplit_path(RawPath), Path = mochiweb_util:unquote(Path0), put(?SAVE_PATH, Path), Path; Cached -> Cached end; get(body_length, {?MODULE, [_Socket, _Method, _RawPath, _Version, _Headers]}=THIS) -> case erlang:get(?SAVE_BODY_LENGTH) of undefined -> BodyLength = body_length(THIS), put(?SAVE_BODY_LENGTH, {cached, BodyLength}), BodyLength; {cached, Cached} -> Cached end; get(range, {?MODULE, [_Socket, _Method, _RawPath, _Version, _Headers]}=THIS) -> case get_header_value(range, THIS) of undefined -> undefined; RawRange -> mochiweb_http:parse_range_request(RawRange) end. %% @spec dump(request()) -> {mochiweb_request, [{atom(), term()}]} %% @doc Dump the internal representation to a "human readable" set of terms %% for debugging/inspection purposes. dump({?MODULE, [_Socket, Method, RawPath, Version, Headers]}) -> {?MODULE, [{method, Method}, {version, Version}, {raw_path, RawPath}, {headers, mochiweb_headers:to_list(Headers)}]}. %% @spec send(iodata(), request()) -> ok %% @doc Send data over the socket. send(Data, {?MODULE, [Socket, _Method, _RawPath, _Version, _Headers]}) -> case mochiweb_socket:send(Socket, Data) of ok -> ok; _ -> exit(normal) end. %% @spec recv(integer(), request()) -> binary() %% @doc Receive Length bytes from the client as a binary, with the default %% idle timeout. recv(Length, {?MODULE, [_Socket, _Method, _RawPath, _Version, _Headers]}=THIS) -> recv(Length, ?IDLE_TIMEOUT, THIS). %% @spec recv(integer(), integer(), request()) -> binary() %% @doc Receive Length bytes from the client as a binary, with the given %% Timeout in msec. recv(Length, Timeout, {?MODULE, [Socket, _Method, _RawPath, _Version, _Headers]}) -> case mochiweb_socket:recv(Socket, Length, Timeout) of {ok, Data} -> put(?SAVE_RECV, true), Data; _ -> exit(normal) end. %% @spec body_length(request()) -> undefined | chunked | unknown_transfer_encoding | integer() %% @doc Infer body length from transfer-encoding and content-length headers. body_length({?MODULE, [_Socket, _Method, _RawPath, _Version, _Headers]}=THIS) -> case get_header_value("transfer-encoding", THIS) of undefined -> case get_combined_header_value("content-length", THIS) of undefined -> undefined; Length -> list_to_integer(Length) end; "chunked" -> chunked; Unknown -> {unknown_transfer_encoding, Unknown} end. %% @spec recv_body(request()) -> binary() %% @doc Receive the body of the HTTP request (defined by Content-Length). %% Will only receive up to the default max-body length of 1MB. recv_body({?MODULE, [_Socket, _Method, _RawPath, _Version, _Headers]}=THIS) -> recv_body(?MAX_RECV_BODY, THIS). %% @spec recv_body(integer(), request()) -> binary() %% @doc Receive the body of the HTTP request (defined by Content-Length). %% Will receive up to MaxBody bytes. recv_body(MaxBody, {?MODULE, [_Socket, _Method, _RawPath, _Version, _Headers]}=THIS) -> case erlang:get(?SAVE_BODY) of undefined -> % we could use a sane constant for max chunk size Body = stream_body(?MAX_RECV_BODY, fun ({0, _ChunkedFooter}, {_LengthAcc, BinAcc}) -> iolist_to_binary(lists:reverse(BinAcc)); ({Length, Bin}, {LengthAcc, BinAcc}) -> NewLength = Length + LengthAcc, if NewLength > MaxBody -> exit({body_too_large, chunked}); true -> {NewLength, [Bin | BinAcc]} end end, {0, []}, MaxBody, THIS), put(?SAVE_BODY, Body), Body; Cached -> Cached end. stream_body(MaxChunkSize, ChunkFun, FunState, {?MODULE,[_Socket,_Method,_RawPath,_Version,_Headers]}=THIS) -> stream_body(MaxChunkSize, ChunkFun, FunState, undefined, THIS). stream_body(MaxChunkSize, ChunkFun, FunState, MaxBodyLength, {?MODULE, [_Socket, _Method, _RawPath, _Version, _Headers]}=THIS) -> Expect = case get_header_value("expect", THIS) of undefined -> undefined; Value when is_list(Value) -> string:to_lower(Value) end, case Expect of "100-continue" -> _ = start_raw_response({100, gb_trees:empty()}, THIS), ok; _Else -> ok end, case body_length(THIS) of undefined -> undefined; {unknown_transfer_encoding, Unknown} -> exit({unknown_transfer_encoding, Unknown}); chunked -> % In this case the MaxBody is actually used to % determine the maximum allowed size of a single % chunk. stream_chunked_body(MaxChunkSize, ChunkFun, FunState, THIS); 0 -> <<>>; Length when is_integer(Length) -> case MaxBodyLength of MaxBodyLength when is_integer(MaxBodyLength), MaxBodyLength < Length -> exit({body_too_large, content_length}); _ -> stream_unchunked_body(Length, ChunkFun, FunState, THIS) end end. %% @spec start_response({integer(), ioheaders()}, request()) -> response() %% @doc Start the HTTP response by sending the Code HTTP response and %% ResponseHeaders. The server will set header defaults such as Server %% and Date if not present in ResponseHeaders. start_response({Code, ResponseHeaders}, {?MODULE, [_Socket, _Method, _RawPath, _Version, _Headers]}=THIS) -> HResponse = mochiweb_headers:make(ResponseHeaders), HResponse1 = mochiweb_headers:default_from_list(server_headers(), HResponse), start_raw_response({Code, HResponse1}, THIS). %% @spec start_raw_response({integer(), headers()}, request()) -> response() %% @doc Start the HTTP response by sending the Code HTTP response and %% ResponseHeaders. start_raw_response({Code, ResponseHeaders}, {?MODULE, [_Socket, _Method, _RawPath, Version, _Headers]}=THIS) -> F = fun ({K, V}, Acc) -> [mochiweb_util:make_io(K), <<": ">>, V, <<"\r\n">> | Acc] end, End = lists:foldl(F, [<<"\r\n">>], mochiweb_headers:to_list(ResponseHeaders)), send([make_version(Version), make_code(Code), <<"\r\n">> | End], THIS), mochiweb:new_response({THIS, Code, ResponseHeaders}). %% @spec start_response_length({integer(), ioheaders(), integer()}, request()) -> response() %% @doc Start the HTTP response by sending the Code HTTP response and %% ResponseHeaders including a Content-Length of Length. The server %% will set header defaults such as Server %% and Date if not present in ResponseHeaders. start_response_length({Code, ResponseHeaders, Length}, {?MODULE, [_Socket, _Method, _RawPath, _Version, _Headers]}=THIS) -> HResponse = mochiweb_headers:make(ResponseHeaders), HResponse1 = mochiweb_headers:enter("Content-Length", Length, HResponse), start_response({Code, HResponse1}, THIS). %% @spec respond({integer(), ioheaders(), iodata() | chunked | {file, IoDevice}}, request()) -> response() %% @doc Start the HTTP response with start_response, and send Body to the %% client (if the get(method) /= 'HEAD'). The Content-Length header %% will be set by the Body length, and the server will insert header %% defaults. respond({Code, ResponseHeaders, {file, IoDevice}}, {?MODULE, [_Socket, Method, _RawPath, _Version, _Headers]}=THIS) -> Length = mochiweb_io:iodevice_size(IoDevice), Response = start_response_length({Code, ResponseHeaders, Length}, THIS), case Method of 'HEAD' -> ok; _ -> mochiweb_io:iodevice_stream( fun (Body) -> send(Body, THIS) end, IoDevice) end, Response; respond({Code, ResponseHeaders, chunked}, {?MODULE, [_Socket, Method, _RawPath, Version, _Headers]}=THIS) -> HResponse = mochiweb_headers:make(ResponseHeaders), HResponse1 = case Method of 'HEAD' -> %% This is what Google does, http://www.google.com/ %% is chunked but HEAD gets Content-Length: 0. %% The RFC is ambiguous so emulating Google is smart. mochiweb_headers:enter("Content-Length", "0", HResponse); _ when Version >= {1, 1} -> %% Only use chunked encoding for HTTP/1.1 mochiweb_headers:enter("Transfer-Encoding", "chunked", HResponse); _ -> %% For pre-1.1 clients we send the data as-is %% without a Content-Length header and without %% chunk delimiters. Since the end of the document %% is now ambiguous we must force a close. put(?SAVE_FORCE_CLOSE, true), HResponse end, start_response({Code, HResponse1}, THIS); respond({Code, ResponseHeaders, Body}, {?MODULE, [_Socket, Method, _RawPath, _Version, _Headers]}=THIS) -> Response = start_response_length({Code, ResponseHeaders, iolist_size(Body)}, THIS), case Method of 'HEAD' -> ok; _ -> send(Body, THIS) end, Response. %% @spec not_found(request()) -> response() %% @doc Alias for not_found([]). not_found({?MODULE, [_Socket, _Method, _RawPath, _Version, _Headers]}=THIS) -> not_found([], THIS). %% @spec not_found(ExtraHeaders, request()) -> response() %% @doc Alias for respond({404, [{"Content-Type", "text/plain"} %% | ExtraHeaders], <<"Not found.">>}). not_found(ExtraHeaders, {?MODULE, [_Socket, _Method, _RawPath, _Version, _Headers]}=THIS) -> respond({404, [{"Content-Type", "text/plain"} | ExtraHeaders], <<"Not found.">>}, THIS). %% @spec ok({value(), iodata()} | {value(), ioheaders(), iodata() | {file, IoDevice}}, request()) -> %% response() %% @doc respond({200, [{"Content-Type", ContentType} | Headers], Body}). ok({ContentType, Body}, {?MODULE, [_Socket, _Method, _RawPath, _Version, _Headers]}=THIS) -> ok({ContentType, [], Body}, THIS); ok({ContentType, ResponseHeaders, Body}, {?MODULE, [_Socket, _Method, _RawPath, _Version, _Headers]}=THIS) -> HResponse = mochiweb_headers:make(ResponseHeaders), case THIS:get(range) of X when (X =:= undefined orelse X =:= fail) orelse Body =:= chunked -> %% http://code.google.com/p/mochiweb/issues/detail?id=54 %% Range header not supported when chunked, return 200 and provide %% full response. HResponse1 = mochiweb_headers:enter("Content-Type", ContentType, HResponse), respond({200, HResponse1, Body}, THIS); Ranges -> {PartList, Size} = range_parts(Body, Ranges), case PartList of [] -> %% no valid ranges HResponse1 = mochiweb_headers:enter("Content-Type", ContentType, HResponse), %% could be 416, for now we'll just return 200 respond({200, HResponse1, Body}, THIS); PartList -> {RangeHeaders, RangeBody} = mochiweb_multipart:parts_to_body(PartList, ContentType, Size), HResponse1 = mochiweb_headers:enter_from_list( [{"Accept-Ranges", "bytes"} | RangeHeaders], HResponse), respond({206, HResponse1, RangeBody}, THIS) end end. %% @spec should_close(request()) -> bool() %% @doc Return true if the connection must be closed. If false, using %% Keep-Alive should be safe. should_close({?MODULE, [_Socket, _Method, _RawPath, Version, _Headers]}=THIS) -> ForceClose = erlang:get(?SAVE_FORCE_CLOSE) =/= undefined, DidNotRecv = erlang:get(?SAVE_RECV) =:= undefined, ForceClose orelse Version < {1, 0} %% Connection: close orelse is_close(get_header_value("connection", THIS)) %% HTTP 1.0 requires Connection: Keep-Alive orelse (Version =:= {1, 0} andalso get_header_value("connection", THIS) =/= "Keep-Alive") %% unread data left on the socket, can't safely continue orelse (DidNotRecv andalso get_combined_header_value("content-length", THIS) =/= undefined andalso list_to_integer(get_combined_header_value("content-length", THIS)) > 0) orelse (DidNotRecv andalso get_header_value("transfer-encoding", THIS) =:= "chunked"). is_close("close") -> true; is_close(S=[_C, _L, _O, _S, _E]) -> string:to_lower(S) =:= "close"; is_close(_) -> false. %% @spec cleanup(request()) -> ok %% @doc Clean up any junk in the process dictionary, required before continuing %% a Keep-Alive request. cleanup({?MODULE, [_Socket, _Method, _RawPath, _Version, _Headers]}) -> L = [?SAVE_QS, ?SAVE_PATH, ?SAVE_RECV, ?SAVE_BODY, ?SAVE_BODY_LENGTH, ?SAVE_POST, ?SAVE_COOKIE, ?SAVE_FORCE_CLOSE], lists:foreach(fun(K) -> erase(K) end, L), ok. %% @spec parse_qs(request()) -> [{Key::string(), Value::string()}] %% @doc Parse the query string of the URL. parse_qs({?MODULE, [_Socket, _Method, RawPath, _Version, _Headers]}) -> case erlang:get(?SAVE_QS) of undefined -> {_, QueryString, _} = mochiweb_util:urlsplit_path(RawPath), Parsed = mochiweb_util:parse_qs(QueryString), put(?SAVE_QS, Parsed), Parsed; Cached -> Cached end. %% @spec get_cookie_value(Key::string, request()) -> string() | undefined %% @doc Get the value of the given cookie. get_cookie_value(Key, {?MODULE, [_Socket, _Method, _RawPath, _Version, _Headers]}=THIS) -> proplists:get_value(Key, parse_cookie(THIS)). %% @spec parse_cookie(request()) -> [{Key::string(), Value::string()}] %% @doc Parse the cookie header. parse_cookie({?MODULE, [_Socket, _Method, _RawPath, _Version, _Headers]}=THIS) -> case erlang:get(?SAVE_COOKIE) of undefined -> Cookies = case get_header_value("cookie", THIS) of undefined -> []; Value -> mochiweb_cookies:parse_cookie(Value) end, put(?SAVE_COOKIE, Cookies), Cookies; Cached -> Cached end. %% @spec parse_post(request()) -> [{Key::string(), Value::string()}] %% @doc Parse an application/x-www-form-urlencoded form POST. This %% has the side-effect of calling recv_body(). parse_post({?MODULE, [_Socket, _Method, _RawPath, _Version, _Headers]}=THIS) -> case erlang:get(?SAVE_POST) of undefined -> Parsed = case recv_body(THIS) of undefined -> []; Binary -> case get_primary_header_value("content-type",THIS) of "application/x-www-form-urlencoded" ++ _ -> mochiweb_util:parse_qs(Binary); _ -> [] end end, put(?SAVE_POST, Parsed), Parsed; Cached -> Cached end. %% @spec stream_chunked_body(integer(), fun(), term(), request()) -> term() %% @doc The function is called for each chunk. %% Used internally by read_chunked_body. stream_chunked_body(MaxChunkSize, Fun, FunState, {?MODULE, [_Socket, _Method, _RawPath, _Version, _Headers]}=THIS) -> case read_chunk_length(THIS) of 0 -> Fun({0, read_chunk(0, THIS)}, FunState); Length when Length > MaxChunkSize -> NewState = read_sub_chunks(Length, MaxChunkSize, Fun, FunState, THIS), stream_chunked_body(MaxChunkSize, Fun, NewState, THIS); Length -> NewState = Fun({Length, read_chunk(Length, THIS)}, FunState), stream_chunked_body(MaxChunkSize, Fun, NewState, THIS) end. stream_unchunked_body(0, Fun, FunState, {?MODULE, [_Socket, _Method, _RawPath, _Version, _Headers]}) -> Fun({0, <<>>}, FunState); stream_unchunked_body(Length, Fun, FunState, {?MODULE, [_Socket, _Method, _RawPath, _Version, _Headers]}=THIS) when Length > 0 -> PktSize = case Length > ?RECBUF_SIZE of true -> ?RECBUF_SIZE; false -> Length end, Bin = recv(PktSize, THIS), NewState = Fun({PktSize, Bin}, FunState), stream_unchunked_body(Length - PktSize, Fun, NewState, THIS). %% @spec read_chunk_length(request()) -> integer() %% @doc Read the length of the next HTTP chunk. read_chunk_length({?MODULE, [Socket, _Method, _RawPath, _Version, _Headers]}) -> ok = mochiweb_socket:setopts(Socket, [{packet, line}]), case mochiweb_socket:recv(Socket, 0, ?IDLE_TIMEOUT) of {ok, Header} -> ok = mochiweb_socket:setopts(Socket, [{packet, raw}]), Splitter = fun (C) -> C =/= $\r andalso C =/= $\n andalso C =/= $ end, {Hex, _Rest} = lists:splitwith(Splitter, binary_to_list(Header)), mochihex:to_int(Hex); _ -> exit(normal) end. %% @spec read_chunk(integer(), request()) -> Chunk::binary() | [Footer::binary()] %% @doc Read in a HTTP chunk of the given length. If Length is 0, then read the %% HTTP footers (as a list of binaries, since they're nominal). read_chunk(0, {?MODULE, [Socket, _Method, _RawPath, _Version, _Headers]}) -> ok = mochiweb_socket:setopts(Socket, [{packet, line}]), F = fun (F1, Acc) -> case mochiweb_socket:recv(Socket, 0, ?IDLE_TIMEOUT) of {ok, <<"\r\n">>} -> Acc; {ok, Footer} -> F1(F1, [Footer | Acc]); _ -> exit(normal) end end, Footers = F(F, []), ok = mochiweb_socket:setopts(Socket, [{packet, raw}]), put(?SAVE_RECV, true), Footers; read_chunk(Length, {?MODULE, [Socket, _Method, _RawPath, _Version, _Headers]}) -> case mochiweb_socket:recv(Socket, 2 + Length, ?IDLE_TIMEOUT) of {ok, <>} -> Chunk; _ -> exit(normal) end. read_sub_chunks(Length, MaxChunkSize, Fun, FunState, {?MODULE, [_Socket, _Method, _RawPath, _Version, _Headers]}=THIS) when Length > MaxChunkSize -> Bin = recv(MaxChunkSize, THIS), NewState = Fun({size(Bin), Bin}, FunState), read_sub_chunks(Length - MaxChunkSize, MaxChunkSize, Fun, NewState, THIS); read_sub_chunks(Length, _MaxChunkSize, Fun, FunState, {?MODULE, [_Socket, _Method, _RawPath, _Version, _Headers]}=THIS) -> Fun({Length, read_chunk(Length, THIS)}, FunState). %% @spec serve_file(Path, DocRoot, request()) -> Response %% @doc Serve a file relative to DocRoot. serve_file(Path, DocRoot, {?MODULE, [_Socket, _Method, _RawPath, _Version, _Headers]}=THIS) -> serve_file(Path, DocRoot, [], THIS). %% @spec serve_file(Path, DocRoot, ExtraHeaders, request()) -> Response %% @doc Serve a file relative to DocRoot. serve_file(Path, DocRoot, ExtraHeaders, {?MODULE, [_Socket, _Method, _RawPath, _Version, _Headers]}=THIS) -> case mochiweb_util:safe_relative_path(Path) of undefined -> not_found(ExtraHeaders, THIS); RelPath -> FullPath = filename:join([DocRoot, RelPath]), case filelib:is_dir(FullPath) of true -> maybe_redirect(RelPath, FullPath, ExtraHeaders, THIS); false -> maybe_serve_file(FullPath, ExtraHeaders, THIS) end end. %% Internal API %% This has the same effect as the DirectoryIndex directive in httpd directory_index(FullPath) -> filename:join([FullPath, "index.html"]). maybe_redirect([], FullPath, ExtraHeaders, {?MODULE, [_Socket, _Method, _RawPath, _Version, _Headers]}=THIS) -> maybe_serve_file(directory_index(FullPath), ExtraHeaders, THIS); maybe_redirect(RelPath, FullPath, ExtraHeaders, {?MODULE, [_Socket, _Method, _RawPath, _Version, Headers]}=THIS) -> case string:right(RelPath, 1) of "/" -> maybe_serve_file(directory_index(FullPath), ExtraHeaders, THIS); _ -> Host = mochiweb_headers:get_value("host", Headers), Location = "http://" ++ Host ++ "/" ++ RelPath ++ "/", LocationBin = list_to_binary(Location), MoreHeaders = [{"Location", Location}, {"Content-Type", "text/html"} | ExtraHeaders], Top = <<"" "" "301 Moved Permanently" "" "

    Moved Permanently

    " "

    The document has moved >, Bottom = <<">here.

    \n">>, Body = <>, respond({301, MoreHeaders, Body}, THIS) end. maybe_serve_file(File, ExtraHeaders, {?MODULE, [_Socket, _Method, _RawPath, _Version, _Headers]}=THIS) -> case file:read_file_info(File) of {ok, FileInfo} -> LastModified = httpd_util:rfc1123_date(FileInfo#file_info.mtime), case get_header_value("if-modified-since", THIS) of LastModified -> respond({304, ExtraHeaders, ""}, THIS); _ -> case file:open(File, [raw, binary]) of {ok, IoDevice} -> ContentType = mochiweb_util:guess_mime(File), Res = ok({ContentType, [{"last-modified", LastModified} | ExtraHeaders], {file, IoDevice}}, THIS), ok = file:close(IoDevice), Res; _ -> not_found(ExtraHeaders, THIS) end end; {error, _} -> not_found(ExtraHeaders, THIS) end. server_headers() -> [{"Server", "MochiWeb/1.0 (" ++ ?QUIP ++ ")"}, {"Date", httpd_util:rfc1123_date()}]. make_code(X) when is_integer(X) -> [integer_to_list(X), [" " | httpd_util:reason_phrase(X)]]; make_code(Io) when is_list(Io); is_binary(Io) -> Io. make_version({1, 0}) -> <<"HTTP/1.0 ">>; make_version(_) -> <<"HTTP/1.1 ">>. range_parts({file, IoDevice}, Ranges) -> Size = mochiweb_io:iodevice_size(IoDevice), F = fun (Spec, Acc) -> case mochiweb_http:range_skip_length(Spec, Size) of invalid_range -> Acc; V -> [V | Acc] end end, LocNums = lists:foldr(F, [], Ranges), {ok, Data} = file:pread(IoDevice, LocNums), Bodies = lists:zipwith(fun ({Skip, Length}, PartialBody) -> {Skip, Skip + Length - 1, PartialBody} end, LocNums, Data), {Bodies, Size}; range_parts(Body0, Ranges) -> Body = iolist_to_binary(Body0), Size = size(Body), F = fun(Spec, Acc) -> case mochiweb_http:range_skip_length(Spec, Size) of invalid_range -> Acc; {Skip, Length} -> <<_:Skip/binary, PartialBody:Length/binary, _/binary>> = Body, [{Skip, Skip + Length - 1, PartialBody} | Acc] end end, {lists:foldr(F, [], Ranges), Size}. %% @spec accepted_encodings([encoding()], request()) -> [encoding()] | bad_accept_encoding_value %% @type encoding() = string(). %% %% @doc Returns a list of encodings accepted by a request. Encodings that are %% not supported by the server will not be included in the return list. %% This list is computed from the "Accept-Encoding" header and %% its elements are ordered, descendingly, according to their Q values. %% %% Section 14.3 of the RFC 2616 (HTTP 1.1) describes the "Accept-Encoding" %% header and the process of determining which server supported encodings %% can be used for encoding the body for the request's response. %% %% Examples %% %% 1) For a missing "Accept-Encoding" header: %% accepted_encodings(["gzip", "identity"]) -> ["identity"] %% %% 2) For an "Accept-Encoding" header with value "gzip, deflate": %% accepted_encodings(["gzip", "identity"]) -> ["gzip", "identity"] %% %% 3) For an "Accept-Encoding" header with value "gzip;q=0.5, deflate": %% accepted_encodings(["gzip", "deflate", "identity"]) -> %% ["deflate", "gzip", "identity"] %% accepted_encodings(SupportedEncodings, {?MODULE, [_Socket, _Method, _RawPath, _Version, _Headers]}=THIS) -> AcceptEncodingHeader = case get_header_value("Accept-Encoding", THIS) of undefined -> ""; Value -> Value end, case mochiweb_util:parse_qvalues(AcceptEncodingHeader) of invalid_qvalue_string -> bad_accept_encoding_value; QList -> mochiweb_util:pick_accepted_encodings( QList, SupportedEncodings, "identity" ) end. %% @spec accepts_content_type(string() | binary(), request()) -> boolean() | bad_accept_header %% %% @doc Determines whether a request accepts a given media type by analyzing its %% "Accept" header. %% %% Examples %% %% 1) For a missing "Accept" header: %% accepts_content_type("application/json") -> true %% %% 2) For an "Accept" header with value "text/plain, application/*": %% accepts_content_type("application/json") -> true %% %% 3) For an "Accept" header with value "text/plain, */*; q=0.0": %% accepts_content_type("application/json") -> false %% %% 4) For an "Accept" header with value "text/plain; q=0.5, */*; q=0.1": %% accepts_content_type("application/json") -> true %% %% 5) For an "Accept" header with value "text/*; q=0.0, */*": %% accepts_content_type("text/plain") -> false %% accepts_content_type(ContentType1, {?MODULE, [_Socket, _Method, _RawPath, _Version, _Headers]}=THIS) -> ContentType = re:replace(ContentType1, "\\s", "", [global, {return, list}]), AcceptHeader = accept_header(THIS), case mochiweb_util:parse_qvalues(AcceptHeader) of invalid_qvalue_string -> bad_accept_header; QList -> [MainType, _SubType] = string:tokens(ContentType, "/"), SuperType = MainType ++ "/*", lists:any( fun({"*/*", Q}) when Q > 0.0 -> true; ({Type, Q}) when Q > 0.0 -> Type =:= ContentType orelse Type =:= SuperType; (_) -> false end, QList ) andalso (not lists:member({ContentType, 0.0}, QList)) andalso (not lists:member({SuperType, 0.0}, QList)) end. %% @spec accepted_content_types([string() | binary()], request()) -> [string()] | bad_accept_header %% %% @doc Filters which of the given media types this request accepts. This filtering %% is performed by analyzing the "Accept" header. The returned list is sorted %% according to the preferences specified in the "Accept" header (higher Q values %% first). If two or more types have the same preference (Q value), they're order %% in the returned list is the same as they're order in the input list. %% %% Examples %% %% 1) For a missing "Accept" header: %% accepted_content_types(["text/html", "application/json"]) -> %% ["text/html", "application/json"] %% %% 2) For an "Accept" header with value "text/html, application/*": %% accepted_content_types(["application/json", "text/html"]) -> %% ["application/json", "text/html"] %% %% 3) For an "Accept" header with value "text/html, */*; q=0.0": %% accepted_content_types(["text/html", "application/json"]) -> %% ["text/html"] %% %% 4) For an "Accept" header with value "text/html; q=0.5, */*; q=0.1": %% accepts_content_types(["application/json", "text/html"]) -> %% ["text/html", "application/json"] %% accepted_content_types(Types1, {?MODULE, [_Socket, _Method, _RawPath, _Version, _Headers]}=THIS) -> Types = lists:map( fun(T) -> re:replace(T, "\\s", "", [global, {return, list}]) end, Types1), AcceptHeader = accept_header(THIS), case mochiweb_util:parse_qvalues(AcceptHeader) of invalid_qvalue_string -> bad_accept_header; QList -> TypesQ = lists:foldr( fun(T, Acc) -> case proplists:get_value(T, QList) of undefined -> [MainType, _SubType] = string:tokens(T, "/"), case proplists:get_value(MainType ++ "/*", QList) of undefined -> case proplists:get_value("*/*", QList) of Q when is_float(Q), Q > 0.0 -> [{Q, T} | Acc]; _ -> Acc end; Q when Q > 0.0 -> [{Q, T} | Acc]; _ -> Acc end; Q when Q > 0.0 -> [{Q, T} | Acc]; _ -> Acc end end, [], Types), % Note: Stable sort. If 2 types have the same Q value we leave them in the % same order as in the input list. SortFun = fun({Q1, _}, {Q2, _}) -> Q1 >= Q2 end, [Type || {_Q, Type} <- lists:sort(SortFun, TypesQ)] end. accept_header({?MODULE, [_Socket, _Method, _RawPath, _Version, _Headers]}=THIS) -> case get_header_value("Accept", THIS) of undefined -> "*/*"; Value -> Value end. %% %% Tests %% -ifdef(TEST). -include_lib("eunit/include/eunit.hrl"). -endif. rabbitmq-server-3.2.4/plugins-src/mochiweb-wrapper/mochiweb-git/src/mochiweb_cover.erl0000644000000000000000000000366412305126066027722 0ustar rootroot%% @author Bob Ippolito %% @copyright 2010 Mochi Media, Inc. %% @doc Workarounds for various cover deficiencies. -module(mochiweb_cover). -export([get_beam/1, get_abstract_code/1, get_clauses/2, clause_lookup_table/1]). -export([clause_lookup_table/2]). %% Internal get_beam(Module) -> {Module, Beam, _Path} = code:get_object_code(Module), Beam. get_abstract_code(Beam) -> {ok, {_Module, [{abstract_code, {raw_abstract_v1, L}}]}} = beam_lib:chunks(Beam, [abstract_code]), L. get_clauses(Function, Code) -> [L] = [Clauses || {function, _, FName, _, Clauses} <- Code, FName =:= Function], L. clause_lookup_table(Module, Function) -> clause_lookup_table( get_clauses(Function, get_abstract_code(get_beam(Module)))). clause_lookup_table(Clauses) -> lists:foldr(fun clause_fold/2, [], Clauses). clause_fold({clause, _, [InTerm], _Guards=[], [OutTerm]}, Acc) -> try [{erl_parse:normalise(InTerm), erl_parse:normalise(OutTerm)} | Acc] catch error:_ -> Acc end; clause_fold(_, Acc) -> Acc. %% %% Tests %% -ifdef(TEST). -include_lib("eunit/include/eunit.hrl"). foo_table(a) -> b; foo_table("a") -> <<"b">>; foo_table(123) -> {4, 3, 2}; foo_table([list]) -> []; foo_table([list1, list2]) -> [list1, list2, list3]; foo_table(ignored) -> some, code, ignored; foo_table(Var) -> Var. foo_table_test() -> T = clause_lookup_table(?MODULE, foo_table), [?assertEqual(V, foo_table(K)) || {K, V} <- T]. clause_lookup_table_test() -> ?assertEqual(b, foo_table(a)), ?assertEqual(ignored, foo_table(ignored)), ?assertEqual('Var', foo_table('Var')), ?assertEqual( [{a, b}, {"a", <<"b">>}, {123, {4, 3, 2}}, {[list], []}, {[list1, list2], [list1, list2, list3]}], clause_lookup_table(?MODULE, foo_table)). -endif. rabbitmq-server-3.2.4/plugins-src/mochiweb-wrapper/mochiweb-git/src/mochiweb_cookies.erl0000644000000000000000000002434112305126066030233 0ustar rootroot%% @author Emad El-Haraty %% @copyright 2007 Mochi Media, Inc. %% @doc HTTP Cookie parsing and generating (RFC 2109, RFC 2965). -module(mochiweb_cookies). -export([parse_cookie/1, cookie/3, cookie/2]). -define(QUOTE, $\"). -define(IS_WHITESPACE(C), (C =:= $\s orelse C =:= $\t orelse C =:= $\r orelse C =:= $\n)). %% RFC 2616 separators (called tspecials in RFC 2068) -define(IS_SEPARATOR(C), (C < 32 orelse C =:= $\s orelse C =:= $\t orelse C =:= $( orelse C =:= $) orelse C =:= $< orelse C =:= $> orelse C =:= $@ orelse C =:= $, orelse C =:= $; orelse C =:= $: orelse C =:= $\\ orelse C =:= $\" orelse C =:= $/ orelse C =:= $[ orelse C =:= $] orelse C =:= $? orelse C =:= $= orelse C =:= ${ orelse C =:= $})). %% @type proplist() = [{Key::string(), Value::string()}]. %% @type header() = {Name::string(), Value::string()}. %% @type int_seconds() = integer(). %% @spec cookie(Key::string(), Value::string()) -> header() %% @doc Short-hand for cookie(Key, Value, []). cookie(Key, Value) -> cookie(Key, Value, []). %% @spec cookie(Key::string(), Value::string(), Options::[Option]) -> header() %% where Option = {max_age, int_seconds()} | {local_time, {date(), time()}} %% | {domain, string()} | {path, string()} %% | {secure, true | false} | {http_only, true | false} %% %% @doc Generate a Set-Cookie header field tuple. cookie(Key, Value, Options) -> Cookie = [any_to_list(Key), "=", quote(Value), "; Version=1"], %% Set-Cookie: %% Comment, Domain, Max-Age, Path, Secure, Version %% Set-Cookie2: %% Comment, CommentURL, Discard, Domain, Max-Age, Path, Port, Secure, %% Version ExpiresPart = case proplists:get_value(max_age, Options) of undefined -> ""; RawAge -> When = case proplists:get_value(local_time, Options) of undefined -> calendar:local_time(); LocalTime -> LocalTime end, Age = case RawAge < 0 of true -> 0; false -> RawAge end, ["; Expires=", age_to_cookie_date(Age, When), "; Max-Age=", quote(Age)] end, SecurePart = case proplists:get_value(secure, Options) of true -> "; Secure"; _ -> "" end, DomainPart = case proplists:get_value(domain, Options) of undefined -> ""; Domain -> ["; Domain=", quote(Domain)] end, PathPart = case proplists:get_value(path, Options) of undefined -> ""; Path -> ["; Path=", quote(Path)] end, HttpOnlyPart = case proplists:get_value(http_only, Options) of true -> "; HttpOnly"; _ -> "" end, CookieParts = [Cookie, ExpiresPart, SecurePart, DomainPart, PathPart, HttpOnlyPart], {"Set-Cookie", lists:flatten(CookieParts)}. %% Every major browser incorrectly handles quoted strings in a %% different and (worse) incompatible manner. Instead of wasting time %% writing redundant code for each browser, we restrict cookies to %% only contain characters that browsers handle compatibly. %% %% By replacing the definition of quote with this, we generate %% RFC-compliant cookies: %% %% quote(V) -> %% Fun = fun(?QUOTE, Acc) -> [$\\, ?QUOTE | Acc]; %% (Ch, Acc) -> [Ch | Acc] %% end, %% [?QUOTE | lists:foldr(Fun, [?QUOTE], V)]. %% Convert to a string and raise an error if quoting is required. quote(V0) -> V = any_to_list(V0), lists:all(fun(Ch) -> Ch =:= $/ orelse not ?IS_SEPARATOR(Ch) end, V) orelse erlang:error({cookie_quoting_required, V}), V. %% Return a date in the form of: Wdy, DD-Mon-YYYY HH:MM:SS GMT %% See also: rfc2109: 10.1.2 rfc2109_cookie_expires_date(LocalTime) -> {{YYYY,MM,DD},{Hour,Min,Sec}} = case calendar:local_time_to_universal_time_dst(LocalTime) of [] -> {Date, {Hour1, Min1, Sec1}} = LocalTime, LocalTime2 = {Date, {Hour1 + 1, Min1, Sec1}}, case calendar:local_time_to_universal_time_dst(LocalTime2) of [Gmt] -> Gmt; [_,Gmt] -> Gmt end; [Gmt] -> Gmt; [_,Gmt] -> Gmt end, DayNumber = calendar:day_of_the_week({YYYY,MM,DD}), lists:flatten( io_lib:format("~s, ~2.2.0w-~3.s-~4.4.0w ~2.2.0w:~2.2.0w:~2.2.0w GMT", [httpd_util:day(DayNumber),DD,httpd_util:month(MM),YYYY,Hour,Min,Sec])). add_seconds(Secs, LocalTime) -> Greg = calendar:datetime_to_gregorian_seconds(LocalTime), calendar:gregorian_seconds_to_datetime(Greg + Secs). age_to_cookie_date(Age, LocalTime) -> rfc2109_cookie_expires_date(add_seconds(Age, LocalTime)). %% @spec parse_cookie(string()) -> [{K::string(), V::string()}] %% @doc Parse the contents of a Cookie header field, ignoring cookie %% attributes, and return a simple property list. parse_cookie("") -> []; parse_cookie(Cookie) -> parse_cookie(Cookie, []). %% Internal API parse_cookie([], Acc) -> lists:reverse(Acc); parse_cookie(String, Acc) -> {{Token, Value}, Rest} = read_pair(String), Acc1 = case Token of "" -> Acc; "$" ++ _ -> Acc; _ -> [{Token, Value} | Acc] end, parse_cookie(Rest, Acc1). read_pair(String) -> {Token, Rest} = read_token(skip_whitespace(String)), {Value, Rest1} = read_value(skip_whitespace(Rest)), {{Token, Value}, skip_past_separator(Rest1)}. read_value([$= | Value]) -> Value1 = skip_whitespace(Value), case Value1 of [?QUOTE | _] -> read_quoted(Value1); _ -> read_token(Value1) end; read_value(String) -> {"", String}. read_quoted([?QUOTE | String]) -> read_quoted(String, []). read_quoted([], Acc) -> {lists:reverse(Acc), []}; read_quoted([?QUOTE | Rest], Acc) -> {lists:reverse(Acc), Rest}; read_quoted([$\\, Any | Rest], Acc) -> read_quoted(Rest, [Any | Acc]); read_quoted([C | Rest], Acc) -> read_quoted(Rest, [C | Acc]). skip_whitespace(String) -> F = fun (C) -> ?IS_WHITESPACE(C) end, lists:dropwhile(F, String). read_token(String) -> F = fun (C) -> not ?IS_SEPARATOR(C) end, lists:splitwith(F, String). skip_past_separator([]) -> []; skip_past_separator([$; | Rest]) -> Rest; skip_past_separator([$, | Rest]) -> Rest; skip_past_separator([_ | Rest]) -> skip_past_separator(Rest). any_to_list(V) when is_list(V) -> V; any_to_list(V) when is_atom(V) -> atom_to_list(V); any_to_list(V) when is_binary(V) -> binary_to_list(V); any_to_list(V) when is_integer(V) -> integer_to_list(V). %% %% Tests %% -ifdef(TEST). -include_lib("eunit/include/eunit.hrl"). quote_test() -> %% ?assertError eunit macro is not compatible with coverage module try quote(":wq") catch error:{cookie_quoting_required, ":wq"} -> ok end, ?assertEqual( "foo", quote(foo)), ok. parse_cookie_test() -> %% RFC example C1 = "$Version=\"1\"; Customer=\"WILE_E_COYOTE\"; $Path=\"/acme\"; Part_Number=\"Rocket_Launcher_0001\"; $Path=\"/acme\"; Shipping=\"FedEx\"; $Path=\"/acme\"", ?assertEqual( [{"Customer","WILE_E_COYOTE"}, {"Part_Number","Rocket_Launcher_0001"}, {"Shipping","FedEx"}], parse_cookie(C1)), %% Potential edge cases ?assertEqual( [{"foo", "x"}], parse_cookie("foo=\"\\x\"")), ?assertEqual( [], parse_cookie("=")), ?assertEqual( [{"foo", ""}, {"bar", ""}], parse_cookie(" foo ; bar ")), ?assertEqual( [{"foo", ""}, {"bar", ""}], parse_cookie("foo=;bar=")), ?assertEqual( [{"foo", "\";"}, {"bar", ""}], parse_cookie("foo = \"\\\";\";bar ")), ?assertEqual( [{"foo", "\";bar"}], parse_cookie("foo=\"\\\";bar")), ?assertEqual( [], parse_cookie([])), ?assertEqual( [{"foo", "bar"}, {"baz", "wibble"}], parse_cookie("foo=bar , baz=wibble ")), ok. domain_test() -> ?assertEqual( {"Set-Cookie", "Customer=WILE_E_COYOTE; " "Version=1; " "Domain=acme.com; " "HttpOnly"}, cookie("Customer", "WILE_E_COYOTE", [{http_only, true}, {domain, "acme.com"}])), ok. local_time_test() -> {"Set-Cookie", S} = cookie("Customer", "WILE_E_COYOTE", [{max_age, 111}, {secure, true}]), ?assertMatch( ["Customer=WILE_E_COYOTE", " Version=1", " Expires=" ++ _, " Max-Age=111", " Secure"], string:tokens(S, ";")), ok. cookie_test() -> C1 = {"Set-Cookie", "Customer=WILE_E_COYOTE; " "Version=1; " "Path=/acme"}, C1 = cookie("Customer", "WILE_E_COYOTE", [{path, "/acme"}]), C1 = cookie("Customer", "WILE_E_COYOTE", [{path, "/acme"}, {badoption, "negatory"}]), C1 = cookie('Customer', 'WILE_E_COYOTE', [{path, '/acme'}]), C1 = cookie(<<"Customer">>, <<"WILE_E_COYOTE">>, [{path, <<"/acme">>}]), {"Set-Cookie","=NoKey; Version=1"} = cookie("", "NoKey", []), {"Set-Cookie","=NoKey; Version=1"} = cookie("", "NoKey"), LocalTime = calendar:universal_time_to_local_time({{2007, 5, 15}, {13, 45, 33}}), C2 = {"Set-Cookie", "Customer=WILE_E_COYOTE; " "Version=1; " "Expires=Tue, 15-May-2007 13:45:33 GMT; " "Max-Age=0"}, C2 = cookie("Customer", "WILE_E_COYOTE", [{max_age, -111}, {local_time, LocalTime}]), C3 = {"Set-Cookie", "Customer=WILE_E_COYOTE; " "Version=1; " "Expires=Wed, 16-May-2007 13:45:50 GMT; " "Max-Age=86417"}, C3 = cookie("Customer", "WILE_E_COYOTE", [{max_age, 86417}, {local_time, LocalTime}]), ok. -endif. rabbitmq-server-3.2.4/plugins-src/mochiweb-wrapper/mochiweb-git/src/reloader.erl0000644000000000000000000001133512305126066026516 0ustar rootroot%% @copyright 2007 Mochi Media, Inc. %% @author Matthew Dempsky %% %% @doc Erlang module for automatically reloading modified modules %% during development. -module(reloader). -author("Matthew Dempsky "). -include_lib("kernel/include/file.hrl"). -behaviour(gen_server). -export([start/0, start_link/0]). -export([stop/0]). -export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]). -export([all_changed/0]). -export([is_changed/1]). -export([reload_modules/1]). -record(state, {last, tref}). %% External API %% @spec start() -> ServerRet %% @doc Start the reloader. start() -> gen_server:start({local, ?MODULE}, ?MODULE, [], []). %% @spec start_link() -> ServerRet %% @doc Start the reloader. start_link() -> gen_server:start_link({local, ?MODULE}, ?MODULE, [], []). %% @spec stop() -> ok %% @doc Stop the reloader. stop() -> gen_server:call(?MODULE, stop). %% gen_server callbacks %% @spec init([]) -> {ok, State} %% @doc gen_server init, opens the server in an initial state. init([]) -> {ok, TRef} = timer:send_interval(timer:seconds(1), doit), {ok, #state{last = stamp(), tref = TRef}}. %% @spec handle_call(Args, From, State) -> tuple() %% @doc gen_server callback. handle_call(stop, _From, State) -> {stop, shutdown, stopped, State}; handle_call(_Req, _From, State) -> {reply, {error, badrequest}, State}. %% @spec handle_cast(Cast, State) -> tuple() %% @doc gen_server callback. handle_cast(_Req, State) -> {noreply, State}. %% @spec handle_info(Info, State) -> tuple() %% @doc gen_server callback. handle_info(doit, State) -> Now = stamp(), _ = doit(State#state.last, Now), {noreply, State#state{last = Now}}; handle_info(_Info, State) -> {noreply, State}. %% @spec terminate(Reason, State) -> ok %% @doc gen_server termination callback. terminate(_Reason, State) -> {ok, cancel} = timer:cancel(State#state.tref), ok. %% @spec code_change(_OldVsn, State, _Extra) -> State %% @doc gen_server code_change callback (trivial). code_change(_Vsn, State, _Extra) -> {ok, State}. %% @spec reload_modules([atom()]) -> [{module, atom()} | {error, term()}] %% @doc code:purge/1 and code:load_file/1 the given list of modules in order, %% return the results of code:load_file/1. reload_modules(Modules) -> [begin code:purge(M), code:load_file(M) end || M <- Modules]. %% @spec all_changed() -> [atom()] %% @doc Return a list of beam modules that have changed. all_changed() -> [M || {M, Fn} <- code:all_loaded(), is_list(Fn), is_changed(M)]. %% @spec is_changed(atom()) -> boolean() %% @doc true if the loaded module is a beam with a vsn attribute %% and does not match the on-disk beam file, returns false otherwise. is_changed(M) -> try module_vsn(M:module_info()) =/= module_vsn(code:get_object_code(M)) catch _:_ -> false end. %% Internal API module_vsn({M, Beam, _Fn}) -> {ok, {M, Vsn}} = beam_lib:version(Beam), Vsn; module_vsn(L) when is_list(L) -> {_, Attrs} = lists:keyfind(attributes, 1, L), {_, Vsn} = lists:keyfind(vsn, 1, Attrs), Vsn. doit(From, To) -> [case file:read_file_info(Filename) of {ok, #file_info{mtime = Mtime}} when Mtime >= From, Mtime < To -> reload(Module); {ok, _} -> unmodified; {error, enoent} -> %% The Erlang compiler deletes existing .beam files if %% recompiling fails. Maybe it's worth spitting out a %% warning here, but I'd want to limit it to just once. gone; {error, Reason} -> io:format("Error reading ~s's file info: ~p~n", [Filename, Reason]), error end || {Module, Filename} <- code:all_loaded(), is_list(Filename)]. reload(Module) -> io:format("Reloading ~p ...", [Module]), code:purge(Module), case code:load_file(Module) of {module, Module} -> io:format(" ok.~n"), case erlang:function_exported(Module, test, 0) of true -> io:format(" - Calling ~p:test() ...", [Module]), case catch Module:test() of ok -> io:format(" ok.~n"), reload; Reason -> io:format(" fail: ~p.~n", [Reason]), reload_but_test_failed end; false -> reload end; {error, Reason} -> io:format(" fail: ~p.~n", [Reason]), error end. stamp() -> erlang:localtime(). %% %% Tests %% -ifdef(TEST). -include_lib("eunit/include/eunit.hrl"). -endif. rabbitmq-server-3.2.4/plugins-src/mochiweb-wrapper/mochiweb-git/src/mochilists.erl0000644000000000000000000000532712305126066027103 0ustar rootroot%% @copyright Copyright (c) 2010 Mochi Media, Inc. %% @author David Reid %% @doc Utility functions for dealing with proplists. -module(mochilists). -author("David Reid "). -export([get_value/2, get_value/3, is_defined/2, set_default/2, set_defaults/2]). %% @spec set_default({Key::term(), Value::term()}, Proplist::list()) -> list() %% %% @doc Return new Proplist with {Key, Value} set if not is_defined(Key, Proplist). set_default({Key, Value}, Proplist) -> case is_defined(Key, Proplist) of true -> Proplist; false -> [{Key, Value} | Proplist] end. %% @spec set_defaults([{Key::term(), Value::term()}], Proplist::list()) -> list() %% %% @doc Return new Proplist with {Key, Value} set if not is_defined(Key, Proplist). set_defaults(DefaultProps, Proplist) -> lists:foldl(fun set_default/2, Proplist, DefaultProps). %% @spec is_defined(Key::term(), Proplist::list()) -> bool() %% %% @doc Returns true if Propist contains at least one entry associated %% with Key, otherwise false is returned. is_defined(Key, Proplist) -> lists:keyfind(Key, 1, Proplist) =/= false. %% @spec get_value(Key::term(), Proplist::list()) -> term() | undefined %% %% @doc Return the value of Key or undefined get_value(Key, Proplist) -> get_value(Key, Proplist, undefined). %% @spec get_value(Key::term(), Proplist::list(), Default::term()) -> term() %% %% @doc Return the value of Key or Default get_value(_Key, [], Default) -> Default; get_value(Key, Proplist, Default) -> case lists:keyfind(Key, 1, Proplist) of false -> Default; {Key, Value} -> Value end. %% %% Tests %% -ifdef(TEST). -include_lib("eunit/include/eunit.hrl"). set_defaults_test() -> ?assertEqual( [{k, v}], set_defaults([{k, v}], [])), ?assertEqual( [{k, v}], set_defaults([{k, vee}], [{k, v}])), ?assertEqual( lists:sort([{kay, vee}, {k, v}]), lists:sort(set_defaults([{k, vee}, {kay, vee}], [{k, v}]))), ok. set_default_test() -> ?assertEqual( [{k, v}], set_default({k, v}, [])), ?assertEqual( [{k, v}], set_default({k, vee}, [{k, v}])), ok. get_value_test() -> ?assertEqual( undefined, get_value(foo, [])), ?assertEqual( undefined, get_value(foo, [{bar, baz}])), ?assertEqual( bar, get_value(foo, [{foo, bar}])), ?assertEqual( default, get_value(foo, [], default)), ?assertEqual( default, get_value(foo, [{bar, baz}], default)), ?assertEqual( bar, get_value(foo, [{foo, bar}], default)), ok. -endif. rabbitmq-server-3.2.4/plugins-src/mochiweb-wrapper/mochiweb-git/src/mochiweb_util.erl0000644000000000000000000010111412305126066027546 0ustar rootroot%% @author Bob Ippolito %% @copyright 2007 Mochi Media, Inc. %% @doc Utilities for parsing and quoting. -module(mochiweb_util). -author('bob@mochimedia.com'). -export([join/2, quote_plus/1, urlencode/1, parse_qs/1, unquote/1]). -export([path_split/1]). -export([urlsplit/1, urlsplit_path/1, urlunsplit/1, urlunsplit_path/1]). -export([guess_mime/1, parse_header/1]). -export([shell_quote/1, cmd/1, cmd_string/1, cmd_port/2, cmd_status/1, cmd_status/2]). -export([record_to_proplist/2, record_to_proplist/3]). -export([safe_relative_path/1, partition/2]). -export([parse_qvalues/1, pick_accepted_encodings/3]). -export([make_io/1, rand_bytes/1, rand_uniform/2]). -define(PERCENT, 37). % $\% -define(FULLSTOP, 46). % $\. -define(IS_HEX(C), ((C >= $0 andalso C =< $9) orelse (C >= $a andalso C =< $f) orelse (C >= $A andalso C =< $F))). -define(QS_SAFE(C), ((C >= $a andalso C =< $z) orelse (C >= $A andalso C =< $Z) orelse (C >= $0 andalso C =< $9) orelse (C =:= ?FULLSTOP orelse C =:= $- orelse C =:= $~ orelse C =:= $_))). hexdigit(C) when C < 10 -> $0 + C; hexdigit(C) when C < 16 -> $A + (C - 10). unhexdigit(C) when C >= $0, C =< $9 -> C - $0; unhexdigit(C) when C >= $a, C =< $f -> C - $a + 10; unhexdigit(C) when C >= $A, C =< $F -> C - $A + 10. %% @spec partition(String, Sep) -> {String, [], []} | {Prefix, Sep, Postfix} %% @doc Inspired by Python 2.5's str.partition: %% partition("foo/bar", "/") = {"foo", "/", "bar"}, %% partition("foo", "/") = {"foo", "", ""}. partition(String, Sep) -> case partition(String, Sep, []) of undefined -> {String, "", ""}; Result -> Result end. partition("", _Sep, _Acc) -> undefined; partition(S, Sep, Acc) -> case partition2(S, Sep) of undefined -> [C | Rest] = S, partition(Rest, Sep, [C | Acc]); Rest -> {lists:reverse(Acc), Sep, Rest} end. partition2(Rest, "") -> Rest; partition2([C | R1], [C | R2]) -> partition2(R1, R2); partition2(_S, _Sep) -> undefined. %% @spec safe_relative_path(string()) -> string() | undefined %% @doc Return the reduced version of a relative path or undefined if it %% is not safe. safe relative paths can be joined with an absolute path %% and will result in a subdirectory of the absolute path. Safe paths %% never contain a backslash character. safe_relative_path("/" ++ _) -> undefined; safe_relative_path(P) -> case string:chr(P, $\\) of 0 -> safe_relative_path(P, []); _ -> undefined end. safe_relative_path("", Acc) -> case Acc of [] -> ""; _ -> string:join(lists:reverse(Acc), "/") end; safe_relative_path(P, Acc) -> case partition(P, "/") of {"", "/", _} -> %% /foo or foo//bar undefined; {"..", _, _} when Acc =:= [] -> undefined; {"..", _, Rest} -> safe_relative_path(Rest, tl(Acc)); {Part, "/", ""} -> safe_relative_path("", ["", Part | Acc]); {Part, _, Rest} -> safe_relative_path(Rest, [Part | Acc]) end. %% @spec shell_quote(string()) -> string() %% @doc Quote a string according to UNIX shell quoting rules, returns a string %% surrounded by double quotes. shell_quote(L) -> shell_quote(L, [$\"]). %% @spec cmd_port([string()], Options) -> port() %% @doc open_port({spawn, mochiweb_util:cmd_string(Argv)}, Options). cmd_port(Argv, Options) -> open_port({spawn, cmd_string(Argv)}, Options). %% @spec cmd([string()]) -> string() %% @doc os:cmd(cmd_string(Argv)). cmd(Argv) -> os:cmd(cmd_string(Argv)). %% @spec cmd_string([string()]) -> string() %% @doc Create a shell quoted command string from a list of arguments. cmd_string(Argv) -> string:join([shell_quote(X) || X <- Argv], " "). %% @spec cmd_status([string()]) -> {ExitStatus::integer(), Stdout::binary()} %% @doc Accumulate the output and exit status from the given application, %% will be spawned with cmd_port/2. cmd_status(Argv) -> cmd_status(Argv, []). %% @spec cmd_status([string()], [atom()]) -> {ExitStatus::integer(), Stdout::binary()} %% @doc Accumulate the output and exit status from the given application, %% will be spawned with cmd_port/2. cmd_status(Argv, Options) -> Port = cmd_port(Argv, [exit_status, stderr_to_stdout, use_stdio, binary | Options]), try cmd_loop(Port, []) after catch port_close(Port) end. %% @spec cmd_loop(port(), list()) -> {ExitStatus::integer(), Stdout::binary()} %% @doc Accumulate the output and exit status from a port. cmd_loop(Port, Acc) -> receive {Port, {exit_status, Status}} -> {Status, iolist_to_binary(lists:reverse(Acc))}; {Port, {data, Data}} -> cmd_loop(Port, [Data | Acc]) end. %% @spec join([iolist()], iolist()) -> iolist() %% @doc Join a list of strings or binaries together with the given separator %% string or char or binary. The output is flattened, but may be an %% iolist() instead of a string() if any of the inputs are binary(). join([], _Separator) -> []; join([S], _Separator) -> lists:flatten(S); join(Strings, Separator) -> lists:flatten(revjoin(lists:reverse(Strings), Separator, [])). revjoin([], _Separator, Acc) -> Acc; revjoin([S | Rest], Separator, []) -> revjoin(Rest, Separator, [S]); revjoin([S | Rest], Separator, Acc) -> revjoin(Rest, Separator, [S, Separator | Acc]). %% @spec quote_plus(atom() | integer() | float() | string() | binary()) -> string() %% @doc URL safe encoding of the given term. quote_plus(Atom) when is_atom(Atom) -> quote_plus(atom_to_list(Atom)); quote_plus(Int) when is_integer(Int) -> quote_plus(integer_to_list(Int)); quote_plus(Binary) when is_binary(Binary) -> quote_plus(binary_to_list(Binary)); quote_plus(Float) when is_float(Float) -> quote_plus(mochinum:digits(Float)); quote_plus(String) -> quote_plus(String, []). quote_plus([], Acc) -> lists:reverse(Acc); quote_plus([C | Rest], Acc) when ?QS_SAFE(C) -> quote_plus(Rest, [C | Acc]); quote_plus([$\s | Rest], Acc) -> quote_plus(Rest, [$+ | Acc]); quote_plus([C | Rest], Acc) -> <> = <>, quote_plus(Rest, [hexdigit(Lo), hexdigit(Hi), ?PERCENT | Acc]). %% @spec urlencode([{Key, Value}]) -> string() %% @doc URL encode the property list. urlencode(Props) -> Pairs = lists:foldr( fun ({K, V}, Acc) -> [quote_plus(K) ++ "=" ++ quote_plus(V) | Acc] end, [], Props), string:join(Pairs, "&"). %% @spec parse_qs(string() | binary()) -> [{Key, Value}] %% @doc Parse a query string or application/x-www-form-urlencoded. parse_qs(Binary) when is_binary(Binary) -> parse_qs(binary_to_list(Binary)); parse_qs(String) -> parse_qs(String, []). parse_qs([], Acc) -> lists:reverse(Acc); parse_qs(String, Acc) -> {Key, Rest} = parse_qs_key(String), {Value, Rest1} = parse_qs_value(Rest), parse_qs(Rest1, [{Key, Value} | Acc]). parse_qs_key(String) -> parse_qs_key(String, []). parse_qs_key([], Acc) -> {qs_revdecode(Acc), ""}; parse_qs_key([$= | Rest], Acc) -> {qs_revdecode(Acc), Rest}; parse_qs_key(Rest=[$; | _], Acc) -> {qs_revdecode(Acc), Rest}; parse_qs_key(Rest=[$& | _], Acc) -> {qs_revdecode(Acc), Rest}; parse_qs_key([C | Rest], Acc) -> parse_qs_key(Rest, [C | Acc]). parse_qs_value(String) -> parse_qs_value(String, []). parse_qs_value([], Acc) -> {qs_revdecode(Acc), ""}; parse_qs_value([$; | Rest], Acc) -> {qs_revdecode(Acc), Rest}; parse_qs_value([$& | Rest], Acc) -> {qs_revdecode(Acc), Rest}; parse_qs_value([C | Rest], Acc) -> parse_qs_value(Rest, [C | Acc]). %% @spec unquote(string() | binary()) -> string() %% @doc Unquote a URL encoded string. unquote(Binary) when is_binary(Binary) -> unquote(binary_to_list(Binary)); unquote(String) -> qs_revdecode(lists:reverse(String)). qs_revdecode(S) -> qs_revdecode(S, []). qs_revdecode([], Acc) -> Acc; qs_revdecode([$+ | Rest], Acc) -> qs_revdecode(Rest, [$\s | Acc]); qs_revdecode([Lo, Hi, ?PERCENT | Rest], Acc) when ?IS_HEX(Lo), ?IS_HEX(Hi) -> qs_revdecode(Rest, [(unhexdigit(Lo) bor (unhexdigit(Hi) bsl 4)) | Acc]); qs_revdecode([C | Rest], Acc) -> qs_revdecode(Rest, [C | Acc]). %% @spec urlsplit(Url) -> {Scheme, Netloc, Path, Query, Fragment} %% @doc Return a 5-tuple, does not expand % escapes. Only supports HTTP style %% URLs. urlsplit(Url) -> {Scheme, Url1} = urlsplit_scheme(Url), {Netloc, Url2} = urlsplit_netloc(Url1), {Path, Query, Fragment} = urlsplit_path(Url2), {Scheme, Netloc, Path, Query, Fragment}. urlsplit_scheme(Url) -> case urlsplit_scheme(Url, []) of no_scheme -> {"", Url}; Res -> Res end. urlsplit_scheme([C | Rest], Acc) when ((C >= $a andalso C =< $z) orelse (C >= $A andalso C =< $Z) orelse (C >= $0 andalso C =< $9) orelse C =:= $+ orelse C =:= $- orelse C =:= $.) -> urlsplit_scheme(Rest, [C | Acc]); urlsplit_scheme([$: | Rest], Acc=[_ | _]) -> {string:to_lower(lists:reverse(Acc)), Rest}; urlsplit_scheme(_Rest, _Acc) -> no_scheme. urlsplit_netloc("//" ++ Rest) -> urlsplit_netloc(Rest, []); urlsplit_netloc(Path) -> {"", Path}. urlsplit_netloc("", Acc) -> {lists:reverse(Acc), ""}; urlsplit_netloc(Rest=[C | _], Acc) when C =:= $/; C =:= $?; C =:= $# -> {lists:reverse(Acc), Rest}; urlsplit_netloc([C | Rest], Acc) -> urlsplit_netloc(Rest, [C | Acc]). %% @spec path_split(string()) -> {Part, Rest} %% @doc Split a path starting from the left, as in URL traversal. %% path_split("foo/bar") = {"foo", "bar"}, %% path_split("/foo/bar") = {"", "foo/bar"}. path_split(S) -> path_split(S, []). path_split("", Acc) -> {lists:reverse(Acc), ""}; path_split("/" ++ Rest, Acc) -> {lists:reverse(Acc), Rest}; path_split([C | Rest], Acc) -> path_split(Rest, [C | Acc]). %% @spec urlunsplit({Scheme, Netloc, Path, Query, Fragment}) -> string() %% @doc Assemble a URL from the 5-tuple. Path must be absolute. urlunsplit({Scheme, Netloc, Path, Query, Fragment}) -> lists:flatten([case Scheme of "" -> ""; _ -> [Scheme, "://"] end, Netloc, urlunsplit_path({Path, Query, Fragment})]). %% @spec urlunsplit_path({Path, Query, Fragment}) -> string() %% @doc Assemble a URL path from the 3-tuple. urlunsplit_path({Path, Query, Fragment}) -> lists:flatten([Path, case Query of "" -> ""; _ -> [$? | Query] end, case Fragment of "" -> ""; _ -> [$# | Fragment] end]). %% @spec urlsplit_path(Url) -> {Path, Query, Fragment} %% @doc Return a 3-tuple, does not expand % escapes. Only supports HTTP style %% paths. urlsplit_path(Path) -> urlsplit_path(Path, []). urlsplit_path("", Acc) -> {lists:reverse(Acc), "", ""}; urlsplit_path("?" ++ Rest, Acc) -> {Query, Fragment} = urlsplit_query(Rest), {lists:reverse(Acc), Query, Fragment}; urlsplit_path("#" ++ Rest, Acc) -> {lists:reverse(Acc), "", Rest}; urlsplit_path([C | Rest], Acc) -> urlsplit_path(Rest, [C | Acc]). urlsplit_query(Query) -> urlsplit_query(Query, []). urlsplit_query("", Acc) -> {lists:reverse(Acc), ""}; urlsplit_query("#" ++ Rest, Acc) -> {lists:reverse(Acc), Rest}; urlsplit_query([C | Rest], Acc) -> urlsplit_query(Rest, [C | Acc]). %% @spec guess_mime(string()) -> string() %% @doc Guess the mime type of a file by the extension of its filename. guess_mime(File) -> case mochiweb_mime:from_extension(filename:extension(File)) of undefined -> "text/plain"; Mime -> Mime end. %% @spec parse_header(string()) -> {Type, [{K, V}]} %% @doc Parse a Content-Type like header, return the main Content-Type %% and a property list of options. parse_header(String) -> %% TODO: This is exactly as broken as Python's cgi module. %% Should parse properly like mochiweb_cookies. [Type | Parts] = [string:strip(S) || S <- string:tokens(String, ";")], F = fun (S, Acc) -> case lists:splitwith(fun (C) -> C =/= $= end, S) of {"", _} -> %% Skip anything with no name Acc; {_, ""} -> %% Skip anything with no value Acc; {Name, [$\= | Value]} -> [{string:to_lower(string:strip(Name)), unquote_header(string:strip(Value))} | Acc] end end, {string:to_lower(Type), lists:foldr(F, [], Parts)}. unquote_header("\"" ++ Rest) -> unquote_header(Rest, []); unquote_header(S) -> S. unquote_header("", Acc) -> lists:reverse(Acc); unquote_header("\"", Acc) -> lists:reverse(Acc); unquote_header([$\\, C | Rest], Acc) -> unquote_header(Rest, [C | Acc]); unquote_header([C | Rest], Acc) -> unquote_header(Rest, [C | Acc]). %% @spec record_to_proplist(Record, Fields) -> proplist() %% @doc calls record_to_proplist/3 with a default TypeKey of '__record' record_to_proplist(Record, Fields) -> record_to_proplist(Record, Fields, '__record'). %% @spec record_to_proplist(Record, Fields, TypeKey) -> proplist() %% @doc Return a proplist of the given Record with each field in the %% Fields list set as a key with the corresponding value in the Record. %% TypeKey is the key that is used to store the record type %% Fields should be obtained by calling record_info(fields, record_type) %% where record_type is the record type of Record record_to_proplist(Record, Fields, TypeKey) when tuple_size(Record) - 1 =:= length(Fields) -> lists:zip([TypeKey | Fields], tuple_to_list(Record)). shell_quote([], Acc) -> lists:reverse([$\" | Acc]); shell_quote([C | Rest], Acc) when C =:= $\" orelse C =:= $\` orelse C =:= $\\ orelse C =:= $\$ -> shell_quote(Rest, [C, $\\ | Acc]); shell_quote([C | Rest], Acc) -> shell_quote(Rest, [C | Acc]). %% @spec parse_qvalues(string()) -> [qvalue()] | invalid_qvalue_string %% @type qvalue() = {media_type() | encoding() , float()}. %% @type media_type() = string(). %% @type encoding() = string(). %% %% @doc Parses a list (given as a string) of elements with Q values associated %% to them. Elements are separated by commas and each element is separated %% from its Q value by a semicolon. Q values are optional but when missing %% the value of an element is considered as 1.0. A Q value is always in the %% range [0.0, 1.0]. A Q value list is used for example as the value of the %% HTTP "Accept" and "Accept-Encoding" headers. %% %% Q values are described in section 2.9 of the RFC 2616 (HTTP 1.1). %% %% Example: %% %% parse_qvalues("gzip; q=0.5, deflate, identity;q=0.0") -> %% [{"gzip", 0.5}, {"deflate", 1.0}, {"identity", 0.0}] %% parse_qvalues(QValuesStr) -> try lists:map( fun(Pair) -> [Type | Params] = string:tokens(Pair, ";"), NormParams = normalize_media_params(Params), {Q, NonQParams} = extract_q(NormParams), {string:join([string:strip(Type) | NonQParams], ";"), Q} end, string:tokens(string:to_lower(QValuesStr), ",") ) catch _Type:_Error -> invalid_qvalue_string end. normalize_media_params(Params) -> {ok, Re} = re:compile("\\s"), normalize_media_params(Re, Params, []). normalize_media_params(_Re, [], Acc) -> lists:reverse(Acc); normalize_media_params(Re, [Param | Rest], Acc) -> NormParam = re:replace(Param, Re, "", [global, {return, list}]), normalize_media_params(Re, Rest, [NormParam | Acc]). extract_q(NormParams) -> {ok, KVRe} = re:compile("^([^=]+)=([^=]+)$"), {ok, QRe} = re:compile("^((?:0|1)(?:\\.\\d{1,3})?)$"), extract_q(KVRe, QRe, NormParams, []). extract_q(_KVRe, _QRe, [], Acc) -> {1.0, lists:reverse(Acc)}; extract_q(KVRe, QRe, [Param | Rest], Acc) -> case re:run(Param, KVRe, [{capture, [1, 2], list}]) of {match, [Name, Value]} -> case Name of "q" -> {match, [Q]} = re:run(Value, QRe, [{capture, [1], list}]), QVal = case Q of "0" -> 0.0; "1" -> 1.0; Else -> list_to_float(Else) end, case QVal < 0.0 orelse QVal > 1.0 of false -> {QVal, lists:reverse(Acc) ++ Rest} end; _ -> extract_q(KVRe, QRe, Rest, [Param | Acc]) end end. %% @spec pick_accepted_encodings([qvalue()], [encoding()], encoding()) -> %% [encoding()] %% %% @doc Determines which encodings specified in the given Q values list are %% valid according to a list of supported encodings and a default encoding. %% %% The returned list of encodings is sorted, descendingly, according to the %% Q values of the given list. The last element of this list is the given %% default encoding unless this encoding is explicitily or implicitily %% marked with a Q value of 0.0 in the given Q values list. %% Note: encodings with the same Q value are kept in the same order as %% found in the input Q values list. %% %% This encoding picking process is described in section 14.3 of the %% RFC 2616 (HTTP 1.1). %% %% Example: %% %% pick_accepted_encodings( %% [{"gzip", 0.5}, {"deflate", 1.0}], %% ["gzip", "identity"], %% "identity" %% ) -> %% ["gzip", "identity"] %% pick_accepted_encodings(AcceptedEncs, SupportedEncs, DefaultEnc) -> SortedQList = lists:reverse( lists:sort(fun({_, Q1}, {_, Q2}) -> Q1 < Q2 end, AcceptedEncs) ), {Accepted, Refused} = lists:foldr( fun({E, Q}, {A, R}) -> case Q > 0.0 of true -> {[E | A], R}; false -> {A, [E | R]} end end, {[], []}, SortedQList ), Refused1 = lists:foldr( fun(Enc, Acc) -> case Enc of "*" -> lists:subtract(SupportedEncs, Accepted) ++ Acc; _ -> [Enc | Acc] end end, [], Refused ), Accepted1 = lists:foldr( fun(Enc, Acc) -> case Enc of "*" -> lists:subtract(SupportedEncs, Accepted ++ Refused1) ++ Acc; _ -> [Enc | Acc] end end, [], Accepted ), Accepted2 = case lists:member(DefaultEnc, Accepted1) of true -> Accepted1; false -> Accepted1 ++ [DefaultEnc] end, [E || E <- Accepted2, lists:member(E, SupportedEncs), not lists:member(E, Refused1)]. make_io(Atom) when is_atom(Atom) -> atom_to_list(Atom); make_io(Integer) when is_integer(Integer) -> integer_to_list(Integer); make_io(Io) when is_list(Io); is_binary(Io) -> Io. rand_bytes(Count) -> list_to_binary([rand_uniform(0, 16#FF + 1) || _ <- lists:seq(1, Count)]). rand_uniform(Lo, Hi) -> random:uniform(Hi - Lo) + Lo - 1. %% %% Tests %% -ifdef(TEST). -include_lib("eunit/include/eunit.hrl"). make_io_test() -> ?assertEqual( <<"atom">>, iolist_to_binary(make_io(atom))), ?assertEqual( <<"20">>, iolist_to_binary(make_io(20))), ?assertEqual( <<"list">>, iolist_to_binary(make_io("list"))), ?assertEqual( <<"binary">>, iolist_to_binary(make_io(<<"binary">>))), ok. -record(test_record, {field1=f1, field2=f2}). record_to_proplist_test() -> ?assertEqual( [{'__record', test_record}, {field1, f1}, {field2, f2}], record_to_proplist(#test_record{}, record_info(fields, test_record))), ?assertEqual( [{'typekey', test_record}, {field1, f1}, {field2, f2}], record_to_proplist(#test_record{}, record_info(fields, test_record), typekey)), ok. shell_quote_test() -> ?assertEqual( "\"foo \\$bar\\\"\\`' baz\"", shell_quote("foo $bar\"`' baz")), ok. cmd_port_test_spool(Port, Acc) -> receive {Port, eof} -> Acc; {Port, {data, {eol, Data}}} -> cmd_port_test_spool(Port, ["\n", Data | Acc]); {Port, Unknown} -> throw({unknown, Unknown}) after 1000 -> throw(timeout) end. cmd_port_test() -> Port = cmd_port(["echo", "$bling$ `word`!"], [eof, stream, {line, 4096}]), Res = try lists:append(lists:reverse(cmd_port_test_spool(Port, []))) after catch port_close(Port) end, self() ! {Port, wtf}, try cmd_port_test_spool(Port, []) catch throw:{unknown, wtf} -> ok end, try cmd_port_test_spool(Port, []) catch throw:timeout -> ok end, ?assertEqual( "$bling$ `word`!\n", Res). cmd_test() -> ?assertEqual( "$bling$ `word`!\n", cmd(["echo", "$bling$ `word`!"])), ok. cmd_string_test() -> ?assertEqual( "\"echo\" \"\\$bling\\$ \\`word\\`!\"", cmd_string(["echo", "$bling$ `word`!"])), ok. cmd_status_test() -> ?assertEqual( {0, <<"$bling$ `word`!\n">>}, cmd_status(["echo", "$bling$ `word`!"])), ok. parse_header_test() -> ?assertEqual( {"multipart/form-data", [{"boundary", "AaB03x"}]}, parse_header("multipart/form-data; boundary=AaB03x")), %% This tests (currently) intentionally broken behavior ?assertEqual( {"multipart/form-data", [{"b", ""}, {"cgi", "is"}, {"broken", "true\"e"}]}, parse_header("multipart/form-data;b=;cgi=\"i\\s;broken=true\"e;=z;z")), ok. guess_mime_test() -> "text/plain" = guess_mime(""), "text/plain" = guess_mime(".text"), "application/zip" = guess_mime(".zip"), "application/zip" = guess_mime("x.zip"), "text/html" = guess_mime("x.html"), "application/xhtml+xml" = guess_mime("x.xhtml"), ok. path_split_test() -> {"", "foo/bar"} = path_split("/foo/bar"), {"foo", "bar"} = path_split("foo/bar"), {"bar", ""} = path_split("bar"), ok. urlsplit_test() -> {"", "", "/foo", "", "bar?baz"} = urlsplit("/foo#bar?baz"), {"http", "host:port", "/foo", "", "bar?baz"} = urlsplit("http://host:port/foo#bar?baz"), {"http", "host", "", "", ""} = urlsplit("http://host"), {"", "", "/wiki/Category:Fruit", "", ""} = urlsplit("/wiki/Category:Fruit"), ok. urlsplit_path_test() -> {"/foo/bar", "", ""} = urlsplit_path("/foo/bar"), {"/foo", "baz", ""} = urlsplit_path("/foo?baz"), {"/foo", "", "bar?baz"} = urlsplit_path("/foo#bar?baz"), {"/foo", "", "bar?baz#wibble"} = urlsplit_path("/foo#bar?baz#wibble"), {"/foo", "bar", "baz"} = urlsplit_path("/foo?bar#baz"), {"/foo", "bar?baz", "baz"} = urlsplit_path("/foo?bar?baz#baz"), ok. urlunsplit_test() -> "/foo#bar?baz" = urlunsplit({"", "", "/foo", "", "bar?baz"}), "http://host:port/foo#bar?baz" = urlunsplit({"http", "host:port", "/foo", "", "bar?baz"}), ok. urlunsplit_path_test() -> "/foo/bar" = urlunsplit_path({"/foo/bar", "", ""}), "/foo?baz" = urlunsplit_path({"/foo", "baz", ""}), "/foo#bar?baz" = urlunsplit_path({"/foo", "", "bar?baz"}), "/foo#bar?baz#wibble" = urlunsplit_path({"/foo", "", "bar?baz#wibble"}), "/foo?bar#baz" = urlunsplit_path({"/foo", "bar", "baz"}), "/foo?bar?baz#baz" = urlunsplit_path({"/foo", "bar?baz", "baz"}), ok. join_test() -> ?assertEqual("foo,bar,baz", join(["foo", "bar", "baz"], $,)), ?assertEqual("foo,bar,baz", join(["foo", "bar", "baz"], ",")), ?assertEqual("foo bar", join([["foo", " bar"]], ",")), ?assertEqual("foo bar,baz", join([["foo", " bar"], "baz"], ",")), ?assertEqual("foo", join(["foo"], ",")), ?assertEqual("foobarbaz", join(["foo", "bar", "baz"], "")), ?assertEqual("foo" ++ [<<>>] ++ "bar" ++ [<<>>] ++ "baz", join(["foo", "bar", "baz"], <<>>)), ?assertEqual("foobar" ++ [<<"baz">>], join(["foo", "bar", <<"baz">>], "")), ?assertEqual("", join([], "any")), ok. quote_plus_test() -> "foo" = quote_plus(foo), "1" = quote_plus(1), "1.1" = quote_plus(1.1), "foo" = quote_plus("foo"), "foo+bar" = quote_plus("foo bar"), "foo%0A" = quote_plus("foo\n"), "foo%0A" = quote_plus("foo\n"), "foo%3B%26%3D" = quote_plus("foo;&="), "foo%3B%26%3D" = quote_plus(<<"foo;&=">>), ok. unquote_test() -> ?assertEqual("foo bar", unquote("foo+bar")), ?assertEqual("foo bar", unquote("foo%20bar")), ?assertEqual("foo\r\n", unquote("foo%0D%0A")), ?assertEqual("foo\r\n", unquote(<<"foo%0D%0A">>)), ok. urlencode_test() -> "foo=bar&baz=wibble+%0D%0A&z=1" = urlencode([{foo, "bar"}, {"baz", "wibble \r\n"}, {z, 1}]), ok. parse_qs_test() -> ?assertEqual( [{"foo", "bar"}, {"baz", "wibble \r\n"}, {"z", "1"}], parse_qs("foo=bar&baz=wibble+%0D%0a&z=1")), ?assertEqual( [{"", "bar"}, {"baz", "wibble \r\n"}, {"z", ""}], parse_qs("=bar&baz=wibble+%0D%0a&z=")), ?assertEqual( [{"foo", "bar"}, {"baz", "wibble \r\n"}, {"z", "1"}], parse_qs(<<"foo=bar&baz=wibble+%0D%0a&z=1">>)), ?assertEqual( [], parse_qs("")), ?assertEqual( [{"foo", ""}, {"bar", ""}, {"baz", ""}], parse_qs("foo;bar&baz")), ok. partition_test() -> {"foo", "", ""} = partition("foo", "/"), {"foo", "/", "bar"} = partition("foo/bar", "/"), {"foo", "/", ""} = partition("foo/", "/"), {"", "/", "bar"} = partition("/bar", "/"), {"f", "oo/ba", "r"} = partition("foo/bar", "oo/ba"), ok. safe_relative_path_test() -> "foo" = safe_relative_path("foo"), "foo/" = safe_relative_path("foo/"), "foo" = safe_relative_path("foo/bar/.."), "bar" = safe_relative_path("foo/../bar"), "bar/" = safe_relative_path("foo/../bar/"), "" = safe_relative_path("foo/.."), "" = safe_relative_path("foo/../"), undefined = safe_relative_path("/foo"), undefined = safe_relative_path("../foo"), undefined = safe_relative_path("foo/../.."), undefined = safe_relative_path("foo//"), undefined = safe_relative_path("foo\\bar"), ok. parse_qvalues_test() -> [] = parse_qvalues(""), [{"identity", 0.0}] = parse_qvalues("identity;q=0"), [{"identity", 0.0}] = parse_qvalues("identity ;q=0"), [{"identity", 0.0}] = parse_qvalues(" identity; q =0 "), [{"identity", 0.0}] = parse_qvalues("identity ; q = 0"), [{"identity", 0.0}] = parse_qvalues("identity ; q= 0.0"), [{"gzip", 1.0}, {"deflate", 1.0}, {"identity", 0.0}] = parse_qvalues( "gzip,deflate,identity;q=0.0" ), [{"deflate", 1.0}, {"gzip", 1.0}, {"identity", 0.0}] = parse_qvalues( "deflate,gzip,identity;q=0.0" ), [{"gzip", 1.0}, {"deflate", 1.0}, {"gzip", 1.0}, {"identity", 0.0}] = parse_qvalues("gzip,deflate,gzip,identity;q=0"), [{"gzip", 1.0}, {"deflate", 1.0}, {"identity", 0.0}] = parse_qvalues( "gzip, deflate , identity; q=0.0" ), [{"gzip", 1.0}, {"deflate", 1.0}, {"identity", 0.0}] = parse_qvalues( "gzip; q=1, deflate;q=1.0, identity;q=0.0" ), [{"gzip", 0.5}, {"deflate", 1.0}, {"identity", 0.0}] = parse_qvalues( "gzip; q=0.5, deflate;q=1.0, identity;q=0" ), [{"gzip", 0.5}, {"deflate", 1.0}, {"identity", 0.0}] = parse_qvalues( "gzip; q=0.5, deflate , identity;q=0.0" ), [{"gzip", 0.5}, {"deflate", 0.8}, {"identity", 0.0}] = parse_qvalues( "gzip; q=0.5, deflate;q=0.8, identity;q=0.0" ), [{"gzip", 0.5}, {"deflate", 1.0}, {"identity", 1.0}] = parse_qvalues( "gzip; q=0.5,deflate,identity" ), [{"gzip", 0.5}, {"deflate", 1.0}, {"identity", 1.0}, {"identity", 1.0}] = parse_qvalues("gzip; q=0.5,deflate,identity, identity "), [{"text/html;level=1", 1.0}, {"text/plain", 0.5}] = parse_qvalues("text/html;level=1, text/plain;q=0.5"), [{"text/html;level=1", 0.3}, {"text/plain", 1.0}] = parse_qvalues("text/html;level=1;q=0.3, text/plain"), [{"text/html;level=1", 0.3}, {"text/plain", 1.0}] = parse_qvalues("text/html; level = 1; q = 0.3, text/plain"), [{"text/html;level=1", 0.3}, {"text/plain", 1.0}] = parse_qvalues("text/html;q=0.3;level=1, text/plain"), invalid_qvalue_string = parse_qvalues("gzip; q=1.1, deflate"), invalid_qvalue_string = parse_qvalues("gzip; q=0.5, deflate;q=2"), invalid_qvalue_string = parse_qvalues("gzip, deflate;q=AB"), invalid_qvalue_string = parse_qvalues("gzip; q=2.1, deflate"), invalid_qvalue_string = parse_qvalues("gzip; q=0.1234, deflate"), invalid_qvalue_string = parse_qvalues("text/html;level=1;q=0.3, text/html;level"), ok. pick_accepted_encodings_test() -> ["identity"] = pick_accepted_encodings( [], ["gzip", "identity"], "identity" ), ["gzip", "identity"] = pick_accepted_encodings( [{"gzip", 1.0}], ["gzip", "identity"], "identity" ), ["identity"] = pick_accepted_encodings( [{"gzip", 0.0}], ["gzip", "identity"], "identity" ), ["gzip", "identity"] = pick_accepted_encodings( [{"gzip", 1.0}, {"deflate", 1.0}], ["gzip", "identity"], "identity" ), ["gzip", "identity"] = pick_accepted_encodings( [{"gzip", 0.5}, {"deflate", 1.0}], ["gzip", "identity"], "identity" ), ["identity"] = pick_accepted_encodings( [{"gzip", 0.0}, {"deflate", 0.0}], ["gzip", "identity"], "identity" ), ["gzip"] = pick_accepted_encodings( [{"gzip", 1.0}, {"deflate", 1.0}, {"identity", 0.0}], ["gzip", "identity"], "identity" ), ["gzip", "deflate", "identity"] = pick_accepted_encodings( [{"gzip", 1.0}, {"deflate", 1.0}], ["gzip", "deflate", "identity"], "identity" ), ["gzip", "deflate"] = pick_accepted_encodings( [{"gzip", 1.0}, {"deflate", 1.0}, {"identity", 0.0}], ["gzip", "deflate", "identity"], "identity" ), ["deflate", "gzip", "identity"] = pick_accepted_encodings( [{"gzip", 0.2}, {"deflate", 1.0}], ["gzip", "deflate", "identity"], "identity" ), ["deflate", "deflate", "gzip", "identity"] = pick_accepted_encodings( [{"gzip", 0.2}, {"deflate", 1.0}, {"deflate", 1.0}], ["gzip", "deflate", "identity"], "identity" ), ["deflate", "gzip", "gzip", "identity"] = pick_accepted_encodings( [{"gzip", 0.2}, {"deflate", 1.0}, {"gzip", 1.0}], ["gzip", "deflate", "identity"], "identity" ), ["gzip", "deflate", "gzip", "identity"] = pick_accepted_encodings( [{"gzip", 0.2}, {"deflate", 0.9}, {"gzip", 1.0}], ["gzip", "deflate", "identity"], "identity" ), [] = pick_accepted_encodings( [{"*", 0.0}], ["gzip", "deflate", "identity"], "identity" ), ["gzip", "deflate", "identity"] = pick_accepted_encodings( [{"*", 1.0}], ["gzip", "deflate", "identity"], "identity" ), ["gzip", "deflate", "identity"] = pick_accepted_encodings( [{"*", 0.6}], ["gzip", "deflate", "identity"], "identity" ), ["gzip"] = pick_accepted_encodings( [{"gzip", 1.0}, {"*", 0.0}], ["gzip", "deflate", "identity"], "identity" ), ["gzip", "deflate"] = pick_accepted_encodings( [{"gzip", 1.0}, {"deflate", 0.6}, {"*", 0.0}], ["gzip", "deflate", "identity"], "identity" ), ["deflate", "gzip"] = pick_accepted_encodings( [{"gzip", 0.5}, {"deflate", 1.0}, {"*", 0.0}], ["gzip", "deflate", "identity"], "identity" ), ["gzip", "identity"] = pick_accepted_encodings( [{"deflate", 0.0}, {"*", 1.0}], ["gzip", "deflate", "identity"], "identity" ), ["gzip", "identity"] = pick_accepted_encodings( [{"*", 1.0}, {"deflate", 0.0}], ["gzip", "deflate", "identity"], "identity" ), ok. -endif. rabbitmq-server-3.2.4/plugins-src/mochiweb-wrapper/mochiweb-git/src/mochiutf8.erl0000644000000000000000000002650312305126066026632 0ustar rootroot%% @copyright 2010 Mochi Media, Inc. %% @author Bob Ippolito %% @doc Algorithm to convert any binary to a valid UTF-8 sequence by ignoring %% invalid bytes. -module(mochiutf8). -export([valid_utf8_bytes/1, codepoint_to_bytes/1, codepoints_to_bytes/1]). -export([bytes_to_codepoints/1, bytes_foldl/3, codepoint_foldl/3]). -export([read_codepoint/1, len/1]). %% External API %% -type unichar_low() :: 0..16#d7ff. %% -type unichar_high() :: 16#e000..16#10ffff. %% -type unichar() :: unichar_low() | unichar_high(). %% -spec codepoint_to_bytes(unichar()) -> binary(). %% @doc Convert a unicode codepoint to UTF-8 bytes. codepoint_to_bytes(C) when (C >= 16#00 andalso C =< 16#7f) -> %% U+0000 - U+007F - 7 bits <>; codepoint_to_bytes(C) when (C >= 16#080 andalso C =< 16#07FF) -> %% U+0080 - U+07FF - 11 bits <<0:5, B1:5, B0:6>> = <>, <<2#110:3, B1:5, 2#10:2, B0:6>>; codepoint_to_bytes(C) when (C >= 16#0800 andalso C =< 16#FFFF) andalso (C < 16#D800 orelse C > 16#DFFF) -> %% U+0800 - U+FFFF - 16 bits (excluding UTC-16 surrogate code points) <> = <>, <<2#1110:4, B2:4, 2#10:2, B1:6, 2#10:2, B0:6>>; codepoint_to_bytes(C) when (C >= 16#010000 andalso C =< 16#10FFFF) -> %% U+10000 - U+10FFFF - 21 bits <<0:3, B3:3, B2:6, B1:6, B0:6>> = <>, <<2#11110:5, B3:3, 2#10:2, B2:6, 2#10:2, B1:6, 2#10:2, B0:6>>. %% -spec codepoints_to_bytes([unichar()]) -> binary(). %% @doc Convert a list of codepoints to a UTF-8 binary. codepoints_to_bytes(L) -> <<<<(codepoint_to_bytes(C))/binary>> || C <- L>>. %% -spec read_codepoint(binary()) -> {unichar(), binary(), binary()}. read_codepoint(Bin = <<2#0:1, C:7, Rest/binary>>) -> %% U+0000 - U+007F - 7 bits <> = Bin, {C, B, Rest}; read_codepoint(Bin = <<2#110:3, B1:5, 2#10:2, B0:6, Rest/binary>>) -> %% U+0080 - U+07FF - 11 bits case <> of <> when C >= 16#80 -> <> = Bin, {C, B, Rest} end; read_codepoint(Bin = <<2#1110:4, B2:4, 2#10:2, B1:6, 2#10:2, B0:6, Rest/binary>>) -> %% U+0800 - U+FFFF - 16 bits (excluding UTC-16 surrogate code points) case <> of <> when (C >= 16#0800 andalso C =< 16#FFFF) andalso (C < 16#D800 orelse C > 16#DFFF) -> <> = Bin, {C, B, Rest} end; read_codepoint(Bin = <<2#11110:5, B3:3, 2#10:2, B2:6, 2#10:2, B1:6, 2#10:2, B0:6, Rest/binary>>) -> %% U+10000 - U+10FFFF - 21 bits case <> of <> when (C >= 16#010000 andalso C =< 16#10FFFF) -> <> = Bin, {C, B, Rest} end. %% -spec codepoint_foldl(fun((unichar(), _) -> _), _, binary()) -> _. codepoint_foldl(F, Acc, <<>>) when is_function(F, 2) -> Acc; codepoint_foldl(F, Acc, Bin) -> {C, _, Rest} = read_codepoint(Bin), codepoint_foldl(F, F(C, Acc), Rest). %% -spec bytes_foldl(fun((binary(), _) -> _), _, binary()) -> _. bytes_foldl(F, Acc, <<>>) when is_function(F, 2) -> Acc; bytes_foldl(F, Acc, Bin) -> {_, B, Rest} = read_codepoint(Bin), bytes_foldl(F, F(B, Acc), Rest). %% -spec bytes_to_codepoints(binary()) -> [unichar()]. bytes_to_codepoints(B) -> lists:reverse(codepoint_foldl(fun (C, Acc) -> [C | Acc] end, [], B)). %% -spec len(binary()) -> non_neg_integer(). len(<<>>) -> 0; len(B) -> {_, _, Rest} = read_codepoint(B), 1 + len(Rest). %% -spec valid_utf8_bytes(B::binary()) -> binary(). %% @doc Return only the bytes in B that represent valid UTF-8. Uses %% the following recursive algorithm: skip one byte if B does not %% follow UTF-8 syntax (a 1-4 byte encoding of some number), %% skip sequence of 2-4 bytes if it represents an overlong encoding %% or bad code point (surrogate U+D800 - U+DFFF or > U+10FFFF). valid_utf8_bytes(B) when is_binary(B) -> binary_skip_bytes(B, invalid_utf8_indexes(B)). %% Internal API %% -spec binary_skip_bytes(binary(), [non_neg_integer()]) -> binary(). %% @doc Return B, but skipping the 0-based indexes in L. binary_skip_bytes(B, []) -> B; binary_skip_bytes(B, L) -> binary_skip_bytes(B, L, 0, []). %% @private %% -spec binary_skip_bytes(binary(), [non_neg_integer()], non_neg_integer(), iolist()) -> binary(). binary_skip_bytes(B, [], _N, Acc) -> iolist_to_binary(lists:reverse([B | Acc])); binary_skip_bytes(<<_, RestB/binary>>, [N | RestL], N, Acc) -> binary_skip_bytes(RestB, RestL, 1 + N, Acc); binary_skip_bytes(<>, L, N, Acc) -> binary_skip_bytes(RestB, L, 1 + N, [C | Acc]). %% -spec invalid_utf8_indexes(binary()) -> [non_neg_integer()]. %% @doc Return the 0-based indexes in B that are not valid UTF-8. invalid_utf8_indexes(B) -> invalid_utf8_indexes(B, 0, []). %% @private. %% -spec invalid_utf8_indexes(binary(), non_neg_integer(), [non_neg_integer()]) -> [non_neg_integer()]. invalid_utf8_indexes(<>, N, Acc) when C < 16#80 -> %% U+0000 - U+007F - 7 bits invalid_utf8_indexes(Rest, 1 + N, Acc); invalid_utf8_indexes(<>, N, Acc) when C1 band 16#E0 =:= 16#C0, C2 band 16#C0 =:= 16#80 -> %% U+0080 - U+07FF - 11 bits case ((C1 band 16#1F) bsl 6) bor (C2 band 16#3F) of C when C < 16#80 -> %% Overlong encoding. invalid_utf8_indexes(Rest, 2 + N, [1 + N, N | Acc]); _ -> %% Upper bound U+07FF does not need to be checked invalid_utf8_indexes(Rest, 2 + N, Acc) end; invalid_utf8_indexes(<>, N, Acc) when C1 band 16#F0 =:= 16#E0, C2 band 16#C0 =:= 16#80, C3 band 16#C0 =:= 16#80 -> %% U+0800 - U+FFFF - 16 bits case ((((C1 band 16#0F) bsl 6) bor (C2 band 16#3F)) bsl 6) bor (C3 band 16#3F) of C when (C < 16#800) orelse (C >= 16#D800 andalso C =< 16#DFFF) -> %% Overlong encoding or surrogate. invalid_utf8_indexes(Rest, 3 + N, [2 + N, 1 + N, N | Acc]); _ -> %% Upper bound U+FFFF does not need to be checked invalid_utf8_indexes(Rest, 3 + N, Acc) end; invalid_utf8_indexes(<>, N, Acc) when C1 band 16#F8 =:= 16#F0, C2 band 16#C0 =:= 16#80, C3 band 16#C0 =:= 16#80, C4 band 16#C0 =:= 16#80 -> %% U+10000 - U+10FFFF - 21 bits case ((((((C1 band 16#0F) bsl 6) bor (C2 band 16#3F)) bsl 6) bor (C3 band 16#3F)) bsl 6) bor (C4 band 16#3F) of C when (C < 16#10000) orelse (C > 16#10FFFF) -> %% Overlong encoding or invalid code point. invalid_utf8_indexes(Rest, 4 + N, [3 + N, 2 + N, 1 + N, N | Acc]); _ -> invalid_utf8_indexes(Rest, 4 + N, Acc) end; invalid_utf8_indexes(<<_, Rest/binary>>, N, Acc) -> %% Invalid char invalid_utf8_indexes(Rest, 1 + N, [N | Acc]); invalid_utf8_indexes(<<>>, _N, Acc) -> lists:reverse(Acc). %% %% Tests %% -ifdef(TEST). -include_lib("eunit/include/eunit.hrl"). binary_skip_bytes_test() -> ?assertEqual(<<"foo">>, binary_skip_bytes(<<"foo">>, [])), ?assertEqual(<<"foobar">>, binary_skip_bytes(<<"foo bar">>, [3])), ?assertEqual(<<"foo">>, binary_skip_bytes(<<"foo bar">>, [3, 4, 5, 6])), ?assertEqual(<<"oo bar">>, binary_skip_bytes(<<"foo bar">>, [0])), ok. invalid_utf8_indexes_test() -> ?assertEqual( [], invalid_utf8_indexes(<<"unicode snowman for you: ", 226, 152, 131>>)), ?assertEqual( [0], invalid_utf8_indexes(<<128>>)), ?assertEqual( [57,59,60,64,66,67], invalid_utf8_indexes(<<"Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; (", 167, 65, 170, 186, 73, 83, 80, 166, 87, 186, 217, 41, 41>>)), ok. codepoint_to_bytes_test() -> %% U+0000 - U+007F - 7 bits %% U+0080 - U+07FF - 11 bits %% U+0800 - U+FFFF - 16 bits (excluding UTC-16 surrogate code points) %% U+10000 - U+10FFFF - 21 bits ?assertEqual( <<"a">>, codepoint_to_bytes($a)), ?assertEqual( <<16#c2, 16#80>>, codepoint_to_bytes(16#80)), ?assertEqual( <<16#df, 16#bf>>, codepoint_to_bytes(16#07ff)), ?assertEqual( <<16#ef, 16#bf, 16#bf>>, codepoint_to_bytes(16#ffff)), ?assertEqual( <<16#f4, 16#8f, 16#bf, 16#bf>>, codepoint_to_bytes(16#10ffff)), ok. bytes_foldl_test() -> ?assertEqual( <<"abc">>, bytes_foldl(fun (B, Acc) -> <> end, <<>>, <<"abc">>)), ?assertEqual( <<"abc", 226, 152, 131, 228, 184, 173, 194, 133, 244,143,191,191>>, bytes_foldl(fun (B, Acc) -> <> end, <<>>, <<"abc", 226, 152, 131, 228, 184, 173, 194, 133, 244,143,191,191>>)), ok. bytes_to_codepoints_test() -> ?assertEqual( "abc" ++ [16#2603, 16#4e2d, 16#85, 16#10ffff], bytes_to_codepoints(<<"abc", 226, 152, 131, 228, 184, 173, 194, 133, 244,143,191,191>>)), ok. codepoint_foldl_test() -> ?assertEqual( "cba", codepoint_foldl(fun (C, Acc) -> [C | Acc] end, [], <<"abc">>)), ?assertEqual( [16#10ffff, 16#85, 16#4e2d, 16#2603 | "cba"], codepoint_foldl(fun (C, Acc) -> [C | Acc] end, [], <<"abc", 226, 152, 131, 228, 184, 173, 194, 133, 244,143,191,191>>)), ok. len_test() -> ?assertEqual( 29, len(<<"unicode snowman for you: ", 226, 152, 131, 228, 184, 173, 194, 133, 244, 143, 191, 191>>)), ok. codepoints_to_bytes_test() -> ?assertEqual( iolist_to_binary(lists:map(fun codepoint_to_bytes/1, lists:seq(1, 1000))), codepoints_to_bytes(lists:seq(1, 1000))), ok. valid_utf8_bytes_test() -> ?assertEqual( <<"invalid U+11ffff: ">>, valid_utf8_bytes(<<"invalid U+11ffff: ", 244, 159, 191, 191>>)), ?assertEqual( <<"U+10ffff: ", 244, 143, 191, 191>>, valid_utf8_bytes(<<"U+10ffff: ", 244, 143, 191, 191>>)), ?assertEqual( <<"overlong 2-byte encoding (a): ">>, valid_utf8_bytes(<<"overlong 2-byte encoding (a): ", 2#11000001, 2#10100001>>)), ?assertEqual( <<"overlong 2-byte encoding (!): ">>, valid_utf8_bytes(<<"overlong 2-byte encoding (!): ", 2#11000000, 2#10100001>>)), ?assertEqual( <<"mu: ", 194, 181>>, valid_utf8_bytes(<<"mu: ", 194, 181>>)), ?assertEqual( <<"bad coding bytes: ">>, valid_utf8_bytes(<<"bad coding bytes: ", 2#10011111, 2#10111111, 2#11111111>>)), ?assertEqual( <<"low surrogate (unpaired): ">>, valid_utf8_bytes(<<"low surrogate (unpaired): ", 237, 176, 128>>)), ?assertEqual( <<"high surrogate (unpaired): ">>, valid_utf8_bytes(<<"high surrogate (unpaired): ", 237, 191, 191>>)), ?assertEqual( <<"unicode snowman for you: ", 226, 152, 131>>, valid_utf8_bytes(<<"unicode snowman for you: ", 226, 152, 131>>)), ?assertEqual( <<"Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; (AISPW))">>, valid_utf8_bytes(<<"Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; (", 167, 65, 170, 186, 73, 83, 80, 166, 87, 186, 217, 41, 41>>)), ok. -endif. rabbitmq-server-3.2.4/plugins-src/mochiweb-wrapper/mochiweb-git/src/mochiweb_http.erl0000644000000000000000000002264512305126066027563 0ustar rootroot%% @author Bob Ippolito %% @copyright 2007 Mochi Media, Inc. %% @doc HTTP server. -module(mochiweb_http). -author('bob@mochimedia.com'). -export([start/1, start_link/1, stop/0, stop/1]). -export([loop/2]). -export([after_response/2, reentry/1]). -export([parse_range_request/1, range_skip_length/2]). -define(REQUEST_RECV_TIMEOUT, 300000). %% timeout waiting for request line -define(HEADERS_RECV_TIMEOUT, 30000). %% timeout waiting for headers -define(MAX_HEADERS, 1000). -define(DEFAULTS, [{name, ?MODULE}, {port, 8888}]). parse_options(Options) -> {loop, HttpLoop} = proplists:lookup(loop, Options), Loop = {?MODULE, loop, [HttpLoop]}, Options1 = [{loop, Loop} | proplists:delete(loop, Options)], mochilists:set_defaults(?DEFAULTS, Options1). stop() -> mochiweb_socket_server:stop(?MODULE). stop(Name) -> mochiweb_socket_server:stop(Name). %% @spec start(Options) -> ServerRet %% Options = [option()] %% Option = {name, atom()} | {ip, string() | tuple()} | {backlog, integer()} %% | {nodelay, boolean()} | {acceptor_pool_size, integer()} %% | {ssl, boolean()} | {profile_fun, undefined | (Props) -> ok} %% | {link, false} %% @doc Start a mochiweb server. %% profile_fun is used to profile accept timing. %% After each accept, if defined, profile_fun is called with a proplist of a subset of the mochiweb_socket_server state and timing information. %% The proplist is as follows: [{name, Name}, {port, Port}, {active_sockets, ActiveSockets}, {timing, Timing}]. %% @end start(Options) -> mochiweb_socket_server:start(parse_options(Options)). start_link(Options) -> mochiweb_socket_server:start_link(parse_options(Options)). loop(Socket, Body) -> ok = mochiweb_socket:setopts(Socket, [{packet, http}]), request(Socket, Body). -ifdef(gen_tcp_r15b_workaround). -define(R15B_GEN_TCP_FIX, {tcp_error,_,emsgsize} -> % R15B02 returns this then closes the socket, so close and exit mochiweb_socket:close(Socket), exit(normal); ). -else. -define(R15B_GEN_TCP_FIX,). -endif. request(Socket, Body) -> ok = mochiweb_socket:setopts(Socket, [{active, once}]), receive {Protocol, _, {http_request, Method, Path, Version}} when Protocol == http orelse Protocol == ssl -> ok = mochiweb_socket:setopts(Socket, [{packet, httph}]), headers(Socket, {Method, Path, Version}, [], Body, 0); {Protocol, _, {http_error, "\r\n"}} when Protocol == http orelse Protocol == ssl -> request(Socket, Body); {Protocol, _, {http_error, "\n"}} when Protocol == http orelse Protocol == ssl -> request(Socket, Body); {tcp_closed, _} -> mochiweb_socket:close(Socket), exit(normal); {ssl_closed, _} -> mochiweb_socket:close(Socket), exit(normal); ?R15B_GEN_TCP_FIX _Other -> handle_invalid_request(Socket) after ?REQUEST_RECV_TIMEOUT -> mochiweb_socket:close(Socket), exit(normal) end. reentry(Body) -> fun (Req) -> ?MODULE:after_response(Body, Req) end. headers(Socket, Request, Headers, _Body, ?MAX_HEADERS) -> %% Too many headers sent, bad request. ok = mochiweb_socket:setopts(Socket, [{packet, raw}]), handle_invalid_request(Socket, Request, Headers); headers(Socket, Request, Headers, Body, HeaderCount) -> ok = mochiweb_socket:setopts(Socket, [{active, once}]), receive {Protocol, _, http_eoh} when Protocol == http orelse Protocol == ssl -> Req = new_request(Socket, Request, Headers), call_body(Body, Req), ?MODULE:after_response(Body, Req); {Protocol, _, {http_header, _, Name, _, Value}} when Protocol == http orelse Protocol == ssl -> headers(Socket, Request, [{Name, Value} | Headers], Body, 1 + HeaderCount); {tcp_closed, _} -> mochiweb_socket:close(Socket), exit(normal); ?R15B_GEN_TCP_FIX _Other -> handle_invalid_request(Socket, Request, Headers) after ?HEADERS_RECV_TIMEOUT -> mochiweb_socket:close(Socket), exit(normal) end. call_body({M, F, A}, Req) -> erlang:apply(M, F, [Req | A]); call_body({M, F}, Req) -> M:F(Req); call_body(Body, Req) -> Body(Req). %% -spec handle_invalid_request(term()) -> no_return(). handle_invalid_request(Socket) -> handle_invalid_request(Socket, {'GET', {abs_path, "/"}, {0,9}}, []), exit(normal). %% -spec handle_invalid_request(term(), term(), term()) -> no_return(). handle_invalid_request(Socket, Request, RevHeaders) -> Req = new_request(Socket, Request, RevHeaders), Req:respond({400, [], []}), mochiweb_socket:close(Socket), exit(normal). new_request(Socket, Request, RevHeaders) -> ok = mochiweb_socket:setopts(Socket, [{packet, raw}]), mochiweb:new_request({Socket, Request, lists:reverse(RevHeaders)}). after_response(Body, Req) -> Socket = Req:get(socket), case Req:should_close() of true -> mochiweb_socket:close(Socket), exit(normal); false -> Req:cleanup(), erlang:garbage_collect(), ?MODULE:loop(Socket, Body) end. parse_range_request("bytes=0-") -> undefined; parse_range_request(RawRange) when is_list(RawRange) -> try "bytes=" ++ RangeString = RawRange, Ranges = string:tokens(RangeString, ","), lists:map(fun ("-" ++ V) -> {none, list_to_integer(V)}; (R) -> case string:tokens(R, "-") of [S1, S2] -> {list_to_integer(S1), list_to_integer(S2)}; [S] -> {list_to_integer(S), none} end end, Ranges) catch _:_ -> fail end. range_skip_length(Spec, Size) -> case Spec of {none, R} when R =< Size, R >= 0 -> {Size - R, R}; {none, _OutOfRange} -> {0, Size}; {R, none} when R >= 0, R < Size -> {R, Size - R}; {_OutOfRange, none} -> invalid_range; {Start, End} when 0 =< Start, Start =< End, End < Size -> {Start, End - Start + 1}; {Start, End} when 0 =< Start, Start =< End, End >= Size -> {Start, Size - Start}; {_OutOfRange, _End} -> invalid_range end. %% %% Tests %% -ifdef(TEST). -include_lib("eunit/include/eunit.hrl"). range_test() -> %% valid, single ranges ?assertEqual([{20, 30}], parse_range_request("bytes=20-30")), ?assertEqual([{20, none}], parse_range_request("bytes=20-")), ?assertEqual([{none, 20}], parse_range_request("bytes=-20")), %% trivial single range ?assertEqual(undefined, parse_range_request("bytes=0-")), %% invalid, single ranges ?assertEqual(fail, parse_range_request("")), ?assertEqual(fail, parse_range_request("garbage")), ?assertEqual(fail, parse_range_request("bytes=-20-30")), %% valid, multiple range ?assertEqual( [{20, 30}, {50, 100}, {110, 200}], parse_range_request("bytes=20-30,50-100,110-200")), ?assertEqual( [{20, none}, {50, 100}, {none, 200}], parse_range_request("bytes=20-,50-100,-200")), %% no ranges ?assertEqual([], parse_range_request("bytes=")), ok. range_skip_length_test() -> Body = <<"012345678901234567890123456789012345678901234567890123456789">>, BodySize = byte_size(Body), %% 60 BodySize = 60, %% these values assume BodySize =:= 60 ?assertEqual({1,9}, range_skip_length({1,9}, BodySize)), %% 1-9 ?assertEqual({10,10}, range_skip_length({10,19}, BodySize)), %% 10-19 ?assertEqual({40, 20}, range_skip_length({none, 20}, BodySize)), %% -20 ?assertEqual({30, 30}, range_skip_length({30, none}, BodySize)), %% 30- %% valid edge cases for range_skip_length ?assertEqual({BodySize, 0}, range_skip_length({none, 0}, BodySize)), ?assertEqual({0, BodySize}, range_skip_length({none, BodySize}, BodySize)), ?assertEqual({0, BodySize}, range_skip_length({0, none}, BodySize)), BodySizeLess1 = BodySize - 1, ?assertEqual({BodySizeLess1, 1}, range_skip_length({BodySize - 1, none}, BodySize)), ?assertEqual({BodySizeLess1, 1}, range_skip_length({BodySize - 1, BodySize+5}, BodySize)), ?assertEqual({BodySizeLess1, 1}, range_skip_length({BodySize - 1, BodySize}, BodySize)), %% out of range, return whole thing ?assertEqual({0, BodySize}, range_skip_length({none, BodySize + 1}, BodySize)), ?assertEqual({0, BodySize}, range_skip_length({none, -1}, BodySize)), ?assertEqual({0, BodySize}, range_skip_length({0, BodySize + 1}, BodySize)), %% invalid ranges ?assertEqual(invalid_range, range_skip_length({-1, 30}, BodySize)), ?assertEqual(invalid_range, range_skip_length({-1, BodySize + 1}, BodySize)), ?assertEqual(invalid_range, range_skip_length({BodySize, 40}, BodySize)), ?assertEqual(invalid_range, range_skip_length({-1, none}, BodySize)), ?assertEqual(invalid_range, range_skip_length({BodySize, none}, BodySize)), ok. -endif. rabbitmq-server-3.2.4/plugins-src/mochiweb-wrapper/mochiweb-git/src/mochifmt.erl0000644000000000000000000003541412305126066026533 0ustar rootroot%% @author Bob Ippolito %% @copyright 2008 Mochi Media, Inc. %% @doc String Formatting for Erlang, inspired by Python 2.6 %% (PEP 3101). %% -module(mochifmt). -author('bob@mochimedia.com'). -export([format/2, format_field/2, convert_field/2, get_value/2, get_field/2]). -export([tokenize/1, format/3, get_field/3, format_field/3]). -export([bformat/2, bformat/3]). -export([f/2, f/3]). -record(conversion, {length, precision, ctype, align, fill_char, sign}). %% @spec tokenize(S::string()) -> tokens() %% @doc Tokenize a format string into mochifmt's internal format. tokenize(S) -> {?MODULE, tokenize(S, "", [])}. %% @spec convert_field(Arg, Conversion::conversion()) -> term() %% @doc Process Arg according to the given explicit conversion specifier. convert_field(Arg, "") -> Arg; convert_field(Arg, "r") -> repr(Arg); convert_field(Arg, "s") -> str(Arg). %% @spec get_value(Key::string(), Args::args()) -> term() %% @doc Get the Key from Args. If Args is a tuple then convert Key to %% an integer and get element(1 + Key, Args). If Args is a list and Key %% can be parsed as an integer then use lists:nth(1 + Key, Args), %% otherwise try and look for Key in Args as a proplist, converting %% Key to an atom or binary if necessary. get_value(Key, Args) when is_tuple(Args) -> element(1 + list_to_integer(Key), Args); get_value(Key, Args) when is_list(Args) -> try lists:nth(1 + list_to_integer(Key), Args) catch error:_ -> {_K, V} = proplist_lookup(Key, Args), V end. %% @spec get_field(Key::string(), Args) -> term() %% @doc Consecutively call get_value/2 on parts of Key delimited by ".", %% replacing Args with the result of the previous get_value. This %% is used to implement formats such as {0.0}. get_field(Key, Args) -> get_field(Key, Args, ?MODULE). %% @spec get_field(Key::string(), Args, Module) -> term() %% @doc Consecutively call Module:get_value/2 on parts of Key delimited by ".", %% replacing Args with the result of the previous get_value. This %% is used to implement formats such as {0.0}. get_field(Key, Args, Module) -> {Name, Next} = lists:splitwith(fun (C) -> C =/= $. end, Key), Res = try Module:get_value(Name, Args) catch error:undef -> get_value(Name, Args) end, case Next of "" -> Res; "." ++ S1 -> get_field(S1, Res, Module) end. %% @spec format(Format::string(), Args) -> iolist() %% @doc Format Args with Format. format(Format, Args) -> format(Format, Args, ?MODULE). %% @spec format(Format::string(), Args, Module) -> iolist() %% @doc Format Args with Format using Module. format({?MODULE, Parts}, Args, Module) -> format2(Parts, Args, Module, []); format(S, Args, Module) -> format(tokenize(S), Args, Module). %% @spec format_field(Arg, Format) -> iolist() %% @doc Format Arg with Format. format_field(Arg, Format) -> format_field(Arg, Format, ?MODULE). %% @spec format_field(Arg, Format, _Module) -> iolist() %% @doc Format Arg with Format. format_field(Arg, Format, _Module) -> F = default_ctype(Arg, parse_std_conversion(Format)), fix_padding(fix_sign(convert2(Arg, F), F), F). %% @spec f(Format::string(), Args) -> string() %% @doc Format Args with Format and return a string(). f(Format, Args) -> f(Format, Args, ?MODULE). %% @spec f(Format::string(), Args, Module) -> string() %% @doc Format Args with Format using Module and return a string(). f(Format, Args, Module) -> case lists:member(${, Format) of true -> binary_to_list(bformat(Format, Args, Module)); false -> Format end. %% @spec bformat(Format::string(), Args) -> binary() %% @doc Format Args with Format and return a binary(). bformat(Format, Args) -> iolist_to_binary(format(Format, Args)). %% @spec bformat(Format::string(), Args, Module) -> binary() %% @doc Format Args with Format using Module and return a binary(). bformat(Format, Args, Module) -> iolist_to_binary(format(Format, Args, Module)). %% Internal API add_raw("", Acc) -> Acc; add_raw(S, Acc) -> [{raw, lists:reverse(S)} | Acc]. tokenize([], S, Acc) -> lists:reverse(add_raw(S, Acc)); tokenize("{{" ++ Rest, S, Acc) -> tokenize(Rest, "{" ++ S, Acc); tokenize("{" ++ Rest, S, Acc) -> {Format, Rest1} = tokenize_format(Rest), tokenize(Rest1, "", [{format, make_format(Format)} | add_raw(S, Acc)]); tokenize("}}" ++ Rest, S, Acc) -> tokenize(Rest, "}" ++ S, Acc); tokenize([C | Rest], S, Acc) -> tokenize(Rest, [C | S], Acc). tokenize_format(S) -> tokenize_format(S, 1, []). tokenize_format("}" ++ Rest, 1, Acc) -> {lists:reverse(Acc), Rest}; tokenize_format("}" ++ Rest, N, Acc) -> tokenize_format(Rest, N - 1, "}" ++ Acc); tokenize_format("{" ++ Rest, N, Acc) -> tokenize_format(Rest, 1 + N, "{" ++ Acc); tokenize_format([C | Rest], N, Acc) -> tokenize_format(Rest, N, [C | Acc]). make_format(S) -> {Name0, Spec} = case lists:splitwith(fun (C) -> C =/= $: end, S) of {_, ""} -> {S, ""}; {SN, ":" ++ SS} -> {SN, SS} end, {Name, Transform} = case lists:splitwith(fun (C) -> C =/= $! end, Name0) of {_, ""} -> {Name0, ""}; {TN, "!" ++ TT} -> {TN, TT} end, {Name, Transform, Spec}. proplist_lookup(S, P) -> A = try list_to_existing_atom(S) catch error:_ -> make_ref() end, B = try list_to_binary(S) catch error:_ -> make_ref() end, proplist_lookup2({S, A, B}, P). proplist_lookup2({KS, KA, KB}, [{K, V} | _]) when KS =:= K orelse KA =:= K orelse KB =:= K -> {K, V}; proplist_lookup2(Keys, [_ | Rest]) -> proplist_lookup2(Keys, Rest). format2([], _Args, _Module, Acc) -> lists:reverse(Acc); format2([{raw, S} | Rest], Args, Module, Acc) -> format2(Rest, Args, Module, [S | Acc]); format2([{format, {Key, Convert, Format0}} | Rest], Args, Module, Acc) -> Format = f(Format0, Args, Module), V = case Module of ?MODULE -> V0 = get_field(Key, Args), V1 = convert_field(V0, Convert), format_field(V1, Format); _ -> V0 = try Module:get_field(Key, Args) catch error:undef -> get_field(Key, Args, Module) end, V1 = try Module:convert_field(V0, Convert) catch error:undef -> convert_field(V0, Convert) end, try Module:format_field(V1, Format) catch error:undef -> format_field(V1, Format, Module) end end, format2(Rest, Args, Module, [V | Acc]). default_ctype(_Arg, C=#conversion{ctype=N}) when N =/= undefined -> C; default_ctype(Arg, C) when is_integer(Arg) -> C#conversion{ctype=decimal}; default_ctype(Arg, C) when is_float(Arg) -> C#conversion{ctype=general}; default_ctype(_Arg, C) -> C#conversion{ctype=string}. fix_padding(Arg, #conversion{length=undefined}) -> Arg; fix_padding(Arg, F=#conversion{length=Length, fill_char=Fill0, align=Align0, ctype=Type}) -> Padding = Length - iolist_size(Arg), Fill = case Fill0 of undefined -> $\s; _ -> Fill0 end, Align = case Align0 of undefined -> case Type of string -> left; _ -> right end; _ -> Align0 end, case Padding > 0 of true -> do_padding(Arg, Padding, Fill, Align, F); false -> Arg end. do_padding(Arg, Padding, Fill, right, _F) -> [lists:duplicate(Padding, Fill), Arg]; do_padding(Arg, Padding, Fill, center, _F) -> LPadding = lists:duplicate(Padding div 2, Fill), RPadding = case Padding band 1 of 1 -> [Fill | LPadding]; _ -> LPadding end, [LPadding, Arg, RPadding]; do_padding([$- | Arg], Padding, Fill, sign_right, _F) -> [[$- | lists:duplicate(Padding, Fill)], Arg]; do_padding(Arg, Padding, Fill, sign_right, #conversion{sign=$-}) -> [lists:duplicate(Padding, Fill), Arg]; do_padding([S | Arg], Padding, Fill, sign_right, #conversion{sign=S}) -> [[S | lists:duplicate(Padding, Fill)], Arg]; do_padding(Arg, Padding, Fill, sign_right, #conversion{sign=undefined}) -> [lists:duplicate(Padding, Fill), Arg]; do_padding(Arg, Padding, Fill, left, _F) -> [Arg | lists:duplicate(Padding, Fill)]. fix_sign(Arg, #conversion{sign=$+}) when Arg >= 0 -> [$+, Arg]; fix_sign(Arg, #conversion{sign=$\s}) when Arg >= 0 -> [$\s, Arg]; fix_sign(Arg, _F) -> Arg. ctype($\%) -> percent; ctype($s) -> string; ctype($b) -> bin; ctype($o) -> oct; ctype($X) -> upper_hex; ctype($x) -> hex; ctype($c) -> char; ctype($d) -> decimal; ctype($g) -> general; ctype($f) -> fixed; ctype($e) -> exp. align($<) -> left; align($>) -> right; align($^) -> center; align($=) -> sign_right. convert2(Arg, F=#conversion{ctype=percent}) -> [convert2(100.0 * Arg, F#conversion{ctype=fixed}), $\%]; convert2(Arg, #conversion{ctype=string}) -> str(Arg); convert2(Arg, #conversion{ctype=bin}) -> erlang:integer_to_list(Arg, 2); convert2(Arg, #conversion{ctype=oct}) -> erlang:integer_to_list(Arg, 8); convert2(Arg, #conversion{ctype=upper_hex}) -> erlang:integer_to_list(Arg, 16); convert2(Arg, #conversion{ctype=hex}) -> string:to_lower(erlang:integer_to_list(Arg, 16)); convert2(Arg, #conversion{ctype=char}) when Arg < 16#80 -> [Arg]; convert2(Arg, #conversion{ctype=char}) -> xmerl_ucs:to_utf8(Arg); convert2(Arg, #conversion{ctype=decimal}) -> integer_to_list(Arg); convert2(Arg, #conversion{ctype=general, precision=undefined}) -> try mochinum:digits(Arg) catch error:undef -> io_lib:format("~g", [Arg]) end; convert2(Arg, #conversion{ctype=fixed, precision=undefined}) -> io_lib:format("~f", [Arg]); convert2(Arg, #conversion{ctype=exp, precision=undefined}) -> io_lib:format("~e", [Arg]); convert2(Arg, #conversion{ctype=general, precision=P}) -> io_lib:format("~." ++ integer_to_list(P) ++ "g", [Arg]); convert2(Arg, #conversion{ctype=fixed, precision=P}) -> io_lib:format("~." ++ integer_to_list(P) ++ "f", [Arg]); convert2(Arg, #conversion{ctype=exp, precision=P}) -> io_lib:format("~." ++ integer_to_list(P) ++ "e", [Arg]). str(A) when is_atom(A) -> atom_to_list(A); str(I) when is_integer(I) -> integer_to_list(I); str(F) when is_float(F) -> try mochinum:digits(F) catch error:undef -> io_lib:format("~g", [F]) end; str(L) when is_list(L) -> L; str(B) when is_binary(B) -> B; str(P) -> repr(P). repr(P) when is_float(P) -> try mochinum:digits(P) catch error:undef -> float_to_list(P) end; repr(P) -> io_lib:format("~p", [P]). parse_std_conversion(S) -> parse_std_conversion(S, #conversion{}). parse_std_conversion("", Acc) -> Acc; parse_std_conversion([Fill, Align | Spec], Acc) when Align =:= $< orelse Align =:= $> orelse Align =:= $= orelse Align =:= $^ -> parse_std_conversion(Spec, Acc#conversion{fill_char=Fill, align=align(Align)}); parse_std_conversion([Align | Spec], Acc) when Align =:= $< orelse Align =:= $> orelse Align =:= $= orelse Align =:= $^ -> parse_std_conversion(Spec, Acc#conversion{align=align(Align)}); parse_std_conversion([Sign | Spec], Acc) when Sign =:= $+ orelse Sign =:= $- orelse Sign =:= $\s -> parse_std_conversion(Spec, Acc#conversion{sign=Sign}); parse_std_conversion("0" ++ Spec, Acc) -> Align = case Acc#conversion.align of undefined -> sign_right; A -> A end, parse_std_conversion(Spec, Acc#conversion{fill_char=$0, align=Align}); parse_std_conversion(Spec=[D|_], Acc) when D >= $0 andalso D =< $9 -> {W, Spec1} = lists:splitwith(fun (C) -> C >= $0 andalso C =< $9 end, Spec), parse_std_conversion(Spec1, Acc#conversion{length=list_to_integer(W)}); parse_std_conversion([$. | Spec], Acc) -> case lists:splitwith(fun (C) -> C >= $0 andalso C =< $9 end, Spec) of {"", Spec1} -> parse_std_conversion(Spec1, Acc); {P, Spec1} -> parse_std_conversion(Spec1, Acc#conversion{precision=list_to_integer(P)}) end; parse_std_conversion([Type], Acc) -> parse_std_conversion("", Acc#conversion{ctype=ctype(Type)}). %% %% Tests %% -ifdef(TEST). -include_lib("eunit/include/eunit.hrl"). tokenize_test() -> {?MODULE, [{raw, "ABC"}]} = tokenize("ABC"), {?MODULE, [{format, {"0", "", ""}}]} = tokenize("{0}"), {?MODULE, [{raw, "ABC"}, {format, {"1", "", ""}}, {raw, "DEF"}]} = tokenize("ABC{1}DEF"), ok. format_test() -> <<" -4">> = bformat("{0:4}", [-4]), <<" 4">> = bformat("{0:4}", [4]), <<" 4">> = bformat("{0:{0}}", [4]), <<"4 ">> = bformat("{0:4}", ["4"]), <<"4 ">> = bformat("{0:{0}}", ["4"]), <<"1.2yoDEF">> = bformat("{2}{0}{1}{3}", {yo, "DE", 1.2, <<"F">>}), <<"cafebabe">> = bformat("{0:x}", {16#cafebabe}), <<"CAFEBABE">> = bformat("{0:X}", {16#cafebabe}), <<"CAFEBABE">> = bformat("{0:X}", {16#cafebabe}), <<"755">> = bformat("{0:o}", {8#755}), <<"a">> = bformat("{0:c}", {97}), %% Horizontal ellipsis <<226, 128, 166>> = bformat("{0:c}", {16#2026}), <<"11">> = bformat("{0:b}", {3}), <<"11">> = bformat("{0:b}", [3]), <<"11">> = bformat("{three:b}", [{three, 3}]), <<"11">> = bformat("{three:b}", [{"three", 3}]), <<"11">> = bformat("{three:b}", [{<<"three">>, 3}]), <<"\"foo\"">> = bformat("{0!r}", {"foo"}), <<"2008-5-4">> = bformat("{0.0}-{0.1}-{0.2}", {{2008,5,4}}), <<"2008-05-04">> = bformat("{0.0:04}-{0.1:02}-{0.2:02}", {{2008,5,4}}), <<"foo6bar-6">> = bformat("foo{1}{0}-{1}", {bar, 6}), <<"-'atom test'-">> = bformat("-{arg!r}-", [{arg, 'atom test'}]), <<"2008-05-04">> = bformat("{0.0:0{1.0}}-{0.1:0{1.1}}-{0.2:0{1.2}}", {{2008,5,4}, {4, 2, 2}}), ok. std_test() -> M = mochifmt_std:new(), <<"01">> = bformat("{0}{1}", [0, 1], M), ok. records_test() -> M = mochifmt_records:new([{conversion, record_info(fields, conversion)}]), R = #conversion{length=long, precision=hard, sign=peace}, long = M:get_value("length", R), hard = M:get_value("precision", R), peace = M:get_value("sign", R), <<"long hard">> = bformat("{length} {precision}", R, M), <<"long hard">> = bformat("{0.length} {0.precision}", [R], M), ok. -endif. rabbitmq-server-3.2.4/plugins-src/mochiweb-wrapper/mochiweb-git/src/mochifmt_records.erl0000644000000000000000000000206612305126066030251 0ustar rootroot%% @author Bob Ippolito %% @copyright 2008 Mochi Media, Inc. %% @doc Formatter that understands records. %% %% Usage: %% %% 1> M = mochifmt_records:new([{rec, record_info(fields, rec)}]), %% M:format("{0.bar}", [#rec{bar=foo}]). %% foo -module(mochifmt_records). -author('bob@mochimedia.com'). -export([new/1, get_value/3]). new([{_Rec, RecFields}]=Recs) when is_list(RecFields) -> {?MODULE, Recs}. get_value(Key, Rec, {?MODULE, Recs}) when is_tuple(Rec) and is_atom(element(1, Rec)) -> try begin Atom = list_to_existing_atom(Key), {_, Fields} = proplists:lookup(element(1, Rec), Recs), element(get_rec_index(Atom, Fields, 2), Rec) end catch error:_ -> mochifmt:get_value(Key, Rec) end; get_value(Key, Args, {?MODULE, _Recs}) -> mochifmt:get_value(Key, Args). get_rec_index(Atom, [Atom | _], Index) -> Index; get_rec_index(Atom, [_ | Rest], Index) -> get_rec_index(Atom, Rest, 1 + Index). %% %% Tests %% -ifdef(TEST). -include_lib("eunit/include/eunit.hrl"). -endif. rabbitmq-server-3.2.4/plugins-src/mochiweb-wrapper/mochiweb-git/src/mochiweb_response.erl0000644000000000000000000000442512305126066030436 0ustar rootroot%% @author Bob Ippolito %% @copyright 2007 Mochi Media, Inc. %% @doc Response abstraction. -module(mochiweb_response). -author('bob@mochimedia.com'). -define(QUIP, "Any of you quaids got a smint?"). -export([new/3, get_header_value/2, get/2, dump/1]). -export([send/2, write_chunk/2]). %% @type response(). A mochiweb_response parameterized module instance. %% @spec new(Request, Code, Headers) -> response() %% @doc Create a new mochiweb_response instance. new(Request, Code, Headers) -> {?MODULE, [Request, Code, Headers]}. %% @spec get_header_value(string() | atom() | binary(), response()) -> %% string() | undefined %% @doc Get the value of the given response header. get_header_value(K, {?MODULE, [_Request, _Code, Headers]}) -> mochiweb_headers:get_value(K, Headers). %% @spec get(request | code | headers, response()) -> term() %% @doc Return the internal representation of the given field. get(request, {?MODULE, [Request, _Code, _Headers]}) -> Request; get(code, {?MODULE, [_Request, Code, _Headers]}) -> Code; get(headers, {?MODULE, [_Request, _Code, Headers]}) -> Headers. %% @spec dump(response()) -> {mochiweb_request, [{atom(), term()}]} %% @doc Dump the internal representation to a "human readable" set of terms %% for debugging/inspection purposes. dump({?MODULE, [Request, Code, Headers]}) -> [{request, Request:dump()}, {code, Code}, {headers, mochiweb_headers:to_list(Headers)}]. %% @spec send(iodata(), response()) -> ok %% @doc Send data over the socket if the method is not HEAD. send(Data, {?MODULE, [Request, _Code, _Headers]}) -> case Request:get(method) of 'HEAD' -> ok; _ -> Request:send(Data) end. %% @spec write_chunk(iodata(), response()) -> ok %% @doc Write a chunk of a HTTP chunked response. If Data is zero length, %% then the chunked response will be finished. write_chunk(Data, {?MODULE, [Request, _Code, _Headers]}=THIS) -> case Request:get(version) of Version when Version >= {1, 1} -> Length = iolist_size(Data), send([io_lib:format("~.16b\r\n", [Length]), Data, <<"\r\n">>], THIS); _ -> send(Data, THIS) end. %% %% Tests %% -ifdef(TEST). -include_lib("eunit/include/eunit.hrl"). -endif. rabbitmq-server-3.2.4/plugins-src/mochiweb-wrapper/mochiweb-git/src/mochiweb_io.erl0000644000000000000000000000212712305126066027204 0ustar rootroot%% @author Bob Ippolito %% @copyright 2007 Mochi Media, Inc. %% @doc Utilities for dealing with IO devices (open files). -module(mochiweb_io). -author('bob@mochimedia.com'). -export([iodevice_stream/3, iodevice_stream/2]). -export([iodevice_foldl/4, iodevice_foldl/3]). -export([iodevice_size/1]). -define(READ_SIZE, 8192). iodevice_foldl(F, Acc, IoDevice) -> iodevice_foldl(F, Acc, IoDevice, ?READ_SIZE). iodevice_foldl(F, Acc, IoDevice, BufferSize) -> case file:read(IoDevice, BufferSize) of eof -> Acc; {ok, Data} -> iodevice_foldl(F, F(Data, Acc), IoDevice, BufferSize) end. iodevice_stream(Callback, IoDevice) -> iodevice_stream(Callback, IoDevice, ?READ_SIZE). iodevice_stream(Callback, IoDevice, BufferSize) -> F = fun (Data, ok) -> Callback(Data) end, ok = iodevice_foldl(F, ok, IoDevice, BufferSize). iodevice_size(IoDevice) -> {ok, Size} = file:position(IoDevice, eof), {ok, 0} = file:position(IoDevice, bof), Size. %% %% Tests %% -ifdef(TEST). -include_lib("eunit/include/eunit.hrl"). -endif. rabbitmq-server-3.2.4/plugins-src/mochiweb-wrapper/mochiweb-git/src/mochiweb_session.erl0000644000000000000000000001603312305126066030261 0ustar rootroot%% @author Asier Azkuenaga Batiz %% @doc HTTP Cookie session. Note that the expiration time travels unencrypted %% as far as this module is concerned. In order to achieve more security, %% it is advised to use https. %% Based on the paper %% %% "A Secure Cookie Protocol". %% This module is only supported on R15B02 and later, the AES CFB mode is not %% available in earlier releases of crypto. -module(mochiweb_session). -export([generate_session_data/4, generate_session_cookie/4, check_session_cookie/4]). -export_types([expiration_time/0]). -type expiration_time() :: integer(). -type key_fun() :: fun((string()) -> iolist()). %% TODO: Import this from elsewhere after attribute types refactor. -type header() :: {string(), string()}. %% @doc Generates a secure encrypted binary convining all the parameters. The %% expiration time must be a 32-bit integer. %% -spec generate_session_data( %% ExpirationTime :: expiration_time(), %% Data :: iolist(), %% FSessionKey :: key_fun(), %% ServerKey :: iolist()) -> binary(). generate_session_data(ExpirationTime, Data, FSessionKey, ServerKey) when is_integer(ExpirationTime), is_function(FSessionKey)-> BData = ensure_binary(Data), ExpTime = integer_to_list(ExpirationTime), Key = gen_key(ExpTime, ServerKey), Hmac = gen_hmac(ExpTime, BData, FSessionKey(ExpTime), Key), EData = encrypt_data(BData, Key), mochiweb_base64url:encode( <>). %% @doc Convenience wrapper for generate_session_data that returns a %% mochiweb cookie with "id" as the key, a max_age of 20000 seconds, %% and the current local time as local time. %% -spec generate_session_cookie( %% ExpirationTime :: expiration_time(), %% Data :: iolist(), %% FSessionKey :: key_fun(), %% ServerKey :: iolist()) -> header(). generate_session_cookie(ExpirationTime, Data, FSessionKey, ServerKey) when is_integer(ExpirationTime), is_function(FSessionKey)-> CookieData = generate_session_data(ExpirationTime, Data, FSessionKey, ServerKey), mochiweb_cookies:cookie("id", CookieData, [{max_age, 20000}, {local_time, calendar:universal_time_to_local_time( calendar:universal_time())}]). %% TODO: This return type is messy to express in the type system. %% -spec check_session_cookie( %% ECookie :: binary(), %% ExpirationTime :: string(), %% FSessionKey :: key_fun(), %% ServerKey :: iolist()) -> %% {Success :: boolean(), %% ExpTimeAndData :: [integer() | binary()]}. check_session_cookie(ECookie, ExpirationTime, FSessionKey, ServerKey) when is_binary(ECookie), is_integer(ExpirationTime), is_function(FSessionKey) -> case mochiweb_base64url:decode(ECookie) of <> -> ETString = integer_to_list(ExpirationTime1), Key = gen_key(ETString, ServerKey), Data = decrypt_data(EData, Key), Hmac2 = gen_hmac(ETString, Data, FSessionKey(ETString), Key), {ExpirationTime1 >= ExpirationTime andalso eq(Hmac2, BHmac), [ExpirationTime1, binary_to_list(Data)]}; _ -> {false, []} end; check_session_cookie(_ECookie, _ExpirationTime, _FSessionKey, _ServerKey) -> {false, []}. %% 'Constant' time =:= operator for binary, to mitigate timing attacks. %% -spec eq(binary(), binary()) -> boolean(). eq(A, B) when is_binary(A) andalso is_binary(B) -> eq(A, B, 0). eq(<>, <>, Acc) -> eq(As, Bs, Acc bor (A bxor B)); eq(<<>>, <<>>, 0) -> true; eq(_As, _Bs, _Acc) -> false. %% -spec ensure_binary(iolist()) -> binary(). ensure_binary(B) when is_binary(B) -> B; ensure_binary(L) when is_list(L) -> iolist_to_binary(L). %% -spec encrypt_data(binary(), binary()) -> binary(). encrypt_data(Data, Key) -> IV = crypto:rand_bytes(16), Crypt = crypto:aes_cfb_128_encrypt(Key, IV, Data), <>. %% -spec decrypt_data(binary(), binary()) -> binary(). decrypt_data(<>, Key) -> crypto:aes_cfb_128_decrypt(Key, IV, Crypt). %% -spec gen_key(iolist(), iolist()) -> binary(). gen_key(ExpirationTime, ServerKey)-> crypto:md5_mac(ServerKey, [ExpirationTime]). %% -spec gen_hmac(iolist(), binary(), iolist(), binary()) -> binary(). gen_hmac(ExpirationTime, Data, SessionKey, Key) -> crypto:sha_mac(Key, [ExpirationTime, Data, SessionKey]). -ifdef(TEST). -include_lib("eunit/include/eunit.hrl"). generate_check_session_cookie_test_() -> {setup, fun setup_server_key/0, fun generate_check_session_cookie/1}. setup_server_key() -> crypto:start(), ["adfasdfasfs",30000]. generate_check_session_cookie([ServerKey, TS]) -> Id = fun (A) -> A end, TSFuture = TS + 1000, TSPast = TS - 1, [?_assertEqual( {true, [TSFuture, "alice"]}, check_session_cookie( generate_session_data(TSFuture, "alice", Id, ServerKey), TS, Id, ServerKey)), ?_assertEqual( {true, [TSFuture, "alice and"]}, check_session_cookie( generate_session_data(TSFuture, "alice and", Id, ServerKey), TS, Id, ServerKey)), ?_assertEqual( {true, [TSFuture, "alice and"]}, check_session_cookie( generate_session_data(TSFuture, "alice and", Id, ServerKey), TS, Id,ServerKey)), ?_assertEqual( {true, [TSFuture, "alice and bob"]}, check_session_cookie( generate_session_data(TSFuture, "alice and bob", Id, ServerKey), TS, Id, ServerKey)), ?_assertEqual( {true, [TSFuture, "alice jlkjfkjsdfg sdkfjgldsjgl"]}, check_session_cookie( generate_session_data(TSFuture, "alice jlkjfkjsdfg sdkfjgldsjgl", Id, ServerKey), TS, Id, ServerKey)), ?_assertEqual( {true, [TSFuture, "alice .'¡'ç+-$%/(&\""]}, check_session_cookie( generate_session_data(TSFuture, "alice .'¡'ç+-$%/(&\"" ,Id, ServerKey), TS, Id, ServerKey)), ?_assertEqual( {true,[TSFuture,"alice456689875"]}, check_session_cookie( generate_session_data(TSFuture, ["alice","456689875"], Id, ServerKey), TS, Id, ServerKey)), ?_assertError( function_clause, check_session_cookie( generate_session_data(TSFuture, {tuple,one}, Id, ServerKey), TS, Id,ServerKey)), ?_assertEqual( {false, [TSPast, "bob"]}, check_session_cookie( generate_session_data(TSPast, "bob", Id,ServerKey), TS, Id, ServerKey)) ]. -endif. rabbitmq-server-3.2.4/plugins-src/mochiweb-wrapper/mochiweb-git/src/mochiweb_html.erl0000644000000000000000000006711012305126066027544 0ustar rootroot%% @author Bob Ippolito %% @copyright 2007 Mochi Media, Inc. %% @doc Loosely tokenizes and generates parse trees for HTML 4. -module(mochiweb_html). -export([tokens/1, parse/1, parse_tokens/1, to_tokens/1, escape/1, escape_attr/1, to_html/1]). -compile([export_all]). -ifdef(TEST). -export([destack/1, destack/2, is_singleton/1]). -endif. %% This is a macro to placate syntax highlighters.. -define(QUOTE, $\"). %% $\" -define(SQUOTE, $\'). %% $\' -define(ADV_COL(S, N), S#decoder{column=N+S#decoder.column, offset=N+S#decoder.offset}). -define(INC_COL(S), S#decoder{column=1+S#decoder.column, offset=1+S#decoder.offset}). -define(INC_LINE(S), S#decoder{column=1, line=1+S#decoder.line, offset=1+S#decoder.offset}). -define(INC_CHAR(S, C), case C of $\n -> S#decoder{column=1, line=1+S#decoder.line, offset=1+S#decoder.offset}; _ -> S#decoder{column=1+S#decoder.column, offset=1+S#decoder.offset} end). -define(IS_WHITESPACE(C), (C =:= $\s orelse C =:= $\t orelse C =:= $\r orelse C =:= $\n)). -define(IS_LITERAL_SAFE(C), ((C >= $A andalso C =< $Z) orelse (C >= $a andalso C =< $z) orelse (C >= $0 andalso C =< $9))). -define(PROBABLE_CLOSE(C), (C =:= $> orelse ?IS_WHITESPACE(C))). -record(decoder, {line=1, column=1, offset=0}). %% @type html_node() = {string(), [html_attr()], [html_node() | string()]} %% @type html_attr() = {string(), string()} %% @type html_token() = html_data() | start_tag() | end_tag() | inline_html() | html_comment() | html_doctype() %% @type html_data() = {data, string(), Whitespace::boolean()} %% @type start_tag() = {start_tag, Name, [html_attr()], Singleton::boolean()} %% @type end_tag() = {end_tag, Name} %% @type html_comment() = {comment, Comment} %% @type html_doctype() = {doctype, [Doctype]} %% @type inline_html() = {'=', iolist()} %% External API. %% @spec parse(string() | binary()) -> html_node() %% @doc tokenize and then transform the token stream into a HTML tree. parse(Input) -> parse_tokens(tokens(Input)). %% @spec parse_tokens([html_token()]) -> html_node() %% @doc Transform the output of tokens(Doc) into a HTML tree. parse_tokens(Tokens) when is_list(Tokens) -> %% Skip over doctype, processing instructions [{start_tag, Tag, Attrs, false} | Rest] = find_document(Tokens, normal), {Tree, _} = tree(Rest, [norm({Tag, Attrs})]), Tree. find_document(Tokens=[{start_tag, _Tag, _Attrs, false} | _Rest], Mode) -> maybe_add_html_tag(Tokens, Mode); find_document([{doctype, [<<"html">>]} | Rest], _Mode) -> find_document(Rest, html5); find_document([_T | Rest], Mode) -> find_document(Rest, Mode); find_document([], _Mode) -> []. maybe_add_html_tag(Tokens=[{start_tag, Tag, _Attrs, false} | _], html5) when Tag =/= <<"html">> -> [{start_tag, <<"html">>, [], false} | Tokens]; maybe_add_html_tag(Tokens, _Mode) -> Tokens. %% @spec tokens(StringOrBinary) -> [html_token()] %% @doc Transform the input UTF-8 HTML into a token stream. tokens(Input) -> tokens(iolist_to_binary(Input), #decoder{}, []). %% @spec to_tokens(html_node()) -> [html_token()] %% @doc Convert a html_node() tree to a list of tokens. to_tokens({Tag0}) -> to_tokens({Tag0, [], []}); to_tokens(T={'=', _}) -> [T]; to_tokens(T={doctype, _}) -> [T]; to_tokens(T={comment, _}) -> [T]; to_tokens({Tag0, Acc}) -> %% This is only allowed in sub-tags: {p, [{"class", "foo"}]} to_tokens({Tag0, [], Acc}); to_tokens({Tag0, Attrs, Acc}) -> Tag = to_tag(Tag0), case is_singleton(Tag) of true -> to_tokens([], [{start_tag, Tag, Attrs, true}]); false -> to_tokens([{Tag, Acc}], [{start_tag, Tag, Attrs, false}]) end. %% @spec to_html([html_token()] | html_node()) -> iolist() %% @doc Convert a list of html_token() to a HTML document. to_html(Node) when is_tuple(Node) -> to_html(to_tokens(Node)); to_html(Tokens) when is_list(Tokens) -> to_html(Tokens, []). %% @spec escape(string() | atom() | binary()) -> binary() %% @doc Escape a string such that it's safe for HTML (amp; lt; gt;). escape(B) when is_binary(B) -> escape(binary_to_list(B), []); escape(A) when is_atom(A) -> escape(atom_to_list(A), []); escape(S) when is_list(S) -> escape(S, []). %% @spec escape_attr(string() | binary() | atom() | integer() | float()) -> binary() %% @doc Escape a string such that it's safe for HTML attrs %% (amp; lt; gt; quot;). escape_attr(B) when is_binary(B) -> escape_attr(binary_to_list(B), []); escape_attr(A) when is_atom(A) -> escape_attr(atom_to_list(A), []); escape_attr(S) when is_list(S) -> escape_attr(S, []); escape_attr(I) when is_integer(I) -> escape_attr(integer_to_list(I), []); escape_attr(F) when is_float(F) -> escape_attr(mochinum:digits(F), []). to_html([], Acc) -> lists:reverse(Acc); to_html([{'=', Content} | Rest], Acc) -> to_html(Rest, [Content | Acc]); to_html([{pi, Bin} | Rest], Acc) -> Open = [<<">, Bin, <<"?>">>], to_html(Rest, [Open | Acc]); to_html([{pi, Tag, Attrs} | Rest], Acc) -> Open = [<<">, Tag, attrs_to_html(Attrs, []), <<"?>">>], to_html(Rest, [Open | Acc]); to_html([{comment, Comment} | Rest], Acc) -> to_html(Rest, [[<<"">>] | Acc]); to_html([{doctype, Parts} | Rest], Acc) -> Inside = doctype_to_html(Parts, Acc), to_html(Rest, [[<<">, Inside, <<">">>] | Acc]); to_html([{data, Data, _Whitespace} | Rest], Acc) -> to_html(Rest, [escape(Data) | Acc]); to_html([{start_tag, Tag, Attrs, Singleton} | Rest], Acc) -> Open = [<<"<">>, Tag, attrs_to_html(Attrs, []), case Singleton of true -> <<" />">>; false -> <<">">> end], to_html(Rest, [Open | Acc]); to_html([{end_tag, Tag} | Rest], Acc) -> to_html(Rest, [[<<">, Tag, <<">">>] | Acc]). doctype_to_html([], Acc) -> lists:reverse(Acc); doctype_to_html([Word | Rest], Acc) -> case lists:all(fun (C) -> ?IS_LITERAL_SAFE(C) end, binary_to_list(iolist_to_binary(Word))) of true -> doctype_to_html(Rest, [[<<" ">>, Word] | Acc]); false -> doctype_to_html(Rest, [[<<" \"">>, escape_attr(Word), ?QUOTE] | Acc]) end. attrs_to_html([], Acc) -> lists:reverse(Acc); attrs_to_html([{K, V} | Rest], Acc) -> attrs_to_html(Rest, [[<<" ">>, escape(K), <<"=\"">>, escape_attr(V), <<"\"">>] | Acc]). escape([], Acc) -> list_to_binary(lists:reverse(Acc)); escape("<" ++ Rest, Acc) -> escape(Rest, lists:reverse("<", Acc)); escape(">" ++ Rest, Acc) -> escape(Rest, lists:reverse(">", Acc)); escape("&" ++ Rest, Acc) -> escape(Rest, lists:reverse("&", Acc)); escape([C | Rest], Acc) -> escape(Rest, [C | Acc]). escape_attr([], Acc) -> list_to_binary(lists:reverse(Acc)); escape_attr("<" ++ Rest, Acc) -> escape_attr(Rest, lists:reverse("<", Acc)); escape_attr(">" ++ Rest, Acc) -> escape_attr(Rest, lists:reverse(">", Acc)); escape_attr("&" ++ Rest, Acc) -> escape_attr(Rest, lists:reverse("&", Acc)); escape_attr([?QUOTE | Rest], Acc) -> escape_attr(Rest, lists:reverse(""", Acc)); escape_attr([C | Rest], Acc) -> escape_attr(Rest, [C | Acc]). to_tag(A) when is_atom(A) -> norm(atom_to_list(A)); to_tag(L) -> norm(L). to_tokens([], Acc) -> lists:reverse(Acc); to_tokens([{Tag, []} | Rest], Acc) -> to_tokens(Rest, [{end_tag, to_tag(Tag)} | Acc]); to_tokens([{Tag0, [{T0} | R1]} | Rest], Acc) -> %% Allow {br} to_tokens([{Tag0, [{T0, [], []} | R1]} | Rest], Acc); to_tokens([{Tag0, [T0={'=', _C0} | R1]} | Rest], Acc) -> %% Allow {'=', iolist()} to_tokens([{Tag0, R1} | Rest], [T0 | Acc]); to_tokens([{Tag0, [T0={comment, _C0} | R1]} | Rest], Acc) -> %% Allow {comment, iolist()} to_tokens([{Tag0, R1} | Rest], [T0 | Acc]); to_tokens([{Tag0, [T0={pi, _S0} | R1]} | Rest], Acc) -> %% Allow {pi, binary()} to_tokens([{Tag0, R1} | Rest], [T0 | Acc]); to_tokens([{Tag0, [T0={pi, _S0, _A0} | R1]} | Rest], Acc) -> %% Allow {pi, binary(), list()} to_tokens([{Tag0, R1} | Rest], [T0 | Acc]); to_tokens([{Tag0, [{T0, A0=[{_, _} | _]} | R1]} | Rest], Acc) -> %% Allow {p, [{"class", "foo"}]} to_tokens([{Tag0, [{T0, A0, []} | R1]} | Rest], Acc); to_tokens([{Tag0, [{T0, C0} | R1]} | Rest], Acc) -> %% Allow {p, "content"} and {p, <<"content">>} to_tokens([{Tag0, [{T0, [], C0} | R1]} | Rest], Acc); to_tokens([{Tag0, [{T0, A1, C0} | R1]} | Rest], Acc) when is_binary(C0) -> %% Allow {"p", [{"class", "foo"}], <<"content">>} to_tokens([{Tag0, [{T0, A1, binary_to_list(C0)} | R1]} | Rest], Acc); to_tokens([{Tag0, [{T0, A1, C0=[C | _]} | R1]} | Rest], Acc) when is_integer(C) -> %% Allow {"p", [{"class", "foo"}], "content"} to_tokens([{Tag0, [{T0, A1, [C0]} | R1]} | Rest], Acc); to_tokens([{Tag0, [{T0, A1, C1} | R1]} | Rest], Acc) -> %% Native {"p", [{"class", "foo"}], ["content"]} Tag = to_tag(Tag0), T1 = to_tag(T0), case is_singleton(norm(T1)) of true -> to_tokens([{Tag, R1} | Rest], [{start_tag, T1, A1, true} | Acc]); false -> to_tokens([{T1, C1}, {Tag, R1} | Rest], [{start_tag, T1, A1, false} | Acc]) end; to_tokens([{Tag0, [L | R1]} | Rest], Acc) when is_list(L) -> %% List text Tag = to_tag(Tag0), to_tokens([{Tag, R1} | Rest], [{data, iolist_to_binary(L), false} | Acc]); to_tokens([{Tag0, [B | R1]} | Rest], Acc) when is_binary(B) -> %% Binary text Tag = to_tag(Tag0), to_tokens([{Tag, R1} | Rest], [{data, B, false} | Acc]). tokens(B, S=#decoder{offset=O}, Acc) -> case B of <<_:O/binary>> -> lists:reverse(Acc); _ -> {Tag, S1} = tokenize(B, S), case parse_flag(Tag) of script -> {Tag2, S2} = tokenize_script(B, S1), tokens(B, S2, [Tag2, Tag | Acc]); textarea -> {Tag2, S2} = tokenize_textarea(B, S1), tokens(B, S2, [Tag2, Tag | Acc]); none -> tokens(B, S1, [Tag | Acc]) end end. parse_flag({start_tag, B, _, false}) -> case string:to_lower(binary_to_list(B)) of "script" -> script; "textarea" -> textarea; _ -> none end; parse_flag(_) -> none. tokenize(B, S=#decoder{offset=O}) -> case B of <<_:O/binary, "", _/binary>> -> Len = O - Start, <<_:Start/binary, Raw:Len/binary, _/binary>> = Bin, {{comment, Raw}, ?ADV_COL(S, 3)}; <<_:O/binary, C, _/binary>> -> tokenize_comment(Bin, ?INC_CHAR(S, C), Start); <<_:Start/binary, Raw/binary>> -> {{comment, Raw}, S} end. tokenize_script(Bin, S=#decoder{offset=O}) -> tokenize_script(Bin, S, O). tokenize_script(Bin, S=#decoder{offset=O}, Start) -> case Bin of %% Just a look-ahead, we want the end_tag separately <<_:O/binary, $<, $/, SS, CC, RR, II, PP, TT, ZZ, _/binary>> when (SS =:= $s orelse SS =:= $S) andalso (CC =:= $c orelse CC =:= $C) andalso (RR =:= $r orelse RR =:= $R) andalso (II =:= $i orelse II =:= $I) andalso (PP =:= $p orelse PP =:= $P) andalso (TT=:= $t orelse TT =:= $T) andalso ?PROBABLE_CLOSE(ZZ) -> Len = O - Start, <<_:Start/binary, Raw:Len/binary, _/binary>> = Bin, {{data, Raw, false}, S}; <<_:O/binary, C, _/binary>> -> tokenize_script(Bin, ?INC_CHAR(S, C), Start); <<_:Start/binary, Raw/binary>> -> {{data, Raw, false}, S} end. tokenize_textarea(Bin, S=#decoder{offset=O}) -> tokenize_textarea(Bin, S, O). tokenize_textarea(Bin, S=#decoder{offset=O}, Start) -> case Bin of %% Just a look-ahead, we want the end_tag separately <<_:O/binary, $<, $/, TT, EE, XX, TT2, AA, RR, EE2, AA2, ZZ, _/binary>> when (TT =:= $t orelse TT =:= $T) andalso (EE =:= $e orelse EE =:= $E) andalso (XX =:= $x orelse XX =:= $X) andalso (TT2 =:= $t orelse TT2 =:= $T) andalso (AA =:= $a orelse AA =:= $A) andalso (RR =:= $r orelse RR =:= $R) andalso (EE2 =:= $e orelse EE2 =:= $E) andalso (AA2 =:= $a orelse AA2 =:= $A) andalso ?PROBABLE_CLOSE(ZZ) -> Len = O - Start, <<_:Start/binary, Raw:Len/binary, _/binary>> = Bin, {{data, Raw, false}, S}; <<_:O/binary, C, _/binary>> -> tokenize_textarea(Bin, ?INC_CHAR(S, C), Start); <<_:Start/binary, Raw/binary>> -> {{data, Raw, false}, S} end. rabbitmq-server-3.2.4/plugins-src/mochiweb-wrapper/mochiweb-git/src/mochiweb_socket.erl0000644000000000000000000000404412305126066030065 0ustar rootroot%% @copyright 2010 Mochi Media, Inc. %% @doc MochiWeb socket - wrapper for plain and ssl sockets. -module(mochiweb_socket). -export([listen/4, accept/1, recv/3, send/2, close/1, port/1, peername/1, setopts/2, type/1]). -define(ACCEPT_TIMEOUT, 2000). listen(Ssl, Port, Opts, SslOpts) -> case Ssl of true -> case ssl:listen(Port, Opts ++ SslOpts) of {ok, ListenSocket} -> {ok, {ssl, ListenSocket}}; {error, _} = Err -> Err end; false -> gen_tcp:listen(Port, Opts) end. accept({ssl, ListenSocket}) -> % There's a bug in ssl:transport_accept/2 at the moment, which is the % reason for the try...catch block. Should be fixed in OTP R14. try ssl:transport_accept(ListenSocket) of {ok, Socket} -> case ssl:ssl_accept(Socket) of ok -> {ok, {ssl, Socket}}; {error, _} = Err -> Err end; {error, _} = Err -> Err catch error:{badmatch, {error, Reason}} -> {error, Reason} end; accept(ListenSocket) -> gen_tcp:accept(ListenSocket, ?ACCEPT_TIMEOUT). recv({ssl, Socket}, Length, Timeout) -> ssl:recv(Socket, Length, Timeout); recv(Socket, Length, Timeout) -> gen_tcp:recv(Socket, Length, Timeout). send({ssl, Socket}, Data) -> ssl:send(Socket, Data); send(Socket, Data) -> gen_tcp:send(Socket, Data). close({ssl, Socket}) -> ssl:close(Socket); close(Socket) -> gen_tcp:close(Socket). port({ssl, Socket}) -> case ssl:sockname(Socket) of {ok, {_, Port}} -> {ok, Port}; {error, _} = Err -> Err end; port(Socket) -> inet:port(Socket). peername({ssl, Socket}) -> ssl:peername(Socket); peername(Socket) -> inet:peername(Socket). setopts({ssl, Socket}, Opts) -> ssl:setopts(Socket, Opts); setopts(Socket, Opts) -> inet:setopts(Socket, Opts). type({ssl, _}) -> ssl; type(_) -> plain. rabbitmq-server-3.2.4/plugins-src/mochiweb-wrapper/mochiweb-git/src/mochiweb_echo.erl0000644000000000000000000000160512305126066027513 0ustar rootroot%% @author Bob Ippolito %% @copyright 2007 Mochi Media, Inc. %% @doc Simple and stupid echo server to demo mochiweb_socket_server. -module(mochiweb_echo). -author('bob@mochimedia.com'). -export([start/0, stop/0, loop/1]). stop() -> mochiweb_socket_server:stop(?MODULE). start() -> mochiweb_socket_server:start([{link, false} | options()]). options() -> [{name, ?MODULE}, {port, 6789}, {ip, "127.0.0.1"}, {max, 1}, {loop, {?MODULE, loop}}]. loop(Socket) -> case mochiweb_socket:recv(Socket, 0, 30000) of {ok, Data} -> case mochiweb_socket:send(Socket, Data) of ok -> loop(Socket); _ -> exit(normal) end; _Other -> exit(normal) end. %% %% Tests %% -ifdef(TEST). -include_lib("eunit/include/eunit.hrl"). -endif. rabbitmq-server-3.2.4/plugins-src/mochiweb-wrapper/mochiweb-git/src/mochitemp.erl0000644000000000000000000001664612305126066026720 0ustar rootroot%% @author Bob Ippolito %% @copyright 2010 Mochi Media, Inc. %% @doc Create temporary files and directories. -module(mochitemp). -export([gettempdir/0]). -export([mkdtemp/0, mkdtemp/3]). -export([rmtempdir/1]). %% -export([mkstemp/4]). -define(SAFE_CHARS, {$a, $b, $c, $d, $e, $f, $g, $h, $i, $j, $k, $l, $m, $n, $o, $p, $q, $r, $s, $t, $u, $v, $w, $x, $y, $z, $A, $B, $C, $D, $E, $F, $G, $H, $I, $J, $K, $L, $M, $N, $O, $P, $Q, $R, $S, $T, $U, $V, $W, $X, $Y, $Z, $0, $1, $2, $3, $4, $5, $6, $7, $8, $9, $_}). -define(TMP_MAX, 10000). -include_lib("kernel/include/file.hrl"). %% TODO: An ugly wrapper over the mktemp tool with open_port and sadness? %% We can't implement this race-free in Erlang without the ability %% to issue O_CREAT|O_EXCL. I suppose we could hack something with %% mkdtemp, del_dir, open. %% mkstemp(Suffix, Prefix, Dir, Options) -> %% ok. rmtempdir(Dir) -> case file:del_dir(Dir) of {error, eexist} -> ok = rmtempdirfiles(Dir), ok = file:del_dir(Dir); ok -> ok end. rmtempdirfiles(Dir) -> {ok, Files} = file:list_dir(Dir), ok = rmtempdirfiles(Dir, Files). rmtempdirfiles(_Dir, []) -> ok; rmtempdirfiles(Dir, [Basename | Rest]) -> Path = filename:join([Dir, Basename]), case filelib:is_dir(Path) of true -> ok = rmtempdir(Path); false -> ok = file:delete(Path) end, rmtempdirfiles(Dir, Rest). mkdtemp() -> mkdtemp("", "tmp", gettempdir()). mkdtemp(Suffix, Prefix, Dir) -> mkdtemp_n(rngpath_fun(Suffix, Prefix, Dir), ?TMP_MAX). mkdtemp_n(RngPath, 1) -> make_dir(RngPath()); mkdtemp_n(RngPath, N) -> try make_dir(RngPath()) catch throw:{error, eexist} -> mkdtemp_n(RngPath, N - 1) end. make_dir(Path) -> case file:make_dir(Path) of ok -> ok; E={error, eexist} -> throw(E) end, %% Small window for a race condition here because dir is created 777 ok = file:write_file_info(Path, #file_info{mode=8#0700}), Path. rngpath_fun(Prefix, Suffix, Dir) -> fun () -> filename:join([Dir, Prefix ++ rngchars(6) ++ Suffix]) end. rngchars(0) -> ""; rngchars(N) -> [rngchar() | rngchars(N - 1)]. rngchar() -> rngchar(mochiweb_util:rand_uniform(0, tuple_size(?SAFE_CHARS))). rngchar(C) -> element(1 + C, ?SAFE_CHARS). %% @spec gettempdir() -> string() %% @doc Get a usable temporary directory using the first of these that is a directory: %% $TMPDIR, $TMP, $TEMP, "/tmp", "/var/tmp", "/usr/tmp", ".". gettempdir() -> gettempdir(gettempdir_checks(), fun normalize_dir/1). gettempdir_checks() -> [{fun os:getenv/1, ["TMPDIR", "TMP", "TEMP"]}, {fun gettempdir_identity/1, ["/tmp", "/var/tmp", "/usr/tmp"]}, {fun gettempdir_cwd/1, [cwd]}]. gettempdir_identity(L) -> L. gettempdir_cwd(cwd) -> {ok, L} = file:get_cwd(), L. gettempdir([{_F, []} | RestF], Normalize) -> gettempdir(RestF, Normalize); gettempdir([{F, [L | RestL]} | RestF], Normalize) -> case Normalize(F(L)) of false -> gettempdir([{F, RestL} | RestF], Normalize); Dir -> Dir end. normalize_dir(False) when False =:= false orelse False =:= "" -> %% Erlang doesn't have an unsetenv, wtf. false; normalize_dir(L) -> Dir = filename:absname(L), case filelib:is_dir(Dir) of false -> false; true -> Dir end. %% %% Tests %% -ifdef(TEST). -include_lib("eunit/include/eunit.hrl"). pushenv(L) -> [{K, os:getenv(K)} || K <- L]. popenv(L) -> F = fun ({K, false}) -> %% Erlang doesn't have an unsetenv, wtf. os:putenv(K, ""); ({K, V}) -> os:putenv(K, V) end, lists:foreach(F, L). gettempdir_fallback_test() -> ?assertEqual( "/", gettempdir([{fun gettempdir_identity/1, ["/--not-here--/"]}, {fun gettempdir_identity/1, ["/"]}], fun normalize_dir/1)), ?assertEqual( "/", %% simulate a true os:getenv unset env gettempdir([{fun gettempdir_identity/1, [false]}, {fun gettempdir_identity/1, ["/"]}], fun normalize_dir/1)), ok. gettempdir_identity_test() -> ?assertEqual( "/", gettempdir([{fun gettempdir_identity/1, ["/"]}], fun normalize_dir/1)), ok. gettempdir_cwd_test() -> {ok, Cwd} = file:get_cwd(), ?assertEqual( normalize_dir(Cwd), gettempdir([{fun gettempdir_cwd/1, [cwd]}], fun normalize_dir/1)), ok. rngchars_test() -> ?assertEqual( "", rngchars(0)), ?assertEqual( 10, length(rngchars(10))), ok. rngchar_test() -> ?assertEqual( $a, rngchar(0)), ?assertEqual( $A, rngchar(26)), ?assertEqual( $_, rngchar(62)), ok. mkdtemp_n_failonce_test() -> D = mkdtemp(), Path = filename:join([D, "testdir"]), %% Toggle the existence of a dir so that it fails %% the first time and succeeds the second. F = fun () -> case filelib:is_dir(Path) of true -> file:del_dir(Path); false -> file:make_dir(Path) end, Path end, try %% Fails the first time ?assertThrow( {error, eexist}, mkdtemp_n(F, 1)), %% Reset state file:del_dir(Path), %% Succeeds the second time ?assertEqual( Path, mkdtemp_n(F, 2)) after rmtempdir(D) end, ok. mkdtemp_n_fail_test() -> {ok, Cwd} = file:get_cwd(), ?assertThrow( {error, eexist}, mkdtemp_n(fun () -> Cwd end, 1)), ?assertThrow( {error, eexist}, mkdtemp_n(fun () -> Cwd end, 2)), ok. make_dir_fail_test() -> {ok, Cwd} = file:get_cwd(), ?assertThrow( {error, eexist}, make_dir(Cwd)), ok. mkdtemp_test() -> D = mkdtemp(), ?assertEqual( true, filelib:is_dir(D)), ?assertEqual( ok, file:del_dir(D)), ok. rmtempdir_test() -> D1 = mkdtemp(), ?assertEqual( true, filelib:is_dir(D1)), ?assertEqual( ok, rmtempdir(D1)), D2 = mkdtemp(), ?assertEqual( true, filelib:is_dir(D2)), ok = file:write_file(filename:join([D2, "foo"]), <<"bytes">>), D3 = mkdtemp("suffix", "prefix", D2), ?assertEqual( true, filelib:is_dir(D3)), ok = file:write_file(filename:join([D3, "foo"]), <<"bytes">>), ?assertEqual( ok, rmtempdir(D2)), ?assertEqual( {error, enoent}, file:consult(D3)), ?assertEqual( {error, enoent}, file:consult(D2)), ok. gettempdir_env_test() -> Env = pushenv(["TMPDIR", "TEMP", "TMP"]), FalseEnv = [{"TMPDIR", false}, {"TEMP", false}, {"TMP", false}], try popenv(FalseEnv), popenv([{"TMPDIR", "/"}]), ?assertEqual( "/", os:getenv("TMPDIR")), ?assertEqual( "/", gettempdir()), {ok, Cwd} = file:get_cwd(), popenv(FalseEnv), popenv([{"TMP", Cwd}]), ?assertEqual( normalize_dir(Cwd), gettempdir()) after popenv(Env) end, ok. -endif. rabbitmq-server-3.2.4/plugins-src/mochiweb-wrapper/mochiweb-git/src/mochiweb_mime.erl0000644000000000000000000002441512305126066027530 0ustar rootroot%% @author Bob Ippolito %% @copyright 2007 Mochi Media, Inc. %% @doc Gives a good MIME type guess based on file extension. -module(mochiweb_mime). -author('bob@mochimedia.com'). -export([from_extension/1]). %% @spec from_extension(S::string()) -> string() | undefined %% @doc Given a filename extension (e.g. ".html") return a guess for the MIME %% type such as "text/html". Will return the atom undefined if no good %% guess is available. from_extension(".stl") -> "application/SLA"; from_extension(".stp") -> "application/STEP"; from_extension(".step") -> "application/STEP"; from_extension(".dwg") -> "application/acad"; from_extension(".ez") -> "application/andrew-inset"; from_extension(".ccad") -> "application/clariscad"; from_extension(".drw") -> "application/drafting"; from_extension(".tsp") -> "application/dsptype"; from_extension(".dxf") -> "application/dxf"; from_extension(".xls") -> "application/excel"; from_extension(".unv") -> "application/i-deas"; from_extension(".jar") -> "application/java-archive"; from_extension(".hqx") -> "application/mac-binhex40"; from_extension(".cpt") -> "application/mac-compactpro"; from_extension(".pot") -> "application/vnd.ms-powerpoint"; from_extension(".ppt") -> "application/vnd.ms-powerpoint"; from_extension(".dms") -> "application/octet-stream"; from_extension(".lha") -> "application/octet-stream"; from_extension(".lzh") -> "application/octet-stream"; from_extension(".oda") -> "application/oda"; from_extension(".ogg") -> "application/ogg"; from_extension(".ogm") -> "application/ogg"; from_extension(".pdf") -> "application/pdf"; from_extension(".pgp") -> "application/pgp"; from_extension(".ai") -> "application/postscript"; from_extension(".eps") -> "application/postscript"; from_extension(".ps") -> "application/postscript"; from_extension(".prt") -> "application/pro_eng"; from_extension(".rtf") -> "application/rtf"; from_extension(".smi") -> "application/smil"; from_extension(".smil") -> "application/smil"; from_extension(".sol") -> "application/solids"; from_extension(".vda") -> "application/vda"; from_extension(".xlm") -> "application/vnd.ms-excel"; from_extension(".cod") -> "application/vnd.rim.cod"; from_extension(".pgn") -> "application/x-chess-pgn"; from_extension(".cpio") -> "application/x-cpio"; from_extension(".csh") -> "application/x-csh"; from_extension(".deb") -> "application/x-debian-package"; from_extension(".dcr") -> "application/x-director"; from_extension(".dir") -> "application/x-director"; from_extension(".dxr") -> "application/x-director"; from_extension(".gz") -> "application/x-gzip"; from_extension(".hdf") -> "application/x-hdf"; from_extension(".ipx") -> "application/x-ipix"; from_extension(".ips") -> "application/x-ipscript"; from_extension(".js") -> "application/x-javascript"; from_extension(".skd") -> "application/x-koan"; from_extension(".skm") -> "application/x-koan"; from_extension(".skp") -> "application/x-koan"; from_extension(".skt") -> "application/x-koan"; from_extension(".latex") -> "application/x-latex"; from_extension(".lsp") -> "application/x-lisp"; from_extension(".scm") -> "application/x-lotusscreencam"; from_extension(".mif") -> "application/x-mif"; from_extension(".com") -> "application/x-msdos-program"; from_extension(".exe") -> "application/octet-stream"; from_extension(".cdf") -> "application/x-netcdf"; from_extension(".nc") -> "application/x-netcdf"; from_extension(".pl") -> "application/x-perl"; from_extension(".pm") -> "application/x-perl"; from_extension(".rar") -> "application/x-rar-compressed"; from_extension(".sh") -> "application/x-sh"; from_extension(".shar") -> "application/x-shar"; from_extension(".swf") -> "application/x-shockwave-flash"; from_extension(".sit") -> "application/x-stuffit"; from_extension(".sv4cpio") -> "application/x-sv4cpio"; from_extension(".sv4crc") -> "application/x-sv4crc"; from_extension(".tar.gz") -> "application/x-tar-gz"; from_extension(".tgz") -> "application/x-tar-gz"; from_extension(".tar") -> "application/x-tar"; from_extension(".tcl") -> "application/x-tcl"; from_extension(".texi") -> "application/x-texinfo"; from_extension(".texinfo") -> "application/x-texinfo"; from_extension(".man") -> "application/x-troff-man"; from_extension(".me") -> "application/x-troff-me"; from_extension(".ms") -> "application/x-troff-ms"; from_extension(".roff") -> "application/x-troff"; from_extension(".t") -> "application/x-troff"; from_extension(".tr") -> "application/x-troff"; from_extension(".ustar") -> "application/x-ustar"; from_extension(".src") -> "application/x-wais-source"; from_extension(".zip") -> "application/zip"; from_extension(".tsi") -> "audio/TSP-audio"; from_extension(".au") -> "audio/basic"; from_extension(".snd") -> "audio/basic"; from_extension(".kar") -> "audio/midi"; from_extension(".mid") -> "audio/midi"; from_extension(".midi") -> "audio/midi"; from_extension(".mp2") -> "audio/mpeg"; from_extension(".mp3") -> "audio/mpeg"; from_extension(".mpga") -> "audio/mpeg"; from_extension(".aif") -> "audio/x-aiff"; from_extension(".aifc") -> "audio/x-aiff"; from_extension(".aiff") -> "audio/x-aiff"; from_extension(".m3u") -> "audio/x-mpegurl"; from_extension(".wax") -> "audio/x-ms-wax"; from_extension(".wma") -> "audio/x-ms-wma"; from_extension(".rpm") -> "audio/x-pn-realaudio-plugin"; from_extension(".ram") -> "audio/x-pn-realaudio"; from_extension(".rm") -> "audio/x-pn-realaudio"; from_extension(".ra") -> "audio/x-realaudio"; from_extension(".wav") -> "audio/x-wav"; from_extension(".pdb") -> "chemical/x-pdb"; from_extension(".ras") -> "image/cmu-raster"; from_extension(".gif") -> "image/gif"; from_extension(".ief") -> "image/ief"; from_extension(".jpe") -> "image/jpeg"; from_extension(".jpeg") -> "image/jpeg"; from_extension(".jpg") -> "image/jpeg"; from_extension(".jp2") -> "image/jp2"; from_extension(".png") -> "image/png"; from_extension(".tif") -> "image/tiff"; from_extension(".tiff") -> "image/tiff"; from_extension(".pnm") -> "image/x-portable-anymap"; from_extension(".pbm") -> "image/x-portable-bitmap"; from_extension(".pgm") -> "image/x-portable-graymap"; from_extension(".ppm") -> "image/x-portable-pixmap"; from_extension(".rgb") -> "image/x-rgb"; from_extension(".xbm") -> "image/x-xbitmap"; from_extension(".xwd") -> "image/x-xwindowdump"; from_extension(".iges") -> "model/iges"; from_extension(".igs") -> "model/iges"; from_extension(".mesh") -> "model/mesh"; from_extension(".") -> ""; from_extension(".msh") -> "model/mesh"; from_extension(".silo") -> "model/mesh"; from_extension(".vrml") -> "model/vrml"; from_extension(".wrl") -> "model/vrml"; from_extension(".css") -> "text/css"; from_extension(".htm") -> "text/html"; from_extension(".html") -> "text/html"; from_extension(".asc") -> "text/plain"; from_extension(".c") -> "text/plain"; from_extension(".cc") -> "text/plain"; from_extension(".f90") -> "text/plain"; from_extension(".f") -> "text/plain"; from_extension(".hh") -> "text/plain"; from_extension(".m") -> "text/plain"; from_extension(".txt") -> "text/plain"; from_extension(".rtx") -> "text/richtext"; from_extension(".sgm") -> "text/sgml"; from_extension(".sgml") -> "text/sgml"; from_extension(".tsv") -> "text/tab-separated-values"; from_extension(".jad") -> "text/vnd.sun.j2me.app-descriptor"; from_extension(".etx") -> "text/x-setext"; from_extension(".xml") -> "application/xml"; from_extension(".dl") -> "video/dl"; from_extension(".fli") -> "video/fli"; from_extension(".flv") -> "video/x-flv"; from_extension(".gl") -> "video/gl"; from_extension(".mp4") -> "video/mp4"; from_extension(".mpe") -> "video/mpeg"; from_extension(".mpeg") -> "video/mpeg"; from_extension(".mpg") -> "video/mpeg"; from_extension(".mov") -> "video/quicktime"; from_extension(".qt") -> "video/quicktime"; from_extension(".viv") -> "video/vnd.vivo"; from_extension(".vivo") -> "video/vnd.vivo"; from_extension(".asf") -> "video/x-ms-asf"; from_extension(".asx") -> "video/x-ms-asx"; from_extension(".wmv") -> "video/x-ms-wmv"; from_extension(".wmx") -> "video/x-ms-wmx"; from_extension(".wvx") -> "video/x-ms-wvx"; from_extension(".avi") -> "video/x-msvideo"; from_extension(".movie") -> "video/x-sgi-movie"; from_extension(".mime") -> "www/mime"; from_extension(".ice") -> "x-conference/x-cooltalk"; from_extension(".vrm") -> "x-world/x-vrml"; from_extension(".spx") -> "audio/ogg"; from_extension(".xhtml") -> "application/xhtml+xml"; from_extension(".bz2") -> "application/x-bzip2"; from_extension(".doc") -> "application/msword"; from_extension(".z") -> "application/x-compress"; from_extension(".ico") -> "image/x-icon"; from_extension(".bmp") -> "image/bmp"; from_extension(".m4a") -> "audio/mpeg"; from_extension(".csv") -> "text/csv"; from_extension(".eot") -> "application/vnd.ms-fontobject"; from_extension(".m4v") -> "video/mp4"; from_extension(".svg") -> "image/svg+xml"; from_extension(".svgz") -> "image/svg+xml"; from_extension(".ttc") -> "application/x-font-ttf"; from_extension(".ttf") -> "application/x-font-ttf"; from_extension(".vcf") -> "text/x-vcard"; from_extension(".webm") -> "video/web"; from_extension(".webp") -> "image/web"; from_extension(".woff") -> "application/x-font-woff"; from_extension(".otf") -> "font/opentype"; from_extension(_) -> undefined. %% %% Tests %% -ifdef(TEST). -include_lib("eunit/include/eunit.hrl"). exhaustive_from_extension_test() -> T = mochiweb_cover:clause_lookup_table(?MODULE, from_extension), [?assertEqual(V, from_extension(K)) || {K, V} <- T]. from_extension_test() -> ?assertEqual("text/html", from_extension(".html")), ?assertEqual(undefined, from_extension("")), ?assertEqual(undefined, from_extension(".wtf")), ok. -endif. rabbitmq-server-3.2.4/plugins-src/mochiweb-wrapper/mochiweb-git/src/mochifmt_std.erl0000644000000000000000000000142112305126066027374 0ustar rootroot%% @author Bob Ippolito %% @copyright 2008 Mochi Media, Inc. %% @doc Template module for a mochifmt formatter. -module(mochifmt_std). -author('bob@mochimedia.com'). -export([new/0, format/3, get_value/3, format_field/3, get_field/3, convert_field/3]). new() -> {?MODULE}. format(Format, Args, {?MODULE}=THIS) -> mochifmt:format(Format, Args, THIS). get_field(Key, Args, {?MODULE}=THIS) -> mochifmt:get_field(Key, Args, THIS). convert_field(Key, Args, {?MODULE}) -> mochifmt:convert_field(Key, Args). get_value(Key, Args, {?MODULE}) -> mochifmt:get_value(Key, Args). format_field(Arg, Format, {?MODULE}=THIS) -> mochifmt:format_field(Arg, Format, THIS). %% %% Tests %% -ifdef(TEST). -include_lib("eunit/include/eunit.hrl"). -endif. rabbitmq-server-3.2.4/plugins-src/mochiweb-wrapper/mochiweb-git/src/mochiweb_request.erl0000644000000000000000000010723012305126066030266 0ustar rootroot%% @author Bob Ippolito %% @copyright 2007 Mochi Media, Inc. %% @doc MochiWeb HTTP Request abstraction. -module(mochiweb_request). -author('bob@mochimedia.com'). -include_lib("kernel/include/file.hrl"). -include("internal.hrl"). -define(QUIP, "Any of you quaids got a smint?"). -export([new/5]). -export([get_header_value/2, get_primary_header_value/2, get_combined_header_value/2, get/2, dump/1]). -export([send/2, recv/2, recv/3, recv_body/1, recv_body/2, stream_body/4]). -export([start_response/2, start_response_length/2, start_raw_response/2]). -export([respond/2, ok/2]). -export([not_found/1, not_found/2]). -export([parse_post/1, parse_qs/1]). -export([should_close/1, cleanup/1]). -export([parse_cookie/1, get_cookie_value/2]). -export([serve_file/3, serve_file/4]). -export([accepted_encodings/2]). -export([accepts_content_type/2, accepted_content_types/2]). -define(SAVE_QS, mochiweb_request_qs). -define(SAVE_PATH, mochiweb_request_path). -define(SAVE_RECV, mochiweb_request_recv). -define(SAVE_BODY, mochiweb_request_body). -define(SAVE_BODY_LENGTH, mochiweb_request_body_length). -define(SAVE_POST, mochiweb_request_post). -define(SAVE_COOKIE, mochiweb_request_cookie). -define(SAVE_FORCE_CLOSE, mochiweb_request_force_close). %% @type key() = atom() | string() | binary() %% @type value() = atom() | string() | binary() | integer() %% @type headers(). A mochiweb_headers structure. %% @type request(). A mochiweb_request parameterized module instance. %% @type response(). A mochiweb_response parameterized module instance. %% @type ioheaders() = headers() | [{key(), value()}]. % 5 minute default idle timeout -define(IDLE_TIMEOUT, 300000). % Maximum recv_body() length of 1MB -define(MAX_RECV_BODY, 104857600). %% @spec new(Socket, Method, RawPath, Version, headers()) -> request() %% @doc Create a new request instance. new(Socket, Method, RawPath, Version, Headers) -> {?MODULE, [Socket, Method, RawPath, Version, Headers]}. %% @spec get_header_value(K, request()) -> undefined | Value %% @doc Get the value of a given request header. get_header_value(K, {?MODULE, [_Socket, _Method, _RawPath, _Version, Headers]}) -> mochiweb_headers:get_value(K, Headers). get_primary_header_value(K, {?MODULE, [_Socket, _Method, _RawPath, _Version, Headers]}) -> mochiweb_headers:get_primary_value(K, Headers). get_combined_header_value(K, {?MODULE, [_Socket, _Method, _RawPath, _Version, Headers]}) -> mochiweb_headers:get_combined_value(K, Headers). %% @type field() = socket | scheme | method | raw_path | version | headers | peer | path | body_length | range %% @spec get(field(), request()) -> term() %% @doc Return the internal representation of the given field. If %% socket is requested on a HTTPS connection, then %% an ssl socket will be returned as {ssl, SslSocket}. %% You can use SslSocket with the ssl %% application, eg: ssl:peercert(SslSocket). get(socket, {?MODULE, [Socket, _Method, _RawPath, _Version, _Headers]}) -> Socket; get(scheme, {?MODULE, [Socket, _Method, _RawPath, _Version, _Headers]}) -> case mochiweb_socket:type(Socket) of plain -> http; ssl -> https end; get(method, {?MODULE, [_Socket, Method, _RawPath, _Version, _Headers]}) -> Method; get(raw_path, {?MODULE, [_Socket, _Method, RawPath, _Version, _Headers]}) -> RawPath; get(version, {?MODULE, [_Socket, _Method, _RawPath, Version, _Headers]}) -> Version; get(headers, {?MODULE, [_Socket, _Method, _RawPath, _Version, Headers]}) -> Headers; get(peer, {?MODULE, [Socket, _Method, _RawPath, _Version, _Headers]}=THIS) -> case mochiweb_socket:peername(Socket) of {ok, {Addr={10, _, _, _}, _Port}} -> case get_header_value("x-forwarded-for", THIS) of undefined -> inet_parse:ntoa(Addr); Hosts -> string:strip(lists:last(string:tokens(Hosts, ","))) end; {ok, {{127, 0, 0, 1}, _Port}} -> case get_header_value("x-forwarded-for", THIS) of undefined -> "127.0.0.1"; Hosts -> string:strip(lists:last(string:tokens(Hosts, ","))) end; {ok, {Addr, _Port}} -> inet_parse:ntoa(Addr); {error, enotconn} -> exit(normal) end; get(path, {?MODULE, [_Socket, _Method, RawPath, _Version, _Headers]}) -> case erlang:get(?SAVE_PATH) of undefined -> {Path0, _, _} = mochiweb_util:urlsplit_path(RawPath), Path = mochiweb_util:unquote(Path0), put(?SAVE_PATH, Path), Path; Cached -> Cached end; get(body_length, {?MODULE, [_Socket, _Method, _RawPath, _Version, _Headers]}=THIS) -> case erlang:get(?SAVE_BODY_LENGTH) of undefined -> BodyLength = body_length(THIS), put(?SAVE_BODY_LENGTH, {cached, BodyLength}), BodyLength; {cached, Cached} -> Cached end; get(range, {?MODULE, [_Socket, _Method, _RawPath, _Version, _Headers]}=THIS) -> case get_header_value(range, THIS) of undefined -> undefined; RawRange -> mochiweb_http:parse_range_request(RawRange) end. %% @spec dump(request()) -> {mochiweb_request, [{atom(), term()}]} %% @doc Dump the internal representation to a "human readable" set of terms %% for debugging/inspection purposes. dump({?MODULE, [_Socket, Method, RawPath, Version, Headers]}) -> {?MODULE, [{method, Method}, {version, Version}, {raw_path, RawPath}, {headers, mochiweb_headers:to_list(Headers)}]}. %% @spec send(iodata(), request()) -> ok %% @doc Send data over the socket. send(Data, {?MODULE, [Socket, _Method, _RawPath, _Version, _Headers]}) -> case mochiweb_socket:send(Socket, Data) of ok -> ok; _ -> exit(normal) end. %% @spec recv(integer(), request()) -> binary() %% @doc Receive Length bytes from the client as a binary, with the default %% idle timeout. recv(Length, {?MODULE, [_Socket, _Method, _RawPath, _Version, _Headers]}=THIS) -> recv(Length, ?IDLE_TIMEOUT, THIS). %% @spec recv(integer(), integer(), request()) -> binary() %% @doc Receive Length bytes from the client as a binary, with the given %% Timeout in msec. recv(Length, Timeout, {?MODULE, [Socket, _Method, _RawPath, _Version, _Headers]}) -> case mochiweb_socket:recv(Socket, Length, Timeout) of {ok, Data} -> put(?SAVE_RECV, true), Data; _ -> exit(normal) end. %% @spec body_length(request()) -> undefined | chunked | unknown_transfer_encoding | integer() %% @doc Infer body length from transfer-encoding and content-length headers. body_length({?MODULE, [_Socket, _Method, _RawPath, _Version, _Headers]}=THIS) -> case get_header_value("transfer-encoding", THIS) of undefined -> case get_combined_header_value("content-length", THIS) of undefined -> undefined; Length -> list_to_integer(Length) end; "chunked" -> chunked; Unknown -> {unknown_transfer_encoding, Unknown} end. %% @spec recv_body(request()) -> binary() %% @doc Receive the body of the HTTP request (defined by Content-Length). %% Will only receive up to the default max-body length of 1MB. recv_body({?MODULE, [_Socket, _Method, _RawPath, _Version, _Headers]}=THIS) -> recv_body(?MAX_RECV_BODY, THIS). %% @spec recv_body(integer(), request()) -> binary() %% @doc Receive the body of the HTTP request (defined by Content-Length). %% Will receive up to MaxBody bytes. recv_body(MaxBody, {?MODULE, [_Socket, _Method, _RawPath, _Version, _Headers]}=THIS) -> case erlang:get(?SAVE_BODY) of undefined -> % we could use a sane constant for max chunk size Body = stream_body(?MAX_RECV_BODY, fun ({0, _ChunkedFooter}, {_LengthAcc, BinAcc}) -> iolist_to_binary(lists:reverse(BinAcc)); ({Length, Bin}, {LengthAcc, BinAcc}) -> NewLength = Length + LengthAcc, if NewLength > MaxBody -> exit({body_too_large, chunked}); true -> {NewLength, [Bin | BinAcc]} end end, {0, []}, MaxBody, THIS), put(?SAVE_BODY, Body), Body; Cached -> Cached end. stream_body(MaxChunkSize, ChunkFun, FunState, {?MODULE,[_Socket,_Method,_RawPath,_Version,_Headers]}=THIS) -> stream_body(MaxChunkSize, ChunkFun, FunState, undefined, THIS). stream_body(MaxChunkSize, ChunkFun, FunState, MaxBodyLength, {?MODULE, [_Socket, _Method, _RawPath, _Version, _Headers]}=THIS) -> Expect = case get_header_value("expect", THIS) of undefined -> undefined; Value when is_list(Value) -> string:to_lower(Value) end, case Expect of "100-continue" -> _ = start_raw_response({100, gb_trees:empty()}, THIS), ok; _Else -> ok end, case body_length(THIS) of undefined -> undefined; {unknown_transfer_encoding, Unknown} -> exit({unknown_transfer_encoding, Unknown}); chunked -> % In this case the MaxBody is actually used to % determine the maximum allowed size of a single % chunk. stream_chunked_body(MaxChunkSize, ChunkFun, FunState, THIS); 0 -> <<>>; Length when is_integer(Length) -> case MaxBodyLength of MaxBodyLength when is_integer(MaxBodyLength), MaxBodyLength < Length -> exit({body_too_large, content_length}); _ -> stream_unchunked_body(Length, ChunkFun, FunState, THIS) end end. %% @spec start_response({integer(), ioheaders()}, request()) -> response() %% @doc Start the HTTP response by sending the Code HTTP response and %% ResponseHeaders. The server will set header defaults such as Server %% and Date if not present in ResponseHeaders. start_response({Code, ResponseHeaders}, {?MODULE, [_Socket, _Method, _RawPath, _Version, _Headers]}=THIS) -> HResponse = mochiweb_headers:make(ResponseHeaders), HResponse1 = mochiweb_headers:default_from_list(server_headers(), HResponse), start_raw_response({Code, HResponse1}, THIS). %% @spec start_raw_response({integer(), headers()}, request()) -> response() %% @doc Start the HTTP response by sending the Code HTTP response and %% ResponseHeaders. start_raw_response({Code, ResponseHeaders}, {?MODULE, [_Socket, _Method, _RawPath, Version, _Headers]}=THIS) -> F = fun ({K, V}, Acc) -> [mochiweb_util:make_io(K), <<": ">>, V, <<"\r\n">> | Acc] end, End = lists:foldl(F, [<<"\r\n">>], mochiweb_headers:to_list(ResponseHeaders)), send([make_version(Version), make_code(Code), <<"\r\n">> | End], THIS), mochiweb:new_response({THIS, Code, ResponseHeaders}). %% @spec start_response_length({integer(), ioheaders(), integer()}, request()) -> response() %% @doc Start the HTTP response by sending the Code HTTP response and %% ResponseHeaders including a Content-Length of Length. The server %% will set header defaults such as Server %% and Date if not present in ResponseHeaders. start_response_length({Code, ResponseHeaders, Length}, {?MODULE, [_Socket, _Method, _RawPath, _Version, _Headers]}=THIS) -> HResponse = mochiweb_headers:make(ResponseHeaders), HResponse1 = mochiweb_headers:enter("Content-Length", Length, HResponse), start_response({Code, HResponse1}, THIS). %% @spec respond({integer(), ioheaders(), iodata() | chunked | {file, IoDevice}}, request()) -> response() %% @doc Start the HTTP response with start_response, and send Body to the %% client (if the get(method) /= 'HEAD'). The Content-Length header %% will be set by the Body length, and the server will insert header %% defaults. respond({Code, ResponseHeaders, {file, IoDevice}}, {?MODULE, [_Socket, Method, _RawPath, _Version, _Headers]}=THIS) -> Length = mochiweb_io:iodevice_size(IoDevice), Response = start_response_length({Code, ResponseHeaders, Length}, THIS), case Method of 'HEAD' -> ok; _ -> mochiweb_io:iodevice_stream( fun (Body) -> send(Body, THIS) end, IoDevice) end, Response; respond({Code, ResponseHeaders, chunked}, {?MODULE, [_Socket, Method, _RawPath, Version, _Headers]}=THIS) -> HResponse = mochiweb_headers:make(ResponseHeaders), HResponse1 = case Method of 'HEAD' -> %% This is what Google does, http://www.google.com/ %% is chunked but HEAD gets Content-Length: 0. %% The RFC is ambiguous so emulating Google is smart. mochiweb_headers:enter("Content-Length", "0", HResponse); _ when Version >= {1, 1} -> %% Only use chunked encoding for HTTP/1.1 mochiweb_headers:enter("Transfer-Encoding", "chunked", HResponse); _ -> %% For pre-1.1 clients we send the data as-is %% without a Content-Length header and without %% chunk delimiters. Since the end of the document %% is now ambiguous we must force a close. put(?SAVE_FORCE_CLOSE, true), HResponse end, start_response({Code, HResponse1}, THIS); respond({Code, ResponseHeaders, Body}, {?MODULE, [_Socket, Method, _RawPath, _Version, _Headers]}=THIS) -> Response = start_response_length({Code, ResponseHeaders, iolist_size(Body)}, THIS), case Method of 'HEAD' -> ok; _ -> send(Body, THIS) end, Response. %% @spec not_found(request()) -> response() %% @doc Alias for not_found([]). not_found({?MODULE, [_Socket, _Method, _RawPath, _Version, _Headers]}=THIS) -> not_found([], THIS). %% @spec not_found(ExtraHeaders, request()) -> response() %% @doc Alias for respond({404, [{"Content-Type", "text/plain"} %% | ExtraHeaders], <<"Not found.">>}). not_found(ExtraHeaders, {?MODULE, [_Socket, _Method, _RawPath, _Version, _Headers]}=THIS) -> respond({404, [{"Content-Type", "text/plain"} | ExtraHeaders], <<"Not found.">>}, THIS). %% @spec ok({value(), iodata()} | {value(), ioheaders(), iodata() | {file, IoDevice}}, request()) -> %% response() %% @doc respond({200, [{"Content-Type", ContentType} | Headers], Body}). ok({ContentType, Body}, {?MODULE, [_Socket, _Method, _RawPath, _Version, _Headers]}=THIS) -> ok({ContentType, [], Body}, THIS); ok({ContentType, ResponseHeaders, Body}, {?MODULE, [_Socket, _Method, _RawPath, _Version, _Headers]}=THIS) -> HResponse = mochiweb_headers:make(ResponseHeaders), case THIS:get(range) of X when (X =:= undefined orelse X =:= fail) orelse Body =:= chunked -> %% http://code.google.com/p/mochiweb/issues/detail?id=54 %% Range header not supported when chunked, return 200 and provide %% full response. HResponse1 = mochiweb_headers:enter("Content-Type", ContentType, HResponse), respond({200, HResponse1, Body}, THIS); Ranges -> {PartList, Size} = range_parts(Body, Ranges), case PartList of [] -> %% no valid ranges HResponse1 = mochiweb_headers:enter("Content-Type", ContentType, HResponse), %% could be 416, for now we'll just return 200 respond({200, HResponse1, Body}, THIS); PartList -> {RangeHeaders, RangeBody} = mochiweb_multipart:parts_to_body(PartList, ContentType, Size), HResponse1 = mochiweb_headers:enter_from_list( [{"Accept-Ranges", "bytes"} | RangeHeaders], HResponse), respond({206, HResponse1, RangeBody}, THIS) end end. %% @spec should_close(request()) -> bool() %% @doc Return true if the connection must be closed. If false, using %% Keep-Alive should be safe. should_close({?MODULE, [_Socket, _Method, _RawPath, Version, _Headers]}=THIS) -> ForceClose = erlang:get(?SAVE_FORCE_CLOSE) =/= undefined, DidNotRecv = erlang:get(?SAVE_RECV) =:= undefined, ForceClose orelse Version < {1, 0} %% Connection: close orelse is_close(get_header_value("connection", THIS)) %% HTTP 1.0 requires Connection: Keep-Alive orelse (Version =:= {1, 0} andalso get_header_value("connection", THIS) =/= "Keep-Alive") %% unread data left on the socket, can't safely continue orelse (DidNotRecv andalso get_combined_header_value("content-length", THIS) =/= undefined andalso list_to_integer(get_combined_header_value("content-length", THIS)) > 0) orelse (DidNotRecv andalso get_header_value("transfer-encoding", THIS) =:= "chunked"). is_close("close") -> true; is_close(S=[_C, _L, _O, _S, _E]) -> string:to_lower(S) =:= "close"; is_close(_) -> false. %% @spec cleanup(request()) -> ok %% @doc Clean up any junk in the process dictionary, required before continuing %% a Keep-Alive request. cleanup({?MODULE, [_Socket, _Method, _RawPath, _Version, _Headers]}) -> L = [?SAVE_QS, ?SAVE_PATH, ?SAVE_RECV, ?SAVE_BODY, ?SAVE_BODY_LENGTH, ?SAVE_POST, ?SAVE_COOKIE, ?SAVE_FORCE_CLOSE], lists:foreach(fun(K) -> erase(K) end, L), ok. %% @spec parse_qs(request()) -> [{Key::string(), Value::string()}] %% @doc Parse the query string of the URL. parse_qs({?MODULE, [_Socket, _Method, RawPath, _Version, _Headers]}) -> case erlang:get(?SAVE_QS) of undefined -> {_, QueryString, _} = mochiweb_util:urlsplit_path(RawPath), Parsed = mochiweb_util:parse_qs(QueryString), put(?SAVE_QS, Parsed), Parsed; Cached -> Cached end. %% @spec get_cookie_value(Key::string, request()) -> string() | undefined %% @doc Get the value of the given cookie. get_cookie_value(Key, {?MODULE, [_Socket, _Method, _RawPath, _Version, _Headers]}=THIS) -> proplists:get_value(Key, parse_cookie(THIS)). %% @spec parse_cookie(request()) -> [{Key::string(), Value::string()}] %% @doc Parse the cookie header. parse_cookie({?MODULE, [_Socket, _Method, _RawPath, _Version, _Headers]}=THIS) -> case erlang:get(?SAVE_COOKIE) of undefined -> Cookies = case get_header_value("cookie", THIS) of undefined -> []; Value -> mochiweb_cookies:parse_cookie(Value) end, put(?SAVE_COOKIE, Cookies), Cookies; Cached -> Cached end. %% @spec parse_post(request()) -> [{Key::string(), Value::string()}] %% @doc Parse an application/x-www-form-urlencoded form POST. This %% has the side-effect of calling recv_body(). parse_post({?MODULE, [_Socket, _Method, _RawPath, _Version, _Headers]}=THIS) -> case erlang:get(?SAVE_POST) of undefined -> Parsed = case recv_body(THIS) of undefined -> []; Binary -> case get_primary_header_value("content-type",THIS) of "application/x-www-form-urlencoded" ++ _ -> mochiweb_util:parse_qs(Binary); _ -> [] end end, put(?SAVE_POST, Parsed), Parsed; Cached -> Cached end. %% @spec stream_chunked_body(integer(), fun(), term(), request()) -> term() %% @doc The function is called for each chunk. %% Used internally by read_chunked_body. stream_chunked_body(MaxChunkSize, Fun, FunState, {?MODULE, [_Socket, _Method, _RawPath, _Version, _Headers]}=THIS) -> case read_chunk_length(THIS) of 0 -> Fun({0, read_chunk(0, THIS)}, FunState); Length when Length > MaxChunkSize -> NewState = read_sub_chunks(Length, MaxChunkSize, Fun, FunState, THIS), stream_chunked_body(MaxChunkSize, Fun, NewState, THIS); Length -> NewState = Fun({Length, read_chunk(Length, THIS)}, FunState), stream_chunked_body(MaxChunkSize, Fun, NewState, THIS) end. stream_unchunked_body(0, Fun, FunState, {?MODULE, [_Socket, _Method, _RawPath, _Version, _Headers]}) -> Fun({0, <<>>}, FunState); stream_unchunked_body(Length, Fun, FunState, {?MODULE, [_Socket, _Method, _RawPath, _Version, _Headers]}=THIS) when Length > 0 -> PktSize = case Length > ?RECBUF_SIZE of true -> ?RECBUF_SIZE; false -> Length end, Bin = recv(PktSize, THIS), NewState = Fun({PktSize, Bin}, FunState), stream_unchunked_body(Length - PktSize, Fun, NewState, THIS). %% @spec read_chunk_length(request()) -> integer() %% @doc Read the length of the next HTTP chunk. read_chunk_length({?MODULE, [Socket, _Method, _RawPath, _Version, _Headers]}) -> ok = mochiweb_socket:setopts(Socket, [{packet, line}]), case mochiweb_socket:recv(Socket, 0, ?IDLE_TIMEOUT) of {ok, Header} -> ok = mochiweb_socket:setopts(Socket, [{packet, raw}]), Splitter = fun (C) -> C =/= $\r andalso C =/= $\n andalso C =/= $ end, {Hex, _Rest} = lists:splitwith(Splitter, binary_to_list(Header)), mochihex:to_int(Hex); _ -> exit(normal) end. %% @spec read_chunk(integer(), request()) -> Chunk::binary() | [Footer::binary()] %% @doc Read in a HTTP chunk of the given length. If Length is 0, then read the %% HTTP footers (as a list of binaries, since they're nominal). read_chunk(0, {?MODULE, [Socket, _Method, _RawPath, _Version, _Headers]}) -> ok = mochiweb_socket:setopts(Socket, [{packet, line}]), F = fun (F1, Acc) -> case mochiweb_socket:recv(Socket, 0, ?IDLE_TIMEOUT) of {ok, <<"\r\n">>} -> Acc; {ok, Footer} -> F1(F1, [Footer | Acc]); _ -> exit(normal) end end, Footers = F(F, []), ok = mochiweb_socket:setopts(Socket, [{packet, raw}]), put(?SAVE_RECV, true), Footers; read_chunk(Length, {?MODULE, [Socket, _Method, _RawPath, _Version, _Headers]}) -> case mochiweb_socket:recv(Socket, 2 + Length, ?IDLE_TIMEOUT) of {ok, <>} -> Chunk; _ -> exit(normal) end. read_sub_chunks(Length, MaxChunkSize, Fun, FunState, {?MODULE, [_Socket, _Method, _RawPath, _Version, _Headers]}=THIS) when Length > MaxChunkSize -> Bin = recv(MaxChunkSize, THIS), NewState = Fun({size(Bin), Bin}, FunState), read_sub_chunks(Length - MaxChunkSize, MaxChunkSize, Fun, NewState, THIS); read_sub_chunks(Length, _MaxChunkSize, Fun, FunState, {?MODULE, [_Socket, _Method, _RawPath, _Version, _Headers]}=THIS) -> Fun({Length, read_chunk(Length, THIS)}, FunState). %% @spec serve_file(Path, DocRoot, request()) -> Response %% @doc Serve a file relative to DocRoot. serve_file(Path, DocRoot, {?MODULE, [_Socket, _Method, _RawPath, _Version, _Headers]}=THIS) -> serve_file(Path, DocRoot, [], THIS). %% @spec serve_file(Path, DocRoot, ExtraHeaders, request()) -> Response %% @doc Serve a file relative to DocRoot. serve_file(Path, DocRoot, ExtraHeaders, {?MODULE, [_Socket, _Method, _RawPath, _Version, _Headers]}=THIS) -> case mochiweb_util:safe_relative_path(Path) of undefined -> not_found(ExtraHeaders, THIS); RelPath -> FullPath = filename:join([DocRoot, RelPath]), case filelib:is_dir(FullPath) of true -> maybe_redirect(RelPath, FullPath, ExtraHeaders, THIS); false -> maybe_serve_file(FullPath, ExtraHeaders, THIS) end end. %% Internal API %% This has the same effect as the DirectoryIndex directive in httpd directory_index(FullPath) -> filename:join([FullPath, "index.html"]). maybe_redirect([], FullPath, ExtraHeaders, {?MODULE, [_Socket, _Method, _RawPath, _Version, _Headers]}=THIS) -> maybe_serve_file(directory_index(FullPath), ExtraHeaders, THIS); maybe_redirect(RelPath, FullPath, ExtraHeaders, {?MODULE, [_Socket, _Method, _RawPath, _Version, Headers]}=THIS) -> case string:right(RelPath, 1) of "/" -> maybe_serve_file(directory_index(FullPath), ExtraHeaders, THIS); _ -> Host = mochiweb_headers:get_value("host", Headers), Location = "http://" ++ Host ++ "/" ++ RelPath ++ "/", LocationBin = list_to_binary(Location), MoreHeaders = [{"Location", Location}, {"Content-Type", "text/html"} | ExtraHeaders], Top = <<"" "" "301 Moved Permanently" "" "

    Moved Permanently

    " "

    The document has moved >, Bottom = <<">here.

    \n">>, Body = <>, respond({301, MoreHeaders, Body}, THIS) end. maybe_serve_file(File, ExtraHeaders, {?MODULE, [_Socket, _Method, _RawPath, _Version, _Headers]}=THIS) -> case file:read_file_info(File) of {ok, FileInfo} -> LastModified = httpd_util:rfc1123_date(FileInfo#file_info.mtime), case get_header_value("if-modified-since", THIS) of LastModified -> respond({304, ExtraHeaders, ""}, THIS); _ -> case file:open(File, [raw, binary]) of {ok, IoDevice} -> ContentType = mochiweb_util:guess_mime(File), Res = ok({ContentType, [{"last-modified", LastModified} | ExtraHeaders], {file, IoDevice}}, THIS), ok = file:close(IoDevice), Res; _ -> not_found(ExtraHeaders, THIS) end end; {error, _} -> not_found(ExtraHeaders, THIS) end. server_headers() -> [{"Server", "MochiWeb/1.0 (" ++ ?QUIP ++ ")"}, {"Date", httpd_util:rfc1123_date()}]. make_code(X) when is_integer(X) -> [integer_to_list(X), [" " | httpd_util:reason_phrase(X)]]; make_code(Io) when is_list(Io); is_binary(Io) -> Io. make_version({1, 0}) -> <<"HTTP/1.0 ">>; make_version(_) -> <<"HTTP/1.1 ">>. range_parts({file, IoDevice}, Ranges) -> Size = mochiweb_io:iodevice_size(IoDevice), F = fun (Spec, Acc) -> case mochiweb_http:range_skip_length(Spec, Size) of invalid_range -> Acc; V -> [V | Acc] end end, LocNums = lists:foldr(F, [], Ranges), {ok, Data} = file:pread(IoDevice, LocNums), Bodies = lists:zipwith(fun ({Skip, Length}, PartialBody) -> {Skip, Skip + Length - 1, PartialBody} end, LocNums, Data), {Bodies, Size}; range_parts(Body0, Ranges) -> Body = iolist_to_binary(Body0), Size = size(Body), F = fun(Spec, Acc) -> case mochiweb_http:range_skip_length(Spec, Size) of invalid_range -> Acc; {Skip, Length} -> <<_:Skip/binary, PartialBody:Length/binary, _/binary>> = Body, [{Skip, Skip + Length - 1, PartialBody} | Acc] end end, {lists:foldr(F, [], Ranges), Size}. %% @spec accepted_encodings([encoding()], request()) -> [encoding()] | bad_accept_encoding_value %% @type encoding() = string(). %% %% @doc Returns a list of encodings accepted by a request. Encodings that are %% not supported by the server will not be included in the return list. %% This list is computed from the "Accept-Encoding" header and %% its elements are ordered, descendingly, according to their Q values. %% %% Section 14.3 of the RFC 2616 (HTTP 1.1) describes the "Accept-Encoding" %% header and the process of determining which server supported encodings %% can be used for encoding the body for the request's response. %% %% Examples %% %% 1) For a missing "Accept-Encoding" header: %% accepted_encodings(["gzip", "identity"]) -> ["identity"] %% %% 2) For an "Accept-Encoding" header with value "gzip, deflate": %% accepted_encodings(["gzip", "identity"]) -> ["gzip", "identity"] %% %% 3) For an "Accept-Encoding" header with value "gzip;q=0.5, deflate": %% accepted_encodings(["gzip", "deflate", "identity"]) -> %% ["deflate", "gzip", "identity"] %% accepted_encodings(SupportedEncodings, {?MODULE, [_Socket, _Method, _RawPath, _Version, _Headers]}=THIS) -> AcceptEncodingHeader = case get_header_value("Accept-Encoding", THIS) of undefined -> ""; Value -> Value end, case mochiweb_util:parse_qvalues(AcceptEncodingHeader) of invalid_qvalue_string -> bad_accept_encoding_value; QList -> mochiweb_util:pick_accepted_encodings( QList, SupportedEncodings, "identity" ) end. %% @spec accepts_content_type(string() | binary(), request()) -> boolean() | bad_accept_header %% %% @doc Determines whether a request accepts a given media type by analyzing its %% "Accept" header. %% %% Examples %% %% 1) For a missing "Accept" header: %% accepts_content_type("application/json") -> true %% %% 2) For an "Accept" header with value "text/plain, application/*": %% accepts_content_type("application/json") -> true %% %% 3) For an "Accept" header with value "text/plain, */*; q=0.0": %% accepts_content_type("application/json") -> false %% %% 4) For an "Accept" header with value "text/plain; q=0.5, */*; q=0.1": %% accepts_content_type("application/json") -> true %% %% 5) For an "Accept" header with value "text/*; q=0.0, */*": %% accepts_content_type("text/plain") -> false %% accepts_content_type(ContentType1, {?MODULE, [_Socket, _Method, _RawPath, _Version, _Headers]}=THIS) -> ContentType = re:replace(ContentType1, "\\s", "", [global, {return, list}]), AcceptHeader = accept_header(THIS), case mochiweb_util:parse_qvalues(AcceptHeader) of invalid_qvalue_string -> bad_accept_header; QList -> [MainType, _SubType] = string:tokens(ContentType, "/"), SuperType = MainType ++ "/*", lists:any( fun({"*/*", Q}) when Q > 0.0 -> true; ({Type, Q}) when Q > 0.0 -> Type =:= ContentType orelse Type =:= SuperType; (_) -> false end, QList ) andalso (not lists:member({ContentType, 0.0}, QList)) andalso (not lists:member({SuperType, 0.0}, QList)) end. %% @spec accepted_content_types([string() | binary()], request()) -> [string()] | bad_accept_header %% %% @doc Filters which of the given media types this request accepts. This filtering %% is performed by analyzing the "Accept" header. The returned list is sorted %% according to the preferences specified in the "Accept" header (higher Q values %% first). If two or more types have the same preference (Q value), they're order %% in the returned list is the same as they're order in the input list. %% %% Examples %% %% 1) For a missing "Accept" header: %% accepted_content_types(["text/html", "application/json"]) -> %% ["text/html", "application/json"] %% %% 2) For an "Accept" header with value "text/html, application/*": %% accepted_content_types(["application/json", "text/html"]) -> %% ["application/json", "text/html"] %% %% 3) For an "Accept" header with value "text/html, */*; q=0.0": %% accepted_content_types(["text/html", "application/json"]) -> %% ["text/html"] %% %% 4) For an "Accept" header with value "text/html; q=0.5, */*; q=0.1": %% accepts_content_types(["application/json", "text/html"]) -> %% ["text/html", "application/json"] %% accepted_content_types(Types1, {?MODULE, [_Socket, _Method, _RawPath, _Version, _Headers]}=THIS) -> Types = lists:map( fun(T) -> re:replace(T, "\\s", "", [global, {return, list}]) end, Types1), AcceptHeader = accept_header(THIS), case mochiweb_util:parse_qvalues(AcceptHeader) of invalid_qvalue_string -> bad_accept_header; QList -> TypesQ = lists:foldr( fun(T, Acc) -> case proplists:get_value(T, QList) of undefined -> [MainType, _SubType] = string:tokens(T, "/"), case proplists:get_value(MainType ++ "/*", QList) of undefined -> case proplists:get_value("*/*", QList) of Q when is_float(Q), Q > 0.0 -> [{Q, T} | Acc]; _ -> Acc end; Q when Q > 0.0 -> [{Q, T} | Acc]; _ -> Acc end; Q when Q > 0.0 -> [{Q, T} | Acc]; _ -> Acc end end, [], Types), % Note: Stable sort. If 2 types have the same Q value we leave them in the % same order as in the input list. SortFun = fun({Q1, _}, {Q2, _}) -> Q1 >= Q2 end, [Type || {_Q, Type} <- lists:sort(SortFun, TypesQ)] end. accept_header({?MODULE, [_Socket, _Method, _RawPath, _Version, _Headers]}=THIS) -> case get_header_value("Accept", THIS) of undefined -> "*/*"; Value -> Value end. %% %% Tests %% -ifdef(TEST). -include_lib("eunit/include/eunit.hrl"). -endif. rabbitmq-server-3.2.4/plugins-src/mochiweb-wrapper/mochiweb-git/src/mochiweb_charref.erl0000644000000000000000000020415412305126066030213 0ustar rootroot%% @author Bob Ippolito %% @copyright 2007 Mochi Media, Inc. %% @doc Converts HTML 5 charrefs and entities to codepoints (or lists of code points). -module(mochiweb_charref). -export([charref/1]). %% External API. %% @doc Convert a decimal charref, hex charref, or html entity to a unicode %% codepoint, or return undefined on failure. %% The input should not include an ampersand or semicolon. %% charref("#38") = 38, charref("#x26") = 38, charref("amp") = 38. %% -spec charref(binary() | string()) -> integer() | [integer()] | undefined. charref(B) when is_binary(B) -> charref(binary_to_list(B)); charref([$#, C | L]) when C =:= $x orelse C =:= $X -> try erlang:list_to_integer(L, 16) catch error:badarg -> undefined end; charref([$# | L]) -> try list_to_integer(L) catch error:badarg -> undefined end; charref(L) -> entity(L). %% Internal API. %% [2011-10-14] Generated from: %% http://www.w3.org/TR/html5/named-character-references.html entity("AElig") -> 16#000C6; entity("AMP") -> 16#00026; entity("Aacute") -> 16#000C1; entity("Abreve") -> 16#00102; entity("Acirc") -> 16#000C2; entity("Acy") -> 16#00410; entity("Afr") -> 16#1D504; entity("Agrave") -> 16#000C0; entity("Alpha") -> 16#00391; entity("Amacr") -> 16#00100; entity("And") -> 16#02A53; entity("Aogon") -> 16#00104; entity("Aopf") -> 16#1D538; entity("ApplyFunction") -> 16#02061; entity("Aring") -> 16#000C5; entity("Ascr") -> 16#1D49C; entity("Assign") -> 16#02254; entity("Atilde") -> 16#000C3; entity("Auml") -> 16#000C4; entity("Backslash") -> 16#02216; entity("Barv") -> 16#02AE7; entity("Barwed") -> 16#02306; entity("Bcy") -> 16#00411; entity("Because") -> 16#02235; entity("Bernoullis") -> 16#0212C; entity("Beta") -> 16#00392; entity("Bfr") -> 16#1D505; entity("Bopf") -> 16#1D539; entity("Breve") -> 16#002D8; entity("Bscr") -> 16#0212C; entity("Bumpeq") -> 16#0224E; entity("CHcy") -> 16#00427; entity("COPY") -> 16#000A9; entity("Cacute") -> 16#00106; entity("Cap") -> 16#022D2; entity("CapitalDifferentialD") -> 16#02145; entity("Cayleys") -> 16#0212D; entity("Ccaron") -> 16#0010C; entity("Ccedil") -> 16#000C7; entity("Ccirc") -> 16#00108; entity("Cconint") -> 16#02230; entity("Cdot") -> 16#0010A; entity("Cedilla") -> 16#000B8; entity("CenterDot") -> 16#000B7; entity("Cfr") -> 16#0212D; entity("Chi") -> 16#003A7; entity("CircleDot") -> 16#02299; entity("CircleMinus") -> 16#02296; entity("CirclePlus") -> 16#02295; entity("CircleTimes") -> 16#02297; entity("ClockwiseContourIntegral") -> 16#02232; entity("CloseCurlyDoubleQuote") -> 16#0201D; entity("CloseCurlyQuote") -> 16#02019; entity("Colon") -> 16#02237; entity("Colone") -> 16#02A74; entity("Congruent") -> 16#02261; entity("Conint") -> 16#0222F; entity("ContourIntegral") -> 16#0222E; entity("Copf") -> 16#02102; entity("Coproduct") -> 16#02210; entity("CounterClockwiseContourIntegral") -> 16#02233; entity("Cross") -> 16#02A2F; entity("Cscr") -> 16#1D49E; entity("Cup") -> 16#022D3; entity("CupCap") -> 16#0224D; entity("DD") -> 16#02145; entity("DDotrahd") -> 16#02911; entity("DJcy") -> 16#00402; entity("DScy") -> 16#00405; entity("DZcy") -> 16#0040F; entity("Dagger") -> 16#02021; entity("Darr") -> 16#021A1; entity("Dashv") -> 16#02AE4; entity("Dcaron") -> 16#0010E; entity("Dcy") -> 16#00414; entity("Del") -> 16#02207; entity("Delta") -> 16#00394; entity("Dfr") -> 16#1D507; entity("DiacriticalAcute") -> 16#000B4; entity("DiacriticalDot") -> 16#002D9; entity("DiacriticalDoubleAcute") -> 16#002DD; entity("DiacriticalGrave") -> 16#00060; entity("DiacriticalTilde") -> 16#002DC; entity("Diamond") -> 16#022C4; entity("DifferentialD") -> 16#02146; entity("Dopf") -> 16#1D53B; entity("Dot") -> 16#000A8; entity("DotDot") -> 16#020DC; entity("DotEqual") -> 16#02250; entity("DoubleContourIntegral") -> 16#0222F; entity("DoubleDot") -> 16#000A8; entity("DoubleDownArrow") -> 16#021D3; entity("DoubleLeftArrow") -> 16#021D0; entity("DoubleLeftRightArrow") -> 16#021D4; entity("DoubleLeftTee") -> 16#02AE4; entity("DoubleLongLeftArrow") -> 16#027F8; entity("DoubleLongLeftRightArrow") -> 16#027FA; entity("DoubleLongRightArrow") -> 16#027F9; entity("DoubleRightArrow") -> 16#021D2; entity("DoubleRightTee") -> 16#022A8; entity("DoubleUpArrow") -> 16#021D1; entity("DoubleUpDownArrow") -> 16#021D5; entity("DoubleVerticalBar") -> 16#02225; entity("DownArrow") -> 16#02193; entity("DownArrowBar") -> 16#02913; entity("DownArrowUpArrow") -> 16#021F5; entity("DownBreve") -> 16#00311; entity("DownLeftRightVector") -> 16#02950; entity("DownLeftTeeVector") -> 16#0295E; entity("DownLeftVector") -> 16#021BD; entity("DownLeftVectorBar") -> 16#02956; entity("DownRightTeeVector") -> 16#0295F; entity("DownRightVector") -> 16#021C1; entity("DownRightVectorBar") -> 16#02957; entity("DownTee") -> 16#022A4; entity("DownTeeArrow") -> 16#021A7; entity("Downarrow") -> 16#021D3; entity("Dscr") -> 16#1D49F; entity("Dstrok") -> 16#00110; entity("ENG") -> 16#0014A; entity("ETH") -> 16#000D0; entity("Eacute") -> 16#000C9; entity("Ecaron") -> 16#0011A; entity("Ecirc") -> 16#000CA; entity("Ecy") -> 16#0042D; entity("Edot") -> 16#00116; entity("Efr") -> 16#1D508; entity("Egrave") -> 16#000C8; entity("Element") -> 16#02208; entity("Emacr") -> 16#00112; entity("EmptySmallSquare") -> 16#025FB; entity("EmptyVerySmallSquare") -> 16#025AB; entity("Eogon") -> 16#00118; entity("Eopf") -> 16#1D53C; entity("Epsilon") -> 16#00395; entity("Equal") -> 16#02A75; entity("EqualTilde") -> 16#02242; entity("Equilibrium") -> 16#021CC; entity("Escr") -> 16#02130; entity("Esim") -> 16#02A73; entity("Eta") -> 16#00397; entity("Euml") -> 16#000CB; entity("Exists") -> 16#02203; entity("ExponentialE") -> 16#02147; entity("Fcy") -> 16#00424; entity("Ffr") -> 16#1D509; entity("FilledSmallSquare") -> 16#025FC; entity("FilledVerySmallSquare") -> 16#025AA; entity("Fopf") -> 16#1D53D; entity("ForAll") -> 16#02200; entity("Fouriertrf") -> 16#02131; entity("Fscr") -> 16#02131; entity("GJcy") -> 16#00403; entity("GT") -> 16#0003E; entity("Gamma") -> 16#00393; entity("Gammad") -> 16#003DC; entity("Gbreve") -> 16#0011E; entity("Gcedil") -> 16#00122; entity("Gcirc") -> 16#0011C; entity("Gcy") -> 16#00413; entity("Gdot") -> 16#00120; entity("Gfr") -> 16#1D50A; entity("Gg") -> 16#022D9; entity("Gopf") -> 16#1D53E; entity("GreaterEqual") -> 16#02265; entity("GreaterEqualLess") -> 16#022DB; entity("GreaterFullEqual") -> 16#02267; entity("GreaterGreater") -> 16#02AA2; entity("GreaterLess") -> 16#02277; entity("GreaterSlantEqual") -> 16#02A7E; entity("GreaterTilde") -> 16#02273; entity("Gscr") -> 16#1D4A2; entity("Gt") -> 16#0226B; entity("HARDcy") -> 16#0042A; entity("Hacek") -> 16#002C7; entity("Hat") -> 16#0005E; entity("Hcirc") -> 16#00124; entity("Hfr") -> 16#0210C; entity("HilbertSpace") -> 16#0210B; entity("Hopf") -> 16#0210D; entity("HorizontalLine") -> 16#02500; entity("Hscr") -> 16#0210B; entity("Hstrok") -> 16#00126; entity("HumpDownHump") -> 16#0224E; entity("HumpEqual") -> 16#0224F; entity("IEcy") -> 16#00415; entity("IJlig") -> 16#00132; entity("IOcy") -> 16#00401; entity("Iacute") -> 16#000CD; entity("Icirc") -> 16#000CE; entity("Icy") -> 16#00418; entity("Idot") -> 16#00130; entity("Ifr") -> 16#02111; entity("Igrave") -> 16#000CC; entity("Im") -> 16#02111; entity("Imacr") -> 16#0012A; entity("ImaginaryI") -> 16#02148; entity("Implies") -> 16#021D2; entity("Int") -> 16#0222C; entity("Integral") -> 16#0222B; entity("Intersection") -> 16#022C2; entity("InvisibleComma") -> 16#02063; entity("InvisibleTimes") -> 16#02062; entity("Iogon") -> 16#0012E; entity("Iopf") -> 16#1D540; entity("Iota") -> 16#00399; entity("Iscr") -> 16#02110; entity("Itilde") -> 16#00128; entity("Iukcy") -> 16#00406; entity("Iuml") -> 16#000CF; entity("Jcirc") -> 16#00134; entity("Jcy") -> 16#00419; entity("Jfr") -> 16#1D50D; entity("Jopf") -> 16#1D541; entity("Jscr") -> 16#1D4A5; entity("Jsercy") -> 16#00408; entity("Jukcy") -> 16#00404; entity("KHcy") -> 16#00425; entity("KJcy") -> 16#0040C; entity("Kappa") -> 16#0039A; entity("Kcedil") -> 16#00136; entity("Kcy") -> 16#0041A; entity("Kfr") -> 16#1D50E; entity("Kopf") -> 16#1D542; entity("Kscr") -> 16#1D4A6; entity("LJcy") -> 16#00409; entity("LT") -> 16#0003C; entity("Lacute") -> 16#00139; entity("Lambda") -> 16#0039B; entity("Lang") -> 16#027EA; entity("Laplacetrf") -> 16#02112; entity("Larr") -> 16#0219E; entity("Lcaron") -> 16#0013D; entity("Lcedil") -> 16#0013B; entity("Lcy") -> 16#0041B; entity("LeftAngleBracket") -> 16#027E8; entity("LeftArrow") -> 16#02190; entity("LeftArrowBar") -> 16#021E4; entity("LeftArrowRightArrow") -> 16#021C6; entity("LeftCeiling") -> 16#02308; entity("LeftDoubleBracket") -> 16#027E6; entity("LeftDownTeeVector") -> 16#02961; entity("LeftDownVector") -> 16#021C3; entity("LeftDownVectorBar") -> 16#02959; entity("LeftFloor") -> 16#0230A; entity("LeftRightArrow") -> 16#02194; entity("LeftRightVector") -> 16#0294E; entity("LeftTee") -> 16#022A3; entity("LeftTeeArrow") -> 16#021A4; entity("LeftTeeVector") -> 16#0295A; entity("LeftTriangle") -> 16#022B2; entity("LeftTriangleBar") -> 16#029CF; entity("LeftTriangleEqual") -> 16#022B4; entity("LeftUpDownVector") -> 16#02951; entity("LeftUpTeeVector") -> 16#02960; entity("LeftUpVector") -> 16#021BF; entity("LeftUpVectorBar") -> 16#02958; entity("LeftVector") -> 16#021BC; entity("LeftVectorBar") -> 16#02952; entity("Leftarrow") -> 16#021D0; entity("Leftrightarrow") -> 16#021D4; entity("LessEqualGreater") -> 16#022DA; entity("LessFullEqual") -> 16#02266; entity("LessGreater") -> 16#02276; entity("LessLess") -> 16#02AA1; entity("LessSlantEqual") -> 16#02A7D; entity("LessTilde") -> 16#02272; entity("Lfr") -> 16#1D50F; entity("Ll") -> 16#022D8; entity("Lleftarrow") -> 16#021DA; entity("Lmidot") -> 16#0013F; entity("LongLeftArrow") -> 16#027F5; entity("LongLeftRightArrow") -> 16#027F7; entity("LongRightArrow") -> 16#027F6; entity("Longleftarrow") -> 16#027F8; entity("Longleftrightarrow") -> 16#027FA; entity("Longrightarrow") -> 16#027F9; entity("Lopf") -> 16#1D543; entity("LowerLeftArrow") -> 16#02199; entity("LowerRightArrow") -> 16#02198; entity("Lscr") -> 16#02112; entity("Lsh") -> 16#021B0; entity("Lstrok") -> 16#00141; entity("Lt") -> 16#0226A; entity("Map") -> 16#02905; entity("Mcy") -> 16#0041C; entity("MediumSpace") -> 16#0205F; entity("Mellintrf") -> 16#02133; entity("Mfr") -> 16#1D510; entity("MinusPlus") -> 16#02213; entity("Mopf") -> 16#1D544; entity("Mscr") -> 16#02133; entity("Mu") -> 16#0039C; entity("NJcy") -> 16#0040A; entity("Nacute") -> 16#00143; entity("Ncaron") -> 16#00147; entity("Ncedil") -> 16#00145; entity("Ncy") -> 16#0041D; entity("NegativeMediumSpace") -> 16#0200B; entity("NegativeThickSpace") -> 16#0200B; entity("NegativeThinSpace") -> 16#0200B; entity("NegativeVeryThinSpace") -> 16#0200B; entity("NestedGreaterGreater") -> 16#0226B; entity("NestedLessLess") -> 16#0226A; entity("NewLine") -> 16#0000A; entity("Nfr") -> 16#1D511; entity("NoBreak") -> 16#02060; entity("NonBreakingSpace") -> 16#000A0; entity("Nopf") -> 16#02115; entity("Not") -> 16#02AEC; entity("NotCongruent") -> 16#02262; entity("NotCupCap") -> 16#0226D; entity("NotDoubleVerticalBar") -> 16#02226; entity("NotElement") -> 16#02209; entity("NotEqual") -> 16#02260; entity("NotEqualTilde") -> [16#02242, 16#00338]; entity("NotExists") -> 16#02204; entity("NotGreater") -> 16#0226F; entity("NotGreaterEqual") -> 16#02271; entity("NotGreaterFullEqual") -> [16#02267, 16#00338]; entity("NotGreaterGreater") -> [16#0226B, 16#00338]; entity("NotGreaterLess") -> 16#02279; entity("NotGreaterSlantEqual") -> [16#02A7E, 16#00338]; entity("NotGreaterTilde") -> 16#02275; entity("NotHumpDownHump") -> [16#0224E, 16#00338]; entity("NotHumpEqual") -> [16#0224F, 16#00338]; entity("NotLeftTriangle") -> 16#022EA; entity("NotLeftTriangleBar") -> [16#029CF, 16#00338]; entity("NotLeftTriangleEqual") -> 16#022EC; entity("NotLess") -> 16#0226E; entity("NotLessEqual") -> 16#02270; entity("NotLessGreater") -> 16#02278; entity("NotLessLess") -> [16#0226A, 16#00338]; entity("NotLessSlantEqual") -> [16#02A7D, 16#00338]; entity("NotLessTilde") -> 16#02274; entity("NotNestedGreaterGreater") -> [16#02AA2, 16#00338]; entity("NotNestedLessLess") -> [16#02AA1, 16#00338]; entity("NotPrecedes") -> 16#02280; entity("NotPrecedesEqual") -> [16#02AAF, 16#00338]; entity("NotPrecedesSlantEqual") -> 16#022E0; entity("NotReverseElement") -> 16#0220C; entity("NotRightTriangle") -> 16#022EB; entity("NotRightTriangleBar") -> [16#029D0, 16#00338]; entity("NotRightTriangleEqual") -> 16#022ED; entity("NotSquareSubset") -> [16#0228F, 16#00338]; entity("NotSquareSubsetEqual") -> 16#022E2; entity("NotSquareSuperset") -> [16#02290, 16#00338]; entity("NotSquareSupersetEqual") -> 16#022E3; entity("NotSubset") -> [16#02282, 16#020D2]; entity("NotSubsetEqual") -> 16#02288; entity("NotSucceeds") -> 16#02281; entity("NotSucceedsEqual") -> [16#02AB0, 16#00338]; entity("NotSucceedsSlantEqual") -> 16#022E1; entity("NotSucceedsTilde") -> [16#0227F, 16#00338]; entity("NotSuperset") -> [16#02283, 16#020D2]; entity("NotSupersetEqual") -> 16#02289; entity("NotTilde") -> 16#02241; entity("NotTildeEqual") -> 16#02244; entity("NotTildeFullEqual") -> 16#02247; entity("NotTildeTilde") -> 16#02249; entity("NotVerticalBar") -> 16#02224; entity("Nscr") -> 16#1D4A9; entity("Ntilde") -> 16#000D1; entity("Nu") -> 16#0039D; entity("OElig") -> 16#00152; entity("Oacute") -> 16#000D3; entity("Ocirc") -> 16#000D4; entity("Ocy") -> 16#0041E; entity("Odblac") -> 16#00150; entity("Ofr") -> 16#1D512; entity("Ograve") -> 16#000D2; entity("Omacr") -> 16#0014C; entity("Omega") -> 16#003A9; entity("Omicron") -> 16#0039F; entity("Oopf") -> 16#1D546; entity("OpenCurlyDoubleQuote") -> 16#0201C; entity("OpenCurlyQuote") -> 16#02018; entity("Or") -> 16#02A54; entity("Oscr") -> 16#1D4AA; entity("Oslash") -> 16#000D8; entity("Otilde") -> 16#000D5; entity("Otimes") -> 16#02A37; entity("Ouml") -> 16#000D6; entity("OverBar") -> 16#0203E; entity("OverBrace") -> 16#023DE; entity("OverBracket") -> 16#023B4; entity("OverParenthesis") -> 16#023DC; entity("PartialD") -> 16#02202; entity("Pcy") -> 16#0041F; entity("Pfr") -> 16#1D513; entity("Phi") -> 16#003A6; entity("Pi") -> 16#003A0; entity("PlusMinus") -> 16#000B1; entity("Poincareplane") -> 16#0210C; entity("Popf") -> 16#02119; entity("Pr") -> 16#02ABB; entity("Precedes") -> 16#0227A; entity("PrecedesEqual") -> 16#02AAF; entity("PrecedesSlantEqual") -> 16#0227C; entity("PrecedesTilde") -> 16#0227E; entity("Prime") -> 16#02033; entity("Product") -> 16#0220F; entity("Proportion") -> 16#02237; entity("Proportional") -> 16#0221D; entity("Pscr") -> 16#1D4AB; entity("Psi") -> 16#003A8; entity("QUOT") -> 16#00022; entity("Qfr") -> 16#1D514; entity("Qopf") -> 16#0211A; entity("Qscr") -> 16#1D4AC; entity("RBarr") -> 16#02910; entity("REG") -> 16#000AE; entity("Racute") -> 16#00154; entity("Rang") -> 16#027EB; entity("Rarr") -> 16#021A0; entity("Rarrtl") -> 16#02916; entity("Rcaron") -> 16#00158; entity("Rcedil") -> 16#00156; entity("Rcy") -> 16#00420; entity("Re") -> 16#0211C; entity("ReverseElement") -> 16#0220B; entity("ReverseEquilibrium") -> 16#021CB; entity("ReverseUpEquilibrium") -> 16#0296F; entity("Rfr") -> 16#0211C; entity("Rho") -> 16#003A1; entity("RightAngleBracket") -> 16#027E9; entity("RightArrow") -> 16#02192; entity("RightArrowBar") -> 16#021E5; entity("RightArrowLeftArrow") -> 16#021C4; entity("RightCeiling") -> 16#02309; entity("RightDoubleBracket") -> 16#027E7; entity("RightDownTeeVector") -> 16#0295D; entity("RightDownVector") -> 16#021C2; entity("RightDownVectorBar") -> 16#02955; entity("RightFloor") -> 16#0230B; entity("RightTee") -> 16#022A2; entity("RightTeeArrow") -> 16#021A6; entity("RightTeeVector") -> 16#0295B; entity("RightTriangle") -> 16#022B3; entity("RightTriangleBar") -> 16#029D0; entity("RightTriangleEqual") -> 16#022B5; entity("RightUpDownVector") -> 16#0294F; entity("RightUpTeeVector") -> 16#0295C; entity("RightUpVector") -> 16#021BE; entity("RightUpVectorBar") -> 16#02954; entity("RightVector") -> 16#021C0; entity("RightVectorBar") -> 16#02953; entity("Rightarrow") -> 16#021D2; entity("Ropf") -> 16#0211D; entity("RoundImplies") -> 16#02970; entity("Rrightarrow") -> 16#021DB; entity("Rscr") -> 16#0211B; entity("Rsh") -> 16#021B1; entity("RuleDelayed") -> 16#029F4; entity("SHCHcy") -> 16#00429; entity("SHcy") -> 16#00428; entity("SOFTcy") -> 16#0042C; entity("Sacute") -> 16#0015A; entity("Sc") -> 16#02ABC; entity("Scaron") -> 16#00160; entity("Scedil") -> 16#0015E; entity("Scirc") -> 16#0015C; entity("Scy") -> 16#00421; entity("Sfr") -> 16#1D516; entity("ShortDownArrow") -> 16#02193; entity("ShortLeftArrow") -> 16#02190; entity("ShortRightArrow") -> 16#02192; entity("ShortUpArrow") -> 16#02191; entity("Sigma") -> 16#003A3; entity("SmallCircle") -> 16#02218; entity("Sopf") -> 16#1D54A; entity("Sqrt") -> 16#0221A; entity("Square") -> 16#025A1; entity("SquareIntersection") -> 16#02293; entity("SquareSubset") -> 16#0228F; entity("SquareSubsetEqual") -> 16#02291; entity("SquareSuperset") -> 16#02290; entity("SquareSupersetEqual") -> 16#02292; entity("SquareUnion") -> 16#02294; entity("Sscr") -> 16#1D4AE; entity("Star") -> 16#022C6; entity("Sub") -> 16#022D0; entity("Subset") -> 16#022D0; entity("SubsetEqual") -> 16#02286; entity("Succeeds") -> 16#0227B; entity("SucceedsEqual") -> 16#02AB0; entity("SucceedsSlantEqual") -> 16#0227D; entity("SucceedsTilde") -> 16#0227F; entity("SuchThat") -> 16#0220B; entity("Sum") -> 16#02211; entity("Sup") -> 16#022D1; entity("Superset") -> 16#02283; entity("SupersetEqual") -> 16#02287; entity("Supset") -> 16#022D1; entity("THORN") -> 16#000DE; entity("TRADE") -> 16#02122; entity("TSHcy") -> 16#0040B; entity("TScy") -> 16#00426; entity("Tab") -> 16#00009; entity("Tau") -> 16#003A4; entity("Tcaron") -> 16#00164; entity("Tcedil") -> 16#00162; entity("Tcy") -> 16#00422; entity("Tfr") -> 16#1D517; entity("Therefore") -> 16#02234; entity("Theta") -> 16#00398; entity("ThickSpace") -> [16#0205F, 16#0200A]; entity("ThinSpace") -> 16#02009; entity("Tilde") -> 16#0223C; entity("TildeEqual") -> 16#02243; entity("TildeFullEqual") -> 16#02245; entity("TildeTilde") -> 16#02248; entity("Topf") -> 16#1D54B; entity("TripleDot") -> 16#020DB; entity("Tscr") -> 16#1D4AF; entity("Tstrok") -> 16#00166; entity("Uacute") -> 16#000DA; entity("Uarr") -> 16#0219F; entity("Uarrocir") -> 16#02949; entity("Ubrcy") -> 16#0040E; entity("Ubreve") -> 16#0016C; entity("Ucirc") -> 16#000DB; entity("Ucy") -> 16#00423; entity("Udblac") -> 16#00170; entity("Ufr") -> 16#1D518; entity("Ugrave") -> 16#000D9; entity("Umacr") -> 16#0016A; entity("UnderBar") -> 16#0005F; entity("UnderBrace") -> 16#023DF; entity("UnderBracket") -> 16#023B5; entity("UnderParenthesis") -> 16#023DD; entity("Union") -> 16#022C3; entity("UnionPlus") -> 16#0228E; entity("Uogon") -> 16#00172; entity("Uopf") -> 16#1D54C; entity("UpArrow") -> 16#02191; entity("UpArrowBar") -> 16#02912; entity("UpArrowDownArrow") -> 16#021C5; entity("UpDownArrow") -> 16#02195; entity("UpEquilibrium") -> 16#0296E; entity("UpTee") -> 16#022A5; entity("UpTeeArrow") -> 16#021A5; entity("Uparrow") -> 16#021D1; entity("Updownarrow") -> 16#021D5; entity("UpperLeftArrow") -> 16#02196; entity("UpperRightArrow") -> 16#02197; entity("Upsi") -> 16#003D2; entity("Upsilon") -> 16#003A5; entity("Uring") -> 16#0016E; entity("Uscr") -> 16#1D4B0; entity("Utilde") -> 16#00168; entity("Uuml") -> 16#000DC; entity("VDash") -> 16#022AB; entity("Vbar") -> 16#02AEB; entity("Vcy") -> 16#00412; entity("Vdash") -> 16#022A9; entity("Vdashl") -> 16#02AE6; entity("Vee") -> 16#022C1; entity("Verbar") -> 16#02016; entity("Vert") -> 16#02016; entity("VerticalBar") -> 16#02223; entity("VerticalLine") -> 16#0007C; entity("VerticalSeparator") -> 16#02758; entity("VerticalTilde") -> 16#02240; entity("VeryThinSpace") -> 16#0200A; entity("Vfr") -> 16#1D519; entity("Vopf") -> 16#1D54D; entity("Vscr") -> 16#1D4B1; entity("Vvdash") -> 16#022AA; entity("Wcirc") -> 16#00174; entity("Wedge") -> 16#022C0; entity("Wfr") -> 16#1D51A; entity("Wopf") -> 16#1D54E; entity("Wscr") -> 16#1D4B2; entity("Xfr") -> 16#1D51B; entity("Xi") -> 16#0039E; entity("Xopf") -> 16#1D54F; entity("Xscr") -> 16#1D4B3; entity("YAcy") -> 16#0042F; entity("YIcy") -> 16#00407; entity("YUcy") -> 16#0042E; entity("Yacute") -> 16#000DD; entity("Ycirc") -> 16#00176; entity("Ycy") -> 16#0042B; entity("Yfr") -> 16#1D51C; entity("Yopf") -> 16#1D550; entity("Yscr") -> 16#1D4B4; entity("Yuml") -> 16#00178; entity("ZHcy") -> 16#00416; entity("Zacute") -> 16#00179; entity("Zcaron") -> 16#0017D; entity("Zcy") -> 16#00417; entity("Zdot") -> 16#0017B; entity("ZeroWidthSpace") -> 16#0200B; entity("Zeta") -> 16#00396; entity("Zfr") -> 16#02128; entity("Zopf") -> 16#02124; entity("Zscr") -> 16#1D4B5; entity("aacute") -> 16#000E1; entity("abreve") -> 16#00103; entity("ac") -> 16#0223E; entity("acE") -> [16#0223E, 16#00333]; entity("acd") -> 16#0223F; entity("acirc") -> 16#000E2; entity("acute") -> 16#000B4; entity("acy") -> 16#00430; entity("aelig") -> 16#000E6; entity("af") -> 16#02061; entity("afr") -> 16#1D51E; entity("agrave") -> 16#000E0; entity("alefsym") -> 16#02135; entity("aleph") -> 16#02135; entity("alpha") -> 16#003B1; entity("amacr") -> 16#00101; entity("amalg") -> 16#02A3F; entity("amp") -> 16#00026; entity("and") -> 16#02227; entity("andand") -> 16#02A55; entity("andd") -> 16#02A5C; entity("andslope") -> 16#02A58; entity("andv") -> 16#02A5A; entity("ang") -> 16#02220; entity("ange") -> 16#029A4; entity("angle") -> 16#02220; entity("angmsd") -> 16#02221; entity("angmsdaa") -> 16#029A8; entity("angmsdab") -> 16#029A9; entity("angmsdac") -> 16#029AA; entity("angmsdad") -> 16#029AB; entity("angmsdae") -> 16#029AC; entity("angmsdaf") -> 16#029AD; entity("angmsdag") -> 16#029AE; entity("angmsdah") -> 16#029AF; entity("angrt") -> 16#0221F; entity("angrtvb") -> 16#022BE; entity("angrtvbd") -> 16#0299D; entity("angsph") -> 16#02222; entity("angst") -> 16#000C5; entity("angzarr") -> 16#0237C; entity("aogon") -> 16#00105; entity("aopf") -> 16#1D552; entity("ap") -> 16#02248; entity("apE") -> 16#02A70; entity("apacir") -> 16#02A6F; entity("ape") -> 16#0224A; entity("apid") -> 16#0224B; entity("apos") -> 16#00027; entity("approx") -> 16#02248; entity("approxeq") -> 16#0224A; entity("aring") -> 16#000E5; entity("ascr") -> 16#1D4B6; entity("ast") -> 16#0002A; entity("asymp") -> 16#02248; entity("asympeq") -> 16#0224D; entity("atilde") -> 16#000E3; entity("auml") -> 16#000E4; entity("awconint") -> 16#02233; entity("awint") -> 16#02A11; entity("bNot") -> 16#02AED; entity("backcong") -> 16#0224C; entity("backepsilon") -> 16#003F6; entity("backprime") -> 16#02035; entity("backsim") -> 16#0223D; entity("backsimeq") -> 16#022CD; entity("barvee") -> 16#022BD; entity("barwed") -> 16#02305; entity("barwedge") -> 16#02305; entity("bbrk") -> 16#023B5; entity("bbrktbrk") -> 16#023B6; entity("bcong") -> 16#0224C; entity("bcy") -> 16#00431; entity("bdquo") -> 16#0201E; entity("becaus") -> 16#02235; entity("because") -> 16#02235; entity("bemptyv") -> 16#029B0; entity("bepsi") -> 16#003F6; entity("bernou") -> 16#0212C; entity("beta") -> 16#003B2; entity("beth") -> 16#02136; entity("between") -> 16#0226C; entity("bfr") -> 16#1D51F; entity("bigcap") -> 16#022C2; entity("bigcirc") -> 16#025EF; entity("bigcup") -> 16#022C3; entity("bigodot") -> 16#02A00; entity("bigoplus") -> 16#02A01; entity("bigotimes") -> 16#02A02; entity("bigsqcup") -> 16#02A06; entity("bigstar") -> 16#02605; entity("bigtriangledown") -> 16#025BD; entity("bigtriangleup") -> 16#025B3; entity("biguplus") -> 16#02A04; entity("bigvee") -> 16#022C1; entity("bigwedge") -> 16#022C0; entity("bkarow") -> 16#0290D; entity("blacklozenge") -> 16#029EB; entity("blacksquare") -> 16#025AA; entity("blacktriangle") -> 16#025B4; entity("blacktriangledown") -> 16#025BE; entity("blacktriangleleft") -> 16#025C2; entity("blacktriangleright") -> 16#025B8; entity("blank") -> 16#02423; entity("blk12") -> 16#02592; entity("blk14") -> 16#02591; entity("blk34") -> 16#02593; entity("block") -> 16#02588; entity("bne") -> [16#0003D, 16#020E5]; entity("bnequiv") -> [16#02261, 16#020E5]; entity("bnot") -> 16#02310; entity("bopf") -> 16#1D553; entity("bot") -> 16#022A5; entity("bottom") -> 16#022A5; entity("bowtie") -> 16#022C8; entity("boxDL") -> 16#02557; entity("boxDR") -> 16#02554; entity("boxDl") -> 16#02556; entity("boxDr") -> 16#02553; entity("boxH") -> 16#02550; entity("boxHD") -> 16#02566; entity("boxHU") -> 16#02569; entity("boxHd") -> 16#02564; entity("boxHu") -> 16#02567; entity("boxUL") -> 16#0255D; entity("boxUR") -> 16#0255A; entity("boxUl") -> 16#0255C; entity("boxUr") -> 16#02559; entity("boxV") -> 16#02551; entity("boxVH") -> 16#0256C; entity("boxVL") -> 16#02563; entity("boxVR") -> 16#02560; entity("boxVh") -> 16#0256B; entity("boxVl") -> 16#02562; entity("boxVr") -> 16#0255F; entity("boxbox") -> 16#029C9; entity("boxdL") -> 16#02555; entity("boxdR") -> 16#02552; entity("boxdl") -> 16#02510; entity("boxdr") -> 16#0250C; entity("boxh") -> 16#02500; entity("boxhD") -> 16#02565; entity("boxhU") -> 16#02568; entity("boxhd") -> 16#0252C; entity("boxhu") -> 16#02534; entity("boxminus") -> 16#0229F; entity("boxplus") -> 16#0229E; entity("boxtimes") -> 16#022A0; entity("boxuL") -> 16#0255B; entity("boxuR") -> 16#02558; entity("boxul") -> 16#02518; entity("boxur") -> 16#02514; entity("boxv") -> 16#02502; entity("boxvH") -> 16#0256A; entity("boxvL") -> 16#02561; entity("boxvR") -> 16#0255E; entity("boxvh") -> 16#0253C; entity("boxvl") -> 16#02524; entity("boxvr") -> 16#0251C; entity("bprime") -> 16#02035; entity("breve") -> 16#002D8; entity("brvbar") -> 16#000A6; entity("bscr") -> 16#1D4B7; entity("bsemi") -> 16#0204F; entity("bsim") -> 16#0223D; entity("bsime") -> 16#022CD; entity("bsol") -> 16#0005C; entity("bsolb") -> 16#029C5; entity("bsolhsub") -> 16#027C8; entity("bull") -> 16#02022; entity("bullet") -> 16#02022; entity("bump") -> 16#0224E; entity("bumpE") -> 16#02AAE; entity("bumpe") -> 16#0224F; entity("bumpeq") -> 16#0224F; entity("cacute") -> 16#00107; entity("cap") -> 16#02229; entity("capand") -> 16#02A44; entity("capbrcup") -> 16#02A49; entity("capcap") -> 16#02A4B; entity("capcup") -> 16#02A47; entity("capdot") -> 16#02A40; entity("caps") -> [16#02229, 16#0FE00]; entity("caret") -> 16#02041; entity("caron") -> 16#002C7; entity("ccaps") -> 16#02A4D; entity("ccaron") -> 16#0010D; entity("ccedil") -> 16#000E7; entity("ccirc") -> 16#00109; entity("ccups") -> 16#02A4C; entity("ccupssm") -> 16#02A50; entity("cdot") -> 16#0010B; entity("cedil") -> 16#000B8; entity("cemptyv") -> 16#029B2; entity("cent") -> 16#000A2; entity("centerdot") -> 16#000B7; entity("cfr") -> 16#1D520; entity("chcy") -> 16#00447; entity("check") -> 16#02713; entity("checkmark") -> 16#02713; entity("chi") -> 16#003C7; entity("cir") -> 16#025CB; entity("cirE") -> 16#029C3; entity("circ") -> 16#002C6; entity("circeq") -> 16#02257; entity("circlearrowleft") -> 16#021BA; entity("circlearrowright") -> 16#021BB; entity("circledR") -> 16#000AE; entity("circledS") -> 16#024C8; entity("circledast") -> 16#0229B; entity("circledcirc") -> 16#0229A; entity("circleddash") -> 16#0229D; entity("cire") -> 16#02257; entity("cirfnint") -> 16#02A10; entity("cirmid") -> 16#02AEF; entity("cirscir") -> 16#029C2; entity("clubs") -> 16#02663; entity("clubsuit") -> 16#02663; entity("colon") -> 16#0003A; entity("colone") -> 16#02254; entity("coloneq") -> 16#02254; entity("comma") -> 16#0002C; entity("commat") -> 16#00040; entity("comp") -> 16#02201; entity("compfn") -> 16#02218; entity("complement") -> 16#02201; entity("complexes") -> 16#02102; entity("cong") -> 16#02245; entity("congdot") -> 16#02A6D; entity("conint") -> 16#0222E; entity("copf") -> 16#1D554; entity("coprod") -> 16#02210; entity("copy") -> 16#000A9; entity("copysr") -> 16#02117; entity("crarr") -> 16#021B5; entity("cross") -> 16#02717; entity("cscr") -> 16#1D4B8; entity("csub") -> 16#02ACF; entity("csube") -> 16#02AD1; entity("csup") -> 16#02AD0; entity("csupe") -> 16#02AD2; entity("ctdot") -> 16#022EF; entity("cudarrl") -> 16#02938; entity("cudarrr") -> 16#02935; entity("cuepr") -> 16#022DE; entity("cuesc") -> 16#022DF; entity("cularr") -> 16#021B6; entity("cularrp") -> 16#0293D; entity("cup") -> 16#0222A; entity("cupbrcap") -> 16#02A48; entity("cupcap") -> 16#02A46; entity("cupcup") -> 16#02A4A; entity("cupdot") -> 16#0228D; entity("cupor") -> 16#02A45; entity("cups") -> [16#0222A, 16#0FE00]; entity("curarr") -> 16#021B7; entity("curarrm") -> 16#0293C; entity("curlyeqprec") -> 16#022DE; entity("curlyeqsucc") -> 16#022DF; entity("curlyvee") -> 16#022CE; entity("curlywedge") -> 16#022CF; entity("curren") -> 16#000A4; entity("curvearrowleft") -> 16#021B6; entity("curvearrowright") -> 16#021B7; entity("cuvee") -> 16#022CE; entity("cuwed") -> 16#022CF; entity("cwconint") -> 16#02232; entity("cwint") -> 16#02231; entity("cylcty") -> 16#0232D; entity("dArr") -> 16#021D3; entity("dHar") -> 16#02965; entity("dagger") -> 16#02020; entity("daleth") -> 16#02138; entity("darr") -> 16#02193; entity("dash") -> 16#02010; entity("dashv") -> 16#022A3; entity("dbkarow") -> 16#0290F; entity("dblac") -> 16#002DD; entity("dcaron") -> 16#0010F; entity("dcy") -> 16#00434; entity("dd") -> 16#02146; entity("ddagger") -> 16#02021; entity("ddarr") -> 16#021CA; entity("ddotseq") -> 16#02A77; entity("deg") -> 16#000B0; entity("delta") -> 16#003B4; entity("demptyv") -> 16#029B1; entity("dfisht") -> 16#0297F; entity("dfr") -> 16#1D521; entity("dharl") -> 16#021C3; entity("dharr") -> 16#021C2; entity("diam") -> 16#022C4; entity("diamond") -> 16#022C4; entity("diamondsuit") -> 16#02666; entity("diams") -> 16#02666; entity("die") -> 16#000A8; entity("digamma") -> 16#003DD; entity("disin") -> 16#022F2; entity("div") -> 16#000F7; entity("divide") -> 16#000F7; entity("divideontimes") -> 16#022C7; entity("divonx") -> 16#022C7; entity("djcy") -> 16#00452; entity("dlcorn") -> 16#0231E; entity("dlcrop") -> 16#0230D; entity("dollar") -> 16#00024; entity("dopf") -> 16#1D555; entity("dot") -> 16#002D9; entity("doteq") -> 16#02250; entity("doteqdot") -> 16#02251; entity("dotminus") -> 16#02238; entity("dotplus") -> 16#02214; entity("dotsquare") -> 16#022A1; entity("doublebarwedge") -> 16#02306; entity("downarrow") -> 16#02193; entity("downdownarrows") -> 16#021CA; entity("downharpoonleft") -> 16#021C3; entity("downharpoonright") -> 16#021C2; entity("drbkarow") -> 16#02910; entity("drcorn") -> 16#0231F; entity("drcrop") -> 16#0230C; entity("dscr") -> 16#1D4B9; entity("dscy") -> 16#00455; entity("dsol") -> 16#029F6; entity("dstrok") -> 16#00111; entity("dtdot") -> 16#022F1; entity("dtri") -> 16#025BF; entity("dtrif") -> 16#025BE; entity("duarr") -> 16#021F5; entity("duhar") -> 16#0296F; entity("dwangle") -> 16#029A6; entity("dzcy") -> 16#0045F; entity("dzigrarr") -> 16#027FF; entity("eDDot") -> 16#02A77; entity("eDot") -> 16#02251; entity("eacute") -> 16#000E9; entity("easter") -> 16#02A6E; entity("ecaron") -> 16#0011B; entity("ecir") -> 16#02256; entity("ecirc") -> 16#000EA; entity("ecolon") -> 16#02255; entity("ecy") -> 16#0044D; entity("edot") -> 16#00117; entity("ee") -> 16#02147; entity("efDot") -> 16#02252; entity("efr") -> 16#1D522; entity("eg") -> 16#02A9A; entity("egrave") -> 16#000E8; entity("egs") -> 16#02A96; entity("egsdot") -> 16#02A98; entity("el") -> 16#02A99; entity("elinters") -> 16#023E7; entity("ell") -> 16#02113; entity("els") -> 16#02A95; entity("elsdot") -> 16#02A97; entity("emacr") -> 16#00113; entity("empty") -> 16#02205; entity("emptyset") -> 16#02205; entity("emptyv") -> 16#02205; entity("emsp") -> 16#02003; entity("emsp13") -> 16#02004; entity("emsp14") -> 16#02005; entity("eng") -> 16#0014B; entity("ensp") -> 16#02002; entity("eogon") -> 16#00119; entity("eopf") -> 16#1D556; entity("epar") -> 16#022D5; entity("eparsl") -> 16#029E3; entity("eplus") -> 16#02A71; entity("epsi") -> 16#003B5; entity("epsilon") -> 16#003B5; entity("epsiv") -> 16#003F5; entity("eqcirc") -> 16#02256; entity("eqcolon") -> 16#02255; entity("eqsim") -> 16#02242; entity("eqslantgtr") -> 16#02A96; entity("eqslantless") -> 16#02A95; entity("equals") -> 16#0003D; entity("equest") -> 16#0225F; entity("equiv") -> 16#02261; entity("equivDD") -> 16#02A78; entity("eqvparsl") -> 16#029E5; entity("erDot") -> 16#02253; entity("erarr") -> 16#02971; entity("escr") -> 16#0212F; entity("esdot") -> 16#02250; entity("esim") -> 16#02242; entity("eta") -> 16#003B7; entity("eth") -> 16#000F0; entity("euml") -> 16#000EB; entity("euro") -> 16#020AC; entity("excl") -> 16#00021; entity("exist") -> 16#02203; entity("expectation") -> 16#02130; entity("exponentiale") -> 16#02147; entity("fallingdotseq") -> 16#02252; entity("fcy") -> 16#00444; entity("female") -> 16#02640; entity("ffilig") -> 16#0FB03; entity("fflig") -> 16#0FB00; entity("ffllig") -> 16#0FB04; entity("ffr") -> 16#1D523; entity("filig") -> 16#0FB01; entity("fjlig") -> [16#00066, 16#0006A]; entity("flat") -> 16#0266D; entity("fllig") -> 16#0FB02; entity("fltns") -> 16#025B1; entity("fnof") -> 16#00192; entity("fopf") -> 16#1D557; entity("forall") -> 16#02200; entity("fork") -> 16#022D4; entity("forkv") -> 16#02AD9; entity("fpartint") -> 16#02A0D; entity("frac12") -> 16#000BD; entity("frac13") -> 16#02153; entity("frac14") -> 16#000BC; entity("frac15") -> 16#02155; entity("frac16") -> 16#02159; entity("frac18") -> 16#0215B; entity("frac23") -> 16#02154; entity("frac25") -> 16#02156; entity("frac34") -> 16#000BE; entity("frac35") -> 16#02157; entity("frac38") -> 16#0215C; entity("frac45") -> 16#02158; entity("frac56") -> 16#0215A; entity("frac58") -> 16#0215D; entity("frac78") -> 16#0215E; entity("frasl") -> 16#02044; entity("frown") -> 16#02322; entity("fscr") -> 16#1D4BB; entity("gE") -> 16#02267; entity("gEl") -> 16#02A8C; entity("gacute") -> 16#001F5; entity("gamma") -> 16#003B3; entity("gammad") -> 16#003DD; entity("gap") -> 16#02A86; entity("gbreve") -> 16#0011F; entity("gcirc") -> 16#0011D; entity("gcy") -> 16#00433; entity("gdot") -> 16#00121; entity("ge") -> 16#02265; entity("gel") -> 16#022DB; entity("geq") -> 16#02265; entity("geqq") -> 16#02267; entity("geqslant") -> 16#02A7E; entity("ges") -> 16#02A7E; entity("gescc") -> 16#02AA9; entity("gesdot") -> 16#02A80; entity("gesdoto") -> 16#02A82; entity("gesdotol") -> 16#02A84; entity("gesl") -> [16#022DB, 16#0FE00]; entity("gesles") -> 16#02A94; entity("gfr") -> 16#1D524; entity("gg") -> 16#0226B; entity("ggg") -> 16#022D9; entity("gimel") -> 16#02137; entity("gjcy") -> 16#00453; entity("gl") -> 16#02277; entity("glE") -> 16#02A92; entity("gla") -> 16#02AA5; entity("glj") -> 16#02AA4; entity("gnE") -> 16#02269; entity("gnap") -> 16#02A8A; entity("gnapprox") -> 16#02A8A; entity("gne") -> 16#02A88; entity("gneq") -> 16#02A88; entity("gneqq") -> 16#02269; entity("gnsim") -> 16#022E7; entity("gopf") -> 16#1D558; entity("grave") -> 16#00060; entity("gscr") -> 16#0210A; entity("gsim") -> 16#02273; entity("gsime") -> 16#02A8E; entity("gsiml") -> 16#02A90; entity("gt") -> 16#0003E; entity("gtcc") -> 16#02AA7; entity("gtcir") -> 16#02A7A; entity("gtdot") -> 16#022D7; entity("gtlPar") -> 16#02995; entity("gtquest") -> 16#02A7C; entity("gtrapprox") -> 16#02A86; entity("gtrarr") -> 16#02978; entity("gtrdot") -> 16#022D7; entity("gtreqless") -> 16#022DB; entity("gtreqqless") -> 16#02A8C; entity("gtrless") -> 16#02277; entity("gtrsim") -> 16#02273; entity("gvertneqq") -> [16#02269, 16#0FE00]; entity("gvnE") -> [16#02269, 16#0FE00]; entity("hArr") -> 16#021D4; entity("hairsp") -> 16#0200A; entity("half") -> 16#000BD; entity("hamilt") -> 16#0210B; entity("hardcy") -> 16#0044A; entity("harr") -> 16#02194; entity("harrcir") -> 16#02948; entity("harrw") -> 16#021AD; entity("hbar") -> 16#0210F; entity("hcirc") -> 16#00125; entity("hearts") -> 16#02665; entity("heartsuit") -> 16#02665; entity("hellip") -> 16#02026; entity("hercon") -> 16#022B9; entity("hfr") -> 16#1D525; entity("hksearow") -> 16#02925; entity("hkswarow") -> 16#02926; entity("hoarr") -> 16#021FF; entity("homtht") -> 16#0223B; entity("hookleftarrow") -> 16#021A9; entity("hookrightarrow") -> 16#021AA; entity("hopf") -> 16#1D559; entity("horbar") -> 16#02015; entity("hscr") -> 16#1D4BD; entity("hslash") -> 16#0210F; entity("hstrok") -> 16#00127; entity("hybull") -> 16#02043; entity("hyphen") -> 16#02010; entity("iacute") -> 16#000ED; entity("ic") -> 16#02063; entity("icirc") -> 16#000EE; entity("icy") -> 16#00438; entity("iecy") -> 16#00435; entity("iexcl") -> 16#000A1; entity("iff") -> 16#021D4; entity("ifr") -> 16#1D526; entity("igrave") -> 16#000EC; entity("ii") -> 16#02148; entity("iiiint") -> 16#02A0C; entity("iiint") -> 16#0222D; entity("iinfin") -> 16#029DC; entity("iiota") -> 16#02129; entity("ijlig") -> 16#00133; entity("imacr") -> 16#0012B; entity("image") -> 16#02111; entity("imagline") -> 16#02110; entity("imagpart") -> 16#02111; entity("imath") -> 16#00131; entity("imof") -> 16#022B7; entity("imped") -> 16#001B5; entity("in") -> 16#02208; entity("incare") -> 16#02105; entity("infin") -> 16#0221E; entity("infintie") -> 16#029DD; entity("inodot") -> 16#00131; entity("int") -> 16#0222B; entity("intcal") -> 16#022BA; entity("integers") -> 16#02124; entity("intercal") -> 16#022BA; entity("intlarhk") -> 16#02A17; entity("intprod") -> 16#02A3C; entity("iocy") -> 16#00451; entity("iogon") -> 16#0012F; entity("iopf") -> 16#1D55A; entity("iota") -> 16#003B9; entity("iprod") -> 16#02A3C; entity("iquest") -> 16#000BF; entity("iscr") -> 16#1D4BE; entity("isin") -> 16#02208; entity("isinE") -> 16#022F9; entity("isindot") -> 16#022F5; entity("isins") -> 16#022F4; entity("isinsv") -> 16#022F3; entity("isinv") -> 16#02208; entity("it") -> 16#02062; entity("itilde") -> 16#00129; entity("iukcy") -> 16#00456; entity("iuml") -> 16#000EF; entity("jcirc") -> 16#00135; entity("jcy") -> 16#00439; entity("jfr") -> 16#1D527; entity("jmath") -> 16#00237; entity("jopf") -> 16#1D55B; entity("jscr") -> 16#1D4BF; entity("jsercy") -> 16#00458; entity("jukcy") -> 16#00454; entity("kappa") -> 16#003BA; entity("kappav") -> 16#003F0; entity("kcedil") -> 16#00137; entity("kcy") -> 16#0043A; entity("kfr") -> 16#1D528; entity("kgreen") -> 16#00138; entity("khcy") -> 16#00445; entity("kjcy") -> 16#0045C; entity("kopf") -> 16#1D55C; entity("kscr") -> 16#1D4C0; entity("lAarr") -> 16#021DA; entity("lArr") -> 16#021D0; entity("lAtail") -> 16#0291B; entity("lBarr") -> 16#0290E; entity("lE") -> 16#02266; entity("lEg") -> 16#02A8B; entity("lHar") -> 16#02962; entity("lacute") -> 16#0013A; entity("laemptyv") -> 16#029B4; entity("lagran") -> 16#02112; entity("lambda") -> 16#003BB; entity("lang") -> 16#027E8; entity("langd") -> 16#02991; entity("langle") -> 16#027E8; entity("lap") -> 16#02A85; entity("laquo") -> 16#000AB; entity("larr") -> 16#02190; entity("larrb") -> 16#021E4; entity("larrbfs") -> 16#0291F; entity("larrfs") -> 16#0291D; entity("larrhk") -> 16#021A9; entity("larrlp") -> 16#021AB; entity("larrpl") -> 16#02939; entity("larrsim") -> 16#02973; entity("larrtl") -> 16#021A2; entity("lat") -> 16#02AAB; entity("latail") -> 16#02919; entity("late") -> 16#02AAD; entity("lates") -> [16#02AAD, 16#0FE00]; entity("lbarr") -> 16#0290C; entity("lbbrk") -> 16#02772; entity("lbrace") -> 16#0007B; entity("lbrack") -> 16#0005B; entity("lbrke") -> 16#0298B; entity("lbrksld") -> 16#0298F; entity("lbrkslu") -> 16#0298D; entity("lcaron") -> 16#0013E; entity("lcedil") -> 16#0013C; entity("lceil") -> 16#02308; entity("lcub") -> 16#0007B; entity("lcy") -> 16#0043B; entity("ldca") -> 16#02936; entity("ldquo") -> 16#0201C; entity("ldquor") -> 16#0201E; entity("ldrdhar") -> 16#02967; entity("ldrushar") -> 16#0294B; entity("ldsh") -> 16#021B2; entity("le") -> 16#02264; entity("leftarrow") -> 16#02190; entity("leftarrowtail") -> 16#021A2; entity("leftharpoondown") -> 16#021BD; entity("leftharpoonup") -> 16#021BC; entity("leftleftarrows") -> 16#021C7; entity("leftrightarrow") -> 16#02194; entity("leftrightarrows") -> 16#021C6; entity("leftrightharpoons") -> 16#021CB; entity("leftrightsquigarrow") -> 16#021AD; entity("leftthreetimes") -> 16#022CB; entity("leg") -> 16#022DA; entity("leq") -> 16#02264; entity("leqq") -> 16#02266; entity("leqslant") -> 16#02A7D; entity("les") -> 16#02A7D; entity("lescc") -> 16#02AA8; entity("lesdot") -> 16#02A7F; entity("lesdoto") -> 16#02A81; entity("lesdotor") -> 16#02A83; entity("lesg") -> [16#022DA, 16#0FE00]; entity("lesges") -> 16#02A93; entity("lessapprox") -> 16#02A85; entity("lessdot") -> 16#022D6; entity("lesseqgtr") -> 16#022DA; entity("lesseqqgtr") -> 16#02A8B; entity("lessgtr") -> 16#02276; entity("lesssim") -> 16#02272; entity("lfisht") -> 16#0297C; entity("lfloor") -> 16#0230A; entity("lfr") -> 16#1D529; entity("lg") -> 16#02276; entity("lgE") -> 16#02A91; entity("lhard") -> 16#021BD; entity("lharu") -> 16#021BC; entity("lharul") -> 16#0296A; entity("lhblk") -> 16#02584; entity("ljcy") -> 16#00459; entity("ll") -> 16#0226A; entity("llarr") -> 16#021C7; entity("llcorner") -> 16#0231E; entity("llhard") -> 16#0296B; entity("lltri") -> 16#025FA; entity("lmidot") -> 16#00140; entity("lmoust") -> 16#023B0; entity("lmoustache") -> 16#023B0; entity("lnE") -> 16#02268; entity("lnap") -> 16#02A89; entity("lnapprox") -> 16#02A89; entity("lne") -> 16#02A87; entity("lneq") -> 16#02A87; entity("lneqq") -> 16#02268; entity("lnsim") -> 16#022E6; entity("loang") -> 16#027EC; entity("loarr") -> 16#021FD; entity("lobrk") -> 16#027E6; entity("longleftarrow") -> 16#027F5; entity("longleftrightarrow") -> 16#027F7; entity("longmapsto") -> 16#027FC; entity("longrightarrow") -> 16#027F6; entity("looparrowleft") -> 16#021AB; entity("looparrowright") -> 16#021AC; entity("lopar") -> 16#02985; entity("lopf") -> 16#1D55D; entity("loplus") -> 16#02A2D; entity("lotimes") -> 16#02A34; entity("lowast") -> 16#02217; entity("lowbar") -> 16#0005F; entity("loz") -> 16#025CA; entity("lozenge") -> 16#025CA; entity("lozf") -> 16#029EB; entity("lpar") -> 16#00028; entity("lparlt") -> 16#02993; entity("lrarr") -> 16#021C6; entity("lrcorner") -> 16#0231F; entity("lrhar") -> 16#021CB; entity("lrhard") -> 16#0296D; entity("lrm") -> 16#0200E; entity("lrtri") -> 16#022BF; entity("lsaquo") -> 16#02039; entity("lscr") -> 16#1D4C1; entity("lsh") -> 16#021B0; entity("lsim") -> 16#02272; entity("lsime") -> 16#02A8D; entity("lsimg") -> 16#02A8F; entity("lsqb") -> 16#0005B; entity("lsquo") -> 16#02018; entity("lsquor") -> 16#0201A; entity("lstrok") -> 16#00142; entity("lt") -> 16#0003C; entity("ltcc") -> 16#02AA6; entity("ltcir") -> 16#02A79; entity("ltdot") -> 16#022D6; entity("lthree") -> 16#022CB; entity("ltimes") -> 16#022C9; entity("ltlarr") -> 16#02976; entity("ltquest") -> 16#02A7B; entity("ltrPar") -> 16#02996; entity("ltri") -> 16#025C3; entity("ltrie") -> 16#022B4; entity("ltrif") -> 16#025C2; entity("lurdshar") -> 16#0294A; entity("luruhar") -> 16#02966; entity("lvertneqq") -> [16#02268, 16#0FE00]; entity("lvnE") -> [16#02268, 16#0FE00]; entity("mDDot") -> 16#0223A; entity("macr") -> 16#000AF; entity("male") -> 16#02642; entity("malt") -> 16#02720; entity("maltese") -> 16#02720; entity("map") -> 16#021A6; entity("mapsto") -> 16#021A6; entity("mapstodown") -> 16#021A7; entity("mapstoleft") -> 16#021A4; entity("mapstoup") -> 16#021A5; entity("marker") -> 16#025AE; entity("mcomma") -> 16#02A29; entity("mcy") -> 16#0043C; entity("mdash") -> 16#02014; entity("measuredangle") -> 16#02221; entity("mfr") -> 16#1D52A; entity("mho") -> 16#02127; entity("micro") -> 16#000B5; entity("mid") -> 16#02223; entity("midast") -> 16#0002A; entity("midcir") -> 16#02AF0; entity("middot") -> 16#000B7; entity("minus") -> 16#02212; entity("minusb") -> 16#0229F; entity("minusd") -> 16#02238; entity("minusdu") -> 16#02A2A; entity("mlcp") -> 16#02ADB; entity("mldr") -> 16#02026; entity("mnplus") -> 16#02213; entity("models") -> 16#022A7; entity("mopf") -> 16#1D55E; entity("mp") -> 16#02213; entity("mscr") -> 16#1D4C2; entity("mstpos") -> 16#0223E; entity("mu") -> 16#003BC; entity("multimap") -> 16#022B8; entity("mumap") -> 16#022B8; entity("nGg") -> [16#022D9, 16#00338]; entity("nGt") -> [16#0226B, 16#020D2]; entity("nGtv") -> [16#0226B, 16#00338]; entity("nLeftarrow") -> 16#021CD; entity("nLeftrightarrow") -> 16#021CE; entity("nLl") -> [16#022D8, 16#00338]; entity("nLt") -> [16#0226A, 16#020D2]; entity("nLtv") -> [16#0226A, 16#00338]; entity("nRightarrow") -> 16#021CF; entity("nVDash") -> 16#022AF; entity("nVdash") -> 16#022AE; entity("nabla") -> 16#02207; entity("nacute") -> 16#00144; entity("nang") -> [16#02220, 16#020D2]; entity("nap") -> 16#02249; entity("napE") -> [16#02A70, 16#00338]; entity("napid") -> [16#0224B, 16#00338]; entity("napos") -> 16#00149; entity("napprox") -> 16#02249; entity("natur") -> 16#0266E; entity("natural") -> 16#0266E; entity("naturals") -> 16#02115; entity("nbsp") -> 16#000A0; entity("nbump") -> [16#0224E, 16#00338]; entity("nbumpe") -> [16#0224F, 16#00338]; entity("ncap") -> 16#02A43; entity("ncaron") -> 16#00148; entity("ncedil") -> 16#00146; entity("ncong") -> 16#02247; entity("ncongdot") -> [16#02A6D, 16#00338]; entity("ncup") -> 16#02A42; entity("ncy") -> 16#0043D; entity("ndash") -> 16#02013; entity("ne") -> 16#02260; entity("neArr") -> 16#021D7; entity("nearhk") -> 16#02924; entity("nearr") -> 16#02197; entity("nearrow") -> 16#02197; entity("nedot") -> [16#02250, 16#00338]; entity("nequiv") -> 16#02262; entity("nesear") -> 16#02928; entity("nesim") -> [16#02242, 16#00338]; entity("nexist") -> 16#02204; entity("nexists") -> 16#02204; entity("nfr") -> 16#1D52B; entity("ngE") -> [16#02267, 16#00338]; entity("nge") -> 16#02271; entity("ngeq") -> 16#02271; entity("ngeqq") -> [16#02267, 16#00338]; entity("ngeqslant") -> [16#02A7E, 16#00338]; entity("nges") -> [16#02A7E, 16#00338]; entity("ngsim") -> 16#02275; entity("ngt") -> 16#0226F; entity("ngtr") -> 16#0226F; entity("nhArr") -> 16#021CE; entity("nharr") -> 16#021AE; entity("nhpar") -> 16#02AF2; entity("ni") -> 16#0220B; entity("nis") -> 16#022FC; entity("nisd") -> 16#022FA; entity("niv") -> 16#0220B; entity("njcy") -> 16#0045A; entity("nlArr") -> 16#021CD; entity("nlE") -> [16#02266, 16#00338]; entity("nlarr") -> 16#0219A; entity("nldr") -> 16#02025; entity("nle") -> 16#02270; entity("nleftarrow") -> 16#0219A; entity("nleftrightarrow") -> 16#021AE; entity("nleq") -> 16#02270; entity("nleqq") -> [16#02266, 16#00338]; entity("nleqslant") -> [16#02A7D, 16#00338]; entity("nles") -> [16#02A7D, 16#00338]; entity("nless") -> 16#0226E; entity("nlsim") -> 16#02274; entity("nlt") -> 16#0226E; entity("nltri") -> 16#022EA; entity("nltrie") -> 16#022EC; entity("nmid") -> 16#02224; entity("nopf") -> 16#1D55F; entity("not") -> 16#000AC; entity("notin") -> 16#02209; entity("notinE") -> [16#022F9, 16#00338]; entity("notindot") -> [16#022F5, 16#00338]; entity("notinva") -> 16#02209; entity("notinvb") -> 16#022F7; entity("notinvc") -> 16#022F6; entity("notni") -> 16#0220C; entity("notniva") -> 16#0220C; entity("notnivb") -> 16#022FE; entity("notnivc") -> 16#022FD; entity("npar") -> 16#02226; entity("nparallel") -> 16#02226; entity("nparsl") -> [16#02AFD, 16#020E5]; entity("npart") -> [16#02202, 16#00338]; entity("npolint") -> 16#02A14; entity("npr") -> 16#02280; entity("nprcue") -> 16#022E0; entity("npre") -> [16#02AAF, 16#00338]; entity("nprec") -> 16#02280; entity("npreceq") -> [16#02AAF, 16#00338]; entity("nrArr") -> 16#021CF; entity("nrarr") -> 16#0219B; entity("nrarrc") -> [16#02933, 16#00338]; entity("nrarrw") -> [16#0219D, 16#00338]; entity("nrightarrow") -> 16#0219B; entity("nrtri") -> 16#022EB; entity("nrtrie") -> 16#022ED; entity("nsc") -> 16#02281; entity("nsccue") -> 16#022E1; entity("nsce") -> [16#02AB0, 16#00338]; entity("nscr") -> 16#1D4C3; entity("nshortmid") -> 16#02224; entity("nshortparallel") -> 16#02226; entity("nsim") -> 16#02241; entity("nsime") -> 16#02244; entity("nsimeq") -> 16#02244; entity("nsmid") -> 16#02224; entity("nspar") -> 16#02226; entity("nsqsube") -> 16#022E2; entity("nsqsupe") -> 16#022E3; entity("nsub") -> 16#02284; entity("nsubE") -> [16#02AC5, 16#00338]; entity("nsube") -> 16#02288; entity("nsubset") -> [16#02282, 16#020D2]; entity("nsubseteq") -> 16#02288; entity("nsubseteqq") -> [16#02AC5, 16#00338]; entity("nsucc") -> 16#02281; entity("nsucceq") -> [16#02AB0, 16#00338]; entity("nsup") -> 16#02285; entity("nsupE") -> [16#02AC6, 16#00338]; entity("nsupe") -> 16#02289; entity("nsupset") -> [16#02283, 16#020D2]; entity("nsupseteq") -> 16#02289; entity("nsupseteqq") -> [16#02AC6, 16#00338]; entity("ntgl") -> 16#02279; entity("ntilde") -> 16#000F1; entity("ntlg") -> 16#02278; entity("ntriangleleft") -> 16#022EA; entity("ntrianglelefteq") -> 16#022EC; entity("ntriangleright") -> 16#022EB; entity("ntrianglerighteq") -> 16#022ED; entity("nu") -> 16#003BD; entity("num") -> 16#00023; entity("numero") -> 16#02116; entity("numsp") -> 16#02007; entity("nvDash") -> 16#022AD; entity("nvHarr") -> 16#02904; entity("nvap") -> [16#0224D, 16#020D2]; entity("nvdash") -> 16#022AC; entity("nvge") -> [16#02265, 16#020D2]; entity("nvgt") -> [16#0003E, 16#020D2]; entity("nvinfin") -> 16#029DE; entity("nvlArr") -> 16#02902; entity("nvle") -> [16#02264, 16#020D2]; entity("nvlt") -> [16#0003C, 16#020D2]; entity("nvltrie") -> [16#022B4, 16#020D2]; entity("nvrArr") -> 16#02903; entity("nvrtrie") -> [16#022B5, 16#020D2]; entity("nvsim") -> [16#0223C, 16#020D2]; entity("nwArr") -> 16#021D6; entity("nwarhk") -> 16#02923; entity("nwarr") -> 16#02196; entity("nwarrow") -> 16#02196; entity("nwnear") -> 16#02927; entity("oS") -> 16#024C8; entity("oacute") -> 16#000F3; entity("oast") -> 16#0229B; entity("ocir") -> 16#0229A; entity("ocirc") -> 16#000F4; entity("ocy") -> 16#0043E; entity("odash") -> 16#0229D; entity("odblac") -> 16#00151; entity("odiv") -> 16#02A38; entity("odot") -> 16#02299; entity("odsold") -> 16#029BC; entity("oelig") -> 16#00153; entity("ofcir") -> 16#029BF; entity("ofr") -> 16#1D52C; entity("ogon") -> 16#002DB; entity("ograve") -> 16#000F2; entity("ogt") -> 16#029C1; entity("ohbar") -> 16#029B5; entity("ohm") -> 16#003A9; entity("oint") -> 16#0222E; entity("olarr") -> 16#021BA; entity("olcir") -> 16#029BE; entity("olcross") -> 16#029BB; entity("oline") -> 16#0203E; entity("olt") -> 16#029C0; entity("omacr") -> 16#0014D; entity("omega") -> 16#003C9; entity("omicron") -> 16#003BF; entity("omid") -> 16#029B6; entity("ominus") -> 16#02296; entity("oopf") -> 16#1D560; entity("opar") -> 16#029B7; entity("operp") -> 16#029B9; entity("oplus") -> 16#02295; entity("or") -> 16#02228; entity("orarr") -> 16#021BB; entity("ord") -> 16#02A5D; entity("order") -> 16#02134; entity("orderof") -> 16#02134; entity("ordf") -> 16#000AA; entity("ordm") -> 16#000BA; entity("origof") -> 16#022B6; entity("oror") -> 16#02A56; entity("orslope") -> 16#02A57; entity("orv") -> 16#02A5B; entity("oscr") -> 16#02134; entity("oslash") -> 16#000F8; entity("osol") -> 16#02298; entity("otilde") -> 16#000F5; entity("otimes") -> 16#02297; entity("otimesas") -> 16#02A36; entity("ouml") -> 16#000F6; entity("ovbar") -> 16#0233D; entity("par") -> 16#02225; entity("para") -> 16#000B6; entity("parallel") -> 16#02225; entity("parsim") -> 16#02AF3; entity("parsl") -> 16#02AFD; entity("part") -> 16#02202; entity("pcy") -> 16#0043F; entity("percnt") -> 16#00025; entity("period") -> 16#0002E; entity("permil") -> 16#02030; entity("perp") -> 16#022A5; entity("pertenk") -> 16#02031; entity("pfr") -> 16#1D52D; entity("phi") -> 16#003C6; entity("phiv") -> 16#003D5; entity("phmmat") -> 16#02133; entity("phone") -> 16#0260E; entity("pi") -> 16#003C0; entity("pitchfork") -> 16#022D4; entity("piv") -> 16#003D6; entity("planck") -> 16#0210F; entity("planckh") -> 16#0210E; entity("plankv") -> 16#0210F; entity("plus") -> 16#0002B; entity("plusacir") -> 16#02A23; entity("plusb") -> 16#0229E; entity("pluscir") -> 16#02A22; entity("plusdo") -> 16#02214; entity("plusdu") -> 16#02A25; entity("pluse") -> 16#02A72; entity("plusmn") -> 16#000B1; entity("plussim") -> 16#02A26; entity("plustwo") -> 16#02A27; entity("pm") -> 16#000B1; entity("pointint") -> 16#02A15; entity("popf") -> 16#1D561; entity("pound") -> 16#000A3; entity("pr") -> 16#0227A; entity("prE") -> 16#02AB3; entity("prap") -> 16#02AB7; entity("prcue") -> 16#0227C; entity("pre") -> 16#02AAF; entity("prec") -> 16#0227A; entity("precapprox") -> 16#02AB7; entity("preccurlyeq") -> 16#0227C; entity("preceq") -> 16#02AAF; entity("precnapprox") -> 16#02AB9; entity("precneqq") -> 16#02AB5; entity("precnsim") -> 16#022E8; entity("precsim") -> 16#0227E; entity("prime") -> 16#02032; entity("primes") -> 16#02119; entity("prnE") -> 16#02AB5; entity("prnap") -> 16#02AB9; entity("prnsim") -> 16#022E8; entity("prod") -> 16#0220F; entity("profalar") -> 16#0232E; entity("profline") -> 16#02312; entity("profsurf") -> 16#02313; entity("prop") -> 16#0221D; entity("propto") -> 16#0221D; entity("prsim") -> 16#0227E; entity("prurel") -> 16#022B0; entity("pscr") -> 16#1D4C5; entity("psi") -> 16#003C8; entity("puncsp") -> 16#02008; entity("qfr") -> 16#1D52E; entity("qint") -> 16#02A0C; entity("qopf") -> 16#1D562; entity("qprime") -> 16#02057; entity("qscr") -> 16#1D4C6; entity("quaternions") -> 16#0210D; entity("quatint") -> 16#02A16; entity("quest") -> 16#0003F; entity("questeq") -> 16#0225F; entity("quot") -> 16#00022; entity("rAarr") -> 16#021DB; entity("rArr") -> 16#021D2; entity("rAtail") -> 16#0291C; entity("rBarr") -> 16#0290F; entity("rHar") -> 16#02964; entity("race") -> [16#0223D, 16#00331]; entity("racute") -> 16#00155; entity("radic") -> 16#0221A; entity("raemptyv") -> 16#029B3; entity("rang") -> 16#027E9; entity("rangd") -> 16#02992; entity("range") -> 16#029A5; entity("rangle") -> 16#027E9; entity("raquo") -> 16#000BB; entity("rarr") -> 16#02192; entity("rarrap") -> 16#02975; entity("rarrb") -> 16#021E5; entity("rarrbfs") -> 16#02920; entity("rarrc") -> 16#02933; entity("rarrfs") -> 16#0291E; entity("rarrhk") -> 16#021AA; entity("rarrlp") -> 16#021AC; entity("rarrpl") -> 16#02945; entity("rarrsim") -> 16#02974; entity("rarrtl") -> 16#021A3; entity("rarrw") -> 16#0219D; entity("ratail") -> 16#0291A; entity("ratio") -> 16#02236; entity("rationals") -> 16#0211A; entity("rbarr") -> 16#0290D; entity("rbbrk") -> 16#02773; entity("rbrace") -> 16#0007D; entity("rbrack") -> 16#0005D; entity("rbrke") -> 16#0298C; entity("rbrksld") -> 16#0298E; entity("rbrkslu") -> 16#02990; entity("rcaron") -> 16#00159; entity("rcedil") -> 16#00157; entity("rceil") -> 16#02309; entity("rcub") -> 16#0007D; entity("rcy") -> 16#00440; entity("rdca") -> 16#02937; entity("rdldhar") -> 16#02969; entity("rdquo") -> 16#0201D; entity("rdquor") -> 16#0201D; entity("rdsh") -> 16#021B3; entity("real") -> 16#0211C; entity("realine") -> 16#0211B; entity("realpart") -> 16#0211C; entity("reals") -> 16#0211D; entity("rect") -> 16#025AD; entity("reg") -> 16#000AE; entity("rfisht") -> 16#0297D; entity("rfloor") -> 16#0230B; entity("rfr") -> 16#1D52F; entity("rhard") -> 16#021C1; entity("rharu") -> 16#021C0; entity("rharul") -> 16#0296C; entity("rho") -> 16#003C1; entity("rhov") -> 16#003F1; entity("rightarrow") -> 16#02192; entity("rightarrowtail") -> 16#021A3; entity("rightharpoondown") -> 16#021C1; entity("rightharpoonup") -> 16#021C0; entity("rightleftarrows") -> 16#021C4; entity("rightleftharpoons") -> 16#021CC; entity("rightrightarrows") -> 16#021C9; entity("rightsquigarrow") -> 16#0219D; entity("rightthreetimes") -> 16#022CC; entity("ring") -> 16#002DA; entity("risingdotseq") -> 16#02253; entity("rlarr") -> 16#021C4; entity("rlhar") -> 16#021CC; entity("rlm") -> 16#0200F; entity("rmoust") -> 16#023B1; entity("rmoustache") -> 16#023B1; entity("rnmid") -> 16#02AEE; entity("roang") -> 16#027ED; entity("roarr") -> 16#021FE; entity("robrk") -> 16#027E7; entity("ropar") -> 16#02986; entity("ropf") -> 16#1D563; entity("roplus") -> 16#02A2E; entity("rotimes") -> 16#02A35; entity("rpar") -> 16#00029; entity("rpargt") -> 16#02994; entity("rppolint") -> 16#02A12; entity("rrarr") -> 16#021C9; entity("rsaquo") -> 16#0203A; entity("rscr") -> 16#1D4C7; entity("rsh") -> 16#021B1; entity("rsqb") -> 16#0005D; entity("rsquo") -> 16#02019; entity("rsquor") -> 16#02019; entity("rthree") -> 16#022CC; entity("rtimes") -> 16#022CA; entity("rtri") -> 16#025B9; entity("rtrie") -> 16#022B5; entity("rtrif") -> 16#025B8; entity("rtriltri") -> 16#029CE; entity("ruluhar") -> 16#02968; entity("rx") -> 16#0211E; entity("sacute") -> 16#0015B; entity("sbquo") -> 16#0201A; entity("sc") -> 16#0227B; entity("scE") -> 16#02AB4; entity("scap") -> 16#02AB8; entity("scaron") -> 16#00161; entity("sccue") -> 16#0227D; entity("sce") -> 16#02AB0; entity("scedil") -> 16#0015F; entity("scirc") -> 16#0015D; entity("scnE") -> 16#02AB6; entity("scnap") -> 16#02ABA; entity("scnsim") -> 16#022E9; entity("scpolint") -> 16#02A13; entity("scsim") -> 16#0227F; entity("scy") -> 16#00441; entity("sdot") -> 16#022C5; entity("sdotb") -> 16#022A1; entity("sdote") -> 16#02A66; entity("seArr") -> 16#021D8; entity("searhk") -> 16#02925; entity("searr") -> 16#02198; entity("searrow") -> 16#02198; entity("sect") -> 16#000A7; entity("semi") -> 16#0003B; entity("seswar") -> 16#02929; entity("setminus") -> 16#02216; entity("setmn") -> 16#02216; entity("sext") -> 16#02736; entity("sfr") -> 16#1D530; entity("sfrown") -> 16#02322; entity("sharp") -> 16#0266F; entity("shchcy") -> 16#00449; entity("shcy") -> 16#00448; entity("shortmid") -> 16#02223; entity("shortparallel") -> 16#02225; entity("shy") -> 16#000AD; entity("sigma") -> 16#003C3; entity("sigmaf") -> 16#003C2; entity("sigmav") -> 16#003C2; entity("sim") -> 16#0223C; entity("simdot") -> 16#02A6A; entity("sime") -> 16#02243; entity("simeq") -> 16#02243; entity("simg") -> 16#02A9E; entity("simgE") -> 16#02AA0; entity("siml") -> 16#02A9D; entity("simlE") -> 16#02A9F; entity("simne") -> 16#02246; entity("simplus") -> 16#02A24; entity("simrarr") -> 16#02972; entity("slarr") -> 16#02190; entity("smallsetminus") -> 16#02216; entity("smashp") -> 16#02A33; entity("smeparsl") -> 16#029E4; entity("smid") -> 16#02223; entity("smile") -> 16#02323; entity("smt") -> 16#02AAA; entity("smte") -> 16#02AAC; entity("smtes") -> [16#02AAC, 16#0FE00]; entity("softcy") -> 16#0044C; entity("sol") -> 16#0002F; entity("solb") -> 16#029C4; entity("solbar") -> 16#0233F; entity("sopf") -> 16#1D564; entity("spades") -> 16#02660; entity("spadesuit") -> 16#02660; entity("spar") -> 16#02225; entity("sqcap") -> 16#02293; entity("sqcaps") -> [16#02293, 16#0FE00]; entity("sqcup") -> 16#02294; entity("sqcups") -> [16#02294, 16#0FE00]; entity("sqsub") -> 16#0228F; entity("sqsube") -> 16#02291; entity("sqsubset") -> 16#0228F; entity("sqsubseteq") -> 16#02291; entity("sqsup") -> 16#02290; entity("sqsupe") -> 16#02292; entity("sqsupset") -> 16#02290; entity("sqsupseteq") -> 16#02292; entity("squ") -> 16#025A1; entity("square") -> 16#025A1; entity("squarf") -> 16#025AA; entity("squf") -> 16#025AA; entity("srarr") -> 16#02192; entity("sscr") -> 16#1D4C8; entity("ssetmn") -> 16#02216; entity("ssmile") -> 16#02323; entity("sstarf") -> 16#022C6; entity("star") -> 16#02606; entity("starf") -> 16#02605; entity("straightepsilon") -> 16#003F5; entity("straightphi") -> 16#003D5; entity("strns") -> 16#000AF; entity("sub") -> 16#02282; entity("subE") -> 16#02AC5; entity("subdot") -> 16#02ABD; entity("sube") -> 16#02286; entity("subedot") -> 16#02AC3; entity("submult") -> 16#02AC1; entity("subnE") -> 16#02ACB; entity("subne") -> 16#0228A; entity("subplus") -> 16#02ABF; entity("subrarr") -> 16#02979; entity("subset") -> 16#02282; entity("subseteq") -> 16#02286; entity("subseteqq") -> 16#02AC5; entity("subsetneq") -> 16#0228A; entity("subsetneqq") -> 16#02ACB; entity("subsim") -> 16#02AC7; entity("subsub") -> 16#02AD5; entity("subsup") -> 16#02AD3; entity("succ") -> 16#0227B; entity("succapprox") -> 16#02AB8; entity("succcurlyeq") -> 16#0227D; entity("succeq") -> 16#02AB0; entity("succnapprox") -> 16#02ABA; entity("succneqq") -> 16#02AB6; entity("succnsim") -> 16#022E9; entity("succsim") -> 16#0227F; entity("sum") -> 16#02211; entity("sung") -> 16#0266A; entity("sup") -> 16#02283; entity("sup1") -> 16#000B9; entity("sup2") -> 16#000B2; entity("sup3") -> 16#000B3; entity("supE") -> 16#02AC6; entity("supdot") -> 16#02ABE; entity("supdsub") -> 16#02AD8; entity("supe") -> 16#02287; entity("supedot") -> 16#02AC4; entity("suphsol") -> 16#027C9; entity("suphsub") -> 16#02AD7; entity("suplarr") -> 16#0297B; entity("supmult") -> 16#02AC2; entity("supnE") -> 16#02ACC; entity("supne") -> 16#0228B; entity("supplus") -> 16#02AC0; entity("supset") -> 16#02283; entity("supseteq") -> 16#02287; entity("supseteqq") -> 16#02AC6; entity("supsetneq") -> 16#0228B; entity("supsetneqq") -> 16#02ACC; entity("supsim") -> 16#02AC8; entity("supsub") -> 16#02AD4; entity("supsup") -> 16#02AD6; entity("swArr") -> 16#021D9; entity("swarhk") -> 16#02926; entity("swarr") -> 16#02199; entity("swarrow") -> 16#02199; entity("swnwar") -> 16#0292A; entity("szlig") -> 16#000DF; entity("target") -> 16#02316; entity("tau") -> 16#003C4; entity("tbrk") -> 16#023B4; entity("tcaron") -> 16#00165; entity("tcedil") -> 16#00163; entity("tcy") -> 16#00442; entity("tdot") -> 16#020DB; entity("telrec") -> 16#02315; entity("tfr") -> 16#1D531; entity("there4") -> 16#02234; entity("therefore") -> 16#02234; entity("theta") -> 16#003B8; entity("thetasym") -> 16#003D1; entity("thetav") -> 16#003D1; entity("thickapprox") -> 16#02248; entity("thicksim") -> 16#0223C; entity("thinsp") -> 16#02009; entity("thkap") -> 16#02248; entity("thksim") -> 16#0223C; entity("thorn") -> 16#000FE; entity("tilde") -> 16#002DC; entity("times") -> 16#000D7; entity("timesb") -> 16#022A0; entity("timesbar") -> 16#02A31; entity("timesd") -> 16#02A30; entity("tint") -> 16#0222D; entity("toea") -> 16#02928; entity("top") -> 16#022A4; entity("topbot") -> 16#02336; entity("topcir") -> 16#02AF1; entity("topf") -> 16#1D565; entity("topfork") -> 16#02ADA; entity("tosa") -> 16#02929; entity("tprime") -> 16#02034; entity("trade") -> 16#02122; entity("triangle") -> 16#025B5; entity("triangledown") -> 16#025BF; entity("triangleleft") -> 16#025C3; entity("trianglelefteq") -> 16#022B4; entity("triangleq") -> 16#0225C; entity("triangleright") -> 16#025B9; entity("trianglerighteq") -> 16#022B5; entity("tridot") -> 16#025EC; entity("trie") -> 16#0225C; entity("triminus") -> 16#02A3A; entity("triplus") -> 16#02A39; entity("trisb") -> 16#029CD; entity("tritime") -> 16#02A3B; entity("trpezium") -> 16#023E2; entity("tscr") -> 16#1D4C9; entity("tscy") -> 16#00446; entity("tshcy") -> 16#0045B; entity("tstrok") -> 16#00167; entity("twixt") -> 16#0226C; entity("twoheadleftarrow") -> 16#0219E; entity("twoheadrightarrow") -> 16#021A0; entity("uArr") -> 16#021D1; entity("uHar") -> 16#02963; entity("uacute") -> 16#000FA; entity("uarr") -> 16#02191; entity("ubrcy") -> 16#0045E; entity("ubreve") -> 16#0016D; entity("ucirc") -> 16#000FB; entity("ucy") -> 16#00443; entity("udarr") -> 16#021C5; entity("udblac") -> 16#00171; entity("udhar") -> 16#0296E; entity("ufisht") -> 16#0297E; entity("ufr") -> 16#1D532; entity("ugrave") -> 16#000F9; entity("uharl") -> 16#021BF; entity("uharr") -> 16#021BE; entity("uhblk") -> 16#02580; entity("ulcorn") -> 16#0231C; entity("ulcorner") -> 16#0231C; entity("ulcrop") -> 16#0230F; entity("ultri") -> 16#025F8; entity("umacr") -> 16#0016B; entity("uml") -> 16#000A8; entity("uogon") -> 16#00173; entity("uopf") -> 16#1D566; entity("uparrow") -> 16#02191; entity("updownarrow") -> 16#02195; entity("upharpoonleft") -> 16#021BF; entity("upharpoonright") -> 16#021BE; entity("uplus") -> 16#0228E; entity("upsi") -> 16#003C5; entity("upsih") -> 16#003D2; entity("upsilon") -> 16#003C5; entity("upuparrows") -> 16#021C8; entity("urcorn") -> 16#0231D; entity("urcorner") -> 16#0231D; entity("urcrop") -> 16#0230E; entity("uring") -> 16#0016F; entity("urtri") -> 16#025F9; entity("uscr") -> 16#1D4CA; entity("utdot") -> 16#022F0; entity("utilde") -> 16#00169; entity("utri") -> 16#025B5; entity("utrif") -> 16#025B4; entity("uuarr") -> 16#021C8; entity("uuml") -> 16#000FC; entity("uwangle") -> 16#029A7; entity("vArr") -> 16#021D5; entity("vBar") -> 16#02AE8; entity("vBarv") -> 16#02AE9; entity("vDash") -> 16#022A8; entity("vangrt") -> 16#0299C; entity("varepsilon") -> 16#003F5; entity("varkappa") -> 16#003F0; entity("varnothing") -> 16#02205; entity("varphi") -> 16#003D5; entity("varpi") -> 16#003D6; entity("varpropto") -> 16#0221D; entity("varr") -> 16#02195; entity("varrho") -> 16#003F1; entity("varsigma") -> 16#003C2; entity("varsubsetneq") -> [16#0228A, 16#0FE00]; entity("varsubsetneqq") -> [16#02ACB, 16#0FE00]; entity("varsupsetneq") -> [16#0228B, 16#0FE00]; entity("varsupsetneqq") -> [16#02ACC, 16#0FE00]; entity("vartheta") -> 16#003D1; entity("vartriangleleft") -> 16#022B2; entity("vartriangleright") -> 16#022B3; entity("vcy") -> 16#00432; entity("vdash") -> 16#022A2; entity("vee") -> 16#02228; entity("veebar") -> 16#022BB; entity("veeeq") -> 16#0225A; entity("vellip") -> 16#022EE; entity("verbar") -> 16#0007C; entity("vert") -> 16#0007C; entity("vfr") -> 16#1D533; entity("vltri") -> 16#022B2; entity("vnsub") -> [16#02282, 16#020D2]; entity("vnsup") -> [16#02283, 16#020D2]; entity("vopf") -> 16#1D567; entity("vprop") -> 16#0221D; entity("vrtri") -> 16#022B3; entity("vscr") -> 16#1D4CB; entity("vsubnE") -> [16#02ACB, 16#0FE00]; entity("vsubne") -> [16#0228A, 16#0FE00]; entity("vsupnE") -> [16#02ACC, 16#0FE00]; entity("vsupne") -> [16#0228B, 16#0FE00]; entity("vzigzag") -> 16#0299A; entity("wcirc") -> 16#00175; entity("wedbar") -> 16#02A5F; entity("wedge") -> 16#02227; entity("wedgeq") -> 16#02259; entity("weierp") -> 16#02118; entity("wfr") -> 16#1D534; entity("wopf") -> 16#1D568; entity("wp") -> 16#02118; entity("wr") -> 16#02240; entity("wreath") -> 16#02240; entity("wscr") -> 16#1D4CC; entity("xcap") -> 16#022C2; entity("xcirc") -> 16#025EF; entity("xcup") -> 16#022C3; entity("xdtri") -> 16#025BD; entity("xfr") -> 16#1D535; entity("xhArr") -> 16#027FA; entity("xharr") -> 16#027F7; entity("xi") -> 16#003BE; entity("xlArr") -> 16#027F8; entity("xlarr") -> 16#027F5; entity("xmap") -> 16#027FC; entity("xnis") -> 16#022FB; entity("xodot") -> 16#02A00; entity("xopf") -> 16#1D569; entity("xoplus") -> 16#02A01; entity("xotime") -> 16#02A02; entity("xrArr") -> 16#027F9; entity("xrarr") -> 16#027F6; entity("xscr") -> 16#1D4CD; entity("xsqcup") -> 16#02A06; entity("xuplus") -> 16#02A04; entity("xutri") -> 16#025B3; entity("xvee") -> 16#022C1; entity("xwedge") -> 16#022C0; entity("yacute") -> 16#000FD; entity("yacy") -> 16#0044F; entity("ycirc") -> 16#00177; entity("ycy") -> 16#0044B; entity("yen") -> 16#000A5; entity("yfr") -> 16#1D536; entity("yicy") -> 16#00457; entity("yopf") -> 16#1D56A; entity("yscr") -> 16#1D4CE; entity("yucy") -> 16#0044E; entity("yuml") -> 16#000FF; entity("zacute") -> 16#0017A; entity("zcaron") -> 16#0017E; entity("zcy") -> 16#00437; entity("zdot") -> 16#0017C; entity("zeetrf") -> 16#02128; entity("zeta") -> 16#003B6; entity("zfr") -> 16#1D537; entity("zhcy") -> 16#00436; entity("zigrarr") -> 16#021DD; entity("zopf") -> 16#1D56B; entity("zscr") -> 16#1D4CF; entity("zwj") -> 16#0200D; entity("zwnj") -> 16#0200C; entity(_) -> undefined. %% %% Tests %% -ifdef(TEST). -include_lib("eunit/include/eunit.hrl"). exhaustive_entity_test() -> T = mochiweb_cover:clause_lookup_table(?MODULE, entity), [?assertEqual(V, entity(K)) || {K, V} <- T]. charref_test() -> 1234 = charref("#1234"), 255 = charref("#xfF"), 255 = charref(<<"#XFf">>), 38 = charref("amp"), 38 = charref(<<"amp">>), undefined = charref("not_an_entity"), undefined = charref("#not_an_entity"), undefined = charref("#xnot_an_entity"), ok. -endif. rabbitmq-server-3.2.4/plugins-src/mochiweb-wrapper/mochiweb-git/src/mochijson.erl0000644000000000000000000004524012305126066026714 0ustar rootroot%% @author Bob Ippolito %% @copyright 2006 Mochi Media, Inc. %% @doc Yet another JSON (RFC 4627) library for Erlang. -module(mochijson). -author('bob@mochimedia.com'). -export([encoder/1, encode/1]). -export([decoder/1, decode/1]). -export([binary_encoder/1, binary_encode/1]). -export([binary_decoder/1, binary_decode/1]). % This is a macro to placate syntax highlighters.. -define(Q, $\"). -define(ADV_COL(S, N), S#decoder{column=N+S#decoder.column}). -define(INC_COL(S), S#decoder{column=1+S#decoder.column}). -define(INC_LINE(S), S#decoder{column=1, line=1+S#decoder.line}). %% @type json_string() = atom | string() | binary() %% @type json_number() = integer() | float() %% @type json_array() = {array, [json_term()]} %% @type json_object() = {struct, [{json_string(), json_term()}]} %% @type json_term() = json_string() | json_number() | json_array() | %% json_object() %% @type encoding() = utf8 | unicode %% @type encoder_option() = {input_encoding, encoding()} | %% {handler, function()} %% @type decoder_option() = {input_encoding, encoding()} | %% {object_hook, function()} %% @type bjson_string() = binary() %% @type bjson_number() = integer() | float() %% @type bjson_array() = [bjson_term()] %% @type bjson_object() = {struct, [{bjson_string(), bjson_term()}]} %% @type bjson_term() = bjson_string() | bjson_number() | bjson_array() | %% bjson_object() %% @type binary_encoder_option() = {handler, function()} %% @type binary_decoder_option() = {object_hook, function()} -record(encoder, {input_encoding=unicode, handler=null}). -record(decoder, {input_encoding=utf8, object_hook=null, line=1, column=1, state=null}). %% @spec encoder([encoder_option()]) -> function() %% @doc Create an encoder/1 with the given options. encoder(Options) -> State = parse_encoder_options(Options, #encoder{}), fun (O) -> json_encode(O, State) end. %% @spec encode(json_term()) -> iolist() %% @doc Encode the given as JSON to an iolist. encode(Any) -> json_encode(Any, #encoder{}). %% @spec decoder([decoder_option()]) -> function() %% @doc Create a decoder/1 with the given options. decoder(Options) -> State = parse_decoder_options(Options, #decoder{}), fun (O) -> json_decode(O, State) end. %% @spec decode(iolist()) -> json_term() %% @doc Decode the given iolist to Erlang terms. decode(S) -> json_decode(S, #decoder{}). %% @spec binary_decoder([binary_decoder_option()]) -> function() %% @doc Create a binary_decoder/1 with the given options. binary_decoder(Options) -> mochijson2:decoder(Options). %% @spec binary_encoder([binary_encoder_option()]) -> function() %% @doc Create a binary_encoder/1 with the given options. binary_encoder(Options) -> mochijson2:encoder(Options). %% @spec binary_encode(bjson_term()) -> iolist() %% @doc Encode the given as JSON to an iolist, using lists for arrays and %% binaries for strings. binary_encode(Any) -> mochijson2:encode(Any). %% @spec binary_decode(iolist()) -> bjson_term() %% @doc Decode the given iolist to Erlang terms, using lists for arrays and %% binaries for strings. binary_decode(S) -> mochijson2:decode(S). %% Internal API parse_encoder_options([], State) -> State; parse_encoder_options([{input_encoding, Encoding} | Rest], State) -> parse_encoder_options(Rest, State#encoder{input_encoding=Encoding}); parse_encoder_options([{handler, Handler} | Rest], State) -> parse_encoder_options(Rest, State#encoder{handler=Handler}). parse_decoder_options([], State) -> State; parse_decoder_options([{input_encoding, Encoding} | Rest], State) -> parse_decoder_options(Rest, State#decoder{input_encoding=Encoding}); parse_decoder_options([{object_hook, Hook} | Rest], State) -> parse_decoder_options(Rest, State#decoder{object_hook=Hook}). json_encode(true, _State) -> "true"; json_encode(false, _State) -> "false"; json_encode(null, _State) -> "null"; json_encode(I, _State) when is_integer(I) -> integer_to_list(I); json_encode(F, _State) when is_float(F) -> mochinum:digits(F); json_encode(L, State) when is_list(L); is_binary(L); is_atom(L) -> json_encode_string(L, State); json_encode({array, Props}, State) when is_list(Props) -> json_encode_array(Props, State); json_encode({struct, Props}, State) when is_list(Props) -> json_encode_proplist(Props, State); json_encode(Bad, #encoder{handler=null}) -> exit({json_encode, {bad_term, Bad}}); json_encode(Bad, State=#encoder{handler=Handler}) -> json_encode(Handler(Bad), State). json_encode_array([], _State) -> "[]"; json_encode_array(L, State) -> F = fun (O, Acc) -> [$,, json_encode(O, State) | Acc] end, [$, | Acc1] = lists:foldl(F, "[", L), lists:reverse([$\] | Acc1]). json_encode_proplist([], _State) -> "{}"; json_encode_proplist(Props, State) -> F = fun ({K, V}, Acc) -> KS = case K of K when is_atom(K) -> json_encode_string_utf8(atom_to_list(K)); K when is_integer(K) -> json_encode_string(integer_to_list(K), State); K when is_list(K); is_binary(K) -> json_encode_string(K, State) end, VS = json_encode(V, State), [$,, VS, $:, KS | Acc] end, [$, | Acc1] = lists:foldl(F, "{", Props), lists:reverse([$\} | Acc1]). json_encode_string(A, _State) when is_atom(A) -> json_encode_string_unicode(xmerl_ucs:from_utf8(atom_to_list(A))); json_encode_string(B, _State) when is_binary(B) -> json_encode_string_unicode(xmerl_ucs:from_utf8(B)); json_encode_string(S, #encoder{input_encoding=utf8}) -> json_encode_string_utf8(S); json_encode_string(S, #encoder{input_encoding=unicode}) -> json_encode_string_unicode(S). json_encode_string_utf8(S) -> [?Q | json_encode_string_utf8_1(S)]. json_encode_string_utf8_1([C | Cs]) when C >= 0, C =< 16#7f -> NewC = case C of $\\ -> "\\\\"; ?Q -> "\\\""; _ when C >= $\s, C < 16#7f -> C; $\t -> "\\t"; $\n -> "\\n"; $\r -> "\\r"; $\f -> "\\f"; $\b -> "\\b"; _ when C >= 0, C =< 16#7f -> unihex(C); _ -> exit({json_encode, {bad_char, C}}) end, [NewC | json_encode_string_utf8_1(Cs)]; json_encode_string_utf8_1(All=[C | _]) when C >= 16#80, C =< 16#10FFFF -> [?Q | Rest] = json_encode_string_unicode(xmerl_ucs:from_utf8(All)), Rest; json_encode_string_utf8_1([]) -> "\"". json_encode_string_unicode(S) -> [?Q | json_encode_string_unicode_1(S)]. json_encode_string_unicode_1([C | Cs]) -> NewC = case C of $\\ -> "\\\\"; ?Q -> "\\\""; _ when C >= $\s, C < 16#7f -> C; $\t -> "\\t"; $\n -> "\\n"; $\r -> "\\r"; $\f -> "\\f"; $\b -> "\\b"; _ when C >= 0, C =< 16#10FFFF -> unihex(C); _ -> exit({json_encode, {bad_char, C}}) end, [NewC | json_encode_string_unicode_1(Cs)]; json_encode_string_unicode_1([]) -> "\"". dehex(C) when C >= $0, C =< $9 -> C - $0; dehex(C) when C >= $a, C =< $f -> C - $a + 10; dehex(C) when C >= $A, C =< $F -> C - $A + 10. hexdigit(C) when C >= 0, C =< 9 -> C + $0; hexdigit(C) when C =< 15 -> C + $a - 10. unihex(C) when C < 16#10000 -> <> = <>, Digits = [hexdigit(D) || D <- [D3, D2, D1, D0]], [$\\, $u | Digits]; unihex(C) when C =< 16#10FFFF -> N = C - 16#10000, S1 = 16#d800 bor ((N bsr 10) band 16#3ff), S2 = 16#dc00 bor (N band 16#3ff), [unihex(S1), unihex(S2)]. json_decode(B, S) when is_binary(B) -> json_decode(binary_to_list(B), S); json_decode(L, S) -> {Res, L1, S1} = decode1(L, S), {eof, [], _} = tokenize(L1, S1#decoder{state=trim}), Res. decode1(L, S=#decoder{state=null}) -> case tokenize(L, S#decoder{state=any}) of {{const, C}, L1, S1} -> {C, L1, S1}; {start_array, L1, S1} -> decode_array(L1, S1#decoder{state=any}, []); {start_object, L1, S1} -> decode_object(L1, S1#decoder{state=key}, []) end. make_object(V, #decoder{object_hook=null}) -> V; make_object(V, #decoder{object_hook=Hook}) -> Hook(V). decode_object(L, S=#decoder{state=key}, Acc) -> case tokenize(L, S) of {end_object, Rest, S1} -> V = make_object({struct, lists:reverse(Acc)}, S1), {V, Rest, S1#decoder{state=null}}; {{const, K}, Rest, S1} when is_list(K) -> {colon, L2, S2} = tokenize(Rest, S1), {V, L3, S3} = decode1(L2, S2#decoder{state=null}), decode_object(L3, S3#decoder{state=comma}, [{K, V} | Acc]) end; decode_object(L, S=#decoder{state=comma}, Acc) -> case tokenize(L, S) of {end_object, Rest, S1} -> V = make_object({struct, lists:reverse(Acc)}, S1), {V, Rest, S1#decoder{state=null}}; {comma, Rest, S1} -> decode_object(Rest, S1#decoder{state=key}, Acc) end. decode_array(L, S=#decoder{state=any}, Acc) -> case tokenize(L, S) of {end_array, Rest, S1} -> {{array, lists:reverse(Acc)}, Rest, S1#decoder{state=null}}; {start_array, Rest, S1} -> {Array, Rest1, S2} = decode_array(Rest, S1#decoder{state=any}, []), decode_array(Rest1, S2#decoder{state=comma}, [Array | Acc]); {start_object, Rest, S1} -> {Array, Rest1, S2} = decode_object(Rest, S1#decoder{state=key}, []), decode_array(Rest1, S2#decoder{state=comma}, [Array | Acc]); {{const, Const}, Rest, S1} -> decode_array(Rest, S1#decoder{state=comma}, [Const | Acc]) end; decode_array(L, S=#decoder{state=comma}, Acc) -> case tokenize(L, S) of {end_array, Rest, S1} -> {{array, lists:reverse(Acc)}, Rest, S1#decoder{state=null}}; {comma, Rest, S1} -> decode_array(Rest, S1#decoder{state=any}, Acc) end. tokenize_string(IoList=[C | _], S=#decoder{input_encoding=utf8}, Acc) when is_list(C); is_binary(C); C >= 16#7f -> List = xmerl_ucs:from_utf8(iolist_to_binary(IoList)), tokenize_string(List, S#decoder{input_encoding=unicode}, Acc); tokenize_string("\"" ++ Rest, S, Acc) -> {lists:reverse(Acc), Rest, ?INC_COL(S)}; tokenize_string("\\\"" ++ Rest, S, Acc) -> tokenize_string(Rest, ?ADV_COL(S, 2), [$\" | Acc]); tokenize_string("\\\\" ++ Rest, S, Acc) -> tokenize_string(Rest, ?ADV_COL(S, 2), [$\\ | Acc]); tokenize_string("\\/" ++ Rest, S, Acc) -> tokenize_string(Rest, ?ADV_COL(S, 2), [$/ | Acc]); tokenize_string("\\b" ++ Rest, S, Acc) -> tokenize_string(Rest, ?ADV_COL(S, 2), [$\b | Acc]); tokenize_string("\\f" ++ Rest, S, Acc) -> tokenize_string(Rest, ?ADV_COL(S, 2), [$\f | Acc]); tokenize_string("\\n" ++ Rest, S, Acc) -> tokenize_string(Rest, ?ADV_COL(S, 2), [$\n | Acc]); tokenize_string("\\r" ++ Rest, S, Acc) -> tokenize_string(Rest, ?ADV_COL(S, 2), [$\r | Acc]); tokenize_string("\\t" ++ Rest, S, Acc) -> tokenize_string(Rest, ?ADV_COL(S, 2), [$\t | Acc]); tokenize_string([$\\, $u, C3, C2, C1, C0 | Rest], S, Acc) -> % coalesce UTF-16 surrogate pair? C = dehex(C0) bor (dehex(C1) bsl 4) bor (dehex(C2) bsl 8) bor (dehex(C3) bsl 12), tokenize_string(Rest, ?ADV_COL(S, 6), [C | Acc]); tokenize_string([C | Rest], S, Acc) when C >= $\s; C < 16#10FFFF -> tokenize_string(Rest, ?ADV_COL(S, 1), [C | Acc]). tokenize_number(IoList=[C | _], Mode, S=#decoder{input_encoding=utf8}, Acc) when is_list(C); is_binary(C); C >= 16#7f -> List = xmerl_ucs:from_utf8(iolist_to_binary(IoList)), tokenize_number(List, Mode, S#decoder{input_encoding=unicode}, Acc); tokenize_number([$- | Rest], sign, S, []) -> tokenize_number(Rest, int, ?INC_COL(S), [$-]); tokenize_number(Rest, sign, S, []) -> tokenize_number(Rest, int, S, []); tokenize_number([$0 | Rest], int, S, Acc) -> tokenize_number(Rest, frac, ?INC_COL(S), [$0 | Acc]); tokenize_number([C | Rest], int, S, Acc) when C >= $1, C =< $9 -> tokenize_number(Rest, int1, ?INC_COL(S), [C | Acc]); tokenize_number([C | Rest], int1, S, Acc) when C >= $0, C =< $9 -> tokenize_number(Rest, int1, ?INC_COL(S), [C | Acc]); tokenize_number(Rest, int1, S, Acc) -> tokenize_number(Rest, frac, S, Acc); tokenize_number([$., C | Rest], frac, S, Acc) when C >= $0, C =< $9 -> tokenize_number(Rest, frac1, ?ADV_COL(S, 2), [C, $. | Acc]); tokenize_number([E | Rest], frac, S, Acc) when E == $e; E == $E -> tokenize_number(Rest, esign, ?INC_COL(S), [$e, $0, $. | Acc]); tokenize_number(Rest, frac, S, Acc) -> {{int, lists:reverse(Acc)}, Rest, S}; tokenize_number([C | Rest], frac1, S, Acc) when C >= $0, C =< $9 -> tokenize_number(Rest, frac1, ?INC_COL(S), [C | Acc]); tokenize_number([E | Rest], frac1, S, Acc) when E == $e; E == $E -> tokenize_number(Rest, esign, ?INC_COL(S), [$e | Acc]); tokenize_number(Rest, frac1, S, Acc) -> {{float, lists:reverse(Acc)}, Rest, S}; tokenize_number([C | Rest], esign, S, Acc) when C == $-; C == $+ -> tokenize_number(Rest, eint, ?INC_COL(S), [C | Acc]); tokenize_number(Rest, esign, S, Acc) -> tokenize_number(Rest, eint, S, Acc); tokenize_number([C | Rest], eint, S, Acc) when C >= $0, C =< $9 -> tokenize_number(Rest, eint1, ?INC_COL(S), [C | Acc]); tokenize_number([C | Rest], eint1, S, Acc) when C >= $0, C =< $9 -> tokenize_number(Rest, eint1, ?INC_COL(S), [C | Acc]); tokenize_number(Rest, eint1, S, Acc) -> {{float, lists:reverse(Acc)}, Rest, S}. tokenize([], S=#decoder{state=trim}) -> {eof, [], S}; tokenize([L | Rest], S) when is_list(L) -> tokenize(L ++ Rest, S); tokenize([B | Rest], S) when is_binary(B) -> tokenize(xmerl_ucs:from_utf8(B) ++ Rest, S); tokenize("\r\n" ++ Rest, S) -> tokenize(Rest, ?INC_LINE(S)); tokenize("\n" ++ Rest, S) -> tokenize(Rest, ?INC_LINE(S)); tokenize([C | Rest], S) when C == $\s; C == $\t -> tokenize(Rest, ?INC_COL(S)); tokenize("{" ++ Rest, S) -> {start_object, Rest, ?INC_COL(S)}; tokenize("}" ++ Rest, S) -> {end_object, Rest, ?INC_COL(S)}; tokenize("[" ++ Rest, S) -> {start_array, Rest, ?INC_COL(S)}; tokenize("]" ++ Rest, S) -> {end_array, Rest, ?INC_COL(S)}; tokenize("," ++ Rest, S) -> {comma, Rest, ?INC_COL(S)}; tokenize(":" ++ Rest, S) -> {colon, Rest, ?INC_COL(S)}; tokenize("null" ++ Rest, S) -> {{const, null}, Rest, ?ADV_COL(S, 4)}; tokenize("true" ++ Rest, S) -> {{const, true}, Rest, ?ADV_COL(S, 4)}; tokenize("false" ++ Rest, S) -> {{const, false}, Rest, ?ADV_COL(S, 5)}; tokenize("\"" ++ Rest, S) -> {String, Rest1, S1} = tokenize_string(Rest, ?INC_COL(S), []), {{const, String}, Rest1, S1}; tokenize(L=[C | _], S) when C >= $0, C =< $9; C == $- -> case tokenize_number(L, sign, S, []) of {{int, Int}, Rest, S1} -> {{const, list_to_integer(Int)}, Rest, S1}; {{float, Float}, Rest, S1} -> {{const, list_to_float(Float)}, Rest, S1} end. %% %% Tests %% -ifdef(TEST). -include_lib("eunit/include/eunit.hrl"). %% testing constructs borrowed from the Yaws JSON implementation. %% Create an object from a list of Key/Value pairs. obj_new() -> {struct, []}. is_obj({struct, Props}) -> F = fun ({K, _}) when is_list(K) -> true; (_) -> false end, lists:all(F, Props). obj_from_list(Props) -> Obj = {struct, Props}, case is_obj(Obj) of true -> Obj; false -> exit(json_bad_object) end. %% Test for equivalence of Erlang terms. %% Due to arbitrary order of construction, equivalent objects might %% compare unequal as erlang terms, so we need to carefully recurse %% through aggregates (tuples and objects). equiv({struct, Props1}, {struct, Props2}) -> equiv_object(Props1, Props2); equiv({array, L1}, {array, L2}) -> equiv_list(L1, L2); equiv(N1, N2) when is_number(N1), is_number(N2) -> N1 == N2; equiv(S1, S2) when is_list(S1), is_list(S2) -> S1 == S2; equiv(true, true) -> true; equiv(false, false) -> true; equiv(null, null) -> true. %% Object representation and traversal order is unknown. %% Use the sledgehammer and sort property lists. equiv_object(Props1, Props2) -> L1 = lists:keysort(1, Props1), L2 = lists:keysort(1, Props2), Pairs = lists:zip(L1, L2), true = lists:all(fun({{K1, V1}, {K2, V2}}) -> equiv(K1, K2) and equiv(V1, V2) end, Pairs). %% Recursively compare tuple elements for equivalence. equiv_list([], []) -> true; equiv_list([V1 | L1], [V2 | L2]) -> equiv(V1, V2) andalso equiv_list(L1, L2). e2j_vec_test() -> test_one(e2j_test_vec(utf8), 1). issue33_test() -> %% http://code.google.com/p/mochiweb/issues/detail?id=33 Js = {struct, [{"key", [194, 163]}]}, Encoder = encoder([{input_encoding, utf8}]), "{\"key\":\"\\u00a3\"}" = lists:flatten(Encoder(Js)). test_one([], _N) -> %% io:format("~p tests passed~n", [N-1]), ok; test_one([{E, J} | Rest], N) -> %% io:format("[~p] ~p ~p~n", [N, E, J]), true = equiv(E, decode(J)), true = equiv(E, decode(encode(E))), test_one(Rest, 1+N). e2j_test_vec(utf8) -> [ {1, "1"}, {3.1416, "3.14160"}, % text representation may truncate, trail zeroes {-1, "-1"}, {-3.1416, "-3.14160"}, {12.0e10, "1.20000e+11"}, {1.234E+10, "1.23400e+10"}, {-1.234E-10, "-1.23400e-10"}, {10.0, "1.0e+01"}, {123.456, "1.23456E+2"}, {10.0, "1e1"}, {"foo", "\"foo\""}, {"foo" ++ [5] ++ "bar", "\"foo\\u0005bar\""}, {"", "\"\""}, {"\"", "\"\\\"\""}, {"\n\n\n", "\"\\n\\n\\n\""}, {"\\", "\"\\\\\""}, {"\" \b\f\r\n\t\"", "\"\\\" \\b\\f\\r\\n\\t\\\"\""}, {obj_new(), "{}"}, {obj_from_list([{"foo", "bar"}]), "{\"foo\":\"bar\"}"}, {obj_from_list([{"foo", "bar"}, {"baz", 123}]), "{\"foo\":\"bar\",\"baz\":123}"}, {{array, []}, "[]"}, {{array, [{array, []}]}, "[[]]"}, {{array, [1, "foo"]}, "[1,\"foo\"]"}, % json array in a json object {obj_from_list([{"foo", {array, [123]}}]), "{\"foo\":[123]}"}, % json object in a json object {obj_from_list([{"foo", obj_from_list([{"bar", true}])}]), "{\"foo\":{\"bar\":true}}"}, % fold evaluation order {obj_from_list([{"foo", {array, []}}, {"bar", obj_from_list([{"baz", true}])}, {"alice", "bob"}]), "{\"foo\":[],\"bar\":{\"baz\":true},\"alice\":\"bob\"}"}, % json object in a json array {{array, [-123, "foo", obj_from_list([{"bar", {array, []}}]), null]}, "[-123,\"foo\",{\"bar\":[]},null]"} ]. -endif. rabbitmq-server-3.2.4/plugins-src/mochiweb-wrapper/mochiweb-git/src/mochiweb_headers.erl0000644000000000000000000003516512305126066030220 0ustar rootroot%% @author Bob Ippolito %% @copyright 2007 Mochi Media, Inc. %% @doc Case preserving (but case insensitive) HTTP Header dictionary. -module(mochiweb_headers). -author('bob@mochimedia.com'). -export([empty/0, from_list/1, insert/3, enter/3, get_value/2, lookup/2]). -export([delete_any/2, get_primary_value/2, get_combined_value/2]). -export([default/3, enter_from_list/2, default_from_list/2]). -export([to_list/1, make/1]). -export([from_binary/1]). %% @type headers(). %% @type key() = atom() | binary() | string(). %% @type value() = atom() | binary() | string() | integer(). %% @spec empty() -> headers() %% @doc Create an empty headers structure. empty() -> gb_trees:empty(). %% @spec make(headers() | [{key(), value()}]) -> headers() %% @doc Construct a headers() from the given list. make(L) when is_list(L) -> from_list(L); %% assume a non-list is already mochiweb_headers. make(T) -> T. %% @spec from_binary(iolist()) -> headers() %% @doc Transforms a raw HTTP header into a mochiweb headers structure. %% %% The given raw HTTP header can be one of the following: %% %% 1) A string or a binary representing a full HTTP header ending with %% double CRLF. %% Examples: %% ``` %% "Content-Length: 47\r\nContent-Type: text/plain\r\n\r\n" %% <<"Content-Length: 47\r\nContent-Type: text/plain\r\n\r\n">>''' %% %% 2) A list of binaries or strings where each element represents a raw %% HTTP header line ending with a single CRLF. %% Examples: %% ``` %% [<<"Content-Length: 47\r\n">>, <<"Content-Type: text/plain\r\n">>] %% ["Content-Length: 47\r\n", "Content-Type: text/plain\r\n"] %% ["Content-Length: 47\r\n", <<"Content-Type: text/plain\r\n">>]''' %% from_binary(RawHttpHeader) when is_binary(RawHttpHeader) -> from_binary(RawHttpHeader, []); from_binary(RawHttpHeaderList) -> from_binary(list_to_binary([RawHttpHeaderList, "\r\n"])). from_binary(RawHttpHeader, Acc) -> case erlang:decode_packet(httph, RawHttpHeader, []) of {ok, {http_header, _, H, _, V}, Rest} -> from_binary(Rest, [{H, V} | Acc]); _ -> make(Acc) end. %% @spec from_list([{key(), value()}]) -> headers() %% @doc Construct a headers() from the given list. from_list(List) -> lists:foldl(fun ({K, V}, T) -> insert(K, V, T) end, empty(), List). %% @spec enter_from_list([{key(), value()}], headers()) -> headers() %% @doc Insert pairs into the headers, replace any values for existing keys. enter_from_list(List, T) -> lists:foldl(fun ({K, V}, T1) -> enter(K, V, T1) end, T, List). %% @spec default_from_list([{key(), value()}], headers()) -> headers() %% @doc Insert pairs into the headers for keys that do not already exist. default_from_list(List, T) -> lists:foldl(fun ({K, V}, T1) -> default(K, V, T1) end, T, List). %% @spec to_list(headers()) -> [{key(), string()}] %% @doc Return the contents of the headers. The keys will be the exact key %% that was first inserted (e.g. may be an atom or binary, case is %% preserved). to_list(T) -> F = fun ({K, {array, L}}, Acc) -> L1 = lists:reverse(L), lists:foldl(fun (V, Acc1) -> [{K, V} | Acc1] end, Acc, L1); (Pair, Acc) -> [Pair | Acc] end, lists:reverse(lists:foldl(F, [], gb_trees:values(T))). %% @spec get_value(key(), headers()) -> string() | undefined %% @doc Return the value of the given header using a case insensitive search. %% undefined will be returned for keys that are not present. get_value(K, T) -> case lookup(K, T) of {value, {_, V}} -> expand(V); none -> undefined end. %% @spec get_primary_value(key(), headers()) -> string() | undefined %% @doc Return the value of the given header up to the first semicolon using %% a case insensitive search. undefined will be returned for keys %% that are not present. get_primary_value(K, T) -> case get_value(K, T) of undefined -> undefined; V -> lists:takewhile(fun (C) -> C =/= $; end, V) end. %% @spec get_combined_value(key(), headers()) -> string() | undefined %% @doc Return the value from the given header using a case insensitive search. %% If the value of the header is a comma-separated list where holds values %% are all identical, the identical value will be returned. %% undefined will be returned for keys that are not present or the %% values in the list are not the same. %% %% NOTE: The process isn't designed for a general purpose. If you need %% to access all values in the combined header, please refer to %% '''tokenize_header_value/1'''. %% %% Section 4.2 of the RFC 2616 (HTTP 1.1) describes multiple message-header %% fields with the same field-name may be present in a message if and only %% if the entire field-value for that header field is defined as a %% comma-separated list [i.e., #(values)]. get_combined_value(K, T) -> case get_value(K, T) of undefined -> undefined; V -> case sets:to_list(sets:from_list(tokenize_header_value(V))) of [Val] -> Val; _ -> undefined end end. %% @spec lookup(key(), headers()) -> {value, {key(), string()}} | none %% @doc Return the case preserved key and value for the given header using %% a case insensitive search. none will be returned for keys that are %% not present. lookup(K, T) -> case gb_trees:lookup(normalize(K), T) of {value, {K0, V}} -> {value, {K0, expand(V)}}; none -> none end. %% @spec default(key(), value(), headers()) -> headers() %% @doc Insert the pair into the headers if it does not already exist. default(K, V, T) -> K1 = normalize(K), V1 = any_to_list(V), try gb_trees:insert(K1, {K, V1}, T) catch error:{key_exists, _} -> T end. %% @spec enter(key(), value(), headers()) -> headers() %% @doc Insert the pair into the headers, replacing any pre-existing key. enter(K, V, T) -> K1 = normalize(K), V1 = any_to_list(V), gb_trees:enter(K1, {K, V1}, T). %% @spec insert(key(), value(), headers()) -> headers() %% @doc Insert the pair into the headers, merging with any pre-existing key. %% A merge is done with Value = V0 ++ ", " ++ V1. insert(K, V, T) -> K1 = normalize(K), V1 = any_to_list(V), try gb_trees:insert(K1, {K, V1}, T) catch error:{key_exists, _} -> {K0, V0} = gb_trees:get(K1, T), V2 = merge(K1, V1, V0), gb_trees:update(K1, {K0, V2}, T) end. %% @spec delete_any(key(), headers()) -> headers() %% @doc Delete the header corresponding to key if it is present. delete_any(K, T) -> K1 = normalize(K), gb_trees:delete_any(K1, T). %% Internal API tokenize_header_value(undefined) -> undefined; tokenize_header_value(V) -> reversed_tokens(trim_and_reverse(V, false), [], []). trim_and_reverse([S | Rest], Reversed) when S=:=$ ; S=:=$\n; S=:=$\t -> trim_and_reverse(Rest, Reversed); trim_and_reverse(V, false) -> trim_and_reverse(lists:reverse(V), true); trim_and_reverse(V, true) -> V. reversed_tokens([], [], Acc) -> Acc; reversed_tokens([], Token, Acc) -> [Token | Acc]; reversed_tokens("\"" ++ Rest, [], Acc) -> case extract_quoted_string(Rest, []) of {String, NewRest} -> reversed_tokens(NewRest, [], [String | Acc]); undefined -> undefined end; reversed_tokens("\"" ++ _Rest, _Token, _Acc) -> undefined; reversed_tokens([C | Rest], [], Acc) when C=:=$ ;C=:=$\n;C=:=$\t;C=:=$, -> reversed_tokens(Rest, [], Acc); reversed_tokens([C | Rest], Token, Acc) when C=:=$ ;C=:=$\n;C=:=$\t;C=:=$, -> reversed_tokens(Rest, [], [Token | Acc]); reversed_tokens([C | Rest], Token, Acc) -> reversed_tokens(Rest, [C | Token], Acc); reversed_tokens(_, _, _) -> undefeined. extract_quoted_string([], _Acc) -> undefined; extract_quoted_string("\"\\" ++ Rest, Acc) -> extract_quoted_string(Rest, "\"" ++ Acc); extract_quoted_string("\"" ++ Rest, Acc) -> {Acc, Rest}; extract_quoted_string([C | Rest], Acc) -> extract_quoted_string(Rest, [C | Acc]). expand({array, L}) -> mochiweb_util:join(lists:reverse(L), ", "); expand(V) -> V. merge("set-cookie", V1, {array, L}) -> {array, [V1 | L]}; merge("set-cookie", V1, V0) -> {array, [V1, V0]}; merge(_, V1, V0) -> V0 ++ ", " ++ V1. normalize(K) when is_list(K) -> string:to_lower(K); normalize(K) when is_atom(K) -> normalize(atom_to_list(K)); normalize(K) when is_binary(K) -> normalize(binary_to_list(K)). any_to_list(V) when is_list(V) -> V; any_to_list(V) when is_atom(V) -> atom_to_list(V); any_to_list(V) when is_binary(V) -> binary_to_list(V); any_to_list(V) when is_integer(V) -> integer_to_list(V). %% %% Tests. %% -ifdef(TEST). -include_lib("eunit/include/eunit.hrl"). make_test() -> Identity = make([{hdr, foo}]), ?assertEqual( Identity, make(Identity)). enter_from_list_test() -> H = make([{hdr, foo}]), ?assertEqual( [{baz, "wibble"}, {hdr, "foo"}], to_list(enter_from_list([{baz, wibble}], H))), ?assertEqual( [{hdr, "bar"}], to_list(enter_from_list([{hdr, bar}], H))), ok. default_from_list_test() -> H = make([{hdr, foo}]), ?assertEqual( [{baz, "wibble"}, {hdr, "foo"}], to_list(default_from_list([{baz, wibble}], H))), ?assertEqual( [{hdr, "foo"}], to_list(default_from_list([{hdr, bar}], H))), ok. get_primary_value_test() -> H = make([{hdr, foo}, {baz, <<"wibble;taco">>}]), ?assertEqual( "foo", get_primary_value(hdr, H)), ?assertEqual( undefined, get_primary_value(bar, H)), ?assertEqual( "wibble", get_primary_value(<<"baz">>, H)), ok. get_combined_value_test() -> H = make([{hdr, foo}, {baz, <<"wibble,taco">>}, {content_length, "123, 123"}, {test, " 123, 123, 123 , 123,123 "}, {test2, "456, 123, 123 , 123"}, {test3, "123"}, {test4, " 123, "}]), ?assertEqual( "foo", get_combined_value(hdr, H)), ?assertEqual( undefined, get_combined_value(bar, H)), ?assertEqual( undefined, get_combined_value(<<"baz">>, H)), ?assertEqual( "123", get_combined_value(<<"content_length">>, H)), ?assertEqual( "123", get_combined_value(<<"test">>, H)), ?assertEqual( undefined, get_combined_value(<<"test2">>, H)), ?assertEqual( "123", get_combined_value(<<"test3">>, H)), ?assertEqual( "123", get_combined_value(<<"test4">>, H)), ok. set_cookie_test() -> H = make([{"set-cookie", foo}, {"set-cookie", bar}, {"set-cookie", baz}]), ?assertEqual( [{"set-cookie", "foo"}, {"set-cookie", "bar"}, {"set-cookie", "baz"}], to_list(H)), ok. headers_test() -> H = ?MODULE:make([{hdr, foo}, {"Hdr", "bar"}, {'Hdr', 2}]), [{hdr, "foo, bar, 2"}] = ?MODULE:to_list(H), H1 = ?MODULE:insert(taco, grande, H), [{hdr, "foo, bar, 2"}, {taco, "grande"}] = ?MODULE:to_list(H1), H2 = ?MODULE:make([{"Set-Cookie", "foo"}]), [{"Set-Cookie", "foo"}] = ?MODULE:to_list(H2), H3 = ?MODULE:insert("Set-Cookie", "bar", H2), [{"Set-Cookie", "foo"}, {"Set-Cookie", "bar"}] = ?MODULE:to_list(H3), "foo, bar" = ?MODULE:get_value("set-cookie", H3), {value, {"Set-Cookie", "foo, bar"}} = ?MODULE:lookup("set-cookie", H3), undefined = ?MODULE:get_value("shibby", H3), none = ?MODULE:lookup("shibby", H3), H4 = ?MODULE:insert("content-type", "application/x-www-form-urlencoded; charset=utf8", H3), "application/x-www-form-urlencoded" = ?MODULE:get_primary_value( "content-type", H4), H4 = ?MODULE:delete_any("nonexistent-header", H4), H3 = ?MODULE:delete_any("content-type", H4), HB = <<"Content-Length: 47\r\nContent-Type: text/plain\r\n\r\n">>, H_HB = ?MODULE:from_binary(HB), H_HB = ?MODULE:from_binary(binary_to_list(HB)), "47" = ?MODULE:get_value("Content-Length", H_HB), "text/plain" = ?MODULE:get_value("Content-Type", H_HB), L_H_HB = ?MODULE:to_list(H_HB), 2 = length(L_H_HB), true = lists:member({'Content-Length', "47"}, L_H_HB), true = lists:member({'Content-Type', "text/plain"}, L_H_HB), HL = [ <<"Content-Length: 47\r\n">>, <<"Content-Type: text/plain\r\n">> ], HL2 = [ "Content-Length: 47\r\n", <<"Content-Type: text/plain\r\n">> ], HL3 = [ <<"Content-Length: 47\r\n">>, "Content-Type: text/plain\r\n" ], H_HL = ?MODULE:from_binary(HL), H_HL = ?MODULE:from_binary(HL2), H_HL = ?MODULE:from_binary(HL3), "47" = ?MODULE:get_value("Content-Length", H_HL), "text/plain" = ?MODULE:get_value("Content-Type", H_HL), L_H_HL = ?MODULE:to_list(H_HL), 2 = length(L_H_HL), true = lists:member({'Content-Length', "47"}, L_H_HL), true = lists:member({'Content-Type', "text/plain"}, L_H_HL), [] = ?MODULE:to_list(?MODULE:from_binary(<<>>)), [] = ?MODULE:to_list(?MODULE:from_binary(<<"">>)), [] = ?MODULE:to_list(?MODULE:from_binary(<<"\r\n">>)), [] = ?MODULE:to_list(?MODULE:from_binary(<<"\r\n\r\n">>)), [] = ?MODULE:to_list(?MODULE:from_binary("")), [] = ?MODULE:to_list(?MODULE:from_binary([<<>>])), [] = ?MODULE:to_list(?MODULE:from_binary([<<"">>])), [] = ?MODULE:to_list(?MODULE:from_binary([<<"\r\n">>])), [] = ?MODULE:to_list(?MODULE:from_binary([<<"\r\n\r\n">>])), ok. tokenize_header_value_test() -> ?assertEqual(["a quote in a \"quote\"."], tokenize_header_value("\"a quote in a \\\"quote\\\".\"")), ?assertEqual(["abc"], tokenize_header_value("abc")), ?assertEqual(["abc", "def"], tokenize_header_value("abc def")), ?assertEqual(["abc", "def"], tokenize_header_value("abc , def")), ?assertEqual(["abc", "def"], tokenize_header_value(",abc ,, def,,")), ?assertEqual(["abc def"], tokenize_header_value("\"abc def\" ")), ?assertEqual(["abc, def"], tokenize_header_value("\"abc, def\"")), ?assertEqual(["\\a\\$"], tokenize_header_value("\"\\a\\$\"")), ?assertEqual(["abc def", "foo, bar", "12345", ""], tokenize_header_value("\"abc def\" \"foo, bar\" , 12345, \"\"")), ?assertEqual(undefined, tokenize_header_value(undefined)), ?assertEqual(undefined, tokenize_header_value("umatched quote\"")), ?assertEqual(undefined, tokenize_header_value("\"unmatched quote")). -endif. rabbitmq-server-3.2.4/plugins-src/mochiweb-wrapper/mochiweb-git/src/mochiweb_socket_server.erl0000644000000000000000000003141512305126066031455 0ustar rootroot%% @author Bob Ippolito %% @copyright 2007 Mochi Media, Inc. %% @doc MochiWeb socket server. -module(mochiweb_socket_server). -author('bob@mochimedia.com'). -behaviour(gen_server). -include("internal.hrl"). -export([start/1, start_link/1, stop/1]). -export([init/1, handle_call/3, handle_cast/2, terminate/2, code_change/3, handle_info/2]). -export([get/2, set/3]). -record(mochiweb_socket_server, {port, loop, name=undefined, %% NOTE: This is currently ignored. max=2048, ip=any, listen=null, nodelay=false, backlog=128, active_sockets=0, acceptor_pool_size=16, ssl=false, ssl_opts=[{ssl_imp, new}], acceptor_pool=sets:new(), profile_fun=undefined}). -define(is_old_state(State), not is_record(State, mochiweb_socket_server)). start_link(Options) -> start_server(start_link, parse_options(Options)). start(Options) -> case lists:keytake(link, 1, Options) of {value, {_Key, false}, Options1} -> start_server(start, parse_options(Options1)); _ -> %% TODO: https://github.com/mochi/mochiweb/issues/58 %% [X] Phase 1: Add new APIs (Sep 2011) %% [_] Phase 2: Add deprecation warning %% [_] Phase 3: Change default to {link, false} and ignore link %% [_] Phase 4: Add deprecation warning for {link, _} option %% [_] Phase 5: Remove support for {link, _} option start_link(Options) end. get(Name, Property) -> gen_server:call(Name, {get, Property}). set(Name, profile_fun, Fun) -> gen_server:cast(Name, {set, profile_fun, Fun}); set(Name, Property, _Value) -> error_logger:info_msg("?MODULE:set for ~p with ~p not implemented~n", [Name, Property]). stop(Name) when is_atom(Name) orelse is_pid(Name) -> gen_server:call(Name, stop); stop({Scope, Name}) when Scope =:= local orelse Scope =:= global -> stop(Name); stop(Options) -> State = parse_options(Options), stop(State#mochiweb_socket_server.name). %% Internal API parse_options(State=#mochiweb_socket_server{}) -> State; parse_options(Options) -> parse_options(Options, #mochiweb_socket_server{}). parse_options([], State) -> State; parse_options([{name, L} | Rest], State) when is_list(L) -> Name = {local, list_to_atom(L)}, parse_options(Rest, State#mochiweb_socket_server{name=Name}); parse_options([{name, A} | Rest], State) when A =:= undefined -> parse_options(Rest, State#mochiweb_socket_server{name=A}); parse_options([{name, A} | Rest], State) when is_atom(A) -> Name = {local, A}, parse_options(Rest, State#mochiweb_socket_server{name=Name}); parse_options([{name, Name} | Rest], State) -> parse_options(Rest, State#mochiweb_socket_server{name=Name}); parse_options([{port, L} | Rest], State) when is_list(L) -> Port = list_to_integer(L), parse_options(Rest, State#mochiweb_socket_server{port=Port}); parse_options([{port, Port} | Rest], State) -> parse_options(Rest, State#mochiweb_socket_server{port=Port}); parse_options([{ip, Ip} | Rest], State) -> ParsedIp = case Ip of any -> any; Ip when is_tuple(Ip) -> Ip; Ip when is_list(Ip) -> {ok, IpTuple} = inet_parse:address(Ip), IpTuple end, parse_options(Rest, State#mochiweb_socket_server{ip=ParsedIp}); parse_options([{loop, Loop} | Rest], State) -> parse_options(Rest, State#mochiweb_socket_server{loop=Loop}); parse_options([{backlog, Backlog} | Rest], State) -> parse_options(Rest, State#mochiweb_socket_server{backlog=Backlog}); parse_options([{nodelay, NoDelay} | Rest], State) -> parse_options(Rest, State#mochiweb_socket_server{nodelay=NoDelay}); parse_options([{acceptor_pool_size, Max} | Rest], State) -> MaxInt = ensure_int(Max), parse_options(Rest, State#mochiweb_socket_server{acceptor_pool_size=MaxInt}); parse_options([{max, Max} | Rest], State) -> error_logger:info_report([{warning, "TODO: max is currently unsupported"}, {max, Max}]), MaxInt = ensure_int(Max), parse_options(Rest, State#mochiweb_socket_server{max=MaxInt}); parse_options([{ssl, Ssl} | Rest], State) when is_boolean(Ssl) -> parse_options(Rest, State#mochiweb_socket_server{ssl=Ssl}); parse_options([{ssl_opts, SslOpts} | Rest], State) when is_list(SslOpts) -> SslOpts1 = [{ssl_imp, new} | proplists:delete(ssl_imp, SslOpts)], parse_options(Rest, State#mochiweb_socket_server{ssl_opts=SslOpts1}); parse_options([{profile_fun, ProfileFun} | Rest], State) when is_function(ProfileFun) -> parse_options(Rest, State#mochiweb_socket_server{profile_fun=ProfileFun}). start_server(F, State=#mochiweb_socket_server{ssl=Ssl, name=Name}) -> ok = prep_ssl(Ssl), case Name of undefined -> gen_server:F(?MODULE, State, []); _ -> gen_server:F(Name, ?MODULE, State, []) end. prep_ssl(true) -> ok = mochiweb:ensure_started(crypto), ok = mochiweb:ensure_started(asn1), ok = mochiweb:ensure_started(public_key), ok = mochiweb:ensure_started(ssl); prep_ssl(false) -> ok. ensure_int(N) when is_integer(N) -> N; ensure_int(S) when is_list(S) -> list_to_integer(S). ipv6_supported() -> case (catch inet:getaddr("localhost", inet6)) of {ok, _Addr} -> true; {error, _} -> false end. init(State=#mochiweb_socket_server{ip=Ip, port=Port, backlog=Backlog, nodelay=NoDelay}) -> process_flag(trap_exit, true), BaseOpts = [binary, {reuseaddr, true}, {packet, 0}, {backlog, Backlog}, {recbuf, ?RECBUF_SIZE}, {exit_on_close, false}, {active, false}, {nodelay, NoDelay}], Opts = case Ip of any -> case ipv6_supported() of % IPv4, and IPv6 if supported true -> [inet, inet6 | BaseOpts]; _ -> BaseOpts end; {_, _, _, _} -> % IPv4 [inet, {ip, Ip} | BaseOpts]; {_, _, _, _, _, _, _, _} -> % IPv6 [inet6, {ip, Ip} | BaseOpts] end, listen(Port, Opts, State). new_acceptor_pool(Listen, State=#mochiweb_socket_server{acceptor_pool=Pool, acceptor_pool_size=Size, loop=Loop}) -> F = fun (_, S) -> Pid = mochiweb_acceptor:start_link(self(), Listen, Loop), sets:add_element(Pid, S) end, Pool1 = lists:foldl(F, Pool, lists:seq(1, Size)), State#mochiweb_socket_server{acceptor_pool=Pool1}. listen(Port, Opts, State=#mochiweb_socket_server{ssl=Ssl, ssl_opts=SslOpts}) -> case mochiweb_socket:listen(Ssl, Port, Opts, SslOpts) of {ok, Listen} -> {ok, ListenPort} = mochiweb_socket:port(Listen), {ok, new_acceptor_pool( Listen, State#mochiweb_socket_server{listen=Listen, port=ListenPort})}; {error, Reason} -> {stop, Reason} end. do_get(port, #mochiweb_socket_server{port=Port}) -> Port; do_get(active_sockets, #mochiweb_socket_server{active_sockets=ActiveSockets}) -> ActiveSockets. state_to_proplist(#mochiweb_socket_server{name=Name, port=Port, active_sockets=ActiveSockets}) -> [{name, Name}, {port, Port}, {active_sockets, ActiveSockets}]. upgrade_state(State = #mochiweb_socket_server{}) -> State; upgrade_state({mochiweb_socket_server, Port, Loop, Name, Max, IP, Listen, NoDelay, Backlog, ActiveSockets, AcceptorPoolSize, SSL, SSL_opts, AcceptorPool}) -> #mochiweb_socket_server{port=Port, loop=Loop, name=Name, max=Max, ip=IP, listen=Listen, nodelay=NoDelay, backlog=Backlog, active_sockets=ActiveSockets, acceptor_pool_size=AcceptorPoolSize, ssl=SSL, ssl_opts=SSL_opts, acceptor_pool=AcceptorPool}. handle_call(Req, From, State) when ?is_old_state(State) -> handle_call(Req, From, upgrade_state(State)); handle_call({get, Property}, _From, State) -> Res = do_get(Property, State), {reply, Res, State}; handle_call(stop, _From, State) -> {stop, normal, ok, State}; handle_call(_Message, _From, State) -> Res = error, {reply, Res, State}. handle_cast(Req, State) when ?is_old_state(State) -> handle_cast(Req, upgrade_state(State)); handle_cast({accepted, Pid, Timing}, State=#mochiweb_socket_server{active_sockets=ActiveSockets}) -> State1 = State#mochiweb_socket_server{active_sockets=1 + ActiveSockets}, case State#mochiweb_socket_server.profile_fun of undefined -> undefined; F when is_function(F) -> catch F([{timing, Timing} | state_to_proplist(State1)]) end, {noreply, recycle_acceptor(Pid, State1)}; handle_cast({set, profile_fun, ProfileFun}, State) -> State1 = case ProfileFun of ProfileFun when is_function(ProfileFun); ProfileFun =:= undefined -> State#mochiweb_socket_server{profile_fun=ProfileFun}; _ -> State end, {noreply, State1}. terminate(Reason, State) when ?is_old_state(State) -> terminate(Reason, upgrade_state(State)); terminate(_Reason, #mochiweb_socket_server{listen=Listen}) -> mochiweb_socket:close(Listen). code_change(_OldVsn, State, _Extra) -> State. recycle_acceptor(Pid, State=#mochiweb_socket_server{ acceptor_pool=Pool, listen=Listen, loop=Loop, active_sockets=ActiveSockets}) -> case sets:is_element(Pid, Pool) of true -> Acceptor = mochiweb_acceptor:start_link(self(), Listen, Loop), Pool1 = sets:add_element(Acceptor, sets:del_element(Pid, Pool)), State#mochiweb_socket_server{acceptor_pool=Pool1}; false -> State#mochiweb_socket_server{active_sockets=ActiveSockets - 1} end. handle_info(Msg, State) when ?is_old_state(State) -> handle_info(Msg, upgrade_state(State)); handle_info({'EXIT', Pid, normal}, State) -> {noreply, recycle_acceptor(Pid, State)}; handle_info({'EXIT', Pid, Reason}, State=#mochiweb_socket_server{acceptor_pool=Pool}) -> case sets:is_element(Pid, Pool) of true -> %% If there was an unexpected error accepting, log and sleep. error_logger:error_report({?MODULE, ?LINE, {acceptor_error, Reason}}), timer:sleep(100); false -> ok end, {noreply, recycle_acceptor(Pid, State)}; % this is what release_handler needs to get a list of modules, % since our supervisor modules list is set to 'dynamic' % see sasl-2.1.9.2/src/release_handler_1.erl get_dynamic_mods handle_info({From, Tag, get_modules}, State = #mochiweb_socket_server{name={local,Mod}}) -> From ! {element(2,Tag), [Mod]}, {noreply, State}; % If for some reason we can't get the module name, send empty list to avoid release_handler timeout: handle_info({From, Tag, get_modules}, State) -> error_logger:info_msg("mochiweb_socket_server replying to dynamic modules request as '[]'~n",[]), From ! {element(2,Tag), []}, {noreply, State}; handle_info(Info, State) -> error_logger:info_report([{'INFO', Info}, {'State', State}]), {noreply, State}. %% %% Tests %% -ifdef(TEST). -include_lib("eunit/include/eunit.hrl"). upgrade_state_test() -> OldState = {mochiweb_socket_server, port, loop, name, max, ip, listen, nodelay, backlog, active_sockets, acceptor_pool_size, ssl, ssl_opts, acceptor_pool}, State = upgrade_state(OldState), CmpState = #mochiweb_socket_server{port=port, loop=loop, name=name, max=max, ip=ip, listen=listen, nodelay=nodelay, backlog=backlog, active_sockets=active_sockets, acceptor_pool_size=acceptor_pool_size, ssl=ssl, ssl_opts=ssl_opts, acceptor_pool=acceptor_pool, profile_fun=undefined}, ?assertEqual(CmpState, State). -endif. rabbitmq-server-3.2.4/plugins-src/mochiweb-wrapper/mochiweb-git/src/mochihex.erl0000644000000000000000000000400312305126066026517 0ustar rootroot%% @author Bob Ippolito %% @copyright 2006 Mochi Media, Inc. %% @doc Utilities for working with hexadecimal strings. -module(mochihex). -author('bob@mochimedia.com'). -export([to_hex/1, to_bin/1, to_int/1, dehex/1, hexdigit/1]). %% @spec to_hex(integer | iolist()) -> string() %% @doc Convert an iolist to a hexadecimal string. to_hex(0) -> "0"; to_hex(I) when is_integer(I), I > 0 -> to_hex_int(I, []); to_hex(B) -> to_hex(iolist_to_binary(B), []). %% @spec to_bin(string()) -> binary() %% @doc Convert a hexadecimal string to a binary. to_bin(L) -> to_bin(L, []). %% @spec to_int(string()) -> integer() %% @doc Convert a hexadecimal string to an integer. to_int(L) -> erlang:list_to_integer(L, 16). %% @spec dehex(char()) -> integer() %% @doc Convert a hex digit to its integer value. dehex(C) when C >= $0, C =< $9 -> C - $0; dehex(C) when C >= $a, C =< $f -> C - $a + 10; dehex(C) when C >= $A, C =< $F -> C - $A + 10. %% @spec hexdigit(integer()) -> char() %% @doc Convert an integer less than 16 to a hex digit. hexdigit(C) when C >= 0, C =< 9 -> C + $0; hexdigit(C) when C =< 15 -> C + $a - 10. %% Internal API to_hex(<<>>, Acc) -> lists:reverse(Acc); to_hex(<>, Acc) -> to_hex(Rest, [hexdigit(C2), hexdigit(C1) | Acc]). to_hex_int(0, Acc) -> Acc; to_hex_int(I, Acc) -> to_hex_int(I bsr 4, [hexdigit(I band 15) | Acc]). to_bin([], Acc) -> iolist_to_binary(lists:reverse(Acc)); to_bin([C1, C2 | Rest], Acc) -> to_bin(Rest, [(dehex(C1) bsl 4) bor dehex(C2) | Acc]). %% %% Tests %% -ifdef(TEST). -include_lib("eunit/include/eunit.hrl"). to_hex_test() -> "ff000ff1" = to_hex([255, 0, 15, 241]), "ff000ff1" = to_hex(16#ff000ff1), "0" = to_hex(16#0), ok. to_bin_test() -> <<255, 0, 15, 241>> = to_bin("ff000ff1"), <<255, 0, 10, 161>> = to_bin("Ff000aA1"), ok. to_int_test() -> 16#ff000ff1 = to_int("ff000ff1"), 16#ff000aa1 = to_int("FF000Aa1"), 16#0 = to_int("0"), ok. -endif. rabbitmq-server-3.2.4/plugins-src/mochiweb-wrapper/mochiweb-git/README0000644000000000000000000000127012305126066024303 0ustar rootrootMochiWeb is an Erlang library for building lightweight HTTP servers. The latest version of MochiWeb is available at http://github.com/mochi/mochiweb The mailing list for MochiWeb is at http://groups.google.com/group/mochiweb/ R12B compatibility: The master of MochiWeb is tested with R14A and later. A branch compatible with R12B is maintained separately at http://github.com/lemenkov/mochiweb The R12B branch of that repository is mirrored in the official repository occasionally for convenience. To create a new mochiweb using project: make app PROJECT=project_name To create a new mochiweb using project in a specific directory: make app PROJECT=project_name PREFIX=$HOME/projects/ rabbitmq-server-3.2.4/plugins-src/mochiweb-wrapper/mochiweb-git/rebar0000755000000000000000000027203312305126066024453 0ustar rootroot#!/usr/bin/env escript %%! -noshell -noinput PK-qM>÷d getopt.beam…X}lçy¿ãË#ÍW>êhËvçì£#;ÔÇI¤,Q±œW¢hÖŽc3%´s’"O%ŠdÈ£mµq«Xv*×ñ¬ÔI¶af (P ûÈš¦-º?æfÿ Ã: Ú% þ«4X XW`¿÷î(QÍÖ xŽÏû¼Ïçïy?NwêüçF¡ï¥™ÔôsÓf}E\ÿ-BÊ»`˜õ†éi›-Ãk4«ÅÚ‚k±ìm™ÍJmÁkÖ—ZËc.6ë—=F³Yozª•–Ùò5K,\õeÏ¥bµmˆQÏ|±Ú2B–£<\Vêµ|µ^[ð-«ó•ZÙß®• 0F¹§RƒM¥ìhíßaRlµ* PÊ› ½;-Q«Q­˜;µvØ·ëMÓm6ÛÆžòšqÅäÚ¾¹z½jk¤V7{W*ðS[èò¯ðTó5 ¶eâàÞb£a@ŽŠíªé̵ü(mÅX™3š{Jõ1·¢Õ­Ì~M å[ £”7W†Ï¬Û¿•ši,MÏ|µ^4½s•Z±¹ê.¢O»9Üy¨9´3¶4{:#Û"ØrK ¿Õúe£é+–uW¥ÅÈshÈÔäTÐ[mãjˆz0pPê è|ÈU­à|ài·Š †«R÷Î×›+EÓ3_¯–«¾ùjÑ4Z5›/­”óU4>ÈÓâéñ4©=ç ¹gÇ(אַÝÅòVïjÃ[5j æ¢¿ÜÆ"(MÃW2*ð¼àAQµÒ®•z¹]5ì|}7Öu¾{ÈNg[ëÑZþÁ‰Ö§×ï¾ýæ]ÿ`üíwƒjƒinV »U:æ“UF4Vœiá Yö©º\O©JÚ&§T’þvZé•q“•’ìÝ’·Aeñç×9X|/Xh0%Âb SÜpÁHœ•fY6÷zâoÉä#¢ÎA™!²}¤|˜x¤M>Ò2,§„rL#ÐbW=2s‡YUS$’eacY…Í&Yœx27 âýè#òPV…T“î‹tOþ(ÞNeEmUd•£¸Áÿ¯µ<8CÄO\½ÿÞ%9Øh„ÜŒ”Y‰°l˜%QIœi³LɹeúX‚†È$ˆ—PB -I²p–Åc(€Íj¬Là²ÌK—^kz[’å³Å´‚iQxMÞt˜u-­Hr³a”%íqõ”5QÚ\[cJ™i9++××B¡a–°dœÅf™fZ©ö!ÕI(ÎZíÌYí„J‘XYa1¾ .Féèãc“„Ê!sCnüßУš#\ÏÄ*}ÚRù ©<‰Tx“ŽŠRœ*y37DéèvWÜ;ºrŒwå)@¶¯ JÑ :ˆ¥ÔJЧ²“ Lpsm&+\ŸÉêwɱ»ÝÐÅ9ªÀ¶ÄÓšÒØ,1˜ x„X’>9ƒÀÙôõt /•EÚ[ðäxe›¢4ÀL%dò=¹¾¡¶PÀ1•C}‹£P{óKƒqúTr;¹BÉå\‹‘YÞפ›ÅÂL‹0%nç4„œœ rVŸÂ^‡:à|&ÛÃÀå1U”ô #ÓD‹%è¨6 ÊÌhrrFS³Q:šäKd4ËŸ#Š(ë:wñaZÃR¹êakJˆ÷Ü‹R”F·¸Xœö@+Ž(el‚&œ(ˆ2Á£ˆ¢g!@ÅY5ÈP±Œò4¯IÂÏvlòXܧoFéqœ«lÊ”â&St\”ŽZQçç$ÎPšL”&ì<ÆD)§qœž “Ø “Í k z ÔT$„¶ž¨StJ”N€×8 ¦d]åeÃ>x:)0Ô8 Š ¨vNžÏ Â!TÊôDx†dzt~ØZ»m1B§‘–}±ðîá@ÂbH;[?œæiV"½:L/Eè ¹Æ¯C>ž‘7(ÌW·u(‘íFí$Fi³ šBà”uÄóšS:MòßSPÐYZ§çÉÓ„žï»ˆÐÏŽÐÓ'é™@?}6°Ÿž¥Ï"‰sò=Q:m1ï‰Ò‹¹/JÏZÌDélÌ/lŸü*Á*y;Á:¶ž³/~™¾¨Óçy¤çûX ž{Hq¾žÃ‚°´ÎÛɰÀ ‘äOùó|Ÿ~Ya 9’–­§j=uëɬg&J/4àÎÁ3wsa—G’IºÁùàB‡‹èçIzÍznZÏ{Öó=ëy?J¿@Ò(åóŽ‹/Ø.pþ·àbX]LЗfÁËé¢(½¤cŒª }`÷E`ø2pË‹ÒQ‘W¦Ë¢ô²Í-ˆRÞææD©à„)Âõ(²›ëÁ»É|:5¸O£=¤%€U¥`ôDè–-Ä g™­ubƒ6w1ü.LÐ v–¢¥‹Š_ÇÓŸPp·Øi,ÚÛ°§óÄÉc †q.OкcX…a?]¡(U£´¦ø‡DiÅv‚ªj¶“zœ.uœà%-0œ^ ªxKÁÅÅWõå­÷ ®á…%E\$å&$ÆDú"©RFMnŒ•Û ê:7Æ»–ù´ýšm&¶÷Fq'06¹l÷v0ÃBÖÑHœs{AàNñ&á·Ñul‘ U÷éRowËÝoX>YRþŸ —tØ]†{,ŠUQºÂ%¨iu‚®9Üœ'W´LPG^ö)'gqž–pÚµî—(}µ Ð/ád•× ©lZ ‘”ý‰–ò«η¯ŠÒ—è—Kй×H•ºt>­øeæ²™WèUxåçgEIaù*JK½°8ÁÍT§²Ž"Ŷ½:@¿R²mK¶­$ÿ&ãO{ø l-Âe§Xvö¼(}µsõEøQ½ 8×âô ö¢JÀ_¥×€è `|-(È€™·p{r“S€ûú½éÀ½¸×-¸w‚ÍZü¸mÙx¿^âwØ +CfgˆäNðä7Dé†ÌÖRYPÔlÉëQú5Þ"Èýƒ¥®‰¯É÷-QŽ‹,±µDiƒ_ïaeC•Ý:½e¯3”}•ÝŒÓuç^ú:ê9 $nÓÛÊÈ…=r¶_¯zdiQ®zÔ5ÿ^Eé§oˆŠ<®â¿5Y-*ýBñµ~ùeÃÓ/ôËýBÞƒ•_èø{Êö&þA“öÊ÷åT$-…•Qœæ©öCI)ab]1oÈRoGëMÅ&€¶˜óÐ0ârE³mnãxÀÏo£€iÔt‡'Úg'Š@ýtS$à™âZ›vµoB9‰.~ƒõâ6‘ö‰Ò].ù[ U 7îÛ¦ÐäwômÂoç•cüï1þZ|‹dÍfŽÿÃzz¥_ñØ rƒDä¹@~PÀ‘wx—£O»tdGÆÉçèÇw‡¼Kÿ‰.ý£]:Ǻø§ºøhWn]r©‹vüwÅšpæ9ŸèÒº‹¦«FÖUãL—Îì¯ñ®ÔŽ¡pÖÁ+éÌ¿åðüï 1Û¶Ãsû–Ãó8¯8¿j׸ÏÇ_)GþŽãOð|øÑþ³3go=WþàÂ?L>d²çÁ?íûÅ»ø­Í¥;÷þ4U+þÞÜ‘÷{ƒï?ø›Ã·o÷ýç±7öyß¹³ú—õ›‹ÏÎþäg§nFÏè¾¾¿þÕôþ}ú…nßïýÝôk/dþîáðÔ÷.ý›f^ýó¿ú³ÂÏ#ÿzæON¾~þÞ_|÷ŸOÿDü1ùý÷ÿ+úGgG®ýðæ·f¾óË[G~u<þ¯üôÇ|ü­úÏBãG…³õR÷Úê®aÚ©ë褃Å-Д£stÂѹštä«Ïå—Aq‡_Å~4êðs Çö"Hwä/‚†> Ò4è°#ç½=äÈùZP9_/ù˜Ó#—ã{Ÿ³ø:Ý+Ø{€ûÛãÔxÐáEÇNìµËuw;ú²ã¯qiÚ4›øýx½Ê=,ºÊ¹ÔªñX“…ô©ŸWzèïýE=ýͯÿÈWðÛæb½ié”e©]¬-ÕY©¾bT«ÅÖP½¹`©í2®4êMÓúvÈu}\(Y_÷ ) |èçCëÛ¬=–:_í!mUVÕÎ'7[¶õv­¼Cêíìê|fµ--%O׿‘À/­Ý\Ãç|Äã/âX_ó­öÊJ±¹jûk›åJsYps•—ˆ•eÁW©•ªí²Ä·>/Ì•ËB`æÂé³³ùÜéçRËÂîQ}dD‰åõ1=ë(I/$³ùÓçN_v-TLu||D/Îé^>þ9I- žøÐøÐ(—¹ÍÊŠ±èÅ*ó}TtiÑSôƒV‚­z»Y2–…Èð"^6jK•áV³4Ü4æŠM‹³?›Íê’0=×2ù¾þPK-qM>ûp² T mustache.beamX påÞ½ï~ö.·dïöBágÃ&’l²’K¿Ü%9ÂOˆÑêår·IŽ$wçÞž`ÁB‡ªŒ(2“Q´Ò"L¥S D:;E©uœi©ŒÅê@U1#¢U«öýöö’«`m†w÷½÷ï{žý¾eÛW¬¬¥(~™¿­ey‹–¦(úSŠ¢1Ã锎 (¶Hb8RE ¥"á¸5¥©±x¿)1h'¢dXM)yú5¤¬Oª)ÝP¹;<äŒ+ëB½±x¬Sf¢³€4­˜#‰¨bI¦Õ~Å>”GC}Þ:œˆ¦‡3áíªbHMªbS•äP8¦ØÓñ¨Ò‹+Q«ª«š£±ˆ†`)[(1B!KJK¨Še(–ÒR¶¾¡°¦)ñ¼¤ª„ŒB¬_ò¯¬´(ªšPC®"5· ‡µÈ€5•î…*éJ[<¡ ò ›PJ‰h±D܆V…´Dˆ¬âÌ*µpŠKhŠ6Çq%/GÅjÊ0T¢)Ð2mÀ²n @ýŠ%Ç£Nˆ$]}鸾 ihBÕ”¨YSÓŠ¥/<”RÌ`”ÊÅ5¥_Q³)XcäÞkíK¨¯U9%IçîV`,аª™b‰¼LC±x_"VåüÀL(*o%Ìž£2[:<4grÏâh¡¡Mâ8¤x³ÀºmåkCMmHò#Š÷#N¬lãWbÙ8.£rmb‹(¼m,›m”€Íh+GÙéú8‡!Ž›âiÉ "³™cçe,‚ÂÑx1¢» 'îq æÍylÆX»Ë—FMéÌÚ•iþ}ÎÆõäÈõEÒlãqPa1”DNr]\;æƒOÐtÀ?—9[«î.ý—{¦Öëã6¦3µ¦oTëuq²µ&¡ªÍ&·c2G︾ì#½‡(ú`à ääHÙf®LW‹ØQ€,Ò5Ž>Öp†Ÿh µ›yŒDh húä÷«Þ!±%z¬å €„Ebe#¾aÅpNNÒ#ðØ1Ù¤êZÊ1ÜŠf\e:˜¹’à«RÌ{pC“»M8èc=¨ h¢Y¬‡Lô Xó{m|,ïiÂ~…üޝdyäðp]R;–ɸx˜ˆe—¢­3›ŒƒIÞ&#©7£,·1Â1ÈØ=ˆáNJ4ã¾3y d>ÙÇNᛀ°Ÿ§D?/È•ìÑá™´c>J@šMxÇÇB–E¹Yñ±‘-Ò'ïc‹dPË‚_¦Vùe.Š@K µ)P¤Šñ§¸½ ØÒ²eô8(FA1*øG©ÓþQî¼—-:Ž]<^%b ላvšØ„ý"%ûE.PÉN“§Ôe`råqÀ£ç ð €¥cÜðˆáà1‚™,ƒÆ™Ð‚Æ 3•‡‚¶&ol&€–Œa ¡† úØY0„Y¼C(§|û-Üd;*ø–ÞkÁ 'BÙ²Ø)ÑLxÏx—7²sQ ’Ul™Ü,³e…Ø^Âζo`çÐÌl/[€´ŠIˆ9äÇ$Nò±ðƒÇ@5F^uo2ê™lÈó ÞdÄŸløÚsúj5îDnZÓ ø¢ôú'Ó+ÿ±â-‰›ßå8‡§žþÙüáÓÛ¥’bÃgÞ#û ö|Kl’/ü©s¤þ¦¯¸w|yjÓÆþüuîÞüíW®|uôêºBÞ?§äÂÕŠ!û©NljG=ϬÚï·Þ\qâÛÞ7†~û^ôøKÇ~tâ_çZ¿ž÷—ý &¥w-½å½g…ß4V¼‘xeÝŽ£õ¼”'¾‰wþÙóH„E/|àÒ®í›êßž;8µqß¹Qׯ¬É{ªä}¤¾½º`ás5îýqWþ‡>ìTk×>!?£í8ÌÖÜñú‹_ܹ?ioyüTeásSžÌw‰|»´ú½èŠHÃ¥·ñmþxŠ×öß~áÔ_ÕCw>ôÔËWvÜZ½q[ÞÅC÷_Üùe×ýor‡~î¸zyûê%åÛŠÎT·žž¶|CËÎÙ·ßüþyc£Ý¯m°Ü¶åŸ¿|àÕ»ÂMÿìàñç®|ݳvó·žµ½TV÷tÇþÔ»ý¾¶Ï«?p½q-@[ßC}|íÈ7Ôµ¯ÎGž°Ä&ýý¾ºû~õû3›¶]zpßeq?¶©ý¡ÚG›ßPÜ¿ÃÒtÏö×¶ßÕû» [/.}zïü¹wmùÉœ ò³¼Põ¡ϟ?t0öÙÚ©M]»ëw>vàòÙ^½¼ì‘æâ§Ç\íÿíà¼Gw|Ú!Þ±æÄË»_|äêÅà¿g?ºÒýɱﻎì©Go ? rebar.app•VMÜ ½ï¯@+í-ªÔö¶ÇªýUo«QDÀ¤´P>Fö¿v¢NvC›Sb?óbžY¹s¨Úšy˜¸îØÓ*!¯ÝÙ|ÿµØÙÜÌìSÒ(Ù7kñþ%ƒÙz ôaûZ¬La`Oó½y^#ŸŒ£°‹Óƹ1E¡îžx€NaÒ3åó@x¸!Sƺ]‚#ꔚãé™Üd0ï;»iáñØ#qû‘¤;MìHå¤-þQõèÏådÄ -ñ‡lt¥êNg}ì$vÞF;%¥Bh ÞK÷+ÚÇ3áTIÐô{ÀåÙ󹣜¿’ÎùËq¬Bš¤öDê‹CNöIr³ç’80Š{Pמ¢½%`I!rñØá¬#fr= ³”l¶Zù ÞÀ å Q¢žªpË易\0ì3(ž0²Ü“ áxñ®Ù6¾ÚÞ[Ÿ“Tc÷ý°SØÅ—Ï}¼ãæ”%³ܭBÐYa7 ÝÅn ñ"®•­]sßhˆ¼¦`5ÑF5(ÙT5ð&»-äá†óL\p ´Ò¢Í`‡¹ÒZ…ᳬ’‰€öÄ#WéJÙÓ4ªÊÖ8"bšSˆˆi z™æ4!š²MÄ“‡@ß^ ¨Ô†-¥n TjjÌSøÊ‚€Ö$œ€îæ_'àíIÞ=kÿs‰™H ·9Ö­®ØYóëáåÝÝPK-qM>ï”×Öä rebar.beam…X \WºŸÉ$dŒ ™ˆ‚ADy@ex„‚¢¼´Uã$ WgѪ-Ý֊תh×ZëÖÖG‹Zo}õ^ÝV[mu«^|kÝvµÞV«n[ÛÕj÷;“AÙ½÷öòû}9ßùÎw¾ïÿ=Î9ü¦|âä, Ó],±W| #ö`Ö¨x;'(=œË«âÁ'„5q.7ï ã7çmV¶pî€Âצpùš|‚‡ BÐÁùýn—ƒ ¸|^¥ÛÇ9Õ ´qÁÙaaŽ?àS‰N„K¦mn_³ÒåuÔ¼è\þ@Dh°y9O6/Ĩ9»ˆÆÈЇÏÛäjÖˆ|ÀÖìöÙ9wxÐëä›\^Þ©i~$T9y{°™¡mÁ€Ë-ª‘‚£ÝIÚ9‘·9]‚Æçç «HøƒM¯ §ý‚ÏÁ‹"L<Îë•-¼Û|þ€*(rͼÆÏ `†šE•Īgñ‚Ý'ò*H‡ƒ'‘³VŸ]T¢Ÿp°‰b8’ÏâÜA>, Ú&b–è•¶ñs¢ÇgkrsÍ’1»ÏçV„ 8àÜ"¯[|í6—·Égópsì¼ „ìÅñØ-€KpyxA%ºyÞOzpeý¼Ã†à„¹|0ÚÕ.o€oæ…HÈz€$Ÿb˜\Þæ°€¯÷Š‘HÝðÙ8蕊Zàvž’J…ãƒ^În‡%àmÿ´©€fâì>!0PªEŸE›8—öˆaÞcç….ñÿÐó PòÙavÎ éú¯zbÐnk÷ Îǯ!ÿäÿ_uk„Çç ºy)»QiŸùˆô_ž™•îv$Í0ÂhL’þ¿•(3;½)èMÏþõå¬__6¦÷O—OÖ?¹„ƒ[êsò¦¾,…þ:8 8­Ð¥q}$MUæ*é n,Ræ[ˆ‚zB_B`L ARë™ìÔzC M4Fãlj=!hi¯¡õ´…P0¬#Ôzºw}¦B»Æý`’%”¬–PÓúÔ„À*‰NSÒ”VEÿÃ;Æx—B{’Æ×›{ˆb‚1˜{˜bÆTšÞc*4õIJá³v…·»S{J­tN!ÔÏ „cðH¬$¦eñg!¯j̘z•Ô ^£•àÔ&IkÔôL–`X  ÒûYMœÌv„"1°V#Hâ µ±K­ïU")ãÀ%× &Iú_n+´†“tFkeÁH‰µÎdHö3X‰d'µýŒ€,IRJb¢“Ôú+ùTQô(ÓF*Ž)d¨¸X6›bJ‡“ è@Çé5–0S‰.µ”*‹‰G~†ÍF`¥ Hé7â¤îÑØ@À†etȵž2¤R±P M Ã&0ÌjFô²jì6cÁ¬&•` Jµ‘¤Ó¨þPB‚‰V"!d'û#ôÊè$V“2:Š!4qRž2B1,´„Žè4b`Ö¨¢©ZYLI¨õ¬d öcÍTvè SY†bƒ©4‡Ê.e‚5)f«d:i=:iJÔ>*è°–JZ¯·0:Ô¨H )Ê~„œŒ•®ž¾‹¦*“»hrNæ¬29tãÀ9 ¨zž™* "õ4 DÕ†;b´™2Ks¨|d°wÒ4,ä!wJ‚òl†UBªÁÿXÊ ¢§Y‘€E3zn r¨QF!ÀóÑý>¸Ç¨\ˆNL-jM8G0ÈH¡(’:` tÀXœCë1‹Nj±EbŠPýY°Z i+~ÔÅ`d°‘*CFÊÀH.U†Jq²äQšËA¿T2QFér=4@•%šf¬YÀf5ŒåÒaSB0áê!1pC$°„IâCR¥TLIŒŽG!ZÁ@ g¦ÆC~ &3UÅDêÙbšÃ m‘@V#ÕR¤´'+PaCv`¥r|UEÁ…“ƒYA¡±Å?\M‚jO„[ê›j@LB@¨'qr2ka±ÖL5 ^P:Ô‰=Y º*‹T#ÂÓ(%­0ÕãdÝ£¤ÕB£Õ‡fpªAзr¨ÉS#Â4œÕ¦©að|áä0­‡é“0MÃÉi0m€ét˜Ì0m„Ñf¦fð˜¡î”N‡”PH?zËúºš™CÍ óÚ€P‡÷ F| °CT@a@8 ¤ŠŠ”åý€¢äÿ ÐÿÑ2¯bd^Ô_ÖŠ•í ~€Ì£½œA@ƒå½ƒ^ÖI”q!;I@Ã0ôt†øá}lŽ”÷¦¥Ë6{ù^üY2ä&™G1šeûù@2?ºOìE@¬Ì#lŲN úwIæ‘N¹¬ƒb±Ê<Ò©èÃïc‡÷Nš(Ï‘|²,ïå–Ù¨FX•\›Iòú$™0y¦ÌÇ%Ë:¨&YN˾‘\QôöÚD~déòˆ)ƒNT×zyú¤¼#Æö †:Y>U¶‰aÖôT¹ W¾ŽašE³×,i˜>ñb¹.˜qpùùJÏÊïoþ±¾lùÌsÕ/lXá½€%nÖY&­úžßUâ˜{c°ûÏSLwµ÷º3¾üpáºÏh80+aû qé;·..»3úÖö¯æL̨õ}÷zäÔ•Uã¿x"µºdÅ5üÔ¦×NþÜqmAÔú¨+ñgÊSõ4¼zgkÇßék·Ò×e÷ß¡íxeç"ë²LoXM¯ÔÏÛôù­‰×Ws5ÿååÓhºvêŸþ‡·7^.WW¿?ü¸ª2»÷K·Ùný—/>óŃ·ŸLL ÞKo{?úÃ}K[WZö® b–E,¿sÓ´¿‰òÚì›ãÎÕÔûGüg|µgÍ…e6©|?s]¿?8xê/;O|x嫿ûoý¨6æÙ±ƒºgú¯­ëGÇÍÿÞÚoéËÿ6åÈÚ¬ˆ%Þ;xÚw6žˆ+:ðÓ·Û6øO´ÕÞ®ùð7ÖÕ§W_^üÉ 3ó‹´iû~Z}jíþnGØÚÅBåG¹¥÷‹‡íhyïã£ûÞ\ó_O]¿´:êóUnïKíÎâÅ£‹>5¿Ü>W³Aõ÷cߦ=7JÿúÈûFäX;¿Y8ìÏ‹#·Dï©[¼r3³dikWÅœrÜ4zè°Âœs„/~Ûô]™cš%çhæí¢©·×ŸÐÎ|>bëJϞɖ5‡ï~ýñéß_<œb=þˆö'Ÿý4ýÕ‡az»)9{õ/kïwoüŸ˜üô±agîÞ|'pØY² aQSþsÓ®N{åíš6f\¼öâƒÁÏ·ÛÎŽ¦Ì‡ö+S‡ví~iw¤jMåì=U ®˜;§žßþÃëÄ¥Ÿ¿èlž÷ÖíÄ¥4ìÌêqÉ[ºy¿y×sü ê?=)¾àãM{v§¬<ú¶rÖEâádÃÙyÉuü„zs¦>ghJWÌ”n#þãü'b.œ­ST, ¬K{æÐÜï;ãÍåC~;—]óÄßï9žüת¢ý ;—œ|áðkAûŽõÎÕËVLètüìÃÏ?ß™7ï——¯ÝY;÷Ü‘>Ò-.é8ÿuI‘QñÔZ{UÚÊŸÄÍÇßZ󷌢zŽ9õSuツ1#’^,ñU–™—æt\ÞhŸ÷vd*•0¾ ±@µpÊ™1©Ÿ°H»sdꉽQ‰O%h·44vÛöžóûÎ/ÞŸÛrh(guµ}±nÄ®®Š¯ÇlnŸÿªýÂþšQô{µŽû'ÿ6×Û¹ÝìÙúñ…7»–nï´sk»ýþó>â¼W?zXY8wùíëÿžÂ~ÜòÁ¹´›7,KnEåçFuª6—t½±5©.·iÕŠ‹ª•—|%M]{[¶/<þÚ–Ó=ô•²Ok·ë‰yóQNôûlRáü_ÆmÜ‘ukVÖ󊬵»žbyøÔý»Ôñ¸Kƪ÷ÛÙàÝr†ü /ÌzáŽXoûÁèÓÃD£uÏñ%…•ó/üöMeéw;NŽ;_?½ùæØoF`«t=X•Ïî°ëXèÍj”ï7Û¿Ü…}￾w^­|FæÇUË:Y ;rebar_abnfc_compiler.beam]UlUwïÚ^oívíöCp'íœBFoÝ Lß~tµ:¶†ñGÈqm¯ë­í]½»p&"þÂÄ¢FQ !ú‡‰d@1‘80ÄH"„(üaHŒdš 4þÀ÷ÚC'M>½Ï}Þç}ß÷û½—÷†7´àá{ã=ë{l£õ$ 5dª)Å”•”žMËi£XÒ ªéq›1Ò²i6ge3­Êê6Ûc”m9£™\ÑÈ” É­šE£W¬ªÑRŠ¥þ še«Æ7J¶å«ZÒ†žÕÆà˜j»±ªº·d¥‚fÙ–‹ò„R(«žŒšUÊ›¯N×,¹dª–ªÛ®ŠÀ¤ŒêÚšÓÒ9Øíö醎ÓÁ!4}Ìï,_­Œ±Í²êÊ*Ke³XÕ•¢Ê’, ¸Êp醑gÈ(mäiÍpg ³¨Ø.;g[kœj5=kÔ‘ü¼Úœµ¢±¶lYo“ÚpcûpjÐ<¦ä· £ ÃKñtp™H‰µ#<‚ý GP@1ˆ„NFTŒ Nõ ¾¡Êħ Wl xD€ 3P¨uö¡H1- ˜Fý-ñ#”DòBt†$‘¡ƒWEj‹O‘Ààð ÿ2b;Y Jt ðÔ© ×ÂrýŽ Ó±éÞ÷SÇ©=(ÁC:ˆ"~Ì ÿÏbsPç} N€Õ¸F Wƒ@ ¾Çƒ õ‹O’ ‡pa ¸(ùØ/Ô#®ÑÏsMþ Åòxñ@ÈéC/îC¨R/ƒB jÇYFpíŒGÜRI·ÚŠªS¨Àíàgù1œà–&`g­g¼ÞáÀY›¾²>ê¬K|­Î¼FÇ þð‘óù‹o%Ÿš>±üÄ¢UW´#—®þÚU{¨nÿÒN)è…7ö5Ÿ½›ƒSGfž½¾÷ï¹wÚ^ë?’ݺªáØö'vïûcnøùÉ5¿u Íö/6™¯ïO³3æñü¡îžÀºOŸûäV©ÅòL´6ÐuA`¾œŠe¦²þ×\ÿùä’Ù߯ õyÝù×}зùÀäô¹ÃÛ'vϳæ†xYflZ~jI+ÕÝ<¯ì4ÕýÓÍ·ýéÿâÕɧÁ ‘&ub¸ïèMÂïtZE¾uÀé#ÙµNÉÜGgzlÛ$ßçÅQrtÀ K¯¼è<M&w^¿$ŸËöRîÚäøx_RÏâ1oÅÏ¿§zæZDpg€_5MÔ­r±¨˜Û‰ÁOy|È磦4(”–MOÊ5¼eŸÍš®fre2€ëÝ”ì—G“ëãyP“ÚÛ¥X{‡,uIvtÝ6±÷m”“CÃyP3¦ÙâêÕí’’’Æ+9M¨¦…“ÊWçÊÕ+cDcl­¨æÜ)¼‡.+´âW\ŠWñU¬ÞHy‹æŒ¢Í«ú¸µÌt´r¿üÇî¸ÚVâ»jWÝ“²lÒðPK-qM>ܧ=prebar_app_utils.beam]U]lU¾wïlw:»CowÚÒŸ:F:í¥qºËb[ãCãvvgJ§û3›™Ù!$Fä¥CHD$ ‰Æhš0Áê‹ÔLTâ_CPbx#b|ÐxïtjW6ùöž{ιßwæÌ½s3ÇŸé€e“éÁcƒ®UNv4ØFN³³Z¥’­ºfÑáLÇ›è¦^ yîÐIÃÍæçtvÊ,e­d03–YÑYṈ̃sfQÏk¶Î¸vÕNiEÇX'rì¼D@H",u?8A‘<Þ»µÎVä´@i†²ž ¬ó><Š KÚÁmÁm¬áæc„œv>*òd£k\¢ÔÍÇ<Aa$…kBA™'­c…ÿ´hüÿb“kblŒªm&jÍd²¥V­…ªµPµ&‘o†lÓ†ZKZ˺Zó†ZËãj_­…ªm%j[ɤµA”qFT®UE\pAø6é /J"Yœ”@")áTFF*'¨ 5É3·u“8×®±¾2ÀÇÑAq]ZæãÂSoR8oçb|dÛðqiPJ¤Hv‚d'ädŒ&8ŸLˆN7åĽ|<…åyÅah=yÕQbHÉÇBâ"V€_ALe¼ :¼ÿ8ž\«½SEtsq1²»h@<*AvyDI†lgD”‰Q¡ºÙÍKˆk'„i†ô%Fû2Oû"BVò–n'«ºd»”(Á·!»ƒ:H§vÒ]G|â]D˨kÑÃ3TªÐñ‚büs$¨#ï<–Öø×툟Ãlòí >×ý¾Mù7×øÛ|ž‚¸oSÿ6?g;T“¿£&‡Úô)¯þ—8‚.?¾Ó·?nõý­;½Åôë‹úvÄïô9þÍúu@¿GŸ?0lº´†wI¨ñÔ%ã«AnYÆÁÛß\ †"\fì‡OC;z3g_øâÞî7Ÿÿé½ô³Â?ëqpÞ\ú`²ñÆ®?ƒs^9²2þþƒ·ÆVÎõý}çÌ~gùû·W¦/ÏþÑ?w©ïÚçúýÍ×Ò½vùÜ«¯Ü‰Z«ß]\®?¿rö‘†üÑþ£‡v–—®ßzqÂ|¹å–ôåÏÇWïÿ&ïŸxºké×粓O,ê«§ïŒ|4låÇü÷ýþÒ÷Ò9èº6ý–ž)ÒÈt@ô£ïMÊT~y§ø@ÿzÿ½‰ Ÿ·Ý¸vzf&5Tž"1ÆËgh~Ȫx—uÔé€÷n™¬S-•4ûšPgU]rcäÌ2õ@³Bf9_¬ê†6®‘iDbº¸äøÐð‘ìØÐ±t4ôɽ½r_o"+ï“ûÖ“ØgS£Ù¡‘ÌñŸ4]±¿¿WÖròŒWÓ¬a;¤¨îÝÓ¿§ú×,Óu9²±Ô¯µz-âèXU;oÀ“=ÓVÉè)峇\¨=Þ­½am\í{Èí;3˜s\ºþPK-qM>ª…ß[Prebar_asn1_compiler.beammUßkEŸÙÙ»Ýä.ÍäöšÄ¦±E¸^²—k …Iâ哦1‰‚rÙÛ»Ûû±{ì¤Ä@),–€–"!àƒÒ‡R|3h}‘RŠ«øÔ?@ÄßœÙlê .|v¿óý~¾ßù|gvgç.­æˆÏϧ/NûNø`LqiEw˺gçˆÓîX-êJ‘!UÙ­eUä-«eºkFäŠîÑ'dävÌhQÝÆGQžT|«å%LÚ¢>-Sݨ N3¥„“%ŽÈ!¯—Ú^àÒ²i¹=¡§ã{É#‚áØU«†jÔÙŽSiÄ9ÁðcÔu7NÝ–n×b~Ýu¶)רM]ݧf(ÓùÝÖÛTl8–kYžïŪNËl%ÚŽ0-–]uúYõr×x4÷?¥&&sÕÀÎi9™·ÏkÊ®ãøÜ²Ù\ÔÜ[ÜYǤl·˜‰ÁѵÃp’A†XH=£Bõ„Š J“@‰5@J¸@Jê,)iR"kDT2HɬBMH¹*$IÀxªÂ8HT¿“°JöQ (pEHÝÕàFRÕxU‘Œ(a-û)Ú'¿*DÈ ˆ’F0ÁÅÞ”)–V2 «=–Ô• zq©3(Ù]¥WyùìdwÑ~JUà6)m o¨ðú«îÍ#xGHõªð É&G"›«†±Š‹b©£%Üá= lÈ畵m ²¤I -ãëð>ÄPfk p—ºåæÕ œâMdX¡´„ïHø€”¶I}È•#A)Š ÚÁ8šCTd²ÂrÇXn:®QÖ|w/úB»ÃŸ·N0 ‘2Äâ ߆žÈÏÖôEv´Îåã±.-áß4Ùc´«'^Joo=¿dù<×e¸qù–±±qh28ª‡Ëg=þ½FÆ–÷pöýoOü® =‹>>MžK¬ßÿq1÷=¼{ífá£ÕáŸþ\\\|ïðóâÁþíÏŠÅ¿‹äç/îÝ¿õ(½÷)Ì÷/ ‘{ßœU?諟ºñÉ øúñ™i–£»çnÝÝZ£¾ø%"|Ú÷¹æå«-­ &@›žÍÐÆàä»Î—/ýUùíÃÅ•›ÆÕwœ×¿î¸!Ç)7ðØaB*zE¿B7ÇÙ÷Üh°oxÁ®²¸ÖyšÄN'˱= /<‰Ê^Ðnëî•°®øì(k‘V,›{ Õ’e­À¤&è l“V-›šuÄb¦ zg^_Xz¥¼¾p±Øý“Z>¯Mæ eí¼v¡pþ˜$¿1»V^Xž»Ô‰šå«SSyM¯ha+Ò&u=&ª bçÆ§Æ'¹Oô­6­Ç+ì%ùEô>=¦÷èÉP ç®A› ?QwÚt¢Ií†5á¹ÆDxæþký÷·0ÎNÛÆtÅóù;ôPK-qM>jQ¤ô rebar_base_compiler.beamuWklǾãÉÓ‰kŸ¸ÔÓ¶|ÒÑ’mZÒQ¤,YŠã•(Š‘ã©-j¸¥Iñ(ø8úî芠‚# )àÖ@ÜN_@ Ð(ÐHŒôoàºý$à¸.‚õES è,¹Jè¦0w³3³óøvvt\:ûL\B]HÏŸž÷ìª øb‚ ÌÇ,ä\!ïš¹5»Z·*¦ƒœFÍg—¦SÉ×Ö%׬”B-³5»V²ÖåuÓËmÚ×_4 õŽ–®b¯# År=¹æE_,ÖÙR5<«â*%«VÌ• €»kmÃ\+ç*y×ËUíbGݱëÍmMÏÛ®ô¸Vµ^ù<¥Üe'_¯›Žä9 Ó_ÊW\3ÈfB¯¡ ¡Á¶ªÑ.Ô !]IÃiú5¬i"…u1K3ªØjˆ`¹%ÖC[[y”iF#4¨+ѵ]‰ÒT’¢Eª¯5ª^PÓ瑞î8¬Ãc\'t‚di‘@ˆ±Ü¨¢²ìƒÚšLÐÅËxuòXW©¤ƒ)E ê!?=°%nù Ɋ¯×Ss©ë½T‰üDéþ½x;”¥] KMD¨¥(TëP)]DÀŒ¾)!Ñi’Ð(Ä@Oá,ß JbÌ[!ÒDŠê šÒA'ñ.DêÏŠ†h<Ö©(M$!k_PÝb¹G·zd[5‚Ú+MäxÑȇÒ"é(A²zÛ·AM”ÕàL`ÿìÔ`sh‡UQîS@]Ï`‚摞€7™'©•&)®0°`*ÊäŒz[”#`?dˆrwH0žÖ Ü‹æîhúpÏ$îåVŽÜ{‰r؃mÿ Þ‡BÔ˜G(É0‚òš½ÓmàA¶}°¹}`ïåUZíb@BÑYÇÇ{EyOKä Çú–(ï¥QÒÄù¡©(ïKâ>í ² öC#P–ÄCˆ´tC»(àÂNM”‡{ñt ÇÐÇz©†õ,>$ÊúÈRuÇÈÕ–2Š£ÊA<¹Ž*‡ðAQŽvÏàQÕ0æ£(º¤‘Œ2”B–W’A¬AR’x,J•ÃäKš‘nU3Ò:«6K¶©ÀïGæã]A”G¿Ð„cñ˜ƒƒÜ€pHSÚ)a‰DS1(E9ÇSÊX7;…LPp~ ºXת!,i(#e"ÍÎMnjPûßLè•Ã-›N±t¶þWº±><,ÊGúÙsìdT”Çþ h€‰ÝY¦C‚êpe ZXfQ6zñ4à?…fñQ¤í¤ÃG‰2ÔýdÇY.:¢‹:´kQŽŸˆ8É:'ÙìœÉIœåÉfúà·/#mÃd‘l¸2l ±ö`y$vLý_“¤zW]ÒôŒbd$†ü’–È(ñ J't½¹õ`F§Q´šcõú$‹”ÃÝl ·[>Ú‡ÁÑt?{ΓÍ1FgÔG¢<ˀ廅 ÓdX<Âä–(Ñ-Ö—l¦À|ƒë— . ¤¤”}Àú† »»)vÆÙïÁ? § ¿OÌà24¸ap·`4EƒšÜeà)ŦJ7žeÊF`„µÈ Ho¾µÚÖT6 aXÃAaŠXHâ'ÙUIQeŽWƒõ"D›h鼄BDc75'”Løx´Fs˜nw¸”Ä‹ÌaœÌ‚³§Øø#:M „ÏYeÿ|–«uöþPHòóÿK  ç;€ Ô òq{Ìù]@»9ßæ|P/4´§ßËm¿¯M¾ŸóQ m±b\Îro“'¸|‡÷q›£m6ñ6›cŒO_iÖNyÍ“\?ÇyÛ±ý2ÇÂÇßþ6¿¾¥FùIrÙ,Çé)~‘뙟ã»=üÌ;óÏÍþ%6ó±îÕ ½pt¤º0½yäÙ‹vÕ³þ¯wå„ ‚ð›so|ò§«ßø`y†””Ø›ÚÙû7êÏÜwòõ±òKö;ù;ÎÛ«?µüòΣཾî? ¾|hðG«Ëeÿèkï äÎ=x¹úÝŸÿ"÷ì?÷|rïÆGK·î½ ½÷«žÆ÷Õ·/Þ¿k§>Š}ÿÜoœûãµïúþëáS¿ùéà ƒ·RûOÙk,ÿ¼'ÚkŸáx¤¦8â¿p˜àöì=Âm4 a.ïâ|7×ùxo r^åv~Þƒ„óóžçÀûàs†ø†¯( Kn­¹¨©Â­×ĹW×Ïûgß½û•þ}s3µ\+NnÚKÌ>h×=Ë®¹L( ¸ùí˜sÕjÞ¹Ê vïᲠ™«Æ$¢U‚Vm­Ò(šE¡£Q+šðÁn7èŠEAYøêò©ÅÜêòétYØ=iÄãÆd<‘3¦Œc‰©#ùk©•Üò™¥³e¡sÝò´é鸑/›Íœ.™Ž I•r|z|’É$Ϫš4ç{y_çýùŽ|¨™`ë«·,Ä'6ìª9Q6k›Ö„ë¬M4R|Á=þÓe~³lÎ\5ðPK-qM>'f]­ rebar_cleaner.beamURÝŽÒ@>ý ÜzÑè‰ ë†xW!!Ùe W&µ´Ó2´!ÓvÕ Ñë}BÁ ŸÀ;_ÂGp¦[âÚäë9óÍ×žÅÕ‹€¦ŸÏ§—Óœ¥p#Ðns¼õ¸ë'Ø£˜el–o7$ ÎZÕ=£!‰´çFB²<«…ŒcÏß5S v ™‰yâѨ#DîºÓ/í†ã~XоÝG·ŽÒÝ-r’dO]Šff,À"¸nŸH ! +Hí>°ëBŽúÐ÷j68š£÷êBŠ­v?ƒâ8]m…,å¹8!å£õ$aÙÊAí~Gʧr4Xç|#Í—éAFGÀ5ª¨ ˜5µª" ÜÉ%ß’ó“üü]éó¨ú¶^iÍ*‡Ê[=bQP©¿_éšUèɷ׿n¾Æo?’ý~¶¤b´ŠZêu©¯±CNÍ$aÐÆœ3îfEšzü½˜¬ÈÂcÐñ–PÉ($†¡~R8€FAŠƒ&î‚NÎ_./ž¹›åå<†ÎØìñèÔµÏì§§gGQýÕlí.W‹«šÉ­Édd{[{_öty&šŠÁx2˜ Æ’Ós’â¹?â·§zmÏð^«l0c÷q ‡;–âaŒéž 3îËÕú—×z 6s0Ýf¹œï_PK-qM> }ÓûP rebar_config.beammVMlEžñlì“m67mhÓnºn×I¼ŽSZUÚ$¸nÚ4Ò†œµ=I6YïZ»ëRn••¨8ô’[+õ$ªJ•8"„(U'ª •P¹ nˆ oÖ“& ,=íûùÞ7ß›íúÜååBÝçgË3—fB¯‰þ!”ïõYÍò«uÏ]³×‰ËÞîé$Ú¡í‰uVëo7âr’‡ëŽW³yÍv˜k5™´éٮ쀂¶v1ß÷ü˜·g®ÇܰËñê–g¾c¹ë±\®Ëªy~H€«»å{-Ç ›3_³œ6“¹ÇsQ*jTX޳O<;À€,Œ7˜ÃB–œ&¬Æ]¡¤Õ‚>ÎU ½ªí†lù¤i]3wP=V 4Ô­ÐöÜofîµhExv·Ý[³]ÖHÚAõók^ÀâIÎNŸÔòe’‘Òª× ƒ®h¢„ϰž¦×h; –_óú8zOÜ?û/Œ;õÌ[xã{3< ãs^ƒ!$Q8+u~‹`¯ò«±Ô1„µ^„šê9ƒV–+¤3)I!Š ¨«ØÜg¨&É”VÈô 1f ¢³DÓs+tyjE7+ˆšË$¡©g^‚ˆàU“¤;|åtŒBPNS’P5“H Õ(m“ém¢uhTÝØ¦¯ÑíæƒöïáVn[Rz˜™~˜1f3ˆÌf4š{H–û¥þ H’T%¯jjù!g?Â7L]ú?¬@;HjJ¤_Jh&tÜæ’HŒ”%B#ÊŠ —𽗣§+„nP|߬h zK%S~\zN¦ŸGãaü¹Üóâ2@Í9ºh´ðSŽ^ô€Þo`Y?`¹¢ˆR%…’i°Ýv…—{µ%“¦MØ£9ÃHš2brÁº™&²ÑÒ°Lwxå4P€Ìþ’2T•TÅœ2 GRŠtQ»å—= g–?XR¡gpïòƒ°¼±ÇÚ–秦ÝV—ÔsZ6B*‰nf¨Y-÷€eð%ï+À{´Ê)C$9tZ9L{£ã5ù9ßf ]šrHÅòáqeh§Ú»ý¹)Á•Ðͤ´0dRw@bÑxŒå#±T ¸ò*‰JB{ZR4˜ax÷æä”aú…©“”J±¬AD’X7 ‡/,™Ç–u¸ßfÅ¢öøhOפbF\Îf0ÇÍÔ‡HêX>Ù,ˆ9£dÉ ÑaGõg0Ý¢*ƒäQVÖ)5‹?‚åì”r‚¼,Ÿ„î1àÌ™)žéÇòÏ@eœIMNay’ÌŸQ °Õǃ>ëU ˜ &ß¹ìéŒÄÓqÈa¹0¥LÈLAŠg”S‚`êߎS‚"–OM)“„t%ô¯òÂ|³ÅŸ¿ñ÷“Ä»ƒÅÁb(zG YäºÁ’Âïï–˜èí>Ï÷ çM‹:÷ ÷_Ùƒ?$0Ü?²‡ÿ¨À ƒîë{zG„,·§wü?~¬|=š÷˜6&êãÂG¢TøÇ…!±ÞÎ~pM‡…Ïu ]|¶"¿l@äS"&b¿RÂW‹}‰µb vÈu¾Ö¸~§¾ººÊVWÕGkO³.]{rñÑw¿YHÜšÇ_}ùSª,_I_øs¿ÿ'½’~qëÓô‹äg7¤¾\ÈöÞ™?[þøë¿ÊÙl¯Óºû‰y÷ƒ¸qsýú÷Á[-xõ«b^®'/´Á&„ÏsY¡md& }Ž×áÕX‘k®Š.nþüË÷«UTúýÍó››sóîÔp„—8>:ø^<o %úäWƒv³iùïp@Ük‡ ÛßB«Ù.Ï`{ %l·î´¬v¿¬jJήÌ/¼^½:©¼…ú&BÁ˜,«Æ)£T<µ’ߘ»R_¨žm»B rebar_core.beam…X}lבßå[ŠkJÏ^ri+þŠ×Z:vBÓZ‰´%Ù±õ$’¢-Ë2-ÑŽ;¦–äJZ‰_æ.cûŠNŠâ|iï.×"¸¦î‡{E€Ëý‘:Fs` \ \q)R·Ú¤(\÷ É%W7@ýãtfù$3éNÀˆÃyóf~ï÷ff‰8>3 ëåñÌØ±1·^rK3Ø´Šf³Pª7-ÙY¶…²Ý첚³¶@,wM«V¶æíšU–ÜfËò—­bkaM{O¥¾@P-×W_î¶ÂJÿ¼Yq¬5+_¥Ñ¬—,Ç4ÕªY+;þŠí¸N`²š¥Å`½a5M׮לîvè–kWœä/”.”{V ÖæíR³.HŽå:>»Þû«¦ëw›õ Ý+9 a`Þ®X»Øe{_¥ f³&¡-à´Cªõr«b9~/t·ÙhTì’‡ÀKjÕžXgÖ.áÞ÷ôÅbÁFÓâI$»6_ï6Ëå‚U±ªVÍínÔ—/ö¬ ñθO¨´X¯;X(Ým|÷Rà 4­Š‡Ààçºö©Ñ걸 _BÇÕ%¾+`]´J-×’ñ´5³jÉEÓñ1æ·šÍz³kÞ„¥r—]/CþFÓ®¹~³XoºJ«Q6] ˆ.[…†é.ÊààÝß$¥R/™•5µz¡´ÅaIè&㺑 T“Ô+åPÓr\¸ÜŽX÷\g]l@ VbKKu»&_°+å’Ù,¯u€¬’»Âz7ç 醣5¥ÓUµªE« |=a5«»Ùª­º›¥Òо¶Qi-Ø«K´ÍYÛØ.-³R ÌWL×µjþ¤/_‡ I·Ä?¦0^)EÏýq#î¿°h—{jõZÁºûíÚÂÖø§Ž×Ÿèذ-þg¼€ýÞz./nSüÓ Ëó­æ„Nq¬Þøjoõ!¡{z[ÚW@\Í¢â ÷)¢¶N1” MÍöeIÐ/¨ºqR? Ÿìe3{‹ÑP4©R†øt–TÖ$CaE•IDÖ4Edì +ª˜›ÔÅ9_øuEl|21^$È‹½¬ø¹™çÅ˪ø»ETñÚ$¯ûÂwñµA†_¡çñ-_øCE¼=L²6§Œ‘dzA`$* o0¢²( Eƒ°Áp4 䉄9F¤€Ð`II*# !!)‘U=Gû‰*šIúÔP4”dY…´Ëâ]–&~å×9QV’?&m×Ý4DD8‘*Ê!–ÕÈ´òœ(‡}áàf&ÊêÚËŒ%ÒLÏ3µÌˆP®tŽnêe·h¤H׋r3¹H–¡²àý„¥Ý+ 9“<žäõ«l…M—”ë1º‘Ü`e*”×)K M2’dÁí§¿5ûA´q"¨ãDÑa‹zƒ¹*Ó‰¤Ñ¾Îõ(¬GXpÇÿ³7 ŒÀî€v›•uI°àNéftRÑ 6#!ÒÜ Ò¶S^eéœhNK9º…‘tç\")­{Ìé†[´W”7( N2y!çÙ.ŒyÞ'ʽpp8pîÿ€©ãÕsPÆÝ¢|K«!/»va€Cð!ÏkeõÑLÏÑøßÎ%,Y¾2§µO{ S#«‡‘ÈEhÃ+÷·ñ0åMP½òf¨‹”Ï–aºôÌåÆP“,¥BðD„éQFòMV ª!’±õ½_”·bäÓe5”稢ª$ôV kð̉òýXØQ°á¡Cù+J+›Et´€¤XÒó$Û’t3a),_ n„qM”û†i”Œ=1B·ëûA´ƒëוh,ÐΪû;:Ùß¡ØÐH6šÕÃF#¹…­!~¨:C”£Iº°ìs˜wæ}òî¼; úü¡^ì§»‚}P”w1úJ‰òƒm-,Êy3AŽÁ¾½Ði»×Î1¦§ð£ÎâÌ–H25/t4IãäJNöW˜s‰d$,¨k^»É†¢ˆrnœEVÑ ¨Î(£ìuìýv³?éWd˜°/ FíD÷°´ŽU‘l—O( õÍhF”÷ŒJ#Ôr:ÉéWƒ#»é Ü/Êý#t¨Ð5à5£‰àSÓ Âoüøã4[“Ó úÿrušL„`;¬×`šÊຠØJn„ç€ÜÑÞR½sí«»ÞZÙ5ˆÃJVž5’k¡ðÀà¨0äÞ$ÝKXpŒ„5ˆ¼×œÐ<89sH08à÷a lcŒî#7CÀ‹f²’·kVþ„Ÿ€ðÃ#tøêäcH fzÇ‘Bmˆ³)F÷“">!Ø?$8Ö¯û1Øv èáazPC3ÆHB¶Q#™Dö6Œy3ÈQ¡>çï=nƒ…Á­KĈ!ÂÁ$=@ 1D>A‚it˜Ž“†11 Ó¡Ìá®§€’cÐâɆâ=¨ôl$»#ã”·4…›ÂV…¡>&ÊÌ{vH:¦Œb¾Q¨Ð1ü¶UÃx’BPÏÐÞ)ì‚4ÉÁRf˜fIOŽ‘Ôp Q”¼‚HéØ{$ žnh#t(=ܦ4FCyñgi: ˆI8Ç›€˜K‘•¡Í% ÍŸMÒ4i“{Óô' ý$ô:Ó#xÅ@®ÅÂÁÓO…Ù1tEw35LZ˜f³0ÍDëxhgu–’H…fD´Ó€vº³¦Û³g&ó.éÓCj ðKÒ£|HMc‡Ä3PQ¹EaÁY‹R“·Á½kPF3x5NšÇÀçøž‚ÏæS»4šåY´À¨ÉÓGH¡ÁŽx¬FÛ·yoó4>ŸOé)Q>‰·]™^y8ø)Öùí‘$%í¹÷x‰|BŠÇ’ô 4Ý]D~f-þ,"py€±wÓ³ðàð¡¤ÞÏö&Yñ& xQ>Ë{êo©Ç!ô” ÊçX3ö‰r-à9‡±À¨Éº(›`|ŒÅaZ&=ü."R{¸EwÓ žY}L1­DÚª6À^NRq[é,|Ÿ¦ ð@bÀ—Ž—šÑa@ªº×qØXXÝPÎŒ ×u!I- µ¡Pö0­|ÔƒV‘ö*Ò¾T¤Ë¢¼Ô†bCêåU°vgØJ’.bØ*R^ƒØˆ]¿÷[²}'ˆrÖLX;?Lx¨©úmªûA´qUHŒ«J 0$´ñ„0;žPJ1ڜ탩bÒÀZ.Iþ|gú&˜»À&ÊN’6ˆJaÖmæñó‘j>ÅŸ€ºV D‘AÖpJÄ×á#ðßÝ!nWA"ܾd×{;ôû@6vÄÙÄsmÙÊõm ×Wâ ®ƒD;ö>ÀuŒÿ`‡¾›ë ƒ|o$Éõ} C\Ç8ÃÜÿÈÃülx–ƒÜŽ÷Iñ³ žæqPÏvÄ?Òq®I®#WÓ<&êÇ;ΘﰟìÀöHÇyOwØOs;æ}¬#×¹Ÿ9Ô3ñ~…).þ)òµ)~ܳŽÛ×rÁ¿.hð|¨û&Zµ<Ï‡ß ü³Î÷ ]7ײַ²]¬«ýà.^üê“'þu’ (ýùàzÿ™g/Þ5ž=½þóÏ ½øÌ•ì7o÷VØWÿkŸ:ø¨Ûÿ™wÿöÀO?X:~.üáoÞ¼z©ò¥—gÞs¿öÒG±xŹýÃì—߸v‡¼ôô¾ÿóÅW'ã¯_k’ë‘k×ÿñ` ï _ýè/þîÚÛ?üù—²¯Ž=öò‰»±woþ12Öû|ü§ßühß–ïÐ×Þ(ÿdêü‰_œþò_þnßâ¶Þüզ͟‰'k—v>ó‡§ÖǺJCᅵÿ›ïþ›yõ©µÊ¾±ý͛ӯH¿µÿé…½_úÖ†ŸÜùöW6žéÿX»yáÕ_¼û݃_üÍÛO¾wöÜøµ/éë]þú¿¿÷­ýÙûÿrçꕃÁ' #‹3Oûsg?øã¨{}üî³ïüì?ßÿ¨ºüÂÍÖž…/¾ôµw¦>xï¯^9zéÂ{£Gvùçmÿc~eúï{ÒÕ/<%Œ©Ïß ª—òmj½19Ïç?Åùã\·AÎò{šy”Û‹ 3ÜŽµrŠëy®‹|}†ë9 ~^#'xOLò5Ô3 Gy‚æ:öσ}uˆëØ{{ù^ìÏ=Μ8×û@bw}¶‚Ñ}e<áÔ¼/5Eøñ/3wuðï=ýý©w~ùþ.-¥ŽÔðü{þúê ÊõÞœVµj6/¡CW½å–íæ² YE»†Ñ^v­Ti•­²pïÝà"µrYŽŸ<2•.äË, ëcp Q0ö#‰½+Nò©ÔláÈôÄñe¡{Ávµ¡¡Ã,K&|¥ –rÏОA´I®]µ»àÆï˜>“š~sÙãtê­fÉZvõ/Ö«Vÿ²U[²ûf©ß{ÙsOó^o•%a¬èà»áOPK-qM>&À—YZ À rebar_ct.beammW tåžÙvw²dÂìÎæ!»„À’dò $„ ÉfHx‚Ú\ö1ÙL²»“ÎÎ‚Š ­ç`´bA=°(âÁŠJ£r°P›ªœžZÛC}+¨P¬ïÖ¦V ÇGíýg†²¢9çfïÿÏ}|ÿ½ßýw§gÕšz‚`- v®èÔÕ$AØî'¢ÖäHX Eu[Tç´L*¤Ëi=¤ †F59-§tç ’JÄ¡¤C1E³†i™ÒµŒLm k©Ó=¡ÆˆM¡/Æpn”µˆš–s­jjP‰»â²Š'ÔH8áµD8·HNmœfZet%‘¶¥‡r¢ Ù ë’SéŒ&¹eMS5»>¤©›œ)uS(­k†çÚ¤)ºÂjNtHŽŽ`G*K˜c «@<$kóTò$/r>q¢D ‡$›§A Å\A}”ÈyEäw²„A Q¦PŒ¬Ódr5ËA¿Í'J,7&âO‘S`Åqä!8rƒèåDÊ'ú‘]¸[ Gû¹ÕæyV wä <Ä¢x¦¬õ$j;‰ø%ˆ – ‰ÈK±ïˆω/!'Ï"‰%½°Ø­l0‡G(˜ÓaþóÁÒ^\ûSä~œN±lGD ±<öÚÏöð>IZ-yƒ>›¯‡o”\Él´qn¯“ÁÐÎ2ON,Eä)›Ç•Ï’çrYVD”(m@Nvuëg¨q09€é 0nÎUÈòŽ'J£ÜKˆ®BãìÒVD³rŒÐ¸“¥œ‰I”ö[è l„“ß`X4Ž‹E³œvCh@(cIšËƒpØë9?v”& ’ØÊœ‚l8ܸ(âD\ 8ÒŽiöýˆôçÌÂÁú"Q€ñR´E±L‘(Mr"à¿ 8í 0ùè[v4û½†ù¸ù^ ¤Ýˆæ'’.À§(„øàEV à˜Èê,SŒ[kÖ=ÕÊ”À™J²ÏT›ÆÞŽ)‹1·X(W NT ‰fñ$]–7 ÔíQÌIœk êvò“"j‚U>'vCÊI'K?ìX;¸X@h†F3|¡¨1åfI—ƒM!.æ‡Ù9ºÈj];SAÒ3àL$]3á$h7œ><"Ź) u˳A?Bn?TO×bèÍáé!h/.HÌÊÌ " 6›)/ˆ+Ýþ1vx–€À Dä›°›èëv7A–J|¸~)já¦Öˆ¡ö[úaÑ™(‚é¸H·ÕÖQº‘»;‹…¢¥gÖÐ W¯Ô0X W€Aâ$J‚ fxÌיЅèBe. ] Ä0¥‘s t¡ÀÌÆ•+ë‹0U$í‹¢wL#D.RuApçjº¨…ñ£NÄùš˜Y>–Ça‚-ºœ]Íí(Ü…À¨åC„égZU˜hڌۇž…Û€ öðàEƒ[~ˆÏÆÀ«x Ÿ“kd4Ø@—€”š-Ÿ‰«_&0óð!æÁÇÌÕ˜IÏ5xO!‘¢¥ÌÃ!k ä"HT›Ô—èJÎ`1˦ǩÇŨ‹00,uæ™|Ö™L^=ŽÕ±:`¿ÑŒåÿV¬f«ÇjŠ0óIºÉŒ5ËŠ5ÿR¬fkÄZ û-y<‹éâ¡®æ ¶"—hÜtö†‚´‚>›Ã¹²¹aŽ N¾'_„ Ò¦1 IºíR'ª¹1þ;w!½ÐŒ?ÇŠ¿CjHKàYG.A˜xºL<‹1«‰‹ÍNÌÅŽ`+‚O7|vŠ´’¥aT—à8X6„Mž†ñì†ÍÈtðÌ’î¥6R ³1@ `ä jŒ 3‡8€'ó¦Ñ(ÞÒ&¦¾Lè^±"öµ0+P®Àw"Ÿ†@ôá*·3dV⺬ÄMYa–“ô2Ü/²Ãí^n®Æxöâ%q1ËŠ&¦gY)ºú bôLÄZ]ëÇ_Ò½ÉQø$÷‚Z BØAHXy ÓAlÖ÷»ÛÒ9¯¥cßËÛY:¶)¶~”€”Zöå 3²bVd鼥ϴpÙ,_VÌ*+æljËës,›¹ Ëëó,½<˾¤ÖÚ¯ËÊ%€Ô[qðÙ›¬:à3ηj„1,ÈÊÛjÙc½ÍÒqœ…YõiϪOð2ýbÞÞ¬:b›àµ¸GfŒ¡Ûòë²tü×iùÒ“Iaû2Ë®ÇÚZ¶„ãêG—+:ØØà÷šºvoríÙU\'Û1¬æ‹¾r/÷ïÚF׿‘SõÌ… ·¯æXt¾ëù/·xàɆ©Óÿõl/ìë¿o¶ë¥{×l?}îèÄú¶ž#Ûö?û›–Îñ›cÿ§{NÜu—Ëv"ïÂM¿=óÑ/öm¹õpßÏßxdMþ'Róç/»F“o=üØ#•{÷\=ç„ò*ö5·â«÷7žð×( Ž7xåY?{úަñ{Ç·ßûűâ×´óŠyg&wí¼{Ûš^ç᱕×vlùðóãNò‹üwg¬8Ù7xà›²Ñ·ßª œ?pæ©]è½ië7¿_tÛ ø×¡ö“ïïûæÉŸ?w—¿<ðF~UÇ+òº‰•‘/ß\¿óÕÅRfª¯÷¥Ý~a ½‡?¼oýúÃeè Ñ|}ôÆçÞ>W Lì.-ÜôâM¿¿ê¦ÀºeòËÚØ€¿Óš©|¡`ˆâ”ÀýÊ‚Ý낻ىЇÕS¨ùô;G›f8r>*î¹eë¡_Ú1·~ß›ï¶O‰õèËÇò^¼òµç§ŸÛNU»ž<_…¸ºÜóúBËö´úþsãÖãDÅ–Wžš[í¢ï9ô´ra[iõckÚÝñºÏÊwI§v\}ö|Þýá êׇ¡’å?<õÆÞ¸­î¯W-}nwjæ5ï-“Ÿ¾â9Í;õ“ô×?¸Áþì½öÀá¯ûJ'\}‰¢OŸ¹oêxñÀíêá+ï¹Ps®âçºÍ?^[xÛ_Ú^,¨}°³îø…kŽMÿ˜X®F1÷Žæ}±Ôâ^ˆdñQºŒ“K,Zv€,¶lZ¬5ÖAYz­õÌfÍyƒ¥ã¹eé˜÷>˾(kð¼ægÍt®5O9Ö§1ߺ®áY»9-‡l1mL§ŒEŠ%†o-ø÷2ÏŸWÿÎ~KÍä× wõ¦áá׆=…íꨮ¨©4ÞpÄÆx†·d2¬]‡ jF‡×Á‚’#J ïÊáTRÑD&&LjK¯wCžÅb„kɺÞåÝ¡þÞÁbzƒP_/4Ô7†„ùBkãü‹Fô]kC½+{VÓâŠÎ/XP/„#° ^øÒj„°7Õ.¨mÀ{”®$å!GÞÚ΄ma&lç„s €i5£E墪nHMÊu#rjX©KkÑ:ãíÿ’/¯µ²–ÆP$­ã&þPK-qM>Î¥Hxàü"rebar_deps.beam¼X{|U¾ÏôLÛ!í)“N ”ç”I Z†&…¦<œ&Mƒò m}…6M¦%6MB’P^¾ÑUìâ\QT_ àúèÝeå®úñâ⪻º>®Ëòq? >ÖÇ^õþ~3“6EV¯ÿÜ~>§sæœßãû{ž3©_Ø0Õdÿ¹Û[;¿6ë2™ØC&“)eN¨mDKH'Íñ„OÄ‚j2Éá{K(œÈ×·ƒ±h{¸ÃÜ¡¦Z:"±¶@„E‚!ø‰áµ= e‡Ô¶îŽ!:G$ÖA`d·"IuH²3×tdGÂÉT2·=–PÁY±Î¼x,™2´æ¨‰H ÚA@ìîhH¡j([M’jn0ÖGTsp…ì,×D¥V$b«8 Ö^I¼;•×Rªö΂†P^H¨Æ‚ìGß’6Ï<°–Ƥ׹6ЩMÚAi4Ð¥²—ÅÂÑaº|, ©-ñ@jW6•èVs‘8n3«ÑdwBãg‘jH Ò(`L"–‚ÞÒ„ä&Ô5‘T³=p$·+œL†£yº »SáH2aW…²m±DŠ ƒz¬8˜Ö¥FSfÝF\Î kèÙp´=ÆëB’.);ÑÕ’h–PWv‡\2Öª-j´¼Ìc oÑ`Ú"j.˜¢†êRpOb6Ñ5øD×äâ¤'ÍJ¨$ÑÍÆº©àŠlí?»*ˆrêê¸L©!²"äÑâp,ÚÖj$…ô¿ñ†45ˆÞÜL£Í Çr u€Ž)Š­ŠFb±G:Â)’ì‰f­è m—'rÚhpI:´`¢Žœp¬ìÊmR)5š FàrV0”•\AØêÒr ç ƒÜ¤û§ ìj F°­™m·SÌê–T¬%Õ¨E†‹٠¡ZØÕÕj°;…>Îg´ôµå´BDG^W,Ô ÃÅÈg¼.,nŠ£<´-—§L-—ˇ¦„£)µCM—gdþ”Ê Ê¨òöðêâòŒZ1¦ÁÔòsíè¬ÃËÓÅ6ˆáË:µµ| Va£½; ‹#ÊšÌYÔƒ6tjsºû$TNo!á4-Ô”É4l Ly“þ· Æ30Ê>«p¼Èˆ"¯«’%(•$W4)DP¬„i‘Ò&(Y¼X¬¹2ëWáºÍå%5^"ò"ï&&ÖMx«—:ŸIP¶\6L^+.ð‚Ū/),ay:Zé”ã¨Ä^E|b‡Ia…\QfdØÞ$š€âI^æëEÁgæ}DH¡I`”9„ñgš-"ÓZÀ›ÌÙJ!±w³Uñɤ˜¸BXXËåý¼lª 2³¸±¸†‹LoŽxˆÙ ó"‘ÙWÀóhS›0Ø¢¤æÁÁù;A1óšàçíàã&Þ0ŸB8¾Õļz!aÞyÅ"s:ßtNy”'50P"þ8ŒGq`ŠqM>XÆñ`gI£D†+<[”y´& X÷Àxà‡ìpŽNk>EXÖDG*ÄaD%Šƒ= Ô05 A™ˆn,ïè7 Ñ ™cAf‘“Ž‘Ï/)•iH•„7šn2K1P‹ð>ƒ d.Ñ3ˆ¶Œtb­—g¸Q@nƒçèj:Ž@ÚÕArÑñB ¿[0·À;Ü‚èq r£Ž'æRE²*‚âQ$–•é\-;J4;™–3ZR¤˜Ëè˜>:–áÆ(¾VÔiasÅ^ÅÌrùv*3¯oñû´·2† ž É VsÒQİMDw”@¨¹ñŠo#Dþy À‚Éð´ÉT"3•Š”«h©y49¥Š¯WÊ‘éD†+ƒè³ È 3ÜD™Ú‘ÁŽ çÃ$†;ÏIí‚‹Ú¥b>/»%pĸWu·AÂܨ V/ HLnr*YÀ¿Êpöj:A¨™Nvð­þz¹ÑçðùvúÌVo£GÐqLvQ‡c¦ƒ:Š‘–Ë´‚áÊÝS£ÛÁeêhä[ãõ²Ã×è "›#ÍVA[[ýi:·CL*R“BêS Ú”Fk½Ÿõ™KEãL*AAiÄd›ã¢U¤*=HP’L«0PUZ ¦ôQðÉEr(¬¤˜+¥É£ÔÅÙ´IY?®X!j˜ÄÙü-cr»¨“­áw³ “%;u ˜"Ú¦qX!Kl«ž'?aj­d¸©vZ%Ù„ÍñÁQ™&ò“¤Ž|^Á4½Ë+¼—d/ 1õíƒZ8 5à4’ª•áª0ɦA¢8ü 7]¦Ó0Q¦a¢TC¢Ì`¸jXCä°f® .óZÃp.æ© Üïö@ˆ<|ÐEgB6Í”ü˜Jv:S« ­|JˆÒÈ*AèäÒKX{¥à³ŠQ5?[Z…øŸ%Íê4i3 x¿‹ÎæYiæYƒ˜=¬Æ)"§žÒ3Šl–1/ͯTÁó|õ@0=ÄŸ¦z öP4PXà]—âéªmáéºkÆJ [ÁýKúkk)O3FcÙ@\aXahqÑåpX.ÈpÒ·™.—fHtyÑF³Ÿ¶šѹªæFÚÎp­.„¾ôˆé¦%Ó`ãŒF„o¢óE´áù²vKtX!Ôý"Ñ™nÏV‚9éãŠÐï£`g4P£=®^”|æ%>¢¥‚v'¹±˜„¶,È?àÑÏ7@Í"5„Pómÿ ŠDûµå&Ÿ§^†:ñÃ]A‚bha¸P¾ìG€HÛlÕb k 5u#3`Ú´[<.¤xœ §þ¨ %­B·eÔYÂÏ%ÙF,¶´¬YºïFÿ„Ú¾c~¦˜å+ «›á%\ @têW˜.g ¿Û …ç%·SqØi—`ŽÚI öæesã,V /6¨ô›eÁ¦ÑN·Ëúh'Ã]†MÚᱱz˰j-[ •yàŽ)Æ1Û‰Žrjmsœ{F×LoG°0»ŒÂT.Š&@aÆ\4 …=»0£X˜Q­0ãP˜)(Ìn(̆‹»h 3™Y˜I,̤V˜+¡0 ·’Šþ8ÜJy¦ÉÙa¨/8UÑÏ€+ñoùK~À_|þä¿+‡Ã¥(/bžx=ZïÿcYQîL.ýyÏ`rÛO¯‚@,‡çj]­{‘±uCË^Îo k k kÀùknM¾,âõÒ ®ø y=&¼v”\9‘^_æ2R(CÄ/ßÄ‹zÂ\‰©w%¯U’¼DBT¥ØôÁMW€ö¨œµvºŽô×:íâŸUœdeúÚE7² ™·— Ö•–Ä>n‚dÁ[_‘‹®ºõ™tësˆ»ànVv®WúôŒÜ€•„_òm°z¥L7bl£éU`ðÕ`ø5à€kî*Ð1¿Ü®†Éy8¹&“pr-Lì8¹ A×Ëô:tZD7€@Ð ô ·)ßd†ÉØàÛ+Çj©à ·¾uoÐw§¤wåA»7ê»SÓ»•ƒv¡ï:Ò»ÎA»7¸xJý6w›n3€û%€Ûàne¸Íù/ýYÕÿa‹7ŠÛ‘ãv<¿oþÐËp·É4­à¯½àW èèÕœúË|“!dº0°·¥µ:cõÖþUWÆêm˜@ éöô6ªöuªßÚïCÚh«R‡>'1Ü6\;õ_1ˆœá~‹+`ñ®jz7ÉçùZ¢ÝrKû¿}1ð%z.Üí¤¿B¥Ûñ2pÔŽjz/)ÅZ"9\t|nìÒ?7à#Úc§»ð“{ãØ•ð¨(“é}è«ûÐW÷€¯v2Ü=˜¤pIéÈòÚ©ÊÏ´|¯“nGí÷aÜeôHX¿ÐDÀŒªéƒ¤€7~ÕØ ír÷À¯vº[ûÂ_eðלL³tÒûQðîïž_ƒÌ.x]àC ð!M`ç÷vúPç÷æR7œ“éC³ËQÐ~ ái8Ó{2=ús`ávÒ_£ÊG@Oôöòîî7;Ïtv¸Ï¿ebý…£góª§&ïÏ{广†—]þŸÍ£üôäŸx¢M¯ï¸¦3öÆì=§— lXtäèÆèü°÷µ i[Qß§ÅÅ£>øëÉë6Ü¿¹rŽðÍ+Ï1·¬}{þØ}B½ùÆÕ¾o6/Yýܾܷþ_Ÿìy%±ûëmOùßÙÚqüôö&û„û?=öÕw3ÿ2ßDÇž^ùÁSÇÿrO[û Öfõùöz®ŸµuÎ-#Û–¾½í¶ÕÑÏïÝûÜ‹cŠ¿Û6C:V¶;ùÅã{&m:yÉÜ¡¿Éùüý÷Ý5{RÝÈßÿ}Þæ{Ï,úŸ²eW¾Å=|âæ—?²õ]RvüÌA÷º¯_]ȬW¢äéâÞ«Ž7H‡Þ³ü©~Ao\¾ô©ŠbÖvSïö=¥¿­{gSŒùþÀ¶Ôªõ®ì òQ¥öwýý±›7Œ˜=ÍýÀï6Mß]æoÏ]|ê¼}î™»øOc;]ÿñù‰+ž]ØÒ²þŸ·{vrýí¾¥ùvßÎÒ#ÿ¸õÇÞ;¾múçj7¬»w\Áömod.<}çôîüƒ»Ü UKŽ]ÿòâß,|äæG^;ÿêïNM™'´d*†Ö|üþµw[G ßþä‹Gmßr¨ë­ï¯ùâÔ×_,.­ê\5$vìÈÉqïÜùðÃ?z¾=züÅÃùoŸêéÙSúÖÞŠOÞñ.ºHÊÿrâÖœŠÈ£[^_óQòÕÿ%<"\òÛ£îæ–MöÚÉoNºð€sÜП½åzñã¡[Ng¯²zÜ¡ÿÿÿE‘MhA†'ÿVÍ­ Uƒˆ “MÒj%ÖjC«E›Æƒâº›™6»›³›øƒREÑz¡x+BA‚¤âÕƒ jª"^Dë¥P¿‰Ÿ¸ðÀ³ï¼ß2|k¿þ^ܵ³]Y]ÞýáârréÛlòð¹¹Óqþ<6|yáq ýâSß—›ú2?ã7ï÷ŽÎÇÊýטïŽ<önr±­¿Z]¸2û»õõ×½µmÛ{Þ< dÜ©– ñ$„làž§Ð—€úSÀApôG€þ¨£/&àî5Ìïó€Šù5@G¿„y8œÀü pgt™Àærn ½Œ.;G€AüæºìŒ{°3äч€ @gèrv"û½@œü}6[±ÓSô<¹ÛÄåÎfj~J-—w^xŒ\ý¼2·’›ŒÞz»0!nWLs¸Ä§áp­ÓÊ~Äix†Ã]„)‰2!¡ºMÛÖÄYY;MÂ"A¦\&>Ã"ƒWëMÊ(éjrʦ Îh-g”’õ{§JãûÔréàˆEº³J&£d39UÉ+¹ü¿ÒºÊð¤Z:´Â"f /^(dMWÌÎZL¸p)‹„úS…TVfAϰY- 1ò^ókQ-¤ui;t¦¨2‹$Ò5Çfi‹qÓH»¢šL×ÄS)k¸)&ê&)ê®'—ùPK-qM>HRòƒˆ rebar_dialyzer.beamuWl׿ó;ÇgÇ—\òB ¤NÁ8±c‡ü#í%Áñè(ÑŠ¶š³}±/±ï¼ó9:Z@Û” ÚnS» ¡õÏTm¢í:­ÛЀ©í˜ºŠ?¢ ºª…I[›QQ:´±}ï|Im–>Ý÷~ï{ß÷ûþÜéy`íú E¹wôEzè5´,EÙ2EÝW¦ËqI%)3ñ°¬;,…Ø\ƈ)êˆf—u]ÓmÚ˜K—¥dÌ\9U͈K%éVµX¾HÇF”Œ\ZôY0”LÞ.Å5ÝàfÜÅ´œ‘w÷š:¢¤PJ6P^O8sº–Ë(y#Ï‹kZ†1ô‚l‘2y™UTňv‹¤«ŠšÊÛ“r¼r]e´"¢T»‘Öµ-e³‹Dã%“ôÃùòâ)—+ò㉒Q’¡hjÞ¥Œ\ÁŒå$Éäcºœ`Hœ‰´œ#NlŠV2¢éYÉ`Éñ¤¢çË­c³ôÌT`%K‰´[•·±œd¤Í3ª”•‰A’…dgAMÊ#Š*'mZ¾`Y/‘õŒ¤¦Üt,fh1âÔæó±„ñÀŒjŠZ!o‚ÎFpýŒw)„}ª‘ôÒ¬–,dd³•å$æmëÿ]ä[‚þ‘‚êøËŠYÎlÌñϤ ™DýCAxýLBKʈG¶þË&Ï€¿L(ÊÞ 3ÇSÅ™¿NŽæm•‹Z(yóŠˆqðT'Ç£.¡Q¸ñÞÇãnÌñÕâú¶xÀÚÛí…õf=òØÆ2-òal¸‚©ðˆQ 9¾ç:=xÊ[èæ;PÁBsâ ,Ú¼¢9À‹×`ƒB݈vUîvá'é|ŽPÔå‰2 àHTĨçYzòŽ àƒчˆ'±§‚axÎ~Á²çuú?È8ꪊ¢ö ú/ðP„ˆ8D7cÑ5ˆˆiæØWxü BÔÓS£Œï rÍ뼂»®`¡S¡>Ì÷û®„\óya0ÒoÃb4g¥5•ñbzZŒ£JÓ,?¢Ù [¥«V ÙJRvLÊ.̲tð›yx0P ñ à²c†‹È 3‰ZþX‘ú=QOÛð€àºHË!ëIŒ€l˜Ãˆ”ÙÌæ†B»=œ‡faIR¡YÏ ¯* ƒÀÎJd Òn.Ÿ#<î,éÓ¹â sÕÈê¢=©æz¸y4[=‹šÅæŽz|\ )Wƒ»@Ì‚dVË2çgÍkH½Øy3Äæ±žfkÝœCvž[NÑ쀮só„dŠÌ ;¹vš ÁÍCU‘žQÈš.‰!Æ0—¢òq ‘Ë/F§ÀðÁÃKpLŒNc‡p Æ"âl6qV˜‚ +y ¶â´Aoñݹ;43ä1ã0³®!ºTô2·ƒ«G½{}Üì|¤ƒ[âíõ†úar¶ˆýV8P!XœÂÿÁÊ!L?àšÈ»ÒDޮх¹šm£,ÍÉãÿ×r1Í6B³ä‹EÒ¶âó‰ 6‘Á] 9WA|Ð ’ä lUtWb,½YVðô‹•h ÏVÐl3Aà\ ±P`+i6`€ApæàYL2BfäJˆœ­`±,B\A£{ù8ÁÐÎ4‰ 9Æ dö$æZ<Ûàà}ppy×aÖ¸kÇn>M÷› ˜ºÝÍòÛÝ´‹^TÍv„¹6„5dèȇsU6Oš¨U „¡Š€ ¤ÄF¾« eÖ>ùæVXx5È\ 'Rc]Rgé^zË~1ÈK'6K-âs™…7ƒ´Xx$x›ÞjÙ„@–¾¤ý.?Ȳï¼íl§eOöº-¼ä^¢G¶’:P"ˆ¤ÃÚo±tòóƒ,²|Ì©µôJëiÊ@AÝ`í‘ó]Ö3hù P´áýÕŠAj¾Ì_ÝúÌöõÇïGAÏÞM+Ë«–>txÝŠ —.$ÖMúÙ×~èÌåsoŒœL¾xýHõ¿ïŒ]ýüÅ=/luîÿî…‰ƒ'[ßødn"ª OoþôsÞ•¥u¯í:þ7~thþáµ_¿·vMîQû ½w_àƒM'Õám“—þõtߦ/¦§#»ÿ°ûÑ:¾öæK×V®|é³ò›aO<ÕÐÞšýɾ‡‡m¯¬¬©ª:ò§¥=Ì­·¶Ç·þpgß®}°îAÔðƒþËC»v„N„ŸøÝ†Šß,zïôÓÏå³/7?˜øk¶éÂðôa~øÒÐsø•žáyýZ—üûÙÉÆÓo~õ,WÛtðÓí¿øÊÕ=úÛ±Ó7¾äþöà/µå›ßXpm[ïÇ-ïýãň×hxrb×Kç.Þûü7º«›týõÏOäοV¶Ôóå' ¦"êþúTòݺæ«{/lÊ!oýÙ=]Kž¢o1öœýõû¯éßKwˆ¾Õ˜]ÿÌ?oáG^¸vT»¹å|ø£3\vùåï?öÎ}X~$2õöÑ߿ӹ퓋õÆÑ2ßù 7wŒŸ¹ ½Y­%Hï’ ,¹ÏZ½#óµÂÒCwõ´ÊÒ} mÖ yo²t¤Ñ²!ïCƒ¥×ö†NÞ‡äæB§mI çUs¡–SôoðÝúóÏÛ¦²òo}4:Jõ¯RG`™ö ±wÀõ—\2 P’¤8ór çlVÒ'ˆA ÜÄàî4F1r\Q B+c”CQ™BRNRŸ]Óö’IÊÕ·qÕꕱ «ˆŒQå­`0Ð ÅmÎPÛŒ;Ü?[µf`íUšR ¡½=âQ“Ó¸¬çÔe7·7·Œ1”¬œ.‰S”ã]É&q’]rJn“`^+è yŒZÖ’Ö²r˘¬Ž*-po1/ÖŸi³)šá;JõÆóy—þPK-qM> Ãf4rebar_edoc.beamM’MOÛ0ÇŸÄ¡¥´QsÚ­; !Ñ”R!8¹íʨÆËl§Ii;­›WŽƒØiâ¾ëû h_b;ìÄmf³C«駦Â1l¨rebar_erlc_compiler.beamY pÕ}ß½]éÖ+=kïöü-Áš=°|ÖJwF’?`ugù¿ÍÙöyµ·º;ë¾¼wg[| Æ0æÃahë†É„Ìd¨3Œ;$aRЧm !¡I›Nè¤i'¥¦L¦LoïI^›Ò©fÞíÿýßÿëýÿ¿÷{ºÍ;oê縞³ÉÑ‘í#j™ãÚ»9Ž{TuqËÍ:nÉÎÚÕr­XrÜ #ºŽ¹¥ìDÑ­7ðYrê-Y»Z™(æçåF¶Tµ­31nÕ9‚Û¬tM]ªÞU.Žûçmvɱ*m¥b½QNT]Dz -[ÍF±T—'Š•\KTi±)ÝZëÈ9%§ád©N :9?Wm` ³î»œK=K^¬ð#Ñ…j­QÀ‘sÎx3Ÿ-V&ª2È—ªãV©ÍãÎk9,Uó†TwílöæÕÜjÍ ˜XµšƒðŽX¥¦So‡]«’ôö¶MTK¹’DÝV¬²#ª+A:+Çe§Roºµ$ÚÕœã…U³ÉÊå•YÝš[¬ºÅÆ”Œ dsÕ\Þq[~.DòÓȹFMb¶n„ÆmxŽÍÇ‚"]3L¶!ƒÛüÛF¶Íë¨[€²­¼´ØÍ?‘?K+ P%ã,lé] Ò6šží0œE(;†È͸*õø0Ù«oÐÉÞE¦Avšä&^Ú‰~Œ^¬ kèÅ{SòÁN£ffè]eÚ3NÏÛ ƒÜB+t‹W¡]¨Ðn^Ú¥ìâ¼ó>NÏ»H¯YdwJ³ÛôÏnò{@ǯ3/æ4óRGošñÄeàh/e”ƒÜfÃse®žquéŸíÅÅ;ªã%.´ƒÃK7'ÈvZg”a%/ÝBsòä$‡TíkWHŽ—nÅÔÁô¶VÅÃ*ƒ 1@ Ir;âØÏK·Ó÷1€—©H®…Ê~TÐËõj7 C”ÿ ¦îzyÉ¢ÈSü€©I«yÉó˜¹!âð ÄŠÀØms/˜äh›…–q'Al É (N"ùaR: ‚ tÄŽTR02½¤—KøLɃÈ@ c$3œÌ(õdFÃåU°½¥:–êf²ÎNÖ•“uã,öt_”Ëø|E® ‘ÂÌÈÌ…w!~âÌäîWÉ Ê§É F‡™_yòŸÊUHt(ë臑ìP¸Ž>•Ž0>µ"!¹Jª\K»´u„õÆ9^*´Î_û: Œ&eì«ìíKǾ°7#ÕKÊ:õUŽË.RHÉ—I¦;™Ò¦rÆ[Â]]¶MÜÕ3¸«O'mãE,Íxº§å²AÊ/®‘”QÓ:™”¤ÄK“ÐB6Ê^6^A6. ïBþOë‚ÜÄç»Ë¡Aã,ý¿¤q‰¡ÒåÖæ*ØÜQT»ÚB×ÅWov3øô%ûž‡‡HýËC}ÓS¤˜Aš…M….PXç%—j¢Ë ]õVcƒÅÃ~´4¤F7)$Àú=J_H½WÏ¥mÒšYÙcX¾ Χ†È³PdoNsPœò¿#AŽQãwBñn(Þ5Dîþ2Å»üŠw'ÈTñ(Þƒszo»I–óÒ4¦÷"¾û†È´:¢êq<ã#ñTÏÌHÆ®'Èt½Ó¬ÑNœòš„ž€é1ƒ<@SóRs„Ü‚ÎðÒýÊ47Å;®QG‘ûÑ„Úz˜™]ˆ€)&tô‡ÖÂtAŒ £[œÕxaM#¬ãCäa¡Ó˜»Tðšä]V'©ó“^‡zµ9ÁKµÞÉQÔã8¡'Z³šB¿µøóðp‚ƒç©!òøl²ñ…€¾{õà›…„ïvR?Æ€?û§ü^OǨ×'`é,=ÙÉÑk&ÞKžÂ[ýò"=E_CNcý$"zºÝ h_Ï`ú¦Ïbšà¥ç0}Ó3˜\¦áî¡_ ÇÊ5< £ CÀhDzÑщÀ óÝž‹óL7Ât)½ÐG/fòK1–1~ÆŒ%†Æhêk9“¹ Cgü(ÆÕÌ×5+Øÿ(½’ñgcÿZƧvV3šú]ÃlR¾Áè~Œ½–ÉÓØ†½Î•ÙÀø4¶ëMã¿ÉPùŸ/ÉÐùzß~G}¼Í>¿72šøö¾•ÉÎæä+ŒOuoeôíû}º–/6Ûó„O&ï«EÑCÑçkÊÇ¿Ó'gü0dµ£üã>ù‡M1ó0¥GQìqÛXÝ l}œÑôï F˜Ù“`ò2£E_>››Øä;Ù^eºg˜=®ýä3€Ç#Œÿ,óɉ š?Àã$ã?Íìqü/^z›kýŸ‰Ê=ÉÖ¹À9ƒÇýŒÿ(‹ƒkûå9šß{™þ}\ëüèŸö¯ø½öã‘ã§¢ËûËÆŸ×÷?þä Ÿ¾±ôû½Gþ¦¯ñßÏo}íÖØ›‰¿>ßyùÍ…c«¢oô¿ñ“ÒËáU¯þè;on[¾èÙØÑyá»·‰ï ?[óø÷ßÚ™:gö¶ ûþño×ÜúÑï¾ûòK/Çο½6œ}yÙg»ýÛÜ‚þðô¦Á5?ÿë­½O~ôÃÞ?ú´GœÜ·ÿ§kògÎ¥Ÿ{êóÆ…Co»÷µÆ÷>~ø`òzþå¯â3{¿3°aï_¾ô¯ÿùðíoq‘÷møüW.|þÔN ÚªMsú×:×~œù±åÇ“C3Œ>u†¦Y]_†!?nîfòw±Aé©Ë0tŒñ_†!?nüX9Ädr£ocsJïÃÈ2ÝlòÇØåÓ¾u ãoÂèf4í73Ú#÷²½\‡±›Å@ïžíŒ`v)Ý‹a2yz'lä.ö–ÙûŠÞ9}ÜÅû¨—Ñd¤Ñpñ\9S¢‘9N8R¯x“ŠÂ]}⇷žÎÍû³ÆÂÅÛÇ®€CÔ ˜ rebar_erlydtl_compiler.beamuW}pÓæ—üʶâXD¶ á#!*6Ÿ‰Ùq |”¾ qL„,PºöÖÅ’%¶äI2_ƒ^î k¸•Ž­£ÝzlMáVv£¬£ô8Ö·•­t[JÙ:nWÊØÝhïÆÊnÝí¶îëye\zMî‰=ïóüÞßóñ*RïæÁEq‡»Ó]›ºl£HQž)Š¢ÖÏ2Õ!Ù̪fa·b²9£XÒ ªéwV1rYÓ0ì€e”ÍœšUwÙ~£lgÍ  ¥\pL>ˆ—õaOs³PÁ’-õ2Ëzpz£d[ÁŠSÎÐóÚ0VmX5C¯)™F© Y¶UÆì¹PVýŠš—Ë».W¶€wÖ–‡-²{­‹žP¿ Îä EõîÑr#AÝÐ`iÀK3|yÃ,ʶ×1Œm–Uo^.XªßÓJ%U (Æ4_1V릦ËE•̓ÍQHRDñÁý°=BÇ}–m¼Ï*ÆéªªXÓ(~VІ¸‚lÙYÀÓòšªxì¬ï®3Õ¼jªzNUH c©° «;keEɪµ¨êv­¢¦u¿mdI4G`Âcª~S-äœê“!]©É›P)âÌ5Û”s6ci{ToY‡*O'§éy£ŽÔ¹ê~~üNô¶öx!ûR²-OÆš•5ÕárA6?Ó3ž‰83jhúgúHà#Åýù‚lÛª^[‡²­,5âUMÓ0}¶1¦êV}üU…ø|Y‡XzM(>mKº¶uÐ}Šò¶Ã\óTågd%Hˆæ=á"-Îà1êaø4FN",¤QÅ(†SîFŽ!ú`E}á¨ã–¡¿HaÄ S8µGÚ1³Ç¢å°GÀÞÂ=ˆçhÉ~‰§1öDñKB¿$Òžð5‘ÞE,0°Ã?ŒàG+CÉ„xz\*£Õ¨\?™<2øý¡—»/¿¡㌈zg$¸œÂàNŸÇ™¸Laü½ Ñ‚Dß JÉ%Æ "~7s< Ô¿ ‰Â™íÈ/àL ±üvŠfy0Å1ÄHÜ\‰`sN¨Çy\(ÐÀ…i6tËÃ+q3%š ã@# KÍ ÍF`çù`ž9c¶îÁQ§¤•ò‚sK#Õvt†è0¹áoò½¢ „3(-dÆ…^1šIf˜tTpÔÁLTh 1!åfc”"ÑŠ„b¤)RÃP êî—JÍÜ,h ·Y<æÓȃÒ=H˜€Ä2ñz -ò4;;Hñ~~|¯—?Œ„}^qRø|‡V:NsÀi1ä6ÊbHa¨+õ¼“e17AP®JEæa óNWXÇÑØ„È3"×HªÁ Vœ‚-µE¤ÙÆ[Ãà§®‡P¼É‹|:âi¯ ÇÏãvÒš¦ ÀOùE–‡ßЛ@I ×ĽˆC/5rëß õgœ¹ŒâÌ©vœ9/ø1tUJÌÚü<+PF·C·V[ æ‹Àƒ´6žI¸òì¬fND4äƳHx!’µÓ'kÜëIÀÊÑi‚Œï«€øFý<;›f£Ä5‰‘MÁ(²shv!×€qQ'·E¾ !¦²3Lè22¡Ë`B¸Å0¥Khv1ÙxÂKœñ„5©#ƒP˜ŠKSÜB8$ì22°Í€¾|[:¹8âD,v!稤£žhZˆ’\æ¹dH· T¢/žâš ^+@a€jëäÚj¼ ¥3S†EÓ™«hÎÜ$El\É¥Ð*±QB7⣗V \ ’jâ¤@— Y gX^€Óóïæ’4›€ƒN³ÉOSk«¦ÖžâZ µIµøõ¿åAžLŒk­—mšv]«ëa|:}ÒßµÅ6·’f_±Wú¨"ˆ„ñ€Ô€Üû ‚@êÜç-Ñg‚Ì¡AfƒÌqc Î\×qmÄÿ.®øD«ô˜ë·d‘ë¿d©ë³ ¤Ùõ‰ƒ´ºÏ|¢·UÙ¥*=áÆ’ÿ)ÆÅépíÄgy•¾¢*¶³Ê¾²*¯ÕUœW»vÂón×Nr¼§Šs—«wƒ¬«Ê1]…™!zzé…ƒEr_åÆÅ\rkç™–Þ²¾Õ͋ܯwã:]_Êÿí3$®×]ŸÎ“¦Þzdj£f“¾ë°tp×Ñïþ¨ÿg_=OÕðß8€=±ðŸ6l´¥+²àÄk‹ž}¬ñrý3­÷ÿëG¼Ø¨ŸúÞÓû~ýá_Zt Ý ú¶¡£G–Ì»òÅbðÅã{6|<}èk÷ÊÊä±/o8ø×Á§Æ³{zsé#6Åäíׯîky¹±ôÌÁÎÏí²ÏÝè…¯|üÑ+ïÇrvFË19Yµà䊱']úiÇóËÙ¿Sÿ»Ý×Nçã3?ïë? ÷á‹O&Þ=Þ5‡âJÇ€öÃsßlï=¶ã©ëµ'¤“GOóÏ=ýÊ??Ü¿2ûø¶{G†ÞXôÛþöÖ·NÏœýàžÞ™<ý¿ÌÙ}þÃ…EýÛ½²úÅו¥gñ…«sëš6­9ó«-žK»ç0ñË×v÷¿;UȽïýˆ>ãyû ¹÷ž­¿xézÃåþå›þsßæƒûŽ£ôåÄ{ *¢|׃ýËvPu3®Üsý¾¦¼¹V5ýã­ÛCëÏ>öUãøël;[:³¾|ãô×¢Þ=û_ŠÚhäHÏž™qGϪû„]ÌõZWoYãöœ¤Û䮟FÅ®œ?‘º}6çS·Ï¬@Ý>Ë!ׇu9H­kgºlÛ$s¹¿@,#…B;,ݹÑyêÑWØýZà\â'SGØ…?]×§ça­Öñgˆ¿¿ò¾oƒO¡8ç/k•‹EÙÜM|ð/ùc£i:±ÐÚå×ô\¡¬¨ USÖá»@ÓUeÁš¢Pî{û6öd·ömJQuI)‘’‰ö¬Ô!­lï˜vb·­Û’íëïÝõiÕ †Qª ¾È™ü?PK-qM>ƒhmJ8 rebar_escripter.beameVol[W¿Ï÷9~vìæÚÏmÒ&ioû¼•Ì8~‰]Ú&Ý$sMPÖEÍŠ€M8ÏöMòbû=÷ýi×ie%#‚TÚ'¤mÙZ?À`Ú„C0!&MHûТMbBª´/bÚεïÚ"ç¼sçœßùÝ÷Þ}g9?…PÜœ¯Ì=<¸„”Û¡É!×-¯Æý†gwî%¤g?Éå’ÕíÖÂÀnûšð«Ã“ӿ裮³f¯Ç×yPk» «[³Û¼m×ÜñCך¶q[éÏ3m§Ñ•ýîµ-g=’Ïã'íî@ÃãVÀ£Üó\/^¿ðšL°Õn«¢`â²gCL¸ñ~ß¶»ŽÁ¢Á†ç^>ÙÍÞ*4Xsãw=\w½ÁÆ4ⵎÛäÑF›[é—è¡z6y›C}n56Rb1q[_åuÛQƒ¡Ä4ƒýä^^Ô‚úvÙn7–×L´]IÃße¤‰!˜ºéÚNª×D ¸øƒÀ)”T‡Dß=×#…{ÕŠÓ…v#÷m³8U0 £…} ÷­!´TÂÛ°Çõÿ„OÁ ‰dNP…0)Ã9¦ãAì¼Î°Ár˜Ù˜IVc„æ·ðû•Î"b!ñˆ®Ò·EVé¬J°JS„åtX¤&⫚8f²™φ˜Îc¤Ïcb˜¡þe=f;§ä‚b΄ÆlhÐy•æ ²KU“)ø©èòò‚îF±N0üƇ îD1ZFøqm}+šÈ\E ¢Šctu¦²¯E>Ô„0³bDp% ÓT™žÎ²:]V]†9¯*,â¹²¼¸úÿÀUˆ@r}f Ïníé²¥ïÌl³[ÆnŸ}w!¿UJ~:ºüÂBœ jÛ&ŠÑW…z¤+ݯaåêW±r=’IŒQå…$ÙÕ}²C A /¡¤‚#X#o!åU€£Ê[g>ÂIFÓê{,)¤”cô½üû¸Ú%UÊÐý*Öè.SÞëmÁLWcôc¦¬¬§ËÛÄTÍÔQ¦êÛ„ÊRq”¾M•ÝòëÆºò1ô»Ÿ*üd¶¥©Q¢hiX; k™Þš!Ò~ ¨$•%&9KõªZ¥2DW42€Ìl‘ÑÒ3©ƒx잌©ƒúT iAí¤ä‘¢ ³ >G´Œ¢ˆ9,Bj€=Áp=“ÃIJA—,P1Ó“RgYqo¢ ò ¨ŠûœÆÊ©#0¨6&ME;z&u §Øª9‡KP¢ÌŒ+©•Ü ŠW*ú l‘–•UÅ£qw`†K ,Ë¢Y©œÎ¦sB`²,u(WthÊ Ù±rjëx%ð…goØ8^ }¯o“"w.Qù>L ÅNÖñœÃ`*êÀb2¦Åe< –‹€’OKŒ–•Q÷ÐÌðÌÈžšG$^ÄG¥?vTbŽƒq,'}Áí>élbO“{êñü½x¥ò„Еåüy‰=,}$yɼ„üß³%;¹¯}úÄ ?zpè–|ö‡?ØyîÚÅòðøÒXPþË¿›Ûýù?'º/ߘšœüìbíñë?½òé'/ß·3‘®¼{íìÛ™±g®¯~øíï¾xñ÷[Ïý{ü–úîñó»G~ý›Ü—Ö_úíJñ—?yÿgç_?ôØôTüÑ‘Ä7ÿ_ºåý¤ðÆéÞ¸Äï|ôÊÓ­Ý7ë·V²ëŸžy¾”ûÓ9ÿâöÉï|úsñµwn|6Ñxì__9wóæ‡ßQî U¿‡–܆à¾$÷{Rî“м ç{ñ€Ô#+5ñ ØýÒïúcÒOÎ'´½ÖY‘&—|§wá”;ñÔóoþõæà¦÷ýnÿù›› ‹Î¬©=¼*ð1¾\Ç&JõÎåšv:–wEÜ0€Ã°…z¤ˆ(v ÅÄñ6yÅC§É×l‡770¬5›(1aqé¡Ú£‹WZhhÚœš2§§J5ó”9S:õ9HûúÂJmñÜÙGZhpÝèéÓS¦U77{œ.qÏR--Ožžœ15°;|c Ê߬ˆ•²¢VÜJöúnè5x Šn‡[ÜÙ´‹¾×(öÎï{Þ½O Iø$Ùœ«û¸Ùþ PK-qM>æõ—z¦!rebar_eunit.beamŒX tUš®Ju§+M.T§áMA„"Ý@BTBCx‚¼$étW: È[#APPgv|>F=g\ÖÙÝÙ=gÇarÜñ1ºëÁÙwVG|ÌàÊì¸ß_}C Ew8ç¦ný÷ÿ¿ÿýßjæ-½yª ŒUêj×f‚û´ ‡¤Ì¶`ªÅìŠG3Nëo^W{æ%[R*÷? ÁÉÎ$NSÉ }ïÎ63Ø™vÛ©ŒœæŠ¡˜Œ;S-©ö<+ndœ‹ì m ˤ…üwlHDã²ÙÓ1Kš©öd²áNwE3¦ƒX]鬜#c¦3ù³–L¢%ˆ< $Ä,~"™I»£é–Ífª-‘6ÝýT+$•Ÿ¥e³%“t\ÐGµÜÉâXño‰ÆÛt«€ÝÔ m u˜¡-ÁÍÁhL¨+ź¦dn ¹r‚LH™‘®X0%%»2×| %`³þ¶À÷¶˜æoÁx0vÛ6Ó‘F]à5ƒ¡Žœh"—Ä‚5Ë”D9eúÝYZ”¢dm)f:È^§™J%Ržë [:á\¬®˜)[ÁˆéâgÎ-ÑPG>¬¶ÂÝf†sÛ‚á`*RÐäÄŠ{K{W|@$˜šò7±t˜Á0ª"«‘G1œ—L™±ÂùñD¼ÅÜŠð£!@O‹L…ƒ¼´å†:ºâÓ,؆® †(asH0Ä[≌l†AíŠgÄ2îÚ–ª†„Í­ŽDÒŒ;-B^2˜ÊÀ‹Dˆ*ö-æ–´²ÎÛ±p,7š \í±`&cÆ íÁî‹”8‰Ç›J1ŸªŽªêÉä†Ìx†˜JhÜxh$͘9Ë ª=[ÔF—ÝHEùÔ2D·¬¢ì{§–å¢m"™ŽïåÒ˼eßéu¹#ýÿ&kâe+Wņê§\¹Ë(Yײ_ŠàŸ%(9²NË…¥L±¢&¸)y =Å?Ü( œ;¤]±q9¤EeFËR©‹rA)+ôVä+ÚlS ÕKú¼P,euŽÃ(Ì×ôÙ…l0éõ’Ú!œÇ‘e<§°@ÓV(¢\”¯(”7A.ÒÙTQd\bC{Ù0QjŽH5l¸(3r`ÅpJ‚Ö£¸1ŸÃ¥ƒÇJŸ¬µm‚,ôt¼Œ¨+V1¯ÎÆôX‚ÝËÆˆòh#pК(± 5ª&÷ ºXÊâ: w¥PH„³öh öŠ¡4¸«$_Cà¬ÏkÉÃ]õcÉ–q°¥Zeï@Ep;åáîj©”Ý„†r× e³)r#JY±¸`ôª5l¼(‹¨_YEàFB•(7 …òqµ–ƒZë}•7ÏÒMÖߨ«Cš&ä뺡^‡Ñ ³ê­6Õá4Ê×áCÛ: 6 |‰ßåI:›HšH*íe“E¹ÔPѪáóæêlŠ(O¦B†Š2ˆÌ…è?+W9­œÔQ%:Ð T‰h£•z+Xzé0jò åZAÌ)– -‹(x¦Q¥*šÒ .SÍŒµö@ È Eiœá^ ’3Å’ÇrEgdqY¬÷²©¢¬[LZÇ8v ¢>Õj>VP2|0½÷묒d+1°Ø´Klº(OãžLGiS¨Ù{Í ·ì_‹yÀ=4)öÁ<îð³Î ¨PzÁp/±¸²*ÉÊ21ƒÌRðîê›reV OŽ•‡êĸAÝTÁÊ¥xΤòu/Çrž¾â*V#ÍÄÒê$A­“ÔuZ­²š" ³j÷6K”«Áå—W«ó ¾:¯RB=õZ]½ÐTW¯„JY¯˜æD“ÃÑ œc†JíU,¡6!Á³ˆyTäñJ+…Aj(”¤†b‰ÂQ¨"Òý¾κUCQž ûWÀþ9ÙÎú\ÕQ¼ë(Wy­(“Ъ 8=̵VùÖ)º2OSîæ ñ“oÂY=Wâ97_@@nQ“ËÍœr l²ô6€c5;/_Ó¨mUËj- ­ ŠZÝkXÀ½–Íw¯cóE9`¥ªX#âÙØÏRÖ¨º§`jÕ°¢<Œ¢¼¦©= Ú]žxc‰òF ¹â«d¾Z_}ˆ{£öžoÈÝ rä´V—Vºý¬± §ÂéÆ-Ã6ÙÝj¤É»¾Ñ¢‹t¶ÐWíc )ˆ‹{ÙQ^¼Ó©Ë“¼¯bèót_@ ¨¯á£:^òmÒR…¤eùºæqP»¢Ó²¡ ‡R–V±åðo¹Ý¿åðçÃhÐ[7¬<Dº ¥ˆ‚YB·¨evY/d¡@N9ÆÓ„ýºuðAp0’mx}í;%ûnÅ`9Åàf˜Þ’lò³^Þ©+hæx)×p%¢*ËÁÔKåU¬†4÷;‘eï:jèBLútG‘r §f¯Í¬)ÍPMclâý\8ó J±Ñ)Ÿt9àN Èššmÿ~Ë­frk%ÜŠ¡°oÉ^Tƒnå~'VÁ‰U7rÖG–¯hqît*r…4ì믭éÇfç¥CŠ´Rv(7šÒJI yzØ!Ÿ—¦<a]EƬ†1q³]g}`(Vù ‡9Ü€Ïjȱ˜hkÁšD%­+e·J"þ¨"¸ÇSVnÍ´NMöKªªÌÐð¡©hA©Dª%ÊzÓY"”(xÉ —hazÑJ„gk‰ í€Ì4‰ÿt@Ý„V(ZE4Ç[ŒúVš!Ê­D•Aʈš\)Êm vÁžPkCÌÚ$sas l¾:I«§"Á蓬àÃÌ!Ñ@£@”X@@›ñ4«X@a)dݾˆÉDºJ’JX;¿uÛû®ß$·B²£ŠE ‘tJtû@PAPµ:U¨¯S•¦ÎVÙ_g“OUôÖyš—: ¨( nÔ†*Tô¯÷iŘ‚C®+Y[ýmì«¿”ò4mƒ¦Î*ƒ¦˜Ý茎ýõFǵP‰*Tœ ¤Õ•ÄÑmªd©Vò¦ëÝ;ñ·Éƒ?!÷pbT¦iT Ý—Ç@>æÉ×`XÒõé+´~~È3'³”$ZŸçô]Fs”1±’“ÊžàªÙ{Òˆ\.¶¢œñ³$ß w£¨6W²­°PõV±-p‹å¾î×—²->÷úª'Ùm¢¼~çâå­~ÖE(·åvø¹­’íà~n‡ŸÛ­{Øò³”moB»l¯w£®–Á £ž¾‹¶ÙmÝžµvøÙmt fµìú°qW%ÛÃmÜ w÷Û®›Ýö[~w> #‰9ÙB‘ø¬rŸØ7ð•´ »³®ìå=~¶“\¹ʺqrG%»“+놲nR¦À¯n^|Z~ùȯîzwA¾ÒJ7D“õUdw©;‹‡(ßég·þ^àß ü}•ì.)_Sj%\ÚÝDÕöcû”eÖç@aÀÑ Œ~7Üåg{ ¢û±¿Šõ àz¨U«U­OŽ5†åê$/¯~]žUÅ€ñ@v –²*o…Ô w®p+Ù=È"ÀÌ´›sÐîÔ=~v7Ùq‚û‘õÕì^+ë“Ù¯š¯”^¯õÙk;’MïaQ¾×ÏÀQ€æc•ì¾>ÍDÍu¿Jí÷ùÙQ<ÁƒŽ¿ŸË âŠQ‡ðØÎùûò-:fO¢±ÓûjBpÔ<ÿ ·ñ÷ ÜFÑùØ9ÂØÊéÜoÁUóÊxlætªQ§¥÷ãgàÑÅ锇\KïØõcE34ë€åX¹õTsÓ„:UÙ<&ÚûEÃÚ39á¹Ožqwµ?~cÊöýÛæ6/øû¼¿ùì™’[ÝZ½õ§? –ÿï?~épýO&Úgÿr‡o¡ü?‹äè{Kÿùè´{ôÓvÿàçNy³pÃÄüæ£çßþè¾éÏMiÏè¡æ,w¼øùê_}ú‰œÙ4´-wR÷æoŒtlþÕº»GÛøpçKGŒãO<Þ{vë?œhμ6Wœµ!ÜÚ½bÕö+¯^øzü’wfœijþ»1™+5”§&ϧvU=ùO;•?ÿÝ£SÇ=;ª7çéãÿùرŠ]ãWç }ûÂŒw.ϸ;Õùò„Wåï]üÜÈóÍo ZØ0ö_fÉ—_ÿé+Ö{ïËìým²è?ž˜üÑU×üósV¼5Á<:øóÆ«Öv=|WEóëGŠšÿôHbèW—ê×;6¼1.ïHäКO_ÙóûƒçWD»÷®üþ_¶¯ýü…ž+G>ùàØ”¿Ô¾úÌå{~ó»¶N¿Yíâ¸gÏn¸åŸžúQÕïm`|-çÅUk†ý¢"}|â~}V­{zmÙÁî%GÚ•µµG+]ÿxì-¹É¸ôUðM#еº¢æðÕч¯NyrÄ!ó± §k_ºýÜßþ¨æùŸ|°ëÇ_¾;dÕgÉsç\Ÿ?» ©&õèUmÛ©AGÏU|ãéŽQÞ²+•3Ë/¾ §×-ÿÍ…oÕÆ¼Ã×ÿyæ×ÿȭǘޭ]9â'7_9>zïŸ?»ÐtjlæRÀxaØ/¦-zõʃ¿ÏÛX~:gKô×ÓÖÿqéª]_~¡Ÿô|ùÞ¿W”}¼öC¯¾:äêzVôÉW/§Z’÷å”~-=áúæ¢DˆzæC!;»óž8uˆïObäûXøþï­.×Ãé¿Ñ{wò=Ѻùþ¾hO3òvŽC=¸›Ó©vpú¦oô­½WíýiïI{^ë½ÚL†æù„nkJvä„is:n½ÄÁ˜µ6ºíÞèGYýâÃïì>»aCý‚8îq¸Åï ~WâÿÿÿUËNÃ0E‡Ò6-Pñ lÙ$NJ±äQ¤H<<¶–ÄqbWcÁ·ò3$H±»:3š9º» õ,àÇÎQà¢ë¬È÷±ï}6sƒÒd`ŠRÛ‘ìi‰¶u*XF«ðU[TÍþ0SÃÁËçêöš?Uw[ÇËsVäkÎ6ì|½ù]Z¼\=òêþæÁÀá›'e™3!Ù?vü–¼#ùA×Àì,-ÓbdÓ {læ ù±3±G?¶ÞEªÑÀiÖ¸3ƒ¶Õ™§:#”‚þÇhuH‘ºàBú0”ßPK-qM>M(|ò}” rebar_file_utils.beamuV}låÏïÙ¾8>zñ¹qÒz‰Ý´©kû’8N´í’àxéúEmíœí‹í;ïîœ&hTŠ*‚iË`huRWQ`lE›†@Tªº? L]&¤¡-Z6m AWD·2i =ïùBL&"=òó>ïóü~¿÷y?rSÇNô!Ôú½‰äø‘qS«"Dý!ãt9›ÑÓ¥"§ë¦R1œz5­šA›‹5™®«Ê‚ó´¢ô»-]Q²®‚¦W3¦³¢¦á.T2¦)«­  Àa”ZÙM!9­Tò¹ŒžwÉz%£‘«¥u7ÀÈ™\Ée˜º¢é9MQÕy†”©™ªìQ3¦2o¹NY×5½5/WdSN“"šd¹—¬j²j¶4T´"sš%];½½©$Wô´µŽÖ…œV[lø. +š%QԈЦ^—…LÅ™lư0ÕLY&4©t)ñ[«Z¾MSÔ‚¶­(›é¦±?² ëêjDŒÜe?ò«Ñ±¾H%ú¶¿b6dRËË9_—C¿e°10/Å9|Ý%x9N´¡„ŒGe,L`Ä‹2?ÆËéÄ`6I‰œ€’´ƒ_æ”BØ-pnNRïÄðý8%H«Ø‡xJ’hÜF»9 àhŽ’0‰§ÝÂqo‡ÜU Œv’©:þuLÍÂTÍáóøjÉ+P"a?Qt ^³]E×Röé—¨€)"ÉÏ/ È-ÌÚü¤”ÈK~Üæw 5Nâ@s0‰ƒ$IJI[t¿º©û2(¸ n€‚vZ÷ŠB-ñ~ ‡ˆ–Ç£` ,2X:ó¯,ËQ·8 %ýœ a~Yšã[hXß&ÃI!ìæ– = ¢C1y LÍ~±6µ£`ñæ‚Æ¯ÆÙ¶ Á¯m+{ÍFàDnJàSžÎ´¿ÁíƒE2<¬’ñÃ2wp³}„íÀ^ÇØj7·’`Û±³™±“÷tdAÏnN“Aàòã ”Z²šêéÄnº¾‚î2¢˜vÈÇ«€íq† Ógýô‚‚NB¾È»€|ç» ÃÉ#ä¤é/¥.líßnÒ? n'”튳;l¸ÝdAw\7ÐìiÞ³/ïðå­î‚õv5¯·‹_ý®S¼ÄûX¶6úÊ—7º‹èê]!ÐL°½@ÑkQb@d{ƒcA¶7 yö²!OÛC1!Èâ!‹&x49Ás3a¶wÒ³×+΂ê,Í4ÖuƒÜ(ãF­»¹[Ù½8u#Ì Mß+Ñdrt ë«GnšÀî±,m=ÿGr&Ç&m9û@Î~ŠÙç…+…ý1m³0¼±àX0ìŠÀaWö{Ѭ4ÃC[`¸ЂY]n~uãü÷’» À<&ç·†S°u¸Èm,ÏO¸È3b/bóŠ3HwÃÐÝ0œ·ƒ’åÅDH”DI rcŒÀ&ˆ-9Ÿs-Nëý‚š[ßg7©PôCmj¼HhLÇíé8™„éð °‰/Ü!¦MdGñfG¡£=ì0tu„b†'xG­$ï#9ô4Æ>PqvœêÑCÃã÷iä°b’ÚÿÂðÜÂùSßçÐUÉÿØ/Y®¾ûè²péö‹ë?¿çÔkµ÷ñ'ŽŸæoÎV{øbÏ¥µüS;¾}Í{çÏ¿óàÅot¿VŠëç~|Ôøð•…9ýõߟ+\œ~øø¯~öÃÞÛåtÝDoÿ`éÉ“^žr}t½žp™k¿ýÉ+gÖþúÇ¿¬ü®°~ëŒÑÿÂW.þfϳ§ o}ð‰mg_]:¹ËùЃcåÏúl†{ïå‡?¡~é+¿~XË5ïIÌîÏЖ^6÷/dûäœtÛ>9K]gbÜ4urFÎVH¤äÈ#±¿o -ЉÁ$æÉ™ôôÑ©ceÔZTLax¸OÌdÅ9KÓ¼¬ ªŒœñèp´ŸÄhS©Ê%W.ïŸ2Ž ›qfZ2^K ¡Õõœ\FÑXI«Ê±²¬Î)1CÏŬÑM¯éÓ: ŸÀs°âñ¬a’Ãû?PK-qM>ø¯ÆDrebar_lfe_compiler.beam]TmhW}ó±ÙlÌìNÔ H\+•t“Ù²5h$Ý,Õ“è´ÝÌμÝý˜Ù¼™MR”Tj[LhÅZˆ?’h l+bcl­µ¥iCTZÁ‚E¨è€-…R*ÅbK+}o3AÛ3sß¹çÝ{ç0ó:ºö†pìh‹µînµŒ"àWŒ€Á”Œ’…4L*F±¤ rÙA-!Ó2-|/@Ó»"U =­eÜh% šiñ+lJ6W`PY¯¶¤´{µ<«*t g5%ëÕ = GpMÏКáL¨([Nˆ ²žqXYd Wö%Ët"h•‘Ž%Y,‡6òÕEC-ãšž6jÉ«ÏÞ|î¾rð'nzbؽõsïæþܸñôëË tO?3OI'~ÿyᇮ÷z÷7›N^¼piæArBÛ2ôË«K3gN›S¢3ì•ûÁâµú×v}<=Áß½~çhÝØòõ³ƒ—f÷ÿ3ôýðà·¹GîOö5žŽXnyë©]@þàüâ CYõˆþŸGn;f[- ߈“YZÌ©W:®z"›Gÿ˜NŒ¶L6;?WÖçrízç\=Kô.üj†n©‚ˆ’f¹X”Ñ+Dà4Ê–ª¡<`aJÓ CiyàÒt¥PV¡ ªÊº ÓšÕ,ƒsª (‡@èÏLrebar_log.beamMTÍoãDŸñäÃq3Ô±Ó¦ŸÔ»­RV­ÓݪÚ]MÛÝ ]µÝj·]Á)±ãIêÆ±#Û)åVØ!q@BâK½"n.À¸ð¡JœÊ­Ä$„=pA¼I¼jGúé½ù½7¿÷‹&ž{VJßY»»ºµ„Ѐé\Èm+¬yA+åúnœ=ä¡Dý"“þ7ûêןϲýáŸtö;ÝSAc7ñ!´'“Y〱„ÓVã8„øâOT÷%‘ÃÈïo|í¤÷?3Þ]þ¸ýýÖÌ—g߬oøM(þ×ïO‰þlÐßv$ˆŒƒhÿ=¨E½NÇ _ ™ ;nØF)n»¾`°ÛFY×ox=‡;èâÃß'Ps¤¬ímlÞ©ínlÝm£áE³R1+×kæ’yóúÒ³&ùñú£ÚÆö½m4Ôrccy¹bZ¶yÐ÷OW¦Ú(}c~y~Qp©ØíðýŒ „3K²¨•¶rV¾o0 zaƒ·Ñ ûA‡/´¹à.Dac¡ÿ‚]dâ¹™‡×è¡U;ŠÅeýPK-qM>í£ø rebar_neotoma_compiler.beamuWlç¿ów¶/Žœ}&„À'Û  ý’àx¡ü¤!¨¹Øgçbûλ;ó§Ö¨SÛ uŒµEEÕÒ–®šÚ"ÆèVU[•ò§t-«è¦"M•¶jk5itel]+í}ç3u©éÅïÞ÷ÞïýÞŸ³>oÞÚKQþ«ƒÉ–^¢(×9Š¢R͆2&iMÑÁ(§3z©¬Ãë(lVϤ ]·¼zÅJgUÃWÒ³•¢’Vö[Å(ÊZÞÕÕ%TAÆdS¹‰€ŒŠæ¯ÁêeËôW2º–Só(¯X°ªºÖP6ôrQ5-³Œé½r±¢x³JN®-Ÿ©WŒŒ­Ñ&T½.“ѳŠ{߸š÷kºn£%U÷ät£$[nkÜÐ÷1–QQÜ9¹h*^³ –ËJÖ—ÕkTÙüÓä’Â’ˆâ'tÒ–ž–!‹§Z±P®X qvéNS”¬YƒðkQãŠ2B€šS•¬Û® ÉÚ&CÉ)†¢e”lº¬äMÆTà@Sö5ÊÙlZ)*%E³³J±¦{!9‰æo ìuŠ×PÊE9£xd(DË6ä ½d;³feÌ2äŒÅ˜ê]Š»¢Awy©ZNo"ý­{ž½½'-f"wÆzz£±¨O5Ó†’¯eãk={Á³7ÊLèªöµ>øHQo®([–¢5V× b©EÓeŽ»ÃÐ i07¥Íl‰~©¹“«hA¯ Dk¶˜c‚  (æ2ì2OUÿ¦@Vgšw;DZœ…yŒ ŸÄHÀ1„…#*…pDÀƒÈÖÃDߊpØ>JQ‚W¤0bòŽ áÇÌ(…1Ê`—€S¢‰ˆä1-¹‚Oñ4Æ®0~JØ$‰ôWð"½Ç/ŠX` Ã?€$!V‡²+èãyzRª Õ¨Ò29x$vÄxfë‹ôaœ’@OC>ø8‰]ð¼ƒ}É/IE°OŠ B^w]A¾f 3%Q8…‘WÜ‚S[Ëï¡è÷pHÀ Ô„‰k–¸¤â-Ø×zÝׯñôÕ›çn‰$šå±o JÍÖ#š BÖv0 ³0¤Mà0rš7X×¼/@¼búTíž}À(À@û¼ü$?Í‹á”oa %îð°Où:R¡d<Œ " Dì6Wqwq!ä‹1°ñ˜O"J&0…¡¾=_ª ÁfèK€!!®LÛd(K¸AÅÕ²Z€Už·Ç À9ÌyJä‘›[%ÌŠ'yš¨ËDš{sz^j†8„ û%^ä“!W¼:Í)žÇqÒݶ*ÀOyÅ÷Xþ*k ȵù±M.d“‹|±‚¾´‘±­Æ©É8N¼¦`ç „€X——g$–#Vë­sÚÉð\x¡^‘Už uqó åÙ=œGhóWÝUkÁ{6éX2ý6¨·¯âóqmâÙfš]@,Бä£È¶ÐìB0öƒ±c·ùE~!¦šxŽÄ-&+¶V¬ ûZ¹ÍÚ €&$ˆØâ iÒE¡  %¸…°ãìb²sK} øv®â–"NÄâ²7,NRC)ì\g~ ™5ÁƒFÔã-MpKÞ2€º  ºVq=5Y…’©i„’ 'S'mÐVœš!=lëã$Ô""JD|Xâ$aµÀIPT„[îä¢4»§. ð>@À¼µ\7ÍFá5¥Ùî¯2ëªgÖ“à–f©´è%^ÌÏ“5ƒ]mt³í5×8œ¦`{éDQ£–±|©”ÊðIAâñ‚¸@Xç³Ä‘Ô,&GÌ¡AZ@æ8±g®c'¸ êì¢c@ÂŽ}1ÈÇÞ ²Ô±w,w¾‰­³w×é=N,ÜE¨ãàÄ;ñIÔé+êb¿Qg_Ydzϱ×ôÏÕuu­­ã|»£cÇd]æ0Ñ“ûIÏíÒÃUNœè蔃íªÉpEÛæð'Ï)'.áøRîC×I|Ò99x´ëåþÇ7¨™ïN8ºcÿ±'¾µvóY‰¯<¹ôÒ“ßœzàÛ>¸>rñÈQê§:|?ÒÂè…CoÚòøòÿ¾¿këÎÜK¯Þµï•ÝÁö ƒÇ*mósß8øÄèÞ×¾ó÷ûòÿi?’Zñãà¿6NoR¯<|{gëúÙ}gÎlîËw¿üûöâû~yùÌs…™Žeì¬Ó×ZϾÒxâ‘{;÷m;óæã¡ÈsëÉ_~ú§^Éa‡=ŸÐ÷>/´>6_ÞxâþÁ‡Nýîè«;ÜÒóh¶åà·û®u–6õ¿yÏǣƟÙþÐ&kÏë¥âî¡Éìñè̇GJê§f^¸r~÷ÞÏsáˆqü\6z`Ýùk…;;×øÃ…ç~=yùìGwÿ©éíËè¾—Þ=Í}ð÷;„3—o+žnúüûoÍ;7åïžsÑw¦UkÿͽÏÿ퟇þÌu¤~ûúékG?Þ%üûÂŽ¿Þóì±þŸÌÚ½àô³ù쓟§¨ z†Ìg„»e>õ3¹­nçÖ8:Ù~g^ ’Û²Ìñ!ïÑ"ÇÞ Òîèäý ::ÉË;8¬ó\Û9Ÿcg,Ë 9¿GÞvzÜ•¥Ð^S³4žêïKÿêÞYRº}ÅÀwŸÞõ㉉¡-g¶?Cü½Õ«µI ž,ÅÙ—¬´Y)•dãq ·Y¸Í(FS5b¡ÕåUµL±’U²TCEƒ+¸ª)ÙqgÙ,åÜ>²a]zÛÈÆdjŠI½½R¬7ž–VH}ñ5'vÇÐhzdÓðæÕ˜W-qåÊ^I“&lN{ÃRÊè^Ù#6ÆRKʸg ¾ÌÞ•]2'»åÙo¬Þü T¢g\/)=p/œP{L#Óc߿оòÓ¥~–LPc¦EÞ¹ÿPK-qM>Xù0"T rebar_otp_app.beam…W}lç¿óëØÇ¯}GI Gl>‚I|Ž/é%©ãd|6ª«Ö™³}I.>û¬»sÒˆµb°MQ«‰l* vü´ee“Ú!婨Úè¶±ŽÒI“Z4Æ4µSË*­Ò:íyÏ—Ä+šéáž{Þßó{Ÿç÷¼>½ŒQ”ßPrpÿ ¥(ʵHQÔk(ÙHëV)-—JÞ¬^(©š²¶…Hºl©šéSMûÅ4²nË(+5“²f*¬¦Ë9;> 95ŠaèF]%ÓΪ‘3ºa¹ô…À@à¢YÖ,Òƒ6¿ÂPc7Êä•yÓÒ …]Ñ‹lÍddÓ®ÉOPv×0ÀkÚÐçð Ò‘Í«9SÑ& ½& ŒYÎX†œµ¼“šlYJѯdÔâ2¾&£ÈÓm ê*¡4©z-Ѽ꽱½:)*¶kÙðWÅh¬]l¯# ¤*XÜÔþÅz¢64ÐXûÿ\®0 ƒÄU³Î%¦* `Ý`,]ÁVü¢pK(,qHB¼SâêGK ÒxW&I‹Ïx)ŒÜÜs„–$чl î[B» PPÄ2}tQÜ¡ÈwKb2äBIqRŠBŒ ˆti0„„8€.³BR6ç½Eú%'‡`«@Ø+Š+U|3sš>.¹¹,H÷‘W$ u£…ê¥K((rôù/!ú¢+è ôU?I/nÒ ‹†ÅÀónæSú$ ~È‹öÝE»î"a¥ì»Ü‰Ÿ†|õôí æè{„ž f&Ô Í×H‚„6}˜(ÀÖƒl=hÀr"ËÓ ·ÂÇÖ¯ê&:`¢ƒD3ü °KRdà¥PÂÙõP¸›b·ãCxD¥î§0†°èJ!@®f|ˆ¡”¯1ÅW00¦”=m<†FO”#ì:t Â^|Þ‹/zñU‡€ÝåºQ貞´Ú­†0ͬ_ƒ±ä ‡$߯a7 _XJ‰œä‚ØVäoH®Jò,`Ø$醕”Ä-¯’(/¾ÝÇ6¢]`«R³Ðs)Hn$;7Á¦;@ßæ^v#D¡xÛÚ&°X”†BÔðPOÀQâ©áÔ„Ä…¤' #¯toå84CÕl‚ññ&àlÎ?¨ŠÀÌR‡*b0  hcØ@CT’‡Q¹4q”[(é„ÝFª„Ì)šÙ Œ1`l°!Îf)'éù8÷6TùYq<2NØ#•òPo¿ðN-|‚ £=ìš Ãø°¶K„˜ _¬"‡Å Íl!Cåá øJþVäü ˜­@{€â<· >ØÎ6h§žÛý%¥.òzHï€å·Ár~¥¼ô˜çÔµtiü…__þÎçŸÜÿ~ÛÙ·gÿâ›·Äë=ÿò°={rŸž%º—œY 8º“9ìq|¸·RýŽßáÜ(çLÅœ³Öîø-ά\Ι UͽÁ‰-Ë '5²:íÊQhÖ,Ú/EL½©d߉}÷ÇFàÀüñ÷ž-ÌÌ 'aÍeãÝïÕKä*i’€'G±öõ7m– Ù˜'^¶à™§ÜäîD"´š§¼j1«•sJŽZ½6N#XËå(ßБ±}§íO橵b,&vÆâi±Kì‹w-ƒ˜G‡'ÒcF橺)Õzzb¢œgìšfÄ¢òTM¢£§£“ÄÜ–ZP¦=ø(üIvɬ\#×Ê~»@S/Y%OE¢ÓzA‰æ•⌅›uÔ¾³®zËÿ=è€Ëô E fL‹ à?PK-qM>–ú$m—ørebar_port_compiler.beamu9 tÕ•3š±õ$ë9#b'qH&%q¢(G²ãOLÆ–eåo‡ücG–ƶlYÒÈù9ÄäG§¥{ í² åÓÐ-ì'Kt»ËvOYà´å„B( [ =–J~…nwïyNDz6ç<ë¾ûîÿ÷ž¢îž- Wûag´cS‡™ç8ñYŽãŠrÞŒçrÙ¼9ÈŽçRi#ïd€Ç²Å|Â(xlÂD63”&Æ9NLGvÌeQ™‰B¹‘OÇ3ÃŽ@@Le†².›#`•!yÁ9”ÍñÄHY"mÄ3’M1ºŠf*]¨HiÃ4¤Ò8‹g’Óú+lZ‹Ì™* Äó e(ž.¢™/N’N ’ý©t2Ï'§Ù³ƒ£FÂ,Èùbf —7˜k#Y°¼˜IC©Œ‘œaùÇ…D>•3ðÏ JòÆp1Ï;RÙr0|M§2cŽöva<~ ,i ‡×·“éDVŽùa[ÿÀD<ïÌæ“ÉTÂÁçd™‘Ïgóe"±X HÌfseñAð§l(›N¦]Cù츕l>XQB(3"‚ûT|0m8òXŸKÇF8ly«0ˆ‘7 ÉT^Ld“†å7îœè&¢¢p°`ãX4åP`‰¸Yž- §#[(‡Tä3ÚÅ52/¦­’s¦2‰t1iP¨<`}C Ú Á´´fSÁ* ð¼:dðËf Õ0Øef-Ÿ¬JÆZ¢v!~0•!…ì@!g$ ¢y0gH…ý)bH8N¦Ót<>f LÓ8À<ΰK4žËÙeJƒ H[ œ KöÕÁi1õ¡`:áï×ê‚Zд#P¯• Ë ¹tʤh7bsicf°$' b¨˜Ê9ÁkSZ¿’Í ^­@^•>7øõ–äÕC'Ä]!ƒñ‚UÇrЪv&¡ˆ‚3®àlU_§±yƒ¬:UCP,fÁce¯z¡ œ,9å3ŸÊ _Ë¢ÝÐAEèV0 †XŠŠã*ÃJœýï4¬[aùyÉQµPá•Ê^E—ÃzŒSõ•².t95NwÈ¢r2Ü(èƒBU¯Ìkºà9ÚgáiL|z^ÖªÞ%LS#VštAÖEá´¤;Ɇ½"‚Ñ*Q¢íˆ º,ˆ ƒº¨êŽ‘Ý'x}b/½®%*´F¥SàäNARuYÐU0χ²ü¨ Ãë÷†En—PU8‹b’¬?V)Ãt*šîC†%ØØñúZïuT}¬ðû<šâuÙwÅwÿßщqJú°b{öJŸ¢4Aõút¿€ŠuQ>­HàÇ ¢2‰Î–øœ£Ê]¥ðSÍÏ ‚jyRm}RU<šÞ©rB§*ùA–ò9¥^í¢Ð&\¬ÑÝ3ïqWŸåïy€2夯?*¼~§´uHÊ•h¡Ÿó(º® Órl©”F⟠@ù ëþ-0 ,û°\¢Ež@æÝsžx+5Ƚ_wתº{®ìÔr-Ô'´Ò+î>ˆ»pJS ÚZ–VÓ*÷L*ó¤JÒ¹¨Ï!DEÈELÁ°MÑx"K ÈÛ˜&8•»¤^®[Qcî1TuÈVŠÁ5åZ Úªí,hµ<ØNgòÄuîZžÌÄúÓ@W5$Ô€d˜®J<™])I¶Ý~´{9VˆQtØš!™¬AW-èªÖU+òdÊ—@~-ÊŸ ¢õòäºfª ž©^¯èõuBRøõPXW»ty«.˜NéFÙ„àB1>£Çt™ÞdE½X£~ —KçAÈæódFÅÄ í•Á}Ó®RDŠþˆÞ¥ê[¡+BzR(ƒâŸâÉ|›<Ùgybõ…D—7ƒìAVÔ/»ü°S;ÔPv!Wv‘ŽH_"Hý}m}¨ß¡Šk]À%Lý L™)3,ˆå@ò§ô–Ô+±ua‚ Zít!O€ÔDlꦻþ_&ž,´ü7lÀ±+þ¨a:WðH½zHÐ#PS^i+€% dÉ11†keÄÉ^YuºØ#AB« N‰H%ŒDª(#^Q°y–y=×…éRÙÃIì¼Jà…*ΗV* Î.Y€@æáTF¡>Kh€.x»p!E@[sº{%¦JÞf_&é ÛwµæÏÉŒ”øDŸP¥UŒCB¢Y¢e× ØY‰ ÒÆP[ˆ6Z© º´ž'ÁfºÂÊö¹záo"öL; ódE˜6FôØèbR"Xv1»5S®Õ@Dƒë]é ÐO´fÚèHŽƒ‚+ìÇ{À ¯´T¼e©Yð‡< ³ÃF=F$šÀ“FçªfÚj2Ú¤¶ÂR<úô(³Æ§€ýáTÈÌÚ =Övujh›<ˆã›fr×N[xÒ '‚» Þ%§)ê:,D€,öDdt?F@‡(ÌgºAj>cÍt#KD·ºZ¥Ý5ºF×*tOÖ^MI¸SUJnº GÑ&kr¯ƒq´ž'ëØ@ãÖ©»ï 7t3RÏBšÙÖd™ÃÁ½Õ²÷H™Dü·/ÂáÈbô§TŒÌ‰ Q9Fj{;7&Feµ^gýgý/°c%æÃc{ƒw M»Ð²N•ín+ø¸âq£G’¬‚<7ýâØ%C b° èvB…m¯”4h™½¶mKtøâ·Ÿ C g€ÖPÜ »±«…î„æÜ)ÀCDbý鳇*>|¤sºD,‚h.’­·‡õêÕd1^plD 1ä°&ÝnT¶ï{À¦½MÃöREûfÞi?©rº.gݽW¶ðÖ»±ýˆÅ{ ‚\w7¦c K6næIm§<é ¼º¦q<°®Ëž¨ì°íØgýƒ5û Rƒz”&YÊ“b I[…Ó`O @r¨™ý$ÁMO¾]%¯=$5}» ‡©“gÀ˜j¦£ÓŒ`ØRìÚeØäð`y©˜T©˜Ñ0A1c fº,ÝBÇ /cE‡¼D /}pCB t<Ò¡bû„všáɸBøÊ¤ÌH½ 6¦“£*»~² vf¼ä² 6kÍbd†¬÷¢ "Ê5áÉM@8nä›iaگݮxG–^Ó›P« Œ)`,6Ó Á£ £Ï¡ÁÒ›y{Ymæ°ZŸ¨©/ÕP,Õ0¦&jØÒàÃfz4(–YÜ áT°&ŒV†ïîRþƒaºùÿ8Xx¸…‚²b€“pƒ#Íôæ’œßXjÑ‘R‰7‡é$2Æ,TøT = B²t „†­'²Ê.pN+ Vâ» °VÚ_Àö:ÇÙ|Üz&ÞóùOnÁ7ˆõE†äÓ:g?ñŠOc€^nw'´AåmTPe/\ß$øgO3>͈òÚqœÐ'À"p²…žGN€#Nìºp€ž-=§Ö BŸ™ßŠ_×çàÓ1`#,V,å‚å€UËÃðV%Ãã÷N/,– ËÇàX³Œ2¯c¼ˆŸÇðóa)Lò.dðbXK Âu ¿´„mXÆh”è 2í_ÁèÖJxJhB ßkU ÜÂlFÛÚJxW3<Ò´—ȹžÑtÀêd4Ó0Æ «›}OGúµ%ö¯cðX â719È{CI|¶”øuc ¼­$Û™”¹‹Áý°JlŽ_OÛŸä®Ö€Q’‹Ñx¬ÞÂà\IL¾©Î3¸Pb?櫈øè¬C.ÌbµÑ&ŒÿaÍ`|åìÓZÝÅ òNrv회÷$ããÊ}YæÓ;w”=½c:Îö‡™<Îñðòûác˜ísŒãÞ®@{‡˜iöépüöw³6¦Lì£'À„£þúέ{{ÞÐ|4øDï>}äÎ[ñ†ã ÝuÇC·¥·Ìl=õÊu¾WÏ?¿aÏ_4mZØf™]ÿÇî›üî–ëyzÇsÏý÷ͯýêóe·=¸íãß¿þ\ëÅíï¦7äî;x鯷ûÅ5{$oÃî»ûÇ—3ß{2ÐñÚóò?~ÑyL[<9K¶wÕ7猿öÙ–šBÆ;¼ð“¥ŸŸø×^ül«ÿî§µ77µ=ñóî‡/]ÓKåO>}ë;?z|õÿŽõfæ½ûåïjÏDþ­ÿb²þdlæù‡®t¶s×…ºó{W¾þ;å_ö´]ض‰°mÿü-Ë'w„*w¼à8tñvõLlé?ö“Ô¤³8qß:c^îÞÉj/ùàWZnòî½ÿòkî÷¦ÎÔëG^ýÔ1ÙÒpÇÂO(ËænèkþSîƒêK_î~éĆ–;.<¹u÷ìó3»Mt<ñ½W>÷~õÎkÏ/÷¤”úüÏž“{ïi{è§cÞ§.¾¹þõ‘†³îS·<ûÔË}Ëü©çRÿ¯‹wwJ?[óØí½Mg/}qó—G/ÿ¦ÿ©¹7Ÿ¹|¿¯ë¿þYìï);ùUðÛ§N×½~{õ¡Ç—Îà^åîÿ§þEíï¿ôÿþÝzwŠNá½?wÃåÚáÈÚÌ/½ŸÔüàÍ]úÆlj—?ÁÙóµ´J{&ÃðG®é™4ë“°R ==Âàü5½TÚ? F“býͳó=Lï^X»gØN†ÇÙ¶ƒáqþmf­Þk=ƒ±·»Ü+ÂlˆÁÒ¹«su ƒñ¼•Ѭa0ÊÇyÖÈðx?„~9¬z†¯cûéù¼ˆ³gÞ{*£Ÿ k£ñ²=âq¦U1<é0MŒWÝqŒ?âHrÂD!cm27zì¾ËúøG‹Ž>Øÿ½Ëß½}bt4².ñ‚ûßšFHïÌæðÿ’ ˆ(OrÔú½c Pç"Ay¶h&Sù1N4SÄð©1nú'…$wõç¡Î’IÎÝyãº][×mŠŽq3Vj ÚʆЀ֨µ„§‰È¶HßÀºÍÝ=c\ÅpÊTV­jÐâƒÚ¨eûÅcŒ+ ¯Xµb%âD35nŒ”CÖoÄq/‹»âË@û'‰1®¡~$;nÔ™ÑT}!Ÿ¨·~h¸ }ýç»F>=Ú1XÀúåþPK-qM>ºAÐ48rebar_post_script.beamU’AoÓ0ÇŸ“6]×–v͈à‚ZÓnS5NiË&*mÚ .!MÜÖMbWŽ3m„„Ɖ;BBˆ+$Ž ‰OÀ• 7¾v–i]¤_Þóÿým?Yoÿè¸  Ûý½ÞaO°¾IêO<î.Y"ÜÄçd)J>‹—$ÂfWkE?ÂÝÈþ«º‰Ï°ŸŠ[ÞrJ<%Õ«;|F§dVžaáFÌ÷¢Ê•œ %Z2×XX‰YÊ 2óÈ£³º²¯È`Ù÷[I®¾‘¤&)¢†Ö¼k!Ë阆…‘­5ûrœãlõTkN,ô² –Ãï•lx˜êÜÑÌ’ÕØ½Ð]èV_óÁ…y‰–Î¥Þ½~¢£wZó7 NS5,ôU®è§£›J°làDð±jb/UÜ–$k’²D:`]R‘h’;êÍ%h%×öÎní­åõjžC~F!?ã:f0œ¿…ÚcäºÑ‚ËxÿM¤*s-ý4¡Ù‚6àÃ÷î«þ¯/‡|þ÷âý§óÅb0¤SY32AùKl)£‰Œj˜sÆÝ$cŸ+ƒÁRBOU "!”õ£4ÀÜ À\—µ €õþ³áÁcw<<Ü ¡Þ±Ûm»ÓÞrí{wkçÚ´ö|pâGûG!TfDXÝnÛö&ö"ëéóD6Bq{³»ÙQZAÏ @é§y5¯è•½jÖ`ÂRîãZ­9‹q+ÄtAZ ÷[ÙäÝd«c»)çnЛ$B=üPK-qM>p´÷–{iÀÉRT–,IŒ­"®•ÊAŒ}jæï5ÙÂ×8Èĺ³šÑO Åaýîü€Ñ)™UgXx1 ü¸v'g‚Ä©–Î5Õfòs„N™yìÓYSÙ×ä! ±ìù³Ä„»çTÒ”‘©YOld»½–acähÖÀF®{ž¯ÞhÖÄFïê`»üiÅ­Lç®ÖªØæþJ?Xéö@‡Ö‹Uë-Ý[Ý‚úøZG_5ë o®¥Ÿš6º‘+ýtõ–lG¸üR51J–*îHJ’ IU"°)©I4É#uß´–k‡×ÿímõz‘CqF©8ã>æ³à²¸ µÇ(t£/—ñÙ§XUæZúUJó5î¾ü5þ~Éžÿ~<ø¾X Gt*kåÜ_Rþ [ Âhª#„æœq/Í’Äçï•Á`™  „'„*‘*„qâ`®ËZÂæ`<:~å]ŽN#höœn×éu·=g×ÙßÞ½7m¼^x£Ó£³j3"ì½½®ãOœEÞÓæ©l*‚òN{¯ÝSZIÏ @寯ù ¿ìWýzÞ`Ê2àÚ9Kp'ÂtA:):ùä=dkSÛ–c·ÜŸ¤B]ü?PK-qM>rFçŸÔ rebar_protobuffs_compiler.beammV}lgÏï9w‰}íkŸ“6iÒ\b÷3q|Î\’nÎ ®—µk«.eh‚:gßëø’ówwn; b­6Uê†öÇåCˆMb*hSAh'>Ä4U¥bÿ ”•IPøc¬P:&˜Ïk_:°ô;?÷{¾Ÿç=û9–E¨ûõÙBþÁ¼ïÔâ®"„&ú]ZÖÝRÃu|§Ü¬V½RÅ©7L‹ºB U¸XfYKO¤L˜H[wT+Y %ÔÇ‚J´¢‚E¢ nñÌ5Bñë ·úat’Hã–!PŒçiOî™õ„ç ä0á.„âo#îb!íoà£FÂî‘qÉÜåP¼'A¸kQyTYP ½&‹Ê"ân€j+ánuªŽ¶U"4ÙÓO81¶ÑOP‰F 8$Š‹2TÝÛ8Øn[yc NÛÆºmlNì:Ód(wµ3¤@9×îV“y#á ù^€ÕÔYáY™ÌÍÊ ¯ÍÉšœÐpJKæ`b½ª4+‘†`'ÒVWàÄ­0ðB*$kÅU,(µd¾<&õãcZñœKiÅEà¯ äÆ˜4ÈÈEYKàXBPnµ \Mí­›Ì°<ýíæp!…“Zñ‚ãc ˆ~wñi h9̇ƉÛrRÛ.t;x?æÄ!8âvè{'ô=<-â¨BòCs0‘ì—|¯”ÄÊ,Fò,&É1))?>.${öM-$!5ÏR_„Ôí´3Ò'*`‡qâtÅT1š“¶©“,k ²î…íÐâø0cœ¸“1PÇ.¶ 1Ή»÷=ÓÒ^(Ni'³CÓ 1Ïæ¦%g ag—(¤°¾Î½9i7,™%ƒ iˆ<>-¥q”°YùîA`Ï@§o:'1Ç pœÇÌ´¤â¨Jb|{8)ž¼ÁX óä‹EÈ ö’Er@•‹©"_Ld§B5'M`Ãþï.°~¾Þ`ßȦâ Ðp@4àÙoE,„½€¾@fü–~ °_·á‚¸Cq¶ö `$7F;|žù&>Øð»»;bŽý—*œnõ› úÜèw2 bIA<1ønáé3ß7À¥ÿôs3OÍÄyò„Í~¿2Zør,’WGê\yó Ê¥KÞÚÛk™¼ôð·æÏüùSÉoîùÇ–þ¸ãáØw¯þ4÷î+k?®ŸÿÅà×ß;ún)üúµÜÌg—^¾ž<óìþþŸüÑåæË¯¾ðÚ;·£Ü|ïêõû¾ùÈÀÔ3·Ë¿_šþÈO¾zbuç[¿²ž\:½éó»÷¢pxõåO¿?üãÿºÒs+öƒÎ~Æ]ûÒðÇîüáÏ ×8óÒ}¡\æÒ›ßyøû¯~/ÿì¿ÿ9øþÓ¯­uýúÎÍã>eýü`ßÏ^º±n~ ;äT‚ÿ6¯‰`6@:ǰyìì øá\°÷ÁŽÝo xv¾ú™Ÿ­Ìvœd6÷MÁ"yßwÙ>¿h1m-d |Ò³[76AàÆ‰OùMê—矻é}ÅxgyynÞ®‚nSËžgö‚ÓðMÇöÑe ©õîQòšõºî>Æ ºœ¦Ì+ˆ§eÓf g® Á´+VÓ ênÚ­š65jt†zfÏúDiaþÁ Ú<©f³êdöž’ºOÝϾu#ñ“s•æ8²‚"K¦¯LMeU½¬.·j:I]ŠZAáÜÄÔÄ$ãx߬ÓZW!á·zH—ô°Þ­G[zNÓ­Ð4•©9ušY¡ö²™ñÜJ¦õ.ñ¡ôÿ^É&à½j¡|ÙóÙ@ÿPK-qM>ÒET4rebar_rel_utils.beam]RMkA~'³É¶MC†ôàIXDAD›M?¥—MkZ"m*ýÓF!tÅ<Þ½h$ž#´X$,ßw¼ˆý&³yÐ LxN0(«1ÿÈë!eÒÇ+ §-1+¡!’«ÜdH¢äI)‚¬21HoÖ ±°¦ÃLð*N®Y“ƒ =$&lxs²©UÈê¨Ïጞç*_ZÜ&&z/AŸ-<§ÃÂ{±ØWZþ¡º-‰¼V^2oŠ$¤ž`*‹•ßÒq®9Nç,eýÅ,_̠δªËt-‹ÕÉmñXõÞ‘0Æo{N‡v:§ÃohòúûìÓæÙÊ­ó󕓯çÇüÍÏǰ‹ô ÀVØÛ¿ôÚˆc!¯Û/=5}˜£€¢ %?gÏ–“ñ¯wŸ~\?ßÖ[A_æ´´^Sõzxó0ˆ”P PbB„ÂŽßwı*(„I,×Äuy Ä]ÐyÐóÊ(L'e}0:Ä2G)̬´¶îÛû­í¦ å³V3j‹¶¹l®,._M=Zß³[íŠõzÍtºæ(õtÄD$M¹_š¯Ï/(M‹¹Ï†…®ü!?œœSròδ3›ŒÂDô˜ ÷ªÃÐgU—#^D¯šnöUtµþórOGn«7ü PK-qM>äé ãÚ Àrebar_reltool.beam…X pW¹ÞÕ‘¬ãµÖYye;±{Ùy)¶eKŽ"'vŽ%ËŠót,;¤I‹žk[Ñ3«UgZðs¹.̽ 7÷Ò6!}·Í-i‡@™Hi`  mJ§LÚR eèƒKdÊ´L{ÿ³Z; …â™_ûï9ÿùÿïîz‡wu3Lí£¾ÀàŽA5—aff?¯È±¨V䴚˥ñ”œ••¨*›õKA*j¸ +‡dÅK™dEÉ)“ÑdZNT–ΦsS¨BVÒÑì”IVr7›âi9šJ“ .ªÉtÁ¤dÂÊdUBN˪–£ñéÊø´O…²Æx.!›ÓÉX8‘TªJ'K‡¢±œ¢bª%ÍÈ8-hLU:M„ã¹ìdrÊHwÍÀŠiµ²0S«Å|ZFÀ™ÒÉ‚Z0§ä™Éd6ašŒ¦ 2^MÉ*µTYÌ&dØ‘–’Í’BŽnO¥s±hA,ÌÑXÚ´äQ7g‡¢JÁz(šN& Z4|áh>_0)\X>L­VëaÔh¦Jaר*EÙ AÈÈYµJ)fâ¿„ èØ y9Ž•\NC)È`«|Ç ê É\¶ Á­ž1ÞÅâP Z÷YÖ6|«„´¸ˆ]¤za™š§ÚYì&ÈE‹À EàAÄåÖ¶i-ô‚­õå®9‡_o‡ AHjiÀ³¹@§‰ðCÂ^ÒÊ "éÅy†ÑÅâõZc«j-Ð ¶>(ïÂ`Áu^~#(7:Ѱs›àx ´J©UúPC£ :ëhÓÓ¾õó›XÜ'HLÀHÇ'¶‰ósÝ…A²TÒ¬lÒj´Ÿ6ç…´ $¢7gÉä@Éä f²ò°†kÙG¹À0è6\Ö—j‰Åµ4³0|0Çi±.4‚ñƒ~?ø?´GƒÈòò!ÿ&?ªŸ•ø€“ßBøÑQ~7‹>?÷ù…‚“Å7ÆA€pCü0àƒ,"³ÃN ‚†€?„* ü,ò£d:Õ5]@Ÿc![ Äuþ€ËOk¯´‰ÐÃ{KÁntð{ИæÛ¦Å'®Ÿ·j£/( ꩞á- À|~in\„ÛÆpÛùmr‹G,ùãPF6"‘mmâ¢U's ˆÏr2¤±åf/é*Ëúèü„¨=V¯?P†|H$ dM”ÖµZ€È{ù­ «üéÊÃ㵬)À¿¥´ ó,Þ {4¢ö„=û4Å×jg™8/.Ä‚v?XqA›ÒXŒ²x›%nÑMt!ð:ƒ„†Èܸ†ÙýqÌã¢u|éöŠ´"°x»†ô°F(êO¶C¶ý9Ûb® ¦–]íÕåúC<r‹ŒnDüÔ^3¿“sð»X¼Së9ÝlAœ—h‘þÔÌhyÍøüΨnT˜==< U< U<LC‹^Éâ,î[Ñ |YœÒ ‚tdx£†·ƒi¯_´ýæ%¾]ÐdD¥+í˜`ž£q7A"‚—õªŒÓ—÷‘L®ì À®¢[F UêkP•¾ÎU—ñKtÞJÿÐyÈdªªÓ×—-Óù& åºþV eòme2«t~ ÐZ]†âY§óô|g†.ýÿºî,ÃߣËPÞ¥ŸíZ_†yƒ~–âܨ¯o"z\èÙÁ2_|e˜‡õõ Чë#eü°.OÏî(“ßYÏ]ºÌШnwh¼ìì§Ê0ì-‹É¾2)o¦ùeܺžôý°ÎÓ¿›€,ºŽJýªÑö¤ g 8zÏỊ¡9±[x©®áô¬ážÿÝ:qwò"{›úA+½x·/ð:[=¯´~ãÉ“Ï=—êú¶'VÛ{Ç_žò¼‘½<û­GÎ|ù½—/}oyp÷Ÿ7}þž¯ÿâÝé«Cooöþiã©Ïðè+WžÚòÐögê~1ý?Ÿ¿wê±+k~› ÝVøÍ¦#‘GÕ}O½pôß¼Q~qÇÞ#ìýñ½¾»Ÿø¦kïVÝ4òô™{Sßzïk×ÝúÑö UŽçޝ|þöóèá;¾ú@ôV4æúKåõT¯àoXz’m¾ëHÕ“~®GX{ÿÙ;>sñà_ß=zã·mÞ2Ýz굋¯tÎ]V.Y¾[µõßf²ý‡-ê§óƒu¯ž·oÝØðÃû#Ë.úês^ڼǾ2ð~W6ôòóWщ /nÚ½nðÄ>û“ZÏ¥ƒï|tõô·ï¯ºô…Éo»tæê—í½ßÿù÷Ì›Ö?þ«?’,7~êu«ç?ÿûëöÉ7wøß›ýõ‡÷$oœëü÷»~6»oÕ­Ìk/5Í9¦žœ©Më —´…{cí¿´ãuo~î©æÎÇUÞ»÷«O„ÖMü:9¿S‰ý<ÿ¥/íæ_èøæ;ÓG~'KÏWïš\ÓñÈ™?ç^­ŒüñöÈçŽNfÞuó4ܹüåµÌ©+ßùºé–—\þâPþüÝW/9î[ÿÎ{þs7LŸ;r¦ã‰›¢¶ÎÛF/ý×–4óØóÓo?êØúÆOjjýý¿¾õÄ›Oß÷þ-ÿW­|çÈùæ‡Nˆ…#«‹?¼rnßwοúò±:ü…ÚïíÐÑNþাØÚí¹8­Ñ3Li®ì×ë/ ´Gç÷•Õ?­w¿^ÏC@zMÓíÓy/P‡ÞûtN¬ÖÏÒëJ·µëòÍ@-:OgUƒÎÓyV¯ótÎ-|ó¨TU…ê›KÓÝiC‚A‡ Yí&+0óø¬:å+„6d.³·ð;søG²“°gÐäTÞœËÓ9ºP‘`xí+d¸PÌd¢Ê ¨ÈÕDRI1F9–ÌÒ6™bÌÉl<]LÈ æÚW¾i{‰Ãù&F¶…ÇGvRÌ’gw·³§Ûvö:½®Þ!¼Ç ìÞ•bª¦’ªäñt;£1ç “þ.ŘܞκfT“yº"Æ0æËQC”š¢•Q‹°+*q9Å8º¦s¹+%g$» J¼Kûêx[øØ)+é0@c•ñÿPK-qM>£™GŒÜrebar_require_vsn.beamUTMlEžÙYï:vš¬H$$¤-F-B"^Û)QA‘ÆI\×Mê†$T-—õzwl¯íÝu÷'j‡‚§(*BHETA¥ªP„Ê…S{°¸p@7¤  'Ä 3ë5¤#}zoÞûf¾7³³ïÌ…ü÷K•òù²ïX€Ÿ(fS.ij®ê’+éuÛ³EݱfŸÄH`›þ”Þ!zOÝ&®g:¶'‰Äõ=Æž­×»e¶Q›øbDˆÛ×ìvÒÛñ|b©¦Ýr8— 7°c–æëÑvB3H3hOŒ¶é;mD‘Íßì{1­é¸þôX×ñL6ɬKúDóHÒrŒ OB‰iZzd–ƒçéY%0uŠE J\úYÊ‚D Â¥‹2ÄÌ]çÒKlLÉ®‚ÞÈ`”€ßF¢D£RóQ‘•!z gñÃàð]8e%,Ux®TA¥®Ê™ÿ@¢¢,~¯%ä*(Ç’U‰2†»8‘Í„rY”âS#½,N<õŸ`ö Áýïà'Qšm˜+â Õ‹+Š žH‡z¸ºŽâ2–áýs~Ç¥3þˆÓ¨.­ÃßÙT‚q £ É ´é»[ìÂjÖ€ÙK"…YD1A‘ €IŠÉ(.EwÌü4E†‚‹ø³ìs•«áþìñ3Q^Š|6¦¢½¸ˆÃ±fúlí Š¿®~¬7 þÒN,¾(¯Þ9-ž-¶”}åàäÉ™ë×gö?S~~üë~ ƒk¿Í¿™YÝ+mlfßßH®–Þz˜ø¢|üA‚|^Þøsçb"&¾ÞÆ{ÉÛ²·I—Ÿ~›¯ßÝýPýt7YŒkk¯vßèÆ¶n½´~ëå÷*‡¸^ï6¯¼pgñ~,œýrå2õØê=ZØš£oEçQýÌ eßw©}þ>‹t8 ú´Ã‰-ê7ß>siøÏ9¯ps°rf»ÝåšÝ¢9!äóŒ/:Ÿý–, àq]ÇU½À²4w‡'ð Óíž4M›E Ù¢iëýÀ ˜lƒ´L›Ds†K¯ÕÖVÔ­ÚùJL•BA)JªrJ9]:5&Å/.oªµú™ =l›¾¼°PP´¦Ò kŠ@ÄæçæŠ,Æû¦E:B“>œ4N;¦Å´ m2,ÐsW'=Ïw‹ä{ÄîšyÏÕóaøß;Ú¢æhoéPnz>{ÿPK-qM>l(»çRHrebar_subdirs.beamMSËnÓ@½ö8¯&¡£¸ –e„’8I«–ݤ%­"õÚ”%®cO’ñc&ò£Àº[¾oà#Ê‚™ÔUkéÈwÎ9¾÷ÎøÎÁéY‘½Ñðx˜‰~J4i’5zéLÆÇ£Öûv¯g÷{ÇÞ¶_ ¶ïLÕ×ûçÎøäà4„úœeÖÎNÏv§v°êéŠ&©l*„ÒVg§ÓWœ‘±˜.ÊSyÈ]Ýmº%·æ6V ¦"O<ÂóîBÄ´R°nšxÝÕHßGwW¢#‡8NÓLôPK-qM>'ðênÊ8rebar_templater.beamX}tוŸÑKÃXÆa¾ ŒãFöØ’±elx¶, ó 6Á„Yc[¶,93#bNNRI6›Å[Ê!!! ‡¤MÛs I›¶Û¼´Ý$Kóµ›²{J’Íöìîa—´›´%g“½o4¶¥ûÇúœ+Ýyï÷îýÝûî»ó¬ŽM[kf–ÚnÝÐjf‡ý3Ã0{fèZ<¦GMmx$35]Hè|ûb##üÄ ;Id3}©~ÁÐÌh:¥‹ml&›Ô¦§S†é›Xa85=Ëô;ªª©¬³/«ÇLGvÈ™_Q”Ôâ¹þiy³él?™¶7¦§bñ´fQS†kHÛ×—Ê$¹d*a¢ŒvW‘¦ëY½8¿(g¦ÒFQ,žÕÍi¹LR¤–,ê‹¥ »+¦g„>ÍL DÁ†á2³Qj±X$4¡’¾”ˆ%´¨f$ôÔˆíKo—ý„'G³éd߀A#9³x"Òh*YJiNš™LO’5•LCS㎬á„)-³—§æ2±a̦€2ÅZ¼–š5´©1Ü“.“)}†¡¥µÄ”7>3,SÓÒÙXÞ G? Çö£0Ó - Y6Š 3«kŹ‘$µfXé*Õ5#›Þ«Eu-‘ÓÔÞü¤µµQÈb<•‰éû\PF.mNÏ?Fíôò°ãQ#Ë8Íì–1¸að´l—Ìf4—®íÕÀÿ4в˜Ø| ä†º[¨;t ƒp?œ3Lº;Â]z 8Ò\ô#Š )öçÒ1]?9ÝJgê9MÔF¹©M¦ÁLQb`8›,N @=jQP5ŒÒ\9µQ«Òú ûQ s¹4ìh¦/;ƒ–IÁóßͦkVøÒ‰Š=jM­Oõ9S4 ñrß-ö»F-Vøn],7€žËÁI Ì÷Ý¢FÛ—Ë®Ìwã¡«©+0‡;±2Œ{5¨"“ÿ{äN¹¬èð,’YÙ-Ëy‰Ä‘#‘:ä’ÂIÄ‹ŠädVuxâ2K @⟂6;<ºÌöNŽùŒcð,‚8øšID8T¹dFˆC"–Ê0ø`Eœ!ãÈÃHìˆÃó¶ÌîŸN¦ & PI ˆÔF p($¢Jä#äRU€xò"8—ßCMï!¹ 1R"!¢HDòTÓ2x¬%%A JÀ >‹š.Ná«.JB Q8³y‚:,[<ŠšŽ ŽJB©HÔ°â@áà"‚ê%©å%ö0¬„¯§«."a®(3yÆ›%"Ì£”ó¦Ù3”â\â¤Ñò²ÌzÜ/1Œ,»°ª×Ž˜À çË3ƒ­¸=2öJ¤Ñxó+VÓ°óH8àW $²9 Ô@‡ ç'^˜ ‘ ‰8º «E½x-aÏ­Eì¥5ˆ½âð2Ã^ƒmîgè~BÀD(·–:¬¤ZÛêRŸb5L¥ ‹Ò8Ý AA¼|†ay ò%`q1(ª²½…’G†0›hÉÁ^‹üì ^ u´²°ŽVJ㢠]z Ôx>Fð°’ÖTóZ…å[ Ñð« ä0 ¯v‹²ubøèm¼Ç’ä"üXÍËü\H'l'¤§ÕMÔŽ&Hª€îþçAÙ/ÇmÞï­ÂЉY¾ Ì”Uá¯Â¡ü\ˆ6ä»4´áhüLú†jÁí,ºq¢”N°|;´Ç’ jLæçqÂ\Sæš›ßü,ÚÅà4‡a[Ǽ†g#KÐø×ÐÐ;!œp¾×6âP— #ˆ{Í ÜC÷hŠ7±üº¶s°-!QqÏÁ•é”P‚× ›ð–_O ä„–ÍòÜ#O©œ@ï:‚H—]ÄD £› $ôEš‹ ÞôwÒßY@?iÑŸKé°üF˜Dã¤ÂOPü!ÒUßEº­·Loš Ö–OMÒë6ãÍux+4§n–ßìÃ=GÜûÏPnG$rê̈dBbñ–[2ë`†Â¦Åne·Ÿå·üì`z+õ GâGº¼$TAü‚Ú‰ÔMŒ$9eB2Zobú»Ýù÷g`ò¼W(ÄDœŠáÜtÝŠ|*BW ÞÆò]Ëñv4Þ‚w²|÷ÿËëînÿóîX~-QÓÛEÚð“nX"ɉ o·rÂòÛé `€žDôà^y?éê&¡vÊM© —%ƒ '襅/›¸µÐõ@©=DïÝ]´ÛÁz(ÕÜ Í«7€ïè²ïrüÐ6!²YpíˆÁ· 7·0Šðó©Å`±ñª Ím'­ù]PóÛàa7ñ "_Îò{èî(Í Ê<¼Õzap; Æqa°ØŠ$Î~+.¤'Q™¼Q·Ô%‡ò/·x÷Òœ;ÀD²kÈ-‚Þ¾8)nοmü0h¯Ñ8A×ôÁš;`M#„))Aœ’š@àÖ¬¶I \/í[/+ôu¤òUx »ò· °ß?a¿¼ÀþÍ ÌA;I‘‰›Ì`÷Q§Càt7´‹´[&ôÖõã÷®cl;\…%/²úí0 ÷½L#±ée^è©”×&ÁµƒÞ9àR¤Xw±2ãPÂ^E #E‚7p/·/å@)æ²yJ– àa$!¦ËÔ»é?Ã#ðÍžu1RâáA¦ÙºRlë3ìÿ=ˆD²u/ÈLû’Y ³m</am}¾­S_ m Å/²íP¿n³ñKA–ÙzÈò‚µ>[§ãµ¶î ø]QÀ³±À~“¡z³­·€¬*ˆ±Í´ÛzHÄŽc Hض¹d¡úz[§|: ¸m)à¼ÕÆP_Ý|n¿I§øž‚½ vRžáQº–/'È6{]ÔÖéßn\·ËÖ¶8ìXÒ‘ËtìÝn{>mÛc|öß×§LÀ8`Œ;9úäÑî-ÙwTñ­ÞÄ‹êì8?›œï»çö4”?v¡rt§z}r~ìôßID~ðÎóÇßw]ýO~¾Àé©ùô“W~òŪ_ïö„Ùá W½«×½éýtùÁKË®¾}rL]0nd³žýèžð’úŸ?¿ú"»Êù‡+u‡7œÝÿ•sU ³þÀئ‘3o¿ÿÉ#×{ùhù›ß¿¯>uâл¸\?àܺ®flïò7Oô£Sߘóñ™¥~ôùLJî>’ÉäÉÜùÔW‡>xòë_¬½x÷s£¿ÿ`—l~ãþãKŽ æ•5¯üÝoÛ4ß;î9Õrâú˯\Ý"í¸oæß_Ùôêaÿ ÷å׸U­W®ß÷î®ú //½´,>­¤øt¬ùÀ õǶ,r=Ú^þoMW.Îø‹o~;}~Ϙï³ݳm“ãË•×N_8±gWð›Û¹;_rÔw×®øhþ;¯[6û½úÙøçé7¼Omo7¯ö<¾jûmç_üã{áŸ{æw¯.ûÖØ/þñÁO=¯ý¯ÒDø‰Ö3™ª|átå‡~ö×ëz‡¾[òã‡/=±aàê·úüÁFã•¿ß1ýDìõã+žóÀ·¿ð~ÏÀ©®Á—:yáÑŸ½c8öÃÑþçò£ïßsìWûž86dT>sµí­}Ï~Ýs÷WÛuŽ‘±{wûå‡ÚNœ=®•ûÿ!4üÚõ·œ›=îx~$9ÞÿÈ¥‹Õ{óEÝÒ“ —ÝÿôåýgIýâû_¬|ørlãÂÖŸ~í¹G2;—Ïü©y¨jÝ®õ=¿üÉaß3ó^8ÜTÉ=ðIcå†Òß^x«;Ñqò|ÃæôÞûÎó/íyØý·=GÄåé‡Vwün7÷ëéç?|õ¾Üc};¯®þößdúÖg´.ÿÛ>Ë{ìúÌÜT£wØãý ;l= ²ÝÖc íÚ_kŸMzÞ[ Î2ýe¥=°uÖî1AC{Oƒ­ÓþToë´ŸÖÙº ¢Ú:=OÕöš²ÄÖi«´õ™özÆî ²­Ïh5M®9H#dIí52ÖCFdžºðƒw¯JÌ»÷¯^ø…³ÿº~p0Ô™éƒ9ÎÂsïÊŽ˜©lÆ Î$ƒ­Ÿ`£Fnx8¦ï£g6g&SúÃiñT†Ž°©!Æ•Ê$Ò¹¤–d¦~œ@0—L2BÛ¶ÎõíÑîÎ á!fFZ[«ÖÕú£j½ô×O€øÛC]ÑΛ†˜âþ”)74Ôª±¸:hq¢?$©!¦(PÝP]GÇ835¬ 8ãШ.Ç1+ŠM‹¹-‚F6§'´!ÆW3Öj†´Ì`ªÆÐ5ÖÉSÚÔOàÕšžl&MâÿPK-qM>G%È”1 ¨rebar_upgrade.beam}Xpåß»ï.·9²ÉwÙ ùG’ {DàÙäÉ‚›»G…Jtlµ^6w›pÉåöÜÛ‹¤ØBEhG@ÅŠÅŽ)m´ŠŽø'8£¥8ý㨌ʤÕ­-&eJUK§V§ïÛýBNez™—{ßûÞ{ßû½?ßf³zà í ãĺ®ë2´†±?Ã0ÌZNWû=QÈ êJJŃjVÕCm¥瀒ɫ8§«£i­OèjFUòj™e•Ô²éA÷ j$3Z¿’™C½éLÞ©ôkºQ¢ê%;h÷ûI-¥²D7§›íÚ0›§¼ÃÐ ª[/dÉÍjr8ïHgÔLº¿$O¤Ò:K–YeDu ié¬}åJ´²m%&Žh4 s“h¹ ¢|!c üXÁniN×r™tÞÈ—d4m¸ã‹ÍFU=ŸÖ²ìéL*©è)»®ºt5—Q’jy:«èc CKs5qV”Nˆ¾P¹1§u‚’˩ٔ[I¥LTy¥Œ@‚H MËäÙÆ=¢ «$†BΩ꺦;Sja°ÔJ]FD@sL¥|ROç Öä Ew÷kš‘ 8ó– ’Sf)ŽdÒÙa$›(ºÔ-†®$’„m¨ C—3™Ñòª=­• húˆb¸’€*[ȹ`©*Éͺ:¢š~†®ª˜®•LÆ:vΈ–*dÔD:; UT­ëZ¿¬ÝÖÑ:PȶJ­åà=eÊLÍÒYNR“†¦±$‡ä`ÄL¾=­4¸¶õÂD¡†}ú3ÖgÐ2²¶a{å|Á&”Ë‚Ìå^Ž —Àø—¡ÙÎËq±–m’äetj(†Â1$`Gã ,Ê¢/VšyÙ –‚Œ.F’QTö‰²——9ˆähÐ!s^ M™2ä¸jÂù×@}‚CÞã§È>æs_„Å. ;$N4­a…–aqQžB• o“× ÛF{¥ ¶¾ò& ÔíÂ!ÄX·]”ã˜sì/€Ey‚ü`¨€Â!<€ʼ/ÆÛ±¸@.Ü'#/õàý’/ïñša¿C€‡xðÊÝŽèþÂqî˜ãÌuóH&ž¤Ëž@èë¶„2ïñÍŠ·{–x#¿ ËÅêTÞW¤Ž%fµ€âÁ¸£Ræm9HÅvHE5¶í+ØÔï M ðÄå`Dÿ?Õ9!v‰hh"ž‘ð&ÿDÔ]'o‚SÙ]ÅM¢ð$’gL#Hø'yw=–drªŒc‰9H·äH·`Ûã£Q°,ƒ–àr|;Or*x;Ž!;ŠÅ÷!ø5Žø˜ƒGˆ³Ï…tN£.Ä‹ÁiÑ´9r¹§xœÔ»¤WL-$ºðI‰¦gHŒè ÎeâÜti¶I?ÂÓEð§þ´:žÈÀOú§7¹ÅÐt2<"I&IâÁé(–ö¬ùø‚õ4@»Ð|’ÅÒ%´]ª–;8ÏE®ÒÆzd¨²È_/`[ÉÛXÈ6ÖËÉð aRdÞ UV‹B«E­V³0xÁ´8A¾™üx!?¾"E'1X6.ð–Þlo—p:ÄU¡05Q\?eV(þ ²Ò } à ‚“—3oŠ|1/ˆŠœF/ÑȈDÇÇ‚e²|Á…Y Ç )’!¶ RÄÎè‹[ÍaóNÄÐ2/ºdÖâj Â$YeÄ%\ïnµ±5rœÅfµÝK‘Kb+ÁˆÔ×%°|ˆ«£Ú¯Õ‚‘ç FN`½!®ÌêgÍü\½iV‡)&’¸ØJ«qÙzr§`1â@ü e’àq@j@ ŠË[©`«ü\#šÂ}LÌg§e¢e¸¼ ^«.ÐÉlmå¯T·¨z¤¿ˆx®å|;Ùgçšz$é–®Y0ø±ŠC·é–wÖ‘À˜}ÐÈgú ‘· ÔH Ô;±P…޳Õt<­áɽ!°Õ~®Ù¼qRÅÇÙÚËy­ ( 4;Z\3OtêxY4o*p#±uÔtœÎð¬ÈšgÌÖ›ËË—[Å`çAlÍ$Ðùè*˜6±L–H%‚d„DRy_,¹•cÏgÈL5D>:DWš ¯ååÊ›0}lÃÿ?RæFÂâñÙ9 yÍy 2ð%#° òŒkñs>3­u³+³D>‚| —! -ä9„HjT"p mìU°Óݹ° “Ûu<䬔ÁV„±±‹åJt=fm¬ŸH`g i  l“ma7xXZeœ‹1^¤0 "Bˆk‡Ú¶×¶Ÿ q’:è) ¹Wû¹6Þ·¥ùÊ–p+ZOý…ðÅbv>ÄÓf±5ÀJ‚&²aÑN°w@|ka(c°ÕAššà„f“¡÷’?dzFrðm{X¨Èäb)_ ä¦ü 2úwáËl@ JÊó@^ÊÛª"?s)_TKuæ5P9ñÓDåP3¢¶ó©œØ¶Pý«€R9‰gåý@K€@m@õCäíÔ–ðEñ‹ü/£ò«–étR"é„©¯ :×­,ŠóÚ¢{â‰ÎÃóÞž|ú³“·¿>õé©?=ŸX³Uÿïóïî©r®Û™¬=pnèßö?™j0™-ûá#ã¯>qÓ:÷]óo¾#úÆsËŸAŸ´}„–¿sð×ïøà¾³ûÂçþ¶5u±£½û•U…Æ×^«Ýú!‰ÞL-léùQ÷ª§Z¸°­ûq|ìÛÒGZÖŒ,\àš»ƒƒg'—õ\,¿ÿŒ+~õÚÕó¶ßÖ\8uÛáûËGë=ÒÚ·÷'ß™ü¬ô®ÇÙ£á?7þûꋟïÝséÎÚmMO·:~s÷k¯öfö‡÷Æ^øë­w}ÔòÔ‹‡ÊßëÝ}UãÑõ»&W®»gòÜ“ÿ_úc|,wcç7w®¸ôÐÏšnûà_[œ:^,g[w>öØÚý·>–yóãÂÐ{§N}ÒõÒ¾éw[*Ò¿Ýß<öì|®2}³¬eŸxy<;À<÷Éùã þaчeϼ»õ¦ûF÷­‡ŽçêÊÏŸ9x⟷±¥ùÚ™óÇϬ¸e›ý쯼ýá­ÛïÍ]³áž¯+—î+ìÿýK½žÝÿýãé[}ë@öØèÿø~|ï@ùC|çoMü²é7á{j†Ïmcæ´•ÂT¬×’¤_Ƹ/õKqtQžô¡LuÈl®¢})Ò›™çÕo(êÏj tVɽ᣶ä}«‘êpTof0•—t†NÎß‘!»›í)æ³æ"‹™UKüAfm£ýo??:úÙ¡uCCÑÈ%c³›ú¢ïÒr¼‘牠$Åpæûq"_—q¢P¢ x9f*¼¡‰-≠ÒÙd¦RSLi!›RÒY5µÁ^*Ÿ#7ö¬ïNôö\f*:¤öv©£=–I¡À²%ö¦è¦DÏõ«7 3sÓ†°|y»¤ôKCfLôßÃŒ3¸tùÒ"séusI?\Îï+v…SœJ©Rf˜× zRfüm›µµmXÍ¥Ûòz²Í|¿Ÿåfþå²ÞÙ‡ xýyƒÌþÿPK-qM> 2¦T ¸rebar_utils.beamXpÜv•—VZ¯V²byµþ'NdïÆIì8–½vlÇN¢ÝÍz›ÄN8nÚ¤ÍZޕ׊×Òž¤S˜ÌB˜&´P†)Má\†”£ÜÍ”æÚ¡@ å Sàf:0¹^‡×ûñžöëf¹\gžôÞçû¾ïû¾ï½ïû*;q÷á~Šjº’Ê$§’ž½LQì)Š2ǘ×\Å3Kn¨hx¹üJ]0KFÀ^ ™nNwò‹Ç`œŠ\Ö½übȲý7ë9#¸ —\ƒÃy¨È­ØNÁ5ßcÔNI·Š‚û ëË9ÓZ°éîÓòŒ¢áä<;W2]O°½rÎ1J†î2ÑD+¦g佊czzî"‹“ÃU/Kv‘ —»ŒÜPÞ^.ëyO4Çvr‹ºU(Ný9¥—*Æ»â•+Þê€X¶/çžgZEwïv©TUuƒnY_±ÂvÙ°r¨ômJeÜlζr+¦U°WÜ€í²Þƒeƒ_9‡‘rCø,™óü‚]Z…,{%çz—×K†Uоd›óÌe£ÎÄýÏ×-ØD2XÝÈBI÷<Ãâ Ë…­ç ¦Sg§a(¨Ïƒ3ì¢^‚]ºyÇ,{9\§Ä¼Ç,³y»`ˆdNÉÖ F!è6.T¬¼g‚ÛÆiÜŒQ‘É ¾ßÆi#_ñôù’Á¡¿–¾lð–î™§|v L‚ˆåÜÅøUä+®›)@0Ã:ÈÖøNaTü 58$ÌzW!I94à«…ÀLɶËlA÷t6)ðt¯âò~:ò%Û50 X¤F‚–mØ%H˜7ôeY¶ ¢’éÕA\!ìIÛ´¸y(t¹~Õ€ÅÍCù‘)œcÛ*ÑŽÛd,W ÒFîOB2N{”QÈ/¿S‹ºu®]qò†F*%ïᬘycïÿk®/Ñ áïíïýóãjïÇЫóW˜Küs½ ½þûú‰ùÖÞ?Í#è¿ÓÀàî4pÇ5½ÓŽöÞ:#}d‚Ôë.‚PÊÇO¨ ¬öRTŠ˜¢xú‘DUÿ.-)´ˆtR´ROQ!Šbv1JŠ¡ä#Åz†ä”c"”L«w1´ˆ–èézIÒ–¥>«e©˜ÆÊlH•ÔóÌs¾E{¿ñp…žÓžd"’L—µ«þûì~†¾ˆ¼@ÑO¬Q(í{LHRÎ%õ} pšÆD5>‚˜Õx9ø— ÷FåÆhH™® Œ¬± §L+ô•@„oRèçEUSYMŽƒ…L<Àd¢LLËJ²Æ73!uNË*²gã`"$•YI450¯c`JH9‹«ÅAng|AÖ¢0µF ìàÈF‹æE-«Êè‡*M(±,¯d㨃yOh˜†n²ª80ú6³óí[ÑSß–Çä·[4¾óû©_Ð×µlì2”ˆ*Ó7ðqÃAø˜DsÕÀ†¨+=b„ÉjZvšoâÛ@ºŠ.eç0ZŒ_Ðl™!œ0ÎÉ`³K¡¹h½¢h2 *RÚ“1I@´@öÊM? M ¸•¢¹f¿®Š-ÌN w7€ €¬¦d*‘’¥tJVfŒS¥ççR1*ŸŠIn*¦œËœƒ$¸ “ÉÍ¥èéYðô'Ý„•Z ’¸VXV‡×ÖSRHâ¤Q± Öm«)=±Mæ;áãûµ”_‚\›ÿ\SÀóõõl-æ§´ÓÏw#ÃI\#,Ñ*ƒ*Ím¨WU‰küF ’ KEzÄN&{QãGd­?†C!•“U±êWìhÑž7^ÁüFHk5_AUœcÊ»§rQ:0y¸›¬7»‰WwÓÔ#nb®úÎn±YË>!¯–q'SÝKLÙ S6Š=°ó®š²» nÄ®–³üq ¯‰[ù$PJ즹-=bWìjQò+QÎòíY(YÌm]E6¬"ÝPŸEe^· ÷€yÜiW˘ßƧÅ^0½æ¶ÕÛ¬öµÛ l/N߆õÁföBÌTIS2r –a Ö³W˜ƒ ×Bsý0šx `6ü4@Nh.Ñ"îbFÅqØýxm½CiǨ«ÔUZÇc qÎÑ„8ÈgÅ47ZiÐJ+©45“JKùq8ŸÌ»çzÄa7œé\òÜ#—@z$\éRòÒ³×@z6lƒt-yí•7@z%ì€ôFò· ķˆ‚”$¡Q€:}[B$)DYˆ"$‡q1!š¢B“ÐŒPSx¡æ¤Ð,´­µ„ µ&…Va­Ð†ÐÚª­¶¤Ð&¬Ö#´.ì"´>)¬Ú… µWØ6¡a!%)(B‡Ð‰PGU«3)t 1!ŽP,\A(žâÂ&¡ ¡MUó]I¡KØ,lAhsÕ‰-Ia‹°UèFhkW‘ãM»£âT·&tÇ¡j[inhO´Ú?%nm¸.–¹ R!é&©€”_~=ïX-ŠÎ*͆ÜÍŒÍø¹Û/ŽðÄQšéÇa1lCÑØèùyhˆ(Aƒ‹âYó=J”²ÏË0ŽM.Š7 ¨ß®»³GKÓ«VïèàXUCR§'ÝLû>Ž·Š šÛµŸ»¡P'ÁâžúêU„7×6"jL’‘¡#a#Í^/(¿÷së´ì 8ØÜzh;íÐv4ìI0·$—ªö‚ @Éx†ŽÀÐÞj£/Î‘Žœ½é·d[2 g@mÎËé^p^²œ„÷ Þ §ŒŠSph¦j[ƶŒ©-%ÂÖÄ4—§bÉX" ït2˜÷Lr&Å;'%áŠSî¨8™Ø ¤¤“JHÐ'±9LBs8*ÞÅß+îãï÷ÓÜ]’ªàÕÇfeì‚~ ì÷á}$³ÅrõBö¬Ÿÿš‰§!1æ€v{>öý‹·¦>ñWN=àgnr?¤l {ðAØ1ˆïÝZ„9(q47„ò`ŠÑÜaïp&þàgAzÑ= æ@< C÷?ü}Õ¡c êPÇ%EÉ0~»» yØýZ³Rír'̃^õdõæ*¤×)"¨Ïƒh€˜÷ƒé×  Z€6DïjhŽl†ÃY®‹l“¤P™(\ë è.€î"èo9³ îš#âI +ÉÀ·™$n~7¬øÝƒWËT? NŠ‹0>þf<ç~ î[.Û~Ø.  ïÄ:Êÿ.ô±5@ @4á%¢‡|c %x P+™»¨è ¿žè ¿±ÆNáã@›ˆ›¶ºz¾ ¨—èoê#öQ_­ñ'Aø@Ã5ø(ñm'ÐáqÝ1¢3´‹ðH5~ÞUcg_þáÝMôŸ®™{¨Fº†Ÿ!<úsѪñ ç¯Y÷8ÑÁ±/®Æ$ssJ}™äì?DxŠøw„à{>4Il爫Æf¬·¡&ëkâùÜJì7SÕzB¬‰&Â×Â?žªæ•&ïÕº LT,¬IÔ€ÉX‘ŒSô™÷jðÊÔñÐ¥’Ò¾3ÒgÍ<ô/+¿}ç7?þç.<º×{Åɾyïõ#ŸøÒçŸRž¹~þÔ™Ÿœ™™ûÞ®¥©ëÒÝ+m85½î¥4ýã—ÞÿËCO÷|³ò5cöÍËö•÷æ@ùPóË/þëç6¾a\¾Øÿݱðcí™7QÛ;üÜã¿úìþ/ïj~àßÞ¾|ú'á¶–æ¿ßzê­Ÿ½øÔ‹öÇž9ñ©ÉÃß:ýÃgþùÏFyö[¯?ö¾Aæ¥bCø8S¢óú'ÿ…Ÿÿé+Ò:~ý?Á+Ÿ´þ;þÚ“ß¾ñ>ÓýŸßHæ_ýðß]¼ÿ¹ž™à_{úÐãÛ\ëk,óÖÇ?pm@ßviýÈ\›Õþ#*×¾;ø•®}Ÿyé#ŸÿÛ¾¯Ÿ^ùÑc{?ö7P“vký:UíU&‰¯ùj«¶>jk¢¶jk®¶Îjk¢¶js_›ïÚÏ;@ÂãùÚKlâùÚMÝêo1Â7&=Ï÷–s%DŠ9åZ¾`ITæØÍÃÝ©o>þ?ÿ»þ‡/=y2½ÏZÀ©¾>‹ú!»Œ?d¹Ô(òSŸ[Y^ÖQ¡Î®xÓY¢XcÞ´¡Í%*dZùR¥`¨pÅ* ¦e+(>5»oroîȾ©ÌÕ0 ö÷«ý‰œ:¤Ž&†V•¸{Ò3¹}'î^¢„¢é)ÃÃýª>¯žô}:e8.8µD·o@ŒÅßöë â¡×õ€.êA=¬×ûVIZ¢¶ö-ÚËFß’a4û\'ßçÿ¬y‹«þ »ÝpJ'“ó®‡çöPK-qM>IA¤\ Lrebar_xref.beam…X}l#Gßõ¬íÍÆs™d}Iî#×MÖ¹\›K²ŽÆÎ]îÆvÇwÉ]¸´UR}k{8ñGº»¾"ÐÑÓA ´* R‘8Q JU©Hˆ"ÚòñGÿ*Ðò´ªEˆö@üAEycOsj“fgæÍ{¿÷æ÷ÞL<·xþBXz’éÄJ­W}(ªb[yÓÎ]±­’Ä>^Ç5m×Sß"Žåæ*å¼mÚWsÛ¦»Ùrî²i×ʵuÇ[2+ŽhYêµRy­[®Rvr—,;_w,?ïå]“n†X´Jf£âb³XÌ˶UpëöU©P/Z2˜7u·@n¹âø™°p¹(—Ê«fV-i³^®ÉÌš©J®Ý°º›6¬Â–C¬+ÛuÛurµº›k8VÑ[);®ã«ZÕ¼e6jà¿\³Š¹R£VpËõZ®`V*ŽìpßýM˜Üí(~³fV®>bi-Œ¿T·-³°ÑÅöÓÄS!nײsæeój®¼^ƒõ¢·á8ªšÛþRÅt]«æÙ*ù·¬«Y ËÎv”«%Óñ”ë>€¬š®Òê˜ÔW®³¼tqIÉ 8fÉÊY«jÕ\ŸeWÌÚºŸO¥ôƒÙû|y³hÚë]í°{˜'†•sê »`õ0–ëùMÈF®™Š¼eV™_a£QÛr°™w\Ûä«=¶y9×–\ wÁìr¾áZË’¼ËIwµ^lT¬\¹Vª7=ṫ&n a*‚6®>2áµl»nßIoú鉡рÁÒŽÜén­5BWÞÚ0/•!.Ïøø|„¡ß1ÚÖ~öµ››ïbÅ’7¡\&Ú•2etø‘Œ8NpJŽMܹîÚ:þÿ÷œ)ð-òÜDhýÛvZ¿H<}#š¨í3E!:‚üDˆß@s7–D‚:~CMJ†5•­idüJÒ¼Jm†ßÐ( úƒÜ$‹šžy>ƒÒº±á+™`ZGjo°iFiFh¬Þî.6!¶™†_»æ'O‚ ¥Ÿ**Ͷ•*ƒˆª’_»i4Ð Ô JÿŒ ÐÈ3"¥’Ú+Qåú•ûmK\•ÞDÞ/Ò Ú1?y®å$‰úUÜ>ƒÄkKH|ÒÓ§ ñf@À[+Þ—â/ ¹Zñ&ÑÇ_P“T¸f4UÒð Gy^„»ˆøÚ>‡vÞAsït ¼³‹°L‘´.@Ü;Dðk¯qœ·çà ¢LhPgtIªWà D”{Akú¾}$(¸ 6ȳ~ò6ãLB;„øµ[~"“ÖLÃ`¢‚éQM”ƒ¢QU§½*7äÞ8ÞæpG¸¸_• Þ>¢Šò~˜!›zZ³~àM¤c€4ÃPé‘8Ðç J“:‰&u-ö; Bl¡8>." ªf×KZò t¡tšM…Ú õFiÆ å>Ø4ìÌËØåQ<€€-á %‚ÆaS‡ãø B.¶¡“H‹¤#ž6,ÍP©ÊÀ P<Æ`|$އÀxˆS0&`¬é¬œ[F«FwÑ$lZúNIx¸Û+‘ ¡ Ÿ–âxpF:Q•0ˆ–]KêBDeš*‘‘#ͯ QˆÒAGFÀØÝE‚‘¨ŠàŒB.÷ÇñhŒ!cÏǘ¢™‹*0 qöï*h IB c­ 7©K%RkXXƒ…5-¹&8É5rÔ%ÅcE ¢£×ç iÉëJ^'ê8>Š”x ª éq< ÞFYNà›D ÚTkãxTWæàé…OJ9šàh´é(Dƒ:Û«M2ðD¤ܘ Ѩ«IÂTI*©jk,å$DͲ&cuQC™`&Õ§w£Kð9ºt]”ÇXE*ç!OwÓ>tŽÈ¢|“¹ãì€P“Eù8O¢ ž§P€  5ëT¥½ˆêAªFá€kãx)'iT¥aÄæwÃ<Ȧ‰öTj(»­v ÂöB4’–P+½“íE/¬@OEñqV½ø§PFᎢ€¡%à‚H2Üax.1<Ãn1Íï’SP°§t-`À]"¡fC4ÂáçÉE²h¨ ª ‡õá)X÷Á¢(ŸŽâ“,f ¨Y@OÄpÍÃ߉3:U΢m C„Ø:7ŸŒbÊÌS`¾ A-Äpæ¶$ù—X––¨Ó¨EQN·³´¼/vfi¡ÓA&ŠSˆhZZõ0?Kì6Í‚³óë™8ΑÊîpvR–U5rBÊà\µöÕ¶-ÅnªmVÝ}¢|°Vk9†ÏñŒ¯€ùŠ l²Œ#0²?zˆ]ËDa“ LXƳI&Lmù#I_iʲ(Ÿ‹â³p k®}û¡‘­nC/²ñahhšÈÇ^ÞËкø+üw [ügmï{:~ËôBëãcZ°Cg?÷uÚÁùᎎðžéhc½Ã6Ô!íñ˜ï†v×9Þ1ž‚ftøá¶÷B›íÐ9Åå»ã]y¢Cžáòhç˜<}…q+ã1ÌsÝq>x\»Üy5¦åóó\ÿŒ°KöÏ_u¡Kqù Þ þ÷¿K–Ë.³}‘‰®|ëþ'Nw¿b_>}ìõï¼ýÀË£±Iåѳ?Û© ¯\xì_úSOãÕßL½÷Ì…_gÞzóý·æ“K‹·=ÓŸøºïƒoÿÄ÷׿úÌ#óÿó‰Ïýýxltô“Þ'¿ÿ»›¡ ù‡Øxù©_½ù°õøÑ—¢ôÑ¿¬?õÞ³¼ñéÃõ‡_|ìÙ/W³SxôóŸÊú¾þуNèÏK¥Ç–ç_¼þÛDð3/~%ÔýP¼þã[˃߻pMµ¿ða÷»Kÿ¾ö§>øWé?¾G6W~º\/°=¼Ëëd•ïoù6.–9? в\Îò°Äåó·q”äc–OÊuà .œæy™àœ‹¼Ž&¹ŽÆ×D^ƒã||˜ç”é B;ÊǬ®G¸«÷až6vîârvV†øXIÀ«‡a]¯0Ɇ§( KN­9©᛿XÿÛ7¾øGþ5ïgŸ<½¹™ÊÖJ°øaS_búþú6{T8Là+ ¸ùË9jÕ´¯2_½áÂÃeK¬|¹Æ$byKð—k…J£h…½·è‚µbQP’÷g—r÷eWÒ[BÏ´ÓáHΘ1â‘™]%ùÔZ.{nñü–н^vµÙÙ°aæÍfL—,Û ¶otrvršÉ$·\µ6|y¨Õß››^³Ë 4l=;·„cSõª5µeÕ6ËSŽ]˜jþïÃÞ¨ù"œ„Wõ¦€7/#ö¿PK-qM>:&priv/templates/basicnif.c­TÑn›0}ç+®¨T%ÈZ³½V}¨:*EË҉ѽT•eY­“‰eüû.4ÒXya_Ÿ{α ¡"YÄ\n$U"ùðâ:Nn™øFnEð\&âa™qöûTÇ…äUEÿûÃcpç_;ŽÅ¹˜'[SDÖÙ;U¿ð…©Xr,»º‚oF[]—çŽlèv}OC?øÚ/Wü×â°µ¯vpµ# ”f~F"­r ƒµ8±{z^^¿‰˜–I¡"+´š ƒ®s¡ªÈF<ê^½a·žäÏ(›åÀT q©X*"LN M|˜å1¤<Õ¦Ä;Aüj½ê\&Ǿ{K$Òo§VI+*5‹§™{±£1³Œ 5¬×P¡=q<ºÔvaÒWG©ê;¬•wBIwNÔ/ÏX2¯ë4é]à߆>üé…·_ü‡~0z5<«ÆŽ{½]‡=ÛÈñ®$pÙE`û¸Ùô߈øPK-qM>ûV5‡4Øpriv/templates/basicnif.erl­’MOÃ0 †ïýV¥I™Ôq'†Äe6NUiã€Y–Li LUÿ;IÊ>O“À§Øzý&~âtcD«uÝpèûqE)~om؋Ư|’D°ÍN¶ºjÈèüæ5(.”á‚‘¦&Ÿ„I’­æË•KSÒ•jŠJcëe¿¥€ãe¹Ý6 ø±Ó?€=¡¼¦c4‚ÙßÃÛÌŸÝÏ@ƒuSÿ—ëù®D%¯©*ü GY'àfíî@i iÖ.¿ 6wØ¢PK-qM>ý+¡R‡ priv/templates/basicnif.template«.K,ÊLLÊI-ÖQˆ®ÎÍO)ÍIÕQPÊ­„0•jckõ¸ªKRs rK@2I‰Å™Éy™iz©E9J@~qQ²~5Tcm-X—Ždúäx4É õPK-qM>ôävÞ priv/templates/simpleapp.app.srcmŽÁ „0 DïýŠà9,ì÷Ȳ¸6HØn-Mñüwk[P\s 3/ÌD‡CâÙ#¨fÉv]Ñ@oÔ’Œ‘C¥]·û ‹ìâÙT¤‰%Q$‹Ð¿ªw ,I×ùRôäð†H²Ž?ÿ EÿæÜ£Ç§ï¼KqÅä—¢L¾˜ PK-qM>üÁ™\Î!priv/templates/simpleapp.template«.K,ÊLLÊI-ÖQˆ®N,(ÈLÑQPÊ­²”jckõ¸ªKRs rKRÂÅ™@f*PJ„‹‹’•@‚EÉúÕµµp \:ãA R‹r0tÂ%pê,.Å¡&Q«PK-qM>À­À‰œk priv/templates/simpleapp_app.erlÓÍÍO)ÍIÕ¨®N,(ÈL©­Òšz\\ºI©‰e™ù¥E@‘œÌäÄ’Ìü<Œªª‚#BD!91'')19»˜K7µ¢ ¿¨D#º¸$±¨DßHG¡¸$¿@ß0ªË–r€Ûr*™Ïv»F|0ˆ ©,HÕQ€°‹Ò‹5tí¸€ZÅ¥V`-ñ9™yÙ Ÿ‚< 6 $®!?[ PK-qM>‡O³Ì priv/templates/simpleapp_sup.erl­RQKÃ0~ϯ¸—A ©ë|TÄ +LÔ§QJ–¦.,MJš¥ä¿{uÝêÃÞìA¸»/Ü÷}GâÊ­–´ëx]«"„¼iëèŠx+wü lë(¾HwPu}a6ƒ‡×”Äò«¶ÎÓMã¹ó¹Vf?O²¡áíŒÁµÞr±oF„2ÊÏ§Þ•ÔØ ÎB‰ˆB Í2Ÿ vJN°%ŒC¸¥2’>®Òõ’¦ Þ¿k1èÒã'b°ÉDVÜHã\'Ir`-ÍÂ0ÄíÿcÊÖ¯¬i¦ú—Œ|hñŒQŽ›?åN[Ô›ÁýóËòcýη^ˆi©^´x*Æý†PœøÄ¶³he‡ÉÈW$ÇŒV2X$á×bÈíPK-qM>@*‡«priv/templates/simplefsm.erlµS]kÂ0}÷Wäe¡Õ}ø´‡ Á Â6‡2_DBÖ^5˜ÞHE)þ÷%Z5ºn[[hiî=99÷æ\?VÑJͲi‹h·«7jþ'ÌùZ¨UBg€Ì$l0‚©@ Ã`0 y~íw>^“©ÝÜÿßei¿÷Hw…¡ I°YªD§%±×|ØóÑqªy¢™¸hÞNJ•Ÿ7«ú ݼóˆ)ECCóþbõà‘9ÇHƒ5 vÖéÃ<Ø:N•ÅhHb†Å.B bÍV¹º¸çŽõ•°¿¥5ê|Å´Nü§9^Í£“ɤ ¹4F>8zw²´GÆûVë ʶ|”µ“YšW©…Gö§pÉÎö¸ŠíûŽåIÊë mèH„°Ñ´ë³ôë&*¾âI`)·±º i\×^*y;‹D]c²³å ¥;*áµSCYÏ|ÿ.ñ4q” €§ 6Ç\2µ0œ©¤¬/£QŠß™ÍÆ`£îÚ èôÒÜÝCSrY©½¿PK-qM>¥DŒrFS!priv/templates/simplefsm.template«.K,ÊLLÊI-ÖQˆ®N+ÎÍLÑQPÊ­²”jckõ¸ªKRs rKRÂÅ™@f*PJ/µ(G $P”¬_ ÑU[ êPK-qM>>Ò8ì[lpriv/templates/simplemod.erlÓÍÍO)ÍIÕ¨®22Sjk5õ¸¸tS+ ò‹J4¢s+ãÓJó’õ bÁ™i)©i!®Á!@®nr~nA&P+Dq|bNH45/%3 ¨ªUCSA׎KA!?[ PK-qM>þ6ÛöV’!priv/templates/simplemod.template«.K,ÊLLÊI-ÖQˆ®ÎÍOÉLÑQPÊ­²”jckõ¸ªKRs rKRÂÅ™@f*PJ/µ(G $P”¬_ ÑU[ Ä¥#¾$µ¸¤¦ÄAhD’jPK-qM>+]çI;D"priv/templates/simplemod_tests.erlÓÍÍO)ÍIÕ¨®22SjkãKR‹KŠ5õ¸t3ó’sJSRãs2“4”RKó2Kô¡Bú`ž^FQŽP!PK-qM>Õv¬N$priv/templates/simplenode.app.config}޽‚0…÷>Å I·ª˜ˆºêŒ#! b!$`MË ’¾»—…8p·ó÷å¦ œ#9%1 }/ëŠa°¹mR†ïyG*c´‘®*e†²n”@@z3Æ+¯IΉٖ|2e×?¨îKÿñ*ÛRÞj3£N|z±®@¡*:mú@›?¯}§¬À6Ü£Ã>ô N—3(Æø:lýR˘±F˜Èa:ŽÈÏíšæ™cÙš±7PK-qM>K"’V`$priv/templates/simplenode.erl.scriptmR{kÛ0ÿߟ▸mš5v÷Ë–0 ̓$ ‰lgS[2’œ4týî»ócËBÁéìû½îúÂ(Sa$lêyý>lÓÌ‚MV:0Xæ"F .E˜ˆ*wÐC“÷ S€ÆÙÑÍ‚ûƒ¦…Ô`…91˜°€-–Ä•´ ¹1¡$c¸Ê¨»ºpö=‡Lý38 ‚±"­]‹5°Npå6€…vH …£×?ítZ.ÉA?£d)l&q„I‚±cH€©”b²NæhT›Å"B)©Mi‰Ja-åÐ)¯Ú ¾` 23„—׆D“9°©®rIÚ¨Æå÷%â¹Í–Ы¢t™oÿBƒl$³Õ]œ£Pµa†K²œz"ËED'ÊÑ_/—ÛéÃ:4HZ i.ͦèЙ†'²¥p)?Ö‰±ŸÊq‰ÑEàÍÖÛÍîËÃbGÐcKð_ï¯Âá\_Cy”·L±ÐGšÞ9!m,ÚœšL϶ªR¶ÆÿoƒîÉj8" ©(ó-ÅOÃ·ŽºHqm®ÇD³ /|<—JPl3ðÚTÆþëùg2@XúJ‹ +^õ:·zº,‹BM´·ÙNÖÛÝlý8ÞÇ4–Ë”mØL‡6!‰}9"Æ¿½W@d“Õê²Þ‰ MµÂºÎÄïp8o6ÿ>ŽPÞj½ü¶˜Ìgã=Æ©ÿ~ƒ¥”nl ŸžÂ0¼Ù{_çÓqÏo`ÃvG{¾”Ú8 ¨îØvצ¡»uLžW¯¸O 0âõ{'¿õž­*íɧ=ÿsïíPK-qM>ì,?¯ˆÓ"priv/templates/simplenode.nodetoolÍWÝoÛ6Ï_qTZ宊=(Ȱ.ëÚ>t’ìÉ3F¢bÎ2)t“ÀIÿöÝ‘”õa9Ú«üAÝýîwwäÝñøf?Ì`­Jž×5“×'þk&dÉ¥Õü#¯3xyþ[vef^^Šš´ŽßfPÙS¯ Öœ¾sƒÜÒÛÙ×?CH [¥Ð[^7\ÃE¡Ec¡R„´\³Â dp#ìjñ‘; ´¿£52~¥¯M³Ÿµ‚S0–i›óf]ÆIê–Ñàë[KŒÀ.90TqëÛsn,¤p‰‹Üþ¢ÑªàÆä${ù"… ¾’—ˆÛ_p¢r¸ä ÅFkLP}z#%ý%!aŸ”²)Üð'u WLÔ§`†ÃVr›¯¸–˜å¥(1Çy¡¤ä…Í 9î(&),+×Yƒðý7 *éü³zÃSh”¼~hCÔ>juÒÉå(Ä&„„Ê0ŸkfãˆÐáSCôAsƒ˜%yfóìoa:&‹ûöY²ÚÆ/·Æeèo³Ð§>6ZŒaÄßU>¸V”LŒvÅtÚ…ŸÕš³ò.P4¼$†ÌqLÁ(øgc,”›u3FeQœ¢CþÓKô19éQ4V5û{JŸÝYÁ꺗©O‰À@~wýôŸd1°€nÐnþZ#æ1;WJ}3„òˆ•¦@„÷ªÜÔ¨óûFb‰Pîá¼)hì™wÛcÒ`-ŒÍ­Ê™UëØ#&£Õ´‡Ï¼5Ý2îoÂöÁ²2"Ö½9Ù[ß^±9§¸¯™QrïPMÄöüÏ3Ú§x¼*, ¼Ì vßg7>XíØ>Ÿüþ‘l<š£Œa)_›‰´¥@q{e.¬ÆÃõ?¤‹£Ù }ÉciüÞó«–þ$Z“N~ñH¾&{@î}çBÀK‰ÿeØ5 ¡ÓÖªè=¬ûPPîý‰ ÂØUvúÑëe¤'ÏŽŽ]•jÄ«¢èwÞ]ßÒf0™ÆG£X2èÐ'#¨hf¸-”Z Ž~¹TUä#Vüˆ”¡jîuc×fÇ{ÑÃ%!LÃd`Ÿdk"dðψ\¾ãt‰ÍuÚS`MƒÑt­?7›ª·qB”Óøcó(ÛªÑð2=&)ž·¨èv1bcŸñ‡Ì’`Ïf2á™ù~\3K¥í·ó «ÊÈ•í&Í ì ‚²‹ Œ{þ¨?¶Êóú¢LVà"½Éf—øúéSˆ`V2¾V²u^­¥/0^kk~ò7¡«ÂÚDe¥ÐÎ3nÜ4žù¯Ü­µ[Øeé"Òn CB8Ü–9¿åÅ/5}>:Sƒ²Z±µ¦Êþ¤É¢<‰2QŒÎÔ¦.ÝôIÐ@äŸ}ÚEiü¬¹ojuÅêר}Èf'q¸ÐNéï4P’¿ÛeÞõ íâc\¯Ê¬ZqiB£_¢A|æ¹ßÖù[…[pllP¡œ^×vã÷XcŽ3¾‡:Ù' Â"ÌPÏ'=lÓWhlÁ&gî©¢J°‘$½HLœvïò…ûó¡ñæ>˜)’ÞhJ{Ï~#è’8`þ¹@~‰…a@Âø ^Š%Þ;¼Ë€÷æ+!™¾£»¶=¼-ÒEšn/dnKñŽÃ܉ÏÂôãsBlÇ!„¸Y"´0>§n¥ r¢ö‹ë4«£Çí*žòN׳qkÊþínß”CÿZ±3%m°B-|gl¾¹)˜l3Ý“oÛRI7b$}SowÕö*‰b“Ã5‘KgÌ5“§ß‹aœ©ÝI—‹Ì}æÿØc¨;ýí¨Ò´ˆš¡7L¥-W’róØAfû3ÑÖ CøNVêQ/{r‡ËÜv­4§JÚûñîeùE ÎbÕmôPK-qM>¯oLÎ)0(priv/templates/simplenode.reltool.config•Rmoƒ þî¯ |Ú¢Ùï™­Q¹R h3Çøï»³Ñ²Ù5Ÿäîy¹{0úÉ ö^°Û‰ZuTŽjû$Ö²-ÑX J¦ÄñöÆ×þ]€±8ƒè{Á‰ªy¡õz½m]|h]hz ­!›¹<”í¬ Ífƒ 0:{TƒsR‚ÌzðÑëCj`†:eªr—Möàð¸àË]Eà©Z=}‚û Óî•çóµã(æPP;*ƒ~½5R0ú¼HHûT,K•E1ž½Ò¯…¨i¯àt;‰<+´8Ÿnpm‡Šœ²íç~oGäpJÁW¨@Áױ޴Bsõ¦Nuš¡Þ3.M¬ý[`8ÈLgð priv/templates/simplenode.runner½W[SÛ8~÷¯8o)lC§O0Ùi )Í,¹LÊt(“8¶’h±-¯$XÂß#ùçÒ.íÃúÁéèÜôOÇû{΄ÆÎÄscì#¤7±4óÓg4H,mvÄrÓP ¡(y<)ê@,ðF¤a ®»ÝÖ`ä^ Úýá¨ÙÔ­·~ÖóñoÎÑ ¼yÉ"8,åÎn+“zÞZ©r­áE&¶±Î!Ò/d®z—»eB63úí~fÈ‘Qâl‰:®ÝÖ n`dH99§„Ïi"ßxÇ4ž'p†€—$œ%œz’@*7ènaìÀ´*JM¸SÁßÂx1g^DǰWß’8S*cð"ÄGû;…ªØ¬c°>SºîèÅMS9(ˆÉ´Ÿ„î)€rCmÂFÔëË1KJø’ñ'´O…FtC`'åÚ<ÉjiëQrÏ—: Òã3´#< ö"SÎ"ýYÃatÖ¨1¸¬gœ$`8°oÅÝ‘’=(•ç»ì VF~ì{[U)>içs¼ªˆ¬¢êcëx¬ô=ŽØ`©NB¢pâÅ.ÐxÊ wØ G­ÁU}ì{r =N¾J8S%G„‡µÀ“ÞØh †îè‹ÛÅ¢.uüXÌ~s|ÿ^”3 µˆ UXÊ1d9ÏöÃÏ;êݵ­Â¢¢1¥Í%2Mpë¢H…„ª|KÎB…J£Ûk¶†½ÞUÝ´JíÉÓVRÂ’áÊPÝGeìbNü{­yJ¹€»˜F¸0EÔÑXHžú’²X¾J²i˜8¬7PgîP¿ªkvÞ±žc†*CN¼à Ñ +,ç rÝ åÖÇV$87.'5þiZ® H9 ‹gëð+® †]eÍ&s[{æºl†¼âX¼~n©½èu:n³nnm˜:h¬ ’Yø+Åä1a\®k('WLTPy%m]&IV´Ü£¡¢gâa,^‰;¥|e{1:\°DkÒ›Œ¦¦äƃ(,$&¼ÿãÍ*9ggF¾Ù,©îõG3Œ Ì€%!–xø¤åkµZ¹B£gœê¶Å¸ÀPq]Ñ8}\6=¾ ñò'äÜm.›Ü›±øSø´ì©z ‰ñy¸¶4ó§ßnÂfÖ‹ çêãQñ6C€uõÌ ¬¾ü¶µ@]š'·P;rn'wċ̥·¸‡ƒg<>±Z¬“—ƒñ–L^õÓMãžû«ÎÛdZõ^±íÿèúÅ×Ë›v÷h—ó×è¼  ¯nÃáWp‡íNë5ñÜ,ÒÓ÷ÿá)ž¿*”’RËáÅœ†ˆÄ{b᫚i"â€<8q†ã•¶€­Ù!AgO*Ó1Ù*N6YqÙ˜®”/XàÑ®Î-ÅBªØÕ0¶a>b‡ï¹Â†&ŒýÐN¥ßbs'`Nô,+t­¬¯ZTš· *^^3ç¢è9·¦I—> “*Ûê<)=¾ûôÈжûëgÅÞOêŒzíAQ¾‹9®’T!eÉ4'o}yγËü9ò±‰«‰¨©ü£1„©|J¨ï…¸…¥x8Tý–’wE¯Û¤êò9[ÂßivÈ$Í0²w v_4B d-¶›ÙÂ$ B¦ixºÎ×ÕÓ¾œÈÜ>,¾Ï{½á§öU«^8·ÁëaVä+^|·†‹fh‚\`sòwŠ-~Øû­ úvý8•çín6Ÿ îjº ÑV纮L•ýAïRµNõ±† þº,ñ%€õí›ã8Bºè¨–!3‡VB}äÚ:Áßo?­¼­t¬"1Ȍфš±1yS:ÛjÏqÛkù”­‚‘Ëwšx°müƒ=ùÝ´>š/[ý †¼9”'js8 ls´ÈQÙ³f%@âÊY¬{IÕ‘k8âoš#$)O†¿Ò¦+²…;ŵÓ47f˜EœÉ]3«Ö®XÆ¡OéŠè•-õ %Æ4o-ëÎÓU‚Ê‹4YSäVس¦ê›Ð£­:®†™×›‘Ó²HŸµCKuø,sÆ]fܺT¼UÔÿ2cµYc´§kÂÐãÇÆ¿PK-qM>M•Þ¥¹"priv/templates/simplenode.templateuÍ Â0„ï>E©×/}ñÛm äM,HÈ»›õ/5¡—e™Ùù&,¿Jp]sÚŒ Æ®iÕƒÖ6^"ÛÊJî!éN¤ÈcÒ#Ù`ô$æ6™…BÑIÈ"(™PXOòÝ!i¯ëá¦Lú~Úû¾2k z˜A?e“öwQ#ñ®5`†O%1n#‹›Ê­]µô­´íŠÅ8Î.§¾BŠ<PK-qM>Z·{6«!priv/templates/simplenode.vm.argsEMO1†ïýc¸hÌ"?b¼HpQ#(ü¸‘nwšÝ’v !„ÿîìz ½´3ïû¼ÓQ|èÁÀkr9ª„šÊáÐõ¯ï»=9}¥D?t®´…óÛÀÞf‘1ô•¦•J²ùWœ­ïµç 5C­I¯°FâGБ]â1°4|OÀ`YÈ@24®–k$Ñl»ÅvþlƒÎ*ÉÍöc¡cÅÝn ;Ëk0‚µŽÎ.D›¬›àv„””è +ظªM9h(p:ìÉÈ<ê<¨Ëw`Q]à¶õ¾‘‘ŽP¬3ôÍÆŒ#½—KÆ¿ ΔÈA%H[Hgãådð»œ~Îs¸é=ܵœÅu /C`>ÔÎ7ëg¤“mô5ÏÒtºŒé ú=¥þPK-qM>‘£0¤Vpriv/templates/simplesrv.erlµRQkÂ0~ï¯È‹!]·ù¶‡ Á Âġ̑ٳcâ’T¥ÿ}‰s5ÆÖRr¹û>îîûâÊ ¸,>𬪺7QüvàªÐ8I èhÿžÁšKÀ³t:O§='ƒ×çÔe¢NÅÿþZƒ`óJV!priv/templates/simplesrv.template«.K,ÊLLÊI-ÖQˆ®..*ËLÑQPÊ­,N-*K-Rª­Õãª.IÍ-ÈI,IÊg™©@uz©E9J ¢dýjˆÆÚZ° PPK-qM>÷d getopt.beamPK-qM>ûp² T Dmustache.beamPK-qM>©Go ? }rebar.appPK-qM>ï”×Öä Ãrebar.beamPK-qM>:Y ;Á+rebar_abnfc_compiler.beamPK-qM>ܧ=p31rebar_app_utils.beamPK-qM>ª…ß[PÕ6rebar_asn1_compiler.beamPK-qM>jQ¤ô f;rebar_base_compiler.beamPK-qM>'f]­ @Drebar_cleaner.beamPK-qM> }ÓûP „Frebar_config.beamPK-qM>¨žm»B ®Lrebar_core.beamPK-qM>&À—YZ À Zrebar_ct.beamPK-qM>Î¥Hxàü"¢erebar_deps.beamPK-qM>HRòƒˆ ¯zrebar_dialyzer.beamPK-qM> Ãf4cƒrebar_edoc.beamPK-qM>¦Â1l¨Ä…rebar_erlc_compiler.beamPK-qM>€CÔ ˜ f—rebar_erlydtl_compiler.beamPK-qM>ƒhmJ8 ° rebar_escripter.beamPK-qM>æõ—z¦!,§rebar_eunit.beamPK-qM>M(|ò}” »rebar_file_utils.beamPK-qM>ø¯ÆD°Ârebar_lfe_compiler.beamPK-qM>(‡@èÏLÇrebar_log.beamPK-qM>í£ø þÊrebar_neotoma_compiler.beamPK-qM>Xù0"T ÚÓrebar_otp_app.beamPK-qM>–ú$m—ø(Ürebar_port_compiler.beamPK-qM>ºAÐ48õírebar_post_script.beamPK-qM>p´rFçŸÔ ¿òrebar_protobuffs_compiler.beamPK-qM>ÒET4šùrebar_rel_utils.beamPK-qM>äé ãÚ À ürebar_reltool.beamPK-qM>£™GŒÜ* rebar_require_vsn.beamPK-qM>l(»çRHê rebar_subdirs.beamPK-qM>'ðênÊ8lrebar_templater.beamPK-qM>G%È”1 ¨hrebar_upgrade.beamPK-qM> 2¦T ¸É*rebar_utils.beamPK-qM>IA¤\ LK8rebar_xref.beamPK-qM>:&ÔBpriv/templates/basicnif.cPK-qM>ûV5‡4ØEpriv/templates/basicnif.erlPK-qM>ý+¡R‡ ~Fpriv/templates/basicnif.templatePK-qM>ôävÞ Gpriv/templates/simpleapp.app.srcPK-qM>üÁ™\Î!ÂGpriv/templates/simpleapp.templatePK-qM>À­À‰œk ]Hpriv/templates/simpleapp_app.erlPK-qM>‡O³Ì 7Ipriv/templates/simpleapp_sup.erlPK-qM>@*‡«Jpriv/templates/simplefsm.erlPK-qM>¥DŒrFS!NLpriv/templates/simplefsm.templatePK-qM>>Ò8ì[lÓLpriv/templates/simplemod.erlPK-qM>þ6ÛöV’!hMpriv/templates/simplemod.templatePK-qM>+]çI;D"ýMpriv/templates/simplemod_tests.erlPK-qM>Õv¬N$xNpriv/templates/simplenode.app.configPK-qM>K"’V`$fOpriv/templates/simplenode.erl.scriptPK-qM>ì,?¯ˆÓ"þQpriv/templates/simplenode.nodetoolPK-qM>¯oLÎ)0(ÆWpriv/templates/simplenode.reltool.configPK-qM>8ÈLgð 5Ypriv/templates/simplenode.runnerPK-qM>M•Þ¥¹"Ú_priv/templates/simplenode.templatePK-qM>Z·{6«!¿`priv/templates/simplenode.vm.argsPK-qM>‘£0¤V4bpriv/templates/simplesrv.erlPK-qM>Zƒ`óJV!Äcpriv/templates/simplesrv.templatePK99‹Mdrabbitmq-server-3.2.4/plugins-src/mochiweb-wrapper/mochiweb-git/test/0000755000000000000000000000000012305126066024402 5ustar rootrootrabbitmq-server-3.2.4/plugins-src/mochiweb-wrapper/mochiweb-git/test/mochiweb_http_tests.erl0000644000000000000000000000252212305126066031165 0ustar rootroot-module(mochiweb_http_tests). -include_lib("eunit/include/eunit.hrl"). -ifdef(gen_tcp_r15b_workaround). -define(SHOULD_HAVE_BUG, true). -else. -define(SHOULD_HAVE_BUG, false). -endif. has_acceptor_bug_test_() -> {setup, fun start_server/0, fun mochiweb_http:stop/1, fun has_acceptor_bug_tests/1}. start_server() -> application:start(inets), {ok, Pid} = mochiweb_http:start_link([{port, 0}, {loop, fun responder/1}]), Pid. has_acceptor_bug_tests(Server) -> Port = mochiweb_socket_server:get(Server, port), [{"1000 should be fine even with the bug", ?_assertEqual(false, has_bug(Port, 1000))}, {"10000 should trigger the bug if present", ?_assertEqual(?SHOULD_HAVE_BUG, has_bug(Port, 10000))}]. responder(Req) -> Req:respond({200, [{"Content-Type", "text/html"}], ["Hello"]}). has_bug(Port, Len) -> case httpc:request(get, {"http://127.0.0.1:" ++ integer_to_list(Port) ++ "/", [{"X-Random", lists:duplicate(Len, $a)}]}, [], []) of {error, socket_closed_remotely} -> true; {ok, {{"HTTP/1.1", 200, "OK"}, _, "Hello"}} -> false; {ok, {{"HTTP/1.1", 400, "Bad Request"}, _, []}} -> false end. rabbitmq-server-3.2.4/plugins-src/mochiweb-wrapper/mochiweb-git/test/mochiweb_base64url_tests.erl0000644000000000000000000000125712305126066032021 0ustar rootroot-module(mochiweb_base64url_tests). -include_lib("eunit/include/eunit.hrl"). id(X) -> ?assertEqual( X, mochiweb_base64url:decode(mochiweb_base64url:encode(X))), ?assertEqual( X, mochiweb_base64url:decode( binary_to_list(mochiweb_base64url:encode(binary_to_list(X))))). random_binary(Short,Long) -> << <<(random:uniform(256) - 1)>> || _ <- lists:seq(1, Short + random:uniform(1 + Long - Short) - 1) >>. empty_test() -> id(<<>>). onechar_test() -> [id(<>) || C <- lists:seq(0,255)], ok. nchar_test() -> %% 1000 tests of 2-6 char strings [id(B) || _ <- lists:seq(1,1000), B <- [random_binary(2, 6)]], ok. rabbitmq-server-3.2.4/plugins-src/mochiweb-wrapper/mochiweb-git/test/mochiweb_tests.erl0000644000000000000000000001477412305126066030142 0ustar rootroot-module(mochiweb_tests). -include_lib("eunit/include/eunit.hrl"). -record(treq, {path, body= <<>>, xreply= <<>>}). ssl_cert_opts() -> EbinDir = filename:dirname(code:which(?MODULE)), CertDir = filename:join([EbinDir, "..", "support", "test-materials"]), CertFile = filename:join(CertDir, "test_ssl_cert.pem"), KeyFile = filename:join(CertDir, "test_ssl_key.pem"), [{certfile, CertFile}, {keyfile, KeyFile}]. with_server(Transport, ServerFun, ClientFun) -> ServerOpts0 = [{ip, "127.0.0.1"}, {port, 0}, {loop, ServerFun}], ServerOpts = case Transport of plain -> ServerOpts0; ssl -> ServerOpts0 ++ [{ssl, true}, {ssl_opts, ssl_cert_opts()}] end, {ok, Server} = mochiweb_http:start_link(ServerOpts), Port = mochiweb_socket_server:get(Server, port), Res = (catch ClientFun(Transport, Port)), mochiweb_http:stop(Server), Res. request_test() -> R = mochiweb_request:new(z, z, "/foo/bar/baz%20wibble+quux?qs=2", z, []), "/foo/bar/baz wibble quux" = R:get(path), ok. -define(LARGE_TIMEOUT, 60). single_http_GET_test() -> do_GET(plain, 1). single_https_GET_test() -> do_GET(ssl, 1). multiple_http_GET_test() -> do_GET(plain, 3). multiple_https_GET_test() -> do_GET(ssl, 3). hundred_http_GET_test_() -> % note the underscore {timeout, ?LARGE_TIMEOUT, fun() -> ?assertEqual(ok, do_GET(plain,100)) end}. hundred_https_GET_test_() -> % note the underscore {timeout, ?LARGE_TIMEOUT, fun() -> ?assertEqual(ok, do_GET(ssl,100)) end}. single_128_http_POST_test() -> do_POST(plain, 128, 1). single_128_https_POST_test() -> do_POST(ssl, 128, 1). single_2k_http_POST_test() -> do_POST(plain, 2048, 1). single_2k_https_POST_test() -> do_POST(ssl, 2048, 1). single_100k_http_POST_test() -> do_POST(plain, 102400, 1). single_100k_https_POST_test() -> do_POST(ssl, 102400, 1). multiple_100k_http_POST_test() -> do_POST(plain, 102400, 3). multiple_100K_https_POST_test() -> do_POST(ssl, 102400, 3). hundred_128_http_POST_test_() -> % note the underscore {timeout, ?LARGE_TIMEOUT, fun() -> ?assertEqual(ok, do_POST(plain, 128, 100)) end}. hundred_128_https_POST_test_() -> % note the underscore {timeout, ?LARGE_TIMEOUT, fun() -> ?assertEqual(ok, do_POST(ssl, 128, 100)) end}. do_GET(Transport, Times) -> PathPrefix = "/whatever/", ReplyPrefix = "You requested: ", ServerFun = fun (Req) -> Reply = ReplyPrefix ++ Req:get(path), Req:ok({"text/plain", Reply}) end, TestReqs = [begin Path = PathPrefix ++ integer_to_list(N), ExpectedReply = list_to_binary(ReplyPrefix ++ Path), #treq{path=Path, xreply=ExpectedReply} end || N <- lists:seq(1, Times)], ClientFun = new_client_fun('GET', TestReqs), ok = with_server(Transport, ServerFun, ClientFun), ok. do_POST(Transport, Size, Times) -> ServerFun = fun (Req) -> Body = Req:recv_body(), Headers = [{"Content-Type", "application/octet-stream"}], Req:respond({201, Headers, Body}) end, TestReqs = [begin Path = "/stuff/" ++ integer_to_list(N), Body = crypto:rand_bytes(Size), #treq{path=Path, body=Body, xreply=Body} end || N <- lists:seq(1, Times)], ClientFun = new_client_fun('POST', TestReqs), ok = with_server(Transport, ServerFun, ClientFun), ok. new_client_fun(Method, TestReqs) -> fun (Transport, Port) -> client_request(Transport, Port, Method, TestReqs) end. client_request(Transport, Port, Method, TestReqs) -> Opts = [binary, {active, false}, {packet, http}], SockFun = case Transport of plain -> {ok, Socket} = gen_tcp:connect("127.0.0.1", Port, Opts), fun (recv) -> gen_tcp:recv(Socket, 0); ({recv, Length}) -> gen_tcp:recv(Socket, Length); ({send, Data}) -> gen_tcp:send(Socket, Data); ({setopts, L}) -> inet:setopts(Socket, L) end; ssl -> {ok, Socket} = ssl:connect("127.0.0.1", Port, [{ssl_imp, new} | Opts]), fun (recv) -> ssl:recv(Socket, 0); ({recv, Length}) -> ssl:recv(Socket, Length); ({send, Data}) -> ssl:send(Socket, Data); ({setopts, L}) -> ssl:setopts(Socket, L) end end, client_request(SockFun, Method, TestReqs). client_request(SockFun, _Method, []) -> {the_end, {error, closed}} = {the_end, SockFun(recv)}, ok; client_request(SockFun, Method, [#treq{path=Path, body=Body, xreply=ExReply} | Rest]) -> Request = [atom_to_list(Method), " ", Path, " HTTP/1.1\r\n", client_headers(Body, Rest =:= []), "\r\n", Body], ok = SockFun({send, Request}), case Method of 'GET' -> {ok, {http_response, {1,1}, 200, "OK"}} = SockFun(recv); 'POST' -> {ok, {http_response, {1,1}, 201, "Created"}} = SockFun(recv) end, ok = SockFun({setopts, [{packet, httph}]}), {ok, {http_header, _, 'Server', _, "MochiWeb" ++ _}} = SockFun(recv), {ok, {http_header, _, 'Date', _, _}} = SockFun(recv), {ok, {http_header, _, 'Content-Type', _, _}} = SockFun(recv), {ok, {http_header, _, 'Content-Length', _, ConLenStr}} = SockFun(recv), ContentLength = list_to_integer(ConLenStr), {ok, http_eoh} = SockFun(recv), ok = SockFun({setopts, [{packet, raw}]}), {payload, ExReply} = {payload, drain_reply(SockFun, ContentLength, <<>>)}, ok = SockFun({setopts, [{packet, http}]}), client_request(SockFun, Method, Rest). client_headers(Body, IsLastRequest) -> ["Host: localhost\r\n", case Body of <<>> -> ""; _ -> ["Content-Type: application/octet-stream\r\n", "Content-Length: ", integer_to_list(byte_size(Body)), "\r\n"] end, case IsLastRequest of true -> "Connection: close\r\n"; false -> "" end]. drain_reply(_SockFun, 0, Acc) -> Acc; drain_reply(SockFun, Length, Acc) -> Sz = erlang:min(Length, 1024), {ok, B} = SockFun({recv, Sz}), drain_reply(SockFun, Length - Sz, <>). rabbitmq-server-3.2.4/plugins-src/mochiweb-wrapper/mochiweb-git/test/mochiweb_html_tests.erl0000644000000000000000000005567412305126066031172 0ustar rootroot-module(mochiweb_html_tests). -include_lib("eunit/include/eunit.hrl"). to_html_test() -> ?assertEqual( <<"hey!

    what's up

    sucka
    RAW!">>, iolist_to_binary( mochiweb_html:to_html({html, [], [{<<"head">>, [], [{title, <<"hey!">>}]}, {body, [], [{p, [{class, foo}], [<<"what's">>, <<" up">>, {br}]}, {'div', <<"sucka">>}, {'=', <<"RAW!">>}, {comment, <<" comment! ">>}]}]}))), ?assertEqual( <<"">>, iolist_to_binary( mochiweb_html:to_html({doctype, [<<"html">>, <<"PUBLIC">>, <<"-//W3C//DTD XHTML 1.0 Transitional//EN">>, <<"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">>]}))), ?assertEqual( <<"">>, iolist_to_binary( mochiweb_html:to_html({<<"html">>,[], [{pi, <<"xml:namespace">>, [{<<"prefix">>,<<"o">>}, {<<"ns">>,<<"urn:schemas-microsoft-com:office:office">>}]}]}))), ok. escape_test() -> ?assertEqual( <<"&quot;\"word ><<up!&quot;">>, mochiweb_html:escape(<<""\"word ><>)), ?assertEqual( <<"&quot;\"word ><<up!&quot;">>, mochiweb_html:escape(""\"word ><>, mochiweb_html:escape('"\"word >< ?assertEqual( <<"&quot;"word ><<up!&quot;">>, mochiweb_html:escape_attr(<<""\"word ><>)), ?assertEqual( <<"&quot;"word ><<up!&quot;">>, mochiweb_html:escape_attr(""\"word ><>, mochiweb_html:escape_attr('"\"word ><>, mochiweb_html:escape_attr(12345)), ?assertEqual( <<"1.5">>, mochiweb_html:escape_attr(1.5)), ok. tokens_test() -> ?assertEqual( [{start_tag, <<"foo">>, [{<<"bar">>, <<"baz">>}, {<<"wibble">>, <<"wibble">>}, {<<"alice">>, <<"bob">>}], true}], mochiweb_html:tokens(<<"">>)), ?assertEqual( [{start_tag, <<"foo">>, [{<<"bar">>, <<"baz">>}, {<<"wibble">>, <<"wibble">>}, {<<"alice">>, <<"bob">>}], true}], mochiweb_html:tokens(<<"">>)), ?assertEqual( [{comment, <<"[if lt IE 7]>\n\n>}], mochiweb_html:tokens(<<"">>)), ?assertEqual( [{start_tag, <<"script">>, [{<<"type">>, <<"text/javascript">>}], false}, {data, <<" A= B <= C ">>, false}, {end_tag, <<"script">>}], mochiweb_html:tokens(<<"">>)), ?assertEqual( [{start_tag, <<"script">>, [{<<"type">>, <<"text/javascript">>}], false}, {data, <<" A= B <= C ">>, false}, {end_tag, <<"script">>}], mochiweb_html:tokens(<<"">>)), ?assertEqual( [{start_tag, <<"script">>, [{<<"type">>, <<"text/javascript">>}], false}, {data, <<" A= B <= C ">>, false}, {end_tag, <<"script">>}], mochiweb_html:tokens(<<"">>)), ?assertEqual( [{start_tag, <<"script">>, [{<<"type">>, <<"text/javascript">>}], false}, {data, <<" A= B <= C ">>, false}, {end_tag, <<"script">>}], mochiweb_html:tokens(<<"">>)), ?assertEqual( [{start_tag, <<"textarea">>, [], false}, {data, <<"">>, false}, {end_tag, <<"textarea">>}], mochiweb_html:tokens(<<"">>)), ?assertEqual( [{start_tag, <<"textarea">>, [], false}, {data, <<"">>, false}], mochiweb_html:tokens(<<"