ratproxy-1.58.orig/0000750000764400076440000000000011233642416013427 5ustar iustyiustyratproxy-1.58.orig/types.h0000640000764400076440000000234611023063104014736 0ustar iustyiusty/* ratproxy - type definitions --------------------------- A couple of semi-portable integer types with reasonably short names. Author: Michal Zalewski Copyright 2007, 2008 by Google Inc. All Rights Reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ #ifndef _HAVE_TYPES_H #define _HAVE_TYPES_H typedef unsigned char _u8; typedef unsigned short _u16; typedef unsigned int _u32; #ifdef WIN32 typedef unsigned __int64 _u64; #else typedef unsigned long long _u64; #endif /* ^WIN32 */ typedef signed char _s8; typedef signed short _s16; typedef signed int _s32; #ifdef WIN32 typedef signed __int64 _s64; #else typedef signed long long _s64; #endif /* ^WIN32 */ #endif /* ! _HAVE_TYPES_H */ ratproxy-1.58.orig/string-inl.h0000640000764400076440000000555411023463635015701 0ustar iustyiusty/* ratproxy - strcasestr implementation ------------------------------------ Some modern operating systems still ship with no strcasestr() or memmem() implementations in place, for reasons beyond comprehension. This is a simplified version of the code that ships with NetBSD. The original code is licensed under a BSD license, as follows: Copyright (c) 1990, 1993 The Regents of the University of California. All rights reserved. This code is derived from software contributed to Berkeley by Chris Torek. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _HAVE_STRCASESTR_INL_H #define _HAVE_STRCASESTR_INL_H #include "types.h" static inline _u8* rp_strcasestr(const _u8* haystack, const _u8* needle) { _u8 c, sc; _u32 len; if (!haystack || !needle) return 0; if ((c = *needle++)) { c = tolower(c); len = strlen(needle); do { do { if (!(sc = *haystack++)) return 0; } while (tolower(sc) != c); } while (strncasecmp(haystack, needle, len)); haystack--; } return (_u8*)haystack; } static inline void* rp_memmem(const void* haystack, _u32 h_len, const void* needle, _u32 n_len) { _u8* sp = (_u8*)haystack; _u8* pp = (_u8*)needle; _u8* eos = sp + h_len - n_len; if (!(haystack && needle && h_len && n_len)) return 0; while (sp <= eos) { if (*sp == *pp) if (memcmp(sp, pp, n_len) == 0) return sp; sp++; } return 0; } #endif /* !_HAVE_STRCASESTR_INL_H */ ratproxy-1.58.orig/ssl.h0000640000764400076440000000164211023252223014373 0ustar iustyiusty/* ratproxy - SSL worker --------------------- Author: Michal Zalewski Copyright 2007, 2008 by Google Inc. All Rights Reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ #ifndef _HAVE_SSL_H #define _HAVE_SSL_H #include "types.h" _s32 ssl_cli_tap, ssl_srv_tap; void ssl_setup(void); void ssl_start(_s32 srv_fd, _s32 cli_fd); void ssl_shutdown(void); #endif /* !_HAVE_SSL_H */ ratproxy-1.58.orig/ssl.c0000640000764400076440000001343511023063041014367 0ustar iustyiusty/* ratproxy - SSL worker --------------------- This helper process is launched on CONNECT requests to act as a SSL MITM intermediary. Author: Michal Zalewski Copyright 2007, 2008 by Google Inc. All Rights Reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "config.h" #include "types.h" #include "debug.h" #include "ssl.h" _s32 ssl_cli_tap, /* Client traffic tap */ ssl_srv_tap; /* Server traffic tap */ static _s32 ssl_cli_tap_b, /* Rear end of client tap */ ssl_srv_tap_b, /* Rear end of server tap */ ssl_pid; /* SSL worker PID */ static _u8 rdbuf[MAXLINE], /* Internal I/O buffer */ init_ok; /* Initialization state */ /* Prepare pipes for SSL worker */ void ssl_setup(void) { int p[2]; if (init_ok) fatal("ssl_setup() called twice"); init_ok = 1; if (socketpair(AF_UNIX,SOCK_STREAM,0,p)) pfatal("socketpair() failed"); ssl_cli_tap = p[0]; ssl_cli_tap_b = p[1]; if (socketpair(AF_UNIX,SOCK_STREAM,0,p)) pfatal("socketpair() failed"); ssl_srv_tap = p[0]; ssl_srv_tap_b = p[1]; } /* Clean up SSL worker */ void ssl_shutdown(void) { int st; if (init_ok != 2) fatal("ssl_shutdown() called prior to ssl_start()"); init_ok = 0; if (ssl_pid > 0) { ssl_pid = 0; close(ssl_cli_tap); close(ssl_srv_tap); wait(&st); } } /* Display SSL-enabled error message */ #define ssl_fatal(reason,err) do { \ if (init_ok == 2) \ ERR_print_errors(err); \ fatal("%s", reason); \ } while (1) /* Start SSL worker and do the dirty job */ void ssl_start(_s32 srv_fd, _s32 cli_fd) { SSL_CTX *cli_ctx, *srv_ctx; SSL *cli_ssl, *srv_ssl; BIO* err; _s32 i; _u8 no_client = (cli_fd < 0); if (!init_ok || init_ok == 2) fatal("ssl_start() called out of order"); init_ok = 2; ssl_pid = fork(); if (ssl_pid < 0) pfatal("fork() failed"); /* Make sure that each endpoint has just the right set of pipes */ if (ssl_pid) { close(ssl_cli_tap_b); close(ssl_srv_tap_b); ssl_cli_tap_b = -1; ssl_srv_tap_b = -1; return; } close(ssl_cli_tap); close(ssl_srv_tap); ssl_cli_tap = -1; ssl_srv_tap = -1; SSL_library_init(); SSL_load_error_strings(); err = BIO_new_fp(stderr,BIO_NOCLOSE); srv_ctx = SSL_CTX_new(SSLv23_client_method()); /* To server */ cli_ctx = SSL_CTX_new(SSLv23_server_method()); /* To client */ if (!srv_ctx || !cli_ctx || !err) ssl_fatal("unable to create SSL CTX or BIO", err); if (SSL_CTX_use_certificate_chain_file(cli_ctx,"keyfile.pem") != 1) ssl_fatal("certificate load failed", err); if (SSL_CTX_use_PrivateKey_file(cli_ctx,"keyfile.pem",SSL_FILETYPE_PEM) != 1) ssl_fatal("private key load failed", err); cli_ssl = SSL_new(cli_ctx); srv_ssl = SSL_new(srv_ctx); if (!srv_ssl || !cli_ssl) ssl_fatal("unable to create SSL objects", err); SSL_set_fd(srv_ssl, srv_fd); if (SSL_connect(srv_ssl) != 1) ssl_fatal("server SSL handshake failed", err); if (!no_client) { SSL_set_fd(cli_ssl, cli_fd); if (SSL_accept(cli_ssl) != 1) ssl_fatal("client SSL handshake failed", err); } while (1) { _s32 fmax = 0; fd_set fds; FD_ZERO(&fds); if (!no_client) { FD_SET(cli_fd,&fds); fmax = cli_fd; FD_SET(ssl_cli_tap_b,&fds); if (ssl_cli_tap_b > fmax) fmax = ssl_cli_tap_b; } if (ssl_srv_tap_b > 0) { FD_SET(srv_fd,&fds); if (srv_fd > fmax) fmax = srv_fd; FD_SET(ssl_srv_tap_b,&fds); if (ssl_srv_tap_b > fmax) fmax = ssl_srv_tap_b; } if (select(1 + fmax, &fds, 0, 0, 0) <= 0) exit(0); /* Real client sending - send to cli_tap socket. */ if (!no_client && FD_ISSET(cli_fd,&fds)) { i = SSL_read(cli_ssl,rdbuf,sizeof(rdbuf)); if (i <= 0) exit(0); if (write(ssl_cli_tap_b,rdbuf,i) != i) pfatal("short write to client tap"); } /* Real server sending - send to srv_tap socket. */ if (ssl_srv_tap_b > 0 && FD_ISSET(srv_fd,&fds)) { i = SSL_read(srv_ssl,rdbuf,sizeof(rdbuf)); if (i <= 0) { /* In no_client mode, server shutdown means end of work. */ if (no_client) exit(0); /* In client mode, we still want to relay proxy-processed client response before exiting. Just let the proxy know by shutting down the server tap. */ close(ssl_srv_tap_b); ssl_srv_tap_b = -1; } else { if (write(ssl_srv_tap_b,rdbuf,i) != i) pfatal("short write to server tap"); } } /* Data from srv_tap socket - send to server. */ if (ssl_srv_tap_b > 0 && FD_ISSET(ssl_srv_tap_b,&fds)) { i = read(ssl_srv_tap_b,rdbuf,sizeof(rdbuf)); if (i <= 0) exit(0); if (SSL_write(srv_ssl,rdbuf,i) != i) exit(0); } /* Data from cli_tap socket - send to client. */ if (!no_client && FD_ISSET(ssl_cli_tap_b,&fds)) { i = read(ssl_cli_tap_b,rdbuf,sizeof(rdbuf)); if (i <= 0) exit(0); if (SSL_write(cli_ssl,rdbuf,i) != i) exit(0); } } } ratproxy-1.58.orig/ratproxy.c0000640000764400076440000014637011164370452015500 0ustar iustyiusty/* ratproxy -------- A simple HTTP proxy to use for code audits of rich web 2.0 applications. Meant to detect JSON-related and other script-accessible content problems as you interact with the tested application and otherwise just mind your business. Please use this tool responsibly and in good faith. Thanks. Author: Michal Zalewski Copyright 2007, 2008 by Google Inc. All Rights Reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "config.h" #include "types.h" #include "debug.h" #include "nlist.h" #include "http.h" #include "mime.h" #include "ssl.h" #include "string-inl.h" static struct naive_list domains; /* Domains to keep track of */ static _u8 check_png, /* Check all PNG files? */ dump_urls, /* Dump all visited URLs? */ all_files, /* Report all file inclusions */ all_flash, /* Report all Flash documents */ get_xsrf, /* Report GET XSRF status */ bad_js, /* Report risky Javascript */ all_post, /* Report all POST requests */ all_cookie, /* Report all cookie URLs */ picky_cache, /* Be picky about chdrs */ use_double, /* Make 2, not 1 extra req */ try_attacks, /* Validate XSRF/XSS suspects */ fix_attacks, /* Correct XSRF/XSS fallout */ log_active, /* Log cross-domain content */ log_mixed, /* Log mixed content */ use_any, /* Listen on any address */ all_xss; /* Report all XSS suspects */ static _u32 use_port = DEFAULT_PORT; /* Proxy port to listen on */ _u8* use_proxy; /* Upstream proxy */ _u8* trace_dir; /* Trace directory */ _u32 proxy_port = 8080; /* Upstream proxy port */ _u8 use_len; /* Use length, not cksum */ static FILE* outfile; /* Output file descriptor */ /* Display usage information */ static void usage(_u8* argv0) { debug("Usage: %s [ -w logfile ] [ -v logdir ] [ -p port ] [ -d domain ] [ -P host:port ] " "[ -xtifkgmjscael2XCr ]\n" " -w logfile - write results to a specified file (default: stdout)\n" " -v logdir - write HTTP traces to a specified directory (default: none)\n" " -p port - listen on a custom TCP port (default: 8080)\n" " -d domain - analyze requests to specified domains only (default: all)\n" " -P host:port - use upstream proxy for all requests (format host:port)\n" " -r - accept remote connections (default: 127.0.0.1 only)\n" " -l - use response length, not checksum, for identity check\n" " -2 - perform two, not one, page identity check\n" " -e - perform pedantic caching headers checks\n" " -x - log all XSS candidates\n" " -t - log all directory traversal candidates\n" " -i - log all PNG files served inline\n" " -f - log all Flash applications for analysis (add -v to decompile)\n" " -s - log all POST requests for analysis\n" " -c - log all cookie setting URLs for analysis\n" " -g - perform XSRF token checks on all GET requests\n" " -j - report on risky Javascript constructions\n" " -m - log all active content referenced across domains\n" " -X - disruptively validate XSRF, XSS protections\n" " -C - try to auto-correct persistent side effects of -X\n" " -k - flag HTTP requests as bad (for HTTPS-only applications)\n" " -a - indiscriminately report all visited URLs\n\n" "Example settings suitable for most tests:\n" " 1) Low verbosity : -v -w -d -lfscm\n" " 2) High verbosity : -v -w -d -lextifscgjm\n" " 3) Active testing : -v -w -d -XClfscm\n\n" "Multiple -d options are allowed. Consult the documentation for more.\n", argv0); exit(1); } #define sayf(x...) fprintf(outfile,x) /* Check hostname against a list of tracked ones. */ static _u8 host_ok(_u8* hname) { _u32 i, hlen; /* If no domains defined, accept all. */ if (!domains.c) return 1; hlen = strlen(hname); for (i=0;i hlen) continue; if (!strcmp(hname + (hlen - dlen), domains.v[i])) return 1; } return 0; } /* Test for XSSable payload */ static _u8 xss_field(_u8* value, _u8 head) { _u32 c = 0; if (strlen(value) < (head ? MIN_XSS_HEAD : MIN_XSS_LEN)) return 0; while (no_xss_text[c]) { if (!strncasecmp(value,no_xss_text[c],strlen(no_xss_text[c]))) return 0; c++; } return 1; } #define MOD_PRED 1 #define MOD_AUTH 2 #define MOD_ECHO 4 #define NOECHO(_x) ((_x) & ~MOD_ECHO) #define ECHO(_x) ((_x) & MOD_ECHO) /* Check if the page has a predictable URL, user-specific content, echoed parameters. */ static _u8 get_modifiers(struct http_request* req, struct http_response* res) { FILE *server; static struct http_response* mini = 0; _u32 ret = 0; _u32 fno = 0; _u32 i; /* Test for echoed query parameters in response body... */ if (res->is_text && res->payload_len) { #ifdef CHECK_ECHO_PATH if (req->path && strstr(res->payload,req->path)) ret = MOD_ECHO; #endif /* CHECK_ECHO_PATH */ for (i=0;!ret && ip.c;i++) if (!req->p.fn[i][0] && xss_field(req->p.v2[i],0) && strstr(res->payload,req->p.v2[i])) { ret = MOD_ECHO; break; } } /* ...and in HTTP header values. */ for (i=0;!ret && ip.c;i++) if (!req->p.fn[i][0] && xss_field(req->p.v2[i],1)) { _u32 j; for (j=0;jh.c;j++) if (strstr(res->h.v2[j],req->p.v2[i])) { ret = MOD_ECHO; break; } } /* Check for predictable URLs. */ if (!req->xsrf_safe) ret |= MOD_PRED; /* Check for authentication. */ /* Some field names may override our checks. */ while (auth_fields[fno]) { _u32 i; for (i=0;ip.c;i++) { if (auth_fields[fno][0] == '=') { if (!strcasecmp(req->p.v1[i],auth_fields[fno] + 1)) return ret | MOD_AUTH; } else { if (rp_strcasestr(req->p.v1[i],auth_fields[fno])) return ret | MOD_AUTH; } } fno++; } /* No cookies? Then do not resend. */ if (!req->cookies.c) return ret; /* Try to verify that the request requires authentication by replaying it with no cookies. This should have no side effects in sanely written applications. */ /* TODO: We should continue also if custom HTTP headers or HTTP auth is detected; we currently bail out on this, however. */ if (!mini) { server = open_server_complete(0,req); if (req->from_ssl) { ssl_setup(); ssl_start(fileno(server),-1); fclose(server); server = fdopen(ssl_srv_tap,"w+"); } mini = send_request(0,server,req,1); if (req->from_ssl) ssl_shutdown(); checksum_response(mini); if (use_double) { _u64 temp = mini->cksum; /* ...and do it again! */ server = open_server_complete(0,req); if (req->from_ssl) { ssl_setup(); ssl_start(fileno(server),-1); fclose(server); server = fdopen(ssl_srv_tap,"w+"); } mini = send_request(0,server,req,1); if (req->from_ssl) ssl_shutdown(); checksum_response(mini); /* If checksum changes over time, give up. */ if (temp != mini->cksum) mini->cksum = res->cksum; } } if (mini->cksum != res->cksum) ret |= MOD_AUTH; return ret; } /* DISRUPTIVE CHECK: Try removing XSRF protection, see what happens. */ static void try_replay_xsrf(struct http_request* req, struct http_response* res) { FILE *server; struct http_response* not; struct http_request r2; _u32 i; _u8 got_token = 0; if (!req->xsrf_safe || req->authsub) return; memcpy(&r2,req,sizeof(struct http_request)); /* Duplicate parameter value pointer array, so that we may modify it at will. */ r2.p.v2 = malloc(r2.p.c * sizeof(_u8*)); if (!r2.p.v2) fatal("out of memory"); memcpy(r2.p.v2,req->p.v2,r2.p.c * sizeof(_u8*)); /* Do not run contains_token() checks on file fields. */ for (i=0;ip.c;i++) if (!req->p.fn[i][0] && contains_token(req->p.v1[i],req->p.v2[i])) { got_token = 1; r2.p.v2[i] = "0"; /* Clobber value. */ } /* Ooops! */ if (!got_token) return; /* Rebuild query / payload strings. */ reconstruct_request(&r2); server = open_server_complete(0,req); if (req->from_ssl) { ssl_setup(); ssl_start(fileno(server),-1); fclose(server); server = fdopen(ssl_srv_tap,"w+"); } not = send_request(0,server,&r2,0); if (req->from_ssl) ssl_shutdown(); /* Fix potential side effects of our request. */ if (fix_attacks) { server = open_server_complete(0,req); if (req->from_ssl) { ssl_setup(); ssl_start(fileno(server),-1); fclose(server); server = fdopen(ssl_srv_tap,"w+"); } send_request(0,server,req,0); /* sink response */ if (req->from_ssl) ssl_shutdown(); } checksum_response(not); /* Clobbering all XSRF-ish tokens caused no change? */ if (not->cksum == res->cksum) req->xsrf_safe = 0; } /* DISRUPTIVE CHECK: Try injecting XSS payload, see what happens. */ static _u8 try_replay_xss(struct http_request* req, struct http_response* res) { FILE *server; struct http_response* not; struct http_request r2; _u32 i; _u8 got_candidate = 0; _u8* cur; _u8 htmlstate = 0, htmlurl = 0; if (!res->is_text) return 0; memcpy(&r2,req,sizeof(struct http_request)); /* Duplicate parameter value pointer array, so that we may modify it at will. */ r2.p.v2 = malloc(r2.p.c * sizeof(_u8*)); if (!r2.p.v2) fatal("out of memory"); memcpy(r2.p.v2,req->p.v2,r2.p.c * sizeof(_u8*)); for (i=0;ip.c;i++) if (!req->p.fn[i][0] && xss_field(req->p.v2[i],0) && strstr(res->payload,req->p.v2[i]) #ifndef XSS_XSRF_TOKENS && !contains_token(req->p.v1[i],req->p.v2[i]) #endif /* !XSS_XSRF_TOKENS */ ) { /* This does not account for all scenarios possible XSS scenarios, but is a pretty good all-around string. Since we want to minimize the number of requests generated, it will have to do. */ r2.p.v2[i] = "qg:qg qg=-->qg\"qg>qg'qg>qg+qg"; got_candidate = 1; } if (!got_candidate) return 0; /* Rebuild query / payload strings. */ reconstruct_request(&r2); server = open_server_complete(0,req); if (req->from_ssl) { ssl_setup(); ssl_start(fileno(server),-1); fclose(server); server = fdopen(ssl_srv_tap,"w+"); } not = send_request(0,server,&r2,0); if (req->from_ssl) ssl_shutdown(); /* Fix potential side effects of our request. */ if (fix_attacks) { server = open_server_complete(0,req); if (req->from_ssl) { ssl_setup(); ssl_start(fileno(server),-1); fclose(server); server = fdopen(ssl_srv_tap,"w+"); } send_request(0,server,req,0); /* sink response */ if (req->from_ssl) ssl_shutdown(); } if (!not->payload_len) return 0; detect_mime(not); if (not->is_text) detect_charset(not); /* Do some minimal and dumbed down HTML parsing on the response to detect q9g strings in dangerous configurations. */ #define HS_IN_TAG 1 #define HS_IN_DBLQ 2 #define HS_IN_SNGQ 4 #define HS_IN_COMM 8 #define HS_IN_CDATA 16 cur = not->payload; while (*cur) { /* Detect successful XSS attempts... */ if (!strncasecmp(cur,"qg",2)) { /* */ if (htmlstate == HS_IN_TAG && !strncasecmp(cur+2," qg=",4)) return 1; /* */ if (htmlurl && !strncasecmp(cur+2,":qg",3)) return 1; /*
    _EOF_ if [ ! -s "$1" ]; then echo "No activity to report on found in log file." exit 1 fi PREVDESC=X CNT=0 SCNT=0 # So this is some nearly incomprehensible logic to sort entries by priorities, # sort groups based on highest priority within a group, and then remove any # duplicates (paying no attention to some fields, such as trace file location), # group "offending value" fields, and more. At some point - too late in the # game - it became painfully obvious that this should not be a shell script ;-) ( sort -t '|' -k 1,9 -k 11,100 -ru <"$1" | grep '^[0123]|' | sort -t '|' -k 3,3 -s | \ awk -F'|' '{if ($3!=PF) { npri=$1;PF=$3; }; printf "%s-%s|%s\n", npri, $3, $0}' | \ sort -r -k 1,1 -s | sed 's/|!All /|All /'; echo "Dummy EOF" ) | \ awk -F'|' '{ PTRM=TRM; PFR=FR; PTA=TA; FR=""; TA=""; TRM=""; GOTVAL=""; for (a=1;a<=NF;a++) { if (a < 5) { TRM=TRM "|" $a; FR=FR $a "|"; } else if (a > 5) { TRM=TRM "|" $a; TA=TA "|" $a; } else GOTVAL=$a; } if (PTRM == TRM) { if (GOTVAL != "-") { if (LIST == "-") LIST="" GOTVAL ""; else LIST=LIST ", " GOTVAL ""; } } else { if (PTRM != "") print PFR LIST PTA; if (GOTVAL == "-") LIST="-"; else LIST="" GOTVAL ""; } }' | \ while IFS="|" read -r skip severity modifier desc offend code len mime sniff cset trace method url cookies payload response; do # If issue name changed, output a new header, complete with fold / unfold controls. # Default groups with 'info' items only to folded state. if [ ! "$PREVDESC" = "$desc" ]; then SCNT=$[SCNT+1] if [ ! "$severity" = "0" ]; then echo "
$desc [toggle]" echo "

Section hidden

" echo "
    " else echo "
$desc [toggle]" echo "

Section hidden

" echo "
    " fi echo "" grep -F "~$desc~" messages.list | cut -d'~' -f3 echo "

    " PREVDESC="$desc" fi # Output severity data. echo -n "

  • " if [ "$severity" = "3" ]; then echo -n "HIGH" elif [ "$severity" = "2" ]; then echo -n "MEDIUM" elif [ "$severity" = "1" ]; then echo -n "LOW" else echo -n "INFO" fi # Provide additional flags on all but 'All visited URLs' sections. if [ ! "$desc" = "All visited URLs" ]; then echo -n "" if [ "$[modifier & 4]" = "0" ]; then echo -n "echo " else echo -n "ECHO " fi if [ "$[modifier & 1]" = "0" ]; then echo -n "pred " else echo -n "PRED " fi if [ "$[modifier & 2]" = "0" ]; then echo -n "auth" else echo -n "AUTH" fi echo -n " " else echo -n " " fi # Prepare trace / decompile links, if available. if [ "$trace" = "-" ]; then TLINK="" else if [ -s "$trace.flr" ]; then TLINK=" [decompile] [view trace]" else TLINK=" [view trace]" fi fi # Output URL, query, and response data. test "$method" = "-" && method="[Referer]" if [ "$payload" = "-" ]; then echo "$method $url ⇒ $code$TLINK
    " if [ ! "$response" = "-" ]; then echo "Response ($len): $response
    " fi if [ ! "$cookies" = "-" ]; then echo "Cookies set: $cookies
    " fi if [ ! "$offend" = "-" ]; then echo "Offending value: $offend
    " fi if [ "$method" = "[Referer]" ]; then echo "Target resource: $sniff" else echo "MIME type: $mime, detected: $sniff, charset: $cset" fi else isfile="" if echo "$payload" | grep -qF "=FILE["; then isfile="(FILE) " fi echo "$isfile$method $url ⇒ $code$TLINK
    " echo "Payload: $payload
    " if [ ! "$response" = "-" ]; then echo "Response ($len): $response
    " fi if [ ! "$cookies" = "-" ]; then echo "Cookies set: $cookies
    " fi if [ ! "$offend" = "-" ]; then echo "Offending value: $offend
    " fi echo "MIME type: $mime, detected: $sniff, charset: $cset
    " if ! echo "$payload" | grep -q '^GWT_RPC\['; then echo "" echo "
    " echo "$payload" | sed 's/\&#x\(..\);/%\1/g' | sed 's/&/\ /g' | sed 's/%26/\&/g;s/%3B/;/g' | sed 's/\%\(..\)/\&#x\1;/g' | \ while IFS='=' read -r param val; do echo "" done echo "
    " fi fi echo "

  • " CNT=$[CNT+1] done echo "
" ratproxy-1.58.orig/ratproxy-back.png0000640000764400076440000022167011023013047016721 0ustar iustyiusty‰PNG  IHDRWÁ5^ãtEXtSoftwareAdobe ImageReadyqÉe<€PLTEÞéøñõüèðú¶ÒÙæ÷àêøËâô«ÒîÑáõâëù»ÚñQ¯ÊÜôêñû‡Äæãìùt¨ÉÉÛôÖäön—®Ôâö7UdšÌêïôüùúþÎÞõ¢ÎìrºáJet±Õï¦Ñí•ÊéSt‡ÅÝóÚè÷ÈÛì6­ñöü¼ÔçÀÝò÷úýÌÜôÀÚòåíùëòûÆÚóèîú™ÀÚ ³¹×ðÊßô¶ÖðÐäõ)1·ÙðÅàó¦ÆÝ%2:bœÀi‡™y£¼^²ÜÏßõÕçö²Øïàëö~Àä°ÍâŽÇèÞìøîôûZ€•,@LæðúÐàð·ÑåW”»žÎëÿÿÿ×åòA†°ËÝíÔâñÀ×èûüþF§Õöùýýýþüýþèñúøúýþþÿìòûþÿÿòöüó÷ü­Õîúüþõøýíóûèïú¾Øñæîúôøýùûþìóûô÷ýûýþöøýîóûõùýÿþÿ÷ùýùüþÜçøæïúýþþóöüíòûüüþôùýçîúúýþþýþøùýÍÝõñ7œ¬!ÎIDATxÚ¤—ýOiÇ×u•¡Û>+Š`À“h¡²¦Ö·½˜»UûÂÝ×MîB@ÀEyÙ. à µ½äþõ›™çY¤jm›NX\Hžß™ùÎlÂÏ0Ö)èöY8Æã–e©j4ªëŠ¢ ’$M5-ç¹nYŽ8­|lbõä´Ù+³ F¡ptTªÙÒ3ó#†×‹8gE9‹£| ºÈš ²FX¥RÕ–åÓømxˆªT…,®j "ˆ,DE§²VOOÛÄ"]¥ê%°H &œ· 5DEº®4DC’ePŠÀ‚+d¬È1> ‡9Þ߆ãøUÒ`@‚HÌŠìº^.—ó«HLWؼ¦m3X†h¢or͵Ϛ èQõÉl ¾¶Ä–S EY ±2HD,m.²)mŸy»u(|¤;_Öù¿GGUÁR}' ëu¦n±Ð{¦–gëkP¦Ð@Ê$v˜É´4;`À‚æ¹OÛÜþüÔk“½×²9¿”dPíd2ºÆ˜.I¡ƒ´iJïYÚÛßÎ`IŸê,z¾q.fQ°ÔTJ…´¡Ý_•—³ª¾1€¹V$¾³ÀZæR ŸÙõ­~ðÇRDCp”-Ñ¢“$X °[‚p£oà "÷ ¹lo† D‘µp ÇÇGè’ø~‚•se7”” øÂÃy-W{13Ð÷V»W²ÄFµ}Vpf2ƒ›†5îÈo‚ÊFP{yè´Z­½¿eï#¢$63mšNŸê~rÖîõŠW•ŠØó¢XÄšÒä§ÏßDž££Ÿ:®–ÞмöZ3++±¾K ôMgXÆ4ó1±¶(Ãʨ‰öHl<YYžÄ‡°æfÓÌŠ=‹9eÌUÖ2e'cRa¦›4Ôê!².Gºh x<Üò¡ëMIøˆ”Ú‰ÐöŠlìÏOóºŸqUbzÆS´%m,A ‹À²ƒ›‡ÐqÞ™fwbëN¬ŠÈðÖ[㬠ï?6n´¬€Á ˆSÈÝÐ+ús(,yËÊÑi¡+—ã.ÀæÁ:‚á8ÜW%ŠÕ€bÛ³<<= Q7 ª’hži9ˆ.øÃSª}Ár?¢‡nÃçR·‹¢ÈWðÌç.ŒŠu—u/d—ƒPSCŒ× TqÔuç¡ %ûáŠKH2 ÔÄ׉ò= uïÎïÖXhÓ²Ì/úCŠ Ê®Õ':†›aáúº 2¬ÙwtFd, cPn¢P«¼´HAÕµoÒ; âiƒ´ â3pú¢N³S~´h¢U»Çju?wQ½¡J-óIˆ¢¢_! ;Hcxs_–-åóù~¿uðÝ–H(Š6¡˜è‡X  À| (‡‰Šc÷¨æWYîÐQ‚÷IÈ !B©­rÐY›‹º¢¢£ÄSºf?ÄÂs(b•t'rCs^ô„¨ŸfTU-=$ YðÿOàðê(HÐ逰â£öu ßV5û+,pŠÀO𢰣ÚM^oa¡®Ttß¡_IÍvû NcFP6¾7Û½‹ »GKT8´ú5Y¶ÔkŠ¿&—Åä* žþb¸;ƒ_°ÄÉb±Y쉼|E4Æ ‰¶w•m¬l¶8W_pð÷É9¹“Ò»¬Ù„§àl–!G]|ŸSÍK5ûQ”-u*~Øg úÁTàÞ<£ü8ˆXðÿáò“ ¶J£ð_A¸+£üm”-5°(p5:××`#êYCH"äKûÛ!ùÇ(f  ¤šý=¬#~ðü–!j$@xó> ¢€/ŸÁ»v º´¿›E§à,)!5ü‹R r«Ú?,ÛRµ4µê µíGIÀ‚#UÔ€)Ý !á³ý=x€e_Âilîݪý3!îjöÏÆÿ°b·OM\Q€¯ÉB6‘¸z"IIl˜Å„$@> c§ã`‘D &„’ð&T§Óþõž·›Ý„‚¥íetø²‡û¶wïï1Cu(v P(u„¬#®ñ¯¢_ÕºñŠ?ro̽¾F•˜M\arÓe¾áq(šÔd‹¯Ÿ#8ÃØ¯¡¾R]ë n9Rj€âƒÇY™Öèè¤^¨ œF×øh3SìEÀNáø¸CÚ'1Џæd¢î6› Ô'.Ø:î1vTàÞQGÊ1>YöÇ÷¼–ïK)•Λܭ£â—¶N—kSSØ»©b% éÕ½ÅaÇàóu§Õô#‘» ¿Q#ê`eR¢ç!ß1vÿìè­‡|‚Ë] ¶ØÞ…›ò_G’þ[¯ô(MúÑòÁ‘]ðkA8Ëàؼ½¨Ò166t±E\¿”ÿ¬ñïzÏ0‰ToGQÅëTà+’Ž)uó[‡´±L:³XÄZ®‹³5À•£ë¾gy©¢Ž®)hx×K°q],T̬VÒ±ìñ:ÎÄÄôv©Ci©utë–ñTrŸ½$’› ½ªŒ-^Œÿ×¥uL 3)œO»Ë«¦>žŸÌÌb-î–&nŽÉêr[1ÃÀ#›pÝñ!¨ ïÁ“ôv —…ñÔ| œÕ¼ù~ÄÀsZDζÝä'7}Úô¶VðÑ Öš¿À?]„{²/2Ù³ìˆwêqïÅ\ ^â-»\ëšœ¿p²5©Tf¾«Ð ‹˜I¤RÙ¤r¹ŒYzhÒ0µ-ð„Ñ´[’‹¤[6øa­àû’™OÁ…½Øý™œ“ú!Ι›5±Uó–<ïN¢%YDa!mT¾ Ø›¾qœ à›±é‡0ŒÃ›Ï¼ÊÇò8;;ÛÎßÉ//g!^y çI‹¡$˜Ç"wé똂“Z×qž,Oç õl.Q‰åœecRõ§N>5| Ͳ„¿I!9™­Nø¦ˆýJ¤çg8VŸÞžMÌgœŠ;!ïµî,“Î>Ç—ˆ{y„;]û íyµ>êälÀ_æùà‹•Éªµ†¼ˆÁ–ïCúóš‘[˜Óë5“Qz0ºlâkˆsU‡Ðñ ‘­ ˜k=Ëà)ޝ™8ÄA-y>¸ü“×ä]ùvtO@:³žNTËp$IY&Kˆµži”:èßy$iy8h>cpÙèЪFÊÕ'Ogçê‹d6YÃN_ô3Á‚Ñ‘mÔ‘¬ùØ_ ¨µê`~‚zõE¢VȘ—£Ò÷äKS²L}Kbä­ŠO¬ØîKú³á¶çÞaBÔáHq.<ÅÊ”»©Ò-àþ±p•ˆ6Ö:鳎VØ:´R@_‚U“6¿üÖ{>„|â²tXê(cjV % –°#;þ[ÖÁ]¢ÈL±{µmTÞ%rì3&µŽ¦pº1 £¢Bôþ¡½ú,;kãÒ­˜­ÃB‡Ö‘.Õ„,|ÂäuZ°>Áóþár­¾f‰b…Vj·9ã K;½'M¨ÖA­&ßårR¥ãà Æ¶²Ž}ªMÊI@ì/YG#l_ZÈZÇÅ¡ PréßaŽX>©Îq´rÄR!Î…hùè›#;ô³…¯'!̨¶ÑvP–o·y«ãÛŒ½¢Ïߊ«|ÂZ‡x‡Š‰QèS˜Žn†+­ƒŸ¾eyÂŽ»ôI¨cÓZN¿¨^²’Ž:v>r!š&……M¦o©‚Qéà;j/l¢§’šŸX¿:ßzš¹¤GÖ9>´(PÕÓÐwö]¶ŽcrŽ}ûvG”¢À…ªhÒ;J×%&CÔqøþø7ѱªÇûS¦¥‚÷‰î‘[¿_ŸÍ©ö¢‡L´Ðçäðiu}Ž3›b§øÃ%lë. :¯ÏËæµŽpå—NÇšÐuË×c¶mzà¡b{$‡ Ž~þuì®í2uÐÜì®í†ˆBD€9àdë&Ö´NMÖׯ0Ë«j]nkëZ·Áɬƒ±ƒ´£kV_>Ü Ï³u„ž—FËvC4áZaèØìÀ*'7[·Ö« Wà"<°““gøfP'¶ÞÐ&zsò¿XÇo @¼Õx%táŸ@€(Ò;hi(?¢$У|¨Å¶j®ZÒÝv="!ˆâ·–ÚîÙ}ÿú;÷cæ7Зuì¼sOÎÓÜ;wî<σ…·v5Æö ㎩B{=С1‹4QL`x!!S^ nt+áòÜPt°¡àCé ËCºh7m^"9Ó"bâ?Ÿ½lÒxÐ{y©,(þY“FŘ–B…t; é Œæh:ŒŠˆ\(Û‡LvcR“C„¦6W €Žç};ð–Äôà`º3«à´¯bB4dCè&7 J³Ûº%1Æu¶N¶,(J ½ýéâa!Ç¡0ñºÁSïΰXsü=B"–È ^"⌒-G/Ì„X1FTÜ/k]ç€uŠaCUo¹™/jxö²oåòòZWŒ‘•°dŠ÷Þ¹Þ PÎåüÉ7ŠE”Eo@4$«Ø^bÍ ¸ªR ß:͈ÜdªRIœ°¶ÀÈÜyð^öæû†‡ššHüd§ÁôãIZn÷öCׯIddÜ™ÅíûO’Á»ÁàKàQ’ƒË¿7Ÿ$‹w Ú¶¡ºÈ+ßNœÔrz £O±0‘ï´ËìíØŠÏþE,ŒÓ¶ðx’Ý/€Ç &·[2@¿þ>Á¹¼™ º_'’Õê«äq¨ø¢™LVÝeÀEí}™$LÕ3,yGØâ>E )mB ‘U<ðˆødá'™[=i†¯N&¢”V÷œÖù?êÎ÷‚2{x`–ƒÎ½Eu¬oUfqqh˜úÎ…âü³z˜q{bgϦ‡Å­U¢4Sk%üñQ?’šxßT;O%y ,JÛÎZÑHåÕ=­Ò=hH'&áŸ>Ÿ Ôë3€…Þ)ív!’˜g ¾gTä„ë'o&³ì~OÜ/«Åê8çýª[þÙeÌ2ÝÝžùɰʮ`õÏfOÏrr°øÛ²{Èäw02x…)[nÝùòŒ˜ª@ ‚TÚY Ò®¹>‘Vê„E6î¤Ëí®öLŸÝTqÊ?ݬÞtµB ïJ¿èhù¶‹öDW±ëÏÁ" V ŒË57â›]Ú—°š#åTyÇÎû†Ña•.J•ea 3—t‚m—უ⚟÷Z$ð–Ëä–ó#,—¦pˉ§£‰rulZÌ(âT»»”Vïx©Þï™.àJ>¾”¹Þ­9ìÓŠŸãtd,dQbFauÿÕ«b,‹Là ?/<“¶YbLl‚ã«Õk²Ï8¥½Ÿô@O2ŸvO-GÁi±3ŸÈÅ,+F¸Jξ&Ú5» _×.Íz:½(v2Ÿ¡]¬P(úä`¯cF¿fXçªiQN:dà«ÚGGÌ=ô@qU¤ ¨ªÒ'Ml¬°x Ñ8þÉ–Éã;æ>òRS5hØÖà\VI•2y3ÇóyŽÊrtšÞ78h v÷#’èû`T‡Ÿ²À} íw´®LY{ÀC£‘©}Áp¤5s̤í6¡¤Õaê„ï²Z§ 2ëC¦ £Ç5á¤ÝßE·A¦ó˜…û5²ý•áÂ*ÀEÀŒåø1ZÛ÷v GëfQÀT?4ÌKxÞ|žc²‚ŽÌbzT•Çk• 9ÚIµ šm » SèÄëªÞØd,+•Ê—5VªÐy—bY¾,»ÙAí8Åü^FÓ©£5HP°yâ¹~t¤o6Äí®­™7‰‹ÚWéXKE9¯b ª¥ÁpQbËï¿öѼzÜT§‹Z'º•bï¢RŠï´õÇ ßg`|´OóvŒý*½/±P Xnò©ŽÅðz¢Bç1ö Ê€h\šõEâ ´¥%'k’÷/˜{Ÿü¼MDËZ´JdbŪKk2TËw·vØíÉÍ‹‘R‡ú¨©”®h?³ÈÇ î`ø’ Xƒáx<&ík5+T°°lE¥\ÅoZ)õO?bùŒëéauQP>3ж ;;Î\&îïÖ•f`bn^{,¯¤<°ìÖõ•q—è^[Ô`RÖØ”qÄÛÑ`QEÉO•Z¥vu»õÆ»”ý™d4(ð! Û.Ô¦Ý#àïRJ4Âuê(RPJßjŽ|ûáísÜ#Sõ+au¸*a«â.µÎ"ÖKOÆ29bOåôÛŒ‰†äààmûxCO 4"T O”RkÒÚkmEFqÛ:i>»òÍîO°v“{ë`g—Xw·ø ògkKùÏUn“³úMÒ ÷Ötì6 ·íÅEíûœ¤r¶#è‹`nyjœœœù ç‘i÷nϤ½!^&uePkJ‰‚6½ò}¦RkýK#å¼Há½VÎï=-d¶étJ «”.èêðVWë °©uzH¡wò&õNm{Ó…îàAQÓ\%Çã\îåû|ÀŽu=¥œë)ãCQ» 4_ÕU*L‡¦ÀJÛ®T¹’ô{Ueø58á‡`ö!ÈÈe#TŽò¬”¶Àñ•ZÎJí„; JÌï÷H°&·~ƒœúª5œÍÏÂñßk‡¦¡œuÍkÀ¤5fÌ’=k§?#ih³ý¡2Ý;òqI±ê´r=˜ 雲äP¯ÇZç+¹:13Õ©”Hþ]½6DZE§jÓ6?¿Øàäi«‘N¢ÕJåziXüÙƒO d£ÄŸn€¥T» PYý1ÃR²¾cØPOê­ÿRúȤF>¸vŠ!«­þÀaQ48q鸇‚ˆ¯ð-¹.dŠ 'Â5}Lá*ŸÔ¨¡c'f ~^ãTïxùº¶zúÃÁ˜¦ þÏŸÊ'ðD¨õàçÊêÿeüOæ®þ+­kÛQÔn«&!…ªXÄ‘V"éSc•ô5Á¶¯?.‚‚ ÁoMï»?ô_{}샚˜4íxŒxíM~`޵÷Y{íµæœÇ1ýëó•2» › ùó'j.ÝɃHj"„ž/*ÆÁ‘=]ÔC5ét“×¶UDZ‰·¡B–¨7ž°‚‹¨Nz“¶©U~ÅÍ7bb_¤L3 ­§Õ[°BÎMv†¨¯˜!üŒGì`ݤgX¨zL°hÆ>Š,¦|r´.X‹¨Î0€õÖˆ6÷øI#D±VÐBuyƒ4¢(4W¬hr¬’ÊvÌ—E¦BÔíôiW"¦ip°þtc [sb‹ÊÒí†ueQZL±™iN;±šƒ2…›LöÖa{EõIG£3øwD°±ÖÎI“Yº—ŰøiÞBRîÕY5¬‘MFe ÑËפöøó;Ž”ŽñmúBÌR¨ÔNç-nmuõøu÷¸Dôä#aW¯ÀH’=PMqê¶5‚Ä1ŠÅ¢7¸Zň9|I‹5l86:J6Å9,ªµ?ÍÁòPó7c“€L4|ÖÌ^¼5k(ƒ…Ì8h,š^CKIÛ¼°ä¦bâ öçG*./Ùª§GÆ “ÐKl2í]ÃêH.ñ4.¢žÂªËî:“Y!ñ§µ\ÖgTˆ(d²>f#¤çUO·yâ@T@í_œ âô›ÃÓœ´xkñtÑPËßÑŽßä¦ÅFÝt õ‡i5°X}Lþ̼™ÍEû…ˆGJ¥èW(ÆòË ÄŸžžîÞžß´ «Ä b£ÕBh¨6±¨?å8àâœjÖ5ØÐ#„ÏžvÓ‚”6üó¦}/£•{3Ó^8r_5 ƒáÉpïÕÏ4 }í‘ÿ&+ð ½X¯%²“F¥"ãÅ#õ¶ôàº?ðšé5ÝY¥ä&JÍÄ⣑€Ä3„¤îf¡þ6|xX˜è}õì°~1©z¿™ß*ÞÆÉt{•ɰGM˜ÏbèŠjÂoDRù+Iöµº:9‹|ÎÙ¸€*õ§Üò‘ÅGš'õÌWðö&aǧ½?{&Ã^§P˜œTƒ)œHy'ljòv¨F–—ÅùW)>¾›¾µÅkX6ü-M•‚À‘o×£ÀB\ð:NOFV=ÊuëÐKb*=‹á.¾GKµYZèô`³!.ê=\kÁ˜¸¥¥}o‘HàÜQÀ›ZTÙè‰x°03Ç^[æ£=…Ê£×°ÅS~n–¿Ó<›Nf`YkPÐ:ÊðÊåâ°ÝÈõ¬ +€MNw†²©¼“Vhe݆VÆ„²¦AÆðäÄ$­}¾¸‹’háÒÊ(N³ÑÙ¾ti$Ëâ/Ó‹1¢LY`üCÏwwSl|†"Píz¥o4;6‡4¦RMà‚AÕÂT¹m¨©5˜c!²™ÀˆLë‘û3|]ˆ¬øb'ÙÍœßÍEãÑ!ß\Âïs|A$»ùò)ÿ.­³´äôX9K—4¦Z>:ú_Ë!£îbw®«až3<Œáš‰íb«21$`ÙÞŒE Ë(¹eñ͉ôp6¦»?ÍÏ¥J+ýó>'/v˜÷‡æóCsÏK¥”sÕÁvÓœÖÅèù Âjëѵi²Û-8ˆÄwsúJ߬Æ üM?eXÃ˹H)XDZW"²:]”¿io­¶"B ù¸Æ—œ|¿ˆ‡ò_‹ÝehEŒ$u°(ßè`½Ç è©uJ×7ìæ½f¬ÅYÐG÷-f#c«…7 ÎÄrÁ¨«VvLþc-PÙ-¥Ÿ ±’ÈEb¥@í¹(&JÃÙñMÞ7¿˜K&K¢7”\Š‹Ð€uî ¼­Ø¥ê?u·ÐÔÀºi•_[CŒVߪXI‡bÒ¹¡Ä›ááD@à JñUQ ”DDžJñ´W¬Š€7:t™þi, \·Xªä“d@  $ã"o-!¥ÒâÍ9•[ëøXÓ(Õ¤ƒ†  ös°$úßÄÅX< Wel†`徇½•HÈ >l0³«">+Vú¨‰PòRF*åøWD¯Dä“€èO6“£Ëc•ðÌÏUÜÀ#Î&=´57Ð’dC<*ús߯ô‹Ù`6XÙÀJo µ Üï9Q“°OÄX**R——Á~1ï$!¾óI¨kbaù¬ ŽØÍÌŸ©e7¯<˜JmM&Rƒ֛Ȉˆeùþ{kvDÄß|#FD.T¾ÐÀÎ&²ÃQ‘¸tæV%,'ÿXüW“–&bÉ»Y$:g=´oÓÎ>+.V²‰h4,ÓtbQŠCKîq¦H94+rro )NÂr­«(jÝ.X]gýË*´XFIë¢n|X¶Ü6,ÖÜ’£cc¥Xn6–‘ÍæäNÏrpø£ÏSýbun;ó`‡çïùxDÊe±ê4å“8ç1kS: gÃbL½5°¸ÒZwE˧`>yŽÆÆD ˜î•¡ÎÆž„FGC¾áÔóÜä«Cp½ÈÔ†œôØK¿ožØd²¢XÉ¥ùÀÒ•CƒcÕµÇU©MÄ«keà Æ›Ë\eXò{W‹éØ‚ˆ¬¡Ôó\".J¡Ä¼\W?Á’Çuà§yùÐd–ï]οS‡)±²\ÅÜŽ’¿âSÈSÛ=å‹f®ÌðÔ²‚‚§OÂê"îPö±è_·È•Ñlú±ˆasgŸÆÅóÑÝgÙ¡Äc±–°.ó/FÅÿ²¬öŸ-ɇq^V6ð{l^."Ö¬ 8=a:!.¥ËR ÃuVuÃch§ò‘|Hd³µB¿H­ˆþÄü“èpöin>P›õûüDzÂÏ'eu“Ì.×BsÎ\*åOvC¸æº›Óɹ¹¥dia ÍÌ`í,J Ö¶Øáºz#ZAÐ\”RCÀ†—åÖhàéó…ÇÏü11¶êÉû²OÓÄJ ÎÇ"µÔœ¦ ª~ƒÊ~ÿ–ZNLÂÊTôÕPe‡÷ûû,‚Õ„f¦xjzD'¬¡D4©%ðŸÍÅb¹D"¶›òùccc1™ò<~—ÖýÞ1‚ž¥åÑÑšŸNÂ5€ÅUÖ‰çîï³a›ºâ_èášrVr7)“I°t1IŸ¢ëÎÍÉ¥òÍeÁ÷#1–N8H™Ir#þi€.+C%iñÄÞXï4*EQb†’šˆV;Xº†|é8º3Žuû¥ “„uiú|=ÐT¤Zæ°KV´ÜèMþÆÃðܨÆ6\—ÖŽh]¦²RáÍfüçŸùB‘K[Üad 2'ÎR†0ñŒaè[é/X¥h‚ú0TõßvçS¨Èæ=Å;°àC¤æÄBÊø(ÑôPw@ {xzmmÚ^«IXØ(5ž½›ŒØºKWc³›œæži¯6Ð`‡ãqà#®üBÚ!ÃaOxðGE©BkÑ&’ñ\ó/׿“; HCJÕÞµ7”Ê£Óc;Léw[‹£oz"*øF/6[<‡?î<lŒGwp,‰êI²ðí¯­×ƒ¿þÞÛúõoø(bŠFèyÙ/jkkµ§k-[€1ArôÓÓc£8ºPmÉ }FŸÝ ZËåùÑóZnÓÉoÃã…ñðxåE£8^l‡ p‰Î/¤d…МÜÉüâí•ßWìýíAÑK]MûXÞ­ý$ÄÀ2VÊKUM"íÝ2±¥%<ô V*¿ïÖXò4/>¯xšžiy_yÙ–— •B׃ßë?ê.½¶¼œ’'Qañ *½Ñ¾Ü[nw¶>ë–$2À§Á¥ëð oøµ&q!a9KËb9)‘KX•B£ñúõo¯$¬'¯¸èÜlؙ·–RËsžµšwí¤èF¥XÍSÖ©Ó¶DGwÁhòÍ ¸^î,†½‡ÍäØ×¢äïXT€YNáÁ Óï(¨'ìYÚ»ÚÉ´Öbµµ¢JXD–W…ò¹ëºÓ ÿ6*®owq>bÚ»‹œÉ,Ç?¿’À Ìù ‡‘˜^¤Ud#ðtþ¥ÿ*óÇÒhìêQ;Xuƒ‹íÙ¶ˆ]· •kBÓ4”al™“2  Õ@³Y0ž°•ÖIŒÉÖ½Hx-õ}hn)4ûoãíiGí”U·u4·3PK€âf¥{¼ßz–òko¢ñ\ºoT–¹fÖR» µ¯E¾Å½Û «§ÌÁ²˜±šÜuû<±Çðø{:ØòȘf*ñf^ÃBzš {L'P~®–ò²þºÒSîmšÜðÐî…Ðtàv\ƿނգGI ‹ŽBíy³Îü6X!åækn±roeZ ¾ØO(Ylž«žƒ+X××åÛy&Î-þÍ–oNOÛœ~:mx±MbZŠwmÓÓ‰ÆOLâÙ=p×BŒ»Ôwª ¸N˜¶L•yÇ|g|^Ù6Øb^kTš3¯@Ù­ù{°§óôšU%ð#jÒ§\@fAsg µÄ•¯ÐǧvÂz»¡§¿š6øXdUíR¯p "–ÛZ’`"f3'\Þé-}ÁÄ{%æ¦Ñ”ûÌù°>D¹V»«].ÖŒëªéÖì„`»2'æ´Üp\׺ÛÁŸÂ;EÊþzº©¶,Ä­ !ž?H³‘1 p´jÕ ¬E<¶ó¨K%‰ÉáìNû ç Tnkn OÓ­°Íž2l®dÙ?ÛùнÕ<ÚîGÒÀâân¤£@¤yu¥ÅåÍš >“ù*Ÿ¡¬@<[ߣ\ˆN7mT«Qz,ûÛ›·ËD”6cÇhDXßCEû;TèDtª,Ž•š­®X©Jéú!?„å¹Ív7.³Í©ÌZš·üCµOÚב£Š™ 2¹ÅV÷‡˜D ØØtÌs¨5tVˆHÀ¢µYƒŠtˆ]¼‚ðî1‡^Ý u-S·¨Îåjœ°KAcbsh‰j, KÅ,_Q‰#µI–³©yJÉm«ï·õQÜÏÍæKÁFyŠE'&Uq¨4ªM«r§ÌPGæ¬T?JuÔ‰ _ðìh”˳­ÕâœNFìV^W"LíÖÓ¤Qše*‡Œ{ºý“Aå‘^:TÑò…×ò %ôQwú)-ô!;˜ 6ÓÛ*߃3 Vû…ŒÚPÿ¢eËhÝÏjK‹ò£½÷{J¦¥/9ºD¶¹ý(¹C•‘eE†þ+cá±öS±hçt;TÔfPcSL_¿¨¿µ,Ø"½®žÝ ÖmЍ–ÚI-<õpC©4e@uM(m ©"6] ´—­i+ŸÝÉÉi4þhàwWôŠ´Z¸h-x µè}]*¥[¿wÖUˆF±½Áל¶N gÕ{‰µðƒ¢5”jñzµVj5”`ŠÅQFc§^9À ’M–¹š;}ç5:·÷ã;ZBÖù ù–‘™ e®ÔR3²s5Ï!NOÛ„e¢#Þ‹à ±¢úrÚ@€SþoñÄ%h3»¼‹ò£‚Š˜cPnœŸó)¨9öf¬³û¢÷TâP½¯â„ÍXëfGŠ^Ó@í´w&Vœ­ˆ“U§Ô®WpëÞ¦ø­.#lëêÔµi¹&kíæ©=Ž”ÜSJ4¥Ÿ@[c£Am}‚Å>¹S²°ÿhH–ÔnÂv­¤·Y¼c¥¤‘I±U1´]6àÓ¶~XôB»%wJ%IÛ\3¨˜:Vr ­s¹¡ÀÝVÖÿë÷j8¤¶S¨&  ד§^BšR-pS\,uÞXƒ}ŸÝÙ³_Y¢%€ŒFW%(ƒ ðèôôÀõÎu0×MÏ]ë]·>Yáàžp½OEkm', kÔ;”Ãm[;ÝÒÝmÔÛæÅ[d2ôÉ:gÏ(NX?FKº§Þ×BÇ1}຅Үó)—ŒÓ˜Qª—S íâìSaÑûbäw¿Gï÷µ›ê{%œ¸Ã¡t9Õ2eÒ»éWœ\(½«•­Øýqý“£EŠÉ#ü½×¡žÜ·äŠ Ãtz‹$äTÆ-`[Uí²ùÁ ¼ç›JÐy„ÇéHé'á|@mZZN³§ÔõTÁÚÖݼ¥~º¿¥„¥Þ«st@aQ¢Î…è…”–ÜÕšëMÕ¡ dIP•D¯ŸkÁ¯ý9R ˆÐ¼MÈ‚4u®ê<-¬k_[¸µõÙŒ;>`yé1„âhNì(MmjÕ+ÇéBç)¥>g«»D¦ð½Üö¡Ä}ºIí–c·Ö”·8¯¾< ‹u½Õ•ÔŒ4çgŸtÞÜ¢}ÚüÈçœö¸B„»ïõ *öÚæÄË<¶?[úºîLñËšnƒBI€]Lpá(LµžÒ\!þmË”­þ’öw ”º›à·4ÕäúdQ›I–¬Z®«¡`›T•ÝOï÷B¥Ãú×+‚§Îϵs3A¹áàL,”·ê½L¦kÅ;ýúšíMþ’.‹ƒi…(0S”.?|¨Õ¹èÁMÃfØRÿV¥‚vÙ“{ù/ªòcGýPý‡½`¬¶Õ¼¡ÚJ kÉ+Ëw S?OÀŒ_KÉþ<$3üýC ÏêŒi»L(¸Ú£nLõ‹ÀrŒšú‚Å1g¾%?í¥®‰”1£øB@¸Ðé­|Aõ ¬ëu~‹Š™ëo³„Þ,>ÿ„×G̰WÔ¦1/S{Ë&ãoù™«»5ÍÛÛvF`ò6ä„/$³tø%lìx¿HÕÅ=¼ú†VæëÃX?{[Êyœ^"v¶þ¥>Žõu:"özµ;MÕ·M:WÕ ˆ‡¿ &„ÕÖßÜv[º·Ý³í*[¶µ›9šˆŸ­—«Õ/ ˆ©¨}‹0Þö{0{ Uñª³/®Üuh§lÜñÙæ%SQrïòr¹\­þ-²fr¾ßnosÇϽº%t¨äõëÿ®¦³¿Gáìpî”ì#òXØ6bAxõïR€;[©ôùm†fÉì•++ÓŽõ/iþp·•À6½x@Y¸¬Êz#•QãÅðηÂ*[?®÷°½Þ÷Øo^FPýûÅûJªj}Ê[e ¨Š)àš^²@ö7«ÕõV•G‚S+¥|1ªêJ×áóO™8ëô¤“ùBY½<ž|0)+LëëgÕÒxüp’†÷:·ŽÓt[!3ˆõ³õòã˜ÜŒªzí.΋þ‰]t¬ÿ—Ÿÿ€¼kak*Ù²Ç D0(Ó$˜t t€O!’¶…«€ö(Œm3¼L "!°h;SbÕa$ë,ÿjtÃL×mw_hs±`÷!q¯‰Â¡&¥£a›7^œ°[L½uÏ›´_ûšÇPG~ BꦦÙ@»²Â1 `u5ØÕ?Nšõ‚6®8ò$ûr̆XOGõˆ!¯–­³—;Ü¢:!‰l{XZÐʽ@aâVµ¶Ìt5ž¦¤¸fH>šþbvaM‘Xi›´2â¹áÇJÊ·¤}@YÃr5.ÄŠµ¡ÁÒ6f ¤wШнÄý˜7ħº¨ypàŸÕXµ <êx§ZK _säiÚ¯ù"Y»øÓ±±\üSë)R>0X˜nà¶ï†Ç”´(Í'/©Kœ€%±²kTx¡Ñë»4èc?…zð®h1!ò9s¡ rH.©À’ˆ¡‚0/KAZ3üXbãqÚÝÆÆãó=‰œê;ö>Z±oˆNhJÍã”ãzšßŸ÷ÚA³èJ‡/\ÉݪOBfÝš+Ü™ýµÛ‘6SxçNÑÅ–ÄF§^ްvcaút Z‚Ÿ_ÅÆ€¼>‡_;ˆM³óÝ|àWgñ?NˆrÜM3©Úï&CÃbŠR àéy°Ó[ƒ²[,h5u«ªÏLWü CÇO\[$äR²\³¾Ù®ã«¥oXóùk”'Àw0¾×j)“™LÐ',ÕòF t9”AL” 0M‰Ùº"ýWî#>”iΙîÉ 1Ö©YZWõ¥-ãWÌôw½îÔ[é&¡»0éCÁ¼? {Ô]“šV,øÔ*`”ãi†Vå™\a¬ £ )‹€„'3J;*<Øy\ív#Ì‚°ÑçË`DˆGõÌ3·ãtü¡õB{Jiƪ¾¢‰Õð-š˜ï²vb×ùNqî£Â{~àÐ@IæÇó‰D"?T27[ yÒJHr $eî=/´müÁ׾Ȉ3m£-Zü9XÛËìáÐXÔN!“ÊžÙÐ’ R­ÖŒ+ÊÑ2žmd à×"ÉbpÝY—]Pî­Sx/m‰a]Iª d$BVö T?®åòáxÏÀÀÀüÕ‡?ü—뇇óÁÇO€h|ÌòL¥ßhE”`µú¼ZÍà²@ÔÕ(=nošÙd °±ó(SlëT/ìíÍÀXT ª ….áb Åö _¼Ò 5­P g`/™Q`(æégoóÀ4øê ìÍklY,ÑÒ6¢èkßµç@:J>?\ˆ'“ᑱ؛ŒŠCO) º d¼ç™§¬;Ÿ©7}ªÞñ¹¸zö"Š;jÑà·Ñ¡èèó -X½½ÏF‹·÷öÚŠ™Bq4¨õÌ0'¶³GÔ ïÙy}›cɉS= dÀª0kÝìIÚIˆH°¯ÈŒ±!%Q.|(œú;^}ø XÖ7ñWííÄóÆX!XʬžÂŽY!¨ž¡h&PÝÿ‚7ÕêoNuÁ8ëP2ƒ£A ÏÁÚ¶3½‹‹m ²‚ >™=b1¨Ùƒ.ª6i }‹ 1\­yæí\—¤ÔãBd×η8sS7ˆ®¿³Oã=°ÜC7| 2…ÖØ«|>?þJe£ã=? X9ý=­Ì@×Òâ)°:ŸîïÁèÆ·÷”›Á mBxKÐ V÷†¢/îE”÷ Q°¬BàÑ‹Àío£Ñ¶Báö³gÅ`áv°ösÛO{mÿêüÏZ¦VìB°´YÀwBD2,»G ü—gí§_õèhWòpó(ÞyE²9Û¢>µh!#=`Y¸„ìçM7oº¬Wn~ Ô¡Áºi</_¶ŒÔÿg™´ŠY÷ž=ÿ³–6nHd…‹&zçfkóÌÑÑg…`€¿ÔÍzàZhNè],ž;ÃYXàÚÃ5#£`$Ž6MÒ½A¯› ºsñn¹°ÁÚÇr¯ÆÇÁ¦PGñÁÍ\Àz¼ôJÈ«j´Z4Q=…àS: 5“I¿ƒU^!Ú—»MûnZ`ñÿÊ M•Ä´&¯„r›g²†ÃC¨>ÒÂқ QüEn¬˜ÙêZ–§!ÒGù´­©}/ \ïïï¿>°Î#^V÷RŽ‹/P©â«Œ”¡õ´^˜J°PÌ,mP®®†UC’î,Í`À²JTU^Å"AF{/鄯aT¦–Ü)Aá¨Hºðudæ¶½™SgƒÄ%áÚû@ÿ Ö”KµxpóÚ«ð@l{ g)_xëOBš0†`Íô¼¢Û²¼ êK_úy€é";U—粓-ÞåGÁNºÿýdMî2K×Úû2å©TŠå± ¹ÅK4QCul{.9Ãß8ѼjW ÌpIå܊׎֙ï™jÚË>° bêLJ±W‰äRÏR2‘Ëå“Ýwã‰\;$öcùxO,9Þþ`, wû ¬ÆâKC9¯«5Ilw«¿ðîÌT4úÒfc)þ ¶·dcZŠØfW¯6Ì6Ý(«öÀ•ЪöðAH>H©ûª¶,-ʾy Ò:Û• WwRIä¦S˜„ƒ±þžùØv<Ÿ¹ÎÝ$g{Ð>žì¿ž{ X±Ö õOÓª^Pu•c‰Hj"[^Úg»ºZ§#sår"RJM%Êå¹ÈD—òÜtk$¼´”,G¦'»&''»fÓ—¯x-“ÓÙH6šL_qÀ2[5fIloÏn9{*¯q Øè9ƒyd­49 ±ã¾åçÇF 0xÛ©±\n<|7œÏÿÝŸŸ¡]*r‰ëý ¬vkœ* êáˆäR€èƒ˜B¬õAJýmÉøv02Ú¢ùx,I¥æ¾ßþ¾çñövÏ\j"Géívÿ42ç%9Ý}”Ý~r}~ 95 Ý›¡¯¸—î>Èëbt|Of%sQÚuxI[¼Õc×zXß Ž°æˆ=¶°›•ovÆâù”B¡=ŸéW`=|xu ùªXóÉþüXk{9FçÇ1®·N¼ ÇffºûûïŒØá¤ÊëÇS©¼‚]}Y\!”‹äÆËñX8?UŽ•±'±ÇåéÖTbþ‰ú’‡s“ž×•MÎÇn-Í)3šÌö¨¨Øv+vkr6¤¡óåÉ…²RÛµ. •*î¨|†±ÝV±†ÏŒdF¦óÄ„Ð:Ñ>ˆá¼Rs°Z'rá«*Ù|Ò3ÞÞžÊår å‚K=בzU¥Tà­©ñp¿Br"¡Á"˜Õ§—z®÷,©Ÿ•!t÷« ãR"2Ø Å‰T$þXÙaÏãþp8+g[”qþ¤5Ý@ç§@áÇ1å§ž X—'“V2”ö:ÒÙõ·M/ÈZŸØö«‘ðê2ÑZ¹³©ë}»VŒÅè0±Žht<¨™{ê›ÎóL¬iÍÁχáÜ«äüŒ:U4Ïc/Ï¡ )Tfò©Ö›ù«wÉ ©h¬ln"¾>¯ ¼ŸLDÔ±ˆ]OäòóÝðU‘dìVgÛÕ`,\NÞ½>¸éx@Ðò¦+2Kå¥X÷\¨…ˆ&ÁѯN¥U„wÁªú±B"!lPˆÖ%³™EJC''»¾€Õ§çãV*>e+?ÐŒF×{oÜÈAf~5<®þb󷺩›Ê9—–Â9$èÓ`=Èã DTXÊ+¯Kä”Ï ¨·ï)+ âÌT¢G»Ä<²G±ûWïÇî&Æ@¯péxò@¤Ky_d*?bÉì¤Ç%åÉ2€A°"=šÄ‹ k#ê4'˜ßHnóA¸C»=´…èß8ÚÔm »4Ú°XŠÀ ^YÅoäzÚ¬™~©în—s­Útn8`3X)„CÙâp;œjås°5’œé/‡¬ÈÄD$QNŒ§B©ÄõX9…Dø“sà‡S]žAk»';ëé¤ÁšW`íï[°ø† ·Å÷šCA*ýqit·VvåÊ&“blêl”R}Ã8Ícþ1/ÏÇ[¬‡áT*{’Tщ02YT*ŸŒ%R­­‘ntCxe?(+/߉¤nè»K!¡YuiÎÔ3mÀò,´,Ï •ÑÕç³³—usp–ÁÚ—`í*²¿GdÆÞA#e÷R,ŠW²„5¬û϶÷Uwææé Üj¶!Àz< O¨`ŸJM<Ða*O†ã*UzàKY–Š'óêÈL*Óº£Ò%NF»ð #xÌG€©×Z&¦Ð !/E7ìɶ\öÒ“Ùx7f =Ù´¾õÌÎXÙô~•À ‡FdUT^ayÓÞEC•S§›³)‚{E“ ÃÒ¥ÐÛkÊeÁB –'ÌgnLä È®NÄàR2¾ÔK(ßÌõ<‡—{¹Y.‘ìîNŒçãO¹Vë† ÷ Ôi –¾øtå±àTè äTêàØ‡¶¹¥Ø­ù‡èˆÓiä YodS‡òä~Õ €ê…e£’Ú+›Ï;¦‚¥¼ðÄTeptS&£vúz]zË:-5S÷Pm™:#ódY,Šä‘H>¼Ô‹õK"Xmä`ËU²YÎeÝw{òÀ«rD26•š|xˆ`ué®<šÖÒÔº+/ì™ …²euãœ/gÁ+cw—ZØÊICjqµ<ÊÎÅ!+O^ŒhÑÞœmyP4T¹ØG‚{î6âægXrwÓ™vÞ"Êצ[Qž¹ÅµbÜ.„‘¬Ÿ HwbWó­poQ ¨—"­tlb4êšPÑévD†÷¯TŽ– —ÃñÛ1HÚ[(]͇ Þ€„-¡©Û±ûKáò’Â"ÉNÍÌ`‚ …¦-‹ ¡òvlf~)¸»5€–u±Á"®E]éãòÕ¢0+îz½3…Ñ10£µ6Ï}7Âgˆ—fåN›Ž[i°4 HŸÚ,R·è¢ìóa’N¹Ö‰üÒÕØ@28‘CçlãÉm¬”ãݹ£¼¬ v« Ñ«kb °}3PÎ…ºøâœîJÍ݆³¯» ÍNfoÝV÷u•³·x³@ëI<äaµaavzjnnn*«`\ŠmÏMþ¸áúè$呵Ûu|Z(³Â3êÔ#—MÌTê+=J³ ~6Å4œXÛ|YeU:ø€»ÄÏ'ùñHd<©ìà›ÇݹÔ8Ì?ì «ÌìJ!£ÀŠL«ƒ!›šŧú ÚÌLÿ÷w"!Qeh™ …¦‘F]÷tº%½€Ì’^/œO”oÎÙ' -ÕÝB6›™›ýÑÜ›±CO¬Y¬àÙ‘t D¡uäkåX®€çBhBû[Zùˆ¾”¶¬ÖÔTüz?yEdBk’Ð^bOnG¦â·¶Ÿl'&Tx[ºK—Þ»eà²UftçŽú¨buÁ‘ššž)ìÒo|3Dv,FŸéÉ~Ó7š]ý/›ŒÍLÍVMd׸‚˄ח5MÜõ¢ò°é6P­ˆ @'Á2,¹7Ÿ¿ôÞ?l ©÷Ëæ²ÓeL=êFH}.—J©—î e§Tä†T©‰©Üž€]©©~VºÉ€•ŒA” R˜Ti°.{³¡é¬z¦•eTíåfÀ D‹6ißÓ„º ƒÕ+퇔_VVÜÕÉäTƒ—Á-ÀÒÛNˆŒŠ¬å¬kR˜~8ÓyÇzñ›´ù>–×tºQÏÅÈ™4§”ÜLä/‚ ÓÉX$âÜB ›°lʰsˆ¬›À u"SQ X}Î .ì¶éA,ᄟZô\0.{yX›G½Xf„˜k/ë»§Áz#b—+~vÆs݈%ôE—K·‹äNU“¿¼ã«ó®Û ” V½ðgAêódž3EfþÓ“¸BXê•2™Ìs õÅzïÓ‘hIå,ŸLu4;Þþ>+¯ìKJbä§Ùveå8ªÐB°²éQáÇÇ’×Ä `é¾³+Ö;,»©çưœû eÓ§ôI]cŸåXwpf¤¬¸ôEiô€ñºŒ`%fîD&õ”ÕH‡!Šlh^5AÝU­îï»lš™»]i¿Ô‰™Q9ûÂtÁ)væËqsv ìï4½Âîk{q¦ž—‰ìç–Ñ®îHššE’Ï2X9ò|χ:Aþ'Øöm@SßíK•)ð†L)LN-ð2\_æfîä&‰Ù–5¼€†ä¡jÅ¡šaW"*¦•Þ7–ûÔÀÁÿŽÙé9,9n‡§Ó?*°Ê±;Ù…wçXRêifÁ”áCû°ÙÎ×Ü Óõª»›e:oÿ,ωTëy¤þ¿Þ¾ý׿"ê^t¶½x3.0¨N hÎ3‹{ÅbA}¾ZØ¡à…`e'ÑGFªCm/à뇂{…ާÁ½½ü®ÅNn‚Aõ½<s Ö…qÀ‘Y¸,õÀ¨Î÷‘ô‚5½€veHþD¿Ëæì/©áµ»ê¸ m¦žÁ#õ‹*æ.ý¼eéfq5˜é|Q,ª÷©†Š·GeE QHPöt»ØöSaæ6z30¯1ºQ¨2Z ¬í;XbQËEõ6Ñ$ƒplÔû©oéÍÁÔçj$±5òQ³f`!4»?5EÍ‹¹Y–b8a—®óA#õðµlâhÖ?ëƒ’Š‚öL×ÅÂ)2yŸ~,­“„üçÑ`± ¦¢jÁ"pÈEƒC@‰®þ¥ƒûgàÖ^ò E®Ë—g³êTÌê@~éjðÙ eXµ`Ž®Îcä~v)¯ùóϽDžZ1Õ¶% Â×1‰M©ôm•ý—';4X6]°Áê’(óA&úZœ–2GöñAX¯ûSQ;^þB}ÒZφ:@÷Ú¾mû× eV ÑNå7`] ²¡ Â óžr¨`áE4°ÞI;m +à|ñe°Ò¡»ÛÔÿ›L_A*é`U´Am*xŽX* m4Î@±fü£BënvráGj ¦³K ¬‹ãE uPWÚ¹-$(š VM¸‚ÌTÃéoÒ+­ä} UG‘7èÖ/UìÁ>‹zYưOщèͪËq(49 bŽ ÆVï0Â8\Ö\Ü+ìÁÁ7ˆ¤Ô|þk ³ÓwG”u]ll\L–ïÇ’Óî•Y0W±YP·K,0a¬Ò.hwÒé=Ð@Ôð[¸+üëž³¾ Ø©]šj“‘–Y0)ÆÉ7H©TÈÅof®6Äüýü§g{{…÷EfèŽÊøkÓ `\ݱï禲ÙHrã¼3&*V&¹ÄWÁ¿Ò!x޳ÿöÓ?è]}"ÿ²mJïW¶æSûx~݆PÃQ–eãJâ‹ Ë’¨’pê=e`ÅH…FGQÁ˜¼áÊŽ*ë eç [{÷IwvöǽKþᮇšÆà®ÍCÍ”Ìæ¹¾ßhJu—(£D˱_L¸Gð4£Ø×e¼Î浊HÒtsÓSx\\he½Ñhñeµ<µÍ4øS×5Œ²µ;Ò*Ê+g¬-ºq]”C1³:I»û æ1žê«×w˜(ZáŠõn¡zŽE]Ñu˜2Á•+ú!0"¯yV@o@Œhúò}»fC…aâ´Õ\¼’ì–¡âǽEß0­­±¿3¥˜]¦¼5·æ³3=ô¡ÕDÃË¥X{»†-¯/ß×õœ*ÀGÌË50À„FÒGFäšÍˆÜCÚ±âbqd4ÚHl8UšQ®âbcùR‘ÙŽ—R‰JR•{k>wvlst®×ˆ…å+(?¶Rô‰°Õ!î}G€¬¶øK.ÒŽPÚýÌd(rþMÙå'à®F iS‡W‡õ¯¾ÞœW|‹L'n©a€P`ù«À2§^‡–ÙöWœš«94ÓØ·7ãFzw8òÔQ¿iq»¦¸çM÷º„ *ša0ݦtÌÍ®MÝC•í®‡i„D̾–²Æ1õ¥}7a B!HÖ¡7´3²E:ûèb¼_uµ ä0¶ñ=­ ÷Oéª|¬o˽—œv îÜ@ëf—×pôUðìÌÒÿ™“Jòîà¼%)⯤bñ¬×Œp`öYK#’û#6 IŸ»pAbœª¿\€Ü;u;¦‹fU°× ê´ÎÙ:çë"®ÓÄǰ$"«ø9£œiQî~-g(æ^X“°È˜=²?2">ôŤ Pw¸ø¨¤‚JlðÑW³íRâwîÕH‰ 8×™cÏÀÕÑ´¥Ñ›¯Ô?fVœZ}=m…gÇñ÷IÖââcR]"®V/šTul)`¶F¹7JáÞ›9ül¹ø’.ÂìXÕ]²*Yb×a×,œöÍŠajÒ¥vÚ2ù5[^õ£Þ¿Ò¶§}lÿcßpîá,?±¡Mj}oÔ)¨ÙÓCŽMb¨^êPEÁpÚºñªAªO'V×Míx…I’¨ƒå˜_GˆäQùÜù1Ô±‡Ù¹U ˆâ uÔh´Ê„t; #õK⪬gxЃ$\J^MÊ[q––Ä,‘B^&Ÿ_–-TõïýxÈ¢Sµj 7¼ªÔ ÖáyœˆüœJÄ<×!jêvzÖTÖ™éùª0È?k/î͆/åÒ’qAC%E쿚ÒÊ ØLU°;[ÈÇZÕ•W È¡6¢Q©ŽQ´§Mó’Í1U>õÑ'E).é]]ÞÀiG½Yy"h^‡ý¢–ÚÕ¸ ¼ –Hù7°–zؤ‚»¬Û²ú’œmcÃIÍ¥EÙÔ€8ÞïÕŒE™±Ì>eJÅÜ1‡DóÁ #œVÉÙÿ>A¤ºb ƒ×]&Î-Þw.•~ 'ÞßÎþ²Øà0 Ðf7V ¨JˆF}*4£VñlÔÜõHRDË›€Ií‰ËŒi”ÚªúïríXºnb¢–lÏî-:‚òäÆüº%\ûºbÌÇÀu‚‹ÿ±p>%ƒùxÔ*ÒÔ´‹ÂˆFÕ);—bV•Âî3“ yß¡-VÁ2É‘¨íi÷ëC¤XvËwi¶fÅ´³[¿™Ì+âå¢õIé QS9Å‹‚'ZŒŠ|œ×àß÷Vê„_L0×Y'ež¶(B©»|´+ˆÍÏÎÎLׯ†õs±«´RÿEöå×mºü+î7 `Ùn1I¡}Er­Ñ(®ˆ>Æ:ò=Z§F0ÕH±fQD…©^‘ˆÝxÑþ$ Ì?4[$'«rÚxÕ”úÜŽ<7åë‚2Ô$¡%æ+-—J¿‘öÎÃÓ¼™|‘A´èh±ÙS3áø°5#Ùò»Þ&"5zúE‡ôw;ZØÇNw¸dùg¶® I»u¬ª×8w„–­ßLc÷¾¶Gg:½²ùa²¢U¨Õ4®5V]Â\€7I-NÇ,žul,ŠÏÖ¦¬¾ˆVò €NB$/°j‡²‘‰Ýpxs”e˜¹Ä^ec¡|@íf ©ÿ=ø»5%•-¾¯${„>(0Љy+CíÕ¬ú’Ñ`Zt%l(w›Ytë{Ç“ ¤Á{£ñ×@ûL¢p€œë•æ<ËÄ­™C/‚Äcý®® UMB¿¼o¢PÐèŠe™½½‹RöÈX“ÙA¢Ñ36©w/u?‹[Z¯zÆ‘OÓC÷L7EFnV®ë²±ÉA™M´ôûñ{xá`k9,ê6á‡0.²õ,˰MžvÜë3¦&ÒGViHªÖPߌj—ÉNŽv¥“YÑ9¸Pñ¯Þ¬Ë=‰ÒÚoΫÀ¢×ÄÔ[óDÁлH²fÇŒå1EkL¾)-öÚSŽb’©E !-–krp2ºLÈäÁ[6'0Œ-‹/«gÃvÍróTœœjeý—uw÷f  K¥Òï —w‰eÂì³èü†Z4?ù5Æ.iÕ³^)56èv¯d(it™¸>Œ)úÑꉫò1l½¯OÐcªãOŒ-ØÁPAÓG·e 뿯eñ ö 93²‘í5'`7ÛƒâŽwiÐxzÞåf»±mÑØJfŠƒþZ—¡âÌ–­ˆ5)éÆü`¥ß,Š'ô¦öí{åG”F|uðvnØ’Ë;±y´NÛk–ÕuÏÆ Ѱ¡b±Ö°¯;§Ÿ¥%bºÚ­å?„2ÛÓ×KƒŽi4 28hRIW²N¥ÁA_ ß1,CX?'é8|@¢‰‡„ŽœhXhØIÓIÄF°×ë FýŽNÀÓÓßÝ ,k úd÷¹‘Ö;4æÃ_àâCŸkÚ1zh\Ö…@¬ c²'®\’ˆRÎf æTz‰¤n2…ºŸ¾þ-’è/Ÿžþa¼þ;;ô¢ƒj~ Ï%ÿçw4LƘT޹#`Ò2m&ÝTng§ƒÜYÙÆÛ G*gºÊn®ø··˜1zkùKÕ&GiGì/ßréOÑüÀÓ‰¥ 8$Dxš-@@^êš8Å!¼ÎqHÒ“R»t ˜LÙàÈÕ4"s›Ò¢ú´ì¥ÉÐV…›„¾ãúÚÿÚ΃nmmý)¿¢Q«¤ß¼‚.ø˜ºàɯ^ÿ²ø)µŠŽVwN:›D­Z±;Sšêë³Âi4&$/~õù&«,C@‘òÆŸ¢¶á©£\Ee$ªŸ'Ê¥°³‚à€*K~êûœ‰7¸¥×pÐA……:2g¢'Ã'›V{ÊØ%üû#JWfYÓHâfëÏTm±/J£Ì‹w²ŠBaWq‚1×b¨*@2¼®}ôåMК<ã—a!šHj³Ï,âà™¾ôÕ}Ÿœ•eutû­B_Ö'Ÿ£UqÞ}§Õ3ˆ`ßL}´Sz~`G^HÏœ}6Guªu«ø–«Ÿ¥åå­å?õñhå“ÏpÓßÊœR%@èLˆpZkb¯“ò V¿…6„úÝz£óm B­å¯œýÝÀ:ÃrœRôÚgÔ!hŽÌ™¶—Õ³añl²Ë9¡©ïàÀiÈ0Mö 7ÜÍ5¦*ÉøÏ´V8 iÕ_ç…ö¡‹š9¼Î¨]nî%gX¾<–]ôáM¡T¬¯wP/œúLžY”H³¥R±jÎEfE+ãÊÕ[qù[晡¿BÑÉ: Û…c$î‡ú#Ö½e\¦Ggö\ s —÷âºïÜ“Ä{ëÎÅo3 ,|:X}ÎËrH‘ÙVœxí(óh˜ˆÜ™‚ Ú“n1ÁÐz]J†Ú*‚Ö448­½å&Í_¥|`p7Žo±ÖD| ²,°ÁÇt¥ØŠ6Ïm“Ê6a¨l : ލê/¿à¼KkSÚžÖ)šsßù¬NK§Ë9XçjĈsMéàÿJ±béiÙ£b•^Ýõ%äuGq]*uÚͶ-œ§*Ùå¶Ò_ꬊûÚaçnà1SAüœ¥ÍV­žR¬h„*º³Ž,®Û¿Ú¸Zgmª´µü7y<×as80ŠÍç¼ÎA蜟Ógô/f݃o*+Üònö²˜Ù‹*(œ[*ý}qb°0Ô÷2P7o/­Eÿްʺ¾Ïé¿¢‰Ï9œ¼ 9:4==Åžný­-ʀ儕úºÖ›·ÿjô™OÆÃ¼óºU_?Hkæ'Öð>%qñåÐãù´å×l”ùìC*ðº6 òK'€º&¬‚¼åé xæÕäR–x?>ÑÅu–ÙµÅ0Ü_} k*Dˆ£õØ©ZŽºãËàuP=8--ÿãÀjxÖpX÷öMì½ðLÙ2y\ðþö!ü3`m™xBÿ4>æ³[âØ§O¾¥Ï½]ão/­ñ€0êÓ—H; ‹+%Þ³=ýGƒUÚÒ× RÕÜZ³gyýDŸ+áp*Q«O½}«×³³•ô|Æ)e˜ÿhKj§;zh••AXT_juN´¥«»%äŠ-Ñ5²IlM‚!•P5 mètùÿX[ø‚%äqÃá&øÈÀD zö¼òoõ§%*[–°wGãc°ÿO™’,*ƒPöŒ ÌÐ gëÀ0s }'øŠS6?=Ý2¼@h>˜}Ÿ.ÿ?x¼†Ï”t ‰‰Zøgü“Sž+-ÿ¿|þWò¾Å¯©$[7$˜`xD@$ÁБÐI¼H@èµQ2Úr ‰$ ´çwÏõ_¿UëQµj'ØÚ­ý˜³ÇQäÑ3ûëµV­Zïó‘Ž»|´®ýÍóžK •5ÇÄ¥?±Ò¦UŒœokyowom}?ÚÀü-t¹‰7H’›³¢)/î? M!cûÆÒ¾Šr#Þ'ØîlÅ»@um&¾KPi¬ôôGˆ} ~÷"Eh³.·Ö,¿*‘º*ô5A±Î+Wç˜7Ф îoK$x`yß_3seˆ€diûPj€XAºwH¤3Ç´½hXFV„<²¼ºA0V¿|¬¤í},†î&Aw©‰U!Ø,a޲ݪ«(Ú:ßö«êõj½K»²X¨v=‚î̈‘™Ao1V@䯫Ô¥É09æô‹ CÒ@uˆß>|ÍKMÀ²ÿeÜ<(Á;+ëGiU –4«f"ˆòiàÞ·œòÝŽY9"š.±”#/ÃÄ@u¸Yp´õ3ÇIÜéDº¯8d,\hC¬Œq4 `MÀê  Ùª´’¹@JHá6šU£6)¸páâ‡AYºN…’:2²‘ VZAÓ‰VÞÐ:£Ù!ÅT#è„5C̉X©,ÀgÞúsp5èˆë?‚UÙ`…†¥%¦›¹`oC`Gѧ÷b½X¶7¤v…|䃒úçÃÖî;’¢Û¯…$¤GÛ‰·;ÍRØU‡=˾'B¶ã’«~ÔfuUÆ*„n!¬7ÁÊ5«æ²^ThUw¥|ß:SIì#m, þ:§ ŒVÃX'M¸òèØž!œ¬8d“¼\¦G{!Ýô™ÿRÇ—VG‡ã}"UøQ„uáyRÞösP¶Žž#rÑkWi–-캴+&Ùú™$ö´‘‰)Þ±«½×''(éÒAà!xF“˜€[Hü—¾ÄÄè‡äìPÞ÷ãU4+ ÛŠþI¤úšÄ*× šEvËRÙ QN«î÷õrí€TxºšÛ aûnK {l…8²\o!Ã:ç "§4˜]ò`Fa\}êfj'uSƒÚýtZõ£ÓÙ’Úúø7ר<çŸëx>øåHg09ª<5óLD‰4pÉ‘£{cS˜>ôd’úÜ´7ËxgFµÏ§,¢ƒl PÂàs©1¶¢ŽK7'£¡èTÊä ìW? ¤½†ÞÔ¨Œì¶Õàv̪‰j¹_èý‹Ëá¶”!¸ala{Ë–eRdªlý­‘‡ÖÅÄêÇ†ËøÇm>­Ÿv\Ú õ/Ž MÞdPÔÿˆOÒ¦$P½ÎŸž¤Ê#åC ëB›ç‚‘{º(“«]!ôD:kÈøQdW3+ؾ=Ú’L6Ví—'ëjr9tÖ^€x†Å&b2&Óqɸ&~íæ¤Vì[ŒÞ¼$3uŒSWɦ„ õÑo ©Qo‚î°:“œtÑÁŠý’e=c±P‹§ÅÑ'·j <&kòv»À_«5(Ñ•Ì̸O¿jš–1¬K&yê ˜$ììæ”Ö‰ì ¥Äé÷#%TÖ¤ÒrŸó2Ö=J§ïüSZ_t?âäêT‚Vêé¶Ù®n'dÉ"!-ƒ3ŒFh}гe }ƒ:fX¾«êøúD~ÈètÈ|ó[x3 2‘C)8ý”E1R|î¡E9‘»Õ¹ó5$蕈1}7÷Ôý¤ÞÝ´:=JÒ¬¶‰áTÊË0U§á¾“ÃàëAGËãƒ8iHå9ß'}Ö»h™ûa‡¸RÊ£]„Õ'4ª«Wd¨°Š@@½ŸK<{ßê}JÆ/²h†¡ÄXµ*…‹€h‰w™E¶º+T:å1ˆÒaŽÔ(/fkb¡—‚¡/ƒF«æìZãä…á0UX]ýçGV‡ a)þä͉TXißÓ?±  ê³&…x$~"í1ÆßË»Kâ¢D €±D¢=ѤoÀñI¬±Äôl‰­O³çº8uư´íª²[ç;L`±FOîqÊPñT›ÆUÆìÁÕ£ßW[–Š\^ÄŒÿ™`/±’§Ÿð>“$ž±5WƒŒâxÂl‰êlï‘'¢f<­V™<Ýòî:ZkÄ*O™(³˜9b¿,A@¤ŠRÆyì)èè±–V Ô¿#¬>é_ä‰ ­OŸ}«kC;:ÎëšVåSRxØ'ž^lP±³©e: öaº¯€yärE0Z,UdßßåŒA0Z2C¬‘…4ÙU‹a Ð É$r¸u ²+NNN*’žE@E¬ç\C&ËPŽô#z#!ÈÄá:ì1³K—vbZýóZtrj*Ní\"³¢@õž¤³Z_*»yÚ}‘”Ö|Ïzž_8éצ؄&¸“)>ÛßÎåö‘׌༬²R[b¾5S´ZÚ&YÖ)/³i“öQ±R {–Èí—g‰JŒGûlaî=„$@˜«ÞÜÙÙÑð„@§õy×òÐÐÐòòPlêf"ÕÇF’W?¤{~ÚM(31ZFìÁÆ>u‘Ý܉-÷Œ,.v]û/…UâZ×ʵÞJuÌ«"£Rï£PHTOYTa Heõ®‰1ÿ˜V¸óõäÆ~~0=…@b`ii;ñr{ÿÁXñE.‡¾È"b»néŠNAd×Cb¯ÃÃ&I».‰b‰aËÉÚiÃÑ#2j&Èt—Øöq®zÄë*ŽŒ\G*4òðÚµkÏÚ¯<¹mDeç†//‡&o~2XåÚUðÏÀ³DµÇ¯uê”ÝìRbùü¹²¨Àn®ýYulìç@ÿN.Йëì tv>øAËŽõ¸:ß`^/¨Ào—¦F,N ‰üp(:9¹“º©£•qÁ@@åLéÝœß?’~‰ç¾ê?é4çä+ŸzÉÎí:ÏV™ê5©W}©À¬zº_ªî^ZzùòeD«S¸ Ú¾ ¦%¦ÀÎ\º Ø1oxex=fUój¸Ã/ù°ÖÔ-çé˜Ò]iØÕõPÇ+}yÖÕ…y“…êhe°ê è§3Ñ£Œ!asÈ€¿Ðæ§Î1m= õG s ÛU‰ýâij—‡/KKÝš½ìÅ¡ÀÊD,G®€ŽA«akï‚BÒ–cŽë|¸Âç!Õ_cùؤ2ñ kÔE8«Tthdq¤_»]ÿ5Àjªƒû4”[)¬r «v¶+õ+¡…sr?}>èQîª}¹Î„Âj,“€oÓ6øàÁ˜Jܾóà¥:Û—–þµ”;Ül¿T&26ºWe¡Ýßi3‘[µ4Þo6]ýZ&,c}µ•=»Î ÔX 8àZÏ;vÅ âó°út3¥ò𹨫#VôcæÌ¡]=SñJYMί°ÚMcržø§ÊÍ•™ž¯kÍͱçc= ¶ùןù;Uøº“èéyðL™QàÙþÇÀÄö‹À¿žïI»ªŠÚqµºŽíæNÊ>n‹p%5f6™‹Y2æ:£+Fch'ÍþÙÙj]$úæ¯^•mAq5™]VgL;i}°mž]‰LjÞú¤þDÇ¥ÔÎä¤ UxI¾*°º*ÚïÖ°|¶üS €}+ƒ›Îax~Z•jäi+Ýc8QX”dÔDDdÇœ½ˆ¢KBÃ9*ÄóÈ)1Œ£ˆn ³YÕÄ?¨ü!±j¶DS-t*êß:RS¡˜ºù ÅtÖ©¿µvE¥Ðy(ñ‰º7ª ## ­ÞŸî¦Ó^ñÃnƒò¤ÂWOÅ ‘(³ïSÊn§cDd³IL‚"²ÓÞ;¯µòˆ;ã_*Pze—<|Ü€Ù™ Ìw‡‡ïú‡¢;*¡ê˜Ò5dƒŽûú,Xï¹HÅ ½o]P_E9êv®žB¥“å$¥ÜŸ·YÚL¡ÆÌ0°PÏGkÀÚ‰gÏ”¶¤lD+ÌD¥¸Úš“\!ùAÞcWÚ8æÛæe¸ÂØ”Š._6·¿åÐN‡‹U›h™Š’¨ÓjßÚŒ'“ñ`ï¨6­ÂòÆ–®ÓÓêyšY¦nE¡}ßSg¿a²+ä‡EFô郔]Uˆ¥ð.XæI9îé£I=`kêPW ËÍèÐpäñˆ.¿ôlD–£êòGX= uÌ3X¢ËåÌæé±—ÖÞ¶xø~9TžÉö* ì/4´L™[_¬ëwêÈo[µ¹Ú7§`Ã0é¬I5Áî}"¨$ÖVV„`‹Z4`E@é²7w¦t /ÞŸŒÝ‹ô…¦TpÆ”… MÝX5Ì 5¶Þ[[û‚É™òíá™`«™|¹`úð>ù99ëhC>YØ®÷ã‚û0,mÛÀnI÷?HQ¯r6œW*+.ц)ÇÀXo‚—ö»©ÐÐrÿrh2µZŽè¢KöÓ§Ž›ê/W6B©«Ÿ&G«xãLc÷½7›œz¼ˆ-ßÛ('µaùF•Ýú|Nmþ¢>=*OQ~Àº¡b×­‚$Žõw=|¸Š+[z?VGíãþrxv693Vß°°¼~k¹¿?63»pA·RÆa=[,³Û¶ <Ü4Š÷n"Ê$û®È¨Q3ü%+•I¶Í_ÍÆS©ª"åÉ”J«z"‹‹Ê'ã8s=ŸŠE´Gîô·VúÕçS“êÙ‰gça*@kËÆÃÑÐÐÄF4ÕÖ×Ú—,ÏE“³áòÆ“@×í+¡d6Ž©ÈFd¦í½Âjf˜þž o /..—“Áà,cçîNûÄ­yfc2lV0 zh¦ÿm¾@oQÆá¨ÉŒèž(´¯Iq§‚¡?÷ØU˜ÀNT‡ô‘{ÑTv~>¬T:ÿæÓ1"¬r«XFõÚ´)ê~ŽÎ'æàáp*®ðʆCË‹]‹‘X8«Tv5 +¨åhlñv䲂"Y^Ô%և堶«™‘‡‘Û‹Ë÷“³É;×uõ5 Á*/¶Gž Ï-<Úõ\®3;q¹Õ@cKâi¡Hõ"‡èDFk Š)«ªšbuUe‹¯=Œ\Qp¨—K©@¾¸x{XùÈr4>/°jKõëÂh{ì&ü¤2·'ss*³¿•J¥¦¢¡XLÁ–ͦÊm(w£qßÎTL…ø™èõáh2êŠDúg‚Áð².^_Ž·úF§gú‡##¡° ïÁ²úz¤g#\˜+#îOŽvŸÊN³_ qd?\œü\EôTc¹Ù%dS¤ë*lÕzV²«O)jÏ,OÂÝEc52roCò¼ƒXí”#e¼¡Âª°¢¼~"ZŽ-÷?ž‹<éWùF?ÙާBê6Ú˜(GC‘h²­W™ÐíȽr¶µ-<¢ «k¦w´7^žˆL̨ä~Ô·0£±ê*Ïöú|Á˜Â*¼vAiXÛûN™ý†[!Éû­Ñ4Ú)®r¦ÀŠ<0ßÔõ+÷_» sU:p¥&VËË#‘9(­gudRÙD$º“5XÅ).©$cydx¤_9ðeÝS¯ÿ86¹]¼¦[ù©xyD}¶¿?+‡î«³ð}k\áÙÖÖ,ÔX¯Çf{ƒ3Ë•­Žêôj4¹¨ÿWà ¾‹‚¡Ë‘áû i±OÂg`§Õ)?<0S7œö B¥×°=šÈ’(%ôà£KWÍX©WRÿ¿o/NÅSS1}ª— ©wÒýø2`¥ÜtNbu“RñØpÿÈb@4¤~häq$Ú™Ôuù‡¡Tx9r;2·Øµ ©³!ܦ°Êj' ÷¾ï @Ýpfv&v{£<«ÐQ™(bµ<ûHeX„ÕnÃØi„HNy oß°…vÖ\3L b˜È΄]­Š©«&ÌŒ•zåzÛ#“©©þÇ‘ÇýýwçB“Qx•ËÊ®Ôc°"»ÂŸSO6557Òu%²¡“ýT¸¬"Ol2¬ç†ÂÑ®ÈÃë*Èß+«[€ÎÝßNßW`,ÞŸö‘aµ÷—c—#¡d¯ï¢À*x1½Û-°â1>9p p‡¶ÀÀi( |lR5æ•gæÊ`eÛ‚+R•dûÎǪ/ÕXõ«w|¬ÿUܾ<•J…àÿux^b¬TÞ®NÏl<®r…ùxy®ëväÊòT<« 0^îWøNj¬ÚV÷>ìz ECw7¢q…•6§ÈãrÐçë /êG"÷f¦•vVº9¤°JV—ï/œZ!e®ÃþÛ¶.³n˜ísoF…(1¼B;M‹ã´ÈUYó±V©D˹«^«©©þˆÊŸð´Wð -«Ô£¸«ì|v'S7ëx6›»¢üoR!¥²Ð¶plx£<5„XMÝtu=‰Äf¦BsÃSY]²éMõ_Q®Âj4#½™»ÁJ]m«XP—ÿ¦Ë «™+¼n=ÔÜlOpÀ›±¿ÝDêpVÀ?~åI*¦È·âì— MhË| UßDcQÄ*•*««öÆÄL|2¹5„)¿äòpd.–ÃÒ—Ï+‘{ `u±Ú%¬FOýÙý6_ ,Ô,ÀÉbÌ&/J8ŠÛ2XasÞ˳U¾3h Ö„|xQÖõ©Lvµ¬± D&´•ôµñl#aÎöÅc„Õyå-““±¹ Uo¯vÂXYµ=×5™²¾†cê;Ûô„_k|¹]c¥>n Â?-r-ôqÁÇXízíj]šUqßÉdrEº¿žI>§`…Õî%SRxÖ›P¹øx½/[~ñj't;2¬‚Ê@ÝK±Æ*$°JEu0{òD%VSå9å©\bè+Û VY}Pª0¦=32×_ë,`Ô%š^H¦"ïO›jŒo–±2vÅ"Ô¦f]‡K‡nÊN.ˆ2"Ú®¶äЕÝt—àœõÊB½§‹ÏÔàHº­rÇpèòÆÆår*kÎ9ƪìbéõ_‹\MMÍ©k¥`GÕ‰%¬pȽµuZcnƒú ÚUP¼ùoõù/½¸nå›í÷b%‚UÆ´÷e‘}@–øè*¨“+«®B²O¼ .çi­Uý%WÍÉ}¶|ÇwÿμÊÊQå4"õ°âYpG•r4üF¶+u-ºššŒLÆÛ4"ºp¥.Êwç¢S+BîKÅ"•m"V*^éØ~A¬}½ŒŒ¨{ÌyX…GÍ ãštÁ](iq†== î ²â“ÝVÒWAÉ&ØœáÅcW «6Ȳښ ' •§ô}8»»b¬â;CO"Wô»<5Ñ•„ªW]n&g4V×cY×îM–#w «¤ÊÀ†ËÓúàʵðN_p±šXùÅúi¦(šòÜ>¢ˆ¦ÕŒZPÞ® ïV6é ²"+Î|ü*V#)Z3Ò¦6¿[ìyråú„ÊÆ£êþÒvEßø°¬¢µº)«ü~(:¨S“Š¡}YuâEU¾þLo +êT´ÆËWžDguTÙҜʚVêÊ‹ÜÖ—ÎþÙQª³?ÒXÍV‚*IUWg™.TIgZ¨nò)øáˆ´ UÑþÍøø«×fàã¤â¹ Ú2²çÔ›)²6ØUÊ6ÛR1ˆ»úNx]WIûçb«2ÚUVà¤JÆ• †"CSÙ>¬·¥¢—‡ÃÙ¤ŠI€ÙUköþ=ÈÍu<_„;Žú(ºéÊQtG°”]Í)V/„GÚÕý{T&ìØ»ù£ìz8tIŠ·¾1³´äƒG ó¯IÅoÏ•Y5êµçI×ú`W±ºæbÕ—ZT0=YŠÅÔUo#ÐÕ5woJ`¥-/Užˆ”Ã*lÇÂmà}³3eå‘Ád?aÅý¯éð:u­ Š.ËÉ…Öéd( ”á_ VZaµ|CÿôlLÝF’Ä Í£U-y§=L¾ÀÝ›Ñ@%¾ WÔj³ZÅvs½-³Ï,cec^¬èÀšÜ™ŒÆúuL™SWÃÞlÔ`¥l(tåºÎEÕ­(¦NÎ^uÙ ]¹¥Âš+Ÿ X!]Uÿj’*”=)ǃ³3Ë]‘'Ë3áemX]÷pä¡;S¡¿?œ +PŸ V²!ZÔ(ô.u8mSǎߊ…ÝWF¨ÎÌ\9û7L„Z»j®pèã-,Âj~tAu‰ÌLÎëRByù^£{!Á×'œ6½I];ˆ«#N¹Rl*O…£±»·•§*¬[¬ SÎLDt==R¹zÿL2y8§þ]$ƒÚ'#·—g}ÐT]o(†î—cW"9åƒ`WrSÂÕ¡P nèŸb³ù€j1ãÎv31>»…«Õµ5&ø,åëÍRÄ L ­h$lìªmr«–:Sm‹O->Q©T/Ž„U<:¡îÃÙT(¢«,Ë¡r(¶|eC‰­}€ô•å8N½ëÆ 6¬H¬ë¿¹RN&ïÍÍAñŽr52,è v/$•w(OÜè_lWÞúÈòUPÕøãö¶s¹Xi&†·oi:MôÇ…>¹ ãww+¡sŽz»Ï4= VÀÚ«öeÌÇû²aå0—cáùì”Á*mÂY•yEFÔ7?韸¹Mª+tvF·§¯,Fg©¨ Kûêãþ‘'‘ÛºÜ~ nHWnÂhXA€õ(xÿ´)&fÊË—5Vt¸ow*u\ç~D‹ÍBI×]ë³™Ò…* iÖV®‚HK”/}+ð8β$uÖiÎõÅ©yH Ô©¨R©å;ñ8xL{,«³Ó¡H4Þ¦N¾ˆÊÃ`Jäö„δzÛ’1½fx»kh&Þ×ÊS ÁpHá7÷g{{ƒ·úû‡Ê3³Ó££A4¬™Ø"ìNÞ¿&9;=[¬:½ à&cosÿœ…rj¸I¡gHìÁ0a‹ Cés굌U[<ºø_0þWFé7%Rº*¥žx8¶¸q}ñŠºõ?Ñö¦ÂTyhã^8«€‰F¢Sá©rH§­êî§¢ßÌòÃ+˜oÜ ¶š‘ΣeBpA¹d0™Ôæß… ÷µ­>Yž]x¤7Tº-LÕWFMß¿‰Í>²ÃVºj¼¿o¸=œ"»­²¿# nG¬Õ¤ìNd—c,KÞœ ÍÇùcxæÖ52m½œ(áùÔ¯¨p8½w%2üP£x¬GaÕ5Šõ_WѪOgT]IУCê6Ôú¾µ;{sO†oÍ̲ú°/? mù |£z€öœ/*'Ô Ú®Przô˜V÷åŽÕ]ƒ_é´¢ËeyláØÐ¡˜¡GÔô«¸5>JØÏÀ¬ ÍIõ VÔy8Sç=„îTäîÈr¬¾½Üµ1ülc&œÁZ¦ŠH!un¶j¬&•«õÒþàûÑ^u;Òí›òýðlGøÑ¾‹rŠTᢢ¹ŽWFÊÉi_÷©iîJ»*ŠýoîŠq«74Ã;–$ÝÇ­$Ëyȼp.û û`V%•ןl^ñ>žR©f?ͪ=‡Ë#º½®ÀÉ–ÜçšÔÙºöA•ÙÓ}¯þq]^ΔïØtx<+ ’fƒåÎhÚNyH»âêÂÇmÛ¹iœeÇ`õößv¥Ë,*Y©‘FÙCSdÿ ÷¾Ï´L•õ`h(šÊö™Ã±M%V1eÑÉd6›,o<™ÉBjùñÜ•ë}=lE¬”«½—ͬ¹cCº8ª¢~ÿHÿrè¾²«41 ¨ÿºvEfÑÊbeßéÎŒÜnA”ŽEnÅfe°2ŸÍú‚ÙÙÙdJEœ^ÍdÐRQH}RÙGït<<ÖÓyÊÅ’3Ñh4œ¨ZuÎ0ïmBõuÁɢ䙲ò©XžÄP?Úm†ÒüÕSÆ*ƒ«$û†W€‚T¶j¨>ðåF†+¡¼çÒ ¸Cç=Îñ½e¾Jô,þu~Q±ó½†hºmºõý˜m fUŒîTƒ+/!“kJ«nézùÂ#Ét,{ÔsÙ€Uy¶;c†b°s(¦blC‚=P³Háäq#o[që¡+v[ÖÏçJõ™™¾°Áo´ôî“þäs™Lpùý¨q6cW ,_SBk²¿ FnÛ`XˆU°›÷“ LEvw0’ñb›.7GnªH97e/êçS‚ûÞ¿oÊ’G ‘ÏrO@î)NÅ‚oQ°ÒÓÔ Þfæ³=ƒÇÈãìÈ«çÓ3«tgÑ4nh€Ès»1Y¨Yè:°ªÀ²ÈÞ°þf¯Í¸XY¨ή»9çabœtî).0Óø:€Õ–X1¹—Ä(mÿL»È™í´Ò¦©ÐõÓÀª»h§Ò=H9ÓVTã{%ò#v»çt$jn™Ý¬Ì†”×ç¡â¸€>FƒÂ’SXLOÓO-´Ä þ% ZzW.’4lKXš¦ÓêénUðÄèë2auêŒ9|-7n8s´ï1-g¡¶'ˆ[$kCÊ«¦×Ì)ùXyM‡Gô/\ððš¥wJ¨'LH%@žª±š‚ê°%fJÓt:-Ý¢ƒYšCC{%iKDËŒ…zÌê«â¾È×½å=ßBŠ«-·ÑœiŽƒï낺Êçø­U ö2KA%6´vážçt ¶ã«Ñép(r?ÞÊVÅì0ÍwD`kÙÀ•N;4Mðõô#õ¨ÌA¥T«}VÌÅçá!‚¢Õæ&¶#„ îk1›†ihMt›WíÐc©ð™X%í ‘bw€—qfÌÓ»´0”ËÁ’(š¹!`5ÛzÁÇ$VLzâ_çÆ#T‰Å#mW¼](lÉé{ó¬ž=>]G¬îVҨܰn+|òrc˜›*HÄà*p‹ñÐR©ðYÌû\¨O)ìÚ8³k™q2š\Bó%œ‚e!ZºMz_û X•þvàì|ð,A{kž]@圌ծkV~]Ñ£Ü*ôN?`5ý=¾ÁŠ“P1je=Ƽ̴œYQûãºä÷(¬– ¿®OnC•¦4 Œ%~V/“{î7Kh|Нû‘ì4—Ø/fдÒVÙVäFd¡âûâAñŠ3?ùÉd/Ipµk9åÀª¦õ ‰zîÍLwûV·«}îEpÑØÜ™uÂN.¨ÙuO^Fvui&ùNÎBk’ WÚѯcE›OõØ€ÞÛî LhÛaÀÆÀ¦r?·?èÙßîIlk°Öý@ŽÁBE«úçÓžê\Oç³Ä }rÝÙ~гý2ñr{»'w'—›Ètæ| {|Õ«î…d,r;°øðv¤+¼à»š™ö+¨öiçF°¬¶ØiGö@תþ1¬ŠÏV*Å~©Þ/ðr` §u´‰}Ìáp`Λ\踼)‡ïÃŰ‹•×=—$}eÖ¹Æ_Ù4ô* å…5±©Ô0›Ö+ΉtHþIT{96¦þú©žcc9èä—ž&žvcÅÎ\• ë‚JPXaºPõëŸ)þë£æ±ÚîÖX¥^$”9 (óZÚ!¼«UÕ«Ô£°ž 'ÃPKŒ©à®cûÌ‚_…*3éÈ+‚-T4þÀ¬à€[Äj›§<ʾ'º\+‚Jû û¯+Ž0‘5¾¥&™¸SÜx Ì«“±ÊVÊ}”¡$ÔLSLd´]éjÊ_pfHÇv4+xOçÏ=Ê6¡&8\z¦Þ0Ëi°´ÿ&§0”ŽVutöÎ\28«ç&ÉÑõõé™»„q€9”i7ÿÂ;â_8ðÌÑB÷´‚ÕÐZì1‚¾Dš…jÚ"N{&ÔQ?‘Ѱü«Ø“ÉdîËAµ;PÜ©^·}ûåËbÏ3Uú¢oA…ö‘H,ÜûÃú æÒцøW÷3ð‹mX-‰—ÂÊßdã[Çöd$9½ ߟ™MgÖõJÓÌÂ:ÕÒ’Ê»¥Ë£V[¯L[‰3ÐeBTÚ TòEvEüžéÝÑŸN:swžg2cw:{¬¯'ÖúA}* éª:ô(GLÜÉi¦¸@1ç×`]h &Ëý‹‘~=GŒŽ ç¦Iª >®,¢=§Þ3X ‹Â ƒ ùëÝ ³·“Ó£FFv«ðBf æaD7žé>0Ï1Ž;Q}ïØ!¯x¹V‰Ó7Õ _UÞg–ØÓtáy”u¢‘ð„P Y·óúu+ßBrîzWWdäÖ­ÙΙG»y/úSÆÐùY§e¨ÀbþOûOM'‡gýc}}]åþéû`W®Ø†»H V ŠU:_?Yqzòvû'òõ_X\°ļŸ QÅ¿}’йÂêÂÂSìþDîj¬€QÕïpœÀOÀ:Xù= µÞ©î8ʰfÒ~ý?³ý`yNa•Yp˜þ[\‚GÌ×ŨÕ+9ô¯£UÅ+Ôíê”h:°ú—Ä+iX–“¹1BµJª=pÅËÁ=çâèôlxF7Ô§•ªíX•ç«Í L¢T*¶+¬2þN¾IST_'xýʰ"aeY ¬ýýÓÙrDce¹.LºÚÐ.‡ud03|{'Ôk®IšGcV:\å _¢Hæ“]º›2-Ωþx÷T=ºujÆñÑG«ÝîG£ÓÓ°â=ê#G³[üýäˆêÙ>TXuÂC–ߘ¤'ë§£ÁŸ"3Éà¨öÃGÉeÕ¾›®›ÝˆM¦Ø™ØcÜ´™qâÑëˆZLOÁ/T’ôQO“Ý0½ë°àn~op w)Ót´rŽk–í¸P8Cá/V{õu71(N#.vSÜ÷Jpž×îé_%b: Í.M†›Lµ"p$B9¢÷w(bXa“ú[´p#èOxÎcÏ”÷ T5¬ìåF«#Ô¿X×÷ÙPΙ?‰V›ê˜K4Î%48!´’5y1åüèy&ªw‹b†(ëÍàÞ€«6ߨ¸ãþGž¸n†Èÿj+Í ÇH úe'àç°ºø¹Ï @LÇ=ía÷’¶wê‡Ú˜ý{Ñ’xè²Ä!pžH³±øÁ’ ¼ÕÓ{<íoô6DyaeÅa_1ƒÜÌ—~/VçÚ™„Ä$©î§HFÃSL÷Ë­6ç1ÃfhÏm™Rs RИX¡¾Ûrn6‚Vç5g ÇMfµ†¼izŸë«ì*ÝÝN ^<ͱÛd¨ÃÓ­r“æÿH¢Yº}Ûô“‰äöy# †aÄòˆ^ìCïÌêݘý@ÙŒP™Uù5ÁöUZç>Š8igáóXíŠñ¯•±0 ÚÔ©{-\o´)³·et·yÍðeszƒRP•XMr¬j/Ìɪ³O‰‚±¿2êÑ +÷Îg‘kD©»‰ ¦ÅàЮ”„8m ºÞªŒÓ²·@fÊzÎ¥¦a/é¯Ûl‰âÞñkg†]çë{RLIòzÐø•úç>#¡Còé–vÆËÒæW¬ÒN ZÝu±ÂÈî°ƒ#“âøíÆTUnÞ8³{oÝh5.*V¸q㙡uØ*VÏôü^ák;`åD®¥w¡©¥]©(ùcng·ê6H­:ĺ7¨[«úH1ÝP-£#% 6µF3äë[P[0´Ù6]Ø×À•FÂ&ÞP«ªë¢ú×ù šƒ ÙŸy<Àò”Ù®<õvJ©|EF´˜œ×Në%·–—¼PñöˆzÌņ¨Mz̹ í17ŒfS¬:Cz«B>ÿÕ>¸Ë¹kõxÐÙµ7qÌ¥M 0Ý„VÜö±D‰TƒJ>÷‹"Sß6›#¢ÓÂ[o¸ÿò*KQ!›H3Na½&æWluÁ çK¿ +O5”óIÎ8w-h¢dêX“3Äá¡ÊƸî—)oA÷·I ÏU‹´ªR5B·§®~ÉD_eæuë{F×Ô¶Y«$ÕbwâåmùÝtSÎÇòIb7Ф ƒ²JX“.³OÉ3|õ¯Ç S!ݪ©Ò¶ûÙç”ï´zÚÌšªNGT¨¨Dõ<‡ÎMùF‹]t³µõ-*®›HuüJŒ¹#잢•Ô—¯ƒ\lé·`ÅT!ߥ±ŒÓª­S°+ô|v«Í ʉçÂûPL*#,ŠöÛˆgÁ™™•c{›¸”dlÊN-ØšÍKUï>3ÚU ©=J_®¬Ü–l1éìV©CØ<4™¡„ªô=(æù=aÊäžÛ<‚ ‹H|üyû¥B‰ÄÄ*VÈ2(–Œ9Yh0+›[1«G=Ÿ/ÕC¼òW¿ä9ýÜý6Ýt›¨ëæ ˜øßG¥’¼½ìŠ£›jÕ[ˆê¦` ¢@´nƒZ7öØÀE»ú?ŒUuÀ¿+? ?UÛ㧉<$½ôà\•3E19cj/bÅ»ÅÎ6ÊûߦH£Þ–&*<°«¹Æÿ÷öÜêzM µ¶&›…¦¤i_†'ÖÕ/ÌïÅÉ/Íi£`PÒ¤Šœ{e9 Lìh£35û†gŒß1íC¦Ca]fë{åE[ÞÓ8~ƒVvªŽ>æQƒª3)ãw'ú71göAQÔËdŒâZ© úé…ê†e€¹õM»¼Åª-–!æ˜ö"ôüúkîÚ¬¬PÊ^óÞ—ñ „ÁÒoÆÊìøUšš+3_0ÆT•0éx¾.Ž=¨Àت'ˆ³˜ñk» o㔜1o|> Û•Œ&9vW‡[§ÎõuOGŒì+çè&,á¾ä!Ÿ~öt  65K(I—¼2Ä_4å(© ÷*«_VÖVœêÞ*.3×ó_ѹñ`¥Û¾þ¦OÕ†"ó›'w2ƒ Å)ÉAhX˜0Nî8oIÁ1«æZë¦GÒÇ>Ä ñÖŸ7–M´¡¥B)ÿ›Æ`up9ëXnÀö{ƒ’5'(¢›.Ÿ SFÖÌu—C”G²´Ub›ë/N´;ßEá‘—øËÙ¡ÜkœõÇÉqêBLþ·–Ï1ˆuhó<R(hÓ}ep²ý=T¤EFµOGß>ʸV$æ¶äq>³/Òr”[¤´õÊÛó¬4)îqÛ”šÌ¥Rá÷ø_#V<LŽ…÷”u˜z]G`Ö±pÞ€ŒnÈV_Ñâ´Ï¼øÙ³»v¬ƒe"h é×…€®f€öTa° ³Ò¤ºny0KçóŸ|Vn_Å}¬ý¬Ÿ÷-èt¤;܉Jò6LAs†j ¨aÓ§nˆ ·µ [úŽä´ É«Æmo—!¦q1ÉÎácÿ Xe<ÝÍ/~2f&¹ØéØSQ*’a+kéðPÆ)Ï•ðdýS,CɱuÉ} éz…”[šEuËÆ¬V¿ .$fÌ‹ÆÌ:Í7Z˜`/SÌkº0nUœB‰ÚL‰x@ŽTÉ­eÊNÀ£WNkkÜC`‰e§2f¥Béw–FŸ\poc(6ñq&%‡+^ƉN„4±¶÷óéÕ[™¤· HúÔ¢OÃbÌHè¿õï#1Þ(9 õeÙYbF¤jMÒ8Týn¬p ¢ˆ½M¬)A†@É#ø[5H¡®ÁGs9>ÄA*÷à3 H-£²Wš-$=Ó Õøžq$A.© Ëå*˜‡C¡¸œô»±B‡Ú ÎdtÚú@ÆüÊd#>º*EŒ˜ã‚ä’Ëõ¾b®‹¢LY™HY ¯Ëbq„÷lé²Ìë[5—¯×(y"_a©ô-°‚W—[Y1Cõ¹ÆÀ-¾ߦ›Û69€+Ÿ™Î£Õ[§ñ×"“ÏM+€÷Žï4RýÀcÆŠŠ n²àäUg¤³QøÝÈX‘óH°ö‹ç?ûžoßööGê4,QÎyˆäêKK6™p[¤‚‘ð9ü+©Ž„X˱¼ÕÐ ðÄðÏÖj®nÄê*«!V ß"] ÄÝGqŠQU@â…xXåE|Üd ºÔ¶IΗ<}ä-§7fVæÌ¨#}™‚G^ ›Ä'ו íX[(Õ¿ X>õrÌND&†²É±·êV±‚Cüf}ïPLÅÚ§Åmºµ*SFEWe±âvÌTŽ¢ ¿g:¦5oÂ"uV` ¥|þaÅ)ã>ÞFôA¦QúH mÓ‡d:ÅT8‘Z2‡KN¯Å)$ç£!=SzÁ!l¼(C@ShÇ‚@€'+L]óT×WÒ”Þá*шǷ±«Côó€C}܆jÓG¼£èÔ'ŠuTb¬„)Úê9£$KS\ô´­,sGþ°iôÜx»ôè¨a Ôr蘆é^³ ÎÓëk,Œ§ þ ¥oUÞ§GžŒ]Xœr CÇÛÑ¡<ñ0ŽR|¢R"Ôk4)¾ùɂϟéäóH:RZÓkËùµ²â†‘›UÛÞú6H)¬à=µ×â¢ápÛóõ !R?\Zb¯³uNI@/Ê.&÷¤>˜»Óã´¬r¾–u;ÿ3ÂR¦_Sià¾\¥=ê/ŸÑ-0_úFP)¬p–G[°´D8n³ƒJ¼ð›á:|ÈNg’MQ(IÞg>8]ð¿#¸üHÿãJ•£¤LAR°¯9æ‚Yw«ë ®Bþ[a5€yõ!Ï?-ÁÊÂ!Þw!ÁѶM_>D;Œð'Ý:‹g&È.²q!Úî˜ m“÷4XÕçªL»ƒ{²_ZqÒ¼õ*¼ÚüžjUs¬hÁݼ9¡pÈhZ7Ã)áÃ¥C1­!@²}và Ð"¢Âd§©ÀûlLwr*"„i˜Y÷ÒŸ£$),¨da•hOJß*XV-2 ’.pl8ê3‡T(šlàš°SrAÇ»áô’‘c–¶d=Ý–?9ÿ´ÝXlV ßv­^ú†vÕÂÆàB6 CPÓ?¤Ï‰Ü€“ÏM†ÚX`Svžÿ-4莖<ÿÆÍ#kU<cy/W4)‰# ÒõÂ7DJcÅ`µ8Îô«O‹©Ù¹cûN£°!¢+¤8 +“v=Z@::à >þJœPH·ãý¬œÛ˜WáJ’œqÔ õü·ÆŠ œ`ÍAkiq`¢ŸòrŽP¢ŠnÏD)í}›зþ-Ur…š;Í ¹+WL¢&Ø‚iѦ)V÷¾edg¬œÇ8e £ÂɪE¸œ¼äñŽƒ½îÙ2»ž(ëÂçM4:‘Ê ÀØü‰hm‰bÕšÃâ¨àª€ŸâÛBXÝhiöå 4û|KC–)²e)[¶¬M;˯“têÀ›Q5–Õùü«È»²NAk’‰¥ü÷x|¶ðÖÒ ¶¦ø´Gk1þ&ˆœoxjèÆû¨BÅż££WN:…™Âñ¸ÃÛa¡ò ,¬ÉñF.ƒba¯^Ê׿VW â kiD¨å†H'³_„ ‘oœüÀ…U<š9{{t„Ú€bLèX{²ªÊž q¬I¬VY-œ€…–Jß+s`I|Ž›ÙüR$™¦¿×B>ÛhÀ ïÛ|G‰§B ²„Wî-ùØF*oõE\þ–®55ÉåxV³úfeÐó°âÇæŽŽ—&ã ™ 9ÙÕQh4ðÕøÍðÛúŒËÃïX®vãåoФ 'ä~5‘R‰º‚ݲÁ2hþû ¥°z#ߨ˜Ä,›˜ü>Y^‘ΔAÉr‹ÎàÒ÷n‹9½$±ž½Ð¼†=Ó|0*¤ï¹ëð"P‰VàMÎ~'Ãò9à+¿ï.`ºáGä—²»pƧ76‘z‡Í™-³yp (M$_Žë}´°uÂóB2§úÅÅÆ -êm·ïeX>á9›û¼Á$é†E“¢æ7dxÒåƒ'žt± `Q:LySO9zöÚ®‹è$aÄ:+6Nyi×PaãºÊ¨ ùïöø6Å«Ò×Þs,&*ÙøíÀ~29P8á¿Í¦SσÔ1MÉÒá·Ç&Å{¸ÎΖÈ@WåN<²ŠëQ´ï¯6©Lbÿhï¨ùJ„61ç5Hãwv|Šf]ÌÂßÇ Žá8.|yž‰J 5‡FÕ®Ä:Uª׿›ÿ!V›a«M4Ï?61G„Û‘ó½Ãj Ðý=¬SC墅qÊ™}Ù³c §ýPk­²H•0NÕë¥ïbeÞã2dDd5ÐØ>lÚÑŒMÞ»Bt˜¨mŒ£‹4”>Íwä€D÷>çê7höšéh4®* ©2ç¿3Voñ:»i@ƒìˆ{Qt™Ó âï¦ç&8JËáúÖDÕNmP[pã;pl Ú)j½ò-ùäd‹/r^vÅVÖW-…W ßר+·k#ÍyÏ/D˜Ð?`óíÖ[3 dB¹f:ðT<¹•¬ ëµH§™¹˜X.¥59Ü «<1T …Óz xê¿·]9lbº¨Û|ûŽ=jS‚÷ÖþùîS âb-’vi.K!{t`´àÁœ”Üù<Ô‰·±²²çæ ÔÝZ•¦¤À[M¾žÿîV¥±‚4‘® 0ÓƒírêÔšè3„ ÄíwøCï ­ÇÔÍ[ƤŒRâóÙÔ1O¨#cª!a:©pEáÜ@%v‘˜Æ±ô]®ÊX©Wƒ·çžP{GŸzÞ·ÔæD¿°ºEÆtÄ®§¬ KÞb'%©â^Ë¡Š‰è² P³±jÍ“¬Ó h!ÿÝݱ:‚W|û–¯kÔƒBøàO€çlr2Ê.Í7ÒÐwƒòb%ú}\Gw›Yp¥Y©4”FL+ t¶ê„Ui¬ÀÐ"ÀÍå@ƒ'ƒßJ| Æù»#XÂz×—ƒ†Ò97V<ÙûNU¨²Wq…kÍvá‘™·„Òuàeªÿ1vEqsr±‘ˆ‡¢( ½µîÆ>§¡Ñœ%G WbÏT,ys/Y£:9Ù3ÄBÇ÷Ü@Å©Âô p`¡þ‡ÄuÀꪭ©Çyô}Í`aC…**[ÔÕ;:B&b²¤ƒ/HÔÁ2Å©q›Ké¡Ož»>9Á1uAÇ[[ñl,[¨V¹±\ÿÝšÏùà+ 9@ ²0XÁ¦²`ù$ÉŠaP‚Ýõ£&?hbNlPÇœs†œAqõãzBÅÎ(Ôj^΀U;,d5«¡[óY•Âʦ?ðÚ Þwð ¼Êdô: ÌùlAT‚©ŸWF0¤Y·•N'H1KªÓs  Ï>Ú€oê}BvT)Wø#Ÿû†ôþPàS"<ŽŽÌZÌÁ9èH ŽÇ +θ“"¸½3Få½Î8iªáç¢^ú¥õ?+ÂöW†ç<ãæ>l²NiOžš‹¤*†¤jÅ¥5Ñ¿ÿ²&wp;$VV±ª^ÿc¡X¿úúgÜû ã<¶™…-dL%Ö´ ÒÓPG¾ÏÿÉXñ;sı‘‡b5M¼~ÝÐ!¶.‡9ùë=aP¼¼v쨆®Ò¤XiÍ[ûÔFu†P•8MøÓ,Ë·÷ºéCÖÃð±£ÙÏò0§a«‹ '{2; zC AxžúOâÔš’åý#˜¿Ö'_!ŸÿS}p_toоýk'N¿þÌ<]‡]å¤bæUr°×¼„Þd@O>mR¤Ho¤ô§úà9Πµ÷Zw£…lº©PŽß¿÷z¯ÉSát“)ízÿ·1ï\[³£T«ÎŒ:‘¦2ýOɨ¼X홓ò!üÛàž™–F.r-ˆñÜ“Uƒ;®ÏSûT•ªXzâš‹ÖZã$•í'(²PÔK®II¬Üg|мK[Apí 63£=’»e†3HÊ ž OçÜ% /íˆ ŒN? ù¿Â㓱Øóp.Ùàc'Í2q.o 6Ø++btßõ=YÈk¨&@ñ2ÏÂÕûû2¬*tRØ6ç·J`Ñ ùÜJEÔY*+.Ñ„;Ce©Å%¹°jfôêZè@wiê ¬(KDÀÐ…¸hâ ™iÞ+3¹3dLµZ­9LkÍ>ŠQȰ®-ªTÏÿEŸŽ)Œ»*•ŠÂÞÝÉI…ït''&~ŸðR%žÖ¯˜”ܹîýb‚ÔŠìÎXllÐ /Ì~æKù¿ V•;lX©0 ÆÔ*t•c›¢’ _ë Çä„\ÃôéÄ«6>ùÖh$h­†k!žš‹¡K=+•¾ÓwÁŠuÓø¥†Áž<úñË Æu¯‚¹BÕ•ÆÜ©æÙ±…ÂÔšÛuï}¼ù‡¹g)ÿCËg(•ÓNÂ=<ö…ÙcnE–€¤ÜQc]ʘ”°ª`EÙ'œ}¥|ý¯fWxL|VD§ž=JäÞ3#Tšq5Ǣ슃ݟñ´À Î FÝBzþ¯çƒ W~Y7Î%—ad+¡V“ÖTsæ……ò´Ã‰³fÆÒ¥ï‘xp¡žÿëd±jb^c!C©9u9Ê5·fG%NJ¢%€u=š b²p(O¡|pý¯ŒUÍ‹‘½‘pýÄ R­`î=o…þƒÖ¢dÖ 6…÷cHÏ ©|ê<»²6QýßšÛ`i´¶¦h­­5¹ÂÈ‹1Åê·>­­¥ÉÂë…ü_øñyß¼ f¶0îÉ ¨§¬Ë‘òšµ' •³ï—cÍ=X¨—J ¬Ö>c<µ•óým~ÔqÏp‹å4Éô§°ÞRúkãX­qeò—_¼€­û}Y±›iÖš!·–+ Ï%\šïLS4bgϾz>ÿwÀ Þ°FaÆVuéÃ_ÖÜ㟹5[Ólr¶ãú^¿ÓÍ«3汄| ¦=Kù¿Vò-"Ü[Y1W]Ž×lP¢¯Û­zž‚áy1ea®¡×óáœÊÅj­Ék˯ÔÖ„¥ ð<‘É7ÝšTÁ¶cÎ TÚñ~?KøŒÕêÚg¯sy Èt‚ycmÕkWÐ^GÙ?î¥ÄRþoóøè¶¿&B²7/jö±Ì8,É#ï vµHçç%¼ƒ5‘Ë•þV@]ñ)µ¶ê-»Ø¬z$ Z“§œ¡ŒóáÜb×Üuõ·Èšaå¼*öìTb¬ÕfköSòç$Dz^ã¬P0²4|9.`:õgý~¬äëšñh¦×„õXxÖº³ŽéëßJ…}Œ4Å¡SÊÿí`jÀJàµjCÛfYk ãýNErüÄÙªa™Çµ™ü7§…ûc±â[,»NÓÇ‹Œõ´‚ü¯ž?Ð6t†Íb¢„[1|¥¿H÷ê·ÚUWm,¶Å¥‚ƒb?[àOΰ¨yF4dP”¸ÁNmãúß(•jŽÕmìk¡©è‚ Hw]†±@ßTb¬JÐN7î´ç„³Íz©”ÿx|”O³•ˆE£@rö¸3î¡‘™|è{RG7Ôt_=|±Ä õzþ?åñ1cM‰œ©—ÛRéŒË¼%\"X "Á÷¯–øvgò IPX•@>²d¾ÿ ¬J(fZ(ÓwâÈÃÓ*øÅUþºÐQ\*@½\íò…ÒH+pñ¼uT·í•’!8¥žp‰ŠOõ|ñ*ÑÅ¥þäu¬”(ê×QoÕ|K´Ÿ¨cß ®Áƒ ;Ë@óƒïåuG]^)þægÝçíJ&ó\`Óˆq5$uÜü¤©r˜C„–a”çÖq”ÅäÿñO{ ~Sè‰CåˆÉP/ìû+%²¢| ¿‹ZTx»ûß•5 ~ãw3)@C(ªÓ€w†©¢ò¿%‰•çÀ*q®Dý\·¬I¥ÿ´Cî˱jx uk_ù¿Iá{=ÿ_îÞį©l‰ Ê,Pd C“øC@¢­¨ˆö¸¨< „0c˜ˆÐ÷~ïó_»†½wí}NPûv÷í¾§•1$tŸÕUµ«V­©®¾yófõMz[ôzpóÁz‹=¸â¢ÇèÇ޼ɟÁŸ° _.x‡ŸªwÕô¯Ÿ~R¾ªK½¹ã^Ïî<ƒË|ÀW¹ºðMyù-øzÕߪw®ÒRõ'x}Vôù ^×"×øªWmE­¼’êÊ«‹Þî윻®õúèÕgÜҌۇq‘3nŽÛžVÉ_·.rl#¾å¸X±@·^‹ñt§÷Ø({3Lüè00ôU'•E^ì$2øß+rÓÜ›߸/Œ*†ÌMùéMýþÚp²°‚×× ÒŸ‹Ká©@uçëO°O«g¨WŒ*‚V¤à‹*DV(®>w}¶W°4²\`•dP©ëÜ”µ«—&ÙÖ)t_ZónK\ ïiùµn V(=]ðT~NOÝ}¡>vÆôaÁ58 Èe8jQÄÃÕNÒŒ3è_…,ó†Þ1¸èËô¡ùƒ›ßsUëÈtS„+¨Ô?êÄ©Ÿ¾Þqƒ•Qw$´\D©hu«H° \¥á×çÏ¥Ÿ?_‰+¯Š * °"di`íìÀ_‰+¶ªÏD…U¶50¼d/c40²Ö(ÂS§ÄQ×°Zg­`M:ZÐÆ_¼Òºà¬7âÖÇÙ™ÞH·,ÅCIgÕCO–Iâ>YÙÈèLÄn~GàòcØ2ß‹)ŽQd"Z©?w N¹)¤sà':¸*/ª`,,Sá‰0˜k¸ ÊLùÀŠJí”ã'N¨Ú&ñ)ÇSÎÈ Åe-ιÎ"¬ƒ[(%îï…ÛV ÉfÁCŸùëJ±hí¨8õ•½«˜’nþ°~üª6 PFJzYƒ«ŸRTVa°¸¢zÊM~˜ÿÊýhu«xmuë úüÙÁT¤øeQUX¦º‚7IX2`9ãÖ¤V»ÐjKcí>+äôe4J¹ \¬ó†â\ŽSZŸÑE³z wÌãü¡¿—'­PVí¸ü„Ž.«¢nç»z“+›"9ýAв ®6_‘±Š«u¬©~ºS¤`/Ç?E`¸*V­ª«+#Õ•¨2iðZ‘êJG+¯vDÅ¿T[eW䢭‹ö¦Á}¶Â^½Ò£Á©®.¤«ã®Ã[ØrÅÍOM}µl4KmÙ¾)Œˆö9Ä]Û²›m3•.l8|èwÕæ†»qæ?E” ‰æUÄK¦ Tý„°úêÆ*™õÊŸ¹8ò@U¤º *-šÿ ¨êRp*’øÂ¢U1T\Ó`4*ƒ™š¨ÈhËÎÎǺj?–þ…Æ…§Û7굇AÖ&sGwòtÁQä$= ³l|fÕ!Ü5Ù%ß¿ž&8ÕâAÍì,Ï"Õö(fW\|óƒI쇠T-ª'{à³ÏåVUP«ÿôÏ­~ T(®Dö+ZYÉþBiѪꊮ‚®Õ±^ȪønXíx„«Œ“SŽO;›#okQY´k£kb$¾YUØ¢jK:1,XS{íD,°æ…üá¡+6²èöp®lŸ¤ 1+qU­ƒÕ¶ú1•ôMÝ^²Àª.4XnZxR‰O'Gs20}*N¿?áùï'ŠUü¾~-‚)nRùG¿bÇ?›MaUZze¡^ìÜǨ®}3\%uq•ÔµÕ¹úsnR I‚ T¶ºJ¥Rú$¸ŸÛ6Uû±öÍÖ½ÖaÆ[@y…RßëV8—ôóÃÄ–ÅiÐzaºËjÝG¿í QË1^YX)\ýä«ÚBÃ=š™"È-“ ¦«qÓ˜R˜êÿ488<<8ø©Àe›¡ÕN¤¢ U_%¨î8½„°³Þ· õÍŽ‚i*D$ª4ll÷Ó½*ôß«:WܼJ†œ5¬t´‚š=‡Ý+]]©dH‡A™¥•¡4-ºX£¢ôÑ´·1Ôì[W§Žœ"ëá?¾Ë€‘g±ú‰‚ôúeñ ùbfW‰zbâ•,]ñܬ®®vŽmÕ"|™`dæ7E»\d¿j «OÃeí-33-ímß,~uÁP¤ ù†‹«™¶Áþ|êÿ¤/hhݹ£ uSRPéÐCØ0p'²kº.BÙ«WïüN¸O³Ëç‰.›¢ô§ìôjº*NÄ{p>¸â{ ƒ;€ ^];:rqrT¾|€re‹v›k$—oÛÒŽ9âŸgèlÊv¤ópqu`ÎGG ,mZ°,+,c­å˜Ñ¦=¤ÑÎèÖW†ö²fgi„S W:panRY‘‘e'vº…ùó | ýdzÌIîïô —©ãàÏ«ºé—“3íemmeêjWWYYÛ°ÂYõW†Õ3YS Pa´!X|œŽ'âê®ýpe:J¶>07hz?‡~€”œÓÁN$zvDÐaH©ûÜ“~7xÿÅÜY…+•‹¶/÷÷uEÑKýEÃÃ)½Xyûzn¤ÞÕ•W5¢f·;!\a´:9°Ù+Kçë6«ö¶×^£ ŽY-Z®œÚ£ i„³±é2ä½ÞÕ’#YKhX[<^96½úJ®†ˆhÀ™˜œ2[Â7UlR‘hpx˜€£ÓÒÒ2Ó4yãîÏÿ‡p5w÷åŽ&uu4u¨ëiCkãx €eZUª(ÿé8·©+­îÑýD|âÍ;ª“nezLǧti€ì`Há ÞM't­ó*=ð¢&õ!mHåq¨k≄z uÎv,1÷"wÉÁ‹8-:5j€ªŠ?™·‘ËÞP„Ó5{TŸST^¥V¹íýKf]MMm‹N³«L4¸o[Ó¸ZØrÈǧ§Ž³(ÊÌßæ© O7ƒ Ö®—‚õLœ1 fƒJSMë½â›h+Œ¯Ÿ¸«†ÜøÕ´)~ª¾ÙÑ©©còÆ/ùº{÷îÏ?ÿÆUc¢±qœR"]+ãŸúoVëA†U騫W÷u¨ª}3u{þ1˜HC¨xCÇ2ѯ|—6á)¦`÷î ”Ãs¼ŠúyuG?¨ã‚ãCúUMêÅ\:·›KÌÑA,öQÝMu „³\êÃn+€ÅÒ±tÕûýr‰´‚ÄýØ+³0ë›cÞ[“ät¥Köým$3‹j« IÔŸà¨,¦ÉHd`\ÁA° <O¥%Y>]ðÍMÃ>> è/:õaê‹&ô™@‰+<„ñ ?Uºò¢âËì0ÐÇ_©õDÔNh)´µtÜk|¬®•ºðëñxkkCƒŠX33*˜©œƒȃ.¬ÔKĬ>Æ¥µÉ|:ÿ³WETî‰Ö¨oa¼¡¢&){• U×BˆŠ½ƒ¤~ìC¼*KÏÝF{z^Äæâ=5÷ãÓWúŠ)hÅUQ÷öý (\M1®èœ?õ^¡«vºvj{ûÅ\L! ‘x?}?w?ƒ„(êø¼Ý¿\Ÿ &Ÿ X±t½^Cå[Ž8W9M»‚@)’ ÷ºù@X"z kb.H5{aakÁ鈢ûšÇ5*ô{ÚŸ`¾ˆe¦ÐêÒTÜbÐÑjÕÁ•9‰Ý¹:já‰ñw¨•yç•ù<…+­šn<®+~=þù妕"ÛÔ5<<ø ÕÕÜ]ÀŠÝTVˆ+8÷½S·g'V7"6F 裿:ÿOOÿC…°Ä6Žt3òã?¨mëû‹Oß§,7}¿¦g.Î0ˆç®TŒ‹Å^ñûpƒßÇ^1Ce™t6^}T¯6§>›V_Hl†02x¿­¾ü¡~ŸŒ8#âÐ&ÿo/ FeiåtÙkp±‹ùì@º2U;ôD5¤lïÊÖV€+œßЮÄfAæ1,ˆÃ [Ø¡Í/÷®n[ ’S§å9÷9òpºwe%t³¤[âë)ELÓèŽÖ7ðe“ãÙ£€wŒ+Ho«ÒwM¬»{£©lÀôà¶#¾v•™êÒ p¥ràG(£Wét’Y,N¸J¼¢ü–ˆ%“î¤î%â*ëѤ¹žtMOG‡Tnp…‡°X,UÓÇ®$%£ý¹éøt:öO…+0>® h¤ß77'Ôéfˆ"ÇW9«··u®§7‚wÝ{5Î^W*gqeP5Å+ƒ¹ Å*3À±8ºÏ;80¡–-Q‚•¥]é™ó¦ö5| .we…oæ,º7œ„äAs™}„;¿íú #›ö†ñ·­÷ªTauãÆädé“/ïþ¬q5Ù>Ü_Màu–ÿÌQÐÓ‰ÖV&^e¢éöVdT‰R"œK'ÅK§c¯ºWâ>è°•ê‰ëR;Þ“Òyð•ÂhO\Ð5ç0`mU}TQë#ÕíS±˜ºÉi(äǰìyG¸‚câlÖD5e=o†³ f\a—Ý”WÌbØÇ†(R®¨¼Ú¶ÌcÁ5ýÐn1äV;°c ‹á(X´Xíù=Qa‡¬-U–ÂÜž²Z ™ !C…•"ÅNLŠºÞú1„©Lø PÕ1[”éUÍõÒÇ•|Á;8· ÃΧ®v0^eÒpbЇú*Æ]£tÚ6â*+Âí«Ø)\Íq•¾ŸªKO¿€ï§_ØúªG=sÍÜ}ü8Võ"U3˜þwùŸs±øû퉶ÞáÛênOã‡UñmÄ•zä@b @] ˆRˆªs‡Ç'¢UTÚí¾ ‚Ö¥FÕ±3nnvZ¢N£]“®°h§¡ ÔWâ,xJ&Ü^«}ùL8Í '?ÃYòQeŒ~õÄ9[WnØ‹ž¦žöÝûІ~uA¢ã^úƒOÐe\¥¡ánq¥Û¡bvC¸êÒ¸ŠWaŒ'`<÷aîÞ”X:ʸ‚âX%$ƒ«$˜Ïwâ±1• cÑWUÓééiÄPL•ì*âxFáj@åÈL,^õJ=ëØ\:=‹pùÐÓ÷º'þnv$±ž¥>Úß¾ü'ÄÄûû*!CÓ4U•x“žhÔçyñ7¸2ŸY0…Ñ/Jäªr–²òKœÇná„¿D4€AËù{ç7çFõÜÄgàj¾ qåƒXR¬Lëêþ\"~wí}¢j j ÏcßxúÃNOÕ4õ5UÙ®`¥êiËW©¨ýG|®J!ä~>>6‚ eR±å\;2ÆpM½ÃÜàLMÆ)‚(KÊ­ê’ª:ÝóA7àéùÎóöm ^Á¨9*8¢bM²à%F+¬Ø½†¨n0 ¥ÖúöÙ±¶2‹]€¬7^.rŒkÕŠ¤{EŒD¤Qm^¡^Ü Š3…é E(Q%˜³«n¶×Í~hHª|æPÒña7=\µi\Ù—s¨{n§=ÂötZrò8‡árhšfZcøx|Kn&ñ;!Wp|ç…Í’q1QFwF¤´à>«¬v‚Äc"1˜³ ‘bÀfè±à;Ìã·jç$Èz ¼‡Ê¨2Nï:^õ£raòg‘œ‰ó’eÑ/¬—ÚgaVÄlvšZçYXN|¨Áî˜*Œ’ä?}Êû*ãßê~‰«-mŸÜxõÌVý-;ÔsÁŠ÷<ѵ¹Jxï¦ñÔ>°»p¥/ªö’·Žˆb”gzLšÑb€{®# OÝ GÉ’¡„UçTV‡á*“1±Š;W5ä¸YíĺÂÎaÀÓ=`)¬vTy΢hC÷ˆT8бãYhnÄJêÎW]9Ý©îìT¨êxXj|Ò€«#öä-ÀçÍLK™BÎýªx¸úd¦ÌŒ+ê2¸Š Þ~„£š÷™ÐDLQØ›xt}h´·r®ÊþΡòz@–ÂÖ»w‰wï-¯ÓsÓéz]‘]Ó zG¥Ø2  |rBsn¦‚âÜÜÑâiš5k~¨è²ïÛâ ³ 7”j ²f_—Û‚[[æ0XcA®–ûØ¥n(n£fÑC$[Dg6+³ðCUFu©ª™xm0ÞëT(k+kX©kĤ7H#? ò©‚KA«¡®®¡]kHáªs0€«òòPÍŽbë¥E7mT½•Ãm±ñ••ñ{Ož´>^Yih«ì|Tÿ¹ˆüKÄ­ËXmÁª0È+,À¾‘‘ƒ3An³»ÛòfÖuFÍÔ¥­®Üå¶.®Ž›mÉÞìnIx‹]kRG”ÕcŽÇÐ|ìëë RÚy_„>6 QI@6‹óds°Ê>ÀÅôy#¡7˜´Z(T Ál×à›ž´Ž7¾PhðÓ À§¡n%Faé«)î«U~Tl&VW÷P¥ÂNõÛ;^&ÜxõM\ÀT–­§PU9¼Ñ¸2>°¡.ü-WVb•C(´árá£òòGõPvi¬uuÑ3wæìpÈ…Ý5f‹ãŠt~ ²ðä÷µz¨z¨“à›ºÇO¡¬„«¥iR•ê“pô¯k€$Ø9tÇ(1R«âdÂö'u­WŸ\\ ºñJáwH•pp=謲ëQPü]¢:;+Uþ+kºòxc¸RQþc¨w=Þ®*¬¡ëCª˜*¸øjioëïˆô¾}ë°[!ov!®Ž”µÚ>y¨¢"ËË !b œéo 'z¯°Fd•¨¼7Ú{ïáÆ†7ü+ýü26Ñûèùg«ö†ÖÆÆÇ@™‡¼¯pÕ£ÝãÆ7ñŽ™²‰JŒa£½e ÷Þj >yôÜÅ•£îa·åk¨*å=¶¥¾‡'ÅÐ-µF°Z7ኹ|: ¶ŽŽÂj«>‘iSâŒæ‚Þ~óa€{ìú¨Ã5»1±ù&®( ƒJ݇IØ}˜|ª’^;¦ I=ÃÊIªVÆ•zۡ΃€Ÿ!ƒWe1ÄU'âj£É°ª&Wæ%ŸN 'ut °c  ȲçáPçàLå¾2õÛÝxYÕÚÚZ·2P6ŒÆKÕ𘀮F*U°z\÷p£MÕV#míM“ \:0d öO¨³Dš;¹w'ÛG®SgqÕqãå8PzšÚ):)Un4ÝxIØÂ~ÝCȈ*eªÇÂÿ1­7šÊ ^]«Í‡ì°Ïe›ìrK‚%D÷QH;W®&Ÿþ÷(WÄåCHý r 49íÓ…S÷ ȇÁM«Æ åieóÊ]BuhW\_Í‚X{ö Wx“ïsÿ\ýOûx€» èY)\ëÞÞ½{·ññã·ñ¦2 ¿X\ÁÍo¯kÝ\•«ªÏWž9/YÙsYð­mƒ ï·‹b3P5©*¨l¸²Òßp£Mao;ÚGà‹êLˆðSQ¯}f\D7Ú&Ú6ÆVVÆÚTás½üúPÿÆÌä4«E%¬òG)X/;6z¯«DØUª°¢0¨ ø¶©}~V•SÏÕ±wBÿ+TÝèhµ@¥Þõhtbfq5931ú<òº6éìG!"! Š«œ£Ð.û¡¾8­˜ß8†> 7æ_¸ƒê6¨¸Z,àœ™Þq®Ü‰³1=wFÍY»2¯‚Õ‰Öþ.\Ý*¿S­î²ŠíúÞÝëhÁxðã÷B®]¬Þsj…ä6d q,¨® }…àJÄ«[åØÃ†§[ï54ÄfZ`ñPá)ÖhD+OUu4XÙ_9ððéäKj‡½™œQ…Tgÿˆú¥ž¶Ž·Æè8±¢Ž«*­¶+XMTv–ß‚Ã#ëÆ=øEAqH}©¾¼SA¥J«i£W Ÿ+¸M´Ï¨ÌÖ  öëÏKµšèóë•퓌+!•5áøw­ëzeYÄÁVøùHm2/ÄŽm°òÚ¡ÞDp_PcšÃĈ¼“ oJhuZ¶­ŽTõ-œŠí›=!#ºi¤|ÖÕ’k ®ˆƒ»¨WÛJù¸‚D3X63y÷gÖÏ0uyPÝÙ .UØÌ4©ÿê--í-M7LeQS¿¡g¤ÐX^þµº£WCWÇ«[å4¦’©µ¡‰FØ“ PÚ¬¼˜€Õñ>{2Õ\å°Ê`„«—@jîïnozB%4$Ò·u ªºV¡îq] Ê÷[Ð*½5T©~ `úTA@%=užµÀz ÀRù®wd£åéŠ*üUP{Ô1}ú®G½eW!øVmm­Å„«×ùà@ÅŽ…QJ2…³cšý` |ÐøfKû*¡Ì•«“-åêö2ÕYðloÏUø° 8®±Ä’Õù`ËÎ,™,~?® ÂúŠm»ÜljWµŽ aXÿWAÝ{UÉ·!¦¬é†985®¨¥þ¹ƒ¥õø8ãêk?e4® ´•»`~Fµ‘Šqã ¸ÔŠu묶)0o(Ãr\…,±Úô¸ΖêXXÖôVEˆ_7TÄ«kDXµÜ«kT%½‚U}T~›Áßw\SCЯ*• új##*X©g~²1Ò õ–åæ ®^òÿB#ן_Ãf{E×õ^«kùP{ìZeììFx”ärÛ$G„£fGߣÙÒÖüP»2¯Ö·ÚˆsäI]:|v)$º'Öº ƒ!2íZK”UÕqpöGp— /Q¶±Ø=Îwêj­km‡S Æ5FK¬}eœMW„«;Ö€ý«¡gÜÛ@D¡‚ ÕY W“7îB|ƒ´×O59VöM°T•…ë-?×p¥:zªhu÷%m5ªX³±¡p5PW7 ÂUy=÷Ýo©zœñtFœRhºÀºÑ¡BãÀŠ: ¨ó<@Ð<\uUà|ãUâªâÕ¹˜ÛHû7Ù¶’êìvÿÔl6{f]BŽÈVìvMÂ0DÉç(܇·o3Ÿ]wCm´: -Ú—Üþ‚¼l ìÈ ÃÕWWÃÃ3ê˜ý"Ä=U©ú¥ec°¿zHúÔá0vo¼®qFÁoÈMåÏ\\=ëBƒÅU%TbPWõcvå£4½šÆ1o:ZðœWNm)nx6­¨XñKä1Ç>³¶öÖºqØÛÇ8§Î‚*ÀÁ©ð­:ú 1¬>wÕ©”…?Öª~ƒë¥@‹ `Ýc`ݽû>n-é•ÁJÇ««Zö¨ízĸjh}^{nX3SÑdOÙÉ ê<šþE+_í¸;Äþ†'‚ëZÞÃ:•ÉåfÝf_6¸ÂP¥÷oØ©$dWÐÕ$2äö‡G`°GõÕõU=u~ÜxÕ$p¥n#ä™»wÓ­UÐzX©{÷üöºTÕ¶C”Î!Ù;ðpõÀÇÕг!$Ù4u`£ú˜m;Æ[ U•ý *ºXêÆ@Œ¦Åàªl¤_åEUJÕÑ!öñ·fVêÞ(€\}.UÈhBõÜñŽöÊ!Ý­Àzû3•± ¬žs°2³@¾èöJŠWI¯àIW l"{F‹<¦¸b¯±Ú°ÐuyÉâìÛÞLP¨{P‰%×ÌF×–¦ÅA³ï€³°@gA¦0 ñ˜;WÂTâÐ7Áq[W: ~YKòúž]ý¬Wõ$snºÚ别*«2U©·Rž¹SA †7ÏhüsN‰˜ËD‡ÜÇU¹¯:épð²ŠI¤ª Ç=ÃvuÔ¬{Û¡>ãN§˜ÚtVn´ÀïÅÓ ?[=Œc÷Z[Ÿ `ë½³WáJýžO7;¯cuùŒI¯mfX`]'º MýË2°V »°Qyý¹(ØyË'bq5 ¸Âx¸ª´¸z^k+öQZ™˜K í\NY/„Çgª+­F„ÁÒäÛâ$H¤c(Úû¬W‰k)A­«3–h§]AeÞˆ|,º 8_بd‘p•ýƒáˆ¾o„.¼ƒêH.qÌ=¯ Ñ4¨ÿ²O º|½Rš_㪌&,å’(¸R °ï‡ŠÈ·me38îwQUŠ]8<Œ®Ê\)Ü^‡¢FË4%¼>ªªnvû†*¯J™þ Oî5 \ATEœ—÷ô¡âFÓD§9 jräѨ‡«dW¯\õìŒÝKÑzDJ¯Ê›£àñ±N‚>áJ0cl´‚džºP8::òI r~ƒ#Áeá«´·¹ºÒ5¯v]GTtVb¨Ø‹¶Ù¸¢Ñ›N9zìÂuû§á²ÝRh„ÚJä¼"¸ú4¼Ñ>^WWƒ*uÍÜàX•øùçV¸/ØÅ¿‡?s«ÞqG‚ß qÜ•õyq…ßæÑ5>J¸-/ÕüR««H½*½-›¤ W>ã*ò|TÁOà*ŸÁ•ÜŽˆÒbXÆTV5^ÏŠ´·©`/Ú¹* î5s›]¯ Bie4ûÌIðôÔ²ö$7»æeáÐL›C™ÇP_}aïJTö»ã•—•ç½l‚DC¼v’¤rZ¶àú*S!Ôàˆ«¶Jì>@ïÈÅÕÆ ˃¬ü¬ÊeLom±?„ÔùÌ÷¬¯¦ò`ûS¨ÊMëpuË‘ÓîR©mˆpÕ²1Òù¨”uÿ¡”j3¸R¹î3qûºž_‡ ÷ó[C“­·[Wà*ŸÔWQ)ÀÍ8]«œuSÚ'?%Ô¤:öJˆn%{ìz(h Ը♠z š.{_oÌË™àž=>#U>½2¿é­€šCaÀuÁEôUÊ’êñÉìÉâªqÕñòÆÕ§!>»}ªT‰ëór²\+ÇÏïàT×ßÙ‰óár¯ ®Ô3:yp¸½ƒrOm¯Ú†+‡Ûê"n‰h%|X··7ÖÝÛ±¸R÷˜qÕÕ¥ ¾Kë‡z' ´aËœùÈ”ð¨õ¶ ΃ÄízŽó@›“1IR×S\¯ŸNX\=b\%m¼*°Ù…f¨¬¢Q»#(Û û9K‹AdË®•·0ÏI°Û´CµÐ£f‡buµuÊä3û7Ë{Zí‘ZWó´~shªö¥¥%á*!G8«bkž†7«?P_9¸²(P¸ÂZç–¥¡kC÷ò¯È …Ý$tLYèšH°\ †âª{U3o »ÞÔÔÇcÞ0t4ê=Èú[ðe±:àÄ`½«Ay°”L“ºtG»æPŠMôé|÷¹ô:œ!,ÝãþÕµk|,ž3uÄj…xô8zrë+¸Be¯Æ¬ž&»®3® }&£aVÍ5Z5z $Â`h1¼Óð'‘+¨¢ÉލZ×M«vÙ žê¿)¬¬­Ò²àœ±‘dúBW„¨¥ÅÿË*í< æû­¸Úè·ÅŽ®îVCs¨‡É­ñM ,»€ëýnUd·#®* bc–zJ!VÒô¦éô2Víu÷ÊpöRïÒUTß\YV¨…öZ•ÅÕ­ÒÏŸ-ª°£¨½m¶‘ÑG¥œë¯ð 'Ö¢RìëDì8ðéË»X÷‚ÀJR¼B\O–Á$0ž'´Ñ8g;y£ìàË醲h›Ýjƃ`sÈV³Ü»Y»°ÓfÄïޡ‡³0ß瘡ÚÔ³Mã²kO‚ºÏ²0¯;WÚÁ9‹MvJƒßÆUiéàÊLÝ貦q §!bňˆôöIŽø&'ÇëZÊ4®6,®:Êà)ab4b×fÃsP;Ëfà®— cáî¬F‡o|e ÈSC½.®ê¥1W'B„V !‚ßæ4Èeû[˜–—0°Í<…ùÐÌL“ù„%—$AxÔ`\©’KåPxN,Eq윷ÌÐŒô"DØ ÍíÛ9sP1Æ¥ññQð‚ »dÛ| • GTp[6$½,xv¦Ç7vÞl§‚¬¤~Úª¦òa×êäf¿;^áF‚Ä•9½Áf6]Û?¾ ÊŽm¤Þ ÔZa¬2®ª¦aÄÕ3ÀU•ÀU¹èv¶¼A~'ö7;ÔâMí8k¤þ‚&±o ¬¬´ ö»·M?Y#ú“‰Ï¬Ü'`¸`=‚¥éÒz¤UãÈi¤óú# #«5M6bûlbdB‡XeX¸wsíùõ‘™ÉFîRŒyÈÌM<à‚cäë|ˆYsÎ. R¨º4>ò¨G7Ü uùV’ŠÆÍ«În¼ƒ õnÖk´ÛL&»›{{‚ÅwhW»¬m¥£ö¸hÜæI –7%¾+^Ù|SŠ[ „«Ç2¸p…#Äé:#õÿ IÄ09VW 1¹òæq]CKÛ'•B]Ïpü4Xf­ï —úíu +uo'g0]/Ç£AåȲšÛ°iq«ÜÁ•¯Øõ [ ÀUÁ¸ëÈÀi§1ùà(wï]êFœþ&*GG+7 °ªX]6`µ{uòkïÀ±õËŽö‰Þ^ £n´«ß¶îžŽWˆ+‡nŒ*åó÷I…¤ÙCvO…$Ÿ”fg6;‰…Áë±Ëµæ¾°- ¡ûïxÍóJ×<ãJfÂ/ä§Î‚'''H>þ¾xåÔ1°ÛôØ]n)ÁÛÅø!œ•chF)f6*;Ÿ¹0¬â§TùíºJoe-o‘J noªk€§}³UÈ "3§½åI–V×UÝUõ7§iŒW·à0Ø‘Ûö]Pbm´·Â†¬KŒŒLÇ´• ²mï¾BpdÔóZ`©Òþš]ÄDØÒ€¤¯3êŒÒ>+Jã*.\;Ý…” V˜A<[—V8hnöY1„ªC Ú=ØÕ"W»ºm%D!d­G„Õmú#v¹q¤/1mAæû¢Õi)Z òñÉãŠÑ%qU%pU*q5¨YnuU7f†;ŸÝ’[2•m-“Щh˜Z XÆ€ÅO‰eTW÷€VÚ?t}h¨p£¡®aI2Ÿ+è¢*µ® “ ³ç#Qþ5ª<] I­¾ÔîÒéO=ùô»êîuàòPSÇSnTöŽŽöN<ôdšGÕ“8ÀÂþè5íQ‘¬½Ö…Äw"¹·ß°q¬¬]‡á‹3ˆ+ŠÉ}Ç”¬×· {a Vš±JÊzè`Ñêâ‚ÛV‚¾p´µö0Þ‚ºuå›ßPÏj3ÌÜwÏU¾,ÑÙQ–ï;«« ®pgY-Wއ$Ç+¾XƒÙ1 !À^E;lò©R{Øâg/º¸jS÷–æ6êÓʶ‡ ŠšÅžô®uCåIz‰Gå£ÐSåòJ»²d(uö›a_ Ûî|² B;,<¨¤Ø9‚¸o¼×kÂ5ˆGÏ»  ·ÀŠ3°ò¤‹Àze~ûÓ{­oß¶Þ‹MŒŒÀšÎ’–ë€Bú:êH¯Iw.mMÂÓ@¬æcÇ¡«9D…Èš Zmö;j.8΂§®ÆU Gp‹ªÃ Ñ¢«ö¸j²cV¿3Zù¸BPtÂyüçÝxî,g¥3Ó«„ãàp W¬xo©]JÛ8*£!®T}5Ù1ó¤Z@·O‰ŒóÁ6Ø!/£Úžqõ°léS-- ­­o”m´™Vi}9ÌþZ4]T½öËɦ‡ÇHéÃÖs…˜H·?mh½÷0V¶tuX@-­„ûƒ°÷7Á[[0jŽiÁÖë ÖgS%Ö5XDUÁ®Qü!U¼+”+\¿ôÑë_2iÍ%·™÷//Ÿ ê/4‡Ä+–`ÀwF7mÝì ²Î#u®ŽªŽ¼à‚˜5ï…XÀÍo†èþK¸¥%ŸpµÊW¸)ñÝÑÊÃHý@QGîŸu0ß\HenÌ*ÇÄ[é—PhC7¾þ›÷÷«S~hµ¾¼[y › ý*¶ê§li¬$FóÛºF‚<%áj¸²_Õ𽕕ƒª,y˜Qþ~ VOÆÇƃ¸RÈ]í„uçÊ^Ü\Öêzþ\E-X¬¯KÌ×®UÔVh;?}~׉È^KÊ~¸å¬üÌkH’ ‰Xu)\>u•HÅŠ 5ì1Ðl4ãÊ< –8ZÇëºJ»§ˆ«¡ˆöV€£WËv&Èã@¶“°~à‡¦ºZò]J$—HW@…-Ô“ÙÙߎ«¡þ‘ñÆÖ7UW“Mí/nÕûʲ™É8݃·êaª–Ý€í¿a‡‡onÀºÞÝ—oWžŒôöëIó[c:°àfñ“ ìpTWübå@S€¡Uųjokckë“\`Ä]å¶‘J& UÈ . ?$Kd ż¦"òÖÏX30 â5fÖòȟŸóZD>¢pÕîãŠV™sV3TLn¦¦d{¡Äm†ÊKèÅ`]u°nH|R;vQµ '7ruSk=R¸b ¸ÃëØCÄ«/ìÃĘïÏ‚~D\½¯s|‘ÆU:ª„£˜Û/Ç&AÓ$×BÇß¶¶¶¾…Xòöá°ª:&A3èîøJ#TÖå†zÛZ&9{µ644<Ò÷ñ€i®C¼\)–ß*ýÜåË!°H=¦RïPê C›_1T‘vŒU ’rE¦ãÕ£Þ††7š´ßÐððáÃQ^ Ñ6ο6ñjĉW¹TH]kz‡,Êk2{‰˜3kéÐ] X[¤ÇWØÚZ(!Åȵf£îAk’!zÊã“‚ÇÙÅ,k\a× 8Ç«¿9^1Z†qMÂÓ†7­ãã+ÕyíV}˜˜K%¦³Pš>lÃ4ÖÛ?²ÑÃÝõF\A¨Ç2z£¥£U,n½À`uˤÖÂU'Váîl†µaJQ¦¼\½©TO¿RWW˜˜Ÿ4«×HÔ­W£÷ÆíÅgÅG€+_'6ç¯M¼r”Ö"jœþzN,rmo»••5~ëîìÝ\8“›ÝcG©cW„a!°,ïTW¬ÃÒ^Ë‚¡ýËD„*ÔÒþ¾fhñó Ó®aI28ÂLRÀ»U&>E:AÌiT˜‚»®7±qïí“1”Ú€Ž7tzi7:éç­/UEv+㪫¨UóçbV»-_{Íw˜×ƽApOxbÔo‚Å<¸¨Ç<èËY…àJÅ«TŠDø+4gæ6ÇÈ6¶ô½æ0ŸõÐ+Íë¨ÀÀ,>$ÅøÝQ¯÷éûm»€JêµA‰ßf_: ¸ÐÜÐ/(³zåÂ|Q\i)(®aL/áU8C\ä```FJ\öø‘ Äú+Ïõä·‹õñ¢ü¥QõÚf*È…àê[ÖÍ‘k"×É«¢øªÄ—T_Å’þù#{=ý!õ½sÇ’K“¬¸BZ¨P7Î]šaà6r­šÍÎM‰—]; òIÐîÜÀ¶¼§ìѧe¥b̲P÷Øt}Àùý¯®µ »Ôe|•T'?­®>Ã")Z‡\]껨1þ½.Ô„  ”=1 ÍýÇ`ƒ_u,æ?ÃkÑx˜qu½ÞŒú®À’Å‘G¾Vá•PµŽa@{_—w ›ÂT@%Mãê—×FWo70"¨T¸Ú×Û—Ì =æùc›}Ç`4êV ñ¸ÅýÐ)Æl¹+‚ VYÇZóÿŒ|º4…áÐS¹röOë‹nZñúÍÉfˆWÇЖA‘(Á·ús‘Ë•[ÔB°ñôGk¿ì>[—}a/^…þß E™ ©v&¡†©Z«ÛNÞ̬÷î:Fh¡Pà =׸jݨ¼Þ•Œº'ˆ©ý}-?äHH%—ëB*0p{aw«ð/: .Hù>$ˆz••U%Î1(\mλ›‚¿.¹Ò´‹²Á°J<¾Uâñe¸¸2¸²¨Š|+óˆBç³xçÜ}GO8MîÞ:ôß>E—ÀU/ãj´<  J©NÊ^‰“@áTü l ‘Òæ^@†Öb t‡ ^X\eä"ó¾= N³È?KŒ"»[±¯uK^¨]Àƒà¿ [\]„ˆpاSà²+¢½7`Å|æ—Æ•±)É®~ßöÍU¸Šø€º‰x•Ë· æz=ðÍšîÞl!ŸIÓJm¼‚e‡àÓ^ «¸“µì“JY,é`$YË^úÕ“áù¯VCJègçC,s¢Ž¨#Ìyý\ãªWáJnFˆ-.JSSav©¬-wØÑk]/sÐûÍU`°)P*f¨-®6Cíumž¨}泬üo–oN¸jÿq\EŠã«Ò ËTóÉ˶‰¸Éhllòù¼ëˆÅ‰éªét<6Ðe¡åZSájBçÁÒˆŸSM‚KZ1bmPÂÉ+äJÒ‚ ¡O¿ÑÁªÖf?÷òý(åF²a2>®ÎÙž™Ú û—ìLɰ’³@áPiM*»×üµ›]Ú¹Áƒ ”ì ®Q%µCOf¨:Þ–k7ážÍn7”‘Åû*yß0ßêä·Áj£ÔçT…+ãW—ƒ³kîéîÑN,¡ÀÔÙI$ÒQít„!¤¢ÖYŒ«Êá2ÀU/j#¸°Â†õä;6žäwŠ_çüªê­ÁG5ŽdI©—-€åY–`öÓ~L;ä ‹kÌÑ®lieõB© Šév( †ÄnÕþYƒÈ¨/l‚b|ZàÊHÉ}.¶’³S2Ðu”|¡ÎÕ “f[ Ïe:˸‰Å91U„ž’Æ„Á¤‹t"­}dÎw¬w|•Z×$®&ÊÆëNôvj\]“úÖ:KyeôNÔ¶Ÿ¹Óæ]NŠ”ÿÉb0z®þ¦‚xuu½VGD"c¼Ú°¸Úg/ùmƒ+= ¼"†ŸP¬Ú5…££-¯Ê6àBA»tYÂñ6¨ó‚lµäTW\²Sëj6;ûÛ®ðIÜÈsáL…’÷æ|ªkôaܹër'Eá MÕøVkdùgDZv\sØM>;<ÿýÒxR’T25:cIx4ñNzv^y›PóÆ@WšÖ¾~Ýõx 0?ª„ùõó®×É_àÕ¢W W¿Ð23Ò¬ ­Ü‹(Fc7¢¡Æ—DïÜp/¥³]u+o›‹clDXíyÌPo­Ù”ìK†É—%3 Ø’XýÍW1T©ÿÒ÷Ó uÅMuqß1l ¹Ë*ÍÂÍ¥s`)š•i¼ËçH:ÑÇC]i•>­lÃxÕyðZÄN…µ¿<ŸÆ>÷§{R©X™s5Ö9Eܬ4¥')ŒíàŒ/Ï~ƒy]«;5Õù¹§«8F{'6Êb[ÕÕð´}bdôQ×ë|TàJEÙG]ç´pºm9¡$ml¶¸ì1°Û˜’èŠ]šÝ°zöµ¬t"tçœ UÔdwÊÒÎÏ‹,xx¬­íP0‹>]‹«¼'¸Jž•¿1 Άg@õ{lú🵧*:ÑØýšÈÜÜ ëŒbƒ˜RäC,~¯…ö:/qž!ÅC–Z„« + ñŠÚä?ÒéX,Öµc›ûð*ýa”Ïîéô\\}ªÎ±ØG˜ÆÅTe÷ê}î¾è õ?G:ýŠãúÙè’Þ­ª‚Þ6êgòÀ­œhoä<Ž7ŸÂæÄë¤ú·Q¸ªÜxXUá£×Q\‹03Ó®rZ¡ÍZ~¨Ûž×\ "’õ0 DÀ -Pìsm*—ÍäfY·BõAðlOŸÝ>û¯ž‘#qõ…$cVµÞãìêɯ°© +d«ª =™Èb¯b âÛC $ÆâcQ1Ô¨JÄ"ú®ÇR‰`ÿת÷*`úC ~6ÒÓ3=ý®Ë «ÂÇÕu)¼A¥§'›‹÷ÔÜO¿Håz1UÀÄâÿüß~1ýB½ÊXâ½Ê:c‰ÄGÐ?1=¦¾v¹KÄÆT,K§Òœ%´’¦¦ÊŸ¤×wò¯~\æR¨¨zã% dŽóšDqñ €%PQ¸{ÇÍÍÅuJlw,I( "w¤b踘ܜö-eŽj(+ñ¹ó!ªoäZ×*qIBEªÕÕÿ$ Î:SÍäc1€KO"1éf FI¦J…•`îWݯ©ùˆg2®É{h«‹¥«âtšÞ?WõO(.®ÔÛímèéıš*¦Ópkm¯€åâJü.I¨wzq^J¡^à# 6þîxlzj»êŸÐÊ>NWÁk°¦¦¦k¡ZÞÞV/‡€N§SPàIKÓsÛ‡ÈÛê1 è_ °Úx:íííM“/«uug&FAæÃÆ+…«Œ™ÙLk5p »î† J̺_àXEÅðB žl(+W9ÔqßÄÅ›=mØLùßþ:¿ô+9ß,z>憒nìÝ€µàïƒ+!v¦Ó¯"Qæ=¾˜æÓs:Ñ“SŸ½OÕ¼ˆÇÓX”Sãw©D0÷qLÝø÷ï¦W ÞÅÆðFpµsžtúY¥ånð<¸â¦F+u‡{zˆ;®J§ôûý±D h—ïÕßé)~•÷p÷Þ%ïæÞñ±~*†p•KñÑÁž-®Âzdë|þúùõÞ‰ˆNLL 㘯70göãÕ¶5'k»ùÇöº=¢CåÚ’€Ðÿ³b$°P=ûTX5ï9¡{¾_Ð]^x¿-ÉÍf: fgi·kö?Å•iXÑÍÄÿÔÑÈX|N¥2U¸¼RJUZ]s W²š±ôÆ1W)s¹÷sé¹ð8]»mp¥"_<¸Bs´t<Š'ÃÚ¤®²"PÆl´C\‰¸2…Üöh,–a ©žxnŸð‚ÝF‹«x?&ø¸b‰±)HLé8œj2怈Núøl‚iðhqÕZ·ö½#í÷,®@>&“1u»ÁM˜MæéG"—#|CyÜfÞÕziØ =*ø¤Xgö,Ào[mÒ‹¡j}ÓÛ¹ ÓµkÕh‡®jnèÉ„+Û-·ÍŽ>x}¨z‘‹ÅszB¯RÙXoi:Å=øq=jWz©i;ýDÃÔn¦[?¦põ3i:¶CÀÒ©°BáªsDã xtŒ«<ãª*NçK•’÷¡n:Ö\q•¡CK`ÒIÎÅ°àæ®>6ƒ|u:¶¿r ··DÓÔgºæÍ;€«‘‡uã½£°6£™õ¨R¥ó ÉƒÇ,½'WmBbì1Ðá.ð×–¡ï©X(lyb´}B~¡Ï™oëŠýn67-°¤7 akÑÝ>ý’åõS&ˆþàŽÄÕ¸ª¨1â~ü>+Ö“ûx¯ òBUOªÎŠ äÈŠ#Eñj #U…-…+k¥°‡¨u¬p…»cq(¬?*U‹FM+ ‚U+p¨;”r°g†“ ÅUO$>7]U5†Å[,‘6{ÿœ{¡bÒ?c¤4E,ÖGˆ]SµqUæ+¤›.ZÔ¶Kµ³£»_I\îzühîd[{ÓúÄÝ»^ÿ’IQ¼jE\=Ñ–ßÍÚ2¢D˜›-ÍXÊ:2…; ¶²b÷ï-Á\ð™¡ÂBB«[±Þÿ¦Msx쮵®,¬¾ÑÚ’ZÌê«ÙˆôŸ­µ=ÈxœþÛÖ¨CX*YMÅ­TêÅÜ}„:˜êTÁ¤Žò1ÆÕ+<1¦Xé"±e_óáćÔõ1ÿçÀ\LÅ« ÒÃqá“Yš#-M“¸" ò]‘ WؤT¸ŠêM϶ÕPꩳÀen;6W•ˆ¿˜šJC¶Ž1°ðDŸœ«R'‰wS*^)Ö˜µã2¢”þ¢Îƒ×{cuq}‚ö¼ˆAšÌ¤RûQà3®6*WSÛ„*Áõ8¡zhÃj캰ÚÕcn/P×JÐû¬ »» h|g¼!HGÁC»Ól”= ^? ÚÞ,jÛj1ÌâPðä?Å• 4‰¿:sŧsé1nC~ˆ ¼ ð|ˆ§Óñ18¹g2‘tb:=ɤï}ÈŒ¥« U4Ʊ+¦*2t¹±X<6€íBJ§ª¾ŠEuÀ­<@U;˜)Ñ*+®‰ªÒ=©Ë+À•±°M¹,'kßG3“ææ1ª±JhÝE…Ž4Æ+ÈÔºÛ vàxdcþ æXOêÞ)4u½~kÉä/™(Ò`¢Èe\Õf´@ŒÍ®²q·gxjZ-í@ …B!¸Ì¼pêVzKþÌŠýï%>–ö𻡋>/käCOX°ÿ§°šHڂ úEm& »2ÎÇV®ÕÑÁÇö(â û8yS©f|e7)ôFHWЀåœã•uuÔyõˆd³öŽ¢|\m3®ô<)upEŸ:4ž E“¬Ñ'u±^ö×ÉhƾÜ~îÄÕ¸ÂÐE3\ªOC•£<$WÙæ%ø¶¶X(f¡pD”q $a+8 .[C]9 Ü<#Zèž< u=|7%j[±õÍ lIü§)p宩d]RZSq÷'ö¿º;ú Nåklòî/Zèc…«âÌuPga[ò ÚÙ»ÆøÆ_#Þ£ovFË+:›Å¸[ ‚èûÛr7» ÇÇs4L®.E¥cA' écgèÁç8ŒÕ5ö"²jÏ£)æím§ÎA¯oFá ×qRÍRËJ«ÛîdzÉúºœ2Ó—ÙW˜*x+7ر:=•ÄÐÛÁ›M^jögÌ>‘ݬG¯J&\ýæ¹M0^I¦²˜4ù[/ tfD\½¢ô9í—ÚýtÚP­ 8Ó=¦§äÖ@6ŒÑyØtÇzÞK×1Ä+JÀ)$·DuuÎÏèò!PÍŒ8ŽÏiBø¶îÉnç(h)|Ã$0Sû|t5»WçûÒ0ÂïY™N¨Ý ¼`—¬«Ìܦ¾ß_ÒãTÐ÷‚Dš3 [ʮբÞ¤˜•Õô…/,›F¨Zý=ÀñvT ² „®ã¤îò¿ñ³çó;!:þ`Çv…Œ¯£d¤{(^Û¡à¡À^r“A“D°C\íh0R€ßEb©À@ý¯>îsÀÒ3J—G•Žnh<"M3˜ G{_=®k¤Í/õKB©õú5Âê áªë—}ß’•ý…'—WW1#´`è–¯Å~jÖ™—yK~ ÇËR7û*o’y©r¼äìYízs²ú ϛ߆+ŽXr_3é2” óÛ—ìd󭯉ÌÅ{>ħáÆL¢Ü—dv0-Ì8ÔuýL¯Þ…Ù“3C›ÆÌØÜ~ç‹Zˆ]éúÀPã7hFx{×pùï2¿PÈRÈZiEðQòáUI°ã¨`Á¸0³–ÃWNE¹.´‡àx´µ –äûÜ`eC«ðqÅŽ’i^¬:íÐy#Ÿ-‚Y‹1r1Ùß)^¯ìVüÉ ø7.æb1¸Ä´-=–¹ŸHÄa@ ñ aå/WyìuÂç;u²LLwéÞ€èˆ ,Aù¢t8ÞÞ~7ø'ôÛ?b¡Êij–í6ȶB&ꉧhÍ4—Ëhd€îÑʽ±‰‰ t´GU­•±J`õQcw‡¹D;Fظ¶f6N¬´1oFÈÊêÔH²ëµSÒKÛ»-++^ä²®ò‡^Ïê0lë&«eÓ0ZQmuòGàŠP%̆‚«tá»Á„$"™õÿ‡8G™htºG~} ª\Œàͮմ߫n§{yå~y­ØÈcôU8ûî±ù:ï#  cØ?=šPଠ?Z&5´ C*ÏÄÿ\Х™ªœ º‡ÌÞs‰ª®FJ«4ÎÂV+´Çƒ”·µ¥ÞCÛiÉ0Ô 6íU ÿ  ÊÝ4Õ»\ \¿X“–”:Tñ’ü‘/æqzjY¡Ë˶±œÎUø'AI ý¿YCŒ¡“ Öõø=ë+?ñÎÍîzVû -•ºÎùœ‰æµX~m%º˜•îž?“rÕá\â*J]S²ªzz^M§uó*¥y‰Q*ß3Ñ`MEfTfp_Õñ*)ž'Ïáú¥ûûSrY0B­T¨ã#@…/EÀp#Ü3à)íœÊ±ÃµÚÔâŽ< ôS Þ¼ ØseqOiì³Pa‘Æñêïˆ*ÂUE`*tÚ«¸ Xß-Ã$§J+¯;ø5»y"ŒàFEƒ«.Áþ-Owx¤ƒ*]g2yѨBÊ;ÖR(àkdı4u——í*Ä6oÄO¹ÛF.Æ#¬.Ö×þº<ªZWN­ã)”ê }}F̲Vù'>ª×7ƒªróTgÀ%«EËÇÀ¢0üΠòâ• ›×ÌùßæKÝDÕFµµ¶LóëowòIù7®¶a0åuÑ’¶ÄÆCÒÝÙàó4ÒªÁ˜2MY.¦Â\l Påj„Š¿ñt“†¹0[ÖNI%üGlÅKù5™AÕøàÀ.ð¾)pB°ŽŠ¶Bí"×Þ›žsÁõ$)Úa aQž뇮þ®90¿‘ù±«Â oÞ—Ük­EAÒ[åK&k‹ê»˜,˜tŸG£ê|'ï´Iw( ¥Œ›VÊH5âègVwp‹Ç©ÔÙ BøšNiýŽÐ•xk—d¸0T­_ȆùqmA"ÄæÂ;ɹ&º¾mF+KˆÁr}oÏ«ÖC¶™¥ÏWÙZ~¥bVÏÃãªö»ê®°‡»-Ó¼\Ý«µ«ˆ¦“¢ ¢#›4ñ*´lÏ;óh´&0=ª‘û…þé/•syìȦ¦Ä¬bDyL9¯±…5imc: ZyHç@Òß+¸fÀUŸ§Àw[J;*HÑÂͼ;¶qVšçÍ1PJg³v6Ñá ©ýÏþþ¸JÖþ^WXçËë•y ±×® µÞjuRäÊ|Èið 6§QF©pÀÀ˜fFà T˜/··¥¡Û1-Ø„­/wK‚Õš0_¬‰Î+.à p·° TÐBá( ¿‡&7§v3Ð]Œ8ãžÕ¼–ÍÞtÏ‚fCþPÛ4/ùµ³Ž‘Þý½3 ãJÀ$mãó÷šyBÿ`§%ìZ{Ò RNEÚ] f{¾ƒØH©H:—LûÆ{ÒU¸ èíׄ,o™&¨ ®_Ø­ÀV`·û[ÐZ¨:B¹Î«ÌÞ×ò™VvÜÜsu½•fÑ u<*Qãx5û…Œš!TœÌÎþA¸’º>ú×Úã­Sÿü8ædÃ@,®_=^ä6BOŸòš¡F Øa—²Ño/r™Å§?§ªbïe¡5K»B»C&ÀnÞˆN”/ z±f„¬XÇC‘AôèÈi¯ã„9¬·p[wȘre6ýi S­ÁÅ/ª^_ý¢›ì³YVûÿp•ôã‡#Â`5¤’EQæbPŠ7„Ç£¬å·Œ"DåÃ!eØyºón ¦(H¹§?Ó«² ‚¦Â6/BL‰0Õ\ ËÂJP×iw‹!…,«5­B2 h.Xúž%Äðj„YdÖm+ë#è‰ð-I®Õ^<«òÙ“? WœgŠ]I›Ðc›bÖ¢Z´ ¿­ ‡“9ï%ŒçÔç´ŠœŒí`ÐRhv¼²=Of†(ÜöM¬ºÜÞvD†¦Ž­*hIÈ–©»gC « Ü äÚj÷`]ïouN’Õ)gÀS-â¶Tb7®bh{¡¿°m/Ô“ "^( ¦a×êƒàʵc! bµÉ°ˆS›üöWŠƒ*$2yµù9ÒÿÎóW±]1YÁˆfÚW4-Зu&5!æËÓ‚©«ŽÝ,Ýæúg@MZ @ÁÛ­ƒ-+¸PXX8òûUfÕfyY*¥9¢ŽV„6ÌæfÉVí‹K^YÅ,vrØçÁM®ÄIË­¦“yq~ áÉä“?vå…Ìž§åé•QøƦoJ“ž,T‘PE}Æ2iÍäjrî'ò-¬¨L÷E†œôç‘«Ö|-cÖ3Þ=® iLPôNú\â±aìAÉ{{{zåt3UKKÒFPô­²ìO ´˜:Îþa¡Jâ*/•0’jI3pÉ'íN£,ŒÛ¢Êk–8Ð%eP ô Xc+t ÙçÓ;ŒQ‡IŒ6€¾u7þˆõâOj(LiÖZgw¤ È‚pËuì=ÒUVÔ]ס Öl¶Õ”îÒTÙÕ­ò\ýªn-d,4²Þ5‹€~ÕBÈZ vxë“Íõe÷h(ìaíuž2­¿³¦bsæ,ÎnþÐHŸ²»¿yÍaÑj+Z¿5ÿƒW²HÍ€Eð’¸é˜{©Çä=Þú n.fÄ0㬓¡†éT)¦°-„ÐŽ)ù;ê !ÍÏÀpÙ²‹/t±a Ù Ü\‡)`A.Æ æ2NO—=ϤeÑ`g6Œ˜ÛH>̯ÙjÑÙfÎ~É~ኵØA9Àÿ,\¹ššB' Õ¹†ÎçÝp†ßÓ‰”íôÞŽÙCœR$<ß1&~;ß½AfwFwÂbJ’õ©‡‚d°eZŸûZŠôËíýýœU¥ žf¶jhánnR´›úŸVt–ëÆ+‰$B}:è)‘Œl· Éëˆ&¹Á^§V}ïPëyReu¸¤;¡R‚ÄλÌô¡µú'¬ÈwÜXV³£ÓÙ¹1y‚S (üôðNC^€óG7£æ´'dŽwœFx>oU¥˜çs°JÏÙ– ih+ Ú ÍžÈ¬×«ê.‘‹kv\#éUëhêv V`—Ò…þú©©ÔC¸{ÜWØtÅý]ž•ãôæ0b°¿ð…LnHÑjuvvõ> Z\EÃäB¯š‰i„&ž«œ»ßÚùV§(:‹Ö!ëúPžss*>GƱ,=äRâç~î2'[ŸÛèaÚ<å3õ<…!gÅ”ó_7’`ÖY¾ƒúŸëÖÙt—BƒãåS±±lÌso»Û¦Z‚}OKÎ_­ie´³Ôb‡¥Sì. 9åêìŸ)ÂU¨ mtçϸ¢b#Õ_†›_§ÜPSh%¨.ÙhY4?±§Þìè y~[bø'6!4e1¥gU¨²ÀÕú¬n…Llô"UŸYŒ_æôw¶©õ²÷ôbġՇ9 !±/:¶ßººª—³''«³ÖÙ‰ yý`ú#1宆·¬PDé0UC}BÅ>(ÎkÜùŒöìÆ¢êRý¶Å®ý±ÏRj¡uk‰…’€G dìí’½÷Ö®åVé@åìDœjIã>ƒ*˜ÞÞ3°âÎR÷ þV‡Ý7Ž:~% ”¾pÛ ¡Ù?V³‘¨ÑÎ×G-Ów?úÿ§¢±µ?ï Õ`)ºã¼f±¢<£‹)\u`2zF®#[>(ѨRAjzNå=øÀvާމQTí†*qò+áåŽUVÀ ¬rÉ.×òÖ±Šœ½#[Qis7ÒÉöœse+”¸h(nìnÄ’”ˆa` µÐ/¤ìx«“?-j\íD£VQSÄ £°²cøúÈup%'*Q¿)*x60™g÷cSÆnµ£òK9ñEk¶üÄÀÏO{tð»äC_N—b+5û›½ŠÊµ0íõ”tssM½Í.ŒIÔU ž¯›YŠ0]оà …ý7ÙÞÆë®j¢ñ<=¦1÷صß)íEœ¬þ©°ÒñʉîzyT÷­j‘TIÐP‘4*’]ÔÖN¶™¹ã¾¨=âÑ!/ƒ8 a}¦ÄŽ¥>9î3VÝØó¼$2Õ¾î%L1C=ÀÑ Ñ«rŠô³hD†œ½åƒƒƒ! C+6@ ô«N[6ËÚ’™€Z!ƒÕüf¨´±!Y-J+’,z‘,jA+΂³³JsÁÁUFt‹_NLÑ‘ÉÆ)u„ŠTÈOïD‹Õâ™ KNQÇ]ŠTæúÐG”¼”*ƒ¬}‚—ôÕ"Ë6Ò4OqåŸü„…[·›þÄÚ2`‰ÙU[æˆ#ÀöŽ„z[%y†Ì„YvºUž:Ì¡4¤4"i‡º¯ì.pÁ~‚\0¹™ý“¯H -ÓYr ’-£ßÀÙŽï¡uòé“W7AžË0¶¢\<]Ár¶ÜP5Ns*§kô´=¥ý2Ž©¡`i %†R%L U¯Äíé $߈K[ÖÒ ô«‚óš>«’m» D0–ª³g›Ú5Ð.È Zê-·ëìvºŠ{̬™¥càêW&KzÅóy9œñ~Û•‰JûZªžp)4*ÇÄ¡9‰¸ÙN´©õ¦r¹`œÚΟ)R¿>nökìHÙÂö´…® J?`{SR‘ÊÂÑV!È®:]B Æ+‰DBYv; gº¦ÚÜ+¢ì/¥ý=E+r¥\[JP Hýn’V?Š+sf·„p£>-gŠ+£ç½ZB*cTô‡—5¤Z¦ã£R¦xxJ¥ °R9²í¢3ŸÙoØ×PºÜ—¼<)ZΚj>öT%Žy·á½˜À³Z#µ®ƒÕîºÙƒØ2LPhV…­B@ t-sµ³•3Æfêîi-«ÃÍ®ØÅ0PgÁ¬J[åº ÞήþÙ••Ä•¿YGÜ%±eN:®QÂX†A•µ©ÌL£3Æ@÷Å3QvÍØ÷aõ¸ÆRJˤ¹3>÷Ч‰ ¹íK¨}f& 5]èA:býA©FǸÆ×!\QY…u:õÌX¾êÈ'‚’c.AEÁ~[ú›êH«ÃP…´…Ã¥»%/²¸1ª°bèŸ+3 ýÖ•aXéœE-Jc!YÃìLîYjÙWžhñ d7eRv+‡:Ç)¼çíÍìçlÊ»‘êW¬H°Cå]–‚Q˜F#ÒB«ÁØÁ2ªü­e3\Æx%…ÑÈ.Ð!-lŠJ݈9 3f^tÆP«ù²hdÒfÑëz 'ÿ\Õ¤R©šÔ·aõ\)Ãéô'ù/Vtw— ·PtËl×@IU´ª¨± ´†úú Ãxo/ :»çPA«ù%§²’ò{_±ÐYašô_A••–ðÁˆ0pV9S¿72pÊÕ™B!cn Á/Ê÷5š,šÀÄaÛC§îÔ1¯Ð`Ç“Î|SÅ:é–œà jüBÝ0õØbÝrÕ†?On-„ïmYv±³ÏYóó›aÖñB$Ô y¸«,²aÈ+‹ ´Ä4>ù¯Á p•b-;’uÍáû” Ɖ9É÷¡HH I)-éÂ/•BYÊrX>Õ„ÏuÓÜTRî5]’=fNžaPiGååä »¤ÁR‰íR…ÙAhS\ƒ·˜* W$†Bä` ¬úa”VFïšJÛ\W&ôpÞ¡í97YÔˆYÕæI°¿µºúß‹V¯ôe’Þq¢Zætc;—²GþáDÒ|Íj‚ùö0¥4¦rjì¥}·¥C‡),¡äv‡§p·ãPO¥\HyƒdCQ—˜Ò-*oF³fQ¥µ…$[I0 ÁÁ²ŽT Tªë‘Ím­ ÃB T«³ÞqqO€ž–Õ¢·ø…» än“Å­ˆTÙÙÿê ´ÜÝf¹ËmR<ÃèM(ÃÂо™Â"‰²v¨y™bCozS“ -Åm„Òï4¼¶·sÛû9RPœÃ‘Ï8“N9})¯H÷PÕ-`’ú.ÄRÍÕÃ6ô/.°)„'´·à¬—:Óš=£áÈòØ›b!Ðçí™Q ìX-.ùå:;ªhÝtvöÏ2Á•¾}>Àb‹a`9(xŒ\aëîó359¿5  œ†Á¾F76/¹|ÊQ%åp¦ˆ•°ÍRTA^‚l¤7K!…n»÷géÄšM¬›TV·ÿ€èŸÌ+M…ÂÖÖV ÎÛ¥ÂzRV{Ëšãln±2ÚÞž/9d¹ëKP%Ú Y".°š£¶gþï_£Éº_,„ì‡@-æÂZL!]qýJûû‚t`4<õ¬ ty)Õ7p±‰•·yoTÓ§¦® RK%¡í)»úw!8 »z:Ÿ» «P(ð®ÖÑV°©pª–"ÌmÙª:ce´=n«³§ ^r…Kó`‘Ð¥EgÛt•úU¸eCåzö/‚+lU_lí‹.¶ &û?Ü!£ƒ\è×hœ3E¸íl“zç%ŸðÔ{7áQIŽ=©c¦LÑÒ¨»ã'ô$¦º¥Y·U“µ*U6ÿ]HTaëI [Va}‹DSa;€ îÚ²öÔoß–žnÌY˜·ÓšÃ3 Ç]_\r„MV€Üwêé¡-ßv+õM¶ŸDXI‹ˆÃ@ ”ÙFË!°fuò[=™ý áÊÞÌ-v`µmådѱO-oÈ —LËý(fürHºÜ.~é… FǤ¶±mhçzEtÊ/£Ü¡LÓ³»»ÛÎX!½n[MñŒfͨõï’¹Ìi¨¢Roþ… éñùï(T íô4ÐVwufÈ vyÙ@Ë“qœŸÙ^^²¡juU/ÇÃfËÙ“¿ª®¦X`›î(SppkX–N\q÷Í/™Üvl›ãDˆb ¨)-_­Â’ž‡d=Îvv»ÝÛDîö´ƒ¼<&s”2‘ Æ3¤U¬©ŸÆd‹ ˆztø;=Zh’\¼çŠÍòò–/‡HdÓù¯8c7"°±ž¥íe,«VOVgÿZW„ oZ™à˜V©´!Ò.¡aJ@„˜rLFÙ‹tü FM‚§XˆÝLõšâǦÅBÖS¡ñ‰ ªÀ4ÆVR>ƒX¨œr ë©5»ðÀ½]Í'ÖŠ(°°¢‚FÆHAw@+´·ì×êL­²+6Žâì¯óÁá²°vÓseØð€yû뫳'5\™Ã•9½7O Þ’”Þ &PÐS¤¡F ”°Lⲉƒ6ŸŽ¹ çÅ=K 6º°S!¹.d­O£É˜Ü»#«Jl¥ù×ÂXÄìHÈÚÕ×–5™Ô»!ã?½³Õܬ! èò²ïŽDòØóó~_ýгßZ ñ´a®E]©3{Õ_-Z)\5Z®ÁTóq³Ýš`Æ`;6_aA*­-Ʀèí±aÕ§\Ç##ËYn*|öâmÊ-ØŸ:Œ!u²GºÆÕ×µ½²Ý¦!Ž®¾³…w§¾ ZUËS£Ÿv±Ù$ÂÂÑÖCü·\mÐÀ> ëÎBÓJS¬€`•å~ÕÉ_WÍÆ½½Ù‰\épN" .,»‰¡n.!SÏo†ý뢰ePËþA`ûÊYéVlÑem-ÈuYs•9¤ýß QvBsÜÒ `–XíA¤’>ng››{ÂɆŠõÃШi€Z+³Æ+‚þ™eIGˆTÙÙ¿ä± ÿÒs\žèNÙˆf¡1%s—ÈdBì|J?ÛTè‘΂¨ÄÒƒuÇÜ/¤Ö”Cœ2™¯{Íúýš.tîӸ•^Ђ6Âh ,j èZZk~b‹ÊêuX«­=¶2u±7ES!HÙsuÑæåpYÒ«èqˆºžÅm V'U\‰þb‰ %®°ttS"ôLM57ë„f¶æPßgLz0zKN¿“Î{¢ëi<•Í")5¨vÉ Ÿ[FT/œ¦·`: ¶Wuû6Ó_–—­¾ž=þÍô‹6®Š£kÀµJ´ušÕ@ËJ…¬“Ù¿fiŸâ*âV‰à”fÀ7Ðqõ£JJœ>©ÆÝ®fsIÈQ¯»[šÚÉq‰Û—òêsêzzÉï@;?á33÷[0œO§Hïc©Ff)œr˜rôe1ùyÐM+ˆ6oªõâ(Pñ2Ģ؊—¥údu't0u²ºúWŔŕ{™ !úÙ&S•ˆJ¨¤Ä‰uúAž×£è,)Ñi®äÊ DÍr‡ÞÒíÌ÷Ü=dTZñÂ=ó­câÓú®YùÛEãp,…0U(RL-HÁbÎÂmÒ–TgÂÍ{Ï6ÜH%&€ŽQ á/ÉÒâ3º1“šã_U€«î¢‡,@8¤Äа43ÍO4$ù° )štË „|g ôÔ`÷Ú]Ï–”²Þ6¨ñ(T†óy´uræsT0V”œ>Õm¡0+¼¼÷¨© f5ܪ2áê×%×(è ža.–I}=ËX‚7Ù¿j]ep¥kà0P}ûjþÆç¡îv2]76Q*PDéÐ䬶¯k‹‡uIóDêÔûý !ÓM Ó*t9úöÞ‹A“¤¿P½nŽgZ†0å ÍÊ£à¯óNg]ìB,Y“ˆEmwYšØˆ~ ù;TÁ½?D—žžÝÿÓ5·?¤3yœ7È'¿ÃÃ Ž¿°’´õìZˆà™Í Ê8þuO€\u;;te²^vV$ôˆŸò󙨎ä©Î¬­—”„D¦5Gr#X˜ó9ïB≽Þôâ(ŸøDœ:Br{Ô9øa7Ýî¾³eMŸX©!ÕâeQ¦›Eø½M/šÕšCc¹ÅìâyÍY_ü*æUéÉ ”é(æº0« X!®œã•œ±u$•˜f¤ŸÕíHüÈdÖÝmÓíàI4¡¨vZëv<ü‚õ“Ùhws7¥Ð=r;žLòä½ ÷gPAh«¢h•taAæ?ßÂîjÙø½Mã´µéS`ƒ¦ÞÎ~©®ðøÅ,ÙdO°Rÿ ÷¸Z³•pwwýÍY†’­ÛË^®¶Û™øäâ×c›Û_dÍÙ¸²¹VÞX¿X—䣙¾‹ÏÝ]»ã F3ðxß}¡ÀmEÛéªB?5Û4Tä„D^Ër«Å`XZos/tú': ¾ÝˆË°"«ÜU­8Ký*ÚŒÿ›€ÊâjÍDеµn³ž¶€…øÈÒ.]‰Ï gSVNÝÝ¡ÉN($¬9K¢ôfw×j&ìÚË$>MJ‡SŸ¿Cãñú¸î”ê}¢¢r§Ég¨-Ä+€l‹4ï6Õ}@Ù`µ¸¸äú#'ìR±è Á–iöï*ÄÕšKMZãêØæ¤µ¢±Ìûª[o[÷Pÿ<§É+¶ýd£“?€¡Ðdºk^a—ôH„˜˜Ã^+¡P »#$|†´<¥”žµ+E8í—=Ã&ÆM­3+­®pÅ=uÚ„×°: Ý…6!u·ME*Cªþ8æ?WëJUkÁoÖ\ȼ±{ü(ó5ø‰ìÏùèñ?YwWB×Ö]Ï5½Ï·{@DŽL,ì‚’y*FýKÌâ‚[ aT§¬ä™¬§dQu{OZ@œq¬:Û4Êý›Âþ°ˆ×–ï·EŠhKŽ|ã*[ÆC <Á7PZýÍbãê‚LÓµ{9j=:tÙ˜¶¦¡e{ßkn°„Rª àt¶–Û}§’HµìΓMëÓá¾ì1Q}oo>à^êè É®ºn¬/ÚJ}I,-# ¨zB•Õ,5þn±ŠqE±Aý1]¤™ÖB1Wìëžµv! vú•Ö×Êw‘Ãå<ÃmÑ›}¢vuŒ—w˜È¶Ž®`¹Ge´©qc•±•´tb[§ë’ BÃjÞéN95Õ¯ó\U…µªœZ€YVÈFÂúêêìßõŠXF.ÜXXÓP01Ëu,‚(öXÖ¼0·{X­Ÿ¿&ÞÑkhLæÃ¦Åâx::l N'­ËìROª@vÜ$šwTX(ÞG°¹o¡Ïa¦Ë(u‡É{²›î:âæÃ¦…•/€&—µ¹Qå,-;rëZh/ËÛ¥Y†ÕÉßW΀ÖÞb+Ôs¡c|é‚mö°‡tAP¼°ˆ™kö1ø¤ft•vÙÙúaÉÀdÊ(äJ!¨¤øì5h½ò^!XMõÉX“QNg¤¡¶§…3&¿]u”ÚÜ,&.« nIå²@³ä ;6êúbV«,Œ½ú·X½‰B7—Ïì¦-ä^Œˆ‹5BÚ… 7qßÛÚyüÌ`@ÒK0(G…I–­[™wäd¤ç0ZÐú8x°} *\Ý’Bhõ-h…S×L™O~·)Fq™¾¼ç›²·V¥êð0¸x¸ä¨+ø²U¢ye™-·pø‡o²³³ã<¸‹÷á7‘3Ðî®nbùßõ 4<ø™AʺhW’ƹla¢ô}‘­EÍÖe;¶ïÛâµPü[0“=VǃÀ´<<ÜÃ"†çUµ”é!°5ͲQ¥2¿=± ,Ô¹Aå½ ö‹«¦Õû^•WS-.‚¾†)\°½´_žÅ ®“Ù¿óÙÕ ãTðï>á`„V€iÍà@‡´†ÜÁ.?†®1¥Aˆ?IÏF¶||˜ôèµô,OË–áèQeÅ­ƒ”QÀ’:¬‚ÆR貌ӟBå–å ‚X!• Â`ešTFM®ù=Ö©=ªÃ° Èmªùi…%¹®l…ÙÑ;;{r€ú¯*íýn¸Ú⳺fPê“©IÓ GÚ´ ÕËÌÚ݉IúH‰SÓž¨Û´~°k•¤´£}†Ý‚ƒ-‡!UàÆæôް"‡u†‚Þi¸âć뢄(GåSLg¹OUOÝvw³ÎŒS›§(k "Žð µ°v°ûÆÕ·`½×ZÖÙÁJƒêvM*#y½i¬ÚT{Å[ ìè$OoÉ_Ôbè—Um^¡*;Kö€Ä-ÎÎþoáʹ‘Hx+Ð 9 €A1—ÑìFŸ!à Ü@âŠÈP2 t~CÜ Øèü†ÊdzÚ#*˜ð ß`Ù…b$§Ól7h_#¡¼ñ±«ðrÆŒ—3½Cºgw“E5UŒôéVÎú»ï ÈM*j’‡Ûì߬÷CyЯ†Í=>ÒŸ)®@•â˜'p<ƒü…u5ÌxuiÙ”\ˆ¢[øÏ=ÊÊ-üPp:=2f©Å(ï•Í´Ûmteómi4ÍE°Çt¦(lòÌï0NŽR±SáN“‹¤Ø¡ ”ö²¤^<;{2û?«°ë(P/ëO¤¾Þ:?*…´½=‹Ç«1Õ²ªÅ(5e¬lúl‡³Ïmôù…ÔmªÏ—½óžèy2œO›ÅÒŸ&ëÔwè+ˆ¨E‡Š! 8U«èäý?ª,®ú‚7µïJ´1^BÐñ]ç¶ïJtVc éœÔ2wè†yç¾Ó^!X˜s5uÛo#œÙð]6ç7}‹î06,“.9ê†û²ä$ÀUb€b¤b‰½L‚ˆ«ÕÕÿÙ`¸êsîä•Q¤ï?C GŸÿ×ÞµäFŽ+Á¾FA§áJ "Àw¸P `àÍœý™ùçGv÷¸§–fºº\.—ÑP 3™q%|. ͧžò „ú Ëò>ùµ-)ÛE`‰;7&ª'n2‡Jì”gÊ£¢j¡¥¿yÉy´û°Ô¥@Ô‹¢±·—“TV%ÿÀ‚ûƒ¯/À—X1þÇÙ=ŠH™èßc-j¶ÀHoúËö V Uk«<Œ»Çòä±5´)N{ uh¢ -!¥†>œ/Œ•çf@3N~e"ƒ *ô¯]­Å+QÊœ,áÁöœ>  ç(·2„&ÜY@Ö&JàýebÓÊm(fÞ­ë´vxz0õ€Žçaw°Êês‹-xB³™~|Üš*ã|¥_ ;oi8ê"¨|9ÿy’l„ý÷¯Ü/-.ô]q5‘¡E‡'æ'/¨Àà¶]\[=“<Ÿ¦CIdŽƒD{¢ùÊ`ö¤ª‰ú™R†‹®âÔØANÓ:œë!¦íõ1¹óhž¼ÚÀ+î@æ =Õ%ÔPM½Þyðê«å;Da¬:¹‘Žú ­‚sîÓàjúg²{säÉ1±ç™–ÒXó :øÀÒSÀÅeÅ"ÞɛĔ?qêŠ&êƒÓv ¦ºyðÀcPQöŽt5~ñù“B2vïy4 Ydåoé«©¥• XREõ-ÅU­ÒV/a*ÄøòŸÅÞ66 Z%^'®6L1xGëø¢TÈõódkiRÕ{×·®G[;!¶̈²{ O‡68ÛÉpÃ3‹Z§Ñ%_Š'ôì<õT®Ío]¶ÕiNC“e‡¤—?‡ýù/pµI3Ñk£žP]6¿»'ö}[†6Mqõ2!"Ñ ¯¯ž 'J„ñ1C4)Ÿ“Šód¨S¹¦·äAò_;ñzþkOäÔ†îZÐKûŽÂ²®ÈU¹O©W›ìŠËAk#=rêa?p¾Vuµ[5ÝåWe¯…þÀèÃÀU'«ó—Á×è¤ÑïáFÑW6¾³H¤'tpB²ÅPÚLºJVË )z¤.Ð2 Ž(PÜm¢Ùrì’u,J&¹å·XÂÖÐÖì`±³_/ìÙ´¦O'J•õЦ³|Í‚/å¯Ý¡ä˦.q%e .J:ÄÍݘÿ¶ÙãXJo”Ìk¼š«¸g¹ÆÓ&‚Ô3ë`×)I®9s85åIXëôÅt£d³á*ï-m[JsŸ1ZIRK#:uS껑u…+“kˆCB„·òK6fÁm]²Òà"œÞ™µÇdkJÐ*œ§M~™ib¦«€d’\Óæv¢F»íÞ•=¥6ÊþŒàЇ#dVæ½k¤}Þ5úû¸¢q°‘„“;Ûe_CÍÜoT}M¼š‡¾y0舟ßb1¥‹ ©¶³Î5š„ÀÙÅ®‰L•åö8>y_ùú9Ÿ§øÄ‹Y‘ÍCKHPpûþ99TŒWytÀ2ùÜwŸ^¯\gSYn¹ù@~aî*ð6Õ-­Ðâ\ aæN$hÑÃÞÒ’‚p‡Ñ8™ÈèlsÁôûS»sè{tG©™%erò×V:sý“& ú—5ça5¾ÔƋݳº$´4ˆòX^‰N0ÞCääyYHŽhMZê)Tåß¹«p_ߎ«êè^Þ,¸pö»ÙÄ·ÜgQV¶«Ð“ßEg+´,¢ˆ0€•7 žª[›ÖÕ9‘‡y¯A8hÔ£Âõ™xþ>€«åÍÔg¼ª¬ê¦ç7Z× Zlk¼K ®Ã>”åÝ1Ux ½aF|Ð:ÇÕö`÷‘< 4*¤{ÞÐø(®¤á£ö@ï@mTŽ}Ûµhzã=…e1u8‰j\Œó|µ¾Î}ßqÏ…~W²^‘^$Ét΂<—ÁÍöúÖLsÙÝ=ôû®D…ý¼ØÛm÷²XuŒåeàgeJ¦ª5N5øLRúùËâ—ªU`ºœ¾S±fR‹Çèt¢GH`ÿ5vŒDÎÔ{LF¿Ï|ßW6Hà›4ñÏËb™»ZóPÿhÖn·á¥0Œ².›}Ï6ÍûzF^˜˜Z7<¨Ã=9EØ¿  Ãi&Cšžˆ+,£¤2¿£ÔwŠWÝm»Û ²3?1-£YÏh*ŒA‚áGJïËéúò²~™ú¬OàLíN L¨Ć‘\™“gòNâžwÞûθòW·Óbm‰Œb­³¦®Ùv»å!c‘ã·ÚqËbœƒñKÕåÄÍ«’ëΚç+¨°ŽŠ¼Ì¾Ã_xèÀó¼¯ï«ª%mß|åwƒWN_¯P5"Š‹(”¥²¥“²µÔÉc—À”N¯ °ÔWZ{ß­ó¯¼Ñ¯¯&ýU<ñ\üÒbÒ«-¨…¬]uYd‡Øí»žpX^ñ,|žÄ6ÎP¬Œ¢—âõ<]À™q `%ÿø[ÿi¼ª8n¾&¼Éù«ü}ººŒÖˆÒ˜¤-K»˜îÛEâåJ*׈x#PJ<€±„&Ç`}¾SYÅÿì;ùý<諳•Ô¬e¬є¦v5_ïžÛ¤æŽ¡)´­LÉy¡nT)Ÿ"kÞ’6TÉ|{)ÈY6ÞÑé‡âÊÜÈ&d¦l‘S¿èÛ`c]ö꟫¿w&Z§ÂLŒü]~-ÏâkNNȧ’pa'a¼ÀÔé´€ºÁõ£pu†a°¨ž_^K÷tñ_{™î¥U’بb©ÈgˆÌ¡‰„¦Ð «À% uÓ¤˜/u/Ëü\Ñ]Œmâ¹×¾™¹ôÝòšð<)&¢¹ñé HA¤ÉÔ (âÊíj5å°„ P:Áÿ¤°ˆÊ°´r|‡§Ÿ˜ÑdØ“ÏïŠ[Âù·šµì!Í>hDÂ-`9áwúÓ À⠨˫¼*ÄMGb,«À`4bO³«}§=™»•ðóqµŠ§†Oà=L"¼!Uɨz '”®‚”ÕA #<°ùˆËR¤‚4’UöI‘Ëh(Y~ái ÓË©0wæ)ê ›Vùò~\QJãGõV妳ŒÙ<ö²=ù'$KésJ‹06±@‰lãñúÎSÄí"‰›â/#G½ñ(ôMWºšÅý¾ …SÄcžظ{¿®x`fvP¢½ÛD¤ôHXŠ„²Q©Ž hÏO „›“w¤ÊÇS«)úhh™4°£‚IÚ¼J_÷+’b kÅ;DýªñjwºryxZ›գ¸Êb4ìp¯+,"^ÍK¢iáñƒBœ¢! s–Šðé¥hŠ¢Q}—â¿M¼ [pt³XÈÅ;Ovr ÔÊ7­IUÀ1\ÀáN,ú‚Õ) öôŽÝË×_¹ñ·ê9‘þŠtîQw¬îžÁï‚+v€Î"aGR7X/á [X3“ˆÔ;ìà0Žã{Å t·!À-…$ø-X‘ŸÀR?0¶#îŠcaRû¥~G\9:˜£'›ná î;vádžŒìuÆÛHrÙv|Šh Ü h(ü‹rëL\>ûÝÿÝq%§*†‡ÕUìÿÀ|Í…€$yà‚yΉë5‚‘J%¡91Ÿ©m‡àÓMñ^ÏûÓâUuE=`…-«Ø[ íàjå{m# NdŒrën~b\]]íBŸÎb÷. w‚Ÿ=Þ½€Ïxý´‹»2ãÀȶIEND®B`‚ratproxy-1.58.orig/nlist.h0000640000764400076440000001505011023237633014731 0ustar iustyiusty/* ratproxy - naive dynamic list implementation -------------------------------------------- Multiple macros for handling several types of dynamic lists and strings. Author: Michal Zalewski Copyright 2007, 2008 by Google Inc. All Rights Reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ #ifndef _HAVE_NLIST_H #define _HAVE_NLIST_H #include "types.h" #define ALLOC_CHUNK 32 struct naive_list { _u8** v; _u32 c; }; #define ADD(list,val) do { \ struct naive_list* __list = &(list); \ if (!(__list->c % ALLOC_CHUNK)) { \ __list->v = realloc(__list->v,(2 + ALLOC_CHUNK + __list->c) * sizeof(_u8*)); \ if (!__list->v) fatal("out of memory"); \ } \ __list->v[__list->c++] = (val); \ __list->v[__list->c] = 0; \ } while (0) #define DYN_ADD(list,val) do { \ _u8* _s = strdup(val); \ if (!_s) fatal("out of memory"); \ ADD((list),_s); \ } while (0) #define FREE(list) do { \ struct naive_list* __list = &(list); \ if (__list->v) free(__list->v); \ __list->v = 0; \ __list->c = 0; \ } while (0); #define DYN_FREE(list) do { \ _u32 _i; \ struct naive_list* __list = &(list); \ for (_i=0;_i<__list->c;_i++) \ if (__list->v[_i]) free(__list->v[_i]); \ if (__list->v) free(__list->v); \ __list->v = 0; \ __list->c = 0; \ } while (0); struct naive_list2 { _u8 **v1, **v2; _u32 c; }; #define ADD2(list, val1, val2) do { \ struct naive_list2* __list = &(list); \ if (!(__list->c % ALLOC_CHUNK)) { \ __list->v1 = realloc(__list->v1,(2 + ALLOC_CHUNK + __list->c) * sizeof(_u8*)); \ __list->v2 = realloc(__list->v2,(2 + ALLOC_CHUNK + __list->c) * sizeof(_u8*)); \ if (!__list->v1 || !__list->v2) fatal("out of memory"); \ } \ __list->v1[__list->c] = (val1); \ __list->v2[__list->c++] = (val2); \ } while (0) #define DYN_ADD2(list,val1,val2) do { \ _u8 *_s1 = strdup(val1), *_s2 = strdup(val2); \ if (!_s1 || !_s2) fatal("out of memory"); \ ADD2((list),_s1,_s2); \ } while (0) #define FREE2(list) do { \ struct naive_list2* __list = &(list); \ if (__list->v1) free(__list->v1); \ if (__list->v2) free(__list->v2); \ __list->v1 = 0; \ __list->v2 = 0; \ __list->c = 0; \ } while (0); #define DYN_FREE2(list) do { \ _u32 _i; \ struct naive_list2* __list = &(list); \ for (_i=0;_i<__list->c;_i++) { \ if (__list->v1[_i]) free(__list->v1[_i]); \ if (__list->v2[_i]) free(__list->v2[_i]); \ } \ if (__list->v1) free(__list->v1); \ if (__list->v2) free(__list->v2); \ __list->v1 = 0; \ __list->v2 = 0; \ __list->c = 0; \ } while (0); /* A specialized structure for parameter handling. */ struct naive_list_p { _u8 **v1; /* Field name */ _u8 **v2; /* Field value */ _u8 **fn; /* Filename ("" if none) */ _u32 *l2; /* Field value length (0 - ASCIZ ) */ _u32 c; /* Field count */ }; #define ADDP(list, val1, val2, fnval) do { \ struct naive_list_p* __list = &(list); \ if (!(__list->c % ALLOC_CHUNK)) { \ __list->v1 = realloc(__list->v1,(2 + ALLOC_CHUNK + __list->c) * sizeof(_u8*)); \ __list->v2 = realloc(__list->v2,(2 + ALLOC_CHUNK + __list->c) * sizeof(_u8*)); \ __list->fn = realloc(__list->fn,(2 + ALLOC_CHUNK + __list->c) * sizeof(_u8*)); \ __list->l2 = realloc(__list->l2,(2 + ALLOC_CHUNK + __list->c) * sizeof(_u32)); \ if (!__list->v1 || !__list->v2 || !__list->fn || !__list->l2) fatal("out of memory"); \ } \ __list->v1[__list->c] = (val1); \ __list->v2[__list->c] = (val2); \ __list->fn[__list->c] = (fnval); \ __list->l2[__list->c++] = 0; \ } while (0) #define ADDP_RAWMEM(list, val1, val2, v2len, fnval) do { \ struct naive_list_p* __list = &(list); \ if (!(__list->c % ALLOC_CHUNK)) { \ __list->v1 = realloc(__list->v1,(2 + ALLOC_CHUNK + __list->c) * sizeof(_u8*)); \ __list->v2 = realloc(__list->v2,(2 + ALLOC_CHUNK + __list->c) * sizeof(_u8*)); \ __list->fn = realloc(__list->fn,(2 + ALLOC_CHUNK + __list->c) * sizeof(_u8*)); \ __list->l2 = realloc(__list->l2,(2 + ALLOC_CHUNK + __list->c) * sizeof(_u32)); \ if (!__list->v1 || !__list->v2 || !__list->fn || !__list->l2) fatal("out of memory"); \ } \ __list->v1[__list->c] = (val1); \ __list->v2[__list->c] = (val2); \ __list->fn[__list->c] = (fnval); \ __list->l2[__list->c++] = (v2len); \ } while (0) #define DYN_ADDP(list,val1,val2,fn) do { \ _u8 *_s1 = strdup(val1), *_s2 = strdup(val2), *_fn = strdup(fn); \ if (!_s1 || !_s2 || !_fn) fatal("out of memory"); \ ADDP((list),_s1,_s2,_fn); \ } while (0) #define DYN_ADDP_RAWMEM(list,val1,val2,v2len,fn) do { \ _u32 _l2 = (v2len); \ _u8 *_s1 = strdup(val1), *_s2 = malloc(_l2), *_fn = strdup(fn); \ if (!_s1 || !_s2 || !_fn) fatal("out of memory"); \ memcpy(_s2,(val2),_l2); \ _s2[_l2] = 0; \ ADDP_RAWMEM((list),_s1,_s2,_l2,_fn); \ } while (0) struct dyn_str { _u8* v; _u32 l; }; #define STR_FREE(buf) do { \ struct dyn_str* _str = &(buf); \ if (_str->v) free(_str->v); \ _str->v = 0; \ _str->l = 0; \ } while (0) #define STR_APPEND(buf,value) do { \ _u8* _data = (value); \ _u32 _len = strlen(_data); \ struct dyn_str* _str = &(buf); \ _str->v = realloc(_str->v,_str->l + _len + 1); \ if (!_str->v) fatal("out of memory"); \ memcpy(_str->v + _str->l, _data, _len); \ _str->l += _len; \ _str->v[_str->l] = 0; \ } while (0) #define STR_APPEND_RAWMEM(buf,value,vlen) do { \ _u8* _data = (value); \ _u32 _len = (vlen); \ struct dyn_str* _str = &(buf); \ _str->v = realloc(_str->v,_str->l + _len + 1); \ if (!_str->v) fatal("out of memory"); \ memcpy(_str->v + _str->l, _data, _len); \ _str->l += _len; \ _str->v[_str->l] = 0; \ } while (0) #define STR_APPEND_CHAR(buf,value) do { \ _u8 _data = (value); \ struct dyn_str* _str = &(buf); \ _str->v = realloc(_str->v,_str->l + 2); \ if (!_str->v) fatal("out of memory"); \ _str->v[_str->l++] = _data; \ _str->v[_str->l] = 0; \ } while (0) #endif /* ! _HAVE_NLIST_H */ ratproxy-1.58.orig/mime.h0000640000764400076440000000165511023056701014530 0ustar iustyiusty/* ratproxy - MIME detection ------------------------- Author: Michal Zalewski Copyright 2007, 2008 by Google Inc. All Rights Reserved. Copyright 2007, 2008 by Google Inc. All Rights Reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ #ifndef _HAVE_MIME_H #define _HAVE_MIME_H #include "types.h" #include "http.h" void detect_mime(struct http_response* r); #endif /* !_HAVE_MIME_H */ ratproxy-1.58.orig/mime.c0000640000764400076440000003214311023471114014516 0ustar iustyiusty/* ratproxy - MIME detection ------------------------- MIME content sniffing routines. This code tries to figure out what is actually being served, regardless of what HTTP headers say. Author: Michal Zalewski Copyright 2007, 2008 by Google Inc. All Rights Reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include "config.h" #include "types.h" #include "debug.h" #include "nlist.h" #include "http.h" #include "mime.h" #include "string-inl.h" /* Check for JSON prologues... */ static _u8 is_json_safe_mime(_u8* str) { _u32 i = 0; /* JSON prologues of more than 1 characters are "authoritative" and override further content sniffing. */ while (json_safe[i]) { if (json_safe[i][1] && !strncmp(str,json_safe[i],strlen(json_safe[i]))) return 1; i++; } return 0; } /* Attempt MIME type detection for formats that are likely to be served by a modern web application based on payload signature matching. */ void detect_mime(struct http_response* r) { _u32 i, max; _u8 text = 1; _u8 sniffbuf[SNIFFBUF + 1]; _u8* xxx; /* TODO: Add more popular formats. This is oriented toward common web 2.0 technologies at the moment. */ if (!r->payload_len) return; if (r->payload_len > SNIFFBUF) max = SNIFFBUF; else max = r->payload_len; memcpy(sniffbuf,r->payload,max); sniffbuf[max] = 0; /* Is this a plain-text file? */ for (i=0;iis_text = 1; /* First, some files with known, fixed signatures. */ if (!strncmp(sniffbuf,"%!PS",4)) { r->sniffed_mime = "application/postscript"; return; } if (!strncmp(sniffbuf,"{\\rtf",5)) { r->sniffed_mime = "text/rtf"; return; } /* Try to detect Javascript - this is a bit tricky, because JSON snippets can have minimal syntax, and CSS uses a notation vaguely resembling Javascript. */ /* JSON breaker prefixes automatically qualify content as JS */ if (is_json_safe_mime(sniffbuf)) goto got_javascript; for (i=0;isniffed_mime = "text/css"; return; } if (isalpha(sniffbuf[i])) got_alpha = 1; if (sniffbuf[i] == '{') { got_bracket = 1; got_alpha_before = got_alpha; } /* { "foo" is very JSONish. */ if (!got_alpha && got_bracket && sniffbuf[i] == '"') goto got_javascript; /* { foo: 1 is JSONish too. */ if (!got_alpha_before && got_alpha && got_bracket && sniffbuf[i] == ':') goto got_javascript; /* And finally, if =, ( or JS keyword is encountered before <, assume JS. */ if (sniffbuf[i] == '=' || sniffbuf[i] == '(' || sniffbuf[i] == '[' || !strncmp(sniffbuf + i, "function ",9) || !strncmp(sniffbuf + i, "throw ",6) || !strncmp(sniffbuf + i, "var ",4)) { got_javascript: r->sniffed_mime = "application/x-javascript"; /* RFC 4329 lists no fewer than 16 variations of Javascript MIME type. Not all of them are common in the wild, but all are roughly equivalent security-wise, so let's be lenient. */ if (r->mime_type) { if (!strcasecmp(r->mime_type,"text/javascript")) r->sniffed_mime = "text/javascript"; else if (!strcasecmp(r->mime_type,"application/javascript")) r->sniffed_mime = "application_javascript"; else if (!strcasecmp(r->mime_type,"application/json")) r->sniffed_mime = "application/json"; } return; } } /* OpenSearch */ if (strstr(sniffbuf,"sniffed_mime = "application/opensearchdescription+xml"; return; } /* Try to detect RSS */ if (strstr(sniffbuf,"sniffed_mime = "application/rss+xml"; return; } /* Try to detect Atom */ if (strstr(sniffbuf,"")) { r->sniffed_mime = "application/atom+xml"; return; } /* Try to detect WML */ if (rp_strcasestr(sniffbuf,"sniffed_mime = "text/vnd.wap.wml"; return; } /* Try to detect - just promote the new, fancy MIME type for security reasons. */ if (rp_strcasestr(sniffbuf,"")) { r->sniffed_mime = "text/x-cross-domain-policy"; return; } /* Try to detect XHTML, SVG, or generic XML of some other type. */ if (rp_strcasestr(sniffbuf,"sniffed_mime = "image/svg+xml"; else if (rp_strcasestr(sniffbuf,"sniffed_mime = "application/xhtml+xml"; else { if (r->mime_type && !strcasecmp(r->mime_type,"text/xml")) r->sniffed_mime = "text/xml"; else r->sniffed_mime = "application/xml"; } return; } /* Try to detect generic HTML */ if (rp_strcasestr(sniffbuf,"sniffed_mime = "text/html"; return; } /* Last resort for XML */ xxx = sniffbuf; while (isspace(*xxx)) xxx++; if (rp_strcasestr(xxx,"") || strstr(xxx,"/ >")))) { if (r->mime_type && !strcasecmp(r->mime_type,"text/xml")) r->sniffed_mime = "text/xml"; else r->sniffed_mime = "application/xml"; } /* Oh well, at least it seems to be text. */ r->sniffed_mime = "text/plain"; } else { /* This is considerably less messy - binary signatures for some non-text files. */ if (sniffbuf[0] == 0xFF && sniffbuf[1] == 0xD8 && sniffbuf[2] == 0xFF) { r->sniffed_mime = "image/jpeg"; /* Progressive JPEG; recognized by MSIE. */ if (r->mime_type && !strcasecmp(r->mime_type,"image/pjpeg")) r->sniffed_mime = "image/pjpeg"; return; } if (sniffbuf[0] == 'G' && sniffbuf[1] == 'I' && sniffbuf[2] == 'F' && sniffbuf[3] == '8') { r->sniffed_mime = "image/gif"; return; } if (sniffbuf[0] == 0x89 && sniffbuf[1] == 'P' && sniffbuf[2] == 'N' && sniffbuf[3] == 'G') { r->sniffed_mime = "image/png"; return; } if (sniffbuf[0] == 'B' && sniffbuf[1] == 'M') { r->sniffed_mime = "image/x-ms-bmp"; return; } if (sniffbuf[0] == 'I' && sniffbuf[1] == 'I' && sniffbuf[2] == 42) { r->sniffed_mime = "image/tiff"; return; } if (sniffbuf[0] == 0xFF && sniffbuf[1] == 0xFB) { r->sniffed_mime = "audio/mpeg"; return; } if (sniffbuf[0] == 0x00 && sniffbuf[1] == 0x00 && sniffbuf[2] == 0x01 && (sniffbuf[3] & 0xF0) == 0xB0) { r->sniffed_mime = "video/mpeg"; return; } if (sniffbuf[0] == 'O' && sniffbuf[1] == 'g' && sniffbuf[2] == 'g' && sniffbuf[3] == 'S') { r->sniffed_mime = "application/ogg"; return; } if (sniffbuf[0] == 'R' && sniffbuf[1] == 'I' && sniffbuf[2] == 'F' && sniffbuf[3] == 'F') { if (sniffbuf[8] == 'A') { if (sniffbuf[9] == 'C') { r->sniffed_mime = "application/x-navi-animation"; } else { r->sniffed_mime = "video/avi"; } } else r->sniffed_mime = "audio/wav"; return; } if (sniffbuf[0] == 0x28 && sniffbuf[1] == 'R' && sniffbuf[2] == 'M' && sniffbuf[3] == 'F') { r->sniffed_mime = "audio/x-realaudio"; return; } if (sniffbuf[0] == 0x30 && sniffbuf[1] == 0x26 && sniffbuf[2] == 0xB2) { r->sniffed_mime = "video/x-ms-asf"; return; } if (!strncmp(sniffbuf+4,"free",4) || !strncmp(sniffbuf+4,"mdat",4) || !strncmp(sniffbuf+4,"wide",4) || !strncmp(sniffbuf+4,"pnot",4) || !strncmp(sniffbuf+4,"skip",4) || !strncmp(sniffbuf+4,"moov",4)) { r->sniffed_mime = "video/quicktime"; return; } if ((sniffbuf[0] == 0x46 || sniffbuf[0] == 0x43) && sniffbuf[1] == 0x57 && sniffbuf[2] == 0x53) { r->sniffed_mime = "application/x-shockwave-flash"; return; } if (sniffbuf[0] == 0x46 && sniffbuf[1] == 0x4C && sniffbuf[2] == 0x56) { /* Again, multiple valid options in use; be polite. */ if (r->mime_type && !strcasecmp(r->mime_type,"video/flv")) r->sniffed_mime = "video/flv"; else r->sniffed_mime = "video/x-flv"; return; } if (r->payload_len > 3 && sniffbuf[0] == 0 && sniffbuf[1] == 0 && sniffbuf[2] < 3 && sniffbuf[3] == 0) { /* Be polite again. */ if (r->mime_type && !strcasecmp(r->mime_type,"image/x-icon")) r->sniffed_mime = "image/x-icon"; else if (r->mime_type && !strcasecmp(r->mime_type,"image/bmp")) r->sniffed_mime = "image/bmp"; else r->sniffed_mime = "image/vnd.microsoft.icon"; return; } if (sniffbuf[0] == '%' && sniffbuf[1] == 'P' && sniffbuf[2] == 'D' && sniffbuf[3] == 'F') { r->sniffed_mime = "application/pdf"; return; } if (sniffbuf[0] == 'P' && sniffbuf[1] == 'K' && sniffbuf[2] < 6 && sniffbuf[3] < 7) { if (rp_memmem(r->payload,r->payload_len,"META-INF/",9)) r->sniffed_mime = "application/java-archive"; else r->sniffed_mime = "application/zip"; return; } if (sniffbuf[0] == 0xCA && sniffbuf[1] == 0xFE && sniffbuf[2] == 0xBA && sniffbuf[3] == 0xBE) { r->sniffed_mime = "application/java-vm"; return; } /* Microsoft office is kind-of fuzzy. */ if (sniffbuf[0] == 0xD0 && sniffbuf[1] == 0xCF && sniffbuf[2] == 0x11 && sniffbuf[3] == 0xE0 && r->payload_len > 512) { _u8 c = r->payload[512]; switch (c) { case 0xEC: r->sniffed_mime = "application/msword"; break; case 0xFD: case 0x09: r->sniffed_mime = "application/vnd.ms-excel"; break; case 0x00: case 0x0F: case 0xA0: r->sniffed_mime = "application/vnd.ms-powerpoint"; break; } return; } /* If we have no idea what it is, just leave it NULL. */ } } ratproxy-1.58.orig/messages.list0000640000764400076440000002376111164366757016163 0ustar iustyiusty~All visited URLs~Complete list of all visited URLs, regardless of their apparent significance to the security of tested application. ~HTTP errors~Requests that unexpectedly produced error responses. Some entries on this list may warrant further investigation as indicators of security issues or programming errors. ~MIME type missing~Pages with no Content-Type header present. Browser-side content sniffing may be triggered in such a scenario, and potentially lead to cross-site scripting if any part of the file is user-controlled. ~MIME type set to text/plain~Pages with Content-Type header set to text/plain. Content sniffing in Internet Explorer may be triggered in such a scenario, and potentially lead to cross-site scripting if any part of the document is user-controlled. ~MIME type mismatch on renderable file~Text documents that seem to have a poorly chosen Content-Type value. Even slight mismatches may trigger content sniffing in Internet Explorer, and potentially lead to cross-site scripting if any part of the file is user-controlled. ~MIME type mismatch on image file~Images that seem to have incorrect MIME types set. Even slight mismatch may trigger content-sniffing in Internet Explorer, and lead to cross-site scripting if the image is user-supplied. ~Generic MIME type used~Files served with Content-Type: application/octet-stream. This is correct for raw binary data resources, but may lead to cross-site scripting if any part of the file is user-supplied. ~MIME type mismatch on binary file~Binary files with poorly chosen Content-Type data. Certain mismatches may trigger content sniffing, and potentially lead to cross-site scripting if the file is user-supplied. ~Dynamic Javascript for direct inclusion~Server-generated, authenticated Javascript apparently structured for <SCRIPT SRC=...> or eval(...) consumption. If the code reveals any sensitive user data and lacks XSRF defenses, privacy breaches may occur. ~Bad or no charset declared for renderable file~Text documents with missing, mistyped, or obscure character sets (see config.h). For some values, UTF-7 and other types of character set sniffing in Internet Explorer may occur if any part of the file is user-controlled. ~Ambiguous HTTP content headers~Files with duplicate or contradictory HTTP headers or HTTP-EQUIV fields. In some cases, this may confuse browsers and produce unexpected content processing results. ~Misstated Content-Length~Resources with Content-Length declared by the server seemingly different from the amount of data actually received. In some cases, this may lead to HTTP response splitting attacks. ~Inline PNG image~PNG images with no Content-Disposition: attachment header. In Internet Explorer 6, this may trigger content sniffing and potentially lead to cross-site scripting flaws if the image is user-supplied. ~GET query with no XSRF protection~Parameter-accepting, authenticated GET requests that lack security tokens. Most GET requests do not change application state, but ones that do might be vulnerable to cross-site request forgery attacks. ~POST query with no XSRF protection~Parameter-accepting POST requests that lack security tokens. Some POST requests change application state, and may be vulnerable to cross-site request forgery attacks. ~HTTP redirector~Requests that seem to redirect to query-specified URLs via HTTP headers. Cross-site scripting attacks in less common browsers, as well as undesirable phishing-related abuse, might be possible if URLs are not properly validated. ~HTML META redirector~Requests that seem to redirect to user-specified URLs via META HTTP-EQUIV directives. Cross-site scripting attacks, as well as undesirable phishing-related abuse, might be possible if URLs are not properly validated. ~Referer may leak session tokens~Outgoing requests to non-audited sites that include Referer headers with non-trivial identifiers. In some cases, this may reveal user- or application-sensitive data to third parties. ~Direct markup echoed back~Pages where HTML or XML markup appears to be copied over from query parameters to a page. This is often a sign of XSS or XML injection flaws, unless proper sanitization takes place. ~XSS candidates~Pages where non-trivial query parameters appear to be echoed back on the page. Most or all of these resources might be safe - but they constitute prime candidates for further manual or automated XSS vulnerability testing. ~Request splitting candidates~Pages where non-trivial query parameters appear to be echoed back in HTTP headers. This does not imply a vulnerability, but these resources constitute high-risk candidates for further response splitting testing. ~XSS candidates (script)~Pages where non-trivial query parameters appear to be echoed back inside a script. This does not imply a vulnerability, but these resources are prime candidates for further code injection testing. ~SQL code in query parameters~Pages where SQL code appears to be accepted in query parameters, and is not echoed back. Unless the query was explicitly entered by the user, this might be a sign of potential SQL injection flaws. ~Javascript code echoed back~Pages where what appears to be Javascript code is copied over from query parameters to a page. Unless code snippets were explicitly entered by the user, this might be a sign of code injection flaws. ~Java method call in query parameters~Pages where Java-style class paths seem to appear directly in query parameters. Unless these paths were explicitly entered by the user, this might be a sign of certain vulnerabilities. ~File name in query parameters~Pages where values resembling file names are passed in query parameters, and not echoed back. Although this does not imply a vulnerability, these locations are prime candidates for further directory traversal testing. Note that some host names in parameters may trigger false positives here. ~File path in query parameters~Pages where values resembling file paths are passed in query parameters, and not echoed back. This is not necessarily a vulnerability, but constitutes a high-risk target for directory traversal testing. ~All Flash applications~Full list of Flash documents detected on the server. Many Flash files produced with automated tools are vulnerable to cross-site scripting flaws, and should be inspected for these patterns. ~File upload forms~Forms that accept file inputs. Although this is not a vulnerability, these resources should be carefully inspected for request forgery problems, filename handling issues, and related issues. ~Directory indexes~Pages that contain patterns consistent with default directory listings. These resources should be investigated for possible disclosure of sensitive data. ~Risky Javascript code~Pages that seem to contain potentially dangerous or discouraged Javascript statements. These statements are particularly likely to open up security vulnerabilities on the page, and as such, the code should be carefully analyzed. ~External code inclusion~Pages that seem to include scripts or stylesheets from external domains. If these domains are not trusted or are susceptible to compromise, this behavior may render the application vulnerable to attacks. ~Cross-domain POST requests~Pages that appear to receive cross-domain POST requests. This is commonly used for mechanism such as single sign-on. Since such schemes may enjoy only a limited cookie protection, the functionality should be surveyed for request forgery flaws. ~Markup in dynamic Javascript~Code that resembles JSON responses or other dynamic code snippets, and quotes non-escaped HTML. If this rendered markup is attacker-controlled, content sniffing in Internet Explorer may potentially kick in and trigger XSS flaws, regardless of MIME type used. ~All POST requests~Complete list of all POST forms encountered, regardless of their apparent significance to the security of tested application. ~Cookie issuer with no XSRF protection~Pages that accept parameters and issue new HTTP cookies, but miss security tokens. Session fixation or other attacks might be possible if the cookie stores important, query-dependent user data. ~All cookie setting URLs~Complete list of all cookie-issuing URLs encountered, regardless of their apparent significance to the security of tested application. ~Bad caching headers~Pages that set cookies or require authentication, but have HTTP headers that may, in some scenarios, lead to proxy-level document caching. Depending on runtime settings, this may also include subtle HTTP/1.1 and HTTP/1.0 intent mismatches (such as Cache-Control: private with no Expires header). ~Suspicious parameter passing scheme~Parameter names look like OGNL expressions, PHP global variables, or other mechanisms to directly affect the state of server-side code. Some of such schemes could lead to data injection unless proper security measures are in place, and should be carefully evaluated. ~Confirmed XSS vectors~Pages where query parameters are echoed back on a renderable page, and no proper escaping or charset declarations seems to take place, as verified by active testing. ~References to external active content~Active content types (such as HTML, Flash, or Java) that seems to be included from or referenced in third-party domains. These resources should be further evaluated to determine their purpose and the impact on site security, if any. ~Potential mixed content~Runtime settings indicate that the application should use HTTPS exclusively, but HTTP-based requests in the tested domain were observed. These may expose the application to man-in-the-middle attacks, particularly if the content is active (scripts, HTML, stylesheets, etc). ~Cross-domain access policy~Resources that specify cross-domain access policies for Flash or Silverlight. These should be examined for overly permissive rules that could open up XSS vectors. ratproxy-1.58.orig/keyfile.pem0000640000764400076440000000341311023320155015552 0ustar iustyiusty-----BEGIN CERTIFICATE----- MIICdzCCAeCgAwIBAgIJALYsu87Jst7lMA0GCSqGSIb3DQEBBQUAMDIxJDAiBgNV BAoTG1JhdHByb3h5IChNSVRNIGNlcnRpZmljYXRlKTEKMAgGA1UEAxQBKjAeFw0w ODA2MDkyMTI3NDJaFw0yMjAyMTYyMTI3NDJaMDIxJDAiBgNVBAoTG1JhdHByb3h5 IChNSVRNIGNlcnRpZmljYXRlKTEKMAgGA1UEAxQBKjCBnzANBgkqhkiG9w0BAQEF AAOBjQAwgYkCgYEArky1aCVlM5NDO5624BHsRvq1OmqIkSGw7GfzlD7qo1THYcB2 azZjhMv82PBSfgDPrh+fkzy+xRidQ7FUiTgXb2b3GQix0e0EyQEni5CCFMo7wkU8 TSSaETO6pWLNk4nHxvWfCwsLLvcCjato52T/nR7+yTyAfNtLu/199snmD50CAwEA AaOBlDCBkTAdBgNVHQ4EFgQUif1wzTOqwmli7LevZoneT0CSXpYwYgYDVR0jBFsw WYAUif1wzTOqwmli7LevZoneT0CSXpahNqQ0MDIxJDAiBgNVBAoTG1JhdHByb3h5 IChNSVRNIGNlcnRpZmljYXRlKTEKMAgGA1UEAxQBKoIJALYsu87Jst7lMAwGA1Ud EwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADgYEAjE6iLPE5w46FMMdAfdofEIqTsH6Z a2LiNTI5c8kS1T3KV0m+JinAjgokJh5lh1KqLuj7r7BBctN76zKfi0G8CtkZVA34 MCGVNFTJZKYLpp6mrqjdJTsUd65d55YIc2Phj+bNFZQnQ37mhjO0X6utm89dFhVU JFrtgHylmjbImu8= -----END CERTIFICATE----- -----BEGIN RSA PRIVATE KEY----- MIICWwIBAAKBgQCuTLVoJWUzk0M7nrbgEexG+rU6aoiRIbDsZ/OUPuqjVMdhwHZr NmOEy/zY8FJ+AM+uH5+TPL7FGJ1DsVSJOBdvZvcZCLHR7QTJASeLkIIUyjvCRTxN JJoRM7qlYs2TicfG9Z8LCwsu9wKNq2jnZP+dHv7JPIB820u7/X32yeYPnQIDAQAB AoGACLBUPrvWfqqxqFAyJ5tdHvCyhhX3dtyqGC7aaqJ0Se4Y/lt8y71rWpxcn2fj hNp/f9udtdZKYELo3A4D+88rA9Kbcig0JZ7dkhTh84jouzg2E8zAISvC8fEIsHms 3+vjZ/ZX9mGXXuYhFuVXuUWqKPJ8Rb82uI/z6f+dSXQouLUCQQDVXn+rKezBUsOa iZIICHaB354McAY7fzhjvTDUxLy7znaJ2ZZkLYY9bgDwjzQhemTZ1KB8b/DuInz0 gAYnzZzjAkEA0R/dpNBkMLIGdl1fuYHWACruUvm7SGF40usUTQwVWppuxAKE6Dyr qdS5XGD6ilLJa2MHpP52j1PgpiiP5x3JfwJATnPlm2jZ7adh1pOYxy1dbZlsQoR6 Niwr7rhkmQcRojhi64K+wmzeu/2TiOAOufSH2nRM4hRC0TyLF1dva/k1IwJAaeuD 7biHJork7wq4M1NpusgD0g8fJrgH5Hyg2a1nG27g73J/MsmYAPr3r6yG+YyY7EVK V+1yy4GmZUJiMKNLrQJARbP1DP/bgWTpHYTRrHHwitr1vxuMFBQ/BVp1rWOGgI06 DxnfkFWCpkF2OdcMGwLH7yaavGOhFI0TyQA/Blkagw== -----END RSA PRIVATE KEY----- ratproxy-1.58.orig/http.h0000640000764400076440000000736311023055132014557 0ustar iustyiusty/* ratproxy - HTTP request handling -------------------------------- Author: Michal Zalewski Copyright 2007, 2008 by Google Inc. All Rights Reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ #ifndef _HAVE_HTTP_H #define _HAVE_HTTP_H #include "types.h" #include "nlist.h" struct http_request { _u8* method; /* HTTP method */ _u8* host; /* Target host */ _u32 port; /* Target TCP port */ _u8* path; /* Target URL path */ _u8* ext; /* File extension */ _u8* query; /* Query string */ struct naive_list2 h; /* Header set */ _u8 is_connect; /* CONNECT method? */ _u8 from_ssl; /* SSL decapsulation? */ _u8 xsrf_safe; /* Has anti-XSRF token? */ _u8 authsub; /* Uses authsub? */ _u8* referer; /* 'Referer' header */ _u8* ref_host; /* Referer host, if any */ _u8 multipart; /* Multipart request? */ _u8 non_param; /* Non-param payload */ _u8* use_boundary; /* Multipart boundary */ _u32 ppar_bound; /* Query/payload delim */ _u32 payload_len; /* POST payload length */ _u8* payload; /* POST payload data */ struct naive_list2 cookies; /* Sent cookies */ struct naive_list_p p; /* Decoded parameters */ }; #define INTENT_NONE 0 #define INTENT_PRIV 1 #define INTENT_PUB 2 struct http_response { _u32 code; /* HTTP return code */ _u8* ext; /* File extension */ struct naive_list2 h; /* Header set */ _u8* mime_type; /* Declared MIME type */ _u8* charset; /* Declared charset */ _u8* sniffed_mime; /* Detected MIME type */ _u8* location; /* Location: update */ _u8 ex10intent; /* Expires intent */ _u8 pr10intent; /* Pragma intent */ _u8 cc11intent; /* Cache-Control intent */ _u8 has_multiple; /* Has duplicate fields */ _u8 has_badclen; /* Bad content length? */ _u8 is_attach; /* Attachment? */ _u8 is_text; /* Text document? */ _u8 bad_cset; /* Mistyped charset? */ struct naive_list2 cookies; /* Set cookies */ _u32 payload_len; /* Response body length */ _u8* payload; /* Response body data */ _u64 cksum; /* Payload checksum */ }; struct http_request* collect_request(FILE* client,_u8* ssl_host,_u32 ssl_port); FILE* open_server_complete(FILE* client, struct http_request* r); struct http_response* send_request(FILE* client, FILE* server, struct http_request* r, _u8 strip_state); void send_response(FILE* client, struct http_response* r); void checksum_response(struct http_response* r); void detect_charset(struct http_response* r); void parse_urlencoded(struct naive_list_p* p, _u8* string); void parse_multipart(struct naive_list_p* p, _u8* string, _u32 slen); _u8 contains_token(_u8* name, _u8* val); _u8* S(_u8* string, _u8 nl); _u8* stringify_payload(struct http_request* r); void reconstruct_request(struct http_request* r); #endif /* !_HAVE_HTTP_H */ ratproxy-1.58.orig/http.c0000640000764400076440000010520611202621115014544 0ustar iustyiusty/* ratproxy - HTTP request handling -------------------------------- The following routines take care of HTTP request handling, parsing, and error reporting. Note that this code is one-shot, process is terminated when request handling is done - and as such, we rely on the OS to do garbage collection. Author: Michal Zalewski Copyright 2007, 2008 by Google Inc. All Rights Reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "config.h" #include "types.h" #include "debug.h" #include "nlist.h" #include "http.h" #include "ssl.h" #include "string-inl.h" extern _u8* use_proxy; /* Runtime setting exports from ratproxy. */ extern _u32 proxy_port; extern _u8 use_len; static _u8 srv_buf[MAXLINE], /* libc IO buffers */ cli_buf[MAXLINE]; /* Read a single line of HTTP headers, strip whitespaces */ static _u8* grab_line(FILE* where) { static _u8 inbuf[MAXLINE]; _u32 l; if (!fgets(inbuf,MAXLINE,where)) return 0; l = strlen(inbuf); /* Excessive line length is bad, let's bail out. */ if (l == MAXLINE-1) return 0; while (l && isspace(inbuf[l-1])) inbuf[--l] = 0; return inbuf; } /* Return a generic HTTP error message, end current process. Note that this function should not handle user-controlled data. */ static void http_error(FILE* client, _u8* message,_u8 sink) { if (client) { _u8* l; if (sink) while ((l=grab_line(client)) && l[0]); fprintf(client, "HTTP/1.0 500 %s\n" "Content-type: text/html\n\n" "\n" "The proxy is unable to process your request.\n" "

%s.

\n", message, message); fflush(client); fclose(client); } debug("[!] WARNING: %s.\n", message); exit(0); } static _u8* BASE16 = "0123456789ABCDEF"; /* Decode URL-encoded parameter string */ void parse_urlencoded(struct naive_list_p* p, _u8* string) { _u8 val_now = 0; _u8 name[MAXLINE+1], val[MAXLINE+1]; _u32 nlen = 0, vlen = 0; name[0] = 0; val[0] = 0; do { _u8 dec = 0; switch (*string) { case '+': dec = ' '; break; case '=': val_now = 1; break; case '%': { _u8 *a, *b; /* Parse %nn code, if valid; default to '?nn' if not, replace with ? if \0. */ if (!string[1] || !string[2] || !(a=strchr(BASE16,toupper(string[1]))) || !(b=strchr(BASE16,toupper(string[2])))) { dec = '?'; break; } dec = (a-BASE16) * 16 + (b-BASE16); string += 2; if (!dec) dec = '?'; break; } case '&': case 0: /* Handle parameter terminator; note that we also iterate over \0 because of loop condition placement. */ if (nlen) { name[nlen] = 0; val[vlen] = 0; DYN_ADDP(*p,name,val,""); } val_now = 0; nlen = 0; vlen = 0; break; default: if (!(dec=*string)) dec = '?'; } /* Append decoded char, if any, to field name or value as needed. */ if (dec) { if (!val_now) { if (nlen < MAXLINE) name[nlen++] = dec; } else { if (vlen < MAXLINE) val[vlen++] = dec; } } } while (*(string++)); } /* Read a line of multipart data from a linear buffer, advance buffer pointer. */ static _u8* get_multipart_line(_u8** buf) { static _u8* retbuf; _u8* x; _u32 cnt; if (retbuf) free(retbuf); /* We assume \r\n formatting here, which is RFC-mandated and implemtned by well-behaved browsers. */ x = strchr(*buf,'\r'); if (!x || x[1] != '\n') { _u32 l = strlen(*buf); retbuf = malloc(l + 1); if (!retbuf) fatal("out of memory"); strcpy(retbuf,*buf); *buf += l; return retbuf; } cnt = x - *buf; retbuf = malloc(cnt + 1); if (!retbuf) fatal("out of memory"); memcpy(retbuf,*buf,cnt); retbuf[cnt] = 0; *buf += cnt + 2; return retbuf; } /* Collect multipart data from a reasonably well-behaved browser. This routine makes multiple assumptions that might be not true for maliciously formatted data, but we do not strive to serve such requests well. */ void parse_multipart(struct naive_list_p* p, _u8* string, _u32 slen) { _u8* field, *fname; _u8* endptr = string + slen; do { _u8 *l, *end, *c; field = 0; fname = 0; /* Skip boundary */ l = get_multipart_line(&string); if (l[0] != '-' || l[1] != '-') return; /* Sink headers, but grab field name if any */ while ((l = get_multipart_line(&string)) && l[0]) { if (!strncasecmp(l,"Content-Disposition:",20)) { /* Grab field name. */ _u8* f = rp_strcasestr(l,"; name=\""); if (!f) continue; f += 7; c = strchr(++f,'"'); if (!c) continue; *c = 0; field = strdup(f); if (!field) fatal("out of memory"); /* Grab file name, if any. */ f = rp_strcasestr(c + 1,"; filename=\""); if (!f) continue; f += 11; c = strchr(++f,'"'); if (!c) continue; *c = 0; fname = strdup(f); if (!fname) fatal("out of memory"); } } end = rp_memmem(string,endptr - string, "\r\n--", 4); if (!end) return; if (field) DYN_ADDP_RAWMEM(*p,field,string,end-string,fname ? fname : (_u8*)""); string = end + 2; } while (1); } #define BASE64 "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ+/_-" /* Looks for what could pass for a reasonably robust session token or XSRF protection. */ _u8 contains_token(_u8* name, _u8* value) { _u32 run16 = 0, run16_num = 0, run64 = 0, run64_true = 0, run64_num = 0, run64_up = 0, run64_low = 0; _u8* st = 0; static _u32 tmin,tmax; _u32 fno = 0; if (!tmin) { tmin = time(0); tmax = tmin + (60 * 60 * 24 * 30); /* One month forward */ tmin -= (60 * 60 * 24 * 365 * 5); /* Five years back */ } /* Known bad field names - return 0. */ fno = 0; while (no_xsrf_fields[fno]) { if (no_xsrf_fields[fno][0] == '=') { if (!strcasecmp(name,no_xsrf_fields[fno] + 1)) return 0; } else { if (rp_strcasestr(name,no_xsrf_fields[fno])) return 0; } fno++; } /* Known safe field names - return 1. */ fno = 0; while (xsrf_fields[fno]) { if (xsrf_fields[fno][0] == '=') { if (!strcasecmp(name,xsrf_fields[fno] + 1)) return 1; } else { if (rp_strcasestr(name,xsrf_fields[fno])) return 1; } fno++; } /* URLs are not anti-XSRF tokens, no matter how random they look. */ if (!strncmp(value,"http",4)) return 0; /* Iterate over value data, compute base16 / base64 runs, collect basic character disttributin data, rule out patterns such as unix time, and make the call. */ do { if (*value && strchr(BASE16,toupper(*value))) { run16++; if (isdigit(*value)) run16_num++; } else { if (run16 >= XSRF_B16_MIN && run16 <= XSRF_B16_MAX && run16_num >= XSRF_B16_NUM) { _u8 tmp[5]; _u32 val; strncpy(tmp,st,4); tmp[4] = 0; val = atoi(tmp); if ((val < tmin / 1000000 || val > tmax / 1000000) && (st[0] != st[1] || st[0] != st[2])) return 1; } run16 = 0; run16_num = 0; } if (*value && strchr(BASE64,toupper(*value))) { if (!isalpha(*value)) run64_num++; if (isupper(*value)) run64_up++; if (islower(*value)) run64_low++; if (!run16) run64_true = 1; if (!run64) st = value; run64++; } else { if (run64 >= XSRF_B64_MIN && run64 <= XSRF_B64_MAX && ((run64_num >= XSRF_B64_NUM && run64_up >= XSRF_B64_CASE && run64_low >= XSRF_B64_CASE) || (run64_num >= XSRF_B64_NUM2)) && run64_true) if (st[0] != st[1] || st[0] != st[2]) return 1; run64 = 0; run64_num = 0; run64_up = 0; run64_low = 0; run64_true = 0; st = 0; } } while (*(value++)); return 0; } /* Try to parse cookie header values. */ static void parse_cookies(_u8* str, struct naive_list2* c) { _u8 name[128], val[128]; /* Iterate over cookies. We ignore cookies over 128 bytes for name / value, and "special" values such as expiration date, version, etc. */ while (str) { while (isspace(*str)) str++; if (sscanf(str,"%127[^;=]=%127[^;]",name,val) == 2) { if (strcasecmp(name,"expires") && strcasecmp(name,"comment") && strcasecmp(name,"version") && strcasecmp(name,"max-age") && strcasecmp(name,"path") && strcasecmp(name,"domain") && name[0] != '$') DYN_ADD2(*c,name,val); } str = strchr(str + 1 ,';'); if (str) str++; } } /* Process the entire HTTP request, parse fields, and extract some preliminary signals. */ struct http_request* collect_request(FILE* client,_u8* ssl_host, _u32 ssl_port) { struct http_request* ret; _u8 *line, *x; _u32 i; /* Begin carefully - on CONNECT requests, we do not want to read more than absolutely necessary. As soon as non-CONNECT is confirmed, we switch to proper buffering. */ setvbuf(client, cli_buf, _IONBF, 0); ret = calloc(1, sizeof(struct http_request)); if (!ret) fatal("out of memory"); line = grab_line(client); if (!line || !line[0]) exit(0); x = strchr(line,' '); if (!x || x == line) http_error(client, "URL address missing or malformed request",1); *(x++) = 0; ret->method = strdup(line); if (!ret->method) fatal("out of memory"); if (strcmp(line,"CONNECT")) { /* Ok, safe to handle HTTP at full speed now. */ setvbuf(client, cli_buf, _IOFBF, sizeof(cli_buf)); if (!ssl_host) { /* Unless coming from within CONNECT, we want a properly specified protocol and so forth. */ if (x[0] == '/') http_error(client, "Direct HTTP requests not allowed",1); if (strncmp(x,"http://",7)) http_error(client, "Unsupported protocol",1); x += 7; } } else { /* We do not want CONNECT requests within CONNECT requests, really. */ if (ssl_host) http_error(client,"Evil CONNECT nesting",1); ret->is_connect = 1; } ret->host = x; x = strchr(ret->host,' '); if (!x) http_error(client,"Missing HTTP protocol version",1); if (strcmp(x," HTTP/1.0") && strcmp(x," HTTP/1.1")) http_error(client,"unsupported HTTP protocol version",1); /* Trim HTTP/1.x part now, we do not need it */ *x = 0; if (!ret->is_connect) { ret->path = strchr(ret->host,'/'); if (!ret->path) http_error(client,"Incomplete request URL",1); *(ret->path++) = 0; } /* Try to find port, if any */ x = strchr(ret->host,':'); if (x) { ret->port = atoi(x+1); if (!ret->port || ret->port > 65535) http_error(client,"Illegal port specification",1); if (ret->port < 1024 && ret->port != 80 && ret->port != 443) http_error(client,"Access to this port denied",1); *x = 0; } else { if (ret->is_connect) ret->port = 443; else ret->port = 80; } /* Populate HTTP envelope data with higher-level CONNECT information if one present. */ if (ssl_host) { ret->host = ssl_host; ret->port = ssl_port; ret->from_ssl = 1; } if (!ret->host[0]) http_error(client,"Host name is missing",1); ret->host = strdup(ret->host); if (!ret->host) fatal("out of memory"); /* Grab query data */ if (!ret->is_connect && (x = strchr(ret->path,'?'))) { *(x++) = 0; ret->query = strdup(x); if (!ret->query) fatal("out of memory"); } /* Grab path data */ if (!ret->is_connect) { ret->path = strdup(ret->path); if (!ret->path) fatal("out of memory"); x = strrchr(ret->path,'.'); if (x) ret->ext = x + 1; } /* Request target is now fully parsed. Let's collect headers, if any. */ while (1) { line = grab_line(client); if (!line) http_error(client,"Incomplete or malformed request headers",1); /* Empty line == end of headers */ if (!line[0]) break; x = strchr(line,':'); if (!x) http_error(client,"Invalid request header",1); *x = 0; while (isspace(*(++x))); if (!strcasecmp(line,"Content-Length")) { ret->payload_len = atoi(x); if (ret->payload_len > MAXPAYLOAD) http_error(client,"Payload size limit exceeded",1); } if (!strncasecmp(line,"Cookie",6)) parse_cookies(x,&ret->cookies); if (!strcasecmp(line,"Referer")) { _u8* rh; ret->referer = strdup(x); if (!ret->referer) fatal("out of memory"); /* Extract referer host to simplify other checks later on. */ if ((rh = strstr(x,"://"))) { _u8* x; rh = strdup(rh + 3); if (!rh) fatal("out of memory"); if ((x = strchr(rh,'/'))) *x = 0; if ((x = strchr(rh,':'))) *x = 0; ret->ref_host = rh; } } if (!strcasecmp(line,"X-Ratproxy-Loop")) http_error(client,"Proxy loop detected",1); /* These are specific to publicly documented anti-XSRF features of Google Web Toolkit and Google Data APIs; this might be further extended to accomodate other custom schemes in popular frameworks. */ if (!strcasecmp(line,"Authorization") && !strncasecmp(x,"GoogleLogin auth=",17)) { ret->xsrf_safe = 1; ret->authsub = 1; } if (!strcasecmp(line,"Content-Type")) { if (rp_strcasestr(x,"text/x-gwt-rpc")) { ret->xsrf_safe = 1; ret->authsub = 1; } if (rp_strcasestr(x,"multipart/form-data")) ret->multipart = 1; else if (!rp_strcasestr(x,"application/x-www-form-urlencoded")) ret->non_param = 1; } DYN_ADD2(ret->h,line,x); } /* Get POST payload */ if (ret->payload_len) { ret->payload = malloc(ret->payload_len + 1); if (!ret->payload) fatal("out of memory"); if (fread(ret->payload,ret->payload_len,1,client) != 1) http_error(client,"Premature end of payload data",0); /* To make string matching safe. */ ret->payload[ret->payload_len] = 0; } /* Parse GET/POST parameters */ if (ret->query) parse_urlencoded(&ret->p, ret->query); ret->ppar_bound = ret->p.c; /* Do not parse payloads of arcane types. */ if (ret->payload && !ret->non_param) { if (ret->multipart) parse_multipart(&ret->p, ret->payload, ret->payload_len); else parse_urlencoded(&ret->p, ret->payload); } /* Locate XSRF tokens, if any */ /* Do not perform contains_token() checks on file fields. */ for (i=0;ip.c;i++) if (!ret->p.fn[i][0] && contains_token(ret->p.v1[i],ret->p.v2[i])) { ret->xsrf_safe = 1; break; } return ret; } /* Connect to server */ static FILE* open_server(FILE* client, _u8* host, _u32 port) { FILE* ret; struct sockaddr_in sin; struct hostent* he; _s32 ss; if (!(he = gethostbyname(host)) || !(he->h_addr_list[0])) http_error(client,"Unable to find target host",0); ss = socket(PF_INET, SOCK_STREAM, 0); if (ss < 0) pfatal("socket() failed"); sin.sin_family = PF_INET; sin.sin_port = htons(port); memcpy(&sin.sin_addr, he->h_addr_list[0], 4); if (connect(ss,(struct sockaddr*)&sin,sizeof(struct sockaddr_in))) http_error(client,"Connection to target failed",0); ret = fdopen(ss,"w+"); if (!ret) fatal("fdopen() failed"); setvbuf(ret, srv_buf, _IOFBF, sizeof(srv_buf)); return ret; } /* Connect to server, take proxy CONNECT handling into account */ FILE* open_server_complete(FILE* client, struct http_request* r) { FILE* ret; _u8* l; if (use_proxy) ret = open_server(client, use_proxy, proxy_port); else ret = open_server(client, r->host, r->port); if (r->is_connect) { if (use_proxy) { fprintf(ret,"CONNECT %s:%u HTTP/1.0\r\n\r\n",r->host,r->port); fflush(ret); setvbuf(ret, srv_buf, _IONBF, 0); /* Sink proxy response */ while ((l=grab_line(ret)) && l[0]); } if (client) { fprintf(client,"HTTP/1.0 200 Go ahead, please.\r\n\r\n"); fflush(client); } } return ret; } #define NEEDS_URLENC(x) \ (!(x) || !strchr("ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_.",toupper(x))) /* Rewrite GET and POST parameters as needed. */ void reconstruct_request(struct http_request* r) { struct dyn_str p = { 0, 0 }, q = { 0, 0 }; _u32 cp = 0, i; _u8 c; _u8 tmp[32]; /* Encode params to query string, until ppar boundary is hit. */ for (;cpp.c;cp++) { if (cp == r->ppar_bound) break; if (q.l) STR_APPEND_CHAR(q,'&'); i = 0; while ((c=r->p.v1[cp][i])) { if (NEEDS_URLENC(c)) { sprintf(tmp,"%%%02X",c); } else { tmp[0] = c; tmp[1] = 0; } STR_APPEND(q,tmp); i++; } STR_APPEND_CHAR(q,'='); i = 0; while ((c=r->p.v2[cp][i])) { if (NEEDS_URLENC(c)) { sprintf(tmp,"%%%02X",c); } else { tmp[0] = c; tmp[1] = 0; } STR_APPEND(q,tmp); i++; } } /* Update query string. */ if (q.l) r->query = q.v; /* Deal with the rest of parameters, putting them in a multipart envelope or as urlencoded payload, as needed. */ if (r->multipart) { /* Update boundary; be just random enough to prevent accidents. */ sprintf(tmp,"ratproxybound%08x",rand()); r->use_boundary = strdup(tmp); if (!r->use_boundary) fatal("out of memory"); for (;cpp.c;cp++) { STR_APPEND(p,"--"); STR_APPEND(p,r->use_boundary); STR_APPEND(p,"\r\nContent-Disposition: form-data; name=\""); STR_APPEND(p,r->p.v1[cp]); if (r->p.fn[cp][0]) { STR_APPEND(p,"\"; filename=\""); STR_APPEND(p,r->p.fn[cp]); } STR_APPEND(p,"\"\r\n\r\n"); if (r->p.l2[cp]) { STR_APPEND_RAWMEM(p,r->p.v2[cp],r->p.l2[cp]); } else { STR_APPEND(p,r->p.v2[cp]); } STR_APPEND(p,"\r\n"); } STR_APPEND(p,"--"); STR_APPEND(p,r->use_boundary); STR_APPEND(p,"--\r\n"); } else if (!r->non_param) { for (;cpp.c;cp++) { if (p.l) STR_APPEND_CHAR(p,'&'); i = 0; while ((c=r->p.v1[cp][i])) { if (NEEDS_URLENC(c)) { sprintf(tmp,"%%%02X",c); } else { tmp[0] = c; tmp[1] = 0; } STR_APPEND(p,tmp); i++; } STR_APPEND_CHAR(p,'='); i = 0; while ((c=r->p.v2[cp][i])) { if (NEEDS_URLENC(c)) { sprintf(tmp,"%%%02X",c); } else { tmp[0] = c; tmp[1] = 0; } STR_APPEND(p,tmp); i++; } } if (p.l) STR_APPEND(p,"\r\n"); } else return; /* Leave payload intact. */ /* Update POST string. */ if (p.l) { r->payload = p.v; r->payload_len = p.l; } return; } /* Detect and convert GWT RPC syntax where appropriate. This is specific to Google Web Toolkit. */ static _u8* maybe_gwt_rpc(_u8* str) { struct dyn_str p = { 0, 0 }; _u8 *c = str, *n; _u32 num = 0; _u32 l = strlen(str); if (l < 3 || str[l-3] != 0xEF || str[l-2] != 0xBF || str[l-1] != 0xBF) return str; STR_APPEND(p,"GWT_RPC["); while ((n = strstr(c,"\xEF\xBF\xBF"))) { *n = 0; if (num > 4) { if (num != 5) STR_APPEND_CHAR(p,','); STR_APPEND_CHAR(p,'\''); if (!strncmp(c,"[L",2)) c += 2; if (!strncmp(c,"com.google.",11) || !strncmp(c,"java.",5)) c = strrchr(c,'.') + 1; /* We *could* escape here, but it's probably not worth the effort. */ STR_APPEND(p,c); STR_APPEND_CHAR(p,'\''); } num++; *n = '\xEF'; c = n + 3; } STR_APPEND_CHAR(p,']'); return p.v; } /* Convert multipart data to URLencoded string, to simplify reporting. */ _u8* stringify_payload(struct http_request* r) { struct dyn_str p = { 0, 0 }; _u32 cp, i, c; _u8 tmp[32]; if (!r->multipart) return maybe_gwt_rpc(r->payload); /* Reconstruct payload from multipart boundary... */ for (cp=r->ppar_bound;cpp.c;cp++) { if (p.l) STR_APPEND_CHAR(p,'&'); i = 0; while ((c=r->p.v1[cp][i])) { if (NEEDS_URLENC(c)) { sprintf(tmp,"%%%02X",c); } else { tmp[0] = c; tmp[1] = 0; } STR_APPEND(p,tmp); i++; } STR_APPEND_CHAR(p,'='); /* When dealing with a file field, use field name, rather than field data. */ if (r->p.fn[cp][0]) { STR_APPEND(p,"FILE["); i = 0; while ((c=r->p.fn[cp][i])) { if (NEEDS_URLENC(c)) { sprintf(tmp,"%%%02X",c); } else { tmp[0] = c; tmp[1] = 0; } STR_APPEND(p,tmp); i++; } STR_APPEND_CHAR(p,']'); } else { i = 0; while ((c=r->p.v2[cp][i])) { if (NEEDS_URLENC(c)) { sprintf(tmp,"%%%02X",c); } else { tmp[0] = c; tmp[1] = 0; } STR_APPEND(p,tmp); i++; } } } return p.v; } /* Do a naive date comparison for t-1 sec/min/hr scenarios. */ _u8 comp_dates(_u8* exp, _u8* dat) { _s32 i = strlen(dat), dc = 0; if (i != strlen(exp)) return 1; while (--i >= 0) { if (exp[i] != dat[i]) { if (!isdigit(dat[i]) || exp[i] > dat[i] || ++dc > 1) return 1; } } return 0; } /* Send HTTP request, collect and parse response, spot header-related problems. */ struct http_response* send_request(FILE* client, FILE* server, struct http_request* r, _u8 strip_state) { struct http_response* ret; _u8 *line, *x; _s32 decl_clen = -1; _u32 i; _u8 port_spec[16] = { 0 }; _u8 *exp_value = 0, *dat_value = 0; /* Send the request... unfortunately, we cannot specify :80 on all standard requests, as some URL rewriters that redirect to https will copy this over and cause problems. */ if (!r->from_ssl) { if (r->port != 80) sprintf(port_spec,":%u",r->port); } else { if (r->port != 443) sprintf(port_spec,":%u",r->port); } if (use_proxy && !r->from_ssl) fprintf(server, "%s http://%s:%u/%s%s%s HTTP/1.0\r\n" "Connection: close\r\n" "Host: %s%s\r\n" "Accept-Encoding: identity\r\n" "X-Ratproxy-Loop: 1\r\n" "Content-Length: %u\r\n", r->method, r->host, r->port, r->path, r->query ? "?" : "", r->query ? r->query : (_u8*)"", r->host, port_spec, r->payload_len); else fprintf(server, "%s /%s%s%s HTTP/1.0\r\n" "Connection: close\r\n" "Host: %s%s\r\n" "Accept-Encoding: identity\r\n" "X-Ratproxy-Loop: 1\r\n" "Content-Length: %u\r\n", r->method, r->path, r->query ? "?" : "", r->query ? r->query : (_u8*)"", r->host, port_spec, r->payload_len); if (!strip_state) for (i=0;ih.c;i++) { /* There are several types of headers we'd rather skip and override elsewhere. */ #ifdef FORCE_NOCACHE if (!strncasecmp(r->h.v1[i],"If-",3)) continue; #endif /* FORCE_NOCACHE */ if (!strcasecmp(r->h.v1[i],"Host")) continue; if (!strcasecmp(r->h.v1[i],"Range")) continue; if (!strcasecmp(r->h.v1[i],"Connection")) continue; if (!strcasecmp(r->h.v1[i],"Keep-Alive")) continue; if (!strncasecmp(r->h.v1[i],"Proxy-",6)) continue; if (!strcasecmp(r->h.v1[i],"Accept-Encoding")) continue; if (!strcasecmp(r->h.v1[i],"Content-Length")) continue; /* Override multipart boundary on requests after rewriting. */ if (!strcasecmp(r->h.v1[i],"Content-Type") && r->use_boundary) { fprintf(server,"Content-Type: multipart/form-data; boundary=%s\r\n",r->use_boundary); continue; } fprintf(server,"%s: %s\r\n",r->h.v1[i],r->h.v2[i]); } fprintf(server,"\r\n"); if (r->payload_len) fwrite(r->payload,r->payload_len,1,server); fflush(server); /* Ok, sending complete. */ /* Process the response... */ ret = calloc(1,sizeof(struct http_response)); if (!ret) fatal("out of memory"); ret->ext = r->ext; line = grab_line(server); if (!line || !line[0]) http_error(client,"Malformed HTTP response",0); x = strchr(line,' '); if (!x || x == line) http_error(client,"HTTP response code missing",0); *(x++) = 0; ret->code = atoi(x); if (ret->code < 100 || ret->code > 999) http_error(client,"Invalid HTTP response code",0); while (1) { line = grab_line(server); if (!line) http_error(client,"Premature end of server headers",0); if (!line[0]) break; x = strchr(line,':'); if (!x) http_error(client,"Invalid response header",0); *x = 0; while (isspace(*(++x))); for (i=0;ih.c;i++) if (!strcasecmp(line,ret->h.v1[i]) && strcmp(x,ret->h.v2[i]) && strncasecmp(line,"Set-Cookie",10) && strncasecmp(line,"X-Cache",7) && strncasecmp(line,"Server",7)) ret->has_multiple = 1; /* Again, some headers need to be analyzed in more detail or skipped. */ /* Caching headers checks... */ if (!strcasecmp(line,"Expires")) { exp_value = strdup(x); if (!exp_value) fatal("out of memory"); } if (!strcasecmp(line,"Date")) { dat_value = strdup(x); if (!dat_value) fatal("out of memory"); } /* Both "no-store" and "max-age=0" are generally discouraged, but in practice, should be sufficient, so let's be polite. */ /* TODO: These checks should be probably more robust to detect typos such as missing whitespaces. */ if (!strcasecmp(line,"Cache-Control")) { if (strstr(x,"no-cache") || strstr(x,"private") || strstr(x,"max-age=0") || strstr(x,"no-store")) ret->cc11intent = INTENT_PRIV; else ret->cc11intent = INTENT_PUB; } if (!strcasecmp(line,"Pragma")) { if (strstr(x,"no-cache")) ret->pr10intent = INTENT_PRIV; else ret->pr10intent = INTENT_PUB; } if (!strcasecmp(line,"Connection")) continue; if (!strcasecmp(line,"Keep-Alive")) continue; if (!strcasecmp(line,"Content-Range")) continue; if (!strcasecmp(line,"Content-Type")) { _u8 *copy = strdup(x), *y; if (!copy) fatal("out of memory"); if ((y = strrchr(copy,';'))) { *(y++) = 0; while (isspace(*y)) y++; if (!strncasecmp(y,"charset=",8)) { y += 8; if (*y == '"' && y[strlen(y)-1] == '"') { y[strlen(y)-1]=0; y++; } ret->charset = y; } } ret->mime_type = copy; } if (!strcasecmp(line,"Content-Disposition")) { _u8* y; ret->is_attach = (strncasecmp(x,"attachment;",11) == 0) || (strcasecmp(x,"attachment") == 0); /* If filename is specified, try to grab it (it supersedes any URL-derived ones). */ y=strrchr(x,'.'); if (y && y[1] && y[1] != '"') { ret->ext = strdup(y + 1); if (!ret->ext) fatal("out of memory"); y = strchr(y + 1,'"'); if (y) *y=0; } } if (!strcasecmp(line,"Location")) { ret->location = strdup(x); if (!ret->location) fatal("out of memory"); } if (!strcasecmp(line,"Set-Cookie")) parse_cookies(x,&ret->cookies); if (!strcasecmp(line,"Content-Length")) { decl_clen = atoi(x); if (decl_clen < 0) http_error(client,"Bogus content length returned by server.",0); continue; } DYN_ADD2(ret->h,line,x); } /* Some final "Expires" parsing for caching headers checks... */ if (exp_value) { _u8* year = 0, *z = strchr(exp_value,','); ret->ex10intent = INTENT_PUB; /* Try to extract the year, at least roughly... */ if (!isalnum(exp_value[0])) { /* "Expires: -1" is a nasty trick, but it works. */ ret->ex10intent = INTENT_PRIV; } else if (dat_value && (!strcmp(exp_value,dat_value) || !comp_dates(exp_value,dat_value))) { /* Date == Expires is an alternative and valid method. */ ret->ex10intent = INTENT_PRIV; } else { if (z && z == exp_value + 3 && strlen(exp_value) > 11) { /* Sun, 06 Nov 1994 08:49:37 GMT ; RFC 822, updated by RFC 1123 */ year = exp_value + 11; if (*year == ' ') year++; } else if (z) { /* Sunday, 06-Nov-94 08:49:37 GMT ; RFC 850, obsoleted by RFC 1036 */ year = strchr(z,'-'); if (year) year = strchr(year + 1,'-'); if (year) year++; } else if (strlen(x) > 19) { /* Sun Nov 6 08:49:37 1994 ; ANSI C's asctime() format */ year = exp_value + 19; if (*year == ' ') year++; } if (year) { _u32 yval = atoi(year); if (yval < 1000) { yval += 1900; /* 94 -> 1994, 104 -> 2004 */ if (yval < 1970) yval += 100; /* 03 -> 2003, 93 -> 1993 */ } if (yval < 2008) ret->ex10intent = INTENT_PRIV; } } } /* Headers read. Grab the actual payload, regardless of content length (but note a discrepancy, if present). */ while (1) { _u8 buf[1024]; _s32 i; if ((i = fread(buf,1,1024,server)) <= 0) break; ret->payload = realloc(ret->payload, ret->payload_len + i + 1); if (!ret->payload) fatal("out of memory"); memcpy(ret->payload + ret->payload_len, buf, i); ret->payload_len += i; if (ret->payload_len > MAXPAYLOAD) http_error(client,"Response size limit exceeded",0); } if (ret->payload_len) ret->payload[ret->payload_len] = 0; /* Let payload_len < decl_clen slip through - transmission errors happen. */ if (decl_clen >= 0 && ret->payload_len > decl_clen) ret->has_badclen = 1; fflush(server); fclose(server); return ret; } /* Just send data back to client. */ void send_response(FILE* client, struct http_response* r) { _u32 i; setvbuf(client, cli_buf, _IOFBF, sizeof(cli_buf)); fprintf(client, "HTTP/1.0 %u Proxied response\r\n" "Connection: close\r\n" #ifdef FORCE_NOCACHE "Pragma: no-cache\r\n" "Expires: Fri, 01 Jan 1990 00:00:00 GMT\r\n" "Cache-Control: no-cache, must-revalidate\r\n" #endif /* FORCE_NOCACHE */ "Content-Length: %u\r\n", r->code, r->payload_len); for (i=0;ih.c;i++) { #ifdef FORCE_NOCACHE if (!strcasecmp(r->h1[i],"Expires")) continue; if (!strcasecmp(r->h1[i],"Last-Modified")) continue; if (!strcasecmp(r->h1[i],"Cache-Control")) continue; if (!strcasecmp(r->h1[i],"Pragma")) continue; #endif /* FORCE_NOCACHE */ fprintf(client,"%s: %s\r\n",r->h.v1[i],r->h.v2[i]); } fprintf(client,"\r\n"); if (r->payload_len) fwrite(r->payload,r->payload_len,1,client); fflush(client); fclose(client); } /* Calculate a checksum for response payload */ void checksum_response(struct http_response* r) { MD5_CTX ctx; _u8 res[16]; if (use_len) { r->cksum = r->payload_len; return; } if (!r->payload_len) return; MD5_Init(&ctx); MD5_Update(&ctx, r->payload, r->payload_len); MD5_Final((char*)res, &ctx); r->cksum = *(_u64*)res; } /* Attempt charset sniffing inside the payload; currently, supports HTML http-equiv only; kinda fuzzy, but should be good enough. */ /* TODO: Make this a bit more robust; reversed http-equiv / content order is not detected, for example. */ void detect_charset(struct http_response* r) { _u8 sniffed[33]; _u32 i, max; _u8 got_equiv = 0; if (r->payload_len > CHARSNIFF) max = CHARSNIFF; else max = r->payload_len; for (i=0;ipayload[i] < 0x20 && !isspace(r->payload[i])) break; if (!strncasecmp(r->payload+i,"http-equiv",10)) got_equiv = 1; if (r->payload[i] == '>') got_equiv = 0; if (got_equiv && !strncasecmp(r->payload+i,"charset=",8)) { _u32 p = 0; _u8* cp = r->payload + i + 8; while (p < 32 && (isalnum(*cp) || *cp == '-' || *cp == '_')) sniffed[p++] = *(cp++); sniffed[p] = 0; break; } } if (i != max) { if (r->charset && strcasecmp(sniffed,r->charset)) r->has_multiple = 1; r->charset = strdup(sniffed); if (!r->charset) fatal("out of memory"); } if (!r->charset) return; i = 0; while (valid_charsets[i]) { if (!strcasecmp(r->charset,valid_charsets[i])) return; i++; } /* But note that utf8, iso_8859_2, etc, are not recognized and lead to XSS... */ r->bad_cset = 1; if (!r->charset[0]) r->charset = 0; } #define TOHEX(c) ("0123456789abcdef"[c]) /* Sanitize output; make sure it's easily reversible, too. */ _u8* S(_u8* string, _u8 nl) { _u8* ret = malloc(MAXTOKEN + 10 /* �...\0 */), *wp = ret; if (!ret) fatal("out of memory"); while (*string) { switch (tolower(*string)) { /* Well, we kind-of want to maintain readaibility of text output, so let's pay the price and let '&' through. */ case '&': /* Quote literally */ case 'a' ... 'z': case '0' ... '9': case ' ': case '+': case '!': case '@': case '#': case '$': case '%': case '^': case '*': case '(': case ')': case '-': case '_': case '=': case '{': case '[': case '}': case ']': case ':': case ';': case ',': case '.': case '?': case '/': case '~': case '`': case '\\': *(wp++) = *string; break; /* These can be harmful or confusing, so replace with HTML entities */ case '"': case '\'': case '<': case '>': case '|': case 127 ... 255: entitify: *(wp++) = '&'; *(wp++) = '#'; *(wp++) = 'x'; *(wp++) = TOHEX(*string / 16); *(wp++) = TOHEX(*string % 16); *(wp++) = ';'; break; /* Replace with shorthand codes */ case '\r': if (nl) { *(wp++) = *string; } else { *(wp++) = '\\'; *(wp++) = 'r'; } break; case '\n': if (nl) { *(wp++) = *string; } else { *(wp++) = '\\'; *(wp++) = 'n'; } break; case '\t': if (nl) { *(wp++) = *string; } else { *(wp++) = '\\'; *(wp++) = 't'; } break; /* Replace with hex tokens */ default: if (nl) goto entitify; *(wp++) = '\\'; *(wp++) = 'x'; *(wp++) = TOHEX(*string / 16); *(wp++) = TOHEX(*string % 16); } if (wp - ret >= MAXTOKEN) { *(wp++) = '.'; *(wp++) = '.'; *(wp++) = '.'; break; } string++; } *(wp++) = 0; return ret; } ratproxy-1.58.orig/debug.h0000640000764400076440000000227111023027324014661 0ustar iustyiusty/* ratproxy - debugging macros --------------------------- Author: Michal Zalewski Copyright 2007, 2008 by Google Inc. All Rights Reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ #ifndef _HAVE_DEBUG_H #define _HAVE_DEBUG_H #include "types.h" #define debug(x...) fprintf(stderr,x) #define fatal(x...) do { \ debug("PROGRAM ABORT: " x); \ debug(" [%s(), %s:%u]\n",__FUNCTION__,__FILE__,__LINE__); \ exit(1); \ } while (0) #define pfatal(x...) do { \ debug( "SYSTEM ERROR : " x); \ debug( " [%s(), %s:%u]\n",__FUNCTION__,__FILE__,__LINE__); \ perror(" Message "); \ exit(1); \ } while (0) #endif /* ! _HAVE_DEBUG_H */ ratproxy-1.58.orig/config.h0000640000764400076440000001617211202621066015047 0ustar iustyiusty/* ratproxy - hardcoded configuration ---------------------------------- Author: Michal Zalewski Copyright 2007, 2008 by Google Inc. All Rights Reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ #ifndef _HAVE_CONFIG_H #define _HAVE_CONFIG_H #include "types.h" #define VERSION "1.58-beta" /* Maximum request / response header line length (HTTP traffic that exceeds this limit will be rejected). */ #define MAXLINE 8192 /* Maximum request payload size (to avoid DoS / malloc overflows). */ #define MAXPAYLOAD (30 * 1024 * 1024) /* Maximum saved trace file payload size (to conserve disk space). */ #define MAXTRACEITEM (1 * 1024 * 1024) /* Default proxy listen port. */ #define DEFAULT_PORT 8080 /* Uncomment to forcibly disable client-side page caching. Will slow things down - but may be useful if there is no way to purge browser cache manually prior to testing, or if you are forgetful. */ // #define FORCE_NOCACHE 1 /* Maximum token length for log entries produced (making this higher will include more query / response data in reports). */ #define MAXTOKEN 1024 /* MIME sniffing buffer size. */ #define SNIFFBUF 1024 /* Character set sniffing buffer size (when looking for META directives). */ #define CHARSNIFF 1024 /* Minimum parameter value length to be tested as an XSS candidate. */ #define MIN_XSS_LEN 4 /* The same, but for HTTP header injection checks. */ #define MIN_XSS_HEAD 6 /* Maximum parameter length to be considered a file path, as opposed to being just a random base64 blob with slashes in it. */ #define MAX_FPATH 64 /* Uncomment to XSS anti-XSRF tokens in -X mode. When defined, may prompt the proxy to miss some self-XSS vectors (because clobbered security tokens may inhibit page rendering), but will improve coverage in poorly written apps with no real XSRF protection to begin with. */ // #define XSS_XSRF_TOKENS 1 /* Uncomment to look for query path, not only parameters, being echoed back in response body, to derive risk flags. This may trigger false positives with some applciations, and hence is disabled by default. */ // #define CHECK_ECHO_PATH 1 /* NULL-terminated list of query field names that imply authentication. These override standard request repost based checks. This is a substring match - prefix with '=' to do full field matching. You might want to customize this list to include any other common values you encounter. */ static _u8* __attribute__((used)) auth_fields[] = { "login", "user", "sess", "account", "pass", 0 }; /* NULL-terminated list of known fields that implement XSRF protection features, even if they fail our tests. You might want to customize this list to troubleshoot any false positives you encounter. */ static _u8* __attribute__((used)) xsrf_fields[] = { "token", "once", "secret", "secid", "auth", "=tok", "=sig", /* The values below are chiefly Google-specific. */ "=gb", "=usg", "=at", "=bb", "=cid", "=ids", "=et", 0 }; /* NULL-terminated list of known fields that look like XSRF tokens, but have a different meaning and should be ignored. This is chiefly Google-specific - customize as needed, based on -X mode findings or manual testing. */ static _u8* __attribute__((used)) no_xsrf_fields[] = { "=ver", "=id", "=zx", "=_", 0 }; /* NULL-terminated list of common values that if visible in request parameters and inline on a page, do not really imply an XSS vector. */ static _u8* __attribute__((used)) no_xss_text[] = { "utf", "html", 0 }; /* NULL-terminated list of JSON-like response prefixes we consider to be sufficiently safe against cross-site script inclusion. You might want to extend the list as needed. */ static _u8* __attribute__((used)) json_safe[] = { "while(1);", /* Parser looping - common */ "while (1);", /* ... */ "while(true);", /* ... */ "while (true);", /* ... */ "&&&", /* Parser breaking - OpenSocial */ "//OK[", /* Line commenting - GWT */ "{\"", /* Serialized object - common */ "{{\"", /* Serialized object - common */ "throw 1;", /* Parser bailout - common */ ")]}", /* A robust alternative */ 0 }; /* NULL-terminated list of known valid charsets. Charsets not on the list are considered invalid, as they may trigger strange encoded XSS attack vectors, etc. You might want to extend this list as needed when testing foreign-language applications. WARNING: Please note that "harmless" misspellings such as 'utf8' or 'utf_8' are *not* harmless, and may trigger utf-7 XSSes. Do not add these to the list unless thoroughly validated. */ static _u8* __attribute__((used)) valid_charsets[] = { "utf-8", /* Valid Unicode */ "iso8859-1", /* Valid Western */ "iso-8859-1", /* Invalid but recognized */ "iso8859-2", /* Valid European */ "iso-8859-2", /* Invalid but recognized */ "iso8859-15", /* ISO-8859-1, new and improved */ "iso-8859-15", /* ISO-8859-1, new and improved */ "windows-1252", /* Microsoft's Western */ "windows-1250", /* Microsoft's European */ "us-ascii", /* Old school but generally safe */ 0 }; /* NULL-terminated list of active content MIME types, as produced by our sniffer. Any content that may execute in the browser in the security context of its serving domain belongs here. */ static _u8* __attribute__((used)) active_mime[] = { "text/html", /* HTML */ "application/xhtml+xml", /* XHTML */ "application/java-vm", /* Java class */ "application/java-archive", /* Java JAR */ "application/x-shockwave-flash", /* Flash */ "video/flv", /* Flash */ "video/x-flv", /* Flash */ 0 }; /* XSRF detector parameters; these might need to be tweaked if seeing false positives, but are otherwise OK for most intents and purposes. */ #define XSRF_B16_MIN 10 /* Minimum base16 token length */ #define XSRF_B16_MAX 45 /* Maximum base16 token length */ #define XSRF_B16_NUM 2 /* Require at least this many digit chars */ #define XSRF_B64_MIN 9 /* Minimum base32/64 token length */ #define XSRF_B64_MAX 32 /* Maximum base32/64 token length */ #define XSRF_B64_NUM 1 /* Require at least this many digit chars */ #define XSRF_B64_CASE 2 /* Require at least this many uppercase chars */ #define XSRF_B64_NUM2 3 /* Digit char count threshold to waive uppercase check */ #endif /* ! _HAVE_CONFIG_H */ ratproxy-1.58.orig/README0000777000764400076440000000000011233642416015736 2doc/READMEustar iustyiustyratproxy-1.58.orig/Makefile0000640000764400076440000000246311023464434015074 0ustar iustyiusty# # ratproxy - Makefile # ------------------- # # Author: Michal Zalewski # # Copyright 2007, 2008 by Google Inc. All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # PROGNAME = ratproxy CFLAGS = -Wall -O3 -Wno-pointer-sign -D_GNU_SOURCE LDFLAGS = -lcrypto -lssl all: $(PROGNAME) flare-check $(PROGNAME): $(PROGNAME).c http.c mime.c ssl.c http.h mime.h ssl.h nlist.h config.h debug.h types.h string-inl.h $(CC) $(PROGNAME).c -o $(PROGNAME) $(CFLAGS) http.c mime.c ssl.c $(LDFLAGS) flare-check: @flare-dist/flare 2>&1 | grep -qF Igor || ( \ echo; \ echo '*** WARNING: 'flare-dist/flare' bianry is not operational.'; \ echo '*** Please see flare-dist/README and update it for your OS.'; \ echo ) clean: rm -f $(PROGNAME) *.exe *.o *~ a.out core core.[1-9][0-9]* *.stackdump ratproxy-1.58.orig/doc/0000750000764400076440000000000011033070642014166 5ustar iustyiustyratproxy-1.58.orig/doc/Solaris.README0000640000764400076440000000115711033070417016466 0ustar iustyiustySolaris is not officially supported, as I have no usable test system; one of ratproxy users contributed the following workaround that may work, however: -- snip! -- Changes needed to Makefile to compile on Solaris10. 23,24c23,25 < CFLAGS = -Wall -O3 -Wno-pointer-sign -D_GNU_SOURCE < LDFLAGS = -lcrypto -lssl --- > #CFLAGS = -Wall -O3 -Wno-pointer-sign -D_GNU_SOURCE > CFLAGS = -Wall -O3 -D_GNU_SOURCE > LDFLAGS = -lcrypto -lssl -lsocket -lnsl You will need GCC. You must also have openssl built and resolvable via ENV variable LD_LIBRARY_PATH To compile type in "make CC=gcc" -- snip! -- ratproxy-1.58.orig/doc/README0000640000764400076440000006662411163004675015074 0ustar iustyiusty=========================================================== ratproxy - passive web application security assessment tool =========================================================== http://code.google.com/p/ratproxy * Written and maintained by Michal Zalewski . * Copyright 2007, 2008 Google Inc, rights reserved. * Released under terms and conditions of the Apache License, version 2.0. ----------------- What is ratproxy? ----------------- Ratproxy is a semi-automated, largely passive web application security audit tool. It is meant to complement active crawlers and manual proxies more commonly used for this task, and is optimized specifically for an accurate and sensitive detection, and automatic annotation, of potential problems and security-relevant design patterns based on the observation of existing, user-initiated traffic in complex web 2.0 environments. The approach taken with ratproxy offers several important advantages over more traditional methods: * No risk of disruptions. In the default operating mode, tool does not generate a high volume of attack-simulating traffic, and as such may be safely employed against production systems at will, for all types of ad hoc, post-release audits. Active scanners may trigger DoS conditions or persistent XSSes, and hence are poorly suited for live platforms. * Low effort, high yield. Compared to active scanners or fully manual proxy-based testing, ratproxy assessments take very little time or bandwidth to run, and proceed in an intuitive, distraction-free manner - yet provide a good insight into the inner workings of a product, and the potential security vulnerabilities therein. They also afford a consistent and predictable coverage of user-accessible features. * Preserved control flow of human interaction. By silently following the browser, the coverage in locations protected by nonces, during other operations valid only under certain circumstances, or during dynamic events such as cross-domain Referer data disclosure, is greatly enhanced. Brute-force crawlers and fuzzers usually have no way to explore these areas in a reliable manner. * WYSIWYG data on script behavior. Javascript interfaces and event handlers are explored precisely to a degree they are used in the browser, with no need for complex guesswork or simulations. Active scanners often have a significant difficulty exploring JSON responses, XMLHttpRequest() behavior, UI-triggered event data flow, and the like. * Easy process integration. The proxy can be transparently integrated into an existing manual security testing or interface QA processes without introducing a significant setup or operator training overhead. ----------------------- Is it worth trying out? ----------------------- There are numerous alternative proxy tools meant to aid security auditors - most notably WebScarab, Paros, Burp, and ProxMon. Stick with whatever suits your needs, as long as you get the data you need in the format you like. That said, ratproxy is there for a reason. It is designed specifically to deliver concise reports that focus on prioritized issues of clear relevance to contemporary web 2.0 applications, and to do so in a hands-off, repeatable manner. It should not overwhelm you with raw HTTP traffic dumps, and it goes far beyond simply providing a framework to tamper with the application by hand. Ratproxy implements a number of fairly advanced and unique checks based on our experience with these applications, as well as all the related browser quirks and content handling oddities. It features a sophisticated content-sniffing functionality capable of distinguishing between stylesheets and Javascript code snippets, supports SSL man-in-the-middle, on the fly Flash ActionScript decompilation, and even offers an option to confirm high-likelihood flaw candidates with very lightweight, a built-in active testing module. Last but not least, if you are undecided, the proxy may be easily chained with third-party security testing proxies of your choice. ---------------------------------- How does it avoid false positives? ---------------------------------- Operating in a non-disruptive mode makes the process of discovering security flaws particularly challenging, as the presence of some vulnerabilities must be deduced based on very subtle, not always reliable cues - and even in active testing modes, ratproxy strives to minimize the amount of rogue traffic generated, and side effects caused. The set of checks implemented by ratproxy is outlined later on - but just as importantly, underneath all the individual check logic, the proxy uses a number of passively or semi-passively gathered signals to more accurately prioritize reported problems and reduce the number of false alarms as much as possible. The five core properties examined for a large number of checks are: * What the declared and actually detected MIME type for the document is. This is a fairly important signal, as many problems manifest themselves only in presence of subtle mismatches between these two - whereas other issues need to be treated as higher or lower priority based on this data. More fundamentally, the distinction between certain classes of content - such as "renderables" that may be displayed inline by the browser - is very important to many checks. * How pages respond to having cookie-based authentication removed. This provides useful information on whether the resource is likely to contain user-specific data, amongst other things. Carefully preselected requests that fail some security checks are replayed as-is, but with authentication data removed; responses are then compared, with virtually no risk of undesirable side effects in common applications. * Whether requests seem to contain non-trivial, sufficiently complex security tokens, or other mechanisms that may make the URL difficult to predict. This provides information needed to determine the presence of XSRF defenses, to detect cross-domain token leakage, and more. (In active testing mode, the function of such tokens is further validated by replaying the request with modified values.) * Whether any non-trivial parts of the query are echoed back in the response, and in what context. This is used to pick particularly interesting candidates for XSS testing - or, in active mode, to schedule low-overhead, lightweight probes. * Whether the interaction occurs on a boundary of a set of domains defined by runtime settings as the trusted environment subjected to the audit, and the rest of the world. Many boundary behaviors have a special significance, as they outline cross-domain trust patterns and information disclosure routes. In addition to this, several places employ check-specific logic to further fine-tune the results. ------------------------------------ What specific tests are implemented? ------------------------------------ Key low-level check groups implemented by ratproxy are: * Potentially unsafe JSON-like responses that may be vulnerable to cross-domain script inclusion. JSON responses may be included across domains by default, unless safe serialization schemes, security tokens, or parser breaking syntax is used. Ratproxy will check for these properties, and highlight any patterns of concern. * Bad caching headers on sensitive content. Ratproxy is able to accurately detect presence of several types of sensitive documents, such as locations that return user-specific data, or resources that set new, distinctive cookies. If the associated requests have predictable URLs, and lack HTTP caching directives that would prevent proxy-level caching, there is a risk of data leakage. In pedantic mode, ratproxy will also spot differences in HTTP/1.1 and HTTP/1.0 caching intents - as these may pose problems for a fraction of users behind legacy cache engines (such as several commercial systems used to date by some corporations). * Suspicious cross-domain trust relationships. Based on the observation of dynamic control flow, and a flexible definition of trusted perimeter, ratproxy is capable of accurately detecting dangerous interactions between domains, including but not limited to: * Security token leakage via Referer headers, * Untrusted script or stylesheet inclusion, * General references to third-party domains, * Mixed content issues in HTTPS-only applications, * Tricky cross-domain POST requests in single sign-on systems. * Numerous classes of content serving issues - a broad class of problems that lead to subtles XSSes, and includes MIME type mismatches, charset problems, Flash issues, and more. Research indicates that a vast number of seemingly minor irregularities in content type specifications may trigger cross-site scripting in unusal places; for example, subtle mistakes such as serving GIF files as image/jpeg, typing utf8 instead of utf-8 in Content-Type headers, or confusing HTTP charset with XML declaration charset values are all enough to cause trouble. Even seemingly harmless actions such as serving valid, attacker-controlled PNG images inline were known to cause problems due to browser design flaws. Likewise, certain syntax patterns are dangerous to return to a browser regardless of MIME types, as there are known methods to have MIME types overridden or ignored altogether. Ratproxy uses a set of fairly advanced checks that spot these problems with a considerable accuracy and relatively few false positives in contemporary scenarios, accounting for various classes of content served. * Queries with insufficient XSRF defenses (POSTs, plus any requests that set cookies by default; and other suspicious looking GET requests as an option). In active testing mode, the proxy will also actually try to validate XSRF protections by replaying requests with modified token values, and comparing responses. * Suspected or confirmed XSS / data injection vectors, including attacks through included JSON-based script injection, or response header splitting. In the default, passive mode, ratproxy does not attempt to confirm the quality of XSS filtering in tested applications, but it will automatically enumerate and annotate the best subjects for manual inspection - and will offer the user the ability to feed this data to external programs, or modify and replay interesting requests on the fly. The proxy will also take note of any seemingly successful manual XSS attempts taken by the user. In active testing mode, the proxy will go one step further and attempt a single-shot verification of XSS filtering mechanisms, carefully tweaking only these request parameters that truly need to be tested at the time (and carefully preserving XSRF tokens, and more). * HTTP and META redirectors. Redirectors, unless properly locked down, may be used without owner's consent, which in some contexts may be seen as undesirable. Furthermore, in extreme cases, poorly implemented redirectors may open up cross-site scripting vectors in less common browsers. Ratproxy will take note of any redirectors observed for further testing. * A broad set of other security problems, such as alarming Javascript, OGNL, Java, SQL, file inclusion patterns, directory indexes, server errors, and so forth. Ratproxy will preselect particularly interesting candidates for further testing. Although in the initial beta, not all web technologies may necessarily be analyzed to greatest extent possible, we intend to actively improve the tool based on your feedback. * Several additional, customizable classes of requests and responses useful in understanding the general security model of the application (file upload forms, POST requests, cookie setters, etc). For a full list of individual issues reported, please see messages.list in the source tarball. ------------------------------------------ What is the accuracy of reported findings? ------------------------------------------ Ratproxy usually fares very well with typical, rich, modern web applications - that said, by the virtue of operating in passive mode most of the time, all the findings reported merely highlight areas of concern, and are not necessarily indicative of actual security flaws. The information gathered during a testing session should be then interpreted by a security professional with a good understanding of the common problems and security models employed in web applications. Please keep in mind that the tool is still in beta, and you may run into problems with technologies we had no chance to examine, or that were not a priority at this time. Please contact the author to report any issues encountered. --------------------- How to run the proxy? --------------------- NOTE: Please do not be evil. Use ratproxy only against services you own, or have a permission to test. Keep in mind that although the proxy is mostly passive and unlikely to cause disruptions, it is not stealth. Furthermore, the proxy is not designed for dealing with rogue and misbehaving HTTP servers and clients - and offers no guarantees of safe (or sane) behavior there. Initiating ratproxy sessions is fairly straigtforward, once an appropriate set of runtime options is dediced upon. Please familiarize yourself with these settings, as they have a very significant impact on the quality of produced reports. The main binary, ./ratproxy, takes the following arguments: -w logfile - this option causes raw, machine-readable proxy logs to be written to a specified file. By default, all data is written to stdout only. The log produced this way is not meant for human consumption - it might be postprocessed with third-party utilities, or pretty-printed using 'ratproxy-report.sh', however. -v logdir - prompts ratproxy to store full HTTP traces of all requests featured in the logfile, writing them to a specified directory. In most cases, it is advisable to enable this option, as it provides useful hints for further analysis. -p port - causes ratproxy to listen for browser connections on a TCP port different than the default 8080. -r - instructs ratproxy to accept remote connections. By default, the proxy listens on loopback interfaces only. This option enables remote access to the service. WARNING: Ratproxy does not feature any specific access control mechanisms, and may be abused if exposed to the Internet. Please make sure to use proper firewall controls whenever using -r option to prevent this. -d domain - specifies a domain name suffix used to distinguish between the audited infrastructure and third-party sites. Host names that match -d values will be subjected to analysis, and ones that do not will be considered the outside world. Interactions between these two classes will be subjected to additional checks. NOTE: This feature is extremely important for several of the checks implemented by ratproxy. If -d option is missing, ratproxy will treat all URLs as being a part of the audited service, and cross-domain interaction checks will not be carried out at all. If it is set incorrectly, report coverage may decrease. Multiple -d options may and often should be combined to define the perimeter for testing and flow analysis (e.g., -d example.com -d example-ad-service.com -d example-ng.com). -P host:port - causes ratproxy to talk to an upstream proxy instead of directly routing requests to target services. Useful for testing systems behind corporate proxies, or chaining multiple proxy-type security testing tools together. -l - ratproxy sometimes needs to tell if a page has substantially changed between two requests to better qualify the risks associated with some observations. By default, this is achieved through strict page checksum comparison (MD5). This options enables an alternative, relaxed checking mode that relies on page length comparison instead. Since some services tend to place dynamically generated tokens on rendered pages, it is generally advisable to enable this mode most of the time. -2 - several services are known to render the same page with dynamic content of variable length in response to two subsequent, otherwise identical requests. This might be a result of inline ad rendering, or other content randomization. When dealing with such services, ratproxy might be instructed to acquire three, not two, samples for page comparison for some checks, to further minimize the number of false positives. -e - enables pedantic caching header validation. Security problems may arise when documents clearly not meant to be cached are served in a way that permits public proxies to store them. By default, ratproxy detects poorly chosen HTTP/1.1 caching directives that are most likely to affect general population. Some additional issues may appear with users behind legacy proxies that support HTTP/1.0 only, however - as is the case with several commercial solutions. These proxies may ignore HTTP/1.1 directives and interpret HTTP/1.0 cues only. In -e mode, ratproxy will complain about all cases where there appears to be a mismatch between HTTP/1.0 and HTTP/1.1 caching intents. This tends to generate a large number of warnings for many services; if you prefer to focus on more pressing issues first, you might want to keep it off at first. -x - tells the proxy to log all URLs that seem to be particularly well-suited for further, external XSS testing (by the virtue of being echoed on the page in a particular manner). By default, ratproxy will not actually attempt to confirm these vectors (-X option enables disruptive checking, however) - but you will be able to use the data for manual testing or as input to third-party software. Generally recommended, unless it proves to be too noisy. -t - by default, ratproxy logs some of the most likely directory traversal candidates. This option tells the proxy to log less probable guesses, too. These are good leads for manual testing or as input to an external application. Generally recommended, unless it proves to be too noisy. -i - with this option supplied, ratproxy will log all PNG files served inline. PNG files are a cross-site scripting vector in some legacy browsers. The default behavior is to log these images that require authentication only, based on the assumption that such images are most likely to be user-controlled. This option should be enabled when auditing applications that permit picture uploads and sharing; otherwise, it may just generate noise. -f - with this option enabled, the proxy will log all Flash applications encountered for further analysis. This is particularly useful when combined with -v, in which case, Flash files will be automatically disassembled and conveniently included in 'ratproxy-report.sh' output. Since recent Flash vulnerabilities make the platform a major potential cross-site scripting vector, it is advisable to enable this feature. -s - tells ratproxy to log all POST requests for further analysis and processing, in a separate section of the final report. This is useful for bookkeeping and manual review, since POST features are particularly likely to expose certain security design flaws. -c - enables logging of all URLs that seem to set cookies, regardless of their presumed security impact. Again, useful for manual design analysis and bookkeeping. Not expected to contribute much noise to the report. -g - extends XSRF token validation checks to GET requests. By default, the proxy requires anti-XSRF protection on POST requests and cookie setters only. Some applications tend to perform state changing operations via GET requests, too, and so with this option enabled, additional data will be collected and analyzed. This feature is verbose, but useful for certain application designs. -j - enables detection of discouraged Javascript syntax, such as eval() calls or .innerHTML operations. Javascript code that makes use of these will be tagged for manual inspection. -m - enables logging of "active" content referenced across domain boundaries to detect patterns such as remote image inclusion or remote linking (note that logging of remote script or stylesheet inclusion is enabled at all times). This option has an effect only when a proper set of domains is specified with -d command-line parameter - and is recommended for sites where a careful control of cross-domain trust relationships needs to be ensured. -X - enables active testing. When this option is provided, ratproxy will attempt to actively, disruptively validate the robustness of XSS and XSRF defenses whenever such a check is deemed necessary. By the virtue of doing passive preselection, this does not generate excessive traffic and maintains the same level of coverage as afforded in passive mode. The downside is that these additional requests may disrupt the application or even trigger persistent problems; as such, please exercise caution when using it against mission-critical production systems. -C - in disruptive testing mode, ratproxy will replay some requests with modified parameters. This may disrupt the state of some applications and make them difficult to navigate. To remediate this, -C option enables additional replaying of the unmodified request at the end of the process, in hopes of restoring the original server-side state. This option is generally recommended in -X mode. -k - instructs ratproxy that the application is expected to use HTTPS exclusively; any downgrades to HTTP will be reported and prioritized depending on potential impact. This option obviously makes sense only if the application is indeed meant to use HTTPS and HTTPS only. -a - tells ratproxy to indiscriminately log all visited URLs. Useful for assessing the coverage achieved. In practice, for low verbosity reporting that looks for high-probability issues only, a good starting point is: ./ratproxy -v -w -d -lfscm To increase verbosity and include output from some less specific checks, the following set of options is a good idea: ./ratproxy -v -w -d -lextifscgjm For active testing, simply add -XC options as needed. Once the proxy is running, you need to configure your web browser to point to the appropriate machine and port (a simple Firefox extension such as QuickProxy may come handy in the long run); it is advisable to close any non-essential browser windows and purge browser cache, as to maximize coverage and minimize noise. The next step is to open the tested service in your browser, log in if necessary, then interact with it in a regular, reasonably exhaustive manner: try all available views, features, upload and download files, add and delete data, and so forth - then log out gracefully and terminate ratproxy with Ctrl-C. NOTE: Do not be tempted to tunnel automated spider traffic (e.g. wget -r or active scanners) via ratproxy. This will not have the desired effect. The tool depends strictly on being able to observe well-behaved, valid user-application interaction. SECURITY WARNING: When interacting with SSL applications, ratproxy will substitute its own, dummy, self-signed certificate in place of that legitimately returned by the service. This is expected to generate browser warnings - click through them to accept the key temporarily for the site. Do not add the key permanently to your browser configuration - the key is known to anyone who ever downloaded the tool. Furthermore, please note that ratproxy will also forego any server certificate validation steps - so while interacting with the service in this mode, you can have no expectation of server identity, transmission integrity, or data privacy. Do not use important accounts and do not enter sensitive data while running ratproxy tests. Once the proxy is terminated, you may further process its pipe-delimited (|), machine-readable, greppable output with third party tools if so desired, then generate a human-readable HTML report: ./ratproxy-report.sh ratproxy.log >report.html This will produce an annotated, prioritized report with all the identified issues. When opened in a browser, you will have an opportunity to replay GET and POST requests, tweak their parameters, view traces, and inspect Flash disassemblies, too. Enjoy :-) ----------------------------------- Credits, contributions, suggestions ----------------------------------- If you are interested in contributing to the project, a list of features and improvements for the proxy can be found in doc/TODO in the source tarball. If you have any questions, suggestions, or concerns regarding the application, the author can be reached at lcamtuf@google.com. Ratproxy was made possible by the contributions of, and valuable feedback from, Google's information security engineering team. ratproxy-1.58.orig/doc/TODO0000640000764400076440000000372611023456551014675 0ustar iustyiusty----- TODO: ----- - Javascript formatter / prettyprinter: this would make it easier to inspect "compiled" Javascript. - Multiple report-related improvements: - Proper CSS classes instead of current inline mess, - Add better issue filtering capabilities based on host / path, - Make it possible to edit target URLs in forms. - Machine-readable output improvements: use a better output format with less escaping necessary. Move most of escaping to ratproxy-report.sh instead. - Better caching header analysis: current Expires/Date parsing logic is very simplistic and may trigger false positives in some scenarios. - Context-aware XSS testing: make XSS injection checks aware of the context, so that only a small snippet of code would need to be injected (minimizes the risk of query rejection). - Better XSRF token checks: validate rudimentary alphabet distribution properties with better resolution; "0aBaBaBaBaB" should not qualify as a valid token. - Unified Javascript analyzer: simplified JS related checks are currently dispersed through the code. This should be moved to a separate component and much improved. - Flash security lint: decompiled SWFs could be automatically surveyed for problems. - Code refactoring and improvements: modularize check logic, add configuration file parsing in place of config.h, etc. -------------------- Check-specific TODO: -------------------- - Cookie injection: look for query payloads copied over to cookies. - Data leakage: look for non-FQDN domain names, private IPs, and file:// references when a "production service" option is supplied. - Common exception trace pattern detection. - Enumeration of server types and versions. - Checks for revealing or offensive comments, file names, etc. - Perhaps a brute-force checker for UTF-8 character consumption, SQL injection checks. - Referer-based XSS: devise a scheme to check for this reliably. ratproxy-1.58.orig/doc/COPYING0000640000764400076440000002613610161362341015233 0ustar iustyiusty 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.