From 2f69f9a0db2a3ec43c84245c9f4b628ac87270b8 Mon Sep 17 00:00:00 2001 From: John Date: Mon, 27 Jun 2022 16:11:51 -0400 Subject: [PATCH 1/7] Initial work on ESP32-S2 support --- Distribution.xml | 2 +- Main.py | 237 ++++++++++++++++++++------------- README.md | 45 +++++-- brewflasher_com_integration.py | 16 ++- build-on-mac-m1.spec | 6 +- build-on-mac.spec | 6 +- build-on-win.spec | 2 +- build.bat | 8 +- build.sh | 2 +- requirements.txt | 7 +- 10 files changed, 202 insertions(+), 129 deletions(-) diff --git a/Distribution.xml b/Distribution.xml index afb917f..807b3ef 100644 --- a/Distribution.xml +++ b/Distribution.xml @@ -11,5 +11,5 @@ - brewflasher.pkg + brewflasher.pkg \ No newline at end of file diff --git a/Main.py b/Main.py index d2976b8..39ea4e3 100644 --- a/Main.py +++ b/Main.py @@ -1,5 +1,7 @@ #!/usr/bin/env python +from time import sleep +import serial import wx import wx.adv import wx.lib.inspection @@ -22,7 +24,7 @@ import brewflasher_com_integration firmware_list = brewflasher_com_integration.FirmwareList() -__version__ = "1.2" +__version__ = "1.3" # __flash_help__ = ''' #

This setting depends on your device - but in most cases you will want to use DIO.

#

@@ -83,32 +85,32 @@ def __init__(self, parent, config): self._config = config def run(self): - try: - command = [] - - # Fermentrack-specific config options - if self._config.project_string == "" or self._config.project_id is None: - print("Must select the project to flash before flashing.") - return - if self._config.device_family_string == "" or self._config.device_family_id is None: - print("Must select the device family being flashed before flashing.") - return - if self._config.firmware_string == "" or self._config.firmware_obj is None: - print("Must select the firmware to flash before flashing.") - return - - print("Verifying firmware list is up-to-date before downloading...") - if not self._config.firmware_obj.pre_flash_web_verify(brewflasher_version=__version__): - print("Firmware list is not up to date. Relaunch BrewFlasher and try again.") - return + command = [] - print("Downloading firmware...") - if self._config.firmware_obj.download_to_file(): - print("Downloaded successfully!\n") - else: - print("Error - unable to download firmware.\n") - return + # Fermentrack-specific config options + if self._config.project_string == "" or self._config.project_id is None: + print("Must select the project to flash before flashing.") + return + if self._config.device_family_string == "" or self._config.device_family_id is None: + print("Must select the device family being flashed before flashing.") + return + if self._config.firmware_string == "" or self._config.firmware_obj is None: + print("Must select the firmware to flash before flashing.") + return + + print("Verifying firmware list is up-to-date before downloading...") + if not self._config.firmware_obj.pre_flash_web_verify(brewflasher_version=__version__): + print("Firmware list is not up to date. Relaunch BrewFlasher and try again.") + return + + print("Downloading firmware...") + if self._config.firmware_obj.download_to_file(): + print("Downloaded successfully!\n") + else: + print("Error - unable to download firmware.\n") + return + if self._config.device_family_string == "ESP32" or self._config.device_family_string == "ESP32-S2": if self._config.device_family_string == "ESP32": # This command matches the ESP32 flash options JSON from BrewFlasher.com command_extension = ["--chip", "esp32", @@ -116,80 +118,127 @@ def run(self): "--before", "default_reset", "--after", "hard_reset", "write_flash", "0x10000", self._config.firmware_obj.full_filepath("firmware")] - # For the ESP32, we can flash a custom partition table if we need it. If this firmware template involves - # flashing a partition table, lets add that to the flash request - if len(self._config.firmware_obj.download_url_partitions) > 0 and len( - self._config.firmware_obj.checksum_partitions) > 0: - command_extension.append("0x8000") - command_extension.append(self._config.firmware_obj.full_filepath("partitions")) - - # For now, I'm assuming bootloader flashing is ESP32 only - if len(self._config.firmware_obj.download_url_bootloader) > 0 and \ - len(self._config.firmware_obj.checksum_bootloader) > 0: - # We need to flash the bootloader. The location is dependent on the device, so we need to use the address - command_extension.append("0x1000") - command_extension.append(self._config.firmware_obj.full_filepath("bootloader")) - - else: - command_extension = ["--chip", "esp8266", - "write_flash", - # "--flash_mode", self._config.mode, - "0x00000", + elif self._config.device_family_string == "ESP32-S2": + # This command matches the ESP32-S2 flash options JSON from BrewFlasher.com + command_extension = ["--chip", "esp32s2", + "--baud", str(self._config.baud), + "--before", "default_reset", "--after", "hard_reset", + "write_flash", "-z", "--flash_mode", "dio", "--flash_freq", "80m", + "0x10000", self._config.firmware_obj.full_filepath("firmware")] + else: + print("Error - Improperly implemented device family. Update BrewFlasher -- if the error persists, " + "Post an issue on GitHub for this, and specify the device family that you are attempting to " + "flash.") + return - # For both ESP32 and ESP8266 we can directly flash an image to SPIFFS. - if len(self._config.firmware_obj.download_url_spiffs) > 0 and \ - len(self._config.firmware_obj.checksum_spiffs) > 0 and \ - len(self._config.firmware_obj.spiffs_address) > 2: - # We need to flash SPIFFS. The location is dependent on the partition scheme, so we need to use the address - command_extension.append(self._config.firmware_obj.spiffs_address) - command_extension.append(self._config.firmware_obj.full_filepath("spiffs")) - - - # For both ESP32 and ESP8266 we can directly flash an image to the otadata section (I think?). - if len(self._config.firmware_obj.download_url_otadata) > 0 and \ - len(self._config.firmware_obj.checksum_otadata) > 0 and \ - len(self._config.firmware_obj.otadata_address) > 2: - # We need to flash the otadata section. The location is dependent on the partition scheme, so we need to use the address - command_extension.append(self._config.firmware_obj.otadata_address) - command_extension.append(self._config.firmware_obj.full_filepath("otadata")) - - - if not self._config.port.startswith(__auto_select__): - command.append("--port") - command.append(self._config.port) - - # command.extend(["--baud", str(self._config.baud), - # "--after", "no_reset", - # "write_flash", - # "--flash_mode", self._config.mode, - # "0x00000", self._config.firmware_path]) - command.extend(command_extension) - - if self._config.erase_before_flash: - command.append("--erase-all") - - # There is a breaking change in esptool 3.0 that changes the flash size from detect to keep. We want to - # support "detect" by default. - command.append("-fs") - command.append("detect") - - print("Command: esptool.py %s\n" % " ".join(command)) - + # For the ESP32, we can flash a custom partition table if we need it. If this firmware template involves + # flashing a partition table, lets add that to the flash request + if len(self._config.firmware_obj.download_url_partitions) > 0 and len( + self._config.firmware_obj.checksum_partitions) > 0: + command_extension.append("0x8000") + command_extension.append(self._config.firmware_obj.full_filepath("partitions")) + + # For now, I'm assuming bootloader flashing is ESP32 only + if len(self._config.firmware_obj.download_url_bootloader) > 0 and \ + len(self._config.firmware_obj.checksum_bootloader) > 0: + command_extension.append("0x1000") + command_extension.append(self._config.firmware_obj.full_filepath("bootloader")) + + elif self._config.device_family_string == "ESP8266": + command_extension = ["--chip", "esp8266", + "write_flash", + # "--flash_mode", self._config.mode, + "0x00000", + self._config.firmware_obj.full_filepath("firmware")] + else: + print("Error - unsupported device family. Try updating BrewFlasher.\n") + return + + # For both ESP32 and ESP8266 we can directly flash an image to SPIFFS/LittleFS + if len(self._config.firmware_obj.download_url_spiffs) > 0 and \ + len(self._config.firmware_obj.checksum_spiffs) > 0 and \ + len(self._config.firmware_obj.spiffs_address) > 2: + # We need to flash SPIFFS. The location is dependent on the partition scheme + command_extension.append(self._config.firmware_obj.spiffs_address) + command_extension.append(self._config.firmware_obj.full_filepath("spiffs")) + + # For both ESP32 and ESP8266 we can directly flash an image to the otadata section + if len(self._config.firmware_obj.download_url_otadata) > 0 and \ + len(self._config.firmware_obj.checksum_otadata) > 0 and \ + len(self._config.firmware_obj.otadata_address) > 2: + # We need to flash the otadata section. The location is dependent on the partition scheme + command_extension.append(self._config.firmware_obj.otadata_address) + command_extension.append(self._config.firmware_obj.full_filepath("otadata")) + + if not self._config.port.startswith(__auto_select__): + command.append("--port") + command.append(self._config.port) + elif self._config.device_family_1200_bps: + # For some reason, this code never executes (at least on Mac OS) + print("ERROR - Cannot automatically select the serial port for this device family. Please explicitly " + "select the correct device to continue.") + return + + # command.extend(["--baud", str(self._config.baud), + # "--after", "no_reset", + # "write_flash", + # "--flash_mode", self._config.mode, + # "0x00000", self._config.firmware_path]) + command.extend(command_extension) + + if self._config.erase_before_flash: + command.append("--erase-all") + + # There is a breaking change in esptool 3.0 that changes the flash size from detect to keep. We want to + # support "detect" by default. + command.append("-fs") + command.append("detect") + + # For certain devices (such as the ESP32-S2) there is a requirement that we open a brief connection to the + # controller at 1200bps to signal to the controller that it should set itself into a flashable state. We do + # this using basic pyserial, as esptool doesn't have this functionality built in. + if self._config.device_family_1200_bps: try: - esptool.main(command) - except: - print("Firmware flashing FAILED. esptool.py raised an error.") - print("Try flashing again, or try flashing with a slower speed.") - return + sleep(0.1) + print("Performing 1200 bps touch") + sleep(0.1) + ser = serial.Serial(self._config.port, baudrate=1200, timeout=5, write_timeout=0) + sleep(1.5) + print("...done\n") + ser.close() + except SerialException as e: + # sleep(0.1) + # self._parent.report_error(e.strerror) + sleep(0.1) + print("...unable to perform 1200bps touch.") + + print("\nMake sure you have selected the correct serial port (unfortunately,") + print("auto-select will not work for this chip) and try again.") + print("\nAlternatively, you may need to manually set the device into 'flash' mode.") + raise e + + print("Command: esptool.py %s\n" % " ".join(command)) - # The last line printed by esptool is "Staying in bootloader." -> some indication that the process is - # done is needed - print("\nFirmware successfully flashed. Unplug/replug or reset device \nto switch back to normal boot " - "mode.") + try: + esptool.main(command) except SerialException as e: + sleep(0.1) self._parent.report_error(e.strerror) raise e + except: + sleep(0.1) + print("Firmware flashing FAILED. esptool.py raised an error.\n") + print("Try flashing again, or try flashing with a slower speed.\n") + if self._config.device_family_1200_bps: + # TODO - Add instructions here + print("\nAlternatively, you may need to manually set the device into 'flash' mode.") + return + + # The last line printed by esptool is "Staying in bootloader." -> some indication that the process is + # done is needed + print("\nFirmware successfully flashed. Unplug/replug or reset device \nto switch back to normal boot " + "mode.") # --------------------------------------------------------------------------- @@ -211,6 +260,7 @@ def __init__(self): self.project_id = None self.device_family_string = "" self.device_family_id = None + self.device_family_1200_bps = False self.firmware_string = "" self.firmware_obj = None @@ -304,6 +354,7 @@ def on_select_project(event): # reset the device_family items self._config.device_family_string = "" self._config.device_family_id = None + self._config.device_family_1200_bps = False self.device_choice.SetItems(firmware_list.get_device_family_list(selected_project_id=self._config.project_id)) # reset the firmware items @@ -317,8 +368,10 @@ def on_select_device_family(event): if len(self._config.device_family_string) > 0: self._config.device_family_id = firmware_list.get_device_family_id(self._config.project_id, self._config.device_family_string) + self._config.device_family_1200_bps = firmware_list.Projects[self._config.project_id].device_families[self._config.device_family_id].use_1200_bps_touch else: self._config.device_family_id = None + self._config.device_family_1200_bps = False # reset the firmware items self._config.firmware_string = "" diff --git a/README.md b/README.md index 1bc00ad..5d07214 100644 --- a/README.md +++ b/README.md @@ -1,35 +1,39 @@ # BrewFlasher ![BrewFlasher Logo](images/BrewFlasher.png) -A standalone desktop application for flashing brewing-related firmware to your ESP8266 or ESP32. +A standalone desktop application for flashing brewing-related firmware to your ESP8266, ESP32, or ESP32-S2. -![Image of NodeMCU PyFlasher GUI](images/gui.png) +![Image of BrewFlasher GUI](images/gui.png) ## About BrewFlasher is a standalone desktop application that allows the user to flash specific firmware (upload software) to an -ESP32 or ESP8266. It will automatically locate the firmware on the internet, download it, and flash it to your chip with -minimal input required. Simple, fast, and magic. +ESP32, ESP32-S2, or ESP8266. It will automatically locate the firmware on the internet, download it, and flash it to +your chip with minimal input required. Simple, fast, and magic. This project was built as a natural complement to a handful of other projects I either support or collaborate on, where -a user is expected to flash firmware to an ESP8266 or ESP32 controller. For many users, this step of the installation -process is the most daunting - either because it requires the use of third-party tools that aren't mentioned in the -project they want to use, requires the use of the command line, or - in some cases - isn't well explained at all. -I solved this problem in my [Fermentrack](http://www.fermentrack.com/) project by building in a guided "firmware flash" -workflow - but this only helps when the user has installed Fermentrack. BrewFlasher was designed to take the best parts -of the Fermentrack firmware flash workflow and integrate them into a standalone desktop application. +a user is expected to flash firmware to an ESP8266, ESP32, or ESP32-S2 controller. For many users, this step of the +installation process is the most daunting - either because it requires the use of third-party tools that aren't +mentioned in the project they want to use, requires the use of the command line, or - in some cases - isn't well +explained at all. I solved this problem in my [Fermentrack](http://www.fermentrack.com/) project by building in a guided +"firmware flash" workflow - but this only helps when the user has installed Fermentrack. BrewFlasher was designed to +take the best parts of the Fermentrack firmware flash workflow and integrate them into a standalone desktop application. ## Supported Firmware -BrewFlasher is designed to specifically support a handful of beer- and brewing-related projects for the ESP32 or -ESP8266. Those projects include: +BrewFlasher is designed to specifically support a handful of beer- and brewing-related projects for the ESP32, ESP32-S2, +or ESP8266. Those projects include: -- BrewPi-ESP8266 +- BrewPi-ESP (ESP32, ESP8266, and ESP32-S2) - TiltBridge - BrewBubbles - Keg Cop - Flite - iSpindHub +- SBL4TILT +- GravityMon + +An up-to-date list of supported firmware can be found at the [BrewFlasher](https://www.brewflasher.com/about/supported_projects/) website. If you have a beer- or brewing-related project you would like supported, raise an [issue](https://github.com/thorrak/brewflasher/issues) and we can discuss it. @@ -40,13 +44,26 @@ If you are looking to flash generic firmware, I recommend the [NodeMCU PyFlasher BrewFlasher doesn't have to be installed; just double-click it and it'll start. BrewFlasher is available for both MacOS and Windows. +## Manually toggling "Flash" Mode + +For certain chips (e.g. ESP32-S2) the USB-to-serial functionality is provided by the controller itself rather than a +separate piece of hardware. For these chips, you may be required to manually set the controller into "flash" mode before +BrewFlasher can install new firmware. Below is the process for doing this for the Lolin S2 mini -- other controllers +are likely similar (though the "0" button may be labeled something else, like "boot" or "flash") + +1. Plug the Lolin S2 Mini into your computer +2. Hold down the "0" button on the right of the board +3. While continuing to hold the "0" button, press the "RST" button on the left of the board +4. Wait several seconds, then release the "0" button +5. Flash your controller with the desired firmware +6. Manually press the "RST" button on the left of the board to reset the controller once flashing is complete ## Background & Development BrewFlasher is based *heavily* on the [NodeMCU PyFlasher](https://github.com/marcelstoer/nodemcu-pyflasher) project. In comparison to that project, BrewFlasher adds explicit ESP32 support as well as a workflow to automate selecting and downloading brewing-related firmware to flash. The firmware selection is taken from a curated list maintained -behind-the-scenes on Fermentrack.com. +behind-the-scenes on BrewFlasher.com. ## License diff --git a/brewflasher_com_integration.py b/brewflasher_com_integration.py index 6835152..98060e8 100644 --- a/brewflasher_com_integration.py +++ b/brewflasher_com_integration.py @@ -161,12 +161,13 @@ def pre_flash_web_verify(self, brewflasher_version): class DeviceFamily: - def __init__(self, name="", flash_method="", id=0, detection_family=""): + def __init__(self, name="", flash_method="", id=0, detection_family="", use_1200_bps_touch=False): self.name = name self.flash_method = flash_method self.detection_family = detection_family self.id = id self.firmware = [] + self.use_1200_bps_touch = use_1200_bps_touch def __str__(self): return self.name @@ -221,13 +222,14 @@ def load_families_from_website(self) -> bool: try: # This gets wrapped in a try/except as I don't want this failing if the local copy of BrewFlasher # is slightly behind what is available at Brewflasher.com (eg - if there are new device families) - newFamily = DeviceFamily(name=row['name'], flash_method=row['flash_method'], id=row['id'], - detection_family=row['detection_family']) - if newFamily.flash_method == "esptool": # Only save families that use esptool - self.DeviceFamilies[newFamily.id] = copy.deepcopy(newFamily) - self.valid_family_ids.append(newFamily.id) + new_family = DeviceFamily(name=row['name'], flash_method=row['flash_method'], id=row['id'], + detection_family=row['detection_family'], + use_1200_bps_touch=row['use_1200_bps_touch']) + if new_family.flash_method == "esptool": # Only save families that use esptool + self.DeviceFamilies[new_family.id] = copy.deepcopy(new_family) + self.valid_family_ids.append(new_family.id) for this_project in self.Projects: - self.Projects[this_project].device_families[newFamily.id] = copy.deepcopy(newFamily) + self.Projects[this_project].device_families[new_family.id] = copy.deepcopy(new_family) except: # TODO - Display an error message pass diff --git a/build-on-mac-m1.spec b/build-on-mac-m1.spec index a52fbbc..e1da5a5 100644 --- a/build-on-mac-m1.spec +++ b/build-on-mac-m1.spec @@ -28,7 +28,7 @@ exe = EXE(pyz, codesign_identity='Developer ID Application: John Beeler (RAS94LVJ7S)', console=False , icon='images/icon-512.icns') app = BUNDLE(exe, - name='BrewFlasher-1.2.app', + name='BrewFlasher-1.3.app', icon='./images/icon-512.icns', bundle_identifier='com.brewflasher.macos', info_plist={ @@ -36,8 +36,8 @@ app = BUNDLE(exe, 'NSAppleScriptEnabled': False, 'LSRequiresIPhoneOS': False, 'LSApplicationCategoryType': 'public.app-category.utilities', - 'CFBundleVersion': '1.2.0', - 'CFBundleShortVersionString': '1.2', + 'CFBundleVersion': '1.3.0', + 'CFBundleShortVersionString': '1.3', 'CFBundleSignature': 'BFLS', 'LSMinimumSystemVersion': '10.4.0' }, diff --git a/build-on-mac.spec b/build-on-mac.spec index 820a43f..48e7877 100644 --- a/build-on-mac.spec +++ b/build-on-mac.spec @@ -28,7 +28,7 @@ exe = EXE(pyz, codesign_identity='Developer ID Application: John Beeler (RAS94LVJ7S)', console=False , icon='images/icon-512.icns') app = BUNDLE(exe, - name='BrewFlasher-1.2.app', + name='BrewFlasher-1.3.app', icon='./images/icon-512.icns', bundle_identifier='com.brewflasher.macos', info_plist={ @@ -36,8 +36,8 @@ app = BUNDLE(exe, 'NSAppleScriptEnabled': False, 'LSRequiresIPhoneOS': False, 'LSApplicationCategoryType': 'public.app-category.utilities', - 'CFBundleVersion': '1.2.0', - 'CFBundleShortVersionString': '1.2', + 'CFBundleVersion': '1.3.0', + 'CFBundleShortVersionString': '1.3', 'CFBundleSignature': 'BFLS', 'LSMinimumSystemVersion': '10.4.0' }, diff --git a/build-on-win.spec b/build-on-win.spec index e2a774d..45a4d49 100644 --- a/build-on-win.spec +++ b/build-on-win.spec @@ -26,7 +26,7 @@ exe = EXE(pyz, a.zipfiles, a.datas, [], - name='BrewFlasher-1.2', + name='BrewFlasher-1.3', debug=False, bootloader_ignore_signals=False, strip=False, diff --git a/build.bat b/build.bat index aafdb40..22ba090 100755 --- a/build.bat +++ b/build.bat @@ -13,8 +13,8 @@ REM I'm assuming Python 3.9 (since that's what I have) installed for the local REM First, we'll create the 64 bit version REM Delete any previous versions -del "dist\BrewFlasher-1.2.exe" -del "dist\BrewFlasher-1.2 x64.exe" +del "dist\BrewFlasher-1.3.exe" +del "dist\BrewFlasher-1.3 x64.exe" REM Make sure packages for the 64 bit version are up-to-date C:\Users\%USERNAME%\AppData\Local\Programs\Python\Python39\Scripts\pip.exe" install --upgrade -r requirements.txt REM And then, run pyinstaller @@ -25,8 +25,8 @@ move "dist\BrewFlasher-1.0.exe" "dist\BrewFlasher-1.0 x64.exe" REM Next, we'll create the 32 bit version. REM Delete any previous versions -REM del "dist\BrewFlasher-1.2.exe" -REM del "dist\BrewFlasher-1.2 x32.exe" +REM del "dist\BrewFlasher-1.3.exe" +REM del "dist\BrewFlasher-1.3 x32.exe" REM Make sure packages for the 32 bit version are up-to-date REM "C:\Users\%USERNAME%\AppData\Local\Programs\Python\Python37-32\Scripts\pip.exe" install --upgrade -r requirements.txt REM And then, we'll actually run pyinstaller diff --git a/build.sh b/build.sh index 34c366b..de7e4e8 100755 --- a/build.sh +++ b/build.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash #rm -fr build dist -#VERSION=1.2 +#VERSION=1.3 #NAME=BrewFlasher pyinstaller --log-level=INFO \ diff --git a/requirements.txt b/requirements.txt index f92a451..963859d 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,5 +1,6 @@ -esptool==3.2 +esptool==4.1 wxPython # Previously PyInstaller 3.4 was used - this has security vulnerabilities per GitHub -PyInstaller>=4.7 -requests +PyInstaller==5.1 +requests==2.28.0 +pyserial From 2e2b44aa4ec4188e90f0e5b88eba82edef9c8ccc Mon Sep 17 00:00:00 2001 From: John Date: Sat, 9 Jul 2022 23:58:49 -0400 Subject: [PATCH 2/7] Update local copy of esptool.py --- esptool.py | 5155 +--------------------------------------------------- 1 file changed, 23 insertions(+), 5132 deletions(-) diff --git a/esptool.py b/esptool.py index d2b1f3f..395075c 100755 --- a/esptool.py +++ b/esptool.py @@ -1,5143 +1,34 @@ #!/usr/bin/env python # -# ESP8266 & ESP32 family & ESP8684 ROM Bootloader Utility -# Copyright (C) 2014-2021 Fredrik Ahlberg, Angus Gratton, Espressif Systems (Shanghai) CO LTD, other contributors as noted. -# https://github.com/espressif/esptool +# SPDX-FileCopyrightText: 2014-2022 Fredrik Ahlberg, Angus Gratton, +# Espressif Systems (Shanghai) CO LTD, other contributors as noted. # -# This program is free software; you can redistribute it and/or modify it under -# the terms of the GNU General Public License as published by the Free Software -# Foundation; either version 2 of the License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License along with -# this program; if not, write to the Free Software Foundation, Inc., 51 Franklin -# Street, Fifth Floor, Boston, MA 02110-1301 USA. +# SPDX-License-Identifier: GPL-2.0-or-later -from __future__ import division, print_function +# This executable script is a thin wrapper around the main functionality +# in the esptool Python package -import argparse -import base64 -import binascii -import copy -import hashlib -import inspect -import io -import itertools +# When updating this script, please also update espefuse.py and espsecure.py + +import contextlib import os -import re -import shlex -import string -import struct import sys -import time -import zlib - -try: - import serial -except ImportError: - print("Pyserial is not installed for %s. Check the README for installation instructions." % (sys.executable)) - raise - -# check 'serial' is 'pyserial' and not 'serial' https://github.com/espressif/esptool/issues/269 -try: - if "serialization" in serial.__doc__ and "deserialization" in serial.__doc__: - raise ImportError(""" -esptool.py depends on pyserial, but there is a conflict with a currently installed package named 'serial'. - -You may be able to work around this by 'pip uninstall serial; pip install pyserial' \ -but this may break other installed Python software that depends on 'serial'. - -There is no good fix for this right now, apart from configuring virtualenvs. \ -See https://github.com/espressif/esptool/issues/269#issuecomment-385298196 for discussion of the underlying issue(s).""") -except TypeError: - pass # __doc__ returns None for pyserial - -try: - import serial.tools.list_ports as list_ports -except ImportError: - print("The installed version (%s) of pyserial appears to be too old for esptool.py (Python interpreter %s). " - "Check the README for installation instructions." % (sys.VERSION, sys.executable)) - raise -except Exception: - if sys.platform == "darwin": - # swallow the exception, this is a known issue in pyserial+macOS Big Sur preview ref https://github.com/espressif/esptool/issues/540 - list_ports = None - else: - raise - - -__version__ = "3.2" - -MAX_UINT32 = 0xffffffff -MAX_UINT24 = 0xffffff - -DEFAULT_TIMEOUT = 3 # timeout for most flash operations -START_FLASH_TIMEOUT = 20 # timeout for starting flash (may perform erase) -CHIP_ERASE_TIMEOUT = 120 # timeout for full chip erase -MAX_TIMEOUT = CHIP_ERASE_TIMEOUT * 2 # longest any command can run -SYNC_TIMEOUT = 0.1 # timeout for syncing with bootloader -MD5_TIMEOUT_PER_MB = 8 # timeout (per megabyte) for calculating md5sum -ERASE_REGION_TIMEOUT_PER_MB = 30 # timeout (per megabyte) for erasing a region -ERASE_WRITE_TIMEOUT_PER_MB = 40 # timeout (per megabyte) for erasing and writing data -MEM_END_ROM_TIMEOUT = 0.05 # special short timeout for ESP_MEM_END, as it may never respond -DEFAULT_SERIAL_WRITE_TIMEOUT = 10 # timeout for serial port write -DEFAULT_CONNECT_ATTEMPTS = 7 # default number of times to try connection - -SUPPORTED_CHIPS = ['esp8266', 'esp32', 'esp32s2', 'esp32s3beta2', 'esp32s3', 'esp32c3', 'esp32c6beta', 'esp32h2', 'esp8684'] - - -def timeout_per_mb(seconds_per_mb, size_bytes): - """ Scales timeouts which are size-specific """ - result = seconds_per_mb * (size_bytes / 1e6) - if result < DEFAULT_TIMEOUT: - return DEFAULT_TIMEOUT - return result - - -def _chip_to_rom_loader(chip): - return { - 'esp8266': ESP8266ROM, - 'esp32': ESP32ROM, - 'esp32s2': ESP32S2ROM, - 'esp32s3beta2': ESP32S3BETA2ROM, - 'esp32s3': ESP32S3ROM, - 'esp32c3': ESP32C3ROM, - 'esp32c6beta': ESP32C6BETAROM, - 'esp32h2': ESP32H2ROM, - 'esp8684': ESP8684ROM, - }[chip] - - -def get_default_connected_device(serial_list, port, connect_attempts, initial_baud, chip='auto', trace=False, - before='default_reset'): - _esp = None - for each_port in reversed(serial_list): - print("Serial port %s" % each_port) - try: - if chip == 'auto': - _esp = ESPLoader.detect_chip(each_port, initial_baud, before, trace, - connect_attempts) - else: - chip_class = _chip_to_rom_loader(chip) - _esp = chip_class(each_port, initial_baud, trace) - _esp.connect(before, connect_attempts) - break - except (FatalError, OSError) as err: - if port is not None: - raise - print("%s failed to connect: %s" % (each_port, err)) - _esp = None - return _esp - - -DETECTED_FLASH_SIZES = {0x12: '256KB', 0x13: '512KB', 0x14: '1MB', - 0x15: '2MB', 0x16: '4MB', 0x17: '8MB', - 0x18: '16MB', 0x19: '32MB', 0x1a: '64MB'} - - -def check_supported_function(func, check_func): - """ - Decorator implementation that wraps a check around an ESPLoader - bootloader function to check if it's supported. - - This is used to capture the multidimensional differences in - functionality between the ESP8266 & ESP32/32S2/32S3/32C3 & ESP8684 ROM loaders, and the - software stub that runs on both. Not possible to do this cleanly - via inheritance alone. - """ - def inner(*args, **kwargs): - obj = args[0] - if check_func(obj): - return func(*args, **kwargs) - else: - raise NotImplementedInROMError(obj, func) - return inner - - -def stub_function_only(func): - """ Attribute for a function only supported in the software stub loader """ - return check_supported_function(func, lambda o: o.IS_STUB) - - -def stub_and_esp32_function_only(func): - """ Attribute for a function only supported by software stubs or ESP32/32S2/32S3/32C3 ROM """ - return check_supported_function(func, lambda o: o.IS_STUB or isinstance(o, ESP32ROM)) - - -def esp32s3_or_newer_function_only(func): - """ Attribute for a function only supported by ESP32S3/32C3 & ESP8684 ROM """ - return check_supported_function(func, lambda o: isinstance(o, ESP32S3ROM) or isinstance(o, ESP32C3ROM)) - - -PYTHON2 = sys.version_info[0] < 3 # True if on pre-Python 3 - -# Function to return nth byte of a bitstring -# Different behaviour on Python 2 vs 3 -if PYTHON2: - def byte(bitstr, index): - return ord(bitstr[index]) -else: - def byte(bitstr, index): - return bitstr[index] - -# Provide a 'basestring' class on Python 3 -try: - basestring -except NameError: - basestring = str - - -def print_overwrite(message, last_line=False): - """ Print a message, overwriting the currently printed line. - - If last_line is False, don't append a newline at the end (expecting another subsequent call will overwrite this one.) - - After a sequence of calls with last_line=False, call once with last_line=True. - - If output is not a TTY (for example redirected a pipe), no overwriting happens and this function is the same as print(). - """ - if sys.stdout.isatty(): - print("\r%s" % message, end='\n' if last_line else '') - else: - print(message) - - -def _mask_to_shift(mask): - """ Return the index of the least significant bit in the mask """ - shift = 0 - while mask & 0x1 == 0: - shift += 1 - mask >>= 1 - return shift - - -def esp8266_function_only(func): - """ Attribute for a function only supported on ESP8266 """ - return check_supported_function(func, lambda o: o.CHIP_NAME == "ESP8266") - - -class ESPLoader(object): - """ Base class providing access to ESP ROM & software stub bootloaders. - Subclasses provide ESP8266 & ESP32 Family & ESP8684 specific functionality. - - Don't instantiate this base class directly, either instantiate a subclass or - call ESPLoader.detect_chip() which will interrogate the chip and return the - appropriate subclass instance. - - """ - CHIP_NAME = "Espressif device" - IS_STUB = False - - FPGA_SLOW_BOOT = False - - DEFAULT_PORT = "/dev/ttyUSB0" - - # Commands supported by ESP8266 ROM bootloader - ESP_FLASH_BEGIN = 0x02 - ESP_FLASH_DATA = 0x03 - ESP_FLASH_END = 0x04 - ESP_MEM_BEGIN = 0x05 - ESP_MEM_END = 0x06 - ESP_MEM_DATA = 0x07 - ESP_SYNC = 0x08 - ESP_WRITE_REG = 0x09 - ESP_READ_REG = 0x0a - - # Some comands supported by ESP32 & ESP8684 ROM bootloader (or -8266 w/ stub) - ESP_SPI_SET_PARAMS = 0x0B - ESP_SPI_ATTACH = 0x0D - ESP_READ_FLASH_SLOW = 0x0e # ROM only, much slower than the stub flash read - ESP_CHANGE_BAUDRATE = 0x0F - ESP_FLASH_DEFL_BEGIN = 0x10 - ESP_FLASH_DEFL_DATA = 0x11 - ESP_FLASH_DEFL_END = 0x12 - ESP_SPI_FLASH_MD5 = 0x13 - - # Commands supported by ESP32-S2/S3/C3/C6 & ESP8684 ROM bootloader only - ESP_GET_SECURITY_INFO = 0x14 - - # Some commands supported by stub only - ESP_ERASE_FLASH = 0xD0 - ESP_ERASE_REGION = 0xD1 - ESP_READ_FLASH = 0xD2 - ESP_RUN_USER_CODE = 0xD3 - - # Flash encryption encrypted data command - ESP_FLASH_ENCRYPT_DATA = 0xD4 - - # Response code(s) sent by ROM - ROM_INVALID_RECV_MSG = 0x05 # response if an invalid message is received - - # Maximum block sized for RAM and Flash writes, respectively. - ESP_RAM_BLOCK = 0x1800 - - FLASH_WRITE_SIZE = 0x400 - - # Default baudrate. The ROM auto-bauds, so we can use more or less whatever we want. - ESP_ROM_BAUD = 115200 - - # First byte of the application image - ESP_IMAGE_MAGIC = 0xe9 - - # Initial state for the checksum routine - ESP_CHECKSUM_MAGIC = 0xef - - # Flash sector size, minimum unit of erase. - FLASH_SECTOR_SIZE = 0x1000 - - UART_DATE_REG_ADDR = 0x60000078 - - CHIP_DETECT_MAGIC_REG_ADDR = 0x40001000 # This ROM address has a different value on each chip model - - UART_CLKDIV_MASK = 0xFFFFF - - # Memory addresses - IROM_MAP_START = 0x40200000 - IROM_MAP_END = 0x40300000 - - # The number of bytes in the UART response that signify command status - STATUS_BYTES_LENGTH = 2 - - # Response to ESP_SYNC might indicate that flasher stub is running instead of the ROM bootloader - sync_stub_detected = False - - # Device PIDs - USB_JTAG_SERIAL_PID = 0x1001 - - # Chip IDs that are no longer supported by esptool - UNSUPPORTED_CHIPS = {6: "ESP32-S3(beta 3)"} - - def __init__(self, port=DEFAULT_PORT, baud=ESP_ROM_BAUD, trace_enabled=False): - """Base constructor for ESPLoader bootloader interaction - - Don't call this constructor, either instantiate ESP8266ROM - or ESP32ROM, or use ESPLoader.detect_chip(). - - This base class has all of the instance methods for bootloader - functionality supported across various chips & stub - loaders. Subclasses replace the functions they don't support - with ones which throw NotImplementedInROMError(). - - """ - self.secure_download_mode = False # flag is set to True if esptool detects the ROM is in Secure Download Mode - self.stub_is_disabled = False # flag is set to True if esptool detects conditions which require the stub to be disabled - - if isinstance(port, basestring): - self._port = serial.serial_for_url(port) - else: - self._port = port - self._slip_reader = slip_reader(self._port, self.trace) - # setting baud rate in a separate step is a workaround for - # CH341 driver on some Linux versions (this opens at 9600 then - # sets), shouldn't matter for other platforms/drivers. See - # https://github.com/espressif/esptool/issues/44#issuecomment-107094446 - self._set_port_baudrate(baud) - self._trace_enabled = trace_enabled - # set write timeout, to prevent esptool blocked at write forever. - try: - self._port.write_timeout = DEFAULT_SERIAL_WRITE_TIMEOUT - except NotImplementedError: - # no write timeout for RFC2217 ports - # need to set the property back to None or it will continue to fail - self._port.write_timeout = None - - @property - def serial_port(self): - return self._port.port - - def _set_port_baudrate(self, baud): - try: - self._port.baudrate = baud - except IOError: - raise FatalError("Failed to set baud rate %d. The driver may not support this rate." % baud) - - @staticmethod - def detect_chip(port=DEFAULT_PORT, baud=ESP_ROM_BAUD, connect_mode='default_reset', trace_enabled=False, - connect_attempts=DEFAULT_CONNECT_ATTEMPTS): - """ Use serial access to detect the chip type. - - First, get_security_info command is sent to detect the ID of the chip - (supported only by ESP32-C3 and later, works even in the Secure Download Mode). - If this fails, we reconnect and fall-back to reading the magic number. - It's mapped at a specific ROM address and has a different value on each chip model. - This way we can use one memory read and compare it to the magic number for each chip type. - - This routine automatically performs ESPLoader.connect() (passing - connect_mode parameter) as part of querying the chip. - """ - inst = None - detect_port = ESPLoader(port, baud, trace_enabled=trace_enabled) - detect_port.connect(connect_mode, connect_attempts, detecting=True) - try: - print('Detecting chip type...', end='') - res = detect_port.check_command('get security info', ESPLoader.ESP_GET_SECURITY_INFO, b'') - res = struct.unpack(" self.STATUS_BYTES_LENGTH: - return data[:-self.STATUS_BYTES_LENGTH] - else: # otherwise, just return the 'val' field which comes from the reply header (this is used by read_reg) - return val - - def flush_input(self): - self._port.flushInput() - self._slip_reader = slip_reader(self._port, self.trace) - - def sync(self): - val, _ = self.command(self.ESP_SYNC, b'\x07\x07\x12\x20' + 32 * b'\x55', - timeout=SYNC_TIMEOUT) - - # ROM bootloaders send some non-zero "val" response. The flasher stub sends 0. If we receive 0 then it - # probably indicates that the chip wasn't or couldn't be reseted properly and esptool is talking to the - # flasher stub. - self.sync_stub_detected = val == 0 - - for _ in range(7): - val, _ = self.command() - self.sync_stub_detected &= val == 0 - - def _setDTR(self, state): - self._port.setDTR(state) - - def _setRTS(self, state): - self._port.setRTS(state) - # Work-around for adapters on Windows using the usbser.sys driver: - # generate a dummy change to DTR so that the set-control-line-state - # request is sent with the updated RTS state and the same DTR state - self._port.setDTR(self._port.dtr) - - def _get_pid(self): - if list_ports is None: - print("\nListing all serial ports is currently not available. Can't get device PID.") - return - active_port = self._port.port - - # Pyserial only identifies regular ports, URL handlers are not supported - if not active_port.startswith(("COM", "/dev/")): - print("\nDevice PID identification is only supported on COM and /dev/ serial ports.") - return - # Return the real path if the active port is a symlink - if active_port.startswith("/dev/") and os.path.islink(active_port): - active_port = os.path.realpath(active_port) - - # The "cu" (call-up) device has to be used for outgoing communication on MacOS - if sys.platform == "darwin" and "tty" in active_port: - active_port = [active_port, active_port.replace("tty", "cu")] - ports = list_ports.comports() - for p in ports: - if p.device in active_port: - return p.pid - print("\nFailed to get PID of a device on {}, using standard reset sequence.".format(active_port)) - - def bootloader_reset(self, usb_jtag_serial=False, extra_delay=False): - """ Issue a reset-to-bootloader, with USB-JTAG-Serial custom reset sequence option - """ - # RTS = either CH_PD/EN or nRESET (both active low = chip in reset) - # DTR = GPIO0 (active low = boot to flasher) - # - # DTR & RTS are active low signals, - # ie True = pin @ 0V, False = pin @ VCC. - if usb_jtag_serial: - # Custom reset sequence, which is required when the device - # is connecting via its USB-JTAG-Serial peripheral - self._setRTS(False) - self._setDTR(False) # Idle - time.sleep(0.1) - self._setDTR(True) # Set IO0 - self._setRTS(False) - time.sleep(0.1) - self._setRTS(True) # Reset. Note dtr/rts calls inverted so we go through (1,1) instead of (0,0) - self._setDTR(False) - self._setRTS(True) # Extra RTS set for RTS as Windows only propagates DTR on RTS setting - time.sleep(0.1) - self._setDTR(False) - self._setRTS(False) - else: - # This fpga delay is for Espressif internal use - fpga_delay = True if self.FPGA_SLOW_BOOT and os.environ.get("ESPTOOL_ENV_FPGA", "").strip() == "1" else False - delay = 7 if fpga_delay else 0.5 if extra_delay else 0.05 # 0.5 needed for ESP32 rev0 and rev1 - - self._setDTR(False) # IO0=HIGH - self._setRTS(True) # EN=LOW, chip in reset - time.sleep(0.1) - self._setDTR(True) # IO0=LOW - self._setRTS(False) # EN=HIGH, chip out of reset - time.sleep(delay) - self._setDTR(False) # IO0=HIGH, done - - def _connect_attempt(self, mode='default_reset', usb_jtag_serial=False, extra_delay=False): - """ A single connection attempt """ - last_error = None - boot_log_detected = False - download_mode = False - - # If we're doing no_sync, we're likely communicating as a pass through - # with an intermediate device to the ESP32 - if mode == "no_reset_no_sync": - return last_error - - if mode != 'no_reset': - self._port.flushInput() # Empty serial buffer to isolate boot log - self.bootloader_reset(usb_jtag_serial, extra_delay) - - # Detect the ROM boot log and check actual boot mode (ESP32 and later only) - waiting = self._port.inWaiting() - read_bytes = self._port.read(waiting) - data = re.search(b'boot:(0x[0-9a-fA-F]+)(.*waiting for download)?', read_bytes, re.DOTALL) - if data is not None: - boot_log_detected = True - boot_mode = data.group(1) - download_mode = data.group(2) is not None - - for _ in range(5): - try: - self.flush_input() - self._port.flushOutput() - self.sync() - return None - except FatalError as e: - print('.', end='') - sys.stdout.flush() - time.sleep(0.05) - last_error = e - - if boot_log_detected: - last_error = FatalError("Wrong boot mode detected ({})! The chip needs to be in download mode.".format(boot_mode.decode("utf-8"))) - if download_mode: - last_error = FatalError("Download mode successfully detected, but getting no sync reply: The serial TX path seems to be down.") - return last_error - - def get_memory_region(self, name): - """ Returns a tuple of (start, end) for the memory map entry with the given name, or None if it doesn't exist - """ - try: - return [(start, end) for (start, end, n) in self.MEMORY_MAP if n == name][0] - except IndexError: - return None - - def connect(self, mode='default_reset', attempts=DEFAULT_CONNECT_ATTEMPTS, detecting=False, warnings=True): - """ Try connecting repeatedly until successful, or giving up """ - if warnings and mode in ['no_reset', 'no_reset_no_sync']: - print('WARNING: Pre-connection option "{}" was selected.'.format(mode), - 'Connection may fail if the chip is not in bootloader or flasher stub mode.') - print('Connecting...', end='') - sys.stdout.flush() - last_error = None - - usb_jtag_serial = (mode == 'usb_reset') or (self._get_pid() == self.USB_JTAG_SERIAL_PID) - - try: - for _, extra_delay in zip(range(attempts) if attempts > 0 else itertools.count(), itertools.cycle((False, True))): - last_error = self._connect_attempt(mode=mode, usb_jtag_serial=usb_jtag_serial, extra_delay=extra_delay) - if last_error is None: - break - finally: - print('') # end 'Connecting...' line - - if last_error is not None: - raise FatalError('Failed to connect to %s: %s' - '\nFor troubleshooting steps visit: https://github.com/espressif/esptool#troubleshooting' % (self.CHIP_NAME, last_error)) - - if not detecting: - try: - # check the date code registers match what we expect to see - chip_magic_value = self.read_reg(ESPLoader.CHIP_DETECT_MAGIC_REG_ADDR) - if chip_magic_value not in self.CHIP_DETECT_MAGIC_VALUE: - actually = None - for cls in [ESP8266ROM, ESP32ROM, ESP32S2ROM, ESP32S3BETA2ROM, ESP32S3ROM, ESP32C3ROM, ESP32H2ROM, ESP8684ROM]: - if chip_magic_value in cls.CHIP_DETECT_MAGIC_VALUE: - actually = cls - break - if warnings and actually is None: - print(("WARNING: This chip doesn't appear to be a %s (chip magic value 0x%08x). " - "Probably it is unsupported by this version of esptool.") % (self.CHIP_NAME, chip_magic_value)) - else: - raise FatalError("This chip is %s not %s. Wrong --chip argument?" % (actually.CHIP_NAME, self.CHIP_NAME)) - except UnsupportedCommandError: - self.secure_download_mode = True - self._post_connect() - self.check_chip_id() - - def _post_connect(self): - """ - Additional initialization hook, may be overridden by the chip-specific class. - Gets called after connect, and after auto-detection. - """ - pass - - def read_reg(self, addr, timeout=DEFAULT_TIMEOUT): - """ Read memory address in target """ - # we don't call check_command here because read_reg() function is called - # when detecting chip type, and the way we check for success (STATUS_BYTES_LENGTH) is different - # for different chip types (!) - val, data = self.command(self.ESP_READ_REG, struct.pack(' 0: - # add a dummy write to a date register as an excuse to have a delay - command += struct.pack(' start: - raise FatalError(("Software loader is resident at 0x%08x-0x%08x. " - "Can't load binary at overlapping address range 0x%08x-0x%08x. " - "Either change binary loading address, or use the --no-stub " - "option to disable the software loader.") % (start, end, load_start, load_end)) - - return self.check_command("enter RAM download mode", self.ESP_MEM_BEGIN, - struct.pack(' length: - raise FatalError('Read more than expected') - - digest_frame = self.read() - if len(digest_frame) != 16: - raise FatalError('Expected digest, got: %s' % hexify(digest_frame)) - expected_digest = hexify(digest_frame).upper() - digest = hashlib.md5(data).hexdigest().upper() - if digest != expected_digest: - raise FatalError('Digest mismatch: expected %s, got %s' % (expected_digest, digest)) - return data - - def flash_spi_attach(self, hspi_arg): - """Send SPI attach command to enable the SPI flash pins - - ESP8266 ROM does this when you send flash_begin, ESP32 ROM - has it as a SPI command. - """ - # last 3 bytes in ESP_SPI_ATTACH argument are reserved values - arg = struct.pack(' 0: - self.write_reg(SPI_MOSI_DLEN_REG, mosi_bits - 1) - if miso_bits > 0: - self.write_reg(SPI_MISO_DLEN_REG, miso_bits - 1) - else: - - def set_data_lengths(mosi_bits, miso_bits): - SPI_DATA_LEN_REG = SPI_USR1_REG - SPI_MOSI_BITLEN_S = 17 - SPI_MISO_BITLEN_S = 8 - mosi_mask = 0 if (mosi_bits == 0) else (mosi_bits - 1) - miso_mask = 0 if (miso_bits == 0) else (miso_bits - 1) - self.write_reg(SPI_DATA_LEN_REG, - (miso_mask << SPI_MISO_BITLEN_S) | ( - mosi_mask << SPI_MOSI_BITLEN_S)) - - # SPI peripheral "command" bitmasks for SPI_CMD_REG - SPI_CMD_USR = (1 << 18) - - # shift values - SPI_USR2_COMMAND_LEN_SHIFT = 28 - - if read_bits > 32: - raise FatalError("Reading more than 32 bits back from a SPI flash operation is unsupported") - if len(data) > 64: - raise FatalError("Writing more than 64 bytes of data with one SPI command is unsupported") - - data_bits = len(data) * 8 - old_spi_usr = self.read_reg(SPI_USR_REG) - old_spi_usr2 = self.read_reg(SPI_USR2_REG) - flags = SPI_USR_COMMAND - if read_bits > 0: - flags |= SPI_USR_MISO - if data_bits > 0: - flags |= SPI_USR_MOSI - set_data_lengths(data_bits, read_bits) - self.write_reg(SPI_USR_REG, flags) - self.write_reg(SPI_USR2_REG, - (7 << SPI_USR2_COMMAND_LEN_SHIFT) | spiflash_command) - if data_bits == 0: - self.write_reg(SPI_W0_REG, 0) # clear data register before we read it - else: - data = pad_to(data, 4, b'\00') # pad to 32-bit multiple - words = struct.unpack("I" * (len(data) // 4), data) - next_reg = SPI_W0_REG - for word in words: - self.write_reg(next_reg, word) - next_reg += 4 - self.write_reg(SPI_CMD_REG, SPI_CMD_USR) - - def wait_done(): - for _ in range(10): - if (self.read_reg(SPI_CMD_REG) & SPI_CMD_USR) == 0: - return - raise FatalError("SPI command did not complete in time") - wait_done() - - status = self.read_reg(SPI_W0_REG) - # restore some SPI controller registers - self.write_reg(SPI_USR_REG, old_spi_usr) - self.write_reg(SPI_USR2_REG, old_spi_usr2) - return status - - def read_status(self, num_bytes=2): - """Read up to 24 bits (num_bytes) of SPI flash status register contents - via RDSR, RDSR2, RDSR3 commands - - Not all SPI flash supports all three commands. The upper 1 or 2 - bytes may be 0xFF. - """ - SPIFLASH_RDSR = 0x05 - SPIFLASH_RDSR2 = 0x35 - SPIFLASH_RDSR3 = 0x15 - - status = 0 - shift = 0 - for cmd in [SPIFLASH_RDSR, SPIFLASH_RDSR2, SPIFLASH_RDSR3][0:num_bytes]: - status += self.run_spiflash_command(cmd, read_bits=8) << shift - shift += 8 - return status - - def write_status(self, new_status, num_bytes=2, set_non_volatile=False): - """Write up to 24 bits (num_bytes) of new status register - - num_bytes can be 1, 2 or 3. - - Not all flash supports the additional commands to write the - second and third byte of the status register. When writing 2 - bytes, esptool also sends a 16-byte WRSR command (as some - flash types use this instead of WRSR2.) - - If the set_non_volatile flag is set, non-volatile bits will - be set as well as volatile ones (WREN used instead of WEVSR). - - """ - SPIFLASH_WRSR = 0x01 - SPIFLASH_WRSR2 = 0x31 - SPIFLASH_WRSR3 = 0x11 - SPIFLASH_WEVSR = 0x50 - SPIFLASH_WREN = 0x06 - SPIFLASH_WRDI = 0x04 - - enable_cmd = SPIFLASH_WREN if set_non_volatile else SPIFLASH_WEVSR - - # try using a 16-bit WRSR (not supported by all chips) - # this may be redundant, but shouldn't hurt - if num_bytes == 2: - self.run_spiflash_command(enable_cmd) - self.run_spiflash_command(SPIFLASH_WRSR, struct.pack(">= 8 - - self.run_spiflash_command(SPIFLASH_WRDI) - - def get_crystal_freq(self): - # Figure out the crystal frequency from the UART clock divider - # Returns a normalized value in integer MHz (40 or 26 are the only supported values) - # - # The logic here is: - # - We know that our baud rate and the ESP UART baud rate are roughly the same, or we couldn't communicate - # - We can read the UART clock divider register to know how the ESP derives this from the APB bus frequency - # - Multiplying these two together gives us the bus frequency which is either the crystal frequency (ESP32) - # or double the crystal frequency (ESP8266). See the self.XTAL_CLK_DIVIDER parameter for this factor. - uart_div = self.read_reg(self.UART_CLKDIV_REG) & self.UART_CLKDIV_MASK - est_xtal = (self._port.baudrate * uart_div) / 1e6 / self.XTAL_CLK_DIVIDER - norm_xtal = 40 if est_xtal > 33 else 26 - if abs(norm_xtal - est_xtal) > 1: - print("WARNING: Detected crystal freq %.2fMHz is quite different to normalized freq %dMHz. Unsupported crystal in use?" % (est_xtal, norm_xtal)) - return norm_xtal - - def hard_reset(self): - print('Hard resetting via RTS pin...') - self._setRTS(True) # EN->LOW - time.sleep(0.1) - self._setRTS(False) - - def soft_reset(self, stay_in_bootloader): - if not self.IS_STUB: - if stay_in_bootloader: - return # ROM bootloader is already in bootloader! - else: - # 'run user code' is as close to a soft reset as we can do - self.flash_begin(0, 0) - self.flash_finish(False) - else: - if stay_in_bootloader: - # soft resetting from the stub loader - # will re-load the ROM bootloader - self.flash_begin(0, 0) - self.flash_finish(True) - elif self.CHIP_NAME != "ESP8266": - raise FatalError("Soft resetting is currently only supported on ESP8266") - else: - # running user code from stub loader requires some hacks - # in the stub loader - self.command(self.ESP_RUN_USER_CODE, wait_response=False) - - def check_chip_id(self): - try: - chip_id = self.get_chip_id() - if chip_id != self.IMAGE_CHIP_ID: - print("WARNING: Chip ID {} ({}) doesn't match expected Chip ID {}. esptool may not work correctly." - .format(chip_id, self.UNSUPPORTED_CHIPS.get(chip_id, 'Unknown'), self.IMAGE_CHIP_ID)) - # Try to flash anyways by disabling stub - self.stub_is_disabled = True - except NotImplementedInROMError: - pass - - -class ESP8266ROM(ESPLoader): - """ Access class for ESP8266 ROM bootloader - """ - CHIP_NAME = "ESP8266" - IS_STUB = False - - CHIP_DETECT_MAGIC_VALUE = [0xfff0c101] - - # OTP ROM addresses - ESP_OTP_MAC0 = 0x3ff00050 - ESP_OTP_MAC1 = 0x3ff00054 - ESP_OTP_MAC3 = 0x3ff0005c - - SPI_REG_BASE = 0x60000200 - SPI_USR_OFFS = 0x1c - SPI_USR1_OFFS = 0x20 - SPI_USR2_OFFS = 0x24 - SPI_MOSI_DLEN_OFFS = None - SPI_MISO_DLEN_OFFS = None - SPI_W0_OFFS = 0x40 - - UART_CLKDIV_REG = 0x60000014 - - XTAL_CLK_DIVIDER = 2 - - FLASH_SIZES = { - '512KB': 0x00, - '256KB': 0x10, - '1MB': 0x20, - '2MB': 0x30, - '4MB': 0x40, - '2MB-c1': 0x50, - '4MB-c1': 0x60, - '8MB': 0x80, - '16MB': 0x90, - } - - BOOTLOADER_FLASH_OFFSET = 0 - - MEMORY_MAP = [[0x3FF00000, 0x3FF00010, "DPORT"], - [0x3FFE8000, 0x40000000, "DRAM"], - [0x40100000, 0x40108000, "IRAM"], - [0x40201010, 0x402E1010, "IROM"]] - - def get_efuses(self): - # Return the 128 bits of ESP8266 efuse as a single Python integer - result = self.read_reg(0x3ff0005c) << 96 - result |= self.read_reg(0x3ff00058) << 64 - result |= self.read_reg(0x3ff00054) << 32 - result |= self.read_reg(0x3ff00050) - return result - - def _get_flash_size(self, efuses): - # rX_Y = EFUSE_DATA_OUTX[Y] - r0_4 = (efuses & (1 << 4)) != 0 - r3_25 = (efuses & (1 << 121)) != 0 - r3_26 = (efuses & (1 << 122)) != 0 - r3_27 = (efuses & (1 << 123)) != 0 - - if r0_4 and not r3_25: - if not r3_27 and not r3_26: - return 1 - elif not r3_27 and r3_26: - return 2 - if not r0_4 and r3_25: - if not r3_27 and not r3_26: - return 2 - elif not r3_27 and r3_26: - return 4 - return -1 - - def get_chip_description(self): - efuses = self.get_efuses() - is_8285 = (efuses & ((1 << 4) | 1 << 80)) != 0 # One or the other efuse bit is set for ESP8285 - if is_8285: - flash_size = self._get_flash_size(efuses) - max_temp = (efuses & (1 << 5)) != 0 # This efuse bit identifies the max flash temperature - chip_name = { - 1: "ESP8285H08" if max_temp else "ESP8285N08", - 2: "ESP8285H16" if max_temp else "ESP8285N16" - }.get(flash_size, "ESP8285") - return chip_name - return "ESP8266EX" - - def get_chip_features(self): - features = ["WiFi"] - if "ESP8285" in self.get_chip_description(): - features += ["Embedded Flash"] - return features - - def flash_spi_attach(self, hspi_arg): - if self.IS_STUB: - super(ESP8266ROM, self).flash_spi_attach(hspi_arg) - else: - # ESP8266 ROM has no flash_spi_attach command in serial protocol, - # but flash_begin will do it - self.flash_begin(0, 0) - - def flash_set_parameters(self, size): - # not implemented in ROM, but OK to silently skip for ROM - if self.IS_STUB: - super(ESP8266ROM, self).flash_set_parameters(size) - - def chip_id(self): - """ Read Chip ID from efuse - the equivalent of the SDK system_get_chip_id() function """ - id0 = self.read_reg(self.ESP_OTP_MAC0) - id1 = self.read_reg(self.ESP_OTP_MAC1) - return (id0 >> 24) | ((id1 & MAX_UINT24) << 8) - - def read_mac(self): - """ Read MAC from OTP ROM """ - mac0 = self.read_reg(self.ESP_OTP_MAC0) - mac1 = self.read_reg(self.ESP_OTP_MAC1) - mac3 = self.read_reg(self.ESP_OTP_MAC3) - if (mac3 != 0): - oui = ((mac3 >> 16) & 0xff, (mac3 >> 8) & 0xff, mac3 & 0xff) - elif ((mac1 >> 16) & 0xff) == 0: - oui = (0x18, 0xfe, 0x34) - elif ((mac1 >> 16) & 0xff) == 1: - oui = (0xac, 0xd0, 0x74) - else: - raise FatalError("Unknown OUI") - return oui + ((mac1 >> 8) & 0xff, mac1 & 0xff, (mac0 >> 24) & 0xff) - - def get_erase_size(self, offset, size): - """ Calculate an erase size given a specific size in bytes. - - Provides a workaround for the bootloader erase bug.""" - - sectors_per_block = 16 - sector_size = self.FLASH_SECTOR_SIZE - num_sectors = (size + sector_size - 1) // sector_size - start_sector = offset // sector_size - - head_sectors = sectors_per_block - (start_sector % sectors_per_block) - if num_sectors < head_sectors: - head_sectors = num_sectors - - if num_sectors < 2 * head_sectors: - return (num_sectors + 1) // 2 * sector_size - else: - return (num_sectors - head_sectors) * sector_size - - def override_vddsdio(self, new_voltage): - raise NotImplementedInROMError("Overriding VDDSDIO setting only applies to ESP32") - - -class ESP8266StubLoader(ESP8266ROM): - """ Access class for ESP8266 stub loader, runs on top of ROM. - """ - FLASH_WRITE_SIZE = 0x4000 # matches MAX_WRITE_BLOCK in stub_loader.c - IS_STUB = True - - def __init__(self, rom_loader): - self.secure_download_mode = rom_loader.secure_download_mode - self._port = rom_loader._port - self._trace_enabled = rom_loader._trace_enabled - self.flush_input() # resets _slip_reader - - def get_erase_size(self, offset, size): - return size # stub doesn't have same size bug as ROM loader - - -ESP8266ROM.STUB_CLASS = ESP8266StubLoader - - -class ESP32ROM(ESPLoader): - """Access class for ESP32 ROM bootloader - - """ - CHIP_NAME = "ESP32" - IMAGE_CHIP_ID = 0 - IS_STUB = False - - FPGA_SLOW_BOOT = True - - CHIP_DETECT_MAGIC_VALUE = [0x00f01d83] - - IROM_MAP_START = 0x400d0000 - IROM_MAP_END = 0x40400000 - - DROM_MAP_START = 0x3F400000 - DROM_MAP_END = 0x3F800000 - - # ESP32 uses a 4 byte status reply - STATUS_BYTES_LENGTH = 4 - - SPI_REG_BASE = 0x3ff42000 - SPI_USR_OFFS = 0x1c - SPI_USR1_OFFS = 0x20 - SPI_USR2_OFFS = 0x24 - SPI_MOSI_DLEN_OFFS = 0x28 - SPI_MISO_DLEN_OFFS = 0x2c - EFUSE_RD_REG_BASE = 0x3ff5a000 - - EFUSE_DIS_DOWNLOAD_MANUAL_ENCRYPT_REG = EFUSE_RD_REG_BASE + 0x18 - EFUSE_DIS_DOWNLOAD_MANUAL_ENCRYPT = (1 << 7) # EFUSE_RD_DISABLE_DL_ENCRYPT - - DR_REG_SYSCON_BASE = 0x3ff66000 - - SPI_W0_OFFS = 0x80 - - UART_CLKDIV_REG = 0x3ff40014 - - XTAL_CLK_DIVIDER = 1 - - FLASH_SIZES = { - '1MB': 0x00, - '2MB': 0x10, - '4MB': 0x20, - '8MB': 0x30, - '16MB': 0x40 - } - - BOOTLOADER_FLASH_OFFSET = 0x1000 - - OVERRIDE_VDDSDIO_CHOICES = ["1.8V", "1.9V", "OFF"] - - MEMORY_MAP = [[0x00000000, 0x00010000, "PADDING"], - [0x3F400000, 0x3F800000, "DROM"], - [0x3F800000, 0x3FC00000, "EXTRAM_DATA"], - [0x3FF80000, 0x3FF82000, "RTC_DRAM"], - [0x3FF90000, 0x40000000, "BYTE_ACCESSIBLE"], - [0x3FFAE000, 0x40000000, "DRAM"], - [0x3FFE0000, 0x3FFFFFFC, "DIRAM_DRAM"], - [0x40000000, 0x40070000, "IROM"], - [0x40070000, 0x40078000, "CACHE_PRO"], - [0x40078000, 0x40080000, "CACHE_APP"], - [0x40080000, 0x400A0000, "IRAM"], - [0x400A0000, 0x400BFFFC, "DIRAM_IRAM"], - [0x400C0000, 0x400C2000, "RTC_IRAM"], - [0x400D0000, 0x40400000, "IROM"], - [0x50000000, 0x50002000, "RTC_DATA"]] - - FLASH_ENCRYPTED_WRITE_ALIGN = 32 - - """ Try to read the BLOCK1 (encryption key) and check if it is valid """ - - def is_flash_encryption_key_valid(self): - - """ Bit 0 of efuse_rd_disable[3:0] is mapped to BLOCK1 - this bit is at position 16 in EFUSE_BLK0_RDATA0_REG """ - word0 = self.read_efuse(0) - rd_disable = (word0 >> 16) & 0x1 - - # reading of BLOCK1 is NOT ALLOWED so we assume valid key is programmed - if rd_disable: - return True - else: - # reading of BLOCK1 is ALLOWED so we will read and verify for non-zero. - # When ESP32 has not generated AES/encryption key in BLOCK1, the contents will be readable and 0. - # If the flash encryption is enabled it is expected to have a valid non-zero key. We break out on - # first occurance of non-zero value - key_word = [0] * 7 - for i in range(len(key_word)): - key_word[i] = self.read_efuse(14 + i) - # key is non-zero so break & return - if key_word[i] != 0: - return True - return False - - def get_flash_crypt_config(self): - """ For flash encryption related commands we need to make sure - user has programmed all the relevant efuse correctly so before - writing encrypted write_flash_encrypt esptool will verify the values - of flash_crypt_config to be non zero if they are not read - protected. If the values are zero a warning will be printed - - bit 3 in efuse_rd_disable[3:0] is mapped to flash_crypt_config - this bit is at position 19 in EFUSE_BLK0_RDATA0_REG """ - word0 = self.read_efuse(0) - rd_disable = (word0 >> 19) & 0x1 - - if rd_disable == 0: - """ we can read the flash_crypt_config efuse value - so go & read it (EFUSE_BLK0_RDATA5_REG[31:28]) """ - word5 = self.read_efuse(5) - word5 = (word5 >> 28) & 0xF - return word5 - else: - # if read of the efuse is disabled we assume it is set correctly - return 0xF - - def get_encrypted_download_disabled(self): - if self.read_reg(self.EFUSE_DIS_DOWNLOAD_MANUAL_ENCRYPT_REG) & self.EFUSE_DIS_DOWNLOAD_MANUAL_ENCRYPT: - return True - else: - return False - - def get_pkg_version(self): - word3 = self.read_efuse(3) - pkg_version = (word3 >> 9) & 0x07 - pkg_version += ((word3 >> 2) & 0x1) << 3 - return pkg_version - - def get_chip_revision(self): - word3 = self.read_efuse(3) - word5 = self.read_efuse(5) - apb_ctl_date = self.read_reg(self.DR_REG_SYSCON_BASE + 0x7C) - - rev_bit0 = (word3 >> 15) & 0x1 - rev_bit1 = (word5 >> 20) & 0x1 - rev_bit2 = (apb_ctl_date >> 31) & 0x1 - if rev_bit0: - if rev_bit1: - if rev_bit2: - return 3 - else: - return 2 - else: - return 1 - return 0 - - def get_chip_description(self): - pkg_version = self.get_pkg_version() - chip_revision = self.get_chip_revision() - rev3 = (chip_revision == 3) - single_core = self.read_efuse(3) & (1 << 0) # CHIP_VER DIS_APP_CPU - - chip_name = { - 0: "ESP32-S0WDQ6" if single_core else "ESP32-D0WDQ6", - 1: "ESP32-S0WD" if single_core else "ESP32-D0WD", - 2: "ESP32-D2WD", - 4: "ESP32-U4WDH", - 5: "ESP32-PICO-V3" if rev3 else "ESP32-PICO-D4", - 6: "ESP32-PICO-V3-02", - }.get(pkg_version, "unknown ESP32") - - # ESP32-D0WD-V3, ESP32-D0WDQ6-V3 - if chip_name.startswith("ESP32-D0WD") and rev3: - chip_name += "-V3" - - return "%s (revision %d)" % (chip_name, chip_revision) - - def get_chip_features(self): - features = ["WiFi"] - word3 = self.read_efuse(3) - - # names of variables in this section are lowercase - # versions of EFUSE names as documented in TRM and - # ESP-IDF efuse_reg.h - - chip_ver_dis_bt = word3 & (1 << 1) - if chip_ver_dis_bt == 0: - features += ["BT"] - - chip_ver_dis_app_cpu = word3 & (1 << 0) - if chip_ver_dis_app_cpu: - features += ["Single Core"] - else: - features += ["Dual Core"] - - chip_cpu_freq_rated = word3 & (1 << 13) - if chip_cpu_freq_rated: - chip_cpu_freq_low = word3 & (1 << 12) - if chip_cpu_freq_low: - features += ["160MHz"] - else: - features += ["240MHz"] - - pkg_version = self.get_pkg_version() - if pkg_version in [2, 4, 5, 6]: - features += ["Embedded Flash"] - - if pkg_version == 6: - features += ["Embedded PSRAM"] - - word4 = self.read_efuse(4) - adc_vref = (word4 >> 8) & 0x1F - if adc_vref: - features += ["VRef calibration in efuse"] - - blk3_part_res = word3 >> 14 & 0x1 - if blk3_part_res: - features += ["BLK3 partially reserved"] - - word6 = self.read_efuse(6) - coding_scheme = word6 & 0x3 - features += ["Coding Scheme %s" % { - 0: "None", - 1: "3/4", - 2: "Repeat (UNSUPPORTED)", - 3: "Invalid"}[coding_scheme]] - - return features - - def read_efuse(self, n): - """ Read the nth word of the ESP3x EFUSE region. """ - return self.read_reg(self.EFUSE_RD_REG_BASE + (4 * n)) - - def chip_id(self): - raise NotSupportedError(self, "chip_id") - - def read_mac(self): - """ Read MAC from EFUSE region """ - words = [self.read_efuse(2), self.read_efuse(1)] - bitstring = struct.pack(">II", *words) - bitstring = bitstring[2:8] # trim the 2 byte CRC - try: - return tuple(ord(b) for b in bitstring) - except TypeError: # Python 3, bitstring elements are already bytes - return tuple(bitstring) - - def get_erase_size(self, offset, size): - return size - - def override_vddsdio(self, new_voltage): - new_voltage = new_voltage.upper() - if new_voltage not in self.OVERRIDE_VDDSDIO_CHOICES: - raise FatalError("The only accepted VDDSDIO overrides are '1.8V', '1.9V' and 'OFF'") - RTC_CNTL_SDIO_CONF_REG = 0x3ff48074 - RTC_CNTL_XPD_SDIO_REG = (1 << 31) - RTC_CNTL_DREFH_SDIO_M = (3 << 29) - RTC_CNTL_DREFM_SDIO_M = (3 << 27) - RTC_CNTL_DREFL_SDIO_M = (3 << 25) - # RTC_CNTL_SDIO_TIEH = (1 << 23) # not used here, setting TIEH=1 would set 3.3V output, not safe for esptool.py to do - RTC_CNTL_SDIO_FORCE = (1 << 22) - RTC_CNTL_SDIO_PD_EN = (1 << 21) - - reg_val = RTC_CNTL_SDIO_FORCE # override efuse setting - reg_val |= RTC_CNTL_SDIO_PD_EN - if new_voltage != "OFF": - reg_val |= RTC_CNTL_XPD_SDIO_REG # enable internal LDO - if new_voltage == "1.9V": - reg_val |= (RTC_CNTL_DREFH_SDIO_M | RTC_CNTL_DREFM_SDIO_M | RTC_CNTL_DREFL_SDIO_M) # boost voltage - self.write_reg(RTC_CNTL_SDIO_CONF_REG, reg_val) - print("VDDSDIO regulator set to %s" % new_voltage) - - def read_flash_slow(self, offset, length, progress_fn): - BLOCK_LEN = 64 # ROM read limit per command (this limit is why it's so slow) - - data = b'' - while len(data) < length: - block_len = min(BLOCK_LEN, length - len(data)) - r = self.check_command("read flash block", self.ESP_READ_FLASH_SLOW, - struct.pack('> 0) & 0x0F - return pkg_version - - def get_flash_version(self): - num_word = 3 - block1_addr = self.EFUSE_BASE + 0x044 - word3 = self.read_reg(block1_addr + (4 * num_word)) - pkg_version = (word3 >> 21) & 0x0F - return pkg_version - - def get_psram_version(self): - num_word = 3 - block1_addr = self.EFUSE_BASE + 0x044 - word3 = self.read_reg(block1_addr + (4 * num_word)) - pkg_version = (word3 >> 28) & 0x0F - return pkg_version - - def get_block2_version(self): - num_word = 4 - block2_addr = self.EFUSE_BASE + 0x05C - word4 = self.read_reg(block2_addr + (4 * num_word)) - block2_version = (word4 >> 4) & 0x07 - return block2_version - - def get_chip_description(self): - chip_name = { - 0: "ESP32-S2", - 1: "ESP32-S2FH2", - 2: "ESP32-S2FH4", - 102: "ESP32-S2FNR2", - 100: "ESP32-S2R2", - }.get(self.get_flash_version() + self.get_psram_version() * 100, "unknown ESP32-S2") - - return "%s" % (chip_name) - - def get_chip_features(self): - features = ["WiFi"] - - if self.secure_download_mode: - features += ["Secure Download Mode Enabled"] - - flash_version = { - 0: "No Embedded Flash", - 1: "Embedded Flash 2MB", - 2: "Embedded Flash 4MB", - }.get(self.get_flash_version(), "Unknown Embedded Flash") - features += [flash_version] - - psram_version = { - 0: "No Embedded PSRAM", - 1: "Embedded PSRAM 2MB", - 2: "Embedded PSRAM 4MB", - }.get(self.get_psram_version(), "Unknown Embedded PSRAM") - features += [psram_version] - - block2_version = { - 0: "No calibration in BLK2 of efuse", - 1: "ADC and temperature sensor calibration in BLK2 of efuse V1", - 2: "ADC and temperature sensor calibration in BLK2 of efuse V2", - }.get(self.get_block2_version(), "Unknown Calibration in BLK2") - features += [block2_version] - - return features - - def get_crystal_freq(self): - # ESP32-S2 XTAL is fixed to 40MHz - return 40 - - def override_vddsdio(self, new_voltage): - raise NotImplementedInROMError("VDD_SDIO overrides are not supported for ESP32-S2") - - def read_mac(self): - mac0 = self.read_reg(self.MAC_EFUSE_REG) - mac1 = self.read_reg(self.MAC_EFUSE_REG + 4) # only bottom 16 bits are MAC - bitstring = struct.pack(">II", mac1, mac0)[2:] - try: - return tuple(ord(b) for b in bitstring) - except TypeError: # Python 3, bitstring elements are already bytes - return tuple(bitstring) - - def get_flash_crypt_config(self): - return None # doesn't exist on ESP32-S2 - - def get_key_block_purpose(self, key_block): - if key_block < 0 or key_block > 5: - raise FatalError("Valid key block numbers must be in range 0-5") - - reg, shift = [(self.EFUSE_PURPOSE_KEY0_REG, self.EFUSE_PURPOSE_KEY0_SHIFT), - (self.EFUSE_PURPOSE_KEY1_REG, self.EFUSE_PURPOSE_KEY1_SHIFT), - (self.EFUSE_PURPOSE_KEY2_REG, self.EFUSE_PURPOSE_KEY2_SHIFT), - (self.EFUSE_PURPOSE_KEY3_REG, self.EFUSE_PURPOSE_KEY3_SHIFT), - (self.EFUSE_PURPOSE_KEY4_REG, self.EFUSE_PURPOSE_KEY4_SHIFT), - (self.EFUSE_PURPOSE_KEY5_REG, self.EFUSE_PURPOSE_KEY5_SHIFT)][key_block] - return (self.read_reg(reg) >> shift) & 0xF - - def is_flash_encryption_key_valid(self): - # Need to see either an AES-128 key or two AES-256 keys - purposes = [self.get_key_block_purpose(b) for b in range(6)] - - if any(p == self.PURPOSE_VAL_XTS_AES128_KEY for p in purposes): - return True - - return any(p == self.PURPOSE_VAL_XTS_AES256_KEY_1 for p in purposes) \ - and any(p == self.PURPOSE_VAL_XTS_AES256_KEY_2 for p in purposes) - - def uses_usb(self, _cache=[]): - if self.secure_download_mode: - return False # can't detect native USB in secure download mode - if not _cache: - buf_no = self.read_reg(self.UARTDEV_BUF_NO) & 0xff - _cache.append(buf_no == self.UARTDEV_BUF_NO_USB) - return _cache[0] - - def _post_connect(self): - if self.uses_usb(): - self.ESP_RAM_BLOCK = self.USB_RAM_BLOCK - - def _check_if_can_reset(self): - """ - Check the strapping register to see if we can reset out of download mode. - """ - if os.getenv("ESPTOOL_TESTING") is not None: - print("ESPTOOL_TESTING is set, ignoring strapping mode check") - # Esptool tests over USB CDC run with GPIO0 strapped low, don't complain in this case. - return - strap_reg = self.read_reg(self.GPIO_STRAP_REG) - force_dl_reg = self.read_reg(self.RTC_CNTL_OPTION1_REG) - if strap_reg & self.GPIO_STRAP_SPI_BOOT_MASK == 0 and force_dl_reg & self.RTC_CNTL_FORCE_DOWNLOAD_BOOT_MASK == 0: - print("WARNING: {} chip was placed into download mode using GPIO0.\n" - "esptool.py can not exit the download mode over USB. " - "To run the app, reset the chip manually.\n" - "To suppress this note, set --after option to 'no_reset'.".format(self.get_chip_description())) - raise SystemExit(1) - - def hard_reset(self): - if self.uses_usb(): - self._check_if_can_reset() - - print('Hard resetting via RTS pin...') - self._setRTS(True) # EN->LOW - if self.uses_usb(): - # Give the chip some time to come out of reset, to be able to handle further DTR/RTS transitions - time.sleep(0.2) - self._setRTS(False) - time.sleep(0.2) - else: - self._setRTS(False) - - -class ESP32S3ROM(ESP32ROM): - CHIP_NAME = "ESP32-S3" - - IMAGE_CHIP_ID = 9 - - CHIP_DETECT_MAGIC_VALUE = [0x9] - - FPGA_SLOW_BOOT = False - - IROM_MAP_START = 0x42000000 - IROM_MAP_END = 0x44000000 - DROM_MAP_START = 0x3c000000 - DROM_MAP_END = 0x3e000000 - - UART_DATE_REG_ADDR = 0x60000080 - - SPI_REG_BASE = 0x60002000 - SPI_USR_OFFS = 0x18 - SPI_USR1_OFFS = 0x1c - SPI_USR2_OFFS = 0x20 - SPI_MOSI_DLEN_OFFS = 0x24 - SPI_MISO_DLEN_OFFS = 0x28 - SPI_W0_OFFS = 0x58 - - FLASH_ENCRYPTED_WRITE_ALIGN = 16 - - # todo: use espefuse APIs to get this info - EFUSE_BASE = 0x60007000 # BLOCK0 read base address - MAC_EFUSE_REG = EFUSE_BASE + 0x044 - - EFUSE_RD_REG_BASE = EFUSE_BASE + 0x030 # BLOCK0 read base address - - EFUSE_PURPOSE_KEY0_REG = EFUSE_BASE + 0x34 - EFUSE_PURPOSE_KEY0_SHIFT = 24 - EFUSE_PURPOSE_KEY1_REG = EFUSE_BASE + 0x34 - EFUSE_PURPOSE_KEY1_SHIFT = 28 - EFUSE_PURPOSE_KEY2_REG = EFUSE_BASE + 0x38 - EFUSE_PURPOSE_KEY2_SHIFT = 0 - EFUSE_PURPOSE_KEY3_REG = EFUSE_BASE + 0x38 - EFUSE_PURPOSE_KEY3_SHIFT = 4 - EFUSE_PURPOSE_KEY4_REG = EFUSE_BASE + 0x38 - EFUSE_PURPOSE_KEY4_SHIFT = 8 - EFUSE_PURPOSE_KEY5_REG = EFUSE_BASE + 0x38 - EFUSE_PURPOSE_KEY5_SHIFT = 12 - - EFUSE_DIS_DOWNLOAD_MANUAL_ENCRYPT_REG = EFUSE_RD_REG_BASE - EFUSE_DIS_DOWNLOAD_MANUAL_ENCRYPT = 1 << 20 - - PURPOSE_VAL_XTS_AES256_KEY_1 = 2 - PURPOSE_VAL_XTS_AES256_KEY_2 = 3 - PURPOSE_VAL_XTS_AES128_KEY = 4 - - UARTDEV_BUF_NO = 0x3fcef14c # Variable in ROM .bss which indicates the port in use - UARTDEV_BUF_NO_USB = 3 # Value of the above variable indicating that USB is in use - - USB_RAM_BLOCK = 0x800 # Max block size USB CDC is used - - GPIO_STRAP_REG = 0x60004038 - GPIO_STRAP_SPI_BOOT_MASK = 0x8 # Not download mode - RTC_CNTL_OPTION1_REG = 0x6000812C - RTC_CNTL_FORCE_DOWNLOAD_BOOT_MASK = 0x1 # Is download mode forced over USB? - - UART_CLKDIV_REG = 0x60000014 - - MEMORY_MAP = [[0x00000000, 0x00010000, "PADDING"], - [0x3C000000, 0x3D000000, "DROM"], - [0x3D000000, 0x3E000000, "EXTRAM_DATA"], - [0x600FE000, 0x60100000, "RTC_DRAM"], - [0x3FC88000, 0x3FD00000, "BYTE_ACCESSIBLE"], - [0x3FC88000, 0x403E2000, "MEM_INTERNAL"], - [0x3FC88000, 0x3FD00000, "DRAM"], - [0x40000000, 0x4001A100, "IROM_MASK"], - [0x40370000, 0x403E0000, "IRAM"], - [0x600FE000, 0x60100000, "RTC_IRAM"], - [0x42000000, 0x42800000, "IROM"], - [0x50000000, 0x50002000, "RTC_DATA"]] - - def get_chip_description(self): - return "ESP32-S3" - - def get_chip_features(self): - return ["WiFi", "BLE"] - - def get_crystal_freq(self): - # ESP32S3 XTAL is fixed to 40MHz - return 40 - - def get_flash_crypt_config(self): - return None # doesn't exist on ESP32-S3 - - def get_key_block_purpose(self, key_block): - if key_block < 0 or key_block > 5: - raise FatalError("Valid key block numbers must be in range 0-5") - - reg, shift = [(self.EFUSE_PURPOSE_KEY0_REG, self.EFUSE_PURPOSE_KEY0_SHIFT), - (self.EFUSE_PURPOSE_KEY1_REG, self.EFUSE_PURPOSE_KEY1_SHIFT), - (self.EFUSE_PURPOSE_KEY2_REG, self.EFUSE_PURPOSE_KEY2_SHIFT), - (self.EFUSE_PURPOSE_KEY3_REG, self.EFUSE_PURPOSE_KEY3_SHIFT), - (self.EFUSE_PURPOSE_KEY4_REG, self.EFUSE_PURPOSE_KEY4_SHIFT), - (self.EFUSE_PURPOSE_KEY5_REG, self.EFUSE_PURPOSE_KEY5_SHIFT)][key_block] - return (self.read_reg(reg) >> shift) & 0xF - - def is_flash_encryption_key_valid(self): - # Need to see either an AES-128 key or two AES-256 keys - purposes = [self.get_key_block_purpose(b) for b in range(6)] - - if any(p == self.PURPOSE_VAL_XTS_AES128_KEY for p in purposes): - return True - - return any(p == self.PURPOSE_VAL_XTS_AES256_KEY_1 for p in purposes) \ - and any(p == self.PURPOSE_VAL_XTS_AES256_KEY_2 for p in purposes) - - def override_vddsdio(self, new_voltage): - raise NotImplementedInROMError("VDD_SDIO overrides are not supported for ESP32-S3") - - def read_mac(self): - mac0 = self.read_reg(self.MAC_EFUSE_REG) - mac1 = self.read_reg(self.MAC_EFUSE_REG + 4) # only bottom 16 bits are MAC - bitstring = struct.pack(">II", mac1, mac0)[2:] - try: - return tuple(ord(b) for b in bitstring) - except TypeError: # Python 3, bitstring elements are already bytes - return tuple(bitstring) - - def uses_usb(self, _cache=[]): - if self.secure_download_mode: - return False # can't detect native USB in secure download mode - if not _cache: - buf_no = self.read_reg(self.UARTDEV_BUF_NO) & 0xff - _cache.append(buf_no == self.UARTDEV_BUF_NO_USB) - return _cache[0] - - def _post_connect(self): - if self.uses_usb(): - self.ESP_RAM_BLOCK = self.USB_RAM_BLOCK - - def _check_if_can_reset(self): - """ - Check the strapping register to see if we can reset out of download mode. - """ - if os.getenv("ESPTOOL_TESTING") is not None: - print("ESPTOOL_TESTING is set, ignoring strapping mode check") - # Esptool tests over USB CDC run with GPIO0 strapped low, don't complain in this case. - return - strap_reg = self.read_reg(self.GPIO_STRAP_REG) - force_dl_reg = self.read_reg(self.RTC_CNTL_OPTION1_REG) - if strap_reg & self.GPIO_STRAP_SPI_BOOT_MASK == 0 and force_dl_reg & self.RTC_CNTL_FORCE_DOWNLOAD_BOOT_MASK == 0: - print("WARNING: {} chip was placed into download mode using GPIO0.\n" - "esptool.py can not exit the download mode over USB. " - "To run the app, reset the chip manually.\n" - "To suppress this note, set --after option to 'no_reset'.".format(self.get_chip_description())) - raise SystemExit(1) - - def hard_reset(self): - if self.uses_usb(): - self._check_if_can_reset() - - print('Hard resetting via RTS pin...') - self._setRTS(True) # EN->LOW - if self.uses_usb(): - # Give the chip some time to come out of reset, to be able to handle further DTR/RTS transitions - time.sleep(0.2) - self._setRTS(False) - time.sleep(0.2) - else: - self._setRTS(False) - - -class ESP32S3BETA2ROM(ESP32S3ROM): - CHIP_NAME = "ESP32-S3(beta2)" - IMAGE_CHIP_ID = 4 - - CHIP_DETECT_MAGIC_VALUE = [0xeb004136] - - EFUSE_BASE = 0x6001A000 # BLOCK0 read base address - - def get_chip_description(self): - return "ESP32-S3(beta2)" - - -class ESP32C3ROM(ESP32ROM): - CHIP_NAME = "ESP32-C3" - IMAGE_CHIP_ID = 5 - - FPGA_SLOW_BOOT = False - - IROM_MAP_START = 0x42000000 - IROM_MAP_END = 0x42800000 - DROM_MAP_START = 0x3c000000 - DROM_MAP_END = 0x3c800000 - - SPI_REG_BASE = 0x60002000 - SPI_USR_OFFS = 0x18 - SPI_USR1_OFFS = 0x1C - SPI_USR2_OFFS = 0x20 - SPI_MOSI_DLEN_OFFS = 0x24 - SPI_MISO_DLEN_OFFS = 0x28 - SPI_W0_OFFS = 0x58 - - BOOTLOADER_FLASH_OFFSET = 0x0 - - # Magic value for ESP32C3 eco 1+2 and ESP32C3 eco3 respectivly - CHIP_DETECT_MAGIC_VALUE = [0x6921506f, 0x1b31506f] - - UART_DATE_REG_ADDR = 0x60000000 + 0x7c - - EFUSE_BASE = 0x60008800 - MAC_EFUSE_REG = EFUSE_BASE + 0x044 - - EFUSE_RD_REG_BASE = EFUSE_BASE + 0x030 # BLOCK0 read base address - - EFUSE_PURPOSE_KEY0_REG = EFUSE_BASE + 0x34 - EFUSE_PURPOSE_KEY0_SHIFT = 24 - EFUSE_PURPOSE_KEY1_REG = EFUSE_BASE + 0x34 - EFUSE_PURPOSE_KEY1_SHIFT = 28 - EFUSE_PURPOSE_KEY2_REG = EFUSE_BASE + 0x38 - EFUSE_PURPOSE_KEY2_SHIFT = 0 - EFUSE_PURPOSE_KEY3_REG = EFUSE_BASE + 0x38 - EFUSE_PURPOSE_KEY3_SHIFT = 4 - EFUSE_PURPOSE_KEY4_REG = EFUSE_BASE + 0x38 - EFUSE_PURPOSE_KEY4_SHIFT = 8 - EFUSE_PURPOSE_KEY5_REG = EFUSE_BASE + 0x38 - EFUSE_PURPOSE_KEY5_SHIFT = 12 - - EFUSE_DIS_DOWNLOAD_MANUAL_ENCRYPT_REG = EFUSE_RD_REG_BASE - EFUSE_DIS_DOWNLOAD_MANUAL_ENCRYPT = 1 << 20 - - PURPOSE_VAL_XTS_AES128_KEY = 4 - - GPIO_STRAP_REG = 0x3f404038 - - FLASH_ENCRYPTED_WRITE_ALIGN = 16 - - MEMORY_MAP = [[0x00000000, 0x00010000, "PADDING"], - [0x3C000000, 0x3C800000, "DROM"], - [0x3FC80000, 0x3FCE0000, "DRAM"], - [0x3FC88000, 0x3FD00000, "BYTE_ACCESSIBLE"], - [0x3FF00000, 0x3FF20000, "DROM_MASK"], - [0x40000000, 0x40060000, "IROM_MASK"], - [0x42000000, 0x42800000, "IROM"], - [0x4037C000, 0x403E0000, "IRAM"], - [0x50000000, 0x50002000, "RTC_IRAM"], - [0x50000000, 0x50002000, "RTC_DRAM"], - [0x600FE000, 0x60100000, "MEM_INTERNAL2"]] - - def get_pkg_version(self): - num_word = 3 - block1_addr = self.EFUSE_BASE + 0x044 - word3 = self.read_reg(block1_addr + (4 * num_word)) - pkg_version = (word3 >> 21) & 0x07 - return pkg_version - - def get_chip_revision(self): - # reads WAFER_VERSION field from EFUSE_RD_MAC_SPI_SYS_3_REG - block1_addr = self.EFUSE_BASE + 0x044 - num_word = 3 - pos = 18 - return (self.read_reg(block1_addr + (4 * num_word)) & (0x7 << pos)) >> pos - - def get_chip_description(self): - chip_name = { - 0: "ESP32-C3", - }.get(self.get_pkg_version(), "unknown ESP32-C3") - chip_revision = self.get_chip_revision() - - return "%s (revision %d)" % (chip_name, chip_revision) - - def get_chip_features(self): - return ["Wi-Fi"] - - def get_crystal_freq(self): - # ESP32C3 XTAL is fixed to 40MHz - return 40 - - def override_vddsdio(self, new_voltage): - raise NotImplementedInROMError("VDD_SDIO overrides are not supported for ESP32-C3") - - def read_mac(self): - mac0 = self.read_reg(self.MAC_EFUSE_REG) - mac1 = self.read_reg(self.MAC_EFUSE_REG + 4) # only bottom 16 bits are MAC - bitstring = struct.pack(">II", mac1, mac0)[2:] - try: - return tuple(ord(b) for b in bitstring) - except TypeError: # Python 3, bitstring elements are already bytes - return tuple(bitstring) - - def get_flash_crypt_config(self): - return None # doesn't exist on ESP32-C3 - - def get_key_block_purpose(self, key_block): - if key_block < 0 or key_block > 5: - raise FatalError("Valid key block numbers must be in range 0-5") - - reg, shift = [(self.EFUSE_PURPOSE_KEY0_REG, self.EFUSE_PURPOSE_KEY0_SHIFT), - (self.EFUSE_PURPOSE_KEY1_REG, self.EFUSE_PURPOSE_KEY1_SHIFT), - (self.EFUSE_PURPOSE_KEY2_REG, self.EFUSE_PURPOSE_KEY2_SHIFT), - (self.EFUSE_PURPOSE_KEY3_REG, self.EFUSE_PURPOSE_KEY3_SHIFT), - (self.EFUSE_PURPOSE_KEY4_REG, self.EFUSE_PURPOSE_KEY4_SHIFT), - (self.EFUSE_PURPOSE_KEY5_REG, self.EFUSE_PURPOSE_KEY5_SHIFT)][key_block] - return (self.read_reg(reg) >> shift) & 0xF - - def is_flash_encryption_key_valid(self): - # Need to see an AES-128 key - purposes = [self.get_key_block_purpose(b) for b in range(6)] - - return any(p == self.PURPOSE_VAL_XTS_AES128_KEY for p in purposes) - - -class ESP32H2ROM(ESP32ROM): - CHIP_NAME = "ESP32-H2" - IMAGE_CHIP_ID = 10 - - IROM_MAP_START = 0x42000000 - IROM_MAP_END = 0x42800000 - DROM_MAP_START = 0x3c000000 - DROM_MAP_END = 0x3c800000 - - SPI_REG_BASE = 0x60002000 - SPI_USR_OFFS = 0x18 - SPI_USR1_OFFS = 0x1C - SPI_USR2_OFFS = 0x20 - SPI_MOSI_DLEN_OFFS = 0x24 - SPI_MISO_DLEN_OFFS = 0x28 - SPI_W0_OFFS = 0x58 - - BOOTLOADER_FLASH_OFFSET = 0x0 - - CHIP_DETECT_MAGIC_VALUE = [0xca26cc22] - - UART_DATE_REG_ADDR = 0x60000000 + 0x7c - - EFUSE_BASE = 0x6001A000 - MAC_EFUSE_REG = EFUSE_BASE + 0x044 - - EFUSE_RD_REG_BASE = EFUSE_BASE + 0x030 # BLOCK0 read base address - - EFUSE_PURPOSE_KEY0_REG = EFUSE_BASE + 0x34 - EFUSE_PURPOSE_KEY0_SHIFT = 24 - EFUSE_PURPOSE_KEY1_REG = EFUSE_BASE + 0x34 - EFUSE_PURPOSE_KEY1_SHIFT = 28 - EFUSE_PURPOSE_KEY2_REG = EFUSE_BASE + 0x38 - EFUSE_PURPOSE_KEY2_SHIFT = 0 - EFUSE_PURPOSE_KEY3_REG = EFUSE_BASE + 0x38 - EFUSE_PURPOSE_KEY3_SHIFT = 4 - EFUSE_PURPOSE_KEY4_REG = EFUSE_BASE + 0x38 - EFUSE_PURPOSE_KEY4_SHIFT = 8 - EFUSE_PURPOSE_KEY5_REG = EFUSE_BASE + 0x38 - EFUSE_PURPOSE_KEY5_SHIFT = 12 - - EFUSE_DIS_DOWNLOAD_MANUAL_ENCRYPT_REG = EFUSE_RD_REG_BASE - EFUSE_DIS_DOWNLOAD_MANUAL_ENCRYPT = 1 << 20 - - PURPOSE_VAL_XTS_AES128_KEY = 4 - - GPIO_STRAP_REG = 0x3f404038 - - FLASH_ENCRYPTED_WRITE_ALIGN = 16 - - MEMORY_MAP = [] - - def get_pkg_version(self): - num_word = 3 - block1_addr = self.EFUSE_BASE + 0x044 - word3 = self.read_reg(block1_addr + (4 * num_word)) - pkg_version = (word3 >> 21) & 0x0F - return pkg_version - - def get_chip_revision(self): - # reads WAFER_VERSION field from EFUSE_RD_MAC_SPI_SYS_3_REG - block1_addr = self.EFUSE_BASE + 0x044 - num_word = 3 - pos = 18 - return (self.read_reg(block1_addr + (4 * num_word)) & (0x7 << pos)) >> pos - - def get_chip_description(self): - chip_name = { - 0: "ESP32-H2", - }.get(self.get_pkg_version(), "unknown ESP32-H2") - chip_revision = self.get_chip_revision() - - return "%s (revision %d)" % (chip_name, chip_revision) - - def get_chip_features(self): - return ["BLE/802.15.4"] - - def get_crystal_freq(self): - return 40 - - def override_vddsdio(self, new_voltage): - raise NotImplementedInROMError("VDD_SDIO overrides are not supported for ESP32-H2") - - def read_mac(self): - mac0 = self.read_reg(self.MAC_EFUSE_REG) - mac1 = self.read_reg(self.MAC_EFUSE_REG + 4) # only bottom 16 bits are MAC - bitstring = struct.pack(">II", mac1, mac0)[2:] - try: - return tuple(ord(b) for b in bitstring) - except TypeError: # Python 3, bitstring elements are already bytes - return tuple(bitstring) - - def get_flash_crypt_config(self): - return None # doesn't exist on ESP32-H2 - - def get_key_block_purpose(self, key_block): - if key_block < 0 or key_block > 5: - raise FatalError("Valid key block numbers must be in range 0-5") - - reg, shift = [(self.EFUSE_PURPOSE_KEY0_REG, self.EFUSE_PURPOSE_KEY0_SHIFT), - (self.EFUSE_PURPOSE_KEY1_REG, self.EFUSE_PURPOSE_KEY1_SHIFT), - (self.EFUSE_PURPOSE_KEY2_REG, self.EFUSE_PURPOSE_KEY2_SHIFT), - (self.EFUSE_PURPOSE_KEY3_REG, self.EFUSE_PURPOSE_KEY3_SHIFT), - (self.EFUSE_PURPOSE_KEY4_REG, self.EFUSE_PURPOSE_KEY4_SHIFT), - (self.EFUSE_PURPOSE_KEY5_REG, self.EFUSE_PURPOSE_KEY5_SHIFT)][key_block] - return (self.read_reg(reg) >> shift) & 0xF - - def is_flash_encryption_key_valid(self): - # Need to see an AES-128 key - purposes = [self.get_key_block_purpose(b) for b in range(6)] - - return any(p == self.PURPOSE_VAL_XTS_AES128_KEY for p in purposes) - - -class ESP8684ROM(ESP32C3ROM): - CHIP_NAME = "ESP8684" - IMAGE_CHIP_ID = 12 - - CHIP_DETECT_MAGIC_VALUE = [0x6451806f] - - def get_pkg_version(self): - num_word = 3 - block1_addr = self.EFUSE_BASE + 0x044 - word3 = self.read_reg(block1_addr + (4 * num_word)) - pkg_version = (word3 >> 21) & 0x0F - return pkg_version - - def get_chip_description(self): - chip_name = { - 0: "ESP8684", - }.get(self.get_pkg_version(), "unknown ESP8684") - chip_revision = self.get_chip_revision() - - return "%s (revision %d)" % (chip_name, chip_revision) - - -class ESP32C6BETAROM(ESP32C3ROM): - CHIP_NAME = "ESP32-C6(beta)" - IMAGE_CHIP_ID = 7 - - CHIP_DETECT_MAGIC_VALUE = [0x0da1806f] - - UART_DATE_REG_ADDR = 0x00000500 - - def get_chip_description(self): - chip_name = { - 0: "ESP32-C6", - }.get(self.get_pkg_version(), "unknown ESP32-C6") - chip_revision = self.get_chip_revision() - - return "%s (revision %d)" % (chip_name, chip_revision) - - -class ESP32StubLoader(ESP32ROM): - """ Access class for ESP32 stub loader, runs on top of ROM. - """ - FLASH_WRITE_SIZE = 0x4000 # matches MAX_WRITE_BLOCK in stub_loader.c - STATUS_BYTES_LENGTH = 2 # same as ESP8266, different to ESP32 ROM - IS_STUB = True - - def __init__(self, rom_loader): - self.secure_download_mode = rom_loader.secure_download_mode - self._port = rom_loader._port - self._trace_enabled = rom_loader._trace_enabled - self.flush_input() # resets _slip_reader - - -ESP32ROM.STUB_CLASS = ESP32StubLoader - - -class ESP32S2StubLoader(ESP32S2ROM): - """ Access class for ESP32-S2 stub loader, runs on top of ROM. - - (Basically the same as ESP32StubLoader, but different base class. - Can possibly be made into a mixin.) - """ - FLASH_WRITE_SIZE = 0x4000 # matches MAX_WRITE_BLOCK in stub_loader.c - STATUS_BYTES_LENGTH = 2 # same as ESP8266, different to ESP32 ROM - IS_STUB = True - - def __init__(self, rom_loader): - self.secure_download_mode = rom_loader.secure_download_mode - self._port = rom_loader._port - self._trace_enabled = rom_loader._trace_enabled - self.flush_input() # resets _slip_reader - - if rom_loader.uses_usb(): - self.ESP_RAM_BLOCK = self.USB_RAM_BLOCK - self.FLASH_WRITE_SIZE = self.USB_RAM_BLOCK - - -ESP32S2ROM.STUB_CLASS = ESP32S2StubLoader - - -class ESP32S3BETA2StubLoader(ESP32S3BETA2ROM): - """ Access class for ESP32S3 stub loader, runs on top of ROM. - - (Basically the same as ESP32StubLoader, but different base class. - Can possibly be made into a mixin.) - """ - FLASH_WRITE_SIZE = 0x4000 # matches MAX_WRITE_BLOCK in stub_loader.c - STATUS_BYTES_LENGTH = 2 # same as ESP8266, different to ESP32 ROM - IS_STUB = True - - def __init__(self, rom_loader): - self.secure_download_mode = rom_loader.secure_download_mode - self._port = rom_loader._port - self._trace_enabled = rom_loader._trace_enabled - self.flush_input() # resets _slip_reader - - -ESP32S3BETA2ROM.STUB_CLASS = ESP32S3BETA2StubLoader - - -class ESP32S3StubLoader(ESP32S3ROM): - """ Access class for ESP32S3 stub loader, runs on top of ROM. - - (Basically the same as ESP32StubLoader, but different base class. - Can possibly be made into a mixin.) - """ - FLASH_WRITE_SIZE = 0x4000 # matches MAX_WRITE_BLOCK in stub_loader.c - STATUS_BYTES_LENGTH = 2 # same as ESP8266, different to ESP32 ROM - IS_STUB = True - - def __init__(self, rom_loader): - self.secure_download_mode = rom_loader.secure_download_mode - self._port = rom_loader._port - self._trace_enabled = rom_loader._trace_enabled - self.flush_input() # resets _slip_reader - - if rom_loader.uses_usb(): - self.ESP_RAM_BLOCK = self.USB_RAM_BLOCK - self.FLASH_WRITE_SIZE = self.USB_RAM_BLOCK - - -ESP32S3ROM.STUB_CLASS = ESP32S3StubLoader - - -class ESP32C3StubLoader(ESP32C3ROM): - """ Access class for ESP32C3 stub loader, runs on top of ROM. - - (Basically the same as ESP32StubLoader, but different base class. - Can possibly be made into a mixin.) - """ - FLASH_WRITE_SIZE = 0x4000 # matches MAX_WRITE_BLOCK in stub_loader.c - STATUS_BYTES_LENGTH = 2 # same as ESP8266, different to ESP32 ROM - IS_STUB = True - - def __init__(self, rom_loader): - self.secure_download_mode = rom_loader.secure_download_mode - self._port = rom_loader._port - self._trace_enabled = rom_loader._trace_enabled - self.flush_input() # resets _slip_reader - - -ESP32C3ROM.STUB_CLASS = ESP32C3StubLoader - - -class ESP32H2StubLoader(ESP32H2ROM): - """ Access class for ESP32H2 stub loader, runs on top of ROM. - - (Basically the same as ESP32StubLoader, but different base class. - Can possibly be made into a mixin.) - """ - FLASH_WRITE_SIZE = 0x4000 # matches MAX_WRITE_BLOCK in stub_loader.c - STATUS_BYTES_LENGTH = 2 # same as ESP8266, different to ESP32 ROM - IS_STUB = True - - def __init__(self, rom_loader): - self.secure_download_mode = rom_loader.secure_download_mode - self._port = rom_loader._port - self._trace_enabled = rom_loader._trace_enabled - self.flush_input() # resets _slip_reader - - -ESP32H2ROM.STUB_CLASS = ESP32H2StubLoader - - -class ESP8684StubLoader(ESP8684ROM): - """ Access class for ESP8684 stub loader, runs on top of ROM. - - (Basically the same as ESP32StubLoader, but different base class. - Can possibly be made into a mixin.) - """ - FLASH_WRITE_SIZE = 0x4000 # matches MAX_WRITE_BLOCK in stub_loader.c - STATUS_BYTES_LENGTH = 2 # same as ESP8266, different to ESP32 ROM - IS_STUB = True - - def __init__(self, rom_loader): - self.secure_download_mode = rom_loader.secure_download_mode - self._port = rom_loader._port - self._trace_enabled = rom_loader._trace_enabled - self.flush_input() # resets _slip_reader - - -ESP8684ROM.STUB_CLASS = ESP8684StubLoader - - -class ESPBOOTLOADER(object): - """ These are constants related to software ESP8266 bootloader, working with 'v2' image files """ - - # First byte of the "v2" application image - IMAGE_V2_MAGIC = 0xea - - # First 'segment' value in a "v2" application image, appears to be a constant version value? - IMAGE_V2_SEGMENT = 4 - - -def LoadFirmwareImage(chip, filename): - """ Load a firmware image. Can be for any supported SoC. - - ESP8266 images will be examined to determine if they are original ROM firmware images (ESP8266ROMFirmwareImage) - or "v2" OTA bootloader images. - - Returns a BaseFirmwareImage subclass, either ESP8266ROMFirmwareImage (v1) or ESP8266V2FirmwareImage (v2). - """ - chip = chip.lower().replace("-", "") - with open(filename, 'rb') as f: - if chip == 'esp32': - return ESP32FirmwareImage(f) - elif chip == "esp32s2": - return ESP32S2FirmwareImage(f) - elif chip == "esp32s3beta2": - return ESP32S3BETA2FirmwareImage(f) - elif chip == "esp32s3": - return ESP32S3FirmwareImage(f) - elif chip == 'esp32c3': - return ESP32C3FirmwareImage(f) - elif chip == 'esp32c6beta': - return ESP32C6BETAFirmwareImage(f) - elif chip == 'esp32h2': - return ESP32H2FirmwareImage(f) - elif chip == 'esp8684': - return ESP8684FirmwareImage(f) - else: # Otherwise, ESP8266 so look at magic to determine the image type - magic = ord(f.read(1)) - f.seek(0) - if magic == ESPLoader.ESP_IMAGE_MAGIC: - return ESP8266ROMFirmwareImage(f) - elif magic == ESPBOOTLOADER.IMAGE_V2_MAGIC: - return ESP8266V2FirmwareImage(f) - else: - raise FatalError("Invalid image magic number: %d" % magic) - - -class ImageSegment(object): - """ Wrapper class for a segment in an ESP image - (very similar to a section in an ELFImage also) """ - def __init__(self, addr, data, file_offs=None): - self.addr = addr - self.data = data - self.file_offs = file_offs - self.include_in_checksum = True - if self.addr != 0: - self.pad_to_alignment(4) # pad all "real" ImageSegments 4 byte aligned length - - def copy_with_new_addr(self, new_addr): - """ Return a new ImageSegment with same data, but mapped at - a new address. """ - return ImageSegment(new_addr, self.data, 0) - - def split_image(self, split_len): - """ Return a new ImageSegment which splits "split_len" bytes - from the beginning of the data. Remaining bytes are kept in - this segment object (and the start address is adjusted to match.) """ - result = copy.copy(self) - result.data = self.data[:split_len] - self.data = self.data[split_len:] - self.addr += split_len - self.file_offs = None - result.file_offs = None - return result - - def __repr__(self): - r = "len 0x%05x load 0x%08x" % (len(self.data), self.addr) - if self.file_offs is not None: - r += " file_offs 0x%08x" % (self.file_offs) - return r - - def get_memory_type(self, image): - """ - Return a list describing the memory type(s) that is covered by this - segment's start address. - """ - return [map_range[2] for map_range in image.ROM_LOADER.MEMORY_MAP if map_range[0] <= self.addr < map_range[1]] - - def pad_to_alignment(self, alignment): - self.data = pad_to(self.data, alignment, b'\x00') - - -class ELFSection(ImageSegment): - """ Wrapper class for a section in an ELF image, has a section - name as well as the common properties of an ImageSegment. """ - def __init__(self, name, addr, data): - super(ELFSection, self).__init__(addr, data) - self.name = name.decode("utf-8") - - def __repr__(self): - return "%s %s" % (self.name, super(ELFSection, self).__repr__()) - - -class BaseFirmwareImage(object): - SEG_HEADER_LEN = 8 - SHA256_DIGEST_LEN = 32 - - """ Base class with common firmware image functions """ - def __init__(self): - self.segments = [] - self.entrypoint = 0 - self.elf_sha256 = None - self.elf_sha256_offset = 0 - - def load_common_header(self, load_file, expected_magic): - (magic, segments, self.flash_mode, self.flash_size_freq, self.entrypoint) = struct.unpack(' 16: - raise FatalError('Invalid segment count %d (max 16). Usually this indicates a linker script problem.' % len(self.segments)) - - def load_segment(self, f, is_irom_segment=False): - """ Load the next segment from the image file """ - file_offs = f.tell() - (offset, size) = struct.unpack(' 0x40200000 or offset < 0x3ffe0000 or size > 65536: - print('WARNING: Suspicious segment 0x%x, length %d' % (offset, size)) - - def maybe_patch_segment_data(self, f, segment_data): - """If SHA256 digest of the ELF file needs to be inserted into this segment, do so. Returns segment data.""" - segment_len = len(segment_data) - file_pos = f.tell() # file_pos is position in the .bin file - if self.elf_sha256_offset >= file_pos and self.elf_sha256_offset < file_pos + segment_len: - # SHA256 digest needs to be patched into this binary segment, - # calculate offset of the digest inside the binary segment. - patch_offset = self.elf_sha256_offset - file_pos - # Sanity checks - if patch_offset < self.SEG_HEADER_LEN or patch_offset + self.SHA256_DIGEST_LEN > segment_len: - raise FatalError('Cannot place SHA256 digest on segment boundary' - '(elf_sha256_offset=%d, file_pos=%d, segment_size=%d)' % - (self.elf_sha256_offset, file_pos, segment_len)) - # offset relative to the data part - patch_offset -= self.SEG_HEADER_LEN - if segment_data[patch_offset:patch_offset + self.SHA256_DIGEST_LEN] != b'\x00' * self.SHA256_DIGEST_LEN: - raise FatalError('Contents of segment at SHA256 digest offset 0x%x are not all zero. Refusing to overwrite.' % - self.elf_sha256_offset) - assert(len(self.elf_sha256) == self.SHA256_DIGEST_LEN) - segment_data = segment_data[0:patch_offset] + self.elf_sha256 + \ - segment_data[patch_offset + self.SHA256_DIGEST_LEN:] - return segment_data - - def save_segment(self, f, segment, checksum=None): - """ Save the next segment to the image file, return next checksum value if provided """ - segment_data = self.maybe_patch_segment_data(f, segment.data) - f.write(struct.pack(' 0: - if len(irom_segments) != 1: - raise FatalError('Found %d segments that could be irom0. Bad ELF file?' % len(irom_segments)) - return irom_segments[0] - return None - - def get_non_irom_segments(self): - irom_segment = self.get_irom_segment() - return [s for s in self.segments if s != irom_segment] - - def merge_adjacent_segments(self): - if not self.segments: - return # nothing to merge - - segments = [] - # The easiest way to merge the sections is the browse them backward. - for i in range(len(self.segments) - 1, 0, -1): - # elem is the previous section, the one `next_elem` may need to be - # merged in - elem = self.segments[i - 1] - next_elem = self.segments[i] - if all((elem.get_memory_type(self) == next_elem.get_memory_type(self), - elem.include_in_checksum == next_elem.include_in_checksum, - next_elem.addr == elem.addr + len(elem.data))): - # Merge any segment that ends where the next one starts, without spanning memory types - # - # (don't 'pad' any gaps here as they may be excluded from the image due to 'noinit' - # or other reasons.) - elem.data += next_elem.data - else: - # The section next_elem cannot be merged into the previous one, - # which means it needs to be part of the final segments. - # As we are browsing the list backward, the elements need to be - # inserted at the beginning of the final list. - segments.insert(0, next_elem) - - # The first segment will always be here as it cannot be merged into any - # "previous" section. - segments.insert(0, self.segments[0]) - - # note: we could sort segments here as well, but the ordering of segments is sometimes - # important for other reasons (like embedded ELF SHA-256), so we assume that the linker - # script will have produced any adjacent sections in linear order in the ELF, anyhow. - self.segments = segments - - -class ESP8266ROMFirmwareImage(BaseFirmwareImage): - """ 'Version 1' firmware image, segments loaded directly by the ROM bootloader. """ - - ROM_LOADER = ESP8266ROM - - def __init__(self, load_file=None): - super(ESP8266ROMFirmwareImage, self).__init__() - self.flash_mode = 0 - self.flash_size_freq = 0 - self.version = 1 - - if load_file is not None: - segments = self.load_common_header(load_file, ESPLoader.ESP_IMAGE_MAGIC) - - for _ in range(segments): - self.load_segment(load_file) - self.checksum = self.read_checksum(load_file) - - self.verify() - - def default_output_name(self, input_file): - """ Derive a default output name from the ELF name. """ - return input_file + '-' - - def save(self, basename): - """ Save a set of V1 images for flashing. Parameter is a base filename. """ - # IROM data goes in its own plain binary file - irom_segment = self.get_irom_segment() - if irom_segment is not None: - with open("%s0x%05x.bin" % (basename, irom_segment.addr - ESP8266ROM.IROM_MAP_START), "wb") as f: - f.write(irom_segment.data) - - # everything but IROM goes at 0x00000 in an image file - normal_segments = self.get_non_irom_segments() - with open("%s0x00000.bin" % basename, 'wb') as f: - self.write_common_header(f, normal_segments) - checksum = ESPLoader.ESP_CHECKSUM_MAGIC - for segment in normal_segments: - checksum = self.save_segment(f, segment, checksum) - self.append_checksum(f, checksum) - - -ESP8266ROM.BOOTLOADER_IMAGE = ESP8266ROMFirmwareImage - - -class ESP8266V2FirmwareImage(BaseFirmwareImage): - """ 'Version 2' firmware image, segments loaded by software bootloader stub - (ie Espressif bootloader or rboot) - """ - - ROM_LOADER = ESP8266ROM - - def __init__(self, load_file=None): - super(ESP8266V2FirmwareImage, self).__init__() - self.version = 2 - if load_file is not None: - segments = self.load_common_header(load_file, ESPBOOTLOADER.IMAGE_V2_MAGIC) - if segments != ESPBOOTLOADER.IMAGE_V2_SEGMENT: - # segment count is not really segment count here, but we expect to see '4' - print('Warning: V2 header has unexpected "segment" count %d (usually 4)' % segments) - - # irom segment comes before the second header - # - # the file is saved in the image with a zero load address - # in the header, so we need to calculate a load address - irom_segment = self.load_segment(load_file, True) - irom_segment.addr = 0 # for actual mapped addr, add ESP8266ROM.IROM_MAP_START + flashing_addr + 8 - irom_segment.include_in_checksum = False - - first_flash_mode = self.flash_mode - first_flash_size_freq = self.flash_size_freq - first_entrypoint = self.entrypoint - # load the second header - - segments = self.load_common_header(load_file, ESPLoader.ESP_IMAGE_MAGIC) - - if first_flash_mode != self.flash_mode: - print('WARNING: Flash mode value in first header (0x%02x) disagrees with second (0x%02x). Using second value.' - % (first_flash_mode, self.flash_mode)) - if first_flash_size_freq != self.flash_size_freq: - print('WARNING: Flash size/freq value in first header (0x%02x) disagrees with second (0x%02x). Using second value.' - % (first_flash_size_freq, self.flash_size_freq)) - if first_entrypoint != self.entrypoint: - print('WARNING: Entrypoint address in first header (0x%08x) disagrees with second header (0x%08x). Using second value.' - % (first_entrypoint, self.entrypoint)) - - # load all the usual segments - for _ in range(segments): - self.load_segment(load_file) - self.checksum = self.read_checksum(load_file) - - self.verify() - - def default_output_name(self, input_file): - """ Derive a default output name from the ELF name. """ - irom_segment = self.get_irom_segment() - if irom_segment is not None: - irom_offs = irom_segment.addr - ESP8266ROM.IROM_MAP_START - else: - irom_offs = 0 - return "%s-0x%05x.bin" % (os.path.splitext(input_file)[0], - irom_offs & ~(ESPLoader.FLASH_SECTOR_SIZE - 1)) - - def save(self, filename): - with open(filename, 'wb') as f: - # Save first header for irom0 segment - f.write(struct.pack(b' 0: - last_addr = flash_segments[0].addr - for segment in flash_segments[1:]: - if segment.addr // self.IROM_ALIGN == last_addr // self.IROM_ALIGN: - raise FatalError(("Segment loaded at 0x%08x lands in same 64KB flash mapping as segment loaded at 0x%08x. " - "Can't generate binary. Suggest changing linker script or ELF to merge sections.") % - (segment.addr, last_addr)) - last_addr = segment.addr - - def get_alignment_data_needed(segment): - # Actual alignment (in data bytes) required for a segment header: positioned so that - # after we write the next 8 byte header, file_offs % IROM_ALIGN == segment.addr % IROM_ALIGN - # - # (this is because the segment's vaddr may not be IROM_ALIGNed, more likely is aligned - # IROM_ALIGN+0x18 to account for the binary file header - align_past = (segment.addr % self.IROM_ALIGN) - self.SEG_HEADER_LEN - pad_len = (self.IROM_ALIGN - (f.tell() % self.IROM_ALIGN)) + align_past - if pad_len == 0 or pad_len == self.IROM_ALIGN: - return 0 # already aligned - - # subtract SEG_HEADER_LEN a second time, as the padding block has a header as well - pad_len -= self.SEG_HEADER_LEN - if pad_len < 0: - pad_len += self.IROM_ALIGN - return pad_len - - # try to fit each flash segment on a 64kB aligned boundary - # by padding with parts of the non-flash segments... - while len(flash_segments) > 0: - segment = flash_segments[0] - pad_len = get_alignment_data_needed(segment) - if pad_len > 0: # need to pad - if len(ram_segments) > 0 and pad_len > self.SEG_HEADER_LEN: - pad_segment = ram_segments[0].split_image(pad_len) - if len(ram_segments[0].data) == 0: - ram_segments.pop(0) - else: - pad_segment = ImageSegment(0, b'\x00' * pad_len, f.tell()) - checksum = self.save_segment(f, pad_segment, checksum) - total_segments += 1 - else: - # write the flash segment - assert (f.tell() + 8) % self.IROM_ALIGN == segment.addr % self.IROM_ALIGN - checksum = self.save_flash_segment(f, segment, checksum) - flash_segments.pop(0) - total_segments += 1 - - # flash segments all written, so write any remaining RAM segments - for segment in ram_segments: - checksum = self.save_segment(f, segment, checksum) - total_segments += 1 - - if self.secure_pad: - # pad the image so that after signing it will end on a a 64KB boundary. - # This ensures all mapped flash content will be verified. - if not self.append_digest: - raise FatalError("secure_pad only applies if a SHA-256 digest is also appended to the image") - align_past = (f.tell() + self.SEG_HEADER_LEN) % self.IROM_ALIGN - # 16 byte aligned checksum (force the alignment to simplify calculations) - checksum_space = 16 - if self.secure_pad == '1': - # after checksum: SHA-256 digest + (to be added by signing process) version, signature + 12 trailing bytes due to alignment - space_after_checksum = 32 + 4 + 64 + 12 - elif self.secure_pad == '2': # Secure Boot V2 - # after checksum: SHA-256 digest + signature sector, but we place signature sector after the 64KB boundary - space_after_checksum = 32 - pad_len = (self.IROM_ALIGN - align_past - checksum_space - space_after_checksum) % self.IROM_ALIGN - pad_segment = ImageSegment(0, b'\x00' * pad_len, f.tell()) - - checksum = self.save_segment(f, pad_segment, checksum) - total_segments += 1 - - # done writing segments - self.append_checksum(f, checksum) - image_length = f.tell() - - if self.secure_pad: - assert ((image_length + space_after_checksum) % self.IROM_ALIGN) == 0 - - # kinda hacky: go back to the initial header and write the new segment count - # that includes padding segments. This header is not checksummed - f.seek(1) - try: - f.write(chr(total_segments)) - except TypeError: # Python 3 - f.write(bytes([total_segments])) - - if self.append_digest: - # calculate the SHA256 of the whole file and append it - f.seek(0) - digest = hashlib.sha256() - digest.update(f.read(image_length)) - f.write(digest.digest()) - - with open(filename, 'wb') as real_file: - real_file.write(f.getvalue()) - - def save_flash_segment(self, f, segment, checksum=None): - """ Save the next segment to the image file, return next checksum value if provided """ - segment_end_pos = f.tell() + len(segment.data) + self.SEG_HEADER_LEN - segment_len_remainder = segment_end_pos % self.IROM_ALIGN - if segment_len_remainder < 0x24: - # Work around a bug in ESP-IDF 2nd stage bootloader, that it didn't map the - # last MMU page, if an IROM/DROM segment was < 0x24 bytes over the page boundary. - segment.data += b'\x00' * (0x24 - segment_len_remainder) - return self.save_segment(f, segment, checksum) - - def load_extended_header(self, load_file): - def split_byte(n): - return (n & 0x0F, (n >> 4) & 0x0F) - - fields = list(struct.unpack(self.EXTENDED_HEADER_STRUCT_FMT, load_file.read(16))) - - self.wp_pin = fields[0] - - # SPI pin drive stengths are two per byte - self.clk_drv, self.q_drv = split_byte(fields[1]) - self.d_drv, self.cs_drv = split_byte(fields[2]) - self.hd_drv, self.wp_drv = split_byte(fields[3]) - - chip_id = fields[4] - if chip_id != self.ROM_LOADER.IMAGE_CHIP_ID: - print(("Unexpected chip id in image. Expected %d but value was %d. " - "Is this image for a different chip model?") % (self.ROM_LOADER.IMAGE_CHIP_ID, chip_id)) - - # reserved fields in the middle should all be zero - if any(f for f in fields[6:-1] if f != 0): - print("Warning: some reserved header fields have non-zero values. This image may be from a newer esptool.py?") - - append_digest = fields[-1] # last byte is append_digest - if append_digest in [0, 1]: - self.append_digest = (append_digest == 1) - else: - raise RuntimeError("Invalid value for append_digest field (0x%02x). Should be 0 or 1.", append_digest) - - def save_extended_header(self, save_file): - def join_byte(ln, hn): - return (ln & 0x0F) + ((hn & 0x0F) << 4) - - append_digest = 1 if self.append_digest else 0 - - fields = [self.wp_pin, - join_byte(self.clk_drv, self.q_drv), - join_byte(self.d_drv, self.cs_drv), - join_byte(self.hd_drv, self.wp_drv), - self.ROM_LOADER.IMAGE_CHIP_ID, - self.min_rev] - fields += [0] * 8 # padding - fields += [append_digest] - - packed = struct.pack(self.EXTENDED_HEADER_STRUCT_FMT, *fields) - save_file.write(packed) - - -class ESP8266V3FirmwareImage(ESP32FirmwareImage): - """ ESP8266 V3 firmware image is very similar to ESP32 image - """ - - EXTENDED_HEADER_STRUCT_FMT = "B" * 16 - - def is_flash_addr(self, addr): - return (addr > ESP8266ROM.IROM_MAP_START) - - def save(self, filename): - total_segments = 0 - with io.BytesIO() as f: # write file to memory first - self.write_common_header(f, self.segments) - - checksum = ESPLoader.ESP_CHECKSUM_MAGIC - - # split segments into flash-mapped vs ram-loaded, and take copies so we can mutate them - flash_segments = [copy.deepcopy(s) for s in sorted(self.segments, key=lambda s:s.addr) if self.is_flash_addr(s.addr) and len(s.data)] - ram_segments = [copy.deepcopy(s) for s in sorted(self.segments, key=lambda s:s.addr) if not self.is_flash_addr(s.addr) and len(s.data)] - - # check for multiple ELF sections that are mapped in the same flash mapping region. - # this is usually a sign of a broken linker script, but if you have a legitimate - # use case then let us know - if len(flash_segments) > 0: - last_addr = flash_segments[0].addr - for segment in flash_segments[1:]: - if segment.addr // self.IROM_ALIGN == last_addr // self.IROM_ALIGN: - raise FatalError(("Segment loaded at 0x%08x lands in same 64KB flash mapping as segment loaded at 0x%08x. " - "Can't generate binary. Suggest changing linker script or ELF to merge sections.") % - (segment.addr, last_addr)) - last_addr = segment.addr - - # try to fit each flash segment on a 64kB aligned boundary - # by padding with parts of the non-flash segments... - while len(flash_segments) > 0: - segment = flash_segments[0] - # remove 8 bytes empty data for insert segment header - if segment.name == '.flash.rodata': - segment.data = segment.data[8:] - # write the flash segment - checksum = self.save_segment(f, segment, checksum) - flash_segments.pop(0) - total_segments += 1 - - # flash segments all written, so write any remaining RAM segments - for segment in ram_segments: - checksum = self.save_segment(f, segment, checksum) - total_segments += 1 - - # done writing segments - self.append_checksum(f, checksum) - image_length = f.tell() - - # kinda hacky: go back to the initial header and write the new segment count - # that includes padding segments. This header is not checksummed - f.seek(1) - try: - f.write(chr(total_segments)) - except TypeError: # Python 3 - f.write(bytes([total_segments])) - - if self.append_digest: - # calculate the SHA256 of the whole file and append it - f.seek(0) - digest = hashlib.sha256() - digest.update(f.read(image_length)) - f.write(digest.digest()) - - with open(filename, 'wb') as real_file: - real_file.write(f.getvalue()) - - def load_extended_header(self, load_file): - def split_byte(n): - return (n & 0x0F, (n >> 4) & 0x0F) - - fields = list(struct.unpack(self.EXTENDED_HEADER_STRUCT_FMT, load_file.read(16))) - - self.wp_pin = fields[0] - - # SPI pin drive stengths are two per byte - self.clk_drv, self.q_drv = split_byte(fields[1]) - self.d_drv, self.cs_drv = split_byte(fields[2]) - self.hd_drv, self.wp_drv = split_byte(fields[3]) - - if fields[15] in [0, 1]: - self.append_digest = (fields[15] == 1) - else: - raise RuntimeError("Invalid value for append_digest field (0x%02x). Should be 0 or 1.", fields[15]) - - # remaining fields in the middle should all be zero - if any(f for f in fields[4:15] if f != 0): - print("Warning: some reserved header fields have non-zero values. This image may be from a newer esptool.py?") - - -ESP32ROM.BOOTLOADER_IMAGE = ESP32FirmwareImage - - -class ESP32S2FirmwareImage(ESP32FirmwareImage): - """ ESP32S2 Firmware Image almost exactly the same as ESP32FirmwareImage """ - ROM_LOADER = ESP32S2ROM - - -ESP32S2ROM.BOOTLOADER_IMAGE = ESP32S2FirmwareImage - - -class ESP32S3BETA2FirmwareImage(ESP32FirmwareImage): - """ ESP32S3 Firmware Image almost exactly the same as ESP32FirmwareImage """ - ROM_LOADER = ESP32S3BETA2ROM - - -ESP32S3BETA2ROM.BOOTLOADER_IMAGE = ESP32S3BETA2FirmwareImage - - -class ESP32S3FirmwareImage(ESP32FirmwareImage): - """ ESP32S3 Firmware Image almost exactly the same as ESP32FirmwareImage """ - ROM_LOADER = ESP32S3ROM - - -ESP32S3ROM.BOOTLOADER_IMAGE = ESP32S3FirmwareImage - - -class ESP32C3FirmwareImage(ESP32FirmwareImage): - """ ESP32C3 Firmware Image almost exactly the same as ESP32FirmwareImage """ - ROM_LOADER = ESP32C3ROM - - -ESP32C3ROM.BOOTLOADER_IMAGE = ESP32C3FirmwareImage - - -class ESP32C6BETAFirmwareImage(ESP32FirmwareImage): - """ ESP32C6 Firmware Image almost exactly the same as ESP32FirmwareImage """ - ROM_LOADER = ESP32C6BETAROM - - -ESP32C6BETAROM.BOOTLOADER_IMAGE = ESP32C6BETAFirmwareImage - - -class ESP32H2FirmwareImage(ESP32FirmwareImage): - """ ESP32H2 Firmware Image almost exactly the same as ESP32FirmwareImage """ - ROM_LOADER = ESP32H2ROM - - -ESP32H2ROM.BOOTLOADER_IMAGE = ESP32H2FirmwareImage - - -class ESP8684FirmwareImage(ESP32FirmwareImage): - """ ESP8684 Firmware Image almost exactly the same as ESP32FirmwareImage """ - ROM_LOADER = ESP8684ROM - - -ESP8684ROM.BOOTLOADER_IMAGE = ESP8684FirmwareImage - - -class ELFFile(object): - SEC_TYPE_PROGBITS = 0x01 - SEC_TYPE_STRTAB = 0x03 - - LEN_SEC_HEADER = 0x28 - - SEG_TYPE_LOAD = 0x01 - LEN_SEG_HEADER = 0x20 - - def __init__(self, name): - # Load sections from the ELF file - self.name = name - with open(self.name, 'rb') as f: - self._read_elf_file(f) - - def get_section(self, section_name): - for s in self.sections: - if s.name == section_name: - return s - raise ValueError("No section %s in ELF file" % section_name) - - def _read_elf_file(self, f): - # read the ELF file header - LEN_FILE_HEADER = 0x34 - try: - (ident, _type, machine, _version, - self.entrypoint, _phoff, shoff, _flags, - _ehsize, _phentsize, _phnum, shentsize, - shnum, shstrndx) = struct.unpack("<16sHHLLLLLHHHHHH", f.read(LEN_FILE_HEADER)) - except struct.error as e: - raise FatalError("Failed to read a valid ELF header from %s: %s" % (self.name, e)) - - if byte(ident, 0) != 0x7f or ident[1:4] != b'ELF': - raise FatalError("%s has invalid ELF magic header" % self.name) - if machine not in [0x5e, 0xf3]: - raise FatalError("%s does not appear to be an Xtensa or an RISCV ELF file. e_machine=%04x" % (self.name, machine)) - if shentsize != self.LEN_SEC_HEADER: - raise FatalError("%s has unexpected section header entry size 0x%x (not 0x%x)" % (self.name, shentsize, self.LEN_SEC_HEADER)) - if shnum == 0: - raise FatalError("%s has 0 section headers" % (self.name)) - self._read_sections(f, shoff, shnum, shstrndx) - self._read_segments(f, _phoff, _phnum, shstrndx) - - def _read_sections(self, f, section_header_offs, section_header_count, shstrndx): - f.seek(section_header_offs) - len_bytes = section_header_count * self.LEN_SEC_HEADER - section_header = f.read(len_bytes) - if len(section_header) == 0: - raise FatalError("No section header found at offset %04x in ELF file." % section_header_offs) - if len(section_header) != (len_bytes): - raise FatalError("Only read 0x%x bytes from section header (expected 0x%x.) Truncated ELF file?" % (len(section_header), len_bytes)) - - # walk through the section header and extract all sections - section_header_offsets = range(0, len(section_header), self.LEN_SEC_HEADER) - - def read_section_header(offs): - name_offs, sec_type, _flags, lma, sec_offs, size = struct.unpack_from(" 0] - self.sections = prog_sections - - def _read_segments(self, f, segment_header_offs, segment_header_count, shstrndx): - f.seek(segment_header_offs) - len_bytes = segment_header_count * self.LEN_SEG_HEADER - segment_header = f.read(len_bytes) - if len(segment_header) == 0: - raise FatalError("No segment header found at offset %04x in ELF file." % segment_header_offs) - if len(segment_header) != (len_bytes): - raise FatalError("Only read 0x%x bytes from segment header (expected 0x%x.) Truncated ELF file?" % (len(segment_header), len_bytes)) - - # walk through the segment header and extract all segments - segment_header_offsets = range(0, len(segment_header), self.LEN_SEG_HEADER) - - def read_segment_header(offs): - seg_type, seg_offs, _vaddr, lma, size, _memsize, _flags, _align = struct.unpack_from(" 0] - self.segments = prog_segments - - def sha256(self): - # return SHA256 hash of the input ELF file - sha256 = hashlib.sha256() - with open(self.name, 'rb') as f: - sha256.update(f.read()) - return sha256.digest() - - -def slip_reader(port, trace_function): - """Generator to read SLIP packets from a serial port. - Yields one full SLIP packet at a time, raises exception on timeout or invalid data. - - Designed to avoid too many calls to serial.read(1), which can bog - down on slow systems. - """ - partial_packet = None - in_escape = False - successful_slip = False - while True: - waiting = port.inWaiting() - read_bytes = port.read(1 if waiting == 0 else waiting) - if read_bytes == b'': - if partial_packet is None: # fail due to no data - msg = "Serial data stream stopped: Possible serial noise or corruption." if successful_slip else "No serial data received." - else: # fail during packet transfer - msg = "Packet content transfer stopped (received {} bytes)".format(len(partial_packet)) - trace_function(msg) - raise FatalError(msg) - trace_function("Read %d bytes: %s", len(read_bytes), HexFormatter(read_bytes)) - for b in read_bytes: - if type(b) is int: - b = bytes([b]) # python 2/3 compat - - if partial_packet is None: # waiting for packet header - if b == b'\xc0': - partial_packet = b"" - else: - trace_function("Read invalid data: %s", HexFormatter(read_bytes)) - trace_function("Remaining data in serial buffer: %s", HexFormatter(port.read(port.inWaiting()))) - raise FatalError('Invalid head of packet (0x%s): Possible serial noise or corruption.' % hexify(b)) - elif in_escape: # part-way through escape sequence - in_escape = False - if b == b'\xdc': - partial_packet += b'\xc0' - elif b == b'\xdd': - partial_packet += b'\xdb' - else: - trace_function("Read invalid data: %s", HexFormatter(read_bytes)) - trace_function("Remaining data in serial buffer: %s", HexFormatter(port.read(port.inWaiting()))) - raise FatalError('Invalid SLIP escape (0xdb, 0x%s)' % (hexify(b))) - elif b == b'\xdb': # start of escape sequence - in_escape = True - elif b == b'\xc0': # end of packet - trace_function("Received full packet: %s", HexFormatter(partial_packet)) - yield partial_packet - partial_packet = None - successful_slip = True - else: # normal byte in packet - partial_packet += b - - -def arg_auto_int(x): - return int(x, 0) - - -def div_roundup(a, b): - """ Return a/b rounded up to nearest integer, - equivalent result to int(math.ceil(float(int(a)) / float(int(b))), only - without possible floating point accuracy errors. - """ - return (int(a) + int(b) - 1) // int(b) - - -def align_file_position(f, size): - """ Align the position in the file to the next block of specified size """ - align = (size - 1) - (f.tell() % size) - f.seek(align, 1) - - -def flash_size_bytes(size): - """ Given a flash size of the type passed in args.flash_size - (ie 512KB or 1MB) then return the size in bytes. - """ - if "MB" in size: - return int(size[:size.index("MB")]) * 1024 * 1024 - elif "KB" in size: - return int(size[:size.index("KB")]) * 1024 - else: - raise FatalError("Unknown size %s" % size) - - -def hexify(s, uppercase=True): - format_str = '%02X' if uppercase else '%02x' - if not PYTHON2: - return ''.join(format_str % c for c in s) - else: - return ''.join(format_str % ord(c) for c in s) - - -class HexFormatter(object): - """ - Wrapper class which takes binary data in its constructor - and returns a hex string as it's __str__ method. - - This is intended for "lazy formatting" of trace() output - in hex format. Avoids overhead (significant on slow computers) - of generating long hex strings even if tracing is disabled. - - Note that this doesn't save any overhead if passed as an - argument to "%", only when passed to trace() - - If auto_split is set (default), any long line (> 16 bytes) will be - printed as separately indented lines, with ASCII decoding at the end - of each line. - """ - def __init__(self, binary_string, auto_split=True): - self._s = binary_string - self._auto_split = auto_split - - def __str__(self): - if self._auto_split and len(self._s) > 16: - result = "" - s = self._s - while len(s) > 0: - line = s[:16] - ascii_line = "".join(c if (c == ' ' or (c in string.printable and c not in string.whitespace)) - else '.' for c in line.decode('ascii', 'replace')) - s = s[16:] - result += "\n %-16s %-16s | %s" % (hexify(line[:8], False), hexify(line[8:], False), ascii_line) - return result - else: - return hexify(self._s, False) - - -def pad_to(data, alignment, pad_character=b'\xFF'): - """ Pad to the next alignment boundary """ - pad_mod = len(data) % alignment - if pad_mod != 0: - data += pad_character * (alignment - pad_mod) - return data - - -class FatalError(RuntimeError): - """ - Wrapper class for runtime errors that aren't caused by internal bugs, but by - ESP8266 responses or input content. - """ - def __init__(self, message): - RuntimeError.__init__(self, message) - - @staticmethod - def WithResult(message, result): - """ - Return a fatal error object that appends the hex values of - 'result' and its meaning as a string formatted argument. - """ - - err_defs = { - 0x101: 'Out of memory', - 0x102: 'Invalid argument', - 0x103: 'Invalid state', - 0x104: 'Invalid size', - 0x105: 'Requested resource not found', - 0x106: 'Operation or feature not supported', - 0x107: 'Operation timed out', - 0x108: 'Received response was invalid', - 0x109: 'CRC or checksum was invalid', - 0x10A: 'Version was invalid', - 0x10B: 'MAC address was invalid', - } - - err_code = struct.unpack(">H", result[:2]) - message += " (result was {}: {})".format(hexify(result), err_defs.get(err_code[0], 'Unknown result')) - return FatalError(message) - - -class NotImplementedInROMError(FatalError): - """ - Wrapper class for the error thrown when a particular ESP bootloader function - is not implemented in the ROM bootloader. - """ - def __init__(self, bootloader, func): - FatalError.__init__(self, "%s ROM does not support function %s." % (bootloader.CHIP_NAME, func.__name__)) - - -class NotSupportedError(FatalError): - def __init__(self, esp, function_name): - FatalError.__init__(self, "Function %s is not supported for %s." % (function_name, esp.CHIP_NAME)) - -# "Operation" commands, executable at command line. One function each -# -# Each function takes either two args (, ) or a single -# argument. - - -class UnsupportedCommandError(RuntimeError): - """ - Wrapper class for when ROM loader returns an invalid command response. - - Usually this indicates the loader is running in Secure Download Mode. - """ - def __init__(self, esp, op): - if esp.secure_download_mode: - msg = "This command (0x%x) is not supported in Secure Download Mode" % op - else: - msg = "Invalid (unsupported) command 0x%x" % op - RuntimeError.__init__(self, msg) - - -def load_ram(esp, args): - image = LoadFirmwareImage(esp.CHIP_NAME, args.filename) - - print('RAM boot...') - for seg in image.segments: - size = len(seg.data) - print('Downloading %d bytes at %08x...' % (size, seg.addr), end=' ') - sys.stdout.flush() - esp.mem_begin(size, div_roundup(size, esp.ESP_RAM_BLOCK), esp.ESP_RAM_BLOCK, seg.addr) - - seq = 0 - while len(seg.data) > 0: - esp.mem_block(seg.data[0:esp.ESP_RAM_BLOCK], seq) - seg.data = seg.data[esp.ESP_RAM_BLOCK:] - seq += 1 - print('done!') - - print('All segments done, executing at %08x' % image.entrypoint) - esp.mem_finish(image.entrypoint) - - -def read_mem(esp, args): - print('0x%08x = 0x%08x' % (args.address, esp.read_reg(args.address))) - - -def write_mem(esp, args): - esp.write_reg(args.address, args.value, args.mask, 0) - print('Wrote %08x, mask %08x to %08x' % (args.value, args.mask, args.address)) - - -def dump_mem(esp, args): - with open(args.filename, 'wb') as f: - for i in range(args.size // 4): - d = esp.read_reg(args.address + (i * 4)) - f.write(struct.pack(b'> 16 - args.flash_size = DETECTED_FLASH_SIZES.get(size_id) - if args.flash_size is None: - print('Warning: Could not auto-detect Flash size (FlashID=0x%x, SizeID=0x%x), defaulting to 4MB' % (flash_id, size_id)) - args.flash_size = '4MB' - else: - print('Auto-detected Flash size:', args.flash_size) - - -def _update_image_flash_params(esp, address, args, image): - """ Modify the flash mode & size bytes if this looks like an executable bootloader image """ - if len(image) < 8: - return image # not long enough to be a bootloader image - - # unpack the (potential) image header - magic, _, flash_mode, flash_size_freq = struct.unpack("BBBB", image[:4]) - if address != esp.BOOTLOADER_FLASH_OFFSET: - return image # not flashing bootloader offset, so don't modify this - - if (args.flash_mode, args.flash_freq, args.flash_size) == ('keep',) * 3: - return image # all settings are 'keep', not modifying anything - - # easy check if this is an image: does it start with a magic byte? - if magic != esp.ESP_IMAGE_MAGIC: - print("Warning: Image file at 0x%x doesn't look like an image file, so not changing any flash settings." % address) - return image - - # make sure this really is an image, and not just data that - # starts with esp.ESP_IMAGE_MAGIC (mostly a problem for encrypted - # images that happen to start with a magic byte - try: - test_image = esp.BOOTLOADER_IMAGE(io.BytesIO(image)) - test_image.verify() - except Exception: - print("Warning: Image file at 0x%x is not a valid %s image, so not changing any flash settings." % (address, esp.CHIP_NAME)) - return image - - if args.flash_mode != 'keep': - flash_mode = {'qio': 0, 'qout': 1, 'dio': 2, 'dout': 3}[args.flash_mode] - - flash_freq = flash_size_freq & 0x0F - if args.flash_freq != 'keep': - flash_freq = {'40m': 0, '26m': 1, '20m': 2, '80m': 0xf}[args.flash_freq] - - flash_size = flash_size_freq & 0xF0 - if args.flash_size != 'keep': - flash_size = esp.parse_flash_size_arg(args.flash_size) - - flash_params = struct.pack(b'BB', flash_mode, flash_size + flash_freq) - if flash_params != image[2:4]: - print('Flash params set to 0x%04x' % struct.unpack(">H", flash_params)) - image = image[0:2] + flash_params + image[4:] - return image - - -def write_flash(esp, args): - # set args.compress based on default behaviour: - # -> if either --compress or --no-compress is set, honour that - # -> otherwise, set --compress unless --no-stub is set - if args.compress is None and not args.no_compress: - args.compress = not args.no_stub - - # In case we have encrypted files to write, we first do few sanity checks before actual flash - if args.encrypt or args.encrypt_files is not None: - do_write = True - - if not esp.secure_download_mode: - if esp.get_encrypted_download_disabled(): - raise FatalError("This chip has encrypt functionality in UART download mode disabled. " - "This is the Flash Encryption configuration for Production mode instead of Development mode.") - - crypt_cfg_efuse = esp.get_flash_crypt_config() - - if crypt_cfg_efuse is not None and crypt_cfg_efuse != 0xF: - print('Unexpected FLASH_CRYPT_CONFIG value: 0x%x' % (crypt_cfg_efuse)) - do_write = False - - enc_key_valid = esp.is_flash_encryption_key_valid() - - if not enc_key_valid: - print('Flash encryption key is not programmed') - do_write = False - - # Determine which files list contain the ones to encrypt - files_to_encrypt = args.addr_filename if args.encrypt else args.encrypt_files - - for address, argfile in files_to_encrypt: - if address % esp.FLASH_ENCRYPTED_WRITE_ALIGN: - print("File %s address 0x%x is not %d byte aligned, can't flash encrypted" % - (argfile.name, address, esp.FLASH_ENCRYPTED_WRITE_ALIGN)) - do_write = False - - if not do_write and not args.ignore_flash_encryption_efuse_setting: - raise FatalError("Can't perform encrypted flash write, consult Flash Encryption documentation for more information") - - # verify file sizes fit in flash - if args.flash_size != 'keep': # TODO: check this even with 'keep' - flash_end = flash_size_bytes(args.flash_size) - for address, argfile in args.addr_filename: - argfile.seek(0, os.SEEK_END) - if address + argfile.tell() > flash_end: - raise FatalError(("File %s (length %d) at offset %d will not fit in %d bytes of flash. " - "Use --flash-size argument, or change flashing address.") - % (argfile.name, argfile.tell(), address, flash_end)) - argfile.seek(0) - - if args.erase_all: - erase_flash(esp, args) - else: - for address, argfile in args.addr_filename: - argfile.seek(0, os.SEEK_END) - write_end = address + argfile.tell() - argfile.seek(0) - bytes_over = address % esp.FLASH_SECTOR_SIZE - if bytes_over != 0: - print("WARNING: Flash address {:#010x} is not aligned to a {:#x} byte flash sector. " - "{:#x} bytes before this address will be erased." - .format(address, esp.FLASH_SECTOR_SIZE, bytes_over)) - # Print the address range of to-be-erased flash memory region - print("Flash will be erased from {:#010x} to {:#010x}..." - .format(address - bytes_over, div_roundup(write_end, esp.FLASH_SECTOR_SIZE) * esp.FLASH_SECTOR_SIZE - 1)) - - """ Create a list describing all the files we have to flash. Each entry holds an "encrypt" flag - marking whether the file needs encryption or not. This list needs to be sorted. - - First, append to each entry of our addr_filename list the flag args.encrypt - For example, if addr_filename is [(0x1000, "partition.bin"), (0x8000, "bootloader")], - all_files will be [(0x1000, "partition.bin", args.encrypt), (0x8000, "bootloader", args.encrypt)], - where, of course, args.encrypt is either True or False - """ - all_files = [(offs, filename, args.encrypt) for (offs, filename) in args.addr_filename] - - """Now do the same with encrypt_files list, if defined. - In this case, the flag is True - """ - if args.encrypt_files is not None: - encrypted_files_flag = [(offs, filename, True) for (offs, filename) in args.encrypt_files] - - # Concatenate both lists and sort them. - # As both list are already sorted, we could simply do a merge instead, - # but for the sake of simplicity and because the lists are very small, - # let's use sorted. - all_files = sorted(all_files + encrypted_files_flag, key=lambda x: x[0]) - - for address, argfile, encrypted in all_files: - compress = args.compress - - # Check whether we can compress the current file before flashing - if compress and encrypted: - print('\nWARNING: - compress and encrypt options are mutually exclusive ') - print('Will flash %s uncompressed' % argfile.name) - compress = False - - if args.no_stub: - print('Erasing flash...') - image = pad_to(argfile.read(), esp.FLASH_ENCRYPTED_WRITE_ALIGN if encrypted else 4) - if len(image) == 0: - print('WARNING: File %s is empty' % argfile.name) - continue - image = _update_image_flash_params(esp, address, args, image) - calcmd5 = hashlib.md5(image).hexdigest() - uncsize = len(image) - if compress: - uncimage = image - image = zlib.compress(uncimage, 9) - # Decompress the compressed binary a block at a time, to dynamically calculate the - # timeout based on the real write size - decompress = zlib.decompressobj() - blocks = esp.flash_defl_begin(uncsize, len(image), address) - else: - blocks = esp.flash_begin(uncsize, address, begin_rom_encrypted=encrypted) - argfile.seek(0) # in case we need it again - seq = 0 - bytes_sent = 0 # bytes sent on wire - bytes_written = 0 # bytes written to flash - t = time.time() - - timeout = DEFAULT_TIMEOUT - - while len(image) > 0: - print_overwrite('Writing at 0x%08x... (%d %%)' % (address + bytes_written, 100 * (seq + 1) // blocks)) - sys.stdout.flush() - block = image[0:esp.FLASH_WRITE_SIZE] - if compress: - # feeding each compressed block into the decompressor lets us see block-by-block how much will be written - block_uncompressed = len(decompress.decompress(block)) - bytes_written += block_uncompressed - block_timeout = max(DEFAULT_TIMEOUT, timeout_per_mb(ERASE_WRITE_TIMEOUT_PER_MB, block_uncompressed)) - if not esp.IS_STUB: - timeout = block_timeout # ROM code writes block to flash before ACKing - esp.flash_defl_block(block, seq, timeout=timeout) - if esp.IS_STUB: - timeout = block_timeout # Stub ACKs when block is received, then writes to flash while receiving the block after it - else: - # Pad the last block - block = block + b'\xff' * (esp.FLASH_WRITE_SIZE - len(block)) - if encrypted: - esp.flash_encrypt_block(block, seq) - else: - esp.flash_block(block, seq) - bytes_written += len(block) - bytes_sent += len(block) - image = image[esp.FLASH_WRITE_SIZE:] - seq += 1 - - if esp.IS_STUB: - # Stub only writes each block to flash after 'ack'ing the receive, so do a final dummy operation which will - # not be 'ack'ed until the last block has actually been written out to flash - esp.read_reg(ESPLoader.CHIP_DETECT_MAGIC_REG_ADDR, timeout=timeout) - - t = time.time() - t - speed_msg = "" - if compress: - if t > 0.0: - speed_msg = " (effective %.1f kbit/s)" % (uncsize / t * 8 / 1000) - print_overwrite('Wrote %d bytes (%d compressed) at 0x%08x in %.1f seconds%s...' % (uncsize, - bytes_sent, - address, t, speed_msg), last_line=True) - else: - if t > 0.0: - speed_msg = " (%.1f kbit/s)" % (bytes_written / t * 8 / 1000) - print_overwrite('Wrote %d bytes at 0x%08x in %.1f seconds%s...' % (bytes_written, address, t, speed_msg), last_line=True) - - if not encrypted and not esp.secure_download_mode: - try: - res = esp.flash_md5sum(address, uncsize) - if res != calcmd5: - print('File md5: %s' % calcmd5) - print('Flash md5: %s' % res) - print('MD5 of 0xFF is %s' % (hashlib.md5(b'\xFF' * uncsize).hexdigest())) - raise FatalError("MD5 of file does not match data in flash!") - else: - print('Hash of data verified.') - except NotImplementedInROMError: - pass - - print('\nLeaving...') - - if esp.IS_STUB: - # skip sending flash_finish to ROM loader here, - # as it causes the loader to exit and run user code - esp.flash_begin(0, 0) - - # Get the "encrypted" flag for the last file flashed - # Note: all_files list contains triplets like: - # (address: Integer, filename: String, encrypted: Boolean) - last_file_encrypted = all_files[-1][2] - - # Check whether the last file flashed was compressed or not - if args.compress and not last_file_encrypted: - esp.flash_defl_finish(False) - else: - esp.flash_finish(False) - - if args.verify: - print('Verifying just-written flash...') - print('(This option is deprecated, flash contents are now always read back after flashing.)') - # If some encrypted files have been flashed print a warning saying that we won't check them - if args.encrypt or args.encrypt_files is not None: - print('WARNING: - cannot verify encrypted files, they will be ignored') - # Call verify_flash function only if there at least one non-encrypted file flashed - if not args.encrypt: - verify_flash(esp, args) - - -def image_info(args): - image = LoadFirmwareImage(args.chip, args.filename) - print('Image version: %d' % image.version) - print('Entry point: %08x' % image.entrypoint if image.entrypoint != 0 else 'Entry point not set') - print('%d segments' % len(image.segments)) - print() - idx = 0 - for seg in image.segments: - idx += 1 - segs = seg.get_memory_type(image) - seg_name = ",".join(segs) - print('Segment %d: %r [%s]' % (idx, seg, seg_name)) - calc_checksum = image.calculate_checksum() - print('Checksum: %02x (%s)' % (image.checksum, - 'valid' if image.checksum == calc_checksum else 'invalid - calculated %02x' % calc_checksum)) - try: - digest_msg = 'Not appended' - if image.append_digest: - is_valid = image.stored_digest == image.calc_digest - digest_msg = "%s (%s)" % (hexify(image.calc_digest).lower(), - "valid" if is_valid else "invalid") - print('Validation Hash: %s' % digest_msg) - except AttributeError: - pass # ESP8266 image has no append_digest field - - -def make_image(args): - image = ESP8266ROMFirmwareImage() - if len(args.segfile) == 0: - raise FatalError('No segments specified') - if len(args.segfile) != len(args.segaddr): - raise FatalError('Number of specified files does not match number of specified addresses') - for (seg, addr) in zip(args.segfile, args.segaddr): - with open(seg, 'rb') as f: - data = f.read() - image.segments.append(ImageSegment(addr, data)) - image.entrypoint = args.entrypoint - image.save(args.output) - - -def elf2image(args): - e = ELFFile(args.input) - if args.chip == 'auto': # Default to ESP8266 for backwards compatibility - print("Creating image for ESP8266...") - args.chip = 'esp8266' - - if args.chip == 'esp32': - image = ESP32FirmwareImage() - if args.secure_pad: - image.secure_pad = '1' - elif args.secure_pad_v2: - image.secure_pad = '2' - elif args.chip == 'esp32s2': - image = ESP32S2FirmwareImage() - if args.secure_pad_v2: - image.secure_pad = '2' - elif args.chip == 'esp32s3beta2': - image = ESP32S3BETA2FirmwareImage() - if args.secure_pad_v2: - image.secure_pad = '2' - elif args.chip == 'esp32s3': - image = ESP32S3FirmwareImage() - if args.secure_pad_v2: - image.secure_pad = '2' - elif args.chip == 'esp32c3': - image = ESP32C3FirmwareImage() - if args.secure_pad_v2: - image.secure_pad = '2' - elif args.chip == 'esp32c6beta': - image = ESP32C6BETAFirmwareImage() - if args.secure_pad_v2: - image.secure_pad = '2' - elif args.chip == 'esp32h2': - image = ESP32H2FirmwareImage() - if args.secure_pad_v2: - image.secure_pad = '2' - elif args.chip == 'esp8684': - image = ESP8684FirmwareImage() - if args.secure_pad_v2: - image.secure_pad = '2' - elif args.version == '1': # ESP8266 - image = ESP8266ROMFirmwareImage() - elif args.version == '2': - image = ESP8266V2FirmwareImage() - else: - image = ESP8266V3FirmwareImage() - image.entrypoint = e.entrypoint - image.flash_mode = {'qio': 0, 'qout': 1, 'dio': 2, 'dout': 3}[args.flash_mode] - - if args.chip != 'esp8266': - image.min_rev = int(args.min_rev) - - # ELFSection is a subclass of ImageSegment, so can use interchangeably - image.segments = e.segments if args.use_segments else e.sections - - image.flash_size_freq = image.ROM_LOADER.FLASH_SIZES[args.flash_size] - image.flash_size_freq += {'40m': 0, '26m': 1, '20m': 2, '80m': 0xf}[args.flash_freq] - - if args.elf_sha256_offset: - image.elf_sha256 = e.sha256() - image.elf_sha256_offset = args.elf_sha256_offset - - before = len(image.segments) - image.merge_adjacent_segments() - if len(image.segments) != before: - delta = before - len(image.segments) - print("Merged %d ELF section%s" % (delta, "s" if delta > 1 else "")) - - image.verify() - - if args.output is None: - args.output = image.default_output_name(args.input) - image.save(args.output) - - -def read_mac(esp, args): - mac = esp.read_mac() - - def print_mac(label, mac): - print('%s: %s' % (label, ':'.join(map(lambda x: '%02x' % x, mac)))) - print_mac("MAC", mac) - - -def chip_id(esp, args): - try: - chipid = esp.chip_id() - print('Chip ID: 0x%08x' % chipid) - except NotSupportedError: - print('Warning: %s has no Chip ID. Reading MAC instead.' % esp.CHIP_NAME) - read_mac(esp, args) - - -def erase_flash(esp, args): - print('Erasing flash (this may take a while)...') - t = time.time() - esp.erase_flash() - print('Chip erase completed successfully in %.1fs' % (time.time() - t)) - - -def erase_region(esp, args): - print('Erasing region (may be slow depending on size)...') - t = time.time() - esp.erase_region(args.address, args.size) - print('Erase completed successfully in %.1f seconds.' % (time.time() - t)) - - -def run(esp, args): - esp.run() - - -def flash_id(esp, args): - flash_id = esp.flash_id() - print('Manufacturer: %02x' % (flash_id & 0xff)) - flid_lowbyte = (flash_id >> 16) & 0xFF - print('Device: %02x%02x' % ((flash_id >> 8) & 0xff, flid_lowbyte)) - print('Detected flash size: %s' % (DETECTED_FLASH_SIZES.get(flid_lowbyte, "Unknown"))) - - -def read_flash(esp, args): - if args.no_progress: - flash_progress = None - else: - def flash_progress(progress, length): - msg = '%d (%d %%)' % (progress, progress * 100.0 / length) - padding = '\b' * len(msg) - if progress == length: - padding = '\n' - sys.stdout.write(msg + padding) - sys.stdout.flush() - t = time.time() - data = esp.read_flash(args.address, args.size, flash_progress) - t = time.time() - t - print_overwrite('Read %d bytes at 0x%x in %.1f seconds (%.1f kbit/s)...' - % (len(data), args.address, t, len(data) / t * 8 / 1000), last_line=True) - with open(args.filename, 'wb') as f: - f.write(data) - - -def verify_flash(esp, args): - differences = False - - for address, argfile in args.addr_filename: - image = pad_to(argfile.read(), 4) - argfile.seek(0) # rewind in case we need it again - - image = _update_image_flash_params(esp, address, args, image) - - image_size = len(image) - print('Verifying 0x%x (%d) bytes @ 0x%08x in flash against %s...' % (image_size, image_size, address, argfile.name)) - # Try digest first, only read if there are differences. - digest = esp.flash_md5sum(address, image_size) - expected_digest = hashlib.md5(image).hexdigest() - if digest == expected_digest: - print('-- verify OK (digest matched)') - continue - else: - differences = True - if getattr(args, 'diff', 'no') != 'yes': - print('-- verify FAILED (digest mismatch)') - continue - - flash = esp.read_flash(address, image_size) - assert flash != image - diff = [i for i in range(image_size) if flash[i] != image[i]] - print('-- verify FAILED: %d differences, first @ 0x%08x' % (len(diff), address + diff[0])) - for d in diff: - flash_byte = flash[d] - image_byte = image[d] - if PYTHON2: - flash_byte = ord(flash_byte) - image_byte = ord(image_byte) - print(' %08x %02x %02x' % (address + d, flash_byte, image_byte)) - if differences: - raise FatalError("Verify failed.") - - -def read_flash_status(esp, args): - print('Status value: 0x%04x' % esp.read_status(args.bytes)) - - -def write_flash_status(esp, args): - fmt = "0x%%0%dx" % (args.bytes * 2) - args.value = args.value & ((1 << (args.bytes * 8)) - 1) - print(('Initial flash status: ' + fmt) % esp.read_status(args.bytes)) - print(('Setting flash status: ' + fmt) % args.value) - esp.write_status(args.value, args.bytes, args.non_volatile) - print(('After flash status: ' + fmt) % esp.read_status(args.bytes)) - - -def get_security_info(esp, args): - si = esp.get_security_info() - # TODO: better display and tests - print('Flags: {:#010x} ({})'.format(si["flags"], bin(si["flags"]))) - print('Flash_Crypt_Cnt: {:#x}'.format(si["flash_crypt_cnt"])) - print('Key_Purposes: {}'.format(si["key_purposes"])) - if si["chip_id"] is not None and si["api_version"] is not None: - print('Chip_ID: {}'.format(si["chip_id"])) - print('Api_Version: {}'.format(si["api_version"])) - - -def merge_bin(args): - try: - chip_class = _chip_to_rom_loader(args.chip) - except KeyError: - msg = "Please specify the chip argument" if args.chip == "auto" else "Invalid chip choice: '{}'".format(args.chip) - msg = msg + " (choose from {})".format(', '.join(SUPPORTED_CHIPS)) - raise FatalError(msg) - - # sort the files by offset. The AddrFilenamePairAction has already checked for overlap - input_files = sorted(args.addr_filename, key=lambda x: x[0]) - if not input_files: - raise FatalError("No input files specified") - first_addr = input_files[0][0] - if first_addr < args.target_offset: - raise FatalError("Output file target offset is 0x%x. Input file offset 0x%x is before this." % (args.target_offset, first_addr)) - - if args.format != 'raw': - raise FatalError("This version of esptool only supports the 'raw' output format") - - with open(args.output, 'wb') as of: - def pad_to(flash_offs): - # account for output file offset if there is any - of.write(b'\xFF' * (flash_offs - args.target_offset - of.tell())) - for addr, argfile in input_files: - pad_to(addr) - image = argfile.read() - image = _update_image_flash_params(chip_class, addr, args, image) - of.write(image) - if args.fill_flash_size: - pad_to(flash_size_bytes(args.fill_flash_size)) - print("Wrote 0x%x bytes to file %s, ready to flash to offset 0x%x" % (of.tell(), args.output, args.target_offset)) - - -def version(args): - print(__version__) - -# -# End of operations functions -# - - -def main(argv=None, esp=None): - """ - Main function for esptool - - argv - Optional override for default arguments parsing (that uses sys.argv), can be a list of custom arguments - as strings. Arguments and their values need to be added as individual items to the list e.g. "-b 115200" thus - becomes ['-b', '115200']. - - esp - Optional override of the connected device previously returned by get_default_connected_device() - """ - - external_esp = esp is not None - - parser = argparse.ArgumentParser(description='esptool.py v%s - ESP8266 ROM Bootloader Utility' % __version__, prog='esptool') - - parser.add_argument('--chip', '-c', - help='Target chip type', - type=lambda c: c.lower().replace('-', ''), # support ESP32-S2, etc. - choices=['auto'] + SUPPORTED_CHIPS, - default=os.environ.get('ESPTOOL_CHIP', 'auto')) - - parser.add_argument( - '--port', '-p', - help='Serial port device', - default=os.environ.get('ESPTOOL_PORT', None)) - - parser.add_argument( - '--baud', '-b', - help='Serial port baud rate used when flashing/reading', - type=arg_auto_int, - default=os.environ.get('ESPTOOL_BAUD', ESPLoader.ESP_ROM_BAUD)) - - parser.add_argument( - '--before', - help='What to do before connecting to the chip', - choices=['default_reset', 'usb_reset', 'no_reset', 'no_reset_no_sync'], - default=os.environ.get('ESPTOOL_BEFORE', 'default_reset')) - - parser.add_argument( - '--after', '-a', - help='What to do after esptool.py is finished', - choices=['hard_reset', 'soft_reset', 'no_reset', 'no_reset_stub'], - default=os.environ.get('ESPTOOL_AFTER', 'hard_reset')) - - parser.add_argument( - '--no-stub', - help="Disable launching the flasher stub, only talk to ROM bootloader. Some features will not be available.", - action='store_true') - - parser.add_argument( - '--trace', '-t', - help="Enable trace-level output of esptool.py interactions.", - action='store_true') - - parser.add_argument( - '--override-vddsdio', - help="Override ESP32 VDDSDIO internal voltage regulator (use with care)", - choices=ESP32ROM.OVERRIDE_VDDSDIO_CHOICES, - nargs='?') - - parser.add_argument( - '--connect-attempts', - help=('Number of attempts to connect, negative or 0 for infinite. ' - 'Default: %d.' % DEFAULT_CONNECT_ATTEMPTS), - type=int, - default=os.environ.get('ESPTOOL_CONNECT_ATTEMPTS', DEFAULT_CONNECT_ATTEMPTS)) - - subparsers = parser.add_subparsers( - dest='operation', - help='Run esptool {command} -h for additional help') - - def add_spi_connection_arg(parent): - parent.add_argument('--spi-connection', '-sc', help='ESP32-only argument. Override default SPI Flash connection. ' - 'Value can be SPI, HSPI or a comma-separated list of 5 I/O numbers to use for SPI flash (CLK,Q,D,HD,CS).', - action=SpiConnectionAction) - - parser_load_ram = subparsers.add_parser( - 'load_ram', - help='Download an image to RAM and execute') - parser_load_ram.add_argument('filename', help='Firmware image') - - parser_dump_mem = subparsers.add_parser( - 'dump_mem', - help='Dump arbitrary memory to disk') - parser_dump_mem.add_argument('address', help='Base address', type=arg_auto_int) - parser_dump_mem.add_argument('size', help='Size of region to dump', type=arg_auto_int) - parser_dump_mem.add_argument('filename', help='Name of binary dump') - - parser_read_mem = subparsers.add_parser( - 'read_mem', - help='Read arbitrary memory location') - parser_read_mem.add_argument('address', help='Address to read', type=arg_auto_int) - - parser_write_mem = subparsers.add_parser( - 'write_mem', - help='Read-modify-write to arbitrary memory location') - parser_write_mem.add_argument('address', help='Address to write', type=arg_auto_int) - parser_write_mem.add_argument('value', help='Value', type=arg_auto_int) - parser_write_mem.add_argument('mask', help='Mask of bits to write', type=arg_auto_int, nargs='?', default='0xFFFFFFFF') - - def add_spi_flash_subparsers(parent, allow_keep, auto_detect): - """ Add common parser arguments for SPI flash properties """ - extra_keep_args = ['keep'] if allow_keep else [] - - if auto_detect and allow_keep: - extra_fs_message = ", detect, or keep" - elif auto_detect: - extra_fs_message = ", or detect" - elif allow_keep: - extra_fs_message = ", or keep" - else: - extra_fs_message = "" - - parent.add_argument('--flash_freq', '-ff', help='SPI Flash frequency', - choices=extra_keep_args + ['40m', '26m', '20m', '80m'], - default=os.environ.get('ESPTOOL_FF', 'keep' if allow_keep else '40m')) - parent.add_argument('--flash_mode', '-fm', help='SPI Flash mode', - choices=extra_keep_args + ['qio', 'qout', 'dio', 'dout'], - default=os.environ.get('ESPTOOL_FM', 'keep' if allow_keep else 'qio')) - parent.add_argument('--flash_size', '-fs', help='SPI Flash size in MegaBytes (1MB, 2MB, 4MB, 8MB, 16M)' - ' plus ESP8266-only (256KB, 512KB, 2MB-c1, 4MB-c1)' + extra_fs_message, - action=FlashSizeAction, auto_detect=auto_detect, - default=os.environ.get('ESPTOOL_FS', 'keep' if allow_keep else '1MB')) - add_spi_connection_arg(parent) - - parser_write_flash = subparsers.add_parser( - 'write_flash', - help='Write a binary blob to flash') - - parser_write_flash.add_argument('addr_filename', metavar='

', help='Address followed by binary filename, separated by space', - action=AddrFilenamePairAction) - parser_write_flash.add_argument('--erase-all', '-e', - help='Erase all regions of flash (not just write areas) before programming', - action="store_true") - - add_spi_flash_subparsers(parser_write_flash, allow_keep=True, auto_detect=True) - parser_write_flash.add_argument('--no-progress', '-p', help='Suppress progress output', action="store_true") - parser_write_flash.add_argument('--verify', help='Verify just-written data on flash ' - '(mostly superfluous, data is read back during flashing)', action='store_true') - parser_write_flash.add_argument('--encrypt', help='Apply flash encryption when writing data (required correct efuse settings)', - action='store_true') - # In order to not break backward compatibility, our list of encrypted files to flash is a new parameter - parser_write_flash.add_argument('--encrypt-files', metavar='
', - help='Files to be encrypted on the flash. Address followed by binary filename, separated by space.', - action=AddrFilenamePairAction) - parser_write_flash.add_argument('--ignore-flash-encryption-efuse-setting', help='Ignore flash encryption efuse settings ', - action='store_true') - - compress_args = parser_write_flash.add_mutually_exclusive_group(required=False) - compress_args.add_argument('--compress', '-z', help='Compress data in transfer (default unless --no-stub is specified)', - action="store_true", default=None) - compress_args.add_argument('--no-compress', '-u', help='Disable data compression during transfer (default if --no-stub is specified)', - action="store_true") - - subparsers.add_parser( - 'run', - help='Run application code in flash') - - parser_image_info = subparsers.add_parser( - 'image_info', - help='Dump headers from an application image') - parser_image_info.add_argument('filename', help='Image file to parse') - - parser_make_image = subparsers.add_parser( - 'make_image', - help='Create an application image from binary files') - parser_make_image.add_argument('output', help='Output image file') - parser_make_image.add_argument('--segfile', '-f', action='append', help='Segment input file') - parser_make_image.add_argument('--segaddr', '-a', action='append', help='Segment base address', type=arg_auto_int) - parser_make_image.add_argument('--entrypoint', '-e', help='Address of entry point', type=arg_auto_int, default=0) - - parser_elf2image = subparsers.add_parser( - 'elf2image', - help='Create an application image from ELF file') - parser_elf2image.add_argument('input', help='Input ELF file') - parser_elf2image.add_argument('--output', '-o', help='Output filename prefix (for version 1 image), or filename (for version 2 single image)', type=str) - parser_elf2image.add_argument('--version', '-e', help='Output image version', choices=['1', '2', '3'], default='1') - parser_elf2image.add_argument('--min-rev', '-r', help='Minimum chip revision', choices=['0', '1', '2', '3'], default='0') - parser_elf2image.add_argument('--secure-pad', action='store_true', - help='Pad image so once signed it will end on a 64KB boundary. For Secure Boot v1 images only.') - parser_elf2image.add_argument('--secure-pad-v2', action='store_true', - help='Pad image to 64KB, so once signed its signature sector will start at the next 64K block. ' - 'For Secure Boot v2 images only.') - parser_elf2image.add_argument('--elf-sha256-offset', help='If set, insert SHA256 hash (32 bytes) of the input ELF file at specified offset in the binary.', - type=arg_auto_int, default=None) - parser_elf2image.add_argument('--use_segments', help='If set, ELF segments will be used instead of ELF sections to genereate the image.', - action='store_true') - - add_spi_flash_subparsers(parser_elf2image, allow_keep=False, auto_detect=False) - - subparsers.add_parser( - 'read_mac', - help='Read MAC address from OTP ROM') - - subparsers.add_parser( - 'chip_id', - help='Read Chip ID from OTP ROM') - - parser_flash_id = subparsers.add_parser( - 'flash_id', - help='Read SPI flash manufacturer and device ID') - add_spi_connection_arg(parser_flash_id) - - parser_read_status = subparsers.add_parser( - 'read_flash_status', - help='Read SPI flash status register') - - add_spi_connection_arg(parser_read_status) - parser_read_status.add_argument('--bytes', help='Number of bytes to read (1-3)', type=int, choices=[1, 2, 3], default=2) - - parser_write_status = subparsers.add_parser( - 'write_flash_status', - help='Write SPI flash status register') - - add_spi_connection_arg(parser_write_status) - parser_write_status.add_argument('--non-volatile', help='Write non-volatile bits (use with caution)', action='store_true') - parser_write_status.add_argument('--bytes', help='Number of status bytes to write (1-3)', type=int, choices=[1, 2, 3], default=2) - parser_write_status.add_argument('value', help='New value', type=arg_auto_int) - - parser_read_flash = subparsers.add_parser( - 'read_flash', - help='Read SPI flash content') - add_spi_connection_arg(parser_read_flash) - parser_read_flash.add_argument('address', help='Start address', type=arg_auto_int) - parser_read_flash.add_argument('size', help='Size of region to dump', type=arg_auto_int) - parser_read_flash.add_argument('filename', help='Name of binary dump') - parser_read_flash.add_argument('--no-progress', '-p', help='Suppress progress output', action="store_true") - - parser_verify_flash = subparsers.add_parser( - 'verify_flash', - help='Verify a binary blob against flash') - parser_verify_flash.add_argument('addr_filename', help='Address and binary file to verify there, separated by space', - action=AddrFilenamePairAction) - parser_verify_flash.add_argument('--diff', '-d', help='Show differences', - choices=['no', 'yes'], default='no') - add_spi_flash_subparsers(parser_verify_flash, allow_keep=True, auto_detect=True) - - parser_erase_flash = subparsers.add_parser( - 'erase_flash', - help='Perform Chip Erase on SPI flash') - add_spi_connection_arg(parser_erase_flash) - - parser_erase_region = subparsers.add_parser( - 'erase_region', - help='Erase a region of the flash') - add_spi_connection_arg(parser_erase_region) - parser_erase_region.add_argument('address', help='Start address (must be multiple of 4096)', type=arg_auto_int) - parser_erase_region.add_argument('size', help='Size of region to erase (must be multiple of 4096)', type=arg_auto_int) - - parser_merge_bin = subparsers.add_parser( - 'merge_bin', - help='Merge multiple raw binary files into a single file for later flashing') - - parser_merge_bin.add_argument('--output', '-o', help='Output filename', type=str, required=True) - parser_merge_bin.add_argument('--format', '-f', help='Format of the output file', choices='raw', default='raw') # for future expansion - add_spi_flash_subparsers(parser_merge_bin, allow_keep=True, auto_detect=False) - - parser_merge_bin.add_argument('--target-offset', '-t', help='Target offset where the output file will be flashed', - type=arg_auto_int, default=0) - parser_merge_bin.add_argument('--fill-flash-size', help='If set, the final binary file will be padded with FF ' - 'bytes up to this flash size.', action=FlashSizeAction) - parser_merge_bin.add_argument('addr_filename', metavar='
', - help='Address followed by binary filename, separated by space', - action=AddrFilenamePairAction) - - subparsers.add_parser( - 'version', help='Print esptool version') - - subparsers.add_parser('get_security_info', help='Get some security-related data') - - # internal sanity check - every operation matches a module function of the same name - for operation in subparsers.choices.keys(): - assert operation in globals(), "%s should be a module function" % operation - - argv = expand_file_arguments(argv or sys.argv[1:]) - - args = parser.parse_args(argv) - print('esptool.py v%s' % __version__) - - # operation function can take 1 arg (args), 2 args (esp, arg) - # or be a member function of the ESPLoader class. - - if args.operation is None: - parser.print_help() - sys.exit(1) - - # Forbid the usage of both --encrypt, which means encrypt all the given files, - # and --encrypt-files, which represents the list of files to encrypt. - # The reason is that allowing both at the same time increases the chances of - # having contradictory lists (e.g. one file not available in one of list). - if args.operation == "write_flash" and args.encrypt and args.encrypt_files is not None: - raise FatalError("Options --encrypt and --encrypt-files must not be specified at the same time.") - - operation_func = globals()[args.operation] - - if PYTHON2: - # This function is depreciated in Python3 - operation_args = inspect.getargspec(operation_func).args - else: - operation_args = inspect.getfullargspec(operation_func).args - - if operation_args[0] == 'esp': # operation function takes an ESPLoader connection object - if args.before != "no_reset_no_sync": - initial_baud = min(ESPLoader.ESP_ROM_BAUD, args.baud) # don't sync faster than the default baud rate - else: - initial_baud = args.baud - - if args.port is None: - ser_list = get_port_list() - print("Found %d serial ports" % len(ser_list)) - else: - ser_list = [args.port] - esp = esp or get_default_connected_device(ser_list, port=args.port, connect_attempts=args.connect_attempts, - initial_baud=initial_baud, chip=args.chip, trace=args.trace, - before=args.before) - - if esp is None: - raise FatalError("Could not connect to an Espressif device on any of the %d available serial ports." % len(ser_list)) - - if esp.secure_download_mode: - print("Chip is %s in Secure Download Mode" % esp.CHIP_NAME) - else: - print("Chip is %s" % (esp.get_chip_description())) - print("Features: %s" % ", ".join(esp.get_chip_features())) - print("Crystal is %dMHz" % esp.get_crystal_freq()) - read_mac(esp, args) - - if not args.no_stub: - if esp.secure_download_mode: - print("WARNING: Stub loader is not supported in Secure Download Mode, setting --no-stub") - args.no_stub = True - elif not esp.IS_STUB and esp.stub_is_disabled: - print("WARNING: Stub loader has been disabled for compatibility, setting --no-stub") - args.no_stub = True - else: - esp = esp.run_stub() - - if args.override_vddsdio: - esp.override_vddsdio(args.override_vddsdio) - - if args.baud > initial_baud: - try: - esp.change_baud(args.baud) - except NotImplementedInROMError: - print("WARNING: ROM doesn't support changing baud rate. Keeping initial baud rate %d" % initial_baud) - - # override common SPI flash parameter stuff if configured to do so - if hasattr(args, "spi_connection") and args.spi_connection is not None: - if esp.CHIP_NAME != "ESP32": - raise FatalError("Chip %s does not support --spi-connection option." % esp.CHIP_NAME) - print("Configuring SPI flash mode...") - esp.flash_spi_attach(args.spi_connection) - elif args.no_stub: - print("Enabling default SPI flash mode...") - # ROM loader doesn't enable flash unless we explicitly do it - esp.flash_spi_attach(0) - - # Check flash chip connection - try: - flash_id = esp.flash_id() - if flash_id in (0xffffff, 0x000000): - print('WARNING: Failed to communicate with the flash chip, read/write operations will fail. ' - 'Try checking the chip connections or removing any other hardware connected to IOs.') - except Exception as e: - esp.trace('Unable to verify flash chip connection ({}).'.format(e)) - - if hasattr(args, "flash_size"): - print("Configuring flash size...") - detect_flash_size(esp, args) - if args.flash_size != 'keep': # TODO: should set this even with 'keep' - esp.flash_set_parameters(flash_size_bytes(args.flash_size)) - - try: - operation_func(esp, args) - finally: - try: # Clean up AddrFilenamePairAction files - for address, argfile in args.addr_filename: - argfile.close() - except AttributeError: - pass - - # Handle post-operation behaviour (reset or other) - if operation_func == load_ram: - # the ESP is now running the loaded image, so let it run - print('Exiting immediately.') - elif args.after == 'hard_reset': - esp.hard_reset() - elif args.after == 'soft_reset': - print('Soft resetting...') - # flash_finish will trigger a soft reset - esp.soft_reset(False) - elif args.after == 'no_reset_stub': - print('Staying in flasher stub.') - else: # args.after == 'no_reset' - print('Staying in bootloader.') - if esp.IS_STUB: - esp.soft_reset(True) # exit stub back to ROM loader - - if not external_esp: - esp._port.close() - - else: - operation_func(args) - - -def get_port_list(): - if list_ports is None: - raise FatalError("Listing all serial ports is currently not available. Please try to specify the port when " - "running esptool.py or update the pyserial package to the latest version") - return sorted(ports.device for ports in list_ports.comports()) - - -def expand_file_arguments(argv): - """ Any argument starting with "@" gets replaced with all values read from a text file. - Text file arguments can be split by newline or by space. - Values are added "as-is", as if they were specified in this order on the command line. - """ - new_args = [] - expanded = False - for arg in argv: - if arg.startswith("@"): - expanded = True - with open(arg[1:], "r") as f: - for line in f.readlines(): - new_args += shlex.split(line) - else: - new_args.append(arg) - if expanded: - print("esptool.py %s" % (" ".join(new_args[1:]))) - return new_args - return argv - - -class FlashSizeAction(argparse.Action): - """ Custom flash size parser class to support backwards compatibility with megabit size arguments. - - (At next major relase, remove deprecated sizes and this can become a 'normal' choices= argument again.) - """ - def __init__(self, option_strings, dest, nargs=1, auto_detect=False, **kwargs): - super(FlashSizeAction, self).__init__(option_strings, dest, nargs, **kwargs) - self._auto_detect = auto_detect - - def __call__(self, parser, namespace, values, option_string=None): - try: - value = { - '2m': '256KB', - '4m': '512KB', - '8m': '1MB', - '16m': '2MB', - '32m': '4MB', - '16m-c1': '2MB-c1', - '32m-c1': '4MB-c1', - }[values[0]] - print("WARNING: Flash size arguments in megabits like '%s' are deprecated." % (values[0])) - print("Please use the equivalent size '%s'." % (value)) - print("Megabit arguments may be removed in a future release.") - except KeyError: - value = values[0] - - known_sizes = dict(ESP8266ROM.FLASH_SIZES) - known_sizes.update(ESP32ROM.FLASH_SIZES) - if self._auto_detect: - known_sizes['detect'] = 'detect' - known_sizes['keep'] = 'keep' - if value not in known_sizes: - raise argparse.ArgumentError(self, '%s is not a known flash size. Known sizes: %s' % (value, ", ".join(known_sizes.keys()))) - setattr(namespace, self.dest, value) - - -class SpiConnectionAction(argparse.Action): - """ Custom action to parse 'spi connection' override. Values are SPI, HSPI, or a sequence of 5 pin numbers separated by commas. - """ - def __call__(self, parser, namespace, value, option_string=None): - if value.upper() == "SPI": - value = 0 - elif value.upper() == "HSPI": - value = 1 - elif "," in value: - values = value.split(",") - if len(values) != 5: - raise argparse.ArgumentError(self, '%s is not a valid list of comma-separate pin numbers. Must be 5 numbers - CLK,Q,D,HD,CS.' % value) - try: - values = tuple(int(v, 0) for v in values) - except ValueError: - raise argparse.ArgumentError(self, '%s is not a valid argument. All pins must be numeric values' % values) - if any([v for v in values if v > 33 or v < 0]): - raise argparse.ArgumentError(self, 'Pin numbers must be in the range 0-33.') - # encode the pin numbers as a 32-bit integer with packed 6-bit values, the same way ESP32 ROM takes them - # TODO: make this less ESP32 ROM specific somehow... - clk, q, d, hd, cs = values - value = (hd << 24) | (cs << 18) | (d << 12) | (q << 6) | clk - else: - raise argparse.ArgumentError(self, '%s is not a valid spi-connection value. ' - 'Values are SPI, HSPI, or a sequence of 5 pin numbers CLK,Q,D,HD,CS).' % value) - setattr(namespace, self.dest, value) - - -class AddrFilenamePairAction(argparse.Action): - """ Custom parser class for the address/filename pairs passed as arguments """ - def __init__(self, option_strings, dest, nargs='+', **kwargs): - super(AddrFilenamePairAction, self).__init__(option_strings, dest, nargs, **kwargs) - - def __call__(self, parser, namespace, values, option_string=None): - # validate pair arguments - pairs = [] - for i in range(0, len(values), 2): - try: - address = int(values[i], 0) - except ValueError: - raise argparse.ArgumentError(self, 'Address "%s" must be a number' % values[i]) - try: - argfile = open(values[i + 1], 'rb') - except IOError as e: - raise argparse.ArgumentError(self, e) - except IndexError: - raise argparse.ArgumentError(self, 'Must be pairs of an address and the binary filename to write there') - pairs.append((address, argfile)) - - # Sort the addresses and check for overlapping - end = 0 - for address, argfile in sorted(pairs, key=lambda x: x[0]): - argfile.seek(0, 2) # seek to end - size = argfile.tell() - argfile.seek(0) - sector_start = address & ~(ESPLoader.FLASH_SECTOR_SIZE - 1) - sector_end = ((address + size + ESPLoader.FLASH_SECTOR_SIZE - 1) & ~(ESPLoader.FLASH_SECTOR_SIZE - 1)) - 1 - if sector_start < end: - message = 'Detected overlap at address: 0x%x for file: %s' % (address, argfile.name) - raise argparse.ArgumentError(self, message) - end = sector_end - setattr(namespace, self.dest, pairs) - - -# Binary stub code (see flasher_stub dir for source & details) -ESP8266ROM.STUB_CODE = eval(zlib.decompress(base64.b64decode(b""" -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\ -5dwuzr3/OyU1/H+n+L8kk1ilxnz4f3giyVw=\ -"""))) -ESP32ROM.STUB_CODE = eval(zlib.decompress(base64.b64decode(b""" -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\ -"""))) -ESP32S2ROM.STUB_CODE = eval(zlib.decompress(base64.b64decode(b""" -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\ -+rqe/Hebvj3Y4S8jQkWaGpP//j8geRE3\ -"""))) -ESP32S3BETA2ROM.STUB_CODE = eval(zlib.decompress(base64.b64decode(b""" -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\ -"""))) -ESP32S3ROM.STUB_CODE = eval(zlib.decompress(base64.b64decode(b""" -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\ -"""))) -ESP32C3ROM.STUB_CODE = eval(zlib.decompress(base64.b64decode(b""" -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\ -xp4M93cxNksKk1z9D2WAtrU=\ -"""))) -ESP32C6BETAROM.STUB_CODE = eval(zlib.decompress(base64.b64decode(b""" -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\ -"""))) -ESP32H2ROM.STUB_CODE = eval(zlib.decompress(base64.b64decode(b""" -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\ -"""))) -ESP8684ROM.STUB_CODE = eval(zlib.decompress(base64.b64decode(b""" -eNrFWmtXG8kR/SssYLPrPE635tl2jCVWQgiMY++xl9hHxDvTM0O82SUBCxsn0X9P33poRgLJm0/5IJBmerqrq27devT8e29W3872Hm+Ve9NbY6e3NnzKLHzHx/x0PL31efgWTW8LN73N6erDcLF4Ef6kP4Q/cbiU\ -hv/1dvjj5emYnp7eNtXbDHMUz8If8zzMH83CVdxuptfT29qEX71+OdwJC+S7LEPZm0xvq97wYLIdnjVJERbuhU8Ym+f98Cea7k0vsQLmuwkzJDQfjXLZPFwNC9RBZuvClybc8UH4ssmmeyTXf07CuCqML/nZpsmy\ -NTd06QGrhnYaPlWV0U55Pgifis56C+WFT1CdCx8f4f/3c5ElP8Me+xB+1K5jwv/cDVgF9y/qns1laV6h35FBV2p/W/89DMCzh/XuTg2Lxdkw/C2DfVzE8waLBhs5f6Irw97hoSI87JvzzLI6bcR25uE2PwqLVOMw\ -tx0GFFThyVrVEA9xD9bjVcqYTWTMKdZNnkHYYVdxlud3WJ+uhSmzsI065QEEspQxgd/OMZb0Ok+iunjJJsCS+F9mDxcqOyCjDILczvIUJhljKLZTAE6QjWGORfJa5slJp9thZ643XFKtqEa34qHLQfhrA6jqhK/m\ -ltWTYzGH+e038AAgyTAWMKxxZ/sY1E4dpPPsh6rd3B3iSlBvJVea6owND21A3zaTKW0rW2ngf97KZBFDDfI1NSYdq9N0gBEewT5S8TgjmLPtEN1xY9vVYY+KViPBaKmwmwpL+btTQLBfeeEyGxE2xQ8wIk9GgBsD\ -89UzP5GdpRg97iAZu/KqoqjjoEJnFUbjR4dBDjBkwOOtSE66M7iT4k5vBwaXqfMUANnhRQrdfndyZy9acWj5uF0Eugy6bpQ2MCcxpdpI5S8wi6LRrGxGIU87X68D+i1EYmIsvXAnoS/ekiCw0h/YLC/1Dd8JmGQj\ -GsEBjLhKLzJl1Z2yFoErQSaHG4oa93IQhRl8HWuEoWj0gvfQpR8ADmwhoCwA4HCrdITZoLHvhnIHocQ9ZFe20VvGOMURf+TfhGmM/hz699grTIM48pSY96j/ULRYs1s60S7oADRLPm1kv34lPGHDPtFN9slTpvTs\ -tM/6CtNNSeYpGDPibbisP2QCokgpoVHCZDc6Xic1+40G8k5cvnkiYdnXz37R0InHhyz4/RsJYtWlsJRNmB7K3pi3QLjNtvbZHrV90g09YwVm/57F4Pp5I8QKl++N1qsSnFwD5yG0MTlqziDU2FHBQBMY9QIicyaL\ -HSZvRWHHP2YsHsDqu7xGrHkxZw5AaoPg4eUOoJFXjxl1wBX+l5apPcfgcodvMC8OEEgcUx0r4yVT5b2RuQ36y7EEkDISRno6kZL5Og3CB6rOaE+j23WtsAo/dyGTQCN34gWRd97GiY1LmnZJ5n9ot8za1EMSC97q\ -I3Fa8esykbAP6VwsYX9dxDXIpIyMooAQjxDWiGpurkAcdv4Rtz5g5eShGDNsoapZO5VkLVUhEmVzAKPgzECIacbKyDUzEGEheFPss6BMMtsMTuWi9USxvTq5SX5uVyASKMYDZjPOTy468ZY+ENSJplmUNSI6EXH5\ -8c5qMGmyvZnbIIRtZJC3I3yBq+GbSXyrs7LoP4K1iuH0MlBVk75t3kHH7yYLhwWdOv8Rg9R2H46ZYmGLPHmxSZafFKIrJFtXS3Ns3M8WJ2aINAgKTLq7gw/MX4xfyJW+YW5VRGumc6/zIIHw9upq/vFHEME7xJm/\ -AlKlUAzFxm0wYdBAFR1jIwhsDSqqCkVC9DNzRS0QLcSmqtwlOXp/5JqlhFLLlAkIBOF7m/YNuCQXHpc+84x5UimYcq3jNuP9t4Almv9r/ZyERf+YGZUA6O8ODgtf8yPEu5oK2cm+FGzJap6VrfgQZRFWcsEKgQjr\ -NHFINU3pr9i/iEYQY4ok0yAPiCYDUlX2gmFVfB1WfUYjpnColZ3znz4wUkplVIeqoOmJ0Is7vxuwxXMSMPosRTFdWRLgx6/nIH7ZPU45+/qt2kIA82yEJkdkmyDmhUkKjHF6p/m6HGVvLtkUPCOJ+Udd8JO12/d/\ -buGMIFP3nkr5vV5Wukgw+IHz8EvOwknWBHSqZcgiZ0XppjmrtWO+CI3WTtoS/292pYQ1fpO0/Hrz5Orpqr9vYETcXKHhl49eA4avp5dvIf7kZ/BNcXx8gpsnj57j5vPp5Sk4+vy0024ps7PB5O1VawDkfNhrIPt9\ -cRCh2QIhNJa0v8eEigwAY7yEWC8hlu4VLDuQTvljj3NclCRgLWDDm0sesElZRakJX/EMNLZU/WjmpFkMrpXAdC0FiY0fwBh29DdOC3PWc8K4WVRky9XUNxf7BLgtSYK1CkvyvnbP8M3Yw2VJrOadidpy0RyzyYim\ -kzC4yZe4WcUNq+l0vAqN7KSjA9piRknjlKVfi5tGS2jK4PP8PZQxwrVjmvAKLl9w1LBRwl++JmtRAcIX3I6w2XI6i0w2T5pBo+prmz+UTIQNzLA0/ubV37Pnaox1WyhUvwVjTCx/qc1CYuNSQw7jcdEfyOSZnBkC\ -QZiux+31UAdxYXspZS3xn2Wfo5ifaWNrOsNQqpnkfhEtj8enSk+pnVNKXZK+op9Of36Hn67uNHtokbjtNPhsV0pbqdMrJ7WVpWeT9lnnkYz57/fJCa+foK8w+pbNUIAoTHfyvDu5o3zPZOc89wLTaB+giGtUxP+p\ -JnF3apJ1o83KaMqD6w2x11Gp7bjtWGbaVlNNYLPZr3zXO7UUW+aG0bhszkR7bD57BDTAWaA3y823mhTnS74RoHLdjkfDzP8id+LpjO7kqlyEVA0i1HxoNGBTj/xDqj8RO5tX6amVQGbkmTvIe9oi6sD/CrqIFQ1g\ -7jr7AWLTTwLH6+m1xEEnnNio+ZP7sGCFwDgMCPASSSwqSTmIU2NpGNCPQ1mfWkKEzENZNeGLoD6PkGySkefeAJFrLcit8qOdXWXInW2OEFQUSgFeJGqLkFqD4htROqJldShaqdD8Lawu3sjiabct08P6layfqqvi\ -2lCpaQOsoS0aVFV/gubddOZaX6PTiQfpXMwN+xs7lEjdwBNJUi8FQlGppD2RFFolayKaNNKerjyCeP4cMfgIljwCuw2BtOGGCiCvUHU7sDl3VqQItxT/TlVnDC5fKYgHh8JSK+iGMRbySkelof6lIMxICkFG7EJ/\ -0TdOxCnZlmIdE08UonKsgKooj8YcHbyQRMb91AWbO+kgUPcg291hMJmybQIXMan/AW+fm9Vb1ORGF6eiwOmZwhdIihYnDDSuEBHT9pZdtEpcyXcB1YKMZnwHVsnokfrR5EYcheaQuQkEB3qxv5jVy6z5ihLSTprh\ -0SLR4lT2uaCATlLUUX5ux+0mCJ1oYcLstTgiR4jXXVYYatCedCME36sEdr07d2aS6a8ELcrGBWZ13EpoVUJhdJMMR9LzFYhRS67NBeZRrJCeSE804mwklw17Qy3WC15Q1eEoAbJUezzt/QF5ywAdI1fNuX3XVHMt\ -Bao+X4IZyN8LijXSArxfMHz+BTRVl4zLWjLNMvr8gPmUypNs8KFdxl9KtWXmX9qrX0CJX1nMmFsJbe6Y12u0BbfpMW8+aUQkA+wOmNahR6Jo2KtMFnw9lJgk2KYphXxGj0HMnUfb0XE72vkjL7FHAqv3R0JedZWz\ -jThH1KcLfrquF08rPdViXJ1C2ui55Cc+MVzXzvTsI5bmiZzLlZnUhM0izzoU57KSu2fS6q2lxVgpkycjPijnmDeWKySwxBOqebGvXOPI/Yb7+FQP3z4LY0hljC4VBGD/OB93onLcwpvEaapzPPOJZaqao+GmFd/T\ -scdfgOq4P4dDykmjHtY4I1zklcYbTpryRhPDXLw9VN8Ddt1KDxGtNGDoIDh6cExNcWnv8skjkv1mKTD8JD02K20JHPwT5RKv13rGTNz7uasjabtXxFnf6jNSkgWeEzdqqGBTc2vHuXYtR1LU0kPMHGlHxQnIrjT3\ -pcgpyxXQWPNCE03OrFgvhzw9RfplfIhOKbWNdluRrZxiLVoNxIVh/UtJhOg/QrhmyjheKcslRW7hGW1ydQMvz/bqnjvO6DN20q1KrKc8l8LyaCUs44xyfYmyhFF7t2Rxwv4m0zciJvdE8+CA1+2hv4/8EK1M68/4\ -NQQtMf9JWmIj1a4DDS/+m7aNGt7qW5aIH5csQAszr9fbICwn+JiHdhnfTZYREeNzDuRrAtW79uUa3uGAUq2PVBtsi9Yjqgtm3N9t47khTrcSV1hPM4rzP7Ynmao/DiD+JSH0UrJjwx7n/Q3n7zR3onPnaduuUJut\ -o4/avCH/XT7eFP03rivLRAJwIYfnUPryCNUFdxn3BlR0f7dJgK3XnKiUocCqOx2R5KqjXzWQGW4Kz6OlF6Dg9Ser75VIkUPqORNaswTmG0ZyKe8QKbJLLpj3hEuorRLJOWjW9vPuwcdhu5nc7K/d/kEAb+nvz/7V\ -0qh1csRNvH7DF//BE+VW37f4pOemipqUnXpDM0zei2n2uce3wBtFVLyMFSa8XJwGXpOd9IghblcwyZEc4zecj10fHaAz+FjagrKJms5Gtse9I3k3hPETIDrlxEHzV+3tWP1EQrbI/+/XYh+xoXdGu9+TnAOQ8Bok\ -EMIp66tkw9Tt7Z0hGFAeQPWTHmMkcg5sOq81iFBOamV9I4Be8NDAhThUp9JU130XdGwufQynzlhxpkHxgwiCQqI25zPuHeniEjiWXZJexuhJia28pk+azSmKu+tra+CZrJ+mMPmcEUBJW00QofhTfEWA3KS/yTkw\ -s/TbXPxF8Jy+fIieeIpaJkVXPJ006Iqnx4dw9/TkIQrq9Dluoy/eO687fXGiAbP3+y16ffL9x1lxjZcorcmy2No8NuFOfTm7/rK4GEW9PFysilmhb1sCVsGf9uRydxbTc4nL0vl/AZcQ2NA=\ -"""))) +if os.name != "nt": + # Linux/macOS: remove current script directory to avoid importing this file + # as a module; we want to import the installed esptool module instead + with contextlib.suppress(ValueError): + if sys.path[0].endswith("/bin"): + sys.path.pop(0) + sys.path.remove(os.path.dirname(sys.executable)) -def _main(): - try: - main() - except FatalError as e: - print('\nA fatal error occurred: %s' % e) - sys.exit(2) + # Linux/macOS: delete imported module entry to force Python to load + # the module from scratch; this enables importing esptool module in + # other Python scripts + with contextlib.suppress(KeyError): + del sys.modules["esptool"] +import esptool -if __name__ == '__main__': - _main() +if __name__ == "__main__": + esptool._main() \ No newline at end of file From 1bf8ec11f2449058f46103e3903ba4380c3d59e0 Mon Sep 17 00:00:00 2001 From: John Date: Sun, 10 Jul 2022 01:25:47 -0400 Subject: [PATCH 3/7] Update requirements for new esptool --- .gitignore | 2 ++ build.sh | 2 ++ esptool.py | 34 ---------------------------------- requirements.txt | 8 +++++--- 4 files changed, 9 insertions(+), 37 deletions(-) delete mode 100755 esptool.py diff --git a/.gitignore b/.gitignore index b5a7601..0a76f09 100644 --- a/.gitignore +++ b/.gitignore @@ -113,3 +113,5 @@ staple.sh # Exclude the pyinstaller directory (if it's here) pyinstaller/ +dist-pkg/ +/brewflasher.pkg diff --git a/build.sh b/build.sh index de7e4e8..77e05ef 100755 --- a/build.sh +++ b/build.sh @@ -3,6 +3,8 @@ #VERSION=1.3 #NAME=BrewFlasher +./venv/bin/activate +# NOTE -- YOU NEED TO RUN THE BELOW COMMAND MANUALLY! pyinstaller --log-level=INFO \ --noconfirm \ build-on-mac-m1.spec diff --git a/esptool.py b/esptool.py deleted file mode 100755 index 395075c..0000000 --- a/esptool.py +++ /dev/null @@ -1,34 +0,0 @@ -#!/usr/bin/env python -# -# SPDX-FileCopyrightText: 2014-2022 Fredrik Ahlberg, Angus Gratton, -# Espressif Systems (Shanghai) CO LTD, other contributors as noted. -# -# SPDX-License-Identifier: GPL-2.0-or-later - -# This executable script is a thin wrapper around the main functionality -# in the esptool Python package - -# When updating this script, please also update espefuse.py and espsecure.py - -import contextlib -import os -import sys - -if os.name != "nt": - # Linux/macOS: remove current script directory to avoid importing this file - # as a module; we want to import the installed esptool module instead - with contextlib.suppress(ValueError): - if sys.path[0].endswith("/bin"): - sys.path.pop(0) - sys.path.remove(os.path.dirname(sys.executable)) - - # Linux/macOS: delete imported module entry to force Python to load - # the module from scratch; this enables importing esptool module in - # other Python scripts - with contextlib.suppress(KeyError): - del sys.modules["esptool"] - -import esptool - -if __name__ == "__main__": - esptool._main() \ No newline at end of file diff --git a/requirements.txt b/requirements.txt index 963859d..bfb8995 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,6 +1,8 @@ -esptool==4.1 +# esptool==4.1 +# We need to use my version of esptool, as the "esptool.py" utility file creates issues with PyInstaller +git+https://github.com/thorrak/esptool.git@v41_noutil wxPython # Previously PyInstaller 3.4 was used - this has security vulnerabilities per GitHub PyInstaller==5.1 -requests==2.28.0 -pyserial +requests==2.28.1 +pyserial==3.5 From 64b50e190bef046ed075c275f0f0625919af3406 Mon Sep 17 00:00:00 2001 From: Thorrak Date: Sun, 10 Jul 2022 01:29:09 -0400 Subject: [PATCH 4/7] Update to latest pyinstaller --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index bfb8995..86374f0 100644 --- a/requirements.txt +++ b/requirements.txt @@ -3,6 +3,6 @@ git+https://github.com/thorrak/esptool.git@v41_noutil wxPython # Previously PyInstaller 3.4 was used - this has security vulnerabilities per GitHub -PyInstaller==5.1 +PyInstaller==5.2 requests==2.28.1 pyserial==3.5 From 936b1e2ad4410833ae04401fa095c890700eb9c8 Mon Sep 17 00:00:00 2001 From: John Date: Sun, 10 Jul 2022 09:46:28 -0400 Subject: [PATCH 5/7] Update error messages --- .gitignore | 2 +- Main.py | 4 ++-- brewflasher_com_integration.py | 12 +++++++++--- build.sh | 4 ++-- 4 files changed, 14 insertions(+), 8 deletions(-) diff --git a/.gitignore b/.gitignore index 0a76f09..2863327 100644 --- a/.gitignore +++ b/.gitignore @@ -114,4 +114,4 @@ staple.sh pyinstaller/ dist-pkg/ -/brewflasher.pkg +/*.pkg diff --git a/Main.py b/Main.py index 39ea4e3..21a4a3e 100644 --- a/Main.py +++ b/Main.py @@ -231,8 +231,8 @@ def run(self): print("Firmware flashing FAILED. esptool.py raised an error.\n") print("Try flashing again, or try flashing with a slower speed.\n") if self._config.device_family_1200_bps: - # TODO - Add instructions here - print("\nAlternatively, you may need to manually set the device into 'flash' mode.") + print("\nAlternatively, you may need to manually set the device into 'flash' mode.\nFor instructions " + "on how to do this, check this website:\nhttp://www.brewflasher.com/manualflash/") return # The last line printed by esptool is "Staying in bootloader." -> some indication that the process is diff --git a/brewflasher_com_integration.py b/brewflasher_com_integration.py index 98060e8..ee2eea3 100644 --- a/brewflasher_com_integration.py +++ b/brewflasher_com_integration.py @@ -203,7 +203,9 @@ def load_projects_from_website(self) -> bool: show=row['show_in_standalone_flasher']) self.Projects[row['id']] = copy.deepcopy(newProject) except: - # TODO - Display an error message + print("\nUnable to load projects from BrewFlasher.com.") + print("Please check your internet connection and try launching BrewFlasher again.\nIf you continue " + "to receive this error, please check that you have the latest version of BrewFlasher.") pass return True @@ -231,7 +233,9 @@ def load_families_from_website(self) -> bool: for this_project in self.Projects: self.Projects[this_project].device_families[new_family.id] = copy.deepcopy(new_family) except: - # TODO - Display an error message + print("\nUnable to load device families from BrewFlasher.com.") + print("Please check your internet connection and try launching BrewFlasher again.\nIf you continue " + "to receive this error, please check that you have the latest version of BrewFlasher.") pass return True @@ -273,7 +277,9 @@ def load_firmware_from_website(self) -> bool: self.Projects[newFirmware.project_id].device_families[newFirmware.family_id].firmware.append( newFirmware) except: - # TODO - Display an error message + print("\nUnable to load firmware list from BrewFlasher.com.") + print("Please check your internet connection and try launching BrewFlasher again.\nIf you continue " + "to receive this error, please check that you have the latest version of BrewFlasher.") pass return True # Firmware table is updated diff --git a/build.sh b/build.sh index 77e05ef..289ac38 100755 --- a/build.sh +++ b/build.sh @@ -3,9 +3,9 @@ #VERSION=1.3 #NAME=BrewFlasher -./venv/bin/activate +source ./venv/bin/activate # NOTE -- YOU NEED TO RUN THE BELOW COMMAND MANUALLY! -pyinstaller --log-level=INFO \ +./venv/bin/pyinstaller --log-level=INFO \ --noconfirm \ build-on-mac-m1.spec From d18d82b1560b763556756b85b8591847ac9e4a02 Mon Sep 17 00:00:00 2001 From: John Date: Sun, 10 Jul 2022 14:17:50 -0400 Subject: [PATCH 6/7] Add 256x256 PNG icon --- README.md | 4 +- images.py | 2267 +++++++++++++++++++++++++++++++++---------- images/icon-256.png | Bin 0 -> 92119 bytes 3 files changed, 1747 insertions(+), 524 deletions(-) create mode 100644 images/icon-256.png diff --git a/README.md b/README.md index 5d07214..19f2b99 100644 --- a/README.md +++ b/README.md @@ -32,6 +32,8 @@ or ESP8266. Those projects include: - iSpindHub - SBL4TILT - GravityMon +- FermWatch +- BrewUNO An up-to-date list of supported firmware can be found at the [BrewFlasher](https://www.brewflasher.com/about/supported_projects/) website. @@ -61,7 +63,7 @@ are likely similar (though the "0" button may be labeled something else, like "b ## Background & Development BrewFlasher is based *heavily* on the [NodeMCU PyFlasher](https://github.com/marcelstoer/nodemcu-pyflasher) project. In -comparison to that project, BrewFlasher adds explicit ESP32 support as well as a workflow to automate selecting and +comparison to that project, BrewFlasher adds explicit ESP32 & ESP32-S2 support as well as a workflow to automate selecting and downloading brewing-related firmware to flash. The firmware selection is taken from a curated list maintained behind-the-scenes on BrewFlasher.com. diff --git a/images.py b/images.py index c5c592b..3bfecc4 100644 --- a/images.py +++ b/images.py @@ -1,49 +1,49 @@ #---------------------------------------------------------------------- -# This file was generated by /Users/jbeeler/PycharmProjects/esp_flasher/encode-bitmaps.py +# This file was generated by /Users/jbeeler/PycharmProjects/brewflasher/encode-bitmaps.py # from wx.lib.embeddedimage import PyEmbeddedImage Exit = PyEmbeddedImage( - "iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0" - "RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAN1SURBVHjaYvz//z8DJQAggFhA" - "xEpGRgaQMX+B+A8DgwYLM1M+r4K8P4+8vMi/P38Y3j18+O7Fs+fbvv7+0w9Uc/kHVG070HKA" - "AGJBNg0omC5jZtynnpfHJeHkzPDmxQuGf6/eMIj+/yP+9MD+xFPrN8Reu3W3Gqi0D2IXAwNA" - "AIEN+A/hpWuEBMwwmj6TgUVEjOHTo0cM9y9dZfj76ycDCysrg4K5FYMUvyAL7+pVnYfOXwJp" - "6wIRAAHECAqDJYyMWpLmpmftN2/mYBEVZ3h38SLD9wcPGP6LioIN/7Z+PQM3UB3vv/8MXB/f" - "MSzdvv3vpecvzfr+/z8HEEBMYFMYGXM0iwrAmu+sXcvw4OxZhqenTjEwAv3P9OsXw+unTxne" - "6Osz3Ll3l+HvyzcMVlLSzMBwqgTpBQggsAG8MuKB4r9eM7zfv5PhHxMzg4qLCwPD0ycMDL9/" - "MzD+/cvw/8kTBgUbGwbB1DSGe1cuMbD8+8EgwMPjCtILEEDgMOCSkhT+t20Nw4v7nxkkNuxm" - "eLNmFYO0sCgDCwcHAwMzM4Pkl68MLzs7GGS6uhmOCwgxcD2+x8DLysID0gsQQGAD/gH99vPL" - "dwZGDjaG/0An/z19goHp/z+Gn9dvgoP4/7dPDD9OnGD4+/0bA5uCAsPPW8DA5eACxxxAAIEN" - "+PDuw/ufirJizE9fMzALCjD8efOO4dHObQx/d29k+PObgeHr268MQta2DCw8fAz/X75k+M/I" - "xPDh1+9vIL0AAQQOg9dPX2x7w8TDwPL2FcOvI8cYxFs7GFjFpRl+PP/K8O3NVwZuIREGpe5u" - "hp83rjF8u3iO4RsnO8OzHz8PgvQCBBA4GrsZGfUUtNXPWiuLsny59YxBch3Qdl4uhq/rNzP8" - "BwYin58PAysbG8MFLy+Gnw9uM5xkYPp38fNX22X//x8DCCAmqD8u3bh6s+Lssy8MrCLcDC/8" - "3Rl+LVvOwG1syMBrYcbwfetmhmsOdgy/795iuMXEwnDh89c2oJ7jIL0AAQR2wQRgXvgKNAfo" - "qRIlJfk2NR42Rj5gEmb5+4/h35+/DJ+/fmd4DUyNN4B+v/DlWwcwcTWzA9PXQqBegACCGwAK" - "ERD+zsBgwszOXirEwe7OzvCP5y/QCx/+/v/26vfv/R///O0GOvkII1AdKxCDDAAIIEZKszNA" - "gAEA1sFjF+2KokIAAAAASUVORK5CYII=") + b'iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0' + b'RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAN1SURBVHjaYvz//z8DJQAggFhA' + b'xEpGRgaQMX+B+A8DgwYLM1M+r4K8P4+8vMi/P38Y3j18+O7Fs+fbvv7+0w9Uc/kHVG070HKA' + b'AGJBNg0omC5jZtynnpfHJeHkzPDmxQuGf6/eMIj+/yP+9MD+xFPrN8Reu3W3Gqi0D2IXAwNA' + b'AIEN+A/hpWuEBMwwmj6TgUVEjOHTo0cM9y9dZfj76ycDCysrg4K5FYMUvyAL7+pVnYfOXwJp' + b'6wIRAAHECAqDJYyMWpLmpmftN2/mYBEVZ3h38SLD9wcPGP6LioIN/7Z+PQM3UB3vv/8MXB/f' + b'MSzdvv3vpecvzfr+/z8HEEBMYFMYGXM0iwrAmu+sXcvw4OxZhqenTjEwAv3P9OsXw+unTxne' + b'6Osz3Ll3l+HvyzcMVlLSzMBwqgTpBQggsAG8MuKB4r9eM7zfv5PhHxMzg4qLCwPD0ycMDL9/' + b'MzD+/cvw/8kTBgUbGwbB1DSGe1cuMbD8+8EgwMPjCtILEEDgMOCSkhT+t20Nw4v7nxkkNuxm' + b'eLNmFYO0sCgDCwcHAwMzM4Pkl68MLzs7GGS6uhmOCwgxcD2+x8DLysID0gsQQGAD/gH99vPL' + b'dwZGDjaG/0An/z19goHp/z+Gn9dvgoP4/7dPDD9OnGD4+/0bA5uCAsPPW8DA5eACxxxAAIEN' + b'+PDuw/ufirJizE9fMzALCjD8efOO4dHObQx/d29k+PObgeHr268MQta2DCw8fAz/X75k+M/I' + b'xPDh1+9vIL0AAQQOg9dPX2x7w8TDwPL2FcOvI8cYxFs7GFjFpRl+PP/K8O3NVwZuIREGpe5u' + b'hp83rjF8u3iO4RsnO8OzHz8PgvQCBBA4GrsZGfUUtNXPWiuLsny59YxBch3Qdl4uhq/rNzP8' + b'BwYin58PAysbG8MFLy+Gnw9uM5xkYPp38fNX22X//x8DCCAmqD8u3bh6s+Lssy8MrCLcDC/8' + b'3Rl+LVvOwG1syMBrYcbwfetmhmsOdgy/795iuMXEwnDh89c2oJ7jIL0AAQR2wQRgXvgKNAfo' + b'qRIlJfk2NR42Rj5gEmb5+4/h35+/DJ+/fmd4DUyNN4B+v/DlWwcwcTWzA9PXQqBegACCGwAK' + b'ERD+zsBgwszOXirEwe7OzvCP5y/QCx/+/v/26vfv/R///O0GOvkII1AdKxCDDAAIIEZKszNA' + b'gAEA1sFjF+2KokIAAAAASUVORK5CYII=') #---------------------------------------------------------------------- Reload = PyEmbeddedImage( - "iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABGdBTUEAALGOfPtRkwAAACBj" - "SFJNAAB6JQAAgIMAAPn/AACA6AAAdTAAAOpgAAA6lwAAF2+XqZnUAAAABmJLR0QA/wD/AP+g" - "vaeTAAAACXBIWXMAAABIAAAASABGyWs+AAAACXZwQWcAAAAYAAAAGAB4TKWmAAACZUlEQVRI" - "x7XVT4iXRRgH8M/8Mv9tUFgRZiBESRIhbFAo8kJ0EYoOwtJBokvTxUtBQnUokIjAoCi6+HiR" - "CNKoU4GHOvQieygMJKRDEUiahC4UtGkb63TY+cnb6/rb3276vQwzzzPf5/9MKqW4kRj8n8s5" - "53U55y03xEDOeRu+xe5ReqtWQDzAC3gTa3D7KP20nBrknDfhMB7vHH+Dj3AWxyPitxUZyDnv" - "xsElPL6MT/BiRJwbaaBN6eamlH9yzmvxPp5bRibPYDIizg96pIM2pak2pSexGiLiEr7H3DIM" - "3IMP/hNBm9It+BDzmGp6oeWcd+BIvdzFRZzGvUOnOtg6qOTrcRxP4ZVmkbxFxDQm8WVPtDMi" - "tmIDPu7JJocpehnb8F1Tyo/XijsizmMX9teCwq1VNlvrdKFzZeOgTelOvFQPfurV5NE2pc09" - "I/MR8TqewAxu68hmMd1RPzXAw1hXD9b3nL4bJ9qUdi0SzbF699ee6K9ObU6swoMd4Y42pYmm" - "lNm6/91C33/RpvQG9jelzHeMnK4F7uK+ur49bNNzHeEdONSmNFH3f9R1gNdwrKZ0UeSc77fQ" - "CCfxFqSveQA/9HTn8DM2d9I3xBk83ZQy3SNPFqb4JjwTEX9S56BN6SimjI857GtKea+ST+Cx" - "6synETHssCuv6V5sd/UQXQur8VCb0tqmlEuYi4jPF1PsTvJGvFMjGfVPzOD5ppTPxvHkqseu" - "Teku7MQm7MEjHfFXeLYp5ey4uRz5XLcpHbAwhH/jVbzblHJ5TG4s/aPN4BT2NKWcXA7xuBFs" - "wS9NKRdXQr6kgeuBfwEbWdzTvan9igAAADV0RVh0Y29tbWVudABSZWZyZXNoIGZyb20gSWNv" - "biBHYWxsZXJ5IGh0dHA6Ly9pY29uZ2FsLmNvbS/RLzdIAAAAJXRFWHRkYXRlOmNyZWF0ZQAy" - "MDExLTA4LTIxVDE0OjAxOjU2LTA2OjAwdNJAnQAAACV0RVh0ZGF0ZTptb2RpZnkAMjAxMS0w" - "OC0yMVQxNDowMTo1Ni0wNjowMAWP+CEAAAAASUVORK5CYII=") + b'iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABGdBTUEAALGOfPtRkwAAACBj' + b'SFJNAAB6JQAAgIMAAPn/AACA6AAAdTAAAOpgAAA6lwAAF2+XqZnUAAAABmJLR0QA/wD/AP+g' + b'vaeTAAAACXBIWXMAAABIAAAASABGyWs+AAAACXZwQWcAAAAYAAAAGAB4TKWmAAACZUlEQVRI' + b'x7XVT4iXRRgH8M/8Mv9tUFgRZiBESRIhbFAo8kJ0EYoOwtJBokvTxUtBQnUokIjAoCi6+HiR' + b'CNKoU4GHOvQieygMJKRDEUiahC4UtGkb63TY+cnb6/rb3276vQwzzzPf5/9MKqW4kRj8n8s5' + b'53U55y03xEDOeRu+xe5ReqtWQDzAC3gTa3D7KP20nBrknDfhMB7vHH+Dj3AWxyPitxUZyDnv' + b'xsElPL6MT/BiRJwbaaBN6eamlH9yzmvxPp5bRibPYDIizg96pIM2pak2pSexGiLiEr7H3DIM' + b'3IMP/hNBm9It+BDzmGp6oeWcd+BIvdzFRZzGvUOnOtg6qOTrcRxP4ZVmkbxFxDQm8WVPtDMi' + b'tmIDPu7JJocpehnb8F1Tyo/XijsizmMX9teCwq1VNlvrdKFzZeOgTelOvFQPfurV5NE2pc09' + b'I/MR8TqewAxu68hmMd1RPzXAw1hXD9b3nL4bJ9qUdi0SzbF699ee6K9ObU6swoMd4Y42pYmm' + b'lNm6/91C33/RpvQG9jelzHeMnK4F7uK+ur49bNNzHeEdONSmNFH3f9R1gNdwrKZ0UeSc77fQ' + b'CCfxFqSveQA/9HTn8DM2d9I3xBk83ZQy3SNPFqb4JjwTEX9S56BN6SimjI857GtKea+ST+Cx' + b'6synETHssCuv6V5sd/UQXQur8VCb0tqmlEuYi4jPF1PsTvJGvFMjGfVPzOD5ppTPxvHkqseu' + b'Teku7MQm7MEjHfFXeLYp5ey4uRz5XLcpHbAwhH/jVbzblHJ5TG4s/aPN4BT2NKWcXA7xuBFs' + b'wS9NKRdXQr6kgeuBfwEbWdzTvan9igAAADV0RVh0Y29tbWVudABSZWZyZXNoIGZyb20gSWNv' + b'biBHYWxsZXJ5IGh0dHA6Ly9pY29uZ2FsLmNvbS/RLzdIAAAAJXRFWHRkYXRlOmNyZWF0ZQAy' + b'MDExLTA4LTIxVDE0OjAxOjU2LTA2OjAwdNJAnQAAACV0RVh0ZGF0ZTptb2RpZnkAMjAxMS0w' + b'OC0yMVQxNDowMTo1Ni0wNjowMAWP+CEAAAAASUVORK5CYII=') #---------------------------------------------------------------------- Splash = PyEmbeddedImage( @@ -3986,489 +3986,1710 @@ #---------------------------------------------------------------------- Icon = PyEmbeddedImage( - b'iVBORw0KGgoAAAANSUhEUgAAAQAAAAEACAYAAABccqhmAAAAAXNSR0IArs4c6QAAACBjSFJN' - b'AAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAACXBIWXMAAAsTAAALEwEA' - b'mpwYAAABWWlUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPHg6eG1wbWV0YSB4bWxuczp4PSJh' - b'ZG9iZTpuczptZXRhLyIgeDp4bXB0az0iWE1QIENvcmUgNS40LjAiPgogICA8cmRmOlJERiB4' - b'bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMi' - b'PgogICAgICA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIgogICAgICAgICAgICB4bWxu' - b'czp0aWZmPSJodHRwOi8vbnMuYWRvYmUuY29tL3RpZmYvMS4wLyI+CiAgICAgICAgIDx0aWZm' - b'Ok9yaWVudGF0aW9uPjE8L3RpZmY6T3JpZW50YXRpb24+CiAgICAgIDwvcmRmOkRlc2NyaXB0' - b'aW9uPgogICA8L3JkZjpSREY+CjwveDp4bXBtZXRhPgpMwidZAABAAElEQVR4Ae2dB4BkRbX3' - b'qzeyu7C7LGzOiZwRlaAuiCQBSavAE5SgPsX0zIp+YhbzM+eICQRFHigmooqSJW7OLJvzLmzq' - b'7/evuqf7Tk93T/dM90z3TJ2Z2zdVnao6dc6pU6fCzbjOghnZPm4/l3HfzexokeQl2UFuq5vk' - b'evHWuf1d1k0h1FjOo7kfwTGUYw+O3o6HjpcRIgUanAJi1J0cW2DZNbDscq6Xc70EPp/L9Sy4' - b'eY77lVsKPytsAtmMe6Pr48a4Xe6azG57Ws9znaWJAs2gqMMp+g2ZXbmCnJ+dDiGO5+lLIM7R' - b'nKcRapBE3INIokMksGv/Iv5ECjQRBSRdvZLDJE38LNWQdStcNvuky2TuQwbu5sm/kZG1nAOo' - b'wSyUG3tXw7Nlq4YohSoR/DszKmqAC7PSa2dycyaFPw49t48njoQ8HCKNlITOAiMfZ/D52/Ai' - b'/kYKNAEFjI8LmzGphN6+sdOVuFw2cRarwLm/ctzsVru/OZOdmdnQLKYbUALVCpR8bUGayzIv' - b'zOdlj0LQL+fqHAo9Nif0u7ygm4IQKYwcihUhUqCbUgC9kOUv4y1iKYdeKIE+XiGYMpA1kHE/' - b'w1L4pfttZo0nhBTBwcSrcdegdgrgmmwvdyeFMeE/L3sMd+8g8xe4vq6/b+V3SSkmVkGWIme8' - b'/vPliz+RAj2YAlIEsn6lDIJ1IGLsdAv4/Q7PvpfrHrwx27eVH01h2wm1UQDpVn9mdjJ66v3k' - b'53LXD9EP5o1aeqWlQy19hEiBSIHWFFALqSNYBr2RFXUAtuM4zLrPuRvd9xGhrKuhNdBBBVDQ' - b'1z8/+3ZE/GoEf0Qi+BJ/ee8R+g4mBaIIkQI9iAJSBMFx3ocugmAnNvZu90F3E45DQbrh9Q+q' - b'/2m/VEoL3SBNhUaSVz/jvk42T/H6a5cXf7X05tevPmcxRqRApIBRIDSkfbEIdmAPOPcJ95vM' - b'J/1LrwSkKNLDiRat7XP7FEBa85yfvQjh/xrG/j5kbjcKYDf3QWO1nX4MESkQKVAJBbJZOQ53' - b'ogL6+mZ1h/szkvYGrIFFvktgjXEluFJhqu+Pywlhjr6Z2c8g6r8gQxL+HYxryq0XhT9F4HgZ' - b'KdBxCtAbyGTUWPdF6GVf76Kb/QqUwb0I/0m5OTZyxFcJ1VkA5oF8fXYPt9n9lEzM9AZJGMns' - b'W2XaMXikQKRA+ygg/8AOmtp++AV20eheiRL4sUflu+apSXdt4K9cY5jwn5Md6ja52xLhl5NC' - b'B8KvPEWIFIgU6AQKqOGW8G/HCtBw+o+wBN7l09WEoSosgcosABP+i7N7o3duQdyPJ+nEw08W' - b'vPBXhqoTiBOTiBToSRTYgQIIfoGd7gM4B6/1hZcSqGDSUNsWgBx+WsBzVnYgQv/blPCrr5/E' - b'j8LfkzgulrWhKNCX9lcdAUeX4LPuguw787nTFPryUF4BqD9hDr/+TE3s516WtPwS/jaRl086' - b'vo0UiBSoEQX65JRAL/dlhuUv8q2/FuK1AWWE2E/e0YwkJvNmv4Tw/w/Crxl9UhrlFYfiRIgU' - b'iBTobArsQDI1UvAcx8kMEf69rclCpQV5RiLkF2QvQ49I+AVSGKXj+CDxJ1IgUqDzKeCd8BL+' - b'7XQF9kBSf4JjcJS34NWNLwHFhdnG+s/PHkm8r3kfn/oZYVpvCVTxcaRApEDXUSBnzIfRgf5u' - b'KnL7bZ8fdeNLjAy0VgDq98vpdzQTfjLuGxgUg9Aq8jSiRaRlcgl1XVljypECkQKlKZBFarcj' - b'tX3dq9wFu4JT8M7ilntrBWBop7DooK87FtEP/kX/PAq/kSeeIwUalgJhmb3mDAK9PoZT8GDf' - b'FZBlXwAtFYD6CppIcH72MBr79wYEsdkvoFm8jRRoBgr08ZZ7PzeYtv+TPsOy7Au6AnkFoBc2' - b'5JdxH8Hrv6d3KGh0MUKkQKRAM1Kgt3feZ9iN6/zs+b4ABV2BvAKwF+dnT6Wbf0Hi9Y/C34zV' - b'HvMcKeANd9/v3+5nA/Rik57Ts/19I5+yAhIFwIyhfOv/7qTN11Rf3sc5/pGbIgWajwI5f512' - b'5dqNEjgGm/4iX44n8p78oABsxtDM7Gm8eoWf5Z/bzCOHqPloEHMcKRApIAH27kDa8quYG9DP' - b'+/kSK0AtfL71z7LBQDD6GfOvfm1xpHWkQKRAo1HAW/B9kjm8L8AWOMvn8JkwTbiX/xKJnpyb' - b'PZzfUxNdgdaILb8nVPyJFGhqCkiO/aKgnUHk3et8cfwXurKZXm4dOkHQ252fTPoJO5L6h/En' - b'UiBSoPkp4BvzjG/cM+5EugGH+jLxGbJevj+gpb4Z98rE36f+Qmz+m7/WYwkiBfIUyOLQ381f' - b'X1yB2aQbMNv6+XvgIcy6IxLzPxkZyMeNV5ECkQJNToEwOzA4AzN09eUEZOQvCHsWs0BbDucW' - b'/DR5YWP2IwUiBYpRIHQDsu5I9wQfGgPCKIDjK70Bgj8guYmnSIFIgW5Fgd6+G9DH7cX5xSpZ' - b'L3ehm8j5UB6Ee3+KP5ECkQLdkALy7e1Ss4+XL1EAO9xBPBju+//6YGeESIFIge5NAU0NkM9v' - b'ZnaAvkZ6SCL2O7mO3v9uVvWq0GJHNytmLE7lFOiVDAdOJspYzfs7IBF7P2WocjwxZCNQIK2x' - b'W1RgctPiWbEMpxCkLmkgInRTCmR8dz/j9qZ8k7WbqLYOkkkQ2/9mq3HqLSeoSK8EuD8/Azh6' - b'J0cfnXnei7NgNxE0FrRT5+TYxvl5Dv5TCLlO4uhxhO5CAb/Z7y6Yojdrfib1oZL3S0yCOP7f' - b'IHUsufPCWJAfmWt9eSkh709t7cEhAVfFSaCfR7LX6dAGrpLy9GHjOwosjZA6BrBPzGju+3MI' - b'n4J6fFw8xyHlsINDm0J6UOYIJ9BJtxGahQLUWJY/8UHGTRBPjYwjAF1feYk8eWHiO7AeJOSD' - b'OfpxSF7Vem9CqNc/z802js3JoXtt9jSQYy+Owc4NG0QHb4Bzw/fgUb8g3LzxSmITCmLVc84t' - b'Bcc6jm3rODbxciuHFoH359gzOcAxhPj7wCmyIqRTtqMUNkoxcPis8jydf4JEaGQKZEK1kcWR' - b'UgBWd42c5W6bNxFfQmRCPxBh3xdh7st5C03usxJuCboEVNcIthvl3GkHOnfgGOcmjKT13heB' - b'H+rcUIR/IAK7J4qgDzXbm6OvWnWOXuAT7EZodyLFOzh2gX8nx2YEfyuKYD1prF3v3PLVzi1e' - b'4dysZ5y7balzGzhv2EJkKQYpGJTDKK4HoRh2gG81OLZy9pAog0SHJQ/jqSEpkHHDpABUV1EJ' - b'dFENSfDVXx+LMA1AUCXwixFAtyapmXHOnX2Yc0dPxVs72bmJCP1IBF7CPghB76sarAPsQKi3' - b'SClsdG4F+Vm0zLmnFzr34Dznfj+HfM4mUXHNPlgIKJ/9UTzbUCrLsCDkW4gcBQ0aGVRHqHI2' - b'/7K2p5Fz2/3ypr78UFrlIQjwJoRtxSrKuJwDgTqJhdkvP9S5w/d3buoEWtvhhKPV9V+IL0IK' - b'q8FQpwTIXXAtIRWkhTL9Prz1v4bfzqlX/lLRNmAlPEte5y127tFZzv31Mef+9ggv1nKMdm4E' - b'eR1MmTZQpvVYBfIdRGg4Cuygy6idgu6MCqAT6kYyaEIqm2sQgi8n23JaV7eEg9b8nGOdO+OF' - b'zh2JaT+JVl8mvXnuLYvCYXgk2Cbb9r6U4Nr7ts5eVlMCm74X7kL88kmoy7BwqXMPP0V34d/O' - b'/e6fpIKScOPRB5SL9aZuC4pgLQpBIBypJMLD+Nu5FNCan35s/bPT3R0VQB1JLwE1gR1Bv34v' - b'hGEezje3koN+9zFHO3fJS507nu8vTZ0YWvl0dhRXQiY8xQQwHbYzrk0BSYApimM3iRawAV/F' - b'vEXO/f1h5352t3P3P8RrugZuBOXDGbkJRbBSTkYgKoJAhy76NQvgnqgA6lkDSIq853LqzVJr' - b'v5gDE/ltJzp35kto7Q/idljLDMhJJ2gEgQ85Kf1rCkEhzMlooVfRJXj4Sef+7x6+LXcHT9XF' - b'mYCvYDDuDZSAHIetTBiLHM/1pYBZADtcVAD1orT698MR/Dny4OM0Y76l+9wZzp1yPN57HHr9' - b'eGfQTEJveS48l1IG2xH2p3Ac/unvzr3vNmI9zTHNuel0D1bxTn6CCJ1MgagAaktwb+oLJS3+' - b'kN7O7U2rvxAT383lQPC/dX4Q/Cn0iw26g9BbWQrPpZTBfPwdUgRvvpEYiSKYNJC5CFgDG3bx' - b'DELmaFmINN7XjgIZ3H99vBMwWgAdpaq6weqni3OnMJS3kGG83TL18Yh/4zXOvXJGGLrjiQcv' - b'+IQtdPDZ++52Fm2kEHqLUAksYl7BrXc6d9X1PFgGLSY6N4l5BfOZoCQlKtpEwyAhVn1OOxH/' - b'PqiBqAA6Ql/fWsGwIzHn5dmfL8Gn9f8kgv+a07F0YWwDCX4z9Ostv7U+m1WQ9hXMXeTcr//o' - b'3Id/SWpYAFPwEWjEYAVdg+gkrHUNpPDFLkCKGO24NMFXSzWFlmuuHHz0cy+fiXl7AZN2Dgmm' - b'rFD3dMEvJG+hIkB/ugcfp5v0G+d+yOGm4B/AUThPlpReitgRakuBqADaR08v+IoKY46i1aex' - b'd0vVz5/s3E1voJ9/ApaAhr2AXbRkUhBqySK0poAUgQTcugaadfine5077/uERZmOn86aAy5l' - b'DUgJiIzSBxFqQoE4DFgtGT0DigO5mEqrPy+ZxPOB1zn3Jlr+SWMDxtjiV0fZQotAU46/fYNz' - b'n/0xeOgSTE2sAUl/7BZUR9syoaMPoAxxWr0y4ddCHc3Zn7OQICOdu+WtLMp5aVhsU8jIrZDE' - b'B2UpkFacWqz0x7udO+sbRFlOl2AyvkLMAS04ikqgLBkrfZmzAGDpCOUoYMI/GpNfM/nmMO/9' - b'8pM5f4nJPCcG4RfzCtIOrvAk/lZKAaOdaKnVi6LtnC86d8UrOD8UlkWrDqRoVSddDzIH01Dt' - b'fTqurquNXxi+WnwhfJwJWEi35N4Lvq6h82RM/gWa0LPUuW++x7lLzwl9fd/q87inDOmJHJ0B' - b'aYUq38DPfodz9QukPI662JO6wEEoLZCro87IVPdKI9cFiBZAkYrNMRbCP5057AtWEIjrP38N' - b'RrwoCL+cfIIo/IEOtfyVNSBTXzSWU/W/obloL1BdqE5UH/w3iDWgnDUnRAVQUG854ee51rjP' - b'wSP9kv2cexyT/+TjQmC1UPJeRw9/AfFqeCvaisZmDYj2j9MlUF3MmRvqRslFJdAuootsHqIC' - b'MEpw9sIPabTn3nTM/ln/oQ96GpNVPubcwdNgNt5p6Mr6q6mo8bJOFBCtbTah6kB1ccXpoW5U' - b'R6qrzvEL5GQmKWmz34diRAWQVCd85BlpTxxQY/rQyjzIDLUrnPvSu5nVywq+aPInhOqCk3Wz' - b'ZA2oLlQnV1M3c1h2PJq62os6q78SEIekoanvc5mHfBFM+MVIe3MseNS5L7zPubf+Fy0Mw367' - b'GJbqzfMIXUcBdQnMLzAYR+BH/psdlTi/l27B+MOC9baRelKYwra563Ld+Cn3eAWQFn4t4V2M' - b'8H/tQzieLgzDUWr5o/A3DiPLLyCFLMX8ztexNTrdgLd9igVXRwTB167JUQm0WV85HdmjFYAJ' - b'vxbyDKOFX4Twf/PDzOxD+GV2euHv4k6STFsDMXZ7IY1HOGqFqyN42lsWKWTVjeYLvOXi4JO5' - b'6hPOTUIJ8NhtqYkSEOHTBO9u94H6PVYBmPBr+22t5pv/gHNf/UjjCL8EVkfa4WhCXK3Qqe+s' - b'OBZPePwzyp5m8bYEslj6ctAJh+FuC0et3tsIgejzJlZfyip4O5bAJLZX067E+qCJ8sRlO6GQ' - b'Mt3qPleYLm7f2lk3NYjmGQMyTMKUnE/Lf+17wxh/I7T8EjQxrwl/WvD0XEJXCSieDuFJC2gO' - b'd/K+Elxe0Enb8FieRC89s/tKcNUqjMplVprmZ1zLJK2FjzFdG4UurVQhmWqVnabE02MtAHHH' - b'fkwomc2+de+/gn7kJflpvWpdugokSCZk/2HXnH88wv55a9nAfRCbiB7KgcOrH7WmFtwURLG8' - b'mkAK14o1zt1zP17zRSHk9EmMp78Ay2efILjpNIvhsrS272SjT5Tl/Y/zMZEt7HXIfobHYXYf' - b'dkBeCVjei+GpxzPvE4AW6g687bXsLrQpLCTaH1rNYhahN0/qkXBz48zpxh6nAJAH31ppNtns' - b'BezK+0rnPnAlm9fiTLLWpKvq1gRR+bjuZudeT7+WXVvCJ7+2c2YF4sdo5f7nUoa+UAgmmKXy' - b'K2F8bDabk3yWffnuINS+ScjV7Et4ImPqH3DuUCbWKF1xhGhTCJbGJgT+yz9x7qNfIMQQDiwn' - b'/ykxWtsf03V67avCxB0rQyGeet6bY1B1KGW+jPL97G8o+KnUMUpAdFD5IrSmQI9aC6CGXaas' - b'tp9auNK5oyY5dzNCNm5U6EN2pbdfgiMQs/7xHudOn4G8nh++7acv7ug7gRnCPP1z577OcRXO' - b'L0ExgTOh1Rd9TmQ48ymsnMNppTdJmQB7IbSPYl0cdBAf9fgclgCKweKEEOE3jfsbvwjDogcw' - b'NJolj/ouoL5kpG8Mrr7JuT/cwcrIl4T8KHZnWwJK0xT40mf5mhLO3IcXUdcjqGvWDkQlIArl' - b'oOetBYBnvfDL4ec37IR5f/juIPxi/q4UflWLCZta2u/fwoMZKACslKe4X0jrP2tr2C7LnYMg' - b'/pYRi2cUKy9w4S78mvDdhdn/1H3MYqSVf3Qzvg4EQYeu9ezJfzmnMAKLE+7CryklpaU0lba2' - b'7FJelCflTXl0Lwt5Vt67UtDMMSiF/qP3kC/VNXlSnXv6hmLF3/zHQf33HXoEQdTA6nPa8AIz' - b'fdiU8gOhVTTBaxQi6Ft8N5I/fS1oOcKqGpLy0nklffBh/bhGIFfSunvwL5NrTunyaM89mesb' - b'aPklmOljvayBwWxssjjE9YIrIhWBlat4SJpKW3lI58nnkbzeuDB8R9BHL4HHv6vzj5VDFs//' - b'vY/EoAG63n9huQuzVedSV4k+RQjYqufAOBh46RPOffGdfIZrRih3WmAaghKqHFpZgRhXYPWl' - b'yvLXdAksTO6lAhaC8HDIU6946aM3z/QuK1xtgSISTuiMYXw+uLc8+u+G28O28NXxvVcACf5X' - b'zmDa8DvQXY85v6RbBFCxI+QpYPWZf9LNrnyFU/Ea7pu71LmZLCS54oJQyGL93qYpfiWcrDBt' - b'CWWleJqGMEHhqW4Fl1PXM19Jt2Vx+DxZ7Ap4suRqvdsrAPG/Psjp+/2DnLvmDeEbfHIYlRtG' - b'82Rqhp9cVRbJbFvCXyRKi0eGW3g47LZFmAa9Ud1KCeiryqpzx3ke/oAR8EJUAvlK69YKwDMs' - b'jKtpvm6Wc9e/Fc/3tMAAMoubGjoq3E1d+Moyr+6AFJfq/NfUvXYbHgDHq/vTw8mXK363VQC+' - b'7immxvvnLmDOOMNXZ54UGKfh+v2V8XN9QuVYoQj6cu+KBG+0R1IANmvy7Jcz05Mpw4sWs9kw' - b'3cFms2jqRdtuqQBM+Idj7s3B7HPMWHvbRWGyT1P3++vBBSJWNwabLrwHQv92eMANZRCIyUFa' - b'9t3k+q0jtZar9W6pAFSx0v7a3EMf6PzJlXyjc0qglzcLO0K6RombVGGuJuuRr7oir0eGi+P0' - b'3T2YQjzwU3jBPcX8BY0H86ybFLF4wUs9TWm+bqkAVG4tCFnAbL+zTmFWGOafQK1/t1EAqUoM' - b'pSvyWwl3V4KnCOpmepTuCpwFL5zJSNCcZ9lDgBmhPdIh2Ctv/HRLBdAXxt+hYSAm1bybft9Q' - b'Jqp0V9O/rPyWfZmIcDklUUn8JtEEXgnAE+KF96orsB4eYW6Dplh3o2JWXRvdSgF4XqY2x9P6' - b'r1jEohnm0h97VKBJt2n5q67iGEEUSNf/i48IDcMzC5kKnjgEexSVsvmeT7dSANLkGuZZrWmu' - b'mHevOzu/dDbNAM1c2bnWqlzLnRSwkjJXgCZ0lAmYS7tJCWhzA/rRQLz2TAqBNTAvcQg2aZHa' - b'l+3uuBbAMzIcOgHB34jj7xMXstR1/0CfSgShfZSsfSz1SQ1Sl/6R7r3GljAmL8sJsB8CI0Ih' - b'HiHzz4hsw2Q+gRI/lpbSLsRleBTVwpVA0xCPjRe0h8HHziNLS1kSwWhRTwXPT92h8GI+zfjT' - b'SjU3gs9Mn5yfEmqV3gzl7ItJOm4gOaU8fSTdJnGcc5XF3IZ+KDpBOaEbMIAA9Hv9vH/D4yPl' - b'nw1UWm2AT0u4AJ8Hw8XZ55E0xoNHeW90EC/4WaCcL3gFud2buQHPM2IkWvcU6K5dgL2lyRfS' - b'+r+KIZ+pSW02ScWakhrOnIVLX0DeZ+GlRqgGM5Sp3Yq1Zfl07tfivT7lUN6NTcpXcBIeOTwF' - b'2kFIjtBeCKomvwwBjw5da28BvTvmEIUMcSwP4Un+V2mdwk5ESlt5UF6UJ+VNeVReLyHPyrug' - b'FJ7wtut/bRbogVOd+zi8otWhI6W8oEmTsEvNiEg1dg/QxA715zTp56wZ+dbfKrvRS2mCq62t' - b'Xn8OuT3YuQfYfkufxN7MsZ3j0UU8R2g/fCkNF0t51foXW89gAvginF3XvJ09AH7JdudYRlrL' - b'r0PXC3h2zducUxiBxQl34TcDdygNpfXhS3hG2sqD8rKJQ3lTHh1KRHlW3pthqNVorfOrTiL/' - b'+AJWs79BjxkR6I4+ALVKbgXe3VOY+z2da0GTqXMxpARu+kTnnriWlWxnObdzEwflen4dO+7Q' - b'Ct/9vbCfXyhg8V/P4ODR3oHver1z3/g54Wjhdq4Mh671TO/6EkZ+AMUphPQj7SGotE8lD8rL' - b'LvKkvCmPT5JX5Vl5L4anEG8j3Fs+ZQW8B4fghkU9c4pwt9gSrB+cKtN21UKY9OtBQJp13F9C' - b'JBCDbqNvOn8xDS+CNoB+/6TxYRxb7ysRNgm2WUCLn3HuWRSAlOKo4TD7GGEJwm9hwpPWv+m0' - b'1pOXhUvIG1uBDablnDIhTLFO57s1hsZ7ks7vvQ/AM2/mM2MogzVYNduTOmi8XNcoRxl2muzD' - b'3jg73D3qNTc97EPrv3w15tzxYZefZi6QBF/8JwWmTS4PNmsmKVSacdsqpwTblIAE3oTe4lWq' - b'JH2eEqHQRJojDjIM4ezNfhQwyTUNqEw+35w1WnT+iexqdD9KFjp1+z0Ed+erimprXvAMB2P6' - b'Of9LnbvwJFqlPStrHRu51CqXH7OmbGJSHfJcG8OKeSsFKQEpDYtv+PSsmP+gFF6laUJjuHQ2' - b'PFVkqVQSnf5c5VH+h6DULngpya+Fxtx3++XCqanATW0BUFduKK2/X/F3AA6twwMPGVN2OkfV' - b'OEFvmtdAssTofiiwBvmrRmnUILm6ohBdpMREm2PEO/vhINWmIQOSvQ9rQPu6FqC9yCU4CTSt' - b'BeDrhoKMwKGlyRwfmsFY9OhQKlVss4GUlg5roZvtbPlvNrqb/0NDnR84jtyvCpvH5o3kZitR' - b'dfltWgUgJSZBf54FHW47+9/jpdYwlBixmcCEXnlWedTCNuNhSleKq5nqQPlWnvtA9xOPoRJw' - b'vGqYU47lbgy50jVvFwBBH0Prv2g9k36ODNs+qcLEfM1ippqgWH634llfuQZPtIbZtP12E0Bv' - b'OGifvbHE9uEDRoxUSKBULh2mFJqgGD6Lh9AFmICDczE8NYz9I9eqcemOkJoH0LwKgIrRPv+O' - b'oa3XvJKZXAxtCZqF6dTqmOA/ywjGXf927rZ/smEFm1XIDPWfBEOIGhrUjqgLBu0vxQfzymOd' - b'e+kLGWbcN+Q6XcZGLofxjPL9+hcxO/CnOAYZfVmLEvYKrZEz3568pfiqaRWAhH+zWkkK86JD' - b'cORw3ywMZ/lUK/mnv/OZLybYzEP43TiOIc4NGskEHbWk7ancTowj+d9BJrfsQHHdy/Fr5/an' - b'H/2/VzB1+ISg4KysnZitdiWlupBCPpaJTg5HIJc9AppWAWjizwpN/Z0C03EIGl1glEcTiB0o' - b'r+9ezye3/h8PMT0PpOXZiMm5mUNC1SyTUaQEhmAF7IUDdk8U2NNYL6e9npmGn3DuDa9OZhqm' - b'rB2CNxyolVe96Ox5ifqYx3TpoZRrPc+7IajaPDStAugrFb3BuStPZAbXiFAYM+XCXft/vSLR' - b'D2QySqmFEORMwoL34W35X2tlFOqHNyL8b3Nu8qkwH4k8JWVmiZVH03hvocWGpL88YSgOtRdj' - b'1VC2PnDXG1ECallV9mrqx9O7BP1FgFb1wbMOkS+JrFmSbzwK5Xw7vo1JKAD8Mrk6V8LdAVI+' - b'AIlR04Ey7euLxSkvwmmjGXPVMlhhoRVfrYBnLAm3gLPu/bPwpOR7xdUkklKQxnH3/c79Ny3k' - b'uFPCQp9FMJkNR5WK3/DPqRCVYTFe9E0og9GvcO5Nn2ZqNmUVpMsfnrT+VZhcHfhIxemfxuWv' - b'RffCuK3Rl32SyL/nJfGUwxnrlzqXjdWkL1N82pQKoD+1tVUtDoJ/4JRQCWIEq8Rqq8XHJbJa' - b'Kmn79hyKKwEQAxcDS0Nz6T/7c0LQz+/PsOUq+s+KWyJaMVQN+0xlEA1W0b3Zg7I5nGqf+wWt' - b'KGX2ZSxTSNFNdO9oHQhHqTooSzjieWVCoAMm8zMYJyDDy/It2fNS8YnaXJDaD6BpugBGZCkv' - b'aeY1Mpkntp7fXm1NmGAqnr6U+8QchoITs69Np4IypQzBJOPoAx9xIIxfxBpJp/HAY8794c+s' - b'nmPoco5a/m4i/KKfwMs4dFmOYhuNArj1HpYM/8e5k48P74v9SmA9HaDl47PZyX1hGAaVMFdS' - b'B6KvhiOnTWJl8n4JrgRnsfSKPVNSsuCUpj4vPgk8+rT4AUwt919X5r2qehc/8s88lxx6yH8A' - b'4laSZQveZWdlMoGGVwBGUNPCmrap8f9ZtCqX7R/GoFUWzyxWqgrPJpg7sSZ+fRv7xH2biMs5' - b'ZF14Tq4AkTKo1o48XfUq5z54BVuS07obUxsG3zLBKfc8xJNBgZH0Lsc8FrCbnJ+DfgOhieAf' - b'jzp34rH51jRdV0anTQjbt37l3Pt/SgS6dlV9bdjqgFb72kv5AtCFOCWhseFWHqoBzWs4djwK' - b'4Mc4NY8iJt0aVs+FetaZQ98YHIXyloWwk0qU83YNh/GplbEh6zflA1BxGhpEUA35jYKZdF6D' - b'WTafltP9AY3PJhSafNIeMOFX3Fv+hvCfzQX4JjCebbIvvioHVrkKJ3zf+B68i2XyjQ+0ZEBL' - b'awNK65+0cNq0RAyj5sJwlEun2d55epBpCYaGNf89h1aUsg/j2mihMunaWv7vMIT4/ivZfGQm' - b'owlj83Sppg40LCwc6oa867KAO52e0iwHJrSDWAtwEhba/JVYajgF1zAisIp6Xc552WYwMG9j' - b'JeXxczXEfygeHVOIJ+f0BvLxLIev3LYKQLBOhxTTNex+AHtAOO3yo5V+S9HA21ZBJipEX3md' - b'ipBOQ0t/BG1//NGBkUREq0BdtwXWOmjm3QnvxhwH9wGYrE9T0dKKKRq1hcorDLUIWpg0C6fX' - b'bd917vSX5VsgS2sJ1sWU/0EwSGMojNPIQ0zi22po0IpIRB7dF6FBUEYi+Pd/IazVMFoovF3L' - b'7D/0DcjQSJQEcRai5KupA+VV8jaJRmLtDpTwCuceQxmrO2BpKL1qQPsd7BRSkGvIdjt4db+V' - b'upNPYy2zBZfBM/OXOffwAtqjOYRdxEH+Hd1BPxqCMlhPHI2QSN8LStNV1NbbekEL/DvIZ+Ps' - b'B+CJkuRvX4RoIIRTC6k1/g4CuzHOXXyccy87nPXx0wIjDWO4adDAQKxqBL+QvEsRyjkw4LiJ' - b'Qfj1XvVeLayAQfyy5L3ox84NCkCtm1qgHGBaeKbieS2gGLukk6s4jSSS6Cic6gv7R8l9u3Ba' - b'4pRVE4WyZlYlz9Mt87xFPEQRjxrv3GxZd6TbnjrQOv79UKwbwSWcUgAqUzoty1a5s8JrA5ZK' - b'QN3HjVgFK+HV+Uuce+hp5377AOeHiE3abiy8RXdE1+solLZk07VetaSrntQTWuDP3UjRdhkY' - b'EUTwfcnJEIRfEzDcsxy8PPd4rPKrnHvBIcHZt2ci8LXMsBdIKsYqQ7JZwKttJpcuh/K9QwwP' - b'wlaKSQFrCEqjKFSQjuVZBR9DqzUQ2msRjFD2gwj6stLiVDlKJVU0/fRDIpbSd0Yf0UsJWxq5' - b'vKXxtHFtcTwOfjxO4pgCaCN6i9cWp5C+6fwpghS8FqCpa6NDG9Ge9jLmEdCNmb0Qf8+Dzn3l' - b'LizYJwlMt28fLMwR/Z1bQnl3Ql+fjhB1IXSZAvAVBkXFbJPQtrPRoqsXQomxmPYX04KeQGuP' - b'Bh8s7ZkCVYpVjAiooyMwjK6Ehqs0dr0XedHZq+cqkBpj+MlJtEJjRiT5shdV4GorqKcbgbRa' - b'bTzM5DevSNJR31fOt0Xby2PxOIgzCOYdBQfMw5zVfopaVemB56LJRPq/arFWoyDbzawkVooM' - b'qkfhHUE6fk2BEld4RVAmq4AWcegKeJzEb/G8CnyV8JZw+7L5n1AW1YEWRulQ9/TSVzl33yPO' - b'/eqvzv3mTgwd6mz8OJQHSlfbkaucKmqCooocdihoLrkuUwDKgbanfg6Bm/0EN2Oc+/zbWFDy' - b'sjAdU4T0QECbYGOVonNHwXBMojI+cjpbiX+KTSHOcO4ZTFA/HFRFAsiIG0nFPrqSi/H5TTuF' - b'p1U3oAq8hUE9o4BTXaStCOU8zE0ni8lqUQyFAh1OmVZJkRUBwyGLS8puHrTfj67VxZR9KnHV' - b'oi2mHH9+2Lm/3AuCiaBECS9DOYhmJF81hDj6zVdchn3JdzMFUjj1kY4zZmTdbfdm3NGHkhb9' - b'bDmqeZtKq2X8kJPwXm+y/I0dkHEPPiZcwhnCS0gDL7WMn+VFxpggiV9peiFTIb7Pgf8hB1ly' - b'TTI6lKNeJKwRofNPde4VJ2Tdm8/NuOv+6NyPbub1vlk3bVTGraEe1TXQPu1K30dV9DahZXnS' - b'9AhR23ofQhnrtJlczQKQL33AQ+b+guVgpbI/diUr+k7Lz+lXWnLeqP5FWwlRrUF1rzTE8Bo2' - b'emyxc7/7Pqlo2EfpVV4TPpN+w00E5U+fR5AmBCZI8VdNsq8sDSO/a6HZsVgZV32cVhzPs/qh' - b'An3ySv6Hq2+kBaIFX8lz0c+K4q+5kfCvlrLY4Nx3PsjXck9EgRFeQ1oChb8Sq+Cu+/nAyncQ' - b'yLX0YzFhl3ZACYScePTJTyanHLXP4LVvzrjb4IcH7+T1VA6EqSW0cQ+xn51HjBcKF07WvTIF' - b'DsCW8dPCr3RaCn94ot88tIxfrDxW3+GcVgayZDPupGPDNuwXoxC+fAPlvR3s+zs3eSBKd3vG' - b'zzFQXKuvfNrFrtrOT8tYLcLnbjpFASg1Xyh+JvXHy0sru5aW59WvZBvvi+jjH2ZaGm8pQimN' - b'XQ+hb0mQkIa09WhM0O9fDbOf4NwdOG+20KoqD0GTF8ZK3VvBEJyDJ+OvOAlvNt0WA2MIu+/I' - b'2SdFXodQY2s3MZpwEPvY0Wr3x4pKwwyY7EGUwE2YnZNGQevnYVWVhUAqjz7mIZPebUZZfYKW' - b'6fh0bAUK4eVkPfcVWDUoszMIt3QddBqMY3ZHHl9BzHbfKl9y2C36knM3/w2T+Un4wNJRxsuA' - b'LxtheqP8Xvy6sM+/Nj8VzlrSv0wWSr5S+pYH36ARUgr75OOCX+vWExl+/gEN4ULqaiIWGbwv' - b'i8CXqSTW2r6ouwIwxlWhplP42c9QAJjwx7Re556S7+OLQApjrVBti1kamyc2zLIPDH8J/bWZ' - b'WCJyDOp5RUBcmg+nT2xZlHoyn5JTQqKXHF1SAEY7vdKmqO94DQrgLuavYCXoYxfP+0ghnqyv' - b'jXOcu+6avPDvkqVAOOXf6CGcUsKH0UL98p2s8383DDoojHToQyW1AktPNJPgvu21zl2BhZMu' - b'k9IqpGn6XtfK60D4y8LqXHEd+lj1/bEGzco1FGX6X2fT7TzMua/+grkjvyL96fS49gi+AU+X' - b'+mXJOKKkg7YmSYuhVDky9yfDqLMfp49PgR/+X77ce24QfhHEKrCrKkzpmp9BU3n3hNE1xFjR' - b'kYRVWa0sXVUO0VHw4iP52AVKYPkCTHfoHpp/BIxWcuEKWvSXhX6ywkr4e1M/sngs3zrrmdHk' - b'OLpFHzoPo2ERXQs1GUk6il8aCgOVvg/pyicQsEmQ9xyUbUH/cveqr4EDAn7DIR9DS2h5Lx9A' - b'Gmp935pIIb28IpDPAP/LJOe+8B7nfvFpbuiSLWI4cTpKwPIjvgrQMr+l8Fvott+HkOjN+oAy' - b'rgKOgunEMPMfYqeVNzr3k4+GOfN6p8oSQYzx6pOTyrCaya98+bwl51L39jx97rKyQGzRUOmr' - b'CyVfgD6Nrtlp+lya/AYCvzPwSiwvTFB97ktgDBnuWv7KGlMd6XzSMbzjeiPWkZyQbUOedUPY' - b'8vfqkysvRs/dKYeanpW7l6IyB1y+DtpOL12GVj6BAqas9j01kkbPdf4+1FW4V33tgZK+6MyM' - b'e4CG8agJzEuZq/kM0INYKnsImY8fEHfoPhe5oqosKEmbt5bx8RTsWfr7GxZjcn6OefJvCqa2' - b'aelyzNdmInUIoIqxw1rEUvf2PH2uQ5YqQwmTGCjfgkMw3b+Mf0UfvpTfYACVoimqjtZl8liF' - b'CMKt/JcDQy1vtma4yXk4qC5cE3Jh9GyL/un36etyZWm0dyqrKVk1kkcf7NzvP4kD9vRgLctq' - b'9t8r5F0b1dTuotW8KoVQGlnOviU4q+Rsuv2L9HfOwuPOy0Zq9dtNtQaLKEayllPXpmDPP43W' - b'H0WwgHrYByXg++5YB9o/oVrwzkbFo8XySsY0Q7WIYvhWFPCWj0gLbaVov0iX4KNXYr39B51L' - b'vUnh5i2BVtHb8yBXezVVAGnhX7iefJHMP2j5Tzk+5NGEvz05jnFKU8CEfs7CMCRoprS+k/DN' - b'/yLebJiIboB8MRp2XbuxNK5SbzagyJ3qFAWiLcvq1iSVykA3f646VL2pS6DJbx96E76Bd+Gz' - b'QQkMRwmo21VjJeApWjMFIBNFLb8m9ywUg3H9r08zXo1DShlvBuH3+VRek/z6c6n75LnF0bmr' - b'QPmU0+4/T+P4o48vMCvg1Jfi8DuVRUrLcQjKS07YR2f5k2c4xS0FKpNv7QkwawE/OBAnYAXY' - b'9l+l4nXkudFT+VfeCu9zdZK8T993ZR10pMzpuOoSyDErP847LmUq8fuQJ/xn8qVppqnKKFnr' - b'IORQ1EQBCJsypkwupoVx9Pv/8SnmZBwWniuzjdbfV57SIIbzWpjCiOmVX38udZ88tzjWCncF' - b'E9pCG61Uu/f+UCrlR3nRcNN7LuQZ3mUtynGTnPvw7WHTDYVUuUvlWa2R8KxDof/0TwTGPBVo' - b'U4xag1C2qIOE/kbfNuuD8Lk6qHXmOhmflLlor0lqV2HBXftenOhYAhNpXCX9tSR/TRSAZzQy' - b'67fpoqW5/aOh5becqmIaGdSKmILSJ7k3b6nyYOKQ4VBZSwlUvWmgYcsv3EzeyY/KI4ESHHu0' - b'c29/NT2BeXiZme+gZdVf+yXhUBhiMuW3MM+61zvBz3/PEud7cR6OQMFLidS4Pn3aqTrYQr4q' - b'rgPKqrCKI/D1WKQ84W3z/HpLIFECmhvx3stQ2k8xRIgFZnLVgdJAoQD0LjoOaim1Fn7h43j7' - b'Pxn2hBdWE4qOp1A/DGI+5X8N/dvb7mL6K3PgK54JaNlC2A6axCy0E8Onpk0JdLbi0y44D/2Q' - b'tfdXOr8Dj9KXEtAw02XnMOHkr7zHITh9Mgrgtyx+QmG84xLG9oeFgogW6bxLqCT8b/s604en' - b'MiVYwl9j8MIPTqW76JmwOcu/YPSdpOXpl2PVEgkTTzj6YH2+6EDnzjqJlpIJRXpm5SkRs+Ef' - b'W3dATtsPXIEzly7Yb+5jFuh4LAKsbF9XHSxFhxQAtPdEnkbfcjYmysfezJz+M0OOxHjWqnYw' - b'j3WLbnlcvgpT6/Os4/4BSR3KoZavLcZL50qEuJVFRdcxvfba/Ay7zmZAmxb8iz/S/ToCxx/1' - b'IlNScMRBmJJ0Bd7/bYTrAPwBCPSnr2fX3qdpXS4Ie/ZpdyWFF+Ot34gj6mts00WZxoFL211p' - b'uXAtmC7kKP8rnI/hqDzsozyDwd3k/Ltqrq77BcqKenjsY/nNQIS7mcF3B6C9lht/9ioUwCKE' - b'n8ZqDOsnnkmUZDWsmtAiR5V2KwBhEINPRjtpeu8ZaN6rLkITwzwmWI1MeOVdCkoLab71a4T/' - b'R0zLZCqwthyT5eLLV2EBCO6GTWCG43Ksn89gqn0zLAgSHTqTAb3J/hLWNfyBYdfTnZvx4mDd' - b'mFC/mmfvpy+/AI/+YIT9YJTAvVht9z6I9XYTLee4UHdSANrk4lsSxgMCjm11EH7jE+2w88Fv' - b'kRZK4JgTWclIN0xQSR2kwwyfhPXzKK0lSu66j2lBUHPwoi9smR/rzmmR2Z3vol5RBLuY8q0t' - b'8rQ5aUegXQrAE52ENba84DmSp8X89Bvzk3waveUXwax1XrjUuU/Qagw5EU83fUnNdGtPH1dr' - b'uw8Yzq5Cj4SNIFRZ6loonXqDJSHB9UuDYfwf3hIWWWkTFT8rlkBa+vyz/2LNwwcx+4+mBZGg' - b'jWSsGfPZLB7VrUC4jqA8j6xkLQFKXjSxdHyADv4Y/YVGoxe33snst4MRYJRBexPSVmL7HQiu' - b'O8B5EesXjiHbSb6tXEqv2SDdiLzshXTl3oFP51rKejg6U/JXfeFyVSmWqRoUW5nSyjJp7R+/' - b'2bnDIbwgndnwpPF+c6Una2vX8bMmLHLZSCvnlRdlUzmqOVRKmciaaffMs4ngV18xQtNu8Hnf' - b'xgrTMQg6CuAftOwClUNWjeD0Gc6ddCJWCoI9SoKNEliO0kvTROF0r+2wBVJkrQL4Nx37MV5Z' - b'sQo8CK/PAz9KrxraK6zl0eMAl8cJWp+Gf9ixvHZ1bJVDFpNAk+peeTKih8U5UXVI+VRF7YF2' - b'KQAlOJ5WQ+v5taRXq/oEnW3yhlSr/00TS5+vkgXjn1Eu8Ur6fTXYDUfffgnjVRO5BmE9s1Oj' - b'XhGhBL76m9CX98/Br1ZXqx7fT+votz9XYaXE6QYVs1TaxxzgqxAszb6yQCBee+meTs7j4Mfj' - b'5IWlkQ7TrNfWFZA/4OrXUQqU9yqUnRpiVWUVkCN1u+pYfQ8/r5wW4l0wk2YuqZ/ZDKZ/IZH0' - b'QY/p+7PeHafXgZjLYpj2HNpkQ9ubOUzYQ6aHVDpbIWpJr1aQrKZepuyDKXwXu/r8PeRFSsCE' - b'4QRM4zecz/cI6f4MUwuCAjBnYQhd5DfHMkXeteNROj/TJoGA/Mr/ohZN1kq1daA4irsaHMLl' - b'cXIpPKYAuW16sLK8GMfspy5h6H0hxVUjVg1AE4OqoooHRNCxEFrbUV1zWVjPLGTeBDOsTXA2' - b'QmrvtmsvZjOQUxGIc+hXocyMPp7nfaGTAvkHyXUSSCc91iaaT91B//qysBdcEqpTT5Y95DlM' - b'1x3LCszrQ370AVXVnZSSvP2Xne3c9+6kCySfB8/85qjlcmsFLRemyndWBwdN5RNir3PufVdA' - b'y1fThSF/ZMmDD6O0DVRIu+faX/Kjx+tQfGtvANcPGJYFp8DSCHfN/6vymFP3Iqzvq/+CJb6F' - b'1Z3I5DojWlvF7JWjYG43ubai+PcitswNLTF1OIguPCMIvpiq2Vp/EdJah7Nejtf49+zOgid6' - b'9hzKJqEwJuOyLIjzoIkbwCjIW8KXgWQR1ZUm5fJGfpQl7fozBXP/MfwAN8Mk/42SMxNS5dEu' - b'TO9lyPbzdBMcykG71HY2qA6MTm96TaiP9/+YvK8lJ9Ji5cqZzqzVwTCU+fcpK7isrM3Gl+li' - b'lbo2f8fkcYz4UNYrP8o8Dabcr8Mh6Pm6VMQizyu2AERjCcxo+rcbn4Jx3ommnhwwKtFmBM+A' - b'lEnDZ3KsvBiv6lNzGVqBkCJypfwniVNXQptb2peK68V4Pk99Q54Lae7rIakLyY/f4Xgaex7+' - b'wrmTXox1MyXEkND1peYvPI16ZOagNhbV/POuABNUKc13X4aT8iU0MAvJz87KmFnFFV/q24BT' - b'J9LyT+eabpAplq4oU73T9HyrRpfCnwa9htMdmLMBPQ4NV0I33wKUy8TufIiKFYCIrL6Ghsq0' - b'86127xU0O6G9oFM2EVVDdzo6AvWghzG5qm1vhH/RJkYa1gfGT+fVKwAUtD5eqS8o6yu9+8MU' - b'sxaz48ytTFTCQvE7/cA8gsMYufnAOUwweU+ox/A0/CrNFtDqQYu3HboxJSDB1Z6K6X0V24O4' - b'HnXQnnzUM46vaxLQ8uHPUIeyAvY+OigAVRUsUBpSdQnJK4ehUhdLnPt/p9OaTA7xLCOVY2m8' - b'kCqDFJwYR+f2gOLWg/F8ZZInLQcdjqXyyAJyN5DZhkflPd2WX32+Sl9S0jZgOIh9SzCfi5HT' - b'mKV5HZuFMunHQHmV5XPBKeHJdjnPBAlztCJDqwcheK1+pQQ6UgfpuPWyvmpV1lrgEc+qDgUn' - b'Yt05lPmsjVgByGgFPJyrzYoVgPr+fuIIzoZTj8+bWd1BAYiIKocxjghY7aG4Fl/4agWqKe3m' - b'41v0RSjfmfgpfsjoy+VMOaAuBL5PyFmOvhdjEi5ASY/DUlAzIOfkHtSd5id8i/6+Vgwqn8Yk' - b'h9JtmYkFsFrzIboYOlIHyrrK1V34saKqSJS1Jnh94mRiLGV9BwqgGoBklcFgQm6DSc47Nj/M' - b'VVnM5golBmrPUa9Sqo61p9+6BTh83o0CwIyfPpHWX0KdgAm0dtW94eO06tTRgmeSSSKE0X7+' - b'48cyYev/mEr6rxBJZdTQmdadv/4M/AX4AQQJT+XO4Wnn/raH/orT00CK31udnE96EaUfgAGI' - b'xecn6JUnRo5aFSkABfIEXuPc2ceRwJ6hBemJRC9P19q99TWEgE6hlV82ny2iXoegnhcsL61f' - b'sBY8naKejVOfECXRb1TwFYxEwLV+X8Kuab+f+zW+AbzsUhq7wSM46pCw2ETXeh6h+Shw4DT8' - b'csfgwMYZqE/clYXUB4jaCurxDIQbl6iPiImpD3UKxGxRAQRa1ONX9NXkonmbwT6aIcozg/DL' - b'W6++eyHt7V7xpk107ruvJt4iLH/qTu+W4RCczJyHu+5l2fOdIcdyCAqG81wftvTfQwiPyjuR' - b'kjDx1PUU8JO/qHPt8iwFoGnt2v2Z/9JAeIOKFIA3KTD/X8NY40RMSQ9lUzD0zXOW4Mic0uGv' - b'udfZrgtnp+nenqXj1bLE2s1XU3bfc0Ke7iboxdLRO+VF8CKGNN0EdACmvT65LonWij43BUvi' - b'F8FPYOHlfVf3QdOivaVAsK6AdB2k6VusDoz2uTqibFZ3XZH3rkpTYmh1pl2F5SDWLF0p/kqg' - b'rALwOGAcfTpa+8HNOIJFMyQgqBB/CNzgv2IiCYPMXx3+mnud7Vr9LbsvfJaOZ5XR4SKTnt96' - b'C6fdARPDuL1wKu1yYO+HMynmZOJpE1B9SVgV9iyjBPvTUri5+Ar+6HWCL6/Kb5C6tEedcpbw' - b'eromdSB6p2le7F7h7ahLHXRKyWuXyOTxYVMUbeC6Z1nJzouv2pjyAJH94hKGlg6dHoKawJSP' - b'2Bxv02WZt9i5J+bQj0JoxHBtCQNBQhiIrRb0cDzq8syncbaXCqo/23tvEB58QVpQw5PSv5ro' - b'szdOIc2oM6Wgal+Ck2jIfiwI+hmjOVgWWsVpeL0wlUZZtzdSmhJgnUX/OQvINspK+am0DjQR' - b'SDsdHQyPqu6kUISzJ4DVrxZ6nXIom/E+ggLYO8wDaYuGZRWAiC8P9OItXEzDkwyTC2rB4AFT' - b'1/5aOeRUu/42ZgN+k/xg6Xiua4vz0lmXhQTTXYWT7oNXhMkZHWVAWet9wanFPSuSITpfmRXm' - b'S9t5zdKUWhS3t0qIp/hbQaxNXLSz7w9+y0zAqQwxEsaUADE8KOnOAC/8JLYJHvv2r1gP8CNS' - b'pdtSVR0oszqwTj93GVOBL8QRxgSojtYBGJsGVH9SeIepkd4U/ABlMp/jopIKQPQUUu0lv3Y9' - b'i1xewkxANIwHvWxyMOFXMW75G8J/NhcI8CRaRI2dm1attJgys7/xbQQL5v3mBzvGgEZ7KQEH' - b'zf/xpHOXIyBi6nS+i+VN7wWLlrEpxuwwGrBFiECqVyqXHLqjJ7Av4I180XiGcycdR4uLuaHv' - b'2ZvQ7PZaQzkx8LHthnNH70NZfGsNqm//Ouved2XGjX4Nis9bAzwsWwmp9Lnsxa4nO3ZnwEHW' - b'yLamFUsg8vRKhVfueVH4ua9U4Wp+WZheW/fVZEBkUr3prPUBjtZ/084szkA+OZ5D1LL89rik' - b'ArAAfokrCuCQSShYmZQA6TQ9GGOsxGv6gZ9TnDOY3UgLMpuW0/Zfr7SQkq8hMNsBL2NREUJ1' - b'8SuY0851e0FVJSJrz7dRDOddf4dzb0E5aTcYgbWa4S7/ax/61Gqx39/JcwR9LK37Asx+qzTh' - b'xkfkPcVaNvvl6/kk1aHkf69Qq2Y292fmkZc/IoQ3hbXe0fu8cD6J2f++n2bcsJlhpEM7D/ex' - b'DJPX4tAy/Z2E1+Qn4XjfT6E/3Rt9ctzq2UphuDpT+JVmYXpt3Vs+qz2P3JfpABOxGrdk3D7w' - b's/ZyDNCCXrkb2LY8iIBipEljCklYPl6zvF2Kl332bAQF55i2VxLT68s3EpJKDymAdRDa+0po' - b'pR+fG0pvLVB7aKEaEj556KXRr/4hE3rongin3knjFx42rPeHu5gLgGAPnxyUSDFZWkHhRg5z' - b'7v/+zafEb8dBuIquHlbDoqUwD9c6bxfzYAHW40tAecFkqHMR6azGwkRZadKSylcp7S2c4iju' - b'vuAQrrnCCag+PQ+H227/O2Qv586cQDHlCKTuZKiJNi1AMp1ASQtAYTSeuEVMgCaRZhF4YrbC' - b'GN41469fBy8u6gCIHKKXJws/O2jB0gzeHtQeH7iWwdQTEdS/P41Z+2U2gXgL7hgq2LfOBYjV' - b'8kv4z7qWF1gOqrrneeaFoCCshHoVAfqOpXvxY17+giNhmFxQFQh/gcJ1BISmGFgZRK+ijFos' - b'UiXPKJu2FRf0FAVgtByAw3j6aAqOH6A/dVsUKt0PQB8llBmqFkhfmBGIsdVv6y4wjLI5lJs2' - b'A90bAVgnZVBl+UwpquugryKNGZEIqKS4A6DoqthFKAGNMlz/L44FfKXnovDVpX1RDPL2y+G3' - b'+BnW/d9By48jzRF2eL8sqwGDGR+y4bGlcpNl042MV/L9UfDPawkhfWhfdh+Unz7EJ4Zuw2+a' - b'MD6QfxN+qr/XJ71VvhHDwUB+6ZX77pd8MM7vZFp5eupT94UxfV6xAkYMD/nxdeMz2DJ/bfXB' - b'23ofypz/bSt8te/zmMNVW/GtfjRJbJQa6234dHztGaaW5benJS0AUVKLUDbCXFIAWq/dncA0' - b'phZSfOR0FlN80rkjOQ+gv1ytglOfXMt0n8B01uSbl7wgUMr31aFhngmrp6CqTfW4WEoAza4R' - b'mUs/zLOJDONNJd0B7GGAyfsojkJtozN6MjqISC2FP0GiUw6CcMkSkANzb/r8Pi3e64361JvA' - b'Z8/C01zkJFQF9yAIKYVfi6E+sDmutI/CGTMy7rZ7GJY8hLz7OmgZ3rBY/ML73SiT4Vgrjz4u' - b'XNqbIcQX7YNfoyW+tvrgbb3P5yNctRW+2vfV4k/TY4Sc9bugb77yeJAqvzRtAqUVAAFoAHxn' - b'bD9amn7qW3UjkAIQA0pjvvlCds5Z7Nzv1Hrux6FytyBeGwVHyJ/RkBst6Z8+G/YUEOOZkrHY' - b'1aC0OHYWLimBfRH4vY9grHwrn2CT0Mti4dm+KJ6hKCE5/DR/QOErTU+Nv456wQ7RswiYj0T7' - b'93/2zUxRxh/z6L8IaKZrpXlK8D+DD8NBm2vBJZx54S+SeDd8ZDw3ED5Ud87PIynGB3ldX35L' - b'MPjaM9goWn/bZbU70c0YcDQm6PevZnfj41kt93CyZFaEgwGNd40X0/d2rbF6zdY79yQmS+2f' - b'p1ChAtBU28lUzgLG9XvRWlUDSl/4tNWXjmEo5L1Ghm67hNc/p/vhM0w4y281adQ6rLek8B9M' - b'gX/06a5SIDprE5CFwSBxqQAAJCVJREFUX6Ib81fn/v0UzEsZRV9f7tTZcFj5vKLjRhOBXngg' - b'n2d7OcYRXSDh7KkgP4D/jDsNnNGwFC2KWgAWSU5AtTDDQNivaMhSaLv+eWGfqVSOxEAylTTH' - b'4dJzWBt/OkVOmK9UnFbPwaEPc4pcAtPE4Y7f5IU8tMeNRwHQUu2xZ+5txReep8EldNrM02/o' - b'abH1nKP9fK+YwmxQ7b3FC1jUo++vDG1m49hxWkFaiC+ENwEWzSS4b78k+DSy3n5N5yePv9iV' - b'FsXoU2iCIPyF4/wt06+UPwLG2v8Wpl9435EUB6pxQeGqK6jJZK2su0q7AN4CQIsMQPj9cFRH' - b'ctXJcQv7XOWSV0tl/VHt6SfPd3vAcIip02C3YtDj6eP+/GaGaGB2h4O1PUIrVpasGl5/zyM7' - b'63X1YNgsZrX3Fi/JhxFhQ5ifvqeWlAL2OB86TwPRT1ZZEOTC9NMxSl8bjjx1LGxLfNXwh2Go' - b'5bkw/cL7atMSXY3//F4R3Mu/Q0+gNaQYpWy77sMJMRepOK0RdoMnvjtAOXzD047CqgKEoxhY' - b'5ej9CUcRAp/KWvrz/bl/vh1pWRodiGoo6nYeStm0HZmWkB+vMgN54Qz36V/I59SKq/UOLXj6' - b'bWXX5eqgMgxNHkpEBDwPc4acxeU2NQyoMCUBhexVyCaYVfPluzuIfrIGJKjVHmK+cmDvtWvt' - b'R19Dn51+7n4yWZN+Wrm4zfTOMxRCPEpO4/mUlW7VwXKsAkaDcFf814S4WvorfCX4i6fa/E+l' - b'NI0Fn6d7qEkgGt3RZStItRxFFYC9915EbISV2+hHYK5GaD8FxJxqAdWVuvw8BgzoCjy2nL0c' - b'cZAVtniqyGY60lRR63MA/pCnV+BXOdC5KyhruouVDhuv60OBLXIGI6+yMFkSUBaKKgCL4U0J' - b'FMByxp5tZpW9i+fqKeBNXJSAxvPv/lCI/xQOwQOwBEbQWfOr/6gwM4Ob5Sw7U3nXrsUqy9OU' - b'SfAnyjiesoqPVPYInUOB56UAsNr9xLTiCkDti4eyPgDvPcSbuGwjQ2NCGqFDFBDVma/iBfxo' - b'LICHvuLcZQx9PXofL6aynx8tZ7GluR1KtBMiy7p5HpNzKXMTVj3BUPyLnPvRuzljAZhpmuO4' - b'TshPT03CukAbmAYs8MOwnD3f+SfJT0XzAIilteNDUAAbmOGmXUYidJwCqiRr2Y88yLk/MnHo' - b'17c5985bEKCnwS+3LYog58FpdMmBR/z6fXU2pzv3lfeyddwZYTqqyikwxgx38beeFBDJV2hS' - b'GnJbknUq/TLQVrBNkgLAAtCeAAJj4FipgR7t+TUayiegedvvuJTdlk/iox/M7HtsLvMEnsWC' - b'w4PegsaqWavRRLB82npW6X1hfLsXojR+j7jgp8h7CXg/hkwnjwq7RR1Ji6+p1QIbkmpRhvAq' - b'/taBAlY9+sDLUhpsxzyTkv3/SiwAz1dg7a8WCYfCspUh18a8dShDj0IpOuqwoTFt5KDj7JOZ' - b'wIHwewHqRIoYA1mSbd0rnMLI+65t0NLzRKxMhiueO4ECSYVtphv2+FLSY9KZ3wS2eNI51V/W' - b'B6C4wittMm8JGoV+nubOR6gdBSRAaknlKFOfTYJkM9pql0r9MVm3RkpNZYrQNRRYx8SrOxaR' - b'NjK7UUP31IeX4RLZaVMBbBUSVgPePx+E+AGGDQkMq4qOUBsKiJZ+2jXoTJBqg7mTsJB/sUMU' - b'/E6id0EyEnCTx2UruMECmIh/aZFmmnJbRAHkHpVUAD4EsdfshDkHO/fnWcwHWBMUQEH68baG' - b'FFBFWmXWEG1E1Z0pgLAaz8xZSEER/NwQoDRAIaTWApQ11hRX/YhJmhtPF0DbZguUmFqqCPWj' - b'gLoE6kvnzly3h+aK4/GkcLUHj0qaw2U4ObcXV/0o13Mxy3d0v0aScCxrJygBVdQaUkqhrAKw' - b'mB4XM9YexEvtJ3WkEFiYeK4NBVRhEqrclGRoLdPazOtqBM7qyuIbTilwvasUlKYOxfO4Umfh' - b'qCZPlaYZw1VOAaP/s6v5JNx/iEeXfVPS/28LS8kugCJ6HqGyPbIRbJjxEHuuM8Y4Yp88Q7SV' - b'QHxfOQWsIiVo29Dm+sz3JvwuWt89YWzY5ELYTBjLYU574pcw5VgbfQpGsveBZudJGUgJ6FwO' - b'CvO0kP7lRoaFBzDjT5+J0xJnQSV5CiHjb70o8PQ8MC9gVyjWXuR3Ay6amhdtvSmrACyqtoba' - b'F6/iw48zzXN+UAD2Lp5rQ4G0oD1FRX7xOj7ccTe4ETaHAjj1KOc+fCmrCY/Od8GkKIqBCb8+' - b'tvFzJhi9+QZCLUtCMtT4zfP52OirGCliwlE5JVAyT5vARbfwNPJy9SWV5alYPuOzjlNAdSSr' - b'TBvC3stmNvoQTNE9ANJJVeoDsDhasuq/D8j5HqwAgRI1BglP4m9HKCBaSqC1nfVBzKb7we9C' - b'az1uGlOEEdrbH2Wvwcuh/wPlUzGG2I7z9ks/QfgvIjzMMX4yO21x6PotF/M9AN5pgZcsgFL1' - b'2CJP7wtfEhqFBTFuasjTHx8hT5e1zBPFiNCJFLCu3FImj33zXyRM/99P4a+wIhDjysAjpfK/' - b'cy/+QBITWOLhLv62lwImtNLiP/wtWGbzGfYjWTJMP24pgqzj8Ek8p3I/8VPn1tMCS1mopS8E' - b'E2Z9H+6ab7AdF8I+kZZ+CTj0ifAxWBMHv5Zlup9j6y31FxMo5BfLk+Z+/Ahl5Fi+/EJa/BWp' - b'PB05mefD2Kr8Z+ymjKWiPGWL5MnSiOfaUkB1Zl24h7DO1+GjG4ul7s1/6qIkpGYCVqwAhHQc' - b'/b0lj8E4tEaCcq1HCBF/K6GACa2GWa97kBi0+k9v8Uu6/TiucMzdSk8AYfvzE8E3oGelhFbv' - b'HiScug4SykX4E8QPquxnuGa2KA4FPMYwjUBhCpFZnlbh8/mZrA7m+c8lT14xKBKJP8H93iOx' - b'TlAk+hRZhM6lgJSt6k6z/26+h7QH0wOgkv2n7cplRfWdQEUKQOGFtI9C42H89d/CpCCv8Qu5' - b'0DDHc9UU2IFkLmHvBUlrnyS2kVf9OhpwxnfCOgFdpupRtzmQkG6FKdIgPL5xJpIsDSWwFQFu' - b'C3yehIt4XilwNjxiB58H8qy1CxG6hgKPYzH+5C8YiKPDJ+B9XVWYlYoUgGdCaloflRzPwo8b' - b'/kwLk2o9rLWoMM0YrAQFfEusdxDcC1ZBOF8PPMuFK3ifvvWmoUVIXhhOHx8pNvMxHa/wOp2W' - b'xbcwuvfKgHM6nL2P5/pRwFtiSO8OWoWb/kY6VIS+TaF5O4X11CoXqdWAFSkAIRBS7RDkZxjR' - b'FfjJbWH3VlV8VACtSNyxB6JpEQy5ii32skj4znjUiHnqjHJ3dRomc4/N4hPvN9H6T2JbdfXt' - b'SvBOqfxWrADEcxL2+SQyifHfn+AY+qeGHQQ5Lgi38bcHUyDyQt0r31p/jfRcdyvJ0ervRZeu' - b'zb6/5azSTUEtvJ19w8MPo0eMUTHMdH3w/sqULOaRtnjxXBsK1KzhrxmiIuWqJ+4iyfXER9b6' - b'30cD/OUbmZczgZEiCSVyWBH5U4EqtgCM0LIClpHYpBF8ifZOPi99R3gTuwJGofqda9a41gxR' - b'kbLWE3eR5HraI5vkpaHgL/6K0tMdN89/xbSodiJQGrEpj80MC7pJfE3nRwxbLwjdgzgvIE2p' - b'nnkd5b9+9W6mv1L43Z+d+z3HZCxxNchVdcNTlVS1BWDF07fo9M03t9K5r/0y7GKjzSxiV8Ao' - b'FM+RArWlgJn+cvxd9l1wM19Em37Y8ypSs3bczw2pIl4qKFpEDsGpk537+s+d+y3aSBCnCAc6' - b'1OM3V2v1QF4jnM2QxxoVtVPRaO6GZEs7/n78ByT9HA0wMzy1X4e63+2FdlsAPk1qey0aKMNm' - b'kBd/KZl9Rk6kkdqhldpbhh4TrwP13JJGUUpb0qPB72RV256LP8Tp95s/8FWpcTTAKAHve6s+' - b'/zlWarcCEA/J+78ODTRen4FiEsKbvkJ/hC2JpKliV6D6WmkrRk5uc9XXVowS7zsavxjaeuAs' - b'lk4Pe6aG1Fr4W+5w7l1fZb7/Ie0b88+Rrj1rAXKRUxcoJp+5xXQFpg0PFsA136ZfwhTT3r2Z' - b'OCRHYYTKKZCTcOhaLlYqXMlgZcJ466xsAiWxln5h6dm5dMj4pkIKmCUtBXA/a3DO/gwRJ4XV' - b'ftsRvnZXYXtmApbKs69vcjKXueDTpzj3fWYlffFHZBLPpFcC0hIRKqOAahTFKdCnnQVWydKl' - b'fex98rCkrFk44SrAI5weFKYS+89wcTZ9rkcCjL+QXaVjD/UiQocpYMIva3rWAlZifhKUTPaZ' - b'wAKvVUm/v2T9t5V6rSyAwnTmoQSmYZ58/DuMDFwXthFX3yVaAoWUKrhPhGcoK/TOncA7HD1j' - b'2XBDwutba877UPnPa7gHS2skczAExWRO4fV8ynh+wKPvOgygDoyh9HIw3TVHV23aRM6ATyNc' - b'tvodygqz8ybxeD2rQWE+zTqzPKnrt5o6d6OZjMJS5Qi1oYDVlYR/wVL8a58G7xoc7qwGlbXd' - b'zn5/OnM51iGJ2oAwah7AEph08mHOvefzYXRA68ljd6A8jUU7Vbp26HnjWdz8HQcPK+ymI3BT' - b'UQTTOPsVfP8HTc9lff+YgM/6hobdMwZ4BC89xrnDTnDuyaepjwTPFHAdNIAvEPHsoJMJ84IQ' - b'VmmXwrUXQ71vUJ4eDEuUpxNfeHJ5upk8nRe2BxO2QjwhhfhbKQUKhf+ST/ENydnwwig25X2u' - b'JsLfIisZd4GSrA0YIw9CrajFWky/5dp3Ovf214avx8gSkDKI0JoCJoQS9J8hVJddSxi1rtDR' - b'L7mj8q+5CifQ61AUCKXNCGuNKSgTCeJ/Zjl3yec4o1A0Y8wD/plDjmWrsPehIPbPt/7FBLdo' - b'nsiHHL6+P0BrdM1bKstTSDz+lqOA6lT1oEOT6/7rM849IOEf59yc2gr/DuqwL3P676mpAlDh' - b'0kpgOMy7kM0i3nu5cx+8kuWKmJPpQpYjRk98ZwKnsj/yFIutHgnfZByEZXD0wc696AimfULT' - b'csKvuKbSxUgrVvMp8vvDl530bipdA1kHIzHZ0+H0rhjIqrNlw8rTfeRpzTq+XoQSegF5emGF' - b'eSqGOz7LU0CK34b6HqDhPIaW363C0qJ7NVdKV4JVK8jivulH01IPBaA8mhLQHOWJ9BPnwDgz' - b'T3bus29N+qaEaYuJa1XWZsOTVgLKe1oA/T2Mor5hW1Ao3GbmGR8Vvi+Hr1UeUkpB8WJdlqNe' - b'+XeqB9HXhP/WO5w7U31+rCz1+WX211T4lZ0Mot8nWAAVsJJiVAeUx5sx2kdwDmbs/gexicg/' - b'2Nfu/WwgSWsksLkCxojhafxVq+2ZAkEXWOsrIdPzSoRf8cyUtHgSfFPMembvFbYtUB5qkae2' - b'0ulp71UPAgm/dnD+358i/O/mAd21iXvn+/w+UC1/OrIYqNJ8eCWQBJ61DW02kb3LNmJ+voOP' - b'F/yaAm8NzCymNEJUiru7h5NwStAldHboXs+rBVMYhsdwV4vH4hkendubp2rT7m7hJRvyhxn9' - b'NMz3Flr9d36Rz8XvR/cMJ6v2cfSKtz6FVxY81NwHYIhbnUlyLGbNVrTeOvo4r8Wb/cHL8EZP' - b'CyH9XGcYvD1M3iqt+CBSoEEpkLa+NFfmtrsY+v1fMruB/v4ENm3FsSoZkRzkpLT2Zck5AWlX' - b'OgdUIC1bVLdgv6PZyeRutqfGGvjVrRSYfo7MIIURgdS6RIgU6E4UEE+Lt63V1/j+1V9F+N9J' - b'KXHsTkX45ezbSrg6C7/IiqQF6DwLIEnVyzY/GkfWNtNuLuPMM517x0UohOkhU2ZmilgRIgWa' - b'mQKFvPwcLfwfafzO/R6lWujcZCzgLSiGlTSOnSD4gZT1HgVoq8KkfkQYDRNqzoC+N+cY6vre' - b'FRDmFcwhGBowpM2ltnDG95ECjUaBQv7V9t3fvN65b91ATifSCDIsPp++vo2yoAc6C3JdgE61' - b'ANKlMyUgR8eEfigBDXcwXDjjREyji/neHLPU9sAZIoj+gUCH+NscFJDgC8yCfWZl2C/jrT/i' - b'IQ7xiQj/czSAK2j1ZYx7WVCEzoLUMGCXKQCVNVdwiDGEGYIjcRLOZvKDdhl6ywXOvf5s5446' - b'OD9GWqhRO4teMZ1IgbYoYKa+zHgdAn0u7S9/d+4jjHrNeoCh/QNZT6HGjm4ALN910NVdgJIl' - b'hypaYCL6LV7ID9dXn+fchacF/4ARtlDDlsQXX0QK1JkCxQRfy+HvZb7L13/Hxrl/IwNM5d1/' - b'n+Dh38TwX6f19UuXveu7AMXyJp+f+kP6BNkErIFFaMpd8g8wMeJjDBuef7JzB0xtaREIj5la' - b'uo4QKdAZFJDg+xl8aq2SFn/DZqZKs1X3d3/P13r+ynOmW0/gQObdMnhZ4RS0S1t/0icTuZmA' - b'XdoFUF4KIUcgqKRuwVAchYtxlGQXEBLn4P9DEbzqxGAR9MdCEBTTwuFN/I0UqCEF4EkJr/gt' - b'3ejoA6paI/EDhrRvvp0Ao2j0h4ewK3ayLJ7wDdDqpwmxk4nA9VsLkE6pFteD0AqjEHZ92Xbb' - b'AjAOcu5tdAvORREciY9gqK1045V1D0Rw6zLUIg8RR8+lQKkGZuEyprbTt/8+Qn83Q3sS/Ckj' - b'WcSJwD+Lg08tvwBW7PpW3+ck+WlYH0A6k4XXEHUgXYNxjAxIEWxW1wAKv+oE5y46ybljj8Lc' - b'Gt0ykimDtLZuGSLeRQoUp4AJvd6m+WcbvPcUc1f+/E9msv4FwX6SAAj+VFp8GnvfbfXSLqlv' - b'VGhGBZDToiiCvegajMBHsA4tuxbzy7Hk1e3n3GfwEbz8RcFPoDXzBqpMG2uNVoFRJZ4LKWBC' - b'D7vkVucpjO6XMzKlL2LfTEv/gzt5wFoWCf6kPeEtLhdrSI+ADWbqk6ki0Mg+gCLZbfEorQg0' - b'iWgoykBzCZbgeXVLOOgqzHyZc+dgGbzgUMZcx7AtVuIrECKzCkwR2FnvIvQ8CnihV7ET4U3z' - b'g4bxZs3HvMfM/987sTwfItwIeqAcfos2JH8lVqhwyM7P8Sa3DQ3NrACMsGliowPcYJTBMKyC' - b'rdhh0tZuOQdWwTuOc+6kFzh36P50H+gi9FXgBHKVz73wpSvfwsRz96KAF1aKZEKrxiMNGsKb' - b'tyjswnvLv/j25X28VeMygZl7Q+jfI/T6KtY2CX0CaV60Zw19bsYuQEUEpVJUoZpL0B+FMHsT' - b'sVZwPMeBMnjPMc695MigDMbgrOmPwkiDVwhJxUoZRIWQpk7zXrdVr/raznysxwefcO5PtPY3' - b'PEhZV3EwhLcvxz7w01pMfO3G60ES38zQXRVAThMnQrwvQ4hDOLZhpj0jLS5/gfpuk527ihWJ' - b'Lz2C/fFQDOPoyw2mL9cCwCG/gcAUgZ3D0/jbqBQwgVf1iSfSTjzlWRvValuzeYsR+iedux2B' - b'v5VhPC3JdcM4aOm1kariy5v/HK2+QPWfsER40Ly/jTkRqFb0VKULvJnHWVuT7c2h8y5q8BlZ' - b'BKuTYywTjBhBOPFwNslEGUwezyIlmCDtNyCkx2X40oogfa1wETqXAlYndlbqhQKvZxs3U+9Y' - b'g7MXstEmQn8T/fknHuOFJujQAAxA6PfFIpSAb0VBrJXQ6wZmEj91E8GnJB66twKwUupcWHl9' - b'eTCQQ5OMpBCWMayzTZbBsxwD6eodwPwC5hYcxXn/yXQn8BvsuzdhC7oLwi2myzEeOPn3EJVC' - b'QogannJ0Bqddi86laK0ttrQhqtbdPz6HiTpPOXf940ReyDGAgy7g+MEoevhAn7rXV3a1QCdp' - b'7AnQmnf8w+7x01wTgepC80Sl74ES0CIkfTxjI328Z/D8+q6CugwI/sFTGFrEgXj4NNwIk4JC' - b'2Ifne6IsSkELxUAgY1I7l4oXnwcKmIDbWU/LCbtM+o30459F4LW0/Kn5YTvtX80mIn17Jr76' - b'ulR9TkX4tfnMBupas/SsleeqJ0FUAKpttdheDyTKQGsQRtAiDODYSVOgj5zsls9ASkEKoT/H' - b'OCYeoQyOlEKYGIYZ9VWcIcxGHKSWpQSklYKSU9qmEOxcImq3fJwWbk+bhCYqbDET3oggYd9M' - b'naxdj7JmtEct/JMI/H1znbtzHqHkvKMeHa27w6+zL335wX1CPauVX8ORs+dlQaRuuewp0HO6' - b'AJXUqJhAkFYGEsohMJIsA/9NPt6rb7iGLoM+ueWtBPkSEP5xk5w7eTLWAufJ+BTGYl7Kj6DP' - b'aslSKPQnEKsFpJVD+kUxxaBnCl/sXTpuZ1+nBbow7WLvlP9yZZADdhv0Vd9dwi5zfgndtDm0' - b'6I8swGnH4RZzbOOg/67WXVPER2PNqZsnU14f0NzMoW22otBDgzxEBZCnResr+CfHL/ZWjUo/' - b'XuzBoSnJshIUbj1WwmpZCRt0wyGzcigHvoNTUQYHckzmeswIuhooC+12ZIphAK1TX1qnSiEt' - b'SOnrFvEt8zoDBbfhYQW/kpkWYA8Mob1MpaNH5YTaothZKJ9HoWpPSJnwmnizGn/MclrxJTjs' - b'5i137mFa+EeWEZB7P5yLkHthx+LShzI13KsPqUo5a2xe8/C172QhFGa78H0Pu49dgA5XeMJk' - b'6jZohGFPFIKcimq5NEV5tawDdRt0qJUSyG9AS3UQyuCg4XQfOMZwjMRakKNRX07ScOSeMPkA' - b'uhN7MP4s52M1SsKn0wA/ooN2vd3BIQHfBg00yUaCvgZFuXodgr7GuaUI+wKOv2DO76aV94pU' - b'Vhbl9vSCHt45Cy0GJKa8hnU3cGxUM2/CniginkRomwJRAbRNo/IhjN88/xkTJlHUKvnuA0pB' - b'3Qe11jJH18O0mxEIP/QkJpeS0FlWA2EdLZr6rnthJRyDQhjNeRTHvpi4eyEIwzn3J8xgFIQ+' - b'JNobIRmAX2Igz/TNRR1SFvp8mO9Hk3aGvGhylA61znrOyYO11sqfiqCzBNefya9/ntxrH3sv' - b'0ORV06kl2FvI/3aG0XSsx1SXkOt7D6uxhjZzvxwhX8X1fM4PI/TeQuK5L79yICFXmXXIv8K9' - b'5m4MEt3Ip9JXa76FtNcn+SFUAJXHrjkTLELlFIhdgMppVVlIY8YcI+YuiM9L+Nr7E/pzrT5q' - b'bw7+c7ADBt/GoZbNKwQpBo1RS0nokJLQvSLRGnqBkeCgDNRCShFM5H4M1/tw7keY3oky0IzH' - b'/nbNWV5wKQQvZESXw1OCv0NCTjo6nkPA9TnyHRJ4js3kZyUCvlSHKS4Js7o/llcpN3D7/Em4' - b'5RS1vCb5Gcp7jbwofYHIJEFXsSXsooGfZqsXaSB8EsU/LXydDhqv26RAVABtkqgGAYxhyzGr' - b'wkhmpBCkJOwsJaFDQmpOSIUTLgmshEVKY5UpDK69FCGsXlnouQLbc53tWs/tnTJgh88I9zqn' - b'r/VeFoqEWplM3u/Jtbo+yp+6P8q7oZZQq2+uzTDsrGtlT1nThCxlJwfct5Dw5FaPI9ScArku' - b'gKozQp0oUAnzKowJhBp4L0Hp/BRDgqBJJtWKylzWZBaZ8xJArzQ4S0YFes5/OFLX/p1+AEtC' - b'Z2/2J8/sWmEksCbIXo9wr5Zaq+FygiwEhaDEK4Ei4YqhqwRVDFM5BaICqJxWXRMyEdrCxCUc' - b'EsotOvSyM6WliLD6RwXPOzNLhfSJ92UokKqYqADK0KlRXqXqq3SWEuErkMHS4dvxplw+yr1r' - b'R1IxSj0pkEmaC85RAdST0F2AOwpiFxC92ZK0z4Nn3W51FSPPNFsFxvxGCnSEAnkL4HkpgHpa' - b'jR3JZowbKRApUC8KBKnfnLIAoiFQL1pHvJECDUmBrFsrBbAijBllcqM5DZnZmKlIgUiB2lDA' - b'fADIfi86ALP9JA8cArXBHrFECkQKNC4FsPQz/Mngz7olvfiZ570A5hho3JzHnEUKRAp0mALe' - b'0u/tp2T2cgvUBXg6GQeIzsAOEzciiBRoeApkfZc/61iiJQWQdY/7uaia5Z1NVEHDlyFmMFIg' - b'UqCdFNjtu/ws0iT+sl4s8HiS3v8q/zCTqIJ2Yo7RIgUiBZqAAsHWf9TdkNnWy/3KLSLLjyWr' - b'R6IjsAnqL2YxUqCdFJDrr7d392fdfcKBDyCjh/d4R6C/122ESIFIgW5IgV1IfC8cgJv4NQVA' - b'MTPuDjab2M2ZtQEZrU6NECkQKdD9KJBNuvoPu4PdEyqeRgG048z9/D6aOAdiN8ATJf5ECnQj' - b'CgQHv7Z10fj/7e4ahgNnZNlvZma2t7slo42dbk26AQoU+wEiVIRIge5CgQwWvsz/HW4zcn6L' - b'L9Z+2jJy78QK2OV+w8stPlBqk5fuUv5YjkiBnksB354H8z9Ld/+GzGOeFt91O3s5fvzNbzOP' - b'cv5T0g0gRjQCei7DxJJ3HwpIjr2jv08yyP8TX7Y3ZtnhMZMNowD0BfzDTE4dyBkYfQHdhwti' - b'SXosBfyg/06/metu9wAWfjD/xwR1EKYEuCxnryWcuyD7JyYHvYLugDZ5Rkt4DdJjyRcLHinQ' - b'5BSQAGdRAL0Q+csw/3/s/X43hNG+MAog4TcrIOu+mJgK2gQaKyDREU1OhZj9SIGeRYFcF17f' - b'AJDw34/775eeBgfn+/eJAuDxDD8/yLkbM7fz+kb/QYewjXvPolssbaRAt6CAb7jVje/nG/Td' - b'7lr3h8zzvqHXEGACeQWQjAv65zvdJ5gYtBm9oe+6BCehxYjnSIFIgWahwC4vwVn3Oxr2G32m' - b'raFPSpBXAHpwZ2an7x9oRCDjPp+MCEiV5OyJJF48RQpECjQ2BXbSgPelId+Ibf9hn1V5/lOt' - b'v561VADpAs13n8EN+E9QaGJQYgVEPZAmUbyOFGhICoRZf72SBvyjtP5PeNP/uxk59ltAawUg' - b'76A0xYMEzrqrkslBfblGCURjoAX14k2kQCNSIIPU9qNx3+Fudr/JfMVnscD0t2y3VgB6I02h' - b'UYEbMw8j+G/3cu8XCsmdEEcFjHjxHCnQOBTIWefbGfLrh/Brq7//9vmTLBeY/pbvMtLsJwkF' - b'b+EF2S+B8n/oT6grIKVRXHEY1niOFIgU6AoK7EAyZa0/R1N9srsp83ffkMu3VwLKCDJDBVoo' - b'JPhN5l0I/00oAc0Y1HLhnLrR6wiRApECXU6BnbT4mruj2TuXVyL8ClpGAfBW/gCbIPS8uwQl' - b'cBdKQIlIo0QlABEiRAo0AAUk/H280283lvqNmV+6a7Dg7/SNddnslVcAiirzQU5BLRnu585F' - b'CfwjpQSSCQVRF5SlcnwZKVA/CuzICf8O98Gc08+nl0zvL5N2GR9AQSwpATkHz8kOxQa4ieNE' - b'lIHtHhS6CgVR4m2kQKRAXSmwHRtek/Vk9r8H4f+iv1brX8Lp59+nfipXAIpkSuD12T2YJ/hT' - b'kp6JEhAkC4f8dfyJFIgUqC8FZHLv8N7+nTTCGXelX+SjNOW3Sxb6VJKF6hSAMJoS0PUF2c/S' - b'73i/LsmG5g30ITPV4/QI4k+kQKRABRQIVnc/JG+7W0b419Hy/xWXXMZdg+xV2PJbOu0TVjkG' - b'bWjh/OxFJPt1ugTDUAG7UQLJ5qKWRDxHCkQKdJgC2Syf9MQfp2G+MDf3L5zf4H6VWRhafeTO' - b'lvRXkVj7FIAS8KZGkujM7P4I/ldp/0/xYwOyBsIIQ/QNVFEZMWikQAkKSJ56I/qa3bcdGfsU' - b'63U/4QXeN8byxbXt8CuGu/0KwGPD7JhBxvLWgGYNXo1vYIRXAVn/ixLwk4qKpR+fRQpEChSn' - b'gPr5wdzvQ9Mq2MnA3m48/Tdl/J7+bU3y8XHa+OmgAkiwp7sEM7OT0VDyC1zuhwulu/w6Au8b' - b'UHptDz0maOMpUqCHUUBCr0PD61rMExb0bHdzefo5Wv3v+5Ze1rc29aiyv1+MlrVRAMIcJh4w' - b'+SCZdnhe9hhE/p0c52O69PdFCvosTEvUHqXRYVisTuKzbksByXZRkZPASzp68bo3fwF2ugVc' - b'fIdn38Ozv9Y/TDvhk2AdORXNTUcQtjJLXpM9iqJdDs5zMWTG+PKH4ooaNkdZVoGO2ucHpBEi' - b'BRqHArC9lutm/J58oaW3WXziflnMzv0bSfgZ0vFL99vMGv+khq2+x5f81EngCnwDSuzCrPYh' - b'PZOin8XdsSiDfbzIiwThkEKQFtRZoLwlSsFvWuofxp9IgSahgPGxuFvXdi+eDq28NXmhmzyL' - b'53/luNmtdn/LWdISfEEVY/s+fIU/dVIAlnqiCIZT+HQBzs3uBwmOJ9RLOI7mmMr9oJzpY+Qq' - b'JJ2hjedIgWaggDVhJujKs3g7rKRZQRP3JPf3cb6bp//OmfkKJ79aodzoeY2hzgoglVsVaD+K' - b'WrgrySXZQcwqnIzw6+1+EGQK57GcRxN7JMcQjj04NJrASdB52Q7pxd9IgUooIP70vGlivoXb' - b'NVi4z3JezrGYAHM51NrPdTe4JYQ3puYRDeYbfUd5Vy0cfCBsE/4/lYe6PwkK/i4AAAAASUVO' - b'RK5CYII=') + b'iVBORw0KGgoAAAANSUhEUgAAAQAAAAEACAYAAABccqhmAAAAAXNSR0IArs4c6QAAAERlWElm' + b'TU0AKgAAAAgAAYdpAAQAAAABAAAAGgAAAAAAA6ABAAMAAAABAAEAAKACAAQAAAABAAABAKAD' + b'AAQAAAABAAABAAAAAABn6hpJAABAAElEQVR4Aey9B5wdxZUvXFXdfcPcyTlnjUYa5SwhRBAZ' + b'AxY2Tgs2YMBh7bdrb7B3P79d7779NvzeW+8+f15nG0y2AWOTQSQJgeIoj+JIk3OO997urqrv' + b'f+rOCCGD16ztNeGWNHPv3NBdfbpO/p9TjCVHkgJJCiQpkKRAkgJJCiQpkKRAkgJJCiQpkKRA' + b'kgJJCiQpkKRAkgJJCiQpkKRAkgJJCiQpkKRAkgJJCiQpkKRAkgJJCiQpkKRAkgJJCiQpkKRA' + b'kgJJCiQpkKRAkgJJCiQpkKRAkgJJCiQpkKRAkgJJCiQpkKRAkgJJCiQpkKRAkgJJCiQpkKRA' + b'kgJJCiQpkKRAkgJJCiQpkKRAkgJJCiQpkKRAkgJJCiQpkKRAkgJJCiQpkKRAkgJJCiQpkKRA' + b'kgJJCvz3UID/95zm/XyWr4va2iEnFusVBQVZfmPj931QQ/++KbJ8+R3O5KQf8n0vzJgdDCgh' + b'BLe0ksyLW2z69Onvj/2+55A8/jufAkkB8Lu4RzfcYNXuy6oUSlZqpucwLaqVkqWc8xzOdToT' + b'Isg1sxhnHng/jlNGuebTmvNhwdkJpdh+yeWhU6fu7Hg701lQdVuBq9Qy4VhLlNaVWqkcpVRE' + b'KZ0CEZOCY6UyzkNacwdzEZbAWS3u4yGG19q54I1M6j1cyG6l+BQmODolo+NpaXVTTU1fx1x/' + b'/4Lq7Vxv8rO/ewokBcB/iaY3WPOqs6uVdhdLZq3R0l8LBqoVFssPBBwWCuEnbDMpfT05Eccj' + b'B51J6SfIrfEUTGp+6PQQFnhXd0ul9rqu96T25IiwrFRu86DQwrJt/AQdFrCYVIzFuGL4Nj8f' + b'R71QSl2hNAefMxbGOVNTHZaaHlThoCOdICRP0LEcx1JSaX90JKq6u0bFxIQfgNBheJHOju9q' + b'H1+P4a8JvDYFYUKPE5jnFD4QxeSmtNajnKk+ydkgV3zUYvYwd/QEvjdlhcRk2E8fj2gvWn3e' + b'SPyhhx6SdF3J8c6nQGJFvvPn+QefYRW0rcPZcjDeBcr312vF6qBBcyOpQZaTG2aFxeleVlbY' + b'J96emnT12GhU9PVOiKGhqOX7ygHHYmhtCQbm5Co7K2zDJeDhcIgxYUM2JH7AfEz6sNM9/Liu' + b'YVIlPdbf26cnpkmCgA3BuGBoZjuMFRamxSursmVldQ4rLkm3I5GggPDhgYBNx9D9vRO6+eQA' + b'P3FiiHV2jPLx8ThLDWLy1en8vAtWiMo5lSwlNZU5toXZSea7ksVx7ljMY3H8TE/H2fjYNBsb' + b'n2ZDQ+NseHiCjY9OscmpKItNx7xY3I+6cXc67vrTvu9PQ1BMYGqjgvFBWBy9TFidtqM6LW53' + b'iaDVnzoh+hq7vz/9B7+hyQkYCiQFwK9ZCHV1d+RCfa9XUm+Cxr4AvFkRCgdYXl4Kq6zKkuWV' + b'2V4waKmR4Shrbx/hPV1j9vBw1ALzcFLpkbDwczKYzM+y/MIswQtzBM/LZDwng1tZGaFgaloK' + b'c5wAE06IWQE8D6eyQCSLBdPzWSgtl6Vk5LKhMclefnGv+sG3H423dkyFLFsoML1XNy9f1TcU' + b'8NLSTCccDliYH8wAyBKYAsND0/LggS596EAPb28bFfG41PlZQtZXWGzpHJvVlQuRn+2I1PRM' + b'bofTmRNKYWPRkNsxFPAn3RCPqpDCpOzsrBQIqUyJR5GenqLT0wIMTC00zuL5WrieZtGYy8ZJ' + b'OAxOsIH+MdaPn4H+UdbXN8Z6e0fY4MAYGx2dgCCJxT1XjsLuGbCEaIaFc8gW9v5ggB0V4Xj7' + b'wYP3kLWRHP/NFEgKgHMI3tDw+VTPi61hnvggNNoV0Pg1aWkhVlGZCYbL96trc8EEQnd3jLKD' + b'h7rZ6ZODNrSqAMPDy+YsHOJTc0osr6HasutKBS8r4FZGRNiOxSwobk5WNxQ85Aq5AGSCY0Cy' + b'0D96hDnOAo5gE/GAfO1kht6y37dOHO/iEDzxhgUF7rIVpVZ5ZaZTWJBrFxcX8a7uXjYyMsoC' + b'8A+I8Xdub1O7d7aLQVge6SnCXzXfjq9baFt1pZaVnYYIAGfCx2kh1GBFKKahrulf37B0j7Up' + b'BYEjoOj18JgSQxMaQQGh4ogawA9h6WkhDcGlsrIiPCs7FVZMmsjJy1S5eRkiNy+L5+ExMyuN' + b'p0RCIhyCsIC08HCx42NTrKNjkJ043s1Onuxmp/BDfw8NjTE37o3AauiyLOuoZVuHLJsdRrTk' + b'tBW3+1XInzx+/McTCSIlf/8+KJAUADNUnTv31mLm8xvhtn/Cl3phSkpAlJSmqYaFRd78BYVW' + b'XkEq6+0eV2AwvbexWwwNTglYzYwLQUfAL7AuBha9jzAAt4WG740IYApnRTlcVxYJVllo8fws' + b'xtPwWghhOQdWP3jeOPZ0EMfmLA6rf+sBTz7+aly09Xg8NzfFXbGqPL5ydbmVl58asm3LnlNT' + b'y+bWzYFZPs527tnN+npH5J4d7frVba0cFgivKLT8lLDQk1GtMyNCgxdtnEumhHgAfOzbgvl4' + b'bmVGOKwSzsC3Iiud87Qw5oS5YyocAkpH41yPTCo2OKpU16Bi3YNK9w8rNgLBMDEt+XRc6WhM' + b'8zgsAcQ5QAvLuB7hlABPw0Xm5aWzsrJcNmdOsa6fV6br6op0aWmOdhDTGBqZ5qea+9jefS3s' + b'yOFWdvpUD6yGUTY9GUWAg+IPehTUmeLcOgb59LJS3hZXB/pSU+2JpqZvTxK9kuO3p8D7XgAs' + b'Z8udyepln/ak+kss4aq8vDBbsLjIXbCoiBcVp1skCPr6Jrxnnzyq9u/rtmzuq/pyRy2ps1VN' + b'iRBTMe1PxZgdjSsZi3HpKTKNmY3X/LEJxUcmNXxqaF2pSVxIuOaKmC8FeYFIiOm1CyxrUa0V' + b'BFPqY+1a3vtcnB1s9kQeGH/9hkp/+cpyOyMrHEBwUKSkRNiq5cvg9xew1rY2tnv3XrVje4va' + b'8uJp3tszyeZW2P5V5zl6ea1tQ/iw4XHFwLiqa0gbjQ5L3Y+7WkjJnGhcexAQHPPUZJkgxsgg' + b'EFhultDl+ZxXFgpenCtEdrrgKSF48hBxZLngOjSYXcMFYHGfhATj0zEtcWw+BmExOqHU2JQW' + b'sCD0INwX/PBRCIy4xxHvCLKS4gx/6cJ8tX51KVu2pNyqqC4VVjjNisYt3doxxp5+qpHfe/dm' + b'PTYWT6xNeDbIXzIQfgJCaRgWxRTMllZYDNscy3ryeMsPD/72bPD+PcL7WgDU1t5Wqn31v5Wv' + b'P1ZUkqrXX1DjNiwstFNTQxaUGYJwUu7f2+U98dgRa3hoSqycF5g8f5FjFeVBeSMMTla7ZXEB' + b'5iEm0ZEghxYno4Ci8ho5d65dnynDOPDRkSmQ5Dcjxkb+M54zlZPOHQgE8eQOTz78UszypCU3' + b'XFjlXnBRrZ2RGQoggMjB/KygIJ+tWbUSUf4IO9zUxF54YZf/5GNHWFPToKgo5P71G0Jy9XzL' + b'AY/ZHpAGFHPENAzz0GPiFWNwmF+w/BHLRAgfAmBoHMw6olXviOJD41qBYQVifxSPJGHF8jI5' + b'I2E3r0I4GREOQQZRNvOLHhPXSy+QC2Me6Pza97mejms9jhwCWQ8nOnx9tE3yth5fxOKKZadz' + b'VVUckPNq05TL01lTqwy2tgxYnucpWDuqrDxL5cPyysoO87SMkO25CrGGadaFYGZrC+IL/ZOw' + b'TfTzdsB6IORPv3So/f4RmkVy/OYUMPfxN//4e+OTxcV3pMCdvT3uel8Kh52Kq69Z5K3bUCWU' + b'ci0yyeHL65ZTg+6zT59gracGxJxSSyH45kMLEgOThregjYSH5D250GB2UpAcpjZPT+UsK1Xo' + b'3Ez8ZGhRVmDx0lxhk0ww1JuhOAXrSOu29yn/zqdctuuIKyqrMuPXbVqoa+tyQnR8SdF+qOvi' + b'okJ23ro18PMdtmPXHn3fPS/7m585afmuq687P+R+YJ3jZCBpSIxP6UVifhp0LW81iFFhZpug' + b'IdKMZwQFvYZ/2vOYjnlaT05rhliA6h5QMjXE3WV1FrAF5PIkBl1O3GeSri8UAKKAzj9zXjoH' + b'/bwuiOg9rvpGtPfkdi++ebcXcT0FhvcRDLVUcXGamjuvQNfPL4D1lSZwbwx4IRQMmqyHB8KT' + b'sKGZT0zE1bEjfaxxd5fV1TnKfE8egbFwZ0DKe5ta7+qdmV7y4T+hAFHzfTXqq29eCGv8/0Cz' + b'XjavIV99+c83+RddtNzZuauRd3R2Iv0l/Zc2n/C3vtxqZ6Yq+ekPhNTyuRby5lzD+iXuIJ9d' + b'JNJ1HCEDmMQ+zGAXjiuSWzCJZdwDG+LztPgzIRBqS0UEFoMRLkRsIy2QJ0CAz7/vubhAVo1d' + b'cGFl/LIr621E9AOUAqRBp0tFiu7SjRcBWxBgz23eKv/vN57UTYcHRFWxiH/q8hCbXyUCMReJ' + b'fEyEvkMhCfAzLBim8YjAJPEghRYTxzP5f/xBnx4dQUpvbBJCBlFBfALhBQbcAAvQD4QNPRpT' + b'BweySfqZAKY5kvk+zY+upblLRXc0+X5mGhfnL7KDiHvYkANnBtHBgUWF7/uHWqT73E6PN7W4' + b'jusLQZoeMRaNHwaXSzgBAbgiUEzhFJYPq6ekuJhlZ2WxoeFh9sq27QmBAiEAgcEQDwHOIubu' + b'3N4un3vmWEp0mkwfdQKhzW8IR/yyNSkIztyDt3ryvhIAc2tv/yPf9b/hBK38Gz66wv3jL26y' + b'CvLzrWPHT7AjR4/o082D7qMPH+ZtbaP2uoWB+GeuCwqkz4JkrtKChnYD2A62PSl9cAzMfSTL' + b'wMnmvRkSAyAA/5SsCMPAFG0nf3mWH4gRJuEz37s5rjbvjNu5uRF304cXSgQbQzg+wIQzmQEc' + b'jrT/yhXLWFVlGfvpT5/z/+ObzyF6PgEHn/x0axoxBAcmNhiJ+zQ3upkQNKSJLaTXPGhsgUyj' + b'hB8vcmHGF2Rynod0JISScVvATZyEDeX8p6fibHIauX1IMETmgSGA74K50HWA0SAYAgA3BY0g' + b'CoWCEA4BZCtAACNtEsFLmPoqLawFAomCaEKD6ANxKI+1q/hj2zzeeMwNICLJGxbkSwQ2kU7N' + b'FqlpQYHzcQhlw+xz5tSwkpJiRpqfxjTmtWPXbjY4OIi5CD0+HvNbWob9E0cGWGvLkJgcj4qM' + b'jJAoqSgjecRaW/tYT/dgm+vJZxAKeSISijQebft+jzlY8tcbKPC+EAAXXvh1u6ut8yu+5/9N' + b'cWm6/aW/+ID/wesuDFiWww4fOcIOHmjyt2457W19sdmJI+d15dpA9IqVAadvRFonO7XuG1Hk' + b'xwrwhjGLIQzIEtXwh/mcEqERxOMleYKDIcXp071sEqZABH+kZ6SylEgKmAeBAahix9KsY0B5' + b'SOmzI6c9a9mK4th11y+ysrJDQcQb3nBj6A86SWZmhn7l5ZP+Tx/YLVxXijULAgpYHz06qWgu' + b'NrIGEnEGEjJ2LI64gs8EXtMI1nHwNkkrM8AZOkBZiQhXwB+p8nyhywoEL82zGDJ4PDtNcPA1' + b'rBRuGBHMw+IQBAD5QEDEWRRBAXqkeISPoEZC+0MwAPWYkprC0lPDsFZSWID8IDI7IPJsW+vj' + b'7Tr28Muu3nfcDVgI/y9dVuyft76Sl1ZkIZvKBV03HS8rK8NkNirLy03KIjFrxjo6u5BuPcym' + b'piYUAp3e7p0d6mhTnzUwMEU5FLai3pm6aKllL6hLD8xdsd5KK57Pxt0UtmdfF3vx+UNs144m' + b'1t092AlB14hpvWJb1mtOWDY1N983PnuO9/Pje14AVFbeTArxX6EhP796bbn3l1/9MF+8uAFL' + b'kyGYdpi9tn2f++hDh9Xxo31BaBdKzcm8DBMIsyeiZLaSsoeFjFVCP4iLGY1Pi8aY05AGsJZ1' + b'aYGjLl8V0Bct5RZMa05gGBIEEjDfYCDAcnJS2ZTKkt95nEGgaHHFlbWxjZfWw2vmmEsCEzDL' + b'rHRs8ssBI5a//PlBhUAkFrvFrr8w4H/s4gBy+drgCUhB4ztkKCA3QZF2psCvFJVXiMozROX1' + b'wJhm/SOa9w0rPojnY1OKBAQCkrgeCIWgzXVqihEKfnWxUHMrLF5VCKBQlrDgAcCUN6a7sWBo' + b'nmSeE8OSIIhDIk5BO08hdQegj0EwkmVQkJ/O0rKy5Qv7RPznL8ccCadk1aoSuXpdBS8tyyRp' + b'yOGzm+OkpIRZ/dw5rLamGm5HgC7dDBI2R48fY6dPt+iuzhF325YWdfhgDwqcPGQ4hKooslzK' + b'NtC1REJIZ2YzVlOo2PzaFNYwv4hX1dWJjJK5fHAqhR08Nsp2bD/B9jY2s5bmDnd8MnoKUY+X' + b'nSB/EtnPV/e33oWU4/tzvKcFQGnpDYDHp38LzH/rVdfM87761x+3SopLEOxT7NDhw+zllxvd' + b'B+/Zq7u6J4IpYcT1pLIyMiKyrKIQ4JoJNTY6yRF4gt4mv1oorDwJH92Y4FBe0gEALyUctOEr' + b'q717WxCE8/mVq4PyxsuChBEQcZjRJATGAdRpbpvWD+3O41E/xd9wQeV0fmGaPa+hIEy+7ED/' + b'hJ+dHcFxLTC0Nv5tb/eE/+B9jQTftTXAd1eucbybrww4kCec3BEa5FvPDvMUv+iRXqcgo3kf' + b'vj28Eo00HKDEyOOPao3Aoz7VrVjvkAH9sNFJxmE9mACebXGVHmGyLM/yF9UKtbzOssoL4OlY' + b'HBkKElR0fHM280hPSXABNJWwFqan1Y6D4/6LTRl224DD5s7NkVdfO59VVOXY5D+RmU/XSMHK' + b'8rIStmjRApaRnj57GeaxvaOTHQfzt7f3ea++0urv2t5mT066CJnC9Sm03A9usPWqetsmnEN7' + b'n5bHOySj62ntUdb4pObpKZLPLdN6zfygXr44T1TPrYUwqOfTIo/1DHG2Y0cze23bMbZ/33G6' + b'z0cg3R6HJfMYkjZ7ETeIvWEy7/E/EnfyPXiRN7AbrANV6d/0fPX5K66e53797z7l5OfnA+Ai' + b'YVIeYlu37nPvvauR9fROBhbWBOKuq2TXiAjeedeX/VWr6pwpqNHJiaiemooB+gpNiQS+E7Bh' + b'RiNUhuATEuOKHsHAQLVa7D+++Zj/r//6SEBpm0FLyxsucmwyzQnVBwbz/+neadbaq/hHPrYo' + b'ur+x2z64vyvwxS9vcMH84uGfHRAf+fhSf+15VSgMYKyzfcS/9yd7KOVlI97I1i+wvM9vChoU' + b'3yzzz94yeAkIxIHZ4fyS2Y1EnOFIkhH0WTB/wmLBy/RZChLSI73lkVCIwkqAUDjVhTRdu2St' + b'fUpASJC7Y4QR8DzevHLLv2CJrZfMsZxImDsmpkEnOGsE4OvDmvcefUXGf7k1Bqloi8sunwOt' + b'XwkBiRQKND4NEr5A/LFFCxYYzT8rTOi9yakp1gSXrL29Qx7Y2+VufvaE6O+bCEAAkoviXrXG' + b'8Tcutx1CUBNt6TooxjA0puMnO6RHOEdKszZ3Kr7vpG93DmiRFVF8RR3XG5bYbF5tusgpLheZ' + b'pfOZyKhm3RAGL754lL285TA7evh0HAHRwyDfkwHHeWL5mqm974eiJpDwvTnm1tz2P+Mx/+/X' + b'nV/tfeP/foaCfUirSbbvwAG2b98R767v71Zt7WPB9UsC7kcvDuh/vBsYfhlgz2z+B11SkgNt' + b'8/bGyPCEvGzj/8P7BybEinlO/CsfDznQdSLmavmNB+JqX7O0bvjIgjiwBs5dP9zpe4jc3XjL' + b'Kmv7q6fVq1tOs4/ftILV1ecH2lqH/Hvu3MNGhsH8WrAF1cL/8kcArQ0yaOg3zokiXljk8W0H' + b'6XCahwM8COZQWQj6IT4BFCDQfamcR4JAJsIiIYFAGnz2OKS96YeOQ8yE9wk9qLoHmT7SJnXT' + b'aclOdysL8QZ8l0sAhLxLVjn6kqWoTZwJ9NH3YfXrlh4du/PJONt/wgvOb8iT131oISsuTneQ' + b'0jcan2ZOzE/u0OrVK1kpgnyzgzIqra1t7Bi0fmfHoLv5meNyX2MXhCmzaM4Lq63YHdeGEWdh' + b'kNSEp5j9ZmL+EAbydJfy952UqmdIsVLENxZUUXGTZruOSr69SdpTUS3mlHG9dj5jy+cIVlIY' + b'ttLzy3lm2ULkbiEMhgXbsuU46i72A5nYMj0xOb3Lse2fweB76mjLj9peP+N76xlu33tv1Nfc' + b'/kUE8/69rj5Pfe9H/4NXlJfAvlesce8+1nzqlHr4gQPx3bs7w8vrA96ffSwkYL3qv/xuVPcN' + b'us6f/cWm6J98aROaaLy98fNHXnW/9lc/sadjvli7wIn/2UeC0FKKf++Xnvf8Hte65pq5sUuv' + b'rA9jHjgfbGECD8CsJsgtAm4qLTVg9fdNyh9/f4ceQoBLQaVXFwnvLz4RFFmp3CIw0bmDmI/8' + b'fmhASYg/aHFFVgagu3wiahidBAcrzOS6rkyw+kqLVRRYIjMVwfsZgUDmOwkEeqRBgoAsCrIU' + b'KBHQPyr16W6tmzuNmc3Hp7X8kw8FBaDNNmlvfIauz/3ZS64zFeP2JZfW+JdcNtdCpoKqIBMH' + b'xW9ifsoenLd2jQE1zb4xMjqKDMxR1tXVrQ7u74k/++Qxa3BwEhVSFksJCv+CBXG2qnqMRyKO' + b'lZufa7IRxNhnD6IDXBRIA617B7XcctCXjcd9BGkFQ1pSFwOKjVQle+2wL2Ad2BSnXDrHUhsW' + b'cVZfzqxwJEWk5lWx/DnL0EGhkrV2u+yZp/ex557eDcRlT6/09FOBoLi/vLpty8svvwzb470z' + b'QLX31qiruX2T9NUDubkh+7s/+oJesrjepsXXuO8Aa2k5zXa+1hZ99OFDQWD22d/eHPbrK0SA' + b'Umjf+YXrvrjXDWamBeXX/+Em76KLF9lZWWkIvr31gLbyd+44KrduPcyee2avDT/YQjaLfeA8' + b'x/vMNSHrnufi/n3PxuzzL6iKfvijiwjcgyg7oeUSZJ9dyBQHGB+Lybt+tFN1tI2AdSxWli/8' + b'P/9YkBcgGEdY+7cadCjDtGAAcgEQtFSE0YfbofqGgZntlex4h+LQkAzMy1OB96/I54oqAxH0' + b'I7gvByKPk4VB+pSCfHD1jaVAswQfJlwMHJsEApneJDwQIGQd/Tr2wyfiClo/VFKSpq75YAPl' + b'9B0IOWjp1+dMRUcpoRA777w1LD8vz1xKFMHDE82nwGCtrL9v1H2OtP6ergC+hcpGpudX2vE/' + b'utThc8qAc4hDqA2MIjZis2yUV87Sja4bczGuDp0O3zPWDL02PsX8nUd9ufUAipEAUUYFJI5p' + b'KYpxnO6W/HCLsuD6AKjF+Sc2OrymSNm4PyyYmslyKxewgrmrEbTNZtt3tLCnn9zNdu064gNz' + b'8BJ8rW9GlLftvRI4TKzEt1pd77LX66o+vQrs9RjnsuAb37zVu/rq9caUP3DwMDt24jgV88R/' + b'+J3tYnzCd9YvduJfvB7RO63RK4ux3mHt/eM9MTY0Kuk7qqQ0W86pLQEUNUvAh5VIWSkCx2Rn' + b'pwUQF1AHD7awpkOtor8fvTFwUkqHkT2NOJ7/tU+GFMxm/i/3Rq158/PjN9260ka8wCFBdO4g' + b'QRSd9uR9P9mtT54YoM8xuA36+gsC0UuWO1YqUouAGQNwDAY1EflEIO519nrjEemGklCgmAAF' + b'DQgCBHuD5gNhoGUTTPvjrVJ0DKIFUJRqAAzUV9eUcD23zEIhkWD5mQKBNPA+zkrMRsxFSndW' + b'8VLWY3+zin7rkZiF9gDO+vUV3iVX1Nnp6SGg+t5oqpDbRfBlQjLm5uSwyclJdrL5NNJ7BLqK' + b'6pPHB+O//PlhZE0mgiT4MGUJZGP8Qxc4yChym3x6cz24IJrL2cw/PKH9Y21S5WdbrDCLk9uD' + b'2CxcJTAy0Qdy1QitUz1K7jgs1ZFWYB48DYEnVEkulxCGCq4By80Q+rr1TiqtBbJa0MgFcQqb' + b'5RRXsuL563Q0UCUfeegV/b3vPktWDk3iFGhyBNPdgZTnq5JbB96tLdbeMwJgbsVtVSi3eQq5' + b'6/o7PrvR/euv3YicEmcnT51mjY37CO3m/+h7O/zTzcOhXNTnf/2WkAbG3Zk1rcmP/ebDbuyV' + b'A34YisaAYHwsXsO0M9w282A4jhiXmJUeZwcyY+zCZZb7iY0B/pffmeaBSMT/3BfW80hqIEgu' + b'yLnDMH/UUw/c3UhpSIgIiwG8o5bWWX5nPwprJoHmQ5IwFwuWGHMu6vgrYcJnZzBK0SGbwU1G' + b'gLStYdBzTzDztxEKmKbBI2P9gkcl8P7w9bU61S0ZsA7w9aVAlR++wTmyAFQQpAGBZpXFBCCy' + b'BPADLBLWFmqj9At7/egPHo8FnKAjbvjoIrloaQm0Pnzzc66RMgPE9GvXrGIZGens+ImTCPId' + b'Y7E4qqdsS766pcV99qmjiBNIG9AKVpAtvJsucyQKpIKwpIBuSlzXm10Wmfzt/dK75xkX7g+M' + b'f3yI5ryiHgHGGssiywm3xsRNSIAA3Q3ByhQEvTrZCWHQJllXH0OthmaoYNaItTAgPq2SHGE5' + b'SM7C6pBHWlxv6z6PHe8OWCj64mB4CUyHSEsPoWrSEgMD02J8DGVVSrcIYW2xHP0sGjvsOnHi' + b'u11vNud34mvvCQFQUHBTJDM1+Es3rjauXlfl/uBHX0ZBTwqq+PrZlm2vkupSjz/aFN+29RSw' + b'cZa+/dqAf+lyJ3C2aQ3eU9/4WTyKoFGEBMB/ZZB5fPEy20Npvnp2t2997gtrPfQPCJ+rFenY' + b'tDpjxPz3NkoAWxxyA8B86vMfDMgLltoUtEIpLnxaVPK1IW3X0iN1zyBV36HEN5VTJaKuLbFE' + b'SR5HjIBafwGVCNMcWtvcUzI2KLhmBMPZkovOYhiCzOXXLQQK/iH6L9t6JaUIOXxmDmahoiWF' + b'SLumWAKyEW4WtOVPnoxGCorS1cdvXMrKK7KIgc156LpmB2l+9Ctg61avgjZGMG53owH1UF0y' + b'tKz/+M8PAdTTHgTwCP3OuESmYWolvLXiPJ5K9Mc1csQ+CJxE1wPXBLEKXMfZRlRC9nJFxUwt' + b'Pcrfe1zqQwhcUgaD6LNqnsUbqoVAMxYkHrgJgpIFQddNiwKFUBQ0VE0tUu89qfQYBGBtKZfL' + b'5tjs6Z2uhcIlkZEZlgsWFsq59XkchUkWekNQ7YH/2rZWhd4MKKhS4vCBHrutdTgwNgYshNLd' + b'MCl3oZhsM4yrrUdP/bCJpj9Ll3fao1ks77RJvd35zKn59Ne0FP8rK8vx73ngz5F7rrIJPvri' + b'S1vQsWaaHdjXHX3wnsYA6musZXOF++cfDUHjvA5XpfMBd6P+94Px6b0npFmAb3cO9HkyldF0' + b'w52cVvy8i+q8K66aF3YR7T/3WASvRestw/xNh3odauYBS0R/+ELH/6NLAzZcgDORbkIDkouC' + b'9Uqlt3pwnISC0gj6aQT/yIQlHldgBh0CRBh1/YT0s3OzuJWdilLeMFkL5OYk8Hk0F/oCYo9v' + b'YCY6h8kz0rkQTAPARo1BAAFQJBF5R/CN6d1HZBwVi5GaOTn6E59cwdECzX4z4UbMX1lRbjQ/' + b'YfhRZ4GuQKMmCDg5Gfd+du9e/8iRvjD5KeiREL/h4oBaUiuQtlPyeLukYKbuHSGEE7PyYdpD' + b'0PEaxCuKgLbMINcE1wJGS2Qz6EbS3BMxEI3eI4AdS3/7YWkqD2OuEqX5ll49z2a496I4mxyb' + b'GTdh5rtASJLLIPccle5dT8d0R690CovTvI2X1KqGRUUw5EBBqmLCOQmgtXdPp/fD77xmUa+I' + b'z//Jeod8SECpvebmQXn8aL9oOT0cGBmMAqTkj4Lue5Ao/pmy9NPNzT/sJPq/k8avLM530uR+' + b'k7nU19yyDrflmXg8nvo3f3+Dd8stHwgQS2zfsZu1dbSz0eFo/HvfepUDSBIIB4X8608GVU2x' + b'5ZC1Sjd0doCB1D/fH48dbJYpsxYALW5jRxqNMfvJX/9IOfLikoj/2S+cj+YYKHE7W2XNfBXm' + b'r/7FIwe9bVtOBQgmTHNBfwDvavi+xTnMzk63RG46h9ltCojOqI9ZzU0LnoA+pFnBJAD5kHmL' + b'zp3wTyeAxwfiTw6OKwmBQUExaHAIhyACfXCKcB4BhLJAExALlYsC8Aa6uhlXIpERoGm+fq5E' + b'1eKLe/3pbz0yHSwpy9a33LGaIWuBoCcmfs4g5i8vK4XPvxapvVbWuP8gAEJxU0OA1KZ73917' + b'UGk5HIRKVpeucOIfvdixZ/P6s9kHkk0TyDaQQIDfDjixYv3IbKDACg1VuJhbgfRolRDIaPAI' + b'xAisAyAhE9YBXYwNbAAeqC+BBDhIwirQB2EZAAgFN8FiaxfYYmGVZaVHTNMWNjDCvCd3uOrF' + b'PXHbDoblhotq3PPOryRYokNQ5VAY0MOz1gpeV/v2dPgU91kM9wc9F+FaDkmUcAfCKQ6LRj1/' + b'oG/CP3a0H3GiniAgzNSVlboe/dwS9vePnvru4XPI9gf7810tABoabkj1o5lPu56/ft16Mv3/' + b'HNV0YdHW3sFe3b4DEWJL3X93YxygmzA13lxTO642NoxSOS/LyExj5ZVFWOgJEqDLl/6ne133' + b'8GkZJAFAcNfrP7zebdx9gre3D6D3BKnGXz9IsyJ2xFatS2Ur18xnebn5iRjCWV8DepAB5OLB' + b'74cmSpil8K/lFzcFFaWnoPkkotNqHL15UUqs1i+y4JEbM/iso7zxKV0CXYV5xBOyGkjNk2Ah' + b'6xxuAxUgkbWgxgFK6hkGc/UrjdfQIogj6Mct5MitqkIbDUAwKxgd5H/TwJz0lgNy+j8engrm' + b'FqTrT39mDSfUItHn3EHCLisr0/QtaD59Gu2/Thn6IojK0C8xfv9PGoHLnwgGQ0J+6vKACwEQ' + b'hCb/FXwDHZcugbQ6CTsUVBG0WXUPKwmwEvAJxgLiCEaKueUWX1JrcXqk9CbmDrBXQpAZYUCW' + b'AUQoFUzBclKHYe7jRwLnxdC5jNP9Otbq2SOTQq8BVHzjpbVWbkFasLtzTN79411keLFP3rqK' + b'5+anEhOfuWS6j3S/ieYPP7AvtvmZE84f/+l6f9GSkiAJC7LqIOR0dNr1W04Pua9ubeEnjg2k' + b'wC0bwxfvg5H1zeMtPz5+5oB/oCe4/Hfv8KLpXwax1+flh/3P/vEVqB8Pi1gsxg4dajJlrAj4' + b'uZDACOlYDGax/7HL0QSThdkEVhMtb7q5swKAaulwrDP0wFvqA9es1sC5ayrw+U0FQCgsWAQl' + b'wB1t7SwrMxsL+HXBQcdAKzH51ONNVC1DixXteJi+4UJHLZ4jgLBjrLYMU8TkALs1Jj8tMToE' + b'LTYaNOdzB71kXp19a4Z56XM4JbX6YijRJQufrGe0LwFDzATE2gckZQfUs7t8BeiyRPCMcucC' + b'QTECP1LJcvQ7P48GM1HLcNPNK3lOTuRNzX46F9GSHI3tO3ehe/AIaGYbRjh1cjD24L2NYngo' + b'FoikWP5nr3P8DYudELk6Z/EUHeLMIIWLRi3mb5BJQNOL+jLLno/05bXrmAJSW57oRB/1k0oC' + b'gwAEINKbRZwvn2NxpPtQywCy4WIpI0DngBCwES9h5QUOu2adQ8FP999/Guenun1nfn1O7Mbb' + b'GqAQssNYAwJpZNbeNuy1tw6HAM/WIyPTCtBt3DISSOinhvdni7dISK2/oNpCTMStmZOLRuxo' + b'xTYZUyeP9wPROKopUDg16QVx33UsbmaCBmzW5wWXH62rvvUH2K/lP/6QrsGZBX+G8u+SJ/U1' + b'ty3Hwv9TioNf+YEFas6ccjLZgPE/YnrlOQFHbnnxJNpXITeAu3/deluW5AeCrh9GLjnTMNSs' + b'eU6MCMmsPHTpISah46BUjaEdGCssygaEfZaz6J23HuY4WGwkTKajUQiacXSzyTZWAL0H5tVP' + b'P9ak0LzTBP3IElnTYMmLltnw++l9HHuGefF5HnKwewj1yMP5CT6LHKHxQWkRJpht5jtgfyME' + b'zAHeOD/zOr105hJmmAp+cEk+F+WFDtuw0AgcaFk0AAFiDlYBlTrrrQf86Ld/Hg1kZEXYp25d' + b'xcoqMm2gK994grP+ojkNw+enQXOF5tcnjvbF7vvJHmtyyg+kgvn/+PqAv7LeCp5AJJ66DeUg' + b'0IfoOglEcw3EIud6TTRjCgLO3gcSCOS+rGmw2doGCuY5sr1fyf0QBi/vl+wXr3g8L1sAAmyJ' + b'FfW2yM802QBkFciy0AyoRfWtR+I2Ghfr6z88P3r+BTVANlpnBBsJWTQlcS7cOCdGXaCrqnIC' + b'hI8Y6J/ysa+CnDuvkOI2JkVKAqa4JNMpLcuyITQULAF16GAfmxqPIpCpdEmu0KWZQs2vR5X0' + b'AgdCVksUgyGGw7L7hq2vSld9fE7l7f8WTo/98A/RGfldKQDMtlej6v+Fv521dn2Fu2hJMTAi' + b'AaSZmpFjPgV/02GIrLsnjg/AqEb6rEx45y2ybTTqSDCZWaLn/EKMx0WHHzIXaSCKy1NSQk5R' + b'cTbi7me455wv/eqftFAN02EVU647PQN9wLFiKWW487VW/+D+btQUJXb4gLktPwYQCt6GRfjG' + b'Y5lj4KUYonFDAMFMTsIGBndQAJHgtFSbTz32aIEGEaEjjAKdg5r30WdmGZ7mTv9m/549Cx3f' + b'mMqvCxz0DjCWAuHr+Z7j/vR3Ho076egAfDPgFcWlGdaRQ73xzKywyM6NOMQQNEgDmunPBMlI' + b'ONEgExiR8fgD9zRaU1MecvpCIsPhr55vh8anlfzRE14cpdGBsjzTg1AB+KQB4QUwiXPK5yNq' + b'D9FuYhwmuGoOOvOLzkx0dhNzgBvDbGAYbGQSYDnZEgAo2dRKuX9fPv6aby1H8G/jUodXl3Kr' + b'tVvLf7kfFYyurW65fbk/b35BCmI9pi/C7DlI0KAbkX39RxYbZQCNDyEl9NaXTvkvbD7u3Hr7' + b'Gm/V2gqkdiGYUb/VfHJQvvJSsz6M9mwpjsfWLXTUugUhXo6qSqR1KfFEfEb3GcRBzQTckbY+' + b'GYvGlPV8oyzdc1z/+/ho+DrgWL56ouVHu2bn8d/x+K4UAJNDciOE+SW5eSG58bK5AG9IvnsP' + b'Is1j48ZEQx98//lnj5OEJrNXX77Gpi68vxZRB+2A+nmobgxiDvKjUeWHzraZOIaRCua9/+ym' + b'mNQbFicxwhgi30NDg6wILb0G+yckMO5YDMSdtAy4AvMjv2854HFYHDNafOb85jOYfG5uJkqJ' + b'M035LZXcTkEQTAHnOzkxhQYZI6YKj0xTKkgiIUCCAYKLhVOCqNXHDwADMDeMBZGIDZAswAWS' + b'YEjwMJ0qIbTwN+XXER+IgfkBkQ0KaH5dXpllP//c8fjjPz9sl1Vmep/9wnqoM4s6HOnnnz3h' + b'9XSPsWs3LRLp6NtHVhUJuL7e8fj9dzWa4CuMcfWpKwLeauT3KR6BEmTrSzcEnFebpItOQtbW' + b'g1Kg9ZhJYSKLooF5kA1VwgCTqGdBGsx/nGu2BNrM9w2/QFESdJSGJVKg07FVmm+zS1ZY2G9N' + b'ej9+wpUvNvrO+Yst/zh6EsZUQN32uVWqoiI7BZDxNxxq9g8SAgpNHWf/JnTjkuUl1sRETBYU' + b'pSGvKKjduXzp+Wb16rY2iF1fX7Eq6F+xOk0AZISsAXAMOAYFJ+HmvT7wx4lTo3zL0VQGa8hZ' + b'UGUjQOm7v9wmL2oC6LCy8rbPt7b+8Kevf+H3++xdKAC+DuO14/MKYK1151e56RnBAFntwyi5' + b'pbsfCFps+ystXlvrSAgrigpD/JVzKQuMwAyulhY9KQ76oec06C5TMIrWrnmBXoPggBugIilB' + b'QFJMI0yjDWbff6tHY6qaA+MAeOzp6iLsu37phRNqdDRqUn5k5hZkMb8wm1PlWhz8gipD2sGT' + b'Uwtv1N4a+YHvQ/LgGFSTT4xMP1nZKJ2l13ABqAAyTToSgoFq8qk2fxqFRGN4HyfBQCCUBJkR' + b'BujXz1LRoCSC5h0kKMhMJ2Ewq81JRcEq8H/8JHY2mmKBW+9Y7MPsD4BJFLQ/hJBEpyEHjbwQ' + b'vYQc6+4alxC0NgQuWwP8BZp3wnaA4BuLuvch4Dc8PIU9iIS+dIXtoooPhTyG1Ib26GHoXIte' + b'hlessuXwOJMdAPWc6KDGoRIYBGntPu4D18A54fhRDOQtRqCP2qpnpTPgpWasA2Iu3MPhcR2H' + b'66KLsuG9wAiatWxwPRa+Z/3TZ8Pe3c+43tPb3VBOdih+62ch1MqzQkjRvultJNqRO0NCdZaO' + b'BOSqrs1x6uflw61UbPeOdo8EemfXuD23wvE/fXWqnl9lBUiRTEWpNJoap/iGzgRhpkFKYXhw' + b'lJ042SUGhmuCMTcAa0vzxTV2AHEL+eIeP+PBl+QPiotvj3Z3/+CxN53c7/jFd50AqK1tX618' + b'cUl2dlAtXFxshYJhU1q6c/ceLF4wBFIwO15rBe8nNC3o5T+9w1NQ5gEsOok8OfLjQLWlcAFP' + b'gXDnRgLgUSIIRzxgBmktLHKNHvdYBwRDNUJh5t23fqDj0QKkQTd8OjrN9u1tlgf29dAefeZ1' + b'OhYadDj/626X+vYp0qWonoWVgpZayAhQQ1EELXUh/FhE6NHOC/lvmMXBAOIZmEZizsZCQQce' + b'x2Q06MAIY1BzTOaio2cs6hqBMA20S5QsB+B+qQcgCRRiXmrxlZYWYcWl+SyNoH94nYJ+D29x' + b'443H3fDV19b7DcD1u9CQcIcE/GEODR+Hv4zIOYgDAZSWHuRgCuxBENBlAATRaxAS/gP37FWI' + b'ooeo4qggg3sf3uDY4BnS4mcGCUHK5ROf5QLZWJBts1XzUBjlOwjwoYahR7nA6zNocIEApfXk' + b'Dl9kpwKhWGhJ9EHUCAjyigKBTkTMQpDTQurTBcxXptkQ9TPnoUe6F1gKVNHIMjMc95O3LFcV' + b'5dmEzzgzl7OfENNmZWay+Q317ARcyqGh4YQ0xocoLgShp557+igVLqFaU7Or1obcP7o8aEeC' + b'2uruGmF9/cPY24B2PsMmMdj2rbS8wFhmRF/cIcQRhlnUgwTD/hFYVuL+57z4BcusYFmusK5c' + b'a+v8bBH59i/c7wp5S19n3507z57b7+P5u04AWIp9Gr33w4uWFLlpaYFAeWkp2malG0lNjHrs' + b'SL/f0z0OrkULLvTgRx07FqVyWnqp7p1xmJqmTTfcaH9tg6U3rQ/AS6Pdcuh1qFojAcAkCQ2g' + b'YVYD6EFygW7grHh481tBnzKaeQa/TvecNAj8Q8LIw49EpgEKF5V5aE2IzfPQqQc9/SzK4SNt' + b'D22P7kD9dB5wB7wOLFyTw0fHG5WbwX3gFzwg1UgTioJMIUIhGCnkS+BEtNDpfIS0o58INH0O' + b'zzTTJo1FC5u66ppOPtTqC8/RIs28TldD6UAg36KPvBwP1NfnygsvnoM5K3PB1NcQQbHA/IWF' + b'aHWOyD1xLwaCpNYtt68x1gBoRIaBeubJo17ziYHQDLhJUYYDW6KhcSnRNGF5gQZmrnQMmjOF' + b'IUgYYBjFSzsY5WXaDgmE6USAzz/SqqhEWbR0K7G/2TdgIEC5VW2J8GEhsHmVIgiMA6X1yKgx' + b'uAC6mTiuQiBTHmrl7NbbVkhE6t+U+RMMytCjoI4tWtjAOru6TSaDhDgJTKwnjU1h/GefOCJG' + b'xuIONZC56bKAvGwVWsf1DYuj6ENINKY2cBVVJUa4kuVFF0THpkdqqzY5PsEGp9IY6hfI31Qn' + b'u6Q6H70WiA6EYAQcmX/ycqfoPx5lP5hbdusVxzt+3E2E+X2Nd5UAmIvde7TLrwoherxkGfbd' + b'grlZVlbCunt60cTSo4Ydas/OdiK4yS3XFwsfKZ8g7h918UXZLUfuW6HxBFMU7YaARnMtug9Y' + b'KGAgo1lnKG1uOrQy3bi3M+gYHhY7fQ8ZIfj+PqrdfMP8FIUGE8u/upGmxGjTEA20HUXfJRXm' + b'DIwCAYfWXdhOjyPNxdGHEHsCaIGt9ayhMeVQMQsOrJCcULTXXyX2A6jCjkMINvHaYssC6g8+' + b'OGl4Mv1pSSUklhFmItHpF0F38+rsVdHnSUqQxXrvcy54xhYfQFUf+fhn5/qJ6UGj2a8ZktCq' + b'BWNQkpL8fv3atpb49m0t6OxFnY3IAtIcXYAFsq4eBBjLwSYj0Ng8HRWJBPHFvGZcHBIACWFA' + b'3ztbIJA8q0OArx4BvuuUI6moCbBf71ibIqSfONAsBfohCBQOMQgabNoiNLkLc9AfFAAj/b3H' + b'YnL3ScbB/D76LYD5QcNzBglpip8sX7qEVVVVArU4hh2LDphPEfIP35GP/6JJ7Xy1hdZWLC/L' + b'Dnz2uiBbUKkChw40w7qKGUsqLy+LoT6CyDHD9KABBLm52fjV1TGCPos+6xsP640L0LrZYs4X' + b'PxRkwIHYFCugW0NALigmhozGwpf2sX8D1uWmpqaHECX6/Yx3lQDgPrsMhCqqrsj2C9A3nhZL' + b'C/Ltrfih3XCBuPJPnRqEayuoCgw5XziEYHBKsWHQckOVG2cZEeIR2N44AC08yGhIb+MOGHan' + b'4yKiLnBM3BL88TYGMQUJABp0nNbTtD04FgG0P2n0D12IJppovkkWKMx7qmIjTjCxdDoX+BG7' + b'7nCktgibjlp/QH/Rx4/RRh24dicaxS48qGCD32sBu095bJIKoiDL9268PCDRQyCIDTZiz+32' + b'yCe2aIcfCqQRshAIOQB8cMHnDKoIfHaXG2867RnTv7wi23krE/mcr5qFTqAYZF1iT/6yCTEA' + b'oBfxIRhgCq6Lj2YcYvNuCqNwitbTtbMcuDgoukFaljNkAVD6bHG4AWDiRDqQhOisQCD5dAYP' + b'gGPDFUJU33ZW1gOu7DkKdPDRA8FH4xKGmglOG4/sb5YGkg3Xyjndw9nNt67wYcGE3izgR8wf' + b'QqnyurWrWGFBgVEkuxBQBrLUoBcp9ffQg/t0T8cQdYCKoVYh9LkPhlhBmuscPNhmGqHW1FWY' + b'OAvFUpAzNlWImDbt5izRm4GNgqkB/hZjvSN21LWxD3uqnFeJXCsWCKwdg0olumLfV/bkrhis' + b'PIffeJkjAGn+SN9IGmUF/pXe/32Md40AgCQM+DFxM/m5CxcXwW8W2ClGsiOoLiMzjSC1hw92' + b'KyCvEGjDZYGrS/MoWEQ8TUsywZDElDSAv0k8wW8yFaOugvsMEA5epxsTDAUU+v+hEy+SQAAI' + b'kX175gu/5gkd34cLQHX0Q4M+fD5IFrA3MfyqegHMOzfMT59DqIkYnp5g0HnNgY2gopQcBBWj' + b'PQXJ0jHqgeaMQ9PnKOtGjUDpuMAvIMNhyoZNBV1eprDB/P4eFMc8sd2jryKWIPxN5zt6DSLx' + b'ZO3MDjAqQzGN+/Mtrl1ali7PO7+aNP9vdK10DIprdLaPxn92/14bmhJ2A1qEY1OR685zgPF3' + b'HGpW0j2kTaceFDZRH0LeN8IozSi2HqCYBlUZomkJgn2oPvSg7XkVAD0o0aUuy5TRPBP9p+s+' + b'2zogYQPLwsQP1jRAeEqkctGzAO6G+tbPY2x/M+Ofvn25N29BYRjM/yvXRMxPfvp6wJbz8nJx' + b'LxTbs3c/7tkACyGTcupkv//Avft5mEX9rAzLLcm1Qrdf49ioR7DaO8exYWwxw2aoxu0zjA99' + b'ATNe4trka4fRRKVLWRNowoobLCIBn9XkpbLCdMGqC2I8FdFZJJoT9x8XRmCIspXXsevKXD7e' + b'sl1kOoP2xy9x/G8/6n2tuuzWLac7frxn9p79Lh/fNQLAi6ZtAJ3Oy80NUw99i9BaNChSSyYu' + b'4a+B+gMdLbNg0PYaO+Mi0kIrBoPEAC12ekwwkHnZPCf+ggmOrjtUNIPbBa7MxF0GnoCPIdUD' + b'8/dMAC/xrV/3G7Ie58RaYi2n0LN7RvtDJqmr1xqf0JjHJGSomy4+afL3FJGHUDPCDBKA+MIs' + b'DrJSwOz4SVzH7JnxigHPQO5hY0HO0JHbCAbSnFiTNlKM9qYNDoFOFLXLOnQaDUqj1GHQoqwU' + b'jp4YVOn39A7XgzURvu2GeX4kEviVmv7Zz577SPPFlmku4NYMO/Wgg1bC8ppTKtwPnm+wTjYC' + b'mTYEcUJ+YdKwVxQVNY1Oagloro/qQ/RKlBzCge85Jvm2gxJNO2CpofwYIBqGeIlB9mH7MwRt' + b'Yc+BDnSNsxbCWQIB54Bbh1qHp3A9h06pwCduXOJhj8e3ZH4KhK5DhyJifhpNTUfZ6ZYWpFBD' + b'ei+w/g89cADoQ42Qk+3mZ/PgLWjKCpdEUAlxUVEu7hW5jtD44CJqmQbcgf/L1zzWjmKi/NSo' + b'mJMzzfIr4ijx9hgJAHio9Dms1ynrle2orgoVsfVL01gm+s7EkSKZHOphqy69KeBNrWXNrz7E' + b'1vj7xK56kbntkP6rG2644SO/jx6F7xoBALJ9CIvHBvO7iD5js8zX1RjlZI8d7ZO9PeMGsw8N' + b'xM5bKKgllAmwET9RLTgi74qw8WSGon8emcSSUuTYyYtjo0vcaHLLSEDANMtJI+HCR0emwFhg' + b'trcxyIQdG5VsoC+xlRXcC4aGmgp49TMCiQ5H6bvRkXGTyksU1pAvTbvzvA70oecUTKLXSdgZ' + b'4WDmkrAYSEDM/Jl4xG86P/YyIaazwEQWhKGDPgVIXxHW4czHzMVizz73+d3xwNIlxXLewgJT' + b'2vv6J15/RuedPTfRh2iKe+D/7P59CoUvIXIDyJoBus+/9aoginRoqzKNwFcUnXdxjeB6CFYI' + b'aLQbx/WkpATtuUVBtrga24jbIQRgOQQDFTRpSduRkYDogbWAnof64CmYVBB4AAsJbL3Oa0qx' + b'oxCyIzA+YOElhAFdMzUI3XHEdx/cHBeXXTWPdlV+U+an+ZPAXYPehAX5iQ5FLS2taBN/lMx+' + b'jQ1XvUceOCwuW82x5ZkNy1AHbr0SFYEQMMbhoovHgMCh7d2g6bX3yJa4QiUp9TEUBekeK8uJ' + b'sqL0GMtLi7FIEE0L4QTQD8UEiI4pjsuOdgyz/3NMsOsviiiUIIu+Y6+y1LwKVtSwgdVdfDNr' + b'fYWLq1bu9vaf5Ffs3ZW6Gqd8zZz4d/jrXSEAFpZ/Lstl7kb4dGT+g34JjUKPpK1xQxUkNiy6' + b'hAZHFx25rA6daGcWO2l+NLyI/fQlD/3xsacf9veD9NZ0M1Alx5BGop11SIGZO0umYQZyhkRn' + b'tI2GQasNzPg3ozs0FBZ+e2sccQWDFCPLA7lw5OJRvIJtvNDYJ6HVCwpzsP1VNj5Hm3AgbQcz' + b'ZBJWAT2Oo6cVRe1pLmSWIMDJwoicpcBejuAHWsoICnqd3qc1SQub5AE90qAHskZm6GCu5+xr' + b'oHk9sd2V055lb7x8jkIgnyPUd+YjCToTjZXxiV0UENAgYFEkNUW/8OSxRMQfZggNxF30DRfY' + b'PgqLglRCTAOuFLooZSTwCgiWEaJxDNuRxUkiQ3sCa0/XIrCdOIBEEVQZhu28DOTHSdWibAG3' + b'loqZFNqP+SgTplJfve2wD7eBo42XEGgiYpXmMY54g0XxgDufjInauQX+xZfOoS3WfuWaZ2mz' + b'YtkSs+0YzXEAOw417ttPcSS9a3u7/8iDh8SmDbaqLbP8g83KuuUKSGEIIBIys4NKiAdGlPf4' + b'do/ajqEXJBJGM9wE+AMbmEQrJ9znhOk/zhaUjLKsMNYEhABZdBT0WVw+zvJHXXbf0wVwjTLc' + b'K1ZbTnvjEzyjaA5LyS5iles+zryJQWvRjmZne5P1GZz7/SkA3ED8fOnz2rz8iN/TM04RJVaI' + b'rbuBS1cpkYDd1zfuJdppJfavK8m3fCwMsL1WCO4SbzBsahleWG0jaESR9oQ1gJZSamRSMuBm' + b'sGNPIsc+e4NTIkHYEcyKImqTWMqz7/z6R5rb+LiEeU+Mm/DxsfGGREoc/euVT0KASnIRsefY' + b'VsBEFlA1jLr9FGyLhbA1TkYLLSEUsGUXrIQzggHPJ3oHzXtkxRP0l/YMJIGQih5elPojwWCY' + b'h86dEI5vOmF8FT3ytbtlr2evXVelCMtO5c+zg4QKBcIGBgaQCx+CJkdEi0wZXB8xrRuHpnyt' + b'LwABZJiMhAz8d/fy1Q6siNddDDoOzYlASDlANdL1UY9AD2YaXRshGicQLRvoH2Fdnf3G6Z/F' + b'KKQDn5CKYAhQjVZ1sWPVlROHUWoQOxkPUbmwJCsBW54LiQB85KcvxPVY1GKfvG4+TgvVPeMm' + b'zl4TPZIwW7RwAauurjIvT+O6du7ag6MqxJD6vIcfPCiuWWepj24M2AdOKYk4Bu5WzvnZagAA' + b'QABJREFUIqtEXwBZqe2beuWQ596/2RMQAsBGJQKc5oD4RZYBPCv6E5vKOlP7OnIiJ/rS+dq6' + b'KbmkfELEo5NGOaHyhBVlxNhl8zvF87skHIQc96qV4wESAvWX3sYm40hh56wRV5/XjY7H0Wuq' + b'sa/l6dN3HZo9z+/i8V1hASCGci2RtaQs030KW3UjnaMAx0RNdhf/4pfOl3t3d/rTU24KiWDS' + b'9t2DUvzND2MoNmGSfEkoGI096yzqBQfTkUM48DmlNkBEDM6AjQgf1w+97Mbv2+yGKSJOixQm' + b'KnkDtEceoQPNIv9NCE5iZ3QYkaiECU6pMwZYq6LyW9S3K9TpU7yBegyydAgBYHEUuSrYWFPD' + b'd0fgj/bzQ0Uh0AnBQBDIv6AoACqIUmqESadItsknTxK4Z9owEZnY/QCYQP9jHwKjnU1wKiMj' + b'zQgHiqTNar7Za6CMxFPb49LCVj4XXlxLwsJcIwkw+mxPTw/2IeyA6Y72whhGUhEZ8B5ZJo27' + b'UFYNBCC8pNlDYvMSSyMNjsao5mPGTyc60PGIpnhmPkvfIMuA0Ig5CP/T+yR8DGAJFgIJhARw' + b'ady8RwKHIvUR3NAQCBMOBqw89B+sKCTDDG4T5vAKWqO/gO7Ll19VH8fuQ2+K8qM8fVVlBVvQ' + b'MM/MgyyQPWgXN4X9CLo6x7wH7tsvNi4X6uOXYityxINQEYnqwISLQV9I0EDL+19wAd31AiAV' + b'kJFnrt8c8+xfuCyEp1RwcbU1cbjVTnv+cKbVNZ4pr1o2rpzpXlgNgF3CIkgJSHbpvB7xzC7L' + b'qczP0A3iIJ8eaGZ33XeMLV1Wwy68bJ346ebnsg62WDfj+H929jl+2+fveAFQXX1HBvbfXU+M' + b'tXxluZ2ZGVbQ/hw5VTCEFGgh7e1r7EQAKpF7hsZXt14dkIgXWd3D8CXHlQKSVUy7yJ8DikpN' + b'IuKelHADKD0WwU2C+NZoFgFSEgfNMDs0q4EF+4gMvPUtfnPy06KZHXAr1FWrHQGoJ7UgM807' + b'YN3TZhwKXX0Y5f6R4wckWOvhSWrsgf4WiVMiGGZ8akn4eEpp1hRzUZxr85yMgCjNSqN0G2hA' + b'KczErjxR+NnGYoBmHQLkdBBalbQv9T2gltyzQoCOS3sUvgTtf9nVDTonN1HiS9qaNGJrS4vZ' + b'iJMWPEX5Ub6KSkmFHYglUqNC9fX4YrA/AWyavU7SjI+87Nt7j0kPOXh0+hEckX2kXXEjsI8K' + b'URYGiREKJAwSQgFPZgZZM2lwAdJR1F9EnwURCahEm5QSaIlgz9RshFJt6LQDK0TCLUpoZNDS' + b'v/eZOC8oTPfXb6imXgW/csvoeNSrYBly/STkaBw9dhwYkh6gNX3//nsP6IZyqW++MkwIv0RA' + b'9XWDCDSg+Wt555Nu/PlGP0Se18xhZq7gVx/ofYAvA+BpduUqa+qpnX7kSCuzB8cz/ZsuDvoR' + b'0YHOVeTmIRMSlGxVeb94eY9i88rT2GN33+c37suw7/jsFSzgZ4kNy7bLw62T19XW3vLPzc13' + b'Dvzq2f5rr7zjBQBCV4tB+Or8/IgqK8+w6+ainSsYpG5unrpwYx0BfzQ6zRiMPVmwtQWWXL8A' + b'yxRmm1letNrODGg3eo5fFEWeQZ+Z59RLH5ryzMJBsIo+iioxHBUAszOHeBtPSPuXFqADbZ4Q' + b'QPxh0QNmA22Fztamsw0h2Mxk8AtrFm24EARD7SEsBLTiMvv4KQIBYX8/9ANEEUknlr9GQAwK' + b'E9ZM7MPonFuaz6GJsGsRfOZUmBPGVsGJiNkUJkCuBDHXLPPT9MkgeGG3KzNzM53z1lcTrBeC' + b'hABL/ayzs8OY/hQQiWMuPd2+N9AbV4Ooa8cuS6iQtNGeA9wA94h+0XGR6dCXrAhM5WRwjmIb' + b'C9oRGQdtISKvIQQYAncKW6RTq3OegxbkkEmUCeFkKcwOMz/MOSGDE6+ipBtMThYN8oTnGGGz' + b'AgTpVv3TF12U10rrltvm+pG0QGi2Vv/sYxMNaKdlSvvR6O3tY0eOHaO5ywfu2accf4LfcW0K' + b'lY+ciR3Nfp+EG/7Lu55y3ecbPbISz6yT2c+81SMJ26MdKgChqNHtePqXr7iR/hHf/ukrIfn5' + b'q8ql39VqUUCbLIHirCgLTfayg0di8u6X4vJP/upWK4xMFGNF7IJLVul7n95cPhkXS3CuzW91' + b'vrf7+n9pYb/dk/w2nwfx14I5nJraXI/25UNe3hCfurNiEelDB7rI3zOvkebFBpHadaOIdpv9' + b'4yG5KUA2e78ME76BGegd8IgCWMP4dzNz1fBDKeIVjMao0z+5Cm9/kJAhZBpcdE4VfzQwZ/OT' + b'sBJIxpiBKWp0mkUKDyZlDup9aM7QnXgzwRJ0rRJCgjYbgbWCLb20RFMjwtifuZ6zmZyOStce' + b'hCdDrxMJoMwRcQcaclp7wAiIpesyxcBgjzUBk2RsbJTadJvzUkFVV0ecHdw7CU0b5lWVedaS' + b'pQsIHeiePN5tHT7cRvPFZwUCZ45KTQ2rXUcnQ/PLtf7UVSnIvjABlwfgHK2Ptfscm3TwzXvI' + b'kKIGptTQlLMLljjkGqFqLsHalIolOYVpmzQpCU9IO7oMQy+iw7mDwg+opPNf2R+3FgMavnBR' + b'kTO7BdnZn6VU3cIFDWf2JKBeDY3I98Mq0I//4ojsbu0TX7s5ldGGqJSJOHsQ3eBWqns3e+7z' + b'e7zQucxPUwQlcK/e+L2zj0F037zHC/zFJ0IQVHa08ZgMd/ZJ9uz+FL1pVTFao3fgLAk6ZEd8' + b'dv9LjpWWKtTq6nE6qHlv/pr1vLRwm334tLcSr71/BAAufy2RoKLKNNagPL8xBcmv7UU1Wl/v' + b'JF4yNKI0kCrOnOZHmwZ5FI0riAEoYk3+JkXPTZks/E7SKpTDJiajhQx3AHX3eEp3AYMeMzJS' + b'iPsQzItR7o2evu2B02vqYEP89599eWatm8UOnp4Zb1hUxHTYvRglwrAgKA2WYP7ZzyYeaaqk' + b'dXB55pB0bhI2EHJy20HPbe50GboLMzQXDQ7294tjR4eNHz+JjrijI2RyJ84+PBjw/8eXPuxf' + b'vHGhVYhOmnCJgI0EyAd+zHPP7nP/51fvdrJz09S//X936MLCLOvwoXb5j//wCP+7O/vE392a' + b'whbWWKFFNXReW0FYEWJPtvdJ/zSacQyNagsBSNVQRcYJ5+h4HHsC+XO6HwRrnlMsaMMOAdQm' + b'5WVm5/+GCyWtTICfn77gYU+GgLrq2nnwVLCDElyiswe5DYWF+WxefZ15mYThgQOH2OT0JJrF' + b'dnkoHLP+9IawqiziApWI0ygwQtuuxBGIlhTwQ3wo9vhrXsg5S/NTSo8+RlH+ENyR8ZiDXgRk' + b'GSWEwdkCgY4D74w/u9NzUD/gnuyAEyO1+9phL7SuIVuVlk5a3d1DzFM2e+l4kTnW9Wv67eHW' + b'vbx40SUoEw2ztLwKa+nyOnbg+D5KB/7OxjvaAqipuSkfi3xpJNUG1jpVFBUWwo/LYvvQaJLy' + b'zu2tQyoW8wzihBY5dcRdthDlVIFM+HXY1x5UJ7+YHsdgS1OZLA2sZOTWE0GoCKLTwXCqQiUZ' + b'LbbEwCNSUmYZwKfGEp15/W08EPfh0Bp4fVOe+ja++pYfNRyNdwn8MjtobqYiCI/EFNBgPqDA' + b'fjPSZWPTUpbk2ja2KhM/eyHqHerOsmpqi5xIiRYL0ye9pkNdVke7C6GKVFifyzMyMgAEiui+' + b'vlGRmqrU2nV1gj4PpjfWCFL4CMQF+KZN60Ntrf3x73/naZGNria5uenWJZcutkrLctwbNv0z' + b'/7sfjes5ZbYszLXRGMMRiAfYwRyBllwCzTLM5Ak4Z1wAAkoV5YjgdesDSPNRv36l0dGXcu+8' + b'BDGEhkrBG6psUZSDvD+gzOS2UcYBHg8D3FkCvmxdt2l+vLgYpYrn1PYTs1NQdOmSRRByRp4b' + b'2HhbezsJOvnsM6fY+QtthY1DBXaGiqOuwqopQYaDkJygJYSTemSrG334ZTcEQUAvwV0Eg8M7' + b'rMqdZNW5E0D2RRHE8xml/vqR+huZChDWnw3hb1pP9B0aNN+9JxT/wFrtXL/BdmFRoEkKiz2x' + b'3Q9/7KJCr6mHOQc7M3EvNfvA4m4mY3HeebqZ1Qy1seb+ECsrzWYbLlmr7nto//z6kk/mHOu6' + b'eyhx5N/u9ztaAGAvntWoPisrLkn3EQkXixYthI/aBdVGsE+ljh2lWEiCPUkbIh+sUHACfhCa' + b'fCeNVlYkzcmcpO+Y72HlkUlIPi+Zi3RXyT+HjDij6MlfzEInHCLt+Pg01b+bgODbITXNpzDH' + b'ovmYfvRv9l2aeYId3uzdN38NsguLGe/RF3EAxMd89LaX0yga6uhV3hOvRXlnP7ezYSZkZkbs' + b'F/cP8l9sHZcr1i4Rj3z7RjsnB7AnzA3Wr7V1y2H/n/7hIWp7xr/05bV61Zq5Vipa2HQC9/63' + b'X7uXfe72b/MHH/mKLChAL22clDT07Ljl1svsZ57aAwts2C4qyjQFMTU1Rc7f/O1H4y+8eMga' + b'GpqULxzoF0+9Nso+d33EQ4GLg7nOjjMHosuAiUwBWYcKmy5ZgRgI8v49AwwVfFLvOemjR78v' + b'M1KFRJEP4NTYvCOP24hv+vCnRWlpur92fRUBmM4cc/YkpP0b5tezHLRlo0FZE9oliu7vrh3t' + b'Mjo+IT52U4p+6CUflpGyPn4Jmh3AgqDLpCwJeg3GH9nihSEIjJNJfno+gD0rKgZZZfakEQQU' + b'wKNrKMyIspKsaXwXFqUvGIQte7U5H21CkDYFU9MxgSAUj77iqz/9SMB6cS+kDF5s7fHVvzxA' + b'ux8XePMK+52GYrRPx7ayBGbr6exlY53YuRjHObSvmV125XKRm5tRiupD2FbsvS8AQPeNAE/y' + b'2jk5qrq6wk5LTTWVWmS+T026srd7jLrI0L01Zi98TmzHFfPQE58BCw8oKcfGGYI2mEB/SurA' + b'S2gs2s0n0T2Hvkcm9ekuSWCTmSPRqwymtpGNPoA5/yULgAQPNbNA2TEaVppjvuEXRaVJENHs' + b'Sbe8MVbxho+e+QOeiwaQyWtqQVoDqGEUKPhPbY+SCW2TVgS20Vm1pl5/9e8v0kuWVlnpKId7' + b'ddsR/3N3fMcuLs3x8vMzbLKIaICZrQ0XLbCWr6yVaC2GFuY2AFLUEIGzxYtr2Le++3nvmiv/' + b'HpDYZv/qa1airdcUXCiA4HFiGgBKWX/51Y+gFwA1wU0gJRGt55s+vC6EH8pkqF6UNv71V+5V' + b'3/zZESv1U6k+WnmbeZoDnPWLGIgsARLUGBza1qoq5hYFDq9dZyNLwrClma/Qt5/6FHq3Xe0A' + b'2my2Mbdu+VAdsCBO4NzAn4n6o65/bt3rpv/BQ4eR5UApqOJy65Y2dulKW7f1av/xV13rr24M' + b'CcQaEeik0mjqi+DF8ROEcCL2NfGIBUVDbHXVICL2mCV0AlmSZA0g2ErYBD46ZaHUN8h6xyMG' + b'CFQA6wCwZtY5EgFdgQ2A4D7S5ovhCYdfi1qJB170gotr7Xj/sAp+7ZNBcfJolHX0oZ8kGoWk' + b'hVx0HEJGpqmRXbPpK5QdQpYkhZWU5Ie6Oocoj/k7aR32DrYAUO2iP72Eglh19UWiqqLCaPAx' + b'1FMT9Le7a1iNjcbA1gkBQIsI2gHAH84pvXakBflyAEZIW+ZlCX9OCczJKktUwMxDKpnihrTW' + b'zQ2inWWQWcLCw0EwEDnXg0jYt7b06u7OIZRtJBZ94t3f8DcmBLyBsQLpPJSrRngLf9Mj/Nco' + b'/EaUnVJOn0xXCqiVlBWY3DhZKmcPfJxMSIUgVPSeZ6I2NujCrsKSI2UXWLa0Rn/l1pUKexbK' + b'3Lx0a/mKGmREHMPMdJxLL18ivvwX17k/e+AV/YU/uVaC0c0GpQlrSCIqHjR/x4DMo7Qfah/U' + b'1pfRTE8ppxpVK8jVY5s8C64UXCp0XI5ACMyO9RvmBwEW0mcH3gh8Ewoi/C+0VVqaZ/3bNz/t' + b'ffyj/6oefqlPL6pJxf4YiexMwm0hq4zMarJIZo9K1hrFDhKmPlELTZDsi9DX4YLFNtUQKKRO' + b'5bM749bChQXewsUlbxr4o6OR9idQEY2u7h5j/tPf21+DjzSNbdzrw96/P+QK7MNIwVo7BkGN' + b'smLqhBx75GU30V0IGY/UQJxtqB/B+kITlIwyxJNSDGqwZ4jJg6d82dLtY7MWqH0IhdSQstKs' + b'UWtNZb+BAdPS2dOWw/a059BtR6xJ811HlPrgBSn2o6+MYZNW4YxMKu9oOw9VVxSwLU3oGNSX' + b'xTYtbQMhfNZ56iRb6g6zvPxqcx1lFXnYqPR4g/njd/DrHSsAlld/Jn3UV6UZuSmsrq6U/FMD' + b'DpmGJoKJT8AN4MeRl0braRrgL3UZ8u0oRLERcdfA9msIAFOK2YbAEwpO9GPbaFkxidSUIqQv' + b'vuPMq7AUevEncu8zNgC0Md/8XKN+7Jev6anpuHUG4/k2CA5fTlNVG0kZpMTc7Yd9b3QC1XJg' + b'5Ayq9EsV+MkREXS5yclWAr09kR5DiSM17YacIG1oglGYMIGTXtrvxX7wuBv4yEcvULfcdgkC' + b'dpNA6E3otevqAaMN0841ZNYjZ05twmZSDpgvGJff9KmLA3VzS6i56RlJlgiQmpZXpMBM3pss' + b'I2gX/xePbtf9fWPu6VM99rf+7+O6oCDTrZ9XGqCUIsGBUfCPcymTn6e5zpKFhDHV1dNxaNBn' + b'8vMz7eXLq70H72mz7n7GlhuXB4Bqk/4gSpnB2BbwDbS9GXr6k4+fOBYJAxIKJAjw3zynv0FK' + b'pBGFgGkuY56lL7uiDj0WEfg7x8Ii0592IS4rKzXziGPOpP1poGOU3PLSab5xmYMOwj61ZuNX' + b'rkLDWGh+8tPROMa951mXsisWNlpi84pG2NUIuzXUFaHWn9KRZh4IImrvWIcXT8cGKRcuD9KG' + b'o8jeoGAp4Iuh/jiwFKMmuEz6aV1Nv4kTvNJcQEKWb90f4x+7rtZe3uDFegfjgRsvCShAit2G' + b'D2aGl9cMscxwn7EYXN9GC7FBNth+hEVmBEB1FY7B1SKaBn6IPL/VeMcKAGBlChCKyUrPCCBK' + b'WoSL5WwCO8vSzUSOWrW3jSa4C5dPjALAiUoJagGmp2pAU2CfKKnlVnUh0YqCO9hxBrX0wMlQ' + b'e2akC7VNbcJaugE0puU1M4jhn3t2L7WCJtN49uXf+JEWcE6GkPBpEeiiJpjMRuqLD49bVHor' + b'kNdnJ7thoaDjNyl/BLwk/Azsv+djw1KBjj8cgsxGpB/GDvzjk10qftf/z915AMhVXef/lWnb' + b'tEXaVV/1hgSiit4NMc2ADTau2MbGDnZIbCdO4hYn9h+XuCSOWzCQ2NjEBWM6NpjeJASogFDX' + b'qqy02t53Z+a1/++7s7OaXe2KFRKOnAvamXnlvvtuOefcU77zYL/7wQ9dEHz+S+8kEMp3ZsAJ' + b'kGOMV14fUoRiAsyM0KopKCJAKDrt896yNCVpQ4RCPgNg1/s/+sEfg+efXW9f896zgksuW0YO' + b'Qx8orNrEv6HZZ3sSQQyCb950Z/Txj3zf+s3v/tFIGJlszlySUWfqRQeKngNYabhrZ3O4aCHB' + b'7vwWkekiHc/EmnL/X772geg7377fXbOl3/qrd6RcbccAOPHZCwvbQAlInMkTHAfAFIfIP2Pl' + b'oNnS0ZiAH72WNuLbyAH41MtZ9/gTp3vTZ1YlCqWPwbbw3IVo/fOEaOPGzQbdB/du6+kn6nw7' + b'0+NOHJ8M/vhyNva59xcB8JnDEcxmbf+/Hkwr/Vq8dqKTPXVWg3vq0UUoNycPSCn73hdjUuKS' + b'U2L4m6ADoG2agyLADgloptVOsopLi6JVL++wGtpde29XsbW3m/gNPP7gJ4CuBvbmvUXR2Wcs' + b'sm//n5XB/NpE0dxdTndzpxOfPasq5qXrjETYwFaiFSyI9p3rrNoTLjbHZs2eKB3G9MWLbyhZ' + b't+6HPfl3fqOfBz+73+iTDvI+ZuBUerYc7gaHrDAsRfnl5LPNwg1bm3uY/zmGJqWWfGCU6SU/' + b'//VpBobnGr7Pp+ZkHhBEE5T/pWyxdzaGQtMeUjhvwwKGHBvrDx6N9pn9fzyX+Yf1JslExN88' + b'E8FXVfGKuBrzTxKLQnVJtR3uwV14c30YrXgtE8DIAxa7u6PRxz5txZ54fI33/mvPCWrAA5P+' + b'IF+0RXn6yXVZFqx39bvOwH0156kjF9rWlm7/V3c8nT373MXu4iUzAM2yrYY9bd6n//qW8Pnn' + b'1sfeftVpwbKT5xvce9Wnevmn17drZ1Q73/3+9eE9v1uO7yTaLoqkgG27G7yp08YPUYxqIfT2' + b'ZoIvfe7n3nnnHxvc8MnLjO+E0Flu+OQlRSJC6B8yX/3KbxOPvBjzPva2ZIJ8fyyauFJ4maw/' + b'2/eEiNQBCL5aTpZdXkb6rxqLhB9AoFWSFgzi+OTLeEvFEuE5b5mH1LJPolHbVMT9BewxlcSk' + b'KkL32bR5i5FM2tv6/cce3eJccmLcJ8Oxc97xcXlXAhefE/1/t8Ij8i5ILZrpep++itzk1ni3' + b'dNy4wfljKiz4o7GTSUYCz8D8idq6UU5v98KVmxLRxu21Gid3QmnWlsXgrLmN1vK6amvNjmJn' + b'zcYe/6MfOS92x69W+ng/21gjUmIE48ZVxoqKm0z8R01Zxlq+rcpq2LHdWtTTaiXLJNVUy6uz' + b'qq8tM56n/98lALjMLbFAoa0htpLU0oYAtDOYmsDgzIdMtkHlnKZLdbkdsb0zNmNNYklHCvnU' + b'9fqeIwj5pcchCtpda0+zTyouw6xyB3N/I+zeIRF6PMPM+8Jzr/tdk4HQY3cHeekAsDSKJSnp' + b'1I6CYmrWtZgL7VIyCoGJ7xyDd6Am1Abw+b50a6+74KhZ1t9/9JRo8uTy7K6dLTjmGAeowWpE' + b'BDs6ev3bfvKw94kbL0UDkmuwiEJ7K5PsQ//uz2GlQTgMse/u7g8+8ze3AGpZF//Gtz/kXfPu' + b'swTmKWh1U6fu0z85QGo7QXWkAD8jqfPiqIID/fIX78h+4IPnWeeef8wgcpD6fMrU8fFvfufD' + b'1qOPrMGBEpU3KhBBa0tSUH6D005f5GBGVPZhE+EHzUDItozybRGwX4vxmaCLQtQNBhi0viUI' + b'sc1Hj7zgB3LUguvaO/Z4sTPOmu9j9ksKsHR40evPnz/XDKikHSWKUVATe//ogfs2BLOr0k5Z' + b'SQKiE8TwzHO1iKWcI07Du/spL4ZJMvjElUmrusomU1MuTmH/Z3AP4yaiB3MJG/FpUMoxnKss' + b'QEB0eXjUDCf68KWlYYnd4rQ27AIDNDf6Z8xtCerbp4frt3Q4E6bNtKomTqItHUC8uQkxBNlk' + b'J4I1sHXzTquUMGKEPWvzjl7r5L2bDAGorinH4zM1vrG3ewrP2TG8bQf7+4iVAOiKJXqZyVMq' + b'GLycI14PWwBNeCwAUpzl57pZ3EBsC2HXzpr+l1NLtwlBlSOQEmgokaMIgu4fWCN8t6ytu6MQ' + b'M2CMKD1TpMRiv+x/4pOX+Z/9u1uSiJjSF+ZOHsRfKdRXbfajxcS7j1YMOeBP/jPvmkxToj8s' + b'T0fHnrDI/untN9L+uPbfkfYD8ounNeAciTZp/Vg23NX5wj9dE1uyZEain4UmMVTJUW79ycMY' + b'1EPnG9/6YIwtAhYTzF8r1gYvrNgU+9o3r/Xf94HzEuDZITWZFnAfmX1au/2mps5g5qyJcfrM' + b'UcCMtgbgIoTNzZ0+WwSiBv3kLTf/ITzz7CXqbXoxV3Qd+oL4+689N96PV2FhkW7g8cdeCdmu' + b'xOdMRomGroPLTTHis9HOmJ+001JqL/wDhBRM5mQf9CMW2q8fywY7mouiU0+fGQsO4O8/ZdJE' + b'U1EDWJH1u3czf0gUs77R376x3vn8+1Phj+7NOn+xLC6kZZMrAgsRSsqM8Ajin7o6GQBTNpA6' + b'PtcvqkxTQIRCc0HK5a2NYQjeYfTKliAiK5GNniZEyoved0HcOmaOC1IR2gkIXNabYL2W7qJf' + b'c8xrfHloL51te9v29gGZnrSnzJzjdvesiKorqVyFzlDU5O5djUChZayKYs9aU1cWXbzjFbtq' + b'3ukEh5VaE6qr4nsbO2QJeN7ccwh/jlgCQOjJdPxOyDE/3kxoBYaIkmuS9nSnCUxBSyOyStEw' + b'EUPClOI7PzTRJxAfqhh7ubkqMEbfc5JBbi+pWPxJkytwVTVIl4OTWJzu6GNmRWectRh3zKII' + b'RRv1HTwBEJ15pS608TCUJcIo2Uxjx/AHF4Vod2sUnzo/Ht70lV9Z5Cb04Ma2FnVRKpEpKU3F' + b'SkuTLgi0/oQJZU55eUlYUVkSRxJIQyyktcdnxw2fffo18BNmBF2ACJL2D+6bJLd9S4CXo3Xm' + b'2UfbKAuHLH6kqvAfP/tTb/nz693jT5ib/Y8f/WUM4mKsIA0Nbf71130/uu2nf8N2IMKpqlsO' + b'QkZHktcraGwkNQieXUWLRYuPj2jF8k3Z23/6KFZEIh1xjebYqEVjqPTlRpDjKsV1MPxsizx3' + b'2SlzA/ITSg+y3/2SNKZPm4bihIzLsNN1wMWpbTJJPvHY1uiK010b5KMIsFXnrKWuQfaRgvWF' + b'9X6WBKgxcPh8fA2S6IeMSC8Vh+aW2sqYhKQu91ZvDaJNOCt19kUm5+KsyW50+ZlxokvJNpzL' + b'v0gsgZKU6E7dCwTY3FrMjxtJCZ+xevvET2wlGLF7QD8ZP7E60bGL0HEeglqKcKNI0qej/A/N' + b'e5usiYCKrNnlRHu2b7amdzXZ48bVWNMml1qvrLXnmAcc4p8jlABcLbz+qlQqhha53CxOYd0L' + b'+Vczp6MdbG801ywsU2RjTVh9mPGSVkj0vuEo/JHJJ1WDOFdTaRa/FEaqB+6hcF8pA3FNZf8/' + b'UI8q0xgsXDhN+1lb2PoHnKm5x4/4V3XiD+8CRAIApGu2ASNeOMJBrY1UMhYiSiez8lHGrVcT' + b'xExGdgz61LzmUBxzGtjg6NxQ6Gti8c9ILGx2SHIZiBiED/9+VcAnkNnGnIc4H1o4kwSTp1RK' + b'QTL4jhAY56ZvXJvYsaMpePzRNRBNT9KF6bsZM/GRBf//e9+926vbtid54knzFZtBIgzuZ+Gv' + b'XVPntTR3+aectpDMZRKQ0bins+EfH17tP/Tgi6DsbLBPPnlBsG7dLuveZ9tJ8hnzl85zEbN5' + b'Ea10XlrEQf9UGAbzT9+1VVu5MRu098bsk5ZN1756RPIhCS8P77WtbofVBJaBCFDdtna/v73N' + b'OmVJUfTN/0lb5x4Xs7HEGPEfVGb/Z3/IOvOJ2bjoFNkB1M9RBKHw8B/B1cKsTYNURLIUn3wE' + b'7umL44SW2xBUYToIcZosQAWLXm3OF7kEV5SnYEjV4aMre5xVu6rtzn4nlkp4ZLLqtRcfNTXa' + b'2RJjfC0HaATv0Zc8MAiSRVVIAc1gP1SWZC22K/b2XXhX1r1sT156gVVdgtaU5Ef5ZxzK5xFJ' + b'AE6YUpnsCDPjhBADZzODrcVvODi/yLjK9NCUyRUJAq/UsUcs8bzKMge7v41EgEkGqwDDCZeT' + b'8i03uQSvpSLl/soNfrC3LUpw0WBRFNzceZOdJmYAJkAUjQUnB696/S+6iy2q89xrgb94tgHK' + b'HVKR2lxYtyZ87pVyVoo2QoTHlRWFl3/gbA/NLwClSaHSYiZ0hFZMFqG4gFF9HJbYGgBdDXFD' + b'yx/Dc9FDzJbyUPv6OEQs6OvN+OlMRplyFUJtPXj/i/Ff3fFUdMIJoABREN1hksAexWPu+All' + b'6F0q4LTzAf0QrgEmFShNCRLHtOnV4e8fehmFXlH4nvefKyWsNsGcx85e3xLW17dZeBMaw6Cc' + b'ZLg2c/t/P2YfddR0+3s/+Jh95llHx+69+3nvr2+8lUQfnrV4dm4LI24uLz1JaXqWQpdLATnU' + b'WKlfaHf0zGrPmjt/YlRTU4ozkdnnDRkEXSfz5LiyMmMtenXdOlMXbYxWrKiPjkctQF4BH4Wj' + b'S5YiE/GHjjS6+xlPeIiJT749GTInnDVbgwyw49l5Ux0Hs56ZLJIEmE/x04/GSMsw5RmMlM+E' + b'9FM0dvuKpoy2Cxw1TkwvbkyHj6wsd3Y0ljvTx/dZF5wQBfcuj9lkirLPOq3WfWFnCokBnwwC' + b'FUE3FvR5NA5xIg4DK0b0YBNkNbYnrbatL7BrQAcQ61JQ11SeqDk19OH7mjGmb0ckAUg7QYpO' + b'TpWWJiL5/KvIdVfhrXCbCAlA82SwaDE3EVf/u6ezOIoICRjnEcBaZ03JmeIEPT15vEkrxV5N' + b'68625TN/F1lkuXaoBYB74WTBk0+8KlfhmHQHb7SInxAf77ScYQVsUUzknupS2wHrzLLIA7bx' + b'KIiwn2M+RxyNmGiIqaHX0JJNnn/h4uD/ff0DcQifNN6mGfrEtg8LhMCl4kWFo69OyfVLvnM4' + b'K9mAta3bdU5SAPv0vn/7zj1FcHXvrz91eeIH37svU1fXaH31ax9IQQwGE38Uvjcm0RCgDkKy' + b'q61//MLV/mmnL0QMzxngZf66+NKTlBrb6CggU2bhXva2ZSn+RUhb2moAZpKxTjvjKHfa1Kqg' + b'vonow0zSV2yW8hjqn4iTPBW7wENvaW7TXlcSoLVjr1KBR/Y1759OZ0HJzaIrbF3uu96/HUuR' + b'sP2UJk2m0ba2vqBuU4N9Jgi7dz7uOW9HXFfiES1qlJHZh1Z4MbwNAyUXve+5bB8ilXXOsfEi' + b'nCghNPt6l1eEyO77PfzpElw0jvrEohO8tCkIVqwzEOUOmY5cXJ2DC49uDeeNb3bGTZjE7ePC' + b'3h6ywsVTtktiWy/ThwswPchoifhXTSe8GyKYSbfjFejZr263gk0/r/dOW3x7bHyJ1Fl2zZQp' + b'1xft2XOzkCzecDkiCUDoZiTLx0pKwVgcMGlJ1DThoT6JNDrTjHVukou7x13fuujoRvvEE+bG' + b'iMoK0cSG67aZHHMgzYYk18CZBl0caoEAhXhw1MxY1NwZgpYbKMhjSOfJdPa1m37tdHf1uyz+' + b'oSeHXPn6P8QJWjpDl0i37AcvirswLlOf/mhPiwQiuzbZgZQLgO0feBeYDqFyAp+MHHzrDQiH' + b'vPD0vmK4uIcGn/z4jzwWrP2lf3lP9qKLTwD4MrcQpRPBxh8hLZlFrHvginBq9gfsyyVFidp9' + b'9OMXJXftakl/77v3xJsaOzL9hNWtXL5JbsIhyjoWx1AOKzH6+ec2+Js27ra/9s0PZq648tRi' + b'rAmGmKgXtHDze3LpX1Iyx7ASeE9EY5JxYs9UW4phcZm4b2PJwEST29tziSEWqkftBxvQEhSY' + b'CL4kPonQz6zJhiVAO5HVB6efoW3TfSqqX05Kzzz7PPflLBaSQtau2h2WxDK44MYJn7bdc46L' + b'GcQimhegVIwgBtalp8saEIEGFJe+eDDgKFfz/n95FO1S+/VpLAHCbwibcCjbuMuPHn/ZB+k4' + b'cnmVkO2ff8bRbnT8vHhs59Y9ThNhwOQNNHiUEFQGFQaHoMG7QigdmakjpQ9HOrIrgYjbs5cc' + b'5sgAIB45l54ac4iyJCQ4QFpxyvwwzR7O+r9HADIuPpXCiwQ0rz+dNtxP3EPcT+apvr6skT41' + b'NKLJCUnYIWwhCsjMmnTE8c851o3YPpNUQ5j0EaYnTDRwkVdRzD33ahbJlT6UnnZY0UTCy07m' + b'NMMxh50+6J/EGthErcUX1OJYsiRmwDLFTQDHSF57MZQfQoDkK7hsfBJQfRLzr63Jz+qzEco+' + b'8zy9I042kaQRjrlf+PI1YV1dE8pKZpdupIizr1u3E5v/U/5HP/7W2LRp45n/rkklrvMmtoF3' + b'0iIBSyH2r9+5zn7fB871bv/p4+HWLXuivQ1tziMPrwre+a4zXSIszeJT74qrQxj8//j3+7TI' + b'nZrqcdINmOM7dzajtyKQZ/p4k5FIzxGhlrOWILxEDDwWcr4QkMHCRoHY0m2TECUyCoxhEqzG' + b'WP/0XG3HULYFz63z7SXHTQejAb8Kdd4BihZ/fuywFIWrV+3BqcjJrt0auh97G7Z99uwiOqQX' + b'817aFLqfuDIRVRhrgPEEPKCuRoseNYP8NsK2HnAl20OsSEG0blsY7cASgFQp/48Q1GJyBroB' + b'Jl3Qix34utETWIkiBae1M1d9Xi2IunvAbmaQGjus3t8+kkXP7Sd3NYZJGJ0yG4VrdpZED6yZ' + b'4bb3JeSvoGzScXAZgURTCjS7PJF1FOW0+wDd8bqnjkgJAE4XR6PletlMvKuri4UsqKschj5J' + b'N9jf7ov8Yq4wueEKoN1rzxrgECR8bwZL4r6NXRc4acs6+ShNRou6ouhBHD5++Wg2t7cYoYvE' + b'aQ9XEYkRI/vvh7LAeTlZFn5Ciq+8eKl2Iv2aB0pPIUllR6OTYRK4aO3F2pVyO/ztnc/2HXvc' + b'bGnni3DLjePUY8xzRi+ii5jZq1/eFrHnds9/yzH+zJk1uESjhGAxam+sIiWZCIDuYSG5xx4/' + b'xwVzjpDqbPhv3747ixNPrHFvR/bCtx5vV1aUIDgYn4Dw6//vN1IKJj903VuyJyybh8egUIYc' + b'q7GhI1y+fIP/ib+6ZMg8yi9RgX/mF6MWrsbq9w+95EybXpXG1diFWwZLWCSMy4gFrEZSZHlB' + b'Z1/MrqjKkmq8zy4tVSKO/aWAPNHIVyRpYnd9h9/a1GUHpVYwY6IdXzQTqHLRSzsKfvukr5wD' + b'1mmLY7G8QUHtG6lQldnTC7L8sZeDAEWdhSe25liIVGHPnuJEpx0dtxR4hvnSEcYj9xhrgCwm' + b'otGaUwJvVX9EIWIMus+e3mxSk2NypVX0vgsIh95jZ0hzhg9IGP7Trf0xpVtbMrWVRDKRtaVt' + b'siMCM3XWfCvVTQplC8RQ1CUjtfdgjg0ZuIO58c28ltXvZCN2+3R8mrhoeXN5HmIkD0VfJbF4' + b'CHdOxgjrpUfFbdTBTLbwpc1+L5xfkw4cevmaw6lqXBfgTYd4cwR/Lc0/TdEEYh8Y//E9mcw/' + b'vDfll4KZnycAmnSD844vRhLIvbxdUoYak2OynV37obdA2nLitj61CAuLuPIVbz/FPZHovlmz' + b'JhKkk9sWIEEZjppf/OofmTU1MZXCmkJ+hJjzmc++w64aPy7709sedf7zhw8KPCVCakBtaNmA' + b'dcY+eeOlmRs/9TbjaKQFqOefdPLc5HEnzDFZgfNtUadKfBfqjj5RQsrNMiopSboNDS0oLe3g' + b'q1//gH3t+79nt+MWLRXFaAXdX/Ts2gCcQMeNJ7I2UU7mXYZfr/YsPWaJObf2lXVGetCCe23d' + b'XpkY/K4+N3bhMlAiGXNt+XDYyW6uD2J//x78edEJ5QlAYb3QU+pRPxN32x0F5CAMnngZswq1' + b'nHt83CbHA5YEK0Y2Z6U840p0T9AlY74cWPSF9WmUBYIqEyWvhfQTRrhjI/opjXjGAbg2cfx8' + b'/XNDlIABIRx2EZnYt2/swnOwKOjb4zlO6WxrwVtvsLxxT9nuf97BZupg4OqHtib/64gkAHir' + b'szcK7GwGSGxAKneQ+y+/uBGBJG4OLl4tnhQEgO438f1SCDJ49gnzYyW4CygQJ8DUI21siGee' + b'//ALZJhtEJRzvgv+NJ9SCOLimySgJ0M8uI2oqExEEKv9n88xQ/zYD2uVM7lUZM3IfdNfw0kK' + b'DogDyn68cBGph6Ei+p2/TiK5zJ9iS+gOvDtuf9z7m89ckSD234juRmwGf+zjN1yUuuqdZ/iv' + b'rK7zV67cFOzc2WIvf26DfdU7T/e/+E/vTSkOIE9YVLfMibRjPx8HPVuLH7oV3fXb59IP3LvS' + b'+uZ3PpSonVHjvus9Z7u3//QxL9PTbU+fNE5CwogUQGZUQp+DTbtCd97iJCbIIiS9nFXAvNjA' + b'H7V9yuRJRP4tMtF+Oqy+Saf9YNP6JruXFH/H4ZF7VC2x04ZmRsHdz2QBGnFBLSK93FA6apgM' + b'bQq3N/PsnUGwvTEMusFnFJr0By9OxmZNkgojh8YknZS6OUdHCwansIED33WdnKEUh4F3pIsa' + b'BD8AIiw7dluPrezsXTgjWTRlPLkHYHygQuOtKOsH16IsKUo6csV2kxVkRXGSdvXMo50kipag' + b'oy/nITfC88Z66IgkAMRri6KijPFAp22ydu7Kp/828FoipoMEgOtMyiUkUqu9Kxtufinwu3t9' + b'hfx60vZWkZW2tsZ1lpKTjwGNbrnfV9TZ/0phS4LTiZf4zeN2+uSjYuDjEZtAZli4lUH3zW9v' + b'Jf5r/4yzz+BC1gTKF807NPDKRDFAHHJntPDkjTdS0TmJ/lj6rMuvPDWGYg9l375K0fLLuoCj' + b'SVH8bFx8z7tgKY1wrDt+/mT/D753v3vuecd4k6ZUOlNJNcTjbfwwjFibq3dfPYXPhjMrErEI' + b'xWW6s7MPs6UrL8LwuWc3KBpT4rLRxhfek/+uN1u1yQ+R6eLVNQ7ck9xnsOTh4r8W+7y5c81t' + b'2t6oPZJwGvb0BE2N3QhPto3iD86Lug2+gXZe4B8x4v9x57VNbsX8M/WpibWnNezd0RjRPsc9' + b'Zp6bGA+eBJZJgsxsAdKy4Ie+ryQFbVcQTkck6KpX7dI2Tb4pgj/nu9+6a0t89+pd0YbtoTWp' + b'KrSnV8eAlO8xFhF5sKIsMH3MWCkEhh9JM95YTMBAICFc1CN34EMq/0tL4cBt5m0ZV1Fx0Fsb' + b'mqzx4yeiHQY0n0JHFiz+XD0S/zUk0nQTVms1EqeNiUciJkpEOBUDQyYZeYDJ+UNb2z9p0eBL' + b'S65Piv3LR7Kp3zxqh5j8ggUzkunTj04odVicLSLwJFqoUi7DWplZA/cMtleTaPv2xuDeu5f3' + b'E3DDMhoqGQxeOOyLOk1bo1/c/njmve8/Dx1dHMTj3FYq16zcDSISQWDCic3zL77sxOQLKzak' + b'P3XjLSRj9aKr332W/573nu0qsg5lKZrrlI3vgKC4TQUiGqojXyStfeKvLk3B6rHGeCzkBH4B' + b'0+yHHnjRWbvFD09ZjKfSMJqltsr9FwAQnLhieEA6xOCbHVC+WvOpvhFISXW14mLgxNKm0sUS' + b'/7fXtYX9/X68dlIsgNPjPCS+EQWY+mxCwK3FeX2AuXPfH7V8Wo1TBpI6xWwnjd1/JC6veaQh' + b'am6P/J1NQUh68jgu6YMZhPBWY7+fFzGwViEBQGCRVPuI/IyFnQ1bSfSSAM3JFSK0ssS4HUDX' + b'qf+qxmu7o56w5QoOueVZiRwWA4TfLWOysIGqUCsPpRyRBEBSpaz5YM8Ttpplwm+zFi1abEQo' + b'6MJ+RRtVM/CkYD5tsZM4bbGMCNpe2VEfwQGaTIh94UPLvbjyyP+pihaFFhlOHdYppy6yTj/j' + b'KHFtfOBDu7Wly92wYbf7Cimmn/1Fezh7qpt9zwVFPs4mCQRrlOlhPJP2RAmHNFd14h7tfujD' + b'F7Aihi5+TXwWIOZEOPSwvYUmEFU5n/rbK4oRQ41DEIRW13IPLHOEojrQA7g3feODReLgBBBl' + b'v/m1O+3f/voZxVYQkJV2x48vC39y219F02fUoKEOkdi6vXHjUkg1NIaiRYrGa7B+fCvsSy47' + b'0fnxjx4OifwLsYyYpulaaJtZvFpYRGiC4RC6i5bKmiD34X1AJLo2X4yeQS7iSEyC+tZjRei2' + b'bWm2tUM5aVEsQsrCBGtbdbsDj22Y8+l3JuHAcP+cmiRf1eCn5lJOkFLThhZxe7VPugAAj4hc' + b'9NPt3aE1F1fgWRCNkK2P2dfESeNWMdEqnzzTGldTC3MiCerLj4fNPcXRsyS03tNuJ6dNwlTq' + b'xMgV4YUgg6OiEBMLjYSgfOnqO7WFhK2mA8mBlGsM4gCKRMZTNolDK4dcwaE9fuS7EYiZlU6U' + b'7gutJrLHFhV1gAVYb82ZM5uXRgLNLYqBSQXHVPfwvzgACm1Om1N85Py1sbNbG3dqMg/cMvJj' + b'D+tR7ZXlNPO2y0+xLr7kJGvholpN5CEN0OCCqSfsAeeOO55Kfe327cGlpyXTePZpEx9PFwQ8' + b'6Z3E/TUp2PfamANZ5PsmqBZJMw5MX/7iL7yPffwi+9jjZydH2g6wDzVmVSkFV67YnNlLit7L' + b'Lj+leKRr1SEiAjybeINi59zzl8ZOXDbP37xpj0+MBUrDckkU0Y033BzdfNtf2a+9tiv81jfv' + b'8m/97xttEIpieUlA7zmwMM3YSPlFbIIQjiH0eoYV3vHHbJZUbTYwavZctrpEUwboQpMVBMm4' + b'btyYFfXuhUV9IqlCqb0kLTW3tJo+6urMgEsAsCk29ZMWuWwlycfAWy9fF0RYYuyjZ7nGF6Cw' + b'rtf7LuKkwWvptHxSkhEAFIXK9AQKVeLYeRoZuAxXFI+fadXMXmpVTl9k2akJ1u7GXkyOjdaL' + b'L262HnmgP2xoBA59WgnZoND3BlEsx/FJamO2vbn+zo2F/AuYBvyHNcgs9da6VWAELrBad66P' + b'vL4uJLQ3GK9e8LJHJAEgnAVrH2ERvHz9riwAC3EgwOqtCROAVbLZyUlOZk7l34M4F74STAHZ' + b'FoeUsiVPPUWxn14DbBO4eQr8eLOL5qgm5eVXnGp99h/fCYZbTjwd6bma/AByWh/44Fusq955' + b'pnXP3cvdH/7ggaK9u5tCLEBy0TXjo4mOJBFuAUUExR2efJXKVDviy5SNK4pSRblFPtIz84tI' + b'nPPoY2YkFx9dS58Nk8GH3ZgjOiI8su8nYscdP1scHg16zFq8pDa46Su/Tl/73u+GbW1diXnz' + b'J8cqKwG1LyBOuhZTo49ZC7rjRg8+8FKY7uuPnTAfGGdkHHSF9ltPjrtwfZ+cf6RQi3zi8t3y' + b'CtdOAcKTIEXaaBYAEZYWFr6KniNCWLethbb0xxfOiAdkRjYiOaCp4cubA/tsoMVI5+UM38cP' + b'e2Xqykkkmlfs+4UdGKxY73vElgH1Zju1JHt5ywluAuncDrFkVMw8zqo95hwrDmTYxi3N1t2/' + b'WktY9Cpr/Wv18vmPgArzly1KBR88P+mUWF3ObU8UhZondXUNbI2msOXLaaVFNBVbIWqjADg6' + b'BwaItzr+YZnutmjDwz9iLsAD5UCEonx4uw/29xFJAATYA68DjRc3J5J3ptHCFpUEEINdYLzP' + b'0lsPvri+yC1AekET7EOnigCo6BxOaNEzr+BxSxeagwV/NEnF4US/D0fRQhER+vB1F1qf++K7' + b'h9QrK0YahYRRVNFacWA5y4CfZx6t4KR3v+ds6+xzltjve/c33U0b65VBl5h6Ga8IQcVLD/fd' + b'oGlvu/WD/7zBnji50ojc+XZr4iCOu9/67nUpidn5PXn+/PBPESriCugTbZ+Gctbh1xb+Vn9l' + b'JWUh3T/26BpPmv0v/fM1xate3pb5/r/f723aXB/r7OgLx1eXkTvQN1rvvY3t/pc///PsN779' + b'YaQ0377vnpXk3YvjkenE8+ZQAD/ipD3DSqdIOit87hUvqCIcWOrgIvb5Wtx69khF5wpKtH5d' + b'I0QtspfOEUYkyR+5Da2+39UbOicuIIDC7Khzd2hW6J/piYHvejfiA0IQiwI4vqDlpPuzuTeO' + b'7wBUDNmSAyKcFdOPsqYdd7HlJSZZfyT68ld3/BaJZAtRqH3R+ArXXzQz4R9/fjEhwjGXmDQN' + b'NluPKQFuP24m048k1YenpB+TByjDYBy7BFlPG0wGZXlVoq9B+w++Ap2huUBsqZqIuFDw1m/w' + b'6xFJAHDNAEUvBg6qo4Fk8odkv0VDip93BdDL2sPSaWbg9N6eL2w7dVlu/1SGK6nkB+3VGlvD' + b'cE/L/og/WvyItUFFZWkExr008W+wC/fdxuS23nH16dbnv/getM65SSnzWwu4bh2dXRAHZRof' + b'WGwMJCpq9nfF1oTx400Qi2pS+DPOPta6V3cQQrsxxO2WxBdxe2Kqwv3eDz7ukKcgAiXJ1V5R' + b'cyG/gLUIlMcP7fwQX35NGPQO9COZQQbuyTch95nbUeWPqcbhxUw6Dg62ne86xo4Gi5YhNu5J' + b'y+anvvav12avuOSr4be/cVf0D198JwEtRbgXZ4N//sIvgv5+D33BOPfpp17L7tzVGrvhyiKf' + b'ST/IiWmaOK0Zsz0tID51Rs4x8yHMdJcUfWMpGsOu7kxQt60NfEUnOnpuLl8kkfkWQT4hST/c' + b'KePlXCyPPbPwsaZYEWAjkcm2BKMBss3asisK2rqDiGzE9qKZjjMBUFIDN8+QSlhSMJKkn3Fz' + b'zoqa7QX2r3+80nD7zZsbpMcIFs9J+me8dVxIaLELUA0xEnLtzukVNGbYT6SctitctqyZyGH/' + b'H2fKmi2diIrGS/0rF2rQl3HUMC7ihL+yIOgPjZVMkLyB/hxSOSIJQCIRyRu1X/Nb1BvgWdMh' + b'WkC9Pd0AVcSi7u7ce6tD+yEAysoCFi5YAX2WYv1VxBh2NYWE/YYmo07ujtxf7dE/dN1fZE86' + b'ab7z7nd9nf5WKG3hFQf3XZx/9pxJ1ue+8O7Bxd/Z1WXtAY1WdngNqP5J2sgTG42hQE6EdVhF' + b'wpNJNTUs4rj1rmvOtu6/dzmcckVs794ef/a8qX66L+1s3dbozp9XY33s4xcCCwbUsQHFiHCR' + b'FXHsCzdv2h2QC8CZvwCN1MDbcE147z3LSWiXdN56yYny9zdIPQNRkTaKO+NYRR0K2OGlIbs5' + b'Ypj7wYwT1Jd6g+2HCWvUDJRyE0CQlKStXjq4btveEFwC553vPrP/e9+5p5g9b0h/ZIApc1Eg' + b'Onfe/TlE873+v37jLqesyA6JxxB2435F+sjtjX6IlBsvJbJT7ZGkNJYi8b9+R3vQ2tofn4H2' + b'v7ZmwF6PjmFdXWidfnTcmIAx8flb6onrr5crbwiMV06Zipk2moC9/4QFMedd56dcrT1ZDyR4' + b'5AiUaUXU0h4FL2yJh8//9yuxLZt/j0NVJqoZHw/OOzEVnEeo8cKZJAVHdaFFL2kDJ9XBojmm' + b'oCLFc5VWZQEjVZQqiVFLHMYhNJKboiHFoDRX6FNwAohGhKcxzNwtJSdQcV4UYzc8Qg8OPmpM' + b'X45IAhCPF2UJ1We3lRNPc9RO7yNRuA/AOzZEKGJzR0jr5bnmXyLlm9TS0karq/QPYCBF/OnX' + b'YNFEh/v7KOgcwDZwhgmM7+bgBQf5RfVpIXyexU+WHHN3W3s7aDQNrBUBl7jsYQ13DkHcCcDp' + b'wwQXOuzX/eqaMpnU3Pb2DohBrzURNNs5cydGiNbB5k0NgMavsnZ1r5SS215QGQVPPxx3fv/7' + b'V9AtTEBH5Md4dIgZLtpe1xjV72yirpR16aXHeyeeNDumifT4Y2u9X/9qeWzpcXP8u+5+2dvb' + b'0B4VFcXsxYun2gCLBi+9VOfs3NkanX76POfCv1iKeO9ba1ZvjzZtbAhBnzGOQs88vT4UNsMZ' + b'Zx8jWHFAUnpIKbYLK4vnnnPOomDVqjqgquvcEsCJu3szxXYs6Wyta3e3bG2Jy/dh8tTx/n//' + b'16P+nXcuj/V3d4V/eWWJP3WCVZQHzSjsbm3m6oDVShW7NjQLokkg18A2qfC6kb5zbbRlUzPB' + b'UKGzeFbcx/RLwhBwAXtJnNJPSCQ4IV/5WX8ICpQSlEbTUAieclQMDb5j4dJrkRcgBnESKhcL' + b'EcZjrKH7nqT6sSL0r90SeI3tHbHJRW3BnGWxaP60hIJ0XPxOkqxVTDjcO4qFQRMRNwAWe2RV' + b'lWajtA9OA8BLZbxvT3eX2VZoDLXdETKQCKLt2c7E8Q7vA/HgPukGyRGpudWxr3Vv7NsRSQBe' + b'eulmb/6cD3flX0lUOF8QkQgJlWUpd0QTRErAPi8GfBIxA6TW7Ue+Ui5AFRic7s7J4+aIlHS4' + b'sS5bEKClT+LLnoHaKtf7Gy6SJq58x+nWWy48ztQhzl+/ew8DJARewXgRGvr05uCPv381QoPu' + b'gmgkTTzJQGPOxEkVwTnnH+VdfMmxcTiYu2sAwmp67Xh7zdo91vknRcEN16RTlkcDGa3m5sD/' + b'3RMNfnvXnqisGBRk0p7v2GtbRx9H5NnVYfjgc559311POb/+5TN0UWRjrnc/dFnkTxu/zuno' + b'jrxZtQ6xBnbswbteIVDKYd8dBlOrQ/tnt2y0f/LjP5qOTTlpu2IcVghQclkI0VnHBdZ5J3rW' + b'8rWv2i0dmqyRdcrUCOVqPPrW1zc4NSRAufA47ZdtB+tVUDsxzKLiAGzVce99JhlP93Ra9//m' + b'YWvpjETmHWeXAfLpFKOqgfPRQsZR//IFc12IMrerobYAAEAASURBVBDTKc470nMx2JKK1JcH' + b'KpKuEBujbdvawEuwiL4D54tdkhYQjj0BgTv2rx7zrBMXOvbV58Rt8BfJvCsVgwzOaoP0Qfu4' + b'/UjP4hIbYlFEDoGifLIoTRvJp+L00M7XLZpneBby4r5bUZS1u/oTSASWvXVrk+31NAFoWmGN' + b'wwEMSyZ1qXUmrsUpwrL98z942XHA2YNnIOh7UtxEDa/7wNe54IgkAGozuuG6vPk4gw4gXzAO' + b'4LtOxvn8AT5l4+3qj1vTAALJIoqjjSZqDrgWUQm6uuBS81XUddmy+eY49njD5YZfczC/Japd' + b'9jbA4ykyRe7es2/xt7f1+t/6xn3B6pe3SzOptvNumjbGauG2NrZY//nDR+MvvrA1+w+fv8JA' + b'e+UUbYARsIV95pW485dvd1kWIOAywaorwtj1V6ULx415oCdTqPbKM7ywbo/rN7bRF77t4GEW' + b'zZ/hY/jmPPTIXAdJ7Oxygu5eQk7LQ5d0gPbWnU64dlsmEMc+akboTKgw/hNaFHbluCBmo5e6' + b'6nzuxppq5CkW5yd7gnDjDtebhAvrxGo/ERHJiJWWlct1ich64rmEf9eTyQjxlkCZlFKFJwh/' + b'drGbB6XFjl1SBIEC+lvRbWqXxGxUHFEjOQMmwJVVtFXBecg8cjgNkMivIt2Gti0tLf1Bc1Mv' + b'EaGxYM60nPgP/bXkAUo2YueiU2OxSXj3SdegZ4nLK3OPcEv7s9hdcc82DTG1jvKH1S4OPxST' + b'ID8Ao9xTcBi9h6VQ9ARYLqXkFGzoLLa6++3otj/EvZgzwa2dWmZN3JFRnoSImBGhQQevbfe1' + b'hUmestiNLjk1HieVfaQ8LSgE2gqqfkNfCyfSG6rgzboJCrjGRG7ygB4cLbQnUvH9LDbRwl2V' + b'ocCWQib1TatAYBKTp1QLL4sjRlGSO6EKKHDl8MRlC8z3JoAumX45Vbw5cnB/tBeeN3+KdfIp' + b'C82Ne5ua4Pj43bPQiV0Pv/fdh8KXVm5LYsrZr2IclKKrzk2kWzrjRb95dHviW1+/N/Olr1zN' + b'HIzc3u50CPqtt2PzxgQqArj9wO1m8h1gmrKFnzU1SMyaxvV6ddmXleB8GHcqL43c8jIqU89w' + b'bs700JkzE+dz/ZadRZ9WlCMYUjoP+KDoqClw8FQ8cpYuhLiIPiOh0I+YYgaexf3EcRnujoGD' + b'ZO1W+MKGwO/o9gOiIdFZ2kqGEpEgRWCa1lK89UgC6pKYKCTphjObRBsqG9f3hp3tW73Tz5qN' + b'IIDMYNrFq/Gw1pYeac4RlUtVH0AuvQGI0Ylzj00E5IRwJcLDG0JiP+Ca8bgSjKJ0UzuZG6Jl' + b'VrBma5i55ykPgFDLvuHtxtWWs4ev6FmiU/oHb5J0EylJaFVJBr1UaO0G6ee0JTFCfYuizbuj' + b'NBgVKK7JG1CPnoC24r8Qmz01Hv79exOkSrNxY7Pt9dsjn3frI/FpLtvtITT3iCUAcP9tSg6m' + b'ge3qwgZKZxDVh7jvgaDCpn9IiaxORCnFCIkT9Pb0g8LaAYb6hCFX6Ye4xaRJVT4wVebd8VPf' + b'f2Xud9foB6Rdv+jik1CQFaEs6yW1VidtkI3cte594CV/xXObQZkY+RGyRmHpsz94UcLBvhz+' + b'/vltyd/+ekXmkrcdZ8+aMzGcv2hK/D9WbbTbu+2wjAU7lOuM0iYtkMHFfoC5rEVbWHSPFu/B' + b'FIF/qh4Q9E0ZWJz5KhiPkEnvnrjQjV99diKuNOG92HgVXIMd3kfCMTb65g6UcmAnTquJUqT9' + b'sjHrgkXoAn4SWK+u6XZWvbg+PmNWZTh3fo0jU6/EejD+vZt/8BycPLI/9onT/anTyuOtzb1Q' + b'oMg6erYcphDveR0BdbR0IlFUKAJSWZZkNraCDTvD7D3PetGqTUGc622APeUiPqJiMv8+Y/0s' + b'XPQS1bc3hRHw5uEKUoKRyJXcf457Um0GScKxmrpJEHJyDn4Mrm8tW6AxiGPkiSKpsmg0rtAu' + b'19o27sKm/SgtsUtaPRCH/7sEgLevi2JuF5S+PJMOAcQIEAWZaOydU0VDwyDVZaArGYuB7Mjo' + b'SfAZaGQ/VS77rk7rnylasAsWTosqq4yKGVtrBn6Xn8H5q8b2KakE27uFJ525oaW11ShvZONH' + b'Kx/cc9dKifyDzx5eK5PVISkEvMG23nthwt64048euH+1+xcXHRNed/15qdfW1TOdXWzGQgka' + b'EN+HV/Jm/9ZsljgwbHEb1XYFGaoCAGl6tuwjAgXtoXvMXZLQSdUmzkukG4lF2RIUljlTLcRb' + b'nHgYrJUbQg+luJ2AGbe1ChVIQUfSFxhJztwmAgvUl4+zD+HSEd6U3dnpMypjLa19bCusCMwF' + b's5BFKHa3KOuTJfOf1Qs48uotgf/wCo/MTGFsxiTH/uurk4Ie1yDlRPvCho3hu7pHhEYSiT41' + b'05S4ZntjFAI6YuIZ2ohGJXV9dOwc17r+soR1832+XxT34m29cWh1UYReAd+A3LYk90iiAtl7' + b'yXVFGkkpFPfpQABU6Y7wbQjbo+Ju0EUOrRyxEkBxhb8j3evsoQvKFXa6t8GzxhMttWsXASUE' + b'h4jT54u+dkEA6lrZPwGjTBw1zkO9pFfeAyfG4Xrf+jdbiVmzJ2limlkoDzsjE+YrO4hPmf6W' + b'HjvbmjVrkjH1daPF1+REVLVefnFbuLu+nbyCw4SVYfUjARiPT0UGEmce/PShbnfjhgbvvAvG' + b'4yQTEjduObjdG3XGsFvf3J/0qZxdUFNDHhkFhVDm5W+ta0CbrNkfRa7FHrvuiyO2RToBdTQ0' + b'W7zMiO86MKjBzd+lbQ0lBXIhab9DAC/lAEd6cwcv0OJwwoQqj/wQ5ALIiS2S4iZOHhefN786' + b'qyCj2hkVQJT7EVsAYN9cEH60gGRyxQGoIYoQGqJfPJxJvwA8HP3tyrb/d2enLLIVOxhvDCDJ' + b'4KvlmjKmv1r8EuvhyAFZ0ay2zija3hBG24CkIwxZHoPWW06K2bIQKEM17iusaTusKstkJqTS' + b'1vbWEmve9HiIuVJBakRf5mYqbSFexJj8pYOR5h/dDNpQiqQXLBHMCnvtunW/GWanGFOzh1x0' + b'xBKAtWtv750/5yMrmTeL6DP2e3gEktevaa9n1c5KmMGVEkeDIE2pMqg8umEK/YKJryhrVZf2' + b'W5uas1ZvBBoEvuRMQ/PiXB/NnTtlsBM4OrJP7eAVo3+RBIADjCFG0vxLZS4CwKBFK57fwurZ' + b'P3XV0Nq0pckd0UDPZy8sjd6WzXuj8y5YIugzDEBhRN68A1ORoZUe+i/6NCBWPbsbEAWcm3Ck' + b't5LTKi23DFWJVoo01Cn6MDWVf/o+GWeMegaiYDpRhyQxDhLsEsmGoX0QHyMXnRAcGo5b2Opz' + b'lxH+b1159UIgx6aTNScc8FOAgNDvxUXx2Ic+erLsCHKccdJ92aCluc8+amoimjBtlt3WsIMa' + b'cSsmoIxmIN7b7gfeyj6aHI1wY1bXgOYe7vpGi1oJAQgQ6zOt5BvACOFKz3DK4gSfDiAfbNuY' + b'ncbzkEbQbBX7nEXtycY9nrWrvZRoR8v/2cMemZDMa0WAjLhLZjsRWZKIw7IdMCX934Ng9e63' + b'JIpQK1ngDoY7SGXHGzxiajvEPwUjdog1vQm3IwY9RZz1B7TI5Q3YwzYgzacmiERESQb5Iop/' + b'3IxWk4V1S1OZtbm53Hplj9YN5rYCmwGTJZw3n4k7UESSc+OSPzL2TzngLD12jrmhm7TlKpJM' + b'0CuE2NHRVRghwxwf+Q/bFSE+UDQ5mJjgvRGPvrudaWPjM9DnlKb8UNryAfo1cjWH/SgWiiZA' + b'71A180IYnYlqbCJBSumALsMQgEmcE2GlFM9Efc+CKyQAHNaeW/QCTba0flQlmqhjI/Q4Yywx' + b'mNx6bPXkLJW7HxAQ4yE3/B79pn9NB+s7yr+AfrcXnFtLBN4cu3X3VpzDYiFBO9b5x7v2lWfH' + b'QUmC4NLR8g2gFfpzSEVjhsk+fuICGkn7+d/UKmIuS4NMnToycDx8hIW8cmMQ6+4ucXr7Z1nN' + b'PcmooTMb39XgWyVJobyj8QfC4P5n46AOud5fXpFIkFtCYKPAxhHZmrYCbStAx2uLx/0Vh9T4' + b'gZuPaALANFiJNaCbxVAmNNimRiUHkQ82c459ZG/PPuld3dydjltnzGm0lkwGZTEbM7+3NJdZ' + b'r+6pNJKBJoqgribgp57vPCwCfD/4ySAuVAHOmKQJZcJJg15EO1FQ4Y1W30byUgNGkX/MKJ+s' + b'a7a4LAvZrC0015jlYvgK7HXB9w+2bWu2Zk4iGhJ7v9HMj1LL4T+8f3+YBUhjeUkeJ64PAciX' + b'snmEyT2V/zX4yeXwWUF19ycB6EAGThBGnDBOUwaUgQvUjyqqFa036LqYHQEAMQtK/Sk5fpRi' + b'2sQ59bmSxZBExVm0dAGHqRMiJVBYMCDsijIHBZoRpUep6Y0fVvPDnKgzpBJtS+Hg5phm2FOk' + b'd7/5vmyqehxeZ8Qnpb2Y+7m3t/oXHttrTa3wYfdwMATAjh4nvOnOCd4vnhmXOvOYwNu4KxTu' + b'oPXQCj997zOB09SexWztkKUhdimV//uQh76BH6P37huo7HDfEivu3OD1l73GjvBkTaS9iE3K' + b'Bd+NJFBe7prtQG7qwIzg43s6ijEHklQCLM0y/mFqsYAJl0iODMicYGKwJ7eBp5ZoYApweIOm' + b'pfyxsXyafeikSpOrrRfYMikX1UZxuq1b9gLw4OHJNsAhR6uQ+SEttuarJhI2cfvEhbHw7qfa' + b'3fvvfim9aVNj7LKlnEEptk+zP1plh/M4GsfqUsP5Q7xbEKGsRA2ALJrJAwvWKp6274Gl8+ng' + b'/S0dRruC+gBgjmj37mY+DUs0tv3y8jLiOsoM9r38ZhFp8eXAStAfOlOK9xEAXD72PWeUb1L3' + b'NzX1KtmLPXfRPCvd8wrzAWsQFgfyPpJ41RDaUe4+/IcloSo3QEMb5A0ehVIyWrE+iEisFH3/' + b'o43+zY9UuOhFsnNqst69KwmaYlojLcXSHnOnKR5s2ZOIVY8LgvueD5QkxCGzXfTISi/x/rM7' + b'w9NPKguffq3C+dUfOm+aM+e6F7duvfXZQ3mDI5oASMmxcPaHH2d2QQCg6GD8iWO0tfjWtOkm' + b'w8fgu4sA9ACU2tBZZC2clLU6MAsmmIGSBHJcixVGgZgEcAymW67AiQa/54+N5VMEYObMiZgm' + b'41ZrW4shLiIAYj+bN+5VFTny/zqVaf2zRmhcThUBQIb1hxc8+45fPJ8oTvjhJadhK5Jd/kCF' + b'5xopJveKB7pybOegSBL3U3Mn5JSAWqBSZuYXv0T9ZIEEUFyL5aoSFktYrlbyQIHwQtxCq6Ss' + b'1Ft6XFWiP+3bRDii20gbb82mxjaIeJtVPbHSJABp60JhhxolhXOQSp6gDlQ35ENcX5pyEU+u' + b'i5qbuqOq8WXR1NrJduOLTxoboAJtdB4xPaeNHFLDm/ODfTrOW17mric9t74ZEw7MZ+oEO+K1' + b'k1PHB9Fxc9Ku9bAVzp+ScWonZVPbm+Mks4lHvRmQQaAKR0317L+7osV+al2J9827JySkAJ5a' + b'5YX/+oHWcMq4Pn/ivFmJCz/y19aay75d/PJrXefyFv93CYCGiDn0R5bV3/IV3TCkAGrf0RaQ' + b'JkrZZMCsBzTEzH8uoP+sPXhWLWILsBdCsGFvudWZRoPmMArmvDy/hDaUm2A6hm5ocPHp91iL' + b'pIlFR003lyutlepUtfjSR/W7Wsn2s28hHKhONUfeYVq7ahWJIdADOFFrRzb27sv7M3Nn+PiK' + b'7mvvkLp0GDMZELIwYBYpC/WwFS0s+touEWdXF6mFKnw6BOckC3wsYkgHxVNxFmrSTbnL+EuS' + b'IUQgSPcA4VC8hAgmSU0Hr5HiVOf1KkQAGrcC6XcGFjbV6Xv+2bnbZBLc8FpjdsasqkQyieEX' + b'm3lba689ZVqNTd3Ojp4Ocx8YAGwWcxmX+BylE3N1Ho6/KfxUwDHo/+FdWUi3FVs2p9dbXOtF' + b'q+uK7BfrUjHyqVrX/3ByuL4+4daU+9G8SV583iTc+dUy3nF7UyIzoZS0OPTHyk2u29PruWef' + b'mM385C/3OskqL37Tz2q8adu3hleV34YncZYQk7wS5o23/oiWAPRa8aLkCr8/sw7OvVTcRItM' + b'CsGWZt+qmhCz6rcTaTcw7wUW1NhVRKRVzJpX02XNHN9jPbetxugAYgNEwEExV2hCpD5Rh4Ne' + b'OTLvLVkyC6ZIfDyQ5SoiAj3AELe39Qh/wBw70B9J1Ch5LBKH9JMM1p1chbY9bgNbxpSAq02s' + b'wtzzOtVk9xJmjPnLgWMXzSYKUh10OMuwxWdWZhw0snj5vqfomVIEtr+07xjf5ATD7doVmaKF' + b'nKtu34LOKQd1WgpAzCZURTKj3A38LSTW5qBOUc3KFTu98ooid/KUceARhjhg9VuLF0937TBr' + b'eele41PQ2UMUKOo5fAOMv/9gpYfxi15dFlJ2gBE4LsGDyz1g6OzYe07vzN7019Vuwtvj9rfv' + b'Cu97qdxr63Gt+ta4X5wIpR7OZvqFLYD1D1S0XzxR2f/DhyvsK5d19a/annSmHnN+0aeXhf49' + b'v3vO+frvxoepZND/6OpStx+i+tPHN1n1HUXdKIwfPtRXOeIJwLp1P+zBHPgAy3Zpjj/k5viW' + b'TRmrDHfRAoZj9AAdxAS0oQeYOK4fV1Xw+FK5fWe+ozThjIvYwAEW6kETAHEshWnOxQU4DXKp' + b'JqAmquom7XNE+GxuE5t/6CifmuwE6LhPrvYj/OORGizv0+9CSVnuJHc1h7IF72OnI9XBOgqJ' + b'1DUcclAcHulCjuUJ0gA3HuWqMRymu+JEPLp53+SBW4pn6CFD7gc1DJUtQpfUW/vW9JBrCn5E' + b'HfQBv82aF6EYiZbpAlEVgWjQ7wLSNFJXT1faFrqS39+FUi6DLwaSYk9E7rdIOTYHCE/B0w7i' + b'q7qO5gypwyx82AYZg0OwBrx1dbgsQZjKS2wlO/BPmgdqc1UFK34LiWpcfAWc8OXtKben37U7' + b'+pyooT0Wa4EgTKlCSOHGx9YVRe8+syt27XntMcVlHHsJQa9zr3dmV/dmPv3V1bGqimQEdIXd' + b'Toxsgxf7PXaHb2zZcsshif/qgiOeAJhxCqN7sAJ/iu8mxE+dD2aY1d6aQ7U11/BHk0O4APXt' + b'Jdbk8j4zaIWTSJMKA6ou0z9TEKNkiUdUHXvR/r+6psIC944EGN2MnwiA1jwSQHcGkIl9YCUH' + b'qlX7QzIZB59/f8rNMkt60naMKm2QZYUr6ZA6Th74ubDGkSrieckpiA6EirnjwK2WSKGXHFbk' + b'U+q1ICXgSRmroLr9Lxl2xwF+8q6G+4NSMaQUTaFzB7YLOsEziAUwsQVow0d3hxyoRGZ+JACj' + b'ZpCupxy8WxE27fOHFrn0BpESpHKFaYRSgKFgtAWm4vW2GQBOsWVcjl1gDiQN5PZYQyt63V+y' + b'u0OCTXo5mYvZvQxSOLohfPrVIL12exBOrXKcS0+Lx9nro7O0vc7eTO9PHy8tqq1+KdubjkXf' + b'vb/aWr29GMkOl+SSTJxxtuZPjbzqcs0TOormnTS33/nxI5VyHAluuKgpFWx+wHJnvcs69vSz' + b'7bKiVcGnrooRwehYX7o1k+5Je/+0fcfPXnjdFxjDBYMvNIZr/9cuiRd3raajVhVmkaHP1G/7' + b'FR3a1SbExdyr5Rh8fsYjjwKUUSie8yN/cr+6RjugSVkDAQCqie3IvigZtaeHpJlYBNS60W4f' + b'PK4rcPPFX17WCdtmGyDACnLZcYbZTwyAAp9HLywQmzj9OETAIe53pMUvzh8gHmf3dOLY08Xe' + b'8UAVjv6ofWforoRS0g17v9RE2AlbAxGIgYKwIROn1qI30ljlr9M5mXdxhpEuF9mYPxxTP0tH' + b'YESC/MV8isCCmIzApehDzL/dmRD4MWDSqqxML3tqQ5CtiJAQjG1ARQ+6EBVUMspXsQdUFcL5' + b'D+v2ht6tD3jZT38/Hf7uKS/De5i5ovZKkJo2ESeVC+PFV5wVKwbMFM9NYgmApLzhiniyZFxp' + b'+oaf1Aaf+dnUKFFUat1webxvxvis9/Zjt1vXnNaa2dyYCv7mthp/894kjsOWdf0FHYlrz+6K' + b'/uuJcre7L+YDW0ofkCW5qUUYmMQyOM6u5shp740ay9zUrlGaf9CHh5Hxg77/T3KDrAELZn/k' + b'50yE08wIHOCpmkGtvUmCg+J4AwIXrRlVUJg0DN++2UtIfsHZsX0VZ6ombbUmppKW5ieoPkG/' + b'MUqvA5iv9z2EliAFaMVIqjXrV75j2K1F3OzWLhSU+q+gvftuHvims7p5tMIppxhF6DjgtZEU' + b'jJQw2rVjPV64/8/f46LY09bA2xefglBkGkbqgAM0MPdyOByGhAIbGHSzpRqo1wNNqbAI3qu9' + b'NR309GQgAGBtsWI72pQ30nFrqsutdG+duVwPRB8bIyGIGZ4DdZFmhNmnYDNg2xK8tskn/59v' + b'vUJCUaLKnbOXxkJAS+OMleaO6W6ELad2olOk7WDO4cc8FsaDr0nKTn3m6niCEHUw4CwlQIk9' + b'9EKIr2o/iP4osGcXJb6wsCj9vTvd8B9uj9m/+vRuHzN17H1ndTi/fnZc+B8PTbCvOr3T2/nD' + b'm4Lv/DoEDCRhwf2jh1dmhWa8flv9zcbMlHviof39syAAekUMSL+NRYnPMl1mMgQcGbloMDNA' + b'hLX1gp5LXICk4sLCuuKnGUdzWDbogy2aTBMBblAR5l9h6ezoDdBKj7lSSbj5PYh5K/7gDqos' + b'tojEQEGyRTT+JKO/cuHj9/9OY4UmUYRJ77AVaf2HFymkZQqMdtC9udenr02rgTTUPNvX6cPu' + b'NWPmYRjHBKhbhJajIkKr3IaFRQu+sbEbNCK2/5IAqLYdJyByD1oTa0qt9HbiY1Qhheg5+for' + b'AdCIgpTmhhY+YQTBpvrAf+7VIFrxmi/gFHf2ZCf80CXxYNnCmIuHZkI4NNqy5YtaqEClkYrG' + b'lBYo8MnEF+Pg5D+xyrNrK3uhvyAPlZXZZeVWjJDszNodqaJ3fHtahMpCzqw2CkTnp0+U2//z' + b'9Di7u7+Py53ok1el6JEoRnZr6o2W88yRHzxSY17n2J8NAdi69famBXOuuxNnqb8Fxe6Ar6UF' + b'2tiVwhy4/6zD40KdN9iBmKYO2hFI8wtMPlONyas3MOHUqF7jeDD6ZNc1+aJpCoinQ/IYcmHn' + b'jqph8vzCEgAGvSQMJ4wZn/L8XUfApzuCWkLa2LiI4r5VgolTP8BnxUC7z9K53wuIRcP9A+z2' + b'RlegKON8UYh1YVGfAbJCN3GXwfyMrK6OdDQOpWxlZbG1e10Pnc/DcK6EoPjg6UoxMVjkV6SF' + b'LxAQQo+Dlzd70VNrAwXxOCYcd6Ebgh0YzJ5MLlIFCkGdFYZ7sEV36O3lDfhqXZDd25JOnLq0' + b'DzfnYquyotgCYjyzaaef/ORFHQQDZUmZBuUjJVx5aRhUloSZT94yKd4HrtLH3hb3zz3OTexo' + b'tALlSoC2Hpa9f/59/mwIgGlwaN/OcvkYgw8LGn1QpFhp7C4yCkFt8TVpVDTRPBRGRJXlDylr' + b'z0H3gTD+hPefs2Hvm/A8IsLJRQx97BIA14pj5Iu4DJlshFlnIY5Gvf22X1I8RiyAfCVv6idd' + b'N8znf/BxiULToCY/Ij0nEZK0pEftZ10DZp+Dn7624EYfwEPMePVBAAQGqz5XgbhHHe39+iqS' + b'o6GOuoDUkVt2EfoQL0N4sqgNF8K1Iy1AbcdkT4HQhnsB9Fy3LSQ2P7A21SOVczFpw60br0pE' + b'ShhCtl9cbXMBPHlcv9z2QA83LgtmPvFgJRzRFu6AhS0CGamCaNb47lhZMktEaw2wUG7w5BrP' + b'WjI9E33qklYBl9NgGq0CK+jscu2iRBh1886zp0q0su3dTb5NPpVWNiKbDvjAgzw56qAcZD1/' + b'kss31t2ydv6c6x7EeeddB5IC8nqADrA+MAwPtk0EoB9/8bQcwy0UVpQZM2qUtFKdz2R4/SLp' + b'Qj4A1ew3Jf5roqleFeYiwUrwjIHfr1sbt5mAGXRH3IKKSUwAN3v8AEj0G/X1B67icY68Mgrx' + b'lR6goIAEZMx/cGJ1zahF3cV7gp8kU0pky8KjflC/SsciU6tyQ0opiAUmwuZvulz3oTyJujvT' + b'UVVVNdsmFJ7yycgNh3ykWFuWv7s5sl6pC8Llr/rRlt2ga7N/nz3Vjt77lkRI8k9HOQmkddH+' + b'3UyNgcaKaHBttLctyoIjQJ4AYOcFHab9/yTbJTEIGIjKMjTyy8mKsLMpzG7ZlYlfsrgDF+gE' + b'kmOV1dEV+et3hLG3LkW0wBGM7OCDfSMKiExqk0gEU6FyCORIA1BqQIuHO8pK+3YNXnwYvvxZ' + b'EQC9L8kWb0Xz83a+jmq608TI4Fe9s63UKi3wA9CskY2+va3bnzSp0rx7NSlg5Z2WM+UNzJwD' + b'dixuslDmIrwwJAEUEgDNGwBAx8z99TRFjXXB6stSueQX2q0yz6W3JlOE0F8NGMgBW/SnPclL' + b'jrYFGxYPUJLKmemAXGAdHqDQEVp8WvRaCkJ/Ur+qaIvVRai1CIDGjwWvpJ9QdXF5pgNUo6/P' + b'd2fNAtPL9B0ImwMUAIOPjXdh5pd/9CLw/mNK3Hn9ZfEQUE83h/Ofw+uXnkXku7CIJ9AO77dP' + b'Z7O/XxHGkq4fm4OL+cTywBGG3/3PpuynVseiT7w94S+eSZrxgm1Lvh7t99dtt/xxid6SyuI0' + b'6Mi15IFIWnV7/AB/sdisGiidJmtB0WsXpwIH6cBbsz3pNrRE3sJaKy7CxbUvHw4MgILHjS6W' + b'FV50JH3v93qfKUmMk0lwGcBIozZN/boDc+D8iYPgwqavwetz9pJdZ9FRtebektIE2WNcpALZ' + b'8ketbsgJEYD4QLKNwhNm0QYDOHqFJ0b9ziQO/fh6Zkl7Y8qaNKWG/ACa6DkaIts43FMv+acj' + b'1OoDdYTWw8AiHNJ8c3yo4nPwvITygcWnYxXj0HwTuc07CObggEV9Zy7g2TIDShGYE8ws0H/A' + b'eJw8mWZxCUufVW8aKFMc14V9RPwAYc7txAaYbLy5qthSRMTlJ0D9IeMO3FyiNrVIDeTxbzSI' + b'NQXzYNLL/tud2eyqzV4R+/TgmtO77YkVnquwCJZitHx9sffxH090v3dnZH/5w6kQKcLkECh8' + b'Sb0yYcqxBTUdOCmNhwBUcwRzJ5HW2jpAAHINLbjJdBOddvlJvfYvny2LtsL5j+kMg517wwgI' + b'sEcKLj0sX/fJHoeluje/kvr637BbtO7OU/nRnqi9f3NPymrpQQ4tMPUrao8ce6afc/fuNwaj' + b'VWmOa00oECWOfCfuVFh0Tk5CB1vUgo6OHmvDa9vA5N9obdtaj2RgJAFJAAPGp4Ot9Q1czwKT' + b'n4Df3mcAQQwhGF6NGhuYPfjwM6ytAuGHNTp5PHEO5BshVALx/sAkgPWOMjYXpqHUYyb/Hc9C' + b'1Q++QhcBRLl4C9a0Antw7RX7hwCwktP9WYesQ5AeIxIM0iDTVLyLOQqsChl4EA6GQm/t/woo' + b'DS1Qd9Pf/mUmu367l/r+R5uCv72yNTGtysdgDPEAYCzEq+HUxb2JGy7u8BtaLfv+Z3zlqhhS' + b'maFVPHhuZUPy7BNLrZlzZnI396KHWLM5iBLkfpxYYd7aioGgXPiPa8xbkgYy3NUY2qu2BHJG' + b'aiQX6IohDzkMP/50nOUwNDZfBdPkbrjA3zE9UMWPvOA0HEIJEh5A4dDIdrRi+Qb7I9dfJLWL' + b'3Q9CozLVasDGVpipTAWBfZBQZNgtyKccpK4x92v+sTJviYCYSLmOLISkjOmMUmv4I4Y98XD+' + b'FNJkegeYXN04N7EQUrWgAJXLc7CAXuqBPoq2kYqRAAZOcEtZUUigkxx8IhcpAJObFjT/9NL5' + b'F+c6cVxMdYYZaRy0+IX+pIxgerTwFhr37rXK5s3jN+p96XX5x3cnAygYBEMYj6pjSKv0k1cy' + b'Vp5hbzDkuvwP6RB2t4b93/hFxiI9WfG/X9fsX3pSdyJgj56/3zxBP2Del53Q7d78x/LwqbWW' + b'c87xbnjUDNdYDdRmhMTgt49n++NuddFlx5caPYEszmu3+r0Pv+ilipOR89mfTQoWTU9nZtdk' + b'XfQlnoBrejO288yGYntzQwIouAh04MBpaJHe0Fq1ecstu/NtPVyfY56oh+uBh6OezZtvWT9/' + b'9nX/49ixGxSMc6DSR4hw4bwgGYf10otb3B07mvyZM2vimzfvJm9dJk7W2wNVM+ScJpo4Uxjt' + b'LwozKYdc+3o/1LbC9okSqW6V3OQvPPt6tR3CeVZl2JOxQqDAtPh5Ocvv6M8RgOHVevu2VUNP' + b'meUxeEjKNsRWG+7l4JQTbdtj9b+0idx3DAmpu2OCCy9K2LHS4lBBUfKhN/NRglUPSWHHE+wl' + b'kVl90gTc+uQpk4kmHDRBCjjTwaIjKyNxIYPHzfPVa0gfxFNQw4GnyGB7uTL41WNZv25vVHbN' + b'Gd3ZK0/tSgTZ3OLXmyloB4KSG2BY/pSJ2dhZC/uziOqJB54H5N3gigIACrovjkTebx73Uu+7' + b'IClVQI6G8okBCl+AKLrq1O6+6VWes7Eh6byyM+Uj6UmnZa4kVDi8+tQu7+dPlTvrdiVTOJdC' + b'HaPfcf7gJlfBm4329c+SAJiX8aNvR/HgCrpzyuvpAgpfXpy2vb079u1v/iZz0zc+7P32zmdY' + b'b4YnFV426nctSgGyKdx3uFetJqo8N0a9edgJjaZhZcOO58dZU58Jd+CIQM1MzXZVdpDEZ8hj' + b'ud+EE2vx68Woy8Gstn/h9Yy3X671Q84P08lQk5GsiIWXW240ewoYKYmYR75GYK7CLACgCnqg' + b'gDgG1h1dOkCFkRpABK6dkfupSmQK3LFjhzV//kLZChG1GHVu1j+a6iqLrlBfjCBB0ySukxkt' + b'1oXZj5/am6inRi2G+zeHGdJ+JXHEii4/qcd6cVNxZumMNLm55UAZWfetLE3f8QxqfzQaCyZn' + b'g5Pm9zk1lT4BR1Zi5Xo/hhMRjTGJTkj+GSaEBj+12vbYdoD4Y5ww7ekYKwhJD+9eWZaaXOEH' + b'0yd41kyUgeVFQUCsQHx8me9feUp3/MEXy4KNe9BOMR6YHJsxDTw2auMP4cRII3wI1f3pbt20' + b'87Zt82Z/5G8ZnP9ibOUIP+aHS+v/0IMrEx0dvelX1talJBUcTNESF83ABj28AHsF2Mv+x4df' + b'9zq/qVtXIOLmdhmqcIT5y8IAW8oK4NwO+IQuKaXecDELniw80yssvw2scmZ1bIIUa8NeRsTG' + b'IyFNiPQzTOtvBfLaG3K9usKGR8uFNWKNOrMmO8k5U7VjZoPM1dSmjDyxF9YFfTjMhIi6hh63' + b'NOdAYJOAg6gSSUWtZFluLN+LbT+mhY+W3g9FUPiu/HpQZQgAREA1C2eFjEMetvykKMSI/cfR' + b'fOG50UoSlwBJVrRsbsbfvCcePvlaSfSLG0kkSLXLNxVlPv3fk2LjSgO7OB5GKzYXuT9+uBIf' + b'g3DAmZTArHho1U7w/L4MuSxcNyDox/nRPaBZj/OD2VOsaNmimEO4t0dG8NRnLusIzlnai0NQ' + b'EduOuLO3Mx7g16TYBcvLutalJ/XE8QgM1uwocW03WL1p4/Qd+bYezs+Dm/mH88mHoa7N2275' + b'H7YCQNM432JGsiw10GMrsv0/+/S6IgNHpUl9EEUipSaVwCoKC5wqSiXjstzjxjO2ohYPb7W8' + b'W3ItgvPlRc7h1XGBFn+6rk22QjO/E1MrrPh4BeQMr3H4zaP85j4XUVr/TAOkZt+vKt45i7ut' + b'tgGFoCCqUohABUVyhH6qGnR1iOq4Nu+vfZdSj+fB2AeGQZ8Cetmz27PmAPwSFNjZ63ftRIDO' + b'KikqeSA9h6QrJvbC3KyVKgRozqkOQXG3dmG267OjcbhXqx0jFV0Loq//0kafXbhtL5jiBU+u' + b'L3bmTyGFryIAce7+xZPj0FWEDgQhmFXtOztbY+GrO1NWXVM8fHhNSQiyj/uta5u8txzdS94+' + b'J2rrdcMdzTGfvbz9zIai8JGXShKPvezZVWVRqjgROecv6bWWzMzEl9YOBJOZPqB1fIZsJrTx' + b'qCgV2qBkmWCFZX2Z7jz8ZegMPvz1v+k1btp263dRC/09oh+62bG/jtg0eOGsYzP9xtxOGL+J' + b'RkPzjFJrGP2EcVdWlQjaaUz1URWLAy7OP3HEwqJJyYQFIstmdY9QuCDoIs0sUTQ5rRoKL/bs' + b'I6zYEW4+wCG1Xf9GXS30sXIB9A/XR3FP/x4q1lvliqrgf+2bNXnh1mAN0mVCQNI/cTv1p64h' + b'bDduXPtzt5rjO7ZlrP7eQvMs5jnfQxj34MEysWVCrDraO0vEpxDuHNO2gY5DxVteCrIyKEMk' + b'XDGKRnPJCH+0SW9oDr365tBAxE6v9tC6u/bUSul4gJoDxevVXSnnmJnZYOGULDwjcudNysbR' + b'EcQ//baWJP4O4QXH9PoXn9qVTCQjt6w0iM2oySbOOrovdfWp3W4aPcKJSBXvPasz09xpu289' + b'rsdfVJuJBUIpBu3J/EOpmP80XY/+ZEltWjkNKDZRVm9OGfuKeXOef1hq3bz11m+hnvkIpLIl' + b'b0N/vYohFuH/+/oHMxe+9USczfZX5o16PwtPCUB78MscvnXQMq6sLNGQaU6PoeSyweQ9k7XP' + b'xGqmfHDoEhQbjx8AqDqFi2qwUp5gI/ab9TawYM3vggU4eO3h/iLxv+PlobVmCcPt30l7Cogi' + b'7c9dFDlPrPKd517xAyCz/OfX+QTe+P6GHcooLMOJRcpyJcbYx6RFy3t7A2vzRqEt73uUvicS' + b'Ztra3V2KxFRf2+gD1O3oYHCoEgFWlxBTob2G9dzqbgcP0EHl6r7act9QVpJBCAejDDQJUjKp' + b'nJzd1AvhMkUEmvxRzoRxRJlRoxaoifiGU+9sSnibGhLunra4/f27x2d/+WS59/yGIr+xHTQa' + b'mvaDhyozVWW+88tP18e+ek1z4stXt6T//vI2DXFO8hnemIHfkjKvOqXbrZ3Q78Nrrpw799o5' + b'o1x6SIcLRuuQ6vlfv3nT1tt+Nn/2R9fT6d9GmXwmDIdJMDCCw1qncNMZM2uCq64+I1lVWeo/' + b'cN8LutDMqmGXjvBTCqnA6sRuP2v2BCZgwezk6ioSVRq17wh37neIW5X0V5NVKEbCMAQwwppQ' + b'mkaDLWMwzFZutEMfkauGkzFAQKLJ4yy/M23APhKT3jRGMbTpAgNpftqyplzOaqzKnWtfmdsC' + b'GGX2QBMNIWQzjkT7al3or9mCmZFciHD/qAykXoJvggW1YXThSfEisBCBNCDZXQHGoxRgO4F8' + b'Kx2HT/ycBOZA1YsUAZNXt3eDAoQ+QFgDNmNixi+eUh8w9oyonoEeINy023ZWrdphLVgwhbpK' + b'jBI318LcX+3kBOtAd4vuRGUkOykvDpzX6pNQEvMsgjEMoRqQNAbuZhXXt8XDDOkqT1+Is4Pn' + b'hA+vLbJ2NFXYfZgOzzyqz/vYhe3xmdUe3sMQDtp0/V+0F5MxCalopEHd1ypSAlq11V7iPz/W' + b'kPnMTydNXl+fumvu7I9+M1kUv0coWfuuPLRv/2cIgLph07afrJw27eq/SCXKP8YivBEhc5Zy' + b'2JlRLOgnKZAmTChDke84M2dNtsswWKeR08ZiDNDEU0qwpiZ8u0lEL6V/vn7pBSZMIM4zbnYB' + b'w2lDQQtyX/NTQI5tFcVZa3plr0EzErCpJgsUgFRWYqnMwhGpAIthYpmB8M6xSa4T1Xizixx+' + b'MoSk7/29ZdW+h2eyDWn849Bm8nLSz2shKijnHWfFLdJbx3CBDTDPxeLsrbHSIYiZMFuFyQZl' + b'JQT6aGoXLDP194ZX+812oXamxHtJAKx4TnQSBUjiTJeATgGEmHOpMoUki7BG6ADIzkPu4k4R' + b'110c9jaBUFwOKGmJgSaXYlEFxZzV24eanv+4LSpKhtZJczLRr58vs3t7XdobmbRlLZ1QZfwK' + b'BrEeGJnGTm0jLfeyZV3WvFmZlABce7vdYEtjImjtcdzJ5b69pz0W8Km3Is4hP+rm0Qf846NN' + b'WjK1K3n7J3uz//DzqYsfXVfxczYKKxbNuu6z6+tufeqAN4/xZK4Hxnjxn8Nl8hTcsu2WfwOQ' + b'+QymwVcYUzamwztdqh6yMyDLTZlaaQMkgTvB2BeOXEl37mxGpATFgdmQ3/PLv3NCdaldWirF' + b'89jq02Vy9VMAU21Vr3X6nCbrvAUNpDfztAWw+9PaJVM0M0dqY/6YKhrbIw/PMIrT7/0DXB/R' + b'vwvBq3szMtRQfsLWxrRK+/GOXiuWSjrxcSUOelKLJWe5iv6DlpqLCL0VItJ+rygCoEpeXdPP' + b'dgA2ze8kUfYi1oRek0SUuAzU8v1Ajasky3K4B+oW8PkI1sEIARF6dc944v5lAu6wtm/bbW3a' + b'sMN4Xsr78rVXt5BzorFEHEDPSiNTnHlUr723Peas3pEKkkUBorhnI+o7L2wr6t/SGE9vaUik' + b'O3scv4X8L0gm9r/8qsb74m0TM4+vLvEw57lLZ6YT5x3XG3tsXYn/kR9MDpAScqGOY+19Uc5E' + b'mRVMv8qqWXR+4kc3etb15+0GMiU8mdjIBxbOuf6TY63qQNf9nyMA+ZfduPG2PRu33vIlls0/' + b'D9cLiHugxEOf5IfFxclYzcRyJolY7tjLtm1wQIoy3eSLCEolbKd2xgSFHOcPv/7nwMKVWCh9' + b'gH7KK4xPhQPjwIrI2EO4HOm6cpz+9asc9YocORn19JhPSFjONqMLQPTvWEVLpc0eWnlOisk1' + b'ubG5jzj+LsKlM4i/vBnvJA6c48Ls3VHg11TIG3j/FogIqDM2rOu3Xl2NSzCPFgHAi5Pkua5d' + b'NaE4bG3LScXFVZNxB1BwlwgFiUBnCA6apDHAxK/dXSXnIM7nCMjg83lAcYJNPiJ9gKUC0T9c' + b'OivtzJnkRbc9Vq4WRe89s5NMU459zXemxt76lVr74pumu5d8tTa89Y8VNrb84EvvarYXTcta' + b'AHzI9EhIAo2G4Dz0cmm0YGrWLikO9yk49n/FEY7oft41CcbC0s9byfNudj//2fNS33hfQ39J' + b'IlPMLvQ/wMf4CtaBQ1rDQ0n2CM34cz00d+5fJZN+UOnZaSywQ2eVJk83iJFwck4IoaUYyj/0' + b'mgO9N54c1vp1O8EDZH9aUkK0WjfzWeIj+duTceetlxxrrV29UxRgTIMz0pMFHTVYiF/wu/ox' + b'+yFqj3Tx4IUH+KL2UY/cYpRDwKzVN1pX/jGSAnbdSZsQvwv2/vnT+N4jH9M1LHS2TPG1qyGa' + b'XJdABFA0JWnaSPFWzCceO2UJe2o1VM/CD3gkKsd6kE5g+7YsKeKUhJVdiHwgILSTJ5dHdcTL' + b'8lynuGISUPJlVrYPdODQtU85Km4//KJChqLYyu0TrBRS/JIpHYbQ5tspPUw1ehdllMqShuHZ' + b'DUX2jZdG9qcvbbWu/8/Jzm+eKs9efXpn4td/Wx+2dLpWGlqxelsqxE6fYPum2P3wqXXF1qUn' + b'9tg1pV7c4M5q5PELABMBRx/MAACCOhAE0b4xFVE9tq/h+lutqP01yzn+c5Z91Kett//lHMBG' + b'f5y54eYat70v9YX5c+p3bdpq3TymOke46M+ZANBDppguPcc6J9Y0c/4JgEWfDzDzcVGYnotO' + b'ZhoqqIrhnoIK5tmzp819+A8vegsWTg82bKhnX6ct2tgK6cTYAjRZdUgBs+fWWA17GwdvFGDl' + b'KafNjy08aoq/cT05nsYIOabxzi9ufR0Q/I1zm4Vvvt8KN6AuLWJl6z2oQuVeK8AaJPgUAYjh' + b'MJSYVpGr5yAI337PFCtON3CYFut7YeFQa3sQl1RkhAVFSaNNx3PX8nt98jrm4gm075ajeym4' + b'LEFPOYaVSr3+qEULXz4CKhnM9GwDHFKF2+tf2S00ZgFw2sWVkwEHbUf34Fizpjhx0H38TbvA' + b'B+Tep7dMNLRvydR2o4iThl9dUJL0QZLuB0syYa2qS7nPvlaSuWhZd+r7gZ3t6nMx/brRCbOx' + b'B4LjH2ad4L4XygBzte150zjFuS/cMSH+nXurwsmVXjijOvj/3L0HYBzXdS58p25vWPTeCIAA' + b'SbBXURQlSlSXLFnNshUVS3FcE/9+eVbiPCdxHL/EiZO4x1WypFjN6iIpimKTSEqkwA6SKARA' + b'ovftu9PfdwYACVJssh3L+S+52N3ZmTszd+49/XzHqilQrdqyNOdxGvpL7/mEhmJFXVmXFlwu' + b'1HrA5ZOEQOe9MD3AUAgw9A7sZOZ7f4X6WN9C/PEtbOGNg47/M/pc+s9/VS6Cony1qupTLxFi' + b'1nkH7QI//I8iANXV18GmW7LG1LQ7OV3IpXxvqJcYTive7zAL4XFexFuiA88UD5m8APjlHBOc' + b'uDV8T/xX//KXgH0SkK2mQJI8awJfYNDoeHID7t7dwuobSpkDxkAF/ropKQDBKfzVa+ewI809' + b'SIin2Nrzt/NNALIJUKMJz1ITBi5a/Cbq6wkBxBldKiuhe4WkovYhcIfGAlejR4iYgCkVBexz' + b'/E5/pmcAntXRhFZFtw/gTJrw+GQPBq6JxmqqQa9lcYwndhJcsp8BCsu2iUz9fvb7xKEgJgi/' + b'BzyYmZcfYJvfaLX6kFBQXlko+Auq2Xh3s30+eErF5bMk9dgJBRQA8wUX8fbxPDaWdrCGgnHb' + b'1kJXRm5XKiZDlaWR2yf8/XPZxhP5qnbLyqjMgC1B4jxhHI+Oi9pfP5VjrtvrkWeWcOpX7sGU' + b'hNpGEF8ADuEGxiS2/agprtvrBk8JIrDActGof/qH+VZdkWpdOy+lrpyZYognAOCoQTbk0wMx' + b'/UZpsCabySEtcOQAMw9/nwkL/oaxkrvZdau2OV5piihvHs6qcHDOq7HrU1P7f5j3P2oCcMUV' + b'V4iDJ6qKdI6fjajxxYbCrgHdX5Bb7Ret4qSRMBOQMYHgFOV5tdkl2FHf05O8MbT2RDsHHAVt' + b'h++YT8OC82EW/+nBtdh7u46y+x+42garyCBMdWpSU8rx/EWVfFbYa8BVhfKj537Gp/s6+xMm' + b'5CQBwDsS5CH6UxeYFEZKnSAAZx9yvu84zkR5b9utMHUdeNfhQ5fzQTttCnO+g3+X7ZTNh+lF' + b'zwDdEFArcdvzNx5cGEVfXSoy4iaOO/++E7+AbnDDKAo6Z24RjKWacfRwmwACwIIlM1n3Xngo' + b'YEgjm8q8GQIAOHktmbEort+mnfu7Q6x1wMdCHg1xFxMZ1yo8iTQcKEjOWvpl+dM/yle/eON4' + b'piZfs3Gl9nY4rB+/EULyjuyoK+W0v7jLwYd9vEhugJuWA54dQRztPYbyk1dU9ablMpgLGSAt' + b'SDewRI+Y5ltNAvcvrzjk760LWCgIYs0s1nS4CE1ME9HrMg0QCwR38nzfmMhFUzwFJekLKtPm' + b'dfOTokt28kbPJmYVrWZcwUqEfWfzn7ys2drcnAVWZ9yKEfn/BwFYsOARKT5uzYXYflP3CeEK' + b'jGCDQ7b8lsGL2VUu9pWv3p656vL5LCkl+K/t+xY7PH5MQCi5mV7vixlRUHiCeYPZDM9egHeK' + b'MyMA1u2UPcRzzp5QUwv27O2X8p2CgPbv60CJshhAPAJsZOx0GCy5GWFYFBYsrFQ3vXFIlClg' + b'57yNLusDl3ZaBSD4CTJjU6PJC25us7aJLRf/i8mJAHRb3LdrAtAKIJZEasTZYvvFezv3HuQG' + b'nB4ANLkXgXbioz3MKggADGx2oNM05nZGf7QQc30Z1ovCLpd6k0NACPYHHLzP7zTf3rLXvO7m' + b'VcwbLmHe7GIWG+wExeRYXogXZ1UKmR0HdSpPaI82ReIQUeqLTIL904XiRZIANQeYxuEep/yZ' + b'/ywwPU7K0IejI82J8CRwc6s49fO3O3jUbwASEBk56MGQW9I0/utNTb/9CskBNGHUCZi6U47N' + b'nyFYSApKEZJcTanEmjtFtqvNIWzczzlgM0BMIPadmJAUcICHTLUUBPcTbxtsw4GE+p0/GRI9' + b'ErIfD3yHcb1bGD98lM2t1MTS7Ix1YkRqnFt+f3B/12NwyXy4dqGZ+eF6+h32pkWfjJhzQElv' + b'iI5Z14BqLkCYrTPfr7HZ5RljRoFu/mqTbPz55z/Fblt7uTNlpNix4XaUZQICLPyqymGnKRRr' + b'TobQT25WkmdBXUQqC+eR3JZoiPzQt1yZVDtD6RyAQ+BRcsizPsea+1B3QFJDP0DbNr+1n915' + b'9+WAcXKxZDqNhUvTyJ5M3OqrZnFb3jpCDGJq8znPAYRrPHvo5mT5n+SSNogJrhKqALHOyeMg' + b'zlMpMPI7XSrnxqE8qqE7kOSjDiTsvAEqJiIjgMg2UU51fc4ru8SNvjqE7XXYHHf6EYqK0mCo' + b'C4JtHMXpkJeDjGLnI2B0KYXQww9MLsLpfZ3rMxkFe7ojNODcjNoc/e23j4nRkUEjkJ0n5FQv' + b'ZLEBXNNE4y9vFDlgAtKSPKWT0aOakrSmdpz+Do5MX/k0cvRxH+S9sFbMEpQ/vdkheF3MhgEj' + b'j0IqmYbvP8E0IUu7YZkkza7iJYAUnerKAUyEzU2G+laTITz6KYeEGpDC6nmi+ne/zIjpjPUy' + b'eMk3EQcJLwFqwYGZoU4wFrIGVZa7BWP15fX7fKHGckX9/HVjspkaAl58M2NzH2X+th+hAGlC' + b'PT4QLkyKRjlOuP/USS/xw0dGABCw43KJ3jmY4ddGR821MMjPQ9qTM+DR2YzCjD63QtcKAhlB' + b'S8cFlffDSycZ8RFFXj+8if2k5QnWl+pH4gdCZbf51HST0/AsVa3sMjc/s6xOWFI0j69yVTCf' + b'HuBiwxl5z90tmcfeeDWuOjOC6AP89DtulxkTZEKM/N2axV579V328TtXokxYFkv29BAVt7uk' + b'YKGG2SVibV2hfvRIjyyd1xhosXfac2GBDrGAU7U5YFXORIkc4p+YX2DVkw1dU+KPHkEYcja4' + b'5CnCMLXDed6pHyT4uIBHZ0sB4P52sa7f9fbJmkVAoNVfYKztu2CRx7BcaL2j4VpVDbCGFod4' + b'HwQ0QY/OaIJthQfPnNjnrL+2Nd6XZh5ZQ1l3RApNqkFn7XbqKxHh4aEE39cbteYvLGG7d3Sw' + b'97a/a15z2y1CuGIe69m/Ed6AOKIpeTa7gpdnVwsKQpHdwCP4UA0aHT0H4+blsn7nGkmEE0Ug' + b'aYYe9fDACGtp7WOlpbmsvFxwFecgtxkC0VSD8MWQZZj5xXqVff42Wcj28wJgxs0nNqoicAe6' + b'XAL70tGOn52Y2v+s90O1FZ/uwvU+tnG/m//0lRFThu/SElHvHKoASx1jl9f9xnzm3WwPiMUs' + b'HPvHTQAaGh7K0jL8EoSHrQVK0xWIdq9HDQ3J59JZNQwus8tVrSJXR0EF+G8wvBFM9LeRLrm7' + b'M4ucYuZzY88bid19VmynoDnCXlkf5yzpvXy2/ME8uaaoXCx3lDF33Mv614+zX+99n7V2nVRG' + b'pWFd82YEM6hKjgrNcCxLu4VyXU08GTChHjh+F2lAxpNpajrOjiHMrK6u2AatIKRgkuSIY5BL' + b'8NbbFzIQgHNKAcTtPbLOrqrpx4QXbQgzqm5MhU1tURQTzGb0p0mAzT11lPqSsgCX82EaXRDE' + b'fztfgD7j/0Ubzm/vN/V+9gGUq+wvA4plKWPZKyYCgqbtA3+4bXSjw0kFiMHCHkLE49nnhgWW' + b'jLK2wZbGg9SA4yNEAKZ1dp6PAGHlUSpcX7O2VszODxovPPe2sObGKy2HN8RllTWyvuatkJaA' + b'Dg3ucs+VEg8dXUVaANbReTqc3Ey0lRY+rsGsL+f12xDJOKuSgLuAHgzXYyKeZEP9AyjTk2Tt' + b'kWJ9ybKgAC5l3+9UzxQiAvjxzA9fUrkHrpO5udXQVhE4CrAQHdqKBqLyWUT0nZja/1zvhtD7' + b'nGAVf75v3LFkKCYYpWFo/PGTzNz5FcZnepBRaAK0yaAYhdU4/slz9XGhbR+SFl6oq3P/Vl5+' + b'PxCuxSsxnp/IJLkVEKNKnTBv+D2aBaNPanld3Koq0PmgxxQNZFjEEfAyEEelDDyg0YgBlwwC' + b'O1ZmtOD1CW4U5aOFtCk480UztdGd1o4hGDcnbe36Qa/1TqpPUVNvS7qlcWoaZ4GrWEY9NXmG' + b'Jkk+OG59hLBiO3n+AABAAElEQVTJOzNb3BafZTgDXxhTlcOOROZNr2ylgScwIe6d+ybOs5UW' + b'egIJ5L9+aqv6jW/eJ4ezw3AvQjIh1oBGUsCyFbXi0uUz9J3vtKKW/ZnDTWtQEBB3DsNXDiY9' + b'lTOnbTTxT4xRD/hAXU32R1voM0kBlKmC+Fl704f6Q4v/UhouwohnbO8BFRSVcsDpP9AgAXiq' + b'JrYG58N6RlIJqa8T90/BbFjt9hcys40Dpr2cKphPHHGKDiC5/9Rn4volWSkQAIrpv/i1koH1' + b'eNsIW3v9THHx0jJt24b94sG33zTmXnWbSGrAYMtOux8CBa0sEhz3Xu1I/eRVhSwg5xw8OiMu' + b'h/IUtJoSwbxyvsA1VgkIXeb4aFxlY6NRSB3jcGMmGSr8sj3dhfodVwdNJ5CNpjg/XRNFg287' + b'YCg/e03hAT/OVs2DVorOW06Y2q/fRLABMx893vULWCov3AKBEhMScgSRhJCgIHKJwMTGwJjD' + b'O7mULrHcoMCvakhkXn0/cE9t5cM7Wjp++osL93jmr2fOyDN/+52+NZTfn6/z0l241nuh2S4k' + b'U3g4qFoNxaoR9pnpvccdDDnVYsBjWUG3Lg4OpezAmgmIbpSEQmjnyZEAS7sELeuahMDn65J1' + b'3JVKvy1ZvgdiHiFHV2Lfy9JdD0RFIQ/B5hl4//c408oONxe6C2Jfp2ymX/M6jQ5Ad7XCJpgE' + b'G3BYlmM2QOahkxkjouCYm5b9XxnR4z8JMXNIBHroxSfc2YNCVqVXX9nFHnjwKqWistAxNjaO' + b'bMGJeoHkgkTMAP/gw6v51pZ+HS4rRA6fOe9shRSTnvTjqbNzIEaUYWAvAKIGtNDpK60cvMjb' + b'YRMA6mvqoLMv7PfwXUcBDgMQYeRFEFHNhqMsvLPP58yfOBO9O/JgC+jC0pqYVrbBbWq1Y69Y' + b'xl4DyKwjvWbC9Uazme7cvjX8IVpXlpWw1YCMhvj8S1AD+vpi/EB/zFq4uETcvKndeObJjVxl' + b'DVTAwtnM6c9m6cggpAD48lF+DAva2XJSTG/Zp7mRAzDt6nBruDdcj7F6gajctEISPC6OR+4C' + b'f/i4wg2PRJnLHGIq4I2IrpFKE+eKzIduDVm1xQwGP4pshLgASSYZj1qb9pjKa+87uPuvlbnV' + b'8wEbAgoIiHL1Ry+rqBnInqqoLP1ux4mJobvQ38S43giGshpIQdo3ns017AqFZMpCf2mVM//m' + b'jhFkGQ4J+4FrA2CRv66ru+/lY8d+ddoifaHO8dvvnQDYYn6a/SkY8MN4nBU0qEGPkVg7Ly4s' + b'qFbk/jFRe2KrVxyC/17LcNIoEidKQuBo2JEKbmrgbuOEm4wF0dIbsJw3xUwscNlMIod8TkZO' + b'v+FV1f0OQ5qbkYUKLZX4eVDw3Bvl5HpF9lybNPQOOW0MCy73HTGe85rJ1Ms+0Xt/xFCPORRl' + b'm9ulD4tO751RJGzrpt4vGlKl5pIbMkq612vjCl1kvD7ws12sciwp//Qn61Lf+Mf7rcKCfK6z' + b'6/STpczBktJs8U8/u0b9p2++AlWAgC8m5h1N7jT04qQi2aLxVFowLTLahfaijzYBmH5myKe2' + b'Lu+Y3GP6b7+vzzix4HNCCkAaLSENIYSWLubMhtUrTkoGCFhhRASSx7ELphX29XlstxtdpL3I' + b'yb9P97u/O8z6EZpLoK1kjZcgBZEkZOfIYkyIKJJ6RKezD6YOztNonNIIBjpyeFC75vo6cf7C' + b'4tSm3ccd16x7wqhZcg0Svk4HeNFchCtSuPdqWeocMJTuActJRIpiFIjO0hnpvbXbFL7zjAIc' + b'AIuDfQ/cQ+dKQgZzIfNRgjI6v3ScVVVksaurQjxsO8hnIBhzHdJBBBJhjO3t9Ch7jnvZV+Am' + b'bKjkEQxFQUuW9v0XFbl70Nrm8qpf2rr1b6dZCs5zc9hMo6HC4PC5tWPcgpoM3zsiEvAoBzuE' + b'VRTS+eIwJFyUYEPmoHpyRCqGwawSh10yATg9Oue/hkv+BVV77jY0/jFEN9yN0MsQcyCkwmNo' + b'lMLR02fbVLXX3vXy4w2KJXkRSIW06No8Ta4sMJHQ4bTz7CNjUdsye2I0qOyLBy3/XTFgcCM/' + b'DIPIOQGRNc5rWpuDcyyEGIcQzMxOl2mlYKhtQgG9bBRwmKOw5As+TZqhSnKDKhm9IlAeJYf/' + b'TyMSbIlpGAAlda9LxOKnrF3BHEUQOkI9tDaSyghS5pJv99SOhA/Y2THIZjYU6NXVJSJNhhQ8' + b'AlMLnbJRKqrzUErK0vbv7RQQIWKfhf6QK4qqGVMiEIWpEi+kX0cAad6GoJQrF2hsbjGi+GIU' + b'bjt5cZjJtDip6Ke9Sk5dye/3A/UvhmDuBjLw1L2ccQaS8XNWwgZQNrE50TJhCCSXIG5icJTX' + b'X97uQCgw2QKAMozQ2IaCCCsMpllRMMXciL4jQG2yf0QRmDOGcRhFUVeCcnfJlHgHjorjJu/6' + b'jFOf/SWT0a35C4r5YMhpbd3Ww4W9upXLtwoKwYmTmDHZiAh4nBwV/9R3NhtWtictVMPomoa0' + b'oYAgwVvBg/+IKFUuAtoL5cow6PhP9V4pZmBRtcqqykPMF/BRQRc2PBxh/X3DrKuzhynpDOtP' + b'5aZPjPmsz37MIZXn81RRmLy4xo9fVvmmNqvFJYh3HGv/OYVPXlILe2ZxqindvaQmHViD5KKy' + b'sMajngCPBc+HYCuj++EFg2tql7UDJ70OwI2/MTK+D9lZl9Z+LxJATc0j2cCu+lc8sU/BoIfI' + b'Ot6UahTFzDY1Iw5D1+KMkGqXrBde8zu818atwI0JNb3FY0nHLFRa0THk0MChQPUMQOwfDYA7' + b'uK0TQwHe8pEPHPOe3GOg0uRrFetUQXneZZlx3pKqNEks0TPyLMUl5Opa+i133H1d0u1cm9SN' + b'bikj5Ckuzy0JMfLtsKH3irLrqpRba3Eo6jGZ1w46RRACTm7MpMQCzXJcljZgH5B+GxIATwZy' + b'CzLSj36wIV1YHNSzgkHojBKMSCDVeA54RoRfz93zyeXS0EBEfXPDQdmBkrn0iMjY1xdxs9cO' + b'FbNlFcMsjJLmLgnMgedx57akjJs+i06jQxsGjDr472yYXR/KziBT4YvJ5YqJj+AW4PfZC8Cm' + b'XeQFwNNGQs6E3SPLrYAgRO1gHXITkkRAhZXsRQrisL0tz4Z1J8ngQo28AX09EaGzY9Soqc2V' + b'62flZdbt6pdWzHEDsJOjfATKzrG7sFUBcOwZJYLjoevl9H++anG5/rR469yTLIKS8r3jbkRe' + b'Q1UB4aHrDLkU2z6TBeOl20kmQAGuxyTuA1IrSWLUNwhhfkE2Kyot0Y0+3nx4HueCAZBqHZJE' + b'YTy+QTV3HDZibgf3wNH2H3dd6F7O/s2X5xxKDVjdTR3OkochCqBs2uQA2yfG7nj35bPK2mqe' + b'eycKiwtfdHYfF/p+1sy60K5n/hYMfqLMJc+8Pi97wTWQgv4eD/7GpbXpVJbb1Afgt8eVGDUj' + b'vLMO67R3j0uQ1iQ5Z72ii7mGmWpyCZmdbunqugy3uE7hTgyJ5sb9TnPb0TDfMhRgQ+MujquG' + b'8wb2pMz7bk6qAKxq2ICgQ5lcnKWA68tzFIEPmgLvsozkM37etSYlO5fBzIwTgyjIQthWqnne' + b'YwpmilfEAl3iA2A3BoBokxznvTOuai0yYLB5p3NFWnJdhp12Y8amKS/tzHu9lG80CbtPjiHW' + b'W1Sqa3MhBdD58XAmG32EB4ebO7+C6+oY0rs6h0kSsBcGiZ0JuL3ah/2sdTDAWof8KGvmAXgG' + b'z121QGWNlQqnjWWmSQD4iDRY4sz/nRLA1LWf9x1BFSy0ECu9amIXQgQaQ/FaLBIawxSy557d' + b'ghJqqJRA90jcvjScROYd0uWww0QcPjFYUgMsm+t7nTrKuemQFgzYAVDEBWNyKVIAyoWTpGHM' + b'biwUg0GXvnlrN4d0YKu+nER0E/kBhUwEpLiajtn2AKLNKLwphgPMeKNJ5juHPVwBJJPZRRFW' + b'g5BgcsWWQyrLR4l5uh66fuLm5AEgdZUieMkEQ+7dsvIiVlFZQkhFfFE2k0lmIJkD6994YoOm' + b'b9xjmrLAPdLS8bM3zjuW5/mhv7/JzArNW6lB6b3tqpDpDhUhZLKQ8f5yJmTPYXzVbYzN+TxL' + b'CNXCKy/tBEPhm0fH9755nu4+sPlDSwA1hY9kpwz1K4UFofsvu3x2Hhk+Nm7cA7dIwjrYJThS' + b'QEI1igx1sc+U7loDoxfmQnCfS3l9vUf03xu14v+UzVUGTG7FsqSFFEn9F28G2DFwZzBIqrVh' + b'i/+wdFqOhoyu7HA5jG5RiP5blum5LaY7L0dWhgesQrR0Kwq2AJUTAUDEMpT4z4Ky//PAZXLD' + b'I4oNmd0uVaxXBDHL5FyXpyRjWFQxEx1iKVKE1nktsVp1B/9qRE087U/HfhRygQgAvcFQzDGA' + b'ytHT+y0aGfx+/eROeWZDiVLfUOSkCjfTG0UIIk9A+PJXb2Q/+u6b6vatR2CG4jiqMjQVkEJ6' + b'coJqGcBPSpPuxIAA8EFephV0ip5gu5mGlEBhLfh8SY32w8jYnZymS5d06Pl3wv1NBwK1zf6T' + b'nePNB+IM6zgHtB07EIoMZdta8rE6bLgzbJzQuYHMYOv/pAIRsi7dJ9HPNMaBbEE2kbvIfVLS' + b'1eED/UL35eNGZVXYuWxFeeqFre2O+bWCnuvVpfyZK1i4Yi47tunnLNbfBjulDKMg41Y1SnJB' + b'yLSe3ayx9YfzwfF1VpmTtFWybEhjZJ8gCYIaESqS2Eg6QD0ZgIFAVfHnpRoLwxRkZovj5Dqk' + b'lONY0tR++rpm7j5iqiBun2vt/PkzE718+L+Qoo71jwns+RM3srvuucIQJER24cGjsjzZFlj/' + b'kQFz/Svv4BsMHpb5ofzD6OjSGiXiZAVW384k7WfX3FR3+z9/705vySydvf7mplRvu8ZVVOfw' + b'quoQcvPCnDEGxBdLMREUAfeIJQITje0/6DYybot5+kT+T66MmbBaGq/vcYNoph0+p87HFULX' + b'mRhpDtZ6qUY11AMuCHAYbZXjlP1OjD9nOOYqnHoABzggXVbBFIvHIs9TqEaHru5xWzDoidDp' + b'OWMQJdcPOvAdswjrKfkbn8KHDVFEZgE8BZpYrAtSBUJD56V5/aSc0o4AXTZiY718aKI4NYKk' + b'JwNfkG9vH9BXrpppwe33AYxwyo5DERJ+xcparrIqVx8dSRjDwzGAx6MKKBY0EQmg3QPpBrYj' + b'1KHa1ybysEYriwpiVN9uYhkQicN+AgJ7bOz+yQk6dR0feKc1BHhhMugRIfnQ2YQf6HBqA05s' + b'2wGuwGPAoxjcCFGmFZ8nhhALmXt+qxMAm5B98DMFz5SFU2xuyRhVwJ3gqthGqgE0KNvuQXEQ' + b'Q3En7AFOOynID+5LtgDykhD9Ol+j31TE6cKNbDY2FgKTIcT27BkwegdUtqyB3CgIoW9YxbJK' + b'G1hqrI+lxuGuxXoh6SInJHFLZ4qsukBlVCOyc9jBjg54Wd+4i8mCbgdo0X1GoSKQRNIynGUM' + b'pXP1rOw8fd5ML4J7iGVNPBtCF+oaMJVvP6OYx04aEAy5JMb8VXBlhO/9di07NB+Tn923Y0cb' + b'/8oru/kXfvMe+/Wvt7OnntjMnvjlRvbUk1u4/fu7LHDQ7zo56R8Gx99PXuqZLpkA5PhXP2yZ' + b'wmP+HDW3etWwfrhnG9u6fY/WvocXcioUs7CGqQ6fwr738/sEJyp2/eb1Y0JLv9usL1atLL/J' + b'HzvhMMZFJE4Ni9zMfMjhWkqalT8ozi8ZZxkYwo5jYKkRDeC9lg4CYKqHnfJExJUtU3Hw+0Nu' + b'5A0+pOuw6vPORRmaEryQBe9IDaw4kAQIawbHC0K2zqff8qhY8KKQA6kBeSHpN72WYymwn1RO' + b'hfTKicUa0jc4XixXLdfytKF1SJYRQcgIurAv5rf4MxGdFhVTaVVFWrCABf+BaUsiJBpXXpkr' + b'rFpdz81uLDPyC0JGXp5fL6/INa64cpZ5973LLU1DsAhWyhs70tLqmoSFXHPUuJvsDoSEIGNt' + b'NeADZ5h24fiNPAYZBBbowwnbrSciKvBD6fbTujvjI4n6ClKhZcBwCchQPPEYnQy74KT4D2+g' + b'9eoOh9k/xtOw2NuJsy+pGLFjHiqyE3bx1pn5UTYTtoA6vNflRVk9DIWUsz+neJzNs4mFibgI' + b'Kv11YUpHYbmD/XEugMiY2pl5UlbIpb7+RrcY9gtmiX8UrASBSCX1LFzeCGKCGI7hE5gyMDZi' + b'THGFrCjPyRbMlNmyeo4tqDZZfYnB8lGdyA9M8SCKtnqDYVZUlGMtnRMwVy9w8gtqBBGbbRcf' + b'3R2kHQuVj9R/+rXKwh5Fe/CqhAni5+sfl2/Py260Rsf3baf9PmwrH1/Uo2aZR0Cw4pHx5AgM' + b'j3GAqySi0eQQAFYOGqbxIqTI/9Pa8bMff5jFT9dxSQSgrOzTFbKT/SC/NulLIt1xuEfl9rzi' + b'5AbaEYMP/rri/lE9mUhzS+/rFo+0tmhvPBET8N1KqQJ5yUxE+Akn+kXzJCaBBrDEItnk6wtG' + b'RcsgnyrP/CjhnY/ot6JQxhyLuUwNgY18sa75TohWRW6SxC2eiAQoKae3SLzRJ5P1nodBz8Qi' + b'58xe0RCKUVupRgUCHMRjOA5ISYMkoSnvOplcr/JiviEYcBEq77oF13UJEW5AWjakyjE+gMIV' + b'Rx0i7AGWBQKFPi5pXM73IGm2t7cO8GXlOUplVZ5E2YHnasTtyS5QWJwlzJtfzi9dXitcdnmt' + b'MGtOiZid4xcuW1knFBYGrdfXHRPQhbCmLmZzQrsvTGCCBCeOLvjggjvf2rD3M5g2GMON4hjq' + b'KAgPAuFzX0qjfmmkztfQP4segtsCc1sHXPg02omYdu6dg5IJvzsQ2NENdiVrexilskm8JpsA' + b'Ndpu2wCg99s2ABgAKSLQAZWAfiOQVMJJpDgC3MLFGtdxfJQVFwfMWXMK5HhczbyxbVicV4cY' + b'+3i7wMse5i+oYsHiOubLq2RjJw8Dhx8eFjRy15F2T2AlYURa5iL4KQfZO+HsEMBegywvx8Xy' + b'wwLno0ruoBkYShvlh64RRj8LyMfKd3+j8XMrMul7L0+4sgK8qzInZXYOCdx40rE6Ozx3cGx8' + b'X9PFbuDs3/tZkwnicXh0rOnl8eitT2Xnmr8UHfrPAhnpx8090cfGIk9tgITRefZxl/L9kiZ6' + b'yLnw67PXRm/wZatK/ZqY5XDDmY1UxbxKxQoWasLCj4+JvrDB9jyfra/7rlOIRBOWDxBsohNr' + b'mWeOuRUqwC1541CvzEsw7kWOOIUqGFoQAQZBEFFTMADRhCgLIw7c7VTbMUn4PJPL6jH56xp7' + b'hMrsBLAwTDtUFuIg0C3I3ANbwwCA/WMCp7XDqt/qQL0pUU896+PSmz1M2e5h5pjAIy6AKe85' + b'ucx2L2/0C6LaKgvqQSdv9osss81jKe+5mXrQYaRf9wnwHMCv9rstfhp04i7k728+3GMtWFiu' + b'Z4V9Ii12apPc397H3oA/5CYkoyGCSKAG2C9MRujJYE35+UGutaVP390cF66tTyBeYIJjTRwL' + b'0ZjwAeCn5y8Q4E7cnqQFIhjE/UUUD7mEdYTkoRjThuN2fUAiNOdutB0EDrnaoEZn7oLRPNIu' + b'me8dlag01mRD9V24OItgcCMQDtKnpxrNBfpuv+jz5FXiKQOlV2MdKPRK3JoW3PkajT1iLzBm' + b'w6yoJGgtWlLCHzg4pB84kgI6kGglB5r5TCJqBwjJbj8b69zPtAwhOk0SI3ScAFhJAgX5ABlH' + b'fdnJPsODY6TeMacLufkTj9K+BCpsilMaL76tqY+t14ElmMp8bEnaY+iqnFu7jM1cciXvSuw1' + b'D3dJHMKhLw8HG7eMRfb3nu/6L759qzU2ttsYHd2n9sebQLmOnI/0X7wr7HEJBOAOITtb+tqS' + b'u0eLgwUoc5bm+J2/yhHWfG7IOnkQPvWUoA0fdxpbAVHUc9AtLvhYFBnNvJ5dBuz8qCCXeS2z' + b'rkQVXEBYPnDYhZQfxRrvBgRUymLFoSREWkwbjD09U3o1dwf1kSIQ5W6Jq3emufxAElWfAOON' + b'MFmag52jE6IgTQLb2EzHYnJZEZ6IgGClMNsBIIDIQB7qBtyLSK+KwJGEuCArA8INrmTFQTQ6' + b'ZN4YEidevSgKTbXjz5q/lzSC59mJWARAQwQQAX3x0mrT73dBhzeg/zthOZaQMEJuJCJndNcf' + b'bKQ0028yzMeIWDDe2NTGNxZnuIZCTEwyjFGjN1IF0C+F6563YT8RcQMCovkk+PXPd85Tx2N/' + b'Ah5ReiI2YZGo7/Nc58QxOOBcv+O5dPaJ5ua9EoH+0NXau6VA4HujHlaMWAAPdPzpRMDeZ3I/' + b'EvmpW7reLMClk1vu5Pi5QpLpqNONxj4DZM/DBwdYVtjDrVxVabyF2ICuPpUtrAPhH+vkB1vf' + b'R5jwLiQLRdH/mQ+eVAmqIxCNxFG2PQ4XbxIXz7FA0IfnQTwCCwcrBx8t1BNAdJ9mbm7SrFuX' + b'JJWrGzMePBKJCL6MGgWLbvtzID6bfLqvSTvS6/XgVorKKxc9S9b901f80X26KAHws7WhnFLl' + b'i403RLKig5K1+cf54pzrI2bxrAz/7q+z2ehJWUyMylYmxgurHh7WPYiYGu508LOviXIHN/rF' + b'WSWqWZGnC0iJ5HSFM461OkXP6qR2cmdQKApbphdxAyeGBCOScaojqZC+e9xrmoBlzhsUxVuW' + b'xnBMBplXYDAQFylJhAxCCBYBIz1rxhEhoLuhZ0lTDS/iFkStRVRusckkMRX6ZXJfm4DgGPs4' + b'/PD7bqQKjIzERRABbfGSasPjc4pZwRArLSkGSAQwsPFPg/hJRS2mL0pKjjl+/DhrPtyMLLMS' + b'SAcWt2F9M6vNTXPLK+CDniIAdMEYBguhurYUQLkG5+MHtJBIDr/UhmsXUKCesg5/a6MhFmIk' + b'zpmv7aActtPPiwg5eTu6kfdPeRA+qICTj8y+OrL8UzwAqX1kHB5DYNBA3EVBOnagEAXsnO7t' + b'3DdERIBiLw4f7CfkYG7xslJ1285hoaVLt2ZVyaYX2qumktRCZz6zEfH1eFy23p+VRSpAkIXw' + b'TrkcFJOAYbQGx5n2wnZd+8XrKC+vaOr9qxNmY6XmBS22vQFEVLRMkhXXL2X5NYsQm/c+f7R9' + b'1ByJOyvUjAkpAIUK/gjaRWdEWXnDWgC4P9x9yGkc3+mjx8g13hDV3/t1Fle9LKEvvmPczCpR' + b'zNiQzBbcPmaNnXSY828Z5/c8l8UPIj65sSpjlmYbAp4FV5Krc92tTn0YXFleklbbd0O87Q8y' + b'IX8xP6zl8+8czIioEctZo0zywR00EHUafWMeMy9kmA5RJ4Maq8xOWpG0WxuMyhSA94FGRml6' + b'plRjPlyiaPOuTysInlCSo3AoSIg+1CxJhf+H7HB2Bx98/h/o8+wNdKx92CUcS0RgaDAqAiRU' + b'n9NYYgRCLtHn8UEScLBgIMACfj/ZAezIwenn2bFjJzt69BgmXoi5nH791Vf3c/OKk/xlVYkz' + b'CQAdhHGhYp6Ch8Igpvfy238mgkQFR23R/7ftE+ODR2T9ZqsTi5csOKevh4hARheR9ONjXWNe' + b'W7yn+IdjiIM41Bdih3vx6guyI5gfLdhGRuKuUa9tN5jez+keP/hpgqhyHJKF+PGxtFBU5E8f' + b'6Ujxu4/oAPPg9eJcgUwh2A0XM3lt9sepz+iSLpp8Q7heM5owjSNdpvbyTl3/rzcR2ddiyLNL' + b'lcwjaxNSls/0QGOYPJLmIAiQkmZZxdV41RBaENfdvNuAFEDIjiOjkUv31X/wzn5/Wy5KAMJZ' + b'CypNnf/Ygo+NyaFiBOojMtoThA0/JlqiZIrt7/qEQxuCcuWShDlrTVwUwOnf+WUO17nXI0gw' + b'9i2rjgvhAIzwxInhqKwuUtnJ/S5rHGI5FYbwZTn4f/yHPxO/8KVbuHAh07dsaBZv/PgMQ8wS' + b'2eGOFDMLOGvvgTAqvQo6Mua4oZjM7eoIw+0yTRekCYqhh9eMQQKhRW6VVXuMv/zGanbw3Zjg' + b'yB7hZ6xI6j3HeM7tCEgPfXotu/Gmpaz5ULeVSKIS7hlT8/yDS4CfpBNivZIqjwAwEHt7RLBY' + b'piSPcxxuSwLDcXHXznYzgKT/giI/AoZcUM0n6gr4fF6ImoiIg1pAxICSifbt3Yd31NXGuOXk' + b'FFjrXjvALa5MqsvKE+IZEgCdD/fPu5HyeiFj4Dmu6w+xifLhX9kpW6MxkNuzCDYtNtLzEzDu' + b'xTKy/SJ3ICUBkQRArj96sPZf/CGi8WEbnYPGPxrN8GOjSXANxidSlrj7mMEfRWYeypYbWJxg' + b'O0CLgQ2YqAE9WwhlwPK3rEjSMg60G9oL21Tj2a0ah1ResaPXlOBYsUt+I5Sbqy9WMD8n4gCm' + b'X59paMwdyGaFdYuYA/aGoWPbuKYWk4O30u32Vv8qFjtySfkA0/v8fX8GbbtwU5LsaDDfSGQV' + b'q46D63IknSqfdiNcQ+etrFJFi/RKmqHzzpEuB/f814rNYRjdaGnCNZhWB+A58cDSb5F+Shlv' + b'KJ2FGJzrF6fSP3wpKAVrFN5bOKo+u+3frb+o/zP5vrtvdWx/o8NseuekfOc3h/XO45bVeHXM' + b'is0V9S1Ph8WD3W4ATNhQTnAuIAEDVVhAcAgG1FKTPFe3Oqb6czX9wGsh6aGvzGRJuZWrvfUA' + b'TDSy9eI3wlJ91Sz5m//3PuZ0ONijf/WfxqzbW7S2dwJWzyEXQhXPz+ZI8qAIsBUrZrG1181n' + b'RRVu1jT4tN41dNQc7/JauGe++4BHAgFC7sm5+5GQvTE+Fpf/+R9fMQ7uP6E89Mgasbg4D0GU' + b'SJBRMqdARWmVJBMJ6KAo94XPx9tiZlFRHEUwTdhiYKg41yrAJP+9uPUuPBU+/K8YCifw8KuL' + b'TaulGwzgHOyG1vQUDNeHP8GlH0HoQWgwtMJFjOsgmnmow3Ac7NAthAubiLWAOspZKFJKKCbA' + b'nQUBgOqFMgZ8Mm3JJGRRoJp9D9PuYzTOS1sOudJ3rUiQZ9k+ydRVUSJSfLTP/koFS0rLi5Cj' + b'0GnFFW+FWwyV4YdjU/t+VO/TbuXcl1BYsLBSA5jJ8V1eiOCckYqKotNjWCsfHFEyMcHMrlCE' + b'GZfFtfYdXllL8TzUgwy0IHWkx+WqDUeE2eUAXaRibmg0PNCRjBd3IUMoAPoOSlG7Mmm+v22M' + b'5S/oEOqzr4UVnHFPPrYdOgDyBcYdbP+rISkygJBdYGGORhwSDEjEf9GnZdRfFdPm3hRR4yOS' + b'nl2isNorEuaOx3MkQxUE4u5vrx/iOneFuPdf8fBVxXXSY098marIWH/2mX83si7bbjZenRYP' + b'rA/AH4x1SCNxxuOzL5ks8TDaiezr37iLLb4qpGrhJr0vcVB3FLfKwaIk19/q0iT4f+tXRw0i' + b'ghlkLp/N6SZ6wozD4gWD4Y8e6RX37G7Xw2G37g9KAqzOp85MlYbaj3cguaQT6dHw36e8Jpxo' + b'xt73O4RHbkiZRXJCnOCMU71OvItZqHn335wcdOYZL/CNHrRNqPAOmnW8WzB2HpZscfsCR/1B' + b'f6IBhzSAlw0rzSPLV4glLGEsbnGRhMXH05aICEYB85FsgjZ9PXN5T1wu3eZYQmCzylQdVYIp' + b'IOhUI2blcHpZ+fyr0IkIpOLD3PtNJ6z+iMvBC+bLcO11ntr5I/pwllD2watAXXfgmFiORXeO' + b'6nkzMsih5VjhzIwiOkypcnFSCJcp/PFdHqea5nksRr2kMcWigw5JVAxpdjEy+4CDYNNb/CVK' + b'39IjayeTgrjglnEzOiBx3hygdDjcbPuGE1rUPMYQGWdlIQbgyKYQ33fUJZYvSCiBXJXd/o0+' + b's6AmrVKcictvajd9rV+HZ4J17vFaQ20Ox6xrcfQWH1v7FwPWdV/pU3OqkqkFNyX18kUpPQ0D' + b'5f0PXsM8QZ397bf/OROYt9uYt1aVW3b49NETTi5cqqZlt5lCGoFtG5g+CipcPw8/fAObj8X3' + b'z//+c2PDpu3GhlePmAM9ae2dx3PV+TdFnKgrJh7cEOQXfGxc9ecg8pwSl87TaBIB8wD5AMOO' + b'v/ub58THfr4tgypFGpKDbFE1mUwCTvwI9E4YO4c1Fgz6jM7OUa4wxzLrwykJnOmDjSYdzbxz' + b'zdAP7v3fuwUrwiRVaSRply8nVltXbsD+SBf5x9noadFCJsmAODy9iDgQIb/YkNLviQwvdAxK' + b'SGr74D0inBNq3EQciMPlRbFSmLQhKELRuPmPYTQuTgAy7JqGayJWTqWiJEYgHwkW37bD697w' + b'T/nyhn/Ld23/zxzHUJsL0erM6jnqtt74Xr4rNSC4V9UMsLCPADEos2riVsH9zH3tDqsIREIC' + b'uFIS8Medu73csnvG+WO7BP03R/7a3Nj0rOoAnvINX+0zq5fFtfyaNFMSPHOHdGEW1AHS8/UM' + b'zw6tR0IBWHZZY4r3ZCHI322yOddGuPIFSb632cX583THoo+POYsakpzP67Xmza9i27p+Yrnn' + b'bRUX356S4alQ3/llNlcyJ2VBdbBCRSqi7gDNLFsaJR1RI51/wcJa9uDnlrGNu180ksMubqwz' + b'aFbO1UVct/Xe02HngdcCxprPDUoVixLcvtdCwuxrI4qI+MWpe5648w/+JWAQ+JXFp371jvPL' + b'X3zCRIZgGuNj7N3bBM/BCA4QkGaqWUXFOWpX1xh32cyMGWSJ05GA07vELFRR9MMAVJjdaDaf' + b'63Wx2XxWn2f0MTEk0/c48/Nk3zoKkGSOjzAVLsRM5ygzehNsdqVOdf8+bPW1M/v/Y/4GE1Dn' + b'AHRRpDGccZmYBIKEGA2bCZKtlnbA0ieiYHE3o3oVpU9+pO0iNoC/5R3O7rq+Zpcx0ik7gM8p' + b'hOCPBQwbt6hslFE6J4J1WTcy1xAjzRvtcJMi3zM/O21nU7k8ZOEmrjrhzwUzNXuBAdBwTdQa' + b'aHWy+iujSvOmoFy1LGk2Xhdng4NpIxoRuOGOkHD8Xa8JDs+NnJABCM74oeMOHcZwS0J0H7ab' + b'omyyppey9LYdHgfsE2Z2ucof2+qzNv8oj56CcM+/dLPdz4Yzwz2c6fN45Ch3hLXEXuPyywW+' + b'+U2f+s6vcvhonwiXZjTjCWmyO2TqzjHDLJ2bUjuAWZCO84LDIZiPfu0OLsFOWOt/mbCSo34+' + b'6lMtp0/njmzJ4Upmp9T3ng2jOCSvLr1nRMzEBbNrr5fLKtFVXK+D0pjPbmTUIwmBFMqcHAS2' + b'cIrV2z3q+NdvrTM3rt+vB8NJPpwtckODKoyaDl1AsPJA3zD/sRuShqkQzTvHSsQmC2jBma4x' + b'2xvAuwEDDvZl2wuIixErw/koWIiQJGy3Hl3adCpF3VLf2E5xBRQ0ZCJ/gDwMtD9lH9rBRkRY' + b'ph87eT1GUkG0IYhQAq410qUm91NR0aigzi1WFRna7iNAIz4Hlzx7jP6nfSfzwjDWBqVyYDhO' + b'qQFEEbyhPKwB0i8RNZ1KWLEUMD0ljpIESk01sRybX7Z//Ij+XIQANOPWfPGhdreILFdxbeMQ' + b'K85Ks6auANvfk8VumXPSrqwShC+XYrcF3uSRy89eP1zEUkbAKvHLyL2dWAQ0TzIKT/OUcwcM' + b'loviixC/rdYdPuH1b+Vzqx4ZBhcWYUR08TUrY5nDGwNi1dKEVXd53NO8MWDsfTnEIggBxkIz' + b'ZJdhHt/t5QtmZMRAvqbHgZICAyQWqMhl4jy39BOjZvu7HuvoFh9XtTwi98E8s3nfi9q+Jo/Z' + b'si3MjXQ6hOqlCVP2yKoBrDV3ANEFvClQhCOMiA5ENuqbfpjNLb/ep89dnCd85cuvGb1HHbT6' + b'xNSY6Gp7x68rSV647e97+JP73MbmH+fxfc1Og8479EsnHx0g4LaJ+556rrTW7HRmnPKmh7KM' + b'W6/8GCKRgmar8EOjaU+/tv+lXP7gvl5Uk0CodKlsjQwr1jVrF6hj42k5xxs3FlRlBP1CxZ8w' + b'vtSoboCJ4iEfaPQ7FiUp4rxXRkAQ4lnJZjC5UGnRUwFSAhyl423EIfuicRw9PDoWcOKiHwFF' + b'CCqyCQk2U6ESKjtmRLHwydVD/U02CuRxouzizmaofYNUx/PMMZna73/6O90x4o5M8D7Ya07f' + b'IzG+rOIZ9u0BVYgN9PSz7mGJgztSRfKXc6BPvwo/fqQEYII0nfcJHLF8vgWJnBz+bm9ItLwA' + b'TVkwU0DVVIudGHUpu4/7EdKbMd0OA+AHxBg45kPGHxI3jMG4V0fhAhobe0bQvEgqHPdeq5Ov' + b'vzYqFNQo3Fs/yEN+Ng87gmoc2RTkQQwoV4C79ssDrOeQmx9sc1pAGNIObwxKkV6ZLb5rVJt/' + b'SwTIHhYXKtaskrkpq6vJw/UdcUk1lyUMcG+j/6hbIONg08thfsUnR3gZlt196x3c/m0pNtTu' + b's/JmpNll949YWORC/1EXApgEvmRuEkUkZCMVFxzBfNWac21MOLrFa829itfeermH37ptL3f3' + b'twYQ4OQ0oTpIeGfzbh63KhYkpfiwpM29PsJ17fWwA68HBcR/WIlRyTk9uAyfTRdwEP25urH2' + b'zweNwW7FNAv2mE1t28y3X1T1AiQ+QSrUalekzMHjCKUeNa3qmtzMZ794vdzQUCS+1zRodLaP' + b'IggoBcYxkUp73kdGi/V8LxxEC91EqTGCFjfBtWmx62NJpoJ76+Mwg1ABUjxL+6md6mfibBRO' + b'TBmFRgS+M9h6aX8NHN6i0mX2k7Yftb0zhXdTINb3txfojz7uE9LAO8C1X1TlnDjTH99fe1mf' + b'XttnCGLkknbJlr5kBkrMIX6Krp4WP9m/6q+4A7anXKZE+tjTj79i7mjmhYWLiw0K/R4eiquR' + b'2P7HGfu7j+yGL0IA4LYLNF7p8Uo3NMx2cDsPICknY6n1pYaAOmf88SGntqczaNWWCkZ5gcS7' + b'3S4uC2Gj+SFL27DfRQ/bqC3SAYWF8cLcAE68uRuLOq8+bex+OouES8ubpXPzb42YQyi7RKKx' + b'AKx+xBzwAy0uo22HTx5odRCX5iQn6scNyxC9/Wb7Lhj+ACqKyES9ZbvfXbsyrl923wj37tNh' + b'igUQHB4EYmqcAFUBWj0qtvTJek6lqsJ4qa/5/KBLclrcoXVBDd+5/a8FudpVcRgeVbN9hw+5' + b'IqZVMR++T5R9bnnfYMD342/92ogF6YP2gVTh5yF1sKu/MMjjuqw9z4UMGCCdRbPTCHVB+HyL' + b'SwYRI0JgN5IwiuphNHWZDCqDCQMm8wQ0+dV/DQDbkwComNG8KQAVxymEyxVWNDNtdR/wCnMW' + b'yFJunk8sLS3i6huK2U9eGLb2tWWE5dVp5kMJrXN5Ai5pFk0tauxMqEJEDEyI+xOLHg/J/v08' + b'PU0/ltQEovrUaPtkIwLlhEv1JDw4f/1aMfslcjAuX1WnP/DQKmPPu+2cBjZpT4apA/7I3u3o' + b'USzoiShScjZPaF10XzLmJuEV0GdKZJq6a9oX2AfaslpwL0xhuiUS/93+MJu56g4mIpPu6Dsv' + b'Wz998ihL6G7uM5+9hh072sP198Wi2bmbf0mx/R/VMFyUIkuiWDg+arCRIZ3NW+DitzS75ed3' + b'eJDnZ7EHroxJ1UD/+cXmELejza84HRLpNqyqQJNvWpQCyo+H33XUoSMMmAgiMr1Mlh0w9Te/' + b'nyeAS7Ib/ncf7/QZBlxnnAYvwuUPDpmekE7RhMT5Wf2aqFa1JCGB41vX/69+iN2ckI4I4uI7' + b'x8T5N41zLdt9cKdYWmF92iTpAe+WAI9tBwyLM1YkUCYapYELVZ64dXxIEqqWxgHJxvgD64J6' + b'JsEL6Ft0eE0GewPzA5swieQhLHDx8KaAjmMNfw6y00ICkxCaDGMfVz4/KS+/dyyz7N4RY6DF' + b'aSD+wYiNSCbp/odeDzItJThv/4duhEMjFGnSkAiTD4MqY8KQKRDB6DnsQjqqqi++a1wfQaRk' + b'y7aAC9KNEy8X1Akxr1pB5SLDOrQvzu/csQsw4wOsuCQs/uO3buc7uEb1kz8vZnu7PTa+HnHZ' + b'36nRwiXRjF5Ts/lSO5xGDOgjsOjsaxqKS+y7W/LYnT8tA8CGz/zkJ5eoj37tZnHh4ko5ryCI' + b'qOdJonGp5/kD7EfElKDKqPkcKuWoICU5ylZUDbFrG3rZTbO72W2ADPv4/C728Xld7Pb5J1gu' + b'MhQpZJkaze2g10CAwWk3IKzVLJBbxpzeIIv2HmEbXtxoHh+SuNraAnb11UtIH8LBlpDJDFx0' + b'Ddon+W/6cxEbADEGK+B0ClZbKwp3NDrlxUvc/K7dzIHq2upty5Pcp66IS6XQf9c1efgjXZJ+' + b'67KkUZytS5c3ZKS0yqsvvOcVUNtPnV+pIFaKCfMqMkZrl49HEBGDvi35cvW0jsK68AjIQ8dd' + b'XLBIs0gaSEV4ofaKpJUB8k/1iriJhSpA17eugK2gclFSePJLpVbZvLQZG4SXAfXa4uOiXndF' + b'TGh928chVkGGZ0A5tB6hpJt94KgeR35t2iioywhjvZJ+bAsyHP68j3P6DQHEQUfYMsWpqlBH' + b'CE2F2/azHEduZcZc+okxbcO/FAhde906IHskHZLIojtGnTyiHZ/5/0q1xhsjlBUpjPfIxmi3' + b'zOkgWkiCQlRkUgXBkAA0DuoPdCO/zitIQDr+nlcKFqjqka0+NtrlFG77Rg/3+j8VWqlxQSme' + b'lRbIpQmXJH/zo33Wum8XGM0HY0J5xSEYC3MYKuCK3/zH24wf/XCrct/j+6QbG8b5+5Yhjz6P' + b'AoaQUwBJhybk70gSLjrN7HWPvUi/n0DxJf2XZwf7XOzlgyG27rCX9YwL1szaPP2z/3uFtWx5' + b'rYxVjwnPs4ZZJRYyG+EZuqjgedHr+H3sQAuXOHwJFjyBsgIbkAVdyPhDGjKN6RRNpDGlfanR' + b'VkpOI8wCyk+gRmau/ICB6sMWADwnj8JAlcy+jCUQCPT2M9+1NuyGuRcQb9ffuAj4Ai5LyRC4' + b'HwdUG89kz3ZXf/A/F30SAf/cjxUU+hasWFmV3L6lVygokvjKKgfX2mGJSPOEFMhpy+oUYdEM' + b'hTs+ILE39rlJPNUp/r+2WIU3m+mvve/hUAvAKA4bAtKCzdaokE6NSQI4KlcAMXysx2Gd3O/h' + b'Iv0SN/OKmBEu0bgjm/18DaKrIOJbDWtifKhAE49tDRhzb4iQ3s9OQOde+6VBdvhNv1BYn2El' + b'c5A5WJORsIgMcHtpah+I/4IAGlE6J2nVXhHndzyWjbgAgV/xqVHh4PqAGsjTjaF2l9i20yth' + b'MfNIDIKVlpnQ1y0ENVlHN/l46Pm6nuasjvc9BhYoTQzo+aKx7+UsEUTDcgUNq/+ok4frkZt5' + b'ZYwfancaJw+4Eb8zofqEijQdxM4gw2Fvs9sZ7ZdMQbb4xmtjPF03VBpz7o2IixiUBVyHsfiu' + b'Mc4TgpdjnYt3edPczPpKuFcceIn8istm8KUV+fobe3Xz8S08t/8kQFKgbyDjDEk1gNSCmEqG' + b'qNMMGj9jWp39utBMo31JKCApj9YqSRr0ImcCccuEKiCbT2ZNJ73slUNB9oPtOewHW8NsV4fL' + b'KirL1x95ZJXx8J9eKVRV5yHvQrer5RABoLTO7VuP2ZdC1/e7NHvV4A8tSBLBSQ+nu5xathfq' + b'n44FTaLiHWxZ5TBbWT3ECkMpcH/Qedwz/U79Ub90v7TAbWIx+U7nIRWA8BtpX6C36VfMTum5' + b'fqSx2fuYzOEJgBnUseY3fsLWbx81dxxzC2WlIfZ33/gTlkzGzGefftscH08PI1niZ5HI/o8s' + b'JPiiEgDdugqYpCXLyzzJlJrZtOEYv2Ax9LorPawZyTvrmzhhd6usXTlHMe9ZleA7QATePuLi' + b'gISSXtOYlq+em5ILgeCzr9Oh5YBKYj5Z2VhEFBux88ls/aav9Yk7n3JaJfNShhORvjD4ibOv' + b'iegQoQF9ZloQ1YE5oAqJMcFENiE9CBALlzXvlggHTizAKm+GClWzoDYt41h97CSEUainkAYA' + b'VgIlG2rZaI/MBQo0oXu/Wz/8ZlBY+6V+4+hWv779Fzn8J75zEqpA3OxpdqLoGwcd3TDDZYhG' + b'Fy0nFq1QfVlS2fdK0A4VdkHMo99ha1DqrogLzZv8vBYXpbZ3vJn4KKV7WCSRkItyYjZibkAq' + b'4ECQjOrlCVIm094sw9Wx2yND1E+v+5d8fdGdY8LyT47yIHg6xSRs+n6u85n/VZq5/MFhK682' + b'ZR09xMudnZ1s3rz5dq4AuuQvW1kjL1xYYb7/fpexbv1h46/Wn+DdyHeuzc1wc0oyyBpUUV1H' + b'Q/YkxFBg3BFRoAuyJyt1gC8kgJJ6cq5G0kQsI7DhpAR4LhFJWUDLjUhI2pGBmiuxQWwbxe3E' + b'0wS0BPBmn8OcOTvPuObaOQxVkASv1ylQVSSFbAuTjXIoZtTkCwWFIaO3Z3QKImjq5zPeabER' + b'EhQttLNlGpuw4ReSQFAkAwCjSLGeBA6hbEGqO0BQ64QwTAuY9qM+7L/ol7JJCdu/KjfB5gNt' + b'iMqwkeQ0pQJMXYits2JfKv+GlGx7M0WF2tuh35MtgKoZ0/nKstVMTYEuIwQMhAVEBHiDlAh0' + b'cP3PGOqJAOw2C0RQZ8h3YcB3YO/sPEZFcKgsyZRgMXXaP/j7RQkAAlsHEvDtDgIc4vob652Z' + b'tJbctrndPXuuR5i/yI34ZplrPZaRn90hWNubHdra+Wnz02tisPoyYETBzgQjWEm2zqH8lxNe' + b'ImsIBSMhDovLPjVCYq607tv5eudujwh3n7n8T4atp79cZm38br6zoC5t+/9jQxIPMdysWRkH' + b'MqAlw1bAuYOmNfvqmHjyANCDsMBbd/itHU/mGBClibsLSFoyaFEf3RygFGXxxb8rshJjkrHx' + b'PwJi+cKEBr3d2vGrHGcO1BFPWOcQOMRgM9DmXBfVEGDEdR92C8UNKQv2BhMZhZYvW9PgJXCE' + b'6tIaAo7MOHAGCBfBfnr4M9rlcCJQCYmgnPHGv+fziFxEcsnEs6R9IC1IB14PmMF83QGVQ224' + b'OkorD4ZMp/TS14utQtxrblXGSMG+ESrUDB8w31/+h0JeguFQTeisrfUEmzNnDkTniceVRo0o' + b'TB5IA9VAEaqyBvqjxqFD3fr+fb3s1bYB9ngT9CYkSngklWI1uJBrIhKPQDnpQERDswJERQKB' + b'zCYOdKWUYEQFMmJpgXWhLl/7EDD6kshTUDkYKxEDAAUXZc6tYMDJsnLdZmmD1yorC7PyihwO' + b'qEdcYVEIUOhAacJCJ+CMczVgIXLIzze7T4zYUXfn2oc4LiECEzwYYQAQWKrN3fFOY0qLjiQc' + b'YELZ8Om0L3FtIgx0LN0jJRMRfl8vXNIUo5IBMSAJhlKPAdXFKoAtQQt/6pjp1zGx8AntV0QU' + b'ppu5kWQ1hRdw6jf0hVoV+AN4CYS937gohej3jAx9lpXMWs669m5mhgYbAS799b0+a3BME/7s' + b'z64lQE9gRCRYX28/sF8o74iZHk/yIzWKXJQAwNZ5hB7o00/ss665oYbddmcjEtmk9JvrWp3R' + b'cV2cNdfNVlzuYQN9GtdyTJUff0s0y4HRv2pWxphZotI4Wq19opoXNMUcvyF7AOmfQkQhou4s' + b'hM1a8KlzroCuxUehZKNeL3R3cqOZWDQA60P465qYCTefBQOfAKMbsASZuBBpx9FhQcMCIoqM' + b'JKWAuODWcSU+KsIg5zZyqhTOn2vAqDjMJ8eBAgP4sEPtAVJH7MShrvdRlVBjPFQGveegyxw5' + b'4eRv/0Y3c2cZMoiTAlccN9ThMl/4m2KCIhCv+eKg/taPchWEOXNYlDw8DSYWKzwOPAcDn0K5' + b'Cg1rIlxBrcKe+2ox3ye4nGSMpNRm8mr0NMMzkBasG/6yTwHRQtRgiu17Kciv+cIgHY/ApIDV' + b'tssnD7UDtLgxpUE94boPulHQ18V7UW1rbHQURSjiLDs7m+Xl5oAvwbMRj0GUTOEaNA5YgmJh' + b'0Wx27bVzrFRKtSKRpDk6mjTjsYw5NBzn+/qiZhLxqvA9i6i2bI2Alrb0Zqx4GwpzUPGCST4E' + b'3C6kqQE3L+SxKuZ5uSU5HjMcRmBT2Ivqxz7kx7uBt+fmAFgqEmyWBO6IYqgcMExtTIPpHH/6' + b'oqLPtHhARDifzyVSpdRzNSJCWR5Vvaq2XygIpJBqiSd2jjZ1NHVD+9B3+kzcnkpxOyXFJh6E' + b'OZgpAz4MJAMiEgQoYhMU7E/Ewj7QPnaiR1qRuDdgATjxQgQfdB667qmFTwSDCMlARDSff88H' + b'SYNTP7YknikLJ325M5ay+Tc9wsZ62lj7u69RWLf1+vtu8/0WlMj69Brzq4/eie441tZ+3AYb' + b'mRwCtbmZ4JQ+unZxAiCwdqDXZG64aZnzvV1HzNHhpHH9TfWu/AK/8tLzB43NGyNydY2bKy2T' + b'2WWrJFA3jW9rURy/2iKa4DLa4lrFnF+lSsBpFEmsg7WUz3aZ5ps/yudi/SK/+uFhiNMJ6c3/' + b'yNFhoGPg8EjqielHN/udO54Mc+WNaR1cWAjkaaLkNMjnr7bt8vOw2FvX/sUg33PYqUb6ZSmv' + b'Nm2m9nhFGOA06N7g0Dys/QHzCFxsFMFI6kRWsWbCFcfpqidDXBnrSIMaIquI5V73LwVWOipY' + b'yYjgdnos20ugZSTu1q/3GllFmuOqzw5BAmEWApBoolkUHYliJdLs66JmcT3qEQAWmrISKxcl' + b'1KNbAnLpPJQGgqQ90IJ4QkQtuoK6Cu8Cl1+b0QdbnVx0wCE0vxVMwRPhyq3O8JBGNAWJRCcO' + b'uE0nnBAOL7RMzsHX1jtZQUEecOpc4KwK60Xx0fxccJqiIntiUgUiyh6Mgxjgdw4hxlxurp/P' + b'zw/YkYA0qfHPnuEEOUa+VhJlFfj7gZQAgASs3on5D86Koh0OSXA6RY7w7jFjCdWYItdxLojP' + b'OI5eYZRCzwqFaJKzgaEhNjo6Bi557sV6xtRGX3TMuRqJ6yWhdPLquj7R49CAH3Hu/c517PRt' + b'9nXiWqdWlcBBYsDCp0ZxStPZLZEOipIkMZ8WPhE1PC2b409f+HQsgiFtFPZ3W53mBhiFkf+f' + b'+czacQ5VenzVy+/gZ1/9KcS0JFjzW09CvbWsV/Z4zC37Be6hT1+pfe3r90p0jrHxCOvoPEGE' + b'ByjQqIAN2zVjz01dKp3mD94uSgDAlLuTqjKQySjl3/mPz/APPfBvALiIG7ffNc9ZWbVa2/RG' + b'S7ppT4/YdiwlFZXIXF094gAKvGygX+NPdKqOl3cL1pZDTn1BtaosnqHwRVmadFVjmvuv7T6u' + b'KGBqhzYFpDLE71/1+SES71F8kbeK61P8cLsDCZmctePxbLnxxnEei8t0eg3W9GKWC5zXuvlr' + b'vdroSYmD351lV2RM+OiFsnlD4t4Xs4yDG/w89GwO3F+cf8uY7g4a6aJZabGgFihG/5XFIG4L' + b'LiCOHH0r4MDDsrEFkMlnr4NihPeC45sHXg0a4Mp8bqUivP9iSB846qK4AnPbT/NprvPIAuTD' + b'pYoB9cXwZqHSccg0O/a4tJUPjQiQQJRj2wPC5Q8Nm+v/OR9p4RzXcFVEg0riSkUFw5etwyDI' + b'ySoEihN73YbsNsSDb2aB2HRbvTAmRnpknaoTYAxRghoEscaLiemwuSzBivX09bHxSASglTmw' + b'KAOt1uNhEBSQu0Cw1ooNLpJGmSoVn0kXtxf+JMux37BWRYDXB1CmGTdDL3sBwzUFIkCLwQnR' + b'14UFLrAUSmsNj4xOcEKsoPz8PEghuacmKp2bCMDFGp0DHkBjdCSO2IczMZhIBwfwp3VtfbcL' + b'0KxUjuti3Z33d7o/KjA7UYmZ+pmkbvYRE/dJBI1eRPCongDdJ32ndvbCn9gIu9OIqO9pc2oI' + b'ZjNuh/errlBxgdhKs679DJux5HqmJKOs6TffZoO9feZLe4LWu0c57oEHV+l/8/VP0OJHlqvB' + b'Dhw8iGehI9NzTEkkNAkKxIDd/0f456JegMHxG9PZodh1oF5VH79riXnbbVfw617dz2/ccNAs' + b'rwzzK1dVSXPmFRoQmbRIxDTTcMX7kKcTCArwX0twYYlcMsUJzR2C2NTmMFHBVCuFhX0NEoJW' + b'1GeEE10Oc9urQYiHtsHGaAfqENxrFPvPnAFDH+5wOnOrFR2cEi4+PwBcAViu/AAAQABJREFU' + b'eY2CaRbeNsaaXsgywuUZiP0iv+j2cQGoP0ZsWDSW3jNmQZw25t8c5WdcHidubSJJx7HvtaDa' + b'e9jDXf3FARGxAuZ4LyBLMNmwkFVvlmlnDWaXaQq2M3gnLJxPzKvJGBDRAWFkcQtvG+d7Dzvh' + b'pkTlOqgQy+8d1XA+YaDNZcEgaWz+fj6PSEUeQUf83heDrH41AZ/yFNUozFiOuASnacB74UqM' + b'IdcPC2LO2ihyB9wMgUUWQp1leEOMhqtjJrwGAtkvUlGAK2LVFJe6WE1NjT1NcJi9WCF6A+Qi' + b'xuLg/sTCEa8BToYCyCAUtChDwYDNpUPBIAtMIg8FAn7m9/lsokGEw+8P2KhEtE9WKItlh8M2' + b'd6ffXCAC1Be9RsfG7YWBE0P6IXEa0UsgBglkLg4NDdufLzaHiQO2HuvVn316FxEcCpg51Qju' + b'DSXBudq8KHLxf1vOT14KIEwD9DQc9oOAoWiHS7a5OnH2iZcM4ibaYrwElu6AVEXH2Cx52vWc' + b'ujB8ILqQVHgtluaU+lJNXFKTceUFDAekYiFcWs/m3/gIiw0cZ7uf/1dr29st5jM7s7jDnSb/' + b'4IOr9b/9+0+JDlS+oP6OHDnKunt7rJOd46mnn9onwvUNH5H5DFKC35l+vj/054sSAMa2WjlZ' + b'C0oUxbjKHzKN+Qtm8HfedSUXjyv8k4/tRKDKmFFTlyfOaSyUG+cVCbV1BZzH44aIqdgiqxuw' + b'wDAUQioQybIrtPVw4p4WiYM12cQzMFc2pPlin8kO7/Cy3ZsCIrnKgnmaXntlnPU3u63hLqcM' + b'0V2tvTwuBgp0BYvfBPgHX9QASgN9r2R2WoaYbw20OfR3HssVsJhEb8iwSKxHwA6/4V8LjNI5' + b'KRlqgorQYg4RfCJchBqi7yRKYUY/6i3/px/iGwo67PVwJbPSZu3qhJBdrglILmK9CNwZ6XKK' + b'lYsT1owVcXEA+f8I5hHzaxRtxX1j3P7Xg9zJvR5pvJfyPBkP42DKG9Z56gtBTlbtygR/5K2A' + b'bUe66nNDXDom6oPtdmFqBC1BBYeRre+okyVGJGArShaAVfmeQx4LrkKKYoSyYbGKai986HWT' + b'k3ViihABgWxPOjjsAXEAWEZZEtyaUIWo0cQmzkYvGSCktJCJs5Mq4Z58uYBwS9BkRDjIWEPH' + b'UL90TuJY8XiC9fYPQIqYMOrRGiE1JBKNooJzxCZAdv3D6avZPvuZf0idQNN//IM3jc6OYZky' + b'Iac34tELKLkM4DHn0/un7z/1ma6TGl03LfhwGNIQVTI+q1FUnoF7oHhrF+Cqi2YuZQ2r72R5' + b'VXPwbA+QJkhRqoiSRpIOXMHTD6czwF0oZPtMB+JZ7BoA0IIw9pi8WpoNt+9h2157zXxyXcTa' + b'sNfDx2Ck/sIXbzAf/eu7Ty3+rhMn2O7396tvbz2e/s1zB+RMSnegiIeGoKj/Ox7d1zX9fH/o' + b'z5dAABi4QiOeu/HJopKAxPFpLisryK67bilbvqKee2/ncdQkazKhLhqFRQEyEIEAAE8dYqID' + b'tdiOt8WtE10oxgcjTEmZA3XUJMJH43sGObGpVeYPnZBNFA4x18xLEcyngWQJcRjAGrPWxAz4' + b'xynWXoDPHEFDuvH+81mUSIQ6YIIw9+ZxLDCLvfd0lgWrPg8wEj2JNIG5N41ZDkTxVS9Nilv/' + b'M08nA9y8myN6JiYadaviAnR+493/CkP85kXS1y//9LDRstXPkAFoIUIPOQESP4RwZeAcohAj' + b'Z3Xu9jlg+COjJCudlzIpLgG1EbgbH+0HPLohNP0mRCvRRGCPhCQmQ4dXgqIcYR/gYMeQcqtU' + b'FXYFNgQw1PL5Kb3vKJB5XZYKNQS2AJcEUFUBxkwnUp0zyHS0cI2EbkQAJQayH/Ww3yPmQL4v' + b'LS2DYQpAopOTfmqi0IKlF3FkEv9jIAbjIAa0SGMoVU1EIQN0IVq4tJDpNQF3TZ8nVAZCH0ok' + b'kiyK/UfHxpCOPIqqtyPQWYF8if1tYjN5wqnz0dfpn6euZ/o76fuYD1ZvX0T73nfW67t2tDlA' + b'DIiOnGrkTy+FD35x+TDkmDN+OrXP9A9T908iOyH0EscPhRDJSXDnICxTw0OLniC5KCJPRh5+' + b'Qc18NuvKe9jc6x5g5fNWA059nB3e8mvW3R2xDne7FAS2JXMgucLRAbbywUaLfqpvDDcMiiiE' + b'nNTN17dFzKe3yf+PvfMArKq8G/4Zd2UnJCEQQjYJEARkuAfuWbVV1DoqAmK1tf3aasfbhR1v' + b'tdraYYcIuOoqb9FqrQO1KCoOtkDInpAA2fvee8b3+5+bS25CCGBbxZYHbu65ZzznOc95/nup' + b'5bs0NT9/jPLze260b7jxXPBu6Dlr6mrsvz77j95Hlr5nrXuvLionN4UMtZaGDqaWApI/aerc' + b'LLqiT6wdEgJISj61mSIeF0EUMiYfM9qqr9+FssmlFBXlKZd+9kTJmKr9ZcV72gfvVpnRsR5z' + b'FEUVvFFU44aVzMlJU2PJedewq08p2d4hmVqVQvQEGeM9vDRNbe1Q9U1lLn1TlZdy0VicyOfZ' + b'3u7yQqXt9kZJ/GlLlh1VPPyoQaCMmdCn1H0YLUlIrTXE8xPBJ4lBbJSDWhCqD7ArKbkB9dU/' + b'pJnlb8T6sP9baYV9gdqtMdo7jyTrPZVuzR/UNYKCApd8f5cmijcAUJtyXrt+3NwWhfuaBBpp' + b'Bad0uvFFMGtwbDr/a41BtPIaH4vgIZUYBDd5BwTYbRKBqOf9v0Yjc3q3NZUgJ5yOdDwQbV8M' + b'ANnl0nEIUg1s6sJtlK2NFTFAnbNoj4Z4oZO/wGzcEaVxP9H8aylZflfNxhj7hKtb1PQpPRZ9' + b'aLuLE7TRY23KzXqV7Oxsh4oNt1rCwBgGVqHgwh309PQ6wC1WBBEZHOqN/kB0COFPWJQQlr6P' + b'1DjCRaA3OCiADzcO2SeALzJ4d7c/+Oxf3vf/9r6XtB3Fu3zY0wdBuIhfeI8rZ01swIlp//Tg' + b'0lcI6MTMh5O9g1A8CpYExJoQ0AtrL/sFMUicvRT5kHTrAvSjs4uUiad+Vpl+/jxlwgkXK4lj' + b'spWu3ZX2G395WHl86Qpr1ft9/voWX3c21qiizAC1tZ3UX3Lb/ZqIAmJ+FMcoPFztdRUe689v' + b'RCnbdsaok4rGdV999Wn2T/93nmva9FwHpmQ8JaWl1rIHX+h5ZNl7LsuwPZ//wgz7uJOyzPfW' + b'1rnNoPlqSd3Dj+53o495xyEhAAlWSE2Z4Wpp6r04bWyckZ4er9fV73IW1ui0VJxU8pQLLzpO' + b'7ejw688/u1Fd+3aF2dMdCI5KjrYTEqO0MWMT1KIpY5X8AkqnikhkS7iqqSSOCukJkpJ0Ckiq' + b'VA/S3CRphMvApbIHGigkQZaMaE0BIGz4WASC9vt/HuXFUcfKP6lTyudJejDJDWhi6ydnoWqu' + b'fTxZ9ew2vRMzOtSynZQbXxflimoiQci4Zv2YrFZ1Z1uU1m14TEklFkthyJzjukTJaL/1cKol' + b'973oWw0e/AlM/BFwKyZ70WVtSiLJTNevTHKz3+WJpoJYg8eu2xqlxsTbOA8ZZuJYQ137ZIpN' + b'liSrfksM2Yx8buR+NW2C36xZH+MVl2CQgIgx5uwrWvXmao8gLXXOzXusaRe2azyTlXNcjyq6' + b'DvpWqb2g4ABlln3gY96Dam+v38qfkGVQporCi/2ANByp6l9AkQghcnvo+oo8NnR76LnD/RZq' + b'KNRYSv+IWdCl61ZLS3fwlZc2B3//m5eVf7y2zQfSFx+BQZcL5Ufhp5xZSKwDHIBjlos4I0zp' + b'RTTBsQiApzxXYowD/KLkC4sRwtZThMO5UhJwji2cRQDO55Rp512vFJx0iZJMRl4scvaOD9bY' + b'Tyx5zP7FL5+3XvjHTj8ca99xhYZ6YmFfdGq8RbQJHk1D5tMBesy4GFZslH921W6X9Vaxz3p2' + b'rVf9oMyjTJg03rqdQq/fuP1Kz1lnzfTExPocBNeLZWbdhg2IPC/0rlyxxZedk6zN/+IJalb2' + b'KHv1a2VmRRkspEt5gCpBlFL+ZJsz4EMZQk7OwjTqc783OjUm8+bbTjaxF7vEPyARZdOM6VOV' + b'9PSxTjd1dXuVv7/wgfLM/71t19fvMaZMSzdnH5+lZYxP1L0+arzAS3V1dKM5blb27N1L1RWU' + b'WLBrAuvkS1CaSIO1d7ehtLUSH0vlU/knC0wAnew/gTNu2aMg8wcLTu7QX/t9mijpAmQrUt9b' + b'kezupuJ2MKjZFJtQTynYg4eYQR55rzJhdKdjF5YXLKZIcRSp2hurlOyMV5p6MOd5MZNhjCEc' + b'WLv4W7sMicp7+Tdj7S6qHXtI85B1Zk9gzsK9rpfvSzPgMtRJZ3WaL9w91iMJQC+4vdH/5rJU' + b'N9xDsO7DKFftpmjFE2NT/MTtnfm5FmPKuR3Wk9/I1HlElF/cHwIFtQ8kEln4/I/HeaZeRBo1' + b'IgnpzysAf8r1zbgWG9azd47zoJAXxzIXa1x0AXY8Za8nTR5nHndCnnLM1GxtNPZ/AIuFKzK7' + b'FBVltoau4kN5uSOcI0hBWgjQRUcQkrlDu3ESoqIpBVCs3Y3tJlTe3rqlVrIt63vJgoyWPVTy' + b'OaJ/MffJEMcm9OKGiwsu3/tr/bHZg0yScMTxUnPLUaDQR+Sz4f/gcAVxyWOVMfnTlHFk3h2d' + b'PYlU5nHO3aibZ2/fXGy9/9Y65e23tqnFZa3inBU4cZJhHlcQdCfFWqBkp7yXc748ZejZeD5Z' + b'DligOrBI1e5x2VtrUWDuhPProWxYtMeedmymdfnlx6tnnz1LT0oSEXCg1dfXm2+v3RBc+ecP' + b'gu+sqY6efUKWddW1M3Qc6QJP/Wmj2drSTQkrUYKa55RUPPT6wJWfzNagwR9sCAV5C+81g/Y3' + b'Jh+TGrj6uhk6L0mXtFmihMnJzlKmFE1y5FTph6KFyquvbFSefGK1svXDKpOQYnP6jAxr6vR0' + b'XQJbAGpVEEgnDi3NyJytyJskx+NKWciUhu6xcIAxyYsHMmgj200vKEKzzLk/abB6qX365rJk' + b'tbnWpxPFh+eQqk9Oa9dyKDfWi596fVuM0tARK9soGoPkvTAdL7BUyo+lUsA0ITqAFxkQz0Ik' + b'DbXd5XerpDC0Xi8dbadO8QfqPoxxx1hB19lTdimNrdHKxtbk4PW/qtbILWiQD8CYdEZnNLoE' + b'f2wqTjj5fvWJr2ZqF9zeYCaMDQR3kptg26pEjaQjGinJeo+9tNXzf/8zXuIc3IIwRMmlo0ry' + b'xVsmCUwQM1AyRaF/wsFJQpdZ5DYJSgw/OgrHbzXiDQmAixmQZscnRJs5OanWZAJsiqaMUzMy' + b'kzVkYU3yDQrfJKVQIhFCJPAM4AgheZzMyg8t/tC2IFznJgwXxGLzjm1EA7u7y292dvaqOBqZ' + b'zXu7VIDcrqvZq9bUNGvNezuIbJNqzWRNcXwI9vXhuOTKc4vrsRQBmZnZrBSmdcAt8K5lvyD5' + b'kKuCwwkQPmt7Y+JVEiEHkxClPG6LeNIQgIYGhiw6aRZs/YVK4tgCYsGildb2HqW0uFbdurXK' + b'3rC+kqIq1UpjY6uJc6aZmWoHZxUa9tSsoDs+yvQC3E5NP5btwH1xh+ry6/ZenCir91CvoJF1' + b'tEcj7gFzaaLPKpoyhsCmAvWkk6eoRUX5mtcTovbOeBA6ysrqAn999i1z9eubVWoT6j1kr51z' + b'VoF16eem6NVVrf5Hlr6rZuWMMqsqWqJwmGomb9AJpaXLK0PXf3J/I5bXwQeRl7dwJrqPN1kQ' + b'0RMnpwWuuGq6xuS4glSmoUIpdf2ilcLCCUpergSvSDLQENbevq1WefHv65RXXt5g19ftMbNz' + b'E81TTstXc/JTXFE+in0i+UsO/E6UUC2YnNrbyScHMpDKrbJwpMgH5kVlx9Y+ot5YjCTRjcZZ' + b'JYCNG7FVSY3tNaS67LhkKzhmFKXsYlUN5KRRiNJuaFb1na0o4do9ViPfnVxLiVE1zhtUBRmM' + b'ie9zosDEQ+xvW8dzH12ZlN6uTKVqMec4RSlXvJ9pn/mlvQEiGPXnf5Jhkq9QQeZ3SzCRpEdf' + b'/cBo99X31uIHEOMnv2BUdKKhNeyIEgA3W+o9VkudR69EmYj3Y/+cyMQwDhSj0gYtbvkNAgwf' + b'c04Y5o8AuJgIxacUfYwdH++zxowlX2Femp1XMEYZS03BOBRjUCxSm7ksyDENrMvaFzOeh/kT' + b'BIifgM2CtHt7/HZnZ5/VRpKP5uYOm2QVZCXqUKFYIOdutb0d80aPXyNJqkrVYjgS+YCUaSKD' + b'hywIAwMVTksWl7jqUqTXmWO8+xyKL0hAWH75IB3Y3WaU1dCs640dPuHYwAneYFKcGSSC1Jia' + b'FYjB755SW1LhHE09dRjAQbaaPM3uUNKVippOpbKqWW9owCrR0Wuhq7KSYu1gzljFmJJpqrlY' + b'hZLjqR6NQURwp1B2aBY+/Bo5/zV7dxvOTEQvNjTj845zGcYtTL5uOyU1xs7NTVIoMKrMnj1R' + b'nT59kpY8KsWBF3F3bmnuUMrLd0HcapR33trmf++9EtF5uPDKtHPzU5SZx2Uo+RNSlffWVgee' + b'f2abfvqZeTJVxisvlkaTEuzduET9tPXrlwzvMz0wjf/2rcNCAHPmLHY11NQ9z9s+X6rrpI2J' + b'NS+/crqZNyGFqC9sKCxIYeel4s2ECXlKdlYmiCCUElyehAAI5f13dyhPPLFaeWfNNjM6zm3O' + b'mj3eRkxQk1NiYGfx9AYZSCbeLkSDdhRV7WizJVOubQeVulq/UlYcUI45Npqaby5HROjqhFNA' + b'XGhuNgkcwqIMzYrGDTc13rAyUe5kUho8LdHUYigFJTSEICVld5tuV+/W9KrdFKrsoB9s9bJQ' + b'pRottevt/NQutaHdp/hN5E9PUHl1e7oSTNCDx17UavzjgdE+FH3mtAtbjU7iC4gCxHyne9Ab' + b'BIgRsGOSTZWUZcqYwgCmQVfw7YdSiQvRdByNfMIB/LuaUPuQGOAo70AKus2qx3/fbVM62kI+' + b'p4kDjGZIcEsiUELTOjt6BfDVHrIDQeXFl1+cVgBuGams2ZCML/Z//sueER9BLpMw4dFxVHum' + b'AGgycfOkVnRELwF4CdSRAJoef8hfv7nHZ3f14WQBzzI60QwUEcdRkBHQRgO0mOVce9p1pbZJ' + b't+uJT2gmOWwPIpgEIfX0GsKfIO6p5uhEy8hIseys0SRdoSw8Luc6ONHlJxCLHHxKS6dm72l3' + b'vpWmTsqLdajOfuIcwMO6mBCt5JRoYhsSMVlTBXhMDEVZk7S8vCytgHUcFxvvrN2/Pf+e8taa' + b'bUpVRSPWg71wpt2gOdtOGR1jFU4aax8zdaxQebwoNbuuti344t+K7V0721wXXDxZmzQ5zbz/' + b'vjfVzg7DA3K/p6Ri6TdHnMiP6eDIb3OYQRTk3fRZLloJdd4DNnb7ovSkc88v9J94Sg7htKom' + b'BTREgyzUIZ6yV4IEsqhvJxaByFa8vVZ57tl3lZdeWmfvhlVLSY22ps3IsKccM5akmDEOuZIF' + b'bYK2xbwlSEBs3aKxxjMZjkGQp1AgFqWwrLyKgN9G9LARK0yolql0tGEy7BU3E8scFWNaWWlB' + b'O4+Q3fRRppoYA0KwTY3y0ereDkXdQ2x3uz/Kzk/zW5nJffqmmihlSw32eahNt18327vFnViR' + b'7MN2LspInIOIZpBl68j2JDIJWlggAk01XqNuS5T3om81qiVvxJpbXkhyq0T/Ms7DnuvI+foo' + b'2yEgFrFDuIzQd6ifkHgg2/AEzvyF2H62/wWjFL97idCTRgJZJ3RWgN/BKTIW50joRuAof3pS' + b'sG98iqn60MLzWl1t3VhmAHwoNIhCcJEKoFsmIc9WHCbZlHjTzhhlKGMJL0eBpxLZQXyBqgly' + b'r2umrmKDC4ShqwC6XO+MAaUf+gSXHRePiTfJh5k61k5Lw1IwRmIdYlA0UrmaFSzn5efl8MnF' + b'Z4KS5B295ksvrtOXLXkZZ55aKwVEkTo6zsogtHdcBq7d6fFqamqsmL/tPXu6jPUf1Jofbtql' + b'dlCJCP8Y9dwLComAjNf+/MSmvrferIiCIIKhzYtLK5a/6EzDJ/znsF93dvY8n1fXX2XpFLH8' + b'7wZGF4KI8yZOTgmce+EkdVxGIhIu9jMBXj4S+CGVeEYTxCJFMcekjXYcUsLPTZCKsmFDhfLK' + b'S+uV1f/YTNG0dpOJNWbNzlIKJo92UUoLlTd8KxROFrKYt/y4vPZi35bIKvGDF3dVsXOLGNK/' + b'zBxKBR7CPRalY6cd0ic0ic6BwWE7iKG4U0qCqYwlMxkIgTRmppYQbWsQTIlZwR7MM/CqZAEi' + b'2pqi9X13RzSFh1H8fWen6Y2xVdKBGV17Pfrkc9rsnVujiUqMYwGJRUJRr7yrRrCTvWZ5il2z' + b'CS8VBgYQsA8izKxzaAAj9L+Fw34Z4Uk8Ar9DDj28sMiHcoBfaCaaHtnmg/QQFPMa54tIIdF1' + b'cHCKlRBjWaMTDCudsvMAO7X8LA1CjbRha7xBtbuPugmdItrBIezVlJrdOpwdruRwbT4S9KWm' + b'Rtuj02LwRI21RyWTaCbRp8TGe9XoKLfKccQW0QOI7gHywGDkIy8GxyjLrcf7N1LAo2THTnXH' + b'jl3ant1tbjT41hlnF5CrMQU9Cz7AWGLwXkUvgqWmZE/w/bU1Sk1Nq5aSEqseMz0d02CabFMP' + b'RFNrqpr8D9z/juh48Dm265FnZm+rfvgTdwOWZRP5eg55GRXkLrwQTPkCmU7/wpwtJib8fpJg' + b'ne4jAefM2eMDM2ZnqmPT45A6NeT7fkTQb1eORk8wOjWl36c8dZ/SUG7ejiLnvXdLlL89956y' + b'9p1tNg4qRm5eijl9ZoaYULS4WA/1BiWoT0o8haiavDixW4vfuzi0CGKQAJk+PoIU5JiIJQJw' + b'JG4ASehKUvI4s5sM1vW1bcquBkpAt3SrATwXyVdBglPbSa6B3GiRv4BSZrLwFBs5FOlEVT/Y' + b'4VVLKDP++bvr1K2vxAdHjQ9o5BZ0te5ym5RJV957epQuvgeX/WCn9o8/pAVnfLZFfe5/07Wp' + b'o8zAuNSgXkJuwSYSkrCAVVhc8Xvn2zFdS1ppgQGH5PW/DIcgyx/nIztlu5+GOj8/0hvs7/2f' + b'/GJGw+S8n7qHRiaA7Xyc/qXuHuXb4Lfc0Oko1J5EhJqJVJcahYIvCS9QFH0qAK8S208VacWG' + b'E6ASj83aUQUBK209utrSqSqioNsLwCPCqa1dVIIPoHvAVBId46aCb7SVmztKyc5JVNPGxON7' + b'4pWAJt66cOmKw40m4vKciDu0OKqJHkTcqD/cuh2igqkFJ6L2tj7/yy8Wkz26zpU0KlrLgMKP' + b'TU9QM7NHQe0THcCXR2JNW40NHYH179da27ftVqneDIs/Wpsxe7xYu0QEcPRaci7zYDy05F2l' + b'ZMceAxHXw9t9vqRi2WVy7EhoH3H5zHEV5Ob9VdNcF1hW8Fx3lO9d0++/AwJ8GwQ6SUpl5eSN' + b'Cs6YNd4unDhaj0H/JdDjcARArogIsoxDFXLjlRQQQiqhrslUwhWXVWl79rQrb725Vfnb8+8r' + b'mzdVWIgBZtKoKAsfBCUnL9XG61AbNSpK78fmIp3Sr0y4A0XOPUR8CHm/4WJKnxLo4sGs5PNi' + b'WhIyzOkoMO2e3qDV0dZr76xvUUt21CtNzd2uXkQJSvahUaA/hiwIxM0HfINGXHWlZgcCUiUZ' + b't16yv1iqpCQnvBdXYZ/x+h9Hq+QwVHA3RksdMLe8kqBdnBMwpuf7YyQxKn2Y2MEt5kpDjynD' + b'JF266iKJRVDKURG5a7LwQRKaCaJw4YtuwYVoqFBw7tHQjhPtCF4Dt1IoBOMsf+iT0QkRlaey' + b'ZfsjvluZluGa9IzyjUPSM/CD96dQcLGT21YoYaZtQnypfgOQk0eRzFdKPElWMVhosO9qfDQO' + b'TRSMhe13VArMhdpLvgieE+Wso5RT2nvQ0/RoVluXprYg83dLwWhOd4l8QJlv/Eis2DgXVZVd' + b'SjyOqXzgLhORvcc5VFlGaTExMhEy0W7coGfOmK6MzxgHkKPCjmhNzXvtf6x+mwQlbcHtWxut' + b'de/XqPgcuC+4eJKak5cs/TmJS+R5Jb19wG+YlRVNgbfeqKJWQ7s+fnyiNnXGODVvQiphzl6J' + b'nHS4XthAQSiiWzFffL7Y9f7a2jLdo/0ZLcp3mMCvlJYv/V3EMD7RzY+8SPLzF87hPSIKmGvG' + b'Vow/Z7Wy2MjPv6kIg/dtAMwVsLvJYtJLTsZ2XTTGLJo6BuyYBBalgAJAJcgg/JJYsaKcchBC' + b'XFy8gwhSU0Yhp6UAtG7MOW2YdWqV9evK+K5RKit32W2tXZYUWABD2/SrjM9MIClFokr5bRRA' + b'MOK8MFkAzrLth4UQdISQROSsC+vHy+Zcy2pD8djS0kIlWVE+CicBd4GVA823AtABrbLAbKWu' + b'iv1qn4QIW71tbteU81tNIgcpNBqtEAsgab5UAoOMdSuTxJnIQyg9lA2xwkBrz+jE5RRTN1QR' + b'oCFbIopLKx6xAsAxWesCJEKksBhLTCQTKdDHHwE6EAdhvKqF3pURaAb6WF3qeIBjUTaIYxzu' + b'rOAAlNU4nMHWMNVMt+grpA8CZB2nF/HMYUoAav47fYcnhWeCNZf0IbZMi5jhAHCpFh6UmHrR' + b'K7rdqiFikoQQCHzQtxO/j6nWTY08Kz7KIu+O+G846eCVZkKtKZ4B5VbtVgBb6umJgk5SxaN3' + b'5P7OwDEh8i7IckYqBKi2bhFUZicmem1+izs5D0OvnC25CySuQYKYEpOSnRiH8PDD3/Lg48al' + b'K6efenJ4l/OOa2sbjdWrNxmvrtpgl5fuxsnK0EenxarTZ4zTMFVr5LtwnIKE0mMVMevr2o2a' + b'6ha7qrKZaFUqVE1LJyvWeA3xgreBRN+/lvutITa5GEQk0Ddv2NWHufRZJvG7vM95RIx/F2/F' + b'2aVVyzfvG9AnvPGREYAyd65esD7uWU1zX2xagWvKKh96MvwsubnzJhCSfzEa4+sA9hkCiIJ8' + b'Yc0Cx0wba09jopGPHF2BKA3DLYwQ5Fu0zWJKjCawaFRSIhxCMl5g1FbzRQOYlBiv3YvDSVVg' + b'1ar1vJg9aFeJ5mHBpqXFKYVFaUpBYapKWm1eJrVoWOVyH+l3uCYvrmlvV/D1VWWyuhRZBBMK' + b'kt2YJskUSlATokUf7ICIGaKQlH295NMvK+lWaiopjIGegRgFc/aVTf4tLya6Ck7rNMg9GJVI' + b'EBPBQeI+7Dv2uBg1Klq3+nolYw6ejlyDpy42dhIoEnPgJ+0aSAZoRjJ1xskyD20IdAp8gAuQ' + b'YcT+xh+BOpFBBXjhckUeBWlQNxEKnBRrKJkpuE0nmUS+URvZZelybGiTbkNt8DKQ2/PKuItM' + b'GcNj6vrw1Ozs0yzx2MRgYKBhd4H+REnaD8iUOhPkCMpCVg+kxFu6JC6Cc7F7Ma3B4TBIKDkA' + b'7vXiUBNFKXcCxSRYzIdJ3ecD23FD4BrTpQQycX/514/EhUBIXsSY2FgnulEiGSVkWbg6Kbkl' + b'OF7OEQQpT8VPx4dBkF9SUjKKYI9VXb3HfPvNYnvz5lrOsnSovFqIoi4nN1kVlh/TsaQth7j0' + b'GiXFu43irbvtjk6Sy8R7cbqK0zKzEuVcDY7WsVYJ4AvxQM4X7Gvuqm9DCVivbdnUACHpW4X4' + b'ed/O3Y+9PleZq2/JS3if2XSZ2q7jystflPJJR0Qb/OYPc0gT8246iWX5Oli52NJ6Ty8vf7wj' + b'souiormxRnfsWczQPN7kuejjo008XuLivUbRlHTzhFOyNBR+0EFlWACV9b/vQ8dCEoWNE9Eh' + b'NhbNLciBUFW7paWd7DdSYqvVKt6+28bZAsVfnxYV47ZFeQPSQUYbg7jgJlfdYEQgiEYwPcEa' + b'wR3b93hFNGB8wdu+fppkxpGE5pGP5IxHXryBJ1p5WQkxDtS/I+VUc5Ol1Da0B3ATDpLG3Nxd' + b'5o0TZZVQK6ilcsqcWJFTHa5EdBNCnWSVAtf9/YsIA6kXW7UDfaxgAUKOO9wM27hAYKoDUYA8' + b'mpsMpb4O0u94TFvsUR8HNcjCSmZ4yFF2CngtTiPNIcAUzWOBgsWQB8IIDQszConqMOOzC2ad' + b'fPaCT2Q0fDEE2ZRcCWLtcIBTnjsGoidALIAWCuGW9yLb8h2i3qHjQtGFswIpQc0FyKVItAC4' + b'nCvzLMK5PKPcVFLPb1xPfj64Kwkln3l8PO+YyEV0RrGEMMcC+ELx5f3LOwuvCxmu/IbdDu5p' + b'7CLfQLdNsk35bXdj1O/s8tu4pfO+TKHsajZmumnHZmjjs5LIfoRQx3PKvMPlGSjz+nYU78YT' + b'tUvDjV2fPGWMLiHvcXE+cUYUDmof5ypEA8CXewSLtzdaG9ft9ODwg3ObuYEz75p1fNczK1aE' + b'kn1MzJ13DHXV1qMs/3VJ1YN3yJiPlDZYKDrMUe2oeHBtQe6CFYTrXUcg941c/uvILrZtW9HF' + b'byl99NdJ+TfO4FVdjzFtbl+vNe7dd2pcmzfW2UxyYNZxWchwSXgWhsQDAY7QwnDWamSXjlKv' + b'izx5EqoqiwCsL44oeiKmnWnTjyPxYg5yvWXW17cqmzdWud5+a7v64vOlFtTdOOHk7OD0YzMg' + b'JLw5uQFNFh8ebGZDQ4eOjOksJiK1NHIfBpVRNiG5AxxKeCCC9SW0dkLBRJZwCcqjVjTMEvwS' + b'44EjgCmGrYeiCYXLyUelza0gXizgWCU3L8+xXEiUnlgvxG88iFVDwmrhb8kUTwab/rHJCAUK' + b'ZfU5C06AB8hDmWSvXdMKJ2Cgy7ZfovLKXRDeCYpLvVS4Y12xni6t7vhTdjYITPXgWdPr9ffF' + b'kDKgz+0yPbpgCXweJqPIPQfkUgfArzJ4gUK9iWVCjgCjifRBoSvukYMgPIkdcxjGyampujZl' + b'mqTDHpg/fjjvQr6dJoOmyZfzKDLJnC6A6vxjhILMsfU6AC0puPAkNDraO5yYgb27g3ZWZoGd' + b'mZWMhqG/M6evAYIg/Ycb47L37u60sL2DmhSbEvBmQqK3P3WZ2wKAtXjWR0JCFCIL+gaQA/4O' + b'cF+CxkLjEuRGHUadsHY3pj1NzpVDIWQfMmnKY0jMA6/famrqCW74oNbasG5nVEtTN3ybsgYV' + b'38Pc4JnKyiXtVbXh0cmj62eCW92Gbb42sPfI2BqY3Y84nsmZNxRRUvdt3i+xcerZOyqXfDhS' + b'V+gOMigZ/1nI2rVQlqlwXJJZRUkfF2MiWxkTJ49RsbU6Pu6CmR0lXD9AjNSvALSEy556MtGJ' + b'iAyRjZwFyvvvFVurVr0dmDI13SVORw4F7j8JgLZWrtgcfA+kJP3gzGHcdMtJMgZHsRPZV+S2' + b'AKNYGepqa5WGhl0OEO9pNJXGnUElr1Cy6gCs/X5QQr19ULBjjz0WAEbV3f9MMo7wR7TRsuBE' + b'OyjssJwTAnzN7mj3B2FNLTgYN1xA36oXS70gqR6E9SKSFOaQQPEN6HD/+4RuK9YtOyqWPRA5' + b'3vB2Qc6C42DH/8LvDBZ1ALl0fknl8sfDx8PfhXkLzwQPEMFlvlhSktk9Ia/2S1ZQ+eUJp4yx' + b'Tzo1UyUGAFHIz1ApghnrJchbZSiw48yL+BfI/AiQg0Ccb9ke+pFzcFoi9qMnuOyBd1HEtrkz' + b'MhIDt3zlFGJHsBsIp3SAJghFmgOYQpH5yLYgaEFPIDfxcgTg/VbTni5z164Oa09jp4WjmX3s' + b'rPFq4aQ0ONJQ/9KXsPKCsYQDE64r3OQYKc3l3Zi11a3B9R/UKYgHPoLf+uB6/gYn9Mf0zPFv' + b'rF69GCFov6ZiNfsbXZwKDzatpGRp1X5nfII7+hfMPzeCgpz539B098+QxVpYufd4TffyD2v/' + b'0DpSr5RGRpDqmwoDfjI+HHMolnYSkm0qbJqSnhFnIMOb4kop5bF8VB/nvYCNh6cA4fvIYhHK' + b'PKVoMj4H45zt8DGhtqteew1TIar0gXfrHJYXDEWAgrQG/X2mnY5Ygt2YxTfkxHBnEd9yrXzE' + b'Y1EQQXtHG4tHZFKHuIQoIOfL2ARBTZs+3QEM6UIWrGiLYT/F355McrDIEF2y1oRYEXawgIOv' + b'v1IaXPdBnRtWVpR7/YgB5s22dpRUPjhpQs78O3TN/XMLb0lpwtXT3ho7vuyM1atX77coC/IW' + b'/BZp/MtYcABUCTmwnyqtePDzcpG0wpT5cUqCtpTNKwELjpvvok+8sqLioboJ2fMf8vq888aR' + b'xQUnKolrd8aTlZMYxE5ujc9M8og3YRjBOR1G/IncH7ktc9HS3GNUU1JclLqpowVJjzj/BFAw' + b'q8iV6HcsrDmw37iIYVZA/jabmrpwBPNbMj5EETsuwaumpMY6Tjk4AUnew32muojhOZvhdyoi' + b'DMgEN+mgUbJjtyFca01Vm9Q6IO5b/SufJZj03h56feTvoux5Y1CXoPSzmpLTOmetXbviE43/' + b'jxybbP9TIkC4M7SavyjMW/Auv78LIrgXxfTNhbkL72N5PSHsUPi8yO/y8t8KJ/pB/+dXE7Pn' + b'ZVuwpPimf7airPn4itLmUR5vOXJzlI3iJZibn2xji9XjEynMQ5oAAWLB3rKIBHCkCTUR+Xrd' + b'+g3KtuIdjvIwAW9EOaexcbcToCQvd2iT44gFBNQkQjtEA+3W+4Nuhp663+/Q/ZFbcX+OKyoS' + b'CwLcQIPSAUIQ7kDuJ+cI5RuXkeGwvEIxCZixoUYBUnlbleVNGjZo/JNkv0tcUo1pMzO00aNj' + b'lb88vcksKd4brUOB6KqMAXaAAwBq4iNV7RkZELx6WQiryeidPdzTbB8O+J3DFnJLCD9xMf9t' + b'm+sHmh2nXsXSv1Jy2YsBQtc8J9D/lzjj2zzPHwL+wGmlpXsrebL18Oh7mPhxmzZ0X7OjeM+Y' + b'z1xa1EcEHAE3SCiH0eRdYuZ1pY7O5Cr4FxCmvFeZu6FN5pQaFcHKsqa+1tYeN153oEnivlxi' + b'LXRZMXj1kbRWm1xEZuV4nxYdI15+QDMjEqQiegYhJuEm/QnXIDoNGhwCpuEevym5LytKmzT0' + b'Sp49u7vd4Jtqj1t/nMSFT24vf3Bb+PqRvg1y1yCkjuaVv3CkAb+M+7Be0kgP6hwjVqCwvv5q' + b'ZMrvQ1kKoEjFPPjveqLtJ+u3LTt45sj+G0zJX5QXtAwWnXYWgHgayq0sjdcbHe1SUkZHm5lZ' + b'o8wJBSk2eQb02DiPBtV0ZHpZRGGqIQsnvIgEOAQ5yGe4BvWxSW7qB8OzFBRl+sxx9vkXTfLy' + b'Q5REh9XkHnJvJ7DJiXDsQ/Glg8hSEE2SnDEJ1V/7dnXvK38vdnd3G1ibGRfCOwtRIM7FY4Aw' + b'sCzEeIJdnQFc+bVG9t8R69dWrt+1pGfogNLTF0UT5fY7uIPzWb9Mv5ZEj3VEUJ9RXr60fuj5' + b'U9OujwnEeH7EeV9nbtar7sB5O3Y82hw+ryBv/m9Q2d0m8RfSsPTA2BkPllYsWyS/8QZNrK5+' + b'uE22w21i7k0F5LhaDqCddMttJwfHjounJNiB2ffwdUO/heLiZIOzp6XgQou0pDkh5EPPk98C' + b'uDSm25k7AWKRPuRACHkIsHMskp2XC+Q6AXih8DLxiARo7XuN2po2W5AxRTvd7e1+4iNEeWhB' + b'7bX3UbY87bKNFw7Xgw8d2f/qmvc7huW/tqxy2RNy/yOp/WsRQP+TFRQsSsEBfCHz/FUWzxjT' + b'MsrB6Q8ibf6ppG75rsOZgGMyr0kKuGOn85JPhaqdCpWciu5gtMiNsbFucg3GGWh0TbT9anpG' + b'vO5obHm/IscJppfFMVKTxQCSsX77izctfLmBVVkcmnHb1081MVsKJXMuB5mw4Syc4bHIkJsM' + b'h2ykCwmVLd7W2Pvo0g9IfKLisaC9hcHqLzi7bONl9EHdM1jHoiO5CLQltQphGc1LSiuXv+qw' + b'ky7Pxaxq0hT0PlNc86eGiNuqkyYtGiO/rT7jOk33/ZzaPMvLypctiDhn32Zh7vxZiqrDgVkr' + b'YGOv3HeAjcL8+ZdgcfwTcxcXEifsJijm3PLqpavD5+Xnzz+RTIJ5fjvwhogGsl+03Zj+3jrl' + b'1Jyoy66YSm4GcSU49AbysN99u7rvuWc+dHIgoBg2rrxmhgsF78HEgRFvEgZ4ofAMyFESwzlg' + b'32+zse1rO1EeNjc70Y7CnDWyJD6EY9vEe+Bb3Qi1384NRl5Iw4wgI2PBKLxIXwUtTVCC9tSS' + b'mqVVw5z2ie46rBd0uCPNzf1CJszXAgD2ZtjINHK0NfAGHuc9PHyoLNTQe+bl3Thes13TQChn' + b'gN1Pw2yWB5QniXY2IdGjkH0lkJefYo3NiMdTMFoX0w/YXjzlQAiDRYZw3ywQ65Fl7we3fdgg' + b'OetQ3OnGV75xOoEfMR+JioX7HfotC5ExGw/c/7axs7bDx+L6Y3cg7uv19fftJxfiVHU6tSZ/' + b'wtDe2lG+9Dt5edePdinev0O3ZgqFgyK/1tWrXbJrGI4gP/9aXGh8bwLgk3jqC4g8e33oWCbi' + b'yIXO5R+CfEoql10x5LgKF/CWprpPQvZ/nKJsd++ofHifcrcgf8H1+OT8EYQYDZKohqG+HgT1' + b'FmZfT29X3PuZWQlTb/7SyYIvIcVDej7AT5kbMgdJxJwgYiwWmlhn7Kuvm0kClCxBJge4cv/d' + b'0lc/IuegowiUIik487SJuKXv2tnubgHgxZcDjnEv5+8AObwNMl6juAKbS0sf3bl/r4e+pyBz' + b'fi5BDXMZxgIePxWr0NdLypY+dOg9fHxn/kt0AAcabmXlo7Uc++GUvBuXBs3gNZis4Ao8t5Ot' + b'7hYUUSvh9v6wo3z52gNdP9z+fmojFOdvM2cucne32jlE92BiVM5qa/WftqFpZ87GdeSfw9kE' + b'Bw5rTHqcOT5zVHAcPtpEfmmxIXlwn8ggHIIgiIsvK8IebgcaGzq1Y6aPlbyG/1Lgl2cRLXP5' + b'9sYgFIfQYK3ebxl3CvDn5i7KxPntAhaLFw/hVWVlS4vLyx98Y86cOfuUeDjCzoZln+ko+mAT' + b'wNynU8xyPN2WSN+RTfwxiNq8Ewq2EsT3U1j2M2DZ+yLPEX8i+BlxLdqvAfyXwZzMJtajRvcE' + b'vxopHnAyr1G9AaYb4CcZjOrOBsh+zP4zlfZ4qqbY8fgkSTgySlt8nPfrffgdDEbyG+BwFNJZ' + b'ynuBChO9R6624S9x9gqwy7XC0suHky0Qh7W7odtAqYuvRBsA3+FCwYh7N1XbbVtEnWLY+nfd' + b'Hu0dbvrhjuqHatg30m1GGMHAoYICrCuGdjMDuoIhkbLWfs5UjR+Vlz20YeCsI2vr34oAwo+6' + b'NcQi3l1Q8PllkK7LWEC3sHCup0jCNYV5N62ENb6/rGr8W4rEFR1G60+oUMol8nkKQEpg2U1j' + b'HZyI7HZSU1P31L17e8Z+uHmPVyzaZCXCqhBrZGYnBTH1IT7Ea4SBss40ddy4BNfCW060e4kL' + b'wPyEYy5Q5oxGxIjDGNQIp7Io7C2bdzEFqIVs5SmAslEoOwFw+Eq4pnMc2cWu5jlOR3laG6nE' + b'Q9HdBJUSxZ/zzgCQ9ZbujxQBBt152oy257ZsiH8OQL4EX8jnsNRwriA7vQ9r46+g/njiD7rE' + b'+QGyoN6a+i3YJjeL93dlA7qB8NlMiNIqGEhIvPMNNuCHHfQq55J6JKe1rcfavrWhb3LRGHwQ' + b'xH334BMo55BmTj/plNzA6tdKSVxsqcefON6Am3NLsIRzt35gD1N4bk6CENNCVrcAcHPnzjal' + b'pqpVEwrf2uKXlHUiBDbxendA3XNAwO/4FP1b25hbp8N/yZ+5emFe7OnM2S04T1/MTLjhuv6C' + b'tHd/adXSNf+SW/wbO/lYEEB4/KWlTzaxvbQode5TgbiEz0ChvoyMORfP/csKcupf09SFj7oN' + b'90sHMyGG+xv63W9xeJP98lGKkMFMrzaRFzIDID4es9XM9vamzNKSvTFiR4ghhzxmRoN4Ags5' + b'0yb0WIsnDx1IwRIvMXENZdGICCFUBoV3aL1L3+EtoVTykd8CUM5S78cY8hX5W8xVexpJke4Y' + b'Cs3npReCUyfRw/QIE162W7WO5dCgRVpWnfVBYW7tPNj6u7m8FV/Uq9Mzd6IQvM3b19cIkIVy' + b'02laq51Wn2SsWLEkOCHr+m8z/snM8TmiZJQmrj6qCx9nxXwKnoSpcXbv+0O2k6s563jLDFRT' + b'+f2RfQeUuVpBTvxMSP6l7DtNngxk1MrYawHeH8h5vM9GvJnWdnYEpzy2fF3cCadk9150ySQP' + b'wHdARd5A/wwFT6Q5Z+V78Nw0AHo7NS2ONCZgbqehksRU29tjYH70W43Y9GtrW1Wh7q0tPe5u' + b'Ku1gnuNp7GbGJRT+DQw7b1lu77bS0j/uLMid/wRvqPVfBfxixtbN7vPgyr7MfJ0jSAkdVQMM' + b'yJUiDkU+15G83T+5n8wQhdpg0bse2Po1nyhWp8i2lWBTIg3NFYYSs6HfXPgvGWDa1Ntj4npa' + b'C+D/74D3vQIjMotXTed+3JvXyIeFg8+5ePqR3SfGbcXE+fj2mGIaJKFEQEyQXg/GOpdmoNAj' + b'xFPHxZhf1C3FfCRsqAunEQtvPYO4cTdsps15KukTpcpP8IHfvk3efZLwBwPTync+Xj+FZKtE' + b'tb7NZXksIOc5ccxZUlqVectwHFFh/sLlqq3NRe5GgacKf0yVIQnEEWh2ngG+W0WnYNWamvot' + b'2aeZCt58FugHNz9FfYxFWw4SuQvE8GqkDiA3dy4VVOMZi7sIZ+cvh6PWJmctONZ0qT/kHhfj' + b'b8C9jG3oBu6lUO9axaPsKilZ3in3CbXFWmFO/RQA4ZeBoHXWGWfl9V14SZEX5LffWpP5ZsTO' + b'vAsA9SNaccTBLYS06r0BHHi6DRx4lD2NHSTW7NLQ1rt6eoinwL7PM4jSdBcUvgQ0vRHJYw1j' + b'Ki6uGl83dO4KcxY8y9O3lJQvnd8/0I/0lYlSOsoVfRnDXsDYUXRYuL9rS+gsH5xo4pcxVJ/y' + b'ke7zcV30sXIAQx8qJJfaSwvyb7oVeVNMhnuhIlfiS/A1qMrXqPb+Lt5oK4nk+FtZWQay7uGJ' + b'CEPvt3vLvd27FWUjppkPWXYnoPCZ4zJ96bzE4yBffgAnFko5EX/uQhxKxuNTnqDYHTHQTmGL' + b'Bbqc+epfyQJwmArpCQ6BPvo9eIXSSiSflE5wsuIaHkLmQApygEwxfqGIdVaUwsJRlK1VS3cX' + b'5Cy8ERfgr8NJxHD/Y3n+RQW5dV2llYvxGx/8zHjsPgNTfRKLbRrUV5M+QkYwaDnhZpgChQrG' + b'w8GfQjnlF0uqlv6JU+rlPGkT8xY2cp8UzmOqnSHJH6e57YQsALcIJLyGZIfLZGdGxtwoHI4f' + b'0VXXMSCFDaYd/DXh73+trFw+rH+HjLekStkC93UlnsSvvf9e3bQTT801neAvXjCzJTCPCoI7' + b'4TkGCy9++LDxeOs1dVuw8Gp1ZbPeRTbOgN/Su7uDbilkwkN28rSsD6Uaz8JSgkQ3uUx9s8vq' + b'Kfmw+okRnc6chxMODgnI2f4IfyblLMgiw+i1iK8gEDUPhAOiCr6A7/H/6zaD9V6cfXgfD3+E' + b'rj/RSz5RBBB6cqbUXrgKKDozLkm7oadJuctUA+eyUK7GCH8eVOoEXLZ+WJhX966tLHqWt/jK' + b'jspx5UMB47BmkdgUliCmpUBnedXjkpt9v/zsok/AkzcFnVQKoncCLj3oF5Q4FI6Ew2hEh9g4' + b'xGs+FlU0Szqe9ZwKLhhHX8k8C/0rUD1bvOI8RAA6jksgEPQN4uQHSoto/bLiGtmFee1cqPLT' + b'APDXC3PrgiWVc78bWUF2R9Wy5wsKvrBBM7RRiNf0o6I4NLs0SyfkzWqG34hhqZ/D8/2UMJdY' + b'MclK0qRkl+7t9XTgbai2c/+xsNtci94TMVr8CFJMzGBSk9dylkSpyxVnH5N5S1Kvp49gLTuL' + b'iM+nyHb4VZcr0FtZsjSC4kc8SMTmtvplLQU5Ny7z92m/fWdNhTFl6jgTd1+7taUXF2K/SoZh' + b'ArawtZPVowcg73WiJMUVWtKuaK2MsRH0uYO53ez2KpuptFSNz3JNxRD/g4hbjrwJ0hk06SOf' + b've/o5PwFx8IlLgB1fR7LxyiCI98Hj/HalXxQ+gPbKpeVF2YvvJSXWgBHIo5tn6p2BCAAIQjK' + b'0yzMr3S1mJeV1CxbwQw+Ih+o//eZ6B/xaeCcU6FCZ5Gkurcwr3atYi98ngmHwi0fpAVHc+7a' + b'tasgMT09ve0AvtkiDgv1dsUYuNcdoPXrE4TKVRzglP12ixksGHTFq/6YOFU3YqEY0bCkpMTQ' + b'iIczSYlBXmDbgGiodWjqhwWi8vLlr6CFn4848DCI5I68vPjVFRXKS5E3U03v/4NjSSY8bRfA' + b'cgxxr/fDcfwe+ekaaNwPeL43ofK96PkzSDO0Os5nPRhQrc/opvcdjrezerFCOI7v0m1nrM/4' + b'il+NyrP7zLth6Q2IGxJD73zCmuah1LsepgLwUcuJLL5CCWo3wBXMqa8/uEurobofQ5/x2XfW' + b'1J/5zpo6gFuSFig9vHDHIgE159XaJPdSt0LV1/O7Ab6pxKUa1Z2BblLsH/wekfMy4rZto/yQ' + b'KMmDN3mPZnfiGQhWN4OOPsOCAeSV5ylPs8Swg5tcmvcNxLTq7qAScgPWlOvgAHdpHmPjwXs/' + b'ss44IhDAMTPaN324PmEN2SxuR7nyXFjuxy3uSfLBfIvJf4kFvdTU/ReCCC6E8p2ELHomirOf' + b'gSTeYBU9obkDL1hB96kNdepXOSezoW7nVhxnbh7quSWZjXfV1ecC+QkBPXo8r+Pg7GP/O5Pi' + b'KF5N/R4AVADlLIEqLS+rfnBT+JUS/RhgWxSd8vnIjYSRzxTm3DhT1b3fJf9G8tCOeN4MgH0U' + b'+8ksYI8BXqOYo7H8ToVrmipyMPRdxiJ17vJgTceAFPJBKNXsA+OqpFk2O/nmh+aHUxgHMj0H' + b'fcU9cOUk4VLJXGllcXgGWQtSYZa4VPNwDn0ok3w+YnMdByXpbPhWWDg/rqSktDsvb+LndTuI' + b'vGz7UYXUkNWvlnIijvhD7l7D22e2CrcwfC+RexdrBXn11yE7fIawn3j6e6qkMuORQ+EE0Zss' + b'AIGdgqhkIQIt2lGxdEm456KiW2MNf+AsBKgcYn02ok/IMPq0L6ku9UTEFJyC7F8D/o8SxrtF' + b'rpEAKVQuE8lv9YP6+qUthVkLcxADz2d9PjrEXBq+xRH9fUQgAImbhur9ntCYlSqaVWbsOZm1' + b'ioplFcjrq1AizzNU/6/Kyx/5GS/87vz8nZM0038S6TvPATmfChU8zwp66gECYb9hzSUYx5VL' + b'As91dPNj6Uuak5ihrv4XAMNViPQELypLMcNdXFHx2J7QGSP/Bfhvp98vk+YNQqqfSxjKxYzv' + b'JnJdOG6xqkHVR7L9EFxIRC1mcBf++l63X+slYZorrjWM2Ea+S/9RXdkBwAGn5n7A4TgbE3gH' + b'YEslDqJdtA62+zDtQ0SVaLSAmexHnenIvCAJVQzyqDZBC6gnAGy8hK12S2KPyUXCfFAAyyaP' + b'ER6GIAcQXCy/0X9wRPQfcM/8Zl7taIakoXkUDmrYJoBvG9oPFVM/uyA3nyx+fV/GiYj3NnyT' + b'8xFpxsFm+9QgmcVcODnKwHgWm/hCnc4YMbvqLwBz/YQ0dAxD/ttzCnJ3bi2tdOJJhu+cvZie' + b'8UpVvs9zOmmpQSBfzs+/4BFJyjET0afLH3iCx/sMXI9oSFE2yEddh4ZiIQX99nf9te3LOdYb' + b'tNWn5abIFZ9jMORYF6vKp68dEQhApq2r1/UyaaS2sVi/gYPPi/02fpG1lgLUl7Eavs1pNwnG' + b'Ly9XJBBDPg9OnPiFZKVPn8K6RvuqflmcU0IN4NGgWBFtS06c/J7P4hEYEiQx22VFnc4+ETsO' + b'2uBYJ6Cg5lKBJ0kepOVwz1dDk0ivkq/UWZwsWxfAo8KA405OFjwy2fvLcH76A/70UK2DNwBN' + b'dApE41r7cSjcAgC0M6D2uBOoWVCqeZxLALv2RUYRx2I/nXEKwGKesnyiS+GOSVx3Ij3K71Tg' + b'+O7QYO3LeQaWvx2N5+FSjifw+1QmiCQjCo/mupdjggRY+CoKDEUNWK4k+msc7im0gPZZW9e/' + b'IXMElyYa/c9z3odDz81Ev+BzB+5WTZJZJq4AACcFSURBVO0MkNIYYg49oBUdXQpRT6jYuDO3' + b'4o/EIYS2EZ8c4Vv64t2RedIWrmfEppKFEERPQjZOQz/KqkhDB8ozKnvaooLTSWv3GcmLIgtN' + b'9LZwQCtKK8ddNxxnIRYAOrmYuXizsvLBsvz8ei9dXglC2GLpcfvpkUYc2BFyMLR2j4DBiEtr' + b'TN78B3TV/Zv2ZutMhvSyDMvWdr1qWelreDnX5+ff+Kfy8ofeiBxuP9v1BgEu6/pivKfBqU4V' + b'JABw8lLVQUoZxIl2aDdKMB0WFlBBkIMNOCTqL/dEHnwF8onCx4EDFpPZzhJ9Vw6xWOECuSPU' + b'lsUEUwAlEVYBVlkoMKF+87jujxNyFzQRFPKC9DdccwJ7fPa3UNLfARB94PJJpN9AI+ryZPo/' + b'HcBOAz6O4RmAF+0GATie6yL5ZpGOkedjSU9zjivaLBap7J8oPTmwoOoXONcoaja7nMacHS/7' + b'OO4NMQ+CJFWJw5CL0nlWZ17hF36GCffqod6F0okoFZ1v4V4E3AYwsuzub3N1LKq/waB6HYrY' + b'DdzlJV60WGC4L5OLzMG9sGg47AowJqyINUoUwtKB824tqxbMsB9iCd8h/E0eg8aJufV/Rqvx' + b'Ja4EuxgbMfY4FgydUpK8LTI1iHWHZ2TN8BY5tlgma7/mc0edDvufSRK373EyaYvnTwTLzcCc' + b'8dPD4u726/mT23HEIACZAvw8VsDZfo/gvK/DsL8q2m9h1WCz7+TdvajbriWTshfeUFy9VIBu' + b'UNuy+7HuCdnzbgAcfozclg1sv+aO8j4ceZLoAwpzF/wApdZibA+tLKBf7qjOWBM+Z+LELyWj' + b'Y8yhdlRDaf3+/uBxSeqDHW0WxgH7YqhSp6ZZ9+8of8hBVOE+DvTNfStZuHehDPxNQcEXN4lz' + b'ynDnxkXZ34G6fQ/Z+yFvjP+2LVse6w6fNzH/pvMwnT0CcoGKCRiHWgjoWcIO8Mu+8LHQOg4B' + b'f+T+gXNBg6FO5Kr9rpd9YVgInSfnML5LsWX+lEu+se/i/o2Aor9AntNHQSDXIr80eXT7qaHn' + b'FOQlLEDDL8DfyHv4PLbz0qHnDP0tiDE22rqDXGVnQdFbmIOf7xgmuAbE5MMRIw8A9ZaXp6Of' + b'WWzpnXO/bcXHvwVqiyem97mSaicUncQsbZup6/wk/MblPCdTYdUD1wfkBsFC1yH7N5NgkbXJ' + b'E2rqObwGuDHL+T10zJ+G34LUj6hWmLPw51C021m0Z0cGsbD/Dmb852DoHtjix6mx8VB5eSds' + b'VyjvWuRDiBa3XyEXuXvftpjGfL7e3kjgEgUfGeL+yknHQWkaeam/m1rRfteKYfrf19FhbMjC' + b'9Go6Dk7ec6lX9DCiwI3DXV6Yf9OfgMlTEc3Pwcp4DQCPwgu0hmwPCF4NRU4YAMrhevi49gmD' + b'bj8O1dzFu0L3QLJnNfAoepptTjCSHVUGRO285vrxsxYvHqCoeRkL8nWPSqCRRnCYOa+0+tBE' + b'okN5qpCtXnsQrHUKoxPA/DGRjj8Z6Vrxc4jxjKLIDSoVd6D6QIq8wqzrc1Tdt5VnerSkcukt' + b'6BFIaJP+BvdJckW1z+xPfzfSrY7IY0ccApC4cjA8rLu13uUbf/62bYtFm+20CbkLP4dm63u4' + b'Wx+LBQAiaL8KT/cYgvbLh6rIC/c19HtC1rxrNJfncUd8oFNetPDS7/ChJAXcv8Pmk9YRRgUS' + b'2Ac16IG170WEIKOf+kfx3R/a59DfEi7LKlsN5BBma15MINQrQ88hkcpS9p2JDvE6aor9kuxC' + b'JOwU0QIfA1tNGaDmQ6/8uH/L0hE2RC0GCGAL0NSZwdvLq7tezclJSPFoyhbeT0Nckj47sggm' + b'3Nxjuu69Dr+CP5dWtF8zHAIf+iQg/yugsyfjycjU2zHMfRRrhHIt4nevkmHOkpIN6PC0TE4o' + b'cMQeJoz713mN3mkf1h6Co9DQm0b8njjuC8l2lOceuJWryDF0YlXVo1smTFh4DpnbX8GbdHFp' + b'5dI7I07/VG0eUSKAzNwO2EH8tn/PIvl2sIfkIooCOxlqZZVLV6I1XmUG+y6GhbwFZ5lzOIIl' + b'QK3BvPMydPJZb9D17keKJWBlQV0F1FhTcj+RRZVZLG4WOZFBCN3Iiv05+uEXqW7OsR64kgku' + b'K3gMFOEKEVdCIx3+r4TUTsi56WfkNrkHyv7DEzPmrlk7xNbNrfvw78lBG3YfSK6L++5mUGj5' + b'EYUV8vMdSY2KawznbQAwFnyZgBv1twvz4n8IoopmrKMR5xoihwvwn4VF5yph/VHy/8+hAP+E' + b'CTcejyb0Id4FehW7CaSDklNSIaMyBOLhCEn4xReQz6uC6oeaSPvgbKtTI0/6R2w5eP95NPU6' + b'+l7UL/vfKcBPdxKPjTUIN2CX9dhH7P6IuOyIQwDOrPS5fmFHBa/glf5oUtZ1qyITX/T7nT8J' + b'S/0MhSkkccXNLIPTVNW9SLWMRQF3sBQq+jrQsgrf3PXFVR31QxeaOAvV1hbE9Dv7OLfsNbSX' + b'Y1zGc8jpJ7LIcAu2fkft0L+yiKkArpoucVLDrOcxg0bQ7Sbbl5Mup49Sr1/XdO9Pca67hY5+' + b'dbC3Gu9Xf98VFbwY5HV6szte/MYHLSCo1hss6jNYtclImcmOqO+sbuR+RIGP3OhIUBiAQxd8' + b'mFz5oGyU5fwRmvShxHMpSJgRw6bwezffRCzaorf4B2c8MUD9wazqTVhydDdczQ/Lq5Yc1MFK' + b'TIQ4Hv2WIVLayT7XbxrbfD4rRu/T3H5X0OUy3K4gmjxcOkEImF1Ig84TfR8R7niGY4IX7qmu' + b'HJy56GAPGspV2T0bJHM9JIGwXo3qkdYLhCLNJ6v9W3J9Qe68WRCgC3iOZaWlyysP1ueRfPwj' + b'vfqP44GE7SMUb4VtBf5IxloBrmGb2PY35ifMJuPHJaywi1hmx5B8hBWJyscyWliUm1mg/4A/' + b'fTOoG8Uu1Xsieq2v8wJHEY5MSG3fV8L1DBxPvs64DGJ5eoY6EA17c3Y6C8bufZaJPBlt8Oyh' + b'nonDXUdo7jSe7TVYVdE13IE83IuHHJUCJUifUVOMRzHEWZ8Su0CtI58q7u/zHOcNKOqG63n/' + b'fRRcgBCS8jsqivK6ibYZGw1guCwtEND1jg5Nb+8g/5FBLSE8fsWz+BCbo4m3rWpcim+UfOOE' + b'/cKCUweE63HdBvcKZsGI6OZZaDzZsXDr90HIny4dP/46ZfgMunLqviaeoCgcf4SId2NZxfKH' + b'9x0YYUMcvRoa6seT2iFwOIk98sffkKe5vZcw0qtQ7h0PwhFU+SJMxG9Lqscjqg3oMciYtJzQ' + b'jxtIRXpSWfVD740wnCP+0BGLAOZSeYh49idJyDwXc9tvAdrnWcpbqgieOdCsSq67vgTvDM1S' + b'z2ZhngHAHIPjSKIsVthOIXy1/MFZSI8B8CCAwkka30JR9PMD9Xko+wtz5hfCla6FPr9Kdt1B' + b'6bUOdH1+7o23ECP4exkU0MFpQkKdJuIG+gdZf7JLRBCOiTueY/8PnXSwvw7ggz36JuQZ7Scd' + b'b/dOKtSM1FS8iKnQAaahRpmq93Ranrpddty6DXbc++s0vanFRR0wjh/qshAfYXHrFU7CKVYk' + b'UYkC+OyW39IPH/nPXOObsJO6LDNHeofh5yKUeZLm8uGQYz9fOqP9WqW/yEb4+GF+a3CMnqFm' + b'S4n3cKnmGVD6axnguSBcSsIGMQvb/4fz0WPF5ftbmyQjFaFdW3nO10sr2+Dg9ldCH+bYPtHT' + b'5Q0dsU0mm9IRywHgsx0wsM1GFto7rLWVpma8gk/A3gMPfrE2Kbc6D4+AWcQQnIELiGiG81mK' + b'pNYW/V5oUbLA3nX72k8fyWpw4HsMHCnAxRQo+ANx9l8CYreGjwDMxI8I742LmYrnHY1zbNye' + b'KRSmXI34gpbfDvB84j9gQEelAjm6BopJE1wv5/dfhMMK7rxhNCEHDtBELRlITw80XfVZu2v2' + b'LJctacblkUN4ZuAqAVWRmlkF7j0twaTnXzQTVr3uhoKj39onTg+cP2hLlo4twPI7eUY6oRwo' + b'6Q3Eho9nIX2KA45AvVRipTOeTFU28uyvUxUZ5R1ghIwlXVIsUWQIsAi2HXR5mFfxgNa+ipB/' + b'HI46x3/UGH6AHsuLNg9m5HK4rDhY9jJTM3+mGW7CMsxrWQ9XwmGQvNYQEWM16+xJine9gpg5' + b'bN5Kh0P0x3+Xag8/MMzAeeVV+ytxB03Rp+DHEY0AZP6cxAt2zyz8/09D83Ihi+mEkMdWsIbD' + b'f0Y8f6q4PMux944037y82GBvzCTWITUMXFfJuSHOwHhubEXZ5auV1TAYB29iQkRBdyWKKfG9' + b'XRlJzXDSeVZTPZeKxxrLel9nDi3nFyt8YF+IwksgjOwcOOCAo/yWXf2vxwEwm8hDhwvY18dw' + b'G7D2AvSBxpvm6UYKZddgfPb13k+bnW6l+0iEIPDOJ/aDjX1jHnhI19vb3eT1Gu4WkfsESYkb' + b'srgXy2DDn/5NvhytqnOJPCpyhhqhlQs932CGo38fXRF6PKjmpCgEXZb7NMT77cWV41+MZMud' + b'Owz5w/v4Jrqhu8MIP/QGrD3cAaSrSsTmZsa0gnl4nrBpx9d/SBfOT8esaUZdAm9zK+tvFpr/' + b'x2wt+tZPq/NP5DOGZjtyzxG8vVhZrP0pv24aLD4FK5RriJvPhGWDWtqv4S22xFRcr0Yq9oZ7' + b'FKEKHt11JUxwNgt3r+0KPHeosqLj5x5UVqLAO1uAChl+M66uX9Rt/25qjkPirWzW+3ncl0UO' + b'RetvQhVZcPJ73z6OCtD0g2QIBKD6IYrIKqN/KCauvpAoIEfCjk/l+qQBaA73PvAtlL/zlBP7' + b'Gm9dKPV8dccPUQ4LHNOz1u03tY4u2H+UAj6vy0hAZ4ZHD4bNfjaDbx//t5f7M+79taZ3dLpH' + b'5gTEEmK/wbO0MT7eg5hIQY3OIIWmCwfjyDfAmSC6MCqEL2CCwr/ZEFQUgk850/kou4OKudKN' + b'+pVs6bblcl3E/ruYslhsMJhjza+UVi5DhDpww/mK1Gauu6QAijRnulW7mYHdT4LYlymwvHGo' + b'WBDZm3CgBFpdRRjwAtiSiTzROiwzd1IIVzw5Gfanv+1bkJ+2R5Fcem7FfSGq5+tY2mc58rwV' + b'LGH1vMmzvE4a5ven1XbW/KsceWR+JuQsPAcF0SthiiIcBIsCxZ0qK0wIPG6lsPOy6ax3uWpf' + b'i5xrLgnvj0AMrMzw3v5vepF9zjko0w4c0q5SyrCvIC9Q9z/f1K3oqBDwS28w256ancHE196w' + b'Yj4k6rYdT2gpQuTzqv6xY6yOk0+0O085iZAIEEYIThwkEPvuhr70+34nNczgxIcOa98oAQJV' + b'lCsAPUPFVLrvSAhAuDCEAGQ/JzhAw05xu9vXKSAfvm7fPrknSMIXwgUyuYpwQKFe0CfABXzo' + b'iuqcNZLoJmnUDd21Chw6xRkOCh/6uBnPw+UR4xy0KR6H0dHB2chA1zGGz4E0RoFs3me897dH' + b'B1bujvDMHHThp/THwIR/Sh+AYWsTchacgox3A+vqQnLejREAFBs6L3sjkLaac1aTQKO4uCYd' + b'BeJiZ7FJBBp0MHg4DkTUNZwDSf5H5FSBDJahkwDxYIpymujwQnI8C17CcQVLDJ5nYenZB1Xp' + b'v4blGXEOh4VjkIq90GOVMFzbwz7cTtVxzkKOHIBsCzl1ucy673/b7CvM9Thsv9wRCTzpxVWB' + b'lBUrXVBzl00p7VAOEXoVYCJrr5TG7S0sCDQumqf5czLdzrXSJ+gm7cFH+5JeWuW1JEfafo1d' + b'qt0BHK9ko1umHPhHuSHpyASVCLCL7gPwlueVQY7YRA2gkMWM4ihEJbLt3FPwAJp48TW8AtHv' + b'WEG+pCxDPAhsdPs6ThgJAcjtivIW5Ju2fi1vAMWv+ToK35eGDkNke7Mv4RhQ1aWg2Et5MVPR' + b'Gosp80Xe63JLjXn9P4HdH/rc8nuYFzvcaZ+OfeLOy5qfRj6u0xjxGTzeVKwAhGqygGxLHGpK' + b'WYjreGoCS1SxX/uhPV/B+ehvh/KEjslP6bmVpX4Z/SBHai+WZpb9QFk9WH8gIaiqGftL+szk' + b'I0DOPA9d/6H1zX5nQ8inMwbZwPTBuickF6rH9YAPUX8S/y/BMvs3Yf3bz5rjb7x1gXcfAINC' + b'kp95vi/liRUem3yEOCztf2H/HvQGRP2nBOu/c7vtzxzncTgBrnc1tQSz/+eHqt7Z5RreRKgG' + b'oZCiMMOkIhjM8TToBZJ7eQbUjg7g81wHQwAC/A5GDADgL8Da3zd0sHjeTdItyVdgUDhFr8Q4' + b'+svSyiVvDT3vQL+dWALcqUt3LcGZKNSKMm+cHHTpl8DIUYhFOY5XAXGwNzLcP7Ng/nooJt1w' + b'X5/W79Ci+7SOfsRxL9Ym5u7Ml5oB0KDTYMlPYLHmgd3jWWtcKWpxgMK2a0gzdnpx1bIa6W5C' + b'9qLj0UJfDRh2EY7+5LbyB7bL/kNtjtuoz/M0i+l0HHfeAPRR9HEz6OBwfTASIZAsPIcmD5wC' + b'3WMX3AORanAEDPlYOkhjwAPnyBYHAE6r7gffMfoK80LAC9sfvWmbP+Oue7kWfnn4Ww/qR5BA' + b'78RCf+13v+myRX8gt4ELGPOH5X4sA17bOxT3yOPYpDhW13CuyP6MRGR+cWXAzsgDyQ34w36+' + b'HAFc9gzTBPgdYQVPR02bgYh/R1nFsnuHOXPEXeIqDid4OpzI7p6A+w+1/QVqqc57IZzFz8Gt' + b'iRhXnmEtrCbu7wbWwnmMTTisLXw/gxLnhbgkz6YB56URb/cfcdB5Sf8RT3KQh5AiIp2dFNII' + b'KhegY/s161IESdabsJPGz1lw38rL++JohGfJ0Jsvx6A2dQDgclavsLWhJo45rHLSfFGZG74C' + b'awALCbU/jga23QUpnMdvcvIZ10nJ7Ul5C6YAybfTHzHoAgtDG/Qn3ETedpoY6gmFFRGAdGLs' + b'8kGcshkLXMfgLsTe78/ODNb8ZDG6qpDtDo9Ia/xPf25Ebd/hsSlFfqhN9QfshttuDnSccUqI' + b'kwABxH6wyZ9+z6/cTrrk/TsKQo1LQUE9cFl+8IwkE8GFycGuwLwD+yCFAzeAUor4bNpRPv7H' + b'+fnv6ZqZ/ghc21XglB+j6SuhuHg8HaGL4FWhgLGpBizqU94OyBFXA2mCQG1rEgj9C1gcJSYA' + b'qcGAQ3jwG2Lrxzb5AYhqgnCCIbzkkIAKxocDl/WMocau/09l8Z35GeEPjN5/R+vH6pVT025/' + b'2B/TdjO6gmNCwAQtcIJKIAWqlYHUmhXSGgsvro1nQf0wtHDC8wS/wBWyuPsz6sgqZ2UBsyx8' + b'VmU3199UWvXQ48K2IhP/DdqeyjnlIJJ9wB66Jtyn800fA/iY3lAokj9PcuYRdAQAjOEsEMCQ' + b'hnzsz8yybS/ALyY/4N1TUW/4yiqJnj504Hd6BbDi33lf6Tj1ZHl4B4z7srI1Ky7O0ru6QTAD' + b'43POJx6CWdjpzCNiCxclCLAyn4LIeNZ++HS2nSuG/OEJFcnV57qkILd+XGn5izdhabnJIn86' + b'2aG+Qg1V4Xzoi7Fwd2fiIfGhfhmM/HOazCyJQ8SHEo0/Sj8+9kw5xDv0wkwlSDJCEBW4wyWa' + b'iRcsrefasAdoqI//zr//NQgg/Hq37L63G6p8DbLm+ZBxj6IF92qeqJVy3G+1VrjVxPegQKfI' + b'okZpjItr8GbAG3dioBzVsGaSq0YINHyDeOuoBm61aNIkFVjQ+fa24w24syDjC+OQKB9lBWaB' + b'AC4nhPQZZc6d+mAX2MWaMldqgtJWFAk07GtFubsySKH5NXZI+K8oA/P2HYzcABP501L3gYKA' + b'na+mHt28X7M9kPDDaeAQb129qnf1mGZsDJCC7BITo5mx5Dft7KSnfgbF6VOGLZSUhCpERiJp' + b'MB/GknLHJ4ND4efau5cT5zhX8Owid/U/J88+Z7WWXZ3t8ijmQyQHWYDdvqGkZNn358yZ84W6' + b'urxsL9nH4LfgswzYLUkSxMSzLT5FzqYeDFKKC3cik3gA161wc/ND3fPuDPvvctMZM5qbP9yQ' + b'+GfOpwgNlyIDkBTkiVLKp4UG9d/9978OAcjrLq5YJp56+7z1wkugsnJF+6SsRVeS0O8qNPSZ' + b'0ItVATO41uvyfJ4llQjw/7206oEN4fMP9C1pyqiT9RgLEqeRwD0O8CtLbWW1YkzM/mK27TKm' + b'Qa52llQqGwZcXFcM6s6v3RQHvrkEtBOHNAB1Nfen/v1XWFGSmby/AV4a1BqkAyE+vCYsjNrX' + b'p2t9fsWMQ2kuHbhwX4zyhrj5Qd1x0EmJrl6IDsKARJsAIcrUxaH5GfQ4q50rZV6soPc4aDnm' + b'uOY3y1ev9lcjeGNdIdFHYArz9T38/ztWr156D4ab8kG3G+YHxT7mMuYit+V6x9C7v+YytWJI' + b'PFYg+209pkNs9UzvChMt/zeM3rh3mZlp4Og1O6oeYpxHm8zAwMI5Oh/7zYB4gGlW9AvInnAE' + b'gKJlYERX7kf23MvqF6oLN+l475CcQEEjLqG8Vjd75kHRLrMs/wOuqI6vhE1VhXnzz4CKPkZX' + b'Ys6DfVZWqG7r1sGVdfYNQ8XXIVU39VEgIywC6o/gfi9AQbbvBNnAAmDvue4as/VzF7gUCUZG' + b'V5fw99eDY5c+5BrefDfo8sE/eBorNsaovvsnipGEF6EIJSbeTd9dTMxAPWbEAQ5A5GxQTDHn' + b'zMMm30EWxPYpNf49B/K7cKoRW8of4YgKBXOAXFci48wPO27loStB6bqCAxOx2dxB/xVoIuNM' + b'xfKiJsB9G4dhLgoNWDgP+3RY/c+KpMIvGfk3SyuW/mLwAx39dbAZ+K/kAA42KeHjMMTnA3yn' + b'7PMkU7UEFt13RWkQbiEMKiIzy5plCZUheljtxk79v+6ojjvDwB86X/sqbCgZcMXjRqWqkHYd' + b'bjSCEF4JHR/4C0DkoXlbAtc9msWOId4ajcpx4ITwFrd2t7SKgBt6lwwhOHY0OAjLITcJn3Yo' + b'35jxlWBKChGDsVhTQ1drvX4LjiL0gBGdAHA8sJqDau4JMiSTedjTuSnH+02lynHEijgztIm2' + b'9Euq5il0grLYBTL7HJ5HD7HpUGMyQG/NzZ13iUfxLEWx+GPQLbEFnOWoTXgMeZKIp5FXgHjG' + b'nLNbRV9qW18tTJm/pKQpskxZ6N5H/x54Bo4igAPPDXCuVUBcWmBNRwFg/Dc6Cdb9Kou/ztIQ' + b'RHF7ibwcAhm0LHc34ettpZUPl0Uek21Yhhj6698NWAMV+MS2Dz3POVe12pF114JU0lBxSyWi' + b'0+hBstkObujCvPV1orDDAAGFxB7hz83TgqNTTM9eCgWJLeFQG0kOuo+datlUCHUUiqwO9+5G' + b'y3Ei2s+PQIBSvB6tDZBfntnVSVXFA0Zqwi20OdDaPxamE68BicocaJXMGUrAi5WARo5+KwZn' + b'CKoeOdYaqaXEg8B10TTysfMyrsYVfGEIAwD/jCM2S+/75yoyDIzlv2XrKAIY4U1TQGL9xLyb' + b'PsPims/KG8WCfxhPsudGuGTEQzCr76HxPluUUYIOEClegoY5CsahF8L6j2XJN8BZtLK85f9U' + b'zhkvzHNkk4Adb02t7t7TZAH02L9Q3MVHudrPPbtv9MOPwbYT/nsIjfgAxRw1ymg//TSnD+cS' + b'hhm7ZZut+ftUaz8/AM6gCCmPspFnwfxnUm48OIXU2Xtqh0vBZauPAPGXg0yTpG9EGRGnip37' + b'RPzpF4cOGJgTPhXHnrXx0dYufJDJyhv8QHHpv/9vst+H5+Gf/T6kxfHP3uTo9aEZCAUTaV8C' + b'9ify+UDrDTy1Y+ejzZHzE1KUeb6DGLEIvlukDd6R7YH9R6U/GPjD14keYO/11/hbPneBzym6' + b'xRWq4bfG3Xt/MGbDBq/tw4gwQkMxJhBpNdy6MLjPB0D6oLBh1vfvtLy1dQeIDITlUDX8H8QR' + b'SIp3kK9Pscv5/T2i6/5v6C3zqbOHuHAtsnwcFP7/yqqWrhp6ztHfH+8MHEUAH+98j3i3wqz5' + b'Z1Cb4jeA3hQo5F2IG0+jc4gjLRlKMO1HcA7UBBisBJQOhXqLK2/NTxejvY/Fs4md8HZ6e6cx' + b'9ndLzNgNGym6QZi+iAOirAg3BGgJIoK6m3uvvdpou/BsMhGBcATPgDMSXlrtH7NkuTgTRVwU' + b'utjhYmyrBmedRaRb6cVMh++86sVc/0tk+BMY/xJLNb83cs6G8ECOfn9SMzCg1v2kRvAfel8J' + b'O25ruwzSunp4sh3x3BJjkJo09X8oXrFEgI+aIjcaauBpilAuA9Cu54PLqp2PvDs8KUc+J7WX' + b'mO+M7tnTHe29o6OL9mqdx89Szbi4oGfvXlvrJGYnGIBWO0FARBZ4rZ6pRcbum+fbXSfN9u4D' + b'fvyH3I3NwbF/eFBT+wI44+0H/4zeeSwfSlLSqLsu46SLMcivIK/Z/Qg3MTjc3IoO5YLUhGOL' + b'm9o2VEc87gE3pVRXQ+d6tBhH28c1A8O92Y/r3v+x98nLu+kkFFj3QWDxgrF+BsDhLYdyDmcZ' + b'3PZxlue7L4BVDZ24yxuDkf8uEotejvvqa7jxfkmCUNJIb5YU65tPH9ORnVMwdJ0M9SZR6AHw' + b'iajDYeN3z/9CoP3CM3yOSVBOlTcMQOudvYa3stp2NzZSY9VvBeMTXYGsDNWfmQHs8k8ME9Lg' + b'HDRqdY+759dm9NbtB3MllqCfN+Ej9qDQKyESYHlxzZIG6aYgf8H1CAi/QndByTL7a6rRg+4k' + b'mgDEPs3yOTkbcVVwq17ch5gR8IV9LqNcRPq3LW6f97Zt237fJf0cbf/eGTiKAP7F84sXm2tX' + b'bd7rKLtOddh1sprihSZOutLgCMRDRwIK8CIM+c0T866h3bd+5Wr3fH/b3tDCF32BYrrOR1OY' + b'AhBLRCOKSHXiUCVgqNv+v+KVQIqkPTdcG2w//0yvYxcI01PROwq/J9/SBDkwGkdcCCMKtAx6' + b'S4cx9vcPWjEbNnlG9iRk6ahKM/38BmVgs6qrbX1B9fWafgQgt5iQfdN03PeWcXwGN2rk5twd' + b'64kEC4k3NQ/Oac4a5PmolYBbNrFLlimu1MuWSh9H2793Bo5aAf7V87uaFZ3Xb5NnbQNbXXAB' + b'cAMafv2hQCKH5kncvKTQtJQ+bIF1ZVXL3hw0lICSDuv9S4AmHSrrgO2ACXHQmQM/YNXxm9XT' + b'lj+q+mrq/M1XflY3kuPdYhp0AD1M5QeuCCEEOARBBkQQBtIeeUL11NQeBPilA57MVpMB2jvR' + b'VALNWjdp2q/kgMMByBlSOr2oaME5Rrd1KmY8SawBeGse8oi5wQDoArFu0FB4TgfwvyDIDSQn' + b'aOKoaCoT8zG0oxzAv2GSC3IXnUJI6mLAIhZC/4uSqmWDHGPllhPzbyY9ufU9Nht0LXAfLu1t' + b'sh952hEPhE1GVM8irC0FIPPApX8L2Jh9UCQgnQCbYhkIjhlttJ99htl53Gw9kDaaXJbAX+Qb' + b'B+i17h7TV1FlJb72ph3zwTqXkyL84LkAZaRynwZQ09cxInRTz7EL43y5jyQr+O5Tk1jG79d0' + b'P/48Lu0kshrcxNhLk/3x31xbf99AdCU9hVKr99xLf6eBAN42td5vHw3UkRf572+Ry+Hff7f/' + b'ujvMhZINlzZ6kbswz3yHBKIkO3Wi1KTKEDIvLj8I/EyT+BnzbQf4E4RbRjdvpsMvUONe+PVD' + b'axjm8LQnn158nImsb/nHZWDrT4BH0C18/l2e3U2Kt6ZadTfsIRdxkNoAsAKRVoKD3waNol4j' + b'+AZxRvIOSOogSV7Sz9oj28P6IOskOZSdSDyQwpdLq5b/briuJaf/6kOoFzDctUf3fbQZOCoC' + b'fLR5O8SrhgN+ubQVaT2xDv4/hABU7VUAux7YRkFImCF+rfwXY57wxKl8JIkJDjQqCODQm2P2' + b'oxKnAHtUcYkSva0YDUQYgQCSQsRxX3Q+hxs5KMPA/g9V344/fgu/+uicBwix7/Tu/OKY3OVk' + b'EMVkkJ0ffn+Q30Pk0xwF/sjZ+Hi2j3IAH88873eXzMxbknzuvnNxa+3ZUdVB6OpgZCEprOJ9' + b'1qUAVDoxsPGwBNcBUbkCdUdGc5ZOK3+XgEmaMWE2BQzz75Fp0sPjLMj44jjFa5wFY1BJGq+3' + b'2X+kPER4iP+130cRwBH66gtyFhxHMpLnUSMmCovNMPlIggyREI6cBmUnFFg4F62HzEq3UPb8' + b'qSNndEdHcrAZcLSwBzvp6PGPfwZKqzrwiAnOUu3glKDtl7TW58FMvwnAffyDGeaOKCsh/Np6' + b'koBMkzH6LXsaWXpXDnPq0V1H8AwcRQBH7MtZYfp8XbupFXapR/F+kcLE24l+nQci2BWy3X1y' + b'AwfwubndjifDA1TxOt9WvYu8qhk/OPT5kxvf0Tsf+gwcRQCHPlcf+5lGT9z1uu6+h3x3Xwuq' + b'2m0lNUurUBB+A/gTv3socEiCC3/LAAe25dWGjg98D+wTrXyoDf/d73rAWeFr5H6yzcdWJUrx' + b'UvFQ1DXXL0ihdjvJPW7t7/Do16doBuSNHm1H6gyQUlwMApL4Au35BROzbzxdZGx2rQfQ63EP' + b'XiIiAbp3/O9VkINahr5gqQAq6XN/wr4tKOXZZ/06JDpYlNZSXgMhtIFInqRTLA02FZh1nJRs' + b'EnOoVPq1twPpkp//Ua7HxGc/zBgkak9yI7wK4P//9s5mtYkoDMNzZmJCLBoQ2rWr4tZr6KZ3' + b'4NYrEHTlpbgQwW0pLdidi7ZoWsEuKgaUlihdVMyiTemPYBoz4/PVpbS70lk8gWEyZ344eYbz' + b'zeSc97zfAb3981iW4j+UnpKaDanCmBzj2VpdMVqvywkYAC5nc+N7JvnUIhKAR8j4DhHHPcR5' + b'dGn2/uMHNLxofD+R066zjnp2CQgDxEIDGulqlFWp+EDZN9x0j9h+z8Js3XyVQLJL+QkRYpN1' + b'JPb4yGg9PYupx3WQLRNcsnRKr95b9uMEmm8REHp8H7AvvAuGkUizLCZzjaI5fZHcqCqf7/T/' + b'FztFxfzUm4ABoMb3J7zqd/qvcLRN6/863RKmJMVdnsIh6mUMHg0+GyyMECam1NDEU4YrT0iQ' + b'Y8IB/QUl2Xhjvj7beT4O//4QILc4NwTC3H/ODXPP8BSKi1XZD8rOOCg8C3HsKTsEiDZlzERM' + b'LS7TjBwLrVS8npTnC0z7XR6VzeUaY7RqVxBQCHQFnNrsKtpPyj/jrzTh4Z172fbZcfWOvwGd' + b'zqjRPb1dPUNev4F5J/kMUvv31Gi7/at4kRq3PuXlCPfdYsgExF0Cx2I+nnzH1XyLZt/CYoiy' + b'7A3zEL4QNFb4rTE+P4NAf40ogr9/2mPpYrq9h+n5Me8Z54SKHudcPDQ+91/uczxvJ34kIAEJ' + b'SEACEpCABCQgAQlIQAISkIAEJCABCUhAAhKQgAQkIAEJSEACEpCABCQgAQlIQAISkIAEJCAB' + b'CUhAAhKQgAQkIAEJSEACEpCABCQgAQlI4BoI/AVulBvcrMXaOAAAAABJRU5ErkJggg==') diff --git a/images/icon-256.png b/images/icon-256.png new file mode 100644 index 0000000000000000000000000000000000000000..718dd9358d5c014b0431fc0f8a4963fb1a1c4888 GIT binary patch literal 92119 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

l`6yTkk2rH95e~s0@vzU% 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

1vq%^;r=4= zzvJbhwPp#!?cYgz3Wy@@&s`KbPptBt=U(vxAhZ1E*ZBnA`2L0+$|x+uiABnCCC1pt zq(#endjo6pMxib5dz8K>5@y=k-Cc^rRA1ZZ1Jv#4U~s4s0alj~Q=z?v_1x-i2M^Fe zFC{kz9!fB9s&_xy$;zp))O8k+Wlhbl8wWxn&vPuIu3dQEfU%U8Fg|Nine4RKEL z8Qz$I-;y$~I;GpKozU;YYp$F-_u4t5TzW`{3r6dZ>iJ*4dDGV0el~yhN7vKo-$t2y zCJcv3Fff9{TBmT+88d5wtFAsHSyfr;KXBg*y3ow3VV92ZQwpiT>cnn8YxV>tV8QI< z>M9ad8ny2TckXwHTb1-zlT|22!Y~9d!kSQ;MuRP5Fw9nNv_l_}tA>*?KtQ6&<1D{3 zZNNSflioB&F|_Fd18IKRvZh?lYOKngYhRh$0vKiXKoboiWHXLL`)Xb2ui1i`kz9yy z|ELV4UV?9e1+`&x;Ysl#un>VXAlY33#-kKqJAr&F9fwc+oCM}T)r%AXlUKKQg93y; zKv)AdV`9cHo>Ct$_Kc{WfgT{-wA*%8t=eHNSTKdUN{kXW*TURi?c@aOKzEDoL}es9 zDK8G3*Xol{67wvAF$|#^kTeGFW);`B#lsBgDoBD@hHbCz=0nNck0Cn=C7OejN< z?>IAOO}5K0Sf`QG#$pW6#8XPJrY3y5NklKDf4+X{1tv@&&NFUy0mErSK?`zU^HV^M zZ572?YkFm`K{FDtsU`~)fK*musm#I=sQ`;%Vwr*P&ap|Z6V-ULiyVG3grx8Ny=B$D zhi9@4Y5e2RX7X~<&ubwnDCZq##VyiX$8doSFwe!}?5(lVA&8kUTZPF6WhDgqXlfTM zGxhg|SNqL&p?0Rkdr1JScusT@1xVsdmw-+IgqU-wGKD0Iutw+r$j(FV;!Y9QT^#l{ zflyoyC~1j-CYNGS1;w1z+lQK-|F|tGN`}@+b28DdpD(j}dtKTanY3jsols@`3I?$r z7@5XSZ6huBvSnS?yjhu)09<>!-C#>&B53V#+{xv>y{A1E@Ts>V&LKbQ=FtcI%?UsK7 zkogRz!B-elHm1WnU8)|kGa$=NnObQBB!N4@*cXmmNq6pSMx+GAf!UDX^UJ?;LUpNK zS}Mi!*y__|a`jUHQ*BkRb^4qp>%0XGq&M@l1+e?m+9gvoGe>G;{+KEn+anLpFpAUf z{R3Pd(Z379t9vst)KGrH*2c6-`|*xmE0#(+@o^;%dQyueXSs_0gO-|$2)z{|(tfWf z0-#D>UDMBY05;9$hHAjY}|(76HJEljOOsT{WRNY;DU)#l=;VaR*Rvmk0%kKxYUJnxrwn#IN05 zCFdZ{=LpE)^LapVf=xameSoC`(LY=|EA7mg)1VOjC}1&3C58-ujhV z`{J9XyO(^mHoWzZ6*ji~;7jjnwiivyS^#{=^hihojfUVn^m1vmU~1MbDGv83IQD(KfuTM3f6%`TEjz0_6W`Rb3HV7 z?q4O7eo*PzX)LfqXO$*TH;9pNa!v@Lr5MUT^qK>`H=Z2U`gJ?O17v?%QbM#^H}hHI zBl+8tap$d<9BZvzy;BrmOoKDhlLZ|$ScqTnyZSNvA!?6w@!*9A_@eevkKAIEL%^)n zH(FQzF_Hpy-AS7ezYF&M`P2B`BOlW>EOfR^@wKZVnp~Ga1W+_3Y1&BfR?H_JJ7o!b zYBf~P!Vh>PD#v<|PGI}CEGgoYgq2;0d>|mSlP8x)b;Qf^T&K8V5>WDGR<;jx;Lx>C zIVx^H{GvjJqS(sq6RZ?c{E{ghhS28QDLqUzdKYDs%94iR*$qYZjh9CDr!Q@_uK&-; z&TpP7&t83cXX4j?TOYP`x>g!mv3gr7#7>`J`=;3a@Tqmh)}<%**fphI+~Ce?BQIqG+A{>0kh}USPgp{2X7Q$FK&Gu5d4jEn}u(_-wHRNE-hkZ>piGK0f^x+l$chL ztLGpH-+s>&D^53Xm=^1MVc}3~dk~jYWP}ApNuy22bJy~Feeycy;t90xmZN(qxGX_W zIfj)=z5b|03tv70DjCf5Yy%uph1=_2*)23?0dU&Im6HJnZAbUuShJ=$anODIO}oGc zT@yuy3q-< zu?K?VA7-84z8A^>bG7Yx(>TSsFWfO9{+)ZP!pW6hIHNlF|J=O?U>w(VE_|nMZ&>u+ z2!H@duvbwOB}!D6ELqL66%|WyToeC(c~;^)CvhCV#EFx*$5pbVSk3ApDT-o~NJ^x@ z4w5JYK%)2UyVKuy1^@|CY_c88`7gQH-PxHtGk5Mi{d~u&DNwE2vNY#$8v0A``GkgI zMO|5!7F;gWdcftAgh1!LFg?If2r%>x>}2M9e}(#3-$MNHEo|Y9gO2|*`ds?Ye^oAm zqI|Wg>QgTfV%B*F?E*jik0Joo)z`tMTe8N~v^zOn$fbO5sFxT{E8g!g3*m8I#9N{R z&lC@tya4#+921t)@VdJZl19V9@Azas%$(-NNb{N|^)3Kn4D~ zDJcNKDg4!I=ddHqJxGYB*xK{A^GyJ<2~eX6&r%ZxE?WF1>gx#s#2H;GE1`RZq@wmA zaEHbMSEEOWn1Cr21?+SDPJgCn0G`#+gjPkj58zCi@c3j82Cj+5YN|o6WpRurb`o5& zp8*QXwuwyre)jvsp&%v*zXv>+nU^16o8M@)`jAjiURfyk3#!?8ce8yycuK|Pvn2J{ z2?Z1Y^92|2_VGM6mUgg)f^pl{LRUs^S1Kk$m8Fr}C;a_$*~Sz3s&>oDsLX&ZLE=1N z9FLBR+Fw7FW3Jolk!O~0>R0Z;l!V$w5MKZe;RePew*9CnuG{MdPYEKhz;e;3fBJ{{ zR$Y;5T{|zOuAG@-h$jHxs6jU5(*rU6Mrp7no5>+9aO40p4}YHt3;u?&lDpY;tF}2_ zX^JRs9?q(8aL%i->r+$vf0*|_Y65V@6<3IZC#s5cj-QRF@x_M1t^wU&kX!8+t>UDS zFcXk5f#4M7d9~Rk*iqlple{ss_Cz}e90hHM@0d@+g7aY(|LMWC*n7K~R@iI6RfY1S=YGbg`#Sp*Cgdamz&jG;A^KAnm=s1zoge^bA9B9$ zIL<_QZ`-Xfbsc!u;X{}6K|5^uHUAe z`@2J|b->3$9u0996B*YkJc%?MC`is)`epgkKgw6Xc;k4cCSS90rS^6>tRKG-Lh_F6 zs4L~Pzqrf6hkd+AZh)JX1D+j09PK@Z@{?Co^`_-Am^u!Hd~d zF7}nL-k!PY^7$+&CHSxH`xZMqeoR0pxtU(?iy2W+c!GI@*$mHKfOm>BBLLRzls&|A z&YnaY&RYVCTGzF6#rA zc3K4>_z5y&Q=`cXZf>)-i7glZi^+)qbX(lFYXZ;;AeKaG#Mxr|#d|yV9^?j`9so4C z7lC%-qdm+j2mlOhcA(QV=5|JZv=DQB8PXpc5U;t)~li%f$3(}m(ik^nUan8x8Ar~H}! zEHFJz%Fu_SBh88MBye-9IQ8?lJ9yM@01^-xIq1QVThcWC>rG9+{R+teG-1>Un7UJr z&7UDyND4|3l3Y!x#F{%rwyVt{Y~0T|U^75WAoiV@kQ8u$hfK8;1osnf8*IaYg!-L7 z84^7bvL6q8hjG1I7(aZJ&8^hL((H_NVnk}3TYi6Vf7fGh$$YqWp_%#NdiovqrbVBO zm~%i$Z-|ar*MMp+K$xvF->)%fDHLl?hR{!LR+48yT|_Di=aJl&Xo&pKw_KT2J45LlfJ5L>a>%nj$C~?4cR*4@ zKS0|yzqOy;dH3ajadNR_I*o-()5xAo-0G`laa-OxLJVSR^EuA}gljx|=;mbkpX8D@ zhzYI|ssORh$>Si-Qzea zgza_M9C!K=ii*-;s0)H^9L4F7mxGLA=ObWrDTUC(4@@q?>3yB+GZ_VYx+65;+>F{B z{q47piP4ckBaodZoAuMB^`S6ggl5(vm!-lhLD^lC-9Foc<1uOkepla`bT@ zR^!GW2fPB0d-233~31!MK)_4|CG#&Sjd z{B>ipnHmCKd^2NnA7%cwAE5wgLOnhZE=-C>IZn9$)JZS#!$(E{5U}HNiQYMw;nzk- z&9yMd&qLaiGvLwLjKYjQw?fwn0vSO|#|4%5!%HU_@exH{KfHES=XFXt8(Nb76rF zv4B&xIbc=JM2Q^YpO{}@)sqcfQ{s;vK^Ss2xa29qFtx*Z-l-oX__%;aXG;O#{&umh z-}Uy%nnggM)n8z&?Ym%+$FN*zy`$k;RSmF)7KeBr1T;a9&S-*dg$K`^*ypUjwl&_D zW*%8XS$9MVO{zg>?RM%b5#iyX1mD*iwdOA@VY_#9u=lpVYhH8PEkd|r9_!h^5#E3} zqA7VcyMmWzR|^V4k=?)}_)rZR9X$u*=H;?}=Nd_b6Gb3th933szzAz;?PH~-xvacg za24kuw;2M_RDX)x?BSL($S8eotWDHtoK8; z6`$_H^**+7znlN`l@U{h@6r-c?;NTCOC4jE*ZszP=G|-$h{Y@%`^QZH8X6wT(lY!K zgomvKO4AjHcCSYb4aw)ySv3qUv&&VjB3DO21^90;yb(Aifm{J}iArl?#jca$-A+{^mckF#IzeV?^m(!K^Rm_1h51IIEI?yMP`H*JC1{WJCP}DASW< z?U7=A$+DmTE@j{ERL>M50{HRF4_{Kb2dlhPilEx+^Q@I`qrV7U=J;q_Wn-gJNFC#F zVK;TSSl~v0)Y|}5^@BQgpi;ha*4pi#=w}vJGqoDvD~1*uWCqSUVT4sPi^JHJ6bw^ z`il$qc;>HX&d4)=`<=cul;5AP^U__o)_bAZE+kWUIH+0;#i|kZnd!a99Sk|uV!&fr zLANdr4yEkCnhA(*l!QWP=gE-(OS=Ru>zahX=j)Pn+?7hdEm^(?Vjdw!S7P7G(p?Wk zMIjHt<{5bZ_c+ta4mTIN3u0fVY^GoHI*krMceTPMm;@VeSe9cpK<1&786%?Ln46aU zUm4NkKM65&NCbN5#V6d^gF;rNS6|u19(eF7rJ}OXF*Y`iY{7|of#iZj%mDx3!>jq$ zmVO;BD?|>TIqz(R6qBCxHN(wdl7w!v*`wPUYX#$E%+tRuZCa~A z$RMNu`0`PH3=7)Xa#Boh*{8XY12FCCaBH|XT#vDOfvDWHLJ~YKjz{hSfB3k<4Ua^b z%N$}V;Ejl`kxCQiip+;@4Oz9t3l{5e5juB)T z4hj2#YXe}Bzpksh@8x61es$U+eWA|r+wYwK*kXQ~{V5pm!+4w(G^jz3kytw~E-a{4 zHdt$3s9D@H|%W%>t5+_PR;Aq&93T|rPZsUZTj0Mrs8?c-=#Y`-4*-Rpbd`?DA zzu{HY{SHH#n~{YIEtU9rQ1ILv<>Y!r_FS7Z^bR>~3=1yz9WkEsn#t75KGA!B#88hp z6lI&+r4Nfv@10R3Z0n}pFB(#%=8_vSO1jr;;|g75ygu-=U955}DgX2*>r&tN$NR0q zf_$#C>-3YQ%)yeft58OlNNoK;n1v8$^>JZwA2XCN4J9nwJr z5@C$(?er*nj(gcx;3jOSVpn7sdDu%(V5{F$f0XRK6=f8$a{smQg z?lv_3F+?}qjnK;wb0DO`V`!AZ(bH$!RJGUM_44BliY0jwNQJcM+B{9JEHIJK;k5JY zBV$q9GJ9e)sO*aeE&p9HU~nTp41>ry0g*M%Yg(Iwb1Z}yhY-xnPM2w=V5n_E0ljP# zaG0a8+@r>tGU97Pa1LOrxLlFA5D z=8|vs)Q*G?*x512W;PV))zu{;O@NZZV?xViayWd2yJ@v^c5gr@cx}UCHnF1NAS4VD1Jo z@YKDWaR!p{b5_CzP&TnS(K2BOB$ps=VsMn#U*7IOC@|RqfHI8G*oJ}#D-5PtQ82~a zh`u90ZL)tv5tuWEaTrBWSAueP$&`2pj*8Hxs!-c)N zmCLsZ3c-n!m@(Oi2zZh$vMq0@@4Z$}s5o zPxW3YW?)gZ%Bspk%op%cK^HbW9AW)^!>p^bhbid{>rdsTPmKAj&wk7ymFM$RQJB2A z#*bfC`KC6j#U+S$9BcnMg->2m3wvg9swv&Qq$V9$gXE&Ju*RdF0FMRFhhQtC`{4zH zYigIZ11G%>z>U8#GQJPlS(ny+FA_ja%_G^suKHIzu}{IEhsZkKlxh^k%r-S64nx=C zjF4)VtQTJMJG|G%t-y^5HNC}SNyjWyTG27&(7>TU^$bAl9}R#zxUCaI0p9YF4;=HJ z++(29RS3Ocieql((PQE)QxT_BjhPA&n*ct z^6jvp_lmOXs+3!6aVY9Bnb!_FMGyi`Zp@^_0?l$*@2R|^oYpV*B5cK*A5l4Wfj9L zjFRRq3Cw}#ap$(AjGI1-PNPE`28=rR?`)V|AIi=kQ{jur<%)@q;1=Nb*$cp?UE~G8 z(?&whgxw>{t$-jz?O+{p6Ou$gg_Z0@3gWQ6EzgE^C&}PKjl2PUJrSX^W7Mdr&6VqC zX%l`aRacEqkII)&au0&RRM7986|?_q3h-Jf4*vQx&E|x>)ewpf|ByR<8DM= zLsbFcq3aB}6x%+N1>>dLNhUx6uE!+q15ztVV$?SXVSYh2D=IC~jXvIdcpm410g!4P zl0;!VzCks295!NZ2lv3y_8)g$=w8nL&6npKN)1@uO&!jXhan1}Y}(`i+b72Ec=zSA z%Gzq4dnXEu3tx109~b(5*37!lu4n!h41S`_CC|J*FMGi?kb?dm5B|obwdqur+tdf( zx5t$jH6y&U4(qgck4uo&BspijqKmnPnQC$gnVoLw>beZKxK80t42kB({Z4b+(J~)^9J^$%=>OmssOBN*nprznOvNufa}Y16oC(#0`IbnsxV_qk z{j7B`z*>j=C~M{ccm~g1wLoQ!l?tbgWu{30_=q%E;>`b@62R28pZ6U>6)dz6E4^xB z7eWLYL-ATH5*ou4vge-Nf)Z+|ltA}L+`crNMCKjR<*>s<96m8vQUffT>wBF#%DL%~ z77W+{P{ajeaw$>(%7v4pVa#qU6oWyRzIkgmhjd`8zMMpK6Zrv!Oa!F3nvU7_0HVz( zyeWnQ%y^?o<~xTyTmdAL*+mgngOFfy#g;=V%SVZMx*ocI;^yQ5Aa#`@c*z7q?%lHT zB34mZLP$k?Q8trFW+0gZ>)&`{gQjoXW16zSJ<`(gvp3E=mgo7QzrV@M3e8)oLFv8i zs*vdp6(MA@kn#RjLrVZPg^y&X z4D~C81)=*dyL@&Y89p{{+yl2r!aCR`I8s1DHHr*%vCow5S_7jO=0b3vOL=|0NA%wt zwc`Jj%~b|WZpE^sg%nBs7jFjGF>q%vNUF7Ai~q26T8@T{uIz9*jBZhg{#%ymxhFBv4Vm38RjgM8G0Ws!m!~9SSX40+ z9bzd`gw}a2v08Np|7t`{Jnc`%eiU+n2mrmoP|Pua%F)yNEgBj8e*NT5d1gb2Qr}SI zqzX6F8$}2rPeAzcS8rrL`tFN+WRoJ;~ zMS1Flt?iEawSu1O)usHID_FQ=+YV`;$#I@-_9iMXV=_Rcl$qo?@n*YES?c zwjZeke_iNk&Z0()%i{>ceCbsZmgr!@q4VKV3uA^FhRgdgZ| zY6DJe+X1e?W5A;r+z3&o6`v=D5DS@meybAzn~;6*GX>9-g;Q*9$rx3@o#3k2Mydfc zDBJEqaS%gsC+q=EJ1NKy?n|}+@{$n!I$xvTRK)4RjchhH76OwY#P;kNFnR}6wyc5N zC=7`4@ik9{csLx3j07*vy{ze{5e?wI zmJR}7s)wEOM8uUXQ*rS7LvG{^KBVig>hsP;8JZHjkOl8Z4Xikj1PE&e#|uKX&Zpn< zs95l#kOQd!c_HaHy_RDsu%A>;h4jja#TwE#I9@DQE!Xn2p>;@>5kbfZy09Y9XwTyxa8o9qsRgdk&WHQ)nhn0Dd#jXVY!1QzJS3EQnFA}a7h>GspQ zJL4mX`U+B^Wx#L=$WT1-7@Z8e;H3BuZ=m(+4u{!4#?!Fa+ljL;sTi?i9xAdEcJbDk z`B63#wtzak*X2c7Jq(4Evp=VJoXxX|g^9QbD*bg~N=IS2gZ*(XfXJBInR!xH$fdsi zMz2n>&LfU6{;(c};SRt_4b@gk(i z|I^y>vmbw$#ZT99Nd%y*?9&ypll>sSHt9 z@9P$iw6Td4oFFZB%vwqI+=PW#u_aWmTR;*@5S3#O=v0P*|KL%$r}%FI`?MTy}Y_Fl$bUn4RMn zE?ZeA6cz@p*Vi2r(1oz3E@pE=yDv;&f&?dyF8JVrJKx%{_cNF_7{iU?80shp4+7zH zUrM8XX{65A&_9bFg4+UfTL)bDG}?)ncJ7^nk_o>%5ZKWTb|q_j7^SjFye69fHQH|5 z0HF8VHUJm^DI(ATm4JRDkW|7+q&NcH!o?cbaeR~&7YEE)a|+~mT+O_(ZCIRFhZy^K zyTHpH<}avX!QwjR%d2E#Cl3RMA08Goa@Ub|PhcfsL|Wz|_$de3JK^jQz+QtaFUQ65 z!vg1{O75T;7)l%EhprJuKMTmm%6EUG@pCIO>3c6vxUvGgt1>5Lb`A;Lc+#;tJ3M!A zYhX#R?W`!orV_iN3JG_B@}huluf3h(r^X z4-jmk6Kk1gj=2>oz%6;>P_N8OFz!W;IE5-0S`YySK@d?>FaXhnC<`MF-0f7`F-iD5 zlgsKc`Rf{cgv#s$urN$JR2JeO&@IT^16#uYfc;|vr?tbX-|9fUDN#>7>*La!Jxtl| zVdj{?BQAg`?>V{5b}w)A3!>U83+h29Z}y8Uv&~~E@41?+~3~E-he;kCM2UFf=HkS*e^^*=*eJB`T0SvwWUwr z-5eLLtxq6cV1i>!91GEy@B!eb=PwZ8PTZcP1tJ*4{Y4ZHxrB9u7dt1^RBk==0=N;wb~A zS7RM0^h(^C7Toz7jXh#7FlNK7s3d4DT2jIvI5?yqIFbT7kZ2_bn)ys3Y6l3(Za*9A z+|RTOAv#SGBXpbqSV;l}`2ZP5ec8!A!-Hd_-Z7^Ox%m^1(!K;LY>HDFFTSm*kFD2% zC78;5Y)RT<=&GDsyNu0TawYFd>@^Q}NgTqVFAoPBw~R&h_nz~RSM;0_@>Tl(6PyGM(I1t@ct=J=hz$`RIlZpb=$5I*&kpbZ~) z8e0KT)N{}+F8Ej!8O^+&T?Xv@s34blEwipf6_p8(^HFj<;|oud*i6S_a#<0ch=5?F zFxvqjfXF}|>IU44NUw^(k%YJ)D+9s}u4KhQG&*G77!oI5y(kJzwd2p4zn3(E=h=x^ z1VBRs5CMJh(rVN1cR`0Yp#M8zIhK$xLT)4?XLQ#eY@{^PZ!*lsh*&V**wn^17H7DI zLQG6Dj8UUEQU%a2h3lTTVLuUZ0|KJ?B>45ucg|DCV}Al3QFwFZX}pElfUZ83Evy6KAM4}?Ti-{R@Gc|^MbZD651v#B zsv{7M#8I|A4i|3{7tgUk(1+(iJOT>`D+eDf)Du8-pJr}u(yUvTB$cZhGaft=i3q-o z8U>4P`*R>Zn|!*jNjuW(_25>D$}1N=OV<6mz3ItPKC|ud~_cNm)#c%2p=E3#%R;);)-r8t!!Pv#*JA2RHh~StY7jk*5nt ziR5&JGmf=7MbGM_c5-J>C<_1Te7iPlNbLMJ=W;N=lA7e*8FVKHQ8fvl2)L z7Pn!2Gpo%_bIU8>gPtM)bio(~3!%EU6hOHK=i>*okVp={)P`#pP@tZ&4u5N-Ar@jJ z&Y7?6pd7Z-&x;5-c{{q1_fL5cKB$0`kIcS0viws#0I7Xs93Dep&_LWpK{|Gz5C!a< z?(N(+L_~mMFAg85N+s zUXoVZcSF4G4>BQtF+Z&3^Y0wYh^P_ES))wy!5uUZbsBwR9y2dwm<~}VgBq*MPFj() zTN{kZ6oB`EMn-9Rrc`4-T%u_6u1_lno=}pba41NKKGZBph5v`_aCQeDeEuKk^Xv_D ztbN!e97{xCXfP@QBvhZ%SYiZ1F45=lK@xDVU?9K(em~g(?8w3C=h?AiCp&ud7$#nb zxtxCe)mQg(^NN%FWmSnY2>>00aiL}>IKt>ml^y6b)V_sXlr}&3sh=VxP7h;Ed@#+h*BbXm8*hWU;u2HXTH<;ef z=^j7$X@aP79Fm3j@v*c}ROC+|=}7UrkLUpN;Pv8MflMLT4Hq+cZT82h&*+jantVgJ zUNf37jU!#A_VP|$|F1U@+1FyovrCoCBWn{W|JZ_$jme>61nMI)+7pBgKPFnDWQy(Y z`h-Ipf^y}OggI+XTol0R-}z+@*SXgtNHF#-tBwod0F3a&iQ%ZME>hXa{Vr=9VmTFt z@MSspfBc6(6Tk4KTexr`)3OIGJ&g}?D4}E$qyYZ%_ ztocy4l}Mrz?io|_{DVt?pQICFy^<=A05A}Hdql8UrX-JZ9BxYj!*Oxf&UQ0^r2m2< zKLUnaP|YXm3iy0ph?VAt>s~v+Ev`(e%gPht84>`U z5BJZzk@9*WW8gWi>kqMs^5I|EDO;m4klV8eHZ3;N^Aj-c#WJ$}B6lDq0g(hiu0MLP z_Fw!VqVZuHorA_d8qM%yqe*ZL#wSvixcivFA4O&!%9a~goM1aZi-8T8r~y4&2xY+X zx2#CgG7hvG+6&uM{RV z1NMfYW81i<7L$Xw((U$E|0)(ca!L6B)BF5=e+F&4a8r`(XfWSMWEHE9gX?l6ohqMp zBV0r0t*lZ-i}XsGq4Um>E(iDg*NV+y7~N=T!Znyy2jDsJz|wD#eo7f{D4m5Eoa+~- z(m#ADCcqr+@^=cIh+H;47k>7lR8WJ$S|tG)FAOf<6f z;y1!lebp@aoB#Jd=5#pNqkr|E#;n_0w6=EwR?i_9LKV-?=1B6O2(T3^X0f%`&1Xdw zZq_vTwB9vz)Ew{fTDWJv`+!FR0YdJ{x%-ijy)ix(m;d=6Uoj5uKcPJI$QrS@I1fRT zNRUx7r$9w%l_V1h=%6U~h0n*^VrEfM97Qlq*kWL)IM*t`B>%m*^)5UWKK!p33McUJ ztBXymr5g<39PEbH^b`!&hd;rkA3^9rXfU+GMU3kpnt744odp4a>V+}}d@^mxBxF&bntcz`?qf90OIr@P(s!*$kZ0LG$<$R*B2s*`&;CjU zOG?X&kfYFP#T9RbTMU)qhhtOwepK(%ZspvUP*||AQUjRD@m*es;GB_)ilWnFSSueK zQ8F>X%&t&`8JESi_8neXOYuC^gABAFb)?7Tstrek+2sITq+)JpG(6Cej2CwyLnr|H z4oXqGGHJfQZH(nF=n(3&uZ0zyaZf(B9XbH=1;!n0|EnP>GJud>U}26%91;vj#DCGJ zWz=64)8^h3QR5?$o?W7_+A9*~j>mH(Llp$#?r*Oj;yQPQxc6W2@Kwci(qm72nX1TG zfA*PwH?l677wfsz#oitNF#B^WB=~>pS4RyZf*E8kpUvqedcusu;st}@j~?k2_v~)h!(q4X4@v^8&Zo{y zm4@1ncObc>6Y0_L->1ALoM^`0_dA3~Zb+F$azdQoj8nZ%yo*_=dH3I(9CYRxFYt{X zv`wh+4w`kmTQGJWmTYnR0!RHpf1&}0G=P^4E6pRzSBNDnVJvQOk%Yy^)0T(`MgjAY zY=Sm@J#%?aTrS<_SVCa4%2XXyf+-;AR3m2PaC%w!{HxH32&Ce}-1|)@tp140!3*Zg zaP4)T+W8~;aF$T^!K*-Bci@;UlFV$f4y};mnL8I!vi@aZ(7EDg5zW9;ce- zc`Qb~q%p;!gAPel3~6>TGW&poVAEUtB}(7YBWov`-T%* z)I7!z8E0i72H?o15Z`yyC6+HpD1ls+-TsX}v!EueQk;p)Z)!JvtzU;{f_3ikT0?CP z$E<5{^cEjm`xgV&bzkXIbE=Z51ve%2@4S|X9nHLR&Cn0-{olI!32 zdfjn>bBnaUcM_eAh=i646v||05K@DYT{PG{mgys4yy=6LISu_67a{JyS?19 zd&c==y9E6=NB-K}*z~OG0G{#}w;6i1@{+d!D%S5B?=!5crkFr+)R0^UGg+ z!bFB(8slT^-P;7u!3YizkY=h`Ma4O4SJxPK+02X?WQo&}fYZCgEL2hS!vIv6-DozS z>vgf&d{&=l^f56c)Au;@^JL#T3Xo)uk1!Q3#7yTXGkOzjcBM{r|2}N>wKMzwWBvvc zQ0D-2QKT`PahaF|f`k|in+cMwmUh6>C!%0+H=}wLrB8mO?IJdSzvUgy?z+Bamod^Q zJAltAgy4?_3>&woY?M(tCxUfZH!{}{Bh4G_aFZh6Ge0|RXH&U6WZ@>RI^oX+Gc|jG z0nl(w)Ea1Yvid8dO7o_mT(vA|HeMHJgM(=!8WFhRj*xKtU9Sla&yAdr0SM0cq2mr6 z#&AnQbRV{xqHMCJm$LM>9Ucel6J~a~${*Y6vo`-IkDh{X&%boD-Oq+I!#$ko^LXSa zcZ9XXUgPr11-|)BpZdwlTBlB0e;>QgPJPv?$o$>B<7r_}eJ4Wl?DuP(i3M9jnmvum%H%PP@TT(5)D zn9pux)FTOj6v~_&1h#OB)!RMl_}6c(GdHf^uLr|PKAbIbLxU=enhsq+u<}6PF#oX| zl7^`e%{#|R#3l=9!I`cx+Z({U0Rs;9W!npgixDfs`6yV3kR)uk9$ngWDn;E=-`GxZ z1r#)7B7cB9475LGAKJl2L|CRDJ9#}uQbDvKh)@EqHPWRf_ft{PsG!a*RuviA?jt}W zJ_naPdyM|4eJAt6FxCd8a$q=4sR2Y0yrDd-0n#rKHJwUWu@o>pC61B=N=-Gf9GhRZ zfBcC4T!a8L5V9vKD~7GXqm@ii-B znZp|cV%5@wRd;#Z)4VZY?0q@JA_xJ-LNjESVIJS@*y9ASG7DM_rW}~dEblLz9x^^vMtPwbUK9Ur3q8^$f^OXHFp5f1-vOx zgd>cI4n#KUn|_$hEx+EU&t04+eC5lp8NEjxwED!x^q8|Z82r9A(2{u!q5-K}pM6vM6 z)kFPFHVWi%qU_?%W~hCGRLAqoF`3%$fBHM!G2)I)@IKgUPTwOjzO3RI_U!>xhz<1g zv+iMugF8}1@|Saofvf~ zyN~-3(wi~e4g=r^#27f{L&hHxH;lo!S4ZIj8XJ2?(7Z@09QR(Uldr!vDiqWx+*?1$ zLw+_7JA!H)*%ahK3@BHCyY|ZitmlxMA8d14Kp4^vZwyM2UYRYvYgC(mO9aRs78fek ztdhAYtEZ7Xp|BzGQ9^MI>Y+6&D=AeASwBZA>`2#cR#Iir3zHxrg7nZ7+BCw+0a4 zNuEw_jBC0wg{`D%5IMq|CwN2&Eo1t?HWG%xAxNz1+}HB)-=)XmqxZ zA_yo2#xapfd)`Mzi}idj97GG*FwkPytdrOZ%yv>Sy9? z6i!STg+>IvGuV1*e+?YoqS9sdleQnVy)%V(Qy|v&w-@M-KJF9Jz&pUTUsUCsIMW~B zUwc`fUfX8~V&sx`$(Fuk21?8!eu}Q17C+g)>aVy1wx?XCMEcm%kH2E>Xy%25i;E2k z{T?2QtC86L#~J&(kL-poLIB{l3p8Ho@k%!|%yw`)4m<|HTT#|_I6z5QnUE*Sm*DvHQNy=A-K zUAr=_Uv}RJ_wLhSiUklH9t2`)oB&k;T0JVZ^vQZorK-YssjvC`pi6RE+@Wzv0<`B1|&968e66rRq zsz8%(T9g9HkB8rN)S)8`m=y-b!JF!eXTpC^DzvK#()AMf-T23%*H1~0Ro zk8KAGi!)XvP$n9sfeTfhxOIF;5~`NQ0m;Vr1M7l%Ccz8nTXc9$273eZ1Di03yK%eH_E(v1@@7t{$cuUbLn zBEvegFV64Wu?sNc1FX0tEdJxSZs$9=M)i|FFJ^nYJvP1`aoOLg(ZVIsj9yc-`BFQa zMhxg9u;}b-8j4HoyIbLf`}q7W_VIaL?DqL5SS~UYDP)-%&F!Gq zK!Cw%Hz2IlERb8qoZcXd_8wsyUfgINACkD*+5&d<)k{bp!oil1$qZa{4caI9Z~Ai) z8vro|E8uhrR$D6ycQiWX#Y^1$uHDRm>e}jU%ah!vu82#e(0|u8dH5q;l78#5q*0u$ zOP4ofq_oPbFTCd!P}@(PU#TEgiV5>7GDd5ck4F#@gT5{Ka`m*1!n*JX$V10nT(C&9 zNE%2*c%k-+q?G~kPxXqpiG?aa*SD^Kt)OyIQh4%9rB>Ozv>6+OmjU(K;^U%TcSTHS zecQ(&RzZemKsmG?p`@FA;HVx)er?()sLKdry^?-x3o;!3ypMDG4FSYKN7ypOsj5&% z2u+3C_Ol#EZe_+?`iU`Z!@m>=U3=X+AbTVolE|VvMx8vO9iRFCO0~utBa{^>jQ7aK zXt&JiAX-R*LR4f@1;LO2G!E(ybR)mcD@Z^({+?F~7O3ixtv)u|k_{cx*t-{bqF8ym*? z`<5Y(K92&1kW&CjhbH9jND?kO&FpoLy-2^GK=CF0muCn2Tjjg|%#Xt&CNV3D2{JStS-S8{rwcsNi|g>-c@_Kns^Rd1dnOUV$p9|u$$&t%VbSAXz77kv@||J;ui6#5pdSXq_azNJ?vD3bWfDhJov zVTnldgcQhW%jy(i(F}z~(pw$m$NG4n_af|Zt;(AO;lHCabD`FQC0x}N5&j`uwV7AQ>& z==q|t@8v8JM8k3g4XgjClZWe(n|Wo7A8L0RCl9z0zcZowgo-pB#LghYVQ;hB8SR%$ zLALnDYhyfJH&hyP?v03x7?cHEhq3ssG0qc$mt&oacX`v?%=${WR~&eW{EEwF@TC>` z`Wt(7^YJY_xBnzSQlM`j;|xhPfYgGRN`|P@3>rUUTAls6&`hI!NhlyGkJc(l8uTJ( z0&&ZPDj=IrW=$u(?3F`7_Ji#?><3%JY*&ZNDk{s@A9-Yz@$jEsDO6SGA@4%BtK|>@ zptR2ITaVe7Lf7}ZG<((H4=qR%!ATFNyPR6K7wVsm1x=#j9c)?UFk4wY#0o)0md8o|}>jf#9>R z)1l>nN@6})*;qsr8?p1rZ2hLM^@%&5a#|(xQic}htQ=o<$e-7v#th(;GJCl;+xeOXf3 z_e#(X6?Q?)qu*g`Q0lIT3(cGSycQRwws*Xl_$Z}&SR|2g5Si zCez+5!_~3dBSX|rultvLebJp`!tzg!@*sFR#UyO{ey;PG|5ci~{J~)>uQp{JJ;ckM zot7HdUCEt(nKsHu;HWxcrFo1SwPE;NJ!d|fto9^L2Mhv?Zndr zv;^>GpTnFvJI}c0+BpnWkOZ&SDNt1;g=`CxjdCbv)Z_~Vg(0K2XLJf8XzJ%P-f6KB z5)>`8vt=5au;CYyKu{zD0Ha8;o&*k|Y(c6!Kv3(1FiZ=W_M<-Rzv!2;NeSD(DmTIA z18s=Pu#x06r28Glx%x5MTOeiq2H4&fT|hO`O31@Oih6WKjCHVZ^hXUKP9z;|Hp>^w$AaHuTFlwdJ++CTXFMF{``TL%*G?G6GQ z;`$rwotdj>5IDqOGtlN-7u678#C0Eb3&jm7 z3-$&R8HJWFThrhraD?j88Ul{YIB*6C7r}md_%qt&a3W9%iJ+YE#=qzDh+IT+$;7jy zeIPAJ2VM`D!F=5Tl|yZ~I!Y@KhD@jQ($|ZvLfmU^RmMocz7ZjjVMeWNCVYC5vsBV`lH67L*4rReZB0}wgL8d6Z9q|N_Zrd zVl}vsYa$YlKso6^L_@OzL`4FD%q9+WrIcVq1u|l3fpwuSU;7X+`jW^~P&pVY5d#1P z7iG?^V8F?;a@}TWgV!o63$yZy91f^QTwzfNQ0PEu!a^tDjB_<$A#%viH@i=a*im=q z+J`tUAp#RT7-0YqSgOt4@lIn(i;g55U_#mO>9j9#Z6XYGEZrj|6A^x2FI>_TqmltJ zAPI(2j{()iDu69P3xDdE>DMu_@Cof#L=>i*xshZwg%@z@H}r*C75D>q3531hxG06_ z_lyjEmX*v}&bsz)W`+hE0WSUZy*_JjOcVa>&#omvPhdnOSYK~HuwN+eh?yQw@*_2h zT$BL7)_H^;=+jT^v#zqiFqS828t$m`J7c|8jzae`7>7PPGA)@Xqgw0y;sdKJ?uEj^8WTRd$ba!&2 znOHOc>qGeKnwSYUp9KS-0HYhQ1ev%HX~)rFLBj$fii{+sfVkk+aV0(~!XW21a;g;0 zpKHLVILs%p|1B)l~7|mR0h50pvxRN;pA`sMmKY388V2I0#_V2 z)ZsE;_?u#aA`q|n;-LQ4k8%}+IdfQ)JUk617ArgsJO=}xLb(bJYa(1ht-_xBYBAp@ zxSV8+q||2eYV(TJDcU@=72B3vk{L$luY3oG!9sTVqwv2cI~xutW-+1 zB9WvyI+`@&v5Yx19OwJ`qGl5Ds_;FFsJ3j4fR?uOW~_J{3Ug5Lf=NCE+%BZ40XHw? zu`1?yxg|LsGaN=>Q`n2@$3Eo8yMedo<^WhK5^RtvIhZK} zJ`5xSA`%2BViOeXPsGAL&^~seM_Q4%H(&uc@j?V2bRN3ysfAAjg9yn$L^Pj&&j(3^ zQ$MyOo+%3_eYrE1viUbX!p3^qSo^!LQCPS2`ulG4{T7tS`t%y}tB>A^?l{)ge%uBd znH&POxtZXUKDu^s0wAzxM`X5yWS$`H~XDCo(yy4jcFZRSP0~4qU1El=dZTy^7F9RTi5=@Am4M? zsYd!`DX%tdruKM67~nMM-r&$Yto;G=2wZFw!AR;vRqvtdBCCky zUiU8rRyrzJ$%x=~dMw*Zpk*ZP*01*(Sw))Ts?QEV0$~;ckZ7V=6dj3TCDQEcqGoYD z>Jb1Inz9lr7bVoATLNqYU={9JIFq9S`@QUxN) z9*lz+;CBuo#$0Z$pU=+^*pYxVsqxRA;RHEGzE%=t75MvslmLJPtlo+F56+6B9S%uw zIz^7~?lEHt)tDmJaW06@IF4RnltRx6g=mtqfuSKbIywd}dG5t}#?(e%bj-OLiR&ey zbn@!DKGEaQfFE)0{myml^lkQa;##LxmB2w_z{00SaZ1zKEs+k2k|Z&o7CsR*JT05! zPha?SEP^3z6!v#po#qA@g^~ZC`OMmJ4pn-5)ywbTXJ7p(#Iz(>^IK0sy|t`Y_IS)K z`vvZyPhY8h?d$hSbdIs{2*Sh&@z1rwWiG$yrWmjZO_~?bQc|+pf7qg6m z8~i-^J%X0$O7cUrHTRd#qegK(s9T%JNCG=l@E;w zkU*4U+XKSo4-K2^|2ZFN;T+d+RYZeI;z~sY!S3iuLsMvGGU*pp`kWC|j81Su ztf2h-JV+tArzR?$n+U+g8l3|kKx1?yj@XAYF_=gP2k@tLZGE>3(5zIB>tfxV_jkHK zDlj`yiJAJDq;B>R6Zc63jb23XsGb1bCw-@O_QIdo2)omWsPAcWY6xaCZin})u26A- z*h;gm{S2G24jep)XQ3n0 zb4*DjGzkjCfZhK`_~)WtfWh$_)7hceb)a5VAHQpfdE0GQ@ataP&u`pt&@8VE^D9?X zNpt2E8W5SZNW?VLaK-zOrxOSY@Lx-CVToKa#R<(Fg4opNFj2u&D}{x94HAM@)Mtbf zT@G{Gt3il|w!y||2kH>qYZUv>oB=~0?r=JDs}&ub5-vVJ09*lBuKWN1KmbWZK~#B- zf@v1sHpZG>$TGs^8HoKNzv%XH0jNJlY*;jw-ZN%FoHpj)9OY+R9w%;XB1y-w@3o-X zd)UKW{lx(hu>$6JFCa@W*|3mRZ9&}K95L69zjR^-WP+cel-D~@)Xr5%vg@N1gB}h zd*MoqA=eKJV$RwqatGWDfkhTVon?4KjE1XYCcFj$*)LL2fGc9v6qmYKO-+qGO>mgK zSRr}?mOd<~j0)FQA`D~&=gv0L-*r-Ib zPgW?4WrxEycc(!rq zdKVEK3Ya<72<{Cf!MWPJD01U+_y~&) z9A~?q|5t0<+b!lZJF~dMohJX_gRAww{rgXe4phFN{*D|u%DQ`dtdpJNsi&XXC&Kj& zACdVCQi9)^e!f5S=Zg{m#?L?r;m{C)g zC(daslpE(23AJ?voX6vah^g2js~fPuFcd;65XrJDwDoY}o)(FNHQB^7FjqFD`C^~R z4)5@?-J1d;xypihnqGTlob@-mt>G@G4AEV!y*w@k3UmdF-vsyvU(^6f1AVV#c3Os* zZw<6L^miW16|k5@Z^*DntVh5Ozu{jCjM6zN8ES%x&|(e|d?H+g8lvwcN?}Gn>Mj4L zAL1JdI_&juC9~3I?dpV(U9Jg8E@Hh1+!^U|ij|8K){GT#aRB-M2<8#2y&h@2m-0Lr5946U8`gR13qej+?aBmyVxfeVQK^|K?R4A zt?#IlB}OD*D@qoCRr#Jn9t*BQieiMaVX=y8FMQ~AlaqB~iVy*TY)?8k>;Z8ASVmbA z+?r5@sL{kG&PFd8Af&XAiL;X`;hucCfN)FDWJEZ~SVPB9zjRLGSn+s*_4W@yikL9! z(HbE&Bod9Hf^)8sg3`T3G9jlo;?WBzxeVYj=hOSA z??3gKu9F&FH!b*Z7}5|`GCr$ORGxu*pm=K+;HryeE@cg??__yZbMR~rkS0h`s)&+C zk`7$K(+{UJz+EV0`%DMoS?n4B(1I}bn7mq=4Y%)M+g^Lkd~#jH+OXHd$6%!X!WVBa zAN}jQPc8ng6DQd2_xG!BZ#|y=&2tCjOiFj4h=+!tsQ)`2-Pbk!e1GWAmp}j*xI!bI zyYb1Ql7PhVX)Y@($gaC?DObyDb`+q z&m2KRy7B(=S(HeGI$(k@_vUddFpItSbe09HJ`XSwJ&81dxi^hj4n*-)FHMSD|1(b~ z1KhluBYGw#8g;AU0(5@k-Tw+h{N_c{*DwF{u+g&B&yWFVAwmy10TMriaAn{eq7Wlz zb?){#VE7}WBrBblGAS+rwGp@*AMFP`x*;_ECPXXIL|~7EBql?LSAwD(VISaN$B=TX zR26mwHUu!#^7$#f?+FTDY{3=`{g&O`j)J z20|Z7B$6zO{YS^fkd8cxs<$K1S%G|s{cU11dBUml(bwspr>o0UB2PvhenHKAHtWiJ*xc(LVCC~x15SOM9p3V5*4-Vk4tKj01hyq}Ai2WP0k-nN zMvH!`ZwxmKiYSDf)XmqoMa-wS$^VbN^8l=>yc_-*cV#CeArL|~2@nKixCic8wN=zQ zDgt7)wf)*^$J>P+Z?)RmVTTB~>MC#1YOMpcC@K!NK**ku0NMNAd&c+spPNf=LI_}6 z#g+$d?zv|?=Q+=L{(GtAyEHXFe~j|;dv3IExba-@Zs<8{>T2x2KKqZ}N0z>4t$VL7 zDknFE47HYq4yKj@l0Rwc+$_4HPplmh0!T_ewV5Iw7eN#OO_o~Jp8CZpp2Q&r__BIElEhN zHN^81!6%79Y?Omq5ULNbD=E1F_0>P5ndNW9`mq07X@z}(+O09#JC7vmJ(X_FAJjF1 zf&!O(f0rhTHvmwZa$dWB+}sw0`cVZ5t&J5iK%KK_kA`@m zlfS@h+!3X5KhgYaDOrA3&Bhq}gsWTB^eH_SeQ3Lj6SUD|ZOYAhmF( z23Dcq!X5PV^g6&TRs<0l9O{k!Ky(Pu0kCx9<9cz3ry z`0QWa_y6|3m$V(lyL{Nw2SK=qUwDrzXH9ItiE01z;L=wJ=)}y2lf8pbJPMWs#F`M$ z3u`a?1u;mRy%hP7bn622qqB>YiKl*6nSTB}Wx@#;D~V&Wm9E{D_8WhBSb2Qu3TxH- zeg66uUw1avsG`gOwY8npUvk_1nur2oeiX+jJY4N{6&~x)Z$v5EcE+faipF(cef4Sf zPyctGYufZ&2c~2^C8ed-vIk%2d1TppF3YezpZ~%P`?!;`%=gyTxy_*YYDwM0kM4J) zk9o%-Api+hNKKjHYH8}dIBjg4k)9r}*VXTG7S`yrRGd`ulnXC9PVMOM>(4*CQC<6X zh1t^`2#!jQwi6Pgv@v57)S@Y4mHYxqr;12qOSr13B#sK{36hd@3P`F{57OKuX@twb zrLqSaC?r9ajA%^(AZ++p1cLVae;(z~CVSCkZAv1^OxLeWaBgU7Dh8l}d>+c*yyX5v^wUHfE;O_n69 zeoGA5jC^k7el=}^->g|5;}w@+kbsCW=Ikq4_2z1iAT4#y&3mkA7q)9Wla+H^k1Dzj z`c|pEpx^*ymVMx3-h*myuiwg_kY!M&io%QifHWMb>R&*S2qAKN==zF0HgtRFxx@Vy zYADoLO8KnMpSNE4$4);SYu|B&hI(RQUvz4`MYIVXO+)6>0eZ~17*=eQe|FVw zm-SY$&w6&PSN)*OqfD4I-nyMauiv=+O3ztm&Gf{?`Wyt;i)Cirh7E{3FZ8ZlvBj62 zldR4E;t6V2_9%PxYh`9d87!nrd4MWGlv4g=n={};8A49Z!Zhl0zc)HHCiCXoPByU@ zyTm^r5oObi=~I>T^s!Dib#;4{zrXN-^34CeZP(ZDF{VsQH)kK8rDcpy)V)4xyueF! zb#$XSZdUf}-AmOKlvuE90_)^UP?|`CwRg9nw6zi+OXXAfCkspfo$Nn>Gj7?VAoB+c zPVUfO`+b@y=>lXcQr}yV?Cz%Gb}*>f6q`^_DcFODm_Z(SuQFkDr(+kE7c8boaTKZA z8>^J;j8~d^Fz0zOlVOY@99X;fTe}R2%6s`YW9=@g9eYUgkacEHV9vt5u9xpiGvG4R zNoRGMFWf!WBMCq+xV_Q;=CV{b+(WSL!zfqnrf9_zV^jRZ?Vb6#7Guh}9oCcI$kcg6 zlwaH*0tK}XBobNp{Ex?Zrd~uEH6jV=&np0b%Jt2-78};HcaHO*kQc`?7i(N}0d_oP zuP03&XC8M#o^s68Y;835e*lYxD>Azj6=k-DuHr*^xg(q-NI_Z%&_zcOlDR{>aT21U zDFslh-Hq)gRNmgYrB<>n>wC$9jFvrA@;Rb^G55(3$0qdRhKma>-}`I*vDt%6l5oWF zQgh2upwLI;v*G{Xa0PM6W0f)a)0A;!-W{DiiB#rs&fTb+XK&wJY`y>1I_2%RwyDKs zt>T;&IB}9;9#;@_C&gNzWT(8BbG|%f=-GHaSq@mBIqbR6jdPyK15 z+1k=g2`f>8n&*^MJoNg&m7mPkpurz(2nBfy?=^$=HzpsG8o2tp89FaXm$X@;gvrUy zQl=D5a^zI$hoXhbtFLTSo_u1pvh~9%laOL_`iu-~>hyG70$TuTRS-xg4lT{doUO>4 zB*)`QS;&-z?y+!yG0BSuGH4^)O)n@yv&^|aX|Q^!efs9IWVN~0rxV48=a8yTPHWe4 zC^y!NpL%^;jMC5%E88d(wcX`+tE4crUN0SO zr%v$)>OPEd$5=tv*;95Yjjhqj#@6KE^}njt$Sr7)55SmoMrSm-1b=KQPB{5~^@*=$ zY8TwzU?z+W1b32~VB4xhjie(QDam?|y|mTyfB!RH;vC$9Fht3vqe}9{TP6ui5HnCR zMWKJf!AU}wS>!eeN(?_b3de6X;tdIaiy4q+$0tOaIXS7;WCCo8ri@cFGLtoAVNLQ4 z3g0B9P$CgRB=8L22qAf#%*qcf{?N7{T<0bX7sO)oj%`E(ySvM8c6RovI2xJFd%IMC z+^(zHtJc&sYt4H*h-{N;&16k+dRYkOnjRT3cwlMtmmZi{%*5P*gThAcX17Hs{6O5)f8V!@)7*7hEyw76E?y0yyQ zu)dO_D%DD3W2=dCrkR;)2WJ%;_SCGPJ3h+v0^CkbKbGyleQ}5C^6U0qoG7dJP_Lko zb+kt#?g4XYqR%RtGKRpW0`;Vmr>I3m`I^@gqV~>s5IV}r>H>d#_APVu>zh?-6Y4!= zubp#NfpzKUrs&mGt^P-rzN=>Cj54b#TB2~6Y9?>c38kgWD?`_Ra(^S1*TDyom$z^x zx{o(m5YZDSrv!BprR-u=4dkRzh|+FoR`s2&DB;>YRwLh? zTuX^jHO?DU1sRNq?{lKS#6#?FTgP)BU73{Lu1uwBG3Pi%DObFoX`lI}y#XQ^_2++* zVUn*P8jBo0JxY4#itZ~j2$2Ev&M`iUtwOFomVhM8B0yUI22=0 zEK-}fEXXkptjpRLGoFX}69kB#fX#xmdwcwLXJ?<)Mv{-_<_?==6=WsqP@z~L=WeyV z9rH$yUn5DXO4VXG68V6XX(EG%EC>Sw6;4YQm$>Ruq}Q2ay!#xAFGxUGe)%9B*xhE7 z)zGZ#jU7JW*uV+iU{ahJB!bkKniYt_@19ayQsEp;J#`qsLAIJa&F)arm5Q29rLwA7 zZ)m_O(a~$6tFn?}?O@JW#h8+5s<~K&lH;i!jX^|kr%-li7C!tMIsY|#cN@-3L@zcp zkwDs$k z4DT~NFpdBAt;0e9bLK2|HPqBS&)YsEu4P?J+)U}y341{p{u-Y!Ig zb`(|ZXtO0#u5AaEx>~5e5ZTR8w7|Euw#- zJ9-81)gH0~LFL7lUz}C|ZW*bp*^rDc_J97%o)I5GE|W0f(Q#CJrT}O%ar2~BbVM%! zcnQ>z0Gb|u$X~y?$7gr-;bZ~NGCI)=6cNW!kP*;E1GJdsTzlGerM5}8>xoZjCOK>m zBA5gr_4FFTpCIn3=IBJr$Vjp5tkEQ0p)5Qu=Q=pi$zdiq+^46MdN>xQ8 z)`Puprrn@9+fErBV--#sYacUptWbHpC^fsTwk`PL--_*BJKJ0rTs&EuG&#+@|GqcX z&JM!^a=)jfV(B+WoXC&q;K*-tm_Zce-Sk;5S_yUD12%U1qV%M5&oA_!cuEf8w5lcr zG(>|e)FGa-SAqnxsBb40fyh?8y;gbd*>{zfURr1GhE+>Rjkc!E$grmzGnS;7F%G$s z1#N=1#k?g*Ky2NjvBonQjzN&8P#_kiu&lg_fZs;+un{XvsFta8v|%#r6*m*h92H|) zS!qE#kC5H;QKp(0146J(jq=gz-VR0GLu_}uKg!Ne^IMt8efp-FC}m3x_IapHw_i8g zyTzSYk?g~EF3L!pgNSC3W$VcHBr*wFSRevTHD04`OO*GbZ#AkVZ^W8gUPyAQME^3* z!=CHN`T8i^As`m9L%594cc`C`cp%&G1kU`0*nYPE1)~(ddx_AKMgmzUbXI`h!6`Bp z=Sb*A;3$83Qm}7)imCe0!t+{PZQWRA0DLGkh(d6Y3ZPpiAm6)flF=jHIp#b<(&Bft81>u>3W

*Z%y(roOk{tcZdjf}zceODmSY=uE>W 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 Date: Sun, 10 Jul 2022 14:25:04 -0400 Subject: [PATCH 7/7] Update Windows build configuration --- build-pyinstaller-bootloader.ps1 | 6 ++++++ build.bat | 7 ++++--- update_pyinstaller.sh | 2 +- 3 files changed, 11 insertions(+), 4 deletions(-) create mode 100644 build-pyinstaller-bootloader.ps1 diff --git a/build-pyinstaller-bootloader.ps1 b/build-pyinstaller-bootloader.ps1 new file mode 100644 index 0000000..504fb24 --- /dev/null +++ b/build-pyinstaller-bootloader.ps1 @@ -0,0 +1,6 @@ +. .\venv64\Scripts\activate.ps1 +cd .\pyinstaller\bootloader +python.exe ./waf distclean all +cd .. +python.exe setup.py install +cd .. diff --git a/build.bat b/build.bat index 22ba090..9a8412d 100755 --- a/build.bat +++ b/build.bat @@ -16,11 +16,12 @@ REM Delete any previous versions del "dist\BrewFlasher-1.3.exe" del "dist\BrewFlasher-1.3 x64.exe" REM Make sure packages for the 64 bit version are up-to-date -C:\Users\%USERNAME%\AppData\Local\Programs\Python\Python39\Scripts\pip.exe" install --upgrade -r requirements.txt +REM "Scripts\pip.exe" install --upgrade -r requirements.txt REM And then, run pyinstaller -"C:\Users\%USERNAME%\AppData\Local\Programs\Python\Python39\Scripts\pyinstaller.exe" --log-level=DEBUG --noconfirm build-on-win.spec +REM "C:\Users\%USERNAME%\AppData\Local\Programs\Python\Python39\Scripts\pyinstaller.exe" --log-level=DEBUG --noconfirm build-on-win.spec +".\venv64\Scripts\pyinstaller.exe" --log-level=DEBUG --noconfirm build-on-win.spec REM Rename the file to x64 -move "dist\BrewFlasher-1.0.exe" "dist\BrewFlasher-1.0 x64.exe" +move "dist\BrewFlasher-1.3.exe" "dist\BrewFlasher-1.3 x64.exe" REM Next, we'll create the 32 bit version. diff --git a/update_pyinstaller.sh b/update_pyinstaller.sh index 8747971..006ba10 100755 --- a/update_pyinstaller.sh +++ b/update_pyinstaller.sh @@ -6,7 +6,7 @@ # Note - this command (at least the "pip install" bit) needs to be done from within the virtualenv git clone https://github.com/pyinstaller/pyinstaller.git cd pyinstaller -git checkout v4.7 +git checkout v5.4 cd bootloader python ./waf all pip install ..