# Bazaar merge directive format 2 (Bazaar 0.90) # revision_id: rousskov@measurement-factory.com-20080929082520-\ # yj6ot9lk2iq6mgwn # target_branch: file:///home/rousskov/programs/bazaar/repos/squid\ # /trunk/ # testament_sha1: 899d9cfdcd47008b37b7e633e41270956c7d138b # timestamp: 2008-09-29 02:26:27 -0600 # base_revision_id: squid3@treenet.co.nz-20080929045352-\ # vw0d7umqmnetevyo # # Begin patch === modified file 'configure.in' --- configure.in 2008-09-19 03:29:56 +0000 +++ configure.in 2008-09-27 18:33:49 +0000 @@ -784,13 +784,21 @@ eCAP support requires loadable modules. Please do not use --disable-loadable-modules with --enable-ecap.]); fi + + dnl eCAP support requires libecap + AC_CHECK_LIB([ecap], [main], + [ECAP_LIBS="-lecap"], + [AC_MSG_FAILURE([ + eCAP support requires libecap library, + but no usable library was found])] + ) fi AM_CONDITIONAL(USE_ECAP, test $use_ecap = yes) if test $use_ecap = yes; then AC_DEFINE(USE_ECAP,1,[Enable eCAP support]) - ECAP_LIBS="eCAP/libeCAP.la" + ECAP_LIBS="eCAP/libeCAP.la $ECAP_LIBS" use_adaptation=yes else AC_DEFINE(USE_ECAP,0,[Disable eCAP support]) === modified file 'src/BodyPipe.h' --- src/BodyPipe.h 2008-04-17 05:44:45 +0000 +++ src/BodyPipe.h 2008-09-27 18:19:22 +0000 @@ -96,7 +96,7 @@ bool mayNeedMoreData() const { return !bodySizeKnown() || needsMoreData(); } bool needsMoreData() const { return bodySizeKnown() && unproducedSize() > 0; } uint64_t unproducedSize() const; // size of still unproduced data - bool stillProducing(Producer *producer) const { return theProducer == producer; } + bool stillProducing(const Producer *producer) const { return theProducer == producer; } // called by consumers bool setConsumerIfNotLate(Consumer *aConsumer); @@ -105,7 +105,7 @@ void consume(size_t size); bool expectMoreAfter(uint64_t offset) const; bool exhausted() const; // saw eof/abort and all data consumed - bool stillConsuming(Consumer *consumer) const { return theConsumer == consumer; } + bool stillConsuming(const Consumer *consumer) const { return theConsumer == consumer; } // start or continue consuming when there is no consumer void enableAutoConsumption(); === modified file 'src/HttpMsg.h' --- src/HttpMsg.h 2008-01-20 15:54:28 +0000 +++ src/HttpMsg.h 2008-05-08 20:03:16 +0000 @@ -55,6 +55,8 @@ virtual HttpMsg *_lock(); // please use HTTPMSGLOCK() virtual void _unlock(); // please use HTTPMSGUNLOCK() + virtual HttpMsg *clone() const = 0; + public: HttpVersion http_ver; === modified file 'src/HttpReply.cc' --- src/HttpReply.cc 2008-07-02 03:49:07 +0000 +++ src/HttpReply.cc 2008-09-27 18:33:49 +0000 @@ -552,6 +552,7 @@ } } +// XXX: check that this is sufficient for eCAP cloning HttpReply * HttpReply::clone() const { @@ -561,6 +562,8 @@ rep->hdr_sz = hdr_sz; rep->http_ver = http_ver; rep->pstate = pstate; + rep->body_pipe = body_pipe; + rep->protocol = protocol; rep->sline = sline; return rep; === modified file 'src/HttpRequest.cc' --- src/HttpRequest.cc 2008-06-07 05:20:05 +0000 +++ src/HttpRequest.cc 2008-09-27 18:33:49 +0000 @@ -143,6 +143,59 @@ init(); } +HttpRequest * +HttpRequest::clone() const +{ + HttpRequest *copy = new HttpRequest(method, protocol, urlpath.buf()); + // TODO: move common cloning clone to Msg::copyTo() or copy ctor + copy->header.append(&header); + copy->hdrCacheInit(); + copy->hdr_sz = hdr_sz; + copy->http_ver = http_ver; + copy->pstate = pstate; // TODO: should we assert a specific state here? + copy->body_pipe = body_pipe; + + strncpy(copy->login, login, sizeof(login)); // MAX_LOGIN_SZ + strncpy(copy->host, host, sizeof(host)); // SQUIDHOSTNAMELEN + copy->host_addr = host_addr; + + if (auth_user_request) { + copy->auth_user_request = auth_user_request; + AUTHUSERREQUESTLOCK(copy->auth_user_request, "HttpRequest::clone"); + } + + copy->port = port; + // urlPath handled in ctor + copy->canonical = canonical ? xstrdup(canonical) : NULL; + + // This may be too conservative for the 204 No Content case + // may eventually need cloneNullAdaptationImmune() for that. + copy->flags = flags.cloneAdaptationImmune(); + + copy->range = range ? new HttpHdrRange(*range) : NULL; + copy->ims = ims; + copy->imslen = imslen; + copy->max_forwards = max_forwards; + copy->client_addr = client_addr; + copy->my_addr = my_addr; + copy->hier = hier; // Is it safe to copy? Should we? + + copy->errType = errType; + + // XXX: what to do with copy->peer_login? + + copy->lastmod = lastmod; + copy->vary_headers = vary_headers ? xstrdup(vary_headers) : NULL; + // XXX: what to do with copy->peer_domain? + + copy->tag = tag; + copy->extacl_user = extacl_user; + copy->extacl_passwd = extacl_passwd; + copy->extacl_log = extacl_log; + + return copy; +} + bool HttpRequest::sanityCheckStartLine(MemBuf *buf, http_status *error) { === modified file 'src/HttpRequest.h' --- src/HttpRequest.h 2008-06-07 05:20:05 +0000 +++ src/HttpRequest.h 2008-09-27 18:33:49 +0000 @@ -65,6 +65,8 @@ void initHTTP(const HttpRequestMethod& aMethod, protocol_t aProtocol, const char *aUrlpath); + virtual HttpRequest *clone() const; + /* are responses to this request potentially cachable */ bool cacheable() const; === modified file 'src/ICAP/AsyncJob.cc' --- src/ICAP/AsyncJob.cc 2008-04-17 05:50:09 +0000 +++ src/ICAP/AsyncJob.cc 2008-09-28 01:16:18 +0000 @@ -115,7 +115,7 @@ typeName << " status in:" << status()); } -void AsyncJob::callException(const TextException &e) +void AsyncJob::callException(const std::exception &e) { // we must be called asynchronously and hence, the caller must lock us Must(cbdataReferenceValid(toCbdata())); @@ -212,9 +212,9 @@ try { doDial(); } - catch (const TextException &e) { + catch (const std::exception &e) { debugs(call.debugSection, 3, - HERE << call.name << " threw exception: " << e.message); + HERE << call.name << " threw exception: " << e.what()); job->callException(e); } === modified file 'src/ICAP/AsyncJob.h' --- src/ICAP/AsyncJob.h 2008-02-27 04:49:32 +0000 +++ src/ICAP/AsyncJob.h 2008-09-28 01:16:18 +0000 @@ -30,7 +30,7 @@ * asynchronous calls. */ -class TextException; +class std::exception; /// \ingroup AsyncJobAPI class AsyncJob @@ -63,7 +63,7 @@ // asynchronous call maintenance bool canBeCalled(AsyncCall &call) const; void callStart(AsyncCall &call); - virtual void callException(const TextException &e); + virtual void callException(const std::exception &e); virtual void callEnd(); protected: === modified file 'src/ICAP/ICAPModXact.cc' --- src/ICAP/ICAPModXact.cc 2008-09-19 17:26:31 +0000 +++ src/ICAP/ICAPModXact.cc 2008-09-29 07:46:55 +0000 @@ -566,7 +566,7 @@ parseBody(); } -void ICAPModXact::callException(const TextException &e) +void ICAPModXact::callException(const std::exception &e) { if (!canStartBypass || isRetriable) { ICAPXaction::callException(e); @@ -575,10 +575,10 @@ try { debugs(93, 3, "bypassing ICAPModXact::" << inCall << " exception: " << - e.message << ' ' << status()); + e.what() << ' ' << status()); bypassFailure(); } - catch (const TextException &bypassE) { + catch (const std::exception &bypassE) { ICAPXaction::callException(bypassE); } } === modified file 'src/ICAP/ICAPModXact.h' --- src/ICAP/ICAPModXact.h 2008-03-31 01:06:13 +0000 +++ src/ICAP/ICAPModXact.h 2008-09-29 07:46:55 +0000 @@ -158,7 +158,7 @@ protected: // bypasses exceptions if needed and possible - virtual void callException(const TextException &e); + virtual void callException(const std::exception &e); private: virtual void start(); === modified file 'src/ICAP/ICAPServiceRep.cc' --- src/ICAP/ICAPServiceRep.cc 2008-04-05 05:16:03 +0000 +++ src/ICAP/ICAPServiceRep.cc 2008-05-08 20:06:07 +0000 @@ -110,11 +110,6 @@ return self != NULL && !isSuspended && hasOptions(); } -bool ICAPServiceRep::broken() const -{ - return probed() && !up(); -} - bool ICAPServiceRep::wantsUrl(const String &urlPath) const { Must(hasOptions()); === modified file 'src/ICAP/ICAPServiceRep.h' --- src/ICAP/ICAPServiceRep.h 2008-04-03 05:31:29 +0000 +++ src/ICAP/ICAPServiceRep.h 2008-05-08 20:06:07 +0000 @@ -89,7 +89,6 @@ void invalidate(); // call when the service is no longer needed or valid bool probed() const; // see comments above - bool broken() const; // see comments above bool up() const; // see comments above virtual Adaptation::Initiate *makeXactLauncher(Adaptation::Initiator *, HttpMsg *virginHeader, HttpRequest *virginCause); === modified file 'src/LoadableModules.cc' --- src/LoadableModules.cc 2008-03-31 04:31:48 +0000 +++ src/LoadableModules.cc 2008-05-08 20:06:52 +0000 @@ -21,5 +21,5 @@ int count = 0; for (const wordlist *i = names; i; i = i->next, ++count) LoadModule(i->key); - debugs(1, 1, "loaded " << count << " Squid modules"); + debugs(1, 1, "Squid modules loaded: " << count); } === modified file 'src/Makefile.am' --- src/Makefile.am 2008-09-29 03:03:47 +0000 +++ src/Makefile.am 2008-09-29 06:42:09 +0000 @@ -723,8 +723,7 @@ @DISK_LINKOBJS@ \ @REPL_OBJS@ \ @AUTH_LINKOBJS@ \ - @AUTH_OBJS@ \ - ${ADAPTATION_LIBS} + @AUTH_OBJS@ if USE_LOADABLE_MODULES squid_SOURCES += $(LOADABLE_MODULES_SOURCES) @@ -960,8 +959,7 @@ @DISK_LINKOBJS@ \ @REPL_OBJS@ \ @AUTH_LINKOBJS@ \ - @AUTH_OBJS@ \ - ${ADAPTATION_LIBS} + @AUTH_OBJS@ nodist_ufsdump_SOURCES = \ repl_modules.cc \ @@ -1515,8 +1513,7 @@ tests_testCacheManager_LDFLAGS = $(LIBADD_DL) tests_testCacheManager_DEPENDENCIES = $(top_builddir)/lib/libmiscutil.a \ @REPL_OBJS@ \ - @SQUID_CPPUNIT_LA@ \ - ${ADAPTATION_LIBS} + @SQUID_CPPUNIT_LA@ tests_testDiskIO_SOURCES= \ $(SWAP_TEST_SOURCES) \ @@ -1689,8 +1686,7 @@ tests_testEvent_LDFLAGS = $(LIBADD_DL) tests_testEvent_DEPENDENCIES = $(top_builddir)/lib/libmiscutil.a \ @REPL_OBJS@ \ - @SQUID_CPPUNIT_LA@ \ - ${ADAPTATION_LIBS} + @SQUID_CPPUNIT_LA@ ## Tests of the EventLoop module. tests_testEventLoop_SOURCES = \ @@ -1847,8 +1843,7 @@ tests_testEventLoop_LDFLAGS = $(LIBADD_DL) tests_testEventLoop_DEPENDENCIES = $(top_builddir)/lib/libmiscutil.a \ @REPL_OBJS@ \ - @SQUID_CPPUNIT_LA@ \ - ${ADAPTATION_LIBS} + @SQUID_CPPUNIT_LA@ tests_test_http_range_SOURCES = \ tests/test_http_range.cc \ @@ -2158,8 +2153,7 @@ tests_testHttpRequest_LDFLAGS = $(LIBADD_DL) tests_testHttpRequest_DEPENDENCIES = $(top_builddir)/lib/libmiscutil.a \ @REPL_OBJS@ \ - @SQUID_CPPUNIT_LA@ \ - ${ADAPTATION_LIBS} + @SQUID_CPPUNIT_LA@ ## Tests of the ICMP base module. # Its used by pinger so SHOULD NOT require more dependancies! :-( @@ -2523,5 +2517,4 @@ tests_testURL_LDFLAGS = $(LIBADD_DL) tests_testURL_DEPENDENCIES = $(top_builddir)/lib/libmiscutil.a \ @REPL_OBJS@ \ - @SQUID_CPPUNIT_LA@ \ - ${ADAPTATION_LIBS} + @SQUID_CPPUNIT_LA@ === modified file 'src/Server.cc' --- src/Server.cc 2008-09-18 02:55:19 +0000 +++ src/Server.cc 2008-09-27 18:33:49 +0000 @@ -66,6 +66,13 @@ ServerStateData::~ServerStateData() { + // paranoid: check that swanSong has been called + assert(!requestBodySource); +#if USE_ADAPTATION + assert(!virginBodyDestination); + assert(!adaptedBodySource); +#endif + entry->unlock(); HTTPMSGUNLOCK(request); @@ -74,19 +81,31 @@ fwd = NULL; // refcounted - if (requestBodySource != NULL) - requestBodySource->clearConsumer(); - -#if USE_ADAPTATION - cleanAdaptation(); -#endif - if (responseBodyBuffer != NULL) { delete responseBodyBuffer; responseBodyBuffer = NULL; } } +void +ServerStateData::swanSong() +{ + // get rid of our piping obligations + if (requestBodySource != NULL) + requestBodySource->clearConsumer(); + +#if USE_ADAPTATION + cleanAdaptation(); +#endif + + BodyConsumer::swanSong(); +#if USE_ADAPTATION + Initiator::swanSong(); + BodyProducer::swanSong(); +#endif +} + + HttpReply * ServerStateData::virginReply() { assert(theVirginReply); === modified file 'src/Server.h' --- src/Server.h 2008-06-20 04:43:01 +0000 +++ src/Server.h 2008-09-27 18:33:49 +0000 @@ -100,6 +100,7 @@ virtual void processReplyBody() = 0; //AsyncJob virtual methods + virtual void swanSong(); virtual bool doneAll() const { return #if USE_ADAPTATION Adaptation::Initiator::doneAll() && === modified file 'src/TextException.cc' --- src/TextException.cc 2007-12-27 05:33:31 +0000 +++ src/TextException.cc 2008-09-28 01:16:18 +0000 @@ -5,11 +5,17 @@ message(xstrdup(aMsg)), theFileName(aFileName), theLineNo(aLineNo) {} -TextException::~TextException() +TextException::~TextException() throw() { xfree(message); } +const char *TextException::what() const throw() +{ + /// \todo add file:lineno + return message ? message : "TextException without a message"; +} + void Throw(const char *message, const char *fileName, int lineNo) { === modified file 'src/TextException.h' --- src/TextException.h 2007-12-27 05:33:31 +0000 +++ src/TextException.h 2008-09-28 01:16:18 +0000 @@ -7,14 +7,14 @@ // simple exception to report custom errors // we may want to change the interface to be able to report system errors -class TextException +class TextException: public std::exception { public: TextException(const char *aMessage, const char *aFileName = 0, int aLineNo = -1); - ~TextException(); + virtual ~TextException() throw(); - // ostream &print(ostream &os) const; + virtual const char *what() const throw(); public: char *message; // read-only === modified file 'src/adaptation/Config.cc' --- src/adaptation/Config.cc 2008-04-04 05:31:40 +0000 +++ src/adaptation/Config.cc 2008-05-08 20:34:13 +0000 @@ -81,6 +81,12 @@ const Vector &configs = serviceConfigs; debugs(93,3, "Found " << configs.size() << " service configs."); for (VISCI i = configs.begin(); i != configs.end(); ++i) { + const ServiceConfig &cfg = **i; + if (FindService(cfg.key) != NULL) { + debugs(93,0, "ERROR: Duplicate adaptation service name: " << + cfg.key); + continue; // TODO: make fatal + } ServicePointer s = createService(**i); if (s != NULL) AllServices().push_back(s); === modified file 'src/adaptation/Config.h' --- src/adaptation/Config.h 2008-04-04 05:31:40 +0000 +++ src/adaptation/Config.h 2008-05-08 20:08:51 +0000 @@ -57,7 +57,7 @@ ServicePointer findService(const String&); Class * findClass(const String& key); - void finalize(); + virtual void finalize(); private: Config(const Config &); // unsupported === modified file 'src/adaptation/Initiate.cc' --- src/adaptation/Initiate.cc 2008-04-05 05:16:03 +0000 +++ src/adaptation/Initiate.cc 2008-09-27 18:09:04 +0000 @@ -39,7 +39,9 @@ Adaptation::Initiate::~Initiate() { - assert(!theInitiator); + // TODO: we cannot assert(!theInitiator) because that fails if a child + // constructor fails. AsyncJob should have wasStarted flag so that we + // can assert(!(wasStarted && theInitiator)). } // internal cleanup @@ -89,7 +91,7 @@ } const char *Adaptation::Initiate::status() const { - return ""; // for now + return AsyncJob::status(); // for now } === modified file 'src/adaptation/Makefile.am' --- src/adaptation/Makefile.am 2008-07-13 21:40:50 +0000 +++ src/adaptation/Makefile.am 2008-09-27 18:33:49 +0000 @@ -22,6 +22,8 @@ Initiate.h \ Initiator.cc \ Initiator.h \ + Message.cc \ + Message.h \ Service.cc \ Service.h \ ServiceConfig.cc \ === added file 'src/adaptation/Message.cc' --- src/adaptation/Message.cc 1970-01-01 00:00:00 +0000 +++ src/adaptation/Message.cc 2008-05-16 00:31:16 +0000 @@ -0,0 +1,57 @@ +/* + * DEBUG: section XXX + */ + +#include "squid.h" +#include "HttpMsg.h" +#include "TextException.h" +#include "adaptation/Message.h" + +Adaptation::Message::Message(): header(NULL) +{ +} + +Adaptation::Message::Message(Header *aHeader): header(NULL) +{ + set(aHeader); +} + +Adaptation::Message::~Message() +{ + clear(); +} + +void +Adaptation::Message::clear() +{ + HTTPMSGUNLOCK(header); + body_pipe = NULL; +} + +void +Adaptation::Message::set(Header *aHeader) +{ + clear(); + if (aHeader) { + header = HTTPMSGLOCK(aHeader); + body_pipe = header->body_pipe; + } +} + +void +Adaptation::Message::ShortCircuit(Message &src, Message &dest) +{ + Must(!dest.header); // the message is not "used" + Must(!dest.body_pipe); // can relax if needed, but need !body_pipe->used() + Must(src.header); // or there is nothing to shortcircuit + + if (src.header->body_pipe != NULL) { + // check that it would not be too late to shortcircuit the pipe + Must(!src.header->body_pipe->consumedSize()); + src.header->body_pipe->clearConsumer(); // if any + // note: current header->body_pipe producer may later become + // dest.body_pipe consumer and consume its own data + // TODO: consumer should detect and bypass short-circuit adaptation + } + dest.set(src.header->clone()); +} === added file 'src/adaptation/Message.h' --- src/adaptation/Message.h 1970-01-01 00:00:00 +0000 +++ src/adaptation/Message.h 2008-09-29 08:25:20 +0000 @@ -0,0 +1,53 @@ + +/* + * $Id$ + */ + +#ifndef SQUID__ADAPTATION__MESSAGE_H +#define SQUID__ADAPTATION__MESSAGE_H + +#include "RefCount.h" + +class HttpMsg; +class BodyPipe; +typedef RefCount BodyPipePointer; + +namespace Adaptation { + +// Manages the header and the body of an HTTP message being worked on. +// Adaptation transactions use this class for virgin and adapted HTTP messages. +// TODO: remove this class after adding refcounted message pointers and +// after making sure nobody abruptly clears the HttpMsg::body_pipe pointer. +class Message +{ + +public: + typedef HttpMsg Header; + + Message(); + Message(Header *aHeader); + ~Message(); + + void clear(); + void set(Header *aHeader); + + static void ShortCircuit(Message &src, Message &dest); + +public: + // virgin or adapted message being worked on + Header *header; // parsed HTTP status/request line and headers + + /// Copy of header->body_pipe, in case somebody moves the original. + /// \todo Find and fix the code that moves (if any) and remove this. + BodyPipePointer body_pipe; + +private: + Message(const Message &); // not implemented + Message &operator =(const Message &); // not implemented +}; + +} // namespace Adaptation; + +// TODO: replace ICAPInOut with Adaptation::Message (adding one for "cause") + +#endif /* SQUID__ADAPTATION__MESSAGE_H */ === modified file 'src/adaptation/Service.cc' --- src/adaptation/Service.cc 2008-04-03 23:10:04 +0000 +++ src/adaptation/Service.cc 2008-05-08 20:15:25 +0000 @@ -18,6 +18,11 @@ { } +bool Adaptation::Service::broken() const +{ + return probed() && !up(); +} + Adaptation::Services & Adaptation::AllServices() { === modified file 'src/adaptation/Service.h' --- src/adaptation/Service.h 2008-04-03 05:31:29 +0000 +++ src/adaptation/Service.h 2008-05-08 20:15:25 +0000 @@ -30,7 +30,7 @@ virtual void invalidate() = 0; virtual bool probed() const = 0; // see comments above - virtual bool broken() const = 0; // see comments above + virtual bool broken() const; virtual bool up() const = 0; // see comments above virtual Initiate *makeXactLauncher(Initiator *, HttpMsg *virginHeader, HttpRequest *virginCause) = 0; === modified file 'src/adaptation/forward.h' --- src/adaptation/forward.h 2008-04-03 05:31:29 +0000 +++ src/adaptation/forward.h 2008-05-08 20:16:36 +0000 @@ -21,6 +21,7 @@ class AccessCheck; class AccessRule; class ServiceGroup; +class Message; typedef RefCount ServicePointer; === modified file 'src/cache_cf.cc' --- src/cache_cf.cc 2008-09-23 23:53:34 +0000 +++ src/cache_cf.cc 2008-09-29 07:45:11 +0000 @@ -64,10 +64,7 @@ #include "adaptation/Config.h" static void parse_adaptation_service_set_type(); - static void parse_adaptation_access_type(); -static void dump_adaptation_access_type(StoreEntry *, const char *); -static void free_adaptation_access_type(); #endif @@ -78,12 +75,15 @@ static void dump_icap_service_type(StoreEntry *, const char *, const ICAPConfig &); static void free_icap_service_type(ICAPConfig *); static void parse_icap_class_type(ICAPConfig *); -static void dump_icap_class_type(StoreEntry *, const char *, const ICAPConfig &); -static void free_icap_class_type(ICAPConfig *); static void parse_icap_access_type(ICAPConfig *); -static void dump_icap_access_type(StoreEntry *, const char *, const ICAPConfig &); -static void free_icap_access_type(ICAPConfig *); - + +#endif + +#if USE_ECAP +#include "eCAP/Config.h" +static void parse_ecap_service_type(Ecap::Config *); +static void dump_ecap_service_type(StoreEntry *, const char *, const Ecap::Config &); +static void free_ecap_service_type(Ecap::Config *); #endif CBDATA_TYPE(peer); @@ -3496,18 +3496,6 @@ Adaptation::Config::ParseAccess(LegacyParser); } -static void -free_adaptation_access_type() -{ - Adaptation::Config::FreeAccess(); -} - -static void -dump_adaptation_access_type(StoreEntry * entry, const char *name) -{ - Adaptation::Config::DumpAccess(entry, name); -} - #endif /* USE_ADAPTATION */ @@ -3540,35 +3528,34 @@ } static void -free_icap_class_type(ICAPConfig *) -{ - Adaptation::Config::FreeServiceSet(); -} - -static void -dump_icap_class_type(StoreEntry * entry, const char *name, const ICAPConfig &) -{ - Adaptation::Config::DumpServiceSet(entry, name); -} - -static void parse_icap_access_type(ICAPConfig *) { debugs(93, 0, "WARNING: 'icap_access' is depricated. " << "Use 'adaptation_access' instead"); - parse_adaptation_access_type(); -} - -static void -free_icap_access_type(ICAPConfig *) -{ - free_adaptation_access_type(); -} - -static void -dump_icap_access_type(StoreEntry * entry, const char *name, const ICAPConfig &) -{ - dump_adaptation_access_type(entry, name); + Adaptation::Config::ParseAccess(LegacyParser); } #endif + + +#if USE_ECAP + +static void +parse_ecap_service_type(Ecap::Config * cfg) +{ + cfg->parseService(); +} + +static void +free_ecap_service_type(Ecap::Config * cfg) +{ + cfg->freeService(); +} + +static void +dump_ecap_service_type(StoreEntry * entry, const char *name, const Ecap::Config &cfg) +{ + cfg.dumpService(entry, name); +} + +#endif /* USE_ECAP */ === modified file 'src/cf.data.depend' --- src/cf.data.depend 2008-09-12 08:14:32 +0000 +++ src/cf.data.depend 2008-09-27 18:33:49 +0000 @@ -30,6 +30,7 @@ icap_access_type icap_class acl icap_class_type icap_service icap_service_type +ecap_service_type int kb_int64_t kb_size_t === modified file 'src/cf.data.pre' --- src/cf.data.pre 2008-09-25 13:20:12 +0000 +++ src/cf.data.pre 2008-09-29 06:42:09 +0000 @@ -5271,7 +5271,7 @@ NAME: icap_class TYPE: icap_class_type IFDEF: ICAP_CLIENT -LOC: TheICAPConfig +LOC: none DEFAULT: none DOC_START This depricated option was documented to define an ICAP service @@ -5288,7 +5288,7 @@ NAME: icap_access TYPE: icap_access_type IFDEF: ICAP_CLIENT -LOC: TheICAPConfig +LOC: none DEFAULT: none DOC_START This option is depricated. Please use adaptation_access, which @@ -5301,6 +5301,45 @@ ----------------------------------------------------------------------------- COMMENT_END +NAME: ecap_enable +TYPE: onoff +IFDEF: USE_ECAP +COMMENT: on|off +LOC: Ecap::TheConfig.onoff +DEFAULT: off +DOC_START + Controls whether eCAP support is enabled. +DOC_END + +NAME: ecap_service +TYPE: ecap_service_type +IFDEF: USE_ECAP +LOC: Ecap::TheConfig +DEFAULT: none +DOC_START + Defines a single eCAP service + + ecap_service servicename vectoring_point bypass service_url + + vectoring_point = reqmod_precache|reqmod_postcache|respmod_precache|respmod_postcache + This specifies at which point of transaction processing the + eCAP service should be activated. *_postcache vectoring points + are not yet supported. + bypass = 1|0 + If set to 1, the eCAP service is treated as optional. If the + service cannot be reached or malfunctions, Squid will try to + ignore any errors and process the message as if the service + was not enabled. No all eCAP errors can be bypassed. + If set to 0, the eCAP service is treated as essential and all + eCAP errors will result in an error page returned to the + HTTP client. + service_url = ecap://vendor/service_name?custom&cgi=style¶meters=optional + +Example: +ecap_service service_1 reqmod_precache 0 ecap://filters-R-us/leakDetector?on_error=block +ecap_service service_2 respmod_precache 1 icap://filters-R-us/virusFilter?config=/etc/vf.cfg +DOC_END + NAME: loadable_modules TYPE: wordlist IFDEF: USE_LOADABLE_MODULES === added file 'src/eCAP/Config.cc' --- src/eCAP/Config.cc 1970-01-01 00:00:00 +0000 +++ src/eCAP/Config.cc 2008-09-29 05:46:28 +0000 @@ -0,0 +1,36 @@ + +/* + * $Id$ + */ + +#include "squid.h" + +#include +#include "eCAP/Host.h" +#include "eCAP/ServiceRep.h" +#include "eCAP/Config.h" + +Ecap::Config Ecap::TheConfig; + +Ecap::Config::Config() +{ +} + +Ecap::Config::~Config() +{ +} + +void +Ecap::Config::finalize() { + Adaptation::Config::finalize(); + libecap::shared_ptr host(new Ecap::Host); + libecap::RegisterHost(host); +} + +Adaptation::ServicePointer +Ecap::Config::createService(const Adaptation::ServiceConfig &cfg) +{ + Adaptation::ServicePointer s = new Ecap::ServiceRep(cfg); + return s.getRaw(); +} + === added file 'src/eCAP/Config.h' --- src/eCAP/Config.h 1970-01-01 00:00:00 +0000 +++ src/eCAP/Config.h 2008-05-08 20:28:58 +0000 @@ -0,0 +1,34 @@ + +/* + * $Id$ + * + */ + +#ifndef SQUID_ECAP_CONFIG_H +#define SQUID_ECAP_CONFIG_H + +#include "adaptation/Config.h" + +namespace Ecap { + +class Config: public Adaptation::Config +{ + +public: + Config(); + ~Config(); + + virtual void finalize(); + +private: + Config(const Config &); // not implemented + Config &operator =(const Config &); // not implemented + + virtual Adaptation::ServicePointer createService(const Adaptation::ServiceConfig &cfg); +}; + +extern Config TheConfig; + +} // namespace Ecap + +#endif /* SQUID_ECAP_CONFIG_H */ === added file 'src/eCAP/Host.cc' --- src/eCAP/Host.cc 1970-01-01 00:00:00 +0000 +++ src/eCAP/Host.cc 2008-05-16 00:33:20 +0000 @@ -0,0 +1,106 @@ +#include "squid.h" +#include +#include +#include "TextException.h" +#include "eCAP/ServiceRep.h" +#include "eCAP/Host.h" + +const libecap::Name Ecap::protocolInternal("internal", libecap::Name::NextId()); +const libecap::Name Ecap::protocolCacheObj("cache_object", libecap::Name::NextId()); +const libecap::Name Ecap::protocolIcp("ICP", libecap::Name::NextId()); +#if USE_HTCP +const libecap::Name Ecap::protocolHtcp("Htcp", libecap::Name::NextId()); +#endif + +Ecap::Host::Host() +{ + // assign our host-specific IDs to well-known names + libecap::headerReferer.assignHostId(HDR_REFERER); + + libecap::protocolHttp.assignHostId(PROTO_HTTP); + libecap::protocolHttps.assignHostId(PROTO_HTTPS); + libecap::protocolFtp.assignHostId(PROTO_FTP); + libecap::protocolGopher.assignHostId(PROTO_GOPHER); + libecap::protocolWais.assignHostId(PROTO_WAIS); + libecap::protocolUrn.assignHostId(PROTO_URN); + libecap::protocolWhois.assignHostId(PROTO_WHOIS); + protocolInternal.assignHostId(PROTO_INTERNAL); + protocolCacheObj.assignHostId(PROTO_CACHEOBJ); + protocolIcp.assignHostId(PROTO_ICP); +#if USE_HTCP + protocolHtcp.assignHostId(PROTO_HTCP); +#endif +} + +std::string +Ecap::Host::uri() const +{ + return "ecap://squid-cache.org/ecap/hosts/squid"; +} + +void +Ecap::Host::describe(std::ostream &os) const +{ + os << PACKAGE_NAME << " v" << PACKAGE_VERSION; +} + +void +Ecap::Host::noteService(const libecap::weak_ptr &weak) +{ + // Many ecap_service lines may use the same service URI. Find each + // matching service rep, make sure it is an eCAP rep, + // and update it with the actual eCAP service. + int found = 0; + + libecap::shared_ptr shared(weak); + typedef Adaptation::Services::iterator SI; + for (SI i = Adaptation::AllServices().begin(); i != Adaptation::AllServices().end(); ++i) { + if ((*i)->cfg().uri == shared->uri().c_str()) { + ServiceRep *rep = dynamic_cast(i->getRaw()); + Must(rep); + rep->noteService(shared); + ++found; + } + } + + debugs(93,5, "Found " << found << " ecap_service configs for " << + shared->uri()); + if (!found) { + debugs(93,1, "Warning: ignoring loaded eCAP module service without " << + "a matching ecap_service configuration: " << shared->uri()); + } +} + +static int +SquidLogLevel(libecap::LogVerbosity lv) +{ + if (lv.critical()) + return DBG_CRITICAL; // is it a good idea to ignore other flags? + + if (lv.large()) + return DBG_DATA; // is it a good idea to ignore other flags? + + if (lv.application()) + return DBG_DATA; // is it a good idea to ignore other flags? + + return 2 + 2*lv.debugging() + 3*lv.operation() + 2*lv.xaction(); +} + +std::ostream * +Ecap::Host::openDebug(libecap::LogVerbosity lv) +{ + const int squidLevel = SquidLogLevel(lv); + const int squidSection = 93; // XXX: this should be a global constant + // XXX: Debug.h should provide this to us + if ((Debug::level = squidLevel) <= Debug::Levels[squidSection]) + return &Debug::getDebugOut(); + else + return NULL; +} + +void +Ecap::Host::closeDebug(std::ostream *debug) +{ + if (debug) + Debug::finishDebug(); +} === added file 'src/eCAP/Host.h' --- src/eCAP/Host.h 1970-01-01 00:00:00 +0000 +++ src/eCAP/Host.h 2008-05-16 00:33:20 +0000 @@ -0,0 +1,40 @@ + +/* + * $Id$ + */ + +#ifndef SQUID_ECAP_HOST_H +#define SQUID_ECAP_HOST_H + +#include + +namespace Ecap { + +// Squid wrapper, providing host application functionality to eCAP services. +class Host : public libecap::host::Host +{ +public: + Host(); + + // About + virtual std::string uri() const; // unique across all vendors + virtual void describe(std::ostream &os) const; // free-format info + + // Service management + virtual void noteService(const libecap::weak_ptr &s); + + // Logging + virtual std::ostream *openDebug(libecap::LogVerbosity lv); + virtual void closeDebug(std::ostream *debug); +}; + +extern const libecap::Name protocolInternal; +extern const libecap::Name protocolCacheObj; +extern const libecap::Name protocolIcp; +#if USE_HTCP +extern const libecap::Name protocolHtcp; +#endif + +} // namespace Ecap + +#endif /* SQUID_ECAP_HOST_H */ === modified file 'src/eCAP/Makefile.am' --- src/eCAP/Makefile.am 2008-04-05 05:24:42 +0000 +++ src/eCAP/Makefile.am 2008-05-08 21:02:24 +0000 @@ -9,18 +9,18 @@ noinst_LTLIBRARIES = libeCAP.la libeCAP_la_SOURCES = \ + Config.h \ + Config.cc \ + Host.h \ + Host.cc \ + MessageRep.h \ + MessageRep.cc \ + ServiceRep.h \ + ServiceRep.cc \ + XactionRep.h \ + XactionRep.cc \ + \ Registry.h INCLUDES = -I. -I$(top_builddir)/include -I$(top_srcdir)/include \ -I$(top_srcdir)/src - - -# Sample adapter section. - -EXTRA_DIST = \ - MinimalAdapter.cc - -lib_LTLIBRARIES = MinimalAdapter.la -MinimalAdapter_la_SOURCES = MinimalAdapter.cc -MinimalAdapter_la_LDFLAGS = -module -avoid-version -MinimalAdapter_la_LIBADD = ./libeCAP.la === added file 'src/eCAP/MessageRep.cc' --- src/eCAP/MessageRep.cc 1970-01-01 00:00:00 +0000 +++ src/eCAP/MessageRep.cc 2008-09-29 06:03:57 +0000 @@ -0,0 +1,436 @@ +/* + * DEBUG: section XXX + */ + +#include "squid.h" +#include "HttpRequest.h" +#include "HttpReply.h" +#include "BodyPipe.h" +#include "TextException.h" +#include "adaptation/Message.h" +#include +#include +#include +#include "eCAP/MessageRep.h" +#include "eCAP/XactionRep.h" +#include "eCAP/Host.h" /* for protocol constants */ + +/* HeaderRep */ + +Ecap::HeaderRep::HeaderRep(HttpMsg &aMessage): theHeader(aMessage.header), + theMessage(aMessage) +{ +} + +bool +Ecap::HeaderRep::hasAny(const Name &name) const +{ + const http_hdr_type squidId = TranslateHeaderId(name); + // XXX: optimize to remove getByName: we do not need the value here + return squidId == HDR_OTHER ? + theHeader.getByName(name.image().c_str()).size() > 0: + (bool)theHeader.has(squidId); +} + +Ecap::HeaderRep::Value +Ecap::HeaderRep::value(const Name &name) const +{ + const http_hdr_type squidId = TranslateHeaderId(name); + const String value = squidId == HDR_OTHER ? + theHeader.getByName(name.image().c_str()) : + theHeader.getStrOrList(squidId); + return Value::FromTempString(value.buf()); +} + +void +Ecap::HeaderRep::add(const Name &name, const Value &value) +{ + const http_hdr_type squidId = TranslateHeaderId(name); // HDR_OTHER OK + HttpHeaderEntry *e = new HttpHeaderEntry(squidId, name.image().c_str(), + value.toString().c_str()); + theHeader.addEntry(e); +} + +void +Ecap::HeaderRep::removeAny(const Name &name) +{ + const http_hdr_type squidId = TranslateHeaderId(name); + if (squidId == HDR_OTHER) + theHeader.delByName(name.image().c_str()); + else + theHeader.delById(squidId); +} + +libecap::Area +Ecap::HeaderRep::image() const +{ + MemBuf mb; + mb.init(); + + Packer p; + packerToMemInit(&p, &mb); + theMessage.packInto(&p, true); + packerClean(&p); + return Area::FromTempBuffer(mb.content(), mb.contentSize()); +} + +// throws on failures +void +Ecap::HeaderRep::parse(const Area &buf) +{ + MemBuf mb; + mb.init(); + mb.append(buf.start, buf.size); + http_status error; + Must(theMessage.parse(&mb, true, &error)); +} + +http_hdr_type +Ecap::HeaderRep::TranslateHeaderId(const Name &name) +{ + if (name.assignedHostId()) + return static_cast(name.hostId()); + return HDR_OTHER; +} + + +/* FirstLineRep */ + +Ecap::FirstLineRep::FirstLineRep(HttpMsg &aMessage): theMessage(aMessage) +{ +} + +libecap::Version +Ecap::FirstLineRep::version() const +{ + return libecap::Version(theMessage.http_ver.major, + theMessage.http_ver.minor); +} + +void +Ecap::FirstLineRep::version(const libecap::Version &aVersion) +{ + theMessage.http_ver.major = aVersion.majr; + theMessage.http_ver.minor = aVersion.minr; +} + +libecap::Name +Ecap::FirstLineRep::protocol() const +{ + // TODO: optimize? + switch (theMessage.protocol) { + case PROTO_HTTP: return libecap::protocolHttp; + case PROTO_HTTPS: return libecap::protocolHttps; + case PROTO_FTP: return libecap::protocolFtp; + case PROTO_GOPHER: return libecap::protocolGopher; + case PROTO_WAIS: return libecap::protocolWais; + case PROTO_WHOIS: return libecap::protocolWhois; + case PROTO_URN: return libecap::protocolUrn; + case PROTO_ICP: return protocolIcp; +#if USE_HTCP + case PROTO_HTCP: return protocolHtcp; +#endif + case PROTO_CACHEOBJ: return protocolCacheObj; + case PROTO_INTERNAL: return protocolInternal; + case PROTO_NONE: return Name(); + + case PROTO_MAX: break; // should not happen + // no default to catch PROTO_ additions + } + Must(false); // not reached + return Name(); +} + +void +Ecap::FirstLineRep::protocol(const Name &p) +{ + // TODO: what happens if we fail to translate some protocol? + theMessage.protocol = TranslateProtocolId(p); +} + +protocol_t +Ecap::FirstLineRep::TranslateProtocolId(const Name &name) +{ + if (name.assignedHostId()) + return static_cast(name.hostId()); + return PROTO_NONE; // no PROTO_OTHER +} + + +/* RequestHeaderRep */ + +Ecap::RequestLineRep::RequestLineRep(HttpRequest &aMessage): + FirstLineRep(aMessage), theMessage(aMessage) +{ +} + +void +Ecap::RequestLineRep::uri(const Area &aUri) +{ + // TODO: if method is not set, urlPath will assume it is not connect; + // Can we change urlParse API to remove the method parameter? + // TODO: optimize: urlPath should take constant URL buffer + char *buf = xstrdup(aUri.toString().c_str()); + const bool ok = urlParse(theMessage.method, buf, &theMessage); + xfree(buf); + Must(ok); +} + +Ecap::RequestLineRep::Area +Ecap::RequestLineRep::uri() const +{ + return Area::FromTempBuffer(theMessage.urlpath.buf(), + theMessage.urlpath.size()); +} + +void +Ecap::RequestLineRep::method(const Name &aMethod) +{ + if (aMethod.assignedHostId()) { + const int id = aMethod.hostId(); + Must(METHOD_NONE < id && id < METHOD_ENUM_END); + Must(id != METHOD_OTHER); + theMessage.method = HttpRequestMethod(static_cast<_method_t>(id)); + } else { + const std::string &image = aMethod.image(); + theMessage.method = HttpRequestMethod(image.data(), + image.data() + image.size()); + } +} + +Ecap::RequestLineRep::Name +Ecap::RequestLineRep::method() const +{ + switch (theMessage.method.id()) { + case METHOD_GET: return libecap::methodGet; + case METHOD_POST: return libecap::methodPost; + case METHOD_PUT: return libecap::methodPut; + case METHOD_HEAD: return libecap::methodHead; + case METHOD_CONNECT: return libecap::methodConnect; + case METHOD_DELETE: return libecap::methodDelete; + case METHOD_TRACE: return libecap::methodTrace; + default: return Name(theMessage.method.image()); + } +} + +libecap::Version +Ecap::RequestLineRep::version() const +{ + return FirstLineRep::version(); +} + +void +Ecap::RequestLineRep::version(const libecap::Version &aVersion) +{ + FirstLineRep::version(aVersion); +} + +libecap::Name +Ecap::RequestLineRep::protocol() const +{ + return FirstLineRep::protocol(); +} + +void +Ecap::RequestLineRep::protocol(const Name &p) +{ + FirstLineRep::protocol(p); +} + + +/* ReplyHeaderRep */ + +Ecap::StatusLineRep::StatusLineRep(HttpReply &aMessage): + FirstLineRep(aMessage), theMessage(aMessage) +{ +} + +void +Ecap::StatusLineRep::statusCode(int code) +{ + // TODO: why is .status a enum? Do we not support unknown statuses? + theMessage.sline.status = static_cast(code); +} + +int +Ecap::StatusLineRep::statusCode() const +{ + // TODO: see statusCode(code) TODO above + return static_cast(theMessage.sline.status); +} + +void +Ecap::StatusLineRep::reasonPhrase(const Area &) +{ + // Squid does not support custom reason phrases + theMessage.sline.reason = NULL; +} + +Ecap::StatusLineRep::Area +Ecap::StatusLineRep::reasonPhrase() const +{ + return theMessage.sline.reason ? + Area::FromTempString(std::string(theMessage.sline.reason)) : Area(); +} + +libecap::Version +Ecap::StatusLineRep::version() const +{ + return FirstLineRep::version(); +} + +void +Ecap::StatusLineRep::version(const libecap::Version &aVersion) +{ + FirstLineRep::version(aVersion); +} + +libecap::Name +Ecap::StatusLineRep::protocol() const +{ + return FirstLineRep::protocol(); +} + +void +Ecap::StatusLineRep::protocol(const Name &p) +{ + FirstLineRep::protocol(p); +} + +/* BodyRep */ + +Ecap::BodyRep::BodyRep(const BodyPipe::Pointer &aBody): theBody(aBody) +{ +} + +void +Ecap::BodyRep::tie(const BodyPipe::Pointer &aBody) +{ + Must(!theBody); + Must(aBody != NULL); + theBody = aBody; +} + +Ecap::BodyRep::BodySize +Ecap::BodyRep::bodySize() const +{ + return !theBody ? BodySize() : BodySize(theBody->bodySize()); +} + +Ecap::BodyRep::size_type +Ecap::BodyRep::consumedSize() const +{ + return theBody->consumedSize(); +} + +bool +Ecap::BodyRep::productionEnded() const +{ + return theBody->productionEnded(); +} + +Ecap::BodyRep::Area +Ecap::BodyRep::prefix(Ecap::BodyRep::size_type size) const +{ + Must(size <= static_cast(theBody->buf().contentSize())); + // XXX: optimize by making theBody a shared_ptr (see FromTemp*() src) + return Area::FromTempBuffer(theBody->buf().content(), size); +} + + +/* MessageRep */ + +Ecap::MessageRep::MessageRep(HttpMsg *rawHeader): + theMessage(rawHeader), theFirstLineRep(NULL), + theHeaderRep(NULL), theBodyRep(NULL) +{ + Must(theMessage.header); // we do not want to represent a missing message + + if (HttpRequest *req = dynamic_cast(theMessage.header)) + theFirstLineRep = new RequestLineRep(*req); + else + if (HttpReply *rep = dynamic_cast(theMessage.header)) + theFirstLineRep = new StatusLineRep(*rep); + else + Must(false); // unknown message header type + + theHeaderRep = new HeaderRep(*theMessage.header); + + if (theMessage.body_pipe != NULL) + theBodyRep = new BodyRep(theMessage.body_pipe); +} + +Ecap::MessageRep::~MessageRep() +{ + delete theBodyRep; + delete theHeaderRep; + delete theFirstLineRep; +} + +libecap::shared_ptr +Ecap::MessageRep::clone() const +{ + HttpMsg *hdr = theMessage.header->clone(); + hdr->body_pipe = NULL; // if any; TODO: remove pipe cloning from ::clone? + libecap::shared_ptr res(new MessageRep(hdr)); + + // restore indication of a body if needed, but not the pipe + if (theMessage.header->body_pipe != NULL) + res->addBody(); + + return res; +} + +libecap::FirstLine & +Ecap::MessageRep::firstLine() +{ + return *theFirstLineRep; +} + +const libecap::FirstLine & +Ecap::MessageRep::firstLine() const +{ + return *theFirstLineRep; +} + +libecap::Header & +Ecap::MessageRep::header() +{ + return *theHeaderRep; +} + +const libecap::Header & +Ecap::MessageRep::header() const +{ + return *theHeaderRep; +} + +libecap::Body * +Ecap::MessageRep::body() +{ + return theBodyRep; +} + +void +Ecap::MessageRep::addBody() +{ + Must(!theBodyRep); + Must(!theMessage.body_pipe); // set in tieBody() + theBodyRep = new BodyRep(NULL); +} + +void +Ecap::MessageRep::tieBody(Ecap::XactionRep *x) +{ + Must(theBodyRep != NULL); // addBody must be called first + Must(!theMessage.header->body_pipe); + Must(!theMessage.body_pipe); + theMessage.header->body_pipe = new BodyPipe(x); + theMessage.body_pipe = theMessage.header->body_pipe; + theBodyRep->tie(theMessage.body_pipe); +} + +const libecap::Body *Ecap::MessageRep::body() const +{ + return theBodyRep; +} === added file 'src/eCAP/MessageRep.h' --- src/eCAP/MessageRep.h 1970-01-01 00:00:00 +0000 +++ src/eCAP/MessageRep.h 2008-09-29 06:03:57 +0000 @@ -0,0 +1,173 @@ + +/* + * $Id$ + */ + +#ifndef SQUID__ECAP__MESSAGE_REP_H +#define SQUID__ECAP__MESSAGE_REP_H + +#include "adaptation/forward.h" +#include +#include +#include + +namespace Ecap { + +class XactionRep; + +// Translates Squid HttpMsg into libecap::Header. +class HeaderRep: public libecap::Header +{ +public: + typedef libecap::Name Name; + typedef libecap::Area Area; + +public: + HeaderRep(HttpMsg &aMessage); + + virtual bool hasAny(const Name &name) const; + virtual Value value(const Name &name) const; + + virtual void add(const Name &name, const Value &value); + virtual void removeAny(const Name &name); + + virtual Area image() const; + virtual void parse(const Area &buf); // throws on failures + +protected: + static http_hdr_type TranslateHeaderId(const Name &name); + +private: + HttpHeader &theHeader; // the header being translated to libecap + HttpMsg &theMessage; // the message being translated to libecap +}; + + +// Helps translate Squid HttpMsg into libecap::FirstLine (see children). +class FirstLineRep +{ +public: + typedef libecap::Name Name; + +public: + FirstLineRep(HttpMsg &aMessage); + + libecap::Version version() const; + void version(const libecap::Version &aVersion); + Name protocol() const; + void protocol(const Name &aProtocol); + +protected: + static protocol_t TranslateProtocolId(const Name &name); + +private: + HttpMsg &theMessage; // the message which first line is being translated +}; + +// Translates Squid HttpRequest into libecap::RequestLine. +class RequestLineRep: public libecap::RequestLine, public FirstLineRep +{ +public: +// typedef libecap::Name Name; + typedef libecap::Area Area; + +public: + RequestLineRep(HttpRequest &aMessage); + + virtual void uri(const Area &aUri); + virtual Area uri() const; + + virtual void method(const Name &aMethod); + virtual Name method() const; + + virtual libecap::Version version() const; + virtual void version(const libecap::Version &aVersion); + virtual Name protocol() const; + virtual void protocol(const Name &aProtocol); + +private: + HttpRequest &theMessage; // the request header being translated to libecap +}; + +// Translates Squid HttpReply into libecap::StatusLine. +class StatusLineRep: public libecap::StatusLine, public FirstLineRep +{ +public: + typedef libecap::Name Name; + typedef libecap::Area Area; + +public: + StatusLineRep(HttpReply &aMessage); + + virtual void statusCode(int code); + virtual int statusCode() const; + + virtual void reasonPhrase(const Area &phrase); + virtual Area reasonPhrase() const; + + virtual libecap::Version version() const; + virtual void version(const libecap::Version &aVersion); + virtual Name protocol() const; + virtual void protocol(const Name &aProtocol); + +private: + HttpReply &theMessage; // the request header being translated to libecap +}; + + +// Translates Squid BodyPipe into libecap::Body. +class BodyRep: public libecap::Body +{ +public: + typedef libecap::Area Area; + typedef libecap::BodySize BodySize; + using libecap::Body::size_type; + +public: + BodyRep(const BodyPipe::Pointer &aBody); // using NULL pointer? see tie() + + void tie(const BodyPipe::Pointer &aBody); // late binding if !theBody; + + // libecap::Body API + virtual BodySize bodySize() const; + virtual size_type consumedSize() const; + virtual bool productionEnded() const; + virtual Area prefix(size_type size) const; + +private: + BodyPipe::Pointer theBody; // the body being translated to libecap +}; + +// Translates Squid Adaptation::Message into libecap::Message. +class MessageRep: public libecap::Message +{ +public: + explicit MessageRep(HttpMsg *rawHeader); + virtual ~MessageRep(); + + virtual libecap::shared_ptr clone() const; + + virtual libecap::FirstLine &firstLine(); + virtual const libecap::FirstLine &firstLine() const; + + virtual libecap::Header &header(); + virtual const libecap::Header &header() const; + + virtual void addBody(); + virtual libecap::Body *body(); + virtual const libecap::Body *body() const; + void tieBody(Ecap::XactionRep *x); // to a specific transaction + + Adaptation::Message &raw() { return theMessage; } // for host access + const Adaptation::Message &raw() const { return theMessage; } // for host + +private: + Adaptation::Message theMessage; // the message being translated to libecap + libecap::FirstLine *theFirstLineRep; // request or status line wrapper + HeaderRep *theHeaderRep; // header wrapper + BodyRep *theBodyRep; // body wrapper +}; + +} // namespace Ecap; + +#endif /* SQUID__E_CAP__MESSAGE_REP_H */ === added file 'src/eCAP/ServiceRep.cc' --- src/eCAP/ServiceRep.cc 1970-01-01 00:00:00 +0000 +++ src/eCAP/ServiceRep.cc 2008-05-08 20:28:58 +0000 @@ -0,0 +1,76 @@ +#include "squid.h" +#include +#include "TextException.h" +#include "assert.h" +#include "eCAP/ServiceRep.h" +#include "eCAP/XactionRep.h" + +Ecap::ServiceRep::ServiceRep(const Adaptation::ServiceConfig &cfg): + /*AsyncJob("Ecap::ServiceRep"),*/ Adaptation::Service(cfg) +{ +} + +Ecap::ServiceRep::~ServiceRep() +{ +} + +void Ecap::ServiceRep::noteService(const AdapterService &s) { + Must(s != NULL); + theService = s; + debugs(93,7, "Matched loaded and configured eCAP services: " << + s->uri() << ' ' << cfg().key << "\n"); +} + +void Ecap::ServiceRep::invalidate() { + theService->retire(); + theService.reset(); +} + +void Ecap::ServiceRep::noteFailure() { + assert(false); // XXX: should this be ICAP-specific? +} + +void +Ecap::ServiceRep::finalize() +{ + Adaptation::Service::finalize(); + if (!theService) { + debugs(93,1, "Warning: configured ecap_service was not loaded: " << + cfg().uri); + } +} + +bool Ecap::ServiceRep::probed() const +{ + return true; // we "probe" the adapter in finalize(). +} + +bool Ecap::ServiceRep::up() const +{ + return theService != NULL; +} + +bool Ecap::ServiceRep::wantsUrl(const String &urlPath) const +{ + Must(up()); + return theService->wantsUrl(urlPath.buf()); +} + +Adaptation::Initiate * +Ecap::ServiceRep::makeXactLauncher(Adaptation::Initiator *initiator, + HttpMsg *virgin, HttpRequest *cause) +{ + Must(up()); + XactionRep *rep = new XactionRep(initiator, virgin, cause, Pointer(this)); + XactionRep::AdapterXaction x(theService->makeXaction(rep)); + rep->master(x); + return rep; +} + +// returns a temporary string depicting service status, for debugging +const char *Ecap::ServiceRep::status() const +{ + assert(false); // move generic stuff from ICAP to Adaptation + // add theService->status()? + return NULL; +} === added file 'src/eCAP/ServiceRep.h' --- src/eCAP/ServiceRep.h 1970-01-01 00:00:00 +0000 +++ src/eCAP/ServiceRep.h 2008-09-29 06:03:57 +0000 @@ -0,0 +1,53 @@ + +/* + * $Id$ + */ + +#ifndef SQUID_ECAP_SERVICE_REP_H +#define SQUID_ECAP_SERVICE_REP_H + +#include "adaptation/Service.h" +#include "adaptation/forward.h" +#include +#include + +namespace Ecap { + +/* The eCAP service representative maintains information about a single eCAP + service that Squid communicates with. One eCAP module may register many + eCAP services. */ + +class ServiceRep : public Adaptation::Service +{ +public: + ServiceRep(const Adaptation::ServiceConfig &config); + virtual ~ServiceRep(); + + typedef libecap::shared_ptr AdapterService; + void noteService(const AdapterService &s); + + virtual void finalize(); + + // call when the service is no longer needed or valid + virtual void invalidate(); + + virtual bool probed() const; + virtual bool up() const; + + Adaptation::Initiate *makeXactLauncher(Adaptation::Initiator *, HttpMsg *virginHeader, HttpRequest *virginCause); + + // the methods below can only be called on an up() service + virtual bool wantsUrl(const String &urlPath) const; + + // called by transactions to report service failure + virtual void noteFailure(); + + virtual const char *status() const; + +private: + AdapterService theService; // the actual adaptation service we represent +}; + +} // namespace Ecap + +#endif /* SQUID_ECAP_SERVICE_REP_H */ === added file 'src/eCAP/XactionRep.cc' --- src/eCAP/XactionRep.cc 1970-01-01 00:00:00 +0000 +++ src/eCAP/XactionRep.cc 2008-09-29 06:03:57 +0000 @@ -0,0 +1,416 @@ +#include "squid.h" +#include +#include +#include +#include "TextException.h" +#include "assert.h" +#include "HttpRequest.h" +#include "HttpReply.h" +#include "eCAP/XactionRep.h" + +// CBDATA_CLASS_INIT(Ecap::XactionRep); +// TODO: add CBDATA_NAMESPACED_CLASS_INIT(namespace, classname) +cbdata_type Ecap::XactionRep::CBDATA_XactionRep = CBDATA_UNKNOWN; + + +Ecap::XactionRep::XactionRep(Adaptation::Initiator *anInitiator, + HttpMsg *virginHeader, HttpRequest *virginCause, + const Adaptation::ServicePointer &aService): + AsyncJob("Ecap::XactionRep"), + Adaptation::Initiate("Ecap::XactionRep", anInitiator, aService), + theVirginRep(virginHeader), theCauseRep(NULL), + proxyingVb(opUndecided), proxyingAb(opUndecided), canAccessVb(false) +{ + if (virginCause) + theCauseRep = new MessageRep(virginCause); +} + +Ecap::XactionRep::~XactionRep() +{ + assert(!theMaster); + delete theCauseRep; + theAnswerRep.reset(); +} + +void +Ecap::XactionRep::master(const AdapterXaction &x) +{ + Must(!theMaster); + Must(x != NULL); + theMaster = x; +} + +void +Ecap::XactionRep::start() +{ + Must(theMaster); + + if (theVirginRep.raw().body_pipe != NULL) + canAccessVb = true; /// assumes nobody is consuming; \todo check + else + proxyingVb = opNever; + + theMaster->start(); +} + +void +Ecap::XactionRep::swanSong() +{ + // clear body_pipes, if any + // this code does not maintain proxying* and canAccessVb states; should it? + + if (theAnswerRep != NULL) { + BodyPipe::Pointer body_pipe = answer().body_pipe; + if (body_pipe != NULL) { + Must(body_pipe->stillProducing(this)); + stopProducingFor(body_pipe, false); + } + } + + { + BodyPipe::Pointer body_pipe = theVirginRep.raw().body_pipe; + if (body_pipe != NULL) { + Must(body_pipe->stillConsuming(this)); + stopConsumingFrom(body_pipe); + } + } + + terminateMaster(); + Adaptation::Initiate::swanSong(); +} + +libecap::Message & +Ecap::XactionRep::virgin() +{ + return theVirginRep; +} + +const libecap::Message & +Ecap::XactionRep::cause() +{ + Must(theCauseRep != NULL); + return *theCauseRep; +} + +libecap::Message & +Ecap::XactionRep::adapted() +{ + Must(theAnswerRep != NULL); + return *theAnswerRep; +} + +Adaptation::Message & +Ecap::XactionRep::answer() +{ + MessageRep *rep = dynamic_cast(theAnswerRep.get()); + Must(rep); + return rep->raw(); +} + +void +Ecap::XactionRep::terminateMaster() +{ + if (theMaster) { + AdapterXaction x = theMaster; + theMaster.reset(); + x->stop(); + } +} + +bool +Ecap::XactionRep::doneAll() const +{ + return proxyingVb >= opComplete && proxyingAb >= opComplete && + Adaptation::Initiate::doneAll(); +} + +// stops receiving virgin and enables auto-consumption +void +Ecap::XactionRep::dropVirgin(const char *reason) +{ + debugs(93,4, HERE << "because " << reason << "; status:" << status()); + Must(proxyingVb = opOn); + + BodyPipePointer &p = theVirginRep.raw().body_pipe; + Must(p != NULL); + Must(p->stillConsuming(this)); + stopConsumingFrom(p); + p->enableAutoConsumption(); + proxyingVb = opComplete; + canAccessVb = false; + + // called from adapter handler so does not inform adapter +} + +void +Ecap::XactionRep::useVirgin() +{ + debugs(93,3, HERE << status()); + Must(proxyingAb == opUndecided); + proxyingAb = opNever; + + BodyPipePointer &vbody_pipe = theVirginRep.raw().body_pipe; + if (proxyingVb == opOn) { + Must(vbody_pipe->stillConsuming(this)); + // if libecap consumed, we cannot shortcircuit + Must(!vbody_pipe->consumedSize()); + stopConsumingFrom(vbody_pipe); + canAccessVb = false; + proxyingVb = opComplete; + } else + if (proxyingVb == opUndecided) + proxyingVb = opNever; + + HttpMsg *clone = theVirginRep.raw().header->clone(); + // check that clone() copies the pipe so that we do not have to + Must(!theVirginRep.raw().header->body_pipe == !clone->body_pipe); + sendAnswer(clone); + Must(done()); +} + +void +Ecap::XactionRep::useAdapted(const libecap::shared_ptr &m) +{ + debugs(93,3, HERE << status()); + Must(m); + theAnswerRep = m; + Must(proxyingAb == opUndecided); + + HttpMsg *msg = answer().header; + if (!theAnswerRep->body()) { // final, bodyless answer + proxyingAb = opNever; + sendAnswer(msg); + } else { // got answer headers but need to handle body + proxyingAb = opOn; + Must(!msg->body_pipe); // only host can set body pipes + MessageRep *rep = dynamic_cast(theAnswerRep.get()); + Must(rep); + rep->tieBody(this); // sets us as a producer + Must(msg->body_pipe != NULL); // check tieBody + + sendAnswer(msg); + + debugs(93,4, HERE << "adapter will produce body" << status()); + theMaster->abMake(); // libecap will produce + } +} + +void +Ecap::XactionRep::vbDiscard() +{ + Must(proxyingVb == opUndecided); + // if adapter does not need vb, we do not need to send it + dropVirgin("vbDiscard"); + Must(proxyingVb == opNever); +} + +void +Ecap::XactionRep::vbMake() +{ + Must(proxyingVb == opUndecided); + BodyPipePointer &p = theVirginRep.raw().body_pipe; + Must(p != NULL); + Must(p->setConsumerIfNotLate(this)); // to make vb, we must receive vb + proxyingVb = opOn; +} + +void +Ecap::XactionRep::vbStopMaking() +{ + // if adapter does not need vb, we do not need to receive it + if (proxyingVb == opOn) + dropVirgin("vbStopMaking"); + Must(proxyingVb == opComplete); +} + +void +Ecap::XactionRep::vbMakeMore() +{ + Must(proxyingVb == opOn); // cannot make more if done proxying + // we cannot guarantee more vb, but we can check that there is a chance + Must(!theVirginRep.raw().body_pipe->exhausted()); +} + +libecap::Area +Ecap::XactionRep::vbContent(libecap::size_type o, libecap::size_type s) +{ + Must(canAccessVb); + // We may not be proxyingVb yet. It should be OK, but see vbContentShift(). + + const BodyPipePointer &p = theVirginRep.raw().body_pipe; + Must(p != NULL); + + // TODO: make MemBuf use size_t? + const size_t haveSize = static_cast(p->buf().contentSize()); + + // convert to Squid types; XXX: check for overflow + const uint64_t offset = static_cast(o); + Must(offset <= haveSize); // equal iff at the end of content + + // nsize means no size limit: all content starting from offset + const size_t size = s == libecap::nsize ? + haveSize - offset : static_cast(s); + + // XXX: optimize by making theBody a shared_ptr (see Area::FromTemp*() src) + return libecap::Area::FromTempBuffer(p->buf().content() + offset, + min(static_cast(haveSize - offset), size)); +} + +void +Ecap::XactionRep::vbContentShift(libecap::size_type n) +{ + Must(canAccessVb); + // We may not be proxyingVb yet. It should be OK now, but if BodyPipe + // consume() requirements change, we would have to return empty vbContent + // until the adapter registers as a consumer + + BodyPipePointer &p = theVirginRep.raw().body_pipe; + Must(p != NULL); + const size_t size = static_cast(n); // XXX: check for overflow + const size_t haveSize = static_cast(p->buf().contentSize()); // TODO: make MemBuf use size_t? + p->consume(min(size, haveSize)); +} + +void +Ecap::XactionRep::noteAbContentDone(bool atEnd) +{ + Must(proxyingAb == opOn); + stopProducingFor(answer().body_pipe, atEnd); + proxyingAb = opComplete; +} + +void +Ecap::XactionRep::noteAbContentAvailable() +{ + Must(proxyingAb == opOn); + moveAbContent(); +} + +#if 0 /* XXX: implement */ +void +Ecap::XactionRep::setAdaptedBodySize(const libecap::BodySize &size) +{ + Must(answer().body_pipe != NULL); + if (size.known()) + answer().body_pipe->setBodySize(size.value()); + // else the piped body size is unknown by default +} +#endif + +void +Ecap::XactionRep::adaptationDelayed(const libecap::Delay &d) +{ + debugs(93,3, HERE << "adapter needs time: " << + d.state << '/' << d.progress); + // XXX: set timeout? +} + +void +Ecap::XactionRep::adaptationAborted() +{ + tellQueryAborted(true); // should eCAP support retries? + mustStop("adaptationAborted"); +} + +bool +Ecap::XactionRep::callable() const +{ + return !done(); +} + +void +Ecap::XactionRep::noteMoreBodySpaceAvailable(RefCount bp) +{ + Must(proxyingAb == opOn); + moveAbContent(); +} + +void +Ecap::XactionRep::noteBodyConsumerAborted(RefCount bp) +{ + Must(proxyingAb == opOn); + stopProducingFor(answer().body_pipe, false); + Must(theMaster); + theMaster->abStopMaking(); + proxyingAb = opComplete; +} + +void +Ecap::XactionRep::noteMoreBodyDataAvailable(RefCount bp) +{ + Must(proxyingVb == opOn); + Must(theMaster); + theMaster->noteVbContentAvailable(); +} + +void +Ecap::XactionRep::noteBodyProductionEnded(RefCount bp) +{ + Must(proxyingVb == opOn); + Must(theMaster); + theMaster->noteVbContentDone(true); + proxyingVb = opComplete; +} + +void +Ecap::XactionRep::noteBodyProducerAborted(RefCount bp) +{ + Must(proxyingVb == opOn); + Must(theMaster); + theMaster->noteVbContentDone(false); + proxyingVb = opComplete; +} + +void +Ecap::XactionRep::noteInitiatorAborted() +{ + mustStop("initiator aborted"); +} + +// get content from the adapter and put it into the adapted pipe +void +Ecap::XactionRep::moveAbContent() +{ + Must(proxyingAb == opOn); + const libecap::Area c = theMaster->abContent(0, libecap::nsize); + debugs(93,5, HERE << " up to " << c.size << " bytes"); + if (const size_t used = answer().body_pipe->putMoreData(c.start, c.size)) + theMaster->abContentShift(used); +} + +const char * +Ecap::XactionRep::status() const +{ + static MemBuf buf; + buf.reset(); + + buf.append(" [", 2); + + if (proxyingVb == opOn) { + const BodyPipePointer &vp = theVirginRep.raw().body_pipe; + if (!canAccessVb) + buf.append("x", 1); + if (vp != NULL && vp->stillConsuming(this)) { + buf.append("Vb", 2); + buf.append(vp->status(), strlen(vp->status())); // XXX + } else + buf.append("V.", 2); + } + + if (proxyingAb == opOn) { + MessageRep *rep = dynamic_cast(theAnswerRep.get()); + Must(rep); + const BodyPipePointer &ap = rep->raw().body_pipe; + if (ap != NULL && ap->stillProducing(this)) { + buf.append(" Ab", 3); + buf.append(ap->status(), strlen(ap->status())); // XXX + } else + buf.append(" A.", 3); + } + + buf.Printf(" ecapx%d]", id); + + buf.terminate(); + + return buf.content(); +} === added file 'src/eCAP/XactionRep.h' --- src/eCAP/XactionRep.h 1970-01-01 00:00:00 +0000 +++ src/eCAP/XactionRep.h 2008-09-29 06:03:57 +0000 @@ -0,0 +1,100 @@ + +/* + * $Id$ + */ + +#ifndef SQUID_ECAP_XACTION_REP_H +#define SQUID_ECAP_XACTION_REP_H + +#include "BodyPipe.h" +#include "adaptation/Initiate.h" +#include "adaptation/Service.h" +#include "adaptation/Message.h" +#include "eCAP/MessageRep.h" +#include +#include +#include +#include + +namespace Ecap { + +/* The eCAP xaction representative maintains information about a single eCAP + xaction that Squid communicates with. One eCAP module may register many + eCAP xactions. */ +class XactionRep : public Adaptation::Initiate, public libecap::host::Xaction, + public BodyConsumer, public BodyProducer +{ +public: + XactionRep(Adaptation::Initiator *anInitiator, HttpMsg *virginHeader, HttpRequest *virginCause, const Adaptation::ServicePointer &service); + virtual ~XactionRep(); + + typedef libecap::shared_ptr AdapterXaction; + void master(const AdapterXaction &aMaster); // establish a link + + // libecap::host::Xaction API + virtual libecap::Message &virgin(); + virtual const libecap::Message &cause(); + virtual libecap::Message &adapted(); + virtual void useVirgin(); + virtual void useAdapted(const libecap::shared_ptr &msg); + virtual void adaptationDelayed(const libecap::Delay &); + virtual void adaptationAborted(); + virtual void vbDiscard(); + virtual void vbMake(); + virtual void vbStopMaking(); + virtual void vbMakeMore(); + virtual libecap::Area vbContent(libecap::size_type offset, libecap::size_type size); + virtual void vbContentShift(libecap::size_type size); + virtual void noteAbContentDone(bool atEnd); + virtual void noteAbContentAvailable(); + + // libecap::Callable API, via libecap::host::Xaction + virtual bool callable() const; + + // BodyProducer API + virtual void noteMoreBodySpaceAvailable(RefCount bp); + virtual void noteBodyConsumerAborted(RefCount bp); + + // BodyConsumer API + virtual void noteMoreBodyDataAvailable(RefCount bp); + virtual void noteBodyProductionEnded(RefCount bp); + virtual void noteBodyProducerAborted(RefCount bp); + + // Initiate API + virtual void noteInitiatorAborted(); + + // AsyncJob API (via Initiate) + virtual void start(); + virtual bool doneAll() const; + virtual void swanSong(); + virtual const char *status() const; + +protected: + Adaptation::Message &answer(); + + void dropVirgin(const char *reason); + void moveAbContent(); + + void terminateMaster(); + void scheduleStop(const char *reason); + +private: + AdapterXaction theMaster; // the actual adaptation xaction we represent + + MessageRep theVirginRep; + MessageRep *theCauseRep; + + typedef libecap::shared_ptr MessagePtr; + MessagePtr theAnswerRep; + + typedef enum { opUndecided, opOn, opComplete, opNever } OperationState; + OperationState proxyingVb; // delivering virgin body from core to adapter + OperationState proxyingAb; // delivering adapted body from adapter to core + bool canAccessVb; // virgin BodyPipe content is accessible + + CBDATA_CLASS2(XactionRep); +}; + +} // namespace Ecap + +#endif /* SQUID_ECAP_XACTION_REP_H */ === modified file 'src/http.cc' --- src/http.cc 2008-09-18 02:55:19 +0000 +++ src/http.cc 2008-09-29 07:46:55 +0000 @@ -62,8 +62,8 @@ #define SQUID_EXIT_THROWING_CODE(status) \ status = true; \ } \ - catch (const TextException &e) { \ - debugs (11, 1, "Exception error:" << e.message); \ + catch (const std::exception &e) { \ + debugs (11, 1, "Exception error:" << e.what()); \ status = false; \ } === modified file 'src/main.cc' --- src/main.cc 2008-09-11 06:32:57 +0000 +++ src/main.cc 2008-09-29 07:28:13 +0000 @@ -69,6 +69,7 @@ #include "forward.h" #include "MemPool.h" #include "ICMPSquid.h" +#include "TextException.h" #if USE_LOADABLE_MODULES #include "LoadableModules.h" @@ -77,6 +78,9 @@ #if ICAP_CLIENT #include "ICAP/ICAPConfig.h" #endif +#if USE_ECAP +#include "eCAP/Config.h" +#endif #if USE_ADAPTATION #include "adaptation/Config.h" #endif @@ -1048,11 +1052,13 @@ // We can remove this dependency on specific adaptation mechanisms // if we create a generic Registry of such mechanisms. Should we? #if ICAP_CLIENT - TheICAPConfig.finalize(); // must be after we load modules - enableAdaptation = TheICAPConfig.onoff; -#endif - // same for eCAP - + TheICAPConfig.finalize(); + enableAdaptation = TheICAPConfig.onoff || enableAdaptation; +#endif +#if USE_ECAP + Ecap::TheConfig.finalize(); // must be after we load modules + enableAdaptation = Ecap::TheConfig.onoff || enableAdaptation; +#endif // must be the last adaptation-related finalize Adaptation::Config::Finalize(enableAdaptation); #endif @@ -1082,20 +1088,40 @@ configured_once = 1; } +static int SquidMain(int argc, char **argv); +static int SquidMainSafe(int argc, char **argv); + #if USE_WIN32_SERVICE /* When USE_WIN32_SERVICE is defined, the main function is placed in win32.cc */ extern "C" void WINAPI SquidWinSvcMain(int argc, char **argv) -{ - SquidMain(argc, argv); -} - +#else int +main(int argc, char **argv) +#endif +{ + SquidMainSafe(argc, argv); +} + +static int +SquidMainSafe(int argc, char **argv) +{ + try { + return SquidMain(argc, argv); + } + catch (const std::exception &e) { + std::cerr << "dying from an unhandled exception: " << e.what() << std::endl; + throw; + } + catch (...) { + std::cerr << "dying from an unhandled exception." << std::endl; + throw; + } + return -1; // not reached +} + +static int SquidMain(int argc, char **argv) -#else -int -main(int argc, char **argv) -#endif { #ifdef _SQUID_WIN32_ === modified file 'src/tests/stub_HttpReply.cc' --- src/tests/stub_HttpReply.cc 2008-03-21 09:45:33 +0000 +++ src/tests/stub_HttpReply.cc 2008-09-29 08:25:20 +0000 @@ -108,3 +108,10 @@ { fatal ("Not implemented"); } + +HttpReply * +HttpReply::clone() const +{ + fatal("Not implemented"); + return NULL; +} === modified file 'src/tests/stub_HttpRequest.cc' --- src/tests/stub_HttpRequest.cc 2008-01-20 15:54:28 +0000 +++ src/tests/stub_HttpRequest.cc 2008-09-29 08:25:20 +0000 @@ -94,6 +94,13 @@ return false; } +HttpRequest * +HttpRequest::clone() const +{ + fatal("Not implemented"); + return NULL; +} + /* * DO NOT MODIFY: * arch-tag: dd894aa8-63cc-4543-92d9-1079a18bee11 # Begin bundle IyBCYXphYXIgcmV2aXNpb24gYnVuZGxlIHY0CiMKQlpoOTFBWSZTWSsHSAgAlu3fgE30f/////// //6/////YLQ+8M9nve1XnlnLdius4w91Lnvb2g7ze5F7no+xfZ7e5BbPtITYZCEXmTR6Blew0HQe 9qL673vvWxAb1j5a82fcHOUpjjfDvZYXc2XNazHZeM7e+FhM0e9Xe+3b676+LMLsDeayAoCqBQeO effdW1fUsbKj7uclQCnb4833y+3NtPWbNCiqDm4c1VKUoipRzfePHKqlKqCj3em3PL7BoAlPffTj xSihBS53u91WVQQVz3jzvaBSIB7x7r2tADAMy+FRBQQhQijrUpSOmh9vXCtjVpkQC9aB0e9jwngB o7jrdnQNVI0XvPACpVx4O4AaRaYLsiEAccA23bFlB67XfaZV9a87198AcLHLsMt11fee6vRrqoBd Z20dGncKobZWDi1kK0NaBoWzJ57OgpXoDFpTKhk0AQEpUg22zEgCgKKBIqgGmgIKjaytBSARt3t9 33RKhQRVX0PPq8HvUViIJEAACgptqAAvTACCUEAQAgQATUZJhNTRlPT00iNAPRqAGhkGgGmgCImk 0mmlMyaUaMMhADQ9JkAADQANGgDTEEIkkp+QyamnqeqfkKNA0aZ6k9RoA00AAAABhJpIiECGhU/B CaZU/E0MRoU8kj9SZqDTE2gmgAbUaCJJCZAjRo0AAI0AJkGggNKemp6RvSjUYjIPQCqITQAIIimj AITEUep+lM0jaTT1D1BoB6gAANlzRUCQUUyggnQRVEClTPIxBRFYIIKCJFIKQRICKCiskRgqJEYp IqIrBkWCiERBkYjERVIrFBggxRWMYsRIIKgisEEBGf6P8P/D/k0+7rX7QHUYb50GR4//fT2iUP7l l/fcYrKKfNhv7Y/pc+in0Jf9/nhG4V/BXdT/l/4aTR/uh/ZqaK0eeCwRMmmK3Q5v/ul/AQyfjPxz I2WR7JbhCV8hhepSCQS/Lv0XY4ThS6vKuHW/Dxu/de3O4m3Qc+u4/vSnoeyT1smn0eF6e29nxevp 92jTrzw/sQ79aYYP3WiKinm+n+SuPQ/gIYuUFLy7OlED8pHJ/38viyDRRigySfv20S/uq0PGOE/6 wOSAceejlmX/gL7Xk3fgP6hHirq6931n5dKlVT2LKXV2FXBE6WpVvPDFoHt+55rSbOrus9Q9C5kr j1UPkXBrQ7FPn7r0qgkhSpB/C6sUjozi+LMKosGmvtrQ9lA8VSKJpluppuPXgVW3mZdl8/ZF1dQ+ LJi8V5jMWGhxeNeReC1ZnelrB2kOs5QqTm8P6AEPkvbbmeqmn1dXPScz2pGkYwUpfN9Kue0NfOhR q78TO1GSvClox6rYd+1j3S2vJRA13po+LQgtCYFKQ9/akMwJIK/0YYLtQUMMtpzdJ4dvL3cbikfP 9Fz70Kn2eikxOqdyLMTSRXXm+GsTvTh59lOOhvP1+25u0ft+NejwhStMn0FSpX1d/VSP6/qQGsSH y7Rw16LipQbX6Q/0RtJqenmvsL8l+UH4ATlv41Q+z4rYVvi/1e0otGC4rGOVB4Csx/4FeJ8C/Uf3 jXJU/uO4xzPMZJYSMxqn/oL3I+m458dtj7wkXVfkExY5ptNvdf8g79BUH/yD9sfcD71xoX0rOOwq R5qb+kVSi32Iv1DUdhzJ/LUr/gR/+Ri2gz6n8h4lD8CvfiT04zvhxH5ekScZ0drRveLzJxRx3ckt adPKCOTUmpJVq8vq3VciI6+gH66YkFP8SKNh/6P2sCTRP12/4f02Gcy39+Bgp+cDz5zcF6SY/Yp9 keng8ISj3EOy0m1lCN65wt6eN/xh72Sf67d9L6NWmUawb7awgrH64+VOHG8MusEsh0KuH/LZqyWg 4/9ql8sorz2aFfaXo9SQdzMq+8GgzQON39N09zJTw3x7zc3NOs6Q/inGU6MKie3p6PINvwWSbw4V 9FmiquhmW0mmFWPx51e2/OBBBT1X49G+Rm2FPnI7HsQ5JjRPRYN6Or+5ZLz5kfSfMxYVJKU7Jydn ZkGDro/hKsiBNGRYTpE08ZUgMocKFcEwwP0MNHb8Pfj37Ohpoh1vqzTDA+LNm9fpfo2bfSdNkWZa UH6PoxZ/y536dcmSniY3HvZ4ygKB9pgXE8DsmUNeg25oaMuc8lCJC6sYhuwZUCfe6DkeZIkBEIzK n0g/A7FZ+PN+sqBQPViWJfyTc0I3yFAZjzrTCoL6gkTP0IAIxUzUddIO4ysL5GTIjqf0Skn9PF1l pi35QOncZ5Q3zv7WHX5L3z7znAVR1D8lPV2ThQs4MSLVZ3gyooM9toPgzElEZ1rzbSRm8yyUbY5s QFSIpqwp86PuzBL+hcXbBMFVrQLS/waEBYfccj/X/EQUTA/ejoyGe+jPDiS6Moo5uXmuC5OSYyPn LTGfY30irPIcdDI6nzfb02cPSylpee7ppffZPqEDo9lfCG9oozxqFeijRE9xij2xZKiOmDqRQOk6 2kpaKeaVjiW2lWlLVoD1LcSjSjSI1r6HWVRmmWBZJBgoGdVIAsO8hbS0ZS8UNfDbKHqk0VJdup+O aiTSmkwfGrr0LVeU6DJ5pWpbHMUvd61SCvKenetTVqmC65TMtKi93okTQfQEkColYlK216u2S7kS tTuReP6xmZbLfGk9p+v7j3X11ijGwv1/ugQU5Mx8Yg0x2hKbRUX5tFU9cX6whh8wHUbXRccUnUPs uX07PFgycyMduPe9cCgnwM1mDRgoKVM3ZoOmYxTg5N9S89vZSkU0XXZ7lTksVF/Bhqajg6opUab7 +G5E7KeR77O5IAHqZ2Tj1WTEXSCr8EOWGJF+ZIcJRJMZOWYhNsNOemzoimdOcD5mBWa3QUk6Jggp DlkOnypiSdetnRAnHO7nOUmPZhww0nZk2gdGXpXdkDSTaBxq1nZhxqmuKHCGk0mIVFJWIgmdPa6Y ktIFkaumR7KvOMK07JMWz1eq1jLZU7On3dm3VGTInVG0t+mivl24ckvjfwZ+iX6zARB5t3f3578c py7eLTDU1LchTUlBUGF5UysIUVpOKoe+W5cKAYJpnG/l4/V18OnAnxXv66+OXfUIVMqZwKbnvKKN sm3dh+FQmQ6Rq7FOoWZXHqZszK0XNMZLWcLy11FUapFMvEQrTIghxhFsZs3hDrSTekREGWCQ5B0C HosXQ4zrll4GLKdveXujmxpXpA1dtFpChyjimePU2tTDch72NCbrJJUOiQjOsTnFc84NXeYZ+9u+ jIxa2iTPHm5aJZcaQ1b2NYxEQbcFljI27QuqWxqWLNpWoZ29gqd3iCMzAMzAwqAyh+eZpJAgoXu1 m8OvXK5MT8MP2Hf/me44hPW/ikRVUPL2+uEtoFtCjAqHO56PdY8P34X6/u78ZqY96eSEPNOXhCao 8kE5Yzk6/AZyYlmxBkQjEJFJ6KqERkYwFGCMBRURVSDk7vd9tdyHHpn5J7rT/5YFSYysKihaXEz7 abYbYGmRYKVIKp+pnyfBIewYaQUmE+EbH2VmcZr9IAiNp+3tihbxgQCI40VFUT9YohIiqHnEUQ0E VIQIXFs1Bl+mfS6CBF20UGympIYfnVn/HT/5yLFiTd8D2nPuo9EDHOV9E4T6lXHmxISX0NFqQhJL PGhUNpGln8/5xFoxSj2/9YXrNC73+UUOagEcoGhQIbBcAVcWAGNGQJES8EWgsBpoMC/9yqfS+Xq3 T+LglBlEvkloMwwtMtFFi+BAwz7x+xOMXv6Kc0MYpdIEG7N54QQSZNkJMMiTF/coe+tJJRsyKBmP BhQ8FHmAOvrA/AY9ojf2RmobQEjpBDoWHNzBYPcVMm6XRlwZriTjJfSgzi0TjcZvJ+74zB+zoGJr NgHv+OCIegh6/WFNEAKGA2gJIoXKAmB7QRMxzRGRRIkBkJCQWBQILFiJFWLFAUFWKKsWKsWRYKoQ WSIgCiohCLJBEFIxIiQFFIMZIskWIqRGRBWLARWKCqKxBVRIqxRSKoosFBjBRGKBIyEgSAySMiyE mjy09XMepAB+Z9D7c9wiBPwoU18tCPvX8PhdvKO1m6VST8WIkSxL3qduuOOnTOhrb2Pl6ZA6ncpI DCwEEiqLGMEUioiiqoDFiCMRRgVIQeX2U8R1J3pdOHPHPLDspthmO7PDqrKBFFCQdTsPZJGeZRm6 Y2eGzB2NOGkFpMyYm6hXUxOmELqaLRlKmpWa0GDEapRZiFupDQ9sNFtTYxqzHgCSsm00ReFaIkkg 4QunQIIGzc46Nu9JDBtXjbNobus5WUYSgoEZSusTDOiLxaSMraUricEOmTQ5c3QsuwEgUmWMW3ek SNGjeIblUUSbOmNanVFViRaWjbQfMYRFTVyywCCDtQtkDQEVLiVBwMFOipSJ77QIAHm6ldzO6fei uCQu1V800XCaHi+wT+4PO4ok8leOBw4kEcm2FCvg663fRPRq62rRqVjsuInPXZoFTo21FEc5jNBB lncoCVCJGqCs2aOEbcImCCJbYIxJrJl2ZTqRRZJIMmTFCYQGwEtaScnqWQgQzNqgyErpiVXJUoUR aQo5xRfG1kDG+b4BMlRdMaI4Y2XemTBGhdNV1IrUoYxjp2VjQZyg1jXbWNVKqDoABn1rMbFLO8a1 bi3M6xqXWLyAOXjRSdFcNcm9qutWx3VCXI2scaIRETpFNxut1UMUHkvRJE4pxJ9pxsxhjWkJ3uXq 5thoMgyFDvjetrkjVbybIkrnKzbvARJncsEzxM6IZywIyawIW1hnQk6mVFgpM81TiOOXRgLOGGu3 EStEPAxqLzTYa0EGM4OPpjF6WsczMabSwwdSuESQNGCNEEiSNGqnT4VIWHXV4i465YojFnToGIgi ikHRFkVjhLVqZ707FxT2zXWZOklHOPLJYIAjMtXD4nyQ44DBSxoSDHMgCqE8lG7Ey7GmmEJOEaIn AouUGRRCW3WpDGii7y5tob42L3OSBrKYhQLWkZS3Mqg8KpZFK5RtBXCohuQsOLLHGxNJepwkGyGK LpZ63dRsiqkVszDkGut2jeHfmqHicJ6Ogfo/t7hJurnP2YPUJkfWhH7GVQFZlWKkWuwiHvd6X5ZN hIah/iZwLyU0FbHAhxjLn8SRMBzeV90d/ivqonvOObhx3KeIQNwIqQxbcdYgPhPfuYnDqASAURv8 NYfCkQxTZ4zBBtoOS0/I1c1r+g5EZyuVzdJH7T61f5HBU5n47pQjjXSYi8XdPoKimrIEQ/ZHFP5Q rMcvw52wf8CbQehQDmrP35SZ7fV1vqdcea4JhfDh04KzUstkCgY4pgmKSKeP31Ey2W2i5ZhKporl URcR7zyqWqrmVjbIxMEVJu5OU1R0cXA0b3Wq6jNiWT9PLN0VJH7FLqlYEaQDrpiZnJ+hxzIGE9xO dLuGsN9C+C6ISA4OTTJkI8QWdYb4e6HVYZD+TkbwEJmQyY9MNde3HDszKvuiIh6drzmzMzMzMzMz KrGtYlqv4MlFSqkSWWTZ5c2kPNk6eswT+RQzVCOL+FNHDU78nwLLWAWFgA5rDdEkVYHO/WxUVQYV DNSagZQNW9H36m4oqqqn6la1RaZKcHDOWY0WPNuIIWItFVITjI9SQyyG5pmpzuf33K1SheCA+Ce7 YJDoESa5phqP1J6hX3V8QZQCP56SkkWxPnwPA4/93EUWrMYOOPHQfyLxy/QXh3n74aB40J+Xy6IN ZbuyBp+A2OHvWTTn0Gh0BOe2pSh0A0E2TRSEV/NIYO0BVUUWpqViF3JLpRvMJYdS3cZJ3h9g7fRu OT2YaOgNMe7BRIKZg0zfzHj5Jnklq82znXS4fc9tW0RzJqfDUSGqyIKQd6Bway4LmhI11QyVD5iH GEBYNHJcPzfJYIYChQdc0UorcafVOWzzMSsEqqlmUb2VyiTrQiJFdpJU4OoRTnh4F4GXgaPIVf3M FDw0XIsCgmGnRFRdFYrgixwCdNorODYabSjWnLw7EbC51hLijy3yCknlzxXh4REQFhKtoK/lFZ70 CIOkSwhYHQBGqutnwYV2qu8d1FxN6Q0730gYYY206mmmlGPEsdqTx1MrSiSnBPalnzC+XHN4kTG9 yzERyi79rOhRcEWrMlUqseIBsRNn5CG4MUJSVnH3YIW+uMoNyxnKcTHT8cckp5a3qRhX6IclDX95 jGhfLz5dr6XLZ+I0Tn2I4GWQejq7IZrgjtg1R3KpL5LajkozwU4SKMio6NS1je6ZyS6GWfS2PLSS tk2GZiGa+hx52SQpSLrsiIhuiIh4QjUyKB3dHoOKf+mKUwY6VSgsjpDSGAvMGKGFSgOdOcXNbmED CuE2VRU5dCHNYCmXeOcEimRMdgwwSFfXCU8Mp+uIR+v1/Xmd3xPGCav3agqxUxXj7TiW+1qQ59kr 3fubIOlWK8zW5DUfJ4I6tkzRhnQgkRiHRCCfEJHQeJtk3nriIgcqrCHQMlyh6ImQwNL5+HbCJvZm Ri4KMo0zgwPUZrz1Vvo7U7iK1dEw8DwhLe8ai0uUBdTI2cecjSBOAyESMsMyeGjWhQV7G6HIIeYc Hs3S3QHM7t+ouzom1WRJligoQB09dfXQaBu2IukYxlEgUzlwGWQ8zohqD0pgPvYWhVhiJlW+TSSQ PfQemVj7lgENf+puPEijKpkyurGhC1JDRIR6vjsdLJx2nQ5zW3OQ2vr9Ws59ZTV0etnnH3yBDUkg iOvnLJGZflSkj48RozrtB7ki2bgnmqc/Q5nTiUO/wPATnNHKOr69OU7BqiKIMoIq5FCVNCRETs/x zQ9Pmy+m0JQ5Z7+3/mGR9ihY3sxoMo1utuLGGrWzUcLhBkUJF99kz6eX28lq9/GWQfUubzAmtG6G AL9FSU+PFEQEcdSaVRrCqR8p5IKYXHtLj7p9W9fXLmN9lVU5kQKpeRIXkw6h2b2RFfnPm1vV39Wt GId3vmgSKov09+8iagH0H51fF28s8uszz84G37iu5ODhPeekkQwkUoMsF+JUPpgRFQx8eND6X/fr dVUsNbtUcrqaKIH0k6dPmkIT6IiiIoooooooooooooiKKKKKKKKKIiIooooooooooooooooqKoKE 77SMmg5cwunxHElkcl9GfpwxNXMeTC/e5CCk1aypBN8djS6wO1unfx3kJ41VR8lGOZeH8p9sh4R9 zQ4ctglzR6p6CgsFVEYOo5PjpYlPUczgg4uCPj7QDe1WWxVonnN+NalVRULCm+ePJDDrzwfO8gyi Bzh1a3MipQqKxidNegYTK1pnsKjr4NLq2Jgq8NwvWbFfERBBJwOFTrmz7RiLSKSgkEazY8uRQsSQ mpyCNPXGnFJvjP7LH6MbnU5Be9s3cBwZEL17ZERIbduHsKNB/JuuFc7xGkeqo0yxKRAttyxbmz6/ o8/zRoIYMIIkThEdFQ4iNsdrR9eR1EDMHUbaEOD2/CSaAi/cKUec2EREGM4byzmdnkubQWRgMkDG OHaN4NIYfCwnclGRIWs6rX7dJWhExaBmRjjfEyjMooqeA/Gh3UrTpkBYc5EencJlYnTDM0zlK1Re RipKKuz8qdMaaQ2zGrpbr4ZbxPDwS820Fb6Z8+d7N5ZROnClUS6dFSuqW7ZrXVSS1qYZU79FYQmY lMCZiIjTsGg65Yc1Ry89mVc4cPlJRoQdGeVtI8ULEIMO2vKSI2SJbjKIuoGM3CzntgdlXQvKwxwP DCCNpMjkslQkLEUvVphJOO3o4z+xWXoYoFVRMyqUWQxh3slH4dJRTfsG/MTy9oej/1ECCogoxGSL IqhFFPYE+59CQD/o/d936/1L9P4X/D+JoNi7DXN/iM3bXj0z1DxVCVx7yArFmk5CArLBax/OXb87 eHf7dsoZ/x8IYx/j5cafhvPjS/y2Xg/p/zcdO7rx5fh+OWHdnhr4c5978Yw0hKY7T5CrAV14VWdW q05tj58GjDPy39XN2jvxPVAmf953piXlU+KqcutVNXAMT1HmZkyYefs1qPAiHBQpNguGTXHHsMz1 wPZCcyYGZyHG/Wfj7bVFLSisW0o20RUWKqxWKqjL8r9aLiaRxtbqmnB1lh+rkORGRjIKytggwGWw ooVJVgDBOqnl4te58Hwe5xkyWKn7Zc0aMn9EwfsFzZ2XPkeCTRU6PkcPBoudHR4OHwXLHkop7mT8 78fO/x+zDN46ULFfH07e6r5W+L+1LHx8sp1vnCtb5Novy9823WVKrXSNo44kvCLPnLt49+V6x+vw oWi9odqeXczVrqtPqrvh06zz6vp5NqvnodZcvLv8z4vu8iafrhYtmwyam53x2zOGzUjncWYFTxK8 VqvhTwDG+Gd8aEMFwvCGdCpVYyVS7vlKOEPl422657z69M4X6z8/eWk/DPXx8PL26166+XktOa9T 29PXLz9PGPtmY9O5vCEBfPzLL0sR7eZcTC2SDTLAWleIUX8R8faD3J9i+9kZ1048Pj/WrJYZVVrf xX8PXx/AAT7lARBDHO3h4a9+zQtt3+Xl5vbB+PNc/ff4+XT19vOvp8ax5+/xbT364Zc/f4+KIiIW REh959MAn0iRsShbQRiIoVkKkClpBFI2SlgD4f+WQhkDSJaDARgAW0AUkEGAgCQgpJCihUEZFQAg xQZQ0Cf1BF6VuE7J84hBYCB7Yob8UIqkMYIMgrHroRPnDaMjCEiQIEkIhIuSe1TxJZnoQRG+o9mg 6ECLU9rECKKeJJv0tN4n1t9IlZkvLBWdScVg2UaIk3S0JGKS/uXcikyB+Ygp8TUj2CVRhkTKFHpJ iwFXS6YWx2EGZ3tyRmlwkykiOASAS7Eh88nyf3QQNyB2N8dAMAEDtDtGcAePqBxdvTjB50pnRNoH O+23kx5TgHolthl48cOAdz6M7uBQRhBIRC+z3JOIkygkmEhLKcDaqC7vt2krycLM4dNKYZje3Zm0 C1cqJ8F0YO6mkzGVIsuZNp1JFSOa5d+Q6ybI1xWycD4SFjTcsFVboLBSIMej6QeKhSAluCSRM/WI HZPx3vttehDSD216xNTuGHITlWK8pv6z/u/9s7+P7s5A6g9t56JdmhRb8ss0d57C9OdyclOQ0f8X p00ddLw/1cVmRPfOaGhX9P9hrDLPcHooOhLDA2njvy6PBglASzRgxO/0dTWMvpPzGEHQ1Vn5Yglt yu7BKKOOUsJjOjdzIUKNWCIMEU6xTKDGQqHFLFpBFPa7CCooKpfJohmgoRBkmQ2wx61M9887kl4L j4gJH5XfrChBjXcRglOmVUEAGmKEzqkWtVnekbFnMQCFUIdqCGbcDsRN9Ngp+CGRRY/sBnVD9pNH +ZQ8j81tJsG7rwP8heI6rP6+eUIqfxUT8hXyspVbuYxgDt/B0TvU/Z+qNjFuI/frvMxmyT99IikP XVvDxaqilaQL5kaT1X1od9e/mWgBUA7FNFGKQaZ+X3uGI6Sesc+bwwJcrsOMJM/VaIcMkNIoadMk WLIaGGkh3IePdOy80t8eeJn29eTZUpgzc4DcV/KhBHuKLYFRlAmKBWCMCqI4wqCjWhpKJtA82GJP BhRgcJPsK3wqYBS6+BFCsUQmtqugqCpQ0FpBrOaY8MhJU8+Ia5Neeg4/ty+CffznLr23Mg+LfGnb tk1IZLO2WkNFQhOLZT3+1Z6KubEdctoGq5Z4S8ojCkGGGVL5MViwq3Vum95tLKTHDXc2aF70/nbF SKkDudcOrc9w7gnkKDDKWKnjRdiR4G5+ILzLHRDbzRXzP2PhUeY14B4vTQrEu/qYe48Z51AhT0w2 wUYv7n1A+78c9cVf5L3R4gUo4BDt8PkfXlitwGZtGcTsQiKn05759nfIqBJj39qGaXv8ox1AJhW2 Tnll3MRdmX+tXl4T/K9Ji9e9ihnT0mQ9pOvgsGeylZbznJhVZTFVmZekCMDFucGWkO6A0t+Q2VAk 7Nfu8VUDgpMwCQWx4mXLHyjwhu4AQ6a4gygcS5NMbTeCgus1pJadfJzmi4ywtiefd9EPYgSEANlN bChQ/lQGfbfeocgQQz1XNzygLojCQiBIoffP8jHPvGzYSuSLwF1G9Lj69n55/6XS1+3jAURIT3/e inLPFU/EaZ47R7ssPrNSxXw9oX/Jw/xfVWXXS4XyXVUXti4irTN3KuHb7yRfaVTSxGz4HzohxYMu i4zAb9zMgTBaX3v2R/CJ4gSBwJvBuB6Q7EeZH+Kfwyrq3+Muu4quhdaX0YWLzAwT7Rk9UgsGJFBp aklLyAfQdgNB8YCPgShdCSLxHDmD7/rGyHHnnbvrxhetL1mW04XrhGOK5jFX8x/kMXJRkiiiUpJE pSfUyUVYQ+t4IYnx6iIxYrQlRKlEha9CKImI+lImYoiBYwFCEUKIEEEkSCIJApJCYhJDVhSQQqqo lUVQqhIjGAiaDpVSBsE3In8FQ6d2vg2VslU00WuwROJB3AYiaFavvMIZQjCrULubFywi1fFLhbCa RLlozLihxWCaj99hCZXm5Lus3yFg2ktak54s0JDWhB+bcLqTRcBrRDf77IZqmyoG8hjp1izDKYgY MYqKI/rNUMt4wWmrmI2I4rz5yg8/Y+Hx9zVCiHwajfRlERCEKPmpsGcIhVigtEViGTJeIwJkpx4o 6YjydexHSoBAdCObSUj0qphCLDXZEH5duIFiMoMz3zXByShMQNINI1g7cIVaxENYRiTGdURBp58z y+7EOPfvWEViIpz/W2QwN8IKwcVjHGKcodmCIjjOF8tF08Px31U7d/zg8DxGjCb2rPmsiVKPTssi Ff3svJ+TXay5iW5yYqhMAvAWuRDHnlhKBmGv4f4SLfAyfW5SdSNxVwkqkDzKK0sWq83YzMDE/afe +T4fD4e/5m+J+EfMLdjdkfGFt8tpmlWsNTWVNLFL9bm4AGlah5w+dvR11DjnVusZB08xUIy7qLYs aHUhPmK2T5ZrfaYaZmadJWBUPHPme7y7hmdNTLlhZNMQGJAEiJABBDFAYNgWCMjIoKDMGAuYEyth FXJVETTo0TCFR2OuBCBAux+mE5ojlEcVyr8wxEOzjiIhRslR4q4uTUqELhCmbmgMOUcDMKpNEIxA 8IWswmuUlkrrIwXXUYsVBcKMTFCoGhvSNYiGpvrYNOwDH5+mEewUDtOGYIGMCECQHSW0ljy15zK4 aK2eo8VXFzZlN5UwY1QQVNmuiD6MKumcN6woxBBRnrD5rD7GoKBp9ij8UkAFf+P7lclhH86n7fyt ZkthfdLX1m7rWaLmaWM0NSUBKDllxCibKVzSZrVIg63hgIZmZAN2gy2Ywc0mAiQxJlzAUWR1YWlk KilQKJ/0KqBIz/IIoCc/PEgQIQdwUcgvX5/H0f0gywg/10ET0/V/p9VtWtb4f5+Y58lT9dlWeSd/ kTgzMy/H6In2nz6UfWny9nfrlfKGh+h14d1/giIhKH2/f/VzvKUta6HSEgD52SQvwVfRbQtpbbbb bbLaW22y2yFtttq2FthbS2lttpbS2ltLVoW22ltLbatCW0LbbbbbS220tstsLaW2222W2fh5Pxvq PwS11v33Mhm+2Eyun83Hjy8PTPOlKTnOc/66a7dm7vf8e/yj8SzkF7OFIEkgaBBHTRO56qa0ruen 1bzUrOPL69CdOenXbm8oLsHuCEh1tCQWExJWSCqdkNsJ2QJ2erDGGJ2YFTbmWQNoKc8dcxAnCVAW Q6pDFZMQOyBwyGkDGHVk6Mh05s6daB2ZUDEAWB0YB1YvCdmGkk29DrxnTiwmZvCCwDonLCdkNoHb reyEDSEUmIQ5urPLXCl1wAqhS46/hj+n2wuvt6Z3lB4y0ZmREQ/f+rfJNI8UiFO4IqRKFUKFqd5a NLdVy8ZzlKdM8YiIT/ZxoNGK8IMu2i5YiUEwgxXqZJ6j+f7NaIblEA2UgeZ0LCFGB4uKkREuVAFE wiIRC7ipY3YEcN2rBIqcEiRE/2IJK9ViNWTAESOoDgzyRE1IMCSCYhLLCc8KRbnpCtidVwMhkEYw HGwIIE12KsIhkoymKySGiWbZgwUZrubYGMUUcZ0cSpCL7wjCMMN4gMiKQhimt4Rsxbrsmn688ckK BpnShCIzkxw2ViN2S7dduxSqs4brM9Y2petJ4ltdQ1RtViY1UULEascqoLVZKTDOESwhEKoTRjSI hlUybMW9smMQ0iGJsxZrxDLGKRWEYLsYRtA5Z6ZR3MQvCJiLphFl1VnnzZ2zak8LFhTJmWTRjrgy AZgmqaEAUqyJBJKRojQiz8WRUjrrHRDhrDhaIho2VwV0xY0jaCKIlswQ2KvtiA68TiydN2jJs0bu GSUt2rWmCnEogzkutjaLu0hVJmaKxdVECGYyXeVqIjg0qRENE3YqVxV+MzQqjRtbK2cREmmaii8b rPS7d0yVZuGGbfbeuMkt2M2syumyFLIXgWQikQlim+SIYLrZoYssZRHS2MQ2aOnL161g187FB6FB klqZmxA5oJtsiBMgrO1htIom6CV3YoVW1qYWTRE8OFUMoMbM0aNWCIYaeWNzWhgSopoMk1MDUiEC RU8BDSiRwuOqq75WjQRCkSARbda0IkmEREF3r1gh0sooYihd5eFWcYSnSDpislVJdgJcu2qijnLS J7nOm7LTW5ElDnnNlB0SwaKQghiTCCKuFWei3TxgRpV01Sq4VeWqVojUxYunXXDw+m8RBF5DxCYg d2cLvLZdZmxYOmLyUcMFGLZ4YLMTU1O8Pz+4I0F2MyxDUWxcUudQicuWpYFODpDRm9LMPhw4bPLp V6e3hk1ZvLJm6ZvYfehswdMmbp0ly3aRK7Nkxcs3bF/KIjhh9nrszVtbNmqxViZEy1TGKVmiXoqx LqPxo3KRDNw9s2rJqoUavazwszZPLJVddgos2UWds3Zn9vUIzUhD+p6+EGzX5a0ef1ofch3CnrR3 lMAOBDE2Nea+oOhH1HsR5OpDCwpuPFGRMtvPvc2Fad2E59WReYUTdnim0gZ8ZpBkQQwiilTPC1s5 ozl0zPA82SFTWjth3M53rroiZZiBy4hicW3KLp1ugoHe7TaBWSXN3pqSEzpQoyb2oeIApI4Xiihw oQNJQI2DELWkwwapQKgwIsi3LgQCNc5gqgTdbzLd2ZkPLoO8W1yoNsrRUpWpqHu4I/reJgNPLrxm rnkAooiInKa+MGiFynks29MLzxnN80+wn9j70EIICCB1gUMc69A36AM8zjpJy1r6G1fLOmqANKB5 DaD4AFyzx/hT3PnkQlFVFxoMqCEJNJK5Ih0gdhDNx0IZHqeJs9R02kgMw2jKGJJOLKWNCNojirEU JE2AFWEAYDkzH3coZmJ3ZEzL58ywZnQY4HNccdHTXAY6jMopnr0cWV9XQCQA1oo6UDMDiw6QaK0o 9EKPoxJUkIjX58bO15SjtLblCrY3FUzHM3sKYilG9I8cOGy+GRF4iL1WksOsWi0bXojDNPTwVFIz KChuXNi5kYmopAfZMNVxwYRWZllrNLVmk238Z74uYY7FiNY17UZNo6Wgjfe7lfZP8Lt0RkQ6RS99 tzhXF2ojuEV0TXZw0rqthB5jkNSD4wrtA1JFA0FM8rY6YaUjGnLSNJYSxvFjSrcLl+V4TdbDcDXs 3zpnOjrmpudGOF3zXg1Abhlvkarnjga1BavZzq7zW+eljNXjPm+GC6WKfWpjtqswjpe2b51e4ztX MR2oLT5CIiDkWOwu3KMEsnC7hg3Rntnr22lFk3w0itetYM4DCJuKcTnI2IwljmYIgBqSaOIZQgbt mKqbEp6FJ4iwVDW5GpQmOVIGQ50AzhjQWKgK0p4p0L7bwvF7PSEQZMM7lTtnulVrMTutEV1WYiGR wObikFsLmLI2MjflIuk9lSqkpp3pVVOtdbYYPbJQowoY0coRFZRBMcJknWIfRlVpLBEOLVp5XVvN mjtqyXvMJNE0Zpek1wTHx7niXLIzUS2ZP1h7Xebt2l2wLRdcvv4s4hgDfrDMSKpjiKpmLwHHCUiJ 4EB4A9boO8dB0A8kR4IONSUPQcTUDmMOgpBeRYY5QbQkUHGFQkWGTYqRJnPpU3FJEixY8xEMuW2G SNdRl0g5hdWi7NalKxlLLlTGErXpkJ6hhEeIRhbWVUKxsrkyy5eWSFlruoRCqkUZKKzhCJpdZWPH 0bKr86O0xpxYMip9GMDqamRYueosx7IXSDNkDawcGgu0Hgrrr1uicIiVqLmpU2oK5ggWKDlNCMIx xoiFt76SzTRhEdKrzCsQJhqqojYgqY5tMW6qvdMauBYfhUoLochjUkW2O4gSLvhu1XdtfHm6sTCa J1mtaTXqVeJ1HikMiYw7zrBgljMGiZgnVLAieWzhNUahOMI3dqK+majNgp6ksmXzCIKSRu9/Xhmz eFHpy9vD42h6SYoRB4wxYq1yUS41TqxZOmaXpVgyelkvTZqyfDdqondg/CBds0SoyS4dOGbdLRQ1 ZOEs3LJq4UXatl0bMWTJ4SyNmLdZkqldYu0bt0u4PXrg1aMmThjjwwWYNXTdo6SxeTQgZGRAqOTP hIEDwQI2NiZUYhGBwHdvvUr8Y7Gx0XeW7du7PBZmwXeFlUrrsWLnmrZWuLN29Phsslo0btjy/FD9 8R9LxH6Ep9oB4mf1o86ObMvHqQxD1Pij61eAV4w2RAPhESgR0EOMQ9UEmIgV9gKeGZ17msvYfxON rwB7CjAQIEhKL3o7KXIAhmIiPdqp1G1QdiK6pjNdNHeLJQnFUARBAQKIRwnEGZnTbCAdU4DaFysw RACUAhTrMs5CmIMjKrCSZrVS0UKqUmlSbUgrSyaGjkhdLRuI1Ds+JrTlwbi7xVWRY+1bU91pVtVH CI6iEgxwpM3rTy0arlMJxku1cXnXSEf8xsBqgnYmgTeQOlknUkLrQXBzS9U66nknWTG+o8vTGMQ1 Qy/bcjNBJpgoRFSGihCiEkIQiYQokNDLS1iLJgtCIVoFFJoI4EJEOsnWneht2QQYFsOSDkbI1cwu bkHMZii6/p8pZs4CVQuQhRpJO1YpDSScFGK1GXMQvLyUekvTw4eHG1zWjJFmQk+rxg+E9KTZWJII KAUBzZJkAPeuBqTHAU2LwdjFimfOETXZcmnxCNFzjl2DHHBQCZE3rqeKDwkA2qpAdBCGgoWiOGMR TSESizNdweEqvB6Lv1QfJlG84acYM/Ji69KYENLTQTkgMVqiMIljm6rKpWskQD5ki/w4iIg0IaLM XsUiNbwhSIPiYjNEylEnlIszRar4b+N1V71aO3Tr8qtECAorBx57gQilOTamF5i5ohgCigoCoUQV pZVHDVlgqdtWi1paM4RaECsZ960zTiwroqVuKWJClixQ6dTIQwneq0dkFwtFGgjRi8VSGUuFQQzJ yc0KoiEISkYjhM6gzBZAnkJGCE9sHgig5QeFoSF9B6SyORAKMDPIdux9+3hs7SZlJaFNqVnbml6y IjZhbtRV5s8ZKUMoijAjkpLJY6S0cL1nhu8O+4pluLQyMR7ECWRsUHkImQpiMZmzzZZVgyYUrW1d bwhhVDmOcl2J05ZQ4btpz2y8aZJQ3yrEzDy6z1ZV1ZNG7pul/KIe4Q6Q572im0snujZM7U3ceb2o h4HTJp0yyRCFsp799M0trzRTN09t7uWuvUI592nd4zVG8fNIyVo3UNjE7HF8cGXO0Loysrw5IiBN ERyUbmpyQEhLtf07gziMYhCjB8rxXBuszREGa+RPrzEYIg0eWh13mzyWarvbZ29Ku2yn9JbnRsyV ol2lam8QFcDZjZxA1SQhdn4YFaCEAkTJokiC1JpaGpY0ImEaC7QOe77mxZk3UVbuVXTeIRdCCLsn ajNRuwdvRzUoSInA45UyC5AiUPapgXO5AJ69vU3IaOXbRV8qqHhi8JXdslnaizJU6YNF2rBlCPTB keXpwzXglRgqUUYsVGbV5apfthE6TKqlJ4aumzlo1YMGrByswdKmC7lyu1cSlmZtnNupbsmTR583 YOErvajlo0eC/TypHbp5ZunlZ33icOy7IxMi4sUcCmw5w4lb14RQ9HsEwXqR9CHgcqHGIdpoA5+3 ldKN4dqvgjjyFyN5rE17EoHI9jz7de5o+NCHWY021hsOolRawmrEbIDKQKKuq7xI3vFyDk0yLTCY MyyiSKhQGIBpQCywUJTZcwDdROlOMNEE1l0oirtTBnNAnUZD1BOO1gO71C3b61rRiVUjSnAoJwGJ YDT0q6D4ogQrxtBZAz5aG9TdzLnhAPuJQEZQfQ41RxEZRATCMEKRfWmkp3hdrvxTPNjTLCuUMCKw iUL5qmTRpJqwJg/HF9ykXUWIqRHQu2MepKPvMYFFR1Mz2KYHY9jUz9qOzpRpBltOHbeNpwOGNJtV VbN3neUKqVZCJtJ+aCKkM6K1QSYE0dYh5ES4UMbYLljbKzVW7Vp4YFI3cKIhhbPVZRBkyYK+GzSG C7am8xjQoaFjIuXcvkpJUWUIkIKZSpJDPJSEUyo8RDGkIhuqohnamApLBaXN3SyuMYwgYuGC0RCy npm2iI2c6XppNFkt/Ml8TE1C3DlRTU4JFIipAUTYvd4YGyhnBlehSbYqxGijCWCUZYGqYhmos7WW ZowXUeYgYsGTFgzdPLe7ylgupqwRds6cFy5UYoRJlByA5W32DMucVZoOuimgsS5qdviIWaM89IPj JmlduhlaEVUipwpEdpcszdg94GcI6iBfFkq1aJeGDP34jJk/W3QE53YMjHNVmLrnIOkyKzQRUSUh jWBAoQlCMIps5paICZTkmsxlERi7VjzaBoqv3RiwZPaXy+Ha75Slg6Sz+VaRg0pXHBDQ3lEQeoMr Plk3TzOaXWKmKdM1G3rc6csjENCx5E8pcFLzXZYTWOOZFEKoiTlGQ5c/ViZGE9DJERsoGm43IiMs yREmXFLGYoooxLOqC6WezQGJASRKm5oTnVBLDsiULjGBxylRdXFW7p6cJcO0sX8ktIzwxoTOM+OY RS6WxolGJCqFhh55SB7ESxYbyFRaKbqbimJfvWPCWjB2cPywPnGIiOXbwyWZLF1V1FHDJZ+RHt8L vLZZk2XaOWrZZu5XZHDAxJljuJlyZzIGJkVjYqYkIYETMyJDmBc4Uct2jRk3XUYuVHLhowZKN10k sFDJZmyVUZqtmjds/qtENpbN1deUrJ0bMCjFoqlywatmrJ04YLGzJo6YKKujAhmDQZGRccSDmLHI e1TpE7/WjrDPSO53FjtR9qGiBkrtAnq9vMYid+82R8VN40o5CHZETqAOeAyB7J39/it3t4+UF03D qKhMyG5ROz2ANFkc8dXlJJSXM0RNiqOGmTQ7Xhi5lAVCuUDgg8QLXKvMoNY1iuIsSSGvBeStzF0Q yYZgrkYxa5uazLbKxmy1ypCswLwotqhZfIsmKkHnXNznIQdvm2vGYDvTtrazzy1bftjGEcjSIhnB iqpBa02xcdYYw4oreZ3vvjGKm6adJfno2a7mCYTaIh2wYba4xeYtLcplGCxVwqhEFVDZ+pi0mIca 7q6aJmdlC+TYymXJInuSIkBoJmZlSW+Mb5xo0sfM1JIGprIMzW2l1ZD1JmzglAmVeR6mRqFTct71 LvZJ3OPEqUKYYGffmCO5nCIVWsnlulgbkzggGZnI2yScsCEKDDQCnA+hFsiSBuakqbShw5aN1mqz NkuoffEeI3zynPzxYlWrLzrkyJJBKG3Mm+1BDloYHAvELOU2LBIUc0QsycusoiPL0zVGztu3YMV3 Xuqrt4Zj5oCZRysXk66qlMnQS06lTKcykkWOWh52uVLTShwYEDkfRJjlfgjrZba6u+IywZZoyrFp hglnXxRyuxgy8pvfvCEQ9vPEdKLqwRo5qy97mpMNTMXmQMkpTgJGJQ2PVOpvwKpqCrq7rtRxEIxz FMCUsslkiJruZk46liER0ElU3OKrjdwza74s3DJk1bqrNHUT1N8dojLKPpCLLrzUQsKSetQqmhgK a1IDRqZ55lDkcixMuMVfw+0wiA4576nxHjxgrhOK/gN1rcM2NVHTJxyIp9epfmQ4oRMCxIYsUMyJ E0LFVMdFJpSeqBHTJS8H17S1crN7pcJzfLZyydO8k4s3s1btWDZMRFN8EIiFEIglTVOjFg5dKrNv jtq6cGKqrtk4cKKqNNN4Ro6bOGSrZVw7ZMnSjFL3Ryw5TRguxaKtWjJRmwS6iKKO1m7ZLwxZmbNs 3WTYiVLmhUtcXIYiYGOmehEWDnNo+LVMzEoeFksGazt0slRw/JDNkwZtHLVZRyuUYvB2u9+8F3t/ R94mEe/KH8Ij74gP2QjlDeIrEfXCr+MGJ0h97X8zeDSiHzr9nw5REHSo7yBFPPlOcAtoCyDq6+rq OPVy9OPNdV3hRMQfrhlQlPAjW0ApdNrbSNjtKQQ5tlxYO6ATQ3ghFFHLdlyUqIvmUJEWY0awRAHE LFPUVciBo0VeZqJcUJDC9WHCytY5subbBEWGmHrIcqqxREEW0i3DZJiVQisLzepmZsWwy07sq61U 1mARaUTXAuM0Zx6N62qX59NtS41iv6QwMECIkDUCDDAAOS7gSPN7/M8ljKFMdSLl7rmzRGLOYpMW d6Iiz71sFtFIU+5Sxd+x1aEQQ3UUZNmdX7IYuDZZTe+BdCAzu0LzVAyl5EkxOHIxggXREpL1X2OZ EMSLz1hHbUNCBhqinA7ZrQREQqSd2Co5LJymqzh6bHTFwssuyVbNmL5w19T6mqERRMkDa+QGPa69 OQnaBbNkOxuYhoOLr0MmRLFhEQkiFTgxLJdLsVKmBtivIO4V9T0PpP0Fy+ezTbzPrODvFJG/gx4H LDoNdV6LVYIOiAGKc3HieaBI4AURDsVa53HaMhKnca64DmJmgjIJhVIDaYCmF4SNGLMRzdOqSO3a h4mQbGByDM0wF5nyQTbXVsbMzqyX0GMV5yjLDgiM+BOFUIz6WZMV2vojVv8fHbNhERbrLpq/fLc3 dMsNyhM9xDGccJLJlsqNHAXblRBJGYV4LEnyualipuepxOI1CQqQVjMzHxNyhTAtkaZEDXBBFYsO ZnIoOeLXey5brbVlZWzdlYMRBaDozRNuTzLkw1ChuZkmNyRApHJSRqbX1OA1JGmj52TUVMM7CDIB TLEIFwkVIkvU+difBmMYmB6AGZI4Njc2O7TG8Nhld9qX3sgiDJc0KFTehcwgSKj1JtY3MTwJGRYw NyZ8Anv8W1XVOLLAr2vK8xEdBH0ZoR4LEiybk73I9Cp11OUig254GJgTJGZE6GBMczOhM1Ni5QMe 6YzSHS0ZnpL8IiNjpg4YOFXaijbby8MHCj8vwQ3XXaO3kq3YNtsWLFqx8pyZrpDpczNjdMCpqYhU wNixMgWDEyPP1gNAyJ+nNzR8nJm7ZY5Tdm8NG50sk1UXalHh20yZOGbhLFRVVo0UeH7IiNqfbB1E dx9sQv9sDxIHgL0F4vpUAoVCBgb69hvaubk5d3GbYmfIdh7QYImD6qNjbcUZlRDrsgbd1Z7WVq3X VOtduaG2jJ4bPLWEByFJgK3tUElGnMvMSs0oFM1w1DWswYcWhTQLpau6y1ucSX1GrljpMIilsS6z RFRTwW07UvDKGu5XfCDM056b7LbfOOlqYmn6HCFUMkKFkHCFKEaIhhVEQWQmDKm2N7VZsWOUOZmc c62tCIFUP1J0QtVpEBtFGjFixgZn4V2WMCDIAQFLDvqb6hYyOYhM0hBQWrVbuW5kO8RijeIZ5y4r k9lXchAc2MQgAmFsERJlhjEUyKGBAmbFjEkSGLmhZVCNnHzpYnKfquk8M+GGaGWMRGNUuC7hy0S7 bvSrdzv1tNlxxwjFTSQmbQsenoqqu9CUiQ90RIjQQLGJExgib7BIqYlDYo1MFzdkfF3wxjAnVICx RDQxNs9GvhgtDXNVmrF/uiOGbB9yD9EkI+qYQKCgiqu4whgKCIeJobmRM6k814aWUNYVViHY0GVB LlyhI3KMgkm4OQhgdLnIuKSMjcxGMSBM6GuD4g1HV1QxwdGzznkJQvsWc2GgbuFVGLdngdKdM2S7 Ju4ZNmDwqlyyYjHy5eIhxfOnCDqzV9gFdLS5wzTlIinMYUs84mZh4VIFzmOXJhyInAx0JimBWOr5 aLeKsorMxTKSVHsY3GDmQJ/FtSRUjaLKRUNfG55oJkZqKtduy93IbMyiZY45G5EwzORHgthmSiUN Cxoo9MHxEIgqxau2TVdi8PhsuzbMHtZ01N2a67Zks4SzVVXcOWCzdRZRylo3aMGaqixiySwZrqqt XDJwwcLvPmzp2luyatma7tu6cuGjBRRo2XcqxDVqqwZMGaXaVl2TRw3VYqMyyrRLU5bTTzzLESvd kQMRTUmMZGI5qZliZuOFT6Ig8MGrN5aMlTBkj98HuESf0HXkffpEOINtYMkMoGEIW/chwiHhhl90 RdDSEICBUQqIZonzDkOd2HGPhE5ci1MqPKNeZpWwSUBc661T+WZYkDGnK6pWIgix0htIPsaaIFgS t5ukKiSzridVyQQlIR26qaEuEiEHhWGqMipEug0jO8CGbXCxo8VEc+rAenTN11zzlNcrDzv0gZ80 Wy0JFIgQyE1xW6XyWtRHjnF7tLSmEXS82mKuR449hTIud5sUImZkCVqhtVFYdOV0LrJMHSWq7hsa tnhdwgS+h3HJCbeOu1chQpuJdHCMMrV0scTdnlRrGujFiwXbaohDarIbsjhLNd3llxnpakBVxRz1 1qkToSJlXCJXcQGfA/Ij4OPQcUIwMPCHCFdd0xEdMILJ2dtnliopCMGLpRsamBqczQspcZd3QdR+ GmaGZGNtsKkSYoJiFx6lsicURKHHjY1CQajHBKUSVtTG8LSe+SuabMHnee87u1dfttBSEQx1KwjN ZN1I3vNzYIh80E4MTgiVDI5kjYsHGGdDhRUqrqiz68Mi7WKRlCLrOHrdmh4920esI6e3bN4eTfks V1FIabRL3HgpAUhA4LD1LTNjRSBkSiCmhU4MiJ9SJynXXOeVokjA5RHmqiruNqTxdhyBQqZm5oYW kWMzEjQxjqXMiAfMEpCSxaraawWEYPF2TicozmyGYcNCBmVMGNQwJTdlNaGAo5ibmpM25xIlbZaq MYi1m8BWxLkYGZE0qu4bP2elmsaabrOK8ddartF3SrFu8KvMEEUZOnto22zRwcsVDZZuzarbtWLX XF5WZl2arJRZw9LpaacLNG7h+WQVcHiMHTlm3VaN99WbRk6bNV12jw320dK1lwoydpZHPN2rNdVs s1Soo02YNVEq5WtkRIRKlCxcuMahI2CZUkUOxmW+xEM86Grl5So3dN27POjBk2YYdsGq6VCj+Hb7 ocjuQd8TShyvIukHq5BPIVDamsDzAPV6lA8raeACOKGYK5FyUAh5o8KHZ1dE3b/Z7fmn5M7r7VAd D3DYXXDSPcYXJ0aTIc9SpfUdwQ+pXgjVLEaY6VSqqLIa51UalIyhTsCsOCFdwDprbVTRindXWlCU XlSWqahnusWs1gzWQqjC+mrIgjRsTelrC2qPD07szcJSIgHeFqE1SkaemMZYFKOTUjX1ENzqDBii JBEogFgBHR0RLW1Zbl0NcZUNYVZR2o5Jt6xJESQytiCX4ObMDe4FqFVzkMCIIjm0mHVcREzRNqUq 3ViFSICVEqtXhd7/HbGJsuNc3bDCawmM/yVBM5csrRyPf3zwQNDcDKZrFEqREwF14iiEpVgvCMG6 7B5eFFXC7xizzYpTlNbaNq3hCEzEIIydKqwhKRpKqjJLyzYEbt2UaVfkrEeH7ogLLNHnwnzw8NzV Kr08vLU8R16zmXnGsY0rZSEaFpFnLAQ5LGyIgrhVzzuwbvKjRRiyS2YMRi4y4jKZxpzzkz4TeI1V hszK4+W4zzmRIkipqZ0pkVjTE0BKNpdVi7vmw0TO1iWEGfbVfXlshg0ZMHppCIbOedGDBixXvdiW pNJ6ctzeqymbty9ywZIlu6UW7708ShsKUJqYlSkYq1hnk5UxLimwwtikgyIbYhwbYaJjZlgrNfZz KG8uCDFLGOsDEWgObkc8ykBcgpmZg0lr7huaGpqMVJE0bJTce6hwqlWUeUx5e6F2706VYvarJdiz iIhRjs/MM2jBZooycvR2yWWbKv2oVKvHzi+XR0xZlHy8LN2mlXbRo4bNWz4UYsWxdw7S1VavCzlK VFWydX49rtWrBRRk8pbsGKjklVw/hEVYvs7u2bK2hssq7ZJZOVGbdwzcyQ3LaJirV4aKNnDtKrBR us2NHDpg6Q/gh/Ah2P2fn+LMj5Q/ODJD6QjWEQ+D8YMXj1EP0PKp7pTzMZe3J9oIivaPnK7zzSp0 PV1VGep2ZCLQ7Qb49UKF2IqJVnCVkrd4DE6ImC7Gph9DWhdWKu7CgSbaWEXYMrS1RWGwtlXcizNQ YeJWqWrF28VEccBBQ7Wv1iRF8xvl42gARUQcqCQQQiYLMDUjkjgFKBAvRvCS6Hbzlt+Slx0vLtZs zavuurLKysIpaRWETWLJbqpXLK9JiXtkCxFL4q5EE4C8OAjrJyGZCREsWCgSKHG1n1LK6GeZEcfL WmQqqYRCrdjHOCjPQ0cNWEUTBo5as1WxVmzalKHBiZlydScieRmPCKQHHigbedjIibjIS7aFUMSI g75qNJ3ZjxFDi3X5TY7Jl7gd/OIiiEyBMXAxJcjQ5nQ5kTochiZ03KkCZQyLGumY2xmZjFxSZQiZ muOM8Hu6jLleqqYEZi2iOVIliQ9rlZmfSBKJFEzMSdQBYEjEUUzPARA9Y6xqxNqu8BspYIJMdsA2 IERiqCZIVrwSOB7g64HOpFTA3ImRAqbb2MydkdZPg6wfRYrK+miogBIrXstK1mMOY3LHeKTKHIrI wNCpuTOh0NSxmUJDkhr62wwesJZQsUEJGiik1zGwFN4ZnBUfExNSfGBYuMRKDFNDObZqXbZwhRia tEEm2xkUJkY1WhoOSLbXCYYGpUUzCc7siKW11bljoRjDUwNwxNxzPfJICkZUiG8kfoSwYu2jlisw WeGy77YhvHpw2XavDdoS9t2ajtu2bKGiq2rNZdajFdVyl7dKvXqzdd07ZMlWDp0yYsIjlrrZk3Ys WTpZms6anC7lgwdsGTYqszdpbumCrhks1XVXasGjFoxS7VXcsG7Jm0YsnD9PqRqs6ct2e0zOyiiT BdZRR2uatnS2a6quqyXRmqyambpQlKW67dquwbvPnwz8/vhHqEdQj00iHf5gwUPSX74O5A8Q70TQ hxPeaHm3j61VSiSiQpKXUWKCubqtf5S+TqC9/5f4P4f9yn3y999P/g+4Yp3KJdfCBiZf1qpsQjJh Khkf7CaxSJLI8kKKNtFKZVZf4KN+XC/s/sU/sc/s/8l9RTIU3Qfk6qwu3LhDnRT2RQa4iCjIvHKY SNRWeA57AT+xFgbCbsCogisEFBk0UooCSCMIUMYCNgBkOpGBSRwsCGw0WECb1+G9T4BrMT5Poys5 25mCcEB0Y0WQ8LZCbQdwLOzJA4ZCdEKyoL0mjQ32XGKBjldYtPUIguoYoSHjC2IH6gaRgwRCDDBg UjASBECL6lUge+UXFAeqZQAvEUII+5BBgiXCKksZqLCKEUfeowSCIMTGALuTTB/DO0fMnDa+3B9+ xpsF8Ojk5c9iTN9sBYVDlPQzhP+J9NzKHG9YoGNvwyXLyJFD3PghoUSV7r1N3ez8BKj0snQTGHTi m0hbYFamapisNCVjhTdsmkViDqzpveQTVK0+E31Q8uOCVKzo9L0wgxgYyftywX0erfbRf5prOjD/ SpcRcYQi9RG+LaCyKN0addDpYhEiyKxiyMY+WriyUQqTrQzv6HH+P2a7PXlQVMREJyhzWwqvinPS znrftZ/H2UXzQ7IKUakqChRj4JfAZef0ZDhg9PdxqQP7UDoik8y+GfUmMMED6nTyk4BmKnka88O/ /vWzgZ+sQ8mHTVEeiH5d5qOGUXRg5iNSXcNuOVw5YmYMVUtFU/iA6IDID+oBpgKt6qRVLlBvUzRS rKI0EVSgSwBSKB+yqXFKgxT9QvH9plLMbChJBSokghaIVAJwWkUEFgIwVAUDGQnaSQ/d6QKEWKPd JIUKkUFkSIqMUGIoKoqrFUUYiMZ1JJC1BisRIyKCjFiEUjFVEVRkHQqlKCUPSrIRCUqlJEpKKKME gghSBxYELAMsFkgggQ9rEGIxYsWMYjFjGMgxYsjBjBiMRixGIxGIyIILEYjFIhGIMWLFiMWIxjGD IRkZGMIxUaIqRxOCABm2eXAqH8D+gJIAEoCgCgCKpxqpeqlKhcqmSqWAG0VkEkZGRWBoVTP5MOyY Mk8k4p/qTBgWSpckkNmoSH4gpIK5KpEUKgpblxwc2FpWuVCd9+ZuwwPra+/2b1GEJlOpOM/svUfo qiJ+miYwPBVznDD8TwT0/XlIfg/0/5ef9X/5I7X/SDP4/7HxNMTU0oOkJH/AJhDt2VFBSMn/T/6P /tgj3/FEZyPKh4HYQ9lB3YF57sBLWIVHme77KLG9K/zDSFw3ShSuoVDCYhWYnJ+pn4QHwFPMiXuG NJKzn7rjP81nAqmIXl+cCwg+gdSagxBggxinRDoz8e3Uw575/S21X+2w8CQEIIxkFFiyEgoIMGRA YQCCoyAhAYp0j0v6heHk3m9jAop6VjJgKMDI17p4UPbwa0k8Yw8/Uus/lIIUFQ0hekLShe2FMHIB SQKkMTYUyoXHwXlDkuJNgZvQcHAZESURBZFgLFUgMhYBiPf4cTw/I5nFOsTpge1D6A4VaTWw4FPn 8Q+HY7qd3tPJRBYgb7jzrwCXZGRRUeCkt7K/9Fxt5W/Nb6BcWLscQLHJq2STtwvreYFxfcxTWnw+ uMVNdH6I+s3TkQ5j/McE9RzFx04iBYP/peq1ySAwCIah4nAv1qjpc0/t+nR+4md1v2dEslA70yKw 6fh9yge9HWXePro5PWc3Oj9nz9FhMM2OIatNfHM2mYuvUoZEezUfP0/605Zoh/5/vpsJe6SLcwJq kkicSHCosD9A0oUhKJH8qH5sknjqisxLEm2MkwbyWuQS+AlJ1nSHa/ZHxOzvmOBoie4Ij5nDDvJ1 NjOd28bO8CroEK4ahTYlEooqwavifMN6+kzUu8dBp9qns6LE9rOF48S9Ezjsrpe4fTJC9P+sKE+4 9OZD23tE5KMH5atqV4A1kj5vaPbH4wgTCiZiOzsGIXu/L2JhubqRIpmzNVu2tkRlFKWbhqjaf4/q Lnf84/xlWHUNyK/RGm6eyjNM1opVSszEMH4KLDWXA+zc9ib2HFOC5QONzhhwaj0PfJnys+8r1Jy5 jCQOAjkSHrZoO9RuMD2PheHrzumAXeMnmb0TYG5fevSI9BcESdV4cxsvPgnQepuOZ+7mu6y+Scx2 UBeGL2UbwfLHbOiHrD80OQ9bIcs7kMYgHPAJFJ1pcHU+8snciuoO3t0b2ft+kPs+n8B+H47AFFFI sRIqxYKEhAgSDIHV3deBgHKaZtD4yyFk0wOTu/8ww73jWGP5w3H8ir8IQ/pTAWlV+ST+3NHisqRE B9C7wKMA/p3/YOZuvWAvdIRTDozIH6u8fulDDhkJsDikKBxzqW/jS2lwLLepdrkn4yO+pHsUM2Ed R4unZdbOY0D2nG6ludnCoGM0b2qoypVRSoSimin81yGDlpCWpW0IVr759X2n55T4+R9d4mw8I+B1 LV4fj2ubA2CdRAjBIERkFtmVpj6QshEiTmhR/sRM0KD0j4KlXXzHMfUut9BA1Gw9i2Dy4xA+4S6G L7eEOQKCgM3sObJ7Mg0oXIuV6LrDagaU6t0ler0Ps6TgEiJ8k7kiMkWBlEpIUp+3oan/M4LCa4LP RzDn6FVVVVZFVffwcEPXDmy5CCGv5HV2UO+NIDtuSAECEJNFdfkSSW9f+ua2FcZAzocgaAseYYIZ bxxKONIfxN1PEEA9HEJwdN2y85YFi7kRaeQjne9eLyfLQdBDXxPj5M9s1H3DVPeUBcEwyFbkQwRJ gwVGKVSllRYiIrjLaUZY5lhhhUxcpgGBlMREVFUVyRLEFERUFRhCzHJmYYUMuIqMRShG3GlLK1WW Yi0Vq2SsbcxcYLBUyYDMMWhmTFwFAsrI2WKK3HK45C25bGy34SB1OnytJkA/p8Rsk0a3bILbZDDW xvduSJ89snkdJVFj9i5Dl52C+h25c/i85b9yRE6SyCnjYdga52Tg2od6Dc+vZFiMO4smA6KewoY+ 8lYGYoocYh76r4kOn4+rLqrQ2LYKegnekzr+mHhInpRHdbZay0DB8597FBoaTBHPE2x3qr6BinDp C6YVQmk0/MOste/M5D0Nodp5HwO/1d3Z5eBR0AUPvG/MeKFCZnPgmTHI1cokVLOKL7A+skT0BqEz GLnT8AM7d1eRagIfldQ9CS3N02vieXcnZ35F6QinaN07oBKkqH3+4ij0Iryk6U3fPr0BY5aFvzPc B7A9D5njzOfxdugLsx5gSIyFNVEhtCBeAaEaxH78GEpglSqkQRofnu31bQoq+GMEf3ib8RyYqZlS 3K4G8ZmRKN4hLWLUHPAzZQo7CdVuu0w3kJ62gKuVW/xPHNb8CVOSI5o4x/ls7pdXJbkrgPW8LcUe rc/PrYPczvwWgcQMH3WxewyNM+70rcthmSWpM2oQFiPuAj1BSaH7cZp6RwQMrZ4RT4FMwdRRbSRV VSyUHjBMcxUDBtche2HbweB5yT8QWyvfA3Bh/UpDM8YYq4AMQSKwYiGAghBIFKhRCIqPkY/ZYsZl RfM6PdAD82JnAZ1D6v8/iaYB4HYYqiLFVFEQWRQWLIioxioiqiqIsFFFirAUAWRiIgElPRJyd4eE /vSdzhlhND+y0n9VYFBJ4NGcHgHYncak0gH9PQtQaiFQoh5RD7LqJEI3EdWt/3G9nLyMCDCKxP2v P9Sv2NPwvLz9joM5/gvLyjcUo3aKPl/2t2sQzTDV/i7arLbdOFlrWS4bJZaZS+UIg770dtGbR0za tmqEQWbN3KWbZ00dKP+hmu2YPDl/hEf3/kYnLZR4ZNXv3Vw6eF2TNo7en2wSzaPh5ctCrJRi2VVb PSWyyiq7N61aKYqOWTvvVm7cOGpg2cxHtLTT8UOEeHDR4cpZsHC7tkuyXcsXKXLRVZ4VS1XdqKvD E0YKNyqz/sybv+6EWcuEuFEmrhyswWemZVu0HstXBNO3bg9+/DVwo5VUeXTVL02eXjHrFwra12zB d06cJMGzdkzbNGzy4ctTD3BKT4IIfz/vUPnz7NMTQwiALHRRMlJEqJqtpk8qaPLw7Ucuntdysl7e WLRm2UUVf4/fB7N3w5fLBi5VLJf70Nnhwlu5UdNWTFu3fu/NPv91YiP3Vi0PmUpUY9yJiZG5cwOR yMxEc6kiZMqn6lT5gmtmxNWSBwvIcXMj8UgBTG8wPZCuzjHUfP0khA5yJCiiEZAKKaQFggUy2+qi JF9Pnq9XN1k5joKKDcdZmNKlHMXF3QdB0mp8t+SRT0QJaP0U/WkmH3fb/wzNEOWC/1DQGOLbbaGT eJXpr+8T1w0j+T+u8HCAKZzZmLLuPYc5xkF/FlY6FD7fmenqfYCjnkGBI9DE81D1IDyImKWjBk0V UbqNVXhi1fl/njjZszdPR+398TmVOSInnACljIiBCAJIiI+0RB9xRIizBIG4MkDiP8KZ6IR/qQrO dSsIxoz+8Z8wDDGGkGMEYgIQgddtHzwOApA+Vw0JIp14XWBZEULrEvIloZagoHDanyhmPjEsRHEN 5G8ILH9nIkAmpD0AP0fvVdUA5IhKoYoGiUhFUTlIJ6x9xwqp8teKQiwNmqwk+Jd/xE4zlnzNaqXi josC4NxT+lUDnAqNwmewCmZzhDX8A/oW/pE2XL9rLAazQZ6p0N0cnVEcEZRoUDSYgipaK1IhERz8 xBdvUSralq614fBQFlKGnx9tDUT0PXC2bM7INDOX+ElJWdH+VWO2EIaREQIoqaT8pCV5aIa/riwg Tcrwpu7nUaBjM8n3kaGzR3EQxEtSGu8RCUxMYx9iUvM6K4T8wM1asTMiP1DgkIwaxEQhC71pM8MZ QQgt0kAkAoAGtsOMP0YiQZ4ukTrZqmJL/Qce9Kq6WNl9BZ7sLqn9SyHIJAwcFwGJwkhlSmObKxmg F5XeLzJxyFkQwI8IeBmPOnVoyZb3MCYhIDBP23fbe54BezFCIQAJBhZPKCjpVzo8DvlI8BCEiyQi BrDjPrum59YFwB+jvp6YIwmwI/IPmc9xQ1HcQKsWE7in7RPmgf20ocHpPvPl+X+ZEQUVYKLEEUR/ OM444/D9EsT8nfr9F1e46CmehVECWO0QCoIMEVYXPhcZv2mpI/I0PyJGp0NjYkHoOfMiQKGJtkZh cvaUKRuYmIxIxJ1F/nLilyxUoKY5tiOzyM2rJZwxdN2SGqiy6rRq0ZwjZisq4YPshEqOEuGzFsqw Vcv4/2au2CjNk4Nl1GWVmLFi2dOWy6qjtdppZ4bNl1GjI3KMWzVul4N99FXDCDRi1Ozls3XcNHS7 Vo0Xcu2qzJRZJRg3S1UbMHDNm0bpaNWizdgxfZBrm0ZK5M1iXKrNR4XbrunKjJVw6ePGzNw4ZODV 2xbOTg8LKuWq7Nolgo6fvhENHbRdVozWUxjdO7wwVbulG6rNVZVgqyavo+X1fqS+tIeaFKzMpUiq UJkmf7EbNWr27bN1VFzU3NjYY1idevBqR7gOdS41SwnQobEjuQIGL9Ty8KsmiWpgu0YsGDF/bERn FGD09sUmRQ5FjY44gISFKFCRmalSJkZGRkRLGRqXGMDZhygbGZM9xBOXgljEPHx2sRMzEh5Sn3LP Dh8NnTj22VcLIgiPo8f6ElPr7fCz4ijmPYX8VESYL23Km52IQNzsRNTO25zMyxwYmL24cMWa6n90 I6/vPfyy9xEUaQg+4Qwo/xnvrNJB8CwnqP5/eOE/jq6G/sPjpaIlKfydif5NFc+1uDRHnC83Sijv MDASrQozKGszRif5CmwR3aQqFOvy+eE9hD6ZDIwfw11Ikoot69sU9QQpOgC8SO+xO11KpzP54Jtn DMuS/71A5OMMy/lsmXDw/8JKoKhKlQlrS+qOdSRHjqkZ3LFzQPR+CtIZQzw7vE+vHNKgq6ooDhcA ehYIERH18036JbqDjGKhQCMTMcP19hiYmRiesKIWDwPM5n2m4pMgVQadWZuxI+Z8GAOXDAuOWJqr Jss0VWfoZsGyhle6ik2Zqs3DRkqzfRysycLpVZMWiyyjFkxatnLJqoly2bpYMzdGbR1ERxBZLFdg uzcMWDlRixUVZLKsFXDpsu1dLM2J0l+aH9JiwS6g1fp+lXDd4bOnl2l4eGDwWbwZslUsG++yrRg2 Xvg1em7ps9RDVRu4irNV6dM1mSXCq7Fd08NjBRm7VbMm6zY4VamzZRm0cpQycO+6t1nLQxdtV13b Uq4Yuzhi+sQfrgkiPxiO+93hu8M3TVy8MXlVm5UaMEsHvJP5wcQ/dCUWW0aTOGwOd2EIRTpnVBOv zKPPsKE8pX6hvKEwk1RIEyIpAmExCUJRIkJmCYCSJhCYRJIiSYiJCRAiDIEgQirIANRZEYDPJvcQ SB/EFhnGJhhD1QPiJd1y8hF4tnp9Ze8b3k6TwPETqNAdYdB3HaYFB5GB06TSeKi35qAUbqV+8/Ri o5XS5UcHKy7Bg5j+UIk+kDnzobFShYMjUyHNBSJuUGGKEDA+/qzKfoWHUIkrMQWSis7zEGCuCFKw Mnhfdu4cOX73jxRkxcNiZExMIRszdNnPUMVMDgN8xMx5PmYOj8lRyAKE3wqtMXkeuAE1vartPMix Img5yGw3Gwo5g/mchymJx8hrIaCxym41EOnt7PT77WJ5yTya/2tz9hvxDqLVIydSqVkL7YDngGYQ IHlBKM09RiWLNz/zlg6VOhDcB3asrKazORHE1kwNxmDN3QMaoWEREKlTOD7gqulF9+n/HKChMvEw /O+/L74UX7xhtQtUwxh7/wM53U+thU8BQPer3I8ShmVbwMpInCAhZVETfLKDveQtN3TbVCEkn/i9 KCwQKDCCp+fn3A5QhmP5UHCaGEmk04XeZY2IYG0wdawLRVVBCwmEYGsMSEnp85Sotgk9aHxEniQ7 U0J16vXaQqWWVcQqFGRMxEzke/gP9JIQ43Vjh7gDvc/OfvE3NLCGJSddlqQ7ahBIEUIMBRrQUoEh CFL1iaC8LBC5VESvTS/ADpcDVOiZmzpE1H3obF1ujRiew+tBswigyUjlsZBMP23EcPI9gZr+utTW hOGUQHhK1uUcyCMHOtpjOgDJcLBolqxEuJY5GmDMlcWIb1LiFGU0DXmWGrhpNTQMj2bls0BSTWrm pgm9FUwNOBxmGLoLW2WCYWy5c4Qze9zIQXVgWJDClQFh20cfVmvwMM7aDnO6ToAaNpWHcxRQ0DOL YgOnaYhiUIksNzJO40TMI3Q1v15edRZR3rMxcLK1wPAs3IM0gNk6SUPP/Du7/y+86jv9pAYc0O88 xj+U+4oHoWLnM+nb7xmYl8sDQUf1IkDLRVwu2phh3kCBkXLDmZcgXMjQiRNRjwBOogfr2IEidBak DkQMjgYzIHAMWHNGDJd4fzqxeXDBZs8NmijlLh3ERFmTVgxZKuHlKVFGfKrF0u4ZN3K6Xbd0Ztkp ZKNmzNZyzaMVWjRZksyapZLNmz9uDhg+Pjdi3dO279kQiDh4eWTt26eXhp20Uu3ZNGrh33mu6dtm T6QQR6YvB4KOir8YNfMfb+F1nZ6dM3CrHp5cLPl0e27NV8xEQouzZM3fLBpBizaKuWbZ4Soo9LO1 lzdRU1axgueX9v3Ig1h+r9RB6+d9dgQkONkPYFhsqWGgglEKasDA//P5OJAAXHGlTsKDvDobnBwW JjCnQ5ky0emCrFowH9spSTKUiJIEwlJCKSSIRiRAIsSCb/aeapzchxvMaDfNzM4GBTuODgU1NiZA c4LA55+dT1MTE6GTBZo8OlGK76Iu+iWZgwdsI+kw5dKLtGrVV4VYQ2btUqPBd5bjGLrN1Yh9f6II UlCJ+KqJpKImT4+NY8tm7R28LPT+vGmUS1lWpuETUyTcgZED7vwTwPBU+/71RU/BRlXxKHoBh0vN z1UN/fpMFstmQuOgpuWAFG+YmrE/9Lbpd8+Wwbg0OqXjYqPPrFRN7kuPcEPsM85M6B+1O/0ODqeB BMTkeZI9yQ5QIFD0NipU7zQXn/ZQL+IU8hFDmxLFctNjkp9EEtOBB3svMLgTXeLx9+l3AHBxIV7Y p9YPj0HVaMosw3tb+QHH8zzE1icT7GM/4RTk5AcUPQcckNmz55tHRzJwVe8qnUtsARwieXLn+IZN bFMANBCRQkhBVQ9oXVBIcZ+/h+7EhJPhWeuDlwpSwx9gV9se+q1hQa+zMgMgdUpMbf3zFfSQPvjy Kux1aby8+NG920Y2NJl9LmojNZmVLEUM8HHFMMUo0iJFSkRFJJMo4KRwmGEryB26A6ilq21sCBgk wB+rLrnEBYHAQFQvvhk+y9IMdilt1082yiOjEsrCNojXnXJeubIdkNJsJOGppC2UhrknqhOrMI0y iE9MFLpCn8xkjAeIogs46Hfy7UYUN56EvKdyMEuF4KJz28KZHTpORnPc4WmYnPffq9xCNqaRpK50 VGQGHjhu3ObXyIXyxhHTNnDjxDakEkd6IgHjXXGt9MOAwUeARFonBA0c66vfCb8CyO6QYFERKliK NkqXZkJZxYXaE0CupgKQZ5DXUwBrSLjXHJrZTWYUJImgKpgpRwqS0mMZtR6SF6I612ViywKQlDQM vS6IvYwZ9HiWPknfgv5cvEd521yjXJI5aUFHBbsZSg6GupDMOUUPubL7/0W9/wj6Vrex4PePd61X 169XHsbWjltJKyVDBvNi4ciAYN0NpozRvRxhz23htH3ZkKmM9LdQS8UFZD1GCArqpM5IXcxOCWsA zcmp9QFFAKMgdqGtjJUKoZlymZZyQVsVTBCkWkLqjFtvruNuw/S0x205FmGDckBaQFywBrgpAYCh JcBEAbYVmLnnLdnWYWHMUUOBtSiHyhR5liyxOFk4v0JuolBAabGi0hOlcShMcJ27hzjjkh/CSeZD kzoQVVIPf6TkqpnjGzG2Chio2oxEaFoN5Y70mFFEXlKmORZkpYCJDYIIdgngfTqHzQEO+c0NGejA /9ZndqUR6PA3FPwNp5nSdQdBD5EPcXFBjc7xSpEid5UxHMTqgn0AzzxoOz5Ez2xyW/tLP53rlxt8 FPL35YPaeXfrJvTw+Na1nhTy2/qtxh+ry7fZPtL5xt6eRqdg8SJ1OQQFIEzQUc6jFhnO4qVKuWJH kOSFP0ff7Fh3qd8hblTAgZlzcxIGBmGZc1CBqSMSBqWMDEma64mpMhDl5/Pnt48benbp3eu9J29P Lr6ei9PGvmunrm0e7nbTSHqeeWF6efPnj6xlHLHSBivttHLPllhivnft3dz49e6nsU5cutt+NGkV 7cpcrXfDXOi9fXbam8du2HW/SPfU5Qcwy43qzYRvXHW+HLxF482x8+lvDY8UE9jE9vZjE8whDyM8 9hep2OZI4Dv2JHsaEjzKG5cYo7VZLPwbNVmjF5fg0WYs1WjBaI3mGJVWsYJYqKRq9OGLNVg9erMz Buul+2DVll03cNWzRq6WeiqXKVGTB9sQ82aOFdWLpRR5atXlwlus2XYMF2jvvJm7+9Dx8xjvby9B g7xBjuUkMzCzgnnCLOKLGAMFJ0FoNOFWKoMJhjfeWSxA51UxURxEUMm4QcExogkappVOr0444+HS mkN2vUGNJc9wSwelAcxhvPOuBAkAMoKhSQRQVViIsiIiKqRUZBWCqqRSdjkEFiEw8BCwlPtk/gwF H98Xr5kDAU0JB1uLlvtFFyBFghCJRKIh4TEIjntYvGOBk9wTKJTTCHs3OGgcMcMMgYo0YiIYomTA xKgKpFUQQRyCJUoVBKMQiltCNcmCK7PVnEDAPOB26E2yJsHlU9ZyQ0GYuSSagdxVnY7WSPC9ZBHI RBvv0glQkAIMIalHlYAdRzHYdZtIdx2HYZBedBkUZxNgdxzWd2s+xXgVgrGRWMYMQIiwVUEgpCRI 1eroyfcrWaRkrBV9ZDRVBWIiEISX2PcbI2ND5EiJ7nIciKaFTmGpOZQoUIGJ/qiNCUSQw2waM1bf Q2WXKMX0YKvolgNgbFDhhOxBKRPu4rSwKp+iqfvsvzPKlJ/zInTGDps6VeUpSwjw+XlkP2xD7YiK YnSezyKDD/h5E0rd6Xn9rbTDnq1g7TCjLWVVS3bhgQ4kFVSuFGYRNSA1DZKoKEBftBvJl3Si2VUO U1+rh3mhQTZfBswoFno77PDnfdJ4U53xhKM9SdbbWhFFBRT8BnOQ2ltC7o8LLish3hQ6Fk+Bjmew 5EY+o+DvGMUxFE1SDwbFrYAdBpPM1m8Ym+PKoWMrJt4XnLqefXJLm48O7M0OREnFVUgaBmfUUJl3 UIDimxpNon+cAuOEpbMvOMnny51Xb0+4TlMRG8CI9vsVfg4S2QauWDwwe3s8rPSsYv+aEZRYvNeg uL/s7x4QG5fZMxvf36qs5EPHh+Zep3Ho2PyE9JqIxzjrKhcUNaig6nqND8Mvx/I90/TeKkIuO//v A2ntOBVESKS6j2tl3EIfsBi5eXalUZYmjKL3hELeQNRP0mhc/UoeGde2QvcSsIH7ojYCPGiVUR/A OB49oAc4ezjDHRyZ9cJatr9D6BMfRlJMkkIQ1ZATJIE1p2FKSakUDN+RYMFQQuuPwLuFUL1gqk8k CBZGMSCIMixhBJBgBBSAKMgOJyZ1Lm4AgEFjUA4lhOCoI4yzqmyRWCJGCiggIIIIMAGG/Dr+jyzW YZ+etZ6eO6YQRIsEKm2bPD0+jDnnlbROVRjDoPCFB4N0nB5evPk8pwXeUTsM7Dje3r7tGpSTpgZT gs1O53PCiiXHNPGs0KwNDOnhcNWrQGytaJPHjnc3DcqRjBVgUhR6uKeWanUmoMBLKG5CxDPP84E0 TQHXrnPKu+64dbozxpeemBCWj6MmhGTB6xhJGKSMYQSKsGSBZc19zZXaZx1iv+o2LyNUOsNI+83l p4sYRBifr+X+iX3S8GjDfsY1KKlO+rnBIpIaagN4qk+m+WJJDP5RBiRQSIREgiCQFBFGIMIRIRGP 8ONe9+Hhznd8eNHPhsDz1wJ2sLSCWXs5GesvoINNFk2BWjXP2IsyeVCiDsllkvkybFF2GbMKpqhr b1HpBxRoXqTJziGMhr4QgIgwBZEjGQIsFRBgQCIRAYqkAiqRESEIo7rNHCCGRIRgQGQCMQS4sqmn 1QxwCik1Ab0m/TQEBeEsxV/xYLmETNH+flBRpq0zj6Mk2I6hJKUzB3njcROqII9/HxocXwU92UDi D7xmSoC9Km54AHuhdVYB+nO51U+J5qaIRzhGoB4nM5/Zce4E0hiKI5rpJKVT8UgeAdyvQqn0E636 yHrBgEN/rrAZD7ERgsNXTmtYZkjcWsG/VwC/0KkuhJLwjgfH8Nv4Xd35VsyUzkDAOYoE51e+qRIG RnO0hqLH1PyLjuPyMjYRNSBwdDA/f6quRkYkIbFy4xncX8zIcUzNDCMtvjTjKvLVqyXVXZu2jNsk 1XVSluqzaMUt2bV+LZk/yRAwRBfHRNN3LZu8eNlXDw7Uct/Lwq8si6jJRg4NGCD7dWLFvvdy0YsX TA4O3bFxEKpcseUxw6WYqEDPO5mYilCMZEShCGpEkYljI0KmBAuLQnNLlRmq3YsWbXwzcun5xGey 6m7w0brMiJttgOTImRAcqTnQsO7lDQ7rj1YVtyRU8O2DFg6YOWDF5crsHaXDJq0ZqMl47f3NGLhy xYtV2yjF/lQbqOGTp06YPbpLluS2at3bpol/Fy1YN2jRH64+zzCPuZO2Ll5LQcuXh4eVS6jpgzf0 fEREIQ1fX6/J4ocqP30SRInWcTwGk2ljfOA2G0vOE8Oc4zg2c3OZ3inumWkcjEg8EyKFCR6IhAiY YeYhsbGDRytw+1g8vTZKijbbJZq4dKOZam7tguqxauII6RH1OlWD0uxUX1KuG7yxQIgYmI1BUJdD 3Dn5MdKKtTnzVdzbAXVEJFCizpyq6bPpB8Pb6MlWTV4QiD15hZNEaCaBDd7nMJwcZXiIJ4B/VRG7 OA+lRGkUfsIvNJJH8al4FrVRR9QqxODlKfZA8nWutsnfFNUVyl08iCqUGs7ZIfUuP5//1e1fUe7d cbJricgwRgmpTAVDYnQdQZI/UTlVTIz+6sXXn8D0nYvQBvHiYHeWDLgoKD7QSVpShSTE8/PWbKhR EZCoFggjIYICkJzz0bRi3C3MhwM6S2RTTUpEIJhOS26uaih84Gw0YQ2QqN8boxgWI5jC/MWM6OgE +1CH0Rz7ynUG8I2/gaPxQ43hF1zidCYpE9y7thWUIuL6RaCA+wTuw2hm9qgaB5/Sr1cImtVO9RCc AhWBWFYFYFZAWBFkIHl5elbeKaAkCcHjT39AqLGKI019sCunrs7TAB3n3K2NQPB6tAqaol8SEGQB bjgDKBevMDeinVBN938kfXzLz76JqVPikvMydnQFluMr+DZdpLKy3Ke2nIA6z2Kp1q3Bfn4NAh76 H2fYJpXi0o+k5wfHfrqWi0BwYpFctPmKKVckkNoQEuGAIUqlF8DFDxE4F3HcHOcQcSOQB1IbIR5h H0REHSgceYj0eCFYM/FChCIG6xAMgj3o2VpihcqUmHfWZDwkgshCBFmwsv6fu+ZZNiHlvicfmfrm +XqMvghxKb22CQiB98SESQIRFKEgINDFGBVKowIAsAN7ADhPEo0cSS1DUDBTzv7kxFDw/f0yei78 hHvgHugqx8Y+79ZIZj/oXg3k/AvyhZhCrizG34IWDXf+9MFaV0pe0pSmZSRH5wP57PxItAcPz6aG OlTca6OI+8hCOhONL77tBiA5UXHSinzbwf2HjMONGA+kRiPoAOwQzA+0LhUPHTwb0+8sn1PGcO0L s2aMewppooo9Ppe32IOw9YcKKcR8zTsQEGdl10ZCEpX6+ijslwX7vJTrQv+xHSfRXHy/D4fADtFQ 0Idxv93zHzRxdjvwQPtRSn6qgus0lPnFwgUVItELRLumAYQL9BDCB8hf0E+M+koqqzNcTbDeQRPx DRouMFU866EAOnS81pGAQEhEkRkVxgpUUI+N99hDoEIq3+ICKUKYuo4czXOhOkm0KyYFIeAmwwye DOS67ZsTEVSHCjq+Z5hIk+woI1VBS1BBgSugP7jbIP2IHtYTxjshINoheI4hzthzEEcSRb7MGkQc 6n+ljEF4RBA5FzGJDrUDP8pJ94oUpiaw5pnURkAFbpuEzE+wpEuH/F5Sff9NnYP+7ltkADxnnT9I zRDX5EP34v3iifONIJER8bK94UAwYRRPYURIYA4EZ/l/6aYwhGRnAtEUwA09agGTy8R4CIMs/Cfw EyXaVIjEgiypY34mnb+fhvXdnhRTs5LrGbNfc49eGK1CSJT7uSLX7UyHIijoed8KLkToAVifRKjS dzIzsTuQzE4wKkkgkEoQVuO0gK3CvpuzFJIBUGQYQS4hYyRSBqdxrYPt/T5yzNedg7zDPp3UeyFw VH12tGeg+7Ni3IhfvVdZTGW3eNjFVNCqUqm0+3AGmMAiDFUgjAYRAQEFAYMEFGKMAFiKEVSACQRQ igBBUGArt/CIkiDGARgoxhBIqQFi9ongj0HUdKf4cdqdgh/RZFZGRZJFiEYBFA6DwQgwVsIgb6nf CLGQJDgiFMZBijOXj+6V+ob/YyIZCgL1dfIeK7O+PrstoeQkOTV62zsFmsv4HzJA/CB7qcgh2eVY jkqmsN/T8FKxE5g0Ql4Vb2oaL717UecOd5c6lzJJvgfmhrCMhvBTKyloFEKwWWRUCwFCLJlshCVC QtF9e4lG+j9RTtMkbjkE9gnAg/kAYrkePUf3ofKrw12nXKiLsYiYjBDhjCNqxCyH0b4dHYYifUOF Etvr1g8S6Azmn6dPpOoTFFMges4DZTOoiuN1QIqmsuubyXm1QDgFN8TV4KcB+PShcrTjtXiXWaqK 3o8ppR0ocFsC9Qy6YyhNhuoB4Q0NfFu4uYHfQiPOLcQNn1EQcVyDx5UeT5qdy90c202q6tLrmw+S N4G+Kop4ob6HaEAPavPWW8alAt+iH5qbRO4Obl6Vfagakc16HZu6pRZadXha28uJGJA2UZSFgwjb Rr6M4yppICFViMaRHFzGYBAuZs0Fis0VgtpSHBopdZhK/QQ/zgcTNF3SnpOVOZG7eQvQdxiB4oUj yIQVEv5u8TsQ6RB9hq015UKIJgjgUIojklEumxjAgnknX5gWMMIi/ffhsqQiOgiwopBbBZeVD0oc pnu4wKgBIByA026E4SZe4paEQial4/hULRAPG6JleTe2EGalEdZ+ny4EDoNAYaAokyM6MNG4Jpvw q8maOrZk74wCerz/sqljqejh2qH2w+0E95QMhIpP5tZNAygyKTQFlAP6iBYyG3QFpJstVVVV3ukx MTUYsnqATWOQcjVrh403q4+Oi87RM2WwPStA+pfSJ8oTPYcfEMPilFkQ0HuC723RCZskwFC68sN5 EL7oANB7dfL+FB2TZ00HxOXxtbmBCtVJwFqfQ3HgB3tenUj6uBA6dxDooMwJcAcYfmql1oYKpcah QLlbkz63gkPxkOh9inWBu5NXwhZq4tYo7dlC/FCA9aGvgNBsT0+ZhnJDDCcBSkprCEe58YBRAIYe 4iPpaNYRb6fhEBI4NXSIsRaEPzQ+mHIGoD0cwN5XYHaEC//K997Aug4Q+PpqTsrxzhmCEIQvB+yF 9/O/EgqlxAtSnxHpPb1XU1RPSfKDGQBnslKILCqCixiQBkB5Eedrp7+SyIJgGX8lURMi4uAu2nMF oqiJIyIY1typE5JjhVIGIcsL4I5G4gQIAPvVSyUtliRKMlUzGkxLjkJCVNsosvrtmVTwEzI/ah7c 4mHeimY0H8Pj1AcIpmN6QnEYxVIukS/UIB+pCz6/sR6hOY37ySaDlg8xYNQBcXKfO92jYKSck29h cBZh7EcEB4LBIQtmEULcQX7dsGEdqkvMWb9NgfE0HId8P1NpgbQwDYfYKH0A9KEPX54bF9xAzwnB TYquIYiIGmwxKTBkPZSwP2powQ2WsTYWTWa4dG9YwCbhrZvHQU1TY4kYBhUuzMLZszjA2oY6ExGW NJvMPab5OCGhIZg4Lm5QrU1qyIcB/zbJtNDFFZsZWiUdUi1RQQZhZQiKRaXr/vbCx0pqmEYMQ0z1 5ZsL1pDIByzMCsBEYRQhjIERQ/xQDX7eVHtKPlEcanej8kfAA3w0oIa8LWLQ1xVQuIE2KQG9sBQ7 QaLmxtbDQJAQYEYQQAFYYQsLFYBCXqWD6Ba4ZmKaplKejDZ1iccONlV2WKUsCoerAp9h6aSJL/SJ oQ1Upy7/CWSgBsdsD8TmSAcm4bnBVEmkgoGDFAkEP2IBLo0FwiDahKq7/qBev3rg4MSHrLZIocAf myWamiCMiveJKJUCopFFF6pLbKgIiQ7QLAkoixToLVypvrsghhdlRuKVfQ3jwxJIRTRmUEzAYfmJ SgWgCwkjGSEYowgmtGIsYKEAqKUlfkKhgH1U9IhuL247lUzFk2FxY65JJAIEQkCRkY0MgT8OssYD suo3g1gedbAfvIakfkoxMbCpSNo+r6IWh9MqEyiZpIpEkWEUogakn4yU/JX9lttVVVVUJSH42L4R ft0CaOHWIG+EDjjUuL6FiEga5zWIiCoBaSIMKiNEJTKZkIDASIAfshDA26asRlpQVYrFFRGjZJ1Q CQg0QjQ4iBI0EALQuuQS5UNwQuvZdZS6yKBym5G4v7UvbY0IDGCINQ4rOVwAhh6luQ0hDim4H10d qrm9Z4P5lYwfcf27LJcRYSVzDWBpnKGmfSju8IGbLANsTiH9zAwhyzSHEGBd3Z0+pmf6Yfd8x8PW KKChnKDAollXN1B4o/u7TyL16xPTv5xLtvKupG9DoKDDghm+v84OP/ZPYSEhDgugfHj0GF95BzgI ansNm+0Kd4oWpf7NDXIP8liFgmL9wl+hAb0zQf9eaQikFkRhEkgkYrGSAKwYjBFeLqJlqNYnAD8I eZtqf/kPcWe6AcZzjoIUGtHgi/goCZU/mH9gAkkjxufZpyDsiFl5YpISCRBkM4EETHJJG9HXBZcq lJVAACUJw0ehH5I0CB0EgGgDVEW+Eki1HmihKIsylgpWTGVAkUURiwJ36oLcEIhFUkEVbhigv/OK COoweFzDokoIEPWRSoMK9QWfNVIXBZppCGrUAyBBiECCwE/qjYyYmSd1+HuuhqBHejrFwEQDBkIg QIkZCQIRWRIT+zVSQJGSIkWTNtfp7HS86ru1mCZhIhFSBOYiXIdX6Gz9C4FU/0NeRx5J/8QPGXhw EVD7g/VD8kcj7nNGg9/RTjpLWDShjiHi0NJQLKtL/rBk1ujCCBrl0CRkRQec8AMDUTLwcIWYXEtE sHvJVLY4kMNRhc/etwoOJpNN8JpB8yMHoRpzIXKpqiqIkIKp+vK+XW5ugck7HY/3gkcpQRVjEEiA oJPvg0kBhg3daFtg9xEA8yAB4CUUKSKhnDiSpPXYBDxQMSoDuiQhuIUQOjcl3YjM75h/hVMlUROI yIfDfFOtVPkxVETwv4whADtmljnDn4qo0ypYtYKh4IYFoQZYO8SKpAnEj8kPyDZqN8s8txQHxCj2 BBA9lxQpDwS8KwuKYR20fZlhkbA/0d3ciI6nxzN4dDc5hSyoQESVCVnZZzC8IUYd66uRMj7Rga3W q/UYqkGzenpaKgbav3iMSpQXBJvapKBKYoDZE0Osn5B+YlHavShxg/g74l/6cKNwfQS2cDrA3gen yBo2LsCEgQjICwBVFkgpIshIjCIhBRkUkRkVkViQBkAAgEAiKkSDIhEGAJAQEkRgjEAkYsgBxWOE LI6S9VICPKreECAhFGCjTSBYohZCKEA0o+Dj7+Uo5pnIAj/RVP7qp7EEHNLv5/OjpZD9CxxOF7+9 Hg7iCKGrjQ+uhjEgjIDCMhIMWMQkCMWCr0USQnYWFqMgLGAHEp01ZQ3z5cznKVIEIESv6JCmAqmA YdyHuLjl4MrZjpC4NwBCCEhCDCSKDCZEVKCQ+0zNHCK7dUm+W2YCh6P6oRCsbH3NmsFgyetY0mEz GE0nXGMyA0ozOjzq3Bm5crwSyVG1c4k/vLRT1xKhqy61U6xVIql2LdRgECECDVNdlFhaWFpbSk0U 4E9bPveJ/qMAwMmTLAbNQ9oc537DhDew/ACwoBhEVInDyEFJFGiMCE4+NQu8sQ1SRXgEPahwWDU2 e3VfsE69Y6CKvRAN7JTfE9Ilwdb8RT1K2Q0j/X78d1kfES8TfMbyygYeghDn0I/iD70Oe5HUGKFw lzi7eldaOwHUJpU975hjgREH3oHqEhFBiwpOrjR+aJnE5fe8nSYmaCSEJCMIIzfOoagWCiqbayJ/ AHDrQVVKIJ4pVhUqQ2lFUQtKxIh89CisiFuZjkQYqqgiDyWoMjE0wWGSMgUUQxiIIgLFUiiyJw0g CwEGKR8YSFgYwIadICJEkYIMCCRBkMl+HQAfZcdaPajxHV0t6D1Ln5gNQNE7xAU9FKp5IZlwZ/Yh n0pZNwCKpUSMC+bGAHxvsXXKA8ZESlOL9cREHA5VU8ej33aFMwMAgEIhIQWBBItfNc2JDtA0l5tN JaRLR0fYHwDXJAmUyiX9PL6QjcZH3BGp9453hF3iJxl4S6BlQQuDMBBy0EKWHygw1zNFUJoRakH+ ALxCUOoammkFeUxvSlHxKhD0F5qSz3LrN7Uid79YGKr8AFxyIH2Tr7SjQqiJopNceqdZrVQHYByj CFn9b/noS/n9hwglISWOhMQyj/ioeJhwRKLwZo/DPemXAcDLXTFDlF4w03TgKQ7YHsT9D64etIxW DGRW1TuZf92GGEiIQaJCIVIkGH3Kp9yqUojxKpBRCwC9fjtDvQ+7oGySFtwovtRTrEvXMj3gHYDz i/7yQ+ui9nZv9Cd80bx3hcGYliNESjgOw/hooS3leu8bz5qUBkEbhQc4H2BYUqIkCBqgCzMWHA+C F95PkGkTaeKxEUURqEoggj4B64GvSQnqSiAbbkMAVTxA4SgXIIqRIAbv9lU8VfyjI9hTRRTRRSSk hSwKSFglEoNEoNiUGiUjLBLBKJQaJSMsEpIyFkEoNiUGiWUpYDCwEoDCkSwSglglBKDYlgliWCUS wSglglBLKUoCFkKlKDRLBKCWCUEoNEspSyRCUiWRCiUGxKDYlBsSwSglBsSwSglIyglAYUSwSiUG iUGiUjKJYM2H24KUqmraPAbigJGQJAhNtUyUpEB61UtUEkgFmECgoi0kFzI2FUtagoq5BAsKpgL+ AkHiu/BG8QV97GDU+yDA0zicAiaTMTMUCIQmQS8sskh3QmdCQ3fX8vG4fxNX6E1w5lT8q55EE/Dd oTaONZb93tliyyQCoChXUVSSpDCA6kQGYhQ7uLIehwGSDaiVEhyLgSQkkVW6vNdfH88zY9xSmdkZ j/rp3OJ3h9ec6oKclUhEEHYIL2BI9NbWdyaZQxf+NSa8pRMd7NfxTiO+hdwwNJ4jKSGvhnc/n53H RlXMEGJslUGi2fhM/E/dnEJuhJRjAzw3uPZdpcAT8VhcWhQJH9/eZh063z9r8+dXhFjxsuno+r28 HMz1U1mM57zzPx7FLketH/iUHuE5ynoO5Xe0Za9ezet3bOPhzl7tiqZCqY0qmhj1Fl5IoUF7YTdV XakNNlRRjcrnaMWtziBlDECBkd2ghZP2pKIaTdC7cUdRrTBbpgomJKTXH0ZoOLDIgFYCdi1xJ3v0 S9/frKPn1T5whYMPOqPwKlcKGi76adcTFvF2eo9YxnSfiieSUFUYxZ9zd7VMHALt+BdfRRRZN2gz 0V8UuXeF1Vwfgl6Wun3hD+IJ2EAhCLCF9J4eYeYB2ukJ3AE0CKHEIoaHmnRG4W9CkXMDkDnFQ4S7 hP4tlCztKKYc6mSqQUIqIPOdgce9mNI5Pn+Y1iKGrmG8LmE9UhCZA/pAQ9RCXEGSRtY9KOceMQ1i qKdqKppVQgPMak5hPQYcxo8CCG4Q+gnOjzN0IyFKHb/oBLdw8QSDIEikhQ8aR/bgRSjlMFQvOznr lU0m8qTlJQw6oH0FQsUIAskVh+6hDrtReKopEo6DMROyxYQMsiyNtsAglHZliSOBZEZIDrRrIN0Q K1BCTMRbUAUqVJA4ZAyZEWJwNBiEQURBJEjD5kGgg4ChVUlwLVlYKTMrFEiiMRRRWKIrBQTgwsAd GDw7PHqDks16KJD0+mp5pCNoGe4YQTA8qzz/LL3AwQwd5N6KInjPcFIHSdWUrL40b2+bThIwRY/K 8Naki4OjNmI3G+fpwa4Wtm5QgjSnUR/dG0GC0xJk/rYnR1Rj+x+EzOX+WynB9GSBRBWog2B0w4VU RLe74KB70foYZiECSGJmBB2H80fgD7xULy9EyV0nghA+7kNmAceNRKIFfeeRRtvvJbCZiOReKHvt fy3LaAXzFj6LrWRTCGUBcC8oDYSGqgi5I1Qc19an9OUmH55sCeMKIodQ5FCnBCURCDLgidqTZCxK 6wSxYUCiOogQCAduE4zWYItAwsFNEcGdAgUTSAICSJhq1QcEEQZpHOrCcBDAsBUb1p0NhjEpEvEC oBIx0ynRWSBCZu4BDwIrZTRD0OzHtNaDPDxRSC+Nvf3TiQWRFYD0pmWvWHfBRw9Xa874wqzBnLMS uspdCVkF0MNHCNhoQILCbtmCSjpJXYNFRKZJIQhjzmo6k7IRGGSSO2aVmkiIHbsFQHk/7AJ3EPvA Nn4/A9KIg2eogfZ+v+I9IcPXxRHiQT5pAp16rtE+SqZlUspYF2iqTcjaZ4zHEuCGETGkVikSYn5E MIQkmEbNlEBlG5k4qXFWLWIAjmFEcVArBuLh9HXi4NZqhgov6hFiSRUMlugDIihIhGgEsITDQr4q WeNxA3iL8yBvuZfxB/yX18tCDHZImUMaIohKR5+39ak0niyFyJgsoDiVSDUIsIMCLFcW4oJ6p4u2 nnghmGWYshYHfzTex2qwNI0qIggmjcyEd/D6/bx+FPpOxzAh1iSFxx4NEwia0ZMctG3IGIANsghL QdaqaaLdF7YgpyXZe/0GotOBL0ymVGfUp2SsTzKcQsKI4Kp6r5MsuUTIXw/kvAKbBugyBGEDmpDA NIh8CCpxwBJBKFh/AE85ll/GJoMkup+9G0dWOgzI5cz9zmrvAXcXZQxUWFGqOsh/7/yzB3NvJTHm YgN30dhGM/OhqBiCdObHlFOiZmy48SyquWpnGkEnTjdwU4wNUuULkwIiTGYc2d/0nvQQch8MMyTg QjElkAheTbagzkDtR9AqGPJiCHEiEw6Z6o1CnEVTPmeZUvAB7Eotf35zWazRsbFLRgK0ZShUurKZ alBlsa0WWI0WlSgrKwQCkllgWKwAGW20YkSIhIRgpasQKz1a0qBGWopxq4e5Gl3vtMM+UYfzF0q6 YIkQiJIBOgrISvA2AIf4bXmTH2lEiQIOY3gIEQWQoFBsWTJVIqiJBVO39YH3g2LWEFpGCnuXfP1M lhSBloBPCcYDgDR+SraxeRgSQc7BOkwkQszspLpvzjJ6jnDOWwJw1QgOH2K4FkEH8EUwsqnGKfH5 RiqkVCGIt4QEkVBhmyXqR0II6lFnw+KHtQ4E1aw0qpDdjZVP3rpzfSQBOI5YJ6ZJJd3npUdQn3Bw q8ofateKB9Qdyub7jbwBuQ41NSB5o8oHiC64DvwUHfhulQdACXusSKF5FeSAwewRDEi0yENH3QSu m49Yn/fMiDtV/D9liCb0oNWI2RkSMHkd5oA9QdymdBS3T/CyeAEvE4kPBDOAHGHyiXH+cNqqa9+E NZxRJQLqeWkU9f9NDZ6Hcjt0GlN8f5FyQhuGLZWBkGsqH0o9x917Y11rRy9Gd2BA67yFhaVREon0 +3U6Gmire4pPvN6rjagjuLUQjIg6pGB4pAz2AjEEEGEO1FUoBbKThn56jQW1DgY292ngFUU4zuhP 5iI0Ylr344PTGdUA/3kJ756xPuwwcXA3CaB/j05hT2+4Triv7xNnzF+R/uMVUquSqJJCZ8iSEIQb Njv+zOiYvvR70eBPeGuj37Q/JA5ftEOFQDooNKqIm5Ti8mHpPTXmej93ndbcpxWHRMZIR++2y1Vt vXn9r+mE/SB0O1aIWkVKnz/OTno5VMFvQ0ffLLch/GxtRQLe3goitBTJWDpDYGYIBAxxzYOBd0cw qGvpR2EPE+cRlB63hnByCGxgsiP4JdfL/TX6WtowmUxmZv8Ce1kWAsUKhUIsfkuZJLlJVFQWVQIb eJUBeD6o7ENqHN+YbAR74yRknZh3pWBbVIW0BYiRK2LI77NYUFBghzupT1aF0IcZ7HoXnV3w9QA5 PsAOcaUZJJphU9MLKsIzt6wDkfQrqwDOaUDD3ih9ENu9cHsRNRk7wZ0bhOM656OJCg6JzEPAx4j8 60henXBkBeR4ka6s+t+y5yBBnvENKPcbrk9Zj5WsQNkR/ESKZyAnQBkLpiH0U4w9S3Ic1kL6bL0I MOhDBHyKQiRj6wuTQDpQYt4UKhwe9QPh0HJMxqVSjTE988LF/PyX4tHtLPQJyaDoOZS4TxD9dOJz BzhYOn3A8KEAgFuNT/lvC7ld8LRYyRgEJCLEgQfS7F1b0OeWvdwU8KD6lA9oe+kej5voRKMjLzeV QN7r0q4oeSFhPmDk7Qge3kaBRDV4CZuDNk3KpvqWE+B1PAchTabpRCsAk67VRUb4Z3ifizX7ilOb eg/ac3neXrq8HOpJDgDcExXqdCvnAoTCiIgXUPQIj67uhdHLBqRdvWh8fFy0VpJ3B2NmQ8U0lTXd R2GGCiIwgqqZrrqdW78c4hOZJCEE3mTrnpVL0NPyPWvszKAd4YvDwomNnPn0GuGzfVS19yl6n5ps sCrenGYNlRYqmCHGHQ6ld/UTWUbTxecOoTYvQaw39Vi0UTrE24XVBNan4pA3Hc+DxIdSZAf3irYK oByOn3oZ/l1BrR4NHP0+xbzXtU70HvV5xM5DVw2sEhCE2GSrRZNoBuDIivQB4t5yBwo8aMFDVdmP RiIDr0ySlFDyB0ZkO49CKcqHEKdxxifEU5Asr6To8UedVOLWcgdZEUuEyMxvPLnQzodyPJEInAD4 AecX7AkYhBAkVEipASI/3TZ2bzcn0DnkAqxkgZn/9msLarrIQ0wANan7y1jF2GiN1ppR1IfyxXaq v/+LuSKcKEgVg6QEAA==