commit 150b15fc333d70f4f3b673846d177c6c21338bff Author: ilv ilv@users.noreply.github.com Date: Sat Oct 18 18:09:49 2014 -0300
Changes related to GetTor meeting of October 10th. Deleted obsolete documentation. --- LICENSE | 31 + README.md | 80 +- blacklist.cfg | 6 + core.cfg | 12 + core_demo.py | 19 + dropbox.cfg | 8 + dropbox.py | 190 ++ gettor/__init__.py | 1 + gettor/blacklist.py | 136 + gettor/core.py | 355 +++ gettor/db.py | 106 + gettor/smtp.py | 493 ++++ gettor/utils.py | 27 + gettor/xmpp.py | 304 ++ lang/smtp/i18n/en/LC_MESSAGES/en.mo | Bin 0 -> 1730 bytes lang/smtp/i18n/en/LC_MESSAGES/en.po | 95 + lang/smtp/i18n/es/LC_MESSAGES/es.mo | Bin 0 -> 1811 bytes lang/smtp/i18n/es/LC_MESSAGES/es.po | 94 + lang/xmpp/i18n/en/LC_MESSAGES/en.mo | Bin 0 -> 340 bytes lang/xmpp/i18n/en/LC_MESSAGES/en.po | 22 + lang/xmpp/i18n/en/LC_MESSAGES/es.mo | Bin 0 -> 340 bytes lang/xmpp/i18n/es/LC_MESSAGES/es.mo | Bin 0 -> 342 bytes lang/xmpp/i18n/es/LC_MESSAGES/es.po | 22 + providers/dropbox.links | 25 + providers/dropbox.links.backup | 25 + scripts/blacklist.py | 111 + scripts/create_db.py | 57 + scripts/stats.py | 123 + smtp.cfg | 16 + smtp_demo.py | 22 + spec/design/blacklist.txt | 74 - spec/design/core.txt | 155 - spec/design/smtp.txt | 118 - spec/design/twitter.txt | 99 - spec/overview.txt | 94 - src/LICENSE | 31 - src/blacklist.cfg | 6 - src/core.cfg | 12 - src/core_demo.py | 19 - src/create_links_demo.py | 19 - src/dropbox.py | 163 -- src/gettor/__init__.py | 1 - src/gettor/blacklist.py | 143 - src/gettor/core.py | 419 --- src/gettor/db.py | 113 - src/gettor/smtp.py | 603 ---- src/gettor/utils.py | 104 - src/gettor/xmpp.py | 378 --- src/i18n/en/LC_MESSAGES/en.mo | Bin 1730 -> 0 bytes src/i18n/en/LC_MESSAGES/en.po | 95 - src/i18n/es/LC_MESSAGES/es.mo | Bin 1811 -> 0 bytes src/i18n/es/LC_MESSAGES/es.po | 94 - src/log/all.log | 21 - src/log/debug.log | 12 - src/log/error.log | 1 - src/log/info.log | 10 - src/log/warn.log | 1 - src/providers/dropbox.links | 17 - src/scripts/blacklist.py | 111 - src/scripts/create_db.py | 54 - src/scripts/stats.py | 123 - src/smtp.cfg | 17 - src/smtp/log/all.log | 16 - src/smtp/log/debug.log | 14 - src/smtp/log/info.log | 3 - src/smtp/sample/sample-email.eml | 57 - src/smtp_demo.py | 22 - src/tbb-key.asc | 2986 -------------------- src/upload/tor-browser-linux32-3.6.2_en-EN.tar.xz | 1 - .../tor-browser-linux32-3.6.2_en-EN.tar.xz.asc | 11 - src/upload/tor-browser-linux32-3.6.2_es-ES.tar.xz | 1 - .../tor-browser-linux32-3.6.2_es-ES.tar.xz.asc | 11 - src/xmpp.cfg | 20 - src/xmpp/i18n/en/LC_MESSAGES/en.mo | Bin 340 -> 0 bytes src/xmpp/i18n/en/LC_MESSAGES/en.po | 22 - src/xmpp/i18n/en/LC_MESSAGES/es.mo | Bin 340 -> 0 bytes src/xmpp/i18n/es/LC_MESSAGES/es.mo | Bin 342 -> 0 bytes src/xmpp/i18n/es/LC_MESSAGES/es.po | 22 - src/xmpp_demo.py | 7 - upload/tor-browser-linux32-3.6.2_en-EN.tar.xz | 1 + upload/tor-browser-linux32-3.6.2_en-EN.tar.xz.asc | 11 + upload/tor-browser-linux32-3.6.2_es-ES.tar.xz | 1 + upload/tor-browser-linux32-3.6.2_es-ES.tar.xz.asc | 11 + upload/tor-browser-linux64-3.6.2_en-EN.tar.xz | 1 + upload/tor-browser-linux64-3.6.2_en-EN.tar.xz.asc | 11 + upload/tor-browser-osx32-3.6.2_en-EN.tar.xz | 1 + upload/tor-browser-osx32-3.6.2_en-EN.tar.xz.asc | 11 + upload/tor-browser-windows32-3.6.2_en-EN.tar.xz | 1 + .../tor-browser-windows32-3.6.2_en-EN.tar.xz.asc | 11 + xmpp.cfg | 19 + xmpp_demo.py | 7 + 91 files changed, 2389 insertions(+), 6377 deletions(-)
diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..530ff57 --- /dev/null +++ b/LICENSE @@ -0,0 +1,31 @@ +GetTor is distributed under this license: + +Copyright (c) 2008-2014, The Tor Project, Inc. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + + * Neither the names of the copyright owners nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file diff --git a/README.md b/README.md index 93a43e6..e194589 100644 --- a/README.md +++ b/README.md @@ -1,80 +1,6 @@ -gettor +GetTor ======
-GetTor Revamp (on development). - -Google Summer of Code 2014. - -* To get the current repo: -$ git clone https://github.com/ileiva/gettor.git - -* To upload bundles to Dropbox and create a links file: - -1) Install the Dropbox and GnuPG Python modules (just the first time): - -$ pip install dropbox gnupg - -2) Change account info in src/dropbox.py (app_key, app_secret, access_token) - -3) Specify the path of the PGP key that signed the packages (to include fingerprint). - -4) Run the script: - -$ cd src/providers/;rm *.links;cd ..; python dropbox.py - -If everything works good, you should see a dropbox.links file inside the 'providers' directory. The script will take the files on upload_dir (default to 'upload/') which end up on .xz and .xz.asc respectively. To add more locales for testing do the following (example for german): - -$ cd upload; cp tor-browser-linux32-3.6.2_en-EN.tar.xz tor-browser-linux32-3.6.2_de-DE.tar.xz - -$ cd upload; cp tor-browser-linux32-3.6.2_en-EN.tar.xz.asc tor-browser-linux32-3.6.2_de-DE.tar.xz.asc - -A script for getting the latest bundles is pending. - -* To test if the core module is working: - -1) Use the dummy script provided: - -$ python core_demo.py - -* To test the smtp module (without mail server): - -1) Set request parameters on smtp/sample/sample-email.eml (by default, 'To: gettor+en@torproject.org' and 'linux' in the body of the message. - -2) Run dummy script: - -$ python smtp_demo.py < smtp/sample/sample-email.eml - -If mail server is configured, then uncomment lines 328-332, 337, 353-359, and comment lines 334-335, 338, 360 on gettor/smtp.py. Also, you should enable e-mail forwarding as specified on https://gitweb.torproject.org/gettor.git/blob/HEAD:/README - -* To test the xmpp module - -1) Install the SleekXMPP module: - -$ pip install sleekxmpp - -2) Change user details on xmpp.cfg - -3) Run dummy script. - -$ python xmpp_demo.py - -4) To communicate with the bot using Pidgin click on Friends -> New instant message -> Enter the address used in xmpp.cfg to start comunicating with it. Current commands are as follows: - -operating_system locale: it'll get you links for operating system in the locale specified e.g. linux en - -help locale: it'll get you help info in locale e.g. help es - -Default locale is en, and default response is help. - -The xmpp module has been used in the following providers: - - * dukgo.com (works) - * riseup.net (works) - * jabber.ccc.de (works) - * jit.si (worked for a while, not any longer) - - - - - +GetTor development. Project started at the Google Summer of Code 2014, under the +Tor Project organization.
diff --git a/blacklist.cfg b/blacklist.cfg new file mode 100644 index 0000000..bb8a3d8 --- /dev/null +++ b/blacklist.cfg @@ -0,0 +1,6 @@ +[general] +db: /path/to/gettor.db + +[log] +level: DEBUG +dir: /path/to/log diff --git a/core.cfg b/core.cfg new file mode 100644 index 0000000..f82c890 --- /dev/null +++ b/core.cfg @@ -0,0 +1,12 @@ +[general] +basedir: /home/ilv/Proyectos/tor/gettor/src/ +db: gettor.db + +[links] +dir: /path/to/providers/ +os: linux,windows,osx +locales: es,en + +[log] +dir: /home/ilv/Proyectos/tor/gettor/src/log/ +level: DEBUG \ No newline at end of file diff --git a/core_demo.py b/core_demo.py new file mode 100644 index 0000000..88f725d --- /dev/null +++ b/core_demo.py @@ -0,0 +1,19 @@ +#!/usr/bin/python +# +# Dummy script to test GetTore's Core module +# + +import gettor.core + +try: + core = gettor.core.Core() + links = core.get_links('dummy service', 'linux', 'en') + print links +except gettor.core.ConfigError as e: + print "Misconfiguration: " + str(e) +except gettor.core.UnsupportedOSError as e: + print "Unsupported OS: " + str(e) +except gettor.core.UnsupportedLocaleError as e: + print "Unsupported Locale: " + str(e) +except gettor.core.InternalError as e: + print "Internal error: " + str(e) diff --git a/dropbox.cfg b/dropbox.cfg new file mode 100644 index 0000000..a29989c --- /dev/null +++ b/dropbox.cfg @@ -0,0 +1,8 @@ +[general] +upload_dir: upload +tbb_key: tbb-key.asc + +[app] +key: suchkey +secret: suchsecret +access_token: suchtoken \ No newline at end of file diff --git a/dropbox.py b/dropbox.py new file mode 100644 index 0000000..457955f --- /dev/null +++ b/dropbox.py @@ -0,0 +1,190 @@ +# -*- coding: utf-8 -*- +# +# This file is part of GetTor, a Tor Browser distribution system. +# +# :authors: Israel Leiva ilv@riseup.net +# see also AUTHORS file +# +# :copyright: (c) 2008-2014, The Tor Project, Inc. +# (c) 2014, Israel Leiva +# +# :license: This is Free Software. See LICENSE for license information. + +import re +import os +import gnupg +import hashlib +import ConfigParser + +import dropbox +import gettor.core + + +def valid_format(file): + """Check for valid bundle format + + Check if the given file has a valid bundle format + (e.g. tor-browser-linux32-3.6.2_es-ES.tar.xz) + + :param: file (string) the name of the file. + + :return: (boolean) true if the bundle format is valid, false otherwise. + + """ + m = re.search( + 'tor-browser-(\w+)\d\d-\d.\d.\d_(\w\w)-\w+.tar.xz', + file) + if m: + return True + else: + return False + + +def get_bundle_info(file): + """Get the os, arch and lc from a bundle string. + + :param: file (string) the name of the file. + + :raise: ValueError if the bundle doesn't have a valid bundle format. + + :return: (list) the os, arch and lc. + + """ + m = re.search( + 'tor-browser-(\w+)(\d\d)-\d.\d.\d_(\w\w)-\w+.tar.xz', + file) + if m: + os = m.group(1) + arch = m.group(2) + lc = m.group(3) + return os, arch, lc + else: + raise ValueError("Invalid bundle format %s" % file) + + +def get_file_sha256(file): + """Get the sha256 of a file. + + :param: file (string) the path of the file. + + :return: (string) the sha256 hash. + + """ + # as seen on the internetz + BLOCKSIZE = 65536 + hasher = hashlib.sha256() + with open(file, 'rb') as afile: + buf = afile.read(BLOCKSIZE) + while len(buf) > 0: + hasher.update(buf) + buf = afile.read(BLOCKSIZE) + return hasher.hexdigest() + + +def upload_files(basedir, client): + """Upload files to Dropbox. + + Looks for files ending with 'tar.xz' inside basedir. + + :param: basedir (string) path of the folder with the files to be + uploaded. + :param: client (object) DropboxClient object. + + :raise: ValueError if the .xz file doesn't have an .asc file. + :raise: UploadError if something goes wrong while uploading the + files to Dropbox. All files are uploaded to '/'. + + :return: (list) the names of the uploaded files. + + """ + files = [] + + p = re.compile('.*.tar.xz$') + + for name in os.listdir(basedir): + path = os.path.abspath(os.path.join(basedir, name)) + if os.path.isfile(path) and p.match(path) and valid_format(name): + files.append(name) + + for file in files: + asc = "%s.asc" % file + abs_file = os.path.abspath(os.path.join(basedir, file)) + abs_asc = os.path.abspath(os.path.join(basedir, asc)) + + if not os.path.isfile(abs_asc): + raise ValueError("%s doesn't exist!" % asc) + + # chunk upload for big files + to_upload = open(abs_file, 'rb') + size = os.path.getsize(abs_file) + uploader = client.get_chunked_uploader(to_upload, size) + while uploader.offset < size: + try: + upload = uploader.upload_chunked() + except rest.ErrorResponse, e: + UploadError("An error ocurred while uploading %s" % abs_file) + uploader.finish(file) + print "Uploading %s" % file + + # this should be small, upload it simple + to_upload_asc = open(abs_asc, 'rb') + response = client.put_file(asc, to_upload_asc) + print "Uploading %s" % asc + + return files + +if __name__ == '__main__': + config = ConfigParser.ConfigParser() + config.read('dropbox.cfg') + + app_key = config.get('app', 'key') + app_secret = config.get('app', 'secret') + access_token = config.get('app', 'access_token') + upload_dir = config.get('general', 'upload_dir') + + # important: this key must be the one that signed the packages + tbb_key = config.get('general', 'tbb_key') + + client = dropbox.client.DropboxClient(access_token) + + # import key fingerprint + gpg = gnupg.GPG() + key_data = open(tbb_key).read() + import_result = gpg.import_keys(key_data) + fp = import_result.results[0]['fingerprint'] + + # make groups of four characters to make fingerprint more readable + # e.g. 123A 456B 789C 012D 345E 678F 901G 234H 567I 890J + readable = ' '.join(fp[i:i+4] for i in xrange(0, len(fp), 4)) + + try: + uploaded_files = upload_files(upload_dir, client) + # use default config + core = gettor.core.Core('/home/gettor/core.cfg') + + # erase old links + core.create_links_file('Dropbox', readable) + + for file in uploaded_files: + # build file names + asc = "%s.asc" % file + abs_file = os.path.abspath(os.path.join(upload_dir, file)) + abs_asc = os.path.abspath(os.path.join(upload_dir, asc)) + + sha_file = get_file_sha256(abs_file) + + # build links + link_file = client.share(file, short_url=False) + link_asc = client.share(asc, short_url=False) + osys, arch, lc = get_bundle_info(file) + + link = "Package (%s-bit): %s\nASC signature (%s-bit): %s\n"\ + "Package SHA256 checksum (%s-bit): %s\n" %\ + (arch, link_file[u'url'], arch, link_asc[u'url'], + arch, sha_file) + + core.add_link('Dropbox', osys, lc, link) + except (ValueError, RuntimeError) as e: + print str(e) + except dropbox.rest.ErrorResponse as e: + print str(e) diff --git a/gettor/__init__.py b/gettor/__init__.py new file mode 100644 index 0000000..c87425a --- /dev/null +++ b/gettor/__init__.py @@ -0,0 +1 @@ +# yes it's empty, of such a fullness diff --git a/gettor/blacklist.py b/gettor/blacklist.py new file mode 100644 index 0000000..b95d888 --- /dev/null +++ b/gettor/blacklist.py @@ -0,0 +1,136 @@ +# -*- coding: utf-8 -*- +# +# This file is part of GetTor, a Tor Browser distribution system. +# +# :authors: Israel Leiva ilv@riseup.net +# see also AUTHORS file +# +# :copyright: (c) 2008-2014, The Tor Project, Inc. +# (c) 2014, Israel Leiva +# +# :license: This is Free Software. See LICENSE for license information. + +import os +import time +import logging +import sqlite3 +import datetime +import ConfigParser + +import db +import utils + +"""Blacklist module for managing blacklisting of users.""" + + +class BlacklistError(Exception): + pass + + +class Blacklist(object): + """Manage blacklisting of users. + + Public methods: + + is_blacklisted(): Check if someone is blacklisted. + + Exceptions: + + ConfigurationError: Bad configuration. + BlacklistError: User is blacklisted. + + """ + + def __init__(self, cfg=None): + """Create new object by reading a configuration file. + + :param: cfg (string) path of the configuration file. + + """ + # define a set of default values + DEFAULT_CONFIG_FILE = 'blacklist.cfg' + + logging.basicConfig(format='[%(levelname)s] %(asctime)s - %(message)s', + datefmt="%Y-%m-%d %H:%M:%S") + log = logging.getLogger(__name__) + config = ConfigParser.ConfigParser() + + if cfg is None or not os.path.isfile(cfg): + cfg = DEFAULT_CONFIG_FILE + + config.read(cfg) + + try: + dbname = config.get('general', 'db') + self.db = db.DB(dbname) + except ConfigParser.Error as e: + raise ConfigError("Couldn't read 'db' from 'general'") + + try: + logdir = config.get('log', 'dir') + logfile = os.path.join(logdir, 'blacklist.log') + except ConfigParser.Error as e: + raise ConfigError("Couldn't read 'dir' from 'log'") + + try: + loglevel = config.get('log', 'level') + except ConfigParser.Error as e: + raise ConfigError("Couldn't read 'level' from 'log'") + + # establish log level and redirect to log file + log.info('Redirecting logging to %s' % logfile) + logfileh = logging.FileHandler(logfile, mode='a+') + logfileh.setLevel(logging.getLevelName(loglevel)) + log.addHandler(logfileh) + + # stop logging on stdout from now on + log.propagate = False + + def is_blacklisted(self, user, service, max_req, wait_time): + """Check if a user is blacklisted. + + The user is blacklisted if: + + a) The 'blocked' field is set to one, meaning that is permanently + blacklisted. + + b) Does too many requests on a short period of time. For now, a user + that makes more than 'max_req' requests should wait 'wait_time' + minutes to make a new request. + + :param: user (string) the hashed user. + :param: service (string) the service the user is making a request to. + :param: max_req (int) maximum number of requests a user can make + in a row. + :param: wait_time (int) amount of time the user must wait before + making requests again after 'max_req' requests is reached. + For now this is considered in minutes. + + :raise: BlacklistError if the user is blacklisted + + """ + r = self.db.get_user(user, service) + if r: + # permanently blacklisted + if r['blocked']: + self.db.update_user(user, service, r['times']+1, 1) + raise BlacklistError("Blocked user") + # don't be greedy + elif r['times'] >= max_req: + last = datetime.datetime.fromtimestamp(float( + r['last_request'])) + next = last + datetime.timedelta(minutes=wait_time) + + if datetime.datetime.now() < next: + # too many requests from the same user + self.db.update_user(user, service, r['times']+1, 0) + raise BlacklistError("Too many requests") + else: + # fresh user again! + self.db.update_user(user, service, 1, 0) + else: + # adding up a request for user + self.db.update_user(user, service, r['times']+1, 0) + else: + # new request for user + self.db.add_user(user, service, 0) diff --git a/gettor/core.py b/gettor/core.py new file mode 100644 index 0000000..792add0 --- /dev/null +++ b/gettor/core.py @@ -0,0 +1,355 @@ +# -*- coding: utf-8 -*- +# +# This file is part of GetTor, a Tor Browser distribution system. +# +# :authors: Israel Leiva ilv@riseup.net +# see also AUTHORS file +# +# :copyright: (c) 2008-2014, The Tor Project, Inc. +# (c) 2014, Israel Leiva +# +# :license: This is Free Software. See LICENSE for license information. + +import os +import re +import inspect +import logging +import tempfile +import ConfigParser + +import db +import utils + +"""Core module for getting links from providers.""" + + +class ConfigError(Exception): + pass + + +class UnsupportedOSError(Exception): + pass + + +class UnsupportedLocaleError(Exception): + pass + + +class LinkFormatError(Exception): + pass + + +class LinkFileError(Exception): + pass + + +class InternalError(Exception): + pass + + +class Core(object): + """Get links from providers and deliver them to other modules. + + Public methods: + + get_links(): Get the links for the OS and locale requested. + create_links_file(): Create a file to store links of a provider. + add_link(): Add a link to a links file of a provider. + get_supported_os(): Get a list of supported operating systems. + get_supported_lc(): Get a list of supported locales. + + Exceptions: + + UnsupportedOSError: Request for an unsupported operating system. + UnsupportedLocaleError: Request for an unsupported locale. + ConfigError: Something's misconfigured. + LinkFormatError: The link added doesn't seem legit. + LinkFileError: Error related to the links file of a provider. + InternalError: Something went wrong internally. + + """ + + def __init__(self, cfg=None): + """Create a new core object by reading a configuration file. + + :param: cfg (string) the path of the configuration file. + :raise: ConfigurationError if the configuration file doesn't exists + or if something goes wrong while reading options from it. + + """ + # define a set of default values + DEFAULT_CONFIG_FILE = 'core.cfg' + + logging.basicConfig(format='[%(levelname)s] %(asctime)s - %(message)s', + datefmt="%Y-%m-%d %H:%M:%S") + log = logging.getLogger(__name__) + config = ConfigParser.ConfigParser() + + if cfg is None or not os.path.isfile(cfg): + cfg = DEFAULT_CONFIG_FILE + + config.read(cfg) + + try: + basedir = config.get('general', 'basedir') + except ConfigParser.Error as e: + raise ConfigError("Couldn't read 'basedir' from 'general'") + + try: + dbname = config.get('general', 'db') + dbname = os.path.join(basedir, dbname) + self.db = db.DB(dbname) + except ConfigParser.Error as e: + raise ConfigError("Couldn't read 'db' from 'general'") + + try: + self.linksdir = config.get('links', 'dir') + self.linksdir = os.path.join(basedir, self.linksdir) + except ConfigParser.Error as e: + raise ConfigError("Couldn't read 'links' from 'dir'") + + try: + self.supported_lc = config.get('links', 'locales') + except ConfigParser.Error as e: + raise ConfigError("Couldn't read 'locales' from 'links'") + + try: + self.supported_os = config.get('links', 'os') + except ConfigParser.Error as e: + raise ConfigError("Couldn't read 'os' from 'links'") + + try: + loglevel = config.get('log', 'level') + except ConfigParser.Error as e: + raise ConfigError("Couldn't read 'level' from 'log'") + + try: + logdir = config.get('log', 'dir') + logfile = os.path.join(logdir, 'core.log') + except ConfigParser.Error as e: + raise ConfigError("Couldn't read 'dir' from 'log'") + + # establish log level and redirect to log file + log.info('Redirecting logging to %s' % logfile) + logfileh = logging.FileHandler(logfile, mode='a+') + logfileh.setLevel(logging.getLevelName(loglevel)) + log.addHandler(logfileh) + + # stop logging on stdout from now on + log.propagate = False + + def get_links(self, service, os, lc): + """Get links for OS in locale. + + This method should be called from the services modules of + GetTor (e.g. SMTP). To make it easy we let the module calling us + specify the name of the service (for stats purpose). + + :param: service (string) the service trying to get the links. + :param: os (string) the operating system. + :param: lc (string) tthe locale. + + :raise: UnsupportedOSError if the operating system is not supported. + :raise: UnsupportedLocaleError if the locale is not supported. + :raise: InternalError if something goes wrong while internally. + + :return: (string) the links. + + """ + + if lc not in self.supported_lc: + raise UnsupportedLocaleError("Locale %s not supported" % lc) + + if os not in self.supported_os: + raise UnsupportedOSError("OS %s not supported " % os) + + # this could change in the future, let's leave it isolated. + links = self._get_links(os, lc) + + if links is None: + raise InternalError("Something went wrong internally") + + # thanks for stopping by + return links + + def _get_links(self, osys, lc): + """Internal method to get the links. + + Looks for the links inside each provider file. This should only be + called from get_links() method. + + :param: osys (string) the operating system. + :param: lc (string) the locale. + + :return: (string/None) links on success, None otherwise. + + """ + + # read the links files using ConfigParser + # see the README for more details on the format used + links = [] + + # look for files ending with .links + p = re.compile('.*.links$') + + for name in os.listdir(self.linksdir): + path = os.path.abspath(os.path.join(self.linksdir, name)) + if os.path.isfile(path) and p.match(path): + links.append(path) + + # let's create a dictionary linking each provider with the links + # found for os and lc. This way makes it easy to check if no + # links were found + providers = {} + + # reading links from providers directory + for name in links: + # we're reading files listed on linksdir, so they must exist! + config = ConfigParser.ConfigParser() + config.read(name) + + try: + pname = config.get('provider', 'name') + except ConfigParser.Error as e: + raise InternalError("Couldn't get 'name' from 'provider'") + + # checking if current provider pname has links for os in lc + try: + providers[pname] = config.get(osys, lc) + # avoid showing it all together + providers[pname] = providers[pname].replace(",", "\n") + except ConfigParser.Error as e: + raise InternalError("Couldn't get %s from %s (%s)" % + (lc, osys, name)) + + # each provider must have a fingerprint of the key used to + # sign the uploaded packages + try: + fingerprint = config.get('key', 'fingerprint') + providers[pname] = "%s\n\nFingerprint: %s" %\ + (providers[pname], fingerprint) + except ConfigParser.Error as e: + raise InternalError("Couldn't get 'fingerprint' from 'key'") + + # create the final links list with all providers + all_links = [] + + for key in providers.keys(): + all_links.append( + "\n%s\n\n%s\n" % (key, ''.join(providers[key])) + ) + + if all_links: + return "".join(all_links) + else: + # we're trying to get supported os an lc + # but there aren't any links! + return None + + def get_supported_os(self): + """Public method to get the list of supported operating systems. + + :return: (list) the supported operating systems. + + """ + return self.supported_os.split(',') + + def get_supported_lc(self): + """Public method to get the list of supported locales. + + :return: (list) the supported locales. + + """ + return self.supported_lc.split(',') + + def create_links_file(self, provider, fingerprint): + """Public method to create a links file for a provider. + + This should be used by all providers since it writes the links + file with the proper format. It backs up the old links file + (if exists) and creates a new one. + + :param: provider (string) the provider (links file will use this + name in slower case). + :param: fingerprint (string) the fingerprint of the key that signed + the packages to be uploaded to the provider. + + """ + linksfile = os.path.join(self.linksdir, provider.lower() + '.links') + linksfile_backup = "" + + if os.path.isfile(linksfile): + # backup the old file in case something fails + linksfile_backup = linksfile + '.backup' + os.rename(linksfile, linksfile_backup) + + try: + # this creates an empty links file + content = ConfigParser.RawConfigParser() + content.add_section('provider') + content.set('provider', 'name', provider) + content.add_section('key') + content.set('key', 'fingerprint', fingerprint) + content.add_section('linux') + content.add_section('windows') + content.add_section('osx') + with open(linksfile, 'w+') as f: + content.write(f) + except Exception as e: + if linksfile_backup: + os.rename(linksfile_backup, linksfile) + raise LinkFileError("Error while creating new links file: %s" % e) + + def add_link(self, provider, osys, lc, link): + """Public method to add a link to a provider's links file. + + Use ConfigParser to add a link into the os section, under the lc + option. It checks for valid format; the provider's script should + use the right format (see design). + + :param: provider (string) the provider. + :param: os (string) the operating system. + :param: lc (string) the locale. + :param: link (string) link to be added. + + :raise: UnsupportedOSError if the operating system is not supported. + :raise: UnsupportedLocaleError if the locale is not supported. + :raise: LinkFileError if there is no links file for the provider. + :raise: LinkFormatError if the link format doesn't seem legit. + :raise: InternalError if the links file doesn't have a section for + the OS requested. This *shouldn't* happen because it means + the file wasn't created correctly. + + """ + linksfile = os.path.join(self.linksdir, provider.lower() + '.links') + + # don't try to add unsupported stuff + if lc not in self.supported_lc: + raise UnsupportedLocaleError("Locale %s not supported" % lc) + + if osys not in self.supported_os: + raise UnsupportedOSError("OS %s not supported" % osys) + + if os.path.isfile(linksfile): + content = ConfigParser.RawConfigParser() + content.readfp(open(linksfile)) + # check if exists and entry for locale; if not, create it + try: + links = content.get(osys, lc) + links = "%s,\n%s" % (links, link) + content.set(osys, lc, links) + with open(linksfile, 'w') as f: + content.write(f) + except ConfigParser.NoOptionError: + content.set(osys, lc, link) + with open(linksfile, 'w') as f: + content.write(f) + except ConfigParser.NoSectionError: + # this shouldn't happen, but just in case + raise InternalError("Unknown %s section in links file" % osys) + else: + raise LinkFileError("There is no links file for %s" % provider) + + def add_request_to_db(self): + """Add request to database.""" + self.db.add_request() diff --git a/gettor/db.py b/gettor/db.py new file mode 100644 index 0000000..e5e0acc --- /dev/null +++ b/gettor/db.py @@ -0,0 +1,106 @@ +# -*- coding: utf-8 -*- +# +# This file is part of GetTor, a Tor Browser distribution system. +# +# :authors: Israel Leiva ilv@riseup.net +# see also AUTHORS file +# +# :copyright: (c) 2008-2014, The Tor Project, Inc. +# (c) 2014, Israel Leiva +# +# :license: This is Free Software. See LICENSE for license information. + +import time +import sqlite3 +import datetime + +"""DB interface for comunicating with sqlite3""" + + +class DB(object): + """ + + Public methods: + + add_request(): add a request to the database (requests table). + get_user(): get user info from the database (users table). + add_user(): add a user to the database (users table). + update_user(): update a user on the database (users table). + + """ + + def __init__(self, dbname): + """Create a new db object. + + :param: dbname (string) the path of the database. + + """ + self.con = sqlite3.connect(dbname) + self.con.row_factory = sqlite3.Row + + def add_request(self): + """Add a request to the database. + + For now we just count the number of requests we have received so far. + + """ + with self.con: + cur = self.con.cursor() + cur.execute("SELECT counter FROM requests WHERE id = 1") + row = cur.fetchone() + if row: + cur.execute("UPDATE requests SET counter=? WHERE id=?", + (row['counter']+1, 1)) + else: + cur.execute("INSERT INTO requests VALUES(?, ?)", (1, 1)) + + def get_user(self, user, service): + """Get user info from the database. + + :param: user (string) unique (hashed) string that represents the user. + :param: service (string) the service related to the user (e.g. SMTP). + + :return: (dict) the user information, with fields as indexes + (e.g. row['user']). + + """ + with self.con: + cur = self.con.cursor() + cur.execute("SELECT * FROM users WHERE id =? AND service =?", + (user, service)) + + row = cur.fetchone() + return row + + def add_user(self, user, service, blocked): + """Add a user to the database. + + We add a user with one 'times' and the current time as 'last_request' + by default. + + :param: user (string) unique (hashed) string that represents the user. + :param: service (string) the service related to the user (e.g. SMTP). + :param: blocked (int) one if user is blocked, zero otherwise. + + """ + with self.con: + cur = self.con.cursor() + cur.execute("INSERT INTO users VALUES(?,?,?,?,?)", + (user, service, 1, blocked, str(time.time()))) + + def update_user(self, user, service, times, blocked): + """Update a user on the database. + + We update the user info with the current time as 'last_request'. + + :param: user (string) unique (hashed) string that represents the user. + :param: service (string) the service related to the user (e.g. SMTP). + :param: times (int) the number of requests the user has made. + :param: blocked (int) one if user is blocked, zero otherwise. + + """ + with self.con: + cur = self.con.cursor() + cur.execute("UPDATE users SET times =?, blocked =?," + " last_request =? WHERE id =? AND service =?", + (times, blocked, str(time.time()), user, service)) diff --git a/gettor/smtp.py b/gettor/smtp.py new file mode 100644 index 0000000..655b5df --- /dev/null +++ b/gettor/smtp.py @@ -0,0 +1,493 @@ +# -*- coding: utf-8 -*- +# +# This file is part of GetTor, a Tor Browser distribution system. +# +# :authors: Israel Leiva ilv@riseup.net +# see also AUTHORS file +# +# :copyright: (c) 2008-2014, The Tor Project, Inc. +# (c) 2014, Israel Leiva +# +# :license: This is Free Software. See LICENSE for license information. + + +import os +import re +import sys +import time +import email +import gettext +import logging +import smtplib +import datetime +import ConfigParser + +from email.mime.text import MIMEText + +import core +import utils +import blacklist + +"""SMTP module for processing email requests.""" + + +class ConfigError(Exception): + pass + + +class AddressError(Exception): + pass + + +class SendEmailError(Exception): + pass + + +class InternalError(Exception): + pass + + +class SMTP(object): + """Receive and reply requests by email. + + Public methods: + + process_email(): Process the email received. + + Exceptions: + + ConfigError: Bad configuration. + AddressError: Address of the sender malformed. + SendEmailError: SMTP server not responding. + InternalError: Something went wrong internally. + + """ + + def __init__(self, cfg=None): + """Create new object by reading a configuration file. + + :param: cfg (string) path of the configuration file. + + """ + # define a set of default values + DEFAULT_CONFIG_FILE = 'smtp.cfg' + + logging.basicConfig(format='[%(levelname)s] %(asctime)s - %(message)s', + datefmt="%Y-%m-%d %H:%M:%S") + log = logging.getLogger(__name__) + config = ConfigParser.ConfigParser() + + if cfg is None or not os.path.isfile(cfg): + cfg = DEFAULT_CONFIG_FILE + + config.read(cfg) + + try: + self.our_domain = config.get('general', 'our_domain') + except ConfigParser.Error as e: + raise ConfigError("Couldn't read 'our_domain' from 'general'") + + try: + core_cfg = config.get('general', 'core_cfg') + except ConfigParser.Error as e: + raise ConfigError("Couldn't read 'core_cfg' from 'general'") + + try: + blacklist_cfg = config.get('blacklist', 'cfg') + self.bl = blacklist.Blacklist(blacklist_cfg) + except ConfigParser.Error as e: + raise ConfigError("Couldn't read 'cfg' from 'blacklist'") + + try: + self.bl_max_req = config.get('blacklist', 'max_requests') + self.bl_max_req = int(self.bl_max_req) + except ConfigParser.Error as e: + raise ConfigError("Couldn't read 'max_requests' from 'blacklist'") + + try: + self.bl_wait_time = config.get('blacklist', 'wait_time') + self.bl_wait_time = int(self.bl_wait_time) + except ConfigParser.Error as e: + raise ConfigError("Couldn't read 'wait_time' from 'blacklist'") + + try: + self.i18ndir = config.get('i18n', 'dir') + except ConfigParser.Error as e: + raise ConfigError("Couldn't read 'dir' from 'i18n'") + + try: + logdir = config.get('log', 'dir') + logfile = os.path.join(logdir, 'smtp.log') + except ConfigParser.Error as e: + raise ConfigError("Couldn't read 'dir' from 'log'") + + try: + loglevel = config.get('log', 'level') + except ConfigParser.Error as e: + raise ConfigurationError("Couldn't read 'level' from 'log'") + + # use default values + self.core = core.Core(core_cfg) + + # establish log level and redirect to log file + log.info('Redirecting logging to %s' % logfile) + logfileh = logging.FileHandler(logfile, mode='a+') + logfileh.setLevel(logging.getLevelName(loglevel)) + log.addHandler(logfileh) + + # stop logging on stdout from now on + log.propagate = False + + def _is_blacklisted(self, addr): + """Check if a user is blacklisted. + + :param: addr (string) the hashed address of the user. + + :return: true is the address is blacklisted, false otherwise. + + """ + + try: + self.bl.is_blacklisted(addr, 'SMTP', self.bl_max_req, + self.bl_wait_time) + return False + except blacklist.BlacklistError as e: + return True + + def _get_lc(self, addr): + """Get the locale from an email address. + + Process the email received and look for the locale in the recipient + address (e.g. gettor+en@torproject.org). If no locale found, english + by default. + + :param: (string) the email address we want to get the locale from. + + :return: (string) the locale (english if none). + + """ + # if no match found, english by default + lc = 'en' + + # look for gettor+locale@torproject.org + m = re.match('gettor+(\w\w)@\w+.\w+', addr) + if m: + # we found a request for locale lc + lc = "%s" % m.groups() + + return lc.lower() + + def _get_normalized_address(self, addr): + """Get normalized address. + + We look for anything inside the last '<' and '>'. Code taken from + the old GetTor (utils.py). + + :param: addr (string) the address we want to normalize. + + :raise: AddressError if the address can't be normalized. + + :return: (string) the normalized address. + + """ + if '<' in addr: + idx = addr.rindex('<') + addr = addr[idx:] + m = re.search(r'<([^>]*)>', addr) + if m is None: + # malformed address + raise AddressError("Couldn't extract normalized address " + "from %s" % self_get_sha256(addr)) + addr = m.group(1) + return addr + + def _get_content(self, email): + """Get the body content of an email. + + :param: email (object) the email object to extract the content from. + + :return: (string) body of the message. + + """ + # get the body content of the email + maintype = email.get_content_maintype() + if maintype == 'multipart': + for part in email.get_payload(): + if part.get_content_maintype() == 'text': + return part.get_payload() + elif maintype == 'text': + return email.get_payload() + + def _get_msg(self, msgid, lc): + """Get message identified by msgid in a specific locale. + + :param: msgid (string) the identifier of a string. + :param: lc (string) the locale. + + :return: (string) the message from the .po file. + + """ + # obtain the content in the proper language + t = gettext.translation(lc, self.i18ndir, languages=[lc]) + _ = t.ugettext + + msgstr = _(msgid) + return msgstr + + def _parse_email(self, msg, addr): + """Parse the email received. + + Get the locale and parse the text for the rest of the info. + + :param: msg (string) the content of the email to be parsed. + :param: addr (string) the address of the recipient (i.e. us). + + :return: (list) 4-tuple with locale, os and type of request. + + """ + req = self._parse_text(msg) + lc = self._get_lc(addr) + req['lc'] = lc + + return req + + def _parse_text(self, msg): + """Parse the text part of the email received. + + Try to figure out what the user is asking, namely, the type + of request, the package and os required (if applies). + + :param: msg (string) the content of the email to be parsed. + + :return: (list) 3-tuple with the type of request, os and pt info. + + """ + # by default we asume the request is asking for help + req = {} + req['type'] = 'help' + req['os'] = None + + # core knows what OS are supported + supported_os = self.core.get_supported_os() + + # if no OS is found, help request by default + found_os = False + lines = msg.split(' ') + for word in lines: + if not found_os: + for os in supported_os: + if re.match(os, word, re.IGNORECASE): + req['os'] = os + req['type'] = 'links' + found_os = True + break + else: + break + return req + + def _create_email(self, from_addr, to_addr, subject, msg): + """Create an email object. + + This object will be used to construct the reply. + + :param: from_addr (string) the address of the sender. + :param: to_addr (string) the address of the recipient. + :param: subject (string) the subject of the email. + :param: msg (string) the content of the email. + + :return: (object) the email object. + + """ + email_obj = MIMEText(msg) + email_obj.set_charset("utf-8") + email_obj['Subject'] = subject + email_obj['From'] = from_addr + email_obj['To'] = to_addr + + return email_obj + + def _send_email(self, from_addr, to_addr, subject, msg): + """Send an email. + + Take a 'from' and 'to' addresses, a subject and the content, creates + the email and send it. + + :param: from_addr (string) the address of the sender. + :param: to_addr (string) the address of the recipient. + :param: subject (string) the subject of the email. + :param: msg (string) the content of the email. + + """ + email_obj = self._create_email(from_addr, to_addr, subject, msg) + + try: + s = smtplib.SMTP("localhost") + s.sendmail(from_addr, to_addr, email_obj.as_string()) + s.quit() + except smtplib.SMTPException as e: + raise SendEmailError("Error with SMTP: %s" % str(e)) + + def _send_links(self, links, lc, os, from_addr, to_addr): + """Send links to the user. + + Get the message in the proper language (according to the locale), + replace variables and send the email. + + :param: links (string) the links to be sent. + :param: lc (string) the locale. + :param: os (string) the operating system. + :param: from_addr (string) the address of the sender. + :param: to_addr (string) the address of the recipient. + + """ + # obtain the content in the proper language and send it + links_subject = self._get_msg('links_subject', lc) + links_msg = self._get_msg('links_msg', lc) + links_msg = links_msg % (os, lc, links) + + try: + self._send_email(from_addr, to_addr, links_subject, links_msg) + except SendEmailError as e: + raise InternalError("Error while sending links message") + + def _send_help(self, lc, from_addr, to_addr): + """Send help message. + + Get the message in the proper language (according to the locale), + replace variables (if any) and send the email. + + :param: lc (string) the locale. + :param: from_addr (string) the address of the sender. + :param: to_addr (string) the address of the recipient. + + """ + # obtain the content in the proper language and send it + help_subject = self._get_msg('help_subject', lc) + help_msg = self._get_msg('help_msg', lc) + + try: + self._send_email(from_addr, to_addr, help_subject, help_msg) + except SendEmailError as e: + raise InternalError("Error while sending help message") + + def _send_unsupported_lc(self, lc, os, from_addr, to_addr): + """Send unsupported locale message. + + Get the message for unsupported locale in english, replace variables + (if any) and send the email. + + :param: lc (string) the locale. + :param: os (string) the operating system. + :param: from_addr (string) the address of the sender. + :param: to_addr (string) the address of the recipient. + + """ + + # obtain the content in english and send it + un_lc_subject = self._get_msg('unsupported_lc_subject', 'en') + un_lc_msg = self._get_msg('unsupported_lc_msg', 'en') + un_lc_msg = un_lc_msg % lc + + try: + self._send_email(from_addr, to_addr, un_lc_subject, un_lc_msg) + + except SendEmailError as e: + raise InternalError("Error while sending unsupported lc message") + + def process_email(self, raw_msg): + """Process the email received. + + Create an email object from the string received. The processing + flow is as following: + + - check for blacklisted address. + - parse the email. + - check the type of request. + - send reply. + + :param: raw_msg (string) the email received. + + :raise: InternalError if something goes wrong while asking for the + links to the Core module. + + """ + parsed_msg = email.message_from_string(raw_msg) + content = self._get_content(parsed_msg) + from_addr = parsed_msg['From'] + to_addr = parsed_msg['To'] + bogus_request = False + status = '' + req = None + + try: + # two ways for a request to be bogus: address malformed or + # blacklisted + try: + norm_from_addr = self._get_normalized_address(from_addr) + except AddressError as e: + status = 'malformed' + bogus_request = True + # it might be interesting to know what triggered this + # we are not logging this for now + # logfile = self._log_email('malformed', content) + + if norm_from_addr: + anon_addr = utils.get_sha256(norm_from_addr) + + if self._is_blacklisted(anon_addr): + status = 'blacklisted' + bogus_request = True + # it might be interesting to know extra info + # we are not logging this for now + # logfile = self._log_email(anon_addr, content) + + if not bogus_request: + # try to figure out what the user is asking + req = self._parse_email(content, to_addr) + + # our address should have the locale requested + our_addr = "gettor+%s@%s" % (req['lc'], self.our_domain) + + # two possible options: asking for help or for the links + if req['type'] == 'help': + # make sure we can send emails + try: + self._send_help(req['lc'], our_addr, norm_from_addr) + except SendEmailError as e: + status = 'internal_error' + raise InternalError("Something's wrong with the SMTP " + "server: %s" % str(e)) + + elif req['type'] == 'links': + try: + links = self.core.get_links('SMTP', req['os'], + req['lc']) + + except core.UnsupportedLocaleError as e: + # if we got here, the address of the sender should + # be valid so we send him/her a message about the + # unsupported locale + status = 'unsupported_lc' + self._send_unsupported_lc(req['lc'], req['os'], + our_addr, norm_from_addr) + return + + # if core fails, we fail too + except (core.InternalError, core.ConfigurationError) as e: + status = 'core_error' + # something went wrong with the core + raise InternalError("Error obtaining the links") + + # make sure we can send emails + try: + self._send_links(links, req['lc'], req['os'], our_addr, + norm_from_addr) + except SendEmailError as e: + status = 'internal_error' + raise SendEmailError("Something's wrong with the SMTP " + "server: %s" % str(e)) + status = 'success' + finally: + # keep stats + if req: + self.core.add_request_to_db() diff --git a/gettor/utils.py b/gettor/utils.py new file mode 100644 index 0000000..cbf01ce --- /dev/null +++ b/gettor/utils.py @@ -0,0 +1,27 @@ +# -*- coding: utf-8 -*- +# +# This file is part of GetTor, a Tor Browser distribution system. +# +# :authors: Israel Leiva ilv@riseup.net +# see also AUTHORS file +# +# :copyright: (c) 2008-2014, The Tor Project, Inc. +# (c) 2014, Israel Leiva +# +# :license: This is Free Software. See LICENSE for license information. + +import os +import hashlib + +"""Common utilities for GetTor modules.""" + + +def get_sha256(string): + """Get sha256 of a string. + + :param: (string) the string to be hashed. + + :return: (string) the sha256 of string. + + """ + return str(hashlib.sha256(string).hexdigest()) diff --git a/gettor/xmpp.py b/gettor/xmpp.py new file mode 100644 index 0000000..e9d2a10 --- /dev/null +++ b/gettor/xmpp.py @@ -0,0 +1,304 @@ +# -*- coding: utf-8 -*- +# +# This file is part of GetTor, a Tor Browser distribution system. +# +# :authors: Israel Leiva ilv@riseup.net +# see also AUTHORS file +# +# :copyright: (c) 2008-2014, The Tor Project, Inc. +# (c) 2014, Israel Leiva +# +# :license: This is Free Software. See LICENSE for license information. + +import os +import re +import sys +import time +import gettext +import hashlib +import logging +import ConfigParser + +from sleekxmpp import ClientXMPP +from sleekxmpp.exceptions import IqError, IqTimeout + +import core +import utils +import blacklist + + +"""XMPP module for processing requests.""" + + +class Bot(ClientXMPP): + """XMPP bot. + + Handle messages and pass them to XMPP module for parsing. + + """ + + def __init__(self, jid, password, xmpp_obj): + ClientXMPP.__init__(self, jid, password) + + self.xmpp = xmpp_obj + self.add_event_handler("session_start", self.session_start) + self.add_event_handler("message", self.message) + + def session_start(self, event): + self.send_presence() + self.get_roster() + + try: + self.get_roster() + except IqError as err: + # error getting the roster + # logging.error(err.iq['error']['condition']) + self.disconnect() + except IqTimeout: + # server is taking too long to respond + self.disconnect() + + def message(self, msg): + if msg['type'] in ('chat', 'normal'): + msg_to_send = self.xmpp.parse_request(msg['from'], msg['body']) + if msg_to_send: + msg.reply(msg_to_send).send() + + +class ConfigError(Exception): + pass + + +class InternalError(Exception): + pass + + +class XMPP(object): + """Receive and reply requests by XMPP. + + Public methods: + + parse_request(): parses a message and tries to figure out what the user + is asking for. + + Exceptions: + + ConfigError: Bad configuration. + InternalError: Something went wrong internally. + + """ + + def __init__(self, cfg=None): + """Create new object by reading a configuration file. + + :param: cfg (string) the path of the configuration file. + + """ + # define a set of default values + DEFAULT_CONFIG_FILE = 'xmpp.cfg' + + logging.basicConfig(format='[%(levelname)s] %(asctime)s - %(message)s', + datefmt="%Y-%m-%d %H:%M:%S") + log = logging.getLogger(__name__) + config = ConfigParser.ConfigParser() + + if cfg is None or not os.path.isfile(cfg): + cfg = DEFAULT_CONFIG_FILE + + config.read(cfg) + + try: + self.user = config.get('account', 'user') + except ConfigParser.Error as e: + raise ConfigError("Couldn't read 'user' from 'account'") + + try: + self.password = config.get('account', 'password') + except ConfigParser.Error as e: + raise ConfigError("Couldn't read 'password' from 'account'") + + try: + self.core_cfg = config.get('general', 'core_cfg') + except ConfigParser.Error as e: + raise ConfigError("Couldn't read 'core_cfg' from 'general'") + + try: + blacklist_cfg = config.get('blacklist', 'cfg') + self.bl = blacklist_cfg + except ConfigParser.Error as e: + raise ConfigError("Couldn't read 'cfg' from 'blacklist'") + + try: + self.bl_max_req = config.get('blacklist', 'max_requests') + self.bl_max_req = int(self.bl_max_req) + except ConfigParser.Error as e: + raise ConfigError("Couldn't read 'max_requests' from 'blacklist'") + + try: + self.bl_wait_time = config.get('blacklist', 'wait_time') + self.bl_wait_time = int(self.bl_wait_time) + except ConfigParser.Error as e: + raise ConfigError("Couldn't read 'wait_time' from 'blacklist'") + + try: + self.i18ndir = config.get('i18n', 'dir') + except ConfigParser.Error as e: + raise ConfigError("Couldn't read 'dir' from 'i18n'") + + try: + logdir = config.get('log', 'dir') + logfile = os.path.join(logdir, 'xmpp.log') + except ConfigParser.Error as e: + raise ConfigError("Couldn't read 'dir' from 'log'") + + try: + loglevel = config.get('log', 'level') + except ConfigParser.Error as e: + raise ConfigError("Couldn't read 'level' from 'log'") + + # establish log level and redirect to log file + log.info('Redirecting logging to %s' % logfile) + logfileh = logging.FileHandler(logfile, mode='a+') + logfileh.setLevel(logging.getLevelName(loglevel)) + log.addHandler(logfileh) + + # stop logging on stdout from now on + log.propagate = False + + def start_bot(self): + """Start the bot for handling requests. + + Start a new sleekxmpp bot. + + """ + xmpp = Bot(self.user, self.password, self) + xmpp.connect() + xmpp.process(block=True) + + def _is_blacklisted(self, account): + """Check if a user is blacklisted. + + :param: addr (string) the hashed address of the user. + + :return: true is the address is blacklisted, false otherwise. + + """ + anon_acc = utils.get_sha256(account) + bl = blacklist.Blacklist(self.bl) + + try: + bl.is_blacklisted(anon_acc, 'XMPP', self.bl_max_req, + self.bl_wait_time) + return False + except blacklist.BlacklistError as e: + return True + + def _get_msg(self, msgid, lc): + """Get message identified by msgid in a specific locale. + + :param: msgid (string) the identifier of a string. + :param: lc (string) the locale. + + :return: (string) the message from the .po file. + + """ + # obtain the content in the proper language + t = gettext.translation(lc, self.i18ndir, languages=[lc]) + _ = t.ugettext + + msgstr = _(msgid) + return msgstr + + def _parse_text(self, msg, core_obj): + """Parse the text part of a message. + + Split the message in words and look for patterns for locale, + operating system and built-in pluggable transport info. + + :param: msg (string) the message received. + :param: core_obj (object) the object of gettor core module. + + :return: request (list) 4-tuple with locale, os, type of request + and pt info. + + """ + # core knows what OS are supported + supported_os = core_obj.get_supported_os() + supported_lc = core_obj.get_supported_lc() + + # default values + req = {} + req['lc'] = 'en' + req['os'] = None + req['type'] = 'help' + found_lc = False + found_os = False + + # analyze every word + # request shouldn't be more than 10 words long, so there should + # be a limit for the amount of words + for word in msg.split(' '): + # look for lc and os + if not found_lc: + for lc in supported_lc: + if re.match(lc, word, re.IGNORECASE): + found_lc = True + req['lc'] = lc + if not found_os: + for os in supported_os: + if re.match(os, word, re.IGNORECASE): + found_os = True + req['os'] = os + req['type'] = 'links' + return req + + def parse_request(self, account, msg): + """Process the request received. + + Check if the user is not blacklisted and then check the body of + the message to find out what is asking. + + :param: account (string) the account that did the request. + :param: msg (string) the body of the message sent to us. + + :return: (string/None) the message to be sent to the user via the + bot, or None if the user is blacklisted. + + """ + bogus_request = False + reply = '' + status = '' + req = None + core_obj = core.Core(self.core_cfg) + + try: + if self._is_blacklisted(str(account)): + status = 'blacklisted' + bogus_request = True + + if not bogus_request: + # let's try to guess what the user is asking + req = self._parse_text(str(msg), core_obj) + + if req['type'] == 'help': + status = 'success' + reply = self._get_msg('help', req['lc']) + elif req['type'] == 'links': + try: + links = core_obj.get_links("XMPP", req['os'], + req['lc']) + reply = self._get_msg('links', req['lc']) + reply = reply % (req['os'], req['lc'], links) + + status = 'success' + except (core.ConfigError, core.InternalError) as e: + # if core failes, send the user an error message, but + # keep going + status = 'core_error' + reply = self._get_msg('internal_error', req['lc']) + finally: + # keep stats + if req: + core_obj.add_request_to_db() + + return reply diff --git a/lang/smtp/i18n/en/LC_MESSAGES/en.mo b/lang/smtp/i18n/en/LC_MESSAGES/en.mo new file mode 100644 index 0000000..e686fcb Binary files /dev/null and b/lang/smtp/i18n/en/LC_MESSAGES/en.mo differ diff --git a/lang/smtp/i18n/en/LC_MESSAGES/en.po b/lang/smtp/i18n/en/LC_MESSAGES/en.po new file mode 100644 index 0000000..6f78da2 --- /dev/null +++ b/lang/smtp/i18n/en/LC_MESSAGES/en.po @@ -0,0 +1,95 @@ +domain "en" + +#: Links subject +msgid "links_subject" +msgstr "[GetTor] Links for your request" + +#: Links subject (PT) +msgid "links_pt_subject" +msgstr "[GetTor] Links for your request" + +#: Help subject +msgid "help_subject" +msgstr "[GetTor] Help" + +#: Delay subject +msgid "delay_subject" +msgstr "[GetTor] Delay message" + +# Unsupported locale subject +msgid "unsupported_locale_subject" +msgstr "[GetTor] Unsupported locale" + +# Unsupported locale message +msgid "unsupported_locale_msg" +msgstr "The locale you requested '%s' is not supported." + +#: Links message +msgid "links_msg" +msgstr "Thank you for your request for %s-%s.\n\ +\n\ +Here are the download links:\n\ +\n\ +===\n\ +Tor Browser Bundle:\n\ +===\n\ +%s\n\ +===\n\ +\n\ +===\n\ +Support:\n\ +===\n\ +\n\ +Still need help? If you have any questions, trouble connecting to Tor\n\ +network, or need to talk to a human, please contact our support team at:\n\ +\n\ + help@rt.torproject.org\n\ +\n\ +We are ready to answer your queries in English, Farsi, Chinese, Arabic,\n\ +French and Spanish." + +#: Links message (PT) +msgid "links_pt_msg" +msgstr "Thank you for your request for %s-%s.\n\ +\n\ +Here are the download links:\n\ +\n\ +===\n\ +Tor Browser Bundle:\n\ +===\n\ +%s\n\ +===\n\ +Info about pluggable transports.\n\ +\n\ +===\n\ +Support:\n\ +===\n\ +\n\ +Still need help? If you have any questions, trouble connecting to Tor\n\ +network, or need to talk to a human, please contact our support team at:\n\ +\n\ + help@rt.torproject.org\n\ +\n\ +We are ready to answer your queries in English, Farsi, Chinese, Arabic,\n\ +French and Spanish." + +#: Help message +msgid "help_msg" +msgstr "Hello, this is the 'GetTor' robot.\n\ +\n\ +Thank you for your request. I am here to help you download the latest\n\ +Tor Browser Bundle.\n\ +\n\ +Please reply to this message with one of the options below:\n\ +\n\ + windows\n\ + linux\n\ + osx\n\ +\n\ +And I will send you the download instructions quickly.\n\ +\n\ +Tip: Just send a blank reply to this message if you are not sure." + +#: Delay message +msgid "delay_msg" +msgstr "Delay message." diff --git a/lang/smtp/i18n/es/LC_MESSAGES/es.mo b/lang/smtp/i18n/es/LC_MESSAGES/es.mo new file mode 100644 index 0000000..c21fe7b Binary files /dev/null and b/lang/smtp/i18n/es/LC_MESSAGES/es.mo differ diff --git a/lang/smtp/i18n/es/LC_MESSAGES/es.po b/lang/smtp/i18n/es/LC_MESSAGES/es.po new file mode 100644 index 0000000..bc4b5a8 --- /dev/null +++ b/lang/smtp/i18n/es/LC_MESSAGES/es.po @@ -0,0 +1,94 @@ +domain "es" + +#: Links subject +msgid "links_subject" +msgstr "[GetTor] Enlaces para tu petición" + +#: Links subject (PT) +msgid "links_pt_subject" +msgstr "[GetTor] Enlaces para tu petición" + +#: Help subject +msgid "help_subject" +msgstr "[GetTor] Ayuda" + +#: Delay subject +msgid "delay_subject" +msgstr "[GetTor] Mensaje de demora" + +# Unsupported locale subject +msgid "unsupported_locale_subject" +msgstr "[GetTor] Locale no soportado" + +# Unsupported locale message +msgid "unsupported_locale_msg" +msgstr "El locale especificado %s no está soportado." + +#: Links message +msgid "links_msg" +msgstr """Gracias por tu petición para %s-%s.\n\ +\n\ +Aquí están los links de descarga:\n\ +\n\ +===\n\ +%s\n\ +===\n\ +\n\ +===\n\ +Soporte:\n\ +===\n\ +\n\ +¿Aún necesitas ayuda? Si tienes dudas, problemas para conectarte a la\n\ +red Tor, o necesitas hablar con un humano, por favor contacta a nuestro\n\ +equipo de soporte a:\n\ +\n\ + help@rt.torproject.org\n\ +\n\ +Estamos listos para responder tus consultas en Inglés, Farsi, Chino,\n\ +Arábico, Francés y Español.""" + +#: Links message (PT) +msgid "links_pt_msg" +msgstr """Gracias por tu petición para %s-%s.\n\ +\n\ +Aquí están los links de descarga:\n\ +\n\ +===\n\ +%s\n\ +===\n\ +Tip: Información sobre pluggable transports.\n\ +\n\ +===\n\ +Soporte:\n\ +===\n\ +\n\ +¿Aún necesitas ayuda? Si tienes dudas, problemas para conectarte a la\n\ +red Tor, o necesitas hablar con un humano, por favor contacta a nuestro\n\ +equipo de soporte a:\n\ +\n\ + help@rt.torproject.org\n\ +\n\ +Estamos listos para responder tus consultas en Inglés, Farsi, Chino,\n\ +Arábico, Francés y Español.""" + +#: Help message +msgid "help_msg" +msgstr "Hola, este es el robot 'GetTor'.\n\ +\n\ +Gracias por tu petición. Estoy aquí para ayudarte a descargar la última\n\ +versión del Tor Browser Bundle.\n\ +\n\ +Por favor responde a este mensaje con una de las siguientes opciones:\n\ +\n\ + windows\n\ + linux\n\ + osx\n\ +\n\ +Y te enviaré las instrucciones de descarga.\n\ +\n\ +Tip: Sólo envía una respuesta en blanco a este mensaje si no estás\n\ +seguro." + +#: Delay message +msgid "delay_msg" +msgstr "Mensaje de demora." diff --git a/lang/xmpp/i18n/en/LC_MESSAGES/en.mo b/lang/xmpp/i18n/en/LC_MESSAGES/en.mo new file mode 100644 index 0000000..2480872 Binary files /dev/null and b/lang/xmpp/i18n/en/LC_MESSAGES/en.mo differ diff --git a/lang/xmpp/i18n/en/LC_MESSAGES/en.po b/lang/xmpp/i18n/en/LC_MESSAGES/en.po new file mode 100644 index 0000000..d242625 --- /dev/null +++ b/lang/xmpp/i18n/en/LC_MESSAGES/en.po @@ -0,0 +1,22 @@ +domain "en" + +#: Links +msgid "links" +msgstr "Links %s-%s:\n %s" + +#: Links +msgid "links_pt" +msgstr "Links-PT for %s-%s:\n %s" + +#: Help +msgid "help" +msgstr "*help*" + +#: Unsupported locale +msgid "unsupported_lc" +msgstr "Unsupported locale" + +#: Internal error +msgid "internal_error" +msgstr "Internal error" + diff --git a/lang/xmpp/i18n/en/LC_MESSAGES/es.mo b/lang/xmpp/i18n/en/LC_MESSAGES/es.mo new file mode 100644 index 0000000..5896536 Binary files /dev/null and b/lang/xmpp/i18n/en/LC_MESSAGES/es.mo differ diff --git a/lang/xmpp/i18n/es/LC_MESSAGES/es.mo b/lang/xmpp/i18n/es/LC_MESSAGES/es.mo new file mode 100644 index 0000000..d54f22c Binary files /dev/null and b/lang/xmpp/i18n/es/LC_MESSAGES/es.mo differ diff --git a/lang/xmpp/i18n/es/LC_MESSAGES/es.po b/lang/xmpp/i18n/es/LC_MESSAGES/es.po new file mode 100644 index 0000000..b6caac5 --- /dev/null +++ b/lang/xmpp/i18n/es/LC_MESSAGES/es.po @@ -0,0 +1,22 @@ +domain "es" + +#: Links +msgid "links" +msgstr "Enlaces para %s-%s:\n %s" + +#: Links +msgid "links_pt" +msgstr "Enlaces-PT para %s-%s:\n %s" + +#: Help +msgid "help" +msgstr "ayuda" + +#: Unsupported locale +msgid "unsupported_lc" +msgstr "Locale no soportado" + +#: Internal error +msgid "internal_error" +msgstr "Error interno" + diff --git a/log/blacklist.log b/log/blacklist.log new file mode 100644 index 0000000..e69de29 diff --git a/log/core.log b/log/core.log new file mode 100644 index 0000000..e69de29 diff --git a/log/smtp.log b/log/smtp.log new file mode 100644 index 0000000..e69de29 diff --git a/log/xmpp.log b/log/xmpp.log new file mode 100644 index 0000000..e69de29 diff --git a/providers/dropbox.links b/providers/dropbox.links new file mode 100644 index 0000000..e0ffaf0 --- /dev/null +++ b/providers/dropbox.links @@ -0,0 +1,25 @@ +[provider] +name = Dropbox + +[key] +fingerprint = 8738 A680 B84B 3031 A630 F2DB 416F 0610 63FE E659 + +[linux] +en = Package (64-bit): https://www.dropbox.com/s/p2l6keaoly2kzce/tor-browser-linux64-3.6.2_en-EN.ta... + ASC signature (64-bit): https://www.dropbox.com/s/b85ecxkoz9126j3/tor-browser-linux64-3.6.2_en-EN.ta... + Package SHA256 checksum (64-bit): 98ea6e4f216f2fb4b69fff9b3a44842c38686ca685f3f55dc48c5d3fb1107be4, + Package (32-bit): https://www.dropbox.com/s/rxfczlz7j8gn6pi/tor-browser-linux32-3.6.2_en-EN.ta... + ASC signature (32-bit): https://www.dropbox.com/s/g5g0havjgunf1un/tor-browser-linux32-3.6.2_en-EN.ta... + Package SHA256 checksum (32-bit): 98ea6e4f216f2fb4b69fff9b3a44842c38686ca685f3f55dc48c5d3fb1107be4 +es = Package (32-bit): https://www.dropbox.com/s/xkv4dvmeuppscs2/tor-browser-linux32-3.6.2_es-ES.ta... + ASC signature (32-bit): https://www.dropbox.com/s/66c5x6jnzrs67vw/tor-browser-linux32-3.6.2_es-ES.ta... + Package SHA256 checksum (32-bit): 98ea6e4f216f2fb4b69fff9b3a44842c38686ca685f3f55dc48c5d3fb1107be4 + + +[windows] +en = Package (32-bit): https://www.dropbox.com/s/oocrw3joj4d8kn8/tor-browser-windows32-3.6.2_en-EN.... + ASC signature (32-bit): https://www.dropbox.com/s/gwbepymnaxvhm94/tor-browser-windows32-3.6.2_en-EN.... + Package SHA256 checksum (32-bit): 98ea6e4f216f2fb4b69fff9b3a44842c38686ca685f3f55dc48c5d3fb1107be4 + +[osx] + diff --git a/providers/dropbox.links.backup b/providers/dropbox.links.backup new file mode 100644 index 0000000..e0ffaf0 --- /dev/null +++ b/providers/dropbox.links.backup @@ -0,0 +1,25 @@ +[provider] +name = Dropbox + +[key] +fingerprint = 8738 A680 B84B 3031 A630 F2DB 416F 0610 63FE E659 + +[linux] +en = Package (64-bit): https://www.dropbox.com/s/p2l6keaoly2kzce/tor-browser-linux64-3.6.2_en-EN.ta... + ASC signature (64-bit): https://www.dropbox.com/s/b85ecxkoz9126j3/tor-browser-linux64-3.6.2_en-EN.ta... + Package SHA256 checksum (64-bit): 98ea6e4f216f2fb4b69fff9b3a44842c38686ca685f3f55dc48c5d3fb1107be4, + Package (32-bit): https://www.dropbox.com/s/rxfczlz7j8gn6pi/tor-browser-linux32-3.6.2_en-EN.ta... + ASC signature (32-bit): https://www.dropbox.com/s/g5g0havjgunf1un/tor-browser-linux32-3.6.2_en-EN.ta... + Package SHA256 checksum (32-bit): 98ea6e4f216f2fb4b69fff9b3a44842c38686ca685f3f55dc48c5d3fb1107be4 +es = Package (32-bit): https://www.dropbox.com/s/xkv4dvmeuppscs2/tor-browser-linux32-3.6.2_es-ES.ta... + ASC signature (32-bit): https://www.dropbox.com/s/66c5x6jnzrs67vw/tor-browser-linux32-3.6.2_es-ES.ta... + Package SHA256 checksum (32-bit): 98ea6e4f216f2fb4b69fff9b3a44842c38686ca685f3f55dc48c5d3fb1107be4 + + +[windows] +en = Package (32-bit): https://www.dropbox.com/s/oocrw3joj4d8kn8/tor-browser-windows32-3.6.2_en-EN.... + ASC signature (32-bit): https://www.dropbox.com/s/gwbepymnaxvhm94/tor-browser-windows32-3.6.2_en-EN.... + Package SHA256 checksum (32-bit): 98ea6e4f216f2fb4b69fff9b3a44842c38686ca685f3f55dc48c5d3fb1107be4 + +[osx] + diff --git a/scripts/blacklist.py b/scripts/blacklist.py new file mode 100644 index 0000000..1aefe1a --- /dev/null +++ b/scripts/blacklist.py @@ -0,0 +1,111 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +# +# This file is part of GetTor, a Tor Browser distribution system. +# +# :authors: Israel Leiva ilv@riseup.net +# see also AUTHORS file +# +# :copyright: (c) 2008-2014, The Tor Project, Inc. +# (c) 2014, Israel Leiva +# +# :license: This is Free Software. See LICENSE for license information. + +import sys +import time +import sqlite3 +import argparse + + +def main(): + """Script for managing blacklisting of users. + + See argparse usage for more details. + + """ + parser = argparse.ArgumentParser(description='Utility for GetTor' + ' blacklisting') + parser.add_argument('database', metavar='database.db', type=str, + help='the database file') + parser.add_argument('-u', '--user', default=None, + help='filter by user hash') + parser.add_argument('-s', '--service', default=None, + help='filter by service') + parser.add_argument('-b', '--blocked', default=None, + help='filter by blocked users') + parser.add_argument('-a', '--add', default=None, nargs=3, + metavar=('USER', 'SERVICE', 'BLOCKED'), + help='add user') + parser.add_argument('-c', '--clean', default=None, const='c', nargs='?', + metavar='user hash', + help='clean table (delete expired blacklistings)') + parser.add_argument('-r', '--requests', default=None, + help='number of requests; everyone with number of' + ' requests greather than this will be cleaned up') + + args = parser.parse_args() + query = '' + con = sqlite3.connect(args.database) + + if args.add: + # add new entry, useful for adding users permanently blocked + query = "INSERT INTO users VALUES('%s', '%s', 1, %s, %s)"\ + % (args.add[0], args.add[1], args.add[2], time.time()) + with con: + cur = con.cursor() + cur.execute(query) + print "Query execute successfully" + elif args.clean: + if args.clean == 'c': + if args.requests: + # delete by number of times + query = "DELETE FROM users WHERE times > %s" % args.requests + with con: + cur = con.cursor() + cur.execute(query) + print "Query executed successfully." + else: + sys.exit("Number of requests missing. See --help.") + else: + # delete by id + query = "DELETE FROM users WHERE id='%s'" % args.clean + with con: + cur = con.cursor() + cur.execute(query) + print "Query execute succcessfully." + else: + query = "SELECT * FROM users" + has_where = False + # filter + if args.service: + query = "%s %s" % (query, "WHERE service='%s'" % args.service) + has_where = True + if args.user: + if has_where: + query = "%s %s" % (query, "AND id='%s'" % args.user) + else: + query = "%s %s" % (query, "WHERE id='%s'" % args.user) + has_where = True + if args.blocked: + if has_where: + query = "%s %s" % (query, "AND blocked=%s" % args.blocked) + has_where = True + else: + query = "%s %s" % (query, "WHERE blocked=%s" % args.blocked) + + with con: + cur = con.cursor() + cur.execute(query) + rows = cur.fetchall() + # show it nice + print "\nNumber of results: %s\n" % len(rows) + cns = [cn[0] for cn in cur.description] + print "%-70s %-10s %-10s %-10s %-s" % (cns[0], cns[1], cns[2], + cns[3], cns[4]) + + for row in rows: + print "%-70s %-10s %-10s %-10s %s" % (row[0], row[1], row[2], + row[3], row[4]) + +if __name__ == "__main__": + main() diff --git a/scripts/create_db.py b/scripts/create_db.py new file mode 100644 index 0000000..ec4ba32 --- /dev/null +++ b/scripts/create_db.py @@ -0,0 +1,57 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +# +# This file is part of GetTor, a Tor Browser distribution system. +# +# :authors: Israel Leiva ilv@riseup.net +# see also AUTHORS file +# +# :copyright: (c) 2008-2014, The Tor Project, Inc. +# (c) 2014, Israel Leiva +# +# :license: This is Free Software. See LICENSE for license information. + +import os +import sqlite3 +import argparse + + +def main(): + """Create/delete GetTor database for managing stats and blacklisting. + + Database file (.db) must be empty. If it doesn't exist, it will be + created. See argparse usage for more details. + + """ + parser = argparse.ArgumentParser(description='Utility for GetTor' + ' database') + parser.add_argument('-c', '--create', default=None, + metavar='path_to_database.db', + help='create database') + parser.add_argument('-d', '--delete', default=None, + metavar='path_to_database.db', + help='delete database') + + args = parser.parse_args() + if args.create: + con = sqlite3.connect(args.create) + with con: + cur = con.cursor() + # table for handling users (i.e. blacklist) + cur.execute("CREATE TABLE users(id TEXT, service TEXT, times INT," + " blocked INT, last_request TEXT)") + # table for stats + # cur.execute("CREATE TABLE requests(service TEXT, type TEXT," + # " os TEXT, lc TEXT, pt INT, year INT, month INT," + # " day INT, status TEXT, logfile TEXT)") + + # for now we will use a counter + cur.execute("CREATE TABLE requests(id INT, counter INT)") + print "Database %s created" % os.path.abspath(args.create) + elif args.delete: + os.remove(os.path.abspath(args.delete)) + print "Database %s deleted" % os.path.abspath(args.delete) + else: + print "See --help for details on usage." +if __name__ == "__main__": + main() diff --git a/scripts/stats.py b/scripts/stats.py new file mode 100644 index 0000000..7fca2af --- /dev/null +++ b/scripts/stats.py @@ -0,0 +1,123 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +# +# This file is part of GetTor, a Tor Browser distribution system. +# +# :authors: Israel Leiva ilv@riseup.net +# see also AUTHORS file +# +# :copyright: (c) 2008-2014, The Tor Project, Inc. +# (c) 2014, Israel Leiva +# +# :license: This is Free Software. See LICENSE for license information. + + +import sqlite3 +import argparse + + +def main(): + """Script for showing stats. + + See argparse usage for more details. + + """ + parser = argparse.ArgumentParser(description='Utility for GetTor stats') + parser.add_argument('database', metavar='database.db', type=str, + help='the database file') + parser.add_argument('-s', '--service', default=None, + help='filter by service') + parser.add_argument('-t', '--type', default=None, + help='filter by type of request') + parser.add_argument('-o', '--os', default=None, + help='filter by OS') + parser.add_argument('-l', '--lc', default=None, + help='filter by locale') + parser.add_argument('-p', '--pt', default=None, + help='filter by PT requests') + parser.add_argument('-y', '--year', default=None, + help='filter by year') + parser.add_argument('-m', '--month', default=None, + help='filter by month') + parser.add_argument('-d', '--day', default=None, + help='filter by day') + parser.add_argument('-u', '--status', default=None, + help='filter by status of the request') + + args = parser.parse_args() + query = 'SELECT * FROM requests' + has_where = False + + # we build the query piece by piece + if args.service: + query = "%s %s" % (query, "WHERE service = '%s'" % args.service) + has_where = True + if args.type: + if has_where: + query = "%s %s" % (query, "AND type = '%s'" % args.type) + else: + query = "%s %s" % (query, "WHERE type = '%s'" % args.type) + has_where = True + if args.os: + if has_where: + query = "%s %s" % (query, "AND os = '%s'" % args.os) + else: + query = "%s %s" % (query, "WHERE os = '%s'" % args.os) + has_where = True + if args.lc: + if has_where: + query = "%s %s" % (query, "AND lc = '%s'" % args.lc) + else: + query = "%s %s" % (query, "WHERE lc = '%s'" % args.lc) + has_where = True + if args.pt: + if has_where: + query = "%s %s" % (query, "AND pt = %s" % args.pt) + else: + query = "%s %s" % (query, "WHERE pt = %s" % args.pt) + has_where = True + if args.year: + if has_where: + query = "%s %s" % (query, "AND year = %s" % args.year) + else: + query = "%s %s" % (query, "WHERE year = %s" % args.year) + has_where = True + if args.month: + if has_where: + query = "%s %s" % (query, "AND month = %s" % args.month) + else: + query = "%s %s" % (query, "WHERE month = %s" % args.month) + has_where = True + if args.day: + if has_where: + query = "%s %s" % (query, "AND day = %s" % args.day) + else: + query = "%s %s" % (query, "WHERE day = %s" % args.day) + has_where = True + if args.status: + if has_where: + query = "%s %s" % (query, "AND status = '%s'" % args.status) + else: + query = "%s %s" % (query, "WHERE status = '%s'" % args.status) + has_where = True + + con = sqlite3.connect(args.database) + + with con: + cur = con.cursor() + cur.execute(query) + rows = cur.fetchall() + # show it nice + print "\nNumber of results: %s\n" % len(rows) + cns = [cn[0] for cn in cur.description] + print "%-10s %-10s %-10s %-10s %-10s %-10s %-10s %-10s"\ + " %-15s %s"\ % (cns[0], cns[1], cns[2], cns[3], cns[4], cns[5], + cns[6], cns[7], cns[8], cns[9]) + + for row in rows: + print "%-10s %-10s %-10s %-10s %-10s %-10s %-10s %-10s"\ + " %-15s %s" % (row[0], row[1], row[2], row[3], row[4], + row[5], row[6], row[7], row[8], row[9]) + +if __name__ == "__main__": + main() diff --git a/smtp.cfg b/smtp.cfg new file mode 100644 index 0000000..671c090 --- /dev/null +++ b/smtp.cfg @@ -0,0 +1,16 @@ +[general] +basedir: /path/to/gettor/smtp +our_domain: torproject.org +core_cfg: /path/to/core.cfg + +[blacklist] +cfg: /path/to/blacklist.cfg +max_requests: 3 +wait_time: 20 + +[i18n] +dir: /path/to/i18n/ + +[log] +level: DEBUG +dir: /path/to/log/ \ No newline at end of file diff --git a/smtp_demo.py b/smtp_demo.py new file mode 100644 index 0000000..0ec341e --- /dev/null +++ b/smtp_demo.py @@ -0,0 +1,22 @@ +#!/usr/bin/env python +import sys + +import gettor.smtp + +service = gettor.smtp.SMTP() + +# For now we simulate mails reading from stdin +# In linux test as follows: +# $ python smtp_demo.py < email.eml + +incoming = sys.stdin.read() +try: + print "Email received!" + service.process_email(incoming) + print "Email sent!" +except gettor.smtp.ConfigError as e: + print "Misconfiguration: " + str(e) +except gettor.smtp.SendEmailError as e: + print "SMTP not working: " + str(e) +except gettor.smtp.InternalError as e: + print "Core module not working: " + str(e) diff --git a/spec/design/blacklist.txt b/spec/design/blacklist.txt deleted file mode 100644 index 34ce40e..0000000 --- a/spec/design/blacklist.txt +++ /dev/null @@ -1,74 +0,0 @@ - Google Summer of Code 2014 GetTor Revamp - Blacklist module - Author: Israel Leiva - israel.leiva@usach.cl - Last update: 2014-05-16 - Version: 0.01 - Changes: First version - -1. Preface - - Since GetTor was created it has been a collection of functions and - classes separated in various modules. As its main purpose was - to serve files over SMTP, almost all current files have SMTP-related - procedures, including black and white lists. The proposed design for - the blacklist module intends to separate GetTor services from the - blacklist procedures. - -2. Blacklist module - - The main functionalities the blacklist module should provide are: - - * Check if a given entry is blacklisted for a given service - * Add/update/remove entries. - * Provide a standard critera to prevent flood. - -3. Design - - The new design should consist of the following files, directories and - functions: - - * lib/gettor/blacklist/: Directory for storing blacklisted users of - different services. - - ----- service1.blacklist: users blocked for service1 - ----- service2.blacklist: users blocked for service2 - - * lib/gettor/blacklist.py: Blacklist module of GetTor. - - isBlacklisted(address, provider) - Check if the given address is in the blacklist of services and - if it acomplish certain restrictions. For example, it could - check when was the last time it was updated on the blacklist. - - -4. Roadmap - - A possible example of how the blacklist module could work: - - a. A service receives a request and call the blacklist module. - b. The blacklist module check the blacklist for that service. - c. If the user (hashed) is present in the blacklist, it checks when - was the last time it was updated. If this date is more than X days - ago, updates the entry with the current date and returns false. If - not, returns true. If the user is not present in the file, it adds - the user with the current date and returns false. - - -5. Discussion - -5.1 Mistakes - - Mistakes concerning the package requested should be consider. If I - send a message asking for a Linux 'es' request but I write 'en' instead - of 'es', should I be able to ask again? or wait until I'm no longer - blacklisted? - -5.2 Users - - The method presented above (Roadmap) should consider weekly or monthly - clean-up of the list. - -5.3 SorryMessage - - May be when a user tries to send too many requests we could send him - a message saying that he won't be able to ask for packages in the next - X days. diff --git a/spec/design/core.txt b/spec/design/core.txt deleted file mode 100644 index ce07238..0000000 --- a/spec/design/core.txt +++ /dev/null @@ -1,155 +0,0 @@ - Google Summer of Code 2014 GetTor Revamp - Core module - Author: Israel Leiva - <israel.leiva@usach.cl, ilv@riseup.net> - Last update: 2014-07-15 - Version: 0.05 - Changes: - [0.05] - Added fingerprint support - [0.04] - Changed log format in 'Design' - Added section 'Features' - Deleted stuff from 'Discussion' and added some others - [0.03] - Changed proposed format for link files to RFC 882 (ConfigParser). - Read configuration from file with ConfigParser. - [0.02] - Combine official mirrors with providers links (as another provider). - Eliminated on demand link generation. Now it reads from files. - Modified description according to PEP-8. - [0.01] - First version. - - -1. Preface - - Since GetTor was created it has been a collection of functions and - classes separated in various modules. As its main purpose was - to serve files over SMTP, almost all current files have SMTP-related - procedures, including address normalization, message composition, etc. - The proposed design for the core module intends to separate GetTor - main functionalities which are independent of the service that - transports the bundles. - -2. Core module - - The main functionalities the core module should provide are: - - * Receive a request with OS version, bundle language, and respond - with the respective links. - * Read links from providers files. - * Log anonymous transactions. - -3. Design - - The new design should consist of the following files, directories and - methods: - - * gettor.cfg: Configuration values, e.g. base directory. - - * providers/: Directory for generated links. Should be specified on - gettor.cfg. - - ----- provider1.links: links from provider1. - ----- provider2.links: links from provider2. - ----- mirrors.links: links of official mirrors. - - All this data is generated automatically. - - * logs/: Directory for logs. Should be specified on gettor.cfg - - ----- all.log - ----- info.log - ----- debug.log - ----- warn.log - ----- error.log - - * Core module of GetTor. - - __init(config_file)__ - Creates a new Core object. It reads its configuration from - the config_file using ConfigParser. - - get_links(operating_system, locale) - Public method to obtain the links. Returns links for - operating_system in locale language. It checks if the operating - system and locale are supported and then calls the private - method _get_links() - - - Example: get_links('linux', 'en') - - _get_links(operating_system, locale) - Gets the links for a specific operating system and locale - according to the options received. It reads all the .links - files inside the providers directory. Each one of these files - should follow the ConfigParser's format. There should be a - section [provider] with the option 'name' for the provider's - name (e.g. Dropbox), and a section [key] with the option - 'fingerprint' for the key's fingerprint that signed the - uploaded packages. - - Following sections should specify the operating system and - its options should be the locale. When more than one link is - available per operating system and locale (always) the links - should be specified as a multiline value. Each link has the - format: - - link link_signature - - Example: - - [provider] - name: Dropbox - - [key] - fingerprint: 123A 456B 789C 012D 345E 678F 901G 234H 567I 890J - - [linux] - en: https://foo.bar https://foo.bar.asc, - https://foo.bar https://foo.bar.asc - - es: https://bar.baz https://bar.baz.asc - - PROVIDER NAME - operating_system locale link package_signature - - NOTE: For now, the official mirrors are considered just as - another provider. - - - _log_request(operating_system, locale) - Log information about the request for future stats (e.g. which - OS from which service is the most required). All logging - should be done with the logging module. - - * Providers: There should be one module/script per provider in charge - of generating the .links file with the proper format, including - the official mirrors. - - -4. Roadmap - - An example of how the core module work: - - a. The SMTP service receives a request. - b. The SMTP calls core.get_links() with the options sent by the user. - c. get_links() calls to _log_request(). - d. get_links() calls to _get_links(). - e. get_links() constructs a message with the information obtained. - f. get_links() returns the message previously constructed. - g. The SMTP service creates a message with the links obtained and - send it to the user. - -5. Discussion - -5.1 Daily logs - - Currently, logs are separated by level of information (debug, info, error). - Is it necessary to do this by days/weeks too? - -6. Features - - Possible features to be added in the future (open to discussion) - - a. Send HTTP links (currently some official mirrors are HTTP only). - diff --git a/spec/design/smtp.txt b/spec/design/smtp.txt deleted file mode 100644 index e86e864..0000000 --- a/spec/design/smtp.txt +++ /dev/null @@ -1,118 +0,0 @@ - Google Summer of Code 2014 GetTor Revamp - SMTP module - Author: Israel Leiva - israel.leiva@usach.cl - Last update: 2014-05-16 - Version: 0.01 - Changes: First version - -1. Preface - - Since GetTor was created it has been a collection of functions and - classes separated in various modules. As its main purpose was - to serve files over SMTP, almost all current files have SMTP-related - procedures, including address normalization, message composition, etc. - The proposed design for the SMTP module intends to separate GetTor - main functionalities from the services, in this case, SMTP. - -2. SMTP module - - The main functionalities the SMTP module should provide are: - - * Receive requests via mail. - * Identify user instructions, such as ask for help or for a specific - bundle (OS version, language). - * Get the required links from the core module. - * Send different types of answers to the user. - * Manage black lists to avoid flood. - * Log requests for stats (anonymous). - -3. Design - - The new design should consist of the following files, directories and - functions: - - * lib/gettor/services/smtp.py: SMTP module of GetTor. - - __init__(configuration path) - Creates an object according to the configuration values. - - processEmail(email object) - Process emails received (by forwarding). - - __parseEmail(email object) - Parse the raw email sent by processMail(). Check for multi-part - emails and then parse the text part. It also tries to get the - locale information from the user's address. - - __parseText(email object) - Parse the text part of an email looking for the package requested. - - __getFrom(email object) - Returns the from address of an email object. - - __getLocale(address) - Tries to get the locale information from an email address. - - __checkBlacklist(address) - Check if the given address is blacklisted by comparing the - hashed address. If address is not present, it's added. If present, - check for the date when it was added. Yet to define how many - days will be considered for blacklisting or if another method - will be used. For this it uses the blacklist module. - - __sendReply(address) - Sends a reply to the user with the links required. It asks for - the links to the core module. - - __sendDelayAlert(address) - If enabled (on configuration), sends a delay message to the user - letting him know that the links are on their way. - - __sendHelp(address) - Sends a message to the user with help instructions. - - __createEmail(from, to, subject, body) - Creates an email object. - - __logRequest(options) - Log information about the request for future stats (e.g. which - OS and language are the most required). If this is called - after a failure, a copy of the email should be stored. - - * BASE_DIR/logs/: Directory for logs. The BASE_DIR should be in the - configuration file. - - ----- yyyy-mm-dd.log: daily log of requests. - - -4. Roadmap - - An example of how the SMTP module should work: - - a. The SMTP service receives a request (via forwarding). - b. The email sender is checked for blacklisting (comparing hashes). - c. The email is parsed, obtaining the package requested and the - locale information. - d. If the email was asking for help, a help reply is sent. - e. If the email was invalid, the process break. This fail is logged - and the email that triggered it, too. - f. If the email was valid and the delay alert is set, then a reply - informing the links are on their way is sent. - g. If the email was valid, the SMTP service asks for the links to the - code module. - h. After that, a reply is sent to the user. - i. In all cases the request is logged (with no user information). - - -5. Discussion - -5.1 Email forwarding - - Are we going to support forwarding emails as ForwardPackage() did in - the old GetTor? - -5.2 Blacklist sublists - - Now with less types of request (two if no forwarding is added), creating - sublists for different types of requests necessary to blacklist and - email address? Or should we blacklist it if it floods anything? - diff --git a/spec/design/twitter.txt b/spec/design/twitter.txt deleted file mode 100644 index 46a178a..0000000 --- a/spec/design/twitter.txt +++ /dev/null @@ -1,99 +0,0 @@ - Google Summer of Code 2014 GetTor Revamp - Twitter module - Author: Israel Leiva - israel.leiva@usach.cl - Last update: 2014-05-16 - Version: 0.01 - Changes: First version - -1. Preface - - Since GetTor was created it has been a collection of functions and - classes separated in various modules. As its main purpose was - to serve files over SMTP, almost all current files have SMTP-related - procedures, including address normalization, message composition, etc. - The proposed design for the Twitter module intends to separate GetTor - main functionalities from the services, in this case, Twitter. - -2. Twitter module - - The main functionalities the Twitter module should provide are: - - * Receive requests via direct messages. - * Identify user instructions, such as ask for help or for a specific - bundle (OS version, language). - * Get the required links from the core module. - * Send different types of answers to the user. - * Split answers to fit Twitter's format. - * Manage black lists to avoid flood. - * Log requests for stats (anonymous). - -3. Design - - The new design should consist of the following files, directories and - functions: - - * lib/gettor/services/Twitter.py: Twitter module of GetTor. - - __init__(configuration path) - Creates an object according to the configuration values. - - processDM(message) - Process direct messages received. - - __parseDM(message) - Parse the direct message received. Check for the package requested - and the locale information. - - __getUser(message) - Gets the user from the message sent. - - __checkBlacklist(user) - Check if the given user is blacklisted by comparing the - hashed user. Yet to define how many days will be considered for - blacklisting or if another method will be used. For this it uses - the blacklist module. - - __sendReply(user) - Sends a reply to the user with the links required. It asks for - the links to the core module and then split them. - - __sendHelp(user) - Sends a message to the user with help instructions. - - __splitMessage(message) - Receives the links message and split it according to Twitter's - format. - - __CheckNewFollowers() - In order to ask for links the user has to follow the GetTor - account. The Twitter module will be constantly checking for - new followers and follow them back. - - __FollowUser(user) - Follow the given user. - - __logRequest(options) - Log information about the request for future stats (e.g. which - OS and language are the most required). If this is called - after a failure, a copy of the DM should be stored. - - * BASE_DIR/logs/: Directory for logs. BASE_DIR should be in the - configuration file. - - ----- yyyy-mm-dd.log: daily log of requests. - - -4. Roadmap - - An example of how the Twitter module should work: - - a. The Twitter account receives a DM. - b. The Twitter service check if is a valid message and if the user is - in the blacklist, and then tries to obtain the package requested and - the locale information. - c. The Twitter service asks for the links to the core module, then it - splits the message received to adopt Twitter's format. - d. One or more DMs are sent back to the user. - e. For all this, the user must follow the GetTor account. The Twitter - service will be constantly checking for new followers and following - them back. - diff --git a/spec/overview.txt b/spec/overview.txt deleted file mode 100644 index 435d256..0000000 --- a/spec/overview.txt +++ /dev/null @@ -1,94 +0,0 @@ - Google Summer of Code 2014 GetTor Revamp - Overview - Author: Israel Leiva - israel.leiva@usach.cl - Last update: 2014-05-16 - Version: 0.01 - Changes: First version - -1. Background - - GetTor was created as a program for serving Tor and related files over - SMTP, thus avoiding direct and indirect censorship of Tor's software, - in particular, the Tor Browser Bundle (TBB). Users interact with GetTor - by sending emails to a specific email address. In the past, after the - user specified his OS and language, GetTor would send him an attachment - with the required package. This worked until the bundles were too large - to be sent as attachments in most email providers. In order to fix this - GetTor started to send links instead. - -2. Current status - - The GetTor status can be summarized in the following points: - - * Emails are sent to gettor@torproject.org - * The GetTor reply contains: TBB links, signatures (with text guides - for verification), mirrors, support instructions in six languages. - * Dropbox links are sent to download the TBB and signatures. - * Users can not ask for packages in their language. - * English-only replies are sent. - * Any email directed to GetTor is replied with the same information, - there is no recognition of instructions. - * Links generation is not fully automated. - * All code is written in Python. Various parts are not currently used. - * Current repositories are [0] and [1]. - -3. Proposal - - The accepted proposal [2] for Google Summer of Code (GSoC) 2014 proposes - rewriting the current GetTor using a modular design, with a core module - that handles the main GetTor functionalities, and several other modules, - one for each service (e.g. SMTP), which can interact with the core and - send replies to the users. Three modules will be developed for the - purposes of GSoC: SMTP, Twitter, Skype|XMPP. - -3.1. Goals - - The main goals of this proposal are the following: - - * Provide old GetTor functionalites, such as replies in several - languages and recognize user instructions. - * Send fewer information in each reply. - * Support more providers for uploading the TBB packages. - * Automate links generation. - * Clearer, modular and well-documented code. - * Possibilty to create new modules for other common services. - -3.2. Design - - Preliminar designs for the core module and the services can be found - in the design/ folder. All services consider creating a python script - to add the logic for using them. For example, there should be a script - that receives the emails and uses the SMTP module. For simplicity, - I've tried to specify mostly the main functions of every module; there - are some functions, like opening and writing files, that were not - considered in this preliminar phase. - -4. Discussion - -4.1. Skype - - My co-mentor for GSoC, Nima, has publicly rejected the idea of creating - a module for Skype and proposed to implement one for XMPP instead. - I've chosen Skype for its popularity, but I have no other main reason - to maintain this option, so it's probable that XMPP transport will be - implemented. - -4.2. Storing links - - My original proposal considered the fact that links could be stored - somewhere with restricted access, ideally a git repository. Nima - mentioned that ideally the links shouldn't be stored. May be this idea - could be used only to the mirrors and providers configuration (see - core module design). - -4.3. Generating unique URLs - - Nima mentioned that unique URLs could be generated for each request, - and in case the user don't have access to SSL, these links could be - served and later deleted or recycled. I like this idea. - -4. References - - [0] https://gitweb.torproject.org/gettor.git - [1] https://gitweb.torproject.org/user/sukhbir/gettor.git - [2] https://ileiva.github.io/gettor_proposal.html - diff --git a/src/LICENSE b/src/LICENSE deleted file mode 100644 index c71c94c..0000000 --- a/src/LICENSE +++ /dev/null @@ -1,31 +0,0 @@ -gettor is distributed under this license: - -Copyright (c) 2008-2014, The Tor Project, Inc. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - - * Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - - * Neither the names of the copyright owners nor the names of its -contributors may be used to endorse or promote products derived from -this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/src/blacklist.cfg b/src/blacklist.cfg deleted file mode 100644 index bb8a3d8..0000000 --- a/src/blacklist.cfg +++ /dev/null @@ -1,6 +0,0 @@ -[general] -db: /path/to/gettor.db - -[log] -level: DEBUG -dir: /path/to/log diff --git a/src/core.cfg b/src/core.cfg deleted file mode 100644 index 0b3231e..0000000 --- a/src/core.cfg +++ /dev/null @@ -1,12 +0,0 @@ -[general] -basedir: /path/to/gettor -db: gettor.db - -[links] -dir: providers/ -os: linux,windows,osx -locales: es,en - -[log] -dir: log/ -level: DEBUG diff --git a/src/core_demo.py b/src/core_demo.py deleted file mode 100644 index 6298f70..0000000 --- a/src/core_demo.py +++ /dev/null @@ -1,19 +0,0 @@ -#!/usr/bin/python -# -# Dummy script to test GetTore's Core module -# - -import gettor.core - -try: - core = gettor.core.Core() - links = core.get_links('dummy service', 'linux', 'es') - print links -except gettor.core.ConfigurationError as e: - print "Misconfiguration: " + str(e) -except gettor.core.UnsupportedOSError as e: - print "Unsupported OS: " + str(e) -except gettor.core.UnsupportedLocaleError as e: - print "Unsupported Locale: " + str(e) -except gettor.core.InternalError as e: - print "Internal error: " + str(e) diff --git a/src/create_links_demo.py b/src/create_links_demo.py deleted file mode 100644 index e97138b..0000000 --- a/src/create_links_demo.py +++ /dev/null @@ -1,19 +0,0 @@ -#!/usr/bin/python -# -# Dummy script to test GetTore's Core module progress -# - -import gettor - -try: - core = gettor.Core('gettor.cfg') - core.create_links_file('Github') - core.add_link('Github', 'linux', 'es', - 'https://foo.bar https://foo.bar.asc 111-222-333-444') - core.add_link('Github', 'linux', 'es', - 'https://foo.bar https://foo.bar.asc 555-666-777-888') - -except ValueError as e: - print "Value error: " + str(e) -except RuntimeError as e: - print "Internal error: " + str(e) diff --git a/src/dropbox.py b/src/dropbox.py deleted file mode 100644 index baaafee..0000000 --- a/src/dropbox.py +++ /dev/null @@ -1,163 +0,0 @@ -# -*- coding: utf-8 -*- -# -# This file is part of GetTor, a Tor Browser Bundle distribution system. -# -# :authors: Israel Leiva ilv@riseup.net -# see also AUTHORS file -# -# :copyright: (c) 2008-2014, The Tor Project, Inc. -# (c) 2014, Israel Leiva -# -# :license: This is Free Software. See LICENSE for license information. - -import re -import os -import gnupg -import hashlib -import dropbox -import gettor.core - - -def valid_bundle_format(file): - """ - Checks for a valid bundle format - (e.g. tor-browser-linux32-3.6.2_es-ES.tar.xz - - Returns True or False if it's valid or not. - """ - - m = re.search( - 'tor-browser-(\w+)\d\d-\d.\d.\d_(\w\w)-\w+.tar.xz', - file) - if m: - return True - else: - return False - - -def get_bundle_info(file): - """Get the operating system and locale from a bundle string. - - it raises a ValueError if the bundle doesn't have a valid format - (although you should probably call valid_bundle_format first). - It returns the pair of strings operating system, locale. - - """ - m = re.search( - 'tor-browser-(\w+)\d\d-\d.\d.\d_(\w\w)-\w+.tar.xz', - file) - if m: - operating_system = m.group(1) - locale = m.group(2) - return operating_system, locale - else: - raise ValueError("Bundle invalid format %s" % file) - -def get_file_sha256(file): - """Get the sha256 of a file.""" - - # as seen on the internet - BLOCKSIZE = 65536 - hasher = hashlib.sha256() - with open(file, 'rb') as afile: - buf = afile.read(BLOCKSIZE) - while len(buf) > 0: - hasher.update(buf) - buf = afile.read(BLOCKSIZE) - return hasher.hexdigest() - -def upload_files(basedir, client): - """Upload files from 'basedir' to Dropbox. - - It looks for files ending with 'tar.xz' inside 'basedir'. It - raises ValueError in case the given file doesn't have a .asc file. - It raises UploadError if something goes wrong while uploading the - files to Dropbox. All files are uploaded to '/'. - - Returns a list with the names of the uploaded files. - - """ - files = [] - - p = re.compile('.*.tar.xz$') - - for name in os.listdir(basedir): - path = os.path.abspath(os.path.join(basedir, name)) - if os.path.isfile(path) and p.match(path) and valid_bundle_format(name): - files.append(name) - - for file in files: - asc = file + '.asc' - abs_file = os.path.abspath(os.path.join(basedir, file)) - abs_asc = os.path.abspath(os.path.join(basedir, asc)) - - if not os.path.isfile(abs_asc): - raise ValueError("%s doesn't exist!" % asc) - - # Chunk upload for big files - to_upload = open(abs_file, 'rb') - size = os.path.getsize(abs_file) - uploader = client.get_chunked_uploader(to_upload, size) - while uploader.offset < size: - try: - upload = uploader.upload_chunked() - except rest.ErrorResponse, e: - UploadError("An error ocurred while uploading %s" % abs_file) - uploader.finish(file) - - # This should be small, upload it simple - to_upload_asc = open(abs_asc, 'rb') - response = client.put_file(asc, to_upload_asc) - - return files - -if __name__ == '__main__': - # to-do: use config file - app_key = '' - app_secret = '' - access_token = '' - upload_dir = 'upload/' - - # important: this must be the key that signed the packages - tbb_key = 'tbb-key.asc' - - client = dropbox.client.DropboxClient(access_token) - - # import key fingerprint - gpg = gnupg.GPG() - key_data = open(tbb_key).read() - import_result = gpg.import_keys(key_data) - fp = import_result.results[0]['fingerprint'] - - # make groups of four characters to make fingerprint more readable - # e.g. 123A 456B 789C 012D 345E 678F 901G 234H 567I 890J - readable = ' '.join(fp[i:i+4] for i in xrange(0, len(fp), 4)) - - try: - uploaded_files = upload_files(upload_dir, client) - # use default config - core = gettor.core.Core() - - # erase old links - core.create_links_file('Dropbox', readable) - - for file in uploaded_files: - # build file names - asc = file + '.asc' - abs_file = os.path.abspath(os.path.join(upload_dir, file)) - abs_asc = os.path.abspath(os.path.join(upload_dir, asc)) - - sha_file = get_file_sha256(abs_file) - - # build links - link_file = client.share(file) - link_asc = client.share(asc) - link = link_file[u'url'] + ' ' + link_asc[u'url'] + ' ' + sha_file - - # add links - operating_system, locale = get_bundle_info(file) - core.add_link('Dropbox', operating_system, locale, link) - except (ValueError, RuntimeError) as e: - print str(e) - except dropbox.rest.ErrorResponse as e: - print str(e) diff --git a/src/gettor/__init__.py b/src/gettor/__init__.py deleted file mode 100644 index c87425a..0000000 --- a/src/gettor/__init__.py +++ /dev/null @@ -1 +0,0 @@ -# yes it's empty, of such a fullness diff --git a/src/gettor/blacklist.py b/src/gettor/blacklist.py deleted file mode 100644 index 1c721bb..0000000 --- a/src/gettor/blacklist.py +++ /dev/null @@ -1,143 +0,0 @@ -# -*- coding: utf-8 -*- -# -# This file is part of GetTor, a Tor Browser Bundle distribution system. -# -# :authors: Israel Leiva ilv@riseup.net -# see also AUTHORS file -# -# :copyright: (c) 2008-2014, The Tor Project, Inc. -# (c) 2014, Israel Leiva -# -# :license: This is Free Software. See LICENSE for license information. - -import os -import time -import logging -import sqlite3 -import datetime -import ConfigParser - -import db -import utils - -"""Blacklist module for managing blacklisting of users.""" - - -class BlacklistError(Exception): - pass - - -class Blacklist(object): - """Manage blacklisting of users. - - Public methods: - - is_blacklisted(): Check if someone is blacklisted. - - Exceptions: - - ConfigurationError: Bad configuration. - BlacklistError: User is blacklisted. - - """ - - def __init__(self, cfg=None): - """Create new object by reading a configuration file. - - :param: cfg (string) path of the configuration file. - - """ - # define a set of default values - DEFAULT_CONFIG_FILE = 'blacklist.cfg' - - logging.basicConfig(format='[%(levelname)s] %(asctime)s - %(message)s', - datefmt="%Y-%m-%d %H:%M:%S") - log = logging.getLogger(__name__) - config = ConfigParser.ConfigParser() - - if cfg is None or not os.path.isfile(cfg): - cfg = DEFAULT_CONFIG_FILE - log.info("Using default configuration") - - log.info("Reading configuration file %s" % cfg) - config.read(cfg) - - try: - dbname = config.get('general', 'db') - self.db = db.DB(dbname) - except ConfigParser.Error as e: - log.warning("Couldn't read 'db' from 'general' (%s)" % cfg) - raise ConfigurationError("Error with conf. See log file.") - - try: - self.logdir = config.get('log', 'dir') - except ConfigParser.Error as e: - log.warning("Couldn't read 'dir' from 'log' (%s)" % cfg) - raise ConfigurationError("Error with conf. See log file.") - - try: - self.loglevel = config.get('log', 'level') - except ConfigParser.Error as e: - log.warning("Couldn't read 'level' from 'log' (%s)" % cfg) - raise ConfigurationError("Error with conf. See log file.") - - # keep log levels separated - self.log = utils.filter_logging(log, self.logdir, self.loglevel) - self.log.setLevel(logging.getLevelName(self.loglevel)) - log.debug('Redirecting logging to %s' % self.logdir) - - # stop logging on stdout from now on - log.propagate = False - self.log.debug("New blacklist object created") - - def is_blacklisted(self, user, service, max_req, wait_time): - """Check if a user is blacklisted. - - The user is blacklisted if: - - a) The 'blocked' field is set to one, meaning that is permanently - blacklisted. - - b) Does too many requests on a short period of time. For now, a user - that makes more than 'max_req' requests should wait 'wait_time' - minutes to make a new request. - - :param: user (string) the hashed user. - :param: service (string) the service the user is making a request to. - :param: max_req (int) maximum number of requests a user can make - in a row. - :param: wait_time (int) amount of time the user must wait before - making requests again after 'max_req' requests is reached. - For now this is considered in minutes. - - :raise: BlacklistError if the user is blacklisted - - """ - r = self.db.get_user(user, service) - if r: - # permanently blacklisted - if r['blocked']: - self.log.info("Request from blocked user %s" % user) - self.db.update_user(user, service, r['times']+1, 1) - raise BlacklistError("Blocked user") - # don't be greedy - elif r['times'] >= max_req: - last = datetime.datetime.fromtimestamp(float( - r['last_request'])) - next = last + datetime.timedelta(minutes=wait_time) - - if datetime.datetime.now() < next: - self.log.info("Too many requests from user %s" % user) - self.db.update_user(user, service, r['times']+1, 0) - raise BlacklistError("Too many requests") - else: - # fresh user again! - self.log.debug("Request after wait time, cleaning up for" - " %s" % user) - self.db.update_user(user, service, 1, 0) - else: - self.log.debug("Adding up a request for %s" % user) - self.db.update_user(user, service, r['times']+1, 0) - else: - self.log.debug("New request for %s" % user) - self.db.add_user(user, service, 0) diff --git a/src/gettor/core.py b/src/gettor/core.py deleted file mode 100644 index 8b1f51a..0000000 --- a/src/gettor/core.py +++ /dev/null @@ -1,419 +0,0 @@ -# -*- coding: utf-8 -*- -# -# This file is part of GetTor, a Tor Browser Bundle distribution system. -# -# :authors: Israel Leiva ilv@riseup.net -# see also AUTHORS file -# -# :copyright: (c) 2008-2014, The Tor Project, Inc. -# (c) 2014, Israel Leiva -# -# :license: This is Free Software. See LICENSE for license information. - -import os -import re -import inspect -import logging -import tempfile -import ConfigParser - -import db -import utils - -"""Core module for getting links from providers.""" - - -class ConfigurationError(Exception): - pass - - -class UnsupportedOSError(Exception): - pass - - -class UnsupportedLocaleError(Exception): - pass - - -class LinkFormatError(Exception): - pass - - -class LinkFileError(Exception): - pass - - -class InternalError(Exception): - pass - - -class Core(object): - """Get links from providers and deliver them to other modules. - - Public methods: - - get_links(): Get the links for the OS and locale requested. - create_links_file(): Create a file to store links of a provider. - add_link(): Add a link to a links file of a provider. - get_supported_os(): Get a list of supported operating systems. - get_supported_lc(): Get a list of supported locales. - - Exceptions: - - UnsupportedOSError: Request for an unsupported operating system. - UnsupportedLocaleError: Request for an unsupported locale. - ConfigurationError: Something's misconfigured. - LinkFormatError: The link added doesn't seem legit. - LinkFileError: Error related to the links file of a provider. - InternalError: Something went wrong internally. - - """ - - def __init__(self, cfg=None): - """Create a new core object by reading a configuration file. - - :param: cfg (string) the path of the configuration file. - :raise: ConfigurationError if the configuration file doesn't exists - or if something goes wrong while reading options from it. - - """ - # define a set of default values - DEFAULT_CONFIG_FILE = 'core.cfg' - - logging.basicConfig(format='[%(levelname)s] %(asctime)s - %(message)s', - datefmt="%Y-%m-%d %H:%M:%S") - logger = logging.getLogger(__name__) - config = ConfigParser.ConfigParser() - - if cfg is None or not os.path.isfile(cfg): - cfg = DEFAULT_CONFIG_FILE - logger.info("Using default configuration") - - logger.info("Reading configuration file %s" % cfg) - config.read(cfg) - - try: - self.basedir = config.get('general', 'basedir') - except ConfigParser.Error as e: - logger.warning("Couldn't read 'basedir' from 'general' (%s)" % cfg) - raise ConfigurationError("Error with conf. See log file.") - - try: - dbname = config.get('general', 'db') - dbname = os.path.join(self.basedir, dbname) - self.db = db.DB(dbname) - except ConfigParser.Error as e: - logger.warning("Couldn't read 'db' from 'general' (%s)" % cfg) - raise ConfigurationError("Error with conf. See log file.") - - try: - self.linksdir = config.get('links', 'dir') - self.linksdir = os.path.join(self.basedir, self.linksdir) - except ConfigParser.Error as e: - logger.warning("Couldn't read 'links' from 'dir' (%s)" % cfg) - raise ConfigurationError("Error with conf. See log file.") - - try: - self.supported_lc = config.get('links', 'locales') - except ConfigParser.Error as e: - logger.warning("Couldn't read 'locales' from 'links' (%s)" % cfg) - raise ConfigurationError("Error with conf. See log file.") - - try: - self.supported_os = config.get('links', 'os') - except ConfigParser.Error as e: - logger.warning("Couldn't read 'os' from 'links' (%s)" % cfg) - raise ConfigurationError("Error with conf. See log file.") - - try: - self.loglevel = config.get('log', 'level') - except ConfigParser.Error as e: - logger.warning("Couldn't read 'level' from 'log' (%s)" % cfg) - raise ConfigurationError("Error with conf. See log file.") - - try: - self.logdir = config.get('log', 'dir') - self.logdir = os.path.join(self.basedir, self.logdir) - except ConfigParser.Error as e: - logger.warning("Couldn't read 'dir' from 'log' %s)" % cfg) - raise ConfigurationError("Error with conf. See log file.") - - # keep log levels separated - self.log = utils.filter_logging(logger, self.logdir, self.loglevel) - # self.log.setLevel(logging.getLevelName(self.loglevel)) - self.log.info('Redirecting logging to %s' % self.logdir) - - # stop logging on stdout from now on - self.log.propagate = False - self.log.debug("New core object created") - - def get_links(self, service, os, lc): - """Get links for OS in locale. - - This method should be called from the services modules of - GetTor (e.g. SMTP). To make it easy we let the module calling us - specify the name of the service (for stats purpose). - - :param: service (string) the service trying to get the links. - :param: os (string) the operating system. - :param: lc (string) tthe locale. - - :raise: UnsupportedOSError if the operating system is not supported. - :raise: UnsupportedLocaleError if the locale is not supported. - :raise: InternalError if something goes wrong while internally. - - :return: (string) the links. - - """ - - # Which module called us and what was asking for? - self.log.info("%s did a request for %s, %s." % (service, os, lc)) - - if lc not in self.supported_lc: - self.log.warning("Request for unsupported locale: %s" % lc) - raise UnsupportedLocaleError("Locale %s not supported" % lc) - - if os not in self.supported_os: - self.log.warning("Request for unsupported OS: %s" % os) - raise UnsupportedOSError("OS %s not supported " % os) - - # this could change in the future, let's leave it isolated. - links = self._get_links(os, lc) - - if links is None: - self.log.error("Couldn't get the links", exc_info=True) - raise InternalError("Something went wrong internally. See logs for" - " detailed info.") - - self.log.info("Returning the links") - return links - - def _get_links(self, os, lc): - """Internal method to get the links. - - Looks for the links inside each provider file. This should only be - called from get_links() method. - - :param: os (string) the operating system. - :param: lc (string) the locale. - - :return: (string/None) links on success, None otherwise. - - """ - - # read the links files using ConfigParser - # see the README for more details on the format used - links = [] - - # look for files ending with .links - p = re.compile('.*.links$') - - for name in os.listdir(self.linksdir): - path = os.path.abspath(os.path.join(self.linksdir, name)) - if os.path.isfile(path) and p.match(path): - links.append(path) - - # let's create a dictionary linking each provider with the links - # found for os and lc. This way makes it easy to check if no - # links were found - providers = {} - - self.log.info("Reading links from providers directory") - for name in links: - self.log.debug("Reading %s" % name) - # We're reading files listed on linksdir, so they must exist! - config = ConfigParser.ConfigParser() - config.read(name) - - try: - pname = config.get('provider', 'name') - except ConfigParser.Error as e: - self.log.warning("Couldn't get 'name' from 'provider' (%s)" - % name) - raise InternalError("Error while reading %s links file. See " - "log file" % name) - - self.log.debug("Checking if %s has links for %s in %s" % - (pname, os, lc)) - - try: - providers[pname] = config.get(os, lc) - except ConfigParser.Error as e: - self.log.warning("Couldn't get %s from %s (%s)" % - (lc, os, name)) - raise InternalError("Error while reading %s links file. See " - "log file" % name) - - # each provider must have a fingerprint of the key used to - # sign the uploaded packages - try: - self.log.debug("Trying to get fingerprint from %s", pname) - fingerprint = config.get('key', 'fingerprint') - providers[pname] = providers[pname] + "\nFingerprint: " - providers[pname] = providers[pname] + fingerprint - self.log.debug("Fingerprint added %s", fingerprint) - except ConfigParser.Error as e: - self.log.warning("Couldn't get 'fingerprint' from 'key' " - "(%s)" % name) - raise InternalError("Error while reading %s links file. See " - "log file" % name) - - # create the final links list with all providers - all_links = [] - - self.log.debug("Joining all links found for %s in %s" % (os, lc)) - for key in providers.keys(): - all_links.append( - "\n%s\n%s\n" % (key, ''.join(providers[key])) - ) - - if all_links: - return "".join(all_links) - else: - self.log.warning("Trying to get supported os and locales, but" - " no links were found") - return None - - def get_supported_os(self): - """Public method to get the list of supported operating systems. - - :return: (list) the supported operating systems. - - """ - return self.supported_os.split(',') - - def get_supported_lc(self): - """Public method to get the list of supported locales. - - :return: (list) the supported locales. - - """ - return self.supported_lc.split(',') - - def create_links_file(self, provider, fingerprint): - """Public method to create a links file for a provider. - - This should be used by all providers since it writes the links - file with the proper format. It backs up the old links file - (if exists) and creates a new one. - - :param: provider (string) the provider (links file will use this - name in slower case). - :param: fingerprint (string) the fingerprint of the key that signed - the packages to be uploaded to the provider. - - """ - linksfile = os.path.join(self.linksdir, provider.lower() + '.links') - linksfile_backup = "" - self.log.info("Request to create new %s" % linksfile) - - if os.path.isfile(linksfile): - # backup the old file in case something fails - linksfile_backup = linksfile + '.backup' - self.log.info("Backing up %s (%s)" % (linksfile, linksfile_backup)) - os.rename(linksfile, linksfile_backup) - - try: - # this creates an empty links file (with no links) - content = ConfigParser.RawConfigParser() - content.add_section('provider') - content.set('provider', 'name', provider) - content.add_section('key') - content.set('key', 'fingerprint', fingerprint) - for os in self.supported_os: - content.add_section(os) - with open(linksfile, 'w+') as f: - content.write(f) - self.log.info("New %s created" % linksfile) - except Exception as e: - if linksfile_backup: - os.rename(linksfile_backup, linksfile) - raise LinkFileError("Error while trying to create new links file.") - - def add_link(self, provider, os, lc, link): - """Public method to add a link to a provider's links file. - - Use ConfigParser to add a link into the os section, under the lc - option. It checks for valid format; the provider's script should - use the right format (see design). - - :param: provider (string) the provider. - :param: os (string) the operating system. - :param: lc (string) the locale. - :param: link (string) link to be added. The format should be as - follows: - - https://pkg_url https://asc_url - - where pkg_url is the url for the bundle and asc_url is the - url for the asc of the bundle. - - :raise: UnsupportedOSError if the operating system is not supported. - :raise: UnsupportedLocaleError if the locale is not supported. - :raise: LinkFileError if there is no links file for the provider. - :raise: LinkFormatError if the link format doesn't seem legit. - :raise: InternalError if the links file doesn't have a section for - the OS requested. This *shouldn't* happen because it means - the file wasn't created correctly. - - """ - linksfile = os.path.join(self.linksdir, provider.lower() + '.links') - - # don't try to add unsupported stuff - if lc not in self.supported_lc: - self.log.warning("Can't add link for unsupported lc: %s" % lc) - raise UnsupportedLocaleError("Locale %s not supported" % lc) - - if os not in self.supported_os: - self.log.warning("Can't add link for unsupported os: %s" % os) - raise UnsupportedOSError("OS %s not supported" % os) - - # check if the link has a legit format - # e.g. https://db.tt/JjfUTb04 https://db.tt/MEfUTb04 - p = re.compile('^https://.+%5Cshttps://.+$') - - if not p.match(link): - self.log.warning("Can't add an invalid link: %s" % link) - raise LinkFormatError("Link '%s' doesn't seem legit" % link) - - if os.path.isfile(linksfile): - content = ConfigParser.RawConfigParser() - content.readfp(open(linksfile)) - # check if exists and entry for locale; if not, create it - try: - links = content.get(os, lc) - links = links + ",\n" + link - content.set(oc, lc, links) - with open(linksfile, 'w') as f: - content.write(f) - self.log.info("Link %s added to %s %s in %s" % - (link, os, lc, provider)) - except ConfigParser.NoOptionError: - content.set(os, lc, link) - with open(linksfile, 'w') as f: - content.write(f) - self.log.info("Link %s added to %s-%s in %s" % - (link, os, lc, provider)) - except ConfigParser.NoSectionError: - # this shouldn't happen, but just in case - self.log.error("Unknown section %s in links file") - raise InternalError("Unknown %s section in links file" % os) - else: - raise LinkFileError("There is no links file for %s" % provider) - - def add_request_to_db(self, service, type, os, lc, pt, status, logfile): - """Add request to database. - - This is for keeping stats about what is the most, less requested - and stuff like that. Hopefully it will help to improve user experience. - - :param: type (string) the type of the request. - :param: os (string) the operating system. - :param: lc (string) the locale. - :param: pt (bool) true if the user asked about pt, false otherwise. - :param: status (string) short text describing the status. - :param: logfile (string) path of the logfile of the email in case - something went really wrong (address blacklisted/malformed). - - """ - self.db.add_request(service, type, os, lc, pt, status, logfile) diff --git a/src/gettor/db.py b/src/gettor/db.py deleted file mode 100644 index 1f6cfbd..0000000 --- a/src/gettor/db.py +++ /dev/null @@ -1,113 +0,0 @@ -# -*- coding: utf-8 -*- -# -# This file is part of GetTor, a Tor Browser Bundle distribution system. -# -# :authors: Israel Leiva ilv@riseup.net -# see also AUTHORS file -# -# :copyright: (c) 2008-2014, The Tor Project, Inc. -# (c) 2014, Israel Leiva -# -# :license: This is Free Software. See LICENSE for license information. - -import time -import sqlite3 -import datetime - -"""DB interface for comunicating with sqlite3""" - - -class DB(object): - """ - - Public methods: - - add_request(): add a request to the database (requests table). - get_user(): get user info from the database (users table). - add_user(): add a user to the database (users table). - update_user(): update a user on the database (users table). - - """ - - def __init__(self, dbname): - """Create a new db object. - - :param: dbname (string) the path of the database. - - """ - self.con = sqlite3.connect(dbname) - self.con.row_factory = sqlite3.Row - - def add_request(self, service, type, os, lc, pt, status, logfile): - """Add a request to the database. - - This is for keeping stats about what is the most, less requested - and stuff like that. Hopefully it will help to improve user experience. - - :param: type (string) the type of the request. - :param: os (string) the operating system. - :param: lc (string) the locale. - :param: pt (bool) true if the user asked about pt, false otherwise. - :param: status (string) short text describing the status. - :param: logfile (string) path of the logfile of the email in case - something went really wrong (address blacklisted/malformed). - - """ - now = datetime.datetime.now() - - with self.con: - cur = self.con.cursor() - cur.execute("INSERT INTO requests VALUES(?,?,?,?,?,?,?,?,?,?)", - (service, type, os, lc, pt, now.year, now.month, - now.day, status, logfile)) - - def get_user(self, user, service): - """Get user info from the database. - - :param: user (string) unique (hashed) string that represents the user. - :param: service (string) the service related to the user (e.g. SMTP). - - :return: (dict) the user information, with fields as indexes - (e.g. row['user']). - - """ - with self.con: - cur = self.con.cursor() - cur.execute("SELECT * FROM users WHERE id =? AND service =?", - (user, service)) - - row = cur.fetchone() - return row - - def add_user(self, user, service, blocked): - """Add a user to the database. - - We add a user with one 'times' and the current time as 'last_request' - by default. - - :param: user (string) unique (hashed) string that represents the user. - :param: service (string) the service related to the user (e.g. SMTP). - :param: blocked (int) one if user is blocked, zero otherwise. - - """ - with self.con: - cur = self.con.cursor() - cur.execute("INSERT INTO users VALUES(?,?,?,?,?)", - (user, service, 1, blocked, str(time.time()))) - - def update_user(self, user, service, times, blocked): - """Update a user on the database. - - We update the user info with the current time as 'last_request'. - - :param: user (string) unique (hashed) string that represents the user. - :param: service (string) the service related to the user (e.g. SMTP). - :param: times (int) the number of requests the user has made. - :param: blocked (int) one if user is blocked, zero otherwise. - - """ - with self.con: - cur = self.con.cursor() - cur.execute("UPDATE users SET times =?, blocked =?," - " last_request =? WHERE id =? AND service =?", - (times, blocked, str(time.time()), user, service)) diff --git a/src/gettor/smtp.py b/src/gettor/smtp.py deleted file mode 100644 index b4fa3cd..0000000 --- a/src/gettor/smtp.py +++ /dev/null @@ -1,603 +0,0 @@ -# -*- coding: utf-8 -*- -# -# This file is part of GetTor, a Tor Browser Bundle distribution system. -# -# :authors: Israel Leiva ilv@riseup.net -# see also AUTHORS file -# -# :copyright: (c) 2008-2014, The Tor Project, Inc. -# (c) 2014, Israel Leiva -# -# :license: This is Free Software. See LICENSE for license information. - - -import os -import re -import sys -import time -import email -import gettext -import logging -import smtplib -import datetime -import ConfigParser - -from email.mime.text import MIMEText - -import core -import utils -import blacklist - -"""SMTP module for processing email requests.""" - - -class ConfigurationError(Exception): - pass - - -class AddressError(Exception): - pass - - -class SendEmailError(Exception): - pass - - -class InternalError(Exception): - pass - - -class SMTP(object): - """Receive and reply requests by email. - - Public methods: - - process_email(): Process the email received. - - Exceptions: - - ConfigurationError: Bad configuration. - AddressError: Address of the sender malformed. - SendEmailError: SMTP server not responding. - InternalError: Something went wrong internally. - - """ - - def __init__(self, cfg=None): - """Create new object by reading a configuration file. - - :param: cfg (string) path of the configuration file. - - """ - # define a set of default values - DEFAULT_CONFIG_FILE = 'smtp.cfg' - - logging.basicConfig(format='[%(levelname)s] %(asctime)s - %(message)s', - datefmt="%Y-%m-%d %H:%M:%S") - log = logging.getLogger(__name__) - config = ConfigParser.ConfigParser() - - if cfg is None or not os.path.isfile(cfg): - cfg = DEFAULT_CONFIG_FILE - log.info("Using default configuration") - - log.info("Reading configuration file %s" % cfg) - config.read(cfg) - - try: - self.basedir = config.get('general', 'basedir') - except ConfigParser.Error as e: - log.warning("Couldn't read 'basedir' from 'general' (%s)" % cfg) - raise ConfigurationError("Error with conf. See log file.") - - try: - self.our_domain = config.get('general', 'our_domain') - except ConfigParser.Error as e: - log.warning("Couldn't read 'our_domain' from 'general' (%s)" % cfg) - raise ConfigurationError("Error with conf. See log file.") - - try: - core_cfg = config.get('general', 'core_cfg') - except ConfigParser.Error as e: - log.warning("Couldn't read 'core_cfg' from 'general' (%s)" % cfg) - raise ConfigurationError("Error with conf. See log file.") - - try: - blacklist_cfg = config.get('blacklist', 'cfg') - self.bl = blacklist.Blacklist(blacklist_cfg) - except ConfigParser.Error as e: - log.warning("Couldn't read 'cfg' from 'blacklist' (%s)" % cfg) - raise ConfigurationError("Error with conf. See log file.") - - try: - self.bl_max_req = config.get('blacklist', 'max_requests') - self.bl_max_req = int(self.bl_max_req) - except ConfigParser.Error as e: - log.warning("Couldn't read 'max_requests' from 'blacklist' (%s)" - % cfg) - raise ConfigurationError("Error with conf. See log file.") - - try: - self.bl_wait_time = config.get('blacklist', 'wait_time') - self.bl_wait_time = int(self.bl_wait_time) - except ConfigParser.Error as e: - log.warning("Couldn't read 'wait_time' from 'blacklist' (%s)" - % cfg) - raise ConfigurationError("Error with conf. See log file.") - - try: - self.i18ndir = config.get('i18n', 'dir') - self.i18ndir = os.path.join(self.basedir, self.i18ndir) - except ConfigParser.Error as e: - log.warning("Couldn't read 'dir' from 'i18n' (%s)" % cfg) - raise ConfigurationError("Error with conf. See log file.") - - try: - self.logdir = config.get('log', 'dir') - self.logdir = os.path.join(self.basedir, self.logdir) - except ConfigParser.Error as e: - log.warning("Couldn't read 'dir' from 'log' (%s)" % cfg) - raise ConfigurationError("Error with conf. See log file.") - - try: - self.logdir_emails = config.get('log', 'emails_dir') - self.logdir_emails = os.path.join(self.logdir, self.logdir_emails) - except ConfigParser.Error as e: - log.warning("Couldn't read 'emails_dir' from 'log' (%s)" % cfg) - raise ConfigurationError("Error with conf. See log file.") - - try: - self.loglevel = config.get('log', 'level') - except ConfigParser.Error as e: - log.warning("Couldn't read 'level' from 'log' (%s)" % cfg) - raise ConfigurationError("Error with conf. See log file.") - - # use default values - self.core = core.Core(core_cfg) - - # keep log levels separated - self.log = utils.filter_logging(log, self.logdir, self.loglevel) - self.log.setLevel(logging.getLevelName(self.loglevel)) - log.debug('Redirecting logging to %s' % self.logdir) - - # stop logging on stdout from now on - log.propagate = False - self.log.debug("New smtp object created") - - def _log_email(self, addr, content): - """Log a request. - - This should be called when something goes wrong. It saves the - email content that triggered the malfunctioning. - - :param: addr (string) the address of the sender. - :param: content (string) the content of the email received. - - :return: (string) the path of the logfile of the email. - """ - # we store the sha256 of the original address in order to know when - # specific addresses are doing weird requests - filename = "%s.log" % str(time.time()) - path = os.path.join(self.logdir_emails, filename) - abs_path = os.path.abspath(path) - - log_file = open(abs_path, 'w+') - log_file.write("Address: %s " % addr) - log_file.write("\nBody:\n%s" % content) - log_file.close() - self.log.debug("Logging request from %s in %s" % (addr, abs_path)) - - return filename - - def _is_blacklisted(self, addr): - """Check if a user is blacklisted. - - :param: addr (string) the hashed address of the user. - - :return: true is the address is blacklisted, false otherwise. - - """ - self.log.debug("Checking if address %s is blacklisted" % addr) - - try: - self.bl.is_blacklisted(addr, 'SMTP', self.bl_max_req, - self.bl_wait_time) - return False - except blacklist.BlacklistError as e: - self.log.info("Blacklisted address %s. Reason: %s" % (addr, e)) - return True - - def _get_lc(self, addr): - """Get the locale from an email address. - - Process the email received and look for the locale in the recipient - address (e.g. gettor+en@torproject.org). If no locale found, english - by default. - - :param: (string) the email address we want to get the locale from. - - :return: (string) the locale (english if none). - - """ - self.log.debug("Trying to obtain locale from recipient address") - - # if no match found, english by default - lc = 'en' - - # look for gettor+locale@torproject.org - m = re.match('gettor+(\w\w)@\w+.\w+', addr) - if m: - self.log.debug("Request for locale %s" % m.groups()) - lc = "%s" % m.groups() - - return lc.lower() - - def _get_normalized_address(self, addr): - """Get normalized address. - - We look for anything inside the last '<' and '>'. Code taken from - the old GetTor (utils.py). - - :param: addr (string) the address we want to normalize. - - :raise: AddressError if the address can't be normalized. - - :return: (string) the normalized address. - - """ - if '<' in addr: - idx = addr.rindex('<') - addr = addr[idx:] - m = re.search(r'<([^>]*)>', addr) - if m is None: - self.log.info("Malformed address: %s" % addr) - raise AddressError("Couldn't extract normalized address " - "from %s" % self_get_sha256(addr)) - addr = m.group(1) - return addr - - def _get_content(self, email): - """Get the body content of an email. - - :param: email (object) the email object to extract the content from. - - :return: (string) body of the message. - - """ - self.log.debug("Getting the body content of the email") - maintype = email.get_content_maintype() - if maintype == 'multipart': - for part in email.get_payload(): - if part.get_content_maintype() == 'text': - return part.get_payload() - elif maintype == 'text': - return email.get_payload() - - def _get_msg(self, msgid, lc): - """Get message identified by msgid in a specific locale. - - :param: msgid (string) the identifier of a string. - :param: lc (string) the locale. - - :return: (string) the message from the .po file. - - """ - self.log.debug("Getting message '%s' for locale %s" % (msgid, lc)) - # obtain the content in the proper language - t = gettext.translation(lc, self.i18ndir, languages=[lc]) - _ = t.ugettext - - msgstr = _(msgid) - return msgstr - - def _parse_email(self, msg, addr): - """Parse the email received. - - Get the locale and parse the text for the rest of the info. - - :param: msg (string) the content of the email to be parsed. - :param: addr (string) the address of the recipient (i.e. us). - - :return: (list) 4-tuple with locale, os and type of request. - - """ - self.log.debug("Parsing email") - - req = self._parse_text(msg) - lc = self._get_lc(addr) - req['lc'] = lc - - return req - - def _parse_text(self, msg): - """Parse the text part of the email received. - - Try to figure out what the user is asking, namely, the type - of request, the package and os required (if applies). - - :param: msg (string) the content of the email to be parsed. - - :return: (list) 3-tuple with the type of request, os and pt info. - - """ - self.log.debug("Parsing email text part") - - # by default we asume the request is asking for help - req = {} - req['type'] = 'help' - req['os'] = None - req['pt'] = False - - # core knows what OS are supported - supported_os = self.core.get_supported_os() - - # we must search word by word, otherwise we could misinterpret - # stuff (i.e. 'option' will match .*pt.*) - found_os = False - found_help = False - lines = msg.split(' ') - for word in lines: - # check for help request - if not found_os and re.match('help', word, re.IGNORECASE): - self.log.info("Request for help found") - req['type'] = 'help' - found_help = True - break - # check for os - if not found_os and not found_help: - for os in supported_os: - if re.match(os, word, re.IGNORECASE): - req['os'] = os - req['type'] = 'links' - self.log.debug("Request for links found") - found_os = True - break - # check if the user is asking for terms related to pt - if re.match(".*obfs.*|pluggable|transport|pt", - word, re.IGNORECASE): - self.log.info("Request for PT found") - req['pt'] = True - - return req - - def _create_email(self, from_addr, to_addr, subject, msg): - """Create an email object. - - This object will be used to construct the reply. - - :param: from_addr (string) the address of the sender. - :param: to_addr (string) the address of the recipient. - :param: subject (string) the subject of the email. - :param: msg (string) the content of the email. - - :return: (object) the email object. - - """ - self.log.debug("Creating email object for replying") - email_obj = MIMEText(msg) - email_obj.set_charset("utf-8") - email_obj['Subject'] = subject - email_obj['From'] = from_addr - email_obj['To'] = to_addr - - return email_obj - - def _send_email(self, from_addr, to_addr, subject, msg): - """Send an email. - - Take a 'from' and 'to' addresses, a subject and the content, creates - the email and send it. - - :param: from_addr (string) the address of the sender. - :param: to_addr (string) the address of the recipient. - :param: subject (string) the subject of the email. - :param: msg (string) the content of the email. - - """ - email_obj = self._create_email(from_addr, to_addr, subject, msg) - - try: - s = smtplib.SMTP("localhost") - s.sendmail(from_addr, to_addr, email_obj.as_string()) - s.quit() - except smtplib.SMTPException as e: - self.log.error("Couldn't send the email: %s" % str(e)) - raise SendEmailError("Error with SMTP: %s" % str(e)) - - self.log.debug("Email sent") - - def _send_links(self, links, lc, os, from_addr, to_addr, pt): - """Send links to the user. - - Get the message in the proper language (according to the locale), - replace variables and send the email. - - :param: links (string) the links to be sent. - :param: lc (string) the locale. - :param: os (string) the operating system. - :param: from_addr (string) the address of the sender. - :param: to_addr (string) the address of the recipient. - :param: pt (bool) true if the used asked for PT info; false otherwise. - - """ - self.log.debug("Request for links in %s" % lc) - - # obtain the content in the proper language and send it - links_subject = self._get_msg('links_subject', lc) - links_msg = self._get_msg('links_msg', lc) - links_msg = links_msg % (os, lc, links) - - # don't forget to check if user did a PT request - if pt: - # if so, we get the links message + info about PT included. - links_subject = self._get_msg('links_pt_subject', lc) - links_msg = self._get_msg('links_pt_msg', lc) - links_msg = links_msg % (os, lc, links) - - try: - self._send_email(from_addr, to_addr, links_subject, links_msg) - except SendEmailError as e: - self.log.warning("Couldn't send links message") - raise InternalError("Error while sending links message") - - def _send_help(self, lc, from_addr, to_addr): - """Send help message. - - Get the message in the proper language (according to the locale), - replace variables (if any) and send the email. - - :param: lc (string) the locale. - :param: from_addr (string) the address of the sender. - :param: to_addr (string) the address of the recipient. - - """ - self.log.debug("Request for help in %s" % lc) - - # obtain the content in the proper language and send it - help_subject = self._get_msg('help_subject', lc) - help_msg = self._get_msg('help_msg', lc) - - try: - self._send_email(from_addr, to_addr, help_subject, help_msg) - except SendEmailError as e: - self.log.warning("Couldn't send help message") - raise InternalError("Error while sending help message") - - def _send_unsupported_lc(self, lc, os, from_addr, to_addr): - """Send unsupported locale message. - - Get the message for unsupported locale in english replace variables - (if any) and send the email. - - :param: lc (string) the locale. - :param: os (string) the operating system. - :param: from_addr (string) the address of the sender. - :param: to_addr (string) the address of the recipient. - - """ - - # obtain the content in english and send it - unsupported_lc_subject = self._get_msg('unsupported_lc_subject', 'en') - unsupported_lc_msg = self._get_msg('unsupported_lc_msg', 'en') - unsupported_lc_msg = unsupported_lc_msg % lc - - try: - self._send_email(from_addr, to_addr, unsupported_lc_subject, - unsupported_lc_msg) - - except SendEmailError as e: - self.log.warning("Couldn't send unsupported locale message") - raise InternalError("Error while sending unsupported locale" - "message") - - def process_email(self, raw_msg): - """Process the email received. - - Create an email object from the string received. The processing - flow is as following: - - - Check for blacklisted address. - - Parse the email. - - Check the type of request. - - Send reply. - - :param: raw_msg (string) the email received. - - :raise: InternalError if something goes wrong while asking for the - links to the Core module. - - """ - parsed_msg = email.message_from_string(raw_msg) - content = self._get_content(parsed_msg) - from_addr = parsed_msg['From'] - to_addr = parsed_msg['To'] - bogus_request = False - logfile = '' - status = '' - req = None - - try: - # two ways for a request to be bogus: address malformed or - # blacklisted - try: - norm_from_addr = self._get_normalized_address(from_addr) - except AddressError as e: - status = 'malformed' - bogus_request = True - # it might be interesting to know what triggered this - logfile = self._log_email('malformed', content) - - if norm_from_addr: - anon_addr = utils.get_sha256(norm_from_addr) - - if self._is_blacklisted(anon_addr): - status = 'blacklisted' - bogus_request = True - # it might be interesting to know extra info - logfile = self._log_email(anon_addr, content) - - if not bogus_request: - # try to figure out what the user is asking - req = self._parse_email(content, to_addr) - - # our address should have the locale requested - our_addr = "gettor+%s@%s" % (req['lc'], self.our_domain) - - # two possible options: asking for help or for the links - self.log.info("New request for %s" % req['type']) - if req['type'] == 'help': - # make sure we can send emails - try: - self._send_help(req['lc'], our_addr, norm_from_addr) - except SendEmailError as e: - status = 'internal_error' - raise InternalError("Something's wrong with the SMTP " - "server: %s" % str(e)) - - elif req['type'] == 'links': - try: - self.log.info("Asking core for links in %s for %s" % - (req['lc'], req['os'])) - - links = self.core.get_links('SMTP', req['os'], - req['lc']) - - except core.UnsupportedLocaleError as e: - self.log.info("Request for unsupported locale: %s (%s)" - % (req['lc'], str(e))) - # if we got here, the address of the sender should - # be valid so we send him/her a message about the - # unsupported locale - status = 'unsupported_lc' - self._send_unsupported_lc(req['lc'], req['os'], - our_addr, norm_from_addr) - return - - # if core fails, we fail too - except (core.InternalError, core.ConfigurationError) as e: - status = 'core_error' - self.log.error("Something went wrong with Core: %s" - % str(e)) - raise InternalError("Error obtaining the links.") - - # make sure we can send emails - try: - self._send_links(links, req['lc'], req['os'], our_addr, - norm_from_addr, req['pt']) - except SendEmailError as e: - status = 'internal_error' - raise SendEmailError("Something's wrong with the SMTP " - "server: %s" % str(e)) - status = 'success' - finally: - # keep stats - if req: - self.core.add_request_to_db('SMTP', - req['type'], req['os'], - req['lc'], req['pt'], - status, logfile) - else: - # invalid request, so no info about it - # logfiles were created for this - self.core.add_request_to_db('SMTP', '', '', '', '', - status, logfile) diff --git a/src/gettor/utils.py b/src/gettor/utils.py deleted file mode 100644 index 53891ea..0000000 --- a/src/gettor/utils.py +++ /dev/null @@ -1,104 +0,0 @@ -# -*- coding: utf-8 -*- -# -# This file is part of GetTor, a Tor Browser Bundle distribution system. -# -# :authors: Israel Leiva ilv@riseup.net -# see also AUTHORS file -# -# :copyright: (c) 2008-2014, The Tor Project, Inc. -# (c) 2014, Israel Leiva -# -# :license: This is Free Software. See LICENSE for license information. - -import os -import logging -import hashlib - -"""Common utilities for GetTor modules.""" - -class SingleLevelFilter(logging.Filter): - """Filter logging levels to create separated logs. - - Public methods: - - filter(): fitler logging levels. - - """ - - def __init__(self, passlevel, reject): - """Create a new object with level to be filtered. - - If reject value is false, all but the passlevel will be filtered. - Useful for logging in separated files. - - :param: passlevel (string) the name of a logging level. - - """ - - self.passlevel = passlevel - self.reject = reject - - def filter(self, record): - """Do the actual filtering.""" - if self.reject: - return (record.levelno != self.passlevel) - else: - return (record.levelno == self.passlevel) - -def filter_logging(logger, dir, level): - """Create separated files for each level of logging. - - :param: logger (object) a logging object. - :param: dir (string) directory to put the log files. - :param: level (string) the level of logging for the all.log file. - - :return: (object) a logging object. - - """ - # Keep a good format - string_format = '[%(levelname)7s] %(asctime)s - %(message)s' - formatter = logging.Formatter(string_format, '%Y-%m-%d %H:%M:%S') - - # Keep logs separated (and filtered) - # all.log depends on level specified as param - all_log = logging.FileHandler(os.path.join(dir, 'all.log'), mode='a+') - all_log.setLevel(logging.getLevelName(level)) - all_log.setFormatter(formatter) - - debug_log = logging.FileHandler(os.path.join(dir, 'debug.log'), mode='a+') - debug_log.setLevel('DEBUG') - debug_log.addFilter(SingleLevelFilter(logging.DEBUG, False)) - debug_log.setFormatter(formatter) - - info_log = logging.FileHandler(os.path.join(dir, 'info.log'), mode='a+') - info_log.setLevel('INFO') - info_log.addFilter(SingleLevelFilter(logging.INFO, False)) - info_log.setFormatter(formatter) - - warn_log = logging.FileHandler(os.path.join(dir, 'warn.log'), mode='a+') - warn_log.setLevel('WARNING') - warn_log.addFilter(SingleLevelFilter(logging.WARNING, False)) - warn_log.setFormatter(formatter) - - error_log = logging.FileHandler(os.path.join(dir, 'error.log'), mode='a+') - error_log.setLevel('ERROR') - error_log.addFilter(SingleLevelFilter(logging.ERROR, False)) - error_log.setFormatter(formatter) - - logger.addHandler(all_log) - logger.addHandler(info_log) - logger.addHandler(debug_log) - logger.addHandler(warn_log) - logger.addHandler(error_log) - - return logger - -def get_sha256(string): - """Get sha256 of a string. - - :param: (string) the string to be hashed. - - :return: (string) the sha256 of string. - - """ - return str(hashlib.sha256(string).hexdigest()) diff --git a/src/gettor/xmpp.py b/src/gettor/xmpp.py deleted file mode 100644 index f296559..0000000 --- a/src/gettor/xmpp.py +++ /dev/null @@ -1,378 +0,0 @@ -# -*- coding: utf-8 -*- -# -# This file is part of GetTor, a Tor Browser Bundle distribution system. -# -# :authors: Israel Leiva ilv@riseup.net -# see also AUTHORS file -# -# :copyright: (c) 2008-2014, The Tor Project, Inc. -# (c) 2014, Israel Leiva -# -# :license: This is Free Software. See LICENSE for license information. - -import os -import re -import sys -import time -import gettext -import hashlib -import logging -import ConfigParser - -from sleekxmpp import ClientXMPP -from sleekxmpp.exceptions import IqError, IqTimeout - -import core -import utils -import blacklist - - -"""XMPP module for processing requests.""" - - -class Bot(ClientXMPP): - """XMPP bot. - - Handle messages and pass them to XMPP module for parsing. - - """ - - def __init__(self, jid, password, xmpp_obj): - ClientXMPP.__init__(self, jid, password) - - self.xmpp = xmpp_obj - self.add_event_handler("session_start", self.session_start) - self.add_event_handler("message", self.message) - - def session_start(self, event): - self.send_presence() - self.get_roster() - - try: - self.get_roster() - except IqError as err: - logging.error('There was an error getting the roster') - logging.error(err.iq['error']['condition']) - self.disconnect() - except IqTimeout: - logging.error('Server is taking too long to respond') - self.disconnect() - - def message(self, msg): - if msg['type'] in ('chat', 'normal'): - msg_to_send = self.xmpp.parse_request(msg['from'], msg['body']) - if msg_to_send: - msg.reply(msg_to_send).send() - - -class ConfigurationError(Exception): - pass - - -class InternalError(Exception): - pass - - -class XMPP(object): - """Receive and reply requests by XMPP. - - Public methods: - - parse_request(): parses a message and tries to figure out what the user - is asking for. - - Exceptions: - - ConfigurationError: Bad configuration. - InternalError: Something went wrong internally. - - """ - - def __init__(self, cfg=None): - """Create new object by reading a configuration file. - - :param: cfg (string) the path of the configuration file. - - """ - # define a set of default values - DEFAULT_CONFIG_FILE = 'xmpp.cfg' - - logging.basicConfig(format='[%(levelname)s] %(asctime)s - %(message)s', - datefmt="%Y-%m-%d %H:%M:%S") - log = logging.getLogger(__name__) - config = ConfigParser.ConfigParser() - - if cfg is None or not os.path.isfile(cfg): - cfg = DEFAULT_CONFIG_FILE - log.info("Using default configuration") - - log.info("Reading configuration file %s" % cfg) - config.read(cfg) - - try: - self.user = config.get('account', 'user') - except ConfigParser.Error as e: - log.warning("Couldn't read 'user' from 'account' (%s)" % cfg) - raise ConfigurationError("Error with conf. See log file.") - - try: - self.password = config.get('account', 'password') - except ConfigParser.Error as e: - log.warning("Couldn't read 'password' from 'account' (%s)" % cfg) - raise ConfigurationError("Error with conf. See log file.") - - try: - self.basedir = config.get('general', 'basedir') - except ConfigParser.Error as e: - log.warning("Couldn't read 'basedir' from 'general' (%s)" % cfg) - raise ConfigurationError("Error with conf. See log file.") - - try: - self.core_cfg = config.get('general', 'core_cfg') - except ConfigParser.Error as e: - log.warning("Couldn't read 'core_cfg' from 'general' (%s)" % cfg) - raise ConfigurationError("Error with conf. See log file.") - - try: - blacklist_cfg = config.get('blacklist', 'cfg') - self.bl = blacklist_cfg - except ConfigParser.Error as e: - log.warning("Couldn't read 'cfg' from 'blacklist' (%s)" % cfg) - raise ConfigurationError("Error with conf. See log file.") - - try: - self.bl_max_req = config.get('blacklist', 'max_requests') - self.bl_max_req = int(self.bl_max_req) - except ConfigParser.Error as e: - log.warning("Couldn't read 'max_requests' from 'blacklist' (%s)" - % cfg) - raise ConfigurationError("Error with conf. See log file.") - - try: - self.bl_wait_time = config.get('blacklist', 'wait_time') - self.bl_wait_time = int(self.bl_wait_time) - except ConfigParser.Error as e: - log.warning("Couldn't read 'wait_time' from 'blacklist' (%s)" - % cfg) - raise ConfigurationError("Error with conf. See log file.") - - try: - self.i18ndir = config.get('i18n', 'dir') - self.i18ndir = os.path.join(self.basedir, self.i18ndir) - except ConfigParser.Error as e: - log.warning("Couldn't read 'dir' from 'i18n' (%s)" % cfg) - raise ConfigurationError("Error with conf. See log file.") - - try: - self.logdir = config.get('log', 'dir') - self.logdir = os.path.join(self.basedir, self.logdir) - except ConfigParser.Error as e: - log.warning("Couldn't read 'dir' from 'log' (%s)" % cfg) - raise ConfigurationError("Error with conf. See log file.") - - try: - self.logdir_msgs = config.get('log', 'msgs_dir') - self.logdir_msgs = os.path.join(self.logdir, self.logdir_msgs) - except ConfigParser.Error as e: - log.warning("Couldn't read 'msgs_dir' from 'log' (%s)" % cfg) - raise ConfigurationError("Error with conf. See log file.") - - try: - self.loglevel = config.get('log', 'level') - except ConfigParser.Error as e: - log.warning("Couldn't read 'level' from 'log' (%s)" % cfg) - raise ConfigurationError("Error with conf. See log file.") - - # keep log levels separated - self.log = utils.filter_logging(log, self.logdir, self.loglevel) - self.log.setLevel(logging.getLevelName(self.loglevel)) - log.debug('Redirecting logging to %s' % self.logdir) - - # stop logging on stdout from now on - log.propagate = False - self.log.debug("New xmpp object created") - - def start_bot(self): - """Start the bot for handling requests. - - Start a new sleekxmpp bot. - - """ - - self.log.debug("Calling sleekmppp bot") - xmpp = Bot(self.user, self.password, self) - xmpp.connect() - xmpp.process(block=True) - - def _is_blacklisted(self, account): - """Check if a user is blacklisted. - - :param: addr (string) the hashed address of the user. - - :return: true is the address is blacklisted, false otherwise. - - """ - anon_acc = utils.get_sha256(account) - bl = blacklist.Blacklist(self.bl) - self.log.debug("Checking if address %s is blacklisted" % anon_acc) - - try: - bl.is_blacklisted(anon_acc, 'XMPP', self.bl_max_req, - self.bl_wait_time) - return False - except blacklist.BlacklistError as e: - self.log.info("Blacklisted address %s. Reason: %s" % (anon_acc, e)) - return True - - def _get_msg(self, msgid, lc): - """Get message identified by msgid in a specific locale. - - :param: msgid (string) the identifier of a string. - :param: lc (string) the locale. - - :return: (string) the message from the .po file. - - """ - self.log.debug("Getting message '%s' for locale %s" % (msgid, lc)) - # obtain the content in the proper language - t = gettext.translation(lc, self.i18ndir, languages=[lc]) - _ = t.ugettext - - msgstr = _(msgid) - return msgstr - - def _parse_text(self, msg, core_obj): - """Parse the text part of a message. - - Split the message in words and look for patterns for locale, - operating system and built-in pluggable transport info. - - :param: msg (string) the message received. - :param: core_obj (object) the object of gettor core module. - - :return: request (list) 4-tuple with locale, os, type of request - and pt info. - - """ - self.log.debug("Starting text parsing") - # core knows what OS are supported - supported_os = core_obj.get_supported_os() - supported_lc = core_obj.get_supported_lc() - - # default values - req = {} - req['lc'] = 'en' - req['os'] = '' - req['type'] = 'help' - req['pt'] = False - found_lc = False - found_os = False - found_help = False - - # analyze every word - # request shouldn't be more than 10 words long, so there should - # be a limit for the amount of words - for word in msg.split(' '): - # check for help request - if not found_os and re.match('help', word, re.IGNORECASE): - self.log.info("Request for help found") - req['type'] = 'help' - found_help = True - # look for locale, os and pt - if not found_lc: - for lc in supported_lc: - if re.match(lc, word, re.IGNORECASE): - found_lc = True - req['lc'] = lc - self.log.debug("Found locale: %s" % lc) - if not found_os and not found_help: - for os in supported_os: - if re.match(os, word, re.IGNORECASE): - found_os = True - req['os'] = os - req['type'] = 'links' - self.log.debug("Found OS: %s" % os) - if re.match("obfs|plugabble|transport|pt", word, re.IGNORECASE): - req['pt'] = True - self.log.debug("Found PT request") - - return req - - def parse_request(self, account, msg): - """Process the request received. - - Check if the user is not blacklisted and then check the body of - the message to find out what is asking. - - :param: account (string) the account that did the request. - :param: msg (string) the body of the message sent to us. - - :return: (string/None) the message to be sent to the user via the - bot, or None if the user is blacklisted. - - """ - bogus_request = False - reply = '' - logfile = '' - status = '' - req = None - core_obj = core.Core(self.core_cfg) - - try: - if self._is_blacklisted(str(account)): - status = 'blacklisted' - bogus_request = True - - if not bogus_request: - self.log.debug("Request seems legit, let's parse it") - # let's try to guess what the user is asking - req = self._parse_text(str(msg), core_obj) - - if req['type'] == 'help': - status = 'success' - self.log.debug("Got a help request") - reply = self._get_msg('help', req['lc']) - elif req['type'] == 'links': - self.log.debug("Got a links request") - try: - links = core_obj.get_links("XMPP", req['os'], - req['lc']) - # did the user asked for PT stuff? - if req['pt']: - self.log.debug("Also asked for PT info") - reply = self._get_msg('links_pt', req['lc']) - reply = reply % (req['os'], req['lc'], links) - else: - reply = self._get_msg('links', req['lc']) - reply = reply % (req['os'], req['lc'], links) - - status = 'success' - except (core.ConfigurationError, core.InternalError) as e: - # if core failes, send the user an error message, but - # keep going - status = 'core_error' - self.log.debug("Something went wrong with Core") - reply = self._get_msg('internal_error', req['lc']) - - # if the user asked for an unsupported locale, warn him - # and keep going - except core.UnsupportedLocaleError as e: - status = 'unsupported_lc' - self.log.debug("User asked for unsupported locale") - reply = self._get_msg('unsupported_lc', req['lc']) - finally: - # keep stats - self.log.debug("Request processed, saving stats.") - - if req: - core_obj.add_request_to_db('XMPP', - req['type'], req['os'], - req['lc'], req['pt'], - status, logfile) - else: - # invalid request, so no info about it - # logfiles were created for this - core_obj.add_request_to_db('XMPP', '', '', '', '', - status, logfile) - - return reply diff --git a/src/i18n/en/LC_MESSAGES/en.mo b/src/i18n/en/LC_MESSAGES/en.mo deleted file mode 100644 index e686fcb..0000000 Binary files a/src/i18n/en/LC_MESSAGES/en.mo and /dev/null differ diff --git a/src/i18n/en/LC_MESSAGES/en.po b/src/i18n/en/LC_MESSAGES/en.po deleted file mode 100644 index 6f78da2..0000000 --- a/src/i18n/en/LC_MESSAGES/en.po +++ /dev/null @@ -1,95 +0,0 @@ -domain "en" - -#: Links subject -msgid "links_subject" -msgstr "[GetTor] Links for your request" - -#: Links subject (PT) -msgid "links_pt_subject" -msgstr "[GetTor] Links for your request" - -#: Help subject -msgid "help_subject" -msgstr "[GetTor] Help" - -#: Delay subject -msgid "delay_subject" -msgstr "[GetTor] Delay message" - -# Unsupported locale subject -msgid "unsupported_locale_subject" -msgstr "[GetTor] Unsupported locale" - -# Unsupported locale message -msgid "unsupported_locale_msg" -msgstr "The locale you requested '%s' is not supported." - -#: Links message -msgid "links_msg" -msgstr "Thank you for your request for %s-%s.\n\ -\n\ -Here are the download links:\n\ -\n\ -===\n\ -Tor Browser Bundle:\n\ -===\n\ -%s\n\ -===\n\ -\n\ -===\n\ -Support:\n\ -===\n\ -\n\ -Still need help? If you have any questions, trouble connecting to Tor\n\ -network, or need to talk to a human, please contact our support team at:\n\ -\n\ - help@rt.torproject.org\n\ -\n\ -We are ready to answer your queries in English, Farsi, Chinese, Arabic,\n\ -French and Spanish." - -#: Links message (PT) -msgid "links_pt_msg" -msgstr "Thank you for your request for %s-%s.\n\ -\n\ -Here are the download links:\n\ -\n\ -===\n\ -Tor Browser Bundle:\n\ -===\n\ -%s\n\ -===\n\ -Info about pluggable transports.\n\ -\n\ -===\n\ -Support:\n\ -===\n\ -\n\ -Still need help? If you have any questions, trouble connecting to Tor\n\ -network, or need to talk to a human, please contact our support team at:\n\ -\n\ - help@rt.torproject.org\n\ -\n\ -We are ready to answer your queries in English, Farsi, Chinese, Arabic,\n\ -French and Spanish." - -#: Help message -msgid "help_msg" -msgstr "Hello, this is the 'GetTor' robot.\n\ -\n\ -Thank you for your request. I am here to help you download the latest\n\ -Tor Browser Bundle.\n\ -\n\ -Please reply to this message with one of the options below:\n\ -\n\ - windows\n\ - linux\n\ - osx\n\ -\n\ -And I will send you the download instructions quickly.\n\ -\n\ -Tip: Just send a blank reply to this message if you are not sure." - -#: Delay message -msgid "delay_msg" -msgstr "Delay message." diff --git a/src/i18n/es/LC_MESSAGES/es.mo b/src/i18n/es/LC_MESSAGES/es.mo deleted file mode 100644 index c21fe7b..0000000 Binary files a/src/i18n/es/LC_MESSAGES/es.mo and /dev/null differ diff --git a/src/i18n/es/LC_MESSAGES/es.po b/src/i18n/es/LC_MESSAGES/es.po deleted file mode 100644 index bc4b5a8..0000000 --- a/src/i18n/es/LC_MESSAGES/es.po +++ /dev/null @@ -1,94 +0,0 @@ -domain "es" - -#: Links subject -msgid "links_subject" -msgstr "[GetTor] Enlaces para tu petición" - -#: Links subject (PT) -msgid "links_pt_subject" -msgstr "[GetTor] Enlaces para tu petición" - -#: Help subject -msgid "help_subject" -msgstr "[GetTor] Ayuda" - -#: Delay subject -msgid "delay_subject" -msgstr "[GetTor] Mensaje de demora" - -# Unsupported locale subject -msgid "unsupported_locale_subject" -msgstr "[GetTor] Locale no soportado" - -# Unsupported locale message -msgid "unsupported_locale_msg" -msgstr "El locale especificado %s no está soportado." - -#: Links message -msgid "links_msg" -msgstr """Gracias por tu petición para %s-%s.\n\ -\n\ -Aquí están los links de descarga:\n\ -\n\ -===\n\ -%s\n\ -===\n\ -\n\ -===\n\ -Soporte:\n\ -===\n\ -\n\ -¿Aún necesitas ayuda? Si tienes dudas, problemas para conectarte a la\n\ -red Tor, o necesitas hablar con un humano, por favor contacta a nuestro\n\ -equipo de soporte a:\n\ -\n\ - help@rt.torproject.org\n\ -\n\ -Estamos listos para responder tus consultas en Inglés, Farsi, Chino,\n\ -Arábico, Francés y Español.""" - -#: Links message (PT) -msgid "links_pt_msg" -msgstr """Gracias por tu petición para %s-%s.\n\ -\n\ -Aquí están los links de descarga:\n\ -\n\ -===\n\ -%s\n\ -===\n\ -Tip: Información sobre pluggable transports.\n\ -\n\ -===\n\ -Soporte:\n\ -===\n\ -\n\ -¿Aún necesitas ayuda? Si tienes dudas, problemas para conectarte a la\n\ -red Tor, o necesitas hablar con un humano, por favor contacta a nuestro\n\ -equipo de soporte a:\n\ -\n\ - help@rt.torproject.org\n\ -\n\ -Estamos listos para responder tus consultas en Inglés, Farsi, Chino,\n\ -Arábico, Francés y Español.""" - -#: Help message -msgid "help_msg" -msgstr "Hola, este es el robot 'GetTor'.\n\ -\n\ -Gracias por tu petición. Estoy aquí para ayudarte a descargar la última\n\ -versión del Tor Browser Bundle.\n\ -\n\ -Por favor responde a este mensaje con una de las siguientes opciones:\n\ -\n\ - windows\n\ - linux\n\ - osx\n\ -\n\ -Y te enviaré las instrucciones de descarga.\n\ -\n\ -Tip: Sólo envía una respuesta en blanco a este mensaje si no estás\n\ -seguro." - -#: Delay message -msgid "delay_msg" -msgstr "Mensaje de demora." diff --git a/src/log/all.log b/src/log/all.log deleted file mode 100644 index f7eb32f..0000000 --- a/src/log/all.log +++ /dev/null @@ -1,21 +0,0 @@ - -[ INFO] 2014-06-20 20:51:38 - Redirecting logging to ./log/ -[ DEBUG] 2014-06-20 20:51:38 - New core object created -[ INFO] 2014-06-20 20:51:38 - Request to create new ./providers/dropbox.links -[ INFO] 2014-06-20 20:51:38 - Backing up ./providers/dropbox.links to ./providers/dropbox.links.backup -[ INFO] 2014-06-20 20:51:38 - New ./providers/dropbox.links created -[ INFO] 2014-06-20 20:51:39 - Link https://db.tt/jp3Ytnzh https://db.tt/MDfUTb04 111-222-333-444 added to linux es in Dropbox -[ INFO] 2014-06-20 20:51:43 - Redirecting logging to ./log/ -[ DEBUG] 2014-06-20 20:51:43 - New core object created -[ INFO] 2014-06-20 20:51:43 - <module '__main__' from 'core_demo.py'> did a request for linux, es. -[ INFO] 2014-06-20 20:51:43 - Reading links from providers directory -[ DEBUG] 2014-06-20 20:51:43 - -- Reading /home/ilv/Proyectos/github/gettor/src/providers/mirrors.links -[ DEBUG] 2014-06-20 20:51:43 - -- Checking if Official mirrors has links for linux in es -[ DEBUG] 2014-06-20 20:51:43 - -- Reading /home/ilv/Proyectos/github/gettor/src/providers/dropbox.links -[ DEBUG] 2014-06-20 20:51:43 - -- Checking if Dropbox has links for linux in es -[ DEBUG] 2014-06-20 20:51:43 - -- Reading /home/ilv/Proyectos/github/gettor/src/providers/gdrive.links -[ DEBUG] 2014-06-20 20:51:43 - -- Checking if Google Drive has links for linux in es -[ DEBUG] 2014-06-20 20:51:43 - -- Reading /home/ilv/Proyectos/github/gettor/src/providers/github.links -[ DEBUG] 2014-06-20 20:51:43 - -- Checking if Github has links for linux in es -[ DEBUG] 2014-06-20 20:51:43 - Joining all links found for linux in es -[ INFO] 2014-06-20 20:51:43 - Returning the links diff --git a/src/log/debug.log b/src/log/debug.log deleted file mode 100644 index 9698f90..0000000 --- a/src/log/debug.log +++ /dev/null @@ -1,12 +0,0 @@ - -[ DEBUG] 2014-06-20 20:51:38 - New core object created -[ DEBUG] 2014-06-20 20:51:43 - New core object created -[ DEBUG] 2014-06-20 20:51:43 - -- Reading /home/ilv/Proyectos/github/gettor/src/providers/mirrors.links -[ DEBUG] 2014-06-20 20:51:43 - -- Checking if Official mirrors has links for linux in es -[ DEBUG] 2014-06-20 20:51:43 - -- Reading /home/ilv/Proyectos/github/gettor/src/providers/dropbox.links -[ DEBUG] 2014-06-20 20:51:43 - -- Checking if Dropbox has links for linux in es -[ DEBUG] 2014-06-20 20:51:43 - -- Reading /home/ilv/Proyectos/github/gettor/src/providers/gdrive.links -[ DEBUG] 2014-06-20 20:51:43 - -- Checking if Google Drive has links for linux in es -[ DEBUG] 2014-06-20 20:51:43 - -- Reading /home/ilv/Proyectos/github/gettor/src/providers/github.links -[ DEBUG] 2014-06-20 20:51:43 - -- Checking if Github has links for linux in es -[ DEBUG] 2014-06-20 20:51:43 - Joining all links found for linux in es diff --git a/src/log/error.log b/src/log/error.log deleted file mode 100644 index 8b13789..0000000 --- a/src/log/error.log +++ /dev/null @@ -1 +0,0 @@ - diff --git a/src/log/info.log b/src/log/info.log deleted file mode 100644 index 06d7160..0000000 --- a/src/log/info.log +++ /dev/null @@ -1,10 +0,0 @@ - -[ INFO] 2014-06-20 20:51:38 - Redirecting logging to ./log/ -[ INFO] 2014-06-20 20:51:38 - Request to create new ./providers/dropbox.links -[ INFO] 2014-06-20 20:51:38 - Backing up ./providers/dropbox.links to ./providers/dropbox.links.backup -[ INFO] 2014-06-20 20:51:38 - New ./providers/dropbox.links created -[ INFO] 2014-06-20 20:51:39 - Link https://db.tt/jp3Ytnzh https://db.tt/MDfUTb04 111-222-333-444 added to linux es in Dropbox -[ INFO] 2014-06-20 20:51:43 - Redirecting logging to ./log/ -[ INFO] 2014-06-20 20:51:43 - <module '__main__' from 'core_demo.py'> did a request for linux, es. -[ INFO] 2014-06-20 20:51:43 - Reading links from providers directory -[ INFO] 2014-06-20 20:51:43 - Returning the links diff --git a/src/log/warn.log b/src/log/warn.log deleted file mode 100644 index 8b13789..0000000 --- a/src/log/warn.log +++ /dev/null @@ -1 +0,0 @@ - diff --git a/src/providers/dropbox.links b/src/providers/dropbox.links deleted file mode 100644 index 7cccca0..0000000 --- a/src/providers/dropbox.links +++ /dev/null @@ -1,17 +0,0 @@ -[provider] -name = Dropbox - -[key] -fingerprint = 8738 A680 B84B 3031 A630 F2DB 416F 0610 63FE E659 - -[linux] -en = https://db.tt/ZAzgGm4Q https://db.tt/dUI80d2K 98ea6e4f216f2fb4b69fff9b3a44842c38686ca685f3f55dc48c5d3fb1107be4 -es = https://db.tt/jp3Ytnzh https://db.tt/MDfUTb04 98ea6e4f216f2fb4b69fff9b3a44842c38686ca685f3f55dc48c5d3fb1107be4 - -[windows] -en = https://db.tt/ZAzgGm4Q https://db.tt/dUI80d2K 98ea6e4f216f2fb4b69fff9b3a44842c38686ca685f3f55dc48c5d3fb1107be4 -es = https://db.tt/jp3Ytnzh https://db.tt/MDfUTb04 98ea6e4f216f2fb4b69fff9b3a44842c38686ca685f3f55dc48c5d3fb1107be4 - -[osx] -en = https://db.tt/ZAzgGm4Q https://db.tt/dUI80d2K 98ea6e4f216f2fb4b69fff9b3a44842c38686ca685f3f55dc48c5d3fb1107be4 -es = https://db.tt/jp3Ytnzh https://db.tt/MDfUTb04 98ea6e4f216f2fb4b69fff9b3a44842c38686ca685f3f55dc48c5d3fb1107be4 diff --git a/src/scripts/blacklist.py b/src/scripts/blacklist.py deleted file mode 100644 index bf812e8..0000000 --- a/src/scripts/blacklist.py +++ /dev/null @@ -1,111 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- -# -# This file is part of GetTor, a Tor Browser Bundle distribution system. -# -# :authors: Israel Leiva ilv@riseup.net -# see also AUTHORS file -# -# :copyright: (c) 2008-2014, The Tor Project, Inc. -# (c) 2014, Israel Leiva -# -# :license: This is Free Software. See LICENSE for license information. - -import sys -import time -import sqlite3 -import argparse - - -def main(): - """Script for managing blacklisting of users. - - See argparse usage for more details. - - """ - parser = argparse.ArgumentParser(description='Utility for GetTor' - ' blacklisting') - parser.add_argument('database', metavar='database.db', type=str, - help='the database file') - parser.add_argument('-u', '--user', default=None, - help='filter by user hash') - parser.add_argument('-s', '--service', default=None, - help='filter by service') - parser.add_argument('-b', '--blocked', default=None, - help='filter by blocked users') - parser.add_argument('-a', '--add', default=None, nargs=3, - metavar=('USER', 'SERVICE', 'BLOCKED'), - help='add user') - parser.add_argument('-c', '--clean', default=None, const='c', nargs='?', - metavar='user hash', - help='clean table (delete expired blacklistings)') - parser.add_argument('-r', '--requests', default=None, - help='number of requests; everyone with number of' - ' requests greather than this will be cleaned up') - - args = parser.parse_args() - query = '' - con = sqlite3.connect(args.database) - - if args.add: - # add new entry, useful for adding users permanently blocked - query = "INSERT INTO users VALUES('%s', '%s', 1, %s, %s)"\ - % (args.add[0], args.add[1], args.add[2], time.time()) - with con: - cur = con.cursor() - cur.execute(query) - print "Query execute successfully" - elif args.clean: - if args.clean == 'c': - if args.requests: - # delete by number of times - query = "DELETE FROM users WHERE times > %s" % args.requests - with con: - cur = con.cursor() - cur.execute(query) - print "Query executed successfully." - else: - sys.exit("Number of requests missing. See --help.") - else: - # delete by id - query = "DELETE FROM users WHERE id='%s'" % args.clean - with con: - cur = con.cursor() - cur.execute(query) - print "Query execute succcessfully." - else: - query = "SELECT * FROM users" - has_where = False - # filter - if args.service: - query = "%s %s" % (query, "WHERE service='%s'" % args.service) - has_where = True - if args.user: - if has_where: - query = "%s %s" % (query, "AND id='%s'" % args.user) - else: - query = "%s %s" % (query, "WHERE id='%s'" % args.user) - has_where = True - if args.blocked: - if has_where: - query = "%s %s" % (query, "AND blocked=%s" % args.blocked) - has_where = True - else: - query = "%s %s" % (query, "WHERE blocked=%s" % args.blocked) - - with con: - cur = con.cursor() - cur.execute(query) - rows = cur.fetchall() - # show it nice - print "\nNumber of results: %s\n" % len(rows) - cns = [cn[0] for cn in cur.description] - print "%-70s %-10s %-10s %-10s %-s" % (cns[0], cns[1], cns[2], - cns[3], cns[4]) - - for row in rows: - print "%-70s %-10s %-10s %-10s %s" % (row[0], row[1], row[2], - row[3], row[4]) - -if __name__ == "__main__": - main() diff --git a/src/scripts/create_db.py b/src/scripts/create_db.py deleted file mode 100644 index 057ae82..0000000 --- a/src/scripts/create_db.py +++ /dev/null @@ -1,54 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- -# -# This file is part of GetTor, a Tor Browser Bundle distribution system. -# -# :authors: Israel Leiva ilv@riseup.net -# see also AUTHORS file -# -# :copyright: (c) 2008-2014, The Tor Project, Inc. -# (c) 2014, Israel Leiva -# -# :license: This is Free Software. See LICENSE for license information. - -import os -import sqlite3 -import argparse - - -def main(): - """Create/delete GetTor database for managing stats and blacklisting. - - Database file (.db) must be empty. If it doesn't exist, it will be - created. See argparse usage for more details. - - """ - parser = argparse.ArgumentParser(description='Utility for GetTor' - ' database') - parser.add_argument('-c', '--create', default=None, - metavar='path_to_database.db', - help='create database') - parser.add_argument('-d', '--delete', default=None, - metavar='path_to_database.db', - help='delete database') - - args = parser.parse_args() - if args.create: - con = sqlite3.connect(args.create) - with con: - cur = con.cursor() - # table for handling users (i.e. blacklist) - cur.execute("CREATE TABLE users(id TEXT, service TEXT, times INT," - " blocked INT, last_request TEXT)") - # table for stats - cur.execute("CREATE TABLE requests(service TEXT, type TEXT," - " os TEXT, lc TEXT, pt INT, year INT, month INT," - " day INT, status TEXT, logfile TEXT)") - print "Database %s created" % os.path.abspath(args.create) - elif args.delete: - os.remove(os.path.abspath(args.delete)) - print "Database %s deleted" % os.path.abspath(args.delete) - else: - print "See --help for details on usage." -if __name__ == "__main__": - main() diff --git a/src/scripts/stats.py b/src/scripts/stats.py deleted file mode 100644 index f1d782d..0000000 --- a/src/scripts/stats.py +++ /dev/null @@ -1,123 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- -# -# This file is part of GetTor, a Tor Browser Bundle distribution system. -# -# :authors: Israel Leiva ilv@riseup.net -# see also AUTHORS file -# -# :copyright: (c) 2008-2014, The Tor Project, Inc. -# (c) 2014, Israel Leiva -# -# :license: This is Free Software. See LICENSE for license information. - - -import sqlite3 -import argparse - - -def main(): - """Script for showing stats. - - See argparse usage for more details. - - """ - parser = argparse.ArgumentParser(description='Utility for GetTor stats') - parser.add_argument('database', metavar='database.db', type=str, - help='the database file') - parser.add_argument('-s', '--service', default=None, - help='filter by service') - parser.add_argument('-t', '--type', default=None, - help='filter by type of request') - parser.add_argument('-o', '--os', default=None, - help='filter by OS') - parser.add_argument('-l', '--lc', default=None, - help='filter by locale') - parser.add_argument('-p', '--pt', default=None, - help='filter by PT requests') - parser.add_argument('-y', '--year', default=None, - help='filter by year') - parser.add_argument('-m', '--month', default=None, - help='filter by month') - parser.add_argument('-d', '--day', default=None, - help='filter by day') - parser.add_argument('-u', '--status', default=None, - help='filter by status of the request') - - args = parser.parse_args() - query = 'SELECT * FROM requests' - has_where = False - - # we build the query piece by piece - if args.service: - query = "%s %s" % (query, "WHERE service = '%s'" % args.service) - has_where = True - if args.type: - if has_where: - query = "%s %s" % (query, "AND type = '%s'" % args.type) - else: - query = "%s %s" % (query, "WHERE type = '%s'" % args.type) - has_where = True - if args.os: - if has_where: - query = "%s %s" % (query, "AND os = '%s'" % args.os) - else: - query = "%s %s" % (query, "WHERE os = '%s'" % args.os) - has_where = True - if args.lc: - if has_where: - query = "%s %s" % (query, "AND lc = '%s'" % args.lc) - else: - query = "%s %s" % (query, "WHERE lc = '%s'" % args.lc) - has_where = True - if args.pt: - if has_where: - query = "%s %s" % (query, "AND pt = %s" % args.pt) - else: - query = "%s %s" % (query, "WHERE pt = %s" % args.pt) - has_where = True - if args.year: - if has_where: - query = "%s %s" % (query, "AND year = %s" % args.year) - else: - query = "%s %s" % (query, "WHERE year = %s" % args.year) - has_where = True - if args.month: - if has_where: - query = "%s %s" % (query, "AND month = %s" % args.month) - else: - query = "%s %s" % (query, "WHERE month = %s" % args.month) - has_where = True - if args.day: - if has_where: - query = "%s %s" % (query, "AND day = %s" % args.day) - else: - query = "%s %s" % (query, "WHERE day = %s" % args.day) - has_where = True - if args.status: - if has_where: - query = "%s %s" % (query, "AND status = '%s'" % args.status) - else: - query = "%s %s" % (query, "WHERE status = '%s'" % args.status) - has_where = True - - con = sqlite3.connect(args.database) - - with con: - cur = con.cursor() - cur.execute(query) - rows = cur.fetchall() - # show it nice - print "\nNumber of results: %s\n" % len(rows) - cns = [cn[0] for cn in cur.description] - print "%-10s %-10s %-10s %-10s %-10s %-10s %-10s %-10s"\ - " %-15s %s"\ % (cns[0], cns[1], cns[2], cns[3], cns[4], cns[5], - cns[6], cns[7], cns[8], cns[9]) - - for row in rows: - print "%-10s %-10s %-10s %-10s %-10s %-10s %-10s %-10s"\ - " %-15s %s" % (row[0], row[1], row[2], row[3], row[4], - row[5], row[6], row[7], row[8], row[9]) - -if __name__ == "__main__": - main() diff --git a/src/smtp.cfg b/src/smtp.cfg deleted file mode 100644 index ddbf5fb..0000000 --- a/src/smtp.cfg +++ /dev/null @@ -1,17 +0,0 @@ -[general] -basedir: /path/to/gettor/smtp -our_domain: torproject.org -core_cfg: /path/to/core.cfg - -[blacklist] -cfg: /path/to/blacklist.cfg -max_requests: 3 -wait_time: 20 - -[i18n] -dir: i18n/ - -[log] -level: DEBUG -dir: log/ -emails_dir: emails/ diff --git a/src/smtp/log/all.log b/src/smtp/log/all.log deleted file mode 100644 index 21e5f3b..0000000 --- a/src/smtp/log/all.log +++ /dev/null @@ -1,16 +0,0 @@ - -[ DEBUG] 2014-07-01 19:32:28 - Redirecting logging to smtp/log/ -[ DEBUG] 2014-07-01 19:32:28 - New smtp object created -[ DEBUG] 2014-07-01 19:32:28 - Checking if address "Jacob Applebaum" ioerror@gmail.com is blacklisted -[ DEBUG] 2014-07-01 19:32:28 - Parsing email -[ DEBUG] 2014-07-01 19:32:28 - Trying to obtain locale from recipient address -[ DEBUG] 2014-07-01 19:32:28 - Request for locale en -[ DEBUG] 2014-07-01 19:32:28 - Parsing email text part -[ INFO] 2014-07-01 19:32:28 - New request for links -[ DEBUG] 2014-07-01 19:32:28 - Sending delay message... -[ DEBUG] 2014-07-01 19:32:28 - Creating email object for replying -[ DEBUG] 2014-07-01 19:32:28 - Email sent -[ INFO] 2014-07-01 19:32:28 - Asking Core for links in en for linux -[ DEBUG] 2014-07-01 19:32:28 - Sending links... -[ DEBUG] 2014-07-01 19:32:28 - Creating email object for replying -[ DEBUG] 2014-07-01 19:32:28 - Email sent diff --git a/src/smtp/log/debug.log b/src/smtp/log/debug.log deleted file mode 100644 index bef7c7a..0000000 --- a/src/smtp/log/debug.log +++ /dev/null @@ -1,14 +0,0 @@ - -[ DEBUG] 2014-07-01 19:32:28 - Redirecting logging to smtp/log/ -[ DEBUG] 2014-07-01 19:32:28 - New smtp object created -[ DEBUG] 2014-07-01 19:32:28 - Checking if address "Jacob Applebaum" ioerror@gmail.com is blacklisted -[ DEBUG] 2014-07-01 19:32:28 - Parsing email -[ DEBUG] 2014-07-01 19:32:28 - Trying to obtain locale from recipient address -[ DEBUG] 2014-07-01 19:32:28 - Request for locale en -[ DEBUG] 2014-07-01 19:32:28 - Parsing email text part -[ DEBUG] 2014-07-01 19:32:28 - Sending delay message... -[ DEBUG] 2014-07-01 19:32:28 - Creating email object for replying -[ DEBUG] 2014-07-01 19:32:28 - Email sent -[ DEBUG] 2014-07-01 19:32:28 - Sending links... -[ DEBUG] 2014-07-01 19:32:28 - Creating email object for replying -[ DEBUG] 2014-07-01 19:32:28 - Email sent diff --git a/src/smtp/log/error.log b/src/smtp/log/error.log deleted file mode 100644 index e69de29..0000000 diff --git a/src/smtp/log/info.log b/src/smtp/log/info.log deleted file mode 100644 index 66d40f1..0000000 --- a/src/smtp/log/info.log +++ /dev/null @@ -1,3 +0,0 @@ - -[ INFO] 2014-07-01 19:32:28 - New request for links -[ INFO] 2014-07-01 19:32:28 - Asking Core for links in en for linux diff --git a/src/smtp/log/warn.log b/src/smtp/log/warn.log deleted file mode 100644 index e69de29..0000000 diff --git a/src/smtp/sample/sample-email.eml b/src/smtp/sample/sample-email.eml deleted file mode 100644 index 7c30644..0000000 --- a/src/smtp/sample/sample-email.eml +++ /dev/null @@ -1,57 +0,0 @@ -X-Account-Key: account6 -X-UIDL: 1214981061.25808.faustus,S=2285 -X-Mozilla-Status: 0001 -X-Mozilla-Status2: 02000000 -Return-Path: ioerror@gmail.com -Delivered-To: jpopped@appelbaum.net -Received: (qmail 25806 invoked by uid 89); 2 Jul 2008 06:44:21 -0000 -Delivered-To: appelbaum.net-jacob@appelbaum.net -Received: (qmail 25804 invoked by uid 89); 2 Jul 2008 06:44:21 -0000 -Received: from unknown (HELO wa-out-1112.google.com) (209.85.146.180) - by 0 with SMTP; 2 Jul 2008 06:44:21 -0000 -Received-SPF: pass (0: SPF record at _spf.google.com designates 209.85.146.180 as permitted sender) -Received: by wa-out-1112.google.com with SMTP id j40so170432wah.1 - for jacob@appelbaum.net; Tue, 01 Jul 2008 23:42:01 -0700 (PDT) -DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; - d=gmail.com; s=gamma; - h=domainkey-signature:received:received:message-id:date:from:to - :subject:mime-version:content-type; - bh=IvFqNkffeoST7vamh2ytuq/b7GpLhg2hStTrQq3I3rE=; - b=xQR0hE/J4AXpAqH1UDXTtDrU9Izc6WM8vtFudRBzldWYyRx3Vvfh2I2Opu8+O6wbAv - jlDi18anUMbZqlIGSgGOxvXW4CltpX/SFZm1aGL4AisQ1Bi5xEqlrc8OnX3sA2xKeM3g - KWsWm+GVSMI4XAqnY9FYAfPx4DmOAfkdMyWCU= -DomainKey-Signature: a=rsa-sha1; c=nofws; - d=gmail.com; s=gamma; - h=message-id:date:from:to:subject:mime-version:content-type; - b=kyzDtGRDbiC5y4Bz/ylQjyHOChiOP2A6QDzybsVXc0C1hjHLImOQYR8gOxcRY+mRkN - 1xpBaEF4UloZAxTb79khRRp4TWmjT1DagtLx2MFzIj/F6awtdE/9U3p4QyKr8S43tGcE - ET26BSfT5u9zrXblVVAP3JedMPZ8mlIGQxyDs= -Received: by 10.115.90.1 with SMTP id s1mr6711509wal.51.1214980921268; - Tue, 01 Jul 2008 23:42:01 -0700 (PDT) -Received: by 10.114.184.16 with HTTP; Tue, 1 Jul 2008 23:41:57 -0700 (PDT) -Message-ID: 7fadd8130807012341n3b3af401mbdb4a29c80310bd3@mail.gmail.com -Date: Tue, 1 Jul 2008 23:41:57 -0700 -From: "Jacob Applebaum" ioerror@gmail.com -To: gettor+en@torproject.org -Subject: Positive DKIM header -MIME-Version: 1.0 -Content-Type: multipart/alternative; - boundary="----=_Part_462_28562233.1214980917793" - -------=_Part_462_28562233.1214980917793 -Content-Type: text/plain; charset=ISO-8859-1 -Content-Transfer-Encoding: 7bit -Content-Disposition: inline - -linux - -------=_Part_462_28562233.1214980917793 -Content-Type: text/html; charset=ISO-8859-1 -Content-Transfer-Encoding: 7bit -Content-Disposition: inline - -This email should have a positive DKIM header.<br> - -------=_Part_462_28562233.1214980917793-- - - diff --git a/src/smtp_demo.py b/src/smtp_demo.py deleted file mode 100644 index 418b3bd..0000000 --- a/src/smtp_demo.py +++ /dev/null @@ -1,22 +0,0 @@ -#!/usr/bin/env python -import sys - -import gettor.smtp - -service = gettor.smtp.SMTP() - -# For now we simulate mails reading from stdin -# In linux test as follows: -# $ python smtp_demo.py < email.eml - -incoming = sys.stdin.read() -try: - print "Email received!" - service.process_email(incoming) - print "Email sent!" -except gettor.smtp.ConfigurationError as e: - print "Misconfiguration: " + str(e) -except gettor.smtp.SendEmailError as e: - print "SMTP not working: " + str(e) -except gettor.smtp.InternalError as e: - print "Core module not working: " + str(e) diff --git a/src/tbb-key.asc b/src/tbb-key.asc deleted file mode 100644 index bd13d7e..0000000 --- a/src/tbb-key.asc +++ /dev/null @@ -1,2986 +0,0 @@ ------BEGIN PGP PUBLIC KEY BLOCK----- -Version: GnuPG v1.4.11 (GNU/Linux) - -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 -aH2j7xNkRUp2beptFF6GFRJMzcHKA7Pl6z/A0BdXwjMuAFZf7PwoxzWEqJ18XXWs -pXfK8MP6q3SA24siAeMdO1fFbwBgIPbNBc/TEAGT4GA4vWtlL8h4sJFt/HpWJ748 -RbGg9Nfre7dUzwMVD5YPcag4i1YJgVrmiYk9K3p/2xx2kajqW/h+i3hboJyEIU9b -o8qGamTnpcpYKWO8iEX3S6RlMkPi/6V+qgl20iiMyHtVrEToHQekrSh/EgtmeWx1 -zZum6y8SKCFjkU9IJry6NTZ7cmuZyD4LYXAtefUDv3beMwWASQGBCq+zd3b3Rn5I -wg4j+4NN226xKyZ+tD3sn3WtHSlhq+wfN1BRi0tX/BZq4YGu2VAAqF/q9n4F/o4a -UhNHxpgqb/IUtkmPpjhBEuOqj0lbTb6KFcG+H1EeQAot5TM7M5fGUbU8ZlY742AJ -IhvjhoP/3POCeryNYIkCHAQQAQoABgUCS6e8LgAKCRDM0u2U0hc56W6PD/4vIdIw -AW6JcFgwBmIL5eVJhS4NszELeLJoVWOgE1bxFYTLn0WJiMg1IJtURJNste2+tE8p -tVFDS88cVdVKH67olE7PUFKPS4h3CPf7NQCbqx9igN42w0EpdedvRZSvQ2rEIU9Q -Z2uk2CWWGsKMny2GFG9zSDWGgiSX+sJKaGxvuGnZLfNf//////////////////// -//////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////// -/////////////////////////////////////4kCHAQQAQoABgUCUhL5sAAKCRAx -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 -5r/sl2AcI/A8jxLn7WtKShq5rfUtNXwrDV3MXtaKw+1Mypqy6zkuYmjXZr5/7zYs -Czzc0vM0FOZfmzBSznGG9ZoYCuGbi/T1pHqZ3VteamTdh8qHV1CYNTuJvldULI08 -cqnIlDIWK4Le3g5AA5hMuT3gIdo9KCZzfqHR855UbzkWqfI41LnjkGm/IfzwDeGZ -1aTHUhrwwsEtig+UUCn+gna8Fz/w3GjZN/YCg/n7k6gqKsV7spdM1T0uA0+skrqD -P3nx6Jv8CH5fCUwx5mJKUdpJz0HGnkbxFo+zoECZt8poO2/nS0woFSeifuFbDpMJ -2m+OiHkYwR/a/JkQn+snJ/n6iym2ajoPiTqtmSjIlbBph52ky8QdLHh8fqJcZTCr -T8bZOBv0/DXIX/cdTA8pOsXrzAv8P20u+AR8QauGljq8cxPIPv9Ojq2TX2lNUDDT -EyuiJUHUe68rS50/8Q6OgfGt1KoNY8Q3VOjNQdCOjWDPSBhdRezJt13DGrv+ihGN -MeNehdOtdOtxRBOufRQCCxA9//////////////////////////////////////// -//////////////////////////////////////////////////////////////// -/4kCHAQTAQIABgUCTPn4SgAKCRAN+KXPnVGk/OXwD/9xbPPhWix1my7+O9Z1MWv8 -Q+pPVIOOqgQe0UmtQdsd5r/sl2AcI/A8jxLn7WtKShq5rfUtNXwrDV3MXtaKw+1M -ypqy6zkuYmjXZr5/7zYsCzzc0vM0FOZfmzBSznGG9ZoYCuGbi/T1pHqZ3VteamTd -h8qHV1CYNTuJvldULI08cqnIlDIWK4Le3g5AA5hMuT3gIdo9KCZzfqHR855UbzkW -qfI41LnjkGm/IfzwDeGZ1aTHUhrwwsEtig+UUCn+gna8Fz/w3GjZN/YCg/n7k6gq -KsV7spdM1T0uA0+skrqDP3nx6Jv8CH5fCUwx5mJKUdpJz0HGnkbxFo+zoECZt8po -O2/nS0woFSeifuFbDpMJ2m+OiHkYwR/a/JkQn+snJ/n6iym2ajoPiTqtmSjIlbBp -h52ky8QdLHh8fqJcZTCrT8bZOBv0/DXIX/cdTA8pOsXrzAv8P20u+AR8QauGljq8 -cxPIPv9Ojq2TX2lNUDDTEyuiJUHUe68rS50/8Q6OgfGt1KoNY8Q3VOjNQdCOjWDP -SBhdRezJt13DGrv+rP4q5QW0Jk40ee/BLsNbATOfJI906GwQr8EArMi4qXTQBC8d -pUcF06M9+hYViCZd3g36NR3zSnt1AS1jWRjpiozg2x6ZR3R0b7tJb7hwdu30vf9a -YPNYsxqc5rMm7RpsLWg424kCHAQTAQgABgUCTHVazgAKCRBir0AxyC4AOUC9D/9i -jMgmg9qpaTZR1DVNu+e/ZTX96btuv2SbbkZgFB7TGLE/DQ1Hn8ETe8RMRzfkUpYs -rJJfMD+e0UmhXK2+1jzs8b3PkW7K1CBr45yKl9eFD7t2d6TjPsRFw+I+Q/xtLdZz -FAwrNffGxPM0VMbfUFFruBVzC7Ce1JFYpxifazzK7TcMrE8ZUgQmNHl2r2xbYxWN -8/rEQsMC1SBYmZe4EoCFOef1uGn0iKBXqGDicljm5GiEhZDokScSpbsjoIXH6PgY -Jg/nQDwh9ZZqe/d+iPtCkOjPUwLFHTYXBZxIWPOc4/uQs3vGcDi2RxioKfblu/EG -dAof5g3zuU3Fe7BfX99KbOVMQdSUapl0haUF/lSVkSOYGxUgZJOtJAtggzUtWrtE -rpq2KkkrKpEg0COB+OhRK9Qy3Ln99EchwSkdjo5NKSbf2B6aFUcibZzmM9+r9L99 -1CEsvSj4yfXefCRF76v+oIJf6PC5wOShHewk787140RUfHOFJj0zusR6Na8dj3MT -UvUKp+uLi9vCaAZ+UIohVHG8Z45jQprYl52yVg7ao4aoQWlzgm82irsmRYTcvgLn -2CcfZEb05tlyMig2RxGKAQy7eJxaEqZWWhgsnjDBmUPC/urVo8AlafOKQHNn0R9Z -cctQm9cQQhcFsepNG3XU18rA2TWL5vvLiiazQ+5Wu4kCHAQTAQgABgUCTXudGgAK -CRDqIQJPqFJUXTULD/9LTHb3y5CfpRd9iKZT2sJFi6uNCRbmLutfuNCueE32tBxR -1aauyvkWV70lOg9HyZVkvwOEUtNKH1hkpjY1+AMppOzs2VRXl1oltxJ3ALP87/RU -zS0jfpFx922ISAchY51Sp6dTvPr42Q/CZqcugRT/flc71WC5QaL/iEdinwtI30Kf -2em7bzupD0oq662EtcbNKYF0jtJKCtCv0tcMR6GM0GXn30D1ssCNu3UtceChUtGe -lm/PihaVISTf0LtjYvy8LvHqrUq35voui63oJ5DKa0bG9AzxiXdLwcXFbPrbI68m -+1eIIERCG+AuKQMjtvNZJPCZEJNyNDfKIBzjxrkbIsd0at/P0rNfrXAka52TiRIB -s+k8c0x1mvyw3q2IGH4hfwa+nayURfvJwXEymiu0HjF/G3igO5eASO0tX34WrgOY -ssJm5VHSAbm5yDKBTxU1kgEUb+l+W5Dk1YmPPo0MP6xWnmAVLW1guVYyuQH5PHQY -7wHXiLOsdGzRP5AzlDmnxnXc4ndYx2A13geVhs0JjXcMEsKjrthX1elLzDdAJ+DR -ffl1NSLV5RV4SqUNoY1QlKYVwRjnKsEEvzHWMyzz0ZE41h1pZ/soPXCPRjipWYPs -ynDJ6EJv1joM/tZ4gMZjJq04hVTkBg6uPFMY4H+evpbFtitdlH1CcuyTNhUm84kC -HwQQAQIACQUCT+X7/QIHAAAKCRBxd0Dbs16EdN1tEACvA1Z62yx6B9gRLRAV4Maa -5yaJ4h8zfoFVYrng4r0KicKRLwPIYnBsd9FyiS2qFSzYqAFTB8e0pQnBbkGSzw1P -BLAg5HjRUjgAVhmpXjB4cOVZD1ymDu+LRHE4CfzTsLOabYlGkA+sScIBYKJVQutq -kg7Ax8vArGyoNy57lBa0drnflrh/cFKtsFa9L0XO60HWZZnc3c4+G63uYqaUw1+i -JcXvcbXS0AVgqeuc1RiE+bw2IMJeo3gWxIMz5XeL4vu1vEx3c0LL+6WcpCYO24Ic -uBGpFuM2sr0l6yWLd23zkeiU9SUNCcPYz96DUakPJbFIzft2SOlDUp5s3tpmjsXC -4G1qPdcUKtlKKrLtR5am7TE0gIjSaAmE/i042v/JPLHVFLfo8NJbmxb+tbkzBfKp -n2SJfLUCz24mLoQHndeegq8xf2FzfIjJprqykdKTdoRAgOcopEoRFkGmCXabUSOH -oPfSGy4WTXepUSqDu+QKlBQFNU4pQNQRhNKO+MWxTuKnLLl+VnL+trBUqXyXzBFe -Nq8V2MrA13obhl24vH6DyOY9aXY/Fcb9lGk92bh1zAt326nf+ymfF/0YvffESaif -w4+VX5K7vTKSScz2CiqzBOgY0uXSy3Eaa3XUU3EPMBhyjnjvXgkZXaHcHOBqM4ZZ -a5cjD6f/gMPmVdPRpLYHwIkCIgQSAQoADAUCUuKU8wWDA8JnAAAKCRCtp7Jf52Nw -1tcgD/0dY7EuVlD2S32DibToYqox8x6CgVEjhKqHihKWJdEN0UBVWQ0rutVCW02w -nL7BKOjoxcyN1FQPGoISZPll3avSfLjeOjynXHXApjYImGb6vm+Uv1b1Oh8//UQW -XW5Chg1VzaDn9l20hYdZQAXGkBquFOax+PQ9tIUJfjkn3s70KoMsQsYJeN0oGZdr -4eqS0+JDyw965oi7wXjdbSwJl9+V8bkt0B9FjwfP7kURcfvPD21WU786p/KOIH4r -uuZROR9lyA8HuwJivheuTe6juFFEi3xexQ8+8nYHUOaM6SItDvRG6EiJNReEryxv -s+oxXPt8YK9s2Bn5cakZkRnIOF3VNMlGGXz1Hjl3MJesaDnNE0gnHbRDyF8Sb7Br -ic3n6qx418ciqLEJzH5Hm3OP55uNv4gJwXxy3gXbDe5jyv1fK7+IlVMOYQFRzbDO -sf5SeZnK7sxHcAZtp41LdY8lle9Ej+BZYFu4ZnjWeQ9MDSPBjk/qEww3y2wYS4Hf -s19o4o7+JZ3HRfT8zcMbfYBSWs7XS8RY6Ld95m6Q/jWTXyr2fYG6k1xAXFP/9DL3 -qJAiMeA7THVWd0bgc55TmGaFjIreQAXaQil7JotRxUU9Th5j+dQMWMSdv19UjJtG -JcVWXj0Dxz3weMWG/3+Ef1IdFHq/KjnaribxZaQa47b6hpsKFIkCRAQSAQoALgUC -U7vxVScaZ2l0Oi8vZ2l0aHViLmNvbS9pbmZpbml0eTAvcHVia2V5cy5naXQACgkQ -ExjvrF+7286bjBAAmCIbjeFFKyxHCSwJeVOp42G+0bcYqY0eHPdeMVpKDWAxyhvn -RJZIZlDntaZ5Upidgbrk9CuVgAZrV9UZ7GBtY2nFqCF7YbLfAXeEdRD8q71b/FTG -tTP7Dz9dbV7ZahczQ70qbWpDu3ceVeOC7Jdj3gIxKaQAVp87VWmHaTG7ZMTmr2Dv -WZCO6eo1aRfgi8kyf5aIof13DL3V8IhbMvXYBfehuC4AOQd2a3GbEerrjw2I+2RK -key+1ur+fYjyl+YeBQG98awdbxbRTShty+OTVauYi5ltQwkYGaKM+3AOJjCsm0zB -gTjuBzbkx7RrUZZQEgNBFT4pNXMALNe96x6dtPVVIt7JMChfobUhVYaG4jEenzVy -IcmhjebpLZ+8M66h4z8/pxvyKx76RcQbI6If2XtrGTbuREiY6IWS4y4trdvvFFnk -ENdWQG1qAjopRMarDFHg86k0j4rAfOYGoPt1ovtpveiCf6p+/cMUGYshjSTSgak5 -iOXBR7evqL0tIcusapQBigRNmapEYqz4tsdjYv0aA7ubEvDQK/bfZfyKbyT+8w6v -rm3S1Pnk06347/mjGQJ0Tyc3evKg6TpxlPxG0n4U4dliy6O+9aGTtHBBbKr+qsfe -Mis195Z2djiKo8s/Q0ky7MlPncfhDdNfVMNN35Dn2/eYSwRCEKEdjJ1Z6eaJBBwE -EAECAAYFAlFIqX4ACgkQa8dYy8EfYnaRcB/8DnCiIXzZ/xw8g7+do2M1N/qHhp42 -+IZN/6T8NZdvHaULSk9eXbjrAAQ4r9ywrMf+HXFUK/cVkh0cD2Uv0bPnSq6HeCor -gR4dYJvEPzi4gl+9K7zB45kWX/n8cTPzhL6SJpH3dCMXaB0o6mBvfKytu+As5vmr -UmdPn9rN8tTZaS6joycU8OfjPzCfvMzadRDPTVHbF3E+BDL64fxX2eGJhnuYElrv -PKU1GrRxrdd9vQ5fq8JxUzy+jtZoWJDmzjhQ6vT3uTcV14IoDxWa3O/5VP8kC/uC -fcMZAn/RPC9Z4whowOP9yeNnVUaFI3EqCub7c9RM4Iw4yJTdgtK/nGkgYKPz7rKl -9/QE3G8J6d6s18hMgfXmfWZKaMPN7nShS67HaONxOJNLS1fnAJuLG6bE/puBI2Wo -E2koo70JY2/DSXPVMz4X3CogB0lhk1SPXINcsVSyvNgoEdfUxeygi4h4Vyj13l2V -NWZOoHhGyqYhMki+mwFXAuIybp3MvbCaa65+fh7AzFwO5C87NCHf/kCLBw0uQuWU -lPFShBfgf//cxTadp5mwOLm2Mh2ACNqKRdQBBiKEbeLHVvaIBHpIAE2qhMWGDyzu -R2XcsUoguuLUd6asGfI8Ml9ig41Nv5e5mOty4ymBsbSmTAgkxtgYcN+3flYrLdbA -Knf7LaqXO5XsOxxrGiMALaRPmoOq9AeiTjDri9DI1pSP+7rV3bdrxY+2t68QpaDG -VX7BQzxXXbiD0l1FAtpmK31Q3PKTYBB+/Grh6J4dkbNyWJYWbM/Bzk0tskvN0z6O -mNnXvbcuUt0hxnSJbRrvjTOJDIygpcR6hqVBKLCxga43JLM8+Nemgyu2zYXpuQYX -xHqsgtcrlCW0Icr7m8DctNMzoTkxaLSFElg8s/PJ87lcNZYHxV/T4JAFg+0ddo0g -yIi2JyBVs2GzXfEqSXsjPRnrvYh8HFNmwnAB0uc4njcffWtFci+ax323LOgwNCOA -ZYuJC2jQR98g9MNwHQYOmKoFEGGnuH3bbmS4fQ7gN+RpAXhF9I1rI2vmcV00e9VA -ubk3J/XlpUKIWZS+eN41QZvuHVgnjzbIaBMeNztyvDdIm1i6jalOgBs0lZ4gatk+ -12rRPIeW3phJ8vUO5aZQefO6r26gL2d4UqI3EltEpkx3mZvoWq3oWI6lz4Ecap7j -zpRrt8okrNs1XCz/LO4+x1I+JY0WaPSAk1HaZjVR2gMl8dvt8AFXdrX36HdWw3A/ -sjUXF9k7EcvfNE24w9fHAMBn05p2ruPIZq9YToHsdxelog6t2j3VlZCAePC/Tgrd -7Ut5d84Xjcy4wJCFN2kh5eKUj9Ng60ZQ0nofdg4scc3qQLlczWBj/MgAEIkEHAQQ -AQIABgUCUf559wAKCRB6Y4Cd5RJ2IrzyH/9hB8TJrXndZNrx2Fcky/mmXS7zTbYc -UrPPwx2BElFaRQkzAB/t2FPZrjCi9SrQcIjEig91hflUzGJu+bTXBgqxLRZbYqa2 -wG6D0Chid4v921tOlhixFZ1NIXUY+D/GZSprC/SmyFjs5ocNMtjiGskk79dj2HYK -0WcRiLUFvJd+wswc4eAGriagdQWf+dJivFY1CPYlsu/FvJuDhHi04jwMNuWx0hEW -XUdm1Koy3LEkJ8mHCSEjS0p6boPGSgjy1CZhzIh9B291ooAFAOhzgzFvcfKIv7Rg -zVELFFPICRI+kLjL9O9c9+a3qngr8P7UlbRL3FU8Qs4KvFD2E4lAityhKLlPPg6I -wRZMaAY5Br1sV0EZOEE2lqK12xH8/+Y+N/YHNAEMPTlBdZQfCsMHd3G7GUEvFs5I -xxjEGU7ffdJlXyw+pnzFXBstAAox4MNVxMMYsseTkY7a1GegVY0tJNBOEEjbuRpS -F25zQo96AeFl0gGclvalBVYJCQ00t468v1zs8JyHpgjyA04t1MrZS3w5gLFlRFdc -tjwvhKp55a6cxZPxUXVTr7mEb+mykuAaCdl4R+4qwhbLN/hkirGv40xcRDXOsagf -cvVFPtbIuTus/38X1eO+4TSKGlncukTwffCTKaBrRAUUwE0GXxDJkcvdMU5fKF2n -GAn4RwaKh1hf3xLwxvQoDikYTQ7rPERqE0tgmCm4KjzGbAR0gQ4M6ndYueUZWpOS -GR+lIxyzLYthbh3kWpdCD97Odi/8BDb9gqPpdrYPy2clVPByFzHs/Ybp1oN1Bv10 -o1O/54E2exgMIqPE5hPPL2f5OVeijHegTzC8SHlQmWVZFu7IrVb39eKtzZPER3bc -r/LVMqBPHxoYhLJjSLSMg/nMLGxdHhD/gYg7bAxpkF3aITblv9x1V8r2qxCmeK+Z -2rO1I70viYuufuUe5YixffOy44gVKZPRUJQINMH149xcJ8e29UitRCKDMZTO/skE -/coFEPxVE/qBEHycNgfLWbO6aHzPOkLjjx4+6ZcmE9x+DScfIqx63CAN/Zk81Xwp -OnQpMeFlzS9wC8i3yL3MlrDQ3rbVBTUOu05Smwy31w45sMSJoOO69/zHGwZ+mwsp -FXBQ69VSYLq5FtNHuyeqqXYGyv8NXBcrlMmcSU59nVt4RvqfFXT0QkZO7CocG10T -RSb2pqzGAduusXVT365uJeqM5ggbMDd4h2j7c9RPoTR5/a+yK8Vs0leM32v5Qp97 -twfREe3w3gI9GqFZtrZMeb34NQzbWoahskLZuNUWkXGyACA+PKyocu6ifSR+o/OH -UnVJJ/CZ09cO0yi1+VoQKd331Jt8FXtbNLeZapTPPPAcTBkw6jdgU74btCJFcmlu -biBDbGFyayA8ZXJpbm5AdG9ycHJvamVjdC5vcmc+iEUEEBECAAYFAkt4x7QACgkQ -O50JPzGwl0stXgCcCWxAk+dYg687rEfQGrDhYDMcqo0AljMgrOw07VtYH0I6nZav -sggyGCmIRQQQEQIABgUCTqn2XgAKCRBeSWHBYxM1MIBAAJduWZxz7yu7Y8JDjzgC -XLbW84L9AKD7g+VWv3sCleWZ+/JeSCdpZaqxL4hGBBARAgAGBQJMUA9fAAoJELrr -otdFbK1RwLEAoI25wLkq/VTtEdd4mpZ4JWVdktU4AJwNqMPtzmcJeu6o9v1Q+Bpi -QmpDrohGBBARAgAGBQJM0YkAAAoJECotsX2kXgURhwYAn1/aCJSH7f+rEVolFMpB -rhCiHWPoAJwL3VgZwtDNQxdhbHz7BjdcY05GfIhGBBARAgAGBQJM9+ATAAoJEAYi -dmOmQvqYppsAnj4GixbD/Lq7uToXkAIBKAbgcZ6TAKCyaJAiYJjise7wBCM/CNb6 -mhFrf4hGBBARAgAGBQJM9/nIAAoJEKotwq6l89tWpDAAn190+A3AyuHIW4EEKTCC -aaLclkMgAJ9jBB3Fc3jl8aSU/RYTs6+/VOQNj4hGBBARAgAGBQJNeS8AAAoJEIr2 -URweWybxNmIAn0nJ/n38iVFYFNs4jhdA65kTdp5AAJkB1rYpgO8bcJMwoRxumcCj -qQXuwYhGBBARAgAGBQJOvMagAAoJEOtaiWoomIv1BNoAoIYap+gKhLzDfQ9qImcA -h7drlpfOAKDRhyBh/dEbMAdLXJfCIbfIl7YMqIhGBBARAgAGBQJPKYzJAAoJELhC -CT3GdlQwrT0An3EpNUXkRfqKpjTiy2KsVT+79l7DAJ9BlpGlQC6wY28knUlsYJ8e -CM/O6ohGBBARAgAGBQJRT7TmAAoJEIvYLm8wuUtcbYoAoKIed5z+H3g2hYQSl0ah -qYEcV9ZtAJ49DQ6DOo3IwMqNsZiduEBzZ2Ek74hGBBMRAgAGBQJMUBxnAAoJENDP -lj33wRJlAHsAoL3w8ITh9IzTHJ4ptejyci9sFlHbAKCpQgB7rt3imW0AO1BC+Nxr -xJ+r6YhGBBMRAgAGBQJMdVquAAoJEN56r26UwJx/OlwAnAv/btFpEU72QqPlXsoU -f9D1NhxhAJ4igmIsEzja/CzRUyZGBZj4rnKtoIhWBBARCAAGBQJNLcY0AAoJEPKt -haweQrNnZ3EA4K6HZz2BM9hc/g/TmNsymf+ArcTJ0vzk2yGi4Q4A31qNf1ghv3Vx -sqP0Oj1Q9tf067t8FXdhig+S5geIXgQQEQgABgUCTNSQwAAKCRArhaVXIFHydFmd -AP0Z44uFOSUJMwhnAv8Hne1J0ddPEkZt2fhO/Uut10z37wD/Y7PFU5Icm0vOEx01 -LBDiQm+laQ57MBFJysJoQbLZdPqIXgQQEQgABgUCT6ma2QAKCRBqJGPKeqRmBI0O -APwKN0FChDsN36kY8ZKwSPM19/T+WTbwHWnqd3+3OqthzAEAhccOTbk85+1emG5z -LmS3qw+4wXL7EgvdUVHAGOyBTi2IXgQQEQgABgUCT7rHiAAKCRA5EXc2wLnHd8uH -AP9PEdDwpJR7GG2A7Zp9IXOSGljjNIHtEGq4oKsNiIVPJAEAt0wk0u1pYOnFOaKp -+WkuvWfnsS7ERsGSooxE/u5rsDyIXgQQEQgABgUCUnZ8NwAKCRCn8zWz5z1ldQGd -AQC7sG3aYOn/rTFHL1qKHbw0OTQ6Dh9N93ietabsWAiQrAEAqfqrkBvQVY89+a/n -c4qkvEgnTKH1TJuONA0/+HmeYcSIXgQQEQgABgUCU2PIsAAKCRDK4M68dTJXF7w5 -APsFdgq4K4bfbI2mDk86jCIgSEY8oR6VNzvdSYCL/Lo7kAEAkoh/ktW3KTgGYjws -TGQcKI5Gwo70aE5mcCg4pccwXFWIXgQQEQoABgUCUVVQvgAKCRCHWDJ6EJ8lkdlD -AQDVtvaNyED04CciX7B6JRz9DdcKZfbULOv2wP85ZIM8vgEAinbTsvMoYff2YPfE -Nj2nppfQ4/UqPmyIGI8KADHiDQmInAQQAQIABgUCTSdTsgAKCRC/1u5YV/d/CWN8 -A/4mDpVYR5WQ0Ra8VvavYNuuR+8wmgBw9JV49U+M0gHIh9zRKcxL3899QE2+3nbL -HwgF1HZJWtVJklyWJtvNWHo4xNr5BY0T0JrAz7ZVXFQHAGAGk+Xv+xJAr6+EMJ0s -TxCz9tN5zsx7ww0sv3enyGUIckyGAgwmkbxgkTABjbw45oicBBABAgAGBQJNvF8P -AAoJECsJyRTz0BSIilsD/185+6w035DOxByLbjJbWWUD3TGNtXLwp1RE9t/GZJtL -qyjPusO7E6pXPy52q6kpByj1MLD4SictHizpFa9iWi1L/v3w1bbaK44oN7opFCSr -9DHNn+R2W8KlCu1yFcCH1bQTE9afPvSUxhnTj6htwLqI758XyQmliFFe4x1fLoqC -iJwEEAECAAYFAk28X1UACgkQ3ahBZT1UaYqMLAP+KTa/yi0Q+RIKQO6yk/GtCjsR -XSZWKT85P4SUsLLXfCuQyN3fOS0Ks3KLvPyWhDacvMYT7qwbDsko9bwP7mf7fSpX -Z7Tt9i+Dh+4o4sG2aPUkABJqhSNc2XpltoLsN47tZsl7ZayKZ/X9+93CM9zur/gM -emrcNV/otvevDj6xdJ2JARwEEAECAAYFAkzymqMACgkQhGj7kI1GguhZegf/bwYT -Py0NiHV0RaL3AcAGzbHKVf2KUl1U60pg7ywar66FHU+pCpqM6qa6puN5wYgn5qga -ANkhqkj1LJPIAe7nI04T4ylKgGZXaEW0NDN35RMt76g4+8fuho2qZ88BUODYe80X -EW8LevTeMICPjaoNwT5R1YH5qdjgTXhMn4UYRBFph685HjX3aVGMcIf15mo1EGm6 -ke9sIhQqbucO+YnQDIvVAuGy6xMF0NQsMyuOY3CmYHtns1V4UUvztIroDKJtpuUg -05+sg5K4n4SNxABfX025QDzNvy+ZiXhYOqQVAAuQxfx6NY0ZSWqWTfwHlvKFJ2W/ -T7upExty0FTeYIL7RIkBHAQQAQIABgUCTdI+UAAKCRDeIajoo0kj7XnSCADYXEjM -wg+ID+kfKGp2QRRtdRdrPG8VcTKBQnQE2IdU1CYo5jWfN7Mih3rrdAFZfBtchf/o -+UEfwJ5ouDJau05g7mjXUwLuGiUIp8dM3leoAuS879iN+W3HekVkHspDAuJ6boMw -Tio4uMninKYdJJxhpGjeD9ZwDTHGYMF9+7Nr6NBy+J24FTq2/220ONMTV5CI9fyc -XnE4z7iXS5AoOkAnSqrWFxFM4tidAkWepC0dBczLN1cH+0JcFG3tX6m8I+TaZCSU -cZhjja+9JKLj83lXpbCgwdEBdEp/1Elr/lC5wrBFvm0h0QF+7xpRva8bSA4GNJDC -rTQHk40Zv3D5mLU/iQEcBBABAgAGBQJOFixCAAoJEBf9jGrnmt759XkH/2aiMVpO -khVGyTjmFOL+v92Q14hYLFgK21VwnrMPrOI1YgYluDFFTx841YpP89yD1P8LX9af -fDno3IEKuspbGzFg+UdSMGikLfHZJXtBIR+VzJDT8HDLenLU2QaBdSYKvFyEb+8u -2EEO+awmEddL+jvcDrsa/M13aCP/fT8K9/lBiCJeA4knFiBdTtsq9/AufoZGlx4E -Vz1zaivXX4FFkJ5Xb/f1UMJBaE8/NjAFHxHdByukFVP8/WH77U4dQ2NwVvLBM7ck -hlmWfnlzT4xShbrmWEKODBqB/40MCdBAfOXt13PKd+o2+x0GZcweFapF0F3KDnNi -NTKLwJT7vBRL+LCJARwEEAECAAYFAk8GFlUACgkQH3iLRQq9KilAQQf9HfHXQXZ4 -C4hoBIZUpc+viegjRmMqvgyATTe6yWcClGumQvhDnlaDgIU2GiwuIoGSMFopegUL -37wa8E55hjKTK4n6E0G7IP1qFNHtLqs69xL3dzPoPo7y2JRNVqnqvKJ32BrAEJQf -HVG5lGlU+smGnHosfPir5xdNESBApCurRt26+00tr2Zs1sYVHkWwejhk1ltM82GT -kEa0QEiqOl7wJU3Sm7oX8MchEWngtSlnbXdBPnPiC/DobNHKGFyGTAXV0urXrRh8 -cq232hjDQsGjIwM4fZlymaNJaFFgr26+sbvQPGkDdhnvR00rpfzZyapmj7wsQ6A4 -PumLdyw8ZlxxlokBHAQQAQIABgUCTwkqtgAKCRBCuEjFld36k0shB/45x26tP5kL -Jd2N9A1SgDxS5+ZS+JrlumNlQ2f5zfOFLcRsV7Z46M+2+0roAtlANfQE796UKzNV -aQva5K7N9BimjEqIj2RQAgvPPPag4rYxpCfOkJmZG7UZG6diicMDKgllis3mKk37 -8QPo5/rKQt7ANl5rcn30eRYse+vu//gLr6iwfYfKiVFAeoyvzE4jYOZ1CpdmaaXP -3PVQMkj9DSoEyA7H4+ZAPbmQ9sBiWojbeMNZu74Fga1DMVgRuyLF3YErmPag/nHG -lXEQ9Wo0X2m70RrtbHBtZ1MOr4edJqgjwqB+vUR5F5nRGipb/eVlqlMFWWrtJvVK -PYbZG6tZfBVciQEcBBABAgAGBQJPaLZHAAoJEGw3QuOkE0l8MGoH/22YZG0fIJyk -5a/YAh/RMH1LSALdgxHtulRIlBsH79BqJyF5Snwgnp5XVspoKqm1eyYIIBLh66Ps -JLv3269FMARUDzXQBbNiwp2wJrGIy3twm9NVStvhJwESNwq1ZqfkDKe5HUQHD9H+ -W5itaOjkvlAjE8IuG8Snn9d1KNIvdN+CSaQrEPsP628F9SyF3615u8CQbSRpxl4h -q5SI2GjfAOFxVTsnoTCs7+3NaPU5VR1E1AoQkIRmnkVUs5vdH0bMXK1d/VIgZxLr -qApzPw/B5d9EXNY5ANyrkwAv7zlkhfx9ROk/9QX1WVRS6j7iSUDt2YpenGSpU+s8 -B2bZ1IJFKdaJARwEEAECAAYFAk95zBYACgkQByWlrochbRfIJQf/Vgnl7EsYamB8 -zC9/Lf1sYdk3CEoM17R0lp2EqKp4P3nRieX+D8Y+VY7t+M9fENwrOPdt1rqum0BZ -epp5i7esQ5zVc5gGQ9/evHHQNQp9RIld/royQtnoGKnkbwSxc9EtRv/nTZP4WUlw -/kgnbgabntzSUHkkLp4IaZIhynot9LzNNnuVi77vPr+JQqiXMz2XDuoW4Ku/0Fl5 -wtn4JoriXhBH0O2AUB7Vh/YzNREBS4SgORBTL/ENqAvka9YE1HbHvp6E7fJAJ+ys -W2ZslzjMrtPgydoz4sQjo+BhZZnJQWKFm5k6pkGYVOudn0DGzQR6kVLNcfGCs82o -qLBPty6a7IkBHAQQAQIABgUCT/jHaAAKCRD5Hg/sdwJpViWbCADMROqKHAqoy3B3 -iDLD3H5nzADDkGA0CcDIvr/URIgEIbn5SLzr0GOx975w7jYkFHvWtPG9yIJ4hfA+ -uwOd+ZUaRSyFJAcHuwGm74+ztMnWKuXF2IExI1N32Qt5n66s2F/utuIMbMPlpb07 -aenx5JSgeNVE+hYo4kdSD2/LNKFsUiTj3cnbypq2pswa8iy1flFCdqyER+uQmN+V -8Y1Pfu7xkwlrf933M8nZv3Lc/0gPQVWHJv1EG1Q6GN63ohV7Iw7una5M+0dQKEnH -LPX2YhLf+61bAh9MwLHU3So4cCrkKDhNbPCcfulztO9z5Vlh0WPI/nzYDfaniOhr -C9VZTpb8iQEcBBABAgAGBQJQYTa2AAoJEC/ehsX5r8eebBcIAL1f6LSSQDmejquH -QHszR8MSW9DrLOJV3J3Syo/lkZOcCfLdFfpbVFJv4MvVMcRj1JnW+N/2bqDV5e20 -N9mceOP2AKD+6wilHW6Blj+u7RLYXcD/o5o4TsidjlzBV0aMpWPSCj//1gtIiGnp -YQPShmYkIlKeIJ1xt9oWIoV53o8BW6s03YRJNKC5C129sxT25nZIgYpjl/p0yYUd -8JFyMtig17CjFOIsJhSPsXKl698FzCDKDos43U9wsVZnvGk+EoVd64fNOT6H5jQP -kG5jZl81Mszvq/D0J63X8ywfxklrTUGMKo55qZf9F/RtvmYU+SETChw7FpcOUhQk -VdcEDNyJARwEEAECAAYFAlEZVl8ACgkQvIoD/olqd77w0Qf/WyMMWZzdSokntQh+ -B68MUxfIc1J6KX1vlce2x1rZBX/R3UIzc9uBM3kW5F24Y00oGigGS6pG3TAr0a2B -ne2kxGyHZs8ilWxUAQQh4Z8IkkkedpdTdFFze7Mk//m3meBarWsG50QySAWjnqgg -XX5nqibloimEr5fnCOddewsH5g4MNvY84Ag1H7VP9rlfCB8HBlzCzeuyeA8oRjQU -BvjC2P2L8nwzQNAz0luwHKhperwK8AH3ZVAE+vbUVqQ9RQxu0/U5430IviTk5Zf0 -ItRfz2Dvpqz0Rg+e5qfOmkdDtsNTlxTc7FHlWEbpXpjrBKqN1WCtDfAuPstWFQ+n -FC5R84kBHAQQAQIABgUCUV0cRgAKCRBzQV1JAIe1s26YCACNcawOF2aZJG0CFPCq -OBD5GPrmzdj7MqeO8A0n9SZlxAv2+5y5tWWuiY61LEfG4J3XraWBEGtZKKXREb4G -G9RnyaQA08EjZt5ABl0g7SCliLaHUTfVix3xKrvOajEtrlnuzP5RlydzmDiay8ko -0h3bgGgnJUo1MJUSY/BLQ4pktA9AVVbJHvXGM1mAP1pAQH8nE/ormKMez7Jx91Vl -DUz2lSqkLTMQdjOhXGM5XkRPoFAXUJxTSuBvp1eo/Fdg8lGJB65z6WF84pprsS+C -9AzpH+dPkJz/TzvjR+xlNFQQbXucXIZDw7LUa4MO7mSw5NSOQFvWpx/xg0pLfuE7 -1YM8iQEcBBABAgAGBQJRvgpQAAoJENLXKZ/BKRWO6n8IAJ0Oe139RFDni4WJiSY/ -BkiL66cqOWx6rE31xTPaRREvvtC1RLQKxY+0+0VbJG071T9vy73Y/92LKwCNOhNu -vWn/yoh2ZkuUt1/m/8riXf4KZu1h4RwSLJy53rXv250wIyBbGJwKrIX6A7atQw+s -8e8HUGs7CIrVq2ARAcd6IP1aBNcvxikBrRG/36OaTC9DlolxDbD0SaWhh14187jx -8zjVjD9M7bm0wE32mxIii0InqqEAc5otKSo6itDxVhJ8N3xkx9bXagjLK+Rokvin -//ZV1Y+/J2O/+sZLO+1F6G9tNmZwCpp6IJIFcMNSdy2RdRE0AA4FRW30m+tx6ewL -aXCJARwEEAECAAYFAlHPdu0ACgkQ5IF0TP/bHMwrtwf9H/5SB+Nw73cPqqd/m6/J -YSg05aF/mbt7m3Ps3FcNEWNhM/j6mcOHnnDoI2UBvNdBzDiue/PKboUzPOs3aY0h -cXs1z5bB4T/7Anm+MoRmXM5+yYFovQa1INAxSF9sa1P676/pd3e0LeRv6BgRRzNd -yceEC2cZw5KRa/8KKTBh93rS8+KsnZ09vGag1hwyvWKzNJ5B3GEHH4XJgLU4WPT1 -dlWAZjhon3hhTJ4KPv/HYKCE1ibgSm+qIK8aYLSKgA/rCJWmuexw5I6XTJMj7rtK -I3QnwhzecSmWJc3xgrjos3rLWjAiaydFEQOn4qPNYo4h6UPyZ+MsJ3XmSDPTj8gC -UIkBHAQQAQIABgUCUhEJ9AAKCRBQaINgGVqrUnZsB/sH3aYK5xwpy3iuhYbjiTka -FxIGRFMa1VGSpispBhA+2LFjNp3eE1jW2C3oKr6K4nYfkhg1qWxS51If4rZQG9Qv -I7P6+/3c5gsI06fCxjyX2MaZmgHY0/fKLlaFN1G0PjKH4XHvbjHkCGC0O5NEhM1L -CtCpX84xuenFzpNn4VOaFRMMjKzgGGNe5mW8026aGT2AEHMKRpu9KyEMVkFiOgBu -2l+t2HXT0kyQJX59pRt+aUf3XCROVbsXzKmr6K9ouqBsuvHgbaQpeSuh70yU4UvN -h9NeWgJYG9bcPfEicbUL3rlDgwpEUXgo5VVaSO++y2+0LaV/IBfhR3UTWZFsODJC -iQEcBBABAgAGBQJST/0EAAoJEFBuExZSGqQFyxwIAKRE/QNWpChq/UHE1nr3E1eE -oTgpmWRygT3eR+1UG3PePZLtApFN73HJjioMNKq3AcY2q8WIWwsjEoeMpEmiN9Ff -5DXnJK6j+c336pSMqtqpubE3lMlL4q3J7qINPoZBw49UOGBV1iRG6dbKynmr6CR0 -sRTAoEO9TgQGq1fJ0Hgqo/QyCbJhCU+sMEJ30IGYYGDiwEpes7zfUKwc3kNmZto/ -XjBKiEOK5BsA5klogfOPIBOrVsIt9QQPyqsTRJolW1lO2HzZ8zhSXG2cOA3rRrmu -g/T6T7bSeHUGZqytOhW1roE/b9bkR47mTjSU4twO+4yRwGHvayQR3Tf6mjnop+WJ -ARwEEAECAAYFAlJ0ViAACgkQT+kYsVT7S+V9cwf8Cy0fXS2+tr4nHD+pYnmSr4kY -9k6usdxJwh/XMv+hKDCHmPN8z8ZdTMZF+99Z1XQUhItbcfEfLdMtLYoqmCM0+ES9 -HQS1mufGzlATIMVo6+hGyhAQf5PJ2kk7wxC4il33wPQ3LxmI2UAd8NctK2T5OUlD -IByjZ+o4/FkeD7hTmK56PkL89d99LUTk3ViJQm2N9574dmX0luRD/t6R91LYcT/s -pd7CrBPgdz/4vyx+SV04vbN45DW/rUaGCr40wYTtiZArlmISuLKCGOV+cVexx5XV -eJ7+0b5CXfwpZzW5AkriT+EJ3p4jcJb5cPCPQkL7kXaBpI1qG2Sgng5zkEzpsYkB -HAQQAQIABgUCUn0IugAKCRA7zGVyYJPSPFomB/9BotPp82amqKCTsipgro1a6Jdl -t2BrxnlRlnCYEEZa/euxf0vmV1s+gJrkpeRc6WgOs4xhpSv+Kg7f7QHv+bl4zik+ -SEDb79e8uz+OYS67qBIqwuEccPoBa5Rj0gf5VOBz3qk/4yrMYkM76N/r+jDqs0Qv -sIbnQ6pJfSfvVpVjSkISkGn1/Qj1kuzmgy/nIitSeDJSUdWvZgie0kbDZvjsjUSe -qot9OC5FjL0Hd6tVWeX4DRJYzlHTv67P6JmcwpAgMYBzSCPznFmlhwLoaaT/fEig -HoT7FNZ/ETcX1FrLTt8ro+GctpGcQVyKefHEgxaNO38pFUnG4rY/u9+Q2qOeiQEc -BBABAgAGBQJSqyV7AAoJEGpJ73gvrqlT7NIH/1qHS3Vfy2dekol3e3SrR9gyMBhO -tQs31vbl2S81w2rFZctolM1oKtasS5GX1XCJ6gpC6iLMyQIauTJRdUoCKnfafJlf -X2v01bUCyDVhbvzPUuRsVH80jxrCJ57JXtaQfFaplCby4ULfsbbBv1MX7gx28RwA -zOYD0jfG+ruoDooGsLULH/idVju1hTua9KE9MNqFJ1YNY/f3I1UHMJlO+kQb8DXM -83xo2Icc6PWVOOU1/jplOIdCy7x4zkgABYZuN0DI+CCAIuxh58XM4FL0uaYVcWJ/ -kTv7uToZhpNqLx1/jqJAXxy9Lji73acyWqqv1z+ICQzbt2qjuEp+ouz7wguJARwE -EAECAAYFAlK4yBYACgkQuRat5Wi1M+VNlgf+PLUDysuylM6JnB0VttLA3QeROHB7 -l1zLeVohrwWjVQNX6QRHfS1pj4mKIZ9HRpFRJc7SLPfXNxK8/lREBQbsz7LSR2vN -VPYX+aPBXTzspbuQRMbo3zWQVPEcQEVYrM4d/JRkM3EAWZcmBUJ/p5hxGxMM5R97 -t0HUu2rzYABtq7wtIFWRDnhEKUx0qcJLtrJr5FBKz0D8Hs0w493WA8rabxfbm+0L -8JFx1Sc6OYQzYW2ynrc+xYcNVBE6Pa06tvb59hXKd7L1RzLyJJR5qAUy20aEjyPJ -UX5Z7e9eOL/YCBmUERmShJK2hdALME6wi0/JZZU13HAmvnEtiLTba5KOmYkBHAQQ -AQIABgUCUtFcSgAKCRBrs6FtsnJRLCowB/9SSNGGxsFAQ79IEf93AM22pA9vtlIw -hXr99/Fokt9m3oJOdznBsgSQMoOGgFka4M3oXnDYfqEJ2SD3cc+HhIYLEanLG0BZ -SjR53h4CHodM2EroE2xJPSQCyS1evrBWTzf13ATXAPsc4XGJ1tjHwCeXNl2BQkXv -pwtDps1hz6zMjLhybU8JFYFZ2XoagTohIVHyaYqndCswNe0FjsCXv8pITQb2QuA+ -wcKtBOJ3aHEIuXOAnNgfW53VindsNvPiuEudN7oUfNI5st9ONmaKj3hnWXg30gm7 -YVUJarafncsJ6QkWbm3bobXFzfh+20hXiD4S15curliRHkHDr4v+z8U6iQEcBBAB -AgAGBQJS2YomAAoJEEjriy1mvrzjrfEH/ikXDybL5xhLAU+6VZysn1ZKbZF5BUtu -t0yIBEDIcc/wuNar3dYfxu9lc1nxk5zHEtrZhF63968Tp9wm72nGbGzL5Ig6Ma8Y -BlmTNXXgQiVmcRR38KNpBoACeMrdxUPhwQ9UMpltDIsV9VBnHfwrquiCExY+JCTg -752tKHkNa5ipGIgyzhWmcPt7cc5Ouy4W9iNSHtmWWg8+t47QmooZH4XCWlChBBI5 -q8HaQ5BzhFtFPxiKhtgoT6DwNHoQp+ITr8DIszmo4VWQ+whBxaFs9JZqxZDW6LF5 -bBFwIEE2QdKSzyRPd5atMVFgWGny2JXQMTM7mmRc3ylISz6TWYhyCNKJARwEEAEC -AAYFAlMGdlwACgkQ2C/gPMVbz+OBcQf+KUCAMVlcVvOsUD4AjM19bVrTbhm0fBz0 -5wvvifcR66MfkN02y2cEDlET5dY2lLfzgvSHHwfAE1e1laXGKsQLfe4Y69vUHZMH -ioy63cpL7nQyfvp6dsmNCa/Fq7G49u+2Pvch9T/5xCOpw0/cFkxA1sEXQCLKKVTJ -zxlsmtkiHZjqplHtC6vAarV3JSUxHxvcRCDijtwYoXuU+NcHMsjbhzMCiI8RLm6Z -tVgSBdxEZLo/uizaJ73WWtULOMbSfqNebjrRXUtVa36tcOW04fwc8IhrZHhlMbhE -W7An539yTNmCLTWRVkS38OjebNmL+OkGTRu5IB4f+orOImzPm4EL2IkBHAQQAQIA -BgUCUxhxSgAKCRAe/U4W/IPIDGkBB/4+eDpIsZmyu29c3d323Z+go/uer7X/2NI5 -nqaKqbH0IyvhgWePkkHphWiYZTzkckvBxGahUX4DQq8xVP9L72rHDrsGYzrwg+GH -W42hnRzXDL9ImyS1CtDuUrp8g6ssNw1KypAlfNw913T0Hsz98KLknlPsRu1w/2N3 -5/0cS8H1XmSfk0fDKTKgzuALP23N5pHzYKB/mjxVHIftXcv6EVmpSMCXkwotBB/P -jVxZwSiaSWMdY6j3sV7NWFTHBt1z1pLw5/SeNzATTIydaWacV9Qo/ifeYqvlXvr1 -ZgskDepdeKgiqrvrKBftK1jWYQxNjO7CtSCnkESL5+Bf01NTbkOWiQEcBBABAgAG -BQJTJlTsAAoJEAYnyoUDsz2YR8UIAK7jnNxk3veCdl4TQavj01VWGp82/mVWgEAR -VO9lRO/HBh4R9HtL/C3DtPAlPvr6p8/ogrnG/wEPywvIJxfua9pl4ZcoQrOiLt8Q -20EqJbuZIy6mFP5bEvoEUiC8CpdtBkVUW9FKanLigQzQlpLS6kDYm2dM+QLNVK3l -/oAscuV0O1imfzrzZOUAHnHwlJZcyx26y8EaW5t2uNrxTS5W9au7yPP3tY8R7UPt -4T0327YU4aF0EdmpyBEoiSkKQBjBihRtRcBj2NOV5CJ0+jr67R4D5geC3wzuf894 -deI/2Uq5S9urZJFp7MknRfEGXq9Ex3kl6DIrvL92eWegvLd3pKyJARwEEAECAAYF -AlMozwwACgkQGhhnLTXfIJgRgwf/XWvpOeszTteR1dMFTq+ZDGRzyVLiDlRa/vDc -ykh4XrwXesE4c+6qFXXRBEq5EdOGn6d1BqcXxq0jYFFq7/kLXpTtT5IgG5LR62dR -2leQHmeZ8sZUsd/3vw1xH89gSSRlTZDF07STooBvaF6RV+cn4q+OcQXrnQx+/648 -XEDVduhKRSML6YO7Qw52nUBvJqRbmqY4Wxbc+NejFuX0goEC+BeNk1pM6/CVi7w/ -nTGYtu6zZGic7uRCHN1DP7Ty0+HDTrbMeaG9JgbaMp+AEF3SVUbH9DjQCPa9J10B -MZds5sCNI/giOmXY8R3QIP4VJZOSD/kdRsCsti8xp1MCdziAaIkBHAQQAQIABgUC -Uyn5PAAKCRDIFBE27BEYA9VQB/9A+99OgjDnTySlILf/beQOxgxpq+uIvkW+WTyK -/obMuxN9F7xyot5MEidgZUSzVXm/29BY+FjUtfPRD6BFq/KyuS1tLiubQc0J274y -l/0Y3Zwvchzy2kJsfi/5R0yGEZsxuyjtxwCQdGL9u/sYJgcrGXiKmqxyAmfvil5l -O8UHgjiu0y2vh5qkMS56EbM5gL72BxXqeZfxkqm7pvZHkCixx0dKBd/Uen9V9Axe -pM1wTNVJcCym0Xw9a6GYlT53k3ATwGPRG2UzaNS1x9FO9I0Nuyqe0SAZyw0R1Lmp -HBkwbjNH2G7en8MKUlYOpFJklroQrqWYma+n7Sa0PCnQwnFjiQEcBBABAgAGBQJT -SgLuAAoJEICTTdf4qi3xTh8IAIWclQJqmSWQi7+zCNZnHR9T4mxCLqymPuv6q8Ke -oJ/FhTb0oVhpOCZRgarvajNaodPbPp19UIkADmsYAJfW8Yg6jucuK7SsenhqMaXO -yjOmOQ42BmQXqhxr/vNF4lPBTEMThLJrh0dEQexDFoqD5+ryeict8iyxpuNu+YJM -hI1eVMSb0APW2L9EPXzDtnzE5kzJADJBq0NRi7V/CGQd5SXKQUsH29ViqD611miT -tiY/cP3iLknV47ghRXB6o/pL7qW5cS5bxYVOlCtl3Uehqu1AcMBl0b5mT/L46PIq -mKDZWuC3JoDqEQRB07d3L11ETVbWWPaPv3a3pC2Kv1464dOJARwEEAECAAYFAlNl -0kwACgkQMkOr0j+GaWCv1QgAo7R5+lB/WT9t7obLX0HSBx7yO/NzFjDVUqbRD4H+ -aXAxC/QxPbGfEu4qOdzs+i7dROFpS4svthaYLvpmvnNNa+zXWOP40EXquENZLVVl -rBr8bcEQkvjhyd78oi35Cp/SDVeA1EQMcSN8mgVOTpjtiom+pVqKe+TsyWiO5bJY -zRh5ryJKTMhblf/fM/QiIhhjaRzTe4EisheT4WtBUbJOktIbnJT1TMVnmyAciJOw -R72sv7WmXqhF3JHcl2/KArSRPEdibQMEpAYggy26RgnTc3CiGiV7ezkn8hC2zJ3i -q0TVzx6EmIKsIGZhIKQ3faKqdL3Egn1nQ4npaKk4IFSe+IkBHAQQAQIABgUCU2ci -PgAKCRCxjRh6J6GeOIJ7CACH7oG2wYBWXh2+FenwxTwKLVWJ0RllLA7Du3EK4Cm0 -gaAc15WVkRtUVsJWdlzGDYeTCve+XkneswJhQape/q8kBmu1zVSgrYueeShx0YfN -GElzL4iibN3gu/38IuAph7neH4jifFT/X4MJ73KsMGbLlzRlUNVQ7pOOS6sqLFv/ -w+9mUgUA5BXefdteiA+eSQF9JX7DwtSAMgx+vdesEpTwJspT21Rx+icm5I6sguMq -Emj2xFekPwnvS29ftnFokNXYjI6fAwW4bxpqNfdcYjrH2TmXEm6ax6MWbvIiKVvK -qqaoozwuZ0rVQfUk5rU9V66iD58AYyoa0haQRkIue5BWiQEcBBABAgAGBQJTaM0i -AAoJEGUU3HV1ZwZEj5EH/A521RlaTGAh67xsHTWAMoIDshw5u/qqLsuCGp/pqiN+ -+U5o8k+wjMVR+sety+I6Q9J698ZwzD7ahtu2yXl4KIrJkGBawpM7SCDwVJrR9gBL -FS4L4AfcN/yYpek9pNa3o2ab8qKYNGvlcvMUIBOS3VcAKCFKsP37XocgaDiWb1nK -u0/SSJipjk6+TetanooXnQQL6MlFO5vWln1ucSJeRhuLqcoZTAfMPCK2Zg+RhVWp -Ibhyw4cpbBYkFJMEgOetoBZQyUWPEOSDgM67AEfExyY06HZdqIERwmTOxpBKqGj/ -OoC38Y9ZG3kJKkh93R5YgLI3IVppzARTEd8sbjoQLb+JARwEEAECAAYFAlN0FCMA -CgkQ688OAmNixTr7lAgAysXw0Os2uyv/sHW+NIaGt5E1nyzKZToOpvL9faaFCKG8 -/aFvGDnHIYCJo7iK4oN6kyNQakqfI5pF0EmG/SdjDrZnhsitpQ7jC/pirvJyXPXR -Cz8ojgXu1KMJBAokqXZ2U0jlskm4EDMdUlcBJsACy1pHQDmM0dSez5vkXdNAPvbO -kxoQZrVWhWhkppERow349pJ6J93fJHl4sMfROHzMvYQnanjVcd8GwtjvViV9ImtP -fY5yIeuAZuO4teBgEr/dJx5TdCxAHduRuio2oF1q1WA4IsTv7ttNmn4Brfw1mSPL -1gYbm4UTuZLhmGQIlJ2MbM6YAXS/xtIlXBGCnZAWKYkBHAQQAQIABgUCU5JdSQAK -CRBRW6D31EnTU9vuCACTdoYkFaRr8wv9WmGdAOrM9zkY5RERdlmFSDQLXe9e6Zp6 -rxvnlx568n6Jg/9+jZYXE2fQACtVRHlBOGimGzgEdpXLOPwWJpUG0XQLFV72LUp4 -V6VZFuqSTB62mljnugKMYmNmcxCmze/nzQcbJDoirQ6VE95xmKDa/HgGD63dXulZ -Uvb0t0Sv3Hopcx/VcUm1pl1Dxn0qMOIr3SGZjyBxi5ziIiNd3tDT6D9LjfMRInjF -zymqOx1IfafAEpFBIceJf3pjTnu2iXM47SqdFuBOC23HVB3HB7ixpMxHXxaPX23X -Y2poECCdTwsd8CoVxh4ShhQbUyOxdcPlrYx9aydwiQEcBBABAgAGBQJTltIcAAoJ -EGtBqabOXY8/H0QH/3DQ0lEo87tt0NYFt0P9GxieOnUcGOMj3qo1mmAYfS3Iqe9o -wsJr1Wttt2Yv+GhmMdLmCBDPkWOxfsfoDdpn0olElnlxXYvT+/UurWgfyomRneTk -2ChTyqsjm8i9pqVoWGWsPG4K1XVSSWaVNF34Yua7Vys/DdB3Wuyyke4bSnQlbP0H -YaoNGCAeUzvwF8luP0f0geNErnXa7ZLaL1DZ4f/Xfg9Y5Kma0odpzVV9pbU1NQai -tCKy4hjz1ELYBf62IFXUlQL2vxf2F+h+d7Q8uMfUQi2oB1v1lLWCjRntlFTx/zg6 -lS2baEQolb/rjdgDrK5D3EaOHyiGkZGhLlJ4+dCJARwEEAECAAYFAlOty0wACgkQ -AWmZK+jRPCyw1gf/XKT3We1yJ8/Dmt75uI4gCPXHxXYNjwdaQS0Bs7DIX4MI0TW/ -uE0OQMI9NKpTGIj7ySOIdzEGhiys73CesCknuDOH90XTOKMtTP933pgI2rP+Qc5g -OtiHfgg3SL+ypTNyBsSTQNiQKlSmHhx3jAu6VT2v1nhH/G/bofVuW7QPvu4vNLX7 -EuqvM3pNl5Q/1SYA/m6hMMr92OdWqcuhRHVMk1lJva/TLI/B0e9XWeUno7aEfRCL -aTD6qQOHeO0aUU20KUJEVRsWivOgLsbXWQFu0GAifn8lu90gmnoY2gudmCB7eS2h -gxTdYMIO5CHjQV8lqg36sVFklR0vPzSWao1K1okBHAQQAQIABgUCU7kVeQAKCRDq -xevweqnCo7gdCACatN9VT2j+XVh+Y1+wGmz1uNEHNwVEeJJi+FZBwTqDPjyvqKxY -oIHTORTh7FaOevu29owSjfkYVy3lnbUDuVgwbIDZCNLE0ZBAaLoy3oFbokDjJvE0 -c1kEoJlDe+a13aqW4ieFx9kYT7dzeSBFecKxKf2U8G/+WGlGn5cAt4JvxNBUQmw0 -sazYN1ZfW2jwk39Zfn2fYYNptzO4+54082BZCRFseF/T4p+iaTYGxPfj1B6QxNUi -HitVFnSD2g6MDatqT9QRzb1A2F2tvmCUFw8a3aW/lC25/I/E18Zi2hUUbQgd3I5Q -dzAG3Ocl0ggCN5yLVC+PeZx63bI6EO+WLDIyiQEcBBABAgAGBQJTvLZ/AAoJEDD8 -h6ogg6s/YCsIAJ3iPMhM/dUHcOuyr6xgdLelVz55m7y94rFoa8kW3rSRdQ4ZJ1Wg -WQw5MyPP931ya7FHe7JKPXHqof5xFLwobMQZqgnZqNMxlB+gap/ilKutmO9x66hJ -4ycuSSpg/7LBEw4U6srVJiJOsyxhrz+Bgjbli3kbjxoEyYjhBGfNmzb1a5ib6EN0 -uInHppW4m72CU3GLoojI0J/mH8wSYJX3a95WNTW39JV5roYlHt9FMg+q8K1jzA3N -BTwXgE9XsAPWuxpl6suQe/1kw5o4w54SNOyknT89KNnd6DZhXzZmgMbJ/TxwMz2l -+Vj0zVeQjvBhyyV1yMDDxOXAsqvxel+YYAeJARwEEAEIAAYFAkz6s48ACgkQyofp -6CqsM/HwnAgAuvig6ZFImL/Hq43v9cMPNxWbnumbhAU5j5Ek+zXqI12gDoKL0QFO -OzwJot1i8qDlgNdOOW0z8EP/cJgivaa/noqbpI0/+pQEqu7Qc8aevSDcxW8zSQMj -GLzHTB54YoBge6YKHnVJ5bdhIedG0RNhTsOAtIWq4PUmSLDZW5KdbcRfbtMaLHQb -B2UypDedasoDErAWBbtMs6hZEUqLaNy9d082ZGR4nOk+DviyTLHXRvKkJ90gQBpc -BACcsQrtyZkkXepWT4qVwNDtlCBZEmz7RMinWhwIa4jw9230jDNbYp7mR7EkLeAx -o7iMIUM5BvO7GCF/ZTFrJxZPWuPbIkWRsokBHAQQAQgABgUCTPvVdwAKCRBJa8M5 -8qKCWzxUB/9201np3PALZL34cvrlA5oPcDvBPGN6vOI5J+BizA2it69oKWs4KwMd -XY6J8kdUzINnyy6i+BdsvoaSn9YsHm22/SfHMK2Lngr/Rpc2ed8z8DWbK/3qGlvr -dEOX6+1NA0YwNZrIC3OWamS23CS4pM6koqqK024JDX6AZNvuuWdQ8HwTONBlhBj2 -Gv2HxtvbmyQ4TI/aAkopHDhZVva4HRqm+h3ocaSp+mTpDJ9UHrkTLg9tSg22HpSI -plCekzYL+Riri0Tcs+R7tMcfbrpc+NER7ReOxKZVJFmdmbKONUIBCq/OZsA1Uq49 -dE6U1cWXtrgYVcU076kF816jmVSJDXn+iQEcBBABCAAGBQJSQFfbAAoJEBBAm1tU -UpHpLXAH/AhCpJTuo8S6o0ui3b4xeQWMt5rhQL5vQpbcvCiZRM6YFcILKUswxKZh -b0aFSujRVij+NoadfmKXO7F68vlIyup3o7DN3Qu1dL+e8ZDApqdRCGXB2qrWU+pX -d/Ifiu8683LuNqNRUNw2NW5a/tjJMi6nhw9hrI2wtjGGFz5IqT40jJL/7ve3g2pp -WAnEmKbnMLnS5XWyBTRYmVha5gNVK4KdIPz+npdv/3UHFMcHU+5YlfQ2GhqNNd4m -XQ6aQFxdcfiuYZ8osFmcBAp4kLWkl+wxfqHGqq49BOHskVE2yy8zs8fZeTx54URa -Fp9nIEQlD7gH97xjFaonfZD63tY9bIGJARwEEwECAAYFAlDMaN8ACgkQCLWg8mNt -aOk9Vwf+KdgZ5ClaKadGNVIjVHtTAE0cmY/OjxSsEWuICdN46u+pZFgVV4fs7N5v -m2lTE2zMR2XVdHEAX52UYgq412MLG5cYNtUeR0jG3uQoXUyLdIXVBM/bokqlDzwU -u6QRQb2hRsWLM3QM7Gq3mn20dEwNU1BJnBiL/sp3sMlsuMFuqoFlL/kihY+IzHxK -RSIQ0kgBX5qhkVdXNZ7ngT4FMolIXWbmF/W8r0DrHn8oSTLWYurfSyEWRYGxP6KO -fAU149uycTAS7Vacj5+11fVp+tSZPSJORmsYgkaCPYBEOnJbnQfQPCUQxOR2XmOw -L/xzvS2fXVz4vFVowvIWDyBJx/RrRokBIgQQAQoADAUCU7Nj+wWDB4YfgAAKCRBN -cga/TYOYaeiDCACACNY3VinAzkKgMo+qQOxDcVxrEfAL/pbTUTE95kg8dm2HYPwX -mSBW0W6pCEx4vStfrPo+cJRbeSVjsFfl6qYQlGRUYkkqH2eBrCBKUxQKVDXGozHB -q1jM2EMh7CaXgTDYex5lKCI76TA1ljupS2p0UJiQj63ZvIrlv7tsaI6RbBWOW2w0 -o1cpjx94TrG0mpc/3bh2tI9W4NDTuO3I3lbkb5rdkbKWZxbqvP6+ko3b3cMJrtYq -RbY0VZhaoizZOukpEFCqfH2aYAABCNxT8pUoj7HQuotf+mmFgnK8jEVCAI/laSgu -OcOubgSk3MKPNZP4VCHGR8SsuPZhkiPRoqyPiQEiBBIBAgAMBQJRXJ+HBYMHhh+A -AAoJEF+VGQSajQw2u2kIAJtzVDZT678McAw00+TnuL1xKh7iXPtBthTOtKRFJ0Iw -uy7/G14S63kyJ5EKuxKzxyTnZ1fev8K7pDoIXvyyTXTRSGsSeuM074kpkTQzuOcr -iA6kpTo84GDp52hLJTQokT3LJFZQMunDpDf/JYqIxu7BIccX/qro99ndhEYT6w/T -REsBb9DvrVRg4b5w2KXecnpT5BSf4CfBHN6YIRGI6ot0LHrSXgBButJVtBQJX95D -4J9KDytHyOt2PvvA1YbtvGgB4XQP7Me2fGYfnVI2T7pi27KsC1OAK9B9Di1FDLfm -iuoiYwVLmMZ0p4b/GrvuTebiezAr33oeiDy8h85ADxCJASIEEwECAAwFAk9sUsQF -gweGH4AACgkQb4e/S5WIfo/vrwf/bDgw/rLGA3AItlE/h4RVBzLPE4QxIaPPCGIK -0k40ZUf4o3/c/P1GbNEvEh3qlUeTODq/U1WNU6/tdf31Pgiq5PWtJ35j+HzsTY/f -ZCg+ZJbB+CIMeYTrdKbhAHHLiBiC5ZMU/F5pBiKXopT909SPCjXdU4cUa6Ik/XE0 -S5uH1V3joYteqNL/hUdZGzfkRygPCklZOwAksV9sGp4wZkwvx5FvD9T4iBjmMcsj -KZsbkuFlpvfR6jjaQg7vH0eP63uyo0VVkVbctoFpZxbbg6j8IfO2WuUI7pg8XZTE -EGawGhgBxvzN8qpM/qFdk+fsKH7OqKyi+o0aO2T34N4NtjHCp4kBNgQTAQIAIAUC -S1ECxAIbAwYLCQgHAwIEFQIIAwQWAgMBAh4BAheAAAoJEEFvBhBj/uZZj/IH/i4f -qrDH0EdJeT4XwZsAeU9zRbvr6DOoDLvCwW2IYKZ5YradcHHc40K/+QNxX4AC2O5X -1iHLCccMVm2aJwiH53ldoFTak2Ag+//z4Q0KTQLYRgVc1lBNDoifWzNlLhzbqyiY -16imeF/WwsViRXkvb4yWxaf54AhMg5UTzKM70jNMgmcpr5AoPAUyQ0/5LwdhScLC -kNpq1Q6ZyvnwtHPB8D8nA/aGMmpqoE5pTOndGXncCa2EpdidB/Xw0b8KtVE41nhH -9JZJ+IXzsGrUKPRqwlmtNBCFaVsAuJ857CxYMIWkoXqpxjy2MwFWyDAbA+cu3789 -Im0TLtF5RjHQuQoxBcGJAVwEEAECAAYFAlN7sEMACgkQinL5E/UMZNpkmAn/cxcQ -zxjH39zp1+N6o9bab2ym2ZB2afS4JuSeJgWRwRBzWC70p7NGTN5g61/HOgU3o13r -eKVZ9AmXmw7DQTsKcD3Kl4hX8bRIjJnl3MWiUzLyDksgoFBAT0CB3sUblCfiG/LC -q0mlCsB5OnN9NEKNCU8np0+T/f5qDDzMv/6uHQMZfwRmdiJL90ybpH1ydGitlIgi -0jybTd8rpWFNsdVDQLi9thAZbEit6EBZFpfeyOb9OSIz0X3IHwmpoqQi+CbmmTp1 -LPEz36i/itgGEyraDIPxO+A80h5MPl/hhGi389m8dUwc9yvt0OGsp2MnuTSjAiUA -0cUV5g9tcgHUHbQcwiXsI6epfV+51R3YAhWzhkWySZCS4IbnoxgN7knQePNIHmWL -1rHSl3inCdHNl71UqLAis5vPgf8tkxU5Tm5GBLGJAZwEEAECAAYFAk/q1JkACgkQ -CQZoeE3rZuJVTQv+KLgpZKuuYEEG64sVTtFhTsJ4BhCzmSgw5V8h4AoSyCNTpWno -ZRfTNWEqNUUFrnCr7/dWRc86SMiRoHcSaIQw8AH+X0QdvNN7mKbBMmg+RPfTPmxZ -z8yoMgGmX6JQDKZgw32yYBDHn364aH0267WsVpK1P1EXHr24nTZaZ1l839S1JZ7c -Ei3rjiCu+/GUaUGRzDANHKxr0jIEeKsOtj+LjGgt9odjisoa1Tx86SWvs6lJ+AfH -sF+GZgR9/JqPIfG5bydNigXLJDsnZCkGWv9RITnCK9PVobB2C0CrL1YasaI8m4bS -hXOWI1mrmL3rq38Tnyrsftn5wfWgZ8IqgeqaJ69Wptsmp5Ref3j0w7pVXxML4C69 -1lKusEEcz043gDq9Gg/DaYyrAQA60sbE1aXhVaPhRp8hGXExrA2I4BJKsuBCHkD5 -D16BXr7ZZgkbIi6bNqfH0hYi5GucIIdyMnwZtDx9M1QaWD7pqUtKqnO8tIw8PYpp -nTOLdt6M3c9uSabtiQGcBBABAgAGBQJTf7ODAAoJEE+jjoIuT6SPTFsL/iruHCM8 -q5FCtzXfr/xs7w9rBn+ELqjsuq3FJ7IMCiWgUYHJDWaUSPMZ0PGiI7zo1gZy8+Af -AbzCOAK/IqgiOVzmx773GSvO+CL7Y55WOJcpQCAeD8O4YhCUHIbwIQyXdYsPSDpP -/B/za+n25qcKpmdnJ/++5x4GoXJGzn2mKjw5DJMKgzuZuxCS4jEq6k/r13sjEg8v -JM9KUxOeLvz7hfoOy4UnImKQU9kaw7KKQ0/Q0jlZyyUOjdGiL6CevVSzcI7cZhQS -WLqJiuMfZIXNBoupl0CdbtqiS+RX3/lhYyAb6sP9kKD/ROX9uY8h7KinTPzDGZsN -coi9t6qbIRqkaf4GTyM4Tw25tSlZwYmv7rJUe5ojb85Aff4DHsMEmuD8LdPoFsGb -yhp2UlbwyCvQ5WR/4a3b7JFQdFhyQkPgEAEj9LXJK+LhOSrdKweF8XlsBu84pQ6x -EY93eXTF5LuiADLP8HdnL4KW3CbgQYtM1eCzzub0zWI4L9f6FzbsRucvZIkBnAQQ -AQoABgUCU3gBoQAKCRBEKQe1iN/EV2+cC/9/g6wpKwml7jQ6kkbbNT7PFKWXYYW+ -XQ9pQOQhfZYb0Gx6NqZPG14uii6GM9qEodBxmIfZbqvU8sT47dG14O+tp6G9aJHv -kVMG8lE+6IKjZrkQlmfnAvOZSiAdRdKYpZr3nNRWid7mHMMGhBA3PE2EV4F45bXC -YC0YF2Eug8rBjMsDp0wFPTezTtTmNQhDrRK9WRhfj6msC+BNqxSaQGKoqBOm4JIf -U0pa1ThqF74nbLCsryZIBR5088dAso/sYfDSu0tO7Wowfk7jaZhXFfjkLSPyI2QF -bsmykBTgePZfuZAu/cv/2R45nBUMwKMAYYZUn6RYRvVRyX06y2Mx9DIfH6oNYGoZ -DE/xWqfB2PHBP/SbZ9DzRD5pBjnJiXGcNefhT+NFt+6HI7+Exo5bu+7Fx21TD5Km -ah/HUKfcwWDQs0b0XTlGWLC33X9fWmzhPIqingRsxDjXHGjXEublaeAjj3p0iB2U -uMz5Xro+1yPtSqVzo7DsYtxqjW8aD5sPZySJAZwEEAEKAAYFAlN42wgACgkQ8u8v -Rwaei49QHQv+JCT/WEZQFlsUfRISHpQSf0VgDqjcKDH7bN/zoRvit1KnmrBoRVcQ -DCwN3BlubA+RkFFY5qowUB/ldTmb273Tjbb8UERZv0GrXJZJaeuWl9sRqn2PEppc -j7HxmK/I0RZ5xDjNCaQKYJ2TghGXOkqODuYJSE1NVsvGHkZktuj3/FG9qojIAeXN -Q6+oemjvz3q+hhqUruG7oauBPO4WINk5iGyf0C6slIONe5xVt6vsWCMrNccRVer+ -yX3auyjSUIXvTa2/C+IxcJ4gHRyWq8THDbRAMbqigKPml+C+aaoMgmFuI/9f5J6H -HeOjSJF4CpIJBlRg/KUbXk2vDCohQnwewa5wQ0CQF4snIRFJlEBhKH92ChdAA5nV -7/GrR/XXO+QdfIwa9XqMYfRbg7KcdNBvo6BblCZx9ivXtjdNMnagPcaJ+Zeljlvz -3lSl/3KM+MrOa/3rYNyDHYpUUnDCA6GFsFJ3NlST1aWjvyBV/kkvplaMEmsU43A6 -OyFexxtSVzQNiQGcBBABCgAGBQJTgMDhAAoJECrT7UPn2xWPD3wL/AmwPBGouvOr -4BCXL0Nzhlyo4HU2EFOtDw2jkTAxsSje2hyZbTDGB7VmpjLl73SOxLNnGd4bhYSU -0+qdNFqmsluNfg3a4UwHnFflcAO42Pte2Q6gdc4Mo7YjQwyCb+f1wqyK6uv/8FfJ -cEwwKlHK4R6H/KgUFTbE8L7yZ31WGRDJNyFqh7NlyI30O9Dqv6WezyHELCPMtiJl -GoY5W9z6eNJ6r1xwOVled6kcbiw/lorg7LhWOBVeCyGWfK+CiudWi/6h5U37B+iN -FTiCCef0WUZlrtCawI6R+HQMv5fyUJx/EVO7TcB45smG7Ioy9GzUKegpGiuQSv59 -idB2RysIQX6It+CUOM3oK/pAhjkAlTLetWsDiuH8QHRi2jXKAEvORxDs9zgWpXdq -uMHc+TSrPmQ75jh6pu/9RgfVJ96G57Dq0Cutx8e4h19zCV+B39BMXY7CFa0B0fkk -jp0XwRNE2XbihB1uUWeBLG83IaPTF367/qdz0eMVcvVFK5VGce3rnIkB8AQQAQIA -BgUCUp/NVwAKCRD9tbjAZ/JThx57DpwIbHNKPV578tEDFldKEjUH6Gi2i5NOWiKV -NUGc00MJ7BDV4C17zlp3fLzVGKwuaweD4pln+2Nl47JdK1r5UT8T96STVScOl8gc -y1D+BlVbadwoBk9DJSR+WyLVtOMVjNstZpzLhIgUVo/sq1D3EUzFfjGuNvy7d+xA -WaD2wNXM0rLXpOPndIJ2uFP1mypf1E6Pf0yBgt9U9jmQo5YZiWjmyQPQvW46XhPs -hE1yOxI3HMneaLDP1ydCkMyGKSzyuZpcpvRZEywwj8UQ1TxWAooMsHO8mIUYxwGD -8hz1hUbRVLg/RBBlhHCktreTSLH0wHbPDGODlXtYpu/7gz3SVcgHpxUJOZNBxMUE -spmUmqkarCo7XEtkRkBIWpYATdNtAJzUbjiIJ7HKh9S5LbtAalvmLtjHymlYLsK2 -f32BeZoWeMNQxKMX5TQf8aZSzkpYt/+KSkHNDwO7mNt16hDPLSvfrfq7q5czoWmU -qtqLmafhpZEe1IY6IgtgRKPuIt1h/I1CuoBjE6/eNh7FdjhUkpS53TfGubgIzqbj -NaxTaja9xG80S3fjY4SS2uuuv3+VqFMatWVuRP1jbGVJ6nGRTQP0tUQoHqne8gFF -9/58nTW0xzOQT6iJAfAEEAECAAYFAlLSy8kACgkQpCK52OUn29sebg6fUhFf2Nni -RiZy6K99WJSGdcqt/pH4mXEfgGAIli5EHSUnVtgSPVNXdMpRYKxf/MHlGdCz9Vax -GjykQzIox5r9npQVNHdtMLJIjFFKluQWQp8PB0Xr7cXSQKJutMPIL465qFVdr2I1 -0Ovz2mY2X9UWcaDKJsKnxS6kyAruLcPpBU0099iVzeQThLJmeUgA7LNhi+T/NdnW -MTpJ+mwTH+2e6BB5jxFzm1jLBHMXGWcR3jHAjaLyWM+VczHrPNzUBZQLGmuZGSjW -n4VvMUvc/IVtwItYESR6q9ip6AhajGTtIw6Na11TQaM9V4cTt/LMqLVRRRTttZcY -rqq407jiWDD0oUixOqR2qxPakqO6No7bGfsjT3uWvm0hOL4/sSHcax+evYqpZPA/ -odVYUsvDMvoQKskhy98apbAyY1ySf6T6DKe0IaPlno+1EqSdLys8qnNqxDOPyq2f -iPd/rL/ljHe31DqTXXexQu0WdvRNfhPJpalaF+ThFBJTJgYt7iD9Cw91gDGKJdb+ -oOS3kDyDaurvzM9pX/jnd9b7mq8xL06k8Iccyl3wD7xAonvOeYD5pDzB9eiv2X7W -wH84Is2HCsyPZzbm/T9ZXh+Wlv7RF1SVwI2jC0L2iQHwBBABCgAGBQJSjUjKAAoJ -EMQJSn+pq5SBrCsOnAoGsX1mJrtt8K9whH58A1O++PyHra91FrEE4h0/s8Qb5h1J -b9TZKgbTapBGurOJkfOEm42aXnRCm669BGHweH3eUIhhM3jIBgqP0yPwa38ucVS0 -29wXBMxEGPry3fC/3tseTaBGC1GpvzTeTChGc1OUzVelR6UfiUDDGTwph4rW7DiH -JNGJrbI+2zySpFQP+DnCnCzP9170fu/+8PtmKkiixiolt4+dzChBpVKygZ+GBwl5 -cPEC9c6f6/vJ3fKkEvrFqCFf9oBoGaNd2RORhQkc9r/Bw05ZsjWNo5oyjLa/v1Cv -yF1bIQouA/OgQtad/xtjTvewPRTdGVDqWt6Uqz3PRdTjrthkknKvQJFyb3ELgfz4 -9eCeNwbXHI2CFRWJVnJf4yOlrKGOosKkF2atLUIkBY2MFKh1291KiGmidWxvDLYU -HZxWmHnsSN+ofeGRkYgYC8YjTcwNUzDOINjkJI37RzL5abm9ADEAOWukvt5e6U7A -fQ7u/2MoNZgqgX6D+XK51kqR3SfBWlZD4YoIN4B+09wX0NvXz0PNXhujoW7eOc0O -tHYFfR0eHdAhle/bUCxhOEBJU0Mn4U+nIPUOyfbeS5BKjR5gLNkXYGOPoZBUID4/ -O4kCHAQQAQIABgUCTERq1AAKCRCjT6dF4BK0LXkVD/0QqO6EtLbY02QX5wjW6wk7 -SWbHUo8pHSooAjI2LKKeTtyGuFbF0mDBt6wiFigwYmLfQFKQC8wygXxtpl3ZF+e+ -rGB4f7DBY5fpJsJz8gFH+YSG05igQ14z4yTotUSGXjG3z1j8lgWDmhG/SDAtFjV4 -cTYoZZKDXYipCOkPRL7emZ6/XaUBlPOVqIF7l4OnDjbre0K+XQUDdUif+Dn2WAOu -v+xdyR/ynxICaqrIZC8NtLSWdQPzGTPJlhRF3gSPE/65ChNWQ5ocNGLq2kxTir9r -5j1SFgz+gCmCsm544pbGvhRrHcsKz8mnEIiILl0gth+tAJZuOZcJPaxZlI3C/F5S -2yQwGQWBM2H/ATZcQhdh/fjHqd27UMpSCC6ma15JL/a/o/KV0Eav/sXeLTwNBNlS -UoudfxAxyrXtkGYhCvBU1hlh+H8tfXHkfBUqi3eu4fy+MMTO9YVs+3E9uYm+wmra -xoeQe/j5Jkvlp7Y9eiCt70hEKdoGeQvNfyyP0EYCAKq51bmqn+9kaQGoQ51N5srE -hoTXuNn+SKEsb+MttQ02kLaX024QuEQNYT6YXFbsbAi5SajBDfupYivDDKylqyNC -PP26hlD/1lpFz1pSUqYNExv6fSjMZgYSYw2tKD2nU++b6gvQmAFqW4fU0BC1QkWB -BQcZF11C3IO00bXHf9fKo4kCHAQQAQIABgUCTE+AHwAKCRBmyMLXxapEbZWyD/wM -2shOlJ7gVDVThP6FbyJkM0YtEErqRcLfwIGbx4HrycUnyxXiHBqE540w17511QVb -rnSXabfqJP64wRis09MG3oquPsXdTPcF5NIX1nX6pP77oxsbCncym25Hid00v4pY -nx8Oiu1JLv5PueUNa5YEkiPqrNMiOsOlk2P5yH9krjfNSvQPpX/HJOWOyhvzEqID -WC71WMlzl4JQLl7R8+5kW3scjUvL6z2Ewc+YD5fVzETfYmx1R0Xg3QZ+qSiY6Mif -JK+xajcLXCdUXsp0ZKEANxJBpjjcxPGtXM1cnLSS6lzevBNh+HmRdc/bQHbKd7/W -h1DNDdRAa4J5tSiT3FgEAOJulwaw81ibxlE4qsiwG6gFRHAFCEwc76qRpxMtB+f6 -JWIdGU2jt8/5u1OuD2SCvrAeXIPftPuQA8/iTAhHGmHYNi1+AKNPQlraOEHxeHdG -EfpX+s56NASI3UG3ZuzVafqGbg+pUtU7DPbmE12M+Zhh9G/QFrJHuCl6rS44IIfC -vTn9Mj8Q7otXdRQ0q54mRmy6BvMi1pi1XshPzsmLCZiDvs8h7u9YkKXopdKRT0UR -488idF5An235TR+JQL/DLpyzUu+nqPteusD8DHIE9Xv8aRrbyie6t0J4wUsSnTUz -7x6p5weXMbJRinWQonylDi3stUTWOIgDWj3RJ0Mqk4kCHAQQAQIABgUCTFN02wAK -CRCXupznYaCWO4o2D/0W/FIBtcUnNCWRaqF4Jbfla+uIEmpihcNohpCp72TY6q/n -/b7KpbaV6ewRlBirpbGZTsJqHTTqpwISQsR5mNp3DDKwyQ8KsCUaz8zUZWzBL9If -fTDtFPIftSYzonELe/XwE/BfLz1O0AbBa8iozL6Dd+te9Iu3YiwRIjTwLcHrL9FK -usdlj5jhG2gRWAjwOlRMBfqNHPbRjzmRrwnZHf0oczKxZvtGAuYoF36s8ezDh/DO -Kmvh0o7uA2wBHO11AfuLUx53/AHbYekdj49VctfPfNEMCt2Peg6NSLe71Zn/aZtQ -hjB4YOhTAHKot82ijrxBcXmBoAF70i/rY49RpzIcWQawh6BgdgwI/z6rNVDhI5Fh -U83JnKV321PKfO4wR/AL0nmVOeX4FecHXq6S0Mxzc+0m4soELTJeYKuow6MjgzO1 -gC05dZu4yyyN0Dg7G+XPQ9NGVxLOBYiOB+dX9lOExaQd4RDUid8GMRXMcAfhPvfC -rQXkhTFfHF7n6feaLMxdOAjdNGRXcNtAi/C3GkN0ulJ5yPfVHB3JV0XVTbKbdxzn -U9//vDGMe0xFkg+LMX8BNt/8Yub5ObKDEUkXF7pws6zpyXCRIf1g3vINXQPkeuHf -pUVzUISN8nV2fRwbT6eA+ycCa6qdW9StKbocZfLRAcWSvo6mtOrcdlTDFgmcy4kC -HAQQAQIABgUCTH+9HgAKCRDhX+XIeS+xOInXD/4iJ6zfxajA5+TWMCFWqknjan2a -4nomMxh8RMWrW8zxeSuHVdIMUIC1OF9c+E0GHdbeGi2G+lIjxG7h+6C9vBJ+jjdj -ZTxy8tCknhrylB7+2cTlULRkwCahicCBtjPsMuMrleswK7xex7f5ENSuZjQyeH9R -7MkMHLkx6krWVLVnIk4nJB6df1KjNlctymbtwZnuEEFFf+xtDPu5oORnYQ7VMR6o -7qbPRNWJnV6z31D1d5wU2TyzSXOjpbBM6o69hToW8e/2mxEKsMvLzWvs1W1TVr6d -ZtkdkrQPaV3Uc80wuBne/zzzGYvtpelK8qB5KMRM/mzubFSaFHl9s7AUYvgL2LSt -fuS/TV3Nlfct1IZ+izR8C9x9avmjuoBAIlAZTGBcKcphJ2qNjCY95dRu5nm91sBw -2on4zoEoWi+dW1h6deO2Tt9zjplxc9XOsW49iab5u+b7ERRdOB0TGbakGKt5MZ81 -rrwrrM5yZZ2EqXZS4clKhLOSbJnS6URnHj+tt+nawxfFfYhrR6iogftR0HV4vYAK -CBEenWT0ia79Y+dCRS9IVtqR3EkASJX0Z7AJx5B+j2BFiqsK61BaGczt2XSgq0F0 -58acJTUIPvi8h5rVPBe6uNpJrZ9QBxjKLmYuQjZhiWU/IuRVmG+AjgIYvManwa9T -21DkF8WqU1JkxZaVqYkCHAQQAQIABgUCTRiW1gAKCRCDtbgWGhvVDgWnD/4pZdkM -W4I1dGeLQsC3NwV0s02uZ0CLmbSazYvQ44Bl4fIbMGv8Iae4givvuDit6M0YiQk2 -ahL/8lCuxi00xvON+NGCamkwCP+DgoSmR+NJSZ9KJIfQHNvLBrH6YAY4QfHYgit9 -tZ/BBL1v93a+iQNLzlkldkuN00btSi4UD4D1apgdMkP3rDffFC/7wlYNuVxkLlyv -3FhWeIPVPToGrIa3qfdxcLJ1bB6e7ndd39jCixg9nZubqEDpfvXiWCGThkQ9W8Lc -WWivViTj8kPi3OhpADlJises0cQaFqxOyfkw0TeWd/MmZGg8lIKKcaeE13NPgFE2 -10U06uACWjc6cYchJ/QrM9cwb+OtRf+QPWKsDNcwzVVT/kSe4MIcPz5u727U229I -gzKBMAmY7dy3gSwVe4dS18LbnAv/UNVWtaU+f/hp2zRcY7bLDtGO8ROAq2Nb9NnM -klJPo0XWILjxXP9Tna1T22/9fMFgOeBKRx7NfFjsu0mlexO/u5sz80EqtSFL4dzN -0T/lZY1cnB/UXwbUAIK9MUyrv7H8ipLKsvpk2dSgnfT+5SeEGJv4OxEcIzc3OdH7 -cYbGwztjIasQfQEFinj96NDAv1NkvFxsRfjTIzFccDKln3CsxrMp+pZtnVn6+NcF -npkfwwd4FDSfZvfmsSVEabjru3ncjsBO+dLZ54kCHAQQAQIABgUCTgS48gAKCRBn -Yr1rjex9erhQD/9TFwPUB6+UcxUw4HRcB6P5efpN81fzXE55iB3cGVnbNWXTVGgY -snO4iqGtTqkWj5pUFI2sLrzLsP/Csu9LvgsogfPt5foz5D1QkIN0y7YKLtdxDBl1 -8YKDoW+1YsBOqD9OtNkLrrF+Dh5XYEc5/7MSN351GTbJCmJEa1rtpWRo0BfvSgPn -zwnIEv+fGoJNlEDzmJU2KhR4uTtMCaHhr4/YGFRLwJKR+fffAKOoGHgMjfgPOmFQ -8ifoAy9ulZ8bKA6Ime8Mxi8icHyKstBUwjtXa/7/gbe8Qs3/YPWQeyrjMNLbybe8 -AoaMHIGygKBxrxEvRKycVBP9FxjEmhDryNLDj9Oy7GUOCz4peMwRaGB2P9icbTOc -2cm4RuwPoEz3urAqVM4sVppZUyljESpeAYaC4aFrssVwEhd5rSK6+c67klNrY6ya -p0H/1gCQ0Not89uusfuE13hbpraL+669qNmP91l6YdnME0pMC5Ai8xAOG7BMpgrw -2LG5W96NpKaIfZwVSgx56LvZgYF0DJ95kK/oEWzk/m0sfDiuVV7mJJN/srzYQcGT -L3QUad0j42lQ/0fjGxuuguDgCv+N1yf3mBcrR7yvvCZT7PaSFyfwzeCaqGVW8m9d -qnjyNC/3o/uwGg/6qNpFhxzEA/JucHV7WDn5PTE0cicaUYoWLMq01L9rAIkCHAQQ -AQIABgUCTjwC+wAKCRCKpPvWpxppFe6nEADFzuGgOxF8Y+5FLmdhghrWgI1NTQWy -f7zBUfpn+lcfKhnl5vo1hkVNErwTP5gI9axUrPif/90JpTRCFELI82cJAG2g2BTI -dMt0G7Z4nTOfSQN1wkJ1urgY2wpINTtoxnz/oKr91vyZ9G45ic/xHbQ7vlZQBh/5 -IC4Qgofy58rXTPUP9TezEkuCBXmO2ci7NBubPwU8ih1PZW0kCCHKOtDCKQiT38Lg -6Bm8Np8Eh83b0R/CM3kkxASVAjVt6lxHZSUGQN24rbGb5WNb9Fm8/617X8jWC1MI -L3i21sEsKSUGjGUcyRx+jA4lXKA1uVQlnbM/ZQrw45ECIS55qzctVrwizxQWLpnx -xH64E48NhsC59/lHIwbVgGmwG2o4LdWTb3GLEBwpSzNgi9Wqf15zGgbCf3Ny9n+i -tw7vdcUC28MpOv5Kz9JK2wRmCcO3ES2F+Wkil3elYCDadzQioP1RPF9QPRs+Uee3 -XjZcKgFRmPBD8n/2hk8FBrHcvLToIL69n6XfkcKqzp3+IqLxw+F4IR/XPB1QIIUA -wc+CIrFBaauapXEaxPOqayt+Shd/fIlfSubWOdwfkSNfJGlkQ2wzxCRwOr3TIe/i -d3/VgMphMPGM++wqgWaCv9DhuC7F/q4DkFl3H9+ncSbb23Fg67Bna/QkTLA/23cW -d2OK02Rpz683+IkCHAQQAQIABgUCTmaaWAAKCRDXw/ExqyqR9ZZJD/sE39DgyKAu -6heqRrrRGYR9YqwjzNzTsA6ex49SJSMV5XlgqqexsfQnrQXCLsatn0Al2WMItcor -jW3ZnsbWBwI3Ktnmo4ZbP6xle3OHil4ky5Rmisks2BR5jA3wJGKa0bTMrONmFZln -cdL+YRmyt8RFJy3UIMfDaNrQ4TbaGUM02K4yKs5E5g7fXZJ3rDVB4tO6i1DxKbJR -pxcwREt8t+v6ryEjhouh2d5wxqyEWnPGCYx0/yVXEO6tkCReh+4hLQs7fcOJfk8j -bfD3eEtFNwc/k8DFpG7L6oGieT13VqVmCUoesPc/cTdiDRTwWoAit/e5AnssDSpp -ogaqz7c55RjpjyAsNZz/aJufGANG9/3rx/IHRFUlXZ90YFouGh+X+eJKXuj7kh+5 -aEtyucNSqc/dwl9UV12wBEZguwICjfE1HSXbxuN+dKr9WDpnz/ApV0U4v/GqYRsd -fzAIyl010XzbUYXDrT4qzCP/CBkvubyjcVYZR1Vl8MyMpZmaFK/HzrOYa41aIVHe -mM/EYZDZ/+m66Jm0LuBq16+q0MEIdqZ44OYtetH/9HkBgegQ1EaIMOViuj91Jia9 -Xe2yqplUbzQFU39m3E38C4MFeSYioqEW4pPnAA8Qdbyhp+ZiDgyU8zgitWSsYz+4 -ubfdKq905jiNlkONvTnFiiGNtrFiXOkYHIkCHAQQAQIABgUCT3MqPwAKCRDJtMRn -bcSX2fvPD/0R0NIzHisnA5XOfNndqzQy5Wq5HpsVvrPffWCC7kCkVjHPb76KHkHl -9+iKTVhn9Fii77UBulaK+YWdiFu+M7B1sMDVryjAsQ8quFEosphB73QmdMsXNFRO -2ph+mBGJyXywXS10NMuCcaTKyoWhwdr4FxKjMJPYejXd85TL14FUp49KK+Hki2Xu -yWzxDtUZ357GhoB7odLkNxyZzOfLMVURQi/P5Nf0wAI2/szvfKd0wOyj4Zc/sGq2 -5JC5K/neAEiUwWr3ga88IDXki3ZYrpwWhP+8pF1xj7l8nL6yXbz+welc0kvSZIUY -DN9AM6JSQg8dvMLQ9MJzSEvXjVRsAkKxpJBiY1TQmspZCDBb/YRn7I9gZt76fJIt -HVqjK8f9PEF4OkZVBbthYDrakWoessbCFM27gR3dW8lpCK4aC4Aly+CbGVyS1lyS -WY3OYcf2CsA+WcWrAYMUMjiq8k4PsR4RKDD5V/g49hJsDhcW/tE5xUSZssUoW8VP -vnzBBTsOYDaDZB3Vu41wOb6BABFVrnFe1NxDtsHL4GUNhDC92ZtEGfdmvdCxTS7O -ycnNeyQB0/pnUEJuZvbolaGyVcD5Ct/enEtchp1yayLizWQdKXlocty4cruoKE66 -81nvpWOqEAt5ism9qjzzoxCbRcuMKqoLiNTDuyjbOwvSSdF2Av8I/4kCHAQQAQIA -BgUCT4MRywAKCRAH8GBBKdn0mVfBD/wMUqHIh5QrOx2tCpq73nyIR2o6L39TH08q -K4SgxGh2qDDuL72u9g4clm5P5iQ+QBvGAaIS/iiGtd8+7q17eRv8IvznPXHQRUL7 -JzAfSJ6mSdh/LmtDxzE5aiCbiF8Am623ceuygvr2/FJy45ohTx1yafY6BIseY0Z5 -IQpHC0swT0rQnKN15pixQd6gFxzhapHigV/ppX3Sb7ysK4uak3IHYmFwXEQ7JF/2 -0va8nNt1lxKwdzWis4GJu9X08A1KStm3EOafJhCSjbNPMzKP6xLM8AEOTneBdO69 -NJy8RrYIvA4MF7F2pvJ4sKMFo16fVFZvtVbu6Wyv3fDkVGGwuogH3ZYImLhiuYep -4i/0nMqi6s9FnpkM/j4n6iI0rW/TgIuYR9wSpDF6SsPd1Rb/j02rdgjJOCy5kR0E -ZiRKj+VF2OdQ8Sgwp4KThKCF0WpmaNyXG4XRxglhPLzP+LVBbqf1/824JB/q5AAw -J2qOEOvijJXjeKO5lwn6aJPPnGCCVUVRT60uM8529GfW/J4P/4oWDx3s+paOZGJo -4sJOLZVXSNQojGVK7kFzLljZEfieKYGYCf6M3PMhReD64F4GEGoHsaZAyUD+CEzz -x4d5vBs77L/MTeoQw6f2/5kFAHWEdkhrJc3OzfELaTL072pGpcn6SiewnewOHSls -Pi62x0Ptj4kCHAQQAQIABgUCUWhsUQAKCRC00loemZmWlxskD/wJjC4YrllZH/dZ -5g4Te7za+AEO/Ezv/WyDGTLI1oEKD7HrfHjVGFlBRcE8ukH4kCCpRxOLMC31Agz6 -dMJLVGjGjHYAkx9OBHu1F0qPS0BgMDw+glj28GCsp0TIyP9GIKHFwnXBQS9/7ZvF -Tj1B4D7wa4stELoSDmZzjHb8MplysL7+lGAhthasIXTbjmBU5ANUTkVCQiKbC9rY -wrFSn8QsM+UJ+30pWdQLLvM+EA6wm8EOqJKg9fDxr4a/YIscpUtvZIS7NITO/Ug6 -HCqwFDYi6UscDR+Are8Ri6EL4wLbdOebl1XOMjgm8c/gXdQwOG010J+NQn2f6p2B -y8kN6wI999DuXUGv1H2IDJBsEuisrPdDYzD8OgeBS7rKu81MQ568EjA3Ejv2qW7c -laAGNLiwJDCSjC2PDoK9Zf4QGmAcZQ36mLpkwgcEppsgFO4mwbPXdZsG6E4ss6D6 -bXeBjxcVv1YSoQ3z2WNMnhsFjIdkLHRSh86bMvOggzfKNbo5aIC6f/ipLYRd2OCi -1G/VhjBhRzU23lkeyoBPAS54OQ9Q5W4eSfbBvWP+U3thFjZYRO6Tv8nzqhAGH2sb -ANdtgQLPZRoMHTtUKx+tfmwQ59sWdvS/siClfkTkXE/TkSmp8jddPVCQ1GTmFZx6 -HECail5W4Z9zK8Eno1nw29clzAApFIkCHAQQAQIABgUCUXUWZwAKCRAMPZa2BG8H -CvNbEACL3mTaGCBr1Oy7IT+0UcvAEMibRIcT4V8EyKLhar2r10MqDWbseJvrkMFa -gYxlSbkk87Nk59tHyrTiq85GBiksaCFaZO7hU9nTe9CihGySVn8wpSpsmlw42/yE -FN9Q4RVMrvMFIwiq3VJRcwEe859o19/aRUGrRxnLuFf3ebQdDZpQOi3XsI/pr/yp -k7amItlySC8mI52XbO2O/AWTlEffuJj0TCt7FuKrVQwl2IjmEBVMGtB06Swzf51h -DE87aF1jY2iC7JxETLcpZKemY3nuC1uAhfEPWyRZTQhD5QXi7Nez12YUJ3hnHfoZ -2deR1VM31kAaGJ+DEaxPaU7e5vib8NnptFnnrsRGOLwLy1lADKIteF1K3yYJnMWB -iv/DLw+a0UiwAJFH6OVpofNVUN5n7lf0xkr8d1T089a+UDZsRGDVbgEuX0wv0Sdo -RUWNeHMRq1/ZIezp9yF828iFN/sWD7YbjBWXvVXR9a04MuPhDTExpHLu9pl9wKkL -R6kDUxjdvyxLuHlUbdX0oD8FPY5c920a1pdPcRw3ZQrsmrpg4wNrykb0qln+r5zd -2FqwUG0ka15G3Fj3lWcgNrLYtU2/f1afU+caohqrc8OC82iLxoL/BikOpMD5bUC4 -YXKX/qN0RwPnXhHpJ52w2PahOGpQmjlvun2H7sOK6Vhz3bjsAokCHAQQAQIABgUC -UZ+zHQAKCRDrOkYTsNBlnLeZD/9pcg5T8fJv/V0n6HRHEzJxooKnETxCQq1PONE7 -AD3kwmUTeX4XItPbIGGVQO5MyVdjMNiXmBCHtsrNgJXVKVW1EBx1L83v5zYzdnjS -DWddOZGutfPgxyA7wN/0BA6meH7nzlArc25LoUolE5ifqZRSgcFmtqbfa1ubqrcn -jeOgQtBEFugM3g806hCi7r8ZbKTOxrml8HjhnLcmCPG2PBlwATEwKHFfn0jswmRw -275nXHFIsiCRljPoyBDAJ8NqHkalZCci9xigK5cXOTgKslEnV/nqztV/ufkwkqS0 -iTKRwGJ2mGA7cFOESgigZmAbPnUNCGya1D17wOZeTBdjp/Ss1lYYwV6pgQTYNAen -oleKbFU4ly2qn42duDm79PB87je+uUXxEhjM7HWZeNriTj/BLOCE2o+xv1Xo8ulN -TeSS42Ez0Mk536bHV30IrPNf3PNSeHX1WjL6L0vL93srgIG+Meepm6BoLXTtVMYL -kqq9Cs2PbZ7Da3qeoAhxsLO49uIoTBJIGXtLD/MVrTGBZ6KSkeXPj6Xy6+tRFuaS -P7Lj+BR8nl8oahRjXCQsvzKq7UEn3bjIAp4CSd/X/XWRDL2zaWtmflVLVl1KwNZJ -zH7156m/lz8YcCNhZDErfadIxDEddw1DwUxZ93Un6qnEQGh4u1TueaQUbRwg9XwF -si7vX4kCHAQQAQIABgUCUgIiQwAKCRC5byMArRHL7vgzEACx9DKUK2guhiAwk9AT -XRM6Rp4s7JONowQcYIVWUAvtlZQOwC5CINkMtC8OCniutYBRlhl3hSD481UhOsSa -HOGdXqQ/Fbo6Lm0kpiakYKV6mmTf1c7fgqxwO8gDBaSIyj3NQ9DOpHeRWsYe1Vkg -qjNjiawu058b7igfmTxoqdXKKJDypzuBFtSLqPYq/yOCcpEdH8rmVyK5+nUzS646 -eXtyf/fKpbmNMcNZ0RC47qkRGRBQEzl43WrjmDPWIt5+XO4rt1vuCOLVI31t8wYp -I3GKRYuuuXY3aR3jTxuyCTWLcbk5tavSK+HxEuu7c6Ta0ALJ4ZfGk8yntX2S2gT5 -X2xKLz1Q52S3seEP+bY11ezDk5fv91vSnSSIhZtiaxWc4fjgPcXiF0dcSPkW8a+9 -Z4JJGEemwn8liB0rvyZvusBT/1QySDkcfETYTuwIR+eGdaKuho2U6FZc98i442YH -7euXodJPHE+6VwAs7Uq/Ks3+jrUy9obLPad1r36xtipDDyszA32tJqKnZX4fsIVc -T8n+PQ2a4BZ+VBiwaRXvYKCQZ9dNVcitd8EzfzF5m53FfpvDvD+xXyDmheQpZEdO -tCZpS7e0dWGIRFtifqXVLmhP99Ay7QOD5P2Kcu9I2SphRs6DJUsKRCAeY+gkd9BP -AuqoKQHPAuMTnJNZHeAeJ6JKHYkCHAQQAQIABgUCUgxugwAKCRC4Q+b9jTf96UI3 -D/4wOO+zyKMqi+lfmN6RzqBR8/JSb3SzqmB7Mij4ZtHrbqWNUB5AzSSgK/i7Rlg4 -uzi7/WssmdQBJVQtl80MeOsok3HSC5krO2fnJ5Ldt24gni674L0eOowC4LrFYzkG -U89tVZqo5DuzCsb1tW6OFEGjboEceyCgNNRlV6rWw7Z9YUrfMPtcFHRh20RIVKGm -JxMsCJtBmD4oxHIV2fyhPs96HE7YdJdilZLEbbw2xY64LhoueOEf7MxNFnJ8g0+h -4zxVPfplP2woycSy3V70vaSIHrHqaS0jWzevrC88WLFAfjosJQkwEQtoCjd+LXF0 -9oqxfpYhQKfazXF0ORE0Gqdxl2hN6BaB0/G/4+KlhssJ6zCCC/aBbOqJtNYNKbIV -dSXwF2Xqrq5mGda7Fh+Pz6DNGzadm3787PFG0FaBPDH3mT5O0M4WNN4PoTFSLt2Y -9fy+wR7kNdCllUvzO/TGGiV5MOP82KogGRBwTKv1Xh/L7/uoT7phoaN7rSQ/aYWz -uWvkJwxHtKbYuPZUr357uqtMgTxlVBQqBePO2UfvatUlednPQP0tn4Didk1uUcdf -RYdVLtsH191mS6yCwwOVUhnVKwkb7LlOx2PhGw3EdRamI/OqxpxRWfvTTkigkpo/ -94svEepjFRmajERf63k4v5RSdKw3oKOq/54mo9KyhFblJYkCHAQQAQIABgUCUktB -ggAKCRC8M5xKtROFD4piD/4gV5MoFV4ozihQFFochDt3496PPxcd+tRZKP3tJNEJ -hbUTaQp0Hw8OWyFkjiVRl4DeCczwO2jFeJyxhdwju0NRGcMzBnA0h1rPjqFby+G1 -Z2UsN0i7ArurK+1D4QkgHG9MPVI1z5mgopCMwzKiRteO1sBoFn2NaVu+p3eYQ2s3 -zFzx94bCPuTkUNw0Ouf07S0LK/FETLJBomymq4D0sCyLEJI0vmn6HUwI3VehChVc -Whza7vjuL1lhzitrqd8pM+FOSXzi/bkjr1D4Kd6Y3wS8aaLyo0kg0701i9u8OZt4 -KWuAgGAXXcFhcwRNh80UvTSN1eOaNRoXLOREH+Vq1FGbNh9NDnmqAAFp7f6sPPYG -OsDWHKwBM0FN8EDHZVKLdKRS+iBXD2j23OgjVUGfuwqM92Jg/HKieHrHD3OT6Oo5 -vO3NZGhaN+5QyfPfoa01iUGd8i9NEy2nMynnEkZ3XqdrsVitM5/ggxUgKtCZ6afT -Am2dAs9OZlF24bAF1DBxBr2HCb3Z0zP8rOVgj8ESRZZ1QAKrSeGizM6QLQxJfEgV -hqADviuu5DbVfhS00KBOW7VjoVFKQI2tUwGFMk99B6sz7d+fsBeZL6WnKgcHz/jx -4glgaWLl4slTAvvv+dc3jVZreIVmL7QBR2CCYeL/pa2fBa2WR21gFVnlfTg/XQaG -VIkCHAQQAQIABgUCUtkmeQAKCRAktkLfWX7QlT6MEACcjaiJl5kZP79tmMzmWHoQ -sJJw5KQLGH6jnO/at2n6XcbeBbEIT5DPPP6o0X4I79F0FVrebBRMkZCW90YCPmKP -n6niubL9dR+XNMRMEyVLH8QLN+iApA3r1znyLrY4Q8dd3qqAYXyWY/aaI1iu+r5L -7FCcfnb7xqypnd3ocK2PGlEwECuusEjDrv3m7d2jM8L68AmlDZKvH6Br9fw5zz0K -+fHeVK6brRQJwATlDB210cUFi9dzUBwUMe1rYrBK7NCMHYqxdkdNySMb+WhYMK+P -LYgM499zfIsqzepmpTXKSbEsIheQAIZEQYUGUlDyY1m48+RNWPbpLjgvsdg3WQds -olzcVaUlbow3NXQkevRj5ODtOfG8Zd0JmWZvLj91TKUV8UbxEn1/8uvIbJw8wu26 -SH4TWqtqSI71Dw0cuWxgrtZNUxTIlDGN69DPncyGg7XDpsAkWUcnQXNl5KUHV8Fe -MOQYpXickvpWzWPGYQnbP4tmmpylykUjCmyFGnRWdg9JvFElCa3Tn3t0seGRfSDv -dOX+AKc5B3LcMffHV1G1lxE+wUPGPI0XfCwHaNJ4hcyLFzonhqayVDOQHLL6DHdr -iCwmMk7XPfJN8VEnso5lC5FQAiVMx9LB4jCyngn64N6/IaedRFi++apOu2GSZjMW -GS2q0i7jDetVLH8nSgYKIYkCHAQQAQIABgUCUwYHBwAKCRAgZwAbG2eKYy7YEACe -qeWWVspg85mkEtHixrGaPHYVnLwnyl7mBR7NuDS986kB7OkEsKEjk9QJB1+8K6Iw -tySHYXo31p/xa3MwfPffq2mm1eQh3iHawRzD8Rtb+y4u6b4l8kylGzbe4mJBciv6 -DU0QYvIJwZkrISRxBxuwkbyTVlO/AXWb+ijTeT8VwCawmGr8T2CJnAj+1sRglTGO -xij415YsUmPywzi2NFvNVztkMq/nxaWjlrKK86INuxMb93ORU8y6MQ8vnc5tMtmJ -qlShujs1mOOCVzc7gc+1kVd/5XVEvIornFDebc6fhO7rpXntKMlWa8OyPp/6H0QY -UXqxcNmvwb3+9VBXq+/MTVEce0VDVtmQfLuDvDIb4AM9J5vLJt6Ke9LX4nYBN5S0 -RVSGkOZw+IxBRju60vnurqhAOmNhisuQEpm7ho1WUcJ3mC6T62wzWeQMVW+hw+pL -t9Hw27q6o9v0SsRziZe58+hnk8aHk8N2NUqmOVFshrwUz3uX7OOQIDD6Q3FX4ioG -yFNhzdgEVGVd0Fl4njb4C1ZjJ8u+qUJEtEvtQOvDSa1/NFS+YuyYjIyXZ9RMi04I -3m+Xl1StuE5d+uKtQftD2L8M7e3jNe8gCrgJXKDtnEsaQ+5n0aCQ5qYPQXrpq2En -zPvFuDf+hflOUWoD8nhhOvYpaaEXS+sSuAGIEv71aIkCHAQQAQIABgUCU2qx3QAK -CRBjhPdUnXAdi4pID/9ZPwIFhGqqzh4MFvvol+TXP7a1kl3XZZ7CThOE3/PQV7Am -F8iM53xUoGReOhaecytWxYpHn1Ry3kz/de2pCQltYAKnRIuE1l/9141/BbFDcuSm -mYkNChziV+LHhsGQ4MtHkwPOct5M5Z1A6eCSeB0NEDlW0eTrqKJ7aozbtDKh5cOO -SzPtJXq/xYzhqnjyr1nPRCrHE+Wz1ZBHlM8lBSvmOleOXx0Cn5470Y65dxI9Wz8K -X/eK2qx98bCI20BrBDfvZgb3m2kl98oCzFONXOWSj6RgCgtZ8Hwsomv8gucqDSxU -vRu4ZbYXPYfZHv9JQnccqVLYHDjdGjWNX0+1KE/1gxyRL2Hpl1PjWIG1WpglSF3w -RMXMQ3RiwmXm44FXNUt0xJ8OdJ68iFNnECVy0qVkWZlpj141GQ7V7FSzlBf/OLU/ -7c9XMB2BlMXrsutFa8mPSIKcLHtsP15W/Fr6yCws+YOtb8dnzMwvAc13GkOFNyFt -UwfkH5xVk2OXPFqznyRCOogGnARLRZ5trM9SbF2FXnZDnoDQLRT1UojH7K4nAx2X -4KlzX9yDAOWzg4oFwretq2TfnJ7uLngmIJeGtRwRag8fcP1551Mul5FKmD/+MozS -UG9UvuePwJmVZrKCY5fcks43/EnlZ7Xm9AhC8RKIxmSh49km12yhFakiSH8Y74kC -HAQQAQIABgUCU4BKYQAKCRDxLZhXQ+4mINV9D/47lUSPCeWOaEhaXCh25xTxl0QL -/NyZaoyugfWXgTZNYWAmX36Yz8zgz0LS73tnI/Xf2BMptb1piQqaHYiT6LSPACDN -BMsVLBZRkchsBvcd7EL7KoVpWR+7frsSz68ASiRWcfD5+BcxZv3V51SCmtuz0kuV -3LExo2oNYSBZun/j8u4qsznRQaJlcX5XD5pcuBV+RK+hNaelNBeM2Ltmos5sudU7 -XkpP6L/3OHgLM2tFp+MdEBzt0s52i5goqcyIfF6h65KTo2qlPMwgksAYQ45819zJ -B+XTBpk4/tV5Db2mTO4HuD0hgSLum0ueWQ8Nc3uWCCSPtmiNGtTAs15nn7ADbo46 -xibt4AHbmZ9szcoJhVAnQ7xTV301X7HfMKjoZZT0+Bqx1ZF/HahF8LYhSg6sIgk/ -S6A2EUjY8MFnGcAEvga8RDE0bsq3oR9W4+iiaq3dczF8Y81zWdMV0AHXYp3nMFvc -DzUkXvUXAlw79yIwxL42jU9AMF6+CEw07x+XTzWmyVVgTrJIR05Qzu2xP6raPKtR -I4AbZCXFJ/BbpTWQFtLpcTR8Bzx0vees92PImbYmYfPtGmH7fzpj8SOsWNoUndXx -I3A3PDNN1pkJsAHM5jEr7ib4gSNTaUbMWTL41WXPifVv9K3oCuTQwuMzhgfD/6b9 -asU0ggh1rqq8bq9efIkCHAQQAQIABgUCU8FM5QAKCRB4VAVOzv4Z5PCgD/9UbXSq -zuW77x0eFqZK/WyUXhXoFuNEkel4vsixRHwzwDWGxgZNzoZCuxicw1QxHMFNQdyG -t8ZdX7bxrk9RQmEiCG+ChQUUPukzlNg/cuSq3AIJqDd5kcmFYbGGZBJgj6TE9yBK -6NEl9K3mBJ08hPLi0EpqVT9brWB0FRsgjHj2McLquuaKxUjcBcUyGJyPZtLPjjwH -YrIDNVjK+HuaeA74R//pgv/jaEdC3f48jASvtLpAvcAyQBW+odYUfUw6LFdKDvvE -2cLQnyk/o8+L788D9SrNrfQ0y1eQh16AioPFRdr7NshDRSc+LZmWFn+cE5Xgl9Lh -xixZCQzYlN8H8D7LWBgJbUFBrV0VJNnZcK3a6Th6cKaLXesa374F0CwZZtza9PRr -emHN0G2jkYxxvBOyxnJQ9qID97iDh3Oi3ON0GlCBltMXmF9d0MU4peLL1QYGVhAE -P9rGeKnkoxmY0ME3X8HuO2fGXuZxjsN8ZBtI88h88JjOOntMvqE3QRFn1tNB94kR -tvk5Ptc+b/VDn/KXq2vCMcAc3VYJcAR1++GH3CpFylQK8VOpv/v19cbci+LYdG0/ -Jp6n6Lx4+blvIsXti1h2IRzWi9M9XGs7eYgQhIlonDINt5+iy3H54mzK8K6Uq9jE -g7Yy2zGMEUPCTA7yrZJLAMsGvag2JqUKWrHH4YkCHAQQAQgABgUCTERleAAKCRAe -i/NJIykSZXTTD/sEg9cOgG/81NciZV9UuqoURhMC6ZIAzHWBC81dd8BAOU9QD021 -HmafiEyh9lMmUYs2WgWNAndBm0lnkIhQvJ0v6b4GRKQZ8rdY/de9c+zHxJu4Y9y6 -8VlXyIskyOnD48rV3rLZNZutDmw9T9/JlgFil+gfH2BSBrNKoN8CXqsREDMtvN88 -7AdbovBFoMgNKXvGqdSpx0MaFLWfX4e7MnP2+Plj9o5aIEO3Gde9J4zkrpqAd0JF -t4DhYdqLZyjkM0q64/QeEdhahWgckKKoEmzAIiKQ0kSeIs/tJ7FOyheTOd1AHe3b -sHWLeR/vQFeNL+Py69pb4hcA+ztGf+FGlUWHsTmU2j+ryy965MrokBlBny1H5o2W -1URVKpVDHFnOGDkVoPAB/Ia00avyZFs5L+vb0Db0iS2pAl524IQjkNYy4Vd3J9wB -Z19nBbS5NauV1sK8Y1b1Uv9qtrqznUFoBUWtpmrSKL58G/kFMqqWiCGe7osQ2/A9 -jVToFS8RicVE0BABsTcPUsodwrVEpKtQC5eI+8SVDu42ifX8lE21eBIOBMD/ROQK -s0cakzzLwrLClSUlHla6lJWmeYTIE1yL/QD2JbJxepy34+NZ89LtjhxoRmrKvRhN -9mAGVvuSpUxWJHYO1vGlEdoGqVoql1IHAm3OVtBaUgXylf/SqJMjNkWwDIkCHAQQ -AQgABgUCULsVhAAKCRDCGFJYGfeEUb5IEACo+WouEVY+W0am3JxisdIZnzdCOOt/ -jisucGkx233+7dxf8/EcI33WYTLmLT4TQfh4UMMF4yxAIo5gwHQEQolJuMItegEv -rcW/w7iMQLROk3dqpme47IaF15p74/epNk36uAvokKzfKsMbobajFOf1raCRqf/Y -UVja5dMuBOBOdUMNANO5IuPqc0A9yb1I3LIkkX3THi/rTNUdKubFTJlmihHe+WZs -tLHVhlgLdh2Eckkir3Jw35M/owM1eblHYa7OTwpkrZULsmTCCyt+lz4Vn2f/WjlP -Vhwrpi88SoydVA6EsuCA8VNSvpPvWChlp7RJIrf18BhETrc808GRcLNnkgKM9Jw5 -z7GtXn8nXmojzijnN49QM5yW6ZaXzClCsn4wZbGbBcIOw53WgwpaPNUHj+Amekzn -07ghxxwprnTOkrxhybgPZdcmH/hdoY20vQYPeEaxdGOdU8wSbkqnH9KUvO1YBdzu -1zO8WLS+yByDJW/2PicFwqfcXlfA3dsTkXDNRBoURFBtO1GtEXIoNRvUpqPswrf6 -a2V6GMXo6WCQyxgEdGScEZWblXQVKd1RINu5YAPS/JjqTUWKTyicO0VqsMqD/ce3 -Bp2+AXR8fzKivH69QsjalcwsuT250vNd0QG4bcnbnbnOCCclzYmEhNsDNOXfNYMv -yaGnFIbuLY1BAIkCHAQQAQgABgUCUf0RJAAKCRBNP6LlmWxnZ0T8EAC4wLUYb66j -BZCYqfh4lJSO4J7Rgw0eTkCnusseM7IbU42iLdmd80zn8HiNAIrcsQjsL/lLDHHj -tCkywv/40SmCfmhkbXJn8EPx9+jRiZquHBPS1RY6k8hjn4lYtqdRUFwRAmS86RgF -c8XlvnLdMovEapzUyVJjTDDUzVurZ8gGqharWPOIEg1k6wwBexWSArcdegYtpnjk -+DgvP2jl2bXYljq2332h81OrBxoYXAgW+fJljoTFbQDaHzU8KfJetvQRjdlsIInY -uw7StXdNpxKm0Ha3twzACpi5psNCeX/a7p301yjNAELK0AExUBsoNGx/HX6SaX7y -sfg0AsqV3UmO6ZDT1ah1o+02HDXXtUnm9zFKjJbKUDX5F+7t9AGQzrdhbiEBUewh -HAc1I23eblpMcqn5TmknP6CFyqxyQ33mfVieWWkeqZg9JOFeOk+VXeL0mAbjf5H+ -lkeOPUdOIdOK9U8Xqtr1m5oVN9rxij5SbOs6G8yP4/XZ4fF33eNV5BZe7FRiFZFU -VZ747xNffJYaYEWEXLtVsggINrJlCdohJg40H2gJhXDZLTaVhBCfb463iRAP5nw4 -Z/ljlCJfa80CRH1WwBU/6HpM6WbPvuh1ofjnDljDZ7nqqa0A0miLWpZzMERrQxi1 -DiJaWXlaxdDxXxjkTHQ9dsaJKJKyyotA7okCHAQQAQgABgUCUzpGzQAKCRAlJJYo -7TvNxsPcEACiSn8jkJdUkWFzTo+WVFqe/+zdtsA9wJabpYS8P2tBYOHYufgE6qtM -rWiz977/rJBE1j0Wt3eHLtwHq1oUf7qwLBgBuS55f/Z8fmYgueWTASYBjerqmHjv -WAhUKjLtPXsxCgK/FsxrMH8po3wAhqXjo+vtSQXR+geEjO6miOOiF7+N1dmp1GDI -1IJYdn0QHOBi4fuzr8Xl19rVd6KVIObWl22n+8xDRLP6T8/ltq5QkbkwJTtg+MRC -aGM76YvZTOsub6CJ53OheZizJUn3jFeaaIf2VOGma9UFTZjHUmEkKdKqgA6yFfyt -SKQ4b3g1O0/MdEZ2zXAPatJTRLGaodHbkABqV0fdL6O4jDp1IE/bYZSH/+1zzSOc -D/Bt+Vpz438WG8TxhIzJn/St7UnABUKf9Fi2XitRC1uxs2blT9gLUb67QrMAFdw7 -pO8SXIwdeW+goCjEhJbCFk2fY9HcObKerLXFX7owUs2WFUFmjAIdlQ0Q7JWmlQjY -9Ej7j+dR+ogi2Lu4H1t7qV142TQ6seSDSMo+0soMrJuQwUiwH8DtJxkKd7hS9Gu4 -HmZCCJxK2wgRwfzGylY0+Q/ppytJpsDl+8MaIp2YziQDWSPhT2uAuRq3dDei28zr -ry9L4LcxHAzs/+nSwhPwSN54dXT9cLA9PB+FSnWF/KZlV/yGS24mq4kCHAQQAQgA -BgUCU7kiFwAKCRCcMVA8bYZjllcJD/0QFgSmIfV/zRZvbBxaygwYxMint1JD/FII -V+DrPdh39cUywg6wB0nPveBvSTe6+eVEVMi4TNcQvh0GYzU70XHhBucZSg18/PgG -oDpTVZZ7Ryu6Y+cumYqpcfWJ+Kg++x5nfMeIlGTHFR1QUU0TpNU07ULV5CYXCUTA -bFYPMozgH4IvOBqRJmwCXDMxz7WHPOE2X64GwNewo3LJrkRk3uIIsMvA4x8GDoBU -+EstW4Sh6qyFVuLdBBjI3s4ZRLGH8DwRuLf5l7U47AT9uCeG8RRhWVQKnEXZY19/ -wLkgVUF5nEiNtZrYUU03f0I69n29TF4E75RPOvWjkm+f2L91gi3bIBjN2txVmVeb -ikCSVYWkAsor7lFGcGe7CfIrHrV11/KgfdkX+Hh9T9dvttw3doDE4znayXEmy6IC -exnzXX4R3fXTmMfq97t7ySEcwRdrj6aJJaUxOZUx6H3bfCHqQBzo3+St7ni4X/rA -fDo961dPm/Wj7OIz9Cmh6HyfexGEhTCqtzk+C2Jld65yKfSXUXEhW1WN2LZZhFCh -0QxTvrZ6KXHLf6TlQ4TlUrfkg9W2AlOEx0S+xj5/Ia9QMBtLSzTzONbUxdvl1OwK -5jL+jRsRydYLewmNMyocZZeMH+sLPEDlIIjyRFdYtlpA6f1aGO7MqJ2HYwSUP2OA -8BQhIDM+i4kCHAQQAQoABgUCS6e8LgAKCRDM0u2U0hc56b6CEAChuwv6ovVLkAzm -l4opVTXcaWLJobMw3YGkFRFwck7gvTTJtTiXFLtUNvw+CM883KBZzWUG6v8yAmKp -FWWb7aJ9O8B5rGPDLfgh+o67Nnso/rd4zcx//d+3p+biRXXYkkG7+od7h4nyK9uS -s0BJwepSTiZiCb476aDxF5zZueKRnOQhIZTlk9oeuirMWO7U9M1+PsHYwesJ7PUu -4g5j1/s/SSPg6Vo5th0lTmUDj5GHWrfYSKEC+S0L3cFHiFm3k9ypaFrw5kjSusv8 -0Q9lfg8MPHr1ctZROhvXd8J42oc/NEsQRHFGZ1SZFp0dcgFR4o1ch92MzKO8Bmp5 -moC2Ox7gXsmRl1hAMEFwkbM3xJnHhpZXTPyLlICnb0tZBaoszMkxjDOAOh0gU4xh -hFkk0Vg/rHwuj5gBywj5NBbS2HWysQ8PvlesPgOhepcEj05bJS3qncOI0vNPbtnf -QQuP6x7/yyjVhNUOXTZ9fxKNLv1OzTNPHtujAbekWfabcilqqDb+yrqyol0o3ld1 -Z8h8w9TSykMRb9J9zJTCntXCBa8N7deIu770VdKGXfThqXwk1cSIYZJEE0QMr0is -CtHb9KrsNQBItL94w8Rr6xV0IoFK4oekvGC1BIWhuWJ3xiOF34lWicRmCHZFsA30 -GXPhO+8N8NiXSeXPsYzMKNXO08Z+6YkCHAQQAQoABgUCUhL5sAAKCRAxjeRVivx5 -g4RMEACP3C26J51PhDbC6I8dnusxXAh4QbfpZXtv64xfMo0FDsyL09Hf69wnAhyx -KZoWLOytvaRCi6nBYgFmw+xaozu/oa8EqXxhdlDDfjc9ZBF3DzKGPTpt4cK8Rtqp -l6DITYViyeBH+63k1OpSmA3eFoLDzsCthP9zRPgfEUyMEv3vYyUmOTzQYKNaBHjE -jzAPgChat2duLYubNfpZjH+9M231Qd3XdHyE1Cb3e9v1iFZzCT22uedjMLmYDFzX -eEzd6HJXOvcp4Cvx6V1LV/nLevraerMto/QA19s6KbLVmYZqKnTpOrDJnP2fBSc7 -j7UrMgxVr67b2oD21InE8e7oQyksxFyJ46Sen+BujAyQFXuQsNTR0MNgRMnhH5I/ -U/x2VcnZTUaiZol2CcMKQT81zsxaXm3d7FZ9Bi1FXWNPt/lUTGBTyjAcp9WaHXPd -3WWpWVEoLlAYZ/gsYwGeIv0uLIA6g9oiBTw7lMF0aYq1K7ZOqy5QZOG4Y5q+Nn8H -oCzy8ZJ0DlVD4w9xi8I71COwwRwYFf4ILzEQuhzhmQTXBHpGZsBktzK6yNG+J+8M -XYCEtpdXRz/Qd1wvnDBDwiF1ut8LhP44eQCAuSLZ6sHoe3KZvokK9vspvQD3X6Bm -gDnDBEJgCX4pTLNfbbg7sNJJH28fnd9AGQAhywwl9vasFGqWH4kCHAQQAQoABgUC -U4C3qwAKCRC3YYg7RCi9wE2IEACogite/W501eK/GMU0kEGLXK9pPcjs2MAVUTlG -x7h2K0DiSj6huw2FkLVEOGsS/kTx13qCdi7ygQK4ZqKtGa4r/ky4RwGX/m2Mv+uJ -KkpWTA9EMlIozeWnx5fgsNjDtI3wi7UhhYpnFTn5yf8Yd/qWLOL+nNZYsgpDh8O4 -5wzdfDXAd11Kakaq2e54qZazPHHSZ3bc7nvEo7lxZDH0yta/lLNhSN0blDNYEJHz -rmyLooVWZD1IjkSrD1zUm0HzAigIO+Ymhu0Am/Et9aLvV+WnJJumukFnBc2ibCKN -8r4vcKogwoT9uQQWu4sveZEuyC7Cx6E11/Q9S0HF9jG5AyoxN8h/fmK8RwEgPrp2 -sno9ve6yQ/WQYPMqOCXgDKswbyjd1DR2Q/bOKErZnZwDwbqf5XOZhlEO+Zq7y2Ak -SINmARDqqgM/I5PEpYBLbEEm5WrwMpdp1MlJ6+l6ESQka0gatiXwdxpx2mHM1fUP -ZUR9g20TzQqs22r/aJfcO2sYn/i1cG1uPpMBNjq9ESMUmYmE+nH4l/S/8BQg5env -Wstz0YKEkigOzNQX0GD5rIsurZbNDeOJpERW0Z+eaznFGSzv1DOSbyya7SaAamAm -6v1iRl63ZEF0jO8CHc0AZGMSJxoY3tfJlI1bgzFpeokAqaLha6ockKPaSKAFBMQe -WbLFpYkCHAQQAQoABgUCU4EgiQAKCRBdcNLrytLJ5gaeD/sGd6pVGm6kTjU+Nrqu -yiXGdB+D0v8ZcgCyNX+/p5VSCa3tWzBrH810xvND/14Pf8iXcjVMIO70lkcLdyR+ -13Qu6rFqqHoHp4VrwGrU9A0i2EGgJMN57dhMhDvEO55IOT7XdXSwsSOGnhs2hz+s -uEivygdPiJj0zVWwS/QPse0Eq61F6eTcCe2hUkB+MqeDIZcX3T5rV8E59Z1h7MQp -qSG92muVvj4Mm+SQbuWy0EWIMA+zXhKUSr018ktoyOEnyLwGyaLRc759rEUUtUGE -uH4KA/zPcF/9ow1E/aV0IRJtVk2bElOmyXLRMCYwWvIo8+pl20qC6UotvgzUdsaY -k1Oc8Qr3y+f3f5e6jKV4YyqwwhmS8rm2JSKtmbpszSie9VAyxUytCXUTaX0BzyX9 -ARyokWGXqC/9CIKsU8+4dL2NAm2VYj8tQxMy/WRiH6i94kniG/GzLbTnX+36rzzI -nd3D1P7Ot0nfybL+TBnkb3nL80OLrh4ssPz3SLYvf4WwOteQnYazrIBO7XO1GOFY -TfKHpPqPOS7qz+jXUuumCUncWz590LCYgdiAKZRaYyhPOG8Bo6Q6c88NmPPhyx13 -3zleYRfqp7FMNV5uU9wl1rAzyEb1e1TZyxA5KAl6qtf+rkmgDWzzZBwEkrGiJemr -0Qe5M4iJeAqOCd9ov+IxWLLz04kCHAQQAQoABgUCU6SwPgAKCRB0N3+fakeRn4qP -D/9KCKepN49U7mvo8jkOWAx75jvcQBBkk/wJOlwdflvX2C1VEOkD9BldhIajZLqA -DJk5hELGJ9BWwk7CTXnujfxor6KstHHXVvM57vM5I2eT6bw4/qWXW2SyW2lYo9ia -4qGhQsOdicLGYMUjLU48Ffk0SKW8aH8rMDeytlsSlFO9pMrvMCiI8gNR20Q8wpCr -SSM0gbsEyNejdGtUEENBdhlxA2p/jQ5aOVOB0bsfCFfJlVhFaXkKyKg2pCu5dykC -pKoxI9k10bwRKyyr9XQs1+YY4AGdldvPASn4y7Zv7WYbaPuZD3IwosnfzZUQbuQN -ol6AN25dmX4M8xSThU0C8CAWSJlaSWibTbEop1AB7IfgYvfylSCUQ8NRmyTbT6Hh -wOfJGRQcK7759LaayQqrQkQX00z3guBYZdy9qaCKsdGiusuQoe8Ko+35oidyn8wu -rtXnYApqJ77mx5BFmFKoDB0o0xyr9LsIo0Y9oZLlw36wixSe5OcwU82XK5Jea2Vd -Y6XGv4nkCrJctN+RK6wRe5Z2VrJd+Yd2zTcDTz2esZ3r+fNBR7R/hcErsO1PyCfD -eMS54hsY+QGKL9R/3M7As8r9LBVruVLC+NLZSFGuEHEhzSQi5/mPLbPZlcbRjFoq -2wB5tPeJLL4YQM32UMOWSntDlL4FO0gjnXvu9w1qG9lHb4kCHAQSAQIABgUCTTId -AAAKCRCZkx4l2R4BLAPeD/44ekxSiSjIKgb0w/zW0EWYT3gwVEbUwiVBufedKCR4 -7n5D3awkwnrIYvjSj5zKxXAxmQ5CbF6VT0D4Ey3Xjw2lOZOnIOGueqarLXZYg1Em -L4NSfQYwbkEx1ZwW/DF2z6V3e042VtGwLz6SVLjlfO2n3kQmst/UH2COePd6nV6Y -zXK1HSkRdlWCJQ+0eVmJR3s4fja92wJH1eu0XuQnGKIpYU1k4Eu8X27G1MiPCyFR -xqcKQsjlCtdb4PdrOrQanAryVX1avUlDwPDFCbHNB9fjyAGbl+KXHhM2A+8az5/u -BVzpLWHpxtTuV/GM7S+oxtFAX2qHa8YuRNKQB9xbIQgu1I4MuIazTxs/TwFxRIqu -4Ntgyw67xegb0tKsWI0TubPe3iIZ8oTQusrGi4OJyrjN0YDXkPCDDl/dNya8prJt -jeZGnuTNclfqd/oHgegOdWnxuuy1w+AYsFywiy+5E8WU9q2GfdeNk986Hrsiey/A -2SQZF2th0IFDbv+R+LhywcyCJ58+BoLer5cVxXVSDdticF5gvZOplSAlsSw1p7dx -pzWHc1J/Ru+zJScqx/dTFJr33gmQPPlHEnUcGowIYLQkybTX504Sm0nTvPdkAlqU -V1KlN/CG40iSV0VeD4Hc41YGyhgLZ4SEfigKvc3dWgn7+KkKp6e1nfmGzGwsoHa9 -aYkCHAQSAQIABgUCUfZx/AAKCRCdtbsn9Y+/tLK8D/9o7MhLTcAY6WrtfewxWZYY -jkl3k/l/YO1KWlCoN9MIgad6exoz4nS5lYI9CO0lZAe70WM3XOy3j7MqKo2jqU2v -5MOkVj8wov5M9zs0WccU00xYBd0b0cf5uEEPyKQMdif1LiUzoNi/3ydNxa7xEiIj -00uG5v5rb/9eTOUTlzXugUjmavar4ZY4Q59biEKIbw82i0Qv+PDdiEibtIR77qr3 -VXeNQw9kTPxlujiCJG//weDNOysGxcRhDhheo1Fj6LmNHXZxHzc3PiPeyvSzPwDF -9bC6y9tIvhsqwGfNwb3YYeNFXak3togZJRa0Z67CK67WweKgPPDg15iLAZnqo4Uz -kF+0+LDKQdjpvkf4rZITNbTKH1j56OEM3awNDwtsqHIkPhnQtJqEK2Q9GV2zJGFp -CohNwvQxtjOdf9CAQkg9lUkPLTX4zYJZ5ffFw17nwbwHns/vLYSnmig5AfT8q36/ -F07qf2nTUjy/W5jHG6LcBy6tEFav/lOmXlTgxrngj+cQ/2vgbzYz2p1rA3NjdTBN -lW/6sWwzAYseOUHE4D9VviN/hw3lSFTJ6R4TgKT/7xs8oZtyZoX5kwxX73mG4vDz -8QLV8f2/ZB36a+Ut3gks3DqPilnH3BeRVGYncMobWIyIp6hL3hDrP+UuvnErkbMX -JpGVfyi7YNoMXVv32IdxAIkCHAQSAQIABgUCUfZyDAAKCRAXqDRKneFCUwiBD/9T -2Z/Lngh4H1/izqIcp/yyw0pmgHga35yERcxKRz50mWMnuaKmC3yArSVmLMZ3tqfm -A5DDUs42WMP/jjREeq7VVsNx/mVYZ2F9q84H9VA6pEwqhKPKwtcI9/68+n9Y1160 -IVQs+X/3yTBjFucr82o6ImzLva3TeW4FoE+lBNdp8kla/zkWprPflMExgrjTgsBu -+nUoi5AvE6sToyQSrB+FPrUYDEyMMm4yIMuOtKjPgEZaGo8/eqn7S1oXOz0hWUhA -InfTRamvmk0w1IFpdnbUruXwE/YM1x1OlL75l/ikS0FIbnxc/j0R/AvF72fzi1Xr -Y4UfnUUIJHYK/0vbOcuzdKxKtrs8QO2ApqmvDLGyFKXTCQK6eiN4mcm4X3/XHC7E -UwfKZUrF3mPKfAqD303TFCADfBrHIbYy6lgvG6ncyPzZ0/XJnawje1c6BOWS9rQ5 -V0Mo+PZ5bM03XCpbh03jxzhdo69QzZb2ADeX2nmukABbwbMU6B24I0VYjqmX/8hH -GzEBUWmyd3Et5aQENhWQ5k3N7LL5vYxZJrUepWwhri6rrAdsLite3M2kvs4mVSBQ -ghJZgbUWKkBB6JAlnIHLcwCA3n7EOBrJL1Ht93aPXN0ytRLN4+uxmRVCxWIUYx1O -h1RbUH8hrUNQi+K6fK7BrLjQeYjPlpT19qhuvFakK4kCHAQSAQIABgUCUqU0FgAK -CRCQe35tuBCo6rQaD/wMkhwdzcfB7Fu4M9xlYQQMNeK8ke40Ot4vdoQrlyR5lJ3p -2TOgEUz/gHcsGOjB/KHMzI6Rx8hJQ8r1vZ0yzJFK/qQsEQoqrs88UW4n49nL3UQM -nPtq6V4sPru44B2L+rdw4JXpfr95JjJl+T8uu07nx/tdGco0t+X1yGdYTMilXW7F -N5nvuKwtIu9UP1wwia2/kftE9++SQjExCyGQjQJ3jM6cc39TrvMn22AaqXvinSwq -3CiSxOCMXC0FFAw8J0+SSez2CVyQKbBXFqYx8s2Aetxjt5M8uoF9VNwfvok1I7Yw -lo4JUNUKYsWbbhrhhTNWUAURSyxjIIMc7/iTTfZkgDVD1zMZDXWBFPw12m1Iksok -uGJLdL75CaU2Jw2+Zlas4Oj8e+a3uHUFP7CTJ4zh28O2oM9G3oYcATQ04wpMuLpY -A3H3X4JqmHfkR5KkKg2WApvGX9Flp8YTlBgxTUAp50r1F/HRQ/VBjtIUQ7AzquBK -6kMisNYeMFyuXH1Xs/6SoZ4xYNm3vkiDYTxjuRkIN/EUR89KimeDSH2mZ/tdCsah -uv3aJGsxZxeZJPN9UAKGY6a9l12CaKxj3ACNCk/icFIC/X+Ekmy1dDnK4aXcw8na -T4aIBdjFvWGYvu9KdYR0OGj0btJFy4XAQMmJ0pB7KkJiC5XiyPjDLpMaER0bCIkC -HAQSAQIABgUCUu4VjAAKCRBybazw2G9AbDyuD/9LhLQCdOfLReLta0hd8FJbK0CV -0/ObvdYOrz5Aa1vP64O2qN87imYDg5g4W+NBYfs9L4auHokus/R08jZSoApscKAY -AJ2FJ8wiaC4P4uEiyriWeijkpiTPKBz+LTX2OoF9KyxrnrzKqxAaZouRVdLk3rrm -GYoq74sswnp8XAUBwtw0vzJ124FZjJbB3aB2yrpZjwM4sPAGXI9Gw4tVFHyJ6oBN -VL6B6WF+32MRYaooO03aeD3U/KSeU8eGM9y8A7bMBQZtt3s8GKyasp4jXjCpuh2w -NRWosgLMAQAIcbd3DDzLxmMO5/HQdy9lLkE/kHZyKhYYz8UiogPK7fsOD4iRhfRp -fgJqiF719XptP9lN0j38/s4SLmYbaNjudb/74MXNBwrpLyeKq9IwnUTUwpL2REKb -T2aCU6pQyfYgXJ0kq1Ikus1T0NnOsmYOWt+nkHEnZUT0tjHS0H6O8VBWfl9I1ZSB -5I4eLhJQ31RigF9TroxRtZtQHHrmjDGu1pDRCHTGlLiwt+HOavEXJgpKeb5z0Ng2 -klg8/+LoL2ejVSoa8b3G2DQhO1fTofABy2Dde9tc4HWUduzwl6TTg+0QwXaih5jD -SRPmUC4xq9S8sb3O23xngbqsIrRVwTpZh18cUfHrWIo+QmB0lKb21d0vRm2C7NSQ -+lRAhGKv/08Z5Rg/UYkCHAQSAQoABgUCUf2QbgAKCRAz0l9fwPHXegMtD/9a1xE/ -gLon9cclqf8i0zo/QsB+AGCF9L37s9SuOVXzftxTLckeJEMNV6hSGHg7X+STQj4j -FICElETqXuExBDraatJJ9Rl6rO0Tm5sl0B1snBCQsfeIKFFiK6kc5AZgV22eshK1 -/8LqeuwR53jpfDuGYUmZNN0DkzWXmXnPEbAkQ2HZE9zAPHJyzujclUyRo/NyHSBa -w5ZxOrqTmCAdKScu63G7LxuWBDtmH6GnTlRtqO8CgAdk1qdqElJcSCoXwOkdl+uw -jVtH8zlfi2+WSHhCtAgxYq4Eq0aQe0EOqmbJcjaEMnWkAgyXwh1VFcxOkop6d41Y -KB1UYRDT3v7Ws04PgfLT8n/Xyxk0oKsYJTKruBzpBqYeOsV99RHHy0oWqu/4kEME -pZrzrbt4ZWM5+Nj+BJgC6AmNC1fA5X4CdPJ8FEo0O/G8FCBSXcroakF2zH8pmTJD -GtjhwL4xfBsLXuVQM9zWH6qxz00bGzrwMPpgTXwMhuIaw9pQKlKsFmyVHMt/2tir -JUh/lDyq64ikDC1ZC/AHM6GcPBqex7NUMOqu4c67+NpxjJJyXjsgP8NXTW24YxHn -LoReFloksX8O9XZUR4+LnxTAHJ8rVLy3BUsFgvFFD/nrr+4ReOBDaq+89sGiodf5 -rkt6Tg5sxVTqyJmzIH9SHSjseuFhZWyBeAk+AYkCHAQSAQoABgUCUiyRsgAKCRCG -WuZ6XiTgiSonD/0WB1FNxxRV8xbk+gvy/y4uhdSOWWUAgovurgU3nsmRB2m6W94J -ADncJiW9M9wW3Qq4sFilGwe8dCBYz1o6eokwH/Yw1IBric1m66VGVyqi9Zzn/qRc -rvjMwQu1EblQx3KnPPXPQd41fb9HgdqdTGYogOGm2GeqjixHUSphLP5fsL4sYzTF -2bYOyxIjoDErNAYE5DNZzlTmLrlr+g1Ojz9tM8uehmzJcpgYOhdje9sB4NAKKfio -7AgAeF29+UT/LWMcEbeneXoIPPrkPssZjp4vCiRDsqQrpHjY38ahXXbGtXnenEKr -G7s/R/mYs1i18Wr4fW+9oWZV3PTHsSPtrcwdcrbiXrPOSBAKiGqKZTRgWVjxVmRM -bIfpb1VDcPMoYRVtBpV2Dqsxsf7EO3g/afJIWk51JCyXwZp1ZJ2JJZBiWDDp6S2i -XvSTVb87kRa66cmnVtnFR/yhnq4VQvMxv1Pfl1a8BFPqgrpPOPLJ6gacUu0NExca -LQsR6RWV/DVIk5VqcBzKut1F4g7jxxJNeOk1R6EAxVQQZRKVqjEsmR2h/08HAj+n -01ZfSUZd5xBPfcmpdUeUE8D5SEjWoK4FZTLeDKTrAnC1BR1dfUsEgZl+onlDZn5O -dT17e3bk3NBKtoBZetX06raoVX+DhbzJ5MPNy9hovof96LYjG86cmm6IYIkCHAQT -AQgABgUCTHVazgAKCRBir0AxyC4AOUw8D/wIy07KX4AhJ/siytso6FucrBw4gEPJ -iOpeDzH8+HTIVESqn8QbhQS61x2YkU0Eran44BdCeDnQIWpukADfAc32f1cgctX1 -2t0up1jiTvoa8cFvjQwFgZpCG1IhagYyKZZXykd/hyzDmhUfxa4xYLwDhu/an0OU -y2ouOLcRNsohAaOb74CxZrPNxZmX/cIO1crNUvErEhTx511QLWIDguYZSFa/9yNh -LU0tKWDlT4B6Bp59+NmQngjAUoJZ6HM3TgHX1TN6D/VR4TYep9nnRVO/95YoGs1u -hIEINeimEpw4uwrvfXUjFn6J38ojtYq2H2XX+XrbZACraXWxAmq7mgDevsdixBGd -KLzAX5NY+a42IYMfVAdG2Aci52fj2nq/+llcaoXWLmtY0Y6lVDwjoZxeUXK2vhvw -Z4eAn1TxodoXulum/dctXieZEgnXPJuPgzvy+FgEpRfqOL2IEuvnHxOyL84BcewD -QBR2d/KygRBpAEx76MH2a+xwOHqdpvJSYztZxRq60jvaxIgUOxy01Mv0Ec4E2MOq -4Oj7Hw53N1frgPFindyG7GClrEuBhWm1eCRyiE1J3zsv2iuENrq4lqKfley7Akdz -ZW2wXarFqCC1fmACEYHZQFtveAarypa9JkADLXRaa8Y6OTvaTo6ZPMvR8VmFWZ2P -fs3EVYlPW1/v8IkCHAQTAQgABgUCTXudGgAKCRDqIQJPqFJUXd7pEACwq5N3wqTF -KCo3s7jzaM/rsN92OX1dtcapr6xsSMY4lnVorB+w4oCn9+w6HdOiZUxaoSt+6VBE -i2jPZqrOBqjfdZMuGelLaBFYCdpdOHCet6NHdLlE2CYN09BmlkRdmFDS0CTSKc3q -JDRAGnpfY5B6HeFzcLvf6E0Tan/9gYlUpPo6M+WKd+Y+92q3ZML7eHuWd4hmcphH -/GxO9JChAhJfkGsEeB9p3oMjMsTCYbKhKpyFrsXUly/sHjtT58Uq1qrE0ed9zBc2 -gbDBUo/xF4pEdiTSM4v9b2Nmn9H2P8GwmXTtM3syLxSStTkUAk5wOBZhCqQy12EA -LD8v9JyUzeIbXu8sjTYCXI36iJyfSP2CavE/8FDzBYtBPK8vv3ntlbZ0BSzI2dC2 -hFXBpmGKy877TK266s5bLUnD8IXlaZppe5jKwB6sAO1Q/B7eGmhXJEZp1wy6nUE/ -NJnqKhQ1/5LQrgl5e+NvoIvlmwSs7R9sWLkbsuQiBlJktSq88R+xQLZ6NMddTdIo -V3GdgivpEn5ls88osTqWrVv3Ue0HI02qUT6S9KTIHtTPSLVXrqEeosOyQ6IZ8ML0 -z/his681kRgsYJHzGA0f6p0DBcr8W829S7gywwv8DMFI9gDhm2LkG2r35YNOvZ5S -W452Brnx5JblljiWGFRBD9Hh1kiJ5XO7b4kCHwQQAQIACQUCT+X76QIHAAAKCRBx -d0Dbs16EdLj1EACd+vzQWuEy/V5R9XZYRDYjF245fZApSeqlIbHYjXdcbeGtHqrN -MIm+X6HNTjrvGlOa+K380oj9wsrutdywVTkJJvDCzU/GZ1NfT8XSeI6/PIURlH9t -HkyFR17VkejJOpJhYIq+Z0irzqlKXUMSW2T3SW+aYgBAz6CRqjVRZbIyo3fDWtKH -KEEoQxNX5+noa5xgn7X9du7dCU8CBdVYaJ1LZ11d01TL2EDTbyw3+f2AN1Nbcf21 -c33/oddEWbu2dE3IpisosEmCOBrUYYKU+CdHqutsIva4dLeXy1g+xcScz/InF+y9 -i+BKiNLSuIWCsI18anxa6H8tdC8F9WYyfKB3kSQP4RCUBTnmrgZPbWNxKakUoCzT -RfMpw8ZVSkcGTpC7bYjEKgwf0oMFY1oCzqq/zIyYmLX6j1LzvFwAgppX1VYJi2XH -HrUGliA6z7a0i6vQ3nwbAOCPRSrfciTt5KPCvaga5LVcHYTaIwIHeiFVR57O1kCc -eR87uoUWDLIPpEdq3LKSgVPTjOqnDr7ZFdCw+PPS9wmbsBsBWPJwVtHa8sln1zNA -6Ucpyyx9JoxMdYqaeV+fZH0pAaofZ/mgPcqEnvYoBi5gty7/JrB07tCkKxr0L2/H -+UFihUtF6ZWmRP2Eg+wfRKSRHtXJRf0B6Ya922sX5y3VnVZUmxB+nHvd2okCIgQS -AQoADAUCUuKU7AWDA8JnAAAKCRCtp7Jf52Nw1vGtD/0ZL6ovDwv1q5l3br4G1vzM -HtB946eqLEu9yH784/ErSeCwYlcNdcoN6UkzBw3ru+cpbaW/rzVkFuvINB0jWG1g -wfo1aEhwhLHuEEV9ZHaoO+Iw84r83h86EGHYShnEAjpRlULop0092hlJjwZtJtdq -aOboze+mwNOasdMKYbQt4AQiBn1/nQb3fAV/zztYY3BKm817tYkWO07PtZvtdgPl -QiB7BpG+KfStp0/34RAZX2hsNBJdmCPUX64b7BZfxyxvRBm5nNWGNuJJ4hEwwZKf -nLHmyNwFqLmWXjaYd9bQMjLzStSGN70HHQQNd+8gM3T4yPVy45PVVpyZ8vH59nFO -Mvyq5RW8hlVjT75pFuV0K5fu34v3Q58h+X7IndToGEZm/SvTxBfRgMnG2FemOgk+ -i0zRt1QTixNWJiONC0HlnD4DAc3FAdgAG/pUP5xiNuEdAj3fKCigmMWvd7qfNvsC -GO+VPMGbNnIGDhJi2h3aaxzFqOlmxuWvWaDuNaT1lWgNw3TYyRedT8fC2N4cpf79 -O3YJ3bAR+yJFMVMl9+PQcL1TMTGcBMpDyKxdhRjiyVnS7c5I57BRlPfzR6C2q/qy -2r361lN9FJYQoLE7XrT2K62yDef8GAhON8ov5JET1jiOMpqa56jAxh6By3i6vXJQ -rrnMGkoxMD6akpsgvhI2nIkCRAQSAQoALgUCU7vxVScaZ2l0Oi8vZ2l0aHViLmNv -bS9pbmZpbml0eTAvcHVia2V5cy5naXQACgkQExjvrF+7284RWQ/8D2fV/dbb+mVL -ZfgTL48JW3hz6tpJ47TANL3VWhTNYUruKLIT0hqIFfZETFcUFgl7QhugKK5Jb111 -6wssMDsCWpa9ZCMsMiSFiTBOkvqKcbejxu3pqKbla0gVN2lGQNvazpXvUXyiQtT0 -n+COn+SWmqEu0g7bcI6lefRmE122xHjoyRayZeFNVKQW/2FgZJDA5RRZuuvQyCDs -JYmDb9qWPCzkPwUpWp577asSfgX8ByAuPDM/yAuSXqoComdEkfO4YYxNTcVArCLF -ZisQETN59vIWb8oF7D7Zdl+LAvtPMahw0z73DVC9aa/WE3FSAJekWt0OpPpCcSF8 -Ns8Wl2kKhFQ3To4N0T+C68ylHEWb4FHMzSQi8b4g8xOxVx+4u4IFzTCkLjRY9K/y -gVJpW59UViwvm2lKr7DJnJ3HJbIYqNfSpBrh2ZFlpn+78SPjbxARC9ZZ8i3NaoLh -hOtg//YxSos8j0Jkr+KqQWytvgdUDqwiNiH6QK3RApgxmBcYuMJNbaAIqCCfWi6F -/GByKAh/VI6LcMrFY9TjUcwkfmO5KROFuS1juK/R49efb3ZVn7wKFT6ht7hf2Ivx -Mzb06eBhEXYsG+KPsRe2P0/GBmtI4zzmFkT5Scx1bCnGuWfvEr0OtqP/1JuHCy3O -lxPze6nUswROndfpS8Clc8CD7FwCLm2JBBwEEAECAAYFAlFIqX4ACgkQa8dYy8Ef -YnZq9R/+PyP3ZaO/muLrRP6gmXR2UZgJ+7IlsQKY81+ZAQXKvGWMAqmVPI7FAL6j -rfc2iplQAgZ8vCyPHzJ8QYE2CJlVTERMliMSvQq1a/Mqe5ZHcpLAMHDk82oELobS -P+BfmrQfjQTtBQKZlWfDoyCT+CL1+lAHq0pULbAI9T/inDlQB/q00f7j/3vW6kka -BqBnxu8QoTRmipTxI2bI3lt1axaqgvOM8I2Jxx0/rRJBYskb1o6iGW9NTAgFLDDs -ReFjbqZd1AKVt78n825d8SjRVo5HRRyRBUKz/simAIiioZLfKOSIZQxGQPCNNdVc -E/9rFxV2hyW500BjbYw4OMQGoOirmsjVgGgPKkWjuZWpSXi3goSTzPfkmckMmSbU -nRP2/47Az+eoUIhphJPAVvSytKaIc8Wo+oW37JhhnGFkOIeezSTna3Tc69sWN3yl -3tZoSE7wG7akM4ctcYDKUJrsHkA9SnyYTE247bAwI36WUl5fHmgs40zUl2SrVoYy -QAR6APvRTSepN4cInvvu+SS0TIosl3IbuzEm8BGPpwWyo9pNz7A4kLHlgR1g4+Oy -xy42Po9EzItlOTleZJ0v2+fTguOiUkHc6vuMkboam4BxTMrQmmD1e6FO0ll0k7pJ -4AEhiAXezgnYZMmth+38cCx/cQAyOjAiIkQI6szjJ6hoU1XPm3t9J4eZivJyGn2O -/M6MfokS2DfSKEn92v13l9EofklooYy5igDe76b1c3uhy7wrQjuclAev6kRESbTm -nacErkeGMMb+jujaEQr16BUB3vMqK61ifwD4DrXhe4HtJCEHl3+TM6bMOaAKp/8p -PljwAMZVH8rcOBEwKYLVW/02NVzS2Yybcfh4+4UnNN8n7byv5jKqbAm3YQrhJuVf -9eLhgCAy1XGx5+S/vZeLRzDjEBFtPBenMRhsJ6C9Wvh1J29LtkIFWlYuop4/GEz5 -410+brkiAdlfxaV3dIOS7spRqf0Geo8LrjEMjciSx8e+gCLprG5d5VJM7HmYnmyU -An3OAKPFDSzZhcnJwgYTtRHCg1Z+R/czPv3IeISrLLZ9hLGmso5MycKpd1/KodV0 -g3/U0b5DLyvO6vV3tJhIYfK1YptCuBjF0z2si0p0gAU5ywerQ2GqD9ZRD8yQEjka -f6PE4fEKpIT2/zrztZ6S3vbRSkM0vVRmqjDXnvB21U6UFdaTQSJrCzlQhW1OY5BZ -ISgBnnK1aNLxQl5sR7Q/6KjLK746EueTINrOxhQfCYgBNxiZUgffjVsi5UeBzgv8 -LfnSm46Hj+6c4hceOAJl22sduFbq0Ll+30ah5mSiNVFHO/EUHTOnaq/IXibUSwjy -D3Ixto9faeKlk9wAqSPcQ9BdYfzZtIkEHAQQAQIABgUCUf559gAKCRB6Y4Cd5RJ2 -Iks4H/94S8ktPCVM/K6kzMay60kwCklO78HFNf2R3XrL8x1yYQzUtxP9N6/EVR55 -C4kCB+pw2vs+TjOsy+I1J84vwdr2NF4awolUJOOEJXdVUMqWc7d5KE+4NvbLdeQF -pBRElqM/+jAVdW8hZ0fbZKeKIqR9WQQR2wEW5nM90t91thalTEMaO4Dvu9QAm2ni -Uy+W+Eze7r8ohc0fVkp25NfW9fXoqJUNpny8ROSnpP7bvjM1UvjG0qUUaaCYcGJ7 -4zM15IUImIm8GA5MOtWW7piqc4qvwzd3ConV/ABoaCo24nC2PnpRuUDvxyVNHLAd -gott5gO3HJF3xx+sr9rie398p6C38gpDhFcpxx5RUi27UAdABQKsuNjcsafFn+tF -QmdHvDZAgZMRR5jow53sf38X6OI//IklWn3MWu8hZKp8BQoS7v1JGFPdS+LYYp+u -9wuBygnhPzlI4WOc+DP8l3GOFodcLveU/qfYw4IhBU5huitPR9kfyHfFcpWw2mb+ -mhN7zmL66JaD2WnpctyXflNLF/bGfBK0zNE9GVBLJA9NuoLrQeH1Sx9n5wLd8Br3 -gNMXF+Uo6KrsN0eEQEBJR3JLi2YfBJ8PDAZl6iH5fwYrPN5gxaZ1qBVA6PFCUT9s -qG+7aunfEqDXxrEh7+8mqDlHAgQN1ZjktGKjX/mc+c6S3rmjhg7q5+hWThUBKg8q -p+9bDnct9GGG+XNAet73k5a5o6YTAHNIqYFzsgsj9+HXs8XoOa99KP6IINw+gn+K -RAni/ft33cXIId7h+g31ZIxRNFbCErp9YKHKTrGXKU7DOkgZ1gk29Phxe5uDyM++ -3gPyu0AdvFtXJL1+oj1YFPoWS7ow7njvwtMl2i6dzLUZskRoamsGH5dE2hGaDi7s -O/hhGvu6dEMybLRDx0wzJjHTP02efmc8zd9G4AcrpdartQGX/SwGxI8xEo66RC2F -T6lrx0BaJUKm8vwxwVBL20YnIyaWE+jhnTfqXdLoWt3AGithz3kHL9F3okD09G+e -1FSHKB5isPphZxQSc7G3T0QXkQvR8nV/gW2SuKDebFi1sCE7P/HVX722xnh8zjvC -ahAaAuJ9NAfBd+RsUqXMFROLkXQ2Afemv61bE9pHmXIueErssoT7oqKO0hnmW5Cy -woTstxhNOOZmMPMXpyWM7+o23PDRm6am64DZ+O/pR2vGPNxI67ZRiIqGmBa+2max -HXpoSLGmRQQheVGBgRJlz7SVeDLP647qk09saf7iqvq9cjw52r32kinfzFt5cKNh -3ECiA1PZ3d46sHsh3yJF6o8ONLBvFyODxO42EdJrxwh+iGwdc8Um6lraYaHYSMU8 -h5iHC5gSf8fp0duQGJh2w4NfyQIOtCJFcmlubiBDbGFyayA8ZXJpbm5jQGJlbGxz -b3V0aC5uZXQ+iEUEExECAAYFAkDbAIAACgkQ1U6uS8mYcLHKuACfd8ByZCS5CPEJ -HazRCQ1JEz/OzRgAl06kA2ugWl274VjZoZkBjCQ1EA+IRgQQEQIABgUCQMIvuAAK -CRBj8wjbNW4WzeE1AJ0USaxD7Y46mCfmWMVbRDrXetH1WgCePv49JDtjuGNodolI -BvLZ/lZSncGIRgQQEQIABgUCQQEdmgAKCRApvl0iaP1Un7/QAJwMSG9QiNOz38lk -WjAY2LWBMxSfkgCgq9V13zs9oI/Bp3GWOMGAfqUdEhOIRgQQEQIABgUCQi33HgAK -CRA0UO1RP8wqkI0mAKCOB9ZRYwJjakZVGoGA1j4hhnKmzgCfS5Wqhkg1GZspouAr -/ASVWeCulhGIRgQQEQIABgUCQoa96QAKCRBkp8Cn8s8BqFFAAJkB5W1Rq66OMj3s -QPSa/VxDb/0DZACeIKrLb2Ym3dRzrbxL2yKecoJom8OIRgQQEQIABgUCQtkiAgAK -CRAiC8iDMwxKdeEHAJ9p7Tyih2YiO+ujaxeUAlZ4VNRargCdFQ8wZ+B/ivvoA9MJ -FIB7+LCw/euIRgQQEQIABgUCQtk40AAKCRAlePh+FJzdslfVAKDUywn/OsCZcwQv -6pQqcm+m8OLyqwCeNyy3V5KzNlwJc646wGYMU7AcFHKIRgQQEQIABgUCQ5o0yAAK -CRDu2NTMHeuOrjxUAJ492vzgLQfeKEfuLbxSu1SePkYcDACfeRQP4vwbQn4wN3EV -jG/dr45JhvKIRgQQEQIABgUCRn60VwAKCRALVEeiIA0VluVGAKDHWZVxgd2amx69 -LWyTDN1O8u1CMQCgmuSbuFXmH04u7GWS+T80wMh/mMqIRgQREQIABgUCQug4IQAK -CRDf7bsiJbzVv8L2AJ9emcVh79xmDjyady6H5jh2zJrxSQCgv5T8oTWhCrIIedNS -x0KlxcYSNZqIRgQSEQIABgUCQLt0mQAKCRAYoMyNVwaktAZrAJ4+We0/zjqChf7i -cSD7ciAwJGo3HACgkgVqNNvP5MutMZ9OqY7jlsX0z+OIRgQSEQIABgUCQLvn2AAK -CRCfzyzNPz5kJs3UAJ9cyBaMih1pRo8CoK7E+VgyPE+fbQCfTBxlZrddt1CX++Eq -VFuHqANWtemIRgQSEQIABgUCQMGTHgAKCRBApb7tctA8sVrlAJ9H+/scfkVX2CYf -CQvlrIAMj1t+igCfXXwRXpMdmrjcWkYP6OWc3Yx0CAiIRgQSEQIABgUCQMP50wAK -CRDJdCX7rktdkrKEAJ9XJyxP30MtX4k1kq1Zg99f47eU3wCfXSLUlpfUg/Xb1ZL8 -ZR5B3XU2QG2IRgQSEQIABgUCQMZcbQAKCRD2fipdHPLWKlxyAJ0R2mgIjyB+TXAn -+wIAp7bUNfN1kACePclfyRmHyexn8AClRM5oEzhkpeKIRgQSEQIABgUCQMs8pwAK -CRAospXD9G6tu48qAKCa6YnZeZFdRvzGWe1qe8A+lpbSjACeOBSZFFbxGArQYvyr -/nyds2hCIaeIRgQSEQIABgUCQVTLUgAKCRAXlhsiHX8fu3ZhAKDtFEX9EiXES+D9 -zuRnsmCXkOadRwCghrkfTw5mVv/uEvD6rNPn7kBv63OIRgQSEQIABgUCQt2DjwAK -CRDeeq9ulMCcf4QRAKCmp1oJHtkrOJ3bVa+w2W+dF/THvwCdEncjnspAZCcqe2dI -wb1+w0LwXr+IRgQTEQIABgUCQEKxVAAKCRDIt+k11jRp39LkAJ9nYG1ozpgNNLq2 -OFqu6z5EF3o3wQCgnFzseCMebkRDnp+KgdOOxlq0A7eIRgQTEQIABgUCQLqnAwAK -CRCMkDR/jwaAEr7CAJ4v0eKx+H7dVZF5p7MQ5bFN6JLF7gCeNxfDG+hVf8SwZ8s6 -SXqxkKPZur6IRgQTEQIABgUCQLsU0wAKCRCKkGd5GIAoPO5sAKCasjtvqKHwOLxd -QDTdlbDG2B0TlQCePz8F/OX05QHMs1FwxPQ8H3qK08CIRgQTEQIABgUCQLs55wAK -CRBRrPatdb6Al6vEAJsGJUGvEAfcUgjELxd0yP01gkFTiACg1L/twxsY7Lf5DXqr -hR8Mvk/th4eIRgQTEQIABgUCQLtQvQAKCRAie3C2VZUHStVnAKCkEW72W7fJnhy4 -qhEyQtL7lodhDACfSUbJ66ak5FGOOlVPKPtt3i3O2iGIRgQTEQIABgUCQLtptwAK -CRCELNt6RHeeGDCpAJwLsY/hLAN3VpYFjFXHx4EDNh1LFQCgg4t7x0N9HvJMKKFe -CEiugbGsm7GIRgQTEQIABgUCQLuTDQAKCRDGE9zpPiBgrF7AAJ42IFyWZYFnH5Pn -MTZRTmxEplv57ACfefY4VAaMKCTgcAp22xls8mdSaheIRgQTEQIABgUCQLvn/AAK -CRCfsNsywCRAuFxLAKCQ93n4MLkjd6ME2ZE+vXJFEjOkRQCgic2epa+YRb877yKh -hpYQf01E/uWIRgQTEQIABgUCQLwxzQAKCRAEMjbrEHMZd1QWAJ93+Cx+Y7wMhkjk -+d1K7D0+SRc49gCgkT/+Dih5QTU7RQHDJ8Dk2FcUv8OIRgQTEQIABgUCQL5jkQAK -CRDU5e2swBQ9LfA2AJ9odcIuoAHuQao7rsdUQG7f+3UFrgCfSlGaF84JOgsWSrw9 -U9iN6lGPj3mIRgQTEQIABgUCQMI54QAKCRAo3q5/KZguWsB+AJ96yLNLGd11pbDI -YrPcHDvvS4YrQQCg1QrC/NsuPF1eAnRYP7hN4CiGQOSIRgQTEQIABgUCQMKGHQAK -CRABtHM04NSemepBAJ9VpyzYstyNS5ZbreuolzHkh3TSFgCgjXXyncKrUa6cbUbY -FXjWk23HK1CIRgQTEQIABgUCQMMdWwAKCRAhT2hBUV+bdG+xAJ4hxV4jwZCt3IlQ -m91yeVAQSnv/9wCeMmaLHdcTssI+wSJ7Q/AtFtL3AIqIRgQTEQIABgUCQMN6hAAK -CRDYDvNai7Unr0OFAJ4sE38ZN/1tezFgLGjHOT5S82WqXQCgp29uM97zN/Kp8ZAg -2dBXYveAeOeIRgQTEQIABgUCQMOAFAAKCRB8O3lwiMfB9yjzAJ4m9B40bSkRsH/I -rrzDka7td7qjUACglMQPxapxAcje4aezls8XFY2PFcSIRgQTEQIABgUCQMO4rAAK -CRCG4A0MGaQtGbPXAJ48zfYGHn6P6hT+tpY6bQwV8AzVcwCdEgFcf9Cp8f95gt+p -ovzQxhjDi3yIRgQTEQIABgUCQMQO7AAKCRDExxT6HgXVFrWNAJ4mUgDQX022tssx -lVFQEreeSz9MIgCePC26dGdW0o+v6HI0/BEjvvEOoVGIRgQTEQIABgUCQMUf8QAK -CRDM3+SbCgrJJ6iMAJ9KWN36aazePIOKA9+NDs8nk5eJPQCcDgMvok9j8FAgQdlH -0Zyb2Om9zUeIRgQTEQIABgUCQMWcoAAKCRDxvUvkW0MDZ7m8AKCGWaOHEX1jEmdA -jcnbKw5xcsu5HACeJzaKyj+v23irIjdaLWMvBPzVhNmIRgQTEQIABgUCQMYqzgAK -CRDnTSm4K+FtAeEyAJ497QwCjrzXT8TRTBMl4BZHvqGHfwCfZ2EaUYXC7fRtoDhR -T8cvZKchHtOIRgQTEQIABgUCQMdUAQAKCRBFyLbDHGS5Bw1NAJsHCtGU3BtVulBD -gStDsO+auey7eACeJY7i/b+NJSI4ORcTX2SDhZX9/FqIRgQTEQIABgUCQMd3hgAK -CRAdc2WnVYFdQk0lAJ47zcAPTdIqnjoUQ+XyY/ZWmekWhACffOw1JIN7lgW06fmw -rw7Md8p3zFuIRgQTEQIABgUCQMfR7AAKCRCUC5THW0j/ro3HAJ0dEPON7LTjuLnf -KgIbQ3MAaC1stACfVug5ek92Ore1Kh0XrXUkn5V58wiIRgQTEQIABgUCQMh0OQAK -CRC3VqeMiCpsS+0qAJ9fs0q2x2iPsRjI/MykhnBpdiQg7gCgy2+P0kIzp7Pqy7W9 -wYJSXRfoCC2IRgQTEQIABgUCQMijWwAKCRAYlT8sc7AlkhO7AKCL4CV7q1lXzAOb -YmK4ia/PoCNpNQCdF2BK39j9sMf6G23cI2XoAgBwhV+IRgQTEQIABgUCQMi1fwAK -CRBxof9gG/jeD5LiAKDIuP946bFdvEv/OlnxcsxeefwnDwCfYpM2oQwDMcgarw2p -o/KveflCYeCIRgQTEQIABgUCQMsQRQAKCRCoipqwhkgmw5+lAJ0aP7wq6pzmVFMV -DOODUlSmSiWPEgCfU7+JyqRXfYXKvpAhxsgxIHyVwaCIRgQTEQIABgUCQMta/QAK -CRAo7rNaPo3MwIV3AJ4itPRjt2ucWcG7U5lDqGp322nNBACfal5PKl/K0gLK3zaR -lCtfWnXfOQWIRgQTEQIABgUCQMuWKAAKCRCv9GcLD3qNAebdAJwKx7UWHH2CYXn8 -rtdFh3GTXk4d+QCglQCk/l00JMMpoSQr76KhT2tJsJOIRgQTEQIABgUCQMvrHAAK -CRAYlT8sc7AlkpVhAJ0cfbA3nPx3/GqJrWNichIWe3pLpwCeLMw0KMnb0N4Udhk2 -ADCRFP3twyyIRgQTEQIABgUCQMx6wAAKCRAPgDPwusq2whUVAKCppSZ8rvfSz5Lt -soMWMOC+bbRkrQCfTKciRI9ICjRdOxVemWqKZIrErIWIRgQTEQIABgUCQM0XVwAK -CRDU2DVhZvJFIcBuAJ9WEVilyp0Mg8saA/sc4DQBO1n5bwCgkBAQS837sjL3CqE8 -YkNQTWlOIWGIRgQTEQIABgUCQNCI0gAKCRD1mBMlOgllvGr8AJ9nC8ib0pjCKUi2 -CbvMbnBVpJa9MgCeOG4nff7mf81umitetBv9aWFDYsKIRgQTEQIABgUCQNSgYAAK -CRBuuXmMH/+CrzR7AKCcyYX0ByjYBWAt+Ir8P8yoqzYWkgCfX9sMpWl2YAwRHDDS -7nyJojK2uoyIRgQTEQIABgUCQNqGaAAKCRCJzUshYHVZ5hJwAJ0dGeyAVG78jiQI -P5dje0E1ip7f3wCdELSu6jtH+H0/fVQMSti2el7E+ZOIRgQTEQIABgUCQPNL8AAK -CRAYRFL6JooITV8UAJ49VB48O4TX0X+VBMK2PrRoiLN3sACfRnad5timUYXaTcfZ -KHkNhyJ8vO+IRgQTEQIABgUCQQWGOAAKCRDbTMxLKjDXKQuFAJsHbEarpisxsWL9 -uxcKs+YEHfyMOACdHFZuz+XEXXUqb79l/FO3kOv55iOIRgQTEQIABgUCQXaAaAAK -CRD0tLDMeX6/qzifAKCRcTzScl3WkNglbE6ZFaH6rdgMcwCfbUCYwIguqlSDw8gY -fW8E4ZlJz1aIRgQTEQIABgUCQXlTRgAKCRBQctA2rFg1IGgnAJ9HQw6rHGBQF+FE -jH/Kyc/Yd1x+IgCeMe5PAsXdHVaMowDv1hBuNVZ5PpaIRgQTEQIABgUCQblzcQAK -CRCf8lg+aBtkaZB/AJ9N7MUjfUP30/DZxzs23OB4K4rE5gCfd0DM0lVR6XUCzDbM -h7LEvtA5V9WIRgQTEQIABgUCQjB1VQAKCRDik6Piqaq+665CAJ9yE6VhEp3zFw7l -pKZbAF3LpQ+lkACdEG/tgftcHApSPXrAYNoLX/V3qV6InAQTAQIABgUCQMU2MwAK -CRCr/we0RvMhLU0fA/4jGHFaoSMtdhDSXgGP7rT+/Xv7Q/dd8G6ZnLM25HL894CC -u2ZTGiU98DB6Msmc9NfHupkLgl2pFxb6KOQSE6Dkmopz8lmWKJjCtY43F7RcQJUJ -Zewx2Y7jJ1GQm/9LOatuNPfT8UkwR+k0ZNY29VkHdP3QASA01sfyOl1ciY+XZIic -BBMBAgAGBQJAxZyhAAoJELmFmCJNxOf9tukEAMW3F7GMSBfqC2uBTGk2WTpFJygc -APnx4QrrRQ8guFK1F0G3+mV9Mb6WGv04j5JF0ZqI91IgAki9nTZyoqd/RDGoag1t -W1eXGsBHNvu5gafjmNYPec15uPDI10ljNUWSanVjO02obFO1kbCWWodSdpzQ1RZL -kBL4RphEfOBVjmDRiQE0BBMBAgAeBQI/jmNAAhsDBgsJCAcDAgMVAgMDFgIBAh4B -AheAAAoJEEFvBhBj/uZZWFcH+gMrFSp6LBrl8Czg4hR5+uIF+xypxFFCCYrrPU8H -Z7Ijlue+W9M6f6ZgY9GWbMelPcLMIkmMScMd/e8HkNLIRGSkufyY7PcO3IGoq8w/ -yrYeaymYzyTEx3b0S//Js4GHnxhWVWYG5vNEmO+z4pAm+cslpNn3I0ag7YoctDmD -3tMwEiaaHZnbCKC1EeuSCspBmyVMCFwniFVWzqVhWzECcv1udFzVNJjT3ynf0vDl -bQpTwY2QfEQ8YSD9Qr3cSdEY1xaza4Aqawlwbv/Ya3hrdeUIX0z1xyYA/OL9ReSQ -H5/6oG7AGCj4HnBeDi0yFIROTaA31c8whqBwKbbZa6nVQAeJATUEMAECAB8FAkZ4 -MKwYHSBlbWFpbCBubyBsb25nZXIgZXhpc3RzAAoJEEFvBhBj/uZZ6CAIAKJBXMOi -jlBud9V1UqEWJZ+mdLonXMoM8jUQmKmGyEa4n3dPfTyTVUxlEMxrOLxKeNImnfxT -s+L2L1oG36OiEEsoe77CB5v97Fbs/uH5z00pB4JW7+ZKHDxvCtPcHhyILDzGtYS6 -XMJuJ6cyLDN3wfG+w2Ao/Ys8VJfPHMVhDjvTI2LF/jIA7HH9u/D5ei8TepY4hZ8Z -zIwykavkq6mAnsFna9JuMeRDj2msC15IhJaFBBuDKlXR9iRoMDKa6fAj7M5BzqR3 -HgZ0o4zj1h9ydEJpToVV/+exy/NbwcGrRi7cIAnckLTM+2e4yRjghiq0xScqJYV9 -7KgU2Eh3VhUVvo6JATwEEwECAB4FAj+OY0ACGwMGCwkIBwMCAxUCAwMWAgECHgEC -F4AAEgkQQW8GEGP+5lkHZUdQRwABAVhXB/oDKxUqeiwa5fAs4OIUefriBfscqcRR -QgmK6z1PB2eyI5bnvlvTOn+mYGPRlmzHpT3CzCJJjEnDHf3vB5DSyERkpLn8mOz3 -DtyBqKvMP8q2HmspmM8kxMd29Ev/ybOBh58YVlVmBubzRJjvs+KQJvnLJaTZ9yNG -oO2KHLQ5g97TMBImmh2Z2wigtRHrkgrKQZslTAhcJ4hVVs6lYVsxAnL9bnRc1TSY -098p39Lw5W0KU8GNkHxEPGEg/UK93EnRGNcWs2uAKmsJcG7/2Gt4a3XlCF9M9ccm -APzi/UXkkB+f+qBuwBgo+B5wXg4tMhSETk2gN9XPMIagcCm22Wup1UAHiQIcBBAB -AgAGBQJC3Z/7AAoJEKOILr94RG8mHXgP/Rw1uMfTgVz3ZjhSfut6F9ckU7mv1Iai -Y9fOmEroWMJvcQ4YisHFU9kOHnaLqeP1JMjXbwCITrlowbHpObdPCkYdmU8LsYgj -fl5K74ytQMgQN3+XS6OItauERwxt6S6PaFm+XnD1/F89dK2OYdzwCHJ0a6MxcosV -kPv7t2l+YmXot74slCpHO7cCKwEOsSs6sPXQELNB08WdAG8R1lwGj9gbliRh4yjA -9I5q5ktf1Wi3Su9vsKxXjstkWQMGg6wqxt/c/cDPrzETgQY0u0wuQ5PWk3kkVmVW -jy4657LrsaBU3TtFKB83zaqAr9r1oSz2KT6LiFaQACdAzpc5fSBPCMeqaaYNc9Mx -6G+3llbpkpZcUaJmEYvFSPpq1vd5yUNMdmAN3vMjg2oVGZZkWUh0JeGLK/BOsNd0 -lBNaI9+/hVmTzp9cGA8CvSnHG4Yi+Du5OJBdWUtpPJw5HOeBuVdC1SAaGf4V2eSY -I9Lmm6xSZtyY2ru7XaOi4o4tA0LsdkmSFitHQpPNEX0HXu72nEARJXN+N1UkV6oX -jKen49DLlHJkgS+AGqiW88avVjpXcUO55b07PR9mOapsS1U1kJ/xOWR40DCbD/c7 -mzTMgULZecwHUi6hIr2fBqkUWBwonRLztct0aFCNrXLqBjtvRTQ3LtdLVe8zStj1 -CIbS52mZMTXyiQIcBBABAgAGBQJEVXe0AAoJENfD8TGrKpH1q2AP/3b4iL6ZR56F -bS8OV9V2NlFxNo1vMCcYXlE+rjUs+4KNrBUcm9aaSTb9D3yR7aaBq3O3gHMmAeyz -yiCigCfsXqUeidtRvq1erbPVeuHmGlKqFy4znoeP9xdeQlpARdUigVON4JGCOoox -8FdhLTx1Hs9CNluzVcrDaeX0TBzWrg76CyKkJvnI3EMg3YqtJqRoxrGvCc/CEmdo -Kt184SF7W1fYlMJDKmjI8ElONOMZYCRTXTah/MI0FXFbwLWzoAk1JmEU973AOV1c -XbSBw4LRmJ3XPFEZco/eaBBMox1GwNK5QFQwtut8o5FfhSTEscj6CgReheD4ja8F -da0X2TOTxzWyNQFmelKFYm8a4HTJtNLWx9ItpMk2wIviFJdk2UGVJ0H43J4QqZiH -xnYm5VkaZT5coaszWrK3irYJkfYL0ChIfYWWebKjpF/9d6G+JbI24+jeKrEx/Nne -Sv9KpZoRusQL7SLSjH16lgl0aeHtgClcAyXg6U2ZVxbJ+vNBs1DVk/6hUarjympa -VoNEjPqkmJ/Uv3DTKcY+2K4IXqB8IhzX/PAiGHKxT7cKiYcKvuqihdOVLP6J/h1r -Wossj0lYEprx04D4CN+7T3srmCLikhNIRmW3XcO0oP1VGLHAp+pusGeSco0Gj+pH -I8JIQhvesofdg3oFLJaUJBOhHFW1AYEZiQIcBBMBAgAGBQJAu1peAAoJEAgUGcML -Q3qJc1MP/RjDmpMwmspKQNyFg+HvoxLawoIWOr0FqNZcg0kabh1n5dmMg6e1HzmE -z8YuxJsJIAjGmOE/nO9MQSjaCANQlk1XIQtv5RI7eHfuujMFoZI0KjCp9Hpw9d5m -HwhgZKENGhO0TzVQSTTp85LN1/LnxRol8amtkBLktTqb0mZ+0n/3XOAkq7Ls/Mp+ -86J5yhgTXt4weZSRQZRjUyA0Q2PmfVvjU0V/XghmkRge8Pr7cjA3dsgz+FtJ3oKF -kITcXu+ziRXF0C1nP2n4xQ/hkFB1DdWfh7poQn/U4IJoIgnzFSk2WhCD962pvx3J -bVio6I7eo3/8opq8LQMeEGpsqchtZcJLmhor0hJGXShSKFDsQJKJMdqJ0ORHL+xR -rXdYmepVvGiA6uFCR25w8L0qhrywkrM9tYX+JNnQ5BnuK86+yK/Uk80X3RIBxlpm -DH9pgYUQAB7xdMlIdDXzZqTmVs0iz3S81TG62cLOpOSgMNP7Jg5iHsB8X3LEWiZK -PIUW53zbuWkEhzxV+xnFqn2UsqKSS8qASx04UfCWHuJ1HcVmTbQIoe062u5zIyu+ -5aGpVHjEJi7EyGClLw5o5rYIFA733hMzJ27yFaUX+Zl29gl3K40PIojW64/FVyNo -IllSGwX9xmZy+a6grDGgfKU7cynXLASQLtG+OzpMHLm7F00kpFc7tCRFcmlubiBD -bGFyayA8ZXJpbm5AZG91YmxlLWhlbGl4Lm9yZz6IRQQTEQIABgUCQMtbAwAKCRAo -7rNaPo3MwDtVAJ9zmutEhh9CfX1JuHiXMHS7mqc/jQCWO5D+mUC+DxwXI2nEauqv -xpj7UIhGBBARAgAGBQJAwi+8AAoJEGPzCNs1bhbNYRAAnRLEW8+kpPcVBHtDpOrq -Uovn1kC/AJ4hmZ4MVqfJREbsvzr0A2sB37t964hGBBARAgAGBQJBAR2dAAoJECm+ -XSJo/VSfoSwAnit3XNNXslixuLInToBBxRFU6LXcAJ9vhDSJdpvH99zduegexyOz -KxBGVIhGBBARAgAGBQJCLfceAAoJEDRQ7VE/zCqQZ1kAoJ9V11KqJgLR3L3R7D94 -dju98N0kAKDa+/bWW40naGGSTweRhwGiJvNRtohGBBARAgAGBQJChr3tAAoJEGSn -wKfyzwGoEwoAn2SanILc1A4B/pekAY6kacIeivXvAJ4hO0qNXJrTEQJPdSjMfWx/ -lVvh8YhGBBARAgAGBQJC2SIKAAoJECILyIMzDEp1f5cAoKwF/xl4f3mUcz6OWb1G -Zt5j5AmaAKDCfuxKm2v9hs+rjW1oIlloWqJl2IhGBBARAgAGBQJC2TjUAAoJECV4 -+H4UnN2yGIcAoMtdqB/kkDTAOySZm+gWcTq/NJdmAKCrVOFC4ZoaoB6XNuczAa8+ -PSzxK4hGBBARAgAGBQJDmjTLAAoJEO7Y1Mwd646uPCkAmwYtIo7XRGRqVvCVVKgp -CzXfth//AJ9VdrBjv2Hg0jb+maMmrLo/CWXAVohGBBARAgAGBQJFql7UAAoJECWE -lLqReiJexfwAnRQWAN2zfK3e69fepkCChocoendfAJ0Q8npYobKWfNGo73uxKpcR -M/SgLIhGBBARAgAGBQJGfFBSAAoJELxq+1uh7nYc7H0An1JAFz6VaA0u1yjWMl0t -XP1wNuxvAJ41ptglc03alNTaPp24Q75DIAUlYIhGBBARAgAGBQJGfHLnAAoJEFyk -UN5St0h+9EoAoOk4y5J7euQ4y8U9ZIbjjT/kbtaxAKC5Emcx6QvQ90SgETfJTXvq -3k8nsIhGBBARAgAGBQJGfHM5AAoJEJhL04CsX3AMo1UAninbEQagHCjH5hvzGtYP -ikx5/aJ9AJ9HayeBDDucEP67CERncwZEXckJn4hGBBARAgAGBQJGfrRZAAoJEAtU -R6IgDRWWAmEAn00W+TyvfWWhetk865T4iUSLDu8XAJ9M6dQEsknJ2Fae7h/+zcYd -SGE7RohGBBARAgAGBQJGvAEtAAoJEDfhwXVwCWrRtasAnjLipo19NRfjSd+Z0n22 -mJYIN7KIAKCMkLLMnGyC6b3sUATernJ1Xed1k4hGBBARAgAGBQJLeMfHAAoJEDud -CT8xsJdLTN0An3i4U+X+Cl9E4F7vscSVBuUiLdCQAJ0d4SpbjXDFOjzZgkaljbr9 -dJQHz4hGBBARAgAGBQJMUA9fAAoJELrrotdFbK1Rr1cAniKR/qtjl8Jysui6llMD -IWWcXCLkAJ9bmTfP5zxi40590BDJELLVI9mVfYhGBBARAgAGBQJMZmH7AAoJEBWc -6+rvzZsG2KEAoIYefyYxuI0Yd/Yj0NKkgckBbvbHAJ9EbgFJHUZrBn1pha5tqMfl -4ccOuIhGBBARAgAGBQJM0YkAAAoJECotsX2kXgURrjEAn0x0p2ntriR/uBc5ETLM -FJScJ/DTAKCNDYANO/AfiBtgbESqR8C0gE8d3ohGBBARAgAGBQJM9+ATAAoJEAYi -dmOmQvqYoEMAn3adaG+7sLzaGPTRbazqEsZtb0p6AKCAX4n+WIpjhJYQEJ2EwWok -tAFJ+ohGBBARAgAGBQJM9/nUAAoJEKotwq6l89tWqSYAoJ3BvGdrUEFyam4NSXKW -QmKIiYTgAJwMFh4QX8OScX/28hd1b/2uzaJK6ohGBBARAgAGBQJNeS8MAAoJEIr2 -URweWybxvCUAoKPW56RuO/5BE0ClnJ9wpPXBKXkzAKCJ+B9wAPybJlWHUWmJHIeq -ZetPQ4hGBBARAgAGBQJOvMagAAoJEOtaiWoomIv1uyAAoNjTfAvsPvSMdBVHEi0R -lkEzaAXbAKC51hFeNp/UUXx+PKU6ePVVzFFmuohGBBARAgAGBQJPKYzJAAoJELhC -CT3GdlQwtf8AoJFZlfFX3BadsHtixO7DQGPm/+gqAKCtMaNSlxfxJ418rNeJpF9C -OaqgVohGBBARAgAGBQJRT7TmAAoJEIvYLm8wuUtc10AAn0NQ/N2hNPZ+ZwKc5e+G -o0w9kWAbAKCjuPP4SnIEYzwrZDCPxGp3kZccsohGBBERAgAGBQJC6DgjAAoJEN/t -uyIlvNW/MvEAmgP7c7Vg8MqDqDXNrr3eG92UG/3gAJ48ToRxZAC+r/wAJkCPywaw -5EbMMYhGBBIRAgAGBQJAu3SaAAoJEBigzI1XBqS0OwUAnjta1tvh5+AX0q7IptB0 -kxzCb8eqAKCd9HYGEv/CKxRsCFAvxreMclVgS4hGBBIRAgAGBQJAu+fYAAoJEJ/P -LM0/PmQmxrIAnjeS+n9yCSPTHJZdGDZkEcErf4k4AJ43m78Y4qI1R2fFASp7xk2M -CizFiIhGBBIRAgAGBQJAwZMgAAoJEEClvu1y0DyxU1YAnibmcel8TDL+x5Cez007 -IC8Ga9xVAKCR87TLU4hdUESyTXMwQqyxBDyFhYhGBBIRAgAGBQJAw/nWAAoJEMl0 -JfuuS12Sqs8AniELecdxJwEWaO1B0/kfwUrA0UNFAJ974eHp7yUlN+lBSB4o9Qa0 -CsM03ohGBBIRAgAGBQJAxlxuAAoJEPZ+Kl0c8tYqJCQAnRGjUkSWyZkhepF07RpO -2jumFubiAJwJg8CbM4+K66aBgEat2Y7wMTwV1ohGBBIRAgAGBQJAyzynAAoJECiy -lcP0bq279HoAn1fcam7H1AtRMlpgtkHr5/oA2QniAJ0TcXUpU+z3aq+yO8Sm1Cqm -2AeDDYhGBBIRAgAGBQJBVM4GAAoJEBeWGyIdfx+7I0AAn3D7n9Noy+fMKbgSxSXY -Ry70Sg3KAJ4h3RW0yy6PoujuEkCwfTkGrVIZO4hGBBIRAgAGBQJCK9MNAAoJEOZt -LuurljNwyEwAn1oxzK3qjrAGQzu/acHgyxWlbkXAAJ4hawpReMxEwSIHn7dI6IWe -Eia73IhGBBIRAgAGBQJC3YOSAAoJEN56r26UwJx/0hUAoNCvyD0qc4ToclAd3q4y -QwXWTsm6AJsFQrZPBe749eb8sHvnkEiYdSTwEYhGBBMRAgAGBQJAQrFgAAoJEMi3 -6TXWNGnfIJgAniZJx6/asyoY7g2OgfmTTFhIMD6VAJ9QYDOqhKOsSR76xt8SPGVm -mbL9lIhGBBMRAgAGBQJAuqcJAAoJEIyQNH+PBoASg8wAnRikrjCBk/aOjgzT/gQ3 -T/k72aD3AKCI+GsHm6xE5Q7ulLZOh/6NwhLy7YhGBBMRAgAGBQJAuxTQAAoJEIqQ -Z3kYgCg8sL8AnjjicglAreMCMVAOK5M0MUspjsg+AJ9rPN0IfFMW+25FHZ1vtQC+ -2WNGTIhGBBMRAgAGBQJAuznnAAoJEFGs9q11voCXm9cAoM+Ho3ZCogDhrhOVflyU -+WSax4POAJ4xWgq2YgjULPsuV1We5brZd8p/BIhGBBMRAgAGBQJAu1DDAAoJECJ7 -cLZVlQdKewUAnjdiVKOfEhvn5MnrmgrpYMB9lz5HAJ9Viuul7JEe00mEKGRZIHG7 -/slgj4hGBBMRAgAGBQJAu2m4AAoJEIQs23pEd54YZlMAn33529qKhqR7mVDSGOil -WyCxK/ybAJsGWHUrJ6P1OGVVAHnQSINYLZHm4IhGBBMRAgAGBQJAu5MOAAoJEMYT -3Ok+IGCsp/0AmgMrpML8QroEgNa8VVdXDGKxozX+AJ9BfTs2KvCfuy8XnxkkqWq2 -drcYPIhGBBMRAgAGBQJAu+f9AAoJEJ+w2zLAJEC4xdsAoJ04H+wNbJme7WwI9Us8 -evxIn5kJAJ9LfJEm+51bUI7DOXJT6psImsJCTohGBBMRAgAGBQJAvDHSAAoJEAQy -NusQcxl3wZUAnRkgh/wGV/zw3wzdo8E+EdaWPc1wAJ4mZiCPqUB3BSUH9rd2d+u+ -BbzoJIhGBBMRAgAGBQJAvmOTAAoJENTl7azAFD0t92oAoIOy/FxVQ+auiy4BN3Pz -Gy/g/AbIAKCtoJ5oi6x4hgDpf8SS6Bf6aUktzohGBBMRAgAGBQJAwjnqAAoJECje -rn8pmC5ama8AoKu4Ki5mecYAwouougLSSeAq5CArAJ9Lrtby/GsbISGFnEcoewFT -XLBT2YhGBBMRAgAGBQJAwoYfAAoJEAG0czTg1J6ZqbIAn38nft8G8lTZPMnvxMWq -oe4fnL0uAJ0XonpIpYXmC8pBs07zKHMhHRBPpIhGBBMRAgAGBQJAwx1eAAoJECFP -aEFRX5t0f60An2epDZG2LkKOvYAMAL1oyX5SqXjFAKCGF5XMFi32W8PNWAzNtS5m -WsOYRohGBBMRAgAGBQJAw3qEAAoJENgO81qLtSeviCwAn0fp1XLid06chXR8B/re -HoiU4hB6AJ0YkQAUKmyJ0l/Q/vTkalVT/8t+yIhGBBMRAgAGBQJAw4AXAAoJEHw7 -eXCIx8H3P9QAnjMh2Wva4RdY6J+mlgEE7MtWXg1JAJ9M2PqQRpY3FViNs9q4pUjf -wsI6PYhGBBMRAgAGBQJAw7iuAAoJEIbgDQwZpC0Zl7IAniPb66tBzbxIBCyv8xS3 -QvtFz3/gAKCOMNy0VZSJZOohi8Tc9+6k8D9/qIhGBBMRAgAGBQJAxA7vAAoJEMTH -FPoeBdUWkBoAnRKfJ0tRPlsoPxjCtlFLFk+j7rLAAJsF65Si2ks9JL5mW7czkCBs -ZcYKzYhGBBMRAgAGBQJAxSApAAoJEMzf5JsKCsknT8oAnAn/HH5vTFiL6fyRXG7w -n99+Hs60AJ9U0hkEPOp6OtN7gBrLMhGxrolp04hGBBMRAgAGBQJAxZyjAAoJEPG9 -S+RbQwNnv5oAnAgh5Ciw4jPx8P4ZbG1DoKVAx9cAAJ0TI3rj45C40jlg7sAY2+eI -8MnQcohGBBMRAgAGBQJAxirSAAoJEOdNKbgr4W0B9ggAnj7wolYGZhUF6CSYLpEb -xNpUyDOVAKCCUROB1p/y70qWM8yLlzwvz3hjpIhGBBMRAgAGBQJAx1QCAAoJEEXI -tsMcZLkHw5EAnjkKsVBBrpNBCtm9xhbZqfG29tqEAJ0ROiwwcecZ1/5CtIWa+SzC -xgX0NohGBBMRAgAGBQJAx3eUAAoJEB1zZadVgV1C4YsAn1rHAiuPhUphBFCL9R2O -4ZhBgSNrAJ0bDJMTFTkt5fzlg4KSArRwTh/wLIhGBBMRAgAGBQJAx9HuAAoJEJQL -lMdbSP+uKvQAn2OP96Z8s2GUfKazz7FU2v4F3XOEAKCqjIJODOgSr94eQ5WBoqJ2 -FMJ4TIhGBBMRAgAGBQJAyHCQAAoJELdWp4yIKmxLJpkAn3ce1Kwc6z4GTwA8rUWb -7I0iWBkjAKDrLIUgkmBeqknenXPM7UaonbPzkohGBBMRAgAGBQJAyKNcAAoJEBiV -PyxzsCWSesYAn2swX6nYTvVVCp58JTjczFVF1K8rAJ0QsNJLTSLyQUBliB7yM7FU -yIl0iYhGBBMRAgAGBQJAyLWDAAoJEHGh/2Ab+N4PCBcAn0RqibXfQa3/v7b/HbR9 -XGWzZrUDAKC6S4GAEf+67pXaWyk/tnclGwQP8ohGBBMRAgAGBQJAyxBOAAoJEKiK -mrCGSCbDZiMAniuGMYEE6vBknqHX6Y4uR1jdfs9/AJ0RZ6V57LvYZ3kfSuZBpRf5 -4h9OmYhGBBMRAgAGBQJAy5YpAAoJEK/0ZwsPeo0BkRwAoLqhRlOOo9uElriKnCrF -6gQUhwwpAKCBEflRB8azE0RrGMaSn775Epx+YIhGBBMRAgAGBQJAy+scAAoJEBiV -PyxzsCWSZsoAoJT2YFyo2vnSXGpyJUlaBgYj9/BZAKCp5HK3dgYtTmLgezZXqwYt -YDlDDYhGBBMRAgAGBQJAzHrLAAoJEA+AM/C6yrbCutYAoJ1X73aNmCplkCBM0vx6 -cjfBXIdwAKDmmZn3GWP/D7EUwnlvxEf/0boeM4hGBBMRAgAGBQJAzRdbAAoJENTY -NWFm8kUha0YAoKqJTtOSUlZGeXT5ucQrGfX13QTIAJ4yse+BEB/LqQvlVZ8B218A -J+2AzohGBBMRAgAGBQJA0IjSAAoJEPWYEyU6CWW8/7IAnjvGu+qRsROi8B9XxBKm -Wt5D2ekBAJ0R0nufmfGoTYxc/zrsF6crW6wsdYhGBBMRAgAGBQJA1KBlAAoJEG65 -eYwf/4KvD+IAnR0Jsmc21vpS5OqKQpPvZ9OuUlLPAJ9yX4BUuXxnc0I2u0ItKNQA -X1q9G4hGBBMRAgAGBQJA2oZpAAoJEInNSyFgdVnmfPUAoKiGlbkDpEgSGlBuCLSK -uwUNwpriAKCabamq9Estyk1/QiwmJmCskxu8B4hGBBMRAgAGBQJA2wCBAAoJENVO -rkvJmHCx1pIAn2ftKu5eD4gaEieOqm/Rq8GDCx7wAJ0ZBGGGxgN3NaqjJkjgz/57 -o4SRtYhGBBMRAgAGBQJA80vzAAoJEBhEUvomighN0AkAn15RqVp3Z8FtgsL3ZnLx -v4CogyQlAKCXnv/lVsIv7ksIiBomXQMjN8EPzIhGBBMRAgAGBQJBBYY6AAoJENtM -zEsqMNcp1bcAn2wwkeXPMDcc6CSwYY8i0sWbRyj1AJ9CpDYC5zRpee/TMaHFlN8f -tCb6hIhGBBMRAgAGBQJBdoBqAAoJEPS0sMx5fr+rLKYAoIwL4/9doz9XuC3zHyyl -3BEW9YcpAJ4lVFkQvCwfEwS0J6q2UK7/9273x4hGBBMRAgAGBQJBeVNLAAoJEFBy -0DasWDUg6jAAn2cgEkOQm7YbdvVH1DP6KxIA72h6AKCQTIu+jVruJ4NyoWM+34mO -QMsqp4hGBBMRAgAGBQJBuXN0AAoJEJ/yWD5oG2RpPqsAn1IKXzZviWLzWbMATo8J -9jZxqMg4AJ9reSyPyCbWGAI42gikt+VbMC849ohGBBMRAgAGBQJCHNAlAAoJEDsX -vHQqTj6qyZgAn3rhtzkJcMQ0YlnZii52fvGYBiV+AJsG9A0xX4+S+LW1AoXwnPI4 -NpxLX4hGBBMRAgAGBQJCMHVcAAoJEOKTo+Kpqr7rTTIAn0L0pUoDY/Woy5hmbIJu -fBXclSnrAKCcy115cVinF3JPtBjDplHhQEUt04hGBBMRAgAGBQJMUBxnAAoJENDP -lj33wRJlikoAoKfq6ILvwBUJ/4uWtGqT/az70BCVAJ0QqReJbD+b/PECVPul3ihF -TUF0yIhKBBARAgAKBQJKvyJlAwUBPAAKCRB6a9wf8d0oYrwnAJwJq3B47l8AD9u4 -vySDS5nNZcQOpwCfaTyT2vl9grWJb1MFzssa7R6WjHOIVgQQEQgABgUCTS3GNAAK -CRDyrYWsHkKzZ9YRAN9YZZXeOA8wILpNnGw31FaIOILqJ0FVQCXHZ1g7AODgZg4S -3iBoqu5mq4AlGhjVnDkyZg8aPR8utghziF4EEBEIAAYFAkzUkMAACgkQK4WlVyBR -8nREaQD+LfaX0JiJOUTG3l0qT7c8XXDPehMDhEHcjIknOkIBpYUA/0Zn7Om2owrQ -Ty7qGJGPymIacEYwPdu6T1PBai9m/7IAiF4EEBEIAAYFAk+pmtkACgkQaiRjynqk -ZgQuqgEArdtrYCnG4uB+nd1kuzOT6GtN4slPiPQZgd3+TBS/1X0A/RqB/V+bAmR7 -oEOft68CnQeXDk7N5omBICnLkpre1eI1iF4EEBEIAAYFAk+6x4gACgkQORF3NsC5 -x3d0EwEA8oRZRiPJEpa8d6gfCiloqVZwhshj5zAxmUiF6iAIqcIBAJ/3cGtDyxf2 -6c2NfcRT/yqYfME75ucq+WOSqiO2W6IsiF4EEBEIAAYFAlJ2fEgACgkQp/M1s+c9 -ZXWzmwEAuJXbGUYv+CQPRD4Q7yryPkN+UJpqjxHw/sdnXPz9LCMA/2BWYALJ8poa -zFxBb1Al7bJHTZGisdB7sxsG9J6dGZ7biF4EEBEIAAYFAlNjyLAACgkQyuDOvHUy -Vxcs7gD/Qt8HED1QYWqQ14TRNwSX5zS5TuI5CHtCXOehQ+LmkswBAMFXXpxoE8tY -ZkzCTUz4IUsoMDMDmCsKn/SYoKBjOPUpiF4EEBEKAAYFAlFVUL4ACgkQh1gyehCf -JZGicwEAhgRrah5ijv8d8U8gYp2TTT9a32hV6rIUPr0ZraBfvMUBANDl/+ANBqz8 -SOwsNtcyzVXlS50dEHBrnEIWZwoZBq1miF4EExEIAAYFAkz5+uwACgkQa3h7HhDZ -VOmuJAD/ZZv3Sr3d/uesN+O/Mpgj0Ga3bkPaY0xErgew7zGRu+YA/1eULSKpjgvC -SgTrJNyy5A79wIZQGAzjEEVs0wp3xZTRiJwEEAECAAYFAk28Xw8ACgkQKwnJFPPQ -FIhxagP/TqqxYvKTmfJOD4sRuEWCSJBILKM5XdjrI1E933xkyon5ZsM0v0uAyIdS -VUN6bIJATD0DnIJYAc18vrfbu5Obs+aN/65dE+HS/0sUxkD1X54UjeMv6LdG0Tzc -dPWNeWy36VSoN7sCjWlKwc13E/Isu9OQooFAdcquccFhiu/cGsWInAQQAQIABgUC -TbxfWQAKCRDdqEFlPVRpitouA/91ofLi3OA/7s1jdq//EDGszOcWZpGAXoT/KDSG -ZdfcrM1DPnSNQrvT55c4u2WJoD2r6b7j3EPOLWomCnji2KC+hKT84FlEJ84je3aH -mBuvJC1Anh6Sg6hetNV2i2e+C3f4SG6qBvlGpSIj0uLo7qrCvL00JmJxLaAxwDL1 -ozNmp4icBBIBAgAGBQJCK9L6AAoJEBkn0wU+MKc5pm8EAK4+YdEtcB166lhUIgLz -SUgghb8Ntx6ZSNeJ3q9fNTjJsjkm08hPUHrUFemlsBWKRnQza+HRLXySR7OHdCqi -1azQz3bFJz6ULXbBvCsDKh/qf/TtGBNoCl13RcRONu2UkP/CLJTM2QyPHjkND7rS -EzIe8FUYUSMeBS8gPge9F51riJwEEwECAAYFAkDFNjcACgkQq/8HtEbzIS0LkwP/ -d0zGovRDtfzzCwoHHpTpjtCVy+ZDeMJs+DCD18AkFk1I9uF8rLQJ4iH/xSBIbRev -eKNSsd2dPTe/N3RtU2nz67BiQkcD2m7NgZki8h6A2s4fTY01YEd9QKJVb1GNC+pF -ZhieeorjGQw4vqoW3ZmX9hfeuBOtykx1ewzJqcRqaRGInAQTAQIABgUCQMWcowAK -CRC5hZgiTcTn/fnzA/9d/oB9G4eFIzED786QKvyDfvcLLLkdXmmbBB+mLwbqMb8P -lSi19d3QTV08Nilf4M4PmuNL+mZ5tV9d6iBKuO285hfsBkXoH/9777ptNsB4a8po -mqKneFD5Oh2HgF6ST0pN7IULjoD4TLQSu9y5a+WFmGP/AjGTNPyIOH+5jBbbmokB -HAQQAQIABgUCTPKaowAKCRCEaPuQjUaC6Cs7CADIqXrTQLq/DtL8At33n2tZqXDl -XmHj9uB/mfbQg2qVa3+Za1lcPRDknKtL8D487zmdDKvqLw12+gIcqmDxTGMqShye -3eYCZRXp10RMhEG1PkL2p8uDBJkcVsAurjDp75XmOmZS6IKYB1CS+QMUPzWSm/Ly -AtALHwIKzoOR43w7M3/FNYPb0mqGyyHEu7uGWzID7utOymT0hka09nT537pa3kd/ -/7PtQyhejKQRDv1IIKM2mrm/uR6cjFNF1EOWt1zf1r2mlYOJVz/H8Ucd2DHhjueG -+vRo02HOOruJYn9EZBVJSqKyvQvSnJGUFhKe56t8PVLY+UUyxJlsjqFB5PjtiQEc -BBABAgAGBQJPBhZcAAoJEB94i0UKvSoplnMH/1NQ3CopjopjX48EjsEzzooPqcVC -pH7D7+E+fCDJV3ssdm66K2sVViqy8LEmEgwFHv2VT/u6TyTYohooamsd/z2Xevyv -omqCKWgllrz/KjVXmzuWnzh6//SpRh05dM7arsxGPJrsM+7QJ+C+gNOUyDDQ9btd -/V0ql28lP8t/jvYVrSNrRWqegm6IVlAdJHMR9H6DvPHXik9LxSpfUmgxYvgPz4/z -zXXflZytWe1SJ9cbIAf0FOYsntLv0P8nFdeQhKvmHU+Q1aTyhFBHeAXV+xQOo7wl -509xkgv8sgl+IiY82xVx2+IV5+esLCLk0peLfriKzE6CRofMqO9eH0FFaiCJARwE -EAECAAYFAk8JKrYACgkQQrhIxZXd+pM3zgf/ViDPA+jg3pDpN2ZCU0gD6oTFvIOZ -UrZEZF3cn6qTdVyk2iGMoGLJ8IGlDkNc4z4l0i+4rk0TEekQzykDV3YOUZkVwJPC -Ch2vR/5jBQXnrZQToJgi8dSFYUnbzvzr6fWbaOPybaSFXvV8bJt9spu8SjqW937h -VaXe3Ll+5XC5/y8AY+sq4qlrWYh+EY/FvK254UG+8lU2UM5J3RxyZHQE8PgNZnMC -q7Zf/VWLUwcVag/++T9uaYhiDQSGaw5S5Rqn09kWbMqOyfma4tYEV9FSuPPR5gPJ -Q8iDIqsE5nwqUCi/ZPMs9qt90oo6M8YnHEMgpy8Imjq5XzxW+urVlug314kBHAQQ -AQIABgUCT3nMFgAKCRAHJaWuhyFtF41AB/wLTAe43rudmg/QlMpDiA8VcadRFI63 -K9Gj4NQ31u1xxo+l/30MbVhyi21B0RD77vouZ0JviWZsPTsKEeI16+rSf6II0ySh -+ezxDCiIoHa0JPCA0yPr7KW8B1rBwu5Q3pRiBLh6XexBh/NDf0+ZLgnfyBCeZ2Ff -NIrtRgRJNUvdUeWToifqf459tXAvLK4c+hz9rP30194SezhOXUAdG6jFj4b93BUx -NmLLbuG4cH3FziAoddNrAtkPci+vmBBE0f5Z4Majs1mOSr0x5DvNpCTZ25iQkAl+ -iLAXba35dwqKB2TkcpFU44eDUhjCRKgml3mGx7o3bhfF8PCOmNvTr1nPiQEcBBAB -AgAGBQJP+MdoAAoJEPkeD+x3AmlWmiAH/iBE2fyFT2I84EFUdGjEfxY41OPCkubD -d7i2ibyLBai71wGwE7HVln0Rrz3kzgSnhsM8d8ETuScSh9dGA8DGKQIUZBDKGpcW -7Yc309omT13E+JflbWxy2PTvfQ/w3pV08EqFSVwBFBNDnk3fCTyEE1kitaajU8UL -lKkPbd8nETmPl5Z3MW79nZ36wE8DbnhYwPbHuPfJuc6Xuf11uZvvjydeB1+jxjYu -Q4SxzHDP47qfeWWJQYJLzebalP1IsUATc4+bWLBiHqXf208vbUHq5L57uBBcdgHs -hNAqzfcSjk5/+CeTemnUzC0JxbFXgBPsnpGO2/DsP4+pVpomu6NQQfaJARwEEAEC -AAYFAlBhNsIACgkQL96Gxfmvx54mLggA1U+3U2Z3MNwdtA38k8EsuBulddPLFUon -H73ZmSy15p3+aEfywf4bq7iOcvw49pt6RdvuqpvsdYCh04FQW89MnNEljP9HQO31 -qPYXGd4aWF3Y3BZyuqeVReEdFF9fq/s45W9TCkkug7YDJ+BkzUhMVJtMAviK92S6 -mOPi9PCuHJBd0yMuU2mFMlGD5pQXZfLT9BpXAFBE7PWG9tvHsTym4Eg8sF52fOd9 -wrzIFQU+CvuQdoEzd4aaJtBErJjNE4UISp9kZheuDcqZRuG42IAgHMYy6N1CPUl6 -wpT41sZZYCtuC6+/9OOIPyLaPAMLjsFyEJmD//i4sb7Ha8bUPkaWKYkBHAQQAQIA -BgUCURlWXwAKCRC8igP+iWp3viYPCADOYAVfIKsjdBMO+dLrj8yIkUBvraGcJZtS -fswefd8gywsOXfgkEqO7qB9SWZPXKCtgcu7SF9QXanwQGc0evd8lVM5lJ7FfdAfc -2F2QAm3xPSCPTGhopRL9eB1FgJPWRz+gDxEZdyTxQwNs7Q40vts4O26ljRc3nqHu -VX3h5n2H4KMg6tx6Rwes8+LS4m/07FLQ04Tq6Vnm+9gDgt7kduYIjtp9jUD+0kk8 -qGeOswU3nQhRKqwDZQix1M24wEenvOAx7nYLP7HUALlEOl2IbiCkWIgCQPvavKly -/wEjvBdNPWWG9OvSQ65HMszTy9s8MA+t8+Y2VQ6rMbpEnynAb4kmiQEcBBABAgAG -BQJRXRxPAAoJEHNBXUkAh7Wza/8IAJVSFMqPARHUT3XBVEbNcVlNRGvLYy2VdAL3 -UAWBBON3o3swtfPAMbqXWnR6/fDEk+O1SEy6+DJP47NZ33yPwz0WoYzGalNqFmvx -umFnpRWWfg2AhYwtUGxc+CqN3zuGIzHPpkoJe0dNglvn0GqtggwA9pd0zWDd2UKA -e8f7SRcyuQZsuKzYbPThSogK4AmiWiZBGcUHEt9mP3O/JJVAkxujbtrxa/MH0sZM -IPaA/jHcYsupfRxXgvbN1DWIwSwqdb7iDjcKlLdVzhxSZG8tz5gf2NWqG+c2Zo4r -dDSyCd2fYmfJa3UiMlxZUy2dlKnQd9tECCalIxZIcl1qI6MuMzuJARwEEAECAAYF -AlHPdwwACgkQ5IF0TP/bHMzdKAgAluQBNdeGR9SL4x5lWGZLIysvbdGy9zurABHs -q7ZAquCDwYZYkAMdcpN1tlYImT/lYqQQUw5A5w8dh899DK0EIBOztjHCV0rTz7nN -+c0j067Ee3eP2PzCCWvkwaZhL0N79zJfB2AhMYrFQ6bXtg6IfDFz9TS6Av0l8SPC -2KFeoTgsjqWIBemtJiHn1piVKK4zRIATGPQjFdPc9Io52iKXALStpgw7b65yFE9o -D8TSBG8C0OzUnp+f0crC2ltSecxLbU9/cxZ9mIV/CS6nmFMzArHYmX9ma3r0wm6a -J5NHLotOlAw9XENgtpxDzVVPJn5nL0w9O8zzspUTiJiGdhB9/YkBHAQQAQIABgUC -UhEJ9AAKCRBQaINgGVqrUoErB/9oPF8lziBJaAoVCLlE1IHot+6I0SPZb2iQijxB -v80urkQAwB/GfwjVk+6gpMgZoBQZQLTKfLjkxicqV0NsGy5bHeuuAasZoFs08Jqa -Ha02bmf6ZFAAty7ACGLh0sGgyv4PjikTbfd8bCpzR0Fqr6W0mSDkHh7BBmEFxD7E -/x9m+8j+jlH30lojLbHGJDz72bkifW68i98MCfLtkuQH+XKoBda29fZcqGH6V3qI -CZZpEMiq6F2gqAguhCMS36mFalxxqqgdkIeaZZw3GVKFcf6afWjYC61TNkxWqPig -+kUgmRKbAU3Oxy70bJk125pZlXhV+oF+hUelCguk1pR5702KiQEcBBABAgAGBQJS -T/0OAAoJEFBuExZSGqQFLX4H/1JyJDPMTZYB9acXRpvbdOTc5M1xmkJf/K0NYrNT -dAxC8TTanig6a81hqtiA4fGkOJRJfw9u2ZBrBCLXqawlH8/ZnUV1LkaeB9o3qik6 -9WCCcisA8jGdtqzMXWdHQr0HPfD3ChKtbQrcG6Uku1jHXBA8Kt1NfKmBjP6HY2qA -v430OJvtkOzf/X1zf7MrfaBFcTJzMN3zazkFhJoDtY1Ead9P70Qgu9baj2431jjX -VweoaWuAkwrNcObl1m4RHk7IZFA0a6fu3zTnsrRBjAJyTLGOEBsjxmRmzJb5ZM3l -q2Z2iv+2MzJRS6F+pBbkqk7v0d7W33ILcHeWHEzUNF1kcYaJARwEEAECAAYFAlJ0 -ViYACgkQT+kYsVT7S+Uo4Qf/T8uCOdUztQwWJyhyX1Y2tiUvo1VDQ7lOFPw+ZIrf -QzJR/TZBcRQyDjuRrIYPsvaNnUk7H5wJ8ZkS1USOn9MPOBeb73F2Fd2L1JoQyyWw -hLYCRXhRKI9Zkkyl6LDR/d3Y9+lw2OMC2iKGWfVDkXyPYVaAO3O/udO1JcVwbLLx -VVv/SWr3+K5/Oy+Gpa5sbYLkmQ/+L/4e69a7zdfdcIFmTgpfLthCYudHANdOw0NT -0WV7ocLCUMVsdLqPwwGD0Irp6lmumazvBffS9OLdrWp5cj7ZLIiGrfvrLFsncA2K -tLjEJj1oKHRdjxlTgXo5yk360lnt2XG07aFVOGfI/6lgiYkBHAQQAQIABgUCUn0I -ugAKCRA7zGVyYJPSPIfqB/9yN5v6i3DawO2msfWZqOoW4Uxznyje628jSv9o91xk -we1rumeaB/ZpKTObZkKJxGsXm5qoG7N7qaBUWe5uCjEhN58FDKjzqmxZ+qHM1ASy -i1HOZ6dd/j1n4n+fgNOOQSoHXjfeWmqXxLJk7uLa5DeKp0XQ4CbJtXmRBHyPoQKn -1DNbmD2ngu67d/NhFJ6HUiIKTgh17jbtMV3PLopdKCxetiom1/SscnAXqYHLqLea -tsU2iNtDICgJF+7x7pRVOmGLtZXrifcrz297/Lx4uH5/D9K6yBYuxdrQqhg1RNBE -o3DYMrXZEBnhFtA4QL3rwhPWBU2KZUiUnOAwquFeaHcLiQEcBBABAgAGBQJSuMga -AAoJELkWreVotTPl91wIAKu5GhODSHZ2S+ApSB6D64KIrMHaz50m6WgDVlNfkQuz -Ua+I3vHcDvUNTCXbyg93Ocb7j32PmSuCYE8CvCKi5V+E8soyyYK/oPzsAzdm75wW -P9GX/kkKTpGW425BD1SXBpTIsADp3XnHUEyUk1n4Qwtl36ZseVf9AVcmGXcIvDNc -nn7XCLztOj56VvBZNO5Lp6bR076Opuegkfv/JQms5Llf00yr0HKNPdzXR06uBewZ -LAAjYWuawP2Xxw9/uvTMlJcJNNkpU64e6pNkErqZrvIL9hZDRSldCqkebK5OwBMT -IDf9M4Ja1kcnV6O/51hgEcPY1BRHLDMyWoW/N9kure+JARwEEAECAAYFAlLRXEoA -CgkQa7OhbbJyUSzIngf/ezKuh2Lo+NER3isacN5DtbkEcb+TClv9X28tRjSGyIVw -SRhtPeqEppDR31ibn++dDd8YWEXmk+d27JoOng9Kq8eISY4EHb32swFyTwl3D6GV -lGUxpaJb6BAemAyT012p53zAfDUwTo68qI5baL5kRgLkOl4wMFLqIDGi7hIh8Aeh -DPUAnZZrXrPGGcgxVbJg8eVh52rnsej9lXQJC502g84JQa5VXegZFXnj9PDhPt2b -s/YUfoaJBHJXIqOS1JE7GGPUB5Iuemk/38NGgTZOAji7bovG9W9ZxitpF/ZDK6Ws -Dek2/onQCSfq6H9tgZsjy3Ed4MBbthbbasS4sTx42IkBHAQQAQIABgUCUtmKJgAK -CRBI64stZr6845UJB/9cJIDq43QE4A1h2oySkL7AP3QArbY5hKzO0gPneTZYz4uZ -ZyZ+z4QqMJQUExE5kpc1Rt5dL4cHp6dQ6/4nZal0KnR60jHk3D+QLHW7UW5Qq068 -Hv0hXkBR2P65hDotHSD7S2OKZuufUIkBaHMNhLBOpdOVs+jIFRKHJAOPjS3JH0Hf -SprvJ/3IjTAxP96TtOFwKwvqrIPPdJ59ezH7iA7aE9QbCokhD2dpD/4RJgwpa0CY -yiZp6NGStMN9zytMmOVCu2kXi4up1S35wMY6i5QMbC1M6J7zIVIB0O16MWzJLiKq -UC6OdbayIkhoN6SLKX4rTVdy3u7I2ifpyeJGMBbOiQEcBBABAgAGBQJTBnZcAAoJ -ENgv4DzFW8/jcQIIALKV+kX9NBzdHgiBaDdDGkieiSzyzcw9mCfuCb8LhV/vQxcg -Ky9b4Ey3uB4I5ZJGND3gEcsTvfKWQW0CujssIk2cP5fKNljHjDYVlFu9Uegv66nU -MpT8rRLsCL7W5KuF6bG7/XEgKYt7q0NlRXROfCTOM4h0gS5qwfLFMjHoV3CTu/Pp -sn6JhzAEYVjDcywjkPKoY7guKYm1E2ELdG0naGbKz4CPKLL6p/XEUusQeUfDJAaV -KMY7bl4R7XDiIePDuTN0A4oexxxb+iMsGbcXZLmCumJaSQEiI9VgYNzw00Jb3ND9 -93yQbcPL5usRwacAowR4k2HimrW2ei99DK1pnNGJARwEEAECAAYFAlMYcWAACgkQ -Hv1OFvyDyAzV0gf/bMGrTvxpc9xdqTSP1rLo9/TNvbh/P/jRR2AaIjp2vWNdn1+f -8KGLH40jCs3awS9ak8ZG0xjr9ZaqLuYJ0aOFiIdO+bKOOB8Svnp0ufDsELcojQzP -TfD++Q82F44tEw4d5jWAHCbzS7l9ZgRwGSjKOLFskqHsNh4PwGAY5r2PvZxw1R2x -7l9QZjYAWQe7iP/qggIuhlXIsAFse1zfLXMms1sE9eAaqIH7g+ushnq3yk1yR091 -vY+q54C4OCyHo4pCaJKQYp20HZT6zPM6m2p1hBNt3/Vp4Gq/jDT1EL4k1pfUlYBl -PYNP+yyyeyHUv4fZ0D4alc+vPeycBIKrXLVXhYkBHAQQAQIABgUCUyZVIgAKCRAG -J8qFA7M9mLfLB/wPhL/zxd8j/yTKPOHoqSXEW6cmNzgz4+VWAMlNUAwWwMd4ABqX -UnMvWMGtiCQDcIGszcPgQj744Bvp9Zt6JNfViLpZzrpKeUKHPA0cc1fGF9Bf0FTU -i5gfFI0jKX7joeCSJnahiFxjRGmzrsotEmdp1sEQFJbsz9M3T/1HOLglq4520c4k -zHG1KWFRYk6nfYwQzB7LAiA9Ag9Di1PEZIhK3jsEQUaXlzQnQslSoaSuEDZROTYY -0DkTxiTynPjshfeBY7ssrubeGRwZmu/wOgQCjlpKW7Ld2JYPOBk/LC4/sLCguBv+ -hdjFnUAjtNIXjTbhhUUrYpeCF9IxIdHJ0DaMiQEcBBABAgAGBQJTKM8MAAoJEBoY -Zy013yCY4ooH/18y3K6wUNyE/YBBqef4R58JBVQwWnA61FS9U1xHO83p4/s/HHnU -X3P3lEdBizD4y3OxfYang0sswD5ewIyFqaclkvlXe9l/FCKYYoucof3icSrxkRRG -sq3tYnsugfULOAAAh06LxbypvMOv5WE4CU5vAUDAcuSzcc0cOvad7VbgKtAhKiJa -iflb0WKH3Tk6X4PQHsskxfQAMIpL/FywSzXJEK2YvVC53sqDDY0M20G1EAQPqR2T -3OGRBKCa+TljIDPTB6/1Cq4ePT1PkQSxaEC9MEcfNJ+vsMj+XM651UuxWd3HwHWB -/ytInXecIkbIPP+bzE6eQbL7ZyUyzL3rXPqJARwEEAECAAYFAlMp+WgACgkQyBQR -NuwRGAOdKwf/YZf9NQYniDlYx7f+fwGM9pe9xAnXYj+UYxVD+guAPmI7lDegFQpn -pciMxmTR3ja8nZtfUIKwra+Y994+rKFKIF/dCiKOYCI00DOLMHnGv4R38QAj8MfO -ujbgCNwShDA58fWGJCnvL3rSLQebSRYapCRA5uIjvEqvJcekMI0eCvN+avQynnW7 -H21TjFx7aZLCtbmtW3h3LpZzMyPv2AdH3jnsmS5fuHIaEVybZZYbwh2HV639+U++ -Q+4CJnSoXfzZjrDKFL1AgBahL8BB5AuUKVIKoJb65Max1VW7pvnlqsbXDNUFEKlI -jyjZrkoNl9HFB9OEPup0nNCVxSE1vNJ9SokBHAQQAQIABgUCU0oC9gAKCRCAk03X -+Kot8SiIB/41uY6Gq+s2lDA2J3CMPvlmwz0+I6B1OQyjMaVDgwJiw6uVHSiEGeli -3gwHQ2HwM3kbtmGGl7mYYJQFEVdroVCa//vYof1zEFEbpqmc12fBLn+tu8i16/3o -7iXTQiJZoZsqOTkagwo0Z/gMLAYoqpF7cRhYA8zHBWKjvFIfB5lsQhS0zoBF4QPi -lXCgq8TdAEjvJkKf/Sk7jrzhjD7lQpkOcFSlkJFSAwwpQPkQ/VDPI7Hv9+PxD13G -QErWw24mQSSEbupYloWJpC042qN1DrSdBAjl8EnvyH8FUQhM1cd2CALgU3G7OjwQ -ctHNnRVXaXmFVunAq/K9gWFFPkYLlUaciQEcBBABAgAGBQJTZdJaAAoJEDJDq9I/ -hmlgOdMH/0LVDnO/leLYuOnX2qdzxAfsO4W3UoIEPC86tSxPNpdPny4FGQ+ZggsO -no0KpA0L0JxNK+y4fuYwPNL8IhIdK1ErrNYbGW1aRqQPWUWGeQ8WPyL8vv2YCCCY -PcWhlGRNfHS/Nma+iAXkxLQkYaqYCh8k4g3p57Q7DWS59+84+7rsaS1BjNDaj5oC -e5tPnywzSwoWzdX7A+yc0awMWm5kghE2plNguNyY4Kwx6i9foC1Vvx657GGulMnd -nNNoe+bkCnQ3/HUuXE5OioGaaJsPC1J7wnzI7LqvUkCqA+kr+ojx/2d3uSiH2GQh -G+aHpoAlq0vBptQvowHGw+trKk7WdbiJARwEEAECAAYFAlNnIkUACgkQsY0Yeieh -njhmUgf9E0Dvc4mmDpl/IWifqgFC/I03gU3DtwH2/m0WkNCUMk8Ha8i8a8PvuvYW -b7wKQ2ec4vWnHaWLWknggan8WbaVPAQXBky5af3uODKvSAwsGFQLv03CVIKaBupX -9FAPOf2WoIqhaJNyn95fwTghbBoBSt3cdKZx6hH5eZa49EwUxTtzxIw6hvjHU//p -yxIH6H6MwaC+5Z+Qkxc57zWmi9V/6tvpTNfGOwSNBWD08p15LLu1aROQj270830h -EUM6TexdBHwYQ8SIBXjmY5gY8dBC8e6SqBVSCOKHj6fY7oMr4IRQlIgy4VkGqEbG -80eGrVrAgQf+pbkTPyDUW/vqHylS1IkBHAQQAQIABgUCU3QUMQAKCRDrzw4CY2LF -OsZzCAChqp5sLo63oof1gVkJDrFPJBOkhZriChTSS3eSJfKAyQzIxLZwdilrH5nh -Zht+zqEWipSJ3eKQ6GBREOYWJY8vjzJwDKNxDICCPGnadnCwr4NjoIaUPq6Datt8 -VA6lV/mCD2TO8VItdiQ2lYn0arCnKoQE/Kl3kOU/mthFMnqkJa4U+wdPKrVg67Mc -scPxvHgRwHMHaIsWe7JDdfVIa8iWaYzzuB1PSMSdMGoB4Ox1xfdPcNq27CHShaaE -9DlrDxfeTeyJu9EihhauFb+G3ATunOJAZyjSj+qL36TPkh/ubv9eTFvd1sXTADvh -WfNCawk1fdISMJYGkRG/rT2oZjDgiQEcBBABAgAGBQJTkl1PAAoJEFFboPfUSdNT -Od8H/jUx94m9ZegBBgTbW900kiRrqw3Fv/1DAjv/rqcn7jrAq/gEk/YbkuJX4fP4 -vcUQbQ8toAF0JZFUiM6zfNTupK/rw2i9OQSGhUfUJalMH8aCSvXGYOZ/A0Jsd8ow -0hoCNB/S+i8l5n//PVUcWXxX6cDLtVOXpNJZxJ02sCQwrKFk/HzObWl34yPP3JJ8 -cOeJXGh3aOSmujo74CVoUl723PRJlLde/Yh3sjtzY8hhLNcAbiBLhQxk6KkyqZFo -rjxTTjctclI5GSE8GviPFvg2YV2fTLOXf9RYq2rAHY6BCyySMnYVxQwzb62mqZ0A -4PsS658aQnaJRfZWffRk9UuiZIiJARwEEAECAAYFAlOW0jYACgkQa0Gpps5djz9h -FAf9HtrfnemrsfgJmoGbODcUNoqHo8GGaxT0sq7sRFMIx5tAINXqjlEgmO0/T1Kk -lKfWrEbK5/LrcsCrn4Nll/vAjvGTjuEi+pArLa7+Cmvmglyx24AtBYdhfdp7vZwd -o8IwkGKhcHLokNaKbJwAgkj3M1PHas+vESUiJ4gNZ7801kq0qSj7FdCo+OIZ88xM -jKCsC471rDlgUkMic3HfCAdHSLtN1zy0opfhz0k/QdmQV6+lAx+6CAiNPgbQZ1Pe -uFfO/O9XjFJEVGHCwtiLJ5qyYI2elwtl3wC1NrLycxFSxCcNlfhw67TZF56FlKBW -N1wcAkaTtjB6SzBuehdBoKpdEYkBHAQQAQIABgUCU7kVeQAKCRDqxevweqnCo1/1 -B/9EJCHPmSFTKoD5sNBodNA7n8LkCFj52gPNfpzdlsrKJ/qwDLERgdesPxXqLUEk -/iltCvSrNh2gK0K/S667spmvDgvtphTwMkRY6ZzNDuBn1U7Yfes4RdPN4B5JYkBN -6TmwnzIiPFntWrVKuVnCXzPKbY6Npal5a0nzLoQ742CFpT6oTfbEz+ah6ATyHtTo -lvONKDdv73KHgaJI7PINEJHKMv7C4SJiaolhtb+Kd/26SPyiEW6BDPUyc3bblTfE -XZozmmYy6nYvFFJSvr+UC4CnnQt9cAln4ldbGQ1wsAd5FqhBSyteAxlKQfj4sPtB -TG0ItEcEKzapzdV+nodyw0LtiQEcBBABCAAGBQJM+rOPAAoJEMqH6egqrDPxgNcH -/3Uom5ks6ytzz4Xxvc80jbkw+lIJhsbCD75b2K8kzyaD+NXUBdCyd2Q4gw4jUKun -Y/VKrkI/w0UAG5IXeLmWEaWQt9Z/lJdtxwWMhIbErMm4yFCpqgMMuev7Bv7zDB9R -/zn/vE8YLHjLyti1GcrqWd/U+CQRF9CiFLyvn096/o29zf0yKLoo+NLDNnY1sdgV -rpaoKNLumye+c5+kCMruVDC8MQ4Ii7pLKzRCIUqShhBTwudC9hgIqpsL3jvMOR0t -YMlxbtyX9Cuym/6B8RY/yUBjQxTjobt7Ha+HvEIBJbW/B8H2sj3eWH6yO1KhgeaE -jgX3v/J3DM9DdJYQS3Pi97KJARwEEAEIAAYFAkz71XcACgkQSWvDOfKigluiTwf+ -KYfBd274MhSr2HhjYwLTxxSqCTl/S0s8hCcgKZNl0Zao/Gei24oYGRMKYG7ELEEq -ByhCENT1SLZ8I0AyAzNV3PKj5MH9zhNkXx72B8KuU+Vp2T0usRmDvcxwRpQu8yE0 -wNLGtiec8CBfA08ANhy+rpkaq4/f1pb68asDOP8mOGT8JH0zHnV9cjbFmOE/dIwv -jSe5aQvEBSjKG1Iuc/7DvhtsHOx4dyyTQ9LkiHu+hnymaxqHpHpplh+JIjrFO0hF -vXV1+6GFAqKwUJi2+odUbeeLVPwCtfJU4QwD4TqWQN9ZagiBw4NVUUANXzntsVHg -Onvm2H6Rw+in79Xx3/USpYkBHAQQAQgABgUCUkBX2wAKCRAQQJtbVFKR6TwPB/9j -o3Mf9WcZ/hnjl+4uJzUgTB899FLl0BIKBFlSM0pYb14WqxkgkUIRi59JXSce0YRY -EfcFhldUwnxSokLbKWpQJIKipMn9GaZjgGaXHULpEM7ZH/cEP0GJSYCdAjZG/U7w -XNgajdmdJ9Kr+TSXJ6DX3fKK/F2EjIq7ipJwwcqnxuOWuVjjjqVL6CIjJ8morWmN -QZ5Xs+tXQXUeP8TdeCUSqlJ3GKxMPQ43nMAaSRcP4edc0KYIicvgeat5MXixXzbX -VVC+B72lejCHtyE0rLYiYOIZRBHURmk3GeSJ1En7DcpaOSwZLLtWB0siJZ5DSWEE -OoYPE9MEocRXXrk7BPnSiQEcBBMBAgAGBQJQzGjfAAoJEAi1oPJjbWjpnCYIAIcp -Vwt7Wj98/F8n7sHjewn2QfW9YnrvrQXGzR4b3ifY6Cd4xI5BkHv7Yv2dgK8b+bl9 -PxWGhahlsdGw3XvNFxF72EkWzvNTNxT9C1ZSJ3eWOp6migOpoBW90Es2OTh/XX6D -6OgNdwVyDWg+bNm6s5lERKhinFm0eIn2CQb50y1VT0UV/JpTHGHa8V//noGieBb9 -9i7mn10xY4o97Yf6O4zBcueSOh0fFtrrChMIlfVWn7h1n5T4F4NDddOFv4vMXYbh -c4xdaGu/iPwO92sezCX5JhOL6txcMiLAr8WBssrkpv8u8Db8CFLfmlDnQ+glApHD -tXPr9YbqAY611pI68JOJASIEEAEKAAwFAlOzY/sFgweGH4AACgkQTXIGv02DmGmT -Fgf/bTkRu6TL1Yh/cibVlE00GqDf+zOOMFNiQSd8vVdZcg20ieqDKPjwt2kLdmVz -kXxVFYYbCaR40u06Az0W5PEw8av84a/yBB4st3b2sUy8j6dxINfTd6hFGMIzrCE/ -qumtyAaHMsgUA3J5RfIWR5Q3GPSlWQzwm8YiYlFhSsYsuzSK9URx6c/2Xa/lzk7h -dX0hUSHp/z9JUQaZpttfqL694+eESbgQcVLkGjH0N/x1yPX31v1xD21oqA4HMYCW -OzfZFPUFPlFDuuZj61XN7GT3QM20hEFL1bvv4A/bbjXXwjLIDvVFVfk3GZEXLFl3 -4IQ1hpRGXV9okdw84kmLACQtXokBIgQSAQIADAUCUVyfhwWDB4YfgAAKCRBflRkE -mo0MNgA+B/4tOtMohfSPByGw8zu/m0yvT6/BH7XOTDS/hcor6iv7VHt9Keqxr93+ -KrFf9DvGVnmqrR4EWo42kGKIYctihgFKa/9yOhcGlL3zibQCArC72JGSNRhPbY00 -dUXa5Uyl5gOMbeQw9qlAPNgSAvllNSNe9f4GdSRcOaAthHZpXsLTAh80ipSP2yJP -2GB9kc/MbOGy2/fYnsHZDLQcMYzuAzYD+A1QPVn4hoNreclL6s2eTDA94E1kHtC2 -6EIlOPLFms/RazFvfxuaJHNzTGvfMFEQjG9gnESRTQBmv0Ujq/V6m23KAkCPuvX1 -c/INat4r6fGroHJbeq6zt5kpTrK7qP0DiQEiBBMBAgAMBQJPbFLUBYMHhh+AAAoJ -EG+Hv0uViH6PlccH/RrgalK4LmI19GI8gAn4cb2fdlAfTdky1HBQMoQ3SBsfUw0X -FtfVeRh0xTS1CN+jdeDCEDUGTc8TNYyk3//KCnUOFJ703HSyWIPMUORs2JiXw3u1 -NU88HbClCwbImXIPtMSkXx9d4ZR43wQeuuWfSa5ftGwDRRlwse/rSr/T6FPOYbg6 -QFHyi1l6qOSVd27r+cLCPaY7tKQ2BzOPAit/kDeDjRT3ej2pl7zywjtyAjMyWDxn -vgfy1Q1Moy/YNvgA0brj6iJx8Rr+Z/GsYhUFvt3VBBQUWIvkxz1VFWl7w5r4EXMW -pWee+MuBMg6tJ8Y5yK17K5ihyrNwEQxy/IdljnGJATQEEwECAB4FAj+ORtUCGwMG -CwkIBwMCAxUCAwMWAgECHgECF4AACgkQQW8GEGP+5lmFDQgAjifluZyJa12v3/QX -Y5+ExSSLNFgJFT1XKLfnso5l8QSxIqCx8kCCr+LGRF5XXvITuj3JlA30Iu+czl7B -PqPoT9Xw1iErRHd6U8J1CC5jPvA9ac510bLpGtHu5liv9oUp8rC+Y0t4MZ0mnmo4 -DqN8T+vbg8ybP2Yq5jBEWfMuui74y2KbRf3zhmmnhiYOEXJHuG3IrkyhgrgEAIiD -HQ3ysTRITHkH/zCyxHujhGXh8TfiuTTWwnS439Js+4ONLXQZRddFkjybzD8M1Dpe -5TRojPhYGcXXFY3d696Md6EQXIST26xswIg4gTHHi1RqBq7YSYuYs2AuwGgIEbJ+ -Nx6Y4IkBPAQTAQIAHgUCP45G1QIbAwYLCQgHAwIDFQIDAxYCAQIeAQIXgAASCRBB -bwYQY/7mWQdlR1BHAAEBhQ0IAI4n5bmciWtdr9/0F2OfhMUkizRYCRU9Vyi357KO -ZfEEsSKgsfJAgq/ixkReV17yE7o9yZQN9CLvnM5ewT6j6E/V8NYhK0R3elPCdQgu -Yz7wPWnOddGy6RrR7uZYr/aFKfKwvmNLeDGdJp5qOA6jfE/r24PMmz9mKuYwRFnz -Lrou+Mtim0X984Zpp4YmDhFyR7htyK5MoYK4BACIgx0N8rE0SEx5B/8wssR7o4Rl -4fE34rk01sJ0uN/SbPuDjS10GUXXRZI8m8w/DNQ6XuU0aIz4WBnF1xWN3evejHeh -EFyEk9usbMCIOIExx4tUagau2EmLmLNgLsBoCBGyfjcemOCJAVwEEAECAAYFAlN7 -sEMACgkQinL5E/UMZNojYwn9F91u0brBfMNVkJ6i094jfc+zMfibW1WUu6n/TYue -W4nzreR5IAvArp5+I4MvgJzxDYh2d7mgZ9mOAM/nVTI4dNKJb9kB4305BmEAgM5O -ZuglekBZe1lzPHt++YikkO67uJ4ahE6fuDA6d0HdArQ63dPEXC4tGAQQIamBu3Az -hGcqaG3jtvHsniH31v4ahJmGSu8KXd3vaP5hAhGP9j7eRzU/JRApx7W6hI8jvCm5 -Gl3kaWlMpBIiqE7/ahmnflb2TYZRlTKlYJDmwO1/jXhOjfc828ZW5PfCFmtAheT8 -q91EJtYJT+PTKxSHtqFY4kz4C2mSOYb/TB/RhxRkqG05BYXPP/4NxH/5MRsOTpaY -il63A3h5vF4dB4nBgSEwBw/dH1ALuroCLBXbR81PvdphDmqcgW9HFxdiJgnJw/nq -xEKJAZwEEAECAAYFAk/q1KYACgkQCQZoeE3rZuKTXAv/bBiV/vtdSMsTehSMhwvx -Mo2Xgq7/c+nnVxeLoPb2ZqyLoYE5Hoh97Afn6MdUhVDPqyUZ8XJUensNlEOadvbB -tyt/jli8FD2L+j1c0nk5IKK7XYfgHQQdAJNIPYSHFNeDRfJnfZL/7B/MP68KzIKS -1WvYYLwUCO7IXa/gFRaHmnm99wJWmiyscmHgrBTZJIngWFQSHHTggNfk8ezviQ/D -fcOWXPL5hXzoOpDRUSCluQdYDn6eUVmPZ8zG31Mz08dFI25ouInWzruJGK0haZsa -xtdDyX5kX6wUVZE8/aSX312QyKlLANceHZumOiC1RzYrAyhtubyril+UB8UIV10x -Fy/SSpuxeiHHjW7Y24LKbl1TalDeMH70gmIc19W1l3JOTAn34V9Mnymz+HgVNpR7 -h3D4z0Mi24A96o4muaemiobGlf0KKi5FkDyChO5MLmUEthyWy8UMkG1cSJMZXZ6l -yL0QBMy1wlxMUqbUxQZTeyYC0Xkqo9MusCZMJLrnRdowiQGcBBABAgAGBQJTf7OD -AAoJEE+jjoIuT6SPTH0MAJnPRAIP0AsdhpiAwQV0qEyATC+eCk2DDsqKxepgV2Hk -BSUPLkYc8YlPpyBBUONkXltmf86sQuzPpm5HfdhdCq337YX7ZsJ1gh+mSero+m3u -+Xd50KCE+0CtpjQS4COvgVm9TlrctGBmVCbjka0+ZQ14gd5Jox8KYZs1mdPBYWz4 -yV9Tud4Ge7Xe6CPmWtNsYEMDPCP7IxZ7uV5jqLGkK7504vNYjxPnYQh1sFfMcFZo -eeOnUKzJ08e2Tng0QbtTtuKSBu+USpuE/uHzERTv69hTS9kI9ZpwfCHMoeeaS3bo -LONbIQoVAOL0O50v02ZzYY6IQAuLoWNWSF4tSefD7Ppw/M8SJ5LrlREJdnzlRA52 -uskhJlxwZoE0Q+RB6GwKvWcRBY22asqK6WQb7Hzk0F9elWx860LA0RwQ+Kr4BA96 -++4TUO+ku0CIc6y9nGz6SVEqoKHxbizvyHcjRz8B5IJqNvaH5NWkY7DlKn2x51QB -KRPEXTPELjwpZj+B8WyqgIkBnAQQAQoABgUCU3gBoQAKCRBEKQe1iN/EV6pUC/4g -BFmu8UgANzDmxaoNve8NbjQzyVqNRGh4sJKIGzXzx5p9xo474frbOOtglJTe/S2d -P5mNr2+BGPRtzjnzJDXNADPBSLV7aliNJz+07UZnkNGctOFv2oYmnqlZoi+4t6yY -krjdOiSKissZUqvrD1Ti6roxxUyeV5EokA7H4Adm5+xUGegVlaA2nKc+ZnV0LdJk -NJaeyLn9qiPT0wYInGMM3Ndj9qfNciBu7jfoytUPfi9gmCj5lah4G0A7tu5x6tzx -OP0p+FrrljtiivAC77XmzGkLxLB3M5BYMDgaA3gMD+EGkkREhGWApyVo44pIm5p8 -MW0gGkbwzx0hzjwfVel6kkv2z9y15G6Yc4rcZc0p8cGxBy7WG207Y6h4Llu5OpB1 -YXqKuhuiWlXR17WSSbJtYFb/QIdEnFeLajmaJ4PxaxKtK9AThiDG2gDFsbZISEw2 -qjJRrbZGkc+2b6mauZW0nX1uq5RCvrkeqk4eBUk66tDacc3pQY1cNJ5yv7fz7HKJ -AZwEEAEKAAYFAlN42wgACgkQ8u8vRwaei496AAv/cNeSI8z57yt1hZtKb/BQI4m/ -KJvbIMjuQzn6YEIf5IJ5BdB0A7Sa1vRv8eXDV7Qbm+RNHLcxdxu/BY9QC3rWvW3C -bXRpmpyjcNXvXcax7IBabjWl7CO9vllGe2oJT3wb/0Em6pSUSdSvo2Gg0Za/7dW5 -MKI6dJIreSAMzduGNZmPxZRSQX3dSDnfCEB9XUuKefpg3sgn2m3DaxW0Pf9+4CR+ -7qLcXNyIG0nWes8tWnkaBdT1m3o/+KUKVCPLKi1DHFwnx/CjxEe0UwFKR4vteHpX -JQYLJpJChY84mcCRRl4QHoKdYQw0s6sMyp2paJ9Nl0/ymJ1uvYh4aIAV+oXBpGjP -cFqniUPSdvjOCo1VTsSLaTy4987/d8v+cICtZZduJhiA8xL0ZddU9DakVi7ghViq -u1TOSE72ODUjUZzqxABCKnb4DFq4M9Ib2zTVGcfcZiM8+x8xTGtjYf823yfIIf1n -CMZasF5sQIrf1aZWlpwjOqMOwF0kn+OrAsPfh8tsiQGcBBABCgAGBQJTgMDhAAoJ -ECrT7UPn2xWPt/wL/2pMpmkojYy9vXmpajEAVwzilMFoiqupDSc3JekrF1B1n/Vr -bdLkGv5pJJd98aRmaxi3klW/2ce1YvwXgrytui47XyGHHKZgILiOQ3Q3+mkdjkf/ -ZDuxDkBDAiZFtw46K0OUvSJTap84gQIBB7ybBvL7g2ofJXJUOzinkduhfb5qaMdQ -5AB6dCKOscWqQYe8V/PcH7W/rGiDOSGSgP2b49UU9qZde3YIx4JvzEStExqEPksN -wOQ3gfTo8G+xDtLdg1rSrUtA5PiCpzPSUQphQEfnvFPloH9dnMJeBxUbq1eblUBi -7T1JYZW8laZLRXbmEgWFtSTS7uB0sGB1oL38qF7StGkMpg/b5te7VGvH0x692cTT -ODOkiRlZr8fk5dAV19IirVr+CXlMei7nOO3QgFWS2e8DdIZjPJXqCd5yIKF8daKP -7sM5WLkZNNuK0RJU8fyx8EpPTfERUxlb7VgsCG0BJCtLDglDqndgwhzBBBJ/4PM9 -H8U9oJjKVEbJbdStNYkB8AQQAQIABgUCUp/NVwAKCRD9tbjAZ/JTh6taDp9rLKA4 -EoMebqRMT/NfLQQoTy07x+dnHP267PDfA60fZnQEOBUgFfx+6Z1WR4DZsFGHRthF -c3kkHqSQF0hp11Ff7OGycnB4vfrnKpdgvwg3H3zAj6ggI4FJ3yhlB2ObnyBjpGCG -BSDtYYMTBPCmgOAUtzpOU68TOwxwwMD7UN3LxT4jsA+OyPvFd8FqH3Uu4x7NwPDJ -HgLLYFRwrgedsnV/SzDy0uX6TR4JnSAmg5CsueGXeGAPtDi4vbrYE16TJOG2wONh -F0JyiHyAVbwCpwmW9+DojvA2laJb/QVRB8VzsTGRIPKWLhTjU7r7n7Ae+Lkw3PRM -mV5oAxp4rjlNWGrlNSG0iW/oFUTrZbI1TVjldDs1QSKG8F1LBTWUZ4H3xYHWmfHy -LvpjXofbYm/zOHs5eOfp9IF//cnPVixaDavjEbPBDbt/t224wtsxK0w7NHzjQjLm -kbsnxIU7IutNDMXef7o8I5vTEhe7ds+1Zo7K/M4q6zn1z3iUidiqVw5mPcIszFLg -e6Bf5OYE7yY5N6sy0eChNSZOIkQRUZZ4DYpBdZKjDodrtGxRUq/GR6LeizEbqERJ -NRuUy4GWBjw6IE/Lej1sxuueTnp89MoBrUwkh7woPFmJAfAEEAECAAYFAlLSy8kA -CgkQpCK52OUn29uXog6gh6AMHJfsVcSzyXQGptt9HkYjUaXTliEn686dIgGoyOS/ -mAZg94oH+L3qLWWqTRrH+ybPBW0b5LYJAKlX4QJan50CYacofqUrjSQqG22ON4h2 -pEy+szrnWkffAk87pMfOGcRxmYdEpHoDAqOqXg8Pn1mquVVgoVsZN+yEoSCfgpJc -GoRWXkmfFtr5WF068aT4jPMUiWBcV3quKJnMtMtXmwSc60g8joC2oftXN/XWONfJ -z5vRM9SYDb1iRKQZmCX6G7x1fq+sFUgpd7pHc8LSkuIi2K1LbjFHEuwRvWZIX3/I -AQ4zQ7eN7MWA2yjqfSzYfMl6zA6Z+9cF7kxPxgbOc/B7MWIRl2Kc5zUaWW/veYLY -izq/dbWlEFr18mI5CpR6OsRCwtfJoVM7eC4Xbo3wWT+JfsmdCKwnWegSpWbGtQaL -MUgpqR1vAfRvm3HBQSj2SJdDxyjCfDhkT4bnvwUS5SGgdggTm+zjWovzZvJtqCGr -a4UhgmsjwNR7zzLnNu1eh/FJm8t3Wcpf90VH+4k64UcYvHdxpgLWyp5PlTu7CXlF -AtxNthPiJRPrs0SGP7iEaHLj63d61V6JCoRUOULqXB2MuJztH3l9o2Z/jKdgHMNC -A6W7iQHwBBABCgAGBQJSjUjKAAoJEMQJSn+pq5SBREIOn0jj2gd1D26nslBhDnfN -/tocuo+RimOS247LrqLKe72EEeiuk23FGaPi3iIHrX0w7prk/s11BvxHIgENkWIf -pQpWp+6kiVxFfMkmfYqcwdrK3DPcSZ/Tvo78LxO8g1Re0HUwA7SIBIJP3DHlLjGo -dQjBu8VltByYlAUhMi4qMGskbxinSKnI1cfQE8CqiUezzI0xwpy+FPKrgZZBBt4W -HdHlHDBIU2NEeQQNoHB9feFq3RU3psVbDPxKC4YejvQLIPWhq9yJPiWnr8kfu/nL -Xa32SBIxjZrmw39QT/Q3pf1qYkw6hGWtDuUZkiRbt+iuXD8stZ9WB19Zmcb2ibKh -6mlPXrUMDxV5jfjtm+T4Skmh6Pn8EWh10vGXmpoIySoIHeH7XS4BZj2mLUyaWktt -VsGOf+A/vVfTGGAVtGHoxnVnY6LUo08+c/Qaw9bNi7Mpg+OCHqyIXjFdBzIxt8XP -kII6JQOaEyx6Fx0po9zB+47BXrGMBGNHqLIMsOH68z0fdg3sotVgVRhrxhB2vAvc -dEt5bMtyiE5vFZxUOwFMJbK7+oaVpo4tTcNNpDFrAd6CDi2thMO7QgAj0fwOA4Wj -LptvY5rxDdueVQogEOyhjldW1dsW7YkCHAQQAQIABgUCQt2f+wAKCRCjiC6/eERv -JpFREADc5GQkKCPkRYqTtNAQx1sRhyX7uqtWZs6RDOn4hHKsb0iimPqDBma714qe -656d+mAN/GqMS5A7QnrwUDSXoZH9Opl5giZZBi7R3H5yYbUHx7lB2jNYY42Dmcat -J5F8mtguFXtahU5Ge66Ck1HrMC5tiiw08hSDlSucr7ow9QHFLBipk2b6WPQPybGf -p++2IFXEFFJpyhwz0kJwnTjzBvN6AD/9ayeVvL8EiWroUt17JJYESYyWTtPrj5US -rm2O2O23d/oG90dCs7MycUghxzpUIwvwe3E/RlZpJJERuy8Ogk4JSubZs1/g1rKj -J3lP3CZ6zi08RA7mmTUCaz4m8giRUJY5JmXUzxxwQrrLiywUa4uri8K2c4KC7EYZ -TenGmcyyzdXLJykXLLUa0h76dVrvoU41bFHa9FpB79NUDXZL0ywkOVW3ryvJfCuG -jaxOhhlTnCI4ywMxxJVq34gDIVI0b6jFttFEYkgMTLYq3skvrkONwj7ge12YirVM -5O3aKa+TxyGlHpiXCF2VPl5N3uqjhbkVR7FZlDSPdhOF3A5h7H4Cn5FM7K6bqW47 -H0+qMlz4U+T86ZURZUlIMc1gQJkVzKHOqdbSoJqO+c+KqvI7w2W6aWGFdc4joDA6 -CqLhInN+9dKSfKXdhCSulUgWpO7biDip0jh33VOuwogMkKQO0IkCHAQQAQIABgUC -RFV3uAAKCRDXw/ExqyqR9dqTD/9GN0y077p03ZAFGYnwQ0SVQzjhP66dL69n4QdM -A2GVFlsYWgV6pNdPfz/XlsB6HIbM/wAZqEq6r8/iiwq6LPmVzZOuD4RWeRQh8HvY -UIqD0st4UcgB9M8mpYzDCkY/6wtBkYtmGw5WrzR7sGEok+yjXtMZzrpVOz7DU4em -5rSiAB+PMQvY5zQGK/j12Sc8A4z3aEoQJZTatHe72dCJyCondPb/M8II3KRhLCjF -Oju6x5V9CaqdWqivaJA4fHOwkQ+0Ldt04F3EThCWzcVLPcgdGjrCLILAkTc+YL6m -uSl2dwe2Ha8+dEEeI3wAOWuolAdTIFrwVuKIVtDGJIYI7Fz8gGBK9ijN0CITeUhD -ERLS0EH/DLXWoKZ1JevrcAmmyorH5CTM5FGHXwLA7sSN4SbJfi31IqJ+WuehQVoc -Q89Cncg1cCi90vXcfB1VBzBoKGjBI7Q5FLcS0W7Raqbjl3jNBRYTMd0MxjwZTDx2 -0uUQxiKWyE0XZy3KU6/y3MB1otM4GtnoVAPXlp5X3PVJLq4bcwyRXagCh6d9ZimB -N59OrMgnJ2s0wTqmEmBpHNkDYnDlCUNDpp3H1YwuUutXuW2ExQXb75pEKVdZ0riO -OZLTjkIH6zACQZi/ZmXgG2qw40JJkrFsP4umK93DZxbmNcHe3/BvccnpbE1YGUdA -dJZkw4kCHAQQAQIABgUCTERq1AAKCRCjT6dF4BK0LRCJEACEWCAEAm9jRkdZJPMn -Ndb0pzWse9N+FgSdvHpYrsDOPSlSYcwMaucMbK8SojFDVq7nDrsPtiVzrcjF3pU8 -h7Y0Ih/QykuFq+lloabxhYojVfH2GCa+O8gNIT8XWiVD0yE6YWhatCm7Ls/LY405 -mxJ3+QjiWoEnFSeViM9Mclf67DXE553R2p1cyQiP4PC7GkK8gS9vnvbFw2g/nhaB -Pn/U7EnujLOW9AqOJpHd2kRs52SLv+rcVD2l0evp04vquopn680m87F6y/cDw9q6 -J3t5RaB8vkmP6ZK6cT285o9RY+ytGHuOO9WoCnTYOybpi9uZoBL98AoxJ6EolnjG -wZsyFNfa0f0VimaqhcxwxsTUKFTkEQ1S3hPJEn+PJKprHxMJvpTLxuy8olxJ0zmN -d+h26UHUnaxr/h49rWBvmTtx4Kip+OSAdfLnodusXbzvrf+Q31dg8AJgbVtnoaVM -/3ew3T0NvKHCMIJ4e3qaDaCDpnMbGS8lXGCHmZi1KMk9m3W9RSPcnsYk97yTtdwi -xujVFu2b2TOYkxWvrbITeTqOi6E2U3k9Qdqi1ZQfTvCNt/ej9cifAP4UQu/wMDMr -NPLsSJV4cHnNkghO1vdc0Hx62fPjX7599bPfCyicskAo47rZLD6siuxMf1TOtUaI -jJF/433W4j3KRjy/Ukk2i0ArrYkCHAQQAQIABgUCTE+AHwAKCRBmyMLXxapEbRxL -EACiTgdDgDvZXrOYON9fUDe0kV7uHWGP8bG3cy2vsImFzOAnGgTIIHNjqZbIN8p1 -sDs9XeWz4o0U/uL2m0DR2pAfTT7C832AYqB9hABi7JoEjUiJEJ3UzS73D7r4GiYB -fIdE9uEZE2V5ggKiHPWD+N4I24LYcjGLqFDqHAC4IohD6FawA4n7aR6FnFuNpbT0 -YgESpkotNto4sRgpOJ/sJy62uvbZcg682VvP7xOATH9lXgxO0EDkD4nj7oLcjbOK -GGYxnYAP+JP8k4HvpCBdldsVciZ7/MalO35ar7t2wwioWtHbL8OStagRU2zyzjaO -5Op/6haRrXg8FQFqsM6viguWSp8L0ulTXwDA0Bzn9wW19yjyBYThxZyM9y4Aeiw0 -GuH8CvNJ6vQHBuodHUYRUe4gbRLOJc2EvYERXPEL83fqkWa3RZMNExFZdwrIRjtr -n0a6KoXR/d6p2vymUF1zF1V34XHX9Gu+JHUmE64vwqGmcQHBNLH9WYgixRsX7+Jk -JqkSU8NAVTvxn4BEmGlTQY7v6gz5aFP9u9Jbc870FEOcCOJh48oDLk8a/iz1Saea -g000nnddGh5RSpCNZI8weCS3ZhLZV6W9b53SdrP2u1fhq33nxnRrc/yyz9G3krly -dRj19xoTTU2fjdOxXsQUnTjFekhAOJabY1MjyTWAbTdmtYkCHAQQAQIABgUCTFN0 -2wAKCRCXupznYaCWO8ASEACVT5i/2GKoIUgg+WZymwn9JB1Kkvg47qxfzg7jinD1 -zAE+ZaJb0A+O4KdwYKzFMiIxzo/R5RWZeSbJwbmmwn9T2uk0JdMCbROUFfFNZFHJ -zLgVzc8e3D4PleaO+/2dResV4a4bs+jDgVcOBkyIpABhg+jCpXLOJ9HmKFSrv13A -GMIOwJZ31apbLJQzp9FMQt0VIc5fKZ+/ARQuV8hgpUL8D3yy3Wnqz0PfD1TpfU41 -MijLo5u/fe1smuJ5G9E0PjaXjEGB+ChfMy4LZeK3i1Ze5OU3yRPM5HX9yDzPbcxJ -esFyrQM5+81Yab2HA964ARmjkiu0630o8lP9OdC4dtjD5oZUMCGB96jFVbc/SB1v -XJjm6S+RhI9Y0/ZRgGR8MHuVgWzg4mCnSPi8WhHdN39rD+73xCVAa6K5LEJCULjy -T/RNd9Ki+gZFxYaIB+WxVy9Tg598HO83FQzqB9eH56TpfaxmAVb6uYwPDchmI1G3 -cnosjwTTumGbyjrF2xUc+o7swBa4l+gmOHOc4sMSE8CkW7A1cnc5lD16T29gH0xA -ejeJv+wEFg8ObTsLNbPF+GFQ36kRJyLeNXwZVAVp8qjkjIc2HmjJhH0Zrcia3zvc -tgJlCVVOy53ouPQ+kLVDPBixY/wk7omHKne6ynQflMLsyiEzpWafmePBhbbJea1U -R4kCHAQQAQIABgUCTH+9HgAKCRDhX+XIeS+xOHk/EACCeoQ/wEE4J5OU7o0m4FAV -o3/nyOFlcR+SdSh33pjnwFt1TCWnF/vAASHBC5xZrrGRRgzmQC+owYt/oRWHAnIk -VPGAtt4ARj6s6bifOU35X0MyJ0zoWC4xJA981JjOt0Uhds9p4eQ7c0lqpTdGsbNz -zAAZJNxFszlp0f6i+AO8TpYcGn38hHq1fBKh00krwE6yyJMb3V8RNkEMWeU4ldJF -/+wWK0oYCJRk0L7XSZYbiKo6oYDIx8hc3mJt/R/MbZqZo3DWX8XarATUNUXiojkl -4SSdZUeeykiprp7JM4bNbwnNhDNWjaI3jwNKMdj7ZBW2/9RGrteLNunpVCY3lwR1 -bt2avrq0kidupwCdV4NoN/+EkvFURJ5C7FHQ0E8GOmW9pPwkddYYi2Rp4DN3xCsf -hoXWXa/pj08UczxwZJbZZnMGCJ1DFp2bN5PY35wmUXk61h2mnz5TgN9xx00WlxJa -XhlXvqbWJwkyXGSrTFlA9bGRqotmbJ3moOa3Bd/h2bKd9ZC3tszEPSdHOigaRG4T -/xP5lUBIlF9qgr46O0OWUSoAu+cS33O5ap6ajr7cxrTmtYvCaKu5TKc7h9es+cLS -YgzX1RNHGMPWkbIbI6/Ffr8JAbWW4L4MUzbDFT1YyIzVTzOri5spLTk/apUysAZh -r74Vwb5W++OINH01H2A8JYkCHAQQAQIABgUCTRiW1gAKCRCDtbgWGhvVDp9TEACN -qHzMADIU4iaf3zsRt2hZmLumKLytVkipbUXylQ9CbJkFpct43WdtUt6yQLnpmVFl -4gpvTWHHRXL1HglFX+oFQo94D1NyYmEeTdJj9+ZBGJGtxrU/NboyJelfzqlmTPYq -Fv3GeoPBdal1CY+nUJbATvwgLilDHYZViyV+uS/O54aypKLgMdMMbwOFyDJaej9R -0MST2YpOCUCaEfnb8fswSoYKtnP0eHAgPXIyDCDd1LBLuWhkLUYVNYb1PySC23OX -NP1nFoN1e295U23CsuhzCz8wmrJG6Vxktkc0l9XcaQDMheeq86KOKbc/ofNt2xN1 -yymavPDY8qwPHzRBa33LN/LLeclUUkEyP8GdVvTg8oCB71LT+ZNIHvwEjEDJXbze -22AwppaLcaZYBEb2uousYsrMNoUYAD4nMBiszhu4NPjkWls3maT5TpuR30JFQnPx -rWvLJ/r2WvD+jNh/mAexJj8KdF7KDgQIfMakmlrkPV0Cz3AVJRic6rDw0YrKX4VF -ghyqPmmyHAgIA55T0HhKIaBeQSBOSOfx9CBQXSOxbPZ2DbmmCBY8bWsE4t9yLmNg -SYgMvskBlafh1WQD1O8q+bfP1MwZ7CGfl7RRlctixS5EPdWDvBrrYPWkcd+14vCD -+Grni6LoY/TJhilNdhU39RYd9VHd59UI7VhbQd8f3YkCHAQQAQIABgUCTgS48gAK -CRBnYr1rjex9eiDaEAC3Ah0vf049Si2D4p9CZk4qcwZCSA00vHbDKYvimC6/HjvD -Hu9UE2SEVBVioThNNQpvIR7SKKrZXa/nIX9WDlmWbGoxaHht1DHPWsr+fcYdnMvl -z8eGTRd96/dgXKVl9Uk2c+Fc3vXsXsYDh3NepyBuZjx/n9Od1OCxEn1DivZ1W+4S -bZKDs2KhGW6xl6zuo4cmJf40i+jVdhgG2KIhJrktAnxEYYZZdKWGhWWBzJDSt5UD -I8J861GkpdfWO6NnasjfCEVUEnQpnfPgi9Iw+lipUj+nkzKa5bcv//D/D+VlIkLi -DdH39og3ByNbL/29Buf8IEBl4FeorpZ+3MdGYMbwEJ83TIvyLdQFpzBH0NaPEn+b -iGurt8EQoSm69mcGydeae1JZ789gi6PdvacQIPfjLmdEhiaFzZPvrsvjALpGB0St -UwsOPggiW7S2ZxwjXeM6uCM4+vaNu92H3r/3Va/vZ0UiyCL2qo2QzE41XudOrPSG -a7c44UEscz9vRTZD3A23kBneK6xWDnABgYnA/CGp43YBBdCIP2pA4IXtbNnZGYfL -hR5IYhUscQBZpVSZGnskJtFuLNvh6toJSGYelkIeMR0md+qDaiKnND55k1EacM8U -X7f/TuyuS7724PhpnrP2CIsO29EaqOEF/q+EvdkrMASsm5X7ot1xaUjt8QSN94kC -HAQQAQIABgUCTjwC+wAKCRCKpPvWpxppFQeHEACdmbYoIVsb/Z8fSJpXilJnpt6f -X5C0lzJOJ1mkyTCyH9THi2wKNWR3WWisq5PueyF1EsyqpBzCXgeh1TxnSAFpZ7kw -gQk0/MpaNtmCviXZptthSZ507uv7s1nV8HnD2tI/xaN0L8D7D/idZFdjg1jFVUvS -lRjjbgg5XCtIwhG2biEYspXOIMXs8LiAFN2ZhP4y9x9Y0A7V81HBdkgMRDcPINdk -pc3rZS5zSovwYd86v0U4sbIBeZf75L4ew1ysNvbPVs/fDAsIsC4F8p5Y7pPgtrdv -Vai5UfiEqoRilDyS86k+YGSAL3NKtoo+D8ocDppYINul4Ytq38eY3t93m6QW1Slm -Zrv1SBgVCk74wddJ48QfsUa6HtEJf4KaauMbtruh2pRjmKk6q/nVmie8aZWudgKW -B/4ad11tmm5wVgDxwibAFg5lNOeDCPeh8WQuQF0bLjkm5bYPfvUsGcmWyhyfSANf -+vegAchlhrV0lAV+99v2Of8QUfYZlq7APzGx/VIKRVywA4tS0cUWX+LoWAK8RjYz -lYAqHCsPtbfBTAApmHegGwxi3Oy9xVm/yClMwg8STddhSfxhnvZd79yl++mfX9JF -fOVYGQsQOEu6VvIBL1Yp+rM7AW3jpCXVayamik45azwH1rCMiFfhQAwrPZAWhqSu -3jIV73Ze7Ti9zcB7AIkCHAQQAQIABgUCT3MqPwAKCRDJtMRnbcSX2dSlEACSFIW0 -o22kN8A+tx5bUfxeLjPTHeMxktmWas3DkE6WIC4RcO4oGGRpsQjn0nzc1NiGZduQ -YW+TAZNU4+/hormph6CF7tXXPevPuxDTmUvXkTzOdVUyBmYae3QXyUSlMqZ0dlU6 -wSb9nCJSvOL9UIaMIJjkLHSHV6zOSwcIEUHJDol/xOAwe0YDAW0aFLIYy/EDWXmF -uP/1pe5Z0n+AKUSfTmqGla7A02OjsOXz+4ZzPeVlN+vZZf5XssUisVJN+L4PWgLr -SlTn13Xlo0kW/pkTAFOEfxIQfKkXPI7Irp71YSMg57GHbCl4OsDsZcif5ShOEmz9 -X6CPE+8eMCvRR8xrSLn8XZtduMTH3ZBshDWFyMdqJVfUOztPejAsNuiAWEO7woQf -j27lmTRsCiaRt0CTR/0+0AuZZsUeXbStje+oYDduUUa603G0OHGKODqbemxomljS -HgxyrN8FvXKHpcPc7LaTQ+yKgqUsfEOU5iCzXl1cbsff8k3ONtNN7wiRKW3KZ0Kt -1LVFyUDySZuM/EkIVFi54fMrO3XvuR5xUd4qc5yoIUetm17gWlPZcqC1Rgqp3MUQ -Q0of5hZLhvSnGhlbw9H0kwAl9C1TkwJ06If24SwyVYwQ/h76V8kVSjz0LJNREGB3 -401Xb1DTmvsF57+Ol+eN/+57GGuINJyKMOCpAokCHAQQAQIABgUCT4MR6AAKCRAH -8GBBKdn0mYpsEAC9cneTSZHCZpcUcmVD7iCt4NpaXRCjINJG+mh4E/d0dEFkQ+36 -B9Dcye6KhIbjtGnnYHKbhEm4JdZ9XVOO/5/J+ylJ+9dATcY29dJta/LHLJMoAVqz -qiaU18rUE/3/ISdVOYC9Qf4mqIeDTNCNA4VfQdvagW4FsbQnSp8XgL0WCjy46Ce+ -2lcZh9lgMO8go0zLSm3KoJUVo+puT3l3uHMdtUpWKWqnbeefgHzw7Ml9uraLctSh -bO7ANwljsQtlI6iU1afK7IHX99k+4toB94dmWr6yjbfPp4driO6SZ/2npD4QfOCZ -WEY37Lhebeior2ubQkYtiBikfgDasoJv2Iu/ZbeiBfkR0GwSbZlQv6Er0JVjsCXv -E1fpCdy1IZrNgBL7LymzrU0jV7oe77ZafzI7YWhi3a79lyXblX/L0gR/ipKdjb1v -W2lj6wdUI6R/Mxeem2jtUDuPCPbhdDcmu8Cd/qYrvuHsMrylW3DRzExjTwMbwxNU -ovz5mrltlE865HvJDS/Hn9NCYWCdanQyGbkYEcxiN3D/vEr1DtU8dRdpiX7j4I+L -I9l/MFa4zSG1D0zcEo/gZQ8cj4pYNSrSuENoPwYPeOx9ip4pGjsswXrx0bTmCW+N -K4F5PgVRIAAsUVvLgSzB6ewISdTP0BARS82bIEtzO+8/mJvzhJXTkUXVvIkCHAQQ -AQIABgUCUWhsUQAKCRC00loemZmWlwpJEAC0gHZPsQAxZYmCtp5hlcUon4dp6chh -3nbOHVOdphPiNNyr3SDberM2PrtjcRDkMKMzpdzLbmkIanEsjOrf3iQx98dMq91i -ziSUWKEzGTLbQ5RI18owDC4rc6LJigH78yBYKWlAOuDpsm3A0kqree05oOt6ft/G -XcGodho0cDysBzEcD9tjO2IuU5vae9gu8Ez3g5toF4zFP6kP6VeUhXqexUHXOvN/ -EBq3RvoerAYcykb5prlPxPKvbNCLaioqj8EDEtr3mjvS2Eu9uVcEEuZkMNCebZEM -F+E+jThOa97/cXTDByulA/UDdaJb5YTnclBZbzzdwIZFsW3HP6Kym9j+335H7tD3 -C4OKdVf6TrJxb87zGKjNMsNVq3PSsF6QqpqrkZXfkTclFTa8YaNJCnM6YQZ+hddA -4e1Qq6nMxcRFz0LCbsvd1JaGV8v9opxcHW1b06nOzSZzKxzxihZcs/AqmcSX1Nw5 -HBp3JXGeiIZVz61/bkApO7DIKtTPcI+DE+YlZ1mGb0Gt+BHy2Z4ug8W5lB8h3wFI -S8a0qdlKTnOQkF8RHw766d/2IjJTc0q4pAP8mDk9C9xn93Ak373huYjS0KwPwRH5 -yE40j7o2LZ3NwCDgeEynRBY0iCSxinFXxUwwH32IddyGs7XPTtopEbxQcmE48ZBD -LFMrRl0Fo6NZ5YkCHAQQAQIABgUCUXUWZwAKCRAMPZa2BG8HCsO3EAC43lNjmFum -dxqMRc67HXmNx8+cLlGNEpPkr7Wt+Anmw2XYjfhSTaB/iFBc9lVH2E9kVsGqZ6HY -sgLlA9VF9T1UrX1UUkyyfQ+exDVlZwN3Vj6Gv0g7aRNUC7zsxtiF0fSO0pl/mFmv -XHLo8lqxE8+s3dHlh+S//d/hFv0Z8uWMEFGoCJZAcWPKGsW1iuasSrzn/s460wBN -MbizguuMYpqug4jLuTE+8gUbSqZoIeFy+OBE6qnkOTjLZr2038bxoXmm/Fu4ftlH -HL1BCr+Gb+7zTsccw9POgUzVVqdrSfGgn3Y61OrGXPgSwZptufVOvfQyzqPPOuf+ -PYhV0ln1PK4p8adL7tXSHTFoGjedT6hMBhUDi0z39ZBn0jP+cmONlluXPqGBn3XL -bRVjMrtHUgvntxUsb2E0rYkPYUMUgZFjdLDmvVAq5R1xOqDdsAhljD1A0x53l2SH -EQy1oPtz1yhLbXgr9P7I87S+klc+Ijb6JZ3LnEIKiSVxZfv7NNV/cNx335te9XIV -Vu6loZ7Te/mLDXf/1e2lABUlqd2prLYkPB+AoVEKgBRgNACSr+/WUnwsVW1Z4sUX -Lc1mRf4f1fnrH4cGJ/G8pnU2rqg+9yPUhb6EizB0hopIqTG7uxfovSfRLYVpwJKu -jdvq/KrNefnXzKiCjqpsS/0AfHQeLIR0JYkCHAQQAQIABgUCUZ+zIQAKCRDrOkYT -sNBlnCUDD/9IbkDFxukdzreElM04Qe0mZQj6j6FWlqZZCjxAP8AQs9ySDAgmB4Ry -dcLNJdkHe3IPV8vAeECxVYXM5BdIVpJ3YwiwG5SWGg2w32rnnLkUu2ebvYppUApa -Ke5uQQa7ZGPr7UHsD8xozmisqWTIkDXemlhjWZHHPIYbn8415PT4hjDqmXvbfdJw -G9PM5WTZ/hsyobT5jR35wCHLQ5p2iENjNoebgq8A4TWusmnuu1VxA+lu1RvUCXJ4 -Q8elsQYi+ExUY8DvrAu5yOosmf+Xwrd9lqd2Lv9HA7b1E6JiTdhxW4vbDyROpRCQ -O4y7KT/AGxfNKqRvTQmwG7rXVrVXqD81CkppNyVpURYyxR45yzT7u3aQ6U8CHJiv -fIMCT4XAPRVEhD0WFumWlmFb7BmubiUBFuzvjcxYOKtOx3JY3xRUOPivj+D5gV+0 -YqQ6EVvOMuVPuKxhMKfS/yBTSZ/ko1X+u8Ddt0eC+WrL3zOb789LdipCDJCiNNBB -Yw600IAjlBaCATti9YaCvbbQHH5HBiw518v6pnECikQZTPLgeOSoGk56CG8fUZpY -FCvuYNlupv3qsKYn6B/eHDAVKD0EwL81hfbiMt1roO6D+E60eI6o4Dqu18b/L3ay -bTV1LLMbyvs8vCETM3PVKasSoHH+NdshjjLiCNboPojVNA1bKZv0xIkCHAQQAQIA -BgUCUgIiTgAKCRC5byMArRHL7u7HEACvj6wtk4PAhRhxKVpesKSw7Qm7ChrKmilZ -OCjEgP3h98ewX7C6WTri3JYUknECq6Z0zKmVzIXk3op+qGIa8xOY3Qd4PZu1pvLc -euBPWey3Ww3J9Q6MT1Ka6tTjEiKKhpZVN+FhauJrl3MgS9/RYhe3IsxM2b4/klX0 -fdAJYLjPJQs1j+oBzl1rxLTN/DBO++ZnUHXGZSlHvka52oRMXG1CEGuX8TqPGq3y -P4gZVZvaNVXpppMQBTa6B6PLRirsV7wNubvVgOlCYKZxYrWh65MmmnHN6HK3Byi+ -9xVJWED8bnvg1F65lug2k4ILY9nRYfLxDAaZNNZ8bsPDJxWHbVBjeiBgJNz4JJQf -rF2l4z7s0c4hWxfgA5bR214FjnTSU/z4W9LBSYZJ/Y58SicDntl+zghXp9tSIbWh -bM90K9WAmG9k528yWykI1y4d1Y85IpHLAWAy99vel9oAZBOPCJlaXg2dN1Elfjj8 -iuHf+ClxGMkK46+ub7Q5HE1dBPUh5L/VSHFGl2TKVzE7QnMVaZGpov541m0qeN73 -V+xMx8Rdu/EEK0qF6xNxNU3cm+TLIhl2tKwnMXbwN2PEYDWIstDZuTbHwBN6s0+1 -hz+VzQS6kIwG6w3VIF/6A3Ve0VdcieTBmfTuDEYMm/rMm9VKNygovEwybYEkQxVW -8lJcZn8ikIkCHAQQAQIABgUCUgxukQAKCRC4Q+b9jTf96cXFD/9702MqDi2jSYu6 -UbCRP8cAkCTthc1JesfcnKAaTu8aEUPtj9seTOmAT/Wkcjq2RbBAIajMjxOSqYvK -UD91vADzTKW2wSGMCmYz5Qsy+4fL/nNHyyUPw7TofHOzEtNG8TcESYqUr4fvFzAX -KxCl2o1yPyNNAL8WuEbs4ouv85Fv+XnCJ29cBdb8TIbmxnv2rUOV5FpX8wItsONH -Pzg0NFjq65IqL5PrqjCH7dIiZcBw/xeAzL5wGVB4n1vVd6upfqLGFMzMq20+u0/7 -OCw7qfb3VLzVutD0PsM5jYSjATcu6pwTOa895GafVL5KoWoYs95uVaGPd9ABPsPo -+Fras9qeUvg8fctUudzr1sQoAYRAIBqHnX2osRXxPo3Y4eQyoR4eiIh6DPgDF0Yd -HCphhxAQ/FJCFXt5Z9IswxVs4AOyFABWwG91ou7nhrdjZzdgZKHYbwix8n5pGFbz -zmeZAs0tUljwUjL5EJkCuvaEgBDTWp0UkPjP2InWlH9lDqz9OjEHI2ohhCFH5RfN -dYTcaNYvHoZG+VOO/qFM20u7ljV1bBbfbsH+oRBKnq2Ximad2IKBVZqPybpsBjbU -dyYj4WBpnZP7fc9Sqs1NBiVR2QMUVh1JdqrU9C05Aw9G5JawXxoD1Uvriya3trph -VUYt4EQ5UDG3eQc4qmJJsjYuXxOU7IkCHAQQAQIABgUCUktBggAKCRC8M5xKtROF -Dwb5EAC34wAXDXT4sTzLF90eNvfPKXsuh3uz+VmVW6+c7HdF1NkWsbssmzesmbLA -FCA5lv4AdTXUb/Q3t6y+uJX34c9rbRC9RmwS/jqwxvcz5fMUXKSCCHnv/nJjAtLJ -ye8QAFEnPMCZDsUGGCoOy1uErP8v20mQjns0O3WW91zeRW/5DWob/qRmgOFD/CLO -52w+mOorMhx3FOBe2PdpRovxZM88YQbp8RV196gg8gSbyN87P6DKM1H9Q7E2cdj+ -0p+sdwOmRJhn3csBdNZjKFiQ47q1ZCcGRad8pyubc9CbVV0B3vol3ooD5jLw0LaO -Yn04rpQAXVfzjMZRaTvAhWBWYH+IibC8EcoLj9TTfLYdEXTN5GpiL7ozVfP8OdVZ -2pMyJO5W6XCh6o2SSM8bx5E5OYy5jasGne5TICL/2/HARFtKLSp9Npv23lyQ350b -nkdZPoy13UZeZ9t6xYUvDfF3w4PwbHCGPKnla3yCRHCpfthwpvKqQxrRQH0IvoIp -t1khn0BofT9MkgpQZdoIvFZIl6BODtHz6gJ1CWFz1fBUsqE7npevMoDq0GUQfmfO -m3CEfQZ5yNh+jFpMUSJg6lGfodX/VpEW1FZTLntI23ggDsLTwMyln+7dDXNlZzSi -8HVQNqJGUrSXvaeFO6nIY4WuNZCD8PrOdse5bWVoh9TcP3o2Z4kCHAQQAQIABgUC -UwYHBwAKCRAgZwAbG2eKY5dFD/9juFYZY/+ffsiMNGQ1h3Ki+vcT3/s6LOKIfSuO -1AY0GEpzY977Ji0xxv5F21m+ZQmB0azYpCtL16puhG1oOjUH2KKSJKXPNIHYrmsI -m1RbdIJfdbAoxzwRvBl/iLIMecomad06LOywxSxLVv445N3P+YNG6YxlILgbrFVm -CcaYak3ctzz+OwJd6nXuDh0VJLYC3onHsRrNSbezg9TKYnVX5RMtSy9NCuD6qPbr -CCh92AxPR0sVgOZwIRj2PSJ+NHnvriEAQRbbL3v/Z3V417aiolAoh5Z3WvuJ4l8H -AIRUNQN8y87HOHzYriyPKeCPUVpyV/u4qm0ogsrkz6WnpRm6SC+dPofV4FHyc2yc -Fb4dYR0yMIdH+lP0EvRaeF9DR2abuQv2oUvuo1fNk2XHDVNtLjYTYQKnO6b9GHIB -wTAhKD47SIzDK4jJblCXyNhwsCig5WDI8GkHDyMmCl3IK8tv7QuJSBPP7rJhgDh3 -/psW6/xqo0fIfvogOCFK52hvsVR81d06ZjvM2i39wRjbxnsIff59mit0vwpvJ1Vj -wHML4JKkx5cWSCQpAMCTVP2v0XSJFoPT+AgqNyB3V7fzHQCQ8WvljkzvZzBRtez+ -rUdv32poRMrTIrK7GKDQCTgMlv88B75v2WWF2mmhoEdqlZMAhE1A2jtkRoKihGLz -pXqSPIkCHAQQAQIABgUCU2qyAAAKCRBjhPdUnXAdi3W0EACIcpjJU9Y8GBagS11s -fdRGlOVkBW01B5FOQQDQZqS4/c9Qtw20W7VkU3Kgx5EOk26gEY6RpsbM3HJuFZ+E -UiWOlVdmFpQ+bEXRalhh/UhK2XskEuDdapfz7O2il36gwLk01/UcWUfMOvzInVPB -qfgm5fEmMmNIisBHvFS+kAjXobAp8FWaM4QYAvUgujtxqz/sGBBAOvP9IcbyoyqW -1YrVnv7papNZuHjftVLkuQBW9l1nYkG+pwcrAFp7HiYinU98Q3N9oZTv+7zs2aqd -qQWqnk/qUHQ+YcUXh2GPE1aVOjeQWiKgCH36n5ObI03oW8dPDhX/9JpZiVf7ZDJp -rysK2ul/+D18bzRrYwKMKK+q0+SY89g0UOxPUCI2kuBSJ4okDAhJAXQ9rxUYd8d9 -Qu9vpkRyxpH3sD4SWW2PCFAIlYUtYYLdJqQdoglVJT3MP5L9+f+sW4KwrbU2teHF -kaQEFo1Yvv5bKtz95KtdMiZk8iRHIv6Bf8MfQ/FtJQzqPFt01i8MsulOciKwOyVN -HPfC7M1hI+nInQUEoSwmucDcc18Qz/Huu223YxFlmcbBhd5lsESjVQKDNuXBOHCS -tRAL6K2RVqJtFMD+Ge8epIKZA6pUj8NQSo48KmljbYMg30q2Q/4b9NrHZ3ZMtE53 -v5LIlRQvlHXYNf0EB0+fnqWMFYkCHAQQAQIABgUCU4BKYQAKCRDxLZhXQ+4mIEwh -D/9xWjW2/nLXeIe6SlDdQQkeEnsTcTGnp1kZlx5YiGBZucBmUfX1v89Pr5XjUSGC -Sv2NQ6S3BHi+i8WFjOt3XEtM1ehcpHbDTk+xyo6FVaFtwsWI5scCOzcI6wqLRvWt -UE9/iNldoTaZGCpnvJ6UY2itwWbHOrGHEqcyPm8QfKvI+5HRmszNReOOccrTB2xr -2DRrpXu2Lcf/yc4U1iTj4fEJnKRnY0YJFdK9uEKVs9+BZH2/3efxWJKlzgJBwExk -t9oIddFpChmu5rBgusa+i1QMIGJZPB/YA+6bBUEpq3TdS8+8mMa1+9RXWINMcPfr -eSAIpVGCzUHYA5V0ogYOS6ena+Nl2W5SgbrsemH39kgw43tBGQXImC0OvFyNIpXa -5T0Br4xERx/Ke7/AqB8hP5f4HYZ7NwISdkaJo+ICbj5ubjnS3QfpBcho4Ma3whHl -9oai/diLZ/b0UpVTAAnWPn+Z/f8dgTomEWn8jJldhGgoJjzIvtkAt3FrmAvjsFCY -aOQgYAtDpXFAS56+iO7uRr/26GXf6VYIwClm5fAJrbNsPfVvURpwThhTQaA1gGBk -/TDKfV5phmKNqnKq22eG7r1cReVVzb32fSBN/0dhMHZdtZ7C8nIE5r2jfPGkic+Y -tyhKlUObtIAhD0QmG3zYQY/CCUArWrQsVPhw62CkE1J9fokCHAQQAQIABgUCU8FM -5QAKCRB4VAVOzv4Z5OCzD/95iWCBrz45wO3ZONo69qjyPpM11j17XN2YHuEdzIWA -nOqdaTZ7v1zI9YMYuyV6lyvKWa6YFkRqn/79FQMZRyxG28B1gLXkSz4biEwFO6te -JKx5aSFfHi5tGwfINWnoXmYf1leiKMqevgGP3uPXT3RpU1ZO3AqFd2e1FpbFSCCH -TdGmumg4AI2uEYVSaP4hSs9jOpcx0YtyfB1JELcB4xHPKujPilzfpC9Um2qQ42Tk -8w6QF/cD2tSOzSjP6djZbghqicAfTKOAqaaqmRkwc0OwwaaMiEbvz9g7Mw6bJJRn -0QlVwxhipkogJ44iIUPFYtxOlsqWjyfgM+/l264V1pKNQpSfRtYL1e3WsVbr/MkU -nblX40bjT1Fg/yTdir642fgWDjQyApqRMEqpuukDbTySwksgkWJBgeDLR62wriT3 -7D4G24tNFSuCQzjJ81Str8vNAhu6T6NbWUzoOQyYsP/KtbihytaSXgjrK/eVacei -3YbpqEu1FnZnP6PlvZcsd97I27jwodDoAsTP35+ShGuqimST8wX6eAK6Yn7doJaX -2NzMWyRHHGo4Bq+qw5xy3dUO2T77JytHTLcPJfhUiKCBTSVpfQDJQz/1buzlUebR -6va1sDMSXIRa/mPdrWlzlZuFae+WIIz+iFN1NbIWUPYEpIfPc6LgznfuavwGsn4U -VokCHAQQAQgABgUCTERleAAKCRAei/NJIykSZbnIEACu+d5hX2Dspeq0nDPtFsT2 -ynqpg+sjjyVr6jNTkPGYglrDWYJQ1GURNYOCd54aBbVI8N9sNGbEpli5N4IlKtIE -6Yd7Sd1h/A1yoMinq4EqMjC6E8O3Xa7vwaEZ+49vmrbtTLC5vonQMW8VrZJZ2iis -rXdppSnPG3WlXL9EJerfCK2EDWqXEYco05O/AZQ+s2gh/5tpZmipN3qyk/0788I2 -l78cO/pnUXwSZ52gJ8ZjbKBLrznUOr8DlHfpx35QdIMQG0vC9y6Etpsrd49KQCAT -F1hWLDg3HBL44PySNrJavNuWSipvcTqI3r0A40O8DGhn0apose0NoyqjK1ou0UWn -5q6e4bs0D6OtVaGLHW8H3u8hcDBCwPD05wL9uvReYNv2GHyP/lsXJZuIdM5W/qgG -WTW562SJuCVlqXqBW3T7SPGA2h1YMy5XsGBmVowkB2MEfH2gKpMVLUpFeDqV5M53 -ht2Tf1wZxZtdWFCf2DtiE923yIXdJ09Tdz3zygejwEUBYviuK/5XVctv7V5njo5N -H1T2GmhNrdJg/2DEWrytnauUKY5z7hs6JEvj19RNV8vhS2MddWkHPuAFtod/ZAKJ -FZxPwJch+dc5jxy4ivDsAt/JRANgJSifOXYw4Gcqw0iA+ZV1oFL1/PvH0bRWlvtu -Y0dSufAjx+mwVM4OPW6btokCHAQQAQgABgUCULsVhAAKCRDCGFJYGfeEUQ2IEACJ -N2Wk0imtndfFNWpfy93XBG1QjT5YyNl7XcDVYX0A0kSRYKXEQz5RlwVACobTBiHJ -pKp8czlMWEdYIYXAXkMcwkcHSzOQXBprhy2hcsnbx5VQ5PwqYKgb8pP722jqc7zU -4ZL3ZKxw6Mk7oAt2I6lpYrzigXcmGeit1TJsW7dUsmzXURs9BpC+FnuXCOhcZckT -/O0S7fobFSzelzMz/ZpOiBO+OMdIs/heNLlY1zhNt0ypers4w5IqM/vEpTrnRzP4 -dtk0PHTRCphO7qlsSEbtv7ZEc4vL/cQdO9+SK4hUU2eDHWdpROepRECumVRQLdfF -t+7EEgQzv3byQaB1seAQhQ34rpO5pQsgCqQDe2Xs49kktFYVrei88fd64HN8x/ZX -gbH1evIp9OBQteD1ZcLLH7Emqy4qZl3PFcL3RuJFVtC4ofGBJdyWhIBj2VDGX/T7 -cwaLjsSrs4DjIkWS0LT1i0NXtRIc1YBxGdxNDYHNH0O1oY6cCiSQlSchSLVKVao5 -fdVwv1nK5CMMHFrLPk97JP++LTY62arcxi12oYfZuzOYOt/owb7NA5ky03t6/Rfi -ZfiRZouPfJCQhM5MgTUNYDCwa/gwEWZXw34BUraPYteCmh3evRU0JXz1fdLQFQpO -ynpIYNsPC3zsp7P3yLyK79w5+Eq9vslFrofqam2N3okCHAQQAQgABgUCUf0RJAAK -CRBNP6LlmWxnZ762D/wN9KLtC+z/q6VU4IKEPZfl3+uMOvJReds2CPHEHl4RLqYR -eyWoUtLhpq4ItlbvLn1dFI1fAvbswxO939xEHLFEKEulh+eSpti7QIBkWTSSOGp9 -Ku1QyFGrbKXfbMyleiwH0x3f2stSMNcgHFzriCMFnMcpjpvWZ3nqHAiNbR+kq8PU -mE/hNRuuWYX3gKMft0hFt4pd4ihce7WkTsN6atahgreRXQriMvPzhWdHlkIDKMDh -qWtSWKDw5UvX2QK4rEhQJXOhasEI/J05WXJ0b4B9FOGpn5IpKgPAvw7ph5YBbiKA -wNzkupv61esoyCB4Rg+BHxXSqUW2JQUHyk37Ajo7bwbGGBaoDQ1fBoKcTvhHGeNC -xqg6EFXfAYRrhLSd1dGzhKFqJAn4ns0geLwocTuU9S+LZuyOkGuRmTVAqOKbu0Vd -vXFCqo27yjZzY6BX5Lqyx5rUH4aMeVneJP/sp5LptL84NFWHWvBlnSouOBhUfpaG -uZQEVtPDnuDNgfrfXpjsqsTe3/GdcsABU8jtK+CunrRqYQzaYPeV8z/Ys45jh166 -5hb8ROwv4nlW6cp2Ojmr5rjohTvNZ8Mucku+uzTPOz2ilPSzEgKBPTrtI3vKe+Wj -OC4DA8LVeyxstwjTcHpXJrAa5qvspTz+aIWi9F4eZnxvszV56/Kar7pRlH9p84kC -HAQQAQgABgUCUzpGzQAKCRAlJJYo7TvNxnDMD/9ut48Ej6takxvrF7RL1Eq7ejTL -zzBa4DeChs1QvqJUKWANSoncTm/WZyPQKKFB+hi8INXspEr928OPLvDo06AB61xS -wFkViFqMihWZ0uiSolxiHUzrLtyNRZz8fwNZrji77XPJfe+HwIZ1BWF87dftHxvd -e1EKQVZpwsNzZM/40jeB3Ll/90BhepmlmOxOBFLHCJ9Dh+pYxw+33C/F1IIRiVzc -4mKUI8aB+PVui4dlY6Y91vc/mxIRpWuX5HqXHiVG95Z+blBl5QD5emvDhA4af7B/ -DWgUBXtzipL40KwmGn6eKl8tiknW6WF7IsmA/9xhbw89aZWZiqtdkFewTBabZzHy -RqUhN65Ox2spybg6wVpMmirBhU+Gv3b6L3uke/69ZgsQBJzHf+O5hOv0CDiJZIva -flK+YI0/gpJTF6Ztdu/0CEKTN8XKyguoL1XcfXMCVzkJlaueE3RO/67RLllroLRu -P3jP9D5vItJxw4f0k4YBiK3mF2V02fXIvzTvRFtdOUUiAgpIFz8tmeY3bcMMgkaw -9bg/K4dlk2kkZos3TcJlNi6detyykD3WzB+PlOevO0sJGrsniMjJ6R28ajvlqgr4 -zOqcyF7FykiPmtIgwAHXzTscQgjyWuJWDfbo3yAklFy1bXVnAyjnb14okjKN7URh -G7MMlEHBZDyg42Zj84kCHAQQAQgABgUCU7kiFwAKCRCcMVA8bYZjljyBD/9pA11c -r2usDQJPohGGxmU0ELsKavFPr4j9HxaADDNWYw/JeHDmXorb5IRzFSRn4ihkEDsg -C/1MzQQNvbK63Uksh1JAHQzy95/PaxCPK9GXRZhQ8YiDlp/Qi64jPpghJxoc5uxt -aerKDKgafLVMFGL6Xi4/05GU9fs/efaO6ikQfveT9MavQn2FyzAtuSG4ZWiS/U3g -1dIlOOe6qQOGPgu+MNmVJd8qBmfGHvze59OnuXjiZudArf9NJW8l/JsIF3KM2wLK -AfVyMkKKOBA3AM83Yky883UrYNjPA2yGP4osyQSiOQh2qrogPoEZ6VjejbV4F2iO -DmH46xTf68eY2RGEYqREIAtIjz0lctkM0b+ZHQJMyj2yzdgNYuG2yDZoTsG1jpqt -LymOMWd6f+anmW0/vFOhiH7ZBOckpTI+PtML9KU3HXsiPC5Kod8i/TUYuqzb4+sa -fepBEiOUa4SSKGnFL1JlnMQ6MZ1JtwxvPeON10glvWEy023gMCx4A7G6h9AHktel -56fLDYKeUzb7MmWaliZn74KgI9uCrdALfswgOhYQPQHebXp4sG/+vRIc9tgbILmZ -V0NjW1kMuhpCMeoqmA4Mv/BXPfLiQZ1G53Yzs2fnMfCBkwutErmaUha5FNL2A41p -LWjyYrQEhyZv+HWSy4MAwMI6flcD2xJDlEH8KIkCHAQQAQoABgUCS6e8LgAKCRDM -0u2U0hc56VYSEACBcgqCCE2VWijE+56Zr2mOnIZt4bvWS99ij6Z8QgJKqhdYYxa5 -Zpz6N5stajEpqqgCLsUsdwkDaZu8JJ/lr3msB71KpSVeUIRoCl+H+XeUGAONTIot -lo0E5t03ZaHJRWyK4JVyFV8BtXNcWE4IXXM+yv9UJDJl56oVsHG7csWByORjAN4Q -ecfzqmDvxEaoZZv4bSUSrwtmSNfopbQypy1J9RsoFgI1N6aQ1pjONzOb+56xZi3U -r5pB90M2Pr65AMmHehxFZenLDukBAYFpab8RGcxvjNMcgnfuwfiKkZ1k4sO4qvpO -vbHMyJPjOO8QPUmA7TBDUmtmGI0Ca9bIxE049JD7wKufp/i/5oosPaxr+jvHix5/ -uYE509+hMsHnft52S6u4tvuFijLJaIidfNl1Jrl2XtkPorSjAYNI5JiEZntYQUx6 -tMD0wuWLFkEbHrAcr7Hbb6c8g4CEyTSx2SgGQE/AjkXnu22YyuFQNc494Smy4vGY -gTQx4WfbsrldiHRRvT84G0To4GrivxVG6rffsn/x3dTpdrPWawJJrjLyvbiIxtNr -J8ckSs7sRgCMBE5CE7Xt+EhqYXZYARPNGe/tCnfrQP4pIHTgVAOSNQCROQJ9F6io -tH9zhvHogmKvfa35r//J4T/Nr1kQdmbnO/Bc3ktp6sJ9oWoztDjZX75fAYkCHAQQ -AQoABgUCUhL5sAAKCRAxjeRVivx5g5xsD/458olw7L2seYGexHsdppLmd0ndk3tC -Frc952jTr+iSxS5nOUMw/fyqsRW20+1l20yLGhQzg2Wy3CCg4M2wPCs8swqw13kU -LQfaVCHiIxdzLFo/GsoGrk8c43mVxAXNmH2Gdl87D+zxX3HEORxnDdl4vBEzPPYI -WUAUxS3X3UYubyX1YAXLr9nXUg519PLlh9z5JPV4TChhRy7SA+ykO+9VVqt1f9yP -Qazmj8i6KcZGhXaaYULopMGp4/lkh+qMbuGEoT9nVbu8DHyDlppFJbNs/Z+T/6ql -PDOsE7FPzDAnhLaHaUHnFM26VCruI2uBT0Kx/dKptPH6oOMxxFmmhcT+wR0GPP+i -UfA89v+2W+6EHT0BFKBB5rPmLb1jKPwsPlmyunr04GsoMt3wNDgde63uOYIWjqug -Q2N7Q/mbaOVsHI3RsgM7U2FxxjKlXP2DHyCCi6RlzClhhkKnYRAJUoPGelnLMtJ8 -yzp0PYBFW9QesKzn7f60sEW22y6LYWZp8pxq3JnnoRChmZdgwWpNJ+Bb3E0qnsyK -C+Ey/WxI44fbRdIWDDHUk2v+DO0eX5WIwwFGabsSi38Thg+lMCNBd+p1eLAhSkgt -N2pujJEVx4UtS3YrpvhOioQYgIDcc/gSXnTpL9rY8JUqkBe3tOgsIzqNS3fv3r1F -v/I2NxZqwi0rhYkCHAQQAQoABgUCU4C3qwAKCRC3YYg7RCi9wIadD/9xNGRKDMbd -UPvfichU9/L8K3pcS369jTjJWAfrDz8Ru/eYO3kKk40OOe2TrEEv15cANYS+GfcE -vIhlSIi5r6tarmiegDVQxr7gsPacTyjVjbLpsYItHdDW86om5tvQNdHvrcMhV41k -uGlXgvl+XC4ofHVHgD23pp+F5hudKRU+IV87DyGCz8tlf5u6FTVAVyjjwhekDtc7 -ItWazZgtcngrjpHwuOA/RK5dvwd5q/ezEPQGPSGqQf4lgqq+zZI1lRtq1KzLdzud -WvUNP1HGlvRQHULB8lXOKgsaMUTTPV40nDRjoxhXcp1HGob/uUU637CPu63jG3pQ -rcEVbs/UqVxvRRYXFUnd5UGfwPh+ieETKL64aHFVsoDKNxubKdFwO554VHtScesg -d+WnBoBAT5M0BzqHcwkZFWGDGy1DwoOXhaw+na5VigSlLbkFZC+0evibO71/+SxU -E+hb0ZWvCc/zuSU897eF8E/vp/39VQyJBiK/MGuhC2WyTkspUXP6gXxgHZIorVxV -g1qNsaQR/pj+iMPANyA0c+0X9VhzTyM4dlZqjkmqFrPPGzDqabONkY8f80qbov+8 -pwf3VNm+x661LJZhAt8NKxWB5rIF/8+gHqWeiv6Mt7Dnuv/iySyEWtspc0r9ZleT -QWkZG7eIRsRjVLorDpfLVYL8+y8iANtk/IkCHAQQAQoABgUCU4EgiQAKCRBdcNLr -ytLJ5mc6D/9G8gr86Z1vyx1rXpjOn+L9kYNUbU6hfnt90rLdDMQ4oybcDp6NNiQ5 -oMDsyJTpBnDbg6+Mpm5WPyr2VQ1DrP+9jp15YCNzGFheRp98Dn0LmOyYnBwhbURB -iAwR9ZyHqzaMfJ+YeWcbROUrRGwNfmFQZqDgrrssZzFCdxCpQdaLJOotfLovcdMn -/GySVVExR4/H6QToOrgTsSGyed6bHf1ej5pKfSvNB6R8jseTYqehWVe2xjqshzhr -Xq0/fPilDEOx5vt2lA5G75YqMVhDPWdFEblUn3C+kNc+Oa4dNtcoZW6oh2u7CQ2+ -RVaPHO3tEywscjd+8zU5vOepOShDU5rMxMK6o97YrK7KzrAbtgSMtka7XCNGcndS -sfXFwmi1fTMHrefs6y7E2IvUSeQV3yzdBYrrtQbJOT/6mAZNMj4RiY712gmN5e7c -B4tu0OTJOqtrYv8wegEcKLcehEnqplVN5KpwYLPC4Y6KyKpjs7BQ822xKHYgmYCm -NP9hAJAMgRmpma1mzsqGJ3uUh77bo/W4DG9eB9cLfQZMZBnY/ccAaYcZ0dLJwwEV -aWUy/DrPsvK2+zb3hmO+cDEhTF3bBSXGY/pFGzyIKNAjfq4v8DzEeODzHI9JWdW/ -8O8C1qUp3d9LbYCKn8iLVTXF1vDt17waUi5+ckiwvTJ4iLb2rvhQEokCHAQQAQoA -BgUCU6SwPgAKCRB0N3+fakeRn/QfD/44iMsZyyDPWZOPU63RQSPYtuoB5E5qD+2q -n/iE8t7cjvz/mOPSjVGF93rw7tFirxGHg9tH1xoyFgEeT92g6yrAO56GXgQHRNud -YFicX98J/tr7NHTn3XZ69bakoOtOqwT/aQ2mx5JFmYXvpslh1GjyosWT+S8gYhwU -FgNyEMnzlgwY3xXx858H0znTG+Qvt8pDuGLa1+XgcoTX9x6sCE7BXE9B+v2D8kkM -zs9+Xj/gn3e5vllqvqHiegwPhrRBpOQ5FpJAo7CL/Y+3mQT4WgAwR/64CsY/T33D -cbsLOD6T5GMkaHLYb02Zbu4Am4rUPVK/C8M8RKxD4VXMs5PLiiY+PaBQDuTT7WfO -zvNtmeOQ9b4Y0dj/yqtgFMxom6gANLcKnpAlHbcDzk4EXf8E9ErGqoEFByfjiAko -vOlDvv6qViFYvYb1FkLc/SnjHl2Btn3EyamLMxRkQGqTgD5bLFyg7EDSmoNGsKO+ -tQQiOcGzfpThbzLbVJjbY9pNUypM3KTLZgCkFtfrufvMXTfjo44V1+uY/aOg3VzS -8coY1LUPrEmRQSdxHv108Z59WBRiHHVQOAWf0LqZecH1WvCVS8yNUMSL9F1XHVYm -koYuC3qeM2TIdy2+nOHKppdH6ls+3wt2OvyQUCYM/iUe3IatD9sfwnBQE31Ute/A -r+kuqbBzE4kCHAQSAQIABgUCTTIdAAAKCRCZkx4l2R4BLFFaD/4kdbZwY+y70F7c -yJu8IMaRVevx+pIsQPQ+wqnwGlishclY4mhAJrI+UcFWM7de0N4lO1RhyX4yOeiy -V++iWGscwg+L0jTb2CRN2Z0Bc8lc8U2mKAY0//rUzEj74zzmUJ82M/MhftMkaBc1 -pqFy7KpPru1rSQKBFsGd5uRxdqp1WhlFO1IA89jftsa/y2lZXLhyZCo6tS1DwwT8 -cw3hNZZrC6wr+InV5r8DloAetWYozyIBvGa8b0mJLL72iXsGj35J1nvEAULZ6wzU -NM1GzHPJWwRajbybXryqGmwBZEXdw8CdjiP2lyvrt284kYh2e2WPQe2IuqMLZgPg -S7soqBj4Q+WrmIxbAMmgbF14xld3bFot92v3xsRoPps0YS19l0YFop4m9J2C3uPg -fpy8xbh+cOrtY/nSH7H7fg9IYEyRJqJ73Wx107dkzY+AF/KAw7rhvQxub63ZOG3P -sR8jfJv7/srjfZW3XmwL4nd3b1+iJD9QU6I9MUVSOC93iqtYppbkcd4z2mFPDOpy -V3X6WiwPzkUFNnWeP5FQ/1xv/3kxiqW9yfjCKiUZOtBnjb9b1x3ueZXzpPQlSEYE -jKuAR8wjkpJPUHNvkmOq0i8pVubjendvdViUN3b6Ye3aBhQu4OqRjE591ZouYyAp -Jt7SMJLDSbt3n2whKo2BFU0V8XzNGYkCHAQSAQIABgUCUfZx/AAKCRCdtbsn9Y+/ -tKYcD/sF3ONskONYHZIBG416+4XgzqeCVYYL7SCERSR4WvRFbtEu76wqjgZTl0JV -9EEKHldTTlSd952AYf7hrmxwz52sChUWQUGIGBm3igdFQ6AQb6HBU+iVICaAHoyc -zlHvj4bZpV99+qCS14llZMhmTRtOHArfKHykG0YDZNRO/QUSEKBuBXuFK2RXuWf1 -35z6EdhrJphnamTuS34g83iGjTckYBp/UIsEhlBs6T0r6MiDedlVTW0jG4ydgtPZ -teMu7azq95WRg7PPANKF6+okPtiZUToQarNyBWy88XYpSSK3/tgqQfI+0PjP3HIo -a+X9YhEzZoIhwzNV0/meeq5/Us/yEE+JuRxXj7Lsyz+8JgKBGaMtJVfTH1RQjHTy -xenEz6DKv6NPvGfSwh6evkW3dr2SFnw9pe8tUDRkX1bGLRuk+iYzyGGo2xgIqNKx -Sz8iY5zbIkFYb3hwlCJ7TH+tdtKs/DXaxyK4JYe8y7ZhU0Cy7XqfjcuSyc7IZD26 -SShzqv7R3v9hngW7VO85O7xAQWUfFej1KT4efrw/HWDyvQLmo2tNKYgKLI5dLt8D -i5az/PCGdZ/nzt1Qf9aL8v58afFuiI4l+YVEGpgWj7P5xTLPP5dB7+1NipbmhtId -4GHQCYMAtETIdPAauNRHw9pOFd9fn3dc3yDPisfRTe5x05wSgokCHAQSAQIABgUC -UfZyDAAKCRAXqDRKneFCU7U3EAC1sMXR/sserwJtiGaTtBMbp1A8xj94WBDNE5oA -amqa2Orho41MbbQZo86p8JonGhZKuDaudzX3UDf1IbMQ7fc6Sj7Ug/MbPT9RuN9y -oV/DIw+tOL2v6rhqtfxCdHf1VqqcMQNFqAU8+N9ULSbMxRsJRIbnSjniBg3iXDXo -TVVonJnX2u6SuLGO3qKe/9DWU9xz8l1nfPbHv8pzul9/RURPXXYQjeNLJb99m1YW -pwl4eBkdzM+LWHWyyoBJ/gTRi/nPABKSFBcWb0u5ia5knmNg8AIYhRLh+0FTzzYV -a+Et3iH55h4SCJ8U2vcbgBSbAjhn5zVWKIvvPHivXHC7epeBOpDbqLhjdtdrCoqB -H2K9P4oVctET61EwHUG5VaocWEA/HYQySnzydfgJw4sp3N2HoTxrYForQ+Y2PU7r -13UJ2/DuCsvjya4LFkfcbutK8MhAW9KP5nKbLlHERiMz8uytRbyYUy6J+PcJZw2H -S7095joNqPAZVUj2+JhDI8b0TqJpbQCw8n2S2UeaizZ43zdIOdvXSLHySH5FuHfS -5hv/CHa/oEeI16SCWpf8MAb0FRH5pTHeayKe+d7oBx4ZmVe7Wyap/rEIksTvXj7T -+bcTahZP+QNdO41qXu7Khu0JxjDeneDQZjhWVxENasdUp/hJ+/KJ7YJu+D5fba4J -CuuApYkCHAQSAQIABgUCUqU0FgAKCRCQe35tuBCo6gzOD/95niQemYpdXGuW4LnK -2mqhMsf2p1ho+uQu7iYesFMR4R3G7Pty4oS0g2RRifYqUuq/V5YC/urfObSMlAeI -XA9ll8PNwCykYbx3PtzQ2PPjRcU4WReAVXqRlPPIckzivPpAXTX49mGZmOh6WqhE -Fe6He0LnjNQBundiuCCt9EcmAi96DCje7xUz56VagNxzg54f82PK1HRRTzpyA7yT -sNh4HzWKaqQgAQQnx09N1ui3zk4uEu8BjOau5WjzhpEPFqd2YjYXGZLDAckjeUPj -8GtYXV1n+wTXOj0oHz6EJJXIAs3Jiy+8ZzBZiMGSZ/qSyt8D+dcsRQ87MxPjSrrA -1ximNrat1NntCiz65WrJ7+Y5PAoVUDvpzwW8zVpn+DjCPsJIfEbxIKeUxVvj10sx -e3xu6s9Ox32NU8w7Tjzr39tqxyXiQNPY7LTPSyd04V0NPoFm3QTNRpO/MQCheU8P -UUQ0cyyEOtvdEHRAUyoJNNld1dHqHgLH2Gkf3z5iRu/xRMgHv2rIwhNHaI7BH+xe -kqW2JsygOn6uCiuyi8TTojBSVkIo78K7CY60DkvCdxHnoXABEnH37kfJeTnZHIkC -znNANnfhiE9xRlj5GhiRq5+I4zazmTV/kVRgqGsk21WmMlZcSjMv8j60agsxE/I6 -1pyih3YavwO3KP9Z6fsnYbQ4zIkCHAQSAQIABgUCUu4VlQAKCRBybazw2G9AbGIZ -EACI1Xp14AVatkOBaqg8J6fKXN2C2kO33THwbdpYfavqHIePAsLeAvfptwQq3HGc -nP6JBss+W5vOSdaI+R8zT+7u7OZ6f77hsmMXt6fr8xmnFxe+bU4ZdWnptPNFU5CX -kfANVt8P+O+kfqjJDReAPnkpK77QnaIX5VwhL0gt5eV/7ALPGSANL1GnfUXlBCdF -orU8ZRS41ft60ZJGs5ibFkHfeChrrTV4hkRqckWTZk2XiTHVr6aLmFXZPZu9DJ+F -iual+TLH7csJSvkOvdQMz2dS+ObfwPYhKcxGcB1tGPY6dGZRRc5qJ4UR/d2y6SEa -qC9ip1QPfzPI+xrdBN9Uk1yvOyjkLmJCV+Yk4P2cGs3rzdW78vQxD6vGw/whMzFM -JjNifOBJrCSLyZGrLAv+6zOJ7kW2VUmvNkmn8aVII2vnsy4a21BQYFXz50ua7Mck -+wGFnBy7lqfQNfMJKmzKH29J3uV0w8FyUMcCqR8yJuXW4yDwcGMBPpn0m08DMDCP -317DOFutb1AOFzh27OHr1c33DVOq7GVTeV5tCjwxZrEYrvusO+edJw2NCI4wyWYV -To+c0nIzDimcMTN3ckT+livigRIFs8m1Wi8IUJSpNGrEGqgMg2uuIo1XWgb1Q8zO -E9qEyJf45BF7zFbHo0kGdKUVaOq+c7W2J2gvmu7SAHcud4kCHAQSAQoABgUCUiyR -uAAKCRCGWuZ6XiTgic1YEACARCb8LAhKfzcf5ILpBfXu7eV67inemY789rJg0Dj1 -Ev2LHgzKlcbV2Gwvs0WQjr4o/zN+Qrak4W2to+PB+xtrGadIZog6o4SYjl5l7i73 -b/wXH+clPnvbhMS8VddCs4G3eHGzWHalnVfGVZcNITbANH1TBNaZYq07RjDidrOw -DxOiCXFITCtb49/tYTHYUEoXPQvH2iVe406APcDIKDp2JrsMqGmKXMbogeDPSKFd -/9zuplVHGzbzTwbhgVEbuLgF1TutwJtkjHh4U7G63cSEhNbsz7f+fcxI+P5K2AH0 -q18ebjxip+b2jT5bZoa35c9r8LtjPhXaHFiaKmuy5Z6IVIb1OVE4s6iAWCbLr10w -tnLli+Id5R352yH1CnGVdwh3HIwuGOKucllX3X1w5GuVZ7CLn6sY+cUfDoPZy6vr -7DTj+xTlFruLWGOqJsuR/6TbR5zQsRawWBQQv7OBMwAx2x0Yx3QjF6/uZ9kV9mab -C85IDKrRI+OQitvs0hy78xRzZGDDmu14AePe1XQgqZe7FQyj9hmsy//MAdg5gWEy -dcWemjI0fdLjOVX34H5aqXMZgg3T3b0NsxoC8pOY/DZsxE6VLWW199xF4bjDKu9K -18vQRw5GXWlHkBq+BRp6UJMU7jAQc/vDSEQPXVmfq7be62o/Anph+Yrlt7H6P2Be -hYkCHAQTAQIABgUCQLtaYAAKCRAIFBnDC0N6iSmaD/4rG0Tr93dQ40WNeSyr5xZv -lK/1+rGlphHlLn+S72sQFiaiPiw27XYETmiAcTHnUkpRLvnPJFrlEF+43HeNrnmu -8KZxMOw61lKmKI4nnkFrvSGt9IiFeAyDQICktgNWNetNxxJjnJWIhggt6cLxMqvW -zGal0newDwycyNqCQfYzWVNmpsjQjfCo9dE7YjebcbuFHeTBgSnebmfdO7JLQnGC -efdbXJczEavYLEi5fOihwqjZibOaURXvZo8aGY4VoCvkAMNhgHdg8gBeH2LvUXMH -ndCEaV4aJMdNN1F8ioFdx3+ZpYoYg590S6jEXILj1yaPsNVuqTJo8V93wfUwKWju -3EbXdcf6VLqgICBmM4B/q1auLEi2lWRG8eQKFEpvN8krRIqb0HLpEotw3kR28rsc -NGrxJyfLj/HH3ERhdF05bjdM82febXYZjx8RpI135bOSTt2GFG3yQ0B2UybBhM5+ -S+qGX3xl4grSGUW95Mx74Cew7ZK++KddEEIAOG5+OUxUoEmR87cXhDrE8Tj+V9Ev -uguJSceqTZgaz+9NslPThhOxIhuiN73hk/G6uFe5bfdvnYGgASKZu3rB2fy8TxQS -BbguvjXbYmqWyqKd/sS8KD0enakc896MRiv6S5iwIBm+s+XULA1wf/WzJuadUAJY -Z9sd3AyrKxMYaDk59X3xUYkCHAQTAQIABgUCTPn6rwAKCRAN+KXPnVGk/NTWEACd -tQ497pJG+yvxgSsS3kp1nWF97Cfp11dzbQM7fwKEcMCC7i+kl5hYcKJ8p99stAlx -Vw8JTfwZ8b+YhBCbIDQAx3Vgcv+TTbLcT6+szCzPWyJcCykE6IKBys3Q0LapSTmn -ChntD7qiAbyjMjQMmUOIl5BaKbcqOLCTVp74DOzeNfSqGlBG0ajxs3CCibC+lrTM -FwSGm+vIumLdzUJuMvMwcEbEwoGK7FO0i1qhfZMvn4F6tz2x7lJVXGBEkib6n1wb -jEW5bfnGk1lb/09yRmNX13GRoGIEGmeUCmHrM43dErJfXh7/SWWL1N4422F+F0hA -2SkDV/7NihLUHXmiPwx3D83GQWVKsHONtOAbswdXtRD15rSOO4aHIhMchwBNJS84 -+i4LDCcZMMIdbI9ZvbqimHBeuQNGvJzkd3qsdMf8o0NS+gJCV5dR61z8HpgermPI -bOwY+T+dst+PUh5OZjagk+qC7tQ+nIO4wXguRxX9h49KjdiY6bnEnatrHH4yzeeD -4iOmj3DOw5PeRSmEVnufwwz9CjtTwZM7mAxlHpcC9ZUGVyBVJbZh6qRxX7f9vC3K -GaYQDBrIxOwS7ouDClFnpDha6kSud61UDjKBA8eW+UTY5xzfCpsA7gnQT1SIxg/T -6JHghlkqYdMt0KKr7nVEjnwpvX9VPJZU48ZZ4pwLgIkCHAQTAQgABgUCTHVazgAK -CRBir0AxyC4AOU5cD/4tqfE3PTnQoXd3N2wlVJqitsKqy4pLBuKQixuwHGJnzmUe -UBz4uXNDTU2BHx8Eom3DKpTA2pzwaBOv5FWuP7HrClQE3Zq/TCSmZwem4ltGWUww -L3wpJ8I8V0Ks5+GHgowVzPCYGXQUcy9ZaMJCzQx0oaezmDyFYsSs5W+yAXLPzdBj -FevuMvCbWMHtRgU4CDjIHU6dwuPshwX98QsOi5Mi4V1UWoHynuV32Qctq8n3Me9c -s/NqrFzi8vko5C+l5uhD9CVXb+tsBWpvNHsQYhfzKOgde216Iw0rpFYPpkkgsYQO -3knsMBKUSme8KUNDfNB23geGj2jZt3m0b56mj/j+R9d8lNlKEONdWFWOQcNd93BH -s1PV9V0JTYy8YGIbP8hjeRxhNAJop2eiPAI4plqu4mGpg83qIaARkwtJkWwe0WCO -Cwznmqbk2otguSCoMLFx/u5d6Hl77ZXx9nBJQxVHETS2o2fOO+jnZnnIjCjgx13D -1weYyu+q6+QJ3GO4s6DXitW4dxNdwBR0x0VQaOR2ui9XKuLZtgkXq6L+9SGYNpYW -MrhKAZWr0GHhaCTpclaNujN42l68PB2BtVgQBFUwVMdOM7MKH5HDIJJ0pfNQGEh3 -QKTRR+rkpP0LD8OMX10fe7dYS4mywSiGWnmLHVtaIR/vSl/8f7y07b7gA2kelokC -HAQTAQgABgUCTXudGgAKCRDqIQJPqFJUXRkwEACYGbSB1X40KkjVYU+9F3aWvb4R -ansOyAzdefmlJolneuIwacRDEBJShR8vd9YzlkCg+o+tgTbJ4L5xboSuMq9Y/wbI -BgIZLBnXXmE8s1xZMcZhvpPiZ1sjxgLJqjTtWKXTMX2lPYO3RmLETCAaU/8HwKdl -oIb5fJfUJtaukjlkZ03TDvkrJ9J+XqSPFY3u5/G5r9ansnp0yu3nt8c6K+ZAyJRq -l/AsXtU3dUQGT4CwRpIuHK4P4zE+4oXW1PT5CJZqIFbEX/zIWqoNtgc50wLRlYA8 -RynO9A19gvzXYw6aWNGkp+an1g9uiuLcmEsZl5G90oO6IEFYfx/aPb0c1jaSX5mJ -XeRHUGtiPN/YM7lQqPKQpClRRJ6B7pW85YvxgLqUIcIgllgNDTaMnW5W7MeJ1JJV -eZI4tI4OBhXzfvs5zP5cSTGqtl64WptSM7563xG06pUwNDBl36+VGnZH4BMW2Hpl -Ji4pkQGfVfCVFmhYlgBjRs/DBwdO7ix1vKlM/Sr2jEJSuCLYJKluZ7CUmS9OdoZ+ -pEKGl96suis1BjOqOsBXVCtWe9O2g58PD0R3FXQzGwoKlPt50XUJpOgOFL/KybcL -52O5WLB4eSBhCEeQ7e+8ta0IvaejBOnbTAb+O1iMZpBE0thAyfgBNTvNHnbYVkkv -uEwA7rDzSyIY3Ag534kCHwQQAQIACQUCT+X7/QIHAAAKCRBxd0Dbs16EdFkPD/92 -MK8qe1NVkaj3FVpNpew86b4Wuu6iFZ7gpjVjjRTAdVXqhdm9uySCfKSfX6LFOQRZ -Vw9muwZUiRkyLwIqcAUfBEVE4T7Onp+lcayuPAFTt54nTQhvY4dN2U0bud3f1s0w -Fr+C0VDc6SJgNhj7JbV4O/8ARAoDx1GmaWUS8h0EvEooC0UnaHx7i5ABVVah+8L9 -tPleu7Smmpp1kUFz+I1vHI+T96DzZodBNjtnSCjcGKriL4Dj4V0IZ3rKyFob1F6R -0mIGVA5kPryISujySTWu49G//juRnbqmGKCferZstpBD+aaclkXsHw1AiLWkbRzD -awMYlVdObG3q6XPWqe1Howk8AR/spAPfXPV8rzNR1BRuiEOmZZwXreO3Giz4IlN2 -W+LzXhvy6YeRyWwCKEs2U66OmPUEJPRQt2k3nJdtd1d32RevksgTsQCKR/JUDkmZ -OMFRY0TAK6E/pKQwKv3Ru+ULky080ZgT58eXTdtX+doBg4YOY9LjN/AFsKNyTdXu -z/IHSKJ8Zl3Qpf86h+EmuVIli20yPAOllqovx2ObSOD1dwSAjDeWRUoXhg2fj0B8 -2uerd0f1+6Hyt0v7biBpUtrUZR0U13wSHfuuuI39QPxTUyQ8PRuewsir7esKroOt -hRUJZ8eZyOAAYJ2k38dsY4xxI2gJqfanxhUnkVRP4YkCIgQSAQoADAUCUuKU9AWD -A8JnAAAKCRCtp7Jf52Nw1rCyD/9usTBs0ijp+TxwmYqgaRupnUQ8Zw0OvcN2yGTO -kfEjT13jlEkiV2pC7Y8OYTbQ8tiGM6TkDUV75qFLMV89SHwQDG/I1g7b669Ju+ef -WbW3Wy6ZCOTuMSnJyL3XBw9uQzAsOaP1qrZtD9L2P4j5av5/cbvM/gH58aDCMNFg -gibEE6frEecFHl88Z2Yc8m6pLj+JG//QuRaNKQYZ7CISVar+uzLiPThXp5FFq2Ic -fzZMrShC6xEnnklBgUKJb4eKDY6GzyNjayRvOuitK4am7FV/gJaVSdvL6W8Uvszz -c4cMaMF3V4++lZGS8yhzorLPhSHEwt3WZ4KECwnDHh53VmGB27RnwdGC+wAdTpC4 -wL0IXH4+lZXXIG2H4NtSE9cSfPdg5m3s0aPDrb6FbV+rmQEsWgVxfzRlGdgusqW3 -v+ZO34A98fQPIA4GSP+HRc9E7GzBURN7C2bMY9kDAweulvn/HghL3ljDwzOWCOz3 -0qFMzwyM/1jrVDh9lX1jK3bRPPuujTLsyNVHVozblY+sTR8abtNC7EkbfDYbhfdr -2P3lF4UkoBhMMirz49+yGgIoZ7MJgFrRK/jSjCui/w6neHqdaZYwNVX7WYTaTCJY -D2k6OPeAgOP1Yh+7grcJXPdeuiq1U76HHP2qSoQLCUmwXKW8S/ZO1NiFyAe5oOZ+ -6Yt0SokCRAQSAQoALgUCU7vxVScaZ2l0Oi8vZ2l0aHViLmNvbS9pbmZpbml0eTAv -cHVia2V5cy5naXQACgkQExjvrF+7285t8A//WLCSDm8unq+NEEIEihAWOkaURk8h -kxCxamlswMHy60se1GktLbUkiqjLwLVmXEK7HxrrZhF0b8tMdINhTKL1yv8gGVlK -WI0ngCPHt5I8bFQp12cXxIgTTs+gMA3TL444eFu7pM6CY/iw48U6k2dye2inW/UT -hIcBkYKUNeITNEaW2enBFd0eo4MJ/5irU5kh0FbImXKiDaJ2LM5hzHNm3JuqYOYM -7RxcUS/zsPyjFbfkx4vtmJXx/MiSTzO45Mmoj4O8QRsNizM1TvEn0QtNux7CsaYF -UD2UDDg0oYOgepCQfa+lEtJAUSL6/58tcUZU1mk2RHOay/jXGy9BQXVuiXl8SDzO -z5BW8zRR76n3qjBdvWXySLvhxK6DuE5HIqZa6zQ9KgjV+GIAy8h4exVYKOSKzcx6 -hXBScW/W45l+S/uJemTWvkBfGbo3VU+ToAheDt25RnisQODw6nMSSSzfhUpZ+qnl -Svjn9rnJdCbEcn2udTChnM4N3HN5gYBEbTUPM91SsYKeObKLJ5wEfJSWuwcoNE3M -UjojJ6yNBODsZIn0MSZfc+LYdZKeAZY1tSFR8Frp6LXsQqOfX4kyaHniX0KXTYbT -T50eYNoe7hydgTScXMsrIe3VxOTh7MNFDe2J+UBdoTVWx3tfTocQ9EeG1C0cQ2/q -Jr5uBYfebnydaVaJBBwEEAECAAYFAlFIqX4ACgkQa8dYy8EfYnZkRx/+NSmDfiJ9 -I1R2XPMHBt+6XndcvUdUxsiiSC6HgXVWd5cOvo+LC2RcdIOHwki1BFQrgHWTeDAZ -3ABSzbCUcNc92ToyQ9xygbPQHZwdRnr4qPxihqLeU+tHg4OPSPDmUaIPGky2Y1WQ -UsRVDWNCqd91kT7wEhutYhVO4I2fiw4oSBKgT17ReSoeqs8bqlHdeh4ROlSrJuW+ -awqhgZ3h7TTpaLXEaI+jsd8QLkawc5jOtxRWgSiofyhLF2SUByYDwpSrUvFsL8Oy -EYOFSfw+ULPQSMNA9XmJSWlzrVN2wAH/atczMlTnavYk7Ih8NuHu74GOBrqSGeFO -lPdVloNa+sqF7uIoHDd2+OL1hVyQxSo141cJ2azlNGkHoo/GHlBhmiCPuXIb9raw -GDV1eSvTItBeEOcVzof7kldvkT5/HKJMscZ2nQKqQF2cab6zMg8io3/dNXwXlSAQ -biaxqzOytNTUGE3YBzKaHeg7Ani0lQsvHXjYTXcG7oGL7wsUrGeUmN26HIWtJcOk -KajAIqORCxZbmBd1NOvSIYjzYiwWLDSTsLbaA3ntnWt7UZt+WIkju1L265jxh3OL -c+Uou6n/XApPC7qy1EooSOFt6UGmIyDp+gn27k6zU4IDGuUOOEpL737tthqMvVXu -oYo0Z+E+MRaITZvmCcorGWFbaRcAQjQRTsgZrLi/FYBcgwABOiBrkaXg8xtbotDJ -x1GBKAp2g74jvSE9nDDiidSHR7Nr4ZwtUsIQXAm8Ph0B5BJWvB+8qMfh0iF3pDTk -BkkP63stz5Sz/QfE9AKhUeC3gg5iek8BB8HFq25BYZxENP7uJ8RvzEOgoiCJI0Ol -PQzhptD+1k7SGE2fW8/D7HmzhXgd32xdM0CIg+7p5F+3/ax70gZPAfHyi+HKg4N/ -JfPpsI9dd8h7CBxyLD+Fbr1llKcN7P5YHjKBcfKn80kkLuA+0dj89QZX853+xgJG -vGpvMXlFD0GgbebKEtJnMI8v38aDwZEKRQxFkW4Gcw6KdrNoM/fw65YTGAILXoBu -xxNcp4U8kBLHtFnEE8WPMKcwy7fFnW2Jdpp60K4wOWm1iRmPDousDz7FwiXR0Vi3 -bbNFutnNON4OhAGPH/cZE6d5P3EEt37k1/0xNUdkhM+qCDn0SzX6JmChkn+46q4I -+lKvl5sTT4/lVnmRst6b8PbjdDiH4yWjPNXqm0q6UPHXLOO9khoNexrtJ9XS5fO2 -OTyAWcyRRnrFlmEqDfVbMyRB6lUuy3rTzJ/09p1uY4stcQGhVJqNJ4RPcHeftlOw -EFE8q2RAe6tE9/QghWUlRQZHRGbNOPm5VMu/FAuYCZ29hI2q1/xdjgr+LSZm/TQf -TFlRFj9fhh7CJYkEHAQQAQIABgUCUf559wAKCRB6Y4Cd5RJ2It7mH/4n0+wA9w4x -qBDonKA1cTaSNKiHhpw9DUlj57KvEmolLyhAx1whBJk/hSmDbevKj31Ft+GjelBK -GAl0JcqE16zcEcADW9s7ZoS8LuKUzgY5DFBqmfmPjYvBA43p2EEZ9NCSvfKMRDaX -XpeFdXGwggC83OAZDbGuZcMHJHr2NbGHWDolEE6BNh4qQq/13sKayW9ouSt6xhLW -A3gwvJSnyPvonsoC1Zz2D0jm2JA4fXHfSEVqJAo7LwVQ0eYX2xDIL7BUU3rvHjT0 -h5ZDj3ROkhenEKnQQqG7jYga/syI5hJXqu110GTD1BHJ7pfJW6fk/fcpZ+4YXUpo -ZF8+SZ/TXWxjJOWVLPiDxluTwCM6nGKiXcgg1+gEXvIdmC4VFdxQVgMS2r2q+vt1 -XXMyr/9XJjl+WLWjJxrsWNmmUrXQN4ggGiD59o88iYtjP86HYOyvDvrHHm54YoWj -G6qhqTyvaHsObQuTE6MjKnp944MndGuzaS2TXT5QEQ47F0RKsH5c2TNCjZqlCh9j -zHMyOtOYZMNIrJBTnaP2OOsq8NK6naZWBMavTmK8ZNKchQ+HF/6u/5z68u3yAm/P -xtB8H89xK6sA2BZAn1iWf+zeKsa/zVGHqJdHlgM86N1wQ76jp+G8nE+zRk+jo+UD -AWorK1Iv9UN4Gn532g38Z5uNmIpzLP83HF/lyPmP3pK0+ILp2+PnM3ftJ+gxdNUU -T2rw8+Y/2egrtp/99QxFe7S75lTkKZK11bph24kSc6FUy/HSWOv7EWRt87SOurYD -Fe6t3KaS98irLQE1JJ9sAOaujR9ktJuSG1ZnvOg4KCohHFUF9JQ6d0dBe+gdXtcU -dNo+XS8acrCmwFvkfj1WMP8CsU22RNvVV+XVyvmJZe5Gea2nf6qTRQrFwJWg962d -JZS6E36xUgdnozjF7lo3C8/6G66W16agkY4xl9mK/vvSWVQPtdS9pucO/R6BwG3m -g1MrF0RzEztxCp7aMmfbQ0Ksh1kpoEiz5eogT9s0E8Xz4P43gl1KCW5grFQG/Cee -sLsYiMt1XVwPg2MQwC7NgBK0uymGw0X7KJEtpViX5vQcCPh53kjo3PbU76xVTh5u -oEsAUxkPai72PpHRHazULp+5jlyIDst6xakHHj24tv0Wflxm9U1f3rDoxUqJGvmD -Z3M9thC+6oLi3YXAo6tm6Q0h7KAf14MdksN2pyz0tIaBO9ErJLrxEqrtetdWBbXT -evt5BzUbVG7ZKGm2TKzcWON7Tp/RrJ+sUGaeJ3rmvo8lvZaZwvkEBB1lTpkxSMri -1TnYdAz0/mUqkHC/fW9zPG38SwxzjKGZjBFLa5sGV1g6pbaSlMnvWalQfP2O7Wix -mtFA9zYgljcHuQELBD+OYqkBCACxteL3uSuHXxTbj96uyuHGO8/luaqKksuSOU98 -YcE3tDtP4r5I4aL5FjYgR4pucaPkXx9dbC70tMuQlCAhTIiey2AKz5E8ohbSKG4W -xd9KsqRxADKtSIH87kCQcifZK7qw2u8fZXoHT6AecJ87uy1Ud/l7hoAUa2FP/kcB -5F63Yv1iGbKjcWHcoznU7uKPjxXSBut54ruNZ8b6loaxY+Teh9/54o3xzu3uLu0f -/P13Q5zCTVMLoTv2/o3dTb5Tq6VTJzBd5+vM/NVnGRje+3stFjeOVLbvYfxGG6FR -t2N39Y0jSDY0mPE7GatZcIS/uhp5rFQ1wqLwMlW2HAv3K0EtAAYpiQEnBBgBAgAJ -BQI/jmKpAhsMABIJEEFvBhBj/uZZB2VHUEcAAQFcCAgA14Qh3zxTJr9cMKzun2O+ -HVOXXV+VbhD/sbM/S0+8Zvk9Yw6J8uR+ovC6fZLMERB1w0On8DlVJahHf9tIYM5+ -LYIb1AfOPZdPZWJTbXQVn52zt/o4eIqSIPCX9KSLAXCekQUUx2RUSua3aplOP1TI -IKdcWz/rVqM0UMIAB5TYEX902pKxht7RQdxWNTj6gLx2ssrFrFv4YFvY97o5kQgE -i59hf/+NLaZghFavrfZDENODi+gawBaM88iRmlxuZORMWuXQf77DDw6E8AzB3q6T -Bl1ZMlMhMgK+LGah/dqLSO+6KdFJWyEaHq0yMOkxOgyiJLdztLUAwXEvKICDw5eP -qg== -=QqHT ------END PGP PUBLIC KEY BLOCK----- diff --git a/src/upload/tor-browser-linux32-3.6.2_en-EN.tar.xz b/src/upload/tor-browser-linux32-3.6.2_en-EN.tar.xz deleted file mode 100644 index 45b983b..0000000 --- a/src/upload/tor-browser-linux32-3.6.2_en-EN.tar.xz +++ /dev/null @@ -1 +0,0 @@ -hi diff --git a/src/upload/tor-browser-linux32-3.6.2_en-EN.tar.xz.asc b/src/upload/tor-browser-linux32-3.6.2_en-EN.tar.xz.asc deleted file mode 100644 index f540c1f..0000000 --- a/src/upload/tor-browser-linux32-3.6.2_en-EN.tar.xz.asc +++ /dev/null @@ -1,11 +0,0 @@
diff --git a/xmpp.cfg b/xmpp.cfg new file mode 100644 index 0000000..0b2f547 --- /dev/null +++ b/xmpp.cfg @@ -0,0 +1,19 @@ +[account] +user: account@domain +password: + +[general] +basedir: /path/to/gettor/xmpp/ +core_cfg: /path/to/core.cfg + +[blacklist] +cfg: /path/to/blacklist.cfg +max_requests: 3 +wait_time: 20 + +[i18n] +dir: /path/to/i18n/ + +[log] +level: DEBUG +dir: /path/to/log/ diff --git a/xmpp_demo.py b/xmpp_demo.py new file mode 100644 index 0000000..144f4a8 --- /dev/null +++ b/xmpp_demo.py @@ -0,0 +1,7 @@ +#!/usr/bin/env python +import sys + +import gettor.xmpp + +bot = gettor.xmpp.XMPP() +bot.start_bot()
tor-commits@lists.torproject.org