diff --git a/lib/vcr/__init__.py b/lib/vcr/__init__.py new file mode 100644 index 0000000000..60af6905eb --- /dev/null +++ b/lib/vcr/__init__.py @@ -0,0 +1,17 @@ +import logging +from .config import VCR + +# Set default logging handler to avoid "No handler found" warnings. +try: # Python 2.7+ + from logging import NullHandler +except ImportError: + class NullHandler(logging.Handler): + def emit(self, record): + pass + + +logging.getLogger(__name__).addHandler(NullHandler()) + + +default_vcr = VCR() +use_cassette = default_vcr.use_cassette diff --git a/lib/vcr/cassette.py b/lib/vcr/cassette.py new file mode 100644 index 0000000000..2f5c293898 --- /dev/null +++ b/lib/vcr/cassette.py @@ -0,0 +1,308 @@ +import sys +import inspect +import logging + +import wrapt + +from .compat import contextlib, collections +from .errors import UnhandledHTTPRequestError +from .matchers import requests_match, uri, method +from .patch import CassettePatcherBuilder +from .persist import load_cassette, save_cassette +from .serializers import yamlserializer +from .util import partition_dict + + +log = logging.getLogger(__name__) + + +class CassetteContextDecorator(object): + """Context manager/decorator that handles installing the cassette and + removing cassettes. + + This class defers the creation of a new cassette instance until + the point at which it is installed by context manager or + decorator. The fact that a new cassette is used with each + application prevents the state of any cassette from interfering + with another. + + Instances of this class are NOT reentrant as context managers. + However, functions that are decorated by + ``CassetteContextDecorator`` instances ARE reentrant. See the + implementation of ``__call__`` on this class for more details. + There is also a guard against attempts to reenter instances of + this class as a context manager in ``__exit__``. + """ + + _non_cassette_arguments = ('path_transformer', 'func_path_generator') + + @classmethod + def from_args(cls, cassette_class, **kwargs): + return cls(cassette_class, lambda: dict(kwargs)) + + def __init__(self, cls, args_getter): + self.cls = cls + self._args_getter = args_getter + self.__finish = None + + def _patch_generator(self, cassette): + with contextlib.ExitStack() as exit_stack: + for patcher in CassettePatcherBuilder(cassette).build(): + exit_stack.enter_context(patcher) + log_format = '{action} context for cassette at {path}.' + log.debug(log_format.format( + action="Entering", path=cassette._path + )) + yield cassette + log.debug(log_format.format( + action="Exiting", path=cassette._path + )) + # TODO(@IvanMalison): Hmmm. it kind of feels like this should be + # somewhere else. + cassette._save() + + def __enter__(self): + # This assertion is here to prevent the dangerous behavior + # that would result from forgetting about a __finish before + # completing it. + # How might this condition be met? Here is an example: + # context_decorator = Cassette.use('whatever') + # with context_decorator: + # with context_decorator: + # pass + assert self.__finish is None, "Cassette already open." + other_kwargs, cassette_kwargs = partition_dict( + lambda key, _: key in self._non_cassette_arguments, + self._args_getter() + ) + if other_kwargs.get('path_transformer'): + transformer = other_kwargs['path_transformer'] + cassette_kwargs['path'] = transformer(cassette_kwargs['path']) + self.__finish = self._patch_generator(self.cls.load(**cassette_kwargs)) + return next(self.__finish) + + def __exit__(self, *args): + next(self.__finish, None) + self.__finish = None + + @wrapt.decorator + def __call__(self, function, instance, args, kwargs): + # This awkward cloning thing is done to ensure that decorated + # functions are reentrant. This is required for thread + # safety and the correct operation of recursive functions. + args_getter = self._build_args_getter_for_decorator(function) + return type(self)(self.cls, args_getter)._execute_function( + function, args, kwargs + ) + + def _execute_function(self, function, args, kwargs): + if inspect.isgeneratorfunction(function): + handler = self._handle_coroutine + else: + handler = self._handle_function + return handler(function, args, kwargs) + + def _handle_coroutine(self, function, args, kwargs): + """Wraps a coroutine so that we're inside the cassette context for the + duration of the coroutine. + """ + with self as cassette: + coroutine = self.__handle_function(cassette, function, args, kwargs) + # We don't need to catch StopIteration. The caller (Tornado's + # gen.coroutine, for example) will handle that. + to_yield = next(coroutine) + while True: + try: + to_send = yield to_yield + except Exception: + to_yield = coroutine.throw(*sys.exc_info()) + else: + to_yield = coroutine.send(to_send) + + def __handle_function(self, cassette, function, args, kwargs): + if cassette.inject: + return function(cassette, *args, **kwargs) + else: + return function(*args, **kwargs) + + def _handle_function(self, function, args, kwargs): + with self as cassette: + return self.__handle_function(cassette, function, args, kwargs) + + @staticmethod + def get_function_name(function): + return function.__name__ + + def _build_args_getter_for_decorator(self, function): + def new_args_getter(): + kwargs = self._args_getter() + if 'path' not in kwargs: + name_generator = (kwargs.get('func_path_generator') or + self.get_function_name) + path = name_generator(function) + kwargs['path'] = path + return kwargs + return new_args_getter + + +class Cassette(object): + """A container for recorded requests and responses""" + + @classmethod + def load(cls, **kwargs): + """Instantiate and load the cassette stored at the specified path.""" + new_cassette = cls(**kwargs) + new_cassette._load() + return new_cassette + + @classmethod + def use_arg_getter(cls, arg_getter): + return CassetteContextDecorator(cls, arg_getter) + + @classmethod + def use(cls, **kwargs): + return CassetteContextDecorator.from_args(cls, **kwargs) + + def __init__(self, path, serializer=yamlserializer, record_mode='once', + match_on=(uri, method), before_record_request=None, + before_record_response=None, custom_patches=(), + inject=False): + + self._path = path + self._serializer = serializer + self._match_on = match_on + self._before_record_request = before_record_request or (lambda x: x) + self._before_record_response = before_record_response or (lambda x: x) + self.inject = inject + self.record_mode = record_mode + self.custom_patches = custom_patches + + # self.data is the list of (req, resp) tuples + self.data = [] + self.play_counts = collections.Counter() + self.dirty = False + self.rewound = False + + @property + def play_count(self): + return sum(self.play_counts.values()) + + @property + def all_played(self): + """Returns True if all responses have been played, False otherwise.""" + return self.play_count == len(self) + + @property + def requests(self): + return [request for (request, response) in self.data] + + @property + def responses(self): + return [response for (request, response) in self.data] + + @property + def write_protected(self): + return self.rewound and self.record_mode == 'once' or \ + self.record_mode == 'none' + + def append(self, request, response): + """Add a request, response pair to this cassette""" + request = self._before_record_request(request) + if not request: + return + response = self._before_record_response(response) + if response is None: + return + self.data.append((request, response)) + self.dirty = True + + def filter_request(self, request): + return self._before_record_request(request) + + def _responses(self, request): + """ + internal API, returns an iterator with all responses matching + the request. + """ + request = self._before_record_request(request) + for index, (stored_request, response) in enumerate(self.data): + if requests_match(request, stored_request, self._match_on): + yield index, response + + def can_play_response_for(self, request): + request = self._before_record_request(request) + return request and request in self and \ + self.record_mode != 'all' and \ + self.rewound + + def play_response(self, request): + """ + Get the response corresponding to a request, but only if it + hasn't been played back before, and mark it as played + """ + for index, response in self._responses(request): + if self.play_counts[index] == 0: + self.play_counts[index] += 1 + return response + # The cassette doesn't contain the request asked for. + raise UnhandledHTTPRequestError( + "The cassette (%r) doesn't contain the request (%r) asked for" + % (self._path, request) + ) + + def responses_of(self, request): + """ + Find the responses corresponding to a request. + This function isn't actually used by VCR internally, but is + provided as an external API. + """ + responses = [response for index, response in self._responses(request)] + + if responses: + return responses + # The cassette doesn't contain the request asked for. + raise UnhandledHTTPRequestError( + "The cassette (%r) doesn't contain the request (%r) asked for" + % (self._path, request) + ) + + def _as_dict(self): + return {"requests": self.requests, "responses": self.responses} + + def _save(self, force=False): + if force or self.dirty: + save_cassette( + self._path, + self._as_dict(), + serializer=self._serializer + ) + self.dirty = False + + def _load(self): + try: + requests, responses = load_cassette( + self._path, + serializer=self._serializer + ) + for request, response in zip(requests, responses): + self.append(request, response) + self.dirty = False + self.rewound = True + except IOError: + pass + + def __str__(self): + return "".format( + len(self) + ) + + def __len__(self): + """Return the number of request,response pairs stored in here""" + return len(self.data) + + def __contains__(self, request): + """Return whether or not a request has been stored""" + for index, response in self._responses(request): + if self.play_counts[index] == 0: + return True + return False diff --git a/lib/vcr/compat.py b/lib/vcr/compat.py new file mode 100644 index 0000000000..e76c68ff50 --- /dev/null +++ b/lib/vcr/compat.py @@ -0,0 +1,18 @@ +try: + from unittest import mock +except ImportError: + import mock + +try: + import contextlib +except ImportError: + import contextlib2 as contextlib +else: + if not hasattr(contextlib, 'ExitStack'): + import contextlib2 as contextlib + +import collections +if not hasattr(collections, 'Counter'): + import backport_collections as collections + +__all__ = ['mock', 'contextlib', 'collections'] diff --git a/lib/vcr/config.py b/lib/vcr/config.py new file mode 100644 index 0000000000..ae993465b7 --- /dev/null +++ b/lib/vcr/config.py @@ -0,0 +1,275 @@ +import copy +import functools +import inspect +import os +import types + +import six + +from .compat import collections +from .cassette import Cassette +from .serializers import yamlserializer, jsonserializer +from .util import compose, auto_decorate +from . import matchers +from . import filters + + +class VCR(object): + + @staticmethod + def is_test_method(method_name, function): + return method_name.startswith('test') and \ + isinstance(function, types.FunctionType) + + @staticmethod + def ensure_suffix(suffix): + def ensure(path): + if not path.endswith(suffix): + return path + suffix + return path + return ensure + + def __init__(self, path_transformer=None, before_record_request=None, + custom_patches=(), filter_query_parameters=(), ignore_hosts=(), + record_mode="once", ignore_localhost=False, filter_headers=(), + before_record_response=None, filter_post_data_parameters=(), + match_on=('method', 'scheme', 'host', 'port', 'path', 'query'), + before_record=None, inject_cassette=False, serializer='yaml', + cassette_library_dir=None, func_path_generator=None, + decode_compressed_response=False): + self.serializer = serializer + self.match_on = match_on + self.cassette_library_dir = cassette_library_dir + self.serializers = { + 'yaml': yamlserializer, + 'json': jsonserializer, + } + self.matchers = { + 'method': matchers.method, + 'uri': matchers.uri, + 'url': matchers.uri, # matcher for backwards compatibility + 'scheme': matchers.scheme, + 'host': matchers.host, + 'port': matchers.port, + 'path': matchers.path, + 'query': matchers.query, + 'headers': matchers.headers, + 'raw_body': matchers.raw_body, + 'body': matchers.body, + } + self.record_mode = record_mode + self.filter_headers = filter_headers + self.filter_query_parameters = filter_query_parameters + self.filter_post_data_parameters = filter_post_data_parameters + self.before_record_request = before_record_request or before_record + self.before_record_response = before_record_response + self.ignore_hosts = ignore_hosts + self.ignore_localhost = ignore_localhost + self.inject_cassette = inject_cassette + self.path_transformer = path_transformer + self.func_path_generator = func_path_generator + self.decode_compressed_response = decode_compressed_response + self._custom_patches = tuple(custom_patches) + + def _get_serializer(self, serializer_name): + try: + serializer = self.serializers[serializer_name] + except KeyError: + raise KeyError( + "Serializer {0} doesn't exist or isn't registered".format( + serializer_name + ) + ) + return serializer + + def _get_matchers(self, matcher_names): + matchers = [] + try: + for m in matcher_names: + matchers.append(self.matchers[m]) + except KeyError: + raise KeyError( + "Matcher {0} doesn't exist or isn't registered".format(m) + ) + return matchers + + def use_cassette(self, path=None, **kwargs): + if path is not None and not isinstance(path, six.string_types): + function = path + # Assume this is an attempt to decorate a function + return self._use_cassette(**kwargs)(function) + return self._use_cassette(path=path, **kwargs) + + def _use_cassette(self, with_current_defaults=False, **kwargs): + if with_current_defaults: + config = self.get_merged_config(**kwargs) + return Cassette.use(**config) + # This is made a function that evaluates every time a cassette + # is made so that changes that are made to this VCR instance + # that occur AFTER the `use_cassette` decorator is applied + # still affect subsequent calls to the decorated function. + args_getter = functools.partial(self.get_merged_config, **kwargs) + return Cassette.use_arg_getter(args_getter) + + def get_merged_config(self, **kwargs): + serializer_name = kwargs.get('serializer', self.serializer) + matcher_names = kwargs.get('match_on', self.match_on) + path_transformer = kwargs.get( + 'path_transformer', + self.path_transformer + ) + func_path_generator = kwargs.get( + 'func_path_generator', + self.func_path_generator + ) + cassette_library_dir = kwargs.get( + 'cassette_library_dir', + self.cassette_library_dir + ) + additional_matchers = kwargs.get('additional_matchers', ()) + + if cassette_library_dir: + def add_cassette_library_dir(path): + if not path.startswith(cassette_library_dir): + return os.path.join(cassette_library_dir, path) + return path + path_transformer = compose( + add_cassette_library_dir, path_transformer + ) + elif not func_path_generator: + # If we don't have a library dir, use the functions + # location to build a full path for cassettes. + func_path_generator = self._build_path_from_func_using_module + + merged_config = { + 'serializer': self._get_serializer(serializer_name), + 'match_on': self._get_matchers( + tuple(matcher_names) + tuple(additional_matchers) + ), + 'record_mode': kwargs.get('record_mode', self.record_mode), + 'before_record_request': self._build_before_record_request(kwargs), + 'before_record_response': self._build_before_record_response(kwargs), + 'custom_patches': self._custom_patches + kwargs.get( + 'custom_patches', () + ), + 'inject': kwargs.get('inject_cassette', self.inject_cassette), + 'path_transformer': path_transformer, + 'func_path_generator': func_path_generator + } + path = kwargs.get('path') + if path: + merged_config['path'] = path + return merged_config + + def _build_before_record_response(self, options): + before_record_response = options.get( + 'before_record_response', self.before_record_response + ) + decode_compressed_response = options.get( + 'decode_compressed_response', self.decode_compressed_response + ) + filter_functions = [] + if decode_compressed_response: + filter_functions.append(filters.decode_response) + if before_record_response: + if not isinstance(before_record_response, collections.Iterable): + before_record_response = (before_record_response,) + filter_functions.extend(before_record_response) + + def before_record_response(response): + for function in filter_functions: + if response is None: + break + response = function(response) + return response + return before_record_response + + def _build_before_record_request(self, options): + filter_functions = [] + filter_headers = options.get( + 'filter_headers', self.filter_headers + ) + filter_query_parameters = options.get( + 'filter_query_parameters', self.filter_query_parameters + ) + filter_post_data_parameters = options.get( + 'filter_post_data_parameters', self.filter_post_data_parameters + ) + before_record_request = options.get( + "before_record_request", + options.get("before_record", self.before_record_request) + ) + ignore_hosts = options.get( + 'ignore_hosts', self.ignore_hosts + ) + ignore_localhost = options.get( + 'ignore_localhost', self.ignore_localhost + ) + if filter_headers: + replacements = [h if isinstance(h, tuple) else (h, None) + for h in filter_headers] + filter_functions.append( + functools.partial( + filters.replace_headers, + replacements=replacements, + ) + ) + if filter_query_parameters: + replacements = [p if isinstance(p, tuple) else (p, None) + for p in filter_query_parameters] + filter_functions.append(functools.partial( + filters.replace_query_parameters, + replacements=replacements, + )) + if filter_post_data_parameters: + replacements = [p if isinstance(p, tuple) else (p, None) + for p in filter_post_data_parameters] + filter_functions.append( + functools.partial( + filters.replace_post_data_parameters, + replacements=replacements, + ) + ) + + hosts_to_ignore = set(ignore_hosts) + if ignore_localhost: + hosts_to_ignore.update(('localhost', '0.0.0.0', '127.0.0.1')) + if hosts_to_ignore: + filter_functions.append(self._build_ignore_hosts(hosts_to_ignore)) + + if before_record_request: + if not isinstance(before_record_request, collections.Iterable): + before_record_request = (before_record_request,) + filter_functions.extend(before_record_request) + + def before_record_request(request): + request = copy.copy(request) + for function in filter_functions: + if request is None: + break + request = function(request) + return request + return before_record_request + + @staticmethod + def _build_ignore_hosts(hosts_to_ignore): + def filter_ignored_hosts(request): + if hasattr(request, 'host') and request.host in hosts_to_ignore: + return + return request + return filter_ignored_hosts + + @staticmethod + def _build_path_from_func_using_module(function): + return os.path.join(os.path.dirname(inspect.getfile(function)), + function.__name__) + + def register_serializer(self, name, serializer): + self.serializers[name] = serializer + + def register_matcher(self, name, matcher): + self.matchers[name] = matcher + + def test_case(self, predicate=None): + predicate = predicate or self.is_test_method + return six.with_metaclass(auto_decorate(self.use_cassette, predicate)) diff --git a/lib/vcr/errors.py b/lib/vcr/errors.py new file mode 100644 index 0000000000..bdc970194e --- /dev/null +++ b/lib/vcr/errors.py @@ -0,0 +1,7 @@ +class CannotOverwriteExistingCassetteException(Exception): + pass + + +class UnhandledHTTPRequestError(KeyError): + """Raised when a cassette does not contain the request we want.""" + pass diff --git a/lib/vcr/filters.py b/lib/vcr/filters.py new file mode 100644 index 0000000000..bd7e6c6518 --- /dev/null +++ b/lib/vcr/filters.py @@ -0,0 +1,163 @@ +from six import BytesIO, text_type +from six.moves.urllib.parse import urlparse, urlencode, urlunparse +import copy +import json +import zlib + +from .util import CaseInsensitiveDict + + +def replace_headers(request, replacements): + """ + Replace headers in request according to replacements. The replacements + should be a list of (key, value) pairs where the value can be any of: + 1. A simple replacement string value. + 2. None to remove the given header. + 3. A callable which accepts (key, value, request) and returns a string + value or None. + """ + new_headers = request.headers.copy() + for k, rv in replacements: + if k in new_headers: + ov = new_headers.pop(k) + if callable(rv): + rv = rv(key=k, value=ov, request=request) + if rv is not None: + new_headers[k] = rv + request.headers = new_headers + return request + + +def remove_headers(request, headers_to_remove): + """ + Wrap replace_headers() for API backward compatibility. + """ + replacements = [(k, None) for k in headers_to_remove] + return replace_headers(request, replacements) + + +def replace_query_parameters(request, replacements): + """ + Replace query parameters in request according to replacements. The + replacements should be a list of (key, value) pairs where the value can be + any of: + 1. A simple replacement string value. + 2. None to remove the given header. + 3. A callable which accepts (key, value, request) and returns a string + value or None. + """ + query = request.query + new_query = [] + replacements = dict(replacements) + for k, ov in query: + if k not in replacements: + new_query.append((k, ov)) + else: + rv = replacements[k] + if callable(rv): + rv = rv(key=k, value=ov, request=request) + if rv is not None: + new_query.append((k, rv)) + uri_parts = list(urlparse(request.uri)) + uri_parts[4] = urlencode(new_query) + request.uri = urlunparse(uri_parts) + return request + + +def remove_query_parameters(request, query_parameters_to_remove): + """ + Wrap replace_query_parameters() for API backward compatibility. + """ + replacements = [(k, None) for k in query_parameters_to_remove] + return replace_query_parameters(request, replacements) + + +def replace_post_data_parameters(request, replacements): + """ + Replace post data in request--either form data or json--according to + replacements. The replacements should be a list of (key, value) pairs where + the value can be any of: + 1. A simple replacement string value. + 2. None to remove the given header. + 3. A callable which accepts (key, value, request) and returns a string + value or None. + """ + replacements = dict(replacements) + if request.method == 'POST' and not isinstance(request.body, BytesIO): + if request.headers.get('Content-Type') == 'application/json': + json_data = json.loads(request.body.decode('utf-8')) + for k, rv in replacements.items(): + if k in json_data: + ov = json_data.pop(k) + if callable(rv): + rv = rv(key=k, value=ov, request=request) + if rv is not None: + json_data[k] = rv + request.body = json.dumps(json_data).encode('utf-8') + else: + if isinstance(request.body, text_type): + request.body = request.body.encode('utf-8') + splits = [p.partition(b'=') for p in request.body.split(b'&')] + new_splits = [] + for k, sep, ov in splits: + if sep is None: + new_splits.append((k, sep, ov)) + else: + rk = k.decode('utf-8') + if rk not in replacements: + new_splits.append((k, sep, ov)) + else: + rv = replacements[rk] + if callable(rv): + rv = rv(key=rk, value=ov.decode('utf-8'), + request=request) + if rv is not None: + new_splits.append((k, sep, rv.encode('utf-8'))) + request.body = b'&'.join(k if sep is None else b''.join([k, sep, v]) + for k, sep, v in new_splits) + return request + + +def remove_post_data_parameters(request, post_data_parameters_to_remove): + """ + Wrap replace_post_data_parameters() for API backward compatibility. + """ + replacements = [(k, None) for k in post_data_parameters_to_remove] + return replace_post_data_parameters(request, replacements) + + +def decode_response(response): + """ + If the response is compressed with gzip or deflate: + 1. decompress the response body + 2. delete the content-encoding header + 3. update content-length header to decompressed length + """ + def is_compressed(headers): + encoding = headers.get('content-encoding', []) + return encoding and encoding[0] in ('gzip', 'deflate') + + def decompress_body(body, encoding): + """Returns decompressed body according to encoding using zlib. + to (de-)compress gzip format, use wbits = zlib.MAX_WBITS | 16 + """ + if encoding == 'gzip': + return zlib.decompress(body, zlib.MAX_WBITS | 16) + else: # encoding == 'deflate' + return zlib.decompress(body) + + # Deepcopy here in case `headers` contain objects that could + # be mutated by a shallow copy and corrupt the real response. + response = copy.deepcopy(response) + headers = CaseInsensitiveDict(response['headers']) + if is_compressed(headers): + encoding = headers['content-encoding'][0] + headers['content-encoding'].remove(encoding) + if not headers['content-encoding']: + del headers['content-encoding'] + + new_body = decompress_body(response['body']['string'], encoding) + response['body']['string'] = new_body + headers['content-length'] = [str(len(new_body))] + response['headers'] = dict(headers) + return response diff --git a/lib/vcr/matchers.py b/lib/vcr/matchers.py new file mode 100644 index 0000000000..8fe334e497 --- /dev/null +++ b/lib/vcr/matchers.py @@ -0,0 +1,101 @@ +import json +from six.moves import urllib, xmlrpc_client +from .util import read_body +import logging + + +log = logging.getLogger(__name__) + + +def method(r1, r2): + return r1.method == r2.method + + +def uri(r1, r2): + return r1.uri == r2.uri + + +def host(r1, r2): + return r1.host == r2.host + + +def scheme(r1, r2): + return r1.scheme == r2.scheme + + +def port(r1, r2): + return r1.port == r2.port + + +def path(r1, r2): + return r1.path == r2.path + + +def query(r1, r2): + return r1.query == r2.query + + +def raw_body(r1, r2): + return read_body(r1) == read_body(r2) + + +def _header_checker(value, header='Content-Type'): + def checker(headers): + return value in headers.get(header, '').lower() + return checker + + +def _transform_json(body): + # Request body is always a byte string, but json.loads() wants a text + # string. RFC 7159 says the default encoding is UTF-8 (although UTF-16 + # and UTF-32 are also allowed: hmmmmm). + if body: + return json.loads(body.decode('utf-8')) + + +_xml_header_checker = _header_checker('text/xml') +_xmlrpc_header_checker = _header_checker('xmlrpc', header='User-Agent') +_checker_transformer_pairs = ( + (_header_checker('application/x-www-form-urlencoded'), urllib.parse.parse_qs), + (_header_checker('application/json'), _transform_json), + (lambda request: _xml_header_checker(request) and _xmlrpc_header_checker(request), xmlrpc_client.loads), +) + + +def _identity(x): + return x + + +def _get_transformer(request): + for checker, transformer in _checker_transformer_pairs: + if checker(request.headers): + return transformer + else: + return _identity + + +def body(r1, r2): + transformer = _get_transformer(r1) + r2_transformer = _get_transformer(r2) + if transformer != r2_transformer: + transformer = _identity + return transformer(read_body(r1)) == transformer(read_body(r2)) + + +def headers(r1, r2): + return r1.headers == r2.headers + + +def _log_matches(r1, r2, matches): + differences = [m for m in matches if not m[0]] + if differences: + log.debug( + "Requests {0} and {1} differ according to " + "the following matchers: {2}".format(r1, r2, differences) + ) + + +def requests_match(r1, r2, matchers): + matches = [(m(r1, r2), m) for m in matchers] + _log_matches(r1, r2, matches) + return all([m[0] for m in matches]) diff --git a/lib/vcr/migration.py b/lib/vcr/migration.py new file mode 100644 index 0000000000..6e30027757 --- /dev/null +++ b/lib/vcr/migration.py @@ -0,0 +1,168 @@ +""" +Migration script for old 'yaml' and 'json' cassettes + +.. warning:: Backup your cassettes files before migration. + +It merges and deletes the request obsolete keys (protocol, host, port, path) +into new 'uri' key. +Usage:: + + python -m vcr.migration PATH + +The PATH can be path to the directory with cassettes or cassette itself +""" + +import json +import os +import shutil +import sys +import tempfile +import yaml + +from .serializers import yamlserializer, jsonserializer +from .serialize import serialize +from . import request +from .stubs.compat import get_httpmessage + +# Use the libYAML versions if possible +try: + from yaml import CLoader as Loader +except ImportError: + from yaml import Loader + + +def preprocess_yaml(cassette): + # this is the hack that makes the whole thing work. The old version used + # to deserialize to Request objects automatically using pyYaml's !!python + # tag system. This made it difficult to deserialize old cassettes on new + # versions. So this just strips the tags before deserializing. + + STRINGS_TO_NUKE = [ + '!!python/object:vcr.request.Request', + '!!python/object/apply:__builtin__.frozenset', + '!!python/object/apply:builtins.frozenset', + ] + for s in STRINGS_TO_NUKE: + cassette = cassette.replace(s, '') + return cassette + + +PARTS = [ + 'protocol', + 'host', + 'port', + 'path', +] + + +def build_uri(**parts): + port = parts['port'] + scheme = parts['protocol'] + default_port = {'https': 443, 'http': 80}[scheme] + parts['port'] = ':{0}'.format(port) if port != default_port else '' + return "{protocol}://{host}{port}{path}".format(**parts) + + +def _migrate(data): + interactions = [] + for item in data: + req = item['request'] + res = item['response'] + uri = dict((k, req.pop(k)) for k in PARTS) + req['uri'] = build_uri(**uri) + # convert headers to dict of lists + headers = req['headers'] + for k in headers: + headers[k] = [headers[k]] + response_headers = {} + for k, v in get_httpmessage( + b"".join(h.encode('utf-8') for h in res['headers']) + ).items(): + response_headers.setdefault(k, []) + response_headers[k].append(v) + res['headers'] = response_headers + interactions.append({'request': req, 'response': res}) + return { + 'requests': [ + request.Request._from_dict(i['request']) for i in interactions + ], + 'responses': [i['response'] for i in interactions], + } + + +def migrate_json(in_fp, out_fp): + data = json.load(in_fp) + if _already_migrated(data): + return False + interactions = _migrate(data) + out_fp.write(serialize(interactions, jsonserializer)) + return True + + +def _list_of_tuples_to_dict(fs): + return dict((k, v) for k, v in fs[0]) + + +def _already_migrated(data): + try: + if data.get('version') == 1: + return True + except AttributeError: + return False + + +def migrate_yml(in_fp, out_fp): + data = yaml.load(preprocess_yaml(in_fp.read()), Loader=Loader) + if _already_migrated(data): + return False + for i in range(len(data)): + data[i]['request']['headers'] = _list_of_tuples_to_dict( + data[i]['request']['headers'] + ) + interactions = _migrate(data) + out_fp.write(serialize(interactions, yamlserializer)) + return True + + +def migrate(file_path, migration_fn): + # because we assume that original files can be reverted + # we will try to copy the content. (os.rename not needed) + with tempfile.TemporaryFile(mode='w+') as out_fp: + with open(file_path, 'r') as in_fp: + if not migration_fn(in_fp, out_fp): + return False + with open(file_path, 'w') as in_fp: + out_fp.seek(0) + shutil.copyfileobj(out_fp, in_fp) + return True + + +def try_migrate(path): + if path.endswith('.json'): + return migrate(path, migrate_json) + elif path.endswith('.yaml') or path.endswith('.yml'): + return migrate(path, migrate_yml) + return False + + +def main(): + if len(sys.argv) != 2: + raise SystemExit("Please provide path to cassettes directory or file. " + "Usage: python -m vcr.migration PATH") + + path = sys.argv[1] + if not os.path.isabs(path): + path = os.path.abspath(path) + files = [path] + if os.path.isdir(path): + files = (os.path.join(root, name) + for (root, dirs, files) in os.walk(path) + for name in files) + for file_path in files: + migrated = try_migrate(file_path) + status = 'OK' if migrated else 'FAIL' + sys.stderr.write("[{0}] {1}\n".format(status, file_path)) + sys.stderr.write("Done.\n") + +if __name__ == '__main__': + main() diff --git a/lib/vcr/patch.py b/lib/vcr/patch.py new file mode 100644 index 0000000000..ac1127a47f --- /dev/null +++ b/lib/vcr/patch.py @@ -0,0 +1,456 @@ +'''Utilities for patching in cassettes''' +import functools +import itertools + +from .compat import contextlib, mock +from .stubs import VCRHTTPConnection, VCRHTTPSConnection +from six.moves import http_client as httplib + + +# Save some of the original types for the purposes of unpatching +_HTTPConnection = httplib.HTTPConnection +_HTTPSConnection = httplib.HTTPSConnection + + +# Try to save the original types for requests +try: + import requests.packages.urllib3.connectionpool as cpool +except ImportError: # pragma: no cover + pass +else: + _VerifiedHTTPSConnection = cpool.VerifiedHTTPSConnection + _cpoolHTTPConnection = cpool.HTTPConnection + _cpoolHTTPSConnection = cpool.HTTPSConnection + +# Try to save the original types for boto3 +try: + import botocore.vendored.requests.packages.urllib3.connectionpool as cpool +except ImportError: # pragma: no cover + pass +else: + _Boto3VerifiedHTTPSConnection = cpool.VerifiedHTTPSConnection + _cpoolBoto3HTTPConnection = cpool.HTTPConnection + _cpoolBoto3HTTPSConnection = cpool.HTTPSConnection + + +# Try to save the original types for urllib3 +try: + import urllib3 +except ImportError: # pragma: no cover + pass +else: + _VerifiedHTTPSConnection = urllib3.connectionpool.VerifiedHTTPSConnection + + +# Try to save the original types for httplib2 +try: + import httplib2 +except ImportError: # pragma: no cover + pass +else: + _HTTPConnectionWithTimeout = httplib2.HTTPConnectionWithTimeout + _HTTPSConnectionWithTimeout = httplib2.HTTPSConnectionWithTimeout + _SCHEME_TO_CONNECTION = httplib2.SCHEME_TO_CONNECTION + + +# Try to save the original types for boto +try: + import boto.https_connection +except ImportError: # pragma: no cover + pass +else: + _CertValidatingHTTPSConnection = boto.https_connection.CertValidatingHTTPSConnection + + +# Try to save the original types for Tornado +try: + import tornado.simple_httpclient +except ImportError: # pragma: no cover + pass +else: + _SimpleAsyncHTTPClient_fetch_impl = \ + tornado.simple_httpclient.SimpleAsyncHTTPClient.fetch_impl + + +try: + import tornado.curl_httpclient +except ImportError: # pragma: no cover + pass +else: + _CurlAsyncHTTPClient_fetch_impl = \ + tornado.curl_httpclient.CurlAsyncHTTPClient.fetch_impl + +try: + import aiohttp.client +except ImportError: # pragma: no cover + pass +else: + _AiohttpClientSessionRequest = aiohttp.client.ClientSession._request + + +class CassettePatcherBuilder(object): + + def _build_patchers_from_mock_triples_decorator(function): + @functools.wraps(function) + def wrapped(self, *args, **kwargs): + return self._build_patchers_from_mock_triples( + function(self, *args, **kwargs) + ) + return wrapped + + def __init__(self, cassette): + self._cassette = cassette + self._class_to_cassette_subclass = {} + + def build(self): + return itertools.chain( + self._httplib(), self._requests(), self._boto3(), self._urllib3(), + self._httplib2(), self._boto(), self._tornado(), self._aiohttp(), + self._build_patchers_from_mock_triples( + self._cassette.custom_patches + ), + ) + + def _build_patchers_from_mock_triples(self, mock_triples): + for args in mock_triples: + patcher = self._build_patcher(*args) + if patcher: + yield patcher + + def _build_patcher(self, obj, patched_attribute, replacement_class): + if not hasattr(obj, patched_attribute): + return + + return mock.patch.object(obj, patched_attribute, + self._recursively_apply_get_cassette_subclass( + replacement_class)) + + def _recursively_apply_get_cassette_subclass(self, replacement_dict_or_obj): + """One of the subtleties of this class is that it does not directly + replace HTTPSConnection with `VCRRequestsHTTPSConnection`, but a + subclass of the aforementioned class that has the `cassette` + class attribute assigned to `self._cassette`. This behavior is + necessary to properly support nested cassette contexts. + + This function exists to ensure that we use the same class + object (reference) to patch everything that replaces + VCRRequestHTTP[S]Connection, but that we can talk about + patching them with the raw references instead, and without + worrying about exactly where the subclass with the relevant + value for `cassette` is first created. + + The function is recursive because it looks in to dictionaries + and replaces class values at any depth with the subclass + described in the previous paragraph. + """ + if isinstance(replacement_dict_or_obj, dict): + for key, replacement_obj in replacement_dict_or_obj.items(): + replacement_obj = self._recursively_apply_get_cassette_subclass( + replacement_obj) + replacement_dict_or_obj[key] = replacement_obj + return replacement_dict_or_obj + if hasattr(replacement_dict_or_obj, 'cassette'): + replacement_dict_or_obj = self._get_cassette_subclass( + replacement_dict_or_obj) + return replacement_dict_or_obj + + def _get_cassette_subclass(self, klass): + if klass.cassette is not None: + return klass + if klass not in self._class_to_cassette_subclass: + subclass = self._build_cassette_subclass(klass) + self._class_to_cassette_subclass[klass] = subclass + return self._class_to_cassette_subclass[klass] + + def _build_cassette_subclass(self, base_class): + bases = (base_class,) + if not issubclass(base_class, object): # Check for old style class + bases += (object,) + return type('{0}{1}'.format(base_class.__name__, self._cassette._path), + bases, dict(cassette=self._cassette)) + + @_build_patchers_from_mock_triples_decorator + def _httplib(self): + yield httplib, 'HTTPConnection', VCRHTTPConnection + yield httplib, 'HTTPSConnection', VCRHTTPSConnection + + def _requests(self): + try: + import requests.packages.urllib3.connectionpool as cpool + except ImportError: # pragma: no cover + return () + from .stubs import requests_stubs + return self._urllib3_patchers(cpool, requests_stubs) + + def _boto3(self): + try: + import botocore.vendored.requests.packages.urllib3.connectionpool as cpool + except ImportError: # pragma: no cover + return () + from .stubs import boto3_stubs + return self._urllib3_patchers(cpool, boto3_stubs) + + def _patched_get_conn(self, connection_pool_class, connection_class_getter): + get_conn = connection_pool_class._get_conn + + @functools.wraps(get_conn) + def patched_get_conn(pool, timeout=None): + connection = get_conn(pool, timeout) + connection_class = ( + pool.ConnectionCls if hasattr(pool, 'ConnectionCls') + else connection_class_getter()) + # We need to make sure that we are actually providing a + # patched version of the connection class. This might not + # always be the case because the pool keeps previously + # used connections (which might actually be of a different + # class) around. This while loop will terminate because + # eventually the pool will run out of connections. + while not isinstance(connection, connection_class): + connection = get_conn(pool, timeout) + return connection + + return patched_get_conn + + def _patched_new_conn(self, connection_pool_class, connection_remover): + new_conn = connection_pool_class._new_conn + + @functools.wraps(new_conn) + def patched_new_conn(pool): + new_connection = new_conn(pool) + connection_remover.add_connection_to_pool_entry(pool, new_connection) + return new_connection + + return patched_new_conn + + def _urllib3(self): + try: + import urllib3.connectionpool as cpool + except ImportError: # pragma: no cover + return () + from .stubs import urllib3_stubs + return self._urllib3_patchers(cpool, urllib3_stubs) + + @_build_patchers_from_mock_triples_decorator + def _httplib2(self): + try: + import httplib2 as cpool + except ImportError: # pragma: no cover + pass + else: + from .stubs.httplib2_stubs import VCRHTTPConnectionWithTimeout + from .stubs.httplib2_stubs import VCRHTTPSConnectionWithTimeout + + yield cpool, 'HTTPConnectionWithTimeout', VCRHTTPConnectionWithTimeout + yield cpool, 'HTTPSConnectionWithTimeout', VCRHTTPSConnectionWithTimeout + yield cpool, 'SCHEME_TO_CONNECTION', {'http': VCRHTTPConnectionWithTimeout, + 'https': VCRHTTPSConnectionWithTimeout} + + @_build_patchers_from_mock_triples_decorator + def _boto(self): + try: + import boto.https_connection as cpool + except ImportError: # pragma: no cover + pass + else: + from .stubs.boto_stubs import VCRCertValidatingHTTPSConnection + yield cpool, 'CertValidatingHTTPSConnection', VCRCertValidatingHTTPSConnection + + @_build_patchers_from_mock_triples_decorator + def _tornado(self): + try: + import tornado.simple_httpclient as simple + except ImportError: # pragma: no cover + pass + else: + from .stubs.tornado_stubs import vcr_fetch_impl + + new_fetch_impl = vcr_fetch_impl( + self._cassette, _SimpleAsyncHTTPClient_fetch_impl + ) + yield simple.SimpleAsyncHTTPClient, 'fetch_impl', new_fetch_impl + try: + import tornado.curl_httpclient as curl + except ImportError: # pragma: no cover + pass + else: + from .stubs.tornado_stubs import vcr_fetch_impl + + new_fetch_impl = vcr_fetch_impl( + self._cassette, _CurlAsyncHTTPClient_fetch_impl + ) + yield curl.CurlAsyncHTTPClient, 'fetch_impl', new_fetch_impl + + @_build_patchers_from_mock_triples_decorator + def _aiohttp(self): + try: + import aiohttp.client as client + except ImportError: # pragma: no cover + pass + else: + from .stubs.aiohttp_stubs import vcr_request + new_request = vcr_request( + self._cassette, _AiohttpClientSessionRequest + ) + yield client.ClientSession, '_request', new_request + + def _urllib3_patchers(self, cpool, stubs): + http_connection_remover = ConnectionRemover( + self._get_cassette_subclass(stubs.VCRRequestsHTTPConnection) + ) + https_connection_remover = ConnectionRemover( + self._get_cassette_subclass(stubs.VCRRequestsHTTPSConnection) + ) + mock_triples = ( + (cpool, 'VerifiedHTTPSConnection', stubs.VCRRequestsHTTPSConnection), + (cpool, 'VerifiedHTTPSConnection', stubs.VCRRequestsHTTPSConnection), + (cpool, 'HTTPConnection', stubs.VCRRequestsHTTPConnection), + (cpool, 'HTTPSConnection', stubs.VCRRequestsHTTPSConnection), + (cpool, 'is_connection_dropped', mock.Mock(return_value=False)), # Needed on Windows only + (cpool.HTTPConnectionPool, 'ConnectionCls', stubs.VCRRequestsHTTPConnection), + (cpool.HTTPSConnectionPool, 'ConnectionCls', stubs.VCRRequestsHTTPSConnection), + ) + # These handle making sure that sessions only use the + # connections of the appropriate type. + mock_triples += ((cpool.HTTPConnectionPool, '_get_conn', + self._patched_get_conn(cpool.HTTPConnectionPool, + lambda: cpool.HTTPConnection)), + (cpool.HTTPSConnectionPool, '_get_conn', + self._patched_get_conn(cpool.HTTPSConnectionPool, + lambda: cpool.HTTPSConnection)), + (cpool.HTTPConnectionPool, '_new_conn', + self._patched_new_conn(cpool.HTTPConnectionPool, + http_connection_remover)), + (cpool.HTTPSConnectionPool, '_new_conn', + self._patched_new_conn(cpool.HTTPSConnectionPool, + https_connection_remover))) + + return itertools.chain(self._build_patchers_from_mock_triples(mock_triples), + (http_connection_remover, https_connection_remover)) + + +class ConnectionRemover(object): + + def __init__(self, connection_class): + self._connection_class = connection_class + self._connection_pool_to_connections = {} + + def add_connection_to_pool_entry(self, pool, connection): + if isinstance(connection, self._connection_class): + self._connection_pool_to_connections.setdefault(pool, set()).add(connection) + + def remove_connection_to_pool_entry(self, pool, connection): + if isinstance(connection, self._connection_class): + self._connection_pool_to_connections[self._connection_class].remove(connection) + + def __enter__(self): + return self + + def __exit__(self, *args): + for pool, connections in self._connection_pool_to_connections.items(): + readd_connections = [] + while pool.pool and not pool.pool.empty() and connections: + connection = pool.pool.get() + if isinstance(connection, self._connection_class): + connections.remove(connection) + else: + readd_connections.append(connection) + for connection in readd_connections: + pool._put_conn(connection) + + +def reset_patchers(): + yield mock.patch.object(httplib, 'HTTPConnection', _HTTPConnection) + yield mock.patch.object(httplib, 'HTTPSConnection', _HTTPSConnection) + try: + import requests.packages.urllib3.connectionpool as cpool + except ImportError: # pragma: no cover + pass + else: + # unpatch requests v1.x + yield mock.patch.object(cpool, 'VerifiedHTTPSConnection', _VerifiedHTTPSConnection) + yield mock.patch.object(cpool, 'HTTPConnection', _cpoolHTTPConnection) + # unpatch requests v2.x + if hasattr(cpool.HTTPConnectionPool, 'ConnectionCls'): + yield mock.patch.object(cpool.HTTPConnectionPool, 'ConnectionCls', + _cpoolHTTPConnection) + yield mock.patch.object(cpool.HTTPSConnectionPool, 'ConnectionCls', + _cpoolHTTPSConnection) + + if hasattr(cpool, 'HTTPSConnection'): + yield mock.patch.object(cpool, 'HTTPSConnection', _cpoolHTTPSConnection) + + try: + import urllib3.connectionpool as cpool + except ImportError: # pragma: no cover + pass + else: + yield mock.patch.object(cpool, 'VerifiedHTTPSConnection', _VerifiedHTTPSConnection) + yield mock.patch.object(cpool, 'HTTPConnection', _HTTPConnection) + yield mock.patch.object(cpool, 'HTTPSConnection', _HTTPSConnection) + if hasattr(cpool.HTTPConnectionPool, 'ConnectionCls'): + yield mock.patch.object(cpool.HTTPConnectionPool, 'ConnectionCls', _HTTPConnection) + yield mock.patch.object(cpool.HTTPSConnectionPool, 'ConnectionCls', _HTTPSConnection) + + try: + import botocore.vendored.requests.packages.urllib3.connectionpool as cpool + except ImportError: # pragma: no cover + pass + else: + # unpatch requests v1.x + yield mock.patch.object(cpool, 'VerifiedHTTPSConnection', _Boto3VerifiedHTTPSConnection) + yield mock.patch.object(cpool, 'HTTPConnection', _cpoolBoto3HTTPConnection) + # unpatch requests v2.x + if hasattr(cpool.HTTPConnectionPool, 'ConnectionCls'): + yield mock.patch.object(cpool.HTTPConnectionPool, 'ConnectionCls', + _cpoolBoto3HTTPConnection) + yield mock.patch.object(cpool.HTTPSConnectionPool, 'ConnectionCls', + _cpoolBoto3HTTPSConnection) + + if hasattr(cpool, 'HTTPSConnection'): + yield mock.patch.object(cpool, 'HTTPSConnection', _cpoolBoto3HTTPSConnection) + + try: + import httplib2 as cpool + except ImportError: # pragma: no cover + pass + else: + yield mock.patch.object(cpool, 'HTTPConnectionWithTimeout', _HTTPConnectionWithTimeout) + yield mock.patch.object(cpool, 'HTTPSConnectionWithTimeout', _HTTPSConnectionWithTimeout) + yield mock.patch.object(cpool, 'SCHEME_TO_CONNECTION', _SCHEME_TO_CONNECTION) + + try: + import boto.https_connection as cpool + except ImportError: # pragma: no cover + pass + else: + yield mock.patch.object(cpool, 'CertValidatingHTTPSConnection', + _CertValidatingHTTPSConnection) + + try: + import tornado.simple_httpclient as simple + except ImportError: # pragma: no cover + pass + else: + yield mock.patch.object( + simple.SimpleAsyncHTTPClient, + 'fetch_impl', + _SimpleAsyncHTTPClient_fetch_impl, + ) + try: + import tornado.curl_httpclient as curl + except ImportError: # pragma: no cover + pass + else: + yield mock.patch.object( + curl.CurlAsyncHTTPClient, + 'fetch_impl', + _CurlAsyncHTTPClient_fetch_impl, + ) + + +@contextlib.contextmanager +def force_reset(): + with contextlib.ExitStack() as exit_stack: + for patcher in reset_patchers(): + exit_stack.enter_context(patcher) + yield diff --git a/lib/vcr/persist.py b/lib/vcr/persist.py new file mode 100644 index 0000000000..f8b8d2a8c9 --- /dev/null +++ b/lib/vcr/persist.py @@ -0,0 +1,14 @@ +from .persisters.filesystem import FilesystemPersister +from .serialize import serialize, deserialize + + +def load_cassette(cassette_path, serializer): + with open(cassette_path) as f: + cassette_content = f.read() + cassette = deserialize(cassette_content, serializer) + return cassette + + +def save_cassette(cassette_path, cassette_dict, serializer): + data = serialize(cassette_dict, serializer) + FilesystemPersister.write(cassette_path, data) diff --git a/lib/vcr/persisters/__init__.py b/lib/vcr/persisters/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/lib/vcr/persisters/filesystem.py b/lib/vcr/persisters/filesystem.py new file mode 100644 index 0000000000..884d891129 --- /dev/null +++ b/lib/vcr/persisters/filesystem.py @@ -0,0 +1,11 @@ +import os + + +class FilesystemPersister(object): + @classmethod + def write(cls, cassette_path, data): + dirname, filename = os.path.split(cassette_path) + if dirname and not os.path.exists(dirname): + os.makedirs(dirname) + with open(cassette_path, 'w') as f: + f.write(data) diff --git a/lib/vcr/request.py b/lib/vcr/request.py new file mode 100644 index 0000000000..63e451e584 --- /dev/null +++ b/lib/vcr/request.py @@ -0,0 +1,131 @@ +import warnings +from six import BytesIO, text_type +from six.moves.urllib.parse import urlparse, parse_qsl +from .util import CaseInsensitiveDict + + +class Request(object): + """ + VCR's representation of a request. + """ + + def __init__(self, method, uri, body, headers): + self.method = method + self.uri = uri + self._was_file = hasattr(body, 'read') + if self._was_file: + self.body = body.read() + else: + self.body = body + self.headers = headers + + @property + def headers(self): + return self._headers + + @headers.setter + def headers(self, value): + if not isinstance(value, HeadersDict): + value = HeadersDict(value) + self._headers = value + + @property + def body(self): + return BytesIO(self._body) if self._was_file else self._body + + @body.setter + def body(self, value): + if isinstance(value, text_type): + value = value.encode('utf-8') + self._body = value + + def add_header(self, key, value): + warnings.warn("Request.add_header is deprecated. " + "Please assign to request.headers instead.", + DeprecationWarning) + self.headers[key] = value + + @property + def scheme(self): + return urlparse(self.uri).scheme + + @property + def host(self): + return urlparse(self.uri).hostname + + @property + def port(self): + parse_uri = urlparse(self.uri) + port = parse_uri.port + if port is None: + port = {'https': 443, 'http': 80}[parse_uri.scheme] + return port + + @property + def path(self): + return urlparse(self.uri).path + + @property + def query(self): + q = urlparse(self.uri).query + return sorted(parse_qsl(q)) + + # alias for backwards compatibility + @property + def url(self): + return self.uri + + # alias for backwards compatibility + @property + def protocol(self): + return self.scheme + + def __str__(self): + return "".format(self.method, self.uri) + + def __repr__(self): + return self.__str__() + + def _to_dict(self): + return { + 'method': self.method, + 'uri': self.uri, + 'body': self.body, + 'headers': dict(((k, [v]) for k, v in self.headers.items())), + } + + @classmethod + def _from_dict(cls, dct): + return Request(**dct) + + +class HeadersDict(CaseInsensitiveDict): + """ + There is a weird quirk in HTTP. You can send the same header twice. For + this reason, headers are represented by a dict, with lists as the values. + However, it appears that HTTPlib is completely incapable of sending the + same header twice. This puts me in a weird position: I want to be able to + accurately represent HTTP headers in cassettes, but I don't want the extra + step of always having to do [0] in the general case, i.e. + request.headers['key'][0] + + In addition, some servers sometimes send the same header more than once, + and httplib *can* deal with this situation. + + Futhermore, I wanted to keep the request and response cassette format as + similar as possible. + + For this reason, in cassettes I keep a dict with lists as keys, but once + deserialized into VCR, I keep them as plain, naked dicts. + """ + + def __setitem__(self, key, value): + if isinstance(value, (tuple, list)): + value = value[0] + + # Preserve the case from the first time this key was set. + old = self._store.get(key.lower()) + if old: + key = old[0] + + super(HeadersDict, self).__setitem__(key, value) diff --git a/lib/vcr/serialize.py b/lib/vcr/serialize.py new file mode 100644 index 0000000000..a9c04d667f --- /dev/null +++ b/lib/vcr/serialize.py @@ -0,0 +1,63 @@ +from vcr.serializers import compat +from vcr.request import Request +import yaml + +# version 1 cassettes started with VCR 1.0.x. +# Before 1.0.x, there was no versioning. +CASSETTE_FORMAT_VERSION = 1 + +""" +Just a general note on the serialization philosophy here: +I prefer cassettes to be human-readable if possible. Yaml serializes +bytestrings to !!binary, which isn't readable, so I would like to serialize to +strings and from strings, which yaml will encode as utf-8 automatically. +All the internal HTTP stuff expects bytestrings, so this whole serialization +process feels backwards. + +Serializing: bytestring -> string (yaml persists to utf-8) +Deserializing: string (yaml converts from utf-8) -> bytestring +""" + + +def _looks_like_an_old_cassette(data): + return isinstance(data, list) and len(data) and 'request' in data[0] + + +def _warn_about_old_cassette_format(): + raise ValueError( + "Your cassette files were generated in an older version " + "of VCR. Delete your cassettes or run the migration script." + "See http://git.io/mHhLBg for more details." + ) + + +def deserialize(cassette_string, serializer): + try: + data = serializer.deserialize(cassette_string) + # Old cassettes used to use yaml object thingy so I have to + # check for some fairly stupid exceptions here + except (ImportError, yaml.constructor.ConstructorError): + _warn_about_old_cassette_format() + if _looks_like_an_old_cassette(data): + _warn_about_old_cassette_format() + + requests = [Request._from_dict(r['request']) for r in data['interactions']] + responses = [ + compat.convert_to_bytes(r['response']) for r in data['interactions'] + ] + return requests, responses + + +def serialize(cassette_dict, serializer): + interactions = ([{ + 'request': compat.convert_to_unicode(request._to_dict()), + 'response': compat.convert_to_unicode(response), + } for request, response in zip( + cassette_dict['requests'], + cassette_dict['responses'], + )]) + data = { + 'version': CASSETTE_FORMAT_VERSION, + 'interactions': interactions, + } + return serializer.serialize(data) diff --git a/lib/vcr/serializers/__init__.py b/lib/vcr/serializers/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/lib/vcr/serializers/compat.py b/lib/vcr/serializers/compat.py new file mode 100644 index 0000000000..8364997529 --- /dev/null +++ b/lib/vcr/serializers/compat.py @@ -0,0 +1,79 @@ +import six + + +def convert_to_bytes(resp): + resp = convert_body_to_bytes(resp) + return resp + + +def convert_to_unicode(resp): + resp = convert_body_to_unicode(resp) + return resp + + +def convert_body_to_bytes(resp): + """ + If the request body is a string, encode it to bytes (for python3 support) + + By default yaml serializes to utf-8 encoded bytestrings. + When this cassette is loaded by python3, it's automatically decoded + into unicode strings. This makes sure that it stays a bytestring, since + that's what all the internal httplib machinery is expecting. + + For more info on py3 yaml: + http://pyyaml.org/wiki/PyYAMLDocumentation#Python3support + """ + try: + if resp['body']['string'] is not None and not isinstance(resp['body']['string'], six.binary_type): + resp['body']['string'] = resp['body']['string'].encode('utf-8') + except (KeyError, TypeError, UnicodeEncodeError): + # The thing we were converting either wasn't a dictionary or didn't + # have the keys we were expecting. Some of the tests just serialize + # and deserialize a string. + + # Also, sometimes the thing actually is binary, so if you can't encode + # it, just give up. + pass + return resp + + +def _convert_string_to_unicode(string): + """ + If the string is bytes, decode it to a string (for python3 support) + """ + result = string + + try: + if string is not None and not isinstance(string, six.text_type): + result = string.decode('utf-8') + except (TypeError, UnicodeDecodeError, AttributeError): + # Sometimes the string actually is binary or StringIO object, + # so if you can't decode it, just give up. + pass + + return result + + +def convert_body_to_unicode(resp): + """ + If the request or responses body is bytes, decode it to a string + (for python3 support) + """ + if type(resp) is not dict: + # Some of the tests just serialize and deserialize a string. + return _convert_string_to_unicode(resp) + else: + body = resp.get('body') + + if body is not None: + try: + body['string'] = _convert_string_to_unicode( + body['string'] + ) + except (KeyError, TypeError, AttributeError): + # The thing we were converting either wasn't a dictionary or + # didn't have the keys we were expecting. + # For example request object has no 'string' key. + resp['body'] = _convert_string_to_unicode(body) + + return resp diff --git a/lib/vcr/serializers/jsonserializer.py b/lib/vcr/serializers/jsonserializer.py new file mode 100644 index 0000000000..3378c27fab --- /dev/null +++ b/lib/vcr/serializers/jsonserializer.py @@ -0,0 +1,29 @@ +try: + import simplejson as json +except ImportError: + import json + + +def deserialize(cassette_string): + return json.loads(cassette_string) + + +def serialize(cassette_dict): + error_message = ( + "Does this HTTP interaction contain binary data? " + "If so, use a different serializer (like the yaml serializer) " + "for this request?" + ) + + try: + return json.dumps(cassette_dict, indent=4) + except UnicodeDecodeError as original: # py2 + raise UnicodeDecodeError( + original.encoding, + b"Error serializing cassette to JSON", + original.start, + original.end, + original.args[-1] + error_message + ) + except TypeError as original: # py3 + raise TypeError(error_message) diff --git a/lib/vcr/serializers/yamlserializer.py b/lib/vcr/serializers/yamlserializer.py new file mode 100644 index 0000000000..0d6afc96c0 --- /dev/null +++ b/lib/vcr/serializers/yamlserializer.py @@ -0,0 +1,15 @@ +import yaml + +# Use the libYAML versions if possible +try: + from yaml import CLoader as Loader, CDumper as Dumper +except ImportError: + from yaml import Loader, Dumper + + +def deserialize(cassette_string): + return yaml.load(cassette_string, Loader=Loader) + + +def serialize(cassette_dict): + return yaml.dump(cassette_dict, Dumper=Dumper) diff --git a/lib/vcr/stubs/__init__.py b/lib/vcr/stubs/__init__.py new file mode 100644 index 0000000000..a703ff4372 --- /dev/null +++ b/lib/vcr/stubs/__init__.py @@ -0,0 +1,346 @@ +'''Stubs for patching HTTP and HTTPS requests''' + +import logging +import six +from six.moves.http_client import ( + HTTPConnection, + HTTPSConnection, + HTTPResponse, +) +from six import BytesIO +from vcr.request import Request +from vcr.errors import CannotOverwriteExistingCassetteException +from . import compat + +log = logging.getLogger(__name__) + + +class VCRFakeSocket(object): + """ + A socket that doesn't do anything! + Used when playing back casssettes, when there + is no actual open socket. + """ + + def close(self): + pass + + def settimeout(self, *args, **kwargs): + pass + + def fileno(self): + """ + This is kinda crappy. requests will watch + this descriptor and make sure it's not closed. + Return file descriptor 0 since that's stdin. + """ + return 0 # wonder how bad this is.... + + +def parse_headers(header_list): + """ + Convert headers from our serialized dict with lists for keys to a + HTTPMessage + """ + header_string = b"" + for key, values in header_list.items(): + for v in values: + header_string += \ + key.encode('utf-8') + b":" + v.encode('utf-8') + b"\r\n" + return compat.get_httpmessage(header_string) + + +def serialize_headers(response): + out = {} + for key, values in compat.get_headers(response.msg): + out.setdefault(key, []) + out[key].extend(values) + return out + + +class VCRHTTPResponse(HTTPResponse): + """ + Stub reponse class that gets returned instead of a HTTPResponse + """ + def __init__(self, recorded_response): + self.recorded_response = recorded_response + self.reason = recorded_response['status']['message'] + self.status = self.code = recorded_response['status']['code'] + self.version = None + self._content = BytesIO(self.recorded_response['body']['string']) + self._closed = False + + headers = self.recorded_response['headers'] + # Since we are loading a response that has already been serialized, our + # response is no longer chunked. That means we don't want any + # libraries trying to process a chunked response. By removing the + # transfer-encoding: chunked header, this should cause the downstream + # libraries to process this as a non-chunked response. + te_key = [h for h in headers.keys() if h.upper() == 'TRANSFER-ENCODING'] + if te_key: + del headers[te_key[0]] + self.headers = self.msg = parse_headers(headers) + + self.length = compat.get_header(self.msg, 'content-length') or None + + @property + def closed(self): + # in python3, I can't change the value of self.closed. So I' + # twiddling self._closed and using this property to shadow the real + # self.closed from the superclas + return self._closed + + def read(self, *args, **kwargs): + return self._content.read(*args, **kwargs) + + def readline(self, *args, **kwargs): + return self._content.readline(*args, **kwargs) + + def close(self): + self._closed = True + return True + + def getcode(self): + return self.status + + def isclosed(self): + return self.closed + + def info(self): + return parse_headers(self.recorded_response['headers']) + + def getheaders(self): + message = parse_headers(self.recorded_response['headers']) + return list(compat.get_header_items(message)) + + def getheader(self, header, default=None): + values = [v for (k, v) in self.getheaders() if k.lower() == header.lower()] + + if values: + return ', '.join(values) + else: + return default + + +class VCRConnection(object): + # A reference to the cassette that's currently being patched in + cassette = None + + def _port_postfix(self): + """ + Returns empty string for the default port and ':port' otherwise + """ + port = self.real_connection.port + default_port = {'https': 443, 'http': 80}[self._protocol] + return ':{0}'.format(port) if port != default_port else '' + + def _uri(self, url): + """Returns request absolute URI""" + uri = "{0}://{1}{2}{3}".format( + self._protocol, + self.real_connection.host, + self._port_postfix(), + url, + ) + return uri + + def _url(self, uri): + """Returns request selector url from absolute URI""" + prefix = "{0}://{1}{2}".format( + self._protocol, + self.real_connection.host, + self._port_postfix(), + ) + return uri.replace(prefix, '', 1) + + def request(self, method, url, body=None, headers=None): + '''Persist the request metadata in self._vcr_request''' + self._vcr_request = Request( + method=method, + uri=self._uri(url), + body=body, + headers=headers or {} + ) + log.debug('Got {0}'.format(self._vcr_request)) + + # Note: The request may not actually be finished at this point, so + # I'm not sending the actual request until getresponse(). This + # allows me to compare the entire length of the response to see if it + # exists in the cassette. + + def putrequest(self, method, url, *args, **kwargs): + """ + httplib gives you more than one way to do it. This is a way + to start building up a request. Usually followed by a bunch + of putheader() calls. + """ + self._vcr_request = Request( + method=method, + uri=self._uri(url), + body="", + headers={} + ) + log.debug('Got {0}'.format(self._vcr_request)) + + def putheader(self, header, *values): + self._vcr_request.headers[header] = values + + def send(self, data): + ''' + This method is called after request(), to add additional data to the + body of the request. So if that happens, let's just append the data + onto the most recent request in the cassette. + ''' + self._vcr_request.body = self._vcr_request.body + data \ + if self._vcr_request.body else data + + def close(self): + # Note: the real connection will only close if it's open, so + # no need to check that here. + self.real_connection.close() + + def endheaders(self, message_body=None): + """ + Normally, this would actually send the request to the server. + We are not sending the request until getting the response, + so bypass this part and just append the message body, if any. + """ + if message_body is not None: + self._vcr_request.body = message_body + + def getresponse(self, _=False, **kwargs): + '''Retrieve the response''' + # Check to see if the cassette has a response for this request. If so, + # then return it + if self.cassette.can_play_response_for(self._vcr_request): + log.info( + "Playing response for {0} from cassette".format( + self._vcr_request + ) + ) + response = self.cassette.play_response(self._vcr_request) + return VCRHTTPResponse(response) + else: + if self.cassette.write_protected and self.cassette.filter_request( + self._vcr_request + ): + raise CannotOverwriteExistingCassetteException( + "No match for the request (%r) was found. " + "Can't overwrite existing cassette (%r) in " + "your current record mode (%r)." + % (self._vcr_request, self.cassette._path, + self.cassette.record_mode) + ) + + # Otherwise, we should send the request, then get the response + # and return it. + + log.info( + "{0} not in cassette, sending to real server".format( + self._vcr_request + ) + ) + # This is imported here to avoid circular import. + # TODO(@IvanMalison): Refactor to allow normal import. + from vcr.patch import force_reset + with force_reset(): + self.real_connection.request( + method=self._vcr_request.method, + url=self._url(self._vcr_request.uri), + body=self._vcr_request.body, + headers=self._vcr_request.headers, + ) + + # get the response + response = self.real_connection.getresponse() + + # put the response into the cassette + response = { + 'status': { + 'code': response.status, + 'message': response.reason + }, + 'headers': serialize_headers(response), + 'body': {'string': response.read()}, + } + self.cassette.append(self._vcr_request, response) + return VCRHTTPResponse(response) + + def set_debuglevel(self, *args, **kwargs): + self.real_connection.set_debuglevel(*args, **kwargs) + + def connect(self, *args, **kwargs): + """ + httplib2 uses this. Connects to the server I'm assuming. + + Only pass to the baseclass if we don't have a recorded response + and are not write-protected. + """ + + if hasattr(self, '_vcr_request') and \ + self.cassette.can_play_response_for(self._vcr_request): + # We already have a response we are going to play, don't + # actually connect + return + + if self.cassette.write_protected: + # Cassette is write-protected, don't actually connect + return + + return self.real_connection.connect(*args, **kwargs) + + @property + def sock(self): + if self.real_connection.sock: + return self.real_connection.sock + return VCRFakeSocket() + + @sock.setter + def sock(self, value): + if self.real_connection.sock: + self.real_connection.sock = value + + def __init__(self, *args, **kwargs): + if six.PY3: + kwargs.pop('strict', None) # apparently this is gone in py3 + + # need to temporarily reset here because the real connection + # inherits from the thing that we are mocking out. Take out + # the reset if you want to see what I mean :) + from vcr.patch import force_reset + with force_reset(): + self.real_connection = self._baseclass(*args, **kwargs) + + def __setattr__(self, name, value): + """ + We need to define this because any attributes that are set on the + VCRConnection need to be propogated to the real connection. + + For example, urllib3 will set certain attributes on the connection, + such as 'ssl_version'. These attributes need to get set on the real + connection to have the correct and expected behavior. + + TODO: Separately setting the attribute on the two instances is not + ideal. We should switch to a proxying implementation. + """ + try: + setattr(self.real_connection, name, value) + except AttributeError: + # raised if real_connection has not been set yet, such as when + # we're setting the real_connection itself for the first time + pass + + super(VCRConnection, self).__setattr__(name, value) + + +class VCRHTTPConnection(VCRConnection): + '''A Mocked class for HTTP requests''' + _baseclass = HTTPConnection + _protocol = 'http' + + +class VCRHTTPSConnection(VCRConnection): + '''A Mocked class for HTTPS requests''' + _baseclass = HTTPSConnection + _protocol = 'https' + is_verified = True diff --git a/lib/vcr/stubs/aiohttp_stubs/__init__.py b/lib/vcr/stubs/aiohttp_stubs/__init__.py new file mode 100644 index 0000000000..5730d3bb35 --- /dev/null +++ b/lib/vcr/stubs/aiohttp_stubs/__init__.py @@ -0,0 +1,100 @@ +'''Stubs for aiohttp HTTP clients''' +from __future__ import absolute_import + +import asyncio +import functools +import json +import urllib + +from aiohttp import ClientResponse, helpers + +from vcr.request import Request + + +class MockClientResponse(ClientResponse): + # TODO: get encoding from header + @asyncio.coroutine + def json(self, *, encoding='utf-8', loads=json.loads): # NOQA: E999 + return loads(self.content.decode(encoding)) + + @asyncio.coroutine + def text(self, encoding='utf-8'): + return self.content.decode(encoding) + + @asyncio.coroutine + def release(self): + pass + + +def vcr_request(cassette, real_request): + @functools.wraps(real_request) + @asyncio.coroutine + def new_request(self, method, url, **kwargs): + headers = kwargs.get('headers') + headers = self._prepare_headers(headers) + data = kwargs.get('data') + params = kwargs.get('params') + + # INFO: Query join logic from + # https://github.com/KeepSafe/aiohttp/blob/b3eeedbc2f515ec2aa6e87ba129524c17b6fe4e3/aiohttp/client_reqrep.py#L167-L188 + scheme, netloc, path, query, fragment = urllib.parse.urlsplit(url) + if not path: + path = '/' + + # NOTICE: Not sure this is applicable here: + # if isinstance(params, collections.Mapping): + # params = list(params.items()) + + if params: + if not isinstance(params, str): + params = urllib.parse.urlencode(params) + if query: + query = '%s&%s' % (query, params) + else: + query = params + + request_path = urllib.parse.urlunsplit(('', '', helpers.requote_uri(path), + query, fragment)) + request_url = urllib.parse.urlunsplit( + (scheme, netloc, request_path, '', '')) + + vcr_request = Request(method, request_url, data, headers) + + if cassette.can_play_response_for(vcr_request): + vcr_response = cassette.play_response(vcr_request) + + response = MockClientResponse(method, vcr_response.get('url')) + response.status = vcr_response['status']['code'] + response.content = vcr_response['body']['string'] + response.reason = vcr_response['status']['message'] + response.headers = vcr_response['headers'] + + response.close() + return response + + if cassette.write_protected and cassette.filter_request(vcr_request): + response = MockClientResponse(method, url) + response.status = 599 + msg = ("No match for the request {!r} was found. Can't overwrite " + "existing cassette {!r} in your current record mode {!r}.") + msg = msg.format(vcr_request, cassette._path, cassette.record_mode) + response.content = msg.encode() + response.close() + return response + + response = yield from real_request(self, method, url, **kwargs) # NOQA: E999 + + vcr_response = { + 'status': { + 'code': response.status, + 'message': response.reason, + }, + 'headers': dict(response.headers), + 'body': {'string': (yield from response.text())}, # NOQA: E999 + 'url': response.url, + } + cassette.append(vcr_request, vcr_response) + + return response + + return new_request diff --git a/lib/vcr/stubs/boto3_stubs.py b/lib/vcr/stubs/boto3_stubs.py new file mode 100644 index 0000000000..93a7bdb394 --- /dev/null +++ b/lib/vcr/stubs/boto3_stubs.py @@ -0,0 +1,15 @@ +'''Stubs for boto3''' + +from botocore.vendored.requests.packages.urllib3.connectionpool import HTTPConnection, VerifiedHTTPSConnection +from ..stubs import VCRHTTPConnection, VCRHTTPSConnection + +# urllib3 defines its own HTTPConnection classes, which boto3 goes ahead and assumes +# you're using. It includes some polyfills for newer features missing in older pythons. + + +class VCRRequestsHTTPConnection(VCRHTTPConnection, HTTPConnection): + _baseclass = HTTPConnection + + +class VCRRequestsHTTPSConnection(VCRHTTPSConnection, VerifiedHTTPSConnection): + _baseclass = VerifiedHTTPSConnection diff --git a/lib/vcr/stubs/boto_stubs.py b/lib/vcr/stubs/boto_stubs.py new file mode 100644 index 0000000000..af0277ab23 --- /dev/null +++ b/lib/vcr/stubs/boto_stubs.py @@ -0,0 +1,8 @@ +'''Stubs for boto''' + +from boto.https_connection import CertValidatingHTTPSConnection +from ..stubs import VCRHTTPSConnection + + +class VCRCertValidatingHTTPSConnection(VCRHTTPSConnection): + _baseclass = CertValidatingHTTPSConnection diff --git a/lib/vcr/stubs/compat.py b/lib/vcr/stubs/compat.py new file mode 100644 index 0000000000..d640ac4ad0 --- /dev/null +++ b/lib/vcr/stubs/compat.py @@ -0,0 +1,43 @@ +import six +from six import BytesIO +from six.moves.http_client import HTTPMessage +try: + import http.client +except ImportError: + pass + + +""" +The python3 http.client api moved some stuff around, so this is an abstraction +layer that tries to cope with this move. +""" + + +def get_header(message, name): + if six.PY3: + return message.getallmatchingheaders(name) + else: + return message.getheader(name) + + +def get_header_items(message): + for (key, values) in get_headers(message): + for value in values: + yield key, value + + +def get_headers(message): + for key in set(message.keys()): + if six.PY3: + yield key, message.get_all(key) + else: + yield key, message.getheaders(key) + + +def get_httpmessage(headers): + if six.PY3: + return http.client.parse_headers(BytesIO(headers)) + msg = HTTPMessage(BytesIO(headers)) + msg.fp.seek(0) + msg.readheaders() + return msg diff --git a/lib/vcr/stubs/httplib2_stubs.py b/lib/vcr/stubs/httplib2_stubs.py new file mode 100644 index 0000000000..b08f3575d8 --- /dev/null +++ b/lib/vcr/stubs/httplib2_stubs.py @@ -0,0 +1,63 @@ +'''Stubs for httplib2''' + +from httplib2 import HTTPConnectionWithTimeout, HTTPSConnectionWithTimeout +from ..stubs import VCRHTTPConnection, VCRHTTPSConnection + + +class VCRHTTPConnectionWithTimeout(VCRHTTPConnection, + HTTPConnectionWithTimeout): + _baseclass = HTTPConnectionWithTimeout + + def __init__(self, *args, **kwargs): + '''I overrode the init because I need to clean kwargs before calling + HTTPConnection.__init__.''' + + # Delete the keyword arguments that HTTPConnection would not recognize + safe_keys = set( + ('host', 'port', 'strict', 'timeout', 'source_address') + ) + unknown_keys = set(kwargs.keys()) - safe_keys + safe_kwargs = kwargs.copy() + for kw in unknown_keys: + del safe_kwargs[kw] + + self.proxy_info = kwargs.pop('proxy_info', None) + VCRHTTPConnection.__init__(self, *args, **safe_kwargs) + self.sock = self.real_connection.sock + + +class VCRHTTPSConnectionWithTimeout(VCRHTTPSConnection, + HTTPSConnectionWithTimeout): + _baseclass = HTTPSConnectionWithTimeout + + def __init__(self, *args, **kwargs): + + # Delete the keyword arguments that HTTPSConnection would not recognize + safe_keys = set(( + 'host', + 'port', + 'key_file', + 'cert_file', + 'strict', + 'timeout', + 'source_address', + 'ca_certs', + )) + unknown_keys = set(kwargs.keys()) - safe_keys + safe_kwargs = kwargs.copy() + for kw in unknown_keys: + del safe_kwargs[kw] + self.proxy_info = kwargs.pop('proxy_info', None) + if 'ca_certs' not in kwargs or kwargs['ca_certs'] is None: + try: + import httplib2 + self.ca_certs = httplib2.CA_CERTS + except ImportError: + self.ca_certs = None + else: + self.ca_certs = kwargs['ca_certs'] + + self.disable_ssl_certificate_validation = kwargs.pop( + 'disable_ssl_certificate_validation', None) + VCRHTTPSConnection.__init__(self, *args, **safe_kwargs) + self.sock = self.real_connection.sock diff --git a/lib/vcr/stubs/requests_stubs.py b/lib/vcr/stubs/requests_stubs.py new file mode 100644 index 0000000000..8cae533bd1 --- /dev/null +++ b/lib/vcr/stubs/requests_stubs.py @@ -0,0 +1,19 @@ +'''Stubs for requests''' + +try: + from requests.packages.urllib3.connectionpool import HTTPConnection, VerifiedHTTPSConnection +except ImportError: + from urllib3.connectionpool import HTTPConnection, VerifiedHTTPSConnection + +from ..stubs import VCRHTTPConnection, VCRHTTPSConnection + +# urllib3 defines its own HTTPConnection classes, which requests goes ahead and assumes +# you're using. It includes some polyfills for newer features missing in older pythons. + + +class VCRRequestsHTTPConnection(VCRHTTPConnection, HTTPConnection): + _baseclass = HTTPConnection + + +class VCRRequestsHTTPSConnection(VCRHTTPSConnection, VerifiedHTTPSConnection): + _baseclass = VerifiedHTTPSConnection diff --git a/lib/vcr/stubs/tornado_stubs.py b/lib/vcr/stubs/tornado_stubs.py new file mode 100644 index 0000000000..b6750650fe --- /dev/null +++ b/lib/vcr/stubs/tornado_stubs.py @@ -0,0 +1,107 @@ +'''Stubs for tornado HTTP clients''' +from __future__ import absolute_import + +import functools +from six import BytesIO + +from tornado import httputil +from tornado.httpclient import HTTPResponse + +from vcr.errors import CannotOverwriteExistingCassetteException +from vcr.request import Request + + +def vcr_fetch_impl(cassette, real_fetch_impl): + + @functools.wraps(real_fetch_impl) + def new_fetch_impl(self, request, callback): + headers = request.headers.copy() + if request.user_agent: + headers.setdefault('User-Agent', request.user_agent) + + # TODO body_producer, header_callback, and streaming_callback are not + # yet supported. + + unsupported_call = ( + getattr(request, 'body_producer', None) is not None or + request.header_callback is not None or + request.streaming_callback is not None + ) + if unsupported_call: + response = HTTPResponse( + request, + 599, + error=Exception( + "The request (%s) uses AsyncHTTPClient functionality " + "that is not yet supported by VCR.py. Please make the " + "request outside a VCR.py context." % repr(request) + ), + request_time=self.io_loop.time() - request.start_time, + ) + return callback(response) + + vcr_request = Request( + request.method, + request.url, + request.body, + headers, + ) + + if cassette.can_play_response_for(vcr_request): + vcr_response = cassette.play_response(vcr_request) + headers = httputil.HTTPHeaders() + + recorded_headers = vcr_response['headers'] + if isinstance(recorded_headers, dict): + recorded_headers = recorded_headers.items() + for k, vs in recorded_headers: + for v in vs: + headers.add(k, v) + response = HTTPResponse( + request, + code=vcr_response['status']['code'], + reason=vcr_response['status']['message'], + headers=headers, + buffer=BytesIO(vcr_response['body']['string']), + effective_url=vcr_response.get('url'), + request_time=self.io_loop.time() - request.start_time, + ) + return callback(response) + else: + if cassette.write_protected and cassette.filter_request( + vcr_request + ): + response = HTTPResponse( + request, + 599, + error=CannotOverwriteExistingCassetteException( + "No match for the request (%r) was found. " + "Can't overwrite existing cassette (%r) in " + "your current record mode (%r)." + % (vcr_request, cassette._path, cassette.record_mode) + ), + request_time=self.io_loop.time() - request.start_time, + ) + return callback(response) + + def new_callback(response): + headers = [ + (k, response.headers.get_list(k)) + for k in response.headers.keys() + ] + + vcr_response = { + 'status': { + 'code': response.code, + 'message': response.reason, + }, + 'headers': headers, + 'body': {'string': response.body}, + 'url': response.effective_url, + } + cassette.append(vcr_request, vcr_response) + return callback(response) + + real_fetch_impl(self, request, new_callback) + + return new_fetch_impl diff --git a/lib/vcr/stubs/urllib3_stubs.py b/lib/vcr/stubs/urllib3_stubs.py new file mode 100644 index 0000000000..dff38d1396 --- /dev/null +++ b/lib/vcr/stubs/urllib3_stubs.py @@ -0,0 +1,15 @@ +'''Stubs for urllib3''' + +from urllib3.connectionpool import HTTPConnection, VerifiedHTTPSConnection +from ..stubs import VCRHTTPConnection, VCRHTTPSConnection + +# urllib3 defines its own HTTPConnection classes. It includes some polyfills +# for newer features missing in older pythons. + + +class VCRRequestsHTTPConnection(VCRHTTPConnection, HTTPConnection): + _baseclass = HTTPConnection + + +class VCRRequestsHTTPSConnection(VCRHTTPSConnection, VerifiedHTTPSConnection): + _baseclass = VerifiedHTTPSConnection diff --git a/lib/vcr/util.py b/lib/vcr/util.py new file mode 100644 index 0000000000..2e6effbc82 --- /dev/null +++ b/lib/vcr/util.py @@ -0,0 +1,124 @@ +import collections +import types + + +# Shamelessly stolen from https://github.com/kennethreitz/requests/blob/master/requests/structures.py +class CaseInsensitiveDict(collections.MutableMapping): + """ + A case-insensitive ``dict``-like object. + Implements all methods and operations of + ``collections.MutableMapping`` as well as dict's ``copy``. Also + provides ``lower_items``. + All keys are expected to be strings. The structure remembers the + case of the last key to be set, and ``iter(instance)``, + ``keys()``, ``items()``, ``iterkeys()``, and ``iteritems()`` + will contain case-sensitive keys. However, querying and contains + testing is case insensitive:: + cid = CaseInsensitiveDict() + cid['Accept'] = 'application/json' + cid['aCCEPT'] == 'application/json' # True + list(cid) == ['Accept'] # True + For example, ``headers['content-encoding']`` will return the + value of a ``'Content-Encoding'`` response header, regardless + of how the header name was originally stored. + If the constructor, ``.update``, or equality comparison + operations are given keys that have equal ``.lower()``s, the + behavior is undefined. + """ + def __init__(self, data=None, **kwargs): + self._store = dict() + if data is None: + data = {} + self.update(data, **kwargs) + + def __setitem__(self, key, value): + # Use the lowercased key for lookups, but store the actual + # key alongside the value. + self._store[key.lower()] = (key, value) + + def __getitem__(self, key): + return self._store[key.lower()][1] + + def __delitem__(self, key): + del self._store[key.lower()] + + def __iter__(self): + return (casedkey for casedkey, mappedvalue in self._store.values()) + + def __len__(self): + return len(self._store) + + def lower_items(self): + """Like iteritems(), but with all lowercase keys.""" + return ( + (lowerkey, keyval[1]) + for (lowerkey, keyval) + in self._store.items() + ) + + def __eq__(self, other): + if isinstance(other, collections.Mapping): + other = CaseInsensitiveDict(other) + else: + return NotImplemented + # Compare insensitively + return dict(self.lower_items()) == dict(other.lower_items()) + + # Copy is required + def copy(self): + return CaseInsensitiveDict(self._store.values()) + + def __repr__(self): + return str(dict(self.items())) + + +def partition_dict(predicate, dictionary): + true_dict = {} + false_dict = {} + for key, value in dictionary.items(): + this_dict = true_dict if predicate(key, value) else false_dict + this_dict[key] = value + return true_dict, false_dict + + +def compose(*functions): + def composed(incoming): + res = incoming + for function in reversed(functions): + if function: + res = function(res) + return res + return composed + + +def read_body(request): + if hasattr(request.body, 'read'): + return request.body.read() + return request.body + + +def auto_decorate( + decorator, + predicate=lambda name, value: isinstance(value, types.FunctionType) +): + def maybe_decorate(attribute, value): + if predicate(attribute, value): + value = decorator(value) + return value + + class DecorateAll(type): + + def __setattr__(cls, attribute, value): + return super(DecorateAll, cls).__setattr__( + attribute, maybe_decorate(attribute, value) + ) + + def __new__(cls, name, bases, attributes_dict): + new_attributes_dict = dict( + (attribute, maybe_decorate(attribute, value)) + for attribute, value in attributes_dict.items() + ) + return super(DecorateAll, cls).__new__( + cls, name, bases, new_attributes_dict + ) + return DecorateAll diff --git a/lib/wrapt/__init__.py b/lib/wrapt/__init__.py new file mode 100644 index 0000000000..6e8e5e9ff3 --- /dev/null +++ b/lib/wrapt/__init__.py @@ -0,0 +1,19 @@ +__version_info__ = ('1', '10', '8') +__version__ = '.'.join(__version_info__) + +from .wrappers import (ObjectProxy, CallableObjectProxy, FunctionWrapper, + BoundFunctionWrapper, WeakFunctionProxy, resolve_path, apply_patch, + wrap_object, wrap_object_attribute, function_wrapper, + wrap_function_wrapper, patch_function_wrapper, + transient_function_wrapper) + +from .decorators import (adapter_factory, AdapterFactory, decorator, + synchronized) + +from .importer import (register_post_import_hook, when_imported, + notify_module_loaded, discover_post_import_hooks) + +try: + from inspect import getcallargs +except ImportError: + from .arguments import getcallargs diff --git a/lib/wrapt/_wrappers.c b/lib/wrapt/_wrappers.c new file mode 100644 index 0000000000..9194f540c4 --- /dev/null +++ b/lib/wrapt/_wrappers.c @@ -0,0 +1,2729 @@ +/* ------------------------------------------------------------------------- */ + +#include "Python.h" + +#include "structmember.h" + +#ifndef PyVarObject_HEAD_INIT +#define PyVarObject_HEAD_INIT(type, size) PyObject_HEAD_INIT(type) size, +#endif + +/* ------------------------------------------------------------------------- */ + +typedef struct { + PyObject_HEAD + + PyObject *dict; + PyObject *wrapped; + PyObject *weakreflist; +} WraptObjectProxyObject; + +PyTypeObject WraptObjectProxy_Type; +PyTypeObject WraptCallableObjectProxy_Type; + +typedef struct { + WraptObjectProxyObject object_proxy; + + PyObject *instance; + PyObject *wrapper; + PyObject *enabled; + PyObject *binding; + PyObject *parent; +} WraptFunctionWrapperObject; + +PyTypeObject WraptFunctionWrapperBase_Type; +PyTypeObject WraptBoundFunctionWrapper_Type; +PyTypeObject WraptFunctionWrapper_Type; + +/* ------------------------------------------------------------------------- */ + +static PyObject *WraptObjectProxy_new(PyTypeObject *type, + PyObject *args, PyObject *kwds) +{ + WraptObjectProxyObject *self; + + self = (WraptObjectProxyObject *)type->tp_alloc(type, 0); + + if (!self) + return NULL; + + self->dict = PyDict_New(); + self->wrapped = NULL; + self->weakreflist = NULL; + + return (PyObject *)self; +} + +/* ------------------------------------------------------------------------- */ + +static int WraptObjectProxy_raw_init(WraptObjectProxyObject *self, + PyObject *wrapped) +{ + static PyObject *module_str = NULL; + static PyObject *doc_str = NULL; + + PyObject *object = NULL; + + Py_INCREF(wrapped); + Py_XDECREF(self->wrapped); + self->wrapped = wrapped; + + if (!module_str) { +#if PY_MAJOR_VERSION >= 3 + module_str = PyUnicode_InternFromString("__module__"); +#else + module_str = PyString_InternFromString("__module__"); +#endif + } + + if (!doc_str) { +#if PY_MAJOR_VERSION >= 3 + doc_str = PyUnicode_InternFromString("__doc__"); +#else + doc_str = PyString_InternFromString("__doc__"); +#endif + } + + object = PyObject_GetAttr(wrapped, module_str); + + if (object) { + if (PyDict_SetItem(self->dict, module_str, object) == -1) { + Py_DECREF(object); + return -1; + } + Py_DECREF(object); + } + else + PyErr_Clear(); + + object = PyObject_GetAttr(wrapped, doc_str); + + if (object) { + if (PyDict_SetItem(self->dict, doc_str, object) == -1) { + Py_DECREF(object); + return -1; + } + Py_DECREF(object); + } + else + PyErr_Clear(); + + return 0; +} + +/* ------------------------------------------------------------------------- */ + +static int WraptObjectProxy_init(WraptObjectProxyObject *self, + PyObject *args, PyObject *kwds) +{ + PyObject *wrapped = NULL; + + static char *kwlist[] = { "wrapped", NULL }; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "O:ObjectProxy", + kwlist, &wrapped)) { + return -1; + } + + return WraptObjectProxy_raw_init(self, wrapped); +} + +/* ------------------------------------------------------------------------- */ + +static int WraptObjectProxy_traverse(WraptObjectProxyObject *self, + visitproc visit, void *arg) +{ + Py_VISIT(self->dict); + Py_VISIT(self->wrapped); + + return 0; +} + +/* ------------------------------------------------------------------------- */ + +static int WraptObjectProxy_clear(WraptObjectProxyObject *self) +{ + Py_CLEAR(self->dict); + Py_CLEAR(self->wrapped); + + return 0; +} + +/* ------------------------------------------------------------------------- */ + +static void WraptObjectProxy_dealloc(WraptObjectProxyObject *self) +{ + PyObject_GC_UnTrack(self); + + if (self->weakreflist != NULL) + PyObject_ClearWeakRefs((PyObject *)self); + + WraptObjectProxy_clear(self); + + Py_TYPE(self)->tp_free(self); +} + +/* ------------------------------------------------------------------------- */ + +static PyObject *WraptObjectProxy_repr(WraptObjectProxyObject *self) +{ + if (!self->wrapped) { + PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); + return NULL; + } + +#if PY_MAJOR_VERSION >= 3 + return PyUnicode_FromFormat("<%s at %p for %s at %p>", + Py_TYPE(self)->tp_name, self, + Py_TYPE(self->wrapped)->tp_name, self->wrapped); +#else + return PyString_FromFormat("<%s at %p for %s at %p>", + Py_TYPE(self)->tp_name, self, + Py_TYPE(self->wrapped)->tp_name, self->wrapped); +#endif +} + +/* ------------------------------------------------------------------------- */ + +static long WraptObjectProxy_hash(WraptObjectProxyObject *self) +{ + if (!self->wrapped) { + PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); + return -1; + } + + return PyObject_Hash(self->wrapped); +} + +/* ------------------------------------------------------------------------- */ + +static PyObject *WraptObjectProxy_str(WraptObjectProxyObject *self) +{ + if (!self->wrapped) { + PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); + return NULL; + } + + return PyObject_Str(self->wrapped); +} + +/* ------------------------------------------------------------------------- */ + +static PyObject *WraptObjectProxy_add(PyObject *o1, PyObject *o2) +{ + if (!((WraptObjectProxyObject *)o1)->wrapped) { + PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); + return NULL; + } + + if (!((WraptObjectProxyObject *)o2)->wrapped) { + PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); + return NULL; + } + + if (PyObject_IsInstance(o1, (PyObject *)&WraptObjectProxy_Type)) + o1 = ((WraptObjectProxyObject *)o1)->wrapped; + + if (PyObject_IsInstance(o2, (PyObject *)&WraptObjectProxy_Type)) + o2 = ((WraptObjectProxyObject *)o2)->wrapped; + + return PyNumber_Add(o1, o2); +} + +/* ------------------------------------------------------------------------- */ + +static PyObject *WraptObjectProxy_subtract(PyObject *o1, PyObject *o2) +{ + if (!((WraptObjectProxyObject *)o1)->wrapped) { + PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); + return NULL; + } + + if (!((WraptObjectProxyObject *)o2)->wrapped) { + PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); + return NULL; + } + + if (PyObject_IsInstance(o1, (PyObject *)&WraptObjectProxy_Type)) + o1 = ((WraptObjectProxyObject *)o1)->wrapped; + + if (PyObject_IsInstance(o2, (PyObject *)&WraptObjectProxy_Type)) + o2 = ((WraptObjectProxyObject *)o2)->wrapped; + + + return PyNumber_Subtract(o1, o2); +} + +/* ------------------------------------------------------------------------- */ + +static PyObject *WraptObjectProxy_multiply(PyObject *o1, PyObject *o2) +{ + if (!((WraptObjectProxyObject *)o1)->wrapped) { + PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); + return NULL; + } + + if (!((WraptObjectProxyObject *)o2)->wrapped) { + PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); + return NULL; + } + + if (PyObject_IsInstance(o1, (PyObject *)&WraptObjectProxy_Type)) + o1 = ((WraptObjectProxyObject *)o1)->wrapped; + + if (PyObject_IsInstance(o2, (PyObject *)&WraptObjectProxy_Type)) + o2 = ((WraptObjectProxyObject *)o2)->wrapped; + + return PyNumber_Multiply(o1, o2); +} + +/* ------------------------------------------------------------------------- */ + +#if PY_MAJOR_VERSION < 3 +static PyObject *WraptObjectProxy_divide(PyObject *o1, PyObject *o2) +{ + if (!((WraptObjectProxyObject *)o1)->wrapped) { + PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); + return NULL; + } + + if (!((WraptObjectProxyObject *)o2)->wrapped) { + PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); + return NULL; + } + + if (PyObject_IsInstance(o1, (PyObject *)&WraptObjectProxy_Type)) + o1 = ((WraptObjectProxyObject *)o1)->wrapped; + + if (PyObject_IsInstance(o2, (PyObject *)&WraptObjectProxy_Type)) + o2 = ((WraptObjectProxyObject *)o2)->wrapped; + + return PyNumber_Divide(o1, o2); +} +#endif + +/* ------------------------------------------------------------------------- */ + +static PyObject *WraptObjectProxy_remainder(PyObject *o1, PyObject *o2) +{ + if (!((WraptObjectProxyObject *)o1)->wrapped) { + PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); + return NULL; + } + + if (!((WraptObjectProxyObject *)o2)->wrapped) { + PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); + return NULL; + } + + if (PyObject_IsInstance(o1, (PyObject *)&WraptObjectProxy_Type)) + o1 = ((WraptObjectProxyObject *)o1)->wrapped; + + if (PyObject_IsInstance(o2, (PyObject *)&WraptObjectProxy_Type)) + o2 = ((WraptObjectProxyObject *)o2)->wrapped; + + return PyNumber_Remainder(o1, o2); +} + +/* ------------------------------------------------------------------------- */ + +static PyObject *WraptObjectProxy_divmod(PyObject *o1, PyObject *o2) +{ + if (!((WraptObjectProxyObject *)o1)->wrapped) { + PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); + return NULL; + } + + if (!((WraptObjectProxyObject *)o2)->wrapped) { + PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); + return NULL; + } + + if (PyObject_IsInstance(o1, (PyObject *)&WraptObjectProxy_Type)) + o1 = ((WraptObjectProxyObject *)o1)->wrapped; + + if (PyObject_IsInstance(o2, (PyObject *)&WraptObjectProxy_Type)) + o2 = ((WraptObjectProxyObject *)o2)->wrapped; + + return PyNumber_Divmod(o1, o2); +} + +/* ------------------------------------------------------------------------- */ + +static PyObject *WraptObjectProxy_power(PyObject *o1, PyObject *o2, + PyObject *modulo) +{ + if (!((WraptObjectProxyObject *)o1)->wrapped) { + PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); + return NULL; + } + + if (!((WraptObjectProxyObject *)o2)->wrapped) { + PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); + return NULL; + } + + if (PyObject_IsInstance(o1, (PyObject *)&WraptObjectProxy_Type)) + o1 = ((WraptObjectProxyObject *)o1)->wrapped; + + if (PyObject_IsInstance(o2, (PyObject *)&WraptObjectProxy_Type)) + o2 = ((WraptObjectProxyObject *)o2)->wrapped; + + return PyNumber_Power(o1, o2, modulo); +} + +/* ------------------------------------------------------------------------- */ + +static PyObject *WraptObjectProxy_negative(WraptObjectProxyObject *self) +{ + if (!self->wrapped) { + PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); + return NULL; + } + + return PyNumber_Negative(self->wrapped); +} + +/* ------------------------------------------------------------------------- */ + +static PyObject *WraptObjectProxy_positive(WraptObjectProxyObject *self) +{ + if (!self->wrapped) { + PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); + return NULL; + } + + return PyNumber_Positive(self->wrapped); +} + +/* ------------------------------------------------------------------------- */ + +static PyObject *WraptObjectProxy_absolute(WraptObjectProxyObject *self) +{ + if (!self->wrapped) { + PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); + return NULL; + } + + return PyNumber_Absolute(self->wrapped); +} + +/* ------------------------------------------------------------------------- */ + +static int WraptObjectProxy_bool(WraptObjectProxyObject *self) +{ + if (!self->wrapped) { + PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); + return -1; + } + + return PyObject_IsTrue(self->wrapped); +} + +/* ------------------------------------------------------------------------- */ + +static PyObject *WraptObjectProxy_invert(WraptObjectProxyObject *self) +{ + if (!self->wrapped) { + PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); + return NULL; + } + + return PyNumber_Invert(self->wrapped); +} + +/* ------------------------------------------------------------------------- */ + +static PyObject *WraptObjectProxy_lshift(PyObject *o1, PyObject *o2) +{ + if (!((WraptObjectProxyObject *)o1)->wrapped) { + PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); + return NULL; + } + + if (!((WraptObjectProxyObject *)o2)->wrapped) { + PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); + return NULL; + } + + if (PyObject_IsInstance(o1, (PyObject *)&WraptObjectProxy_Type)) + o1 = ((WraptObjectProxyObject *)o1)->wrapped; + + if (PyObject_IsInstance(o2, (PyObject *)&WraptObjectProxy_Type)) + o2 = ((WraptObjectProxyObject *)o2)->wrapped; + + return PyNumber_Lshift(o1, o2); +} + +/* ------------------------------------------------------------------------- */ + +static PyObject *WraptObjectProxy_rshift(PyObject *o1, PyObject *o2) +{ + if (!((WraptObjectProxyObject *)o1)->wrapped) { + PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); + return NULL; + } + + if (!((WraptObjectProxyObject *)o2)->wrapped) { + PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); + return NULL; + } + + if (PyObject_IsInstance(o1, (PyObject *)&WraptObjectProxy_Type)) + o1 = ((WraptObjectProxyObject *)o1)->wrapped; + + if (PyObject_IsInstance(o2, (PyObject *)&WraptObjectProxy_Type)) + o2 = ((WraptObjectProxyObject *)o2)->wrapped; + + return PyNumber_Rshift(o1, o2); +} + +/* ------------------------------------------------------------------------- */ + +static PyObject *WraptObjectProxy_and(PyObject *o1, PyObject *o2) +{ + if (!((WraptObjectProxyObject *)o1)->wrapped) { + PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); + return NULL; + } + + if (!((WraptObjectProxyObject *)o2)->wrapped) { + PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); + return NULL; + } + + if (PyObject_IsInstance(o1, (PyObject *)&WraptObjectProxy_Type)) + o1 = ((WraptObjectProxyObject *)o1)->wrapped; + + if (PyObject_IsInstance(o2, (PyObject *)&WraptObjectProxy_Type)) + o2 = ((WraptObjectProxyObject *)o2)->wrapped; + + return PyNumber_And(o1, o2); +} + +/* ------------------------------------------------------------------------- */ + +static PyObject *WraptObjectProxy_xor(PyObject *o1, PyObject *o2) +{ + if (!((WraptObjectProxyObject *)o1)->wrapped) { + PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); + return NULL; + } + + if (!((WraptObjectProxyObject *)o2)->wrapped) { + PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); + return NULL; + } + + if (PyObject_IsInstance(o1, (PyObject *)&WraptObjectProxy_Type)) + o1 = ((WraptObjectProxyObject *)o1)->wrapped; + + if (PyObject_IsInstance(o2, (PyObject *)&WraptObjectProxy_Type)) + o2 = ((WraptObjectProxyObject *)o2)->wrapped; + + return PyNumber_Xor(o1, o2); +} + +/* ------------------------------------------------------------------------- */ + +static PyObject *WraptObjectProxy_or(PyObject *o1, PyObject *o2) +{ + if (!((WraptObjectProxyObject *)o1)->wrapped) { + PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); + return NULL; + } + + if (!((WraptObjectProxyObject *)o2)->wrapped) { + PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); + return NULL; + } + + if (PyObject_IsInstance(o1, (PyObject *)&WraptObjectProxy_Type)) + o1 = ((WraptObjectProxyObject *)o1)->wrapped; + + if (PyObject_IsInstance(o2, (PyObject *)&WraptObjectProxy_Type)) + o2 = ((WraptObjectProxyObject *)o2)->wrapped; + + return PyNumber_Or(o1, o2); +} + +/* ------------------------------------------------------------------------- */ + +#if PY_MAJOR_VERSION < 3 +static PyObject *WraptObjectProxy_int(WraptObjectProxyObject *self) +{ + if (!self->wrapped) { + PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); + return NULL; + } + + return PyNumber_Int(self->wrapped); +} +#endif + +/* ------------------------------------------------------------------------- */ + +static PyObject *WraptObjectProxy_long(WraptObjectProxyObject *self) +{ + if (!self->wrapped) { + PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); + return NULL; + } + + return PyNumber_Long(self->wrapped); +} + +/* ------------------------------------------------------------------------- */ + +static PyObject *WraptObjectProxy_float(WraptObjectProxyObject *self) +{ + if (!self->wrapped) { + PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); + return NULL; + } + + return PyNumber_Float(self->wrapped); +} + +/* ------------------------------------------------------------------------- */ + +#if PY_MAJOR_VERSION < 3 +static PyObject *WraptObjectProxy_oct(WraptObjectProxyObject *self) +{ + PyNumberMethods *nb; + + if (!self->wrapped) { + PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); + return NULL; + } + + if ((nb = self->wrapped->ob_type->tp_as_number) == NULL || + nb->nb_oct == NULL) { + PyErr_SetString(PyExc_TypeError, + "oct() argument can't be converted to oct"); + return NULL; + } + + return (*nb->nb_oct)(self->wrapped); +} +#endif + +/* ------------------------------------------------------------------------- */ + +#if PY_MAJOR_VERSION < 3 +static PyObject *WraptObjectProxy_hex(WraptObjectProxyObject *self) +{ + PyNumberMethods *nb; + + if (!self->wrapped) { + PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); + return NULL; + } + + if ((nb = self->wrapped->ob_type->tp_as_number) == NULL || + nb->nb_hex == NULL) { + PyErr_SetString(PyExc_TypeError, + "hex() argument can't be converted to hex"); + return NULL; + } + + return (*nb->nb_hex)(self->wrapped); +} +#endif + +/* ------------------------------------------------------------------------- */ + +static PyObject *WraptObjectProxy_inplace_add(WraptObjectProxyObject *self, + PyObject *other) +{ + PyObject *object = NULL; + + if (!self->wrapped) { + PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); + return NULL; + } + + if (PyObject_IsInstance(other, (PyObject *)&WraptObjectProxy_Type)) + other = ((WraptObjectProxyObject *)other)->wrapped; + + object = PyNumber_InPlaceAdd(self->wrapped, other); + + if (!object) + return NULL; + + Py_DECREF(self->wrapped); + self->wrapped = object; + + Py_INCREF(self); + return (PyObject *)self; +} + +/* ------------------------------------------------------------------------- */ + +static PyObject *WraptObjectProxy_inplace_subtract( + WraptObjectProxyObject *self, PyObject *other) +{ + PyObject *object = NULL; + + if (!self->wrapped) { + PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); + return NULL; + } + + if (PyObject_IsInstance(other, (PyObject *)&WraptObjectProxy_Type)) + other = ((WraptObjectProxyObject *)other)->wrapped; + + object = PyNumber_InPlaceSubtract(self->wrapped, other); + + if (!object) + return NULL; + + Py_DECREF(self->wrapped); + self->wrapped = object; + + Py_INCREF(self); + return (PyObject *)self; +} + +/* ------------------------------------------------------------------------- */ + +static PyObject *WraptObjectProxy_inplace_multiply( + WraptObjectProxyObject *self, PyObject *other) +{ + PyObject *object = NULL; + + if (!self->wrapped) { + PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); + return NULL; + } + + if (PyObject_IsInstance(other, (PyObject *)&WraptObjectProxy_Type)) + other = ((WraptObjectProxyObject *)other)->wrapped; + + object = PyNumber_InPlaceMultiply(self->wrapped, other); + + if (!object) + return NULL; + + Py_DECREF(self->wrapped); + self->wrapped = object; + + Py_INCREF(self); + return (PyObject *)self; +} + +/* ------------------------------------------------------------------------- */ + +#if PY_MAJOR_VERSION < 3 +static PyObject *WraptObjectProxy_inplace_divide( + WraptObjectProxyObject *self, PyObject *other) +{ + PyObject *object = NULL; + + if (!self->wrapped) { + PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); + return NULL; + } + + if (PyObject_IsInstance(other, (PyObject *)&WraptObjectProxy_Type)) + other = ((WraptObjectProxyObject *)other)->wrapped; + + object = PyNumber_InPlaceDivide(self->wrapped, other); + + if (!object) + return NULL; + + Py_DECREF(self->wrapped); + self->wrapped = object; + + Py_INCREF(self); + return (PyObject *)self; +} +#endif + +/* ------------------------------------------------------------------------- */ + +static PyObject *WraptObjectProxy_inplace_remainder( + WraptObjectProxyObject *self, PyObject *other) +{ + PyObject *object = NULL; + + if (!self->wrapped) { + PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); + return NULL; + } + + if (PyObject_IsInstance(other, (PyObject *)&WraptObjectProxy_Type)) + other = ((WraptObjectProxyObject *)other)->wrapped; + + object = PyNumber_InPlaceRemainder(self->wrapped, other); + + if (!object) + return NULL; + + Py_DECREF(self->wrapped); + self->wrapped = object; + + Py_INCREF(self); + return (PyObject *)self; +} + +/* ------------------------------------------------------------------------- */ + +static PyObject *WraptObjectProxy_inplace_power(WraptObjectProxyObject *self, + PyObject *other, PyObject *modulo) +{ + PyObject *object = NULL; + + if (!self->wrapped) { + PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); + return NULL; + } + + if (PyObject_IsInstance(other, (PyObject *)&WraptObjectProxy_Type)) + other = ((WraptObjectProxyObject *)other)->wrapped; + + object = PyNumber_InPlacePower(self->wrapped, other, modulo); + + if (!object) + return NULL; + + Py_DECREF(self->wrapped); + self->wrapped = object; + + Py_INCREF(self); + return (PyObject *)self; +} + +/* ------------------------------------------------------------------------- */ + +static PyObject *WraptObjectProxy_inplace_lshift(WraptObjectProxyObject *self, + PyObject *other) +{ + PyObject *object = NULL; + + if (!self->wrapped) { + PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); + return NULL; + } + + if (PyObject_IsInstance(other, (PyObject *)&WraptObjectProxy_Type)) + other = ((WraptObjectProxyObject *)other)->wrapped; + + object = PyNumber_InPlaceLshift(self->wrapped, other); + + if (!object) + return NULL; + + Py_DECREF(self->wrapped); + self->wrapped = object; + + Py_INCREF(self); + return (PyObject *)self; +} + +/* ------------------------------------------------------------------------- */ + +static PyObject *WraptObjectProxy_inplace_rshift(WraptObjectProxyObject *self, + PyObject *other) +{ + PyObject *object = NULL; + + if (!self->wrapped) { + PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); + return NULL; + } + + if (PyObject_IsInstance(other, (PyObject *)&WraptObjectProxy_Type)) + other = ((WraptObjectProxyObject *)other)->wrapped; + + object = PyNumber_InPlaceRshift(self->wrapped, other); + + if (!object) + return NULL; + + Py_DECREF(self->wrapped); + self->wrapped = object; + + Py_INCREF(self); + return (PyObject *)self; +} + +/* ------------------------------------------------------------------------- */ + +static PyObject *WraptObjectProxy_inplace_and(WraptObjectProxyObject *self, + PyObject *other) +{ + PyObject *object = NULL; + + if (!self->wrapped) { + PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); + return NULL; + } + + if (PyObject_IsInstance(other, (PyObject *)&WraptObjectProxy_Type)) + other = ((WraptObjectProxyObject *)other)->wrapped; + + object = PyNumber_InPlaceAnd(self->wrapped, other); + + if (!object) + return NULL; + + Py_DECREF(self->wrapped); + self->wrapped = object; + + Py_INCREF(self); + return (PyObject *)self; +} + +/* ------------------------------------------------------------------------- */ + +static PyObject *WraptObjectProxy_inplace_xor(WraptObjectProxyObject *self, + PyObject *other) +{ + PyObject *object = NULL; + + if (!self->wrapped) { + PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); + return NULL; + } + + if (PyObject_IsInstance(other, (PyObject *)&WraptObjectProxy_Type)) + other = ((WraptObjectProxyObject *)other)->wrapped; + + object = PyNumber_InPlaceXor(self->wrapped, other); + + if (!object) + return NULL; + + Py_DECREF(self->wrapped); + self->wrapped = object; + + Py_INCREF(self); + return (PyObject *)self; +} + +/* ------------------------------------------------------------------------- */ + +static PyObject *WraptObjectProxy_inplace_or(WraptObjectProxyObject *self, + PyObject *other) +{ + PyObject *object = NULL; + + if (!self->wrapped) { + PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); + return NULL; + } + + if (PyObject_IsInstance(other, (PyObject *)&WraptObjectProxy_Type)) + other = ((WraptObjectProxyObject *)other)->wrapped; + + object = PyNumber_InPlaceOr(self->wrapped, other); + + Py_DECREF(self->wrapped); + self->wrapped = object; + + Py_INCREF(self); + return (PyObject *)self; +} + +/* ------------------------------------------------------------------------- */ + +static PyObject *WraptObjectProxy_floor_divide(PyObject *o1, PyObject *o2) +{ + if (!((WraptObjectProxyObject *)o1)->wrapped) { + PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); + return NULL; + } + + if (!((WraptObjectProxyObject *)o2)->wrapped) { + PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); + return NULL; + } + + if (PyObject_IsInstance(o1, (PyObject *)&WraptObjectProxy_Type)) + o1 = ((WraptObjectProxyObject *)o1)->wrapped; + + if (PyObject_IsInstance(o2, (PyObject *)&WraptObjectProxy_Type)) + o2 = ((WraptObjectProxyObject *)o2)->wrapped; + + return PyNumber_FloorDivide(o1, o2); +} + +/* ------------------------------------------------------------------------- */ + +static PyObject *WraptObjectProxy_true_divide(PyObject *o1, PyObject *o2) +{ + if (!((WraptObjectProxyObject *)o1)->wrapped) { + PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); + return NULL; + } + + if (!((WraptObjectProxyObject *)o2)->wrapped) { + PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); + return NULL; + } + + if (PyObject_IsInstance(o1, (PyObject *)&WraptObjectProxy_Type)) + o1 = ((WraptObjectProxyObject *)o1)->wrapped; + + if (PyObject_IsInstance(o2, (PyObject *)&WraptObjectProxy_Type)) + o2 = ((WraptObjectProxyObject *)o2)->wrapped; + + return PyNumber_TrueDivide(o1, o2); +} + +/* ------------------------------------------------------------------------- */ + +static PyObject *WraptObjectProxy_inplace_floor_divide( + WraptObjectProxyObject *self, PyObject *other) +{ + PyObject *object = NULL; + + if (!self->wrapped) { + PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); + return NULL; + } + + if (PyObject_IsInstance(other, (PyObject *)&WraptObjectProxy_Type)) + other = ((WraptObjectProxyObject *)other)->wrapped; + + object = PyNumber_InPlaceFloorDivide(self->wrapped, other); + + if (!object) + return NULL; + + Py_DECREF(self->wrapped); + self->wrapped = object; + + Py_INCREF(self); + return (PyObject *)self; +} + +/* ------------------------------------------------------------------------- */ + +static PyObject *WraptObjectProxy_inplace_true_divide( + WraptObjectProxyObject *self, PyObject *other) +{ + PyObject *object = NULL; + + if (!self->wrapped) { + PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); + return NULL; + } + + if (PyObject_IsInstance(other, (PyObject *)&WraptObjectProxy_Type)) + other = ((WraptObjectProxyObject *)other)->wrapped; + + object = PyNumber_InPlaceTrueDivide(self->wrapped, other); + + if (!object) + return NULL; + + Py_DECREF(self->wrapped); + self->wrapped = object; + + Py_INCREF(self); + return (PyObject *)self; +} + +/* ------------------------------------------------------------------------- */ + +static PyObject *WraptObjectProxy_index(WraptObjectProxyObject *self) +{ + if (!self->wrapped) { + PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); + return NULL; + } + + return PyNumber_Index(self->wrapped); +} + +/* ------------------------------------------------------------------------- */ + +static Py_ssize_t WraptObjectProxy_length(WraptObjectProxyObject *self) +{ + if (!self->wrapped) { + PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); + return -1; + } + + return PyObject_Length(self->wrapped); +} + +/* ------------------------------------------------------------------------- */ + +static int WraptObjectProxy_contains(WraptObjectProxyObject *self, + PyObject *value) +{ + if (!self->wrapped) { + PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); + return -1; + } + + return PySequence_Contains(self->wrapped, value); +} + +/* ------------------------------------------------------------------------- */ + +static PyObject *WraptObjectProxy_getitem(WraptObjectProxyObject *self, + PyObject *key) +{ + if (!self->wrapped) { + PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); + return NULL; + } + + return PyObject_GetItem(self->wrapped, key); +} + +/* ------------------------------------------------------------------------- */ + +static int WraptObjectProxy_setitem(WraptObjectProxyObject *self, + PyObject *key, PyObject* value) +{ + if (!self->wrapped) { + PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); + return -1; + } + + if (value == NULL) + return PyObject_DelItem(self->wrapped, key); + else + return PyObject_SetItem(self->wrapped, key, value); +} + +/* ------------------------------------------------------------------------- */ + +static PyObject *WraptObjectProxy_dir( + WraptObjectProxyObject *self, PyObject *args) +{ + if (!self->wrapped) { + PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); + return NULL; + } + + return PyObject_Dir(self->wrapped); +} + +/* ------------------------------------------------------------------------- */ + +static PyObject *WraptObjectProxy_enter( + WraptObjectProxyObject *self, PyObject *args, PyObject *kwds) +{ + PyObject *method = NULL; + PyObject *result = NULL; + + if (!self->wrapped) { + PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); + return NULL; + } + + method = PyObject_GetAttrString(self->wrapped, "__enter__"); + + if (!method) + return NULL; + + result = PyObject_Call(method, args, kwds); + + Py_DECREF(method); + + return result; +} + +/* ------------------------------------------------------------------------- */ + +static PyObject *WraptObjectProxy_exit( + WraptObjectProxyObject *self, PyObject *args, PyObject *kwds) +{ + PyObject *method = NULL; + PyObject *result = NULL; + + if (!self->wrapped) { + PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); + return NULL; + } + + method = PyObject_GetAttrString(self->wrapped, "__exit__"); + + if (!method) + return NULL; + + result = PyObject_Call(method, args, kwds); + + Py_DECREF(method); + + return result; +} + +/* ------------------------------------------------------------------------- */ + +static PyObject *WraptObjectProxy_bytes( + WraptObjectProxyObject *self, PyObject *args) +{ + if (!self->wrapped) { + PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); + return NULL; + } + + return PyObject_Bytes(self->wrapped); +} + +/* ------------------------------------------------------------------------- */ + +static PyObject *WraptObjectProxy_reversed( + WraptObjectProxyObject *self, PyObject *args) +{ + if (!self->wrapped) { + PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); + return NULL; + } + + return PyObject_CallFunctionObjArgs((PyObject *)&PyReversed_Type, + self->wrapped, NULL); +} + +/* ------------------------------------------------------------------------- */ + +#if PY_MAJOR_VERSION >= 3 +static PyObject *WraptObjectProxy_round( + WraptObjectProxyObject *self, PyObject *args) +{ + PyObject *module = NULL; + PyObject *dict = NULL; + PyObject *round = NULL; + + PyObject *result = NULL; + + if (!self->wrapped) { + PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); + return NULL; + } + + module = PyImport_ImportModule("builtins"); + + if (!module) + return NULL; + + dict = PyModule_GetDict(module); + round = PyDict_GetItemString(dict, "round"); + + if (!round) { + Py_DECREF(module); + return NULL; + } + + Py_INCREF(round); + Py_DECREF(module); + + result = PyObject_CallFunctionObjArgs(round, self->wrapped, NULL); + + Py_DECREF(round); + + return result; +} +#endif + +/* ------------------------------------------------------------------------- */ + +static PyObject *WraptObjectProxy_get_name( + WraptObjectProxyObject *self) +{ + if (!self->wrapped) { + PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); + return NULL; + } + + return PyObject_GetAttrString(self->wrapped, "__name__"); +} + +/* ------------------------------------------------------------------------- */ + +static int WraptObjectProxy_set_name(WraptObjectProxyObject *self, + PyObject *value) +{ + if (!self->wrapped) { + PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); + return -1; + } + + return PyObject_SetAttrString(self->wrapped, "__name__", value); +} + +/* ------------------------------------------------------------------------- */ + +static PyObject *WraptObjectProxy_get_qualname( + WraptObjectProxyObject *self) +{ + if (!self->wrapped) { + PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); + return NULL; + } + + return PyObject_GetAttrString(self->wrapped, "__qualname__"); +} + +/* ------------------------------------------------------------------------- */ + +static int WraptObjectProxy_set_qualname(WraptObjectProxyObject *self, + PyObject *value) +{ + if (!self->wrapped) { + PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); + return -1; + } + + return PyObject_SetAttrString(self->wrapped, "__qualname__", value); +} + +/* ------------------------------------------------------------------------- */ + +static PyObject *WraptObjectProxy_get_module( + WraptObjectProxyObject *self) +{ + if (!self->wrapped) { + PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); + return NULL; + } + + return PyObject_GetAttrString(self->wrapped, "__module__"); +} + +/* ------------------------------------------------------------------------- */ + +static int WraptObjectProxy_set_module(WraptObjectProxyObject *self, + PyObject *value) +{ + if (!self->wrapped) { + PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); + return -1; + } + + if (PyObject_SetAttrString(self->wrapped, "__module__", value) == -1) + return -1; + + return PyDict_SetItemString(self->dict, "__module__", value); +} + +/* ------------------------------------------------------------------------- */ + +static PyObject *WraptObjectProxy_get_doc( + WraptObjectProxyObject *self) +{ + if (!self->wrapped) { + PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); + return NULL; + } + + return PyObject_GetAttrString(self->wrapped, "__doc__"); +} + +/* ------------------------------------------------------------------------- */ + +static int WraptObjectProxy_set_doc(WraptObjectProxyObject *self, + PyObject *value) +{ + if (!self->wrapped) { + PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); + return -1; + } + + if (PyObject_SetAttrString(self->wrapped, "__doc__", value) == -1) + return -1; + + return PyDict_SetItemString(self->dict, "__doc__", value); +} + +/* ------------------------------------------------------------------------- */ + +static PyObject *WraptObjectProxy_get_class( + WraptObjectProxyObject *self) +{ + if (!self->wrapped) { + PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); + return NULL; + } + + return PyObject_GetAttrString(self->wrapped, "__class__"); +} + +/* ------------------------------------------------------------------------- */ + +static PyObject *WraptObjectProxy_get_annotations( + WraptObjectProxyObject *self) +{ + if (!self->wrapped) { + PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); + return NULL; + } + + return PyObject_GetAttrString(self->wrapped, "__annotations__"); +} + +/* ------------------------------------------------------------------------- */ + +static int WraptObjectProxy_set_annotations(WraptObjectProxyObject *self, + PyObject *value) +{ + if (!self->wrapped) { + PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); + return -1; + } + + return PyObject_SetAttrString(self->wrapped, "__annotations__", value); +} + +/* ------------------------------------------------------------------------- */ + +static PyObject *WraptObjectProxy_get_wrapped( + WraptObjectProxyObject *self) +{ + if (!self->wrapped) { + PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); + return NULL; + } + + Py_INCREF(self->wrapped); + return self->wrapped; +} + +/* ------------------------------------------------------------------------- */ + +static int WraptObjectProxy_set_wrapped(WraptObjectProxyObject *self, + PyObject *value) +{ + if (!value) { + PyErr_SetString(PyExc_TypeError, "__wrapped__ must be an object"); + return -1; + } + + Py_INCREF(value); + Py_XDECREF(self->wrapped); + + self->wrapped = value; + + return 0; +} + +/* ------------------------------------------------------------------------- */ + +static PyObject *WraptObjectProxy_getattro( + WraptObjectProxyObject *self, PyObject *name) +{ + PyObject *object = NULL; + PyObject *result = NULL; + + static PyObject *getattr_str = NULL; + + object = PyObject_GenericGetAttr((PyObject *)self, name); + + if (object) + return object; + + PyErr_Clear(); + + if (!getattr_str) { +#if PY_MAJOR_VERSION >= 3 + getattr_str = PyUnicode_InternFromString("__getattr__"); +#else + getattr_str = PyString_InternFromString("__getattr__"); +#endif + } + + object = PyObject_GenericGetAttr((PyObject *)self, getattr_str); + + if (!object) + return NULL; + + result = PyObject_CallFunctionObjArgs(object, name, NULL); + + Py_DECREF(object); + + return result; +} + +/* ------------------------------------------------------------------------- */ + +static PyObject *WraptObjectProxy_getattr( + WraptObjectProxyObject *self, PyObject *args) +{ + PyObject *name = NULL; + +#if PY_MAJOR_VERSION >= 3 + if (!PyArg_ParseTuple(args, "U:__getattr__", &name)) + return NULL; +#else + if (!PyArg_ParseTuple(args, "S:__getattr__", &name)) + return NULL; +#endif + + if (!self->wrapped) { + PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); + return NULL; + } + + return PyObject_GetAttr(self->wrapped, name); +} + +/* ------------------------------------------------------------------------- */ + +static int WraptObjectProxy_setattro( + WraptObjectProxyObject *self, PyObject *name, PyObject *value) +{ + static PyObject *self_str = NULL; + static PyObject *wrapped_str = NULL; + static PyObject *startswith_str = NULL; + + PyObject *match = NULL; + + if (!startswith_str) { +#if PY_MAJOR_VERSION >= 3 + startswith_str = PyUnicode_InternFromString("startswith"); +#else + startswith_str = PyString_InternFromString("startswith"); +#endif + } + + if (!self_str) { +#if PY_MAJOR_VERSION >= 3 + self_str = PyUnicode_InternFromString("_self_"); +#else + self_str = PyString_InternFromString("_self_"); +#endif + } + + match = PyObject_CallMethodObjArgs(name, startswith_str, self_str, NULL); + + if (match == Py_True) { + Py_DECREF(match); + + return PyObject_GenericSetAttr((PyObject *)self, name, value); + } + else if (!match) + PyErr_Clear(); + + Py_XDECREF(match); + + if (!wrapped_str) { +#if PY_MAJOR_VERSION >= 3 + wrapped_str = PyUnicode_InternFromString("__wrapped__"); +#else + wrapped_str = PyString_InternFromString("__wrapped__"); +#endif + } + + if (PyObject_HasAttr((PyObject *)Py_TYPE(self), name)) + return PyObject_GenericSetAttr((PyObject *)self, name, value); + + if (!self->wrapped) { + PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); + return -1; + } + + return PyObject_SetAttr(self->wrapped, name, value); +} + +/* ------------------------------------------------------------------------- */ + +static PyObject *WraptObjectProxy_richcompare(WraptObjectProxyObject *self, + PyObject *other, int opcode) +{ + if (!self->wrapped) { + PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); + return NULL; + } + + return PyObject_RichCompare(self->wrapped, other, opcode); +} + +/* ------------------------------------------------------------------------- */ + +static PyObject *WraptObjectProxy_iter(WraptObjectProxyObject *self) +{ + if (!self->wrapped) { + PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); + return NULL; + } + + return PyObject_GetIter(self->wrapped); +} + +/* ------------------------------------------------------------------------- */ + +static PyNumberMethods WraptObjectProxy_as_number = { + (binaryfunc)WraptObjectProxy_add, /*nb_add*/ + (binaryfunc)WraptObjectProxy_subtract, /*nb_subtract*/ + (binaryfunc)WraptObjectProxy_multiply, /*nb_multiply*/ +#if PY_MAJOR_VERSION < 3 + (binaryfunc)WraptObjectProxy_divide, /*nb_divide*/ +#endif + (binaryfunc)WraptObjectProxy_remainder, /*nb_remainder*/ + (binaryfunc)WraptObjectProxy_divmod, /*nb_divmod*/ + (ternaryfunc)WraptObjectProxy_power, /*nb_power*/ + (unaryfunc)WraptObjectProxy_negative, /*nb_negative*/ + (unaryfunc)WraptObjectProxy_positive, /*nb_positive*/ + (unaryfunc)WraptObjectProxy_absolute, /*nb_absolute*/ + (inquiry)WraptObjectProxy_bool, /*nb_nonzero/nb_bool*/ + (unaryfunc)WraptObjectProxy_invert, /*nb_invert*/ + (binaryfunc)WraptObjectProxy_lshift, /*nb_lshift*/ + (binaryfunc)WraptObjectProxy_rshift, /*nb_rshift*/ + (binaryfunc)WraptObjectProxy_and, /*nb_and*/ + (binaryfunc)WraptObjectProxy_xor, /*nb_xor*/ + (binaryfunc)WraptObjectProxy_or, /*nb_or*/ +#if PY_MAJOR_VERSION < 3 + 0, /*nb_coerce*/ +#endif +#if PY_MAJOR_VERSION < 3 + (unaryfunc)WraptObjectProxy_int, /*nb_int*/ + (unaryfunc)WraptObjectProxy_long, /*nb_long*/ +#else + (unaryfunc)WraptObjectProxy_long, /*nb_int*/ + 0, /*nb_long/nb_reserved*/ +#endif + (unaryfunc)WraptObjectProxy_float, /*nb_float*/ +#if PY_MAJOR_VERSION < 3 + (unaryfunc)WraptObjectProxy_oct, /*nb_oct*/ + (unaryfunc)WraptObjectProxy_hex, /*nb_hex*/ +#endif + (binaryfunc)WraptObjectProxy_inplace_add, /*nb_inplace_add*/ + (binaryfunc)WraptObjectProxy_inplace_subtract, /*nb_inplace_subtract*/ + (binaryfunc)WraptObjectProxy_inplace_multiply, /*nb_inplace_multiply*/ +#if PY_MAJOR_VERSION < 3 + (binaryfunc)WraptObjectProxy_inplace_divide, /*nb_inplace_divide*/ +#endif + (binaryfunc)WraptObjectProxy_inplace_remainder, /*nb_inplace_remainder*/ + (ternaryfunc)WraptObjectProxy_inplace_power, /*nb_inplace_power*/ + (binaryfunc)WraptObjectProxy_inplace_lshift, /*nb_inplace_lshift*/ + (binaryfunc)WraptObjectProxy_inplace_rshift, /*nb_inplace_rshift*/ + (binaryfunc)WraptObjectProxy_inplace_and, /*nb_inplace_and*/ + (binaryfunc)WraptObjectProxy_inplace_xor, /*nb_inplace_xor*/ + (binaryfunc)WraptObjectProxy_inplace_or, /*nb_inplace_or*/ + (binaryfunc)WraptObjectProxy_floor_divide, /*nb_floor_divide*/ + (binaryfunc)WraptObjectProxy_true_divide, /*nb_true_divide*/ + (binaryfunc)WraptObjectProxy_inplace_floor_divide, /*nb_inplace_floor_divide*/ + (binaryfunc)WraptObjectProxy_inplace_true_divide, /*nb_inplace_true_divide*/ + (unaryfunc)WraptObjectProxy_index, /*nb_index*/ +}; + +static PySequenceMethods WraptObjectProxy_as_sequence = { + (lenfunc)WraptObjectProxy_length, /*sq_length*/ + 0, /*sq_concat*/ + 0, /*sq_repeat*/ + 0, /*sq_item*/ + 0, /*sq_slice*/ + 0, /*sq_ass_item*/ + 0, /*sq_ass_slice*/ + (objobjproc)WraptObjectProxy_contains, /* sq_contains */ +}; + +static PyMappingMethods WraptObjectProxy_as_mapping = { + (lenfunc)WraptObjectProxy_length, /*mp_length*/ + (binaryfunc)WraptObjectProxy_getitem, /*mp_subscript*/ + (objobjargproc)WraptObjectProxy_setitem, /*mp_ass_subscript*/ +}; + +static PyMethodDef WraptObjectProxy_methods[] = { + { "__dir__", (PyCFunction)WraptObjectProxy_dir, METH_NOARGS, 0 }, + { "__enter__", (PyCFunction)WraptObjectProxy_enter, + METH_VARARGS | METH_KEYWORDS, 0 }, + { "__exit__", (PyCFunction)WraptObjectProxy_exit, + METH_VARARGS | METH_KEYWORDS, 0 }, + { "__getattr__", (PyCFunction)WraptObjectProxy_getattr, + METH_VARARGS , 0 }, + { "__bytes__", (PyCFunction)WraptObjectProxy_bytes, METH_NOARGS, 0 }, + { "__reversed__", (PyCFunction)WraptObjectProxy_reversed, METH_NOARGS, 0 }, +#if PY_MAJOR_VERSION >= 3 + { "__round__", (PyCFunction)WraptObjectProxy_round, METH_NOARGS, 0 }, +#endif + { NULL, NULL }, +}; + +static PyGetSetDef WraptObjectProxy_getset[] = { + { "__name__", (getter)WraptObjectProxy_get_name, + (setter)WraptObjectProxy_set_name, 0 }, + { "__qualname__", (getter)WraptObjectProxy_get_qualname, + (setter)WraptObjectProxy_set_qualname, 0 }, + { "__module__", (getter)WraptObjectProxy_get_module, + (setter)WraptObjectProxy_set_module, 0 }, + { "__doc__", (getter)WraptObjectProxy_get_doc, + (setter)WraptObjectProxy_set_doc, 0 }, + { "__class__", (getter)WraptObjectProxy_get_class, + NULL, 0 }, + { "__annotations__", (getter)WraptObjectProxy_get_annotations, + (setter)WraptObjectProxy_set_annotations, 0 }, + { "__wrapped__", (getter)WraptObjectProxy_get_wrapped, + (setter)WraptObjectProxy_set_wrapped, 0 }, + { NULL }, +}; + +PyTypeObject WraptObjectProxy_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "ObjectProxy", /*tp_name*/ + sizeof(WraptObjectProxyObject), /*tp_basicsize*/ + 0, /*tp_itemsize*/ + /* methods */ + (destructor)WraptObjectProxy_dealloc, /*tp_dealloc*/ + 0, /*tp_print*/ + 0, /*tp_getattr*/ + 0, /*tp_setattr*/ + 0, /*tp_compare*/ + (unaryfunc)WraptObjectProxy_repr, /*tp_repr*/ + &WraptObjectProxy_as_number, /*tp_as_number*/ + &WraptObjectProxy_as_sequence, /*tp_as_sequence*/ + &WraptObjectProxy_as_mapping, /*tp_as_mapping*/ + (hashfunc)WraptObjectProxy_hash, /*tp_hash*/ + 0, /*tp_call*/ + (unaryfunc)WraptObjectProxy_str, /*tp_str*/ + (getattrofunc)WraptObjectProxy_getattro, /*tp_getattro*/ + (setattrofunc)WraptObjectProxy_setattro, /*tp_setattro*/ + 0, /*tp_as_buffer*/ +#if PY_MAJOR_VERSION < 3 + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | + Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ +#else + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | + Py_TPFLAGS_HAVE_GC, /*tp_flags*/ +#endif + 0, /*tp_doc*/ + (traverseproc)WraptObjectProxy_traverse, /*tp_traverse*/ + (inquiry)WraptObjectProxy_clear, /*tp_clear*/ + (richcmpfunc)WraptObjectProxy_richcompare, /*tp_richcompare*/ + offsetof(WraptObjectProxyObject, weakreflist), /*tp_weaklistoffset*/ + (getiterfunc)WraptObjectProxy_iter, /*tp_iter*/ + 0, /*tp_iternext*/ + WraptObjectProxy_methods, /*tp_methods*/ + 0, /*tp_members*/ + WraptObjectProxy_getset, /*tp_getset*/ + 0, /*tp_base*/ + 0, /*tp_dict*/ + 0, /*tp_descr_get*/ + 0, /*tp_descr_set*/ + offsetof(WraptObjectProxyObject, dict), /*tp_dictoffset*/ + (initproc)WraptObjectProxy_init, /*tp_init*/ + PyType_GenericAlloc, /*tp_alloc*/ + WraptObjectProxy_new, /*tp_new*/ + PyObject_GC_Del, /*tp_free*/ + 0, /*tp_is_gc*/ +}; + +/* ------------------------------------------------------------------------- */ + +static PyObject *WraptCallableObjectProxy_call( + WraptObjectProxyObject *self, PyObject *args, PyObject *kwds) +{ + if (!self->wrapped) { + PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized"); + return NULL; + } + + return PyObject_Call(self->wrapped, args, kwds); +} + +/* ------------------------------------------------------------------------- */; + +static PyGetSetDef WraptCallableObjectProxy_getset[] = { + { "__module__", (getter)WraptObjectProxy_get_module, + (setter)WraptObjectProxy_set_module, 0 }, + { "__doc__", (getter)WraptObjectProxy_get_doc, + (setter)WraptObjectProxy_set_doc, 0 }, + { NULL }, +}; + +PyTypeObject WraptCallableObjectProxy_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "CallableObjectProxy", /*tp_name*/ + sizeof(WraptObjectProxyObject), /*tp_basicsize*/ + 0, /*tp_itemsize*/ + /* methods */ + 0, /*tp_dealloc*/ + 0, /*tp_print*/ + 0, /*tp_getattr*/ + 0, /*tp_setattr*/ + 0, /*tp_compare*/ + 0, /*tp_repr*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ + 0, /*tp_hash*/ + (ternaryfunc)WraptCallableObjectProxy_call, /*tp_call*/ + 0, /*tp_str*/ + 0, /*tp_getattro*/ + 0, /*tp_setattro*/ + 0, /*tp_as_buffer*/ +#if PY_MAJOR_VERSION < 3 + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ +#else + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ +#endif + 0, /*tp_doc*/ + 0, /*tp_traverse*/ + 0, /*tp_clear*/ + 0, /*tp_richcompare*/ + offsetof(WraptObjectProxyObject, weakreflist), /*tp_weaklistoffset*/ + 0, /*tp_iter*/ + 0, /*tp_iternext*/ + 0, /*tp_methods*/ + 0, /*tp_members*/ + WraptCallableObjectProxy_getset, /*tp_getset*/ + 0, /*tp_base*/ + 0, /*tp_dict*/ + 0, /*tp_descr_get*/ + 0, /*tp_descr_set*/ + 0, /*tp_dictoffset*/ + (initproc)WraptObjectProxy_init, /*tp_init*/ + 0, /*tp_alloc*/ + 0, /*tp_new*/ + 0, /*tp_free*/ + 0, /*tp_is_gc*/ +}; + +/* ------------------------------------------------------------------------- */ + +static PyObject *WraptFunctionWrapperBase_new(PyTypeObject *type, + PyObject *args, PyObject *kwds) +{ + WraptFunctionWrapperObject *self; + + self = (WraptFunctionWrapperObject *)WraptObjectProxy_new(type, + args, kwds); + + if (!self) + return NULL; + + self->instance = NULL; + self->wrapper = NULL; + self->enabled = NULL; + self->binding = NULL; + self->parent = NULL; + + return (PyObject *)self; +} + +/* ------------------------------------------------------------------------- */ + +static int WraptFunctionWrapperBase_raw_init(WraptFunctionWrapperObject *self, + PyObject *wrapped, PyObject *instance, PyObject *wrapper, + PyObject *enabled, PyObject *binding, PyObject *parent) +{ + int result = 0; + + result = WraptObjectProxy_raw_init((WraptObjectProxyObject *)self, + wrapped); + + if (result == 0) { + Py_INCREF(instance); + Py_XDECREF(self->instance); + self->instance = instance; + + Py_INCREF(wrapper); + Py_XDECREF(self->wrapper); + self->wrapper = wrapper; + + Py_INCREF(enabled); + Py_XDECREF(self->enabled); + self->enabled = enabled; + + Py_INCREF(binding); + Py_XDECREF(self->binding); + self->binding = binding; + + Py_INCREF(parent); + Py_XDECREF(self->parent); + self->parent = parent; + } + + return result; +} + +/* ------------------------------------------------------------------------- */ + +static int WraptFunctionWrapperBase_init(WraptFunctionWrapperObject *self, + PyObject *args, PyObject *kwds) +{ + PyObject *wrapped = NULL; + PyObject *instance = NULL; + PyObject *wrapper = NULL; + PyObject *enabled = Py_None; + PyObject *binding = NULL; + PyObject *parent = Py_None; + + static PyObject *function_str = NULL; + + static char *kwlist[] = { "wrapped", "instance", "wrapper", + "enabled", "binding", "parent", NULL }; + + if (!function_str) { +#if PY_MAJOR_VERSION >= 3 + function_str = PyUnicode_InternFromString("function"); +#else + function_str = PyString_InternFromString("function"); +#endif + } + + if (!PyArg_ParseTupleAndKeywords(args, kwds, + "OOO|OOO:FunctionWrapperBase", kwlist, &wrapped, &instance, + &wrapper, &enabled, &binding, &parent)) { + return -1; + } + + if (!binding) + binding = function_str; + + return WraptFunctionWrapperBase_raw_init(self, wrapped, instance, wrapper, + enabled, binding, parent); +} + +/* ------------------------------------------------------------------------- */ + +static int WraptFunctionWrapperBase_traverse(WraptFunctionWrapperObject *self, + visitproc visit, void *arg) +{ + WraptObjectProxy_traverse((WraptObjectProxyObject *)self, visit, arg); + + Py_VISIT(self->instance); + Py_VISIT(self->wrapper); + Py_VISIT(self->enabled); + Py_VISIT(self->binding); + Py_VISIT(self->parent); + + return 0; +} + +/* ------------------------------------------------------------------------- */ + +static int WraptFunctionWrapperBase_clear(WraptFunctionWrapperObject *self) +{ + WraptObjectProxy_clear((WraptObjectProxyObject *)self); + + Py_CLEAR(self->instance); + Py_CLEAR(self->wrapper); + Py_CLEAR(self->enabled); + Py_CLEAR(self->binding); + Py_CLEAR(self->parent); + + return 0; +} + +/* ------------------------------------------------------------------------- */ + +static void WraptFunctionWrapperBase_dealloc(WraptFunctionWrapperObject *self) +{ + WraptFunctionWrapperBase_clear(self); + + WraptObjectProxy_dealloc((WraptObjectProxyObject *)self); +} + +/* ------------------------------------------------------------------------- */ + +static PyObject *WraptFunctionWrapperBase_call( + WraptFunctionWrapperObject *self, PyObject *args, PyObject *kwds) +{ + PyObject *param_kwds = NULL; + + PyObject *result = NULL; + + static PyObject *function_str = NULL; + + if (!function_str) { +#if PY_MAJOR_VERSION >= 3 + function_str = PyUnicode_InternFromString("function"); +#else + function_str = PyString_InternFromString("function"); +#endif + } + + if (self->enabled != Py_None) { + if (PyCallable_Check(self->enabled)) { + PyObject *object = NULL; + + object = PyObject_CallFunctionObjArgs(self->enabled, NULL); + + if (!object) + return NULL; + + if (PyObject_Not(object)) { + Py_DECREF(object); + return PyObject_Call(self->object_proxy.wrapped, args, kwds); + } + + Py_DECREF(object); + } + else if (PyObject_Not(self->enabled)) { + return PyObject_Call(self->object_proxy.wrapped, args, kwds); + } + } + + if (!kwds) { + param_kwds = PyDict_New(); + kwds = param_kwds; + } + + if (self->instance == Py_None && (self->binding == function_str || + PyObject_RichCompareBool(self->binding, function_str, + Py_EQ) == 1)) { + + PyObject *instance = NULL; + + instance = PyObject_GetAttrString(self->object_proxy.wrapped, + "__self__"); + + if (instance) { + result = PyObject_CallFunctionObjArgs(self->wrapper, + self->object_proxy.wrapped, instance, args, kwds, NULL); + + Py_XDECREF(param_kwds); + + Py_DECREF(instance); + + return result; + } + else + PyErr_Clear(); + } + + result = PyObject_CallFunctionObjArgs(self->wrapper, + self->object_proxy.wrapped, self->instance, args, kwds, NULL); + + Py_XDECREF(param_kwds); + + return result; +} + +/* ------------------------------------------------------------------------- */ + +static PyObject *WraptFunctionWrapperBase_descr_get( + WraptFunctionWrapperObject *self, PyObject *obj, PyObject *type) +{ + PyObject *bound_type = NULL; + PyObject *descriptor = NULL; + PyObject *result = NULL; + + static PyObject *bound_type_str = NULL; + static PyObject *function_str = NULL; + + if (!bound_type_str) { +#if PY_MAJOR_VERSION >= 3 + bound_type_str = PyUnicode_InternFromString( + "__bound_function_wrapper__"); +#else + bound_type_str = PyString_InternFromString( + "__bound_function_wrapper__"); +#endif + } + + if (!function_str) { +#if PY_MAJOR_VERSION >= 3 + function_str = PyUnicode_InternFromString("function"); +#else + function_str = PyString_InternFromString("function"); +#endif + } + + if (self->parent == Py_None) { +#if PY_MAJOR_VERSION < 3 + if (PyObject_IsInstance(self->object_proxy.wrapped, + (PyObject *)&PyClass_Type) || PyObject_IsInstance( + self->object_proxy.wrapped, (PyObject *)&PyType_Type)) { + Py_INCREF(self); + return (PyObject *)self; + } +#else + if (PyObject_IsInstance(self->object_proxy.wrapped, + (PyObject *)&PyType_Type)) { + Py_INCREF(self); + return (PyObject *)self; + } +#endif + + if (Py_TYPE(self->object_proxy.wrapped)->tp_descr_get == NULL) { + PyErr_Format(PyExc_AttributeError, + "'%s' object has no attribute '__get__'", + Py_TYPE(self->object_proxy.wrapped)->tp_name); + return NULL; + } + + descriptor = (Py_TYPE(self->object_proxy.wrapped)->tp_descr_get)( + self->object_proxy.wrapped, obj, type); + + if (!descriptor) + return NULL; + + if (Py_TYPE(self) != &WraptFunctionWrapper_Type) { + bound_type = PyObject_GenericGetAttr((PyObject *)self, + bound_type_str); + + if (!bound_type) + PyErr_Clear(); + } + + if (obj == NULL) + obj = Py_None; + + result = PyObject_CallFunctionObjArgs(bound_type ? bound_type : + (PyObject *)&WraptBoundFunctionWrapper_Type, descriptor, + obj, self->wrapper, self->enabled, self->binding, + self, NULL); + + Py_XDECREF(bound_type); + Py_DECREF(descriptor); + + return result; + } + + if (self->instance == Py_None && (self->binding == function_str || + PyObject_RichCompareBool(self->binding, function_str, + Py_EQ) == 1)) { + + PyObject *wrapped = NULL; + + static PyObject *wrapped_str = NULL; + + if (!wrapped_str) { +#if PY_MAJOR_VERSION >= 3 + wrapped_str = PyUnicode_InternFromString("__wrapped__"); +#else + wrapped_str = PyString_InternFromString("__wrapped__"); +#endif + } + + wrapped = PyObject_GetAttr(self->parent, wrapped_str); + + if (!wrapped) + return NULL; + + if (Py_TYPE(wrapped)->tp_descr_get == NULL) { + PyErr_Format(PyExc_AttributeError, + "'%s' object has no attribute '__get__'", + Py_TYPE(wrapped)->tp_name); + Py_DECREF(wrapped); + return NULL; + } + + descriptor = (Py_TYPE(wrapped)->tp_descr_get)(wrapped, obj, type); + + Py_DECREF(wrapped); + + if (!descriptor) + return NULL; + + if (Py_TYPE(self->parent) != &WraptFunctionWrapper_Type) { + bound_type = PyObject_GenericGetAttr((PyObject *)self->parent, + bound_type_str); + + if (!bound_type) + PyErr_Clear(); + } + + if (obj == NULL) + obj = Py_None; + + result = PyObject_CallFunctionObjArgs(bound_type ? bound_type : + (PyObject *)&WraptBoundFunctionWrapper_Type, descriptor, + obj, self->wrapper, self->enabled, self->binding, + self->parent, NULL); + + Py_XDECREF(bound_type); + Py_DECREF(descriptor); + + return result; + } + + Py_INCREF(self); + return (PyObject *)self; +} + +/* ------------------------------------------------------------------------- */ + +static PyObject *WraptFunctionWrapperBase_get_self_instance( + WraptFunctionWrapperObject *self, void *closure) +{ + if (!self->instance) { + Py_INCREF(Py_None); + return Py_None; + } + + Py_INCREF(self->instance); + return self->instance; +} + +/* ------------------------------------------------------------------------- */ + +static PyObject *WraptFunctionWrapperBase_get_self_wrapper( + WraptFunctionWrapperObject *self, void *closure) +{ + if (!self->wrapper) { + Py_INCREF(Py_None); + return Py_None; + } + + Py_INCREF(self->wrapper); + return self->wrapper; +} + +/* ------------------------------------------------------------------------- */ + +static PyObject *WraptFunctionWrapperBase_get_self_enabled( + WraptFunctionWrapperObject *self, void *closure) +{ + if (!self->enabled) { + Py_INCREF(Py_None); + return Py_None; + } + + Py_INCREF(self->enabled); + return self->enabled; +} + +/* ------------------------------------------------------------------------- */ + +static PyObject *WraptFunctionWrapperBase_get_self_binding( + WraptFunctionWrapperObject *self, void *closure) +{ + if (!self->binding) { + Py_INCREF(Py_None); + return Py_None; + } + + Py_INCREF(self->binding); + return self->binding; +} + +/* ------------------------------------------------------------------------- */ + +static PyObject *WraptFunctionWrapperBase_get_self_parent( + WraptFunctionWrapperObject *self, void *closure) +{ + if (!self->parent) { + Py_INCREF(Py_None); + return Py_None; + } + + Py_INCREF(self->parent); + return self->parent; +} + +/* ------------------------------------------------------------------------- */; + +static PyGetSetDef WraptFunctionWrapperBase_getset[] = { + { "__module__", (getter)WraptObjectProxy_get_module, + (setter)WraptObjectProxy_set_module, 0 }, + { "__doc__", (getter)WraptObjectProxy_get_doc, + (setter)WraptObjectProxy_set_doc, 0 }, + { "_self_instance", (getter)WraptFunctionWrapperBase_get_self_instance, + NULL, 0 }, + { "_self_wrapper", (getter)WraptFunctionWrapperBase_get_self_wrapper, + NULL, 0 }, + { "_self_enabled", (getter)WraptFunctionWrapperBase_get_self_enabled, + NULL, 0 }, + { "_self_binding", (getter)WraptFunctionWrapperBase_get_self_binding, + NULL, 0 }, + { "_self_parent", (getter)WraptFunctionWrapperBase_get_self_parent, + NULL, 0 }, + { NULL }, +}; + +PyTypeObject WraptFunctionWrapperBase_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "_FunctionWrapperBase", /*tp_name*/ + sizeof(WraptFunctionWrapperObject), /*tp_basicsize*/ + 0, /*tp_itemsize*/ + /* methods */ + (destructor)WraptFunctionWrapperBase_dealloc, /*tp_dealloc*/ + 0, /*tp_print*/ + 0, /*tp_getattr*/ + 0, /*tp_setattr*/ + 0, /*tp_compare*/ + 0, /*tp_repr*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ + 0, /*tp_hash*/ + (ternaryfunc)WraptFunctionWrapperBase_call, /*tp_call*/ + 0, /*tp_str*/ + 0, /*tp_getattro*/ + 0, /*tp_setattro*/ + 0, /*tp_as_buffer*/ +#if PY_MAJOR_VERSION < 3 + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | + Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ +#else + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | + Py_TPFLAGS_HAVE_GC, /*tp_flags*/ +#endif + 0, /*tp_doc*/ + (traverseproc)WraptFunctionWrapperBase_traverse, /*tp_traverse*/ + (inquiry)WraptFunctionWrapperBase_clear, /*tp_clear*/ + 0, /*tp_richcompare*/ + offsetof(WraptObjectProxyObject, weakreflist), /*tp_weaklistoffset*/ + 0, /*tp_iter*/ + 0, /*tp_iternext*/ + 0, /*tp_methods*/ + 0, /*tp_members*/ + WraptFunctionWrapperBase_getset, /*tp_getset*/ + 0, /*tp_base*/ + 0, /*tp_dict*/ + (descrgetfunc)WraptFunctionWrapperBase_descr_get, /*tp_descr_get*/ + 0, /*tp_descr_set*/ + 0, /*tp_dictoffset*/ + (initproc)WraptFunctionWrapperBase_init, /*tp_init*/ + 0, /*tp_alloc*/ + WraptFunctionWrapperBase_new, /*tp_new*/ + 0, /*tp_free*/ + 0, /*tp_is_gc*/ +}; + +/* ------------------------------------------------------------------------- */ + +static PyObject *WraptBoundFunctionWrapper_call( + WraptFunctionWrapperObject *self, PyObject *args, PyObject *kwds) +{ + PyObject *param_args = NULL; + PyObject *param_kwds = NULL; + + PyObject *wrapped = NULL; + PyObject *instance = NULL; + + PyObject *result = NULL; + + static PyObject *function_str = NULL; + + if (self->enabled != Py_None) { + if (PyCallable_Check(self->enabled)) { + PyObject *object = NULL; + + object = PyObject_CallFunctionObjArgs(self->enabled, NULL); + + if (!object) + return NULL; + + if (PyObject_Not(object)) { + Py_DECREF(object); + return PyObject_Call(self->object_proxy.wrapped, args, kwds); + } + + Py_DECREF(object); + } + else if (PyObject_Not(self->enabled)) { + return PyObject_Call(self->object_proxy.wrapped, args, kwds); + } + } + + if (!function_str) { +#if PY_MAJOR_VERSION >= 3 + function_str = PyUnicode_InternFromString("function"); +#else + function_str = PyString_InternFromString("function"); +#endif + } + + /* + * We need to do things different depending on whether we are likely + * wrapping an instance method vs a static method or class method. + */ + + if (self->binding == function_str || PyObject_RichCompareBool( + self->binding, function_str, Py_EQ) == 1) { + + if (self->instance == Py_None) { + /* + * This situation can occur where someone is calling the + * instancemethod via the class type and passing the + * instance as the first argument. We need to shift the args + * before making the call to the wrapper and effectively + * bind the instance to the wrapped function using a partial + * so the wrapper doesn't see anything as being different. + */ + + PyObject *module = NULL; + PyObject *dict = NULL; + PyObject *partial = NULL; + + if (PyTuple_Size(args) == 0) { + PyErr_SetString(PyExc_TypeError, + "missing 1 required positional argument"); + return NULL; + } + + module = PyImport_ImportModule("functools"); + + if (!module) + return NULL; + + dict = PyModule_GetDict(module); + partial = PyDict_GetItemString(dict, "partial"); + + if (!partial) { + Py_DECREF(module); + return NULL; + } + + Py_INCREF(partial); + Py_DECREF(module); + + instance = PyTuple_GetItem(args, 0); + + if (!instance) { + Py_DECREF(partial); + return NULL; + } + + wrapped = PyObject_CallFunctionObjArgs(partial, + self->object_proxy.wrapped, instance, NULL); + + Py_DECREF(partial); + + if (!wrapped) + return NULL; + + param_args = PyTuple_GetSlice(args, 1, PyTuple_Size(args)); + + if (!param_args) { + Py_DECREF(wrapped); + return NULL; + } + + args = param_args; + } + else + instance = self->instance; + + if (!wrapped) { + Py_INCREF(self->object_proxy.wrapped); + wrapped = self->object_proxy.wrapped; + } + + if (!kwds) { + param_kwds = PyDict_New(); + kwds = param_kwds; + } + + result = PyObject_CallFunctionObjArgs(self->wrapper, wrapped, + instance, args, kwds, NULL); + + Py_XDECREF(param_args); + Py_XDECREF(param_kwds); + Py_DECREF(wrapped); + + return result; + } + else { + /* + * As in this case we would be dealing with a classmethod or + * staticmethod, then _self_instance will only tell us whether + * when calling the classmethod or staticmethod they did it via + * an instance of the class it is bound to and not the case + * where done by the class type itself. We thus ignore + * _self_instance and use the __self__ attribute of the bound + * function instead. For a classmethod, this means instance will + * be the class type and for a staticmethod it will be None. + * This is probably the more useful thing we can pass through + * even though we loose knowledge of whether they were called on + * the instance vs the class type, as it reflects what they have + * available in the decoratored function. + */ + + instance = PyObject_GetAttrString(self->object_proxy.wrapped, + "__self__"); + + if (!instance) { + PyErr_Clear(); + Py_INCREF(Py_None); + instance = Py_None; + } + + if (!kwds) { + param_kwds = PyDict_New(); + kwds = param_kwds; + } + + result = PyObject_CallFunctionObjArgs(self->wrapper, + self->object_proxy.wrapped, instance, args, kwds, NULL); + + Py_XDECREF(param_kwds); + + Py_DECREF(instance); + + return result; + } +} + +/* ------------------------------------------------------------------------- */ + +static PyGetSetDef WraptBoundFunctionWrapper_getset[] = { + { "__module__", (getter)WraptObjectProxy_get_module, + (setter)WraptObjectProxy_set_module, 0 }, + { "__doc__", (getter)WraptObjectProxy_get_doc, + (setter)WraptObjectProxy_set_doc, 0 }, + { NULL }, +}; + +PyTypeObject WraptBoundFunctionWrapper_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "BoundFunctionWrapper", /*tp_name*/ + sizeof(WraptFunctionWrapperObject), /*tp_basicsize*/ + 0, /*tp_itemsize*/ + /* methods */ + 0, /*tp_dealloc*/ + 0, /*tp_print*/ + 0, /*tp_getattr*/ + 0, /*tp_setattr*/ + 0, /*tp_compare*/ + 0, /*tp_repr*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ + 0, /*tp_hash*/ + (ternaryfunc)WraptBoundFunctionWrapper_call, /*tp_call*/ + 0, /*tp_str*/ + 0, /*tp_getattro*/ + 0, /*tp_setattro*/ + 0, /*tp_as_buffer*/ +#if PY_MAJOR_VERSION < 3 + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ +#else + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ +#endif + 0, /*tp_doc*/ + 0, /*tp_traverse*/ + 0, /*tp_clear*/ + 0, /*tp_richcompare*/ + offsetof(WraptObjectProxyObject, weakreflist), /*tp_weaklistoffset*/ + 0, /*tp_iter*/ + 0, /*tp_iternext*/ + 0, /*tp_methods*/ + 0, /*tp_members*/ + WraptBoundFunctionWrapper_getset, /*tp_getset*/ + 0, /*tp_base*/ + 0, /*tp_dict*/ + 0, /*tp_descr_get*/ + 0, /*tp_descr_set*/ + 0, /*tp_dictoffset*/ + 0, /*tp_init*/ + 0, /*tp_alloc*/ + 0, /*tp_new*/ + 0, /*tp_free*/ + 0, /*tp_is_gc*/ +}; + +/* ------------------------------------------------------------------------- */ + +static int WraptFunctionWrapper_init(WraptFunctionWrapperObject *self, + PyObject *args, PyObject *kwds) +{ + PyObject *wrapped = NULL; + PyObject *wrapper = NULL; + PyObject *enabled = Py_None; + PyObject *binding = NULL; + PyObject *instance = NULL; + + static PyObject *classmethod_str = NULL; + static PyObject *staticmethod_str = NULL; + static PyObject *function_str = NULL; + + int result = 0; + + static char *kwlist[] = { "wrapped", "wrapper", "enabled", NULL }; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "OO|O:FunctionWrapper", + kwlist, &wrapped, &wrapper, &enabled)) { + return -1; + } + + if (!classmethod_str) { +#if PY_MAJOR_VERSION >= 3 + classmethod_str = PyUnicode_InternFromString("classmethod"); +#else + classmethod_str = PyString_InternFromString("classmethod"); +#endif + } + + if (!staticmethod_str) { +#if PY_MAJOR_VERSION >= 3 + staticmethod_str = PyUnicode_InternFromString("staticmethod"); +#else + staticmethod_str = PyString_InternFromString("staticmethod"); +#endif + } + + if (!function_str) { +#if PY_MAJOR_VERSION >= 3 + function_str = PyUnicode_InternFromString("function"); +#else + function_str = PyString_InternFromString("function"); +#endif + } + + if (PyObject_IsInstance(wrapped, (PyObject *)&PyClassMethod_Type)) { + binding = classmethod_str; + } + else if (PyObject_IsInstance(wrapped, (PyObject *)&PyStaticMethod_Type)) { + binding = staticmethod_str; + } + else if ((instance = PyObject_GetAttrString(wrapped, "__self__")) != 0) { +#if PY_MAJOR_VERSION < 3 + if (PyObject_IsInstance(instance, (PyObject *)&PyClass_Type) || + PyObject_IsInstance(instance, (PyObject *)&PyType_Type)) { + binding = classmethod_str; + } +#else + if (PyObject_IsInstance(instance, (PyObject *)&PyType_Type)) { + binding = classmethod_str; + } +#endif + else + binding = function_str; + + Py_DECREF(instance); + } + else { + PyErr_Clear(); + + binding = function_str; + } + + result = WraptFunctionWrapperBase_raw_init(self, wrapped, Py_None, + wrapper, enabled, binding, Py_None); + + return result; +} + +/* ------------------------------------------------------------------------- */; + +static PyGetSetDef WraptFunctionWrapper_getset[] = { + { "__module__", (getter)WraptObjectProxy_get_module, + (setter)WraptObjectProxy_set_module, 0 }, + { "__doc__", (getter)WraptObjectProxy_get_doc, + (setter)WraptObjectProxy_set_doc, 0 }, + { NULL }, +}; + +PyTypeObject WraptFunctionWrapper_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "FunctionWrapper", /*tp_name*/ + sizeof(WraptFunctionWrapperObject), /*tp_basicsize*/ + 0, /*tp_itemsize*/ + /* methods */ + 0, /*tp_dealloc*/ + 0, /*tp_print*/ + 0, /*tp_getattr*/ + 0, /*tp_setattr*/ + 0, /*tp_compare*/ + 0, /*tp_repr*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ + 0, /*tp_hash*/ + 0, /*tp_call*/ + 0, /*tp_str*/ + 0, /*tp_getattro*/ + 0, /*tp_setattro*/ + 0, /*tp_as_buffer*/ +#if PY_MAJOR_VERSION < 3 + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ +#else + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ +#endif + 0, /*tp_doc*/ + 0, /*tp_traverse*/ + 0, /*tp_clear*/ + 0, /*tp_richcompare*/ + offsetof(WraptObjectProxyObject, weakreflist), /*tp_weaklistoffset*/ + 0, /*tp_iter*/ + 0, /*tp_iternext*/ + 0, /*tp_methods*/ + 0, /*tp_members*/ + WraptFunctionWrapper_getset, /*tp_getset*/ + 0, /*tp_base*/ + 0, /*tp_dict*/ + 0, /*tp_descr_get*/ + 0, /*tp_descr_set*/ + 0, /*tp_dictoffset*/ + (initproc)WraptFunctionWrapper_init, /*tp_init*/ + 0, /*tp_alloc*/ + 0, /*tp_new*/ + 0, /*tp_free*/ + 0, /*tp_is_gc*/ +}; + +/* ------------------------------------------------------------------------- */; + +#if PY_MAJOR_VERSION >= 3 +static struct PyModuleDef moduledef = { + PyModuleDef_HEAD_INIT, + "_wrappers", /* m_name */ + NULL, /* m_doc */ + -1, /* m_size */ + NULL, /* m_methods */ + NULL, /* m_reload */ + NULL, /* m_traverse */ + NULL, /* m_clear */ + NULL, /* m_free */ +}; +#endif + +static PyObject * +moduleinit(void) +{ + PyObject *module; + +#if PY_MAJOR_VERSION >= 3 + module = PyModule_Create(&moduledef); +#else + module = Py_InitModule3("_wrappers", NULL, NULL); +#endif + + if (module == NULL) + return NULL; + + if (PyType_Ready(&WraptObjectProxy_Type) < 0) + return NULL; + + /* Ensure that inheritence relationships specified. */ + + WraptCallableObjectProxy_Type.tp_base = &WraptObjectProxy_Type; + WraptFunctionWrapperBase_Type.tp_base = &WraptObjectProxy_Type; + WraptBoundFunctionWrapper_Type.tp_base = &WraptFunctionWrapperBase_Type; + WraptFunctionWrapper_Type.tp_base = &WraptFunctionWrapperBase_Type; + + if (PyType_Ready(&WraptCallableObjectProxy_Type) < 0) + return NULL; + if (PyType_Ready(&WraptFunctionWrapperBase_Type) < 0) + return NULL; + if (PyType_Ready(&WraptBoundFunctionWrapper_Type) < 0) + return NULL; + if (PyType_Ready(&WraptFunctionWrapper_Type) < 0) + return NULL; + + Py_INCREF(&WraptObjectProxy_Type); + PyModule_AddObject(module, "ObjectProxy", + (PyObject *)&WraptObjectProxy_Type); + Py_INCREF(&WraptCallableObjectProxy_Type); + PyModule_AddObject(module, "CallableObjectProxy", + (PyObject *)&WraptCallableObjectProxy_Type); + Py_INCREF(&WraptFunctionWrapper_Type); + PyModule_AddObject(module, "FunctionWrapper", + (PyObject *)&WraptFunctionWrapper_Type); + + Py_INCREF(&WraptFunctionWrapperBase_Type); + PyModule_AddObject(module, "_FunctionWrapperBase", + (PyObject *)&WraptFunctionWrapperBase_Type); + Py_INCREF(&WraptBoundFunctionWrapper_Type); + PyModule_AddObject(module, "BoundFunctionWrapper", + (PyObject *)&WraptBoundFunctionWrapper_Type); + + return module; +} + +#if PY_MAJOR_VERSION < 3 +PyMODINIT_FUNC init_wrappers(void) +{ + moduleinit(); +} +#else +PyMODINIT_FUNC PyInit__wrappers(void) +{ + return moduleinit(); +} +#endif + +/* ------------------------------------------------------------------------- */ diff --git a/lib/wrapt/arguments.py b/lib/wrapt/arguments.py new file mode 100644 index 0000000000..f71df2573c --- /dev/null +++ b/lib/wrapt/arguments.py @@ -0,0 +1,95 @@ +# This is a copy of the inspect.getcallargs() function from Python 2.7 +# so we can provide it for use under Python 2.6. As the code in this +# file derives from the Python distribution, it falls under the version +# of the PSF license used for Python 2.7. + +from inspect import getargspec, ismethod + +def getcallargs(func, *positional, **named): + """Get the mapping of arguments to values. + + A dict is returned, with keys the function argument names (including the + names of the * and ** arguments, if any), and values the respective bound + values from 'positional' and 'named'.""" + args, varargs, varkw, defaults = getargspec(func) + f_name = func.__name__ + arg2value = {} + + # The following closures are basically because of tuple parameter unpacking. + assigned_tuple_params = [] + def assign(arg, value): + if isinstance(arg, str): + arg2value[arg] = value + else: + assigned_tuple_params.append(arg) + value = iter(value) + for i, subarg in enumerate(arg): + try: + subvalue = next(value) + except StopIteration: + raise ValueError('need more than %d %s to unpack' % + (i, 'values' if i > 1 else 'value')) + assign(subarg,subvalue) + try: + next(value) + except StopIteration: + pass + else: + raise ValueError('too many values to unpack') + def is_assigned(arg): + if isinstance(arg,str): + return arg in arg2value + return arg in assigned_tuple_params + if ismethod(func) and func.im_self is not None: + # implicit 'self' (or 'cls' for classmethods) argument + positional = (func.im_self,) + positional + num_pos = len(positional) + num_total = num_pos + len(named) + num_args = len(args) + num_defaults = len(defaults) if defaults else 0 + for arg, value in zip(args, positional): + assign(arg, value) + if varargs: + if num_pos > num_args: + assign(varargs, positional[-(num_pos-num_args):]) + else: + assign(varargs, ()) + elif 0 < num_args < num_pos: + raise TypeError('%s() takes %s %d %s (%d given)' % ( + f_name, 'at most' if defaults else 'exactly', num_args, + 'arguments' if num_args > 1 else 'argument', num_total)) + elif num_args == 0 and num_total: + if varkw: + if num_pos: + # XXX: We should use num_pos, but Python also uses num_total: + raise TypeError('%s() takes exactly 0 arguments ' + '(%d given)' % (f_name, num_total)) + else: + raise TypeError('%s() takes no arguments (%d given)' % + (f_name, num_total)) + for arg in args: + if isinstance(arg, str) and arg in named: + if is_assigned(arg): + raise TypeError("%s() got multiple values for keyword " + "argument '%s'" % (f_name, arg)) + else: + assign(arg, named.pop(arg)) + if defaults: # fill in any missing values with the defaults + for arg, value in zip(args[-num_defaults:], defaults): + if not is_assigned(arg): + assign(arg, value) + if varkw: + assign(varkw, named) + elif named: + unexpected = next(iter(named)) + if isinstance(unexpected, unicode): + unexpected = unexpected.encode(sys.getdefaultencoding(), 'replace') + raise TypeError("%s() got an unexpected keyword argument '%s'" % + (f_name, unexpected)) + unassigned = num_args - len([arg for arg in args if is_assigned(arg)]) + if unassigned: + num_required = num_args - num_defaults + raise TypeError('%s() takes %s %d %s (%d given)' % ( + f_name, 'at least' if defaults else 'exactly', num_required, + 'arguments' if num_required > 1 else 'argument', num_total)) + return arg2value diff --git a/lib/wrapt/decorators.py b/lib/wrapt/decorators.py new file mode 100644 index 0000000000..dd6016e76d --- /dev/null +++ b/lib/wrapt/decorators.py @@ -0,0 +1,512 @@ +"""This module implements decorators for implementing other decorators +as well as some commonly used decorators. + +""" + +import sys + +PY2 = sys.version_info[0] == 2 +PY3 = sys.version_info[0] == 3 + +if PY3: + string_types = str, + + import builtins + exec_ = getattr(builtins, "exec") + del builtins + +else: + string_types = basestring, + + def exec_(_code_, _globs_=None, _locs_=None): + """Execute code in a namespace.""" + if _globs_ is None: + frame = sys._getframe(1) + _globs_ = frame.f_globals + if _locs_ is None: + _locs_ = frame.f_locals + del frame + elif _locs_ is None: + _locs_ = _globs_ + exec("""exec _code_ in _globs_, _locs_""") + +from functools import partial +from inspect import ismethod, isclass, formatargspec +from collections import namedtuple +from threading import Lock, RLock + +try: + from inspect import signature +except ImportError: + pass + +from .wrappers import (FunctionWrapper, BoundFunctionWrapper, ObjectProxy, + CallableObjectProxy) + +# Adapter wrapper for the wrapped function which will overlay certain +# properties from the adapter function onto the wrapped function so that +# functions such as inspect.getargspec(), inspect.getfullargspec(), +# inspect.signature() and inspect.getsource() return the correct results +# one would expect. + +class _AdapterFunctionCode(CallableObjectProxy): + + def __init__(self, wrapped_code, adapter_code): + super(_AdapterFunctionCode, self).__init__(wrapped_code) + self._self_adapter_code = adapter_code + + @property + def co_argcount(self): + return self._self_adapter_code.co_argcount + + @property + def co_code(self): + return self._self_adapter_code.co_code + + @property + def co_flags(self): + return self._self_adapter_code.co_flags + + @property + def co_kwonlyargcount(self): + return self._self_adapter_code.co_kwonlyargcount + + @property + def co_varnames(self): + return self._self_adapter_code.co_varnames + +class _AdapterFunctionSurrogate(CallableObjectProxy): + + def __init__(self, wrapped, adapter): + super(_AdapterFunctionSurrogate, self).__init__(wrapped) + self._self_adapter = adapter + + @property + def __code__(self): + return _AdapterFunctionCode(self.__wrapped__.__code__, + self._self_adapter.__code__) + + @property + def __defaults__(self): + return self._self_adapter.__defaults__ + + @property + def __kwdefaults__(self): + return self._self_adapter.__kwdefaults__ + + @property + def __signature__(self): + if 'signature' not in globals(): + return self._self_adapter.__signature__ + else: + # Can't allow this to fail on Python 3 else it falls + # through to using __wrapped__, but that will be the + # wrong function we want to derive the signature + # from. Thus generate the signature ourselves. + + return signature(self._self_adapter) + + if PY2: + func_code = __code__ + func_defaults = __defaults__ + +class _BoundAdapterWrapper(BoundFunctionWrapper): + + @property + def __func__(self): + return _AdapterFunctionSurrogate(self.__wrapped__.__func__, + self._self_parent._self_adapter) + + if PY2: + im_func = __func__ + +class AdapterWrapper(FunctionWrapper): + + __bound_function_wrapper__ = _BoundAdapterWrapper + + def __init__(self, *args, **kwargs): + adapter = kwargs.pop('adapter') + super(AdapterWrapper, self).__init__(*args, **kwargs) + self._self_surrogate = _AdapterFunctionSurrogate( + self.__wrapped__, adapter) + self._self_adapter = adapter + + @property + def __code__(self): + return self._self_surrogate.__code__ + + @property + def __defaults__(self): + return self._self_surrogate.__defaults__ + + @property + def __kwdefaults__(self): + return self._self_surrogate.__kwdefaults__ + + if PY2: + func_code = __code__ + func_defaults = __defaults__ + + @property + def __signature__(self): + return self._self_surrogate.__signature__ + +class AdapterFactory(object): + def __call__(self, wrapped): + raise NotImplementedError() + +class DelegatedAdapterFactory(AdapterFactory): + def __init__(self, factory): + super(DelegatedAdapterFactory, self).__init__() + self.factory = factory + def __call__(self, wrapped): + return self.factory(wrapped) + +adapter_factory = DelegatedAdapterFactory + +# Decorator for creating other decorators. This decorator and the +# wrappers which they use are designed to properly preserve any name +# attributes, function signatures etc, in addition to the wrappers +# themselves acting like a transparent proxy for the original wrapped +# function so the wrapper is effectively indistinguishable from the +# original wrapped function. + +def decorator(wrapper=None, enabled=None, adapter=None): + # The decorator should be supplied with a single positional argument + # which is the wrapper function to be used to implement the + # decorator. This may be preceded by a step whereby the keyword + # arguments are supplied to customise the behaviour of the + # decorator. The 'adapter' argument is used to optionally denote a + # separate function which is notionally used by an adapter + # decorator. In that case parts of the function '__code__' and + # '__defaults__' attributes are used from the adapter function + # rather than those of the wrapped function. This allows for the + # argument specification from inspect.getargspec() and similar + # functions to be overridden with a prototype for a different + # function than what was wrapped. The 'enabled' argument provides a + # way to enable/disable the use of the decorator. If the type of + # 'enabled' is a boolean, then it is evaluated immediately and the + # wrapper not even applied if it is False. If not a boolean, it will + # be evaluated when the wrapper is called for an unbound wrapper, + # and when binding occurs for a bound wrapper. When being evaluated, + # if 'enabled' is callable it will be called to obtain the value to + # be checked. If False, the wrapper will not be called and instead + # the original wrapped function will be called directly instead. + + if wrapper is not None: + # Helper function for creating wrapper of the appropriate + # time when we need it down below. + + def _build(wrapped, wrapper, enabled=None, adapter=None): + if adapter: + if isinstance(adapter, AdapterFactory): + adapter = adapter(wrapped) + + if not callable(adapter): + ns = {} + if not isinstance(adapter, string_types): + adapter = formatargspec(*adapter) + exec_('def adapter{0}: pass'.format(adapter), ns, ns) + adapter = ns['adapter'] + + return AdapterWrapper(wrapped=wrapped, wrapper=wrapper, + enabled=enabled, adapter=adapter) + + return FunctionWrapper(wrapped=wrapped, wrapper=wrapper, + enabled=enabled) + + # The wrapper has been provided so return the final decorator. + # The decorator is itself one of our function wrappers so we + # can determine when it is applied to functions, instance methods + # or class methods. This allows us to bind the instance or class + # method so the appropriate self or cls attribute is supplied + # when it is finally called. + + def _wrapper(wrapped, instance, args, kwargs): + # We first check for the case where the decorator was applied + # to a class type. + # + # @decorator + # class mydecoratorclass(object): + # def __init__(self, arg=None): + # self.arg = arg + # def __call__(self, wrapped, instance, args, kwargs): + # return wrapped(*args, **kwargs) + # + # @mydecoratorclass(arg=1) + # def function(): + # pass + # + # In this case an instance of the class is to be used as the + # decorator wrapper function. If args was empty at this point, + # then it means that there were optional keyword arguments + # supplied to be used when creating an instance of the class + # to be used as the wrapper function. + + if instance is None and isclass(wrapped) and not args: + # We still need to be passed the target function to be + # wrapped as yet, so we need to return a further function + # to be able to capture it. + + def _capture(target_wrapped): + # Now have the target function to be wrapped and need + # to create an instance of the class which is to act + # as the decorator wrapper function. Before we do that, + # we need to first check that use of the decorator + # hadn't been disabled by a simple boolean. If it was, + # the target function to be wrapped is returned instead. + + _enabled = enabled + if type(_enabled) is bool: + if not _enabled: + return target_wrapped + _enabled = None + + # Now create an instance of the class which is to act + # as the decorator wrapper function. Any arguments had + # to be supplied as keyword only arguments so that is + # all we pass when creating it. + + target_wrapper = wrapped(**kwargs) + + # Finally build the wrapper itself and return it. + + return _build(target_wrapped, target_wrapper, + _enabled, adapter) + + return _capture + + # We should always have the target function to be wrapped at + # this point as the first (and only) value in args. + + target_wrapped = args[0] + + # Need to now check that use of the decorator hadn't been + # disabled by a simple boolean. If it was, then target + # function to be wrapped is returned instead. + + _enabled = enabled + if type(_enabled) is bool: + if not _enabled: + return target_wrapped + _enabled = None + + # We now need to build the wrapper, but there are a couple of + # different cases we need to consider. + + if instance is None: + if isclass(wrapped): + # In this case the decorator was applied to a class + # type but optional keyword arguments were not supplied + # for initialising an instance of the class to be used + # as the decorator wrapper function. + # + # @decorator + # class mydecoratorclass(object): + # def __init__(self, arg=None): + # self.arg = arg + # def __call__(self, wrapped, instance, + # args, kwargs): + # return wrapped(*args, **kwargs) + # + # @mydecoratorclass + # def function(): + # pass + # + # We still need to create an instance of the class to + # be used as the decorator wrapper function, but no + # arguments are pass. + + target_wrapper = wrapped() + + else: + # In this case the decorator was applied to a normal + # function, or possibly a static method of a class. + # + # @decorator + # def mydecoratorfuntion(wrapped, instance, + # args, kwargs): + # return wrapped(*args, **kwargs) + # + # @mydecoratorfunction + # def function(): + # pass + # + # That normal function becomes the decorator wrapper + # function. + + target_wrapper = wrapper + + else: + if isclass(instance): + # In this case the decorator was applied to a class + # method. + # + # class myclass(object): + # @decorator + # @classmethod + # def decoratorclassmethod(cls, wrapped, + # instance, args, kwargs): + # return wrapped(*args, **kwargs) + # + # instance = myclass() + # + # @instance.decoratorclassmethod + # def function(): + # pass + # + # This one is a bit strange because binding was actually + # performed on the wrapper created by our decorator + # factory. We need to apply that binding to the decorator + # wrapper function which which the decorator factory + # was applied to. + + target_wrapper = wrapper.__get__(None, instance) + + else: + # In this case the decorator was applied to an instance + # method. + # + # class myclass(object): + # @decorator + # def decoratorclassmethod(self, wrapped, + # instance, args, kwargs): + # return wrapped(*args, **kwargs) + # + # instance = myclass() + # + # @instance.decoratorclassmethod + # def function(): + # pass + # + # This one is a bit strange because binding was actually + # performed on the wrapper created by our decorator + # factory. We need to apply that binding to the decorator + # wrapper function which which the decorator factory + # was applied to. + + target_wrapper = wrapper.__get__(instance, type(instance)) + + # Finally build the wrapper itself and return it. + + return _build(target_wrapped, target_wrapper, _enabled, adapter) + + # We first return our magic function wrapper here so we can + # determine in what context the decorator factory was used. In + # other words, it is itself a universal decorator. + + return _build(wrapper, _wrapper) + + else: + # The wrapper still has not been provided, so we are just + # collecting the optional keyword arguments. Return the + # decorator again wrapped in a partial using the collected + # arguments. + + return partial(decorator, enabled=enabled, adapter=adapter) + +# Decorator for implementing thread synchronization. It can be used as a +# decorator, in which case the synchronization context is determined by +# what type of function is wrapped, or it can also be used as a context +# manager, where the user needs to supply the correct synchronization +# context. It is also possible to supply an object which appears to be a +# synchronization primitive of some sort, by virtue of having release() +# and acquire() methods. In that case that will be used directly as the +# synchronization primitive without creating a separate lock against the +# derived or supplied context. + +def synchronized(wrapped): + # Determine if being passed an object which is a synchronization + # primitive. We can't check by type for Lock, RLock, Semaphore etc, + # as the means of creating them isn't the type. Therefore use the + # existence of acquire() and release() methods. This is more + # extensible anyway as it allows custom synchronization mechanisms. + + if hasattr(wrapped, 'acquire') and hasattr(wrapped, 'release'): + # We remember what the original lock is and then return a new + # decorator which acceses and locks it. When returning the new + # decorator we wrap it with an object proxy so we can override + # the context manager methods in case it is being used to wrap + # synchronized statements with a 'with' statement. + + lock = wrapped + + @decorator + def _synchronized(wrapped, instance, args, kwargs): + # Execute the wrapped function while the original supplied + # lock is held. + + with lock: + return wrapped(*args, **kwargs) + + class _PartialDecorator(CallableObjectProxy): + + def __enter__(self): + lock.acquire() + return lock + + def __exit__(self, *args): + lock.release() + + return _PartialDecorator(wrapped=_synchronized) + + # Following only apply when the lock is being created automatically + # based on the context of what was supplied. In this case we supply + # a final decorator, but need to use FunctionWrapper directly as we + # want to derive from it to add context manager methods in in case it is + # being used to wrap synchronized statements with a 'with' statement. + + def _synchronized_lock(context): + # Attempt to retrieve the lock for the specific context. + + lock = vars(context).get('_synchronized_lock', None) + + if lock is None: + # There is no existing lock defined for the context we + # are dealing with so we need to create one. This needs + # to be done in a way to guarantee there is only one + # created, even if multiple threads try and create it at + # the same time. We can't always use the setdefault() + # method on the __dict__ for the context. This is the + # case where the context is a class, as __dict__ is + # actually a dictproxy. What we therefore do is use a + # meta lock on this wrapper itself, to control the + # creation and assignment of the lock attribute against + # the context. + + meta_lock = vars(synchronized).setdefault( + '_synchronized_meta_lock', Lock()) + + with meta_lock: + # We need to check again for whether the lock we want + # exists in case two threads were trying to create it + # at the same time and were competing to create the + # meta lock. + + lock = vars(context).get('_synchronized_lock', None) + + if lock is None: + lock = RLock() + setattr(context, '_synchronized_lock', lock) + + return lock + + def _synchronized_wrapper(wrapped, instance, args, kwargs): + # Execute the wrapped function while the lock for the + # desired context is held. If instance is None then the + # wrapped function is used as the context. + + with _synchronized_lock(instance or wrapped): + return wrapped(*args, **kwargs) + + class _FinalDecorator(FunctionWrapper): + + def __enter__(self): + self._self_lock = _synchronized_lock(self.__wrapped__) + self._self_lock.acquire() + return self._self_lock + + def __exit__(self, *args): + self._self_lock.release() + + return _FinalDecorator(wrapped=wrapped, wrapper=_synchronized_wrapper) diff --git a/lib/wrapt/importer.py b/lib/wrapt/importer.py new file mode 100644 index 0000000000..1eca4b6d6a --- /dev/null +++ b/lib/wrapt/importer.py @@ -0,0 +1,228 @@ +"""This module implements a post import hook mechanism styled after what is +described in PEP-369. Note that it doesn't cope with modules being reloaded. + +""" + +import sys +import threading + +PY2 = sys.version_info[0] == 2 +PY3 = sys.version_info[0] == 3 + +if PY3: + import importlib + string_types = str, +else: + string_types = basestring, + +from .decorators import synchronized + +# The dictionary registering any post import hooks to be triggered once +# the target module has been imported. Once a module has been imported +# and the hooks fired, the list of hooks recorded against the target +# module will be truncacted but the list left in the dictionary. This +# acts as a flag to indicate that the module had already been imported. + +_post_import_hooks = {} +_post_import_hooks_init = False +_post_import_hooks_lock = threading.RLock() + +# Register a new post import hook for the target module name. This +# differs from the PEP-369 implementation in that it also allows the +# hook function to be specified as a string consisting of the name of +# the callback in the form 'module:function'. This will result in a +# proxy callback being registered which will defer loading of the +# specified module containing the callback function until required. + +def _create_import_hook_from_string(name): + def import_hook(module): + module_name, function = name.split(':') + attrs = function.split('.') + __import__(module_name) + callback = sys.modules[module_name] + for attr in attrs: + callback = getattr(callback, attr) + return callback(module) + return import_hook + +@synchronized(_post_import_hooks_lock) +def register_post_import_hook(hook, name): + # Create a deferred import hook if hook is a string name rather than + # a callable function. + + if isinstance(hook, string_types): + hook = _create_import_hook_from_string(hook) + + # Automatically install the import hook finder if it has not already + # been installed. + + global _post_import_hooks_init + + if not _post_import_hooks_init: + _post_import_hooks_init = True + sys.meta_path.insert(0, ImportHookFinder()) + + # Determine if any prior registration of a post import hook for + # the target modules has occurred and act appropriately. + + hooks = _post_import_hooks.get(name, None) + + if hooks is None: + # No prior registration of post import hooks for the target + # module. We need to check whether the module has already been + # imported. If it has we fire the hook immediately and add an + # empty list to the registry to indicate that the module has + # already been imported and hooks have fired. Otherwise add + # the post import hook to the registry. + + module = sys.modules.get(name, None) + + if module is not None: + _post_import_hooks[name] = [] + hook(module) + + else: + _post_import_hooks[name] = [hook] + + elif hooks == []: + # A prior registration of port import hooks for the target + # module was done and the hooks already fired. Fire the hook + # immediately. + + module = sys.modules[name] + hook(module) + + else: + # A prior registration of port import hooks for the target + # module was done but the module has not yet been imported. + + _post_import_hooks[name].append(hook) + +# Register post import hooks defined as package entry points. + +def _create_import_hook_from_entrypoint(entrypoint): + def import_hook(module): + __import__(entrypoint.module_name) + callback = sys.modules[entrypoint.module_name] + for attr in entrypoint.attrs: + callback = getattr(callback, attr) + return callback(module) + return import_hook + +def discover_post_import_hooks(group): + try: + import pkg_resources + except ImportError: + return + + for entrypoint in pkg_resources.iter_entry_points(group=group): + callback = _create_import_hook_from_entrypoint(entrypoint) + register_post_import_hook(callback, entrypoint.name) + +# Indicate that a module has been loaded. Any post import hooks which +# were registered against the target module will be invoked. If an +# exception is raised in any of the post import hooks, that will cause +# the import of the target module to fail. + +@synchronized(_post_import_hooks_lock) +def notify_module_loaded(module): + name = getattr(module, '__name__', None) + hooks = _post_import_hooks.get(name, None) + + if hooks: + _post_import_hooks[name] = [] + + for hook in hooks: + hook(module) + +# A custom module import finder. This intercepts attempts to import +# modules and watches out for attempts to import target modules of +# interest. When a module of interest is imported, then any post import +# hooks which are registered will be invoked. + +class _ImportHookLoader: + + def load_module(self, fullname): + module = sys.modules[fullname] + notify_module_loaded(module) + + return module + +class _ImportHookChainedLoader: + + def __init__(self, loader): + self.loader = loader + + def load_module(self, fullname): + module = self.loader.load_module(fullname) + notify_module_loaded(module) + + return module + +class ImportHookFinder: + + def __init__(self): + self.in_progress = {} + + @synchronized(_post_import_hooks_lock) + def find_module(self, fullname, path=None): + # If the module being imported is not one we have registered + # post import hooks for, we can return immediately. We will + # take no further part in the importing of this module. + + if not fullname in _post_import_hooks: + return None + + # When we are interested in a specific module, we will call back + # into the import system a second time to defer to the import + # finder that is supposed to handle the importing of the module. + # We set an in progress flag for the target module so that on + # the second time through we don't trigger another call back + # into the import system and cause a infinite loop. + + if fullname in self.in_progress: + return None + + self.in_progress[fullname] = True + + # Now call back into the import system again. + + try: + if PY3: + # For Python 3 we need to use find_loader() from + # the importlib module. It doesn't actually + # import the target module and only finds the + # loader. If a loader is found, we need to return + # our own loader which will then in turn call the + # real loader to import the module and invoke the + # post import hooks. + + loader = importlib.find_loader(fullname, path) + + if loader: + return _ImportHookChainedLoader(loader) + + else: + # For Python 2 we don't have much choice but to + # call back in to __import__(). This will + # actually cause the module to be imported. If no + # module could be found then ImportError will be + # raised. Otherwise we return a loader which + # returns the already loaded module and invokes + # the post import hooks. + + __import__(fullname) + + return _ImportHookLoader() + + finally: + del self.in_progress[fullname] + +# Decorator for marking that a function should be called as a post +# import hook when the target module is imported. + +def when_imported(name): + def register(hook): + register_post_import_hook(hook, name) + return hook + return register diff --git a/lib/wrapt/wrappers.py b/lib/wrapt/wrappers.py new file mode 100644 index 0000000000..56fe15b919 --- /dev/null +++ b/lib/wrapt/wrappers.py @@ -0,0 +1,899 @@ +import sys +import functools +import operator +import weakref +import inspect + +PY2 = sys.version_info[0] == 2 +PY3 = sys.version_info[0] == 3 + +if PY3: + string_types = str, +else: + string_types = basestring, + +def with_metaclass(meta, *bases): + """Create a base class with a metaclass.""" + return meta("NewBase", bases, {}) + +class _ObjectProxyMethods(object): + + # We use properties to override the values of __module__ and + # __doc__. If we add these in ObjectProxy, the derived class + # __dict__ will still be setup to have string variants of these + # attributes and the rules of descriptors means that they appear to + # take precedence over the properties in the base class. To avoid + # that, we copy the properties into the derived class type itself + # via a meta class. In that way the properties will always take + # precedence. + + @property + def __module__(self): + return self.__wrapped__.__module__ + + @__module__.setter + def __module__(self, value): + self.__wrapped__.__module__ = value + + @property + def __doc__(self): + return self.__wrapped__.__doc__ + + @__doc__.setter + def __doc__(self, value): + self.__wrapped__.__doc__ = value + + # We similar use a property for __dict__. We need __dict__ to be + # explicit to ensure that vars() works as expected. + + @property + def __dict__(self): + return self.__wrapped__.__dict__ + + # Need to also propagate the special __weakref__ attribute for case + # where decorating classes which will define this. If do not define + # it and use a function like inspect.getmembers() on a decorator + # class it will fail. This can't be in the derived classes. + + @property + def __weakref__(self): + return self.__wrapped__.__weakref__ + +class _ObjectProxyMetaType(type): + def __new__(cls, name, bases, dictionary): + # Copy our special properties into the class so that they + # always take precedence over attributes of the same name added + # during construction of a derived class. This is to save + # duplicating the implementation for them in all derived classes. + + dictionary.update(vars(_ObjectProxyMethods)) + + return type.__new__(cls, name, bases, dictionary) + +class ObjectProxy(with_metaclass(_ObjectProxyMetaType)): + + __slots__ = '__wrapped__' + + def __init__(self, wrapped): + object.__setattr__(self, '__wrapped__', wrapped) + + # Python 3.2+ has the __qualname__ attribute, but it does not + # allow it to be overridden using a property and it must instead + # be an actual string object instead. + + try: + object.__setattr__(self, '__qualname__', wrapped.__qualname__) + except AttributeError: + pass + + @property + def __name__(self): + return self.__wrapped__.__name__ + + @__name__.setter + def __name__(self, value): + self.__wrapped__.__name__ = value + + @property + def __class__(self): + return self.__wrapped__.__class__ + + @__class__.setter + def __class__(self, value): + self.__wrapped__.__class__ = value + + @property + def __annotations__(self): + return self.__wrapped__.__anotations__ + + @__annotations__.setter + def __annotations__(self, value): + self.__wrapped__.__annotations__ = value + + def __dir__(self): + return dir(self.__wrapped__) + + def __str__(self): + return str(self.__wrapped__) + + if PY3: + def __bytes__(self): + return bytes(self.__wrapped__) + + def __repr__(self): + return '<%s at 0x%x for %s at 0x%x>' % ( + type(self).__name__, id(self), + type(self.__wrapped__).__name__, + id(self.__wrapped__)) + + def __reversed__(self): + return reversed(self.__wrapped__) + + if PY3: + def __round__(self): + return round(self.__wrapped__) + + def __lt__(self, other): + return self.__wrapped__ < other + + def __le__(self, other): + return self.__wrapped__ <= other + + def __eq__(self, other): + return self.__wrapped__ == other + + def __ne__(self, other): + return self.__wrapped__ != other + + def __gt__(self, other): + return self.__wrapped__ > other + + def __ge__(self, other): + return self.__wrapped__ >= other + + def __hash__(self): + return hash(self.__wrapped__) + + def __nonzero__(self): + return bool(self.__wrapped__) + + def __bool__(self): + return bool(self.__wrapped__) + + def __setattr__(self, name, value): + if name.startswith('_self_'): + object.__setattr__(self, name, value) + + elif name == '__wrapped__': + object.__setattr__(self, name, value) + try: + object.__delattr__(self, '__qualname__') + except AttributeError: + pass + try: + object.__setattr__(self, '__qualname__', value.__qualname__) + except AttributeError: + pass + + elif name == '__qualname__': + setattr(self.__wrapped__, name, value) + object.__setattr__(self, name, value) + + elif hasattr(type(self), name): + object.__setattr__(self, name, value) + + else: + setattr(self.__wrapped__, name, value) + + def __getattr__(self, name): + # If we are being to lookup '__wrapped__' then the + # '__init__()' method cannot have been called. + + if name == '__wrapped__': + raise ValueError('wrapper has not been initialised') + + return getattr(self.__wrapped__, name) + + def __delattr__(self, name): + if name.startswith('_self_'): + object.__delattr__(self, name) + + elif name == '__wrapped__': + raise TypeError('__wrapped__ must be an object') + + elif name == '__qualname__': + object.__delattr__(self, name) + delattr(self.__wrapped__, name) + + elif hasattr(type(self), name): + object.__delattr__(self, name) + + else: + delattr(self.__wrapped__, name) + + def __add__(self, other): + return self.__wrapped__ + other + + def __sub__(self, other): + return self.__wrapped__ - other + + def __mul__(self, other): + return self.__wrapped__ * other + + def __div__(self, other): + return operator.div(self.__wrapped__, other) + + def __truediv__(self, other): + return operator.truediv(self.__wrapped__, other) + + def __floordiv__(self, other): + return self.__wrapped__ // other + + def __mod__(self, other): + return self.__wrapped__ % other + + def __divmod__(self, other): + return divmod(self.__wrapped__, other) + + def __pow__(self, other, *args): + return pow(self.__wrapped__, other, *args) + + def __lshift__(self, other): + return self.__wrapped__ << other + + def __rshift__(self, other): + return self.__wrapped__ >> other + + def __and__(self, other): + return self.__wrapped__ & other + + def __xor__(self, other): + return self.__wrapped__ ^ other + + def __or__(self, other): + return self.__wrapped__ | other + + def __radd__(self, other): + return other + self.__wrapped__ + + def __rsub__(self, other): + return other - self.__wrapped__ + + def __rmul__(self, other): + return other * self.__wrapped__ + + def __rdiv__(self, other): + return operator.div(other, self.__wrapped__) + + def __rtruediv__(self, other): + return operator.truediv(other, self.__wrapped__) + + def __rfloordiv__(self, other): + return other // self.__wrapped__ + + def __rmod__(self, other): + return other % self.__wrapped__ + + def __rdivmod__(self, other): + return divmod(other, self.__wrapped__) + + def __rpow__(self, other, *args): + return pow(other, self.__wrapped__, *args) + + def __rlshift__(self, other): + return other << self.__wrapped__ + + def __rrshift__(self, other): + return other >> self.__wrapped__ + + def __rand__(self, other): + return other & self.__wrapped__ + + def __rxor__(self, other): + return other ^ self.__wrapped__ + + def __ror__(self, other): + return other | self.__wrapped__ + + def __iadd__(self, other): + self.__wrapped__ += other + return self + + def __isub__(self, other): + self.__wrapped__ -= other + return self + + def __imul__(self, other): + self.__wrapped__ *= other + return self + + def __idiv__(self, other): + self.__wrapped__ = operator.idiv(self.__wrapped__, other) + return self + + def __itruediv__(self, other): + self.__wrapped__ = operator.itruediv(self.__wrapped__, other) + return self + + def __ifloordiv__(self, other): + self.__wrapped__ //= other + return self + + def __imod__(self, other): + self.__wrapped__ %= other + return self + + def __ipow__(self, other): + self.__wrapped__ **= other + return self + + def __ilshift__(self, other): + self.__wrapped__ <<= other + return self + + def __irshift__(self, other): + self.__wrapped__ >>= other + return self + + def __iand__(self, other): + self.__wrapped__ &= other + return self + + def __ixor__(self, other): + self.__wrapped__ ^= other + return self + + def __ior__(self, other): + self.__wrapped__ |= other + return self + + def __neg__(self): + return -self.__wrapped__ + + def __pos__(self): + return +self.__wrapped__ + + def __abs__(self): + return abs(self.__wrapped__) + + def __invert__(self): + return ~self.__wrapped__ + + def __int__(self): + return int(self.__wrapped__) + + def __long__(self): + return long(self.__wrapped__) + + def __float__(self): + return float(self.__wrapped__) + + def __oct__(self): + return oct(self.__wrapped__) + + def __hex__(self): + return hex(self.__wrapped__) + + def __index__(self): + return operator.index(self.__wrapped__) + + def __len__(self): + return len(self.__wrapped__) + + def __contains__(self, value): + return value in self.__wrapped__ + + def __getitem__(self, key): + return self.__wrapped__[key] + + def __setitem__(self, key, value): + self.__wrapped__[key] = value + + def __delitem__(self, key): + del self.__wrapped__[key] + + def __getslice__(self, i, j): + return self.__wrapped__[i:j] + + def __setslice__(self, i, j, value): + self.__wrapped__[i:j] = value + + def __delslice__(self, i, j): + del self.__wrapped__[i:j] + + def __enter__(self): + return self.__wrapped__.__enter__() + + def __exit__(self, *args, **kwargs): + return self.__wrapped__.__exit__(*args, **kwargs) + + def __iter__(self): + return iter(self.__wrapped__) + +class CallableObjectProxy(ObjectProxy): + + def __call__(self, *args, **kwargs): + return self.__wrapped__(*args, **kwargs) + +class _FunctionWrapperBase(ObjectProxy): + + __slots__ = ('_self_instance', '_self_wrapper', '_self_enabled', + '_self_binding', '_self_parent') + + def __init__(self, wrapped, instance, wrapper, enabled=None, + binding='function', parent=None): + + super(_FunctionWrapperBase, self).__init__(wrapped) + + object.__setattr__(self, '_self_instance', instance) + object.__setattr__(self, '_self_wrapper', wrapper) + object.__setattr__(self, '_self_enabled', enabled) + object.__setattr__(self, '_self_binding', binding) + object.__setattr__(self, '_self_parent', parent) + + def __get__(self, instance, owner): + # This method is actually doing double duty for both unbound and + # bound derived wrapper classes. It should possibly be broken up + # and the distinct functionality moved into the derived classes. + # Can't do that straight away due to some legacy code which is + # relying on it being here in this base class. + # + # The distinguishing attribute which determines whether we are + # being called in an unbound or bound wrapper is the parent + # attribute. If binding has never occured, then the parent will + # be None. + # + # First therefore, is if we are called in an unbound wrapper. In + # this case we perform the binding. + # + # We have one special case to worry about here. This is where we + # are decorating a nested class. In this case the wrapped class + # would not have a __get__() method to call. In that case we + # simply return self. + # + # Note that we otherwise still do binding even if instance is + # None and accessing an unbound instance method from a class. + # This is because we need to be able to later detect that + # specific case as we will need to extract the instance from the + # first argument of those passed in. + + if self._self_parent is None: + if not inspect.isclass(self.__wrapped__): + descriptor = self.__wrapped__.__get__(instance, owner) + + return self.__bound_function_wrapper__(descriptor, instance, + self._self_wrapper, self._self_enabled, + self._self_binding, self) + + return self + + # Now we have the case of binding occuring a second time on what + # was already a bound function. In this case we would usually + # return ourselves again. This mirrors what Python does. + # + # The special case this time is where we were originally bound + # with an instance of None and we were likely an instance + # method. In that case we rebind against the original wrapped + # function from the parent again. + + if self._self_instance is None and self._self_binding == 'function': + descriptor = self._self_parent.__wrapped__.__get__( + instance, owner) + + return self._self_parent.__bound_function_wrapper__( + descriptor, instance, self._self_wrapper, + self._self_enabled, self._self_binding, + self._self_parent) + + return self + + def __call__(self, *args, **kwargs): + # If enabled has been specified, then evaluate it at this point + # and if the wrapper is not to be executed, then simply return + # the bound function rather than a bound wrapper for the bound + # function. When evaluating enabled, if it is callable we call + # it, otherwise we evaluate it as a boolean. + + if self._self_enabled is not None: + if callable(self._self_enabled): + if not self._self_enabled(): + return self.__wrapped__(*args, **kwargs) + elif not self._self_enabled: + return self.__wrapped__(*args, **kwargs) + + # This can occur where initial function wrapper was applied to + # a function that was already bound to an instance. In that case + # we want to extract the instance from the function and use it. + + if self._self_binding == 'function': + if self._self_instance is None: + instance = getattr(self.__wrapped__, '__self__', None) + if instance is not None: + return self._self_wrapper(self.__wrapped__, instance, + args, kwargs) + + # This is generally invoked when the wrapped function is being + # called as a normal function and is not bound to a class as an + # instance method. This is also invoked in the case where the + # wrapped function was a method, but this wrapper was in turn + # wrapped using the staticmethod decorator. + + return self._self_wrapper(self.__wrapped__, self._self_instance, + args, kwargs) + +class BoundFunctionWrapper(_FunctionWrapperBase): + + def __call__(self, *args, **kwargs): + # If enabled has been specified, then evaluate it at this point + # and if the wrapper is not to be executed, then simply return + # the bound function rather than a bound wrapper for the bound + # function. When evaluating enabled, if it is callable we call + # it, otherwise we evaluate it as a boolean. + + if self._self_enabled is not None: + if callable(self._self_enabled): + if not self._self_enabled(): + return self.__wrapped__(*args, **kwargs) + elif not self._self_enabled: + return self.__wrapped__(*args, **kwargs) + + # We need to do things different depending on whether we are + # likely wrapping an instance method vs a static method or class + # method. + + if self._self_binding == 'function': + if self._self_instance is None: + # This situation can occur where someone is calling the + # instancemethod via the class type and passing the instance + # as the first argument. We need to shift the args before + # making the call to the wrapper and effectively bind the + # instance to the wrapped function using a partial so the + # wrapper doesn't see anything as being different. + + if not args: + raise TypeError('missing 1 required positional argument') + + instance, args = args[0], args[1:] + wrapped = functools.partial(self.__wrapped__, instance) + return self._self_wrapper(wrapped, instance, args, kwargs) + + return self._self_wrapper(self.__wrapped__, self._self_instance, + args, kwargs) + + else: + # As in this case we would be dealing with a classmethod or + # staticmethod, then _self_instance will only tell us whether + # when calling the classmethod or staticmethod they did it via an + # instance of the class it is bound to and not the case where + # done by the class type itself. We thus ignore _self_instance + # and use the __self__ attribute of the bound function instead. + # For a classmethod, this means instance will be the class type + # and for a staticmethod it will be None. This is probably the + # more useful thing we can pass through even though we loose + # knowledge of whether they were called on the instance vs the + # class type, as it reflects what they have available in the + # decoratored function. + + instance = getattr(self.__wrapped__, '__self__', None) + + return self._self_wrapper(self.__wrapped__, instance, args, + kwargs) + +class FunctionWrapper(_FunctionWrapperBase): + + __bound_function_wrapper__ = BoundFunctionWrapper + + def __init__(self, wrapped, wrapper, enabled=None): + # What it is we are wrapping here could be anything. We need to + # try and detect specific cases though. In particular, we need + # to detect when we are given something that is a method of a + # class. Further, we need to know when it is likely an instance + # method, as opposed to a class or static method. This can + # become problematic though as there isn't strictly a fool proof + # method of knowing. + # + # The situations we could encounter when wrapping a method are: + # + # 1. The wrapper is being applied as part of a decorator which + # is a part of the class definition. In this case what we are + # given is the raw unbound function, classmethod or staticmethod + # wrapper objects. + # + # The problem here is that we will not know we are being applied + # in the context of the class being set up. This becomes + # important later for the case of an instance method, because in + # that case we just see it as a raw function and can't + # distinguish it from wrapping a normal function outside of + # a class context. + # + # 2. The wrapper is being applied when performing monkey + # patching of the class type afterwards and the method to be + # wrapped was retrieved direct from the __dict__ of the class + # type. This is effectively the same as (1) above. + # + # 3. The wrapper is being applied when performing monkey + # patching of the class type afterwards and the method to be + # wrapped was retrieved from the class type. In this case + # binding will have been performed where the instance against + # which the method is bound will be None at that point. + # + # This case is a problem because we can no longer tell if the + # method was a static method, plus if using Python3, we cannot + # tell if it was an instance method as the concept of an + # unnbound method no longer exists. + # + # 4. The wrapper is being applied when performing monkey + # patching of an instance of a class. In this case binding will + # have been perfomed where the instance was not None. + # + # This case is a problem because we can no longer tell if the + # method was a static method. + # + # Overall, the best we can do is look at the original type of the + # object which was wrapped prior to any binding being done and + # see if it is an instance of classmethod or staticmethod. In + # the case where other decorators are between us and them, if + # they do not propagate the __class__ attribute so that the + # isinstance() checks works, then likely this will do the wrong + # thing where classmethod and staticmethod are used. + # + # Since it is likely to be very rare that anyone even puts + # decorators around classmethod and staticmethod, likelihood of + # that being an issue is very small, so we accept it and suggest + # that those other decorators be fixed. It is also only an issue + # if a decorator wants to actually do things with the arguments. + # + # As to not being able to identify static methods properly, we + # just hope that that isn't something people are going to want + # to wrap, or if they do suggest they do it the correct way by + # ensuring that it is decorated in the class definition itself, + # or patch it in the __dict__ of the class type. + # + # So to get the best outcome we can, whenever we aren't sure what + # it is, we label it as a 'function'. If it was already bound and + # that is rebound later, we assume that it will be an instance + # method and try an cope with the possibility that the 'self' + # argument it being passed as an explicit argument and shuffle + # the arguments around to extract 'self' for use as the instance. + + if isinstance(wrapped, classmethod): + binding = 'classmethod' + + elif isinstance(wrapped, staticmethod): + binding = 'staticmethod' + + elif hasattr(wrapped, '__self__'): + if inspect.isclass(wrapped.__self__): + binding = 'classmethod' + else: + binding = 'function' + + else: + binding = 'function' + + super(FunctionWrapper, self).__init__(wrapped, None, wrapper, + enabled, binding) + +try: + from ._wrappers import (ObjectProxy, CallableObjectProxy, FunctionWrapper, + BoundFunctionWrapper, _FunctionWrapperBase) +except ImportError: + pass + +# Helper functions for applying wrappers to existing functions. + +def resolve_path(module, name): + if isinstance(module, string_types): + __import__(module) + module = sys.modules[module] + + parent = module + + path = name.split('.') + attribute = path[0] + + original = getattr(parent, attribute) + for attribute in path[1:]: + parent = original + + # We can't just always use getattr() because in doing + # that on a class it will cause binding to occur which + # will complicate things later and cause some things not + # to work. For the case of a class we therefore access + # the __dict__ directly. To cope though with the wrong + # class being given to us, or a method being moved into + # a base class, we need to walk the class heirarchy to + # work out exactly which __dict__ the method was defined + # in, as accessing it from __dict__ will fail if it was + # not actually on the class given. Fallback to using + # getattr() if we can't find it. If it truly doesn't + # exist, then that will fail. + + if inspect.isclass(original): + for cls in inspect.getmro(original): + if attribute in vars(original): + original = vars(original)[attribute] + break + else: + original = getattr(original, attribute) + + else: + original = getattr(original, attribute) + + return (parent, attribute, original) + +def apply_patch(parent, attribute, replacement): + setattr(parent, attribute, replacement) + +def wrap_object(module, name, factory, args=(), kwargs={}): + (parent, attribute, original) = resolve_path(module, name) + wrapper = factory(original, *args, **kwargs) + apply_patch(parent, attribute, wrapper) + return wrapper + +# Function for applying a proxy object to an attribute of a class +# instance. The wrapper works by defining an attribute of the same name +# on the class which is a descriptor and which intercepts access to the +# instance attribute. Note that this cannot be used on attributes which +# are themselves defined by a property object. + +class AttributeWrapper(object): + + def __init__(self, attribute, factory, args, kwargs): + self.attribute = attribute + self.factory = factory + self.args = args + self.kwargs = kwargs + + def __get__(self, instance, owner): + value = instance.__dict__[self.attribute] + return self.factory(value, *self.args, **self.kwargs) + + def __set__(self, instance, value): + instance.__dict__[self.attribute] = value + + def __delete__(self, instance): + del instance.__dict__[self.attribute] + +def wrap_object_attribute(module, name, factory, args=(), kwargs={}): + path, attribute = name.rsplit('.', 1) + parent = resolve_path(module, path)[2] + wrapper = AttributeWrapper(attribute, factory, args, kwargs) + apply_patch(parent, attribute, wrapper) + return wrapper + +# Functions for creating a simple decorator using a FunctionWrapper, +# plus short cut functions for applying wrappers to functions. These are +# for use when doing monkey patching. For a more featured way of +# creating decorators see the decorator decorator instead. + +def function_wrapper(wrapper): + def _wrapper(wrapped, instance, args, kwargs): + target_wrapped = args[0] + if instance is None: + target_wrapper = wrapper + elif inspect.isclass(instance): + target_wrapper = wrapper.__get__(None, instance) + else: + target_wrapper = wrapper.__get__(instance, type(instance)) + return FunctionWrapper(target_wrapped, target_wrapper) + return FunctionWrapper(wrapper, _wrapper) + +def wrap_function_wrapper(module, name, wrapper): + return wrap_object(module, name, FunctionWrapper, (wrapper,)) + +def patch_function_wrapper(module, name): + def _wrapper(wrapper): + return wrap_object(module, name, FunctionWrapper, (wrapper,)) + return _wrapper + +def transient_function_wrapper(module, name): + def _decorator(wrapper): + def _wrapper(wrapped, instance, args, kwargs): + target_wrapped = args[0] + if instance is None: + target_wrapper = wrapper + elif inspect.isclass(instance): + target_wrapper = wrapper.__get__(None, instance) + else: + target_wrapper = wrapper.__get__(instance, type(instance)) + def _execute(wrapped, instance, args, kwargs): + (parent, attribute, original) = resolve_path(module, name) + replacement = FunctionWrapper(original, target_wrapper) + setattr(parent, attribute, replacement) + try: + return wrapped(*args, **kwargs) + finally: + setattr(parent, attribute, original) + return FunctionWrapper(target_wrapped, _execute) + return FunctionWrapper(wrapper, _wrapper) + return _decorator + +# A weak function proxy. This will work on instance methods, class +# methods, static methods and regular functions. Special treatment is +# needed for the method types because the bound method is effectively a +# transient object and applying a weak reference to one will immediately +# result in it being destroyed and the weakref callback called. The weak +# reference is therefore applied to the instance the method is bound to +# and the original function. The function is then rebound at the point +# of a call via the weak function proxy. + +def _weak_function_proxy_callback(ref, proxy, callback): + if proxy._self_expired: + return + + proxy._self_expired = True + + # This could raise an exception. We let it propagate back and let + # the weakref.proxy() deal with it, at which point it generally + # prints out a short error message direct to stderr and keeps going. + + if callback is not None: + callback(proxy) + +class WeakFunctionProxy(ObjectProxy): + + __slots__ = ('_self_expired', '_self_instance') + + def __init__(self, wrapped, callback=None): + # We need to determine if the wrapped function is actually a + # bound method. In the case of a bound method, we need to keep a + # reference to the original unbound function and the instance. + # This is necessary because if we hold a reference to the bound + # function, it will be the only reference and given it is a + # temporary object, it will almost immediately expire and + # the weakref callback triggered. So what is done is that we + # hold a reference to the instance and unbound function and + # when called bind the function to the instance once again and + # then call it. Note that we avoid using a nested function for + # the callback here so as not to cause any odd reference cycles. + + _callback = callback and functools.partial( + _weak_function_proxy_callback, proxy=self, + callback=callback) + + self._self_expired = False + + if isinstance(wrapped, _FunctionWrapperBase): + self._self_instance = weakref.ref(wrapped._self_instance, + _callback) + + if wrapped._self_parent is not None: + super(WeakFunctionProxy, self).__init__( + weakref.proxy(wrapped._self_parent, _callback)) + + else: + super(WeakFunctionProxy, self).__init__( + weakref.proxy(wrapped, _callback)) + + return + + try: + self._self_instance = weakref.ref(wrapped.__self__, _callback) + + super(WeakFunctionProxy, self).__init__( + weakref.proxy(wrapped.__func__, _callback)) + + except AttributeError: + self._self_instance = None + + super(WeakFunctionProxy, self).__init__( + weakref.proxy(wrapped, _callback)) + + def __call__(self, *args, **kwargs): + # We perform a boolean check here on the instance and wrapped + # function as that will trigger the reference error prior to + # calling if the reference had expired. + + instance = self._self_instance and self._self_instance() + function = self.__wrapped__ and self.__wrapped__ + + # If the wrapped function was originally a bound function, for + # which we retained a reference to the instance and the unbound + # function we need to rebind the function and then call it. If + # not just called the wrapped function. + + if instance is None: + return self.__wrapped__(*args, **kwargs) + + return function.__get__(instance, type(instance))(*args, **kwargs) diff --git a/tests/providers/conftest.py b/tests/providers/conftest.py index 507a54b766..08dff25b59 100644 --- a/tests/providers/conftest.py +++ b/tests/providers/conftest.py @@ -30,11 +30,11 @@ def providers(): for provider in providers: # Load provider test config - input_file = os.path.join(__location__, provider.type, provider.name, provider.name + '_test.yml') + input_file = os.path.join(__location__, provider.type, provider.name, provider.name + '_test.yaml') with open(input_file, 'r') as stream: - data = yaml.load(stream) + test_data = yaml.load(stream) # Update provider with test data - provider.data.update(data) + provider.data.update(test_data) return providers diff --git a/tests/providers/test_parser.py b/tests/providers/test_parser.py index 95dd416216..6f400fde83 100644 --- a/tests/providers/test_parser.py +++ b/tests/providers/test_parser.py @@ -2,9 +2,10 @@ """Provider parser tests.""" from __future__ import unicode_literals -import codecs import os +import vcr + __location__ = os.path.realpath(os.path.join(os.getcwd(), os.path.dirname(__file__))) @@ -15,16 +16,19 @@ def test_parser_daily(providers, limit=3): for provider in providers: # When - html = codecs.open(os.path.join(__location__, provider.type, provider.name, - provider.name + '_daily.html'), 'r') + html = os.path.join(__location__, provider.type, provider.name, + provider.name + '_daily.yaml') - actual = provider.klass.parse(html.read(), provider.data['daily']['mode']) + with vcr.use_cassette(html) as test: - # Then - for i, result in enumerate(actual): - assert result == provider.data['daily']['data'][i] - if i + 1 == limit: - break + actual = provider.klass.parse(test.responses[0]['body']['string'], + provider.data['daily']['mode']) + + # Then + for i, result in enumerate(actual): + assert result == provider.data['daily']['data'][i] + if i + 1 == limit: + break def test_parser_backlog(providers, limit=2): @@ -33,10 +37,13 @@ def test_parser_backlog(providers, limit=2): for provider in providers: # When - html = codecs.open(os.path.join(__location__, provider.type, provider.name, - provider.name + '_backlog.html'), 'r') + html = os.path.join(__location__, provider.type, provider.name, + provider.name + '_backlog.yaml') + + with vcr.use_cassette(html) as test: - actual = provider.klass.parse(html.read(), provider.data['backlog']['mode']) + actual = provider.klass.parse(test.responses[0]['body']['string'], + provider.data['backlog']['mode']) # Then for i, result in enumerate(actual): diff --git a/tests/providers/test_search.py b/tests/providers/test_search.py new file mode 100644 index 0000000000..62be0b0017 --- /dev/null +++ b/tests/providers/test_search.py @@ -0,0 +1,38 @@ +# coding=utf-8 +"""Provider search tests.""" +from __future__ import unicode_literals + +import os + +from vcr import VCR + + +__location__ = os.path.realpath(os.path.join(os.getcwd(), os.path.dirname(__file__))) + + +vcr = VCR(path_transformer=VCR.ensure_suffix('.yaml'), + record_mode='once', + match_on=['method', 'scheme', 'host', 'port', 'path', 'query', 'body'], + cassette_library_dir=__location__) + + +def test_search_backlog(providers): + + # Given + for provider in providers: + + with vcr.use_cassette(os.path.join(provider.type, provider.name, provider.name + '_backlog')): + + search_strings = {provider.data['backlog']['mode']: provider.data['backlog']['search_strings']} + provider.klass.search(search_strings) + + +def test_search_daily(providers): + + # Given + for provider in providers: + + with vcr.use_cassette(os.path.join(provider.type, provider.name, provider.name + '_daily')): + + search_strings = {provider.data['daily']['mode']: provider.data['daily']['search_strings']} + provider.klass.search(search_strings) diff --git a/tests/providers/torrent/extratorrent/extratorrent_backlog.html b/tests/providers/torrent/extratorrent/extratorrent_backlog.html deleted file mode 100644 index d2207196a6..0000000000 --- a/tests/providers/torrent/extratorrent/extratorrent_backlog.html +++ /dev/null @@ -1,231 +0,0 @@ - - - - - - - - - - - - Search for 'Elementary S05E07' torrents - Page 1 - ExtraTorrent.cc The World's Largest BitTorrent System - - - - - - - - - - - - - - - - - - - - - - -
-
ExtraTorrent.cc - The Largest Bittorent SystemLogin   |   Register
-
- - - - - -
-
Latest Articles
Most searched
Hot torrents
First Cams
View Torrent Info: Max Steel 2016 HC HDCAM UnKnOwN
View Torrent Info: Allied 2016 HDCAM x264 AC3 HQMic-CPG
View Torrent Info: Underworld Blood Wars 2016 HDCAM NAKRO
View Torrent Info: Moana 2016 HD-TS XviD AC3-CPG
Hot torrents
XVID DIVX
View Torrent Info: Criticsized.2016.HDRip.XviD.AC3-EVO
View Torrent Info: Stevie.D.2016.HDRip.XviD.AC3-EVO
View Torrent Info: American.Honey.2016.HDRip.XviD.AC3-EVO
View Torrent Info: City.of.Sin.2017.HDRip.XviD.AC3-EVO
Hot torrents
H264 X264
View Torrent Info: American.Honey.2016.720p.BRRip.x264.AAC-ETRG
View Torrent Info: Independence.Day.1996.Extended.BluRay.720p.DTS.AC3.x264-ETRG
View Torrent Info: When.The.Bough.Breaks.2016.720p.BRRip.x264.AAC-ETRG
View Torrent Info: Incarnate.2016.720p.WEBRip.x264.AAC-ETRG
Hot torrents
Television
View Torrent Info: Chance.S01E10.WEB.H264-DEFLATE[ettv]
View Torrent Info: NCIS.S14E10.HDTV.x264-LOL[ettv]
View Torrent Info: Bull.2016.S01E09.HDTV.x264-LOL[ettv]
View Torrent Info: NCIS.New.Orleans.S03E09.HDTV.x264-LOL[ettv]
View Torrent Info: Jijibisha.(2016)-HEVC-Tiny.Rip-x265.AAC.Esubs-400MB-[DDR]
View Torrent Info: Tai Chi Zero (2012) x264 720p BluRay Eng Subs {Dual Audio} [Hindi DD 2.0   Chinese 5.1] Exclusive By DREDD
View Torrent Info: Maalik (2016) HDRIP 1GBRIP x265 AAC Esub [DDR]
View Torrent Info: Born to Defense (1986) DVDRip x264 Eng Subs [Dual Audio] [Hindi 2.0 - English 2.0] Exclusive By -=!Dr.STAR!=-
- -
30s
Chat
To add new messages please Login or Register for FREE
- - - - - -
- - - -
Warning! Protect Yourself from Lawsuits and Fines!
Your IP Address is 87.78.209.173.   Location is Germany
Your IP Address is visible to EVERYONE. Hide your IP ADDRESS with a VPN while torrenting!
ExtraTorrent strongly recommends using Trust.Zone VPN to anonymize your torrenting. It's FREE!
- - -
- - - -
-ExtraTorrent.cc > Search for Torrents -
-

- -

Search for Torrents

- -
- -
-
- - - - - - - - - - - - - -
Search
Category - -
-
-
- - -
Safety Recommendation:   Download Torrents Anonymously!

Your IP Address is 87.78.209.173.   Location is Germany
Torrenting does not guarantee ANONYMITY! Your Internet Provider and Government can track your torrent activity!
ExtraTorrent strongly recommends using Trust.Zone VPN to anonymize your torrenting. Protect yourself with VPN - Save ExtraTorrent!

- - - - -

Search for torrents results: - - RSS: Search 'Elementary S05E07' Torrents - -

-total 6 torrents found -  (watch for "Elementary S05E07" new coming torrents watch for Elementary S05E07 new coming torrents)

- - - - - - -
-   - - Torrents per page: - -
- - - - - - - -
  Sort
Added Size SortS SortL SortHealth
DownloadMagnet linkBrowseEnglish Elementary S05E07 (1080p WEBRip x265 HEVC 10bit AAC 5.1 Qman) [UTR] 10.00 in Elementary, by 21d361.52 MB4914
DownloadMagnet linkBrowseEnglish Elementary.S05E07.1080p.HDTV.x264[state] in Elementary, by 23d434.28 MB21945
DownloadMagnet linkBrowseEnglish Elementary.S05E07.HDTV.XviD-FUM[ettv] in Other, by 23d348.20 MB3514351
DownloadMagnet linkBrowseEnglish Elementary.S05E07.1080p.HDTV.X264-DIMENSION[ettv] 10.00 in Other, by 23d3.69 GB18049
DownloadMagnet linkBrowseEnglish Elementary.S05E07.HDTV.x264-LOL[ettv] 10.00 in Other, by 23d203.37 MB4229302
DownloadMagnet linkBrowseEnglish Elementary.S05E07.720p.HDTV.X264-DIMENSION[ettv] 9.00 in Other, by 23d741.07 MB671151

- - - - - -
-   - - Torrents per page: - -
- - -
-

Recent Searches

planes hindi     zombieland 2 dvdrip jaybob     the wire s04e02 720p     ETTV     game of thrones s02e01 winter is ing hdtv xvid-fqm     dvd     water under the bridge     The Warlords 2007     Luke Cage S01E09 720p     the simpsons se01 720p     the karate kid, part ii 720p     conguring2     software     lil flip carmine     gossip girl s01e03 720p     casting     marvels agent of s.h.i.e.l.d. s04e09     adult     the vampire diaries s05e09 720p     Now You See Me 1     supergirl s02e06 720p     zootopia 720p     sausage party 720p     fear, inc. 720p     movie     the middle s08e07     DDR     elementary s05e07     Westworld     angus 1995 720p web-dl h264-ctrlhd [publichd]     toy story 720p     suicide squad 720p     the conjuring     The Marine REPACK TS XviD TFF[ ]     the lord of the rings - the two towers 720p     anime     wildonesfloride     K-camp ft chris brown lil bit     the legend of korra s03e 720p     the real housewives of atlanta     890 bridge training eur multi5 nds eximius(torrent     south park 1 a 15 temporada dublado     the BFG     SISTER SLEDGE     sex     the middle s08e09 720p     Shawn mendes     music     porn     the 7d     search     the witching 720p     the walking dead     van helsing s01e04 720p     ultimate r&b songs     ETRG     Francesca's Juggies 3     bronchial asthma     game of thrones s02e 720p     zodiac 720p     z nation s01e02 720p     

- -
- - - - - - - - - - - - - - - -
- - -
-
-
- Home - - Browse Torrents - - Upload Torrent - - Stat - - Forum - - FAQ - - Login
- ExtraTorrent.cc is in compliance with copyrights
- BitCoin: 12DiyqsWhENahDzdhdYsRrCw8FPQVcCkcm
- Can't load ExtraTorrent? Try our official mirrors: etmirror.com - etproxy.com - extratorrentonline.com - extratorrentlive.com
- 2006-2016 ExtraTorrent.cc3 -
- - -
- -
- - - - - - diff --git a/tests/providers/torrent/extratorrent/extratorrent_backlog.yaml b/tests/providers/torrent/extratorrent/extratorrent_backlog.yaml new file mode 100644 index 0000000000..0eed50c2f5 --- /dev/null +++ b/tests/providers/torrent/extratorrent/extratorrent_backlog.yaml @@ -0,0 +1,277 @@ +interactions: +- request: + body: null + headers: + Accept: ['*/*'] + Accept-Encoding: ['gzip,deflate'] + Connection: [keep-alive] + User-Agent: [!!python/unicode 'Mozilla/5.0 (X11; Linux i586; rv:31.0) Gecko/20100101 + Firefox/31.0'] + method: GET + uri: http://extratorrent.cc/search/?search=Arrow+S05E07&x=0&y=0&new=1 + response: + body: {string: "\n\n\n \n \n \n \n \n \n + \ \n \n + \ Search for 'Arrow S05E07' torrents - Page 1 - ExtraTorrent.cc The + World's Largest BitTorrent System\n \n \n + \ \n\n\n\n\n \n\n\n \n\n\n \n\n\n \n\n
\n + \
\"ExtraTorrent.cc Advanced SearchLogin   |   Register
\n + \
\n
Browse Torrents
|Search Cloud|Site Stats
|Community
|FAQ 
\n
\n \n \n \n + \ \n \n
\n + \
Latest Articles
+ \
Most + searched
\"Hot
First Cams
\"View
\"View
\"View
\"View
\"Hot
XVID DIVX
\"View
\"View
\"View
\"View
\"Hot
H264 X264
\"View
\"View
\"View
\"View
\"Hot
Television
\"View
\"View
\"View
\"View
\"View
\"View
\"View
\"View
\n \n
30s
Chat
To add new messages please + Login or Register for FREE
\n\n
\n
\n\n\n\n
\n \n\n \n \n\n \n
\n\n\n\n
{\"ct\":\"UAWyjYNPON2EEUgR5m\\/jk\\/M5RTEJZ4nRCQLzMG2p9jl\\/Il6ofVlv4Oa39jiNFA8Ah4UgrmROV4pFG7KvISxR+gWOq8wbEFg6fLhKyJ2\\/iLx0Y1zyamcdCy+s7993U6WEHFNNvvSFYRF9pyItXfDIU8PF9ZZhlPyPtxuecpifT8NXjY45hA8Za5XtXMsQJy4aEhbCZXC2FEEjJ9Lmgq\\/WdrnCN1eerXor1RIksdlwCANPkLe\\/RmYUZQLqXJS1Ke1wOssAw70oWfDKPaxkyaaSOlCSehqhGMJ\\/OU2UpY7FNkmYXrKQddaycVjoKh8MSD2GSASAqXZaYlDkIEjCDU8k52PB+bYIiHf\\/u2k7HA0Q7jqZwpiCl22sjdhzLlhLsRWTU1xyaQg0EaXKl6cuxMVQ06LLIVyBv4PRTWGve9M9dexf3sPJ9GclAVIi9JvXyBjpNxb+erD1EajGZApZhKO5+NxbYndTjRDcaWApXlSJc\\/IkJssM9HTArI1jKJct\\/yZmG1sLSoL1ExGYGtSjYy16hKARNNrts4RhVjkOeVbyvz30pBCrGNdpz0IgTsJQTpL\\/uycLuYDAFrKk6Vx\\/bftp8BQknWYNVT0jErIuf97EOu5ZuBhZRYC5R+TiKggsVTdJzZYbFocP3dirEGupkhzk5F1SxnSoA+dVkFMiZCrSxYN0P8wsFKhf4fkHZdYm7PtZxphcS4ZoP8OkP0hq4F26hLaL5czlIIXI4TqdT1zKVLvFhVhQWftGa25WTKSQlINoxZerdrGeaGXmoNGg9NokzDvM3UXzD+OY2MRGyvf4nhmHiHKNDUjA9Yt2k7zpfDOPIKf\\/jVUM4qKEAqQdwMJZ0tfTnsgnetgT7V+W+0JiCTCB6nbTzOgoTm9EM49vJxaNMAlpbtuIDTcWhTGocWgGkbd1ZzN1Q17GAAM+Zqz0dr3ytiErBXebWBeWPOU6M\\/kZnf5RlTG9qkW6IgVbKE1DhtiuNgIrxXYsVD+DmA5Vbt6tbD7ucjXHMNXzMdE9wYf9GZYKkfceLPEBkFJUHQ3EkBgr7LI0srD6hN3gNZtLI2dUnO2sM0xwT0rVxsugoZIffse\\/00RbsIqmXSbuadvqL2wI2CwBr9DQHSk15mtKtKnBVQ+JYBN3eRuyGa982y7NgS8Bjwbr7IFfhhprP0Jm5Eg+yq59ADL0JBNQdexTz8S8\\/p6bTXwuEJoKKcp1gXsH8ccm7tmKoCWjCcU+TT6D8KuCY\\/fzrwPqnZXDXNwH5SiLsZT6eK3QB2IT2LMoiEI+JuCz9cj+n\\/BuGDVlwaZR5Z\\/bZMXzJ\\/ZRCKIXaIXkzKV+GMu+m+O4f2mhuaA0kvwAeT2TXVVxeFOkcjR0Ei\\/oNHPjH2w1tjJdia1hfsk\\/QdNl+14UPexMeqts2Y2AR0dqwmk41igQG\\/mmGRGZ7VRHVihM9TyizaYU8L2ByC7TnLnlY4FB27Q1ndiRBQbC3C25k4Txyv6m5eFtEzU60Zp2Jt9mzvzfVVT7FIwdt9\\/xwliKEBd7fP\\/gVLjPNxqZszGUtuBtXW9K6saLVNmRusDnCgpbluOouWZ86TeMmJGNU\\/gKbjKi53DqAnl\\/pOAnDZunzZIOH3HMRv8IdgfLGysjwPHsWxzxtP\\/pv15zHe0QxGRbgbrJg6sBABaSBFroyA5\\/2BK0sqUQ\\/e3TvFZUP5A1JJO82SEWugFMZ1Yzc1g71dKtww4bt8njH8YNKrBlL2A12Ugsl933qrbpw41\\/odxNnCPpfhmaZwx1VsAquLXga4LhAMKZxuC+mLAesieb9wxHvJR25IcifEKnUGSz9uv1z9mBT+6IbTRRaWioY9ZkxOECjhTaFi8B+S4D2jBiX+n2qXbG6ZrBCWm8I\\/l0uQv7qotqO1vmzOf7W1by1U5VSh0vQg90\\/RDfCfYRru7WTRhCYSLmmVozmHmYlP7xhxFO6nglLhM1imglLlBPvU47xyLvfilIEpasJtbFL9aJRZ7dC1u8SxOE2JtAy9wWEx\\/JnXse73ZhVh6Qfqcgz+jzDS8oASVJFWbLlyf6nHfU35TEMkKDtuZQRCK71+w5rl2iG1Fonn\\/uAzZYOwEClKX+ERMeZElFIn0Wj\\/yFljPOd2lzODKt5eZsgragMJgRXvNxEhRAkMHwur0K8Gc0BGzbXJEhYM2eeKd5LLvwito\\/r07FQsJyWkUE1+0GQ3Wm6pr4iy7Hy409glML9ldJ4Sc+VYtY4auvI2OHljRKiPcTOYIpWELSEaSVRpg\\/ITyRTGaVoq0Z\\/ZRmoL2NpBHNdk95DbjUv0B6SWdaFTEz3z8bXJqgqLKblGrmF5K5f4tcOgwBOQ2XDHYyMHdo+qFs0AsHNH6QpO+uoLLewrwXNq9QRBQg+ISVTi47dwbL03tE9ODoNui8+9T+JMb7Xc0ILK+krY2zzIxOKe8jbuuT0XZUbbiiB8\\/WS7fTtchK\\/vjyIes1UYE3P28yR4m9Wbay7CCs4LFMLYHnBXVTHXs4PCfN\\/6NW+yAOwsKIx6w9j2dkMDV0uYOs7CxbpMBwbJB6qKMPWh+jmw+kQ87GMIgz5iaqqId617327o4Si+bvWFwI35DTyd0uCy0b1tq7OIA\\/CIdba\\/\\/M7QRNatK41Yr35e6oUiI+3IZtb\\/twr5VN5KTXhluqjgmTYovTCIwDPcNLxldQT5iAPMb4TZTlFYKMjPAKLMtqlo\\/eyVltf719TxZJk6Ff9I8Mjc5b\\/nlWLQY\\/mixX3UN\\/IswlhuL0vjyurBEu2oK2RUdWGBIodPHHc9CYJMeaR3yAE\\/x+3MwgLDLKPS8NyH31Boqsf2CRb6oaadM2\\/C4EhzAcidZltTmwbbWj9GqtTlA0lg\\/lxqqrpaNfg6fdr0hwyRF8V\\/y3t4Q4WqBCb5jDToGAzec5F0Y4+1syajNqtAFn24unBqfv79TYVgyNqYOpuM\\/xbICi7EMOJa5QAVG8cZmkPxVuFZYLj7QBxGyWDj6CfhieMRHXkMcFXbz7h9G37j1G4kk+tFQuqnBiou+QBUJeObh8oSgQcJFvdBHisy4PdSOaNVkyPU03uqC0RRnkRGOb9HeQxu1\\/jgQAO4nSaqVdQbQdqwBcAchnQ9ke9xi+7W4yA9VtH7dfqZbEPqYTffe92GbEjrMz2hhK2kwS94XLFMPS4R50AQw6aaBampNCfzakB4KJlxD86Q5I+R1neGLM6uj72XfCUcE4D9qk8cDkwytrfAaps0M5XNHleetTLSX6Y+l40H+zXFAvAcACdLAyYULIjUwKDYW0U\\/sBqCbxV\\/x3661mC1\\/tJfillHDtc81geBbAPrmrCnuQLqnGjJI++SF72AK1WTF6K6MJMHtgNRTpLgt+RUMrgrGknXUixmuXMPRHzluhpzVmLxMhO7\\/zu7piyRdiJagPDT3tlnsZqx\\/gkMYMFzXNren4iEQn3MY3\\/0mifWPu74L5FxcPJFu566bBcTMDkiT2ZcUtD3WSF3hrv+CX14nOsvwgeikPCP\\/phcAXp5AcH5BJnpCAQr+xN\\/musqWVnWpfWDsyHpRfJ8yiSLlfgVKKY3MndhNFmedBCrb5uOApWAov20jNSAAbF3h1QNTepdHq7uL1NKB4erc02G2bvjca1vDKWNHbLHUSzvT0rFty9sZU9FYJXqXFJBvWYGZnZ2lwWePQMkbvO5uFhO8uUBotK2DQ+GxyXR5I3J08WmTR31usHyGtuK6iMiET1XJzyTe6KPmuwtbjtLjpFXQiUFBpFQo3oruiyUOxx0r\\/G16g12hYvZs3OON3PrBoIPZSY3KWe0HqbJvUhD+W0qVuSaEARIwmtV8Scdq6oaILnsZiCyQGoS93S4OnwghAtMFlf2l0Iwonf72QyLL5o\\/mtZ\\/nbjBJx\\/XYMA+kK\\/ZOUxgF28\\/8IiHKFO9akuOJKH1i4rv8DSg6c26ad6ajT5udgbQtq5hWWElhXhaE0JtnKTImqD5BsEubAyq5Fd5Q4UUGao2VNHod4UMcboZDoyQgao+K8e3rw\\/ZSUuqaXWqP+78uauOIPNk1XdL0uQ4qjsNQk6qmhvHd5x7G6TKt6sW+Pn3AqXt2FQsqUNJVI9LPh96gowUgH6UI41wRq7\\/h1itc+ztQm14\\/Uy4d+Z0pXdrv0ipGyvxTiHXnapwbZSqup7yCdMAE3Wjm3hZ9yRou79EZUPW6jVw0Y8rY3McaK3i\\/2uQBRdhxsjZ9iAbdAXcZJ2XRjqJKxUAzWqZHWVkIajkKvxFIywyfQi2e1Mb8SZ1kym3wrYC\\/I0XQlaBZJRPOwP7FmYoX6bjgajGqn9uVyBegVPe6hOze4M98q1omrt+s3K4dVl4rbZxiiX60L3OULqWQpFV\\/WbnY+QejTxKhZPlJlTAPazJOimADRx5VIclmpa1RLDXrVfcygftxCsDoNUlfSnw+s92Rfwt2wzCzqBUkFdy2dT3wEUf+MjKCIwZf9nirMK2FQtsyzBk3NwopZo1qRcDUdK3\\/Rb2Navy2V59CFJXv8IS5xaR\\/2E9gxbayIFfO\\/JrySKBFLlsp6u2kTL+hpS2pf1fMQemCz5dWJCa68HoDkKd40zRs1M57weMDP7HimstaNm\\/RQ5iVWD\\/GEZOPw5Hk3ZWkUVRpurg6jAlxrFQCg6owCsnWrX4IDXfNgLsmTd8IlBFshW236MU9nVDcGXuI+urqg1\\/zucPflM+dNndSLllIKrbtC8n5Whj7WRWr4ywTQy3hZZGBKjFKKkXbvTpGLsKIVCC4P9Ex+OGi+6\\/UM03P3YJdQRJ64jSWw6J9iWhOe2\\/R7VgZ8b14LaRgg+FsqYXtGINzBTB8ZS0KaLC5JYBTyrzlwGYBV2dfNXSEBXeMJOB\\/RGpJJOwG3+LOTiTkzw8nsQKfKBxgrBTT20t6F42cbP\\/vdUAj3W25EoGOdQXohN+VyU61r2yDj0EUvK8\\/1qdVb9y9Bs2nEoZ4EHrdTWz1VwfxssyF1To8J91QTxNAIqwx0mZMFss2nJ3bwfTJT634ShVvgpy9MpkwOELKHs4nU4JfXv\\/9V4BHiqA985eiP7OrQbNhrw4f9JvD\\/5mem60Prj9eCocpeqkrhvSoMtFuMHfNVW3Fv9uYvMAJG6bkln9ozqhk5X2hY+ftxc3Dr14P42dTcd0zI5DxoqN6OKiAuykiBq8FmMwVKJom3GejknSWe03+iUx+tVQ0pMCm93TjR0UnI\\/yfXeKcy1ODR6N4C104udbCvqsjcGNuuvFk8DUjk00t4m\\/UNl3Uzx71Hyh3ZrU08SW01RIvG2alvJ5wZ4rL7wjgpyxpj3RcQkdI2kV1DqeD3e+bcfD7GupXI4fHo98onDws5MACvC\\/hkgLZH1E26gtfmYvySp11UMapm0KRrvc1jDt1LyDmvkKZXdHrJ2xHfp2QngRwsXCj6A6KiFBGz5bULm7KyBE0lucTZlVqZSSYCs4e\\/cuHBwT4By1iA6Q6ejzoVZz+6BfWmoniI03OmoJ2CozEdxTDqgEnHw+inRPWB4q9qRun9UmQSHePORg\\/JChsMF0JB5l+a7oW71uXdunjYPofXY5gZzc0A5XS3uGMKfejHzM9BSLQahknbRHRDaRj52K4Zf4hYoOFWDRl4arvpZbtEG4ONgPu5pgYQNP3NNpkjsLokfXVnafLjUvDsKKVw4B+QN2WwUmXQ7a7wZxNWw+d26wztGLspfT+oEYWWBP1ZMg7D8SfirkLmRj2ATlvDBuaSGuBoJ1I1i+NiSY0oxWQiW2mvKoYW+TuTPd9VY9aH5qyBGdjFJ+5wFYNXBK92E8VadYrOi5ANmMEnRLSOjKzpKLc8BFzs9DCxzqr1sW\\/scsiMyBJw7O61m1vIn2YG+dJTiM\\/Fjeas+cpsqWaYMHYzSAEy0J83kzi\\/rKwfagBrFyn1UGrsEu7jtbjbpKZ6\\/PAlwYVHlJBBhBmwYShR\\/FzFfnXACUyW+ZX2njjqWU0ziw\\/f3aBCvxncSaA5jRfmNfFAlRuAH9SnkB43PFAgUtiF1774yY3pAeNO22K1+ti3HSm1wgFE4lcj\\/XhFlXgqdZE277GBOPB4\\/RXWgdONmubPfUJ8S6p7tPwzU7GyOJnY6tHyzupenWOwlpyo3aDSVpXHlFw9qK3lfBJNCfkIyzcxLlupAxh7QzYARhHbYVr8PhHMF6Km9OyMwo6fY\\/A+dKWv2\\/21QwMzP0KIxavsssgMsn+FmApsKsS6cDwNa5LvjlzDOADlbd0PhLOMKQWOnSVNoXU4XPpCoUheyqJOXPNJndVuATbCtRUV5A5DYSp4tv0jU9NnPWDHEMjeQpl58PwMNKPx3B43\\/0rmZKdLd32W5lCkZSqgtVZQVLdccSvlKEi0TQ104tnboYchzsQ6YOObNaFAidI+OXFATLmQOM3qb8zidIO3fS1Geobx0BqNsY8KsUdNty0t9XbAKP3cD8q\\/RdhnfKAesKUHUwyx3iJbN5KfcnsUEHB1zOS2N4LoH3kELN7TQuwOdWO1JB8U+L8rAoJ2dED\\/IEZ8L7CYljY\\/nsTAJ4Xa7wbPe6yiw71LraC\\/ssK6iSvnnVIIC2+r7pY4GFDbLIzyjeo3p8caJcwlwrNtIDIfFQ7PV2xl29IzX2eOX7vfj8C8xqTbah1UVd2H0ZIiwOhmBdbFspwH52o\\/ycrKvJo8SO\\/gl1uTiWVEzmzCqf6QVejbdyxZkbhR+K571Mk0AOMxsQjXgF2Xeb81B4KLmLkbEZ4\\/mbHErSojdN0tF+rkcnCHLUSKVR48FxQq81uyG4W41dOg6v02KL+wtPhV+teFIWKCgdnhNDkQOBv61\\/U\\/sfhTiutpo24yocAN6rZ\\/VhSIVrMSMU\\/zDbOWX2jwlzmkTGZRGU1EmX7DokqyRCZF8NRedN1AFh6kXNomjKObKkqfpJWO4ClpcobI8NKpT9s\\/dbH4D3VDDLFBZwDI7T2M+veMzifqRA3hJBKywwKiG6+\\/hMyDPbGvwTz\\/4BpR4WoT7itzSDgDUYmFg57SyXgPxRbQIZKkDzEsQ4IOoekOoEO+xgGqJY7ADYrZr12wtpWqeYTn1IBVuGM4RAvzl0fIJiHMKKl45hE0vibSEXuWqpoQehJ3mWI157MvMfBJhhjIZzBYD30DTAsDe+Vk3v12oKLwOprnrGCUSpYuPeVLBCyLjUVC\\/ofBXt619PSKvArikBzvmnFzku+u9UZ+zAVUvFfGPuGrkATPl8bfx9wO60LgiHA5Q3yzRwJ0XyVx0SowzfhtayEY2+TdfD+JQRsrXW8WTEl4G0Wk2bCyH8prFlH9sr0Z32H\\/LGHQGa\\/pJWXuwl3460UyY6aN8mMRm0dHYlqphNSkjoiync\\/\\/tAXcF3kTH9auJ1myAr+CBoaZqxE55JMmTxmi79oW8zs8Pa1xi6tIy+5xNjP3WY94KX73SQCmlzayS6D99tyu2U3GIhNyGYW8ywX8w\\/wRm7Wzimsseb8JJizavWsXzMZYU7TxXohEBnMkUJVJiz4eJhoSkZ9jekUIbLkuLBSp+VS1lvG2jk6KVIoFJF0xNo1quG9mE7ys7kq6krGWM3VDkE0nbqtuPyC4YM2KlFby7XfYJBOW9C9hFvjZrRxBj6jGw0NwPVyYlcoKb\\/GmxfMMFV63+Gvjjnyyo\\/nRsHsyt2+EckxiXEsS6ba9isjaE49d57Z3kHc2FPTbreaRDt9zSMxQnNCe7Y46LUq9zMmJ22qtlpVOGzMEH5b9qYJmRJ+NMi0pK4AEHRuHqQcavcOfvNPpEEwS6PUNYToTTHqa6zWPWgMi3myhadfFT0poogD6b\\/rcMZjzoqZJYi41YpPRAtxJFbFltKwTz5S72LxisVnoQRKE+Vcpqc+LeskVdLFS8fqqcBS2vlGXcYSRVjANa1TUjZDNPlIdyBkOSwiypLpQHasAo1vLwhjBadj7trZrs6nNmCRTSxhg1NAyAsHkly9Ouj1Bqop1cfeW9QRJ+u8vhEyWPHDUZtB383gQAh8QIIAxAihs1sLeqRTPvorlsFLc8o+JsTXzzlFP8LT1OViL\\/JG66WQyYlcjvCIbV52D5\\/hvlrCiwIuV53iN6K\\/jylccRBM6mDHPGihiSyugyK8OmYrXwFyZ+bRbJOCEcw+LFKvm4QbzPiiz2CgAPbao1z6CryXk4FjLRVlDOhtgW49AvpMTgsCUY5rbEDT2jPMSYiMffdizY5Q6BYymCoiuv9SSf6+nrjuhUvRO\\/AFVPC4ns8YbglCv7d\\/6houflEpb5Oma4UFLgy1udoXWuG6cKm7YTsOV8EAh\\/OVXFRiWB7caohR7wadMUZmzOVl+XbJ19zX4IZNfdVkZ\\/32KOQzdNn\\/FbfPvtubun7he++3GIZLLmTXwgExpgdiJaAnbeywvpMGnFe+ywM9vz14pHEUFzujZ2a9I8K3cySIpJT8uR17qSi7+g7b61RKx2MfdPuvOF8\\/vpHlkxxQZllm9tmQrwqXiDs6+JiGhSty8jO4Rwu\\/BhkdVsjUhiMrHiEjWogmrSDsr4DsNyEcABzTf0Cg3Tl\\/6FRPaWzpXQgGwI1iyq\\/INn5HyIhJ73zO\\/Jh2q9\\/2dAPAIOFN5xKmw3XRMi5GoAY1vBoLomun6m8jIHhjVuTull9pma35yF\\/U+MwW44oZ1nalYtFqPEeJKbsnfHkCUskMLpXHiK13JfxHkKJn8YQDrxLA\\/Vef00P10dEy1IWQmj1OMBODmJwEVyp4XXiuGqjWRzlQ51GaRtGqBVt8rq\\/CLwtGsLt9luTcDs3M1FE7dmCdC7os39oKl6IUSaVMU9GxnicOragM\\/Dnhsp0Qvk7Lw5BfxFLaF2Xp20WXX1jED1LMaJOHmBc\\/Kdv+yzpYCD7Z46xDIGx9DKplbqsffGW\\/u2ciIReXZ4MYwhiTnr69ZjTz8eFrgEmBOMBw\\/vA1INUUh8zQDcmbKMZxBttSX6gp5T5i1gEgU+fcXceW6crPRPIFspnctcmn3qBR0fjCCMnmtlAEjdiUU2rg1XZgvcnx7qBecwuxmQ9PlSSYE1c6vv7BCatl1+eHxixJRYK35bvGV+8nR+6Y2XgwaXn3F0h9VQvCOP8psJz2ytrerCP\\/L3JLQAgm1Yivy\\/8xrbj1hmKoB+xCDGyTjqfZik+szIQZS5Z+3PBG2yVokDltzGhHIO5qWt7aIDLcuqxyow7iRPrg0ecRGrVCUHFK7IdZsGq0fukwQxbLoe2wf0QG9Q8gmx3OjwIobxmOfNcn0LInHDquCoYjbVD27iW+fQat9HbXe2fcE8YpAIhxXWWJBEl0gfUSI1jKwydxyepxNJDwfctE15K65VQPxpOch4wUSTboPGUiFO8LcYNDs0r\\/5Lzj4ri+rHkBSVQHWqdV6BNvSJ0mEg8XmOtev\\/cWQZ1+80Lq+RopnXOvTy3qugH7fp62W94zBO8tEifVJfM0Rn++FWRFogbo6NFFJRzSasGxoDBJI3Gv\\/qfBRbFn1DMlVeETmQUo\\/ClszmvsNKGs8Hp4WhFgL8FtdZqdBmJ\\/1t3n8CooFo\\/nGP4dXCF8IMvIOfkbkiw\\/eNP2jdskNwg6NpRcwCgoKBKCeWEwa6dwg6gFKjIOEX3010hvM7ynGNEnS+z67n9qTiQUzrSKay8zsRxsvIFVTwSyOIJczUV3yvkQ7x69KzeOSaAERzFvsXid9IXyg+\\/VC+31qG2nq0E5NHGnqxctMnF7HV2ZtwtKd96i3gx6TX8AGFneCoBjcGrVZ2CZmv+6t+Y0bXzHsvEsfyznMO4tr3VLwNCxG9lsla\\/p8D9ZIze3ZxNcL\\/Vh+zD4+LaCs9TyR1E+DE4Pxa0M\\/wvRF3sheDWofMBrlkksQnF+2r7nAnI6D1sPc6xqOy39rfhGR+b8pELDENmoLi5lrVgjlhDZzq6s5ixT+zqcOODrLxqxNsdUnRXoCsq5xTOitJ+6upQOZGpceg9X5LM1n\\/Y1si+tvH5gkBeT\\/Qj+JKfFlK48lc\\/2mD29CrBbX0HgMnweVs0dNSi6MW6poNuKuxt6NDUQzodjiwrhPYMDgM+2ISt91FeZGqjKYbWHQtzB49DUAhiTDRiGAXV1z3ewIHjwdFjEUEqSfJYehTchckCrw5idYwkW31S2UtH+GYASIHeKncdA0qNWu6V\\/t5N+PVmyZ4NdFVNbistwnBEID5cFGnAdWfs56BZfJQk1ti1lnYtD2ucBGg8AtQFzt55vE+XsLDczcwZ+PjA3cG9C6q2g7xD6CppgdAOQzS\\/lOYYG2wZgAu1Vpekg06LLkqFi1CQiL8vGwEAjv5vD40pXj8QS+Vu0dv0auKtVOrm3jzOV\\/zh9CV6FMLvGPUyYmaUoz26NHdP9Oqc4Z8eXfllWz8zGWMf5pvoQONfwwgm3A6PrsHWDVkflj1GSJlCKrzb98IqvyrFJigDRiPLC2M8SCPMgdqbn2\\/ET+WNytuIKAGYg2cDqE5pFMh\\/D9cx3vJGYnv+v8AL\\/itADHilny0dZb9b7OsRtmBXDjDNmUeKoTnYwNPlUYMH5qmvvodLSgvRrwf7RaqM9B7oxqDkdIRqdwBUtzzOkSFI7qEDtG1kOy1ZfBmZjCmL5Nb9F1xdMNE8WGaVVg0WseINC2RLxTWAkCWjyNO7Bp\\/c\\/nPGK2reWLxJh1RlV4gSHs8aFdSg\\/RSuUIip8o7D3xCL4kxkOcv8a67+73XiyDw7FfUoABblBdaVBBAP\\/blbRege4xAoEDikvbKeeWTFnxy4YfwNw\\/4IJMAg1k3rBi9SOD1A3aDl8OGjf2B9HA59WzyFKgRepyJ+iSW+aHEMvg+rplaV7H5k+2q5tOFY2\\/Ixol098XDMnUhYBCc6cYCu9Ra8YdkNizmqbrBLEo3s+uNlR87V1YI62QTrAbLlbpMp\\/K6b0tR7kdYEgfOSa9PcTqJMtNvokMa+KiRLGIBD\\/46GdbZ6ui4EOBTjq8fV6ydT7gDh\\/7eZ3uZaErGnyNctNzGBg+igs71g5o7vx71BLfEcYN\\/vDlPa4g72BPNgICmPDq75FhkC+bMv0ZW0QMoC817o7nDl5dQMSAU2lTDYyZ4GDAmDnYiK8c1WWLXqQNEg49FCo3El2Z5imi79eW9GweQYUgGa8WDov1DwcJl3VtNhpCDROCRUVMvqwiXdiFceZJ+Qkqv50l8NC3BJX+7yq4bDZYXTnbxlWs2Q6CoVqPT8ZvRnQP\\/IH6q1AOFzwdHp3T\\/1dehe6H0JjEvrrjfNKcWKjdWwouYWsPUpNTyeYrZC5PCiA+3a+31wvbXkQT2rVI8uc6gqlj5BH\\/2vYBKkrbzP1J6oWG8Rwn1Qd+OzjeCVlq5BDEv17cIzUSBFDG7aL1CeAoEeKPVhxdiLhNVc73dQ\\/j3Po+oZiPHgXfjcgzTCF3zcA2VRR8O9yD3DGlHhbvh55sQ\\/E6VqmjtqEEBkENLFe+0U3aqAHL4juzciizgiA6XURYGBZVB4CqrMcxKbu\\/MFnMl8uysDJouLzR+G3jKRPxyXxeN6r+kaXhwbm912tpXz3gytkbNbICzaolNmJk2\\/w\\/SMsefZQpqv8UNOUkCtqcjKTIZCZpSnRamOuVTo6POQEVlaLnI1bnNK+IsSrHHzB5exW5NZuzox4ApdiM\\/siOXakbRpxMaQOva0JObEdanBtOmRr40vSWaG\\/ip5F+ng0vP7T5EyPVkGaMSGlnjmTm9Ny+YFHGy2ILt6wagLL04T8LkPUvhfVzEnHSJVE3HJ7AsdqZ5w8UkAjrdL7JrmSA6SvBHfRR2s1Vpy1dHp6opugUFo\\/xnuDpPhUWNE6LdO5tsv5qrtB6Pun1Hx4g4H2ZIlXBlxemg9yoUCy2jbs8IcTGddTHBtx8Q6Th9dT2iB53rcW6PoqieXZmR+kvIYIeiPuSiTC1geLHAF9fIPNPN5LGLHW3u6Dt2A2oZdtMcpzQ1kteE5ICyc7qJSpoo4jnaymTq\\/sFOZXw9kg2jlNuW+vDoYU6itjKQ+a4qgBSvSi1tYfNfWUzvAwW9m7+EO+478jYyucsJ91CTYHSpxwUUk3WZJpMzZF\\/i2m769RhxSP6s0BuYH+ApGO6n53GG4v0v3FCm0jkU8Zi4vbgrWQJpSrye5cE9+y9\\/jttqY29PERMIGK9WEi0RkJH2fPWtBtISxzyZoIaEuwbQOMQ3f3h+\\/Oi4llABPsINyjW1XCl28UW9vHSAvY9MZhaiDjoRgmL9416Dk7WqmjVtMPmKTnC30V\\/\\/hy7dgq75qDnHhBwjOK9PAonBS2ceWAXT64oHSgpBz3SMBzpCD\\/Uejm2rHL+FSfpe3Ftrwudth97\\/ue8DE\\/M2qNVSz1IhtrIVlfhPnLnNk4Yznn35bHkaIfI6HcZVQmfi0e425W2RO8oA+qksVZp18vP6frozuEKwRDnck6qTM41DYYfXQI3X6p0hpJ4ymXewtHprbusNGe4PmJpAURATjI\\/9cBXMmKNQyXF4rn47kHPebvelgCNTviKYizG0FkmL+PuVtKWS58eDIDCxc6zWN9EA0VxVTq6ifiaHvtktitFSyOzhwd97eC9JArqXFmn9l2XNpq6fuyum2xttKA\\/87rjLfudq8x9ZnfYPlVx2hu8zckKSjGE0BDaNKUXcQ+o+8DduvNKdvIhHQUGON+nXtr\\/nvhHgK1kHjJ8DxbAb6ffyPTFpfjMTN0KJB\\/nlXRr5eM1kN5LjKTn\\/2egETfDZbytfsa7F5GN\\/QrEksirDPodbUpmsfKNDKuga8QsAj+gxL2MZfZxrgXbFkpewHyMvo+h1YG5XFhs6MGTPIk1dmP+S5vB6p5DT\\/RlnmTK1hujheacvkJGZZIE7YHJn1sSvJfM2aCJ7y5XJZsmrrVizdjjDtY63Qp59azaERW2uzCXVLCAvR9A\\/ZuXzMuxwUaQ52C+jo0uxPx2EtRY5DYaqa+n7UeIpJ9GhOdSwr6FO2coRMga2uaeKH9vzAVa7mbkrkZfFEAzvF50vMITkgWkR+Lkly41bjggx8ZesZga55dgLOSf\\/s4A5HlMuPO2ImFyMmmZBsFske2\\/xO21Cv6+x55HX1OXD2LKWU6hyYVMuJWE\\/Sb+KM+Lg2AGSjvWd2V5q5dP82CHAbdChv5Wm4m+IHGpU3a4zHrS191sY8e7XkROXzfUHYAIG2ybfv2KKxp0UfdevAPisaLC7X3j9p3QcvXEO8RooDTQB7IxziSYQpU0Ku4Zyq7Wc9X3RAjdv51UtIMvihiX\\/vQSu1f6rKJ40ptZbTiKg0mrjnPukW2+AMHUKQKNyjFuC5RF9\\/epaI0nqXaXlSJ2kh1WPUBmiuyojdI99Kw2uEPIQrFjQCzC8GfLA3Mr6GJgP1jGkIWjg\\/cXW15RY0+XVoTKgFY7tfCnGw7sA0z26BEGLUO71qlQe21xnBbyMEFeswL6mfvw8lKcydxZVYyTAeEyPGVXJOEkdbMHZBRBTob+08LPZ8pquto4A+xsOAKBnFXmPCyYKcwlct\\/ctIzTAFoLwR1vNt863eisrQyZi45WzxJhBnakW3DINaOIdJxqXx9KVcZ9cXiTBt+zA2XqQ2Yr0RYRMpigyofxbce0qMNZ2pvDWs6rtvVeLGNX6pNdJiILzw6vVThtsxa8jMl6SXvdOAYgJbZnqaaf1yGEu1IDPYL\\/hi+WSdJ4ao6wZgtTrvUD71pn9lB1D5GkX0a4YOOOZsRM8qLkWZjOonJNGV8AAwRABV742wfTEZL0OXASjt1Stk4bW9D7ic7tJ5h+JOj9qknyJnQ1Ga0KaFe4mDyn3iczQMVGULcYA09iwL263v98wIi3u7ngX7DH4Vv\\/IbjMtLfE0EscCHudibBvJlzQnPtFSbN9c0ul15ZHSUQ8uueDZhnr0aW8lObkMOoFFHjoqNYY1psllL1irwKWzNxJZX1QlhLujNIPSVjrTqmYCld9vKTTw+AVCsFoumJv2ESGLkAq+cfx8csu1I0FnhxhnMHbTDUowm22RirRSc8AY1ElmvfkWNwsHcxiXNx5j7AI7jkEK7ZPOeWaXRmd+g8wrjwgOyC1G98FtxvFFbvC0xnsuQbxh6p0sr602jPfUT1n0QsoTUJ7iBzMyvW5mG4nAmXuuWsKsLJPN3oUodihbAe\\/WNo3WD4Divw8ADPMZO8DocsAMjpJNaVVgVU4n9jKu4O4XtZRvdQ4ii6S0ZWTz3K8UJxk9GA6sLXPQoSOGppSZwrsVJEDDGDpP61v\\/2EIcOEE5\\/ZMdYLbRRO7\\/JsiqcosyVzwyPZcsZ1+CZu\\/yZqOWtlWUHw+vhE2f8b1xqmFS4f1IKltNVRFl+KM\\/5WwShAPZUX5RWUguCqQ27ay2Xh7744l23NuAbmUpftugT7hCtDlmXyM5wHVQC+gqoLyAO1LD5yo95jq9oR2HRN\\/WAv5urgNQAl3r\\/dN4LHPyZGE+M48Olc+X6Z8x4\\/qlU4ttrPtHp7UDhEYO1pD3QyzYzl4gHgjSjCbp\\/6ygN7OkZYlULGP5SuOGPWI++lWOThMKTyBm7X5ySZhf7abPq4crH0HViZaFRKoxza1B2iVLlARE7xP9saQau5Nwt0WYv9mzR3UXhKNVxuVqQnVmRm9+Iq4AvqB1Tg\\/fNRdw\\/AP2DLmcdlf+h1dqAmMYUosp2pYgNZ14ysbz6++2tuHgk\\/CKTxQCyBLJRusUTN9jlXpkmTf3VwJ7ayMt2Dgs\\/ExPTXfCYZdo3fCtfs4ugr6nz3Os+uOH20q7DsW9+DgL\\/K2Hfk\\/RUfwfgY+bA3Csg\\/av\\/cEuwcmJOdWBwBsICXmjEuQnmIJ5wdkL60csY0ucgfRsJSL4Y5BCw9ot7jUSk0H13tRyWDDDRbVBOlB9QDGXB6EKxZIosIFdHCFDcYdX1gYOGVghoWRb3H2nUBFpA+t7CmSTlL+6OzpVxm5oPUhT0+ROf84kMMtOZmPnOe5DwcKMY66pdepdKUVJIqg504cyx41NLu4id3Bz8gEzpdeOrCdJq5eOC58fb5Aro75UMLUHnj7Q3IQjCSO5eOx3wDqoHF3lXU1m8AIyuB3Dp2WBgjVwC4rCWQLAUDb5nE6ZklFzaiQwv2yKlGybF7XFPnMhlusAnl9+kdZvbK6NYjOYIQKh+JUSmKnxos\\/5Cio7RrEjZwsEBYYdGc+KfQl9ynYhuRuC9pnjYBxOWuEQPZpnRbGQtSTVCPN9AN9J5vbFUGn5NXslisTwF4Z3MSG+SPzwsdZtRshFm3vlTFPzX5UmMlHHCCCYVnej0qgUBOqMrjKFT8cTBxLlEILjS18YRN4K0MkdS8dZR3s2WZyFdnfxJNE2vDRDOO78XaoTgcDayKuKhP21ABAHuNF1K+kIRPCrTG3GCnt6sH6U\\/xhCON4zgAm+GZTfQfF4AJvWuVn+C9svd+Bos7UKZy+ojUKvxTe\\/+kQn1seb\\/iasSnD7Voq+xluByX8qKyz3aKa8YmWgZAV6SYzBm3H0tOWmGWiX\\/0\\/KxY9vMx+597Uqm57C6zaAVMY4\\/2\\/uW5PM5jkIpABOQsZFwf4mtNVBmPYaVdGxB4YOAg0WvUf6zThtFCwuTmpD8AJ2EFz+M9a3M9VLwWmlwTt7BA9Cb5VSVFo0CjtdFIbqnfQRwmq67UKiWXl\\/Nj1Ph1r9oy2UmxMe8lV4ZpHMC1+JcAskGSlaodc49CsUhD33xJ3bRxUuNgyTdxqFazmAi+VihWgWvK4Th626328L7tYDfkjHXpUaBzjtLw6gJsiATXdmRikEapKmmFvdDhl6ED6t8r35mhu9VgnGN4qOTV9FUPE5VtkFykkgBDDSrzgnysjq3h\\/xoPtFx9u\\/FxlOxInRYByuj4SunIZrp+p4q0Jt\\/etCoLcayAldSIVO9yYWSffbbzeoRsDWdqkU3+P9wX+sfZNrWqMkOeQzCFeo8tU6pbgyGP7Pq4C4T0iXEaoPAnm\\/gbitVFDg1WVR8R6TQVY4Qm5tCsq7eJnJk6fA7eSnnXAiqYjAr\\/auvgk1oGvuqsIfKLmhBugR2qcQK2IF4f9c3xtmJqh5k\\/8zhNCKKnhWxNgA2SdycuoX8\\/LaggtavZICdZxuoCeR9WQVGoq37QbpJSVEg+Lgv1MxyGceiXVokh\\/OxLoGB848Mz0m3u8jNxda3ZLJjsLmcgLnEZVgJ7hSONk3uXIBb1EPe52auHaAXFhshBl8kkOGLcwMe0zaVk4O2bI4KPMkcFpztmlmq3tKtzt9wVH3NfugR\\/XhzsuLX2YyfdT5gq1SGRuNJ3ZgcvCVUdvzFwQavB4tCmXF2zo5IpUzNfL\\/GV+fn2L1XGHtClUpZowc1c2BGNyn+nDT\\/OhD59EbHYEvHqvx4sBHCbXb9E7RRooW5GXSeb5xcdkpgvtmkxS96oPozbfZYkDNKIE8PDVahOO1hPOjpFJmgHH0DvsXcTARQrYkbakXeWyx86\\/e\\/gl9JXCCUyFETgrh0YQBu18b1UaMW2Y7B+9dlMjEAiE+wainXNF9v+uJqoQtGVwMgKfhUjVw+KylMsMvzvXISA6pJKAq+EbJujBcArPhq6tOkTkVwKTSXuQvBcne4tf4YB5rWxnRd2Eci0nZ\\/iRQfKEG5e8KMrHRGb134z7j34Z+vVoPU1v40z5yIGIwgd0ZuR8yE\\/Tqr7oxrGlivYaVUWuU9tks48Evz+c0SYhK7yhgfRWV33qpyb3zqVbY4EBJ2qjTEfy9tk46F2WPXBMbMw\\/z76Io+aJd60A7sA8PTk9loPxZFG4VjYDjE+Q8HYqKG\\/zLLIJ\\/VSxdWpRdd96kV5vIoKW4c44fdDAAw7XR0VXKnJFJW5fbJhp8szzr89sdicngUCAWWRq1LyfdPcyRL6HI5bLLvlQvC1+C9w3zZ9DoEFmsGMTskdQy5reLWgn68vrdf3CKPw4rzyn7AsUVJbwpUNBCQ\\/Q2xNIrw0Mpvuyx5NJmi4LX564iQb6RDhZgnpbCnlJTx\\/+pzOOw1+BcPXtwXHcaASuTL861qjwPwjZMMTCxaAfzUMI32fCuSX3OnDxRiJYl8qogRIFT2TVi36liKUEETBpbw+e82HgjTGluGUMVDh7xtxQ1CJjMmygLRQaDWIVtemUEXay0nLrUN7Z17\\/t31FpE3NEoZpIyirVXX6fSGaPeeVzithrpzau+xl07lg2eCIWDmHVnGSTPfvBl4LnbigYRswsDyaEPevK4qEP5TOJBgPupk6M\\/ecvMPMRBTKvXSoi9MIPv8g2Xyf+GVrQ5enaDx9pAzfLsUCoSqHWBnPXWcevnADABZ7IUq6OyVNspyeNKkgKq0NYUPXmuuPb4eBt0+id5zZXje9xazRW5tlcsXE0PTtV5qbtKEHQ3E2EhQajoOn45IETYp8lASIWyHLhbEdslOgGN9F\\/jxlBGJAOCNUjoXkCiC7U90p3dlLHwFUnf3eZRonpVVJlNKvZgwAYp6KK8aWZm7eRFC8qHg0w8CCloEZocRyFlSXpoLUHQo060Xew+m\\/BXQR2i7pHK3DLOWwHSSWbSrDRN+RMg2IXPqR9XVqgcTFnHrKfa4VGoGyxwJGm\\/kT30smYdxCoF3Uge4jHkxXO+G0U5KE\\/aTEp6isg1TvX+4xUwEojWfu9zgpCPT67GdB+2StDZjPnNBQE6jTPgRY70nGu+8CHM\\/WL1TMNu68frlHkrF1Lk3L8R9fPB1dW1wrsjbTMXiQZzn1OrPES1v1CH6lUmGASla823MDRZi7dlnF0z7zQrNu+a8zFxUSexSow90Vn\\/HQq6jWjiDz\\/FcZT7e1eHxNW+NDDzcp25U9cmg0IAbAN0d0ZO5rVeu+vwLVFdTUfuSzYYv3YNbovxZPj+5D9SLpSMs7PmnpUyDF286\\/t4zEgox94RzmmmPA0eyjxjKGSCYX131oY1uCUdXxVAGjoQ4YaU2zzUq6Ba1YvKpapBW2zEIuK58X9gEXoRtOqcthjW1GFxULx5L+ck4sG\\/CK520B5fIiCznu4CasrD+txPYf6FdUZndyNnhTv1u4grqDIpFWuu+vKtqPJC+dZGhHKcMft2y13qoVds11KSCNt31uaigcYkwM2LcDFjfzReafNPerv8mb0hjBrE+JQuyrJ+WVMmwc8w5JKkY43sQVhVz3udRodYmSLdnHWoINImkmzcGntSRrXw4+P2K5zIKbdXMZ0zukuELDVa9vJOErzkfw5sOpOEvxL9wS5tfwExpGwDxViG67GAzTsRUk\\/2qleuEZJsKD\\/9svDfBCpXaP4JfcR5ZUKkKtFbVbtBZvUFGVVWc6k8UKIeiOf9AFe3+pX4UN0GbKPGBH2Lg0Ttub837+1jNqQjl5Y\\/8\\/72ZreucpWolieHSdSB+4VpJEg2Dl2pEzvNVGHpOwS6sWSFIl+zUXrO+hjvwC+o4Xo0vXuwjmIvrm5hdKI0+FCzCWjbnIrCL2lJQsHXY2GOQ+TU8M2GpQWvV6oyRgF0XQR0GHdMogI9aH++PzbjQQg1WY9Gk4MMecAfIKeIgf6kEf\\/PR63YHweK\\/WyxxIyQhZ1NTN1MQV7kbMhB8PHEe\\/U9SatQQcw48VNBdw\\/m2x6WWhYQTokBDa\\/p\\/h1tYsYfYsYTldSqPlJdWccyhrij+uVJBBRh33pxlKo7dKjNBqqjblMxoVFxOQqigjKta00QVEGbNlgboYWBwsudM3Yts2XmSQn\\/weVyTPwXTDcms9n\\/34KZYwQDzzBY5F0KHNWjscOGEWFzNeq6g0c8xeCG4pSB0wRnzdYMJS2lY9ZunW0KHoumFFUTn0nkCuma35H+7yq2qmKD5dP7FRja01HMfjQeim80LToQGWNImW0JguZVMM8uMiY59BEzqEgf+VrYbt7eSPiJWDShHI0SyoOQCyg0iPuJIc4hTWNdYeHA1djL0\\/JOWdH0JfQ6NOqoEIViRzsNar01vaPlS5Tai\\/z4+3OS4GBQd8bhbcC2Q69xyPSgLaXqiZ+4LLBvf257Y0C40LwXuhG+Ucgqoq2B3mcbrIz7MxSfJ+7StNwrBVRLqKjEQ5VlZkqpevCOAi4cCnHPQdFNr7Rhd7BnpvybMEsKB7bCB0kcAqeS32ewaEmdPsA4Ks3dA0bIQdCQt\\/dnWVBDaSp4pZ05aco\\/egGdbg2BIdu\\/wssAa5ijff72\\/7edazmFwb29UxIgPR7siDD7lmhQ1YWwHDwGya6WfY3O12t3u9W6WikSUh1acV0+k8vChyv6S1YacD1Z7pgP9VItFhFqeETKDDqSyyI48dRFXlMSqpjRvmsBFBaizmCnv7yraj7szD6JnrWXsl7CwMolc\\/dFxMeog9bRFFUdgPsDl45C\\/LjMq9m8c4A0VAnVXoZeXq0W9yLdu85md6nvzak+ty67cqSu7UQn8Bynw8lnq+vueISbo5OSMDSGzA9Jt1xaxJabvGJITVYHz+k8g\\/lgGBqZvGSqqFWV9+mnVZTgM4NDsae6DLCx\\/oT2lWyLpK6KyMlVhPtmLXjkyyG\\/Q1EcpllgA89mogVgsnLrNmGxNnJh8pmvSEOKySdqTLyyOuE3mSuxOPJNxgdp+MDD0napD149CLgnepKe+MzyuQmLDEqVfPt3Nx6\\/Xs7Q4YUnF2Wkui9LvedY1MKpliE34lBlhwkWRuB7B7a9LwpvwAUZereubhywIZazFbXdNaZFi7HLgSx3Uo4yiyFKUA7cVIpg6YEC6HC9rrUGtsC95ghbFBevzH7lXAxFx16kDK8Mq7+PtychI66ev+OWGmOOPmSg7oMRwsJ+GCJoRpFGSegpXgtvnvC4aMlF+eUzu7eQAZxlzsbLV9+FEoaAGHfxjELm5MycZQxhLxADWrxXCxfnqGFHHWrYBFNhntRNL92dm6hDqRvWLcOY0lEu+o+JZCpjydsbmuHvQ\\/7VNwLz6+B+1CrwlJXOBMjdL1EgQ8Ova0d0pP6jBwO+48t0c25OktbmMkf+\\/IzFC+y3Z7S0yD\\/CLvJF1ZX6vTwPb9C53MbMWO0rzfFee9AuWiEprgQ4fJlb1wsENl7jYYO4IK9tVG7v0ZRoupfn0+kLUWNT4QQu5Bq2oMhEZIRjB1vn57yrm+kWnr1ge\\/Z8\\/sQ9xHuk+fxvg\\/phy5WJv0wMuQrQ3k3uWI5Eo3uoiOzZNzefDKNpLtis1q0uYoo7ouf4RI76xHhed1sh8XTqDAHZwtzyKoEc28Z7YQ8yCKawO2tSiwM+uLwlgKhasiRCAXbK2nl9iym2ytbvsqcy8oJLgejyK\\/nmDM9jAAWEbYmVzUgxpzqD5d6gL7ShnR9i8ANeiq7ixZdwD5xUllpqvdgZd8PQH2vVOj1NsdSwvcpPhPe2k\\/V\\/\\/sY+fz5GtCWReNXbcnEB6bRfjUYB22X7R7R4i6YKZ1Nv+UyNWzGv+3oKkX8fWeZ8hECUQ5S5ZushR0c4axgAIcGDzoedaE\\/mdmTh9aTqtEuMS0KSx5mWXRzNtOEdKq0iuSjkH08EPw8mCwuIvjfI+X\\/7T1PVEcr7BR4a8KXaSbwxbEhH2nLcR8F8wFzce32QO3aaSY13Ux8w3\\/uiBjzfxTuvhWqZepu5q4W7sTk4r9ErUaCkJxfaBlxeCdDad9PxDzhTz8ooqMlP8khT9KzOwBtWzq9a02skUFwQv76Fr2bQpDWgHnapPqtqxGJctvEYDr53uc3Lyn0\\/XFmadNYchGdg8SivaSwgQWsrmGMMoo4CXAHazJKpIvGBYaf4ZUDEotHN6Gd7XjrREtLQCUXPqys5QkSYVdKgdt1Orffvm\\/UMcLnooHw2lqllOIgZV+bh8uYGXeP63K+bnZmOFvPvbHvmUzJPSitYv4Mam7nKZB7WOJfiu1ROgq81B+joKFe6YJeQ8IKmKA+qxbvngqQc6UG+yTn5MtFklcxr82h7xgyT3WpfCfC\\/riVTrMLnBPasvLBRLD0FgceUpafD410rJJgNSjxMaL53mn88CqO8N21XvafairQ\\/nUaz1ALt5HicpzTSIUnMmLXLXqMJEe4aoE43BAgMM+WXGVobnmbaD6\\/JdpNfwRiksDaV2x1VbmlNIR4Hi\\/fam77Tg12AeuR9MYeOG7ujWOLEpDFEnYAxVwlbne4Yt2ug1vnHgTort0Ebm4IgRvD9ndb1YpLcR0dGA9cbmblEf2WUKMrpWgxUg9Bp+GN3qpOIeExRrG1c1j9JAhWaWON8cvu3ROXDo\\/e0ofOKxtPH3sIlR1PxZPBHCPjYD8\\/OG09wVKAblFIH49zTIoesNR6dejoTTD8Xy1Tzi6OmopFi8PMXgl2NNmCcTmx6TELgebpJFO96l3m3Ab7qc0iyIVEdhpJ3DMLha7nI+9EDNKhEVjTe2q\\/saEKddA2Vl4XQJt3zv4uVVs47COm6ZzAp0m2f38PVtbGLWzDpdPvwUi50YOymdIrLToyyzv\\/S1xB5ohIZyNENqY57hIeFAhQd8XQQ+IPiMFuImq2ZP0fN2evYuLfnKgq1BwylNpgwV+jRbYvBrb+cJhW8SLcdamiImpIpjoBSY662yzoCXHwUWcKpARn6Ql2YyarQyJy45PW08hzBJfT0IOrv3\\/n7I4pLMugDvrtUFCn4yjuvHz5o74b3onigV2sNpoYiAjyJzz2ymbtXmdYQ4pIiArxzmC31LDpqBqLfGvg\\/Nh5mW9soFQ3g+qIzZVkHYaSCmylyn9ukWa87XlC3dasQLYczo7NGAv1sKC7v1ZA+KrJAUTzMF6nxHw7igKPntwDMNVc0gYt9uYDlIWotUDXZTBq5sv2ObrhBT2+u2WE6EuHku5snEb94ivDMoPkQ+jcMKNSHi4Vrj00DShe7IrCFKtSjrX3Y3yf6OInZrmFvM3Vh0UseQPZ2FBYYwfBjTZxKD6o9pRVeoJTykKBef9YxBSQDLWQNU13j50kx6xBqPo0H37Ubco6aJhP3gE+CDepKrxgMLlATIhTXclkE+Jt8ICrOtNvCTYfl3kdzhfJbyO8mZ6EITrgfv+PNbEILU8hHacxDSlOY1RITMJ6URZYVXOR1OhfN9OYSrnDDo+ZOWJvS6mykG2vtNji1i9f\\/e5oOmjcSFRX3RT7tlvEhiBd5Ixcw1Wy\\/0w5HpTOrimV9bYyxqXrzzdxnrtF73+b\\/9cxZ3YO3pNFZO6+Q1oNcmwrohEc2r0TFlVgypcNlYl9xLajTlFZHo8biCsFS8yrFeuP6UHrCqJ5FSR\\/3m5s+M2jB6g+4dF02F6oiSq9tWDgtZi2FtCc5UyVW9NUC0j1aIIwUY+ZG6Z2wuAoCGiHZ\\/b+mqThVwPffxAehrA3rIq43zNi7u3eSPWsU4fmWO3V8AYsSd8zM4L\\/BtUMpTH27gWp0laQ6t0bb1wTouAG13qzBiXIPBeSerW0sl3nocYkNN+tbR922ByWdauozysOTkfsfar34C6QIAa3\\/E+TEw3auA+Wg\\/N1Y+tyETjtSJWQUnDlhjc74x75zqJs2M+mYkcw4XeI6vRItg8Uhst6Z1OE3yeIFCAElc3pDQIk9+FMfDUva\\/uTcQbDQiybjYMErAdwMSx83plodd+rlfPnQMfOywD2XyEbXJcRavycdKTIcQW5+PVqUuo0lP6jsBdbxG6YDTZTn\\/UIMz4DQMyZ2lJgpKc+DE71FV3wvrLsyseGXp8IPhyvNm+5f5szMLVX4mMttMHG0kRz++eVS1A6S80VwrHZLCPv8A4XfGIOuwJzipdV0wDJTcG\\/+QiHlFZKfRTQ5zbOl5i1w\\/T8Nn+fd7Y9r8Vzr\\/d20Ja832T\\/VrHiUqC9eJI0YMziGSo8TBZh0MOEWCJfEbUR+iip4cBWs+wkUWYlrGpOdL5zENVmXlKZE1mebzLapO2WDgc2NBbqmRbFK1UtFlDkq2epS9WpeKi7lhPnfnSW8St\\/OA0o5mqDTVv6LVoHnHz\\/SR+rzs8skZUfL3ZH8ztfTr9iUKNYLy+LkFZbrRzoaQWLTxxV1V65XalcvOpuR5nGV7vSV9dmG0v++dzO5DbyrcATsE3HG+Cpiz3FjJT0VuKXoFJP3+1n0W3VXtvEqLsHdYqjtSvi4zQQ5QSU\\/9wwUCCL\\/FqADvZO9PBiEQZfpfEQA+HDP+WzA\\/2y0axJfbxQppGDkWz8m9V9utPbZF4GABICut2UKz2rxeHZ5+epKAN4nNr2utrqmuNJd2XcRalgG5FQ6R+hQ78pk8VI3c4dVZh3oAO16YZ8NTMikTtGDvsWC6Klbem6JCU6JL7OM8S26UT2o5md1gixklBMDxnk5xvFyDac\\/jG0sE1yhFaqYnCu3Qz7QQLGk8EYoT3q\\/pgaYGk3dUvJO0l2iGvQNaeciPaWRsxDNB4surmzUDxYoXcUDMEzMv7x4w4zrwUUHSGkJSxu2idZi0nMTGteYLXuJxqAd7Cak5dvUxVUKmcfwysm08ntvRa4GqwfmWArq9rmJtxSfDB9bhpX2zclPJL\\/+TglapNuHzLoBCc+2xBD9g7btspyEoCIvCqBfvDK64IHIFTOjogAA4WIyEBsRshUiFeWli5UUNxDSeoWXLsCcmF0gl\\/QXqCnA0ZMI\\/RK5CWaurdKe4bttU0I9px+CIhMq6tt\\/bdXrRohlppi6bycDgVlp18Ylk6xRkNYGfdkvQeNPaNz018QAd86AKWGxJjIzLBYd5YdAqeQqzTGpHztGD\\/F7J+VVnmMCPHuoR5zA4iXaqHJY4i2CjdrDcZ78Bbw1LklxEqLFhAfhUEg8rd3QnFM8ykQvhyRPoIo+grm8TGgG19XgIEtvrx87zquWpcmbVWMnFtDBvIHkVCf1pm4yYTzvPSoPIYagcG9ZY00FLbfTJ\\/r6hcMq9Wb21rUTYAVU4l5iWoF6RGFQcDlm32dUnmOxSXqElNezaMPr1DUx5acR8IbKqJLF2Xd\\/OtCLv\\/979nSRy9QSiq4ZVP6kebf0+z4IMRA3wMJHSPqfrU2x5IqUpjK71YPm+Q8mNc84oTXUBILT9Q6bcQrRhVuTPOyyaqUd0nnMQh02xkjlZgSwsPsrkiV9p5xTKayPIR9iJ3wFdveugXwMUGWA51TWXV1MWm+XeOh+Lk7HQYVY8cp98e8e2QFX\\/Oj1z13lJ\\/m1B9ceiJLWrFQ\\/H7t1oJf4bQdG2PihJaPHhT8eg8zIPiPdv8iAzetGtFT1KpJ\\/iL4kCWe5v5oFUFJIQ5mJPBpCrgPQA9g+duEo7OazfaRvqXfENQCTRb1Zk8RR\\/1PolPP\\/m7NEnv1sTQaD97N4BeTA5n0sWmm1NgTw9wiPVGfBMAcqJJnt0shtF0XlRNjtJMYd9+cxHFFj3mi\\/iIfb6MnIZc62\\/XbA2WXpuRVD1fbAS6E4SGgSaZq0R7ODpFXUgV4jfigAX7ZQPsy13Zo0rjukaPf3kmcs1zBgP+2C9C1LYxnReQUfaAmqwhkLqjBiOm30qmF4jQVGhmger433CXYtENq7gbNzGcM8A0diBGZ\\/tBC3bhVFKORMdFDXYhQYBZIGYMOCGAchTWzuDs0IbG82GZDvGvPYvvpmH0VxTj+yRAXzuOARUQL13elFBqpIMaquOAH+g\\/ihpF1FOgw\\/+KPhtp\\/YSjvdpwoWJEvH6oF8e\\/yYBBsqaptQBv1bn0hDGVnFkylRm3TQPWF+GXiQ4gDsBzEdcJbVie83o2VofCeoQlhTj71wjfJCm\\/Bc0++rIyTqFRXcJpoeTNs2fX6rBzPbjfuBeGWW8IQm2r15jqUmrUi60hEJfLGJJYmyV6lP9tFv0TNoUiXfd3+GHNb3Oye1s8mo6n4USfnEVIj20VljJ6\\/llQR6kq8WyoyWZh7Jr+TKPGHr760w1OU9pbKFP\\/yD+JISLRBuf1JrKffkxSzVsudxdLbaIWOMFX\\/beZ0pyVYQJlzls6zveJIOkmu5aRCZy5oJI64sGj3Gw4dwmvhaizL\\/O3cfU9D1EpNS+yj3QvnkyWqBzJBBZhZMSqOc+eNh8w92Dgy9FFwHNPL8L\\/KuzioIlG5huv4JrvuJWw68MbIGeC\\/pKYYP2svZZXQ+4YSHxKxYi1649TT2kIzUvZ3DZLHkhGcCr185ncAdPamm0BbAF7hm66CcUF1\\/z5GBM6cXxh2cTxOF\\/4TqrMeo7Ku0foy\\/9cSZjEhyR7DvJytWdrr8w8tzYj6BKtUgGH4MzTT\\/DHoWBITjAMm5Iua7pCS\\/cGX8hLcyjbyQb1HsUrPvJBIE7mAspvFjpiE2UnM7YsSjCtlfMAAGbgfzD6dWZjWy+0z+iHyWUJUpZQ1eGgkW7VVi0\\/yD9B\\/Nlxcox7UtzQufwz\\/x8X5B0UnEl\\/31hVxVbReTw3kS2leYRo2BG\\/CZGYs+gqvJRE647N56CchWA8WIjSPKfaOW2vYOYUJ+A82TWLD0iM11To7mEPj7QNSXZE0pTAbF8QhrilUbuwarArnjErHcCvZmHcatEqr6ItYO+M66PwbLKJ2sX4WSW7+5qVBR2Ar2FU7pJ6jVG\\/G5lVf47aE6WQtaFyca6jX9aLHWT39qala1HgUUhV+rMWa6G7l0rxe67bR6fEApC6RLfH5UJ68mwyHPizSDr6+18iNOZk+7ZCTV+ZXPPHL6B3HroAdDH6+9QlzIj5Q17+IbUN7HRN5BGDE15GXVsFRg6ieXnsx6AoVyOvciKGEaFPnuDha\\/3LzTIv89yFgIQ6mY6zC79TfCzmKcFBxy2REw6a3UWoUoAsTEQa9R+oXh1SloZ2zXChhIJT8gHTIWo0YGhqmYe5Q+SjcwbdDKli3RcsuDHu33sYmc45T0TlPlPNkpCc9VQoPidDAa1OwIl7yne6RMPHOpMv82SLVk5XzrOvxUzZG3Uj6hV4GF06WFDiwy0NKBMTYdVErPGL7zM\\/yD6YH8UjqPw4Lf2+1V5SePXj7aNW9CnDbTueJDaoxUcV0SBSvn0lhD16OuPV\\/4fSkvkOnswoq0mkLuV+A5euq7f2BaSMkynKAhy44TAbClpNMqCWMCvwzCgJ9WQDTBubo7\\/MUPTrML9KJp9pjvzJnN24ye1MOCzjj8ZxP1PM3xIuFr8oDin\\/qGMiKvd9nMtlQIeHWD7xz7uhNcMZSpOR8Msr7tzxgJvzmFVnoBF\\/8ews7XpPqOmcq\\/o1SrQQP29DBE0yj99n2IXbjdFjxNlPdpIXSh7hD9+ebkxOL6v48fzHwT7Tl6xEnIm9JuzzsQEVtkhoJBClG0fVxRglqY5CYh9Myv6Y9tjV0t1WfcUTGp8\\/OrLqFw156ilmqj1beX87avIces2QTGwDt12Gr8T0NQZre6qCznvNI7R85Ug6DoaS\\/ZYZ4iy0uDzDWGujBS9K37FJZhrijrDdi4GS5ZLk1t5O1pjTqPhavb19jUlhneKrBqxHyvqppaOUHDNvrkAmEv0kcmSz\\/X5HKdaHRzeibOQ3HD6oWnzZU\\/4B8Cxftk7vZ8hd2319v9hscwwAsdu9qLZQ34Qfl3i7VjkqD4tma\\/a6w38pzN3H+qpNmCU+gkFXOmcbOW+GQfBRUBWc9acao94Q2z3pWkawTacuEaD9024m028wa9kmrKLI03lPgB1QmjmjROJJ93K\\/rLV0S5VlYejlCtjrqH7Q\\/\\/OVaDfehQa9WWTQfBVk4Gf8H\\/C4AgT78n+dkrzuxYPlPoQ7XEgqEQltudWn57cPd7v50fJ2NMBYjl62dXYaARBOGKvKRmSbRhDPqKaqt\\/gKildUmtXQ8Sq06TVECeKVHIjYEFnLqlxFvFcx7fAWdWAVXisjicx0cqCgSJA9MH9LH9lx+wbMsPKREsjSfFNfCmnMdbR+Rd4AdvBJQmeaU6UkHhf8Et1QWA7cV9dB516aaUNE2+7Wh0bkP6jdYrajJdJyh+n1ugJShIT8s5GMuytBgCgH\\/9EkYC5XbRwL5bDpgss5rQuP8JBg9RApDambg2tPRt0fTzgLvj4\\/KuMuVLGOIhZiPPJfoc6gpWWw2fPMF7Le39OmwDZTELkuLVrp3EcOCp7oAsVi4v4S1LEXED1YR5fHPzro25vHffwaixX1ws9du7i+mfz6v4iMpPSvr4NOzDED+S\\/P5D7PyIewZxBh98SM9MF50o90DPS8Cpn70t\\/vOJj1uK7qqIjtMfluUff2m1+4H+2HmxeyD5Tn3e6ZVppzBLp0i9USpc2J0aYRIh0eIEmGMZG8Z0EkXadcbnZettp8Dz3IDjQx21gcHPaQJHML5c+vFnCwn91ZHWBB8V01VUg4\\/dOBw\\/xIaVE4u3dh1XpO2iY8+\\/\\/CHnI5894ot35sPU3LvO3orwTVWfxCEPDC1S6abtzr27dSxnw\\/5+Q9NVjVSBM2V9N+wIe0nc14hrAVve2HAFmwdk8n+07vpIU7rj50s39gBxkRzgWGtkfNNnp408jIrSpTRGCukC0ogGAYIY2p\\/MAtAL\\/5uCq8M2oRJaWlistl72\\/VE1xDLyV724VzvJqGWwCfMtEGRutMxFgqeIY7RtBH1l2P4gI58Vhygw4JWTFGXzMiuRds7ZXD\\/nCLkrI7tAkS+ZX\\/rdXCJ+teDEeDr4dLynQklxCpJkldGr2YtdMBNFnlWRkKgK5Xbtn56+tc2MNHaAth3oZCNbLNNJHjCEu2kAuv\\/Xp3zpaYX1pRF1NSoFL6+8HiJw7D6tCHBXzlsVaLWHVETROHPb0spQIL4IAbuXL\\/pSMwPFdI+X9iiMdOGc8Dh+OsVCvtJwYZ\\/Hio2HKPglfqIgNG3z3\\/rVl4Udjo6QWiZWU9W49\\/D\\/8gdpPA5qIwrL50xTbLO3ykVj+1zUG2BKqnyNKQsD1E5yVWoSH1PQaFNLwR0jCKIedQ1oRsBry4HzTM8ofRy\\/nUUVbAkFGFhpqS6VGUSVw+gvfutuhi4fjmoZ5B7avpztxAdkKUsRe\\/svSxK0RHiQwHICRaXYM8DyhuP1rabHI+bZ\\/4lgvgzrLl7I\\/+4EBDodtFAuw6Vmk50rJpIneE1H5hNWx740BGSmGo9RznadDML5TA4PLcR8VCjul1nrpYoRQMHtJeTYpmoJGi24YwqtUK2NCoOsN1uNe4sqpJ16dX5owNSJBhCrP6Y0LXpIpksbQXL6P5MKbSA+CV\\/0Y9rzH1Is+\\/D1KCvYTilnDD5+MltyctM0MPkCRrlV3ZvlG59n8Jnh6r80jlXt66aD0cNH1jvKaQigDc2taaj2FctpxHEVBfdJPmjaEiwy5WzM6H+Sve96ezRv2MEmzHRLvTSgH2tahabKNchRBk6rKPnvfnEMBR35qGjXinGnz9HLnZ7YP3jPJV5Wrse77hsYtFPY1spEvuGcg7V+Kfbx690oLH6mfWgNNSqe8Iy9zopP\\/RPV9UVO4GRkxjzNHvdAdNFjP8chnRbcndd0P7Zt+zEU4mgOm\\/WCEii1zZYNhBicAhJf1yTthuCUE0uMqJt6if4PMGA2pEaMFNFeMcGuA+wz4d2asahUKgGxXSjr41bLf+YUp+aGDy3hvy7ueYUCEt0tHG+etb4jvqFPzqYeT4nx4MtPQlb0vEewA9243alGEvtS\\/xBmRBpfT0Ad1HgKYw3Cp3c+0NpEA0hi0psq82\\/0DrgAXYWGMAxSNv1RqbLGBz4QJP5U\\/JqHOHG5wphpI8D92jlG+BUxN2amPSL07evmPtR2bVNtEnirf74CDSzXxQ18XZWq8llL42NyN3wyTvCgXBeLsF4zazQfbnbc6xMbmy3CGotzu4AXncxwHHU2gRoVDdt67TNrXSI91wubk7C\\/YsFcEI\\/CPDEQHPZEez2na5BphR8ESx60lVCiCpDkuld2ClS5VGdJNSuhHOe2jbX0GE7DXV+jkDwS1eeixgRUtjZPfVkxzWlpHUWvc9u3B9pIfBlY5Cx\\/VnGQfvHjBW8uBUdk0m2CXNvAsRslF09EnRDf0RrF\\/EB7lFv543LBn2iYq5CzkwnFohT6CeEm9ktd1AoQ1KflaR7PLLTp0Bza1NJJyyc0UAB\\/4Nzyknqc6kRPaIObtWLOOQfa5gJNwZsrjCw0IVdUmk1tULqywYIbcRIWoS3EgISGEqbEQLUaiPfSOXYeGaP+I6KjiSksGE67YrkNEsDgofDKGq8\\/nE7ZRkWeeCRCBiWFOXKcCKFwPDKbJ7JHcdw8gGppl5LF5vm8h\\/aojomiIncWH8OxY5TgaM6OxBGcolx05RL7tNLffoBf01rBiU\\/NEKbHIMR9AugIfsjrUl2vXjP4uPLeCNrv73Jei+78pKy0kakojeG1x2sOcgxibckQiXo9IQeWt+b0mGpTBGzVxRQqW1Dzkt2Ub2IL1MH2KUq1YAwy8SR55omOiat0ziLPe8yI5ACgTTAg6dWwtYRo4BYeKYozvq6VBBJ0MY7X6rlC8S47C02X+\\/SEQLrqD12v1TCB7dIvGuLEHeYXR6EZR+vyXSao\\/An3rMuy9syqXbPwgOQapzK8fIsI7pUPCK+6USIJV3j9xXdct8EeUl9HGZfMxRS6FSNBpHkn+tAWJ+SagcG+qohkxdCWs5IqAy+y4VyyGrvSTuq0HiNTpxa9DTWZm1g2Nk7iPhOqhdNSF\\/YPf4nl5IWFH2aUhEHdpL9iJRtuMKo8vlG5Buaxxa2llUGfuuK+wJfQGIg2dL9NvpJQwrCrzaXCkanzerGBH92K6QjoeRibbNRNrlXSzkricyVUJM1VtE0OeGF\\/ln2W3r1EXbuHnlwScTQV9jpu36KYYw6hEOsid6GGkXUYEtNXJUYPTyMYbQUsfETPVqCdl6oSAx0RJI6dVKdNfRhlSwDG8FL+rUynwxoRaKLZuxzKokujNkA1pcYZXlo3DdebokNLtvsarbc8NdP1eKahtVOnGKbr1V2ZMHTW8TCdupHXPxAXPtcXO1SOFoqXji3G2Tb1ts+7UfTcQYBosQxcigo\\/s01FpgTwtQoLEfWt4TlOtMCwBl9nElrrkIKdEpy9Lk0Dlb1HGTV7SnHKl\\/LVhakC3VgeM4DKvn95+JFnnMvwORjNB\\/x8RDKgA0Te4tfaov9DY94xfdf1n+fj7VRezRfDZ9bBfJQSGKigoSStMThs6wsIlyD+6KxKIzGPeDAtCuUJi8xpXQ0c6DKV8M\\/6ANQt8m2RYYA\\/stx42PSD8MxEuuPYlRA6Fcr9\\/gMSEaJ5O67xW1eOfcwLJfRlmD\\/GAu+W7kQBUihfemP+4\\/yE8Xu1jakQmgaa5ez2VTnLhL77sYvifAZlxwoS2thyacvwEoahjtchuULR1M6Wii0U6ghFP\\/eRjRn\\/GXw1eSRz0yTjz5fY9oF2XsWpiLr4GhwUhPUlUgC7MN9O1I2Xvexu+jMSphNQaSiABznCn+9CKzFde3sJhmbFYtit5PTEHywj4E5u7GqhHYrlFJeXjmSCwX9L5htssQluEYyCtzRFKpOua7w9CAhKA\\/QwGd8vIlHSCn64Y93Zir2ZuqrnbthViDgJt+ezNrcF+3GdCwkJ5Z2Q1O4P\\/zlvcoEhZhuP6GilB4EfPCnC65N12KOvLi\\/r0ravyAoWFBGfoawJ9bM0kGGfWJDDv\\/KfFChUEkmDX6jOGZA8B1EJ4V4Z3i5RNkK9f7Z7rWoQkUJ2QczyCIHcOETGZJ+Rst4ztuDSdHOLBtO77aHYV2jMJmhsjFQ37JH3tgHzcHayK62JZSWEL8BzEw9+4LPARm3NzjKtpPAbJf3R9wJ2PBvPmcLljA0pGi5IfgIwfKquoDiYlw7AAIKDNt8MFflc7l0Q9fMWZZAzuqPcif2FcpId3\\/xv2exz+RBSTyhHCS1ROpoiUUoBY8LVjx3XL8hmH5Z7\\/l2u3TPnPx74fpwCFswapEiAiafvXFt0XegBwHvTNK96Tkll7Mgx5nPoS1MwuKwQj3Tr4CifDoEQeN4Kdkjsxn6pHrCmWx\\/DHj0HaxcbQe57pfljEdGqNelWIS6aQHb0aAFdXRZuqM64SVAIfgkwT5x2w2avLRnnfvai5eiBzgCnHP\\/2SepoHYYCAOJQzi+4xzSyDzkyCp3rYcdd8l4L8QhclRLpzglcYb+ZS10qUpnhhmpKFLErucyB\\/AxnawV38svjm8Igk7gyTzlqYsOBcFtr7GHcWFfj4XHEabW8T+xxFU1HbDpZ7Fcnv3quAB+0Zdr3U\\/akVJLekeen8\\/0XCV7rgmSO8+WxPAK1qjwlQcLgeOgrkoGJWgwETIEZzyKIt0WASz35yPyg6A4bDV0qtBm32VycAmqs\\/WKjBx27Gxh0li7bX7awlJ1laTy87B1fmtv2vhX0ceNfJHggjd06bJLQbJnVc9YfkHXOLM\\/JS9+3qSeLVOXSSxjXvhUPqJH4Y2itn1riSR1SU1ef7Xy6dOqe15DipSX6zc15BujVQMuPL5u1hMfxg\\/ZwLhG8jCt4PQin8vbH8CyQjoo4T9UZOZmGt458n2\\/s7xtejAAEpGnrl2gr8EPusyvqPK6NfnAllteZQFPls3XfFciVGs3HDRKmGciQx3z85WhrvNDEP0nAtlGohHSpNEeKTZ0fTltggeqNiF6cmsAVBXZq07va0FIKzgm6QV1LGXY68C\\/pCrOFolEbmmL7d2w2lkL+Rs2I0aJzuA7FAJL0un83TQhloAgYhow1qzASH9KxWLLhjNR00P+NDL+M+JMFgHyXt760gEwTu+IaDMbmhpEUHHm9dpBK\\/mlBFDrgj58HyZHRy2boZekC+TzzT3quF+FHCikUXDluZQIkGFcta3EBOIUtitM0Ah5F4vIWya4GfHwjhV6aAgOgUc9ewxF\\/24TnfnzFeLYAwNFq7ZyOpeqQYAJXayTtuHaMDF9QhgGI\\/TuOdj53G4HRFIcHQ9PufsaQ5LYcienlbb9MBTlmFjcOTN5nkJg\\/IugqFFJUJSeOkrjZM1PNCxaXsUo8Jqfy63WVOzf2ji\\/ECBhKBbSH4arudHHLwxK\\/zNdc8uig5I9QYdURB\\/9VJ87LyTlpfjujmdqnof9wHFw2dMkpv5aW9GWWyXgLxhft5J+z2mJINmD1RY88M4\\/zeTj61pVMZFYTAJxTSzSyXOV9+iZ72P3CH704S+LfBkM7RXuZoZmepq+ESHE4TP2RxYrLknDH5KXJ3+KQ7rfNgBcgar4UNSSGuUj5hMNymJ5cLv8qGaIJHSupDT1eqiMFo\\/BUsNz1GcQkFSH3A2hf8n+p4RG7ZohXnyYj2\\/VpaOIZsw7ZsmLAFarpPduXouiVN29S5OOZZtrjP2PzJUphldC12ZPRpROSZZiox6xsi2onwtuy\\/3knBVmF\\/Yyw+ypoWCYMv\\/CA6v8Q0ji7z6hptyeum8po45uko3Sg\\/twheto4\\/+bdBO7QvIqy3T7cZw1OD2Ft25Wlj1yrcfrFvuUrA5fkax1\\/rtih7PgdlWt5JT5GoJ0KBmg239XZarQ1n\\/wq+9gggBPi\\/Cqw9pZ+E82V1o98eIeap7VcLaWdy22fz88okgTDIFinAK2PSQcZ224hFaKAMZkqkMoPX412mlZGW2dSoUSYVyDSnWxymcUMWipwKfS8TP2lu+A1i\\/C\\/K+9Na1xxF\\/qi4mKY2so4ozB0+V9MtLF0OAJzP+02wrLq2h1itKevhWiaJxCSe6VexBVFCPkq2Y\\/5gHhn0V5p7YaabRP5JQ9Xf6zbjRQYzW+krWMNlK\\/IDSSS4UD\\/PxlOC766nwy4BsTS+I6TCdZkbW\\/hhLiGlxkfmPNMvX7sN+iU3VmAhU6\\/1nzAQAQEhBkuttZsVeyowt3fEfxNQBWq8QrdKOWaTj4uTsbXDj\\/lEIgusR+rCawR4c25hbCWGfQQv1XukbDvImrgQ1Dm1HHJkcuKv+4Mg04m7eIR+ITh5LMpSJgNhmeTwThTGMzanyQD9kaHAQTO78Kmm947gkIHhmUFopGwSHhBHihovZYr0PzFzntm2JuJbk6YVIT90aMzOumnCGOS0BdeWLh8dsiuV35lOP8q5AmhhDTAffTWOQGnotcs3pklKoQNuKbzDFMPwfSBkKAdfEcnkOOSS5ruMxZIs4sfDGx0nc0kh9SM\\/dS7REBIK4DOhH5HcbRDCyU8ZFszzqG5vIml7+fFAnfLbVk7woJz2IFUzFgpXNKX1Sw5r6PKZiCxtWIl5Et0SPV45zd82GMGYKLtHcuae12RKbyZ0CgecPskfq\\/hBP7JCbCGBA648TQRhf3BNf2N0m5lbJot9BmQDY84uB1OJnGIXD31h1bstdCqRJqQy\\/gPnK2kCm693BrFfsXWWSUY9jbTcs6glt5vY3VP2NcGZeB5vzpAQ\\/0BDa6aWqq1CvTnfOJPEnxl0vJ67RUnSMuTf3MFGYx4m3oRs9c5MkeGAY\\/qSZmz5bs8mnOrPLcN9qQgE4ibn5MGlClASPcNIeK5ym\\/j789W\\/ft0HYq6VvtCwHzOyLD\\/AjDhQmuezmkuoG6Kwv267G5a62oRh5FTrR0tdG5NCdhhyYJzOqNeAH3sgjMKFtjfvy\\/sQ\\/v5ZQGzbqyfBq\\/WhfekddFIoaeRnhCu3L6MV9DUEYlM6wshYllynfcFShn29Xn4VsfgpTAf+iaSEg9POZwjCswFq2sM4DIeE80EMZ+G9Of8FnQKkwLI4ttemLMKX3zXRyQWh\\/jFay2yxhH2LJ3LN7JwUH3XFU\\/r3+QLPflv7zV0KiyeMSG+dduEdIWTkkAfuU\\/5qPmUdBtZ1WxMDdCQCho6r1VeqxhuQ1aG8HiacPaThLUktwJVIWkRRbfq6Ii6Lo8jKduGp9BTnCJRnQnYlar\\/n4ScfBE0AhzT5H56v+QYteC1gwGT4ryIGOCH6XNw2igNnwH6zdMa+bL4UuqAfKngQR0OP4BeFgLdaqt0cng7dUZOS4VWy9L7AeI2FHxye7tiuI8yQ95SFjK4k6ubbMMtI0KntbLor5oq+CoxAoQoBFGwCmlgfMvgUtNZ3D49QkIt5KFURJxyspqqRvrvqYNC426CtuoHP\\/2lwU78+S23fGuVXufyzEIaKRGAYaCmb7kJZ54NhwtLAzSnDu7MF7EI9OaiAYxkx9lv6oaPLjDsTNOmfWpSz611JTAbHuep8PES5vxn0zjtjoFv+TbON8C4weXn7ywwGI3MrbxbtlFGVZNoyGD6t12hvr+A6HOYk1OIRdx4D8Vkomyngvs2dnlnJT61MFo\\/fSNGf0chh6oLnHOdtyppVEKgsaFfvu37QJPlCm5zDlJShzTD9RKXAtbSa7VMcImpL1eo\\/IWpUaNoHYszDxTMxqxmOQUZy5Zvbjp6dO5BFRH3h78xgRkudzK50gf\\/1dMc2SiV4iQeZj\\/IVCpkN9RhBQbBXwqOut4CxuhgeYhxD1wnrFsoW6thbox9Swxijikin6aFXGyKCnJAom+LCvjPWu+UabyiQqXRFZ74dp0CQYQn75seRFPKTnd07D1KB5EQG12rhCAMpv9i65dx1cxIRgEipZ86REa17TnmiEpWSLbOYA7FAXH0Ze2W9wQrr5wBj96SgpdCWBYJ3mi\\/F+6QiEFzufnPNSmYxa0dxHIJ0291A2nsXOiMlhEywQrqEdQUzrxQn2KMwadzGau++pgUfViWXiMv1kCoqLD\\/8k0VdbepWwiwUQgE\\/gRSmov6p5Btqqi2pDKlRg4Jhu+F10KET+iw7Ff8fVFCP6HuVSuoGzoIfDtt\\/inzE9ED5p0sAUag3AmNkFaC2FYBxRTTgedV74JQ3l1ZHVsLpf3iWLPjxnzu6HAzg05tCktJZhANf06TGwSqusZv+jI8m69b0CjH+g3OhfS9KGZwnhA7HkQWCKRd4fbMgp0\\/OBNg7ZawF0Bl0a2+a2SpA8O+avlCbbs6g6k8h4VDFkqR1yVZbcRxrMvl511NlJyf9uFYVX\\/tGD7wGLrzT5VDRJuYTGy6qckNx0k8pDXW5Y5U9SQfcs0BHEFZfA5n1qBaOWDH6eoxa\\/CjMcVzPMYRkHYypfSmOCC6I6xNyFMuSxzd9Pct\\/+VGvo2c+1pJPQlga+kCmuHczGDHryBvK\\/GVMDWlzMmQFDkUfsZteXGf4eBbZLDL4m0FoVLm0y37ZtlRRN+zRvycjHmGt+F4oIDW13ZQRgP58sHO2+omjGT1xNQeB15O5Zpn4uo+lTRibhn1co8MdcqdFxm0w7xbhhrVLGEwL1TPT5FcoBKzrG5hxTKl8kOS4hEpPUon28pTYxuYLRgpkT88qopHUjxTjbSQS8sTPX+gfoDcsEmRoD9xwDzFdqIOpPzVJuul2Yl18LX+D2VADY25y1Tdedhe\\/kh+IUP76uvzAR0B9QR\\/\\/bIj3vG9zvqls7yFXLndQkqqfZFMCYPgv1FU08SmUs85ULsKk731FL6yvqKAaW\\/lSbmqojMg7angLuxTgRemfmqxstTJGZAjAJRdjOyuGKaTmtscNE4V8Ombiq5RpFY4VzOxZovZ08iJg9geQ9drnFCexL\\/C\\/450Ftrws1d+rLPW5fkpEevoGa\\/BhTryYB5nCuMu4Fqm7dP\\/7n8J0COlosLCK+AUPY+Q7JxmvO2gU4YWRD0FG67umHCNE9DByLVM1JXDEQnv+9E5YiSkVksP7wIhO9SK7LXV85QCOGV\\/QBIIv8M0IcJ2duseWQwTmGfrGBHSZBVFehSqkfH0MZboRn5V7xpQ4sOrl93nfuioo2vZNOK1kS96Nfb6\\/5sW53tvdHsR3FZcaEFvkh\\/vhf8NpwzDkJqNjBT8gtqeuZdzB0vACoKh7VxyxTDKZweKSLzYVFJ7b40uBsqyR0U4+W912oKrtWzAZPAU9Cd+pnxtlehtY8L8VigxyYqIvfn7phAvW4HWbDgijniFOjY8grHcbn5OERoKNprnSp+DFbT7HxlQixcjZ3onG1Kld0QJZydqbkW7BMo054eSwr7iYPCduBsKDaKGnXDzsd8xA5wF0DVE0JCdXxyieicDWRRAqUJi5ZhTDCZzrUQkLgw6WAj\\/yUx5CkHFRbMSxnEEXDTA6FVCmMj6abYqwTE0gYpjXrAlFfxJLHURCCss5xO3Q0n5\\/oG9sjTs46V+xTBcQro45JK+YnEFI64l3O+Q5+h+VHFa2C8xvyfTBqVmeCR+DAE1TMLTbPdbQGPiviaA35u++2hEui\\/EJnsWITZj2V8PEIf8xssbEl5kkaA52IP41erJc+04d2PYeYO+UHra0rsoxmZf7XwjLuhT6mznMzAy+9s3vHqicWzPqd0RAokOL12JFMsRPpcmM7eWL8qXI1id+lnSyDn5lGN2Yn6fqangPC\\/58gB4Hh3eW35XI2keNkPvgdm0kIvz9sPDb7Y04hsZyk3shsJZ2+Ormh\\/QTL9bPnaxqwWeNU9tUmZqw61+JXINkhk9jeBc30mz28tS42HB2C\\/7iSVpWnx2qF1LF6NIq\\/tL4VUhM8Nimaxb7GVyxD3QTtg3FObgarbNmum0Fr68R+gS+Xht5KjqGFA+zDji+CtxQoHAM6eVAI+OFEokrION\\/TZnvWN2K7vtu4435RPceoykuOW\\/LZ0zczI01T0hQNfwH5xsEKptV0Dy8VP1OXUzsEfoakTVZfnGLsROt\\/a5A7PngDCBy6SZzMa2aocU\\/He3bFlp6o8xt\\/x1WZMeNGfN6xKhDFDjXN1RxhFAV7esRcIvaNfBCTHm6eZR4YnV8sunI9X0uo1xR6AW6PIS3mRmzdPD+7BeeERE\\/gS6Tq4fsr1KTsrABxc\\/OaTmZZv0SR4SgteTMNZ8tI+iC4xrSuJ2iRa6pnqUzDC6fFcGZTH6bbAvhUP3V8bPw0+55bJ3gpQ1glCi6ncSGdrYIBg+YUICEHcuLR78dNx0kK2yQvWT34PDtIhEPi4eJTcCHMHnL3nauZSwt6rLcCVx+Yrr0imcIXLQ60YnU4GQlufXjmIyFZDekgoWIiOLTRMoOFeSD5Xg6jfChSlSf8yUpbNlNxPnxLfhJOvG4BMTFdVB5M8NxjOGzFvAM\\/DWnbN2vaU3+iGj\\/fjwVc+EFKMS3ZTiHtUZ7a0s3SzUbXU0AOWl1nw7xXy0ziGSQcaJ2urSJVx6a+W4mmaE2RkoObOVtWvNHSvtSsAvrMwQVFY9fJg3ysY9ReG30LQA2rHEXHRLqZx2VHN2HCY+qbaHgdTRjFMit1tdiAOMhLjVcjg818uwR8KJq8VtSdY0fYG9\\/CRgEmzhOJMFRdm+LDg\\/nJoud55yYMyNXCsV259hF26Sbhpa6s9DNsfPsMjHndEQWLloOdW\\/YyMcZYUUsOB+FFQ4CPw1koVKBAc\\/XXBkX3cIKdB2oucD9Eoh4sdkdebZ3x\\/H\\/iZSzK9DSXyu99gVt0XqhBQfClq7XwBgoth6vs8dRzXsGzNDF6bqym0pRTacv80aE7rg\\/WGtvor6LAmDWSdkZPqjRRiWY7qgKbhLtg402e2t48lnpNZaO8QpEJm3aLH8oRE\\/mHr2bBXsHgP4gIYnCH7LqPp5RPN0ZlhmQPfRMjRxp3o59fi8gxm9LM9Vaf+24KMi2H6Wh9E2sp6uyIGcbaHOl9KyjjmCfmDNdY+XNQDgUzPLs9w61hC8HauHlgGb6YgJo\\/ifv+jL0LlzZaw1aNpHVn8BC+j5PC\\/lv7y3tsJ4Yo8P8OYeL3IAq0M2dYItX15XjUfZCT78sLSDp4LXL\\/VBfOcrj+BQHzW\\/LLDKmLvnCcyd+ihywFrfk1LgOJ1mWu+XMDXpLa\\/mFi\\/xN2cgMBFZMgC8GZkAtNtk4iYakY0\\/3mcxIkpVFzc0sodZew4pxWwN1tF+Abyc3j+V4xtA6oFAcN9vARXLWJW5\\/h4hjH8yFty+WRCX7NFrj6THgRipoUQG9zMtBmzzgaHTawTqGYpO8UCN5Y1b0WZZfWh4bG5BGpjAbC0RzJO0aym8coJkenH1p1+gehiW9uDbTESGaCdZA5aGH\\/S4p+XCUMqQrWV+TxZDJqEvj1\\/np5BXhqJwAUuE1PGzB3faauJCLONugTE2ycfxkzqxMJjpSXAHbVLZ6r8pfufVr32\\/NtNlcmqg1AZZ84uPAWut8kxnpNCZjc3cJHrY+Ikc6S+qdQwYaCKjr8ZM4V+8OHvz8NEwL94YZjjEutqEDEJ5zRUYX43DWjAazEXQLPeGdz3s83OKeghztt9RCBwvzWlCAiwEvoVWTsckIHgIri+jQrBDP9YE9ZI0UhICPiGLC7y82io9cIouoAluRLj3wztVjRLuhv43pjeGUavaXEeyQG10CJ5CWhQoaVKsYSLKY4LhePrYEX1wYpIpG7lsQn3EF3j7cLha2HEWKVOtrgORF4Ddb81nCAndQOULC3SNNcrRbfO0gUyz8icIc+lEyjcIgBH0OZwwsQnAe+WE2qLOwiTaSZS4JZL+tqK7FZ58yj2ibklGetyUfk1l0bMXPQ5dDQfC2dY9hbgAKL6c74w+yjSyR2wSSC73aqiJ5m48R8Jz2G3+nkkslA5D8poPwP8K0cXVuxOiYIqkzWahj8Bf45axBzUSiNElBc1bbGXecZoOEdiT+m4xJb5pR9oPlYheGzkdZnjRMgAWOu8MBGfHXYZUzLkgfR20T3FsG5\\/l3XZBI8ZE5uH6nieAeN5AJIO5YdGeHI1mjgNuBREiit5Z5IPbbLGoUw1dx0DDf6Y7qmnPitmMU1KYhJeKZLMRVPZgu6\\/FlnBfM7IAcp4f0fIXiCVfZuLDR3ryYLhNunj+jQ5xyMsblZka8l6hvjZkRXtoR\\/Wae9eWsPsig8JA0JMIdbr1WLSXpglI4JjACDf\\/XRsTuu4+LeUpvJW2aLWi\\/2tCoG0B08wF9\\/Hn1aOxkiLRZ7mUOlBcYlzSxqugeNIZmr\\/qtQ2si2x3QPkVsavZnrryo6hS1OlK5ElfY1DXjdVfYDEx7uJwW4qE23uh5oiLlSzw0Ro6x2+pmyTbPcZhhx0jfXpAIw2AACCuE8uhWfORwpKekKHjijqnrcyL6PcylOc0xnQvtMWrq+bFpN9hi8FqZ59mKIX3gNrkKKKFYJlU4LRJyAwHwvotO+y5UFomy+XDFO+uSuPC0BIuhnABe6AlwII+uEQsuHDTFWo\\/EIJ5KnBWbfEWt7SD8z9tOz4ZHy3UlE84ImByf1DMgWomYTchS+SkCrTi95dbo+K4iaashotrEkDTKmFuGwOrosxo5NkICH6jYAhGcSBnbKT3aN1G7csDxHarQsPfREp\\/CRq441IJyUAp\\/vKJJ6xApP2oa9nqS+lVSoyI5HZTgjaORCYmWPQxF5wkuISmjREBrZx1sfgNxNQ71Lahag\\/jCbW7wq9\\/ZzCqo+tBWsVUrNxSqHSfQbjBkHoYdKukfMAcuBgP\\/n1BJnMIE2TBV8Kgpue7XR6S5CqV3R4vDjuAPW6w0AqxDgPNzV3QWdycJc3Rg8oJbTfwSZpMraiQ0ZRwYh\\/lUr2mqZuJEK8iPEfLuibOYHl8AFhm6sxzyAWHgIIznHVDjgPaJEnDsaq4ddXsJoMUNzYQZXCfEznIfM54Fe50rYrz\\/1Apv3KbN\\/reMThta4FDdILdUp7IFcUPbdDZU1zZaxRoASBeXwtT1gaGBjj8\\/VpQ0RRRMz1S7o\\/dVjOe\\/RiZdTz4Qst4jxaP+rcd7rFBBQxFKBXJENaCo\\/7hWnweLZVewhjkiEiHK6AGu8M1q9zXd4p5DpdAKswm9iSFD4Gedvh8Iu\\/9SPmx0b+Y3imj7j5H5Uq4xpm2S2FUd26V7PLyD2MKth+irCoUFE5qSMyQA9SUiUMuWSgcjTrrXrBqSpff1yyYz6nXNDUvamf6w7bR1\\/R3btl07Nf9AcKDmUrBm2HwsAh5jtVfA5\\/CsC0ZIq7tYGyWzLu8qJEnqE7sBDjypgpWPH1Kj0+6jhMWn2Q9GrB+BSMkO2BkViOp4qU5f\\/4UPKpwdZWJzXlz0CDuZ5N4cL01JZGBHUVRDM+LzwtrCAZ6qkUgGtNrWSzN+tBUduYCrwz\\/k0VlIaeU5HcB6R6KxJ7S8tOLr0V1RTRqYmfAa4RYUXYrxwIBTdqBgeCnLntN7Gtrmfico7HocUxNAMmWgKObIu5H\\/DmIYtdyTd3eAFLTIOHL\\/sKa7zYU8T2ku1cByBT4+K0TKStjBtcEeSo2lw4dpMCknIaGFNResv7Aac1Be33H3VA13rEbpbv9PVWbXDO6d5ETz\\/+mDZfC8OA+8dfiE\\/VSoS8wXz+nCnrv8pw6itPz2Rxf7p8UOIxq4BYh\\/rwSp8HNPKzR007oWbthgv6X8yofOVpH8KHQy89n7AfTSvus9T\\/QQKAZ9iyGbCVp4wqwZOD02w\\/5Is5WSmA1FO5CDsrhxv5M6QC2phg4rCugwho6h3uvoL4sveNnnsHJ9vU9eTbtRfmhLh4v5jkecntRIIG65A9CXjoCGzVMueEalLdkEgDJ7DTLpwEfI8yMGfJwOJI\\/+gaZfBRs9Dabg\\/CmF7Rbbm\\/Zju28\\/1dhdEut7mxBVxpD4CsqGNc3SC9URQdc8YMa1H7vWft5RCBldEtM\\/l9Y2xVjQpCtwkak81HXu0Vdhvwdu02AtbAT53+HNvPsl9E\\/dkK7ExcuLMatpLNrq0FZtjhy9KFT9rbKPIEQVpklXh0Q3BhSwOX8M+3rfMTGdq2I8Lut48uKWFuFOD6wVuQVxDMRPCYQvHOsQaLcH\\/UX3PY2gaCkGLgs\\/eAtGLJC72wyui2Kw2yjYWNhYUA9MPcc0lWIe2Q\\/gvFvphpgZkJPtoNs4NkXEWB\\/APDy3ptWCPKy9sEtrvjcHRhvTQIy2ZASvh+FpwPcfig50NzupXUxXmA7sM+B0U\\/AH+kE3T42wMY8VNtJ95mkXI7ieNzt9A5QRNrGQpgUY+v1dIzME+GYXC5rr1zCG20o813CtDQyT+a+MlOlt5jAyzF34vQO8oBg4KiD2L1SIpOsJ7Cv9dIEgcJlP4GzIX3nQvD1Z2HS\\/i2e9UrCk3gXWiMamNux4udg3rNr0g9EJCIC0mlN62OO0bzK7X6rjSwDopO3YwP\\/\\/Uthl\\/Whu0FOLtf5KAZlLG4NhQvGRKc9RC55J+czt6I3HC6ITJqHScd5T8wvbG0lAOrD5SM5XwjAtwPfX1BtXWwADadGu3Qvt1QF\\/izBUPThBb5LHJjFplmI8EuRDjJk8i+\\/WsN4i\\/WMHw9+bQSu4ycr\\/mg3eqB6bOVIaXuPW0h5yxNlyBxXPM0Rb79NzJhCm5WO+k8C4PcHbwvGqITgrE2+oFLo9Jig\\/ILiV5eSWU87lD7tkx9O6MxGkry0GOM0MDSKU3fkGWUo34JwTJa3jZ8VkiTOm0AxgdbPnQw3aMzGHfYspQp37sUCRzpAymjlW+QUVcv1SOldNzHiYMwegzyu9D5I34n24k46821QhO\\/9xFb9WtE8u+b1c7NuxRCBKC9SIAuVUHF8PAhmZN7RWzfsYyfpVdzVD9\\/7jjPrBoVbuMQ37JzotQZXeoPOp4S6Wf2Ws3ZBAuFSpdEz8+ghreYRBEJJZl0TNczL5c2eRVGLj0LvwubjjCr5vg6qAeH5K2SMmC6Cz2UtR1ZIko5tJsnL\\/yNA1KlTzbcLAQSWtGgyi6RQFJ1qrNhMgkgoxTtv9lL3YguEVBiylN00a27jkBb4F0b8Zrea7GYGjD+Ryqf\\/XKR7YFKSPn+\\/1MReQw7Rb0XKrSEp0bj\\/WtCaiZJ9AjoMxyv57q6deWupechHAzc+M7uIF8VPsd7c3tr3DIffsbAVLRmAodE8IRVi2SOcGhYMcVB0XQbio+htNP64uz6XXlx8P91t0MMPxPx3NPGs8tdrzw86kSLgkqBH125+6FMyUeb3WdbzoyF11BQg3pTvl5rKDNiM5SVsOYt+OVH8Mi8aVzlQd+g4uqbGels1+DzP8X9rQRsv\\/rGl2NNa7W1vpCswMFQaKd4+LVk2BeXGz9tFACRdQs9dLqopA\\/eOzJEeG\\/gYKbgvIMuDc+Km6WPl9MdzlXyfb3bjJh0EW3oroaudc0ID0DFt4FMaV4W8+krhslw7c1NKNVCHg2+1n5ibXwEdytNY4neWDi2fQbGDVDMxiSRO4c5wI1mmx19Oj4ovhTOSA19OxHItDj1DX5Aq148lFVCMAiwyQixGJ7aG6syeeid6dkH62dgPqbXGNxMraZHsKdZqFQDZKHfSbu\\/lqNuAo79R7kvDDfJn0Eyjkaqah+a7l\\/qH8bR4O5YQSkWqY982r5\\/m\\/2hzfqE5rLjfV6a1DjRAk9UrhisLBwHXad5B3GuiZRZo5d7BGRXnxaXphYOO12BSZXjscbyWLN0pFs1eub1K5Lu0zdN1mYy4at2bti7qDpwBtRRth9nU6hu06DsUUE2K7fIRjI6S2k8SQfs4A1D8PuclswiH6l2FNmynNINWFa32n95xooJkSnciGsXXsPHyqZ8zRFOle7yzDpP1X32MJ9Q9jXK+cpYYquLaxPBbKpa9\\/bPhpmB9dQ6LzcREJ\\/fsPxkiWRZfCnNSj3cdK4ks6yXQhYnfxrFfqGK3OINY1k8kR5kqyMHNIaFUiDcyxJMEdDEZe6nOgCS2JFrtCDNlCKGcEabLuCSsk5pWyF193rEDR3chz4WxuwaXWV7hfgHFJIuNFJ6GFikPg7daVLitRcZjEWiGyfzy6L3zq22Z4DkGLx34EZBdNK1M31jRCm+jmrBP98LUEqnIrFbWhckrLDUC61qUB0e7sp\\/v483Z0J7t+7OW9exFlwZKUCjCscPlhtGDZmb9bsLhP0J88Logp9aL6PrC\\/VHJZ6n3K+VUtJlri9DnGgmm15jz2qb8Qo01dCvdGNAsnjI\\/CKwis7PfgJkAnNULLey23FskwPRLq0KRzRPnYMcUG+IQfSNLYXgmNkSalPkQ4BTW4gwUFVenZyNgOGEK8EwJHe3p7tU59S2507MOPcNRYsqxC56jwia94hwrGoCHfaFzTflBsmtuzB\\/M9n7b\\/0DoIgY5VXfcR0zR3ETy4OGRiM8JndzV\\/\\/jQxVCHpEGjaPmkDMq2Uo3\\/qE\\/eMS4YciVardJzvCMbPtFL+nRb6ZMGZZqXl9bSnQip8wMnXjgT5B4oYBUfIvmxUWM8STwgvK6S7PkeTZeqeG5x\\/zgq60NAP9WaNmI2LVRfPGUhusGzkjYP\\/EiFUIe8Hxh6AW51ddo6uGuPpzt8UoPlRIVobfehLSVnDWhenrcCfcL6VbxEnCl\\/CJxJ7xhSx2ghdJdKl3Oir+NcSpoPjBn3BYvCrPEbFiq6+pf4ZpRvHynaVvT9TOVCKysackhtfQqmpei5iuFdMtsBzfmkJEqyTW5INZZ3jlyxp46UTEifXRXBToM6JtD\\/VB7o5g3wVhrYPGDXNkI9uIil6TvA5DhZvvz4nxiMZiltZtcdlD\\/\\/L0btbXBgt652+sPRrQiF57Iejun2cxm4SUWIwUF3sOsAY4Ki0vjdpwFfGZJ4lxjyFejAP6Vkurl26pxO29ODwFujP8gDCs0vTFwD1lKHea6ysXXjcmdQ3xGEEMZSO9r4\\/B0RCAstpy9mQLNtb0wSX9YGiWsLBCJ9\\/ZQzODd6biF\\/LZBhBaTmjwoKbYrZl80uHzJDhllCyrbIH6yIFpQYswyK7bjN32Z3TcydD9g1bAtpJWbQtvi0WNQ\\/WcYjHUA20oEwFTeUQAuHLFqyBKWnfafvGvtJlZfBsu0nvo8ienKPI+FwlanzJwA38ASONXNpFXS1\\/LL4O\\/+kM\\/1MaDRHNlAFazCfRLzLHmOrkScUoQuw7XoQWd4Qa6gISv277uqc3qrz34t+blbqevZluy\\/rY1mQRw\\/\\/LFI8S0bSDydW91tMCDJ+b8LCVpfrH00f2PTgyKKNOf4PWbbwdUam72ftMKs8nahtQAoXSWr\\/5tedPb00QX5HjljhWRvCfjTa0GC4UkVXCMfKLrIpLLBuSCGlFyc+4Ir5MWNuTluKCg66nTEpVAuP4VohvAFGugVvrL5MNsfK\\/3K++waOz0gpzBG\\/rmCeg+OFvGFP\\/3fFiPCAlVgrR571txn8gtNGo\\/9wUSfPw495+6DCg3Z\\/W3K6qSKZVyOW0CnGvZ7iQ3eZAch46yJYlj9cwEmDAyA3qP+aK4V5OBiygJ9sPXmqktQ0LA4AdClF5olc4nFndw1V6B+nxddKKQuvcs8XYafiNn65ZHptqJG5Qr+vcJ\\/7FehH0wnKzNBAJBmyLJwrT\\/JMactWbKz519h3phsYGNrtGjj1C6oHEM4LxqTFt2aznk2kcjZYETsOfchQTDd62LCXq4xkczhGYgF\\/5HUVg\\/5AsRTofCwc4TiELQrgaZOJD634Z8NpcHx+DIrCSMlR+f7biPrPmFbjihUmhSFEpJFTMnG8knVUoHFXgUrskGNQ0reZJ2md5+hYr\\/TK2dqdNKKCSnkZ1D0BRO6AvMupg5lVbUGw3TiaK97WNVoWxI+Yn3nSN2435Of\\/kN4QIGtgGmYMXIi4s0+mLuzNqknhB0FBOghemdxIIOd+eoZrOfFwNaW9xYiWDA8LpLJ849LTSxcq+fHQ9wrrBuvnorYB+XbbOhXIftagmXAdGDfiiGhmONNoh+q\\/i4MrbFWjpBUdUah9wfznrg1L9By6E1rocanvSplEWBOsdjEfEQ4owznIvMT3SFSw76dOGlF2cYDsjgY7tfx0RNrrzgAeXYJ26wQckPOioQS4Cbt3oi4oYOWDI50A2hdpvFkUyT7\\/MbBcvQcDPI4Zmb9a\\/d\\/VeUnOu4OF+\\/Krll3BMkXj48P7LU5h6suOwy6+06nDCobzeqM5I0mpNChh8G8FG6OT+UCCVFjXMMaIIx+Jupy4ldCqLEhCQOx0dn1tEADDBkod8Nzr8F9uRMd5vXjO58MFPvJ45Va9Jyv9sEbZFN3i411y2VidqvsAd3hk6on5TPdqDsqH2JVEotoR\\/kFVnmDftYujcCepMeLjbj+CDQs8\\/uIOQ3N4VIVKrQKIhUVEN+pyDtyW+dlU67Jm3xdU\\/HA9tVmjsg5ilFJGh3fTIuRak8vy6ULiuOWpLIWk\\/h64RFngtVdNZft96HBMcEhf7FM9\\/ndN1ZWv0CwD96fz9E8W2w2sR30\\/IVa1Stvom663qUj3L81bZ77BvGC3BZyqJyPQ2TToCXbWCAihScCEoyQKTmhXKRaehuxxS2\\/WPGCaL6fe6+IHRoJO6\\/ionEk\\/H8zM52dvXxcRdTaYB5I2TCqLbmHiMba5idWAeRjI\\/M2mJfcyJEmOuyvEfNh7MjB73e8aq9L+U+Oek8tVS154dYuC8hqH7RA8XIaF6GTtYc1uobvcAlLZGr8sLekHg3rTsw3M3LYOCicmYzEpkH6IUJ2FICC2MkXPfrTdB2k8FeihO7jrudsFcrbeR2+NzS1WZM9hDpDFzX\\/ubdNfrcHA+LmTIUGl33nvkKUnH1mSIWI8OQ24QV10YsTyabrmSV0As91OKYuAbDZvYuvUJTiZwR3abSldjzqbd75rXjz7Hp9Xua\\/wpti0xPR\\/67qsIyDR\\/aKh1g+JKQnv0O3Gy0RKyP\\/PsR8FigW2M0d88d3tgjAatapSvEp7\\/vyxHFRtaOw2rknmnwmFuEupZ6Zy\\/EcvpHsJalvhWyr5JSHJIKZoHuZGCa0mmM0tVqKw\\/1UReGD8yb3Dqvyyh6Y2LE53PYos6xk1WCM15AsLz27Xu\\/m2vihNxFIQ1bUjDq2O4iXbEWCkCkUH+AEvUw+zFZQ4R\\/1eWrzAe8w0DhbyZ54Z2\\/nLSYmcjYPvn0VZ7WzqZuVWyyPjE20CTRFVMOnj7Cy7eb3eyO94KN7ngVQukXIvczrFpFX0BDQ7zrqQ0Ub27H6kXpa0H8FM6fHjHb2QhLTU9VLVEFKT95EqyKFW4BlUsYPwpEAaEkuksPLtLPdmdGZGW7J75sbx5R6YdY7d4dr1Gr0frD46XmARI1aUOc3OQeYschDg3yps4NgIlOSx6u0oIWk21Y0t1QjicV+jQiBAqhNMEbfoxwpw9rcR47C2qSeru7\\/Nyz4bSC4kY7FB1GTtCdpZ6exRk1OORo2mizroBGAhKXzvp4EPWB8JhxjFevIzg0\\/sRjXypnBaA0MWDfPha0dqhla8VURSOl1Ktfs6CQ7Qr\\/ag3kD03kGB0dk8T5qCnwx5j4l48JgBpLWHabRQ2RnR6+2mPzcBf4xTnb+O4VRJlzGTlEl49\\/DKu976MjHQ0DGWwLYmOm3Ng5iz+yhrOxCVwZQnVsu\\/ezVW+YTnUScNtl65\\/7caImQvmtwPKkg6juG+vrGeNUZKyTWYqR8Uh6LNksFFKbY9TCu6yXw7Nrbp3EmycLrrydtgnLYhUA9JoOoODOSU8fYdvUnymx+26FsumnZak04Rb8aR3d6VqkE+NiXKWyooUptt455aIkYPfjGC5N6WB\\/dbPCxx84CUsNIU24F9y2YkBSBofa8xS0bfoxlNW5bou+XsoU2+e2M5HPlJ+dOJsRa34wDS5H9cR9WuDHDj0V0ksTwVC7avlFIjJz7LNXtyEHnx3EP2lUKJpJwDhw5VFeXf+xrylzi\\/dMrq13gybQcvyfGibsAgB0aDhwuX1gwUD25IiZ8iaL2t+6GxsDSLwD2J64MPR0LAhoUVLFtuMFC8V\\/EEvl\\/8ekn3avXX0CcqsSrhcqvWUXLr+HME5\\/IUVZ7QeZQvhcg0oWAIj5XzM\\/p0AD7b0Jemt1Me1\\/\\/zP4hp2kAVmerh+rE+67fI7\\/5KY0GZesADqbND4oN9rWxSYXDIAUF6kzLvkDJweFtPLKyK7CYhfNJUs39LMAqDzdTbr5KC61QQZUVyX4ngarav7F+S9lpSwg0pLi9qDJDatQBeIWQVnJbg1ubrhioIRrWwdvr0IFMFM\\/h4+PjYn4SdELGj8i42XxPR1QUh39CshE\\/O4LOdFrlDIr9DTB2MCtJRJ3PW1uztKza8y7leelCaqpwVVH7PfmmtJyTRqXQHA7npYluA4+MUQ0097qcP9iLiImXPLQ5gYeqfb7IyNY7YGLPwNUVHQxw7gpcKu8WN7+21dUL\\/cqSmFRu20Y9dqQM3qtisx185l4vYFd7HcwyW199T1z2TgNea6xVh3JwrSYaA4DbJC6bOftaU1BZ+EzrpO\\/P\\/1gHjLKc2vs7XrYX97KAdTHKgYKae2em4EL96y7HIkSOts\\/+aiTL16bQJsiPeD0l63PwTHyxUgxOSlsDa3e9Yw+ODxQUSfMyQnFGixav0x83FdLVulFWamdMrnd0nTIld9lvGNzA1yuGnzKQP63FBcbpdl9wCQaOlm\\/pD4Y+KJ+ZYa2JEi+QfFLUfKVqcyRLCP+mZKCWaN8UJjNexGcNekDeYQTYEJ7dTfFuxgQUlQNDQfozyjaVSSBGTpcgY\\/fzVQDaZj4WFqUHTaXOuYlGeIpwwwVOEVZC423Mbzuf5qJe7lqe8Tx0ZuoKcwrKXCHC9FPuDM7L2CCXs+tNOD4qJXgh9UZKkE1DqbMUZJLl5cOZla708Xez0Y83TtAIJIfKxL+wyWR628CFwEvQ36dcRuhS1OpV864GmwwqFxIKSeBttgIVicabQWwgDbqyCN0QXGMQCWdshOhLnRZi2Aq7ayqaXs\\/9nI11DPKvUUOUrkk6qv49muZI5GOKKMZAxA\\/FfMgaqzNavDNsKIIQx0LuElkOL1zmhwnNXFzpxP5bhjUK5C53Ou30ghKTcwfbKveUd0xEf7Vy1frK4xeSBT9t+V01n0FCT04GfR9VCV6eojUVqpRtbso5Wuv1OtJkL0\\/\\/8eqpJ+Ozmo8fERAtGu\\/IsDkHqCKwF6JJMqGwKh38\\/eEnNcIH9XRb2iW7vdfXBLciUQQIZ6G17G5OUP7LL+3lddf4xh1YETKlglIfOizyQTmGmTc2iT\\/mnQh9MqlSCgPe0KhssZt7zkkI1WyCgtMY+gubSTSvjKIy9mchQnp2jsZ\\/RyASEH1\\/njgEthClo6tsSLnIuvvBT12oG9T5ZCm0zeDLRKl57pp9fa3GNmHBogSY9U2JK4gnxlNdewdZAfS931ggRtcPd6JrDXjjsCRPUtnl6aDa+e859QXLQG2R\\/tbU5s3JDhMUipYpcArFtNR+p6jltTlLfy4yQNTrb2TAc28U0FdqiN0HQjlaPMfGioMmbbYeojNFokY7QdBrSS+dNU2LMzKbubBQn8VnahhLVLTJOw1\\/DOgkvjJMOcgrg36UJnoCdCTk1eL2iPVRuKGtEOWhvurQPaJeVVgbZFOtPEBGOHdkdL9dSfyKal6OrO30G4hvgd0KRZ47MXbyKUJAnnuPpQezGFjeoLUpDs+1xLkMb1k3GAOqRViLCAjoFMAB6my7GFfHoVXJiJPiINcaYec3kXq\\/eh0YwSlTHXMcTPUmYaW9S0vztmgblPIbgAiru6AQgvZySxxZPfplcz7CFuzN0h61bX51KTF0vrKfOrQJvpErEwjksYGt8Zl1Gr4a2GOYYEio+JGQ0pB9U1PwtlyQ0vQfq9Rp\\/sgyAxTNDhQTZwvvYV75G7QwUx8p\\/zk5kkFzkuc84Y5iUy4oIv0pPidz7KeW7BJzRkxL+z+uAbwjIKa1nx+1\\/kfCGNwvZDLjt4AnvHhu81oejc3f9MycWR3R6zZAqGbNeubwQ1itrajwHkWuDA4IBzd9Tf8r+miRpk0XCBDPtSoXwvVfRFgSTeAYYMjZHo9WkNiwih6lQCzosF44nyxFreJ7Ks4pzQJPdc83bWChQiE9PdDCrQeuEngphxTJsLBSfNKb4yqeEv5gw1aRkEW6hBuX+ELqimNCN7kwrwxMzWn\\/mfB1wtA5q2CY09md6xhMAE\\/9EMCX1Fz7GiWcC6w\\/h2sioKgYeH0RYRqoTkXxrHKFKG0B0USUhivOFnJPRTVRKMRUwWuOUZr7LBTSXOxneU6oRz9gXaQPTtJ3u5uqwYTcpxFJevN46jxukHDvFKje2+pYCTG8QGI\\/+t48n5tGC2jTlxAVdxdqA\\/YpK8iknsYUFYbi5zylg83fQPbpn9O8JwXp2XJev5G6rCGsuWtPkixHli22nHprXSsvJVqmuCwSMLOPN71IkEVlmXh8VR7EqythKAYDm1x78WIowLk9tG\\/PYs\\/azU6NA77yPNRXikg\\/6dBcmHG7SXgkolN4CWPudzC2onFD7lWk4V\\/fWxM4jDfMhi6Ry+XVWOCCcFNHLlPinLUOj87VTdfEMFIChzYf1Y\\/EL9TZlhlHuOXK519aK19XqeKhwm3IJs1Xjztl2yydvpNUSCfV1hqsR48S68xVC9QC27jt+M7l3YfrZEwT7JBOYF2zhluBuud2PRYLkUm8I5PyfBSQGpfv4FPTaF6DiARMC337AOmiuc4cAi8MR\\/zKD4Vz8pvD1ntV4d8MMmkLAx2OKlFIuob1txAhvzXSDgdKZTCm0unIqMKWRuy+6kVlRx5a50jT7Kc5qbxERVNZVhUtYW0XAo\\/Vp4HKU4+XxHpx3XugWo5TGFqT8rkVpTtd3WE592SmpVNlOvOFIy8Jx9fLvZjeaw0AxknxqDT8YVZ6ClNxuG3em+31pcrBuK1oqDfvYVq4Y465WOaQ+\\/FVnPDoE+ZDkKjozJ\\/M0l3iwxzqCJWoB3JCaJzwMrPfE5Y0iFlXGh3JuUSoaJaMqHcJ\\/2qRE7ydpeFEA2UcWeANOjsP3ijFjycXsdyaazGuiNXkKSedJKpF654fPfAJ+u6s7mM7KvLZ\\/phmXb3flZ3MPm9dPoS8LEW1Ic2e4ltMEf38ZNZ\\/d\\/0LRuEqCF1kjOguYQE7Mi8L65eojprhd+lhJA+u39bePG1BnTWa8wWw8PfzOocifbmxeZM25CNybWhI3UrM0w5o0hFOUqUWrgHgSC2zVF42dytYAVzArZnBLlFXCusY94d9f3L8nibFVXhknhimrjqcBM\\/ORCaBcbbRdPsduKVP4Fr1nPgDOu3xAd7PtnS29FeK5swtWGvTmm8tpBMMLnc2UIjtIUzKdW3SWuDiwJ+tuPSwx4m+rHNPxamVzR\\/aRp\\/57Sj67dPWw\\/D2z8ZEGZ9KYNuL7gvnjuIeZRBYnVGpQt4DVL7b1DkrA0dmsUfX\\/gyC7u\\/R0KUQF3UxRV7Q3bNXPivit51XVJvWSuSk74tNI3Je600Xc6Zp9LnqnVkSRV4D3Tl7krWg6UiDOeS0NE0r9C547c490VZUQ+4wqOHA6T4rWAnYeFp5E6EnBvnklTn3UpR9poV3GWlR\\/If\\/L\\/2WvF9FQkmSM3k8D6g+UjhHBMrtsjz5StPioRHs73QjcAzKrhfzFHdEL\\/I561jFfs9EqgZCr\\/MAN\\/8s56+PZay7KS\\/WcC3NQ0\\/JzHfwGkJNqZV8aiv+C6HZwtzXCicuohy\\/wUjjjaHOE0gf77b3Y4UONpRTeiC+h4\\/M0WCZsKBQbNOJTduAFbjioAzWG74bf+Clt4e1LNStS5jfdn3jPaZseW5EVqUXRSmwNEDCaYpwKBxwhQoaCOTgUY5N9ydtQ1zS4Pmd6M2d2YzxTCDFVRnQyOV0fAuQrGgY5Cx400S2FRd5Mbpj77q7rnuTvNbls9a9WfIS9zSIuoReGzNNf\\/A\\/sFSh3H3FlN6UfHHJHtElIP9OubiiWr7M2OP4DTn0HkLhDRR9wz5gUqu3xYHFe3HkIUyw2R6GNduSkBB9Q0NJa9nZCM5mZv3Zr8PIfEKmEUcuqUiUR6GnNUpHVIYDERTn7iyteLp2IhXOxHQstuwFfTore1B\\/1Dq4oKp\\/2vSBuVChdVM5RKkGjePnX90WIh69v5i0KHoMGnCg9q\\/zDtlg37x+oIYO5AP681JBHEYLPwv0PjYaGozra5uK1aiSFOCE2P0fUHOk0cexUxXhEFzaysRJoAvmwBiAiIYH1eI0wDJdOQVn6xyAtiD8\\/aq+OVgi3OoWbYbhIuL\\/dkoYsxn4uXADpCSmaUj02ZXdgZWI3PaR2HJpc7sxsTAs8R13YZCGrj8bWayBnyiMxA1Lr06XCq9GF\\/zKpthnOYwHfxrW7gLJlmgpRW8DWRljnTOO33AqyMiRabWMTHIHhOuwKLmhGi01cbW0IIvcqCYol2B7xHVeMMzrl2YbTHTPvVJOGLgnJSsVWvpTsUmvq4b7CZQsc39HR0l0zE2XdlI\\/XgZabEazd\\/RqeHL4BqTtVuml1dSWtwOGimQqXpUndoJSaNkYHKX\\/EcHjyRz8Rbu1sJ97hVWKCBxGjk4HAYwrElKT9XrJK97JWDw+cv7osq+GM2Qe8AkBOn4wjqjii8HP60gu1iTv9qyA6mNP8TNuDzMn6jM6dRT0T6xdLNHfxORAbjggBt5jP5QDu2zuxe35gDgASk067Ow5Q+\\/Q\\/wUFKN3MXyyA6SufnChnZnceB5SuLml8wEe1E3rypjAhtFClU1dUEahFiKkNHKQd0ht0b5kpsjDnsPwm1RRr9pPjkJOISN5pvsRmKRhkkfawsS4kYdVqwqiaYNU3mEhlFKViDkUVvIhhbGspAlwfstnjM\\/pdv+PYbBKD4C+zqjCFm\\/f\\/zCZGEBJidgmQlbTWNRLVepk0seW7VgBwZz3dq2pYYxfFjjWTM7HXx4gdchFik0MtR5cgvoV6CrDT5PYa6Z6my3xvN3GJnDIuEjKp1pvFYGwlUrbXHA0pTvoopvRh6iohjZhU9xqKnWFI83q\\/enN0CoygmqisbM5hgabovhftc4CPmztL2ut8PqTnONt1SWwAx0CWMaGSTetMPHDaSFR9BT7q00D8nH6fMIXVaFNY0DxcT5UxMpXdTwAiAAf7Tio2o6RXRhvZUdtMDUtlinZrg7N1YWiv9yGUn171PKrn3KxVrHdQ9fDx4tiCtW4W+QPsl9MpwlHecjC0yzWGhVHumzEb6\\/TebzK+JORBGDhx+PUM6qAVGkyZbjRRHnVZRby9b9RvmkngL\\/75yQYcgC2o474ARwHqD\\/I7H3c0R69Hjc07v1J0esxS9oYc2+d050ApN2ri3iIDD4ox9hI\\/5DUExzDgJywsx1XASYlOskvtndDZVK4dIoyemwsNlvSUnj60yUGmlnrtUCTm+zu737SDSDtvg5ErVKFJZzWTlgmYakcX3t3jNDqRqNJ0Qs38POmfeN353LGNQgBzswTD8\\/jDvC5Uwi2Fx0\\/z+AVJdacPVNr3Kom7a6KooVZiI62laSbbxXBpv7wmBZ86r3e4MaMSYeKhYyF5OXJZ+31IhqOOfJyxiDmHKC8vMl1oV1zz2SnzF75LNPC9I8d1AbnA1QhMfRTo01cStkozJSEqD5y0IWXo49JhhV6OXnZkyO80DUbvPhyZarF3nKC7278sBmJ5yj1xxLGCnGl9Wpr91KFatDQogfxQlLiz3Z\\/ciLbDwoQzneE0Fym\\/zHq5s00OnoFtyvh9MY5gBFMbkYSRkC8\\/dZsidXoCaS9WAmPJ8DD1RyK+cqvES3Z7RLWhDJD+tBBDRCmUHtmEckyfU8LYC1dxQgohFn9bSuMqnhXAWARz67YYVD9h3y5Ctcowy\\/G+NlAkWE+l4k\\/HxAoQxkpyVBZmvyAi9tKpr1aMWRmDknljssUZNPVDVAKqDhTqo64K1IRv9DPhPFLk7iADB8RtP8J6yAj2cdousQagOLDw3pef1hH0Ht5oQIl0IcyHZplrpz2F9hTpA\\/ORRTvJffkhKtMiSbW9pgRCTfN8OoCT2QfXSSIY3+zaYBkH4aNrzKo2ZV9gZ1Xf7LyWXsTkDcKJ+D\\/07OKd14H2oW9GsgCRsz8PSf1oZyUMGpT0GnY6aI624lZFouaS99MnzAEJvnzFYUfDyKUelIeeDcRfzXquRX34IO\\/1nCoS+uqhwdXB+0LYVe\\/g26P9ozSljTQRd8WuRYfwsYw30UbKAtG14KxLP1LXQGEADtjJHiT2K9WXACFi\\/l9UKcf6BV6T+3w31y8b6N6uveRIdC5N3vVXtXvlC47Bf1aOi8fwZNMXg\\/41s5Ie5Yz+Zvwc1\\/zBiC+D23teI3MTf6Plc9HLkb+9oATv7hOPp\\/yJjtZTqrpKfB79w4kRB8OUDJFxTrRWTDpjxYXwjwvxnaCfxf8WsnPow8eK0slWOwGB8qYJh53PvOCkGY3HHq+GPz3\\/rI\\/aCmdHhgxg78UTo1nnhruA9a\\/Aq2Qo5+ELmYefwMwP91KfxmgoMPDOJ60Ku0Wxq8NqqLBlRczGRDSbDcVWyXhqtIbXqK6L9LpJpa1\\/4IUeQcaSmCmfxrk9Aj1BT\\/XIu3QhplTJvynkGi5lDI0VW8ZiGp1BruHK0I\\/Rb9hYv4ua7gf330wddMohw4iTB7ctuTfNYDitUHP2+RuCbW\\/wlYvLKyqJqsWBTm0QB8ZIw1N+aL9OxeShbvnUTWH5jbwX1HJ9JPvMpnnbl6wTSp9a5ASwpaQZ8lN2mBVtfjdKEiPlmvsPnpHJt2rig1\\/UnEGlngHoE0LGgfUfuczfprhSTsZF\\/A7EAzNVOhQdPTbdR+qUR3D+sGYhejdL\\/1xUHkpOtJQj8QFq0JLx9XLoiNW7BrbubqehnISHd5KVhOygOTRLG6x4KpRSvf41DdyUvSEwUX6dZv62nBP\\/6SOzdUcdQHstmD5+RwvZtlE2zoukcNYtjVgK+Z7+hthQIKVj7d4EN1+6i8QsYpCC\\/kmJBfMPHnhGtxoIs9f8LYCiZ9vLCui7KQXQKYILBayoBao8lhPpcCMjxg5NOiItw+QIaMhORLgAQxbPyZQtoXFIcyiBmvgRQ8T2UlZPtS0z8CZJtIEsqcGR4kpK7bcnqBgfggBbspokO1wbmY7MdL2qpd4j77xl22Q0p1K8fU3GIcWVg7tmDKLUaHpmf6XsQ4t0gEoUeoHOKgWGR6\\/FaVkIO1XWcjIFlXr6NH7QJJahPhQfaHRQMEREmFvR96EM4+u7tlEaO982nU0q7VtzVIGfUuCZS2YiN4c7NCjexiXbu+GeK1jF\\/ahBt2896yPbJE6bt0JwpsCRt0mNoVIflCEDFwE9EtZuffc8hhpmXNyVamh3dXz8zDfmRupAoMqkEgZrgdvIJZPGU8SFRMjL7BLJi1W7y7J8C9wwnElGK5+nI50c3UI0Pxao2OO7Nevc3yjx4h8byEFf90ToI7mEcPnedcd4VpXARgjj8QsQ8zZ4cNoUvRjgQPf7k\\/GGi4bIX+5V2wr8xIPxmUohesK8mT8r3KqGS64wRzPFBVqYxUq3ZAx+iJ7dAQwALW2qYHE9z6iR26xQlJK149+WlCiGKnOhdf2+Xnq9tjZrWHUbckOc\\/F+bmkCQ8xdHGXdh+qhFk3xKfAKWHHWE9o\\/YOg+KZ2f05yORAKA6OVKdXzAicqkvBM+RGJqu4VnBnSdlXgv3oCl2911dFqUI2fBOQ6Dp0f9\\/6\\/Ce44gTBB7ZIJoUU6Z88S3UYmZA3RXCiapZziM\\/CYjFDdSAkbQb+gzaVt+A3elTUvLgiONmtVedEppGmKbrDZ\\/nJpgIv8iJyORJD9Lv\\/4HA\\/iExLsa0qBvL8zjzuWEgIEH5vytaOUdaQUb+Aw3woKlH4DEztGTFcAVUuSa5W+RIKRUCrtLHPyUVruARto79fuPdKYnV6M30rO9JlcVmQDv1EtWzWjYP5nFEk7FWjefskB7tsWNmsq6bm6fznpkGTq9FiFaHCDwGc86RhkXgh9ze1Oh9ryweC9WLThyy1\\/8uZyoq9iTzePawqenCak4hOm0aZw6Y96lErTvc7raPuCrM7uqcOjmiwaX1wNTTArTpkDZhkc55JD7Rt9M78wwmXq4hHhzUFE8nj3TusT1ytuGOWJ1VNeHjLsWgGxFtDDGHpa4OgHypt5jz9jwqlxeddEhfWzRLK6sPSNS0\\/p6av8PhHspyQiQJ3qqd7VPbblWH7lmQOCNF1rzrWZpcSaJas4jMz5QS9R1\\/kJOpkxnxUX8\\/QMgFkCjRoqu00vHF\\/CfVQiqr\\/rhE9L+Hpk1g1LXDVDdxNuy3Q\\/uwr+EEqKF8mzLFJxkX1jDPxO\\/JJJPkrv90tBZumxv9KUI3718lg3ktEYXC\\/hC+zqmliLrSxr8siwqU\\/F4wDoLohQc3Yb1gi4FaKUCS1VmkFky9KTFCXGgHy0WHc6tguJghEmDem7a5DUX3YWHdh7a1nKynu5yQoYTVY\\/fPV8uv+tyOOKDxksfZYf+uxVQVaKmr1T+gJ\\/VEBKPtCNvUD8s\\/7mCdrSdEOubOcvTBXBqEhnvpwN1nkx+0MV6aFp2\\/KTEhiqb4Ql3yeuXALxFqr3kRvIsxZ1NO0F+bs2tvMcgjaYmmGhc3ZpFRPeokeFfVhYmQlFuM8DTgthqWqUHjgK7pewWLEjIrzfXMBJLLygP+HGmhrvwvzHvBogj9eww1ry4pekdDTqKEbM178i1hPlJM6N7YjCzxpMqly\\/uXIoO8DkP2ylWCsB6mrIEuVqombq2SfgrP7mouDa0mlkrWsdicN3sk6TKDUDZ0XWM9p5a18a3yVYl3vqX3ZuNQRHW9v5zO7ZtEPpYDT6TnjDlJGlwNfM0MzxekTZ15\\/lRMg0GWKe4klWsO4sXhNsETN2\\/41yXp8LT5s5Npc5GfbJH8TKYv\\/CKpnRmCZCeh0MkSHmtHE7VPhooVauIkFa6ZMDsoYpEFO5hujdoNAG7FIVg4ROgCv\\/+0N8FccZfuFaYzs3vniIUkuVDteAnuNGCjOc2k5pLUnkluqh1sm5OkI2t8wUCNF1Kzl2arI\\/PQQjlr4dvDvE\\/0KGDkDTY1faNVxs35nXb4uuRgzotNQN3WAutx3wPrsj\\/NZfBu0enKCxR04M5izpO\\/h+tjbEZ2TDWIn\\/Reg+VotEnKeicQdYGdK3eP3y4ENPwStafx78G0xsM3Kaf0oX6s6Rci+At\\/Tvy7GvPycpmdb9swYMZXNH4F\\/qGp9+\\/ceCzShbNAixD+0F+ykXAb80e\\/DHbLG1N0J2GTQ+MEcAN29OmChv2G4S19cjea5+Us92PxaK0gzWx\\/mkz7BYocVCJXuwd4gW6O0l755OuRtUOsejtdsx7dvl6kTD\\/m23tSJZiUXTUNUO3glSmmz2tJhIvVZ1su0OjhJ5l4oNGZLiNs+IpX1HObBqCL\\/85II+BIU5xRILtQnBTfJqm2xiPV5Opz2LmBgxdJfy7J2M1UuVi1Q9Sg6nii8QJ9Y\\/q9VqTGzbJGHa\\/wXiPtXimAdwX257hHfw5iinBAhVumCbL9bhwDgrZobJyBaMLPhPsaeIME3sa4M\\/jOTp6e4Np66gpURfCzqPXEjXSkCpqMXS3cmhT\\/MFwHNNdT64Xw\\/37mhO00\\/3G7JYXdO3xUmnei9+WwY4\\/BCraqEvCmgnh7f+Q2CuGRuDEbc\\/mqfi450u5z+oyjBn993xukx5IaXLQ4yQJr5r\\/xfJibMdmS4XVgyGDuHhHT7kz4Sv3Pp2B3BMDqDE8S2pjl4lWmBT74vc4v2A7Ojb+4tL2CvPc0wcxjbpuku3pt6JfCLkcWVCQ9NDkffDH5Hr2KtQACb8X6IS3VVkQkXMUPoKKx+pzAdT3SmDtascYGvWrGNpwE9hjDn53MoohyODaxu+Gi\\/T5VK7BuB9mC5ICSfANCZN5s4\\/mOS5XtnrTchNBvrAab+idEXdVJkxMmYC18bjNRMvtfmX3ZxG1ISb1LNZ8VFym\\/+FK\\/oYaTlzorx\\/AWEIC4R9MkE0YpeAfB0CxpcPZn6r2dfaneap5zyMm6GAT7sm7Nypp0w+OiDIH0QtYZ0MCIudpngEUmV3mGaWVHLow3sweBEJU9qFxFN8verV1R\\/fq9O\\/TPLfZObM2RU+YPNRUaQsQzde0V89zh6KaKRVFMe10wrnvG5J6XU\\/J38Pqfrd+8qVC8m6Q2qGN3iROpdguMo77YZhxamrOs\\/s4SOK3vrTZqCIsYp6tMkhrKLqMxs2Bj0D\\/n35u4vZ9uvW8hW4+KGsGC6mc1GyoyVMRJAwZve+DG+9wGR1HwBge2GvJrWLStV3qDaqiw79iKTWMQvzUDSOUkgVGoifNhvoJgnvy0Sl8LnRXnSREN0kl9d2NPc98cVtreHa8+7xh\\/exWZs74Ods4VDMMOznH5V8D+n3Du0lT8xByxU9JqTpMe+NI5nY57RyaPdI3fK+NS+vxaJFqCInlYXuluEQWJrzZKVLxqpzFYoZEzjh6XUu6rw0xu+qPthjzc5r9uvxJyWF4NqBX\\/DUgPqmKYYDMFZBSb9u\\/4h\\/2ZkPOufrqAVW3ZhcgUprevcuz6SswEVEbokTwk+uwESdD814J07dfjrrH9sTOYJhcY0ZRQQ0C+DFO7xMhpWG4ynPqEUNcX02bq3g8Oh5kAZ4n4QBUmK1FNdLZ6SN3ueldg9rgikgeTXaIqHdj0PjZRfeJLPp4MhIT8oZUhlPsX8LsmRVGCeZE\\/08rcKPO2bRLKjghFvdTWpB0MCX9EWQ4QZUW\\/o\\/vAKQ2YH4Pl+rxDQi7+9ihBfXPd3TmkdylqZN49PBTit\\/MzY5J9G6hNmuwI1blKJ70Df9lg3lZmCvbPcQFIBcEYFiTSzPglk59MX4YuOnG7uZdiYYQ4dk6oFWrTgDHcqPEHjXP79JocrVP3O\\/MVlqMm1+Gf8NpoQf+lWMB9TLN86WijbcN8\\/5LJHurdI0p4Diz9kIXh5MmkpazvxkgPeCHaWd\\/6hZiK5paL8zzeRlJB06whxacaOufsiZB+taAExAEIivwyew6AYCTu0qX141L95q+09fJQInEIiyHcrA8Xmbd2G+ocyN7m3+77cAOXFY\\/UpK2SGSv6hOMlsDYSeXcL3JI+7uBGwBrfVNKPMgDsEW074m\\/g76jPu42it4JlRbYjS1zoQdfLPkc\\/E\\/dRzGOM3iMn+Lq\\/FI08BZ1qHB5ogmp8ZNY+\\/L9B6OuEux0KsTGF9WlzJtBOqbyJpwr6Ej63FfzIXX2\\/dakuI1dZkb\\/GblwbbujG7fv5NFee\\/5KUJ2T2spdhglF11Q43ZTnoy33ddSBARw7TFHFuZ3776IliqGCdrKNCR5u2p6IK\\/OFtsp\\/QOElJ0l11Fcz9IP0aYEI1N3dCXNnh1UMGMsPd3H2H19LXr50IOldTKRc4T5vEaZO138fLW\\/VGcYENiXYZDkhTeedjNQvS8rPdyt\\/ckOAGPkOf3nr5LPAWw7GLRbwxTyxAncPaUetCuY1LDso3korbEuUeVZc\\/xHv9r\\/4LKO0R1L+rHyucePbCvNNYIXY5o\\/yq\\/5hYWP6RQ+c8gvOSr++BZmK7Ue6vYjO9GsHTzgUtQD+3JrCLS3JK+o6izOYjkAu0BC+lqee115Nc2M0w44og1d16F\\/2sR5eq8RDSxELxksAykTYJGzGZ80FUP8ZAdYqboRSfq977T4KX\\/RZWKKDx9umF16H4ey22BAoR8iEWkgx6Mt4pnJbc3P8HYOwlfNRXLhvY3BNqiloLeGOFDfhcBtZq7vpi8glB\\/WJUr1lqoFiySpVSzRe0dFUgTD9Efq8cbzxx8JGX9x9mVrsZG58bIMYG2K8O3Z7EVgf29RzoneILuMD9IWFSH114EoravykpgXpGFbtM6Sw12E8\\/XFVMDnzkKo2pnpPs4+\\/MWor7zNvo452zpgTpq1EpzdjKYIaBiq57e01bscMZwBeqLi\\/S7MfrI4SRJtV4GZZ8W7exGl3ulw4zaJeh6aDlWH0z6MBibjzd6NTu4MATEbJPZJ5aiTCSmclwZV0IXNTb2PfvqhPmMedxNtqyS9T78z05aGvfdXgWpdnq1zQvKRbiFWoFK2e5\\/DGRz5+LbzKTSipgRYM9u8mmChX89tC9ApAbxARytpy61sEFKWglgjhIKJK2GxMPpgo03Rm0l2pUPAw5gTvSq\\/sZWs8Zm8BzAgzeZir45aHAnO+f2L5RMgTfuTG9w3rYnbQt5w1T6C9x523FK86oGuekIJf55rhGEoY3DMzw7Hw8bkNaiEW6lBLjg2t6ho\\/kNbjU+9MQjRFmjo74m6wApRX2WfduPSwCKh\\/iu02s2nBMGaS4Cl0qqWeCrB5znQ9EoJQWzkjJhL\\/KjSwYWxYjK6mZNC3FHuQvQDezVYso\\/XRKNs30dWPgbOW8C1ZzqUBl7zAkbJcfdjSoajz4svypPXfhP9vRgTGPG2UnEvFxWhUeyuW5pf1CtyrreT9d4Y0GqdkNGz8rs\\/MNSZyCq669rrow4VEmT5OKvIyeaUx1B32HXcjuprSaD4m3iu8D8KH8PE5yN9KKCBrVqQZpYSIuqEHQCE6EpxrdH\\/dlCxeOmOjF64SsnDzaAqvx8lTXvqCvFNVHJdgNDcgl+KbnBXCyYWwLjao\\/t5KnBCQcDWG82BhKIsvQ3Q1Om0DPLkQ9kK45iTtU92q4o+EBQpav9rLI0LO8HRhz1mmUKBx\\/RkXPNaGEJNbD+3hWulWUO7KgUeeBFoM+ncXw6iRrUbBqa3mX4EB1GJtg9UoYyY3Ep3Z97xxlehczi3+rLl7r6unV3wfQSgwZaJDISyrFIHTltg\\/rOndieeSCEjQNDmc2DNK3NbbD2bv57lXfizJVKNL0RFPnzLaAmF9mLMihTqkP+bg1fHiRtdz0gmLDj3oCBqlgwBcp9IAxOZcxOaNoqB9oCDGfBva4HaNWC78AVqJXvfWN2t6Hvf3d5UtzfNW08MU0u0+mjUxMDyi0036L\\/cY9plN6yUnbU62v9dmr3UkbTvX1dYX+I5m0nKkk6Z4RUXEhR7frZHe3znsIq5QZFppdNgYqfBpCKfJZSO728o1bvnSsdexqGQQTgz6O52pzZ0CEjveLd\\/ID2O9ZwfkIktiZc+otAOdMfjhyIKQTWRIMb4h7xg3M2gFMtD\\/8Cyf76E5lzzZGw1Cays9EzQViYpQyK+ILO7Kmk03ZWrlzq5gfldlOq0CD5QGcvM1mIC\\/nDOuqiPgg0PqPnUx0Q4tbeSRp7h1ywPwGBcPv9b5ZbSXlVzHc9uDvKSYau5nJOSmBI0GJ\\/XfntlVSvUPP0XJUdwKrJGYKVXHrZfp\\/9X8kBGZaVOpXPe9lXFiMWjor37Cx10g3YmUzckFOSE+a\\/EjR2ZROVSVbnJvrLqi6Wh1B1EH0iO\\/yK\\/WmN9PJpDVv0dNZvSphZVtmRHuWhPPNSQ6JqmFFPVk++4F4IziNUjpKf\\/C7tiF3+Cyk6q3rD5mBeBtuXwWFgNiXrKF3qdOBQSjEEWfqlx984zqhqetcE6NCcmpNaPhm0Zufm+OH6iOvJswFk33h5LgVtyAadugC+zJdA+dxRUZP4RwxLYnwFonI4Jr6GrhRKLrpft8+ehhhLHpmoOIB8hjKDr6J4WFqP13VxHAVXvpAPPw6PU0xR7xEa8ctGaQk7o6t5Jc7LUr95QTh71jPpnOwRXSxQQ+EzzM5Ij4P5dTMTirs+Hz0AH\\/AcZSREvWAzD1arzK5wCm3VeJGQaS8jbZPWwMoRup\\/9swIyO1lJ0gw\\/v6L4\\/A0zrFp+9mJdhrHlP+9r7sO1PN+QJNzEMuwsX2k7wP1oQQU0RfI7rdbsXsacNGYKrhx9TvKBoxTEcemvxjvPPCrOemKZamHivhu6\\/+M\\/NKbUAaVJRkZQR1rxioidqbkP3pYDqVhCyrZ8p9vi9j0vjnF4mwR07QNB8OPvmwQuzIUkneAEs6IVQVGnaeAW2P+FIkgLQJn\\/donVR1zax+TyWyLGsXI1iaGV5Q+IZRnXJ3EvmJIuFRna65lzTe2g5QCKOABvIivxNe+DI2213MudFmWDTIJOpZdtmA4wEVMGB67XPac+pwfgkNu9jlZPGogwJwVbXVE5qXb8HKLK8GYo5\\/ktw6KlRJpxnulGN14MVyE\\/RUA\\/PtZuZo59PWmFrCoTCVtReIci8SrMpjVAsacebPBC+5cbZ2QWfo5hzT1ZrC9Q460T3y4s1I2cDTCTBudjLm0QU8f8UQ7TgwKH+3VteSU2sJIEgRwOO4n8Pwqq7hxwxQoQKTvsng2mqur5Pd4IrTvqMjcTlP2sq2j5Ei0mkLzzKczQs65F1DrMZghFK1tJG2v\\/AVY5\\/f62s5bAgSNWks7L0IsTRonpymRrtQBw1FErfTF2YsgqoO5rHkXKXgILqN5+B1XaNYL5wuCB3DlQoR9XynJPY4twUi2mMsDk2TmtjFl2V350ZRp3qj9snqAz8vELayUdhCcaCSFmcVFUuNRh88RrzmgxlTpqCvHlhLAnmraCoprFfjbNTrQhNHz9avdAJjSz6fMghJvLdxeoiGxo08VbWvH0RfAy26BVUeDZs+moypctth6YSLe77jknO83lsVVsSvTqK1NfjLEz4lGDW4nHto77dCzW0x5N7HEAHuzG23hz3zryWhhNbZeK5Y5\\/zzvhLpwO6XsfvjE1u9OGVRj4reciw0bbeIq4GYyC2JIAGOYxHjp++88Au5\\/bBtDqEpCEMClqkUk6bChw83R8C5jx3jtc7vIeNjbQsD+ypwllEmhu7EKym5G2PxQLjEcJPwphw5WDkDtrJgdQOFd7OTdEOVndH9P3uGnaVQQEzjePw7of+deC9QiOFW\\/pCoDG2l+rC3DbOrs3Ak+4hj5FZT\\/aAVMbbW2p0L4mKOHSo\\/ZYKMHmYYoJmh5QjpKFqLARKb8N0mo8Gy0x25RmQ7aJ7c7sslgw87pGb2VZisv8Z9SVeRnpaEB4eiw5ywOV4gJfAYQP\\/kuhGsXFFwm8aUr26qqrMuMW7eS\\/kKhQw6KvFJWiu\\/z9OxbPOGqAflnUAm5ertK+1lZl1cYWPC0htdwH4Zi+dPqagq46uuwgW5SUkv2wQlNhpDpHYsyP6FJT0Xw5+NvzqmSbd1PCQw2RbB3eIJu6AR\\/Ki4ggRIxpePGLAHEkRmiPrF9537P1gpxI\\/ied4FJX0YoLf88QUtChZIH08PC+pQp4xsWCqSWcIZxXjZafPUeduptBu111OCuKchMLTodpf6l1Qp8aRdbxVr7EiaIpQwjN4k1GMg2QjK2IGVF2Heq2KPotyeIni7Td\\/VBtOsMIDODANwEqiMYHhqjH+hu9zihOD7h\\/eb4fUF9wlpwq0VEyHXNUmTfFgKquI5l+iSX880fEWzs8wGr+3Qe7CFN5XpPLLv6Gx\\/3B8+G8aU9+eaQTWrGAJO4qad74WZuN2LQKQ9h+8Mtk7Yd0mr7ZkzD20j2UlWJZHmYEQ4iO4gkSyzOLyRr1BwAK5w89oQQDBzneUmdTykcYomviL0\\/l03n\\/Q9P4UWRS+soXvAT5NQWRjBmQvHG5iguXbMbfQzw+pCEEtSM\\/IZOwGKpzH+gJwL0RJeGgNisiRaLf3VbfOAhBBOSgU5UJ+fBaV\\/M0W0c6sFg+B4pqoB3eIkIo3ogMNkW76nk08aXtPu7VestqEv+xwafqgw4XOon2uBpnOwy6G5yGEus94pPt1TGplWwWPw+1\\/KzJSj5hOGZdU7Cr7lL9JLAn2MuQmmWDM1WPg1jl0b9VUxjlcyYrh79kCBG0PxZzlpCPu+n6bMZqjsOY2IpE0MW6J5JCdSv1x5tOfZAHj7RxX8S6AD+2V2fidOSe3\\/ybZ4T+iWB4JtoFMydASjlKDufa6TUUV4OFaxQ3Nxw1Nu8sG\\/WpVySTgmYgPEHvZqav79Zm183kMoNwCQIwfWWBBkFcVFKpgSLCc2ikZLgwGZshCo9YfoEi5yNWDnwsVHmw\\/DRntE5YODqfrnyO+A6zZSM9ZBg\\/EM496UbIbZ73iPyX776pRIlNle\\/JGDSO9C98Y9MOM2TMC8YAks05Dyg2aOFVX2sWGrPT2c9TLY49bWeioMMKGOHJNOeRUc93MIPFDSwp8S9YpXGxfkgk8XaruAQ8\\/VfY5BmIpwt0WPPraClXIFA2d0VabkW7ccEE03BNe5OaMWTxrRRUiAivRAu2QhgcYjxyD0vc4ROgYPAtTLZhRE9SvI30oWB9+wKjgtVnKETkMuFIshaX7GNpWjm1+8bj6rIup2w7wtbL9gVx\\/lSzcWemyY0xe0yBOkvAAVX88xqUjwRHYx80GT6o02v19yjuOC60sACpSB\\/L9FRg0PtTsmqLVZBZ1QYSMzcFLvZojJ32Yl8xAKRT+xBumiSULTfQR7wF0kiRnOV3ixXe29o1im\\/\\/YMezdcrqHohTi+yPHVQXncbOjYdFeMQPjU0NgpFpk97pOYFR3I0fZgj7THVeE0ryLlHcLsHP6kAoe8wUAX85R0Awlhp\\/YzJpnfdWYXc3+lYz7GD+VGQclt1lvvlrYHrQEz6vgIZi0Iviv35PU966uqfo4IaHMzA52E1w13xkZvDo4n1vvxgmQNqR1F\\/97XnXgHEMDYS0duD5uhyW4gGrmCX4Djoai2RFMd7e6qKqTmTBYUmKknD2Ptm6RYrhVhkweJJgAFEHbow+Iqep042lLo+dU7DKbZnJ+0HuN1Pw6a7cKYiiYuG+aWFDCKzTdKr6BSe9ii0dGTGaBtJw8Ilt6XTETU0f9Dz87pZvuyKtMz2O77hvwxDeFBx7vyTyJsGK737PLnYvBBrZDEzLTaO+I5RihhHN8+bi\\/MiUHgyEig892fJN4+ivkookRl55K5G3MYuLvu\\/AuGN4n22t3rHN6AIOARsGFY+8aG6QLJ9WS2rEKT7G8cwjkQT+I914VDJHtkYlD\\/H9nl2B7Xdhb0QgbLf1Qo+E5\\/AdPlfcjWsOIhhtqUWijoJSqrBDPVNvIEkbWyq2DIte+S7S4jGs7WYGe8Y01AVIxuaTOOroJYlUtZhpNEho5YvQu2DfREN\\/P0AxjAe8VvyGFKE3MCDaGWyubEgbwm87RzLud8H6XiKUhHT38GcK4NnyUglNjj6NnG5L3D\\/DQH5b9WpoLqBWtRbkdIEpynw5et\\/izKu\\/XyEcDF7Dj\\/0k1Cx4fNVuGRku0Z\\/qHQAIOBJwo6Y5Ifwjm5wyUGIMJvvZgnE6h+uSBkJv3ixaIWhDzvH+8D57OUUYJ29290pAGzB9FB5mhJEcF2NgyqvGaY\\/E4wj4mArlcHOT1xmAEFVtUZxTeBGGFBb0BxLg1G9XodU9r\\/7XYgF7tn\\/z\\/bW+GUXrM\\/CQcZls1GaIlEDOsFtEJbqsLak6MMiKQ\\/OK\\/Zovu500rsQL7D9jucAj2GtncTocrnMQfg1Yj0tUnxBWO28ZTCZ4JyRkLE8wxagEF4O\\/cei2VhvyR0q2tl+uuxraaXvQTmg4FlK\\/ACLMP8csJIWYeHrHmSt75FMWlbrGOohXUVuLVojJDGNf9h7xpV\\/avE7+iANV9qoRQu\\/Etxx+62UoA7h7TTXLeB4f0yBbg3QA7Pdr7A9WogOhszjUH5KdeM+lYswMaNq4yh1By0iY4GkjbzrrdJEoOm06iZfspAaRag+PNrizje3Q9vtPvvdGHidEqRWeRytFiUa+eRZ1JJHEMQSpJTB\\/RPgBJUpm\\/fdhU3SFld2husJ7X76GOINPpU5ELdyO7u48qIOmlrSTjaK4zt8jLqYvbzi3HkK6vLS21a9rKxxgog3r0H+xCv6xgtLXJQF0iEsMrKMlzDiyMOrhduaAU3UlTXXQWRCTnR15xx0FPif6bOQ4hH2ii\\/cgxkPEB5kP0ZB93mpaBub8QCqA8rdAADaRgNgTvSWPAAeov6SDBv91x8x8AhVlhz9fiilJxaKV8yckn1N55dGvnwUCt1P3J95YjkLFiNTVavpxFbnvDvAjCRaujspf560Q0e02FAOePUryv+\\/yLNygMAKoCDPaQrF767PRUN5thVZ\\/a7cDXRclW40JI0jsH6SW5KmJfTYTCqcv\\/y9uq\\/yy0eNWIklpz5Xd4ya7B6rmJ7NZs88HM\\/00BgszyrME0VBIkvVvXX4cEuIrajrJjeeuQaeKftIqJLNpnGNg\\/lOqUDvJUV+xJe9qVUmPQpC5CyctjiKS7\\/07iGE0zaaBCH0coW9fPHSZ4jFuEnygA07vgmNjMQPpI7lRzNr3Rtsu\\/8JBBLJyNbjdJA01OUbGxK0uO5TTHPqwlndkGCqsmox2gvkgxDxmi5\\/3fMIBI\\/X7ESkxwdEb0mtOtmEm+USPqNU3Z5Ax0XOyugbCNON5cgxX2LVczBbkad\\/EmuUenDyAorRr1IDT3CAYGC62HKlgoyTPPMcZPEgVqfcfuh8qKcoUGXaGIQeVEeMkC6\\/kE1e4PLlR7Vx7gXEfoHitHY8CVmGnq66g6+65z+BWMq\\/9h6A812C8wJ72v\\/CZj2wb9tmvklcadUVJXR8br5pJDRy4SUy8aqhejk75den3gWVQD+cNSOofwPuIqoyQjjGirpa2zJBT3Q4ptfK2s7mhbE2jnjxZ8zNorxeSsoN\\/w1YjxQS1rPjzT2EMovAfeQaRCYjDsoZiA6mvB9vCyQYGRKsjn2ZrpSMJf934gVkk9GJ1LwGOnbzt\\/FxkHP+OWYVbCPbHd2D+uOiVQWgQIFNeblbrZpYRhh8vxfoPpzQwZP+Gbb9X88mqlymWrAlTU4apNht4ZRrxAhSpYlwumyioNaugivC1usRFF0YmMIFG\\/rSc6qjTKH+2t02xfdxN42FYxLYiL\\/O7SSvvHisW1Bjy2IgTVRta7ygKHE4aToHgAzPL7q6QILV\\/YCWqDSBKnE3quSRCXGnCNCNTMrYoYscJKy7J0myicpIotTiy+u8e6kwlln1CvzDJh7IWYLKZZKGU2Vqs4ute51eN9CMjsSAsm3xcHEqgpTdC\\/MqWh\\/sj\\/vVfyyol6QTA4OAMg2zw9oGbiyeth9N+NrXX\\/sYb4GCTGPao8QA0UKQcdbqRqAKgS96H2OB1462Wgdyd9Hmi1qiJtj6yY88\\/ZnyiTeO8T3RKo+PkVcXhbhE9oKOij3Y\\/rU\\/JkQQliXjbGDeyl5ZRDU4YLT5X3CsDG3upalP85\\/HmzDib1BCW4zK8Ol1JP6CH1yLmmBYRc2pva\\/RgTo7qA2c8hIOVCOT4ppqph5Tq4yIExtYe4JDm+g8DUIcBnvwWRAZV7pUNfRHVBiCAroNJl7AzNagngJO8xagC41zm7w1daXpUf1TU1k5pgjVV5N3ildZ9nUi2YsZIwSfvQIuY2yu6oL0yfDZU233zTZy1NYMun1nuOhK0YawffO3JQ+495hUfU4l7AWh2Sk\\/5MetBI2kz11+F0F8mzv+KuSDJXOkJgZny7OeQ1\\/oZrI5VkPocvR79n2fH5ajJ90wjkoRNdV9jime1A8LmakaJO4owu4IRU+VFmb9HrIauXHg6WDzj5F5B3ccE5ffgTLsxae8sJWTXvPRWAuKlURIw187033MvjzWcu9lyEejwaEgSerwlLlnOZZwB83\\/ocu6c2bKrlv7iKqOBxvxkOtGI6H1MfwpXQPw3R1+RF3drMt1XwJeLrJcZb9MIkZejOw1r8vz7aK2zeo2\\/ozs51Vabvx2\\/ynRc3oGbFn1nuODW2ZbQE6IIu\\/8QlfqVs9XCTmkDGdaKOsNaKKM2BArDTTqc5k9qyr1eIoTSVbEviFAr0DY\\/GTTjQNyqr3nW4eiLrwIyM\\/\\/VaO+yK0o+Fbrojo+j8hvqFQL8cM\\/oOvtsdeW2KPC1atKR6\\/hXaNikguCzCMQpyhz\\/SbPFce8Z0jkKT9+v8Iz\\/qY3jRly2nazCkQJElLyBR+mr39NnMC3e27hQv\\/+0bBJ3H+2udt5VKQHFrYG2catfCBH0KIk1vS7Ap4vmICV+TSR5t2Zp9aSPkdT05tCeTpUfpcwSMY+ZHDvtQoeFJsSnH66klinUxCCdxUBq7tJk3KFMd1021p70vwx1w\\/Y\\/7MiuWP2Pq5ic9m05Dpq95IkKdvCjh7ZtFJZar9cnODpldYEfy8HZb2PyOKLU5VcI7um8MhaJrDArsHq74TgTdx0IABehajCPyt2KraqTgdpURy4bQ2XTRssee8Asz3vzF4v4hzu+lIqvRjU8PJkMQzKzqfh2FtF7BDO7hB6ET3yehz+utuwRl3WgIn9pZgIssgvWcaBGWQB9IhcqQbtsUTzAYP1lE+5wbyuH5kY3tkNtQd0c5dEjl\\/3UEQlNC4AFUCkr7sEq0I7zTriGC3\\/3ykxv9vmf\\/DI6UeLt0iGR0N6uqO+su0sQSISfYKbGr5thqd\\/ptedBConi9OfhfmoeCa4cN44wd0CgNe5W15ELMlL6Js1OqO9JlKifuPt1q+tsl4kpiTS6SiPrnQjSlmBEiKoxAq7GhSfAojWM7TiCYLEKvTVxDqJSmLDd9Ai0RHkTmuzWrzH8SMKKRNg0ZwO87NfQDOc28nHDMAWwABU\\/nLA\\/\\/aX54uAPqB1VelJTo4ECvLKReJue7kJxawb3Vh3dK0ln5MdxOmZphgWI7VLvgJgda8TZDr3SRBqRP4GK9+Rw8EERI3RZQxMIW2CZEP8kdHQzaQAGSfkmTseFjQD\\/tffa2Aw+DWMyYsSRdLWobLezTH\\/gxDo6fPoKL\\/8raGBg9fbWg2PASRnKpWQZ4ApaRtVGEdG87jgCyBW0QDZ+QxeEsBW5bimH1HPdq\\/iJPZNj8gMS2w7jboG2Kw5FEYe27G3BjYhIOFxVUkx6zOtZx3OGqAtwakrkkja87EIQYj5BVho1+fbAXIimchRvmtsxhb2oP60P3z\\/qCI9cONZtEzbzAnxLFXTy5nyPadecwyXh\\/36KDTSEJ5LAgH3kLGvuPw9+wK6OaiJ96smKbTuAqVDjUJozMMZzS3qXwL+RISP3TOzJSNFQdGMU2ClxkRfQSe8nwLet88IFCo62cAXDlbjp\\/BDYklsQV1EF0eorPWyavNtMvWiVpKh9KNZ4QcgC8DEw9sD+cYD1xyH\\/Y8wrCaew3sSopHakMJ825x0ZTeRz7xAOyE+BcLUrQaQKuCWJXbXX8lNrwio\\/h14\\/TYDt5m2AZAs8F6uar9\\/+g94xidhxp9b612gWrnfmC8mW2lr2xPSBhPtmR0le98k3fbyrzD14ryQ\\/QvTTGN122seSeQheun0r+7oaPyNrw9wix2cz83sp0m\\/m8R53VgcSXvxWllDboQrqn5daeTMN1NGBk1NHWSEszmXqavf4EaR5tQdkUVJFLSfTdygbiCvVhY66Qx4ZlWGnniaxckZQNoJpbEPH84EK5d6RDa7uvOlgIF3n\\/q96bey5F5dNtvY2wuvA252VS7iEScL633lZcGUxSnODnaoJHGBG8QHvffiUnoMe+F8CdxQqGkrSz0l2EaYxJLJatvPKLhKwTGqOZCGkg56avH8eBROjO13Ht\\/V0BQ32lbv9axgpkDCi4qHRwcWYhPsclXsQzYDHZYZPVKcxlOw\\/9tU+wUXwWWmHLDOEEgI+6qPIDiafQGlD8xqs9ycpmapMweJJe9PSCYx8rpWj17qtr6jNHYU6u5wCLLPY0pF65DeIHdiuf7O7++cKhEGHkxvY\\/3DhD1vV56L4+YAK7y6zHKu95xMYlRcO6fr4kf\\/uyipxavE\\/RVm5ugy6Mwg4N+lOzYed0A4vIeDyBU9aenY1k4Ql4tjz1ivZMSm1rTkWHgFSdgwbn\\/4HuvcsvFOHiCKokmMvnfqQYIGGgryauFTOlVjArUpvbU81q8OooU6pYWRyXhLgAdimVK6TrEfaY2opzrnShMiupcEwMOM4NAWp8VKbXB4cJ\\/g2XAvPJ2dLVT+lrjgAmC\\/GFHZfjLqLSZJDl6qCrBbRlyzBVElxU89RYaILx1Zrm01WKH6Pfz5w1yQHRzzfErhgoh4VoEzVd\\/Fnbl1LVVbg8UlWpz9y6zZRblynq7cB0DIb0rHjv7ASz4csc+lXavcd3pbo0qPDNkpZH0edkYFYRxduavtHuQAzceg6Ua7tCKP\\/dwy023wR45Iok99HEjKimtnQEKtQQswfpWynpxlFZ3s\\/3QxASx2gKLoDeDOGhyI9Vx4KP9J80ajsRQbDePD4ATAZKM0vGlLKPi6TQbxHsKQwkwuEwdxZDVpOJt\\/JlzQUwwfpUr06qB27JNUqYF\\/YmUUrUg6Fb9mLB5IgNJEJ\\/70+R8C1+MjN16JpD3cmj1zuRCR9izAuV4lRJv3Z6RUuLWSCNOF0P2Zuo5CQu9PwbpPK7N9EX4fPMbWBP4d84ccYWYxE+lYKw2jVfyht3tpBrmmAHnePSrt4l\\/9nvaki3P3tED2m2LjFcw5Xti8gsBjAMbxWiw\\/2lqRWiLLu63IEr+nKBFpkgqgnjVZqYDlHg6pyZvTdKoVnU3empBhvzFqoPPaDSg6nKzD9OA5n+aYpzhoke3wtjq\\/pX39QrMdCylJcPtUfm5IEj+DZz\\/\\/lsRf0oF6+aXU\\/RrIaaqZG5QmFVOgwjCMJlx9YhzX7+RNzRXMt+378dL9KcZVxSIaOMaCDALD4JXu50h4mLj5gjvzw2DK0kTsDhMzFkYili\\/+bb3swVgQAu8wh7rU2PVLr9992jcszE+gmbTsyBCRdqH\\/B3ZLn+jh3\\/jCkkx8NP6o8c2ybFfZ9+72K6GjA349ThtvP9kylYHT2P5332dS8m54EnT22peqe7fTqUgdC7P220I7qR82A1GHzd7jx6EIsqbkgxHMUlrKGBPnfji97dAJ9R\\/Hwo\\/1ToI8x1XAiht8tBXjLNupp3j4Di7FggTbUlHQrjJTPOvaJVrIPQBn7l83vKd9likObVfRENR6PzHixGCHcyKYiW8dM5697Ng\\/mcd+PDJgINVOs3s33gjiBqx89WU0PiGUFt1UFZzkOcFzoMS79geYWnWyZZ2\\/cTgCEE3Shw0GeQQ4DBD7B05VGveUbTasyK6NOSRucYpRtCtlSIbmx4I4Qup3uLhRFXDoiSg9HhgDDVyQI2wR2fzPvf5KuzUrCNs7ojVQKhH3Fui26UIrQNxW4n01GyvAqbFmN2ofA69pgQwTQBRGX2RLuxxRiHl1Pcs4A6CC66c405WdQ9YcN1yHteFL1n8Q+LbWN8TRUkTA4PTxnnqHp4tjsmLYHFtOh+pn2wI+RJdvqVKG22dLDEQfFxHGAxsmOKQs4gVoUTY67ouuP3fFYNu6qeSogdhwWzZ2y27lcEn4B4jX4qt9blNLaQJKL0cO7URffPJd\\/EsTJwShujcK8QWUPy6T7+\\/h+X0sa7lrCPODnXUdSK+GPtl\\/1KGiPkul5AkaULoWP92qBI5tyFDMNgjGtLFcobDbRH+fYiC3mcY2DYHMZGmMXX8ci2cPPJEwziQebFlf2Dq0eh0vdsmLY6YmSTKTKf759fUffkvQa8HbJee7aMG5ARI\\/IVQBnQLmrEOPVzA5h4tVL13JFWJUyDvcBz7YmMkxeusQV7afJmi3fdCAGdi7lUjRJq6cACqRYFEJldUYK8\\/ZdXadl3p70FGTO8fFWUnwDc5w1eqhbyby6KZQUf6U7A4bckKX15GXvahvk1agO+9hr31+Tsi3UdanYEK0ihjmwx3SYjNeNV2IYngQ5sRirQWEjSiuO8hMh4PlGHecpkHinW2jF6LH1vc9xx7Bon2v8yDLxIKPrOJJ2HcmLL\\/8YJyHwH4pISBW2bqYIILB49lxVeXhNl\\/3CMz+PE2SQdhs63CTFQYZhojETA0gvt+l9H+kkxBe5Xa+q\\/i+NJIfaXnXJZho7gitkB1kcs9G5olSFa3s9gjOXdrL6p8OnWMNVbSTim7KlvcVqzQZQ+CuxdkMP9RlWRFq1VQESEHi9FWXUQ8esBVsTg3GjvjO9D82VYJWcyhDbhbG5ifS4X+HNqn2SqUYnanong+mP5p3cj1MSW9PyNFateDt7zZCNUgS98SDVn9m2zEcokpV3MTldLO4KUyIElLn6Wt9Tx5LeoQ1WPPX\\/DzhRtyV5uQqBQuqq6OkCw5DLpIkJH8MboMPeCn+flaCCLjymZkc6N40xnBaMmsa3YS7sqZ5WI5n+4exqWdfXMRhHPRvyJB6FMIGFymvz3wQH\\/H7\\/bh+P4tn5mb\\/eAYpw8EBKFe0HEPKkjaj95s8RH8KwD+7zfXWT5ccY9kQFCM20VccrfHAYRQuTB6CpJGjJRAaG\\/gjJW\\/Fjhw95BAs5ZNyob3DAyFWEvTj9jh+SZ81szFJQWy0syjZ0FAbYDIWHnckgqDeMbjBJTq8\\/n+zvgJ3s4mm5s9zbV5asbKtZW1nZhud1FxxXtrjQ5a6fj\\/YaM4n0YcwEKhkNhMHrJ\\/+RyVDw\\/A4MOToo8P4wTRQx4ciQ5NkoVdlT+jtTh7hDWIyKU4hfWU2Q3cYBxxWcMaR9ofL4J252ItgflNzqvC1fyyjX+\\/bMGsTETYfcckQaxCpUoQHCIzJ2XVcLMc8YZnrdE9wubV498jRzD4KEO\\/H+XMxfZfk4LjlGlTD3uwo\\/C2MMT+fpb2mM\\/2AQKAOZ1MhUTg2x44j0Xx9oUmRl5GjayZEoLjRB6zCLobvysNHOKqxqPqt3lS5whrnhmh+PHajqs8P\\/zdMtYSfVSMmuGMvbbsAW5Yd3tV3XgIuDYiPjoA\\/jZDqopEWyVUI9cX0BSY6kidd5tQxKwHb6mDtGQw+xJxzhkDgfOH3hEadE2apyTx4gW7WzayRwW3+a29bg\\/FBd6oq1mKKSTghRuatGEqtUThB63uSBqR6vGw4ljVwQUNNnDJZnG8FYN8b4+IMyMJ5iNwbHxCLXeGH7M5po5gZ\\/oBINRdHKYb3sfBZANCrK5sMyrfvmlOWleNgTIg3nnXcOZ5FBa+osq07benoz0FBll6pbR3biiIdvdVI7bb71Q1q0308mhbJSfo+zPXvBoNGNX63azRIIh07P+09OkC1CzQZaZgI99XvIQ4jcpkS\\/ZxEZ8\\/N6aQhVEeVd4rHcGtEVYpmNeqHlUOpFmgvLcxqkuDQ+3cTG3CxsXzAEBlEkLT5D2Oltzn+6W7duphrF7nHXiEo7Aw+HYbkb0PcLgW9GFvhHPL1TmHJoXS7qX5t\\/bRfQatOmAOpvIaSyrYMpI21Wl6nE6oAoxVo8LR+DsJaJPnLIAKPY9BNqcK8iiyxM0PdwY4rULT4yDmcttMwlDLV9FLEmCbr+P3aceFX6W23A9qfTtJJqwZKafW7r2JTRQx8v\\/d1ZAWtvNYlrlVlpPT43nloAjRCfgDVVqNPyN+m7E\\/\\/OL5qHOBDpofQUms08vZQv9P7Amiymur8T18rN11JqKUompDjMGV2YZ3dhWW8W3EuLSUaEULfKbMtGAEtLprVu6\\/KWDnBjAQpLWuN8op1TlbUKv8eEGWY50WJoRsNaE6HNXZcyq4uI8e+\\/r4XRx7cGvmbBnplv\\/o\\/3mDJ8jkO7iDwh7zA9XC5wzJiheNyvTbd4e0w47vjzZk5HKmq7oRRx+TKyYLWq2L48SAqADA=\",\"iv\":\"8b2c0d3615c5113170b7914103950c42\",\"s\":\"8e57120b1ae8b20b\"}
\n\n + \ \n \n\n \n\n \n\t \t\n \t \n \t \n \t \n\n + \ \n \n\n
\n\n\n
\n + \
\n
\n Home -\n Browse Torrents -\n Upload Torrent -\n Stat -\n Forum -\n FAQ -\n Login
\n ExtraTorrent.cc is in compliance with copyrights
\n BitCoin: 12DiyqsWhENahDzdhdYsRrCw8FPQVcCkcm
\n Can't load ExtraTorrent? + Try our official mirrors: etmirror.com - etproxy.com - extratorrentonline.com + - extratorrentlive.com
\n 2006-2016 + ExtraTorrent.cc3\n
\n\n\n
\n\n
\n\n\n\n\n\n\n"} + headers: + cache-control: ['no-cache, must-revalidate'] + cf-ray: [311ae97b15e41a9f-DUS] + connection: [keep-alive] + content-type: [text/html] + date: ['Thu, 15 Dec 2016 15:26:06 GMT'] + pragma: [no-cache] + server: [cloudflare-nginx] + set-cookie: ['__cfduid=d4024e7898143641717ebe6fe088111571481815566; expires=Fri, + 15-Dec-17 15:26:06 GMT; path=/; domain=.extratorrent.cc; HttpOnly'] + vary: [Accept-Encoding] + x-powered-by: [PHP/5.3.8] + status: {code: 200, message: OK} +version: 1 diff --git a/tests/providers/torrent/extratorrent/extratorrent_daily.html b/tests/providers/torrent/extratorrent/extratorrent_daily.html deleted file mode 100644 index c75ee27c7d..0000000000 --- a/tests/providers/torrent/extratorrent/extratorrent_daily.html +++ /dev/null @@ -1,205 +0,0 @@ - - - - - - - - - - - - List of today added TV torrents - ExtraTorrent.cc The World's Largest BitTorrent System - - - - - - - - - - - - - - - - - - - - - - -
-
ExtraTorrent.cc - The Largest Bittorent SystemLogin   |   Register
-
- - - - - -
-
Latest Articles
Most searched
Hot torrents
First Cams
View Torrent Info: Max Steel 2016 HC HDCAM UnKnOwN
View Torrent Info: Allied 2016 HDCAM x264 AC3 HQMic-CPG
View Torrent Info: Underworld Blood Wars 2016 HDCAM NAKRO
View Torrent Info: Moana 2016 HD-TS XviD AC3-CPG
Hot torrents
XVID DIVX
View Torrent Info: Criticsized.2016.HDRip.XviD.AC3-EVO
View Torrent Info: Stevie.D.2016.HDRip.XviD.AC3-EVO
View Torrent Info: American.Honey.2016.HDRip.XviD.AC3-EVO
View Torrent Info: City.of.Sin.2017.HDRip.XviD.AC3-EVO
Hot torrents
H264 X264
View Torrent Info: American.Honey.2016.720p.BRRip.x264.AAC-ETRG
View Torrent Info: Independence.Day.1996.Extended.BluRay.720p.DTS.AC3.x264-ETRG
View Torrent Info: When.The.Bough.Breaks.2016.720p.BRRip.x264.AAC-ETRG
View Torrent Info: Incarnate.2016.720p.WEBRip.x264.AAC-ETRG
Hot torrents
Television
View Torrent Info: Chance.S01E10.WEB.H264-DEFLATE[ettv]
View Torrent Info: NCIS.S14E10.HDTV.x264-LOL[ettv]
View Torrent Info: Bull.2016.S01E09.HDTV.x264-LOL[ettv]
View Torrent Info: NCIS.New.Orleans.S03E09.HDTV.x264-LOL[ettv]
View Torrent Info: Jijibisha.(2016)-HEVC-Tiny.Rip-x265.AAC.Esubs-400MB-[DDR]
View Torrent Info: Tai Chi Zero (2012) x264 720p BluRay Eng Subs {Dual Audio} [Hindi DD 2.0   Chinese 5.1] Exclusive By DREDD
View Torrent Info: Maalik (2016) HDRIP 1GBRIP x265 AAC Esub [DDR]
View Torrent Info: Born to Defense (1986) DVDRip x264 Eng Subs [Dual Audio] [Hindi 2.0 - English 2.0] Exclusive By -=!Dr.STAR!=-
- -
30s
Chat
To add new messages please Login or Register for FREE
- - - - - -
- - - -
Warning! Stop Government from Tracking Your Torrenting!
Your IP Address is 87.78.209.232.   Location is Germany
Your Internet Provider and Government can track your internet activity! Hide your IP and LOCATION with a VPN
ExtraTorrent strongly recommends using Trust.Zone VPN to anonymize your torrenting. It's FREE!
- - -
- - - - - - -
- - ExtraTorrent.cc > - - Today Torrents > All Today TV Torrents - -
- -
- - - - - - -
-

- All Today TV Torrents (169 torrents) - - RSS: All Today TV Torrents - -

-
- - - - - -
- See also: - - Newly Most Popular Torrents
- Yesterday Torrents -
-
- -
- - - - - - -
- 1 2 3 4 > >>>
-
- Torrents per page: - -
- - - -
Browse TV Torrents TV torrents RSS Sort
Added Size SortS SortL SortHealth
DownloadMagnet linkEnglish Carson.Daly.2016.12.13.Simone.Biles.HDTV.x264-CROOKS[ettv] in Other, by 27m189.46 MB------
DownloadMagnet linkEnglish Jimmy.Kimmel.2016.12.13.Rami.Malek.HDTV.x264-CROOKS[ettv] in Other, by 41m422.72 MB------
DownloadMagnet linkEnglish The.Weekly.With.Charlie.Pickering.2016.12.14.Yearly.Special.360p.LDTV.ABC.AU.WEBRIP.[MPup] in Other, by 43m231.50 MB25
DownloadMagnet linkEnglish The.Royal.Variety.Performance.2016.12.13.EN.SUB.WEBRIP.[MPup] in UK, by 47m1.29 GB------
DownloadMagnet linkEnglish Dance Moms S07E03 Return of The Rotten Apples 1080p WEB-DL AAC2.0 H.264-LAZY in Other, by 1h1.53 GB281
DownloadMagnet linkEnglish The 11th Hour with Brian Williams 2016 12 13 720p WEBRip x264-LM in Other, by 1h453.63 MB2231
DownloadMagnet linkEnglish The Last Word with Lawrence ODonnell 2016 12 13 720p WEBRip x264-LM in Other, by 1h840.11 MB1331
DownloadMagnet linkEnglish The Rachel Maddow Show 2016 12 13 720p WEBRip x264-LM in Other, by 1h839.20 MB33128
DownloadMagnet linkEnglish All In with Chris Hayes 2016 12 13 720p WEBRip x264-LM in Other, by 1h848.51 MB1771
DownloadMagnet linkEnglish The Voice US S11E27 Grand Finale Results HDTV x264-PWE[state] in The Voice, by 1h644.29 MB37952
DownloadMagnet linkEnglish Muslims.Like.Us.Complete.BBC.Series.1.EN.SUB.MPEG4.x264.WEBRIP.[MPup] | s01e01 | s01e02 | in UK, by 1h1.98 GB------
DownloadMagnet linkEnglish Conan.2016.12.13.Chris.Pratt.HDTV.x264-CROOKS[ettv] in Other, by 2h283.09 MB266235
DownloadMagnet linkEnglish WWII.Hell.Under.The.Sea.S01E01-E02.HDTV.x264-PLUTONiUM - [SRIGGA] in Other, by 2h567.51 MB167182
DownloadMagnet linkEnglish VICE.News.Tonight.2016.12.13.1080p.HBO.WEBRip.H.264-monkee - [SRIGGA] in Other, by 2h225.98 MB135136
DownloadMagnet linkEnglish James.Corden.2016.12.13.Jennifer.Lawrence.HDTV.x264-CROOKS[ettv] in Other, by 3h565.81 MB377231
DownloadMagnet linkEnglish Shooter S01E01-E04 720p WEBRip 1.3GB - MkvCage in Other, by 3h1.37 GB18208
DownloadMagnet linkEnglish Car.SOS.S01E07.Triumph.of.the.Stag.1080P.HDTV.x264-skorpion.mp4 in National Geographic, by 3h1.48 GB------
DownloadMagnet linkEnglish Man with a Plan S01E07 720p HDTV 160MB - MkvCage in Other, by 3h162.06 MB------
DownloadMagnet linkEnglish Opening.Shot.2016.12.14.The.End.of.the.Line.360p.LDTV.WEBRIP.[MPup] in Other, by 3h102.22 MB58
DownloadMagnet linkEnglish Rillington.Place.Complete.Series.1.EN.SUB.MPEG4.x264.WEBRIP.[MPup] | s01e01 | s01e02 | s01e03 | in UK, by 3h2.91 GB1517
DownloadMagnet linkDark Angel Season S01 Widescreen DVD x265 10bit AAC 2.0 in Other, by 4h6.97 GB223
DownloadMagnet linkEnglish Stephen.Colbert.2016.12.13.Mark.Wahlberg.HDTV.x264-SORNY[ettv] in Other, by 4h389.19 MB1092548
DownloadMagnet linkEnglish Seth.Meyers.2016.12.13.Bernie.Sanders.720p.HDTV.x264-BRISK[PRiME] in Other, by 4h1.30 GB164254
DownloadMagnet linkEnglish Years.of.Living.Dangerously.S02E07.HDTV.x264-CROOKS[ettv] in Other, by 5h311.33 MB------
DownloadMagnet linkEnglish Geordie Shore S13E08 WEBRip x264-RBB[state] in Geordie Shore, by 5h265.97 MB1740847
DownloadMagnet linkEnglish How I Met Your Mother S06e01-24 [Mux - 1080p - H264 - Ita Ac3 Eng Ac3 5.1 - Sub Ita Eng] WEB-DLMux by Fratposa - Complete Season in How I Met Your Mother, by 5h20.51 GB------
DownloadMagnet linkEnglish House.of.Bryan.S01E10.HDTV.x264-BRISK[PRiME] in Other, by 6h163.74 MB------
DownloadMagnet linkEnglish House.of.Bryan.S01E12.720p.HDTV.x264-BRISK[PRiME] in Other, by 6h610.41 MB------
DownloadMagnet linkEnglish House.of.Bryan.S01E11.720p.HDTV.x264-BRISK[PRiME] in Other, by 6h623.63 MB------
DownloadMagnet linkEnglish House.of.Bryan.S01E10.720p.HDTV.x264-BRISK[PRiME] in Other, by 6h579.17 MB------
DownloadMagnet linkEnglish House.of.Bryan.S01E12.HDTV.x264-BRISK[PRiME] in Other, by 6h177.68 MB13777
DownloadMagnet linkEnglish House.of.Bryan.S01E11.HDTV.x264-BRISK[PRiME] in Other, by 6h180.21 MB------
DownloadMagnet linkEnglish Fuller House Season 2 - Ep 1-13 720p in Other, by 6h8.90 GB1107
DownloadMagnet linkEnglish Chance.S01E08.720p.WEB.DL.x264.[ExYu-Subs HC] in Other, by 6h648.44 MB------
DownloadMagnet linkEnglish Chance.S01E07.720p.WEB.DL.x264.[ExYu-Subs HC] in Other, by 6h648.20 MB------
DownloadMagnet linkEnglish Chance.S01E06.720p.WEB.DL.x264.[ExYu-Subs HC] in Other, by 6h648.64 MB------
DownloadMagnet linkEnglish Chance.S01E05.720p.WEB.DL.x264.[ExYu-Subs HC] in Other, by 6h648.49 MB------
DownloadMagnet linkEnglish Chance.S01E04.720p.WEB.DL.x264.[ExYu-Subs HC] in Other, by 6h648.38 MB------
DownloadMagnet linkEnglish Chance.S01E03.720p.WEB.DL.x264.[ExYu-Subs HC] in Other, by 6h648.21 MB------
DownloadMagnet linkEnglish Chance.S01E02.720p.WEB.DL.x264.[ExYu-Subs HC] in Other, by 6h648.15 MB------
DownloadMagnet linkEnglish Chance.S01E01.720p.WEB.DL.x264.[ExYu-Subs HC] in Other, by 6h648.97 MB------
DownloadMagnet linkEnglish Shooter.S01E04.1080p.WEBRip.x264.[ExYu-Subs HC] in Other, by 6h649.04 MB4036
DownloadMagnet linkEnglish Shooter.S01E03.1080p.WEBRip.x264.[ExYu-Subs HC] in Other, by 6h649.14 MB------
DownloadMagnet linkEnglish Shooter.S01E02.1080p.WEBRip.x264.[ExYu-Subs HC] in Other, by 6h649.29 MB------
DownloadMagnet linkEnglish Shooter.S01E01.1080p.WEBRip.x264.[ExYu-Subs HC] in Other, by 6h649.34 MB------
DownloadMagnet linkEnglish The.Curse.of.Oak.Island.S04E05.Bullseye.720p.WEB-DL.x264-FUM[ettv] 10.00 in Other, by 6h1.23 GB15793410
DownloadMagnet linkEnglish Dr.Phil.Show.2016.12.13.HDTV.x264.mp4 10.00 in Other, by 7h216.67 MB4113
DownloadMagnet linkEnglish Johnny Carson 1981.12.10 Jack Lemmon; Walter Matthau [Tdot] in Other, by 7h382.14 MB2974
DownloadMagnet linkEnglish TMZ.on.TV.2016.12.13.SDTV.x264.mp4 in Other, by 7h184.44 MB2736
DownloadMagnet linkEnglish Geordie Shore S13E08 1080P WEB-DL AAC2 0 H 264 in Geordie Shore, by 7h1.53 GB241193

- - - - - -
- 1 2 3 4 > >>>
-
- Torrents per page: - -
- - - - - - - - - - - - - - - -
- - -
-
-
- Home - - Browse Torrents - - Upload Torrent - - Stat - - Forum - - FAQ - - Login
- ExtraTorrent.cc is in compliance with copyrights
- BitCoin: 12DiyqsWhENahDzdhdYsRrCw8FPQVcCkcm
- Can't load ExtraTorrent? Try our official mirrors: etmirror.com - etproxy.com - extratorrentonline.com - extratorrentlive.com
- 2006-2016 ExtraTorrent.cc4 -
- - -
- -
- - - - - - diff --git a/tests/providers/torrent/extratorrent/extratorrent_daily.yaml b/tests/providers/torrent/extratorrent/extratorrent_daily.yaml new file mode 100644 index 0000000000..afadaf43dc --- /dev/null +++ b/tests/providers/torrent/extratorrent/extratorrent_daily.yaml @@ -0,0 +1,270 @@ +interactions: +- request: + body: null + headers: + Accept: ['*/*'] + Accept-Encoding: ['gzip,deflate'] + Connection: [keep-alive] + Cookie: [__cfduid=d4024e7898143641717ebe6fe088111571481815566] + User-Agent: [!!python/unicode 'Mozilla/5.0 (X11; Linux i586; rv:31.0) Gecko/20100101 + Firefox/31.0'] + method: GET + uri: http://extratorrent.cc/view/today/TV.html + response: + body: {string: "\n\n\n \n \n \n \n \n \n \n \n List of today added TV torrents + - ExtraTorrent.cc The World's Largest BitTorrent System\n \n \n \n\n\n\n\n \n\n\n \n\n\n \n\n\n \n\n
\n + \
\"ExtraTorrent.cc Advanced SearchLogin   |   Register
\n + \
\n
Browse Torrents
|Search Cloud|Site Stats
|Community
|FAQ 
\n
\n \n \n \n + \ \n \n
\n + \
Latest Articles
+ \
Most + searched
\"Hot
First Cams
\"View
\"View
\"View
\"View
\"Hot
XVID DIVX
\"View
\"View
\"View
\"View
\"Hot
H264 X264
\"View
\"View
\"View
\"View
\"Hot
Television
\"View
\"View
\"View
\"View
\"View
\"View
\"View
\"View
\n \n
30s
Chat
To add new messages please + Login or Register for FREE
\n\n
\n
\n\n\n\n
\n \n\n \n \n\n \n
\n\n\n\n
{\"ct\":\"fm48SsEHhqhXNanAxWwwbjk70SnA0VUB\\/rRHZk3jh1UGj\\/bC2hbu\\/GJnxrlZSbzVuofzAlbxM1U8zJnrV6QYeQjL4pomhP5wycY2A5jvZb\\/M5OsJoyAlYOtWlP7QADbDj7z6ktd9mMU4Dp1nF53gTkoGnNXBjEUrmFAU83zZYf\\/Hz6j6tkHzAom4n7i7CWqM6u18z9l5ifypckPVod2fiL1FizF391iQ7dwjy59tebak+\\/bcVBEjlG3ltyMgmrSHOAsSOTpHrDUvLXu2SrqfiPfR6OQdJd9DYR4v+AbXrO5znEL\\/GWctAU3MmAlN3tXySqTMD\\/QwUBu+V8AmIscAGQLecAz1UUOYXaO7PM9MIx+trYHZnnpPf73GOgfFVSB7mtIu5OGZeBoLtnwZzYTBAIfCQZ521h\\/AkJnoNVKrl7OICNgTshQQd4dkXIodZ1oJ4IVCuu2KfKMIkS01Tp2TqWjY26LLYSnjP+xUJEwaWES+10iSarCooW167pAHabq2jgidlro7HLpNcfRIjbp248P+HOuHXm5hTNMykp1OkIN3SXUGlH2FdIWwjmZGqGBBlJmqZAbQ1NkAzsPznAAwrLPmds5lu6ub+LRjYKIFRcFKRdhUSMOsWGfIFdrt184uxKywD4piBv3WKtmqTNfpNnN38DZFgm07X9ExLkHHu5G1yCJ+5OtUaYlDkzszlJMGmH8+Fd77QGrInWtB2vtenrGUQmP1+OC7FqlULjcGRfFTWZStV15v2nHyYJ4K7xuO7MCURgJ4fL\\/tyivx\\/uUZxivfOfqmB7\\/p+\\/EljRnikyqtTWqyURQC5bZUiNlSkd57Q4IORe4DWLEmUo\\/Bg3Z2GsaLYDKRSpcFcBZTAFW6MCmwNYxPci0zb0PNpksL+dolnDK17HuMSi+elMeg54F6vxroLCx0\\/B7BhssASyoytyYaVLKNajLb+T5hkLLbqsfKV8S1iwBmoB3VoMKTLSexjEZmx9b1WzbbhkEY3OCFU4XDKkbIa7dh\\/AoS2TZ6d08RgPh6vBmlyRkmWSpqoZ1a+U\\/IcSYM2BugBdR+79baw5F+q7+lETeEPB\\/LT+jTfYwUSzL1PnVJN8laf03LJJizA5b1x2ErqfwejrXLrQwQamFQra8O8L2PsAs6rXjJ6ZlY8upRlB7w26C8aNLbfqw7woStoREtbyODIMR\\/lwi3KIDg7IkwkgtWa9gRrBN6on1NxLxKiNKdaokBvao438HFOMvnxf48casqDUZF34BLxJYDHgrG9RebXyDRc4DWJQZC1kTR7eLhOxcp\\/yQPDYYhJGKARtITprOvIO8iaLNZfk8DZQtdjvRw3gfrzifeekP\\/3Orrq0T9hfTqBbbCY+BtLQmPAvAeR2+Wfrr21vJM2De2pUgVY7OWon7SSutXyvi9arfeiUKwJqS\\/R6E7Y4FMjuJhAtB+MyWUhL5csAIFWY94o0rAkZ+sfZQSk9nc67QJBKIAkZvt6FUKnuhk6J2l6s5NiUZKFFt2\\/A839g\\/st0BQk0yLzs4dSCbTVT1zA52wUGrgDG1CuGfKRCsN\\/LAoC\\/Wr5sOljemZQ36JWkLlQ6JKUlrPw3egqP6D2x000iiNYcu70x5IyDwG+Qo6KA0U0bnGLDN3lvaE+gQZ3ArjfZvZt3oxcV01CDVINmUh6c2TS3tXdgQ1pl3Ap0hNtMIOvCKGSUCCFyqOCzvT8K53JsDI0pkGf\\/zQzLPFW9P5bXlFZYSfU1Pe0EDRCq0980+iGr8F414SCzRw6pI1Sub3FdCsSldEHOjqfkpOe3jWDtTuhpaUYyUoaEp5A4QyAR8MjO0X41zEEtqbBS99\\/xcso2VFggi2QNR\\/8YpaokzQ25jkhJzwmsAgpz4pTOYr5aXf+Kuq4F5bg9nmY1ierRpz1Vku+1GeybirYogkWpGoHRbu08uBPeoLT8sYV29w\\/TsFcj4NO30Sin5ypp4+DM3zgHBrexbNbbqkd92eQqDOEwATyUfp3hFjLqo8n6aumMrusEZ7Db3myg7ioTzp8ACRLpi6uIuwQMMjZ25LVGOXUjpmtJGsQQ79dMKPDm11NTR1ufGTR08K+yBZ2XfbhHiQq3MJ6a6LxhQv81OMH\\/FDX3e7za7pDeQz8QB\\/QWtTsdZrgkqfCuzRGJyfbwu5JfU9Y0sIvd+JVI4DOh0VOp8j7wu4seW69o0\\/G4TFKutASW\\/nJC2IxXSYmBKhMHebuVC\\/wkSfgm7xsMLUkqq1jNm3bQWOtwDjFKa7JsaU3tzD7Cu\\/vzPgW\\/cQuOrYG5bEsrBDtpYbuAir5ZAOo3lmNeR5auupfMdEehOYK3D2Kz39GMcrnYJl2u9NS6veaoSVRellQUf1BVTeFbdyLW5Y++432nhU4yP78y7pxa0aoZwvWzUwyKlgUt+uPWlCPyblDWaoP0x5hoYJPOpg+x8N3BFcxRGpescM+70Yy1vUQcDtFUppE\\/m3+4AMzHxaGiPYR05qgvvUhEcIEe09Arukazhdx5j3BA0ETsL8LGHkBJZqleZGDE+diDKLINKQNKypFSfTPaxmgX\\/rNi8CsRbsqRQr99vhQkS4KSZDp2ml3nZm73tdWbWDCH5R8GF7ly3Sv+AmUOaqdMuovxthsKGJgmC30yP1AWjQ1+A1UpkEWsGmxoHOZUX0ESCSNNjfbyVE+os+6ibgZLOhPb5kwWazyDa+NyA1GGQnApRKV1vUwTq4k6HKlP+tW1wc8OLwOKhvlO3O7tG1uTMerPCMoVY+TMfsHen404wwoH9mk8nMuY6JsS5RQhH3FNTe1jcfkMCxmDcgo4i88bR2dE14gLwnnU7SZxXr3rpyOuPwp4vhesGecs8U3AoQb8htNoZdoi1Q+HMzXacm1+0vau5AICkvrcz\\/wEK37abXkGkPnEoBKpjpqvmxmTWOts1nsxqRxm0TUnlJuqOTzp1ZYRSbf9hOXHdxwTY8MjU6RYmsTp+GjFs4FxLCtrZ0vy7J+X2exCbutUUnt\\/CgQ5w9PbS8phUboLMBxWBvMLSdO8c8EZzoQj\\/oEDGHnG4bx7VYwEdRXFTaXxryBXZTykhA9q8aaG\\/dn+z5rjdkziwG0f887\\/qlBoRIc97xHGIyKjs2ndqkJ8CmQyZbFAkJgpMxsikKEaTV8cOHfnjtpGFvVqBjjjPeA2oAXL\\/kGUcPUfKT3A+vcdPClhIsWmjVLsiwwcPcGZiut2vpqgnokJkXonkkjlMtZgmQVxXJ0Mfr1dO0sKk9EsrqTiSwzzB7kyFir9\\/EFJBL0jRaTchZCbnm33rx5dfnLajNWFYnu+Mn1AAnXh49DpSVXY\\/NKifo1JTvgWpRKvkkEUsnWutDGhDvDUoGC90vDGoCvi8qBVTtyQ0T777EKEUPbV5r2zL\\/vvmskXAgcD\\/nCvDuiCV0vx2CBMrFGg67WHRKj4UGGwO4i42qBvfk+wfSi1JGkwAujvfyJcyyZxQnMDYjVibuhgx4gF4d880DTjiaIHJYw\\/zCRvzLYuHPYo8DlQTFuSK\\/KRWenTqJ3xPiX5kVbAtRsKMKbCtRdo+MX0qFutEvAaen6IR5rgmJr0kVoHaA2DWvlvR6VzZxibjVbyP\\/5EmaWU48C+hnyNzQe3Ve6OO0zg5QCy9FoaZgBEzlYAkY3\\/iuirp2p85TD4\\/W\\/AL66j0C9agujGXaxm7NRhiqiD5g8PSYItBhZLlgvS8TH87OyxGRc3FAEjvVsbS8+cxe+D+llNipc\\/WGWCCVbw+XQp82RDSLQvQxxiMsMg8iUkY998ji7aOrRCQ42bNv45XRoyGgO7bP0xvi\\/h8eTw8SPHQl4cdYTcXiIop1ZnA3RyUKcu3xHfmm0PGoO95gwJAOkQA1JY0BBwDW1hddcetGluALyVWb20jnXjK0RT6T8j2YmbZ4LJfTn4GEyexXhflniIX\\/nqZqBl4yPiEQJ9TTqbJcMkUGvVq7PFM9u55I+zTv5kcBfh6Iv+L4BewXTiJiM8nDM39hDwf\\/znOA6dtX+TKQ9STcV4ExsquNddSnwCZZNavFWZoAJZRy2lPSrVSLm6cZrCrJ7oEGlRTk2mmk6fSME+yhmAdWqPi522A8bPFD7s6ef7ZePh4azDfOIRf+90t1FkFgZhOwLmTFiBY5p0WMcMKFxr7J1VpXpWVa3Lmy8yJc+esbf9kkaIZ9YdRcfAj76AoQpmudPD6MBXeSKJqVKbqgo\\/DIpP3QzFuSJQyT8n9fYSe\\/RP5GtXtgLEv7j4NNp\\/GGk6VQgdxvh7xrqZs0ERUaFXTpjvKUtqDVtgHmZULAbwXfogtAMMrVEHd7w3kkXBBOoLCVkY3jF4WifN7D4NFL7dAd5EebJ+iLXnNxOPtXUERRwNn8yuPSXYajF+v2EzTzxVkaMxJCK3VquvZLPshtFKO1YMlz6vwQFJZPEQr7RNroAfJRxbrMqGq2+1mhm4qJchXRPH8WCc\\/Bh8e477KqS0ikamUzdWATJUe1hBR\\/VgGmE617TGcg8Dd2DlRiEKlCN6HQftOCyF0yFNl79t5X53J3AOUYyAcOLJj5TlCAIMVt93NF27PPk5oPyOsNfwG8I6mLB3pXNbIV3yMlZhunfmySFvsEIAfjNCbPvNay8+kB\\/6vfyT38btbzeUiL5zFsyYzaZG1kCkXyUJgT2qhjV+WxsmKWdf793PV48l0Kz7NpgbojkgARJEtQT93lrpITRuFsOH3ACVfdd56v5QyI6MpNhXD\\/Mm7i7pVA2NfufskKfqqxD6YZnlLs6cYo9RnGDaMjInc2l6\\/CnQgztWz\\/19+JfidXqB1YGEPliiigdTfFpsYKR9rvKi6KEeRU23ZjXw5\\/h51qq6JKtQRsq6jMpVHQNm1AFy05HiHYnSmBOJLstmQ3Yx9YGhRDlDN0gItoKVSj+x0QS5EuamGYR2jDyRaE2CzIL+4WBz+9huLQuoMETcEIGacNfu6EWTqzfzziMUrLkFZbdkhr4s40Um3KVBiYPDJQzN8llL+hT2F208E+Ke\\/9h6AIB7L4BK4KWq0tO9iIiKkQWN3dCDhQVKcUGjbCWpTlg922sgup3uo6hI+lPQKY5tPVlvzhR0GZRZXWFHHre4omUEvy7WoHxlWxoU5z5ppSayZMFnOj+UmeGlHh3XWb02+aRzNOPve5Ghy7bdcaYx430Z3FXW3aGxPvKdFjHn5YK\\/zQg2w55U3zfxPwSrl+aeUAznc5cGfrx4L\\/aiQtku20SdwXT6yTob05yTNGgMsao4BLB\\/S0P4IdKojXj4Vjzqhz5JGt519P1y5gAJzf5GgGcHdI99JeDT\\/aQH002xo80GUTcDqqaGVU6zKexAeWUvmrNcbr+KNBoT3+3xmi+cLu6q31vnQQRz52vnKGbqFd014uoxufPn9iKH2tGI9Dn\\/aCqsBGbBoQeDJ9uwIi2IOHNzkEFriDhCcusRpNJcfM3GFpykub3b2xG9uZiRJD7XUGvoeOzKWgohU59K8FSKmUhkJHF2nZi1C2I0Ukv1ZQsmbyDYfQpMyfEmYXU+Ke2FPHTphXrMVXmdBmPPwC05tXljbC+vQ7Yu0opbmU9Y0fju6x\\/qqulY2chnyEvH4ChjOHQHsXzd9vdSp7Sp15jebK9zrBbWvL1aCVa8AlFrKf0bxoYratviAuxxW4E8jz\\/E0vXMdyVUY39Ym8LkHwD1sI7\\/3ImW8tg4qjEjL+Q13JB8L5DSeEbUK36W4Oq5pPTU0UQvmxYvPivh4pga6Ync\\/S9gFYIm5h0NmPP7HlErwEUbu2iF\\/JTmJf4+r1VES4xOUH7DVZoVbqR9IGtlokeKtCirWRVKA8bsfyIDI1eFO6uv9IwNMN8VXLhCUhTyf5LZKr8Uqs0WhD6kiohb4TArnOqDU9RApcVcKlycU\\/pCSvNg6MmmYvd\\/RT71EzoYYACtg0XQNuTGdPa2fyjvrDXHlbBWzEcK2mN4\\/lvv4E7Ed9Ymr+hkU6UDu1ZmBt0sTi7KlVwToILKu8JSdf4g\\/NdGgvMdkT0Q+0ZFfLo1COBraNSZ\\/POj3\\/P7Qa12l9\\/KUNrNAb9NRDHQIcruxm5friiDpNB0WQwf3EowLvhqrkIGOGWEOVxazuQ7MGGTyTqeLKRQTBVFjgu2QncYztGrkrYE6+Tfcuztb6vlN34BEiqtpkGDyMtrUtJ1WRsRmok5SUpvaQnFRdK4mX12eOdlzV4zicxbbdDr69Sl9uDBKUpLBSVCsP5EOyd2GWraIdwPCvlsvP6A\\/mW\\/lhjFGIbmEkgpWcJUcvAfkkV5RkM5dSNQG9DelA6jRIPjUOuTzu42b+4o99ak6FOPONkU9o\\/+4rt+uGyJWNW6+TQWqdxhLsf7MtRHUE\\/jqEx2m2XPPq1uscHJeVdcwu9F7Liv\\/DT7\\/\\/NEVN1G4twhhD2FcHuCs1+vBPc369TIJOFMUaiAXlz6UPVLwM3d1yPH4bnYPZa76oEKHJprXfVWZ\\/mRWR+nYx7qPNxi7nYedWHGOPzFmpcFTwuI3N9imt3hRUvSZsF9RperchR6LOcbUTswW\\/+6OeIDUNFAtUV457kFNIo4TY1OCphzjFrDJJ0vLBVG7jw5GeTajP0n6VmA88kCUPPLHTl23C31L6fj6YPY528VZY2vq4htxNzC+2ZxoyCkERHg4V04quFhxsvCi\\/7oHCYZIP51PKx5w7Dftlx9W5eZ1R5Ja7dwaJ\\/KRsTd9njGvQ5AVubyA1pvPrdLQbl8vqdYF1LfNP\\/Dk9zHbjnSVDyjoRPJNssaT\\/pFiCOEVnEPB1tzCRVGswEHghQ45PSg+Yzs82aRYdYT\\/abaAhSiTYEIhdw2vj8SkhBaNKKLrnrp3fg4H3MBGZfCitLaC+X1R+ABj9gZ7XnBkC3zPNUVfbgejV1KBweTYG2XlHu2Mrf0s78jCkPkmKm83GFJvHKLZvzcIOn1zuldKNx\\/oa8PPeZmz+pdpAv6B0bqSrkizkNXGqfdPUW6E\\/MpG+mxIqFQwguIvQ9Yitb3472oj206WZ5EiSYyicYZusTGnH1d4hQhUtu7uatsg75HSzCfYz5nn5tm7X9AK01WyBil5KaG7gumGRCFoVtP3jvztAuZXW1OciH+5TSmbjUNdHXp\\/IZhb+FIvdHcoHVPusowCFmOql\\/7zU4tUHPtBMQJDrSzokhOMcINDVxQTEhw93cXTRPJsVj4Ck8kRiQvMcxEHtAgo16tZ0kZad2nQizbjHCb97zgN5pD8pDm+KC8TgAyYZvr0EwbgwPCw2oCDAp5sLJjzdTJEPGqkmQIApEmlSXKavs73VyjYrMdaUboiFrcBwGP3o2KSqrk9+dH1g6x0G7KhBEDDePaJorEngKH\\/62LgerYanZFPN990tRjwwvt5dCywIiT\\/fGLKxgH+eQ\\/rCbLhbAsw5KfVUWsRgEQHUa3RMXCLDqQ5p8ZWKAegKCnH9JfGnR+AVdVWk+pcHnSZRXntLie\\/6RCZV\\/I8j3QS0ciV7TKqaFLKU2CfLr2Pz7M6NZMz6gkpth+l\\/ZeHINw\\/G2c8BXG\\/95eRIJlvWbAvvedceqzZABh9RGVUBPGcdP9pmn+gdCotKr0Gqig6xFadze1ft3owbd9quHxGDcmbZTR5wbMP5mhq2enLxEhRrHeehlAQnQiLZutEr2a+mkEDLHCvJ5Lz\\/zqbnbyK2ETNnDKT9pZ7LGFpw5PiyIbhJWi0G4gSUUbQe++qM5wVYIIGFWyf7cp4pwoCP7Cis+KpnjQ+y4V2EMjfG\\/PlnUVKFiKl3csSqrGQzJfqXJB42IDEDzivplarPTvzYWr4jumWq5ow4rtImowieXtEhVlvrBCZZL8KsyNngoeZ\\/klO6Y62oL9IjYyHd81AkPEE4CU7UF9Uv7EqaF2m9UMJfaGjj5L1+W+USko0L3Ouex1lIN+TIE9p4JoioB8Q3vEJlMCjKWIDgX1jZZU+EjQbqYHC3BaUfPrtKDB8kx2mckrmg\\/abL99D\\/kHBD45fQnO4C6u8smHceyrExAIcZi0E98swiIJcfXUUCCvRqTvjpE5utRLEKjtBLbd52KjThPTjd2N8JFavALi0vxaigdte9HO1krxsi5p2gfEVfhwCT62thW64K4A4YbODqUgawJLkpeDNCfz2X3o0WeIYbawAPnshJ+6+eQXvuidkgF1j40uudU3mG8Ill1hxL13SyWcDCRI3bP9rrsdew99PeiobeKfi7onbsatOdejZGiarfszXC5EM1HG3GFjLCr73tKSxug0g\\/Qej5q9liFWA+U0Bi3Kf0UrMS0m7TFYRtMRWn1GLpDjf+DybH0Dz9iLoaKz+u2JLfB7oxMQlOKPiCmdSa962kQSjQMOma4GRVv0GnCDxsAuf83VVG+sqg1ABNvMpk6eY9MNKDK7B2BTAOwDualldpRzmSK93Jo3fSfxmaYKYA6o6Mzi0iavK4fJhH1in0uQBNzbQ+JhygS8hoiw5bpgPIrBFZs3pSN2imPRpjCXZEXVtk+Q19uJULbskvjynUxFl2aSqUn23uPHI5469hMxrePVKFfNN\\/mf7ojWKsfPhcB0sBUYxJVSwJojtM06yTqYdVabjQ9Upiwmxfuf8itj8RkGj9xnGfnjp\\/MZLqt1fcjcanTmEuUEbgy5Oo36HMo4lremVZigRI6y1ECz+IWuJel2TrF\\/UQiRiNAgktgfyT+HI4iaHxhm3pffAtFm5r6PPXVTi2pBuBkQe29r52Oxl6QdTrSAE7OdqKEdtQDTGO42zIywaWw45IOmzLh2d\\/AWIVqLThcKA0v1mNlKLdVhWS9L60lcEIjBAy\\/KKINp489h78CmvsCkhITKf7UsaOOgtMhPGkk6sqV8BTwfMR8n5kVRfTz+df\\/gftGmww2LW87lCmQuBfRQ2fx\\/jyZeir63mVSBvfNAJBp3UeT\\/1+je9aGo+cndsx5G9AVBLBtCi6LUHAO5lj6JAAiavMCt1\\/sCXIJz0WMGzBfYQ0eHUU6zjHwiNCQ4xz7ZnwFaIGj1g1H7ejmgGFFXbFc4U4qj2aBeNMMbHuRAkMoj696tLkkKkhQaC6DZIVxQCrnlpFnUFmtRsJvKOEOeEnc3dLEVcA8lpRXkA6U\\/3aPXFdBC7M1KV86gbpr5OWdCmNfscM3T7b1ttvS0aGlSkxYaRLvtn7aIS4x927Ew\\/qp+k8nBsIU3Zkv3pD39RDnPGtlhLx3ActojgoQPgnNF7LvRGx3W9WwAM0VkmLjAnksBQwgQ8PgI2rSexeog5BXbbLXckVSN6pFF6iiPi10X28NJrbkmwX6SfVdAiQY823jFoVdCC8QyEz\\/EPe0NXHjRyGQELlouTHax5XXiKez+5PrRuCE\\/hpr2jkmWQe\\/zTkekT+FSlTCmvBQ1CQWHydU2JtAymT\\/5FeBc9BVYDSCIKJzwfns\\/o4jTlNtgNPgXAFxmxL2ADJgL62J7gUXu969G6o\\/OxGq5g\\/huilXFOi5RnKZgPuAz7f4F1zReAqPY7FWqH+rJpX036+QZ3dKk1hME0u+\\/GWjhedmwoCzB88zKboKYu8Y2Jk09nr22a33a6MNfiW4h\\/HlegK4Kz0urH+VCS9SFehCR9URG+POxqRplK0pAu4kXVOzl9hJwEZRqMFIaPaTU\\/syjaOYKYPQH\\/J9Jtdp28ryl\\/eGg4dTBR+XOppOS0aYl4pYicMrzLZi7MfYyQfecZfn33vnINeKiBpU4MREWr1zly7CjVQfm3VzLimsYmAI4t2ehl9abvNSeLf8\\/l1+k9kMNmDppVfdCDJ5X+3vchgKYBlhD64O+uABNkdduUYJynawTXs5Y5OZhb252Fq5O\\/FmqDNBq\\/+C3TtwWrjoLg7dElRJ4fMEqPo0LXC+5A2d4F9bnWoOaUrSb6o7TrWkYJoNAc0X1LI1i2+gTBy8bFEwuR3rLZhYh8dZjiqyNowe1Os6TvzV+sI3+VtHonB6ELFEbErDsi55i\\/FSm4Ih8wcpeIdy+rbOEHBcRoC+6zl625LG4x5YRtinqsU5ZpzjGBmLzRGdDbgXmcXe\\/xdTWjd1iNIrhkbnH9vd8prla5ovRwQg4VLgTW+ycf8GtTI1P7WybB4TyWFQ1Wej8peV+3JxYrT7ZY8f+gwe0rmde0U12WM2Voj5WmuXbAY9tTgNi11KhJgJdqGqN5m9BITHr+koFxrzPRSLwICYWoT+a9ZjZ9Hp+xnRXlertCkyN79UsPBFWbvFN1mtTwTmMYtZzgmrB2OtD8tyA2Z+uOChCeeqvE2kw9GxXOArvTS6sYjvQyS2ULyOix5Pwrecn5vURzhNtDKRb5JKHTmRJn+d22G2+QaaavexNij7I7J7wfOIl3qQIRjfOU6rNsxWjeaeSHQjpWHBZbeChjc0t6XiqIz60J1JVEa4nXXKQ7bztYBLwocTbybdWhZDz9eENdK1TWgxhiCqgOcN+DviTs0TqGu7mLhRFgcXzPB+F19ctPGinLGwYPqp1dQKI1lfe7YJO9WW86CnkFFdrKBYc1sEDJzcQ7uL7GhZmd+qeUJjVUrji4MIIiaF623PWWzwUWepAwFYYW5KpGf9+GBQmR\\/8BQtnpMlYthccIfK2jqLNyXzq7sVD1uQFRIfh9+nObuN\\/1XlEO9DJZceR7GdRFc5c+MJklgdf2Svc5INZt2CwMivNpsD8w1ihwRY8vYMQoaQ+9t6tlXvUIozz\\/ox0PHlTAu8t\\/tL68FaMzU+MVc8lQ9W5mVEQOEmxFEeKol1QwY7D2xze\\/8Ge0k8sCcWJGZGw0pqQiH5p4xu3mlelkX0DLGh6tLGyZHJqARCUqfkulSZV3KFbAsjtFGdB0unhgexOm3bkHpxF94EFKEnqk\\/mX16IXTOEVS1PqOtm1sjY8iWQ7I20sIlm35Z58wwyWEYIVyVQPbee6tQZrR7A31s3rbOZu4GQk0sxC1\\/NxSuqZECi2v3UssyNcVyxLQorVOPdFVihVEF9TYqqWbwd67beiCHJfHtB6IrF8oYlFsFfJhsHFMZIzO1+nOU04HImLMhwp1asM9zMXf6+8kqgQZFmehj9rXsZOYHk9X+02QWNRSMNuvXQJgupk9IDrUpIGXl2e13nglx8A9ve5nzNNnoPEcQK5HV+4sGIPAjSItNuTLAmlSfe7duLKdrVL4p1xJVrx4lgh6PX+ZMIPjwvWhrKi9isSWYLos3Kg94tY+9mlD9xeG2bmPXHDKCO7wvPkuQ16D1jPWnzJ69AMv1LilD9z7B8HJykMOUHlUS5EtKF\\/yES6XwcEaGwRS84AcmFitBXtaVsSDA85zxuhcE1qkYWJxm\\/BqZgnlfE8lXnEXgxsMr15bpSwReyOhtOyYbsN4Zjdb1g5yULh2MW5XSKBzTtKQ8R17+0htGrdxeRWZHPw0GFryUihdXHpkECCryyLEtKOiArpo8ENtCi9Wauf5wz1osnFqmya3WPIuPqj8UU5llm1XnEGtObKrKRPbM4W0QuyCstyATkr56wAFjNAyPKL2cbvcYtn9AAhIdn1McA0MHH6Z9j1tvzqiT+e5Fz1tAiEBv\\/sjCFOth7fpiDZpNXSZ0wHnmhRwCOb+9m2nTa1ufEz4FPCjzjRf4PuffICTuQyKctot2EC9ms+OtTdiGyFzcU69vza0Wx8Q3FdG9qpSAQdM1dS4M4tTJYdgeLCq+lS+RKiHXJ8e3qV7dm0xxr0LMfzgLFuMTPuQ+Q44WTDIV5ysZ1JKlYJw3+F1ofMkygltZfE+9LLEzOlkuV7p2kLteGDogVSjJwp7nNXsO9uNojYF5F8MJAAy3S0GMUm7OPyPvydTzPnkMAPj1De1UaBGXXzRO3fHkxgrpaDDUEQK66MO7udXuSvXjXEP3+miHzw7H2KIMOoTtqmXkRBu8wqqErlUuvhXvaEe2qGjgWwy4EF0ZMd6NE3QUIw24v2fDwCdB2Ytyy\\/GhacYc9zsEMB7qjoh9qoqDIL2ENPRB0cg4VLMGjmGhuUn4N\\/UmvjC8tkgxRwRxU1TgxMz8TXmZAj5Fg0nL4yUMwLYQvV2E3YyMWSCRcf+O5I1ZMuttV+lL1e0KGKkmjNgeN+e2OkF9fby4twQoq9tbZts\\/icBphPDG7TzhafmI9UmWXHatPfWaiWEi0NfyDrFjLXswPJhIBUzfVD+71lhNJDkzOW9GAp6DK+3gh1WH\\/47aQMPmKkjtp8+z5BBUh+B4osbHRrS1w7t1ZBk9IIIl9jNUIXelXbP7qfHudsMG1G\\/zxfXwJDn3khqS5Tt\\/a2vaQzv+OTeQgI1LrVsT2ubVj+Ckq0AHUrV30\\/XWei2Sh0bEdhg+YSgFWSnWau2w\\/vZKefTEZIOtUKvOpOqaubu7hZMndNrhqIyK1DSqYNiOpDD2fEtlMe3pCan4pYnhxpBSv1NLq4Fu2lUw8f1a7zl73cMWv8+CSl1P7WVqKJ0fwvtGue7+qP7DPqy+pePQ0zBaVtwNQ9gXU1kk55Sa+sq93ImU\\/AwRNq2m0UzyIEdsRFOWlICrYk7KTpplSZpywr9KL5VQPcEkp1ECjV3P6TftecAyYOCBbJtQnR76VMBIXy8uuuwejAXh3640DZscl0rvJ9NLKsKNIf1MloUZjaFu2qDiXmt1TyB9Klxqi56lau9CS+FA6oik5A5s23N+v8oP\\/wM9n72yCDTVV3TtJ+LHoChX8fUIykhSnmLHJQAi7UoG2Gz4O8RUgKf4YN6wKo0VFDM7oXgTlzCAUWSvzYsOyVBaepOT+LwRLiKVT\\/iajhTrn0YxIM3EgaTxG9d6q80auhR\\/bvkq5Rss2ykSQ65LgJtIEmUF1Hr1ToWY4o2FLwIlaUp+pUXY\\/jSDwe78w+EnV6NPw7eL1xVpzUjmR8vpQ\\/VoFejNVsIYqx5bNEA+NtiDhT78Kq8y\\/TJV4djP18\\/9OVsOmtcIjN2DrqNDjqC4OPB6fniH9sKJs35hKdltm8XuXCUJbQ9F3hLj0OP87W\\/KvhYk2XlikUJsciDN\\/25vXNkywug4u7YSNb\\/IH4kKw9ojq5Q4gblm0udusu2rjn3+3pTg1w3442phaIszNB2h8nohPIz54e4wEN9dvq5gZypSI2UUmUjYREy1EqKw0n5TlxwkiMlWr0yhjwzulIxuMJ+j9buetFmD21IXJcBoPP+RRNLoIpxfWYcSNZKnT\\/iR5YMdDUM6rMHmnIpS4KBiErjIaLTlJIZR+L5eBD\\/EX2mZgB+4v19MZ4qr2asCOr4zdnyaurhZwVIb8AHePMq6iMzMSG3WUZYADseO9MvDJRxgRJQFpkSvUgFhGK8l6l3r7S3enL9Rpy\\/ooSBMJWkRtIF4Zf\\/Lq9a2MWNfihfDbyMwq2PrhH5QNvqyGK1eMXcHKZIiICdp2vtlWEEDC\\/6mn3c0a69aekof8PyNtI\\/zhH91TDscQZzNb9Fe3QKXkzN1PY6CIlv5PxdjodtqqPYJRGtecD1XQkB7acCUvXw8WagnoMJXDz9h3GsDHKAgeIibSgpwwc0xUGtUwfGRvmVmrqwWt\\/Df57GIqQQzef9xrWMx+QHnMbM6Wrk0Boa1POXp6T8UgrXlB9KWKvOk0EGMv4B3ohz7GZzYqyUGqWL0teAMahYD0Y5KeTsJsf0Rq6jKANjzA3ZoKgx5aYQmvzOkbCLNqLwT30uF1p9dyPjl+qc2Ndl8E9KWzBMIyZI3HJLE1m29NnosTKEsgjzNn9AXVQliSqb2ojiVS1vrglmfpyKrPdwaMrR83pP6Tlz7YF1kYF\\/lraEMqJmQn5yP34FSIb9x+X7R4KHNyjSFYBMp\\/troVpYc8ZWREBJApuqNck0zVyGCJpEqKW26mdPJexwoc1ECPU7CLqk9ctoisaWavXXboeBZjwvtsV5YRKA\\/aZ5XVz+GA5Edc27ryhgfNqIju50xuEUFo1OgYQKnFOx8+M\\/MB2e2k+cDrkIjUWG7NHzSXG5oN+H9oau00C84HC8WMmSdybb9sg813CbgNoQVG\\/97quIlyB93lD+JlE5+UQeoovLmDZfVrlcaK+l3G9zvMnKxWhJJC0YN5xaaUF1k03M4POlWOHP6IhVE6NmFaheIUKhqKki0+bUO12L6hA455x\\/bjJsTiLDcKETfmwvaE3ReweyKJ\\/xr0cCEXI\\/WMAtEAveycrsDqzG6zLj1LUEOY9Q+facf0ZVxJtSE1t2alsqNIR12YEAaO5QrcMGeHuqFjaCun\\/KxH3Axyze93ihc4EPLvPbX14HovbgjBx2olVdtg86IbHMhcexX8bM7mjb2NMTIJUCeeTGZQqvnlcPRp5WBQK7JIptxRzlq\\/0vB\\/1WxAxXhFN+WqH0U+x23MIFwol8GO9\\/+xViY4GHjfzr5tMEBGRFI2G7NqPk6C2aDeSmlOsl11A2xmJGMY3088DUF1pDMUJpAai+U7vt0vX59jl4ODdlkJi73dqwnKE\\/ycRxgx65LZ\\/9Wc+MJ8syMRraUFqkLH8pIr0ZD7unXzBU0ZH0LS+5xOqVuxlvNlRGj+yKha\\/1XeFmz5\\/QbnVg23o6u9uCcQ1HJUiHlMVTgfE0GMu8AaQz5FMnavNRYkRlNWS7c4j+kgzh6\\/bOPE4aQbAAS95NnP4otMg+u4r+HcZg54yEW1\\/7JFOOltntMSAsY7Mgx3VkC07uk149Sb7YXjeX6cuoSiYrlQC2\\/0Rbj9beb3Gm9V3\\/0omzcR7J5OIYg3BD8adezP6kgp5nYh3aI9+ahqxs6I84DXs2KUZVD0XQfbsCwMDiZdIa0Rdw4bA9xLA+2wU527fwjdS4MstANloklX75vwYSElXr93MdFQp0TL3NoeD+VWBtxqyrLAe1XYRPzOq4hgXmuaau1EUOYjMSCrRcFXaOqudj7rc\\/8p+5PQebzEwfpsjF8npM8mZWl4csULnGe\\/cIDSQMfFKwHWn71NKjCUqVnIws+pu8ZKytKRWZA489312vL5s9xiWGAbJeRWgCzfTywwroglyd\\/0PrLMmNBXYpH3CNbvuWjlrfKFnMN45TdOhp3cIzpmkNos0p5hIMjejwuib5eq\\/FhrNySNyvLQgqkbc8bThxCW7+wPgq9HAPm5L1o+paDRyTB45c92lOEp9foiZU+rbgPlCHEjxaKSBIN\\/miJpo9IiUHIOrYPXZhNYSt8rnXbtdOFDb8yr0AoWw2Vnet2xqvUgwZz6gLqm4D16jZwQ1nNx\\/sZCKrTeoy1s8RsMuxeXT5IPHlftvDJP4vXa5XG+QqMiQoOyK\\/Ar262bjZNsDDwryOUERkJi40HgOSCqJ5hCAzY3LvLCKfMsILOKupWIOZObOl5P+hgkJdKyvWUxkWx3sbYq98r+369AOt\\/a0Mtumta8Og+XjIe0WztS3Ikts1saYyfuCrZwjqCgbuB\\/F2egbNle\\/s4ObygorWqDyLk6WEcF8bDbbK+eRz1g1gXTjbYarcq97kyuRDBQt\\/oqU57K+b+jwxpdYrY+60qFOQIFPtJWbEImtULzvaQ656OrDqMRiyFYvXGjG8aJw9w9SLWTORImFxtBuXdQ33175kHXR+KeMRMKML2zf84QEhC1eIUKoq6\\/x5T0xHEB0S\\/4K8YXEUL9BwZOTtY8NyXLdXk2V\\/zsTe+WmfZmq2r4DhPG+\\/YYs+Coerdb+wlCICJrNzEV2bJdVONDMjOHohJxPd1tgZa9rimQr7nIteWT6Eg2dWRKrxvbEl+wReV7RxBdSl\\/ZSU\\/aTZDTsG0Ed+UgMuet391I1OXOnMp6cxcOxb3wgLAwsTA\\/T4bEjx\\/M\\/Fcbeqq\\/82KtriQ70WH82UboYilMVUGPpsVEnxnnPI6o1jOP1lXBB5COAt70zjwvj7UHw33lIpPjinXnYZB742SXTuOW16s56LMlUQHmcXwVfwR3+jPDtP2nxY\\/3JZO4uckFmiZtKQWt0oFoa3NXWXEoT6wAsfXBMBrIuxw1T1Dd6HAaPUR5ZiZhZWlp3kHFVhpaA2mum4avCcDcydsLXI0quw9c458l7YOsBtIINwX7hoNIAyu\\/DxRDQEQwiKXvanM0aAa6YG7N4nZNb1cmhiy3hLRnb5SVZRQJxe61ewO\\/\\/rQkGIWwXmIL21mI7ds8WvJwuOzzzuJe8GijMSRJSli9H+ZydS7Ve7RYrPZUHCFMZQs9MdVIqUzla8eYnbK4TiOBNJK4cPHOJgGt6cKfb3l96VjoWoaXqYG6U49dNUbkEDUBvK40B2KToiZJjdcK3\\/OffSPq6I16iZ8Oc8df0OQSfwByxFygIzcXmEsct2pdkW4\\/znD5LwAge8C49td8Z3wzYlMxrvYYQpPlcpaVhElJ5u\\/PPX5ks1Z6vhQX3c56Hc+uRQ7sR0PMIVIZnP5C4srqEyCytmSRyAywZNvy+ZWRbg8JTAuazG7C9CmuiLqykR8VPayyorOm\\/ei9CiZHq\\/rDgHhDszh52uQmapEya1kdT8VAl2hMmIO27+Afc2lNYaIK5tZSbN0uhQ7zKepsd0sM7IuALnLz+ze1ww3eo6J+UmMkpsdZCAX6vdWDHCRDLLDjzxGQ46N55sB1PgI6d1huFHdWrvN6fL4q0nVp7+KtTTF\\/+z+tvJsXqVfw206fxyYNzn\\/zRcLe1qdPqS9FLZqXRooqXvlhAxe1Ux7DXVEHKJiPkLpg3DpdVc0Vvo3x559RTuXLbLBQkill5Gw5qdc\\/GwrycHhMfLsSjK2VbQzrLS57dJmxSQO5rWRsAUpYtc9UQ0vqANcGqfSiF5ndjymhwCOAeoi6MMP1kibNbkYGa3OGrgxjQdWRIkWPMRpPJpDqPU4ncES+cMKvHOpmufDPK9GyjBUPbSn0dg9Z+WMZMuTqxy8ctEdv5hJ\\/em1XhyuZApMuKTkINUIdsfnBp\\/4j6Ita8WPdy04\\/3FmT898F2GVZmTyKm2TSdb0fE\\/lMj1P\\/1lgEcestqtg9oJLBKD2wiHzGi\\/AZl1U+gC9wazEO8WSyC79RH1mbVxbRA6XDa39t\\/4QKeFA6k0m+6Q6ixex\\/Q4hzxaZoEQP+VyF+cRbyPjfpCkMi9Ht1o\\/lt88Z5y9IMOWKVUBM\\/P8OP11wfhnNV4VvB\\/XLrWuInGVm0acbN+htcR\\/cJ+zaAKkpRdadV+5DJ8oNWFWbeM64j+1J71B7RatTKGNsl5fybOaFc16kRLUK8SMGRFfIzzcWEXi4SYJSTIGeeUxUn6cgXgcHa4MIrCl1fIq9DWQJMR79lFzpP7u9s829yjv4i6bzESUv4mxDMqKSql\\/hMf7DmazzM3dqYcFzhUNfGMNEwL1XJQq38izIHrkg7n7esgXOwTDwmbMvRC\\/vVDSPWKDCiRX\\/9KdfYHD+YYG82zp7ZHm+w4U9iF4efxdzA2BuFpTq5vpw+QIbkAZVw19xKDZjjYZQZjuAFmTl7Uw2KPvHyDHk4q7lp1LQ7HiXbNeBW83PnQRwbTrbFUCYd\\/UqX2Y+VwwqZ1RBIkxqYOCPWMjjTF1hSBk4vOjdWVnyC2Q15bU0vgYQYZS7LGRq6ACv5MztAk3D8eJGuAFuX4PZvUk9bgVuRLK12gPsapfzZCNf+idrmM17\\/b2QguEkzu\\/GZvo+Y\\/mZKL+hsoijDh+5eoKfB4CPJ3PbeuhaEyReU54iiIS8VQdUUHMisBQ41s8311F8TLP0PwBaLkj4LY8dSgFQwfMAwo9Vdu8YOFyKJ9TpKosFqH\\/63Ptdbqq7oL05pVWx0jEysRI7avtn5AQ+oC7NmzsGzJMRG392Ef4z6Io9qjmcPlvtiu8SAZhiVUay6VgaKaCQdcFMMeJDB4DnJJfcgF9lQSSp70UGjU4IlIi3YImMgsiYvFCWx\\/KvEADpxmBd0tuhGKVI7iQ4A9pX99K2pKh8K8F\\/2Hxjwr4i5iSexc3Afi5UdSVuNd1aHEo\\/VZDFDU6uHECy5mr11MP+j0wC3FX7PPD122w63atYjq1iV8XdVGBAX8rf9mF3EcUkq6Ky4aoP902JSdIgrC\\/Yu8l9fzzJ9jS4ZODP19RFMOHe9\\/Tu8Va3bTW6fYzp7MdJ\\/QcKkd4nnI4oNUag7MLlbA4AYYKSHs6fG2ZRUViMJnWl2PmqJOMdAUKJ\\/uPWKO0RPhlhIIMnO3EU87ILP+z9IrZwjUqVLPRW2IID0+LMSGclpItJKMMeaDYM3sm2tNIM0iEdsN7F1TkbcjHje3FTT7rq8CzI9tjqAOzZOnObIBQSKT4xTvTc\\/m9hZlsb9BwC7mN+s+LIZvZT3XfdgX05Ke7A4TAi8XrPLdt1UclJuVruCaAkVOJsBYRQudl5xwLYi8iQwgofu5NdFBxvboImTTLl+aTQMb1BHHl1\\/+enjUtK3afpED8wrJKtKVulqzKqyU2NtszmHJD0F18QIhuBvd6NsokKjaNR5JKbjQAAJ9VsaMvNgZTN3fvkIQVrafZj\\/FifgnA4t\\/0OvR6HXfSNziUWbmPaD6oRRF40brV0MzS6TbAueImvS5sHm9rva9HzlHpzlpTkUscQDE+3aReJDEfOdMCSv1\\/pS1DkIamPs5CJCdNz42vqZxaRs5fW\\/1U3q2VakadS8GTvdEZK+m26OmxfC8EtSbrKn1jY4f6Nk3X2GpuCjjJ2ywZOU8yS3oNezhrh6S0OGsOMXUwYwnnShBRApTkFcV3mtNMn8988SNdHiY1voE9hW3DjK\\/WXDfvqqsEnJltqgeHgnRnu2L65gp6QNnGt1PyxVfymVIj\\/lez\\/AMkTVhJu9JoN8PdKQuGVeGrdU3hLOAScJ\\/abGTBhFFihj\\/19+3Ovfff\\/oSd\\/DEJQL3BZbxGtt9nd4OfzWv171KngwczwzcnK5WVmrklMXTMINBQ2UQIjbfD0Tg4xjfQga1ZcvaigSU6XFCJjxUir8tscrjwnwKyc7LFLVEm0TBNLRARQ7BeCJJwNNTPIV3xi7DzvM8s5IPSHTKDtud3nGu3Ogst1UqmaCPCkX1AipC+4S8zrf+Klp2EROrbge8zivDNg+ZVKrwhldvx5ONNtzjAIiralbA9Fl+dEU4FEU+bjizj8XVhFAwF32vvGz+ctoDQvWwmSub\\/3NpSaB7q72H6gvdbPFvdE0x3DFsBzYjTx97eeaa5rDSfUo5AnCNQG9p8eQ0m4aiKMBoV7LvOIJOQvehFSysSrtNdDFhV5q06DHz1j2mW89TXXoRDxLjPf9mhKZPhtBLsKs\\/Kf+1a+BdUhkMlGnFvkA2IebDz0ag2E+jp1BxxbSAz2mg+DMilNaFdiq1sGOD+ZOGdZ\\/TenRnDh3\\/i6i\\/3iSjqgcAsWl5BHijq+JULkv6Wh0LbACCeLmKYEmeBgLDfcrMxrFVk5yZuOIHIguY6kUOqp\\/VBB4gwlMR+c4JogRm5cZX63LzggqFdErHI32WgXcZ7UUfYkf9kOa4Zzv6rqUFU6e\\/BrFFDBfp08UUHT4497DJf4pn0\\/ADVyC006wiYRfwHGjJl3qZHAyXhyA4MOyNQRl845TjQRmRJRmFQyXJqR8\\/Jk4E7AbPVJY90oEMUHAjw344Bn5pXveMCn9fHV1jJ6K55NHsA6YiGyNPRu0yp8la2juXLcAxYbZD8FDbFz6fT82VaEn9hoYOhdyKYjtNnGlw8le4g2IHWkFxUV7TyP0x5DZmwQpWpjXLNVz+RlpxlolirBjoQckKHJFxGlkATLWZKcVv8lLFkl+7eP7XdjGokwyCKuOMVVk0grxisIcgZiUkP93UhT\\/zoX7iwZg4k13ZmD2GIjm71CiRZ6gYR3i51rOSoKdDZ1uZkER5rCwDnPw4SgkMnt4oerntJtffb6ksIRZAcwEM8KZQqlhZXWVGFiUgY7WUeVkwVcd5jsjfk4FYIsWMVOiOhEZnIyPhceAPtD8PKF2AsZEW69aiHnQ8kQOepujUGZozEJZhkPUFT354wN1LmV8xwq8liwfQhUyIKas7eW9LA2iidtzFK\\/KaSjuMqZ9pAGNXh7LoMmWE\\/YSn9Qv3Ht6SCYcNAtC2Drx9z5WQyQtEaFmgvq7MvLUU6DMoSvQG6H3j5dAWIFepk\\/7U1QQ6jq7ub1AVyRdXAnLmf8Ycml1WisF8Nyg+AnVVlFwVJR5u21Ruk0c9Um+Yh42lUsKe34a2DVySMAp7NriK+0jVcQnA72slP54UTr02SZiy1kDC7Y4gdZB9im6LkYHGpEDwFFYiIqsMgygq1vdqt\\/k150siAS\\/9Z4mGLTnl3u21ldyNxZ+ru3\\/o3hb9SJ45bs2n2mRgiAX+Cj5Uq8z9sTyIMSCjYrwns1IxCm2JN6nwxp39mwHyPu4RC7XUTjK4O4djtgiR4K4bUYldgO6GZjxNOE4XgHFRXUwLePlwP4P3yao77mEYiKbn4qxmmTWXzGnKhiD\\/cQ1SvZbdp1pwZnZRMLuRc+QFBWlKwUYi3obHRc518ks\\/FleT7Nmwcplgjn8OfpW4Z8U3MHCEFErrgFPElDTflaSfnwPqw\\/pj\\/Xj\\/dubtyych+2Hr+KOI8yOSJuWl31OmdHsLTLvy1S0UpPAX8bZlUPjYFZj+2yPAfE8EaCwP+kUBrJpGa\\/bAtdsgQGqLdsp2An7LnLMYLEmhPdMGynLcmW5XteQ1d+1Wf1Ssv0vMVy2B\\/4t67k1120Q0XjzrTPbbOp+luq3gN4B32NHZ5MSxAjHQdCJ2BzV9wGzxQ0RDBkPqyNa243fkcW\\/o5TfZCA5R8LW8VdkW5MKRv6DiCTN+SeCTo+j12hm6YSBYaYR1bL4AEzr7bd+y7xBmPjHhUmBEaB\\/bDiNlLkFnAtlvE8idmGOT0CTzhWdmkj+sLUsOxAdjC7RX+O0nIUsBslxtg43cyeQ2EmwLh0CjG1yXJuqO4zvPsWQfBrimco8y4vCzqHsLRdJb4DGN5w82LRBfn\\/XOCMNlF3OiH2CwnoVBNqTLGf92RvSACSMYU2k3DPNZcXTp\\/k11DE20mtMteKi46s8KE6NGxLi1h4tP6pbbpQ+SIL9b4xD7iZAGzJKGkPUWT2aASiIzH0YakIO562sOMGTmwSwVx7\\/EiEyXJafVU9X4ZO0IKQZuuEiym1ArMfFavQ4A6VEH3SbFEh\\/dsCu7w5vxSBECJLQ+jwwjNOhEogOpQDOGfhpI2\\/ZM5lzmEbX5VSqkJOT4\\/CFNmkHiXXXV0WKH6m1qaRN4xDkzJFrZIBMW+37bfxwKqJ4lpefw3x1rSECKDqReSDHrVlML1dP16wgXaUXP3iVkc39xrn8G4e8PoKhKvHhvk3rxUHTMWq8bzEpxdg4r\\/ttcd+cZ9yd0ZuoS0s1ro+3RGh2vtl024YjuXTrbkwNDQlbiPGTOegpg23XlkfyLhsQGdAZ7nihQnQdGbJciSrYpQ8SNJeKxwr9d6kDWBZve0NzJN0o+lfg4iY\\/+HPZpIUzfR+GelGfePQukFtDiyI2tiWfRLOOlSInPrd3ofh80RYP84fNWrFu3AFn2HILpgrvrq39aGTyEk8NB2QI2Sy1UikX\\/itvK29FWPDnvUsCKLsMikGXmP7aH\\/9vqZbIEYpLbfnqh0cUgG5bMxmwo7RrzqVbfhaBgIIzORxf9rDvo3yOURXOnB5Dg90OQ44TTI2sNUMMzXN9ibap6s2g0MNCeVzWDiuqcv1MZSyGM5l4GiCO4mAYfXQtUo07G79+FNBAQHttjfTg+FdlmQy+8twu+UMtPP+4s4sH+SF2rTnvZfUHR32QhTGe+iXRr5fmKdppxSUknfVCu75hRKNvDtUgVrGlgOCRoiF8ViSJL+aj0AVxAaukmI2ajSQph\\/VV5wGdnpDh8OTPF3NaAVCGZS3ZjWiAwxOl3UCKRl2hzQHVh7\\/DdmV6iJO4I3lU+IKTnSu1oNtHIl2a268K\\/3ABnkRABezgTNPfPlpUC7WJgRKP1XHvusaOxnTFeOqvDCkKY5+vnT3n8kLWbdTGBNFBWJEnOF2GPI0C6EZWB+YvJ6Ya+INJp0g+ZflthxaujN0m57DPuOywOqu2Pf3qFt4jGJQ1QpXl4Pb2Hoy0HbUEiVZTVTOdOlIIfAb+d1nzjm16TIQRqtYcQiflAuTNevJUzhJ+rH3qMnVtZ+0bFvy2cPjgHgY4b8Kpp3Isi0N4gDsdggJ0KDjVfOooYv27\\/NrtE\\/dxrBkV3e6PvgJGJeR6S2XM1DfW70ciC9NRCs2zlfx0fss1HxL4adh8AQ99GeGMqvRgiY1\\/C7ZBZIZpZciN8CS3UxphQFtc4lxDiIVvsWtRyq8snIChBeQNxDiq4Vlxs0nLfoISjYOpsTiuX5GN+zhcBTuPxjnHnL1uYHPubnI\\/N\\/e0Xm11qB+ahbVC6kAZjhNBpSeqMZU3+h\\/2QG+tpMo+v2Vbm+K1hlouSNdvZFk4P5JQzjSPK\\/JNAxSoFippg7cBV04+KyTTlogykzejQQcN97QfXkdMIdK08K2UcHi\\/Fxu7nAoAEzQ0dpuF+8BEY+CwDvJfBKqTxYKh5h\\/hClqzSqm7RZ71+b6J4SJ4EnwceRGRDChiCLR7TR6AxTz62ZimgvGV\\/WFIIde4MM8ORgzc3AOhSQrRidBa0aq1dJEPkoW7YNe1Rfu8ZLfAYbYtTx6360L3Cgub5qnLt3izHa7rtB6Vo2ApQINGQoUf84KsVIudsNImDSURrZAyBmQiZMZ\\/OwaHYy6SUgji7KqXVJ+NWLC3dNwqCcJiZlKDJttZgWwYXuO8AN0jIFTJMY4drx14syAlcZm8SK9jIVIoAYSGtDWS3GPQefvnwjMeEK8uRGX3XqIIu3xd6frstM9qDUrv1TEdNHa9Gu9tFQqicmy3hhO3x6FIbWcymZwBpCLFJ8FQednKGOPY81YqBBUDbY4XmJzy6y0eWiwZiVkRVtu7YqXTXZ0V\\/CIIT7Qx6Asv4afW260e78ywcdcCbx7eAUmvcsExMuwanYwFuds1wlen4mmyLQcq1cqwBd045ZzKQk5xQZ5t5Sv18yydZOMlF+tKDy6z2wD86C\\/4qnw1DK68sAtM+t2VKdYkd8zU1Ai0fO6GTrkPTsWwV4ZNfPh6fjfcI6iOhWbPgL4GCi3j3DJkX2rJv13ofrpYo+zBvv1lzSLcfIjQTuHhR+RFfX9ngH1Q2mcsYDjcdImXscVvb4QElMAGd+h4txpHuxxoAph8e8wQETFaFmyYdowXs4VLBTxjCnOnmHWaxoesDbvghCr\\/UZO03RBQ0+XJnEJuZIH+Jh4LQPjcBu9ZM\\/4wDr4KlQ9Kp3XHStqOfzuXTdrR4svhZTT2l8AH9MyMPZ7d8mBR\\/vVcZuEPkM6VwSrMgbj+1Pn9RL45hM5BdgxjQPyZivynIbCbi6HU1EHigJ12pnH5sReHk\\/fcOwXmHdfIsPdoHodyiOGOpiBQ4ZhM7DImORUnojBvXO0utLlPg0WHfP3Jh4m7oCgJe29d4c2VvdANe+D1+FBejLLAWT1ZNrPlFl2vZNPdJ0aR6JfZIqw\\/Vv1Cq8yNyrej80fEBvYViTkLLq13DHjqLkvOpAy3yS5HjDSIWitWF3gtr5gHTPX1dNKs7ZiXCnKcFQiVrOCXk1xLNC02FegG6EJQES\\/jBn56jzhZ0POyvj6PqLUiXrWSCRh2PtR4ekcOCGF8W40KxoJTtVS2EMEBLE5WW5MHWW11J9ak5MJQp2J0G3t7NKoSkUCPN7ZIjFpJPmE5ZYtvXyBirCTS5UiF8ixreiW4R0rhEOlqLRGtJUAEibAHc7lgrPecqrAiqalz1xA7ZOHop+\\/zmnAwBGg5Zs49BjQUyMlDKjM\\/cl7uTLw4fzb7e27Tr6gf9uXh22+AgVhYomeIYknKu0eq8M5yFTevBQ6HELb0VhvIF4PMZ61QZawEWPKS2u2K5DYqtHIiTpcTtXqsw1mVDtp0xMD1ibb7AuuasjBF3hc1YzQg\\/Of+qK34KIWHHu2lVsHRuHcxJb6qRzJ2bBux3RTwF5pEiHyCKb4FjrtWKyWnKoiiaJ\\/w2DUcGbRDIZFN4RHf5t+n4YOUn9A\\/KrVyBsTbtsacUzRg4xROFuHjZZVKEx9aWDBGkPe6qS2EP18Dk8Px4uzztkixyE84irb2KaytfwNi8xQv70tVkFVHVkHdbzSpjaVPKGsQ\\/9aqlnsRdcJnOgUDKvBEWgYT9LQloyzUrhyNq3oaD0SQLxIXMbjcXpbQCCeaiunTzl0N5ST0U+\\/o4R+ISDq+v95vBC938FAIZPI6jrHMnmtRcP81SukeiMZWB6IFMG2okDoEY\\/xc9pt\\/h8QHNWVaqacyvHdToW2pYT4jndFIve2lJiMbs6Pa2PQjh2cKldFr2CDM8T9RFRoIjK0fSMV5FG1gYhtEGJNqO\\/avwWyx32w2rF7s6vDSTb8ikQo8V3yVmuno5EwcIid7Gjri7POotsyLxbtIzOEIg5Wvob+rYlOX5PYvnR1TgLMliIXd2oLyR0+Nh0Qa\\/aSBGsKJmtZeFmIWyDkChR\\/huIP+kwyQzbyFI2LsmqypwGrvI5kBeN79My0RSa+MCk6tHysnV59\\/4vy8Wb5mvPxO0yN1yh4KZBEopiApK6kIy4p4tGhjGAzl2p62I2rTufrHgO3fNVfZNDA5QRb6a5pCvz5QlNMzAX4QE8+PUN5c3ODrliUOGWmqWwXF2meuEICY9cxFH32usmsghRWErDo7CMWSFVn3tch8TBZz+y1Gklg21+I2kGRdUo6fXGMTetRp5fLuBzoG4CZt9ldhOLVRt2E8w2LKTVyau6w9PfPW3rF\\/u5+W4HvpmGijG4nRSG76I9DN5t7XKnarM174rDIvUTYLkjJdzW5TVZu\\/BaHf2chrcTR1MtxrOinxg4zdAyNvlp8QOGGYbe6w18V2maiyGJwHrLHVklqA+ka7v8fye3BbhRbtmCztF+WIHpUNfbSSy4rpJ0JwBlZPQZMusElLib789zRHzWLKE7ao3\\/Ybet+acikf\\/o5LqHqgE1r2hSxjD+N9ccnDJYGa+MOd3GyLo2exD0TA5ZGEDKsuHvaM2SeLbGWtNu81k4fasqOAtudOV467df94nYzDGwEu24ehoL0E8WgHXrTql+DMlQXssYZtEPXvH6\\/MMCLidzC5tObNwX1oXz1O4zF+quKlwMXQxOMgXvtu7IxVxaYsB0mmmoBi4K5HHIROyUwfXTHY7+tyubX8JJI5QjAZb5PAax16KBw4oRJMWQ47LvYm9u28HhLd9zcY5Y\\/MWfxXQUOm+ntqR2Z7DKOPatpYtnMzzbSZZvkDSJ\\/slfqFuBX33EWq8lMnwUwClump+edVVEr1XaBHmd43wzIPeN7VxFmu\\/3t2Las9csN8MDLSpP336C1KWWCOHEcPzQ1JRD+NPYPDEX823MoDEoVX21gcBvzpSJcq6\\/cQSw09ZUqVgAyoaLqtpbzG6HcEpgd\\/baDG7hlQyH7LLyhlWbNEPKmJgHblbHTepiDqrm4dc2QjLwwkWa\\/AnXm3Xt1vtEpRpf3nF9lxg0MmTHvk77nPDXyIx5xRz9GGrHkIMiUtghKQjAuohSYSMqeDHRC5G5ZFORFtkGmWZzcGI\\/sCWH1RJI7i9ZtQVRBhvcSYSs3eM7aafoqtDT6H5BCIImIUnFQHPA2gsq\\/JmryxFRq5SnNeK2fjN5N+hyCwzhxKDBYDBQ9vGmCpxwhQD14LFa9NS0TGEr55oiSqXFMwlrgHSP5q90QC6c\\/A0HJ7jK4BsqFpoegc9ItDMdpd\\/FJK2bX2hzsQCewu0\\/l82Lvkj81ciXwLzeyWjbPicg8uzlgWYWetwgeuiEYvZPSRwHvtrKYld19aq6EFyP6c\\/oVDVNp0qYF\\/5gnGFLGKlHyl951lWwMAyuGWxpPWabU\\/yJC8GTA8Hm0RzRfvE1Chv2rGJPIm7y5UER5x0ChSdwnxhL+CZaSoh\\/jXNq8yQh\\/Oiq0ZA32rNxUfYukh9s9kf7RHFV3lDUeCtd4ZMVKu2EQOgIfMBnFBC5WNZrFtPZxGGHz5yv99+aQ2WpqWBiANJn6VTbJQnlME\\/BC\\/TKNK4KQasKNyqhVS11JCPpdT5Rs6+fj3Q5B2GTEQcHjzbdxvkHOFM9NEjF9y63kcMrL88JGkVH6SiDiCHA1HuS52gAeyi\\/O3RdkowMvQN7Zs\\/KhORSZGhKLnZrhvgzkGNmbjaCPdwniMUppMAsm2wgn1nPamay3q3Os\\/\\/5MK4FjWYCjtB54OMUkc1HAZwq9VSt0lJ3E1H5skjIr2c3QmFA4VQVeFHJ83X6lJmC1Fs5vYKEo0NafsBChzyHG+44F\\/yW7WHJvAE87GJGah6HdIzG1B6VYGt10vn05hXBZM4Iw5NBkFslPWldrs33FgR4O+GU1xhnqIQD6mXwGZjTs3qhOin3FPQfqAF3jAZKytnhfIqR4mAbTAhR82vNZ4Ka1CW1uXTT3JD6deHyIMwkE8yj50yKCLxLTnsQnoDeMrnZLMT\\/qyWv4o20zgFKJ29qEUhImIBjYkPpZalk8TZllRAkW\\/UXvZ518A+OsfzBjeXWJU6Hq+3vmnVjNWMe9+sYRWQsWauJCly2hh2YoqRD6A3ls67Vo0sOS8EzY9oDAHN+fAjGAhTrWQ6q+Mcn1T34+zL5XmE73pJZD1ievutjdXGk8XYPOdEhObGsw2S9VCTWXPyRbKDSuCxRZGlfG9evVU6TR0batFDRdmteNexQ9o9IkzTt0M2hnI7KCw\\/vXNu1McBrt40+hWBG5tzFbTS29eM0vgyAD6O92mTf\\/0jS2A9+biViK3V5CgMRt4i2+K3K1IE0hyhKCjiN1TDcdqIF2FnleiK\\/2FVUQbWU9WIIV4vxBC+xTLSv5EJpvUicBybVhv3SN+TaXD0RrGu\\/UvYvCcOTsdV5WCZaG6YsjLdsnaRYejFxyHTTnnM\\/0yQ\\/TWjsUZBL6mhlTPoUDFjpizNc23FFLv5H2CpKReu\\/hySS28YUBHjUia6UtVJ8PO2O+BJUiZHdfIOaGkejGvPi6w0zNiIHzxDXpRNHYNk+MKW0RkAF\\/Zodvn7jR1fnIcbwO1jo1HHkARhkvwv6W4TR8UFdwq9JQUw0gy1Y0wqA9SjH08kz1yIwbc9dmSdpYblSVWojDxaDQHox2k4irx0iOoHSNEP88MeGkLuo5Dt7Ae8KbUUn0xeG2ecF02KlvsoXU2jTCV1tzI3mURS4516S3I6I2c5SsbQ2BdOVBLGVFgU7sM24nDSQ4GNECKGgwBrem86ioEhtf\\/u5IpvVJD4qHrou37HE8zumuhKq863GXDBWidR85ElzaQTiXhx6+PZ4USMrf4tANQIxngwDT6WePQcFe2eUYaFQymLpEKeM3uIqyiE2\\/Ll1RvNnIunFP14euNdZMnuzX7VxdMDqC798xhc\\/NkS+dp7FiUZKXR7JNt2sy95jaejRcYk\\/+9SztGgkQ4f3aK4tDF6o\\/T+ntnJrHYYHKPk9+fDW5GcsfDULjMeYIQfF915+9mTIulXwb0juuFIT3PAHSk27h9hPHS3Jg+M7RXK7SuB1ERLlp\\/jEAiiLMNVJF3XQD\\/Fs+wjKeGM2HlL\\/9XO7WHq2ipiqG5eY4ZKJ2TDu7qMVcDIodjAU1QCxmRiWJsxBhi+sg6ZlfxbpRQ32awSraHMnN+4EdmOgO9xdbHQSGsfGbH0SgTFfCuFlsvBNStzm7erjETjRSe4BAuRMODl\\/y1nMFj79OuoOyJYCUfGIkpdRnVOX8q3364FkmYMiyER7+VxfOkboeVRpNSTSq2xWal2L5V5+CKxv25Pl5TeanvzfLM1UVmMUKBCMolxee8vNiGXUcEO53Zy3IVR7MiGwbwwAC75pLws0lqbKofCq4QreESlxjd6c\\/xue9Bkn47mQo27rFAJ9H2Ed\\/1AP29bstj8cgyy0of\\/FgAhaFC7d9j5QTJRTNVQqJHR3JJCbbCTbiGFVUQBVpwZs5FQxD6n29phgxGu+g0Tl2TsupG3w2EgYbMIZV9pVe3k\\/YDp6uUBznFIL\\/lN15CTGLYUfRt9W8nt+ea8D+L0K87Yt\\/srErC9zxzAu0mW23dsm+fdFuACcOBypnpDT\\/sxT7RHRVGlQS39xKYqUBWK9A2GGB9NKm3n\\/TWJIqmxRTrIgWlGgIZllS7j2PtcXpLrylhyULwTbA\\/0Lng5vQFDQUjlPCBUGLQ8jQXZk39RYBzuSKXTlICCwVlbc9ADBGaPukL+3HX4Ww8jZizfjzzBzXXXdFcpk5bSyGCBI91QkLcja08YGFFf\\/20HLTw0IXQIlej0zO0JzfkYaqaPOE2d08hwtniy1lM7966gAHc92y1R4lNjI61KMGEmZ2ojKCjFiMNC3dt9JH2\\/CmB3Kr34p2eBNNPH4tJn1QEt4y\\/mkPFLpSbkR2P5mfl5lEDnL0EU6Eh+mD2jzPqF7qg93+nukWeUdyu0YfeqBrxK0mA6eFu0eyCNqboQBFPoCqDP+3+UkP14xxPzxqYCZTMVI5nDmgWJSP6WJd6cVesLzYnRBDr8Lua7j1gJjm+5Sh6NZid9GOsB0d+EkiCJyzKpCjegPEAkDqWvQwH7V\\/TZGot\\/1s9LG\\/eaWZGNBeg4HuloUV75LcdCLwCxIkUgCTyjSx6mP+nn6pD\\/RlOwDyYFsu1XxbOK\\/5kRfhsy\\/zhch5Ih+0w8sFn4izTe2hWJMANa84AzWWXYwQXCqXjLcbEDtW4VBFXqdRR\\/5Klr+4m8DSHSQv8V1tIqoMQYX6l6vpEb4uj\\/Q1XGrgKY\\/7VT9pu45I5DgccvAq4DS4YwS97W0LWyyJnKiBWg5kJLBkJhRqMZjKRUPoyi+IILdigOmZflakIo7NtbxrJJj0s97KlhScB9ZWt99nGNj8Ve2q69aGnfRboOa23YJV3n8TboleMSA7WF\\/bcVZq7HQfAl9eWGJY\\/GdSF\\/kBNYMuCrxUZXeWaqkOpAxOIPSSXzFgaM3fw1s19vMOuw\\/eUS6r3OtWR2TdgVr4ONm2ZH3YYb1CJu22DxEYi9VaE1vhDeK37i+2SPFCBmjVQz\\/XLRmCHy\\/zeGVY4ooNNi2NgZz3+MFyYbfrNTK4H49GOvwCbboIdbL1IPjsHVaAKfcZCeVgwXLf2PwnRFYFCgvh0yVzuqSb5YKZJ7PAmE3QEkSmdAWdOMqb6yjLv0avIDg1L2ip0IhrvZXQi6eS7b\\/YByy0OD61pUtTXyICxsaLh1dczGepyfs+4sw6TnMpf9SWuGl8gOLz4sTFShTnj1MgMhvZZSdNumI7ciEACgIku+Q+t2AVx6XPt0KcmWbAxK65arWgKIua6Zq7acQb9i\\/dc6mEm7Zh61meEC4KFoIg1qgWZYkCRFkUCVPEBWWz92BnM6oEa9USX1rAqMbbuH3tGauNFbtHridZ7TlPSEmjOqe7mlbrCb5420krhulYrTVK6ov3eR+zRwHqJ34HJ\\/D2Pux0wxIVpA0WffctWHjRJBcWrK7xlkvcxxHGJP1zWqYGBhkJK9kydvvvz2f+z1hL6AsT7lrxWDkpY5J+TihkyZdAHWPCm3GTsr+KvsCBs0I47i41sDdUZcfzBX8+36qyxAttG2Bd8HhEWpP8Lfsm0epsHrVCbsa1rBDXZGX+a+L0rET6RaFksDkhJmmTEv1yV2OezYhK22\\/bt5glNrWcvqwOAuEkfvn5wHWcYPMr6pgVKsD2B1wGy\\/w3bX+4VELELO7OfamMl4LlYfOSu2V5Kf3Y3R\\/Zr4YqM2FNZpxm7fEIUiuPrcfo5oL9IX7Qv9Y\\/wXsklPqzxdWqOiPxa+bbXcCcK+9FnEvhK52498PYL82b54n2KupEnQVtAa4eu92irJEocuDjvTiq+0wxYLHouEOpH0\\/Yxw0Y7S8dGqR24mxdyTsGdunC81f2PI2zUsez8ZJmnJWq9V8bVSXUZgn2zb4fJtjJTCQPXvvaTgI6\\/CKzQjpI2cZODAF\\/H4aPe9TUUrsWYvIEi8PwU3bv2dCXgBlnC33xK0CGhVvrdU1GGFtuOlntoS\\/\\/kvCSUysgKEojnHqk1hbntYE90jyAmEQrxLsKxv7Md\\/lmDVJ\\/cu7Igc7fhnuzWUeDHVoOlaJi177aX6YtMjLgPtLeYjnspvUxNnvRMmFbQKa1VFxGbzAfgVikyxFw6TYxwBpOnHE4Bed5hHhikSbUNjiLJhDyhuCP7ktK6V\\/9K9T70q3HbGBEq7jc2Hs3qLIdoVflY69yUn9OK+LjttW4mql+g3RbaVYmd5Urd+ZPdbcKvKVsbcKfH8A5D1GxpWpVbnT2K6KSEofZE93g5ldTUkiCPEWuZxgoCmxsbJb8wswrrMLQG\\/1CgSRtc5C2jO5raucB7uRB3u2+48oJiq0\\/iirZSfXk8BJI9QlAdTDAdTybAvc2NNHAomJhSd7ECdr3dbo9YDjqns\\/SeIgKRjAndzS7QQ5QnN9Fb0SKkIesO\\/m7ZQKEHWNEZXomCpMeGiZ\\/WHGuLUsRuZ5XHgiqYgYnJ7hInOWimpgdXZr7sCHB0LFpBYeu1115A6An7I1dWUcczP216h8tnfVC9v+1b3eFcqcLu\\/A+sNH0nS0frNqlaY\\/s0wNlJv4vNSx8TOSohpkZINwnJAdll\\/eAFd\\/TeLIrcrezB2PnTaM9Hn3BBR9GnliYpt1cOZgKHmmOQOq7h+ZW7TarRePvp2LzZ28Du+kIg9UiMSc6sIDZ1\\/tb70zNTpxpU0uGPOPwAmzv+vqcYuxsOJbE5sXE230sqozdaUs4Ps2Z3iWBPTrsf8HLZvZOLXlDzjkOXHF8LxvbKKv9o7QXzjMj8otb9PseXmAA9r9scKTrYASKFPDem\\/ZedVruKp1gO9mXkjEKhv908l31A+MAjjcM6ModK2iFZz4DJYFHhWY9+avUuJA0gVR49I6v+Nv87tr9JjqTCTAs+PI+0jsRY0bMMOZbFiuZauoV9VNryZX8kckyL\\/jAnHiirQW\\/jqG+ukzud7T3QYA87KUC5NXaXg\\/AaBRQJZZkcz1sdmlC32tHjIIhHiog8\\/4VVvCFO5wn7btXalSDIWxZThyIDjbQbfCtHbz5yqxzfVyw\\/yAMvioVyK52xOiVskHmcQ9HTszqomEG\\/YCE\\/yW3qYS4IsXVha5jKfG65z\\/stBjWxlBR+5jFafs3xbvPrcX2qeQ3GGPFHl92cT\\/9A21t1BOyxzmjC0Jxz7L4crQ+v8\\/QKWUzoOTNON6Ut\\/GTLaSdq4QicPtJjRhVvh+McGaRuC8sFPtKLN8qH0e9c0\\/CzvWKqHOgYNo\\/0v7vhCmu4mMFLDypqvlQys988G\\/VgZlRNVA1xA+DLWZNJtbtycpS8EGeO25SxXv8d4C+tmOSchHuGeZtoAM3FEnPiQcMR\\/TVsRKpAMC9trqX9pSLKxt9mG+Qyp3XIg10klcJZ5Gf5vzpWXRpJiGnn0dTyArKqMgFPQcnf2uguwN+LqS29zTR0DwIVS6lYfZ8V7nNxoLC0\\/jwxgreDGaOHYdeh64yq8bDHcO0PDAzUuT2tph+Suc1qon0dYlavsPsE558FwO4RAyoKkXjF1mFGSXG9Cv0fGjp25c3E\\/FMMkrHbXjVusDNb20yNNkp0AzNlJC8XWrBW0cQKQKssu7Eoh+q9N0ToQMI+Q9NsXdr6uUJRKnIXvLajCahDQCbPhCYEs\\/DPYX0sEElTSQx7\\/1UcxCRheI+4IXzB4xKlXKp3TAifXTTdK4ky5hbbFL1tcKBM\\/BMLL9zWewH9kDFJKKLBC0PQ\\/CjJNUSyCr8SNF6eorDzY2CxuyCynRrYn1z\\/RJg\\/5KuJ4bx0LnJiFiLJEh8P\\/IQ+AAI2IOjJx65j8tMRDwRf7UWGI0mXbDzGQmv4fiHpNBdgZR5xvNkodPc\\/pQ2t0EZzkm97YgIfEser0G+m1nyF0AWviK4sajClcLApdvzr1+kyiR3GoCH9OD1tbOlyYXpEiaSgGZ3clm2KgAi0nuOmk4phYt835Od+rVGI1F9QMiHJxhKeEFYE22ozUR\\/4OdzlHUMqZBh3aUpitXSdEJk\\/eq7ETgwCNpMStVM6629AKTzzKWi13qUifstejI53yb+UizTBBXpWcMVPyuhjMccKkx1Rv1K2FRIh0kcOUGRQI3azFSLPRUljMXzfvxvSrroFPFlH9AVI8x\\/gSBjKOCgvdlGykeIS0rrk\\/hRq1tSVzpjl9RMyV2eFLPyxSX5drILZjz9exqSdvE+VEJRToEJKm1YvvTdsD17QV+0sAzke4aKrkC5nlw7wYzIgNbaxHWLXhcFSD1\\/KHt\\/UT2JV38LY1JvMBSkTZq20bgpMkUaknkXgJR3AtCqb8EPx4dkfaWAXjrXAW1Zyxj2uLUd4mPBVyFenctad6PHo1CYW9Vt31pbOM5N8R+XVOQOmwxAAGiWC7GhIMDz7U3KRCOx9c6X6BhCcdRbXurTc5xbNwm9QDwSF9yA8lQQTL4+s1BrWJ0SbTSrNzC2t4UZq3jtwjB9EGY9TeK8VcKfXncvbx2zK3cejt+7322wqMI70cn8f34resSsZV31OI7gviR2pGsNd1y3Cw2Ep\\/ikL0R5ELxSTl5dJPZcYGcr34ZyTzI\\/J3w7G+AWB60OgkWyXy6irgjDLS\\/XMrIEVjbOFmeb+gg7TDdPYmcgexFYbsQIIE6narI7ANn6z+fJ4zbOw3X5fkQx98H7iDrgqbun3ntzAsQLKZK8iJpgTzJDbPN50o\\/QlGGnOtiru8R\\/92FW17ksN0TiTiBVRgrcngeWuYU3DFySMn\\/TOjPxkm\\/KjUJlikbRb6kods35WNT2x8GwgEb8E0CMRqHuhdpYKFEusJ2Z+UbvQsQ391Ql1jqJEDF3aiimiUO5vOBEUc+hrMphcJrRR0n2ojQJOH5\\/uBiYURpN\\/Xs9qCOf1ZbFEC1K63vDHsklkCYT26qYho0USWQTjIe1gLM6QQ\\/+eyL8U3jikta+G094VOWHK6Lu7znwlpTD+DK704XhI6hw7aWB2wsNh86Bo7gVthtYdfmaC\\/uN6+6fkNvIkUXZQ9kBUnBohRAdk5NZ+gqqhaD1ddURpERfslBw1y7EEJXYc\\/fsJBY8WlkcySZVEMIySjxr20RkO+hQw0Ei5NOnVJWpjMfJfK\\/SbdO0iGqdx2Et3Guy\\/iV5Y72vAfJcdBGCF012Z7zHhxXXxknkyHQaJrkkTP3Ei2dFvD5a6fHbzp8HxpYAReaCcmdBl9kyRIRnfqElg7Xib9K9L+ddVqKVloQeGKytnvmw+LM42VHTZAazwsT6UiFC9wWlYDv5W6xgcwf74qQdodFCZ+LDc+RBU8VF0srD2lROMbzqcRbU6dr2dLu\\/T1\\/vuNibIQMNZcKXTZpcrvXDJgNzrTw8BdfTuw8PK18uAUfC1H45fZWMXVgAOO9K9K1QeleW2JwFJWzB1jNE\\/e8bsEaHa8oY5i9pVcDDJkuKgPj\\/dS\\/oFmzYP5cUyX3DjU3crE\\/ivPPsYMm7uiE2qQKhpFutsYh4FUxgFOAAz40RCUMjXNTXyHKYB2lbVTfHMqYWt2A337Dpin4wJB7yKffZ4AQ1b\\/tW\\/+Bcf84iFpzHD0v43EcOInB6bnrsIR\\/i+VYswLol0mHGdw2XCsyJtTorClp0Uj2SXxRhRipI5RZiZRKP8ZSOwjqXeop0j4TZr2S1PFrbNrLHvXRmA3orgnJMxhu8y5ivGDYHlCuE0Xh2TZp+MaQHVuuvuKmZOLr0QrnUFUg1TuEL0fe5QGuSQS3fAn8MX9n9Ec42TA0W2EmNSJqx43hXBXoHHpUVrkJhVXRWchqO5XfTplZh7GqjivSfoqJqWTSrQC6b+q+zjx+4Ku9LLbNpbi77fYS\\/Vr5CVnZJM1cl\\/SF7nGSSN81Xs5NdjIWl4K4d\\/YzHYVoDNsFS1UHPgNHk3AW1c2GCfKXZn3997euZB9MExImHumE8m6+PchCVmQ7WubiAIgn66qmKiPXQJCO4v0X3PvfIrFHz\\/KmHsmU8vB8Mdt0iBC5o0U5SdvvKZIL1lSsMOftsfUd3rxX7ugPjkGXWrB\\/Y\\/or0I3+wr8PoQJpgdghWK05TZMv0lwlwa7\\/T2yJL3q9fkDe\\/OVCR+TIn1l\\/YZYsYGN4U0OP8l2YyhcPZUd12AWwVyR2BGM\\/n8NpJxFBLMPERMSQ\\/Up1xLkgm0aK4HWbTWKbtFPDDX+FUelAw6oQvrGtfajDxmgOwcCi0L+9zX2I4gCCuOMmlEestGk3eLwjVfFeaFHftA4AwDYgRvJy9SUmha3RCxqS5JQng\\/DuqCN4HwpQIwx3VFDm4R3H7o1wyr1SIBCh5YI+aQtnb+lKkul4yb+SKsPPgCaRcegNWHJsVQRzv09p\\/I6az9RWq5xZTXAgGH73psvQGlQYR0\\/EPw+UHDT89rTdplHePXU\\/8lekfUCkPn1VGoBqGidw6tuBpYYHmWxvAaxMwTO5\\/Vd\\/aWJIRJs2\\/Mwou6qSHfoWp9iuCjENWkdKGzpC6McjJ3S4qvRgaBJ\\/FjqRYRnsKXLLjC1J9hyHyBC4k04LqXQvFscyCX7BbOHLi0+EP68lm4xRjKsPqGNn4josGX3ZcCYK9wRSAqhDnGEfj5QlHXkr9o\\/LmVXDqGZeGxcj0LxrWplqqF4PDEiZceQfZgoz3sccdWoEPdLWPOo0cgl1ihh88hGapzuzMHinEMb0MzPYAcH8HWHnLhFFwVVLIeaCpHXc5P26gya8vQiG+9BiGzVxqIkz6o616Am8ruVJplByHhnSoFTuJmQSCxlI2hXXHD4iKJGbuykT2BCW8bI\\/L8PYPU5CjBy8KTgJDmOXfcxC7Q3oVJ4k3j+jQuj6KljySvAubWbkbvR8Rzx\\/\\/J12e2VZVi6IvmnDaPxgQSrVcFK6\\/ZQ9G2xh6SRCsUcx8tAGKbrZMWipsfdhldxvpFvF0erQhHVfrj\\/zZTmRTLqNeBJgVxwyn7f+nF2rYzob\\/Bn73msy6\\/oxC2UXAJ28DP3DV7JKXHXl2GuiCGSAadhaTTk5ApnDJgn50tGCxBuwY+qZ4bakjKpIujtPc+ATB+2dlXA4WJFaFw\\/bJVxYhTDy3mohm+48h2+5JB1IfgQTgKIAymUORTexCXrVV6I8Hx1ffzm6OAv1bSIoJw0uc7aMxpBxdcdEQhBKimrehxiuDXeNqnJzDUXf+Bau7SIXs8hIRowwl2a7S0WFfImDGDfEndhTZucXDYW52KxjZ+toh\\/KpjagiDUGF\\/mjumRf8Xgl8DIfI2srMIRrNLZxSK+h3lHbPjXn+zLzhAqA7QTNhm8359kB\\/NJd6KjTzwUd3Zg\\/BLDAkfV0It7Oh6ytG+BQ7tygvVN+a78XliLSsaH8IA74ueyFVQd3+uhRZ9jX9AtRt5jwp1AIVZuokyrfAnsd0OSagec6wMXbe7xtQoW2WMMaLyHroWNZ4dr7yuQzha3Ymbo8LASx\\/5XkNMzcW3y+2SxIPt\\/ZQ942A\\/KkighhHttHRkst2D8gG4aX6F46VaBlOfsZlFDX8XTaBNSJBwHhkDXo8vgjn12qDoKTJYhyiRN12QEPrGYO\\/Q5f7QyEn5O7i3vqu4o4E8cobxmQ8TunW7CLVxhdL9DOZbURPDlT\\/ikp996pX8wTs52hCgxkfPsdhs5it5m+ipz+Qe8uCehzBFaAzqqNGIyS+CQ96bv4lHt0FW2sggI6XvMDSrPpe2l7t8D2eOz0hfLWvlX60kcUGhEJ5u+DeZC0Ad5FpQZWtqoCkvHQOquD0gCkbZP6+Pn9SUOJ4SZdVYvomwghMC6efQrj8+8k1N6dzITwNVAz\\/3g8ykzb4+EhYpBtF+dzaEAfRNYl2G4kdNHjzFLaS1h15EKFPiIp67zUIcfg1DWB3y5qkX\\/hccaatkml4\\/y8mUuwH8rm8P5kvBT1wblIJ5I13BhVdLEiyxFI+CbwX9NYAY82rp8i03qlyKvOO4kFj3fd7iyeR01zE0XuDX3I1nbgKXQM7+u5oF3ZBdyQw0gsZETwnjNOWG6E9EQqTEGcLreICVt8esYaI13vi+kd+0auxVwXrIPca0hlzPK1qhBb1Um5wxvmje+qQkBYgYJDGNLn+5qdH7POmHfR7u3Vs5oqFUfG3\\/T1qHfIP95UjT5++rhCHm5S9NJWU2LAxDteN\\/KuMmWWIKdUtEIMbHzBBpn5RYV1Bw68yMj31U5Flkpg1tpE8yxmUM3cNwj1aNkHkqkv\\/td4piL2jgQs9cMvcAP4DMSZydwTSoDUP5CeoMWO5UjvkNbneX1QR1FYKk+qeRqlf6FcSwQBFfhyafmVslinuUGs4hC4RDnnaADeG8KOHV1SHQ\\/gL9Xxk\\/DnYNf9QbBQ5dWlGAwjrOfIIov49TRTmlc0bLMpUVXd1+\\/spjpjmsYkgIzSIV0H8tpPiWQ6SyKo1sfkOzgYwViJCAw0McWwpeaI6RIAMbDX6RU0t4UqlosekhfOgLVrnnUamTY9Yk5Vo\\/NBVf4ySb+zw54vcKC4uQbKJrwgY\\/qoPHczl\\/XC0BplXwz3XgxRMpHAP2GVZLwkdSSCi9Qxt4HHNt50I8MpWFDOywExicwGVdigMlCsOX4WlQW2l0ckOtcW1dJUilJ6RaabFMtEfd\\/hDdqjitnbUdlrcMaPkrpTOgJt+TVGbS9wWVTAe\\/mPLQx8G1Lhw+rHR6Tf3\\/H7mkURsloGGYYOEOFAgYPeiYvQwq6S5Kp5kxeGjtvpV7VGZ6OJJbWUpi6yq3HGlrW9kp66XfZ1cfb3MZp49gdVKn37wM45JmC1zBRBkY2FNS4lPdHpk6VUGtG5iFL5NLzDtrOOnXBbhEQGJTY0U6LjThqF2AxJlSeAHntu2uh9QWC\\/SzDCTg7NY\\/ZlP\\/1xSZc3lSMkN\\/EHuojiqqHa\\/Ggfz3DAVWovVCFQ\\/LrnjzZ0Rn5CWW+7PfNNy3+Jef5tb+HGK4g\\/OSy2lMrbHi6m0q5gxGjAjSXve8ISvPov6jBD415DHZgdsYhjGvBe4aNWa2uaNC8EhwgAefouiu1nJ1+AW9RZ16Rb0GjbwbfVIEkCwxnlZfucsTGJfvt15fSn5yPXn5vFLQP8bBLGhNZbKtGvkJU3ZztiDjQg0jtz3NgT826QTo3PcFEJiSJPGdyGWiDnXNZlqLiZDS8OBS4TTZ2M9b+kCPnLZA+aWK9LTVGE1\\/DZpA1rXhr+t6Q+j4n97Sa3xO6yd3NDuSVyVGty08hLjQmFRO1T7PP4NFGcu1gT5beykkDmKez+tU9pbWPjIS131dsPDGrd0r5NLtEG8apnq25\\/xc0vcY1XxAxVqiCSUglirOtCj5LBCBoQYH55xAMw607kIgL0P7+3EuPjRBm8BM7\\/RFuhwFFzVquUFzdO9iL0YdTYkqhBHOYEDbf5j62R5t0htTypEfouXLzcUBDJR6E8EfuwxwDMoqOZ7T1f\\/wxp3Qhycqn8vgFKINEP7EsOcYGL2MTLV6mtWrX8mpT1sq0LO7wxAFOZnvVTAZ4Lqbd5bBtYbqG+ESRJnkuAkzTx6HmKEjeHbvG0XmZbKogy7L3lLIaCXtEd8zMNud4meANnYpINWHlRSYn1rlH66ntSBcTBjlRFPTf3PTkOOYydNE5ISGoHhdOSuDmB6i\\/C+G1DIYet\\/wOMuDeF2MfW\\/UGpLjIjLeic\\/NQ6Lu04dzNEK\\/+HJ82EgcJUzS8DIV16ILYIl5eDCOBPVYYVwy7AKEObVmIUGHiPMM5DjiG2\\/h1o7Zvhz5yXsdykhCCpjRfL4IYpJPk4oySinpXB+fABWOlCDpxLEwrW+7Cif7SFLm2Azsuqa8pxmGGEvLKjs11gz64EIVfOaDV6Ko4ThZkMugy2KyPSJaOtjQELTivvwb8zkX58yPyyltw5av7WxOZSTp5juEHWRGJ\\/WDd1sWWpGQhjWftrQAoYFeNTMx1s0Jaq\\/+v0czdBp3Aow\\/mQa8OuaiSN4jKAWnE6jQ2JwgeKgGmWST4EEoVOmKwiMxauTS3RQbu0hnBOaQR7FinCI30RaJ8NzfwBojkv7IcGrBc+vcQfT8vUNuuBFtdcFDHbM4zeGgX9aGmJV80zbQtXaR6q5FnhK5psdUm6EXD5lPPm28eyVjPToo8u\\/f4KvUEDfjV3mQo596u85Pit3zj87XMKUMO3mLPdauKUnUlteZSL2nbMGIaUOtniTcoiRd28DF\\/KcUvG3bHIDRtF6rVxa7jmOwu2ZzJFjrCf0R4282DEofkJbyNvPkhsHdsyL8A\\/IooDLppI8kNly03CJOZ5qw\\/OtSPB+kwJe56ge73dy94xc0O\\/grPCoC+7nh8VpuVl80lEuO8ekANwR7gAKFYYjjJsMij0DSmbdAtYpKzLpM3WmJSvXqf8sb5ZfDbT+ji7EHrxSbQkSdAGbELhBPiokjgy5g2cRsAd7FCbbpFKVOvapkCDfy5NRP3gMPz86e5i\\/FUS2zZjNA1wQd8A8IlJ4q4rD2rpKIIPNJ\\/XRSLhPgUCBqYeCiLGdPU6YQEn\\/pYZ3gkxKA73JD4dJspLlSKIw20YTcqWsGr16xfmkvZ4vn7wsJCoeH2hgBQOTVoiNpkle1UhfzztpcVTnnLhGGYUNYxJSKSHQzMvIqJ+8Xu2sjXEus6VUSMsT5HWMjo5IuUXdsuTvZ1sPdzNlrdDr4JJrISnBFvwkU9YBHcxbQVvshTF7jK4A81BIpb3c0g2pgqPX+mZ1HQe3T8oy\\/OB\\/RWbmqBJAEd4Z\\/hPKJ44oV\\/gILJV7Q+jqJDL+s5xF4TUUmFf3mbQFXXbv5SlQudoaSDN78f\\/47y0ZXgAE22oIF8GtX+E3qnYNIzl\\/2FveG7zLbap58xbKYY18bn7Rb+olme+\\/q8ECC9oJuWvd6AaAXHyh\\/m9v3ZLDMwKi7bSe6ApjuQQulsLZqdlLn\\/2v\\/K7Vv2KQXJSx\\/5F9q8TBABpK\\/Hqp8QfSjaoyXJvdclysDLXnJaR+UPEAdkUZo2mev7A8ZzRtcaUGwyF0JqYN+QMadzkNJcHAn7P3KnM9ivS365tDmBYSawYbAksC+yM\\/5c9ve8Iqk+ib2rnyWIYrhhGYIsOKLkrOFtaJXAiPH791xJ4MZqbbu2gWzO6ZzMh7VwLgS7INkPnhbT\\/RhcVCmoNiuMxghU\\/t7q3UcD3HYdNkepOPIJKep32eCmkTR7hj1peGW1TuM4zi+D8O8DhzlxPIat64YJhKIT7ON0mD3+jwiYyjOHDBOzCvllfLYpl\\/Sa943YvHO9NdLSrPNorjG8Cjkb5sx85WABYg2NmVQBP9xzTsbLRgL\\/asC59RELhmRu36429BGmShXNg\\/yHiKT\\/9+hl8toRQpfgzKCbfx3Z013fkWCxpvRVCl\\/VXxzqfkcRUkgfEZmkQskctWZVAPm9hiAU+GHE8hS8LuOaPWEJgNyQKFd3RCLGKs0ZJgHzlZdwERt6tneHidrRjbeT8TAmjKIiSmpZ5VfKKy9LljmHWYhaE2gXMk7DwH\\/6yokB0FnMPwGeZ7yzFuYi3BGSVE8rqrFcYszUy0MO4ljYuwiR2Hik7ImzAtTTmHQjsfOCnPx0hHCwU66oCBB17VvlJgyDRqbGpDhKMfUw4PHUoKHy7fvshSigbTEmt3Vp6heoFCm7TIENN6ExF1cT4EKsEoJ\\/0BUa4h83XZ6Lmh4XRPx3iKqQRR7KUNUJpsN7DB66VlNzIaRmzkC1ytN0\\/Z0uq8+lcJiLnO\\/v4+yIvQMC5RX3kzjI79Ut0l4ts\\/45X2LcoctLer4r125cxLHr\\/rio1ODgKl\\/fwCu7TVBsgmcq9v+mDNFj6dwsQis5xNKXnAxDaqqWgsx0Kzv1KgAKIx9ytma3d3EE+IkXL\\/T\\/i2p4NqAhNWR8IQ7AXMlAzncNktK3odbI6zaSokUhRj9wsCaX13PDKjXqBNlNv+39e\\/AiuTSJ3z0wv8OuBYWeJawMVvnPVsK8Y2yIacE\\/6Z6FnNG2Rd075VJSdo+zIMJMlsO7s8aoXutZnW5z\\/cncbEaF1jVGFsrPuRPnHyepHGvMLbZRpzkSfMiDC5yyNTIA7D\\/vGUXoEYBW4aBpupYlL9VrAXsSz9Xd27AdvoNI1607EnTqhqW0SLluHGRV4EOnofVPRZeLGehEKMoxjuQvHDEgfz+xtaLwveZDOU1VoOjtehHyPYzm70Kxe6GXfjfYleIwAnVYHctUHLHuNHa8i84lFg\\/LOXQJtCDPwiXRQNg6jBHZ9x6g2mze5fVKcmxqG\\/YpCfbz91KqDcBLwH3T416omp5oyCL+AsE3RodLMU3pBlsBAVB6BJurJdaZvUa1U4wXc1gzgfptS7ULHuNZpuTnRm1UQLunrEGtGOkUuxs6N2Ai+9VRaXOyQaEsUrNT8F7N9UvYCW5nU\\/Bkj9q3Fmt19b+7J\\/KMj6PiGtes9xbrO2c\\/36iy2RQnFyRjM\\/TLXVHOtXVyjnCTUiEvfBUKGx4lU6JW6HOmFbi+15\\/uuDkHr1atJY1s9rM1mzx9utCRbPo\\/YjP65SK9HjyKRroQsgVqVaO+ewuzIo1iXpkp2+al\\/b+nfCwjZBnstTzyvC3ef6lfU7cB3237Cs1e2bKuRufAaPXrx2zyWHI8an2b\\/pjnjaeLy7LJwc8DC5Iky\\/45BcRMzQ0sdE3ZPy5Z3RfqZF6T4pD8czFWI8vzjgfd4VfESndZsH5RnovIojtuo8rRmrVR+DrX9MzAtw0OEhygWO2aLVjTv8sam1IyZ4T65I5OYYO0klJ\\/KBU2kNIl0kxv3no7vRmoy2m0507TJFcZ1opwWnayd47leqi5b8F9kbCVSrVZiJUXvnUqPNAeekPkyDwpWgGAjayOLmPuEAZaP6ZcOanPcl7biEQp04UrvigKiL3lTCLX6xXruHe05ZJbbtNUcQbiGfHzHLTnGYM4nC0XATVn7wfsCkYeeRO\\/pqQ8smVgWS53n4IgElJS3AZbjcM24+tQoFgt9X7tKcZOhAK4RPP2izefxWiemt7l2\\/MNxUTFLdpLJVS39\\/CWpCH54lDI8NluvzRpphgPU+6NqZ1K4dYkXcMASo2DQ8JJY1aA5Kg52nTTGsFFZXNQgw4Bt6jImJ6zHwKtOQhF6gyOjcJNpilxgLzKPyTWI\\/D7fIjv\\/hRCx8oeEtgShc8ULhe2VgoXIbP5czhi3nHLCCaNCxbOhJQI85EU+\\/oOj\\/tutbZAnGIGShwDGiA+2YeTt3AJ2YUkHDqn1qPElT5jg3aRwNlmV31F3fmok0FSeS5jFpWyJP3ZbtrJT6NnAtAAsO2rUK9Vy3ihKzvXg3VVWLh4W\\/B2s+A7xixRkWe9NbfJ7oHXavByWKmsgYv3fwsvCRYenIbCDmkIrfV4oynlurbaKC+MJKCs7yjpc2hIEiny6SeeVR3nasQZEirp4cnmr9H76b6GzE4AiySMS7\\/fOWT5oQSLJhnHtxPeuIq2DPIF7c3\\/LJ9yTNL54aVGP+lCQe18d5RRjkJLgkZ4+BikOcbNv8huTagkjpl\\/uwdhEyStk6dAcCVq17if5klHN890kAApDjJcoH9YxLxtrLAsX43TTGPOcFjsEIDRjUHZRRCaJutzSL\\/hdixQL7dAIS27nBOcBU6UKHqTbZ6A0bSTdWkZ1P3Dy8342p\\/DzGiDdbLtswX9qwX6mK0Jf4K5BwzJez978KGq5R05C0IE2kSYDvGdG9XIT5R7FE6aQavdSajixJwpnUnQNDT8SCTGDv40Xt\\/k6QUNwwWhRcIdcXafu3l24RPuj2adV5ySIsNXAofoBaN0\\/2NBeDVXd4FhyUg2lyZANVyVRyQk+rZnFWLGGuYrUFLfM7\\/c66UA6EM\\/rALNnP4fKuD\\/Ob1ZXSo5ZASSpECXW9qR2gYhTP2sA1kU8SATCMlvOD4bChc2+dPJIfs9GoZuXbuojpAU0soTSfQzT0PZRF6IjPJ054pCSL3uiEIVp7TUlNKaEXK3OhzYQSCKGqHoxKMvT\\/7UZrluVMCWa9sgNowsPF6HTl6H6kuPBaaqZ5QufC3TBk\\/exCn0mPboHIMV1Ch+H4XhVZyKcBoL4Yujtb\\/\\/E64zcfDAn6fRBZ9HPaTG0YbeGMBtvHcO4rfMul0EvlE\\/mXB1qmwPusb1SdHrTzA5CtN3BTqutJtk0D4HJD595fikkKDmFjhRxK\\/wLuRvFkEHDz\\/R3uri8+iVsXMixljic6j6L95trcHm0mHvXgDb89aWLunYHtAXpc8tdgb\\/kZIVAsV+sHs8fAHrh8fLpPosWPkw2LFAnm+bt\\/fWb06VkcZ9oi68YLob7SjmQXTTmXeqmdDhSIZDZKHb6qCEVyLgm7TfGpFuh6sgikrue6ATuURxtJa1qCHqNc+8ErY+z84fOe\\/H96YGkyoGKJVTVgiaHgHLrp9OlYyMacHM57Q7YQZweqspittsMuJ8N1WCXsLaYj5IH9h6IGsyxHKj02AazDugt\\/Kkev\\/mMP2T1FklgdhyYRyvjC8oJc8yWAGkLhLB4UmaNKxbkoB8fe00MTAtQWHh0KE5iynvdJnn1oYrwaQZT6kUAf\\/6Pqcvd90S\\/yLW+03bqqwygZKmKLivNbdJcbFmfIu7caQQ06eCYIARbOzQAjtyWPFmmaBnKJF13ifkc84UXJhjKgw4\\/6K64bM1\\/jFXMd7kNv8bgQddTEk9pRft4mmlpTAAhZjxEVSsGeSGv1qe5whR0B\\/4Qo3xxT1yoFJrEuug+hn84FSH0\\/aTsJ4WqTQdYsdtLE0KL2wKjjJYNSBmt8F9CJhCnyFOhe59rb+7LRjgT0FZ4g24nkhJTC0AFjGotIRf+NAbugg010a8FtlHunVoLyxp9wyMcElGAIumvH33mjkRe7J2jC5KFvcNRcxtBiQ\\/ho9oTlGO6GTiRu9QdJe5S2ahXQ1vbmnSdzd9bNYUIGNU4gK7OD230k9YROdHdH7ShbYX6nNQ8WQMfs3\\/i8pJmZf2GA2N+CRXIVpUKLjQvLkXQ8PI2YwRZXh69uQRyD4rgQcS\\/Yr4\\/3CZiz8xMQctTauf0W0bXJNB6eZ29O54mlxC7irVqi0hJ2W0O2w94iXij8Fj50gyz2XNNCQ6uomkRGYjguuAjAiq6mvhKZANEV3v1N24KVLNzgdGOtxz2gtE+LJLffuZztdDQocElaKNEgQcm2OiWCy2kQZPcC5dNW9IY5SlOrB3\\/IXIB\\/DnpIfP6v4bdUrdHO5IaQYGJ6FF4f7GaLBYGSTnRdtFwKOuzlRllKJUceqRXrM0P4FNb6BU5uHDzk+WKend\\/cflv+w5n9WuSxhtKCvMzDeGyJq\\/3VSGKta3fjd0OdNmhhg\\/BrStOruIsTOUBpl1sjLOOybIuUf5j47AhPEF7DyPTgYTKy8g+np00cbdhIQW2YG4wRc9b2z719afxgwi6Qf9V54b3aMBzWL0quS43aqxdYjKa\\/seriBlwuImV3FydqsVHw9hMua83IePooj4ccO1Ew34JR\\/XaH9y2YiG0Cq8Y6uBL0vuSJD6qTJm0XlAQt+1w\\/uawjAy\\/+hgpMJWVHlHFN3lNsZIKfKPTBbXDs1IBCwWXDz676s377BDtBF1FX4rSCPg8xa6PjDGAZPwk8j0K6PMXI1E2SpPz3cBxUnsypOrY4RixmnnUFLPAqgF\\/V1Bmneq3kJHQWJneC0jIXe4WwYwU8Ii6qP4oE8OWbwqKmu0o3zidAeTsj8UHcBZU4\\/2h\\/HaH03pJSwPNy1so67FaGZQ3rjAwPT\\/9Az1kNqZxMOMCHw+OhmMWuZhu567cLNvav3RpKiKNaFdqtrL1EYC5ufuCvTB0SAqX8YxSw8fpuOG9WwAtt3+u4YFLnoR55bRuNQrnkHonMuI+diEWENtiWbOsQHatvfmBnBRuv4yOHk1S2yEMAbQm3Xx6eU7p0r3SGqsi1ocuF7fEXCqf1ff0JaDQlskfrAh6vZ1lB1kJms9kbh+IYcgnRx+N8Yu8txCcxtfCt9zkla99\\/1lHSM0ay87X\\/T0dThc3wMroW5TuMqFtzSLPBMfmxzAcFySx0LDkQRVjsjBEFZgLSkcmqZQ8bIoeSLUdDgWzo42C+3gZiMqo0AL9YPllSYd7lEN2GhsndGDbrC3dnopikg3ANBn3KgDu+Gm0RgNMAeNAacNNQm5ATJ78+UWrI+MLxDhmsmL3OjS4HgtEEztiCQ\\/4bJEN5bFDrcL69gSruwosZYI4ScQIRI9luBD1sA5pibnbEEXB0hglePnoi8kTMw38MmoxDfwN57TE+bAJnIoDjKWkcbG49TA3+3kzl6E8XyPTGX5z5cX\\/GSXWBqQUqVcO7vjwqawU\\/NmtAitvLk4iZfZxpSr8ealP8BnPbTDb\\/uKAGkbZ6anGpbSXrP3gMcJ+klMqSxojEwFwvRniSlrP2tEmjm9Mt8DmHip8zWSSlxXB8r80CtOV2qgX893tl+Cq9QdUays+wBLX0khXiNmsrF5yQML3qt6tnkLqJmaP1sk6M+NNqdY7GH0\\/05T3HjP9trJuE\\/HxD+mtvzYq\\/RL\\/WvEkNGwoZ17FjH5ffNA55347XQQYRoJcRI+06bvcYurDd3F3vEfV3o6c\\/8CHkhEevy2Q0b2m+9yXRVo88kGMJfCNRF\\/MtBAUAmJnF\\/efAGO6e5YVz\\/W5COOk2tiTz3nU6GFdR\\/bLrrvr9Qfg\\/YxoHcylT+b7hssz3YBVHP4U\\/LKRiVh66Qct0CjgXYJjvqIhMh8QRpSioT39a0\\/eoLnY2\\/h2fsca5zmMseOXHgXCg6BwK\\/1DWf27+RedFZpek99tRKYwoAFkBixQ7brwmGqZuFXAOkyBJD1oX9htjVt495NPKaT3ncBrWRN\\/HAlYedS9NCTOkY+fHxM\\/XJTSAYFS0Tbc4vJZMPOmXt821Uc9GWuOus5F2r+78xzcYsqFQQMI8jdZTp38ASkt2N5JNGBGehN+Vp8jbLcpGSlclLDkP9cy2t+un9grEsfjQUoZsyYw+lw+f3EKriLg1iRQrylyUoIEpgV8LEgy9wYe8y6+0+RbuSorB4UExbMk\\/L8b6HSFDdIPtKpUi8Xhzd0nD0oZgT7TSxJRnQpLyqOKlHQdvvAbVhTBhyLfCVRQuiG0pNrfuzUKLNEBOWzgtVt7avg8ZX10+zT2p2WPzddOboeqBXGi5a2UNmIz5IocGFTDCSRvbTYrzzjrtF8GNmxsf\\/JKTfUj+VhVaInMzQv\\/Js3FEUW0pGNQhZB9+\\/Sn2MVtMopjAaedi6ZgmPATnILVdM\\/Divc9mh6Kpf3lsV8mReIO\\/bhQlNDRtQtmfL14A+drkbFIn678FsmJjDdsAOvT\\/85czelhxYeMYW\\/SRB8hDXKSTeUgPVssmSGI+AT+WrtEgeTC99hAMtDWxQ\\/iTsA38WXxQpoky3jBSoro5tm2E1d1Vr66NBnyEiMAqVGrzLKmZKWiwXlgmzqGxwgDz7boOdDgnfp2501NP0FQq0slAF0mK1wNnXP91wjzZ7FgUL2boqTwjr\\/blsskZJNTeXjTIi0W5yVNIMPJVijpMRK5sOPP0be5kq2v7pCsh+TajtWxt8Xvkajc\\/GWiKUkYoRvblODHqUEOJ5flA+nVavvUvBCcgs\\/4sz8WhhWVnSfTlyOlJZRr6WbT2fnpM3mWCURkIL8XFq243O1wMxJRFdhr2YkKLFmPaAAMMpI5pVvVSMUtCjV0mpDAUEYty9KahD\\/Hhdfwv7ft+s4Kx0fVDEKAufYfl+a1PucePtYwxNWWLXnIpbt5Kp\\/\\/QSCBz+vjGxVJMVCUBb2RLSeP8UT1WrJPjtEULijdcrLg5cIJZi8QP5Cs1nDMDrkpoAJFLYvZHmXBlqNXkHJXun3uGfpLUKTZFrkrh+ZiGb9VS5CiaWYYI3wDrMV9yPJWNV\\/xiPb5er+rZol3crHw3zTdyhthbIHdb9cTKDAOqM2SQY9rogukjnaClqjU5DSLkbGbWKHQqs1UsNlpLfSDJgHv7TN27Fhoo1dM4lUATlx26B\\/NUNGkVFXWI1fg3DH78q8sRVGWG\\/3Nw8Il\\/l3jJS8gfvv\\/169tcuhcEsSjCllljn0a0Utiz1hYgVr93N8YdWTXTXNi1+xwEDkHRziJcQAm4uNCxYvYYB1S4HfNHl93cUpOi97DHup3OTOrJwZyJzdwkzfVQGPHCAVEXeIV5HMZoxXcsLBf\\/UZjPHjEDSooQqYU1tfuiSfl9TdO4UqIYsYo8sI54qTFHpuJdJffTgL84yg\\/QxLVFmaZow781MGiosv8jyUfqx5ulboQ1mFUnvacS8V3Qh5z37tKugvPkWsejKTvobJCSjXzPMzhspcJJZENmbLaO2K96tWIoiuQzN1v4SGL7i8\\/ypYVmENkjyvybf2NAcrinwTKBvizoVN\\/NDuoGGO7fmdcFRYNvzdwGJTuUN\\/FEcfbSwhFn1Drq9qlsPNon+ZUfwoUTgVdXJM4R9fPfF31Fr0IjetzIU4iH2UzNHTOmltTE6xltALM0fUAyVLHNdBmiZaTQ7bJmWsiRrXDBnv3TnKWJ8mf3xprjohNg8vcVJq63wvG9voCMpDn7wUkGF2IaLF\\/nfibSMXHGW+A59swvXbtNJGefOmm5Sq0rnQA7793mr7byqiYACRkAWUiuUrzdM1ZSGcU7PQ0yZ+NtjCCOpYjTRbW7laCzBNxQojjaVMT7ZywDFDU0HMcSPKdXkSDkdN8vrslNOf+iN81Baj7SwcaJt4UZJeHT50RVPUrie86aDGZYY8hqsgtcjU8e82VI6NGjUDv\\/ChC0HZYpe9odJdjjsj9aSYtIDOEVCE3DYhn\\/J4ERnvrkSzgDQ5XXu5HFyb1eGNsItoHkyBlj8Xq\\/mWVti0\\/0FbRsT69xSUKbvm9dsEBKcE31SvCdCFxDTySgD6ghLPIhcfcVSMFKLEhGcJ8IG3ionHGLgHf3bl5VdkoXlFh3e4sRGm6MGCHjQlpc\\/+ce8Z7b6lgLJtPY+Vhkvs9K7QQtKe+rtOXUx4sscNMp3OLB4h8Mvzl2iD\\/2m6ABeDrLjUnIFuqJyI1z3fc4QK0Fvep13PI\\/4M7UAUYfr2CjXaNd8oXEsRGXco7BRtscY1d1kvtcGSoSWNivi4ASuChnZjOi61OflnWLTf1tqpnzBGoILulUXGi5MH487GPsu8CcpaNKb\\/I2OUWcO3VczfuOy+lkXmZy4axJ\\/\\/BR0qKr9LNtXRl+lRD\\/hb2LHP3dNBz9XoWnV1iPmzmVuSFaUZaJpK8xwaz6X2zO2EgqFp5+uYtc1HXuotwNgeFsRh1zqNXxnRjh4uP3MJvW14saCXWLj0NDVql673OVJDUScd4b1wrttHiQeNlH3uh44BbCwKRUxEz0zXFvBO3cdmEaauIDDvieYsAYx6vQ6HEJsZKEIMUnR6bSoAcbVMXLFiW36oM7z98u6bZV\\/MQk3\\/K6yGOBVeaSmSWheH2Gez39ddOQQ\\/fdk2rlfnl13hyMLDM+oOfJ31VhI6zJ0GS9DDWUynMTWHju2oR\\/0VfCg2stOH\\/27REtdSP7mk0n862dmzHYA06rizoqCcGWv7jKZppkTKJoVu+frJdwxVTU8F5O+jP8zmT2a0cPPWYtVdyJlY5mMjFc+S4Lu4XsMeTPtMpTv5jNAR482+gC9BP6Axp31EQ2R2HCQsFLR2rBUIo5JEUv2keg+yljOYPTSHMyCuhvA9ECaHdvYOYFYSR6fHt+4LGuXB8Tqofti4KckZp6YAf9QfSSToqbYw2WA0YOK3D0kYjcAc5+CKRqN238L7FTzJgu5ECP0DrkzAGU7nQofmbv3TdRIus+p0rLWOxrNWSnOCNOIj\\/YjA7y2TpeCNKuEX5TilArEgDR09oyOLhDaYHYJ4XAlqTK8VE1dApE53yJMBEXEJu6zH2fvTILHlWaOLsL\\/V+10HxyAVVk2xALGcEn\\/STpv0h6zK4jAxQRgA6SIjO9MNI6PE7GC+t6FbEspqrYU56ikWokE0D3tIgeoIwrGga8xt7uZ4FibcjKIg4\\/\\/IUhD4qDRgrTkMGX9Fo9a5CCzzECDFHvRiAVxbOY2tCOWBI49TergkS213EZvr04nQErOPWp2gLc+d4W7\\/I13Ak7a7cAVkMo\\/pLeElbmUzTwv4ezH7WnQmyofWLazyzSKd4eFqyRtL7\\/Vwi1Kz63ywwcCdYMgdvF+0gpVdZtSoRxez2sNLYO6i5lGhIhm03M0tqPULs9T6o2vore5XfNH2erIKGHPl5m2dSJqbGiGobobGPmf7i7NYk4y6WIRCZfcG3vtEtJCMPrJI0mmp1qms+YWeuoVu2JRfAVPviCAQLwGKf31LRO0Ai6htSDuZMTh6fm7B+vSkW\\/bMK9Lzha8XS3mp0U93NaA9C1b3k4Sfl0SArk9KV0Y8LTMN8g+0R4Japo6qzM6fUJKBTxIan4Nt0GyzQbg04jmQse8+\\/cJVYNr0uKTvrrPXeqBTDonL853RXbc3odI\\/pqA5stnNvxgCc+JFXgUTZc8wQVv0aBkQgFO7Mq4o0gdG22nJmpHKggkgJuXpLJB19kRIb8aLTOR3g2LCXPBOeil9iDaDxxA+NHjfuYefi3Uq\\/hTFD\\/5q8WtiCmQ8dBlAN+RLISvXFOi91BWbyMGAHfigz4oxD2RYHx8MDwb8USWlBSb4sn9I7E8gEfgW3qysdybD8KlUqSL+ZSza4\\/LR9OAzf6S96QFZMLalNbdgoOBSWiQk2Qf8RZsbDphsT2thPS8baUjdxDGMwQdz7yye4BEAzhVcVu9PbalKsu1R+I0sicq4j6mvLA8v4CJ4W6O5g8b\\/N\\/+MpSl1c3ydTD+KiNAt55sB57Le7eDEZZq9\\/V+PJumoPWclrmu89795BH5wfedH9LoaB6Au4rAdyE3FNEoMGqghnLTV08IE+SyJOXDuzLqbEBwMs7ZC75U3aJXKGtumr9rB006GoFEDH0D\\/or575szEoitdzOlCajvZkhKhvFGhkWb48FSWo\\/ZyGXBWtf0KAP\\/zqvts8CxOlMPSznOPjeBrPXpEcZQ47+5HdC78redqCbn1Sm2uZh\\/\\/ZRIaZmoSAEiQD7vUkO2Vq1sp+\\/v6+co3Lrl3qMaw3hXGjVig4i4tPiEPLb4yO6umbMuyxomPyPrNCdt49LWKe2+B2qUxNhGttqunTQaihe2N07ryFL9K+aYKyWV+ey\\/vKOjSBHhb34D8t9HB9YmgiklBR03sco1ZZrmEy+Ub0NWph2NCPJBAuapPuCeSgBjwSyfg4OG7OWCpwml8ovSsnHbAZUT9N+tVtGcOX92XwTePlVpCo0R0RNrQvPTbA+29fnNtiw1fOyPkfgQqOIc2aawg0MFZqstb3Y40b+JzxJhYOtZaAnap7YRwhNVlTGOjX0clmwNzvithhpMqR7DQLPYmg1k\\/6cIahh0TESLnRbxQxw0srgJbP7w2+UmhPAcpF1snab3HyERsCsGK68r3hlGraguSsIbcErOGNcBFw8JEN58UJxYpTUXBcQ5AigKG2AO3rH+Zseudlhfp3AOl0LexpYkfSsD0hCWL0f97iVb7WbQW44wLuMzDzDqXxVZSZ88LFbQRr2hJfzyaxeKrsPPCyjj+DYaBGWJv1hh5jm1Oajho9fiDWJXGOsCHo4\\/wyHgi77ivb+rcGWK29js3pBPHdjbak2+lsTfn1bwjfSD\\/loamilmYaesb4\\/N65Bixj2nLsKt+ZBjlieV+hZ5KQoRNrCzaz1KdTKe11hOF3H7KXAviWzRPvJmJnln5jFE59G8eRxEBwouYb1u3Dfru2JQg35w9ZQJFg0z\\/QLhfY\\/WiliW22fhT5opOmqJX7jFIUyKGazeZ801lrVlOwhJ6tcaV+o\\/3UJ\\/nMOseHNBlBIE7cxA8\\/UU6SjTKUPpXOtHdZzHXqj5GtF6N4nMsuHD03QEEF8uOPEMcEQPukRuz2Gzl\\/K7JkX6t\\/ouGg4vvFcaRMmFK+0isRBOzfcihPHti1VC3aqkQ3sx3EUk6W0TpMCdbCaXGKE2BeYy+YXgxrh2g\\/riDnqaOpXF5gxbm1tD0dDBPCky09llQIuBwdtgnQTjsHgElmiKyre2qOlhfjYECScRJ3PvqXrQZmU9qh8tXC80LqBB5H1Sq\\/6tiYNl3jRCP+1TQHlwth0gZT1qAl4ZyO\\/nCUKEj4WSC7H9aVjkRnX98lbqBxIhjS5SmLkkT369\\/yknMEAipLVFqGxNo6Ogl\\/OD1oC3TyNjRemfeKTyRE2mV0h9Dl80hsPJzoJ+Oh5QRodgj4lKda+4CjRNpiWGn7XL4VsgV3iAbt1ABzApqJThGWl+VndXpFqNdWPcgyZ7+cY7X9EOYt7NB2YZU5y7ZaNQH5m8qTnZ7DHEDaBfAKz1G3IsG3kH\\/LGG5Ph+\\/PN4oaJH4DaV2vWXAEiAYPUdK8cmtowzO+7W6y5WIlEfurejIe6Dse+UMfty2LZzX1\\/R9hVmHqUEK+6acHyJMEBymFwa1Rp5NLDJ3PhegklNCAVUBKIXAnAFUWbgcClLdvLWUfjjcoRrkbgk9hry9F+A2Y+yuMgWvsK7SrZLvXtaQIafRfoClZAnAd8Dpt2aLkic8qjgdRALkbREYrEIUmqK\\/HRquZHUw+9pal0rZq2+TATH0hdIs1Iod156bsgvfDP\\/EJeYDTFJuW5QlVXAaB5A2x3v\\/fmdxxKg3SGl\\/nCbRzf\\/2oO43h+QC6T1ZM1E8Ub\\/H618fwexl+crhEa3h7\\/3veEE9a0a+0jcRD3+Dc3JvQyV6TH1c3QPZta0NtLreIcwP8E9gOHQ77Ne0PXKx6mv\\/6WPmm9u50xKNmD0qNGeLCd3bxXl+JDi2OmX12mK9merpi4OTyUI5PzRKq52NnT2ZbYWH0niJk1kzOKtX8p7XpaTj3tJQtkY5TUiYR0mw8Op+VUfEgcfDTAERpYy5k9tJmS1ETcuMgd0wpg7EVMRWmuMzaTL3hIzd9bH7pNeRkd5UBgO5co8ZCeiBly5qk04AfTwY0iYavccSp\\/OLL24QBHHy8GyQQMjnqkicC1UagVnTbNORMmSYtYSm525RmT8C3ibppTuKFAdBlK13pSc6PfAsnOMxEiEQuIIrPymSayOSHllJeKZyL\\/LBGVpCelffiEN3Rn2xlbFJSWLCIiKitwZc6\\/grJds\\/OIntSAEMISNmvpDa2zQt8MP9C8RSHBY5F2pnZ\\/P2CBI64d1MgSphaeQyAybmtnCZl7BZBSHC2\\/RUgaIqYN4+YdOGzcPPG3rRQIF935UAWf73OZFAM5gtsw1E2+m3G64wxX4zoQ1kLSOCGOCniy5TboT2LM7+CG8wO+5czN8HKEmBRSLsGvCdM63xXmbseQbC6I\\/723Tuoe5xcSXNZ86v9lMkciFLDu8JmYna1KUWVZdMGlPGtr7\\/Cz6VOKnTXDLDLZ8ZnHViPrKemNlFjauWlKbesNj3ixNopaeGRoYAF7vcWZ7kX1GSeHEryMF24nV8Hc2D4ckbYraygAzKYeW3i0kRdTdXnRm\\/PsQFw+mmMK\\/Hb1r3d7WQ3yPlafVG4ENDZdksXlMbn8I1Cs3jAkYduFV7wD5IFnvxN9UsymIU3krXUez3MLqnXTmkou602clONmU5FVfwryo\\/q4d7tPrvrw7fiPeCzcE3VnOdWyRLg2oIVO67HH4Neex9arks38CaOTg0jEXJyN4lDHiuEUJBk2NZrgh5mgGlNQnbD4z0LBsVvXlkSlAZnaARalbGbwP1IDAec1uAKqVBvW4iTq8Ytqz76p8ulYohyNbBsBEJZaWxeT6Trv4wYSyE55vidWc8llF54EVM5yuvLLF\\/fSI3gfuPKObmPRFNqzJJeiwFJnrwafgDSMX5\\/n4wAm+6ro7ZDFPIY559B6KXao2aVw5p51OT2GDBZuMnWKRtHOyqfFI3wjkFFXDS7IfA8IZkN3OE5L8RW8Q7utwhrM+SDlqGxJDdKCd\\/JRSk8EA2b6r35CxVMxVTDUDaCj0dzbOryOZn9TTVfABeWl7oZFONDM\\/1YJsDGpDA+1tkV8qukrAZ5Awpvs393x9p1tPlN7xIA04m3OlmRrLVPCwJdhS+NKbRynuEBzo1MJ7AYAS3R9BqlCpvKNIOWKn4EG1PIaeyK3bw+x2B1OcwwW906WEWfhEisQx4VG858wVBYNUWI3NsYZT0QEF9Nc\\/elXeVggwIduBcAdlICKnSVvwI1UUJrdWhIk0\\/j81rNzQfRH\\/ijxZOEgpahH3RindYFCIgEyibHI6z2ezvDVrpyeQLwFe6ZLClMqlWT0mmkGriHPJ1XOZUixJmbbq4+EzX4K6LAGtChC4ffmIVqxIEvppCwAidmQLMv8zU7MOXRD6YGcsCYfjhjWunOnc8Gdj\\/a26qu+zlQKshbK5b6tQ6Xe5QEL0hlsl2AolgkGbf+sN4dFe\\/x4ThRqvdLR22GeC1mkswpF0Io8IZnQeiSe\\/lIjIzLxIY\\/dEw8PNc3VjAazNFfqzPhPYFBI\\/8bfTYjtQ00ZfiY3AE5bA9R5m8pvVWSqzQISIqjpvfMKnzqYgmG8Vm7VVnL2A3NlGuYs+noyqcS8kOskaJ56fVoQ1K5XxzFVyTqvkGYUqYY0R7x7yspc2Jg19K3XE5kI8oVV1Axk6oVI70qb4xyJHbT\\/SVo7vQrL15NzT\\/A1+O41OVqemZyw9T72Js1op6tmu7T+rbngEY5LCVgpCZvcxSAybF+zklzBEW29lex80zhEARq4dlsEArRrgPUi\\/1oWQ7AXhT7\\/7N6ZoDVE1iIOHmPUC0jPbRrcR9rFf+tZFf0JY0\\/5ZgvH8HdfHUZ7O99YSE8qJq3RVW\\/E3GmORpUTSFe\\/Mwxx8DwWGG13PAAnN23hjiDkghBELDm6irfuwMdn\\/U2i6KQZSWLhzZcWH+zKsStQ1S1uWZTDHXQJjINdP1Qa0OkEtAR54Q1bcmAUkmj3Ey6Caa3fzKwjRkEprLuAjv8XKnMX\\/d04W1aSd0wz5pSKRZS4RN4eAsd8Vr454lIgLBCcnVm12OhQFqTyko5sJ0oAfIh6om81C61kOg9Rq9lGc\\/5EVb+Y3t+VwdR\\/YC6pcoc4TGRfN14uyqX26rZX\\/kfQTVaNjsZNx77DX3s++TsK2zu3gLUpUVHzOjm4M9ZDHYr0doqxmXnBeEIqrRCZRroQWZmxzrtwEWBubPoQ47CqiRsv1GIcILzOkKHUaaMkPEu8beSsJVA8xS0RpWe4KMLSEarI+l9CyPjMKyFnlgMI\\/PED0uwbm1Zq\\/qN9BeWxvF5a815PApBFa6OvoalJPmQONGcwYZ\\/1umQCGmlc\\/MRISYxcVjEdDXMMLEzxGon8+46mKcAwv3+ziEyMrjXDh7D2fYfjbbbF5mcLJTZ0sv4YlDJ2CjCJ8gtBwntRLlprzkD\\/DEqdOO9ZSq\\/9whYl\\/HIbBK9TAiKOFpN0KROxPBZwYwI7z9kkh0y\\/o8OngSSD0+36DAbZJWrTAJQ8QyXO1W2QLwTGGSDaPz\\/1zruP0qULD8ReEYafrufQzDH5b6r6kfRLTew9l4gP0TIe5YhuwwJVtymzwuVpjyjt6yw+pSwuZTi4tGWvBuAPBBwSIhn991fqAoM\\/qO4wEViwCh29AfrA22tyZcqHpDp\\/j8LbObcMLUAp3iz3fuCTvn5+4rCinIchYNr2hbiuSD4LwU9\\/empe7X24smhz5GKfUBTyaLL0sh7ds3S+wRoKnxywBcS13uvPvu00z0a2ZF1rd3LvqFUUNAw+e1ejahDRL1ssxGWnAovaDHejbrvl8eONeNrFcpu5x94kJOMaeSzKwDE7JDAMfwK1Dp+VFlD8fHesXLZg3VpLF8\\/neo\\/YGAovYCPgq22Urycmpc1aUD3J3459HNItwyxY7bxViGyb1X3QrFYf9v7BKw59mrc7ioCfZMoQ0P\\/k\\/GSjcCE3EUSaEglJN3oQqhoZBJvZ+kmEr+f3zLD76TW98MCDGxtyG9Eco\\/M9gm\\/7TRaXt3uRXwqUX3n1uObP8wSm5VsCkzh1ThqtigPJMhRTU1xrId1L7HxpDusqRG6vMdtrAR4BDBruvOH0HvbV5kOWHdTKb+9WJnK0rPDO7iRH\\/V8WPdD44voMujfmRHw+f2uZ1g\\/i11PR\\/1cc3A1cPofLba9Hg4jIvqcqXyClmFTDQxc6vpJI77TAr+M7VTbO3p7tTAGck+lpsDwIC4rGo6yCUqffVQeDFoXVrJYm2o2e+ey4fLWU3p9zpI\\/hfW4HQn5+v\\/hetNwIz2aVOlIiGOMtIcH7fT292h16dodO12oGU6TeLmHMl9RGLYu6860uU7VRdZO1yxvvHiRKdGsmguBlBgfxeuieYBsaTfu1ygvpKqE9enl9xdoC8IqI+czkHxvncEV9sCikPqqhPs5vTGUUi6yjKNnoG5O3n5H3anGDlNrnzKYildPJOeko8GBu8CXSe9b7IBa3NPFcTsSJ1pGosr7qdqW+zBLRfQp7uF\\/skXgZJTHonDhjz4QmwfWB\\/fmx29jhr2y1WZkmZYU83Q7am60NyzcAkCWjUvuQhzismn8az8kpGjZ0KweUub6Cwc\\/QEKTHrHc\\/4hhUc6qDrQHz2ZwAIV2RRl6OIin8Vm3jQ9mO9lFKH87sZ5fXvZTu2r8uZG5QRSv0XxXqjyf\\/I\\/eaYW0JQm6t4oNzYVVfxl4uqad3b0i8mGCYAhQaOstXrIdNVmYXb+QP4\\/6aDyU36G\\/gphz5is5bZO+wb9us60oKFw5fG3CO85FJrv33xYFVZDW81XmSx2aNWZFZApnF3rTjSpeK0Xw0+8WAbgmtddc49pJb+UZPbZ96oFYzSZ4KYjEHO64wfurGaWD4LTYE9nya9tqn1OEcSE05qfDrRpgs2WOR3zp6P8V6IUgdFNh\\/ipz2aUJqqUFpUlibgOMtCtWspUMRvHh4+DHnof3QEPqAHJFdJoy\\/0mDCRfaXi+Q5j8ukNulANJ7bOxNHRnEtdrm3lP1v4ObcVAZE1fUsEnm6H2HGNFZf0vUwNsyWZEtJDUrVyqcKoMEHvVGptD0H6dMdtJu5HBnvkIkWwra8\\/Gv08zel45zczFEM2DH5hd7vzpbjD+cNN8r9ppABFdntm324KS+JSYgtk7KGBgiSL9XJ0JS8Qgp18z66X01DXXtXJC7R04wlrBeg+OURzYEXl1N1LLmuGKaXiyxrCmKMTlDbagGaupkleOlW8rPoBDe1wzBE7ulSgdFu\\/sNYcoA0aS\\/+tqUjWuNwFZNEL3ffyqxpMW2Ip\\/vJwqW9HkOlHSSfCNz2+ECqP5XkcHAApepE+NK7VeGinHJEK2C6SeWBN5zEHQQdA+rBQ4aoiKlBtGAmlPuMsNn2htfGle9p9WynKd3rJNrALL+DRBz3J3NaZnMo9jcK\\/BI7pHmDnIhRHO1QZ9zTe6fBgEwJoBmWp+95E+474zBIwaFeGBDijwR1lah4GIiDm0bFz6wA3a2fi0GqMBRS0LYWRTqASDJvHi0tT5HwfvVhGnc\\/6u0rJIYqo0stChBJeT4Qv3OA0TuZqEX3fg+y8E6JRsYB74xYWO8zOWWA6KuvkCgWITK4bTzF693AYf84n8y5f8pf+yJMTxxEJ3WQ6EXen1d0h71FNTKrbMEl86p6AMzc6mAyXScCtqRn0ixlR7dNEcQxvlrf6dqzuOVZ0yvI+PNi3bsE2qRRANE1HEmq17F40IHF64NH84KgT15UBhLWiXMKs\\/re9wO\\/OT48SabPkE2zn01aXego+TQJbtNCUtrj67vMsOgB5IGn5gUI4jKrOkKsVI0OTc9GobcA\\/OlK6uOns\\/Ka+R3RuwEC5c0xZ6wcsN+Q4gQVlOaRpVRPVhh1iyR0mQViQTBUCDO\\/tETVnkzgRNb3G2tkaOM4MPTc94Z67lpCwbuUcFkITTRbPdHs8KyGi4ZPXrWjtdwZDlK4+3NXb5OFnVFOBsbasDUJiz2WDVSU\\/BZNXzkdd8lgzT3bQIcV8CtqXuuSmKe7+cWHjqDTJVqkWrPnR6bFovEsWmCPzDU4xXJC2ZNeexwkpqucSu75IZmQcDghV2ciNtvgzGttEAKKxxay0LGHPvO7QQ5cpAkgpXP3rhKBmNrN6+rsXbM\\/q9+sfXGE636wvwF2jhk++lQRy1dNX8oBxL9WG+rfSzQrkan+tyGbZSFyGjKQ\\/LygSYPP6QzhPuMN+ALynxAdBIljrcNIFEjsEjQUYU7GW\\/d66OmwlcSfwGR8BdZ4gNTPzPl9HTIEDHES8OP6ycak7pl043sQlJk03+x6mnadbZXsPNvrsMHLAs2Ri8PerN5qKKjTB6skf4xcp1PA9gqd+WI5OkBQoyW\\/Nm4cTqiUsbgOLGeFEoeB+hjOEAV9mKGivHr7\\/qdjC42vnrYHpBGKfb8pBrQjiincTMI8Fvs0vX8VQMQB6jToUe1i5i2tDga7KttXLCzQTvA7AuazxV4fiz9mGXiNUQXMHySYV19bU+HCHreCzvcE7cLdqbr6dVLjJu2L1E+PWjt\\/Bj5l0VdaBpZbLtB2AxzVInoturiz0S+Y7q0QUG4wOC9Wlor6LuMjp6AYnmzqW4DDDLL3uIR9\\/LLAFhxREC+PRoIj5KGuzFnEWgi8GlxAmcmcCQDLGVnEydF\\/3q2t17h0IZCOyex5Ves9uogBmB1s9IFNMYqFEubxmY9oNHvl\\/1ytemSVb3ovsyz4SphooOzBanxTzSFvAr2\\/uS+w0ZLaUc\\/A4mYu0SrKzjeOL7wFWTl1OuZCE+nxES7ZdbDvvUSuxeRpDAv\\/Ox7PwgTgxFRQ6y+dcc5m83Ml8gfh\\/TppSTGJS3KkzYy+tBrc+ul1ZBJ0hW4AOmvITB5aXk5KInHcRaMg\\/Q7oIkIj0rjOjZjQuAAwzqI7XRQdf7kDWbBi6SXlMKxbTlSrPqdUC6W9yeXtDMC4MJSlgQ7hKD9KyyBQqVPoH4ByHERP7mf5\\/18bhWCF4X1baBLO03+GUYlI\\/7yq\\/nUxpmJQ0TaVZqYKVS9tKz97+ou6vX3h4MaBVIin4Kuc+knXOqPWX05qcgd5sQ0w+J4fm4Rq\\/V5jycXpQ3HMlTP3HnaY3zWvqsfrPu8dnuDVBx+CgBrE1HTFv6ju\\/SXrFiHnnXnaeDxb6qofEfM6jakkMckYEaF3s7zhc54U8g1QrgEa2mhwb5pR5ImnjNHP4dGVSm3MOnnIcDaHGbZnqvy4dpXRgeaCbI47Z7gOP0h4Bv+EEic7s4AR0ePVq7SSNBSOLnXi5k5WPK4JQob3bOSXjOEDbZh546Bqv\\/m6xLm3TB5g17JomXRP5z6D+yJi2HCKNiXsKVWzTe3j8ppfFdxHIE4nJ3dOogWWHYpVjOzSnL8IeIc9o6mDM6crkn7RUetFs9SPq5ds6UXFJsyTbME5\\/HbPRL6MA\\/l469ITwrG7DpaaQj1X4f0Z4139wTTCQq3gK4NDg+i8xxCrUeKZKz20SpvR8l7adyntWGvk0n+r0CXGtHYsoXvkEJMkpfIQiVZOSKlJgPJj8xTqnU7CEz08hkMyV41XX3ThxZdx\\/X1WJ1Mi5MfP70Kzm0cwoxyxVSKi\\/b3GO93Y1Hz7NDx\\/72BAv1jNjwLj3mBb0o3uVFzTXP9ddq+ipIquZ62QekM67TYrCJiJdv4FjML+TSDeuL0i5vCr8LL3gHQtjpe9lDwa5T0Wzq0wJ4Ny1nWR5nrwSi4yCv9UcIuJBYsaHLv\\/AH1in3lv6jBtMCw\\/0unkfanueiZYZaLJJS9CvtJga0TzJDMwflaI3yk7gYw2VsVmYbpPPEZLDTli56cQ9VMEYvSn1YiKQE9plaeP4IdVMXrnT2g1e9jIU2OH\\/4V1GTvE0qRmOKo+AFOFUovF3LRdR0ZWNNI3GuUkrxlyz0\\/66LtK0jxVapQ+RDFZRCTgV\\/TpMwO3zb4VG53GgKlK\\/rVisfTa341fCZy8pKhTO600FGjsLrSUcvQ9rsVBG05frQ0wvb\\/\\/7RjhIgMNvQ3JAKV\\/h2rCkv9vLEwPH074+brfbWw7NmsA7gG5l1ikOciJsVmxDEf\\/todUFWWzVm\\/dEoTCYYKiL1KvOT6RQ86ot87dk3Y9KFCB6BsJfKtcDEzy4blBc8n7NVGkQlOYDuIY8lNin7fKvKmukVuTDmvhI7Lirs2FWrkFQOx1L8MOq61MYZDDYf0Ekxv6FW2C6nz55Sn9AzJj2LvwgP9vMFFNCPpf8BUAnrrAA0WA1LghJrzRWKyz+5bncSGRMzLOs5Y\\/yVqwwgR4z4xvczg42rrX0mhOguF10D\\/TVLNwmFTgned+JQaNo9eeg1SZD8ZQxHx6RW7pXVSUTRwOR8HbyHlxyjuByl3Pw57HP6ur\\/KnaaDzMO7Q\\/VvsvI0XX7hfQybJU7LoXjtET0e4Q6J8lUWuEq+kqoSaJQ4GUU7gs3YJ8vsQASQmeUg+UKHhXR90zHfOX2q5cPV7tc28mAcRn9z5TXLHy3WYTFlkj\\/GXpvMlBgv4ikFWFxyHFmobmie5rIE2\\/7udGvlMatWql8FpR146uBJ+auFiyXOI8mEzvJK7ncsQGniXQdCAnuC2iwqCMICsC8gxgCysxyvuKcn8XErKGyPzEkz3E+P1Om36\\/yvYFl5xBrr7I6cBtdVJZZKRKGVcpE368xoRigBObOBhMHAmxS9R9mG79QlSV3Q6JHH6IwH\\/WwlBHAADEpP9MrKkDrzf1KkcvVlp5Y5ZY+pXhElLkyBaUjCoi+mMPNTqXB\\/TCakieej5tF+WKpm6W9y452RB9tObz+1EwW\\/fJrDii9OkLdwCH7JU0DEFQc1Psie8I5b4x7RtS+rszpJGgsY5g8IHYNwnyyoVN\\/lYfxdKISYq\\/AP2gSYb5D5QReh4qgAyDrIQYqCIwDA11u8Ffs4CGfv1ba2380z11fh09smCpOujmvJeUrvybmWqcaIsTfCLYPovmIPiRTLIaiexl6euaZYbU1YXduXwMELquZ7UMt0gOtugpscVdtk+IJ2KWOrLsjIiayY292DLg3vVKNvfC\\/7Cb0HGv\\/GlIA1+emZxe0fmY9ucKs70Qvml+aU2YdYsE+8\\/TsnXzpMqgy6Krrc5XeFufKNuuX8eqV2VCT1ybpXUd3yELsS9TbmS69RPpcxIEGzeJ8\\/WeN8kCrjx0hbcHd1pMNVH27w\\/OfW8lNdgvI0JVk0\\/fMiNnoVrtqrsR9JVWUbcvqKBU8Mv398iSuu58S6hyoHPy64y8vxX388FREMIGjoGbYdiwNy8jctU4Cm6\\/wxHWnvJoqQ\\/PwPyV4d\\/NI+rh2QFvOgn1pEUHJ79RRaR+aJXgy9xkXezBXNqepGkQDQ1gAm+C6Otjf8dJ7ZGXa9TJy2vwHqtEmO3XECWbiyU\\/IGrCKs+RBNDHLLGKSXj7mY1+8syFNGJaa3+8Duwdlg+ZWM4K14pmsvNwNeafzKVKMmt51ubUqobvDh04xm8toDU5vr5RbMYtl7zPp0IlWIqyyJiH7pRsTNlaegkTUcCEsPNXmTiQzcNSu2eHU90PQUPQp5ZFvZFr7J8dPyHr7Dr+n195ke5IP+P8xm0V8eUy53QnRF+I+W69Dwn0HiU4kfl29GVIcphZg\\/tlRXJTSST9bEmDxzfXbk75uqWdt1ujLZQuwWgwfeA0+5mRvdyo7ZCibYM8lK8blNoDlVIOSNjffqfwRdUlKPWWZaJ6ILV\\/vVXFKj2tk0HLA4V71B37VBgTG1A5N61OYavu2PndUDu\\/S9y1uK0DvMIdJgG\\/GxwsvYXq79K2v3p4isJWdV9oNgpOw2spKUj1POGSa02hkKetVg43vnWdgkU44z6cZaCOrvKjidMJhFNPg2KCUAzfppHT1M7jIVBF1ai28enIKoIoqbUm03Zbe81iIhpJloPIxWq+Rjgomu+xV5zBh95Kdly7b7GDP1VBU3BP16hMOCCtZBShPOYwAgHnyfi14IsDGIw3tshJYspU7\\/iTwFQiACR0Uqg0njFQQ3dmPvLhFfLfTol+jo9YQ98bvijMYCbEsPODhQlXXme6PEVYZLRFIE9EGHW4bugezC94aXV52ct0n9ke34WJ9ROPnGEipxp0HHWhbSbFcndEcgNbXlX0STWgofcuxwqiyJVYaYjd0zb\\/DkruJCK0GrB0SQmrnbE\\/GeT6zm6BkDuWCiPXIG6tZiK2BbTU4EI+OQfEjy9GACC4J850ho6d4P8yFFGC8CE5YyhskjxA3g\\/M4l6gNxIhVlqmjNM7IR8GP\\/sf1Kb+oa3qoOCkAFs7cG8na8VVS\\/3EYPnPLTUIvy3SiLwjkZGu86O\\/UH9nmQrX2bLNowp6mhVZ40E2mKji9OiwCry7SSkTahD\\/imlU5TeZcCdhNyATv4\\/5KhpTdS9CitR\\/77B8fmV+9HvGFfoHVIeUwA+ikDO+XUKqb3hgeZVY8Bdw9hb+D3WFdcbaBpB0Gd69NINrrt1tFNB81O7LjnRevlYvKmT4JTOl0U1QlTktnNPDltqxsSn4+KBZv5EOMaKLUuImazOhT4MPYZHTrKB7XHQuv\\/na67Nla2CPpw+iG4Woz+0mZrsnhiHa2X6wBBRhJLYeZyPHUPBKT2re8fWTtiJk74mulAfrF+6PGEenJLRg4QSHxYOPT1N1eNYPUrs\\/\\/hgfRovGSCouG00RyS\\/UV8PrzsabfmlDKePD46O1UX5h+77IrLSeuLriyIitqUtTxwlUwpmvZKpo8oaYrZt1AJw\\/37fs6KF+9is6ppw+SVJ6zL3oQToHMckT3Ywe1b9muB6weFd1rQL14Xs0mg71yDbucu27VE9+Q5SLCGZ383sQfwJJwohdwzCrm2Xhx7YLVkFEPiCy\\/UIPuRv9fBSPKu6oyHMj7PnqOL1RcX30qreMLP9FNJas3QOCDvZUHkIUD9\\/Q52RnhFgpgxDU1M464SN+FUGbwV3WwLHo39C1kcfQl5llqrbvPyx4yOB4GepVCC6tAhLGNjf7gqf1avYApDaq8iu8KA+Wvc9aL16dUYg+aj5jCPV23BTZtADkTlitDsiHEHwJjDFrp4ZafLkkQANhrIb15kitgZa4fvFP5ucD\\/dYU6RUd7rSLg5hLK35f5HqijNYK0ObOY2ZjLynWADLcKSnZqOGxcJ5bHgx9R210Rd8Nu4uMd8T7zcZ7Ts0KAH6mLZ\\/FlKwp8wbWUYXJAx\\/pFE\\/Lr12KditfbvCZzODymkEGpvSz+\\/T7s5adxk20IufS3lYZmq8NdiQOujK+2tzjZT3r8ROgoiIqeoKunPTIN1uTteF9RmdHuyXlVw\\/isabGwCtZ4DNNlhuqwizfe+3IccGKbIPCYYVbF5JVtNgzuWiEMtcwKoFgEN7PR1UqYTODc\\/Dc\\/yWuDbCjVgDtbgNn7IL2EiW\\/Y2ChRtHwtoGRG0UwgadW37Mw1\\/AQRe3OjWKSVns6iDmBib70mOanLkZWgjZM8CP\\/qTxpsnkpw9aFIvTQTgLE7YftNjEqOPyyhzzNwRcjbvDvKPIbcgZDIH88T2YAtMYIJ3JWwUw5pkBSIMMIuGHIjedBMQBp5d4vKVmJjo814eu0+i8Q7P0e9MOhoURI8ASZeloQNaWoI0th8kGZk4zbnvLUEYsPHN8f45WZ+XllE7LjB4Muuv0+e81it2rj7IbyM4Azg+hiL3wRUiQGyRleZaVO1Bf7HOyqjdA2L7zYzilfoIFxzRhdAZysAbchnyUv6KNZI33JR78OoS0fRQVc6M8nbwaX1H7h73cFi5e7N5hbdqokTs3\\/XAHxHwMI5RN9b6bKIQAhyAD8X0qKmqOKzw2g8nxaF\\/K\\/Y76GT8Y32I6K9TcnJ37dmRdLjQVDASkcwhU\\/WYYdAKdRP+POCvbCkuzmF6fxPo7pwJ2dSLQxpT0lmVVyxUbHmmqQmSYP2o6Kdkh7jFQFny0YFEt0d7hDv4LJsBPp0BqHXTEv7lsM3vFguYE\\/6AQERkED0xsQsPgInyIz2tyhcHECxlSwvsgKPSRxGarLh3qF1BO7s1W5BJRPE40cbaqOVoVbdrlWHlSYWmqtXwnuSkxMMgvg8WoFljg0lEWSMHfSxNeImMD4uAVaDhyXi3dN1fdEQqBO2FVFPKEYK5u2+i6wlgaxwlVVKbioZdqLTgeAfgA4VoRggid4WdwMtpsWpL\\/rjOMz8S\\/V\\/\\/ae9KcZWuufI\\/YD7E0mXibo7dwJSCPCU5euZ065mdaWRAshF0dTUytCcDffVbZPtmUqlWa6RGfUEWeGVTtAh2aR+Km3a6vUx5Hot27mirXDCME5xVnvaLziNMtlmHjP2A5eKrt8sBATNnFCbe1FKxCPsUXW5Ea9uz9jzPCeWNDdckGQ8HePQ0En4BIv\\/egeB7orLGc4nRYoDO780Wqun4Mnv8phTBdsOTpE482c+7feKD7XCjtO2OxlTpXhPBSQ3JS5J1XnuICVqdiNZGEIa0pIxjV6dD4H0oNKm3PMl5nqEuiTsaUjelqQ9113wMpJ2nEs1fzmWhLuzWydeY6qgI7D4KSqdC8BHateNNNm\\/FGkxUYlStPAScvkgaKlzei0jcuJf6JWnKQ9MWt4BxG+lizxOdnWZLw91jbfQ4XZIUe102WV0XvdlcKDNVyNjgPrhQsO6SI2i+Oc\\/NrNBoByGUePsU\\/zfZUnyG8krY9PMmpp\\/xAw4vn3Dbr0gYg4s8G8cm4lXptK87KIDDgavnfBTvljpuu8\\/dlzjrIoR+riGjLYczWj9TjZeBCPCgVTXmDuxrFj6z8SF9PrFcPyH9X6q8qRG6496Wer8hoXVCedtcHLimUZRNOZ2XFTBoYEOb4l9BR3nJi9kRG8SmXtxWgy5MzVpCtPnbgfoiJ1OkW7SpyEMwdUyVVP7Ey\\/6UivTpotQCpe\\/2T4InEu6txAtAe896UQbyXSE0AlzTrsLK3EO\\/jZ8PGrmiiOx7dCzWcWkMdIObQrZYoC9dKJMzn\\/TTfS4YwKZa2F5GVMbx7rvJpmqCTw0F1SGpyN5WBrLsk1xa742mffFPJgh1ULhQKXjU7qpsDDYGqS6DT\\/gtFBgJXf7wgFWoeN4+aoIcw1p633aB9Se713+AWoIIBn0o9szqimYvvIo8H\\/igLIu6NssFdbu6VWeGdRubLUZA8t79exegZ1PRBZdI0FMCruSUTjHKY9LplccMEKlFCK09u\\/UqF7CDPp2dAwOfHEpX8a32+57S3t8bAcd3ob61B0v99ePkaeeQWpEDDyYkBgGUgW6h4YGNUh9eyCJJkMIZLH621mSelJSSsjCAcK3+mhtjkyFitnyc2pD97vqGfhUdnt+oP3G8Lwh7T+4vqr9eyoSp69O1oaSPmq2HQNQxbf\\/e4wUsMAKTUMELiHmhEUFtRBObKdNLAuo5xtUrTMx5apC\\/N3hyui4viD4EFWSYBSCsXXHV+gdL\\/xF9gMC97izFhgVMK8xB4wMyHnOfFiTz2WSIVEGR1scc7qRyHOFeCleWAUSQE+QyFGmT8DVXToXyAxW\\/PNCAqm+2Cflg32lANj1frq2A66jYoTxFiCo2gyPmsj8wYj4sP3ZDgUkj84FWJhuho7jqT3\\/AwwEh1uRV3Km\\/gf6Z+DmoR5RsMsMLTVaD8P4sXNST2QIEVc837Xh\\/ebtQ9EvUHjhehzdF+q6qIbgWR651fWQkYXIgAkS61GOedCZjT5u3sdFXx5EwLL8\\/9+6lqKFhprHsGTfEC2a+NvukljPo3Km\\/Yr7pA+4uNZgleL8+1E2RUM3MW\\/nPGh21hE8HK8LTRepD9B5fAWDwot+4vm7znm5T+WN+OYvI1Q7eeu063mv7JZR9L2ouUklxVwLxfZ1oUlgfPi0a59C7Onc8ugOwyEVTAlLClCPUwGKdDgzLW4ofqJVG0fULOvni\\/q\\/7P+SHjrCWVWXIHNaRD87S2DIgqtIIgFI9aT7loFxYtrHueL3ZUoMECZcQmww91a+QqF\\/DBTZ3MGXHy+7iw3DrkrVSc77jYmtZw9Tem4iCp93H6i3dGIwzrhTn5yoeImOWbiNOpi\\/fBt3Ij9zP+KFt6OEViukMN81GA68D3GC6jqtIGpmxlb8FFP0cowKZ5li8iuxFLwffMd\\/bjrC0JNEjSuEL24c0XiWwOt88ixC5A721isIWUvNH0J6vjdPX2xcpvRX1LJI2ubu5jxK6plIEc1IAPPD3gqGlVUXZnx8UBfZpOz3uZk3WifszBOxduCKEN01Uh2bckyGO49avd9Dg7IANslzl32WovEei0rFQX2K09buUC00ojqji8heROl5szYBFXgGhGK+3p1i1KXNtzALomJ5esdKc\\/882QU1rrHj6HoQxG3pnkxotX32BJ0had1e4c4uhhZtfdJpYaTswd6bNopR4PlDdvVSvlkvcgiDhCO+G5zK+zfivLCa8zkmL1Y8BM7bWq0L0U57f1LSdr79oA5pitISe6t\\/YpjKsOsJjKUqyUQBuiGFEQAN\\/FND\\/8oaMgReDvRTb0xNn1ohQdZxkeckrqiOlsV7Lb2kKsdX9ONkkPL44yOBI5fb52dPOoPSXKHT42KM\\/kUFXZL6tv7w7Ltmmk868Wj1qKGU1rG58fV9SVIPnn1deAJDafuTTTbFheHCMg1LCKdQJC3QIQnV1oa8bNU9hlX06m6WyRn6lACmi3sQHAJqp9StBryPtzYQSO6G3FGI9UCYY+qJq564THSQKPoNnKhkVZ+LD0nHCZ1Mck8TYX40USnE1z21rg1yKx982Y9djngApHjALReyVmzrQttenDRjNtk5Zp7OghAgJnHS4zdYGRNvXEbiwBPw2apAeoX3louUWwez3aMdOm+7iBh9ZAoQzbrTI3FSpEMzTc2VpbtBNe0DWnTx6g5pB2TPjPStqKh1w8I7L8bQB5mW6tX7rUT7YJ2ZSKHyPZJULZQ1Et9yj0gHWTNkiuCwvWMjPCQCyg+DoGQN4m1CKvnBPgD0UYEI4N9+G1PB3Ph3bIIt+idSCnnPrt3fkabD41SBz85cjNzCiZj8plbq+vjwwnapyhIUFriGu3oh9bU6+2VGEKRyxlDFj6W8dw1FugHTvdVVr2IdZmCeL5Q900rB4\\/2U5SuE9Z6SdCwxB24\\/rLT0MDxM7hoXLBWt5Xnb9Y6dtwovu+lTInloAscwR6wM8iin3J8hNMXXTmxGK6qtTHcNdhxH0UZcF9vuZR7N+fsWUUDOHeZXZ\\/E1qylfiRQtNwck7v9EVmfgn14O5mI9wskhuIUDYI793cVtsLSAheYrHpLv4txep69YZjq7KaFdzfnZjcCZx+fqRTgIROVjdNg\\/cQIMJnTBJcNKweiRF2hB7oilNSFQk4NH6YkdVin8C0RtLxcE9OriJgia4Cke0DhbTnhRvlZY2lPnpFqbtNxUxB\\/JaDlrtZdehStiv4R96f+4PKwbDsZ6\\/y6FUvD6wSsRVazwH+jY+UTy7sEmH2OdXvuby8Yf97xKw56TTeV6UgPK9ULi1P9cFweAFS\\/lHZRiZZIVPBS3+5lhX2WjcY6HVFPY+88jnx6DKSnNm0tMd\\/TIBvTV1Eh6lC\\/LJZNzDX1LHh5qGv1U8fnG5F1h9J9EIgqZyDGJXAL5WYjCDBaIfNxaZ5wHNkCZNwA7w3LUVBqSu6MqpQDSw9v5K5\\/dQW7YB1ZwTaDabrB4k9I3nKiCcj\\/L6DBEPEln6KY3XUe7PwZYcfsmFayQGyeqqPvhStCHpc0IaD9YoEFIUAoyXTitn0jdr9laIfgHdfgaW1yPuMW96PtHarXuxrbWXKqRLFak2sB+jTDZJST9skji87trjlyenCazoZYg1GbKaFTq0FXo3C64l5ll+dyZ24kswdBQ7Pk8qOd52c1qNiRIjt3B1NV5d3\\/GkkDlI+oCy8Y0WE6i+eHRSBWBKWnVEOLoDYg\\/N1drxLJwkOw5\\/dnsdzkVQW+w4caf9\\/TDkTNLDDP9AO6AxarJuRpHlGI0e5AYgfwRgjdbeylp4jWw573vhVjbYLRyoCotIkZODdCgXdxV2H9ldNv9PVWLQxrpi5\\/oMyJL7ItvEduRjGafy5w3GiOm+7Bo700wg5zfa\\/YkIiljUk0h5Drb2gCSVehxfkdaKOSF9jZhSQsv\\/8O9ftUsIS1aQWROkrhsFXEgf2YTNstLTmycVy1Sbj5CSvLLbP0LOYtWsFbakNE2z\\/GeN+B0Hjti+FtnQTAi3toR5\\/meRjHYhl1IpiflJWvkznQ1BAeINscPHnhzc3LC\\/DwK\\/wts6XM1TCJgD71FUucJcWH+1njNhDbFggHUymisv4HQJ7LCDVbS09hC9vLF8pkDza4c\\/G71nms9hriz5NVB9hfFOnSZk0rFOTXrd35qgHUtuXZHt1ZMMhRr47iti0smDMkL94FiPhAGEA2Uh2DAcdS0fbjl2BEL0K7NXZqN+Vrxz+Hgf7p5TL+9+WrqGRmlkPjvnyC0A9wD3LSAj3vN8KtUTR9zC1C8FHzoycOceVsWiR8OJyNHQ7M\\/j+dn7hhkTHx8Eb6hIcvd0zeNdlbUBvgaDt3s+xRCRoPn8UyMnuY5gSl61UKvTQQYGUcZ35rtxqOy5R9uKqdwXIiSafVByBt9+LWjpUO59QKbP\\/lt7\\/x2a+7jEWZRa5lgxJ58DHiKOz6QWBl\\/BkdlFTfnEa9PI\\/JUpomobqZnWEFBTLBQtW5yIw62bAahaX2E3wTd6+0ZcXjVKU5aUcy9lG8AI2otpIzxAI3Ls9R500QDfoRMDP822yO9xFilOI9JX6sQiFXuKDjUbFTQKxYrnYaWqlb4RhWzZaUNebAWZKH43pH2OTUNuM0EXRgln\\/w6A8XDJsx881IQQtXHbN7sIwb3aVA7eINrgmb41K6VpneGmO2zZRRq+tTDjv6VHmsgIVHP84\\/pXpNn3nnJkY3MNMaKBtGKd\\/96gxpF1jyOOM6Lu\\/26AJWZxbsR\\/8VlwL2eKrOJqgpUlRoYVJKJDn5IKps166Xr3zxXo3xsQPU+LHlpbbNIxtyxgL7bJZEvc9R9h6gt4MM\\/qK3lpiZm98fMmeKhW37XYfEfnkyxxls3s2HLdutcNTD2RG\\/jweY4lQu4oB9fvqrFrn5j5V84hz7QoXT4aYNfcmVSXoOA4zXJQzW7wPzdVAR9jBTeMNjzW5RZGIvhHv110qkKo54OwpmcDKDJZv41wTzvt5e2sh51jUCTb1g0incz8DKCREYTruJ97xcDK3piWwMapOAdrhTB\\/99w\\/TgfksTMqHjr+CJAzRy81ABJyLO\\/4ajphxUPbWsSQH6YVpK0H9IS3ndkYuWmT6mDfQb\\/d5aR6usCcmfAati5n9WMwECIsl4nZgnFgJM94FDChrzgSELqxKzViRp\\/Q\\/CZ\\/9nIs5ixf18JWx+7oGXMLkWm2nULqwGyjaA\\/z3303lhEtZLDAOYWD\\/ccdONgtErtp63LZBJvONttkw2WQRT808njgjAkAth1yxHK1MtoI2qT9039o6FMBjZGFhL1ajqbiH8\\/RqZKxbMn9pPOzeWjU7nvdMVmCT94MIP3Re63V5J0OXlJNMHFfUxqUKJWfnX+SOgq4XOdzSHzko1f5Dn54eQJYWDIwKRIv3Tm9FNjCJ0ua+8Y52qA4JYmp9VeylhAZkSwKfk2oT\\/aE2W9Mf9R+x0tC9K+ZARg\\/5DjdZNMyOkgS\\/d27SDkNW\\/oWKw+RajOWtuucUC+d+nxY8XBwlJcH7JWgvvkcwyIL9CdjhOTy52tG1tLktCjQtVDso54RN4TVOyLToB3aKsWmA5r7jciDe4ceImls\\/dRODORflUEQZmV1KGCHVKctTptPJR7\\/zyzlNl2F80K5My26dR+Z0L5ESI8a6cYsIM3r1SO9mIOBbIkE3Evaf4q5vXxQNq4Lt2tP9vHDiQXQqjY2SncnCpREqrT2RQzuT2uZ\\/iJHlPzWQyRQljttUtfUWVyshwSxKo0w3DpY+4ARWqCekLMt+TG5DW4f8UKrVR6w5HyHYg+yAui6OO6g8mKuorHUFnGFkOgiNYHy1sRpzjGWe6\\/z5Wq3xNsdYtvDqO5SD4APulI27mnzMTpeBf6FWCvaq3lWfIxp75C6AstpUjsSNqYgznrEUkLyJvRA99Ls11LHu4RtwQSvzXCiXRoqe95klPb25Q5I6yYOtbvJBzN\\/2OLM54MycKSAuZmviTqRqZT12dqaR8Fr\\/WCb4R+Wd1sDSydgVsvRFlbSHhziUy6+7vt8vQIBmw4ordqXyf8gWyjlbi3blS3kEWH1ZPsAqOIcq8acs6F9uFR9HAOwMcW2d\\/bfHGksgUxbHQA3SAyVHt2q98Wtr0pkqi15CYonUsbjONIcqH38ZoXjil5V1RdAMNV3VlrUYoXXDSRN9NQn21kyLHFnbg3vY1GHZ\\/zirEoV7klGA6MCvEpIEefN9f3AQZtxAB2VhvWSUiKu19XmVA8OrVw\\/zSCtaDmM3u20IX+wJQEwujlEGRsL2KqlkKHw39606wmf2tmnV\\/I69FvWMQ+hBxaEeyT4n1tAstoCA9Ud3oYHwYTYVb1Lj4GY0JqC5iIGOk36bc3qt2teE3X0Hrvj7ZcSzFnko9661wmTMgt5l8mb2MRCVbK\\/hmueV4SJjo66DQFXGLhuDElWpJCAe7Ttna4wzVVitPe5zVhbK7CazRWQTG6ckCv1hz0vnd7Az4tcfUofsjpqm2v6FUFTSVHPA3bznwfcvN\\/\\/8Kyj\\/uuF32+Zfn4mCAd+iAxphFkZtFo1tHmTDzUrK\\/FS\\/ORfeIqVRu9+fnCUMHqsb9Cof\\/LUL3oJle7kGC\\/CUFLEQbPAk7Pbn9M7tYWXKRNFDU9LMDZkiNfDAErmUk3sM+GgBtXR2xOarbcoEgca6fJffacPvNrhSwB\\/mIpLqc67AMovXkOhm3LkSeyCOl+rLCvoIr3PhVx8OXYeflXFhhUw\\/2I4C\\/1eUtgndjjKWQMzBoyG6gF\\/WMftlaJCsBoNy4JxXYhurC8LaF+guDmh86qsqmuPr6YKtYhNRrYW9iXizEvz59hQ6ieCDCpIGFBhlK+\\/3NNih4ePqo97bExfq\\/l42Idi5js34IHbc\\/yXRLDBnFuH5QdCkemsOv\\/XOMF830cZ1OgfH1QiW+O1Kr7ixN+UkztFO5UiukeE0ZIa6buEkx7Z2YcAsZvhRqakiD0CUPjeLnZhAnkH4cGK\\/Wccd8vw6Lqcu71TuR2hWzp\\/gN6DGGS9U0\\/6Z250H1lZZOVexDg1Tpq1YRs1EEyH360ORqlDv6z4mkVGJrjVF4dZXwJAe1OIjtjLvQoHeDK3776lVocmY58g1bg2e5PGgEqKniHPAppHg3nJ58\\/I9nIByJ6NDgToma+tKIuTTmEvvYIRuUNMVBQEDI9ldtKYDjKvbCcjzwHmIlPPGfxnmvQnwEpyV18QdL6+guMuYaZ3SdMbp8DF59chUK2U+YuNrBD2bupMHtY83t30uLOk39ewRQ25FDIfCm7oFXIzkoke0HIMPGHRpBVmEdnn6T5nperQP9gFGFAxFiiypIW4kwQ4YeFxN7vSzUhSWBcVOk6ioaXVfRz1laO2fgITnHZVl3mGb5aPv\\/LOevub3eTLIsWMCoC2W8Bzlgc+yehscQkaiqs1idsMF\\/pdDFuqaqR\\/XX0BGoVvfLNuxat0tBQcDtHkY\\/kxY5KPipKUYvHgQzMpWfNfdhX0hhnubRXoSQMdkhG92RBlFfX\\/o7YtE8jswwiGDMOn+q5sOnBzcwScF9G5n6mQpvFeKCxdPw048cUoHK2wcM6ZmmyxvIUO9q\\/Xp6NrPAUuEpCV30Kdj\\/SP7w+EC9O\\/t1p6mMcQl81u4tfxGFIxuBcT6MnV0ce6fR1SIR\\/zbiqxdFZ1rBQOR30cDVCGqZMhrgplbu82lWrmlrRrl4+DhUDcGknnfwY9w2wotRxG+SGvWvqwZfNGvvwBebSDTHtzatknHQLPzZtzp1J\\/e2lkPZuGSUcPHWRaXI22YQqb+XgPungGzyEIqF9OA7Jnxd4yqq7wrZkoOOWaKHrinZHIs6gGFJVqjjb+2dQMfFj0LCrEWfYcq3MXbMmklhHxDQZhGAxvhyhPwxk2z8ncBZNYfh9m0RuFdFrGUq\\/nv2OzZVn51bCng2QLa9pbJ32avT3q9IVGYcbIBoruGdQwXYfn8LkHJTgyKFufqeFaEJPCg5qS3fVqZQ2ec8V4od9DoB8BvzWaeXbG8PzkLawvilURVm+h0NzD7OXw6w88aHkuo3+OSnuSwBwqzkgdcmx0QuKPmlSuQCd74cts4E\\/viLS4rxRpATl+5HxLHZKXUt64gqwvSeAXD30EsPMA4qVMam+TbK7XfxCnBMGzBLNGbeHSGAuwjc46m6FFUiqI88g8KnHQFSVqsrbA8pXS+25ZMBQXxO1RxIa2nVUWP9dHUEZRse8jOAYTvwr9ffznz1aRi4\\/+UD0ZSJgng1ftswu+XOWmFBRZDyBM8hKweeXIEuaf2e7USPTAMn\\/utKaGSZ15BbkM4o7X4ZSxLgazzBH+myADhB2pIy8n4pcZ3mNuAsFUmWzLNzYZVmX6m+f5o3oyw43gMBGDMWqJ4M\\/krdJK7wJ1u\\/W5bugNERpB6mLtnbA6wIYCic18z0IzCGctzJMzqRxRtWTOvQFj4lLEilA8BMCu6Ho6oBHGzdeARXNq0eJcjSm9e8uxaUUVI03Viq5vbp12hehMuBgPsRRN279ZjT61Bxeu\\/NgYN4mgMSKYA2ez3nPoQSSN\\/dmXbrrgMU1cWeACSwyKmShed7CkbmIdzpMLuU2FIUubSPUQS6mvEE5PYL5ep9EVbQJjUTGq9cCbSjDWcpdQiV3Xlalm4Dyfwq9onsJT4qFtR4dDPOeLw9C7Yd6xoPeL+uGg2bk1v+1bl0esPz+v+KjROZ0ZJ7nPLKgcow6n7Qa++tAM15LQgRuMAfZZ7TQT1+GbRB5EMciW6Ap57wZ7QIo+6d4nA3f97CZy1yL9+fNTy\\/w3xeK0mh4p5sH\\/3JhH8j3UC4PDEY1f1WwW5aqu+zYTdV3O5JtkRckoNJyWrZVEnN8WnHIWs0H+7Akv8aqybDs3EfjFpeF2luVpazjHoE+xJeL+cs8XAD2zamKCcxj3duTYHT06Cu8IfKWIgVwmIgAx\\/5Bg09xrwRAnxIDNIHlrTpSwUUISkxOA2iV5\\/7BqBxi37MhqKdVzBurJWQoWDOJwPsoxX3xUtNURMPR\\/YvapzONc+bDYc7flHdYFFhu6epCQaVA8j85wQ\\/DaJtFwH00GHUmBtVJsT\\/d83VNTROXuNEwe8wgcGffGCfltGWsm7h9wlUYD2wZ\\/F\\/b7L+wToxf69VSSj7xVIevKEqksPFJeFtvguM3CCGsQh+\\/P72jpvD734DilvurM6wKu01jv9DHuVYdoqVnwy1PqZuSIEBLbrMG+Ix2NoNOjgDfV108BpNw6fjTmIYeVTkqCnbQwQ\\/gFY\\/8LOTKR5ypRfYYX\\/eVhiu5FW5\\/hyB4jMdcvWuzeXnQCjEufk6tXsjbOwzvvp9zuG89YBWhD9JRtWeHVGs15AiiOCskabgwxrh1rMIIUCsUtSmPyraNBmVKoyLKA8ClmJSjIrU7J4W9cZUz6lvjK2UEUsP1S\\/zQprQ\\/f1QZIaxRXx8umq9adDxw\\/irTQyYz96U5\\/q6p+ITA0\\/IQDqvqjUOd\\/uh+xNsNsC7TaU8abU8X9GfiZSh5e81qflWQQc4NsbX9nHoeIL3UrjjMzlhU7gSB8UTxH54Lk\\/2K01UZE4oJOGB3ZiXm5DhHpSr8rwmVbbWrWZimP4a7U2vIuhejIG1h7nPdtUEQsNNkReEo2ZWEkvb\\/a3CPdjxQ1oeDCzRMS9dsFkahAo0fHNgdx8oBmLJWKNu2LdF7I8xm5zjDAeiH7vBHe9+kvzgQ42yLR1gxmsoEuRgsi1jsTJQ9gM5OaPGL9aJ6WB3rv3qImK76JsbVdc2yXkNfRgbwDCBE7B14aT4h0i9SihiHnOSxr+2xeTHagUY1yVFOj4\\/8PO08ZY384twpqP1D8Z8b9nvPLcmvD9eMY\\/orM1F1aP\\/191f9ysAPVKnnyNiDYK\\/yhLWOPU9ZV8S+HWPoSrkMYNeZ19A9iPlTDDaIggkO1kBfK4h+hTDEBxjBtPdMWMENChH4xHfEld8cFQ4rYt9kZXHQYML2aTB3qkI+dp0HLiMKcnhMGBddYbtXay8ziEQPOxKlEMEnTm\\/PyOtmjRIZQjr0I8U08ET7EAxcyiFu4Y+84O\\/lVrjJK9nv1i0bwbk30QmXj+aAgoz2LdnzH2W0vysPC97PBdiZPbtFC6tG+BBQhKCy7mxrM\\/98m1n8zWBTaOND5XLEE+71lUFRwgcMB75BhgY8AQHZp0DOLkXA8UVAfC7zEnR4okY3a4KKQzNK4Yd63aQiDFMwnn4BnBvlTXvRlSPQV97h2TrD2QnRAb5w2E1Om\\/aPCPeygyx0XQ\\/mN+INwv2\\/Entgfh6wgAJzZ0gyu8yIB7DgbL6U8BpSekJph9cXZGSjwetbCvJqLJMcCTbNQgZRpSlQGLaQMZ3x4lBpBmYwVWrFpw6izY6eEaeAqy67IxjSoeVaOAUB9OkpNUkHkXO0YEOjWnmevGdy2+4Y\\/nVvY\\/udSaRIZd0nziNxMdAJ5oyGtKvrAkV5aV40tzbgEFMDbVCGNVRi4bQ7ZHul3M0XYz4hbtKB5UHNb\\/7ZNSQUGGqhzAZnKrdU3Vpq5K0hJzkC2b2+uyxScBwMJ4kwoJwerCfLKGBe0K5lGltfLdwIWMxbSQ5lbldh92rL8b36tSRgXv9PKDiemT1Jj5l1xpDZ3phQoOWd0q\\/82XrIOnQPt4ENYZFV\\/tT1ULKElbGYoON3ulYkhhu5jlEr02A4NnPvu5Z1\\/vKRMB2HoiOc9xCTh40NMz8ZtZxGIxNKKpSWOTP9WMv336AQhld7l2ti0O9uASRFpmhrm8CODbnSrEo3I4tyQorV0UCm+aPnNWDNyEVyGFPxeF+e6npGVizW+KRQqEuPdwZan6tVZSkuNhmnjp9hVN1XS9tnzqJozT\\/t6wZHOFr7IL+aDUICOEUTnyKNCqi5vnVjIYjQJS0O9VZFwvLvA2z9N139iBemB6s3+j01JO0xJLkz8V7sCGS0E4KLtJeZtNllZvAh54Bj0kyqxkSYj+MrzqMGpaB88jiy0Wr4DydV0LV6WYu4qrG8Hee1fqOBZNvuHjo+8mtvtCJHJP4MSHbAsw2CxTJ5LzE1usYPlggXgs6IZhS0kzxo8BWJjoB2n+dlwbgxrOhhkHHqJZDeHP\\/g6KQWiw8UWj7FoIMXFlFWsOeuYTGoYBVWwc16MBqu98rX3nLUwCrMvstcCNFt5lG5mmVDcZs\\/1M2mayIpeOCZbSSBUrZeIynttvxBNUB4A6aOnd4SbfAInoAxn\\/1gFruBHsBm33PuEaBZ\\/zCYUZxz5RASak5fWjQwP3ykHRk5YNnLrDxzCoZjlpkeO2HRcH1\\/zUy07zKZABFDiHX3J7BI9qlxxZ5ipxS99YBMQbv5AcaWAjzR0oH6sAG61DhpAgmO8u93S92vMNJttbqHzFQsLScyWzhPqlBB0sNV+tJpaI9V4hUUW0jT8CpIR0MxMg9Ca0DJ\\/fuS4EZqRHh1NDTm+6lEuu6\\/4mChEWyIJkKRcmKkJk94BcsC3mYYhuvtvvswefk329CxRAEXE1tzTAELjyh4iWMOBv27SpL5Kn0Usj3qxSRMiq6oRhqJefd6V0DiEkDTUT3o5dyvDv0A8MuXrNKVxc2kKNbx0X2q3hfRe7e0fagtHyT2l6\\/Lr0N4kyYbPVbAJsbIsg\\/bWZli22y1RUeKPLGy7AkXw8kLGjBBI3AXIxCtlvctTlbDyUqiwFHsiXCe9CWNl2TjBxEyqfdB8bvhlhN0uU1YaDjSFloHm\\/sF+mUhRCZ3VyZXYnOyyU96c\\/Z3CVSXbL\\/XTDUb+ZddxmOxdvgAFYM6osjEzqgHEN9rUaYoIrYpXJpzw9s0gPct8dgjCSzp\\/wt1ssHsAWLLJeoe0MspLXnWVEjpfS0FHzZ9G7lCzDzoW9b24JfAgANiBhTB5H0mw11sdKRf3aGzFiYNZ9Jh\\/X5OZKAReWzDBw5bNLHDK5FgZZESJTK9mTOkn\\/nRRKtpO\\/go+JdtGXXItT8cxpfE5RnkVJvS9NfbbxkJpToyHVD1oG6eHnKXybm9cw4ry\\/GzBxM13pT2IaRHdYj+RlehtlAncEJ\\/Lpl4HoXF7xExSbUmCnbmti0ZbhuzgOYEH9Ms17fAZdms6rqS03KqBXTGf+258Y9SI2DAPjZreV5zFlAVVPHmgH1O7RkhbVUhZbqel0CVGh6Z9V8uEVCEsWrrtvpDjhUXw5plCq2ZC304WyT4CXjR24yqblqcDuA3SQvfloUKFw+IZRqDw2VZpFTjSzlQkcPAPlsIxo2qlHAFW\\/gZgDm+Wv0sxY7e1cN1G\\/ZQKqg1Aa5nGFnmAY5O1GWgt+WZaNJ06yvS1kTSgst71fL3eaNth+XKRvgSd9Vt1KmCTGGFtcZyc7\\/NruZ6N0wDb85vUsnIMJ+nnFkTWgP9wHYW2AYfrwZL6SiKxsuqqmPFD1mnuRLn+48JDjmIvmGn02Cs79BJHJ37Z0Styhg9wkhA26GbypfRRBsi4zSCSdnzGXg+Wjvba745ievCKqTu+fdQIPpjqFto4zzFfGc932SN0aWTAabTCR8siSkacDTLw6AAO+gq8jy3GtOW5JNrqYgdzR\\/cqmrgLbHbTqnMEOdr27kcp5mJoMWVD+TYfaGhyaWAol9huEWh3S7XoVUKbUPr2dGmqiKw+2usXMr0sMwwPpUmgssqeV2azlMmPhP8zS3gFQf\\/Yn0T99SxYQdE2Rqa16hXoHQHB9\\/FGPqCNGAJ\\/lL9nxt8ppj3RLkndrbrGcJjRgDIxcnf+kLANdRc92vXIsERVXIu94ItnrXzcwIOZAQ41OGHNGBHgJJX1xdgQS8MOyZTGtlDIrG7GaZkpm+mSRCQxDsP7gsz60ir8TZhr2IzmuxPqiOitoK8WUJMts1MyLx1aorw83vfqqcIJxrdqlp+RaESjS3K6hXeI2ggl86SxRGGRFoPSi\\/U8gTft5oH48HFESYeq0SBSGIapu3wE1E8yoCigEkAs2kp86NZ9taJx4JdUxFFjUThU5tJoVB9BfwLyr2C7JkIrj9Wfbfudrf5QfrtNvc\\/oWUexN7yI8pAD9m4z04w0DCEfOdxJ\\/0bNc6SbitlBJEY5um\\/f94EiW02wZNLglH9ui666O8gUqOjz2z6Wu90U7fUze273LbVZJlwIs6XEpHRj\\/oAbD8s4knkECtWKfC4aEmNRLjIuP5YQxzoNrku6MY3OFxMHX1XreCIFDyDD3lV08GmYZUjndP8GWD4R0aveUZSXLV0HSEib8bSG0WujRiLz+AHbFA1d9fJE7ioAvzahnGHqfVx0EjM+9slRoRLOWQKi2wk0pyhTZbiZGQAOmhPe\\/N2BZsfuvVBnqFbxto4+cf3oywod+idetKfhD\\/3w82czTG2iieKcPTqU8CtmJuNsse8FXFLOMPcdALcpIFbJvP\\/+TuE0XbIwFsK++jQhgXslRDQ6Om\\/aLTQfL58LHB9B6qMYG5yzjcTuA80fgrA4OBfaxXt7u8ufE+CK\\/AD0LokJfvoid\\/VCtjA2+6dq1xQjah4pquyGH2yec4E9VG1SPhpQino2R0pE9GHXQaw2RWsBDo5ii7AYeoOsiN8\\/4wE9qR2cy6\\/+aQaMuZlMuYwsz2GkGZ02z1415K2GA4j8phiCAbhSs5Fou15wllWm6nLNdSjFyKS9tfK+Blx7Pfiq910vZaTSgxcvRLZ6rDnwZcEPtwrrwqQTBZYfZ6fckvPRxMZHnxMgoqO4Jn7h+f8KMbg1Rsglfd8bA0YF9hEsyQDIceGY8+mkthO41EBFGdcrZ2VQdYozsdMmVgmNS\\/td81rMK34AlZNPwwONYl1PW2kSPvlu15ZNv4F3MFrgogm8JsUslG2H8Pp1G7FvqQgrUEOZu1s31dc3gwMBZq0ORDVrf5GsPjYCrrxErU7IBygcXOWnOI+HTo5pr\\/l+GOfH+aQ4cJNs+40K1LMnJwJ7ZGgQ52DB5tonfuiH5uF5hWdVr6O7KwhXpJBvRefYol0iHkzAb2Vhi\\/L1AdmV7wO8VUkIc7Cu3ruPpEgES6dj60roVxi+3GchvtUXhaQCk260UEEnZeXp6ozU9mUaWZW1UK1zPmO+Md6aOGXIOpDmzfIzBT7x2wsvX7XOvgs9vp3HTK3IdP2rePBdVKYWZRexakMx9PfLLPrcxio1Bmui9oiIg0RMOO7QpGUt0dPOO0\\/VIaSu9RG2QcdhdJBA+Auyt6KFzvb1XJuUTYd4zFBnoSMUS5m2TUKXWvE909DJfueWhqTAVGsgPTuD0gGjNKvPrAu4OA0Cz1U8l5wPIstVjXanJCgRqEh3FBb6XvdNLLsWJ2SExiFpGnvrtO1SQZYLh3WMNheQUAoBKSD3FecaF2lSnE6NmOFdjkzenpLexSMgRgToqZrZSfv7ZKPadcCccMe8zHbDffkNhT\\/tegXKOfMogjlbueuiHRrKIR9W6wZ5prABUkjyceR4JF93QDHPu0pBCs1Po3Iya0pu52JYyqBKsHtjvjRx0Rkazv7kZyppJmFcBsGP1sBno8o\\/bgYA5ABh1zlaZVAQ0jFhro\\/cuAnvuP0EJBPJRxM86xTNw1Tn52SGzTAZvZcoA+MjCi2ckNRJ1KjL7cSh02r2I\\/OV3z3VfRkLFF5Q+DmOKB\\/3hn\\/ps8CD06E54lSzXAro+hy0s7sPQPtlSc3ZUZpNafQ2upIjRKPFnH7SzcjvhCPDirmzdxZsvWUrrWK\\/dzvzBxxT4ijOn3xSIS\\/fFAIGq3stpmiCEBIjpuVcOszCHHENfpXg8gtF2W0GBkO6+TJDOkDPEjcKiIwcx8LI8cqwLPLhey0QWJX25kKL67biOY4fqysaIBGLb05sWPaeXNACqvIC7InkzBX8\\/GHSwnOLC\\/er2\\/xtCtGAIon2e7XMf0XGnM70yU6RRLZe4HCP\\/X25FJ3bjZ1UnBXVo26d60HnUNHME6OeCT2p\\/LG70nmYZH9eKtxTuJmKu\\/r2HFDtItfajkm2jJz8hQJ2vE81ZrhFkjZuLMC1SCZY9edYqDontKRNkbPzn2F6qDyfhxg7zoH1+hgCGH8u1c3JqHH7ESZWseJV87OUg3Pug5zHQOWyaeaffSr9ldl684bTlkwbFQdoUIQbNHLQI+wxDRJGqsVa9WFWr20BOx6TvZpEnPaUZ35kcdJQE7RlI2aU02604vf2i3OmtdnwUNrkA+pR6UQmvd9\\/\\/APKlq5YVZFWwwdXZvfcXsxFRBxZ78\\/m+LxHpnYcson4pwMKx6VBSajenCLMiRnr2hc3Rd+lEk1GgipelWLF4A4vR6Kppp+0L\\/yxJrulW6UHqtJyyaUO6bWFPAh9TjG2\\/ChD49lWKjwtxHDdU\\/g19VdUkQuFuBnyATgp16UrPLl1oowydW+y8XxNqtTm\\/oDeDrYbSu2rl7v1+JsCELJB2YSFjfd6PygW1dBJdyfeNRSw2V0lRtOzi0EboVNhmTiEG9uuwPUB5JcXxIZu4+o7luqm+VWiuKbOEcVKntjM1XzA3AF3+3F7ARWAmaMobW9SK7l6hPSMpgHGA4i+iOLEFaM77CkpY9PMx2RpfCrSqYn3nXB06p9HAzzYS9SyXqukwZsyJcyAUcl4LknKNwRcKvRfeyFD8lRAAUb3cKeDI27EwmSAgdK2VUq5jtLzvfAhshPPOHL7ROrtzKmpT6qOJikty42NvsM9blOzwEaQNu5fZJJ4UYNMH3b8af+qUkxHaqh1nbN3WRYNnglpvF3EP0WsCR88ifw84SXmuZdZ\\/oquNUQ5a0w+8kABFye5+7SyOhi4Geo4T9u1vLRWMPyg8R8xKiK4zJL3Mat\\/dnipV0XQYkvXD0Fniesf1ky6E7Mqy9x4y3q2ePVMrUgy1JGvG74kWQF7T7Mv61GAJkfG5Yq\\/IqY5s6qTnvtgcwiRZRxMyUZ0lKQozLPDMMlNwuiD8gjo618E6otaix+ZJUsK1YRXNM3SE6ys5u\\/hPl9W9BRU\\/57+2\\/8MThOAUj7gUJ8OUKm8Twuil4rgSW2e40BvzLYDUU6u1lb8aOTkLM4JYL3X8D795DMRtgQO3qMmnrC\\/70CZwi4X5jV5064uKhT7wORTbmuOAm9yPwUXrNAgJF5vrn6koaHercVI78u93Ks87eAjYw7egLp0eTHv+X9lxu8bCR\\/m4+6KoRLruao3T6+jKcdfcIxUHoigG0fLfdT7ZTBUeuZQ\\/SFds\\/Raj+DqyLVHdFRlieZZ4dRa\\/GLfExeRB2z5cRKmmpi9uLzXI1153dQYaCVZy0FUVg4Yx\\/M3w\\/9ih3Itab+DYMyZEnhxSftDkaPropiOF\\/F8LhWecjJrSFJ0HHuiu2NjcOfckSdM8S08qK4Kljy5JO8xMPJzc31i69ykWadtw+WsRt3NHMtL6bO9HB1VOKsIpop7zyu\\/EU4LgH3Bz+K4GlATIbHLRiWMbyyas+mLyarBRATTPZRX7bzsxOm4Sa74Zd3MuGH0fG7HoCAmYJ4PtfW1HTeuyFI3OK8Ad2x1tgotBeH5Pe5F8yp0J21bRJZ6MWziXNwTB7hVKIYhdhuWGjGuxXhnPG8PdCC\\/WilPC+\\/9fSOLPGy5ptvfpQV4ok0\\/h6ep7MNPhGpCXuhvr9lB+VW7Mx2SMZvjLANhFnEoBfGg5a+6bjZVJ+nE\\/W0Gf4kUzqQ\\/zdHxJu0H3xKjLl6AqHGIlEzgNiqxPEN5sLfZEZ3RPm49TsWPKRuw+VdhXbb2lXcTmY\\/3gwXEh5mo85ezLJI44zCuC8yxmOB2QW2OlOSy4HpDH5Y1RqdgsoBCxAx4Y0hO4kiJvYcZ8zpr\\/nmFEfplyNhyK2iPunTdjlUobhJz+wxcbhrs0CCOzlLxVgqz5ta1E856eUE4ys8UXGEWly63VBh6dovM2Z2mFtXSum0oVMPkZc81qgAwrX57p3QStpvA9NsowSl0LsX0Y7sRh7AKdSlwWqTzzyzsVal\\/IYh6wDfDQXYVi+1dAIphbFFi5ltJ4Bbpv5UNuKyL29I14+E\\/YzUF59vQlqT0oM6YkKh22a1YwQgtHA7DmMt1t9W6pp4VQ24WqGSNTXTrOlZK\\/Ka0FJoanDXx+UaNmMaXI\\/ftOHnFsP+FHUUnKSln1xSCfUJQfUT5zuGkYCsh2SIcrwHw2OHWHtfU1bcXyADY84QXNvLXLgClqcacvXMD9ivzWWH4CeITKDnG16uUahbfmI56nVQynKvb6XoZ8FTCoeAcNpUEJ8GCSt2nllL49\\/Bh4kOD3vMKLkOcHOBugoFqW81Zc4fAmsolMP6O\\/fghyp0h49\\/74mavvyrTtvi7\\/rJLg1J8q9BypJn5tytypV1KweWTGqvEqVIVKJejuhx\\/oxp0kpVul8Fq9l8v6\\/MapInNiYN1cJ+0QYhyBHTiSn7yi4A3yynaGT5gTDmK03KSHOJIV1yaRGXrGMbLr7H42Nq0ZpJ3tQUY7KzbCmFGaN5RCg5SFZcqeHiHCjJn3ZR+0EYlNZj\\/u1Hc14mF2Rypqmed2jtCM5slXilE2gQxGtCMR+gS1yNuVESo4L+ecmN3K\\/e\\/OKAJ1IX7msZ5wXfZ1z3K8F\\/pqBFrlPu7sBD9m+YVs98jLN8pCJxVElJttS4Kvu20I6FrMjyvv2dqVVIyuxPKQ+\\/Sd6IEAGKYyPTk8U9KIK7mx9CwJWuijEXKCKH5fTPqR3Z7taZWsLd8CtNQDKrYlwqJ10vkNLzSnUzfGJKIUdNrC80mPWlthN3pYXtVVExDrjxEKGu5ljicU5N9Hhgw0kE2xKS25bQvOLXFuNMtptf6I52py+rwprgcSDUqzGYWTqFdiiz8IHLh8k0SYAJxEwNbfa42mEiZ43KOE+rUFM52mPhzsyrEI6l4CWIenJjhMBYFMcZddsXvHE8\\/g\\/SrcYypZRs5EnMznGf5W9jEeeMuGE\\/JsxcEsUprsmi+BErUvT0EhXr6VQpK\\/Y\\/f\\/HvhrnmTmpGHU2SFsJXgx+LlsLrWM5aA0OK24Ii2eqoqwgcnz1fvLTr8HfhIqy+td+9\\/7eedv6UHwoKJ+IYuxiCwBJdqx1l3t1TNj63\\/zsYidKOyos12EB\\/MwSqI3TPfCFqifY9wYbGV5+SxFNQflUwn+4pCjS\\/+wPPYF\\/aXhtvBNkbUgfsJuJ909KmZ5sCVwBtNhu4qQ+fXOtEeEFGgcv+1DJVy0p5QeryDGqjnXo7hxkiFiu9dwMlP1AR8h0HdMQw3Q5moDaLWuFGicnPx+t8iQE5C55EFwdMN1zdypnHNENx6ymzY3rYJSV343RkuomsqV3b2MoZYW1RnKsQDubXxq5XatRUYC0yvaOV+Api02pCtRSZ7F14ispC0JX5BxYGK3z9KjtZFUhjIbatwynuyS0CrrA4MiGnorgukjwx5Un8nI3H9l9wYwBAx1sJSUSi4quvM2AqAfTAlB+k5ZkVsZ5LB5wSu4vJq0MapGDmd6\\/lrrJzcOFffitjr8nCM+k2BBOv2RWjeHwbBukz4\\/t9A4Vxv8FIYai4aaWkZPvU35DBpCKxp+LfXER2U9iCr6f84zX+qH8wUqqaVgGwbBqSMR1GJz2OSJz9YhbHKC2JGDQJ9\\/zoYFg2jbUmQIrUqX8vuQt4kD1q\\/BaAhmOA+\\/b\\/bUJF+yMRglF1wix0XXXjRGDc3M4V9uhiF9LEJrRzEI3toAOot1mhEbAIIegpPBbUeWBoeYl58MM+P4GESfYd0ktY0pIM01SGZ0hCbagTp8ry8DjE3lwDJxaU66w6TGmx\\/7Hyebo3rDSk\\/PViGTuNIOmif0+idmAYmeot1cv0fj2EP2YKeB7fVg+Zsqwm1QWI79dwuaJLeESwg8NMzF5g2b4Ln6YCJt2PphFEGiDgFCX6gQs\\/554M1kbic11UrDYxNuUzc+7k9wixFz+VHJF5SAQeHe2xFD9pm\\/JAA4CxEnPXzkPfOu3ZftU6Oy21+MUyTJ4MnjwHIcayE0MZ\\/aL1NU7lCJOtxdsvXsshmgTjC+0zYr5kWV+ItaI7TZEVTDo4u92YrlN7\\/yinivHw+ujgy9gsMPWpQGcdoQ+vltmeO7gk5PSpTVZopBMztpSaRcT+8W69R4+UkMlwwMay8v8lAk+MfQ8unOAxIzhYUcqQTlV6HGs8wxMGu4MuQBfKt3Btc4I3DoBTlPKhiL9TbcnfgYnIVWaWZ9ralyi2EwpYYsin8EXlWYB6b\\/nadxj6bQoAW3hrvPX5ltgds1i3aGqAFsvOjeDxRY9jVGYqUNV6E2mdEqiJD+wmVhIrRlfPshu8vTB9\\/4Unw5XC9MytriRjyKByq+B7eTshGm8AgOSlYslA2oert9CJFoDXyPQmCuIRqanV7WbiMrln5+PrhtnZ1OD2FUJQYvr+F0n7jZutA0V89odZTv7GYKbaM8i8FYQv6\\/MZDmfJq98NTK87sd38hf0vooE8\\/1SPukapawvjANZdgrIu1KBdC7dn7tK1ZxvYnLIBTUjwgQdY5uZKkF2HkfUgjcWwu3\\/UwJfEh7wDzmax\\/2hs4CiIXNzK+LAKRql7NvKiffunrzg\\/EbVPKck9o+vTKl82k9vNvn\\/uinYAZESVK6MuN8bnxVvY9INk7fvn2k42ljoNiMjahIYKlmFNB4pLHMihgnx6adR0w6Ss\\/veJnn61Qf9kKx6ZqiHJnexhQW1thvOeD12sSf+go5LDdmNOQKGpcECw5Jr0k\\/PFI2PV2NIjJVzg0sxM+itLt+gWgL3BK4+ktZ9MNm1YdZdDQJlEvyWtUrFGX3S7aprmQJe4IwFL0IJCw\\/Rny2h+kNGSCkIkLswe\\/lXvV0OAJMrdRyOxgSxPebfy0FdNmokVD\\/akSwZtciP2g91\\/R9QsAZFSTV5riSBjDMFaF4n6nqTdyTurMAbhTEiQ5D3Jz5fN5dJs7i0E4CdrDFXFU3HbdPt7qmTRh402HtyOS6n+sP0SqygxoVeASS88n7WPyVe62rBczNc8PpZKLdGPwc6NMob48I\\/7ULlhe1lGahldimr4M0I+TbyUjaJoI0eWNYXeu4xVvQK8PO4qQf0F5KBumDqP01OCVdx2VGo3YCt+fqJUNSlDfeXrUTT1VnXSQoF6HJd3J1E0bMQsvNKbns9ieDdzCvvFG2b0VswGa76ZM6fev4+T0YP5VnbnxXvu8IOrkd8MEw+gopr9UdHytNgq3vXr5lN9ezGkjk34UBxzbrBVm93UTZBsU9Id6Wgy2YTQpwWR4VmrLUJiiED\\/59UTepYwMzi7Zo96xaZ4s0ZlF5D+s6GQH88RF1c05qCuar85cLhkvkyhvXtIJQAIBWo3M4rGyjQPCU0Bi\\/Mh761oFppRLDwzXTmDLdoseqp0zT35BjjHZl8p6D7S\\/unVRF2Mbh5y3gH2Uo85GnF5bQylv3crjWSmNm1bJP2fijF6uT+sDYsdF2Q1axm19RydIR4VOXuX+983ugyNqBedu0XHofgJmCDqMsyxqSBdjqUVtGUjrWM3FL3QfvMJWeCqj1Ab\\/r8n+vM0eyZHkog+WlG\\/AU5DFqZiXjXE33g\\/JDTDD6yN3C3m6OiZYfm21tHCZrAn6fVYxHxNofxJ7OEsNesXRPwdUrGN6bl1Vl1STHQNVV8MhrTpWoiUFsAl9NQlUj3XG8xSiL3Pl0tzYz4x5zexJrdVG9DLi66OzNnE8wXHhcCxsoL0MPh935FE3hRlr2t3SUuIXvlFUcPCXEa4+uwbq+2H0EwVdl23CM5S5\\/1nEiwUODYMhbTaQ9lD82DicMLGz6Uwa90OeofEmowtmQWbVjVUqDMv24gyj8qoDu7y8W7GCbrJR7VGc73lPOJf\\/1qe1\\/i91kzrARP4XZnfNFeYOud6XyXlo8EWAWjgDGxXhSm4Rj1OxtOdie64ikYtieR68FQSI5fOK27OaRkmZmmCR74l+uBNUlpM7rXbi1rwoRE1FGkUKna5tVBE\\/yqJ1iGpUYKnL8JzjiWGOCqRXvX4HC9xKiCSLG513B1VeCyGOmbwUsOs1mvdu3cvUcY423KBiFx3z1FLEhPK6yu0Mjq9aTl+Z67jRJE7nV8R4fIUX4r2uMBYOcDMg26n3Zo+qgAL3D2ldNw+iy+kAILte6prrSMFuWXreG+ASh9QMKnJs96dXA2\\/uOI1hDcKL5RY+yJWOCGvulg8rvhF54FDxGkJ8iJDsh6+zjfkSXgtJoDcy9yQuq6LM2ncIwtJmZcb5XMz16H9pWvLvZvEA8VwDTxBmxg\\/euY5YF\\/1wa6UGjTA81RI0xDUMGcFxNqV57szOf3UQFieYt4bbqfoJOY41VF\\/sGTg9vtM4bQfozzn4KeH9qKYfgWscfUF897aam5Ej1OYn6LXsATQc5aEi1DkT9CgrCIz8k1Tnbnan1V+5zukGhbUzoIdc+XkmJ65XF2gL6zQWciJg6tfuC2i2ROtKZRHtgnRrvMG9auFIU0qQOM4F6hhi2jt62FSVYlsPtVmlcWYpKD7v67B7246+APFHtlFyxHp3bjdt6H5rgI+9BFTz+hzNJMIlGM\\/oPUQ+7jOsIQWpl3Wgv+oB7a37vTnqiu+iBbYz469pdi56f1tT3J0Jl6eiYBudyVfJPQgWOdRfYsPx0lhHtkX6sJQy+5qpRVYb1QUia6bkIVgxGntiEvmRNJCNI7VerwtcjN1PwtdkWH935wNoZq2US13K3\\/HSMH7M9MWa+cdWiJ0aE3fMLNlYM+i+HBT\\/FYtQToTrZKT11wcV+2YiGixRUsQTFsoQkTlcTxHt0G+TJd4g2gEEJRf+tpscNw6MKbWK\\/nR8wcA6as1kNWwMH9a3vAhlccdsMQi0pF0bl7PoKDSmTkrhfRoHJ9e+wmCLYkTaz+rDhKG7GjSyWTYrS2OTS46d2lQ6A6b+3OSDbnkndwAz7iAoHmYkWawT5AaORtyEZgbopOwRfhnNX9lHNedhdybImf2GQCICpvQx5Bcm9dnwm0ldZ4CoerpmInAH6b1QDPqu46n87GWm\\/ypafabNG9FCv6T2N+uZCePl7XE1YEcRvAAEyMimHqakoZlVcjr+TCpXPqcPUYMzHCigETMBnHFesqhoQ86rSJCi4ji1DztdAeQW0zoUd5YcAFDIoxS8GfPRmZPccRqkfhg3uiMYeE3SiADzGISd3KcVvJokLtRIKcY6iruOLHh5cWgOfOOp7Ex\\/14WztBpV+Mhd7kFZ4Jmk9J\\/vhybzCbqf3P21xSYT7G4P8HrfCOCYh+KqEOwM8jCivuSmvwezwgRhYPGuceswWnhmQ0cHYBrn4VmvGtwPfJjdeWgds+awiTjRysSWzJz\\/Z4i8FArcUOyIdAX\\/UWwUoFDBcYJWoO142idf5k9GOAt6J0j1LTDe1jS29xN+a7xwU5nc9YRAKkL+QOtB9Oddq+6z6iDaeEqd0mSWHMp+iDhdMb5FmxyqLvLbkc3AZyeIpPw27Eah+WygbsPG66qGX9tXW3D+qVDezoqjKQifMzz1Yjp\\/hETdq3wll5KiT93Ghy6GVhkr6tVg9QXf+edbuGLOB\\/Mwn\\/Ng8Qbxr+BHIZ2vQPCjHTEEWJMB9fo9ORGO1awrctPEDaj4Ks7o\\/rTmSKWy8vfO7U1UGCkUvr6cGC+P1f7PuELvFnJtLHXUnq3ldMO4O+f3GwR7t5cz3rqpXktXOmSXr35Ey9N8iQ6KDUoU\\/Dv6pFYObtLukwfd8nBNJjlzkpQBP2v46NTC\\/J3kTA4kipV3LGRR4PUxgILol\\/cazzO5KBiQbrkZ4rA9X97nAM\\/OgU4\\/8X5dxbQ5dkMOMkQOXks2yFfo9gWEvKHR46oVVzZDXldvnZ2ZXobTiwKAmHJHPWN7Cq1kIPxxEkWBJKLLugPVtIATsdkaedr6Tg9VT9ph7nWA451QJI5K+ItJQCiKpDPYsqyVn2JtMid2mH0ZFF6TyICuKLd4IgmVcj91FaYYdcSR\\/yFi6QPWrl62JODzVRJh+tjVjgIeBPrefipE0904UYX7eCEzYrWfMqVJiXqUmLTJmOzEXH1DSvrXT9rraoVLgEvXCUyq0x8XpFoup2Cjj69SAIM1msASYsTLDNKWnz\\/pKMD9STp3VD19x7N1xIIxekFK\\/tN\\/yrNdm5TRRVAi\\/rzDlOoE3trg7373232RQ1dir1lHZTo4o3V4q0x+7UVMZ6VVYf92hslODNWVPcFC2UAha6MO99MTwRcoQZq3DFwGOmkVzn5+RP8G7+2BEwYe1eqXagNz4d\\/JJcde4rzRKJduAVsbWcdh6cggHcA3wn9Fi9sRMDugxTK0rJZrziJhnnH7rDonD6mDlfuAX1qflkz2QVNwNFTIhgbNYJ7oD1E3b7GctSTM7IqhMRfkDpjEgmHlqchchBfA3uyb0mWeaJIRoBJd+NVqlbYOq6jwEmX9RSNjPFXcjmX0bv8lcngcoWWZwpVQmNiMrqrzCQ93fye8hBjzpLxqXBwvRIWeHCeNtn7tCgXTBV\\/A2WpRWfhs+hkjYrm9Eyuw+p+YPK9lpu65v5z2miu149PB8gq4E3YKL9wVjEK637eLulWbQCCrY4AsF2eCUWtPGGO31i2RhBPeTntUCx+d\\/ohOx6TBwVbSURqnyNYCu0coEY\\/tSWWT9\\/uzjoL91FtCVOm3VXd78R8DawV1BRC1p02vbvW9C4mfpKJb2Zxvn+wMAEJSyGFpxb\\/fBUkdpODxJLS0P6XTqfz7PQGkFQ04VnzvQXjO7hvZPPfDmAwISycC4le3llOHuko4V\\/2Ze7MhMc6F0fn4I7kcjGGUpjq7UxdpvAG\\/mnru2d8IYQT798lqTJ0rHqlknf3qztzzqUtKFvIJ2vXsg3plAHr0ocerLUe1F1hJ97c5mQL9yE89RPSTSNY0Q0L9jfKkFYRTxu5l\\/Ch3eOZORNpzkJLYpHVAK8xtYgXeSgqF289ThJQfQ5k6VkZyImzYrp2n2BciaPCOwKbP6upOFRU8wnU9f7vyznDmhkJNuLt5ai9zIB\\/3gwxpxt9z9xJyhJN8vmrOfNHRh48WQEiKlR6Z+XjUZVYTF6SnBVNS6NlDoT99s9mFfpzZ9RORh6f5JKOHO69fX7DC+v84dVO\\/RBBxWB5oExhxcKJBRrbEMTJKu9k+V\\/XTwXyUsuxNM7TGemfWBdmoSOEy3VbANtxq1ggYzf65XAefSr+zHg+tmqA2Mjgw6jT9EN1o3JIPWDs6nb3UzarcliB\\/EyZWyoA+x5XiPr1mt\\/XtCJRXhKolKyS\\/NXd0dI9zKyvt+Aug7ebH2UNrfX7LhhfJRyey5pxsFAaQkcggu1RdXbYn6Sygr5ZHljSLZmFlcJGzIU1dAtCyopmNiCWWZwBJsi\\/bmymw4K\\/liSQ\\/e79C6ulXWFeVl13+0x+UFySzMdF5EYqJ9da0kPDd\\/VYHsC+g6Jl67AY4WyloLG6r3Ib2LdhTOfU2rMuNwpvYTogHMHQ1m8WyVLklh\\/2tMZsPqj9p8w38qwsgqAHDXajVc53JYqvQAbMr6OcZPJzsfmpanrS5oj1Ry4D9jtPQnKrBt820MANbdctjHBDPZpV7+CHEOownpVsS0RloD7+BmRSFQcYzFb5VJLea1\\/GVhGEKefjOfP+Dak73ZOQCVbcdzcJ2jdEnw9aZSbAZx1WgI1LLcW53Z6gr979Y8I2TIiX7KKiC+cm84Ex+Tbp36dLHrVPA3nA6OuctCQgtd6cAQlSDUS2KfFZXwt8PEOiwL9paA3OlOnZWa8aDHTOiao9sGob4DebOfoHzvGiaks5uLzN3bpFdoiWDnaOxDLyspsCH8rxJULp1KRTR0OcMW8R05rfqCbxDtu2r22KOv8XSS3gbprNcVAscYPPvRx6Rg+1wMfJu6cvOWxM6m1EopbAVQWCyc7o3Yhqod6TUJY3OPRBG8vGXBl0VG\\/otdO\\/MkZbkbq2iolE7oLWbZQMj7I\\/cmHa7gM46p+UVN3ijeKWIbVRPic0+IHArQUCRzx0+QMkogYh578cU+hUQtjTEuniRTxe+6rN7xrU1tMo\\/w3V1wIsHrds4PLvIG5Cqop76WnzSdHN\\/2H1eXsUHssK8sJ+g24wE31kwJgum75JpatJa5JWoKWJUllw5D8QitwpMZEgn3foIFv54x+CbkZpSQo6fd916y1LkgFzuCsH9yFs6nVQ85P1YujtUQnKKsf2RF0WHAH2XeqGxKRf1Jw9vGQ1jCjW9kDB6wemmDPOfXcK+aqwIx8\\/iH1sCGCJCgoUUqjUPnxLdFr77tkbhSDQmD79ViKIggYoueD5sHpilQS1dBjfA7j8et6dVwbG1GwGfyX17rPnl81akfdGU6qCMTqaTJBtq3BU3dfbb9mfNMLdZYA6HM0IulNe+1ZtJX0JOkeg0uUm6oPK7SqYSRuFxxBut1D2WF\\/qNVXaTUwSnpZe2IoiO60mAk1ccy3uWNC53jSAzMzVxqdyGapEHtM67n1UhV1ANMm\\/IaSdCnchDSnlHnI2QqsOSwiHMkEdWegnQl8odxTuQyfU4WG3fLjCCj734oYivE5oRXK1dogN+ZUQTrkz8k8qK7rdfk9\\/vszqm0D67UfwhCsIEZBOq037O3I8pa0YbUA5k3CpMjdQdWEgvHmtgh3FxuNWV40wkTiEJuOJLCIdvIgkycbrOODwpVLI2hwGynTvjfunBymUes1UdwQ9x788+AJeTHsFK3o9spc050Aok7PyAjlI4u7ryeOZQMBdeXIPdyKW5HOdsKrduNvZ6mrgz+\\/ua3+If\\/dCqSsmWJws4K4fojHDqG8Ykz0AMO14HIhqeVbJU4Q2hnTWJCXuvX3X\\/VMbb8Ok7rvAd7Z61D+4c1ZzlESeji+RRyEKpHZj6sTfYSdnlrCATuzVajmS7XTUlXHUZZM7VG8O3TYGSvVWYlLorwhvF9X1RU8jQ3aJXUGxDBxaEUaxg\\/MZVvQNKHNv2J+JtHv0I7Qw7toxXpReidVPBrXr68XIpx\\/hAKcmuxIaHdBq90yFVdDCqIg5SimZxWPCce1xO9b93JP+4O6oFGaxCqbfaXxd5FNjSeVR2\\/5kWZY3lrwVWl+rQB+raPDleLzEX0x35S+JTokLjhq4cXif7WbQwsXbvSMQtz1Sh68CkqJRpROFk7BXDwa2seDcu5HyTmJq0W+kTeKSmNH0J5yHu0mL5+FNXnUPV8W1RV+f0WWpoAjYSvBu\\/rzEtIQVSD3ICLlhq7Qgmdxzz7G22PyQWONeAs+fzS\\/JJLWRgoCnXhGhCzlc87SeugYNhYVqtJlRqCKUV0LPHJ+ecduDDZ3nWkB5DvQSNoNk3fg8GFkzIc9+G6c85rHj8nHoAxi1HQHhQP4SowoCnTcbF52T\\/0WbpBpKuaJZHYpT569Ad3r7ksZiNwvaZ9UeoQlDQAyxxjzm+swEZyhnex0606APGEUXVdBqMvx4W9pum0pUWjsMdp14hVAJ0GxqRT0LZ7akMqD+3HCH\\/H23MBADmxUV\\/SLXNubGyxraV8Z6Gb1Qe\\/8KJA\\/owMZKJHzmI48nXLLU1dHWcXWdHS1aXfv+XbOAbA5IPHkwtHWn+kHe1pQbwMX+cipqPzWZzsjUcqnlpd7WGZLPzp9t1LXSRFbJ6mJtmAS8QZ\\/DxywCSXgRzwNoIT3M37W+TytpRKVrsseWuLo0d6EiC8Eykz8MQUNX3b6iT61zTu1Huw\\/EIO4woObgfO7TKFeDZo7q7CZj1DHAtwIzaCKIooxnSBw7dq\\/qa2zlBhuqYeaxj6HP9q74FZ5qOD6oVC+bUtHDfPVYqmWtsMsp5EJ\\/HtdMJ6SMOYkJDLSkJdVkk2trkK8IzZyUAnMuiCwLRtYzo+B\\/A6j5YX5ca5w693e\\/1Pm47JSRJEXPHED\\/f0ryta7qKfEkBrqwV0KKtl57unhvpElmCVhQ6Qp53gcoG3WbO2GPyhq8e95pTLaDrT88AMNKt6wThjU5\\/D7ooHtTbTfYBs8CVfKaVkS5YdFpdDTWN6Fh8wYxU40WUwUKcRtfNXVwausSkLN1BBTB4DqwQL1xAeYtJMGrx12VcmWSO0NneYxTJAp18KL439HCr2zvOPg2aFSjVQ5yI+sFsjtZb9Sxkhqqg99RWQKi\\/TVpEZAz0kIpfZ5LeGGDcCxKbJ1pQ1Pjd9fHHBad1gvFrF4ovi0fb74sAfNBHvYzSB8134\\/B32VYSTiZAWqfEdvCnwsCqNhngtrlyczceHqqFyNJuUhD8JM0p2YnCE\\/uRjl7HjHNNs7gLf0gRYwUp5iBlF3z4qcqX1+25sqdXuFA4n26YBQBSmaABpjxAAwwWajHbvX4\\/IJokOpgQl\\/nvjRqWy6i1Mxb0ASgEcMahLSZSitR7Lmfgcsw1LuR03j1gVHCct4OfAwRWPn24zZkF4TILws8DvqMUW270NwUJh6W414\\/g+nEM8Nh36+gAm79Vnr+iebEE48YDuf9bpAa7VRpoOVTwuq\\/m46mnwtObZF05EHt3PzG+NEdO2z9mdNsnMiwR\\/tDFp4BZxIvuaGXi0jX\\/oRZzbQ5WqMUJdNerusejtvNjZrdldncp\\/X162YsN4AYbVJr3\\/osec9HxSyZjaZXkEGgbwJlodAdoBN0qnJuk0jBCV712jJwvSs8Fi7F74+yUv1RO7dUbkUd2xqGLIAUwrk4lZIZe06sXqMEkkI+JQODOh2LngFf3BoNglH6VskdDDTcTfk992vPxiUE50fP3jMy\\/hI7f4i2gJ2FsTNWMLLwqN9YfEw4ucyItsxAHp5hCyKSWIkoda1MxSwCXCa1wYkqNy3xH+K6G7RP41pfMXlkfS7fzDjv0pXr80D30+jKXGvkSAwJHciSGeOZ+QggCaMd6TL+aAkf4cTwuM7kSSR+5EllwdkOS\\/9OpYAX0jLjfJbALLGWHocy+lmc+wtd2bgGE+lhawDNXX5XYbYTiBDxYoMrizRmhr0BeXnxyzj1PERYn+Tsu8KCOW0rh\\/rGmLLn8\\/sgq7CtY92TFX\\/3Sz9gi30S0Uo\\/Wu0HZIXiYDGS+U1CBF7vH51P0OUYUb4LaTahuTnDTuJ2dO2S4+FKCMVl20uEO7Ln4W1vPSCQyZVTEwsuBDYANRCSdDlnIML3oxVnQsaHnMacUEX2KiV\\/TND8DZduYA8mO53Bu6zkmH4gJ2ZBXnoOTsHtaSNkOUPDS6xDlseDUbUAjg52jPaN64g4O3bOAANWB5ltso4isCNMDUra+nnuHBZhGeBF6AQKum\\/+ppXjTNgPvBuHmNoT03Lf2z17I0jbXFAM7qXbf0b3oH2sL0AEAXY\\/A9I1w73IyL5WACGDny0PbiVkCwy+qtXnvXKEmDtvT4O9vu\\/zFWGUjD8HD27RTw6nqJCWZKJPGOGXaopk3LsaDhmIDCfBiC4fLF9oT0XWzcerGm6BPHV6ddb9yzRMf+OBXoc\\/7s4f35ZgaWccouGPdWRCEc9sp4B5I6Xce7hU19YeekmXkt16OtNt\\/JnhvXYhOqq019pwhiVW2WQ\\/0Fg2Ilwk6Zbm0EN7j8T4d0lfMuUC4IYekkCghxCV6kzpMgz23v5YQG+X0r0jvv190RK61nSOiFX8TMv+CKxK6mzmYTB4qz\\/WH5Wy4\\/s6Xgt36BfRskK29vgDropbfTDFCtTFp9i+vtGd8EEBTZPxZJYL+dULg8cN9bV2c3bPAGfYbsQgoGklqoXSLpDh0sSm1iiuCr1CCwkktubarnMHRwJCex8rFLEqeD2P3ytUulaiik4Nmk5RprP0do+pDZuWQl+wxpyChII1C1GKjWFouFkeJA7bX810gHpMNZCASQjXJsa61NSpJA6evNXYbdm\\/59vzbIE+vs6pUx705Q47QMuJC5Av\\/yjgS5GA83EpAu1cKiEYpQNdwpkc68UJmXW8Uth8wYuG08NGCa7XVLM1qFcT4gTS6eChU4A81E9KFFEdMaKZlbsOB5EAaFO4IVTiTmVyej+uVkvTRLht6Qy3y7FrtlhlZfYjYjmvPWOPPdpGD1XxxDdXqEheOa6lvFL7UBO75JfcEFZcGM\\/s69QtmR2RK7ikDhPuHGGfo3OXNR4RwWl4hyc4DHscE\\/uJNI\\/iiU7BVQhH2f6QFte44FZSmobkmJqIwDjwjCy9DNqn3y8BclQw2A7MweNcFRJykxcVS\\/ShUn1wUmj7FR2xSu6KAcCmahWGI19W3qtEARN4jR3a3LuGwuXXS1yn+Gyonm9uvug89quzvwIsIF2msmPUWUBRoduKe2lRmgipOK9uys+y2Kt+Usb8U5x5CJ0FFtBniO+g10v+WC+j3XhctruMMS4DeAxD+1t1ZEE+84IVEyMrmiUU8NusFMH02xUgzVhbzwIGHFv6LM8uCccX6yGe8w4YCP5FuBClKwAnVlqdZcEtXrkDuGFMAjASyqY68BgLd63xiH6sn136SUo8nUJIdpavFjCtxwTjtsuVMOtpYtLeBYOaO9teIofly5Za\\/XGlU3XE0VJOii9EnW1X+NpbF8OGfBppfiNMcd2zpjcNoAYd9mKWfMwn0q8c0+iDUu9AqLwLDO71XkMWrpxq46tII0wkQgJA80j3Q6lIf51yq7YVlIT37iJTFYBOD9LAEgIfxp7fdTcagQGlpHBkrpspJOWZBBc5cdlhVdpltbEPL1jGWZfl2SRA+j7HfQnJiI3w4llBdqehy27y3uO4i+E\\/+U7AVJiauiO\\/nDC2yzNbGdZVi3XNnGrNe9a+zJPB9nK2ERsrlW5iBeqQJJU87RZsvBsQd1SXYgq9silh3LBTHjdImUEQDWpqRMXq4\\/nCA9Wy31nkqFNX1KlOm0AeDQ81Hq57Ux9QwldjsPT\\/KCPdEKbQmj+MKfcy0ukw\\/xlnKugwJvKHMjW+BFEWSGQOU8\\/9vK3e2KXZS0voLGtO0dF9L4gUVYweKWaVwct8tmLwgis8u7ER02+LsrsbMgQnWxGth1eL0mkpa1Pj4+XrwNpAvko+u0tk\\/fpaTnniZAI69YziDvz8SFmDUZRHl3uyKdHo9arfqm7XQ6hMM+v0nQHVZB8uFcYts6T2rjYN6g0Y2RG0cVJE3wQSrt5gAa1P2eD5NEwQ7aWQ5b0\\/1CzYvbcReJwxR5NnoCOiGdEuHFGN7F08bgMTZ2i4Ypn31Vr00ycfwsfUN7ZQUsaGWwm5sIqcseNO60cJbzrvMVSuotW9pxCKCwjcgstWd++\\/7ZlZH7wvbwyxFz6qjha0E5nJziYe8wiyrLKe7f8opuXP3Cqwyl57eO\\/\\/JO4194WwbFua02+kzPTKcvfRdRuLfASQWk1ffyQxmSeOAb6McOGUpD+hYqxh\\/ZGYlAw49mNeHzZ5ZBj\\/pfendDD1TNSI5MAd5eXPc98kLWX3ZNPRfxQloZhsFmBE+xitVoJ3W2TrUIdLZX9Yoryl5OJYwVHQMJhKK+\\/5L9mAq8Q0V+4htRLgCh7dEboOkkvpFJBU0UEDEMJ8DlfjvQU\\/UdL93zNmJGOfEZ9WUyTQdnun8Vk3ViSBtkFs3trARqS4j0+jvnthhzSvLya\\/oL01ED57\\/KqIP9dSZiGqaOthrIMx+WDqTwunzTcOHLvENmj6Rk31GqAnK+1bBu78sJ6kUpRv2VCVACEfLSSAgdIRVepl0Hk2Jcwfv59A\\/eteWvLIdL0P2ZGZ0Ie0E0j8dJa8iD+s6nq9BO6QUHCyUjK2Rj80mNP9gNLvwUQYgSx1OVLLE4NFZYG7EmBgaOmI+nx3kS9YYTth9mnIPrpffRyc3r+kAs0WbaphTUiRGR87kA3rCbXD4qpIWh08k7p5SqkpZyjQRyRUGmNa1Bx01ANLibca5NIGLaJJJXNt\\/sIQjWEYYhRTuoVSDG3nmNdPOiDwYmyYO1GscxA2nMTocCp2XnqopOdDtdVAZtU1ZlRwGX36\\/ZLdUSemx7stCneCpfU5PSkglxmUnJw9Ko0bvdHpUL\\/Cz\\/gl\\/+19aGai2jJGWSuOiODAtMA1VFqAMwyuyN+Pe8bU43hHQqkpIUbIGVpA8MHaFp2lVTZgiJu+Z71NHBDR5JXiiCUinNWPq7TgWXei0hGnLbcLfhqGip7hf8+k4kHDBPrmbcKq6jQO8wGnwT2ULtyNRqHtbv63P5Q8zIKq+Ubow9zJHOr+9oYCJSCbwkzDDsi3PnoWobChUnvCwrWj7eavT\\/\\/XBhRAL\\/Ek78ooITI89G0GD62fTIfdHel54nk\\/OgoUdlJREew3Hsyg63rWPf5Pmv\\/8l0emgf6Fxb+obANWN+7sFa\\/2CcJ+f5B6LnevG85UgeObGLKmlRey8nrloZ8y22vYGwPjWIwLIVnoRMwORuLiWlMIJcPt0uxJwSlCv0MCTUV+fIcYz25sdIXTKMkya5eNSyQlg5yf4GROURwfq4qaiG8HJMJwsnJkYQ8XTq6xF6eqlrcWA0+og1YK+QvgZ79tCnCRdLJRXRt0W5DL39Yz\\/n10eK1IWt0zc3Lgq6JVB+OG\\/wGBFPYvNOa8FXeNKPaWFqbKxfmvltvXEnZh9F8W8EG2Kl8mquln32KviyByZr6ZbCsq9De3+Sezb+HrGe1CAw88sh2tpmykkgL5lEYwBSVQh18mMdoZl\\/7NPm5c78RebU0f0Lgj9viqAQURF\\/f+XCtFWTTwFViVmt64kkGL0lH4IyXx0Xgm3iRu6R+YMOVSE38ATnh1u29xCMSXsW6q4i8+R8BjQUVSJ8E5jDP8wDbLW\\/oa5wp\\/u1QIVxXL86XR68IYh60DsI5MCK\\/oymxG0qRgiFon3LNt\\/VnjDYG32dN7tD+mr6nIFVU0vhU4Jb5X91Am9sccLEXFkRhfco\\/rVT+p6\\/OPf\\/fUfNxh7X+pt+vUBarg5K3X25gIcMJdoYGRWBuvk89os1X60N4SROf+69hyeIFwdT0gPDxaJrtiSYoRWmHt\\/zXD\\/3uVYH\\/AnG2FREF3k4B4b3XV\\/It+woQZ74WA9zd\\/eV4q++3hNsTwyFTsooU8RTFCWMIxeQUR+HXCLZ\\/np6uKoT+N+gJ4G\\/D\\/me4F9QvZslteGFO2BAiWuX2TAJ70Ho3Q\\/3PyiawvbDETlU81A9n5zdIWadgXWVlfWDr4lDJCED31W4DRjRa0V2hw7jUBmvGkdM4pLhMF7aqWmOV6R\\/eYXCmkJWpRj7D1mthnz31D0AcPOrOpFejcP29vEWbI6yU9rC3QzsI0qBgCtCidB4e62l2UiPUDDHN57KEmjDqw0HpTkB3EFS9YOXb1sjYtvJS8xeNaZEev78e0kFaIWsNWT7+FF18hDESoUMOAHbQmBh+UsrKXBZwrNe0mnFMmlKVWVRdkYMsvMeYHaPt6spKqyCG+Rw9oKu6jdGFjTMOTrw4FFwt+1KNL53NzAPeqx59KkS\\/dPJ2XTFLtzJ4sGaBol\\/Dp0fZo6nNfMGJ89zarcqg0rE2cdIvFLbXFLyPpbQdVUpf9DXSSEEEsEPancdOrJMsaIk8fkRZq2+HR9HnV7cGppVHJWaVU2RZx+ia1fh0JJSbrSi1Yex7gEKKiV7ypRqHirJ4eV0bRyKvnPuRdeSAhL2SxgNAX0BJ8bJscjJvQecadrEI1C8rHdPJfT\\/rHkrsoCbrZ1oUSCpbeMI1cNrOhQrnCvZTcEWEBAQW3anabnHHLUIveHI9iC49YPG6CFiNhIB3u4DkPbCZDADdZ4Qre4wPh9yGmQ9uszTsXW8W8OZEnwsm14pL6h4MxMcM7zZjMVdBUhl1H+U8hVtibjWuoamNoj1IzQ7\\/3iO1Mwg68aboZvao0QAyhZmB3fBsNB7Jz9vjZGpw9uRdsNnLfb0M0VnmI2sHiayjHUNldnR1N8T395+hFieuJX\\/j0puFnM3soZvYDZi9srW07g8QSHBPd2YnZOsaF\\/ra3wVytHArvmIDkCuroigAapg5P9l3WQGdwuiwjkTZes4qyAocbbNZpYkUaxNlK+jS25S3ERNY4STVrlje8Giy\\/hB5iP7a1shBqoRgrbrZ3Ya3UjAQ\\/h4oqUbP2jGni6vfBsWM0swiJmdd4AyMZZkjuOjOK2P6mXiKdPGwg9ViYZGjCWKz7ae7yPAKSCUeBW7ncKVl\\/hzFWCwboffgScHPN4Ex9uxA601MCF4gFiH8AIT\\/Y1bY76Q2k\\/fSolZXLv\\/HmUsMNkyBXYxJvzvimNe0KHGO+vuJgMWdfxGEdWw6TdbpuhYgTNtBO7UxMyC9Jd\\/reN0fvnWEWzk3wtbJ\\/5XCOCHHTB9tKhL6CwT96Xnlt\\/wT+Zngb3Kod2iMV+v0Q\\/1cK8A7gQR4qRyu0w4WkSLear9qBT9ZRfHCw7zUYuuIYltfIWejccCv3cxKfwNtmusfHBmIFbD\\/7TzzFAyO1\\/4Zt3dW7w7PVcaAib24lnEWGIc\\/0\\/qf9Lcgga5CtPJxto1rh2tuftx468rzfWz\\/vMBUSz4lgknn8Cv3ov+LbLGjiMGXHDKzgEc845F9weIyBfJw\\/HepJfICWSZ3x5ZgOh+Zy2mhnJA1pkb7sDUR9SsTRiVUGyzpS+PmtqZG\\/hdrLuDPu91AiK1IuqIIiFjuIBvRfOa+6nSltAUQfFLM9kQoMkyy0B48rbZ76iLf8Bp9jw10dl78yphfS6qUGGa30GKDU3vT7UieMmfBdf05SC+uLubcG5PLqcAJuSUqIm4ddKVkSY5aHIiaNBsXiHA2bd8VTFS10XenSCAabERD4uNyvWndvXHTwMCqDfpcBKjMh5Jh+ACvCVjOeIJwf\\/8nFAyb9\\/v9pcnWURyGoQSNWje8KMIgV5EonfRhnEL+vBeBxk3Cv1OD4wtSKmAZ9tmVZoQ9CGPPoX7fmw8oj3c0F\\/4DrKFIN6grhYaaiGXT1lG8pTHnJjGI9Edp1wwrZM7rdW25dhu38OuyLsjNLhaJAaqtjIkU2PHCESKec7OrV91KFgg8tJ49MiFx9i39xn2fUKZUwEpYT5m2ov9ss2WssEthCNXxmDqUHUP4YlIJdks41qV89bY+geddVeFWdyORkRd+ve1YwKHmEt3NZzPJvH\\/QaKj6Pl3iwDcGIz5cabVr903WJa9V9Gx\\/NncglLrfsYSO3HJJectyv\\/oj4TNcnM4nzvq7ubNsQkj66\\/6SFaE0kq6Xiy++1gM9DlZbe9ISncyz6jfECyToRU7F6TXEd5sXW4lLEQxbpDfnTIS4CGGZJ9+vPEyPSWdx1s3eAU+zQqPYS+aAdCsh76s0u8sbsQq88lNo+JUl6ygzNcmTnifX39y1+ZckvKktnt6AoC7eKCCKNvP0qNzs\\/ZL6ASet\\/C+0NKSAxnDNutDr\\/Y7xeLefihgLOqh1WmH7HYHJvw25leUBlvaIjQuP8P05rcFw+WKNcECVu8SrcfFg1fBEdYzAhm9perBy6U1D8zY\\/o1uD7oQdTHHcW1pYiSziXeHf2MbU35PzfailfGD+vrPkd83hzhaJK9bWBfe6ZAUom2lnBfgCl7C6z04dpDf29PyqaKJI5PcEF2Cd68f9ebssEqJnUGKKAn2cSG58UJlAhfPN5cq5xDDwg9NqROXCeNwSPw0n7oJ\\/AdUrGoHGZ66O+69YWj0eASUwiS7vyMCiQNH+Uo+gnzWzZ6LZ2lLNTBlZNSmmEkv+EI+9+IHFxu3eK1Onh8TRwXlfLZ3XlpU0oWANefEPRaaAB9qSLQBKRxMZdIKkzirSE+hRU6Jx8yMc7qikSPFyksKvlAxbuR8SvoYrJxljA5sEfcjm3J0dHpuicBESdygubCs2NfcZGlYBScC\\/KKAia4pmk\\/4zolvt8anFQEE3+Xz4++UPMPIldIiRN5boh62qPgQJc\\/B9XZC3I984T7yyGY1gyH24+UWy5bgRl76E6UXp4KVg5C0lHvGWns8glAUrKnFgIVIbECvzDdogIZ1yNFu1it0gmPoGAztjUruL\\/3ByTEapjRNAH+arBicDz5irczUMU9e75xZ6kDAmeVCWGOhQBQllH2cf2GnCDskICNDZoaF5utrpQa+H1cqxZ1v5hlFnNI1\\/O+7+Z3QGkVnjdBFJ5gsPFpoAyccfjf58kJfUf5ZtRfa4o5\\/2jSZIT2yxkOGAUmls1bRBLr6tSBT5IMvypfyuilKFN2dj4+2wMy0Mw\\/RTNTk1zxMBlR3IJhSM4NiXQAYCqhf0mSvcsg3FbZTahOPEO+wbYGFzvxkt2ch9HpheJuNPw\\/G7Eja1r9DzLF\\/tGPP96H1rCSFiG8zUh4kIbrfYyTEjtBRGcPl5H0HCnzZt6qgDDCdSTZwvf1AU55H31UzXppUyjC\\/Vtw2C+UQakIVLeunoUYX62puxvF\\/7vlj8nOkIpnim+A\\/4wvOB5XHx6RhWWPVNYN3hePAJ4Jd0Mdq9C7QLBFLWnFIUWXWMZwrVUUE1U+yvbfRiuyOp6O3NQLupsNtB9Gg9M9Q61C+tewN1PFqP+6IIjHwSmnAYftWYY1PT5W8kltWQOrO+9uGkw6GnsFMQJuLzTfHUh6kc6nZPdkU3maPNZZGHYH+IXgZwTj++zOFw4K\\/69dVaDQwhCIzVvJucayFdowjNxPLnJAHHomLTAEoMml\\/08LPvf7srrpP3xn6Y8VJTffHpClX42z4qVaXt6q56KG+BEE0KaPFCLxwoTtkYof48xMMWjYU8nfUAclWcJQZIvdEcF7m+6Rvtb6KP2fYiZjafX4kdlupaMeFuFDOt9KhBCsmcU+Rq+pWjQzFtspdh0od0qdopYDFqqHUjweRJbFFIv9aGYI9fnCynoWi5uQ\\/10ocKIEh2qA6VSrOWjQgSAMvamjNP38h27oZDL8FH\\/3HrgJ50iMviCaj75QYJEyVS9EAQUe\\/YxbBn\\/o2QEh9fYsBvW1etldXtVPJHo6Ot88uIxGfkUzc1VHnW0O16DP2v9Ijskbkz6StY6CDSP3Y8v\\/V3tsEncM8dtxpDjrt2i0jwITabHZQWsSveZoR4InUMfWav\\/cEIAhf0h7R+jLsqVMjalfdVk8mTL7S6eIpbindKJ6kaG8EjkJBBoMokyV32c6zMdYy4e\\/MJPsHxHbGBFEEUvXHpOSz67iEk9CvLDRd5sF1Nm0LIE2QQp6lWS\\/J4xrgN1fFugo5IKUF90XpI1lAzxNAlvfRvPuYRLa1kXJYuMHekWw3acFK+Lizktki0tmHPKNHzmN+cJSJ\\/K9SDdf4XfgKQL+lU\\/wjl\\/OF3KnExNQ9PnN7ax+6PzPBgFNXTX21YxnHu7krNn4qqBhcRYOyGmxHubd8ft\\/xk4xjvQcR8b0dMJddGu7\\/Wf50mezIM1PAQhKtSSIFVbTLrsnbH17weqiGppWrVOMBvYOWGZKfPFQATzbhK3IPm9l\\/f++QuacUB+YHgAUD4xSAi+u5DT1sDOdqo7D7jMzupEb82bsEgsu4er8sn+l78cLFwKyvrBvgwuJljFLUiVJ3IuM0aodFBaIq08zCK05A+CebvABPBPWFc8fD9zg73KlGS8jkXshuCyFQUPnjAiyNUK688gQjaNXfOPwTOIpqXcsmJNuhyFKgmXFPxUZDjUFm+roHNUt2yXUnxgCEGsLqAaNyNfMRNeQdA+g3ANJDXEVMZOMYLgpPYiXrD5wQi3qILAMYhocyMTs6dC6CpV5ScG+rK71nkd8xvQdIxL9\\/3HD6fEfYe7XOete8aYu75kG0N+mlRSaaCCj7qq47ac0GgWlN29Qo8Sr7Q8HYkk4ccrX419w\\/IExaGmz6eKM7XZ6hHkaP7jjBDSL6j+QJy1cacZROLiq+vAo0qu3mOD7lioCxkNOnKLVKnRGjC1d7Gi54m2L0bQJ0Z14ptA4JeERRXXTjnSnqxPkwVMc3yPhUwuV0O\\/P7vDYUl+bO+fE0DQXF8y4xH9bZLTWlGqccZsCy6BxZA7rXxlm0Qb6PXhvFMiBM5QcyHUpgujhzN0HFtlRcx3ottovAeqDtCOhl0z2wa3Ewf07ltMTBNQ2oF1IVVDv8Tj2Efiz\\/2XfOGBb\\/Qa9XiCbPiVF1TiPl+U6v2MuztXykU+\\/IHdd5+SGW9+piWgFIwvM2keberQDcHfjEIGWCIPNMatbOCQoclIZknorjcCLBlPj3DmVyAToe+NSAaf46yfV15dzJ19kZnrbI\\/2u8ikA5sVHmAa2Q8bAEs19VhWIB9YakoKpdIdvu5gzMh\\/HkAnyhdLpSkZyz6jxUzywAshAIIfDUOApdTMWcWFKymbmShJjinSFEopOlGpZ4l3RVdbO2opyjw9mJ54Fh1\\/X2k9L157men24J9bbMm6HCxXHS7t9jp88OjramHU4VKRAr7MyoqA\\/gRJruZQAwB0HPFEoPz\\/jtS\\/7gU4bvwXgjPEgrIGaZHMvmfqUv3EDXcUuRCwjWLeQQOzmVi4ZA0n50qWn+9zx15kbe3\\/o7imGqLnGlnhJI\\/hcGanPmP9M9c5SajJqw3VHIZpyNqwGVmdEkUfm630Xykd5tCaCm9sac72OfFPHM\\/0oAxRTz57Y8DnIIfw7eHrjAdiQxDGiTYceFoIsjdOrBfe1E\\/BL65bIpJVhaWz3v9EjzSKzDsmW5Ylr9Te632FM9RSAPK48GOkjDpefbM7eCiKVryiPYofAzgYtLe2i5eLUonQ5qJMJfNdKltcu9baEKLuXT21AbuRpLc5SDU0hdiGb\\/GVRyD+QrsbYsej28uUT8\\/6\\/fVBjWWSlw0iXB8ErOlaxSdFyztJElcMS6zUQlCc\\/eMtaZlY+ZIIYAtoVTTFHwVFnwV1HqI1VX6ZA7lD3HR2ud3ycUV6ulM\\/cb+IHSKWRvZ\\/yFCqgEAkJPWZzhFxQexkxx0SDOrPsKrZkYvY0l7dDYcBju4rtpYNbmZgxSU4IRfUf+Oug2vGn8sQb8fZzRtoeJTxTP5YbrKLI8T8\\/TLmEXjJrGGYssLVek3TreNJdjIndxxe0M9b7BdTCO+lPWuCkCRj1Rdh\\/PKXFv0Pq5epSo5NFRlpJProx7vCb\\/HeQLxs2930qoJ5uh1Ia+EWBlNgpiINSx7h\\/TWgHeCY9dmpgISe0mBlCJQZASf0rKwgG40vaPubggVTe5YL1ksdGNIaWqC59A61FoxVnHL+X1i1rDOQ8v86DnkGqVoFIRmo9ZivwpeWQEU09YW97W9OSiUJ0h+I1bvXzeaIo+6fqucoC8QFYh2qConyvACATGAM3Smjf8sUXXKrVGPJ6YHKNLAtwH5OpH4TmLBfdjwDjjZWofLY4V\\/oqJd5DWEo12uVsw5Az9UYqTjVUvi4kRD2bHDrznJBPf8RtBwVdOFHYdWbkhMNeQ3rOg47GzeA9eC9M+81M+n2sfpL5hFwtQ4\\/QLKF7F+m1LTP+IXKeTcmpWL97rSpIve515o9rVaGfgR584Sh9NF48ZHJEAtQQVqwC64izVMANzvQa\\/ttLySVF58S1CHWVXObbiRcDj1FAnzwsB3NRQaKERdd9Rne6wGfAvkE0mgmHtc98m2Le8y2Xllvyvj8Ed1p+GzoXMrECIrNGw50vzQHi7cBP\\/46CMd6JAiLwhzpjCTfqcrxa8ZWIj3azwa9HSiTDHJ9NFV4Uy2WwaEIUWSHX8+43BmnU7NC4IJCXU8bl9ztbdX3xk+ONtow2bfHJP0NEvl9cJLGYPahdrNmq\\/053aF8b7u3xR5l94iHPn\\/cK5SHXGlXepaZ8AnGV47R7SRGLuq4OpIk3TC48cc1+EZrvOmNv7MLsD\\/WILj8BoKTxvfedOPau5Y9rD\\/kP0piZiS2MAVZrh30Bp55CbAKULMJuOhtWulLqFNmEt+\\/dJOTUm+0LSkiK0KlxYeb4\\/BYR7G5ImKRdZ7EWUXK5US56+xmifhyytDRhFeGsN4Q22+QyleCn173wfpEfFmxHcPGXltaJvNTCJOQMneWY9IDL+wWV0eeD0BsRjUE8pqojfLvUqv8IuGiNlxacH1Q4IRrtaQcC4XgMlYvW0fTkTyMzItA5zLt+fjFZ5wDxMlnUsr97a\\/vgLYSfHrIBhyU06p5ou8hN0IYWNPjJC3tpo6K7UFox+wuUFYbHD4blZ5GTVLxKiwFDsEwCKUjWxaBb+V1WZPXz0YlhslDadQedW6OVrbgBeoUigKMmRA5eUnwRF13EnO561U8vjtGrfuBc9jh2c74XptONA999Fs8aCqcMQpvLLevT\\/9GgqUsyCO4vftSsEYxKbYRfvHikB2jZ2tNvXiF\\/3uLYEISN\\/d8hu2yV+77KfXsyuk1LWIZfllojueXCb4bxsL61ehfprD72FNBC3CBt4mqpG5duG\\/Cm3qIZeCq32xoplh8hBnS\\/PlmB\\/+lroNlyufMwvcdNd5P4EgkrW850WMAa+HxpZowwi4h7lYh5Ne0PcsUUP1BW0Do\\/\\/3C1J5Y5GqR8qxPyaZrOQTTUZxbhTvqL2eQh5jEUd9\\/TeAG5XolcfPNKbwrhzIqle8apkcpoB9WQayE1vi+aLy1+ZEqEICO66vngYNIOjkYj9H8h\\/\\/8rVgyFZDyi9wnMZxnzOJnGsi8cWwzvOlp6GBALmP3gDFs44YgDz4H5kBR5HTHEGclAmiaw\\/uw8+Z2VUwYw3QqVizJ7sYn6EY9gzLOIK4tdX8vi3c0P0noZVJwF\\/TJI6pyQvJVgYISsbZXplr9Cy+0b3OU3jyI89NpZZZ4NIOWkZHFgJcQXUcJVbGjV4g0MSvEGFiPqwRTvTPM1VOHQEl9yALyz\\/LlnV4T2nW5fYpBMNT10PLNL\\/\\/T\\/Uo+a6Re3fesytaET33K1t9KM8nJZk6hJ0CNA73LZBSNLImxJDXyw\\/z9ViKsoMADX33V1ACcx1JRBWmDJWqg9amt38n\\/C1XOpQXoDUHonRGx8inRixsYxjRvAvvToQXwushRlhFhFJTkgvmzYzhJlC9MG42Yw1BOlh4b0FpaDJt1A6CcxTnNp2nBv9R\\/iPIbzx+MpbmpPf1bYUua62cwggsAOOp18H8Ig9oUdltLu8tIN39jnB5pO28257a42PdZuzPbbaH\\/5hDPET0a\\/HKi7jr2MgFzyK2Qx7EbrkMXc8R2O99aIfURv10lbO6jmEyHO6PgXDM\\/1GpgwxGTg08vMbQTvWpaEUjWTk8rZJ\\/G4VBAcBGa4zhu1IoHmQyMP1ULq\\/\\/IZCo1bEgyHRTOadADiZZ4ZpXevRaXxSf32lT8VPXkXOQPqaLp24f4Mj8FpkYXv2I+hUmaozs4NBz3NslzYOREa87GGn4kxKbxYZNJLF3urLmFKOPKXatyTaNGyra\\/GVLaX2alLws29nKl5sFD9Exa8TJ89UTP6W50rwQ01R\\/nYXQU8TZ7iF4oaxOjxNUzd3pA2sSwQz55lwBxyypB\\/Hvy2R+\\/8jXBINcyjhTGP8fLT+Spp\\/BFmJ8hiQq05nctmDMypvbzq1hfcfqP4EtMoln1i9aCJ3WrFrJ8uddDzAgV9clu+AMGNI6k\\/+hpWa9FaO1PJmNC51k5N02jkAATT65wGqbwRR11lS2dAKLrknvt3Qq5mP1RO0v+Xk5S5kWoP18Jrn7EG59F8olc8f7gbEdWD0kkI6FITRDmP9h+TW88AL9k5WJsNjYw5vB6pvWsXPXweEpf8VkcQHmeCVcL982YBRl7k8g103G97RtdRB1Pkfexu6gz94lxK3LxjEu3MY4Bo7IHssrFNA6myd5nb50DxUdX6KuBTN2MhA32Gw2pmm08aadFay+\\/LpXlvR6+QWUmzHoryXuJzBEOX1VxdI5EsqVGgyrtiE6Vb\\/\\/nUnxRZLDyNvsPkLu1gUURFWaBGCLmgX5h8ROCnso4o7oBbgxT8CcynP0uxM5Sp4eP\\/ABearXwtfh70Zzv10yCM1Ww4HIvhE68p0DEfgfWLNCwhaZ8ONOKGImeJEC+nEE7o+wBqYeM8irFFgm6no+NpfzIEWjvWBPkiAdMFz3FScwkEJr7L3\\/4PcPAHp3JIS2cDN0Z\\/yBwwGw4lnt9U\\/HfKpdyZ70H+kayLw0m4EQPavnpUZwi0HQ6AgOMRh\\/4GHcfILKng4uutRkwXS92DJEXX1J5imju7xPvWrU+MDlTbF4cxWDb3qBXYyjEOy4AaJkzlhFR7078b2NEPan5lONoLwJvwiMGNxLecAHT53Nw7LgSBjjQFguMjlkHk3FxPlKIyw24\\/6l9SzcVaFSzib1w4TdLSmzjPWIWCHswhKU963a30h4kysHG3iOYR2mhBy1PD1z55APh\\/Iz0ejzWP9UNbb0cyXTpzjbs3kdL87zLyNXiunADFtY5Y53knEuD0Yva2VX8Xg4Y3\\/EakbCWadX1TEMuEvdKeCkN1SC02YwUSpdKl3foSysbzrFtgv4jc+gbDu2TX8\\/+lK5Q7byJxUZ35h2xuAoCkIqV0gLRIyTQOxRC93PVklMFvChhi\\/Seo\\/mv\\/a+bgvxNp\\/alGqCPHYPe\\/N2GIM\\/UPafvJo35xab58opdXlFxM0Heg6TtHAhtWaGr7S4h\\/WBHbXHhWmKrK4uB\\/F9WZJd7Wcw+BfZqQcKBGZi7iJ0wTwlB3FowWP9HJAhj\\/mIPEqL\\/wImtcpuoxNmyp7xFgHl9CeEC88clkjPtoF6Z7FJKM4y20cEDG1ilAeQAwqf4krjpTbRQcZsnPPIuRwc\\/T1lTWRE8j2+\\/F\\/u4LXsKwa5GnaTmDN371Au5Bpm6CQOPfRHOQma8zmTsvfmtumt30YAmrGjpJCRroZW17EAN2AkbUXR2M7DiYf+deIBqss3r7+swZL\\/KuiD9lJiD4qwQtY6iBDdY8SxFR6Zl7YQ9BDiLLLM4zA+5OkNJqgYk7+RZvv78YK2XQYf\\/+n3CRo1nshEHksTMD0mZvX5VBlBIdqNAfO3AxBs8qgipAv\\/4uwbKZXWYsxnaIuVIU7Q5X8j5cgVbz1dsxWiDqyDOpUeqzuBSJffFJYxwzacuUf0ilcAI1uR2Li3RK1EQ+fgsUw6fZzb7WiS\\/lI0zCr3BFxNBhv9qJ11y9Ljuo\\/YEkEjRNSAZADJbEtcMtlcsN9aDz1oFpoUCW0tO0HnMFNrUw9PLwVKyNqXheabSGeZZLQo11WTOGHakjFRMa46481Zgc72yKgba9eXUoh1oPklXHEaQikqfThIcU6IGSIjavDvMBWLkn2aXPX8yrbwTovkXHNhfNmBr3KU9otkmdqgWO9M7gVjskFhZBsNgrZZC4MzcEepISMIWpBwn3Eay+EM\\/V7Z7CuZcPeC6m\\/L16VbSDb6VND75Z9W6w9uWRWE78tgvBj1AwhG8SejBgXWlkL+4WfyqP\\/NfasIqdBXilKYPOCBo4wEvhWuh2+ljh5nO7uGsu6XBp2iQubZWK4ZwlyjufC+T2REU5g0SNmKJXdc6VkvsFbO5xkMu8ueSp43wy6Oz6qNI9Q2oaT1VBETImCbI8YnbgPBmbXdlQlnYfvUK8sKRypIjbGmYJPV\\/9sVwZcyB4n\\/Y+yMFnLY\\/6v29pKAfNqQpDMXUGDDWeoQunRWVBErShleJGX28BtxY0ga3MMzdNBm7e2WcBQeFP5XWjrKb3rSXVgP5s2XBiAJ9CW7tjy0WkCBUNbqAs2WLPWMmR3KGbiEXBWNhBcjPBhKC0ffMKbpxUZSZ\\/G4D04+UrVw\\/tvf0u188TvxIsyocpT7S+cVhbIQBU01CIuBN6Bks6\\/rBRa0lQxoDP+6H5W4RrbWPaVpQALwBeLu\\/iBjnkE1AtRiscnUTHkfQRjSX\\/++NgjchimD2Bn9jPT62LyM\\/ypx9t9DeeXKbANCwuLs17jaN3Iqdeb+rCep6FiWfzSDvTSeWdkElUgDZR\\/RFdSzptWuRHpXkDxgoeqrmYfCPQDC6uts96qSQrhXGPKlqZGpFWT6fs7lfjqGdG58FxCRP29W9D5QjXC3JqQL0BnzE8nlFbjUd+xkmpy9g4Wltf0+U9oMU5X7zXHQre9APd86QHoGjL2HKLVZdlwLu\\/8ejvoBKPGdUZQGklBIggg7iimR54IjRHbTbwc9c6spLzTMf+PX46OxDjHGYBVuHIKcUmxSEhRKulXiScSDzg+H1vZvwsKn9zdLw2rVjM8hbx8SfCvkUcbH4UFzP2u+tequF4OADLGJwVjao4PWg9aWpiYb\\/jjaZomcYMj5f3l8\\/ZBXclTM6kngVPZVK2kbfxr\\/VjVFGARkkxAIhb2qv7vWzNyFyPuhoK4iefvHkGx6zQXcqjBVsg+dA9yaMaiGEx\\/lamslqkw3QW5TwWWyJRFn8aFQyoDKyFTiySnUx9Idgv2y0fJ8Mlzb5S8QYjuY4x\\/FygWZBndTOZHgQT3LRXjcycGB31DdCFHWaUEKy4B4xv9Ivzwowtbat5wYkS7pgBl5m\\/4pB\\/wrQ9LP7AOW+fnm9dOdF+Ox\\/mcVb9erCXlpl27DtgMaq9vbiTVMHhHWrQctRbgiQPEptioudFxV+5YLNkbALlEyWhZNw11NaTwJ2fmpiz72ZITYfc6VIMNG0fvZUGfS+goDpfHc0yumxhZpYUYZpG9velA+qhGzS2ZPhCyYtEMr\\/SrKPa4+OsWC5Cw8lLk\\/Vo6v0GnihezF9dpM16fyZNZU6PongMw\\/C0N85fxsg3xtrvAcqKEYWpv33qSLyqWNjMKgdTwRZWNqa4DfnWAgpbs54\\/kYRTag+ZSM9Z4OshOErAV3yFw8ehFADogSGv2bT+ZraT1AZ8j65XDVRHabeSKjGp\\/RUTdR7XUEHh8kVCceY4xvGX\\/uhYDKl3v50lgtVAhKl3oVq7RjMb17+VVrOyR2qPYcWBSo09aa4MjJN37CytYqkykhoZmQejt6jgyZH1Xc3SqYdg09yf1i96qyJrBUM4eymdXRzNRJ42zFFGAwMGaqUUrG9fL6FrJeqYF5HhY3a0k5ngd9P0vDCi7Lbf4xq7vdbsuudq5RInYi5kZTuG382\\/wqM49BU+0fybHwSkUxUM6tzBF72hY9sUF39ABXU2Xr8RSn5723XA\\/iKgaOQg7C98cqLIUZCMhpmjTCfYgPFU\\/5DCF54u80qHpIr\\/1kLXL5l+zkYJPJMokN30SEt7VpnMQsibNLb8D0XhK2egVGH4pYSD74QPWtyj0E1bBEhW6mRLXywQ\\/JjwXvYJ6NHHaGsWHZG7eZ1l0fro1yW26QUpI2NHuhh6eykaw06Q5bOterCzL0\\/SFcAIdsRyd9ZEugC+rnQChTbMQDOUekvJyJ6mZ6Qil2UZt0T0nEZb9FmIKSuE4KcDGAWQWuDXRTzWZHas2RZubXQJXsbzDAiJHznf1OxSDG7eq941xqu2li6BWbhTc\\/968AGDdCsRPKEaCoiECpojH+e\\/3M4HBKZLUNKjH9L7UE5xx+mM0Vr2Mj18VxuwmRbIvL+8ri4zoXgqnsKNEqRKo0R5xkfp\\/qjVdZSxy8XwSNurVJqNvaRilKxn2j0oaa\\/RjqD0l58N\\/NnrKXC8oyxdK44K2psYLrDDujKEnAX5bie4zC8P8vlZND+0aNZtuUNWRHlZHab11ADhxAo\\/gOYiz9Zpu\\/4jNoYeuvSluhnTqA6lx2o1kb1dlkgvtC1fOlMjo\\/oVpleDT1NYm8Ew8OeR5HMixahx7qYxWeD0sEptSAJYJLCJ2\\/lqPRQLjeAOL9Odar\\/hS5WE5oOs5pwOBrY1opc9lC3tACpTOBli3Kewat9tklSptfJKtZsDyPHF6KrcPP\\/caWFyRL9U1GyM62JXNhobHNH+2vYdUbWDQ7FEaiUF22AYwLr4gAdfynsOvq2UGwG2IqCjnqa7nCEnk4yE0ZuX0WW2eX9Zaqi6NCPA6xFkOpiL9x+E5E05OaB4r+uZ88iKo7jYt6GdYEjb7n1ro95duwLKVf9OfzIDGYOqkuAddE1y2l87kLBcw4zDrIXWx718fqc97KZ5pNxP8HFMk9yqX15fFwpQV\\/qFlu1N0UIddqLYj5Kui1RxFbpYSUMk8EjB6x2Dis7jBByTfvXCnm4dLEL+x0nN6yk0lxBWHnCaCL0u217aCIO44Rt6uTDTYj\\/D\\/67bHU+dCzN1LufixzgoGopRWKH2z5otyoj+7Fw1FtGlWJPa5bg3qkL057uyUl6SVr\\/7bxmB+YxaF597HFbuMqiHRNjCpz3gyASACT625CSFbMRYoPdSgWfo+0HrrHX3Rk9K3LZLR1JYr79B9rsxZ4ctzrVUkKnGg6bYcxjMAwLsaCNwHZu+YcuB\\/haszG9Zzy6vUS6NkSTwGP0FNXLW9D\\/dzYjFHqv+9+ykwEU\\/\\/T81Iv1e32sRJTcGOe1Vq8iyUtG40wdcym4l08QFcFvpwKd0WkTCRnL\\/l3e0S9gUSYVMpodWiGE\\/c9zvFq\\/0H3CuQGMcOWcQB++wXXl1al2ECyr3HhNVrhCckfqNImDi2gKvO1nv\\/I0F9sUeQopJKbQwZHQLUbnnobrfbxYep8VCy8ZS7QgKJhKBqCinMO4PU49OV2gO1xjFCIhtsMYgJV5GxwZ28EOlavY66Hlm1G0s00yQiafyJJNMm0khGQemJFmFW\\/iRoGeDSwvqqx3CdHT3SUm9Ek1crdjTZDMauspL3Jt5o6kw8FYujNsQD2GZRbMLCXPkKOLtRcNufPSccZjI2HJeT0eiHb1tB3exJwh84sGR3NX0iIpEeBhvi2HARykInaHWVKE1v429XnStpl7+3LDa\\/ZRMFQLV3yMfYnMdiA5e1v6iZkG9gtcpcaWPfQQt5FhpiwsQ6bdnUSaT7SFDNwRW8EqdrZ5ymDgUY7MRsHOHSGA0GuPJjNo+ayb3QeocZWzeaSgGu27AB5O2Yown0MAHNpmf4bgzG52HGO8SazyXNdTjJ+cd6NN\\/4o8eaUjCkZY4fT57mGBWWuw5YWvC0KaSGL2e2Hc\\/j7F8esUOzNv1EVv5UWdH6SzOWvF9sjLHDhMdmpgesijF9wEv5yiUaBQ6\\/vrPR35ry9KcylNxl1yq1dui2M+TQ+gI7HdR73fRbJsHXcW0\\/m8emsGxbF34oR9vs8BzavH2Q6bZWe3eFt4B8qnKMXb\\/h5n\\/FhEpR3+Duf3VxuSZS8Zaqk1WIsj1dM8eTznZ52yEsMoRUFihClZoy97h432Mrgk6UeC4O5PXF1\\/mbh+uRh2gyPd7iRerDs3R0xF+fowGq1huw2+UXHETq3Jjqi\\/yCw9Bv34Q3fKFCQkOAzj003tWElVeeE7\\/Gx8SgDTF769nTxpLnpkZWvTkrP8v2Bqat95CyfJHEiRbt0mtr9cPGuneG+c1APwn\\/GuTAlPFjh5hdHMPh8xkSxLfk7z0kaa20ji\\/WlOOJrH5ZWCShuHB0kkMQtvXMO1G6HHB6awH7eyZdHUC6gniCySFB8h5dgu+um3dlAZxu04wR\\/Ct6SdqBTF53EqwCGShPCY8DMQ0XZpvjzeARA46P0ffAiX6T0g2\\/yurkk4AV1rtm3EWTg7jBvrb06KgARdsxFhalXIp6afH9x2OdCQV1J+q58j+4p1TpfU5dNuF1rLLoIU421USyq\\/hXSbSttd695XgAi+Yy6+wknKYYdLNL\\/D4AJmsnuCHqB0l+T2qUCXKSfCtEpbGo5T1LgRuqt4dL98gqFmy+x+uz5OsmCaIXSkZ43JT60dfd6zfi9jSDOwhWiZhPLyayRNrzH41+fbv4+jQYzvudavkz3JV48I0h9YEEjNhM8Uf7neTzo1bNcb1zoZHIbB4+VyTwYC9306yrZWuMk19zt+h4ffeXhdi0O1B0FkJ8ncQ\\/DOQjc3kjod7LA4iLnUL4rwd2P786omWKWaAom7mCrTwAImXaMu+Bp1osVMxx5PrbT+sdjZ+now7Y9vbRj1\\/ydJGczzpYETVxGdBH2exmNAFjyGcOxq9Ls7o5zMTV6KLjmpBGkjhcDc7qKFSIAbiicmHKrJifgDapNalnVdWdOuYxlnH\\/\\/tXtlCIus1hXpVlcpd0XdIKfU4E1VNs6t2jzWve7oyAfZ6eUG9vLV4FNNG+P9WxVBlCGa0l1V54L07Vz6GltIPYniwT2tbqYGxmyqbndQ7eqVP9mQBEP2xMVTJt6Pk6H9J+Z0BMVJ8yygcRWRG+RYLtOnbPxLr90foc9a+ud4Al3Ha\\/gWkbm\\/lu5qoxC8PaD2Zq6IE75NuXsy+xuWXco3Ebu\\/NvhMgUfy3NmFyctEdyRw4qgGeOjPg\\/yVx08e6QzyYpyNowZ2I1e\\/EubToLyuFcdeIxq5DdzJBFnYmYuh3AUPHrZIFKVCWWVGUeZwZmALiEB8lB+MVEE3CWsETmIntr5txD8KNpqM4PENTCUoMY6DKnjO2PWQMQL6OGmb0twAcAaNkfpM9V6v4wUz5GRed9dd4wnFmWSms54PRuaHS3mTOSOn\\/nW5ep1wiDIAt\\/AcfYCX4rWqZrIeYnxSxE7OVasPcnwKXO\\/2+KXYaMTH5BWbdTI82grlFrspZRMfDEZoDw7ZW+lvnBAs0Zl\\/EuZhjrRveLfliySE4x3DXl9U2WQwGJaMCBQ3cXadiWXj57qpCm6OZUgHltyJ8S8W1yaayWqkNE\\/QLIxqFzcZbokJI2IHbw9KJbeUXrwnpBWdTNhV1\\/zxwpkdWHGRQJ98tlcNp\\/0w8P\\/cKmG\\/8r3\\/cyuj\\/mV1iviPpibva5XmmEw9F6b5JYjFGg7MU1omUz3efiaF2TqAlETYouF9NnwnuDDlgPkz938+HLcSLKndKM9fte+\\/KNVofi3r++FN5A9AwzA0CwqCaXJxdNE1B\\/IbAHcW0iGOMA4RWm\\/Ytcw9NLlU32FPe7ThQ74D4PPrWQYmdbE\\/gGZbdJUyoCvlQBINODOKKdxF3wH8D5+0CQm9xcJStT\\/rD\\/87FkWWWC9NRriLtZoqkLZg4aRNptpAmwqu\\/khRwh\\/E7tlS5g+lilD+Fe8DkAAYh\\/h6WNqmJYjmg9pj1oqxAHQ\\/Pz1G4jUwKyOmRxrFc1iTOj2gvSTOD9XLYhY3SiIPVUyPfSivfclPpjaMErTScRu4Sn\\/FpSQ+w0C2kdN25pf2HB+ljDSdmrj\\/6n9Inia0rXg4c6HFn8\\/AoBo41VtOuuY7t\\/cDneueKAaOqVrYd6kyjz9v1Ne5KTP3+in2ncBgsH6FH+C6E+bP5d2DmcJmMbrZn+wLmZF3xaBHC5Z4SBbbMsynfkyUZGjLiBqZgnSwkXW1by\\/KjNomPJcGQF39UGa2z2aPNOijolm9dOGAJV1lvQX7X2sr81aThnRN7\\/T1SlOzRyyfN8\\/W1il+VFv\\/6PSRDuu8M2auOFp0uU8vwhUcYBZC32w++PlQfK1GDCIotk5XkOfmhm5T1\\/qCuiu67aHEZRZsoYP8IYJb9TT9fb8HGhyTjWZdPKQdeYmhLrv\\/8FbfXFvjPAdFIbXLJJ+mjMgpjuqyWtJGIVd8BEkIJJ140eAM\\/smxAifk2ZnAwZVP4\\/l\\/uFvZbz0CEaQA\\/muC5vHd7y7X8K+y7I03mXUf2sdXQ18Lluow+hfbS5pMzj0ZT4ZZ6UOI7PL\\/h1kdHSqY633IaGW+EzGTxG6iny6y53vH3WDC4jaWThWw0Bd4NT6JFL0y50RQDQl8g8L2Wb064WCYorBL2pQJoVEBgHpYEQRFpAM4qc4vFIITIQU+0rA\\/d1ojbr8eLUthfDWKnmtl82jTBjqhSSeF2IiScX\\/wgNFdWE8k18vuScJ4CTAvt1kcF5cAlIY7oiczl+Hm5S8pHZLe3\\/JR\\/hJ062F2VsodXTanWmNn2+wOds3kxmU4d7f4S6RW1E9E24omFoZ85YJEWHgrDmE6fTHXAnQBLgFTASRPkXMTOt3fFblWpVgNY2BHM9sKj664cEzMBSkGJNd7Ri0V9aVBKmrzlL9KhlEXKPGT1Uy\\/e5cUSgl\\/xzlHNDJf2PLLcbx7jrnKbvKtwD7pZptNvyW2ZXRqV7IOVYBTYIZLakDe69GzlJuG9yLX45oBIvH7S\\/g57o\\/Ol2sbClCkvp4nH7P7DyjSGQ5teX5uOFTp+foe8NKpXgp1oIGq7AWD9V58zUWovVpyEfkQFGzTMEWoF8lqm79E2zJJ0C92TpCfvnmbu4M+ha2fnK2jcKYpCNtdSvbvuRDo+jUHBwfcfzsycGG6wZ8qYCxafWbJ9OkudV2eziVAPCeUxuSVg040X0p06xbz+A3z2X6cigR5eDmSoev1HDwM7HBRpHPDrMp4B\\/5HrAl3eDXU18pgrGVUkUgpyw\\/eVOap8194UcCHtE3Nw3ZRHYoodWaweUhOD9XlhiGPDnNIypbAxshAZc41M3JRXEu\\/Px1+rIA7uW+2WV1nw5UOHLwDnbCb9+w\\/QHd\\/X6shRvfdJ+0HUnJy7zcCi0t4USW7rmXeQrtNzfDexd0X0E4DObDBcYKrCmrbA7udIPYT5G2CBN6sHxPsBwrr0i+ZtC+9axKd4hHn0jCrHaDClpHbInhx9KCAZzhZqtv2CIDTA2EghSbAx4ZAygDd2bnSesjQ09e8aJst9gdJrT1uzZAL9cRT7PhzWQFKJbiiDFKqW9as0XxYxXsXnmvTrulLDeOENjhoZst4GiMRt8zVdqjzKAn0UNZRadOC5hy4b9QVNX9V50Za82zRVZwS0sUHYwWcrDMiq6ff9b301dXBGK4WjV\\/dRsNXjv3F\\/LK\\/vN\\/Z0JdYPO6q6yW4pnkdj79h0uwjm7TGC\\/MAbo9Sk80ybpk8O02svQGBuhIsw5ppuSjVTw+XO\\/clEReqOBOap9lmMeCYCJvO718xX6S3Cif++WeRynHGCsLG2rUva+uxdzxEhkP7TtJixBbzLXTgrALnad6+5WBYT9fZKDMKyhON9naclCRE1o67HWdkyCjBG1PP5hDJiUAA+2fbCltsG9tVWGPfXcZ9Wof5Fpt\\/8MpSSwG2R6mJNY1qcZ3Q2bYbfJS90Vh1PKGLFUD50nje3mqUYPLNMz9HKAxhIbVyMqn4MvfJMy2xyJ6h\\/Hli3qTByWlcjL4l8UWv2eEXHVVOmbLnKbukuKRkXMjhRsQQx0pmb21WUfXPHVeI2nVXOKjKVB6cDuEzehkQd2\\/uHICFe+NHp5rgig2cRLhPIgNpazqzbyKXNvR7O4C9rasit82q9H8sGROFADt5xpZz5ryJjWmj534y5OpX0vRntMhpYW63QXZPzzWaRaeYr5nIZQafZdnUdlOcEtBzEoxHBaft87BHtVD1wG3W\\/3D4rEhHcoLsjduSXexGM4+DHouf+5cib4BGH1\\/Y6vPow6911DZ+4OO0sPGAS2+gA79I58DmMmaaAxmJ5Kb2G5IToC9tdPX59fLUnpik58ZosUGE7Sm8xf5fStJpb1vIc+XI+vxpTDx6EIMqIce7NvXINQHsWiza3vwBNvUuggtyWx4GQf6yGv4GZescwmgni7a7RuLelQl7OnVdfey7f6hExGlnA2oB3YR7uS9HLrzl0uVbhKoJf0LmNHt9uXy25FnigS8CzFfpNBieI\\/3gbL5A8fRcLO5gXOZlYFYvqm0GZbdp2atTLheYZnLxyWQpW7vrieX5f\\/sq5Mc6dt2DlI6uAc61IQ6nMnvuZctzgW0zefM8LWSqAQRmA6wCiJx+C9786z7wvlpUcqPNv0nz42fvAzgYZTM1S5IG2TbSqCEPoWSeZqKgYpQ1jYoriaz+KkiSfJo0\\/ZyObl\\/MsTk8u4NLQueDFiiOLiU7yb3X9lPRz86gyvKUQ0xmMiiFC2xSscSgssTkTgxsS3yN9r3v4H0PcOEumDqv9fJ2LONhEqBUsvviK7cNyhD19EJDdW9sBeDgoYfFH7Up9uszkRPq+wqdXsPJH9OVlRVcvzB7vXO5K8TGP9ruh4Sw4tzAIKmRQEgFngut+LPn0Frj04lQPJsOR0jPHKBGQuDQsGiFN6xXv3BEUrs9zDx0A4H43IoyyLqz5CqxkeQDQbkZbXF+aMSvQlhNSlOAv\\/WFxrUdmJJwtx+23M+f2089oaaGFBKqe1PrB9kHOYHyZKY5ClIvGyq5NRXvYXEVljc0D1zjlYzBzqVT\\/z1sgtJdN72IAeR2PpoNa4k\\/iq7p8mHSfuUSKemPhDpjLideIJOX6Se9kdvpSQRRj\\/6HOc7MyVeAwHeIxmj8H7tR+sGZiIeX\\/6BvLoYW38U+qAbEkp3+3TSN2tUjn0PTd22UMi\\/VPn\\/tRbPDX4BRS6+EKKCTsBRaDeScqB0\\/AUnJmpc+1kW28I8fkUdBF+2YU1vF6jXib67iwxJWUwf+8zpiOp2rMuOgH+dg4eJpy1XAouw4Q7eq6L3TPZIPNo2HB7lPxKnjvyB5OHKAbNRkPnZldNJT3CCI2jUFkygNRI3rqKhYAH8LputOsIsPHlt9kYGiShw3lHGFT9igqeAqv4uBm9Rj61A34l05fR4Qknk6bdFs2BufMS4zpw1mmQ5qfelAO507+vplbaSig6+A8GzLw2mMtqQ9MiDq1phajblKP4Rpv7rDtR8jI2oYniMGfx4I0qIWNgmYJkla7mDyYHbdXu\\/nYtOwWrwIvO1Qf9eYKbMY+Fin6ELmh9UnesZvQ3QIZzRJCnqSEEVG3GoJEE2\\/8ER4wH6OLJJCculuz3KqTnQiH6QPa+Eh4D1f6wUFVwiAUQsadX8npyPHqBbD4OY2O1vxbxH3KE6jvwdKxDzV5LnCMfaf\\/QJqyQ4sLKtBIvlfPxopZw25nksgGz67i7DReZ9KxwYCByyKRY\\/YM\\/zX1cWeqdFtl\\/7C+3riuFntkKlwbB6Wol6LDersK6aS7KJYiXeO4OuqlcJNeF1dHUffPPN9I1+AGwCXJy2noaYc60SW+g2CPrd06xaNl4D5gOcqxpUaPXj4NxeBOZgTfWTp8WfnZFO9O8qGqR8SmWpFgC1w7tBVUeEKVoBOnfO\\/0gL88tFarv\\/76u7Jo2cWpSsejDh\\/ss6\\/K3y96JiA\\/Nbk1nOJeboekYVf3ztOLu60wgNJVqgSAEuVUdfp+AsGBCq8ne5cUmDbfo58IXAvqKbd\\/Il2tPOFFOCVTIGObV02V0BrQqlFIKeqtzDZ6pp4NNZ0ck\\/r\\/UgQu5qIHPyygxNyy5gTX4qM8WeyAz7mjNr3mA7kKFpjq\\/OYO7S6Nq2kleQevUb8qjAE7O4BGHEv75paLVLAx88Cb6LGehlB4LL081WdhwiDIxCuXRNv2qCtRF5BLdtjmDPg2NGk5tLhd3WX2\\/TtOeSWrqpY0wdZ5tF0uNqHmckfmD0V+ztWsmBTdAxM6rsWOAyWvRC2QQ0hz1D8WOGgow9v2V9RK5XNW6TkfjTu19yWHpRu1zVwAxD5MaOomvYynrgJsYglQ69vQW9E\\/6Gs8f5TB\\/ALXlKke\\/evxOvZQs\\/Mm79V8ntmWw7OYSSZhgqKboD2TRhS3+zToPqulOOvvjb6\\/SB2XFCYGJMyknylatiVJb3AUdiHz2mj8mguhNhPverz6zfUauAZ326cM9jbsYqCVbQTZ3iJbyujqwDZnwqUJ62w8pBaJAo2fi9iQgaRsSqhvFyE2fQuFYPGsG6lkUJh7LTMry1TCvc+5ZP5UGjB+vjbyKaohRSeCYXwDFbwHVeDb4z7aMim5QhumhESRopY\\/14FyutgHtwsTNBhDcMN\\/eajAFAcTfJJ5+kzbuv2MtNtHvY5LdYBaCgalZemw3lstxbSO0KfOoAZ1vzDyzPS4zLgm4NrCBI5CEgX2Z6GUPhvCNoZ4MRS7IxCJ8MKMG\\/Z0WxxtrqI2MHqwEGy+iG3K7rT+s7vFzFtxx+FfO+VkwGs9T68N5CGr7UBReBqEuIqLdeMz5yvppCN4uvcNwyYD8mTYfNLzh0ceZE\\/Oc1NVUFgZ1k17p66FSxkDqDvfyy\\/v1UcI1wf44rGzyD\\/M4W9e7vYRtrKOv34JqOaXQur\\/ZTGUddV87KljvnoPIWt\\/Yxfg2jnHYYcJ9PNBEcaZF\\/3lUQhxZ9GBr6jTFD9v2omE3vyLYlOK9lf4P5WPYV8HNwLHWsX1iZpB+Yg\\/zJ6fqophBbfr8gIrLZyC1iiJFDe6\\/\\/IiDqu2+LZJHm\\/iQen0cktFVhpJbibNrBTptOLs7WMjogYJAPnDnu0a\\/\\/+Yn\\/QrD\\/Xg+NayNkR7Yyt3W7mRkoMpjA1d0uqKyvGcz\\/TxS5BJQbUzF6T1MuxeM9z+yaIOtK6j6C60DkyqIEtdJhpcBstO8SVqdub8ZehEyQdjgC0swgfii19ctIxJHj+muIJvuto0rhJcM6giexrafd4H0GJiP7aSDnONaFlw2YRUgWPK25cOgNC0MVbqpTNtlPsAhABqvNzL5AAUsqVNP5XhJanY2fIBZjfHsyO9+v91E53AFZyqOWLdJjUpilETDFhvDYGCcL5z90+SUUUriMhww5Y+cEfkSL2LSe3+5yXFTl+yHhDhm3GRZMsFIrvxjSG9nuPymJsG30+nyC\\/\\/BoI1OIFImqAMBTyzhHcPGpNY\\/Fz1F86IrQHfGoqjMUBv\\/sLdxkhkL4yQXlTJPIaoFxmz06e4ea6ph9UnvD2ea3i43oPnIfu97Y\\/KBtaDI908hky2Q6A5sxWvoouZYpha9N0QdkN8PvGxX1x2WPwcBNXxCqFSgqkSDiZPMOAZL23F4sltF3gBsHAG1QOX0XIzBJVS099HnZs7NWCpeowe32+urjcAXmP5sFkPQPskYUuANGlZZ2wZ6VVhKQAI6DZ\\/c+a1FyH7lkbugO47I2AczSJtpHTCcHVFtVIZomKaYU6y0bY9\\/lsID11nHLt95dBV\\/THOWVzZxWsDPobBbrclBt1VtylFq3x7IiKdQU6r8gfg++iW0mRcQTGxUFIVZqTyNgaURzznuWGBAJe6ERj19aBYwoOLv4i+ojKUAUmAYpnO7+Vd0Qpy38fZhX4Xxw9AOQcEeVIjxm5aXpEmn908zBHYA7X1nLVxT3b8IX9sJeh22jofp8rS5bKLszP8q0haxm5AXcxW+6zei2vUQ\\/DowwPdljmK9nOf4MRLVuziVMMVjeusz1LN2lY\\/octaf2lxRB1M2nxeLBjhuwYzuwgWSOWi+FOb2OaFyyGGZKtUxf9qe4E63U7kIUbf86qmaa9wRvYcoci2dXug+08p+0tfU6kkHagk\\/Not6DS2W+brjka2pZtdPa5QddPTAPmihUYtLTgadkULpw5tu4+4Q09WV\\/YIYs9Fd6o+CW\\/4wBryub0V+eR6DEDGwaU5vHkTGme1T1QnMS8SGJJ8WlX5eWyS8KkSj5Zejqxttbtj9nPf780wz6L3VlrSa+ErMfWWFfNbLqVPwqJAdGLsxr+WaTxX0xbVk4oinRNDYAXOxtw04ovRePiJYlXh+khfOI82EoBJLjoM81C6xHTgzpD7XB\\/Mrem4068lhFf5W7r0EVVZxhuawc3AUZka6J708XwCWdYqrNLiB+GDM6vjkjMNGo8uyjvvg0AIN3G+E3qxS1vqFyzhj8Bxok3pxNgV8wjTF5XRZ6usZp5c695y7eUP7lU2dHej58\\/gOzEeVH00vBBhgtgvDKqCVEQMdVh6CFhRFgC9IjbY0Ec8DB5n4NhJGlPhyajM7ZzYhecpussonrkbW9Mryk0qfiLFjCwYUq+H1VIVaHqzOW7kfbxgjv1zUjjormK5ddR68xv2grKvO0zMu00c8Hc9e+J4dSJqU9xIBiwReMyeGI6Qa8xPyGv4SZ2IR9ydahWSSkBwUG5Q+fjjRYSSexhpQBl+y2pVnHK1+vI6XN6DS7rrBny+p1mADVba3gkuZCVyxIUiBwh62\\/\\/RfRsBeCDTA1jdBkC9OLqUagj2DWlVzPbKiA6Ef1RdQS50lc3fVtbqeAyYxRSsGRwOcLoLMKtxRw83M\\/TqExj7BsBX9qBQebF3JAZkKr\\/qEF9pZfM21O6Lw+jDQUuBkI6DX2lnuhEc\\/hrY+hzSeBAtexwMH0RMXuHprS3y4WlYMYJo86KMEuyMXAEzgpPo2l\\/CRvUkHkee2TozmrGxWfSU7aCF67s+nCJ2QZoTQeWi1JFx\\/qsGzMpQhkT+b4f2Dz6wHVmSZO69ax\\/qZScYbPMbFH2d86GWnGRLeK0gDnPzFiopKSVFZFDFu5jJYhl3+pmiXRLgXWApftabPoA79Zh+jwYckeovhQmYAf4cGfRzKis4\\/k+6Q7+wQFRBEFA8+HFSkCBo6f5zmJgjHk3oAt0ba9C23BCJ57dal7t1UQqZBrEZIlc\\/0vRnXhTo6Lz+PbAGyk+TeCCYki5fgUeGUzxZb2JMYsq2EsLA1rJM45czewxrTOhaZvMO1EXWeQbTk9h\\/mMUjr1BHohHQrciEdo+NWq9fMYM9IixZ7aJZKVOS7ChncAZ8d5HLvGJKsWwMgsTWL+rNNnMWytCvsgWo3mNV\\/OLO+UrSYwCJ\\/vGAEy31JQKRr3Dw0TYUa0qjvkSJWES10BaotXe6YZDPE2e8pEd\\/8VoAjpgOC5iHM6n3GfzhtTu79NpC4lcJzc6HRUxYZVoIVTR0hSRRNv+98zS9qz1+e52pkDWaBchRZmX+UvHxAiWNEpDaCnWH6Ut0iWFFx7vCSEuoHZ5CcZI4zo7965uHMF7tVXkW6UBVulf17V+1T\\/pSI9nDg1vrq+fF7BVNGsDdpph8lJh1nvr\\/AlqPx6+tCw645bobLDXxrRBwJyrlQeV2mIOLqaYS0bs2vUPShq5S+mygoB908QfMwP5mfVvr1XQ4Cl4oVVKctHgrfvKIQDOtxXAjJe2DpL7ksbKGUiulcBb09WcK52nuQB1NtLHbC4WoVMMUsbtBMJYAFSCptkRycvRS47A4OexgJZ0flvhghfm+Xv+TmhExeWcNQRd4sQeskdd0b6\\/F\\/9KHtH5DS+\\/DVm8X84u0KxuVmkp0aOib2SUEdseROuGRb6ud+2NoobOfcE0Ex8GqKVfS4ARbsCLtziAB6c+wM\\/xDWUZ7zQWmFE1pn7Bn1uAbBX\\/wqUfuB2UxF9CI4oBoxgaZlhfYFDF+ERBiGMp3NuopkSlcxvrTwMqaIjCUZ\\/OnAuKiCNTn4ouVwEm9mBJGhV4VfIVzbsP76Kf7vpeEfqYRiFIWViZ9kW1NwHFyjs9W9PcBFzIS\\/gKk6HT\\/CHQedzROFecy9Na4BcqZ4Rlp9uH+24yzB7Yye3OcNSlg0kMJN+6Bwz5x1Ah\\/JSa1i4RfjbB3Yf4GslK4lpNiW1xTFZKg8RmGU81Dic0TkqZ5GvVOTca\\/hgnBLbm\\/fE2e9CFcsKW3CJDXO6a0ptw798bIaD6us3ayOUkGgyAvhM73b+cu\\/JN2IKf7X3wvxWY7rF3kWVbC0YWGQc2OvD6qUwP+P3EmMIKi62vso8M\\/dC3uYby31UbM5aL\\/KxbYtJzNx6KRFwly4bKTYD02lR7tDuSSAMmBULSmKDHbSbWI904Tmk+WEapGaCAG7ipSPFlAdRFbqWJLszwh6ByghC9lRe5KvV9mrda6LXJIa3aEUPmgYPZFdcXh6sr4ieFE+JUeeLHSu\\/lXYYHd7WMGeTCvelWc7B2nnv1cGoTynqGfG1WMWQ4\\/PYyjxqf+k+iI0kKGdA5zX3C9u3EfZmK7DU+OLXvgWCCIIGYUoY+jMVAj+rAXyUPKGsKA8umPmmvr7f0Rf5pqwWzOOfpn\\/PusUA10bB18dfw5id4dNxNkRnCADlJTRWLxJ2ZpcvD0CcTKi532Mkls75pwfCv4LCkW9dB4GTHprzNoTpNDXqahCCXQ\\/vJOgpwrmTCK5K94xsYfvRALcFRcVp\\/etZPf0rav3kmPZuTcm0XDfogoe1W9lZQnSBzsYF9H55gHzdv7jG\\/xZQmWMmA9wdLspx0R3HHs0HBieuH2Yj9gjsN11iReMr\\/HGANVSnI0bzN2d4CgX2XIoEEgRiYG2IASoI+mMw+hNxqCH4GfxmCwBKR59Iu2EPsdK\\/6THJipu+swv7uipHxKtfKfZnMOPv7brONIxjbo3idBy6SNtEZriXga0ZHCBb6uMazsmykwzcAspy660cdEFMy21pId2on14Ikcd2CBreol27K7fBhR82myKI166BrefJZqJrL58VViYBbprDlAjFT5Nfkz4+Ba6axo6kcbu52ViiYad6PnWOqZl2QpKqn6Sn6cPloWxbIFQP7PmdcAxsShR4HYCSzrSXbpTjMmcNMIapnR0K8Q4fNm1pB045IxWvkO4dO5rJkc5LQ3b7CKfGzVHvUfePIaI3RFyrqHcRcjLozi6Q5WU6\\/gLalnQPnBNc4eUJeT561QUseI9KC+yAUYSq3vCKDrDKJEFC\\/\\/+0SXgvqcKvFm3SQM4SZ53usuBvwPlNA+oMPV9YIntwVmfkE0rsTsb5nW5qdWNdZi5OdD\\/oSciYxmTnfQCdyA2mxRH4EZUi9WB+tY4S93RSL4dlg9jBEGnso5rW1h3nuBJRdUL+9jGqLyBrq8hCM\\/hzt+yOt+vF4s2HAjByGZMwZNlskk1ffCtkaDoqyaKn1Rf9Tunk7nQ5mkzmz9G9eGqo7gcLs7hAqbwTcluNaPBVnWw2mi9IrW5rufOzyotGCMFTTViTeNq8swTdyX62T\\/QqYq81WgMR0HX3aBOAAARw\\/B1gnA2drWJnsUqM2zPwvOGi8AH1EAMJZ1TyL9\\/tKwkwWacUB\\/hCf+1QX0JkmWH2Su3gg8YYWJgmUy8EZTbW7Lcy\\/zyUJFJxVKV+A64Yh1TO\\/PI5QFmqkA6d0NipgdB2ooygdMU98OxQ7x26fsaUJPQyHmhDRQORJbD+3+HespIRBXEtX9loSkbcIPuI9idXRgLO+LaPLu1Y32TarsmMR3Q7zBzZPUVwys2NQ4nm8RVwlCJLFZc7Wksr4plM6\\/5fBlRYQAi6bJUcGu443m+zxeMVRnlFvfA7Lc6OrfHJFFgxcriL9DGe4p69e9LRnPrnyz9f0hLle2w0YkkRrqIVbJ0FzVS8RvaR800Aydn3ITj8nLsIF8ZHkL+58xgV+Xs4haSi8woJlLHFv5yJ1uxtavJlcPPaQyJf5i1Sdue83GbAA8i62dXTQxo8YKfQ2oBichNF7nNRx07wGf\\/MAgT\\/WKjrglzHGbNkDFOQ6zj\\/ttRlkAyytEFWXKbvGuAeNzrTTWFkW6kRbIdFMFe3BnF1PvmVwV0XV9rStF0axZsV6C\\/gyE1\\/PwSlYOERnXldWGmiGu9dH6OoWdrqu6d2zPJ1mur6tSfKjPzHUF0LW2gMiS987sw0ODA4iMJYeLlgDWcAiEmwydqOEx1XJL80RsOeoPNMnPfeEDsjW+oztfASUxSbU4n9qCVNS3CzoBWGAOJ4FIUNcdrxKrdQ3o6c4MxiGaf6t4hsjfWV8ve\\/ecD9rWwz6tLcdD06HgIoy6EPkrhzwgVBkMUZMukEeHbPcDhSjPxcLgcPPl6taclR9SBr\\/t3n2861pS6K36Xl4lwWCvWyMUWgcRENejxQ5kq5xUNm\\/hx50PivYPdQkltxARwcbp0FePEM7yGAAzbloTeGwNUnvKwhqziU+X3Qzcspoq4PlfZqtVFPr97+l\\/4+1iMl5jzVOKp4qfwipa8zg8a\\/07C6opXOzjlW2VlAqnTj4za\\/fKShYD2Ad6mGpBBJzIVPVV98LijUvrzsstvsAeqGBqWC\\/FcNRXZpq9VQtraaZ6d\\/KpLuVul0PcHjAOjFIxnaxqP36ewH5lw07iQ4xOPro+kWB0HVcW9bPrCQO51JJUjnA6Lk2XwspVghMNnX0cetrN1F6Wl+BwjozcjwtaU9ou6aqqV0c9A3Aqrc03svrC3HyaXtqjsxkPcwibBlAOjjGrSBw6C85fRns6L0ZNSJKgp0+Oy41khCAXu6rh+ezi6KAOXasqoT23xovwOjiSjNwbHXudjVpwLsZ+rHT\\/e56gIpVgsJ+zdD6m7KM02Zd15k1yPlta2oARPT8Vu3ycSUuH\\/oJpooY8Ge6VYc9TLsdzBrZjuVGNeGcZ+\\/UF+xhlL7dPg9rzCGXKipNXf5PoZErOp1GES4+P7hch5nunz5TLbaAUIitqeuTyBtIPOv5PF\\/KLlGWlNGQ\\/BkS\\/pQkqwnuR+MuRnIYPWwoc5frGMApT4gSrLB7rE7JH1Q+N55+lU2bold+Blq6Ltvn5uHiHgII9O+d5X5Og+Wmy7jw1xa1AK6t0xoHktTl4LYPDAO4mBbF6UvobwioXlfblWm6SXZnyE\\/UaH\\/71k\\/WAaVG8JUimn3bJPugccWJUKGQKWb50LewLmI3q8L+7FK76kdJ+tsOCYA2QJlTYbv4S1CgbWPFyph6M9VsjfV4utzZti43A0qc40zfNmdsYj4NDsCvgCYa6zNjMQQktjwpUJQuXUgdgBEEoJkwtlYO2gacXjCYBbcEiNYXpYk7oUemo47876FRSPUqkITD\\/Q8m0oN0jz3SuYYM8MhRmGFTXtrQ9DpT\\/Ge+AvrvCg1E2zTZ\\/t1YAhh1SZPZKNnrJSk1Mk0Ebs4SkjQ0TPSZe7TZGFktLKM0NP60+CaWcy4wiZgh5gV+Jb+C8oV\\/2F92r5CplTk\\/mT\\/XUhnK+sxI3Z1ymkp6HctqRBQsudqaczZqDiuJ8bZHV5X\\/8bMIUtbiwqlj91dVIVyczuYhrKr2K7N\\/LpZw7miCiKawkf71t1km6f2UPkj4kxpdBtZirfeugUHE9o5cMk1CAa9DwL4ZsWbx0vzItK6oG635Dyv6Xx3\\/c2y+umL+HbulaoXkblehLBjlzPtCIDfSLCeXAUnHz3xH7HRy2G\\/JSZxopHZdhAXu1yOgIpm7m0qPPmoODRgfn65ZVftt+Z37s+MVQLc9nAdoTkqMsHhlTJE13uhEgnuKIXc\\/TTDVwbceAg2UvqUL2CO4lSiNIrAuHyXdiRqc7t+pd2+NJuXAUHsoLFs\\/cJTptEm0O7H6qRcINjcyTM3oUWcxrr5GuKbmY3I7yiPsSLeUYvKno5\\/Gwx5GxQoIKlu6huw3xhJM2UxjUUInfRQUPutkQRtkcvaYgN\\/xj4INimy1t8rQqMhKdnqI3XJCcg2ieno5+hxtWe6E7mdPOlxzbcfC6kGp5QEXSPi8JaZpeaJepE5Tq042Ssnbu4Qtp2xcgPWxgdZrhpTttHs5Z2PuiSfztIU13W0grw0UzF\\/STpmCXKkPBrRVLJEcLjQ\\/dCQcdhD2j70d5PaB7RnbOu\\/Ka9m11touSaOXNvlI7p83qlgDoVQkRPv1y2H2ayG8r7y7pknuy\\/4X7a26u15UyzoCmMzARBTGNmcz41fORLFUC0dRckE6wiyrvjorEWTKk\\/OTZqjia\\/em+nodG1Nfbj96XwxuqoHEo6P0TWeCDcHlpuJQUv9h2dJCtc8H3lQZiN+F0GMLnCPC7AoPXUQdrp75LWHS1gjZ5us1x1DdbWDyswADUSq5oeXafmEF+gJV0JtPw4UpdJfkzMTW75DRR6EZhxMUkqOLuA5FUho6UPgj25aaeRgZidbWtRVSwPmyg7VpSfg9wSp2Ajfht51TySrfrvTGNLbmD4x4Q+P0qdWgg8wUowsME5nRpK\\/0JjYXGiJiHqXJNDQ+\\/kkBenYnxppVgNTQVSmtZhwCieRPtAoGV053GV731Gw8wlS7I+YicrQalE8vhH1EiMTe2XL6HZ8oAnwvcsyqZSX1ec4dCwZchkqwMQ7sw6RONfFvfMxWS5UjSo0oS+s8wmX9iVs9LrftRAby4rtRFqxm4D2MEaIDTGJaQuh2ct5wy+g3WC6KgQ8xUybt2W8DHDtyM76zXrIUZSpRCqKynwqVSH2M1cnYpmcFh39\\/hZBgYojheWE5FWAF0m5xpySsAdZKgg4YHs00MCkel7EcymsKHLPXWkMRa8LOCMY43s64JLkXH177J+zX2GrbHksRu9GBgxl6rSR4wxzQhYmmye8m1ECH8WRcYU2TO2g4RvAZTl71U4dySeAf50gXnAMK025PsIdeRYWx1ZEa8Tp3c7VFUyceYmsXwYqL2K4ceDqzEmirQ\\/p\\/ovhp4z8cnmyrY1Ys3iMgDjJBt8Q9h\\/usxfO6FiIXPMiFa1taY9jsloJgshQpG8X5enz8mSeA3MWBefg+3FZC09N13vFprIay+pP5PjEA2rMJXxhPyJw5r\\/NfVWUzMTu4izL2Q7IzUIYP1IycdDapjmBg0peOhOl83haZRvGrEKbhqBeZ7nvh2C21GA9ppdg1kTEhrwG6uRiN4wev82OT3K4eGij6Mwfm76NaKpQoXQzYhPw7z6ap3jvlr\\/0uJ5dJVcy1WH3Rcud4Ivys1BVi2niE5GnqZxVYPLH1TLxdLwY81NQHU\\/NGGer05AiqWU5dlyMnQhHXrp3qpifPpn0ygps6NZLGN2iyega+1nGDx517Ipr1nX8l3WdoDSfva3REcaGfwPoSUt\\/O4pqLifZrsYWrKns9519uWD9A\\/gljTnzyA6tHf+ufOfbkBV8THwBJm1+qHGDa9yQOOgpKa5JAra+zEAJogcqEiKFxyvfPsmzvZ5YrNPCy12CVk2q57csb16BVd3dBhh8GSY1PL4A8Nq45nKHmWf3pZCehPKZ1JSmYJAmSFnTTT+voZ2fQ9cf8e+3BPfwieL0tl5hdXcpifQDvRk1GVUglJ7lUozDwfVb51lclFWW3Y7LrOWbn9Xyw7ii66A8U\\/moER4oh1sHAzW2LFDsdaZwJHoWxqL6mhVPF9thNOkl06g+GpMh2Z9VelkkHGCS7qh4\\/tYJsaOM\\/P1TFv+r9bP+6\\/KqQmtsebM7kPM9pFQlO2Boo51GA9wZkj2ZsydjcQCv+7cgWVubiZ0QRnssyU+ln1Nrvv1+0ltNnnrNz0l4+kKNOZmd0Xm76q9fbD2Bj5ytsT55PqpK76NJmAMuAwCrjyquq1dK2Esj5EVpcAZ5QPXzOEEW2i+TcmhJO7jrf5hD6jieGWiuEoBMAC6+LiLyTaPn536H3yXn371awaenTktd0ucV6DTRgnsVrcOWOjfZxSqs8+gnAXTQGTPqNgFU67pommT\\/0aWhmwubLQxvnHhgO8JSLQzhGZtXPo43QkaVfIOT8TxFPn+PXF8h16yHMZASEYHegFBLwW2LByfBKQSO23J+m5eJtRlsTYChd+If0opyrW9JXWyo4uNzjXxekxSYAb7uUOpkx7khgg5vw94tzzRRr+hTkXNgSnG6W4QhIr1i2KGe0XiTXpdL91Qx\\/03Q+xD\\/aaBymxxGmfuvufD4GC78pIgMFWW75x0egrB8EbyVCEa7qam6HfyxByXEH9pVUxReWZApFrrp2HVZdU3a79RYfmrtRL0M34IK6bOLoXGhvkCWSFUtLmXg0D7P8lKOLklzoZyZlmK2Wy16twkOo3lKQ6+57mO8PvcFcIzBwyAn\\/GyCIMKQw9c2u+ZgmvxkZrucBiWU53vX8DGeYD+Wt1sT+Bz4bH7jxEstkCPj3yU8u6upHedh0Io4LGuljBsxA6\\/mahpPLTynxyT+E4Tp3iKgSJOk8ANwY9gU2izspfomvxPdjXVZUuhIura8GWhGXi4CuRMYyJczNbIvYQ8yIUZIV\\/hbf19HZ9+y3WfCjPYzU2dZJ7rQaD+lLPGt57HqBS\\/Ff5TGWK1oXFAIHSwsa08CJ4TDmDF23NnCGV+nCxxEH8fRyveL+PTwPfBmqqN0Vh5Xjd8i6ZSH\\/Zhp6TPPhUoP2m0dfPN3ZwI5++ulaBWnFNKLBaozEsC95AWXVnG\\/peEZqWwaJnT\\/k\\/AGbT6FWTbxzPhqgzfjvV3qfcQzAodBGS7Y5M\\/SdxZSLcSiGEWCyk4SYvTZ40YdkdQIf87ytGKuARw55fHMLdlE6mo4OABBAJ8grs5k\\/TUVEWYiRVGoJgWje4iWX8S8gPkuKoF5CIUCLzma+O7wHhWjal2r5DLGuQ6I5nUxJIVW\\/EFZEanirbzOzEZmRYPLipScQzFtTuUg\\/0Gsm1L+6Hywb94pysBkChW4F9x8CxX\\/QmuuKwGavGzWf2uWbPTELeU\\/RmXGgrllkTuqfXxvA3py825vTxq43B0T3n7L6E2l5EqRMG7n0DQwLHkms7YOKWutSYGQFpnewzcUAJXcyV81HEzJ4GECbCc2o\\/0gH1WmEGhMJYKL\\/xVyVqrkkoeo2MR0NmPozYnb5+H6UbZ9hcH92wiDg1mS8cya7gkCkq9jdL6zpKIhdlYlTpYrJfsyzt5Gbvcbg7U\\/aX5an2BmP8KeNQI6Ng5BsQ5hTTt9KkV\\/FvxWs\\/VLCLue4\\/wIVVi+SOZGUNANMUBSoIdoofp5ZhT44Y4a8r\\/ubNZIlb2QaV6FTL2Jqr+Tsk6DH4QX\\/Ep56thY9NV2tA8fLzFhuHzFyIDEgCNsc+fivtXOgGFgFtjYGRZ8TPuleYypu5HIQ91lSN9b15wnmi5oi7I+HNpugBkSnTciVPZTtMhHIWL1bckgGUUDrKGeE+VBRFS6kdVRvMTNXJRGlCyFkwY3qzdIXM7oAJ1IqvWB0PoSfzIfY1aZmcZMlGe3SZEBnk8C9SUHezQ6LBO\\/0jdS0isW+fjboljv\\/7Xe90lmNWf6Zvr6sH8yGF338Dwgg4nYd1386l9WP1cJLyr2o\\/i+aRsspdRlLvdQ9eIg1zYDEGmHVZDTLmHniOLf\\/B9zs0o\\/b+F7E\\/wGclak4wV7iPcND2Ni6JdlHTUleEvoXbxJqxCnEbZv\\/bY2jSJQlPwoBDcsm6lZ5wDSxcjcztvBA82qwGTcUwwbSa5E4D+UjdcDeGPH\\/\\/kRbPQoM\\/UqRDXPAAPzXjzHdynN4\\/pOqKQVBwHrTQ2TDKu\\/tCT3ZxRul1EN3B\\/nP6o7ncaOtJWfRcFmSwz1Gg2iPIYa6e5n8oJzrIJrat0SHwuRjxNnXFFl04i6\\/2qQAQ46Rmwps1MSoYc5R26cpn7ESv28bozvqX9DKhWasadmOOBWT27IIEDSaIxa8efSa1oo7PgCY\\/eJGgczYffdqb0c\\/vGOTVcFnFh9bcRFFPID+JtwWmD\\/X\\/bng0EMiBQOzqERg5ZAx9Odg0JBDf9+a2R0FU\\/4wgIw0kNnwGP06DNhJ0MBGXfXb5CKKfHWBF+SFbeL8GdGTgwSnUT4Z5bWjoQAsei4YHR0qfmlC0Dy5vc+xvH6Jw8s+wvGAse4Y14WPwEkLuadVqvwLV4hqN75ZsCXryrhUMtWBwGy8ce3FjsRol9lf3x28tLZaNeYBxI4pVgk2PO8UDgsU2QgJvqxwCW3NwgpE7RTJbvQNciCNdVeSbDw6BtvWNtRCy3hDfj833KbFSwdvX+iNzAYz0xzs61E4k3ZvTIXe6dFvkBUeNQIWSMS5vc6\\/i6pLUVPQx8OLTXIYF70Tl+4RFzSc26+MR7PGh7Ys592getlDc30stYbzhzpEAzU2bJ8A5Kn4KNk1ZkdAdzCDo8xkhMrNbwE+cxVERsVnChRT6fGKJZItnNw6bhfUk+AgUM\\/irMYP3I7sleX8K5TlZaefXgn8N9v2SIgBXfIFq8GPOi+nyr7NvyWTllosVGTZ52ERK21QTr6EWmWVt2nGkyXUbN\\/u7HGhke2UqWbE4Q6XaZlo55PUL8HyX\\/z2k1taS30x1zwGL+pWVbM5ZC+kDSeRnyUfJ6Q1ikMSMfqBUdA8wtCz4jCQio7Q03zBpE5eqCyln\\/mzun1YkI\\/MSbVtWjHfEMeP\\/qLSFEB8Utz4Q4ZLQpNQeqt6zgn9aOiXQWhRlpnBGfNtwjdNrUHtYHqRULHXeGW7yMRn5mXlgs9Y6crPy1SbZHW094M8QndbzyPlsa3EOmh2Woj6TIWHuhpWJDi2AC921Ios88hL+XgTPjwFEsee2ToTb1CphRATRt4hIEZAs26mxJklBvEqfSOOMHcgNT7hzRj8rvyYJ0o5ZYw6qgTWBLB\\/WSgv771HamFEj1du+tZG8UfXZ\\/zIyqRiWD31HGjNHz0WLkDVR16V8wvjwUoc+\\/MNhHyd8xqMCELmaQtxkEYBd0\\/A1IsTSDevJ\\/zEY9uUvLlKJc5\\/2GBbBZakLmaAqp1LmwRxh\\/StFx1AmIqxwbMegl0tIEc53kV3i3w3mSTKPSWXb\\/6oYWkVCIIlg3j9HJKYkfrWCAWN73z77pSZ2lQBVCPTLg3smrvVe4m3WhOc9rGfF4TSxLeegvxA2++oAeuEX0m8NgQkHJiI8NCulyrY7P++WjyBeMKtBYoSn3FbQL2+fc8C\\/v76LtYQwVqLuWqySm9G1SzC+aUic4EDlwdqnCApreKrSRg5bDQsxMDd16xEqu5zvJVfnLHxqSFFJsqjyuygmGEYTNjFsQfGkHZFYmfivrx6rrgvu2mZGQ3fnZJ4hhJn7d67HE0Mz801fYEuRXnyfH7Q5kbuqKpmoT73Zpi4K+KYf+Y3vvEjt4Yrvlk7b\\/0gshX+484pedsR1Zx7OVZDmrL1OWQqZv8k6vJ6edPeQuNr+0Ig+qdr6PfT5z\\/fle5NOtQsnltyREkkZj8DqguJAnKkJdiDun+qrHJvdVYosqDNj6PIhdHzpE8EHEafNRjiMxB3EBZM1k57lEAmwVdsy7K0mNztxUK8pVpCFtovVIWLap9vy76ZHaf\\/aOR59emiHXBy\\/E2HIHoWgaNPDcbT2mahZqXp5dM3Ng3Idyrak4UvLMrZgWsNjxJq6hBhbau3utJpR8Sr7a7M6jvgmtFNpKcMtFUFgz9hfLKDKrzk4nzREFuDv4VQdV1k9Tmq8atPYVqkFZit2t2net\\/jXKXXqwbY4IbPZROQs8TtJoQlzkOcbTDrXOjmCq3JliLse5o4tsd5V6R0oRQP8RugOpGCcuORfESXalnoRgB3ix7zx7n0TOqTsBIeN2FtHzWzr7Eb54tgapc0ejMdV4y2c+QQdLVtZdL1KQPXg\\/l+b0s+ErM1ijWAMQI6KXMa4QiRFW9x4lQalFqCpz5VV5r6DPKx9h\\/LqBGeSjIpWLvK+5pJTnswcxSlI6Z\\/4xXbgxYd\\/dzYMyfcVVio1kM8mJbr9gfE\\/jA6Yg\\/Zk3dpcCi3V4iNbceCCetCvpwd0eI9YcZHlmH5PAi06A1PRlg0hyQtRPKH\\/6K+HVMDDJeasE07T1Onaj9+Pj7UiQg+w9YapMFCMt9IwSwRzd75EXQWcUQxCj+brGW54vw9bV6Pm8Flh0UPzk0x48C5VfHipb4kF2evxJ5\\/iHAw8ajWOn0T3JsMRG\\/x7OR54K\\/W82PFGogVkorp+Fhd60N8cQVP+rjb4UTdGj9yYDLnGm+8fh8gG+HMKRkY16Y1nL24ENskWZVoqAGtaBKnxEgkogN8D7mzmnX3klIfeqKI0LubaiaDIrhkpHRivcdg+GfeXII8436VMczz4IZEpW5SS8L4qU6EKDlGeirGU4oqbSiQBsajesjwf3cjkiE+2YKsUKRJV2Xv0LUqCykEYH3eZ3JaYFP\\/SC4CeIcsWzve4nU0H4o0ljo6irI9Q403FAjLleFoihkeCIifLsq6BK\\/r1NniYEbfOEIRYv0XA5GgKMuisa0wU+o1YrT38nG9uIhGYBkSIZnF1A3canmAMjAUhgELKnTF2HFeAe\\/mya+0onUdbtEnEBLm0K+QXSDFYW83kcrsbbASJPUCTK60V0mZKhLXcN7drBcMFiPASxUWyILCN4CrkJ6ZBSt5RhlgiFGwss+QYqPqNGI+SlOAXlnSXruI\\/aJHtXUrPp+uz4+qvInfnMK61ZUvLXFtkgsLLZUa+dqkF0By+uKawoLcGMe2qLq1GA+O2N3U2wOOGQP+JcIzFyekikINiH7u5Fqn6SO4gal4FqbHNguesxoB8pOVyq\\/uYG\\/zzPpkyZSEn7qwT4IL9YaNtaFcXgq3K1TjX8g7kSDs113yjKm4yx9TlqN7Y+\\/RX16RE64Mx0X+AkJLeNdaCMPv8CxTxflrgpbiROVsCwo4iyJY7Oebn2wtNZKNPjkLscBb8N+RFW5dSx3Ri0OD2G6osm61ugqyzoFurGxx\\/axqQNi2EmPRTwlZDsVFG12eq8kFs13H1srzN+bW4\\/bqJTKaj3GuWw3VVEXI3x5L3lVO6VH+vbu5KoPOBR6+fu6+TeFY7YKjJUJDsg8dR2jFRcXy3Khz2o7djGGCyilEeyv1JMtGguWUSSH\\/Wpzld0hTzcGX8eQLeHRhZCFwrOw53b32CgCkEn3q6yyDsLWyJWIjdVC1d8KJTVQmBEaiyek1bjW3rb5YyyNLLPYMHbb37KhRh7s4ARUxd5Q4iEIS7e\\/siDYZA3iwcAaiOL2aiCvqFmu4MYH5NhnVALfm\\/AKX2nEYPig7SFAe\\/GUSb77oXpGRJuIZBCLp3+7\\/8y4FrlvgefFmWn29jGWvgvBn14ZzWFzOCthYKPh7wadmKKawhAvGDTX7ZmLqjG99qDIEJBCe7nl6OTPoHTQnyhHlHYhjTta85B4lbJQSY8hcnNsdehdXvX2XhI7x24+\\/rLxouhEOWp8IqB8t5OQOY0\\/cFGHeEm1\\/wWKMDoJnfYbKByZdi3qIfSRYbuWDIZ5YyfFUJMMCP3YeAqs4znq3PYFxSuDmMXkkZbpWetB2BuOWvRbdV0wpbQzKqGRxLz1LAGYX7OkpCFIJU0B\\/J1TwpfevmSQ6\\/8vVfU0NE9GZ00OVbHxjSKVFO+oJBZgWY37PojKqpZsxqKgBGn3djTWqvT6OAgCD\\/QsjP36yZdtska96Fi7aRc7gF5o+e95MBMDm4pKec7r0Cvk9wd2pMJfE2d+V8ZyRrHmb3R7q4Y3apG+vMlszip4P2vTjhM0+oLzCyHN6L1KA99Rm6uD6XjN2vScVG18CzQ\\/JGUH+VeN21EhQQMZSSBSjXOpzIccAQbq6SNpi2YBGhUD9nZBMXoIWCQ6r0g0HK75WtDu9g74GNkXK7iWW5bcSD5CnAur0inOnPUpjg6KS5RbaaIlqdnE0Xq6+eicyx6lSLVFG2x8qJcI3\\/9AtgQ+KJbgXXgIMzEnBen3tz\\/X56VkpCqsiWVD\\/FPH+i05HPyUkBNeM49btZoaGPIBxhUzQEhhS8kLs9eaextRufER7tQ6xidDCqg\\/eDjChAP+0MtvHjUXUfDLv\\/Z\\/roKQr\\/L51LzKmK5bx1U3pOWTu9TchKYNg5U+CfJHutZAVq8of\\/4Pf9Csv1OAcJcCGHwY8L5+6OZXamQ7pc8MvQtgX+qnOtjqKxcfuwLq\\/GcfX6Sad7yio6nobPRy5zcaOFZeFGcyXFuDM5UgkLoZ9mVKCuWCJEf4ztjHla03SkYhFRNjlHz5WQvaopvkoXcbmOBiaswGgM77rXchrBmW\\/eEZI0jufqmxdX6npQHKwjoyXCIk9KImf\\/AH\\/zQSnX2Y4jpvhENWZq0Esxs3Cog8wwcNhNTzam9cD5KBU7edAjiQ5FljTsiGeEfL4e3DbED94EiSKdBxm2yO2gd5UWPy4T4OIo+mN2qM6gpjW9pJTg5IyEmsxvvgxTarTRe3hugBVaxCBCUtNit0Y8hPeUb1MkGQ27SzNlGGx5I1EHfjigG7EyVRLZ\\/ihPEpa2c9sV+vsj3w1SfQ930tWoWpB2CzdfqOiIkL5geyrbGDNNsoU9j+NcGc5dRd6HJl8dLEWEPwX3bLSDY9cvoLq\\/gWG3fT12+vwjWDndcWpyYNJBRxIumGr0B0bMP4C1m7sP5v6KaqSgQhW4WoWKwqNMBX02qA1SWfgRIFCOVqrznrK3VfmiSm7ahN0E\\/b4Hh59E2ZYGvlmC9RmOyos1XwN2RaafsAfeKcwfMKpd0XRouE1HAUxwNO8op7Kqlvep7oPxmZU3+OgP6yHRZgm6+I71TA5g9BI0hcYRkqJMV+Yt4N\\/RIE0gRarREY\\/SXUAEvqgdsmdJ0t89kod4ehwTIkgOKG3v47d6iQNK+liVcNY+VeEBnntaj6O8vldGJrQv7oErzYsNvMHjVtJWMK4tFCLeq6qbwSTP8Y5uvykraTXu59lD1U80gxf6kfkbgkAplsIvTIypBX\\/7JOGrrvPT2tX7XHpT9yAL2ERwkESQmYjCLZ4e5WHag6Pp1YPqu52h52BpgosdaxnX0LMGQ2LnGuvumNsmIr8pHcr4CSIXdZNcBYJZnMw+FHnm41Ppm8qCcnSqGKvWOAeFl9znxUXnhWgBbqhPtCBx1BGOS\\/BljP2y9JYc\\/PdOV9jb9zFT8eKHN3ADW03FEm3J2TsFzQN0iz0wS7l6wmEF2yrM19SNgamqfzeI2Iw3DvZ1Vij77I50iuJCw8d4df89kZqrTN5TOl64sMJJ0WjSxIwJEIIaGjsz1l2ezxITYk8di0BxOl5MzuUrC\\/spwKsV3A2shRNl\\/qoBJRkamzbhKlKEycbbrhrmRVtTGZebt9DqSzsxJ6Qq7YDrnXFzQ8kTibsugNWvJL4vTLz\\/yVZeGLHyWeB17R\\/S1xTKwWwgP4W5Vy6ItLHtuZdM0mKwsr86DpDjTB6Ejf7BcahPSPmySmEUnRO0dPhv97dXy0nEu\\/THl6v+AvV\\/5HLFT4\\/hRNKoGsvogeZeeJLLefpb31dvugMNzaIg7uYBbyQSmSopt3p3EUQzB3aRJhLbZs2\\/c8XeEm7195ZG5j1SP0KwjFq1+csf92K4q4Z\\/\\/ma6JTIHakBNJjicUfbxPRIs8QO3zfJwdkXFttfJ9LyNshzr5GmhD6HdzISmPZRbHJ7ufG6saY3OxP3C0ybUpACCOBCrK5bm6TX64h93hyZVxz2I69WyshQW88llbGBvTBSc0ipvgAP\\/v\\/JLZ1xCoQX\\/CICzSprpvbJaNo4wBH2XKu3WaM53ydgKv4ffktNAFYVRPPAgMLpDvrfNZlN4tInv+BSYg1SJf6duPzX5N\\/lsst7rm4FflVi2Ms9LFWYFXK0MIARfPNRi2BfBaq0F53w9IsbpQy9AHXOkWQcM3GVMw8DfATnjQWthipR9+9Bqwwqc1Z4CKgWLAEkievWqdcLPaZZuE3xXQlEajanfQE2+jem+gdFaTLIZuFsSehImb3LQwK9IUiUKZ95aicuwBq0YLEXoZeezn1AIhvOuJq2vTU9Xb8VkIbv6mKixtX+IzdYc0BOBBmfFdOqPdbIEyzUuIFa5eHDx3alR2En4Pwefqc2fLmXYpw1U8\\/SZDXHYsANM0lX5FpO+yLfwvgCR9rGWGcZSbKz093SpVLkfBcYwZfCPWBPkm9spjK86G5jDDX1poOBDHR3u8CJ0clxKHzZSSb7AiuhmMVwxIlHtHrfWq7NTpetexTLEaT1v9mkLNFsw3I73E81k8WCcIQ6Bi+stjqCXN+\\/GuF5BzY4Go8aGXt4dhzitnhMeKaE6CGL+AtmFbKs0TCgBB6BnCbR6m5hq32B+7KhHwOAmSWgpsS19CsrtLTWHW9RJhXd81TYd7FZ1FytgBNkxd8j8iT1keOA4LCOjdY7XA36LSwQd5VMzpTrR\\/ZfHNl6ay2luu4h5Ybyxz1p0Gh+2JOkIacXEkdsYuC01VBF345AfVCegecpyoIlXZrfwne0VQguKDM2TrGcoWV+VugJWHyvfxxjc7ATO2AkDZHJznXlHF6hBsWJov7qzIkpZDXZw4ZaDx3DnoKfnSxSsDhC+ewDAYkWhMxJWflq+0Pi5NhpYMZPegcQ3\\/egtxCDy436lxZfXms99JI88qa4gQiRc9EBN8iyY9TsubaaGMIpo14tBgdw8ifiBGf4vX+WhQPQvTakVxSv9hYb+KU2z15KMhA9NJCV5VeelC4rJBiOyfDPJqYmijYyuVoAduzNKjRLOPAvBt\\/agFbsbL6qwZ1PzmTUo7itQjKvljwhP+B0eRupFpyMKb7ELxElN9EnEkddfwOto5dx14nb+Ug+ON3C37tSV\\/GrdGFPwScwiwzQr681dR3ijQw7msuA7tFbPyKWc1MYtgYU293uXdbptwdHFtKKmkbUm3KvVrucPEBuaSRgrsW49jKBTl+HFgVYcV\\/11UYwR9jiItHGRwtwdwWxz1UBGiQdKddYF5a6XbWTo1oHIOnY7tBt80+CJUYoitPhSCI66Kub\\/qsxl\\/7nc7FCSJP4rq5v4Q8l9DYdmc5NDXiHHC4vkM2S9zfE8N\\/CbLWdEtN3NqnyKJ8C75HNis9aCQD6XRsDAFtf+NlxbEcLhBJkdgRsyDJXWC31a+Hm9TwdzELh8G4EYz8P4HuskfWQ7uKXak3Mgs8yU3zScxX2O0Cvm6IsQzmnpiP5f0bG6L5CMMhhXPYN8kzhLSrTmqfUztiC5FS7Mk9KQc0hjaQoTHSY3qBILXSlIrMQeYktq2El7UCHe1nQn2\\/+u3ujw5292E1v02Lt\\/2LbSf1eCKubV3menBIzedQClBSPzcFmyHSeMQHd7vVBbhec7adEBvkdBvxaMxBWioj3GtEZQPRXVtWnNymWv0hklksLBB1Kkpp9RYYGRS8GsFiLwB6WI0MqMkyOX2iNnH6VO5MlKLPadGAR+LahTg+tAUGWrTIwK+ZtYZzrEGy7uxhWV5euL8tU+yieU84HY81kirii8wYDgkajwl7YKkee7VKySjKi2ytc14+DXAddK5dJAUg0EMNch3\\/1rk4jsQBFSdcjzsH4+TQh6TU7mJyakobS3XNFZweMfJJVgSkhUpt6ABBMWLu2eRD3c9HhX67TF2COF4WDV3ZN6SPsDGBOhrYHFKq1dCHbNrKC+S+apGcc1zdrktJElKSoTVtb75cwee2IvoxTex\\/GX8Cr3zJ7T+svtOMGowc6fBHifMbc4UuyFpd+c7OT60RHib5mbiIQ+ibas+3Q5JuNvljHiG6xxn+JwgYM805Ww7wlgzlOEtZAlRwrtpZmysBb91ToSWTUKIEaufGStwEalyqjT51L5mzwAXtNQBFomatTEAOdUoROptX4YH\\/cSWYU0nyE7vPH7I3jylpTjmekFVfCGJm9P1joCRh4nirHfiBNNxRKb8zmHp\\/t8fp3BTZUd1b+qLuMa3+jbYDXw0C4zb7BNxSJWk7pr20UGKWV4dRWOcTqd8Qo3JX3Tb94+BqF3nzOrEAV4aIHpScAVJXjILGwt4gWwGg82eXLxDIC1fGPqveKzJ\\/h8C5lbO6QnEOz+Bs2RqxStUAppUjIKooghRI34QZNydx5XTSCvsWlu+xJQK5f8SAeZGzeZFkN0APq030y4BFP3oFIEnr9gMsVGfN\\/cQfQXo4uQzsr64fDx5pLAjo5OnX6NO2q0mISgZzv0I7dnPIrApH009b0sAcePjMmKZWCn3J3D9Abx46v70e7NankaY+wqPGIZBN4UqhKh2EBZYsWaq9bCrY0Blhc295v2aUzgf7rQRR8DjK\\/Cq99LaKhmq4g11OvRjB+ioE0lC5XGP0KcUai46ZcVXx5vragI2hXlmPxrB9aL8e70X8ir78rDN7qFxKgSgIaqSMOwl8TFPwDB7QSAQKDXTxwn1n8+IzCEWqaoW8OxQr+gymaYlkXNxxBrJjL5n0fRxGVbpKc18wPelwb9BNFg2WGkqkitOMW3duhyoIpHTfnQv2vFuJs7NkPkscbAmH4mjzZ2Wbkc9BLb+I22WHUfnsuDbg+Q0rrhjKl9Nda+P\\/uP5CtF5HGyxe5z5KuAlUS2U8MUAZ23Iarr\\/v7+TKPyG+WL14f8q0NWzizmr+IXYb6foDzvGdG\\/6N+YogC1l2nvP399ixG5f0yzGviIN6Ixdw3WGUxEFodxthXDcz0g\\/vzetwBYboM3ZnHW01pXxz1TYZ27rjEJ6SQaJgyKBME7bDZvZBkmfzs\\/s1tuERprs8cwQTyW5RiM9WMn3ySYUd7G+\\/r6OgrdRB2dZ9RhOqF9MdypN8mB\\/8DkGtni37s319b7NNpEPsXkwydDtvVXvJ+jCg+rsnI\\/ZHfx3ZlNrZN\\/7Mpfaf7YykE4Ag41WIZADqxMvRuRRjNxRV7oZGMylNhofjFMHMvbNLWWN2ts4qmSlmZr6dVb1cg7XoPvdV+GjJbqKpp68z4NWHJg6TUjYjB8pRzbKH\\/dABEhDVv8mzNdr4zyXeBt1nsHTB1kp\\/pGFRgFt6cG5iee8IWmDylbeV1ZBPQNmsQffWyKrxzETGrDNKlZlCGsfcWHsal8eofs29qKxvO1De0VbTa9ul9oIWqECco7NGbxY+cwYk0\\/SvKM3spalPeeChHaWZjq4g3im2UGViWYcPHi2qyaba0J8o5cTCKnKla7DnpKDED4PaFKL8gQcibRbBj9OnsM5okH9e03snUEZYtbd0jeEJkrq12hALVkjhc2jPCeIH+qREv+ypRVL2VmHzqCGHcNs54uwQw9JUCou9f3B+znv6KMUjZxQS9GNXVKLXw69pHOhgJ9Q6k\\/UIemTeNys6VmpNH41RhmKHn+xKdmAirUMjQOjBNjKzr7C80KzKFf8V6TWzACl4NSLV3FaqQevw18CIdxj0Eiv1\\/JeVcGNv5sr47i8ju7zKKZLip6YsFm6pnpKnvshFzR3gRZuvCM5FvsqMzZaNhWpgyanNU+j4hwLDf6uLEjmwnZ6D+HTiBl86CRe6gE6YLrmDnvKnNwHUM8nycbXcs6PovsRgNs3JXmWsMBAkzh1HFYQBFPSC5ydAVy971xItP6KFroM9uu3sO4MNMK8r2UqzLIn5b5PzikSTZCdeyaZ\\/DcakktfLRN1N0j6KFuVDH5UGfWLZUwjo5SfOgMw4XlTaZa6RA9qIZvKS4IF1foJkoi9KXOn6ce9KHfYSoWE8R8qmVyTYHa\\/Ob\\/AVBo3VWEg3NEXZgWiF3fpWM6PFur174bOCsHegsWtAkXqDJ\\/NvOJs7TT97tYVrm7kPTLnT+wetYVIkFbnX3nnJP07X9IVas6j5u4yzDTt3HP1Y+qhppWnlEyMuyPRm\\/TwozyP70hXSyOrLqQoVvyCNyIRZnQRAD0GQ3lRP5i0+IurOQdz3LNu9z\\/yvWFnCzcln1OoaAt76mYda3OPzaEZCDooK183+LMT4RRvCJpKWoZf42ea+LgPsOboaS+eT9g3WBD+uGZEo\\/0bpE6TvjfcLSZ4s7SaDiS\\/WbKtkQNrwp9UCrJHt6K2frmlK930M1B8EB3ZyponywfQP2zT93ziw4vu9e\\/4fc9IJ\\/Nknc+kO0PEX\\/R7qnLH\\/XskEc5KlQ3\\/CkTGgGQ1eCiVAQfNhDLIipDIK5d7WBsKfystUki9gZ25knB+PYBX0LO4wVTNemyQzO9v7TvaLMnkdT+g0M8QJ3I8COebPA7ns3d3dmOgIAEgX1RaPJik08m2DDWefSuqlNeaoQNgueTbm+fDGw2BGtpD\\/dImiKD2BtNS7HvjScPOcUPAfEx4TntD1E8d\\/EYbGe9zEQC8Vq80AmvadjwOrukpc3l\\/rdODqjuICvOPT+O6E\\/J3yVMYWPCPbTS7i\\/S\\/Ml+TRWP+0uO8O4YTpmedc5u82jNTo23PEmNrSC7yGPvPGVQ4\\/IykcRItPzfquRwdyNzG+kBOT3V1thzbq8jE0AUVxSgpujuedyDWhbNGbgoSfg1CfwqHjXRpOIy61QimCTpthGcldra\\/FvY9vVbA5SHd0TdBmqv2uAKnvGBZyUg2OEaVY1gGIvORck1ZZMvo56a5YmclcUzFaJEHKccnDF42Wgj\\/ITkU+sh+Yi1yF8Qp4FSI+Lvw7hi1ciripqNkzBW6qVDaxxKO0qCdSQMCD4+mNG+URTe948G\\/hglKV4K1S0Zfbwaxnx0NH8b32NUxmnj1Arz+3oxC4IDU1uBZqRDrqWgGmfA23p9XFKVSNPfSRZHY8r3a0h6pwdynltSeUudIQP60qlnyLYrEi6aMI+Dxt2jSVXjPIJmd445djfEpJ6xCAWFcaAl7Ik+yq8wW46Az58m\\/gGZsCR3gvvZ0smqRraJaj7t9Q2a5C+tIIkmaTZwf5R8O292fvcKxSKFAogZYhFhNe5NdpYMzyUnq1UWCAcSfjolXiADgYimzopFPQS5eripMY4qYOMMEIlJOXQfntl\\/OaDK5Zk8MT+kciHNBCo1CMnIReejHdjC49GX5QbRbMmraJxhI7vBpZv\\/zA3zuwt6RAa0G+lLOQCqRoWBGKc5WGegpnDEFYmPhLGjXdddRR9QRDMd0yTLI92zmIb9FrhcEvqPbPsiTD+mIXbKE7rfk6CJ3HaE4IK6ugFLWKnqbXB\\/HZuws3Y\\/IrXWkxddVs0LZfP8pnDqZrmryLanZw4Clcu0joq8tztdGB+NKyj54RmYpPgKQLZfWH9rgP6xVK3LK2GtwC\\/vXquuOwZMOThU9JQ4B4bOgDS3VWxAvwMOkNfM3WfA6PsO5raV+hsLLW38bf7qrpkdl5mDSZNYIKVjY2bgC\\/NBZoiUtkhH06lbIC0WQXEJVODJg\\/xjMvMPU7XrWfkSjpoh09\\/ZkOI1aZArxJJzFoeUkderwM0dGeQpVBOw9bmXnAOVet2FSqOvNK3iGt4SO+mJv9Eel+grmmWxSSB5lGIDDZ0WCXGQHo084TlJMVHI6zXNFRsqcLcWt45UQupiqWdHzYU3O+2HVMMzis+cLzwvXJi4TOWaYjuxXf2OVXY6PW\\/K9wDh05VTZBpeWbrUWS8RAJX6O4tgoAyhqtyNKq3SkBIUg6mcRnOTZjthVyiYe\\/X9clu8Q5zT9I7w3pe4OOWrqBe5zkdeGJIIhassqfG403Fk+wMHLSZ+jnuIXFtRuMj3uf4mJqA8vf0dXOrlCZK2GqkqtMGrlDw60+vuAzSzU3hf\\/ZyYCS7BcbRo3Tpe8LyByrU+MUUenHVER3KXHIpLGH+G1R5FlqRV4D5m3s4SVarPSH2eNoc45FyeH6Y0gmWZqUS7TywK9crw\\/jSzxCFh3QTkaizTF0wGfEg3k5E3eniWWlw03AqSTJhhUY3ue4eIakLJCntyb+vMcfl2KwhbHWyBLDi5Ejsjo3JacIqGuZp1Q2XkrApp5tt6ZWYOeO0khrVsgsbkegXhftIsXTPdlBCZOkTJWsOk551UIo7B7bfIH9TrHVuCAKlS\\/OHMd6p3TNsQfDbaat1OyR7gr+fgIMS6LucdDXTRBPYfBJRf9AaChQDLYoZdglQ6HYh46SxQKxdUmGkIRxl2zgu9xxBPA1q2r1bFlBiSfrGlTMTsiG4A\\/WvOQFXZg+fF4tEqHWtpW3pykJlbYsidGBzlNZMl0j9P6ZGpxjD4AQ1EdOGEz9Vgp8vitL8Wp2MI15jHuJ45VdAcIdD8vdk0AEehTPPsjbEIlRD8HKrufrBTGWs+QaH\\/3vnYRqzvhrEzlBpt9uai9FLKgA2bPTFHrKqu8SoyomLzvWqjNEEtu71B8BdFRuO+BeFeTzZKUCFTgaVK7HgSLZf5CfAD8D2p0o8xw9cpezUdILeUVGmTkw82iKVg7aWFV5pgImip\\/z0+PrkXeQc9lnqfZSXlA6vS\\/mc4EVgzBu5LjhLoBjU5cNkyCKbDhcqz3HLtA8Su4S\\/T\\/\\/849PlOYAebFMELcxxXhl8xMHz34iInbrAljH7OIJLiBs\\/1xOuq+zowgGZ3DSojkMmy3\\/ZUJUPopog0px3UYZuraKHv7sy6l1Qm7N\\/6mFKnxHJ9Le1rsYe3HHcmzanDql5qb65+unkCuPzcm7dPpdrGf8cyFMlcBTfPpq7oshbjF0teWQwcdrmfUYZ8I99bbTkVVB7d7VLFMsXIUmasf9H2MRRWmTQEgmjf\\/J1\\/3ap9rXWDg8wcsyrUGAvLfFXD6JW1wRxntIH2Pf+z9uvC0X0dTa5LCw4c03op3o4qJs16zp6sy\\/73SjntadlvkIAek9RPaT6Bw4ZPNF43TJlIg\\/BCfPI1NDMhIHzpNpG1qJYghi5IwurZkyG4d0MZJRDsgSyJArD7O+H59ods0Q6Qof9GBLr+4ztZP3RcQcMdCaPSqka34bIfV1VaIqB1f5JT5\\/TT0MEl0+O+t7F4HxKib3D0NbIr3sb7aryJxxE8S1+r8O5NPx43\\/MaEEv9lLEPONUI2Ovmy3cO4M1\\/SFmkc1\\/v8uRw1FTYbFeSX\\/4o7+8TxvBZRNzoY03696GG2YhJoHbb6Twy2KBNLqg47AA21aNk1IeNFC7sqmxqsany0EMXvTXKWscWi5IVZ023VHnSK2AcwBFly4P1uToPPGImz6PYW2wfdR+9oz8zQBCOkDaEjV70QqOVfQfaCvVf+hLRc5kU8gLvd4wUK8Nl2QPSB0u8KJdRWAe+CIL+KaZh9RrFPgoWRv3NAHygNzRlZ0oE9iAnU+MRo\\/Sd6lwP0ZMuljhZPQ36w7eEBCVm05WhKJOYqLYgNH0MzWsp0542WfmpWvanyMwh6WLRvKa4ozBcabKa7oJE8NtBw+JdobJwwWRimFN2auRd3Ynp5PXU3FK7+nZ0C3TWFEeA8ttWyyNmUXsJTkZhIrGMUIastg6Kl3h4bzfmWUNptLOhFqupy7XRShD3ufK7ajZ5GChatVogfZ1Miysjx2i8W+UlRpvhGOJ\\/Ebvg9Gj5f6f4OgMzM4m9XuHmOd9+9kBCD8vt4iNBqUgy2x29FRST0iOm3hlGGMccv\\/znBtJ5KiJ\\/aJSo4ThM\\/dWd8JFw6xEU5Vk+XEZ674+IZegd3HSEVzDmZwgk80FBG+q1jldGTxKh4pfnIysSHqkvwmIkUKcslMrGaUC+v3nxHJRk+gU8MxjFXooa3E5lxtLzzkpkphTJeIvflnCsmml4\\/zkaiv1KjLYCEbHkzkNIbGRczHXPOTE\\/qmsjDDLuDktB\\/0v8MEx+7Pef6vXf1IDH0tmpisEZFR4oIdn4uOnaDoPUnYif+PZ9gha\\/dfK383pA3fYt1OJlC6awWsbxI7iWV+Dm0NiDuhMFjDVLhYn79jTecvG2lN2ZyGAiCQEJf0GuPcFaLzCmBEMUOW0dbdgO7otJHQcOsbdeh6cVvjuHSqOQvYHKtoIgjbrl45WI7MEkyFzWN31cT9sBzMf2ypPMwCMHJOvrVpPajXA+wKTIojFHCFvOxjTkfNtU\\/7c7uSxx3VU92nIsN4ud3ZCpLM5IsVqFYVGaVPevElcF7e\\/mKuymxx0KoHz3a54K7NFd1QJOaT+M8e24DCDaX6uZoS4CYnqXAwhkq5Rsv2w0KPTbNOz38\\/HsyFSlLjj271387Dz2KcYaZ4msbPPk+5PUfCSynlhMw\\/WQJMIgNLZLaM0yCIYdSg1dEIFqQtp2k5i4MXe98pV\\/ZFHYAwq62wH5hSvjhZCCB5ljEtycxBJnDLB+BKdoT+EdMNxJGfS4vcCXNVowpUa2jrVd3eyZL7+6D472FR\\/yGQZ\\/j30HdsdPN7hqhmesPEhtPvNJzeLOnn0fcppeS\\/b5jKkX1bcfp0ASI08ngdLvYPQTSkku2TEhQp8cQued4bDsFEwCTyj39nB5xz+bdHzYhyCMfNj+eg5r6dIBc\\/xyqkITAv5fqh\\/YTHAS3kUcKdalzCJUTGZB4FnPwZA+6\\/yXfzo7breDhaCHgMVWYfAMVed2R0aT9AW2s5jGeCLqWkOT8gkRqRBAy8gKC6XL6ruWAMTQGVPQ6pLZWvXdz9WeOO31cVDGX7o+AHHTpYQBhdHmA3l0ZmDfWZQaP3Z04IXkfWJm3H7CichRIJjzKuz2jdaCVM4B5WkKj3+vFU4eAdZCahrvlc4aRAromtWjOmZu\\/7p2xMHUbRxZx9cg0qPeOzc7zT74FfYdc1fW1MVkAHDdwrgsan77NuTVsRJxD+x\\/71Xvy2aOFN96ANB5\\/3bPuB7AIS5mRPvQ+MRuPgn0ieA4V0o4OoS0LiAQ8nUoc7iDmK1ZUx9oIeIKaIfF1Uo8TudmPb3IXPfBC5pklqKY0x1OboJiLOQjB2BM22KJC0TIAg1JGTDp30MLLd42eRizm+lYLvoUhAeHhKHRNRjVXBkydRZGfID7+ze8pKriTkM4pQSJ2V08lmQAyslInY+6pyZvsTEoUPXRrQyVyghM3m1dxwL6bSKLjD6JJKrQEaoJ+phE4fm\\/ACggrQPSF1ick22D6DugYH520+Zq+hylZSjbK\\/bKoYlNr9RNtlAb1vnbCr0djILOKmneOObaad3VkMgBQeRWBk21xYXX5F5vNnJcTztgbgj7Y6Svc77jSR6p6D4ELQkrgbIf4bubhfEEsOwPXDciUdJXZab2bfI\\/DOkoXrNBkId1EIeZVfU82Ora0yK2fVNiCZID+dPE06Qc09qM7DVrMbccqPSmmObKTxa1vQItFmke2+aKZkwvJAPBMcQqxHwetdvSjV+yxRTR1IQXAUkqPW+rRJg7kBZU4vB4DLiBChYlZHu9ITI6USMrTR4V6XyG+ln08nloHaOm+d426PAlNjRUcZMKOfrQKnpQ6oFqA4xfvES6wU37rMFbik7KpVy5ohBbzq3kEc\\/uDTam8K83kRTN5KIgoMnJMITDOwGqaxJMKecmTfX9Fubbb5AjQVW8CHi2NxkvKdDdt0\\/Ptv\\/+4MdPOjIrmFY8iwHoCUTmoze9mK437Htv8XLVXQeLKK3kLJJIboYDN46el7e2NdaSSERLuizxlHasyqFtmY\\/WpjEC3cZL\\/r3emOgXqEISlRiF6w0MkzL8Cu3E0PHrTsDEwtnrLBjQz+VhN6wkcpM7aro9\\/6t+dsqqzJrV5jejZq6m7pMr2EI1KFT4EYETEgJg6kuqygv4yD1Qwq2FN\\/ViEmxwbZKLjP3V\\/N2ogsKG8+\\/2XIPd0a1ITgLARH\\/H\\/7D9ptqFvXNfVEUV37rzen4f5lFvki7SveMJCY11k0Uih0dv46QRUWtLJh9\\/XNi5vTsHifb0LTdQYnoFJ+2EHT0TCxw1VWxoS9Gx+z2hMRhdhzCamWbCXMgITB06eALJD9pVA6UptKYgZvUhfJGVbOgDT1h0TjH3LBuub\\/WUCU2U1MrljX4hL68Grhqbedg8u5UgcLFfJr\\/4kSpweuFK2HBB5aqnQPtQhPFM59YqIBXmQdrycH\\/tGiLh7eDkNTVLnXOxoTeLkqJTHKWt60YIiPrV8sIRiPhlJO1ObEvZ4ST\\/4TcibGzAAR24LisFEyyWuhCydr51tqXQc43Puru\\/F\\/xc5173vCqVyli45\\/fQx3DM7JETP4ZIiT8rihNWLHKRkZngJnks7K5sR6eXHxYW1nhFD6gYEGLGhum4T5oO6GgB3Mhym5cyITN6t+TbqcSb4nXPyPNh8+QyKyUu+fzxJWDNMiwQy7JISE7l+G6MdPft3ICXjFcgv+zSp4insGQLzbDiy0jlhDIDQr3y56IsgCOI\\/e5w+d7PRR80k9BCh837tpzW33fqh\\/++vEneeOfevTTlyju93x1d9gZC1WxmP80PaH93URpJrH0QSWLeEgx3LXxcGxtt4pXOBrGMzXCq0Z1nw2ObmnZ5XIPt3GRIcQCCOEc\\/7qrLkwauGxI0qbfhoiSr+eIXQB2+c0yvB2q33NIjlRlGEmiYmayXp5dcBZVMU+f6Hk9JgH2Dzy538umuplCdJGgEcp9kT6110iOcWqNomJcrNq3DXO1RG1tRm+nfhtCUIfdlAXDxe2IbP2ejvMX+TBX57lrWyIuP8257BoUNXAyhF4s7G67Wl2MmF5OMKijFSXO+qyEeFgHuz\\/CXmDi42IsCLlKB3VkYpblDTqx\\/c0gey0gqQE7E6R+gZ8rQHuI6ctDDjXdLKOVaSQKntXqpRGVqBYpIo6ItSGxQbgkOksZXAS7r10f6FGdAUcuVogaiX2rfIYpdHbtJyivaKPnqz6ljC9Se3\\/riGK2dKI4QgJ0AJVHGmVO1SEBbc07ZwsbFD07+IQQGNc6LGsmRFLEpe6+YbV0TsB1Ao3YKdBRvar9lN8bAbovZa8ntnOKfq+dL7MAvWoWEx\\/kliMuYJaCvD2NAHWn0mg1TjAnvC2q5p4sPIOPe8NfbD5a82D0jFPqOBwTOAlVpJUVxrYwq4j+T1rvsc0K+iWam9hIP157lNusJ0jhuK0ejYOTktPUBmXMfz7w0xdnlIKqoqslL9FF5OXUTx\\/1kNHqUEvI4A0AW9mO+SUBmNbDGAlc1glBW6GjCRuHkiYSl5djLwjlCZJ1EZ9kFS7HIlkYB4+\\/HcZUTovhC2yGjbzxPr0EFX\\/JxtexwuXG5TCR1+d1CmQeWoyZTGZrH5LOddi4ZTyXcY2PH5EClEBvI76BMPrI1hywNCwPTd\\/MCzolCR+e2Cj9bMlTq84Pa8ppZ5NVm70clSmIub8RoPDsxz4WFFzgFy56ekEaYfS5nAFVbhm+pru0Xktp9Qj5k01Mx3hkg503JiQvKELbqOWqrIL3utBg4P9P\\/5gxVSBPoue9aljrPlPMpvShYJ5gE8LuhyuK6fOcu9+MHElO4yqCOGzvMTpth7pDYcJFwyUobThLAhtEJCe61KOuUv\\/AZ2AbZE4uARvHezCDpSFc3B9qrSWBWd8iIs3gSo6M0FLMwG180VnsZknsv\\/lDedCgv6nr+OAmlxXPCPbDbWGkUTzyBtlZ1fyOVDkiSnt4VtBtB93qIT0ZOGLOxAR722EUKVWD6hnavayVEevUVdOFFbXRH\\/8b2zIod0n+TEnQjMpbXYBoX\\/nP8gfavsfbBKu7mpdZ9tJF0c89k3yz1te46y1vV+T64\\/W0CMqB2F0wNVx+S+ExXL0UQ7tTDG+mMvyBj+NrldDl8SSkVKeld2AS5Ha1lIy10Hf\\/Tn0ecsDMKeT1mPje7P6A3TwUYkXQ6fQZ\\/dTFZeA+\\/L2XOT5UOocvTTI5aFV6poq2sOdf7xZH0pRiexNf+VFroOe4yz4KF0jMr3zLxiEIlUmZAhTcdQQpW\\/buMcDK1lYYYhZXc+7H+bJSM5nBVYvNYFSMvjfTgVhMIO3KjyzNwobxiihSWiACuv5dU7dj3TC+uWk8N\\/mP9DxVuSXS9x+DfAl5oUXZQWa2V6RxMuzIm30fb81MVQRPlZuFQqL\\/qwDegv9Go2006ROz+SAEmShq5rWIxTnKXvvvFy93v\\/b7VwtGzr1cXwWM0pwhSofEFMDqfGL6sJkyTBb46CZkHnbTgsjBFCmi\\/NJJ2XJfNTi7mT0rgNWZUI1cbVLcb7tON37YH7nlnIVvDoNHSZ8h2\\/UeyPEikx8gnEF5M0yiBKVM+IQDHqIfimA4vDlrPqaqcNRAgoB\\/z4WXeXeSSjxkZ3e8Jskl+GkJcwgGyk6MguUYhfCfpr8AGdLnR36ir0HSuKt\\/KrOJIjHpA\\/J\\/7cTz8zI\\/kEo0jO1CbsG\\/B\\/k+o\\/rkg3ZzCO\\/OK7ByHK89ozpMfT5RuxULNChoIzbflqr+z1i4d\\/GXyCzziuyl9feHQMnIid80\\/rh2AtY0CqY5gAJ3TzPoTPB1Udqvmt95BCzZgnPkGkMH6vBEOdjJ6xvhjsrdcGtcCHrOKCTDUxZG\\/c1AhAPzPCAXTvNpK3vrWtsv3QFVPcW0w5ujIE+xFZSVpngEWIhs00N14Bi+puQ+0QIuok6wtzY\\/U1wRCsvoHRSoY75WqZ8\\/pkpwILe569gnZzd2WCOmftvAdZM1zG5TRedodIYNoo65D6ItCtYLNuPTbKVivEcdF+SM5AV+PyJAKpKm6UD\\/zC5x2tP6O28alu9hMJlQUyyZc2+4wYrAtGxV0MQY6k9K45R9zOO2moEEmae7fHB\\/q9ueKEWfTrdLIGfpL9dt7wLxXOjZ4ewcSH4WhAciTbLkWUfgn1OZUknBr7ooyYTspk+FJ3zMjFGoSlJmaM5jyWR3QDgtzZjb5+IYw2A6Y0G2jncEbZCpJppm1Ga+7ViacJl9stSIXJDx0dETTzVz9mb7knTmdjc9VqWAxr22+RPTq7k1lEqvjW2lvHpsTc0wNGxo0d1C\\/E8qCv6AyTE3z5CacQylr3+H5WcMY87U9toEL5VP+jzFPgU3gJ2gnUM0g247XuF\\/yNO2hVTHLJXhIluo3c+dC9n5GMRmfKVRv0kII+5AP1uEED3IWryI0MQ025ygrIwcDfIWPeiHI9XBBcQVWEtZodyjeyj0tNP\\/fQvs7+9nD+exSibY8Z5UsCLzjfTlzy\\/qpx7D7L9rTKGOD56rYz1ebj38VFq8eonsGX3uylZX05PIgAiA1qckk85Jgb2+Yaz1AdX14b7IQcNlofxMALSiZVvXJ3NgjTShrJTspmsL5ER1M63cQdofR8+UqETbIrDDatgOcupv3rOYQMCOr7wA8llTMZoV7Jpi6WUfh76CWHQ63sCAa9NdjDJclPZzalH76ORMTPgWuPZbtETnkfdngVOtKLJOGpjBX26eDs5NR\\/PJno3GTRYfKxuL93ULcNdnpv+gfjgbwe2r6UN06P+AD5mO\\/oK7tV1XVBJDbm3Pkbr4o\\/shY2HUrw+sh\\/YsMfWq7CU1ORTF6xXKjsQKEBHBIUt7B1MAIKmjl59kdsSaXKMBlFJ\\/9n4f2rlBrBqvUjC1tCHOaX13d49Jog4+AHbRBDOmk3DXYRu6ej+7Qxbu3SppVmANAF4vr3JJ4IEUHKTK5CREVR338zzpB829N4XQJ3fR7Z5n4u35eTYMjkTi4sMKwQVBos41AMQonS+Jm+uot9DI8AnkESmJOjFMSrz4yJisE3CPtD4lPWuGFIlBuDqdxLYvmcULQGopIcMpZucGU1YwnQaCfvcuQxhDMG7FNnyFsf7WDcc0fQ\\/21lHg6Vctns3CBnmbXn9+mc0QlAVXEiDgOtUuD6Ivs3zW7K0hvfWNhV\\/YSuaY\\/f8UpCYLmljpKGoZi4l2o\\/nO0HcJ3Z1cqkNKH+qCqS3iOY853ATRP\\/j+iPF0TJBpsckQePdIOX8Uwd3ns942M3uZ7CGJjUwFoP4SuxGApRHbWNqn1Gizt8dM\\/V+z5JUges0sN4CN+SlubPYQLDuIFULTwbX+9GXdnuR+wnVR41HkDdStZfbf2VpNFPgc92V1DT+Lpi9bEniBA04ArmhEazrQXqJy5N6jVqNSR42RANji5UmHlRzUSQu52ixAb+gsFc5Gun+d\\/FOTiBDcCINVJdIA1B9kgdV8AEvgyPuo0k55TTL2+Bb5Osc+D4o0X\\/5JC3NkinVQaJK0V0lmazfIMGYCYwagGxmlM7APR2bUrtCvbBXHXjGS9CYrX5EpAI3KWgP0bYvRhS8qPuFekh9kuzSvoLjnZ2irt\\/pfotvAMPyzSGEBjTwqQJg8gxriXB6Mfv3VQ54UJeQN1BJkqIK4lqB8jgUoeOm8Fa7VOw8sneAANoLxhe6ex+w54Wg53z450tCg7ceR9BW3DL1DcSoY0B53MOhG\\/oEywwnSyZLFFLYkHyRSJr0bfvkPAiZw6yiNbJxlPBo0Hz2sUmq2WelKw\\/7U3t2PMIDTic5dsMRIzTXjifRH9LlOuOPAzg5ZJjRmXG3b3hXzS5ahXoja8MKTYm\\/mQKgyhwmSNgeHpKuGIAdhGFM+JL09CkT3Ps8Bc8FdQxAndDdAve0b5uKNg28pGMzWxTZsCgQh6TlIQbrTiuqWCo8++yZg0X8++jkipIRgcexguAAQbRC\\/8mrF9iPE\\/uwT0C4ltr3UjPywr8jgsgq9MRf0ScM4gsEPx\\/XKid\\/wrMbmScLFNFw+NXZp6Vpz32D68qPwz3kTCGIXwNwHdsoOmX4jj8HDkAW6ODaHSJvXM8t4I32ukT0bVT4rLpw3pPtg2T4WaBQfKDbDiIImEzp+TeqOkuV+B\\/zz32OyuY1wHa8VwIEwbViv5E9XQvy7kvm\\/joiE0i3e6hp1D0gmjMuhQVOEBuq0z71bGncasudY3rGND8vgQozBaFA+B+z0g3lI+yuJkn7f1jYXuCNzyYkTAoOWD8vWO+YAAYpArDd2VSNPu6EJdLRdglrMyAzeQwQVisM\\/JBUgFNkWAyk6A4dG45wxxhhis6WoOcvvaTf6oPcVXdnYIdV9PSpeHbtCBTQ3vauFwnU3kLREscbqre8W7Y\\/4xpXkiq0lXYvYnTXsFYU2nrpb+B1BxP\\/QVt9WToJj9ILNU+PQU9sc21oIPYm8seK+wllKwjgKVvAxSeYbuEyTza6ds+3KXwR6HggLVR447Kzsgd\\/dxZMA66KcXsMHGcuTUHyBgpBGJHW\\/APaUsfdIdhKvPe5OghGePUggvlt9jpAsEclq25+yPeJNd2TmGodGMsjEqrecfmRorrRDDV+jtqujKCtaSGNzOCeu8qJ5C9xhl5LC0bdAWiZzDJuHo5GD6O6N\\/BYwBL8jLECY8g93JEGXVgFY7SM7i61gVj3toFogsqF2Fwb0zNZqA6IKMBmcV02DvtxV6hkcIHrh2AGD1pJxL7o5LOtU5lK6Ifhov2ct4ZoZVcQVB5\\/1\\/Fcrgqt9IC9uvbQfU1Gwy4hAUcX2vzOeC+RiO+oV4dYf+KPJF1NKkc4UWY4NMwKJGJ+8HvKiWH\\/Y2\\/BShv7\\/n6+WM7qZfszU7nZ+hOXcttZszn\\/hztA4seFBvhBhcV0YsQGh6T5f4M3cdaDHqnj1Mfh0OOz9NWBw0H\\/XPvBg8ApFJ9Zcx\\/QH70vq9ZKP+FhQdfO1I68Wxy9Q\\/Kjy2suWsXwwfz3AsBgDBVSIhQgTB9iWUpRN46TqVr2v4jQ4A6xw11EboOKEuiB9GE2WeC3GX1ioGbfkeGPSATKneGGROHPrcbZ0kRw\\/CyQkdc4QUK+SfMxjne\\/ltjZrUh1knxNTl49N4o4OVzc6B8Ar06cS8z4JhbLp1kAoXlv9rgsWd4vdLxVnGOovRvk5ULyV9tKqg5gHCmEGUX3\\/R4UOu6FYpwAIAiSDRiWgC62V1xF\\/wOqFH3LdFfLaBHEIzWN33UWw8MmN16mEKPV6wXd7Aq\\/xvNwMgXEMBEUx33sFWbLkjwJjOB6oQu69AJfLNz0LclnKdfQWORD+0hKGEXT8QMxHQHK7ZGydxwTwLfCoCqKuuQiV4mMZ6tzblVKsuEC8YHTswo8uv+k017lzc2zmVv4wJacXGsEZO0usBGov+D9yJ2spt6rPPYZVIS7iO+RIwoHa42g66R4H\\/9oLUCEebZRaX18B0jkaxs+t6E\\/he0lb9HD3dEcqjQZtcBuNTy\\/ykhqSADhuntZ\\/YcgtOk77ie\\/QuqOphEmrRD0wrd73Nm32vaGtWu42wTSUxgwxqvJGfvrC2hNTIG28Q==\",\"iv\":\"11c06c0ea8d77af320685bb5bb1c4f19\",\"s\":\"326d9bfd7ae434d8\"}
\n\n + \ \n \n\n \n\n \n\t \t\n \t \n \t \n \t \n\n + \ \n \n\n
\n\n\n
\n + \
\n
\n Home -\n Browse Torrents -\n Upload Torrent -\n Stat -\n Forum -\n FAQ -\n Login
\n ExtraTorrent.cc is in compliance with copyrights
\n BitCoin: 12DiyqsWhENahDzdhdYsRrCw8FPQVcCkcm
\n Can't load ExtraTorrent? + Try our official mirrors: etmirror.com - etproxy.com - extratorrentonline.com + - extratorrentlive.com
\n 2006-2016 + ExtraTorrent.cc1\n
\n\n\n
\n\n
\n\n\n\n\n\n\n"} + headers: + cf-ray: [311ae97f86981a9f-DUS] + connection: [keep-alive] + content-type: [text/html] + date: ['Thu, 15 Dec 2016 15:26:09 GMT'] + server: [cloudflare-nginx] + vary: [Accept-Encoding] + x-powered-by: [PHP/5.3.29] + status: {code: 200, message: OK} +version: 1 diff --git a/tests/providers/torrent/extratorrent/extratorrent_test.yml b/tests/providers/torrent/extratorrent/extratorrent_test.yaml similarity index 90% rename from tests/providers/torrent/extratorrent/extratorrent_test.yml rename to tests/providers/torrent/extratorrent/extratorrent_test.yaml index 2e457a923b..024358f185 100644 --- a/tests/providers/torrent/extratorrent/extratorrent_test.yml +++ b/tests/providers/torrent/extratorrent/extratorrent_test.yaml @@ -1,7 +1,6 @@ daily: - date: 2016-12-14 - url: http://extratorrent.cc/view/today/TV.html mode: RSS + search_strings: [''] data: - seeders: 1 pubdate: @@ -28,9 +27,8 @@ daily: size: 242745344 backlog: - date: 2016-12-14 - url: http://extratorrent.cc/search/?y=0&new=1&search=Elementary+S05E07&x=0 mode: Episode + search_strings: ['Arrow S05E07'] data: - seeders: 49 pubdate: